Updated Spanish translation
[anjuta.git] / plugins / project-import / plugin.c
blob36d98b703c8278934d16d5ee8a03430296d35e00
1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
2 /*
3 plugin.c
4 Copyright (C) 2000 Naba Kumar, 2005 Johannes Schmid
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 #include <config.h>
22 #include <gtk/gtk.h>
23 #include <glib/gi18n.h>
24 #include <libanjuta/anjuta-debug.h>
25 #include <libanjuta/anjuta-utils.h>
26 #include <libanjuta/interfaces/ianjuta-wizard.h>
27 #include <libanjuta/interfaces/ianjuta-file.h>
28 #include <libanjuta/interfaces/ianjuta-file-loader.h>
29 #include <libanjuta/interfaces/ianjuta-project-backend.h>
30 #include <libanjuta/interfaces/ianjuta-vcs.h>
31 #include <libanjuta/anjuta-async-notify.h>
33 #include "plugin.h"
34 #include "project-import-dialog.h"
36 #define ICON_FILE "anjuta-project-import-plugin-48.png"
38 #define AM_PROJECT_FILE PACKAGE_DATA_DIR"/templates/terminal/project.anjuta"
39 #define MKFILE_PROJECT_FILE PACKAGE_DATA_DIR"/templates/mkfile/project.anjuta"
40 #define DIRECTORY_PROJECT_FILE PACKAGE_DATA_DIR"/templates/directory/project.anjuta"
42 static gpointer parent_class;
44 static gboolean
45 project_import_generate_file (AnjutaPluginHandle *backend, ProjectImportDialog *import_dialog,
46 GFile *project_file)
48 /* Of course we could do some more intelligent stuff here
49 * and check which plugins are really needed */
51 AnjutaPluginDescription *desc;
52 GFile* source_file = NULL;
53 gchar *backend_id = NULL;
54 GError* error = NULL;
56 desc = anjuta_plugin_handle_get_description (backend);
57 if (!anjuta_plugin_description_get_string (desc, "Project", "Supported-Project-Types", &backend_id))
59 if (!strcmp (backend_id, "automake"))
60 source_file = g_file_new_for_path (AM_PROJECT_FILE);
61 else if (!strcmp (backend_id, "make"))
62 source_file = g_file_new_for_path (MKFILE_PROJECT_FILE);
63 else if (!strcmp (backend_id, "directory"))
64 source_file = g_file_new_for_path (DIRECTORY_PROJECT_FILE);
66 g_free (backend_id);
68 if (source_file != NULL)
70 /* Use a default project file */
71 if (!g_file_copy (source_file, project_file,
72 G_FILE_COPY_NONE,
73 NULL,
74 NULL,
75 NULL,
76 &error))
78 if (error->domain == G_IO_ERROR && error->code == G_IO_ERROR_EXISTS)
80 gchar *prjfile = g_file_get_parse_name (project_file);
81 if (anjuta_util_dialog_boolean_question (GTK_WINDOW (import_dialog), FALSE,
82 _("A file named \"%s\" already exists. "
83 "Do you want to replace it?"), prjfile))
85 g_error_free (error);
86 error = NULL;
87 g_file_copy (source_file, project_file,
88 G_FILE_COPY_OVERWRITE,
89 NULL,
90 NULL,
91 NULL,
92 &error);
94 g_free (prjfile);
98 if (!error)
100 time_t ctime = time(NULL);
101 GFileInfo* file_info = g_file_info_new();
102 g_file_info_set_attribute_uint64(file_info,
103 "time::modified",
104 ctime);
105 g_file_info_set_attribute_uint64(file_info,
106 "time::created",
107 ctime);
108 g_file_info_set_attribute_uint64(file_info,
109 "time::access",
110 ctime);
111 g_file_set_attributes_from_info (project_file,
112 file_info,
113 G_FILE_QUERY_INFO_NONE,
114 NULL, NULL);
116 g_object_unref (G_OBJECT(file_info));;
119 else
121 /* For unknown project backend we use the directory project file and
122 * replace the backend plugin with the right one */
124 gchar *content;
125 gsize length;
127 source_file = g_file_new_for_path (DIRECTORY_PROJECT_FILE);
128 if (g_file_load_contents (source_file, NULL, &content, &length, NULL, &error))
130 GString *buffer;
131 const gchar *pos;
132 const gchar *plugin;
133 const gchar *end_plugin;
134 gssize len;
136 buffer = g_string_new_len (content, length);
137 pos = buffer->str;
138 len = buffer->len;
139 for (;;)
141 plugin = g_strstr_len (pos, len, "<plugin ");
142 if (plugin == NULL) break;
144 end_plugin = g_strstr_len (plugin, len - (plugin - pos), "</plugin>");
145 if (end_plugin == NULL) break;
147 if (g_strstr_len (plugin, end_plugin - plugin, "\"IAnjutaProjectBackend\"") != NULL) break;
149 pos = end_plugin + 9;
150 len -= (end_plugin + 9 - pos);
153 if ((plugin == NULL) || (end_plugin == NULL))
155 g_set_error (&error, ianjuta_project_backend_error_quark(),0, "Unable to find backend plugin");
157 else
159 /* Replace directory backend with right one */
160 GString *str;
161 GFileOutputStream *stream;
162 gchar *name = NULL;
163 gchar *plugin_id = NULL;
165 anjuta_plugin_description_get_string (desc, "Anjuta Plugin", "Name", &name);
166 anjuta_plugin_description_get_string (desc, "Anjuta Plugin", "Location", &plugin_id);
168 str = g_string_new (NULL);
169 g_string_printf (str, "<plugin name= \"%s\"\n"
170 " mandatory=\"yes\">\n"
171 " <require group=\"Anjuta Plugin\"\n"
172 " attribute=\"Location\"\n"
173 " value=\"%s\"/>\n"
174 " <require group=\"Anjuta Plugin\"\n"
175 " attribute=\"Interfaces\"\n"
176 " value=\"IAnjutaProjectBackend\"/>\n"
177 " ", name, plugin_id);
179 g_string_erase (buffer, plugin - buffer->str, end_plugin - plugin);
180 g_string_insert_len (buffer, plugin - buffer->str, str->str, str->len);
182 g_string_free (str, TRUE);
184 stream = g_file_create (project_file, G_FILE_CREATE_NONE, NULL, &error);
185 if (stream == NULL && error->domain == G_IO_ERROR && error->code == G_IO_ERROR_EXISTS)
187 gchar *prjfile = g_file_get_parse_name (project_file);
188 if (anjuta_util_dialog_boolean_question (GTK_WINDOW (import_dialog), FALSE,
189 _("A file named \"%s\" already exists. "
190 "Do you want to replace it?"), prjfile))
192 g_error_free (error);
193 error = NULL;
194 stream = g_file_replace (project_file, NULL, FALSE, G_FILE_CREATE_REPLACE_DESTINATION, NULL, &error);
196 g_free (prjfile);
199 if (stream != NULL)
201 gsize written;
203 g_output_stream_write_all (G_OUTPUT_STREAM (stream), buffer->str, buffer->len, &written, NULL, &error);
204 g_output_stream_close (G_OUTPUT_STREAM (stream), NULL, NULL);
208 g_string_free (buffer, TRUE);
209 g_free (content);
212 g_object_unref (source_file);
214 if (error)
216 gchar *prjfile;
218 prjfile = g_file_get_parse_name (project_file);
220 /* show the dialog since it may be hidden */
221 gtk_widget_show (GTK_WIDGET (import_dialog));
223 anjuta_util_dialog_error (GTK_WINDOW (import_dialog),
224 _("A file named \"%s\" cannot be written: %s. "
225 "Check if you have write access to the project directory."),
226 prjfile, error->message);
227 g_free (prjfile);
228 g_error_free (error);
230 return FALSE;
234 return TRUE;
237 static gboolean
238 project_import_import_project (AnjutaProjectImportPlugin *import_plugin, ProjectImportDialog *import_dialog,
239 GFile *source_dir)
241 AnjutaPluginManager *plugin_manager;
242 GList *handles = NULL;
243 GList *node;
244 AnjutaPluginHandle *backend;
245 gchar *name, *project_file_name;
247 /* Search for all valid project backend */
248 plugin_manager = anjuta_shell_get_plugin_manager (ANJUTA_PLUGIN(import_plugin)->shell, NULL);
249 handles = anjuta_plugin_manager_query (plugin_manager,
250 "Anjuta Plugin",
251 "Interfaces",
252 "IAnjutaProjectBackend",
253 NULL);
254 for (node = g_list_first (handles); node != NULL;) {
255 IAnjutaProjectBackend *plugin;
256 GList *next;
258 backend = (AnjutaPluginHandle *)node->data;
259 plugin = (IAnjutaProjectBackend *)anjuta_plugin_manager_get_plugin_by_handle (plugin_manager, backend);
261 next = g_list_next (node);
263 /* Probe the project directory to find if the backend can handle it */
264 if (ianjuta_project_backend_probe (plugin, source_dir, NULL) <= 0)
266 /* Remove invalid backend */
267 handles = g_list_delete_link (handles, node);
270 node = next;
273 if (handles == NULL)
275 backend = NULL;
277 else if (g_list_next (handles) == NULL)
279 backend = (AnjutaPluginHandle *)handles->data;
281 else
283 /* Several backend are possible, ask the user to select one */
284 gchar *path = project_import_dialog_get_name (import_dialog);
285 gchar* message = g_strdup_printf (_("Please select a project backend to open %s."), path);
287 g_free (path);
289 backend = anjuta_plugin_manager_select (plugin_manager,
290 _("Open With"),
291 message,
292 handles);
293 g_free (message);
295 g_list_free (handles);
297 if (backend == NULL)
299 gchar *path = project_import_dialog_get_name (import_dialog);
301 /* show the dialog since it may be hidden */
302 gtk_widget_show (GTK_WIDGET (import_dialog));
304 anjuta_util_dialog_error (GTK_WINDOW (import_dialog),
305 _("Could not find a valid project backend for the "
306 "given directory (%s). Please select a different "
307 "directory, or try upgrading to a newer version of "
308 "Anjuta."), path);
310 g_free (path);
312 return FALSE;
316 name = project_import_dialog_get_name (import_dialog);
317 project_file_name = g_strconcat (name, ".", "anjuta", NULL);
318 GFile *project_file = g_file_get_child (source_dir, project_file_name);
320 g_free (name);
321 g_free (project_file_name);
323 IAnjutaFileLoader* loader;
325 if (!project_import_generate_file (backend, import_dialog, project_file))
327 g_object_unref (project_file);
328 return FALSE;
331 loader = anjuta_shell_get_interface (ANJUTA_PLUGIN (import_plugin)->shell,
332 IAnjutaFileLoader, NULL);
333 if (!loader)
335 g_warning("No IAnjutaFileLoader interface! Cannot open project file!");
336 g_object_unref (project_file);
337 return TRUE;
340 ianjuta_file_loader_load (loader, project_file, FALSE, NULL);
342 g_object_unref (project_file);
344 return TRUE;
347 typedef struct
349 AnjutaProjectImportPlugin *import_plugin;
350 ProjectImportDialog *import_dialog;
351 GFile *checkout_dir;
352 } CheckoutData;
354 static void
355 checkout_finished (AnjutaAsyncNotify *async_notify, gpointer user_data)
357 CheckoutData *ch = (CheckoutData *)user_data;
358 GError *err;
360 err = NULL;
361 anjuta_async_notify_get_error (async_notify, &err);
362 if (err)
364 gchar *vcs_uri;
366 /* show the dialog since it's hidden */
367 gtk_widget_show (GTK_WIDGET (ch->import_dialog));
369 vcs_uri = project_import_dialog_get_vcs_uri (ch->import_dialog);
370 anjuta_util_dialog_error (GTK_WINDOW (ch->import_dialog),
371 _("Couldn't check out the supplied URI "
372 "\"%s\". The error returned was: \"%s\""),
373 vcs_uri, err->message);
375 g_free (vcs_uri);
376 g_error_free (err);
378 goto cleanup;
381 project_import_import_project (ch->import_plugin, ch->import_dialog, ch->checkout_dir);
383 cleanup:
384 g_object_unref (ch->checkout_dir);
385 g_slice_free (CheckoutData, ch);
388 static void
389 project_import_checkout_project (AnjutaProjectImportPlugin *import_plugin,
390 ProjectImportDialog *import_dialog)
392 CheckoutData *ch_data;
393 AnjutaAsyncNotify *async_notify;
394 AnjutaPluginHandle *plugin_handle;
395 gchar *vcs_uri, *name;
396 GFile *dest_dir, *checkout_dir;
397 AnjutaPluginManager *plugin_manager;
398 IAnjutaVcs *ivcs;
399 GError *err;
401 name = project_import_dialog_get_name (import_dialog);
402 dest_dir = project_import_dialog_get_dest_dir (import_dialog);
403 checkout_dir = g_file_get_child (dest_dir, name);
405 g_object_unref (dest_dir);
406 g_free (name);
408 ch_data = g_slice_new (CheckoutData);
409 ch_data->import_plugin = import_plugin;
410 ch_data->import_dialog = import_dialog;
411 ch_data->checkout_dir = checkout_dir;
413 async_notify = anjuta_async_notify_new ();
414 g_signal_connect (async_notify, "finished", G_CALLBACK (checkout_finished),
415 ch_data);
417 vcs_uri = project_import_dialog_get_vcs_uri (import_dialog);
418 plugin_handle = project_import_dialog_get_vcs_id (import_dialog);
420 plugin_manager = anjuta_shell_get_plugin_manager (ANJUTA_PLUGIN (import_plugin)->shell, NULL);
421 ivcs = IANJUTA_VCS (anjuta_plugin_manager_get_plugin_by_handle (plugin_manager, plugin_handle));
423 err = NULL;
424 ianjuta_vcs_checkout (ivcs, vcs_uri, checkout_dir, NULL, async_notify, &err);
425 if (err)
427 anjuta_util_dialog_error (GTK_WINDOW (import_dialog),
428 _("Couldn't check out the supplied URI "
429 "\"%s\". The error returned was: \"%s\""),
430 vcs_uri, err->message);
432 g_error_free (err);
434 goto cleanup;
437 /* hide the import dialog */
438 gtk_widget_hide (GTK_WIDGET (import_dialog));
440 cleanup:
441 g_free (vcs_uri);
444 static void
445 import_dialog_response (GtkDialog *dialog, gint response_id, gpointer user_data)
447 AnjutaProjectImportPlugin *import_plugin = (AnjutaProjectImportPlugin *)user_data;
448 ProjectImportDialog *import_dialog = PROJECT_IMPORT_DIALOG (dialog);
450 switch (response_id)
452 case GTK_RESPONSE_ACCEPT:
454 GFile *source_dir;
456 source_dir = project_import_dialog_get_source_dir (import_dialog);
457 if (source_dir)
459 if (project_import_import_project (import_plugin, import_dialog, source_dir))
460 gtk_widget_destroy (GTK_WIDGET (import_dialog));
462 g_object_unref (source_dir);
464 else
465 project_import_checkout_project (import_plugin, import_dialog);
467 break;
470 case GTK_RESPONSE_REJECT:
471 gtk_widget_destroy (GTK_WIDGET (dialog));
475 static gboolean
476 activate_plugin (AnjutaPlugin *plugin)
478 AnjutaProjectImportPlugin *iplugin;
480 DEBUG_PRINT ("%s", "AnjutaProjectImportPlugin: Activating Project Import Plugin ...");
482 iplugin = ANJUTA_PLUGIN_PROJECT_IMPORT (plugin);
483 iplugin->prefs = anjuta_shell_get_preferences (plugin->shell, NULL);
485 return TRUE;
488 static gboolean
489 deactivate_plugin (AnjutaPlugin *plugin)
491 return TRUE;
494 static void
495 dispose (GObject *obj)
497 G_OBJECT_CLASS (parent_class)->dispose (obj);
500 static void
501 finalize (GObject *obj)
503 G_OBJECT_CLASS (parent_class)->finalize (obj);
506 static void
507 project_import_plugin_instance_init (GObject *obj)
509 // AnjutaFileWizardPlugin *plugin = ANJUTA_PLUGIN_PROJECT_IMPORT (obj);
512 static void
513 project_import_plugin_class_init (GObjectClass *klass)
515 AnjutaPluginClass *plugin_class = ANJUTA_PLUGIN_CLASS (klass);
517 parent_class = g_type_class_peek_parent (klass);
519 plugin_class->activate = activate_plugin;
520 plugin_class->deactivate = deactivate_plugin;
521 klass->dispose = dispose;
522 klass->finalize = finalize;
525 static void
526 iwizard_activate (IAnjutaWizard *wiz, GError **err)
528 AnjutaProjectImportPlugin* plugin = ANJUTA_PLUGIN_PROJECT_IMPORT (wiz);
529 AnjutaPluginManager *plugin_manager;
530 ProjectImportDialog* pi;
532 plugin_manager = anjuta_shell_get_plugin_manager (ANJUTA_PLUGIN (plugin)->shell, NULL);
534 pi = project_import_dialog_new(plugin_manager, NULL, NULL);
535 g_signal_connect (pi, "response", G_CALLBACK (import_dialog_response), plugin);
537 gtk_widget_show (GTK_WIDGET (pi));
540 static void
541 iwizard_iface_init (IAnjutaWizardIface *iface)
543 iface->activate = iwizard_activate;
546 static void
547 ifile_open (IAnjutaFile *ifile, GFile* file, GError **err)
549 AnjutaProjectImportPlugin* plugin = ANJUTA_PLUGIN_PROJECT_IMPORT (ifile);
550 gchar *mime_type;
552 g_return_if_fail (G_IS_FILE (file));
554 mime_type = anjuta_util_get_file_mime_type (file);
555 if (g_strcmp0 (mime_type,"application/x-anjuta-old") == 0)
557 /* Automatically import old Anjuta project */
558 gchar *ext, *project_name;
559 GFile *dir;
560 ProjectImportDialog* pi;
561 AnjutaPluginManager *plugin_manager;
563 dir = g_file_get_parent (file);
564 project_name = g_file_get_basename (file);
565 ext = strrchr (project_name, '.');
566 if (ext)
567 *ext = '\0';
569 plugin_manager = anjuta_shell_get_plugin_manager (ANJUTA_PLUGIN (plugin)->shell, NULL);
571 pi = project_import_dialog_new (plugin_manager, project_name, dir);
572 g_signal_connect (pi, "response", G_CALLBACK (import_dialog_response), plugin);
574 gtk_widget_show (GTK_WIDGET (pi));
576 g_object_unref (dir);
577 g_free (project_name);
579 else if (g_strcmp0 (mime_type,"inode/directory") == 0)
581 GFileEnumerator *dir;
583 dir = g_file_enumerate_children (file,
584 G_FILE_ATTRIBUTE_STANDARD_NAME "," G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE,
585 G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
586 NULL,
587 NULL);
588 if (dir)
590 /* Look for anjuta project file in the directory */
591 GFileInfo *info;
593 for (info = g_file_enumerator_next_file (dir, NULL, NULL); info != NULL; info = g_file_enumerator_next_file (dir, NULL, NULL))
595 gchar *mime_type = anjuta_util_get_file_info_mime_type (info);
597 if (g_strcmp0 (mime_type, "application/x-anjuta") == 0)
599 /* Open the first anjuta project file */
600 IAnjutaFileLoader *loader;
602 loader = anjuta_shell_get_interface(ANJUTA_PLUGIN (plugin)->shell, IAnjutaFileLoader, NULL);
603 if (loader != NULL)
605 GFile* project_file = g_file_get_child (file, g_file_info_get_name(info));
606 ianjuta_file_loader_load(loader, project_file, FALSE, NULL);
607 g_object_unref (project_file);
609 g_free (mime_type);
610 g_object_unref (info);
611 break;
613 g_free (mime_type);
614 g_object_unref (info);
616 if (info == NULL)
618 /* Else import the directory */
619 ProjectImportDialog* pi;
620 AnjutaPluginManager *plugin_manager;
621 gchar *basename;
623 plugin_manager = anjuta_shell_get_plugin_manager (ANJUTA_PLUGIN (plugin)->shell, NULL);
625 basename = g_file_get_basename (file);
626 pi = project_import_dialog_new (plugin_manager, basename, file);
627 g_free (basename);
628 g_signal_connect (pi, "response", G_CALLBACK (import_dialog_response), plugin);
630 gtk_widget_show (GTK_WIDGET (pi));
632 g_object_unref (dir);
635 g_free (mime_type);
638 static GFile*
639 ifile_get_file (IAnjutaFile *file, GError **err)
641 g_warning ("Unsupported operation");
642 return NULL;
645 static void
646 ifile_iface_init (IAnjutaFileIface *iface)
648 iface->open = ifile_open;
649 iface->get_file = ifile_get_file;
652 ANJUTA_PLUGIN_BEGIN (AnjutaProjectImportPlugin, project_import_plugin);
653 ANJUTA_PLUGIN_ADD_INTERFACE(iwizard, IANJUTA_TYPE_WIZARD);
654 ANJUTA_PLUGIN_ADD_INTERFACE(ifile, IANJUTA_TYPE_FILE);
655 ANJUTA_PLUGIN_END;
657 ANJUTA_SIMPLE_PLUGIN (AnjutaProjectImportPlugin, project_import_plugin);