~ubuntu-branches/ubuntu/precise/nautilus-actions/precise

« back to all changes in this revision

Viewing changes to src/common/na-action.c

  • Committer: Bazaar Package Importer
  • Author(s): Christine Spang
  • Date: 2009-08-12 14:04:00 UTC
  • mfrom: (1.1.6 upstream) (3.1.4 squeeze)
  • Revision ID: james.westby@ubuntu.com-20090812140400-ufe3o3jvr62lf0sf
Tags: 1.12.0-1
* New upstream stable release.
  - Actions can now be enabled/disabled: disabled actions will
    never show up in the nautilus context menu
  - Gnome Bugzilla bugs fixed:
    - #325519 asked by Frederic Ruaudel (enabled property)
    - #590398 reported by Pierre Wieser (install doc)
    - #590399 reported by Pierre Wieser (gtk_image_menu_item_set_image)
    - #590709 reported by Claude Paroz (markup in translatable strings)
    - #590711 reported by Claude Paroz (pipe char is ambiguous to translate)
 - Do not install GConf schemas if --disable-schemas-install option has
   been specified
 - New/updated es and fr translations

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Nautilus Actions
 
3
 * A Nautilus extension which offers configurable context menu actions.
 
4
 *
 
5
 * Copyright (C) 2005 The GNOME Foundation
 
6
 * Copyright (C) 2006, 2007, 2008 Frederic Ruaudel and others (see AUTHORS)
 
7
 * Copyright (C) 2009 Pierre Wieser and others (see AUTHORS)
 
8
 *
 
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.
 
13
 *
 
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.
 
18
 *
 
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.
 
23
 *
 
24
 * Authors:
 
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)
 
29
 */
 
30
 
 
31
#ifdef HAVE_CONFIG_H
 
32
#include <config.h>
 
33
#endif
 
34
 
 
35
#include <string.h>
 
36
#include <uuid/uuid.h>
 
37
 
 
38
#include "na-action.h"
 
39
#include "na-action-profile.h"
 
40
#include "na-utils.h"
 
41
 
 
42
/* private class data
 
43
 */
 
44
struct NAActionClassPrivate {
 
45
};
 
46
 
 
47
/* private instance data
 
48
 */
 
49
struct NAActionPrivate {
 
50
        gboolean       dispose_has_run;
 
51
 
 
52
        /* action properties
 
53
         */
 
54
        gchar         *version;
 
55
        gchar         *tooltip;
 
56
        gchar         *icon;
 
57
        gboolean       enabled;
 
58
 
 
59
        /* list of action's profiles as NAActionProfile objects
 
60
         *  (thanks, Frederic ;-))
 
61
         */
 
62
        GSList        *profiles;
 
63
 
 
64
        /* dynamically set when reading the actions from the I/O storage
 
65
         * subsystem
 
66
         * defaults to FALSE unless a write has already returned an error
 
67
         */
 
68
        gboolean       read_only;
 
69
 
 
70
        /* the original provider
 
71
         * required to be able to edit/delete the action
 
72
         */
 
73
        NAIIOProvider *provider;
 
74
};
 
75
 
 
76
/* action properties
 
77
 */
 
78
enum {
 
79
        PROP_NAACTION_UUID = 1,
 
80
        PROP_NAACTION_LABEL,
 
81
        PROP_NAACTION_VERSION,
 
82
        PROP_NAACTION_TOOLTIP,
 
83
        PROP_NAACTION_ICON,
 
84
        PROP_NAACTION_ENABLED,
 
85
        PROP_NAACTION_READONLY,
 
86
        PROP_NAACTION_PROVIDER
 
87
};
 
88
 
 
89
#define PROP_NAACTION_UUID_STR                  "na-action-uuid"
 
90
#define PROP_NAACTION_LABEL_STR                 "na-action-label"
 
91
#define PROP_NAACTION_VERSION_STR               "na-action-version"
 
92
#define PROP_NAACTION_TOOLTIP_STR               "na-action-tooltip"
 
93
#define PROP_NAACTION_ICON_STR                  "na-action-icon"
 
94
#define PROP_NAACTION_ENABLED_STR               "na-action-enabled"
 
95
#define PROP_NAACTION_READONLY_STR              "na-action-read-only"
 
96
#define PROP_NAACTION_PROVIDER_STR              "na-action-provider"
 
97
 
 
98
#define NA_ACTION_LATEST_VERSION                "2.0"
 
99
 
 
100
static NAObjectClass *st_parent_class = NULL;
 
101
 
 
102
static GType     register_type( void );
 
103
static void      class_init( NAActionClass *klass );
 
104
static void      instance_init( GTypeInstance *instance, gpointer klass );
 
105
static void      instance_get_property( GObject *object, guint property_id, GValue *value, GParamSpec *spec );
 
106
static void      instance_set_property( GObject *object, guint property_id, const GValue *value, GParamSpec *spec );
 
107
static void      instance_dispose( GObject *object );
 
108
static void      instance_finalize( GObject *object );
 
109
 
 
110
static void      object_check_edited_status( const NAObject *action );
 
111
static void      object_dump( const NAObject *action );
 
112
static NAObject *object_duplicate( const NAObject *action );
 
113
static void      object_copy( NAObject *target, const NAObject *source );
 
114
static gboolean  object_are_equal( const NAObject *a, const NAObject *b );
 
115
static gboolean  object_is_valid( const NAObject *action );
 
116
 
 
117
static void      free_profiles( NAAction *action );
 
118
 
 
119
GType
 
120
na_action_get_type( void )
 
121
{
 
122
        static GType action_type = 0;
 
123
 
 
124
        if( !action_type ){
 
125
                action_type = register_type();
 
126
        }
 
127
 
 
128
        return( action_type );
 
129
}
 
130
 
 
131
static GType
 
132
register_type( void )
 
133
{
 
134
        static const gchar *thisfn = "na_action_register_type";
 
135
        g_debug( "%s", thisfn );
 
136
 
 
137
        static GTypeInfo info = {
 
138
                sizeof( NAActionClass ),
 
139
                ( GBaseInitFunc ) NULL,
 
140
                ( GBaseFinalizeFunc ) NULL,
 
141
                ( GClassInitFunc ) class_init,
 
142
                NULL,
 
143
                NULL,
 
144
                sizeof( NAAction ),
 
145
                0,
 
146
                ( GInstanceInitFunc ) instance_init
 
147
        };
 
148
 
 
149
        return( g_type_register_static( NA_OBJECT_TYPE, "NAAction", &info, 0 ));
 
150
}
 
151
 
 
152
static void
 
153
class_init( NAActionClass *klass )
 
154
{
 
155
        static const gchar *thisfn = "na_action_class_init";
 
156
        g_debug( "%s: klass=%p", thisfn, klass );
 
157
 
 
158
        st_parent_class = g_type_class_peek_parent( klass );
 
159
 
 
160
        GObjectClass *object_class = G_OBJECT_CLASS( klass );
 
161
        object_class->dispose = instance_dispose;
 
162
        object_class->finalize = instance_finalize;
 
163
        object_class->set_property = instance_set_property;
 
164
        object_class->get_property = instance_get_property;
 
165
 
 
166
        GParamSpec *spec;
 
167
        spec = g_param_spec_string(
 
168
                        PROP_NAACTION_UUID_STR,
 
169
                        "Action UUID",
 
170
                        "Globally unique identifier (UUID) of the action", "",
 
171
                        G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE );
 
172
        g_object_class_install_property( object_class, PROP_NAACTION_UUID, spec );
 
173
 
 
174
        spec = g_param_spec_string(
 
175
                        PROP_NAACTION_LABEL_STR,
 
176
                        "Action label",
 
177
                        "Context menu displayable label", "",
 
178
                        G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE );
 
179
        g_object_class_install_property( object_class, PROP_NAACTION_LABEL, spec );
 
180
 
 
181
        spec = g_param_spec_string(
 
182
                        PROP_NAACTION_VERSION_STR,
 
183
                        "Version",
 
184
                        "Version of the schema", "",
 
185
                        G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE );
 
186
        g_object_class_install_property( object_class, PROP_NAACTION_VERSION, spec );
 
187
 
 
188
        spec = g_param_spec_string(
 
189
                        PROP_NAACTION_TOOLTIP_STR,
 
190
                        "Action tooltip",
 
191
                        "Context menu tooltip", "",
 
192
                        G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE );
 
193
        g_object_class_install_property( object_class, PROP_NAACTION_TOOLTIP, spec );
 
194
 
 
195
        spec = g_param_spec_string(
 
196
                        PROP_NAACTION_ICON_STR,
 
197
                        "Icon name",
 
198
                        "Context menu displayable icon", "",
 
199
                        G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE );
 
200
        g_object_class_install_property( object_class, PROP_NAACTION_ICON, spec );
 
201
 
 
202
        spec = g_param_spec_boolean(
 
203
                        PROP_NAACTION_ENABLED_STR,
 
204
                        "Enabled",
 
205
                        "Whether this action is enabled", TRUE,
 
206
                        G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE );
 
207
        g_object_class_install_property( object_class, PROP_NAACTION_ENABLED, spec );
 
208
 
 
209
        spec = g_param_spec_boolean(
 
210
                        PROP_NAACTION_READONLY_STR,
 
211
                        "Read-only flag",
 
212
                        "Is this action only readable", FALSE,
 
213
                        G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE );
 
214
        g_object_class_install_property( object_class, PROP_NAACTION_READONLY, spec );
 
215
 
 
216
        spec = g_param_spec_pointer(
 
217
                        PROP_NAACTION_PROVIDER_STR,
 
218
                        "Original provider",
 
219
                        "Original provider",
 
220
                        G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE );
 
221
        g_object_class_install_property( object_class, PROP_NAACTION_PROVIDER, spec );
 
222
 
 
223
        klass->private = g_new0( NAActionClassPrivate, 1 );
 
224
 
 
225
        NA_OBJECT_CLASS( klass )->dump = object_dump;
 
226
        NA_OBJECT_CLASS( klass )->check_edited_status = object_check_edited_status;
 
227
        NA_OBJECT_CLASS( klass )->duplicate = object_duplicate;
 
228
        NA_OBJECT_CLASS( klass )->copy = object_copy;
 
229
        NA_OBJECT_CLASS( klass )->are_equal = object_are_equal;
 
230
        NA_OBJECT_CLASS( klass )->is_valid = object_is_valid;
 
231
}
 
232
 
 
233
static void
 
234
instance_init( GTypeInstance *instance, gpointer klass )
 
235
{
 
236
        /*static const gchar *thisfn = "na_action_instance_init";
 
237
        g_debug( "%s: instance=%p, klass=%p", thisfn, instance, klass );*/
 
238
 
 
239
        g_assert( NA_IS_ACTION( instance ));
 
240
        NAAction* self = NA_ACTION( instance );
 
241
 
 
242
        self->private = g_new0( NAActionPrivate, 1 );
 
243
 
 
244
        self->private->dispose_has_run = FALSE;
 
245
 
 
246
        /* initialize suitable default values
 
247
         */
 
248
        self->private->version = g_strdup( NA_ACTION_LATEST_VERSION );
 
249
        self->private->tooltip = g_strdup( "" );
 
250
        self->private->icon = g_strdup( "" );
 
251
        self->private->enabled = TRUE;
 
252
        self->private->read_only = FALSE;
 
253
        self->private->provider = NULL;
 
254
}
 
255
 
 
256
static void
 
257
instance_get_property( GObject *object, guint property_id, GValue *value, GParamSpec *spec )
 
258
{
 
259
        g_assert( NA_IS_ACTION( object ));
 
260
        NAAction *self = NA_ACTION( object );
 
261
 
 
262
        switch( property_id ){
 
263
                case PROP_NAACTION_UUID:
 
264
                        G_OBJECT_CLASS( st_parent_class )->get_property( object, PROP_NAOBJECT_ID, value, spec );
 
265
                        break;
 
266
 
 
267
                case PROP_NAACTION_LABEL:
 
268
                        G_OBJECT_CLASS( st_parent_class )->get_property( object, PROP_NAOBJECT_LABEL, value, spec );
 
269
                        break;
 
270
 
 
271
                case PROP_NAACTION_VERSION:
 
272
                        g_value_set_string( value, self->private->version );
 
273
                        break;
 
274
 
 
275
                case PROP_NAACTION_TOOLTIP:
 
276
                        g_value_set_string( value, self->private->tooltip );
 
277
                        break;
 
278
 
 
279
                case PROP_NAACTION_ICON:
 
280
                        g_value_set_string( value, self->private->icon );
 
281
                        break;
 
282
 
 
283
                case PROP_NAACTION_ENABLED:
 
284
                        g_value_set_boolean( value, self->private->enabled );
 
285
                        break;
 
286
 
 
287
                case PROP_NAACTION_READONLY:
 
288
                        g_value_set_boolean( value, self->private->read_only );
 
289
                        break;
 
290
 
 
291
                case PROP_NAACTION_PROVIDER:
 
292
                        g_value_set_pointer( value, self->private->provider );
 
293
                        break;
 
294
 
 
295
                default:
 
296
                        G_OBJECT_WARN_INVALID_PROPERTY_ID( object, property_id, spec );
 
297
                        break;
 
298
        }
 
299
}
 
300
 
 
301
static void
 
302
instance_set_property( GObject *object, guint property_id, const GValue *value, GParamSpec *spec )
 
303
{
 
304
        g_assert( NA_IS_ACTION( object ));
 
305
        NAAction *self = NA_ACTION( object );
 
306
 
 
307
        switch( property_id ){
 
308
                case PROP_NAACTION_UUID:
 
309
                        G_OBJECT_CLASS( st_parent_class )->set_property( object, PROP_NAOBJECT_ID, value, spec );
 
310
                        break;
 
311
 
 
312
                case PROP_NAACTION_LABEL:
 
313
                        G_OBJECT_CLASS( st_parent_class )->set_property( object, PROP_NAOBJECT_LABEL, value, spec );
 
314
                        break;
 
315
 
 
316
                case PROP_NAACTION_VERSION:
 
317
                        g_free( self->private->version );
 
318
                        self->private->version = g_value_dup_string( value );
 
319
                        break;
 
320
 
 
321
                case PROP_NAACTION_TOOLTIP:
 
322
                        g_free( self->private->tooltip );
 
323
                        self->private->tooltip = g_value_dup_string( value );
 
324
                        break;
 
325
 
 
326
                case PROP_NAACTION_ICON:
 
327
                        g_free( self->private->icon );
 
328
                        self->private->icon = g_value_dup_string( value );
 
329
                        break;
 
330
 
 
331
                case PROP_NAACTION_ENABLED:
 
332
                        self->private->enabled = g_value_get_boolean( value );
 
333
                        break;
 
334
 
 
335
                case PROP_NAACTION_READONLY:
 
336
                        self->private->read_only = g_value_get_boolean( value );
 
337
                        break;
 
338
 
 
339
                case PROP_NAACTION_PROVIDER:
 
340
                        self->private->provider = g_value_get_pointer( value );
 
341
                        break;
 
342
 
 
343
                default:
 
344
                        G_OBJECT_WARN_INVALID_PROPERTY_ID( object, property_id, spec );
 
345
                        break;
 
346
        }
 
347
}
 
348
 
 
349
static void
 
350
instance_dispose( GObject *object )
 
351
{
 
352
        static const gchar *thisfn = "na_action_instance_dispose";
 
353
        g_debug( "%s: object=%p", thisfn, object );
 
354
 
 
355
        g_assert( NA_IS_ACTION( object ));
 
356
        NAAction *self = NA_ACTION( object );
 
357
 
 
358
        if( !self->private->dispose_has_run ){
 
359
 
 
360
                self->private->dispose_has_run = TRUE;
 
361
 
 
362
                /* release the profiles */
 
363
                free_profiles( self );
 
364
 
 
365
                /* chain up to the parent class */
 
366
                G_OBJECT_CLASS( st_parent_class )->dispose( object );
 
367
        }
 
368
}
 
369
 
 
370
static void
 
371
instance_finalize( GObject *object )
 
372
{
 
373
        static const gchar *thisfn = "na_action_instance_finalize";
 
374
        g_debug( "%s: object=%p", thisfn, object );
 
375
 
 
376
        g_assert( NA_IS_ACTION( object ));
 
377
        NAAction *self = ( NAAction * ) object;
 
378
 
 
379
        g_free( self->private->version );
 
380
        g_free( self->private->tooltip );
 
381
        g_free( self->private->icon );
 
382
 
 
383
        g_free( self->private );
 
384
 
 
385
        /* chain call to parent class */
 
386
        if((( GObjectClass * ) st_parent_class )->finalize ){
 
387
                G_OBJECT_CLASS( st_parent_class )->finalize( object );
 
388
        }
 
389
}
 
390
 
 
391
/**
 
392
 * na_action_new:
 
393
 *
 
394
 * Allocates a new #NAAction object.
 
395
 *
 
396
 * The new #NAAction object is initialized with suitable default values,
 
397
 * but without any profile.
 
398
 *
 
399
 * Returns: the newly allocated #NAAction object.
 
400
 */
 
401
NAAction *
 
402
na_action_new( void )
 
403
{
 
404
        NAAction *action = g_object_new( NA_ACTION_TYPE, NULL );
 
405
 
 
406
        na_action_set_new_uuid( action );
 
407
 
 
408
        /* i18n: default label for a new action */
 
409
        na_action_set_label( action, NA_ACTION_DEFAULT_LABEL );
 
410
 
 
411
        return( action );
 
412
}
 
413
 
 
414
/**
 
415
 * na_action_new_with_profile:
 
416
 *
 
417
 * Allocates a new #NAAction object along with a default profile.
 
418
 *
 
419
 * Return: the newly allocated #NAAction action.
 
420
 */
 
421
NAAction *
 
422
na_action_new_with_profile( void )
 
423
{
 
424
        NAAction *action = na_action_new();
 
425
 
 
426
        NAActionProfile *profile = na_action_profile_new();
 
427
 
 
428
        na_action_attach_profile( action, profile );
 
429
 
 
430
        return( action );
 
431
}
 
432
 
 
433
/**
 
434
 * na_action_get_uuid:
 
435
 * @action: the #NAAction object to be requested.
 
436
 *
 
437
 * Returns the globally unique identifier (UUID) of the action.
 
438
 *
 
439
 * Returns: the uuid of the action as a newly allocated string. This
 
440
 * returned string must be g_free() by the caller.
 
441
 *
 
442
 * See na_action_set_uuid() for some rationale about uuid.
 
443
 */
 
444
gchar *
 
445
na_action_get_uuid( const NAAction *action )
 
446
{
 
447
        g_assert( NA_IS_ACTION( action ));
 
448
 
 
449
        gchar *id;
 
450
        g_object_get( G_OBJECT( action ), PROP_NAACTION_UUID_STR, &id, NULL );
 
451
 
 
452
        return( id );
 
453
}
 
454
 
 
455
/**
 
456
 * na_action_get_label:
 
457
 * @action: the #NAAction object to be requested.
 
458
 *
 
459
 * Returns the label of the action.
 
460
 *
 
461
 * Returns: the label of the action as a newly allocated string. This
 
462
 * returned string must be g_free() by the caller.
 
463
 *
 
464
 * See na_action_set_label() for some rationale about label.
 
465
 */
 
466
gchar *
 
467
na_action_get_label( const NAAction *action )
 
468
{
 
469
        g_assert( NA_IS_ACTION( action ));
 
470
 
 
471
        gchar *label;
 
472
        g_object_get( G_OBJECT( action ), PROP_NAACTION_LABEL_STR, &label, NULL );
 
473
 
 
474
        return( label );
 
475
}
 
476
 
 
477
/**
 
478
 * na_action_get_version:
 
479
 * @action: the #NAAction object to be requested.
 
480
 *
 
481
 * Returns the version of the description of the action, as found when
 
482
 * reading it from the I/O storage subsystem.
 
483
 *
 
484
 * Returns: the version of the action as a newly allocated string. This
 
485
 * returned string must be g_free() by the caller.
 
486
 *
 
487
 * See na_action_set_version() for some rationale about version.
 
488
 */
 
489
gchar *
 
490
na_action_get_version( const NAAction *action )
 
491
{
 
492
        g_assert( NA_IS_ACTION( action ));
 
493
 
 
494
        gchar *version;
 
495
        g_object_get( G_OBJECT( action ), PROP_NAACTION_VERSION_STR, &version, NULL );
 
496
 
 
497
        return( version );
 
498
}
 
499
 
 
500
/**
 
501
 * na_action_get_tooltip:
 
502
 * @action: the #NAAction object to be requested.
 
503
 *
 
504
 * Returns the tooltip which will be display in the Nautilus context
 
505
 * menu item for this action.
 
506
 *
 
507
 * Returns: the tooltip of the action as a newly allocated string. This
 
508
 * returned string must be g_free() by the caller.
 
509
 */
 
510
gchar *
 
511
na_action_get_tooltip( const NAAction *action )
 
512
{
 
513
        g_assert( NA_IS_ACTION( action ));
 
514
 
 
515
        gchar *tooltip;
 
516
        g_object_get( G_OBJECT( action ), PROP_NAACTION_TOOLTIP_STR, &tooltip, NULL );
 
517
 
 
518
        return( tooltip );
 
519
}
 
520
 
 
521
/**
 
522
 * na_action_get_icon:
 
523
 * @action: the #NAAction object to be requested.
 
524
 *
 
525
 * Returns the name of the icon attached to the Nautilus context menu
 
526
 * item for this action.
 
527
 *
 
528
 * Returns: the icon name as a newly allocated string. This returned
 
529
 * string must be g_free() by the caller.
 
530
 */
 
531
gchar *
 
532
na_action_get_icon( const NAAction *action )
 
533
{
 
534
        g_assert( NA_IS_ACTION( action ));
 
535
 
 
536
        gchar *icon;
 
537
        g_object_get( G_OBJECT( action ), PROP_NAACTION_ICON_STR, &icon, NULL );
 
538
 
 
539
        return( icon );
 
540
}
 
541
 
 
542
/*
 
543
 * TODO: remove this function
 
544
 */
 
545
gchar *
 
546
na_action_get_verified_icon_name( const NAAction *action )
 
547
{
 
548
        g_assert( NA_IS_ACTION( action ));
 
549
 
 
550
        gchar *icon_name;
 
551
        g_object_get( G_OBJECT( action ), PROP_NAACTION_ICON_STR, &icon_name, NULL );
 
552
 
 
553
        if( icon_name[0] == '/' ){
 
554
                if( !g_file_test( icon_name, G_FILE_TEST_IS_REGULAR )){
 
555
                        g_free( icon_name );
 
556
                        return NULL;
 
557
                }
 
558
        } else if( strlen( icon_name ) == 0 ){
 
559
                g_free( icon_name );
 
560
                return NULL;
 
561
        }
 
562
 
 
563
        return( icon_name );
 
564
}
 
565
 
 
566
/**
 
567
 * na_action_is_enabled:
 
568
 * @action: the #NAAction object to be requested.
 
569
 *
 
570
 * Is the specified action enabled ?
 
571
 * When disabled, the action is never candidate to any selection
 
572
 *
 
573
 * Returns: %TRUE if the action is enabled, %FALSE else.
 
574
 */
 
575
gboolean
 
576
na_action_is_enabled( const NAAction *action )
 
577
{
 
578
        g_assert( NA_IS_ACTION( action ));
 
579
 
 
580
        gboolean enabled;
 
581
        g_object_get( G_OBJECT( action ), PROP_NAACTION_ENABLED_STR, &enabled, NULL );
 
582
 
 
583
        return( enabled );
 
584
}
 
585
 
 
586
/**
 
587
 * na_action_is_readonly:
 
588
 * @action: the #NAAction object to be requested.
 
589
 *
 
590
 * Is the specified action only readable ?
 
591
 * Or, in other words, may this action be edited and then saved to the
 
592
 * original I/O storage subsystem ?
 
593
 *
 
594
 * Returns: %TRUE if the action is editable, %FALSE else.
 
595
 */
 
596
gboolean
 
597
na_action_is_readonly( const NAAction *action )
 
598
{
 
599
        g_assert( NA_IS_ACTION( action ));
 
600
 
 
601
        gboolean readonly;
 
602
        g_object_get( G_OBJECT( action ), PROP_NAACTION_READONLY_STR, &readonly, NULL );
 
603
 
 
604
        return( readonly );
 
605
}
 
606
 
 
607
/**
 
608
 * na_action_get_provider:
 
609
 * @action: the #NAAction object to be requested.
 
610
 *
 
611
 * Returns the initial provider of the action (or the last which has
 
612
 * accepted a write operation). At the time of this request, this is
 
613
 * the most probable provider willing to accept a next writing
 
614
 * operation.
 
615
 *
 
616
 * Returns: a #NAIIOProvider object. The reference is
 
617
 * owned by #NAPivot pivot and should be g_object_unref() by the
 
618
 * caller.
 
619
 */
 
620
NAIIOProvider *
 
621
na_action_get_provider( const NAAction *action )
 
622
{
 
623
        g_assert( NA_IS_ACTION( action ));
 
624
 
 
625
        NAIIOProvider *provider;
 
626
        g_object_get( G_OBJECT( action ), PROP_NAACTION_PROVIDER_STR, &provider, NULL );
 
627
 
 
628
        return( provider );
 
629
}
 
630
 
 
631
/**
 
632
 * na_action_set_new_uuid:
 
633
 * @action: the #NAAction object to be updated.
 
634
 *
 
635
 * Set a new UUID for the action.
 
636
 */
 
637
void
 
638
na_action_set_new_uuid( NAAction *action )
 
639
{
 
640
        g_assert( NA_IS_ACTION( action ));
 
641
        uuid_t uuid;
 
642
        gchar uuid_str[64];
 
643
 
 
644
        uuid_generate( uuid );
 
645
        uuid_unparse_lower( uuid, uuid_str );
 
646
 
 
647
        g_object_set( G_OBJECT( action ), PROP_NAACTION_UUID_STR, uuid_str, NULL );
 
648
}
 
649
 
 
650
/**
 
651
 * na_action_set_uuid:
 
652
 * @action: the #NAAction object to be updated.
 
653
 * @uuid: the uuid to be set.
 
654
 *
 
655
 * Sets a new uuid for the action.
 
656
 *
 
657
 * #NAAction takes a copy of the provided UUID. This later may so be
 
658
 * g_free() by the caller after this function returns.
 
659
 *
 
660
 * This uuid is only required when writing the action to GConf in order
 
661
 * easily have unique subdirectories.
 
662
 *
 
663
 * This is an ASCII, case insensitive, string.
 
664
 *
 
665
 * UUID is transfered through import/export operations.
 
666
 *
 
667
 * Note that a user may import an action, translate it and then
 
668
 * reexport it : we so may have two different actions with the same
 
669
 * uuid.
 
670
 */
 
671
void
 
672
na_action_set_uuid( NAAction *action, const gchar *uuid )
 
673
{
 
674
        g_assert( NA_IS_ACTION( action ));
 
675
 
 
676
        g_object_set( G_OBJECT( action ), PROP_NAACTION_UUID_STR, uuid, NULL );
 
677
}
 
678
 
 
679
/**
 
680
 * na_action_set_label:
 
681
 * @action: the #NAAction object to be updated.
 
682
 * @label: the label to be set.
 
683
 *
 
684
 * Sets a new label for the action.
 
685
 *
 
686
 * #NAAction takes a copy of the provided label. This later may so be
 
687
 * g_free() by the caller after this function returns.
 
688
 *
 
689
 * The user knows its actions through their labels, as this is the main
 
690
 * visible part (with the icon) in Nautilus context menu and in the
 
691
 * NACT ui.
 
692
 */
 
693
void
 
694
na_action_set_label( NAAction *action, const gchar *label )
 
695
{
 
696
        g_assert( NA_IS_ACTION( action ));
 
697
 
 
698
        g_object_set( G_OBJECT( action ), PROP_NAACTION_LABEL_STR, label, NULL );
 
699
}
 
700
 
 
701
/**
 
702
 * na_action_set_version:
 
703
 * @action: the #NAAction object to be updated.
 
704
 * @label: the label to be set.
 
705
 *
 
706
 * Sets a new version for the action.
 
707
 *
 
708
 * #NAAction takes a copy of the provided version. This later may so be
 
709
 * g_free() by the caller after this function returns.
 
710
 *
 
711
 * The version describes the schema of the informations in the I/O
 
712
 * storage subsystem.
 
713
 *
 
714
 * Version is stored in the #NAAction object as readen from the I/O
 
715
 * storage subsystem, even if the #NAAction object itself only reflects
 
716
 * the lastest known version. Conversion is made at load time (cf.
 
717
 * na_gconf_load_action()).
 
718
 */
 
719
void
 
720
na_action_set_version( NAAction *action, const gchar *version )
 
721
{
 
722
        g_assert( NA_IS_ACTION( action ));
 
723
 
 
724
        g_object_set( G_OBJECT( action ), PROP_NAACTION_VERSION_STR, version, NULL );
 
725
}
 
726
 
 
727
/**
 
728
 * na_action_set_tooltip:
 
729
 * @action: the #NAAction object to be updated.
 
730
 * @tooltip: the tooltip to be set.
 
731
 *
 
732
 * Sets a new tooltip for the action. Tooltip will be displayed by
 
733
 * Nautilus when the user move its mouse over the Nautilus context menu
 
734
 * item.
 
735
 *
 
736
 * #NAAction takes a copy of the provided tooltip. This later may so be
 
737
 * g_free() by the caller after this function returns.
 
738
 */
 
739
void
 
740
na_action_set_tooltip( NAAction *action, const gchar *tooltip )
 
741
{
 
742
        g_assert( NA_IS_ACTION( action ));
 
743
 
 
744
        g_object_set( G_OBJECT( action ), PROP_NAACTION_TOOLTIP_STR, tooltip, NULL );
 
745
}
 
746
 
 
747
/**
 
748
 * na_action_set_icon:
 
749
 * @action: the #NAAction object to be updated.
 
750
 * @icon: the icon name to be set.
 
751
 *
 
752
 * Sets a new icon name for the action.
 
753
 *
 
754
 * #NAAction takes a copy of the provided icon name. This later may so
 
755
 * be g_free() by the caller after this function returns.
 
756
 */
 
757
void
 
758
na_action_set_icon( NAAction *action, const gchar *icon )
 
759
{
 
760
        g_assert( NA_IS_ACTION( action ));
 
761
 
 
762
        g_object_set( G_OBJECT( action ), PROP_NAACTION_ICON_STR, icon, NULL );
 
763
}
 
764
 
 
765
/**
 
766
 * na_action_set_enabled:
 
767
 * @action: the #NAAction object to be updated.
 
768
 * @enabled: the indicator to be set.
 
769
 *
 
770
 * Sets whether the action is enabled or not.
 
771
 */
 
772
void
 
773
na_action_set_enabled( NAAction *action, gboolean enabled )
 
774
{
 
775
        g_assert( NA_IS_ACTION( action ));
 
776
 
 
777
        g_object_set( G_OBJECT( action ), PROP_NAACTION_ENABLED_STR, enabled, NULL );
 
778
}
 
779
 
 
780
/**
 
781
 * na_action_set_readonly:
 
782
 * @action: the #NAAction object to be updated.
 
783
 * @readonly: the indicator to be set.
 
784
 *
 
785
 * Sets whether the action is readonly.
 
786
 */
 
787
void
 
788
na_action_set_readonly( NAAction *action, gboolean readonly )
 
789
{
 
790
        g_assert( NA_IS_ACTION( action ));
 
791
 
 
792
        g_object_set( G_OBJECT( action ), PROP_NAACTION_READONLY_STR, readonly, NULL );
 
793
}
 
794
 
 
795
/**
 
796
 * na_action_set_provider:
 
797
 * @action: the #NAAction object to be updated.
 
798
 * @provider: the #NAIIOProvider to be set.
 
799
 *
 
800
 * Sets the I/O provider for this #NAAction.
 
801
 */
 
802
void
 
803
na_action_set_provider( NAAction *action, const NAIIOProvider *provider )
 
804
{
 
805
        g_assert( NA_IS_ACTION( action ));
 
806
 
 
807
        g_object_set( G_OBJECT( action ), PROP_NAACTION_PROVIDER_STR, provider, NULL );
 
808
}
 
809
 
 
810
/**
 
811
 * na_action_get_new_profile_name:
 
812
 * @action: the #NAAction object which will receive a new profile.
 
813
 *
 
814
 * Returns a name suitable as a new profile name.
 
815
 *
 
816
 * The search is made by iterating over the standard profile name
 
817
 * prefix : basically, we increment a counter until finding a unique
 
818
 * name. The provided name is so only suitable for the specified
 
819
 * @action.
 
820
 *
 
821
 * Returns: a newly allocated profile name, which should be g_free() by
 
822
 * the caller.
 
823
 */
 
824
gchar *
 
825
na_action_get_new_profile_name( const NAAction *action )
 
826
{
 
827
        g_assert( NA_IS_ACTION( action ));
 
828
        int i;
 
829
        gboolean ok = FALSE;
 
830
        gchar *candidate = NULL;
 
831
 
 
832
        for( i=1 ; !ok ; ++i ){
 
833
                g_free( candidate );
 
834
                candidate = g_strdup_printf( "%s%d", ACTION_PROFILE_PREFIX, i );
 
835
                if( !na_action_get_profile( action, candidate )){
 
836
                        ok = TRUE;
 
837
                }
 
838
        }
 
839
        if( !ok ){
 
840
                g_free( candidate );
 
841
                candidate = NULL;
 
842
        }
 
843
        return( candidate );
 
844
}
 
845
 
 
846
/**
 
847
 * na_action_get_profile:
 
848
 * @action: the #NAAction object which is to be requested.
 
849
 * @name: the name of the searched profile.
 
850
 *
 
851
 * Returns the required profile.
 
852
 *
 
853
 * Returns: a pointer to the #NAActionProfile profile with the required
 
854
 * name.
 
855
 *
 
856
 * The returned #NAActionProfile is owned by the @action object ; the
 
857
 * caller should not try to g_free() nor g_object_unref() it.
 
858
 */
 
859
NAActionProfile *
 
860
na_action_get_profile( const NAAction *action, const gchar *name )
 
861
{
 
862
        g_assert( NA_IS_ACTION( action ));
 
863
        NAActionProfile *found = NULL;
 
864
        GSList *ip;
 
865
 
 
866
        for( ip = action->private->profiles ; ip && !found ; ip = ip->next ){
 
867
                NAActionProfile *iprofile = NA_ACTION_PROFILE( ip->data );
 
868
                gchar *iname = na_action_profile_get_name( iprofile );
 
869
                if( !strcmp( name, iname )){
 
870
                        found = iprofile;
 
871
                }
 
872
                g_free( iname );
 
873
        }
 
874
 
 
875
        return( found );
 
876
}
 
877
 
 
878
/**
 
879
 * na_action_attach_profile:
 
880
 * @action: the #NAAction action to which the profile will be attached.
 
881
 * @profile: the #NAActionProfile profile to be attached to @action.
 
882
 *
 
883
 * Adds a profile at the end of the list of profiles.
 
884
 */
 
885
void
 
886
na_action_attach_profile( NAAction *action, NAActionProfile *profile )
 
887
{
 
888
        g_assert( NA_IS_ACTION( action ));
 
889
        g_assert( NA_IS_ACTION_PROFILE( profile ));
 
890
 
 
891
        action->private->profiles = g_slist_append( action->private->profiles, ( gpointer ) profile );
 
892
 
 
893
        na_action_profile_set_action( profile, action );
 
894
}
 
895
 
 
896
/**
 
897
 * na_action_remove_profile:
 
898
 * @action: the #NAAction action from which the profile will be removed.
 
899
 * @profile: the #NAActionProfile profile to be removed from @action.
 
900
 *
 
901
 * Removes a profile from the list of profiles.
 
902
 */
 
903
void
 
904
na_action_remove_profile( NAAction *action, NAActionProfile *profile )
 
905
{
 
906
        g_assert( NA_IS_ACTION( action ));
 
907
        g_assert( NA_IS_ACTION_PROFILE( profile ));
 
908
 
 
909
        action->private->profiles = g_slist_remove( action->private->profiles, ( gconstpointer ) profile );
 
910
}
 
911
 
 
912
/**
 
913
 * na_action_get_profiles:
 
914
 * @action: the #NAAction action whose profiles has to be retrieved.
 
915
 *
 
916
 * Returns the list of profiles of the action.
 
917
 *
 
918
 * Returns: a #GSList of #NAActionProfile objects. The returned pointer
 
919
 * is owned by the @action object ; the caller should not try to
 
920
 * g_free() nor g_object_unref() it.
 
921
 */
 
922
GSList *
 
923
na_action_get_profiles( const NAAction *action )
 
924
{
 
925
        g_assert( NA_IS_ACTION( action ));
 
926
 
 
927
        return( action->private->profiles );
 
928
}
 
929
 
 
930
/**
 
931
 * na_action_set_profiles:
 
932
 * @action: the #NAAction action whose profiles has to be set.
 
933
 * @list: a #GSList list of #NAActionProfile objects to be installed in
 
934
 * the @action.
 
935
 *
 
936
 * Sets the list of the profiles for the action.
 
937
 *
 
938
 * The provided list removes and replaces the previous profiles list.
 
939
 * This list is then copied to the action, and thus can then be safely
 
940
 * na_action_free_profiles() by the caller.
 
941
 */
 
942
void
 
943
na_action_set_profiles( NAAction *action, GSList *list )
 
944
{
 
945
        g_assert( NA_IS_ACTION( action ));
 
946
 
 
947
        free_profiles( action );
 
948
 
 
949
        GSList *ip;
 
950
        for( ip = list ; ip ; ip = ip->next ){
 
951
                NAObject *new_profile = na_object_duplicate( NA_OBJECT( ip->data ));
 
952
                na_action_attach_profile( action, NA_ACTION_PROFILE( new_profile ));
 
953
        }
 
954
}
 
955
 
 
956
/**
 
957
 * na_action_free_profiles:
 
958
 * @list: a #GSList list of #NAActionProfile objects.
 
959
 *
 
960
 * Frees a profiles list.
 
961
 */
 
962
void
 
963
na_action_free_profiles( GSList *list )
 
964
{
 
965
        GSList *ip;
 
966
        for( ip = list ; ip ; ip = ip->next ){
 
967
                g_object_unref( NA_ACTION_PROFILE( ip->data ));
 
968
        }
 
969
        g_slist_free( list );
 
970
}
 
971
 
 
972
/**
 
973
 * na_action_get_profiles_count:
 
974
 * @action: the #NAAction action whose profiles has to be counted.
 
975
 *
 
976
 * Returns the number of profiles which are defined for the action.
 
977
 *
 
978
 * Returns: the number of profiles defined for @action.
 
979
 */
 
980
guint
 
981
na_action_get_profiles_count( const NAAction *action )
 
982
{
 
983
        g_assert( NA_IS_ACTION( action ));
 
984
 
 
985
        return( g_slist_length( action->private->profiles ));
 
986
}
 
987
 
 
988
static void
 
989
object_check_edited_status( const NAObject *action )
 
990
{
 
991
        if( st_parent_class->check_edited_status ){
 
992
                st_parent_class->check_edited_status( action );
 
993
        }
 
994
 
 
995
        GSList *ip;
 
996
        for( ip = NA_ACTION( action )->private->profiles ; ip ; ip = ip->next ){
 
997
                na_object_check_edited_status( NA_OBJECT( ip->data ));
 
998
        }
 
999
}
 
1000
 
 
1001
static void
 
1002
object_dump( const NAObject *action )
 
1003
{
 
1004
        static const gchar *thisfn = "na_action_object_dump";
 
1005
 
 
1006
        g_assert( NA_IS_ACTION( action ));
 
1007
        NAAction *self = NA_ACTION( action );
 
1008
 
 
1009
        if( st_parent_class->dump ){
 
1010
                st_parent_class->dump( action );
 
1011
        }
 
1012
 
 
1013
        g_debug( "%s:   version='%s'", thisfn, self->private->version );
 
1014
        g_debug( "%s:   tooltip='%s'", thisfn, self->private->tooltip );
 
1015
        g_debug( "%s:      icon='%s'", thisfn, self->private->icon );
 
1016
        g_debug( "%s:   enabled='%s'", thisfn, self->private->enabled ? "True" : "False" );
 
1017
        g_debug( "%s: read-only='%s'", thisfn, self->private->read_only ? "True" : "False" );
 
1018
        g_debug( "%s:  provider=%p", thisfn, self->private->provider );
 
1019
 
 
1020
        /* dump profiles */
 
1021
        g_debug( "%s: %d profile(s) at %p", thisfn, na_action_get_profiles_count( self ), self->private->profiles );
 
1022
        GSList *item;
 
1023
        for( item = self->private->profiles ;   item != NULL ; item = item->next ){
 
1024
                na_object_dump(( const NAObject * ) item->data );
 
1025
        }
 
1026
}
 
1027
 
 
1028
static NAObject *
 
1029
object_duplicate( const NAObject *action )
 
1030
{
 
1031
        g_assert( NA_IS_ACTION( action ));
 
1032
 
 
1033
        NAObject *duplicate = NA_OBJECT( na_action_new());
 
1034
 
 
1035
        na_object_copy( duplicate, action );
 
1036
 
 
1037
        return( duplicate );
 
1038
}
 
1039
 
 
1040
void
 
1041
object_copy( NAObject *target, const NAObject *source )
 
1042
{
 
1043
        g_assert( NA_IS_ACTION( source ));
 
1044
        g_assert( NA_IS_ACTION( target ));
 
1045
 
 
1046
        gchar *version, *tooltip, *icon;
 
1047
        gboolean enabled, readonly;
 
1048
        gpointer provider;
 
1049
 
 
1050
        g_object_get( G_OBJECT( source ),
 
1051
                        PROP_NAACTION_VERSION_STR, &version,
 
1052
                        PROP_NAACTION_TOOLTIP_STR, &tooltip,
 
1053
                        PROP_NAACTION_ICON_STR, &icon,
 
1054
                        PROP_NAACTION_ENABLED_STR, &enabled,
 
1055
                        PROP_NAACTION_READONLY_STR, &readonly,
 
1056
                        PROP_NAACTION_PROVIDER_STR, &provider,
 
1057
                        NULL );
 
1058
 
 
1059
        g_object_set( G_OBJECT( target ),
 
1060
                        PROP_NAACTION_VERSION_STR, version,
 
1061
                        PROP_NAACTION_TOOLTIP_STR, tooltip,
 
1062
                        PROP_NAACTION_ICON_STR, icon,
 
1063
                        PROP_NAACTION_ENABLED_STR, enabled,
 
1064
                        PROP_NAACTION_READONLY_STR, readonly,
 
1065
                        PROP_NAACTION_PROVIDER_STR, provider,
 
1066
                        NULL );
 
1067
 
 
1068
        g_free( tooltip );
 
1069
        g_free( version );
 
1070
 
 
1071
        GSList *ip;
 
1072
        for( ip = NA_ACTION( source )->private->profiles ; ip ; ip = ip->next ){
 
1073
                NAActionProfile *profile = NA_ACTION_PROFILE( na_object_duplicate( NA_OBJECT( ip->data )));
 
1074
                na_action_attach_profile( NA_ACTION( target ), profile );
 
1075
        }
 
1076
 
 
1077
        if( st_parent_class->copy ){
 
1078
                st_parent_class->copy( target, source );
 
1079
        }
 
1080
}
 
1081
 
 
1082
static gboolean
 
1083
object_are_equal( const NAObject *a, const NAObject *b )
 
1084
{
 
1085
        g_assert( NA_IS_ACTION( a ));
 
1086
        g_assert( NA_IS_ACTION( b ));
 
1087
 
 
1088
        NAAction *first = NA_ACTION( a );
 
1089
        NAAction *second = NA_ACTION( b );
 
1090
 
 
1091
        gboolean equal =
 
1092
                ( g_utf8_collate( first->private->version, second->private->version ) == 0 ) &&
 
1093
                ( g_utf8_collate( first->private->tooltip, second->private->tooltip ) == 0 ) &&
 
1094
                ( g_utf8_collate( first->private->icon, second->private->icon ) == 0 );
 
1095
 
 
1096
        if( equal ){
 
1097
                equal = ( first->private->enabled && second->private->enabled ) ||
 
1098
                                ( !first->private->enabled && !second->private->enabled );
 
1099
        }
 
1100
        if( equal ){
 
1101
                equal = ( g_slist_length( first->private->profiles ) == g_slist_length( second->private->profiles ));
 
1102
        }
 
1103
        if( equal ){
 
1104
                GSList *ip;
 
1105
                for( ip = first->private->profiles ; ip && equal ; ip = ip->next ){
 
1106
                        NAActionProfile *first_profile = NA_ACTION_PROFILE( ip->data );
 
1107
                        gchar *first_name = na_action_profile_get_name( first_profile );
 
1108
                        NAActionProfile *second_profile = NA_ACTION_PROFILE( na_action_get_profile( second, first_name ));
 
1109
                        if( second_profile ){
 
1110
                                equal = na_object_are_equal( NA_OBJECT( first_profile ), NA_OBJECT( second_profile ));
 
1111
                        } else {
 
1112
                                equal = FALSE;
 
1113
                        }
 
1114
                        g_free( first_name );
 
1115
                }
 
1116
        }
 
1117
        if( equal ){
 
1118
                GSList *ip;
 
1119
                for( ip = second->private->profiles ; ip && equal ; ip = ip->next ){
 
1120
                        NAActionProfile *second_profile = NA_ACTION_PROFILE( ip->data );
 
1121
                        gchar *second_name = na_action_profile_get_name( second_profile );
 
1122
                        NAActionProfile *first_profile = NA_ACTION_PROFILE( na_action_get_profile( first, second_name ));
 
1123
                        if( first_profile ){
 
1124
                                equal = na_object_are_equal( NA_OBJECT( first_profile ), NA_OBJECT( second_profile ));
 
1125
                        } else {
 
1126
                                equal = FALSE;
 
1127
                        }
 
1128
                        g_free( second_name );
 
1129
                }
 
1130
        }
 
1131
        if( equal ){
 
1132
                if( st_parent_class->are_equal ){
 
1133
                        equal = st_parent_class->are_equal( a, b );
 
1134
                }
 
1135
        }
 
1136
 
 
1137
        return( equal );
 
1138
}
 
1139
 
 
1140
gboolean
 
1141
object_is_valid( const NAObject *action )
 
1142
{
 
1143
        g_assert( NA_IS_ACTION( action ));
 
1144
 
 
1145
        gchar *label;
 
1146
        g_object_get( G_OBJECT( action ), PROP_NAACTION_LABEL_STR, &label, NULL );
 
1147
        gboolean is_valid = ( label && g_utf8_strlen( label, -1 ) > 0 );
 
1148
        g_free( label );
 
1149
 
 
1150
        GSList *ip;
 
1151
        for( ip = NA_ACTION( action )->private->profiles ; ip && is_valid ; ip = ip->next ){
 
1152
                is_valid = na_object_is_valid( NA_OBJECT( ip->data ));
 
1153
        }
 
1154
 
 
1155
        if( is_valid ){
 
1156
                if( st_parent_class->is_valid ){
 
1157
                        is_valid = st_parent_class->is_valid( action );
 
1158
                }
 
1159
        }
 
1160
 
 
1161
        return( is_valid );
 
1162
}
 
1163
 
 
1164
static void
 
1165
free_profiles( NAAction *action )
 
1166
{
 
1167
        na_action_free_profiles( action->private->profiles );
 
1168
 
 
1169
        action->private->profiles = NULL;
 
1170
}