Set Nautilus-Actions as being the actual official product name
[nautilus-actions.git] / src / io-desktop / nadp-reader.c
blobe8c50e5bb4aa1a4b55dbd781d8934eeac7df57f1
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 <stdlib.h>
36 #include <string.h>
38 #include <api/na-core-utils.h>
39 #include <api/na-data-types.h>
40 #include <api/na-ifactory-object-data.h>
41 #include <api/na-ifactory-provider.h>
42 #include <api/na-object-api.h>
44 #include "nadp-desktop-provider.h"
45 #include "nadp-keys.h"
46 #include "nadp-reader.h"
47 #include "nadp-utils.h"
48 #include "nadp-xdg-dirs.h"
50 typedef struct {
51 gchar *path;
52 gchar *id;
54 DesktopPath;
56 /* the structure passed as reader data to NAIFactoryObject
58 typedef struct {
59 NadpDesktopFile *ndf;
60 NAObjectAction *action;
62 NadpReaderData;
64 static GList *get_list_of_desktop_paths( NadpDesktopProvider *provider, GSList **mesages );
65 static void get_list_of_desktop_files( const NadpDesktopProvider *provider, GList **files, const gchar *dir, GSList **messages );
66 static gboolean is_already_loaded( const NadpDesktopProvider *provider, GList *files, const gchar *desktop_id );
67 static GList *desktop_path_from_id( const NadpDesktopProvider *provider, GList *files, const gchar *dir, const gchar *id );
68 static NAIFactoryObject *item_from_desktop_path( const NadpDesktopProvider *provider, DesktopPath *dps, GSList **messages );
69 static NAIFactoryObject *item_from_desktop_file( const NadpDesktopProvider *provider, NadpDesktopFile *ndf, GSList **messages );
70 static void desktop_weak_notify( NadpDesktopFile *ndf, GObject *item );
71 static void free_desktop_paths( GList *paths );
73 static void read_start_read_subitems_key( const NAIFactoryProvider *provider, NAObjectItem *item, NadpReaderData *reader_data, GSList **messages );
74 static void read_start_profile_attach_profile( const NAIFactoryProvider *provider, NAObjectProfile *profile, NadpReaderData *reader_data, GSList **messages );
76 static gboolean read_done_item_is_writable( const NAIFactoryProvider *provider, NAObjectItem *item, NadpReaderData *reader_data, GSList **messages );
77 static void read_done_action_read_profiles( const NAIFactoryProvider *provider, NAObjectAction *action, NadpReaderData *data, GSList **messages );
78 static void read_done_action_load_profile( const NAIFactoryProvider *provider, NadpReaderData *reader_data, const gchar *profile_id, GSList **messages );
81 * Returns an unordered list of NAIFactoryObject-derived objects
83 * This is implementation of NAIIOProvider::read_items method
85 GList *
86 nadp_iio_provider_read_items( const NAIIOProvider *provider, GSList **messages )
88 static const gchar *thisfn = "nadp_iio_provider_read_items";
89 GList *items;
90 GList *desktop_paths, *ip;
91 NAIFactoryObject *item;
93 g_debug( "%s: provider=%p (%s), messages=%p",
94 thisfn, ( void * ) provider, G_OBJECT_TYPE_NAME( provider ), ( void * ) messages );
96 g_return_val_if_fail( NA_IS_IIO_PROVIDER( provider ), NULL );
98 items = NULL;
99 nadp_desktop_provider_release_monitors( NADP_DESKTOP_PROVIDER( provider ));
101 desktop_paths = get_list_of_desktop_paths( NADP_DESKTOP_PROVIDER( provider ), messages );
102 for( ip = desktop_paths ; ip ; ip = ip->next ){
104 item = item_from_desktop_path( NADP_DESKTOP_PROVIDER( provider ), ( DesktopPath * ) ip->data, messages );
106 if( item ){
107 items = g_list_prepend( items, item );
111 free_desktop_paths( desktop_paths );
113 g_debug( "%s: count=%d", thisfn, g_list_length( items ));
114 return( items );
118 * returns a list of DesktopPath items
120 * we get the ordered list of XDG_DATA_DIRS, and the ordered list of
121 * subdirs to add; then for each item of each list, we search for
122 * .desktop files in the resulted built path
124 * the returned list is so a list of DesktopPath struct, in
125 * the ordered of preference (most preferred first)
127 static GList *
128 get_list_of_desktop_paths( NadpDesktopProvider *provider, GSList **messages )
130 GList *files;
131 GSList *xdg_dirs, *idir;
132 GSList *subdirs, *isub;
133 gchar *dir;
135 files = NULL;
136 xdg_dirs = nadp_xdg_dirs_get_data_dirs();
137 subdirs = na_core_utils_slist_from_split( NADP_DESKTOP_PROVIDER_SUBDIRS, G_SEARCHPATH_SEPARATOR_S );
139 /* explore each directory from XDG_DATA_DIRS
141 for( idir = xdg_dirs ; idir ; idir = idir->next ){
143 /* explore each N-A candidate subdirectory for each XDG dir
145 for( isub = subdirs ; isub ; isub = isub->next ){
147 dir = g_build_filename(( gchar * ) idir->data, ( gchar * ) isub->data, NULL );
148 nadp_desktop_provider_add_monitor( provider, dir );
149 get_list_of_desktop_files( provider, &files, dir, messages );
150 g_free( dir );
154 na_core_utils_slist_free( subdirs );
155 na_core_utils_slist_free( xdg_dirs );
157 return( files );
161 * scans the directory for .desktop files
162 * only adds to the list those which have not been yet loaded
164 static void
165 get_list_of_desktop_files( const NadpDesktopProvider *provider, GList **files, const gchar *dir, GSList **messages )
167 static const gchar *thisfn = "nadp_reader_get_list_of_desktop_files";
168 GDir *dir_handle;
169 GError *error;
170 const gchar *name;
171 gchar *desktop_id;
173 g_debug( "%s: provider=%p, files=%p (count=%d), dir=%s, messages=%p",
174 thisfn, ( void * ) provider, ( void * ) files, g_list_length( *files ), dir, ( void * ) messages );
176 error = NULL;
177 dir_handle = NULL;
179 /* do not warn when the directory just doesn't exist
181 if( g_file_test( dir, G_FILE_TEST_IS_DIR )){
182 dir_handle = g_dir_open( dir, 0, &error );
183 if( error ){
184 g_warning( "%s: %s: %s", thisfn, dir, error->message );
185 g_error_free( error );
186 goto close_dir_handle;
188 } else {
189 g_debug( "%s: %s: directory doesn't exist", thisfn, dir );
192 if( dir_handle ){
193 while(( name = g_dir_read_name( dir_handle ))){
194 if( g_str_has_suffix( name, NADP_DESKTOP_FILE_SUFFIX )){
195 desktop_id = na_core_utils_str_remove_suffix( name, NADP_DESKTOP_FILE_SUFFIX );
196 if( !is_already_loaded( provider, *files, desktop_id )){
197 *files = desktop_path_from_id( provider, *files, dir, desktop_id );
199 g_free( desktop_id );
204 close_dir_handle:
205 if( dir_handle ){
206 g_dir_close( dir_handle );
210 static gboolean
211 is_already_loaded( const NadpDesktopProvider *provider, GList *files, const gchar *desktop_id )
213 gboolean found;
214 GList *ip;
215 DesktopPath *dps;
217 found = FALSE;
218 for( ip = files ; ip && !found ; ip = ip->next ){
219 dps = ( DesktopPath * ) ip->data;
220 if( !g_ascii_strcasecmp( dps->id, desktop_id )){
221 found = TRUE;
225 return( found );
228 static GList *
229 desktop_path_from_id( const NadpDesktopProvider *provider, GList *files, const gchar *dir, const gchar *id )
231 DesktopPath *dps;
232 gchar *bname;
233 GList *list;
235 dps = g_new0( DesktopPath, 1 );
237 bname = g_strdup_printf( "%s%s", id, NADP_DESKTOP_FILE_SUFFIX );
238 dps->path = g_build_filename( dir, bname, NULL );
239 g_free( bname );
241 dps->id = g_strdup( id );
243 list = g_list_prepend( files, dps );
245 return( list );
249 * Returns a newly allocated NAIFactoryObject-derived object, initialized
250 * from the .desktop file pointed to by DesktopPath struct
252 static NAIFactoryObject *
253 item_from_desktop_path( const NadpDesktopProvider *provider, DesktopPath *dps, GSList **messages )
255 NadpDesktopFile *ndf;
257 ndf = nadp_desktop_file_new_from_path( dps->path );
258 if( !ndf ){
259 return( NULL );
262 return( item_from_desktop_file( provider, ndf, messages ));
266 * Returns a newly allocated NAIFactoryObject-derived object, initialized
267 * from the .desktop file
269 static NAIFactoryObject *
270 item_from_desktop_file( const NadpDesktopProvider *provider, NadpDesktopFile *ndf, GSList **messages )
272 static const gchar *thisfn = "nadp_reader_item_from_desktop_file";
273 NAIFactoryObject *item;
274 gchar *type;
275 NadpReaderData *reader_data;
276 gchar *id;
278 item = NULL;
279 type = nadp_desktop_file_get_file_type( ndf );
281 if( !type || !strlen( type ) || !strcmp( type, NADP_VALUE_TYPE_ACTION )){
282 item = NA_IFACTORY_OBJECT( na_object_action_new());
284 } else if( !strcmp( type, NADP_VALUE_TYPE_MENU )){
285 item = NA_IFACTORY_OBJECT( na_object_menu_new());
287 } else {
288 g_warning( "%s: unknown type=%s", thisfn, type );
291 if( item ){
292 id = nadp_desktop_file_get_id( ndf );
293 na_object_set_id( item, id );
294 g_free( id );
296 reader_data = g_new0( NadpReaderData, 1 );
297 reader_data->ndf = ndf;
299 na_ifactory_provider_read_item( NA_IFACTORY_PROVIDER( provider ), reader_data, item, messages );
301 na_object_set_provider_data( item, ndf );
302 g_object_weak_ref( G_OBJECT( item ), ( GWeakNotify ) desktop_weak_notify, ndf );
304 g_free( reader_data );
307 return( item );
310 static void
311 desktop_weak_notify( NadpDesktopFile *ndf, GObject *item )
313 static const gchar *thisfn = "nadp_reader_desktop_weak_notify";
315 g_debug( "%s: ndf=%p (%s), item=%p (%s)",
316 thisfn, ( void * ) ndf, G_OBJECT_TYPE_NAME( ndf ),
317 ( void * ) item, G_OBJECT_TYPE_NAME( item ));
319 g_object_unref( ndf );
322 static void
323 free_desktop_paths( GList *paths )
325 GList *ip;
326 DesktopPath *dps;
328 for( ip = paths ; ip ; ip = ip->next ){
329 dps = ( DesktopPath * ) ip->data;
330 g_free( dps->path );
331 g_free( dps->id );
332 g_free( dps );
335 g_list_free( paths );
339 * nadp_reader_iimporter_import_from_uri:
340 * @instance: the #NAIImporter provider.
341 * @parms: a #NAIImporterUriParms structure.
343 * Imports an item.
345 * Returns: the import operation code.
347 * As soon as we have a valid .desktop file, we are most probably willing
348 * to successfully import an action or a menu of it.
350 * GLib does not have any primitive to load a key file from an uri.
351 * So we have to load the file into memory, and then try to load the key
352 * file from the memory data.
354 guint
355 nadp_reader_iimporter_import_from_uri( const NAIImporter *instance, NAIImporterImportFromUriParms *parms )
357 static const gchar *thisfn = "nadp_reader_iimporter_import_from_uri";
358 guint code;
359 NadpDesktopFile *ndf;
360 NAIImporterManageImportModeParms manage_parms;
362 g_debug( "%s: instance=%p, parms=%p", thisfn, ( void * ) instance, ( void * ) parms );
364 g_return_val_if_fail( NA_IS_IIMPORTER( instance ), IMPORTER_CODE_PROGRAM_ERROR );
365 g_return_val_if_fail( NADP_IS_DESKTOP_PROVIDER( instance ), IMPORTER_CODE_PROGRAM_ERROR );
367 code = IMPORTER_CODE_NOT_WILLING_TO;
369 ndf = nadp_desktop_file_new_from_uri( parms->uri );
370 if( ndf ){
371 parms->exist = FALSE;
372 parms->import_mode = IMPORTER_MODE_NO_IMPORT;
373 parms->imported = ( NAObjectItem * ) item_from_desktop_file(
374 ( const NadpDesktopProvider * ) NADP_DESKTOP_PROVIDER( instance ),
375 ndf, &parms->messages );
377 if( parms->imported ){
378 code = IMPORTER_CODE_OK;
379 g_return_val_if_fail( NA_IS_OBJECT_ITEM( parms->imported ), IMPORTER_CODE_NOT_WILLING_TO );
381 /* remove the weak reference on desktop file set by 'item_from_desktop_file'
382 * as we must consider this #NAObjectItem as a new one
384 na_object_set_provider_data( parms->imported, NULL );
385 g_object_weak_unref( G_OBJECT( parms->imported ), ( GWeakNotify ) desktop_weak_notify, ndf );
386 g_object_unref( ndf );
388 manage_parms.version = 1;
389 manage_parms.imported = parms->imported;
390 manage_parms.check_fn = parms->check_fn;
391 manage_parms.check_fn_data = parms->check_fn_data;
392 manage_parms.ask_fn = parms->ask_fn;
393 manage_parms.ask_fn_data = parms->ask_fn_data;
394 manage_parms.asked_mode = parms->asked_mode;
395 manage_parms.messages = parms->messages;
397 code = na_iimporter_manage_import_mode( &manage_parms );
399 parms->exist = manage_parms.exist;
400 parms->import_mode = manage_parms.import_mode;
403 if( code != IMPORTER_CODE_OK ){
404 if( parms->imported ){
405 g_object_unref( parms->imported );
406 parms->imported = NULL;
411 return( code );
415 * at this time, the object has been allocated and its id has been set
416 * read here the subitems key, which may be 'Profiles' or 'ItemsList'
417 * depending of the exact class of the NAObjectItem
419 void
420 nadp_reader_ifactory_provider_read_start( const NAIFactoryProvider *reader, void *reader_data, const NAIFactoryObject *serializable, GSList **messages )
422 static const gchar *thisfn = "nadp_reader_ifactory_provider_read_start";
424 g_return_if_fail( NA_IS_IFACTORY_PROVIDER( reader ));
425 g_return_if_fail( NADP_IS_DESKTOP_PROVIDER( reader ));
426 g_return_if_fail( NA_IS_IFACTORY_OBJECT( serializable ));
428 if( !NADP_DESKTOP_PROVIDER( reader )->private->dispose_has_run ){
430 g_debug( "%s: reader=%p (%s), reader_data=%p, serializable=%p (%s), messages=%p",
431 thisfn,
432 ( void * ) reader, G_OBJECT_TYPE_NAME( reader ),
433 ( void * ) reader_data,
434 ( void * ) serializable, G_OBJECT_TYPE_NAME( serializable ),
435 ( void * ) messages );
437 if( NA_IS_OBJECT_ITEM( serializable )){
438 read_start_read_subitems_key( reader, NA_OBJECT_ITEM( serializable ), ( NadpReaderData * ) reader_data, messages );
439 na_object_set_iversion( serializable, 3 );
442 if( NA_IS_OBJECT_PROFILE( serializable )){
443 read_start_profile_attach_profile( reader, NA_OBJECT_PROFILE( serializable ), ( NadpReaderData * ) reader_data, messages );
448 static void
449 read_start_read_subitems_key( const NAIFactoryProvider *provider, NAObjectItem *item, NadpReaderData *reader_data, GSList **messages )
451 GSList *subitems;
452 gboolean key_found;
454 subitems = nadp_desktop_file_get_string_list( reader_data->ndf,
455 NADP_GROUP_DESKTOP,
456 NA_IS_OBJECT_ACTION( item ) ? NADP_KEY_PROFILES : NADP_KEY_ITEMS_LIST,
457 &key_found,
458 NULL );
460 if( key_found ){
461 na_object_set_items_slist( item, subitems );
464 na_core_utils_slist_free( subitems );
467 static void
468 read_start_profile_attach_profile( const NAIFactoryProvider *provider, NAObjectProfile *profile, NadpReaderData *reader_data, GSList **messages )
470 na_object_attach_profile( reader_data->action, profile );
474 * reading any data from a desktop file requires:
475 * - a NadpDesktopFile object which has been initialized with the .desktop file
476 * -> has been attached to the NAObjectItem in get_item() above
477 * - the data type (+ reading default value)
478 * - group and key names
480 * Returns: NULL if the key has not been found
481 * letting the caller deal with default values
483 NADataBoxed *
484 nadp_reader_ifactory_provider_read_data( const NAIFactoryProvider *reader, void *reader_data, const NAIFactoryObject *object, const NADataDef *def, GSList **messages )
486 static const gchar *thisfn = "nadp_reader_ifactory_provider_read_value";
487 NADataBoxed *boxed;
488 gboolean found;
489 NadpReaderData *nrd;
490 gchar *group, *id;
491 gchar *msg;
492 gchar *str_value;
493 gboolean bool_value;
494 GSList *slist_value;
495 guint uint_value;
497 /*g_debug( "%s: reader=%p (%s), reader_data=%p, def=%p (%s), messages=%p",
498 thisfn,
499 ( void * ) reader, G_OBJECT_TYPE_NAME( reader ),
500 ( void * ) reader_data,
501 ( void * ) def, def->name,
502 ( void * ) messages );*/
504 g_return_val_if_fail( NA_IS_IFACTORY_PROVIDER( reader ), NULL );
505 g_return_val_if_fail( NADP_IS_DESKTOP_PROVIDER( reader ), NULL );
506 g_return_val_if_fail( NA_IS_IFACTORY_OBJECT( object ), NULL );
508 boxed = NULL;
510 if( !NADP_DESKTOP_PROVIDER( reader )->private->dispose_has_run ){
512 nrd = ( NadpReaderData * ) reader_data;
513 g_return_val_if_fail( NADP_IS_DESKTOP_FILE( nrd->ndf ), NULL );
515 if( def->desktop_entry ){
517 if( NA_IS_OBJECT_ITEM( object )){
518 group = g_strdup( NADP_GROUP_DESKTOP );
520 } else {
521 g_return_val_if_fail( NA_IS_OBJECT_PROFILE( object ), NULL );
522 id = na_object_get_id( object );
523 group = g_strdup_printf( "%s %s", NADP_GROUP_PROFILE, id );
524 g_free( id );
527 switch( def->type ){
529 case NAFD_TYPE_LOCALE_STRING:
530 str_value = nadp_desktop_file_get_locale_string( nrd->ndf, group, def->desktop_entry, &found, def->default_value );
531 if( found ){
532 boxed = na_data_boxed_new( def );
533 na_data_boxed_set_from_void( boxed, str_value );
535 g_free( str_value );
536 break;
538 case NAFD_TYPE_STRING:
539 str_value = nadp_desktop_file_get_string( nrd->ndf, group, def->desktop_entry, &found, def->default_value );
540 if( found ){
541 boxed = na_data_boxed_new( def );
542 na_data_boxed_set_from_void( boxed, str_value );
544 g_free( str_value );
545 break;
547 case NAFD_TYPE_BOOLEAN:
548 bool_value = nadp_desktop_file_get_boolean( nrd->ndf, group, def->desktop_entry, &found, na_core_utils_boolean_from_string( def->default_value ));
549 g_debug( "%s: name=%s, found=%s, value=%s", thisfn, def->name, found ? "True":"False", bool_value ? "True":"False" );
550 if( found ){
551 boxed = na_data_boxed_new( def );
552 na_data_boxed_set_from_void( boxed, GUINT_TO_POINTER( bool_value ));
554 break;
556 case NAFD_TYPE_STRING_LIST:
557 slist_value = nadp_desktop_file_get_string_list( nrd->ndf, group, def->desktop_entry, &found, def->default_value );
558 if( found ){
559 boxed = na_data_boxed_new( def );
560 na_data_boxed_set_from_void( boxed, slist_value );
562 na_core_utils_slist_free( slist_value );
563 break;
565 case NAFD_TYPE_UINT:
566 uint_value = nadp_desktop_file_get_uint( nrd->ndf, group, def->desktop_entry, &found, atoi( def->default_value ));
567 if( found ){
568 boxed = na_data_boxed_new( def );
569 na_data_boxed_set_from_void( boxed, GUINT_TO_POINTER( uint_value ));
571 break;
573 default:
574 msg = g_strdup_printf( "%s: %d: invalid data type.", thisfn, def->type );
575 g_warning( "%s", msg );
576 *messages = g_slist_append( *messages, msg );
579 g_free( group );
583 return( boxed );
587 * called when each NAIFactoryObject object has been readen
589 void
590 nadp_reader_ifactory_provider_read_done( const NAIFactoryProvider *reader, void *reader_data, const NAIFactoryObject *serializable, GSList **messages )
592 static const gchar *thisfn = "nadp_reader_ifactory_provider_read_done";
593 gboolean writable;
595 g_return_if_fail( NA_IS_IFACTORY_PROVIDER( reader ));
596 g_return_if_fail( NADP_IS_DESKTOP_PROVIDER( reader ));
597 g_return_if_fail( NA_IS_IFACTORY_OBJECT( serializable ));
599 if( !NADP_DESKTOP_PROVIDER( reader )->private->dispose_has_run ){
601 g_debug( "%s: reader=%p (%s), reader_data=%p, serializable=%p (%s), messages=%p",
602 thisfn,
603 ( void * ) reader, G_OBJECT_TYPE_NAME( reader ),
604 ( void * ) reader_data,
605 ( void * ) serializable, G_OBJECT_TYPE_NAME( serializable ),
606 ( void * ) messages );
608 if( NA_IS_OBJECT_ITEM( serializable )){
609 writable = read_done_item_is_writable( reader, NA_OBJECT_ITEM( serializable ), ( NadpReaderData * ) reader_data, messages );
610 na_object_set_readonly( serializable, !writable );
613 if( NA_IS_OBJECT_ACTION( serializable )){
614 read_done_action_read_profiles( reader, NA_OBJECT_ACTION( serializable ), ( NadpReaderData * ) reader_data, messages );
617 g_debug( "%s: quitting for %s at %p", thisfn, G_OBJECT_TYPE_NAME( serializable ), ( void * ) serializable );
621 static gboolean
622 read_done_item_is_writable( const NAIFactoryProvider *provider, NAObjectItem *item, NadpReaderData *reader_data, GSList **messages )
624 NadpDesktopFile *ndf;
625 gchar *uri;
626 gboolean writable;
628 ndf = reader_data->ndf;
629 uri = nadp_desktop_file_get_key_file_uri( ndf );
630 writable = nadp_utils_uri_is_writable( uri );
631 g_free( uri );
633 return( writable );
637 * read and attach profiles in the specified order
638 * profiles which may exist in .desktop files, but are not referenced
639 * in the 'Profiles' string list are just ignored
641 static void
642 read_done_action_read_profiles( const NAIFactoryProvider *provider, NAObjectAction *action, NadpReaderData *reader_data, GSList **messages )
644 GSList *order;
645 GSList *ip;
646 gchar *profile_id;
647 NAObjectId *found;
649 reader_data->action = action;
650 order = na_object_get_items_slist( action );
652 for( ip = order ; ip ; ip = ip->next ){
653 profile_id = ( gchar * ) ip->data;
654 found = na_object_get_item( action, profile_id );
655 if( !found ){
656 read_done_action_load_profile( provider, reader_data, profile_id, messages );
660 na_core_utils_slist_free( order );
663 static void
664 read_done_action_load_profile( const NAIFactoryProvider *provider, NadpReaderData *reader_data, const gchar *profile_id, GSList **messages )
666 NAObjectProfile *profile;
668 g_debug( "nadp_reader_read_done_action_load_profile: loading profile=%s", profile_id );
670 profile = na_object_profile_new();
671 na_object_set_id( profile, profile_id );
673 na_ifactory_provider_read_item(
674 NA_IFACTORY_PROVIDER( provider ),
675 reader_data,
676 NA_IFACTORY_OBJECT( profile ),
677 messages );