[nautilus-actions: 20/30] Restore notification in NACT
- From: Pierre Wieser <pwieser src gnome org>
- To: svn-commits-list gnome org
- Cc:
- Subject: [nautilus-actions: 20/30] Restore notification in NACT
- Date: Sat, 21 Nov 2009 18:02:56 +0000 (UTC)
commit 1be56f1365c132750a7fb7a8f5ea110bee47f6a5
Author: Pierre Wieser <pwieser trychlos org>
Date: Fri Nov 20 23:41:00 2009 +0100
Restore notification in NACT
ChangeLog | 24 +++
TODO | 6 +-
nautilus-actions/api/na-iio-provider.c | 10 +-
nautilus-actions/api/na-iio-provider.h | 7 +-
.../io-provider-gconf/nagp-gconf-provider.c | 207 +++++++++++---------
nautilus-actions/io-provider-gconf/nagp-module.c | 63 +------
nautilus-actions/nact/nact-main.c | 19 ++-
nautilus-actions/runtime/na-io-provider.c | 25 +++
nautilus-actions/runtime/na-io-provider.h | 6 +-
nautilus-actions/runtime/na-module.c | 2 +-
nautilus-actions/runtime/na-pivot.c | 176 ++++++-----------
nautilus-actions/runtime/na-pivot.h | 31 +--
12 files changed, 271 insertions(+), 305 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index 675950b..ff4c8c8 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -4,6 +4,30 @@
Update compilation order as io-provider-gconf plugin depends on
runtime.
+ * nautilus-actions/api/na-iio-provider.c:
+ * nautilus-actions/api/na-iio-provider.h (na_iio_provider_config_changed):
+ Advertise interface with id of modified item.
+
+ * nautilus-actions/io-provider-gconf/nagp-gconf-provider.c:
+ Add a timeout to only trigger NAIIOProvider when all modifications
+ on an item have been made.
+
+ * nautilus-actions/io-provider-gconf/nagp-module.c (na_api_module_init):
+ Remove log handler management, no more syslog at initialization.
+
+ * nautilus-actions/nact/nact-main.c:
+ Simplify log management.
+
+ * nautilus-actions/runtime/na-io-provider.c:
+ * nautilus-actions/runtime/na-io-provider.h
+ (na_io_provider_register_callbacks): New function.
+
+ * nautilus-actions/runtime/na-module.c (plugin_check):
+ Fix error message.
+
+ * nautilus-actions/runtime/na-pivot.c:
+ Move static variables to the instance.
+
* nautilus-actions/nact/nact-iaction-tab.c
(on_tab_updatable_selection_changed):
Fix label display when the widget is disabled.
diff --git a/TODO b/TODO
index ae416ea..18eda9d 100644
--- a/TODO
+++ b/TODO
@@ -86,8 +86,10 @@
- na_pivot_new: shouldn't take an argument (use add_consumer)
-- gconf monitor doesn't work when creating with nautilus-actions-new
-
- in 64bits arch, pkglibdir=/lib ??
- NACT: unable to really delete an action imported with schemas
+
+- na_pivot_get_item: should return NAObjectItem
+
+- review log handlers (cf. nact for a ref)
diff --git a/nautilus-actions/api/na-iio-provider.c b/nautilus-actions/api/na-iio-provider.c
index d566ba8..4c4d2a6 100644
--- a/nautilus-actions/api/na-iio-provider.c
+++ b/nautilus-actions/api/na-iio-provider.c
@@ -142,12 +142,20 @@ do_is_writable( const NAIIOProvider *instance, const NAObjectItem *item )
/**
* na_iio_provider_config_changed:
* @instance: the calling NAIIOProvider.
+ * @id: the id of the modified #NAObjectItem-derived object.
*
* Advertises Nautilus-Actions that this #NAIIOProvider @instance has
* detected a modification in one of its configurations (menu or action).
+ *
+ * This function should be triggered for each and every #NAObjectItem-
+ * derived modified objects, but only once for each one.
*/
void
-na_iio_provider_config_changed( const NAIIOProvider *instance )
+na_iio_provider_config_changed( const NAIIOProvider *instance, const gchar *id )
{
+ static const gchar *thisfn = "na_iio_provider_config_changed";
+
+ g_debug( "%s: instance=%p, id=%s", thisfn, ( void * ) instance, id );
+ g_signal_emit_by_name(( gpointer ) instance, "notify-consumer-of-action-change", id );
}
diff --git a/nautilus-actions/api/na-iio-provider.h b/nautilus-actions/api/na-iio-provider.h
index 0970a4e..6131f6b 100644
--- a/nautilus-actions/api/na-iio-provider.h
+++ b/nautilus-actions/api/na-iio-provider.h
@@ -140,10 +140,11 @@ typedef struct {
GType na_iio_provider_get_type ( void );
-/* This function is to be called by the I/O provider when it detects a
- * modification of one of its objects in its underlying storage subsystem.
+/* This function is to be called by the I/O provider when it detects
+ * that the specified object has been modified in its underlying storage
+ * subsystem.
*/
-void na_iio_provider_config_changed ( const NAIIOProvider *instance );
+void na_iio_provider_config_changed ( const NAIIOProvider *instance, const gchar *id );
/* return code of write/delete operations
*/
diff --git a/nautilus-actions/io-provider-gconf/nagp-gconf-provider.c b/nautilus-actions/io-provider-gconf/nagp-gconf-provider.c
index 547195b..535c2e9 100644
--- a/nautilus-actions/io-provider-gconf/nagp-gconf-provider.c
+++ b/nautilus-actions/io-provider-gconf/nagp-gconf-provider.c
@@ -57,10 +57,15 @@ struct NagpGConfProviderPrivate {
gboolean dispose_has_run;
GConfClient *gconf;
GList *monitors;
+ GTimeVal last_event;
+ guint event_source_id;
+ gchar *last_triggered_id;
};
static GType st_module_type = 0;
static GObjectClass *st_parent_class = NULL;
+static gint st_timeout_msec = 100;
+static gint st_timeout_usec = 100000;
static void class_init( NagpGConfProviderClass *klass );
static void iio_provider_iface_init( NAIIOProviderInterface *iface );
@@ -70,9 +75,11 @@ static void instance_finalize( GObject *object );
static GList *install_monitors( NagpGConfProvider *provider );
static void config_path_changed_cb( GConfClient *client, guint cnxn_id, GConfEntry *entry, NagpGConfProvider *provider );
-#if 0
-static NAPivotNotify *entry_to_notify( const GConfEntry *entry );
-#endif
+static void config_path_changed_reset_timeout( NagpGConfProvider *provider );
+static void config_path_changed_set_timeout( NagpGConfProvider *provider, const gchar *uuid );
+static gboolean config_path_changed_trigger_interface( NagpGConfProvider *provider );
+static gulong time_val_diff( const GTimeVal *recent, const GTimeVal *old );
+static gchar *entry2uuid( GConfEntry *entry );
static GList *iio_provider_read_items( const NAIIOProvider *provider, GSList **messages );
static NAObjectItem *read_item( NagpGConfProvider *provider, const gchar *path );
@@ -278,17 +285,21 @@ install_monitors( NagpGConfProvider *provider )
* xml file in gconf, or gconf is directly edited), we'd have to rely
* only on the standard monitor (GConf watch) mechanism
*
- * this is what we do below, thus triggering the NAIIOProvider interface
- * for each and every modification in the GConf underlying system ; this
- * is the prerogative of NAIIOProvider to decide what to do with them
+ * this is what we do below, in three phases:
+ * - first, GConf underlying subsystem advertises us, through the watch
+ * mechanism, of each and every modification ; this leads us to be
+ * triggered for each new/modified/deleted _entry_
+ * - as we would trigger the NAIIOProvider interface only once for each
+ * modified _object_, we install a timer in order to wait for all
+ * entries have been modified, or another object is concerned
+ * - as soon as one of the two previous conditions is met, we trigger
+ * the NAIIOProvider interface with the corresponding object id
*/
static void
config_path_changed_cb( GConfClient *client, guint cnxn_id, GConfEntry *entry, NagpGConfProvider *provider )
{
/*static const gchar *thisfn = "nagp_gconf_provider_config_path_changed_cb";*/
-#if 0
- NAPivotNotify *npn;
-#endif
+ gchar *uuid;
/*g_debug( "%s: client=%p, cnxnid=%u, entry=%p, provider=%p",
thisfn, ( void * ) client, cnxn_id, ( void * ) entry, ( void * ) provider );*/
@@ -298,105 +309,117 @@ config_path_changed_cb( GConfClient *client, guint cnxn_id, GConfEntry *entry, N
if( !provider->private->dispose_has_run ){
-#if 0
- npn = entry_to_notify( entry );
- g_signal_emit_by_name( provider->private->pivot, NA_IIO_PROVIDER_SIGNAL_ACTION_CHANGED, npn );
-#endif
- na_iio_provider_config_changed( NA_IIO_PROVIDER( provider ));
+ uuid = entry2uuid( entry );
+ /*g_debug( "%s: uuid=%s", thisfn, uuid );*/
+
+ if( provider->private->event_source_id ){
+ if( g_ascii_strcasecmp( uuid, provider->private->last_triggered_id )){
+
+ /* there already has a timeout, but on another object
+ * so trigger the interface for the previous object
+ * and set the timeout for the new object
+ */
+ config_path_changed_trigger_interface( provider );
+ config_path_changed_set_timeout( provider, uuid );
+ }
+
+ /* there already has a timeout for this same object
+ * do nothing
+ */
+
+ } else {
+ /* there was not yet any timeout: set it
+ */
+ config_path_changed_set_timeout( provider, uuid );
+ }
+
+ g_free( uuid );
}
}
+static void
+config_path_changed_reset_timeout( NagpGConfProvider *provider )
+{
+ g_free( provider->private->last_triggered_id );
+ provider->private->last_triggered_id = NULL;
+ /*provider->private->last_event = ( GTimeVal ) 0;*/
+ provider->private->event_source_id = 0;
+}
+
+static void
+config_path_changed_set_timeout( NagpGConfProvider *provider, const gchar *uuid )
+{
+ config_path_changed_reset_timeout( provider );
+ provider->private->last_triggered_id = g_strdup( uuid );
+ g_get_current_time( &provider->private->last_event );
+ provider->private->event_source_id =
+ g_timeout_add(
+ st_timeout_msec,
+ ( GSourceFunc ) config_path_changed_trigger_interface,
+ provider );
+}
+
/*
- * convert a GConfEntry to a structure suitable to notify NAIIOProvider
- * interface
- *
- * when created or modified, the entry can be of the forms :
- * key=path/uuid/parm
- * key=path/uuid/profile/parm with a not null value
- *
- * but when removing an entry, it will be of the form :
- * key=path/uuid
- * key=path/uuid/parm
- * key=path/uuid/profile
- * key=path/uuid/profile/parm with a null value
- *
- * I don't see any way to choose between key/parm and key/profile (*)
- * as the entry no more exists in GConf and thus cannot be tested
- * -> we will set this as key/parm, letting the interface try to
- * interpret it
- *
- * (*) other than assuming that a profile name begins with 'profile-'
- * (see action-profile.h)
+ * this timer is set when we receive the first event of a serie
+ * we continue to loop until last event is at least one half of a
+ * second old
+ * there is no race condition here as we are not multithreaded
+ * or .. is there ?
*/
-#if 0
-static NAPivotNotify *
-entry_to_notify( const GConfEntry *entry )
+static gboolean
+config_path_changed_trigger_interface( NagpGConfProvider *provider )
+{
+ /*static const gchar *thisfn = "nagp_gconf_provider_config_path_changed_trigger_interface";*/
+ GTimeVal now;
+ gulong diff;
+
+ /*g_debug( "%s: provider=%p", thisfn, ( void * ) provider );*/
+
+ g_get_current_time( &now );
+ diff = time_val_diff( &now, &provider->private->last_event );
+ if( diff < st_timeout_usec ){
+ return( TRUE );
+ }
+
+ na_iio_provider_config_changed( NA_IIO_PROVIDER( provider ), provider->private->last_triggered_id );
+
+ config_path_changed_reset_timeout( provider );
+ return( FALSE );
+}
+
+/*
+ * returns the difference in microseconds.
+ */
+static gulong
+time_val_diff( const GTimeVal *recent, const GTimeVal *old )
+{
+ gulong microsec = 1000000 * ( recent->tv_sec - old->tv_sec );
+ microsec += recent->tv_usec - old->tv_usec;
+ return( microsec );
+}
+
+/*
+ * gets the uuid from an entry
+ */
+static gchar *
+entry2uuid( GConfEntry *entry )
{
- /*static const gchar *thisfn = "nagp_gconf_entry_to_notify";*/
- GSList *listvalues, *iv, *strings;
- NAPivotNotify *npn;
- gchar **split;
const gchar *path;
const gchar *subpath;
- const GConfValue *value;
-
- g_assert( entry );
- path = gconf_entry_get_key( entry );
- g_assert( path );
+ gchar **split;
+ gchar *uuid;
- npn = g_new0( NAPivotNotify, 1 );
+ g_return_val_if_fail( entry, NULL );
+ path = gconf_entry_get_key( entry );
subpath = path + strlen( NA_GCONF_CONFIG_PATH ) + 1;
split = g_strsplit( subpath, "/", -1 );
/*g_debug( "%s: [0]=%s, [1]=%s", thisfn, split[0], split[1] );*/
- npn->uuid = g_strdup( split[0] );
-
- if( g_strv_length( split ) == 2 ){
- npn->parm = g_strdup( split[1] );
-
- } else if( g_strv_length( split ) == 3 ){
- npn->profile = g_strdup( split[1] );
- npn->parm = g_strdup( split[2] );
- }
-
+ uuid = g_strdup( split[0] );
g_strfreev( split );
- value = gconf_entry_get_value( entry );
-
- if( value ){
- switch( value->type ){
-
- case GCONF_VALUE_STRING:
- npn->type = NA_PIVOT_STR;
- npn->data = ( gpointer ) g_strdup( gconf_value_get_string( value ));
- break;
-
- case GCONF_VALUE_BOOL:
- npn->type = NA_PIVOT_BOOL;
- npn->data = GINT_TO_POINTER( gconf_value_get_bool( value ));
- break;
-
- case GCONF_VALUE_LIST:
- listvalues = gconf_value_get_list( value );
- strings = NULL;
- for( iv = listvalues ; iv != NULL ; iv = iv->next ){
- strings = g_slist_prepend( strings,
- ( gpointer ) gconf_value_get_string(( GConfValue * ) iv->data ));
- }
-
- npn->type = NA_PIVOT_STRLIST;
- npn->data = ( gpointer ) na_utils_duplicate_string_list( strings );
- /*na_utils_free_string_list( strings );*/
- break;
-
- default:
- g_assert_not_reached();
- break;
- }
- }
- return( npn );
+ return( uuid );
}
-#endif
/**
* iio_provider_read_items:
diff --git a/nautilus-actions/io-provider-gconf/nagp-module.c b/nautilus-actions/io-provider-gconf/nagp-module.c
index 2430fa5..aa82bce 100644
--- a/nautilus-actions/io-provider-gconf/nagp-module.c
+++ b/nautilus-actions/io-provider-gconf/nagp-module.c
@@ -38,13 +38,6 @@
#include "nagp-gconf-provider.h"
-static guint st_log_handler_api = 0;
-static guint st_log_handler_plugin = 0;
-
-static void setup_log_handler( const gchar *log_domain, guint *handler_id );
-static void remove_log_handler( guint *handler_id );
-static void nagp_log_handler( const gchar *log_domain, GLogLevelFlags log_level, const gchar *message, gpointer user_data );
-
/*
* A Nautilus-Actions extension must implement four functions :
*
@@ -55,7 +48,8 @@ static void nagp_log_handler( const gchar *log_domain, GLogLevelFlags log_level,
*
* The first two functions are called at Nautilus-Actions startup.
*
- * The prototypes for these functions are defined in nautilus-actions/na-api.h
+ * The prototypes for these functions are defined in
+ * nautilus-actions/api/na-api.h
*/
gboolean
@@ -64,14 +58,7 @@ na_api_module_init( GTypeModule *module )
static const gchar *thisfn = "nagp_module_na_api_module_initialize";
static const gchar *name = "NagpGConfIOProvider";
- syslog( LOG_USER | LOG_INFO, "%s initializing...", name );
-
- openlog( G_LOG_DOMAIN, LOG_PID, LOG_USER );
-
- setup_log_handler( NA_LOGDOMAIN_API, &st_log_handler_api );
- setup_log_handler( NA_LOGDOMAIN_IO_PROVIDER_GCONF, &st_log_handler_plugin );
-
- g_debug( "%s: module=%p", thisfn, ( void * ) module );
+ g_debug( "%s: module=%p, %s initializing...", thisfn, ( void * ) module, name );
g_type_module_set_name( module, name );
@@ -103,7 +90,7 @@ na_api_module_get_name( GType type )
g_debug( "%s: type=%ld", thisfn, ( gulong ) type );
if( type == NAGP_GCONF_PROVIDER_TYPE ){
- return( "Nautilus Actions GConf Provider" );
+ return( "Nautilus-Actions GConf IO Provider" );
}
return( NULL );
@@ -115,46 +102,4 @@ na_api_module_shutdown( void )
static const gchar *thisfn = "nagp_module_na_api_module_shutdown";
g_debug( "%s", thisfn );
-
- /* remove the log handler
- * almost useless as the process is nonetheless terminating at this time
- * but this is the art of coding...
- */
- remove_log_handler( &st_log_handler_api );
- remove_log_handler( &st_log_handler_plugin );
-}
-
-static void
-setup_log_handler( const gchar *log_domain, guint *handler_id )
-{
- *handler_id = g_log_set_handler( log_domain, G_LOG_LEVEL_DEBUG, nagp_log_handler, NULL );
-}
-
-static void
-remove_log_handler( guint *handler_id )
-{
- if( *handler_id ){
- g_log_remove_handler( G_LOG_DOMAIN, *handler_id );
- *handler_id = 0;
- }
-}
-
-/*
- * a log handler that we install when in development mode in order to be
- * able to log plugin runtime
- * TODO: the debug flag should be dynamic, so that an advanced user could
- * setup a given key and obtain a full log to send to Bugzilla..
- * For now, is always install when compiled in maintainer mode, never else
- */
-static void
-nagp_log_handler( const gchar *log_domain,
- GLogLevelFlags log_level,
- const gchar *message,
- gpointer user_data )
-{
-#ifdef NA_MAINTAINER_MODE
- syslog( LOG_USER | LOG_DEBUG, "%s", message );
-#else
- /* do nothing */
-#endif
}
diff --git a/nautilus-actions/nact/nact-main.c b/nautilus-actions/nact/nact-main.c
index 77f29b7..b70d103 100644
--- a/nautilus-actions/nact/nact-main.c
+++ b/nautilus-actions/nact/nact-main.c
@@ -34,7 +34,10 @@
#include "nact-application.h"
-static void na_log_handler( const gchar *log_domain, GLogLevelFlags log_level, const gchar *message, gpointer user_data );
+static void set_log_handler( void );
+static void log_handler( const gchar *log_domain, GLogLevelFlags log_level, const gchar *message, gpointer user_data );
+
+static GLogFunc st_log_func = NULL;
int
main( int argc, char *argv[] )
@@ -42,9 +45,7 @@ main( int argc, char *argv[] )
NactApplication *app;
int ret;
- g_log_set_handler( NA_LOGDOMAIN_NACT, G_LOG_LEVEL_DEBUG, na_log_handler, NULL );
- g_log_set_handler( NA_LOGDOMAIN_PRIVATE, G_LOG_LEVEL_DEBUG, na_log_handler, NULL );
- g_log_set_handler( NA_LOGDOMAIN_RUNTIME, G_LOG_LEVEL_DEBUG, na_log_handler, NULL );
+ set_log_handler();
app = nact_application_new_with_args( argc, argv );
@@ -56,10 +57,16 @@ main( int argc, char *argv[] )
}
static void
-na_log_handler( const gchar *log_domain, GLogLevelFlags log_level, const gchar *message, gpointer user_data )
+set_log_handler( void )
+{
+ st_log_func = g_log_set_default_handler(( GLogFunc ) log_handler, NULL );
+}
+
+static void
+log_handler( const gchar *log_domain, GLogLevelFlags log_level, const gchar *message, gpointer user_data )
{
#ifdef NA_MAINTAINER_MODE
- g_log_default_handler( log_domain, log_level, message, user_data );
+ ( *st_log_func )( log_domain, log_level, message, user_data );
#else
/* do nothing */
#endif
diff --git a/nautilus-actions/runtime/na-io-provider.c b/nautilus-actions/runtime/na-io-provider.c
index 824741b..1faa093 100644
--- a/nautilus-actions/runtime/na-io-provider.c
+++ b/nautilus-actions/runtime/na-io-provider.c
@@ -50,6 +50,31 @@ static guint try_write_item( const NAIIOProvider *instance, NAObjectItem *ite
static GList *sort_tree( const NAPivot *pivot, GList *tree, GCompareFunc fn );
/**
+ * na_io_provider_register_callbacks:
+ * @pivot: the current #NAPivot instance.
+ *
+ * Registers an handler for the item-changed signal for each loaded
+ * NAIIOProvider plugin.
+ */
+void
+na_io_provider_register_callbacks( const NAPivot *pivot )
+{
+ GList *providers, *ip;
+
+ providers = na_pivot_get_providers( pivot, NA_IIO_PROVIDER_TYPE );
+
+ for( ip = providers ; ip ; ip = ip->next ){
+ g_signal_connect(
+ ( gpointer ) ip->data,
+ NA_PIVOT_SIGNAL_ACTION_CHANGED,
+ ( GCallback ) na_pivot_item_changed_handler,
+ ( gpointer ) pivot );
+ }
+
+ na_pivot_free_providers( providers );
+}
+
+/**
* na_io_provider_read_items:
* @pivot: the #NAPivot object which owns the list of registered I/O
* storage providers.
diff --git a/nautilus-actions/runtime/na-io-provider.h b/nautilus-actions/runtime/na-io-provider.h
index f3d5bae..196504c 100644
--- a/nautilus-actions/runtime/na-io-provider.h
+++ b/nautilus-actions/runtime/na-io-provider.h
@@ -44,14 +44,12 @@
G_BEGIN_DECLS
+void na_io_provider_register_callbacks( const NAPivot *pivot );
+
GList *na_io_provider_read_items ( const NAPivot *pivot, GSList **messages );
guint na_io_provider_write_item ( const NAPivot *pivot, NAObjectItem *item, GSList **messages );
guint na_io_provider_delete_item( const NAPivot *pivot, const NAObjectItem *item, GSList **messages );
-/* notification message to NAPivot
- */
-#define NA_IIO_PROVIDER_SIGNAL_ACTION_CHANGED "notify-consumer-of-action-change"
-
G_END_DECLS
#endif /* __NA_RUNTIME_IO_PROVIDER_H__ */
diff --git a/nautilus-actions/runtime/na-module.c b/nautilus-actions/runtime/na-module.c
index c62dc64..fa18621 100644
--- a/nautilus-actions/runtime/na-module.c
+++ b/nautilus-actions/runtime/na-module.c
@@ -324,7 +324,7 @@ plugin_check( NAModule *module, const gchar *symbol, gpointer *pfn )
ok = g_module_symbol( module->private->library, symbol, pfn );
if( !ok ){
- g_debug("%s: %s: %s: symbol", thisfn, module->private->path, symbol );
+ g_debug("%s: %s: %s: symbol not found", thisfn, module->private->path, symbol );
}
return( ok );
diff --git a/nautilus-actions/runtime/na-pivot.c b/nautilus-actions/runtime/na-pivot.c
index e8db861..58e5462 100644
--- a/nautilus-actions/runtime/na-pivot.c
+++ b/nautilus-actions/runtime/na-pivot.c
@@ -74,6 +74,9 @@ struct NAPivotPrivate {
* defaults to FALSE
*/
gboolean automatic_reload;
+ GTimeVal last_event;
+ guint event_source_id;
+ gulong action_changed_handler;
/* list of monitoring objects on runtime preferences
*/
@@ -87,8 +90,6 @@ enum {
static GObjectClass *st_parent_class = NULL;
static gint st_signals[ LAST_SIGNAL ] = { 0 };
-static GTimeVal st_last_event;
-static guint st_event_source_id = 0;
static gint st_timeout_msec = 100;
static gint st_timeout_usec = 100000;
@@ -101,14 +102,13 @@ static void instance_finalize( GObject *object );
static NAObject *get_item_from_tree( const NAPivot *pivot, GList *tree, uuid_t uuid );
-/* NAIPivotConsumer management */
-static void free_consumers( GList *list );
-
/* NAIIOProvider management */
-static void action_changed_handler( NAPivot *pivot, gpointer user_data );
-static gboolean on_actions_changed_timeout( gpointer user_data );
+static gboolean on_item_changed_timeout( NAPivot *pivot );
static gulong time_val_diff( const GTimeVal *recent, const GTimeVal *old );
+/* NAIPivotConsumer management */
+static void free_consumers( GList *list );
+
/* NAGConf runtime preferences management */
static void monitor_runtime_preferences( NAPivot *pivot );
@@ -179,14 +179,14 @@ class_init( NAPivotClass *klass )
klass->private = g_new0( NAPivotClassPrivate, 1 );
/* register the signal and its default handler
- * this signal should be sent by the IIOProvider when an action
+ * this signal should be sent by the IOProvider when an object
* has changed in the underlying storage subsystem
*/
- st_signals[ ACTION_CHANGED ] = g_signal_new_class_handler(
- NA_IIO_PROVIDER_SIGNAL_ACTION_CHANGED,
- G_TYPE_FROM_CLASS( klass ),
- G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE | G_SIGNAL_NO_HOOKS,
- ( GCallback ) action_changed_handler,
+ st_signals[ ACTION_CHANGED ] = g_signal_new(
+ NA_PIVOT_SIGNAL_ACTION_CHANGED,
+ NA_IIO_PROVIDER_TYPE,
+ G_SIGNAL_RUN_LAST,
+ 0,
NULL,
NULL,
g_cclosure_marshal_VOID__POINTER,
@@ -220,6 +220,7 @@ instance_init( GTypeInstance *instance, gpointer klass )
self->private->consumers = NULL;
self->private->tree = NULL;
self->private->automatic_reload = FALSE;
+ self->private->event_source_id = 0;
}
static void
@@ -251,6 +252,10 @@ instance_dispose( GObject *object )
/* release the GConf monitoring */
na_gconf_monitor_release_monitors( self->private->monitors );
+ if( g_signal_handler_is_connected( self, self->private->action_changed_handler )){
+ g_signal_handler_disconnect( self, self->private->action_changed_handler );
+ }
+
/* chain up to the parent class */
if( G_OBJECT_CLASS( st_parent_class )->dispose ){
G_OBJECT_CLASS( st_parent_class )->dispose( object );
@@ -300,6 +305,7 @@ na_pivot_new( const NAIPivotConsumer *target )
pivot = g_object_new( NA_PIVOT_TYPE, NULL );
pivot->private->modules = na_module_load_modules();
+ na_io_provider_register_callbacks( pivot );
/*g_debug( "%s: modules=%p, count=%d",
thisfn, ( void * ) pivot->private->modules, g_list_length( pivot->private->modules ));*/
@@ -366,6 +372,36 @@ na_pivot_dump( const NAPivot *pivot )
}
}
+/*
+ * this handler is trigerred by IIOProviders when an action is changed
+ * in the underlying storage subsystems
+ * we don't care of updating our internal list with each and every
+ * atomic modification
+ * instead we wait for the end of notifications serie, and then reload
+ * the whole list of actions
+ */
+void
+na_pivot_item_changed_handler( NAIIOProvider *provider, const gchar *id, NAPivot *pivot )
+{
+ static const gchar *thisfn = "na_pivot_item_changed_handler";
+
+ g_debug( "%s: provider=%p, id=%s, pivot=%p", thisfn, ( void * ) provider, id, ( void * ) pivot );
+
+ g_return_if_fail( NA_IS_IIO_PROVIDER( provider ));
+ g_return_if_fail( NA_IS_PIVOT( pivot ));
+
+ if( !pivot->private->dispose_has_run ){
+
+ /* set a timeout to notify clients at the end of the serie */
+ g_get_current_time( &pivot->private->last_event );
+
+ if( !pivot->private->event_source_id ){
+ pivot->private->event_source_id =
+ g_timeout_add( st_timeout_msec, ( GSourceFunc ) on_item_changed_timeout, pivot );
+ }
+ }
+}
+
/**
* na_pivot_get_providers:
* @pivot: this #NAPivot instance.
@@ -485,6 +521,7 @@ na_pivot_reload_items( NAPivot *pivot )
static const gchar *thisfn = "na_pivot_reload_items";
GSList *messages, *im;
+ g_debug( "%s: pivot=%p", thisfn, ( void * ) pivot );
g_return_if_fail( NA_IS_PIVOT( pivot ));
if( !pivot->private->dispose_has_run ){
@@ -811,66 +848,6 @@ get_item_from_tree( const NAPivot *pivot, GList *tree, uuid_t uuid )
return( found );
}
-static void
-free_consumers( GList *consumers )
-{
- /*g_list_foreach( consumers, ( GFunc ) g_object_unref, NULL );*/
- g_list_free( consumers );
-}
-
-/*
- * Note that each implementation of NAIIOProvider interface must have
- * this same type of constructor, which accepts as parameter a pointer
- * to this NAPivot object.
- * This is required because NAIIOProviders will send all their
- * notification messages to this NAPivot, letting this later redirect
- * them to appropriate NAIPivotConsumers.
- */
-/*
-static void
-register_io_providers( NAPivot *pivot )
-{
- static const gchar *thisfn = "na_pivot_register_io_providers";
- GList *list = NULL;
-
- g_debug( "%s: pivot=%p", thisfn, ( void * ) pivot );
- g_return_if_fail( NA_IS_PIVOT( pivot ));
- g_return_if_fail( !pivot->private->dispose_has_run );
-
- list = g_list_prepend( list, na_gconf_provider_new( pivot ));
-
- pivot->private->providers = list;
-}*/
-
-/*
- * this handler is trigerred by IIOProviders when an action is changed
- * in the underlying storage subsystems
- * we don't care of updating our internal list with each and every
- * atomic modification
- * instead we wait for the end of notifications serie, and then reload
- * the whole list of actions
- */
-static void
-action_changed_handler( NAPivot *self, gpointer user_data )
-{
- /*static const gchar *thisfn = "na_pivot_action_changed_handler";
- g_debug( "%s: self=%p, data=%p", thisfn, self, user_data );*/
-
- g_return_if_fail( NA_IS_PIVOT( self ));
- g_return_if_fail( !self->private->dispose_has_run );
- g_return_if_fail( user_data );
-
- if( self->private->dispose_has_run ){
- return;
- }
-
- /* set a timeout to notify clients at the end of the serie */
- g_get_current_time( &st_last_event );
- if( !st_event_source_id ){
- st_event_source_id = g_timeout_add( st_timeout_msec, ( GSourceFunc ) on_actions_changed_timeout, self );
- }
-}
-
/*
* this timer is set when we receive the first event of a serie
* we continue to loop until last event is at least one half of a
@@ -880,20 +857,18 @@ action_changed_handler( NAPivot *self, gpointer user_data )
* or .. is there ?
*/
static gboolean
-on_actions_changed_timeout( gpointer user_data )
+on_item_changed_timeout( NAPivot *pivot )
{
- /*static const gchar *thisfn = "na_pivot_on_actions_changed_timeout";
- g_debug( "%s: pivot=%p", thisfn, user_data );*/
+ static const gchar *thisfn = "na_pivot_on_item_changed_timeout";
GTimeVal now;
- NAPivot *pivot;
gulong diff;
GList *ic;
- g_return_val_if_fail( NA_IS_PIVOT( user_data ), FALSE );
- pivot = NA_PIVOT( user_data );
+ g_debug( "%s: pivot=%p", thisfn, pivot );
+ g_return_val_if_fail( NA_IS_PIVOT( pivot ), FALSE );
g_get_current_time( &now );
- diff = time_val_diff( &now, &st_last_event );
+ diff = time_val_diff( &now, &pivot->private->last_event );
if( diff < st_timeout_usec ){
return( TRUE );
}
@@ -907,7 +882,7 @@ on_actions_changed_timeout( gpointer user_data )
na_ipivot_consumer_notify_actions_changed( NA_IPIVOT_CONSUMER( ic->data ));
}
- st_event_source_id = 0;
+ pivot->private->event_source_id = 0;
return( FALSE );
}
@@ -922,42 +897,11 @@ time_val_diff( const GTimeVal *recent, const GTimeVal *old )
return( microsec );
}
-/**
- * na_pivot_free_notify:
- * @npn: a #NAPivotNotify structure.
- *
- * Frees a #NAPivotNotify structure and its content.
- */
-void
-na_pivot_free_notify( NAPivotNotify *npn )
+static void
+free_consumers( GList *consumers )
{
- if( npn ){
- if( npn->type ){
- switch( npn->type ){
-
- case NA_PIVOT_STR:
- g_free(( gchar * ) npn->data );
- break;
-
- case NA_PIVOT_BOOL:
- break;
-
- case NA_PIVOT_STRLIST:
- na_utils_free_string_list(( GSList * ) npn->data );
- break;
-
- default:
- g_debug( "na_pivot_free_notify: uuid=%s, profile=%s, parm=%s, type=%d",
- npn->uuid, npn->profile, npn->parm, npn->type );
- g_assert_not_reached();
- break;
- }
- }
- g_free( npn->uuid );
- g_free( npn->profile );
- g_free( npn->parm );
- g_free( npn );
- }
+ /*g_list_foreach( consumers, ( GFunc ) g_object_unref, NULL );*/
+ g_list_free( consumers );
}
static void
diff --git a/nautilus-actions/runtime/na-pivot.h b/nautilus-actions/runtime/na-pivot.h
index b5e299d..c78e7b7 100644
--- a/nautilus-actions/runtime/na-pivot.h
+++ b/nautilus-actions/runtime/na-pivot.h
@@ -52,7 +52,8 @@
* 1. When an I/O storage subsystem detects a change on an action, it
* should emit the "notify-consumer-of-action-change" signal to
* notify #NAPivot of this change. The user data associated with the
- * message should be a #gpointer to a #NAPivotNotify structure.
+ * message is the internal id of the #NAObjectItem-derived modified
+ * object.
*
* When this signal is received, #NAPivot updates accordingly the
* list of actions it maintains.
@@ -62,8 +63,7 @@
* sends only one message for a whole, maybe coherent, set of
* updates.
*
- * This first stage message is defined in na-iio-provider.h,
- * as NA_IIO_PROVIDER_SIGNAL_ACTION_CHANGED.
+ * This first stage message is defined below as NA_PIVOT_SIGNAL_ACTION_CHANGED.
*
* 2. When #NAPivot has successfully updated its list of actions, it
* notifies its consumers in order they update themselves.
@@ -71,9 +71,11 @@
* Note that #NAPivot tries to factorize notification messages, and
* to notify its consumers only once even if it has itself received
* many elementary notifications from the underlying I/O storage
- * subsystem.
+ * subsystems.
*/
+#include <api/na-iio-provider.h>
+
#include <private/na-object-class.h>
#include <private/na-object-id-class.h>
#include <private/na-object-item-class.h>
@@ -111,6 +113,8 @@ NAPivot *na_pivot_new( const NAIPivotConsumer *notified );
void na_pivot_check_status( const NAPivot *pivot );
void na_pivot_dump( const NAPivot *pivot );
+void na_pivot_item_changed_handler( NAIIOProvider *provider, const gchar *id, NAPivot *pivot );
+
GList *na_pivot_get_providers( const NAPivot *pivot, GType type );
GObject *na_pivot_get_provider( const NAPivot *pivot, GType type );
void na_pivot_release_provider( const GObject *provider );
@@ -136,24 +140,9 @@ gint na_pivot_sort_alpha_desc( const NAObjectId *a, const NAObjectId *b );
void na_pivot_write_level_zero( const NAPivot *pivot, GList *items );
-/* data passed from the storage subsystem when an action is changed
+/* notification message from NAIIOProvider to NAPivot
*/
-enum {
- NA_PIVOT_STR = 1,
- NA_PIVOT_BOOL,
- NA_PIVOT_STRLIST
-};
-
-typedef struct {
- gchar *uuid;
- gchar *profile;
- gchar *parm;
- guint type;
- gpointer data;
-}
- NAPivotNotify;
-
-void na_pivot_free_notify( NAPivotNotify *data );
+#define NA_PIVOT_SIGNAL_ACTION_CHANGED "notify-consumer-of-action-change"
G_END_DECLS
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]