[anjuta] Add a new project backend to open a directory as a project



commit 4aebbe5819471519822e7b25fd7276fecc2837ba
Author: Sébastien Granjoux <seb sfo free fr>
Date:   Sat Jan 2 16:03:48 2010 +0100

    Add a new project backend to open a directory as a project

 configure.in                                       |    2 +
 plugins/Makefile.am                                |    1 +
 plugins/dir-project/Makefile.am                    |   58 ++
 plugins/dir-project/dir-project-plugin-48.png      |  Bin 0 -> 866 bytes
 plugins/dir-project/dir-project.c                  |  986 ++++++++++++++++++++
 plugins/dir-project/dir-project.h                  |  122 +++
 plugins/dir-project/dir-project.plugin.in          |   11 +
 plugins/dir-project/plugin.c                       |  126 +++
 plugins/dir-project/plugin.h                       |   47 +
 plugins/dir-project/sources.list                   |   19 +
 plugins/project-import/plugin.c                    |   60 +-
 plugins/project-manager/plugin.c                   |   59 +-
 plugins/project-wizard/templates/Makefile.am       |    2 +-
 .../project-wizard/templates/directory/Makefile.am |    8 +
 .../templates/directory/project.anjuta             |   51 +
 .../project-wizard/templates/mkfile/project.anjuta |   11 +-
 .../templates/terminal/project.anjuta              |    9 +-
 po/POTFILES.in                                     |    1 +
 18 files changed, 1527 insertions(+), 46 deletions(-)
---
diff --git a/configure.in b/configure.in
index 9961c5a..2eade99 100644
--- a/configure.in
+++ b/configure.in
@@ -847,7 +847,9 @@ plugins/project-wizard/templates/gnome-applet/po/Makefile
 plugins/project-wizard/templates/library/Makefile
 plugins/project-wizard/templates/library/src/Makefile
 plugins/project-wizard/templates/library/po/Makefile
+plugins/project-wizard/templates/directory/Makefile
 plugins/project-wizard/templates/m4/Makefile
+plugins/dir-project/Makefile
 plugins/language-support-cpp-java/Makefile
 plugins/language-support-cpp-java/cxxparser/Makefile
 plugins/run-program/Makefile
diff --git a/plugins/Makefile.am b/plugins/Makefile.am
index 5395330..329fd2b 100644
--- a/plugins/Makefile.am
+++ b/plugins/Makefile.am
@@ -31,6 +31,7 @@ SUBDIRS = . \
 	run-program \
 	gbf-am \
 	gbf-mkfile \
+	dir-project \
 	starter \
 	js-debugger \
 	language-support-js
diff --git a/plugins/dir-project/Makefile.am b/plugins/dir-project/Makefile.am
new file mode 100644
index 0000000..bd35cb6
--- /dev/null
+++ b/plugins/dir-project/Makefile.am
@@ -0,0 +1,58 @@
+# Plugin UI file
+plugin_uidir = $(anjuta_ui_dir)
+plugin_ui_DATA = 
+
+# Plugin glade file
+plugin_gladedir = $(anjuta_glade_dir)
+plugin_glade_DATA =
+
+# Plugin data file
+plugin_datadir = $(anjuta_data_dir)
+plugin_data_DATA = sources.list
+
+# Plugin icon file
+plugin_pixmapsdir = $(anjuta_image_dir)
+plugin_pixmaps_DATA = dir-project-plugin-48.png
+
+# Plugin description file
+plugin_in_files = dir-project.plugin.in
+%.plugin: %.plugin.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*po) ; $(INTLTOOL_MERGE) $(top_srcdir)/po $< $@ -d -u -c $(top_builddir)/po/.intltool-merge-cache
+
+plugindir = $(anjuta_plugin_dir)
+plugin_DATA = $(plugin_in_files:.plugin.in=.plugin)
+
+AM_CPPFLAGS = 					\
+	$(WARN_CFLAGS) \
+	$(DEPRECATED_FLAGS) \
+	$(GIO_CFLAGS) \
+	$(LIBANJUTA_CFLAGS) \
+	-DG_LOG_DOMAIN=\"dir-project\"
+
+plugin_LTLIBRARIES = \
+	libdir-project.la
+
+libdir_project_la_SOURCES = \
+	plugin.c \
+	plugin.h \
+	dir-project.c \
+	dir-project.h
+
+libdir_project_la_LDFLAGS = $(ANJUTA_PLUGIN_LDFLAGS)
+
+libdir_project_la_LIBADD = \
+	$(GIO_LIBS) \
+	$(LIBANJUTA_LIBS)
+
+
+EXTRA_DIST = \
+	$(plugin_in_files) \
+	$(plugin_DATA) \
+	$(plugin_ui_DATA) \
+	$(plugin_pixmaps_DATA) \
+	$(plugin_glade_DATA) \
+	$(plugin_data_DATA)
+
+DISTCLEANFILES = \
+	$(plugin_DATA)
+
+-include $(top_srcdir)/git.mk
diff --git a/plugins/dir-project/dir-project-plugin-48.png b/plugins/dir-project/dir-project-plugin-48.png
new file mode 100644
index 0000000..49beafd
Binary files /dev/null and b/plugins/dir-project/dir-project-plugin-48.png differ
diff --git a/plugins/dir-project/dir-project.c b/plugins/dir-project/dir-project.c
new file mode 100644
index 0000000..60c6f3b
--- /dev/null
+++ b/plugins/dir-project/dir-project.c
@@ -0,0 +1,986 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4; coding: utf-8 -*- */
+/* am-project.c
+ *
+ * Copyright (C) 2009  Sébastien Granjoux
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "dir-project.h"
+
+#include <libanjuta/interfaces/ianjuta-project.h>
+#include <libanjuta/anjuta-debug.h>
+#include <libanjuta/anjuta-utils.h>
+
+#include <string.h>
+#include <memory.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <sys/types.h>
+#include <signal.h>
+#include <glib/gi18n.h>
+#include <gio/gio.h>
+#include <glib.h>
+
+#define SOURCES_FILE	PACKAGE_DATA_DIR"/sources.list"
+
+struct _DirProject {
+	GObject         parent;
+
+	GFile			*root_file;
+
+	AnjutaProjectGroup        *root_node;
+	
+	/* shortcut hash tables, mapping id -> GNode from the tree above */
+	GHashTable		*groups;
+	
+	/* project files monitors */
+	GHashTable      *monitors;
+
+	/* List of source files pattern */
+	GList	*sources;
+};
+
+/* convenient shortcut macro the get the AnjutaProjectNode from a GNode */
+#define DIR_NODE_DATA(node)  ((node) != NULL ? (AnjutaProjectNodeData *)((node)->data) : NULL)
+#define DIR_GROUP_DATA(node)  ((node) != NULL ? (DirGroupData *)((node)->data) : NULL)
+#define DIR_TARGET_DATA(node)  ((node) != NULL ? (DirTargetData *)((node)->data) : NULL)
+#define DIR_SOURCE_DATA(node)  ((node) != NULL ? (DirSourceData *)((node)->data) : NULL)
+
+
+typedef struct _DirGroupData DirGroupData;
+
+struct _DirGroupData {
+	AnjutaProjectGroupData base;
+};
+
+typedef struct _DirTargetData DirTargetData;
+
+struct _DirTargetData {
+	AnjutaProjectTargetData base;
+};
+
+typedef struct _DirSourceData DirSourceData;
+
+struct _DirSourceData {
+	AnjutaProjectSourceData base;
+};
+
+/* A file or directory name part of a path */
+typedef struct _DirMatchString DirMatchString;
+
+struct _DirMatchString
+{
+	gchar *string;
+	gchar *reverse;
+	guint length;
+	GFile *file;
+	gboolean parent;
+};
+
+
+/* A pattern used to match a part of a path */
+typedef struct _DirPattern DirPattern;
+
+struct _DirPattern
+{
+	GList *names;
+	gboolean match;
+	gboolean local;
+	gboolean directory;
+};
+
+/* A list of pattern found in one file */
+typedef struct _DirPatternList DirPatternList;
+
+struct _DirPatternList
+{
+	GList *pattern;
+	GFile *directory;
+};
+
+/* ----- Standard GObject types and variables ----- */
+
+enum {
+	PROP_0,
+	PROP_PROJECT_DIR
+};
+
+static GObject *parent_class;
+
+/* Helper functions
+ *---------------------------------------------------------------------------*/
+
+static void
+error_set (GError **error, gint code, const gchar *message)
+{
+        if (error != NULL) {
+                if (*error != NULL) {
+                        gchar *tmp;
+
+                        /* error already created, just change the code
+                         * and prepend the string */
+                        (*error)->code = code;
+                        tmp = (*error)->message;
+                        (*error)->message = g_strconcat (message, "\n\n", tmp, NULL);
+                        g_free (tmp);
+
+                } else {
+                        *error = g_error_new_literal (IANJUTA_PROJECT_ERROR,
+                                                      code,
+                                                      message);
+                }
+        }
+}
+
+/*
+ * File monitoring support --------------------------------
+ * FIXME: review these
+ */
+static void
+monitor_cb (GFileMonitor *monitor,
+			GFile *file,
+			GFile *other_file,
+			GFileMonitorEvent event_type,
+			gpointer data)
+{
+	DirProject *project = data;
+
+	g_return_if_fail (project != NULL && DIR_IS_PROJECT (project));
+
+	switch (event_type) {
+		case G_FILE_MONITOR_EVENT_CHANGED:
+		case G_FILE_MONITOR_EVENT_DELETED:
+			/* monitor will be removed here... is this safe? */
+			dir_project_reload (project, NULL);
+			g_signal_emit_by_name (G_OBJECT (project), "project-updated");
+			break;
+		default:
+			break;
+	}
+}
+
+
+static void
+monitor_add (DirProject *project, GFile *file)
+{
+	GFileMonitor *monitor = NULL;
+	
+	g_return_if_fail (project != NULL);
+	g_return_if_fail (project->monitors != NULL);
+	
+	if (file == NULL)
+		return;
+	
+	monitor = g_hash_table_lookup (project->monitors, file);
+	if (!monitor) {
+		gboolean exists;
+		
+		/* FIXME clarify if uri is uri, path or both */
+		exists = g_file_query_exists (file, NULL);
+		
+		if (exists) {
+			monitor = g_file_monitor_file (file, 
+						       G_FILE_MONITOR_NONE,
+						       NULL,
+						       NULL);
+			if (monitor != NULL)
+			{
+				g_signal_connect (G_OBJECT (monitor),
+						  "changed",
+						  G_CALLBACK (monitor_cb),
+						  project);
+				g_hash_table_insert (project->monitors,
+						     g_object_ref (file),
+						     monitor);
+			}
+		}
+	}
+}
+
+static void
+monitors_remove (DirProject *project)
+{
+	g_return_if_fail (project != NULL);
+
+	if (project->monitors)
+		g_hash_table_destroy (project->monitors);
+	project->monitors = NULL;
+}
+
+static void
+group_hash_foreach_monitor (gpointer key,
+			    gpointer value,
+			    gpointer user_data)
+{
+	DirGroup *group_node = value;
+	DirProject *project = user_data;
+
+	monitor_add (project, DIR_GROUP_DATA(group_node)->base.directory);
+}
+
+static void
+monitors_setup (DirProject *project)
+{
+	g_return_if_fail (project != NULL);
+
+	monitors_remove (project);
+	
+	/* setup monitors hash */
+	project->monitors = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL,
+						   (GDestroyNotify) g_file_monitor_cancel);
+
+	monitor_add (project, project->root_file);
+	
+	if (project->groups)
+		g_hash_table_foreach (project->groups, group_hash_foreach_monitor, project);
+}
+
+static DirGroup*
+dir_group_new (GFile *file)
+{
+    DirGroupData *group = NULL;
+
+	g_return_val_if_fail (file != NULL, NULL);
+	
+	group = g_slice_new0(DirGroupData); 
+	group->base.node.type = ANJUTA_PROJECT_GROUP;
+	group->base.directory = g_object_ref (file);
+
+    return g_node_new (group);
+}
+
+static void
+dir_group_free (DirGroup *node)
+{
+    DirGroupData *group = (DirGroupData *)node->data;
+	
+	if (group->base.directory) g_object_unref (group->base.directory);
+    g_slice_free (DirGroupData, group);
+
+	g_node_destroy (node);
+}
+
+/* Target objects
+ *---------------------------------------------------------------------------*/
+
+static DirTarget*
+dir_target_new (const gchar *name, AnjutaProjectTargetType type)
+{
+    DirTargetData *target = NULL;
+
+	target = g_slice_new0(DirTargetData); 
+	target->base.node.type = ANJUTA_PROJECT_TARGET;
+	target->base.name = g_strdup (name);
+	target->base.type = type;
+
+    return g_node_new (target);
+}
+
+static void
+dir_target_free (DirTarget *node)
+{
+    DirTargetData *target = DIR_TARGET_DATA (node);
+	
+    g_free (target->base.name);
+    g_slice_free (DirTargetData, target);
+
+	g_node_destroy (node);
+}
+
+/* Source objects
+ *---------------------------------------------------------------------------*/
+
+static DirSource*
+dir_source_new (GFile *file)
+{
+    DirSourceData *source = NULL;
+
+	source = g_slice_new0(DirSourceData); 
+	source->base.node.type = ANJUTA_PROJECT_SOURCE;
+	source->base.file = g_object_ref (file);
+
+    return g_node_new (source);
+}
+
+static void
+dir_source_free (DirSource *node)
+{
+    DirSourceData *source = DIR_SOURCE_DATA (node);
+	
+    g_object_unref (source->base.file);
+    g_slice_free (DirSourceData, source);
+
+	g_node_destroy (node);
+}
+
+
+static void
+foreach_node_destroy (AnjutaProjectNode    *g_node,
+		      gpointer  data)
+{
+	switch (DIR_NODE_DATA (g_node)->type) {
+		case ANJUTA_PROJECT_GROUP:
+			dir_group_free (g_node);
+			break;
+		case ANJUTA_PROJECT_TARGET:
+			dir_target_free (g_node);
+			break;
+		case ANJUTA_PROJECT_SOURCE:
+			dir_source_free (g_node);
+			break;
+		default:
+			g_assert_not_reached ();
+			break;
+	}
+}
+
+static void
+project_node_destroy (DirProject *project, AnjutaProjectNode *g_node)
+{
+	g_return_if_fail (project != NULL);
+	g_return_if_fail (DIR_IS_PROJECT (project));
+	
+	if (g_node) {
+		/* free each node's data first */
+		anjuta_project_node_all_foreach (g_node,
+				 foreach_node_destroy, project);
+	}
+}
+
+/* File name objects
+ *---------------------------------------------------------------------------*/
+
+static DirMatchString*
+dir_match_string_new (gchar *string)
+{
+	DirMatchString *str = NULL;
+
+	str = g_slice_new0(DirMatchString);
+	str->length = strlen (string);
+	str->string = string;
+	str->reverse = g_strreverse(g_strdup (string));
+
+	return str;
+}
+
+static void
+dir_match_string_free (DirMatchString *str)
+{
+	g_free (str->string);
+	g_free (str->reverse);
+	if (str->file) g_object_unref (str->file);
+    g_slice_free (DirMatchString, str);
+}
+
+/* Cut a filename is part representing one directory or file name. By example
+ * /home/user/project/foo will be generate a list containing:
+ * foo, project, user, home */
+static GList*
+dir_cut_filename (GFile *file)
+{
+	GList *name_list = NULL;
+
+	g_object_ref (file);
+	do
+	{
+		DirMatchString *str;
+		gchar *name = g_file_get_basename (file);
+
+		if (strcmp(name, G_DIR_SEPARATOR_S) == 0)
+		{
+			g_free (name);
+			g_object_unref (file);
+			break;
+		}
+		
+		str = dir_match_string_new (name);
+		str->file = file;
+
+		name_list = g_list_prepend (name_list, str);
+
+		file = g_file_get_parent (file);
+	}
+	while (file != NULL);
+	
+	name_list = g_list_reverse (name_list);
+	
+	return name_list;
+}
+
+static void
+dir_filename_free (GList *name)
+{
+	g_list_foreach (name, (GFunc)dir_match_string_free, NULL);
+	g_list_free (name);
+}
+
+/* Pattern objects
+ *---------------------------------------------------------------------------*/
+
+/* Create a new pattern matching a directory of a file name in a path */
+ 
+static DirPattern*
+dir_pattern_new (const gchar *pattern, gboolean reverse)
+{
+    DirPattern *pat = NULL;
+	GString *str = g_string_new (NULL);
+	const char *ptr = pattern;
+
+	pat = g_slice_new0(DirPattern);
+	/* Check if it is a reverse pattern */
+	if (*ptr == '!')
+	{
+		pat->match = reverse ? TRUE : FALSE;
+		ptr++;
+	}
+	else
+	{
+		pat->match = reverse ? FALSE : TRUE;
+	}
+	/* Check if the pattern is local */
+	if (*ptr == '/')
+	{
+		pat->local = TRUE;
+		ptr++;
+	}
+	else
+	{
+		pat->local = FALSE;
+	}
+	pat->names = NULL;
+
+	while (*ptr != '\0')
+	{
+		const gchar *next = strchr (ptr, '/');
+
+		if (next == NULL)
+		{
+			pat->names = g_list_prepend (pat->names, g_pattern_spec_new (ptr));
+			break;
+		}
+		else
+		{
+			if (next != ptr)
+			{
+				g_string_overwrite_len (str, 0, ptr, next - ptr);
+				pat->names = g_list_prepend (pat->names, g_pattern_spec_new (str->str));
+			}
+			ptr = next + 1;
+		}
+	}
+	g_string_free (str, TRUE);
+
+	/* Check if the pattern has to match a directory */
+	pat->directory = (ptr != pattern) && (*(ptr-1) == '/');
+
+	return pat;
+}
+
+static void
+dir_pattern_free (DirPattern *pat)
+{
+	g_list_foreach (pat->names, (GFunc)g_pattern_spec_free, NULL);
+	g_list_free (pat->names);
+	
+    g_slice_free (DirPattern, pat);
+}
+
+/* Read a file containing pattern, the syntax is similar to .gitignore file.
+ * 
+ * It is not a regular expression, only * and ? are used as joker.
+ * If the name end with / it will match only a directory.
+ * If the name starts with / it must be relative to the project directory, so
+ * by example /.git/ will match only a directory named .git in the project
+ * directory, while CVS/ will match a directory named CVS anywhere in the
+ * project.
+ * If the name starts with ! the meaning is reversed. In a file containing
+ * matching file, if a pattern starting ! matches, it means that the file has
+ * to be removed from the matching list.
+ * All pattern are read in order, so it is possible to match a group of files
+ * and add pattern afterward to remove some of these files.
+ * A name starting with # is a comment.
+ * All spaces at the beginning of a name are ignored.
+ */
+static GList*
+dir_push_pattern_list (GList *stack, GFile *dir, GFile *file, gboolean ignore, GError **error)
+{
+	char *content;
+	char *ptr;
+	DirPatternList *list = NULL;
+	
+
+	if (!g_file_load_contents (file, NULL, &content, NULL, NULL, error))
+	{
+		return stack;
+	}
+
+	list = g_slice_new0(DirPatternList);
+	list->pattern = NULL;
+	list->directory = dir;
+
+	for (ptr = content; *ptr != '\0';)
+	{
+		gchar *next;
+		
+		next = strchr (ptr, '\n');
+		if (next != NULL) *next = '\0';
+
+		/* Discard space at the beginning */
+		while (isspace (*ptr)) ptr++;
+
+		if ((*ptr != '#') && (ptr != next))
+		{
+			/* Create pattern */
+			DirPattern *pat = NULL;
+
+			if (next != NULL) *next = '\0';
+			pat = dir_pattern_new (ptr, ignore);
+			list->pattern = g_list_prepend (list->pattern, pat);
+		}
+
+		if (next == NULL) break;
+		ptr = next + 1;
+	}
+	g_free (content);
+
+	list->pattern = g_list_reverse (list->pattern);
+	
+	return g_list_prepend (stack, list);
+}
+
+static GList *
+dir_pop_pattern_list (GList *stack)
+{
+	DirPatternList *top = (DirPatternList *)stack->data;
+
+	stack = g_list_remove_link (stack, stack);
+
+	g_list_foreach (top->pattern, (GFunc)dir_pattern_free, NULL);
+	g_list_free (top->pattern);
+	g_object_unref (top->directory);
+    g_slice_free (DirPatternList, top);
+
+	return stack;
+}
+
+static gboolean
+dir_pattern_stack_is_match (GList *stack, GFile *file)
+{
+	gboolean match;
+	GList *list;
+	GList *name_list;
+	gboolean directory;
+
+	/* Create name list from file */
+	name_list = dir_cut_filename (file);
+	
+	directory = g_file_query_file_type (file, G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, NULL) == G_FILE_TYPE_DIRECTORY;
+	/* Include directories by default */
+	match = directory;
+
+	/* Check all valid patterns */
+	for (list = g_list_last (stack); list != NULL; list = g_list_previous (list))
+	{
+		DirPatternList *pat_list = (DirPatternList *)list->data;
+		GList *node;
+
+		/* Mark parent level */
+		for (node = g_list_first (name_list); node != NULL; node = g_list_next (node))
+		{
+			DirMatchString *str = (DirMatchString *)node->data;
+
+			str->parent = g_file_equal (pat_list->directory, str->file);
+		}
+
+		for (node = g_list_first (pat_list->pattern); node != NULL; node = g_list_next (node))
+		{
+			DirPattern *pat = (DirPattern *)node->data;
+			GList *pat_part;
+			GList *name_part;
+			gboolean match_part;
+
+			if (pat->directory && !directory)
+				continue;
+
+			name_part = g_list_first (name_list);
+			for (pat_part = g_list_first (pat->names); pat_part != NULL; pat_part = g_list_next (pat_part))
+			{
+				DirMatchString *part = (DirMatchString *)name_part->data;
+				match_part = g_pattern_match ((GPatternSpec *)pat_part->data, part->length, part->string, part->reverse);
+
+				if (!match_part) break;
+				name_part = g_list_next (name_part);
+			}
+
+			/* Local match are relative to parent directory only */
+			if (match_part && pat->local && (!((DirMatchString *)name_part->data)->parent)) match_part = FALSE;
+
+			if (match_part)	match = pat->match;
+		}
+	}
+
+	dir_filename_free (name_list);
+
+	return match;
+}
+
+static gboolean
+dir_project_list_directory (DirProject *project, DirGroup* parent, GError **error) 
+{
+	gboolean ok;
+	GFileEnumerator *enumerator;
+
+	enumerator = g_file_enumerate_children (DIR_GROUP_DATA (parent)->base.directory,
+	    G_FILE_ATTRIBUTE_STANDARD_NAME,
+	    G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
+	    NULL,
+	    error);
+
+	ok = enumerator != NULL;
+	if (ok)
+	{
+		GFileInfo *info;
+		
+		while ((info = g_file_enumerator_next_file (enumerator, NULL, error)) != NULL)
+		{
+			const gchar *name;
+			GFile *file;
+
+			name = g_file_info_get_name (info);
+			file = g_file_get_child (DIR_GROUP_DATA (parent)->base.directory, name);
+			g_object_unref (info);
+
+			/* Check if file is a source */
+			if (!dir_pattern_stack_is_match (project->sources, file)) continue;
+			
+			if (g_file_query_file_type (file, G_FILE_QUERY_INFO_NONE, NULL) == G_FILE_TYPE_DIRECTORY)
+			{
+				/* Create a group for directory */
+				DirGroup *group;
+				
+				group = dir_group_new (file);
+				g_hash_table_insert (project->groups, g_file_get_uri (file), group);
+				anjuta_project_node_append (parent, group);
+				ok = dir_project_list_directory (project, group, error);
+				if (!ok) break;
+			}
+			else
+			{
+				/* Create a source for files */
+				DirSource *source;
+
+				source = dir_source_new (file);
+				anjuta_project_node_append (parent, source);
+			}
+		}
+        g_file_enumerator_close (enumerator, NULL, NULL);
+        g_object_unref (enumerator);
+	}
+
+	return ok;
+}
+
+/* Public functions
+ *---------------------------------------------------------------------------*/
+
+gboolean
+dir_project_reload (DirProject *project, GError **error) 
+{
+	GFile *root_file;
+	GFile *source_file;
+	DirGroup *group;
+	gboolean ok = TRUE;
+
+	/* Unload current project */
+	root_file = g_object_ref (project->root_file);
+	dir_project_unload (project);
+	project->root_file = root_file;
+	DEBUG_PRINT ("reload project %p root file %p", project, project->root_file);
+
+	/* shortcut hash tables */
+	project->groups = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
+
+	if (g_file_query_file_type (root_file, G_FILE_QUERY_INFO_NONE, NULL) != G_FILE_TYPE_DIRECTORY)
+	{
+		g_set_error (error, IANJUTA_PROJECT_ERROR, 
+		             IANJUTA_PROJECT_ERROR_DOESNT_EXIST,
+			   _("Project doesn't exist or invalid path"));
+
+		return FALSE;
+	}
+
+	group = dir_group_new (root_file);
+	g_hash_table_insert (project->groups, g_file_get_uri (root_file), group);
+	project->root_node = group;
+
+	/* Load source pattern */
+	source_file = g_file_new_for_path (SOURCES_FILE);
+	project->sources = dir_push_pattern_list (NULL, g_object_ref (root_file), source_file, FALSE, NULL);
+	g_object_unref (source_file);
+	
+	dir_project_list_directory (project, group, NULL);
+	
+	monitors_setup (project);
+	
+	return ok;
+}
+
+gboolean
+dir_project_load (DirProject  *project,
+    GFile *directory,
+	GError     **error)
+{
+	g_return_val_if_fail (directory != NULL, FALSE);
+
+	project->root_file = g_object_ref (directory);
+	if (!dir_project_reload (project, error))
+	{
+		g_object_unref (project->root_file);
+		project->root_file = NULL;
+	}
+
+	return project->root_file != NULL;
+}
+
+void
+dir_project_unload (DirProject *project)
+{
+	monitors_remove (project);
+	
+	/* project data */
+	project_node_destroy (project, project->root_node);
+	project->root_node = NULL;
+
+	if (project->root_file) g_object_unref (project->root_file);
+	project->root_file = NULL;
+
+	/* shortcut hash tables */
+	if (project->groups) g_hash_table_destroy (project->groups);
+	project->groups = NULL;
+
+	/* sources patterns */
+	while (project->sources)
+	{
+		project->sources = dir_pop_pattern_list (project->sources);
+	}
+}
+
+gint
+dir_project_probe (GFile *file,
+	    GError     **error)
+{
+	gint probe;
+
+	probe = g_file_query_file_type (file, G_FILE_QUERY_INFO_NONE, NULL) == G_FILE_TYPE_DIRECTORY;
+	if (!probe)
+	{
+		g_set_error (error, IANJUTA_PROJECT_ERROR, 
+		             IANJUTA_PROJECT_ERROR_DOESNT_EXIST,
+			   _("Project doesn't exist or invalid path"));
+	}
+
+	return probe ? IANJUTA_PROJECT_PROBE_FILES : 0;
+}
+
+static DirGroup* 
+dir_project_add_group (DirProject  *project,
+		DirGroup *parent,
+		const gchar *name,
+		GError     **error)
+{
+	return NULL;
+}
+
+static DirTarget*
+dir_project_add_target (DirProject  *project,
+		 DirGroup *parent,
+		 const gchar *name,
+		 AnjutaProjectTargetType type,
+		 GError     **error)
+{
+	return NULL;
+}
+
+static DirSource* 
+dir_project_add_source (DirProject  *project,
+		 DirTarget *target,
+		 GFile *file,
+		 GError     **error)
+{
+	return NULL;
+}
+
+static GList *
+dir_project_get_target_types (DirProject *project, GError **error)
+{
+	static AnjutaProjectTargetInformation unknown_type = {N_("Unknown"), ANJUTA_TARGET_UNKNOWN,"text/plain"};
+
+	return g_list_prepend (NULL, &unknown_type);
+}
+
+static DirGroup *
+dir_project_get_root (DirProject *project)
+{
+	return project->root_node;
+}
+
+
+/* Public functions
+ *---------------------------------------------------------------------------*/
+
+DirProject *
+dir_project_new (void)
+{
+	return DIR_PROJECT (g_object_new (DIR_TYPE_PROJECT, NULL));
+}
+
+
+/* Implement IAnjutaProject
+ *---------------------------------------------------------------------------*/
+
+static AnjutaProjectGroup* 
+iproject_add_group (IAnjutaProject *obj, AnjutaProjectGroup *parent,  const gchar *name, GError **err)
+{
+	return dir_project_add_group (DIR_PROJECT (obj), parent, name, err);
+}
+
+static AnjutaProjectSource* 
+iproject_add_source (IAnjutaProject *obj, AnjutaProjectGroup *parent,  GFile *file, GError **err)
+{
+	return dir_project_add_source (DIR_PROJECT (obj), parent, file, err);
+}
+
+static AnjutaProjectTarget* 
+iproject_add_target (IAnjutaProject *obj, AnjutaProjectGroup *parent,  const gchar *name,  AnjutaProjectTargetType type, GError **err)
+{
+	return dir_project_add_target (DIR_PROJECT (obj), parent, name, type, err);
+}
+
+static GtkWidget* 
+iproject_configure (IAnjutaProject *obj, GError **err)
+{
+	return NULL;
+}
+
+static guint 
+iproject_get_capabilities (IAnjutaProject *obj, GError **err)
+{
+	return IANJUTA_PROJECT_CAN_ADD_NONE;
+}
+
+static GList* 
+iproject_get_packages (IAnjutaProject *obj, GError **err)
+{
+	return NULL;
+}
+
+static AnjutaProjectGroup* 
+iproject_get_root (IAnjutaProject *obj, GError **err)
+{
+	return dir_project_get_root (DIR_PROJECT (obj));
+}
+
+static GList* 
+iproject_get_target_types (IAnjutaProject *obj, GError **err)
+{
+	return dir_project_get_target_types (DIR_PROJECT (obj), err);
+}
+
+static gboolean
+iproject_load (IAnjutaProject *obj, GFile *file, GError **err)
+{
+	return dir_project_load (DIR_PROJECT (obj), file, err);
+}
+
+static gboolean
+iproject_refresh (IAnjutaProject *obj, GError **err)
+{
+	return dir_project_reload (DIR_PROJECT (obj), err);
+}
+
+static gboolean
+iproject_remove_node (IAnjutaProject *obj, AnjutaProjectNode *node, GError **err)
+{
+	return TRUE;
+}
+
+static void
+iproject_iface_init(IAnjutaProjectIface* iface)
+{
+	iface->add_group = iproject_add_group;
+	iface->add_source = iproject_add_source;
+	iface->add_target = iproject_add_target;
+	iface->configure = iproject_configure;
+	iface->get_capabilities = iproject_get_capabilities;
+	iface->get_packages = iproject_get_packages;
+	iface->get_root = iproject_get_root;
+	iface->get_target_types = iproject_get_target_types;
+	iface->load = iproject_load;
+	iface->refresh = iproject_refresh;
+	iface->remove_node = iproject_remove_node;
+}
+
+/* GbfProject implementation
+ *---------------------------------------------------------------------------*/
+
+static void
+dir_project_dispose (GObject *object)
+{
+	g_return_if_fail (DIR_IS_PROJECT (object));
+
+	dir_project_unload (DIR_PROJECT (object));
+
+	G_OBJECT_CLASS (parent_class)->dispose (object);	
+}
+
+static void
+dir_project_instance_init (DirProject *project)
+{
+	g_return_if_fail (project != NULL);
+	g_return_if_fail (DIR_IS_PROJECT (project));
+	
+	/* project data */
+	project->root_file = NULL;
+	project->root_node = NULL;
+
+	project->monitors = NULL;
+	project->groups = NULL;
+
+	project->sources = NULL;
+}
+
+static void
+dir_project_class_init (DirProjectClass *klass)
+{
+	GObjectClass *object_class;
+	
+	parent_class = g_type_class_peek_parent (klass);
+
+	object_class = G_OBJECT_CLASS (klass);
+	object_class->dispose = dir_project_dispose;
+}
+
+ANJUTA_TYPE_BEGIN(DirProject, dir_project, G_TYPE_OBJECT);
+ANJUTA_TYPE_ADD_INTERFACE(iproject, IANJUTA_TYPE_PROJECT);
+ANJUTA_TYPE_END;
diff --git a/plugins/dir-project/dir-project.h b/plugins/dir-project/dir-project.h
new file mode 100644
index 0000000..b7202df
--- /dev/null
+++ b/plugins/dir-project/dir-project.h
@@ -0,0 +1,122 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4; coding: utf-8 -*- */
+/* am-project.h
+ *
+ * Copyright (C) 2009  Sébastien Granjoux
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _DIR_PROJECT_H_
+#define _DIR_PROJECT_H_
+
+#include <glib-object.h>
+
+#include <libanjuta/anjuta-project.h>
+
+G_BEGIN_DECLS
+
+#define DIR_TYPE_PROJECT			(dir_project_get_type ())
+#define DIR_PROJECT(obj)			(G_TYPE_CHECK_INSTANCE_CAST ((obj), DIR_TYPE_PROJECT, DirProject))
+#define DIR_PROJECT_CLASS(klass)	(G_TYPE_CHECK_CLASS_CAST ((klass), DIR_TYPE_PROJECT, DirProjectClass))
+#define DIR_IS_PROJECT(obj)			(G_TYPE_CHECK_INSTANCE_TYPE ((obj), DIR_TYPE_PROJECT))
+#define DIR_IS_PROJECT_CLASS(klass)	(G_TYPE_CHECK_CLASS_TYPE ((obj), DIR_TYPE_PROJECT))
+
+#define DIR_GROUP(obj)		((DirGroup *)obj)
+#define DIR_TARGET(obj)		((DirTarget *)obj)
+#define DIR_SOURCE(obj)		((DirSource *)obj)
+
+
+typedef struct _DirProject        DirProject;
+typedef struct _DirProjectClass   DirProjectClass;
+
+struct _DirProjectClass {
+	GObjectClass parent_class;
+};
+
+typedef AnjutaProjectGroup DirGroup;
+typedef AnjutaProjectTarget DirTarget;
+typedef AnjutaProjectSource DirSource;
+
+
+GType         dir_project_get_type (void);
+DirProject   *dir_project_new      (void);
+
+gint dir_project_probe (GFile *directory, GError     **error);
+
+gboolean dir_project_load (DirProject *project, GFile *directory, GError **error);
+gboolean dir_project_reload (DirProject *project, GError **error);
+void dir_project_unload (DirProject *project);
+
+#if 0
+AmpGroup *amp_project_get_root (AmpProject *project);
+AmpGroup *amp_project_get_group (AmpProject *project, const gchar *id);
+AmpTarget *amp_project_get_target (AmpProject *project, const gchar *id);
+AmpSource *amp_project_get_source (AmpProject *project, const gchar *id);
+gboolean amp_project_get_token_location (AmpProject *project, AnjutaTokenFileLocation *location, AnjutaToken *token);
+
+gboolean amp_project_move (AmpProject *project, const gchar *path);
+gboolean amp_project_save (AmpProject *project, GError **error);
+
+gchar * amp_project_get_uri (AmpProject *project);
+GFile* amp_project_get_file (AmpProject *project);
+
+AmpGroup* amp_project_add_group (AmpProject  *project, AmpGroup *parent, const gchar *name, GError **error);
+AmpGroup* amp_project_add_sibling_group (AmpProject  *project, AmpGroup *parent, const gchar *name, gboolean after, AmpGroup *sibling, GError **error);
+void amp_project_remove_group (AmpProject  *project, AmpGroup *group, GError **error);
+
+AmpTarget* amp_project_add_target (AmpProject  *project, AmpGroup *parent, const gchar *name, AnjutaProjectTargetType type, GError **error);
+AmpTarget* amp_project_add_sibling_target (AmpProject  *project, AmpGroup *parent, const gchar *name, AnjutaProjectTargetType type, gboolean after, AmpTarget *sibling, GError **error);
+void amp_project_remove_target (AmpProject  *project, AmpTarget *target, GError **error);
+
+AmpSource* amp_project_add_source (AmpProject  *project, AmpTarget *parent, GFile *file, GError **error);
+AmpSource* amp_project_add_sibling_source (AmpProject  *project, AmpTarget *parent, GFile *file, gboolean after, AmpSource *sibling, GError **error);
+void amp_project_remove_source (AmpProject  *project, AmpSource *source, GError **error);
+
+
+GList *amp_project_get_config_modules (AmpProject *project, GError **error);
+GList *amp_project_get_config_packages  (AmpProject *project, const gchar* module, GError **error);
+
+GList *amp_project_get_target_types (AmpProject *project, GError **error);
+
+gchar* amp_project_get_property (AmpProject *project, AmpPropertyType type);
+gboolean amp_project_set_property (AmpProject *project, AmpPropertyType type, const gchar* value);
+
+gchar * amp_project_get_node_id (AmpProject *project, const gchar *path);
+
+AnjutaProjectNode *amp_node_parent (AnjutaProjectNode *node);
+AnjutaProjectNode *amp_node_first_child (AnjutaProjectNode *node);
+AnjutaProjectNode *amp_node_last_child (AnjutaProjectNode *node);
+AnjutaProjectNode *amp_node_next_sibling (AnjutaProjectNode *node);
+AnjutaProjectNode *amp_node_prev_sibling (AnjutaProjectNode *node);
+AnjutaProjectNodeType amp_node_get_type (AnjutaProjectNode *node);
+void amp_node_all_foreach (AnjutaProjectNode *node, AnjutaProjectNodeFunc func, gpointer data);
+
+GFile *amp_group_get_directory (AmpGroup *group);
+GFile *amp_group_get_makefile (AmpGroup *group);
+gchar *amp_group_get_id (AmpGroup *group);
+
+const gchar *amp_target_get_name (AmpTarget *target);
+AnjutaProjectTargetType amp_target_get_type (AmpTarget *target);
+gchar *amp_target_get_id (AmpTarget *target);
+
+void amp_source_free (AmpSource *node);
+gchar *amp_source_get_id (AmpSource *source);
+GFile *amp_source_get_file (AmpSource *source);
+#endif
+
+G_END_DECLS
+
+#endif /* _DIR_PROJECT_H_ */
diff --git a/plugins/dir-project/dir-project.plugin.in b/plugins/dir-project/dir-project.plugin.in
new file mode 100644
index 0000000..36be02d
--- /dev/null
+++ b/plugins/dir-project/dir-project.plugin.in
@@ -0,0 +1,11 @@
+[Anjuta Plugin]
+_Name=Directory backend
+_Description=Directory project backend, get only source files, use it when other backend fails
+Location=dir-project:DirProjectPlugin
+Icon=dir-project-plugin-48.png
+Interfaces=IAnjutaProjectBackend
+Dependencies=anjuta-project-manager:ProjectManagerPlugin
+UserActivatable=no
+
+[Project]
+Supported-Project-Types=directory
diff --git a/plugins/dir-project/plugin.c b/plugins/dir-project/plugin.c
new file mode 100644
index 0000000..ab9d8d6
--- /dev/null
+++ b/plugins/dir-project/plugin.c
@@ -0,0 +1,126 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
+/*
+    plugin.c
+    Copyright (C) 2009 Sébastien Granjoux
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#include <config.h>
+#include <libanjuta/anjuta-debug.h>
+#include <libanjuta/gbf-project.h>
+#include <libanjuta/interfaces/ianjuta-project-backend.h>
+
+#include "plugin.h"
+#include "dir-project.h"
+
+
+#define ICON_FILE "dir-project-plugin-48.png"
+
+/* AnjutaPlugin functions
+ *---------------------------------------------------------------------------*/
+
+static gboolean
+activate_plugin (AnjutaPlugin *plugin)
+{
+	DEBUG_PRINT ("DirProjectPlugin: Activating Anjuta directory backend Plugin ...");
+	
+	return TRUE;
+}
+
+static gboolean
+deactivate_plugin (AnjutaPlugin *plugin)
+{
+	DEBUG_PRINT ("DirProjectPlugin: Deacctivating Anjuta directory backend Plugin ...");
+	return TRUE;
+}
+
+
+/* IAnjutaProjectBackend implementation
+ *---------------------------------------------------------------------------*/
+
+static IAnjutaProject*
+iproject_backend_new_project (IAnjutaProjectBackend* backend, GError** err)
+{
+	IAnjutaProject *project;
+	DEBUG_PRINT("create new directory project");	
+	project = (IAnjutaProject *)(g_object_new (DIR_TYPE_PROJECT, NULL));
+		
+	return project;
+}
+
+static gint
+iproject_backend_probe (IAnjutaProjectBackend* backend, GFile *directory, GError** err)
+{
+	DEBUG_PRINT("probe directory project");
+	
+	return dir_project_probe (directory, err);
+}
+
+static void
+iproject_backend_iface_init(IAnjutaProjectBackendIface *iface)
+{
+	iface->new_project = iproject_backend_new_project;
+	iface->probe = iproject_backend_probe;
+}
+
+/* GObject functions
+ *---------------------------------------------------------------------------*/
+
+/* Used in dispose and finalize */
+static gpointer parent_class;
+
+static void
+dir_project_plugin_instance_init (GObject *obj)
+{
+}
+
+/* dispose is used to unref object created with instance_init */
+
+static void
+dispose (GObject *obj)
+{
+	G_OBJECT_CLASS (parent_class)->dispose (obj);
+}
+
+/* finalize used to free object created with instance init */
+
+static void
+finalize (GObject *obj)
+{
+	G_OBJECT_CLASS (parent_class)->finalize (obj);
+}
+
+static void
+dir_project_plugin_class_init (GObjectClass *klass) 
+{
+	AnjutaPluginClass *plugin_class = ANJUTA_PLUGIN_CLASS (klass);
+
+	parent_class = g_type_class_peek_parent (klass);
+
+	plugin_class->activate = activate_plugin;
+	plugin_class->deactivate = deactivate_plugin;
+	klass->dispose = dispose;
+	klass->finalize = finalize;
+}
+
+/* AnjutaPlugin declaration
+ *---------------------------------------------------------------------------*/
+
+ANJUTA_PLUGIN_BEGIN (DirProjectPlugin, dir_project_plugin);
+ANJUTA_PLUGIN_ADD_INTERFACE (iproject_backend, IANJUTA_TYPE_PROJECT_BACKEND);
+ANJUTA_PLUGIN_END;
+
+ANJUTA_SIMPLE_PLUGIN (DirProjectPlugin, dir_project_plugin);
diff --git a/plugins/dir-project/plugin.h b/plugins/dir-project/plugin.h
new file mode 100644
index 0000000..87d4943
--- /dev/null
+++ b/plugins/dir-project/plugin.h
@@ -0,0 +1,47 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
+/*
+    plugin.h
+    Copyright (C) 2009 Sébastien Granjoux
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef __PLUGIN_H__
+#define __PLUGIN_H__
+
+#include <libanjuta/anjuta-plugin.h>
+
+extern GType dir_project_plugin_get_type (GTypeModule *module);
+#define ANJUTA_TYPE_PLUGIN_DIR_PROJECT         (dir_project_plugin_get_type (NULL))
+#define ANJUTA_PLUGIN_DIR_PROJECT(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o), ANJUTA_TYPE_PLUGIN_DIR_PROJECT, DirProjectPlugin))
+#define ANJUTA_PLUGIN_DIR_PROJECT_CLASS(k)     (G_TYPE_CHECK_CLASS_CAST ((k), ANJUTA_TYPE_PLUGIN_DIR_PROJECT, DirProjectPluginClass))
+#define ANJUTA_IS_PLUGIN_DIR_PROJECT(o)        (G_TYPE_CHECK_INSTANCE_TYPE ((o), ANJUTA_TYPE_PLUGIN_DIR_PROJECT))
+#define ANJUTA_IS_PLUGIN_DIR_PROJECT_CLASS(k)  (G_TYPE_CHECK_CLASS_TYPE ((k), ANJUTA_TYPE_PLUGIN_DIR_PROJECT))
+#define ANJUTA_PLUGIN_DIR_PROJECT_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), ANJUTA_TYPE_PLUGIN_DIR_PROJECT, DirProjectPluginClass))
+
+typedef struct _DirProjectPlugin DirProjectPlugin;
+typedef struct _DirProjectPluginClass DirProjectPluginClass;
+
+struct _DirProjectPlugin 
+{
+	AnjutaPlugin parent;
+};
+
+struct _DirProjectPluginClass
+{
+	AnjutaPluginClass parent_class;
+};
+
+#endif
diff --git a/plugins/dir-project/sources.list b/plugins/dir-project/sources.list
new file mode 100644
index 0000000..50371cf
--- /dev/null
+++ b/plugins/dir-project/sources.list
@@ -0,0 +1,19 @@
+*.c
+*.h
+*.C
+*.cpp
+*.hpp
+*.cxx
+*.c++
+*.cc
+*.java
+*.py
+*.pl
+*.rb
+*.y
+*.l
+*.in
+*.in.in
+*.am
+!CVS/
+!.*/
diff --git a/plugins/project-import/plugin.c b/plugins/project-import/plugin.c
index 44d9c21..1d85652 100644
--- a/plugins/project-import/plugin.c
+++ b/plugins/project-import/plugin.c
@@ -27,7 +27,6 @@
 #include <libanjuta/interfaces/ianjuta-file-loader.h>
 #include <libanjuta/interfaces/ianjuta-project-backend.h>
 #include <libanjuta/interfaces/ianjuta-vcs.h>
-#include <libanjuta/gbf-project.h>
 #include <libanjuta/anjuta-async-notify.h>
 
 #include "plugin.h"
@@ -37,6 +36,7 @@
 
 #define AM_PROJECT_FILE PACKAGE_DATA_DIR"/project/terminal/project.anjuta"
 #define MKFILE_PROJECT_FILE PACKAGE_DATA_DIR"/project/mkfile/project.anjuta"
+#define DIRECTORY_PROJECT_FILE PACKAGE_DATA_DIR"/project/directory/project.anjuta"
 
 static gpointer parent_class;
 
@@ -54,6 +54,8 @@ project_import_generate_file (AnjutaProjectImportPlugin* import_plugin, ProjectI
 		source_file = g_file_new_for_path (AM_PROJECT_FILE);
 	else if (!strcmp (import_plugin->backend_id, "make"))
 		source_file = g_file_new_for_path (MKFILE_PROJECT_FILE);
+	else if (!strcmp (import_plugin->backend_id, "directory"))
+		source_file = g_file_new_for_path (DIRECTORY_PROJECT_FILE);
 	else
 	{
 		/* We shouldn't get here, unless someone has upgraded their GBF */
@@ -153,47 +155,61 @@ project_import_import_project (AnjutaProjectImportPlugin *import_plugin, Project
 	GList *desc;
 	AnjutaPluginDescription *backend;
 	gchar *name, *project_file_name;
-	
+
+	/* Search for all valid project backend */
 	plugin_manager = anjuta_shell_get_plugin_manager (ANJUTA_PLUGIN(import_plugin)->shell, NULL);
 	descs = anjuta_plugin_manager_query (plugin_manager,
 										 "Anjuta Plugin",
 										 "Interfaces",
 										 "IAnjutaProjectBackend",
 										 NULL);	
-	for (desc = g_list_first (descs); desc != NULL; desc = g_list_next (desc)) {
+	for (desc = g_list_first (descs); desc != NULL;) {
 		IAnjutaProjectBackend *plugin;
 		gchar *location = NULL;
-		GbfProject* proj;	
+		GList *next;
 		
 		backend = (AnjutaPluginDescription *)desc->data;
 		anjuta_plugin_description_get_string (backend, "Anjuta Plugin", "Location", &location);
 		plugin = (IAnjutaProjectBackend *)anjuta_plugin_manager_get_plugin_by_id (plugin_manager, location);
 		g_free (location);
 
-		/* Probe the backend to find out if the project directory is OK */
-		/* If probe() returns TRUE then we have a valid backend */
+		next = g_list_next (desc);
 		
-		proj= ianjuta_project_backend_new_project (plugin, NULL);
-		if (proj)
+		/* Probe the project directory to find if the backend can handle it */
+		if (ianjuta_project_backend_probe (plugin, source_dir, NULL) <= 0)
 		{
-			gchar *path;
-
-			path = g_file_get_path (source_dir);
-			if (gbf_project_probe (proj, path, NULL))
-			{
-				/* This is a valid backend for this root directory */
-				/* FIXME: Possibility of more than one valid backend? */
-				break;
-			}
-			g_object_unref (proj);
-			g_free (path);
+			/* Remove invalid backend */
+			descs = g_list_delete_link (descs, desc);
 		}
-		plugin = NULL;
+
+		desc = next;
+	}
+
+	if (descs == NULL)
+	{
 		backend = NULL;
 	}
+	else if (g_list_next (descs) == NULL)
+	{
+		backend =  (AnjutaPluginDescription *)descs->data;
+	}
+	else
+	{
+		/* Several backend are possible, ask the user to select one */
+		gchar *path = project_import_dialog_get_name (import_dialog);
+		gchar* message = g_strdup_printf (_("Please select a project backend to open %s."), path);
+		
+		g_free (path);
+		
+        backend = anjuta_plugin_manager_select (plugin_manager,
+		    _("Open With"),
+		    message,
+		    descs);
+		g_free (message);
+	}
 	g_list_free (descs);
-	
-	if (!backend)
+
+	if (backend == NULL)
 	{
 		gchar *path = project_import_dialog_get_name (import_dialog);
 
diff --git a/plugins/project-manager/plugin.c b/plugins/project-manager/plugin.c
index de5b764..408a08a 100644
--- a/plugins/project-manager/plugin.c
+++ b/plugins/project-manager/plugin.c
@@ -1159,9 +1159,9 @@ project_manager_load_gbf (ProjectManagerPlugin *pm_plugin)
 	gchar *basename;
 	const gchar *root_uri;
 	GError *error = NULL;
-	GList *descs = NULL;
 	GList *desc;
 	IAnjutaProjectBackend *backend;
+	gint found = 0;
 	
 	root_uri = pm_plugin->project_root_uri;
 	
@@ -1175,28 +1175,47 @@ project_manager_load_gbf (ProjectManagerPlugin *pm_plugin)
 	
 	DEBUG_PRINT ("loading gbf backendâ?¦\n");
 	plugin_manager = anjuta_shell_get_plugin_manager (ANJUTA_PLUGIN(pm_plugin)->shell, NULL);
-	descs = anjuta_plugin_manager_query (plugin_manager,
-										 "Anjuta Plugin",
-										 "Interfaces",
-										 "IAnjutaProjectBackend",
-										 NULL);
-	for (desc = g_list_first (descs); desc != NULL; desc = g_list_next (desc)) {
-		AnjutaPluginDescription *backend_desc;
-		gchar *location = NULL;
-		
-		backend_desc = (AnjutaPluginDescription *)desc->data;
-		anjuta_plugin_description_get_string (backend_desc, "Anjuta Plugin", "Location", &location);
-		backend = (IAnjutaProjectBackend *)anjuta_plugin_manager_get_plugin_by_id (plugin_manager, location);
-		g_free (location);
 
-		if (ianjuta_project_backend_probe (backend, dirfile, NULL))
-		{
-			/* Backend found */
-			break;
-		}
+	if (!anjuta_plugin_manager_is_active_plugin (plugin_manager, "IAnjutaProjectBackend"))
+	{
+		GList *descs = NULL;
+		
+		descs = anjuta_plugin_manager_query (plugin_manager,
+											 "Anjuta Plugin",
+											 "Interfaces",
+											 "IAnjutaProjectBackend",
+											 NULL);
 		backend = NULL;
+		for (desc = g_list_first (descs); desc != NULL; desc = g_list_next (desc)) {
+			AnjutaPluginDescription *backend_desc;
+			gchar *location = NULL;
+			IAnjutaProjectBackend *plugin;
+			gint backend_val;
+				
+			backend_desc = (AnjutaPluginDescription *)desc->data;
+			anjuta_plugin_description_get_string (backend_desc, "Anjuta Plugin", "Location", &location);
+			plugin = (IAnjutaProjectBackend *)anjuta_plugin_manager_get_plugin_by_id (plugin_manager, location);
+			g_message ("search plugin %s", location);
+			g_free (location);
+
+			backend_val = ianjuta_project_backend_probe (plugin, dirfile, NULL);
+			if (backend_val > found)
+			{
+				/* Backend found */;
+				backend = plugin;
+				found = backend_val;
+			}
+		}
+		g_list_free (descs);
+	}
+	else
+	{
+		/* A backend is already loaded, use it */
+		backend = IANJUTA_PROJECT_BACKEND (anjuta_shell_get_object (ANJUTA_PLUGIN (pm_plugin)->shell,
+                                        "IAnjutaProjectBackend", NULL));
+
+        g_object_ref (backend);
 	}
-	g_list_free (descs);
 	
 	if (!backend)
 	{
diff --git a/plugins/project-wizard/templates/Makefile.am b/plugins/project-wizard/templates/Makefile.am
index 094cd50..fddc392 100644
--- a/plugins/project-wizard/templates/Makefile.am
+++ b/plugins/project-wizard/templates/Makefile.am
@@ -1,7 +1,7 @@
 
 SUBDIRS = minimal terminal cpp gtk anjuta-plugin \
 	gtkmm wxwin xlib xlib-dock gcj java gnome-applet\
-	python mkfile sdl library licenses m4 js_minimal
+	python mkfile sdl library directory licenses m4 js_minimal
 
 wizard_filesdir = $(anjuta_data_dir)/project
 wizard_files_DATA = \
diff --git a/plugins/project-wizard/templates/directory/Makefile.am b/plugins/project-wizard/templates/directory/Makefile.am
new file mode 100644
index 0000000..ffb141a
--- /dev/null
+++ b/plugins/project-wizard/templates/directory/Makefile.am
@@ -0,0 +1,8 @@
+
+wizard_filesdir = $(anjuta_data_dir)/project/directory
+wizard_files_DATA = \
+	project.anjuta
+
+EXTRA_DIST = $(wizard_files_DATA)
+
+-include $(top_srcdir)/git.mk
diff --git a/plugins/project-wizard/templates/directory/project.anjuta b/plugins/project-wizard/templates/directory/project.anjuta
new file mode 100644
index 0000000..dd12c27
--- /dev/null
+++ b/plugins/project-wizard/templates/directory/project.anjuta
@@ -0,0 +1,51 @@
+<?xml version="1.0"?>
+<anjuta>
+	<plugin name="GBF Project Manager"
+            url="http://anjuta.org/plugins/";
+            mandatory="yes">
+		<require group="Anjuta Plugin"
+                 attribute="Interfaces"
+                 value="IAnjutaProjectManager"/>
+	</plugin>
+	<plugin name="Directory Project Backend"
+            url="http://anjuta.org/plugins/";
+            mandatory="yes">
+		<require group="Anjuta Plugin"
+                 attribute="Interfaces"
+                 value="IAnjutaProjectBackend"/>
+		<require group="Project"
+                 attribute="Supported-Project-Types"
+                 value="directory"/>
+	</plugin>
+	<plugin name="Symbol Browser"
+            url="http://anjuta.org/plugins/";
+            mandatory="yes">
+		<require group="Anjuta Plugin"
+                 attribute="Interfaces"
+                 value="IAnjutaSymbolManager"/>
+	</plugin>
+	<plugin name="Make Build System"
+            url="http://anjuta.org/plugins/";
+            mandatory="yes">
+		<require group="Anjuta Plugin"
+                 attribute="Interfaces"
+                 value="IAnjutaBuildable"/>
+		<require group="Build"
+                 attribute="Supported-Build-Types"
+                 value="make"/>
+	</plugin>
+	<plugin name="Task Manager"
+            url="http://anjuta.org/plugins/";
+            mandatory="no">
+		<require group="Anjuta Plugin"
+                 attribute="Interfaces"
+                 value="IAnjutaTodo"/>
+	</plugin>
+	<plugin name="Debug Manager"
+            url="http://anjuta.org/plugins/";
+            mandatory="no">
+		<require group="Anjuta Plugin"
+                 attribute="Interfaces"
+                 value="IAnjutaDebugManager"/>
+	</plugin>
+</anjuta>
diff --git a/plugins/project-wizard/templates/mkfile/project.anjuta b/plugins/project-wizard/templates/mkfile/project.anjuta
index 471e6e1..390fe09 100644
--- a/plugins/project-wizard/templates/mkfile/project.anjuta
+++ b/plugins/project-wizard/templates/mkfile/project.anjuta
@@ -6,9 +6,16 @@
 		<require group="Anjuta Plugin"
 		 attribute="Interfaces"
 		 value="IAnjutaProjectManager"/>
+	</plugin>
+	<plugin name="Makefile Project Backend"
+            url="http://anjuta.org/plugins/";
+            mandatory="yes">
+		<require group="Anjuta Plugin"
+                 attribute="Interfaces"
+                 value="IAnjutaProjectBackend"/>
 		<require group="Project"
-		 attribute="Supported-Project-Types"
-		 value="make"/>
+                 attribute="Supported-Project-Types"
+                 value="make"/>
 	</plugin>
 	<plugin name="Symbol Browser"
             url="http://anjuta.org/plugins/";
diff --git a/plugins/project-wizard/templates/terminal/project.anjuta b/plugins/project-wizard/templates/terminal/project.anjuta
index 2389e4c..68c60e6 100644
--- a/plugins/project-wizard/templates/terminal/project.anjuta
+++ b/plugins/project-wizard/templates/terminal/project.anjuta
@@ -1,11 +1,18 @@
 <?xml version="1.0"?>
 <anjuta>
-    <plugin name="GBF Project Manager"
+	<plugin name="GBF Project Manager"
             url="http://anjuta.org/plugins/";
             mandatory="yes">
 		<require group="Anjuta Plugin"
                  attribute="Interfaces"
                  value="IAnjutaProjectManager"/>
+	</plugin>
+	<plugin name="AutoTools Project Backend"
+            url="http://anjuta.org/plugins/";
+            mandatory="yes">
+		<require group="Anjuta Plugin"
+                 attribute="Interfaces"
+                 value="IAnjutaProjectBackend"/>
 		<require group="Project"
                  attribute="Supported-Project-Types"
                  value="automake"/>
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 775fffd..99b2b22 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -90,6 +90,7 @@ plugins/gbf-am/gbf-am-properties.c
 plugins/gbf-mkfile/gbf-mkfile-config.c
 plugins/gbf-mkfile/gbf-mkfile-project.c
 plugins/gbf-mkfile/gbf-mkfile-properties.c
+plugins/dir-project/dir-project.c
 plugins/gdb/debugger.c
 plugins/gdb/plugin.c
 plugins/gdb/utilities.c



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]