Updated Spanish translation
[anjuta-git-plugin.git] / plugins / project-wizard / property.c
blob5a6d73061ef7bf6c39880a489c0646391d98c87e
1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
2 /*
3 property.c
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 *---------------------------------------------------------------------------*/
26 #include <config.h>
28 #include "property.h"
30 #include <glib/gdir.h>
32 #include <gnome.h>
33 #include <libgnome/gnome-i18n.h>
34 #include <libgnomevfs/gnome-vfs-utils.h>
36 #include <string.h>
37 #include <stdlib.h>
39 #include <libanjuta/anjuta-debug.h>
41 /*---------------------------------------------------------------------------*/
43 #define STRING_CHUNK_SIZE 256
45 /*---------------------------------------------------------------------------*/
47 struct _NPWPage
49 GNode* list;
50 GStringChunk* string_pool;
51 GMemChunk* data_pool;
52 GMemChunk* item_pool;
53 NPWValueHeap* value;
54 gchar* name;
55 gchar* label;
56 gchar* description;
59 struct _NPWProperty {
60 NPWPropertyType type;
61 NPWPropertyOptions options;
62 gchar* label;
63 gchar* description;
64 gchar* defvalue;
65 NPWValue* value;
66 GtkWidget* widget;
67 NPWPage* owner;
68 GSList* item;
71 struct _NPWItem {
72 const gchar* name;
73 const gchar* label;
76 static const gchar* NPWPropertyTypeString[] = {
77 "hidden",
78 "boolean",
79 "integer",
80 "string",
81 "list",
82 "directory",
83 "file",
84 "icon"
87 /* Property object
88 *---------------------------------------------------------------------------*/
90 static NPWPropertyType
91 npw_property_type_from_string (const gchar* type)
93 gint i;
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;
106 #if 0
107 static const gchar*
108 npw_property_string_from_type (NPWPropertyType type)
110 if ((type > 0) && (type < NPW_LAST_PROPERTY))
112 return NPWPropertyTypeString[type - 1];
115 return NULL;
117 #endif
119 NPWProperty*
120 npw_property_new (NPWPage* owner)
122 NPWProperty* this;
124 g_return_val_if_fail (owner, NULL);
126 this = g_chunk_new0(NPWProperty, owner->data_pool);
127 this->owner = owner;
128 this->type = NPW_UNKNOWN_PROPERTY;
129 this->item = NULL;
130 /* value is set to NULL */
131 g_node_append_data (owner->list, this);
133 return this;
136 void
137 npw_property_free (NPWProperty* this)
139 GNode* node;
141 if (this->item != NULL)
143 g_slist_free (this->item);
145 node = g_node_find_child (this->owner->list, G_TRAVERSE_ALL, this);
146 if (node != NULL)
148 g_node_destroy (node);
149 /* Memory allocated in string pool and data pool is not free */
153 void
154 npw_property_set_type (NPWProperty* this, NPWPropertyType type)
156 this->type = type;
159 void
160 npw_property_set_string_type (NPWProperty* this, const gchar* type)
162 npw_property_set_type (this, npw_property_type_from_string (type));
166 NPWPropertyType
167 npw_property_get_type (const NPWProperty* this)
169 return this->type;
172 void
173 npw_property_set_name (NPWProperty* this, const gchar* name)
175 this->value = npw_value_heap_find_value (this->owner->value, name);
178 const gchar*
179 npw_property_get_name (const NPWProperty* this)
181 return npw_value_heap_get_name (this->owner->value, this->value);
184 void
185 npw_property_set_label (NPWProperty* this, const gchar* label)
187 this->label = g_string_chunk_insert (this->owner->string_pool, label);
190 const gchar*
191 npw_property_get_label (const NPWProperty* this)
193 return this->label;
196 void
197 npw_property_set_description (NPWProperty* this, const gchar* description)
199 this->description = g_string_chunk_insert (this->owner->string_pool, description);
202 const gchar*
203 npw_property_get_description (const NPWProperty* this)
205 return this->description;
208 static void
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"));
213 else
214 gtk_button_set_label (button, _("No"));
217 GtkWidget*
218 npw_property_create_widget (NPWProperty* this)
220 GtkWidget* entry;
221 const gchar* value;
223 value = npw_property_get_value (this);
224 switch (this->type)
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);
230 if (value)
232 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (entry),
233 (gboolean)atoi (value));
235 break;
236 case NPW_INTEGER_PROPERTY:
237 entry = gtk_spin_button_new (NULL, 1, 0);
238 if (value)
240 gtk_spin_button_set_value (GTK_SPIN_BUTTON (entry), atoi (value));
242 break;
243 case NPW_STRING_PROPERTY:
244 entry = gtk_entry_new ();
245 if (value) gtk_entry_set_text (GTK_ENTRY (entry), value);
246 break;
247 case NPW_DIRECTORY_PROPERTY:
248 entry = gtk_file_chooser_button_new (_("Choose directory"),
249 GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER);
250 if (value)
252 gchar* uri = gnome_vfs_make_uri_from_input (value);
253 gtk_file_chooser_set_uri (GTK_FILE_CHOOSER (entry), uri);
254 g_free (uri);
256 break;
257 case NPW_FILE_PROPERTY:
258 entry = gtk_file_chooser_button_new (_("Choose file"),
259 GTK_FILE_CHOOSER_ACTION_OPEN);
260 if (value)
262 gchar* uri = gnome_vfs_make_uri_from_input (value);
263 gtk_file_chooser_set_uri (GTK_FILE_CHOOSER (entry), uri);
264 g_free (uri);
266 break;
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);
270 break;
271 case NPW_LIST_PROPERTY:
273 GSList* node;
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);
283 get_value = TRUE;
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);
291 break;
293 default:
294 return NULL;
296 this->widget = entry;
298 return entry;
301 void
302 npw_property_set_widget (NPWProperty* this, GtkWidget* widget)
304 this->widget = widget;
307 GtkWidget*
308 npw_property_get_widget (const NPWProperty* this)
310 return this->widget;
313 void
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))
322 char* buffer;
323 guint i;
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);
334 g_free (buffer);
336 return;
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);
347 static gboolean
348 npw_property_set_value_from_widget (NPWProperty* this, NPWValueTag tag)
350 gchar* alloc_value = NULL;
351 const gchar* value = NULL;
352 gboolean ok;
354 switch (this->type)
356 case NPW_INTEGER_PROPERTY:
357 alloc_value = g_strdup_printf("%d", gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (this->widget)));
358 value = alloc_value;
359 break;
360 case NPW_BOOLEAN_PROPERTY:
361 alloc_value = g_strdup_printf("%d", gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (this->widget)));
362 value = alloc_value;
363 break;
364 case NPW_STRING_PROPERTY:
365 value = gtk_entry_get_text (GTK_ENTRY (this->widget));
366 break;
367 case NPW_DIRECTORY_PROPERTY:
368 case NPW_FILE_PROPERTY:
369 alloc_value = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (this->widget));
370 value = alloc_value;
371 break;
372 case NPW_ICON_PROPERTY:
373 alloc_value = gnome_icon_entry_get_filename (GNOME_ICON_ENTRY (this->widget));
374 value = alloc_value;
375 break;
376 case NPW_LIST_PROPERTY:
378 GSList* node;
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;
386 break;
389 break;
391 default:
392 /* Hidden property */
393 value = this->defvalue;
394 break;
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);
406 return ok;
409 gboolean
410 npw_property_update_value_from_widget (NPWProperty* this)
412 return npw_property_set_value_from_widget (this, NPW_VALID_VALUE);
415 gboolean
416 npw_property_save_value_from_widget (NPWProperty* this)
418 return npw_property_set_value_from_widget (this, NPW_OLD_VALUE);
421 gboolean
422 npw_property_remove_value (NPWProperty* this)
424 return npw_value_heap_set_value (this->owner->value, this->value, NULL, NPW_EMPTY_VALUE);
427 const char*
428 npw_property_get_value (const NPWProperty* this)
430 NPWValueTag tag;
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;
437 else
439 /* Only value entered by user could replace default value */
440 return npw_value_heap_get_value (this->owner->value, this->value);
444 gboolean
445 npw_property_add_list_item (NPWProperty* this, const gchar* name, const gchar* label)
447 NPWItem* item;
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);
455 return TRUE;
458 void
459 npw_property_set_mandatory_option (NPWProperty* this, gboolean value)
461 if (value)
463 this->options |= NPW_MANDATORY_OPTION;
465 else
467 this->options &= ~NPW_MANDATORY_OPTION;
471 void
472 npw_property_set_summary_option (NPWProperty* this, gboolean value)
474 if (value)
476 this->options |= NPW_SUMMARY_OPTION;
478 else
480 this->options &= ~NPW_SUMMARY_OPTION;
484 void
485 npw_property_set_editable_option (NPWProperty* this, gboolean value)
487 if (value)
489 this->options |= NPW_EDITABLE_OPTION;
491 else
493 this->options &= ~NPW_EDITABLE_OPTION;
497 NPWPropertyOptions
498 npw_property_get_options (const NPWProperty* this)
500 return this->options;
503 void
504 npw_property_set_exist_option (NPWProperty* this, NPWPropertyBooleanValue value)
506 switch (value)
508 case NPW_TRUE:
509 this->options |= NPW_EXIST_OPTION | NPW_EXIST_SET_OPTION;
510 break;
511 case NPW_FALSE:
512 this->options &= ~NPW_EXIST_OPTION;
513 this->options |= NPW_EXIST_SET_OPTION;
514 npw_property_set_default (this, this->defvalue);
515 break;
516 case NPW_DEFAULT:
517 this->options &= ~(NPW_EXIST_OPTION | NPW_EXIST_SET_OPTION);
518 break;
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 *---------------------------------------------------------------------------*/
531 NPWPage*
532 npw_page_new (NPWValueHeap* value)
534 NPWPage* this;
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);
541 this->value = value;
543 return this;
546 void
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);
555 g_free (this);
558 void
559 npw_page_set_name (NPWPage* this, const gchar* name)
561 this->name = g_string_chunk_insert (this->string_pool, name);
564 const gchar*
565 npw_page_get_name (const NPWPage* this)
567 return this->name;
570 void
571 npw_page_set_label (NPWPage* this, const gchar* label)
573 this->label = g_string_chunk_insert (this->string_pool, label);
576 const gchar*
577 npw_page_get_label (const NPWPage* this)
579 return this->label;
582 void
583 npw_page_set_description (NPWPage* this, const gchar* description)
585 this->description = g_string_chunk_insert (this->string_pool, description);
588 const gchar*
589 npw_page_get_description (const NPWPage* this)
591 return this->description;
594 typedef struct _PageForeachPropertyData
596 NPWPropertyForeachFunc func;
597 gpointer data;
598 } PageForeachPropertyData;
600 static void
601 cb_page_foreach_property (GNode* node, gpointer data)
603 PageForeachPropertyData* d = (PageForeachPropertyData *)data;
605 (d->func)((NPWProperty*)node->data, d->data);
608 void
609 npw_page_foreach_property (const NPWPage* this, NPWPropertyForeachFunc func, gpointer data)
611 PageForeachPropertyData d;
613 d.func = func;
614 d.data = data;
615 g_node_children_foreach (this->list, G_TRAVERSE_LEAFS, cb_page_foreach_property, &d);