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