1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
2 /*
3     druid.c
4     Copyright (C) 2004 Sebastien Granjoux
5 
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.
10 
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.
15 
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
19 */
20 
21 /*
22  * All GUI functions
23  *
24  *---------------------------------------------------------------------------*/
25 
26 #include <config.h>
27 
28 #include "druid.h"
29 
30 #include "plugin.h"
31 #include "header.h"
32 #include "property.h"
33 #include "parser.h"
34 #include "install.h"
35 
36 #include <libanjuta/anjuta-debug.h>
37 #include <libanjuta/anjuta-utils.h>
38 #include <libanjuta/anjuta-autogen.h>
39 #include <libanjuta/interfaces/ianjuta-wizard.h>
40 #include <libanjuta/interfaces/ianjuta-editor.h>
41 #include <stdlib.h>
42 #include <glib/gi18n.h>
43 #include <glib.h>
44 #include <gdk/gdk.h>
45 
46 #include <gtk/gtk.h>
47 
48 #include <string.h>
49 
50 /*---------------------------------------------------------------------------*/
51 
52 #define PROJECT_WIZARD_DIRECTORY PACKAGE_DATA_DIR "/templates"
53 
54 /* Default property name useable in wizard file
55  *---------------------------------------------------------------------------*/
56 
57 #define ANJUTA_PROJECT_DIRECTORY_PROPERTY "AnjutaProjectDirectory"
58 #define DESTINATION_PROPERTY "Destination"
59 #define USER_NAME_PROPERTY "UserName"
60 #define AUTHOR_PROPERTY "Author"
61 #define EMAIL_ADDRESS_PROPERTY "EmailAddress"
62 #define EMAIL_PROPERTY "Email"
63 #define INDENT_WIDTH_PROPERTY "IndentWidth"
64 #define TAB_WIDTH_PROPERTY "TabWidth"
65 #define USE_TABS_PROPERTY "UseTabs"
66 
67 /* Common editor preferences */
68 #define ANJUTA_PREF_SCHEMA_PREFIX "org.gnome.anjuta."
69 
70 #define PROJECT_WIZARD_PREF_SCHEMA	"plugins.project-wizard"
71 
72 #define LAST_DIRECTORY	"project-directory"
73 #define LAST_USER_NAME	"user"
74 #define LAST_EMAIL		"email"
75 
76 /* Widget and signal name found in glade file
77  *---------------------------------------------------------------------------*/
78 
79 #define GTK_BUILDER_UI_FILE PACKAGE_DATA_DIR "/glade/anjuta-project-wizard.ui"
80 
81 #define NEW_PROJECT_DIALOG "druid_window"
82 #define PROJECT_LIST "project_list"
83 #define PROJECT_BOOK "project_book"
84 #define PROJECT_PAGE "project_page"
85 #define ERROR_PAGE "error_page"
86 #define ERROR_TITLE "error_title"
87 #define PROGRESS_PAGE "progress_page"
88 #define FINISH_PAGE "finish_page"
89 #define FINISH_TEXT "finish_text"
90 #define PROPERTY_PAGE "property_page"
91 #define PROPERTY_TITLE "property_title"
92 #define PROPERTY_TABLE "property_table"
93 #define ERROR_VBOX "error_vbox"
94 #define ERROR_ICON "error_icon"
95 #define ERROR_MESSAGE "error_message"
96 #define ERROR_DETAIL "error_detail"
97 
98 
99 #define PROJECT_PAGE_INDEX 0
100 
101 /*---------------------------------------------------------------------------*/
102 
103 struct _NPWDruid
104 {
105 	GtkWindow* window;
106 
107 	GtkNotebook* project_book;
108 	GtkWidget *error_page;
109 	GtkWidget *error_title;
110 	GtkBox *error_vbox;
111 	GtkWidget *error_extra_widget;
112 	GtkImage *error_icon;
113 	GtkLabel *error_message;
114 	GtkWidget *error_detail;
115 
116 	GtkWidget *project_page;
117 	GtkWidget *progress_page;
118 	GtkWidget *finish_page;
119 	GtkWidget *finish_text;
120 
121 	const gchar* project_file;
122 	NPWPlugin* plugin;
123 
124 	GQueue* page_list;
125 
126 	GHashTable* values;
127 	NPWPageParser* parser;
128 	GList* header_list;
129 	NPWHeader* header;
130 	gboolean no_selection;
131 	AnjutaAutogen* gen;
132 	gboolean busy;
133 };
134 
135 /* column of the icon view */
136 enum {
137 	PIXBUF_COLUMN,
138 	TEXT_COLUMN,
139 	DESC_COLUMN,
140 	DATA_COLUMN
141 };
142 
143 /* Helper functon
144  *---------------------------------------------------------------------------*/
145 
146 /* Druid GUI functions
147  *---------------------------------------------------------------------------*/
148 
149 static void
npw_druid_set_busy(NPWDruid * druid,gboolean busy_state)150 npw_druid_set_busy (NPWDruid *druid, gboolean busy_state)
151 {
152 	if (druid->busy == busy_state)
153 		return;
154 
155 	/* Set busy state */
156 	if (busy_state)
157 		anjuta_status_busy_push (anjuta_shell_get_status (ANJUTA_PLUGIN (druid->plugin)->shell, NULL));
158 	else
159 		anjuta_status_busy_pop (anjuta_shell_get_status (ANJUTA_PLUGIN (druid->plugin)->shell, NULL));
160 	druid->busy = busy_state;
161 }
162 
163 /* Create error page
164  *---------------------------------------------------------------------------*/
165 
166 /* Fill dialog page */
167 static void
npw_druid_fill_error_page(NPWDruid * druid,GtkWidget * extra_widget,GtkMessageType type,const gchar * detail,const gchar * mesg,...)168 npw_druid_fill_error_page (NPWDruid* druid, GtkWidget *extra_widget, GtkMessageType type, const gchar *detail, const gchar *mesg,...)
169 {
170 	GtkAssistant *assistant;
171 	GtkWidget *page;
172 	va_list args;
173 	gchar *message;
174 	const gchar *stock_id = NULL;
175 	const gchar *title = NULL;
176 
177 	assistant = GTK_ASSISTANT (druid->window);
178 
179 	/* Add page to assistant after current one */
180 	page = druid->error_page;
181 	gtk_assistant_insert_page (assistant, page, gtk_assistant_get_current_page (assistant) + 1);
182 
183 	/* Set dialog kind */
184 	switch (type)
185 	{
186 	case GTK_MESSAGE_INFO:
187 		stock_id = GTK_STOCK_DIALOG_INFO;
188 		title = _("Information");
189 		break;
190 	case GTK_MESSAGE_QUESTION:
191 		stock_id = GTK_STOCK_DIALOG_QUESTION;
192 		title = _("Warning");
193 		break;
194 	case GTK_MESSAGE_WARNING:
195 		stock_id = GTK_STOCK_DIALOG_WARNING;
196 		title = _("Warning");
197 		break;
198 	case GTK_MESSAGE_ERROR:
199 		stock_id = GTK_STOCK_DIALOG_ERROR;
200 		title = _("Error");
201 		break;
202 	case GTK_MESSAGE_OTHER:
203 		title = _("Message");
204 		break;
205 	default:
206 		g_warning ("Unknown GtkMessageType %u", type);
207 		break;
208 	}
209 	gtk_label_set_text (GTK_LABEL (druid->error_title), title);
210 	gtk_assistant_set_page_title (assistant, page, title);
211 	if (type == GTK_MESSAGE_ERROR)
212 	{
213 		gtk_assistant_set_page_type (assistant, page, GTK_ASSISTANT_PAGE_CONTENT);
214 		gtk_assistant_set_page_complete (assistant, page, FALSE);
215 	}
216 	else
217 	{
218 		gtk_assistant_set_page_type (assistant, page, GTK_ASSISTANT_PAGE_PROGRESS);
219 		gtk_assistant_set_page_complete (assistant, page, TRUE);
220 	}
221 	gtk_image_set_from_stock (druid->error_icon, stock_id, GTK_ICON_SIZE_DIALOG);
222 
223 	/* Set message */
224 	va_start (args, mesg);
225 	message = g_strdup_vprintf (mesg, args);
226 	va_end (args);
227 	gtk_label_set_markup (druid->error_message, message);
228 	g_free (message);
229 
230 	/* Set detail */
231 	if (detail == NULL)
232 	{
233 		gtk_widget_hide (druid->error_detail);
234 	}
235 	else
236 	{
237 		GtkLabel *label;
238 
239 		gtk_widget_show (druid->error_detail);
240 		label = GTK_LABEL (gtk_bin_get_child (GTK_BIN (druid->error_detail)));
241 		gtk_label_set_text (label, detail);
242 	}
243 
244 	if (druid->error_extra_widget)
245 		gtk_widget_destroy (druid->error_extra_widget);
246 	druid->error_extra_widget = NULL;
247 
248 	/* Set extra widget */
249 	if (extra_widget)
250 	{
251 		gtk_box_pack_start (GTK_BOX (druid->error_vbox), extra_widget,
252 							FALSE, FALSE, 10);
253 		gtk_widget_show (extra_widget);
254 		druid->error_extra_widget = extra_widget;
255 	}
256 }
257 
258 /* Create finish page
259  *---------------------------------------------------------------------------*/
260 
261 static void
cb_druid_add_summary_property(NPWProperty * property,gpointer user_data)262 cb_druid_add_summary_property (NPWProperty* property, gpointer user_data)
263 {
264 	GString* text = (GString*)user_data;
265 
266 	if (npw_property_get_options (property) & NPW_SUMMARY_OPTION)
267 	{
268 		g_string_append_printf (text, "%s %s\n",
269 								npw_property_get_label (property),
270 								npw_property_get_value (property));
271 	}
272 }
273 
274 /* Fill last page (summary) */
275 static void
npw_druid_fill_summary_page(NPWDruid * druid)276 npw_druid_fill_summary_page (NPWDruid* druid)
277 {
278 	NPWPage* page;
279 	guint i;
280 	GString* text;
281 	GtkLabel* label;
282 
283 	text = g_string_new (NULL);
284 	g_string_append_printf (text, "<b>%s</b>\n\n", _("Confirm the following information:"));
285 
286 	/* The project type is translated too, it is something like
287 	 * generic, GNOME applet, Makefile project... */
288 	g_string_append_printf (text, _("Project Type: %s\n"), npw_header_get_name (druid->header));
289 
290 	for (i = 0; (page = g_queue_peek_nth (druid->page_list, i)) != NULL; ++i)
291 	{
292 		npw_page_foreach_property (page, (GFunc)cb_druid_add_summary_property, text);
293 	}
294 
295 	label = GTK_LABEL (druid->finish_text);
296 	gtk_label_set_markup (label, text->str);
297 	g_string_free (text, TRUE);
298 
299 	gtk_assistant_set_page_complete (GTK_ASSISTANT (druid->window), druid->finish_page, TRUE);
300 }
301 
302 /* Create project selection page
303  *---------------------------------------------------------------------------*/
304 
305 /* Update selected project */
306 static void
on_druid_project_update_selected(GtkIconView * view,NPWDruid * druid)307 on_druid_project_update_selected (GtkIconView* view, NPWDruid *druid)
308 {
309 	GList *selected;
310 	NPWHeader* header = NULL;
311 
312 	/* No item can be selected when the view is mapped */
313 	selected = gtk_icon_view_get_selected_items (view);
314 	if (selected != NULL)
315 	{
316 		GtkTreeIter iter;
317 		GtkTreeModel *model;
318 
319 		model = gtk_icon_view_get_model (view);
320 		if (gtk_tree_model_get_iter (model, &iter, (GtkTreePath *)selected->data))
321 		{
322 			gtk_tree_model_get	(model, &iter, DATA_COLUMN, &header, -1);
323 		}
324 		gtk_tree_path_free ((GtkTreePath *)selected->data);
325 		g_list_free (selected);
326 	}
327 
328 	druid->header = header;
329 	gtk_assistant_set_page_complete (GTK_ASSISTANT (druid->window), druid->project_page, header != NULL);
330 }
331 
332 /* Add a project in the icon list */
333 static void
cb_druid_insert_project_icon(gpointer data,gpointer user_data)334 cb_druid_insert_project_icon (gpointer data, gpointer user_data)
335 {
336 	NPWHeader *header = (NPWHeader *)data;
337 	GtkListStore* store = GTK_LIST_STORE (user_data);
338 	GtkTreeIter iter;
339 	GdkPixbuf *pixbuf;
340 
341 	gtk_list_store_append (store, &iter);
342 	pixbuf = gdk_pixbuf_new_from_file (npw_header_get_iconfile (header), NULL);
343 	gtk_list_store_set (store, &iter, PIXBUF_COLUMN, pixbuf,
344 						TEXT_COLUMN, npw_header_get_name (header),
345 						DESC_COLUMN, npw_header_get_description (header),
346 						DATA_COLUMN, header,
347 						-1);
348 
349 	g_object_unref (pixbuf);
350 }
351 
352 /* Add a page in the project notebook */
353 static void
cb_druid_insert_project_page(gpointer value,gpointer user_data)354 cb_druid_insert_project_page (gpointer value, gpointer user_data)
355 {
356 	NPWDruid* druid = (NPWDruid*)user_data;
357 	GtkBuilder *builder;
358 	GtkWidget* label;
359 	GtkWidget* child;
360 	GtkWidget* assistant;
361 	GtkIconView* view;
362 	GtkNotebook *book;
363 	GtkListStore *store;
364 	GList *template_list = (GList *)value;
365 	const gchar* category;
366 
367 	category = npw_header_get_category ((NPWHeader *)template_list->data);
368 
369 	/* Build another complete wizard dialog from the gtk builder file
370 	 * but keep only the project selection notebook page */
371 	builder = gtk_builder_new ();
372 	if (!gtk_builder_add_from_file (builder, GTK_BUILDER_UI_FILE, NULL))
373 	{
374 		g_warn_if_reached ();
375 		g_object_unref (builder);
376 		return;
377 	}
378 
379 	/* Fill icon view */
380 	view = GTK_ICON_VIEW (gtk_builder_get_object (builder, PROJECT_LIST));
381 	gtk_icon_view_set_pixbuf_column (view, PIXBUF_COLUMN);
382 	gtk_icon_view_set_markup_column (view, TEXT_COLUMN);
383 	store = gtk_list_store_new (4, GDK_TYPE_PIXBUF, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_POINTER);
384 	g_list_foreach (template_list, cb_druid_insert_project_icon, store);
385 	gtk_icon_view_set_model (view, GTK_TREE_MODEL (store));
386 
387 	/* Connect signal to update dialog */
388 	g_signal_connect (G_OBJECT (view), "selection-changed", G_CALLBACK (on_druid_project_update_selected), druid);
389 	g_signal_connect (G_OBJECT (view), "map", G_CALLBACK (on_druid_project_update_selected), druid);
390 	g_signal_connect_swapped (G_OBJECT (view), "item-activated", G_CALLBACK (gtk_assistant_next_page), druid->window);
391 
392 	/* Set new page label */
393 	assistant = GTK_WIDGET (gtk_builder_get_object (builder, NEW_PROJECT_DIALOG));
394 	book = GTK_NOTEBOOK (gtk_builder_get_object (builder, PROJECT_BOOK));
395 	child = gtk_notebook_get_nth_page (book, 0);
396 	label = gtk_notebook_get_tab_label (book, child);
397 	gtk_label_set_text (GTK_LABEL(label), (const gchar *)category);
398 
399 	/* Pick up the filled project selection page from the newly created dialog
400 	 * add it to the wizard project notebook and destroy the dialog
401 	 */
402 	gtk_notebook_remove_page (book, 0);
403 	gtk_notebook_append_page (druid->project_book, child, label);
404 	gtk_widget_destroy (assistant);
405 
406 	g_object_unref (builder);
407 }
408 
409 /* Fill project selection page */
410 static gboolean
npw_druid_fill_selection_page(NPWDruid * druid,GFile * templates)411 npw_druid_fill_selection_page (NPWDruid* druid, GFile *templates)
412 {
413 	gchar* dir;
414 	const gchar * const * sys_dir;
415 
416 	/* Remove all previous data */
417 	gtk_notebook_remove_page(druid->project_book, 0);
418 	npw_header_list_free (druid->header_list);
419 	anjuta_autogen_clear_library_path (druid->gen);
420 
421 	/* Create list of projects */
422 	druid->header_list = npw_header_list_new ();
423 
424 	if (templates != NULL)
425 	{
426 		if (g_file_query_file_type (templates, 0, NULL) == G_FILE_TYPE_DIRECTORY)
427 		{
428 			/* Read project template only in specified directory,
429 		 	 * other directories can still be used to get included
430 		 	 * files */
431 			gchar *directory = g_file_get_path (templates);
432 
433 			npw_header_list_readdir (&druid->header_list, directory);
434 			anjuta_autogen_set_library_path (druid->gen, directory);
435 			g_free (directory);
436 		}
437 		else
438 		{
439 			/* templates is a file, so read only it as a project template */
440 			gchar *filename = g_file_get_path (templates);
441 			npw_header_list_read (&druid->header_list, filename);
442 			g_free (filename);
443 		}
444 	}
445 
446 	dir = g_build_filename (g_get_user_data_dir (), "anjuta", "templates", NULL);
447 	if (templates == NULL)
448 	{
449 		/* Read project template in user directory,
450 		 * normally ~/.local/share/anjuta/templates,
451 	 	* the first template read override the others */
452 		npw_header_list_readdir (&druid->header_list, dir);
453 	}
454 	anjuta_autogen_set_library_path (druid->gen, dir);
455 	g_free (dir);
456 
457 	for (sys_dir = g_get_system_data_dirs (); *sys_dir != NULL; sys_dir++)
458 	{
459 		dir = g_build_filename (*sys_dir, "anjuta", "templates", NULL);
460 		if (templates == NULL)
461 		{
462 			/* Read project template in system directory */
463 			npw_header_list_readdir (&druid->header_list, dir);
464 		}
465 		anjuta_autogen_set_library_path (druid->gen, dir);
466 		g_free (dir);
467 	}
468 
469 	if (templates == NULL)
470 	{
471 		/* Read anjuta installation directory */
472 		npw_header_list_readdir (&druid->header_list, PROJECT_WIZARD_DIRECTORY);
473 	}
474 	anjuta_autogen_set_library_path (druid->gen, PROJECT_WIZARD_DIRECTORY);
475 
476 	switch (g_list_length (druid->header_list))
477 	{
478 	case 0:
479 		anjuta_util_dialog_error (GTK_WINDOW (ANJUTA_PLUGIN (druid->plugin)->shell),_("Unable to find any project template in %s"), PROJECT_WIZARD_DIRECTORY);
480 		return FALSE;
481 	case 1:
482 		druid->header = (NPWHeader *)((GList *)druid->header_list->data)->data;
483 		druid->no_selection = TRUE;
484 		gtk_container_remove (GTK_CONTAINER (druid->window), druid->project_page);
485 		gtk_assistant_insert_page (GTK_ASSISTANT (druid->window), druid->progress_page, 0);
486 		npw_druid_set_busy (druid, FALSE);
487 		break;
488 	default:
489 		/* Add all necessary notebook page */
490 		druid->no_selection = FALSE;
491 		g_list_foreach (druid->header_list, cb_druid_insert_project_page, druid);
492 		gtk_widget_show_all (GTK_WIDGET (druid->project_book));
493 	}
494 
495 	return TRUE;
496 }
497 
498 /* Create properties pages
499  *---------------------------------------------------------------------------*/
500 
501 /* Group infomation need by the following call back function */
502 typedef struct _NPWDruidAddPropertyData
503 {
504 	NPWDruid* druid;
505 	guint row;
506 	GtkGrid *table;
507 	GtkWidget *first_entry;
508 } NPWDruidAddPropertyData;
509 
510 static void
cb_druid_destroy_widget(GtkWidget * widget,gpointer user_data)511 cb_druid_destroy_widget (GtkWidget* widget, gpointer user_data)
512 {
513 	gtk_widget_destroy (widget);
514 }
515 
516 static void
cb_druid_add_property(NPWProperty * property,gpointer user_data)517 cb_druid_add_property (NPWProperty* property, gpointer user_data)
518 {
519 	GtkWidget* label;
520 	GtkWidget* entry;
521 	NPWDruidAddPropertyData* data = (NPWDruidAddPropertyData *)user_data;
522 	const gchar* description;
523 
524 
525 	entry = npw_property_create_widget (property);
526 	if (entry != NULL)
527 	{
528 		/* Not hidden property */
529 		description = npw_property_get_description (property);
530 
531 		/* Set description tooltip */
532 		if (description && (*description != '\0'))
533 		{
534 			gtk_widget_set_tooltip_text (entry, description);
535 		}
536 
537 		label = gtk_label_new (npw_property_get_label (property));
538 		gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
539 		gtk_misc_set_padding (GTK_MISC (label), 6, 6);
540 
541 		gtk_widget_set_hexpand (entry, TRUE);
542 		switch (npw_property_get_type (property))
543 		{
544 			case NPW_PACKAGE_PROPERTY:
545 				gtk_widget_set_vexpand (entry, TRUE);
546 				gtk_grid_attach (data->table, label, 0, data->row, 1, 1);
547 				gtk_grid_attach (data->table, entry, 0, data->row + 1, 1, 1);
548 				data->row += 2;
549 				break;
550 			case NPW_BOOLEAN_PROPERTY:
551 				gtk_widget_set_hexpand (entry, FALSE);
552 				/* Fall through */
553 			default:
554 				/* Add label and entry */
555 				gtk_grid_attach (data->table, label, 0, data->row, 1, 1);
556 				gtk_grid_attach (data->table, entry, 1, data->row, 1, 1);
557 				data->row++;
558 		}
559 
560 		/* Set first entry */
561 		if (data->first_entry == NULL) data->first_entry = entry;
562 	}
563 };
564 
565 static void
npw_druid_fill_property_page(NPWDruid * druid,NPWPage * page)566 npw_druid_fill_property_page (NPWDruid* druid, NPWPage* page)
567 {
568 	GtkWidget *widget;
569 	GList *children;
570 	GtkLabel *label;
571 	NPWDruidAddPropertyData data;
572 
573 	/* Add page to assistant, after current page */
574 	widget = gtk_assistant_get_nth_page (GTK_ASSISTANT (druid->window), gtk_assistant_get_current_page (GTK_ASSISTANT (druid->window)) + 1);
575 
576 	/* Remove previous widgets */
577 	gtk_container_foreach (GTK_CONTAINER (npw_page_get_widget (page)), cb_druid_destroy_widget, NULL);
578 
579 	/* Update title	*/
580 	children = gtk_container_get_children (GTK_CONTAINER (widget));
581 	label = GTK_LABEL (g_list_nth_data (children, 0));
582 	g_list_free (children);
583 	gtk_label_set_text (label, npw_page_get_label (page));
584 	gtk_assistant_set_page_title (GTK_ASSISTANT (druid->window), widget, npw_page_get_label (page));
585 
586 	/* Add new widget */
587 	data.druid = druid;
588 	data.row = 0;
589 	data.table = GTK_GRID (npw_page_get_widget (page));
590 	data.first_entry = NULL;
591 	npw_page_foreach_property (page, (GFunc)cb_druid_add_property, &data);
592 
593 	/* Move focus on first entry */
594 	if (data.first_entry != NULL)
595 	{
596 		gtk_container_set_focus_child (GTK_CONTAINER (data.table), data.first_entry);
597 	}
598 
599 	gtk_widget_show_all (widget);
600 }
601 
602 /* Handle page cache
603  *---------------------------------------------------------------------------*/
604 
605 static NPWPage*
npw_druid_add_new_page(NPWDruid * druid)606 npw_druid_add_new_page (NPWDruid* druid)
607 {
608 	gint current;
609 	NPWPage* page;
610 
611 	/* Get page in cache */
612 	current = gtk_assistant_get_current_page (GTK_ASSISTANT (druid->window));
613 	page = g_queue_peek_nth (druid->page_list, current - (druid->no_selection ? 0 : 1) + 1);
614 
615 	if (page == NULL)
616 	{
617 		/* Page not found in cache, create */
618 		GtkBuilder *builder;
619 		GtkWidget *widget;
620 		GtkAssistantPageType type;
621 		GtkWidget *table;
622 		GtkAssistant *assistant;
623 
624 		/* Build another complete wizard dialog from the gtk builder file
625 	 	* but keep only the property assistant page */
626 		builder = gtk_builder_new ();
627 		if (!gtk_builder_add_from_file (builder, GTK_BUILDER_UI_FILE, NULL))
628 		{
629 			g_warn_if_reached ();
630 			g_object_unref (builder);
631 
632 			return NULL;
633 		}
634 		assistant = GTK_ASSISTANT (gtk_builder_get_object (builder, NEW_PROJECT_DIALOG));
635 		widget = GTK_WIDGET (gtk_builder_get_object (builder, PROPERTY_PAGE));
636 		table = GTK_WIDGET (gtk_builder_get_object (builder, PROPERTY_TABLE));
637 
638 		type = gtk_assistant_get_page_type (assistant, widget);
639 		gtk_container_remove (GTK_CONTAINER (assistant), widget);
640 		gtk_assistant_insert_page (GTK_ASSISTANT (druid->window), widget, current + 1);
641 		gtk_assistant_set_page_type (GTK_ASSISTANT (druid->window), widget, type);
642 		gtk_assistant_set_page_complete (GTK_ASSISTANT (druid->window), widget, TRUE);
643 		gtk_widget_destroy (GTK_WIDGET (assistant));
644 
645 		/* Builder get reference on all built widget, so unref it when all work is done */
646 		g_object_unref (builder);
647 
648 		/* Create new page */
649 		page = npw_page_new (druid->values);
650 		npw_page_set_widget (page, table);
651 
652 		/* Add page in cache */
653 		g_queue_push_tail (druid->page_list, page);
654 	}
655 
656 	return page;
657 }
658 
659 /* Remove all pages following current page except the summary page*/
660 
661 static void
npw_druid_remove_following_page(NPWDruid * druid)662 npw_druid_remove_following_page (NPWDruid* druid)
663 {
664 	gint current;
665 
666 	current = gtk_assistant_get_current_page (GTK_ASSISTANT (druid->window));
667 	for(;;)
668 	{
669 		GtkWidget *widget;
670 		NPWPage* page;
671 
672 		widget = gtk_assistant_get_nth_page (GTK_ASSISTANT (druid->window), current + 1);
673 		if (widget == druid->finish_page) break;
674 
675 		gtk_container_remove (GTK_CONTAINER (druid->window), widget);
676 
677 		page = g_queue_pop_nth (druid->page_list, current  - (druid->no_selection ? 0 : 1));
678 		if (page != NULL) npw_page_free (page);
679 	}
680 }
681 
682 /* Save properties
683  *---------------------------------------------------------------------------*/
684 
685 typedef struct _NPWSaveValidPropertyData
686 {
687 	GtkWindow *parent;
688 	gboolean modified;
689 	GString *error;
690 	GString *warning;
691 
692 } NPWSaveValidPropertyData;
693 
694 static void
cb_save_valid_property(NPWProperty * property,gpointer user_data)695 cb_save_valid_property (NPWProperty* property, gpointer user_data)
696 {
697 	NPWSaveValidPropertyData* data = (NPWSaveValidPropertyData *)user_data;
698 	const gchar* value;
699 	gboolean modified;
700 
701 	/* Get value from widget */
702 	modified = npw_property_update_value_from_widget (property);
703 	if (modified) data->modified = modified;
704        	value = npw_property_get_value (property);
705 
706 	/* Check mandatory property */
707 	if (modified &&  (npw_property_get_options (property) & NPW_MANDATORY_OPTION))
708 	{
709 		if ((value == NULL) || (strlen (value) <= 0))
710 		{
711 			g_string_append_printf (data->error,
712 									_("\nField \"%s\" is mandatory. Please enter it."),
713 									npw_property_get_label (property));
714 			npw_property_remove_value (property);
715 		}
716 	}
717 
718 	/* Check restricted property */
719 	if (modified && !npw_property_is_valid_restriction (property))
720 	{
721 		NPWPropertyRestriction restriction = npw_property_get_restriction (property);
722 
723 		switch (restriction)
724 		{
725 		case NPW_FILENAME_RESTRICTION:
726 			g_string_append_printf (data->error,
727 									_("Field \"%s\" must contains only letters, digits or the following characters \"#$:%%+,.=@^_`~\". In addition you cannot have a leading dash. Please fix it."),
728 									npw_property_get_label (property));
729 			break;
730 		case NPW_DIRECTORY_RESTRICTION:
731 			g_string_append_printf (data->error,
732 									_("Field \"%s\" must contains only letters, digits, the following characters \"#$:%%+,.=@^_`~\" or directory separators. In addition you cannot have a leading dash. Please fix it."),
733 									npw_property_get_label (property));
734 			break;
735 		case NPW_PRINTABLE_RESTRICTION:
736 			g_string_append_printf (data->error,
737 									_("Field \"%s\" must contains only ASCII printable characters, no accentuated characters by example. Please fix it."),
738 									npw_property_get_label (property));
739 			break;
740 		default:
741 			g_string_append_printf (data->error,
742 									_("Unknown error."));
743 
744 		}
745 		npw_property_remove_value (property);
746 	}
747 
748 	/* Check exist property */
749 	if (modified && (npw_property_get_exist_option (property) == NPW_FALSE))
750 	{
751 		gboolean is_directory = npw_property_get_type (property) == NPW_DIRECTORY_PROPERTY;
752 		gboolean exist = (value != NULL) && g_file_test (value, G_FILE_TEST_EXISTS);
753 		/* Allow empty directory */
754 		if (exist && is_directory)
755 		{
756 			GDir* dir;
757 
758 			dir = g_dir_open (value, 0, NULL);
759 			if (dir != NULL)
760 			{
761 				if (g_dir_read_name (dir) == NULL) exist = FALSE;
762 				g_dir_close (dir);
763 			}
764 		}
765 
766 		if (exist)
767 		{
768 			g_string_append_printf (data->warning, is_directory ?
769 										_("Directory \"%s\" is not empty. Project creation could fail if some files "
770 										  "cannot be written. Do you want to continue?") :
771 											_("File \"%s\" already exists. Do you want to overwrite it?"),
772 										value);
773 		}
774 	}
775 };
776 
777 /* Save values and check them, return TRUE if it's possible to go to
778  * next page */
779 
780 static gboolean
npw_druid_save_valid_values(NPWDruid * druid)781 npw_druid_save_valid_values (NPWDruid* druid)
782 {
783 	gint current;
784 	NPWPage* page;
785 	NPWSaveValidPropertyData data;
786 	gboolean ok = TRUE;
787 
788 	current = gtk_assistant_get_current_page (GTK_ASSISTANT (druid->window))  - (druid->no_selection ? 0 : 1) - 1;
789 	page = g_queue_peek_nth (druid->page_list, current);
790 	data.modified = FALSE;
791 	data.parent = GTK_WINDOW (druid->window);
792 	data.error = g_string_new (NULL);
793 	data.warning = g_string_new (NULL);
794 	npw_page_foreach_property (page, (GFunc)cb_save_valid_property, &data);
795 
796 	if (data.modified) npw_druid_remove_following_page (druid);
797 
798 	if (data.error->len)
799 	{
800 		npw_druid_fill_error_page (druid, NULL,
801 								   GTK_MESSAGE_ERROR,
802 								   NULL,
803 									"<b>%s</b>\n\n%s",
804 									_("Invalid entry"),
805 									data.error->str);
806 		ok = FALSE;
807 	}
808 	else if (data.warning->len)
809 	{
810 		npw_druid_fill_error_page (druid, NULL,
811 								   GTK_MESSAGE_WARNING,
812 								   NULL,
813 									"<b>%s</b>\n\n%s",
814 									_("Dubious entry"),
815 									data.warning->str);
816 		ok = FALSE;
817 	}
818 
819 	g_string_free (data.error, TRUE);
820 	g_string_free (data.warning, TRUE);
821 
822 	return ok;
823 }
824 
825 /* Druid call backs
826  *---------------------------------------------------------------------------*/
827 
828 static void
on_druid_cancel(GtkAssistant * window,NPWDruid * druid)829 on_druid_cancel (GtkAssistant* window, NPWDruid* druid)
830 {
831 	anjuta_plugin_deactivate (ANJUTA_PLUGIN (druid->plugin));
832 	npw_druid_free (druid);
833 }
834 
835 static void
on_druid_close(GtkAssistant * window,NPWDruid * druid)836 on_druid_close (GtkAssistant* window, NPWDruid* druid)
837 {
838 	anjuta_plugin_deactivate (ANJUTA_PLUGIN (druid->plugin));
839 	npw_druid_free (druid);
840 }
841 
842 static gboolean
on_project_wizard_key_press_event(GtkWidget * widget,GdkEventKey * event,NPWDruid * druid)843 on_project_wizard_key_press_event(GtkWidget *widget, GdkEventKey *event,
844                                NPWDruid* druid)
845 {
846 	if (event->keyval == GDK_KEY_Escape)
847 	{
848 		on_druid_cancel (GTK_ASSISTANT (widget), druid);
849 		return TRUE;
850 	}
851 	return FALSE;
852 }
853 
854 static void
on_druid_get_new_page(AnjutaAutogen * gen,gpointer data)855 on_druid_get_new_page (AnjutaAutogen* gen, gpointer data)
856 {
857 	NPWDruid* druid = (NPWDruid *)data;
858 	gint current;
859 	NPWPage* page;
860 
861 	current = gtk_assistant_get_current_page (GTK_ASSISTANT (druid->window));
862 	page = g_queue_peek_nth (druid->page_list, current - (druid->no_selection ? 0 : 1));
863 
864 	if (npw_page_get_name (page) == NULL)
865 	{
866 		/* no page, display finish page */
867 		npw_druid_fill_summary_page (druid);
868 
869 		page = g_queue_pop_nth (druid->page_list, current - (druid->no_selection ? 0 : 1));
870 		if (page != NULL) npw_page_free (page);
871 		gtk_container_remove (GTK_CONTAINER (druid->window), gtk_assistant_get_nth_page (GTK_ASSISTANT (druid->window), current + 1));
872 		gtk_assistant_set_current_page (GTK_ASSISTANT (druid->window), current + 1);
873 	}
874 	else
875 	{
876 		/* display property page */
877 		npw_druid_fill_property_page (druid, page);
878 
879 		gtk_assistant_set_current_page (GTK_ASSISTANT (druid->window), current + 1);
880 	}
881 }
882 
883 static void
on_druid_parse_page(const gchar * output,gpointer data)884 on_druid_parse_page (const gchar* output, gpointer data)
885 {
886 	GError *error = NULL;
887 	NPWPageParser* parser = (NPWPageParser*)data;
888 
889 	npw_page_parser_parse (parser, output, strlen (output), &error);
890 
891 	if (error)
892 	{
893 		g_warning ("Parser error: %s", error->message);
894 		g_error_free (error);
895 	}
896 }
897 
898 static void
strip_package_version_info(gpointer data,gpointer user_data)899 strip_package_version_info (gpointer data, gpointer user_data)
900 {
901 	gchar * const pkg = (gchar *) data;
902 
903 	if (!data)
904 		return;
905 	g_strdelimit (pkg, " ", '\0');
906 }
907 
908 static void
on_install_button_clicked(GtkWidget * button,NPWDruid * druid)909 on_install_button_clicked (GtkWidget *button, NPWDruid *druid)
910 {
911 	GList *missing_programs, *missing_packages;
912 	GList *missing_files = NULL;
913 	GList *node;
914 
915 
916 	missing_programs = npw_header_check_required_programs (druid->header);
917 	missing_packages = npw_header_check_required_packages (druid->header);
918 
919 	anjuta_util_glist_strings_prefix (missing_programs, "/usr/bin/");
920 
921 	/* Search for "pkgconfig(pkg_name)" */
922 	g_list_foreach (missing_packages, (GFunc) strip_package_version_info,
923 					NULL);
924 	missing_files = g_list_concat (missing_files, missing_programs);
925 
926 	for (node = missing_packages; node != NULL; node = g_list_next (missing_packages))
927 	{
928 		gchar* pk_pkg_config_string = g_strdup_printf ("pkgconfig(%s)", (gchar*) node->data);
929 		missing_files = g_list_append (missing_files, pk_pkg_config_string);
930 	}
931 	g_list_free (missing_packages);
932 
933 	if (missing_files)
934 	{
935 		gchar * missing_names = NULL;
936 
937 		missing_names = anjuta_util_glist_strings_join (missing_files, ", ");
938 		anjuta_util_install_files (missing_names);
939 
940 		if (missing_names)
941 			g_free (missing_names);
942 		anjuta_util_glist_strings_free (missing_files);
943 	}
944 }
945 
946 static gboolean
check_and_warn_missing(NPWDruid * druid)947 check_and_warn_missing (NPWDruid *druid)
948 {
949 	GList *missing_programs, *missing_packages;
950 	GString *missing_message = NULL;
951 
952 	missing_programs = npw_header_check_required_programs (druid->header);
953 	missing_packages = npw_header_check_required_packages (druid->header);
954 
955 	if (missing_programs || missing_packages)
956 	{
957 		missing_message = g_string_new (NULL);
958 	}
959 
960 	if (missing_programs)
961 	{
962 		gchar *missing_progs;
963 		missing_progs = anjuta_util_glist_strings_join (missing_programs,
964 														", ");
965 		g_string_append_printf (missing_message,
966 								_("\nMissing programs: %s."), missing_progs);
967 		g_free (missing_progs);
968 		anjuta_util_glist_strings_free (missing_programs);
969 	}
970 
971 	if (missing_packages)
972 	{
973 		gchar *missing_pkgs;
974 		missing_pkgs = anjuta_util_glist_strings_join (missing_packages,
975 													   ", ");
976 		g_string_append_printf (missing_message,
977 								_("\nMissing packages: %s."), missing_pkgs);
978 		g_free (missing_pkgs);
979 		anjuta_util_glist_strings_free (missing_packages);
980 	}
981 
982 	if (missing_message)
983 	{
984 		GtkWidget *hbox, *install_button;
985 		g_string_prepend (missing_message, _(
986 		 "Some important programs or development packages required to build "
987 		 "this project are missing. Please make sure they are "
988 		 "installed properly before generating the project.\n"));
989 
990 		hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
991 		gtk_widget_show (hbox);
992 
993 #ifdef ENABLE_PACKAGEKIT
994 		install_button =
995 			gtk_button_new_with_label (_("Install missing packages"));
996 		gtk_box_pack_end (GTK_BOX (hbox), install_button, FALSE, FALSE, 10);
997 		g_signal_connect (install_button, "clicked",
998 						  G_CALLBACK (on_install_button_clicked), druid);
999 		gtk_widget_show (install_button);
1000 #endif
1001 
1002 		npw_druid_fill_error_page (druid, hbox,
1003 								   GTK_MESSAGE_WARNING,
1004 								   /* Translators: Application Manager is the program used to install
1005 								    * new application like apt on Ubuntu, yum on Fedora, zypper on
1006 								    * OpenSuSE and emerge on Gentoo */
1007 								  _("The missing programs are usually part of some distribution "
1008 									"packages and can be searched for in your Application Manager. "
1009 									"Similarly, the development packages are contained in special "
1010 									"packages that your distribution provides to allow development "
1011 									"of projects based on them. They usually end with a \"-dev\" or "
1012 									"\"-devel\" suffix in package names and can be found by searching "
1013 									"in your Application Manager."),
1014 									"<b>%s</b>\n\n%s",
1015 									_("Missing components"),
1016 									missing_message->str);
1017 		g_string_free (missing_message, TRUE);
1018 	}
1019 
1020 	return !missing_message;
1021 }
1022 
1023 
1024 static void
on_druid_real_prepare(GtkAssistant * assistant,GtkWidget * page,NPWDruid * druid)1025 on_druid_real_prepare (GtkAssistant* assistant, GtkWidget *page, NPWDruid* druid)
1026 {
1027 	if (page == druid->progress_page)
1028 	{
1029 		gint previous;
1030 		gboolean last_warning;
1031 
1032 		previous = gtk_assistant_get_current_page (assistant) - 1;
1033 		last_warning = gtk_assistant_get_nth_page (assistant, previous) == druid->error_page;
1034 		if (last_warning)
1035 		{
1036 			/* Remove warning page */
1037 			gtk_container_remove (GTK_CONTAINER (assistant), druid->error_page);
1038 			previous--;
1039 		}
1040 		if (druid->no_selection) previous++;
1041 
1042 		/* Generate the next page */
1043 		if (previous == PROJECT_PAGE_INDEX)
1044 		{
1045 			const gchar* new_project;
1046 
1047 			new_project = npw_header_get_filename (druid->header);
1048 
1049 			if (druid->project_file != new_project)
1050 			{
1051 				npw_druid_remove_following_page (druid);
1052 
1053 				/* Check if necessary programs for this project is installed */
1054 				if (!last_warning && !check_and_warn_missing (druid))
1055 				{
1056 					gtk_assistant_set_current_page (assistant, gtk_assistant_get_current_page (assistant) + 1);
1057 					return;
1058 				}
1059 
1060 				/* Change project */
1061 				druid->project_file = new_project;
1062 				anjuta_autogen_set_input_file (druid->gen, druid->project_file, "[+","+]");
1063 
1064 			}
1065 		}
1066 		else
1067 		{
1068 			if (!npw_druid_save_valid_values (druid))
1069 			{
1070 				/* Display error */
1071 				gtk_assistant_set_current_page (assistant, gtk_assistant_get_current_page (assistant) + 1);
1072 
1073 				return;
1074 			}
1075 		}
1076 
1077 		if (g_queue_peek_nth (druid->page_list, previous) == NULL)
1078 		{
1079 			/* Regenerate new page */
1080 			gtk_assistant_set_page_complete (assistant, page, FALSE);
1081 			if (druid->parser != NULL)
1082 				npw_page_parser_free (druid->parser);
1083 			druid->parser = npw_page_parser_new (npw_druid_add_new_page (druid), druid->project_file, previous);
1084 
1085 			anjuta_autogen_set_output_callback (druid->gen, on_druid_parse_page, druid->parser, NULL);
1086 			anjuta_autogen_write_definition_file (druid->gen, druid->values, NULL);
1087 			anjuta_autogen_execute (druid->gen, on_druid_get_new_page, druid, NULL);
1088 		}
1089 		else
1090 		{
1091 			/* Page is already in cache, change the page to display it */
1092 			on_druid_get_new_page (NULL, druid);
1093 		}
1094 	}
1095 	else if (page == druid->finish_page)
1096 	{
1097 		npw_druid_set_busy (druid, FALSE);
1098 		gtk_container_remove (GTK_CONTAINER (assistant), druid->error_page);
1099 		gtk_container_remove (GTK_CONTAINER (assistant), druid->progress_page);
1100 	}
1101 	else
1102 	{
1103 		npw_druid_set_busy (druid, FALSE);
1104 
1105 		if (page != druid->error_page) gtk_container_remove (GTK_CONTAINER (assistant), druid->error_page);
1106 
1107 		/* Move progress page */
1108 		gtk_container_remove (GTK_CONTAINER (assistant), druid->progress_page);
1109 		gtk_assistant_insert_page (assistant, druid->progress_page, gtk_assistant_get_current_page (assistant) + 1);
1110 		gtk_assistant_set_page_title (assistant, druid->progress_page, "...");
1111 	}
1112 }
1113 
1114 static gboolean
on_druid_delayed_prepare(gpointer data)1115 on_druid_delayed_prepare (gpointer data)
1116 {
1117 	NPWDruid *druid = (NPWDruid *)data;
1118 	GtkAssistant *assistant;
1119 	GtkWidget *page;
1120 
1121 	assistant = GTK_ASSISTANT (druid->window);
1122 	page = gtk_assistant_get_nth_page (assistant, gtk_assistant_get_current_page (assistant));
1123 	on_druid_real_prepare (assistant, page, druid);
1124 
1125 	return FALSE;
1126 }
1127 
1128 static void
on_druid_prepare(GtkAssistant * assistant,GtkWidget * page,NPWDruid * druid)1129 on_druid_prepare (GtkAssistant* assistant, GtkWidget *page, NPWDruid* druid)
1130 {
1131 	/* The page change is delayed because in the latest version of
1132 	 * GtkAssistant, the page switch is not completely done when
1133 	 * the signal is called. A page change in the signal handler
1134 	 * will be partialy overwritten */
1135 	g_idle_add (on_druid_delayed_prepare, druid);
1136 }
1137 
1138 static void
npw_druid_save_default_property(NPWDruid * druid)1139 npw_druid_save_default_property (NPWDruid* druid)
1140 {
1141 	GSettings *settings;
1142 	const gchar *new_value;
1143 	gchar *old_value;
1144 
1145 
1146 	settings = g_settings_new (ANJUTA_PREF_SCHEMA_PREFIX PROJECT_WIZARD_PREF_SCHEMA);
1147 
1148 	new_value = g_hash_table_lookup (druid->values, DESTINATION_PROPERTY);
1149 	if ((new_value != NULL) && (*new_value != '\0'))
1150 	{
1151 		/* Remove project directory */
1152 		gchar *parent;
1153 
1154 		parent = g_path_get_dirname (new_value);
1155 		if (new_value[strlen(new_value) - 1] == G_DIR_SEPARATOR)
1156 		{
1157 			gchar *dir = parent;
1158 			parent = g_path_get_dirname (dir);
1159 			g_free (dir);
1160 		}
1161 
1162 		old_value = g_settings_get_string (settings, LAST_DIRECTORY);
1163 		if (strcmp (parent, old_value) != 0)
1164 		{
1165 			/* If the new directory is in the home directory, store a relative
1166 			 * path */
1167 			const gchar *home;
1168 			size_t len;
1169 
1170 			home = g_get_home_dir ();
1171 			len = strlen (home);
1172 			if ((strncmp (home, parent, len) == 0) && ((parent[len] == G_DIR_SEPARATOR) || (parent[len] == '\0')))
1173 			{
1174 				g_settings_set_string (settings, LAST_DIRECTORY, parent[len] == '\0' ? "" : parent + len + 1);
1175 			}
1176 			else
1177 			{
1178 				g_settings_set_string (settings, LAST_DIRECTORY, parent);
1179 			}
1180 		}
1181 		g_free (old_value);
1182 		g_free (parent);
1183 	}
1184 
1185 	new_value = g_hash_table_lookup (druid->values, AUTHOR_PROPERTY);
1186 	if ((new_value != NULL) && (*new_value != '\0'))
1187 	{
1188 		old_value = g_settings_get_string (settings, LAST_USER_NAME);
1189 		if (strcmp (new_value, old_value) != 0)
1190 		{
1191 			g_settings_set_string (settings, LAST_USER_NAME, new_value);
1192 		}
1193 		g_free (old_value);
1194 	}
1195 
1196 	new_value = g_hash_table_lookup (druid->values, EMAIL_PROPERTY);
1197 	if ((new_value != NULL) && (*new_value != '\0'))
1198 	{
1199 		old_value = anjuta_util_get_user_mail ();
1200 		if (strcmp (new_value, old_value) != 0)
1201 		{
1202 			anjuta_util_set_user_mail (new_value);
1203 		}
1204 		g_free (old_value);
1205 	}
1206 }
1207 
1208 static void
on_druid_finish(GtkAssistant * assistant,NPWDruid * druid)1209 on_druid_finish (GtkAssistant* assistant, NPWDruid* druid)
1210 {
1211 	NPWInstall* inst;
1212 	GList *path;
1213 
1214 	npw_druid_save_default_property (druid);
1215 
1216 	inst = npw_install_new (druid->plugin);
1217 	npw_install_set_property (inst, druid->values);
1218 	npw_install_set_wizard_file (inst, npw_header_get_filename (druid->header));
1219 	for (path = g_list_last (anjuta_autogen_get_library_paths (druid->gen)); path != NULL; path = g_list_previous (path))
1220 	{
1221 		npw_install_set_library_path (inst, (const gchar *)path->data);
1222 	}
1223 	npw_install_launch (inst);
1224 }
1225 
1226 static GtkWidget*
npw_druid_create_assistant(NPWDruid * druid,GFile * templates)1227 npw_druid_create_assistant (NPWDruid* druid, GFile *templates)
1228 {
1229 	AnjutaShell *shell;
1230 	GtkBuilder *builder;
1231 	GError* error = NULL;
1232 	GtkAssistant *assistant;
1233 	GtkWidget *property_page;
1234 
1235 	g_return_val_if_fail (druid->window == NULL, NULL);
1236 
1237 	shell = ANJUTA_PLUGIN (druid->plugin)->shell;
1238 
1239 	/* Create GtkAssistant using GtkBuilder, glade doesn't seem to work*/
1240 	builder = gtk_builder_new ();
1241 	if (!gtk_builder_add_from_file (builder, GTK_BUILDER_UI_FILE, &error))
1242 	{
1243 		g_warning ("Couldn't load builder file: %s", error->message);
1244 		g_error_free (error);
1245 		return NULL;
1246 	}
1247 	anjuta_util_builder_get_objects (builder,
1248 	                                 NEW_PROJECT_DIALOG, &assistant,
1249 	                                 PROJECT_BOOK, &druid->project_book,
1250 	                                 ERROR_VBOX, &druid->error_vbox,
1251 	                                 ERROR_TITLE, &druid->error_title,
1252 	                                 ERROR_ICON, &druid->error_icon,
1253 	                                 ERROR_MESSAGE, &druid->error_message,
1254 	                                 ERROR_DETAIL, &druid->error_detail,
1255 	                                 PROJECT_PAGE, &druid->project_page,
1256 	                                 ERROR_PAGE, &druid->error_page,
1257 	                                 PROGRESS_PAGE, &druid->progress_page,
1258 	                                 FINISH_PAGE, &druid->finish_page,
1259 	                                 FINISH_TEXT, &druid->finish_text,
1260 	                                 PROPERTY_PAGE, &property_page,
1261 	                                 NULL);
1262 	druid->window = GTK_WINDOW (assistant);
1263 	gtk_window_set_transient_for (GTK_WINDOW (assistant), GTK_WINDOW (shell));
1264 	g_object_unref (builder);
1265 
1266 	/* Connect assistant signals */
1267 	g_signal_connect (G_OBJECT (assistant), "prepare", G_CALLBACK (on_druid_prepare), druid);
1268 	g_signal_connect (G_OBJECT (assistant), "apply", G_CALLBACK (on_druid_finish), druid);
1269 	g_signal_connect (G_OBJECT (assistant), "cancel", G_CALLBACK (on_druid_cancel), druid);
1270 	g_signal_connect (G_OBJECT (assistant), "close", G_CALLBACK (on_druid_close), druid);
1271 	g_signal_connect(G_OBJECT(assistant), "key-press-event", G_CALLBACK(on_project_wizard_key_press_event), druid);
1272 
1273 	/* Remove property page, will be created later as needed */
1274 	gtk_container_remove (GTK_CONTAINER (assistant), property_page);
1275 	/* Remove error page, could be needed later so keep a ref */
1276 	g_object_ref (druid->error_page);
1277 	gtk_container_remove (GTK_CONTAINER (assistant), druid->error_page);
1278 	/* Remove progress page, could be needed later so keep a ref */
1279 	g_object_ref (druid->progress_page);
1280 	gtk_container_remove (GTK_CONTAINER (assistant), druid->progress_page);
1281 
1282 	/* Setup project selection page */
1283 	if (!npw_druid_fill_selection_page (druid, templates))
1284 	{
1285 		return NULL;
1286 	}
1287 
1288 	/* Add dialog widget to anjuta status. */
1289 	anjuta_status_add_widget (anjuta_shell_get_status (shell, NULL), GTK_WIDGET (assistant));
1290 
1291 	gtk_window_set_default_size (GTK_WINDOW (assistant),
1292 	                             600, 500);
1293 
1294 	gtk_widget_show_all (GTK_WIDGET (assistant));
1295 
1296 	return GTK_WIDGET(assistant);
1297 }
1298 
1299 /* Add default property
1300  *---------------------------------------------------------------------------*/
1301 
1302 static void
npw_druid_add_default_property(NPWDruid * druid)1303 npw_druid_add_default_property (NPWDruid* druid)
1304 {
1305 	gchar* s;
1306 	GSettings *settings;
1307 	gboolean flag;
1308 	gint i;
1309 
1310 
1311 	/* Add default base project directory */
1312 	settings = g_settings_new (ANJUTA_PREF_SCHEMA_PREFIX PROJECT_WIZARD_PREF_SCHEMA);
1313 	s = g_settings_get_string (settings,LAST_DIRECTORY);
1314 	if (*s == '\0')
1315 	{
1316 		s = g_strdup (g_get_home_dir());
1317 	}
1318 	else if (!g_path_is_absolute (s))
1319 	{
1320 		gchar *path;
1321 
1322 		path = g_build_filename (g_get_home_dir(), s, NULL);
1323 		g_free (s);
1324 		s = path;
1325 	}
1326 	g_hash_table_insert (druid->values, g_strdup (ANJUTA_PROJECT_DIRECTORY_PROPERTY), s);
1327 
1328 	/* Add user name */
1329 	s = g_settings_get_string (settings,LAST_USER_NAME);
1330 	if (*s == '\0')
1331 	{
1332 		g_free (s);
1333 		s = g_strdup (g_get_real_name());
1334 	}
1335 	g_hash_table_insert (druid->values, g_strdup (USER_NAME_PROPERTY), s);
1336 
1337 	/* Add Email address */
1338 	s = anjuta_util_get_user_mail ();
1339 	g_hash_table_insert (druid->values, g_strdup (EMAIL_ADDRESS_PROPERTY), s);
1340 	g_object_unref (settings);
1341 
1342 	/* Add use-tabs property */
1343 	settings = g_settings_new (ANJUTA_PREF_SCHEMA_PREFIX IANJUTA_EDITOR_PREF_SCHEMA);
1344 	flag = g_settings_get_boolean (settings, IANJUTA_EDITOR_USE_TABS_KEY);
1345 	g_hash_table_insert (druid->values, g_strdup (USE_TABS_PROPERTY), g_strdup (flag ? "1" : "0"));
1346 
1347 	/* Add tab-width property */
1348 	i = g_settings_get_int (settings, IANJUTA_EDITOR_TAB_WIDTH_KEY);
1349 	g_hash_table_insert (druid->values, g_strdup (TAB_WIDTH_PROPERTY), g_strdup_printf("%d", i));
1350 
1351 	/* Add indent-width property */
1352 	i = g_settings_get_int (settings, IANJUTA_EDITOR_INDENT_WIDTH_KEY);
1353 	g_hash_table_insert (druid->values, g_strdup (INDENT_WIDTH_PROPERTY), g_strdup_printf("%d", i));
1354 	g_object_unref (settings);
1355 }
1356 
1357 /* Druid public functions
1358  *---------------------------------------------------------------------------*/
1359 
1360 NPWDruid*
npw_druid_new(NPWPlugin * plugin,GFile * templates)1361 npw_druid_new (NPWPlugin* plugin, GFile *templates)
1362 {
1363 	NPWDruid* druid;
1364 
1365 	/* Check if autogen is present */
1366 	if (!anjuta_check_autogen())
1367 	{
1368 		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."));
1369 		return NULL;
1370 	}
1371 
1372 	druid = g_new0(NPWDruid, 1);
1373 	druid->plugin = plugin;
1374 	druid->project_file = NULL;
1375 	druid->busy = FALSE;
1376 	druid->no_selection = FALSE;
1377 	druid->page_list = g_queue_new ();
1378 	druid->values = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify)g_free);
1379 	druid->gen = anjuta_autogen_new ();
1380 	plugin->druid = druid;
1381 	druid->error_extra_widget = NULL;
1382 
1383 	if (npw_druid_create_assistant (druid, templates) == NULL)
1384 	{
1385 		npw_druid_free (druid);
1386 
1387 		return NULL;
1388 	}
1389 
1390 	npw_druid_add_default_property (druid);
1391 
1392 	return druid;
1393 }
1394 
1395 void
npw_druid_free(NPWDruid * druid)1396 npw_druid_free (NPWDruid* druid)
1397 {
1398 	NPWPage* page;
1399 
1400 	g_return_if_fail (druid != NULL);
1401 
1402 	/* Delete page list */
1403 
1404 	while ((page = (NPWPage *)g_queue_pop_head (druid->page_list)) != NULL)
1405 	{
1406 		npw_page_free (page);
1407 	}
1408 	g_queue_free (druid->page_list);
1409 	g_hash_table_destroy (druid->values);
1410 	g_object_unref (G_OBJECT (druid->gen));
1411 	if (druid->parser != NULL) npw_page_parser_free (druid->parser);
1412 	npw_header_list_free (druid->header_list);
1413 	/* Destroy project notebook first to avoid a critical warning */
1414 	gtk_widget_destroy (GTK_WIDGET (druid->project_book));
1415 	gtk_widget_destroy (GTK_WIDGET (druid->window));
1416 	g_object_unref (druid->error_page);
1417 	g_object_unref (druid->progress_page);
1418 	druid->plugin->druid = NULL;
1419 	g_free (druid);
1420 }
1421 
1422 void
npw_druid_show(NPWDruid * druid)1423 npw_druid_show (NPWDruid* druid)
1424 {
1425 	g_return_if_fail (druid != NULL);
1426 
1427 	/* Display dialog box */
1428 	if (druid->window) gtk_window_present (druid->window);
1429 }
1430