~ubuntu-branches/ubuntu/natty/geany/natty

« back to all changes in this revision

Viewing changes to src/sidebar.c

  • Committer: Bazaar Package Importer
  • Author(s): Chow Loong Jin
  • Date: 2010-08-07 03:23:12 UTC
  • mfrom: (1.4.3 upstream)
  • mto: This revision was merged to the branch mainline in revision 22.
  • Revision ID: james.westby@ubuntu.com-20100807032312-ot70ac9d50cn79we
Tags: upstream-0.19
ImportĀ upstreamĀ versionĀ 0.19

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *      sidebar.c - this file is part of Geany, a fast and lightweight IDE
 
3
 *
 
4
 *      Copyright 2005-2010 Enrico Trƶger <enrico(dot)troeger(at)uvena(dot)de>
 
5
 *      Copyright 2006-2010 Nick Treleaven <nick(dot)treleaven(at)btinternet(dot)com>
 
6
 *
 
7
 *      This program is free software; you can redistribute it and/or modify
 
8
 *      it under the terms of the GNU General Public License as published by
 
9
 *      the Free Software Foundation; either version 2 of the License, or
 
10
 *      (at your option) any later version.
 
11
 *
 
12
 *      This program is distributed in the hope that it will be useful,
 
13
 *      but WITHOUT ANY WARRANTY; without even the implied warranty of
 
14
 *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
15
 *      GNU General Public License for more details.
 
16
 *
 
17
 *      You should have received a copy of the GNU General Public License
 
18
 *      along with this program; if not, write to the Free Software
 
19
 *      Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 
20
 *
 
21
 * $Id: sidebar.c 5003 2010-06-06 17:21:52Z eht16 $
 
22
 */
 
23
 
 
24
/*
 
25
 * Sidebar related code for the Symbol list and Open files GtkTreeViews.
 
26
 */
 
27
 
 
28
#include <string.h>
 
29
 
 
30
#include "geany.h"
 
31
#include "support.h"
 
32
#include "callbacks.h"
 
33
#include "sidebar.h"
 
34
#include "document.h"
 
35
#include "editor.h"
 
36
#include "documentprivate.h"
 
37
#include "filetypes.h"
 
38
#include "utils.h"
 
39
#include "ui_utils.h"
 
40
#include "symbols.h"
 
41
#include "navqueue.h"
 
42
#include "project.h"
 
43
#include "stash.h"
 
44
#include "keyfile.h"
 
45
#include "sciwrappers.h"
 
46
 
 
47
#include <gdk/gdkkeysyms.h>
 
48
 
 
49
 
 
50
SidebarTreeviews tv = {NULL, NULL, NULL};
 
51
/* while typeahead searching, editor should not get focus */
 
52
static gboolean may_steal_focus = FALSE;
 
53
 
 
54
static struct
 
55
{
 
56
        GtkWidget *close;
 
57
        GtkWidget *save;
 
58
        GtkWidget *reload;
 
59
        GtkWidget *show_paths;
 
60
}
 
61
doc_items = {NULL, NULL, NULL, NULL};
 
62
 
 
63
static struct
 
64
{
 
65
        GtkTreeSelection *selection;
 
66
        guint keyval;
 
67
} selection_change = {NULL, 0};
 
68
 
 
69
enum
 
70
{
 
71
        TREEVIEW_SYMBOL = 0,
 
72
        TREEVIEW_OPENFILES
 
73
};
 
74
 
 
75
enum
 
76
{
 
77
        OPENFILES_ACTION_REMOVE = 0,
 
78
        OPENFILES_ACTION_SAVE,
 
79
        OPENFILES_ACTION_RELOAD
 
80
};
 
81
 
 
82
/* documents tree model columns */
 
83
enum
 
84
{
 
85
        DOCUMENTS_ICON,
 
86
        DOCUMENTS_SHORTNAME,    /* dirname for parents, basename for children */
 
87
        DOCUMENTS_DOCUMENT,
 
88
        DOCUMENTS_COLOR,
 
89
        DOCUMENTS_FILENAME              /* full filename */
 
90
};
 
91
 
 
92
static GtkTreeStore     *store_openfiles;
 
93
static GtkWidget *openfiles_popup_menu;
 
94
static gboolean documents_show_paths;
 
95
static GtkWidget *tag_window;   /* scrolled window that holds the symbol list GtkTreeView */
 
96
 
 
97
/* callback prototypes */
 
98
static gboolean on_openfiles_tree_selection_changed(gpointer data);
 
99
static void on_openfiles_document_action(GtkMenuItem *menuitem, gpointer user_data);
 
100
static gboolean on_taglist_tree_selection_changed(gpointer data);
 
101
static gboolean sidebar_button_press_cb(GtkWidget *widget, GdkEventButton *event,
 
102
                gpointer user_data);
 
103
static gboolean sidebar_key_press_cb(GtkWidget *widget, GdkEventKey *event,
 
104
                gpointer user_data);
 
105
static void on_list_document_activate(GtkCheckMenuItem *item, gpointer user_data);
 
106
static void on_list_symbol_activate(GtkCheckMenuItem *item, gpointer user_data);
 
107
static void documents_menu_update(GtkTreeSelection *selection);
 
108
static void sidebar_tabs_show_hide(GtkNotebook *notebook, GtkWidget *child,
 
109
                                                                   guint page_num, gpointer data);
 
110
 
 
111
 
 
112
/* the prepare_* functions are document-related, but I think they fit better here than in document.c */
 
113
static void prepare_taglist(GtkWidget *tree, GtkTreeStore *store)
 
114
{
 
115
        GtkCellRenderer *text_renderer, *icon_renderer;
 
116
        GtkTreeViewColumn *column;
 
117
        GtkTreeSelection *selection;
 
118
 
 
119
        text_renderer = gtk_cell_renderer_text_new();
 
120
        icon_renderer = gtk_cell_renderer_pixbuf_new();
 
121
        column = gtk_tree_view_column_new();
 
122
 
 
123
        gtk_tree_view_column_pack_start(column, icon_renderer, FALSE);
 
124
        gtk_tree_view_column_set_attributes(column, icon_renderer, "pixbuf", SYMBOLS_COLUMN_ICON, NULL);
 
125
        g_object_set(icon_renderer, "xalign", 0.0, NULL);
 
126
 
 
127
        gtk_tree_view_column_pack_start(column, text_renderer, TRUE);
 
128
        gtk_tree_view_column_set_attributes(column, text_renderer, "text", SYMBOLS_COLUMN_NAME, NULL);
 
129
        g_object_set(text_renderer, "yalign", 0.5, NULL);
 
130
        gtk_tree_view_column_set_title(column, _("Symbols"));
 
131
 
 
132
        gtk_tree_view_append_column(GTK_TREE_VIEW(tree), column);
 
133
        gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(tree), FALSE);
 
134
 
 
135
        ui_widget_modify_font_from_string(tree, interface_prefs.tagbar_font);
 
136
 
 
137
        gtk_tree_view_set_model(GTK_TREE_VIEW(tree), GTK_TREE_MODEL(store));
 
138
        g_object_unref(store);
 
139
 
 
140
        g_signal_connect(tree, "button-press-event",
 
141
                G_CALLBACK(sidebar_button_press_cb), NULL);
 
142
        g_signal_connect(tree, "key-press-event",
 
143
                G_CALLBACK(sidebar_key_press_cb), NULL);
 
144
 
 
145
        if (gtk_check_version(2, 12, 0) == NULL)
 
146
        {
 
147
                g_object_set(tree, "show-expanders", interface_prefs.show_symbol_list_expanders, NULL);
 
148
                if (! interface_prefs.show_symbol_list_expanders)
 
149
                        g_object_set(tree, "level-indentation", 10, NULL);
 
150
                /* Tooltips */
 
151
                g_object_set(tree,
 
152
                        "has-tooltip", TRUE,
 
153
                        "tooltip-column", SYMBOLS_COLUMN_TOOLTIP, NULL);
 
154
        }
 
155
 
 
156
        /* selection handling */
 
157
        selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(tree));
 
158
        gtk_tree_selection_set_mode(selection, GTK_SELECTION_SINGLE);
 
159
        /* callback for changed selection not necessary, will be handled by button-press-event */
 
160
}
 
161
 
 
162
 
 
163
static gboolean
 
164
on_default_tag_tree_button_press_event(GtkWidget *widget, GdkEventButton *event,
 
165
                gpointer user_data)
 
166
{
 
167
        if (event->button == 3)
 
168
        {
 
169
                gtk_menu_popup(GTK_MENU(tv.popup_taglist), NULL, NULL, NULL, NULL,
 
170
                        event->button, event->time);
 
171
                return TRUE;
 
172
        }
 
173
        return FALSE;
 
174
}
 
175
 
 
176
 
 
177
static void create_default_tag_tree(void)
 
178
{
 
179
        GtkScrolledWindow *scrolled_window = GTK_SCROLLED_WINDOW(tag_window);
 
180
        GtkWidget *label;
 
181
 
 
182
        /* default_tag_tree is a GtkViewPort with a GtkLabel inside it */
 
183
        tv.default_tag_tree = gtk_viewport_new(
 
184
                gtk_scrolled_window_get_hadjustment(scrolled_window),
 
185
                gtk_scrolled_window_get_vadjustment(scrolled_window));
 
186
        label = gtk_label_new(_("No tags found"));
 
187
        gtk_misc_set_alignment(GTK_MISC(label), 0.1f, 0.01f);
 
188
        gtk_container_add(GTK_CONTAINER(tv.default_tag_tree), label);
 
189
        gtk_widget_show_all(tv.default_tag_tree);
 
190
        g_signal_connect(tv.default_tag_tree, "button-press-event",
 
191
                G_CALLBACK(on_default_tag_tree_button_press_event), NULL);
 
192
        g_object_ref((gpointer)tv.default_tag_tree);    /* to hold it after removing */
 
193
}
 
194
 
 
195
 
 
196
/* update = rescan the tags for doc->filename */
 
197
void sidebar_update_tag_list(GeanyDocument *doc, gboolean update)
 
198
{
 
199
        if (gtk_bin_get_child(GTK_BIN(tag_window)))
 
200
                gtk_container_remove(GTK_CONTAINER(tag_window), gtk_bin_get_child(GTK_BIN(tag_window)));
 
201
 
 
202
        if (tv.default_tag_tree == NULL)
 
203
                create_default_tag_tree();
 
204
 
 
205
        /* show default empty tag tree if there are no tags */
 
206
        if (doc == NULL || doc->file_type == NULL || ! filetype_has_tags(doc->file_type))
 
207
        {
 
208
                gtk_container_add(GTK_CONTAINER(tag_window), tv.default_tag_tree);
 
209
                return;
 
210
        }
 
211
 
 
212
        if (update)
 
213
        {       /* updating the tag list in the left tag window */
 
214
                if (doc->priv->tag_tree == NULL)
 
215
                {
 
216
                        doc->priv->tag_store = gtk_tree_store_new(
 
217
                                SYMBOLS_N_COLUMNS, GDK_TYPE_PIXBUF, G_TYPE_STRING, G_TYPE_POINTER, G_TYPE_STRING);
 
218
                        doc->priv->tag_tree = gtk_tree_view_new();
 
219
                        prepare_taglist(doc->priv->tag_tree, doc->priv->tag_store);
 
220
                        gtk_widget_show(doc->priv->tag_tree);
 
221
                        g_object_ref((gpointer)doc->priv->tag_tree);    /* to hold it after removing */
 
222
                }
 
223
 
 
224
                doc->has_tags = symbols_recreate_tag_list(doc, SYMBOLS_SORT_USE_PREVIOUS);
 
225
        }
 
226
 
 
227
        if (doc->has_tags)
 
228
        {
 
229
                gtk_container_add(GTK_CONTAINER(tag_window), doc->priv->tag_tree);
 
230
        }
 
231
        else
 
232
        {
 
233
                gtk_container_add(GTK_CONTAINER(tag_window), tv.default_tag_tree);
 
234
        }
 
235
}
 
236
 
 
237
 
 
238
/* cleverly sorts documents by their short name */
 
239
static gint documents_sort_func(GtkTreeModel *model, GtkTreeIter *iter_a,
 
240
                                                                GtkTreeIter *iter_b, gpointer data)
 
241
{
 
242
        gchar *key_a, *key_b;
 
243
        gchar *name_a, *name_b;
 
244
        gint cmp;
 
245
 
 
246
        gtk_tree_model_get(model, iter_a, DOCUMENTS_SHORTNAME, &name_a, -1);
 
247
        key_a = g_utf8_collate_key_for_filename(name_a, -1);
 
248
        g_free(name_a);
 
249
        gtk_tree_model_get(model, iter_b, DOCUMENTS_SHORTNAME, &name_b, -1);
 
250
        key_b = g_utf8_collate_key_for_filename(name_b, -1);
 
251
        g_free(name_b);
 
252
        cmp = strcmp(key_a, key_b);
 
253
        g_free(key_b);
 
254
        g_free(key_a);
 
255
 
 
256
        return cmp;
 
257
}
 
258
 
 
259
 
 
260
/* does some preparing things to the open files list widget */
 
261
static void prepare_openfiles(void)
 
262
{
 
263
        GtkCellRenderer *icon_renderer;
 
264
        GtkCellRenderer *text_renderer;
 
265
        GtkTreeViewColumn *column;
 
266
        GtkTreeSelection *selection;
 
267
        GtkTreeSortable *sortable;
 
268
 
 
269
        tv.tree_openfiles = ui_lookup_widget(main_widgets.window, "treeview6");
 
270
 
 
271
        /* store the icon and the short filename to show, and the index as reference,
 
272
         * the colour (black/red/green) and the full name for the tooltip */
 
273
        store_openfiles = gtk_tree_store_new(5, G_TYPE_STRING, G_TYPE_STRING,
 
274
                G_TYPE_POINTER, GDK_TYPE_COLOR, G_TYPE_STRING);
 
275
        gtk_tree_view_set_model(GTK_TREE_VIEW(tv.tree_openfiles), GTK_TREE_MODEL(store_openfiles));
 
276
 
 
277
        /* set policy settings for the scolledwindow around the treeview again, because glade
 
278
         * doesn't keep the settings */
 
279
        gtk_scrolled_window_set_policy(
 
280
                GTK_SCROLLED_WINDOW(ui_lookup_widget(main_widgets.window, "scrolledwindow7")),
 
281
                GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
 
282
 
 
283
        icon_renderer = gtk_cell_renderer_pixbuf_new();
 
284
        text_renderer = gtk_cell_renderer_text_new();
 
285
        g_object_set(text_renderer, "ellipsize", PANGO_ELLIPSIZE_MIDDLE, NULL);
 
286
        column = gtk_tree_view_column_new();
 
287
        gtk_tree_view_column_pack_start(column, icon_renderer, FALSE);
 
288
        gtk_tree_view_column_set_attributes(column, icon_renderer, "stock-id", DOCUMENTS_ICON, NULL);
 
289
        gtk_tree_view_column_pack_start(column, text_renderer, TRUE);
 
290
        gtk_tree_view_column_set_attributes(column, text_renderer, "text", DOCUMENTS_SHORTNAME,
 
291
                "foreground-gdk", DOCUMENTS_COLOR, NULL);
 
292
        gtk_tree_view_append_column(GTK_TREE_VIEW(tv.tree_openfiles), column);
 
293
        gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(tv.tree_openfiles), FALSE);
 
294
 
 
295
        gtk_tree_view_set_search_column(GTK_TREE_VIEW(tv.tree_openfiles),
 
296
                DOCUMENTS_SHORTNAME);
 
297
 
 
298
        /* sort opened filenames in the store_openfiles treeview */
 
299
        sortable = GTK_TREE_SORTABLE(GTK_TREE_MODEL(store_openfiles));
 
300
        gtk_tree_sortable_set_sort_func(sortable, DOCUMENTS_SHORTNAME, documents_sort_func, NULL, NULL);
 
301
        gtk_tree_sortable_set_sort_column_id(sortable, DOCUMENTS_SHORTNAME, GTK_SORT_ASCENDING);
 
302
 
 
303
        ui_widget_modify_font_from_string(tv.tree_openfiles, interface_prefs.tagbar_font);
 
304
 
 
305
        /* GTK 2.12 tooltips */
 
306
        if (gtk_check_version(2, 12, 0) == NULL)
 
307
                g_object_set(tv.tree_openfiles, "has-tooltip", TRUE, "tooltip-column", DOCUMENTS_FILENAME, NULL);
 
308
 
 
309
        /* selection handling */
 
310
        selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(tv.tree_openfiles));
 
311
        gtk_tree_selection_set_mode(selection, GTK_SELECTION_SINGLE);
 
312
        g_object_unref(store_openfiles);
 
313
 
 
314
        g_signal_connect(GTK_TREE_VIEW(tv.tree_openfiles), "button-press-event",
 
315
                G_CALLBACK(sidebar_button_press_cb), NULL);
 
316
        g_signal_connect(GTK_TREE_VIEW(tv.tree_openfiles), "key-press-event",
 
317
                G_CALLBACK(sidebar_key_press_cb), NULL);
 
318
}
 
319
 
 
320
 
 
321
/* iter should be toplevel */
 
322
static gboolean find_tree_iter_dir(GtkTreeIter *iter, const gchar *dir)
 
323
{
 
324
        GeanyDocument *doc;
 
325
        gchar *name;
 
326
        gboolean result;
 
327
 
 
328
        if (utils_str_equal(dir, "."))
 
329
                dir = GEANY_STRING_UNTITLED;
 
330
 
 
331
        gtk_tree_model_get(GTK_TREE_MODEL(store_openfiles), iter, DOCUMENTS_DOCUMENT, &doc, -1);
 
332
        g_return_val_if_fail(!doc, FALSE);
 
333
 
 
334
        gtk_tree_model_get(GTK_TREE_MODEL(store_openfiles), iter, DOCUMENTS_SHORTNAME, &name, -1);
 
335
 
 
336
        result = utils_str_equal(name, dir);
 
337
        g_free(name);
 
338
 
 
339
        return result;
 
340
}
 
341
 
 
342
 
 
343
static GtkTreeIter *get_doc_parent(GeanyDocument *doc)
 
344
{
 
345
        gchar *tmp_dirname;
 
346
        gchar *project_base_path;
 
347
        gchar *dirname = NULL;
 
348
        static GtkTreeIter parent;
 
349
        GtkTreeModel *model = GTK_TREE_MODEL(store_openfiles);
 
350
 
 
351
        if (!documents_show_paths)
 
352
                return NULL;
 
353
 
 
354
        tmp_dirname = g_path_get_dirname(DOC_FILENAME(doc));
 
355
        /* replace the project base path with the project name */
 
356
        project_base_path = project_get_base_path();
 
357
        if (project_base_path != NULL)
 
358
        {
 
359
                gsize len = strlen(project_base_path);
 
360
                const gchar *rest;
 
361
 
 
362
                if (project_base_path[len-1] == G_DIR_SEPARATOR)
 
363
                        project_base_path[len-1] = '\0';
 
364
 
 
365
                /* check whether the dir name matches or uses the project base path */
 
366
                if (g_str_has_prefix(tmp_dirname, project_base_path))
 
367
                {
 
368
                        rest = tmp_dirname + len;
 
369
                        if (*rest == G_DIR_SEPARATOR || *rest == '\0')
 
370
                                dirname = g_strdup_printf("%s%s", app->project->name, rest);
 
371
                }
 
372
                g_free(project_base_path);
 
373
        }
 
374
        if (dirname == NULL)
 
375
                dirname = tmp_dirname;
 
376
        else
 
377
                g_free(tmp_dirname);
 
378
 
 
379
        if (gtk_tree_model_get_iter_first(model, &parent))
 
380
        {
 
381
                do
 
382
                {
 
383
                        if (find_tree_iter_dir(&parent, dirname))
 
384
                        {
 
385
                                g_free(dirname);
 
386
                                return &parent;
 
387
                        }
 
388
                }
 
389
                while (gtk_tree_model_iter_next(model, &parent));
 
390
        }
 
391
        /* no match, add dir parent */
 
392
        gtk_tree_store_append(store_openfiles, &parent, NULL);
 
393
        gtk_tree_store_set(store_openfiles, &parent, DOCUMENTS_ICON, GTK_STOCK_DIRECTORY,
 
394
                DOCUMENTS_SHORTNAME, doc->file_name ? dirname : GEANY_STRING_UNTITLED, -1);
 
395
 
 
396
        g_free(dirname);
 
397
        return &parent;
 
398
}
 
399
 
 
400
 
 
401
/* Also sets doc->priv->iter.
 
402
 * This is called recursively in sidebar_openfiles_update_all(). */
 
403
void sidebar_openfiles_add(GeanyDocument *doc)
 
404
{
 
405
        GtkTreeIter *iter = &doc->priv->iter;
 
406
        GtkTreeIter *parent = get_doc_parent(doc);
 
407
        gchar *basename;
 
408
        const GdkColor *color = document_get_status_color(doc);
 
409
 
 
410
        gtk_tree_store_append(store_openfiles, iter, parent);
 
411
 
 
412
        /* check if new parent */
 
413
        if (parent && gtk_tree_model_iter_n_children(GTK_TREE_MODEL(store_openfiles), parent) == 1)
 
414
        {
 
415
                GtkTreePath *path;
 
416
 
 
417
                /* expand parent */
 
418
                path = gtk_tree_model_get_path(GTK_TREE_MODEL(store_openfiles), parent);
 
419
                gtk_tree_view_expand_row(GTK_TREE_VIEW(tv.tree_openfiles), path, TRUE);
 
420
                gtk_tree_path_free(path);
 
421
        }
 
422
        basename = g_path_get_basename(DOC_FILENAME(doc));
 
423
        gtk_tree_store_set(store_openfiles, iter, DOCUMENTS_ICON, GTK_STOCK_FILE,
 
424
                DOCUMENTS_SHORTNAME, basename, DOCUMENTS_DOCUMENT, doc, DOCUMENTS_COLOR, color,
 
425
                DOCUMENTS_FILENAME, DOC_FILENAME(doc), -1);
 
426
        g_free(basename);
 
427
}
 
428
 
 
429
 
 
430
static void openfiles_remove(GeanyDocument *doc)
 
431
{
 
432
        GtkTreeIter *iter = &doc->priv->iter;
 
433
        GtkTreeIter parent;
 
434
 
 
435
        if (gtk_tree_model_iter_parent(GTK_TREE_MODEL(store_openfiles), &parent, iter) &&
 
436
                gtk_tree_model_iter_n_children(GTK_TREE_MODEL(store_openfiles), &parent) == 1)
 
437
                gtk_tree_store_remove(store_openfiles, &parent);
 
438
        else
 
439
                gtk_tree_store_remove(store_openfiles, iter);
 
440
}
 
441
 
 
442
 
 
443
void sidebar_openfiles_update(GeanyDocument *doc)
 
444
{
 
445
        GtkTreeIter *iter = &doc->priv->iter;
 
446
        gchar *fname;
 
447
 
 
448
        gtk_tree_model_get(GTK_TREE_MODEL(store_openfiles), iter, DOCUMENTS_FILENAME, &fname, -1);
 
449
 
 
450
        if (utils_str_equal(fname, DOC_FILENAME(doc)))
 
451
        {
 
452
                /* just update color */
 
453
                const GdkColor *color = document_get_status_color(doc);
 
454
 
 
455
                gtk_tree_store_set(store_openfiles, iter, DOCUMENTS_COLOR, color, -1);
 
456
        }
 
457
        else
 
458
        {
 
459
                /* path has changed, so remove and re-add */
 
460
                GtkTreeSelection *treesel;
 
461
                gboolean sel;
 
462
 
 
463
                treesel = gtk_tree_view_get_selection(GTK_TREE_VIEW(tv.tree_openfiles));
 
464
                sel = gtk_tree_selection_iter_is_selected(treesel, &doc->priv->iter);
 
465
                openfiles_remove(doc);
 
466
 
 
467
                sidebar_openfiles_add(doc);
 
468
                if (sel)
 
469
                        gtk_tree_selection_select_iter(treesel, &doc->priv->iter);
 
470
        }
 
471
        g_free(fname);
 
472
}
 
473
 
 
474
 
 
475
void sidebar_openfiles_update_all()
 
476
{
 
477
        guint i, page_count;
 
478
        GeanyDocument *doc;
 
479
 
 
480
        gtk_tree_store_clear(store_openfiles);
 
481
        page_count = gtk_notebook_get_n_pages(GTK_NOTEBOOK(main_widgets.notebook));
 
482
        for (i = 0; i < page_count; i++)
 
483
        {
 
484
                doc = document_get_from_page(i);
 
485
                if (G_UNLIKELY(doc == NULL))
 
486
                        continue;
 
487
 
 
488
                sidebar_openfiles_add(doc);
 
489
        }
 
490
}
 
491
 
 
492
 
 
493
void sidebar_remove_document(GeanyDocument *doc)
 
494
{
 
495
        openfiles_remove(doc);
 
496
 
 
497
        if (GTK_IS_WIDGET(doc->priv->tag_tree))
 
498
        {
 
499
                gtk_widget_destroy(doc->priv->tag_tree);
 
500
                if (GTK_IS_TREE_VIEW(doc->priv->tag_tree))
 
501
                {
 
502
                        /* Because it was ref'd in sidebar_update_tag_list, it needs unref'ing */
 
503
                        g_object_unref((gpointer)doc->priv->tag_tree);
 
504
                }
 
505
                doc->priv->tag_tree = NULL;
 
506
        }
 
507
}
 
508
 
 
509
 
 
510
static void on_hide_sidebar(void)
 
511
{
 
512
        ui_prefs.sidebar_visible = FALSE;
 
513
        ui_sidebar_show_hide();
 
514
}
 
515
 
 
516
 
 
517
static gboolean on_sidebar_display_symbol_list_show(GtkWidget *item)
 
518
{
 
519
        gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item),
 
520
                interface_prefs.sidebar_symbol_visible);
 
521
        return FALSE;
 
522
}
 
523
 
 
524
 
 
525
static gboolean on_sidebar_display_open_files_show(GtkWidget *item)
 
526
{
 
527
        gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item),
 
528
                interface_prefs.sidebar_openfiles_visible);
 
529
        return FALSE;
 
530
}
 
531
 
 
532
 
 
533
void sidebar_add_common_menu_items(GtkMenu *menu)
 
534
{
 
535
        GtkWidget *item;
 
536
 
 
537
        item = gtk_separator_menu_item_new();
 
538
        gtk_widget_show(item);
 
539
        gtk_container_add(GTK_CONTAINER(menu), item);
 
540
 
 
541
        item = gtk_check_menu_item_new_with_mnemonic(_("Show S_ymbol List"));
 
542
        gtk_container_add(GTK_CONTAINER(menu), item);
 
543
        g_signal_connect(item, "expose-event",
 
544
                        G_CALLBACK(on_sidebar_display_symbol_list_show), NULL);
 
545
        gtk_widget_show(item);
 
546
        g_signal_connect(item, "activate",
 
547
                        G_CALLBACK(on_list_symbol_activate), NULL);
 
548
 
 
549
        item = gtk_check_menu_item_new_with_mnemonic(_("Show _Document List"));
 
550
        gtk_container_add(GTK_CONTAINER(menu), item);
 
551
        g_signal_connect(item, "expose-event",
 
552
                        G_CALLBACK(on_sidebar_display_open_files_show), NULL);
 
553
        gtk_widget_show(item);
 
554
        g_signal_connect(item, "activate",
 
555
                        G_CALLBACK(on_list_document_activate), NULL);
 
556
 
 
557
        item = gtk_image_menu_item_new_with_mnemonic(_("H_ide Sidebar"));
 
558
        gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item),
 
559
                gtk_image_new_from_stock("gtk-close", GTK_ICON_SIZE_MENU));
 
560
        gtk_widget_show(item);
 
561
        gtk_container_add(GTK_CONTAINER(menu), item);
 
562
        g_signal_connect(item, "activate", G_CALLBACK(on_hide_sidebar), NULL);
 
563
}
 
564
 
 
565
 
 
566
static void on_openfiles_show_paths_activate(GtkCheckMenuItem *item, gpointer user_data)
 
567
{
 
568
        documents_show_paths = gtk_check_menu_item_get_active(item);
 
569
        sidebar_openfiles_update_all();
 
570
}
 
571
 
 
572
 
 
573
static void on_list_document_activate(GtkCheckMenuItem *item, gpointer user_data)
 
574
{
 
575
        interface_prefs.sidebar_openfiles_visible = gtk_check_menu_item_get_active(item);
 
576
        ui_sidebar_show_hide();
 
577
        sidebar_tabs_show_hide(GTK_NOTEBOOK(main_widgets.sidebar_notebook), NULL, 0, NULL);
 
578
}
 
579
 
 
580
 
 
581
static void on_list_symbol_activate(GtkCheckMenuItem *item, gpointer user_data)
 
582
{
 
583
        interface_prefs.sidebar_symbol_visible = gtk_check_menu_item_get_active(item);
 
584
        ui_sidebar_show_hide();
 
585
        sidebar_tabs_show_hide(GTK_NOTEBOOK(main_widgets.sidebar_notebook), NULL, 0, NULL);
 
586
}
 
587
 
 
588
 
 
589
static void create_openfiles_popup_menu(void)
 
590
{
 
591
        GtkWidget *item;
 
592
 
 
593
        openfiles_popup_menu = gtk_menu_new();
 
594
 
 
595
        item = gtk_image_menu_item_new_from_stock("gtk-close", NULL);
 
596
        gtk_widget_show(item);
 
597
        gtk_container_add(GTK_CONTAINER(openfiles_popup_menu), item);
 
598
        g_signal_connect(item, "activate",
 
599
                        G_CALLBACK(on_openfiles_document_action), GINT_TO_POINTER(OPENFILES_ACTION_REMOVE));
 
600
        doc_items.close = item;
 
601
 
 
602
        item = gtk_separator_menu_item_new();
 
603
        gtk_widget_show(item);
 
604
        gtk_container_add(GTK_CONTAINER(openfiles_popup_menu), item);
 
605
 
 
606
        item = gtk_image_menu_item_new_from_stock("gtk-save", NULL);
 
607
        gtk_widget_show(item);
 
608
        gtk_container_add(GTK_CONTAINER(openfiles_popup_menu), item);
 
609
        g_signal_connect(item, "activate",
 
610
                        G_CALLBACK(on_openfiles_document_action), GINT_TO_POINTER(OPENFILES_ACTION_SAVE));
 
611
        doc_items.save = item;
 
612
 
 
613
        item = gtk_image_menu_item_new_with_mnemonic(_("_Reload"));
 
614
        gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item),
 
615
                gtk_image_new_from_stock("gtk-revert-to-saved", GTK_ICON_SIZE_MENU));
 
616
        gtk_widget_show(item);
 
617
        gtk_container_add(GTK_CONTAINER(openfiles_popup_menu), item);
 
618
        g_signal_connect(item, "activate",
 
619
                        G_CALLBACK(on_openfiles_document_action), GINT_TO_POINTER(OPENFILES_ACTION_RELOAD));
 
620
        doc_items.reload = item;
 
621
 
 
622
        item = gtk_separator_menu_item_new();
 
623
        gtk_widget_show(item);
 
624
        gtk_container_add(GTK_CONTAINER(openfiles_popup_menu), item);
 
625
 
 
626
        doc_items.show_paths = gtk_check_menu_item_new_with_mnemonic(_("Show _Paths"));
 
627
        gtk_widget_show(doc_items.show_paths);
 
628
        gtk_container_add(GTK_CONTAINER(openfiles_popup_menu), doc_items.show_paths);
 
629
        g_signal_connect(doc_items.show_paths, "activate",
 
630
                        G_CALLBACK(on_openfiles_show_paths_activate), NULL);
 
631
 
 
632
        sidebar_add_common_menu_items(GTK_MENU(openfiles_popup_menu));
 
633
}
 
634
 
 
635
 
 
636
static void unfold_parent(GtkTreeIter *iter)
 
637
{
 
638
        GtkTreeIter parent;
 
639
        GtkTreePath *path;
 
640
 
 
641
        if (gtk_tree_model_iter_parent(GTK_TREE_MODEL(store_openfiles), &parent, iter))
 
642
        {
 
643
                path = gtk_tree_model_get_path(GTK_TREE_MODEL(store_openfiles), &parent);
 
644
                gtk_tree_view_expand_row(GTK_TREE_VIEW(tv.tree_openfiles), path, TRUE);
 
645
                gtk_tree_path_free(path);
 
646
        }
 
647
}
 
648
 
 
649
 
 
650
/* compares the given data with the doc pointer from the selected row of openfiles
 
651
 * treeview, in case of a match the row is selected and TRUE is returned
 
652
 * (called indirectly from gtk_tree_model_foreach()) */
 
653
static gboolean tree_model_find_node(GtkTreeModel *model, GtkTreePath *path,
 
654
                GtkTreeIter *iter, gpointer data)
 
655
{
 
656
        GeanyDocument *doc;
 
657
 
 
658
        gtk_tree_model_get(GTK_TREE_MODEL(store_openfiles), iter, DOCUMENTS_DOCUMENT, &doc, -1);
 
659
 
 
660
        if (doc == data)
 
661
        {
 
662
                /* unfolding also prevents a strange bug where the selection gets stuck on the parent
 
663
                 * when it is collapsed and then switching documents */
 
664
                unfold_parent(iter);
 
665
                gtk_tree_view_set_cursor(GTK_TREE_VIEW(tv.tree_openfiles), path, NULL, FALSE);
 
666
                return TRUE;
 
667
        }
 
668
        else return FALSE;
 
669
}
 
670
 
 
671
 
 
672
void sidebar_select_openfiles_item(GeanyDocument *doc)
 
673
{
 
674
        gtk_tree_model_foreach(GTK_TREE_MODEL(store_openfiles), tree_model_find_node, doc);
 
675
}
 
676
 
 
677
 
 
678
/* callbacks */
 
679
 
 
680
static void document_action(GeanyDocument *doc, gint action)
 
681
{
 
682
        if (! DOC_VALID(doc))
 
683
                return;
 
684
 
 
685
        switch (action)
 
686
        {
 
687
                case OPENFILES_ACTION_REMOVE:
 
688
                {
 
689
                        document_close(doc);
 
690
                        break;
 
691
                }
 
692
                case OPENFILES_ACTION_SAVE:
 
693
                {
 
694
                        document_save_file(doc, FALSE);
 
695
                        break;
 
696
                }
 
697
                case OPENFILES_ACTION_RELOAD:
 
698
                {
 
699
                        on_toolbutton_reload_clicked(NULL, NULL);
 
700
                        break;
 
701
                }
 
702
        }
 
703
}
 
704
 
 
705
 
 
706
static void on_openfiles_document_action(GtkMenuItem *menuitem, gpointer user_data)
 
707
{
 
708
        GtkTreeIter iter;
 
709
        GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(tv.tree_openfiles));
 
710
        GtkTreeModel *model;
 
711
        GeanyDocument *doc;
 
712
        gint action = GPOINTER_TO_INT(user_data);
 
713
 
 
714
        if (gtk_tree_selection_get_selected(selection, &model, &iter))
 
715
        {
 
716
                gtk_tree_model_get(model, &iter, DOCUMENTS_DOCUMENT, &doc, -1);
 
717
                if (doc)
 
718
                {
 
719
                        document_action(doc, action);
 
720
                }
 
721
                else
 
722
                {
 
723
                        /* parent item selected */
 
724
                        GtkTreeIter child;
 
725
                        gint i = gtk_tree_model_iter_n_children(model, &iter) - 1;
 
726
 
 
727
                        while (i >= 0 && gtk_tree_model_iter_nth_child(model, &child, &iter, i))
 
728
                        {
 
729
                                gtk_tree_model_get(model, &child, DOCUMENTS_DOCUMENT, &doc, -1);
 
730
 
 
731
                                document_action(doc, action);
 
732
                                i--;
 
733
                        }
 
734
                }
 
735
        }
 
736
}
 
737
 
 
738
 
 
739
static void change_focus_to_editor(GeanyDocument *doc, GtkWidget *source_widget)
 
740
{
 
741
        if (may_steal_focus)
 
742
                document_try_focus(doc, source_widget);
 
743
        may_steal_focus = FALSE;
 
744
}
 
745
 
 
746
 
 
747
static gboolean on_openfiles_tree_selection_changed(gpointer data)
 
748
{
 
749
        GtkTreeIter iter;
 
750
        GtkTreeModel *model;
 
751
        GeanyDocument *doc = NULL;
 
752
 
 
753
        /* use switch_notebook_page to ignore changing the notebook page because it is already done */
 
754
        if (gtk_tree_selection_get_selected(selection_change.selection, &model, &iter) && ! ignore_callback)
 
755
        {
 
756
                gtk_tree_model_get(model, &iter, DOCUMENTS_DOCUMENT, &doc, -1);
 
757
                if (! doc)
 
758
                        return FALSE;   /* parent */
 
759
 
 
760
                /* switch to the doc and grab the focus */
 
761
                gtk_notebook_set_current_page(GTK_NOTEBOOK(main_widgets.notebook),
 
762
                        gtk_notebook_page_num(GTK_NOTEBOOK(main_widgets.notebook),
 
763
                        (GtkWidget*) doc->editor->sci));
 
764
                if (selection_change.keyval != GDK_space)
 
765
                        change_focus_to_editor(doc, tv.tree_openfiles);
 
766
        }
 
767
        return FALSE;
 
768
}
 
769
 
 
770
 
 
771
static gboolean on_taglist_tree_selection_changed(gpointer data)
 
772
{
 
773
        GtkTreeIter iter;
 
774
        GtkTreeModel *model;
 
775
        gint line = 0;
 
776
 
 
777
        if (gtk_tree_selection_get_selected(selection_change.selection, &model, &iter))
 
778
        {
 
779
                const TMTag *tag;
 
780
 
 
781
                gtk_tree_model_get(model, &iter, SYMBOLS_COLUMN_TAG, &tag, -1);
 
782
                if (! tag)
 
783
                        return FALSE;
 
784
 
 
785
                line = tag->atts.entry.line;
 
786
                if (line > 0)
 
787
                {
 
788
                        GeanyDocument *doc = document_get_current();
 
789
 
 
790
                        if (doc != NULL)
 
791
                        {
 
792
                                navqueue_goto_line(doc, doc, line);
 
793
                                if (selection_change.keyval != GDK_space)
 
794
                                        change_focus_to_editor(doc, NULL);
 
795
                        }
 
796
                }
 
797
        }
 
798
        return FALSE;
 
799
}
 
800
 
 
801
 
 
802
static void update_selection_change(GtkTreeSelection *selection, guint keyval)
 
803
{
 
804
        selection_change.selection = selection;
 
805
        selection_change.keyval = keyval;
 
806
}
 
807
 
 
808
 
 
809
static gboolean sidebar_key_press_cb(GtkWidget *widget, GdkEventKey *event,
 
810
                                                                                         gpointer user_data)
 
811
{
 
812
        may_steal_focus = FALSE;
 
813
        if (ui_is_keyval_enter_or_return(event->keyval) || event->keyval == GDK_space)
 
814
        {
 
815
                GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(widget));
 
816
                may_steal_focus = TRUE;
 
817
                /* delay the query of selection state because this callback is executed before GTK
 
818
                 * changes the selection (g_signal_connect_after would be better but it doesn't work) */
 
819
                update_selection_change(selection, event->keyval);
 
820
 
 
821
                if (widget ==  tv.tree_openfiles) /* tag and doc list have separate handlers */
 
822
                        g_idle_add(on_openfiles_tree_selection_changed, NULL);
 
823
                else
 
824
                        g_idle_add(on_taglist_tree_selection_changed, NULL);
 
825
        }
 
826
        return FALSE;
 
827
}
 
828
 
 
829
 
 
830
static gboolean sidebar_button_press_cb(GtkWidget *widget, GdkEventButton *event,
 
831
                G_GNUC_UNUSED gpointer user_data)
 
832
{
 
833
        GtkTreeSelection *selection;
 
834
 
 
835
        selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(widget));
 
836
        may_steal_focus = TRUE;
 
837
 
 
838
        if (event->type == GDK_2BUTTON_PRESS)
 
839
        {       /* double click on parent node(section) expands/collapses it */
 
840
                GtkTreeModel *model;
 
841
                GtkTreeIter iter;
 
842
 
 
843
                if (gtk_tree_selection_get_selected(selection, &model, &iter))
 
844
                {
 
845
                        if (gtk_tree_model_iter_has_child(model, &iter))
 
846
                        {
 
847
                                GtkTreePath *path = gtk_tree_model_get_path(model, &iter);
 
848
 
 
849
                                if (gtk_tree_view_row_expanded(GTK_TREE_VIEW(widget), path))
 
850
                                        gtk_tree_view_collapse_row(GTK_TREE_VIEW(widget), path);
 
851
                                else
 
852
                                        gtk_tree_view_expand_row(GTK_TREE_VIEW(widget), path, FALSE);
 
853
 
 
854
                                gtk_tree_path_free(path);
 
855
                                return TRUE;
 
856
                        }
 
857
                }
 
858
        }
 
859
        else if (event->button == 1)
 
860
        {       /* allow reclicking of taglist treeview item */
 
861
                /* delay the query of selection state because this callback is executed before GTK
 
862
                 * changes the selection (g_signal_connect_after would be better but it doesn't work) */
 
863
                update_selection_change(selection, 0);
 
864
 
 
865
                if (widget == tv.tree_openfiles)
 
866
                        g_idle_add(on_openfiles_tree_selection_changed, NULL);
 
867
                else
 
868
                        g_idle_add(on_taglist_tree_selection_changed, NULL);
 
869
        }
 
870
        else if (event->button == 3)
 
871
        {
 
872
                if (widget == tv.tree_openfiles)
 
873
                {
 
874
                        if (!openfiles_popup_menu)
 
875
                                create_openfiles_popup_menu();
 
876
 
 
877
                        /* update menu item sensitivity */
 
878
                        documents_menu_update(selection);
 
879
                        gtk_menu_popup(GTK_MENU(openfiles_popup_menu), NULL, NULL, NULL, NULL,
 
880
                                        event->button, event->time);
 
881
                }
 
882
                else
 
883
                {
 
884
                        gtk_menu_popup(GTK_MENU(tv.popup_taglist), NULL, NULL, NULL, NULL,
 
885
                                        event->button, event->time);
 
886
                }
 
887
        }
 
888
        return FALSE;
 
889
}
 
890
 
 
891
 
 
892
static void documents_menu_update(GtkTreeSelection *selection)
 
893
{
 
894
        GtkTreeModel *model;
 
895
        GtkTreeIter iter;
 
896
        gboolean sel, path;
 
897
        gchar *shortname = NULL;
 
898
        GeanyDocument *doc = NULL;
 
899
 
 
900
        /* maybe no selection e.g. if ctrl-click deselected */
 
901
        sel = gtk_tree_selection_get_selected(selection, &model, &iter);
 
902
        if (sel)
 
903
        {
 
904
                gtk_tree_model_get(model, &iter, DOCUMENTS_DOCUMENT, &doc,
 
905
                        DOCUMENTS_SHORTNAME, &shortname, -1);
 
906
        }
 
907
        path = NZV(shortname) &&
 
908
                (g_path_is_absolute(shortname) ||
 
909
                (app->project && g_str_has_prefix(shortname, app->project->name)));
 
910
 
 
911
        /* can close all, save all (except shortname), but only reload individually ATM */
 
912
        gtk_widget_set_sensitive(doc_items.close, sel);
 
913
        gtk_widget_set_sensitive(doc_items.save, (doc && doc->real_path) || path);
 
914
        gtk_widget_set_sensitive(doc_items.reload, doc && doc->real_path);
 
915
        g_free(shortname);
 
916
 
 
917
        gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(doc_items.show_paths),
 
918
                documents_show_paths);
 
919
}
 
920
 
 
921
 
 
922
StashGroup *stash_group = NULL;
 
923
 
 
924
static void on_load_settings(void)
 
925
{
 
926
        tag_window = ui_lookup_widget(main_widgets.window, "scrolledwindow2");
 
927
 
 
928
        prepare_openfiles();
 
929
        /* note: ui_prefs.sidebar_page is reapplied after plugins are loaded */
 
930
        stash_group_display(stash_group, NULL);
 
931
        sidebar_tabs_show_hide(GTK_NOTEBOOK(main_widgets.sidebar_notebook), NULL, 0, NULL);
 
932
}
 
933
 
 
934
 
 
935
static void on_save_settings(void)
 
936
{
 
937
        stash_group_update(stash_group, NULL);
 
938
        sidebar_tabs_show_hide(GTK_NOTEBOOK(main_widgets.sidebar_notebook), NULL, 0, NULL);
 
939
}
 
940
 
 
941
 
 
942
void sidebar_init(void)
 
943
{
 
944
        StashGroup *group;
 
945
 
 
946
        group = stash_group_new(PACKAGE);
 
947
        stash_group_add_boolean(group, &documents_show_paths, "documents_show_paths", TRUE);
 
948
        stash_group_add_widget_property(group, &ui_prefs.sidebar_page, "sidebar_page", GINT_TO_POINTER(0),
 
949
                main_widgets.sidebar_notebook, "page", 0);
 
950
        configuration_add_pref_group(group, FALSE);
 
951
        stash_group = group;
 
952
 
 
953
        /* delay building documents treeview until sidebar font has been read */
 
954
        g_signal_connect(geany_object, "load-settings", on_load_settings, NULL);
 
955
        g_signal_connect(geany_object, "save-settings", on_save_settings, NULL);
 
956
 
 
957
 
 
958
        if (gtk_check_version(2, 10, 0) == NULL)
 
959
        {
 
960
                g_signal_connect(main_widgets.sidebar_notebook, "page-added",
 
961
                        G_CALLBACK(sidebar_tabs_show_hide), NULL);
 
962
 
 
963
                g_signal_connect(main_widgets.sidebar_notebook, "page-removed",
 
964
                        G_CALLBACK(sidebar_tabs_show_hide), NULL);
 
965
        }
 
966
        sidebar_tabs_show_hide(GTK_NOTEBOOK(main_widgets.sidebar_notebook), NULL, 0, NULL);
 
967
}
 
968
 
 
969
#define WIDGET(w) w && GTK_IS_WIDGET(w)
 
970
 
 
971
void sidebar_finalize(void)
 
972
{
 
973
        if (WIDGET(tv.default_tag_tree))
 
974
        {
 
975
                g_object_unref(tv.default_tag_tree);
 
976
                /* This is not exactly clean, default_tag_tree's ref_count is 2 when it is shown,
 
977
                 * 1 oherwise. We should probably handle the ref_count more accurate. */
 
978
                if (WIDGET(tv.default_tag_tree))
 
979
                        gtk_widget_destroy(tv.default_tag_tree);
 
980
        }
 
981
        if (WIDGET(tv.popup_taglist))
 
982
                gtk_widget_destroy(tv.popup_taglist);
 
983
        if (WIDGET(openfiles_popup_menu))
 
984
                gtk_widget_destroy(openfiles_popup_menu);
 
985
}
 
986
 
 
987
 
 
988
void sidebar_focus_openfiles_tab(void)
 
989
{
 
990
        if (ui_prefs.sidebar_visible && interface_prefs.sidebar_openfiles_visible)
 
991
        {
 
992
                GtkNotebook *notebook = GTK_NOTEBOOK(main_widgets.sidebar_notebook);
 
993
 
 
994
                gtk_notebook_set_current_page(notebook, TREEVIEW_OPENFILES);
 
995
                gtk_widget_grab_focus(tv.tree_openfiles);
 
996
        }
 
997
}
 
998
 
 
999
 
 
1000
void sidebar_focus_symbols_tab(void)
 
1001
{
 
1002
        if (ui_prefs.sidebar_visible && interface_prefs.sidebar_symbol_visible)
 
1003
        {
 
1004
                GtkNotebook *notebook = GTK_NOTEBOOK(main_widgets.sidebar_notebook);
 
1005
                GtkWidget *symbol_list_scrollwin = gtk_notebook_get_nth_page(notebook, TREEVIEW_SYMBOL);
 
1006
 
 
1007
                gtk_notebook_set_current_page(notebook, TREEVIEW_SYMBOL);
 
1008
                gtk_widget_grab_focus(gtk_bin_get_child(GTK_BIN(symbol_list_scrollwin)));
 
1009
        }
 
1010
}
 
1011
 
 
1012
 
 
1013
static void sidebar_tabs_show_hide(GtkNotebook *notebook, GtkWidget *child,
 
1014
                                                                   guint page_num, gpointer data)
 
1015
{
 
1016
        if (gtk_check_version(2, 10, 0) == NULL)
 
1017
        {
 
1018
                gint tabs = gtk_notebook_get_n_pages(notebook);
 
1019
 
 
1020
                if (interface_prefs.sidebar_symbol_visible == FALSE)
 
1021
                        tabs--;
 
1022
                if (interface_prefs.sidebar_openfiles_visible == FALSE)
 
1023
                        tabs--;
 
1024
 
 
1025
                gtk_notebook_set_show_tabs(notebook, (tabs > 1));
 
1026
        }
 
1027
}