code-analyzer: Fixed bgo#667903 - Code Analyzer Crashes
[anjuta.git] / plugins / file-wizard / file.c
blob48c38fc1aeb2a86f01211288091315afec86b5ae
1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
3 /***************************************************************************
4 * file.c
6 * Sun Nov 30 17:46:54 2003
7 * Copyright 2003 Jean-Noel Guiheneuf
8 * jnoel@lotuscompounds.com
9 ****************************************************************************/
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU Library General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
27 #ifdef HAVE_CONFIG_H
28 # include <config.h>
29 #endif
31 #include <string.h>
32 #include <time.h>
34 #include <libanjuta/interfaces/ianjuta-file.h>
35 #include <libanjuta/interfaces/ianjuta-file-savable.h>
36 #include <libanjuta/interfaces/ianjuta-document-manager.h>
37 #include <libanjuta/interfaces/ianjuta-snippets-manager.h>
38 #include <libanjuta/interfaces/ianjuta-file.h>
39 #include <libanjuta/interfaces/ianjuta-project.h>
40 #include <libanjuta/interfaces/ianjuta-project-manager.h>
41 #include <libanjuta/interfaces/ianjuta-project-chooser.h>
42 #include <libanjuta/interfaces/ianjuta-vcs.h>
44 #include "plugin.h"
45 #include "file.h"
47 #define BUILDER_FILE_FILE PACKAGE_DATA_DIR "/glade/anjuta-file-wizard.ui"
48 #define NEW_FILE_DIALOG "dialog.new.file"
49 #define NEW_FILE_OK_BUTTON "okbutton"
50 #define NEW_FILE_ENTRY "new.file.entry"
51 #define NEW_FILE_TYPE "new.file.type"
52 #define NEW_FILE_TYPE_STORE "new.file.type.store"
53 #define NEW_FILE_TEMPLATE "new.file.template"
54 #define NEW_FILE_HEADER "new.file.header"
55 #define NEW_FILE_LICENSE "new.file.license"
56 #define NEW_FILE_MENU_LICENSE "new.file.menu.license"
57 #define NEW_FILE_MENU_LICENSE_STORE "new.file.menu.license.store"
58 #define NEW_FILE_ADD_TO_PROJECT "add_to_project"
59 #define NEW_FILE_ADD_TO_PROJECT_PARENT "add_to_project.combo.parent"
60 #define NEW_FILE_ADD_TO_REPOSITORY "add_to_repository"
62 typedef struct _NewFileGUI
64 GtkBuilder *bxml;
65 GtkWidget *dialog;
66 GtkWidget *add_to_project;
67 GtkWidget *add_to_repository;
68 GtkWidget *add_to_project_parent;
69 GtkWidget *ok_button;
70 gboolean showing;
71 AnjutaFileWizardPlugin *plugin;
72 } NewFileGUI;
75 typedef struct _NewfileType
77 gchar *name;
78 gchar *ext;
79 gint header;
80 gboolean gpl;
81 gboolean template;
82 Cmt comment;
83 Lge type;
84 } NewfileType;
88 NewfileType new_file_type[] = {
89 {N_("C Source File"), ".c", LGE_HC, TRUE, TRUE, CMT_C, LGE_C},
90 {N_("C/C++ Header File"), ".h", -1, TRUE, TRUE, CMT_C, LGE_HC},
91 {N_("C++ Source File"), ".cxx", LGE_HC, TRUE, TRUE, CMT_CPP, LGE_CPLUS},
92 {N_("C# Source File"), ".c#", -1, FALSE, FALSE, CMT_CPP, LGE_CSHARP},
93 {N_("Java Source File"), ".java", -1, FALSE, FALSE, CMT_CPP, LGE_JAVA},
94 {N_("Perl Source File"), ".pl", -1, TRUE, TRUE, CMT_P, LGE_PERL},
95 {N_("Python Source File"), ".py", -1, TRUE, FALSE, CMT_P, LGE_PYTHON},
96 {N_("Shell Script File"), ".sh", -1, TRUE, TRUE, CMT_P, LGE_SHELL},
97 {N_("Vala Source File"), ".vala", -1, FALSE, CMT_CPP, LGE_VALA},
98 {N_("Other"), NULL, -1, FALSE, FALSE, CMT_C, LGE_C}
102 typedef struct _NewlicenseType
104 gchar *name;
105 const gchar* type;
106 } NewlicenseType;
108 NewlicenseType new_license_type[] = {
109 {N_("General Public License (GPL)"), "GPL"},
110 {N_("Lesser General Public License (LGPL)"), "LGPL"},
111 {N_("BSD Public License"), "BSD"}
114 static NewFileGUI *nfg = NULL;
117 static gboolean create_new_file_dialog(IAnjutaDocumentManager *docman);
118 static void insert_notice(IAnjutaSnippetsManager* snippets_manager, const gchar* license_type, gint comment_type);
119 static void insert_header(IAnjutaSnippetsManager* snippets_manager, gint source_type);
121 static void
122 on_project_parent_changed (GtkWidget *project_combo, NewFileGUI *gui)
124 gboolean active = TRUE;
126 if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (gui->add_to_project)))
128 GFile *file;
130 file = ianjuta_project_chooser_get_selected (IANJUTA_PROJECT_CHOOSER (gui->add_to_project_parent), NULL);
131 active = file != NULL;
133 gtk_widget_set_sensitive (gui->ok_button, active);
136 static void
137 on_add_to_project_toggled (GtkWidget* toggle_button, NewFileGUI *gui)
139 gboolean status = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(toggle_button));
140 gtk_widget_set_sensitive (gui->add_to_repository, status);
141 gtk_widget_set_sensitive (gui->add_to_project_parent, status);
142 if (!status)
144 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(gui->add_to_repository),
145 FALSE);
147 on_project_parent_changed (toggle_button, gui);
150 void
151 display_new_file(AnjutaFileWizardPlugin *plugin,
152 IAnjutaDocumentManager *docman)
154 gint caps = 0;
155 gboolean has_project;
157 if (!nfg)
158 if (!create_new_file_dialog (docman))
159 return;
161 nfg->plugin = plugin;
163 /* check whether we have a loaded project or not */
164 if (plugin->top_dir) {
165 IAnjutaProjectManager *manager =
166 anjuta_shell_get_interface (ANJUTA_PLUGIN (plugin)->shell,
167 IAnjutaProjectManager, NULL);
168 if (manager)
170 caps = ianjuta_project_manager_get_capabilities (manager, NULL);
171 /* Add combo node selection */
172 ianjuta_project_chooser_set_project_model (IANJUTA_PROJECT_CHOOSER (nfg->add_to_project_parent),
173 IANJUTA_PROJECT_MANAGER (manager),
174 ANJUTA_PROJECT_SOURCE,
175 NULL);
176 on_project_parent_changed (nfg->add_to_project_parent, nfg);
180 g_signal_connect (nfg->add_to_project, "toggled",
181 G_CALLBACK(on_add_to_project_toggled),
182 nfg);
183 g_signal_connect (nfg->add_to_project_parent, "changed",
184 G_CALLBACK(on_project_parent_changed),
185 nfg);
187 has_project = (caps & ANJUTA_PROJECT_CAN_ADD_SOURCE) ? TRUE : FALSE;
188 gtk_widget_set_visible (nfg->add_to_project, has_project);
189 gtk_widget_set_visible (nfg->add_to_project_parent, has_project);
190 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (nfg->add_to_project),
191 has_project);
192 gtk_widget_set_sensitive (nfg->add_to_project, has_project);
193 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (nfg->add_to_repository),
194 FALSE);
196 if (nfg && !(nfg->showing))
198 gtk_window_present (GTK_WINDOW (nfg->dialog));
199 nfg->showing = TRUE;
203 static gboolean
204 create_new_file_dialog(IAnjutaDocumentManager *docman)
206 GtkComboBox *optionmenu;
207 GtkListStore *store;
208 GError* error = NULL;
209 gint i;
212 nfg = g_new0(NewFileGUI, 1);
213 nfg->bxml = gtk_builder_new ();
214 if (!gtk_builder_add_from_file (nfg->bxml, BUILDER_FILE_FILE, &error))
216 g_warning ("Couldn't load builder file: %s", error->message);
217 g_error_free (error);
218 g_free(nfg);
219 nfg = NULL;
220 return FALSE;
222 nfg->dialog = GTK_WIDGET (gtk_builder_get_object (nfg->bxml, NEW_FILE_DIALOG));
223 nfg->ok_button = GTK_WIDGET (gtk_builder_get_object (nfg->bxml, NEW_FILE_OK_BUTTON));
224 nfg->add_to_project = GTK_WIDGET (gtk_builder_get_object (nfg->bxml, NEW_FILE_ADD_TO_PROJECT));
225 nfg->add_to_project_parent = GTK_WIDGET (gtk_builder_get_object (nfg->bxml, NEW_FILE_ADD_TO_PROJECT_PARENT));
226 nfg->add_to_repository = GTK_WIDGET (gtk_builder_get_object (nfg->bxml, NEW_FILE_ADD_TO_REPOSITORY));
227 nfg->showing = FALSE;
229 store = GTK_LIST_STORE (gtk_builder_get_object (nfg->bxml, NEW_FILE_TYPE_STORE));
230 for (i=0; i < (sizeof(new_file_type) / sizeof(NewfileType)); i++)
232 GtkTreeIter iter;
234 gtk_list_store_append (store, &iter);
235 gtk_list_store_set (store, &iter, 0, new_file_type[i].name, -1);
237 optionmenu = GTK_COMBO_BOX (gtk_builder_get_object (nfg->bxml, NEW_FILE_TYPE));
238 gtk_combo_box_set_active (optionmenu, 0);
240 store = GTK_LIST_STORE (gtk_builder_get_object (nfg->bxml, NEW_FILE_MENU_LICENSE_STORE));
241 for (i=0; i < (sizeof(new_license_type) / sizeof(NewlicenseType)); i++)
243 GtkTreeIter iter;
245 gtk_list_store_append (store, &iter);
246 gtk_list_store_set (store, &iter, 0, new_license_type[i].name, -1);
248 optionmenu = GTK_COMBO_BOX (gtk_builder_get_object (nfg->bxml, NEW_FILE_MENU_LICENSE));
249 gtk_combo_box_set_active (optionmenu, 0);
251 g_object_set_data (G_OBJECT (nfg->dialog), "IAnjutaDocumentManager", docman);
252 gtk_builder_connect_signals (nfg->bxml, NULL);
253 g_signal_emit_by_name(G_OBJECT (optionmenu), "changed");
255 return TRUE;
258 gboolean
259 on_new_file_cancelbutton_clicked(GtkWidget *window, GdkEvent *event,
260 gboolean user_data)
262 if (nfg->showing)
264 gtk_widget_hide(nfg->dialog);
265 nfg->showing = FALSE;
267 return TRUE;
270 gboolean
271 on_new_file_okbutton_clicked(GtkWidget *window, GdkEvent *event,
272 gboolean user_data)
274 GtkWidget *entry;
275 GtkWidget *checkbutton;
276 GtkWidget *optionmenu;
277 const gchar *name;
278 gchar *header_name = NULL;
279 gint sel;
280 const gchar* license_type;
281 gint comment_type;
282 gint source_type;
283 IAnjutaDocumentManager *docman;
284 GtkWidget *toplevel;
285 IAnjutaSnippetsManager* snippets_manager;
286 IAnjutaEditor *te = NULL;
287 IAnjutaEditor *teh = NULL;
288 gboolean ok = TRUE;
290 toplevel= gtk_widget_get_toplevel (window);
291 docman = IANJUTA_DOCUMENT_MANAGER (g_object_get_data (G_OBJECT(toplevel),
292 "IAnjutaDocumentManager"));
293 snippets_manager = anjuta_shell_get_interface (ANJUTA_PLUGIN(docman)->shell,
294 IAnjutaSnippetsManager, NULL);
295 entry = GTK_WIDGET (gtk_builder_get_object (nfg->bxml, NEW_FILE_ENTRY));
296 name = gtk_entry_get_text(GTK_ENTRY(entry));
298 /* Create main file */
299 if (name && strlen (name) > 0)
300 te = ianjuta_document_manager_add_buffer (docman, name, NULL, NULL);
301 else
302 te = ianjuta_document_manager_add_buffer (docman, "", NULL, NULL);
304 if (te == NULL)
305 return FALSE;
307 /* Create header file */
308 optionmenu = GTK_WIDGET (gtk_builder_get_object (nfg->bxml, NEW_FILE_TYPE));
309 source_type = gtk_combo_box_get_active(GTK_COMBO_BOX(optionmenu));
311 checkbutton = GTK_WIDGET (gtk_builder_get_object (nfg->bxml, NEW_FILE_HEADER));
312 if (gtk_widget_get_sensitive (checkbutton) &&
313 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(checkbutton)))
315 if (name && strlen (name) > 0)
317 const gchar *old_ext = strrchr (name,'.');
318 const gchar *new_ext = new_file_type[new_file_type[source_type].header].ext;
320 if (old_ext == NULL)
322 header_name = g_strconcat (name, new_ext, NULL);
324 else
326 header_name = g_strndup (name, old_ext - name + strlen(new_ext));
327 strcpy(&header_name[old_ext - name], new_ext);
329 teh = ianjuta_document_manager_add_buffer (docman, header_name, NULL, NULL);
331 else
333 teh = ianjuta_document_manager_add_buffer (docman, "", NULL, NULL);
335 ianjuta_document_manager_set_current_document (docman, IANJUTA_DOCUMENT(te), NULL);
338 checkbutton = GTK_WIDGET (gtk_builder_get_object (nfg->bxml, NEW_FILE_TEMPLATE));
339 if (gtk_widget_get_sensitive (checkbutton) &&
340 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(checkbutton)))
342 insert_header(snippets_manager, source_type);
343 if (teh != NULL)
345 ianjuta_document_manager_set_current_document (docman, IANJUTA_DOCUMENT(teh), NULL);
346 insert_header (snippets_manager, new_file_type[source_type].header);
347 ianjuta_document_manager_set_current_document (docman, IANJUTA_DOCUMENT(te), NULL);
351 checkbutton = GTK_WIDGET (gtk_builder_get_object (nfg->bxml, NEW_FILE_LICENSE));
352 if (gtk_widget_get_sensitive (checkbutton) &&
353 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(checkbutton)))
355 optionmenu = GTK_WIDGET (gtk_builder_get_object (nfg->bxml, NEW_FILE_MENU_LICENSE));
356 sel = gtk_combo_box_get_active(GTK_COMBO_BOX(optionmenu));
357 license_type = new_license_type[sel].type;
358 comment_type = new_file_type[source_type].comment;
360 insert_notice(snippets_manager, license_type, comment_type);
361 if (teh != NULL)
363 comment_type = new_file_type[new_file_type[source_type].header].comment;
364 ianjuta_document_manager_set_current_document (docman, IANJUTA_DOCUMENT(teh), NULL);
365 insert_notice(snippets_manager, license_type, comment_type);
366 ianjuta_document_manager_set_current_document (docman, IANJUTA_DOCUMENT(te), NULL);
370 /* Add file to project */
371 if (nfg->plugin->top_dir &&
372 gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (nfg->add_to_project)))
374 IAnjutaProjectManager *pm;
375 GFile *parent;
376 GFile *source;
377 GFile *header = NULL;
379 pm = anjuta_shell_get_interface (ANJUTA_PLUGIN(docman)->shell,
380 IAnjutaProjectManager, NULL);
381 g_return_val_if_fail (pm != NULL, FALSE);
383 parent = ianjuta_project_chooser_get_selected (IANJUTA_PROJECT_CHOOSER (nfg->add_to_project_parent), NULL);
385 /* Save main file */
386 source = ianjuta_project_manager_add_source_quiet (pm, name, parent, NULL);
387 ok = source != NULL;
388 if (ok) ianjuta_file_savable_save_as (IANJUTA_FILE_SAVABLE (te), source, NULL);
390 if (ok && teh)
392 /* Save header file */
393 header = ianjuta_project_manager_add_source_quiet (pm, header_name, parent, NULL);
394 ok = header != NULL;
395 if (ok) ianjuta_file_savable_save_as (IANJUTA_FILE_SAVABLE (teh), header, NULL);
399 /* Add to repository */
400 if (ok && gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (nfg->add_to_repository)))
402 IAnjutaVcs* ivcs = anjuta_shell_get_interface (ANJUTA_PLUGIN(docman)->shell,
403 IAnjutaVcs, NULL);
404 if (ivcs)
406 AnjutaAsyncNotify* notify = anjuta_async_notify_new();
407 GList *file_list = NULL;
409 file_list = g_list_prepend (file_list, source);
410 if (header != NULL) file_list = g_list_prepend (file_list, header);
411 ianjuta_vcs_add (ivcs, file_list, notify, NULL);
412 g_list_free (file_list);
416 /* Re emit element_added for symbol-db */
417 if (source) g_signal_emit_by_name (G_OBJECT (pm), "element_added", source);
418 if (header) g_signal_emit_by_name (G_OBJECT (pm), "element_added", header);
420 if (source) g_object_unref (source);
421 if (header) g_object_unref (header);
423 g_free (header_name);
425 gtk_widget_hide (nfg->dialog);
426 nfg->showing = FALSE;
428 return ok;
431 void
432 on_new_file_entry_changed (GtkEditable *entry, gpointer user_data)
434 char *name;
435 gint sel;
436 static gint last_length = 0;
437 gint length;
438 GtkWidget *optionmenu;
440 name = g_strdup(gtk_entry_get_text(GTK_ENTRY(entry)));
441 length = strlen(name);
443 if (last_length != 2 && length == 1)
445 optionmenu = GTK_WIDGET (gtk_builder_get_object (nfg->bxml, NEW_FILE_TYPE));
446 sel = gtk_combo_box_get_active(GTK_COMBO_BOX(optionmenu));
447 name = g_strconcat (name, new_file_type[sel].ext, NULL);
448 gtk_entry_set_text (GTK_ENTRY(entry), name);
450 last_length = length;
452 g_free(name);
455 void
456 on_new_file_type_changed (GtkComboBox *optionmenu, gpointer user_data)
458 gint sel;
459 char *name, *tmp;
460 GtkWidget *widget;
461 GtkWidget *entry;
463 sel = gtk_combo_box_get_active(optionmenu);
465 widget = GTK_WIDGET (gtk_builder_get_object (nfg->bxml, NEW_FILE_HEADER));
466 gtk_widget_set_sensitive(widget, new_file_type[sel].header >= 0);
467 widget = GTK_WIDGET (gtk_builder_get_object (nfg->bxml, NEW_FILE_LICENSE));
468 gtk_widget_set_sensitive(widget, new_file_type[sel].gpl);
469 widget = GTK_WIDGET (gtk_builder_get_object (nfg->bxml, NEW_FILE_TEMPLATE));
470 gtk_widget_set_sensitive(widget, new_file_type[sel].template);
471 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), FALSE);
473 entry = GTK_WIDGET (gtk_builder_get_object (nfg->bxml, NEW_FILE_ENTRY));
474 name = g_strdup(gtk_entry_get_text(GTK_ENTRY(entry)));
475 if (strlen(name) > 0)
477 tmp = strrchr(name, '.');
478 if (tmp)
479 name = g_strndup(name, tmp - name);
480 name = g_strconcat (name, new_file_type[sel].ext, NULL);
481 gtk_entry_set_text (GTK_ENTRY(entry), name);
483 g_free(name);
486 void
487 on_new_file_license_toggled(GtkToggleButton *button, gpointer user_data)
489 GtkWidget *widget;
491 widget = GTK_WIDGET (gtk_builder_get_object (nfg->bxml, NEW_FILE_MENU_LICENSE));
492 gtk_widget_set_sensitive(widget, gtk_toggle_button_get_active(button));
495 static void
496 insert_notice(IAnjutaSnippetsManager* snippets_manager, const gchar* license_type, gint comment_type)
498 gchar *name;
500 name = g_utf8_strdown (license_type, -1);
501 ianjuta_snippets_manager_insert(snippets_manager, name, FALSE, NULL);
502 g_free (name);
505 static void
506 insert_header(IAnjutaSnippetsManager* snippets_manager, gint source_type)
508 ianjuta_snippets_manager_insert (snippets_manager, "top_com", FALSE, NULL);