NAIDuplicable: rewrite modification check stack
[nautilus-actions.git] / src / core / na-object-profile.c
blob21c267c5dd423dabd004db593401d70109e6b892
1 /*
2 * Nautilus-Actions
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.
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)
31 #ifdef HAVE_CONFIG_H
32 #include <config.h>
33 #endif
35 #include <glib/gi18n.h>
36 #include <string.h>
38 #include <libnautilus-extension/nautilus-file-info.h>
40 #include <api/na-core-utils.h>
41 #include <api/na-iio-provider.h>
42 #include <api/na-ifactory-object.h>
43 #include <api/na-object-api.h>
45 #include "na-factory-provider.h"
46 #include "na-factory-object.h"
47 #include "na-selected-info.h"
48 #include "na-gnome-vfs-uri.h"
50 /* private class data
52 struct _NAObjectProfileClassPrivate {
53 void *empty; /* so that gcc -pedantic is happy */
56 /* private instance data
58 struct _NAObjectProfilePrivate {
59 gboolean dispose_has_run;
62 #define PROFILE_NAME_PREFIX "profile-"
64 extern NADataGroup profile_data_groups []; /* defined in na-item-profile-factory.c */
66 static NAObjectIdClass *st_parent_class = NULL;
68 static GType register_type( void );
69 static void class_init( NAObjectProfileClass *klass );
70 static void instance_init( GTypeInstance *instance, gpointer klass );
71 static void instance_get_property( GObject *object, guint property_id, GValue *value, GParamSpec *spec );
72 static void instance_set_property( GObject *object, guint property_id, const GValue *value, GParamSpec *spec );
73 static void instance_dispose( GObject *object );
74 static void instance_finalize( GObject *object );
76 static void object_copy( NAObject *target, const NAObject *source, gboolean recursive );
77 static void object_dump( const NAObject *object );
78 static gboolean object_is_valid( const NAObject *object );
80 static void ifactory_object_iface_init( NAIFactoryObjectInterface *iface );
81 static guint ifactory_object_get_version( const NAIFactoryObject *instance );
82 static NADataGroup *ifactory_object_get_groups( const NAIFactoryObject *instance );
83 static gboolean ifactory_object_is_valid( const NAIFactoryObject *object );
84 static void ifactory_object_read_done( NAIFactoryObject *instance, const NAIFactoryProvider *reader, void *reader_data, GSList **messages );
85 static guint ifactory_object_write_done( NAIFactoryObject *instance, const NAIFactoryProvider *writer, void *writer_data, GSList **messages );
87 static void icontext_iface_init( NAIContextInterface *iface );
88 static gboolean icontext_is_candidate( NAIContext *object, guint target, GList *selection );
90 static gboolean convert_pre_v3_parameters( NAObjectProfile *profile );
91 static gboolean convert_pre_v3_parameters_str( gchar *str );
92 static gboolean convert_pre_v3_multiple( NAObjectProfile *profile );
93 static gboolean convert_pre_v3_isfiledir( NAObjectProfile *profile );
94 static void read_done_ending( NAObjectProfile *profile );
95 static void split_path_parameters( NAObjectProfile *profile );
96 static gboolean profile_is_valid( const NAObjectProfile *profile );
97 static gboolean is_valid_path_parameters( const NAObjectProfile *profile );
99 static gchar *object_id_new_id( const NAObjectId *item, const NAObjectId *new_parent );
101 GType
102 na_object_profile_get_type( void )
104 static GType object_type = 0;
106 if( !object_type ){
107 object_type = register_type();
110 return( object_type );
113 static GType
114 register_type( void )
116 static const gchar *thisfn = "na_object_profile_register_type";
117 GType type;
119 static GTypeInfo info = {
120 sizeof( NAObjectProfileClass ),
121 ( GBaseInitFunc ) NULL,
122 ( GBaseFinalizeFunc ) NULL,
123 ( GClassInitFunc ) class_init,
124 NULL,
125 NULL,
126 sizeof( NAObjectProfile ),
128 ( GInstanceInitFunc ) instance_init
131 static const GInterfaceInfo icontext_iface_info = {
132 ( GInterfaceInitFunc ) icontext_iface_init,
133 NULL,
134 NULL
137 static const GInterfaceInfo ifactory_object_iface_info = {
138 ( GInterfaceInitFunc ) ifactory_object_iface_init,
139 NULL,
140 NULL
143 g_debug( "%s", thisfn );
145 type = g_type_register_static( NA_OBJECT_ID_TYPE, "NAObjectProfile", &info, 0 );
147 g_type_add_interface_static( type, NA_ICONTEXT_TYPE, &icontext_iface_info );
149 g_type_add_interface_static( type, NA_IFACTORY_OBJECT_TYPE, &ifactory_object_iface_info );
151 return( type );
154 static void
155 class_init( NAObjectProfileClass *klass )
157 static const gchar *thisfn = "na_object_profile_class_init";
158 GObjectClass *object_class;
159 NAObjectClass *naobject_class;
160 NAObjectIdClass *naobjectid_class;
162 g_debug( "%s: klass=%p", thisfn, ( void * ) klass );
164 st_parent_class = g_type_class_peek_parent( klass );
166 object_class = G_OBJECT_CLASS( klass );
167 object_class->set_property = instance_set_property;
168 object_class->get_property = instance_get_property;
169 object_class->dispose = instance_dispose;
170 object_class->finalize = instance_finalize;
172 naobject_class = NA_OBJECT_CLASS( klass );
173 naobject_class->dump = object_dump;
174 naobject_class->copy = object_copy;
175 naobject_class->is_valid = object_is_valid;
177 naobjectid_class = NA_OBJECT_ID_CLASS( klass );
178 naobjectid_class->new_id = object_id_new_id;
180 klass->private = g_new0( NAObjectProfileClassPrivate, 1 );
182 na_factory_object_define_properties( object_class, profile_data_groups );
185 static void
186 instance_init( GTypeInstance *instance, gpointer klass )
188 static const gchar *thisfn = "na_object_profile_instance_init";
189 NAObjectProfile *self;
191 g_return_if_fail( NA_IS_OBJECT_PROFILE( instance ));
193 self = NA_OBJECT_PROFILE( instance );
195 g_debug( "%s: instance=%p (%s), klass=%p",
196 thisfn, ( void * ) instance, G_OBJECT_TYPE_NAME( instance ), ( void * ) klass );
198 self->private = g_new0( NAObjectProfilePrivate, 1 );
200 self->private->dispose_has_run = FALSE;
203 static void
204 instance_get_property( GObject *object, guint property_id, GValue *value, GParamSpec *spec )
206 g_return_if_fail( NA_IS_OBJECT_PROFILE( object ));
207 g_return_if_fail( NA_IS_IFACTORY_OBJECT( object ));
209 if( !NA_OBJECT_PROFILE( object )->private->dispose_has_run ){
211 na_factory_object_get_as_value( NA_IFACTORY_OBJECT( object ), g_quark_to_string( property_id ), value );
215 static void
216 instance_set_property( GObject *object, guint property_id, const GValue *value, GParamSpec *spec )
218 g_return_if_fail( NA_IS_OBJECT_PROFILE( object ));
219 g_return_if_fail( NA_IS_IFACTORY_OBJECT( object ));
221 if( !NA_OBJECT_PROFILE( object )->private->dispose_has_run ){
223 na_factory_object_set_from_value( NA_IFACTORY_OBJECT( object ), g_quark_to_string( property_id ), value );
227 static void
228 instance_dispose( GObject *object )
230 static const gchar *thisfn = "na_object_profile_instance_dispose";
231 NAObjectProfile *self;
233 g_return_if_fail( NA_IS_OBJECT_PROFILE( object ));
235 self = NA_OBJECT_PROFILE( object );
237 if( !self->private->dispose_has_run ){
239 g_debug( "%s: object=%p (%s)", thisfn, ( void * ) object, G_OBJECT_TYPE_NAME( object ));
241 self->private->dispose_has_run = TRUE;
243 /* chain up to the parent class */
244 if( G_OBJECT_CLASS( st_parent_class )->dispose ){
245 G_OBJECT_CLASS( st_parent_class )->dispose( object );
250 static void
251 instance_finalize( GObject *object )
253 static const gchar *thisfn = "na_object_profile_instance_finalize";
254 NAObjectProfile *self;
256 g_return_if_fail( NA_IS_OBJECT_PROFILE( object ));
258 self = NA_OBJECT_PROFILE( object );
260 g_debug( "%s: object=%p (%s)", thisfn, ( void * ) object, G_OBJECT_TYPE_NAME( object ));
262 g_free( self->private );
264 /* chain call to parent class */
265 if( G_OBJECT_CLASS( st_parent_class )->finalize ){
266 G_OBJECT_CLASS( st_parent_class )->finalize( object );
270 static void
271 object_copy( NAObject *target, const NAObject *source, gboolean recursive )
273 g_return_if_fail( NA_IS_OBJECT_PROFILE( target ));
274 g_return_if_fail( NA_IS_OBJECT_PROFILE( source ));
276 if( !NA_OBJECT_PROFILE( target )->private->dispose_has_run &&
277 !NA_OBJECT_PROFILE( source )->private->dispose_has_run ){
279 na_factory_object_copy( NA_IFACTORY_OBJECT( target ), NA_IFACTORY_OBJECT( source ));
283 static void
284 object_dump( const NAObject *object )
286 static const char *thisfn = "na_object_profile_object_dump";
287 NAObjectProfile *self;
289 g_return_if_fail( NA_IS_OBJECT_PROFILE( object ));
291 self = NA_OBJECT_PROFILE( object );
293 if( !self->private->dispose_has_run ){
294 g_debug( "%s: object=%p (%s, ref_count=%d)", thisfn,
295 ( void * ) object, G_OBJECT_TYPE_NAME( object ), G_OBJECT( object )->ref_count );
297 /* chain up to the parent class */
298 if( NA_OBJECT_CLASS( st_parent_class )->dump ){
299 NA_OBJECT_CLASS( st_parent_class )->dump( object );
302 g_debug( "+- end of dump" );
306 static gboolean
307 object_is_valid( const NAObject *object )
309 g_return_val_if_fail( NA_IS_OBJECT_PROFILE( object ), FALSE );
311 return( profile_is_valid( NA_OBJECT_PROFILE( object )));
314 static void
315 ifactory_object_iface_init( NAIFactoryObjectInterface *iface )
317 static const gchar *thisfn = "na_object_profile_ifactory_object_iface_init";
319 g_debug( "%s: iface=%p", thisfn, ( void * ) iface );
321 iface->get_version = ifactory_object_get_version;
322 iface->get_groups = ifactory_object_get_groups;
323 iface->is_valid = ifactory_object_is_valid;
324 iface->read_done = ifactory_object_read_done;
325 iface->write_done = ifactory_object_write_done;
328 static guint
329 ifactory_object_get_version( const NAIFactoryObject *instance )
331 return( 1 );
334 static NADataGroup *
335 ifactory_object_get_groups( const NAIFactoryObject *instance )
337 return( profile_data_groups );
340 static gboolean
341 ifactory_object_is_valid( const NAIFactoryObject *object )
343 static const gchar *thisfn = "na_object_profile_ifactory_object_is_valid";
345 g_return_val_if_fail( NA_IS_OBJECT_PROFILE( object ), FALSE );
347 g_debug( "%s: object=%p (%s)", thisfn, ( void * ) object, G_OBJECT_TYPE_NAME( object ));
349 return( profile_is_valid( NA_OBJECT_PROFILE( object )));
352 static void
353 ifactory_object_read_done( NAIFactoryObject *instance, const NAIFactoryProvider *reader, void *reader_data, GSList **messages )
355 static const gchar *thisfn = "na_object_profile_ifactory_object_read_done";
356 NAObjectAction *action;
357 guint iversion;
359 g_debug( "%s: profile=%p", thisfn, ( void * ) instance );
361 /* converts pre-v3 data
363 action = NA_OBJECT_ACTION( na_object_get_parent( instance ));
364 iversion = na_object_get_iversion( action );
365 g_debug( "%s: iversion=%d", thisfn, iversion );
367 if( iversion < 3 ){
368 na_object_profile_convert_v2_to_last( NA_OBJECT_PROFILE( instance ));
371 read_done_ending( NA_OBJECT_PROFILE( instance ));
374 static guint
375 ifactory_object_write_done( NAIFactoryObject *instance, const NAIFactoryProvider *writer, void *writer_data, GSList **messages )
377 return( NA_IIO_PROVIDER_CODE_OK );
380 static void
381 icontext_iface_init( NAIContextInterface *iface )
383 static const gchar *thisfn = "na_object_profile_icontext_iface_init";
385 g_debug( "%s: iface=%p", thisfn, ( void * ) iface );
387 iface->is_candidate = icontext_is_candidate;
390 static gboolean
391 icontext_is_candidate( NAIContext *object, guint target, GList *selection )
393 return( TRUE );
397 * starting wih v3, parameters are relabeled
398 * pre-v3 parameters post-v3 parameters
399 * ---------------------------- -----------------------------------
400 * %b: (first) basename (was %f)
401 * %B: list of basenames (was %m)
402 * %c: count (new)
403 * %d: (first) base directory ................... (unchanged)
404 * %D: list of base dir (new)
405 * %f: (first) filename -> %b %f: (first) pathname (new)
406 * %F: list of pathnames (was %M)
407 * %h: (first) hostname ................... (unchanged)
408 * %m: list of basenames -> %B %m: (first) mimetype (new)
409 * %M: list of pathnames -> %F %M: list of mimetypes (new)
410 * %n: (first) username (was %U)
411 * %p: (first) port number ................... (unchanged)
412 * %R: list of URIs -> %U - (removed)
413 * %s: (first) scheme ................... (unchanged)
414 * %u: (first) URI ................... (unchanged)
415 * %U: (first) username -> %n %U: list of URIs (was %R)
416 * %w: (first) basename w/o ext. (new)
417 * %W: list of basenames w/o ext. (new)
418 * %x: (first) extension (new)
419 * %X: list of extensions (new)
420 * %%: % ................... (unchanged)
422 * For pre-v3 items,
423 * - substitute %f with %b, and as a special case %d/%f -> %f
424 * - substitute %m with %B
425 * - substitute %M with %F
426 * - substitute %R with %U
427 * - substitute %U with %n
429 * Note that pre-v3 items only have parameters in the command and path fields.
430 * Are only located in 'profile' objects.
431 * Are only found in GConf or XML providers, as .desktop files have been
432 * simultaneously introduced.
434 * As a recall of the dynamics of the reading when loading an action:
435 * - na_object_action_read_done: set action defaults
436 * - nagp_reader_read_done: read profiles
437 * > nagp_reader_read_start: attach profile to its parent
438 * > na_object_profile_read_done: convert old parameters
440 * So, when converting v2 to v3 parameters in a v2 profile,
441 * action already has its default values (including iversion=3)
443 static gboolean
444 convert_pre_v3_parameters( NAObjectProfile *profile )
446 static const gchar *thisfn = "na_object_profile_convert_pre_v3_parameters";
447 gboolean path_changed, parms_changed;
448 gchar *before;
450 gchar *path = na_object_get_path( profile );
451 before = g_strdup( path );
452 path_changed = convert_pre_v3_parameters_str( path );
453 if( path_changed ){
454 na_object_set_path( profile, path );
455 g_debug( "%s: path=%s changed to %s", thisfn, before, path );
457 g_free( before );
458 g_free( path );
460 gchar *parms = na_object_get_parameters( profile );
461 before = g_strdup( parms );
462 parms_changed = convert_pre_v3_parameters_str( parms );
463 if( parms_changed ){
464 na_object_set_parameters( profile, parms );
465 g_debug( "%s: parameters=%s changed to %s", thisfn, before, parms );
467 g_free( before );
468 g_free( parms );
470 return( path_changed || parms_changed );
473 static gboolean
474 convert_pre_v3_parameters_str( gchar *str )
476 gboolean changed;
477 gchar *iter = str;
479 changed = FALSE;
480 while( iter != NULL &&
481 strlen( iter ) > 0 &&
482 ( iter = g_strstr_len( iter, strlen( iter ), "%" )) != NULL ){
484 switch( iter[1] ){
486 /* as a special optimization case, "%d/%f" parameters
487 * may be favourably converted to just "%f" instead of "%d/%b"
489 case 'd':
490 if( !strncmp( iter, "%d/%f", 5 )){
491 strncpy( iter, iter+3, strlen( iter ));
492 changed = TRUE;
494 break;
496 /* %f (first filename) becomes %b
498 case 'f':
499 iter[1] = 'b';
500 changed = TRUE;
501 break;
503 /* %m (list of basenames) becomes %B
505 case 'm':
506 iter[1] = 'B';
507 changed = TRUE;
508 break;
510 /* %M (list of filenames) becomes %F
512 case 'M':
513 iter[1] = 'F';
514 changed = TRUE;
515 break;
517 /* %R (list of URIs) becomes %U
519 case 'R':
520 iter[1] = 'U';
521 changed = TRUE;
522 break;
524 /* %U ((first) username) becomes %n
526 case 'U':
527 iter[1] = 'n';
528 changed = TRUE;
529 break;
532 iter += 2;
535 return( changed );
539 * default changes from accept_multiple=false
540 * to selection_count>0
542 static gboolean
543 convert_pre_v3_multiple( NAObjectProfile *profile )
545 static const gchar *thisfn = "na_object_profile_convert_pre_v3_multiple";
546 gboolean accept_multiple;
547 gchar *selection_count;
549 accept_multiple = na_object_is_multiple( profile );
550 selection_count = g_strdup( accept_multiple ? ">0" : "=1" );
551 na_object_set_selection_count( profile, selection_count );
552 g_debug( "%s: accept_multiple=%s changed to selection_count= %s",
553 thisfn, accept_multiple ? "True":"False", selection_count );
554 g_free( selection_count );
556 return( TRUE );
560 * we may have file=true and dir=false -> only files -> all/allfiles
561 * file=false and dir=true -> only dirs -> inode/directory
562 * file=true and dir=true -> both files and dirs -> all/all
564 * we try to replace this with the corresponding mimetype, but only if
565 * current mimetype is '*' (or * / * or all/all).
567 * note that inode/directory is actually the mimetype provided by Nautilus;
568 * contrarily all/allfiles mimetype has to be checked separately.
570 static gboolean
571 convert_pre_v3_isfiledir( NAObjectProfile *profile )
573 static const gchar *thisfn = "na_object_profile_convert_pre_v3_isfiledir";
574 gboolean is_all_mimetypes;
575 gboolean converted;
576 gboolean isfile, isdir;
577 GSList *mimetypes;
578 GSList *before_list;
579 gchar *before_str, *after_str;
581 converted = FALSE;
583 na_object_check_mimetypes( profile );
584 is_all_mimetypes = na_object_get_all_mimetypes( profile );
585 g_debug( "%s: is_all_mimetypes=%s", thisfn, is_all_mimetypes ? "True":"False" );
587 if( is_all_mimetypes ){
588 converted = TRUE;
589 mimetypes = NULL;
590 before_list = na_object_get_mimetypes( profile );
592 isfile = na_object_is_file( profile );
593 isdir = na_object_is_dir( profile );
595 if( isfile ){
596 if( isdir ){
597 /* both file and dir -> do not modify mimetypes
599 converted = FALSE;
600 } else {
601 /* files only
603 mimetypes = g_slist_prepend( NULL, g_strdup( "all/allfiles" ));
605 } else {
606 if( isdir ){
607 /* dir only
609 mimetypes = g_slist_prepend( NULL, g_strdup( "inode/directory" ));
610 } else {
611 /* not files nor dir: this is an invalid case -> do not modify
612 * mimetypes
614 g_warning( "%s: is_dir=False, is_file=False is invalid", thisfn );
615 converted = FALSE;
619 if( converted ){
620 na_object_set_mimetypes( profile, mimetypes );
622 before_str = na_core_utils_slist_join_at_end( before_list, ";" );
623 after_str = na_core_utils_slist_join_at_end( mimetypes, ";" );
624 g_debug( "%s; mimetypes=[%s] changed to [%s]", thisfn, before_str, after_str );
625 g_free( after_str );
626 g_free( before_str );
629 na_core_utils_slist_free( mimetypes );
630 na_core_utils_slist_free( before_list );
633 return( converted );
636 static void
637 read_done_ending( NAObjectProfile *profile )
639 /* split path+parameters
640 * not done in io-desktop because some actions may have all arguments in path
642 split_path_parameters( profile );
644 /* prepare the context after the reading
646 na_icontext_read_done( NA_ICONTEXT( profile ));
648 /* last, set other action defaults
650 na_factory_object_set_defaults( NA_IFACTORY_OBJECT( profile ));
653 static void
654 split_path_parameters( NAObjectProfile *profile )
656 gchar *path, *parameters;
657 gchar *exec;
659 path = na_object_get_path( profile );
660 parameters = na_object_get_parameters( profile );
661 exec = g_strstrip( g_strdup_printf( "%s %s", path ? path : "", parameters ? parameters : "" ));
662 g_free( parameters );
663 g_free( path );
665 na_core_utils_str_split_first_word( exec, &path, &parameters );
666 g_free( exec );
668 na_object_set_path( profile, path );
669 na_object_set_parameters( profile, parameters );
670 g_free( parameters );
671 g_free( path );
674 static gboolean
675 profile_is_valid( const NAObjectProfile *profile )
677 gboolean is_valid;
679 is_valid = FALSE;
681 if( !profile->private->dispose_has_run ){
683 is_valid = \
684 is_valid_path_parameters( profile ) &&
685 na_icontext_is_valid( NA_ICONTEXT( profile ));
688 return( is_valid );
692 * historical behavior was to not check path nor parameters at all
693 * 2.29.x serie, and up to 2.30.0, have tried to check an actual executable path
694 * but most of already actions only used a command, relying on the PATH env variable
695 * so, starting with 2.30.1, we only check for non empty path+parameters
697 static gboolean
698 is_valid_path_parameters( const NAObjectProfile *profile )
700 gboolean valid;
701 gchar *path, *parameters;
702 gchar *command;
704 path = na_object_get_path( profile );
705 parameters = na_object_get_parameters( profile );
707 command = g_strdup_printf( "%s %s", path, parameters );
708 g_strstrip( command );
710 valid = g_utf8_strlen( command, -1 ) > 0;
712 g_free( command );
713 g_free( parameters );
714 g_free( path );
716 if( !valid ){
717 na_object_debug_invalid( profile, "command" );
720 return( valid );
724 * new_parent is specifically set to be able to allocate a new id for
725 * the current profile into the target parent
727 static gchar *
728 object_id_new_id( const NAObjectId *item, const NAObjectId *new_parent )
730 gchar *id = NULL;
732 g_return_val_if_fail( NA_IS_OBJECT_PROFILE( item ), NULL );
733 g_return_val_if_fail( !new_parent || NA_IS_OBJECT_ACTION( new_parent ), NULL );
735 if( !NA_OBJECT_PROFILE( item )->private->dispose_has_run ){
737 if( new_parent ){
738 id = na_object_action_get_new_profile_name( NA_OBJECT_ACTION( new_parent ));
742 return( id );
746 * na_object_profile_new:
748 * Allocates a new profile.
750 * Returns: the newly allocated #NAObjectProfile profile.
752 * Since: 2.30
754 NAObjectProfile *
755 na_object_profile_new( void )
757 NAObjectProfile *profile;
759 profile = g_object_new( NA_OBJECT_PROFILE_TYPE, NULL );
761 return( profile );
765 * na_object_profile_new_with_defaults:
767 * Allocates a new profile, and set default values.
769 * Returns: the newly allocated #NAObjectProfile profile.
771 * Since: 2.30
773 NAObjectProfile *
774 na_object_profile_new_with_defaults( void )
776 NAObjectProfile *profile = na_object_profile_new();
777 na_object_set_id( profile, "profile-zero" );
778 /* i18n: label for the default profile */
779 na_object_set_label( profile, _( "Default profile" ));
780 na_factory_object_set_defaults( NA_IFACTORY_OBJECT( profile ));
782 return( profile );
786 * na_object_profile_convert_v2_to_last:
787 * @profile: the #NAObjectProfile profile to be converted.
789 * Converts to v3 a @profile which has just been created from a pre-v2 action.
791 * Since: 2.30
793 void
794 na_object_profile_convert_v2_to_last( NAObjectProfile *profile )
796 NAObjectAction *action;
797 guint iversion;
798 gboolean parms_converted, multiple_converted, isfiledir_converted;
800 g_return_if_fail( NA_IS_OBJECT_PROFILE( profile ));
802 action = NA_OBJECT_ACTION( na_object_get_parent( profile ));
803 iversion = na_object_get_iversion( action );
804 g_return_if_fail( iversion < 3 );
806 parms_converted = convert_pre_v3_parameters( profile );
807 multiple_converted = convert_pre_v3_multiple( profile );
808 isfiledir_converted = convert_pre_v3_isfiledir( profile );
810 if( parms_converted || multiple_converted || isfiledir_converted ){
811 na_object_set_iversion( action, 3 );
814 read_done_ending( profile );