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 <glib/gi18n.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 NPWPropertyType restriction
;
62 NPWPropertyOptions options
;
77 static const gchar
* NPWPropertyTypeString
[] = {
88 static const gchar
* NPWPropertyRestrictionString
[] = {
93 *---------------------------------------------------------------------------*/
95 static NPWPropertyType
96 npw_property_type_from_string (const gchar
* type
)
100 for (i
= 0; i
< NPW_LAST_PROPERTY
; i
++)
102 if (strcmp (NPWPropertyTypeString
[i
], type
) == 0)
104 return (NPWPropertyType
)(i
+ 1);
108 return NPW_UNKNOWN_PROPERTY
;
111 static NPWPropertyRestriction
112 npw_property_restriction_from_string (const gchar
* restriction
)
115 if (restriction
!= NULL
)
119 for (i
= 0; i
< NPW_LAST_RESTRICTION
; i
++)
121 if (strcmp (NPWPropertyRestrictionString
[i
], restriction
) == 0)
123 return (NPWPropertyRestriction
)(i
+ 1);
128 return NPW_NO_RESTRICTION
;
132 npw_property_new (NPWPage
* owner
)
136 g_return_val_if_fail (owner
, NULL
);
138 this = g_chunk_new0(NPWProperty
, owner
->data_pool
);
140 this->type
= NPW_UNKNOWN_PROPERTY
;
141 this->restriction
= NPW_NO_RESTRICTION
;
143 /* value is set to NULL */
144 g_node_append_data (owner
->list
, this);
150 npw_property_free (NPWProperty
* this)
154 if (this->item
!= NULL
)
156 g_slist_free (this->item
);
158 node
= g_node_find_child (this->owner
->list
, G_TRAVERSE_ALL
, this);
161 g_node_destroy (node
);
162 /* Memory allocated in string pool and data pool is not free */
167 npw_property_set_type (NPWProperty
* this, NPWPropertyType type
)
173 npw_property_set_string_type (NPWProperty
* this, const gchar
* type
)
175 npw_property_set_type (this, npw_property_type_from_string (type
));
180 npw_property_get_type (const NPWProperty
* this)
186 npw_property_set_restriction (NPWProperty
* this, NPWPropertyRestriction restriction
)
188 this->restriction
= restriction
;
192 npw_property_set_string_restriction (NPWProperty
* this, const gchar
* restriction
)
194 npw_property_set_restriction (this, npw_property_restriction_from_string (restriction
));
197 NPWPropertyRestriction
198 npw_property_get_restriction (const NPWProperty
* this)
200 return this->restriction
;
204 npw_property_is_valid_restriction (const NPWProperty
* this)
208 switch (this->restriction
)
210 case NPW_FILENAME_RESTRICTION
:
211 value
= npw_property_get_value (this);
213 /* First character should be letters, digit or '_' */
214 if (value
== NULL
) return TRUE
;
215 if (!isalnum (*value
) && (*value
!= '_'))
218 /* Following characters should be letters, digit or '_'
220 for (value
++; *value
!= '\0'; value
++)
222 if (!isalnum (*value
)
237 npw_property_set_name (NPWProperty
* this, const gchar
* name
)
239 this->value
= npw_value_heap_find_value (this->owner
->value
, name
);
243 npw_property_get_name (const NPWProperty
* this)
245 return npw_value_heap_get_name (this->owner
->value
, this->value
);
249 npw_property_set_label (NPWProperty
* this, const gchar
* label
)
251 this->label
= g_string_chunk_insert (this->owner
->string_pool
, label
);
255 npw_property_get_label (const NPWProperty
* this)
261 npw_property_set_description (NPWProperty
* this, const gchar
* description
)
263 this->description
= g_string_chunk_insert (this->owner
->string_pool
, description
);
267 npw_property_get_description (const NPWProperty
* this)
269 return this->description
;
273 cb_boolean_button_toggled (GtkButton
*button
, gpointer data
)
275 if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button
)))
276 gtk_button_set_label (button
, _("Yes"));
278 gtk_button_set_label (button
, _("No"));
282 npw_property_create_widget (NPWProperty
* this)
287 value
= npw_property_get_value (this);
290 case NPW_BOOLEAN_PROPERTY
:
291 entry
= gtk_toggle_button_new_with_label (_("No"));
292 g_signal_connect (G_OBJECT (entry
), "toggled",
293 G_CALLBACK (cb_boolean_button_toggled
), NULL
);
296 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (entry
),
297 (gboolean
)atoi (value
));
300 case NPW_INTEGER_PROPERTY
:
301 entry
= gtk_spin_button_new (NULL
, 1, 0);
304 gtk_spin_button_set_value (GTK_SPIN_BUTTON (entry
), atoi (value
));
307 case NPW_STRING_PROPERTY
:
308 entry
= gtk_entry_new ();
309 if (value
) gtk_entry_set_text (GTK_ENTRY (entry
), value
);
311 case NPW_DIRECTORY_PROPERTY
:
312 entry
= gtk_file_chooser_button_new (_("Choose directory"),
313 GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER
);
316 gchar
* uri
= gnome_vfs_make_uri_from_input (value
);
317 gtk_file_chooser_set_uri (GTK_FILE_CHOOSER (entry
), uri
);
321 case NPW_FILE_PROPERTY
:
322 entry
= gtk_file_chooser_button_new (_("Choose file"),
323 GTK_FILE_CHOOSER_ACTION_OPEN
);
326 gchar
* uri
= gnome_vfs_make_uri_from_input (value
);
327 gtk_file_chooser_set_uri (GTK_FILE_CHOOSER (entry
), uri
);
331 case NPW_ICON_PROPERTY
:
332 entry
= gnome_icon_entry_new("icon_choice", _("Icon choice"));
333 if (value
) gnome_icon_entry_set_filename (GNOME_ICON_ENTRY (entry
), value
);
335 case NPW_LIST_PROPERTY
:
338 gboolean get_value
= FALSE
;
340 entry
= gtk_combo_box_entry_new_text ();
341 for (node
= this->item
; node
!= NULL
; node
= node
->next
)
343 gtk_combo_box_append_text (GTK_COMBO_BOX (entry
), _(((NPWItem
*)node
->data
)->label
));
344 if ((value
!= NULL
) && !get_value
&& (strcmp (value
, ((NPWItem
*)node
->data
)->name
) == 0))
346 value
= _(((NPWItem
*)node
->data
)->label
);
350 if (!(this->options
& NPW_EDITABLE_OPTION
))
352 gtk_editable_set_editable (GTK_EDITABLE (GTK_BIN (entry
)->child
), FALSE
);
354 if (value
) gtk_entry_set_text (GTK_ENTRY (GTK_BIN (entry
)->child
), value
);
360 this->widget
= entry
;
366 npw_property_set_widget (NPWProperty
* this, GtkWidget
* widget
)
368 this->widget
= widget
;
372 npw_property_get_widget (const NPWProperty
* this)
378 npw_property_set_default (NPWProperty
* this, const gchar
* value
)
380 /* Check if the default property is valid */
381 if (value
&& (this->options
& NPW_EXIST_SET_OPTION
) && !(this->options
& NPW_EXIST_OPTION
))
383 /* a file or directory with the same name shouldn't exist */
384 if (g_file_test (value
, G_FILE_TEST_EXISTS
))
389 /* Allocate memory for the string and a decimal number */
390 buffer
= g_new (char, strlen(value
) + 8);
391 /* Give up after 1000000 tries */
392 for (i
= 1; i
< 1000000; i
++)
394 sprintf(buffer
,"%s%d",value
, i
);
395 if (!g_file_test (buffer
, G_FILE_TEST_EXISTS
)) break;
397 this->defvalue
= g_string_chunk_insert (this->owner
->string_pool
, buffer
);
403 /* This function could be used with value = defvalue to only check
404 * the default property */
405 if (this->defvalue
!= value
)
407 this->defvalue
= (value
== NULL
) ? NULL
: g_string_chunk_insert (this->owner
->string_pool
, value
);
412 npw_property_set_value_from_widget (NPWProperty
* this, NPWValueTag tag
)
414 gchar
* alloc_value
= NULL
;
415 const gchar
* value
= NULL
;
420 case NPW_INTEGER_PROPERTY
:
421 alloc_value
= g_strdup_printf("%d", gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (this->widget
)));
424 case NPW_BOOLEAN_PROPERTY
:
425 alloc_value
= g_strdup_printf("%d", gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (this->widget
)));
428 case NPW_STRING_PROPERTY
:
429 value
= gtk_entry_get_text (GTK_ENTRY (this->widget
));
431 case NPW_DIRECTORY_PROPERTY
:
432 case NPW_FILE_PROPERTY
:
433 alloc_value
= gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (this->widget
));
436 case NPW_ICON_PROPERTY
:
437 alloc_value
= gnome_icon_entry_get_filename (GNOME_ICON_ENTRY (this->widget
));
440 case NPW_LIST_PROPERTY
:
444 value
= gtk_entry_get_text (GTK_ENTRY (GTK_BIN (this->widget
)->child
));
445 for (node
= this->item
; node
!= NULL
; node
= node
->next
)
447 if (strcmp (value
, _(((NPWItem
*)node
->data
)->label
)) == 0)
449 value
= ((NPWItem
*)node
->data
)->name
;
456 /* Hidden property */
457 value
= this->defvalue
;
461 /* Check and mark default value (will not be saved) */
462 if ((value
) && (this->defvalue
) && (strcmp (value
, this->defvalue
) == 0))
464 tag
|= NPW_DEFAULT_VALUE
;
467 ok
= npw_value_heap_set_value (this->owner
->value
, this->value
, value
, tag
);
468 if (alloc_value
!= NULL
) g_free (alloc_value
);
474 npw_property_update_value_from_widget (NPWProperty
* this)
476 return npw_property_set_value_from_widget (this, NPW_VALID_VALUE
);
480 npw_property_save_value_from_widget (NPWProperty
* this)
482 return npw_property_set_value_from_widget (this, NPW_OLD_VALUE
);
486 npw_property_remove_value (NPWProperty
* this)
488 return npw_value_heap_set_value (this->owner
->value
, this->value
, NULL
, NPW_EMPTY_VALUE
);
492 npw_property_get_value (const NPWProperty
* this)
496 tag
= npw_value_heap_get_tag (this->owner
->value
, this->value
);
497 if ((tag
== NPW_EMPTY_VALUE
) || (tag
& NPW_DEFAULT_VALUE
))
499 return this->defvalue
;
503 /* Only value entered by user could replace default value */
504 return npw_value_heap_get_value (this->owner
->value
, this->value
);
509 npw_property_add_list_item (NPWProperty
* this, const gchar
* name
, const gchar
* label
)
513 item
= g_chunk_new (NPWItem
, this->owner
->item_pool
);
514 item
->name
= g_string_chunk_insert (this->owner
->string_pool
, name
);
515 item
->label
= g_string_chunk_insert (this->owner
->string_pool
, label
);
517 this->item
= g_slist_append (this->item
, item
);
523 npw_property_set_mandatory_option (NPWProperty
* this, gboolean value
)
527 this->options
|= NPW_MANDATORY_OPTION
;
531 this->options
&= ~NPW_MANDATORY_OPTION
;
536 npw_property_set_summary_option (NPWProperty
* this, gboolean value
)
540 this->options
|= NPW_SUMMARY_OPTION
;
544 this->options
&= ~NPW_SUMMARY_OPTION
;
549 npw_property_set_editable_option (NPWProperty
* this, gboolean value
)
553 this->options
|= NPW_EDITABLE_OPTION
;
557 this->options
&= ~NPW_EDITABLE_OPTION
;
562 npw_property_get_options (const NPWProperty
* this)
564 return this->options
;
568 npw_property_set_exist_option (NPWProperty
* this, NPWPropertyBooleanValue value
)
573 this->options
|= NPW_EXIST_OPTION
| NPW_EXIST_SET_OPTION
;
576 this->options
&= ~NPW_EXIST_OPTION
;
577 this->options
|= NPW_EXIST_SET_OPTION
;
578 npw_property_set_default (this, this->defvalue
);
581 this->options
&= ~(NPW_EXIST_OPTION
| NPW_EXIST_SET_OPTION
);
586 NPWPropertyBooleanValue
587 npw_property_get_exist_option (const NPWProperty
* this)
589 return this->options
& NPW_EXIST_SET_OPTION
? (this->options
& NPW_EXIST_OPTION
? NPW_TRUE
: NPW_FALSE
) : NPW_DEFAULT
;
592 /* Page object = list of properties
593 *---------------------------------------------------------------------------*/
596 npw_page_new (NPWValueHeap
* value
)
600 this = g_new0(NPWPage
, 1);
601 this->string_pool
= g_string_chunk_new (STRING_CHUNK_SIZE
);
602 this->data_pool
= g_mem_chunk_new ("property pool", sizeof (NPWProperty
), STRING_CHUNK_SIZE
* sizeof (NPWProperty
) / 4, G_ALLOC_ONLY
);
603 this->item_pool
= g_mem_chunk_new ("item pool", sizeof (NPWItem
), STRING_CHUNK_SIZE
* sizeof (NPWItem
) / 4, G_ALLOC_ONLY
);
604 this->list
= g_node_new (NULL
);
611 npw_page_free (NPWPage
* this)
613 g_return_if_fail (this != NULL
);
615 g_string_chunk_free (this->string_pool
);
616 g_mem_chunk_destroy (this->data_pool
);
617 g_mem_chunk_destroy (this->item_pool
);
618 g_node_destroy (this->list
);
623 npw_page_set_name (NPWPage
* this, const gchar
* name
)
625 this->name
= g_string_chunk_insert (this->string_pool
, name
);
629 npw_page_get_name (const NPWPage
* this)
635 npw_page_set_label (NPWPage
* this, const gchar
* label
)
637 this->label
= g_string_chunk_insert (this->string_pool
, label
);
641 npw_page_get_label (const NPWPage
* this)
647 npw_page_set_description (NPWPage
* this, const gchar
* description
)
649 this->description
= g_string_chunk_insert (this->string_pool
, description
);
653 npw_page_get_description (const NPWPage
* this)
655 return this->description
;
658 typedef struct _PageForeachPropertyData
660 NPWPropertyForeachFunc func
;
662 } PageForeachPropertyData
;
665 cb_page_foreach_property (GNode
* node
, gpointer data
)
667 PageForeachPropertyData
* d
= (PageForeachPropertyData
*)data
;
669 (d
->func
)((NPWProperty
*)node
->data
, d
->data
);
673 npw_page_foreach_property (const NPWPage
* this, NPWPropertyForeachFunc func
, gpointer data
)
675 PageForeachPropertyData d
;
679 g_node_children_foreach (this->list
, G_TRAVERSE_LEAFS
, cb_page_foreach_property
, &d
);