geany  1.38
About: Geany is a text editor (using GTK2) with basic features of an integrated development environment (syntax highlighting, code folding, symbol name auto-completion, ...). F: office T: editor programming GTK+ IDE
  Fossies Dox: geany-1.38.tar.bz2  ("unofficial" and yet experimental doxygen-generated source code documentation)  

sidebar.c
Go to the documentation of this file.
1/*
2 * sidebar.c - this file is part of Geany, a fast and lightweight IDE
3 *
4 * Copyright 2005 The Geany contributors
5 *
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.
10 *
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.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 */
20
21/*
22 * Sidebar related code for the Symbol list and Open files GtkTreeViews.
23 */
24
25#ifdef HAVE_CONFIG_H
26# include "config.h"
27#endif
28
29#include "sidebar.h"
30
31#include "app.h"
32#include "callbacks.h" /* FIXME: for ignore_callback */
33#include "documentprivate.h"
34#include "filetypesprivate.h"
35#include "geanyobject.h"
36#include "keyfile.h"
37#include "navqueue.h"
38#include "stash.h"
39#include "support.h"
40#include "symbols.h"
41#include "ui_utils.h"
42#include "utils.h"
43#include "keybindings.h"
44
45#include <string.h>
46
47#include <gdk/gdkkeysyms.h>
48
49
51/* while typeahead searching, editor should not get focus */
52static gboolean may_steal_focus = FALSE;
53
54static struct
55{
56 GtkWidget *close;
57 GtkWidget *save;
58 GtkWidget *reload;
59 GtkWidget *show_paths;
60 GtkWidget *find_in_files;
61 GtkWidget *expand_all;
62 GtkWidget *collapse_all;
63}
65
66enum
67{
70};
71
72enum
73{
77};
78
79/* documents tree model columns */
80enum
81{
83 DOCUMENTS_SHORTNAME, /* dirname for parents, basename for children */
86 DOCUMENTS_FILENAME /* full filename */
87};
88
89static GtkTreeStore *store_openfiles;
90static GtkWidget *openfiles_popup_menu;
91static gboolean documents_show_paths;
92static GtkWidget *tag_window; /* scrolled window that holds the symbol list GtkTreeView */
93
94/* callback prototypes */
95static void on_openfiles_document_action(GtkMenuItem *menuitem, gpointer user_data);
96static gboolean sidebar_button_press_cb(GtkWidget *widget, GdkEventButton *event,
97 gpointer user_data);
98static gboolean sidebar_key_press_cb(GtkWidget *widget, GdkEventKey *event,
99 gpointer user_data);
100static void on_list_document_activate(GtkCheckMenuItem *item, gpointer user_data);
101static void on_list_symbol_activate(GtkCheckMenuItem *item, gpointer user_data);
102static void documents_menu_update(GtkTreeSelection *selection);
103static void sidebar_tabs_show_hide(GtkNotebook *notebook, GtkWidget *child,
104 guint page_num, gpointer data);
105
106
107/* the prepare_* functions are document-related, but I think they fit better here than in document.c */
108static void prepare_taglist(GtkWidget *tree, GtkTreeStore *store)
109{
110 GtkCellRenderer *text_renderer, *icon_renderer;
111 GtkTreeViewColumn *column;
112 GtkTreeSelection *selection;
113
114 text_renderer = gtk_cell_renderer_text_new();
115 icon_renderer = gtk_cell_renderer_pixbuf_new();
116 column = gtk_tree_view_column_new();
117
118 gtk_tree_view_column_pack_start(column, icon_renderer, FALSE);
119 gtk_tree_view_column_set_attributes(column, icon_renderer, "pixbuf", SYMBOLS_COLUMN_ICON, NULL);
120 g_object_set(icon_renderer, "xalign", 0.0, NULL);
121
122 gtk_tree_view_column_pack_start(column, text_renderer, TRUE);
123 gtk_tree_view_column_set_attributes(column, text_renderer, "text", SYMBOLS_COLUMN_NAME, NULL);
124 g_object_set(text_renderer, "yalign", 0.5, NULL);
125 gtk_tree_view_column_set_title(column, _("Symbols"));
126
127 gtk_tree_view_append_column(GTK_TREE_VIEW(tree), column);
128 gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(tree), FALSE);
129
131
132 gtk_tree_view_set_model(GTK_TREE_VIEW(tree), GTK_TREE_MODEL(store));
133 g_object_unref(store);
134
135 g_signal_connect(tree, "button-press-event",
136 G_CALLBACK(sidebar_button_press_cb), NULL);
137 g_signal_connect(tree, "key-press-event",
138 G_CALLBACK(sidebar_key_press_cb), NULL);
139
140 gtk_tree_view_set_show_expanders(GTK_TREE_VIEW(tree), interface_prefs.show_symbol_list_expanders);
142 gtk_tree_view_set_level_indentation(GTK_TREE_VIEW(tree), 10);
143 /* Tooltips */
145
146 /* selection handling */
147 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(tree));
148 gtk_tree_selection_set_mode(selection, GTK_SELECTION_SINGLE);
149 /* callback for changed selection not necessary, will be handled by button-press-event */
150}
151
152
153static gboolean
154on_default_tag_tree_button_press_event(GtkWidget *widget, GdkEventButton *event,
155 gpointer user_data)
156{
157 if (event->button == 3)
158 {
159 gtk_menu_popup(GTK_MENU(tv.popup_taglist), NULL, NULL, NULL, NULL,
160 event->button, event->time);
161 return TRUE;
162 }
163 return FALSE;
164}
165
166
167static void create_default_tag_tree(void)
168{
169 GtkScrolledWindow *scrolled_window = GTK_SCROLLED_WINDOW(tag_window);
170 GtkWidget *label;
171
172 /* default_tag_tree is a GtkViewPort with a GtkLabel inside it */
173 tv.default_tag_tree = gtk_viewport_new(
174 gtk_scrolled_window_get_hadjustment(scrolled_window),
175 gtk_scrolled_window_get_vadjustment(scrolled_window));
176 gtk_viewport_set_shadow_type(GTK_VIEWPORT(tv.default_tag_tree), GTK_SHADOW_NONE);
177 label = gtk_label_new(_("No symbols found"));
178 gtk_misc_set_alignment(GTK_MISC(label), 0.1f, 0.01f);
181 g_signal_connect(tv.default_tag_tree, "button-press-event",
183 g_object_ref((gpointer)tv.default_tag_tree); /* to hold it after removing */
184}
185
186
187/* update = rescan the tags for doc->filename */
188void sidebar_update_tag_list(GeanyDocument *doc, gboolean update)
189{
190 GtkWidget *child = gtk_bin_get_child(GTK_BIN(tag_window));
191
192 g_return_if_fail(doc == NULL || doc->is_valid);
193
194 if (update)
195 doc->priv->tag_tree_dirty = TRUE;
196
197 if (gtk_notebook_get_current_page(GTK_NOTEBOOK(main_widgets.sidebar_notebook)) != TREEVIEW_SYMBOL)
198 return; /* don't bother updating symbol tree if we don't see it */
199
200 /* changes the tree view to the given one, trying not to do useless changes */
201 #define CHANGE_TREE(new_child) \
202 G_STMT_START { \
203 /* only change the tag tree if it's actually not the same (to avoid flickering) and if
204 * it's the one of the current document (to avoid problems when e.g. reloading
205 * configuration files */ \
206 if (child != new_child && doc == document_get_current()) \
207 { \
208 if (child) \
209 gtk_container_remove(GTK_CONTAINER(tag_window), child); \
210 gtk_container_add(GTK_CONTAINER(tag_window), new_child); \
211 } \
212 } G_STMT_END
213
214 if (tv.default_tag_tree == NULL)
216
217 /* show default empty tag tree if there are no tags */
218 if (doc == NULL || doc->file_type == NULL || ! filetype_has_tags(doc->file_type))
219 {
221 return;
222 }
223
224 if (doc->priv->tag_tree_dirty)
225 { /* updating the tag list in the left tag window */
226 if (doc->priv->tag_tree == NULL)
227 {
228 doc->priv->tag_store = gtk_tree_store_new(
229 SYMBOLS_N_COLUMNS, GDK_TYPE_PIXBUF, G_TYPE_STRING, TM_TYPE_TAG, G_TYPE_STRING);
230 doc->priv->tag_tree = gtk_tree_view_new();
232 gtk_widget_show(doc->priv->tag_tree);
233 g_object_ref((gpointer)doc->priv->tag_tree); /* to hold it after removing */
234 }
235
236 doc->has_tags = symbols_recreate_tag_list(doc, SYMBOLS_SORT_USE_PREVIOUS);
237 doc->priv->tag_tree_dirty = FALSE;
238 }
239
240 if (doc->has_tags)
241 {
243 }
244 else
245 {
247 }
248
249 #undef CHANGE_TREE
250}
251
253/* cleverly sorts documents by their short name */
254static gint documents_sort_func(GtkTreeModel *model, GtkTreeIter *iter_a,
255 GtkTreeIter *iter_b, gpointer data)
256{
257 gchar *key_a, *key_b;
258 gchar *name_a, *name_b;
259 gint cmp;
260
261 gtk_tree_model_get(model, iter_a, DOCUMENTS_SHORTNAME, &name_a, -1);
262 key_a = g_utf8_collate_key_for_filename(name_a, -1);
263 g_free(name_a);
264 gtk_tree_model_get(model, iter_b, DOCUMENTS_SHORTNAME, &name_b, -1);
265 key_b = g_utf8_collate_key_for_filename(name_b, -1);
266 g_free(name_b);
267 cmp = strcmp(key_a, key_b);
268 g_free(key_b);
269 g_free(key_a);
270
271 return cmp;
272}
273
275/* does some preparing things to the open files list widget */
276static void prepare_openfiles(void)
277{
278 GtkCellRenderer *icon_renderer;
279 GtkCellRenderer *text_renderer;
280 GtkTreeViewColumn *column;
281 GtkTreeSelection *selection;
282 GtkTreeSortable *sortable;
283
285
286 /* store the icon and the short filename to show, and the index as reference,
287 * the colour (black/red/green) and the full name for the tooltip */
288 store_openfiles = gtk_tree_store_new(5, G_TYPE_ICON, G_TYPE_STRING,
289 G_TYPE_POINTER, GDK_TYPE_COLOR, G_TYPE_STRING);
290 gtk_tree_view_set_model(GTK_TREE_VIEW(tv.tree_openfiles), GTK_TREE_MODEL(store_openfiles));
291
292 /* set policy settings for the scolledwindow around the treeview again, because glade
293 * doesn't keep the settings */
294 gtk_scrolled_window_set_policy(
295 GTK_SCROLLED_WINDOW(ui_lookup_widget(main_widgets.window, "scrolledwindow7")),
296 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
297
298 icon_renderer = gtk_cell_renderer_pixbuf_new();
299 g_object_set(icon_renderer, "stock-size", GTK_ICON_SIZE_MENU, NULL);
300 text_renderer = gtk_cell_renderer_text_new();
301 g_object_set(text_renderer, "ellipsize", PANGO_ELLIPSIZE_MIDDLE, NULL);
302 column = gtk_tree_view_column_new();
303 gtk_tree_view_column_pack_start(column, icon_renderer, FALSE);
304 gtk_tree_view_column_set_attributes(column, icon_renderer, "gicon", DOCUMENTS_ICON, NULL);
305 gtk_tree_view_column_pack_start(column, text_renderer, TRUE);
306 gtk_tree_view_column_set_attributes(column, text_renderer, "text", DOCUMENTS_SHORTNAME,
307 "foreground-gdk", DOCUMENTS_COLOR, NULL);
308 gtk_tree_view_append_column(GTK_TREE_VIEW(tv.tree_openfiles), column);
309 gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(tv.tree_openfiles), FALSE);
310
311 gtk_tree_view_set_search_column(GTK_TREE_VIEW(tv.tree_openfiles),
313
314 /* sort opened filenames in the store_openfiles treeview */
315 sortable = GTK_TREE_SORTABLE(GTK_TREE_MODEL(store_openfiles));
316 gtk_tree_sortable_set_sort_func(sortable, DOCUMENTS_SHORTNAME, documents_sort_func, NULL, NULL);
317 gtk_tree_sortable_set_sort_column_id(sortable, DOCUMENTS_SHORTNAME, GTK_SORT_ASCENDING);
318
320
321 /* tooltips */
323
324 /* selection handling */
325 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(tv.tree_openfiles));
326 gtk_tree_selection_set_mode(selection, GTK_SELECTION_SINGLE);
327 g_object_unref(store_openfiles);
328
329 g_signal_connect(GTK_TREE_VIEW(tv.tree_openfiles), "button-press-event",
330 G_CALLBACK(sidebar_button_press_cb), NULL);
331 g_signal_connect(GTK_TREE_VIEW(tv.tree_openfiles), "key-press-event",
332 G_CALLBACK(sidebar_key_press_cb), NULL);
333}
334
336/* iter should be toplevel */
337static gboolean find_tree_iter_dir(GtkTreeIter *iter, const gchar *dir)
338{
339 GeanyDocument *doc;
340 gchar *name;
341 gboolean result;
342
343 if (utils_str_equal(dir, "."))
345
346 gtk_tree_model_get(GTK_TREE_MODEL(store_openfiles), iter, DOCUMENTS_DOCUMENT, &doc, -1);
347 g_return_val_if_fail(!doc, FALSE);
348
349 gtk_tree_model_get(GTK_TREE_MODEL(store_openfiles), iter, DOCUMENTS_SHORTNAME, &name, -1);
350
351 result = utils_filenamecmp(name, dir) == 0;
352 g_free(name);
353
354 return result;
355}
357
358static gboolean utils_filename_has_prefix(const gchar *str, const gchar *prefix)
359{
360 gchar *head = g_strndup(str, strlen(prefix));
361 gboolean ret = utils_filenamecmp(head, prefix) == 0;
362
363 g_free(head);
364 return ret;
365}
367
368static gchar *get_doc_folder(const gchar *path)
369{
370 gchar *tmp_dirname = g_strdup(path);
371 gchar *project_base_path;
372 gchar *dirname = NULL;
373 const gchar *home_dir = g_get_home_dir();
374 const gchar *rest;
375
376 /* replace the project base path with the project name */
377 project_base_path = project_get_base_path();
378
379 if (project_base_path != NULL)
380 {
381 gsize len = strlen(project_base_path);
382
383 /* remove trailing separator so we can match base path exactly */
384 if (project_base_path[len-1] == G_DIR_SEPARATOR)
385 project_base_path[--len] = '\0';
386
387 /* check whether the dir name matches or uses the project base path */
388 if (utils_filename_has_prefix(tmp_dirname, project_base_path))
389 {
390 rest = tmp_dirname + len;
391 if (*rest == G_DIR_SEPARATOR || *rest == '\0')
392 {
393 dirname = g_strdup_printf("%s%s", app->project->name, rest);
394 }
395 }
396 g_free(project_base_path);
397 }
398 if (dirname == NULL)
399 {
400 dirname = tmp_dirname;
401
402 /* If matches home dir, replace with tilde */
403 if (!EMPTY(home_dir) && utils_filename_has_prefix(dirname, home_dir))
404 {
405 rest = dirname + strlen(home_dir);
406 if (*rest == G_DIR_SEPARATOR || *rest == '\0')
407 {
408 dirname = g_strdup_printf("~%s", rest);
409 g_free(tmp_dirname);
410 }
411 }
412 }
413 else
414 g_free(tmp_dirname);
415
416 return dirname;
417}
419
420static GtkTreeIter *get_doc_parent(GeanyDocument *doc)
421{
422 gchar *path;
423 gchar *dirname = NULL;
424 static GtkTreeIter parent;
425 GtkTreeModel *model = GTK_TREE_MODEL(store_openfiles);
426 static GIcon *dir_icon = NULL;
427
429 return NULL;
430
431 path = g_path_get_dirname(DOC_FILENAME(doc));
432 dirname = get_doc_folder(path);
433
434 if (gtk_tree_model_get_iter_first(model, &parent))
435 {
436 do
437 {
438 if (find_tree_iter_dir(&parent, dirname))
439 {
440 g_free(dirname);
441 g_free(path);
442 return &parent;
443 }
444 }
445 while (gtk_tree_model_iter_next(model, &parent));
446 }
447 /* no match, add dir parent */
448 if (!dir_icon)
449 dir_icon = ui_get_mime_icon("inode/directory");
450
451 gtk_tree_store_append(store_openfiles, &parent, NULL);
452 gtk_tree_store_set(store_openfiles, &parent, DOCUMENTS_ICON, dir_icon,
453 DOCUMENTS_FILENAME, path,
455
456 g_free(dirname);
457 g_free(path);
458 return &parent;
459}
460
461
462/* Also sets doc->priv->iter.
463 * This is called recursively in sidebar_openfiles_update_all(). */
465{
466 GtkTreeIter *iter = &doc->priv->iter;
467 GtkTreeIter *parent = get_doc_parent(doc);
468 gchar *basename;
469 const GdkColor *color = document_get_status_color(doc);
470 static GIcon *file_icon = NULL;
471
472 gtk_tree_store_append(store_openfiles, iter, parent);
473
474 /* check if new parent */
475 if (parent && gtk_tree_model_iter_n_children(GTK_TREE_MODEL(store_openfiles), parent) == 1)
476 {
477 GtkTreePath *path;
478
479 /* expand parent */
480 path = gtk_tree_model_get_path(GTK_TREE_MODEL(store_openfiles), parent);
481 gtk_tree_view_expand_row(GTK_TREE_VIEW(tv.tree_openfiles), path, TRUE);
482 gtk_tree_path_free(path);
483 }
484 if (!file_icon)
485 file_icon = ui_get_mime_icon("text/plain");
486
487 basename = g_path_get_basename(DOC_FILENAME(doc));
488 gtk_tree_store_set(store_openfiles, iter,
489 DOCUMENTS_ICON, (doc->file_type && doc->file_type->icon) ? doc->file_type->icon : file_icon,
492 g_free(basename);
493}
495
496static void openfiles_remove(GeanyDocument *doc)
497{
498 GtkTreeIter *iter = &doc->priv->iter;
499 GtkTreeIter parent;
500
501 if (gtk_tree_model_iter_parent(GTK_TREE_MODEL(store_openfiles), &parent, iter) &&
502 gtk_tree_model_iter_n_children(GTK_TREE_MODEL(store_openfiles), &parent) == 1)
503 gtk_tree_store_remove(store_openfiles, &parent);
504 else
505 gtk_tree_store_remove(store_openfiles, iter);
506}
508
510{
511 GtkTreeIter *iter = &doc->priv->iter;
512 gchar *fname;
513
514 gtk_tree_model_get(GTK_TREE_MODEL(store_openfiles), iter, DOCUMENTS_FILENAME, &fname, -1);
515
516 if (utils_str_equal(fname, DOC_FILENAME(doc)))
517 {
518 /* just update color and the icon */
519 const GdkColor *color = document_get_status_color(doc);
520 GIcon *icon = doc->file_type->icon;
521
522 gtk_tree_store_set(store_openfiles, iter, DOCUMENTS_COLOR, color, -1);
523 if (icon)
524 gtk_tree_store_set(store_openfiles, iter, DOCUMENTS_ICON, icon, -1);
525 }
526 else
527 {
528 /* path has changed, so remove and re-add */
529 GtkTreeSelection *treesel;
530 gboolean sel;
531
532 treesel = gtk_tree_view_get_selection(GTK_TREE_VIEW(tv.tree_openfiles));
533 sel = gtk_tree_selection_iter_is_selected(treesel, &doc->priv->iter);
534 openfiles_remove(doc);
535
537 if (sel)
538 gtk_tree_selection_select_iter(treesel, &doc->priv->iter);
539 }
540 g_free(fname);
541}
543
545{
546 guint i;
547
548 gtk_tree_store_clear(store_openfiles);
550 {
552 }
553}
555
557{
558 openfiles_remove(doc);
559
560 if (GTK_IS_WIDGET(doc->priv->tag_tree))
561 {
562 gtk_widget_destroy(doc->priv->tag_tree); /* make GTK release its references, if any */
563 /* Because it was ref'd in sidebar_update_tag_list, it needs unref'ing */
564 g_object_unref(doc->priv->tag_tree);
565 doc->priv->tag_tree = NULL;
566 }
567}
569
570static void on_hide_sidebar(void)
571{
572 ui_prefs.sidebar_visible = FALSE;
574}
576
577static gboolean on_sidebar_display_symbol_list_show(GtkWidget *item)
578{
579 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item),
581 return FALSE;
582}
584
585static gboolean on_sidebar_display_open_files_show(GtkWidget *item)
586{
587 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item),
589 return FALSE;
590}
592
593void sidebar_add_common_menu_items(GtkMenu *menu)
594{
595 GtkWidget *item;
596
597 item = gtk_separator_menu_item_new();
598 gtk_widget_show(item);
599 gtk_container_add(GTK_CONTAINER(menu), item);
600
601 item = gtk_check_menu_item_new_with_mnemonic(_("Show S_ymbol List"));
602 gtk_container_add(GTK_CONTAINER(menu), item);
603 g_signal_connect(item, "draw", G_CALLBACK(on_sidebar_display_symbol_list_show), NULL);
604 gtk_widget_show(item);
605 g_signal_connect(item, "activate",
606 G_CALLBACK(on_list_symbol_activate), NULL);
607
608 item = gtk_check_menu_item_new_with_mnemonic(_("Show _Document List"));
609 gtk_container_add(GTK_CONTAINER(menu), item);
610 g_signal_connect(item, "draw", G_CALLBACK(on_sidebar_display_open_files_show), NULL);
611 gtk_widget_show(item);
612 g_signal_connect(item, "activate",
613 G_CALLBACK(on_list_document_activate), NULL);
614
615 item = gtk_image_menu_item_new_with_mnemonic(_("H_ide Sidebar"));
616 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item),
617 gtk_image_new_from_stock(GTK_STOCK_CLOSE, GTK_ICON_SIZE_MENU));
618 gtk_widget_show(item);
619 gtk_container_add(GTK_CONTAINER(menu), item);
620 g_signal_connect(item, "activate", G_CALLBACK(on_hide_sidebar), NULL);
621}
623
624static void on_openfiles_show_paths_activate(GtkCheckMenuItem *item, gpointer user_data)
625{
626 documents_show_paths = gtk_check_menu_item_get_active(item);
628}
630
631static void on_list_document_activate(GtkCheckMenuItem *item, gpointer user_data)
632{
633 interface_prefs.sidebar_openfiles_visible = gtk_check_menu_item_get_active(item);
636}
638
639static void on_list_symbol_activate(GtkCheckMenuItem *item, gpointer user_data)
640{
641 interface_prefs.sidebar_symbol_visible = gtk_check_menu_item_get_active(item);
644}
646
647static void on_find_in_files(GtkMenuItem *menuitem, gpointer user_data)
648{
649 GtkTreeSelection *treesel;
650 GtkTreeIter iter;
651 GtkTreeModel *model;
652 GeanyDocument *doc;
653 gchar *dir;
654
655 treesel = gtk_tree_view_get_selection(GTK_TREE_VIEW(tv.tree_openfiles));
656 if (!gtk_tree_selection_get_selected(treesel, &model, &iter))
657 return;
658 gtk_tree_model_get(model, &iter, DOCUMENTS_DOCUMENT, &doc, -1);
659
660 if (!doc)
661 {
662 gtk_tree_model_get(model, &iter, DOCUMENTS_FILENAME, &dir, -1);
663 }
664 else
665 dir = g_path_get_dirname(DOC_FILENAME(doc));
666
668 g_free(dir);
669}
671
672static void on_openfiles_expand_collapse(GtkMenuItem *menuitem, gpointer user_data)
673{
674 gboolean expand = GPOINTER_TO_INT(user_data);
675
676 if (expand)
677 gtk_tree_view_expand_all(GTK_TREE_VIEW(tv.tree_openfiles));
678 else
679 gtk_tree_view_collapse_all(GTK_TREE_VIEW(tv.tree_openfiles));
680}
682
683static void create_openfiles_popup_menu(void)
684{
685 GtkWidget *item;
686
687 openfiles_popup_menu = gtk_menu_new();
688
689 item = gtk_image_menu_item_new_from_stock(GTK_STOCK_CLOSE, NULL);
690 gtk_widget_show(item);
691 gtk_container_add(GTK_CONTAINER(openfiles_popup_menu), item);
692 g_signal_connect(item, "activate",
693 G_CALLBACK(on_openfiles_document_action), GINT_TO_POINTER(OPENFILES_ACTION_REMOVE));
694 doc_items.close = item;
695
696 item = gtk_separator_menu_item_new();
697 gtk_widget_show(item);
698 gtk_container_add(GTK_CONTAINER(openfiles_popup_menu), item);
699
700 item = gtk_image_menu_item_new_from_stock(GTK_STOCK_SAVE, NULL);
701 gtk_widget_show(item);
702 gtk_container_add(GTK_CONTAINER(openfiles_popup_menu), item);
703 g_signal_connect(item, "activate",
704 G_CALLBACK(on_openfiles_document_action), GINT_TO_POINTER(OPENFILES_ACTION_SAVE));
705 doc_items.save = item;
706
707 item = gtk_image_menu_item_new_with_mnemonic(_("_Reload"));
708 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item),
709 gtk_image_new_from_stock(GTK_STOCK_REVERT_TO_SAVED, GTK_ICON_SIZE_MENU));
710 gtk_widget_show(item);
711 gtk_container_add(GTK_CONTAINER(openfiles_popup_menu), item);
712 g_signal_connect(item, "activate",
713 G_CALLBACK(on_openfiles_document_action), GINT_TO_POINTER(OPENFILES_ACTION_RELOAD));
714 doc_items.reload = item;
715
716 item = gtk_separator_menu_item_new();
717 gtk_widget_show(item);
718 gtk_container_add(GTK_CONTAINER(openfiles_popup_menu), item);
719
720 item = ui_image_menu_item_new(GTK_STOCK_FIND, _("_Find in Files..."));
721 gtk_widget_show(item);
722 gtk_container_add(GTK_CONTAINER(openfiles_popup_menu), item);
723 g_signal_connect(item, "activate", G_CALLBACK(on_find_in_files), NULL);
724 doc_items.find_in_files = item;
725
726 item = gtk_separator_menu_item_new();
727 gtk_widget_show(item);
728 gtk_container_add(GTK_CONTAINER(openfiles_popup_menu), item);
729
730 doc_items.show_paths = gtk_check_menu_item_new_with_mnemonic(_("Show _Paths"));
731 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(doc_items.show_paths), documents_show_paths);
732 gtk_widget_show(doc_items.show_paths);
733 gtk_container_add(GTK_CONTAINER(openfiles_popup_menu), doc_items.show_paths);
734 g_signal_connect(doc_items.show_paths, "activate",
736
737 item = gtk_separator_menu_item_new();
738 gtk_widget_show(item);
739 gtk_container_add(GTK_CONTAINER(openfiles_popup_menu), item);
740
741 doc_items.expand_all = ui_image_menu_item_new(GTK_STOCK_ADD, _("_Expand All"));
742 gtk_widget_show(doc_items.expand_all);
743 gtk_container_add(GTK_CONTAINER(openfiles_popup_menu), doc_items.expand_all);
744 g_signal_connect(doc_items.expand_all, "activate",
745 G_CALLBACK(on_openfiles_expand_collapse), GINT_TO_POINTER(TRUE));
746
747 doc_items.collapse_all = ui_image_menu_item_new(GTK_STOCK_REMOVE, _("_Collapse All"));
748 gtk_widget_show(doc_items.collapse_all);
749 gtk_container_add(GTK_CONTAINER(openfiles_popup_menu), doc_items.collapse_all);
750 g_signal_connect(doc_items.collapse_all, "activate",
751 G_CALLBACK(on_openfiles_expand_collapse), GINT_TO_POINTER(FALSE));
752
754}
756
757static void unfold_parent(GtkTreeIter *iter)
758{
759 GtkTreeIter parent;
760
761 if (gtk_tree_model_iter_parent(GTK_TREE_MODEL(store_openfiles), &parent, iter))
762 {
763 GtkTreePath *path = gtk_tree_model_get_path(GTK_TREE_MODEL(store_openfiles), &parent);
764 gtk_tree_view_expand_row(GTK_TREE_VIEW(tv.tree_openfiles), path, TRUE);
765 gtk_tree_path_free(path);
766 }
767}
768
769
770/* compares the given data with the doc pointer from the selected row of openfiles
771 * treeview, in case of a match the row is selected and TRUE is returned
772 * (called indirectly from gtk_tree_model_foreach()) */
773static gboolean tree_model_find_node(GtkTreeModel *model, GtkTreePath *path,
774 GtkTreeIter *iter, gpointer data)
775{
776 GeanyDocument *doc;
777
778 gtk_tree_model_get(GTK_TREE_MODEL(store_openfiles), iter, DOCUMENTS_DOCUMENT, &doc, -1);
779
780 if (doc == data)
781 {
782 /* unfolding also prevents a strange bug where the selection gets stuck on the parent
783 * when it is collapsed and then switching documents */
784 unfold_parent(iter);
785 gtk_tree_view_set_cursor(GTK_TREE_VIEW(tv.tree_openfiles), path, NULL, FALSE);
786 return TRUE;
787 }
788 else return FALSE;
789}
791
793{
794 gtk_tree_model_foreach(GTK_TREE_MODEL(store_openfiles), tree_model_find_node, doc);
795}
796
797
798/* callbacks */
799
800static void document_action(GeanyDocument *doc, gint action)
801{
802 if (! DOC_VALID(doc))
803 return;
804
805 switch (action)
806 {
808 {
809 document_close(doc);
810 break;
811 }
813 {
814 document_save_file(doc, FALSE);
815 break;
816 }
818 {
820 break;
821 }
822 }
823}
825
826static void on_openfiles_document_action(GtkMenuItem *menuitem, gpointer user_data)
827{
828 GtkTreeIter iter;
829 GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(tv.tree_openfiles));
830 GtkTreeModel *model;
831 GeanyDocument *doc;
832 gint action = GPOINTER_TO_INT(user_data);
833
834 if (gtk_tree_selection_get_selected(selection, &model, &iter))
835 {
836 gtk_tree_model_get(model, &iter, DOCUMENTS_DOCUMENT, &doc, -1);
837 if (doc)
838 {
839 document_action(doc, action);
840 }
841 else
842 {
843 /* parent item selected */
844 GtkTreeIter child;
845 gint i = gtk_tree_model_iter_n_children(model, &iter) - 1;
846
847 while (i >= 0 && gtk_tree_model_iter_nth_child(model, &child, &iter, i))
848 {
849 gtk_tree_model_get(model, &child, DOCUMENTS_DOCUMENT, &doc, -1);
850
851 document_action(doc, action);
852 i--;
853 }
854 }
855 }
856}
858
859static void change_focus_to_editor(GeanyDocument *doc, GtkWidget *source_widget)
860{
861 if (may_steal_focus)
862 document_try_focus(doc, source_widget);
863 may_steal_focus = FALSE;
864}
866
867static gboolean openfiles_go_to_selection(GtkTreeSelection *selection, guint keyval)
868{
869 GtkTreeIter iter;
870 GtkTreeModel *model;
871 GeanyDocument *doc = NULL;
872
873 /* use switch_notebook_page to ignore changing the notebook page because it is already done */
874 if (gtk_tree_selection_get_selected(selection, &model, &iter) && ! ignore_callback)
875 {
876 gtk_tree_model_get(model, &iter, DOCUMENTS_DOCUMENT, &doc, -1);
877 if (! doc)
878 return FALSE; /* parent */
879
880 /* switch to the doc and grab the focus */
882 if (keyval != GDK_KEY_space)
884 }
885 return FALSE;
886}
888
889static gboolean taglist_go_to_selection(GtkTreeSelection *selection, guint keyval, guint state)
890{
891 GtkTreeIter iter;
892 GtkTreeModel *model;
893 gint line = 0;
894 gboolean handled = TRUE;
895
896 if (gtk_tree_selection_get_selected(selection, &model, &iter))
897 {
898 TMTag *tag;
899
900 gtk_tree_model_get(model, &iter, SYMBOLS_COLUMN_TAG, &tag, -1);
901 if (! tag)
902 return FALSE;
903
904 line = tag->line;
905 if (line > 0)
906 {
908
909 if (doc != NULL)
910 {
911 navqueue_goto_line(doc, doc, line);
912 state = keybindings_get_modifiers(state);
913 if (keyval != GDK_KEY_space && ! (state & GEANY_PRIMARY_MOD_MASK))
915 else
916 handled = FALSE;
917 }
918 }
919 tm_tag_unref(tag);
920 }
921 return handled;
922}
924
925static gboolean sidebar_key_press_cb(GtkWidget *widget, GdkEventKey *event,
926 gpointer user_data)
927{
928 may_steal_focus = FALSE;
929 if (ui_is_keyval_enter_or_return(event->keyval) || event->keyval == GDK_KEY_space)
930 {
931 GtkWidgetClass *widget_class = GTK_WIDGET_GET_CLASS(widget);
932 GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(widget));
933 may_steal_focus = TRUE;
934
935 /* force the TreeView handler to run before us for it to do its job (selection & stuff).
936 * doing so will prevent further handlers to be run in most cases, but the only one is our
937 * own, so guess it's fine. */
938 if (widget_class->key_press_event)
939 widget_class->key_press_event(widget, event);
940
941 if (widget == tv.tree_openfiles) /* tag and doc list have separate handlers */
942 openfiles_go_to_selection(selection, event->keyval);
943 else
944 taglist_go_to_selection(selection, event->keyval, event->state);
945
946 return TRUE;
947 }
948 return FALSE;
949}
951
952static gboolean sidebar_button_press_cb(GtkWidget *widget, GdkEventButton *event,
953 G_GNUC_UNUSED gpointer user_data)
954{
955 GtkTreeSelection *selection;
956 GtkWidgetClass *widget_class = GTK_WIDGET_GET_CLASS(widget);
957 gboolean handled = FALSE;
958
959 /* force the TreeView handler to run before us for it to do its job (selection & stuff).
960 * doing so will prevent further handlers to be run in most cases, but the only one is our own,
961 * so guess it's fine. */
962 if (widget_class->button_press_event)
963 handled = widget_class->button_press_event(widget, event);
964
965 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(widget));
966 may_steal_focus = TRUE;
967
968 if (event->type == GDK_2BUTTON_PRESS)
969 { /* double click on parent node(section) expands/collapses it */
970 GtkTreeModel *model;
971 GtkTreeIter iter;
972
973 if (gtk_tree_selection_get_selected(selection, &model, &iter))
974 {
975 if (gtk_tree_model_iter_has_child(model, &iter))
976 {
977 GtkTreePath *path = gtk_tree_model_get_path(model, &iter);
978
979 if (gtk_tree_view_row_expanded(GTK_TREE_VIEW(widget), path))
980 gtk_tree_view_collapse_row(GTK_TREE_VIEW(widget), path);
981 else
982 gtk_tree_view_expand_row(GTK_TREE_VIEW(widget), path, FALSE);
983
984 gtk_tree_path_free(path);
985 return TRUE;
986 }
987 }
988 }
989 else if (event->button == 1)
990 { /* allow reclicking of taglist treeview item */
991 if (widget == tv.tree_openfiles)
992 {
993 openfiles_go_to_selection(selection, 0);
994 handled = TRUE;
995 }
996 else
997 handled = taglist_go_to_selection(selection, 0, event->state);
998 }
999 else if (event->button == 2)
1000 {
1001 if (widget == tv.tree_openfiles)
1003 }
1004 else if (event->button == 3)
1005 {
1006 if (widget == tv.tree_openfiles)
1007 {
1010
1011 /* update menu item sensitivity */
1012 documents_menu_update(selection);
1013 gtk_menu_popup(GTK_MENU(openfiles_popup_menu), NULL, NULL, NULL, NULL,
1014 event->button, event->time);
1015 }
1016 else
1017 {
1018 gtk_menu_popup(GTK_MENU(tv.popup_taglist), NULL, NULL, NULL, NULL,
1019 event->button, event->time);
1020 }
1021 handled = TRUE;
1022 }
1023 return handled;
1024}
1026
1027static void documents_menu_update(GtkTreeSelection *selection)
1028{
1029 GtkTreeModel *model;
1030 GtkTreeIter iter;
1031 gboolean sel, path;
1032 gchar *shortname = NULL;
1033 GeanyDocument *doc = NULL;
1034
1035 /* maybe no selection e.g. if ctrl-click deselected */
1036 sel = gtk_tree_selection_get_selected(selection, &model, &iter);
1037 if (sel)
1038 {
1039 gtk_tree_model_get(model, &iter, DOCUMENTS_DOCUMENT, &doc,
1040 DOCUMENTS_SHORTNAME, &shortname, -1);
1041 }
1042 path = !EMPTY(shortname) &&
1043 (g_path_is_absolute(shortname) ||
1044 (app->project && g_str_has_prefix(shortname, app->project->name)));
1045
1046 /* can close all, save all (except shortname), but only reload individually ATM */
1047 gtk_widget_set_sensitive(doc_items.close, sel);
1048 gtk_widget_set_sensitive(doc_items.save, (doc && doc->real_path) || path);
1049 gtk_widget_set_sensitive(doc_items.reload, doc && doc->real_path);
1050 gtk_widget_set_sensitive(doc_items.find_in_files, sel);
1051 g_free(shortname);
1052
1053 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(doc_items.show_paths), documents_show_paths);
1054 gtk_widget_set_sensitive(doc_items.expand_all, documents_show_paths);
1055 gtk_widget_set_sensitive(doc_items.collapse_all, documents_show_paths);
1056}
1058
1060
1061static void on_load_settings(void)
1062{
1063 tag_window = ui_lookup_widget(main_widgets.window, "scrolledwindow2");
1064
1066 /* note: ui_prefs.sidebar_page is reapplied after plugins are loaded */
1069}
1071
1072static void on_save_settings(void)
1073{
1076}
1078
1079static void on_sidebar_switch_page(GtkNotebook *notebook,
1080 gpointer page, guint page_num, gpointer user_data)
1081{
1082 if (page_num == TREEVIEW_SYMBOL)
1084}
1086
1087void sidebar_init(void)
1088{
1090
1091 group = stash_group_new(PACKAGE);
1092 stash_group_add_boolean(group, &documents_show_paths, "documents_show_paths", TRUE);
1093 stash_group_add_widget_property(group, &ui_prefs.sidebar_page, "sidebar_page", GINT_TO_POINTER(0),
1094 main_widgets.sidebar_notebook, "page", 0);
1097
1098 /* delay building documents treeview until sidebar font has been read */
1099 g_signal_connect(geany_object, "load-settings", on_load_settings, NULL);
1100 g_signal_connect(geany_object, "save-settings", on_save_settings, NULL);
1101
1102 g_signal_connect(main_widgets.sidebar_notebook, "page-added",
1103 G_CALLBACK(sidebar_tabs_show_hide), NULL);
1104 g_signal_connect(main_widgets.sidebar_notebook, "page-removed",
1105 G_CALLBACK(sidebar_tabs_show_hide), NULL);
1106 /* tabs may have changed when sidebar is reshown */
1107 g_signal_connect(main_widgets.sidebar_notebook, "show",
1108 G_CALLBACK(sidebar_tabs_show_hide), NULL);
1109 g_signal_connect_after(main_widgets.sidebar_notebook, "switch-page",
1110 G_CALLBACK(on_sidebar_switch_page), NULL);
1111
1114
1115#define WIDGET(w) w && GTK_IS_WIDGET(w)
1116
1117void sidebar_finalize(void)
1118{
1120 {
1121 gtk_widget_destroy(tv.default_tag_tree); /* make GTK release its references, if any... */
1122 g_object_unref(tv.default_tag_tree); /* ...and release our own */
1123 }
1124 if (WIDGET(tv.popup_taglist))
1125 gtk_widget_destroy(tv.popup_taglist);
1127 gtk_widget_destroy(openfiles_popup_menu);
1128}
1130
1132{
1133 if (ui_prefs.sidebar_visible && interface_prefs.sidebar_openfiles_visible)
1134 {
1135 GtkNotebook *notebook = GTK_NOTEBOOK(main_widgets.sidebar_notebook);
1136
1137 gtk_notebook_set_current_page(notebook, TREEVIEW_OPENFILES);
1138 gtk_widget_grab_focus(tv.tree_openfiles);
1139 }
1140}
1142
1144{
1145 if (ui_prefs.sidebar_visible && interface_prefs.sidebar_symbol_visible)
1146 {
1147 GtkNotebook *notebook = GTK_NOTEBOOK(main_widgets.sidebar_notebook);
1148 GtkWidget *symbol_list_scrollwin = gtk_notebook_get_nth_page(notebook, TREEVIEW_SYMBOL);
1149
1150 gtk_notebook_set_current_page(notebook, TREEVIEW_SYMBOL);
1151 gtk_widget_grab_focus(gtk_bin_get_child(GTK_BIN(symbol_list_scrollwin)));
1152 }
1153}
1155
1156static void sidebar_tabs_show_hide(GtkNotebook *notebook, GtkWidget *child,
1157 guint page_num, gpointer data)
1158{
1159 gint tabs = gtk_notebook_get_n_pages(notebook);
1160
1162 tabs--;
1164 tabs--;
1165
1166 gtk_notebook_set_show_tabs(notebook, (tabs > 1));
1167}
Contains the GeanyApp.
const gchar * label
Definition: build.c:2676
gboolean ignore_callback
Definition: libmain.c:87
GeanyDocument * document_get_current(void)
Finds the current document.
Definition: document.c:371
const GdkColor * document_get_status_color(GeanyDocument *doc)
Gets the status color of the document, or NULL if default widget coloring should be used.
Definition: document.c:3276
void document_show_tab(GeanyDocument *doc)
Definition: document.c:1273
gboolean document_save_file(GeanyDocument *doc, gboolean force)
Saves the document.
Definition: document.c:2103
void document_try_focus(GeanyDocument *doc, GtkWidget *source_widget)
Definition: document.c:595
const gchar * name
Definition: document.c:3219
GdkColor color
Definition: document.c:3220
gboolean document_reload_prompt(GeanyDocument *doc, const gchar *forced_enc)
Definition: document.c:1635
#define DOC_VALID(doc_ptr)
Null-safe way to check GeanyDocument::is_valid.
Definition: document.h:162
#define DOC_FILENAME(doc)
Returns the filename of the document passed or GEANY_STRING_UNTITLED (e.g.
Definition: document.h:170
#define documents
Wraps GeanyData::documents_array so it can be used with C array syntax.
Definition: document.h:130
#define foreach_document(i)
Iterates all valid document indexes.
Definition: document.h:153
static void expand(ScintillaObject *sci, gint *line, gboolean doExpand, gboolean force, gint visLevels, gint level)
Definition: editor.c:878
currently not working see documentation true uses any is tabs
Definition: filetypes.d:66
#define GEANY_STRING_UNTITLED
Definition: geany.h:49
vString * line
Definition: geany_cobol.c:133
GObject * geany_object
Definition: geanyobject.c:41
GdkModifierType keybindings_get_modifiers(GdkModifierType mods)
Gets significant modifiers from a GdkModifierType mask.
Definition: keybindings.c:121
Configurable keyboard shortcuts.
#define GEANY_PRIMARY_MOD_MASK
Defines the primary modifier mask which is the Ctrl key mask on UNIX/Windows and Command key mask on ...
Definition: keybindings.h:36
void configuration_add_pref_group(struct StashGroup *group, gboolean for_prefs_dialog)
Definition: keyfile.c:128
GeanyApp * app
Definition: libmain.c:86
gboolean navqueue_goto_line(GeanyDocument *old_doc, GeanyDocument *new_doc, gint line)
Adds old file position and new file position to the navqueue, then goes to the new position.
Definition: navqueue.c:151
Simple code navigation.
signal void(* document_close)(GObject *obj, GeanyDocument *doc, gpointer user_data)
Sent before closing a document.
gchar * project_get_base_path(void)
Definition: project.c:1171
#define NULL
Definition: rbtree.h:150
void search_show_find_in_files_dialog(const gchar *dir)
Shows the Find in Files dialog.
Definition: search.c:1041
static gboolean utils_filename_has_prefix(const gchar *str, const gchar *prefix)
Definition: sidebar.c:356
GtkWidget * reload
Definition: sidebar.c:58
static StashGroup * stash_group
Definition: sidebar.c:1057
@ TREEVIEW_OPENFILES
Definition: sidebar.c:69
@ TREEVIEW_SYMBOL
Definition: sidebar.c:68
#define CHANGE_TREE(new_child)
static void on_find_in_files(GtkMenuItem *menuitem, gpointer user_data)
Definition: sidebar.c:645
GtkWidget * collapse_all
Definition: sidebar.c:62
static void prepare_taglist(GtkWidget *tree, GtkTreeStore *store)
Definition: sidebar.c:108
static void on_list_document_activate(GtkCheckMenuItem *item, gpointer user_data)
Definition: sidebar.c:629
static gboolean tree_model_find_node(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
Definition: sidebar.c:771
void sidebar_finalize(void)
Definition: sidebar.c:1115
@ DOCUMENTS_DOCUMENT
Definition: sidebar.c:84
@ DOCUMENTS_FILENAME
Definition: sidebar.c:86
@ DOCUMENTS_COLOR
Definition: sidebar.c:85
@ DOCUMENTS_ICON
Definition: sidebar.c:82
@ DOCUMENTS_SHORTNAME
Definition: sidebar.c:83
static gboolean sidebar_button_press_cb(GtkWidget *widget, GdkEventButton *event, gpointer user_data)
GtkWidget * find_in_files
Definition: sidebar.c:60
static void on_openfiles_show_paths_activate(GtkCheckMenuItem *item, gpointer user_data)
Definition: sidebar.c:622
static gboolean documents_show_paths
Definition: sidebar.c:91
static GtkTreeStore * store_openfiles
Definition: sidebar.c:89
void sidebar_add_common_menu_items(GtkMenu *menu)
Definition: sidebar.c:591
static void openfiles_remove(GeanyDocument *doc)
Definition: sidebar.c:494
static GtkWidget * openfiles_popup_menu
Definition: sidebar.c:90
static void on_openfiles_document_action(GtkMenuItem *menuitem, gpointer user_data)
Definition: sidebar.c:824
static void on_load_settings(void)
Definition: sidebar.c:1059
static GtkTreeIter * get_doc_parent(GeanyDocument *doc)
Definition: sidebar.c:418
static struct @110 doc_items
static gchar * get_doc_folder(const gchar *path)
Definition: sidebar.c:366
static void prepare_openfiles(void)
Definition: sidebar.c:274
void sidebar_focus_openfiles_tab(void)
Definition: sidebar.c:1129
static gboolean find_tree_iter_dir(GtkTreeIter *iter, const gchar *dir)
Definition: sidebar.c:335
static void on_hide_sidebar(void)
Definition: sidebar.c:568
static gboolean may_steal_focus
Definition: sidebar.c:52
SidebarTreeviews tv
Definition: sidebar.c:50
static void unfold_parent(GtkTreeIter *iter)
Definition: sidebar.c:755
@ OPENFILES_ACTION_REMOVE
Definition: sidebar.c:74
@ OPENFILES_ACTION_SAVE
Definition: sidebar.c:75
@ OPENFILES_ACTION_RELOAD
Definition: sidebar.c:76
static void document_action(GeanyDocument *doc, gint action)
Definition: sidebar.c:798
static void change_focus_to_editor(GeanyDocument *doc, GtkWidget *source_widget)
Definition: sidebar.c:857
static gboolean on_default_tag_tree_button_press_event(GtkWidget *widget, GdkEventButton *event, gpointer user_data)
Definition: sidebar.c:154
static gboolean on_sidebar_display_open_files_show(GtkWidget *item)
Definition: sidebar.c:583
void sidebar_focus_symbols_tab(void)
Definition: sidebar.c:1141
void sidebar_remove_document(GeanyDocument *doc)
Definition: sidebar.c:554
void sidebar_openfiles_update_all(void)
Definition: sidebar.c:542
static gboolean openfiles_go_to_selection(GtkTreeSelection *selection, guint keyval)
Definition: sidebar.c:865
GtkWidget * save
Definition: sidebar.c:57
static gboolean taglist_go_to_selection(GtkTreeSelection *selection, guint keyval, guint state)
Definition: sidebar.c:887
static void sidebar_tabs_show_hide(GtkNotebook *notebook, GtkWidget *child, guint page_num, gpointer data)
Definition: sidebar.c:1154
static void on_openfiles_expand_collapse(GtkMenuItem *menuitem, gpointer user_data)
Definition: sidebar.c:670
static void create_default_tag_tree(void)
Definition: sidebar.c:167
void sidebar_openfiles_update(GeanyDocument *doc)
Definition: sidebar.c:507
static gint documents_sort_func(GtkTreeModel *model, GtkTreeIter *iter_a, GtkTreeIter *iter_b, gpointer data)
Definition: sidebar.c:252
static void on_sidebar_switch_page(GtkNotebook *notebook, gpointer page, guint page_num, gpointer user_data)
Definition: sidebar.c:1077
static void on_save_settings(void)
Definition: sidebar.c:1070
static void on_list_symbol_activate(GtkCheckMenuItem *item, gpointer user_data)
Definition: sidebar.c:637
static gboolean sidebar_key_press_cb(GtkWidget *widget, GdkEventKey *event, gpointer user_data)
Definition: sidebar.c:923
GtkWidget * close
Definition: sidebar.c:56
void sidebar_select_openfiles_item(GeanyDocument *doc)
Definition: sidebar.c:790
GtkWidget * show_paths
Definition: sidebar.c:59
void sidebar_init(void)
Definition: sidebar.c:1085
static GtkWidget * tag_window
Definition: sidebar.c:92
static void create_openfiles_popup_menu(void)
Definition: sidebar.c:681
void sidebar_openfiles_add(GeanyDocument *doc)
Definition: sidebar.c:462
GtkWidget * expand_all
Definition: sidebar.c:61
#define WIDGET(w)
Definition: sidebar.c:1113
static void documents_menu_update(GtkTreeSelection *selection)
Definition: sidebar.c:1025
void sidebar_update_tag_list(GeanyDocument *doc, gboolean update)
Definition: sidebar.c:188
static gboolean on_sidebar_display_symbol_list_show(GtkWidget *item)
Definition: sidebar.c:575
@ SYMBOLS_COLUMN_TAG
Definition: sidebar.h:46
@ SYMBOLS_COLUMN_ICON
Definition: sidebar.h:44
@ SYMBOLS_COLUMN_TOOLTIP
Definition: sidebar.h:47
@ SYMBOLS_N_COLUMNS
Definition: sidebar.h:48
@ SYMBOLS_COLUMN_NAME
Definition: sidebar.h:45
gboolean filetype_has_tags(GeanyFiletype *ft)
Definition: filetypes.c:1227
StashGroup * group
Definition: stash-example.c:1
stash_group_add_boolean(group, &china_enabled, "china", TRUE)
stash_group_update(group, dialog)
gtk_container_add(GTK_CONTAINER(dialog->vbox), check_button)
gtk_widget_show_all(dialog)
stash_group_display(group, dialog)
StashGroup * stash_group_new(const gchar *name)
Creates a new group.
Definition: stash.c:360
void stash_group_add_widget_property(StashGroup *group, gpointer setting, const gchar *key_name, gpointer default_value, StashWidgetID widget_id, const gchar *property_name, GType type)
Adds a widget's read/write property to the stash group.
Definition: stash.c:977
Lightweight library for reading/writing GKeyFile settings and synchronizing widgets with C variables.
struct GeanyProject * project
Currently active project or NULL if none is open.
Definition: app.h:49
GtkTreeStore * tag_store
Structure for representing an open tab with all its properties.
Definition: document.h:81
gchar * file_name
The UTF-8 encoded file name.
Definition: document.h:92
GeanyFiletype * file_type
The filetype for this document, it's only a reference to one of the elements of the global filetypes ...
Definition: document.h:101
gboolean has_tags
Whether this document supports source code symbols(tags) to show in the sidebar.
Definition: document.h:86
struct GeanyDocumentPrivate * priv
Definition: document.h:121
gchar * real_path
The link-dereferenced, locale-encoded file name.
Definition: document.h:115
gboolean is_valid
Flag used to check if this document is valid when iterating GeanyData::documents_array.
Definition: document.h:83
GIcon * icon
Definition: filetypes.h:165
gboolean show_symbol_list_expanders
whether to show expanders in the symbol list
Definition: ui_utils.h:57
gboolean sidebar_symbol_visible
whether the symbol sidebar is visible
Definition: ui_utils.h:47
gboolean sidebar_openfiles_visible
whether the open file list is visible
Definition: ui_utils.h:48
gchar * tagbar_font
symbol sidebar font
Definition: ui_utils.h:50
GtkWidget * window
Main window.
Definition: ui_utils.h:80
GtkWidget * sidebar_notebook
Sidebar notebook.
Definition: ui_utils.h:82
gchar * name
The name of the project.
Definition: project.h:36
GtkWidget * tree_openfiles
Definition: sidebar.h:34
GtkWidget * default_tag_tree
Definition: sidebar.h:35
GtkWidget * popup_taglist
Definition: sidebar.h:36
The TMTag structure represents a single tag in the tag manager.
Definition: tm_tag.h:88
gulong line
Line number of the tag.
Definition: tm_tag.h:95
Defines internationalization macros.
#define _(String)
Definition: support.h:42
gboolean symbols_recreate_tag_list(GeanyDocument *doc, gint sort_mode)
Definition: symbols.c:1597
Tag-related functions.
void tm_tag_unref(TMTag *tag)
Definition: tm_tag.c:136
#define TM_TYPE_TAG
Definition: tm_tag.h:108
void ui_sidebar_show_hide(void)
Definition: ui_utils.c:1000
gboolean ui_is_keyval_enter_or_return(guint keyval)
Checks whether the passed keyval is the Enter or Return key.
Definition: ui_utils.c:3009
GIcon * ui_get_mime_icon(const gchar *mime_type)
Definition: ui_utils.c:3058
GeanyMainWidgets main_widgets
Definition: ui_utils.c:72
UIPrefs ui_prefs
Definition: ui_utils.c:74
GtkWidget * ui_image_menu_item_new(const gchar *stock_id, const gchar *label)
Creates a GtkImageMenuItem with a stock image and a custom label.
Definition: ui_utils.c:1574
GtkWidget * ui_lookup_widget(GtkWidget *widget, const gchar *widget_name)
Returns a widget from a name in a component, usually created by Glade.
Definition: ui_utils.c:2743
void ui_tree_view_set_tooltip_text_column(GtkTreeView *tree_view, gint column)
Adds text tooltips to a tree view.
Definition: ui_utils.c:1876
void ui_widget_modify_font_from_string(GtkWidget *widget, const gchar *str)
Modifies the font of a widget using gtk_widget_modify_font().
Definition: ui_utils.c:1894
GeanyInterfacePrefs interface_prefs
Definition: ui_utils.c:71
User Interface general utility functions.
gboolean utils_str_equal(const gchar *a, const gchar *b)
NULL-safe string comparison.
Definition: utils.c:599
General utility functions, non-GTK related.
#define EMPTY(ptr)
Returns TRUE if ptr is NULL or *ptr is FALSE.
Definition: utils.h:38
#define utils_filenamecmp(a, b)
Definition: utils.h:86