[nautilus-actions] Fix edition status and saving in the UI
- From: Pierre Wieser <pwieser src gnome org>
- To: svn-commits-list gnome org
- Cc:
- Subject: [nautilus-actions] Fix edition status and saving in the UI
- Date: Sat, 26 Sep 2009 22:49:11 +0000 (UTC)
commit 87282ae355aa4882dc0371caa89888daadb648cc
Author: Pierre Wieser <pwieser trychlos org>
Date: Tue Sep 22 22:54:36 2009 +0200
Fix edition status and saving in the UI
ChangeLog | 56 +++
TODO | 2 +
configure.ac | 1 +
src/common/na-iduplicable.c | 76 ++--
src/common/na-iduplicable.h | 7 +-
src/common/na-iio-provider.c | 44 +--
src/common/na-object-action.c | 13 +-
src/common/na-object-action.h | 8 +-
src/common/na-object-api.h | 7 +-
src/common/na-object-fn.h | 26 +-
src/common/na-object-id.c | 9 +-
src/common/na-object-item-fn.h | 4 +-
src/common/na-object-item.c | 115 ++++--
src/common/na-object-menu.c | 1 +
src/common/na-object-profile.c | 8 +
src/common/na-object.c | 753 +++++++++++++++++-------------
src/common/na-pivot.c | 133 +++---
src/common/na-pivot.h | 4 +-
src/nact/nact-assistant-import.c | 19 +-
src/nact/nact-assistant-import.h | 4 +-
src/nact/nact-clipboard.c | 2 +-
src/nact/nact-iactions-list.c | 86 +++-
src/nact/nact-iactions-list.h | 1 +
src/nact/nact-main-menubar.c | 178 +++++--
src/nact/nact-main-window.c | 42 +-
src/nact/nact-tree-model.c | 29 +-
src/nact/nact-window.c | 11 +-
src/nact/nautilus-actions-config-tool.ui | 2 -
28 files changed, 1018 insertions(+), 623 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index d7cdbd7..5231847 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,59 @@
+2009-09-22 Pierre Wieser <pwieser trychlos org>
+
+ * configure.ac: Add a comment about GtkActivatable.
+
+ * src/common/na-iduplicable.c:
+ * src/common/na-iduplicable.h:
+ Reorganize the code and add comments about recursivity inside.
+
+ * src/common/na-iio-provider.c:
+ Replace local dump_hierarchy() with call to na_object_dump_tree().
+ na_iio_provider_write_item(): Make debug trace more verbose.
+
+ * src/common/na-object-action.c:
+ * src/common/na-object-action.h:
+ Output debug traces depending on NAIDuplicable flag.
+ Fix equality check if a profile is modified.
+
+ * src/common/na-object-api.h (na_object_dump_norec,
+ na_object_dump_tree, na_object_rewind_origin): New functions.
+ na_object_insert_item(): Add a sibling pointer.
+
+ * src/common/na-object.c:
+ * src/common/na-object-fn.h:
+ Reorganize the code and add comments about recursivity inside.
+
+ * src/common/na-object-id.c:
+ * src/common/na-object-menu.c:
+ * src/common/na-object-profile.c: Make debug trace more verbose.
+
+ * src/common/na-object-item.c:
+ * src/common/na-object-item-fn.h (na_object_item_insert_item):
+ Add a sibling pointer.
+ na_object_item_free_items(): Only unref if object is always valid.
+ object_are_equal(): Position is a factor of equality.
+
+ * src/common/na-pivot.c:
+ * src/common/na-pivot.h (na_pivot_get_item): New function.
+
+ * src/nact/nact-assistant-import.c:
+ Actually imports the actions into the tree store before
+ confirming the operation was done.
+
+ * nact/nact-iactions-list.c:
+ * nact/nact-iactions-list.h (nact_iactions_list_get_item):
+ New function.
+
+ * src/nact/nact-main-menubar.c:
+ Do not use GtkActivatable if version <= 2.16.
+ Rewrite save items process.
+
+ * src/nact/nact-main-window.c (nact_main_window_action_exists):
+ Restore the function, searching in NAPivot and in tree store.
+
+ * src/nact/nact-tree-model.c:
+ Now inserts the new row before a given sibling object.
+
2009-09-21 Pierre Wieser <pwieser trychlos org>
* src/common/na-gconf-provider.c (write_item_menu):
diff --git a/TODO b/TODO
index fc37ca8..458bc45 100644
--- a/TODO
+++ b/TODO
@@ -50,3 +50,5 @@
cf. commit 5ee6938486cd82f1274969506873df950348dd61 and before
function nact-tree-model.c::add_parent
recreate a small code which reproduces this bug and open in bugzilla
+
+- lot of work to do on gconf editor
diff --git a/configure.ac b/configure.ac
index a40bf26..cd60585 100644
--- a/configure.ac
+++ b/configure.ac
@@ -111,6 +111,7 @@ AM_GCONF_SOURCE_2
# Gtk >= 2.12: GtkBuilder
#
# [nact-assistant] remove work-around for #589745 when Gtk+ >= 2.18
+# [nact-main-menubar] GtkActivatable only available starting with Gtk+ 2.16
#
# [configure.ac, nautilus-actions.c] remove test for
# nautilus_menu_provider_emit_items_updated_signal() when Gnome >= 2.16
diff --git a/src/common/na-iduplicable.c b/src/common/na-iduplicable.c
index 6a24264..8f0e994 100644
--- a/src/common/na-iduplicable.c
+++ b/src/common/na-iduplicable.c
@@ -254,43 +254,6 @@ na_iduplicable_dump( const NAIDuplicable *object )
}
/**
- * na_iduplicable_duplicate:
- * @object: the #NAIDuplicable object to be duplicated.
- *
- * Exactly duplicates a #NAIDuplicable-implemented object.
- * Properties %NA_IDUPLICABLE_PROP_ORIGIN, %PROP_IDUPLICABLE_ISMODIFIED
- * and %PROP_IDUPLICABLE_ISVALID are initialized to their default
- * values.
- *
- * As %PROP_IDUPLICABLE_ISVALID property is set to %TRUE without any
- * further check, this suppose that only valid objects are duplicated.
- *
- * Returns: a new #NAIDuplicable.
- */
-NAIDuplicable *
-na_iduplicable_duplicate( const NAIDuplicable *object )
-{
- /*static const gchar *thisfn = "na_iduplicable_duplicate";*/
- NAIDuplicable *dup = NULL;
-
- /*g_debug( "%s: object=%p", thisfn, ( void * ) object );*/
-
- g_return_val_if_fail( st_initialized && !st_finalized, NULL );
- g_return_val_if_fail( NA_IS_IDUPLICABLE( object ), NULL );
-
- dup = v_new( object );
-
- if( dup ){
- v_copy( dup, object );
- set_origin( dup, object );
- set_modified( dup, FALSE );
- set_valid( dup, TRUE );
- }
-
- return( dup );
-}
-
-/**
* na_iduplicable_check_edition_status:
* @object: the #NAIDuplicable object to be checked.
*
@@ -307,7 +270,7 @@ na_iduplicable_duplicate( const NAIDuplicable *object )
* That is, the modification and validity status are only set on the
* specified object.
* Nonetheless, a derived class may perfectly implement a recursive
- * check on childs, if any. See, e.g. #NAObjectItem implementation.
+ * check on childs, if any. See, e.g. #NAObject implementation.
*/
void
na_iduplicable_check_edition_status( const NAIDuplicable *object )
@@ -347,6 +310,43 @@ na_iduplicable_check_edition_status( const NAIDuplicable *object )
}
/**
+ * na_iduplicable_duplicate:
+ * @object: the #NAIDuplicable object to be duplicated.
+ *
+ * Exactly duplicates a #NAIDuplicable-implemented object.
+ * Properties %NA_IDUPLICABLE_PROP_ORIGIN, %PROP_IDUPLICABLE_ISMODIFIED
+ * and %PROP_IDUPLICABLE_ISVALID are initialized to their default
+ * values.
+ *
+ * As %PROP_IDUPLICABLE_ISVALID property is set to %TRUE without any
+ * further check, this suppose that only valid objects are duplicated.
+ *
+ * Returns: a new #NAIDuplicable.
+ */
+NAIDuplicable *
+na_iduplicable_duplicate( const NAIDuplicable *object )
+{
+ /*static const gchar *thisfn = "na_iduplicable_duplicate";*/
+ NAIDuplicable *dup = NULL;
+
+ /*g_debug( "%s: object=%p", thisfn, ( void * ) object );*/
+
+ g_return_val_if_fail( st_initialized && !st_finalized, NULL );
+ g_return_val_if_fail( NA_IS_IDUPLICABLE( object ), NULL );
+
+ dup = v_new( object );
+
+ if( dup ){
+ v_copy( dup, object );
+ set_origin( dup, object );
+ set_modified( dup, FALSE );
+ set_valid( dup, TRUE );
+ }
+
+ return( dup );
+}
+
+/**
* na_iduplicable_is_modified:
* @object: the #NAIDuplicable object whose status is to be returned.
*
diff --git a/src/common/na-iduplicable.h b/src/common/na-iduplicable.h
index a565f52..7260a13 100644
--- a/src/common/na-iduplicable.h
+++ b/src/common/na-iduplicable.h
@@ -145,21 +145,18 @@ typedef struct {
#define NA_IDUPLICABLE_SIGNAL_MODIFIED_CHANGED "na-iduplicable-modified-changed"
#define NA_IDUPLICABLE_SIGNAL_VALID_CHANGED "na-iduplicable-valid-changed"
-#define NA_IDUPLICABLE_EDITION_STATUS_DEBUG 0
+#define NA_IDUPLICABLE_EDITION_STATUS_DEBUG 1
GType na_iduplicable_get_type( void );
void na_iduplicable_init( NAIDuplicable *object );
void na_iduplicable_dump( const NAIDuplicable *object );
-
-NAIDuplicable *na_iduplicable_duplicate( const NAIDuplicable *object );
-
void na_iduplicable_check_edition_status( const NAIDuplicable *object );
+NAIDuplicable *na_iduplicable_duplicate( const NAIDuplicable *object );
gboolean na_iduplicable_is_modified( const NAIDuplicable *object );
gboolean na_iduplicable_is_valid( const NAIDuplicable *object );
NAIDuplicable *na_iduplicable_get_origin( const NAIDuplicable *object );
-
void na_iduplicable_set_origin( NAIDuplicable *object, const NAIDuplicable *origin );
void na_iduplicable_register_consumer( GObject *consumer );
diff --git a/src/common/na-iio-provider.c b/src/common/na-iio-provider.c
index 4e59c29..c78df49 100644
--- a/src/common/na-iio-provider.c
+++ b/src/common/na-iio-provider.c
@@ -55,7 +55,6 @@ static void interface_base_finalize( NAIIOProviderInterface *klass );
static GList *build_hierarchy( GList *tree, GSList *level_zero, gboolean list_if_empty );
static gint search_item( const NAObject *obj, const gchar *uuid );
static GList *get_merged_items_list( const NAPivot *pivot, GSList *providers );
-static void dump_hierarchy( GList *tree, gint level );
static guint try_write_item( const NAIIOProvider *instance, NAObject *item, gchar **message );
@@ -180,7 +179,7 @@ na_iio_provider_get_items_tree( const NAPivot *pivot )
hierarchy = sort_tree( pivot, hierarchy );
}
- dump_hierarchy( hierarchy, 0 );
+ na_object_dump_tree( hierarchy );
return( hierarchy );
}
@@ -280,35 +279,6 @@ get_merged_items_list( const NAPivot *pivot, GSList *providers )
return( merged );
}
-static void
-dump_hierarchy( GList *tree, gint level )
-{
- GString *prefix;
- gint i;
- GList *subitems, *it;
- gchar *id;
-
- prefix = g_string_new( "" );
- for( i = 0 ; i < level ; ++i ){
- g_string_append_printf( prefix, " " );
- }
-
- for( it = tree ; it ; it = it->next ){
- id = na_object_get_id( it->data );
- g_debug( "nact_iio_provider_dump_hierarchy: %s%p (%s) %s",
- prefix->str, ( void * ) it->data, G_OBJECT_TYPE_NAME( it->data ), id );
- g_free( id );
-
- if( NA_IS_OBJECT_ITEM( it->data )){
- subitems = na_object_get_items( it->data );
- dump_hierarchy( subitems, level+1 );
- na_object_free_items( subitems );
- }
- }
-
- g_string_free( prefix, TRUE );
-}
-
/**
* na_iio_provider_write_item:
* @pivot: the #NAPivot object which owns the list of registered I/O
@@ -331,8 +301,10 @@ na_iio_provider_write_item( const NAPivot *pivot, NAObject *item, gchar **messag
NAIIOProvider *bad_instance;
GSList *providers, *ip;
- g_debug( "%s: pivot=%p, item=%p, message=%p",
- thisfn, ( void * ) pivot, ( void * ) item, ( void * ) message );
+ g_debug( "%s: pivot=%p (%s), item=%p (%s), message=%p", thisfn,
+ ( void * ) pivot, G_OBJECT_TYPE_NAME( pivot ),
+ ( void * ) item, G_OBJECT_TYPE_NAME( item ),
+ ( void * ) message );
g_return_val_if_fail( st_initialized && !st_finalized, NA_IIO_PROVIDER_PROGRAM_ERROR );
g_return_val_if_fail(( NA_IS_PIVOT( pivot ) || !pivot ), NA_IIO_PROVIDER_PROGRAM_ERROR );
@@ -424,8 +396,10 @@ na_iio_provider_delete_item( const NAPivot *pivot, const NAObject *item, gchar *
guint ret;
NAIIOProvider *instance;
- g_debug( "%s: pivot=%p, item=%p, message=%p",
- thisfn, ( void * ) pivot, ( void * ) item, ( void * ) message );
+ g_debug( "%s: pivot=%p (%s), item=%p (%s), message=%p", thisfn,
+ ( void * ) pivot, G_OBJECT_TYPE_NAME( pivot ),
+ ( void * ) item, G_OBJECT_TYPE_NAME( item ),
+ ( void * ) message );
g_return_val_if_fail( st_initialized && !st_finalized, NA_IIO_PROVIDER_PROGRAM_ERROR );
g_return_val_if_fail( NA_IS_PIVOT( pivot ), NA_IIO_PROVIDER_PROGRAM_ERROR );
diff --git a/src/common/na-object-action.c b/src/common/na-object-action.c
index d19f7ce..e52c2c1 100644
--- a/src/common/na-object-action.c
+++ b/src/common/na-object-action.c
@@ -34,6 +34,7 @@
#include <string.h>
+#include "na-iduplicable.h"
#include "na-object-api.h"
#include "na-object-action.h"
#include "na-object-profile.h"
@@ -551,7 +552,7 @@ object_copy( NAObject *target, const NAObject *source )
* note 1: version is not localized (see configure.ac)
*
* note 2: when checking for equality of profiles, we know that NAObjectItem
- * has already checked their edition status, and assert that profiles lists
+ * has already checked their edition status, and that the two profiles lists
* were the sames ; we so only report the modification status to the action
*/
static gboolean
@@ -577,7 +578,7 @@ object_are_equal( const NAObject *a, const NAObject *b )
if( equal ){
profiles = na_object_get_items( a );
- for( ip = profiles ; ip ; ip = ip->next ){
+ for( ip = profiles ; ip && equal ; ip = ip->next ){
id = na_object_get_id( ip->data );
profile = NA_OBJECT_PROFILE( na_object_get_item( b, id ));
equal = !na_object_is_modified( profile );
@@ -593,7 +594,13 @@ object_are_equal( const NAObject *a, const NAObject *b )
na_object_free_items( profiles );
}
- /*g_debug( "na_object_action_are_equal: %s", equal ? "True":"False" );*/
+#if NA_IDUPLICABLE_EDITION_STATUS_DEBUG
+ g_debug( "na_object_action_object_are_equal: a=%p (%s), b=%p (%s), are_equal=%s",
+ ( void * ) a, G_OBJECT_TYPE_NAME( a ),
+ ( void * ) b, G_OBJECT_TYPE_NAME( b ),
+ equal ? "True":"False" );
+#endif
+
return( equal );
}
diff --git a/src/common/na-object-action.h b/src/common/na-object-action.h
index 1ecb8c8..c6c6dc7 100644
--- a/src/common/na-object-action.h
+++ b/src/common/na-object-action.h
@@ -39,7 +39,7 @@
* This is the class which maintains data and properties of an Nautilus
* action.
*
- * Note about the UUID:
+ * Note about the UUID :
*
* The uuid is only required when writing the action to GConf in order
* to ensure unicity of subdirectories.
@@ -49,6 +49,12 @@
* Note that a user may import an action, translate it and then
* reexport it : we so may have two different actions with the same
* uuid. The user has so to modify the UUID before import.
+ *
+ * Note about edition status :
+ *
+ * As a particular rule of #NAObjectItem derived class, an action is
+ * considered modified as soon as any of its profiles has been modified
+ * itself (because they are saved as a whole).
*/
#include <glib/gi18n.h>
diff --git a/src/common/na-object-api.h b/src/common/na-object-api.h
index 9a20125..29fdd3d 100644
--- a/src/common/na-object-api.h
+++ b/src/common/na-object-api.h
@@ -46,9 +46,11 @@ G_BEGIN_DECLS
/* NAObject
*/
#define na_object_dump( object ) na_object_object_dump( NA_OBJECT( object ))
+#define na_object_dump_norec( object ) na_object_object_dump_norec( NA_OBJECT( object ))
+#define na_object_dump_tree( tree ) na_object_object_dump_tree( tree )
#define na_object_get_clipboard_id( object ) na_object_object_get_clipboard_id( NA_OBJECT( object ))
#define na_object_ref( object ) na_object_object_ref( NA_OBJECT( object ))
-#define na_object_copy( target, source ) na_object_object_copy( NA_OBJECT( target ), NA_OBJECT( source ))
+#define na_object_rewind_origin( target, source ) na_object_object_rewind_origin( NA_OBJECT( target ), NA_OBJECT( source ))
/* NAIDuplicable
*/
@@ -59,7 +61,6 @@ G_BEGIN_DECLS
#define na_object_get_origin( object ) na_object_iduplicable_get_origin( NA_OBJECT( object ))
#define na_object_set_origin( object, origin ) na_object_iduplicable_set_origin( NA_OBJECT( object ), NA_OBJECT( origin ))
-#define na_object_set_origin_rec( object, origin ) na_object_iduplicable_set_origin_recurse( NA_OBJECT( object ), NA_OBJECT( origin ))
/* NAObjectId
*/
@@ -89,7 +90,7 @@ G_BEGIN_DECLS
#define na_object_set_items( object, list ) na_object_item_set_items( NA_OBJECT_ITEM( object ), list )
#define na_object_append_item( object, item ) na_object_item_append_item( NA_OBJECT_ITEM( object ), NA_OBJECT( item ))
-#define na_object_insert_item( object, item ) na_object_item_insert_item( NA_OBJECT_ITEM( object ), NA_OBJECT( item ))
+#define na_object_insert_item( object, item, before ) na_object_item_insert_item( NA_OBJECT_ITEM( object ), NA_OBJECT( item ), NA_OBJECT( before ))
#define na_object_remove_item( object, item ) na_object_item_remove_item( NA_OBJECT_ITEM( object ), NA_OBJECT( item ))
G_END_DECLS
diff --git a/src/common/na-object-fn.h b/src/common/na-object-fn.h
index fd3d580..923a9f2 100644
--- a/src/common/na-object-fn.h
+++ b/src/common/na-object-fn.h
@@ -46,28 +46,28 @@
G_BEGIN_DECLS
-/* NAObject
- */
-void na_object_object_dump( const NAObject *object );
-gchar *na_object_object_get_clipboard_id( const NAObject *object );
-NAObject *na_object_object_ref( const NAObject *object );
-void na_object_object_copy( NAObject *target, const NAObject *source );
-
-GList *na_object_get_hierarchy( const NAObject *object );
-void na_object_free_hierarchy( GList *hierarchy );
-
/* NAIDuplicable
*/
+void na_object_iduplicable_check_edition_status( const NAObject *object );
NAObject *na_object_iduplicable_duplicate( const NAObject *object );
-void na_object_iduplicable_check_edition_status( const NAObject *object );
gboolean na_object_iduplicable_are_equal( const NAObject *a, const NAObject *b );
gboolean na_object_iduplicable_is_modified( const NAObject *object );
gboolean na_object_iduplicable_is_valid( const NAObject *object );
-
NAObject *na_object_iduplicable_get_origin( const NAObject *object );
void na_object_iduplicable_set_origin( NAObject *object, const NAObject *origin );
-void na_object_iduplicable_set_origin_recurse( NAObject *object, const NAObject *origin );
+
+/* NAObject
+ */
+void na_object_object_dump( const NAObject *object );
+void na_object_object_dump_norec( const NAObject *object );
+void na_object_object_dump_tree( GList *tree );
+gchar *na_object_object_get_clipboard_id( const NAObject *object );
+NAObject *na_object_object_ref( const NAObject *object );
+void na_object_object_rewind_origin( NAObject *target, const NAObject *source );
+
+GList *na_object_get_hierarchy( const NAObject *object );
+void na_object_free_hierarchy( GList *hierarchy );
G_END_DECLS
diff --git a/src/common/na-object-id.c b/src/common/na-object-id.c
index 5793ffe..f7a896b 100644
--- a/src/common/na-object-id.c
+++ b/src/common/na-object-id.c
@@ -34,6 +34,7 @@
#include <string.h>
+#include "na-iduplicable.h"
#include "na-object-fn.h"
#include "na-object-id-class.h"
#include "na-object-id-fn.h"
@@ -432,7 +433,13 @@ object_are_equal( const NAObject *a, const NAObject *b )
}
}
- /*g_debug( "na_object_id_are_equal: %s", equal ? "True":"False" );*/
+#if NA_IDUPLICABLE_EDITION_STATUS_DEBUG
+ g_debug( "na_object_id_object_are_equal: a=%p (%s), b=%p (%s), are_equal=%s",
+ ( void * ) a, G_OBJECT_TYPE_NAME( a ),
+ ( void * ) b, G_OBJECT_TYPE_NAME( b ),
+ equal ? "True":"False" );
+#endif
+
return( equal );
}
diff --git a/src/common/na-object-item-fn.h b/src/common/na-object-item-fn.h
index 108a0dc..dc1d4cd 100644
--- a/src/common/na-object-item-fn.h
+++ b/src/common/na-object-item-fn.h
@@ -78,8 +78,8 @@ void na_object_item_set_provider( NAObjectItem *item, const NAIIOProvi
void na_object_item_set_items( NAObjectItem *item, GList *items );
void na_object_item_append_item( NAObjectItem *item, const NAObject *object );
-void na_object_item_insert_item( NAObjectItem *item, const NAObject *object );
-void na_object_item_remove_item( NAObjectItem *item, NAObject *object );
+void na_object_item_insert_item( NAObjectItem *item, const NAObject *object, const NAObject *before );
+void na_object_item_remove_item( NAObjectItem *item, const NAObject *object );
G_END_DECLS
diff --git a/src/common/na-object-item.c b/src/common/na-object-item.c
index 89880e9..fd1546e 100644
--- a/src/common/na-object-item.c
+++ b/src/common/na-object-item.c
@@ -35,6 +35,7 @@
#include <string.h>
#include <uuid/uuid.h>
+#include "na-iduplicable.h"
#include "na-object-api.h"
#include "na-object-item-class.h"
#include "na-object-item-fn.h"
@@ -562,7 +563,14 @@ na_object_item_get_items_count( const NAObjectItem *item )
void
na_object_item_free_items( GList *items )
{
- g_list_foreach( items, ( GFunc ) g_object_unref, NULL );
+ GList *it;
+
+ for( it = items ; it ; it = it->next ){
+ if( G_IS_OBJECT( it->data )){
+ g_object_unref( it->data );
+ }
+ }
+
g_list_free( items );
}
@@ -714,50 +722,60 @@ na_object_item_append_item( NAObjectItem *item, const NAObject *object )
/**
* na_object_item_insert_item:
* @item: the #NAObjectItem to which add the subitem.
- * @object: a #NAObject to be inserted at the list of subitems.
+ * @object: a #NAObject to be inserted in the list of subitems.
+ * @before: the #NAObject before which the @object should be inserted.
*
- * Inserts a new @object at the beginning of the list of subitems of
- * @item.
+ * Inserts a new @object in the list of subitems of @item.
*
* We add a reference on provided @object.
*/
void
-na_object_item_insert_item( NAObjectItem *item, const NAObject *object )
+na_object_item_insert_item( NAObjectItem *item, const NAObject *object, const NAObject *before )
{
+ GList *before_list;
+
g_return_if_fail( NA_IS_OBJECT_ITEM( item ));
g_return_if_fail( !item->private->dispose_has_run );
g_return_if_fail( NA_IS_OBJECT( object ));
+ g_return_if_fail( NA_IS_OBJECT( before ));
if( !g_list_find( item->private->items, ( gpointer ) object )){
- item->private->items = g_list_prepend( item->private->items, g_object_ref(( gpointer ) object ));
+ before_list = g_list_find( item->private->items, ( gconstpointer ) before );
+ if( before_list ){
+ item->private->items = g_list_insert_before( item->private->items, before_list, g_object_ref(( gpointer ) object ));
+ } else {
+ item->private->items = g_list_prepend( item->private->items, g_object_ref(( gpointer ) object ));
+ }
}
}
/**
* na_object_item_remove_item:
- * @item: the #NAObjectItem item from which the subitems must be removed.
- * @object: a #NAObject object to be removed from list of subitems.
+ * @item: the #NAObjectItem from which the subitem must be removed.
+ * @object: a #NAObject to be removed from the list of subitems.
*
- * Removes a subitem from the list of subitems.
+ * Removes an @object from the list of subitems of @item.
*
- * We also decrement the reference count on removed subitem.
+ * We decrement the reference count on @object.
*/
void
-na_object_item_remove_item( NAObjectItem *item, NAObject *object )
+na_object_item_remove_item( NAObjectItem *item, const NAObject *object )
{
g_return_if_fail( NA_IS_OBJECT_ITEM( item ));
g_return_if_fail( !item->private->dispose_has_run );
g_return_if_fail( NA_IS_OBJECT( object ));
- item->private->items = g_list_remove( item->private->items, ( gconstpointer ) object );
- g_object_unref( object );
+ if( g_list_find( item->private->items, ( gconstpointer ) object )){
+ item->private->items = g_list_remove( item->private->items, ( gconstpointer ) object );
+ g_object_unref(( gpointer ) object );
+ }
}
static void
object_dump( const NAObject *item )
{
static const gchar *thisfn = "na_object_item_object_dump";
- GList *it;
+ /*GList *it;*/
g_return_if_fail( NA_IS_OBJECT_ITEM( item ));
g_return_if_fail( !NA_OBJECT_ITEM( item )->private->dispose_has_run );
@@ -773,9 +791,13 @@ object_dump( const NAObject *item )
NA_OBJECT_ITEM( item )->private->items ? g_list_length( NA_OBJECT_ITEM( item )->private->items ) : 0,
( void * ) NA_OBJECT_ITEM( item )->private->items );
- for( it = NA_OBJECT_ITEM( item )->private->items ; it ; it = it->next ){
+ /* do not recurse here, as this is actually dealt with by
+ * na_object_dump() api ;
+ * else, we would have the action being dumped after its childs
+ */
+ /*for( it = NA_OBJECT_ITEM( item )->private->items ; it ; it = it->next ){
na_object_dump( it->data );
- }
+ }*/
}
static void
@@ -832,21 +854,30 @@ object_copy( NAObject *target, const NAObject *source )
*
* note 1: The provider is not considered as pertinent here
*
- * note 2: NAObjectItem recursively checks for equality in subitems.
- * Nonetheless, the modification status of subitems doesn't have any
+ * note 2: as a particular case, this function is not recursive
+ * because the equality test will stop as soon as it fails, and we so
+ * cannot be sure to even come here.
+ *
+ * The recursivity of na_object_check_edition_status() is directly
+ * dealt with by the main entry api function.
+ *
+ * More, the modification status of subitems doesn't have any
* impact on this object itself, provided that subitems lists are
* themselves identical
*
- * note 3: Only NAObjectAction is modified that one of the profiles are
- * modified (because they are saved as a whole)
+ * note 3: #NAObjectAction is considered as modified when at least one
+ * of the profiles is itself modified (because they are saved as a
+ * whole). See #NAObjectAction.
*/
static gboolean
object_are_equal( const NAObject *a, const NAObject *b )
{
gboolean equal = TRUE;
GList *it;
- NAObject *first_obj, *second_obj;
gchar *first_id, *second_id;
+ NAObject *first_obj, *second_obj;
+ gint first_pos, second_pos;
+ GList *second_list;
g_return_val_if_fail( NA_IS_OBJECT_ITEM( a ), FALSE );
g_return_val_if_fail( !NA_OBJECT_ITEM( a )->private->dispose_has_run, FALSE );
@@ -870,37 +901,49 @@ object_are_equal( const NAObject *a, const NAObject *b )
if( equal ){
for( it = NA_OBJECT_ITEM( a )->private->items ; it && equal ; it = it->next ){
- first_obj = NA_OBJECT( it->data );
- first_id = na_object_get_id( first_obj );
- second_obj = ( NAObject * ) na_object_get_item( b, first_id );
- g_free( first_id );
+ first_id = na_object_get_id( it->data );
+ second_obj = na_object_get_item( b, first_id );
if( second_obj ){
- na_object_check_edition_status( second_obj );
+ first_pos = g_list_position( NA_OBJECT_ITEM( a )->private->items, it );
+ second_list = g_list_find( NA_OBJECT_ITEM( b )->private->items, second_obj );
+ second_pos = g_list_position( NA_OBJECT_ITEM( b )->private->items, second_list );
+#if NA_IDUPLICABLE_EDITION_STATUS_DEBUG
+ g_debug( "na_object_item_object_are_equal: first_pos=%u, second_pos=%u", first_pos, second_pos );
+#endif
+ if( first_pos != second_pos ){
+ equal = FALSE;
+ }
} else {
#if NA_IDUPLICABLE_EDITION_STATUS_DEBUG
- g_debug( "na_object_item_are_equal: object=%p (%s), equal=False", ( void * ) b, G_OBJECT_TYPE_NAME( b ));
+ g_debug( "na_object_item_object_are_equal: id=%s not found in b", first_id );
#endif
equal = FALSE;
}
+ g_free( first_id );
}
}
if( equal ){
for( it = NA_OBJECT_ITEM( b )->private->items ; it && equal ; it = it->next ){
- second_obj = NA_OBJECT( it->data );
- second_id = na_object_get_id( second_obj );
- first_obj = ( NAObject * ) na_object_get_item( a, second_id );
- g_free( second_id );
+ second_id = na_object_get_id( it->data );
+ first_obj = na_object_get_item( a, second_id );
if( !first_obj ){
#if NA_IDUPLICABLE_EDITION_STATUS_DEBUG
- g_debug( "na_object_item_are_equal: object=%p (%s), equal=False", ( void * ) b, G_OBJECT_TYPE_NAME( b ));
+ g_debug( "na_object_item_object_are_equal: id=%s not found in a", second_id );
#endif
equal = FALSE;
}
+ g_free( second_id );
}
}
- /*g_debug( "na_object_item_are_equal: %s", equal ? "True":"False" );*/
+#if NA_IDUPLICABLE_EDITION_STATUS_DEBUG
+ g_debug( "na_object_item_object_are_equal: a=%p (%s), b=%p (%s), are_equal=%s",
+ ( void * ) a, G_OBJECT_TYPE_NAME( a ),
+ ( void * ) b, G_OBJECT_TYPE_NAME( b ),
+ equal ? "True":"False" );
+#endif
+
return( equal );
}
@@ -911,16 +954,16 @@ static gboolean
object_is_valid( const NAObject *object )
{
gboolean valid = TRUE;
- GList *it;
+ /*GList *it;*/
g_return_val_if_fail( NA_IS_OBJECT_ITEM( object ), FALSE );
g_return_val_if_fail( !NA_OBJECT_ITEM( object )->private->dispose_has_run, FALSE );
- if( valid ){
+ /*if( valid ){
for( it = NA_OBJECT_ITEM( object )->private->items ; it && valid ; it = it->next ){
valid = na_object_is_valid( it->data );
}
- }
+ }*/
return( valid );
}
diff --git a/src/common/na-object-menu.c b/src/common/na-object-menu.c
index 1079ae4..9999929 100644
--- a/src/common/na-object-menu.c
+++ b/src/common/na-object-menu.c
@@ -32,6 +32,7 @@
#include <config.h>
#endif
+#include "na-iduplicable.h"
#include "na-object-api.h"
#include "na-object-action.h"
#include "na-object-menu.h"
diff --git a/src/common/na-object-profile.c b/src/common/na-object-profile.c
index 60234dc..d7aacce 100644
--- a/src/common/na-object-profile.c
+++ b/src/common/na-object-profile.c
@@ -36,6 +36,7 @@
#include <libnautilus-extension/nautilus-file-info.h>
+#include "na-iduplicable.h"
#include "na-object-api.h"
#include "na-object-action.h"
#include "na-object-profile.h"
@@ -1551,6 +1552,13 @@ object_are_equal( const NAObject *a, const NAObject *b )
na_utils_string_lists_are_equal( first->private->schemes, second->private->schemes );
}
+#if NA_IDUPLICABLE_EDITION_STATUS_DEBUG
+ g_debug( "na_object_profile_object_are_equal: a=%p (%s), b=%p (%s), are_equal=%s",
+ ( void * ) a, G_OBJECT_TYPE_NAME( a ),
+ ( void * ) b, G_OBJECT_TYPE_NAME( b ),
+ equal ? "True":"False" );
+#endif
+
return( equal );
}
diff --git a/src/common/na-object.c b/src/common/na-object.c
index 165da3e..643f9eb 100644
--- a/src/common/na-object.c
+++ b/src/common/na-object.c
@@ -34,6 +34,7 @@
#include <string.h>
+#include "na-object-api.h"
#include "na-object-class.h"
#include "na-object-fn.h"
#include "na-iduplicable.h"
@@ -60,31 +61,26 @@ static void instance_constructed( GObject *object );
static void instance_dispose( GObject *object );
static void instance_finalize( GObject *object );
-static void dump_hierarchy( const NAObject *object );
-static void do_dump( const NAObject *object );
-
-static gchar *most_derived_clipboard_id( const NAObject *object );
-
-static void ref_hierarchy( const NAObject *object );
-
static NAIDuplicable *iduplicable_new( const NAIDuplicable *object );
-static NAObject *most_derived_new( const NAObject *object );
-
static void iduplicable_copy( NAIDuplicable *target, const NAIDuplicable *source );
-static void copy_hierarchy( NAObject *target, const NAObject *source );
-
static gboolean iduplicable_are_equal( const NAIDuplicable *a, const NAIDuplicable *b );
-static gboolean are_equal_hierarchy( const NAObject *a, const NAObject *b );
-static gboolean do_are_equal( const NAObject *a, const NAObject *b );
-
static gboolean iduplicable_is_valid( const NAIDuplicable *object );
-static gboolean is_valid_hierarchy( const NAObject *object );
-static gboolean do_is_valid( const NAObject *object );
-
-static void do_copy( NAObject *target, const NAObject *source );
static GList *v_get_childs( const NAObject *object );
+
+static gboolean are_equal_hierarchy( const NAObject *a, const NAObject *b );
+static void copy_hierarchy( NAObject *target, const NAObject *source );
+static gboolean do_are_equal( const NAObject *a, const NAObject *b );
+static void do_copy( NAObject *target, const NAObject *source );
+static void do_dump( const NAObject *object );
+static gboolean do_is_valid( const NAObject *object );
+static void dump_hierarchy( const NAObject *object );
+static void dump_tree( GList *tree, gint level );
+static gboolean is_valid_hierarchy( const NAObject *object );
+static gchar *most_derived_clipboard_id( const NAObject *object );
static GList *most_derived_get_childs( const NAObject *object );
+static NAObject *most_derived_new( const NAObject *object );
+static void ref_hierarchy( const NAObject *object );
GType
na_object_get_type( void )
@@ -241,246 +237,331 @@ instance_finalize( GObject *object )
}
/**
- * na_object_object_dump:
- * @object: the #NAObject-derived object to be dumped.
+ * na_object_iduplicable_check_edition_status:
+ * @object: the #NAObject object to be checked.
*
- * Dumps via g_debug the actual content of the object.
+ * Recursively checks for the edition status of @object and its childs
+ * (if any).
+ *
+ * Internally set some properties which may be requested later. This
+ * two-steps check-request let us optimize some work in the UI.
+ *
+ * na_object_check_edition_status( object )
+ * +- na_iduplicable_check_edition_status( object )
+ * +- get_origin( object )
+ * +- modified_status = v_are_equal( origin, object ) -> interface are_equal()
+ * +- valid_status = v_is_valid( object ) -> interface is_valid()
+ *
+ * Note that the recursivity is managed here, so that we can be sure
+ * that edition status of childs is actually checked.
*/
void
-na_object_object_dump( const NAObject *object )
+na_object_iduplicable_check_edition_status( const NAObject *object )
{
+ GList *childs, *ic;
+
+#if NA_IDUPLICABLE_EDITION_STATUS_DEBUG
+ g_debug( "na_object_iduplicable_check_edition_status: object=%p (%s)",
+ ( void * ) object, G_OBJECT_TYPE_NAME( object ));
+#endif
g_return_if_fail( NA_IS_OBJECT( object ));
g_return_if_fail( !object->private->dispose_has_run );
- dump_hierarchy( object );
+ childs = v_get_childs( object );
+ for( ic = childs ; ic ; ic = ic->next ){
+ na_object_iduplicable_check_edition_status( NA_OBJECT( ic->data ));
+ }
+
+ na_iduplicable_check_edition_status( NA_IDUPLICABLE( object ));
}
-static void
-dump_hierarchy( const NAObject *object )
+/**
+ * na_object_iduplicable_duplicate:
+ * @object: the #NAObject object to be dumped.
+ *
+ * Exactly duplicates a #NAObject-derived object.
+ *
+ * Returns: the new #NAObject.
+ *
+ * na_object_duplicate( origin )
+ * +- na_object_iduplicable_duplicate( origin )
+ * +- na_iduplicable_duplicate( origin )
+ * +- dup = v_new( object )
+ * | +- interface->new( object)
+ * | +- iduplicable_new( object )
+ * | +- most_derived_new( object )
+ * | +- object_new( ... ) from a derived class
+ * +- v_copy( dup, origin )
+ * | +- interface->copy( dup, origin )
+ * | +- iduplicable_copy( target, source )
+ * | +- copy_hierarchy( target, source )
+ * | +- object_copy( ... ) from each successive derived class
+ * +- set_origin( dup, origin )
+ * +- set_modified( dup, FALSE )
+ * +- set_valid( dup, FALSE )
+ *
+ * Though the interface api is not recursive per se, the implementation
+ * is ; i.e. duplicating a #NAObjectItem also duplicates the whole tree
+ * inside.
+ */
+NAObject *
+na_object_iduplicable_duplicate( const NAObject *object )
{
- GList *hierarchy, *ih;
+ NAIDuplicable *duplicate;
- hierarchy = na_object_get_hierarchy( object );
+ g_return_val_if_fail( NA_IS_OBJECT( object ), NULL );
+ g_return_val_if_fail( NA_IS_IDUPLICABLE( object ), NULL );
+ g_return_val_if_fail( !object->private->dispose_has_run, NULL );
- for( ih = hierarchy ; ih ; ih = ih->next ){
- if( NA_OBJECT_CLASS( ih->data )->dump ){
- NA_OBJECT_CLASS( ih->data )->dump( object );
- }
- }
+ duplicate = na_iduplicable_duplicate( NA_IDUPLICABLE( object ));
- na_object_free_hierarchy( hierarchy );
+ /*g_debug( "na_object_iduplicable_duplicate: object=%p (%s), duplicate=%p (%s)",
+ ( void * ) object, G_OBJECT_TYPE_NAME( object ),
+ ( void * ) duplicate, duplicate ? G_OBJECT_TYPE_NAME( duplicate ) : "" );*/
+
+ return( NA_OBJECT( duplicate ));
}
-static void
-do_dump( const NAObject *object )
+/**
+ * na_object_iduplicable_are_equal:
+ * @a: a first #NAObject object.
+ * @b: a second #NAObject object to be compared to the first one.
+ *
+ * Compares the two #NAObject objects.
+ *
+ * At least when it finds that @a and @b are equal, each derived
+ * class should call its parent class to give it an opportunity to
+ * detect a difference.
+ *
+ * Returns: %TRUE if @a and @b are identical, %FALSE else.
+ */
+gboolean
+na_object_iduplicable_are_equal( const NAObject *a, const NAObject *b )
{
- static const char *thisfn = "na_object_do_dump";
-
- g_debug( "%s: object=%p", thisfn, ( void * ) object );
+ g_return_val_if_fail( NA_IS_OBJECT( a ), FALSE );
+ g_return_val_if_fail( !a->private->dispose_has_run, FALSE );
+ g_return_val_if_fail( NA_IS_OBJECT( b ), FALSE );
+ g_return_val_if_fail( !b->private->dispose_has_run, FALSE );
- na_iduplicable_dump( NA_IDUPLICABLE( object ));
+ return( are_equal_hierarchy( a, b ));
}
/**
- * na_object_object_get_clipboard_id:
- * @object: the #NAObject-derived object for which we will get a id.
+ * na_object_iduplicable_is_modified:
+ * @object: the #NAObject object whose status is requested.
*
- * Returns: a newly allocated string which contains an id for the
- * #NAobject. This id is suitable for the internal clipboard.
+ * Returns the current modification status of @object.
*
- * The returned string should be g_free() by the caller.
+ * This suppose that @object has been previously duplicated in order
+ * to get benefits provided by the IDuplicable interface.
+ *
+ * This suppose also that the edition status of @object has previously
+ * been checked via na_object_check_edited_status().
+ *
+ * Returns: %TRUE is the provided object has been modified regarding to
+ * the original one, %FALSE else.
*/
-gchar *
-na_object_object_get_clipboard_id( const NAObject *object )
+gboolean
+na_object_iduplicable_is_modified( const NAObject *object )
{
- g_return_val_if_fail( NA_IS_OBJECT( object ), NULL );
- g_return_val_if_fail( !object->private->dispose_has_run, NULL );
+ g_return_val_if_fail( NA_IS_OBJECT( object ), FALSE );
+ g_return_val_if_fail( !object->private->dispose_has_run, FALSE );
- return( most_derived_clipboard_id( object ));
+ return( na_iduplicable_is_modified( NA_IDUPLICABLE( object )));
}
-static gchar *
-most_derived_clipboard_id( const NAObject *object )
+/**
+ * na_object_iduplicable_is_valid:
+ * @object: the #NAObject object whose validity is to be checked.
+ *
+ * Gets the validity status of @object.
+ *
+ * Returns: %TRUE is @object is valid, %FALSE else.
+ */
+gboolean
+na_object_iduplicable_is_valid( const NAObject *object )
{
- gchar *clipboard_id;
- GList *hierarchy, *ih;
- gboolean found;
-
- found = FALSE;
- clipboard_id = NULL;
- hierarchy = g_list_reverse( na_object_get_hierarchy( object ));
-
- for( ih = hierarchy ; ih && !found ; ih = ih->next ){
- if( NA_OBJECT_CLASS( ih->data )->get_clipboard_id ){
- clipboard_id = NA_OBJECT_CLASS( ih->data )->get_clipboard_id( object );
- found = TRUE;
- }
- }
-
- na_object_free_hierarchy( hierarchy );
+ g_return_val_if_fail( NA_IS_OBJECT( object ), FALSE );
+ g_return_val_if_fail( !object->private->dispose_has_run, FALSE );
- return( clipboard_id );
+ return( na_iduplicable_is_valid( NA_IDUPLICABLE( object )));
}
/**
- * TODO: get ride of this
- * na_object_object_ref:
- * @object: the #NAObject-derived object to be reffed.
+ * na_object_iduplicable_get_origin:
+ * @object: the #NAObject object whose status is requested.
*
- * Returns: a ref on the #NAobject.
+ * Returns the original object which was at the origin of @object.
*
- * If the object has childs, then it should also have reffed them.
+ * Returns: a #NAObject, or NULL.
+ *
+ * Do not use here NA_OBJECT macro as it may return a (valid) NULL value
*/
NAObject *
-na_object_object_ref( const NAObject *object )
+na_object_iduplicable_get_origin( const NAObject *object )
{
g_return_val_if_fail( NA_IS_OBJECT( object ), NULL );
g_return_val_if_fail( !object->private->dispose_has_run, NULL );
- ref_hierarchy( object );
-
- return( g_object_ref(( gpointer ) object ));
+ /*return( NA_OBJECT( na_iduplicable_get_origin( NA_IDUPLICABLE( object ))));*/
+ return(( NAObject * ) na_iduplicable_get_origin( NA_IDUPLICABLE( object )));
}
-static void
-ref_hierarchy( const NAObject *object )
+/**
+ * na_object_iduplicable_set_origin:
+ * @object: the #NAObject object whose origin is to be set.
+ * @origin: a #NAObject which will be set as the new origin of @object.
+ *
+ * Sets the new origin of @object, and of all its childs.
+ *
+ * Be warned: but recursively reinitializing the origin to NULL, this
+ * function may cause difficult to solve issues.
+ */
+void
+na_object_iduplicable_set_origin( NAObject *object, const NAObject *origin )
{
- GList *hierarchy, *ih;
+ GList *childs, *ic;
- hierarchy = na_object_get_hierarchy( object );
+ g_return_if_fail( NA_IS_OBJECT( object ));
+ g_return_if_fail( !object->private->dispose_has_run );
+ g_return_if_fail( NA_IS_OBJECT( origin ) || !origin );
+ g_return_if_fail( !origin || !origin->private->dispose_has_run );
- for( ih = hierarchy ; ih ; ih = ih->next ){
- if( NA_OBJECT_CLASS( ih->data )->ref ){
- NA_OBJECT_CLASS( ih->data )->ref( object );
- }
- }
+ na_iduplicable_set_origin( NA_IDUPLICABLE( object ), NA_IDUPLICABLE( origin ));
- na_object_free_hierarchy( hierarchy );
+ childs = v_get_childs( object );
+ for( ic = childs ; ic ; ic = ic->next ){
+ na_object_iduplicable_set_origin( NA_OBJECT( ic->data ), origin );
+ }
}
/**
- * na_object_iduplicable_duplicate:
- * @object: the #NAObject object to be dumped.
- *
- * Exactly duplicates a #NAObject-derived object.
+ * na_object_object_dump:
+ * @object: the #NAObject-derived object to be dumped.
*
- * Returns: the new #NAObject.
+ * Dumps via g_debug the actual content of the object.
*
- * na_object_duplicate( origin )
- * +- na_iduplicable_duplicate( origin )
- * | +- dup = duplicate( origin )
- * | | +- dup = v_new( object ) -> interface new()
- * | | +- v_copy( dup, origin ) -> interface copy()
- * | |
- * | +- set_origin( dup, origin )
- * | +- set_modified( dup, FALSE )
- * | +- set_valid( dup, FALSE )
- * |
- * +- na_object_check_edited_status
+ * The recursivity is dealt with here. If we let #NAObjectItem do this,
+ * the dump of #NAObjectItem-derived object will be splitted, childs
+ * being inserted inside.
*/
-NAObject *
-na_object_iduplicable_duplicate( const NAObject *object )
+void
+na_object_object_dump( const NAObject *object )
{
- NAIDuplicable *duplicate;
+ GList *childs, *ic;
- g_return_val_if_fail( NA_IS_OBJECT( object ), NULL );
- g_return_val_if_fail( NA_IS_IDUPLICABLE( object ), NULL );
- g_return_val_if_fail( !object->private->dispose_has_run, NULL );
+ g_return_if_fail( NA_IS_OBJECT( object ));
+ g_return_if_fail( !object->private->dispose_has_run );
- duplicate = na_iduplicable_duplicate( NA_IDUPLICABLE( object ));
+ na_object_object_dump_norec( object );
- /*g_debug( "na_object_iduplicable_duplicate: object is %s at %p, duplicate is %s at %p",
- G_OBJECT_TYPE_NAME( object ), ( void * ) object,
- duplicate ? G_OBJECT_TYPE_NAME( duplicate ) : "", ( void * ) duplicate );*/
+ childs = v_get_childs( object );
+ for( ic = childs ; ic ; ic = ic->next ){
+ na_object_object_dump( NA_OBJECT( ic->data ));
+ }
+}
- /*if( duplicate ){
- na_iduplicable_check_edition_status( duplicate );
- }*/
+/**
+ * na_object_object_dump_norec:
+ * @object: the #NAObject-derived object to be dumped.
+ *
+ * Dumps via g_debug the actual content of the object.
+ *
+ * This function is not recursive.
+ */
+void
+na_object_object_dump_norec( const NAObject *object )
+{
+ g_return_if_fail( NA_IS_OBJECT( object ));
+ g_return_if_fail( !object->private->dispose_has_run );
- return( NA_OBJECT( duplicate ));
+ dump_hierarchy( object );
}
-static NAIDuplicable *
-iduplicable_new( const NAIDuplicable *object )
+/**
+ * na_object_object_dump_tree:
+ * @tree: a hierarchical list of #NAObject-derived objects.
+ *
+ * Outputs a brief, hierarchical dump of the provided list.
+ */
+void
+na_object_object_dump_tree( GList *tree )
{
- g_return_val_if_fail( NA_IS_OBJECT( object ), NULL );
- g_return_val_if_fail( !NA_OBJECT( object )->private->dispose_has_run, NULL );
-
- return( NA_IDUPLICABLE( most_derived_new( NA_OBJECT( object ))));
+ dump_tree( tree, 0 );
}
-static NAObject *
-most_derived_new( const NAObject *object )
+/**
+ * na_object_object_get_clipboard_id:
+ * @object: the #NAObject-derived object for which we will get a id.
+ *
+ * Returns: a newly allocated string which contains an id for the
+ * #NAobject. This id is suitable for the internal clipboard.
+ *
+ * The returned string should be g_free() by the caller.
+ */
+gchar *
+na_object_object_get_clipboard_id( const NAObject *object )
{
- NAObject *new_object;
- GList *hierarchy, *ih;
- gboolean found;
+ g_return_val_if_fail( NA_IS_OBJECT( object ), NULL );
+ g_return_val_if_fail( !object->private->dispose_has_run, NULL );
- found = FALSE;
- new_object = NULL;
- hierarchy = g_list_reverse( na_object_get_hierarchy( object ));
+ return( most_derived_clipboard_id( object ));
+}
- for( ih = hierarchy ; ih && !found ; ih = ih->next ){
- if( NA_OBJECT_CLASS( ih->data )->new ){
- new_object = NA_OBJECT_CLASS( ih->data )->new( object );
- found = TRUE;
- }
- }
+/**
+ * TODO: get ride of this
+ * na_object_object_ref:
+ * @object: the #NAObject-derived object to be reffed.
+ *
+ * Returns: a ref on the #NAobject.
+ *
+ * If the object has childs, then it should also have reffed them.
+ */
+NAObject *
+na_object_object_ref( const NAObject *object )
+{
+ g_return_val_if_fail( NA_IS_OBJECT( object ), NULL );
+ g_return_val_if_fail( !object->private->dispose_has_run, NULL );
- na_object_free_hierarchy( hierarchy );
+ ref_hierarchy( object );
- return( new_object );
+ return( g_object_ref(( gpointer ) object ));
}
/**
- * na_object_object_copy:
- * @target: the #NAObject-derived object which will receive data.
- * @source: the #NAObject-derived object which will provide data.
+ * na_object_object_rewind_origin:
+ * @target: must be a duplication of @source.
+ * @source: a #NAObject-derived object.
+ *
+ * Recursively rewind origin between @source to @target, so that
+ * @target appear as the origin of @source.
*
- * Copies data and properties from @source to @target.
+ * The origin of @target itself is set to NULL.
+ *
+ * This only works if @target has just been duplicated from @source,
+ * and thus we do not have to check if childs lists are equal.
*/
void
-na_object_object_copy( NAObject *target, const NAObject *source )
+na_object_object_rewind_origin( NAObject *target, const NAObject *source )
{
+ GList *childs, *ic;
+ NAObject *origin;
+
g_return_if_fail( NA_IS_OBJECT( target ));
g_return_if_fail( !target->private->dispose_has_run );
g_return_if_fail( NA_IS_OBJECT( source ));
g_return_if_fail( !source->private->dispose_has_run );
- copy_hierarchy( target, source );
-}
-
-static void
-iduplicable_copy( NAIDuplicable *target, const NAIDuplicable *source )
-{
- g_return_if_fail( NA_IS_OBJECT( target ));
- g_return_if_fail( !NA_OBJECT( target )->private->dispose_has_run );
- g_return_if_fail( NA_IS_OBJECT( source ));
- g_return_if_fail( !NA_OBJECT( source )->private->dispose_has_run );
-
- copy_hierarchy( NA_OBJECT( target ), NA_OBJECT( source ));
-}
-
-static void
-copy_hierarchy( NAObject *target, const NAObject *source )
-{
- GList *hierarchy, *ih;
-
- hierarchy = na_object_get_hierarchy( source );
-
- for( ih = hierarchy ; ih ; ih = ih->next ){
- if( NA_OBJECT_CLASS( ih->data )->copy ){
- NA_OBJECT_CLASS( ih->data )->copy( target, source );
- }
+ childs = v_get_childs( target );
+ for( ic = childs ; ic ; ic = ic->next ){
+ origin = na_object_get_origin( ic->data );
+ na_object_rewind_origin( ic->data, origin );
}
- na_object_free_hierarchy( hierarchy );
-}
-
-static void
-do_copy( NAObject *target, const NAObject *source )
-{
- /* nothing to do here */
+ origin = na_object_get_origin( target );
+ g_return_if_fail( origin == source );
+ na_iduplicable_set_origin( NA_IDUPLICABLE( source ), NA_IDUPLICABLE( target ));
+ na_iduplicable_set_origin( NA_IDUPLICABLE( target ), NULL );
}
/**
@@ -516,28 +597,24 @@ na_object_free_hierarchy( GList *hierarchy )
g_list_free( hierarchy );
}
-/**
- * na_object_iduplicable_are_equal:
- * @a: a first #NAObject object.
- * @b: a second #NAObject object to be compared to the first one.
- *
- * Compares the two #NAObject objects.
- *
- * At least when it finds that @a and @b are equal, each derived
- * class should call its parent class to give it an opportunity to
- * detect a difference.
- *
- * Returns: %TRUE if @a and @b are identical, %FALSE else.
- */
-gboolean
-na_object_iduplicable_are_equal( const NAObject *a, const NAObject *b )
+static NAIDuplicable *
+iduplicable_new( const NAIDuplicable *object )
{
- g_return_val_if_fail( NA_IS_OBJECT( a ), FALSE );
- g_return_val_if_fail( !a->private->dispose_has_run, FALSE );
- g_return_val_if_fail( NA_IS_OBJECT( b ), FALSE );
- g_return_val_if_fail( !b->private->dispose_has_run, FALSE );
+ g_return_val_if_fail( NA_IS_OBJECT( object ), NULL );
+ g_return_val_if_fail( !NA_OBJECT( object )->private->dispose_has_run, NULL );
- return( are_equal_hierarchy( a, b ));
+ return( NA_IDUPLICABLE( most_derived_new( NA_OBJECT( object ))));
+}
+
+static void
+iduplicable_copy( NAIDuplicable *target, const NAIDuplicable *source )
+{
+ g_return_if_fail( NA_IS_OBJECT( target ));
+ g_return_if_fail( !NA_OBJECT( target )->private->dispose_has_run );
+ g_return_if_fail( NA_IS_OBJECT( source ));
+ g_return_if_fail( !NA_OBJECT( source )->private->dispose_has_run );
+
+ copy_hierarchy( NA_OBJECT( target ), NA_OBJECT( source ));
}
static gboolean
@@ -552,6 +629,18 @@ iduplicable_are_equal( const NAIDuplicable *a, const NAIDuplicable *b )
}
static gboolean
+iduplicable_is_valid( const NAIDuplicable *object )
+{
+ return( is_valid_hierarchy( NA_OBJECT( object )));
+}
+
+static GList *
+v_get_childs( const NAObject *object ){
+
+ return( most_derived_get_childs( object ));
+}
+
+static gboolean
are_equal_hierarchy( const NAObject *a, const NAObject *b )
{
gboolean are_equal;
@@ -571,42 +660,56 @@ are_equal_hierarchy( const NAObject *a, const NAObject *b )
return( are_equal );
}
+static void
+copy_hierarchy( NAObject *target, const NAObject *source )
+{
+ GList *hierarchy, *ih;
+
+ hierarchy = na_object_get_hierarchy( source );
+
+ for( ih = hierarchy ; ih ; ih = ih->next ){
+ if( NA_OBJECT_CLASS( ih->data )->copy ){
+ NA_OBJECT_CLASS( ih->data )->copy( target, source );
+ }
+ }
+
+ na_object_free_hierarchy( hierarchy );
+}
+
static gboolean
do_are_equal( const NAObject *a, const NAObject *b )
{
- /*g_debug( "na_object_do_are_equal: a=%s at %p, b=%s at %p",
- G_OBJECT_TYPE_NAME( a ), ( void * ) a, G_OBJECT_TYPE_NAME( b ), ( void * ) b );*/
+ gboolean are_equal;
/* as there is no data in NAObject, they are considered here as
* equal is both null or both not null
*/
- return(( a && b ) || ( !a && !b ));
+ are_equal = ( a && b ) || ( !a && !b );
+
+#if NA_IDUPLICABLE_EDITION_STATUS_DEBUG
+ g_debug( "na_object_do_are_equal: a=%p (%s), b=%p (%s), are_equal=%s",
+ ( void * ) a, G_OBJECT_TYPE_NAME( a ),
+ ( void * ) b, G_OBJECT_TYPE_NAME( b ),
+ are_equal ? "True":"False" );
+#endif
+
+ return( are_equal );
}
-static gboolean
-iduplicable_is_valid( const NAIDuplicable *object )
+static void
+do_copy( NAObject *target, const NAObject *source )
{
- return( is_valid_hierarchy( NA_OBJECT( object )));
+ /* nothing to do here */
}
-static gboolean
-is_valid_hierarchy( const NAObject *object )
+static void
+do_dump( const NAObject *object )
{
- gboolean is_valid;
- GList *hierarchy, *ih;
-
- is_valid = TRUE;
- hierarchy = na_object_get_hierarchy( object );
-
- for( ih = hierarchy ; ih && is_valid ; ih = ih->next ){
- if( NA_OBJECT_CLASS( ih->data )->is_valid ){
- is_valid = NA_OBJECT_CLASS( ih->data )->is_valid( object );
- }
- }
+ static const char *thisfn = "na_object_do_dump";
- na_object_free_hierarchy( hierarchy );
+ g_debug( "%s: object=%p (%s)", thisfn, ( void * ) object, G_OBJECT_TYPE_NAME( object ));
- return( is_valid );
+ na_iduplicable_dump( NA_IDUPLICABLE( object ));
}
static gboolean
@@ -616,142 +719,95 @@ do_is_valid( const NAObject *object )
return( object ? TRUE : FALSE );
}
-/**
- * na_object_iduplicable_check_edition_status:
- * @object: the #NAObject object to be checked.
- *
- * Recursively checks for the edition status of @object and its childs
- * (if any).
- *
- * Internally set some properties which may be requested later. This
- * two-steps check-request let us optimize some work in the UI.
- *
- * na_object_check_edition_status( object )
- * +- na_iduplicable_check_edition_status( object )
- * +- get_origin( object )
- * +- modified_status = v_are_equal( origin, object ) -> interface are_equal()
- * +- valid_status = v_is_valid( object ) -> interface is_valid()
- */
-void
-na_object_iduplicable_check_edition_status( const NAObject *object )
+static void
+dump_hierarchy( const NAObject *object )
{
- /*GList *childs, *ic;*/
+ GList *hierarchy, *ih;
- g_return_if_fail( NA_IS_OBJECT( object ));
- g_return_if_fail( !object->private->dispose_has_run );
+ hierarchy = na_object_get_hierarchy( object );
- na_iduplicable_check_edition_status( NA_IDUPLICABLE( object ));
+ for( ih = hierarchy ; ih ; ih = ih->next ){
+ if( NA_OBJECT_CLASS( ih->data )->dump ){
+ NA_OBJECT_CLASS( ih->data )->dump( object );
+ }
+ }
- /*childs = v_get_childs( object );
- for( ic = childs ; ic ; ic = ic->next ){
- na_iduplicable_check_edition_status( NA_IDUPLICABLE( ic->data ));
- }*/
+ na_object_free_hierarchy( hierarchy );
}
-/**
- * na_object_iduplicable_is_modified:
- * @object: the #NAObject object whose status is requested.
- *
- * Returns the current modification status of @object.
- *
- * This suppose that @object has been previously duplicated in order
- * to get benefits provided by the IDuplicable interface.
- *
- * This suppose also that the edition status of @object has previously
- * been checked via na_object_check_edited_status().
- *
- * Returns: %TRUE is the provided object has been modified regarding to
- * the original one, %FALSE else.
- */
-gboolean
-na_object_iduplicable_is_modified( const NAObject *object )
+static void
+dump_tree( GList *tree, gint level )
{
- g_return_val_if_fail( NA_IS_OBJECT( object ), FALSE );
- g_return_val_if_fail( !object->private->dispose_has_run, FALSE );
+ GString *prefix;
+ gint i;
+ GList *subitems, *it;
+ gchar *id;
+ gchar *label;
- return( na_iduplicable_is_modified( NA_IDUPLICABLE( object )));
-}
+ prefix = g_string_new( "" );
+ for( i = 0 ; i < level ; ++i ){
+ g_string_append_printf( prefix, " " );
+ }
-/**
- * na_object_iduplicable_is_valid:
- * @object: the #NAObject object whose validity is to be checked.
- *
- * Gets the validity status of @object.
- *
- * Returns: %TRUE is @object is valid, %FALSE else.
- */
-gboolean
-na_object_iduplicable_is_valid( const NAObject *object )
-{
- g_return_val_if_fail( NA_IS_OBJECT( object ), FALSE );
- g_return_val_if_fail( !object->private->dispose_has_run, FALSE );
+ for( it = tree ; it ; it = it->next ){
+ id = na_object_get_id( it->data );
+ label = na_object_get_label( it->data );
+ g_debug( "na_object_dump_tree: %s%p (%s) %s \"%s\"",
+ prefix->str, ( void * ) it->data, G_OBJECT_TYPE_NAME( it->data ), id, label );
+ g_free( id );
+ g_free( label );
+
+ if( NA_IS_OBJECT_ITEM( it->data )){
+ subitems = na_object_get_items( it->data );
+ dump_tree( subitems, level+1 );
+ na_object_free_items( subitems );
+ }
+ }
- return( na_iduplicable_is_valid( NA_IDUPLICABLE( object )));
+ g_string_free( prefix, TRUE );
}
-/**
- * na_object_iduplicable_get_origin:
- * @object: the #NAObject object whose status is requested.
- *
- * Returns the original object which was at the origin of @object.
- *
- * Returns: a #NAObject, or NULL.
- *
- * Do not use here NA_OBJECT macro as it may return a (valid) NULL value
- */
-NAObject *
-na_object_iduplicable_get_origin( const NAObject *object )
+static gboolean
+is_valid_hierarchy( const NAObject *object )
{
- g_return_val_if_fail( NA_IS_OBJECT( object ), NULL );
- g_return_val_if_fail( !object->private->dispose_has_run, NULL );
+ gboolean is_valid;
+ GList *hierarchy, *ih;
- /*return( NA_OBJECT( na_iduplicable_get_origin( NA_IDUPLICABLE( object ))));*/
- return(( NAObject * ) na_iduplicable_get_origin( NA_IDUPLICABLE( object )));
-}
+ is_valid = TRUE;
+ hierarchy = na_object_get_hierarchy( object );
-/**
- * na_object_iduplicable_set_origin:
- * @object: the #NAObject object whose origin is to be set.
- * @origin: a #NAObject which will be set as the new origin of @object.
- *
- * Sets the new origin of @object.
- */
-void
-na_object_iduplicable_set_origin( NAObject *object, const NAObject *origin )
-{
- g_return_if_fail( NA_IS_OBJECT( object ));
- g_return_if_fail( !object->private->dispose_has_run );
- g_return_if_fail( NA_IS_OBJECT( origin ) || !origin );
- g_return_if_fail( !origin || !origin->private->dispose_has_run );
+ for( ih = hierarchy ; ih && is_valid ; ih = ih->next ){
+ if( NA_OBJECT_CLASS( ih->data )->is_valid ){
+ is_valid = NA_OBJECT_CLASS( ih->data )->is_valid( object );
+ }
+ }
- na_iduplicable_set_origin( NA_IDUPLICABLE( object ), NA_IDUPLICABLE( origin ));
+ na_object_free_hierarchy( hierarchy );
+
+ return( is_valid );
}
-/**
- * na_object_iduplicable_set_origin_recurse:
- * @object: the #NAObject object whose origin is to be set.
- * @origin: a #NAObject which will be set as the new origin of @object.
- *
- * Sets the new origin of @object, and of all its childs if any.
- */
-void
-na_object_iduplicable_set_origin_recurse( NAObject *object, const NAObject *origin )
+static gchar *
+most_derived_clipboard_id( const NAObject *object )
{
- GList *childs, *ic;
-
- na_object_iduplicable_set_origin( object, origin );
+ gchar *clipboard_id;
+ GList *hierarchy, *ih;
+ gboolean found;
- childs = v_get_childs( object );
+ found = FALSE;
+ clipboard_id = NULL;
+ hierarchy = g_list_reverse( na_object_get_hierarchy( object ));
- for( ic = childs ; ic ; ic = ic->next ){
- na_object_iduplicable_set_origin_recurse( NA_OBJECT( ic->data ), origin );
+ for( ih = hierarchy ; ih && !found ; ih = ih->next ){
+ if( NA_OBJECT_CLASS( ih->data )->get_clipboard_id ){
+ clipboard_id = NA_OBJECT_CLASS( ih->data )->get_clipboard_id( object );
+ found = TRUE;
+ }
}
-}
-static GList *
-v_get_childs( const NAObject *object ){
+ na_object_free_hierarchy( hierarchy );
- return( most_derived_get_childs( object ));
+ return( clipboard_id );
}
static GList *
@@ -774,3 +830,42 @@ most_derived_get_childs( const NAObject *object )
return( childs );
}
+
+static NAObject *
+most_derived_new( const NAObject *object )
+{
+ NAObject *new_object;
+ GList *hierarchy, *ih;
+ gboolean found;
+
+ found = FALSE;
+ new_object = NULL;
+ hierarchy = g_list_reverse( na_object_get_hierarchy( object ));
+
+ for( ih = hierarchy ; ih && !found ; ih = ih->next ){
+ if( NA_OBJECT_CLASS( ih->data )->new ){
+ new_object = NA_OBJECT_CLASS( ih->data )->new( object );
+ found = TRUE;
+ }
+ }
+
+ na_object_free_hierarchy( hierarchy );
+
+ return( new_object );
+}
+
+static void
+ref_hierarchy( const NAObject *object )
+{
+ GList *hierarchy, *ih;
+
+ hierarchy = na_object_get_hierarchy( object );
+
+ for( ih = hierarchy ; ih ; ih = ih->next ){
+ if( NA_OBJECT_CLASS( ih->data )->ref ){
+ NA_OBJECT_CLASS( ih->data )->ref( object );
+ }
+ }
+
+ na_object_free_hierarchy( hierarchy );
+}
diff --git a/src/common/na-pivot.c b/src/common/na-pivot.c
index 8553524..88c47da 100644
--- a/src/common/na-pivot.c
+++ b/src/common/na-pivot.c
@@ -93,28 +93,30 @@ static guint st_event_source_id = 0;
static gint st_timeout_msec = 100;
static gint st_timeout_usec = 100000;
-static GType register_type( void );
-static void class_init( NAPivotClass *klass );
-static void iprefs_iface_init( NAIPrefsInterface *iface );
-static void instance_init( GTypeInstance *instance, gpointer klass );
-static void instance_dispose( GObject *object );
-static void instance_finalize( GObject *object );
+static GType register_type( void );
+static void class_init( NAPivotClass *klass );
+static void iprefs_iface_init( NAIPrefsInterface *iface );
+static void instance_init( GTypeInstance *instance, gpointer klass );
+static void instance_dispose( GObject *object );
+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( GSList *list );
+static void free_consumers( GSList *list );
/* NAIIOProvider management */
-static void register_io_providers( NAPivot *pivot );
+static void register_io_providers( NAPivot *pivot );
/* NAGConf runtime preferences management */
-static void read_runtime_preferences( NAPivot *pivot );
+static void read_runtime_preferences( NAPivot *pivot );
-static void action_changed_handler( NAPivot *pivot, gpointer user_data );
-static gboolean on_actions_changed_timeout( gpointer user_data );
-static gulong time_val_diff( const GTimeVal *recent, const GTimeVal *old );
+static void action_changed_handler( NAPivot *pivot, gpointer user_data );
+static gboolean on_actions_changed_timeout( gpointer user_data );
+static gulong time_val_diff( const GTimeVal *recent, const GTimeVal *old );
-static void on_display_order_change( NAPivot *pivot, gpointer user_data );
-static void on_display_about_change( NAPivot *pivot, gpointer user_data );
+static void on_display_order_change( NAPivot *pivot, gpointer user_data );
+static void on_display_about_change( NAPivot *pivot, gpointer user_data );
GType
na_pivot_get_type( void )
@@ -455,26 +457,6 @@ na_pivot_add_item( NAPivot *pivot, const NAObject *item )
}
/**
- * na_pivot_remove_item:
- * @pivot: this #NAPivot instance.
- * @item: the #NAObjectItem to be removed from the list.
- *
- * Removes a #NAObjectItem from the hierarchical tree.
- *
- * Note that #NAPivot also g_object_unref() the removed #NAObjectItem.
- */
-void
-na_pivot_remove_item( NAPivot *pivot, NAObject *item )
-{
- g_return_if_fail( NA_IS_PIVOT( pivot ));
- g_return_if_fail( !pivot->private->dispose_has_run );
- g_return_if_fail( NA_IS_OBJECT_ITEM( item ));
-
- pivot->private->tree = g_list_remove( pivot->private->tree, ( gconstpointer ) item );
- g_object_unref( item );
-}
-
-/**
* na_pivot_get_action:
* @pivot: this #NAPivot instance.
* @uuid: the required globally unique identifier (uuid).
@@ -488,8 +470,7 @@ na_pivot_remove_item( NAPivot *pivot, NAObject *item )
NAObject *
na_pivot_get_item( const NAPivot *pivot, const gchar *uuid )
{
- uuid_t uua, i_uub;
- GList *ia;
+ uuid_t uuid_bin;
g_return_val_if_fail( NA_IS_PIVOT( pivot ), NULL );
g_return_val_if_fail( !pivot->private->dispose_has_run, NULL );
@@ -498,64 +479,77 @@ na_pivot_get_item( const NAPivot *pivot, const gchar *uuid )
return( NULL );
}
- uuid_parse( uuid, uua );
+ uuid_parse( uuid, uuid_bin );
- for( ia = pivot->private->tree ; ia ; ia = ia->next ){
+ return( get_item_from_tree( pivot, pivot->private->tree, uuid_bin ));
+}
- gchar *i_uuid = na_object_get_id( NA_OBJECT( ia->data ));
- uuid_parse( i_uuid, i_uub );
- g_free( i_uuid );
+/**
+ * na_pivot_remove_item:
+ * @pivot: this #NAPivot instance.
+ * @item: the #NAObjectItem to be removed from the list.
+ *
+ * Removes a #NAObjectItem from the hierarchical tree.
+ *
+ * Note that #NAPivot also g_object_unref() the removed #NAObjectItem.
+ */
+void
+na_pivot_remove_item( NAPivot *pivot, NAObject *item )
+{
+ g_debug( "na_pivot_remove_item: pivot=%p, item=%p (%s)",
+ ( void * ) pivot,
+ ( void * ) item, G_OBJECT_TYPE_NAME( item ));
- if( !uuid_compare( uua, i_uub )){
- return( NA_OBJECT( ia->data ));
- }
- }
+ g_return_if_fail( NA_IS_PIVOT( pivot ));
+ g_return_if_fail( !pivot->private->dispose_has_run );
+ g_return_if_fail( NA_IS_OBJECT_ITEM( item ));
- return( NULL );
+ pivot->private->tree = g_list_remove( pivot->private->tree, ( gconstpointer ) item );
+ g_object_unref( item );
}
/**
- * na_pivot_write_item:
+ * na_pivot_delete_item:
* @pivot: this #NAPivot instance.
- * @item: a #NAObjectItem to be written by the storage subsystem.
+ * @item: the #NAObjectItem to be deleted from the storage subsystem.
* @message: the I/O provider can allocate and store here an error
* message.
*
- * Writes an item (an action or a menu).
+ * Deletes an action from the I/O storage subsystem.
*
* Returns: the #NAIIOProvider return code.
*/
guint
-na_pivot_write_item( const NAPivot *pivot, NAObject *item, gchar **message )
+na_pivot_delete_item( const NAPivot *pivot, const NAObject *item, gchar **message )
{
g_return_val_if_fail( NA_IS_PIVOT( pivot ), NA_IIO_PROVIDER_PROGRAM_ERROR );
g_return_val_if_fail( !pivot->private->dispose_has_run, NA_IIO_PROVIDER_PROGRAM_ERROR );
g_return_val_if_fail( NA_IS_OBJECT_ITEM( item ), NA_IIO_PROVIDER_PROGRAM_ERROR );
g_return_val_if_fail( message, NA_IIO_PROVIDER_PROGRAM_ERROR );
- return( na_iio_provider_write_item( pivot, item, message ));
+ return( na_iio_provider_delete_item( pivot, item, message ));
}
/**
- * na_pivot_delete_item:
+ * na_pivot_write_item:
* @pivot: this #NAPivot instance.
- * @item: the #NAObjectItem to be deleted from the storage subsystem.
+ * @item: a #NAObjectItem to be written by the storage subsystem.
* @message: the I/O provider can allocate and store here an error
* message.
*
- * Deletes an action from the I/O storage subsystem.
+ * Writes an item (an action or a menu).
*
* Returns: the #NAIIOProvider return code.
*/
guint
-na_pivot_delete_item( const NAPivot *pivot, const NAObject *item, gchar **message )
+na_pivot_write_item( const NAPivot *pivot, NAObject *item, gchar **message )
{
g_return_val_if_fail( NA_IS_PIVOT( pivot ), NA_IIO_PROVIDER_PROGRAM_ERROR );
g_return_val_if_fail( !pivot->private->dispose_has_run, NA_IIO_PROVIDER_PROGRAM_ERROR );
g_return_val_if_fail( NA_IS_OBJECT_ITEM( item ), NA_IIO_PROVIDER_PROGRAM_ERROR );
g_return_val_if_fail( message, NA_IIO_PROVIDER_PROGRAM_ERROR );
- return( na_iio_provider_delete_item( pivot, item, message ));
+ return( na_iio_provider_write_item( pivot, item, message ));
}
/**
@@ -618,6 +612,33 @@ na_pivot_set_automatic_reload( NAPivot *pivot, gboolean reload )
pivot->private->automatic_reload = reload;
}
+static NAObject *
+get_item_from_tree( const NAPivot *pivot, GList *tree, uuid_t uuid )
+{
+ uuid_t i_uuid_bin;
+ GList *subitems, *ia;
+ NAObject *found = NULL;
+
+ for( ia = tree ; ia && !found ; ia = ia->next ){
+
+ gchar *i_uuid = na_object_get_id( NA_OBJECT( ia->data ));
+ uuid_parse( i_uuid, i_uuid_bin );
+ g_free( i_uuid );
+
+ if( !uuid_compare( uuid, i_uuid_bin )){
+ found = NA_OBJECT( ia->data );
+ }
+
+ if( !found && NA_IS_OBJECT_ITEM( ia->data )){
+ subitems = na_object_get_items( ia->data );
+ found = get_item_from_tree( pivot, subitems, uuid );
+ na_object_free_items( subitems );
+ }
+ }
+
+ return( found );
+}
+
static void
free_consumers( GSList *consumers )
{
diff --git a/src/common/na-pivot.h b/src/common/na-pivot.h
index 51b7e8a..fbc9ba7 100644
--- a/src/common/na-pivot.h
+++ b/src/common/na-pivot.h
@@ -114,11 +114,11 @@ GList *na_pivot_get_items( const NAPivot *pivot );
void na_pivot_reload_items( NAPivot *pivot );
void na_pivot_add_item( NAPivot *pivot, const NAObject *item );
-void na_pivot_remove_item( NAPivot *pivot, NAObject *item );
NAObject *na_pivot_get_item( const NAPivot *pivot, const gchar *uuid );
+void na_pivot_remove_item( NAPivot *pivot, NAObject *item );
-guint na_pivot_write_item( const NAPivot *pivot, NAObject *item, gchar **message );
guint na_pivot_delete_item( const NAPivot *pivot, const NAObject *item, gchar **message );
+guint na_pivot_write_item( const NAPivot *pivot, NAObject *item, gchar **message );
void na_pivot_register_consumer( NAPivot *pivot, const NAIPivotConsumer *consumer );
diff --git a/src/nact/nact-assistant-import.c b/src/nact/nact-assistant-import.c
index c588cd9..e120263 100644
--- a/src/nact/nact-assistant-import.c
+++ b/src/nact/nact-assistant-import.c
@@ -43,6 +43,7 @@
#include "base-iprefs.h"
#include "base-application.h"
+#include "nact-iactions-list.h"
#include "nact-assistant-import.h"
#include "nact-xml-reader.h"
@@ -247,11 +248,12 @@ assist_new( BaseApplication *application )
}
/**
- * Run the assistant.
+ * nact_assistant_import_run:
+ * @main: the #NactMainWindow parent window of this assistant.
*
- * @main: the main window of the application.
+ * Run the assistant.
*/
-GSList *
+void
nact_assistant_import_run( BaseWindow *main_window )
{
BaseApplication *appli;
@@ -265,7 +267,7 @@ nact_assistant_import_run( BaseWindow *main_window )
base_window_run( BASE_WINDOW( assist ));
- return( assist->private->actions );
+ /*g_object_unref( assist );*/
}
static gchar *
@@ -433,6 +435,8 @@ assistant_apply( BaseAssistant *wnd, GtkAssistant *assistant )
GSList *uris, *is, *msg;
NAObjectAction *action;
ImportUriStruct *str;
+ GList *items;
+ BaseWindow *mainwnd;
g_debug( "%s: window=%p, assistant=%p", thisfn, ( void * ) wnd, ( void * ) assistant );
g_assert( NACT_IS_ASSISTANT_IMPORT( wnd ));
@@ -441,6 +445,8 @@ assistant_apply( BaseAssistant *wnd, GtkAssistant *assistant )
chooser = gtk_assistant_get_nth_page( assistant, ASSIST_PAGE_FILES_SELECTION );
uris = gtk_file_chooser_get_uris( GTK_FILE_CHOOSER( chooser ));
+ g_object_get( G_OBJECT( wnd ), BASE_WINDOW_PROP_PARENT, &mainwnd, NULL );
+
for( is = uris ; is ; is = is->next ){
msg = NULL;
@@ -450,10 +456,13 @@ assistant_apply( BaseAssistant *wnd, GtkAssistant *assistant )
str->uri = g_strdup(( const gchar * ) is->data );
str->action = action;
str->msg = na_utils_duplicate_string_list( msg );
+ na_utils_free_string_list( msg );
window->private->results = g_slist_prepend( window->private->results, str );
- na_utils_free_string_list( msg );
+ items = g_list_prepend( NULL, action );
+ nact_iactions_list_insert_items( NACT_IACTIONS_LIST( mainwnd ), items, NULL );
+ na_object_free_items( items );
}
na_utils_free_string_list( uris );
diff --git a/src/nact/nact-assistant-import.h b/src/nact/nact-assistant-import.h
index 0ca3572..2e679cb 100644
--- a/src/nact/nact-assistant-import.h
+++ b/src/nact/nact-assistant-import.h
@@ -62,9 +62,9 @@ typedef struct {
}
NactAssistantImportClass;
-GType nact_assistant_import_get_type( void );
+GType nact_assistant_import_get_type( void );
-GSList *nact_assistant_import_run( BaseWindow *main );
+void nact_assistant_import_run( BaseWindow *main );
G_END_DECLS
diff --git a/src/nact/nact-clipboard.c b/src/nact/nact-clipboard.c
index a52b4ac..3ba9cf3 100644
--- a/src/nact/nact-clipboard.c
+++ b/src/nact/nact-clipboard.c
@@ -277,7 +277,7 @@ nact_clipboard_primary_get( void )
for( it = data->items ; it ; it = it->next ){
obj = na_object_duplicate( it->data );
- na_object_set_origin_rec( obj, NULL );
+ na_object_set_origin( obj, NULL );
items = g_list_prepend( items, obj );
}
items = g_list_reverse( items );
diff --git a/src/nact/nact-iactions-list.c b/src/nact/nact-iactions-list.c
index f20980b..fd95d2e 100644
--- a/src/nact/nact-iactions-list.c
+++ b/src/nact/nact-iactions-list.c
@@ -95,6 +95,14 @@ typedef struct {
}
ObjectToPathIter;
+/* when iterating while searching for an object
+ */
+typedef struct {
+ NAObject *object;
+ gchar *uuid;
+}
+ IdToObjectIter;
+
/* data set against GObject
*/
#define SELECTION_CHANGED_SIGNAL_MODE "nact-iactions-list-selection-changed-signal-mode"
@@ -117,7 +125,8 @@ static void extend_selection_to_childs( NactIActionsList *instance, GtkT
static gboolean filter_selection( GtkTreeSelection *selection, GtkTreeModel *model, GtkTreePath *path, gboolean path_currently_selected, NactIActionsList *instance );
static void filter_selection_iter( GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, SelectionIter *str );
static GtkTreeView *get_actions_list_treeview( NactIActionsList *instance );
-static gboolean get_item_iter( NactTreeModel *model, GtkTreePath *path, NAObject *object, GList **items );
+static gboolean get_item_iter( NactTreeModel *model, GtkTreePath *path, NAObject *object, IdToObjectIter *ito );
+static gboolean get_items_iter( NactTreeModel *model, GtkTreePath *path, NAObject *object, GList **items );
static gboolean has_exportable_iter( NactTreeModel *model, GtkTreePath *path, NAObject *object, gboolean *has_exportable );
static gboolean has_modified_iter( NactTreeModel *model, GtkTreePath *path, NAObject *object, gboolean *has_modified );
static gboolean have_dnd_mode( NactIActionsList *instance );
@@ -481,7 +490,7 @@ nact_iactions_list_delete_selection( NactIActionsList *instance )
g_list_free( selected );
if( path ){
- /*gtk_tree_model_filter_refilter( GTK_TREE_MODEL_FILTER( model ));*/
+ gtk_tree_model_filter_refilter( GTK_TREE_MODEL_FILTER( model ));
select_row_at_path( instance, treeview, model, path );
gtk_tree_path_free( path );
}
@@ -518,6 +527,41 @@ nact_iactions_list_fill( NactIActionsList *instance, GList *items )
}
/**
+ * nact_iactions_list_get_item:
+ * @window: this #NactIActionsList instance.
+ * @uuid: the id of the searched object.
+ *
+ * Returns: a pointer on the #NAObject which has this id, or NULL.
+ *
+ * The returned pointer is owned by IActionsList (actually by the
+ * underlying tree store), and should not be released by the caller.
+ */
+NAObject *
+nact_iactions_list_get_item( NactIActionsList *instance, const gchar *uuid )
+{
+ NAObject *item = NULL;
+ GtkTreeView *treeview;
+ NactTreeModel *model;
+ IdToObjectIter *ito;
+
+ g_return_val_if_fail( NACT_IS_IACTIONS_LIST( instance ), NULL );
+
+ treeview = get_actions_list_treeview( instance );
+ model = NACT_TREE_MODEL( gtk_tree_view_get_model( treeview ));
+
+ ito = g_new0( IdToObjectIter, 1 );
+ ito->uuid = ( gchar * ) uuid;
+
+ nact_tree_model_iter( model, ( FnIterOnStore ) get_item_iter, ito );
+
+ item = ito->object;
+
+ g_free( ito );
+
+ return( item );
+}
+
+/**
* nact_iactions_list_get_items:
* @window: this #NactIActionsList instance.
*
@@ -538,7 +582,7 @@ nact_iactions_list_get_items( NactIActionsList *instance )
treeview = get_actions_list_treeview( instance );
model = NACT_TREE_MODEL( gtk_tree_view_get_model( treeview ));
- nact_tree_model_iter( model, ( FnIterOnStore ) get_item_iter, &items );
+ nact_tree_model_iter( model, ( FnIterOnStore ) get_items_iter, &items );
return( g_list_reverse( items ));
}
@@ -1115,10 +1159,31 @@ get_actions_list_treeview( NactIActionsList *instance )
}
/*
+ * search for an object, given its uuid
+ */
+static gboolean
+get_item_iter( NactTreeModel *model, GtkTreePath *path, NAObject *object, IdToObjectIter *ito )
+{
+ gchar *id;
+ gboolean found = FALSE;
+
+ id = na_object_get_id( object );
+ found = ( g_ascii_strcasecmp( id, ito->uuid ) == 0 );
+ g_free( id );
+
+ if( found ){
+ ito->object = object;
+ }
+
+ /* stop iteration if found */
+ return( found );
+}
+
+/*
* builds the tree
*/
static gboolean
-get_item_iter( NactTreeModel *model, GtkTreePath *path, NAObject *object, GList **items )
+get_items_iter( NactTreeModel *model, GtkTreePath *path, NAObject *object, GList **items )
{
if( gtk_tree_path_get_depth( path ) == 1 ){
*items = g_list_prepend( *items, object );
@@ -1328,7 +1393,7 @@ on_iactions_list_item_updated( NactIActionsList *instance, NAObject *object )
static void
on_iactions_list_item_updated_treeview( NactIActionsList *instance, NAObject *object )
{
- NAObjectAction *item;
+ NAObject *item;
GtkTreeView *treeview;
GtkTreeModel *model;
@@ -1336,12 +1401,15 @@ on_iactions_list_item_updated_treeview( NactIActionsList *instance, NAObject *ob
treeview = get_actions_list_treeview( instance );
model = gtk_tree_view_get_model( treeview );
- na_object_check_edition_status( object );
- nact_tree_model_display( NACT_TREE_MODEL( model ), object );
+ item = object;
+ if( NA_IS_OBJECT_PROFILE( object )){
+ item = NA_OBJECT( na_object_profile_get_action( NA_OBJECT_PROFILE( object )));
+ }
+ na_object_check_edition_status( item );
+
+ nact_tree_model_display( NACT_TREE_MODEL( model ), object );
if( NA_IS_OBJECT_PROFILE( object )){
- item = na_object_profile_get_action( NA_OBJECT_PROFILE( object ));
- na_object_check_edition_status( item );
nact_tree_model_display( NACT_TREE_MODEL( model ), NA_OBJECT( item ));
}
}
diff --git a/src/nact/nact-iactions-list.h b/src/nact/nact-iactions-list.h
index a05c7ec..3522f60 100644
--- a/src/nact/nact-iactions-list.h
+++ b/src/nact/nact-iactions-list.h
@@ -78,6 +78,7 @@ void nact_iactions_list_dispose( NactIActionsList *instance );
void nact_iactions_list_delete_selection( NactIActionsList *instance );
void nact_iactions_list_fill( NactIActionsList *instance, GList *items );
+NAObject *nact_iactions_list_get_item( NactIActionsList *instance, const gchar *uuid );
GList *nact_iactions_list_get_items( NactIActionsList *instance );
GList *nact_iactions_list_get_selected_items( NactIActionsList *instance );
gboolean nact_iactions_list_has_exportable( NactIActionsList *instance );
diff --git a/src/nact/nact-main-menubar.c b/src/nact/nact-main-menubar.c
index 47e715a..3fe1747 100644
--- a/src/nact/nact-main-menubar.c
+++ b/src/nact/nact-main-menubar.c
@@ -54,13 +54,28 @@
#define MENUBAR_PROP_UI_MANAGER "nact-menubar-ui-manager"
#define MENUBAR_PROP_ACTIONS_GROUP "nact-menubar-actions-group"
+/* GtkActivatable
+ * gtk_action_get_tooltip are only available starting with Gtk 2.16
+ * until this is a required level, we must have some code to do the
+ * same thing
+ */
+#undef GTK_HAS_ACTIVATABLE
+#if(( GTK_MAJOR_VERSION > 2 ) || ( GTK_MINOR_VERSION >= 16 ))
+ #define GTK_HAS_ACTIVATABLE
+#endif
+
+#ifndef GTK_HAS_ACTIVATABLE
+#define MENUBAR_PROP_ITEM_ACTION "nact-menubar-item-action"
+#endif
+
static void on_tab_updatable_selection_changed( NactMainWindow *window, gint count_selected );
static void on_new_menu_activated( GtkAction *action, NactMainWindow *window );
static void on_new_action_activated( GtkAction *action, NactMainWindow *window );
static void on_new_profile_activated( GtkAction *action, NactMainWindow *window );
static void on_save_activated( GtkAction *action, NactMainWindow *window );
-static void save_item( NAObject *object, NactMainWindow *window );
+static void save_items( NactMainWindow *window, NAPivot *pivot, GList *items );
+static void save_item( NactMainWindow *window, NAPivot *pivot, NAObjectItem *item );
static void on_quit_activated( GtkAction *action, NactMainWindow *window );
static void on_cut_activated( GtkAction *action, NactMainWindow *window );
@@ -242,12 +257,23 @@ nact_main_menubar_runtime_init( NactMainWindow *window )
/**
* nact_main_menubar_refresh_actions_sensitivity:
*
- * Sensitivity of items in the menubar is primarily refreshed when
- * "tab-updatable-selection-updated" signal is received.
- * This signal itself is sent on new selection in IActionsList.
- * E.g in "cut" action, this happens before having stored the items
- * in the clipboard.
- * We so have to refresh the menubar items on demand.
+ * Sensitivity of items (whether they are activable of not) in the
+ * menubar should be recomputed each time aaction in the user interface
+ * may lead to a change in one of the menu actions.
+ *
+ * This consists in :
+ * - when there is a change in the current selection in IActionsList
+ * (new profile, cut, copy, duplicate, delete)
+ * - when there is a change in the content of IActionsList
+ * (export)
+ * - when there is a change in the content of the clipboard
+ * (paste)
+ *
+ * Note that the same actions are also used as toolbar actions ; we so
+ * cannot rely on just recomputing the sensitivity e.g. when about to
+ * open a popup menu in the menubar. Sensitivity of the actions need
+ * to be updated as soon as the global context is changed.
+ *
*/
void
nact_main_menubar_refresh_actions_sensitivity( NactMainWindow *window )
@@ -333,30 +359,34 @@ on_new_profile_activated( GtkAction *gtk_action, NactMainWindow *window )
/*
* saving is not only saving modified items, but also saving hierarchy
* (and order if alpha order is not set)
+ *
+ * note that we only go down in the hierarchy is parent is valid and not
+ * modified (or has been successfully saved)
*/
static void
on_save_activated( GtkAction *gtk_action, NactMainWindow *window )
{
GList *items;
+ NactApplication *application;
+ NAPivot *pivot;
g_return_if_fail( GTK_IS_ACTION( gtk_action ));
g_return_if_fail( NACT_IS_MAIN_WINDOW( window ));
+ /* delete the removed actions
+ */
+ nact_main_window_remove_deleted( window );
+
items = nact_iactions_list_get_items( NACT_IACTIONS_LIST( window ));
nact_window_write_level_zero( NACT_WINDOW( window ), items );
/* recursively save the valid modified items
*/
- g_list_foreach( items, ( GFunc ) save_item, window );
-
- /* doesn't unref object owned by the tree store
- */
+ application = NACT_APPLICATION( base_window_get_application( BASE_WINDOW( window )));
+ pivot = nact_application_get_pivot( application );
+ save_items( window, pivot, items );
g_list_free( items );
- /* delete the removed actions
- */
- nact_main_window_remove_deleted( window );
-
/* required as selection has not changed
*/
nact_main_menubar_refresh_actions_sensitivity( window );
@@ -367,48 +397,61 @@ on_save_activated( GtkAction *gtk_action, NactMainWindow *window )
}
/*
+ * only recurse in menus
+ */
+static void
+save_items( NactMainWindow *window, NAPivot *pivot, GList *items )
+{
+ GList *it;
+
+ for( it = items ; it ; it = it->next ){
+ save_item( window, pivot, NA_OBJECT_ITEM( it->data ));
+ }
+}
+
+/*
* iterates here on each and every row stored in the tree
* - do not deal with profiles as they are directly managed by their
* action parent
- * - do not deal with not modified, or not valid, items
+ * - do not deal with not modified, or not valid, items, but allow
+ * for save their subitems
*/
static void
-save_item( NAObject *object, NactMainWindow *window )
+save_item( NactMainWindow *window, NAPivot *pivot, NAObjectItem *item )
{
- NactApplication *application;
- NAPivot *pivot;
NAObjectItem *origin;
NAObjectItem *dup_pivot;
+ GList *subitems;
- g_return_if_fail( NA_IS_OBJECT( object ));
g_return_if_fail( NACT_IS_MAIN_WINDOW( window ));
+ g_return_if_fail( NA_IS_PIVOT( pivot ));
+ g_return_if_fail( NA_IS_OBJECT_ITEM( item ));
- if( !NA_IS_OBJECT_PROFILE( object ) &&
- na_object_is_modified( NA_OBJECT( object )) &&
- na_object_is_valid( NA_OBJECT( object ))){
+ if( NA_IS_OBJECT_MENU( item )){
+ subitems = na_object_get_items( item );
+ save_items( window, pivot, subitems );
+ na_object_free_items( subitems );
+ }
- g_return_if_fail( NA_IS_OBJECT_ITEM( object ));
+ if( na_object_is_modified( item ) &&
+ na_object_is_valid( item )){
- if( nact_window_save_item( NACT_WINDOW( window ), NA_OBJECT_ITEM( object ))){
+ if( nact_window_save_item( NACT_WINDOW( window ), item )){
- /* do not use NA_OBJECT_ITEM macro as this may return a (valid)
- * NULL value
+ /* do not use NA_OBJECT_ITEM macro as this may return a
+ * (valid) NULL value
*/
- origin = ( NAObjectItem * ) na_object_get_origin( object );
+ origin = ( NAObjectItem * ) na_object_get_origin( item );
if( origin ){
- na_object_copy( origin, object );
-
- } else {
- application = NACT_APPLICATION( base_window_get_application( BASE_WINDOW( window )));
- pivot = nact_application_get_pivot( application );
- dup_pivot = NA_OBJECT_ITEM( na_object_duplicate( object ));
- na_object_set_origin( dup_pivot, NULL );
- na_object_set_origin( object, dup_pivot );
- na_pivot_add_item( pivot, NA_OBJECT( dup_pivot ));
+ na_pivot_remove_item( pivot, NA_OBJECT( origin ));
}
- na_object_check_edition_status( object );
+ dup_pivot = NA_OBJECT_ITEM( na_object_duplicate( item ));
+ na_object_rewind_origin( dup_pivot, item );
+ na_pivot_add_item( pivot, NA_OBJECT( dup_pivot ));
+
+ na_object_check_edition_status( item );
}
}
}
@@ -432,11 +475,10 @@ on_quit_activated( GtkAction *gtk_action, NactMainWindow *window )
/*
* cuts the visible selection
* - (tree) get new refs on selected items
- * - (tree) remove selected items, unreffing objects
* - (main) add selected items to main list of deleted,
* moving newref from list_from_tree to main_list_of_deleted
* - (menu) install in clipboard a copy of selected objects
- * - (tree) select next row (if any, or previous if any, or none)
+ * - (tree) remove selected items, unreffing objects
*/
static void
on_cut_activated( GtkAction *gtk_action, NactMainWindow *window )
@@ -485,7 +527,7 @@ on_copy_activated( GtkAction *gtk_action, NactMainWindow *window )
* and renumber its own data for allowing a new paste
* - (tree) insert new items, the tree store will ref them
* attaching each item to its parent
- * checking edition status of the topmost parent
+ * recursively checking edition status of the topmost parent
* selecting the first item at end
* - (menu) unreffing the copy got from clipboard
*/
@@ -523,7 +565,7 @@ on_duplicate_activated( GtkAction *gtk_action, NactMainWindow *window )
if( NA_IS_OBJECT_ITEM( obj )){
na_object_set_new_id( obj );
}
- na_object_set_origin_rec( obj, NULL );
+ na_object_set_origin( obj, NULL );
dup = g_list_prepend( NULL, obj );
nact_iactions_list_insert_items( NACT_IACTIONS_LIST( window ), dup, it->data );
na_object_free_items( dup );
@@ -626,27 +668,49 @@ on_delete_event( GtkWidget *toplevel, GdkEvent *event, NactMainWindow *window )
static void
on_destroy_callback( gpointer data )
{
- g_debug( "nact_main_menubar_on_destroy_callback: data=%p", ( void * ) data );
+ static const gchar *thisfn = "nact_main_menubar_on_destroy_callback";
+
+ g_debug( "%s: data=%p (%s)", thisfn,
+ ( void * ) data, G_OBJECT_TYPE_NAME( data ));
+
g_object_unref( G_OBJECT( data ));
}
+/*
+ * gtk_activatable_get_related_action() and gtk_action_get_tooltip()
+ * are only available starting with Gtk 2.16
+ */
static void
on_menu_item_selected( GtkMenuItem *proxy, NactMainWindow *window )
{
GtkAction *action;
- const gchar *tooltip;
+ gchar *tooltip;
+
+ /*g_debug( "nact_main_menubar_on_menu_item_selected: proxy=%p (%s), window=%p (%s)",
+ ( void * ) proxy, G_OBJECT_TYPE_NAME( proxy ),
+ ( void * ) window, G_OBJECT_TYPE_NAME( window ));*/
+
+ tooltip = NULL;
+#ifdef GTK_HAS_ACTIVATABLE
action = gtk_activatable_get_related_action( GTK_ACTIVATABLE( proxy ));
- if( !action ){
- return;
+ if( action ){
+ tooltip = ( gchar * ) gtk_action_get_tooltip( action );
}
+#else
+ action = GTK_ACTION( g_object_get_data( G_OBJECT( proxy ), MENUBAR_PROP_ITEM_ACTION ));
+ if( action ){
+ g_object_get( G_OBJECT( action ), "tooltip", &tooltip, NULL );
+ }
+#endif
- tooltip = gtk_action_get_tooltip( action );
- if( !tooltip ){
- return;
+ if( tooltip ){
+ nact_main_statusbar_display_status( window, MENUBAR_PROP_STATUS_CONTEXT, tooltip );
}
- nact_main_statusbar_display_status( window, MENUBAR_PROP_STATUS_CONTEXT, tooltip );
+#ifndef GTK_HAS_ACTIVATABLE
+ g_free( tooltip );
+#endif
}
static void
@@ -658,8 +722,14 @@ on_menu_item_deselected( GtkMenuItem *proxy, NactMainWindow *window )
static void
on_proxy_connect( GtkActionGroup *action_group, GtkAction *action, GtkWidget *proxy, NactMainWindow *window )
{
- g_debug( "on_proxy_connect: action_group=%p, action=%p, proxy=%p, window=%p",
- ( void * ) action_group, ( void * ) action, ( void * ) proxy, ( void * ) window );
+ static const gchar *thisfn = "nact_main_menubar_on_proxy_connect";
+
+ g_debug( "%s: action_group=%p (%s), action=%p (%s), proxy=%p (%s), window=%p (%s)",
+ thisfn,
+ ( void * ) action_group, G_OBJECT_TYPE_NAME( action_group ),
+ ( void * ) action, G_OBJECT_TYPE_NAME( action ),
+ ( void * ) proxy, G_OBJECT_TYPE_NAME( proxy ),
+ ( void * ) window, G_OBJECT_TYPE_NAME( window ));
if( GTK_IS_MENU_ITEM( proxy )){
@@ -674,6 +744,10 @@ on_proxy_connect( GtkActionGroup *action_group, GtkAction *action, GtkWidget *pr
G_OBJECT( proxy ),
"deselect",
G_CALLBACK( on_menu_item_deselected ));
+
+#ifndef GTK_HAS_ACTIVATABLE
+ g_object_set_data( G_OBJECT( proxy ), MENUBAR_PROP_ITEM_ACTION, action );
+#endif
}
}
diff --git a/src/nact/nact-main-window.c b/src/nact/nact-main-window.c
index 79749df..ea55e59 100644
--- a/src/nact/nact-main-window.c
+++ b/src/nact/nact-main-window.c
@@ -548,19 +548,21 @@ nact_main_window_new( BaseApplication *application )
gboolean
nact_main_window_action_exists( const NactMainWindow *window, const gchar *uuid )
{
- /*GSList *ia;*/
-
- g_assert( FALSE );
- /* TODO: search in current state of the tree store + in pivot */
- /*for( ia = window->private->actions ; ia ; ia = ia->next ){
- NAObjectAction *action = NA_ACTION( ia->data );
- gchar *action_uuid = na_object_action_get_uuid( action );
- gboolean ok = ( g_ascii_strcasecmp( action_uuid, uuid ) == 0 );
- g_free( action_uuid );
- if( ok ){
- return( TRUE );
- }
- }*/
+ NactApplication *application;
+ NAPivot *pivot;
+ NAObject *action;
+
+ application = NACT_APPLICATION( base_window_get_application( BASE_WINDOW( window )));
+ pivot = nact_application_get_pivot( application );
+ action = na_pivot_get_item( pivot, uuid );
+ if( action ){
+ return( TRUE );
+ }
+
+ action = nact_iactions_list_get_item( NACT_IACTIONS_LIST( window ), uuid );
+ if( action ){
+ return( TRUE );
+ }
return( FALSE );
}
@@ -654,16 +656,24 @@ nact_main_window_remove_deleted( NactMainWindow *window )
/*
* from nact_main_window_remove_deleted:
* Removes the deleted items from the underlying I/O storage subsystem.
+ *
+ * If the deleted item is a profile, then do nothing because the parent
+ * action has been marked as modified when the profile has been deleted,
+ * and thus updated in the storage subsystem as well as in the pivot
*/
static void
actually_delete_item( NactMainWindow *window, NAObject *item, NAPivot *pivot )
{
GList *items, *it;
+ NAObject *origin;
+
+ g_debug( "nact_main_window_actually_delete_item: item=%p (%s)",
+ ( void * ) item, G_OBJECT_TYPE_NAME( item ));
- g_debug( "actually_delete_item %p", ( void * ) item );
- if( nact_window_delete_item( NACT_WINDOW( window ), NA_OBJECT_ITEM( item ))){
+ if( NA_IS_OBJECT_ITEM( item )){
+ nact_window_delete_item( NACT_WINDOW( window ), NA_OBJECT_ITEM( item ));
- NAObject *origin = na_object_get_origin( item );
+ origin = na_object_get_origin( item );
if( origin ){
na_pivot_remove_item( pivot, origin );
}
diff --git a/src/nact/nact-tree-model.c b/src/nact/nact-tree-model.c
index de492bc..3ab8e5a 100644
--- a/src/nact/nact-tree-model.c
+++ b/src/nact/nact-tree-model.c
@@ -499,14 +499,14 @@ nact_tree_model_dispose( NactTreeModel *model )
void
nact_tree_model_display( NactTreeModel *model, NAObject *object )
{
- static const gchar *thisfn = "nact_tree_model_display";
+ /*static const gchar *thisfn = "nact_tree_model_display";*/
GtkTreeStore *store;
GtkTreeIter iter;
GtkTreePath *path;
- g_debug( "%s: model=%p (%s), object=%p (%s)", thisfn,
+ /*g_debug( "%s: model=%p (%s), object=%p (%s)", thisfn,
( void * ) model, G_OBJECT_TYPE_NAME( model ),
- ( void * ) object, G_OBJECT_TYPE_NAME( object ));
+ ( void * ) object, G_OBJECT_TYPE_NAME( object ));*/
store = GTK_TREE_STORE( gtk_tree_model_filter_get_model( GTK_TREE_MODEL_FILTER( model )));
@@ -792,7 +792,7 @@ insert_get_iters_menu( GtkTreeModel *model, const NAObject *select_object, GtkTr
}
/*
- * insert an action or a menu where there is no current selection
+ * insert an action or a menu when there is no current selection
* insert an action or a menu when the selection is an action
* insert a profile before a profile
*/
@@ -801,10 +801,12 @@ insert_before_get_iters( GtkTreeModel *model, GtkTreePath *select_path, const N
{
GtkTreePath *path;
GtkTreeIter iter;
+ NAObject *sibling_obj;
g_debug( "nact_tree_model_insert_before_get_iters" );
gtk_tree_model_get_iter( model, sibling_iter, select_path );
+ gtk_tree_model_get( model, sibling_iter, IACTIONS_LIST_NAOBJECT_COLUMN, &sibling_obj, -1 );
*has_sibling_iter = TRUE;
if( gtk_tree_path_get_depth( select_path ) > 1 ){
@@ -813,10 +815,12 @@ insert_before_get_iters( GtkTreeModel *model, GtkTreePath *select_path, const N
gtk_tree_model_get_iter( model, &iter, path );
gtk_tree_model_get( model, &iter, IACTIONS_LIST_NAOBJECT_COLUMN, parent_object, -1 );
g_return_if_fail( NA_IS_OBJECT_ITEM( *parent_object ));
- na_object_insert_item( *parent_object, object );
+ na_object_insert_item( *parent_object, object, sibling_obj );
g_object_unref( *parent_object );
gtk_tree_path_free( path );
}
+
+ g_object_unref( sibling_obj );
}
/*
@@ -827,12 +831,14 @@ insert_before_parent_get_iters( GtkTreeModel *model, GtkTreePath *select_path, c
{
GtkTreePath *path;
GtkTreeIter iter;
+ NAObject *sibling_obj;
g_debug( "nact_tree_model_insert_before_parent_get_iters" );
path = gtk_tree_path_copy( select_path );
gtk_tree_path_up( path );
gtk_tree_model_get_iter( model, sibling_iter, path );
+ gtk_tree_model_get( model, sibling_iter, IACTIONS_LIST_NAOBJECT_COLUMN, &sibling_obj, -1 );
*has_sibling_iter = TRUE;
if( gtk_tree_path_get_depth( path ) > 1 ){
@@ -840,10 +846,11 @@ insert_before_parent_get_iters( GtkTreeModel *model, GtkTreePath *select_path, c
gtk_tree_model_get_iter( model, &iter, path );
gtk_tree_model_get( model, &iter, IACTIONS_LIST_NAOBJECT_COLUMN, parent_object, -1 );
g_return_if_fail( NA_IS_OBJECT_ITEM( *parent_object ));
- na_object_insert_item( *parent_object, object );
+ na_object_insert_item( *parent_object, object, sibling_obj );
g_object_unref( *parent_object );
}
+ g_object_unref( sibling_obj );
gtk_tree_path_free( path );
}
@@ -861,7 +868,7 @@ insert_as_last_child_get_iters( GtkTreeModel *model, GtkTreePath *select_path, c
gtk_tree_model_get( model, parent_iter, IACTIONS_LIST_NAOBJECT_COLUMN, parent_object, -1 );
g_return_if_fail( NA_IS_OBJECT_ITEM( *parent_object ));
- na_object_insert_item( *parent_object, object );
+ na_object_append_item( *parent_object, object );
g_object_unref( *parent_object );
}
@@ -980,6 +987,7 @@ dump_store( NactTreeModel *model, GtkTreePath *path, NAObject *object, ntmDumpSt
gint depth;
gint i;
GString *prefix;
+ gchar *id, *label;
depth = gtk_tree_path_get_depth( path );
prefix = g_string_new( ntm->prefix );
@@ -987,7 +995,12 @@ dump_store( NactTreeModel *model, GtkTreePath *path, NAObject *object, ntmDumpSt
g_string_append_printf( prefix, " " );
}
- g_debug( "%s: %s%s at %p", ntm->fname, prefix->str, G_OBJECT_TYPE_NAME( object ), ( void * ) object );
+ id = na_object_get_id( object );
+ label = na_object_get_label( object );
+ g_debug( "%s: %s%s at %p \"[%s] %s\"",
+ ntm->fname, prefix->str, G_OBJECT_TYPE_NAME( object ), ( void * ) object, id, label );
+ g_free( label );
+ g_free( id );
g_string_free( prefix, TRUE );
diff --git a/src/nact/nact-window.c b/src/nact/nact-window.c
index e43b0c7..393416c 100644
--- a/src/nact/nact-window.c
+++ b/src/nact/nact-window.c
@@ -202,7 +202,8 @@ nact_window_get_pivot( NactWindow *window )
* An action is always written at once, with all its profiles.
*
* Writing a menu only involves writing its NAObjectItem properties,
- * along with the list and the order of its subitems.
+ * along with the list and the order of its subitems, but not the
+ * subitems themselves (because they may be unmodified)
*/
gboolean
nact_window_save_item( NactWindow *window, NAObjectItem *item )
@@ -212,12 +213,14 @@ nact_window_save_item( NactWindow *window, NAObjectItem *item )
gchar *msg = NULL;
guint ret;
- g_debug( "%s: window=%p, item=%p", thisfn, ( void * ) window, ( void * ) item );
+ g_debug( "%s: window=%p (%s), item=%p (%s)", thisfn,
+ ( void * ) window, G_OBJECT_TYPE_NAME( window ),
+ ( void * ) item, G_OBJECT_TYPE_NAME( item ));
pivot = nact_window_get_pivot( window );
g_assert( NA_IS_PIVOT( pivot ));
- na_object_dump( item );
+ na_object_dump_norec( item );
ret = na_pivot_write_item( pivot, NA_OBJECT( item ), &msg );
@@ -251,7 +254,7 @@ nact_window_delete_item( NactWindow *window, NAObjectItem *item )
pivot = nact_window_get_pivot( window );
g_assert( NA_IS_PIVOT( pivot ));
- na_object_dump( item );
+ na_object_dump_norec( item );
ret = na_pivot_delete_item( pivot, NA_OBJECT( item ), &msg );
diff --git a/src/nact/nautilus-actions-config-tool.ui b/src/nact/nautilus-actions-config-tool.ui
index bea6bb8..f065a22 100644
--- a/src/nact/nautilus-actions-config-tool.ui
+++ b/src/nact/nautilus-actions-config-tool.ui
@@ -1426,7 +1426,6 @@ Defining several profiles lets you have several commands, each applying with a d
<child internal-child="vbox">
<object class="GtkVBox" id="dialog-vbox1">
<property name="visible">True</property>
- <property name="orientation">vertical</property>
<property name="spacing">2</property>
<child>
<object class="GtkFrame" id="frame1">
@@ -1441,7 +1440,6 @@ Defining several profiles lets you have several commands, each applying with a d
<object class="GtkVBox" id="vbox17">
<property name="visible">True</property>
<property name="border_width">10</property>
- <property name="orientation">vertical</property>
<property name="spacing">10</property>
<child>
<object class="GtkCheckButton" id="SortAlphabeticalButton">
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]