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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 * Project properties, used in middle pages
24 *---------------------------------------------------------------------------*/
30 #include <glib/gdir.h>
33 #include <libgnome/gnome-i18n.h>
34 #include <libgnomevfs/gnome-vfs-utils.h>
39 #include <libanjuta/anjuta-debug.h>
41 /*---------------------------------------------------------------------------*/
43 #define STRING_CHUNK_SIZE 256
45 /*---------------------------------------------------------------------------*/
50 GStringChunk
* string_pool
;
61 NPWPropertyOptions options
;
76 static const gchar
* NPWPropertyTypeString
[] = {
88 *---------------------------------------------------------------------------*/
90 static NPWPropertyType
91 npw_property_type_from_string (const gchar
* type
)
95 for (i
= 0; i
< NPW_LAST_PROPERTY
; i
++)
97 if (strcmp (NPWPropertyTypeString
[i
], type
) == 0)
99 return (NPWPropertyType
)(i
+ 1);
103 return NPW_UNKNOWN_PROPERTY
;
108 npw_property_string_from_type (NPWPropertyType type
)
110 if ((type
> 0) && (type
< NPW_LAST_PROPERTY
))
112 return NPWPropertyTypeString
[type
- 1];
120 npw_property_new (NPWPage
* owner
)
124 g_return_val_if_fail (owner
, NULL
);
126 this = g_chunk_new0(NPWProperty
, owner
->data_pool
);
128 this->type
= NPW_UNKNOWN_PROPERTY
;
130 /* value is set to NULL */
131 g_node_append_data (owner
->list
, this);
137 npw_property_free (NPWProperty
* this)
141 if (this->item
!= NULL
)
143 g_slist_free (this->item
);
145 node
= g_node_find_child (this->owner
->list
, G_TRAVERSE_ALL
, this);
148 g_node_destroy (node
);
149 /* Memory allocated in string pool and data pool is not free */
154 npw_property_set_type (NPWProperty
* this, NPWPropertyType type
)
160 npw_property_set_string_type (NPWProperty
* this, const gchar
* type
)
162 npw_property_set_type (this, npw_property_type_from_string (type
));
167 npw_property_get_type (const NPWProperty
* this)
173 npw_property_set_name (NPWProperty
* this, const gchar
* name
)
175 this->value
= npw_value_heap_find_value (this->owner
->value
, name
);
179 npw_property_get_name (const NPWProperty
* this)
181 return npw_value_heap_get_name (this->owner
->value
, this->value
);
185 npw_property_set_label (NPWProperty
* this, const gchar
* label
)
187 this->label
= g_string_chunk_insert (this->owner
->string_pool
, label
);
191 npw_property_get_label (const NPWProperty
* this)
197 npw_property_set_description (NPWProperty
* this, const gchar
* description
)
199 this->description
= g_string_chunk_insert (this->owner
->string_pool
, description
);
203 npw_property_get_description (const NPWProperty
* this)
205 return this->description
;
209 cb_boolean_button_toggled (GtkButton
*button
, gpointer data
)
211 if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button
)))
212 gtk_button_set_label (button
, _("Yes"));
214 gtk_button_set_label (button
, _("No"));
218 npw_property_create_widget (NPWProperty
* this)
223 value
= npw_property_get_value (this);
226 case NPW_BOOLEAN_PROPERTY
:
227 entry
= gtk_toggle_button_new_with_label (_("No"));
228 g_signal_connect (G_OBJECT (entry
), "toggled",
229 G_CALLBACK (cb_boolean_button_toggled
), NULL
);
232 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (entry
),
233 (gboolean
)atoi (value
));
236 case NPW_INTEGER_PROPERTY
:
237 entry
= gtk_spin_button_new (NULL
, 1, 0);
240 gtk_spin_button_set_value (GTK_SPIN_BUTTON (entry
), atoi (value
));
243 case NPW_STRING_PROPERTY
:
244 entry
= gtk_entry_new ();
245 if (value
) gtk_entry_set_text (GTK_ENTRY (entry
), value
);
247 case NPW_DIRECTORY_PROPERTY
:
248 entry
= gtk_file_chooser_button_new (_("Choose directory"),
249 GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER
);
252 gchar
* uri
= gnome_vfs_make_uri_from_input (value
);
253 gtk_file_chooser_set_uri (GTK_FILE_CHOOSER (entry
), uri
);
257 case NPW_FILE_PROPERTY
:
258 entry
= gtk_file_chooser_button_new (_("Choose file"),
259 GTK_FILE_CHOOSER_ACTION_OPEN
);
262 gchar
* uri
= gnome_vfs_make_uri_from_input (value
);
263 gtk_file_chooser_set_uri (GTK_FILE_CHOOSER (entry
), uri
);
267 case NPW_ICON_PROPERTY
:
268 entry
= gnome_icon_entry_new("icon_choice", _("Icon choice"));
269 if (value
) gnome_icon_entry_set_filename (GNOME_ICON_ENTRY (entry
), value
);
271 case NPW_LIST_PROPERTY
:
274 gboolean get_value
= FALSE
;
276 entry
= gtk_combo_box_entry_new_text ();
277 for (node
= this->item
; node
!= NULL
; node
= node
->next
)
279 gtk_combo_box_append_text (GTK_COMBO_BOX (entry
), _(((NPWItem
*)node
->data
)->label
));
280 if ((value
!= NULL
) && !get_value
&& (strcmp (value
, ((NPWItem
*)node
->data
)->name
) == 0))
282 value
= _(((NPWItem
*)node
->data
)->label
);
286 if (!(this->options
& NPW_EDITABLE_OPTION
))
288 gtk_editable_set_editable (GTK_EDITABLE (GTK_BIN (entry
)->child
), FALSE
);
290 if (value
) gtk_entry_set_text (GTK_ENTRY (GTK_BIN (entry
)->child
), value
);
296 this->widget
= entry
;
302 npw_property_set_widget (NPWProperty
* this, GtkWidget
* widget
)
304 this->widget
= widget
;
308 npw_property_get_widget (const NPWProperty
* this)
314 npw_property_set_default (NPWProperty
* this, const gchar
* value
)
316 /* Check if the default property is valid */
317 if (value
&& (this->options
& NPW_EXIST_SET_OPTION
) && !(this->options
& NPW_EXIST_OPTION
))
319 /* a file or directory with the same name shouldn't exist */
320 if (g_file_test (value
, G_FILE_TEST_EXISTS
))
325 /* Allocate memory for the string and a decimal number */
326 buffer
= g_new (char, strlen(value
) + 8);
327 /* Give up after 1000000 tries */
328 for (i
= 1; i
< 1000000; i
++)
330 sprintf(buffer
,"%s%d",value
, i
);
331 if (!g_file_test (buffer
, G_FILE_TEST_EXISTS
)) break;
333 this->defvalue
= g_string_chunk_insert (this->owner
->string_pool
, buffer
);
339 /* This function could be used with value = defvalue to only check
340 * the default property */
341 if (this->defvalue
!= value
)
343 this->defvalue
= (value
== NULL
) ? NULL
: g_string_chunk_insert (this->owner
->string_pool
, value
);
348 npw_property_set_value_from_widget (NPWProperty
* this, NPWValueTag tag
)
350 gchar
* alloc_value
= NULL
;
351 const gchar
* value
= NULL
;
356 case NPW_INTEGER_PROPERTY
:
357 alloc_value
= g_strdup_printf("%d", gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (this->widget
)));
360 case NPW_BOOLEAN_PROPERTY
:
361 alloc_value
= g_strdup_printf("%d", gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (this->widget
)));
364 case NPW_STRING_PROPERTY
:
365 value
= gtk_entry_get_text (GTK_ENTRY (this->widget
));
367 case NPW_DIRECTORY_PROPERTY
:
368 case NPW_FILE_PROPERTY
:
369 alloc_value
= gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (this->widget
));
372 case NPW_ICON_PROPERTY
:
373 alloc_value
= gnome_icon_entry_get_filename (GNOME_ICON_ENTRY (this->widget
));
376 case NPW_LIST_PROPERTY
:
380 value
= gtk_entry_get_text (GTK_ENTRY (GTK_BIN (this->widget
)->child
));
381 for (node
= this->item
; node
!= NULL
; node
= node
->next
)
383 if (strcmp (value
, _(((NPWItem
*)node
->data
)->label
)) == 0)
385 value
= ((NPWItem
*)node
->data
)->name
;
392 /* Hidden property */
393 value
= this->defvalue
;
397 /* Check and mark default value (will not be saved) */
398 if ((value
) && (this->defvalue
) && (strcmp (value
, this->defvalue
) == 0))
400 tag
|= NPW_DEFAULT_VALUE
;
403 ok
= npw_value_heap_set_value (this->owner
->value
, this->value
, value
, tag
);
404 if (alloc_value
!= NULL
) g_free (alloc_value
);
410 npw_property_update_value_from_widget (NPWProperty
* this)
412 return npw_property_set_value_from_widget (this, NPW_VALID_VALUE
);
416 npw_property_save_value_from_widget (NPWProperty
* this)
418 return npw_property_set_value_from_widget (this, NPW_OLD_VALUE
);
422 npw_property_remove_value (NPWProperty
* this)
424 return npw_value_heap_set_value (this->owner
->value
, this->value
, NULL
, NPW_EMPTY_VALUE
);
428 npw_property_get_value (const NPWProperty
* this)
432 tag
= npw_value_heap_get_tag (this->owner
->value
, this->value
);
433 if ((tag
== NPW_EMPTY_VALUE
) || (tag
& NPW_DEFAULT_VALUE
))
435 return this->defvalue
;
439 /* Only value entered by user could replace default value */
440 return npw_value_heap_get_value (this->owner
->value
, this->value
);
445 npw_property_add_list_item (NPWProperty
* this, const gchar
* name
, const gchar
* label
)
449 item
= g_chunk_new (NPWItem
, this->owner
->item_pool
);
450 item
->name
= g_string_chunk_insert (this->owner
->string_pool
, name
);
451 item
->label
= g_string_chunk_insert (this->owner
->string_pool
, label
);
453 this->item
= g_slist_append (this->item
, item
);
459 npw_property_set_mandatory_option (NPWProperty
* this, gboolean value
)
463 this->options
|= NPW_MANDATORY_OPTION
;
467 this->options
&= ~NPW_MANDATORY_OPTION
;
472 npw_property_set_summary_option (NPWProperty
* this, gboolean value
)
476 this->options
|= NPW_SUMMARY_OPTION
;
480 this->options
&= ~NPW_SUMMARY_OPTION
;
485 npw_property_set_editable_option (NPWProperty
* this, gboolean value
)
489 this->options
|= NPW_EDITABLE_OPTION
;
493 this->options
&= ~NPW_EDITABLE_OPTION
;
498 npw_property_get_options (const NPWProperty
* this)
500 return this->options
;
504 npw_property_set_exist_option (NPWProperty
* this, NPWPropertyBooleanValue value
)
509 this->options
|= NPW_EXIST_OPTION
| NPW_EXIST_SET_OPTION
;
512 this->options
&= ~NPW_EXIST_OPTION
;
513 this->options
|= NPW_EXIST_SET_OPTION
;
514 npw_property_set_default (this, this->defvalue
);
517 this->options
&= ~(NPW_EXIST_OPTION
| NPW_EXIST_SET_OPTION
);
522 NPWPropertyBooleanValue
523 npw_property_get_exist_option (const NPWProperty
* this)
525 return this->options
& NPW_EXIST_SET_OPTION
? (this->options
& NPW_EXIST_OPTION
? NPW_TRUE
: NPW_FALSE
) : NPW_DEFAULT
;
528 /* Page object = list of properties
529 *---------------------------------------------------------------------------*/
532 npw_page_new (NPWValueHeap
* value
)
536 this = g_new0(NPWPage
, 1);
537 this->string_pool
= g_string_chunk_new (STRING_CHUNK_SIZE
);
538 this->data_pool
= g_mem_chunk_new ("property pool", sizeof (NPWProperty
), STRING_CHUNK_SIZE
* sizeof (NPWProperty
) / 4, G_ALLOC_ONLY
);
539 this->item_pool
= g_mem_chunk_new ("item pool", sizeof (NPWItem
), STRING_CHUNK_SIZE
* sizeof (NPWItem
) / 4, G_ALLOC_ONLY
);
540 this->list
= g_node_new (NULL
);
547 npw_page_free (NPWPage
* this)
549 g_return_if_fail (this != NULL
);
551 g_string_chunk_free (this->string_pool
);
552 g_mem_chunk_destroy (this->data_pool
);
553 g_mem_chunk_destroy (this->item_pool
);
554 g_node_destroy (this->list
);
559 npw_page_set_name (NPWPage
* this, const gchar
* name
)
561 this->name
= g_string_chunk_insert (this->string_pool
, name
);
565 npw_page_get_name (const NPWPage
* this)
571 npw_page_set_label (NPWPage
* this, const gchar
* label
)
573 this->label
= g_string_chunk_insert (this->string_pool
, label
);
577 npw_page_get_label (const NPWPage
* this)
583 npw_page_set_description (NPWPage
* this, const gchar
* description
)
585 this->description
= g_string_chunk_insert (this->string_pool
, description
);
589 npw_page_get_description (const NPWPage
* this)
591 return this->description
;
594 typedef struct _PageForeachPropertyData
596 NPWPropertyForeachFunc func
;
598 } PageForeachPropertyData
;
601 cb_page_foreach_property (GNode
* node
, gpointer data
)
603 PageForeachPropertyData
* d
= (PageForeachPropertyData
*)data
;
605 (d
->func
)((NPWProperty
*)node
->data
, d
->data
);
609 npw_page_foreach_property (const NPWPage
* this, NPWPropertyForeachFunc func
, gpointer data
)
611 PageForeachPropertyData d
;
615 g_node_children_foreach (this->list
, G_TRAVERSE_LEAFS
, cb_page_foreach_property
, &d
);