1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
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
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>
34 #include "project-import-dialog.h"
36 #define ICON_FILE "anjuta-project-import-plugin-48.png"
38 #define AM_PROJECT_FILE PACKAGE_DATA_DIR"/project/terminal/project.anjuta"
39 #define MKFILE_PROJECT_FILE PACKAGE_DATA_DIR"/project/mkfile/project.anjuta"
40 #define DIRECTORY_PROJECT_FILE PACKAGE_DATA_DIR"/project/directory/project.anjuta"
42 static gpointer parent_class
;
45 project_import_generate_file (AnjutaPluginDescription
*backend
, ProjectImportDialog
*import_dialog
,
48 /* Of course we could do some more intelligent stuff here
49 * and check which plugins are really needed */
51 GFile
* source_file
= NULL
;
52 gchar
*backend_id
= NULL
;
55 if (!anjuta_plugin_description_get_string (backend
, "Project", "Supported-Project-Types", &backend_id
))
57 if (!strcmp (backend_id
, "automake"))
58 source_file
= g_file_new_for_path (AM_PROJECT_FILE
);
59 else if (!strcmp (backend_id
, "make"))
60 source_file
= g_file_new_for_path (MKFILE_PROJECT_FILE
);
61 else if (!strcmp (backend_id
, "directory"))
62 source_file
= g_file_new_for_path (DIRECTORY_PROJECT_FILE
);
66 if (source_file
!= NULL
)
68 /* Use a default project file */
69 if (!g_file_copy (source_file
, project_file
,
76 if (error
->domain
== G_IO_ERROR
&& error
->code
== G_IO_ERROR_EXISTS
)
78 gchar
*prjfile
= g_file_get_parse_name (project_file
);
79 if (anjuta_util_dialog_boolean_question (GTK_WINDOW (import_dialog
), FALSE
,
80 _("A file named \"%s\" already exists. "
81 "Do you want to replace it?"), prjfile
))
85 g_file_copy (source_file
, project_file
,
86 G_FILE_COPY_OVERWRITE
,
98 time_t ctime
= time(NULL
);
99 GFileInfo
* file_info
= g_file_info_new();
100 g_file_info_set_attribute_uint64(file_info
,
103 g_file_info_set_attribute_uint64(file_info
,
106 g_file_info_set_attribute_uint64(file_info
,
109 g_file_set_attributes_from_info (project_file
,
111 G_FILE_QUERY_INFO_NONE
,
114 g_object_unref (G_OBJECT(file_info
));;
119 /* For unknown project backend we use the directory project file and
120 * replace the backend plugin with the right one */
125 source_file
= g_file_new_for_path (DIRECTORY_PROJECT_FILE
);
126 if (g_file_load_contents (source_file
, NULL
, &content
, &length
, NULL
, &error
))
131 const gchar
*end_plugin
;
134 buffer
= g_string_new_len (content
, length
);
139 plugin
= g_strstr_len (pos
, len
, "<plugin ");
140 if (plugin
== NULL
) break;
142 end_plugin
= g_strstr_len (plugin
, len
- (plugin
- pos
), "</plugin>");
143 if (end_plugin
== NULL
) break;
145 if (g_strstr_len (plugin
, end_plugin
- plugin
, "\"IAnjutaProjectBackend\"") != NULL
) break;
147 pos
= end_plugin
+ 9;
148 len
-= (end_plugin
+ 9 - pos
);
151 if ((plugin
== NULL
) || (end_plugin
== NULL
))
153 g_set_error (&error
, ianjuta_project_backend_error_quark(),0, "Unable to find backend plugin");
157 /* Replace directory backend with right one */
159 GFileOutputStream
*stream
;
161 gchar
*plugin_id
= NULL
;
163 anjuta_plugin_description_get_string (backend
, "Anjuta Plugin", "Name", &name
);
164 anjuta_plugin_description_get_string (backend
, "Anjuta Plugin", "Location", &plugin_id
);
166 str
= g_string_new (NULL
);
167 g_string_printf (str
, "<plugin name= \"%s\"\n"
168 " mandatory=\"yes\">\n"
169 " <require group=\"Anjuta Plugin\"\n"
170 " attribute=\"Location\"\n"
172 " <require group=\"Anjuta Plugin\"\n"
173 " attribute=\"Interfaces\"\n"
174 " value=\"IAnjutaProjectBackend\"/>\n"
175 " ", name
, plugin_id
);
177 g_string_erase (buffer
, plugin
- buffer
->str
, end_plugin
- plugin
);
178 g_string_insert_len (buffer
, plugin
- buffer
->str
, str
->str
, str
->len
);
180 g_string_free (str
, TRUE
);
182 stream
= g_file_create (project_file
, G_FILE_CREATE_NONE
, NULL
, &error
);
183 if (stream
== NULL
&& error
->domain
== G_IO_ERROR
&& error
->code
== G_IO_ERROR_EXISTS
)
185 gchar
*prjfile
= g_file_get_parse_name (project_file
);
186 if (anjuta_util_dialog_boolean_question (GTK_WINDOW (import_dialog
), FALSE
,
187 _("A file named \"%s\" already exists. "
188 "Do you want to replace it?"), prjfile
))
190 g_error_free (error
);
192 stream
= g_file_replace (project_file
, NULL
, FALSE
, G_FILE_CREATE_REPLACE_DESTINATION
, NULL
, &error
);
201 g_output_stream_write_all (G_OUTPUT_STREAM (stream
), buffer
->str
, buffer
->len
, &written
, NULL
, &error
);
202 g_output_stream_close (G_OUTPUT_STREAM (stream
), NULL
, NULL
);
206 g_string_free (buffer
, TRUE
);
210 g_object_unref (source_file
);
216 prjfile
= g_file_get_parse_name (project_file
);
218 /* show the dialog since it may be hidden */
219 gtk_widget_show (GTK_WIDGET (import_dialog
));
221 anjuta_util_dialog_error (GTK_WINDOW (import_dialog
),
222 _("A file named \"%s\" cannot be written: %s. "
223 "Check if you have write access to the project directory."),
224 prjfile
, error
->message
);
226 g_error_free (error
);
236 project_import_import_project (AnjutaProjectImportPlugin
*import_plugin
, ProjectImportDialog
*import_dialog
,
239 AnjutaPluginManager
*plugin_manager
;
242 AnjutaPluginDescription
*backend
;
243 gchar
*name
, *project_file_name
;
245 /* Search for all valid project backend */
246 plugin_manager
= anjuta_shell_get_plugin_manager (ANJUTA_PLUGIN(import_plugin
)->shell
, NULL
);
247 descs
= anjuta_plugin_manager_query (plugin_manager
,
250 "IAnjutaProjectBackend",
252 for (desc
= g_list_first (descs
); desc
!= NULL
;) {
253 IAnjutaProjectBackend
*plugin
;
254 gchar
*location
= NULL
;
257 backend
= (AnjutaPluginDescription
*)desc
->data
;
258 anjuta_plugin_description_get_string (backend
, "Anjuta Plugin", "Location", &location
);
259 plugin
= (IAnjutaProjectBackend
*)anjuta_plugin_manager_get_plugin_by_id (plugin_manager
, location
);
262 next
= g_list_next (desc
);
264 /* Probe the project directory to find if the backend can handle it */
265 if (ianjuta_project_backend_probe (plugin
, source_dir
, NULL
) <= 0)
267 /* Remove invalid backend */
268 descs
= g_list_delete_link (descs
, desc
);
278 else if (g_list_next (descs
) == NULL
)
280 backend
= (AnjutaPluginDescription
*)descs
->data
;
284 /* Several backend are possible, ask the user to select one */
285 gchar
*path
= project_import_dialog_get_name (import_dialog
);
286 gchar
* message
= g_strdup_printf (_("Please select a project backend to open %s."), path
);
290 backend
= anjuta_plugin_manager_select (plugin_manager
,
300 gchar
*path
= project_import_dialog_get_name (import_dialog
);
302 /* show the dialog since it may be hidden */
303 gtk_widget_show (GTK_WIDGET (import_dialog
));
305 anjuta_util_dialog_error (GTK_WINDOW (import_dialog
),
306 _("Could not find a valid project backend for the "
307 "given directory (%s). Please select a different "
308 "directory, or try upgrading to a newer version of "
317 name
= project_import_dialog_get_name (import_dialog
);
318 project_file_name
= g_strconcat (name
, ".", "anjuta", NULL
);
319 GFile
*project_file
= g_file_get_child (source_dir
, project_file_name
);
322 g_free (project_file_name
);
324 IAnjutaFileLoader
* loader
;
326 if (!project_import_generate_file (backend
, import_dialog
, project_file
))
328 g_object_unref (project_file
);
332 loader
= anjuta_shell_get_interface (ANJUTA_PLUGIN (import_plugin
)->shell
,
333 IAnjutaFileLoader
, NULL
);
336 g_warning("No IAnjutaFileLoader interface! Cannot open project file!");
337 g_object_unref (project_file
);
341 ianjuta_file_loader_load (loader
, project_file
, FALSE
, NULL
);
343 g_object_unref (project_file
);
350 AnjutaProjectImportPlugin
*import_plugin
;
351 ProjectImportDialog
*import_dialog
;
356 checkout_finished (AnjutaAsyncNotify
*async_notify
, gpointer user_data
)
358 CheckoutData
*ch
= (CheckoutData
*)user_data
;
362 anjuta_async_notify_get_error (async_notify
, &err
);
367 /* show the dialog since it's hidden */
368 gtk_widget_show (GTK_WIDGET (ch
->import_dialog
));
370 vcs_uri
= project_import_dialog_get_vcs_uri (ch
->import_dialog
);
371 anjuta_util_dialog_error (GTK_WINDOW (ch
->import_dialog
),
372 _("Couldn't check out the supplied URI "
373 "\"%s\". The error returned was: \"%s\""),
374 vcs_uri
, err
->message
);
382 project_import_import_project (ch
->import_plugin
, ch
->import_dialog
, ch
->checkout_dir
);
385 g_object_unref (ch
->checkout_dir
);
386 g_slice_free (CheckoutData
, ch
);
390 project_import_checkout_project (AnjutaProjectImportPlugin
*import_plugin
,
391 ProjectImportDialog
*import_dialog
)
393 CheckoutData
*ch_data
;
394 AnjutaAsyncNotify
*async_notify
;
395 gchar
*vcs_uri
, *plugin_id
, *name
;
396 GFile
*dest_dir
, *checkout_dir
;
397 AnjutaPluginManager
*plugin_manager
;
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
);
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
),
417 vcs_uri
= project_import_dialog_get_vcs_uri (import_dialog
);
418 plugin_id
= 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_id (plugin_manager
, plugin_id
));
424 ianjuta_vcs_checkout (ivcs
, vcs_uri
, checkout_dir
, NULL
, async_notify
, &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
);
437 /* hide the import dialog */
438 gtk_widget_hide (GTK_WIDGET (import_dialog
));
446 import_dialog_response (GtkDialog
*dialog
, gint response_id
, gpointer user_data
)
448 AnjutaProjectImportPlugin
*import_plugin
= (AnjutaProjectImportPlugin
*)user_data
;
449 ProjectImportDialog
*import_dialog
= PROJECT_IMPORT_DIALOG (dialog
);
453 case GTK_RESPONSE_ACCEPT
:
457 source_dir
= project_import_dialog_get_source_dir (import_dialog
);
460 if (project_import_import_project (import_plugin
, import_dialog
, source_dir
))
461 gtk_widget_destroy (GTK_WIDGET (import_dialog
));
463 g_object_unref (source_dir
);
466 project_import_checkout_project (import_plugin
, import_dialog
);
471 case GTK_RESPONSE_REJECT
:
472 gtk_widget_destroy (GTK_WIDGET (dialog
));
477 activate_plugin (AnjutaPlugin
*plugin
)
479 AnjutaProjectImportPlugin
*iplugin
;
481 DEBUG_PRINT ("%s", "AnjutaProjectImportPlugin: Activating Project Import Plugin ...");
483 iplugin
= ANJUTA_PLUGIN_PROJECT_IMPORT (plugin
);
484 iplugin
->prefs
= anjuta_shell_get_preferences (plugin
->shell
, NULL
);
490 deactivate_plugin (AnjutaPlugin
*plugin
)
496 dispose (GObject
*obj
)
498 G_OBJECT_CLASS (parent_class
)->dispose (obj
);
502 finalize (GObject
*obj
)
504 G_OBJECT_CLASS (parent_class
)->finalize (obj
);
508 project_import_plugin_instance_init (GObject
*obj
)
510 // AnjutaFileWizardPlugin *plugin = ANJUTA_PLUGIN_PROJECT_IMPORT (obj);
514 project_import_plugin_class_init (GObjectClass
*klass
)
516 AnjutaPluginClass
*plugin_class
= ANJUTA_PLUGIN_CLASS (klass
);
518 parent_class
= g_type_class_peek_parent (klass
);
520 plugin_class
->activate
= activate_plugin
;
521 plugin_class
->deactivate
= deactivate_plugin
;
522 klass
->dispose
= dispose
;
523 klass
->finalize
= finalize
;
527 iwizard_activate (IAnjutaWizard
*wiz
, GError
**err
)
529 AnjutaProjectImportPlugin
* plugin
= ANJUTA_PLUGIN_PROJECT_IMPORT (wiz
);
530 AnjutaPluginManager
*plugin_manager
;
531 ProjectImportDialog
* pi
;
533 plugin_manager
= anjuta_shell_get_plugin_manager (ANJUTA_PLUGIN (plugin
)->shell
, NULL
);
535 pi
= project_import_dialog_new(plugin_manager
, NULL
, NULL
);
536 g_signal_connect (pi
, "response", G_CALLBACK (import_dialog_response
), plugin
);
538 gtk_widget_show (GTK_WIDGET (pi
));
542 iwizard_iface_init (IAnjutaWizardIface
*iface
)
544 iface
->activate
= iwizard_activate
;
548 ifile_open (IAnjutaFile
*ifile
, GFile
* file
, GError
**err
)
550 AnjutaProjectImportPlugin
* plugin
= ANJUTA_PLUGIN_PROJECT_IMPORT (ifile
);
553 g_return_if_fail (G_IS_FILE (file
));
555 mime_type
= anjuta_util_get_file_mime_type (file
);
556 if (g_strcmp0 (mime_type
,"application/x-anjuta-old") == 0)
558 /* Automatically import old Anjuta project */
559 gchar
*ext
, *project_name
;
561 ProjectImportDialog
* pi
;
562 AnjutaPluginManager
*plugin_manager
;
564 dir
= g_file_get_parent (file
);
565 project_name
= g_file_get_basename (file
);
566 ext
= strrchr (project_name
, '.');
570 plugin_manager
= anjuta_shell_get_plugin_manager (ANJUTA_PLUGIN (plugin
)->shell
, NULL
);
572 pi
= project_import_dialog_new (plugin_manager
, project_name
, dir
);
573 g_signal_connect (pi
, "response", G_CALLBACK (import_dialog_response
), plugin
);
575 gtk_widget_show (GTK_WIDGET (pi
));
577 g_object_unref (dir
);
578 g_free (project_name
);
580 else if (g_strcmp0 (mime_type
,"inode/directory") == 0)
582 GFileEnumerator
*dir
;
584 dir
= g_file_enumerate_children (file
,
585 G_FILE_ATTRIBUTE_STANDARD_NAME
"," G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE
,
586 G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS
,
591 /* Look for anjuta project file in the directory */
594 for (info
= g_file_enumerator_next_file (dir
, NULL
, NULL
); info
!= NULL
; info
= g_file_enumerator_next_file (dir
, NULL
, NULL
))
596 gchar
*mime_type
= anjuta_util_get_file_info_mime_type (info
);
598 if (g_strcmp0 (mime_type
, "application/x-anjuta") == 0)
600 /* Open the first anjuta project file */
601 IAnjutaFileLoader
*loader
;
603 loader
= anjuta_shell_get_interface(ANJUTA_PLUGIN (plugin
)->shell
, IAnjutaFileLoader
, NULL
);
606 GFile
* project_file
= g_file_get_child (file
, g_file_info_get_name(info
));
607 ianjuta_file_loader_load(loader
, project_file
, FALSE
, NULL
);
608 g_object_unref (project_file
);
611 g_object_unref (info
);
615 g_object_unref (info
);
619 /* Else import the directory */
620 ProjectImportDialog
* pi
;
621 AnjutaPluginManager
*plugin_manager
;
624 plugin_manager
= anjuta_shell_get_plugin_manager (ANJUTA_PLUGIN (plugin
)->shell
, NULL
);
626 basename
= g_file_get_basename (file
);
627 pi
= project_import_dialog_new (plugin_manager
, basename
, file
);
629 g_signal_connect (pi
, "response", G_CALLBACK (import_dialog_response
), plugin
);
631 gtk_widget_show (GTK_WIDGET (pi
));
633 g_object_unref (dir
);
640 ifile_get_file (IAnjutaFile
*file
, GError
**err
)
642 g_warning ("Unsupported operation");
647 ifile_iface_init (IAnjutaFileIface
*iface
)
649 iface
->open
= ifile_open
;
650 iface
->get_file
= ifile_get_file
;
653 ANJUTA_PLUGIN_BEGIN (AnjutaProjectImportPlugin
, project_import_plugin
);
654 ANJUTA_PLUGIN_ADD_INTERFACE(iwizard
, IANJUTA_TYPE_WIZARD
);
655 ANJUTA_PLUGIN_ADD_INTERFACE(ifile
, IANJUTA_TYPE_FILE
);
658 ANJUTA_SIMPLE_PLUGIN (AnjutaProjectImportPlugin
, project_import_plugin
);