README: add deprecation notice
[nautilus-actions.git] / src / core / fma-iduplicable.c
blob508f0cc395352d517401003b503ca637e144784a
1 /*
2 * FileManager-Actions
3 * A file-manager extension which offers configurable context menu actions.
5 * Copyright (C) 2005 The GNOME Foundation
6 * Copyright (C) 2006-2008 Frederic Ruaudel and others (see AUTHORS)
7 * Copyright (C) 2009-2015 Pierre Wieser and others (see AUTHORS)
9 * FileManager-Actions is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License as
11 * published by the Free Software Foundation; either version 2 of
12 * the License, or (at your option) any later version.
14 * FileManager-Actions is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with FileManager-Actions; see the file COPYING. If not, see
21 * <http://www.gnu.org/licenses/>.
23 * Authors:
24 * Frederic Ruaudel <grumz@grumz.net>
25 * Rodrigo Moya <rodrigo@gnome-db.org>
26 * Pierre Wieser <pwieser@trychlos.org>
27 * ... and many others (see AUTHORS)
30 #ifdef HAVE_CONFIG_H
31 #include <config.h>
32 #endif
34 #include "api/fma-iduplicable.h"
36 /* private interface data
38 struct _FMAIDuplicableInterfacePrivate {
39 GList *consumers;
42 /* the data sructure set on each FMAIDuplicable object
44 typedef struct {
45 FMAIDuplicable *origin;
46 gboolean modified;
47 gboolean valid;
49 DuplicableStr;
51 #define FMA_IDUPLICABLE_DATA_DUPLICABLE "fma-iduplicable-data-duplicable"
53 /* signals emitted on FMAIDuplicable when a status changes
55 enum {
56 MODIFIED_CHANGED,
57 VALID_CHANGED,
58 LAST_SIGNAL
61 static FMAIDuplicableInterface *st_interface = NULL;
62 static guint st_initializations = 0;
63 static gint st_signals[ LAST_SIGNAL ] = { 0 };
65 static GType register_type( void );
66 static void interface_base_init( FMAIDuplicableInterface *klass );
67 static void interface_base_finalize( FMAIDuplicableInterface *klass );
69 static void v_copy( FMAIDuplicable *target, const FMAIDuplicable *source, guint mode );
70 static gboolean v_are_equal( const FMAIDuplicable *a, const FMAIDuplicable *b );
71 static gboolean v_is_valid( const FMAIDuplicable *object );
73 static DuplicableStr *get_duplicable_str( const FMAIDuplicable *object );
75 static void on_modified_changed_class_handler( FMAIDuplicable *instance, GObject *object, gboolean is_modified );
76 static void on_valid_changed_class_handler( FMAIDuplicable *instance, GObject *object, gboolean is_valid );
77 static void propagate_signal_to_consumers( FMAIDuplicable *instance, const gchar *signal, GObject *object, gboolean new_status );
78 static void release_signal_consumers( GList *consumers );
80 GType
81 fma_iduplicable_get_type( void )
83 static GType iface_type = 0;
85 if( !iface_type ){
86 iface_type = register_type();
89 return( iface_type );
92 static GType
93 register_type( void )
95 static const gchar *thisfn = "fma_iduplicable_register_type";
96 GType type;
98 static const GTypeInfo info = {
99 sizeof( FMAIDuplicableInterface ),
100 ( GBaseInitFunc ) interface_base_init,
101 ( GBaseFinalizeFunc ) interface_base_finalize,
102 NULL,
103 NULL,
104 NULL,
107 NULL
110 g_debug( "%s", thisfn );
112 type = g_type_register_static( G_TYPE_INTERFACE, "FMAIDuplicable", &info, 0 );
114 g_type_interface_add_prerequisite( type, G_TYPE_OBJECT );
116 return( type );
119 static void
120 interface_base_init( FMAIDuplicableInterface *klass )
122 static const gchar *thisfn = "fma_iduplicable_interface_base_init";
124 if( !st_initializations ){
126 g_debug( "%s: klass=%p", thisfn, ( void * ) klass );
128 klass->private = g_new0( FMAIDuplicableInterfacePrivate, 1 );
130 klass->private->consumers = NULL;
132 klass->copy = NULL;
133 klass->are_equal = NULL;
134 klass->is_valid = NULL;
137 * FMAIDuplicable::modified-changed:
139 * This signal is emitted by #FMAIDuplicable when the modification
140 * status of an object has been modified.
142 * The default class handler propagates the signal to registered
143 * consumers.
145 * Signal args: New modification status
147 * Handler prototype:
148 * void ( *handler )( FMAIDuplicable *duplicable, FMAObject *object, gboolean is_modified, gpointer user_data );
150 * When the signal is first emitted, thus on FMAIDuplicable, @duplicable
151 * and @object are pointers to the same address. This duplication is
152 * relevant when propagating the signal to customer, as the signal is
153 * emitted on the customer itself, while we still need the @object
154 * pointer.
156 st_signals[ MODIFIED_CHANGED ] = g_signal_new_class_handler(
157 IDUPLICABLE_SIGNAL_MODIFIED_CHANGED,
158 G_TYPE_OBJECT,
159 G_SIGNAL_RUN_CLEANUP,
160 G_CALLBACK( on_modified_changed_class_handler ),
161 NULL,
162 NULL,
163 NULL,
164 G_TYPE_NONE,
166 G_TYPE_POINTER, G_TYPE_BOOLEAN );
169 * FMAIDuplicable::valid-changed:
171 * This signal is emitted by #FMAIDuplicable when the validity
172 * status of an object has been modified.
174 * The default class handler propagates the signal to registered
175 * consumers.
177 * Signal args: New validity status
179 * Handler prototype:
180 * void ( *handler )( FMAIDuplicable *duplicable, FMAObject *object, gboolean is_valid, gpointer user_data );
182 * When the signal is first emitted, thus on FMAIDuplicable, @duplicable
183 * and @object are pointers to the same address. This duplication is
184 * relevant when propagating the signal to customer, as the signal is
185 * emitted on the customer itself, while we still need the @object
186 * pointer.
188 st_signals[ VALID_CHANGED ] = g_signal_new_class_handler(
189 IDUPLICABLE_SIGNAL_VALID_CHANGED,
190 G_TYPE_OBJECT,
191 G_SIGNAL_RUN_CLEANUP,
192 G_CALLBACK( on_valid_changed_class_handler ),
193 NULL,
194 NULL,
195 NULL,
196 G_TYPE_NONE,
198 G_TYPE_POINTER, G_TYPE_BOOLEAN );
200 st_interface = klass;
203 st_initializations += 1;
206 static void
207 interface_base_finalize( FMAIDuplicableInterface *klass )
209 static const gchar *thisfn = "fma_iduplicable_interface_base_finalize";
211 st_initializations -= 1;
213 if( !st_initializations ){
215 g_debug( "%s: klass=%p", thisfn, ( void * ) klass );
217 release_signal_consumers( klass->private->consumers );
219 g_free( klass->private );
224 * fma_iduplicable_dispose:
225 * @object: the #FMAIDuplicable object to be initialized.
227 * Releases resources.
229 * Since: 2.30
231 void
232 fma_iduplicable_dispose( const FMAIDuplicable *object )
234 DuplicableStr *str;
236 g_return_if_fail( FMA_IS_IDUPLICABLE( object ));
238 str = get_duplicable_str( object );
239 g_free( str );
240 g_object_set_data( G_OBJECT( object ), FMA_IDUPLICABLE_DATA_DUPLICABLE, NULL );
244 * fma_iduplicable_dump:
245 * @object: the #FMAIDuplicable object to be dumped.
247 * Dumps via g_debug the properties of the object.
249 * We ouput here only the data we set ourselves againt the
250 * #FMAIDuplicable -implemented object.
252 * This function should be called by the implementation when it dumps
253 * itself its own content.
255 * Since: 2.30
257 void
258 fma_iduplicable_dump( const FMAIDuplicable *object )
260 static const gchar *thisfn = "fma_iduplicable_dump";
261 DuplicableStr *str;
263 g_return_if_fail( FMA_IS_IDUPLICABLE( object ));
265 str = get_duplicable_str( object );
267 g_debug( "| %s: origin=%p", thisfn, ( void * ) str->origin );
268 g_debug( "| %s: modified=%s", thisfn, str->modified ? "True" : "False" );
269 g_debug( "| %s: valid=%s", thisfn, str->valid ? "True" : "False" );
273 * fma_iduplicable_duplicate:
274 * @object: the #FMAIDuplicable object to be duplicated.
275 * @mode: the %FMADuplicableMode duplication mode.
277 * Exactly duplicates a #FMAIDuplicable -implemented object, including
278 * modification and validity status which are copied from @object to
279 * the duplicated one.
281 * Returns: a new #FMAIDuplicable.
283 * Since: 2.30
285 FMAIDuplicable *
286 fma_iduplicable_duplicate( const FMAIDuplicable *object, guint mode )
288 static const gchar *thisfn = "fma_iduplicable_duplicate";
289 FMAIDuplicable *dup;
290 DuplicableStr *dup_str, *obj_str;
292 g_return_val_if_fail( FMA_IS_IDUPLICABLE( object ), NULL );
294 g_debug( "%s: object=%p (%s)",
295 thisfn,
296 ( void * ) object, G_OBJECT_TYPE_NAME( object ));
298 dup = g_object_new( G_OBJECT_TYPE( object ), NULL );
300 v_copy( dup, object, mode );
302 dup_str = get_duplicable_str( dup );
303 obj_str = get_duplicable_str( object );
305 dup_str->origin = ( FMAIDuplicable * ) object;
306 dup_str->modified = obj_str->modified;
307 dup_str->valid = obj_str->valid;
309 return( dup );
313 * fma_iduplicable_check_status:
314 * @object: the #FMAIDuplicable object to be checked.
316 * Checks the edition status of the #FMAIDuplicable object, and set up
317 * the corresponding properties.
319 * This function is supposed to be called each time the object may have
320 * been modified in order to set the corresponding properties. Helper
321 * functions fma_iduplicable_is_modified() and fma_iduplicable_is_valid()
322 * will then only return the current value of the properties.
324 * fma_iduplicable_check_status() is not, as itself, recursive.
325 * That is, the modification and validity status are only set on the
326 * specified object.
327 * #FMAObject implementation has chosen to handle itself the recursivity:
328 * fma_object_check_status() so first check status for children, before
329 * calling this function.
331 * Since: 2.30
333 void
334 fma_iduplicable_check_status( const FMAIDuplicable *object )
336 static const gchar *thisfn = "fma_iduplicable_check_status";
337 DuplicableStr *str;
338 gboolean was_modified, was_valid;
340 g_return_if_fail( FMA_IS_IDUPLICABLE( object ));
342 g_debug( "%s: object=%p (%s)", thisfn, ( void * ) object, G_OBJECT_TYPE_NAME( object ));
344 str = get_duplicable_str( object );
346 was_modified = str->modified;
347 was_valid = str->valid;
349 if( str->origin ){
350 g_debug( "%s: vs. origin=%p (%s)", thisfn, ( void * ) str->origin, G_OBJECT_TYPE_NAME( str->origin ));
351 g_return_if_fail( FMA_IS_IDUPLICABLE( str->origin ));
352 str->modified = !v_are_equal( str->origin, object );
354 } else {
355 str->modified = TRUE;
358 if( was_modified != str->modified ){
359 g_debug( "%s: %p (%s) status changed to modified=%s",
360 thisfn, ( void * ) object, G_OBJECT_TYPE_NAME( object ), str->modified ? "True":"False" );
361 g_signal_emit_by_name( G_OBJECT( object ), IDUPLICABLE_SIGNAL_MODIFIED_CHANGED, object, str->modified );
364 str->valid = v_is_valid( object );
366 if( was_valid != str->valid ){
367 g_debug( "%s: %p (%s) status changed to valid=%s",
368 thisfn, ( void * ) object, G_OBJECT_TYPE_NAME( object ), str->valid ? "True":"False" );
369 g_signal_emit_by_name( G_OBJECT( object ), IDUPLICABLE_SIGNAL_VALID_CHANGED, object, str->valid );
374 * fma_iduplicable_get_origin:
375 * @object: the #FMAIDuplicable object whose origin is to be returned.
377 * Returns the origin of a duplicated #FMAIDuplicable.
379 * Returns: the original #FMAIDuplicable, or NULL.
381 * Since: 2.30
383 FMAIDuplicable *
384 fma_iduplicable_get_origin( const FMAIDuplicable *object )
386 FMAIDuplicable *origin;
387 DuplicableStr *str;
389 g_return_val_if_fail( FMA_IS_IDUPLICABLE( object ), NULL );
391 str = get_duplicable_str( object );
392 origin = str->origin;
394 return( origin );
398 * fma_iduplicable_is_valid:
399 * @object: the #FMAIDuplicable object whose status is to be returned.
401 * Returns the current value of the relevant property
402 * without rechecking the edition status itself.
404 * Returns: %TRUE is the provided object is valid.
406 * Since: 2.30
408 gboolean
409 fma_iduplicable_is_valid( const FMAIDuplicable *object )
411 gboolean is_valid;
412 DuplicableStr *str;
414 g_return_val_if_fail( FMA_IS_IDUPLICABLE( object ), FALSE );
416 str = get_duplicable_str( object );
417 is_valid = str->valid;
419 return( is_valid );
423 * fma_iduplicable_is_modified:
424 * @object: the #FMAIDuplicable object whose status is to be returned.
426 * Returns the current value of the 'is_modified'
427 * property without rechecking the edition status itself.
429 * Returns: %TRUE is the provided object has been modified regarding of
430 * the original one.
432 * Since: 2.30
434 gboolean
435 fma_iduplicable_is_modified( const FMAIDuplicable *object )
437 gboolean is_modified;
438 DuplicableStr *str;
440 g_return_val_if_fail( FMA_IS_IDUPLICABLE( object ), FALSE );
442 str = get_duplicable_str( object );
443 is_modified = str->modified;
445 return( is_modified );
449 * fma_iduplicable_set_origin:
450 * @object: the #FMAIDuplicable object whose origin is to be set.
451 * @origin: the new original #FMAIDuplicable.
453 * Sets the new origin of a duplicated #FMAIDuplicable.
455 * Since: 2.30
457 void
458 fma_iduplicable_set_origin( FMAIDuplicable *object, const FMAIDuplicable *origin )
460 DuplicableStr *str;
462 g_return_if_fail( FMA_IS_IDUPLICABLE( object ));
463 g_return_if_fail( FMA_IS_IDUPLICABLE( origin ) || !origin );
465 str = get_duplicable_str( object );
466 str->origin = ( FMAIDuplicable * ) origin;
469 #ifdef FMA_ENABLE_DEPRECATED
471 * fma_iduplicable_set_modified:
472 * @object: the #FMAIDuplicable object whose modification status is to be set.
473 * @modified: the new modification status #FMAIDuplicable.
475 * Sets the new modification status of a duplicated #FMAIDuplicable.
477 * Since: 2.30
478 * Deprecated: 3.1
480 void
481 fma_iduplicable_set_modified( FMAIDuplicable *object, gboolean modified )
483 DuplicableStr *str;
485 g_return_if_fail( FMA_IS_IDUPLICABLE( object ));
487 str = get_duplicable_str( object );
488 str->modified = modified;
490 #endif /* FMA_ENABLE_DEPRECATED */
492 static void
493 v_copy( FMAIDuplicable *target, const FMAIDuplicable *source, guint mode )
495 if( FMA_IDUPLICABLE_GET_INTERFACE( target )->copy ){
496 FMA_IDUPLICABLE_GET_INTERFACE( target )->copy( target, source, mode );
500 static gboolean
501 v_are_equal( const FMAIDuplicable *a, const FMAIDuplicable *b )
503 if( FMA_IDUPLICABLE_GET_INTERFACE( a )->are_equal ){
504 return( FMA_IDUPLICABLE_GET_INTERFACE( a )->are_equal( a, b ));
507 return( TRUE );
510 static gboolean
511 v_is_valid( const FMAIDuplicable *object )
513 if( FMA_IDUPLICABLE_GET_INTERFACE( object )->is_valid ){
514 return( FMA_IDUPLICABLE_GET_INTERFACE( object )->is_valid( object ));
517 return( TRUE );
521 * fma_iduplicable_register_consumer:
522 * @consumer: the target instance.
524 * This function registers a consumer, i.e. an instance to which edition
525 * status signals will be propagated.
527 * Since: 2.30
529 void
530 fma_iduplicable_register_consumer( GObject *consumer )
532 g_return_if_fail( st_interface );
534 g_debug( "fma_iduplicable_register_consumer: consumer=%p", ( void * ) consumer );
536 st_interface->private->consumers = g_list_prepend( st_interface->private->consumers, consumer );
539 static void
540 on_modified_changed_class_handler( FMAIDuplicable *instance, GObject *object, gboolean is_modified )
542 if( FMA_IS_IDUPLICABLE( instance )){
543 propagate_signal_to_consumers( instance, IDUPLICABLE_SIGNAL_MODIFIED_CHANGED, object, is_modified );
547 static void
548 on_valid_changed_class_handler( FMAIDuplicable *instance, GObject *object, gboolean is_valid )
550 if( FMA_IS_IDUPLICABLE( instance )){
551 propagate_signal_to_consumers( instance, IDUPLICABLE_SIGNAL_VALID_CHANGED, object, is_valid );
555 static void
556 propagate_signal_to_consumers( FMAIDuplicable *instance, const gchar *signal, GObject *object, gboolean new_status )
558 static const gchar *thisfn = "fma_iduplicable_propagate_signals_to_consumers";
559 GList *ic;
561 g_return_if_fail( FMA_IS_IDUPLICABLE( instance ));
563 g_debug( "%s: instance=%p, signal=%s", thisfn, ( void * ) instance, signal );
565 for( ic = st_interface->private->consumers ; ic ; ic = ic->next ){
566 g_signal_emit_by_name( ic->data, signal, object, new_status );
570 static void
571 release_signal_consumers( GList *consumers )
573 g_list_free( consumers );
576 static DuplicableStr *
577 get_duplicable_str( const FMAIDuplicable *object )
579 DuplicableStr *str;
581 str = ( DuplicableStr * ) g_object_get_data( G_OBJECT( object ), FMA_IDUPLICABLE_DATA_DUPLICABLE );
583 if( !str ){
584 str = g_new0( DuplicableStr, 1 );
586 str->origin = NULL;
587 str->modified = FALSE;
588 str->valid = TRUE;
590 g_object_set_data( G_OBJECT( object ), FMA_IDUPLICABLE_DATA_DUPLICABLE, str );
593 return( str );