Fix a Gtk warning when checking path input in the log viewer.
[anjuta-git-plugin.git] / plugins / project-wizard / druid.c
blobb972dbd9701811615bdc7addaff21bc11208e7bc
1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
2 /*
3 druid.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 * All GUI functions
24 *---------------------------------------------------------------------------*/
26 #include <config.h>
28 #include "druid.h"
30 #include "plugin.h"
31 #include "header.h"
32 #include "property.h"
33 #include "parser.h"
34 #include "install.h"
35 #include "autogen.h"
37 #include <libanjuta/anjuta-debug.h>
38 #include <libanjuta/anjuta-utils.h>
39 #include <libanjuta/interfaces/ianjuta-wizard.h>
41 #include <gnome.h>
42 #include <glib/gi18n.h>
44 #include <gtk/gtkactiongroup.h>
46 #include <string.h>
48 /*---------------------------------------------------------------------------*/
50 #define PROJECT_WIZARD_DIRECTORY PACKAGE_DATA_DIR"/project"
51 /* Uncomment if you want to keep project wizards in a non-standard dir
52 #define LOCAL_PROJECT_WIZARD_DIRECTORY anjuta_utils_data_dir/projects/
54 #define PIXMAP_APPWIZ_LOGO PACKAGE_DATA_DIR"/glade/applogo.png"
55 #define PIXMAP_APPWIZ_WATERMARK PACKAGE_DATA_DIR"/glade/appwizard.png"
57 /* Default property name useable in wizard file
58 *---------------------------------------------------------------------------*/
60 #define ANJUTA_PROJECT_DIRECTORY_PROPERTY "AnjutaProjectDirectory"
61 #define USER_NAME_PROPERTY "UserName"
62 #define EMAIL_ADDRESS_PROPERTY "EmailAddress"
64 /* Widget and signal name found in glade file
65 *---------------------------------------------------------------------------*/
67 #define NEW_PROJECT_DIALOG "druid_window"
68 #define PROJECT_SELECTION_LIST "project_list"
69 #define PROJECT_SELECTION_SCROLL_LIST "project_scroll_list"
70 #define PROJECT_SELECTION_FRAME "project_table"
71 #define PROJECT_SELECTION_BOOK "project_book"
72 #define PROJECT_SELECTION_BOOK_LABEL "project_book_label"
73 #define PROJECT_DESCRIPTION "project_description"
74 #define DRUID_WIDGET "druid"
75 #define DRUID_START_PAGE "start_page"
76 #define DRUID_SELECTION_PAGE "selection_page"
77 #define DRUID_PROPERTY_PAGE "property_page"
78 #define DRUID_PROPERTY_LABEL "property_label"
79 #define DRUID_PROPERTY_TABLE "property_table"
80 #define DRUID_FINISH_PAGE "finish_page"
82 #define DRUID_DELETE_SIGNAL "on_druid_delete"
83 #define DRUID_CANCEL_SIGNAL "on_druid_cancel"
84 #define DRUID_BACK_SIGNAL "on_druid_back"
85 #define DRUID_NEXT_SIGNAL "on_druid_next"
86 #define DRUID_FINISH_SIGNAL "on_druid_finish"
87 #define DRUID_PROJECT_SELECT_ICON_SIGNAL "on_druid_project_select_icon"
88 #define DRUID_PROJECT_SELECT_PAGE_SIGNAL "on_druid_project_map_page"
90 /*---------------------------------------------------------------------------*/
92 struct _NPWDruid
94 GtkWidget* dialog;
95 GtkNotebook* project_book;
96 GMemChunk* pool;
97 GnomeDruid* druid;
98 const gchar* project_file;
99 GnomeDruidPage* selection_page;
100 GnomeDruidPageStandard* property_page;
101 GtkLabel* property_label;
102 GtkTable* property_table;
103 GnomeDruidPage* finish_page;
104 GtkTooltips *tooltips;
105 NPWPlugin* plugin;
107 guint page;
108 GQueue* page_list;
109 NPWValueHeap* values;
110 NPWPageParser* parser;
111 NPWHeaderList* header_list;
112 NPWHeader* header;
113 NPWAutogen* gen;
114 gboolean busy;
117 typedef struct _NPWDruidAndTextBuffer
119 NPWDruid* druid;
120 GtkLabel* description;
121 NPWHeader* header;
122 } NPWDruidAndTextBuffer;
124 typedef union _NPWDruidStuff
126 NPWDruidAndTextBuffer a;
127 } NPWDruidStuff;
130 /* Create start and finish pages
131 *---------------------------------------------------------------------------*/
133 /* libGlade doesn't seem to set these parameters for the start and end page */
134 static void
135 npw_druid_fix_edge_pages (NPWDruid* this, GladeXML* xml)
137 GdkColor bg_color = {0, 15616, 33280, 46848};
138 GtkWidget* page;
139 GdkPixbuf* pixbuf;
141 /* Start page */
142 page = glade_xml_get_widget (xml, DRUID_START_PAGE);
143 gnome_druid_page_edge_set_bg_color (GNOME_DRUID_PAGE_EDGE (page), &bg_color);
144 gnome_druid_page_edge_set_logo_bg_color (GNOME_DRUID_PAGE_EDGE (page), &bg_color);
145 pixbuf = gdk_pixbuf_new_from_file (PIXMAP_APPWIZ_WATERMARK, NULL);
146 gnome_druid_page_edge_set_watermark (GNOME_DRUID_PAGE_EDGE (page), pixbuf);
147 g_object_unref (pixbuf);
148 pixbuf = gdk_pixbuf_new_from_file (PIXMAP_APPWIZ_LOGO, NULL);
149 gnome_druid_page_edge_set_logo (GNOME_DRUID_PAGE_EDGE (page), pixbuf);
151 /* Finish page */
152 page = glade_xml_get_widget (xml, DRUID_FINISH_PAGE);
153 gnome_druid_page_edge_set_bg_color (GNOME_DRUID_PAGE_EDGE (page), &bg_color);
154 gnome_druid_page_edge_set_logo_bg_color (GNOME_DRUID_PAGE_EDGE (page), &bg_color);
155 gnome_druid_page_edge_set_logo (GNOME_DRUID_PAGE_EDGE (page), pixbuf);
156 g_object_unref (pixbuf);
159 static void
160 cb_druid_add_summary_property (NPWProperty* property, gpointer user_data)
162 GString* text = (GString*)user_data;
164 if (npw_property_get_options (property) & NPW_SUMMARY_OPTION)
166 g_string_append (text, _(npw_property_get_label (property)));
167 g_string_append (text, npw_property_get_value (property));
168 g_string_append (text, "\n");
172 /* Fill last page (summary) */
173 static void
174 npw_druid_fill_summary (NPWDruid* this)
176 NPWPage* page;
177 guint i;
178 GString* text;
180 text = g_string_new (_("Confirm the following information:\n\n"));
182 g_string_append (text,_("Project Type: "));
183 g_string_append (text, _(npw_header_get_name (this->header)));
184 g_string_append (text,"\n");
186 for (i = 0; (page = g_queue_peek_nth (this->page_list, i)) != NULL; ++i)
188 npw_page_foreach_property (page, cb_druid_add_summary_property, text);
191 gnome_druid_page_edge_set_text (GNOME_DRUID_PAGE_EDGE (this->finish_page), text->str);
192 g_string_free (text, TRUE);
196 /* Create project selection page
197 *---------------------------------------------------------------------------*/
199 /* Display project information */
200 static void
201 on_druid_project_select_icon (GnomeIconList* iconlist, gint idx, GdkEvent* event, gpointer user_data)
203 NPWHeader* header;
204 NPWDruidAndTextBuffer* data = (NPWDruidAndTextBuffer *)user_data;
206 header = (NPWHeader*)gnome_icon_list_get_icon_data (iconlist, idx);
207 data->header = header;
209 /* As the icon list is in Browse mode, this function is called after inserting the
210 * first item but before setting the associated data, so header could be NULL */
211 if (header != NULL)
213 gtk_label_set_text (data->description, _(npw_header_get_description (header)));
214 data->druid->header = header;
218 /* Reselect default icon in page */
219 static void
220 on_druid_project_select_page (GtkWidget* widget, gpointer user_data)
222 /* NPWHeader* header; */
223 NPWDruidAndTextBuffer* data = (NPWDruidAndTextBuffer *)user_data;
225 g_return_if_fail (data->header != NULL);
227 gtk_label_set_text (data->description, _(npw_header_get_description (data->header)));
228 data->druid->header = data->header;
231 /* Add a project in the icon list */
232 static void
233 cb_druid_insert_project_icon (NPWHeader* header, gpointer user_data)
235 gint idx;
236 GnomeIconList* list = GNOME_ICON_LIST (user_data);
238 idx = gnome_icon_list_append (list, npw_header_get_iconfile (header), _(npw_header_get_name (header)));
239 gnome_icon_list_set_icon_data (list, idx, header);
242 /* Add a page in the project notebook */
243 static void
244 cb_druid_insert_project_page (NPWHeader* header, gpointer user_data)
246 NPWDruid* this = (NPWDruid*)user_data;
247 GladeXML* xml;
248 GtkWidget* label;
249 GtkWidget* frame;
250 GnomeIconList* list;
251 GtkLabel* desc;
252 const gchar* category;
253 NPWDruidAndTextBuffer* data;
255 category = npw_header_get_category(header);
257 /* Create new frame according to glade file */
258 xml = glade_xml_new (GLADE_FILE, PROJECT_SELECTION_FRAME, NULL);
259 g_return_if_fail (xml != NULL);
261 frame = glade_xml_get_widget (xml, PROJECT_SELECTION_FRAME);
262 list = GNOME_ICON_LIST (glade_xml_get_widget (xml, PROJECT_SELECTION_LIST));
263 desc = GTK_LABEL (glade_xml_get_widget (xml, PROJECT_DESCRIPTION));
265 npw_header_list_foreach_project_in (this->header_list, category, cb_druid_insert_project_icon, list);
267 /* put druid address and corresponding text buffer in one structure
268 * to pass them to a call back function as an unique pointer */
269 data = g_chunk_new (NPWDruidAndTextBuffer, this->pool);
270 data->druid = this;
271 data->description = desc;
272 data->header = (NPWHeader*)gnome_icon_list_get_icon_data (list, 0);
273 glade_xml_signal_connect_data (xml, DRUID_PROJECT_SELECT_ICON_SIGNAL, GTK_SIGNAL_FUNC (on_druid_project_select_icon), data);
274 glade_xml_signal_connect_data (xml, DRUID_PROJECT_SELECT_PAGE_SIGNAL, GTK_SIGNAL_FUNC (on_druid_project_select_page), data);
276 g_object_unref (xml);
278 /* Create label */
279 xml = glade_xml_new (GLADE_FILE, PROJECT_SELECTION_BOOK_LABEL, NULL);
280 g_return_if_fail (xml != NULL);
281 label = glade_xml_get_widget (xml, PROJECT_SELECTION_BOOK_LABEL);
282 g_object_unref (xml);
283 gtk_label_set_text (GTK_LABEL(label), category);
285 gtk_notebook_append_page (this->project_book, frame, label);
288 /* Fill project selection page */
289 static gboolean
290 npw_druid_fill_selection_page (NPWDruid* this)
292 gboolean ok;
293 gchar* local_dir;
295 /* Create list of projects */
296 if (this->header_list != NULL) npw_header_list_free (this->header_list);
297 this->header_list = npw_header_list_new ();
299 /* Fill list with all project in directory */
300 ok = npw_header_list_readdir (this->header_list, PROJECT_WIZARD_DIRECTORY);
301 #ifdef LOCAL_PROJECT_WIZARD_DIRECTORY
302 local_dir = g_build_filename (g_get_home_dir(), LOCAL_PROJECT_WIZARD_DIRECTORY, NULL);
303 #else
304 local_dir = anjuta_util_get_user_data_file_path ("projects/",NULL);
305 #endif
306 ok = npw_header_list_readdir (this->header_list, local_dir) || ok;
307 g_free (local_dir);
308 if (!ok)
310 anjuta_util_dialog_error (GTK_WINDOW (ANJUTA_PLUGIN (this->plugin)->shell),_("Unable to find any project template in %s"), PROJECT_WIZARD_DIRECTORY);
311 return FALSE;
314 /* Add all notebook page */
315 gtk_notebook_remove_page(this->project_book, 0);
316 npw_header_list_foreach_category (this->header_list, cb_druid_insert_project_page, this);
318 return TRUE;
321 /* Create properties pages
322 *---------------------------------------------------------------------------*/
324 /* Group infomation need by the following call back function */
325 typedef struct _NPWDruidAddPropertyData
327 NPWDruid* druid;
328 guint row;
329 } NPWDruidAddPropertyData;
331 static void
332 cb_druid_destroy_widget (GtkWidget* widget, gpointer user_data)
334 gtk_widget_destroy (widget);
337 static void
338 cb_druid_add_property (NPWProperty* property, gpointer user_data)
340 GtkWidget* label;
341 GtkWidget* entry;
342 NPWDruidAddPropertyData* data = (NPWDruidAddPropertyData *)user_data;
343 const gchar* description;
346 entry = npw_property_create_widget (property);
347 if (entry != NULL)
349 /* Not hidden property */
350 description = npw_property_get_description (property);
352 /* Set description tooltip */
353 if (description && (*description != '\0'))
355 GtkTooltips *tooltips;
357 tooltips = data->druid->tooltips;
358 if (!tooltips)
360 tooltips = data->druid->tooltips = gtk_tooltips_new ();
361 data->druid->tooltips = tooltips;
362 g_object_ref (tooltips);
363 gtk_object_sink (GTK_OBJECT (tooltips));
365 gtk_tooltips_set_tip (tooltips, entry, description, NULL);
368 /* Add label and entry */
369 gtk_table_resize (data->druid->property_table, data->row + 1, 2);
370 label = gtk_label_new (_(npw_property_get_label (property)));
371 gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
372 gtk_misc_set_padding (GTK_MISC (label), 5, 5);
373 gtk_table_attach (data->druid->property_table, label, 0, 1, data->row, data->row + 1,
374 (GtkAttachOptions)(GTK_FILL), (GtkAttachOptions)(0), 0, 0);
375 gtk_table_attach (data->druid->property_table, entry, 1, 2, data->row, data->row + 1,
376 (GtkAttachOptions)(GTK_EXPAND|GTK_FILL), (GtkAttachOptions)(0), 0, 0);
378 data->row++;
382 static gboolean
383 npw_druid_fill_property_page (NPWDruid* this, NPWPage* page)
385 NPWDruidAddPropertyData data;
386 PangoAttribute* attr;
387 PangoAttrList* attr_list;
389 /* Remove previous widgets */
390 gtk_container_foreach (GTK_CONTAINER (this->property_table), cb_druid_destroy_widget, NULL);
392 /* Update title */
393 gnome_druid_page_standard_set_title (this->property_page, _(npw_page_get_label (page)));
394 gtk_label_set_text (this->property_label, _(npw_page_get_description (page)));
395 attr = pango_attr_weight_new (PANGO_WEIGHT_BOLD);
396 attr->start_index = 0;
397 attr->end_index = G_MAXINT;
398 attr_list = pango_attr_list_new ();
399 pango_attr_list_insert (attr_list, attr);
400 gtk_label_set_attributes (this->property_label, attr_list);
401 pango_attr_list_unref (attr_list);
403 /* Add new widget */
404 data.druid = this;
405 data.row = 0;
406 npw_page_foreach_property (page, cb_druid_add_property, &data);
408 /* Change page only if current is project selection page */
409 gnome_druid_set_page (this->druid, GNOME_DRUID_PAGE (this->property_page));
410 gtk_widget_show_all (this->dialog);
412 return TRUE;
415 /* Handle page cache
416 *---------------------------------------------------------------------------*/
418 static NPWPage*
419 npw_druid_add_new_page (NPWDruid* this)
421 NPWPage* page;
423 /* Get page in cache */
424 page = g_queue_peek_nth (this->page_list, this->page);
425 if (page == NULL)
427 /* Page not found in cache, create */
428 page = npw_page_new (this->values);
430 /* Add page in cache */
431 g_queue_push_tail (this->page_list, page);
434 return page;
437 /* Remove all following page */
439 static void
440 npw_druid_remove_following_page (NPWDruid* this)
442 NPWPage* page;
444 for(;;)
446 page = g_queue_pop_nth (this->page_list, this->page);
447 if (page == NULL) break;
448 npw_page_free (page);
452 /* Save properties
453 *---------------------------------------------------------------------------*/
455 typedef struct _NPWSaveValidPropertyData
457 GtkWindow *parent;
458 gboolean next;
459 gboolean modified;
460 } NPWSaveValidPropertyData;
462 static void
463 cb_save_valid_property (NPWProperty* property, gpointer user_data)
465 NPWSaveValidPropertyData* data = (NPWSaveValidPropertyData *)user_data;
466 const gchar* value;
467 gboolean modified;
469 /* Get value from widget */
470 modified = npw_property_update_value_from_widget (property);
471 if (modified) data->modified = modified;
472 value = npw_property_get_value (property);
474 /* Check mandatory property */
475 if (modified && (npw_property_get_options (property) & NPW_MANDATORY_OPTION))
477 if ((value == NULL) || (strlen (value) <= 0))
479 if (data->next == TRUE)
481 /* First error message */
482 data->next = FALSE;
484 /* Show error message. */
485 anjuta_util_dialog_error (data->parent,
486 _("Field \"%s\" is mandatory. Please enter it."),
487 _(npw_property_get_label (property)));
489 npw_property_remove_value (property);
493 /* Check restricted property */
494 if (modified && !npw_property_is_valid_restriction (property))
496 if (data->next == TRUE)
498 NPWPropertyRestriction restriction = npw_property_get_restriction (property);
499 /* First error message */
500 data->next = FALSE;
502 switch (restriction)
504 case NPW_FILENAME_RESTRICTION:
505 /* Show error message. */
506 anjuta_util_dialog_error (data->parent,
507 _("Field \"%s\" must start with a letter, a digit or an underscore and contains only letters, digits, underscore, minus and dot. Please fix it."),
508 _(npw_property_get_label (property)));
509 break;
510 default:
511 break;
514 npw_property_remove_value (property);
517 /* Check exist property */
518 if (modified && (npw_property_get_exist_option (property) == NPW_FALSE))
520 gboolean is_directory = npw_property_get_type (property) == NPW_DIRECTORY_PROPERTY;
521 gboolean exist = (value != NULL) && g_file_test (value, G_FILE_TEST_EXISTS);
522 /* Allow empty directory */
523 if (exist && is_directory)
525 GDir* dir;
527 dir = g_dir_open (value, 0, NULL);
528 if (dir != NULL)
530 if (g_dir_read_name (dir) == NULL) exist = FALSE;
531 g_dir_close (dir);
535 if (exist)
537 if (data->next == TRUE)
539 /* First error message */
540 gboolean yes;
542 yes = anjuta_util_dialog_boolean_question (data->parent, is_directory ?
543 _("Directory \"%s\" is not empty. Project creation could fail if some files "
544 "cannot be written. Do you want to continue?") :
545 _("File \"%s\" already exists. Do you want to overwrite it?"),
546 value);
548 if (!yes)
550 data->next = FALSE;
551 npw_property_remove_value (property);
554 else
556 /* value is not invalid */
557 npw_property_remove_value (property);
563 static void
564 cb_save_old_property (NPWProperty* property, gpointer user_data)
566 if (npw_property_save_value_from_widget (property))
568 *(gboolean *)user_data = TRUE;
572 /* Save values and check them, if it's possible to go to next page */
574 static gboolean
575 npw_druid_save_valid_values (NPWDruid* this)
577 NPWPage* page;
578 NPWSaveValidPropertyData data;
580 page = g_queue_peek_nth (this->page_list, this->page - 1);
581 data.modified = FALSE;
582 data.next = TRUE;
583 data.parent = GTK_WINDOW (this->dialog);
584 npw_page_foreach_property (page, cb_save_valid_property, &data);
586 if (data.modified) npw_druid_remove_following_page (this);
588 return data.next;
591 /* Save current value, but do not check anything */
593 static void
594 npw_druid_save_old_values (NPWDruid* this)
596 NPWPage* page;
597 gboolean modified;
599 page = g_queue_peek_nth (this->page_list, this->page - 1);
600 modified = FALSE;
601 npw_page_foreach_property (page, cb_save_old_property, &modified);
605 /* Druid GUI functions
606 *---------------------------------------------------------------------------*/
608 static void
609 npw_druid_set_busy (NPWDruid *this, gboolean busy_state)
611 if (this->busy == busy_state)
612 return;
614 /* Set busy state */
615 gnome_druid_set_buttons_sensitive (GNOME_DRUID (this->druid),
616 !busy_state, !busy_state,
617 !busy_state, TRUE);
618 if (busy_state)
619 anjuta_status_busy_push (anjuta_shell_get_status (ANJUTA_PLUGIN (this->plugin)->shell, NULL));
620 else
621 anjuta_status_busy_pop (anjuta_shell_get_status (ANJUTA_PLUGIN (this->plugin)->shell, NULL));
622 this->busy = busy_state;
625 /* Druid call backs
626 *---------------------------------------------------------------------------*/
628 static gboolean
629 on_druid_cancel (GtkWidget* window, NPWDruid* druid)
631 DEBUG_PRINT ("Project wizard canceled");
632 anjuta_plugin_deactivate (ANJUTA_PLUGIN (druid->plugin));
633 npw_druid_free (druid);
635 return TRUE;
638 static gboolean
639 on_druid_delete (GtkWidget* window, GdkEvent* event, NPWDruid* druid)
641 DEBUG_PRINT ("Project wizard canceled");
642 anjuta_plugin_deactivate (ANJUTA_PLUGIN (druid->plugin));
643 npw_druid_free (druid);
645 return TRUE;
648 static gboolean
649 on_project_wizard_key_press_event(GtkWidget *widget, GdkEventKey *event,
650 NPWDruid* druid)
652 if (event->keyval == GDK_Escape)
654 npw_druid_free (druid);
655 return TRUE;
657 return FALSE;
660 static void
661 on_druid_get_new_page (NPWAutogen* gen, gpointer data)
663 NPWDruid* this = (NPWDruid *)data;
664 NPWPage* page;
666 page = g_queue_peek_nth (this->page_list, this->page - 1);
668 if (npw_page_get_name (page) == NULL)
670 /* no page, display finish page */
671 npw_druid_fill_summary (this);
672 gnome_druid_set_page (this->druid, this->finish_page);
674 else
676 /* display property page */
677 npw_druid_fill_property_page (this, page);
679 npw_druid_set_busy (this, FALSE);
682 static void
683 on_druid_parse_page (const gchar* output, gpointer data)
685 NPWPageParser* parser = (NPWPageParser*)data;
687 npw_page_parser_parse (parser, output, strlen (output), NULL);
690 static void
691 check_and_warn_missing (NPWDruid *this)
693 GList *missing_programs, *missing_packages;
694 GString *missing_message = NULL;
696 missing_programs = npw_header_check_required_programs (this->header);
697 missing_packages = npw_header_check_required_packages (this->header);
699 if (missing_programs || missing_packages)
701 missing_message = g_string_new (NULL);
704 if (missing_programs)
706 gchar *missing_progs;
707 missing_progs = anjuta_util_glist_strings_join (missing_programs,
708 ", ");
709 g_string_append_printf (missing_message,
710 _("\nMissing programs: %s."), missing_progs);
711 g_free (missing_progs);
712 g_list_free (missing_programs);
715 if (missing_packages)
717 gchar *missing_pkgs;
718 missing_pkgs = anjuta_util_glist_strings_join (missing_packages,
719 ", ");
720 g_string_append_printf (missing_message,
721 _("\nMissing packages: %s."), missing_pkgs);
722 g_free (missing_pkgs);
723 g_list_free (missing_packages);
726 if (missing_message)
728 GtkWidget *dialog, *detail_label, *expander;
730 g_string_prepend (missing_message, _(
731 "Some important programs or development packages required to build "
732 "this project are missing. Please make sure they are "
733 "installed properly before generating the project.\n"));
734 dialog =
735 gtk_message_dialog_new_with_markup (GTK_WINDOW (this->dialog),
736 GTK_DIALOG_DESTROY_WITH_PARENT,
737 GTK_MESSAGE_WARNING,
738 GTK_BUTTONS_CLOSE,
739 "<b>%s</b>\n\n%s",
740 _("Missing components"),
741 missing_message->str);
742 detail_label = gtk_label_new (
743 _("The missing programs are usually part of some distrubution "
744 "packages and can be searched in your Application Manager. "
745 "Similarly, the development packages are contained in special "
746 "packages that your distribution provide to allow development "
747 "of projects based on them. They usually end with -dev or "
748 "-devel suffix in package names and can be found by searching "
749 "in your Application Manager."));
750 gtk_label_set_line_wrap (GTK_LABEL (detail_label), TRUE);
751 gtk_widget_show (detail_label);
753 expander = gtk_expander_new ("<b>Details</b>");
754 gtk_expander_set_use_markup (GTK_EXPANDER (expander), TRUE);
755 gtk_container_add (GTK_CONTAINER (expander), detail_label);
756 gtk_box_pack_start_defaults (GTK_BOX (GTK_DIALOG (dialog)->vbox),
757 expander);
758 gtk_widget_show (expander);
760 gtk_dialog_run (GTK_DIALOG (dialog));
761 gtk_widget_destroy (dialog);
762 g_string_free (missing_message, TRUE);
766 static gboolean
767 on_druid_next (GnomeDruidPage* page, GtkWidget* widget, NPWDruid* this)
769 /* Skip if busy */
770 if (this->busy) return TRUE;
772 /* Set busy */
773 npw_druid_set_busy (this, TRUE);
775 if (this->page == 0)
777 const gchar* new_project;
779 /* Current is Select project page */
780 new_project = npw_header_get_filename (this->header);
782 /* Check if necessary programs for this project is installed */
783 check_and_warn_missing (this);
785 if (this->project_file != new_project)
787 /* Change project */
789 this->project_file = new_project;
790 npw_druid_remove_following_page (this);
791 npw_autogen_set_input_file (this->gen, this->project_file, "[+","+]");
794 else
796 /* Current is one of the property page */
797 if (!npw_druid_save_valid_values (this))
799 /* Error stay on this page */
800 npw_druid_set_busy (this, FALSE);
802 return TRUE;
805 this->page++;
807 if (g_queue_peek_nth (this->page_list, this->page - 1) == NULL)
809 /* Regenerate new page */
810 if (this->parser != NULL)
811 npw_page_parser_free (this->parser);
812 this->parser = npw_page_parser_new (npw_druid_add_new_page (this), this->project_file, this->page - 1);
813 npw_autogen_set_output_callback (this->gen, on_druid_parse_page, this->parser);
814 npw_autogen_write_definition_file (this->gen, this->values);
815 npw_autogen_execute (this->gen, on_druid_get_new_page, this, NULL);
817 else
819 /* Page is already in cache */
820 on_druid_get_new_page (NULL, (gpointer)this);
823 return TRUE;
826 static gboolean
827 on_druid_back (GnomeDruidPage* dpage, GtkWidget* widget, NPWDruid* druid)
829 /* Skip if busy */
830 if (druid->busy) return TRUE;
832 g_return_val_if_fail (druid->page > 0, TRUE);
834 npw_druid_save_old_values (druid);
836 druid->page--;
837 if (druid->page == 0)
839 /* Go back to project selection page */
840 gnome_druid_set_page (druid->druid, druid->selection_page);
842 else
844 NPWPage* page;
846 page = g_queue_peek_nth (druid->page_list, druid->page - 1);
847 /* Create property page */
848 npw_druid_fill_property_page (druid, page);
851 return TRUE;
854 static void
855 on_druid_finish (GnomeDruidPage* page, GtkWidget* widget, NPWDruid* druid)
857 NPWInstall* inst;
859 inst = npw_install_new (druid->plugin);
860 npw_install_set_property (inst, druid->values);
861 npw_install_set_wizard_file (inst, npw_header_get_filename (druid->header));
862 npw_install_launch (inst);
864 npw_druid_free (druid);
867 static void
868 npw_druid_connect_all_signal (NPWDruid* this, GladeXML* xml)
870 glade_xml_signal_connect_data (xml, DRUID_DELETE_SIGNAL, GTK_SIGNAL_FUNC (on_druid_delete), this);
871 glade_xml_signal_connect_data (xml, DRUID_CANCEL_SIGNAL, GTK_SIGNAL_FUNC (on_druid_cancel), this);
872 glade_xml_signal_connect_data (xml, DRUID_FINISH_SIGNAL, GTK_SIGNAL_FUNC (on_druid_finish), this);
873 glade_xml_signal_connect_data (xml, DRUID_NEXT_SIGNAL, GTK_SIGNAL_FUNC (on_druid_next), this);
874 glade_xml_signal_connect_data (xml, DRUID_BACK_SIGNAL, GTK_SIGNAL_FUNC (on_druid_back), this);
877 /* Add default property
878 *---------------------------------------------------------------------------*/
880 static void
881 npw_druid_add_default_property (NPWDruid* this)
883 NPWValue* value;
884 gchar* s;
885 /* gchar* email; */
886 AnjutaPreferences* pref;
888 pref = anjuta_shell_get_preferences (ANJUTA_PLUGIN (this->plugin)->shell, NULL);
890 /* Add default base project directory */
891 value = npw_value_heap_find_value (this->values, ANJUTA_PROJECT_DIRECTORY_PROPERTY);
892 s = anjuta_preferences_get (pref, "anjuta.project.directory");
893 npw_value_heap_set_value (this->values, value, s, NPW_VALID_VALUE);
894 g_free (s);
896 /* Add user name */
897 value = npw_value_heap_find_value (this->values, USER_NAME_PROPERTY);
898 s = anjuta_preferences_get (pref, "anjuta.user.name");
899 if (!s || strlen(s) == 0)
901 s = (gchar *)g_get_real_name();
902 npw_value_heap_set_value (this->values, value, s, NPW_VALID_VALUE);
904 else
906 npw_value_heap_set_value (this->values, value, s, NPW_VALID_VALUE);
907 g_free (s);
909 /* Add Email address */
910 value = npw_value_heap_find_value (this->values, EMAIL_ADDRESS_PROPERTY);
911 s = anjuta_preferences_get (pref, "anjuta.user.email");
912 /* If Email address not defined in Preferences */
913 if (!s || strlen(s) == 0)
915 if (!(s = getenv("USERNAME")) || strlen(s) == 0)
916 s = getenv("USER");
917 s = g_strconcat(s, "@", getenv("HOSTNAME"), NULL);
919 npw_value_heap_set_value (this->values, value, s, NPW_VALID_VALUE);
920 g_free (s);
923 /* Druid public functions
924 *---------------------------------------------------------------------------*/
926 NPWDruid*
927 npw_druid_new (NPWPlugin* plugin)
929 GladeXML* xml;
930 /* GtkContainer* project_scroll; */
931 NPWDruid* this;
933 /* Skip if already created */
934 if (plugin->druid != NULL) return plugin->druid;
936 /* Check if autogen is present */
937 if (!npw_check_autogen())
939 anjuta_util_dialog_error (NULL, _("Could not find autogen version 5, please install the autogen package. You can get it from http://autogen.sourceforge.net"));
940 return NULL;
943 this = g_new0(NPWDruid, 1);
944 xml = glade_xml_new (GLADE_FILE, NEW_PROJECT_DIALOG, NULL);
945 if ((this == NULL) || (xml == NULL))
947 anjuta_util_dialog_error (NULL, _("Unable to build project assistant user interface."));
948 g_free (this);
950 return NULL;
952 this->pool = g_mem_chunk_new ("druid pool", sizeof(NPWDruidStuff), sizeof(NPWDruidStuff) * 20, G_ALLOC_ONLY);
954 /* Get reference on all useful widget */
955 this->dialog = glade_xml_get_widget (xml, NEW_PROJECT_DIALOG);
956 gtk_window_set_transient_for (GTK_WINDOW (this->dialog),
957 GTK_WINDOW (ANJUTA_PLUGIN (plugin)->shell));
958 this->tooltips = NULL;
959 /* add GtkIconView in the program as it's not handled by libglade */
960 this->druid = GNOME_DRUID (glade_xml_get_widget (xml, DRUID_WIDGET));
961 this->selection_page = GNOME_DRUID_PAGE (glade_xml_get_widget (xml, DRUID_SELECTION_PAGE));
962 this->project_book = GTK_NOTEBOOK (glade_xml_get_widget (xml, PROJECT_SELECTION_BOOK));
963 this->property_page = GNOME_DRUID_PAGE_STANDARD (glade_xml_get_widget (xml, DRUID_PROPERTY_PAGE));
964 this->property_label = GTK_LABEL (glade_xml_get_widget (xml, DRUID_PROPERTY_LABEL));
965 this->property_table = GTK_TABLE (glade_xml_get_widget (xml, DRUID_PROPERTY_TABLE));
966 this->finish_page = GNOME_DRUID_PAGE (glade_xml_get_widget (xml, DRUID_FINISH_PAGE));
967 this->page = 0;
968 this->project_file = NULL;
969 this->busy = FALSE;
970 this->page_list = g_queue_new ();
971 this->values = npw_value_heap_new ();
972 this->gen = npw_autogen_new ();
973 this->plugin = plugin;
975 npw_druid_fix_edge_pages (this, xml);
976 npw_druid_connect_all_signal (this, xml);
977 g_object_unref (xml);
979 if (!npw_druid_fill_selection_page (this))
981 /* No project available */
982 npw_druid_free (this);
984 return NULL;
987 /* Add dialog widget to anjuta status. */
988 anjuta_status_add_widget (anjuta_shell_get_status (ANJUTA_PLUGIN (plugin)->shell, NULL), this->dialog);
990 /* Needed by GnomeDruid widget */
991 gtk_widget_show_all (this->dialog);
993 g_signal_connect(G_OBJECT(this->dialog), "key-press-event",
994 G_CALLBACK(on_project_wizard_key_press_event), this);
996 plugin->druid = this;
997 npw_druid_add_default_property (this);
999 return this;
1002 void
1003 npw_druid_free (NPWDruid* this)
1005 /* NPWPage* page; */
1007 g_return_if_fail (this != NULL);
1009 if (this->tooltips)
1011 g_object_unref (this->tooltips);
1012 this->tooltips = NULL;
1014 /* Delete page list */
1015 this->page = 0;
1016 npw_druid_remove_following_page (this);
1017 g_queue_free (this->page_list);
1018 npw_value_heap_free (this->values);
1019 npw_autogen_free (this->gen);
1020 if (this->parser != NULL) npw_page_parser_free (this->parser);
1021 g_mem_chunk_destroy(this->pool);
1022 npw_header_list_free (this->header_list);
1023 gtk_widget_destroy (this->dialog);
1024 this->plugin->druid = NULL;
1025 g_free (this);
1028 void
1029 npw_druid_show (NPWDruid* this)
1031 g_return_if_fail (this);
1033 /* Display dialog box */
1034 if (this->dialog) gtk_window_present (GTK_WINDOW (this->dialog));