2008-04-12 Johannes Schmid <jhs@gnome.org>
[anjuta-git-plugin.git] / plugins / project-import / project-import.c
blob8610ba733a1aad5440b718dbb599afe8a16c00f9
1 /*
2 * project-import.c (c) 2005 Johannes Schmid
3 * 2008 Ignacio Casal Quinteiro
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU Library General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 #include "project-import.h"
21 #include <libgnomevfs/gnome-vfs.h>
22 #include <libanjuta/interfaces/ianjuta-file-loader.h>
23 #include <libanjuta/anjuta-debug.h>
25 #include <config.h>
27 #include <gbf/gbf-backend.h>
29 #define AM_PROJECT_FILE PACKAGE_DATA_DIR"/project/terminal/project.anjuta"
30 #define MKFILE_PROJECT_FILE PACKAGE_DATA_DIR"/project/mkfile/project.anjuta"
32 static GObjectClass *parent_class = NULL;
34 static void
35 on_import_cancel (GtkAssistant* assistant, ProjectImport* pi)
37 g_object_unref (G_OBJECT(pi));
40 static gboolean
41 on_import_key_press_event(GtkWidget *widget, GdkEventKey *event,
42 ProjectImport* pi)
44 if (event->keyval == GDK_Escape)
46 g_object_unref(G_OBJECT(pi));
47 return TRUE;
49 return FALSE;
52 static void
53 on_import_next(GtkAssistant *assistant, GtkWidget *page, ProjectImport *pi)
55 GSList* l;
56 GbfBackend* backend = NULL;
57 GbfProject* proj;
59 if (page != pi->import_finish)
60 return;
62 const gchar* name = gtk_entry_get_text (GTK_ENTRY (pi->import_name));
63 gchar* path = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (pi->import_path));
65 if (!name || !path || !strlen(name) || !strlen(path))
67 g_free (path);
68 return;
71 gbf_backend_init();
73 for (l = gbf_backend_get_backends (); l; l = l->next) {
74 backend = l->data;
75 if (!backend)
77 g_warning("Backend appears empty!");
78 continue;
81 /* Probe the backend to find out if the project directory is OK */
82 /* If probe() returns TRUE then we have a valid backend */
84 proj = gbf_backend_new_project(backend->id);
85 if (proj)
87 if (gbf_project_probe(proj, path, NULL))
89 /* This is a valid backend for this root directory */
90 /* FIXME: Possibility of more than one valid backend? */
91 g_object_unref(proj);
92 break;
94 g_object_unref(proj);
96 backend = NULL;
99 if (!backend)
101 gchar* message_text =
102 g_strdup_printf(_("Could not find a valid project backend for the "
103 "directory given (%s). Please select a different "
104 "directory, or try upgrading to a newer version of "
105 "the Gnome Build Framework."), path);
107 GtkDialog* message =
108 GTK_DIALOG(gtk_message_dialog_new(GTK_WINDOW(pi->assistant),
109 GTK_DIALOG_DESTROY_WITH_PARENT,
110 GTK_MESSAGE_ERROR,
111 GTK_BUTTONS_CLOSE,
112 message_text));
114 g_free(message_text);
116 gtk_dialog_run(message);
117 gtk_widget_destroy(GTK_WIDGET(message));
118 g_free (path);
121 * Now we can't apply
123 gtk_label_set_text (GTK_LABEL (pi->import_finish), _("Please, fix the configuration"));
124 gtk_assistant_set_page_complete (GTK_ASSISTANT (pi->assistant), pi->import_finish, FALSE);
125 return;
128 gchar* summary;
130 summary = g_strdup_printf(_("Project name: %s\n"
131 "Project type: %s\n"
132 "Project path: %s\n"),
133 name, backend->name, path);
134 gtk_label_set_text (GTK_LABEL (pi->import_finish),
135 summary);
137 g_free(summary);
140 * If we are here, everything is ok
142 gtk_assistant_set_page_complete (GTK_ASSISTANT (pi->assistant), pi->import_finish, TRUE);
144 if (pi->backend_id)
145 g_free(pi->backend_id);
146 pi->backend_id = g_strdup(backend->id);
147 g_free (path);
150 static void
151 on_import_apply (GtkAssistant *assistant, ProjectImport* pi)
153 const gchar* name = gtk_entry_get_text (GTK_ENTRY(pi->import_name));
154 gchar* path = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER(pi->import_path));
156 gchar* project_file = g_strconcat (path, "/", name, ".", "anjuta", NULL);
158 IAnjutaFileLoader* loader;
160 if (!project_import_generate_file (pi, project_file))
162 g_free (project_file);
163 g_free (path);
164 return;
167 loader = anjuta_shell_get_interface (ANJUTA_PLUGIN (pi->plugin)->shell,
168 IAnjutaFileLoader, NULL);
169 if (!loader)
171 g_warning("No IAnjutaFileLoader interface! Cannot open project file!");
172 g_free (project_file);
173 return;
175 ianjuta_file_loader_load (loader, project_file, FALSE, NULL);
176 g_free (project_file);
177 g_free (path);
180 static void
181 create_start_page (ProjectImport *pi)
183 GtkWidget *box, *label;
185 box = gtk_hbox_new (FALSE, 12);
186 gtk_widget_show (box);
187 gtk_container_set_border_width (GTK_CONTAINER (box), 12);
189 label = gtk_label_new (_("This assistant will import an existing project into Anjuta."));
190 gtk_widget_show (label);
191 gtk_box_pack_start (GTK_BOX (box), label, FALSE, FALSE, 0);
193 gtk_assistant_append_page (GTK_ASSISTANT (pi->assistant), box);
194 gtk_assistant_set_page_title (GTK_ASSISTANT (pi->assistant), box, _("Import Project"));
195 gtk_assistant_set_page_complete (GTK_ASSISTANT (pi->assistant), box, TRUE);
196 gtk_assistant_set_page_type (GTK_ASSISTANT (pi->assistant), box, GTK_ASSISTANT_PAGE_INTRO);
199 static void
200 on_entry_changed (GtkWidget *widget, gpointer data)
202 GtkAssistant *assistant = GTK_ASSISTANT (data);
203 GtkWidget *current_page;
204 gint page_number;
205 const gchar *text;
207 page_number = gtk_assistant_get_current_page (assistant);
208 current_page = gtk_assistant_get_nth_page (assistant, page_number);
209 text = gtk_entry_get_text (GTK_ENTRY (widget));
211 if (text && *text)
212 gtk_assistant_set_page_complete (assistant, current_page, TRUE);
213 else
214 gtk_assistant_set_page_complete (assistant, current_page, FALSE);
217 static void
218 create_import_page (ProjectImport *pi)
220 GtkWidget *box, *vbox1, *vbox2;
221 GtkWidget *label;
223 box = gtk_vbox_new (FALSE, 12);
224 gtk_widget_show (box);
225 gtk_container_set_border_width (GTK_CONTAINER (box), 5);
228 * Project name:
230 vbox1 = gtk_vbox_new (FALSE, 12);
231 gtk_widget_show (vbox1);
232 gtk_box_pack_start (GTK_BOX (box), vbox1, FALSE, FALSE, 0);
234 label = gtk_label_new (NULL);
235 gtk_label_set_markup (GTK_LABEL (label),
236 _("<b>Enter the project name:</b>"));
237 gtk_widget_show (label);
238 gtk_box_pack_start (GTK_BOX (vbox1), label, FALSE, FALSE, 0);
240 pi->import_name = gtk_entry_new ();
241 gtk_widget_show (pi->import_name);
242 gtk_box_pack_start (GTK_BOX (vbox1), pi->import_name, FALSE, FALSE, 0);
243 g_signal_connect (G_OBJECT (pi->import_name), "changed",
244 G_CALLBACK (on_entry_changed), pi->assistant);
247 * Base path:
249 vbox2 = gtk_vbox_new (FALSE, 12);
250 gtk_widget_show (vbox2);
251 gtk_box_pack_start (GTK_BOX (box), vbox2, FALSE, FALSE, 0);
253 label = gtk_label_new (NULL);
254 gtk_label_set_markup (GTK_LABEL (label),
255 _("<b>Enter the base path of your project:</b>"));
256 gtk_widget_show (label);
257 gtk_box_pack_start (GTK_BOX (vbox2), label, FALSE, FALSE, 0);
259 pi->import_path = gtk_file_chooser_button_new (_("Select project directory"),
260 GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER);
261 gtk_widget_show (pi->import_path);
262 gtk_box_pack_start (GTK_BOX (vbox2), pi->import_path, FALSE, FALSE, 0);
264 gtk_assistant_append_page (GTK_ASSISTANT (pi->assistant), box);
265 gtk_assistant_set_page_title (GTK_ASSISTANT (pi->assistant), box, _("Project to Import"));
268 static void
269 create_finish_page (ProjectImport *pi)
271 pi->import_finish = gtk_label_new (NULL);
272 gtk_widget_show (pi->import_finish);
274 gtk_assistant_append_page (GTK_ASSISTANT (pi->assistant), pi->import_finish);
275 gtk_assistant_set_page_type (GTK_ASSISTANT (pi->assistant), pi->import_finish,
276 GTK_ASSISTANT_PAGE_CONFIRM);
277 gtk_assistant_set_page_complete (GTK_ASSISTANT (pi->assistant), pi->import_finish, TRUE);
278 gtk_assistant_set_page_title (GTK_ASSISTANT (pi->assistant), pi->import_finish, _("Confirmation"));
281 static void
282 project_import_init (ProjectImport *pi)
284 pi->assistant = gtk_assistant_new ();
285 create_start_page (pi);
286 create_import_page (pi);
287 create_finish_page (pi);
289 pi->backend_id = NULL;
291 g_signal_connect(G_OBJECT (pi->assistant), "prepare",
292 G_CALLBACK(on_import_next), pi);
293 g_signal_connect(G_OBJECT (pi->assistant), "apply",
294 G_CALLBACK (on_import_apply), pi);
295 g_signal_connect(G_OBJECT (pi->assistant), "cancel",
296 G_CALLBACK (on_import_cancel), pi);
297 g_signal_connect(G_OBJECT (pi->assistant), "close",
298 G_CALLBACK (on_import_cancel), pi);
299 g_signal_connect(G_OBJECT(pi->assistant), "key-press-event",
300 G_CALLBACK(on_import_key_press_event), pi);
302 gtk_widget_show (pi->assistant);
305 static void
306 project_import_finalize(GObject *object)
308 ProjectImport *cobj;
309 cobj = PROJECT_IMPORT(object);
311 DEBUG_PRINT ("Finalizing ProjectImport object");
313 if (cobj->backend_id)
314 g_free(cobj->backend_id);
316 gtk_widget_destroy(cobj->assistant);
318 /* Deactivate plugin once wizard is finished */
319 if (anjuta_plugin_is_active(cobj->plugin))
320 anjuta_plugin_deactivate (cobj->plugin);
321 G_OBJECT_CLASS(parent_class)->finalize(object);
324 static void
325 project_import_class_init(ProjectImportClass *klass)
327 GObjectClass *object_class = G_OBJECT_CLASS(klass);
329 parent_class = g_type_class_peek_parent(klass);
330 object_class->finalize = project_import_finalize;
333 GType
334 project_import_get_type()
336 static GType type = 0;
338 if(type == 0) {
339 static const GTypeInfo our_info = {
340 sizeof (ProjectImportClass),
341 NULL,
342 NULL,
343 (GClassInitFunc)project_import_class_init,
344 NULL,
345 NULL,
346 sizeof (ProjectImport),
348 (GInstanceInitFunc)project_import_init,
351 type = g_type_register_static(G_TYPE_OBJECT,
352 "ProjectImport", &our_info, 0);
355 return type;
358 ProjectImport *
359 project_import_new(AnjutaPlugin* plugin)
361 ProjectImport *obj;
363 obj = PROJECT_IMPORT(g_object_new(PROJECT_IMPORT_TYPE, NULL));
365 obj->plugin = plugin;
366 gtk_window_set_transient_for (GTK_WINDOW (obj->assistant),
367 GTK_WINDOW (ANJUTA_PLUGIN (plugin)->shell));
369 return obj;
372 void
373 project_import_set_name (ProjectImport *pi, const gchar *name)
375 g_return_if_fail (IS_PROJECT_IMPORT (pi));
376 g_return_if_fail (name != NULL);
378 gtk_entry_set_text (GTK_ENTRY (pi->import_name), name);
381 void
382 project_import_set_directory (ProjectImport *pi, const gchar *directory)
384 g_return_if_fail (IS_PROJECT_IMPORT (pi));
385 g_return_if_fail (directory != NULL);
387 gchar* uri = gnome_vfs_make_uri_from_input (directory);
388 gtk_file_chooser_set_uri (GTK_FILE_CHOOSER (pi->import_path), uri);
389 g_free (uri);
392 gboolean
393 project_import_generate_file(ProjectImport* pi, const gchar* prjfile)
395 /* Of course we could do some more intelligent stuff here
396 and check which plugins are really needed but for now we just
397 take a default project file. */
399 GnomeVFSURI* source_uri;
400 if (!strcmp (pi->backend_id, "gbf-am:GbfAmProject"))
401 source_uri = gnome_vfs_uri_new(AM_PROJECT_FILE);
402 else if (!strcmp (pi->backend_id, "gbf-mkfile:GbfMkfileProject"))
403 source_uri = gnome_vfs_uri_new(MKFILE_PROJECT_FILE);
404 else
406 /* We shouldn't get here, unless someone has upgraded their GBF */
407 /* but not Anjuta. */
409 GtkWidget *dlg;
411 dlg = gtk_message_dialog_new(GTK_WINDOW(pi->assistant),
412 GTK_DIALOG_DESTROY_WITH_PARENT,
413 GTK_MESSAGE_ERROR,
414 GTK_BUTTONS_CLOSE,
415 _("Generation of project file failed. Cannot "
416 "find an appropriate project template to "
417 "use. Please make sure your version of "
418 "Anjuta is up to date."));
420 gtk_dialog_run(GTK_DIALOG(dlg));
421 gtk_widget_destroy (dlg);
422 return FALSE;
425 GnomeVFSURI* dest_uri = gnome_vfs_uri_new(prjfile);
427 GnomeVFSResult error = gnome_vfs_xfer_uri (source_uri,
428 dest_uri,
429 GNOME_VFS_XFER_DEFAULT,
430 GNOME_VFS_XFER_ERROR_MODE_ABORT,
431 GNOME_VFS_XFER_OVERWRITE_MODE_ABORT,
432 NULL,
433 NULL);
434 /* Handle already existing file */
435 if (error == GNOME_VFS_ERROR_FILE_EXISTS)
437 if (anjuta_util_dialog_boolean_question (GTK_WINDOW (pi->assistant),
438 _("A file named \"%s\" already exists. "
439 "Do you want to replace it?"), prjfile))
441 error = gnome_vfs_xfer_uri (source_uri,
442 dest_uri,
443 GNOME_VFS_XFER_DEFAULT,
444 GNOME_VFS_XFER_ERROR_MODE_ABORT,
445 GNOME_VFS_XFER_OVERWRITE_MODE_REPLACE,
446 NULL,
447 NULL);
451 /* Update file time if possible */
452 if (error == GNOME_VFS_OK)
454 GnomeVFSFileInfo *file_info;
456 file_info = gnome_vfs_file_info_new ();
457 file_info->ctime = time (NULL);
458 file_info->mtime = file_info->ctime;
459 file_info->atime = file_info->ctime;
461 gnome_vfs_set_file_info_uri (dest_uri,
462 file_info,
463 GNOME_VFS_SET_FILE_INFO_TIME);
465 gnome_vfs_file_info_unref (file_info);
468 gnome_vfs_uri_unref (source_uri);
469 gnome_vfs_uri_unref (dest_uri);
471 switch (error)
473 case GNOME_VFS_OK:
474 break;
475 case GNOME_VFS_ERROR_FILE_EXISTS:
476 return FALSE;
477 default:
478 anjuta_util_dialog_error (GTK_WINDOW (pi->assistant),
479 _("A file named \"%s\" cannot be written: %s. "
480 "Check if you have write access to the project directory."),
481 prjfile, gnome_vfs_result_to_string (error));
483 return FALSE;
486 return TRUE;