SF.net SVN: geany:[4252] trunk

ntrel at users.sourceforge.net ntrel at xxxxx
Mon Sep 28 11:16:59 UTC 2009


Revision: 4252
          http://geany.svn.sourceforge.net/geany/?rev=4252&view=rev
Author:   ntrel
Date:     2009-09-28 11:16:59 +0000 (Mon, 28 Sep 2009)

Log Message:
-----------
Rename treeviews.[hc] -> sidebar.[hc].

Modified Paths:
--------------
    trunk/ChangeLog
    trunk/po/POTFILES.in
    trunk/src/Makefile.am
    trunk/src/callbacks.c
    trunk/src/document.c
    trunk/src/keybindings.c
    trunk/src/main.c
    trunk/src/makefile.win32
    trunk/src/notebook.c
    trunk/src/prefs.c
    trunk/src/project.c
    trunk/src/symbols.c
    trunk/src/ui_utils.c
    trunk/wscript

Added Paths:
-----------
    trunk/src/sidebar.c
    trunk/src/sidebar.h

Removed Paths:
-------------
    trunk/src/treeviews.c
    trunk/src/treeviews.h

Modified: trunk/ChangeLog
===================================================================
--- trunk/ChangeLog	2009-09-27 20:31:16 UTC (rev 4251)
+++ trunk/ChangeLog	2009-09-28 11:16:59 UTC (rev 4252)
@@ -1,3 +1,13 @@
+2009-09-28  Nick Treleaven  <nick(dot)treleaven(at)btinternet(dot)com>
+
+ * src/keybindings.c, src/sidebar.c, src/sidebar.h,
+   src/makefile.win32, src/project.c, src/prefs.c, src/treeviews.c,
+   src/callbacks.c, src/notebook.c, src/treeviews.h, src/document.c,
+   src/main.c, src/symbols.c, src/Makefile.am, src/ui_utils.c,
+   po/POTFILES.in, wscript:
+   Rename treeviews.[hc] -> sidebar.[hc].
+
+
 2009-09-27  Enrico Tröger  <enrico(dot)troeger(at)uvena(dot)de>
 
  * scripts/create_py_tags.py:

Modified: trunk/po/POTFILES.in
===================================================================
--- trunk/po/POTFILES.in	2009-09-27 20:31:16 UTC (rev 4251)
+++ trunk/po/POTFILES.in	2009-09-28 11:16:59 UTC (rev 4252)
@@ -34,7 +34,7 @@
 src/templates.c
 src/toolbar.c
 src/tools.c
-src/treeviews.c
+src/sidebar.c
 src/ui_utils.c
 src/utils.c
 src/vte.c

Modified: trunk/src/Makefile.am
===================================================================
--- trunk/src/Makefile.am	2009-09-27 20:31:16 UTC (rev 4251)
+++ trunk/src/Makefile.am	2009-09-28 11:16:59 UTC (rev 4252)
@@ -45,7 +45,7 @@
 	templates.c templates.h \
 	toolbar.c toolbar.h \
 	tools.c tools.h \
-	treeviews.c treeviews.h \
+	sidebar.c sidebar.h \
 	ui_utils.c ui_utils.h \
 	utils.c utils.h
 

Modified: trunk/src/callbacks.c
===================================================================
--- trunk/src/callbacks.c	2009-09-27 20:31:16 UTC (rev 4251)
+++ trunk/src/callbacks.c	2009-09-28 11:16:59 UTC (rev 4252)
@@ -52,7 +52,7 @@
 #include "build.h"
 #include "prefs.h"
 #include "templates.h"
-#include "treeviews.h"
+#include "sidebar.h"
 #include "keybindings.h"
 #include "encodings.h"
 #include "search.h"
@@ -219,7 +219,7 @@
 		else
 			document_save_file(doc, FALSE);
 	}
-	treeviews_update_tag_list(cur_doc, TRUE);
+	sidebar_update_tag_list(cur_doc, TRUE);
 	ui_set_window_title(cur_doc);
 }
 
@@ -739,12 +739,12 @@
 
 	if (doc != NULL)
 	{
-		treeviews_select_openfiles_item(doc);
+		sidebar_select_openfiles_item(doc);
 		document_set_text_changed(doc, doc->changed);	/* also sets window title and status bar */
 		ui_update_popup_reundo_items(doc);
 		ui_document_show_hide(doc); /* update the document menu */
 		build_menu_update(doc);
-		treeviews_update_tag_list(doc, FALSE);
+		sidebar_update_tag_list(doc, FALSE);
 
 		/* We delay the check to avoid weird fast, unintended switching of notebook pages when
 		 * the 'file has changed' dialog is shown while the switch event is not yet completely

Modified: trunk/src/document.c
===================================================================
--- trunk/src/document.c	2009-09-27 20:31:16 UTC (rev 4251)
+++ trunk/src/document.c	2009-09-28 11:16:59 UTC (rev 4252)
@@ -66,7 +66,7 @@
 #include "dialogs.h"
 #include "msgwindow.h"
 #include "templates.h"
-#include "treeviews.h"
+#include "sidebar.h"
 #include "ui_utils.h"
 #include "utils.h"
 #include "encodings.h"
@@ -568,7 +568,7 @@
 
 	editor_apply_update_prefs(doc->editor);
 
-	treeviews_openfiles_add(doc);	/* sets doc->iter */
+	sidebar_openfiles_add(doc);	/* sets doc->iter */
 
 	notebook_new_tab(doc);
 
@@ -637,7 +637,7 @@
 	doc->is_valid = FALSE;
 
 	notebook_remove_page(page_num);
-	treeviews_remove_document(doc);
+	sidebar_remove_document(doc);
 	navqueue_remove_file(doc->file_name);
 	msgwin_status_add(_("File %s closed."), DOC_FILENAME(doc));
 	g_free(doc->encoding);
@@ -662,7 +662,7 @@
 
 	if (gtk_notebook_get_n_pages(GTK_NOTEBOOK(main_widgets.notebook)) == 0)
 	{
-		treeviews_update_tag_list(NULL, FALSE);
+		sidebar_update_tag_list(NULL, FALSE);
 		/*on_notebook1_switch_page(GTK_NOTEBOOK(main_widgets.notebook), NULL, 0, NULL);*/
 		ui_set_window_title(NULL);
 		ui_save_buttons_toggle(FALSE);
@@ -1177,7 +1177,7 @@
 		return TRUE;
 
 	if (update_tags_from_buffer(doc))
-		treeviews_update_tag_list(doc, TRUE);
+		sidebar_update_tag_list(doc, TRUE);
 
 	return TRUE;
 }
@@ -2307,7 +2307,7 @@
 
 void document_update_tag_list(GeanyDocument *doc, gboolean update)
 {
-	/* We must call treeviews_update_tag_list() before returning,
+	/* We must call sidebar_update_tag_list() before returning,
 	 * to ensure that the symbol list is always updated properly (e.g.
 	 * when creating a new document with a partial filename set. */
 	gboolean success = FALSE;
@@ -2317,7 +2317,7 @@
 		! filetype_has_tags(doc->file_type) || ! doc->file_name)
 	{
 		/* set the default (empty) tag list */
-		treeviews_update_tag_list(doc, FALSE);
+		sidebar_update_tag_list(doc, FALSE);
 		return;
 	}
 
@@ -2349,7 +2349,7 @@
 		if (G_UNLIKELY(! success))
 			geany_debug("tag list updating failed");
 	}
-	treeviews_update_tag_list(doc, success);
+	sidebar_update_tag_list(doc, success);
 }
 
 

Modified: trunk/src/keybindings.c
===================================================================
--- trunk/src/keybindings.c	2009-09-27 20:31:16 UTC (rev 4251)
+++ trunk/src/keybindings.c	2009-09-28 11:16:59 UTC (rev 4252)
@@ -49,7 +49,7 @@
 #include "symbols.h"
 #include "vte.h"
 #include "toolbar.h"
-#include "treeviews.h"
+#include "sidebar.h"
 #include "geanywraplabel.h"
 #include "main.h"
 #include "search.h"

Modified: trunk/src/main.c
===================================================================
--- trunk/src/main.c	2009-09-27 20:31:16 UTC (rev 4251)
+++ trunk/src/main.c	2009-09-28 11:16:59 UTC (rev 4252)
@@ -59,7 +59,7 @@
 #include "dialogs.h"
 #include "templates.h"
 #include "encodings.h"
-#include "treeviews.h"
+#include "sidebar.h"
 #include "notebook.h"
 #include "keybindings.h"
 #include "editor.h"
@@ -933,7 +933,7 @@
 #ifdef HAVE_PLUGINS
 	plugins_init();
 #endif
-	treeviews_init();
+	sidebar_init();
 	load_settings();	/* load keyfile */
 
 	msgwin_init();
@@ -1003,9 +1003,9 @@
 
 	doc = document_get_current();
 	gtk_widget_grab_focus(GTK_WIDGET(doc->editor->sci));
-	treeviews_select_openfiles_item(doc);
+	sidebar_select_openfiles_item(doc);
 	build_menu_update(doc);
-	treeviews_update_tag_list(doc, FALSE);
+	sidebar_update_tag_list(doc, FALSE);
 
 #ifdef G_OS_WIN32
 	/* Manually realise the main window to be able to set the position but don't show it.
@@ -1083,7 +1083,7 @@
 	editor_snippets_free();
 	encodings_finalize();
 	toolbar_finalize();
-	treeviews_finalize();
+	sidebar_finalize();
 	configuration_finalize();
 	filetypes_free_types();
 	log_finalize();

Modified: trunk/src/makefile.win32
===================================================================
--- trunk/src/makefile.win32	2009-09-27 20:31:16 UTC (rev 4251)
+++ trunk/src/makefile.win32	2009-09-28 11:16:59 UTC (rev 4252)
@@ -66,7 +66,7 @@
 		log.o main.o msgwindow.o navqueue.o notebook.o plugins.o pluginutils.o \
 		prefs.o printing.o project.o \
 		sciwrappers.o search.o socket.o stash.o \
-		symbols.o templates.o toolbar.o tools.o treeviews.o \
+		symbols.o templates.o toolbar.o tools.o sidebar.o \
 		ui_utils.o utils.o win32.o
 
 .c.o:

Modified: trunk/src/notebook.c
===================================================================
--- trunk/src/notebook.c	2009-09-27 20:31:16 UTC (rev 4251)
+++ trunk/src/notebook.c	2009-09-28 11:16:59 UTC (rev 4252)
@@ -31,7 +31,7 @@
 #include "editor.h"
 #include "documentprivate.h"
 #include "ui_utils.h"
-#include "treeviews.h"
+#include "sidebar.h"
 #include "support.h"
 #include "callbacks.h"
 #include "utils.h"
@@ -332,7 +332,7 @@
 {
 	/* Not necessary to update open files treeview if it's sorted.
 	 * Note: if enabled, it's best to move the item instead of recreating all items. */
-	/*treeviews_openfiles_update_all();*/
+	/*sidebar_openfiles_update_all();*/
 }
 
 

Modified: trunk/src/prefs.c
===================================================================
--- trunk/src/prefs.c	2009-09-27 20:31:16 UTC (rev 4251)
+++ trunk/src/prefs.c	2009-09-28 11:16:59 UTC (rev 4252)
@@ -48,7 +48,7 @@
 #include "project.h"
 #include "editor.h"
 #include "main.h"
-#include "treeviews.h"
+#include "sidebar.h"
 #include "printing.h"
 #include "geanywraplabel.h"
 #include "templates.h"
@@ -1105,7 +1105,7 @@
 
 		/* apply the changes made */
 		ui_statusbar_showhide(interface_prefs.statusbar_visible);
-		treeviews_openfiles_update_all(); /* to update if full path setting has changed */
+		sidebar_openfiles_update_all(); /* to update if full path setting has changed */
 		toolbar_apply_settings();
 		toolbar_update_ui();
 		toolbar_show_hide();

Modified: trunk/src/project.c
===================================================================
--- trunk/src/project.c	2009-09-27 20:31:16 UTC (rev 4251)
+++ trunk/src/project.c	2009-09-28 11:16:59 UTC (rev 4252)
@@ -48,7 +48,7 @@
 #include "interface.h"
 #include "editor.h"
 #include "stash.h"
-#include "treeviews.h"
+#include "sidebar.h"
 #include "filetypes.h"
 
 
@@ -318,7 +318,7 @@
 {
 	ui_set_window_title(NULL);
 	build_menu_update(NULL);
-	treeviews_openfiles_update_all();
+	sidebar_openfiles_update_all();
 }
 
 

Copied: trunk/src/sidebar.c (from rev 4247, trunk/src/treeviews.c)
===================================================================
--- trunk/src/sidebar.c	                        (rev 0)
+++ trunk/src/sidebar.c	2009-09-28 11:16:59 UTC (rev 4252)
@@ -0,0 +1,928 @@
+/*
+ *      sidebar.c - this file is part of Geany, a fast and lightweight IDE
+ *
+ *      Copyright 2005-2009 Enrico Tröger <enrico(dot)troeger(at)uvena(dot)de>
+ *      Copyright 2006-2009 Nick Treleaven <nick(dot)treleaven(at)btinternet(dot)com>
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      This program is distributed in the hope that it will be useful,
+ *      but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *      GNU General Public License for more details.
+ *
+ *      You should have received a copy of the GNU General Public License
+ *      along with this program; if not, write to the Free Software
+ *      Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $Id$
+ */
+
+/*
+ * Sidebar related code for the Symbol list and Open files GtkTreeViews.
+ */
+
+#include <string.h>
+
+#include "geany.h"
+#include "support.h"
+#include "callbacks.h"
+#include "sidebar.h"
+#include "document.h"
+#include "editor.h"
+#include "documentprivate.h"
+#include "filetypes.h"
+#include "utils.h"
+#include "ui_utils.h"
+#include "symbols.h"
+#include "navqueue.h"
+#include "project.h"
+#include "stash.h"
+#include "keyfile.h"
+#include "sciwrappers.h"
+
+#include <gdk/gdkkeysyms.h>
+
+SidebarTreeviews tv = {NULL, NULL, NULL};
+/* while typeahead searching, editor should not get focus */
+static gboolean may_steal_focus = FALSE;
+
+static struct
+{
+	GtkWidget *close;
+	GtkWidget *save;
+	GtkWidget *reload;
+	GtkWidget *show_paths;
+}
+doc_items = {NULL, NULL, NULL, NULL};
+
+enum
+{
+	TREEVIEW_SYMBOL = 0,
+	TREEVIEW_OPENFILES
+};
+
+enum
+{
+	OPENFILES_ACTION_REMOVE = 0,
+	OPENFILES_ACTION_SAVE,
+	OPENFILES_ACTION_RELOAD
+};
+
+/* documents tree model columns */
+enum
+{
+	DOCUMENTS_ICON,
+	DOCUMENTS_SHORTNAME,	/* dirname for parents, basename for children */
+	DOCUMENTS_DOCUMENT,
+	DOCUMENTS_COLOR,
+	DOCUMENTS_FILENAME		/* full filename */
+};
+
+static GtkTreeStore	*store_openfiles;
+static GtkWidget *openfiles_popup_menu;
+static gboolean documents_show_paths;
+static GtkWidget *tag_window;	/* scrolled window that holds the symbol list GtkTreeView */
+
+/* callback prototypes */
+static gboolean on_openfiles_tree_selection_changed(GtkTreeSelection *selection);
+static void on_openfiles_document_action(GtkMenuItem *menuitem, gpointer user_data);
+static gboolean on_taglist_tree_selection_changed(GtkTreeSelection *selection);
+static gboolean sidebar_button_press_cb(GtkWidget *widget, GdkEventButton *event,
+		gpointer user_data);
+static gboolean sidebar_key_press_cb(GtkWidget *widget, GdkEventKey *event,
+		gpointer user_data);
+static void on_list_document_activate(GtkCheckMenuItem *item, gpointer user_data);
+static void on_list_symbol_activate(GtkCheckMenuItem *item, gpointer user_data);
+static void documents_menu_update(GtkTreeSelection *selection);
+
+
+/* the prepare_* functions are document-related, but I think they fit better here than in document.c */
+static void prepare_taglist(GtkWidget *tree, GtkTreeStore *store)
+{
+	GtkCellRenderer *text_renderer, *icon_renderer;
+	GtkTreeViewColumn *column;
+	GtkTreeSelection *select;
+
+	text_renderer = gtk_cell_renderer_text_new();
+	icon_renderer = gtk_cell_renderer_pixbuf_new();
+	column = gtk_tree_view_column_new();
+
+	gtk_tree_view_column_pack_start(column, icon_renderer, FALSE);
+  	gtk_tree_view_column_set_attributes(column, icon_renderer, "pixbuf", SYMBOLS_COLUMN_ICON, NULL);
+  	g_object_set(icon_renderer, "xalign", 0.0, NULL);
+
+  	gtk_tree_view_column_pack_start(column, text_renderer, TRUE);
+  	gtk_tree_view_column_set_attributes(column, text_renderer, "text", SYMBOLS_COLUMN_NAME, NULL);
+  	g_object_set(text_renderer, "yalign", 0.5, NULL);
+  	gtk_tree_view_column_set_title(column, _("Symbols"));
+
+	gtk_tree_view_append_column(GTK_TREE_VIEW(tree), column);
+	gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(tree), FALSE);
+
+	ui_widget_modify_font_from_string(tree, interface_prefs.tagbar_font);
+
+	gtk_tree_view_set_model(GTK_TREE_VIEW(tree), GTK_TREE_MODEL(store));
+	g_object_unref(store);
+
+	g_signal_connect(tree, "button-press-event",
+		G_CALLBACK(sidebar_button_press_cb), NULL);
+	g_signal_connect(tree, "key-press-event",
+		G_CALLBACK(sidebar_key_press_cb), NULL);
+
+	if (gtk_check_version(2, 12, 0) == NULL)
+	{
+		g_object_set(tree, "show-expanders", interface_prefs.show_symbol_list_expanders, NULL);
+		if (! interface_prefs.show_symbol_list_expanders)
+			g_object_set(tree, "level-indentation", 10, NULL);
+		/* Tooltips */
+		g_object_set(tree,
+			"has-tooltip", TRUE,
+			"tooltip-column", SYMBOLS_COLUMN_TOOLTIP, NULL);
+	}
+
+	/* selection handling */
+	select = gtk_tree_view_get_selection(GTK_TREE_VIEW(tree));
+	gtk_tree_selection_set_mode(select, GTK_SELECTION_SINGLE);
+	/* callback for changed selection not necessary, will be handled by button-press-event */
+}
+
+
+static gboolean
+on_default_tag_tree_button_press_event(GtkWidget *widget, GdkEventButton *event,
+		gpointer user_data)
+{
+	if (event->button == 3)
+	{
+		gtk_menu_popup(GTK_MENU(tv.popup_taglist), NULL, NULL, NULL, NULL,
+			event->button, event->time);
+		return TRUE;
+	}
+	return FALSE;
+}
+
+
+static void create_default_tag_tree(void)
+{
+	GtkScrolledWindow *scrolled_window = GTK_SCROLLED_WINDOW(tag_window);
+	GtkWidget *label;
+
+	/* default_tag_tree is a GtkViewPort with a GtkLabel inside it */
+	tv.default_tag_tree = gtk_viewport_new(
+		gtk_scrolled_window_get_hadjustment(scrolled_window),
+		gtk_scrolled_window_get_vadjustment(scrolled_window));
+	label = gtk_label_new(_("No tags found"));
+	gtk_misc_set_alignment(GTK_MISC(label), 0.1, 0.01);
+	gtk_container_add(GTK_CONTAINER(tv.default_tag_tree), label);
+	gtk_widget_show_all(tv.default_tag_tree);
+	g_signal_connect(tv.default_tag_tree, "button-press-event",
+		G_CALLBACK(on_default_tag_tree_button_press_event), NULL);
+	g_object_ref((gpointer)tv.default_tag_tree);	/* to hold it after removing */
+}
+
+
+/* update = rescan the tags for doc->filename */
+void sidebar_update_tag_list(GeanyDocument *doc, gboolean update)
+{
+	if (gtk_bin_get_child(GTK_BIN(tag_window)))
+		gtk_container_remove(GTK_CONTAINER(tag_window), gtk_bin_get_child(GTK_BIN(tag_window)));
+
+	if (tv.default_tag_tree == NULL)
+		create_default_tag_tree();
+
+	/* show default empty tag tree if there are no tags */
+	if (doc == NULL || doc->file_type == NULL || ! filetype_has_tags(doc->file_type))
+	{
+		gtk_container_add(GTK_CONTAINER(tag_window), tv.default_tag_tree);
+		return;
+	}
+
+	if (update)
+	{	/* updating the tag list in the left tag window */
+		if (doc->priv->tag_tree == NULL)
+		{
+			doc->priv->tag_store = gtk_tree_store_new(
+				SYMBOLS_N_COLUMNS, GDK_TYPE_PIXBUF, G_TYPE_STRING, G_TYPE_POINTER, G_TYPE_STRING);
+			doc->priv->tag_tree = gtk_tree_view_new();
+			prepare_taglist(doc->priv->tag_tree, doc->priv->tag_store);
+			gtk_widget_show(doc->priv->tag_tree);
+			g_object_ref((gpointer)doc->priv->tag_tree);	/* to hold it after removing */
+		}
+
+		doc->has_tags = symbols_recreate_tag_list(doc, SYMBOLS_SORT_USE_PREVIOUS);
+	}
+
+	if (doc->has_tags)
+	{
+		gtk_container_add(GTK_CONTAINER(tag_window), doc->priv->tag_tree);
+	}
+	else
+	{
+		gtk_container_add(GTK_CONTAINER(tag_window), tv.default_tag_tree);
+	}
+}
+
+
+/* does some preparing things to the open files list widget */
+static void prepare_openfiles(void)
+{
+	GtkCellRenderer *icon_renderer;
+	GtkCellRenderer *text_renderer;
+	GtkTreeViewColumn *column;
+	GtkTreeSelection *select;
+	GtkTreeSortable *sortable;
+
+	tv.tree_openfiles = ui_lookup_widget(main_widgets.window, "treeview6");
+
+	/* store the icon and the short filename to show, and the index as reference,
+	 * the colour (black/red/green) and the full name for the tooltip */
+	store_openfiles = gtk_tree_store_new(5, G_TYPE_STRING, G_TYPE_STRING,
+		G_TYPE_POINTER, GDK_TYPE_COLOR, G_TYPE_STRING);
+	gtk_tree_view_set_model(GTK_TREE_VIEW(tv.tree_openfiles), GTK_TREE_MODEL(store_openfiles));
+
+	/* set policy settings for the scolledwindow around the treeview again, because glade
+	 * doesn't keep the settings */
+	gtk_scrolled_window_set_policy(
+		GTK_SCROLLED_WINDOW(ui_lookup_widget(main_widgets.window, "scrolledwindow7")),
+		GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+
+	icon_renderer = gtk_cell_renderer_pixbuf_new();
+	text_renderer = gtk_cell_renderer_text_new();
+	g_object_set(text_renderer, "ellipsize", PANGO_ELLIPSIZE_MIDDLE, NULL);
+	column = gtk_tree_view_column_new();
+	gtk_tree_view_column_pack_start(column, icon_renderer, FALSE);
+	gtk_tree_view_column_set_attributes(column, icon_renderer, "stock-id", DOCUMENTS_ICON, NULL);
+	gtk_tree_view_column_pack_start(column, text_renderer, TRUE);
+	gtk_tree_view_column_set_attributes(column, text_renderer, "text", DOCUMENTS_SHORTNAME,
+		"foreground-gdk", DOCUMENTS_COLOR, NULL);
+	gtk_tree_view_append_column(GTK_TREE_VIEW(tv.tree_openfiles), column);
+	gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(tv.tree_openfiles), FALSE);
+
+	gtk_tree_view_set_search_column(GTK_TREE_VIEW(tv.tree_openfiles),
+		DOCUMENTS_SHORTNAME);
+
+	/* sort opened filenames in the store_openfiles treeview */
+	sortable = GTK_TREE_SORTABLE(GTK_TREE_MODEL(store_openfiles));
+	gtk_tree_sortable_set_sort_column_id(sortable, DOCUMENTS_SHORTNAME, GTK_SORT_ASCENDING);
+
+	ui_widget_modify_font_from_string(tv.tree_openfiles, interface_prefs.tagbar_font);
+
+	/* GTK 2.12 tooltips */
+	if (gtk_check_version(2, 12, 0) == NULL)
+		g_object_set(tv.tree_openfiles, "has-tooltip", TRUE, "tooltip-column", DOCUMENTS_FILENAME, NULL);
+
+	/* selection handling */
+	select = gtk_tree_view_get_selection(GTK_TREE_VIEW(tv.tree_openfiles));
+	gtk_tree_selection_set_mode(select, GTK_SELECTION_SINGLE);
+	g_object_unref(store_openfiles);
+
+	g_signal_connect(GTK_TREE_VIEW(tv.tree_openfiles), "button-press-event",
+		G_CALLBACK(sidebar_button_press_cb), NULL);
+	g_signal_connect(GTK_TREE_VIEW(tv.tree_openfiles), "key-press-event",
+		G_CALLBACK(sidebar_key_press_cb), NULL);
+}
+
+
+/* iter should be toplevel */
+static gboolean find_tree_iter_dir(GtkTreeIter *iter, const gchar *dir)
+{
+	GeanyDocument *doc;
+	gchar *name;
+	gboolean result;
+
+	if (utils_str_equal(dir, "."))
+		dir = GEANY_STRING_UNTITLED;
+
+	gtk_tree_model_get(GTK_TREE_MODEL(store_openfiles), iter, DOCUMENTS_DOCUMENT, &doc, -1);
+	g_return_val_if_fail(!doc, FALSE);
+
+	gtk_tree_model_get(GTK_TREE_MODEL(store_openfiles), iter, DOCUMENTS_SHORTNAME, &name, -1);
+
+	result = utils_str_equal(name, dir);
+	g_free(name);
+
+	return result;
+}
+
+
+static GtkTreeIter *get_doc_parent(GeanyDocument *doc)
+{
+	gchar *tmp_dirname;
+	gchar *project_base_path;
+	gchar *dirname = NULL;
+	static GtkTreeIter parent;
+	GtkTreeModel *model = GTK_TREE_MODEL(store_openfiles);
+
+	if (!documents_show_paths)
+		return NULL;
+
+	tmp_dirname = g_path_get_dirname(DOC_FILENAME(doc));
+	/* replace the project base path with the project name */
+	project_base_path = project_get_base_path();
+	if (project_base_path != NULL)
+	{
+		gsize len = strlen(project_base_path);
+		const gchar *rest;
+
+		/* check whether the dir name matches or uses the project base path */
+		if (!utils_str_equal(project_base_path, tmp_dirname))
+			setptr(project_base_path, g_strconcat(project_base_path, G_DIR_SEPARATOR_S, NULL));
+		if (g_str_has_prefix(tmp_dirname, project_base_path))
+		{
+			rest = tmp_dirname + len;
+			dirname = g_strdup_printf("%s%s%s",
+				app->project->name,
+				(*rest != G_DIR_SEPARATOR && *rest != '\0') ? G_DIR_SEPARATOR_S : "",
+				rest);
+		}
+		g_free(project_base_path);
+	}
+	if (dirname == NULL)
+		dirname = tmp_dirname;
+	else
+		g_free(tmp_dirname);
+
+	if (gtk_tree_model_get_iter_first(model, &parent))
+	{
+		do
+		{
+			if (find_tree_iter_dir(&parent, dirname))
+			{
+				g_free(dirname);
+				return &parent;
+			}
+		}
+		while (gtk_tree_model_iter_next(model, &parent));
+	}
+	/* no match, add dir parent */
+	gtk_tree_store_append(store_openfiles, &parent, NULL);
+	gtk_tree_store_set(store_openfiles, &parent, DOCUMENTS_ICON, GTK_STOCK_DIRECTORY,
+		DOCUMENTS_SHORTNAME, doc->file_name ? dirname : GEANY_STRING_UNTITLED, -1);
+
+	g_free(dirname);
+	return &parent;
+}
+
+
+/* Also sets doc->priv->iter.
+ * This is called recursively in sidebar_openfiles_update_all(). */
+void sidebar_openfiles_add(GeanyDocument *doc)
+{
+	GtkTreeIter *iter = &doc->priv->iter;
+	GtkTreeIter *parent = get_doc_parent(doc);
+	gchar *basename;
+	const GdkColor *color = document_get_status_color(doc);
+
+	gtk_tree_store_append(store_openfiles, iter, parent);
+
+	/* check if new parent */
+	if (parent && gtk_tree_model_iter_n_children(GTK_TREE_MODEL(store_openfiles), parent) == 1)
+	{
+		GtkTreePath *path;
+
+		/* expand parent */
+		path = gtk_tree_model_get_path(GTK_TREE_MODEL(store_openfiles), parent);
+		gtk_tree_view_expand_row(GTK_TREE_VIEW(tv.tree_openfiles), path, TRUE);
+		gtk_tree_path_free(path);
+	}
+	basename = g_path_get_basename(DOC_FILENAME(doc));
+	gtk_tree_store_set(store_openfiles, iter, DOCUMENTS_ICON, GTK_STOCK_FILE,
+		DOCUMENTS_SHORTNAME, basename, DOCUMENTS_DOCUMENT, doc, DOCUMENTS_COLOR, color,
+		DOCUMENTS_FILENAME, DOC_FILENAME(doc), -1);
+	g_free(basename);
+}
+
+
+static void openfiles_remove(GeanyDocument *doc)
+{
+	GtkTreeIter *iter = &doc->priv->iter;
+	GtkTreeIter parent;
+
+	if (gtk_tree_model_iter_parent(GTK_TREE_MODEL(store_openfiles), &parent, iter) &&
+		gtk_tree_model_iter_n_children(GTK_TREE_MODEL(store_openfiles), &parent) == 1)
+		gtk_tree_store_remove(store_openfiles, &parent);
+	else
+		gtk_tree_store_remove(store_openfiles, iter);
+}
+
+
+void sidebar_openfiles_update(GeanyDocument *doc)
+{
+	GtkTreeIter *iter = &doc->priv->iter;
+	gchar *fname;
+
+	gtk_tree_model_get(GTK_TREE_MODEL(store_openfiles), iter, DOCUMENTS_FILENAME, &fname, -1);
+
+	if (utils_str_equal(fname, DOC_FILENAME(doc)))
+	{
+		/* just update color */
+		const GdkColor *color = document_get_status_color(doc);
+
+		gtk_tree_store_set(store_openfiles, iter, DOCUMENTS_COLOR, color, -1);
+	}
+	else
+	{
+		/* path has changed, so remove and re-add */
+		GtkTreeSelection *treesel;
+		gboolean sel;
+
+		treesel = gtk_tree_view_get_selection(GTK_TREE_VIEW(tv.tree_openfiles));
+		sel = gtk_tree_selection_iter_is_selected(treesel, &doc->priv->iter);
+		openfiles_remove(doc);
+
+		sidebar_openfiles_add(doc);
+		if (sel)
+			gtk_tree_selection_select_iter(treesel, &doc->priv->iter);
+	}
+	g_free(fname);
+}
+
+
+void sidebar_openfiles_update_all()
+{
+	guint i, page_count;
+	GeanyDocument *doc;
+
+	gtk_tree_store_clear(store_openfiles);
+	page_count = gtk_notebook_get_n_pages(GTK_NOTEBOOK(main_widgets.notebook));
+	for (i = 0; i < page_count; i++)
+	{
+		doc = document_get_from_page(i);
+		if (G_UNLIKELY(doc == NULL))
+			continue;
+
+		sidebar_openfiles_add(doc);
+	}
+}
+
+
+void sidebar_remove_document(GeanyDocument *doc)
+{
+	openfiles_remove(doc);
+
+	if (GTK_IS_WIDGET(doc->priv->tag_tree))
+	{
+		gtk_widget_destroy(doc->priv->tag_tree);
+		if (GTK_IS_TREE_VIEW(doc->priv->tag_tree))
+		{
+			/* Because it was ref'd in sidebar_update_tag_list, it needs unref'ing */
+			g_object_unref((gpointer)doc->priv->tag_tree);
+		}
+		doc->priv->tag_tree = NULL;
+	}
+}
+
+
+static void on_hide_sidebar(void)
+{
+	ui_prefs.sidebar_visible = FALSE;
+	ui_sidebar_show_hide();
+}
+
+
+static gboolean on_sidebar_display_symbol_list_show(GtkWidget *item)
+{
+	gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item),
+		interface_prefs.sidebar_symbol_visible);
+	return FALSE;
+}
+
+
+static gboolean on_sidebar_display_open_files_show(GtkWidget *item)
+{
+	gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item),
+		interface_prefs.sidebar_openfiles_visible);
+	return FALSE;
+}
+
+
+void sidebar_add_common_menu_items(GtkMenu *menu)
+{
+	GtkWidget *item;
+
+	item = gtk_separator_menu_item_new();
+	gtk_widget_show(item);
+	gtk_container_add(GTK_CONTAINER(menu), item);
+
+	item = gtk_check_menu_item_new_with_mnemonic(_("Show S_ymbol List"));
+	gtk_container_add(GTK_CONTAINER(menu), item);
+	g_signal_connect(item, "expose-event",
+			G_CALLBACK(on_sidebar_display_symbol_list_show), NULL);
+	gtk_widget_show(item);
+	g_signal_connect(item, "activate",
+			G_CALLBACK(on_list_symbol_activate), NULL);
+
+	item = gtk_check_menu_item_new_with_mnemonic(_("Show _Document List"));
+	gtk_container_add(GTK_CONTAINER(menu), item);
+	g_signal_connect(item, "expose-event",
+			G_CALLBACK(on_sidebar_display_open_files_show), NULL);
+	gtk_widget_show(item);
+	g_signal_connect(item, "activate",
+			G_CALLBACK(on_list_document_activate), NULL);
+
+	item = gtk_image_menu_item_new_with_mnemonic(_("H_ide Sidebar"));
+	gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item),
+		gtk_image_new_from_stock("gtk-close", GTK_ICON_SIZE_MENU));
+	gtk_widget_show(item);
+	gtk_container_add(GTK_CONTAINER(menu), item);
+	g_signal_connect(item, "activate", G_CALLBACK(on_hide_sidebar), NULL);
+}
+
+
+static void on_openfiles_show_paths_activate(GtkCheckMenuItem *item, gpointer user_data)
+{
+	documents_show_paths = gtk_check_menu_item_get_active(item);
+	sidebar_openfiles_update_all();
+}
+
+
+static void on_list_document_activate(GtkCheckMenuItem *item, gpointer user_data)
+{
+	interface_prefs.sidebar_openfiles_visible = gtk_check_menu_item_get_active(item);
+	ui_sidebar_show_hide();
+}
+
+
+static void on_list_symbol_activate(GtkCheckMenuItem *item, gpointer user_data)
+{
+	interface_prefs.sidebar_symbol_visible = gtk_check_menu_item_get_active(item);
+	ui_sidebar_show_hide();
+}
+
+
+static void create_openfiles_popup_menu(void)
+{
+	GtkWidget *item;
+
+	openfiles_popup_menu = gtk_menu_new();
+
+	item = gtk_image_menu_item_new_from_stock("gtk-close", NULL);
+	gtk_widget_show(item);
+	gtk_container_add(GTK_CONTAINER(openfiles_popup_menu), item);
+	g_signal_connect(item, "activate",
+			G_CALLBACK(on_openfiles_document_action), GINT_TO_POINTER(OPENFILES_ACTION_REMOVE));
+	doc_items.close = item;
+
+	item = gtk_separator_menu_item_new();
+	gtk_widget_show(item);
+	gtk_container_add(GTK_CONTAINER(openfiles_popup_menu), item);
+
+	item = gtk_image_menu_item_new_from_stock("gtk-save", NULL);
+	gtk_widget_show(item);
+	gtk_container_add(GTK_CONTAINER(openfiles_popup_menu), item);
+	g_signal_connect(item, "activate",
+			G_CALLBACK(on_openfiles_document_action), GINT_TO_POINTER(OPENFILES_ACTION_SAVE));
+	doc_items.save = item;
+
+	item = gtk_image_menu_item_new_with_mnemonic(_("_Reload"));
+	gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item),
+		gtk_image_new_from_stock("gtk-revert-to-saved", GTK_ICON_SIZE_MENU));
+	gtk_widget_show(item);
+	gtk_container_add(GTK_CONTAINER(openfiles_popup_menu), item);
+	g_signal_connect(item, "activate",
+			G_CALLBACK(on_openfiles_document_action), GINT_TO_POINTER(OPENFILES_ACTION_RELOAD));
+	doc_items.reload = item;
+
+	item = gtk_separator_menu_item_new();
+	gtk_widget_show(item);
+	gtk_container_add(GTK_CONTAINER(openfiles_popup_menu), item);
+
+	doc_items.show_paths = gtk_check_menu_item_new_with_mnemonic(_("Show _Paths"));
+	gtk_widget_show(doc_items.show_paths);
+	gtk_container_add(GTK_CONTAINER(openfiles_popup_menu), doc_items.show_paths);
+	g_signal_connect(doc_items.show_paths, "activate",
+			G_CALLBACK(on_openfiles_show_paths_activate), NULL);
+
+	sidebar_add_common_menu_items(GTK_MENU(openfiles_popup_menu));
+}
+
+
+static void unfold_parent(GtkTreeIter *iter)
+{
+	GtkTreeIter parent;
+	GtkTreePath *path;
+
+	if (gtk_tree_model_iter_parent(GTK_TREE_MODEL(store_openfiles), &parent, iter))
+	{
+		path = gtk_tree_model_get_path(GTK_TREE_MODEL(store_openfiles), &parent);
+		gtk_tree_view_expand_row(GTK_TREE_VIEW(tv.tree_openfiles), path, TRUE);
+		gtk_tree_path_free(path);
+	}
+}
+
+
+/* compares the given data with the doc pointer from the selected row of openfiles
+ * treeview, in case of a match the row is selected and TRUE is returned
+ * (called indirectly from gtk_tree_model_foreach()) */
+static gboolean tree_model_find_node(GtkTreeModel *model, GtkTreePath *path,
+		GtkTreeIter *iter, gpointer data)
+{
+	GeanyDocument *doc;
+
+	gtk_tree_model_get(GTK_TREE_MODEL(store_openfiles), iter, DOCUMENTS_DOCUMENT, &doc, -1);
+
+	if (doc == data)
+	{
+		/* unfolding also prevents a strange bug where the selection gets stuck on the parent
+		 * when it is collapsed and then switching documents */
+		unfold_parent(iter);
+		gtk_tree_view_set_cursor(GTK_TREE_VIEW(tv.tree_openfiles), path, NULL, FALSE);
+		return TRUE;
+	}
+	else return FALSE;
+}
+
+
+void sidebar_select_openfiles_item(GeanyDocument *doc)
+{
+	gtk_tree_model_foreach(GTK_TREE_MODEL(store_openfiles), tree_model_find_node, doc);
+}
+
+
+/* callbacks */
+
+static void document_action(GeanyDocument *doc, gint action)
+{
+	if (! DOC_VALID(doc))
+		return;
+
+	switch (action)
+	{
+		case OPENFILES_ACTION_REMOVE:
+		{
+			document_close(doc);
+			break;
+		}
+		case OPENFILES_ACTION_SAVE:
+		{
+			document_save_file(doc, FALSE);
+			break;
+		}
+		case OPENFILES_ACTION_RELOAD:
+		{
+			on_toolbutton_reload_clicked(NULL, NULL);
+			break;
+		}
+	}
+
+}
+
+
+static void on_openfiles_document_action(GtkMenuItem *menuitem, gpointer user_data)
+{
+	GtkTreeIter iter;
+	GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(tv.tree_openfiles));
+	GtkTreeModel *model;
+	GeanyDocument *doc;
+	gint action = GPOINTER_TO_INT(user_data);
+
+	if (gtk_tree_selection_get_selected(selection, &model, &iter))
+	{
+		gtk_tree_model_get(model, &iter, DOCUMENTS_DOCUMENT, &doc, -1);
+		if (doc)
+		{
+			document_action(doc, action);
+		}
+		else
+		{
+			/* parent item selected */
+			GtkTreeIter child;
+			gint i = gtk_tree_model_iter_n_children(model, &iter) - 1;
+
+			while (i >= 0 && gtk_tree_model_iter_nth_child(model, &child, &iter, i))
+			{
+				gtk_tree_model_get(model, &child, DOCUMENTS_DOCUMENT, &doc, -1);
+
+				document_action(doc, action);
+				i--;
+			}
+		}
+	}
+}
+
+
+static void change_focus_to_editor(GeanyDocument *doc)
+{
+	if (may_steal_focus)
+		document_try_focus(doc);
+	may_steal_focus = FALSE;
+}
+
+
+static gboolean on_openfiles_tree_selection_changed(GtkTreeSelection *selection)
+{
+	GtkTreeIter iter;
+	GtkTreeModel *model;
+	GeanyDocument *doc = NULL;
+
+	/* use switch_notebook_page to ignore changing the notebook page because it is already done */
+	if (gtk_tree_selection_get_selected(selection, &model, &iter) && ! ignore_callback)
+	{
+		gtk_tree_model_get(model, &iter, DOCUMENTS_DOCUMENT, &doc, -1);
+		if (! doc)
+			return FALSE;	/* parent */
+
+		/* switch to the doc and grab the focus */
+		gtk_notebook_set_current_page(GTK_NOTEBOOK(main_widgets.notebook),
+			gtk_notebook_page_num(GTK_NOTEBOOK(main_widgets.notebook),
+			(GtkWidget*) doc->editor->sci));
+		change_focus_to_editor(doc);
+	}
+	return FALSE;
+}
+
+
+static gboolean on_taglist_tree_selection_changed(GtkTreeSelection *selection)
+{
+	GtkTreeIter iter;
+	GtkTreeModel *model;
+	gint line = 0;
+
+	if (gtk_tree_selection_get_selected(selection, &model, &iter))
+	{
+		const TMTag *tag;
+
+		gtk_tree_model_get(model, &iter, SYMBOLS_COLUMN_TAG, &tag, -1);
+		if (! tag)
+			return FALSE;
+
+		line = tag->atts.entry.line;
+		if (line > 0)
+		{
+			GeanyDocument *doc = document_get_current();
+
+			if (doc != NULL)
+			{
+				navqueue_goto_line(doc, doc, line);
+				change_focus_to_editor(doc);
+			}
+		}
+	}
+	return FALSE;
+}
+
+
+static gboolean sidebar_key_press_cb(GtkWidget *widget, GdkEventKey *event,
+											 gpointer user_data)
+{
+	may_steal_focus = FALSE;
+	if (event->keyval == GDK_Return ||
+		event->keyval == GDK_ISO_Enter ||
+		event->keyval == GDK_KP_Enter ||
+		event->keyval == GDK_space)
+	{
+		GtkTreeSelection *select = gtk_tree_view_get_selection(GTK_TREE_VIEW(widget));
+		may_steal_focus = TRUE;
+		/* delay the query of selection state because this callback is executed before GTK
+		 * changes the selection (g_signal_connect_after would be better but it doesn't work) */
+		if (widget ==  tv.tree_openfiles) /* tag and doc list have separate handlers */
+			g_idle_add((GSourceFunc) on_openfiles_tree_selection_changed, select);
+		else
+			g_idle_add((GSourceFunc) on_taglist_tree_selection_changed, select);
+	}
+	return FALSE;
+}
+
+
+static gboolean sidebar_button_press_cb(GtkWidget *widget, GdkEventButton *event,
+		G_GNUC_UNUSED gpointer user_data)
+{
+	GtkTreeSelection *selection;
+
+	selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(widget));
+	may_steal_focus = TRUE;
+
+	if (event->type == GDK_2BUTTON_PRESS)
+	{	/* double click on parent node(section) expands/collapses it */
+		GtkTreeModel *model;
+		GtkTreeIter iter;
+
+		if (gtk_tree_selection_get_selected(selection, &model, &iter))
+		{
+			if (gtk_tree_model_iter_has_child(model, &iter))
+			{
+				GtkTreePath *path = gtk_tree_model_get_path(model, &iter);
+
+				if (gtk_tree_view_row_expanded(GTK_TREE_VIEW(widget), path))
+					gtk_tree_view_collapse_row(GTK_TREE_VIEW(widget), path);
+				else
+					gtk_tree_view_expand_row(GTK_TREE_VIEW(widget), path, FALSE);
+
+				gtk_tree_path_free(path);
+				return TRUE;
+			}
+		}
+	}
+	else if (event->button == 1)
+	{	/* allow reclicking of taglist treeview item */
+		/* delay the query of selection state because this callback is executed before GTK
+		 * changes the selection (g_signal_connect_after would be better but it doesn't work) */
+		if (widget == tv.tree_openfiles)
+			g_idle_add((GSourceFunc) on_openfiles_tree_selection_changed, selection);
+		else
+			g_idle_add((GSourceFunc) on_taglist_tree_selection_changed, selection);
+	}
+	else if (event->button == 3)
+	{
+		if (widget == tv.tree_openfiles)
+		{
+			if (!openfiles_popup_menu)
+				create_openfiles_popup_menu();
+
+			/* update menu item sensitivity */
+			documents_menu_update(selection);
+			gtk_menu_popup(GTK_MENU(openfiles_popup_menu), NULL, NULL, NULL, NULL,
+					event->button, event->time);
+		}
+		else
+		{
+			gtk_menu_popup(GTK_MENU(tv.popup_taglist), NULL, NULL, NULL, NULL,
+					event->button, event->time);
+		}
+	}
+	return FALSE;
+}
+
+
+static void documents_menu_update(GtkTreeSelection *selection)
+{
+	GtkTreeModel *model;
+	GtkTreeIter iter;
+	gboolean sel, path;
+	gchar *shortname = NULL;
+	GeanyDocument *doc = NULL;
+
+	/* maybe no selection e.g. if ctrl-click deselected */
+	sel = gtk_tree_selection_get_selected(selection, &model, &iter);
+	if (sel)
+	{
+		gtk_tree_model_get(model, &iter, DOCUMENTS_DOCUMENT, &doc,
+			DOCUMENTS_SHORTNAME, &shortname, -1);
+	}
+	path = NZV(shortname) &&
+		(g_path_is_absolute(shortname) ||
+		(app->project && g_str_has_prefix(shortname, app->project->name)));
+
+	/* can close all, save all (except shortname), but only reload individually ATM */
+	gtk_widget_set_sensitive(doc_items.close, sel);
+	gtk_widget_set_sensitive(doc_items.save, (doc && doc->real_path) || path);
+	gtk_widget_set_sensitive(doc_items.reload, doc && doc->real_path);
+	g_free(shortname);
+
+	gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(doc_items.show_paths),
+		documents_show_paths);
+}
+
+
+GeanyPrefGroup *stash_group = NULL;
+
+static void on_load_settings(void)
+{
+	tag_window = ui_lookup_widget(main_widgets.window, "scrolledwindow2");
+
+	prepare_openfiles();
+	/* note: ui_prefs.sidebar_page is reapplied after plugins are loaded */
+	stash_group_display(stash_group, NULL);
+}
+
+
+static void on_save_settings(void)
+{
+	stash_group_update(stash_group, NULL);
+}
+
+
+void sidebar_init(void)
+{
+	GeanyPrefGroup *group;
+
+	group = stash_group_new(PACKAGE);
+	stash_group_add_boolean(group, &documents_show_paths, "documents_show_paths", TRUE);
+	stash_group_add_widget_property(group, &ui_prefs.sidebar_page, "sidebar_page", GINT_TO_POINTER(0),
+		main_widgets.sidebar_notebook, "page", 0);
+	configuration_add_pref_group(group, FALSE);
+	stash_group = group;
+
+	/* delay building documents treeview until sidebar font has been read */
+	g_signal_connect(geany_object, "load-settings", on_load_settings, NULL);
+	g_signal_connect(geany_object, "save-settings", on_save_settings, NULL);
+}
+
+
+#define WIDGET(w) w && GTK_IS_WIDGET(w)
+
+void sidebar_finalize(void)
+{
+	if (WIDGET(tv.default_tag_tree))
+	{
+		g_object_unref(tv.default_tag_tree);
+		gtk_widget_destroy(tv.default_tag_tree);
+	}
+	if (WIDGET(tv.popup_taglist))
+		gtk_widget_destroy(tv.popup_taglist);
+	if (WIDGET(openfiles_popup_menu))
+		gtk_widget_destroy(openfiles_popup_menu);
+}

Copied: trunk/src/sidebar.h (from rev 4247, trunk/src/treeviews.h)
===================================================================
--- trunk/src/sidebar.h	                        (rev 0)
+++ trunk/src/sidebar.h	2009-09-28 11:16:59 UTC (rev 4252)
@@ -0,0 +1,67 @@
+/*
+ *      sidebar.h - this file is part of Geany, a fast and lightweight IDE
+ *
+ *      Copyright 2005-2009 Enrico Tröger <enrico(dot)troeger(at)uvena(dot)de>
+ *      Copyright 2006-2009 Nick Treleaven <nick(dot)treleaven(at)btinternet(dot)com>
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      This program is distributed in the hope that it will be useful,
+ *      but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *      GNU General Public License for more details.
+ *
+ *      You should have received a copy of the GNU General Public License
+ *      along with this program; if not, write to the Free Software
+ *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id$
+ */
+
+
+
+#ifndef GEANY_SIDEBAR_H
+#define GEANY_SIDEBAR_H 1
+
+
+typedef struct SidebarTreeviews
+{
+	GtkWidget		*tree_openfiles;
+	GtkWidget		*default_tag_tree;
+	GtkWidget		*popup_taglist;
+}
+SidebarTreeviews;
+
+extern SidebarTreeviews tv;
+
+enum
+{
+	SYMBOLS_COLUMN_ICON,
+	SYMBOLS_COLUMN_NAME,
+	SYMBOLS_COLUMN_TAG,
+	SYMBOLS_COLUMN_TOOLTIP,
+	SYMBOLS_N_COLUMNS
+};
+
+void sidebar_init(void);
+
+void sidebar_finalize(void);
+
+void sidebar_update_tag_list(GeanyDocument *doc, gboolean update);
+
+void sidebar_openfiles_add(GeanyDocument *doc);
+
+void sidebar_openfiles_update(GeanyDocument *doc);
+
+void sidebar_openfiles_update_all(void);
+
+void sidebar_select_openfiles_item(GeanyDocument *doc);
+
+void sidebar_remove_document(GeanyDocument *doc);
+
+void sidebar_add_common_menu_items(GtkMenu *menu);
+
+#endif

Modified: trunk/src/symbols.c
===================================================================
--- trunk/src/symbols.c	2009-09-27 20:31:16 UTC (rev 4251)
+++ trunk/src/symbols.c	2009-09-28 11:16:59 UTC (rev 4252)
@@ -44,7 +44,7 @@
 #include "documentprivate.h"
 #include "support.h"
 #include "msgwindow.h"
-#include "treeviews.h"
+#include "sidebar.h"
 #include "main.h"
 #include "navqueue.h"
 #include "ui_utils.h"

Deleted: trunk/src/treeviews.c
===================================================================
--- trunk/src/treeviews.c	2009-09-27 20:31:16 UTC (rev 4251)
+++ trunk/src/treeviews.c	2009-09-28 11:16:59 UTC (rev 4252)
@@ -1,928 +0,0 @@
-/*
- *      treeviews.c - this file is part of Geany, a fast and lightweight IDE
- *
- *      Copyright 2005-2009 Enrico Tröger <enrico(dot)troeger(at)uvena(dot)de>
- *      Copyright 2006-2009 Nick Treleaven <nick(dot)treleaven(at)btinternet(dot)com>
- *
- *      This program is free software; you can redistribute it and/or modify
- *      it under the terms of the GNU General Public License as published by
- *      the Free Software Foundation; either version 2 of the License, or
- *      (at your option) any later version.
- *
- *      This program is distributed in the hope that it will be useful,
- *      but WITHOUT ANY WARRANTY; without even the implied warranty of
- *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *      GNU General Public License for more details.
- *
- *      You should have received a copy of the GNU General Public License
- *      along with this program; if not, write to the Free Software
- *      Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * $Id$
- */
-
-/*
- * Sidebar related code for the Symbol list and Open files GtkTreeViews.
- */
-
-#include <string.h>
-
-#include "geany.h"
-#include "support.h"
-#include "callbacks.h"
-#include "treeviews.h"
-#include "document.h"
-#include "editor.h"
-#include "documentprivate.h"
-#include "filetypes.h"
-#include "utils.h"
-#include "ui_utils.h"
-#include "symbols.h"
-#include "navqueue.h"
-#include "project.h"
-#include "stash.h"
-#include "keyfile.h"
-#include "sciwrappers.h"
-
-#include <gdk/gdkkeysyms.h>
-
-SidebarTreeviews tv = {NULL, NULL, NULL};
-/* while typeahead searching, editor should not get focus */
-static gboolean may_steal_focus = FALSE;
-
-static struct
-{
-	GtkWidget *close;
-	GtkWidget *save;
-	GtkWidget *reload;
-	GtkWidget *show_paths;
-}
-doc_items = {NULL, NULL, NULL, NULL};
-
-enum
-{
-	TREEVIEW_SYMBOL = 0,
-	TREEVIEW_OPENFILES
-};
-
-enum
-{
-	OPENFILES_ACTION_REMOVE = 0,
-	OPENFILES_ACTION_SAVE,
-	OPENFILES_ACTION_RELOAD
-};
-
-/* documents tree model columns */
-enum
-{
-	DOCUMENTS_ICON,
-	DOCUMENTS_SHORTNAME,	/* dirname for parents, basename for children */
-	DOCUMENTS_DOCUMENT,
-	DOCUMENTS_COLOR,
-	DOCUMENTS_FILENAME		/* full filename */
-};
-
-static GtkTreeStore	*store_openfiles;
-static GtkWidget *openfiles_popup_menu;
-static gboolean documents_show_paths;
-static GtkWidget *tag_window;	/* scrolled window that holds the symbol list GtkTreeView */
-
-/* callback prototypes */
-static gboolean on_openfiles_tree_selection_changed(GtkTreeSelection *selection);
-static void on_openfiles_document_action(GtkMenuItem *menuitem, gpointer user_data);
-static gboolean on_taglist_tree_selection_changed(GtkTreeSelection *selection);
-static gboolean treeviews_button_press_cb(GtkWidget *widget, GdkEventButton *event,
-		gpointer user_data);
-static gboolean treeviews_key_press_cb(GtkWidget *widget, GdkEventKey *event,
-		gpointer user_data);
-static void on_list_document_activate(GtkCheckMenuItem *item, gpointer user_data);
-static void on_list_symbol_activate(GtkCheckMenuItem *item, gpointer user_data);
-static void documents_menu_update(GtkTreeSelection *selection);
-
-
-/* the prepare_* functions are document-related, but I think they fit better here than in document.c */
-static void prepare_taglist(GtkWidget *tree, GtkTreeStore *store)
-{
-	GtkCellRenderer *text_renderer, *icon_renderer;
-	GtkTreeViewColumn *column;
-	GtkTreeSelection *select;
-
-	text_renderer = gtk_cell_renderer_text_new();
-	icon_renderer = gtk_cell_renderer_pixbuf_new();
-	column = gtk_tree_view_column_new();
-
-	gtk_tree_view_column_pack_start(column, icon_renderer, FALSE);
-  	gtk_tree_view_column_set_attributes(column, icon_renderer, "pixbuf", SYMBOLS_COLUMN_ICON, NULL);
-  	g_object_set(icon_renderer, "xalign", 0.0, NULL);
-
-  	gtk_tree_view_column_pack_start(column, text_renderer, TRUE);
-  	gtk_tree_view_column_set_attributes(column, text_renderer, "text", SYMBOLS_COLUMN_NAME, NULL);
-  	g_object_set(text_renderer, "yalign", 0.5, NULL);
-  	gtk_tree_view_column_set_title(column, _("Symbols"));
-
-	gtk_tree_view_append_column(GTK_TREE_VIEW(tree), column);
-	gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(tree), FALSE);
-
-	ui_widget_modify_font_from_string(tree, interface_prefs.tagbar_font);
-
-	gtk_tree_view_set_model(GTK_TREE_VIEW(tree), GTK_TREE_MODEL(store));
-	g_object_unref(store);
-
-	g_signal_connect(tree, "button-press-event",
-		G_CALLBACK(treeviews_button_press_cb), NULL);
-	g_signal_connect(tree, "key-press-event",
-		G_CALLBACK(treeviews_key_press_cb), NULL);
-
-	if (gtk_check_version(2, 12, 0) == NULL)
-	{
-		g_object_set(tree, "show-expanders", interface_prefs.show_symbol_list_expanders, NULL);
-		if (! interface_prefs.show_symbol_list_expanders)
-			g_object_set(tree, "level-indentation", 10, NULL);
-		/* Tooltips */
-		g_object_set(tree,
-			"has-tooltip", TRUE,
-			"tooltip-column", SYMBOLS_COLUMN_TOOLTIP, NULL);
-	}
-
-	/* selection handling */
-	select = gtk_tree_view_get_selection(GTK_TREE_VIEW(tree));
-	gtk_tree_selection_set_mode(select, GTK_SELECTION_SINGLE);
-	/* callback for changed selection not necessary, will be handled by button-press-event */
-}
-
-
-static gboolean
-on_default_tag_tree_button_press_event(GtkWidget *widget, GdkEventButton *event,
-		gpointer user_data)
-{
-	if (event->button == 3)
-	{
-		gtk_menu_popup(GTK_MENU(tv.popup_taglist), NULL, NULL, NULL, NULL,
-			event->button, event->time);
-		return TRUE;
-	}
-	return FALSE;
-}
-
-
-static void create_default_tag_tree(void)
-{
-	GtkScrolledWindow *scrolled_window = GTK_SCROLLED_WINDOW(tag_window);
-	GtkWidget *label;
-
-	/* default_tag_tree is a GtkViewPort with a GtkLabel inside it */
-	tv.default_tag_tree = gtk_viewport_new(
-		gtk_scrolled_window_get_hadjustment(scrolled_window),
-		gtk_scrolled_window_get_vadjustment(scrolled_window));
-	label = gtk_label_new(_("No tags found"));
-	gtk_misc_set_alignment(GTK_MISC(label), 0.1, 0.01);
-	gtk_container_add(GTK_CONTAINER(tv.default_tag_tree), label);
-	gtk_widget_show_all(tv.default_tag_tree);
-	g_signal_connect(tv.default_tag_tree, "button-press-event",
-		G_CALLBACK(on_default_tag_tree_button_press_event), NULL);
-	g_object_ref((gpointer)tv.default_tag_tree);	/* to hold it after removing */
-}
-
-
-/* update = rescan the tags for doc->filename */
-void treeviews_update_tag_list(GeanyDocument *doc, gboolean update)
-{
-	if (gtk_bin_get_child(GTK_BIN(tag_window)))
-		gtk_container_remove(GTK_CONTAINER(tag_window), gtk_bin_get_child(GTK_BIN(tag_window)));
-
-	if (tv.default_tag_tree == NULL)
-		create_default_tag_tree();
-
-	/* show default empty tag tree if there are no tags */
-	if (doc == NULL || doc->file_type == NULL || ! filetype_has_tags(doc->file_type))
-	{
-		gtk_container_add(GTK_CONTAINER(tag_window), tv.default_tag_tree);
-		return;
-	}
-
-	if (update)
-	{	/* updating the tag list in the left tag window */
-		if (doc->priv->tag_tree == NULL)
-		{
-			doc->priv->tag_store = gtk_tree_store_new(
-				SYMBOLS_N_COLUMNS, GDK_TYPE_PIXBUF, G_TYPE_STRING, G_TYPE_POINTER, G_TYPE_STRING);
-			doc->priv->tag_tree = gtk_tree_view_new();
-			prepare_taglist(doc->priv->tag_tree, doc->priv->tag_store);
-			gtk_widget_show(doc->priv->tag_tree);
-			g_object_ref((gpointer)doc->priv->tag_tree);	/* to hold it after removing */
-		}
-
-		doc->has_tags = symbols_recreate_tag_list(doc, SYMBOLS_SORT_USE_PREVIOUS);
-	}
-
-	if (doc->has_tags)
-	{
-		gtk_container_add(GTK_CONTAINER(tag_window), doc->priv->tag_tree);
-	}
-	else
-	{
-		gtk_container_add(GTK_CONTAINER(tag_window), tv.default_tag_tree);
-	}
-}
-
-
-/* does some preparing things to the open files list widget */
-static void prepare_openfiles(void)
-{
-	GtkCellRenderer *icon_renderer;
-	GtkCellRenderer *text_renderer;
-	GtkTreeViewColumn *column;
-	GtkTreeSelection *select;
-	GtkTreeSortable *sortable;
-
-	tv.tree_openfiles = ui_lookup_widget(main_widgets.window, "treeview6");
-
-	/* store the icon and the short filename to show, and the index as reference,
-	 * the colour (black/red/green) and the full name for the tooltip */
-	store_openfiles = gtk_tree_store_new(5, G_TYPE_STRING, G_TYPE_STRING,
-		G_TYPE_POINTER, GDK_TYPE_COLOR, G_TYPE_STRING);
-	gtk_tree_view_set_model(GTK_TREE_VIEW(tv.tree_openfiles), GTK_TREE_MODEL(store_openfiles));
-
-	/* set policy settings for the scolledwindow around the treeview again, because glade
-	 * doesn't keep the settings */
-	gtk_scrolled_window_set_policy(
-		GTK_SCROLLED_WINDOW(ui_lookup_widget(main_widgets.window, "scrolledwindow7")),
-		GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
-
-	icon_renderer = gtk_cell_renderer_pixbuf_new();
-	text_renderer = gtk_cell_renderer_text_new();
-	g_object_set(text_renderer, "ellipsize", PANGO_ELLIPSIZE_MIDDLE, NULL);
-	column = gtk_tree_view_column_new();
-	gtk_tree_view_column_pack_start(column, icon_renderer, FALSE);
-	gtk_tree_view_column_set_attributes(column, icon_renderer, "stock-id", DOCUMENTS_ICON, NULL);
-	gtk_tree_view_column_pack_start(column, text_renderer, TRUE);
-	gtk_tree_view_column_set_attributes(column, text_renderer, "text", DOCUMENTS_SHORTNAME,
-		"foreground-gdk", DOCUMENTS_COLOR, NULL);
-	gtk_tree_view_append_column(GTK_TREE_VIEW(tv.tree_openfiles), column);
-	gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(tv.tree_openfiles), FALSE);
-
-	gtk_tree_view_set_search_column(GTK_TREE_VIEW(tv.tree_openfiles),
-		DOCUMENTS_SHORTNAME);
-
-	/* sort opened filenames in the store_openfiles treeview */
-	sortable = GTK_TREE_SORTABLE(GTK_TREE_MODEL(store_openfiles));
-	gtk_tree_sortable_set_sort_column_id(sortable, DOCUMENTS_SHORTNAME, GTK_SORT_ASCENDING);
-
-	ui_widget_modify_font_from_string(tv.tree_openfiles, interface_prefs.tagbar_font);
-
-	/* GTK 2.12 tooltips */
-	if (gtk_check_version(2, 12, 0) == NULL)
-		g_object_set(tv.tree_openfiles, "has-tooltip", TRUE, "tooltip-column", DOCUMENTS_FILENAME, NULL);
-
-	/* selection handling */
-	select = gtk_tree_view_get_selection(GTK_TREE_VIEW(tv.tree_openfiles));
-	gtk_tree_selection_set_mode(select, GTK_SELECTION_SINGLE);
-	g_object_unref(store_openfiles);
-
-	g_signal_connect(GTK_TREE_VIEW(tv.tree_openfiles), "button-press-event",
-		G_CALLBACK(treeviews_button_press_cb), NULL);
-	g_signal_connect(GTK_TREE_VIEW(tv.tree_openfiles), "key-press-event",
-		G_CALLBACK(treeviews_key_press_cb), NULL);
-}
-
-
-/* iter should be toplevel */
-static gboolean find_tree_iter_dir(GtkTreeIter *iter, const gchar *dir)
-{
-	GeanyDocument *doc;
-	gchar *name;
-	gboolean result;
-
-	if (utils_str_equal(dir, "."))
-		dir = GEANY_STRING_UNTITLED;
-
-	gtk_tree_model_get(GTK_TREE_MODEL(store_openfiles), iter, DOCUMENTS_DOCUMENT, &doc, -1);
-	g_return_val_if_fail(!doc, FALSE);
-
-	gtk_tree_model_get(GTK_TREE_MODEL(store_openfiles), iter, DOCUMENTS_SHORTNAME, &name, -1);
-
-	result = utils_str_equal(name, dir);
-	g_free(name);
-
-	return result;
-}
-
-
-static GtkTreeIter *get_doc_parent(GeanyDocument *doc)
-{
-	gchar *tmp_dirname;
-	gchar *project_base_path;
-	gchar *dirname = NULL;
-	static GtkTreeIter parent;
-	GtkTreeModel *model = GTK_TREE_MODEL(store_openfiles);
-
-	if (!documents_show_paths)
-		return NULL;
-
-	tmp_dirname = g_path_get_dirname(DOC_FILENAME(doc));
-	/* replace the project base path with the project name */
-	project_base_path = project_get_base_path();
-	if (project_base_path != NULL)
-	{
-		gsize len = strlen(project_base_path);
-		const gchar *rest;
-
-		/* check whether the dir name matches or uses the project base path */
-		if (!utils_str_equal(project_base_path, tmp_dirname))
-			setptr(project_base_path, g_strconcat(project_base_path, G_DIR_SEPARATOR_S, NULL));
-		if (g_str_has_prefix(tmp_dirname, project_base_path))
-		{
-			rest = tmp_dirname + len;
-			dirname = g_strdup_printf("%s%s%s",
-				app->project->name,
-				(*rest != G_DIR_SEPARATOR && *rest != '\0') ? G_DIR_SEPARATOR_S : "",
-				rest);
-		}
-		g_free(project_base_path);
-	}
-	if (dirname == NULL)
-		dirname = tmp_dirname;
-	else
-		g_free(tmp_dirname);
-
-	if (gtk_tree_model_get_iter_first(model, &parent))
-	{
-		do
-		{
-			if (find_tree_iter_dir(&parent, dirname))
-			{
-				g_free(dirname);
-				return &parent;
-			}
-		}
-		while (gtk_tree_model_iter_next(model, &parent));
-	}
-	/* no match, add dir parent */
-	gtk_tree_store_append(store_openfiles, &parent, NULL);
-	gtk_tree_store_set(store_openfiles, &parent, DOCUMENTS_ICON, GTK_STOCK_DIRECTORY,
-		DOCUMENTS_SHORTNAME, doc->file_name ? dirname : GEANY_STRING_UNTITLED, -1);
-
-	g_free(dirname);
-	return &parent;
-}
-
-
-/* Also sets doc->priv->iter.
- * This is called recursively in treeviews_openfiles_update_all(). */
-void treeviews_openfiles_add(GeanyDocument *doc)
-{
-	GtkTreeIter *iter = &doc->priv->iter;
-	GtkTreeIter *parent = get_doc_parent(doc);
-	gchar *basename;
-	const GdkColor *color = document_get_status_color(doc);
-
-	gtk_tree_store_append(store_openfiles, iter, parent);
-
-	/* check if new parent */
-	if (parent && gtk_tree_model_iter_n_children(GTK_TREE_MODEL(store_openfiles), parent) == 1)
-	{
-		GtkTreePath *path;
-
-		/* expand parent */
-		path = gtk_tree_model_get_path(GTK_TREE_MODEL(store_openfiles), parent);
-		gtk_tree_view_expand_row(GTK_TREE_VIEW(tv.tree_openfiles), path, TRUE);
-		gtk_tree_path_free(path);
-	}
-	basename = g_path_get_basename(DOC_FILENAME(doc));
-	gtk_tree_store_set(store_openfiles, iter, DOCUMENTS_ICON, GTK_STOCK_FILE,
-		DOCUMENTS_SHORTNAME, basename, DOCUMENTS_DOCUMENT, doc, DOCUMENTS_COLOR, color,
-		DOCUMENTS_FILENAME, DOC_FILENAME(doc), -1);
-	g_free(basename);
-}
-
-
-static void openfiles_remove(GeanyDocument *doc)
-{
-	GtkTreeIter *iter = &doc->priv->iter;
-	GtkTreeIter parent;
-
-	if (gtk_tree_model_iter_parent(GTK_TREE_MODEL(store_openfiles), &parent, iter) &&
-		gtk_tree_model_iter_n_children(GTK_TREE_MODEL(store_openfiles), &parent) == 1)
-		gtk_tree_store_remove(store_openfiles, &parent);
-	else
-		gtk_tree_store_remove(store_openfiles, iter);
-}
-
-
-void treeviews_openfiles_update(GeanyDocument *doc)
-{
-	GtkTreeIter *iter = &doc->priv->iter;
-	gchar *fname;
-
-	gtk_tree_model_get(GTK_TREE_MODEL(store_openfiles), iter, DOCUMENTS_FILENAME, &fname, -1);
-
-	if (utils_str_equal(fname, DOC_FILENAME(doc)))
-	{
-		/* just update color */
-		const GdkColor *color = document_get_status_color(doc);
-
-		gtk_tree_store_set(store_openfiles, iter, DOCUMENTS_COLOR, color, -1);
-	}
-	else
-	{
-		/* path has changed, so remove and re-add */
-		GtkTreeSelection *treesel;
-		gboolean sel;
-
-		treesel = gtk_tree_view_get_selection(GTK_TREE_VIEW(tv.tree_openfiles));
-		sel = gtk_tree_selection_iter_is_selected(treesel, &doc->priv->iter);
-		openfiles_remove(doc);
-
-		treeviews_openfiles_add(doc);
-		if (sel)
-			gtk_tree_selection_select_iter(treesel, &doc->priv->iter);
-	}
-	g_free(fname);
-}
-
-
-void treeviews_openfiles_update_all()
-{
-	guint i, page_count;
-	GeanyDocument *doc;
-
-	gtk_tree_store_clear(store_openfiles);
-	page_count = gtk_notebook_get_n_pages(GTK_NOTEBOOK(main_widgets.notebook));
-	for (i = 0; i < page_count; i++)
-	{
-		doc = document_get_from_page(i);
-		if (G_UNLIKELY(doc == NULL))
-			continue;
-
-		treeviews_openfiles_add(doc);
-	}
-}
-
-
-void treeviews_remove_document(GeanyDocument *doc)
-{
-	openfiles_remove(doc);
-
-	if (GTK_IS_WIDGET(doc->priv->tag_tree))
-	{
-		gtk_widget_destroy(doc->priv->tag_tree);
-		if (GTK_IS_TREE_VIEW(doc->priv->tag_tree))
-		{
-			/* Because it was ref'd in treeviews_update_tag_list, it needs unref'ing */
-			g_object_unref((gpointer)doc->priv->tag_tree);
-		}
-		doc->priv->tag_tree = NULL;
-	}
-}
-
-
-static void on_hide_sidebar(void)
-{
-	ui_prefs.sidebar_visible = FALSE;
-	ui_sidebar_show_hide();
-}
-
-
-static gboolean on_sidebar_display_symbol_list_show(GtkWidget *item)
-{
-	gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item),
-		interface_prefs.sidebar_symbol_visible);
-	return FALSE;
-}
-
-
-static gboolean on_sidebar_display_open_files_show(GtkWidget *item)
-{
-	gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item),
-		interface_prefs.sidebar_openfiles_visible);
-	return FALSE;
-}
-
-
-void sidebar_add_common_menu_items(GtkMenu *menu)
-{
-	GtkWidget *item;
-
-	item = gtk_separator_menu_item_new();
-	gtk_widget_show(item);
-	gtk_container_add(GTK_CONTAINER(menu), item);
-
-	item = gtk_check_menu_item_new_with_mnemonic(_("Show S_ymbol List"));
-	gtk_container_add(GTK_CONTAINER(menu), item);
-	g_signal_connect(item, "expose-event",
-			G_CALLBACK(on_sidebar_display_symbol_list_show), NULL);
-	gtk_widget_show(item);
-	g_signal_connect(item, "activate",
-			G_CALLBACK(on_list_symbol_activate), NULL);
-
-	item = gtk_check_menu_item_new_with_mnemonic(_("Show _Document List"));
-	gtk_container_add(GTK_CONTAINER(menu), item);
-	g_signal_connect(item, "expose-event",
-			G_CALLBACK(on_sidebar_display_open_files_show), NULL);
-	gtk_widget_show(item);
-	g_signal_connect(item, "activate",
-			G_CALLBACK(on_list_document_activate), NULL);
-
-	item = gtk_image_menu_item_new_with_mnemonic(_("H_ide Sidebar"));
-	gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item),
-		gtk_image_new_from_stock("gtk-close", GTK_ICON_SIZE_MENU));
-	gtk_widget_show(item);
-	gtk_container_add(GTK_CONTAINER(menu), item);
-	g_signal_connect(item, "activate", G_CALLBACK(on_hide_sidebar), NULL);
-}
-
-
-static void on_openfiles_show_paths_activate(GtkCheckMenuItem *item, gpointer user_data)
-{
-	documents_show_paths = gtk_check_menu_item_get_active(item);
-	treeviews_openfiles_update_all();
-}
-
-
-static void on_list_document_activate(GtkCheckMenuItem *item, gpointer user_data)
-{
-	interface_prefs.sidebar_openfiles_visible = gtk_check_menu_item_get_active(item);
-	ui_sidebar_show_hide();
-}
-
-
-static void on_list_symbol_activate(GtkCheckMenuItem *item, gpointer user_data)
-{
-	interface_prefs.sidebar_symbol_visible = gtk_check_menu_item_get_active(item);
-	ui_sidebar_show_hide();
-}
-
-
-static void create_openfiles_popup_menu(void)
-{
-	GtkWidget *item;
-
-	openfiles_popup_menu = gtk_menu_new();
-
-	item = gtk_image_menu_item_new_from_stock("gtk-close", NULL);
-	gtk_widget_show(item);
-	gtk_container_add(GTK_CONTAINER(openfiles_popup_menu), item);
-	g_signal_connect(item, "activate",
-			G_CALLBACK(on_openfiles_document_action), GINT_TO_POINTER(OPENFILES_ACTION_REMOVE));
-	doc_items.close = item;
-
-	item = gtk_separator_menu_item_new();
-	gtk_widget_show(item);
-	gtk_container_add(GTK_CONTAINER(openfiles_popup_menu), item);
-
-	item = gtk_image_menu_item_new_from_stock("gtk-save", NULL);
-	gtk_widget_show(item);
-	gtk_container_add(GTK_CONTAINER(openfiles_popup_menu), item);
-	g_signal_connect(item, "activate",
-			G_CALLBACK(on_openfiles_document_action), GINT_TO_POINTER(OPENFILES_ACTION_SAVE));
-	doc_items.save = item;
-
-	item = gtk_image_menu_item_new_with_mnemonic(_("_Reload"));
-	gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item),
-		gtk_image_new_from_stock("gtk-revert-to-saved", GTK_ICON_SIZE_MENU));
-	gtk_widget_show(item);
-	gtk_container_add(GTK_CONTAINER(openfiles_popup_menu), item);
-	g_signal_connect(item, "activate",
-			G_CALLBACK(on_openfiles_document_action), GINT_TO_POINTER(OPENFILES_ACTION_RELOAD));
-	doc_items.reload = item;
-
-	item = gtk_separator_menu_item_new();
-	gtk_widget_show(item);
-	gtk_container_add(GTK_CONTAINER(openfiles_popup_menu), item);
-
-	doc_items.show_paths = gtk_check_menu_item_new_with_mnemonic(_("Show _Paths"));
-	gtk_widget_show(doc_items.show_paths);
-	gtk_container_add(GTK_CONTAINER(openfiles_popup_menu), doc_items.show_paths);
-	g_signal_connect(doc_items.show_paths, "activate",
-			G_CALLBACK(on_openfiles_show_paths_activate), NULL);
-
-	sidebar_add_common_menu_items(GTK_MENU(openfiles_popup_menu));
-}
-
-
-static void unfold_parent(GtkTreeIter *iter)
-{
-	GtkTreeIter parent;
-	GtkTreePath *path;
-
-	if (gtk_tree_model_iter_parent(GTK_TREE_MODEL(store_openfiles), &parent, iter))
-	{
-		path = gtk_tree_model_get_path(GTK_TREE_MODEL(store_openfiles), &parent);
-		gtk_tree_view_expand_row(GTK_TREE_VIEW(tv.tree_openfiles), path, TRUE);
-		gtk_tree_path_free(path);
-	}
-}
-
-
-/* compares the given data with the doc pointer from the selected row of openfiles
- * treeview, in case of a match the row is selected and TRUE is returned
- * (called indirectly from gtk_tree_model_foreach()) */
-static gboolean tree_model_find_node(GtkTreeModel *model, GtkTreePath *path,
-		GtkTreeIter *iter, gpointer data)
-{
-	GeanyDocument *doc;
-
-	gtk_tree_model_get(GTK_TREE_MODEL(store_openfiles), iter, DOCUMENTS_DOCUMENT, &doc, -1);
-
-	if (doc == data)
-	{
-		/* unfolding also prevents a strange bug where the selection gets stuck on the parent
-		 * when it is collapsed and then switching documents */
-		unfold_parent(iter);
-		gtk_tree_view_set_cursor(GTK_TREE_VIEW(tv.tree_openfiles), path, NULL, FALSE);
-		return TRUE;
-	}
-	else return FALSE;
-}
-
-
-void treeviews_select_openfiles_item(GeanyDocument *doc)
-{
-	gtk_tree_model_foreach(GTK_TREE_MODEL(store_openfiles), tree_model_find_node, doc);
-}
-
-
-/* callbacks */
-
-static void document_action(GeanyDocument *doc, gint action)
-{
-	if (! DOC_VALID(doc))
-		return;
-
-	switch (action)
-	{
-		case OPENFILES_ACTION_REMOVE:
-		{
-			document_close(doc);
-			break;
-		}
-		case OPENFILES_ACTION_SAVE:
-		{
-			document_save_file(doc, FALSE);
-			break;
-		}
-		case OPENFILES_ACTION_RELOAD:
-		{
-			on_toolbutton_reload_clicked(NULL, NULL);
-			break;
-		}
-	}
-
-}
-
-
-static void on_openfiles_document_action(GtkMenuItem *menuitem, gpointer user_data)
-{
-	GtkTreeIter iter;
-	GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(tv.tree_openfiles));
-	GtkTreeModel *model;
-	GeanyDocument *doc;
-	gint action = GPOINTER_TO_INT(user_data);
-
-	if (gtk_tree_selection_get_selected(selection, &model, &iter))
-	{
-		gtk_tree_model_get(model, &iter, DOCUMENTS_DOCUMENT, &doc, -1);
-		if (doc)
-		{
-			document_action(doc, action);
-		}
-		else
-		{
-			/* parent item selected */
-			GtkTreeIter child;
-			gint i = gtk_tree_model_iter_n_children(model, &iter) - 1;
-
-			while (i >= 0 && gtk_tree_model_iter_nth_child(model, &child, &iter, i))
-			{
-				gtk_tree_model_get(model, &child, DOCUMENTS_DOCUMENT, &doc, -1);
-
-				document_action(doc, action);
-				i--;
-			}
-		}
-	}
-}
-
-
-static void change_focus_to_editor(GeanyDocument *doc)
-{
-	if (may_steal_focus)
-		document_try_focus(doc);
-	may_steal_focus = FALSE;
-}
-
-
-static gboolean on_openfiles_tree_selection_changed(GtkTreeSelection *selection)
-{
-	GtkTreeIter iter;
-	GtkTreeModel *model;
-	GeanyDocument *doc = NULL;
-
-	/* use switch_notebook_page to ignore changing the notebook page because it is already done */
-	if (gtk_tree_selection_get_selected(selection, &model, &iter) && ! ignore_callback)
-	{
-		gtk_tree_model_get(model, &iter, DOCUMENTS_DOCUMENT, &doc, -1);
-		if (! doc)
-			return FALSE;	/* parent */
-
-		/* switch to the doc and grab the focus */
-		gtk_notebook_set_current_page(GTK_NOTEBOOK(main_widgets.notebook),
-			gtk_notebook_page_num(GTK_NOTEBOOK(main_widgets.notebook),
-			(GtkWidget*) doc->editor->sci));
-		change_focus_to_editor(doc);
-	}
-	return FALSE;
-}
-
-
-static gboolean on_taglist_tree_selection_changed(GtkTreeSelection *selection)
-{
-	GtkTreeIter iter;
-	GtkTreeModel *model;
-	gint line = 0;
-
-	if (gtk_tree_selection_get_selected(selection, &model, &iter))
-	{
-		const TMTag *tag;
-
-		gtk_tree_model_get(model, &iter, SYMBOLS_COLUMN_TAG, &tag, -1);
-		if (! tag)
-			return FALSE;
-
-		line = tag->atts.entry.line;
-		if (line > 0)
-		{
-			GeanyDocument *doc = document_get_current();
-
-			if (doc != NULL)
-			{
-				navqueue_goto_line(doc, doc, line);
-				change_focus_to_editor(doc);
-			}
-		}
-	}
-	return FALSE;
-}
-
-
-static gboolean treeviews_key_press_cb(GtkWidget *widget, GdkEventKey *event,
-											 gpointer user_data)
-{
-	may_steal_focus = FALSE;
-	if (event->keyval == GDK_Return ||
-		event->keyval == GDK_ISO_Enter ||
-		event->keyval == GDK_KP_Enter ||
-		event->keyval == GDK_space)
-	{
-		GtkTreeSelection *select = gtk_tree_view_get_selection(GTK_TREE_VIEW(widget));
-		may_steal_focus = TRUE;
-		/* delay the query of selection state because this callback is executed before GTK
-		 * changes the selection (g_signal_connect_after would be better but it doesn't work) */
-		if (widget ==  tv.tree_openfiles) /* tag and doc list have separate handlers */
-			g_idle_add((GSourceFunc) on_openfiles_tree_selection_changed, select);
-		else
-			g_idle_add((GSourceFunc) on_taglist_tree_selection_changed, select);
-	}
-	return FALSE;
-}
-
-
-static gboolean treeviews_button_press_cb(GtkWidget *widget, GdkEventButton *event,
-		G_GNUC_UNUSED gpointer user_data)
-{
-	GtkTreeSelection *selection;
-
-	selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(widget));
-	may_steal_focus = TRUE;
-
-	if (event->type == GDK_2BUTTON_PRESS)
-	{	/* double click on parent node(section) expands/collapses it */
-		GtkTreeModel *model;
-		GtkTreeIter iter;
-
-		if (gtk_tree_selection_get_selected(selection, &model, &iter))
-		{
-			if (gtk_tree_model_iter_has_child(model, &iter))
-			{
-				GtkTreePath *path = gtk_tree_model_get_path(model, &iter);
-
-				if (gtk_tree_view_row_expanded(GTK_TREE_VIEW(widget), path))
-					gtk_tree_view_collapse_row(GTK_TREE_VIEW(widget), path);
-				else
-					gtk_tree_view_expand_row(GTK_TREE_VIEW(widget), path, FALSE);
-
-				gtk_tree_path_free(path);
-				return TRUE;
-			}
-		}
-	}
-	else if (event->button == 1)
-	{	/* allow reclicking of taglist treeview item */
-		/* delay the query of selection state because this callback is executed before GTK
-		 * changes the selection (g_signal_connect_after would be better but it doesn't work) */
-		if (widget == tv.tree_openfiles)
-			g_idle_add((GSourceFunc) on_openfiles_tree_selection_changed, selection);
-		else
-			g_idle_add((GSourceFunc) on_taglist_tree_selection_changed, selection);
-	}
-	else if (event->button == 3)
-	{
-		if (widget == tv.tree_openfiles)
-		{
-			if (!openfiles_popup_menu)
-				create_openfiles_popup_menu();
-
-			/* update menu item sensitivity */
-			documents_menu_update(selection);
-			gtk_menu_popup(GTK_MENU(openfiles_popup_menu), NULL, NULL, NULL, NULL,
-					event->button, event->time);
-		}
-		else
-		{
-			gtk_menu_popup(GTK_MENU(tv.popup_taglist), NULL, NULL, NULL, NULL,
-					event->button, event->time);
-		}
-	}
-	return FALSE;
-}
-
-
-static void documents_menu_update(GtkTreeSelection *selection)
-{
-	GtkTreeModel *model;
-	GtkTreeIter iter;
-	gboolean sel, path;
-	gchar *shortname = NULL;
-	GeanyDocument *doc = NULL;
-
-	/* maybe no selection e.g. if ctrl-click deselected */
-	sel = gtk_tree_selection_get_selected(selection, &model, &iter);
-	if (sel)
-	{
-		gtk_tree_model_get(model, &iter, DOCUMENTS_DOCUMENT, &doc,
-			DOCUMENTS_SHORTNAME, &shortname, -1);
-	}
-	path = NZV(shortname) &&
-		(g_path_is_absolute(shortname) ||
-		(app->project && g_str_has_prefix(shortname, app->project->name)));
-
-	/* can close all, save all (except shortname), but only reload individually ATM */
-	gtk_widget_set_sensitive(doc_items.close, sel);
-	gtk_widget_set_sensitive(doc_items.save, (doc && doc->real_path) || path);
-	gtk_widget_set_sensitive(doc_items.reload, doc && doc->real_path);
-	g_free(shortname);
-
-	gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(doc_items.show_paths),
-		documents_show_paths);
-}
-
-
-GeanyPrefGroup *stash_group = NULL;
-
-static void on_load_settings(void)
-{
-	tag_window = ui_lookup_widget(main_widgets.window, "scrolledwindow2");
-
-	prepare_openfiles();
-	/* note: ui_prefs.sidebar_page is reapplied after plugins are loaded */
-	stash_group_display(stash_group, NULL);
-}
-
-
-static void on_save_settings(void)
-{
-	stash_group_update(stash_group, NULL);
-}
-
-
-void treeviews_init(void)
-{
-	GeanyPrefGroup *group;
-
-	group = stash_group_new(PACKAGE);
-	stash_group_add_boolean(group, &documents_show_paths, "documents_show_paths", TRUE);
-	stash_group_add_widget_property(group, &ui_prefs.sidebar_page, "sidebar_page", GINT_TO_POINTER(0),
-		main_widgets.sidebar_notebook, "page", 0);
-	configuration_add_pref_group(group, FALSE);
-	stash_group = group;
-
-	/* delay building documents treeview until sidebar font has been read */
-	g_signal_connect(geany_object, "load-settings", on_load_settings, NULL);
-	g_signal_connect(geany_object, "save-settings", on_save_settings, NULL);
-}
-
-
-#define WIDGET(w) w && GTK_IS_WIDGET(w)
-
-void treeviews_finalize(void)
-{
-	if (WIDGET(tv.default_tag_tree))
-	{
-		g_object_unref(tv.default_tag_tree);
-		gtk_widget_destroy(tv.default_tag_tree);
-	}
-	if (WIDGET(tv.popup_taglist))
-		gtk_widget_destroy(tv.popup_taglist);
-	if (WIDGET(openfiles_popup_menu))
-		gtk_widget_destroy(openfiles_popup_menu);
-}

Deleted: trunk/src/treeviews.h
===================================================================
--- trunk/src/treeviews.h	2009-09-27 20:31:16 UTC (rev 4251)
+++ trunk/src/treeviews.h	2009-09-28 11:16:59 UTC (rev 4252)
@@ -1,67 +0,0 @@
-/*
- *      treeviews.h - this file is part of Geany, a fast and lightweight IDE
- *
- *      Copyright 2005-2009 Enrico Tröger <enrico(dot)troeger(at)uvena(dot)de>
- *      Copyright 2006-2009 Nick Treleaven <nick(dot)treleaven(at)btinternet(dot)com>
- *
- *      This program is free software; you can redistribute it and/or modify
- *      it under the terms of the GNU General Public License as published by
- *      the Free Software Foundation; either version 2 of the License, or
- *      (at your option) any later version.
- *
- *      This program is distributed in the hope that it will be useful,
- *      but WITHOUT ANY WARRANTY; without even the implied warranty of
- *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *      GNU General Public License for more details.
- *
- *      You should have received a copy of the GNU General Public License
- *      along with this program; if not, write to the Free Software
- *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * $Id$
- */
-
-
-
-#ifndef GEANY_TREEVIEWS_H
-#define GEANY_TREEVIEWS_H 1
-
-
-typedef struct SidebarTreeviews
-{
-	GtkWidget		*tree_openfiles;
-	GtkWidget		*default_tag_tree;
-	GtkWidget		*popup_taglist;
-}
-SidebarTreeviews;
-
-extern SidebarTreeviews tv;
-
-enum
-{
-	SYMBOLS_COLUMN_ICON,
-	SYMBOLS_COLUMN_NAME,
-	SYMBOLS_COLUMN_TAG,
-	SYMBOLS_COLUMN_TOOLTIP,
-	SYMBOLS_N_COLUMNS
-};
-
-void treeviews_init(void);
-
-void treeviews_finalize(void);
-
-void treeviews_update_tag_list(GeanyDocument *doc, gboolean update);
-
-void treeviews_openfiles_add(GeanyDocument *doc);
-
-void treeviews_openfiles_update(GeanyDocument *doc);
-
-void treeviews_openfiles_update_all(void);
-
-void treeviews_select_openfiles_item(GeanyDocument *doc);
-
-void treeviews_remove_document(GeanyDocument *doc);
-
-void sidebar_add_common_menu_items(GtkMenu *menu);
-
-#endif

Modified: trunk/src/ui_utils.c
===================================================================
--- trunk/src/ui_utils.c	2009-09-27 20:31:16 UTC (rev 4251)
+++ trunk/src/ui_utils.c	2009-09-28 11:16:59 UTC (rev 4252)
@@ -41,7 +41,7 @@
 #include "callbacks.h"
 #include "encodings.h"
 #include "images.c"
-#include "treeviews.h"
+#include "sidebar.h"
 #include "win32.h"
 #include "project.h"
 #include "editor.h"
@@ -1442,7 +1442,7 @@
 	gtk_widget_modify_fg(doc->priv->tab_label, GTK_STATE_NORMAL, color);
 	gtk_widget_modify_fg(doc->priv->tab_label, GTK_STATE_ACTIVE, color);
 
-	treeviews_openfiles_update(doc);
+	sidebar_openfiles_update(doc);
 }
 
 

Modified: trunk/wscript
===================================================================
--- trunk/wscript	2009-09-27 20:31:16 UTC (rev 4251)
+++ trunk/wscript	2009-09-28 11:16:59 UTC (rev 4252)
@@ -111,7 +111,7 @@
 	'src/plugins.c', 'src/pluginutils.c', 'src/prefix.c', 'src/prefs.c', 'src/printing.c', 'src/project.c',
 	'src/sciwrappers.c', 'src/search.c', 'src/socket.c', 'src/stash.c',
 	'src/symbols.c',
-	'src/templates.c', 'src/toolbar.c', 'src/tools.c', 'src/treeviews.c',
+	'src/templates.c', 'src/toolbar.c', 'src/tools.c', 'src/sidebar.c',
 	'src/ui_utils.c', 'src/utils.c' ]
 
 


This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.



More information about the Commits mailing list