1 /*
2 * Copyright 2017 LarsGit223
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 */
18
19 /*
20 * This file contains all the code for the dialogs.
21 */
22 #ifdef HAVE_CONFIG_H
23 # include "config.h"
24 #endif
25
26 #include "wb_globals.h"
27 #include "dialogs.h"
28 #include "utils.h"
29
30 extern GeanyPlugin *geany_plugin;
31
32
33 /** Shows the dialog "Create new file".
34 *
35 * The dialog lets the user create a new file (filter *).
36 *
37 * @param path The current folder
38 * @return The filename
39 *
40 **/
dialogs_create_new_file(const gchar * path)41 gchar *dialogs_create_new_file(const gchar *path)
42 {
43 gchar *filename = NULL;
44 GtkWidget *dialog;
45
46 dialog = gtk_file_chooser_dialog_new(_("Create new file"),
47 GTK_WINDOW(wb_globals.geany_plugin->geany_data->main_widgets->window), GTK_FILE_CHOOSER_ACTION_SAVE,
48 _("_Cancel"), GTK_RESPONSE_CANCEL,
49 _("C_reate"), GTK_RESPONSE_ACCEPT, NULL);
50 gtk_file_chooser_set_do_overwrite_confirmation(GTK_FILE_CHOOSER(dialog), TRUE);
51
52 if (path != NULL)
53 {
54 gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog), path);
55 }
56
57 if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT)
58 {
59 filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
60 }
61
62 gtk_widget_destroy(dialog);
63
64 return filename;
65 }
66
67
68 /** Shows the dialog "Create new directory".
69 *
70 * The dialog lets the user create a new directory.
71 *
72 * @param path The current folder
73 * @return The filename
74 *
75 **/
dialogs_create_new_directory(const gchar * path)76 gchar *dialogs_create_new_directory(const gchar *path)
77 {
78 gchar *filename = NULL;
79 GtkWidget *dialog;
80
81 dialog = gtk_file_chooser_dialog_new(_("Create new directory"),
82 GTK_WINDOW(wb_globals.geany_plugin->geany_data->main_widgets->window), GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER,
83 _("_Cancel"), GTK_RESPONSE_CANCEL,
84 _("C_reate"), GTK_RESPONSE_ACCEPT, NULL);
85 gtk_file_chooser_set_do_overwrite_confirmation(GTK_FILE_CHOOSER(dialog), TRUE);
86
87 if (path != NULL)
88 {
89 gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog), path);
90 }
91
92 if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT)
93 {
94 filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
95 }
96
97 gtk_widget_destroy(dialog);
98
99 return filename;
100 }
101
102
103 /** Shows the dialog "Create new workbench".
104 *
105 * The dialog lets the user create a new workbench file (filter *.geanywb).
106 *
107 * @return The filename
108 *
109 **/
dialogs_create_new_workbench(void)110 gchar *dialogs_create_new_workbench(void)
111 {
112 gchar *filename = NULL;
113 GtkWidget *dialog;
114
115 dialog = gtk_file_chooser_dialog_new(_("Create new workbench"),
116 GTK_WINDOW(wb_globals.geany_plugin->geany_data->main_widgets->window), GTK_FILE_CHOOSER_ACTION_SAVE,
117 _("_Cancel"), GTK_RESPONSE_CANCEL,
118 _("C_reate"), GTK_RESPONSE_ACCEPT, NULL);
119 gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(dialog), "new.geanywb");
120 gtk_file_chooser_set_do_overwrite_confirmation(GTK_FILE_CHOOSER(dialog), TRUE);
121
122 if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT)
123 {
124 filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
125 }
126
127 gtk_widget_destroy(dialog);
128
129 return filename;
130 }
131
132
133 /** Shows the dialog "Open workbench".
134 *
135 * The dialog lets the user choose an existing workbench file (filter *.geanywb).
136 *
137 * @return The filename
138 *
139 **/
dialogs_open_workbench(void)140 gchar *dialogs_open_workbench(void)
141 {
142 gchar *filename = NULL;
143 GtkWidget *dialog;
144 GtkFileFilter *filter;
145
146 dialog = gtk_file_chooser_dialog_new(_("Open workbench"),
147 GTK_WINDOW(wb_globals.geany_plugin->geany_data->main_widgets->window), GTK_FILE_CHOOSER_ACTION_OPEN,
148 _("_Cancel"), GTK_RESPONSE_CANCEL,
149 _("_Open"), GTK_RESPONSE_ACCEPT, NULL);
150
151 filter = gtk_file_filter_new();
152 gtk_file_filter_set_name(filter, _("Workbench files (.geanywb)"));
153 gtk_file_filter_add_pattern(filter, "*.geanywb");
154 gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(dialog), filter);
155 filter = gtk_file_filter_new();
156 gtk_file_filter_set_name(filter, _("All Files"));
157 gtk_file_filter_add_pattern(filter, "*");
158 gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(dialog), filter);
159
160 if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT)
161 {
162 filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
163 }
164
165 gtk_widget_destroy(dialog);
166
167 return filename;
168 }
169
170
171 /** Shows the dialog "Add project".
172 *
173 * The dialog lets the user choose an existing project file
174 * (filter *.geany or *).
175 *
176 * @return The filename
177 *
178 **/
dialogs_add_project(void)179 gchar *dialogs_add_project(void)
180 {
181 gchar *filename = NULL;
182 GtkWidget *dialog;
183 GtkFileFilter *filter;
184
185 dialog = gtk_file_chooser_dialog_new(_("Add project"),
186 GTK_WINDOW(wb_globals.geany_plugin->geany_data->main_widgets->window), GTK_FILE_CHOOSER_ACTION_OPEN,
187 _("_Cancel"), GTK_RESPONSE_CANCEL,
188 _("_Add"), GTK_RESPONSE_ACCEPT, NULL);
189
190 filter = gtk_file_filter_new();
191 gtk_file_filter_set_name(filter, _("Project files (.geany)"));
192 gtk_file_filter_add_pattern(filter, "*.geany");
193 gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(dialog), filter);
194 filter = gtk_file_filter_new();
195 gtk_file_filter_set_name(filter, _("All Files"));
196 gtk_file_filter_add_pattern(filter, "*");
197 gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(dialog), filter);
198
199 if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT)
200 {
201 filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
202 }
203
204 gtk_widget_destroy(dialog);
205
206 return filename;
207 }
208
209
210 /** Shows the dialog "Add directory".
211 *
212 * The dialog lets the user choose an existing folder.
213 *
214 * @return The filename
215 *
216 **/
dialogs_add_directory(WB_PROJECT * project)217 gchar *dialogs_add_directory(WB_PROJECT *project)
218 {
219 gchar *filename = NULL;
220 GtkWidget *dialog;
221
222 dialog = gtk_file_chooser_dialog_new(_("Add directory"),
223 GTK_WINDOW(wb_globals.geany_plugin->geany_data->main_widgets->window), GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
224 _("_Cancel"), GTK_RESPONSE_CANCEL,
225 _("_Add"), GTK_RESPONSE_ACCEPT, NULL);
226 if (project != NULL)
227 {
228 const gchar *path;
229
230 /* Set the current folder to the location of the project file */
231 path = wb_project_get_filename(project);
232 if (path != NULL)
233 {
234 gchar *dirname = g_path_get_dirname(path);
235 gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog), dirname);
236 g_free(dirname);
237 }
238 }
239
240 if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT)
241 {
242 filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
243 }
244
245 gtk_widget_destroy(dialog);
246
247 return filename;
248 }
249
250
251 /* Split patterns in str into gchar** */
split_patterns(const gchar * str)252 static gchar **split_patterns(const gchar *str)
253 {
254 GString *tmp;
255 gchar **ret;
256 gchar *input;
257
258 input = g_strdup(str);
259
260 g_strstrip(input);
261 tmp = g_string_new(input);
262 g_free(input);
263 do {} while (utils_string_replace_all(tmp, " ", " "));
264 ret = g_strsplit(tmp->str, " ", -1);
265 g_string_free(tmp, TRUE);
266 return ret;
267 }
268
269 typedef struct S_DIALOG_DIR_SETTINGS_DATA
270 {
271 GtkWidget *dialog;
272 GtkWidget *w_label_file_patterns;
273 GtkWidget *w_file_patterns;
274 GtkWidget *w_label_ignored_dirs_patterns;
275 GtkWidget *w_ignored_dirs_patterns;
276 GtkWidget *w_label_ignored_file_patterns;
277 GtkWidget *w_ignored_file_patterns;
278 GtkWidget *w_scan_mode_wb;
279 GtkWidget *w_scan_mode_git;
280 }DIALOG_DIR_SETTINGS_DATA;
281
button_filter_workbench_toggled(GtkToggleButton * togglebutton,gpointer user_data)282 static void button_filter_workbench_toggled(GtkToggleButton *togglebutton,
283 gpointer user_data)
284 {
285 DIALOG_DIR_SETTINGS_DATA *data;
286
287 data = user_data;
288 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(data->w_scan_mode_wb)))
289 {
290 gtk_widget_set_sensitive (data->w_label_file_patterns, TRUE);
291 gtk_widget_set_sensitive (data->w_file_patterns, TRUE);
292 gtk_widget_set_sensitive (data->w_label_ignored_dirs_patterns, TRUE);
293 gtk_widget_set_sensitive (data->w_ignored_dirs_patterns, TRUE);
294 gtk_widget_set_sensitive (data->w_label_ignored_file_patterns, TRUE);
295 gtk_widget_set_sensitive (data->w_ignored_file_patterns, TRUE);
296 }
297 else
298 {
299 gtk_widget_set_sensitive (data->w_label_file_patterns, FALSE);
300 gtk_widget_set_sensitive (data->w_file_patterns, FALSE);
301 gtk_widget_set_sensitive (data->w_label_ignored_dirs_patterns, FALSE);
302 gtk_widget_set_sensitive (data->w_ignored_dirs_patterns, FALSE);
303 gtk_widget_set_sensitive (data->w_label_ignored_file_patterns, FALSE);
304 gtk_widget_set_sensitive (data->w_ignored_file_patterns, FALSE);
305 }
306 }
307
button_filter_git_toggled(GtkToggleButton * togglebutton,gpointer user_data)308 static void button_filter_git_toggled(GtkToggleButton *togglebutton,
309 gpointer user_data)
310 {
311 /* Nothing to do for now... */
312 }
313
314 /** Shows the directory settings dialog.
315 *
316 * The dialog lets the user edit the settings for file patterns, irnored file patterns and
317 * ignored directories patterns. On accept the result is directly stored in @a directory.
318 *
319 * @param project The project to which directory belongs to
320 * @param directory Location of WB_PROJECT_DIR to store the settings into
321 * @return TRUE if the settings have changed, FALSE otherwise
322 *
323 **/
dialogs_directory_settings(WB_PROJECT * project,WB_PROJECT_DIR * directory)324 gboolean dialogs_directory_settings(WB_PROJECT *project, WB_PROJECT_DIR *directory)
325 {
326 DIALOG_DIR_SETTINGS_DATA *data;
327 GtkWidget *label, *content_area;
328 GtkWidget *vbox, *hbox, *hbox1;
329 #if GTK_CHECK_VERSION(3, 4, 0)
330 GtkWidget *grid;
331 #else
332 GtkWidget *table;
333 #endif
334 GtkDialogFlags flags;
335 gchar *file_patterns_old, *ignored_file_patterns_old, *ignored_dirs_patterns_old;
336 WB_PROJECT_SCAN_MODE scan_mode_old, scan_mode;
337 gchar *abs_path;
338 gboolean changed;
339 guint row = 0;
340
341 data = g_new0(DIALOG_DIR_SETTINGS_DATA, 1);
342
343 /* Create the widgets */
344 flags = GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT;
345 data->dialog = gtk_dialog_new_with_buttons(_("Directory settings"),
346 GTK_WINDOW(wb_globals.geany_plugin->geany_data->main_widgets->window),
347 flags,
348 _("_Cancel"), GTK_RESPONSE_CANCEL,
349 _("_OK"), GTK_RESPONSE_ACCEPT,
350 NULL);
351 content_area = gtk_dialog_get_content_area(GTK_DIALOG (data->dialog));
352
353 vbox = gtk_vbox_new(FALSE, 0);
354
355 #if GTK_CHECK_VERSION(3, 4, 0)
356 grid = gtk_grid_new ();
357 gtk_grid_set_row_spacing (GTK_GRID(grid), 5);
358 gtk_grid_set_column_spacing (GTK_GRID(grid), 10);
359 #else
360 table = gtk_table_new(5, 2, FALSE);
361 gtk_table_set_row_spacings(GTK_TABLE(table), 5);
362 gtk_table_set_col_spacings(GTK_TABLE(table), 10);
363 #endif
364
365 data->w_scan_mode_wb = gtk_radio_button_new_with_label (NULL, _("filter files using the workbench plugin"));
366 g_signal_connect(data->w_scan_mode_wb, "toggled",
367 G_CALLBACK(button_filter_workbench_toggled), data);
368 gtk_box_pack_start(GTK_BOX(vbox), data->w_scan_mode_wb, FALSE, FALSE, 6);
369
370 data->w_label_file_patterns = gtk_label_new(_("File patterns:"));
371 #if GTK_CHECK_VERSION(3, 16, 0)
372 gtk_label_set_xalign (GTK_LABEL(data->w_label_file_patterns), 0);
373 gtk_label_set_yalign (GTK_LABEL(data->w_label_file_patterns), 0);
374 #else
375 gtk_misc_set_alignment(GTK_MISC(data->w_label_file_patterns), 0, 0);
376 #endif
377 data->w_file_patterns = gtk_entry_new();
378 #if GTK_CHECK_VERSION(3, 4, 0)
379 gtk_grid_attach (GTK_GRID(grid), data->w_label_file_patterns, 0, row, 1, 1);
380 gtk_grid_attach (GTK_GRID(grid), data->w_file_patterns, 1, row, 1, 1);
381 gtk_widget_set_valign (data->w_label_file_patterns, GTK_ALIGN_BASELINE);
382 gtk_widget_set_hexpand (data->w_label_file_patterns, FALSE);
383 gtk_widget_set_valign (data->w_file_patterns, GTK_ALIGN_BASELINE);
384 gtk_widget_set_hexpand (data->w_file_patterns, TRUE);
385 #else
386 ui_table_add_row(GTK_TABLE(table), row + 1, data->w_label_file_patterns, data->w_file_patterns, NULL);
387 #endif
388 row++;
389 ui_entry_add_clear_icon(GTK_ENTRY(data->w_file_patterns));
390 gtk_widget_set_tooltip_text(data->w_file_patterns,
391 _("Space separated list of patterns that are used to identify files "
392 "that shall be displayed in the directory tree."));
393 file_patterns_old = g_strjoinv(" ", wb_project_dir_get_file_patterns(directory));
394 gtk_entry_set_text(GTK_ENTRY(data->w_file_patterns), file_patterns_old);
395
396 data->w_label_ignored_file_patterns = gtk_label_new(_("Ignored file patterns:"));
397 #if GTK_CHECK_VERSION(3, 16, 0)
398 gtk_label_set_xalign (GTK_LABEL(data->w_label_ignored_file_patterns), 0);
399 gtk_label_set_yalign (GTK_LABEL(data->w_label_ignored_file_patterns), 0);
400 #else
401 gtk_misc_set_alignment(GTK_MISC(data->w_label_ignored_file_patterns), 0, 0);
402 #endif
403 data->w_ignored_file_patterns = gtk_entry_new();
404 ui_entry_add_clear_icon(GTK_ENTRY(data->w_ignored_file_patterns));
405 #if GTK_CHECK_VERSION(3, 4, 0)
406 gtk_grid_attach (GTK_GRID(grid), data->w_label_ignored_file_patterns, 0, row, 1, 1);
407 gtk_grid_attach (GTK_GRID(grid), data->w_ignored_file_patterns, 1, row, 1, 1);
408 gtk_widget_set_valign (data->w_label_ignored_file_patterns, GTK_ALIGN_BASELINE);
409 gtk_widget_set_hexpand (data->w_label_ignored_file_patterns, FALSE);
410 gtk_widget_set_valign (data->w_ignored_file_patterns, GTK_ALIGN_BASELINE);
411 gtk_widget_set_hexpand (data->w_ignored_file_patterns, TRUE);
412 #else
413 ui_table_add_row(GTK_TABLE(table), row + 1, data->w_label_ignored_file_patterns, data->w_ignored_file_patterns, NULL);
414 #endif
415 row++;
416 gtk_widget_set_tooltip_text(data->w_ignored_file_patterns,
417 _("Space separated list of patterns that are used to identify files "
418 "that shall not be displayed in the directory tree."));
419 ignored_file_patterns_old = g_strjoinv(" ", wb_project_dir_get_ignored_file_patterns(directory));
420 gtk_entry_set_text(GTK_ENTRY(data->w_ignored_file_patterns), ignored_file_patterns_old);
421
422 data->w_label_ignored_dirs_patterns = gtk_label_new(_("Ignored directory patterns:"));
423 #if GTK_CHECK_VERSION(3, 16, 0)
424 gtk_label_set_xalign (GTK_LABEL(data->w_label_ignored_dirs_patterns), 0);
425 gtk_label_set_yalign (GTK_LABEL(data->w_label_ignored_dirs_patterns), 0);
426 #else
427 gtk_misc_set_alignment(GTK_MISC(data->w_label_ignored_dirs_patterns), 0, 0);
428 #endif
429 data->w_ignored_dirs_patterns = gtk_entry_new();
430 ui_entry_add_clear_icon(GTK_ENTRY(data->w_ignored_dirs_patterns));
431 #if GTK_CHECK_VERSION(3, 4, 0)
432 gtk_grid_attach (GTK_GRID(grid), data->w_label_ignored_dirs_patterns, 0, row, 1, 1);
433 gtk_grid_attach (GTK_GRID(grid), data->w_ignored_dirs_patterns, 1, row, 1, 1);
434 gtk_widget_set_valign (data->w_label_ignored_dirs_patterns, GTK_ALIGN_BASELINE);
435 gtk_widget_set_hexpand (data->w_label_ignored_dirs_patterns, FALSE);
436 gtk_widget_set_valign (data->w_ignored_dirs_patterns, GTK_ALIGN_BASELINE);
437 gtk_widget_set_hexpand (data->w_ignored_dirs_patterns, TRUE);
438 #else
439 ui_table_add_row(GTK_TABLE(table), row + 1, data->w_label_ignored_dirs_patterns, data->w_ignored_dirs_patterns, NULL);
440 #endif
441 row++;
442 gtk_widget_set_tooltip_text(data->w_ignored_dirs_patterns,
443 _("Space separated list of patterns that are used to identify directories "
444 "that shall not be scanned for source files."));
445 ignored_dirs_patterns_old = g_strjoinv(" ", wb_project_dir_get_ignored_dirs_patterns(directory));
446 gtk_entry_set_text(GTK_ENTRY(data->w_ignored_dirs_patterns), ignored_dirs_patterns_old);
447
448 #if GTK_CHECK_VERSION(3, 12, 0)
449 gtk_widget_set_margin_start (grid, 32);
450 #endif
451 #if GTK_CHECK_VERSION(3, 4, 0)
452 gtk_box_pack_start(GTK_BOX(vbox), grid, FALSE, FALSE, 6);
453 #else
454 gtk_box_pack_start(GTK_BOX(vbox), table, FALSE, FALSE, 6);
455 #endif
456
457 data->w_scan_mode_git = gtk_radio_button_new_with_label (
458 gtk_radio_button_get_group(GTK_RADIO_BUTTON (data->w_scan_mode_wb)),
459 _("filter files using git (.gitignore)"));
460 g_signal_connect(data->w_scan_mode_git, "toggled",
461 G_CALLBACK(button_filter_git_toggled), data);
462 gtk_box_pack_start(GTK_BOX(vbox), data->w_scan_mode_git, FALSE, FALSE, 6);
463
464 hbox1 = gtk_hbox_new(FALSE, 0);
465 label = gtk_label_new(_("Note: the patterns above affect only the workbench directory and are not used in the Find in Files\n"
466 "dialog."));
467 gtk_box_pack_start(GTK_BOX(hbox1), label, FALSE, FALSE, 0);
468 gtk_box_pack_start(GTK_BOX(vbox), hbox1, FALSE, FALSE, 6);
469
470 hbox = gtk_hbox_new(FALSE, 0);
471 gtk_box_pack_start(GTK_BOX(hbox), vbox, TRUE, TRUE, 6);
472
473 /* Add the label, and show everything we’ve added */
474 gtk_container_add(GTK_CONTAINER (content_area), label);
475 gtk_container_add(GTK_CONTAINER (content_area), hbox);
476
477
478 scan_mode_old = wb_project_dir_get_scan_mode(directory);
479 abs_path = get_combined_path(wb_project_get_filename(project),
480 wb_project_dir_get_base_dir(directory));
481 if (!is_git_repository(abs_path))
482 {
483 /* Disable git filter option if the directory is not a git repository. */
484 gtk_widget_set_sensitive (data->w_scan_mode_git, FALSE);
485 }
486 else
487 {
488 /* Both options are possible, set the active option from
489 the current settings. */
490 if (scan_mode_old == WB_PROJECT_SCAN_MODE_WORKBENCH)
491 {
492 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(data->w_scan_mode_wb), TRUE);
493 }
494 else
495 {
496 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(data->w_scan_mode_git), TRUE);
497 }
498 }
499 g_free(abs_path);
500
501
502 gtk_widget_show_all(data->dialog);
503 gint result = gtk_dialog_run(GTK_DIALOG(data->dialog));
504 changed = FALSE;
505 if (result == GTK_RESPONSE_ACCEPT)
506 {
507 const gchar *str;
508 gchar **file_patterns, **ignored_dirs_patterns, **ignored_file_patterns;
509
510 scan_mode = WB_PROJECT_SCAN_MODE_WORKBENCH;
511 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(data->w_scan_mode_git)))
512 {
513 scan_mode = WB_PROJECT_SCAN_MODE_GIT;
514 }
515 if (scan_mode_old != scan_mode)
516 {
517 changed = TRUE;
518 }
519
520 str = gtk_entry_get_text(GTK_ENTRY(data->w_file_patterns));
521 if (g_strcmp0(str, file_patterns_old) != 0)
522 {
523 changed = TRUE;
524 }
525 file_patterns = split_patterns(str);
526
527 str = gtk_entry_get_text(GTK_ENTRY(data->w_ignored_dirs_patterns));
528 if (g_strcmp0(str, ignored_dirs_patterns_old) != 0)
529 {
530 changed = TRUE;
531 }
532 ignored_dirs_patterns = split_patterns(str);
533
534 str = gtk_entry_get_text(GTK_ENTRY(data->w_ignored_file_patterns));
535 if (g_strcmp0(str, ignored_file_patterns_old) != 0)
536 {
537 changed = TRUE;
538 }
539 ignored_file_patterns = split_patterns(str);
540
541 wb_project_dir_set_scan_mode(project, directory, scan_mode);
542 wb_project_dir_set_file_patterns(directory, file_patterns);
543 wb_project_dir_set_ignored_dirs_patterns(directory, ignored_dirs_patterns);
544 wb_project_dir_set_ignored_file_patterns(directory, ignored_file_patterns);
545
546 g_strfreev(file_patterns);
547 g_strfreev(ignored_dirs_patterns);
548 g_strfreev(ignored_file_patterns);
549 }
550
551 g_free(file_patterns_old);
552 g_free(ignored_file_patterns_old);
553 g_free(ignored_dirs_patterns_old);
554 gtk_widget_destroy(data->dialog);
555
556 return changed;
557 }
558
559
560 /** Shows the workbench settings dialog.
561 *
562 * The dialog lets the user edit the settings for option "Rescan all projects on open".
563 * On accept the result is directly stored in @a workbench.
564 *
565 * @param workbench Location of WORKBENCH to store the settings into
566 * @return TRUE if the settings have changed, FALSE otherwise
567 *
568 **/
dialogs_workbench_settings(WORKBENCH * workbench)569 gboolean dialogs_workbench_settings(WORKBENCH *workbench)
570 {
571 gint result;
572 GtkWidget *w_rescan_projects_on_open, *w_enable_live_update, *w_expand_on_hover;
573 GtkWidget *dialog, *content_area, *w_enable_tree_lines;
574 GtkWidget *vbox, *hbox;
575 #if GTK_CHECK_VERSION(3, 4, 0)
576 GtkWidget *grid;
577 #else
578 GtkWidget *table;
579 #endif
580 GtkDialogFlags flags;
581 gboolean changed, rescan_projects_on_open, rescan_projects_on_open_old;
582 gboolean enable_live_update, enable_live_update_old;
583 gboolean expand_on_hover, expand_on_hover_old;
584 gboolean enable_tree_lines, enable_tree_lines_old;
585
586 /* Create the widgets */
587 flags = GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT;
588 dialog = gtk_dialog_new_with_buttons(_("Workbench settings"),
589 GTK_WINDOW(wb_globals.geany_plugin->geany_data->main_widgets->window),
590 flags,
591 _("_Cancel"), GTK_RESPONSE_CANCEL,
592 _("_OK"), GTK_RESPONSE_ACCEPT,
593 NULL);
594 content_area = gtk_dialog_get_content_area(GTK_DIALOG (dialog));
595
596 vbox = gtk_vbox_new(FALSE, 0);
597
598 #if GTK_CHECK_VERSION(3, 4, 0)
599 grid = gtk_grid_new ();
600 gtk_grid_set_row_spacing (GTK_GRID(grid), 5);
601 gtk_grid_set_column_spacing (GTK_GRID(grid), 10);
602 #else
603 table = gtk_table_new(5, 2, FALSE);
604 gtk_table_set_row_spacings(GTK_TABLE(table), 5);
605 gtk_table_set_col_spacings(GTK_TABLE(table), 10);
606 #endif
607
608 w_rescan_projects_on_open = gtk_check_button_new_with_mnemonic(_("_Rescan all projects on open"));
609 #if GTK_CHECK_VERSION(3, 4, 0)
610 gtk_grid_attach (GTK_GRID(grid), w_rescan_projects_on_open, 0, 0, 1, 1);
611 gtk_widget_set_halign (w_rescan_projects_on_open, GTK_ALIGN_CENTER);
612 gtk_widget_set_hexpand (w_rescan_projects_on_open, TRUE);
613 gtk_widget_set_valign (w_rescan_projects_on_open, GTK_ALIGN_CENTER);
614 gtk_widget_set_vexpand (w_rescan_projects_on_open, TRUE);
615 #else
616 ui_table_add_row(GTK_TABLE(table), 0, w_rescan_projects_on_open, NULL);
617 #endif
618 gtk_widget_set_tooltip_text(w_rescan_projects_on_open,
619 _("If the option is activated (default), then all projects will be re-scanned "
620 "on opening of the workbench."));
621 rescan_projects_on_open_old = workbench_get_rescan_projects_on_open(workbench);
622 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w_rescan_projects_on_open), rescan_projects_on_open_old);
623
624 w_enable_live_update = gtk_check_button_new_with_mnemonic(_("_Enable live update"));
625 #if GTK_CHECK_VERSION(3, 4, 0)
626 gtk_grid_attach (GTK_GRID(grid), w_enable_live_update, 0, 1, 1, 1);
627 gtk_widget_set_halign (w_enable_live_update, GTK_ALIGN_CENTER);
628 gtk_widget_set_hexpand (w_enable_live_update, TRUE);
629 gtk_widget_set_valign (w_enable_live_update, GTK_ALIGN_CENTER);
630 gtk_widget_set_vexpand (w_enable_live_update, TRUE);
631 #else
632 ui_table_add_row(GTK_TABLE(table), 1, w_enable_live_update, NULL);
633 #endif
634 gtk_widget_set_tooltip_text(w_enable_live_update,
635 _("If the option is activated (default), then the list of files and the sidebar "
636 "will be updated automatically if a file or directory is created, removed or renamed. "
637 "A manual re-scan is not required if the option is enabled."));
638 enable_live_update_old = workbench_get_enable_live_update(workbench);
639 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w_enable_live_update), enable_live_update_old);
640
641 w_expand_on_hover = gtk_check_button_new_with_mnemonic(_("_Expand on hover"));
642 #if GTK_CHECK_VERSION(3, 4, 0)
643 gtk_grid_attach (GTK_GRID(grid), w_expand_on_hover, 0, 2, 1, 1);
644 gtk_widget_set_halign (w_expand_on_hover, GTK_ALIGN_CENTER);
645 gtk_widget_set_hexpand (w_expand_on_hover, TRUE);
646 gtk_widget_set_valign (w_expand_on_hover, GTK_ALIGN_CENTER);
647 gtk_widget_set_vexpand (w_expand_on_hover, TRUE);
648 #else
649 ui_table_add_row(GTK_TABLE(table), 2, w_expand_on_hover, NULL);
650 #endif
651 gtk_widget_set_tooltip_text(w_expand_on_hover,
652 _("If the option is activated, then a tree node in the sidebar "
653 "will be expanded or collapsed by hovering over it with the mouse cursor."));
654 expand_on_hover_old = workbench_get_expand_on_hover(workbench);
655 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w_expand_on_hover), expand_on_hover_old);
656
657 w_enable_tree_lines = gtk_check_button_new_with_mnemonic(_("_Enable tree lines"));
658 #if GTK_CHECK_VERSION(3, 4, 0)
659 gtk_grid_attach (GTK_GRID(grid), w_enable_tree_lines, 0, 3, 1, 1);
660 gtk_widget_set_halign (w_enable_tree_lines, GTK_ALIGN_CENTER);
661 gtk_widget_set_hexpand (w_enable_tree_lines, TRUE);
662 gtk_widget_set_valign (w_enable_tree_lines, GTK_ALIGN_CENTER);
663 gtk_widget_set_vexpand (w_enable_tree_lines, TRUE);
664 #else
665 ui_table_add_row(GTK_TABLE(table), 3, w_enable_tree_lines, NULL);
666 #endif
667 gtk_widget_set_tooltip_text(w_enable_tree_lines,
668 _("If the option is activated, lines will be drawn between "
669 "the nodes in the sidebar tree."));
670 enable_tree_lines_old = workbench_get_enable_tree_lines(workbench);
671 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w_enable_tree_lines), enable_tree_lines_old);
672
673 #if GTK_CHECK_VERSION(3, 4, 0)
674 gtk_box_pack_start(GTK_BOX(vbox), grid, FALSE, FALSE, 6);
675 #else
676 gtk_box_pack_start(GTK_BOX(vbox), table, FALSE, FALSE, 6);
677 #endif
678
679 hbox = gtk_hbox_new(FALSE, 0);
680 gtk_box_pack_start(GTK_BOX(hbox), vbox, TRUE, TRUE, 6);
681
682 /* Show everything we’ve added, run dialog */
683 gtk_container_add(GTK_CONTAINER (content_area), hbox);
684 gtk_widget_show_all(dialog);
685 result = gtk_dialog_run(GTK_DIALOG(dialog));
686
687 changed = FALSE;
688 if (result == GTK_RESPONSE_ACCEPT)
689 {
690 rescan_projects_on_open = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w_rescan_projects_on_open));
691 if (rescan_projects_on_open != rescan_projects_on_open_old)
692 {
693 changed = TRUE;
694 workbench_set_rescan_projects_on_open(workbench, rescan_projects_on_open);
695 }
696 enable_live_update = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w_enable_live_update));
697 if (enable_live_update != enable_live_update_old)
698 {
699 changed = TRUE;
700 workbench_set_enable_live_update(workbench, enable_live_update);
701 }
702 expand_on_hover = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w_expand_on_hover));
703 if (expand_on_hover != expand_on_hover_old)
704 {
705 changed = TRUE;
706 workbench_set_expand_on_hover(workbench, expand_on_hover);
707 }
708 enable_tree_lines = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w_enable_tree_lines));
709 if (enable_tree_lines != enable_tree_lines_old)
710 {
711 changed = TRUE;
712 workbench_set_enable_tree_lines(workbench, enable_tree_lines);
713 }
714 }
715
716 gtk_widget_destroy(dialog);
717
718 return changed;
719 }
720