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
[] = {"hidden",
83 *---------------------------------------------------------------------------*/
85 static NPWPropertyType
86 npw_property_type_from_string (const gchar
* type
)
90 for (i
= 0; i
< NPW_LAST_PROPERTY
; i
++)
92 if (strcmp (NPWPropertyTypeString
[i
], type
) == 0)
94 return (NPWPropertyType
)(i
+ 1);
98 return NPW_UNKNOWN_PROPERTY
;
103 npw_property_string_from_type (NPWPropertyType type
)
105 if ((type
> 0) && (type
< NPW_LAST_PROPERTY
))
107 return NPWPropertyTypeString
[type
- 1];
115 npw_property_new (NPWPage
* owner
)
119 g_return_val_if_fail (owner
, NULL
);
121 this = g_chunk_new0(NPWProperty
, owner
->data_pool
);
123 this->type
= NPW_UNKNOWN_PROPERTY
;
125 /* value is set to NULL */
126 g_node_append_data (owner
->list
, this);
132 npw_property_free (NPWProperty
* this)
136 if (this->item
!= NULL
)
138 g_slist_free (this->item
);
140 node
= g_node_find_child (this->owner
->list
, G_TRAVERSE_ALL
, this);
143 g_node_destroy (node
);
144 /* Memory allocated in string pool and data pool is not free */
149 npw_property_set_type (NPWProperty
* this, NPWPropertyType type
)
155 npw_property_set_string_type (NPWProperty
* this, const gchar
* type
)
157 npw_property_set_type (this, npw_property_type_from_string (type
));
162 npw_property_get_type (const NPWProperty
* this)
168 npw_property_set_name (NPWProperty
* this, const gchar
* name
)
170 this->value
= npw_value_heap_find_value (this->owner
->value
, name
);
174 npw_property_get_name (const NPWProperty
* this)
176 return npw_value_heap_get_name (this->owner
->value
, this->value
);
180 npw_property_set_label (NPWProperty
* this, const gchar
* label
)
182 this->label
= g_string_chunk_insert (this->owner
->string_pool
, label
);
186 npw_property_get_label (const NPWProperty
* this)
192 npw_property_set_description (NPWProperty
* this, const gchar
* description
)
194 this->description
= g_string_chunk_insert (this->owner
->string_pool
, description
);
198 npw_property_get_description (const NPWProperty
* this)
200 return this->description
;
204 cb_boolean_button_toggled (GtkButton
*button
, gpointer data
)
206 if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button
)))
207 gtk_button_set_label (button
, _("Yes"));
209 gtk_button_set_label (button
, _("No"));
213 npw_property_create_widget (NPWProperty
* this)
219 value
= npw_property_get_value (this);
222 case NPW_BOOLEAN_PROPERTY
:
223 entry
= gtk_toggle_button_new_with_label (_("No"));
224 g_signal_connect (G_OBJECT (entry
), "toggled",
225 G_CALLBACK (cb_boolean_button_toggled
), NULL
);
228 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (entry
),
229 (gboolean
)atoi (value
));
232 case NPW_INTEGER_PROPERTY
:
233 entry
= gtk_spin_button_new (NULL
, 1, 0);
236 gtk_spin_button_set_value (GTK_SPIN_BUTTON (entry
), atoi (value
));
239 case NPW_STRING_PROPERTY
:
240 entry
= gtk_entry_new ();
241 if (value
) gtk_entry_set_text (GTK_ENTRY (entry
), value
);
243 case NPW_DIRECTORY_PROPERTY
:
244 entry
= gnome_file_entry_new (NULL
, NULL
);
245 g_value_init (&val
, G_TYPE_BOOLEAN
);
246 g_value_set_boolean (&val
, TRUE
);
247 g_object_set_property (G_OBJECT (entry
), "use-filechooser", &val
);
248 g_value_unset (&val
);
249 gnome_file_entry_set_directory_entry (GNOME_FILE_ENTRY (entry
), TRUE
);
250 if (value
) gnome_file_entry_set_filename (GNOME_FILE_ENTRY (entry
), value
);
252 case NPW_FILE_PROPERTY
:
253 entry
= gnome_file_entry_new (NULL
, NULL
);
254 g_value_init (&val
, G_TYPE_BOOLEAN
);
255 g_value_set_boolean (&val
, TRUE
);
256 g_object_set_property (G_OBJECT (entry
), "use-filechooser", &val
);
257 g_value_unset (&val
);
258 gnome_file_entry_set_directory_entry (GNOME_FILE_ENTRY (entry
), FALSE
);
259 if (value
) gnome_file_entry_set_filename (GNOME_FILE_ENTRY (entry
), value
);
261 case NPW_ICON_PROPERTY
:
262 entry
= gnome_icon_entry_new("icon_choice", _("Icon choice"));
263 if (value
) gnome_icon_entry_set_filename (GNOME_ICON_ENTRY (entry
), value
);
265 case NPW_LIST_PROPERTY
:
268 gboolean get_value
= FALSE
;
270 entry
= gtk_combo_box_entry_new_text ();
271 for (node
= this->item
; node
!= NULL
; node
= node
->next
)
273 gtk_combo_box_append_text (GTK_COMBO_BOX (entry
), _(((NPWItem
*)node
->data
)->label
));
274 if ((value
!= NULL
) && !get_value
&& (strcmp (value
, ((NPWItem
*)node
->data
)->name
) == 0))
276 value
= _(((NPWItem
*)node
->data
)->label
);
280 if (!(this->options
& NPW_EDITABLE_OPTION
))
282 gtk_editable_set_editable (GTK_EDITABLE (GTK_BIN (entry
)->child
), FALSE
);
284 if (value
) gtk_entry_set_text (GTK_ENTRY (GTK_BIN (entry
)->child
), value
);
290 this->widget
= entry
;
296 npw_property_set_widget (NPWProperty
* this, GtkWidget
* widget
)
298 this->widget
= widget
;
302 npw_property_get_widget (const NPWProperty
* this)
308 npw_property_set_default (NPWProperty
* this, const gchar
* value
)
310 /* Check if the default property is valid */
311 if (value
&& (this->options
& NPW_EXIST_SET_OPTION
) && !(this->options
& NPW_EXIST_OPTION
))
313 /* a file or directory with the same name shouldn't exist */
314 if (g_file_test (value
, G_FILE_TEST_EXISTS
))
319 /* Allocate memory for the string and a decimal number */
320 buffer
= g_new (char, strlen(value
) + 8);
321 /* Give up after 1000000 tries */
322 for (i
= 1; i
< 1000000; i
++)
324 sprintf(buffer
,"%s%d",value
, i
);
325 if (!g_file_test (buffer
, G_FILE_TEST_EXISTS
)) break;
327 this->defvalue
= g_string_chunk_insert (this->owner
->string_pool
, buffer
);
333 /* This function could be used with value = defvalue to only check
334 * the default property */
335 if (this->defvalue
!= value
)
337 this->defvalue
= (value
== NULL
) ? NULL
: g_string_chunk_insert (this->owner
->string_pool
, value
);
342 npw_property_set_value_from_widget (NPWProperty
* this, NPWValueTag tag
)
344 gchar
* alloc_value
= NULL
;
345 const gchar
* value
= NULL
;
350 case NPW_INTEGER_PROPERTY
:
351 alloc_value
= g_strdup_printf("%d", gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (this->widget
)));
354 case NPW_BOOLEAN_PROPERTY
:
355 alloc_value
= g_strdup_printf("%d", gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (this->widget
)));
358 case NPW_STRING_PROPERTY
:
359 value
= gtk_entry_get_text (GTK_ENTRY (this->widget
));
361 case NPW_DIRECTORY_PROPERTY
:
362 case NPW_FILE_PROPERTY
:
363 alloc_value
= gnome_file_entry_get_full_path (GNOME_FILE_ENTRY (this->widget
), FALSE
);
366 case NPW_ICON_PROPERTY
:
367 alloc_value
= gnome_icon_entry_get_filename (GNOME_ICON_ENTRY (this->widget
));
370 case NPW_LIST_PROPERTY
:
374 value
= gtk_entry_get_text (GTK_ENTRY (GTK_BIN (this->widget
)->child
));
375 for (node
= this->item
; node
!= NULL
; node
= node
->next
)
377 if (strcmp (value
, _(((NPWItem
*)node
->data
)->label
)) == 0)
379 value
= ((NPWItem
*)node
->data
)->name
;
386 /* Hidden property */
387 value
= this->defvalue
;
391 /* Check and mark default value (will not be saved) */
392 if ((value
) && (this->defvalue
) && (strcmp (value
, this->defvalue
) == 0))
394 tag
|= NPW_DEFAULT_VALUE
;
397 ok
= npw_value_heap_set_value (this->owner
->value
, this->value
, value
, tag
);
398 if (alloc_value
!= NULL
) g_free (alloc_value
);
404 npw_property_update_value_from_widget (NPWProperty
* this)
406 return npw_property_set_value_from_widget (this, NPW_VALID_VALUE
);
410 npw_property_save_value_from_widget (NPWProperty
* this)
412 return npw_property_set_value_from_widget (this, NPW_OLD_VALUE
);
416 npw_property_remove_value (NPWProperty
* this)
418 return npw_value_heap_set_value (this->owner
->value
, this->value
, NULL
, NPW_EMPTY_VALUE
);
422 npw_property_get_value (const NPWProperty
* this)
426 tag
= npw_value_heap_get_tag (this->owner
->value
, this->value
);
427 if ((tag
== NPW_EMPTY_VALUE
) || (tag
& NPW_DEFAULT_VALUE
))
429 return this->defvalue
;
433 /* Only value entered by user could replace default value */
434 return npw_value_heap_get_value (this->owner
->value
, this->value
);
439 npw_property_add_list_item (NPWProperty
* this, const gchar
* name
, const gchar
* label
)
443 item
= g_chunk_new (NPWItem
, this->owner
->item_pool
);
444 item
->name
= g_string_chunk_insert (this->owner
->string_pool
, name
);
445 item
->label
= g_string_chunk_insert (this->owner
->string_pool
, label
);
447 this->item
= g_slist_append (this->item
, item
);
453 npw_property_set_mandatory_option (NPWProperty
* this, gboolean value
)
457 this->options
|= NPW_MANDATORY_OPTION
;
461 this->options
&= ~NPW_MANDATORY_OPTION
;
466 npw_property_set_summary_option (NPWProperty
* this, gboolean value
)
470 this->options
|= NPW_SUMMARY_OPTION
;
474 this->options
&= ~NPW_SUMMARY_OPTION
;
479 npw_property_set_editable_option (NPWProperty
* this, gboolean value
)
483 this->options
|= NPW_EDITABLE_OPTION
;
487 this->options
&= ~NPW_EDITABLE_OPTION
;
492 npw_property_get_options (const NPWProperty
* this)
494 return this->options
;
498 npw_property_set_exist_option (NPWProperty
* this, NPWPropertyBooleanValue value
)
503 this->options
|= NPW_EXIST_OPTION
| NPW_EXIST_SET_OPTION
;
506 this->options
&= ~NPW_EXIST_OPTION
;
507 this->options
|= NPW_EXIST_SET_OPTION
;
508 npw_property_set_default (this, this->defvalue
);
511 this->options
&= ~(NPW_EXIST_OPTION
| NPW_EXIST_SET_OPTION
);
516 NPWPropertyBooleanValue
517 npw_property_get_exist_option (const NPWProperty
* this)
519 return this->options
& NPW_EXIST_SET_OPTION
? (this->options
& NPW_EXIST_OPTION
? NPW_TRUE
: NPW_FALSE
) : NPW_DEFAULT
;
522 /* Page object = list of properties
523 *---------------------------------------------------------------------------*/
526 npw_page_new (NPWValueHeap
* value
)
530 this = g_new0(NPWPage
, 1);
531 this->string_pool
= g_string_chunk_new (STRING_CHUNK_SIZE
);
532 this->data_pool
= g_mem_chunk_new ("property pool", sizeof (NPWProperty
), STRING_CHUNK_SIZE
* sizeof (NPWProperty
) / 4, G_ALLOC_ONLY
);
533 this->item_pool
= g_mem_chunk_new ("item pool", sizeof (NPWItem
), STRING_CHUNK_SIZE
* sizeof (NPWItem
) / 4, G_ALLOC_ONLY
);
534 this->list
= g_node_new (NULL
);
541 npw_page_free (NPWPage
* this)
543 g_return_if_fail (this != NULL
);
545 g_string_chunk_free (this->string_pool
);
546 g_mem_chunk_destroy (this->data_pool
);
547 g_mem_chunk_destroy (this->item_pool
);
548 g_node_destroy (this->list
);
553 npw_page_set_name (NPWPage
* this, const gchar
* name
)
555 this->name
= g_string_chunk_insert (this->string_pool
, name
);
559 npw_page_get_name (const NPWPage
* this)
565 npw_page_set_label (NPWPage
* this, const gchar
* label
)
567 this->label
= g_string_chunk_insert (this->string_pool
, label
);
571 npw_page_get_label (const NPWPage
* this)
577 npw_page_set_description (NPWPage
* this, const gchar
* description
)
579 this->description
= g_string_chunk_insert (this->string_pool
, description
);
583 npw_page_get_description (const NPWPage
* this)
585 return this->description
;
588 typedef struct _PageForeachPropertyData
590 NPWPropertyForeachFunc func
;
592 } PageForeachPropertyData
;
595 cb_page_foreach_property (GNode
* node
, gpointer data
)
597 PageForeachPropertyData
* d
= (PageForeachPropertyData
*)data
;
599 (d
->func
)((NPWProperty
*)node
->data
, d
->data
);
603 npw_page_foreach_property (const NPWPage
* this, NPWPropertyForeachFunc func
, gpointer data
)
605 PageForeachPropertyData d
;
609 g_node_children_foreach (this->list
, G_TRAVERSE_LEAFS
, cb_page_foreach_property
, &d
);