project-manager: bgo #534966 - Order alphabetically project's targets on project tab
[anjuta.git] / plugins / project-manager / project-view.c
bloba33150302698ae6314ae58e1372c2a030725b871
1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8; coding: utf-8 -*- */
2 /* project-tree.c
4 * Copyright (C) 2000 JP Rosevear
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., 51 Franklin Street, Fifth Floor,
19 * Boston, MA 02110-1301, USA.
21 * Authors: JP Rosevear
22 * Gustavo Giráldez <gustavo.giraldez@gmx.net>
27 #ifdef HAVE_CONFIG_H
28 #include <config.h>
29 #endif
31 #include <glib/gi18n.h>
32 #include <gdk/gdk.h>
33 #include <gtk/gtk.h>
34 #include <gio/gio.h>
35 #include <string.h>
37 #include "tree-data.h"
38 #include "project-model.h"
39 #include "project-view.h"
40 #include "project-marshal.h"
41 #include "project-util.h"
43 #define ICON_SIZE 16
45 enum {
46 URI_ACTIVATED,
47 TARGET_SELECTED,
48 GROUP_SELECTED,
49 NODE_LOADED,
50 LAST_SIGNAL
53 static guint signals [LAST_SIGNAL] = { 0 };
55 /* Project model filter with drag and drop support
56 *---------------------------------------------------------------------------*/
58 typedef struct {
59 GtkTreeModelFilter parent;
60 } PmProjectModelFilter;
62 typedef struct {
63 GtkTreeModelFilterClass parent_class;
64 } PmProjectModelFilterClass;
66 #define PM_TYPE_PROJECT_MODEL_FILTER (pm_project_model_filter_get_type ())
67 #define PM_PROJECT_MODEL_FILTER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), PM_TYPE_PROJECT_MODEL_FILTER, PmProjectModelFilter))
70 static void
71 pm_project_model_filter_class_init (PmProjectModelFilterClass *class)
75 static void
76 pm_project_model_filter_init (PmProjectModelFilter *model)
80 static gboolean
81 idrag_source_row_draggable (GtkTreeDragSource *drag_source, GtkTreePath *path)
83 GtkTreeIter iter;
84 GbfTreeData *data;
85 gboolean retval = FALSE;
87 if (!gtk_tree_model_get_iter (GTK_TREE_MODEL (drag_source), &iter, path))
88 return FALSE;
90 gtk_tree_model_get (GTK_TREE_MODEL (drag_source), &iter,
91 GBF_PROJECT_MODEL_COLUMN_DATA, &data,
92 -1);
94 if (data->is_shortcut) {
95 /* shortcuts can be moved */
96 retval = TRUE;
98 } else if (data->type == GBF_TREE_NODE_TARGET) {
99 /* don't allow duplicate shortcuts */
100 if (data->shortcut == NULL)
101 retval = TRUE;
104 return retval;
107 static gboolean
108 idrag_source_drag_data_delete (GtkTreeDragSource *drag_source, GtkTreePath *path)
110 return FALSE;
113 static gboolean
114 idrag_dest_drag_data_received (GtkTreeDragDest *drag_dest,
115 GtkTreePath *dest,
116 GtkSelectionData *selection_data)
118 GtkTreeModel *src_model = NULL;
119 GtkTreePath *src_path = NULL;
120 GtkTreeModel *project_model;
121 gboolean retval = FALSE;
123 if (GTK_IS_TREE_MODEL_FILTER (drag_dest))
125 project_model = gtk_tree_model_filter_get_model (GTK_TREE_MODEL_FILTER (drag_dest));
127 else
129 project_model = GTK_TREE_MODEL (drag_dest);
131 g_return_val_if_fail (GBF_IS_PROJECT_MODEL (project_model), FALSE);
133 if (gtk_tree_get_row_drag_data (selection_data,
134 &src_model,
135 &src_path) &&
136 src_model == GTK_TREE_MODEL (project_model)) {
138 GtkTreeIter iter;
139 GbfTreeData *data = NULL;
141 if (gtk_tree_model_get_iter (src_model, &iter, src_path)) {
142 gtk_tree_model_get (src_model, &iter,
143 GBF_PROJECT_MODEL_COLUMN_DATA, &data,
144 -1);
145 if (data != NULL)
147 GtkTreePath *child_path;
149 child_path = gtk_tree_model_filter_convert_path_to_child_path (GTK_TREE_MODEL_FILTER (drag_dest), dest);
150 if (data->type == GBF_TREE_NODE_SHORTCUT)
152 gbf_project_model_move_target_shortcut (GBF_PROJECT_MODEL (project_model),
153 &iter, data, child_path);
155 else
157 gbf_project_model_add_target_shortcut (GBF_PROJECT_MODEL (project_model),
158 NULL, data, child_path, NULL);
160 gtk_tree_path_free (child_path);
161 retval = TRUE;
166 if (src_path)
167 gtk_tree_path_free (src_path);
169 return retval;
172 static gboolean
173 idrag_dest_row_drop_possible (GtkTreeDragDest *drag_dest,
174 GtkTreePath *dest_path,
175 GtkSelectionData *selection_data)
177 GtkTreeModel *src_model;
178 GtkTreeModel *project_model;
179 GtkTreePath *src_path;
180 GtkTreeIter iter;
181 gboolean retval = FALSE;
183 //g_return_val_if_fail (GBF_IS_PROJECT_MODEL (drag_dest), FALSE);
185 if (GTK_IS_TREE_MODEL_FILTER (drag_dest))
187 project_model = gtk_tree_model_filter_get_model (GTK_TREE_MODEL_FILTER (drag_dest));
189 else
191 project_model = GTK_TREE_MODEL (drag_dest);
194 if (!gtk_tree_get_row_drag_data (selection_data,
195 &src_model,
196 &src_path))
198 return FALSE;
202 if (gtk_tree_model_get_iter (src_model, &iter, src_path))
204 GbfTreeData *data = NULL;
206 gtk_tree_model_get (src_model, &iter,
207 GBF_PROJECT_MODEL_COLUMN_DATA, &data, -1);
209 if (data != NULL)
211 /* can only drag to ourselves and only new toplevel nodes will
212 * be created */
213 if (src_model == project_model &&
214 gtk_tree_path_get_depth (dest_path) == 1)
216 if (data->type == GBF_TREE_NODE_SHORTCUT)
218 retval = TRUE;
220 else
222 GtkTreePath *root_path;
223 GtkTreePath *child_path;
225 root_path = gbf_project_model_get_project_root (GBF_PROJECT_MODEL (project_model));
226 child_path = gtk_tree_model_filter_convert_path_to_child_path (GTK_TREE_MODEL_FILTER (drag_dest), dest_path);
227 retval = gtk_tree_path_compare (child_path, root_path) <= 0;
228 gtk_tree_path_free (child_path);
229 gtk_tree_path_free (root_path);
234 gtk_tree_path_free (src_path);
236 return retval;
239 static void
240 pm_project_model_filter_drag_source_iface_init (GtkTreeDragSourceIface *iface)
242 iface->row_draggable = idrag_source_row_draggable;
243 iface->drag_data_delete = idrag_source_drag_data_delete;
246 static void
247 pm_project_model_filter_drag_dest_iface_init (GtkTreeDragDestIface *iface)
249 iface->drag_data_received = idrag_dest_drag_data_received;
250 iface->row_drop_possible = idrag_dest_row_drop_possible;
253 static GType pm_project_model_filter_get_type (void);
255 G_DEFINE_TYPE_WITH_CODE (PmProjectModelFilter,
256 pm_project_model_filter,
257 GTK_TYPE_TREE_MODEL_FILTER,
258 G_IMPLEMENT_INTERFACE (GTK_TYPE_TREE_DRAG_SOURCE,
259 pm_project_model_filter_drag_source_iface_init)
260 G_IMPLEMENT_INTERFACE (GTK_TYPE_TREE_DRAG_DEST,
261 pm_project_model_filter_drag_dest_iface_init));
264 static GtkTreeModel *
265 pm_project_model_filter_new (GtkTreeModel *child_model,
266 GtkTreePath *root)
268 PmProjectModelFilter *model;
270 model = g_object_new (PM_TYPE_PROJECT_MODEL_FILTER,
271 "child-model", child_model,
272 "virtual-root", root,
273 NULL);
275 return GTK_TREE_MODEL (model);
282 static void gbf_project_view_class_init (GbfProjectViewClass *klass);
283 static void gbf_project_view_init (GbfProjectView *tree);
284 static void destroy (GtkWidget *object);
286 static void set_pixbuf (GtkTreeViewColumn *tree_column,
287 GtkCellRenderer *cell,
288 GtkTreeModel *model,
289 GtkTreeIter *iter,
290 gpointer data);
291 static void set_text (GtkTreeViewColumn *tree_column,
292 GtkCellRenderer *cell,
293 GtkTreeModel *model,
294 GtkTreeIter *iter,
295 gpointer data);
298 G_DEFINE_TYPE(GbfProjectView, gbf_project_view, GTK_TYPE_TREE_VIEW);
300 static void
301 row_activated (GtkTreeView *tree_view,
302 GtkTreePath *path,
303 GtkTreeViewColumn *column)
305 GtkTreeModel *model;
306 GtkTreeIter iter;
307 GbfTreeData *data;
308 gchar *uri;
310 model = gtk_tree_view_get_model (tree_view);
312 gtk_tree_model_get_iter (GTK_TREE_MODEL (model), &iter, path);
314 gtk_tree_model_get (GTK_TREE_MODEL (model), &iter,
315 GBF_PROJECT_MODEL_COLUMN_DATA, &data,
316 -1);
318 uri = gbf_tree_data_get_uri (data);
319 if (uri != NULL) {
320 g_signal_emit (G_OBJECT (tree_view),
321 signals [URI_ACTIVATED], 0,
322 uri);
325 if (data->type == GBF_TREE_NODE_TARGET) {
326 g_signal_emit (G_OBJECT (tree_view),
327 signals [TARGET_SELECTED], 0,
328 uri);
331 if (data->type == GBF_TREE_NODE_GROUP) {
332 g_signal_emit (G_OBJECT (tree_view),
333 signals [GROUP_SELECTED], 0,
334 uri);
336 g_free (uri);
339 static void
340 dispose (GObject *object)
342 GbfProjectView *view;
344 view = GBF_PROJECT_VIEW (object);
346 if (view->filter)
348 g_object_unref (G_OBJECT (view->filter));
349 view->filter = NULL;
351 if (view->model)
353 g_object_unref (G_OBJECT (view->model));
354 view->model = NULL;
357 G_OBJECT_CLASS (gbf_project_view_parent_class)->dispose (object);
360 static void
361 destroy (GtkWidget *object)
363 GbfProjectView *tree;
365 tree = GBF_PROJECT_VIEW (object);
367 if (GTK_WIDGET_CLASS (gbf_project_view_parent_class)->destroy)
368 (* GTK_WIDGET_CLASS (gbf_project_view_parent_class)->destroy) (object);
371 static GdkPixbuf*
372 get_icon (GFile *file)
374 const gchar** icon_names;
375 GtkIconInfo* icon_info;
376 GIcon* icon;
377 GdkPixbuf* pixbuf = NULL;
378 GFileInfo* file_info;
379 GError *error = NULL;
381 file_info = g_file_query_info (file,
382 G_FILE_ATTRIBUTE_STANDARD_ICON,
383 G_FILE_QUERY_INFO_NONE,
384 NULL,
385 &error);
387 if (file_info == NULL)
389 pixbuf = gtk_icon_theme_load_icon (gtk_icon_theme_get_default(),
390 GTK_STOCK_MISSING_IMAGE,
391 ICON_SIZE,
392 GTK_ICON_LOOKUP_GENERIC_FALLBACK,
393 NULL);
395 else
397 icon = g_file_info_get_icon(file_info);
398 g_object_get (icon, "names", &icon_names, NULL);
399 icon_info = gtk_icon_theme_choose_icon (gtk_icon_theme_get_default(),
400 icon_names,
401 ICON_SIZE,
402 GTK_ICON_LOOKUP_GENERIC_FALLBACK);
403 pixbuf = gtk_icon_info_load_icon (icon_info, NULL);
404 gtk_icon_info_free(icon_info);
405 g_object_unref (file_info);
408 return pixbuf;
411 static void
412 set_pixbuf (GtkTreeViewColumn *tree_column,
413 GtkCellRenderer *cell,
414 GtkTreeModel *model,
415 GtkTreeIter *iter,
416 gpointer user_data)
418 GbfTreeData *data = NULL;
419 GdkPixbuf *pixbuf = NULL;
421 gtk_tree_model_get (model, iter,
422 GBF_PROJECT_MODEL_COLUMN_DATA, &data, -1);
423 g_return_if_fail (data != NULL);
424 /* FIXME: segmentation fault with shortcut when corresponding
425 * data is removed before the shortcut, so data = NULL.
426 * Perhaps we can add a GtkTreeReference to the shortcut
427 * node to remove the shortcut when the node is destroyed */
429 if ((data->type == GBF_TREE_NODE_SHORTCUT) && (data->shortcut != NULL))
431 data = data->shortcut;
433 switch (data->type) {
434 case GBF_TREE_NODE_SOURCE:
436 pixbuf = get_icon (data->source);
437 break;
439 case GBF_TREE_NODE_ROOT:
440 pixbuf = gtk_icon_theme_load_icon (gtk_icon_theme_get_default(),
441 GTK_STOCK_OPEN,
442 ICON_SIZE,
443 GTK_ICON_LOOKUP_GENERIC_FALLBACK,
444 NULL);
445 break;
446 case GBF_TREE_NODE_GROUP:
447 pixbuf = gtk_icon_theme_load_icon (gtk_icon_theme_get_default(),
448 GTK_STOCK_DIRECTORY,
449 ICON_SIZE,
450 GTK_ICON_LOOKUP_GENERIC_FALLBACK,
451 NULL);
452 break;
453 case GBF_TREE_NODE_TARGET:
455 pixbuf = gtk_icon_theme_load_icon (gtk_icon_theme_get_default(),
456 GTK_STOCK_CONVERT,
457 ICON_SIZE,
458 GTK_ICON_LOOKUP_GENERIC_FALLBACK,
459 NULL);
460 break;
462 case GBF_TREE_NODE_MODULE:
464 pixbuf = gtk_icon_theme_load_icon (gtk_icon_theme_get_default(),
465 GTK_STOCK_DND_MULTIPLE,
466 ICON_SIZE,
467 GTK_ICON_LOOKUP_GENERIC_FALLBACK,
468 NULL);
469 break;
471 case GBF_TREE_NODE_PACKAGE:
473 pixbuf = gtk_icon_theme_load_icon (gtk_icon_theme_get_default(),
474 GTK_STOCK_DND,
475 ICON_SIZE,
476 GTK_ICON_LOOKUP_GENERIC_FALLBACK,
477 NULL);
478 break;
480 default:
481 /* Can reach this if type = GBF_TREE_NODE_SHORTCUT. It
482 * means a shortcut with the original data removed */
483 pixbuf = NULL;
486 g_object_set (GTK_CELL_RENDERER (cell), "pixbuf", pixbuf, NULL);
487 if (pixbuf)
488 g_object_unref (pixbuf);
491 static void
492 set_text (GtkTreeViewColumn *tree_column,
493 GtkCellRenderer *cell,
494 GtkTreeModel *model,
495 GtkTreeIter *iter,
496 gpointer user_data)
498 GbfTreeData *data;
500 gtk_tree_model_get (model, iter, GBF_PROJECT_MODEL_COLUMN_DATA, &data, -1);
501 /* data can be NULL just after gtk_tree_store_insert before
502 calling gtk_tree_store_set */
503 g_object_set (GTK_CELL_RENDERER (cell), "text",
504 data == NULL ? "" : data->name, NULL);
507 static gboolean
508 search_equal_func (GtkTreeModel *model, gint column,
509 const gchar *key, GtkTreeIter *iter,
510 gpointer user_data)
512 GbfTreeData *data;
513 gboolean ret = TRUE;
515 gtk_tree_model_get (model, iter, GBF_PROJECT_MODEL_COLUMN_DATA, &data, -1);
516 if (strncmp (data->name, key, strlen (key)) == 0)
517 ret = FALSE;
518 return ret;
521 static gboolean
522 draw (GtkWidget *widget, cairo_t *cr)
524 GtkTreeModel *view_model;
525 GtkTreeModel *model;
526 GtkTreeView *tree_view;
527 gint event_handled = FALSE;
529 if (GTK_WIDGET_CLASS (gbf_project_view_parent_class)->draw != NULL)
530 GTK_WIDGET_CLASS (gbf_project_view_parent_class)->draw (widget, cr);
532 tree_view = GTK_TREE_VIEW (widget);
533 view_model = gtk_tree_view_get_model (tree_view);
534 if (GTK_IS_TREE_MODEL_FILTER (view_model))
536 model = gtk_tree_model_filter_get_model (GTK_TREE_MODEL_FILTER (view_model));
538 if (gtk_cairo_should_draw_window (cr, gtk_tree_view_get_bin_window (tree_view)) &&
539 model && GBF_IS_PROJECT_MODEL (model)) {
540 GtkTreePath *root;
541 GdkRectangle rect;
543 /* paint an horizontal ruler to separate the project
544 * tree from the target shortcuts */
546 root = gbf_project_model_get_project_root (GBF_PROJECT_MODEL (model));
547 if (root) {
548 if (view_model != model)
550 /* Convert path */
551 GtkTreePath *child_path;
553 child_path = gtk_tree_model_filter_convert_child_path_to_path (GTK_TREE_MODEL_FILTER (view_model), root);
554 gtk_tree_path_free (root);
555 root = child_path;
557 gtk_tree_view_get_background_area (
558 tree_view, root, gtk_tree_view_get_column (tree_view, 0), &rect);
559 gtk_paint_hline (gtk_widget_get_style (widget),
561 gtk_widget_get_state (widget),
562 widget,
564 rect.x, rect.x + rect.width,
565 rect.y);
566 gtk_tree_path_free (root);
570 return event_handled;
573 static void
574 gbf_project_view_class_init (GbfProjectViewClass *klass)
576 GObjectClass *g_object_class;
577 GtkWidgetClass *widget_class;
578 GtkTreeViewClass *tree_view_class;
580 g_object_class = G_OBJECT_CLASS (klass);
581 widget_class = GTK_WIDGET_CLASS (klass);
582 tree_view_class = GTK_TREE_VIEW_CLASS (klass);
584 g_object_class->dispose = dispose;
585 widget_class->destroy = destroy;
586 widget_class->draw = draw;
587 tree_view_class->row_activated = row_activated;
589 signals [URI_ACTIVATED] =
590 g_signal_new ("uri_activated",
591 GBF_TYPE_PROJECT_VIEW,
592 G_SIGNAL_RUN_LAST,
593 G_STRUCT_OFFSET (GbfProjectViewClass,
594 uri_activated),
595 NULL, NULL,
596 g_cclosure_marshal_VOID__STRING,
597 G_TYPE_NONE, 1, G_TYPE_STRING);
599 signals [TARGET_SELECTED] =
600 g_signal_new ("target_selected",
601 GBF_TYPE_PROJECT_VIEW,
602 G_SIGNAL_RUN_LAST,
603 G_STRUCT_OFFSET (GbfProjectViewClass,
604 target_selected),
605 NULL, NULL,
606 g_cclosure_marshal_VOID__POINTER,
607 G_TYPE_NONE, 1, G_TYPE_POINTER);
608 signals [GROUP_SELECTED] =
609 g_signal_new ("group_selected",
610 GBF_TYPE_PROJECT_VIEW,
611 G_SIGNAL_RUN_LAST,
612 G_STRUCT_OFFSET (GbfProjectViewClass,
613 group_selected),
614 NULL, NULL,
615 g_cclosure_marshal_VOID__POINTER,
616 G_TYPE_NONE, 1, G_TYPE_POINTER);
617 signals[NODE_LOADED] =
618 g_signal_new ("node-loaded",
619 GBF_TYPE_PROJECT_VIEW,
620 G_SIGNAL_RUN_LAST,
621 G_STRUCT_OFFSET (GbfProjectViewClass,
622 node_loaded),
623 NULL, NULL,
624 pm_cclosure_marshal_VOID__POINTER_BOOLEAN_BOXED,
625 G_TYPE_NONE, 3,
626 G_TYPE_POINTER,
627 G_TYPE_BOOLEAN,
628 G_TYPE_ERROR);
632 static gboolean
633 is_project_node_visible (GtkTreeModel *model, GtkTreeIter *iter, gpointer user_data)
635 GbfTreeData *data;
637 gtk_tree_model_get (GTK_TREE_MODEL (model), iter,
638 GBF_PROJECT_MODEL_COLUMN_DATA, &data,
639 -1);
641 return (data != NULL) && (gbf_tree_data_get_node (data) != NULL);
644 static void
645 gbf_project_view_init (GbfProjectView *tree)
647 GtkCellRenderer *renderer;
648 GtkTreeViewColumn *column;
649 static GtkTargetEntry row_targets[] = {
650 { "GTK_TREE_MODEL_ROW", GTK_TARGET_SAME_WIDGET, 0 }
653 gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (tree), FALSE);
654 gtk_tree_view_set_enable_search (GTK_TREE_VIEW (tree), TRUE);
655 gtk_tree_view_set_search_column (GTK_TREE_VIEW (tree), 0);
656 gtk_tree_view_set_search_equal_func (GTK_TREE_VIEW (tree),
657 search_equal_func,
658 NULL, NULL);
660 gtk_tree_view_enable_model_drag_source (GTK_TREE_VIEW (tree),
661 GDK_BUTTON1_MASK,
662 row_targets,
663 G_N_ELEMENTS (row_targets),
664 GDK_ACTION_MOVE);
665 gtk_tree_view_enable_model_drag_dest (GTK_TREE_VIEW (tree),
666 row_targets,
667 G_N_ELEMENTS (row_targets),
668 GDK_ACTION_MOVE);
670 /* set renderer for files column. */
671 column = gtk_tree_view_column_new ();
672 renderer = gtk_cell_renderer_pixbuf_new ();
673 gtk_tree_view_column_pack_start (column, renderer, FALSE);
674 gtk_tree_view_column_set_cell_data_func (column, renderer, set_pixbuf, tree, NULL);
676 renderer = gtk_cell_renderer_text_new ();
677 gtk_tree_view_column_pack_start (column, renderer, FALSE);
678 gtk_tree_view_column_set_cell_data_func (column, renderer, set_text, tree, NULL);
680 gtk_tree_view_append_column (GTK_TREE_VIEW (tree), column);
682 /* Create model */
683 tree->model = gbf_project_model_new (NULL);
684 tree->filter = GTK_TREE_MODEL_FILTER (pm_project_model_filter_new (GTK_TREE_MODEL (tree->model), NULL));
685 gtk_tree_model_filter_set_visible_func (tree->filter, is_project_node_visible, tree, NULL);
687 gtk_tree_view_set_model (GTK_TREE_VIEW (tree), GTK_TREE_MODEL (tree->filter));
690 GtkWidget *
691 gbf_project_view_new (void)
693 return GTK_WIDGET (g_object_new (GBF_TYPE_PROJECT_VIEW, NULL));
696 AnjutaProjectNode *
697 gbf_project_view_find_selected (GbfProjectView *view, AnjutaProjectNodeType type)
699 AnjutaProjectNode *node = NULL;
700 GbfTreeData *data;
702 g_return_val_if_fail (view != NULL, NULL);
703 g_return_val_if_fail (GBF_IS_PROJECT_VIEW (view), NULL);
705 data = gbf_project_view_get_first_selected (view, NULL);
706 if (data != NULL)
709 node = gbf_tree_data_get_node (data);
711 /* walk up the hierarchy searching for a node of the given type */
712 while ((node != NULL) && (type != ANJUTA_PROJECT_UNKNOWN) && (anjuta_project_node_get_node_type (node) != type))
714 node = anjuta_project_node_parent (node);
718 return node;
721 GbfTreeData *
722 gbf_project_view_get_first_selected (GbfProjectView *view, GtkTreeIter* selected)
724 GtkTreeSelection *selection;
725 GbfTreeData *data = NULL;
726 GtkTreeModel *model;
727 GList *list;
729 g_return_val_if_fail (view != NULL, NULL);
730 g_return_val_if_fail (GBF_IS_PROJECT_VIEW (view), NULL);
732 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (view));
733 list = gtk_tree_selection_get_selected_rows(selection, &model);
734 if (list != NULL)
736 GtkTreeIter iter;
738 if (gtk_tree_model_get_iter (model, &iter, list->data))
740 if (selected)
742 if (GTK_IS_TREE_MODEL_FILTER (model))
744 GtkTreeIter child_iter;
746 gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER (model), &child_iter, &iter);
747 *selected = child_iter;
749 else
751 *selected = iter;
755 gtk_tree_model_get (GTK_TREE_MODEL (model), &iter,
756 GBF_PROJECT_MODEL_COLUMN_DATA, &data,
757 -1);
759 g_list_foreach (list, (GFunc)gtk_tree_path_free, NULL);
760 g_list_free (list);
763 return data;
766 void
767 gbf_project_view_set_cursor_to_iter (GbfProjectView *view,
768 GtkTreeIter *selected)
770 GtkTreePath *path = NULL;
771 GtkTreeIter view_iter;
773 /* select node if we find it in the view*/
774 if ((selected != NULL) && gtk_tree_model_filter_convert_child_iter_to_iter (
775 GTK_TREE_MODEL_FILTER (view->filter), &view_iter, selected))
777 path = gtk_tree_model_get_path (GTK_TREE_MODEL (view->filter), &view_iter);
779 else
781 /* Check if it is a shortcut */
782 if (selected !=NULL)
784 GbfTreeData *data;
786 gtk_tree_model_get (GTK_TREE_MODEL (view->model), selected,
787 GBF_PROJECT_MODEL_COLUMN_DATA, &data,
788 -1);
790 if ((data != NULL) && (data->shortcut != NULL))
792 /* Select the corresponding node */
793 GtkTreeIter iter;
795 if (gbf_project_model_find_tree_data (view->model, &iter, data->shortcut))
797 if (gtk_tree_model_filter_convert_child_iter_to_iter (
798 GTK_TREE_MODEL_FILTER (view->filter), &view_iter, &iter))
800 path = gtk_tree_model_get_path (GTK_TREE_MODEL (view->filter), &view_iter);
806 /* Try to select root node */
807 if (path == NULL)
809 GtkTreePath *root_path;
811 root_path = gbf_project_model_get_project_root (view->model);
812 if (root_path)
814 path = gtk_tree_model_filter_convert_child_path_to_path (
815 GTK_TREE_MODEL_FILTER (view->filter), root_path);
816 gtk_tree_path_free (root_path);
820 /* Take the first node */
821 if (path == NULL)
823 path = gtk_tree_path_new_first ();
827 if (path)
829 gtk_tree_view_expand_to_path (GTK_TREE_VIEW (view), path);
831 gtk_tree_view_set_cursor (GTK_TREE_VIEW (view), path, NULL, FALSE);
832 gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (view), path, NULL,
833 TRUE, 0.5, 0.0);
834 gtk_tree_path_free (path);
839 static void
840 on_each_get_data (GtkTreeModel *model,
841 GtkTreePath *path,
842 GtkTreeIter *iter,
843 gpointer user_data)
845 GList **selected = (GList **)user_data;
846 GbfTreeData *data;
848 gtk_tree_model_get (GTK_TREE_MODEL (model), iter,
849 GBF_PROJECT_MODEL_COLUMN_DATA, &data,
850 -1);
852 *selected = g_list_prepend (*selected, data);
855 GList *
856 gbf_project_view_get_all_selected (GbfProjectView *view)
858 GtkTreeSelection *selection;
859 GList *selected = NULL;
861 g_return_val_if_fail (view != NULL, FALSE);
862 g_return_val_if_fail (GBF_IS_PROJECT_VIEW (view), FALSE);
864 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (view));
865 gtk_tree_selection_selected_foreach (selection, on_each_get_data, &selected);
867 return g_list_reverse (selected);
870 static void
871 on_each_get_iter (GtkTreeModel *model,
872 GtkTreePath *path,
873 GtkTreeIter *iter,
874 gpointer user_data)
876 GList **selected = (GList **)user_data;
878 *selected = g_list_prepend (*selected, gtk_tree_iter_copy (iter));
881 GList *
882 gbf_project_view_get_all_selected_iter (GbfProjectView *view)
884 GtkTreeSelection *selection;
885 GList *selected = NULL;
887 g_return_val_if_fail (view != NULL, FALSE);
888 g_return_val_if_fail (GBF_IS_PROJECT_VIEW (view), FALSE);
890 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (view));
891 gtk_tree_selection_selected_foreach (selection, on_each_get_iter, &selected);
893 return g_list_reverse (selected);
896 static void
897 gbf_project_view_update_shortcut (GbfProjectView *view, AnjutaProjectNode *parent)
899 GtkTreeIter child;
900 gboolean valid;
902 /* Get all root node */
903 valid = gtk_tree_model_iter_children (GTK_TREE_MODEL (view->model), &child, NULL);
905 while (valid)
907 GbfTreeData *data;
908 AnjutaProjectNode* old_node = NULL;
910 gtk_tree_model_get (GTK_TREE_MODEL (view->model), &child,
911 GBF_PROJECT_MODEL_COLUMN_DATA, &data,
912 -1);
914 /* Shortcuts are always at the beginning */
915 if (data->type != GBF_TREE_NODE_SHORTCUT) break;
917 old_node = gbf_tree_data_get_node (data);
918 if (old_node == parent)
920 /* check children */
921 gbf_project_view_update_tree (view, parent, &child);
923 valid = gtk_tree_model_iter_next (GTK_TREE_MODEL (view->model), &child);
927 static gint
928 compare_node_name (gconstpointer a, gconstpointer b)
930 const AnjutaProjectNode *node = (const AnjutaProjectNode *)a;
931 const gchar *name = (const gchar *)b;
933 return g_strcmp0 (anjuta_project_node_get_name (node), name);
936 void
937 gbf_project_view_update_tree (GbfProjectView *view, AnjutaProjectNode *parent, GtkTreeIter *iter)
939 GtkTreeIter child;
940 GList *node;
941 GList *nodes;
942 GbfTreeData *data = NULL;
944 /* Get all new nodes */
945 nodes = gbf_project_util_all_child (parent, ANJUTA_PROJECT_UNKNOWN);
947 /* walk the tree nodes */
948 if (gtk_tree_model_iter_children (GTK_TREE_MODEL (view->model), &child, iter))
950 gboolean valid = TRUE;
952 while (valid) {
953 data = NULL;
954 AnjutaProjectNode* data_node = NULL;
956 /* Look for current node */
957 gtk_tree_model_get (GTK_TREE_MODEL (view->model), &child,
958 GBF_PROJECT_MODEL_COLUMN_DATA, &data,
959 -1);
961 data_node = gbf_tree_data_get_node (data);
963 /* Skip shortcuts */
964 if (data->type == GBF_TREE_NODE_SHORTCUT)
966 valid = gtk_tree_model_iter_next (GTK_TREE_MODEL (view->model), &child);
967 continue;
970 if (data->type == GBF_TREE_NODE_UNKNOWN)
972 node = g_list_find_custom (nodes, data->name, compare_node_name);
973 if (node != NULL)
975 GtkTreePath *path;
976 GtkTreePath *child_path;
977 GtkTreeModelFilter *filter;
978 gboolean expanded;
979 gboolean shortcut;
981 expanded = data->expanded;
982 shortcut = data->has_shortcut;
983 data_node = (AnjutaProjectNode *)node->data;
984 gbf_tree_data_free (data);
985 data = gbf_tree_data_new_node (data_node);
986 gtk_tree_store_set (GTK_TREE_STORE (view->model), &child,
987 GBF_PROJECT_MODEL_COLUMN_DATA, data,
988 -1);
990 /* Node already exist, remove it from the list */
991 nodes = g_list_delete_link (nodes, node);
993 /* Update shortcut */
994 gbf_project_view_update_shortcut (view, data_node);
996 /* update recursively */
997 gbf_project_view_update_tree (view, data_node, &child);
999 if (shortcut)
1001 gboolean expanded;
1002 GtkTreeIter iter;
1004 gbf_project_model_add_target_shortcut (view->model, &iter, data, NULL, &expanded);
1005 if (expanded)
1007 /* Expand shortcut */
1008 filter = GTK_TREE_MODEL_FILTER (gtk_tree_view_get_model (GTK_TREE_VIEW (view)));
1009 path = gtk_tree_model_get_path (GTK_TREE_MODEL (view->model), &iter);
1010 child_path = gtk_tree_model_filter_convert_child_path_to_path (filter, path);
1011 gtk_tree_view_expand_to_path (GTK_TREE_VIEW (view), child_path);
1012 gtk_tree_path_free (child_path);
1013 gtk_tree_path_free (path);
1016 data->expanded = expanded;
1017 if (expanded)
1019 filter = GTK_TREE_MODEL_FILTER (gtk_tree_view_get_model (GTK_TREE_VIEW (view)));
1020 path = gtk_tree_model_get_path (GTK_TREE_MODEL (view->model), &child);
1021 child_path = gtk_tree_model_filter_convert_child_path_to_path (filter, path);
1022 gtk_tree_view_expand_to_path (GTK_TREE_VIEW (view), child_path);
1023 expanded = gtk_tree_view_row_expanded (GTK_TREE_VIEW (view), child_path);
1024 gtk_tree_path_free (child_path);
1025 gtk_tree_path_free (path);
1028 valid = gtk_tree_model_iter_next (GTK_TREE_MODEL (view->model), &child);
1030 else
1032 node = g_list_find (nodes, data_node);
1033 if (node != NULL)
1035 /* Node already exist, remove it from the list */
1036 nodes = g_list_delete_link (nodes, node);
1038 /* Update shortcut */
1039 gbf_project_view_update_shortcut (view, data_node);
1041 /* update recursively */
1042 gbf_project_view_update_tree (view, data_node, &child);
1044 valid = gtk_tree_model_iter_next (GTK_TREE_MODEL (view->model), &child);
1046 else
1048 /* Node has been deleted */
1049 valid = gbf_project_model_remove (view->model, &child);
1055 /* add the remaining sources, targets and groups */
1056 for (node = nodes; node; node = node->next)
1058 switch (anjuta_project_node_get_node_type (node->data))
1060 case ANJUTA_PROJECT_GROUP:
1061 gbf_project_model_add_target_group (view->model, node->data, iter);
1062 break;
1063 case ANJUTA_PROJECT_TARGET:
1064 gbf_project_model_add_target (view->model, node->data, iter);
1065 break;
1066 case ANJUTA_PROJECT_SOURCE:
1067 gbf_project_model_add_source (view->model, node->data, iter);
1068 break;
1069 case ANJUTA_PROJECT_MODULE:
1070 gbf_project_model_add_module (view->model, node->data, iter);
1071 break;
1072 case ANJUTA_PROJECT_PACKAGE:
1073 gbf_project_model_add_package (view->model, node->data, iter);
1074 break;
1075 case ANJUTA_PROJECT_ROOT:
1076 gbf_project_model_add_root (view->model, node->data, iter);
1077 break;
1078 default:
1079 break;
1083 /* Expand parent, needed if the parent hasn't any children when it was created */
1084 if (iter != NULL)
1086 /* Check parent data */
1087 gtk_tree_model_get (GTK_TREE_MODEL (view->model), iter,
1088 GBF_PROJECT_MODEL_COLUMN_DATA, &data,
1089 -1);
1090 if (data->expanded)
1092 GtkTreePath *path;
1093 GtkTreePath *child_path;
1094 GtkTreeModelFilter *filter;
1096 filter = GTK_TREE_MODEL_FILTER (gtk_tree_view_get_model (GTK_TREE_VIEW (view)));
1097 path = gtk_tree_model_get_path (GTK_TREE_MODEL (view->model), iter);
1098 child_path = gtk_tree_model_filter_convert_child_path_to_path (filter, path);
1099 gtk_tree_view_expand_to_path (GTK_TREE_VIEW (view), child_path);
1100 gtk_tree_path_free (child_path);
1101 gtk_tree_path_free (path);
1102 data->expanded = FALSE;
1107 /* Shorcuts functions
1108 *---------------------------------------------------------------------------*/
1110 void
1111 gbf_project_view_sort_shortcuts (GbfProjectView *view)
1113 gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (view->model),
1114 GTK_TREE_SORTABLE_UNSORTED_SORT_COLUMN_ID,
1115 GTK_SORT_ASCENDING);
1116 gbf_project_model_sort_shortcuts (view->model);
1117 gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (view->model),
1118 GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID,
1119 GTK_SORT_ASCENDING);
1123 GList *
1124 gbf_project_view_get_shortcut_list (GbfProjectView *view)
1126 GList *list = NULL;
1127 GtkTreeModel* model;
1128 gboolean valid;
1129 GtkTreeIter iter;
1131 model = GTK_TREE_MODEL (view->model);
1132 if (model != NULL)
1134 for (valid = gtk_tree_model_iter_children (GTK_TREE_MODEL (model), &iter, NULL);
1135 valid == TRUE;
1136 valid = gtk_tree_model_iter_next (GTK_TREE_MODEL (model), &iter))
1138 GbfTreeData *data;
1139 gtk_tree_model_get (GTK_TREE_MODEL (model), &iter,
1140 GBF_PROJECT_MODEL_COLUMN_DATA, &data,
1141 -1);
1143 if ((data->type == GBF_TREE_NODE_SHORTCUT) && (data->shortcut != NULL))
1145 GtkTreeIter iter;
1147 if (gbf_project_model_find_tree_data (view->model, &iter, data->shortcut))
1149 GString *str;
1150 GtkTreeIter child;
1152 str = g_string_new (NULL);
1155 GbfTreeData *data;
1157 child = iter;
1158 gtk_tree_model_get (GTK_TREE_MODEL (model), &iter,
1159 GBF_PROJECT_MODEL_COLUMN_DATA, &data,
1160 -1);
1162 if (data->node != NULL)
1164 if (str->len != 0) g_string_prepend (str, "//");
1165 g_string_prepend (str, anjuta_project_node_get_name (data->node));
1168 while (gtk_tree_model_iter_parent (model, &iter, &child));
1169 list = g_list_prepend (list, str->str);
1170 g_string_free (str, FALSE);
1174 list = g_list_reverse (list);
1177 return list;
1180 static void
1181 save_expanded_node (GtkTreeView *view, GtkTreePath *path, gpointer user_data)
1183 GList **list = (GList **)user_data;
1184 GtkTreeModel *model;
1185 GtkTreeIter iter;
1187 model = gtk_tree_view_get_model (GTK_TREE_VIEW (view));
1189 if (gtk_tree_model_get_iter (model, &iter, path))
1191 GString *str;
1192 GtkTreeIter child;
1194 str = g_string_new (NULL);
1197 GbfTreeData *data;
1199 child = iter;
1200 gtk_tree_model_get (GTK_TREE_MODEL (model), &iter,
1201 GBF_PROJECT_MODEL_COLUMN_DATA, &data,
1202 -1);
1204 if (data->node != NULL)
1206 if (str->len != 0) g_string_prepend (str, "//");
1207 g_string_prepend (str, anjuta_project_node_get_name (data->node));
1210 while (gtk_tree_model_iter_parent (model, &iter, &child));
1212 *list = g_list_prepend (*list, str->str);
1213 g_string_free (str, FALSE);
1217 GList *
1218 gbf_project_view_get_expanded_list (GbfProjectView *view)
1220 GList *list = NULL;
1222 gtk_tree_view_map_expanded_rows (GTK_TREE_VIEW (view), save_expanded_node, &list);
1223 list = g_list_reverse (list);
1225 return list;
1228 void
1229 gbf_project_view_remove_all_shortcut (GbfProjectView* view)
1231 GtkTreeModel* model;
1232 gboolean valid;
1233 GtkTreeIter iter;
1235 model = gtk_tree_view_get_model (GTK_TREE_VIEW (view));
1237 /* Remove all current shortcuts */
1238 for (valid = gtk_tree_model_iter_children (GTK_TREE_MODEL (model), &iter, NULL);
1239 valid == TRUE;)
1241 GbfTreeData *data;
1243 gtk_tree_model_get (GTK_TREE_MODEL (model), &iter,
1244 GBF_PROJECT_MODEL_COLUMN_DATA, &data,
1245 -1);
1247 if (data->type == GBF_TREE_NODE_SHORTCUT)
1249 valid = gbf_project_model_remove (GBF_PROJECT_MODEL (model), &iter);
1251 else
1253 /* No more shortcut */
1254 break;
1259 void
1260 gbf_project_view_set_shortcut_list (GbfProjectView *view, GList *shortcuts)
1262 GList *item;
1264 gbf_project_model_set_default_shortcut (view->model, shortcuts == NULL);
1266 for (item = g_list_first (shortcuts); item != NULL; item = g_list_next (item))
1268 gchar *name = (gchar *)item->data;
1269 gchar *end;
1270 GtkTreeIter iter;
1271 GtkTreeIter *parent = NULL;
1275 end = strstr (name, "/" "/"); /* Avoid troubles with auto indent */
1276 if (end != NULL) *end = '\0';
1277 if (*name != '\0')
1279 if (!gbf_project_model_find_child_name (view->model, &iter, parent, name))
1281 GbfTreeData *data;
1283 /* Create proxy node */
1284 data = gbf_tree_data_new_proxy (name, FALSE);
1285 gtk_tree_store_append (GTK_TREE_STORE (view->model), &iter, parent);
1286 gtk_tree_store_set (GTK_TREE_STORE (view->model), &iter,
1287 GBF_PROJECT_MODEL_COLUMN_DATA, data,
1288 -1);
1289 if (end == NULL)
1291 data->has_shortcut = TRUE;
1293 /* Create another proxy at root level to keep shortcut order */
1294 data = gbf_tree_data_new_proxy (name, FALSE);
1295 gtk_tree_store_append (GTK_TREE_STORE (view->model), &iter, NULL);
1296 gtk_tree_store_set (GTK_TREE_STORE (view->model), &iter,
1297 GBF_PROJECT_MODEL_COLUMN_DATA, data,
1298 -1);
1301 else
1303 GbfTreeData *data;
1305 gtk_tree_model_get (GTK_TREE_MODEL (view->model), &iter,
1306 GBF_PROJECT_MODEL_COLUMN_DATA, &data,
1307 -1);
1308 if (end == NULL) data->has_shortcut = TRUE;
1310 parent = &iter;
1312 if (end != NULL)
1314 *end = '/';
1315 name = end + 2;
1318 while (end != NULL);
1321 return;
1324 void
1325 gbf_project_view_set_expanded_list (GbfProjectView *view, GList *expand)
1327 GList *item;
1329 for (item = g_list_first (expand); item != NULL; item = g_list_next (item))
1331 gchar *name = (gchar *)item->data;
1332 gchar *end;
1333 GtkTreeIter iter;
1334 GtkTreeIter *parent = NULL;
1338 end = strstr (name, "/" "/"); /* Avoid troubles with auto indent */
1339 if (end != NULL) *end = '\0';
1340 if (*name != '\0')
1342 if (!gbf_project_model_find_child_name (view->model, &iter, parent, name))
1344 GbfTreeData *data;
1346 /* Create proxy node */
1347 data = gbf_tree_data_new_proxy (name, TRUE);
1348 gtk_tree_store_append (GTK_TREE_STORE (view->model), &iter, parent);
1349 gtk_tree_store_set (GTK_TREE_STORE (view->model), &iter,
1350 GBF_PROJECT_MODEL_COLUMN_DATA, data,
1351 -1);
1353 else
1355 GbfTreeData *data;
1357 gtk_tree_model_get (GTK_TREE_MODEL (view->model), &iter,
1358 GBF_PROJECT_MODEL_COLUMN_DATA, &data,
1359 -1);
1360 data->expanded = TRUE;
1362 parent = &iter;
1364 if (end != NULL)
1366 *end = '/';
1367 name = end + 2;
1370 while (end != NULL);
1373 return;
1376 AnjutaProjectNode *
1377 gbf_project_view_get_node_from_iter (GbfProjectView *view, GtkTreeIter *iter)
1379 return gbf_project_model_get_node (view->model, iter);
1382 AnjutaProjectNode *
1383 gbf_project_view_get_node_from_file (GbfProjectView *view, AnjutaProjectNodeType type, GFile *file)
1385 GtkTreeIter iter;
1386 AnjutaProjectNode *node = NULL;
1388 if (gbf_project_model_find_file (view->model, &iter, NULL, type, file))
1391 node = gbf_project_model_get_node (view->model, &iter);
1394 return NULL;
1397 gboolean
1398 gbf_project_view_remove_data (GbfProjectView *view, GbfTreeData *data, GError **error)
1400 GtkTreeIter iter;
1402 if (gbf_project_model_find_tree_data (view->model, &iter, data))
1404 gbf_project_model_remove (view->model, &iter);
1406 return TRUE;
1408 else
1410 return FALSE;
1414 static void
1415 on_node_loaded (AnjutaPmProject *sender, AnjutaProjectNode *node, gboolean complete, GError *error, GbfProjectView *view)
1417 if (error != NULL)
1419 g_warning ("unable to load node");
1420 g_signal_emit (G_OBJECT (view), NODE_LOADED, 0, NULL, complete, error);
1422 else
1424 GtkTreeIter iter;
1425 gboolean found;
1427 gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (view->model),
1428 GTK_TREE_SORTABLE_UNSORTED_SORT_COLUMN_ID,
1429 GTK_SORT_ASCENDING);
1431 found = gbf_project_model_find_node (view->model, &iter, NULL, node);
1432 if (!found)
1434 if (anjuta_project_node_get_node_type (node) != ANJUTA_PROJECT_ROOT)
1436 g_critical ("Unable to find node %s", anjuta_project_node_get_name (node));
1438 else
1440 GtkTreePath *path;
1441 GtkTreePath *child_path;
1442 GtkTreeModelFilter *filter;
1444 if (!gbf_project_model_find_child_name (view->model, &iter, NULL, anjuta_project_node_get_name (node)))
1446 gbf_project_model_add_root (view->model, node, &iter);
1448 else
1450 GbfTreeData *data;
1452 gtk_tree_model_get (GTK_TREE_MODEL (view->model), &iter,
1453 GBF_PROJECT_MODEL_COLUMN_DATA, &data,
1454 -1);
1455 if (data->type == GBF_TREE_NODE_UNKNOWN)
1457 /* Replace with real node */
1458 GbfTreeData *new_data;
1460 new_data = gbf_tree_data_new_node (node);
1461 gtk_tree_store_set (GTK_TREE_STORE (view->model), &iter,
1462 GBF_PROJECT_MODEL_COLUMN_DATA, new_data,
1463 -1);
1464 gbf_tree_data_free (data);
1466 gbf_project_view_update_tree (view, node, &iter);
1469 /* Expand root node */
1470 path = gtk_tree_model_get_path (GTK_TREE_MODEL (view->model), &iter);
1471 filter = GTK_TREE_MODEL_FILTER (gtk_tree_view_get_model (GTK_TREE_VIEW (view)));
1472 child_path = gtk_tree_model_filter_convert_child_path_to_path (filter, path);
1473 gtk_tree_view_expand_row (GTK_TREE_VIEW (view), child_path, FALSE);
1474 gtk_tree_path_free (child_path);
1475 gtk_tree_path_free (path);
1478 else
1480 gbf_project_view_update_tree (view, node, &iter);
1482 gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (view->model),
1483 GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID,
1484 GTK_SORT_ASCENDING);
1486 g_signal_emit (G_OBJECT (view), signals[NODE_LOADED], 0, found ? &iter : NULL, complete, NULL);
1489 if (complete)
1491 // Add shortcut for all new primary targets
1492 gbf_project_model_set_default_shortcut (view->model, TRUE);
1497 void
1498 gbf_project_view_set_project (GbfProjectView *view, AnjutaPmProject *project)
1500 g_signal_connect (project, "loaded", G_CALLBACK (on_node_loaded), view);
1502 gbf_project_model_set_project (view->model, project);
1505 void
1506 gbf_project_view_set_parent_view (GbfProjectView *view,
1507 GbfProjectView *parent,
1508 GtkTreePath *root)
1511 if (view->model != NULL) g_object_unref (view->model);
1512 if (view->filter != NULL) g_object_unref (view->model);
1514 view->model = g_object_ref (parent->model);
1515 view->filter = GTK_TREE_MODEL_FILTER (pm_project_model_filter_new (GTK_TREE_MODEL (view->model), root));
1516 gtk_tree_view_set_model (GTK_TREE_VIEW (view), GTK_TREE_MODEL (view->filter));
1519 void
1520 gbf_project_view_set_visible_func (GbfProjectView *view,
1521 GtkTreeModelFilterVisibleFunc func,
1522 gpointer data,
1523 GDestroyNotify destroy)
1525 if (func == NULL)
1527 gtk_tree_model_filter_set_visible_func (view->filter, is_project_node_visible, view, NULL);
1529 else
1531 gtk_tree_model_filter_set_visible_func (view->filter, func, data, destroy);
1533 gtk_tree_model_filter_refilter (view->filter);
1536 gboolean
1537 gbf_project_view_find_file (GbfProjectView *view, GtkTreeIter* iter, GFile *file, GbfTreeNodeType type)
1539 return gbf_project_model_find_file (view->model, iter, NULL, type, file);
1542 GbfProjectModel *
1543 gbf_project_view_get_model (GbfProjectView *view)
1545 return view->model;
1548 gboolean
1549 gbf_project_view_get_project_root (GbfProjectView *view, GtkTreeIter *iter)
1551 GtkTreeModel *model;
1552 GtkTreeModel *view_model;
1553 GtkTreePath *path;
1554 gboolean ok = FALSE;
1556 model = gtk_tree_view_get_model (GTK_TREE_VIEW (view));
1557 view_model = model;
1558 if (GTK_IS_TREE_MODEL_FILTER (model))
1560 model = gtk_tree_model_filter_get_model (GTK_TREE_MODEL_FILTER (view_model));
1563 path = gbf_project_model_get_project_root (GBF_PROJECT_MODEL (model));
1564 if (path)
1566 ok = gtk_tree_model_get_iter (model, iter, path);
1567 gtk_tree_path_free (path);
1570 return ok;