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"/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
;
45 project_import_generate_file (AnjutaPluginHandle
*backend
, ProjectImportDialog
*import_dialog
,
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
;
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
);
68 if (source_file
!= NULL
)
70 /* Use a default project file */
71 if (!g_file_copy (source_file
, project_file
,
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
))
87 g_file_copy (source_file
, project_file
,
88 G_FILE_COPY_OVERWRITE
,
100 time_t ctime
= time(NULL
);
101 GFileInfo
* file_info
= g_file_info_new();
102 g_file_info_set_attribute_uint64(file_info
,
105 g_file_info_set_attribute_uint64(file_info
,
108 g_file_info_set_attribute_uint64(file_info
,
111 g_file_set_attributes_from_info (project_file
,
113 G_FILE_QUERY_INFO_NONE
,
116 g_object_unref (G_OBJECT(file_info
));;
121 /* For unknown project backend we use the directory project file and
122 * replace the backend plugin with the right one */
127 source_file
= g_file_new_for_path (DIRECTORY_PROJECT_FILE
);
128 if (g_file_load_contents (source_file
, NULL
, &content
, &length
, NULL
, &error
))
133 const gchar
*end_plugin
;
136 buffer
= g_string_new_len (content
, length
);
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");
159 /* Replace directory backend with right one */
161 GFileOutputStream
*stream
;
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"
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
);
194 stream
= g_file_replace (project_file
, NULL
, FALSE
, G_FILE_CREATE_REPLACE_DESTINATION
, NULL
, &error
);
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
);
212 g_object_unref (source_file
);
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
);
228 g_error_free (error
);
238 project_import_import_project (AnjutaProjectImportPlugin
*import_plugin
, ProjectImportDialog
*import_dialog
,
241 AnjutaPluginManager
*plugin_manager
;
242 GList
*handles
= NULL
;
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
,
252 "IAnjutaProjectBackend",
254 for (node
= g_list_first (handles
); node
!= NULL
;) {
255 IAnjutaProjectBackend
*plugin
;
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
);
277 else if (g_list_next (handles
) == NULL
)
279 backend
= (AnjutaPluginHandle
*)handles
->data
;
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
);
289 backend
= anjuta_plugin_manager_select (plugin_manager
,
295 g_list_free (handles
);
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 "
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
);
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
);
331 loader
= anjuta_shell_get_interface (ANJUTA_PLUGIN (import_plugin
)->shell
,
332 IAnjutaFileLoader
, NULL
);
335 g_warning("No IAnjutaFileLoader interface! Cannot open project file!");
336 g_object_unref (project_file
);
340 ianjuta_file_loader_load (loader
, project_file
, FALSE
, NULL
);
342 g_object_unref (project_file
);
349 AnjutaProjectImportPlugin
*import_plugin
;
350 ProjectImportDialog
*import_dialog
;
355 checkout_finished (AnjutaAsyncNotify
*async_notify
, gpointer user_data
)
357 CheckoutData
*ch
= (CheckoutData
*)user_data
;
361 anjuta_async_notify_get_error (async_notify
, &err
);
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
);
381 project_import_import_project (ch
->import_plugin
, ch
->import_dialog
, ch
->checkout_dir
);
384 g_object_unref (ch
->checkout_dir
);
385 g_slice_free (CheckoutData
, ch
);
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
;
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_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
));
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
));
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
);
452 case GTK_RESPONSE_ACCEPT
:
456 source_dir
= project_import_dialog_get_source_dir (import_dialog
);
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
);
465 project_import_checkout_project (import_plugin
, import_dialog
);
470 case GTK_RESPONSE_REJECT
:
471 gtk_widget_destroy (GTK_WIDGET (dialog
));
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
);
489 deactivate_plugin (AnjutaPlugin
*plugin
)
495 dispose (GObject
*obj
)
497 G_OBJECT_CLASS (parent_class
)->dispose (obj
);
501 finalize (GObject
*obj
)
503 G_OBJECT_CLASS (parent_class
)->finalize (obj
);
507 project_import_plugin_instance_init (GObject
*obj
)
509 // AnjutaFileWizardPlugin *plugin = ANJUTA_PLUGIN_PROJECT_IMPORT (obj);
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
;
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
));
541 iwizard_iface_init (IAnjutaWizardIface
*iface
)
543 iface
->activate
= iwizard_activate
;
547 ifile_open (IAnjutaFile
*ifile
, GFile
* file
, GError
**err
)
549 AnjutaProjectImportPlugin
* plugin
= ANJUTA_PLUGIN_PROJECT_IMPORT (ifile
);
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
;
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
, '.');
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
,
590 /* Look for anjuta project file in the directory */
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
);
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
);
610 g_object_unref (info
);
614 g_object_unref (info
);
618 /* Else import the directory */
619 ProjectImportDialog
* pi
;
620 AnjutaPluginManager
*plugin_manager
;
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
);
628 g_signal_connect (pi
, "response", G_CALLBACK (import_dialog_response
), plugin
);
630 gtk_widget_show (GTK_WIDGET (pi
));
632 g_object_unref (dir
);
639 ifile_get_file (IAnjutaFile
*file
, GError
**err
)
641 g_warning ("Unsupported operation");
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
);
657 ANJUTA_SIMPLE_PLUGIN (AnjutaProjectImportPlugin
, project_import_plugin
);