Commit fe10a641 authored by Pierre Wieser's avatar Pierre Wieser

The plugin now uses the new object hierarchy to handle menu items

parent d47f9e67
2009-06-09 Pierre Wieser <pwieser@trychlos.org>
* src/common/nact-action-profile.c:
* src/common/nact-action-profile.h:
* src/common/nact-action.c:
* src/common/nact-action.h:
* src/common/nact-gconf.c:
* src/common/nact-object.c:
* src/common/nact-object.h:
* src/common/nact-pivot.c:
* src/common/nact-pivot.h:
* src/plugin/nautilus-actions.c:
The plugin now uses the new object hierarchy to handle menu items.
Fix #580378 (context menu doesn't update) reported by James Campos.
2009-06-08 Pierre Wieser <pwieser@trychlos.org>
* src/common/nact-action-profile.c:
......
......@@ -34,6 +34,8 @@
#include <string.h>
#include <libgnomevfs/gnome-vfs.h>
#include <libnautilus-extension/nautilus-file-info.h>
#include "nact-action.h"
......@@ -103,17 +105,19 @@ enum {
static NactObjectClass *st_parent_class = NULL;
static GType register_type( void );
static void class_init( NactActionProfileClass *klass );
static void instance_init( GTypeInstance *instance, gpointer klass );
static void instance_dispose( GObject *object );
static void instance_get_property( GObject *object, guint property_id, GValue *value, GParamSpec *spec );
static void instance_set_property( GObject *object, guint property_id, const GValue *value, GParamSpec *spec );
static void instance_finalize( GObject *object );
static GType register_type( void );
static void class_init( NactActionProfileClass *klass );
static void instance_init( GTypeInstance *instance, gpointer klass );
static void instance_dispose( GObject *object );
static void instance_get_property( GObject *object, guint property_id, GValue *value, GParamSpec *spec );
static void instance_set_property( GObject *object, guint property_id, const GValue *value, GParamSpec *spec );
static void instance_finalize( GObject *object );
static void do_dump( const NactObject *profile );
static void do_dump_list( const gchar *thisfn, const gchar *label, GSList *list );
static int validate_schemes( GSList* schemes2test, NautilusFileInfo* file );
static void do_dump( const NactObject *profile );
static void do_dump_list( const gchar *thisfn, const gchar *label, GSList *list );
static gchar *do_get_id( const NactObject *object );
static gchar *do_get_label( const NactObject *object );
static int validate_schemes( GSList* schemes2test, NautilusFileInfo* file );
NactActionProfile *
nact_action_profile_new( const NactObject *action, const gchar *name )
......@@ -129,6 +133,44 @@ nact_action_profile_new( const NactObject *action, const gchar *name )
return( profile );
}
NactActionProfile *
nact_action_profile_copy( const NactActionProfile *profile )
{
g_assert( NACT_IS_ACTION_PROFILE( profile ));
NactActionProfile *new =
nact_action_profile_new( profile->private->action, profile->private->name );
g_object_set( G_OBJECT( new ),
PROP_LABEL_STR, profile->private->label,
PROP_PATH_STR, profile->private->path,
PROP_PARAMETERS_STR, profile->private->parameters,
PROP_ACCEPT_MULTIPLE_STR, profile->private->accept_multiple_files,
PROP_BASENAMES_STR, profile->private->basenames,
PROP_ISDIR_STR, profile->private->is_dir,
PROP_ISFILE_STR, profile->private->is_file,
PROP_MATCHCASE_STR, profile->private->match_case,
PROP_MIMETYPES_STR, profile->private->mimetypes,
PROP_SCHEMES_STR, profile->private->schemes,
NULL );
return( new );
}
void
nact_action_profile_free( NactActionProfile *profile )
{
g_assert( NACT_IS_ACTION_PROFILE( profile ));
g_free( profile->private->name );
g_free( profile->private->label );
g_free( profile->private->path );
g_free( profile->private->parameters );
nactuti_free_string_list( profile->private->basenames );
nactuti_free_string_list( profile->private->mimetypes );
nactuti_free_string_list( profile->private->schemes );
}
GType
nact_action_profile_get_type( void )
{
......@@ -262,6 +304,8 @@ class_init( NactActionProfileClass *klass )
klass->private = g_new0( NactActionProfileClassPrivate, 1 );
NACT_OBJECT_CLASS( klass )->dump = do_dump;
NACT_OBJECT_CLASS( klass )->get_id = do_get_id;
NACT_OBJECT_CLASS( klass )->get_label = do_get_label;
}
static void
......@@ -438,13 +482,7 @@ instance_finalize( GObject *object )
g_assert( NACT_IS_ACTION_PROFILE( object ));
NactActionProfile *self = ( NactActionProfile * ) object;
g_free( self->private->name );
g_free( self->private->label );
g_free( self->private->path );
g_free( self->private->parameters );
nactuti_free_string_list( self->private->basenames );
nactuti_free_string_list( self->private->mimetypes );
nactuti_free_string_list( self->private->schemes );
nact_action_profile_free( self );
/* chain call to parent class */
if((( GObjectClass * ) st_parent_class )->finalize ){
......@@ -494,6 +532,56 @@ do_dump_list( const gchar *thisfn, const gchar *label, GSList *list )
g_string_free( str, TRUE );
}
static gchar *
do_get_id( const NactObject *profile )
{
g_assert( NACT_IS_ACTION_PROFILE( profile ));
gchar *name;
g_object_get( G_OBJECT( profile ), PROP_PROFILE_NAME_STR, &name, NULL );
return( name );
}
/**
* Return the internal id (name) of the profile.
*
* @action: an NactActionProfile object.
*
* The returned string must be g_freed by the caller.
*/
gchar *
nact_action_profile_get_name( const NactActionProfile *profile )
{
g_assert( NACT_IS_ACTION_PROFILE( profile ));
return( nact_object_get_id( NACT_OBJECT( profile )));
}
static gchar *
do_get_label( const NactObject *profile )
{
g_assert( NACT_IS_ACTION_PROFILE( profile ));
gchar *label;
g_object_get( G_OBJECT( profile ), PROP_LABEL_STR, &label, NULL );
return( label );
}
/**
* Return the descriptive name (label) of the profile.
*
* @action: an NactAction object.
*
* The returned string must be g_freed by the caller.
*/
gchar *
nact_action_profile_get_label( const NactActionProfile *profile )
{
g_assert( NACT_IS_ACTION_PROFILE( profile ));
return( nact_object_get_label( NACT_OBJECT( profile )));
}
/*
* Check if the given profile is empty, i.e. all its attributes are
* empty.
......@@ -541,24 +629,6 @@ nact_action_profile_get_action( const NactActionProfile *profile )
return( NACT_OBJECT( action ));
}
/**
* Returns the profile name.
*
* The returned string should be g_freed by the caller.
*
* The profile name is also the GConf-key of the profile.
*/
gchar *
nact_action_profile_get_name( const NactActionProfile *profile )
{
g_assert( NACT_IS_ACTION_PROFILE( profile ));
gchar *name;
g_object_get( G_OBJECT( profile ), PROP_PROFILE_NAME_STR, &name, NULL );
return( name );
}
/**
* Returns the path of the command in the profile.
*
......@@ -617,7 +687,7 @@ validate_schemes( GSList* schemes2test, NautilusFileInfo* file )
}
gboolean
nact_action_profile_validate( const NactActionProfile *profile, GList* files )
nact_action_profile_is_candidate( const NactActionProfile *profile, GList* files )
{
gboolean retv = FALSE;
gboolean test_multiple_file = FALSE;
......@@ -833,3 +903,153 @@ nact_action_profile_validate( const NactActionProfile *profile, GList* files )
return retv;
}
/*
* Valid parameters :
*
* %u : gnome-vfs URI
* %d : base dir of the selected file(s)/folder(s)
* %f : the name of the selected file/folder or the 1st one if many are selected
* %m : list of the basename of the selected files/directories separated by space.
* %M : list of the selected files/directories with their complete path separated by space.
* %s : scheme of the gnome-vfs URI
* %h : hostname of the gnome-vfs URI
* %U : username of the gnome-vfs URI
* %% : a percent sign
*/
gchar *
nact_action_profile_parse_parameters( const NactActionProfile *profile, GList* files )
{
gchar* retv = NULL;
g_return_val_if_fail( NACT_IS_ACTION_PROFILE( profile ), NULL );
if (files != NULL){
const gchar *param_template = profile->private->parameters;
GString* tmp_string = g_string_new ("");
gchar* iter = g_strdup (param_template);
gchar* old_iter = iter;
/*int current_len = strlen (iter);*/
gchar* uri = nautilus_file_info_get_uri ((NautilusFileInfo*)files->data);
GnomeVFSURI* gvfs_uri = gnome_vfs_uri_new (uri);
gchar* filename;
gchar* dirname;
gchar* scheme = nautilus_file_info_get_uri_scheme ((NautilusFileInfo*)files->data);
gchar* hostname = g_strdup (gnome_vfs_uri_get_host_name (gvfs_uri));
gchar* username = g_strdup (gnome_vfs_uri_get_user_name (gvfs_uri));
gchar* file_list;
gchar* path_file_list;
GList* file_iter = NULL;
GString* tmp_file_list;
GString* tmp_path_file_list;
gchar* tmp;
gchar* tmp2;
tmp = gnome_vfs_uri_extract_dirname (gvfs_uri);
dirname = (gchar*)gnome_vfs_unescape_string ((const gchar*)tmp, "");
g_free (tmp);
tmp = nautilus_file_info_get_name ((NautilusFileInfo*)files->data);
if (!tmp)
{
tmp = g_strdup ("");
}
filename = g_shell_quote (tmp);
tmp2 = g_build_path ("/", dirname, tmp, NULL);
g_free (tmp);
tmp_file_list = g_string_new (filename);
tmp = g_shell_quote (tmp2);
tmp_path_file_list = g_string_new (tmp);
g_free (tmp2);
g_free (tmp);
/* We already have the first item, so we start with the next one if any */
for (file_iter = files->next; file_iter; file_iter = file_iter->next)
{
gchar* tmp_filename = nautilus_file_info_get_name ((NautilusFileInfo*)file_iter->data);
gchar* tmp_uri = nautilus_file_info_get_uri ((NautilusFileInfo*)file_iter->data);
GnomeVFSURI* tmp_gvfs_uri = gnome_vfs_uri_new (tmp_uri);
tmp = gnome_vfs_uri_extract_dirname (tmp_gvfs_uri);
gchar* tmp_dirname = (gchar*)gnome_vfs_unescape_string ((const gchar*)tmp, "");
g_free (tmp);
if (!tmp_filename)
{
tmp_filename = g_strdup ("");
}
gchar* quoted_tmp_filename = g_shell_quote (tmp_filename);
g_string_append_printf (tmp_file_list, " %s", quoted_tmp_filename);
tmp = g_build_path ("/", tmp_dirname, tmp_filename, NULL);
tmp2 = g_shell_quote (tmp);
g_string_append_printf (tmp_path_file_list, " %s", tmp2);
g_free (tmp2);
g_free (tmp);
g_free (tmp_filename);
g_free (quoted_tmp_filename);
g_free (tmp_dirname);
g_free (tmp_uri);
gnome_vfs_uri_unref (tmp_gvfs_uri);
}
file_list = g_string_free (tmp_file_list, FALSE);
path_file_list = g_string_free (tmp_path_file_list, FALSE);
while ((iter = g_strstr_len (iter, strlen (iter), "%")))
{
tmp_string = g_string_append_len (tmp_string, old_iter, strlen (old_iter) - strlen (iter));
switch (iter[1])
{
case 'u': /* gnome-vfs URI */
tmp_string = g_string_append (tmp_string, uri);
break;
case 'd': /* base dir of the selected file(s)/folder(s) */
tmp = g_shell_quote (dirname);
tmp_string = g_string_append (tmp_string, tmp);
g_free (tmp);
break;
case 'f': /* the basename of the selected file/folder or the 1st one if many are selected */
tmp_string = g_string_append (tmp_string, filename);
break;
case 'm': /* list of the basename of the selected files/directories separated by space */
tmp_string = g_string_append (tmp_string, file_list);
break;
case 'M': /* list of the selected files/directories with their complete path separated by space. */
tmp_string = g_string_append (tmp_string, path_file_list);
break;
case 's': /* scheme of the gnome-vfs URI */
tmp_string = g_string_append (tmp_string, scheme);
break;
case 'h': /* hostname of the gnome-vfs URI */
tmp_string = g_string_append (tmp_string, hostname);
break;
case 'U': /* username of the gnome-vfs URI */
tmp_string = g_string_append (tmp_string, username);
break;
case '%': /* a percent sign */
tmp_string = g_string_append_c (tmp_string, '%');
break;
}
iter+=2; /* skip the % sign and the character after. */
old_iter = iter; /* store the new start of the string */
}
tmp_string = g_string_append_len (tmp_string, old_iter, strlen (old_iter));
g_free (uri);
g_free (dirname);
g_free (filename);
g_free (file_list);
g_free (path_file_list);
g_free (scheme);
g_free (hostname);
g_free (username);
g_free (iter);
gnome_vfs_uri_unref (gvfs_uri);
retv = g_string_free (tmp_string, FALSE); /* return the content of the GString */
}
return retv;
}
......@@ -71,17 +71,19 @@ typedef struct {
GType nact_action_profile_get_type( void );
NactActionProfile *nact_action_profile_new( const NactObject *action, const gchar *name );
NactActionProfile *nact_action_profile_copy( const NactActionProfile *profile );
void nact_action_profile_free( NactActionProfile *profile );
void nact_action_profile_load( NactObject *profile );
/*gboolean nact_action_profile_is_empty( const NactActionProfile *profile );*/
NactObject *nact_action_profile_get_action( const NactActionProfile *profile );
gchar *nact_action_profile_get_name( const NactActionProfile *profile );
gchar *nact_action_profile_get_label( const NactActionProfile *profile );
gchar *nact_action_profile_get_path( const NactActionProfile *profile );
gchar *nact_action_profile_get_parameters( const NactActionProfile *profile );
gboolean nact_action_profile_validate( const NactActionProfile *profile, GList *files );
gboolean nact_action_profile_is_candidate( const NactActionProfile *profile, GList *files );
gchar *nact_action_profile_parse_parameters( const NactActionProfile *profile, GList *files );
G_END_DECLS
......
......@@ -94,6 +94,8 @@ static void free_profiles( NactAction *action );
static NactActionProfile *get_profile( const NactAction *action, const gchar *profile_name );
static void do_dump( const NactObject *action );
static gchar *do_get_id( const NactObject *action );
static gchar *do_get_label( const NactObject *action );
/**
* Allocate a new NactAction object.
......@@ -198,6 +200,8 @@ class_init( NactActionClass *klass )
klass->private = g_new0( NactActionClassPrivate, 1 );
NACT_OBJECT_CLASS( klass )->dump = do_dump;
NACT_OBJECT_CLASS( klass )->get_id = do_get_id;
NACT_OBJECT_CLASS( klass )->get_label = do_get_label;
}
static void
......@@ -331,39 +335,20 @@ free_profiles( NactAction *action )
{
g_assert( NACT_IS_ACTION( action ));
GSList *ip;
for( ip = action->private->profiles ; ip ; ip = ip->next ){
g_object_unref( NACT_ACTION_PROFILE( ip->data ));
}
g_slist_free( action->private->profiles );
nact_action_free_profiles( action->private->profiles );
action->private->profiles = NULL;
}
/**
* Create a new NactAction object, with the given parm and value.
*
* Note that the parm may actually be a profile's parm.
*/
/*NactAction *
nact_action_create( const gchar *key, const gchar *parm, const NactPivotValue *value )
{
static const gchar *thisfn = "nact_action_create";
g_debug( "%s: key='%s', parm='%s', value=%p", thisfn, key, parm, value );
NactAction *action = g_object_new( NACT_ACTION_TYPE, NULL );
nact_action_update( action, parm, value );
return( action );
}*/
/**
* Update the given parameter of an action.
*/
/*void
nact_action_update( NactAction *action, const gchar *parm, const NactPivotValue *value )
void
nact_action_free_profiles( GSList * list )
{
static const gchar *thisfn = "nact_action_update";
g_debug( "%s: action=%p, parm='%s', value=%p", thisfn, action, parm, value );
}*/
GSList *ip;
for( ip = list ; ip ; ip = ip->next ){
g_object_unref( NACT_ACTION_PROFILE( ip->data ));
}
g_slist_free( list );
}
static void
do_dump( const NactObject *action )
......@@ -391,72 +376,54 @@ do_dump( const NactObject *action )
}
}
/**
* Check if the given action is empty, i.e. all its attributes are empty.
*/
/*gboolean
nact_action_is_empty( const NactAction *action )
static gchar *
do_get_id( const NactObject *action )
{
g_assert( NACT_IS_ACTION( action ));
if( action->private->uuid && strlen( action->private->uuid )){
return( FALSE );
}
if( action->private->version && strlen( action->private->version )){
return( FALSE );
}
if( action->private->label && strlen( action->private->label )){
return( FALSE );
}
if( action->private->tooltip && strlen( action->private->tooltip )){
return( FALSE );
}
if( action->private->icon && strlen( action->private->icon )){
return( FALSE );
}
GSList *ip;
for( ip = action->private->profiles ; ip ; ip = ip->next ){
if( !nact_action_profile_is_empty( NACT_ACTION_PROFILE( ip->data ))){
return( FALSE );
}
}
return( TRUE );
}*/
gchar *uuid;
g_object_get( G_OBJECT( action ), PROP_UUID_STR, &uuid, NULL );
return( uuid );
}
/**
* Return the globally unique identifier (UUID) of the action.
*
* @action: an NactAction object.
*
* The returned string must be g_free by the caller.
* The returned string must be g_freed by the caller.
*/
gchar *
nact_action_get_uuid( const NactAction *action )
{
g_assert( NACT_IS_ACTION( action ));
return( nact_object_get_id( NACT_OBJECT( action )));
}
gchar *uuid;
g_object_get( G_OBJECT( action ), PROP_UUID_STR, &uuid, NULL );
static gchar *
do_get_label( const NactObject *action )
{
g_assert( NACT_IS_ACTION( action ));
return( uuid );
gchar *label;
g_object_get( G_OBJECT( action ), PROP_LABEL_STR, &label, NULL );
return( label );
}
/**
* Return the label of the context menu item for the action.
* Return the label of the action.
*
* @action: an NactAction object.
*
* The returned string must be g_free by the caller.
* The returned string must be g_freed by the caller.
*/
gchar *
nact_action_get_label( const NactAction *action )
{
g_assert( NACT_IS_ACTION( action ));
gchar *label;
g_object_get( G_OBJECT( action ), PROP_LABEL_STR, &label, NULL );
return( label );
return( nact_object_get_label( NACT_OBJECT( action )));
}
/**
......@@ -464,7 +431,7 @@ nact_action_get_label( const NactAction *action )
*
* @action: an NactAction object.
*
* The returned string must be g_free by the caller.
* The returned string must be g_freed by the caller.
*/
gchar *
nact_action_get_tooltip( const NactAction *action )
......@@ -532,7 +499,13 @@ nact_action_set_profiles( NactAction *action, GSList *list )
g_assert( NACT_IS_ACTION( action ));
free_profiles( action );
action->private->profiles = list;
GSList *ip;
for( ip = list ; ip ; ip = ip->next ){
action->private->profiles = g_slist_prepend(
action->private->profiles,
nact_action_profile_copy( NACT_ACTION_PROFILE( ip->data ))
);
}
}
guint
......
......@@ -71,10 +71,6 @@ GType nact_action_get_type( void );
NactAction *nact_action_new( const gchar *uuid );
/*NactAction *nact_action_create( const gchar *key, const gchar *parm, const NactPivotValue *value );
void nact_action_update( NactAction *action, const gchar *parm, const NactPivotValue *value );
gboolean nact_action_is_empty( const NactAction *action );*/
gchar *nact_action_get_uuid( const NactAction *action );
gchar *nact_action_get_label( const NactAction *action );
gchar *nact_action_get_tooltip( const NactAction *action );
......@@ -82,6 +78,7 @@ gchar *nact_action_get_verified_icon_name( const NactAction *action );
GSList *nact_action_get_profiles( const NactAction *action );
void nact_action_set_profiles( NactAction *action, GSList *list );
void nact_action_free_profiles( GSList *list );
guint nact_action_get_profiles_count( const NactAction *action );
GSList *nact_action_get_profile_ids( const NactAction *action );
......
......@@ -274,6 +274,7 @@ do_load_actions( NactIIOProvider *provider )
GSList *items = NULL;
GSList *ip;
GSList *listpath = load_subdirs( self, NACT_GCONF_CONFIG_PATH );
GSList *profiles;
for( ip = listpath ; ip ; ip = ip->next ){
......@@ -281,7 +282,9 @@ do_load_actions( NactIIOProvider *provider )
NactAction *action = nact_action_new( key );
load_action_properties( self, action );
nact_action_set_profiles( action, load_profiles( self, action ));
profiles = load_profiles( self, action );
nact_action_set_profiles( action, profiles );
nact_action_free_profiles( profiles );
#ifdef NACT_MAINTAINER_MODE
nact_object_dump( NACT_OBJECT( action ));
......
......@@ -56,6 +56,8 @@ static void instance_finalize( GObject *object );
static void do_dump( const NactObject *object );
static void do_empty_property( NactObject *object, const gchar *property );
static gchar *do_get_id( const NactObject *object );
static gchar *do_get_label( const NactObject *object );
GType
nact_object_get_type( void )
......@@ -103,6 +105,8 @@ class_init( NactObjectClass *klass )
klass->dump = do_dump;
klass->empty_property = do_empty_property;
klass->get_id = do_get_id;
klass->get_label = do_get_label;
}
static void
......@@ -199,6 +203,53 @@ void
nact_object_empty_property( NactObject *object, const gchar *property )
{
g_assert( NACT_IS_OBJECT( object ));
NACT_OBJECT_GET_CLASS( object )->empty_property( object, property );
}
static gchar *
do_get_id( const NactObject *object )
{
g_assert( NACT_IS_OBJECT( object ));
return(( gchar * ) NULL );
}
/**
* Returns the id of the object as new string.
*
* This is a virtual function which should be implemented by the
* derived class ; if not, this parent object returns NULL.
*
* @object: targeted NactObject object.
*
* The returned string should be g_freed by the caller.
*/
gchar *
nact_object_get_id( const NactObject *object )
{
g_assert( NACT_IS_OBJECT( object ));
return( NACT_OBJECT_GET_CLASS( object )->get_id( object ));
}
static gchar *
do_get_label( const NactObject *object )
{
g_assert( NACT_IS_OBJECT( object ));
return(( gchar * ) NULL );
}
/**
* Returns the label of the object as new string.
*
* This is a virtual function which should be implemented by the
* derived class ; if not, this parent object returns NULL.
*
* @object: targeted NactObject object.
*
* The returned string should be g_freed by the caller.
*/
gchar *
nact_object_get_label( const NactObject *object )
{
g_assert( NACT_IS_OBJECT( object ));
return( NACT_OBJECT_GET_CLASS( object )->get_label( object ));
}
......@@ -69,6 +69,8 @@ typedef struct {
/* virtual public functions */
void ( *dump )( const NactObject *object );
void ( *empty_property )( NactObject *object, const gchar *property );
gchar * ( *get_id )( const NactObject *object );
gchar * ( *get_label )( const NactObject *object );
}
NactObjectClass;
......@@ -76,6 +78,8 @@ GType nact_object_get_type( void );
void nact_object_dump( const NactObject *object );
void nact_object_empty_property( NactObject *object, const gchar *property );
gchar *nact_object_get_id( const NactObject *object );
gchar *nact_object_get_label( const NactObject *object );
G_END_DECLS
......
......@@ -98,8 +98,8 @@ static void instance_set_property( GObject *object, guint property_id, co
static void instance_dispose( GObject *object );
static void instance_finalize( GObject *object );
static void action_changed_handler( NactPivot *pivot, gpointer user_data );
static void free_actions( GSList *list );
static void action_changed_handler( NactPivot *pivot, gpointer user_data );
static NactAction *get_action( GSList *list, const gchar *uuid );
static gboolean on_action_changed_timeout( gpointer user_data );
static gulong time_val_diff( const GTimeVal *recent, const GTimeVal *old );
......@@ -287,6 +287,16 @@ instance_finalize( GObject *object )
}
}
static void
free_actions( GSList *list )
{
GSList *ia;
for( ia = list ; ia ; ia = ia->next ){
g_object_unref( NACT_ACTION( ia->data ));
}
g_slist_free( list );
}
/**
* Returns the list of providers of the required interface.
*
......@@ -316,6 +326,16 @@ nact_pivot_get_providers( const NactPivot *pivot, GType type )
return( list );
}
/**
* Return the list of actions.