glade: Fix make file some files were not installed
[anjuta.git] / plugins / project-manager / dialogs.c
blob0f582b4164fb7b4102d591750e13b46e816eda5d
1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4; coding: utf-8 -*- */
2 /* am-dialogs.c
4 * Copyright (C) 2009 Sébastien Granjoux
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation; either version 2 of the
9 * License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
16 * You should have received a copy of the GNU General Public
17 * License along with this program; if not, write to the
18 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 * Boston, MA 02111-1307, USA.
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
27 #include <glib/gi18n.h>
29 #include "dialogs.h"
31 #include "project-model.h"
32 #include "project-view.h"
34 #include <libanjuta/anjuta-debug.h>
35 #include <libanjuta/anjuta-utils.h>
36 #include <libanjuta/anjuta-pkg-config-chooser.h>
37 #include <libanjuta/anjuta-tree-combo.h>
38 #include <libanjuta/interfaces/ianjuta-project-chooser.h>
40 #define ICON_SIZE 16
42 #define GLADE_FILE PACKAGE_DATA_DIR "/glade/pm_dialogs.ui"
44 #define ANJUTA_MANUAL "anjuta-manual"
45 #define ADD_SOURCE_HELP "project-manager-source-add"
46 #define ADD_TARGET_HELP "project-manager-target-add"
47 #define ADD_PACKAGE_HELP "project-manager-module-new"
48 #define ADD_MODULE_HELP "project-manager-module-add"
49 #define ADD_FOLDER_HELP "project-manager-folder-add"
52 /* Types
53 *---------------------------------------------------------------------------*/
55 typedef struct _PropertiesTable
57 AnjutaPmProject *project;
58 GtkWidget *dialog;
59 GtkWidget *table;
60 GtkWidget *head;
61 GtkWidget *main;
62 GtkWidget *expand;
63 GtkWidget *extra;
64 GtkWidget *viewport;
65 GtkWidget *scrolledwindow;
66 GbfTreeData *data;
67 AnjutaProjectNode *node;
68 GtkWidget *help_button;
69 const gchar *help_id;
70 GList *properties;
71 } PropertiesTable;
73 typedef struct _PropertyEntry
75 GtkWidget *entry;
76 AnjutaProjectPropertyInfo *info;
77 } PropertyEntry;
79 typedef struct _PropertyValue
81 AnjutaProjectProperty *property;
82 const gchar *value;
83 } PropertyValue;
85 enum {
86 NAME_COLUMN,
87 VALUE_COLUMN,
88 EDITABLE_COLUMN,
89 PROPERTY_COLUMN,
90 LIST_COLUMNS_NB
93 /* Sources list columns in new source dialog */
94 enum {
95 COLUMN_FILE,
96 COLUMN_URI,
97 N_COLUMNS
100 /* Helper functions
101 *---------------------------------------------------------------------------*/
103 static GtkBuilder *
104 load_interface (const gchar *top_widget)
106 GtkBuilder *xml = gtk_builder_new ();
107 GError* error = NULL;
109 if (!gtk_builder_add_from_file (xml, GLADE_FILE, &error))
111 g_warning ("Couldn't load builder file: %s", error->message);
112 g_error_free (error);
113 return NULL;
116 return xml;
119 static void
120 error_dialog (GtkWindow *parent, const gchar *summary, const gchar *msg, ...)
122 va_list ap;
123 gchar *tmp;
124 GtkWidget *dialog;
126 va_start (ap, msg);
127 tmp = g_strdup_vprintf (msg, ap);
128 va_end (ap);
130 dialog = gtk_message_dialog_new_with_markup (parent,
131 GTK_DIALOG_DESTROY_WITH_PARENT,
132 GTK_MESSAGE_ERROR,
133 GTK_BUTTONS_OK,
134 "<b>%s</b>\n\n%s", summary, tmp);
135 g_free (tmp);
137 gtk_dialog_run (GTK_DIALOG (dialog));
138 gtk_widget_destroy (dialog);
142 /* Private nodes functions
143 *---------------------------------------------------------------------------*/
145 static PropertyEntry*
146 pm_property_entry_new (GtkWidget *entry, AnjutaProjectPropertyInfo *info)
148 PropertyEntry *prop;
150 prop = g_slice_new0(PropertyEntry);
151 prop->entry = entry;
152 prop->info = info;
154 return prop;
157 static void
158 pm_property_entry_free (PropertyEntry *prop)
160 g_slice_free (PropertyEntry, prop);
163 static gboolean
164 parent_filter_func (GtkTreeModel *model, GtkTreeIter *iter, gpointer user_data)
166 GbfTreeData *data = NULL;
167 gboolean visible = FALSE;
168 AnjutaProjectNodeType type = (AnjutaProjectNodeType)GPOINTER_TO_INT (user_data);
169 AnjutaProjectNode *parent;
170 AnjutaProjectNode *node;
171 gint need;
173 switch (type)
175 case ANJUTA_PROJECT_GROUP:
176 need = ANJUTA_PROJECT_CAN_ADD_GROUP;
177 break;
178 case ANJUTA_PROJECT_TARGET:
179 need = ANJUTA_PROJECT_CAN_ADD_TARGET;
180 break;
181 case ANJUTA_PROJECT_SOURCE:
182 /* Add node containing target too because target can contains module
183 * It would be probably better to check recursively if any children
184 * can accept a module and keep all parents then. */
185 need = ANJUTA_PROJECT_CAN_ADD_SOURCE | ANJUTA_PROJECT_CAN_ADD_TARGET;
186 break;
187 case ANJUTA_PROJECT_MODULE:
188 /* Add node containing target too because target can contains module
189 * It would be probably better to check recursively if any children
190 * can accept a module and keep all parents then. */
191 need = ANJUTA_PROJECT_CAN_ADD_MODULE | ANJUTA_PROJECT_CAN_ADD_TARGET;
192 break;
193 case ANJUTA_PROJECT_PACKAGE:
194 need = ANJUTA_PROJECT_CAN_ADD_PACKAGE;
195 break;
196 default:
197 need = 0;
198 break;
201 gtk_tree_model_get (model, iter,
202 GBF_PROJECT_MODEL_COLUMN_DATA, &data, -1);
203 if (data->shortcut != NULL)
205 visible = FALSE;
207 else
209 node = data == NULL ? NULL : gbf_tree_data_get_node (data);
210 if (node != NULL)
212 if (anjuta_project_node_get_state (node) & need)
214 /* Current node can be used as parent */
215 visible = TRUE;
217 else if (anjuta_project_node_get_node_type (node) == type)
219 /* Check if node can be used as sibling */
220 parent = anjuta_project_node_parent (node);
221 visible = anjuta_project_node_get_state (parent) & need ? TRUE : FALSE;
226 return visible;
229 static gboolean
230 module_filter_func (GtkTreeModel *model, GtkTreeIter *iter, gpointer user_data)
232 GbfTreeData *data = NULL;
233 gboolean visible = FALSE;
234 AnjutaProjectNode *node;
236 gtk_tree_model_get (model, iter,
237 GBF_PROJECT_MODEL_COLUMN_DATA, &data, -1);
238 node = data == NULL ? NULL : gbf_tree_data_get_node (data);
239 if (node != NULL)
241 AnjutaProjectNodeType type = anjuta_project_node_get_node_type (node);
243 visible = (type == ANJUTA_PROJECT_MODULE) || (type == ANJUTA_PROJECT_PACKAGE);
246 return visible;
249 static void
250 setup_nodes_treeview (GbfProjectView *view,
251 GbfProjectView *parent,
252 GtkTreePath *root,
253 GtkTreeModelFilterVisibleFunc func,
254 gpointer data,
255 GtkTreeIter *selected)
257 g_return_if_fail (view != NULL && GBF_IS_PROJECT_VIEW (view));
258 g_return_if_fail (parent != NULL);
260 gbf_project_view_set_parent_view (view, parent, root);
261 gbf_project_view_set_visible_func (view, func, data, NULL);
262 gbf_project_view_set_cursor_to_iter (view, selected);
265 static void
266 entry_changed_cb (GtkEditable *editable, gpointer user_data)
268 GtkWidget *button = user_data;
269 gchar *text;
271 if (!button)
272 return;
274 text = gtk_editable_get_chars (editable, 0, -1);
275 if (strlen (text) > 0) {
276 gtk_widget_set_sensitive (button, TRUE);
277 gtk_widget_grab_default (button);
278 } else {
279 gtk_widget_set_sensitive (button, FALSE);
281 g_free (text);
284 static void
285 on_value_edited (GtkCellRendererText *cell,
286 gchar *path_string,
287 gchar *text,
288 gpointer user_data)
290 GtkTreeView *view = (GtkTreeView *)user_data;
291 GtkTreeIter iter;
292 GtkTreeModel * model;
294 model = gtk_tree_view_get_model (GTK_TREE_VIEW (view));
295 if (gtk_tree_model_get_iter_from_string (model, &iter, path_string))
297 gtk_list_store_set (GTK_LIST_STORE (model), &iter, VALUE_COLUMN, text, -1);
301 static void
302 on_row_changed(GtkTreeModel* model, GtkTreePath* path, GtkTreeIter* iter, gpointer data)
304 GtkWidget* button = GTK_WIDGET(data);
305 if (gtk_list_store_iter_is_valid(GTK_LIST_STORE(model), iter))
306 gtk_widget_set_sensitive(button, TRUE);
307 else
308 gtk_widget_set_sensitive(button, FALSE);
311 static void
312 browse_button_clicked_cb (GtkWidget *widget, gpointer user_data)
314 GtkTreeView *tree = user_data;
315 GtkTreeView *treeview;
316 GtkFileChooserDialog* dialog;
317 GtkTreeModel* model;
318 AnjutaProjectNode *parent;
319 gint result;
321 g_return_if_fail (user_data != NULL && GTK_IS_TREE_VIEW (user_data));
323 model = gtk_tree_view_get_model(tree);
324 /*if (gtk_tree_model_get_iter_first(model, &iter))
326 gtk_tree_model_get(model, &iter, COLUMN_URI, &file, -1);
327 uri = g_strdup(file);
329 else
330 uri = g_strdup("");*/
332 dialog = GTK_FILE_CHOOSER_DIALOG(gtk_file_chooser_dialog_new (_("Select sources…"),
333 GTK_WINDOW (gtk_widget_get_toplevel (widget)),
334 GTK_FILE_CHOOSER_ACTION_OPEN,
335 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
336 GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
337 NULL));
339 /* Get default directory */
340 treeview = g_object_get_data (G_OBJECT (widget), "treeview");
341 parent = gbf_project_view_find_selected (GBF_PROJECT_VIEW (treeview), ANJUTA_PROJECT_UNKNOWN);
342 if (!(anjuta_project_node_get_state (parent) & ANJUTA_PROJECT_CAN_ADD_SOURCE))
344 parent = anjuta_project_node_parent (parent);
346 gtk_file_chooser_set_current_folder_file(GTK_FILE_CHOOSER(dialog),
347 anjuta_project_node_get_file (parent), NULL);
349 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER(dialog), TRUE);
351 result = gtk_dialog_run (GTK_DIALOG (dialog));
352 switch (result)
354 case GTK_RESPONSE_ACCEPT:
356 GSList* uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER(dialog));
357 GSList* node_uri = uris;
359 gtk_list_store_clear (GTK_LIST_STORE (model));
361 while (node_uri != NULL)
363 GtkTreeIter iter;
364 gchar* uri = node_uri->data;
365 gchar* file = g_path_get_basename (uri);
366 gtk_list_store_append (GTK_LIST_STORE (model), &iter);
367 gtk_list_store_set (GTK_LIST_STORE (model), &iter, COLUMN_FILE,
368 file, COLUMN_URI, uri, -1);
369 node_uri = g_slist_next (node_uri);
371 g_slist_free (uris);
372 break;
374 default:
375 break;
377 gtk_widget_destroy (GTK_WIDGET(dialog));
380 /* Private properties functions
381 *---------------------------------------------------------------------------*/
383 static GtkWidget *
384 add_entry (IAnjutaProject *project, AnjutaProjectNode *node, AnjutaProjectProperty *prop, GtkWidget *table, gint *position)
386 GtkWidget *label;
387 GtkWidget *entry = NULL;
388 GtkWidget *view;
389 static GType column_type[LIST_COLUMNS_NB] = {
390 G_TYPE_STRING, G_TYPE_STRING, G_TYPE_BOOLEAN, G_TYPE_POINTER};
391 GtkCellRenderer *renderer;
392 GtkTreeViewColumn *column;
393 GtkTreeModel *model;
394 GtkTreeIter iter;
395 GList *item;
396 gchar *tooltip = NULL;
397 gboolean editable = TRUE;
399 label = gtk_label_new (_(prop->info->name));
401 editable = prop->info->flags & ANJUTA_PROJECT_PROPERTY_READ_ONLY ? FALSE : TRUE;
403 if (prop->info->description != NULL)
405 if (!editable)
407 tooltip = g_strconcat (_(prop->info->description), _(" This property is not modifiable."), NULL);
409 else
411 tooltip = g_strdup (_(prop->info->description));
415 if (tooltip != NULL)
417 gtk_widget_set_tooltip_markup (label, tooltip);
419 gtk_misc_set_alignment (GTK_MISC (label), 0, -1);
420 gtk_widget_show (label);
421 gtk_table_attach (GTK_TABLE (table), label, 0, 1, *position, *position+1,
422 GTK_FILL, GTK_FILL, 5, 3);
424 switch (prop->info->type)
426 case ANJUTA_PROJECT_PROPERTY_STRING:
427 case ANJUTA_PROJECT_PROPERTY_LIST:
428 if (editable)
430 entry = gtk_entry_new ();
431 gtk_entry_set_text (GTK_ENTRY (entry), prop->value != NULL ? prop->value : "");
433 else
435 entry = gtk_label_new (prop->value != NULL ? prop->value : "");
436 gtk_misc_set_alignment (GTK_MISC (entry), 0, 0.5);
438 break;
439 case ANJUTA_PROJECT_PROPERTY_BOOLEAN:
440 entry = gtk_check_button_new ();
441 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (entry), (prop->value != NULL) && (*prop->value == '1'));
442 gtk_widget_set_sensitive (entry, editable);
443 break;
444 case ANJUTA_PROJECT_PROPERTY_MAP:
445 model = GTK_TREE_MODEL (gtk_list_store_newv (LIST_COLUMNS_NB, column_type));
447 for (item = anjuta_project_node_get_properties (node); item != NULL; item = g_list_next (item))
449 AnjutaProjectProperty *cust_prop = (AnjutaProjectProperty *)item->data;
451 if (cust_prop->info == prop->info)
453 gtk_list_store_append (GTK_LIST_STORE (model), &iter);
454 gtk_list_store_set (GTK_LIST_STORE (model), &iter,
455 NAME_COLUMN, cust_prop->name,
456 VALUE_COLUMN, cust_prop->value,
457 EDITABLE_COLUMN, TRUE,
458 PROPERTY_COLUMN, cust_prop,
459 -1);
463 gtk_list_store_append (GTK_LIST_STORE (model), &iter);
464 gtk_list_store_set (GTK_LIST_STORE (model), &iter,
465 NAME_COLUMN, "",
466 VALUE_COLUMN, "",
467 EDITABLE_COLUMN, TRUE,
468 PROPERTY_COLUMN, NULL,
469 -1);
471 entry = gtk_frame_new (NULL);
472 gtk_frame_set_shadow_type (GTK_FRAME (entry), GTK_SHADOW_IN);
474 view = gtk_tree_view_new_with_model (model);
475 gtk_tree_selection_set_mode (gtk_tree_view_get_selection (GTK_TREE_VIEW (view)),
476 GTK_SELECTION_SINGLE);
477 gtk_tree_view_set_headers_clickable (GTK_TREE_VIEW (view), TRUE);
478 g_object_unref (G_OBJECT (model));
480 renderer = gtk_cell_renderer_text_new ();
481 column = gtk_tree_view_column_new_with_attributes (_("Name"),
482 renderer,
483 "text",
484 NAME_COLUMN,
485 NULL);
486 gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
487 gtk_tree_view_append_column (GTK_TREE_VIEW (view), column);
488 renderer = gtk_cell_renderer_text_new ();
489 column = gtk_tree_view_column_new_with_attributes (_("Value"),
490 renderer,
491 "text",
492 VALUE_COLUMN,
493 "editable",
494 EDITABLE_COLUMN,
495 NULL);
496 g_signal_connect(renderer, "edited", (GCallback) on_value_edited, view);
497 gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
498 gtk_tree_view_append_column (GTK_TREE_VIEW (view), column);
500 gtk_container_add (GTK_CONTAINER (entry), view);
502 break;
503 default:
504 return NULL;
506 if (tooltip != NULL)
508 gtk_widget_set_tooltip_markup (entry, tooltip);
510 g_free (tooltip);
512 gtk_widget_show (entry);
513 gtk_table_attach (GTK_TABLE (table), entry, 1, 2, *position, *position+1,
514 GTK_FILL | GTK_EXPAND, GTK_FILL, 5, 3);
516 *position = *position + 1;
518 return entry;
521 static void
522 add_label (const gchar *display_name, const gchar *value, GtkWidget *table, gint *position)
524 GtkWidget *label;
526 label = gtk_label_new (display_name);
527 gtk_misc_set_alignment (GTK_MISC (label), 0, -1);
528 gtk_widget_show (label);
529 gtk_table_attach (GTK_TABLE (table), label, 0, 1, *position, *position+1,
530 GTK_FILL, GTK_FILL, 5, 3);
532 label = gtk_label_new (value);
533 gtk_misc_set_alignment (GTK_MISC (label), 0, -1);
534 gtk_widget_show (label);
535 gtk_table_attach (GTK_TABLE (table), label, 1, 2, *position, *position+1,
536 GTK_FILL | GTK_EXPAND, GTK_FILL, 5, 3);
538 *position = *position + 1;
541 static void
542 update_properties (PropertiesTable *table)
544 GFile *file;
545 const gchar *title;
546 gint head_pos;
547 gint main_pos;
548 gint extra_pos;
549 const GList *item;
550 AnjutaProjectNodeType type;
551 AnjutaProjectNodeInfo* node_info;
552 gboolean single;
553 GList *children;
555 head_pos = 0;
556 main_pos = 0;
557 extra_pos = 0;
559 /* Update dialog type */
560 switch (anjuta_project_node_get_node_type (table->node))
562 case ANJUTA_PROJECT_ROOT:
563 title = _("Project properties");
564 break;
565 case ANJUTA_PROJECT_GROUP:
566 if ((anjuta_project_node_get_full_type (table->node) & ANJUTA_PROJECT_ID_MASK) == ANJUTA_PROJECT_ROOT_GROUP)
568 title = _("Project properties");
570 else
572 title = _("Folder properties");
574 break;
575 case ANJUTA_PROJECT_TARGET:
576 title = _("Target properties");
577 break;
578 case ANJUTA_PROJECT_SOURCE:
579 title = _("Source properties");
580 break;
581 case ANJUTA_PROJECT_MODULE:
582 title = _("Module properties");
583 break;
584 case ANJUTA_PROJECT_PACKAGE:
585 title = _("Package properties");
586 break;
587 default:
588 title = _("Unknown properties");
589 break;
591 gtk_window_set_title (GTK_WINDOW (table->dialog), title);
593 /* Clear table */
594 children = gtk_container_get_children (GTK_CONTAINER (table->head));
595 g_list_foreach (children, (GFunc)gtk_widget_destroy, NULL);
596 g_list_free (children);
597 children = gtk_container_get_children (GTK_CONTAINER (table->main));
598 g_list_foreach (children, (GFunc)gtk_widget_destroy, NULL);
599 g_list_free (children);
600 children = gtk_container_get_children (GTK_CONTAINER (table->extra));
601 g_list_foreach (children, (GFunc)gtk_widget_destroy, NULL);
602 g_list_free (children);
603 g_list_foreach (table->properties, (GFunc)pm_property_entry_free, NULL);
604 g_list_free (table->properties);
605 table->properties = NULL;
607 /* Update node name */
608 file = anjuta_project_node_get_file (table->node);
609 if (file != NULL)
611 gchar *path;
613 path = g_file_get_path (file);
614 add_label (_("Path:"), path, table->head, &head_pos);
615 g_free (path);
617 else
619 add_label (_("Name:"), anjuta_project_node_get_name (table->node), table->head, &head_pos);
622 /* Display node type only if several types are possible */
623 node_info = NULL;
624 single = TRUE;
625 type = anjuta_project_node_get_full_type (table->node);
626 for (item = ianjuta_project_get_node_info (table->project->project, NULL); item != NULL; item = g_list_next (item))
628 AnjutaProjectNodeInfo* info = (AnjutaProjectNodeInfo *)item->data;
630 if (info->type == type)
632 node_info = info;
634 else if ((info->type & ANJUTA_PROJECT_TYPE_MASK) == (type & ANJUTA_PROJECT_TYPE_MASK))
636 single = FALSE;
639 if (!single && (node_info != NULL))
641 add_label (_("Type:"), anjuta_project_node_info_name (node_info), table->main, &main_pos);
644 /* Show help button if existing */
645 if ((node_info != NULL) && (anjuta_project_node_info_property_help_id (node_info) != NULL))
647 table->help_id = anjuta_project_node_info_property_help_id (node_info);
648 gtk_widget_show (table->help_button);
650 else
652 table->help_id = NULL;
653 gtk_widget_hide (table->help_button);
656 /* Display other node properties */
657 single = FALSE;
659 for (item = anjuta_project_node_get_properties_info (table->node); item != NULL; item = g_list_next (item))
661 AnjutaProjectPropertyInfo *info = (AnjutaProjectPropertyInfo *)item->data;
663 if (!(info->flags & ANJUTA_PROJECT_PROPERTY_HIDDEN))
665 AnjutaProjectProperty *prop;
666 GtkWidget *entry;
668 prop = anjuta_project_node_get_property (table->node, info->id);
669 if (prop != prop->info->default_value)
671 /* This property has been set, display it in the main part */
672 entry = add_entry (table->project->project, table->node, prop, table->main, &main_pos);
674 else
676 /* This property has not been set, hide it by default */
677 entry = add_entry (table->project->project, table->node, info->default_value, table->extra, &extra_pos);
678 single = TRUE;
681 if (entry != NULL)
683 table->properties = g_list_prepend (table->properties,
684 pm_property_entry_new (entry, info));
688 table->properties = g_list_reverse (table->properties);
689 gtk_widget_show_all (table->table);
691 /* Hide expander if it is empty */
692 if (single)
693 gtk_widget_show (table->expand);
694 else
695 gtk_widget_hide (table->expand);
697 pm_project_resize_properties_dialog (table);
700 static void
701 on_properties_dialog_response (GtkWidget *dialog,
702 gint id,
703 PropertiesTable *table)
705 if (id == GTK_RESPONSE_APPLY)
707 GList *item;
709 /* Get all modified properties */
710 for (item = g_list_first (table->properties); item != NULL; item = g_list_next (item))
712 PropertyEntry *entry = (PropertyEntry *)item->data;
713 AnjutaProjectProperty *prop;
714 const gchar *text;
715 gboolean valid;
716 gboolean active;
717 GtkTreeIter iter;
718 GtkTreeModel *model;
720 /* Get property value in node */
721 prop = anjuta_project_node_get_property (table->node, entry->info->id);
723 switch (prop->info->type)
725 case ANJUTA_PROJECT_PROPERTY_STRING:
726 case ANJUTA_PROJECT_PROPERTY_LIST:
727 if (GTK_IS_ENTRY (entry->entry))
729 text = gtk_entry_get_text (GTK_ENTRY (entry->entry));
730 if (*text == '\0')
732 if ((prop->value != NULL) && (*prop->value != '\0'))
734 /* Remove */
735 ianjuta_project_set_property (table->project->project, table->node, entry->info->id, NULL, NULL, NULL);
738 else
740 if (g_strcmp0 (prop->value, text) != 0)
742 /* Modified */
743 ianjuta_project_set_property (table->project->project, table->node, entry->info->id, NULL, text, NULL);
747 break;
748 case ANJUTA_PROJECT_PROPERTY_BOOLEAN:
749 active = prop->value == NULL ? FALSE : (*prop->value == '1' ? TRUE : FALSE);
750 text = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (entry->entry)) ? "1" : "0";
752 if (active != (*text == '1'))
754 /* Modified */
755 ianjuta_project_set_property (table->project->project, table->node, entry->info->id, NULL, text, NULL);
757 break;
758 case ANJUTA_PROJECT_PROPERTY_MAP:
759 model = gtk_tree_view_get_model (GTK_TREE_VIEW (gtk_bin_get_child (GTK_BIN (entry->entry))));
760 for (valid = gtk_tree_model_get_iter_first (model, &iter); valid; valid = gtk_tree_model_iter_next (model, &iter))
762 AnjutaProjectProperty *cust_prop;
763 gchar *value;
765 value = NULL;
766 cust_prop = NULL;
767 gtk_tree_model_get (model, &iter, VALUE_COLUMN, &value, PROPERTY_COLUMN, &cust_prop, -1);
768 if ((cust_prop != NULL) && (g_strcmp0 (cust_prop->value, value) != 0))
770 /* Modified */
771 ianjuta_project_set_property (table->project->project, table->node, entry->info->id, cust_prop->name, value, NULL);
773 g_free (value);
775 break;
776 default:
777 break;
781 else if (id == GTK_RESPONSE_HELP)
783 anjuta_util_help_display (GTK_WIDGET (dialog), ANJUTA_MANUAL, table->help_id);
784 return;
786 g_list_foreach (table->properties, (GFunc)pm_property_entry_free, NULL);
787 g_free (table);
788 gtk_widget_destroy (dialog);
791 static void
792 on_node_changed (AnjutaTreeComboBox *view,
793 gpointer user_data)
795 PropertiesTable *table = (PropertiesTable *)user_data;
796 GtkTreeIter iter;
798 if (anjuta_tree_combo_box_get_active_iter (view, &iter))
800 GtkTreeModel *model;
801 GbfTreeData *data;
803 model = anjuta_tree_combo_box_get_model (view);
804 gtk_tree_model_get (model, &iter, GBF_PROJECT_MODEL_COLUMN_DATA, &data, -1);
806 if (table->data->properties_dialog != NULL)
808 g_object_remove_weak_pointer (G_OBJECT (table->dialog), (gpointer *)&table->data->properties_dialog);
809 table->data->properties_dialog = NULL;
811 if (data->properties_dialog != NULL)
813 g_object_unref (data->properties_dialog);
815 table->data = data;
816 data->properties_dialog = table->dialog;
817 g_object_add_weak_pointer (G_OBJECT (table->dialog), (gpointer *)&table->data->properties_dialog);
819 table->node = gbf_tree_data_get_node (data);
820 update_properties (table);
824 static void
825 on_expand_changed (GtkWidget * widget, gpointer user_data)
827 PropertiesTable *table = (PropertiesTable *)user_data;
828 pm_project_resize_properties_dialog (table);
831 static GtkWidget *
832 pm_project_create_properties_dialog (AnjutaPmProject *project, GtkWindow *parent, GbfProjectView *view, GbfTreeData *data, GtkTreeIter *selected)
834 PropertiesTable *table;
835 GtkBuilder *bxml;
836 GtkWidget *node_combo;
837 GtkTreeIter iter;
839 g_return_val_if_fail (data != NULL, NULL);
841 bxml = anjuta_util_builder_new (GLADE_FILE, NULL);
842 if (!bxml) return NULL;
844 table = g_new0 (PropertiesTable, 1);
845 table->data = data;
846 table->node = gbf_tree_data_get_node (data);
847 table->project = project;
848 anjuta_util_builder_get_objects (bxml,
849 "property_dialog", &table->dialog,
850 "properties", &table->table,
851 "nodes_combo", &node_combo,
852 "head_table", &table->head,
853 "main_table", &table->main,
854 "extra_table", &table->extra,
855 "extra_expand", &table->expand,
856 "viewport", &table->viewport,
857 "scrolledwindow", &table->scrolledwindow,
858 "property_help_button", &table->help_button,
859 NULL);
860 g_object_ref (table->table);
861 g_object_unref (bxml);
863 /* Add combo node selection */
864 ianjuta_project_chooser_set_project_model (IANJUTA_PROJECT_CHOOSER (node_combo),
865 IANJUTA_PROJECT_MANAGER (table->project->plugin),
866 ANJUTA_PROJECT_ROOT,
867 NULL);
868 if (pm_convert_project_iter_to_model_iter (GTK_TREE_MODEL (anjuta_tree_combo_box_get_model (ANJUTA_TREE_COMBO_BOX (node_combo))),
869 &iter, selected))
871 anjuta_tree_combo_box_set_active_iter (ANJUTA_TREE_COMBO_BOX (node_combo), &iter);
873 g_signal_connect (node_combo, "changed",
874 G_CALLBACK (on_node_changed),
875 table);
877 g_signal_connect_after (table->expand, "activate",
878 G_CALLBACK (on_expand_changed),
879 table);
881 update_properties (table);
883 g_signal_connect (table->dialog, "response",
884 G_CALLBACK (on_properties_dialog_response),
885 table);
887 pm_project_resize_properties_dialog (table);
888 gtk_widget_show (table->dialog);
890 return table->dialog;
893 void
894 pm_project_resize_properties_dialog (PropertiesTable *table)
896 gint border_width, maximum_width, maximum_height;
897 GtkRequisition dialog, head, viewport, scrolledwindow_minimum, vscrollbar_minimum;
898 GtkWidget *vscrollbar = gtk_scrolled_window_get_vscrollbar (table->scrolledwindow);
900 gtk_widget_get_preferred_size (table->dialog, NULL, &dialog);
901 gtk_widget_get_preferred_size (table->head, NULL, &head);
902 gtk_widget_get_preferred_size (table->viewport, NULL, &viewport);
903 gtk_widget_get_preferred_size (table->scrolledwindow, &scrolledwindow_minimum, NULL);
904 gtk_widget_get_preferred_size (vscrollbar, &vscrollbar_minimum, NULL);
906 //auxiliary variables
907 border_width = dialog.width - head.width;
908 maximum_width = gdk_screen_width() * 3/4;
909 maximum_height = gdk_screen_height() * 3/4;
911 gint height = dialog.height - scrolledwindow_minimum.height + viewport.height;
912 gint width = (head.width > viewport.width) ? dialog.width : viewport.width + vscrollbar_minimum.width + border_width;
914 if (height > maximum_height)
915 height = maximum_height;
917 if (width > maximum_width)
918 width = maximum_width;
920 gtk_window_resize (GTK_WINDOW (table->dialog), width, height);
923 /* Properties dialog
924 *---------------------------------------------------------------------------*/
926 /* Display properties dialog. These dialogs are not modal, so a pointer on each
927 * dialog is kept with in node data to be able to destroy them if the node is
928 * removed. It is useful to put the dialog at the top if the same target is
929 * selected while the corresponding dialog already exist instead of creating
930 * two times the same dialog.
931 * The project properties dialog is display if the node iterator is NULL. */
933 gboolean
934 anjuta_pm_project_show_properties_dialog (ProjectManagerPlugin *plugin, GtkTreeIter *selected)
936 GtkWidget **dialog_ptr;
937 GtkTreeIter iter;
939 if (selected == NULL)
941 /* Display root properties by default */
942 if (gbf_project_view_get_project_root (plugin->view, &iter))
944 selected = &iter;
948 if (selected)
950 GbfTreeData *data;
952 gtk_tree_model_get (GTK_TREE_MODEL (gbf_project_view_get_model (plugin->view)), selected, GBF_PROJECT_MODEL_COLUMN_DATA, &data, -1);
953 dialog_ptr = &data->properties_dialog;
955 if (*dialog_ptr != NULL)
957 /* Show already existing dialog */
958 gtk_window_present (GTK_WINDOW (*dialog_ptr));
960 else
962 *dialog_ptr = pm_project_create_properties_dialog (
963 plugin->project,
964 GTK_WINDOW (plugin->project->plugin->shell),
965 plugin->view,
966 data,
967 selected);
968 if (*dialog_ptr != NULL)
970 g_object_add_weak_pointer (G_OBJECT (*dialog_ptr), (gpointer *)dialog_ptr);
975 return selected != NULL;
980 /* Group dialog
981 *---------------------------------------------------------------------------*/
983 AnjutaProjectNode*
984 anjuta_pm_project_new_group (ProjectManagerPlugin *plugin, GtkWindow *parent, GtkTreeIter *selected, const gchar *default_name)
986 GtkBuilder *gui;
987 GtkWidget *dialog, *group_name_entry, *ok_button;
988 GtkWidget *groups_view;
989 gint response;
990 gboolean finished = FALSE;
991 AnjutaProjectNode *new_group = NULL;
993 g_return_val_if_fail (plugin->project != NULL, NULL);
995 gui = load_interface ("new_group_dialog");
996 g_return_val_if_fail (gui != NULL, NULL);
998 /* get all needed widgets */
999 dialog = GTK_WIDGET (gtk_builder_get_object (gui, "new_group_dialog"));
1000 groups_view = GTK_WIDGET (gtk_builder_get_object (gui, "groups_view"));
1001 group_name_entry = GTK_WIDGET (gtk_builder_get_object (gui, "group_name_entry"));
1002 ok_button = GTK_WIDGET (gtk_builder_get_object (gui, "ok_group_button"));
1004 /* set up dialog */
1005 if (default_name)
1006 gtk_entry_set_text (GTK_ENTRY (group_name_entry),
1007 default_name);
1008 g_signal_connect (group_name_entry, "changed",
1009 (GCallback) entry_changed_cb, ok_button);
1010 if (default_name)
1011 gtk_widget_set_sensitive (ok_button, TRUE);
1012 else
1013 gtk_widget_set_sensitive (ok_button, FALSE);
1015 setup_nodes_treeview (GBF_PROJECT_VIEW (groups_view),
1016 plugin->view,
1017 NULL,
1018 parent_filter_func,
1019 GINT_TO_POINTER (ANJUTA_PROJECT_GROUP),
1020 selected);
1021 gtk_widget_show (groups_view);
1023 if (parent)
1025 gtk_window_set_transient_for (GTK_WINDOW (dialog), parent);
1028 /* execute dialog */
1029 while (!finished)
1031 response = gtk_dialog_run (GTK_DIALOG (dialog));
1033 switch (response) {
1034 case GTK_RESPONSE_OK:
1036 GError *err = NULL;
1037 AnjutaProjectNode *group;
1038 gchar *name;
1040 name = gtk_editable_get_chars (
1041 GTK_EDITABLE (group_name_entry), 0, -1);
1043 group = gbf_project_view_find_selected_state (GBF_PROJECT_VIEW (groups_view),
1044 ANJUTA_PROJECT_CAN_ADD_GROUP);
1045 if (group)
1047 new_group = anjuta_pm_project_add_group (plugin->project, group, NULL, name, &err);
1048 if (err)
1050 error_dialog (parent, _("Cannot add group"), "%s",
1051 err->message);
1052 g_error_free (err);
1054 else
1056 finished = TRUE;
1059 else
1061 error_dialog (parent, _("Cannot add group"),
1062 "%s", _("No parent group selected"));
1064 g_free (name);
1065 break;
1067 case GTK_RESPONSE_HELP:
1068 anjuta_util_help_display (GTK_WIDGET (dialog), ANJUTA_MANUAL, ADD_FOLDER_HELP);
1069 break;
1070 default:
1071 finished = TRUE;
1072 break;
1076 /* destroy stuff */
1077 gtk_widget_destroy (dialog);
1078 g_object_unref (gui);
1080 return new_group;
1083 /* Source dialog
1084 *---------------------------------------------------------------------------*/
1086 AnjutaProjectNode*
1087 anjuta_pm_project_new_source (ProjectManagerPlugin *plugin,
1088 GtkWindow *parent,
1089 GtkTreeIter *default_parent,
1090 const gchar *default_uri)
1092 GList* new_sources;
1093 gchar* uri = NULL;
1094 GList* uris = NULL;
1096 if (default_uri)
1098 uri = g_strdup (default_uri);
1099 uris = g_list_append (NULL, uri);
1101 new_sources =
1102 anjuta_pm_project_new_multiple_source (plugin, parent,
1103 default_parent, uris);
1104 g_free (uri);
1105 g_list_free (uris);
1107 if (new_sources && g_list_length (new_sources))
1109 AnjutaProjectNode *new_source = new_sources->data;
1110 g_list_free (new_sources);
1111 return new_source;
1113 else
1114 return NULL;
1117 static void
1118 on_target_changed (GtkWidget *chooser, GtkWidget *button)
1120 GFile *file;
1122 file = ianjuta_project_chooser_get_selected (IANJUTA_PROJECT_CHOOSER (chooser), NULL);
1123 gtk_widget_set_sensitive (button, file != NULL);
1126 GList*
1127 anjuta_pm_add_source_dialog (ProjectManagerPlugin *plugin,
1128 GtkWindow *top_window,
1129 GtkTreeIter *default_target,
1130 GFile *default_source)
1132 GtkBuilder *gui;
1133 GtkWidget *dialog;
1134 GtkWidget *ok_button;
1135 GtkWidget *target_chooser;
1136 GtkWidget *source_chooser;
1137 gint response;
1138 gboolean finished = FALSE;
1139 GList *sources = NULL;
1141 g_return_val_if_fail (plugin->project != NULL, NULL);
1143 gui = load_interface ("add_source_dialog");
1144 g_return_val_if_fail (gui != NULL, NULL);
1146 /* get all needed widgets */
1147 dialog = GTK_WIDGET (gtk_builder_get_object (gui, "add_source_dialog"));
1148 target_chooser = GTK_WIDGET (gtk_builder_get_object (gui, "target_chooser"));
1149 source_chooser = GTK_WIDGET (gtk_builder_get_object (gui, "source_chooser"));
1150 ok_button = GTK_WIDGET (gtk_builder_get_object (gui, "ok_add_source_button"));
1152 /* Fill target selection */
1153 ianjuta_project_chooser_set_project_model (IANJUTA_PROJECT_CHOOSER (target_chooser),
1154 IANJUTA_PROJECT_MANAGER (plugin),
1155 ANJUTA_PROJECT_SOURCE,
1156 NULL);
1157 if (default_target != NULL)
1159 GtkTreeIter iter;
1160 if (pm_convert_project_iter_to_model_iter (GTK_TREE_MODEL (anjuta_tree_combo_box_get_model (ANJUTA_TREE_COMBO_BOX (target_chooser))),
1161 &iter, default_target))
1163 anjuta_tree_combo_box_set_active_iter (ANJUTA_TREE_COMBO_BOX (target_chooser), &iter);
1166 g_signal_connect (target_chooser, "changed",
1167 G_CALLBACK (on_target_changed),
1168 ok_button);
1169 on_target_changed (target_chooser, ok_button);
1171 /* Selected default file */
1172 if (default_source != NULL) gtk_file_chooser_set_file (GTK_FILE_CHOOSER (source_chooser), default_source, NULL);
1174 if (top_window) {
1175 gtk_window_set_transient_for (GTK_WINDOW (dialog), top_window);
1178 /* execute dialog */
1179 while (!finished) {
1180 response = gtk_dialog_run (GTK_DIALOG (dialog));
1182 switch (response)
1184 case GTK_RESPONSE_OK:
1186 GFile *target_file;
1187 AnjutaProjectNode *target;
1188 GSList *files;
1190 target_file = ianjuta_project_chooser_get_selected (IANJUTA_PROJECT_CHOOSER (target_chooser), NULL);
1191 target = gbf_project_view_get_node_from_file (plugin->view, ANJUTA_PROJECT_UNKNOWN, target_file);
1192 files = gtk_file_chooser_get_files (GTK_FILE_CHOOSER (source_chooser));
1193 if ((target != NULL) && (files != NULL))
1195 GString *err_mesg = g_string_new (NULL);
1196 GSList *item;
1198 for (item = files; item != NULL; item = g_slist_next (item))
1200 gchar *path = g_file_get_path ((GFile *)item->data);
1201 GError *err = NULL;
1202 AnjutaProjectNode *node;
1204 node = anjuta_pm_project_add_source (plugin->project,
1205 target,
1206 NULL,
1207 path,
1208 &err);
1209 sources = g_list_prepend (sources, node);
1210 if (err) {
1211 gchar *str = g_strdup_printf ("%s: %s\n",
1212 path,
1213 err->message);
1214 g_string_append (err_mesg, str);
1215 g_error_free (err);
1216 g_free (str);
1218 g_free (path);
1220 if (err_mesg->str && strlen (err_mesg->str) > 0)
1222 error_dialog (top_window, _("Cannot add source files"),
1223 "%s", err_mesg->str);
1225 else {
1226 finished = TRUE;
1228 g_string_free (err_mesg, TRUE);
1229 g_slist_foreach (files, (GFunc)g_object_unref, NULL);
1230 g_slist_free (files);
1232 else
1234 error_dialog (top_window, _("Cannot add source files"),
1235 "%s", _("The selected node cannot contain source files."));
1237 break;
1239 case GTK_RESPONSE_HELP:
1240 anjuta_util_help_display (GTK_WIDGET (dialog), ANJUTA_MANUAL, ADD_SOURCE_HELP);
1241 break;
1242 default:
1243 finished = TRUE;
1244 break;
1248 /* destroy stuff */
1249 gtk_widget_destroy (dialog);
1250 g_object_unref (gui);
1252 sources = g_list_reverse (sources);
1253 return sources;
1257 GList*
1258 anjuta_pm_project_new_multiple_source (ProjectManagerPlugin *plugin,
1259 GtkWindow *top_window,
1260 GtkTreeIter *default_parent,
1261 GList *uris_to_add)
1263 GtkBuilder *gui;
1264 GtkWidget *dialog, *source_file_tree;
1265 GtkWidget *ok_button, *browse_button;
1266 GtkWidget *targets_view;
1267 gint response;
1268 gboolean finished = FALSE;
1269 GtkListStore* list;
1270 GtkCellRenderer* renderer;
1271 GtkTreeViewColumn* column_filename;
1272 GList* new_sources = NULL;
1273 GList* uri_node;
1274 GtkTreePath *root;
1276 g_return_val_if_fail (plugin->project != NULL, NULL);
1278 gui = load_interface ("new_source_dialog");
1279 g_return_val_if_fail (gui != NULL, NULL);
1281 /* get all needed widgets */
1282 dialog = GTK_WIDGET (gtk_builder_get_object (gui, "new_source_dialog"));
1283 targets_view = GTK_WIDGET (gtk_builder_get_object (gui, "targets_view"));
1284 source_file_tree = GTK_WIDGET (gtk_builder_get_object (gui, "source_file_tree"));
1285 browse_button = GTK_WIDGET (gtk_builder_get_object (gui, "browse_button"));
1286 ok_button = GTK_WIDGET (gtk_builder_get_object (gui, "ok_source_button"));
1288 /* Prepare file tree */
1289 list = gtk_list_store_new (N_COLUMNS, G_TYPE_STRING, G_TYPE_STRING);
1290 gtk_tree_view_set_model (GTK_TREE_VIEW (source_file_tree),
1291 GTK_TREE_MODEL (list));
1292 renderer = gtk_cell_renderer_text_new ();
1293 column_filename = gtk_tree_view_column_new_with_attributes ("Files",
1294 renderer,
1295 "text",
1296 COLUMN_FILE,
1297 NULL);
1298 gtk_tree_view_column_set_sizing (column_filename,
1299 GTK_TREE_VIEW_COLUMN_FIXED);
1300 gtk_tree_view_append_column (GTK_TREE_VIEW (source_file_tree),
1301 column_filename);
1303 /* set up dialog */
1304 uri_node = uris_to_add;
1305 while (uri_node)
1307 GtkTreeIter iter;
1308 gchar* filename = g_path_get_basename (uri_node->data);
1309 if (!filename)
1310 filename = g_strdup (uri_node->data);
1311 gtk_list_store_append (list, &iter);
1312 gtk_list_store_set (list, &iter, COLUMN_FILE, filename,
1313 COLUMN_URI, g_strdup(uri_node->data), -1);
1314 g_free (filename);
1315 uri_node = g_list_next (uri_node);
1317 if (!g_list_length (uris_to_add))
1318 gtk_widget_set_sensitive (ok_button, FALSE);
1319 else
1320 gtk_widget_set_sensitive (ok_button, TRUE);
1322 g_signal_connect (G_OBJECT(list), "row_changed",
1323 G_CALLBACK(on_row_changed), ok_button);
1325 g_signal_connect (browse_button, "clicked",
1326 G_CALLBACK (browse_button_clicked_cb), source_file_tree);
1328 g_object_set_data_full (G_OBJECT (browse_button), "treeview", targets_view, NULL);
1329 /*project_root = g_file_get_uri (anjuta_project_node_get_file (anjuta_pm_project_get_root (project)));
1330 g_object_set_data_full (G_OBJECT (browse_button), "root", project_root, g_free);*/
1332 root = gbf_project_model_get_project_root (gbf_project_view_get_model (plugin->view));
1333 setup_nodes_treeview (GBF_PROJECT_VIEW (targets_view),
1334 plugin->view,
1335 root,
1336 parent_filter_func,
1337 GINT_TO_POINTER (ANJUTA_PROJECT_SOURCE),
1338 default_parent);
1339 gtk_tree_path_free (root);
1340 gtk_widget_show (targets_view);
1342 if (top_window) {
1343 gtk_window_set_transient_for (GTK_WINDOW (dialog), top_window);
1346 if (default_parent)
1347 gtk_widget_grab_focus (source_file_tree);
1348 else
1349 gtk_widget_grab_focus (targets_view);
1351 /* execute dialog */
1352 while (!finished) {
1353 response = gtk_dialog_run (GTK_DIALOG (dialog));
1355 switch (response)
1357 case GTK_RESPONSE_OK:
1359 AnjutaProjectNode *parent = NULL;
1360 AnjutaProjectNode *sibling = NULL;
1362 parent = gbf_project_view_find_selected (GBF_PROJECT_VIEW (targets_view),
1363 ANJUTA_PROJECT_UNKNOWN);
1365 /* Check that selected node can be used as a parent or a sibling */
1366 if (parent)
1368 if (!(anjuta_project_node_get_state (parent) & ANJUTA_PROJECT_CAN_ADD_SOURCE))
1370 sibling = parent;
1371 parent = anjuta_project_node_parent (parent);
1373 if (!(anjuta_project_node_get_state (parent) & ANJUTA_PROJECT_CAN_ADD_SOURCE))
1375 parent = NULL;
1379 if (parent)
1381 GtkTreeIter iter;
1382 GString *err_mesg = g_string_new (NULL);
1384 if (!gtk_tree_model_get_iter_first (GTK_TREE_MODEL (list),
1385 &iter))
1386 break;
1389 GError *err = NULL;
1390 AnjutaProjectNode* new_source;
1391 gchar* uri;
1393 gtk_tree_model_get (GTK_TREE_MODEL(list), &iter,
1394 COLUMN_URI, &uri, -1);
1396 new_source = anjuta_pm_project_add_source (plugin->project,
1397 parent,
1398 sibling,
1399 uri,
1400 &err);
1401 if (err) {
1402 gchar *str = g_strdup_printf ("%s: %s\n",
1403 uri,
1404 err->message);
1405 g_string_append (err_mesg, str);
1406 g_error_free (err);
1407 g_free (str);
1409 else
1410 new_sources = g_list_append (new_sources,
1411 new_source);
1413 g_free (uri);
1414 } while (gtk_tree_model_iter_next (GTK_TREE_MODEL(list),
1415 &iter));
1417 if (err_mesg->str && strlen (err_mesg->str) > 0)
1419 error_dialog (top_window, _("Cannot add source files"),
1420 "%s", err_mesg->str);
1422 else {
1423 finished = TRUE;
1425 g_string_free (err_mesg, TRUE);
1427 else
1429 error_dialog (top_window, _("Cannot add source files"),
1430 "%s", _("The selected node cannot contain source files."));
1432 break;
1434 case GTK_RESPONSE_HELP:
1435 anjuta_util_help_display (GTK_WIDGET (dialog), ANJUTA_MANUAL, ADD_SOURCE_HELP);
1436 break;
1437 default:
1438 gtk_list_store_clear (GTK_LIST_STORE (list));
1439 finished = TRUE;
1440 break;
1444 /* destroy stuff */
1445 gtk_widget_destroy (dialog);
1446 g_object_unref (gui);
1448 return new_sources;
1451 /* Target dialog
1452 *---------------------------------------------------------------------------*/
1454 enum {
1455 TARGET_TYPE_TYPE = 0,
1456 TARGET_TYPE_NAME,
1457 TARGET_TYPE_PIXBUF,
1458 TARGET_TYPE_N_COLUMNS
1461 /* create a tree model with the target types */
1462 static GtkListStore *
1463 build_types_store (AnjutaPmProject *project, AnjutaProjectNodeType store_type)
1465 GtkListStore *store;
1466 GtkTreeIter iter;
1467 const GList *types;
1468 const GList *node;
1470 types = anjuta_pm_project_get_node_info (project);
1471 store = gtk_list_store_new (TARGET_TYPE_N_COLUMNS,
1472 G_TYPE_POINTER,
1473 G_TYPE_STRING,
1474 GDK_TYPE_PIXBUF);
1476 for (node = types; node != NULL; node = g_list_next (node)) {
1477 GdkPixbuf *pixbuf;
1478 const gchar *name;
1479 AnjutaProjectNodeType type;
1481 type = anjuta_project_node_info_type ((AnjutaProjectNodeInfo *)node->data);
1482 if (((store_type == 0) || ((type & ANJUTA_PROJECT_TYPE_MASK) == store_type)) && !(type & ANJUTA_PROJECT_READ_ONLY))
1484 name = anjuta_project_node_info_name ((AnjutaProjectNodeInfo *)node->data);
1485 pixbuf = gtk_icon_theme_load_icon (gtk_icon_theme_get_default(),
1486 GTK_STOCK_CONVERT,
1487 ICON_SIZE,
1488 GTK_ICON_LOOKUP_GENERIC_FALLBACK,
1489 NULL);
1491 gtk_list_store_append (store, &iter);
1492 gtk_list_store_set (store, &iter,
1493 TARGET_TYPE_TYPE, type,
1494 TARGET_TYPE_NAME, name,
1495 TARGET_TYPE_PIXBUF, pixbuf,
1496 -1);
1498 if (pixbuf)
1499 g_object_unref (pixbuf);
1503 return store;
1506 AnjutaProjectNode*
1507 anjuta_pm_project_new_target (ProjectManagerPlugin *plugin,
1508 GtkWindow *parent,
1509 GtkTreeIter *default_group,
1510 const gchar *default_target_name_to_add)
1512 GtkBuilder *gui;
1513 GtkWidget *dialog, *target_name_entry, *ok_button;
1514 GtkWidget *target_type_combo, *groups_view;
1515 GtkListStore *types_store;
1516 GtkCellRenderer *renderer;
1517 gint response;
1518 gboolean finished = FALSE;
1519 AnjutaProjectNode *new_target = NULL;
1521 g_return_val_if_fail (plugin->project != NULL, NULL);
1523 gui = load_interface ("new_target_dialog");
1524 g_return_val_if_fail (gui != NULL, NULL);
1526 /* get all needed widgets */
1527 dialog = GTK_WIDGET (gtk_builder_get_object (gui, "new_target_dialog"));
1528 groups_view = GTK_WIDGET (gtk_builder_get_object (gui, "target_groups_view"));
1529 target_name_entry = GTK_WIDGET (gtk_builder_get_object (gui, "target_name_entry"));
1530 target_type_combo = GTK_WIDGET (gtk_builder_get_object (gui, "target_type_combo"));
1531 ok_button = GTK_WIDGET (gtk_builder_get_object (gui, "ok_target_button"));
1533 /* set up dialog */
1534 if (default_target_name_to_add)
1535 gtk_entry_set_text (GTK_ENTRY (target_name_entry),
1536 default_target_name_to_add);
1537 g_signal_connect (target_name_entry, "changed",
1538 (GCallback) entry_changed_cb, ok_button);
1539 if (default_target_name_to_add)
1540 gtk_widget_set_sensitive (ok_button, TRUE);
1541 else
1542 gtk_widget_set_sensitive (ok_button, FALSE);
1544 setup_nodes_treeview (GBF_PROJECT_VIEW (groups_view),
1545 plugin->view,
1546 NULL,
1547 parent_filter_func,
1548 GINT_TO_POINTER (ANJUTA_PROJECT_TARGET),
1549 default_group);
1550 gtk_widget_show (groups_view);
1552 /* setup target types combo box */
1553 types_store = build_types_store (plugin->project, ANJUTA_PROJECT_TARGET);
1554 gtk_combo_box_set_model (GTK_COMBO_BOX (target_type_combo),
1555 GTK_TREE_MODEL (types_store));
1557 /* create cell renderers */
1558 renderer = gtk_cell_renderer_pixbuf_new ();
1559 gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (target_type_combo),
1560 renderer, FALSE);
1561 gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (target_type_combo),
1562 renderer,
1563 "pixbuf", TARGET_TYPE_PIXBUF,
1564 NULL);
1566 renderer = gtk_cell_renderer_text_new ();
1567 gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (target_type_combo),
1568 renderer, TRUE);
1569 gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (target_type_combo),
1570 renderer,
1571 "text", TARGET_TYPE_NAME,
1572 NULL);
1573 gtk_widget_show (target_type_combo);
1575 /* preselect */
1576 gtk_combo_box_set_active (GTK_COMBO_BOX (target_type_combo), 0);
1578 if (parent)
1580 gtk_window_set_transient_for (GTK_WINDOW (dialog), parent);
1583 /* execute dialog */
1584 while (!finished)
1586 response = gtk_dialog_run (GTK_DIALOG (dialog));
1588 switch (response)
1590 case GTK_RESPONSE_OK:
1592 GError *err = NULL;
1593 AnjutaProjectNode *group;
1594 GtkTreeIter iter;
1595 gchar *name;
1596 AnjutaProjectNodeType type;
1598 name = gtk_editable_get_chars (
1599 GTK_EDITABLE (target_name_entry), 0, -1);
1600 group = gbf_project_view_find_selected (GBF_PROJECT_VIEW (groups_view),
1601 ANJUTA_PROJECT_GROUP);
1603 /* retrieve target type */
1604 if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (target_type_combo), &iter))
1606 gtk_tree_model_get (GTK_TREE_MODEL (types_store), &iter,
1607 TARGET_TYPE_TYPE, &type,
1608 -1);
1611 if (group && type)
1613 new_target = anjuta_pm_project_add_target (plugin->project, group, NULL, name, type, &err);
1614 if (err)
1616 error_dialog (parent, _("Cannot add target"), "%s",
1617 err->message);
1618 g_error_free (err);
1620 else
1622 finished = TRUE;
1625 else
1627 error_dialog (parent, _("Cannot add target"), "%s",
1628 _("No group selected"));
1631 g_free (name);
1633 break;
1635 case GTK_RESPONSE_HELP:
1636 anjuta_util_help_display (GTK_WIDGET (dialog), ANJUTA_MANUAL, ADD_TARGET_HELP);
1637 break;
1638 default:
1639 finished = TRUE;
1640 break;
1644 /* destroy stuff */
1645 g_object_unref (types_store);
1646 gtk_widget_destroy (dialog);
1647 g_object_unref (gui);
1649 return new_target;
1653 /* Module dialog
1654 *---------------------------------------------------------------------------*/
1656 static void
1657 on_cursor_changed(GtkTreeView* view, gpointer data)
1659 GtkWidget* button = GTK_WIDGET(data);
1660 GtkTreeSelection *selection = gtk_tree_view_get_selection(view);
1662 if (gtk_tree_selection_count_selected_rows (selection) > 0)
1663 gtk_widget_set_sensitive(button, TRUE);
1664 else
1665 gtk_widget_set_sensitive(button, FALSE);
1668 static void
1669 on_new_library(GtkButton *button, gpointer user_data)
1671 ProjectManagerPlugin *plugin = ANJUTA_PLUGIN_PROJECT_MANAGER (user_data);
1672 anjuta_pm_project_new_package (plugin,
1673 get_plugin_parent_window (plugin),
1674 NULL,
1675 NULL);
1678 GList*
1679 anjuta_pm_project_new_module (ProjectManagerPlugin *plugin,
1680 GtkWindow *parent,
1681 GtkTreeIter *default_target,
1682 const gchar *default_module)
1684 GtkBuilder *gui;
1685 GtkWidget *dialog;
1686 GtkWidget *ok_button, *new_button;
1687 GtkWidget *target_chooser;
1688 GtkWidget *modules_view;
1689 GtkTreePath *root;
1690 gint response;
1691 gboolean finished = FALSE;
1692 GList* new_modules = NULL;
1693 GtkTreeSelection *module_selection;
1695 g_return_val_if_fail (plugin->project != NULL, NULL);
1697 gui = load_interface ("add_module_dialog");
1698 g_return_val_if_fail (gui != NULL, NULL);
1700 /* get all needed widgets */
1701 dialog = GTK_WIDGET (gtk_builder_get_object (gui, "add_module_dialog"));
1702 target_chooser = GTK_WIDGET (gtk_builder_get_object (gui, "module_targets_chooser"));
1703 modules_view = GTK_WIDGET (gtk_builder_get_object (gui, "modules_view"));
1704 new_button = GTK_WIDGET (gtk_builder_get_object (gui, "new_package_button"));
1705 ok_button = GTK_WIDGET (gtk_builder_get_object (gui, "ok_module_button"));
1707 /* Fill target selection */
1708 ianjuta_project_chooser_set_project_model (IANJUTA_PROJECT_CHOOSER (target_chooser),
1709 IANJUTA_PROJECT_MANAGER (plugin),
1710 ANJUTA_PROJECT_MODULE,
1711 NULL);
1712 gtk_widget_show (target_chooser);
1713 root = gbf_project_model_get_project_root (gbf_project_view_get_model (plugin->view));
1714 setup_nodes_treeview (GBF_PROJECT_VIEW (modules_view),
1715 plugin->view,
1716 root,
1717 module_filter_func,
1718 NULL,
1719 NULL);
1720 gtk_tree_path_free (root);
1721 gtk_widget_show (modules_view);
1722 module_selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (modules_view));
1723 gtk_tree_selection_set_mode (module_selection, GTK_SELECTION_MULTIPLE);
1725 if (gbf_project_view_find_selected (GBF_PROJECT_VIEW (modules_view), ANJUTA_PROJECT_MODULE))
1727 gtk_widget_set_sensitive (ok_button, TRUE);
1729 else
1731 gtk_widget_set_sensitive (ok_button, FALSE);
1733 g_signal_connect (G_OBJECT(modules_view), "cursor-changed",
1734 G_CALLBACK(on_cursor_changed), ok_button);
1735 g_signal_connect (G_OBJECT(new_button), "clicked",
1736 G_CALLBACK(on_new_library), plugin);
1739 if (parent)
1741 gtk_window_set_transient_for (GTK_WINDOW (dialog), parent);
1744 gtk_widget_grab_focus (modules_view);
1746 /* execute dialog */
1747 while (!finished)
1749 response = gtk_dialog_run (GTK_DIALOG (dialog));
1751 switch (response) {
1752 case GTK_RESPONSE_OK:
1754 GFile *target_file;
1755 AnjutaProjectNode *target;
1757 target_file = ianjuta_project_chooser_get_selected (IANJUTA_PROJECT_CHOOSER (target_chooser), NULL);
1758 target = gbf_project_view_get_node_from_file (plugin->view, ANJUTA_PROJECT_UNKNOWN, target_file);
1759 if (target)
1761 GString *err_mesg = g_string_new (NULL);
1762 GList *list;
1763 GList *node;
1765 list = gbf_project_view_get_all_selected (GBF_PROJECT_VIEW (modules_view));
1766 for (node = g_list_first (list); node != NULL; node = g_list_next (node))
1768 GError *error = NULL;
1769 AnjutaProjectNode* new_module;
1770 const gchar *name;
1772 new_module = gbf_tree_data_get_node (node->data);
1773 name = anjuta_project_node_get_name (new_module);
1775 new_module = ianjuta_project_add_node_after (plugin->project->project, target, NULL, ANJUTA_PROJECT_MODULE, NULL, name, &error);
1776 if (error) {
1777 gchar *str = g_strdup_printf ("%s: %s\n",
1778 name,
1779 error->message);
1780 g_string_append (err_mesg, str);
1781 g_error_free (error);
1782 g_free (str);
1784 else
1785 new_modules = g_list_append (new_modules, new_module);
1787 g_list_free (list);
1789 if (err_mesg->str && strlen (err_mesg->str) > 0)
1791 error_dialog (parent, _("Cannot add modules"),
1792 "%s", err_mesg->str);
1794 else
1796 finished = TRUE;
1798 g_string_free (err_mesg, TRUE);
1800 else
1802 error_dialog (parent, _("Cannot add modules"),
1803 "%s", _("No target has been selected"));
1806 break;
1808 case GTK_RESPONSE_HELP:
1809 anjuta_util_help_display (GTK_WIDGET (dialog), ANJUTA_MANUAL, ADD_MODULE_HELP);
1810 break;
1811 default:
1812 finished = TRUE;
1813 break;
1817 /* destroy stuff */
1818 gtk_widget_destroy (dialog);
1819 g_object_unref (gui);
1821 return new_modules;
1824 /* Package dialog
1825 *---------------------------------------------------------------------------*/
1827 static void on_changed_disconnect (GtkEditable* entry, gpointer data);
1829 static void
1830 on_cursor_changed_set_entry(GtkTreeView* view, gpointer data)
1832 GtkWidget* entry = GTK_WIDGET(data);
1833 AnjutaPkgConfigChooser* chooser = ANJUTA_PKG_CONFIG_CHOOSER (view);
1834 GList* packages = anjuta_pkg_config_chooser_get_active_packages (chooser);
1836 if (packages)
1838 gchar* name = packages->data;
1839 gchar* ptr;
1840 /* Remove numeric suffix */
1841 ptr = name + strlen(name) - 1;
1842 while (g_ascii_isdigit (*ptr))
1844 while (g_ascii_isdigit (*ptr)) ptr--;
1845 if ((*ptr != '_') && (*ptr != '-') && (*ptr != '.')) break;
1846 *ptr = '\0';
1847 ptr--;
1850 /* Convert to upper case and remove invalid characters */
1851 for (ptr = name; *ptr != '\0'; ptr++)
1853 if (g_ascii_isalnum (*ptr))
1855 *ptr = g_ascii_toupper (*ptr);
1857 else
1859 *ptr = '_';
1863 g_signal_handlers_block_by_func (G_OBJECT (entry), on_changed_disconnect, view);
1864 gtk_entry_set_text (GTK_ENTRY (entry), name);
1865 g_signal_handlers_unblock_by_func (G_OBJECT (entry), on_changed_disconnect, view);
1866 anjuta_util_glist_strings_free (packages);
1870 static void
1871 on_changed_disconnect (GtkEditable* entry, gpointer data)
1873 g_signal_handlers_block_by_func (G_OBJECT (data), on_cursor_changed_set_entry, entry);
1876 static void
1877 on_pkg_chooser_selection_changed (AnjutaPkgConfigChooser* chooser,
1878 gchar* package,
1879 gpointer data)
1881 GtkWidget* button = GTK_WIDGET(data);
1882 GList* packages = anjuta_pkg_config_chooser_get_active_packages (chooser);
1884 if (packages != NULL)
1885 gtk_widget_set_sensitive(button, TRUE);
1886 else
1887 gtk_widget_set_sensitive(button, FALSE);
1889 anjuta_util_glist_strings_free (packages);
1892 GList*
1893 anjuta_pm_project_new_package (ProjectManagerPlugin *plugin,
1894 GtkWindow *parent,
1895 GtkTreeIter *default_module,
1896 GList *packages_to_add)
1898 GtkBuilder *gui;
1899 GtkWidget *dialog;
1900 GtkWidget *ok_button;
1901 GtkWidget *module_entry;
1902 GtkWidget *packages_view;
1903 GList *packages = NULL;
1904 gint response;
1905 gboolean finished = FALSE;
1906 GtkListStore *store;
1907 AnjutaProjectNode *root;
1908 AnjutaProjectNode *node;
1909 AnjutaProjectNode *module = NULL;
1910 gint default_pos = -1;
1911 gint pos;
1913 g_return_val_if_fail (plugin->project != NULL, NULL);
1915 gui = load_interface ("add_package_dialog");
1916 g_return_val_if_fail (gui != NULL, NULL);
1918 /* get all needed widgets */
1919 dialog = GTK_WIDGET (gtk_builder_get_object (gui, "add_package_dialog"));
1920 module_entry = GTK_WIDGET (gtk_builder_get_object (gui, "module_entry"));
1921 packages_view = GTK_WIDGET (gtk_builder_get_object (gui, "packages_view"));
1922 ok_button = GTK_WIDGET (gtk_builder_get_object (gui, "ok_package_button"));
1924 /* Get default parent */
1925 if (default_module != NULL)
1927 GbfTreeData *data;
1928 GbfProjectModel *model;
1930 model = gbf_project_view_get_model(plugin->view);
1931 gtk_tree_model_get (GTK_TREE_MODEL (model), default_module, GBF_PROJECT_MODEL_COLUMN_DATA, &data, -1);
1932 if (data != NULL)
1934 module = gbf_tree_data_get_node (data);
1938 /* Fill combo box with modules */
1939 store = gtk_list_store_new(1, G_TYPE_STRING);
1940 gtk_combo_box_set_entry_text_column (GTK_COMBO_BOX (module_entry), 0);
1942 root = ianjuta_project_get_root (plugin->project->project, NULL);
1943 pos = 0;
1944 for (node = anjuta_project_node_first_child (root); node != NULL; node = anjuta_project_node_next_sibling (node))
1946 if (anjuta_project_node_get_node_type (node) == ANJUTA_PROJECT_MODULE)
1948 GtkTreeIter list_iter;
1949 const gchar *name;
1951 name = anjuta_project_node_get_name (node);
1952 gtk_list_store_append (store, &list_iter);
1953 gtk_list_store_set (store, &list_iter, 0, name, -1);
1955 if (node == module)
1957 default_pos = pos;
1959 pos ++;
1962 gtk_combo_box_set_model (GTK_COMBO_BOX(module_entry), GTK_TREE_MODEL(store));
1963 gtk_combo_box_set_entry_text_column (GTK_COMBO_BOX (module_entry), 0);
1964 g_object_unref (store);
1965 if (default_pos >= 0)
1967 gtk_combo_box_set_active (GTK_COMBO_BOX (module_entry), default_pos);
1969 else
1971 /* Create automatically a module name from the package name when missing */
1972 GtkWidget *entry = gtk_bin_get_child (GTK_BIN (module_entry));
1974 g_signal_connect (G_OBJECT(packages_view), "cursor-changed",
1975 G_CALLBACK(on_cursor_changed_set_entry), entry);
1976 g_signal_connect (G_OBJECT(entry), "changed",
1977 G_CALLBACK(on_changed_disconnect), packages_view);
1980 /* Fill package list */
1981 anjuta_pkg_config_chooser_show_active_column (ANJUTA_PKG_CONFIG_CHOOSER (packages_view),
1982 TRUE);
1983 g_signal_connect (G_OBJECT(packages_view), "package-activated",
1984 G_CALLBACK(on_pkg_chooser_selection_changed), ok_button);
1985 g_signal_connect (G_OBJECT(packages_view), "package-deactivated",
1986 G_CALLBACK(on_pkg_chooser_selection_changed), ok_button);
1988 if (parent) {
1989 gtk_window_set_transient_for (GTK_WINDOW (dialog), parent);
1992 /* execute dialog */
1993 while (!finished) {
1994 response = gtk_dialog_run (GTK_DIALOG (dialog));
1996 switch (response) {
1997 case GTK_RESPONSE_OK:
1999 gchar *name;
2000 AnjutaProjectNode *module = NULL;
2001 GString *error_message = g_string_new (NULL);
2003 name = g_strdup (gtk_entry_get_text (GTK_ENTRY (gtk_bin_get_child (GTK_BIN (module_entry)))));
2004 if (name != NULL) name = g_strstrip (name);
2006 if ((name == NULL) || (*name == '\0'))
2008 /* Missing module name */
2009 g_string_append (error_message, _("Missing module name"));
2011 else
2013 /* Look for already existing module */
2014 module = anjuta_pm_project_get_module (plugin->project, name);
2015 if (module == NULL)
2017 /* Create new module */
2018 AnjutaProjectNode *root;
2019 GError *error = NULL;
2021 root = ianjuta_project_get_root (plugin->project->project, NULL);
2023 module = ianjuta_project_add_node_after (plugin->project->project, root, NULL, ANJUTA_PROJECT_MODULE, NULL, name, &error);
2024 if (error != NULL)
2026 gchar *str = g_strdup_printf ("%s: %s\n", name, error->message);
2028 g_string_append (error_message, str);
2029 g_error_free (error);
2030 g_free (str);
2034 g_free (name);
2036 if (module != NULL)
2038 GList *list;
2039 GList *node;
2041 list = anjuta_pkg_config_chooser_get_active_packages (ANJUTA_PKG_CONFIG_CHOOSER (packages_view));
2042 for (node = list; node != NULL; node = g_list_next (node))
2044 gchar *name;
2045 AnjutaProjectNode* new_package;
2046 GError *error = NULL;
2048 name = node->data;
2050 new_package = ianjuta_project_add_node_after (plugin->project->project, module, NULL, ANJUTA_PROJECT_PACKAGE, NULL, name, &error);
2051 if (error)
2053 gchar *str = g_strdup_printf ("%s: %s\n",
2054 name,
2055 error->message);
2056 g_string_append (error_message, str);
2057 g_error_free (error);
2058 g_free (str);
2060 else
2062 packages = g_list_append (packages, new_package);
2063 finished = TRUE;
2066 anjuta_util_glist_strings_free (list);
2069 if (error_message->len != 0)
2071 error_dialog (parent, _("Cannot add packages"),
2072 "%s",error_message->str);
2074 else
2076 finished = TRUE;
2078 g_string_free (error_message, TRUE);
2079 break;
2081 case GTK_RESPONSE_HELP:
2082 anjuta_util_help_display (GTK_WIDGET (dialog), ANJUTA_MANUAL, ADD_PACKAGE_HELP);
2083 break;
2084 default:
2085 finished = TRUE;
2086 break;
2090 /* destroy stuff */
2091 gtk_widget_destroy (dialog);
2092 g_object_unref (gui);
2094 return packages;