3 * A Nautilus extension which offers configurable context menu actions.
5 * Copyright (C) 2005 The GNOME Foundation
6 * Copyright (C) 2006, 2007, 2008 Frederic Ruaudel and others (see AUTHORS)
7 * Copyright (C) 2009, 2010, 2011 Pierre Wieser and others (see AUTHORS)
9 * This Program 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 * This Program 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
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public
20 * License along with this Library; see the file COPYING. If not,
21 * write to the Free Software Foundation, Inc., 59 Temple Place,
22 * Suite 330, Boston, MA 02111-1307, USA.
25 * Frederic Ruaudel <grumz@grumz.net>
26 * Rodrigo Moya <rodrigo@gnome-db.org>
27 * Pierre Wieser <pwieser@trychlos.org>
28 * ... and many others (see AUTHORS)
31 /* We want test here what is the exact behavior of virtual functions in
32 * derived classes, whether or not base class has implemented them or
35 * We define three classes, and some virtual functions :
36 * class 'first': fn_a, fn_b, fn_c
37 * class 'second', derived from 'first', implements fn_a, fn_b
38 * class 'three', derived from 'second': implements fn_a, fn_c
40 * Public entry points are defined in class 'first': we check that calling
41 * public entry points with an object of each class actually calls the
42 * relevant virtual function.
44 * Also we check if calling the parent class is possible even if the
45 * parent class has not explicitely defined the virtual function.
47 * NOTE: this only works if we do _not_ set the virtual method to NULL
48 * in intermediate classes.
51 #include <glib-object.h>
54 #define PWI_TYPE_FIRST ( pwi_first_get_type())
55 #define PWI_FIRST( object ) ( G_TYPE_CHECK_INSTANCE_CAST( object, PWI_TYPE_FIRST, PwiFirst ))
56 #define PWI_FIRST_CLASS( klass ) ( G_TYPE_CHECK_CLASS_CAST( klass, PWI_TYPE_FIRST, PwiFirstClass ))
57 #define PWI_IS_FIRST( object ) ( G_TYPE_CHECK_INSTANCE_TYPE( object, PWI_TYPE_FIRST ))
58 #define PWI_IS_FIRST_CLASS( klass ) ( G_TYPE_CHECK_CLASS_TYPE(( klass ), PWI_TYPE_FIRST ))
59 #define PWI_FIRST_GET_CLASS( object ) ( G_TYPE_INSTANCE_GET_CLASS(( object ), PWI_TYPE_FIRST, PwiFirstClass ))
62 void *empty
; /* so that gcc -pedantic is happy */
68 PwiFirstPrivate
*private;
73 void *empty
; /* so that gcc -pedantic is happy */
79 PwiFirstClassPrivate
*private;
81 /* virtual functions */
82 void ( *fn_a
)( PwiFirst
*instance
);
83 void ( *fn_b
)( PwiFirst
*instance
);
84 void ( *fn_c
)( PwiFirst
*instance
);
88 static GObjectClass
*pwi_first_parent_class
= NULL
;
89 static GType
pwi_first_get_type( void );
90 static void pwi_first_class_init( PwiFirstClass
*klass
);
91 static void pwi_first_init( PwiFirst
*instance
, gpointer klass
);
94 pwi_first_register_type( void )
96 static const gchar
*thisfn
= "first_register_type";
98 static GTypeInfo info
= {
99 sizeof( PwiFirstClass
),
100 ( GBaseInitFunc
) NULL
,
101 ( GBaseFinalizeFunc
) NULL
,
102 ( GClassInitFunc
) pwi_first_class_init
,
107 ( GInstanceInitFunc
) pwi_first_init
110 g_debug( "%s", thisfn
);
111 return( g_type_register_static( G_TYPE_OBJECT
, "PwiFirst", &info
, 0 ));
115 pwi_first_get_type( void )
117 static GType type
= 0;
120 type
= pwi_first_register_type();
127 do_first_fn_a( PwiFirst
*instance
)
129 g_debug( "do_first_fn_a: instance=%p", ( void * ) instance
);
133 do_first_fn_b( PwiFirst
*instance
)
135 g_debug( "do_first_fn_b: instance=%p", ( void * ) instance
);
139 do_first_fn_c( PwiFirst
*instance
)
141 g_debug( "do_first_fn_c: instance=%p", ( void * ) instance
);
145 pwi_first_class_init( PwiFirstClass
*klass
)
147 static const gchar
*thisfn
= "pwi_first_class_init";
149 g_debug( "%s: klass=%p", thisfn
, ( void * ) klass
);
151 pwi_first_parent_class
= g_type_class_peek_parent( klass
);
153 klass
->private = g_new0( PwiFirstClassPrivate
, 1 );
155 klass
->fn_a
= do_first_fn_a
;
156 klass
->fn_b
= do_first_fn_b
;
157 klass
->fn_c
= do_first_fn_c
;
161 pwi_first_init( PwiFirst
*self
, gpointer klass
)
163 static const gchar
*thisfn
= "pwi_first_init";
165 g_debug( "%s: instance=%p, klass=%p", thisfn
, ( void * ) self
, ( void * ) klass
);
167 self
->private = g_new0( PwiFirstPrivate
, 1 );
170 void pwi_first_fn_a( PwiFirst
*instance
);
171 void pwi_first_fn_b( PwiFirst
*instance
);
172 void pwi_first_fn_c( PwiFirst
*instance
);
175 pwi_first_fn_a( PwiFirst
*instance
)
177 g_debug( "pwi_first_fn_a: instance=%p", ( void * ) instance
);
178 g_assert( PWI_IS_FIRST( instance
));
180 if( PWI_FIRST_GET_CLASS( instance
)->fn_a
){
181 PWI_FIRST_GET_CLASS( instance
)->fn_a( instance
);
183 g_debug( "default to invoke do_first_fn_a()" );
184 do_first_fn_a( instance
);
189 pwi_first_fn_b( PwiFirst
*instance
)
191 g_debug( "pwi_first_fn_b: instance=%p", ( void * ) instance
);
192 g_assert( PWI_IS_FIRST( instance
));
194 if( PWI_FIRST_GET_CLASS( instance
)->fn_b
){
195 PWI_FIRST_GET_CLASS( instance
)->fn_b( instance
);
197 g_debug( "default to invoke do_first_fn_b()" );
198 do_first_fn_b( instance
);
203 pwi_first_fn_c( PwiFirst
*instance
)
205 g_debug( "pwi_first_fn_c: instance=%p", ( void * ) instance
);
206 g_assert( PWI_IS_FIRST( instance
));
208 if( PWI_FIRST_GET_CLASS( instance
)->fn_c
){
209 PWI_FIRST_GET_CLASS( instance
)->fn_c( instance
);
211 g_debug( "default to invoke do_first_fn_c()" );
212 do_first_fn_c( instance
);
216 #define PWI_TYPE_SECOND ( pwi_second_get_type())
217 #define PWI_SECOND( object ) ( G_TYPE_CHECK_INSTANCE_CAST( object, PWI_TYPE_SECOND, PwiSecond ))
218 #define PWI_SECOND_CLASS( klass ) ( G_TYPE_CHECK_CLASS_CAST( klass, PWI_TYPE_SECOND, PwiSecondClass ))
219 #define PWI_IS_SECOND( object ) ( G_TYPE_CHECK_INSTANCE_TYPE( object, PWI_TYPE_SECOND ))
220 #define PWI_IS_SECOND_CLASS( klass ) ( G_TYPE_CHECK_CLASS_TYPE(( klass ), PWI_TYPE_SECOND ))
221 #define PWI_SECOND_GET_CLASS( object ) ( G_TYPE_INSTANCE_GET_CLASS(( object ), PWI_TYPE_SECOND, PwiSecondClass ))
224 void *empty
; /* so that gcc -pedantic is happy */
230 PwiSecondPrivate
*private;
235 void *empty
; /* so that gcc -pedantic is happy */
237 PwiSecondClassPrivate
;
240 PwiFirstClass parent
;
241 PwiSecondClassPrivate
*private;
245 static GObjectClass
*pwi_second_parent_class
= NULL
;
246 static GType
pwi_second_get_type( void );
247 static void pwi_second_class_init( PwiSecondClass
*klass
);
248 static void pwi_second_init( PwiSecond
*instance
, gpointer klass
);
251 pwi_second_register_type( void )
253 static const gchar
*thisfn
= "second_register_type";
255 static GTypeInfo info
= {
256 sizeof( PwiSecondClass
),
257 ( GBaseInitFunc
) NULL
,
258 ( GBaseFinalizeFunc
) NULL
,
259 ( GClassInitFunc
) pwi_second_class_init
,
264 ( GInstanceInitFunc
) pwi_second_init
267 g_debug( "%s", thisfn
);
268 return( g_type_register_static( PWI_TYPE_FIRST
, "PwiSecond", &info
, 0 ));
272 pwi_second_get_type( void )
274 static GType type
= 0;
277 type
= pwi_second_register_type();
284 do_second_fn_a( PwiFirst
*instance
)
286 g_debug( "do_second_fn_a: instance=%p", ( void * ) instance
);
287 if( PWI_FIRST_CLASS( pwi_second_parent_class
)->fn_a
){
288 PWI_FIRST_CLASS( pwi_second_parent_class
)->fn_a( instance
);
293 do_second_fn_b( PwiFirst
*instance
)
295 g_debug( "do_second_fn_b: instance=%p", ( void * ) instance
);
296 if( PWI_FIRST_CLASS( pwi_second_parent_class
)->fn_b
){
297 PWI_FIRST_CLASS( pwi_second_parent_class
)->fn_b( instance
);
302 pwi_second_class_init( PwiSecondClass
*klass
)
304 static const gchar
*thisfn
= "pwi_second_class_init";
305 PwiFirstClass
*parent_class
;
307 g_debug( "%s: klass=%p", thisfn
, ( void * ) klass
);
309 pwi_second_parent_class
= g_type_class_peek_parent( klass
);
311 klass
->private = g_new0( PwiSecondClassPrivate
, 1 );
313 parent_class
= PWI_FIRST_CLASS( klass
);
314 parent_class
->fn_a
= do_second_fn_a
;
315 parent_class
->fn_b
= do_second_fn_b
;
316 /*parent_class->fn_c = NULL;*/
320 pwi_second_init( PwiSecond
*self
, gpointer klass
)
322 static const gchar
*thisfn
= "pwi_second_init";
324 g_debug( "%s: instance=%p, klass=%p", thisfn
, ( void * ) self
, ( void * ) klass
);
326 self
->private = g_new0( PwiSecondPrivate
, 1 );
329 #define PWI_TYPE_THREE ( pwi_three_get_type())
330 #define PWI_THREE( object ) ( G_TYPE_CHECK_INSTANCE_CAST( object, PWI_TYPE_THREE, PwiThree ))
331 #define PWI_THREE_CLASS( klass ) ( G_TYPE_CHECK_CLASS_CAST( klass, PWI_TYPE_THREE, PwiThreeClass ))
332 #define PWI_IS_THREE( object ) ( G_TYPE_CHECK_INSTANCE_TYPE( object, PWI_TYPE_THREE ))
333 #define PWI_IS_THREE_CLASS( klass ) ( G_TYPE_CHECK_CLASS_TYPE(( klass ), PWI_TYPE_THREE ))
334 #define PWI_THREE_GET_CLASS( object ) ( G_TYPE_INSTANCE_GET_CLASS(( object ), PWI_TYPE_THREE, PwiThreeClass ))
337 void *empty
; /* so that gcc -pedantic is happy */
343 PwiThreePrivate
*private;
348 void *empty
; /* so that gcc -pedantic is happy */
350 PwiThreeClassPrivate
;
353 PwiSecondClass parent
;
354 PwiThreeClassPrivate
*private;
358 static GObjectClass
*pwi_three_parent_class
= NULL
;
359 static GType
pwi_three_get_type( void );
360 static void pwi_three_class_init( PwiThreeClass
*klass
);
361 static void pwi_three_init( PwiThree
*instance
, gpointer klass
);
364 pwi_three_register_type( void )
366 static const gchar
*thisfn
= "three_register_type";
368 static GTypeInfo info
= {
369 sizeof( PwiThreeClass
),
370 ( GBaseInitFunc
) NULL
,
371 ( GBaseFinalizeFunc
) NULL
,
372 ( GClassInitFunc
) pwi_three_class_init
,
377 ( GInstanceInitFunc
) pwi_three_init
380 g_debug( "%s", thisfn
);
381 return( g_type_register_static( PWI_TYPE_SECOND
, "PwiThree", &info
, 0 ));
385 pwi_three_get_type( void )
387 static GType type
= 0;
390 type
= pwi_three_register_type();
397 do_three_fn_a( PwiFirst
*instance
)
399 g_debug( "do_three_fn_a: instance=%p", ( void * ) instance
);
400 if( PWI_FIRST_CLASS( pwi_three_parent_class
)->fn_a
){
401 PWI_FIRST_CLASS( pwi_three_parent_class
)->fn_a( instance
);
406 do_three_fn_c( PwiFirst
*instance
)
408 g_debug( "do_three_fn_c: instance=%p", ( void * ) instance
);
409 if( PWI_FIRST_CLASS( pwi_three_parent_class
)->fn_c
){
410 PWI_FIRST_CLASS( pwi_three_parent_class
)->fn_c( instance
);
415 pwi_three_class_init( PwiThreeClass
*klass
)
417 static const gchar
*thisfn
= "pwi_three_class_init";
418 PwiFirstClass
*parent_class
;
420 g_debug( "%s: klass=%p", thisfn
, ( void * ) klass
);
422 pwi_three_parent_class
= g_type_class_peek_parent( klass
);
424 klass
->private = g_new0( PwiThreeClassPrivate
, 1 );
426 parent_class
= PWI_FIRST_CLASS( klass
);
427 parent_class
->fn_a
= do_three_fn_a
;
428 /*parent_class->fn_b = NULL;*/
429 parent_class
->fn_c
= do_three_fn_c
;
433 pwi_three_init( PwiThree
*self
, gpointer klass
)
435 static const gchar
*thisfn
= "pwi_three_init";
437 g_debug( "%s: instance=%p, klass=%p", thisfn
, ( void * ) self
, ( void * ) klass
);
439 self
->private = g_new0( PwiThreePrivate
, 1 );
443 main( int argc
, char **argv
)
451 a
= g_object_new( PWI_TYPE_FIRST
, NULL
);
452 b
= g_object_new( PWI_TYPE_SECOND
, NULL
);
453 c
= g_object_new( PWI_TYPE_THREE
, NULL
);
457 g_debug( "expected pwi_first_fn_a, do_first_fn_a" );
458 pwi_first_fn_a( PWI_FIRST( a
));
459 g_debug( "expected pwi_first_fn_a, do_second_fn_a, do_first_fn_a" );
460 pwi_first_fn_a( PWI_FIRST( b
));
461 g_debug( "expected pwi_first_fn_a, do_three_fn_a, do_second_fn_a, do_first_fn_a" );
462 pwi_first_fn_a( PWI_FIRST( c
));
466 g_debug( "expected pwi_first_fn_b, do_first_fn_b" );
467 pwi_first_fn_b( PWI_FIRST( a
));
468 g_debug( "expected pwi_first_fn_b, do_second_fn_b, do_first_fn_b" );
469 pwi_first_fn_b( PWI_FIRST( b
));
470 g_debug( "expected pwi_first_fn_b, do_second_fn_b, do_first_fn_b" );
472 * result is pwi_first_fn_b, default to do_first_fn_b */
473 pwi_first_fn_b( PWI_FIRST( c
));
477 g_debug( "expected pwi_first_fn_c, do_first_fn_c" );
478 pwi_first_fn_c( PWI_FIRST( a
));
479 g_debug( "expected pwi_first_fn_c, do_first_fn_c" );
480 pwi_first_fn_c( PWI_FIRST( b
));
481 g_debug( "expected pwi_first_fn_c, do_three_fn_c, do_first_fn_c" );
483 * result is pwi_first_fn_c, do_three_fn_c */
484 pwi_first_fn_c( PWI_FIRST( c
));