Commit ec204bc9 authored by Pierre Wieser's avatar Pierre Wieser

Begin with porting NACT to new object hierarchy

parent a5fcf9e9
2009-06-18 Pierre Wieser <pwieser@trychlos.org>
Begin with porting NACT to new object hierarchy.
* src/common/nact-action.c:
* src/common/nact-action.h (nact_action_duplicate,
nact_action_get_version, nact_action_get_icon,
nact_action_set_new_uuid): New functions.
* src/common/nact-iio-provider.c:
* src/common/nact-iio-provider.h (+nact_iio_provider_write_action):
New function.
* src/common/nact-pivot.c:
* src/common/nact-pivot.h (nact_pivot_get_label_sorted_actions,
nact_pivot_get_action, nact_pivot_add_action):
New functions.
* src/nact/base-application.c:
* src/nact/base-application.h: New base class.
* src/nact/nact-application.c:
* src/nact/nact-application.h: Updated accordingly.
2009-06-14 Pierre Wieser <pwieser@trychlos.org>
* po/POTFILES.in: Add src/nact-application.c.
......
intltool.m4
libtool.m4
ltoptions.m4
ltsugar.m4
ltversion.m4
lt~obsolete.m4
......@@ -33,6 +33,7 @@
#endif
#include <string.h>
#include <uuid/uuid.h>
#include "nact-action.h"
#include "nact-action-profile.h"
......@@ -325,6 +326,39 @@ nact_action_new( const gchar *uuid )
return( action );
}
/**
* Allocates a new NactAction object, and initializes it as an exact
* copy of the specified action.
*
* @action: the action to be duplicated.
*
* Return a newly allocated NactAction object.
*
* Please note than "an exact copy" here means that the newly allocated
* returned object has the _same_ UUID than the original one.
*/
NactAction *
nact_action_duplicate( const NactAction *action )
{
g_assert( NACT_IS_ACTION( action ));
gchar *uuid = do_get_id( NACT_OBJECT( action ));
NactAction *duplicate = g_object_new( NACT_ACTION_TYPE, PROP_UUID_STR, uuid, NULL );
g_free( uuid );
duplicate->private->version = g_strdup( action->private->version );
duplicate->private->label = g_strdup( action->private->label );
duplicate->private->tooltip = g_strdup( action->private->tooltip );
duplicate->private->icon = g_strdup( action->private->icon );
GSList *ip;
for( ip = action->private->profiles ; ip ; ip = ip->next ){
}
return( duplicate );
}
static void
do_dump( const NactObject *action )
{
......@@ -376,6 +410,28 @@ nact_action_get_uuid( const NactAction *action )
return( nact_object_get_id( NACT_OBJECT( action )));
}
/**
* Returns the version attached to the action.
*
* @action: an NactAction object.
*
* The returned string must be g_freed by the caller.
*
* The version is always upgraded to the latest when the action is
* readen from the I/O provider. So we could assert here that the
* returned version is also the latest.
*/
gchar *
nact_action_get_version( const NactAction *action )
{
g_assert( NACT_IS_ACTION( action ));
gchar *version;
g_object_get( G_OBJECT( action ), PROP_VERSION_STR, &version, NULL );
return( version );
}
static gchar *
do_get_label( const NactObject *action )
{
......@@ -420,6 +476,25 @@ nact_action_get_tooltip( const NactAction *action )
return( tooltip );
}
/**
* Returns the name of the icon attached to the context menu item for
* the action.
*
* @action: an NactAction object.
*
* The returned string must be g_freed by the caller.
*/
gchar *
nact_action_get_icon( const NactAction *action )
{
g_assert( NACT_IS_ACTION( action ));
gchar *icon;
g_object_get( G_OBJECT( action ), PROP_ICON_STR, &icon, NULL );
return( icon );
}
/**
* Returns the icon name attached to the context menu item for the
* action.
......@@ -449,6 +524,24 @@ nact_action_get_verified_icon_name( const NactAction *action )
return( icon_name );
}
/**
* Set a new UUID for the action.
*
* @action: action whose UUID is to be set.
*/
void
nact_action_set_new_uuid( NactAction *action )
{
g_assert( NACT_IS_ACTION( action ));
uuid_t uuid;
gchar uuid_str[64];
uuid_generate( uuid );
uuid_unparse_lower( uuid, uuid_str );
g_object_set( G_OBJECT( action ), PROP_UUID_STR, uuid_str, NULL );
}
/**
* Returns the list of profiles of the actions as a GSList of
* NactActionProfile GObjects.
......
......@@ -70,12 +70,17 @@ typedef struct {
GType nact_action_get_type( void );
NactAction *nact_action_new( const gchar *uuid );
NactAction *nact_action_duplicate( const NactAction *action );
gchar *nact_action_get_uuid( const NactAction *action );
gchar *nact_action_get_version( const NactAction *action );
gchar *nact_action_get_label( const NactAction *action );
gchar *nact_action_get_tooltip( const NactAction *action );
gchar *nact_action_get_icon( const NactAction *action );
gchar *nact_action_get_verified_icon_name( const NactAction *action );
void nact_action_set_new_uuid( 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 );
......
......@@ -32,6 +32,10 @@
#include <config.h>
#endif
#include <glib.h>
#include "nact-action.h"
#include "nact-action-profile.h"
#include "nact-iio-provider.h"
#include "nact-pivot.h"
......@@ -152,3 +156,46 @@ nact_iio_provider_load_actions( const GObject *object )
return( actions );
}
/**
* Writes an action to a willing-to storage subsystem.
*
* @obj_pivot: the pivot object which owns the list of registered
* interface providers.
*
* @obj_action: the action to be written.
*
* @message: the I/O provider can allocate and store here an error
* message.
*
* Returns TRUE if the write is successfull, FALSE else.
*/
gboolean
nact_iio_provider_write_action( const GObject *obj_pivot, const GObject *obj_action, gchar **message )
{
static const gchar *thisfn = "nact_iio_provider_write_action";
g_debug( "%s", thisfn );
g_assert( NACT_IS_PIVOT( obj_pivot ));
NactPivot *pivot = NACT_PIVOT( obj_pivot );
g_assert( NACT_IS_ACTION( obj_action ));
gboolean ret = TRUE;
GSList *ip;
NactIIOProvider *instance;
GSList *providers = nact_pivot_get_providers( pivot, NACT_IIO_PROVIDER_TYPE );
for( ip = providers ; ip ; ip = ip->next ){
instance = NACT_IIO_PROVIDER( ip->data );
/*if( NACT_IIO_PROVIDER_GET_INTERFACE( instance )->write_action ){
list = NACT_IIO_PROVIDER_GET_INTERFACE( instance )->load_actions( instance );
actions = g_slist_concat( actions, list );
}*/
}
return( ret );
}
......@@ -61,12 +61,14 @@ typedef struct {
/* i/o api */
GSList * ( *load_actions )( NactIIOProvider *instance );
gboolean ( *write_action )( NactIIOProvider *instance, const GObject *action, gchar **message );
}
NactIIOProviderInterface;
GType nact_iio_provider_get_type( void );
GType nact_iio_provider_get_type( void );
GSList *nact_iio_provider_load_actions( const GObject *pivot );
GSList *nact_iio_provider_load_actions( const GObject *pivot );
gboolean nact_iio_provider_write_action( const GObject *pivot, const GObject *action, gchar **message );
G_END_DECLS
......
......@@ -33,6 +33,7 @@
#endif
#include <string.h>
#include <uuid/uuid.h>
#include "nact-action.h"
#include "nact-gconf.h"
......@@ -99,6 +100,7 @@ static void instance_dispose( GObject *object );
static void instance_finalize( GObject *object );
static void free_actions( GSList *list );
static gint sort_actions_by_label( gconstpointer a1, gconstpointer a2 );
static void action_changed_handler( NactPivot *pivot, gpointer user_data );
static gboolean on_action_changed_timeout( gpointer user_data );
static gulong time_val_diff( const GTimeVal *recent, const GTimeVal *old );
......@@ -325,8 +327,29 @@ nact_pivot_get_providers( const NactPivot *pivot, GType type )
return( list );
}
/**
* Return the list of actions, sorted by label.
*
* @pivot: this NactPivot object.
*
* The returned list is owned by this NactPivot object, and should not
* be freed, nor unref by the caller.
*/
GSList *
nact_pivot_get_label_sorted_actions( const NactPivot *pivot )
{
g_assert( NACT_IS_PIVOT( pivot ));
GSList *sorted = g_slist_sort( pivot->private->actions, ( GCompareFunc ) sort_actions_by_label );
return( sorted );
}
/**
* Return the list of actions.
*
* @pivot: this NactPivot object.
*
* The returned list is owned by this NactPivot object, and should not
* be freed, nor unref by the caller.
*/
GSList *
nact_pivot_get_actions( const NactPivot *pivot )
......@@ -345,6 +368,82 @@ free_actions( GSList *list )
g_slist_free( list );
}
static gint
sort_actions_by_label( gconstpointer a1, gconstpointer a2 )
{
NactAction *action1 = NACT_ACTION( a1 );
gchar *label1 = nact_action_get_label( action1 );
NactAction *action2 = NACT_ACTION( a2 );
gchar *label2 = nact_action_get_label( action2 );
gint ret = g_utf8_collate( label1, label2 );
g_free( label1 );
g_free( label2 );
return( ret );
}
/**
* Return the specified action.
*
* @pivot: this NactPivot object.
*
* @uuid: required globally unique identifier (uuid).
*
* Returns the specified NactAction object, or NULL if not found.
*
* The returned pointer is owned by NactPivot, and should not be freed
* nor unref by the caller.
*/
GObject *
nact_pivot_get_action( NactPivot *pivot, const gchar *uuid )
{
GSList *ia;
NactAction *act;
GObject *found = NULL;
uuid_t uua, uub;
gchar *uuid_act;
g_assert( NACT_IS_PIVOT( pivot ));
uuid_parse( uuid, uua );
for( ia = pivot->private->actions ; ia ; ia = ia->next ){
act = NACT_ACTION( ia->data );
uuid_act = nact_action_get_uuid( act );
uuid_parse( uuid_act, uub );
g_free( uuid_act );
if( !uuid_compare( uua, uub )){
found = G_OBJECT( act );
break;
}
}
return( found );
}
/**
* Write an action.
*
* @pivot: this NactPivot object.
*
* @action: action to be written by the storage subsystem.
*
* @message: the I/O provider can allocate and store here an error
* message.
*
* Returns TRUE if the write is successfull, FALSE else.
*/
gboolean
nact_pivot_add_action( NactPivot *pivot, const GObject *action, gchar **message )
{
g_assert( NACT_IS_PIVOT( pivot ));
g_assert( NACT_IS_ACTION( action ));
g_assert( message );
return( nact_iio_provider_write_action( G_OBJECT( pivot ), action, message ));
}
/*
* this handler is trigerred by IIOProviders when an action is changed
* in the underlying storage subsystems
......
......@@ -73,8 +73,13 @@ NactPivot *nact_pivot_new( const GObject *notified );
GSList *nact_pivot_get_providers( const NactPivot *pivot, GType type );
GSList *nact_pivot_get_label_sorted_actions( const NactPivot *pivot );
GSList *nact_pivot_get_actions( const NactPivot *pivot );
GObject *nact_pivot_get_action( NactPivot *pivot, const gchar *uuid );
gboolean nact_pivot_add_action( NactPivot *pivot, const GObject *action, gchar **message );
/* data passed from the storage subsystem when an action is changed
*/
enum {
......
......@@ -40,6 +40,8 @@ AM_CPPFLAGS += \
$(NULL)
nautilus_actions_config_SOURCES = \
base-application.c \
base-application.h \
nact.c \
nact.h \
nact-application.c \
......
This diff is collapsed.
/*
* 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 __BASE_APPLICATION_H__
#define __BASE_APPLICATION_H__
/*
* BaseApplication class definition.
*
* This is a base class for Gtk+ programs.
*/
#include <glib-object.h>
#include <gtk/gtk.h>
G_BEGIN_DECLS
#define BASE_APPLICATION_TYPE ( base_application_get_type())
#define BASE_APPLICATION( object ) ( G_TYPE_CHECK_INSTANCE_CAST( object, BASE_APPLICATION_TYPE, BaseApplication ))
#define BASE_APPLICATION_CLASS( klass ) ( G_TYPE_CHECK_CLASS_CAST( klass, BASE_APPLICATION_TYPE, BaseApplicationClass ))
#define BASE_IS_APPLICATION( object ) ( G_TYPE_CHECK_INSTANCE_TYPE( object, BASE_APPLICATION_TYPE ))
#define BASE_IS_APPLICATION_CLASS( klass ) ( G_TYPE_CHECK_CLASS_TYPE(( klass ), BASE_APPLICATION_TYPE ))
#define BASE_APPLICATION_GET_CLASS( object ) ( G_TYPE_INSTANCE_GET_CLASS(( object ), BASE_APPLICATION_TYPE, BaseApplicationClass ))
typedef struct BaseApplicationPrivate BaseApplicationPrivate;
typedef struct {
GObject parent;
BaseApplicationPrivate *private;
}
BaseApplication;
typedef struct BaseApplicationClassPrivate BaseApplicationClassPrivate;
typedef struct {
GObjectClass parent;
BaseApplicationClassPrivate *private;
/* virtual functions */
int ( *run ) ( BaseApplication *appli );
void ( *initialize ) ( BaseApplication *appli );
void ( *initialize_i18n ) ( BaseApplication *appli );
void ( *initialize_gtk ) ( BaseApplication *appli );
void ( *initialize_application_name ) ( BaseApplication *appli );
void ( *initialize_icon_name ) ( BaseApplication *appli );
void ( *initialize_unique ) ( BaseApplication *appli );
gboolean ( *is_willing_to_run ) ( BaseApplication *appli );
void ( *advertise_willing_to_run ) ( BaseApplication *appli );
void ( *advertise_not_willing_to_run )( BaseApplication *appli );
void ( *start ) ( BaseApplication *appli );
int ( *finish ) ( BaseApplication *appli );
gchar * ( *get_unique_name ) ( BaseApplication *appli );
gchar * ( *get_application_name ) ( BaseApplication *appli );
gchar * ( *get_icon_name ) ( BaseApplication *appli );
}
BaseApplicationClass;
GType base_application_get_type( void );
BaseApplication *base_application_new( void );
BaseApplication *base_application_new_with_args( int argc, char **argv );
int base_application_run( BaseApplication *application );
void base_application_error_dlg( BaseApplication *application, GtkMessageType type, gchar *primary, gchar *secondary );
G_END_DECLS
#endif /* __BASE_APPLICATION_H__ */
......@@ -34,8 +34,8 @@
#include <glib/gi18n.h>
#include <gtk/gtk.h>
#include <unique/unique.h>
#include <common/nact-pivot.h>
#include "nact.h"
#include "nact-application.h"
......@@ -48,39 +48,31 @@ struct NactApplicationClassPrivate {
*/
struct NactApplicationPrivate {
gboolean dispose_has_run;
int argc;
gpointer argv;
UniqueApp *unique;
GtkWindow *main;
NactPivot *pivot;
};
/* private instance properties
*/
enum {
PROP_ARGC = 1,
PROP_ARGV
PROP_PIVOT = 1
};
#define PROP_ARGC_STR "argc"
#define PROP_ARGV_STR "argv"
#define PROP_PIVOT_STR "pivot"
static GObjectClass *st_parent_class = NULL;
static GType register_type( void );
static void class_init( NactApplicationClass *klass );
static void instance_init( GTypeInstance *instance, gpointer klass );
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_dispose( GObject *application );
static void instance_finalize( GObject *application );
/*static UniqueResponse on_unique_message_received( UniqueApp *app, UniqueCommand command, UniqueMessageData *message, guint time, gpointer user_data );*/
static void warn_other_instance( NactApplication *application );
static gboolean check_for_unique_app( NactApplication *application );
static void initialize_i18n( NactApplication *application );
static gboolean startup_appli( NactApplication *application );
static int run_appli( NactApplication *application );
static void finish_appli( NactApplication *application );
static GType register_type( void );
static void class_init( NactApplicationClass *klass );
static void instance_init( GTypeInstance *instance, gpointer klass );
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_dispose( GObject *application );
static void instance_finalize( GObject *application );
static void warn_other_instance( BaseApplication *application );
static gchar *get_application_name( BaseApplication *application );
static gchar *get_icon_name( BaseApplication *application );
static gchar *get_unique_name( BaseApplication *application );
GType
nact_application_get_type( void )
......@@ -112,7 +104,7 @@ register_type( void )
( GInstanceInitFunc ) instance_init
};
return( g_type_register_static( G_TYPE_OBJECT, "NactApplication", &info, 0 ));
return( g_type_register_static( BASE_APPLICATION_TYPE, "NactApplication", &info, 0 ));
}
static void
......@@ -130,21 +122,21 @@ class_init( NactApplicationClass *klass )
object_class->set_property = instance_set_property;
GParamSpec *spec;
spec = g_param_spec_int(
PROP_ARGC_STR,
PROP_ARGC_STR,
"Command-line arguments count", 0, 65535, 0,
G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE );
g_object_class_install_property( object_class, PROP_ARGC, spec );
spec = g_param_spec_pointer(
PROP_ARGV_STR,
PROP_ARGV_STR,
"Command-line arguments",
G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE );
g_object_class_install_property( object_class, PROP_ARGV, spec );
PROP_PIVOT_STR,
PROP_PIVOT_STR,
"NactPivot object pointer",
G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE );
g_object_class_install_property( object_class, PROP_PIVOT, spec );
klass->private = g_new0( NactApplicationClassPrivate, 1 );
BaseApplicationClass *appli_class = BASE_APPLICATION_CLASS( klass );
appli_class->advertise_not_willing_to_run = warn_other_instance;
appli_class->get_application_name = get_application_name;
appli_class->get_icon_name = get_icon_name;
appli_class->get_unique_name = get_unique_name;
}
static void
......@@ -159,8 +151,6 @@ instance_init( GTypeInstance *instance, gpointer klass )
self->private = g_new0( NactApplicationPrivate, 1 );
self->private->dispose_has_run = FALSE;
self->private->unique = unique_app_new( "org.nautilus-actions.Config", NULL );
}
static void
......@@ -170,12 +160,8 @@ instance_get_property( GObject *object, guint property_id, GValue *value, GParam
NactApplication *self = NACT_APPLICATION( object );
switch( property_id ){
case PROP_ARGC:
g_value_set_int( value, self->private->argc );
break;
case PROP_ARGV:
g_value_set_pointer( value, self->private->argv );
case PROP_PIVOT:
g_value_set_pointer( value, self->private->pivot );
break;
default:
......@@ -191,12 +177,8 @@ instance_set_property( GObject *object, guint property_id, const GValue *value,
NactApplication *self = NACT_APPLICATION( object );
switch( property_id ){
case PROP_ARGC:
self->private->argc = g_value_get_int( value );
break;
case PROP_ARGV:
self->private->argv = g_value_get_pointer( value );
case PROP_PIVOT:
self->private->pivot = g_value_get_pointer( value );
break;
default:
......@@ -218,7 +200,7 @@ instance_dispose( GObject *application )
self->private->dispose_has_run = TRUE;
g_object_unref( self->private->unique );
g_object_unref( self->private->pivot );
/* chain up to the parent class */
G_OBJECT_CLASS( st_parent_class )->dispose( application );
......@@ -240,15 +222,6 @@ instance_finalize( GObject *application )
}
}
/**
* Returns a newly allocated NactApplication object.
*/
NactApplication *
nact_application_new( void )
{
return( g_object_new( NACT_APPLICATION_TYPE, NULL ));
}
/**
* Returns a newly allocated NactApplication object.
*
......@@ -259,155 +232,62 @@ nact_application_new( void )
NactApplication *
nact_application_new_with_args( int argc, char **argv )
{
return( g_object_new( NACT_APPLICATION_TYPE, PROP_ARGC_STR, argc, PROP_ARGV_STR, argv, NULL ));
return( g_object_new( NACT_APPLICATION_TYPE, "argc", argc, "argv", argv, NULL ));
}
/*static UniqueResponse
on_unique_message_received(
UniqueApp *app, UniqueCommand command, UniqueMessageData *message, guint time, gpointer user_data )
{
static const gchar *thisfn = "nact_application_check_for_unique_app";
UniqueResponse resp = UNIQUE_RESPONSE_OK;
switch( command ){
case UNIQUE_ACTIVATE:
g_debug( "%s: received message UNIQUE_ACTIVATE", thisfn );
break;
default:
resp = UNIQUE_RESPONSE_PASSTHROUGH;
break;
}
return( resp );
}*/
static void
warn_other_instance( NactApplication *application )
warn_other_instance( BaseApplication *application )
{
g_assert( NACT_IS_APPLICATION( application ));
gchar *msg;
msg = g_strdup_printf( "<b>%s</b>\n\n%s",
base_application_error_dlg(
application,
GTK_MESSAGE_INFO,
_( "Another instance of Nautilus Actions Configurator is already running." ),
_( "Please switch back to it." ));
GtkWidget *dialog = gtk_message_dialog_new_with_markup(
NULL, GTK_DIALOG_MODAL, GTK_MESSAGE_INFO, GTK_BUTTONS_OK, msg );
/* i18n: window title */
g_object_set( G_OBJECT( dialog ) , "title", _( "Nautilus Actions" ), NULL );
gtk_dialog_run( GTK_DIALOG( dialog ));
gtk_widget_destroy( dialog );
g_free( msg );
}
/*
* returns TRUE if we are the first instance
*/
static gboolean
check_for_unique_app( NactApplication *application )
static gchar *
get_application_name( BaseApplication *application )
{
gboolean is_first = TRUE;
g_assert( NACT_IS_APPLICATION( application ));
if( unique_app_is_running( application->private->unique )){
is_first = FALSE;
unique_app_send_message( application->private->unique, UNIQUE_ACTIVATE, NULL );
/* the screen is not actually modified, nor the main window is
* switched back to the current screen ; the icon in the deskbar