3 * A Nautilus extension which offers configurable context menu actions.
5 * Copyright (C) 2005 The GNOME Foundation
6 * Copyright (C) 2006, 2007, 2008 Frederic Ruaudel and others (see AUTHORS)
7 * Copyright (C) 2009, 2010, 2011 Pierre Wieser and others (see AUTHORS)
9 * This Program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License as
11 * published by the Free Software Foundation; either version 2 of
12 * the License, or (at your option) any later version.
14 * This Program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public
20 * License along with this Library; see the file COPYING. If not,
21 * write to the Free Software Foundation, Inc., 59 Temple Place,
22 * Suite 330, Boston, MA 02111-1307, USA.
25 * Frederic Ruaudel <grumz@grumz.net>
26 * Rodrigo Moya <rodrigo@gnome-db.org>
27 * Pierre Wieser <pwieser@trychlos.org>
28 * ... and many others (see AUTHORS)
39 #include <api/na-core-utils.h>
41 #include "nadp-desktop-file.h"
42 #include "nadp-keys.h"
46 struct _NadpDesktopFileClassPrivate
{
47 void *empty
; /* so that gcc -pedantic is happy */
50 /* private instance data
52 struct _NadpDesktopFilePrivate
{
53 gboolean dispose_has_run
;
59 static GObjectClass
*st_parent_class
= NULL
;
61 static GType
register_type( void );
62 static void class_init( NadpDesktopFileClass
*klass
);
63 static void instance_init( GTypeInstance
*instance
, gpointer klass
);
64 static void instance_dispose( GObject
*object
);
65 static void instance_finalize( GObject
*object
);
67 static NadpDesktopFile
*ndf_new( const gchar
*uri
);
68 static gchar
*path2id( const gchar
*path
);
69 static gchar
*uri2id( const gchar
*uri
);
70 static gboolean
check_key_file( NadpDesktopFile
*ndf
);
71 static void remove_encoding_part( NadpDesktopFile
*ndf
);
74 nadp_desktop_file_get_type( void )
76 static GType class_type
= 0;
79 class_type
= register_type();
88 static const gchar
*thisfn
= "nadp_desktop_file_register_type";
91 static GTypeInfo info
= {
92 sizeof( NadpDesktopFileClass
),
95 ( GClassInitFunc
) class_init
,
98 sizeof( NadpDesktopFile
),
100 ( GInstanceInitFunc
) instance_init
103 g_debug( "%s", thisfn
);
105 type
= g_type_register_static( G_TYPE_OBJECT
, "NadpDesktopFile", &info
, 0 );
111 class_init( NadpDesktopFileClass
*klass
)
113 static const gchar
*thisfn
= "nadp_desktop_file_class_init";
114 GObjectClass
*object_class
;
116 g_debug( "%s: klass=%p", thisfn
, ( void * ) klass
);
118 st_parent_class
= g_type_class_peek_parent( klass
);
120 object_class
= G_OBJECT_CLASS( klass
);
121 object_class
->dispose
= instance_dispose
;
122 object_class
->finalize
= instance_finalize
;
124 klass
->private = g_new0( NadpDesktopFileClassPrivate
, 1 );
128 instance_init( GTypeInstance
*instance
, gpointer klass
)
130 static const gchar
*thisfn
= "nadp_desktop_file_instance_init";
131 NadpDesktopFile
*self
;
133 g_debug( "%s: instance=%p (%s), klass=%p",
134 thisfn
, ( void * ) instance
, G_OBJECT_TYPE_NAME( instance
), ( void * ) klass
);
135 g_return_if_fail( NADP_IS_DESKTOP_FILE( instance
));
136 self
= NADP_DESKTOP_FILE( instance
);
138 self
->private = g_new0( NadpDesktopFilePrivate
, 1 );
140 self
->private->dispose_has_run
= FALSE
;
141 self
->private->key_file
= g_key_file_new();
145 instance_dispose( GObject
*object
)
147 static const gchar
*thisfn
= "nadp_desktop_file_instance_dispose";
148 NadpDesktopFile
*self
;
150 g_return_if_fail( NADP_IS_DESKTOP_FILE( object
));
152 self
= NADP_DESKTOP_FILE( object
);
154 if( !self
->private->dispose_has_run
){
156 g_debug( "%s: object=%p (%s)", thisfn
, ( void * ) object
, G_OBJECT_TYPE_NAME( object
));
158 self
->private->dispose_has_run
= TRUE
;
160 /* chain up to the parent class */
161 if( G_OBJECT_CLASS( st_parent_class
)->dispose
){
162 G_OBJECT_CLASS( st_parent_class
)->dispose( object
);
168 instance_finalize( GObject
*object
)
170 static const gchar
*thisfn
= "nadp_desktop_file_instance_finalize";
171 NadpDesktopFile
*self
;
173 g_return_if_fail( NADP_IS_DESKTOP_FILE( object
));
175 g_debug( "%s: object=%p (%s)", thisfn
, ( void * ) object
, G_OBJECT_TYPE_NAME( object
));
177 self
= NADP_DESKTOP_FILE( object
);
179 g_free( self
->private->id
);
180 g_free( self
->private->uri
);
182 if( self
->private->key_file
){
183 g_key_file_free( self
->private->key_file
);
186 g_free( self
->private );
188 /* chain call to parent class */
189 if( G_OBJECT_CLASS( st_parent_class
)->finalize
){
190 G_OBJECT_CLASS( st_parent_class
)->finalize( object
);
195 * nadp_desktop_file_new:
197 * Retuns: a newly allocated #NadpDesktopFile object.
200 nadp_desktop_file_new( void )
202 NadpDesktopFile
*ndf
;
204 ndf
= g_object_new( NADP_DESKTOP_FILE_TYPE
, NULL
);
210 * nadp_desktop_file_new_from_path:
211 * @path: the full pathname of a .desktop file.
213 * Retuns: a newly allocated #NadpDesktopFile object.
215 * Key file has been loaded, and first validity checks made.
218 nadp_desktop_file_new_from_path( const gchar
*path
)
220 static const gchar
*thisfn
= "nadp_desktop_file_new_from_path";
221 NadpDesktopFile
*ndf
;
226 g_debug( "%s: path=%s", thisfn
, path
);
227 g_return_val_if_fail( path
&& g_utf8_strlen( path
, -1 ) && g_path_is_absolute( path
), ndf
);
230 uri
= g_filename_to_uri( path
, NULL
, &error
);
232 g_warning( "%s: %s: %s", thisfn
, path
, error
->message
);
233 g_error_free( error
);
238 ndf
= ndf_new( uri
);
242 g_key_file_load_from_file( ndf
->private->key_file
, path
, G_KEY_FILE_KEEP_COMMENTS
| G_KEY_FILE_KEEP_TRANSLATIONS
, &error
);
244 g_warning( "%s: %s: %s", thisfn
, path
, error
->message
);
245 g_error_free( error
);
246 g_object_unref( ndf
);
250 if( !check_key_file( ndf
)){
251 g_object_unref( ndf
);
259 * nadp_desktop_file_new_from_uri:
260 * @uri: the URI the desktop file should be loaded from.
262 * Retuns: a newly allocated #NadpDesktopFile object, or %NULL.
264 * Key file has been loaded, and first validity checks made.
266 * Note: This function is in particular used when importing a file.
267 * So it is rather common that the file not be a .desktop one.
268 * Do not warns when file is malformed.
271 nadp_desktop_file_new_from_uri( const gchar
*uri
)
273 static const gchar
*thisfn
= "nadp_desktop_file_new_from_uri";
274 NadpDesktopFile
*ndf
;
280 g_debug( "%s: uri=%s", thisfn
, uri
);
281 g_return_val_if_fail( uri
&& g_utf8_strlen( uri
, -1 ), ndf
);
283 ndf
= ndf_new( uri
);
284 data
= na_core_utils_file_load_from_uri( uri
, &length
);
287 g_key_file_load_from_data( ndf
->private->key_file
, data
, length
, G_KEY_FILE_KEEP_COMMENTS
| G_KEY_FILE_KEEP_TRANSLATIONS
, &error
);
289 if( error
->code
!= G_KEY_FILE_ERROR_GROUP_NOT_FOUND
){
290 g_warning( "%s: %s", thisfn
, error
->message
);
292 g_error_free( error
);
293 g_object_unref( ndf
);
300 if( !check_key_file( ndf
)){
301 g_object_unref( ndf
);
309 * nadp_desktop_file_new_for_write:
310 * @path: the full pathname of a .desktop file.
312 * Retuns: a newly allocated #NadpDesktopFile object.
315 nadp_desktop_file_new_for_write( const gchar
*path
)
317 static const gchar
*thisfn
= "nadp_desktop_file_new_for_write";
318 NadpDesktopFile
*ndf
;
323 g_debug( "%s: path=%s", thisfn
, path
);
324 g_return_val_if_fail( path
&& g_utf8_strlen( path
, -1 ) && g_path_is_absolute( path
), ndf
);
327 uri
= g_filename_to_uri( path
, NULL
, &error
);
329 g_warning( "%s: %s: %s", thisfn
, path
, error
->message
);
330 g_error_free( error
);
335 ndf
= ndf_new( uri
);
343 * nadp_desktop_file_get_key_file:
344 * @ndf: the #NadpDesktopFile instance.
346 * Returns: a pointer to the internal #GKeyFile.
349 nadp_desktop_file_get_key_file( const NadpDesktopFile
*ndf
)
353 g_return_val_if_fail( NADP_IS_DESKTOP_FILE( ndf
), NULL
);
357 if( !ndf
->private->dispose_has_run
){
359 key_file
= ndf
->private->key_file
;
366 * nadp_desktop_file_get_key_file_uri:
367 * @ndf: the #NadpDesktopFile instance.
369 * Returns: the URI of the key file, as a newly allocated
370 * string which should be g_free() by the caller.
373 nadp_desktop_file_get_key_file_uri( const NadpDesktopFile
*ndf
)
377 g_return_val_if_fail( NADP_IS_DESKTOP_FILE( ndf
), NULL
);
381 if( !ndf
->private->dispose_has_run
){
383 uri
= g_strdup( ndf
->private->uri
);
389 static NadpDesktopFile
*
390 ndf_new( const gchar
*uri
)
392 NadpDesktopFile
*ndf
;
394 ndf
= g_object_new( NADP_DESKTOP_FILE_TYPE
, NULL
);
396 ndf
->private->id
= uri2id( uri
);
397 ndf
->private->uri
= g_strdup( uri
);
403 * The id of the file is equal to the basename, minus the suffix.
406 path2id( const gchar
*path
)
411 bname
= g_path_get_basename( path
);
412 id
= na_core_utils_str_remove_suffix( bname
, NADP_DESKTOP_FILE_SUFFIX
);
419 uri2id( const gchar
*uri
)
425 path
= g_filename_from_uri( uri
, NULL
, NULL
);
428 id
= path2id( path
);
436 check_key_file( NadpDesktopFile
*ndf
)
438 static const gchar
*thisfn
= "nadp_desktop_file_check_key_file";
448 /* start group must be [Desktop Entry] */
449 start_group
= g_key_file_get_start_group( ndf
->private->key_file
);
450 if( strcmp( start_group
, NADP_GROUP_DESKTOP
)){
451 g_warning( "%s: %s: invalid start group, found %s, waited for %s",
452 thisfn
, ndf
->private->uri
, start_group
, NADP_GROUP_DESKTOP
);
456 /* must not have Hidden=true value */
458 has_key
= g_key_file_has_key( ndf
->private->key_file
, start_group
, NADP_KEY_HIDDEN
, &error
);
460 g_warning( "%s: %s: %s", thisfn
, ndf
->private->uri
, error
->message
);
463 } else if( has_key
){
464 hidden
= g_key_file_get_boolean( ndf
->private->key_file
, start_group
, NADP_KEY_HIDDEN
, &error
);
466 g_warning( "%s: %s: %s", thisfn
, ndf
->private->uri
, error
->message
);
470 g_debug( "%s: %s: Hidden=true", thisfn
, ndf
->private->uri
);
476 g_free( start_group
);
482 * nadp_desktop_file_get_type:
483 * @ndf: the #NadpDesktopFile instance.
485 * Returns: the value for the Type entry as a newly allocated string which
486 * should be g_free() by the caller.
489 nadp_desktop_file_get_file_type( const NadpDesktopFile
*ndf
)
491 static const gchar
*thisfn
= "nadp_desktop_file_get_file_type";
496 g_return_val_if_fail( NADP_IS_DESKTOP_FILE( ndf
), NULL
);
500 if( !ndf
->private->dispose_has_run
){
504 has_key
= g_key_file_has_key( ndf
->private->key_file
, NADP_GROUP_DESKTOP
, NADP_KEY_TYPE
, &error
);
506 g_warning( "%s: %s", thisfn
, error
->message
);
507 g_error_free( error
);
509 } else if( has_key
){
510 type
= g_key_file_get_string( ndf
->private->key_file
, NADP_GROUP_DESKTOP
, NADP_KEY_TYPE
, &error
);
512 g_warning( "%s: %s", thisfn
, error
->message
);
513 g_error_free( error
);
524 * nadp_desktop_file_get_id:
525 * @ndf: the #NadpDesktopFile instance.
527 * Returns: a newly allocated string which holds the id of the Desktop
531 nadp_desktop_file_get_id( const NadpDesktopFile
*ndf
)
535 g_return_val_if_fail( NADP_IS_DESKTOP_FILE( ndf
), NULL
);
539 if( !ndf
->private->dispose_has_run
){
541 value
= g_strdup( ndf
->private->id
);
548 * nadp_desktop_file_get_profiles:
549 * @ndf: the #NadpDesktopFile instance.
551 * Returns: the list of profiles in the file, as a newly allocated GSList
552 * which must be na_core_utils_slist_free() by the caller.
554 * Silently ignore unknown groups.
557 nadp_desktop_file_get_profiles( const NadpDesktopFile
*ndf
)
560 gchar
**groups
, **ig
;
565 g_return_val_if_fail( NADP_IS_DESKTOP_FILE( ndf
), NULL
);
569 if( !ndf
->private->dispose_has_run
){
571 groups
= g_key_file_get_groups( ndf
->private->key_file
, NULL
);
574 profile_pfx
= g_strdup_printf( "%s ", NADP_GROUP_PROFILE
);
575 pfx_len
= strlen( profile_pfx
);
578 if( !strncmp( *ig
, profile_pfx
, pfx_len
)){
579 profile_id
= g_strdup( *ig
+pfx_len
);
580 list
= g_slist_prepend( list
, profile_id
);
586 g_strfreev( groups
);
587 g_free( profile_pfx
);
595 * nadp_desktop_file_remove_key:
596 * @ndf: this #NadpDesktopFile instance.
600 * Removes the specified key.
602 * Note that this doesn't work very well for localized keys, as we only
603 * remove a key which has the exact same label that the provided one.
604 * So we'd have to remove:
611 nadp_desktop_file_remove_key( const NadpDesktopFile
*ndf
, const gchar
*group
, const gchar
*key
)
617 g_return_if_fail( NADP_IS_DESKTOP_FILE( ndf
));
619 if( !ndf
->private->dispose_has_run
){
621 g_key_file_remove_key( ndf
->private->key_file
, group
, key
, NULL
);
623 locales
= ( char ** ) g_get_language_names();
627 locale_key
= g_strdup_printf( "%s[%s]", key
, *iloc
);
628 g_key_file_remove_key( ndf
->private->key_file
, group
, locale_key
, NULL
);
629 g_free( locale_key
);
636 * nadp_desktop_file_remove_profile:
637 * @ndf: this #NadpDesktopFile instance.
638 * @profile_id: the id of the profile.
640 * Removes the group which describes the specified profile.
643 nadp_desktop_file_remove_profile( const NadpDesktopFile
*ndf
, const gchar
*profile_id
)
647 g_return_if_fail( NADP_IS_DESKTOP_FILE( ndf
));
649 if( !ndf
->private->dispose_has_run
){
651 group_name
= g_strdup_printf( "%s %s", NADP_GROUP_PROFILE
, profile_id
);
652 g_key_file_remove_group( ndf
->private->key_file
, group_name
, NULL
);
653 g_free( group_name
);
658 * nadp_desktop_file_get_boolean:
659 * @ndf: this #NadpDesktopFile instance.
660 * @group: the searched group.
661 * @entry: the searched entry.
662 * @key_found: set to %TRUE if the key has been found, to %FALSE else.
663 * @default_value: value to be set if key has not been found.
665 * Returns: the read value, or the default value if the entry has not
666 * been found in the given group.
669 nadp_desktop_file_get_boolean( const NadpDesktopFile
*ndf
, const gchar
*group
, const gchar
*entry
, gboolean
*key_found
, gboolean default_value
)
671 static const gchar
*thisfn
= "nadp_desktop_file_get_boolean";
677 value
= default_value
;
680 g_return_val_if_fail( NADP_IS_DESKTOP_FILE( ndf
), FALSE
);
682 if( !ndf
->private->dispose_has_run
){
685 has_entry
= g_key_file_has_key( ndf
->private->key_file
, group
, entry
, &error
);
687 g_warning( "%s: %s", thisfn
, error
->message
);
688 g_error_free( error
);
690 } else if( has_entry
){
691 read_value
= g_key_file_get_boolean( ndf
->private->key_file
, group
, entry
, &error
);
693 g_warning( "%s: %s", thisfn
, error
->message
);
694 g_error_free( error
);
707 * nadp_desktop_file_get_locale_string:
708 * @ndf: this #NadpDesktopFile instance.
709 * @group: the searched group.
710 * @entry: the searched entry.
711 * @key_found: set to %TRUE if the key has been found, to %FALSE else.
712 * @default_value: value to be set if key has not been found.
714 * Returns: the read value, or the default value if the entry has not
715 * been found in the given group.
718 nadp_desktop_file_get_locale_string( const NadpDesktopFile
*ndf
, const gchar
*group
, const gchar
*entry
, gboolean
*key_found
, const gchar
*default_value
)
720 static const gchar
*thisfn
= "nadp_desktop_file_get_locale_string";
725 value
= g_strdup( default_value
);
728 g_return_val_if_fail( NADP_IS_DESKTOP_FILE( ndf
), NULL
);
730 if( !ndf
->private->dispose_has_run
){
734 read_value
= g_key_file_get_locale_string( ndf
->private->key_file
, group
, entry
, NULL
, &error
);
735 if( !read_value
|| error
){
736 if( error
->code
!= G_KEY_FILE_ERROR_KEY_NOT_FOUND
){
737 g_warning( "%s: %s", thisfn
, error
->message
);
738 g_error_free( error
);
739 g_free( read_value
);
753 * nadp_desktop_file_get_string:
754 * @ndf: this #NadpDesktopFile instance.
755 * @group: the searched group.
756 * @entry: the searched entry.
757 * @key_found: set to %TRUE if the key has been found, to %FALSE else.
758 * @default_value: value to be set if key has not been found.
760 * Returns: the read value, or the default value if the entry has not
761 * been found in the given group.
764 nadp_desktop_file_get_string( const NadpDesktopFile
*ndf
, const gchar
*group
, const gchar
*entry
, gboolean
*key_found
, const gchar
*default_value
)
766 static const gchar
*thisfn
= "nadp_desktop_file_get_string";
772 value
= g_strdup( default_value
);
775 g_return_val_if_fail( NADP_IS_DESKTOP_FILE( ndf
), NULL
);
777 if( !ndf
->private->dispose_has_run
){
780 has_entry
= g_key_file_has_key( ndf
->private->key_file
, group
, entry
, &error
);
782 g_warning( "%s: %s", thisfn
, error
->message
);
783 g_error_free( error
);
785 } else if( has_entry
){
786 read_value
= g_key_file_get_string( ndf
->private->key_file
, group
, entry
, &error
);
788 g_warning( "%s: %s", thisfn
, error
->message
);
789 g_error_free( error
);
790 g_free( read_value
);
804 * nadp_desktop_file_get_string_list:
805 * @ndf: this #NadpDesktopFile instance.
806 * @group: the searched group.
807 * @entry: the searched entry.
808 * @key_found: set to %TRUE if the key has been found, to %FALSE else.
809 * @default_value: value to be set if key has not been found.
811 * Returns: the read value, or the default value if the entry has not
812 * been found in the given group.
815 nadp_desktop_file_get_string_list( const NadpDesktopFile
*ndf
, const gchar
*group
, const gchar
*entry
, gboolean
*key_found
, const gchar
*default_value
)
817 static const gchar
*thisfn
= "nadp_desktop_file_get_string_list";
823 value
= g_slist_append( NULL
, g_strdup( default_value
));
826 g_return_val_if_fail( NADP_IS_DESKTOP_FILE( ndf
), NULL
);
828 if( !ndf
->private->dispose_has_run
){
831 has_entry
= g_key_file_has_key( ndf
->private->key_file
, group
, entry
, &error
);
833 g_warning( "%s: %s", thisfn
, error
->message
);
834 g_error_free( error
);
836 } else if( has_entry
){
837 read_array
= g_key_file_get_string_list( ndf
->private->key_file
, group
, entry
, NULL
, &error
);
839 g_warning( "%s: %s", thisfn
, error
->message
);
840 g_error_free( error
);
843 na_core_utils_slist_free( value
);
844 value
= na_core_utils_slist_from_array(( const gchar
** ) read_array
);
848 g_strfreev( read_array
);
856 * nadp_desktop_file_get_uint:
857 * @ndf: this #NadpDesktopFile instance.
858 * @group: the searched group.
859 * @entry: the searched entry.
860 * @key_found: set to %TRUE if the key has been found, to %FALSE else.
861 * @default_value: value to be set if key has not been found.
863 * Returns: the read value, or the default value if the entry has not
864 * been found in the given group.
867 nadp_desktop_file_get_uint( const NadpDesktopFile
*ndf
, const gchar
*group
, const gchar
*entry
, gboolean
*key_found
, guint default_value
)
869 static const gchar
*thisfn
= "nadp_desktop_file_get_uint";
874 value
= default_value
;
877 g_return_val_if_fail( NADP_IS_DESKTOP_FILE( ndf
), 0 );
879 if( !ndf
->private->dispose_has_run
){
882 has_entry
= g_key_file_has_key( ndf
->private->key_file
, group
, entry
, &error
);
884 g_warning( "%s: %s", thisfn
, error
->message
);
885 g_error_free( error
);
887 } else if( has_entry
){
888 value
= ( guint
) g_key_file_get_integer( ndf
->private->key_file
, group
, entry
, &error
);
890 g_warning( "%s: %s", thisfn
, error
->message
);
891 g_error_free( error
);
903 * nadp_desktop_file_set_boolean:
904 * @ndf: this #NadpDesktopFile object.
905 * @group: the name of the group.
906 * @key: the name of the key.
907 * @value: the value to be written.
909 * Write the given boolean value.
912 nadp_desktop_file_set_boolean( const NadpDesktopFile
*ndf
, const gchar
*group
, const gchar
*key
, gboolean value
)
914 g_return_if_fail( NADP_IS_DESKTOP_FILE( ndf
));
916 if( !ndf
->private->dispose_has_run
){
918 g_key_file_set_boolean( ndf
->private->key_file
, group
, key
, value
);
923 * nadp_desktop_file_set_locale_string:
924 * @ndf: this #NadpDesktopFile object.
925 * @group: the name of the group.
926 * @key: the name of the key.
927 * @value: the value to be written.
929 * Write the given string value.
931 * Until v 3.0.4, locale strings used to be written for all available locales
932 * e.g. 'en_US.UTF-8', 'en_US', 'en.UTF-8', 'en', 'C'.
934 * Starting with v 3.0.4, encoding part of the locale is no more written.
936 * The better solution would be to include in the UI a listbox with all
937 * available locales, letting the user choose himself which locale he wish
940 * A first fallback would be to set some sort of user preferences: whether
941 * to write all available locales, whether to write all but C locales, ...
943 * As of v 3.0.4, we choose:
944 * - always write the first locale, which should obviously be the user locale;
945 * - also write all locales derived from the first (e.g. en_US, en_GB, en);
946 * - when the prefix of the locale changes, stop to write other locales unless
947 * the first prefix was 'en', as we suppose that the C locale will always be
950 * The locale prefix is identified by '_' or '@' character.
953 nadp_desktop_file_set_locale_string( const NadpDesktopFile
*ndf
, const gchar
*group
, const gchar
*key
, const gchar
*value
)
960 g_return_if_fail( NADP_IS_DESKTOP_FILE( ndf
));
962 if( !ndf
->private->dispose_has_run
){
964 locales
= ( char ** ) g_get_language_names();
973 prefix
= g_strdup( locales
[0] );
974 for( i
= 0 ; prefix
[i
] ; ++i
){
975 if( prefix
[i
] == '_' || prefix
[i
] == '@' || prefix
[i
] == '.' ){
981 /* using locales[0] writes a string with, e.g. Label[en_US.UTF-8]
982 * after that trying to read the same key with another locale, even en_US.utf-8,
983 * fails ans returns an empty string.
984 * so write all available locales for the string, so that there is a chance at
985 * least one of these will be used as default
987 * pwi 2010-12-30 v 3.0.4
988 * no more write encoding part of the locale as desktop files are supposed to
991 for( i
= 0 ; i
< g_strv_length( locales
) ; ++i
){
994 if( g_strstr_len( locales
[i
], -1, "." )){
998 /* write the locale string for all locales derived from the first one */
999 if( !strncmp( locales
[i
], prefix
, strlen( prefix
))){
1002 /* also write other locales if first was a 'en'-derivative */
1003 } else if( !strcmp( prefix
, "en" )){
1008 g_key_file_set_locale_string( ndf
->private->key_file
, group
, key
, locales
[i
], value
);
1017 * nadp_desktop_file_set_string:
1018 * @ndf: this #NadpDesktopFile object.
1019 * @group: the name of the group.
1020 * @key: the name of the key.
1021 * @value: the value to be written.
1023 * Write the given string value.
1026 nadp_desktop_file_set_string( const NadpDesktopFile
*ndf
, const gchar
*group
, const gchar
*key
, const gchar
*value
)
1028 g_return_if_fail( NADP_IS_DESKTOP_FILE( ndf
));
1030 if( !ndf
->private->dispose_has_run
){
1032 g_key_file_set_string( ndf
->private->key_file
, group
, key
, value
);
1037 * nadp_desktop_file_set_string_list:
1038 * @ndf: this #NadpDesktopFile object.
1039 * @group: the name of the group.
1040 * @key: the name of the key.
1041 * @value: the value to be written.
1043 * Write the given list value.
1046 nadp_desktop_file_set_string_list( const NadpDesktopFile
*ndf
, const gchar
*group
, const gchar
*key
, GSList
*value
)
1050 g_return_if_fail( NADP_IS_DESKTOP_FILE( ndf
));
1052 if( !ndf
->private->dispose_has_run
){
1054 array
= na_core_utils_slist_to_array( value
);
1055 g_key_file_set_string_list( ndf
->private->key_file
, group
, key
, ( const gchar
* const * ) array
, g_slist_length( value
));
1056 g_strfreev( array
);
1061 * nadp_desktop_file_set_uint:
1062 * @ndf: this #NadpDesktopFile object.
1063 * @group: the name of the group.
1064 * @key: the name of the key.
1065 * @value: the value to be written.
1067 * Write the given uint value.
1070 nadp_desktop_file_set_uint( const NadpDesktopFile
*ndf
, const gchar
*group
, const gchar
*key
, guint value
)
1072 g_return_if_fail( NADP_IS_DESKTOP_FILE( ndf
));
1074 if( !ndf
->private->dispose_has_run
){
1076 g_key_file_set_integer( ndf
->private->key_file
, group
, key
, value
);
1081 * nadp_desktop_file_write:
1082 * @ndf: the #NadpDesktopFile instance.
1084 * Writes the key file to the disk.
1086 * Returns: %TRUE if write is ok, %FALSE else.
1088 * Starting with v 3.0.4, locale strings whose identifier include an
1089 * encoding part are removed from the desktop file when rewriting it
1090 * (these were wrongly written between v 2.99 and 3.0.3).
1093 nadp_desktop_file_write( NadpDesktopFile
*ndf
)
1095 static const gchar
*thisfn
= "nadp_desktop_file_write";
1099 GFileOutputStream
*stream
;
1105 g_return_val_if_fail( NADP_IS_DESKTOP_FILE( ndf
), ret
);
1107 if( !ndf
->private->dispose_has_run
){
1109 if( ndf
->private->key_file
){
1110 remove_encoding_part( ndf
);
1113 data
= g_key_file_to_data( ndf
->private->key_file
, &length
, NULL
);
1114 file
= g_file_new_for_uri( ndf
->private->uri
);
1115 g_debug( "%s: uri=%s", thisfn
, ndf
->private->uri
);
1117 stream
= g_file_replace( file
, NULL
, FALSE
, G_FILE_CREATE_NONE
, NULL
, &error
);
1119 g_warning( "%s: g_file_replace: %s", thisfn
, error
->message
);
1120 g_error_free( error
);
1122 g_object_unref( stream
);
1124 g_object_unref( file
);
1129 g_output_stream_write( G_OUTPUT_STREAM( stream
), data
, length
, NULL
, &error
);
1131 g_warning( "%s: g_output_stream_write: %s", thisfn
, error
->message
);
1132 g_error_free( error
);
1133 g_object_unref( stream
);
1134 g_object_unref( file
);
1139 g_output_stream_close( G_OUTPUT_STREAM( stream
), NULL
, &error
);
1141 g_warning( "%s: g_output_stream_close: %s", thisfn
, error
->message
);
1142 g_error_free( error
);
1143 g_object_unref( stream
);
1144 g_object_unref( file
);
1149 g_object_unref( stream
);
1150 g_object_unref( file
);
1160 remove_encoding_part( NadpDesktopFile
*ndf
)
1162 static const gchar
*thisfn
= "nadp_desktop_file_remove_encoding_part";
1171 regex
= g_regex_new( "\\[(.*)\\.(.*)\\]$", G_REGEX_CASELESS
| G_REGEX_UNGREEDY
, G_REGEX_MATCH_NOTEMPTY
, &error
);
1173 g_warning( "%s: %s", thisfn
, error
->message
);
1174 g_error_free( error
);
1177 groups
= g_key_file_get_groups( ndf
->private->key_file
, NULL
);
1179 for( ig
= 0 ; ig
< g_strv_length( groups
) ; ++ig
){
1180 keys
= g_key_file_get_keys( ndf
->private->key_file
, groups
[ig
], NULL
, NULL
);
1182 for( ik
= 0 ; ik
< g_strv_length( keys
) ; ++ik
){
1184 if( g_regex_match( regex
, keys
[ik
], 0, &info
)){
1185 g_key_file_remove_key( ndf
->private->key_file
, groups
[ig
], keys
[ik
], &error
);
1187 g_warning( "%s: %s", thisfn
, error
->message
);
1188 g_error_free( error
);
1193 g_match_info_free( info
);
1199 g_strfreev( groups
);
1200 g_regex_unref( regex
);