[nautilus-actions] Build a hierarchical menu for Nautilus plugin
- From: Pierre Wieser <pwieser src gnome org>
- To: svn-commits-list gnome org
- Cc:
- Subject: [nautilus-actions] Build a hierarchical menu for Nautilus plugin
- Date: Fri, 2 Oct 2009 22:42:09 +0000 (UTC)
commit 89a7f09b5532c742805c8f0c207b2ae48890814c
Author: Pierre Wieser <pwieser trychlos org>
Date: Wed Sep 30 20:10:45 2009 +0200
Build a hierarchical menu for Nautilus plugin
Also defines the NAIAbout interface to be able to provide the actual application name at runtime.
ChangeLog | 15 ++
src/common/Makefile.am | 4 +-
src/common/na-about.c | 127 --------------
src/common/na-about.h | 50 ------
src/common/na-iabout.c | 234 ++++++++++++++++++++++++++
src/common/na-iabout.h | 88 ++++++++++
src/nact/nact-application.c | 4 +-
src/nact/nact-main-menubar.c | 8 +-
src/nact/nact-main-window.c | 34 ++++
src/plugin/nautilus-actions.c | 368 +++++++++++++++++++++++++++++------------
10 files changed, 636 insertions(+), 296 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index 74e5056..e22b55a 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,18 @@
+2009-09-30 Pierre Wieser <pwieser trychlos org>
+
+ * src/common/na-about.c: Renamed as na-iabout.c.
+ * src/common/na-about.h: Renamed as na-iabout.h.
+ Defines the NAIAbout interface to let the implementor provides
+ the actual application name.
+
+ * src/common/Makefile.am:
+ * src/nact/nact-application.c:
+ * src/nact/nact-main-menubar.c:
+ * src/nact/nact-main-window.c: Updated accordingly.
+
+ * src/plugin/nautilus-actions.c:
+ Builds a hierachical menu for Nautilus context menu.
+
2009-09-28 Pierre Wieser <pwieser trychlos org>
* data/nautilus-actions.schemas.in:
diff --git a/src/common/Makefile.am b/src/common/Makefile.am
index abf6560..382a81a 100644
--- a/src/common/Makefile.am
+++ b/src/common/Makefile.am
@@ -35,8 +35,6 @@ AM_CPPFLAGS += \
$(NULL)
libnact_la_SOURCES = \
- na-about.c \
- na-about.h \
na-gconf-keys-base.h \
na-gconf-keys-schemas.h \
na-gconf-monitor.c \
@@ -48,6 +46,8 @@ libnact_la_SOURCES = \
na-gconf-utils.h \
na-gnome-vfs-uri.c \
na-gnome-vfs-uri.h \
+ na-iabout.c \
+ na-iabout.h \
na-iduplicable.c \
na-iduplicable.h \
na-iio-provider.c \
diff --git a/src/common/na-iabout.c b/src/common/na-iabout.c
new file mode 100644
index 0000000..8427bfb
--- /dev/null
+++ b/src/common/na-iabout.c
@@ -0,0 +1,234 @@
+/*
+ * Nautilus Actions
+ * A Nautilus extension which offers configurable context menu actions.
+ *
+ * Copyright (C) 2005 The GNOME Foundation
+ * Copyright (C) 2006, 2007, 2008 Frederic Ruaudel and others (see AUTHORS)
+ * Copyright (C) 2009 Pierre Wieser and others (see AUTHORS)
+ *
+ * This Program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This Program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this Library; see the file COPYING. If not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Authors:
+ * Frederic Ruaudel <grumz grumz net>
+ * Rodrigo Moya <rodrigo gnome-db org>
+ * Pierre Wieser <pwieser trychlos org>
+ * ... and many others (see AUTHORS)
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <glib/gi18n.h>
+
+#include "na-iabout.h"
+
+/* private interface data
+ */
+struct NAIAboutInterfacePrivate {
+ void *empty; /* so that gcc -pedantic is happy */
+};
+
+static gboolean st_initialized = FALSE;
+static gboolean st_finalized = FALSE;
+
+static GType register_type( void );
+static void interface_base_init( NAIAboutInterface *klass );
+static void interface_base_finalize( NAIAboutInterface *klass );
+
+static gchar *v_get_application_name( NAIAbout *instance );
+static GtkWindow *v_get_toplevel( NAIAbout *instance );
+
+GType
+na_iabout_get_type( void )
+{
+ static GType iface_type = 0;
+
+ if( !iface_type ){
+ iface_type = register_type();
+ }
+
+ return( iface_type );
+}
+
+static GType
+register_type( void )
+{
+ static const gchar *thisfn = "na_iabout_register_type";
+ GType type;
+
+ static const GTypeInfo info = {
+ sizeof( NAIAboutInterface ),
+ ( GBaseInitFunc ) interface_base_init,
+ ( GBaseFinalizeFunc ) interface_base_finalize,
+ NULL,
+ NULL,
+ NULL,
+ 0,
+ 0,
+ NULL
+ };
+
+ g_debug( "%s", thisfn );
+
+ type = g_type_register_static( G_TYPE_INTERFACE, "NAIAbout", &info, 0 );
+
+ g_type_interface_add_prerequisite( type, G_TYPE_OBJECT );
+
+ return( type );
+}
+
+static void
+interface_base_init( NAIAboutInterface *klass )
+{
+ static const gchar *thisfn = "na_iabout_interface_base_init";
+
+ if( !st_initialized ){
+
+ g_debug( "%s: klass=%p", thisfn, ( void * ) klass );
+
+ klass->private = g_new0( NAIAboutInterfacePrivate, 1 );
+
+ st_initialized = TRUE;
+ }
+}
+
+static void
+interface_base_finalize( NAIAboutInterface *klass )
+{
+ static const gchar *thisfn = "na_iabout_interface_base_finalize";
+
+ if( !st_finalized ){
+
+ st_finalized = TRUE;
+
+ g_debug( "%s: klass=%p", thisfn, ( void * ) klass );
+
+ g_free( klass->private );
+ }
+}
+
+static gchar *
+v_get_application_name( NAIAbout *instance )
+{
+ if( NA_IABOUT_GET_INTERFACE( instance )->get_application_name ){
+ return( NA_IABOUT_GET_INTERFACE( instance )->get_application_name( instance ));
+ }
+
+ return( NULL );
+}
+
+static GtkWindow *
+v_get_toplevel( NAIAbout *instance )
+{
+ if( NA_IABOUT_GET_INTERFACE( instance )->get_toplevel ){
+ return( NA_IABOUT_GET_INTERFACE( instance )->get_toplevel( instance ));
+ }
+
+ return( NULL );
+}
+
+/* TODO: make the website url and the mail addresses clickables
+ */
+/**
+ * na_iabout_display:
+ * @instance: the #NAIAbout implementor.
+ *
+ * Displays the About dialog.
+ */
+void
+na_iabout_display( NAIAbout *instance )
+{
+ static const gchar *thisfn = "na_iabout_display";
+ gchar *application_name;
+ gchar *icon_name, *license_i18n;
+ GtkWindow *toplevel;
+
+ static const gchar *artists[] = {
+ N_( "Ulisse Perusin <uli peru gmail com>" ),
+ NULL
+ };
+
+ static const gchar *authors[] = {
+ N_( "Frederic Ruaudel <grumz grumz net>" ),
+ N_( "Rodrigo Moya <rodrigo gnome-db org>" ),
+ N_( "Pierre Wieser <pwieser trychlos org>" ),
+ NULL
+ };
+
+ static const gchar *documenters[] = {
+ NULL
+ };
+
+ static gchar *license[] = {
+ N_( "Nautilus Actions Configuration Tool is free software; you can "
+ "redistribute it and/or modify it under the terms of the GNU General "
+ "Public License as published by the Free Software Foundation; either "
+ "version 2 of the License, or (at your option) any later version." ),
+ N_( "Nautilus Actions Configuration Tool is distributed in the hope that it "
+ "will be useful, but WITHOUT ANY WARRANTY; without even the implied "
+ "warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See "
+ "the GNU General Public License for more details." ),
+ N_( "You should have received a copy of the GNU General Public License along "
+ "with Nautilus Actions Configuration Tool ; if not, write to the Free "
+ "Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, "
+ "MA 02110-1301, USA." ),
+ NULL
+ };
+
+ g_debug( "%s: instance=%p (%s)", thisfn, ( void * ) instance, G_OBJECT_TYPE_NAME( instance ));
+ g_return_if_fail( NA_IS_IABOUT( instance ));
+
+ if( st_initialized && !st_finalized ){
+
+ application_name = v_get_application_name( instance );
+ toplevel = v_get_toplevel( instance );
+
+ icon_name = na_iabout_get_icon_name();
+
+ license_i18n = g_strjoinv( "\n\n", license );
+
+ gtk_show_about_dialog( toplevel,
+ "artists", artists,
+ "authors", authors,
+ "comments", _( "A graphical interface to create and edit your Nautilus actions." ),
+ "copyright", _( "Copyright \xc2\xa9 2005-2007 Frederic Ruaudel <grumz grumz net>\nCopyright \xc2\xa9 2009 Pierre Wieser <pwieser trychlos org>" ),
+ "documenters", documenters,
+ "license", license_i18n,
+ "logo-icon-name", icon_name,
+ "program-name", application_name,
+ "translator-credits", _( "The GNOME Translation Project <gnome-i18n gnome org>" ),
+ "version", PACKAGE_VERSION,
+ "website", "http://www.nautilus-actions.org",
+ "wrap-license", TRUE,
+ NULL );
+
+ g_free( application_name );
+ g_free( license_i18n );
+ g_free( icon_name );
+ }
+}
+
+/**
+ * na_iabout_get_icon_name:
+ *
+ * Returns the name of the default icon for the application.
+ */
+gchar *
+na_iabout_get_icon_name( void )
+{
+ return( g_strdup( PACKAGE ));
+}
diff --git a/src/common/na-iabout.h b/src/common/na-iabout.h
new file mode 100644
index 0000000..0dda955
--- /dev/null
+++ b/src/common/na-iabout.h
@@ -0,0 +1,88 @@
+/*
+ * Nautilus Actions
+ * A Nautilus extension which offers configurable context menu actions.
+ *
+ * Copyright (C) 2005 The GNOME Foundation
+ * Copyright (C) 2006, 2007, 2008 Frederic Ruaudel and others (see AUTHORS)
+ * Copyright (C) 2009 Pierre Wieser and others (see AUTHORS)
+ *
+ * This Program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This Program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this Library; see the file COPYING. If not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Authors:
+ * Frederic Ruaudel <grumz grumz net>
+ * Rodrigo Moya <rodrigo gnome-db org>
+ * Pierre Wieser <pwieser trychlos org>
+ * ... and many others (see AUTHORS)
+ */
+
+#ifndef __NA_IABOUT_H__
+#define __NA_IABOUT_H__
+
+/**
+ * SECTION: na_iabout
+ * @short_description: NAIAbout interface definition.
+ * @include: common/na-iabout.h
+ *
+ * This interface displays the 'About Nautilus Actions' dialog box.
+ * The application name may be provided by the implementor.
+ */
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define NA_IABOUT_TYPE ( na_iabout_get_type())
+#define NA_IABOUT( object ) ( G_TYPE_CHECK_INSTANCE_CAST( object, NA_IABOUT_TYPE, NAIAbout ))
+#define NA_IS_IABOUT( object ) ( G_TYPE_CHECK_INSTANCE_TYPE( object, NA_IABOUT_TYPE ))
+#define NA_IABOUT_GET_INTERFACE( instance ) ( G_TYPE_INSTANCE_GET_INTERFACE(( instance ), NA_IABOUT_TYPE, NAIAboutInterface ))
+
+typedef struct NAIAbout NAIAbout;
+
+typedef struct NAIAboutInterfacePrivate NAIAboutInterfacePrivate;
+
+typedef struct {
+ GTypeInterface parent;
+ NAIAboutInterfacePrivate *private;
+
+ /**
+ * get_application_name:
+ * @iabout: this #NAIAbout implementor.
+ *
+ * Returns the application name as a newly allocated string.
+ *
+ * The application name will be g_free() by the interface.
+ */
+ gchar * ( *get_application_name )( NAIAbout *instance );
+
+ /**
+ * get_toplevel:
+ * @iabout: this #NAIAbout implementor.
+ *
+ * Returns the toplevel parent of the displayed dialog box.
+ */
+ GtkWindow * ( *get_toplevel ) ( NAIAbout *instance );
+}
+ NAIAboutInterface;
+
+GType na_iabout_get_type( void );
+
+void na_iabout_display( NAIAbout *instance );
+
+gchar *na_iabout_get_icon_name( void );
+
+G_END_DECLS
+
+#endif /* __NA_IABOUT_H__ */
diff --git a/src/nact/nact-application.c b/src/nact/nact-application.c
index ee36a5e..1c1859f 100644
--- a/src/nact/nact-application.c
+++ b/src/nact/nact-application.c
@@ -35,7 +35,7 @@
#include <glib/gi18n.h>
#include <gtk/gtk.h>
-#include <common/na-about.h>
+#include <common/na-iabout.h>
#include <common/na-iduplicable.h>
#include <common/na-ipivot-consumer.h>
@@ -383,7 +383,7 @@ appli_get_icon_name( BaseApplication *application )
g_debug( "%s: application=%p", thisfn, ( void * ) application );
- return( na_about_get_icon_name());
+ return( na_iabout_get_icon_name());
}
static gchar *
diff --git a/src/nact/nact-main-menubar.c b/src/nact/nact-main-menubar.c
index c55a33d..c715ef9 100644
--- a/src/nact/nact-main-menubar.c
+++ b/src/nact/nact-main-menubar.c
@@ -34,10 +34,10 @@
#include <glib/gi18n.h>
-#include <common/na-about.h>
#include <common/na-object-api.h>
#include <common/na-object-action.h>
#include <common/na-object-menu.h>
+#include <common/na-iabout.h>
#include <common/na-ipivot-consumer.h>
#include "base-iprefs.h"
@@ -693,11 +693,7 @@ on_help_activated( GtkAction *gtk_action, NactMainWindow *window )
static void
on_about_activated( GtkAction *gtk_action, NactMainWindow *window )
{
- GtkWindow *toplevel;
-
- toplevel = base_window_get_toplevel( BASE_WINDOW( window ));
-
- na_about_display( G_OBJECT( toplevel ));
+ na_iabout_display( NA_IABOUT( window ));
}
static void
diff --git a/src/nact/nact-main-window.c b/src/nact/nact-main-window.c
index 282f496..624e24c 100644
--- a/src/nact/nact-main-window.c
+++ b/src/nact/nact-main-window.c
@@ -39,6 +39,7 @@
#include <common/na-object-api.h>
#include <common/na-pivot.h>
+#include <common/na-iabout.h>
#include <common/na-iio-provider.h>
#include <common/na-ipivot-consumer.h>
#include <common/na-iprefs.h>
@@ -122,6 +123,7 @@ static void iaction_tab_iface_init( NactIActionTabInterface *iface );
static void icommand_tab_iface_init( NactICommandTabInterface *iface );
static void iconditions_tab_iface_init( NactIConditionsTabInterface *iface );
static void iadvanced_tab_iface_init( NactIAdvancedTabInterface *iface );
+static void iabout_iface_init( NAIAboutInterface *iface );
static void ipivot_consumer_iface_init( NAIPivotConsumerInterface *iface );
static void iprefs_base_iface_init( BaseIPrefsInterface *iface );
static void instance_init( GTypeInstance *instance, gpointer klass );
@@ -152,6 +154,8 @@ static void ipivot_consumer_on_display_about_changed( NAIPivotConsumer *inst
static void ipivot_consumer_on_display_order_changed( NAIPivotConsumer *instance, gint order_mode );
static void reload( NactMainWindow *window );
+static gchar *iabout_get_application_name( NAIAbout *instance );
+
GType
nact_main_window_get_type( void )
{
@@ -212,6 +216,12 @@ register_type( void )
NULL
};
+ static const GInterfaceInfo iabout_iface_info = {
+ ( GInterfaceInitFunc ) iabout_iface_init,
+ NULL,
+ NULL
+ };
+
static const GInterfaceInfo ipivot_consumer_iface_info = {
( GInterfaceInitFunc ) ipivot_consumer_iface_init,
NULL,
@@ -238,6 +248,8 @@ register_type( void )
g_type_add_interface_static( type, NACT_IADVANCED_TAB_TYPE, &iadvanced_tab_iface_info );
+ g_type_add_interface_static( type, NA_IABOUT_TYPE, &iabout_iface_info );
+
g_type_add_interface_static( type, NA_IPIVOT_CONSUMER_TYPE, &ipivot_consumer_iface_info );
g_type_add_interface_static( type, BASE_IPREFS_TYPE, &iprefs_base_iface_info );
@@ -376,6 +388,16 @@ iadvanced_tab_iface_init( NactIAdvancedTabInterface *iface )
}
static void
+iabout_iface_init( NAIAboutInterface *iface )
+{
+ static const gchar *thisfn = "nact_main_window_iabout_iface_init";
+
+ g_debug( "%s: iface=%p", thisfn, ( void * ) iface );
+
+ iface->get_application_name = iabout_get_application_name;
+}
+
+static void
ipivot_consumer_iface_init( NAIPivotConsumerInterface *iface )
{
static const gchar *thisfn = "nact_main_window_ipivot_consumer_iface_init";
@@ -1178,3 +1200,15 @@ ipivot_consumer_on_display_order_changed( NAIPivotConsumer *instance, gint order
nact_iactions_list_display_order_change( NACT_IACTIONS_LIST( instance ), order_mode );
}
+
+static gchar *
+iabout_get_application_name( NAIAbout *instance )
+{
+ BaseApplication *application;
+
+ g_return_val_if_fail( NA_IS_IABOUT( instance ), NULL );
+ g_return_val_if_fail( BASE_IS_WINDOW( instance ), NULL );
+
+ application = base_window_get_application( BASE_WINDOW( instance ));
+ return( base_application_get_application_name( application ));
+}
diff --git a/src/plugin/nautilus-actions.c b/src/plugin/nautilus-actions.c
index 766798f..83f5253 100644
--- a/src/plugin/nautilus-actions.c
+++ b/src/plugin/nautilus-actions.c
@@ -38,11 +38,12 @@
#include <libnautilus-extension/nautilus-file-info.h>
#include <libnautilus-extension/nautilus-menu-provider.h>
-#include <common/na-about.h>
#include <common/na-object-api.h>
+#include <common/na-object-menu.h>
#include <common/na-object-action.h>
#include <common/na-object-profile.h>
#include <common/na-pivot.h>
+#include <common/na-iabout.h>
#include <common/na-iprefs.h>
#include <common/na-ipivot-consumer.h>
@@ -66,6 +67,7 @@ static GType st_actions_type = 0;
static void class_init( NautilusActionsClass *klass );
static void menu_provider_iface_init( NautilusMenuProviderIface *iface );
+static void iabout_iface_init( NAIAboutInterface *iface );
static void ipivot_consumer_iface_init( NAIPivotConsumerInterface *iface );
static void instance_init( GTypeInstance *instance, gpointer klass );
static void instance_dispose( GObject *object );
@@ -73,11 +75,19 @@ static void instance_finalize( GObject *object );
static GList *get_background_items( NautilusMenuProvider *provider, GtkWidget *window, NautilusFileInfo *current_folder );
static GList *get_file_items( NautilusMenuProvider *provider, GtkWidget *window, GList *files );
-static NautilusMenuItem *create_menu_item( NAObjectAction *action, NAObjectProfile *profile, GList *files );
-/*static NautilusMenuItem *create_sub_menu( NautilusMenu **menu );*/
-static void add_about_item( NautilusMenu *menu );
+static GList *build_nautilus_menus( NautilusActions *plugin, GList *tree, GList *files );
+static NAObjectProfile *is_action_candidate( NautilusActions *plugin, NAObjectAction *action, GList *files );
+static NautilusMenuItem *create_item_from_profile( NAObjectProfile *profile, GList *files );
+static NautilusMenuItem *create_item_from_menu( NAObjectMenu *menu, GList *subitems );
+static NautilusMenuItem *create_menu_item( NAObjectItem *item );
+static void attach_submenu_to_item( NautilusMenuItem *item, GList *subitems );
+
static void execute_action( NautilusMenuItem *item, NAObjectProfile *profile );
+static GList *add_about_item( NautilusActions *plugin, GList *nautilus_menu );
+static gchar *iabout_get_application_name( NAIAbout *instance );
+static void execute_about( NautilusMenuItem *item, NautilusActions *plugin );
+
static void actions_changed_handler( NAIPivotConsumer *instance, gpointer user_data );
static void display_about_changed_handler( NAIPivotConsumer *instance, gboolean enabled );
static void display_order_changed_handler( NAIPivotConsumer *instance, gint order_mode );
@@ -112,6 +122,12 @@ nautilus_actions_register_type( GTypeModule *module )
NULL
};
+ static const GInterfaceInfo iabout_iface_info = {
+ ( GInterfaceInitFunc ) iabout_iface_init,
+ NULL,
+ NULL
+ };
+
static const GInterfaceInfo ipivot_consumer_iface_info = {
( GInterfaceInitFunc ) ipivot_consumer_iface_init,
NULL,
@@ -125,6 +141,8 @@ nautilus_actions_register_type( GTypeModule *module )
g_type_module_add_interface( module, st_actions_type, NAUTILUS_TYPE_MENU_PROVIDER, &menu_provider_iface_info );
+ g_type_module_add_interface( module, st_actions_type, NA_IABOUT_TYPE, &iabout_iface_info );
+
g_type_module_add_interface( module, st_actions_type, NA_IPIVOT_CONSUMER_TYPE, &ipivot_consumer_iface_info );
}
@@ -157,6 +175,16 @@ menu_provider_iface_init( NautilusMenuProviderIface *iface )
}
static void
+iabout_iface_init( NAIAboutInterface *iface )
+{
+ static const gchar *thisfn = "nautilus_actions_iabout_iface_init";
+
+ g_debug( "%s: iface=%p", thisfn, ( void * ) iface );
+
+ iface->get_application_name = iabout_get_application_name;
+}
+
+static void
ipivot_consumer_iface_init( NAIPivotConsumerInterface *iface )
{
static const gchar *thisfn = "nautilus_actions_ipivot_consumer_iface_init";
@@ -271,15 +299,10 @@ static GList *
get_file_items( NautilusMenuProvider *provider, GtkWidget *window, GList *files )
{
static const gchar *thisfn = "nautilus_actions_get_file_items";
+ GList *nautilus_menus_list = NULL;
NautilusActions *self;
- GList *items = NULL;
- GList *profiles, *ia, *ip;
- NautilusMenu *menu = NULL;
- NautilusMenuItem *item;
- GList *tree = NULL;
- gchar *label, *uuid;
- gint submenus = 0;
- gboolean add_about;
+ GList *pivot_tree;
+ gboolean add_about;
g_debug( "%s: provider=%p, window=%p, files=%p, count=%d",
thisfn, ( void * ) provider, ( void * ) window, ( void * ) files, g_list_length( files ));
@@ -287,97 +310,131 @@ get_file_items( NautilusMenuProvider *provider, GtkWidget *window, GList *files
g_return_val_if_fail( NAUTILUS_IS_ACTIONS( provider ), NULL );
self = NAUTILUS_ACTIONS( provider );
+ /* no need to go further if there is no files in the list */
+ if( !g_list_length( files )){
+ return(( GList * ) NULL );
+ }
+
if( !self->private->dispose_has_run ){
- /* no need to go further if there is no files in the list */
- if( !g_list_length( files )){
- return(( GList * ) NULL );
+ pivot_tree = na_pivot_get_items( self->private->pivot );
+
+ nautilus_menus_list = build_nautilus_menus( self, pivot_tree, files );
+ g_debug( "%s: menus has %d level zero items", thisfn, g_list_length( nautilus_menus_list ));
+
+ add_about = na_iprefs_should_add_about_item( NA_IPREFS( self->private->pivot ));
+ g_debug( "%s: add_about=%s", thisfn, add_about ? "True":"False" );
+ if( add_about ){
+ nautilus_menus_list = add_about_item( self, nautilus_menus_list );
}
+ }
- if( !self->private->dispose_has_run ){
- tree = na_pivot_get_items( self->private->pivot );
+ return( nautilus_menus_list );
+}
- for( ia = tree ; ia ; ia = ia->next ){
+static GList *
+build_nautilus_menus( NautilusActions *plugin, GList *tree, GList *files )
+{
+ static const gchar *thisfn = "nautilus_actions_build_nautilus_menus";
+ GList *menus_list = NULL;
+ GList *subitems, *submenu;
+ GList *it;
+ NAObjectProfile *profile;
+ NautilusMenuItem *item;
+ gchar *label;
- NAObjectAction *action = NA_OBJECT_ACTION( ia->data );
+ g_debug( "%s: plugin=%p, tree=%p, files=%p",
+ thisfn, ( void * ) plugin, ( void * ) tree, ( void * ) files );
- if( !na_object_is_enabled( action )){
- continue;
- }
+ for( it = tree ; it ; it = it->next ){
- label = na_object_get_label( action );
+ g_return_val_if_fail( NA_IS_OBJECT_ITEM( it->data ), NULL );
- if( !label || !g_utf8_strlen( label, -1 )){
- uuid = na_object_get_id( action );
- g_warning( "%s: label null or empty for uuid=%s", thisfn, uuid );
- g_free( uuid );
- continue;
- }
+ if( !na_object_is_enabled( it->data )){
+ continue;
+ }
- g_debug( "%s: examining '%s' action", thisfn, label );
- g_free( label );
+ label = na_object_get_label( it->data );
+ g_debug( "%s: %s - %s", thisfn, G_OBJECT_TYPE_NAME( it->data ), label );
+ g_free( label );
+
+ if( NA_IS_OBJECT_MENU( it->data )){
+ subitems = na_object_get_items( it->data );
+ submenu = build_nautilus_menus( plugin, subitems, files );
+ /*g_debug( "%s: submenu has %d items", thisfn, g_list_length( submenu ));*/
+ na_object_free_items( subitems );
+ if( submenu ){
+ item = create_item_from_menu( NA_OBJECT_MENU( it->data ), submenu );
+ menus_list = g_list_append( menus_list, item );
+ }
+ continue;
+ }
- profiles = na_object_get_items( action );
+ g_return_val_if_fail( NA_IS_OBJECT_ACTION( it->data ), NULL );
- for( ip = profiles ; ip ; ip = ip->next ){
+ profile = is_action_candidate( plugin, NA_OBJECT_ACTION( it->data ), files );
+ if( profile ){
+ item = create_item_from_profile( profile, files );
+ menus_list = g_list_append( menus_list, item );
+ }
+ }
- NAObjectProfile *profile = NA_OBJECT_PROFILE( ip->data );
+ return( menus_list );
+}
-#ifdef NA_MAINTAINER_MODE
- label = na_object_get_label( profile );
- g_debug( "%s: examining '%s' profile", thisfn, label );
- g_free( label );
-#endif
+/*
+ * could also be a NAObjectAction method - but this is not used elsewhere
+ */
+static NAObjectProfile *
+is_action_candidate( NautilusActions *plugin, NAObjectAction *action, GList *files )
+{
+ static const gchar *thisfn = "nautilus_actions_is_action_candidate";
+ NAObjectProfile *candidate = NULL;
+ gchar *action_label, *uuid;
+ gchar *profile_label;
+ GList *profiles, *ip;
+
+ action_label = na_object_get_label( action );
+
+ if( !action_label || !g_utf8_strlen( action_label, -1 )){
+ uuid = na_object_get_id( action );
+ g_warning( "%s: label null or empty for uuid=%s", thisfn, uuid );
+ g_free( uuid );
+ return( NULL );
+ }
- if( na_object_profile_is_candidate( profile, files )){
- item = create_menu_item( action, profile, files );
- items = g_list_append( items, item );
+ profiles = na_object_get_items( action );
+ for( ip = profiles ; ip && !candidate ; ip = ip->next ){
- /*if( have_submenu ){
- if( !menu ){
- items = g_list_append( items, create_sub_menu( &menu ));
- }
- nautilus_menu_append_item( menu, item );
+ NAObjectProfile *profile = NA_OBJECT_PROFILE( ip->data );
+ if( na_object_profile_is_candidate( profile, files )){
- } else {
- }*/
- break;
- }
- }
+ profile_label = na_object_get_label( profile );
+ g_debug( "%s: selecting %s - %s", thisfn, action_label, profile_label );
+ g_free( profile_label );
- na_object_free_items( profiles );
- }
+ candidate = profile;
+ }
+ }
- add_about = FALSE; /*na_iprefs_get_add_about_item( NA_IPREFS( self ));*/
- if( submenus == 1 && add_about ){
- add_about_item( menu );
- }
- }
- }
+ g_free( action_label );
- return( items );
+ return( candidate );
}
static NautilusMenuItem *
-create_menu_item( NAObjectAction *action, NAObjectProfile *profile, GList *files )
+create_item_from_profile( NAObjectProfile *profile, GList *files )
{
- static const gchar *thisfn = "nautilus_actions_create_menu_item";
NautilusMenuItem *item;
- gchar *uuid, *name, *label, *tooltip, *icon_name;
+ NAObjectAction *action;
NAObjectProfile *dup4menu;
- g_debug( "%s", thisfn );
+ action = na_object_profile_get_action( profile );
- uuid = na_object_get_id( action );
- name = g_strdup_printf( "NautilusActions::%s", uuid );
- label = na_object_get_label( action );
- tooltip = na_object_get_tooltip( action );
- icon_name = na_object_item_get_verified_icon_name( NA_OBJECT_ITEM( action ));
+ item = create_menu_item( NA_OBJECT_ITEM( action ));
dup4menu = NA_OBJECT_PROFILE( na_object_duplicate( profile ));
- item = nautilus_menu_item_new( name, label, tooltip, icon_name );
-
g_signal_connect_data( item,
"activate",
G_CALLBACK( execute_action ),
@@ -390,58 +447,63 @@ create_menu_item( NAObjectAction *action, NAObjectProfile *profile, GList *files
nautilus_file_info_list_copy( files ),
( GDestroyNotify ) nautilus_file_info_list_free );
- g_free( icon_name );
- g_free( tooltip );
- g_free( label );
- g_free( name );
- g_free( uuid );
-
return( item );
}
-/*static NautilusMenuItem *
-create_sub_menu( NautilusMenu **menu )
+/*
+ * note that each appended NautilusMenuItem is ref-ed by the NautilusMenu
+ * we can so safely release our own ref on subitems after this function
+ */
+static NautilusMenuItem *
+create_item_from_menu( NAObjectMenu *menu, GList *subitems )
{
+ /*static const gchar *thisfn = "nautilus_actions_create_item_from_menu";*/
NautilusMenuItem *item;
- gchar *icon_name = na_about_get_icon_name();
+ item = create_menu_item( NA_OBJECT_ITEM( menu ));
+ attach_submenu_to_item( item, subitems );
+ nautilus_menu_item_list_free( subitems );
+
+ /*g_debug( "%s: returning item=%p", thisfn, ( void * ) item );*/
+ return( item );
+}
- item = nautilus_menu_item_new( "NautilusActionsExtensions",
- _( "Nautilus-Actions extensions" ),
- _( "A submenu which embeds the currently available Nautilus-Actions extensions" ),
- icon_name );
+static NautilusMenuItem *
+create_menu_item( NAObjectItem *item )
+{
+ NautilusMenuItem *menu_item;
+ gchar *uuid, *name, *label, *tooltip, *icon;
- if( menu ){
- *menu = nautilus_menu_new();
- nautilus_menu_item_set_submenu( item, *menu );
- }
+ uuid = na_object_get_id( item );
+ name = g_strdup_printf( "%s-%s-%s", PACKAGE, G_OBJECT_TYPE_NAME( item ), uuid );
+ label = na_object_get_label( item );
+ /*g_debug( "nautilus_actions_create_menu_item: %s - %s", name, label );*/
+ tooltip = na_object_get_tooltip( item );
+ icon = na_object_get_icon( item );
- g_free( icon_name );
+ menu_item = nautilus_menu_item_new( name, label, tooltip, icon );
- return( item );
-}*/
+ g_free( icon );
+ g_free( tooltip );
+ g_free( label );
+ g_free( name );
+ g_free( uuid );
+
+ return( menu_item );
+}
static void
-add_about_item( NautilusMenu *menu )
+attach_submenu_to_item( NautilusMenuItem *item, GList *subitems )
{
- gchar *icon_name = na_about_get_icon_name();
+ NautilusMenu *submenu;
+ GList *it;
- NautilusMenuItem *item = nautilus_menu_item_new(
- "AboutNautilusActions",
- _( "About Nautilus Actions" ),
- _( "Display information about Nautilus Actions" ),
- icon_name );
+ submenu = nautilus_menu_new();
+ nautilus_menu_item_set_submenu( item, submenu );
- g_signal_connect_data( item,
- "activate",
- G_CALLBACK( na_about_display ),
- NULL,
- NULL,
- 0 );
-
- nautilus_menu_append_item( menu, item );
-
- g_free( icon_name );
+ for( it = subitems ; it ; it = it->next ){
+ nautilus_menu_append_item( submenu, NAUTILUS_MENU_ITEM( it->data ));
+ }
}
static void
@@ -474,6 +536,94 @@ execute_action( NautilusMenuItem *item, NAObjectProfile *profile )
}
+/*
+ * if there is a root submenu,
+ * then add the about item to the end of the first level of this menu
+ * else create a root submenu
+ */
+static GList *
+add_about_item( NautilusActions *plugin, GList *menu )
+{
+ static const gchar *thisfn = "nautilus_actions_add_about_item";
+ GList *nautilus_menu;
+ gboolean have_root_menu;
+ NautilusMenuItem *root_item;
+ NautilusMenuItem *about_item;
+ NautilusMenu *first;
+ gchar *icon;
+
+ g_debug( "%s: plugin=%p, menu=%p (%d items)",
+ thisfn, ( void * ) plugin, ( void * ) menu, g_list_length( menu ));
+
+ if( !menu || !g_list_length( menu )){
+ return( NULL );
+ }
+
+ icon = na_iabout_get_icon_name();
+ have_root_menu = FALSE;
+
+ if( g_list_length( menu ) == 1 ){
+ root_item = NAUTILUS_MENU_ITEM( menu->data );
+ g_object_get( G_OBJECT( root_item ), "menu", &first, NULL );
+ if( first ){
+ g_return_val_if_fail( NAUTILUS_IS_MENU( first ), NULL );
+ have_root_menu = TRUE;
+ }
+ }
+
+ if( have_root_menu ){
+ nautilus_menu = menu;
+
+ } else {
+ root_item = nautilus_menu_item_new( "NautilusActionsExtensions",
+ /* i18n: label of an automagic root submenu */
+ _( "Nautilus Actions" ),
+ /* i18n: tooltip of an automagic root submenu */
+ _( "A submenu which embeds the currently available Nautilus-Actions extensions" ),
+ icon );
+ attach_submenu_to_item( root_item, menu );
+ nautilus_menu = g_list_append( NULL, root_item );
+ g_object_get( G_OBJECT( root_item ), "menu", &first, NULL );
+ }
+
+ g_return_val_if_fail( g_list_length( nautilus_menu ) == 1, NULL );
+ g_return_val_if_fail( NAUTILUS_IS_MENU( first ), NULL );
+
+ about_item = nautilus_menu_item_new( "AboutNautilusActions",
+ _( "About Nautilus Actions" ),
+ _( "Display information about Nautilus Actions" ),
+ icon );
+
+ g_signal_connect_data( about_item,
+ "activate",
+ G_CALLBACK( execute_about ),
+ plugin,
+ NULL,
+ 0 );
+
+ nautilus_menu_append_item( first, about_item );
+
+ g_free( icon );
+
+ return( nautilus_menu );
+}
+
+static gchar *
+iabout_get_application_name( NAIAbout *instance )
+{
+ /* i18n: title of the About dialog box, when seen from Nautilus file manager */
+ return( g_strdup( _( "Nautilus Actions" )));
+}
+
+static void
+execute_about( NautilusMenuItem *item, NautilusActions *plugin )
+{
+ g_return_if_fail( NAUTILUS_IS_ACTIONS( plugin ));
+ g_return_if_fail( NA_IS_IABOUT( plugin ));
+
+ na_iabout_display( NA_IABOUT( plugin ));
+}
+
static void
actions_changed_handler( NAIPivotConsumer *instance, gpointer user_data )
{
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]