Compilation fix
[geanyprj.git] / src / menu.c
blob1da811d0f2848c7757d6a211c53434b322378e49
1 /*
2 * geanyprj - Alternative project support for geany light IDE.
4 * Copyright 2008 Yura Siamashka <yurand2@gmail.com>
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 3 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, see <http://www.gnu.org/licenses/>.
20 #include <sys/time.h>
21 #include <gdk/gdkkeysyms.h>
22 #include <glib/gstdio.h>
24 #include "geany.h"
25 #include "support.h"
26 #include "prefs.h"
27 #include "plugindata.h"
28 #include "document.h"
29 #include "filetypes.h"
30 #include "keybindings.h"
31 #include "utils.h"
32 #include "ui_utils.h"
33 #include "pluginmacros.h"
35 #include "project.h"
37 #include "geanyprj.h"
39 PluginFields *plugin_fields;
40 extern GeanyData *geany_data;
41 extern GeanyFunctions *geany_functions;
44 static struct
46 GtkWidget *new_project;
47 GtkWidget *delete_project;
49 GtkWidget *add_file;
51 GtkWidget *preferences;
53 GtkWidget *find_in_files;
54 } menu_items;
56 // simple struct to keep references to the elements of the properties dialog
57 typedef struct _PropertyDialogElements
59 GtkWidget *dialog;
60 GtkWidget *name;
61 GtkWidget *description;
62 GtkWidget *file_name;
63 GtkWidget *base_path;
64 GtkWidget *make_in_base_path;
65 GtkWidget *run_cmd;
66 GtkWidget *regenerate;
67 GtkWidget *type;
68 GtkWidget *patterns;
69 } PropertyDialogElements;
71 static PropertyDialogElements *
72 build_properties_dialog(gboolean properties)
74 GtkWidget *vbox;
75 GtkWidget *table;
76 GtkWidget *image;
77 GtkWidget *button;
78 GtkWidget *bbox;
79 GtkWidget *label;
80 GtkTooltips *tooltips =
81 GTK_TOOLTIPS(p_support->lookup_widget(main_widgets->window, "tooltips"));
82 PropertyDialogElements *e;
83 gchar *dir = NULL;
84 gchar *basename = NULL;
85 gint idx;
86 gint i;
88 idx = p_document->get_cur_idx();
89 if (DOC_IDX_VALID(idx) &&
90 documents[idx]->file_name != NULL && g_path_is_absolute(documents[idx]->file_name))
92 dir = g_path_get_dirname(documents[idx]->file_name);
94 else
96 dir = g_strdup("");
98 basename = g_path_get_basename(dir);
100 e = g_new0(PropertyDialogElements, 1);
102 if (properties)
104 e->dialog =
105 gtk_dialog_new_with_buttons(_("Project Preferences"),
106 GTK_WINDOW(main_widgets->window),
107 GTK_DIALOG_DESTROY_WITH_PARENT,
108 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
109 GTK_STOCK_OK, GTK_RESPONSE_OK, NULL);
111 else
113 e->dialog =
114 gtk_dialog_new_with_buttons(_("New Project"),
115 GTK_WINDOW(main_widgets->window),
116 GTK_DIALOG_DESTROY_WITH_PARENT,
117 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, NULL);
119 gtk_widget_set_name(e->dialog, "GeanyDialogProject");
120 bbox = gtk_hbox_new(FALSE, 0);
121 button = gtk_button_new();
122 image = gtk_image_new_from_stock("gtk-new", GTK_ICON_SIZE_BUTTON);
123 label = gtk_label_new_with_mnemonic(_("C_reate"));
124 gtk_box_pack_start(GTK_BOX(bbox), image, FALSE, FALSE, 3);
125 gtk_box_pack_start(GTK_BOX(bbox), label, FALSE, FALSE, 3);
126 gtk_container_add(GTK_CONTAINER(button), bbox);
127 gtk_dialog_add_action_widget(GTK_DIALOG(e->dialog), button, GTK_RESPONSE_OK);
130 vbox = p_ui->dialog_vbox_new(GTK_DIALOG(e->dialog));
132 table = gtk_table_new(5, 2, FALSE);
133 gtk_table_set_row_spacings(GTK_TABLE(table), 5);
134 gtk_table_set_col_spacings(GTK_TABLE(table), 10);
136 label = gtk_label_new(_("Name:"));
137 gtk_misc_set_alignment(GTK_MISC(label), 1, 0);
139 e->name = gtk_entry_new();
140 gtk_entry_set_max_length(GTK_ENTRY(e->name), MAX_NAME_LEN);
141 gtk_entry_set_text(GTK_ENTRY(e->name), basename);
143 p_ui->table_add_row(GTK_TABLE(table), 0, label, e->name, NULL);
145 label = gtk_label_new(_("Location:"));
146 gtk_misc_set_alignment(GTK_MISC(label), 1, 0);
147 e->file_name = gtk_entry_new();
148 gtk_entry_set_width_chars(GTK_ENTRY(e->file_name), 30);
150 if (properties)
152 gtk_widget_set_sensitive(e->file_name, FALSE);
153 p_ui->table_add_row(GTK_TABLE(table), 1, label, e->file_name, NULL);
155 else
157 button = gtk_button_new();
158 image = gtk_image_new_from_stock("gtk-open", GTK_ICON_SIZE_BUTTON);
159 gtk_container_add(GTK_CONTAINER(button), image);
160 bbox = p_ui->path_box_new(_("Choose Project Location"),
161 GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
162 GTK_ENTRY(e->file_name));
163 gtk_entry_set_text(GTK_ENTRY(e->file_name), dir);
164 p_ui->table_add_row(GTK_TABLE(table), 1, label, bbox, NULL);
168 label = gtk_label_new(_("Base path:"));
169 gtk_misc_set_alignment(GTK_MISC(label), 1, 0);
171 e->base_path = gtk_entry_new();
172 gtk_tooltips_set_tip(tooltips, e->base_path,
173 _("Base directory of all files that make up the project. "
174 "This can be a new path, or an existing directory tree. "
175 "You can use paths relative to the project filename."), NULL);
176 bbox = p_ui->path_box_new(_("Choose Project Base Path"),
177 GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER, GTK_ENTRY(e->base_path));
178 gtk_entry_set_text(GTK_ENTRY(e->base_path), dir);
180 p_ui->table_add_row(GTK_TABLE(table), 2, label, bbox, NULL);
182 label = gtk_label_new(_(""));
183 e->regenerate = gtk_check_button_new_with_label(_("Generate file list on load"));
184 gtk_tooltips_set_tip(tooltips, e->regenerate,
185 _("Automatically add files that match project type on project load "
186 "automaticly. You can't manually add/remove files if "
187 "you checked this option, since your modification will be lost on "
188 "on next project load"), NULL);
189 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(e->regenerate), TRUE);
190 p_ui->table_add_row(GTK_TABLE(table), 3, label, e->regenerate, NULL);
193 label = gtk_label_new(_("Type:"));
194 gtk_misc_set_alignment(GTK_MISC(label), 1, 0);
196 e->type = gtk_combo_box_new_text();
197 for (i = 0; i < NEW_PROJECT_TYPE_SIZE; i++)
198 gtk_combo_box_append_text(GTK_COMBO_BOX(e->type), project_type_string[i]);
199 gtk_combo_box_set_active(GTK_COMBO_BOX(e->type), 0);
201 p_ui->table_add_row(GTK_TABLE(table), 4, label, e->type, NULL);
203 gtk_container_add(GTK_CONTAINER(vbox), table);
204 g_free(dir);
205 g_free(basename);
207 return e;
210 void
211 on_new_project(G_GNUC_UNUSED GtkMenuItem * menuitem, G_GNUC_UNUSED gpointer user_data)
213 PropertyDialogElements *e;
214 gint response;
216 e = build_properties_dialog(FALSE);
217 gtk_widget_show_all(e->dialog);
219 retry:
220 response = gtk_dialog_run(GTK_DIALOG(e->dialog));
221 if (response == GTK_RESPONSE_OK)
223 gchar *path;
224 struct PluginProject *prj;
226 path = g_build_filename(gtk_entry_get_text(GTK_ENTRY(e->file_name)), ".geanyprj",
227 NULL);
229 if (g_file_test(path, G_FILE_TEST_EXISTS))
231 p_ui->set_statusbar(TRUE, _("Project file \"%s\" already exists"), path);
232 g_free(path);
233 goto retry;
235 prj = geany_project_new();
237 geany_project_set_path(prj, path);
238 geany_project_set_base_path(prj, gtk_entry_get_text(GTK_ENTRY(e->base_path)));
239 geany_project_set_name(prj, gtk_entry_get_text(GTK_ENTRY(e->name)));
240 geany_project_set_description(prj, "");
241 geany_project_set_run_cmd(prj, "");
242 geany_project_set_type_int(prj, gtk_combo_box_get_active(GTK_COMBO_BOX(e->type)));
243 geany_project_set_regenerate(prj,
244 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON
245 (e->regenerate)));
247 geany_project_regenerate_file_list(prj);
249 geany_project_save(prj);
250 geany_project_free(prj);
251 p_document->open_file(path, FALSE, NULL, NULL);
254 gtk_widget_destroy(e->dialog);
255 g_free(e);
258 void
259 on_preferences(G_GNUC_UNUSED GtkMenuItem * menuitem, G_GNUC_UNUSED gpointer user_data)
261 PropertyDialogElements *e;
262 gint response;
263 gchar *project_dir;
265 e = build_properties_dialog(TRUE);
267 project_dir = g_path_get_dirname(g_current_project->path);
268 gtk_entry_set_text(GTK_ENTRY(e->file_name), project_dir);
269 gtk_entry_set_text(GTK_ENTRY(e->name), g_current_project->name);
270 gtk_entry_set_text(GTK_ENTRY(e->base_path), g_current_project->base_path);
271 gtk_combo_box_set_active(GTK_COMBO_BOX(e->type), g_current_project->type);
272 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(e->regenerate),
273 g_current_project->regenerate);
275 gtk_widget_show_all(e->dialog);
277 response = gtk_dialog_run(GTK_DIALOG(e->dialog));
278 if (response == GTK_RESPONSE_OK)
280 geany_project_set_base_path(g_current_project,
281 gtk_entry_get_text(GTK_ENTRY(e->base_path)));
282 geany_project_set_name(g_current_project, gtk_entry_get_text(GTK_ENTRY(e->name)));
283 geany_project_set_description(g_current_project, "");
284 geany_project_set_run_cmd(g_current_project, "");
285 geany_project_set_type_int(g_current_project,
286 gtk_combo_box_get_active(GTK_COMBO_BOX(e->type)));
287 geany_project_set_regenerate(g_current_project,
288 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON
289 (e->regenerate)));
290 geany_project_save(g_current_project);
292 if (g_current_project->regenerate)
294 geany_project_regenerate_file_list(g_current_project);
296 sidebar_refresh();
299 gtk_widget_destroy(e->dialog);
300 g_free(e);
301 g_free(project_dir);
304 void
305 on_delete_project(G_GNUC_UNUSED GtkMenuItem * menuitem, G_GNUC_UNUSED gpointer user_data)
307 gchar *path;
308 if (!g_current_project)
309 return;
311 if (p_dialogs->show_question("Do you really wish to delete current project:\n%s?",
312 g_current_project->name))
314 path = p_utils->get_locale_from_utf8(g_current_project->path);
315 xproject_close(FALSE);
316 g_unlink(path);
317 g_free(path);
321 void
322 on_add_file(G_GNUC_UNUSED GtkMenuItem * menuitem, G_GNUC_UNUSED gpointer user_data)
324 gint idx;
326 idx = p_document->get_cur_idx();
327 g_return_if_fail(DOC_IDX_VALID(idx) &&
328 documents[idx]->file_name != NULL &&
329 g_path_is_absolute(documents[idx]->file_name));
331 if (!g_current_project)
332 return;
334 xproject_add_file(documents[idx]->file_name);
337 void
338 on_find_in_project(G_GNUC_UNUSED GtkMenuItem * menuitem, G_GNUC_UNUSED gpointer user_data)
340 gchar *dir;
341 if (!g_current_project)
342 return;
344 dir = g_path_get_dirname(g_current_project->path);
345 setptr(dir, g_build_filename(dir, g_current_project->base_path, NULL));
346 p_search->show_find_in_files_dialog(dir);
347 g_free(dir);
350 static void
351 update_menu_items()
353 gint idx;
354 gboolean cur_file_exists;
355 gboolean badd_file;
357 idx = p_document->get_cur_idx();
359 cur_file_exists = DOC_IDX_VALID(idx) &&
360 documents[idx]->file_name != NULL && g_path_is_absolute(documents[idx]->file_name);
362 badd_file = (g_current_project ? TRUE : FALSE) &&
363 !g_current_project->regenerate &&
364 cur_file_exists &&
365 !g_hash_table_lookup(g_current_project->tags, documents[idx]->file_name);
367 gtk_widget_set_sensitive(menu_items.new_project, TRUE);
368 gtk_widget_set_sensitive(menu_items.delete_project, g_current_project ? TRUE : FALSE);
370 gtk_widget_set_sensitive(menu_items.add_file, badd_file);
372 gtk_widget_set_sensitive(menu_items.preferences, g_current_project ? TRUE : FALSE);
374 gtk_widget_set_sensitive(menu_items.find_in_files, g_current_project ? TRUE : FALSE);
377 void
378 tools_menu_init()
380 GtkWidget *item, *image;
382 GtkWidget *menu_prj = NULL;
383 GtkWidget *menu_prj_menu = NULL;
384 GtkTooltips *tooltips = NULL;
386 tooltips = gtk_tooltips_new();
388 menu_prj = gtk_image_menu_item_new_with_mnemonic(_("_Project"));
389 gtk_container_add(GTK_CONTAINER(main_widgets->tools_menu), menu_prj);
391 g_signal_connect((gpointer) menu_prj, "activate", G_CALLBACK(update_menu_items), NULL);
393 menu_prj_menu = gtk_menu_new();
394 gtk_menu_item_set_submenu(GTK_MENU_ITEM(menu_prj), menu_prj_menu);
399 image = gtk_image_new_from_stock(GTK_STOCK_NEW, GTK_ICON_SIZE_MENU);
400 item = gtk_image_menu_item_new_with_mnemonic(_("New Project"));
401 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item), image);
402 gtk_widget_show(item);
403 gtk_container_add(GTK_CONTAINER(menu_prj_menu), item);
404 g_signal_connect((gpointer) item, "activate", G_CALLBACK(on_new_project), NULL);
405 menu_items.new_project = item;
407 image = gtk_image_new_from_stock(GTK_STOCK_DELETE, GTK_ICON_SIZE_MENU);
408 gtk_widget_show(image);
409 item = gtk_image_menu_item_new_with_mnemonic(_("Delete Project"));
410 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item), image);
411 gtk_widget_show(item);
412 gtk_container_add(GTK_CONTAINER(menu_prj_menu), item);
413 g_signal_connect((gpointer) item, "activate", G_CALLBACK(on_delete_project), NULL);
414 menu_items.delete_project = item;
416 gtk_container_add(GTK_CONTAINER(menu_prj_menu), gtk_separator_menu_item_new());
418 image = gtk_image_new_from_stock(GTK_STOCK_ADD, GTK_ICON_SIZE_MENU);
419 gtk_widget_show(image);
420 item = gtk_image_menu_item_new_with_mnemonic(_("Add File"));
421 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item), image);
422 gtk_widget_show(item);
423 gtk_container_add(GTK_CONTAINER(menu_prj_menu), item);
424 g_signal_connect((gpointer) item, "activate", G_CALLBACK(on_add_file), NULL);
425 menu_items.add_file = item;
427 gtk_container_add(GTK_CONTAINER(menu_prj_menu), gtk_separator_menu_item_new());
429 image = gtk_image_new_from_stock(GTK_STOCK_PREFERENCES, GTK_ICON_SIZE_MENU);
430 gtk_widget_show(image);
431 item = gtk_image_menu_item_new_with_mnemonic(_("Preferences"));
432 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item), image);
433 gtk_widget_show(item);
434 gtk_container_add(GTK_CONTAINER(menu_prj_menu), item);
435 g_signal_connect((gpointer) item, "activate", G_CALLBACK(on_preferences), NULL);
436 menu_items.preferences = item;
438 gtk_container_add(GTK_CONTAINER(menu_prj_menu), gtk_separator_menu_item_new());
440 image = gtk_image_new_from_stock(GTK_STOCK_FIND, GTK_ICON_SIZE_MENU);
441 gtk_widget_show(image);
442 item = gtk_image_menu_item_new_with_mnemonic(_("Find in Project"));
443 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item), image);
444 gtk_widget_show(item);
445 gtk_container_add(GTK_CONTAINER(menu_prj_menu), item);
446 g_signal_connect((gpointer) item, "activate", G_CALLBACK(on_find_in_project), NULL);
447 menu_items.find_in_files = item;
449 gtk_widget_show_all(menu_prj);
451 plugin_fields->menu_item = menu_prj;
452 plugin_fields->flags = PLUGIN_IS_DOCUMENT_SENSITIVE;
455 void
456 tools_menu_uninit()
458 gtk_widget_destroy(plugin_fields->menu_item);