NadpDesktopFile: do not try to import empty or not DES-EMA files
[nautilus-actions.git] / src / io-desktop / nadp-reader.c
blobf2037df7e2b654b33964d4fdc7cb566814461085
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 );
108 na_object_dump( item );
112 free_desktop_paths( desktop_paths );
114 g_debug( "%s: count=%d", thisfn, g_list_length( items ));
115 return( items );
119 * returns a list of DesktopPath items
121 * we get the ordered list of XDG_DATA_DIRS, and the ordered list of
122 * subdirs to add; then for each item of each list, we search for
123 * .desktop files in the resulted built path
125 * the returned list is so a list of DesktopPath struct, in
126 * the ordered of preference (most preferred first)
128 static GList *
129 get_list_of_desktop_paths( NadpDesktopProvider *provider, GSList **messages )
131 GList *files;
132 GSList *xdg_dirs, *idir;
133 GSList *subdirs, *isub;
134 gchar *dir;
136 files = NULL;
137 xdg_dirs = nadp_xdg_dirs_get_data_dirs();
138 subdirs = na_core_utils_slist_from_split( NADP_DESKTOP_PROVIDER_SUBDIRS, G_SEARCHPATH_SEPARATOR_S );
140 /* explore each directory from XDG_DATA_DIRS
142 for( idir = xdg_dirs ; idir ; idir = idir->next ){
144 /* explore each N-A candidate subdirectory for each XDG dir
146 for( isub = subdirs ; isub ; isub = isub->next ){
148 dir = g_build_filename(( gchar * ) idir->data, ( gchar * ) isub->data, NULL );
149 nadp_desktop_provider_add_monitor( provider, dir );
150 get_list_of_desktop_files( provider, &files, dir, messages );
151 g_free( dir );
155 na_core_utils_slist_free( subdirs );
156 na_core_utils_slist_free( xdg_dirs );
158 return( files );
162 * scans the directory for .desktop files
163 * only adds to the list those which have not been yet loaded
165 static void
166 get_list_of_desktop_files( const NadpDesktopProvider *provider, GList **files, const gchar *dir, GSList **messages )
168 static const gchar *thisfn = "nadp_reader_get_list_of_desktop_files";
169 GDir *dir_handle;
170 GError *error;
171 const gchar *name;
172 gchar *desktop_id;
174 g_debug( "%s: provider=%p, files=%p (count=%d), dir=%s, messages=%p",
175 thisfn, ( void * ) provider, ( void * ) files, g_list_length( *files ), dir, ( void * ) messages );
177 error = NULL;
178 dir_handle = NULL;
180 /* do not warn when the directory just doesn't exist
182 if( g_file_test( dir, G_FILE_TEST_IS_DIR )){
183 dir_handle = g_dir_open( dir, 0, &error );
184 if( error ){
185 g_warning( "%s: %s: %s", thisfn, dir, error->message );
186 g_error_free( error );
187 goto close_dir_handle;
189 } else {
190 g_debug( "%s: %s: directory doesn't exist", thisfn, dir );
193 if( dir_handle ){
194 while(( name = g_dir_read_name( dir_handle ))){
195 if( g_str_has_suffix( name, NADP_DESKTOP_FILE_SUFFIX )){
196 desktop_id = na_core_utils_str_remove_suffix( name, NADP_DESKTOP_FILE_SUFFIX );
197 if( !is_already_loaded( provider, *files, desktop_id )){
198 *files = desktop_path_from_id( provider, *files, dir, desktop_id );
200 g_free( desktop_id );
205 close_dir_handle:
206 if( dir_handle ){
207 g_dir_close( dir_handle );
211 static gboolean
212 is_already_loaded( const NadpDesktopProvider *provider, GList *files, const gchar *desktop_id )
214 gboolean found;
215 GList *ip;
216 DesktopPath *dps;
218 found = FALSE;
219 for( ip = files ; ip && !found ; ip = ip->next ){
220 dps = ( DesktopPath * ) ip->data;
221 if( !g_ascii_strcasecmp( dps->id, desktop_id )){
222 found = TRUE;
226 return( found );
229 static GList *
230 desktop_path_from_id( const NadpDesktopProvider *provider, GList *files, const gchar *dir, const gchar *id )
232 DesktopPath *dps;
233 gchar *bname;
234 GList *list;
236 dps = g_new0( DesktopPath, 1 );
238 bname = g_strdup_printf( "%s%s", id, NADP_DESKTOP_FILE_SUFFIX );
239 dps->path = g_build_filename( dir, bname, NULL );
240 g_free( bname );
242 dps->id = g_strdup( id );
244 list = g_list_prepend( files, dps );
246 return( list );
250 * Returns a newly allocated NAIFactoryObject-derived object, initialized
251 * from the .desktop file pointed to by DesktopPath struct
253 static NAIFactoryObject *
254 item_from_desktop_path( const NadpDesktopProvider *provider, DesktopPath *dps, GSList **messages )
256 NadpDesktopFile *ndf;
258 ndf = nadp_desktop_file_new_from_path( dps->path );
259 if( !ndf ){
260 return( NULL );
263 return( item_from_desktop_file( provider, ndf, messages ));
267 * Returns a newly allocated NAIFactoryObject-derived object, initialized
268 * from the .desktop file
270 static NAIFactoryObject *
271 item_from_desktop_file( const NadpDesktopProvider *provider, NadpDesktopFile *ndf, GSList **messages )
273 static const gchar *thisfn = "nadp_reader_item_from_desktop_file";
274 NAIFactoryObject *item;
275 gchar *type;
276 NadpReaderData *reader_data;
277 gchar *id;
279 item = NULL;
280 type = nadp_desktop_file_get_file_type( ndf );
282 if( !strcmp( type, NADP_VALUE_TYPE_ACTION )){
283 item = NA_IFACTORY_OBJECT( na_object_action_new());
285 } else if( !strcmp( type, NADP_VALUE_TYPE_MENU )){
286 item = NA_IFACTORY_OBJECT( na_object_menu_new());
288 } else {
289 g_warning( "%s: unknown type=%s", thisfn, type );
292 if( item ){
293 id = nadp_desktop_file_get_id( ndf );
294 na_object_set_id( item, id );
295 g_free( id );
297 reader_data = g_new0( NadpReaderData, 1 );
298 reader_data->ndf = ndf;
300 na_ifactory_provider_read_item( NA_IFACTORY_PROVIDER( provider ), reader_data, item, messages );
302 na_object_set_provider_data( item, ndf );
303 g_object_weak_ref( G_OBJECT( item ), ( GWeakNotify ) desktop_weak_notify, ndf );
305 g_free( reader_data );
308 return( item );
311 static void
312 desktop_weak_notify( NadpDesktopFile *ndf, GObject *item )
314 static const gchar *thisfn = "nadp_reader_desktop_weak_notify";
316 g_debug( "%s: ndf=%p (%s), item=%p (%s)",
317 thisfn, ( void * ) ndf, G_OBJECT_TYPE_NAME( ndf ),
318 ( void * ) item, G_OBJECT_TYPE_NAME( item ));
320 g_object_unref( ndf );
323 static void
324 free_desktop_paths( GList *paths )
326 GList *ip;
327 DesktopPath *dps;
329 for( ip = paths ; ip ; ip = ip->next ){
330 dps = ( DesktopPath * ) ip->data;
331 g_free( dps->path );
332 g_free( dps->id );
333 g_free( dps );
336 g_list_free( paths );
340 * nadp_reader_iimporter_import_from_uri:
341 * @instance: the #NAIImporter provider.
342 * @parms: a #NAIImporterUriParms structure.
344 * Imports an item.
346 * Returns: the import operation code.
348 * As soon as we have a valid .desktop file, we are most probably willing
349 * to successfully import an action or a menu of it.
351 * GLib does not have any primitive to load a key file from an uri.
352 * So we have to load the file into memory, and then try to load the key
353 * file from the memory data.
355 guint
356 nadp_reader_iimporter_import_from_uri( const NAIImporter *instance, NAIImporterImportFromUriParms *parms )
358 static const gchar *thisfn = "nadp_reader_iimporter_import_from_uri";
359 guint code;
360 NadpDesktopFile *ndf;
361 NAIImporterManageImportModeParms manage_parms;
363 g_debug( "%s: instance=%p, parms=%p", thisfn, ( void * ) instance, ( void * ) parms );
365 g_return_val_if_fail( NA_IS_IIMPORTER( instance ), IMPORTER_CODE_PROGRAM_ERROR );
366 g_return_val_if_fail( NADP_IS_DESKTOP_PROVIDER( instance ), IMPORTER_CODE_PROGRAM_ERROR );
368 code = IMPORTER_CODE_NOT_WILLING_TO;
370 ndf = nadp_desktop_file_new_from_uri( parms->uri );
371 if( ndf ){
372 parms->exist = FALSE;
373 parms->import_mode = IMPORTER_MODE_NO_IMPORT;
374 parms->imported = ( NAObjectItem * ) item_from_desktop_file(
375 ( const NadpDesktopProvider * ) NADP_DESKTOP_PROVIDER( instance ),
376 ndf, &parms->messages );
378 if( parms->imported ){
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;
401 parms->messages = manage_parms.messages;
404 if( code != IMPORTER_CODE_OK ){
405 if( parms->imported ){
406 g_debug( "%s: unreffing imported item %p as na_iimporter_manage_import_mode didn't return IMPORTER_CODE_OK", thisfn, parms->imported );
407 g_object_unref( parms->imported );
408 parms->imported = NULL;
413 return( code );
417 * at this time, the object has been allocated and its id has been set
418 * read here the subitems key, which may be 'Profiles' or 'ItemsList'
419 * depending of the exact class of the NAObjectItem
421 void
422 nadp_reader_ifactory_provider_read_start( const NAIFactoryProvider *reader, void *reader_data, const NAIFactoryObject *serializable, GSList **messages )
424 static const gchar *thisfn = "nadp_reader_ifactory_provider_read_start";
426 g_return_if_fail( NA_IS_IFACTORY_PROVIDER( reader ));
427 g_return_if_fail( NADP_IS_DESKTOP_PROVIDER( reader ));
428 g_return_if_fail( NA_IS_IFACTORY_OBJECT( serializable ));
430 if( !NADP_DESKTOP_PROVIDER( reader )->private->dispose_has_run ){
432 g_debug( "%s: reader=%p (%s), reader_data=%p, serializable=%p (%s), messages=%p",
433 thisfn,
434 ( void * ) reader, G_OBJECT_TYPE_NAME( reader ),
435 ( void * ) reader_data,
436 ( void * ) serializable, G_OBJECT_TYPE_NAME( serializable ),
437 ( void * ) messages );
439 if( NA_IS_OBJECT_ITEM( serializable )){
440 read_start_read_subitems_key( reader, NA_OBJECT_ITEM( serializable ), ( NadpReaderData * ) reader_data, messages );
441 na_object_set_iversion( serializable, 3 );
444 if( NA_IS_OBJECT_PROFILE( serializable )){
445 read_start_profile_attach_profile( reader, NA_OBJECT_PROFILE( serializable ), ( NadpReaderData * ) reader_data, messages );
450 static void
451 read_start_read_subitems_key( const NAIFactoryProvider *provider, NAObjectItem *item, NadpReaderData *reader_data, GSList **messages )
453 GSList *subitems;
454 gboolean key_found;
456 subitems = nadp_desktop_file_get_string_list( reader_data->ndf,
457 NADP_GROUP_DESKTOP,
458 NA_IS_OBJECT_ACTION( item ) ? NADP_KEY_PROFILES : NADP_KEY_ITEMS_LIST,
459 &key_found,
460 NULL );
462 if( key_found ){
463 na_object_set_items_slist( item, subitems );
466 na_core_utils_slist_free( subitems );
469 static void
470 read_start_profile_attach_profile( const NAIFactoryProvider *provider, NAObjectProfile *profile, NadpReaderData *reader_data, GSList **messages )
472 na_object_attach_profile( reader_data->action, profile );
476 * reading any data from a desktop file requires:
477 * - a NadpDesktopFile object which has been initialized with the .desktop file
478 * -> has been attached to the NAObjectItem in get_item() above
479 * - the data type (+ reading default value)
480 * - group and key names
482 * Returns: NULL if the key has not been found
483 * letting the caller deal with default values
485 NADataBoxed *
486 nadp_reader_ifactory_provider_read_data( const NAIFactoryProvider *reader, void *reader_data, const NAIFactoryObject *object, const NADataDef *def, GSList **messages )
488 static const gchar *thisfn = "nadp_reader_ifactory_provider_read_data";
489 NADataBoxed *boxed;
490 gboolean found;
491 NadpReaderData *nrd;
492 gchar *group, *id;
493 gchar *msg;
494 gchar *str_value;
495 gboolean bool_value;
496 GSList *slist_value;
497 guint uint_value;
499 g_return_val_if_fail( NA_IS_IFACTORY_PROVIDER( reader ), NULL );
500 g_return_val_if_fail( NADP_IS_DESKTOP_PROVIDER( reader ), NULL );
501 g_return_val_if_fail( NA_IS_IFACTORY_OBJECT( object ), NULL );
503 boxed = NULL;
505 if( !NADP_DESKTOP_PROVIDER( reader )->private->dispose_has_run ){
507 nrd = ( NadpReaderData * ) reader_data;
508 g_return_val_if_fail( NADP_IS_DESKTOP_FILE( nrd->ndf ), NULL );
510 if( def->desktop_entry ){
512 if( NA_IS_OBJECT_ITEM( object )){
513 group = g_strdup( NADP_GROUP_DESKTOP );
515 } else {
516 g_return_val_if_fail( NA_IS_OBJECT_PROFILE( object ), NULL );
517 id = na_object_get_id( object );
518 group = g_strdup_printf( "%s %s", NADP_GROUP_PROFILE, id );
519 g_free( id );
522 switch( def->type ){
524 case NA_DATA_TYPE_LOCALE_STRING:
525 str_value = nadp_desktop_file_get_locale_string( nrd->ndf, group, def->desktop_entry, &found, def->default_value );
526 if( found ){
527 boxed = na_data_boxed_new( def );
528 na_boxed_set_from_void( NA_BOXED( boxed ), str_value );
530 g_free( str_value );
531 break;
533 case NA_DATA_TYPE_STRING:
534 str_value = nadp_desktop_file_get_string( nrd->ndf, group, def->desktop_entry, &found, def->default_value );
535 if( found ){
536 boxed = na_data_boxed_new( def );
537 na_boxed_set_from_void( NA_BOXED( boxed ), str_value );
539 g_free( str_value );
540 break;
542 case NA_DATA_TYPE_BOOLEAN:
543 bool_value = nadp_desktop_file_get_boolean( nrd->ndf, group, def->desktop_entry, &found, na_core_utils_boolean_from_string( def->default_value ));
544 if( found ){
545 boxed = na_data_boxed_new( def );
546 na_boxed_set_from_void( NA_BOXED( boxed ), GUINT_TO_POINTER( bool_value ));
548 break;
550 case NA_DATA_TYPE_STRING_LIST:
551 slist_value = nadp_desktop_file_get_string_list( nrd->ndf, group, def->desktop_entry, &found, def->default_value );
552 if( found ){
553 boxed = na_data_boxed_new( def );
554 na_boxed_set_from_void( NA_BOXED( boxed ), slist_value );
556 na_core_utils_slist_free( slist_value );
557 break;
559 case NA_DATA_TYPE_UINT:
560 uint_value = nadp_desktop_file_get_uint( nrd->ndf, group, def->desktop_entry, &found, atoi( def->default_value ));
561 if( found ){
562 boxed = na_data_boxed_new( def );
563 na_boxed_set_from_void( NA_BOXED( boxed ), GUINT_TO_POINTER( uint_value ));
565 break;
567 default:
568 msg = g_strdup_printf( "%s: %d: invalid data type.", thisfn, def->type );
569 g_warning( "%s", msg );
570 *messages = g_slist_append( *messages, msg );
573 g_free( group );
577 return( boxed );
581 * called when each NAIFactoryObject object has been read
583 void
584 nadp_reader_ifactory_provider_read_done( const NAIFactoryProvider *reader, void *reader_data, const NAIFactoryObject *serializable, GSList **messages )
586 static const gchar *thisfn = "nadp_reader_ifactory_provider_read_done";
587 gboolean writable;
589 g_return_if_fail( NA_IS_IFACTORY_PROVIDER( reader ));
590 g_return_if_fail( NADP_IS_DESKTOP_PROVIDER( reader ));
591 g_return_if_fail( NA_IS_IFACTORY_OBJECT( serializable ));
593 if( !NADP_DESKTOP_PROVIDER( reader )->private->dispose_has_run ){
595 g_debug( "%s: reader=%p (%s), reader_data=%p, serializable=%p (%s), messages=%p",
596 thisfn,
597 ( void * ) reader, G_OBJECT_TYPE_NAME( reader ),
598 ( void * ) reader_data,
599 ( void * ) serializable, G_OBJECT_TYPE_NAME( serializable ),
600 ( void * ) messages );
602 if( NA_IS_OBJECT_ITEM( serializable )){
603 writable = read_done_item_is_writable( reader, NA_OBJECT_ITEM( serializable ), ( NadpReaderData * ) reader_data, messages );
604 na_object_set_readonly( serializable, !writable );
607 if( NA_IS_OBJECT_ACTION( serializable )){
608 read_done_action_read_profiles( reader, NA_OBJECT_ACTION( serializable ), ( NadpReaderData * ) reader_data, messages );
611 g_debug( "%s: quitting for %s at %p", thisfn, G_OBJECT_TYPE_NAME( serializable ), ( void * ) serializable );
615 static gboolean
616 read_done_item_is_writable( const NAIFactoryProvider *provider, NAObjectItem *item, NadpReaderData *reader_data, GSList **messages )
618 NadpDesktopFile *ndf;
619 gchar *uri;
620 gboolean writable;
622 ndf = reader_data->ndf;
623 uri = nadp_desktop_file_get_key_file_uri( ndf );
624 writable = nadp_utils_uri_is_writable( uri );
625 g_free( uri );
627 return( writable );
631 * read and attach profiles in the specified order
632 * profiles which may exist in .desktop files, but are not referenced
633 * in the 'Profiles' string list are just ignored
635 static void
636 read_done_action_read_profiles( const NAIFactoryProvider *provider, NAObjectAction *action, NadpReaderData *reader_data, GSList **messages )
638 GSList *order;
639 GSList *ip;
640 gchar *profile_id;
641 NAObjectId *found;
643 reader_data->action = action;
644 order = na_object_get_items_slist( action );
646 for( ip = order ; ip ; ip = ip->next ){
647 profile_id = ( gchar * ) ip->data;
648 found = na_object_get_item( action, profile_id );
649 if( !found ){
650 read_done_action_load_profile( provider, reader_data, profile_id, messages );
654 na_core_utils_slist_free( order );
657 static void
658 read_done_action_load_profile( const NAIFactoryProvider *provider, NadpReaderData *reader_data, const gchar *profile_id, GSList **messages )
660 NAObjectProfile *profile;
662 g_debug( "nadp_reader_read_done_action_load_profile: loading profile=%s", profile_id );
664 profile = na_object_profile_new();
665 na_object_set_id( profile, profile_id );
667 na_ifactory_provider_read_item(
668 NA_IFACTORY_PROVIDER( provider ),
669 reader_data,
670 NA_IFACTORY_OBJECT( profile ),
671 messages );