Commit 4b256cba authored by Pierre Wieser's avatar Pierre Wieser

Define NAIPivotContainer interface

parent a640af50
2009-06-26 Pierre Wieser <pwieser@trychlos.org>
Migration to GtkBuilder.
IPivotContainer interface definition.
* configure.ac:
Update Gtk+ dependancy to 2.12 to have gtk_builder functions.
......@@ -13,12 +14,37 @@
* src/common/na-pivot.c
(instance_dispose): g_free( self->private ).
* src/common/na-pivot.c
(na_pivot_get_label_sorted_actions): Removed function.
* src/common/na-gconf.c:
Fix typo in comment.
* src/common/na-iio-provider.c:
Actions list is now automatically sorted by label.
* src/common/na-iio-provider.h:
Move signal definition here to be usable by providers.
* src/common/na-ipivot-container.c:
* src/common/na-ipivot-container.h: New files.
* src/common/na-pivot.c:
na_pivot_get_label_sorted_actions: Removed function.
na_pivot_add_notified, free_containers: New functions.
Remove PROP_NOTIFIED property.
Containers to be notified can be several to many, instead of
just only one.
Use NAIPivotContainer interface instead of sending a message.
* src/common/Makefile.am: Updated accordingly.
* src/nact/base-application.c:
* src/nact/base-application.h
(base_application_get_icon_name,
base_application_get_main_window, base_application_run):
New functions.
* src/nact/nact-application.c:
Records the main window to be notified of an action modification.
* src/nact/nact-wnd-actions.c:
* src/nact/nact-wnd-actions.h:
Renamed to nact-main-window.{c,h}.
......@@ -28,19 +54,19 @@
* src/nact/nact-action-profile.c:
* src/nact/nact-action-profile.h: New files.
* src/nact/Makefile.am: Updated accordingly.
* src/nact/nact-main-window.c:
Implements NAIPivotContainer interface.
* src/nact/base-application.c:
* src/nact/base-application.h
(base_application_get_icon_name,
base_application_get_main_window, base_application_run):
New functions.
* src/nact/Makefile.am: Updated accordingly.
* src/nact/base-window.c:
* src/nact/base-window.h:
Remove libglade stuff.
Create the structure for derived windows/dialogs.
* src/plugin/nautilus-actions.c:
Implements NAIPivotContainer interface.
2009-06-20 Pierre Wieser <pwieser@trychlos.org>
* src/common/na-gconf.c:
......
......@@ -127,6 +127,7 @@ PKG_CHECK_MODULES([NAUTILUS_ACTIONS], \
gconf-2.0 >= ${GCONF_REQUIRED} \
libnautilus-extension >= ${NAUTILUS_EXTENSION} \
uuid \
libglade-2.0 \
unique-1.0
)
AC_SUBST([NAUTILUS_ACTIONS_CFLAGS])
......
......@@ -44,6 +44,8 @@ libnact_la_SOURCES = \
na-gconf-keys.h \
na-iio-provider.c \
na-iio-provider.h \
na-ipivot-container.c \
na-ipivot-container.h \
na-object.c \
na-object.h \
na-pivot.c \
......
......@@ -1083,7 +1083,7 @@ remove_gconf_watch( NAGConf *gconf )
* if the modification is made from nautilus-actions-config ui, then
* the callback is triggered several times (one time for each rewritten
* property) as action/profile are edited as blocs of data ; in this
* case, the ui takes care (aso of 1.10) of also writing at last a
* case, the ui takes care (as of of 1.10) of also writing at last a
* particular key of the form xxx:yyyyyyyy-yyyy-yyyy-..., where :
* xxx is a sequential number (inside of the ui session)
* yyyyyyyy-yyyy-yyyy-... is the uuid of the involved action
......@@ -1106,5 +1106,5 @@ action_changed_cb( GConfClient *client, guint cnxn_id, GConfEntry *entry, gpoint
NAGConf *gconf = NA_GCONF( user_data );
NAPivotNotify *npn = entry_to_notify( entry );
g_signal_emit_by_name( gconf->private->notified, "notify_pivot_of_action_changed", npn );
g_signal_emit_by_name( gconf->private->notified, NA_IIO_PROVIDER_SIGNAL_ACTION_CHANGED, npn );
}
......@@ -73,6 +73,10 @@ GSList *na_iio_provider_read_actions( const GObject *pivot );
guint na_iio_provider_write_action( const GObject *pivot, const GObject *action, gchar **message );
/* modification notification message to NAPivot
*/
#define NA_IIO_PROVIDER_SIGNAL_ACTION_CHANGED "notify_pivot_of_action_changed"
/* return code of write_action function
*/
enum {
......
......@@ -39,6 +39,7 @@
#include "na-gconf.h"
#include "na-pivot.h"
#include "na-iio-provider.h"
#include "na-ipivot-container.h"
#include "na-utils.h"
/* private class data
......@@ -49,41 +50,40 @@ struct NAPivotClassPrivate {
/* private instance data
*/
struct NAPivotPrivate {
gboolean dispose_has_run;
gboolean dispose_has_run;
/* instance to be notified of an action modification
/* list of instances to be notified of an action modification
*/
gpointer notified;
GSList *notified;
/* list of interface providers
* needs to be in the instance rather than in the class to be able
* to pass NAPivot object to the IO provider, so that the later
* is able to have access to the former (and its list of actions)
*/
GSList *providers;
GSList *providers;
/* list of actions
*/
GSList *actions;
GSList *actions;
};
/* private instance properties
*/
enum {
PROP_NOTIFIED = 1
};
#define PROP_NOTIFIED_STR "to-be-notified"
/* signal definition
/* We have a double stage notification system :
*
* 1. When the storage subsystems detects a change on an action, it
* must emit the "notify_pivot_of_action_changed" signal to notify
* NAPivot of this change ; when this signal is received, NAPivot
* then updates accordingly the list of actions it maintains.
*
* 2. When NAPivot has successfully updated its list of actions, it has
* to notify its consumers (its 'containers') in order they update
* themselves.
*/
enum {
ACTION_CHANGED,
LAST_SIGNAL
};
#define SIGNAL_ACTION_CHANGED_NAME "notify_pivot_of_action_changed"
static GObjectClass *st_parent_class = NULL;
static gint st_signals[ LAST_SIGNAL ] = { 0 };
static GTimeVal st_last_event;
......@@ -94,13 +94,12 @@ static GType register_type( void );
static void class_init( NAPivotClass *klass );
static void instance_init( GTypeInstance *instance, gpointer klass );
static GSList *register_interface_providers( const NAPivot *pivot );
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 *object );
static void free_containers( GSList *list );
static void instance_finalize( GObject *object );
static void action_changed_handler( NAPivot *pivot, gpointer user_data );
static gboolean on_action_changed_timeout( gpointer user_data );
static gboolean on_actions_changed_timeout( gpointer user_data );
static gulong time_val_diff( const GTimeVal *recent, const GTimeVal *old );
GType
......@@ -144,23 +143,15 @@ class_init( NAPivotClass *klass )
GObjectClass *object_class = G_OBJECT_CLASS( klass );
object_class->dispose = instance_dispose;
object_class->finalize = instance_finalize;
object_class->set_property = instance_set_property;
object_class->get_property = instance_get_property;
GParamSpec *spec;
spec = g_param_spec_pointer(
PROP_NOTIFIED_STR,
PROP_NOTIFIED_STR,
"A pointer to a GObject which will receive action_changed notifications",
G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE );
g_object_class_install_property( object_class, PROP_NOTIFIED, spec );
klass->private = g_new0( NAPivotClassPrivate, 1 );
/* see nautilus_actions_class_init for why we use this function
/* register the signal and its default handler
* this signal should be sent by the IIOProviders when an actions
* has changed in the underlying storage subsystem
*/
st_signals[ ACTION_CHANGED ] = g_signal_new_class_handler(
SIGNAL_ACTION_CHANGED_NAME,
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,
......@@ -201,40 +192,6 @@ register_interface_providers( const NAPivot *pivot )
return( list );
}
static void
instance_get_property( GObject *object, guint property_id, GValue *value, GParamSpec *spec )
{
g_assert( NA_IS_PIVOT( object ));
NAPivot *self = NA_PIVOT( object );
switch( property_id ){
case PROP_NOTIFIED:
g_value_set_pointer( value, self->private->notified );
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID( object, property_id, spec );
break;
}
}
static void
instance_set_property( GObject *object, guint property_id, const GValue *value, GParamSpec *spec )
{
g_assert( NA_IS_PIVOT( object ));
NAPivot *self = NA_PIVOT( object );
switch( property_id ){
case PROP_NOTIFIED:
self->private->notified = g_value_get_pointer( value );
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID( object, property_id, spec );
break;
}
}
static void
instance_dispose( GObject *object )
{
......@@ -248,6 +205,9 @@ instance_dispose( GObject *object )
self->private->dispose_has_run = TRUE;
/* release list of containers to be notified */
free_containers( self->private->notified );
/* release list of actions */
na_pivot_free_actions( self->private->actions );
self->private->actions = NULL;
......@@ -257,6 +217,15 @@ instance_dispose( GObject *object )
}
}
static void
free_containers( GSList *containers )
{
GSList *ic;
for( ic = containers ; ic ; ic = ic->next )
;
g_slist_free( containers );
}
static void
instance_finalize( GObject *object )
{
......@@ -295,7 +264,13 @@ instance_finalize( GObject *object )
NAPivot *
na_pivot_new( const GObject *target )
{
return( g_object_new( NA_PIVOT_TYPE, PROP_NOTIFIED_STR, target, NULL ));
NAPivot *pivot = g_object_new( NA_PIVOT_TYPE, NULL );
if( target ){
pivot->private->notified = g_slist_prepend( pivot->private->notified, ( gpointer ) target );
}
return( pivot );
}
/**
......@@ -439,7 +414,7 @@ action_changed_handler( NAPivot *self, gpointer user_data )
/* set a timeout to notify nautilus 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_seconds( 1, ( GSourceFunc ) on_action_changed_timeout, self );
st_event_source_id = g_timeout_add_seconds( 1, ( GSourceFunc ) on_actions_changed_timeout, self );
}
}
......@@ -452,9 +427,9 @@ action_changed_handler( NAPivot *self, gpointer user_data )
* or .. is there ?
*/
static gboolean
on_action_changed_timeout( gpointer user_data )
on_actions_changed_timeout( gpointer user_data )
{
/*static const gchar *thisfn = "na_pivot_on_action_changed_timeout";
/*static const gchar *thisfn = "na_pivot_on_actions_changed_timeout";
g_debug( "%s: pivot=%p", thisfn, user_data );*/
GTimeVal now;
......@@ -471,9 +446,12 @@ on_action_changed_timeout( gpointer user_data )
na_pivot_free_actions( pivot->private->actions );
pivot->private->actions = na_iio_provider_read_actions( G_OBJECT( pivot ));
g_signal_emit_by_name( G_OBJECT( pivot->private->notified ), "notify_nautilus_of_action_changed" );
st_event_source_id = 0;
GSList *ic;
for( ic = pivot->private->notified ; ic ; ic = ic->next ){
na_ipivot_container_notify( NA_IPIVOT_CONTAINER( ic->data ));
}
st_event_source_id = 0;
return( FALSE );
}
......@@ -522,3 +500,13 @@ na_pivot_free_notify( NAPivotNotify *npn )
g_free( npn );
}
}
/**
* Records a container which has to be notified of a modification of
* the list of actions.
*/
void
na_pivot_add_notified( NAPivot *pivot, GObject *container )
{
pivot->private->notified = g_slist_prepend( pivot->private->notified, container );
}
......@@ -100,6 +100,8 @@ typedef struct {
void na_pivot_free_notify( NAPivotNotify *data );
void na_pivot_add_notified( NAPivot *pivot, GObject *container );
G_END_DECLS
#endif /* __NA_PIVOT_H__ */
......@@ -159,7 +159,6 @@ instance_init( GTypeInstance *instance, gpointer klass )
self->private->dispose_has_run = FALSE;
/* TODO: be notified when the list of actions is changed elsewhere */
self->private->pivot = na_pivot_new( NULL );
}
......@@ -306,7 +305,11 @@ get_main_window( BaseApplication *application )
static const gchar *thisfn = "nact_application_get_main_window";
g_debug( "%s: application=%p", thisfn, application );
return( G_OBJECT( nact_main_window_new( G_OBJECT( application ))));
GObject *window = G_OBJECT( nact_main_window_new( G_OBJECT( application )));
na_pivot_add_notified( NA_PIVOT( nact_application_get_pivot( NACT_APPLICATION( application ))), window );
return( window );
}
/**
......
......@@ -40,6 +40,7 @@
#include <common/na-action.h>
#include <common/na-action-profile.h>
#include <common/na-pivot.h>
#include <common/na-ipivot-container.h>
#include "nact-application.h"
#include "nact-action-profile.h"
......@@ -62,6 +63,7 @@ static GObjectClass *st_parent_class = NULL;
static GType register_type( void );
static void class_init( NactMainWindowClass *klass );
static void iactions_list_iface_init( NactIActionsListInterface *iface );
static void ipivot_container_iface_init( NAIPivotContainerInterface *iface );
static void instance_init( GTypeInstance *instance, gpointer klass );
static void instance_dispose( GObject *application );
static void instance_finalize( GObject *application );
......@@ -80,6 +82,8 @@ static void on_delete_button_clicked( GtkButton *button, gpointer user_data
static void on_import_export_button_clicked( GtkButton *button, gpointer user_data );
static void on_dialog_response( GtkDialog *dialog, gint response_id, BaseWindow *window );
static void on_actions_changed( NAIPivotContainer *instance, gpointer user_data );
/*static gint count_actions( BaseWindow *window );*/
GType
......@@ -114,6 +118,8 @@ register_type( void )
GType type = g_type_register_static( NACT_WINDOW_TYPE, "NactMainWindow", &info, 0 );
/* implement IActionsList interface
*/
static const GInterfaceInfo iactions_list_iface_info = {
( GInterfaceInitFunc ) iactions_list_iface_init,
NULL,
......@@ -122,6 +128,16 @@ register_type( void )
g_type_add_interface_static( type, NACT_IACTIONS_LIST_TYPE, &iactions_list_iface_info );
/* implement IPivotContainer interface
*/
static const GInterfaceInfo pivot_container_iface_info = {
( GInterfaceInitFunc ) ipivot_container_iface_init,
NULL,
NULL
};
g_type_add_interface_static( type, NA_IPIVOT_CONTAINER_TYPE, &pivot_container_iface_info );
return( type );
}
......@@ -156,6 +172,15 @@ iactions_list_iface_init( NactIActionsListInterface *iface )
iface->on_double_click = on_actions_list_double_click;
}
static void
ipivot_container_iface_init( NAIPivotContainerInterface *iface )
{
static const gchar *thisfn = "nact_main_window_ipivot_container_iface_init";
g_debug( "%s: iface=%p", thisfn, iface );
iface->on_actions_changed = on_actions_changed;
}
static void
instance_init( GTypeInstance *instance, gpointer klass )
{
......@@ -531,6 +556,20 @@ on_dialog_response( GtkDialog *dialog, gint response_id, BaseWindow *window )
}
}
static void
on_actions_changed( NAIPivotContainer *instance, gpointer user_data )
{
static const gchar *thisfn = "nact_main_window_on_actions_changed";
g_debug( "%s: instance=%p, user_data=%p", thisfn, instance, user_data );
g_assert( NACT_IS_MAIN_WINDOW( instance ));
NactMainWindow *self = NACT_MAIN_WINDOW( instance );
if( !self->private->dispose_has_run ){
nact_iactions_list_fill( NACT_WINDOW( instance ));
}
}
/*static gint
count_actions( BaseWindow *window )
{
......
......@@ -41,6 +41,7 @@
#include <common/na-action.h>
#include <common/na-action-profile.h>
#include <common/na-pivot.h>
#include <common/na-ipivot-container.h>
#include "nautilus-actions.h"
......@@ -53,39 +54,15 @@ struct NautilusActionsClassPrivate {
*/
struct NautilusActionsPrivate {
gboolean dispose_has_run;
/* from na-pivot */
NAPivot *pivot;
};
/* We have a double stage notification system :
*
* 1. when the storage subsystems detects a change on an action, it must
* emit a signal to notify us of this change ; we so have to update
* accordingly the list of actions we maintain
*
* 2. when we have successfully updated the list of actions, we have to
* notify nautilus to update its contextual menu ; this is left to
* NautilusActions class
*
* This same signal is then first emitted by the IIOProvider to the
* NAPivot object which handles it. When all modifications have been
* treated, NAPivot notifies NautilusActions which itself asks
* Nautilus for updating its menu
*/
enum {
ACTION_CHANGED,
LAST_SIGNAL
};
#define SIGNAL_ACTION_CHANGED_NAME "notify_nautilus_of_action_changed"
static GObjectClass *st_parent_class = NULL;
static GType st_actions_type = 0;
static gint st_signals[ LAST_SIGNAL ] = { 0 };
static void class_init( NautilusActionsClass *klass );
static void menu_provider_iface_init( NautilusMenuProviderIface *iface );
static void pivot_container_iface_init( NAIPivotContainerInterface *iface );
static void instance_init( GTypeInstance *instance, gpointer klass );
static void instance_dispose( GObject *object );
static void instance_finalize( GObject *object );
......@@ -94,7 +71,7 @@ static GList *get_background_items( NautilusMenuProvider *provider, G
static GList *get_file_items( NautilusMenuProvider *provider, GtkWidget *window, GList *files );
static NautilusMenuItem *create_menu_item( NAAction *action, NAActionProfile *profile, GList *files );
static void execute_action( NautilusMenuItem *item, NAActionProfile *profile );
static void action_changed_handler( NautilusActions *instance, gpointer user_data );
static void actions_changed_handler( NAIPivotContainer *instance, gpointer user_data );
GType
nautilus_actions_get_type( void )
......@@ -123,6 +100,8 @@ nautilus_actions_register_type( GTypeModule *module )
( GInstanceInitFunc ) instance_init,
};
/* implements NautilusMenuItem interface
*/
st_actions_type = g_type_module_register_type( module, G_TYPE_OBJECT, "NautilusActions", &info, 0 );
static const GInterfaceInfo menu_provider_iface_info = {
......@@ -132,6 +111,16 @@ nautilus_actions_register_type( GTypeModule *module )
};
g_type_module_add_interface( module, st_actions_type, NAUTILUS_TYPE_MENU_PROVIDER, &menu_provider_iface_info );
/* implement IPivotContainer interface
*/
static const GInterfaceInfo pivot_container_iface_info = {
( GInterfaceInitFunc ) pivot_container_iface_init,
NULL,
NULL
};
g_type_module_add_interface( module, st_actions_type, NA_IPIVOT_CONTAINER_TYPE, &pivot_container_iface_info );
}
static void
......@@ -147,26 +136,6 @@ class_init( NautilusActionsClass *klass )
gobject_class->finalize = instance_finalize;
klass->private = g_new0( NautilusActionsClassPrivate, 1 );
/* we could have set a default handler here, which have been
* avoided us to connect to the signal ; but a default handler is
* addressed via a class structure offset, and thus cannot work
* when defined in a private structure
*
* the previous point applies to g_signal_new ;
* g_signal_new_class_handler let us specify a standard C callback
*/
st_signals[ ACTION_CHANGED ] = g_signal_new_class_handler(
SIGNAL_ACTION_CHANGED_NAME,
G_TYPE_FROM_CLASS( klass ),
G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE | G_SIGNAL_NO_HOOKS,
( GCallback ) action_changed_handler,
NULL,
NULL,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE,
0
);
}
static void
......@@ -179,6 +148,15 @@ menu_provider_iface_init( NautilusMenuProviderIface *iface )
iface->get_background_items = get_background_items;
}
static void
pivot_container_iface_init( NAIPivotContainerInterface *iface )
{
static const gchar *thisfn = "nautilus_actions_pivot_container_iface_init";
g_debug( "%s: iface=%p", thisfn, iface );
iface->on_actions_changed = actions_changed_handler;
}
static void
instance_init( GTypeInstance *instance, gpointer klass )
{
......@@ -408,12 +386,13 @@ execute_action( NautilusMenuItem *item, NAActionProfile *profile )
}
static void
action_changed_handler( NautilusActions *self, gpointer user_data )
actions_changed_handler( NAIPivotContainer *instance, gpointer user_data )
{
static const gchar *thisfn = "nautilus_actions_action_changed_handler";
g_debug( "%s: self=%p, user_data=%p", thisfn, self, user_data );
static const gchar *thisfn = "nautilus_actions_actions_changed_handler";
g_debug( "%s: instance=%p, user_data=%p", thisfn, instance, user_data );
g_return_if_fail( NAUTILUS_IS_ACTIONS( self ));
g_assert( NAUTILUS_IS_ACTIONS( instance ));
NautilusActions *self = NAUTILUS_ACTIONS( instance );
if( !self->private->dispose_has_run ){
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment