1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
4 Copyright (C) 2004 Sebastien Granjoux
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 * Project properties, used in middle pages
24 *---------------------------------------------------------------------------*/
30 #include <glib/gdir.h>
33 #include <libgnome/gnome-i18n.h>
38 /*---------------------------------------------------------------------------*/
40 #define STRING_CHUNK_SIZE 256
42 /*---------------------------------------------------------------------------*/
47 GStringChunk
* string_pool
;
58 NPWPropertyOptions options
;
73 static const gchar
* NPWPropertyTypeString
[] = {
85 *---------------------------------------------------------------------------*/
87 static NPWPropertyType
88 npw_property_type_from_string (const gchar
* type
)
92 for (i
= 0; i
< NPW_LAST_PROPERTY
; i
++)
94 if (strcmp (NPWPropertyTypeString
[i
], type
) == 0)
96 return (NPWPropertyType
)(i
+ 1);
100 return NPW_UNKNOWN_PROPERTY
;
105 npw_property_string_from_type (NPWPropertyType type
)
107 if ((type
> 0) && (type
< NPW_LAST_PROPERTY
))
109 return NPWPropertyTypeString
[type
- 1];
117 npw_property_new (NPWPage
* owner
)
121 g_return_val_if_fail (owner
, NULL
);
123 this = g_chunk_new0(NPWProperty
, owner
->data_pool
);
125 this->type
= NPW_UNKNOWN_PROPERTY
;
127 /* value is set to NULL */
128 g_node_append_data (owner
->list
, this);
134 npw_property_free (NPWProperty
* this)
138 if (this->item
!= NULL
)
140 g_slist_free (this->item
);
142 node
= g_node_find_child (this->owner
->list
, G_TRAVERSE_ALL
, this);
145 g_node_destroy (node
);
146 /* Memory allocated in string pool and data pool is not free */
151 npw_property_set_type (NPWProperty
* this, NPWPropertyType type
)
157 npw_property_set_string_type (NPWProperty
* this, const gchar
* type
)
159 npw_property_set_type (this, npw_property_type_from_string (type
));
164 npw_property_get_type (const NPWProperty
* this)
170 npw_property_set_name (NPWProperty
* this, const gchar
* name
)
172 this->value
= npw_value_heap_find_value (this->owner
->value
, name
);
176 npw_property_get_name (const NPWProperty
* this)
178 return npw_value_heap_get_name (this->owner
->value
, this->value
);
182 npw_property_set_label (NPWProperty
* this, const gchar
* label
)
184 this->label
= g_string_chunk_insert (this->owner
->string_pool
, label
);
188 npw_property_get_label (const NPWProperty
* this)
194 npw_property_set_description (NPWProperty
* this, const gchar
* description
)
196 this->description
= g_string_chunk_insert (this->owner
->string_pool
, description
);
200 npw_property_get_description (const NPWProperty
* this)
202 return this->description
;
206 cb_boolean_button_toggled (GtkButton
*button
, gpointer data
)
208 if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button
)))
209 gtk_button_set_label (button
, _("Yes"));
211 gtk_button_set_label (button
, _("No"));
215 npw_property_create_widget (NPWProperty
* this)
221 value
= npw_property_get_value (this);
224 case NPW_BOOLEAN_PROPERTY
:
225 entry
= gtk_toggle_button_new_with_label (_("No"));
226 g_signal_connect (G_OBJECT (entry
), "toggled",
227 G_CALLBACK (cb_boolean_button_toggled
), NULL
);
230 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (entry
),
231 (gboolean
)atoi (value
));
234 case NPW_INTEGER_PROPERTY
:
235 entry
= gtk_spin_button_new (NULL
, 1, 0);
238 gtk_spin_button_set_value (GTK_SPIN_BUTTON (entry
), atoi (value
));
241 case NPW_STRING_PROPERTY
:
242 entry
= gtk_entry_new ();
243 if (value
) gtk_entry_set_text (GTK_ENTRY (entry
), value
);
245 case NPW_DIRECTORY_PROPERTY
:
246 entry
= gnome_file_entry_new (NULL
, NULL
);
247 g_value_init (&val
, G_TYPE_BOOLEAN
);
248 g_value_set_boolean (&val
, TRUE
);
249 g_object_set_property (G_OBJECT (entry
), "use-filechooser", &val
);
250 g_value_unset (&val
);
251 gnome_file_entry_set_directory_entry (GNOME_FILE_ENTRY (entry
), TRUE
);
252 if (value
) gnome_file_entry_set_filename (GNOME_FILE_ENTRY (entry
), value
);
254 case NPW_FILE_PROPERTY
:
255 entry
= gnome_file_entry_new (NULL
, NULL
);
256 g_value_init (&val
, G_TYPE_BOOLEAN
);
257 g_value_set_boolean (&val
, TRUE
);
258 g_object_set_property (G_OBJECT (entry
), "use-filechooser", &val
);
259 g_value_unset (&val
);
260 gnome_file_entry_set_directory_entry (GNOME_FILE_ENTRY (entry
), FALSE
);
261 if (value
) gnome_file_entry_set_filename (GNOME_FILE_ENTRY (entry
), value
);
263 case NPW_ICON_PROPERTY
:
264 entry
= gnome_icon_entry_new("icon_choice", _("Icon choice"));
265 if (value
) gnome_icon_entry_set_filename (GNOME_ICON_ENTRY (entry
), value
);
267 case NPW_LIST_PROPERTY
:
270 gboolean get_value
= FALSE
;
272 entry
= gtk_combo_box_entry_new_text ();
273 for (node
= this->item
; node
!= NULL
; node
= node
->next
)
275 gtk_combo_box_append_text (GTK_COMBO_BOX (entry
), _(((NPWItem
*)node
->data
)->label
));
276 if ((value
!= NULL
) && !get_value
&& (strcmp (value
, ((NPWItem
*)node
->data
)->name
) == 0))
278 value
= _(((NPWItem
*)node
->data
)->label
);
282 if (!(this->options
& NPW_EDITABLE_OPTION
))
284 gtk_editable_set_editable (GTK_EDITABLE (GTK_BIN (entry
)->child
), FALSE
);
286 if (value
) gtk_entry_set_text (GTK_ENTRY (GTK_BIN (entry
)->child
), value
);
292 this->widget
= entry
;
298 npw_property_set_widget (NPWProperty
* this, GtkWidget
* widget
)
300 this->widget
= widget
;
304 npw_property_get_widget (const NPWProperty
* this)
310 npw_property_set_default (NPWProperty
* this, const gchar
* value
)
312 /* Check if the default property is valid */
313 if (value
&& (this->options
& NPW_EXIST_SET_OPTION
) && !(this->options
& NPW_EXIST_OPTION
))
315 /* a file or directory with the same name shouldn't exist */
316 if (g_file_test (value
, G_FILE_TEST_EXISTS
))
321 /* Allocate memory for the string and a decimal number */
322 buffer
= g_new (char, strlen(value
) + 8);
323 /* Give up after 1000000 tries */
324 for (i
= 1; i
< 1000000; i
++)
326 sprintf(buffer
,"%s%d",value
, i
);
327 if (!g_file_test (buffer
, G_FILE_TEST_EXISTS
)) break;
329 this->defvalue
= g_string_chunk_insert (this->owner
->string_pool
, buffer
);
335 /* This function could be used with value = defvalue to only check
336 * the default property */
337 if (this->defvalue
!= value
)
339 this->defvalue
= (value
== NULL
) ? NULL
: g_string_chunk_insert (this->owner
->string_pool
, value
);
344 npw_property_set_value_from_widget (NPWProperty
* this, NPWValueTag tag
)
346 gchar
* alloc_value
= NULL
;
347 const gchar
* value
= NULL
;
352 case NPW_INTEGER_PROPERTY
:
353 alloc_value
= g_strdup_printf("%d", gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (this->widget
)));
356 case NPW_BOOLEAN_PROPERTY
:
357 alloc_value
= g_strdup_printf("%d", gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (this->widget
)));
360 case NPW_STRING_PROPERTY
:
361 value
= gtk_entry_get_text (GTK_ENTRY (this->widget
));
363 case NPW_DIRECTORY_PROPERTY
:
364 case NPW_FILE_PROPERTY
:
365 alloc_value
= gnome_file_entry_get_full_path (GNOME_FILE_ENTRY (this->widget
), FALSE
);
368 case NPW_ICON_PROPERTY
:
369 alloc_value
= gnome_icon_entry_get_filename (GNOME_ICON_ENTRY (this->widget
));
372 case NPW_LIST_PROPERTY
:
376 value
= gtk_entry_get_text (GTK_ENTRY (GTK_BIN (this->widget
)->child
));
377 for (node
= this->item
; node
!= NULL
; node
= node
->next
)
379 if (strcmp (value
, _(((NPWItem
*)node
->data
)->label
)) == 0)
381 value
= ((NPWItem
*)node
->data
)->name
;
388 /* Hidden property */
389 value
= this->defvalue
;
393 /* Check and mark default value (will not be saved) */
394 if ((value
) && (this->defvalue
) && (strcmp (value
, this->defvalue
) == 0))
396 tag
|= NPW_DEFAULT_VALUE
;
399 ok
= npw_value_heap_set_value (this->owner
->value
, this->value
, value
, tag
);
400 if (alloc_value
!= NULL
) g_free (alloc_value
);
406 npw_property_update_value_from_widget (NPWProperty
* this)
408 return npw_property_set_value_from_widget (this, NPW_VALID_VALUE
);
412 npw_property_save_value_from_widget (NPWProperty
* this)
414 return npw_property_set_value_from_widget (this, NPW_OLD_VALUE
);
418 npw_property_remove_value (NPWProperty
* this)
420 return npw_value_heap_set_value (this->owner
->value
, this->value
, NULL
, NPW_EMPTY_VALUE
);
424 npw_property_get_value (const NPWProperty
* this)
428 tag
= npw_value_heap_get_tag (this->owner
->value
, this->value
);
429 if ((tag
== NPW_EMPTY_VALUE
) || (tag
& NPW_DEFAULT_VALUE
))
431 return this->defvalue
;
435 /* Only value entered by user could replace default value */
436 return npw_value_heap_get_value (this->owner
->value
, this->value
);
441 npw_property_add_list_item (NPWProperty
* this, const gchar
* name
, const gchar
* label
)
445 item
= g_chunk_new (NPWItem
, this->owner
->item_pool
);
446 item
->name
= g_string_chunk_insert (this->owner
->string_pool
, name
);
447 item
->label
= g_string_chunk_insert (this->owner
->string_pool
, label
);
449 this->item
= g_slist_append (this->item
, item
);
455 npw_property_set_mandatory_option (NPWProperty
* this, gboolean value
)
459 this->options
|= NPW_MANDATORY_OPTION
;
463 this->options
&= ~NPW_MANDATORY_OPTION
;
468 npw_property_set_summary_option (NPWProperty
* this, gboolean value
)
472 this->options
|= NPW_SUMMARY_OPTION
;
476 this->options
&= ~NPW_SUMMARY_OPTION
;
481 npw_property_set_editable_option (NPWProperty
* this, gboolean value
)
485 this->options
|= NPW_EDITABLE_OPTION
;
489 this->options
&= ~NPW_EDITABLE_OPTION
;
494 npw_property_get_options (const NPWProperty
* this)
496 return this->options
;
500 npw_property_set_exist_option (NPWProperty
* this, NPWPropertyBooleanValue value
)
505 this->options
|= NPW_EXIST_OPTION
| NPW_EXIST_SET_OPTION
;
508 this->options
&= ~NPW_EXIST_OPTION
;
509 this->options
|= NPW_EXIST_SET_OPTION
;
510 npw_property_set_default (this, this->defvalue
);
513 this->options
&= ~(NPW_EXIST_OPTION
| NPW_EXIST_SET_OPTION
);
518 NPWPropertyBooleanValue
519 npw_property_get_exist_option (const NPWProperty
* this)
521 return this->options
& NPW_EXIST_SET_OPTION
? (this->options
& NPW_EXIST_OPTION
? NPW_TRUE
: NPW_FALSE
) : NPW_DEFAULT
;
524 /* Page object = list of properties
525 *---------------------------------------------------------------------------*/
528 npw_page_new (NPWValueHeap
* value
)
532 this = g_new0(NPWPage
, 1);
533 this->string_pool
= g_string_chunk_new (STRING_CHUNK_SIZE
);
534 this->data_pool
= g_mem_chunk_new ("property pool", sizeof (NPWProperty
), STRING_CHUNK_SIZE
* sizeof (NPWProperty
) / 4, G_ALLOC_ONLY
);
535 this->item_pool
= g_mem_chunk_new ("item pool", sizeof (NPWItem
), STRING_CHUNK_SIZE
* sizeof (NPWItem
) / 4, G_ALLOC_ONLY
);
536 this->list
= g_node_new (NULL
);
543 npw_page_free (NPWPage
* this)
545 g_return_if_fail (this != NULL
);
547 g_string_chunk_free (this->string_pool
);
548 g_mem_chunk_destroy (this->data_pool
);
549 g_mem_chunk_destroy (this->item_pool
);
550 g_node_destroy (this->list
);
555 npw_page_set_name (NPWPage
* this, const gchar
* name
)
557 this->name
= g_string_chunk_insert (this->string_pool
, name
);
561 npw_page_get_name (const NPWPage
* this)
567 npw_page_set_label (NPWPage
* this, const gchar
* label
)
569 this->label
= g_string_chunk_insert (this->string_pool
, label
);
573 npw_page_get_label (const NPWPage
* this)
579 npw_page_set_description (NPWPage
* this, const gchar
* description
)
581 this->description
= g_string_chunk_insert (this->string_pool
, description
);
585 npw_page_get_description (const NPWPage
* this)
587 return this->description
;
590 typedef struct _PageForeachPropertyData
592 NPWPropertyForeachFunc func
;
594 } PageForeachPropertyData
;
597 cb_page_foreach_property (GNode
* node
, gpointer data
)
599 PageForeachPropertyData
* d
= (PageForeachPropertyData
*)data
;
601 (d
->func
)((NPWProperty
*)node
->data
, d
->data
);
605 npw_page_foreach_property (const NPWPage
* this, NPWPropertyForeachFunc func
, gpointer data
)
607 PageForeachPropertyData d
;
611 g_node_children_foreach (this->list
, G_TRAVERSE_LEAFS
, cb_page_foreach_property
, &d
);