2007-10-22 12:42:19 +00:00
|
|
|
/*
|
|
|
|
* filebrowser.c - this file is part of Geany, a fast and lightweight IDE
|
|
|
|
*
|
2012-06-18 01:13:05 +02:00
|
|
|
* Copyright 2007-2012 Enrico Tröger <enrico(dot)troeger(at)uvena(dot)de>
|
|
|
|
* Copyright 2007-2012 Nick Treleaven <nick(dot)treleaven(at)btinternet(dot)com>
|
2007-10-22 12:42:19 +00:00
|
|
|
*
|
|
|
|
* 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.
|
|
|
|
*
|
2012-08-24 19:25:57 +02:00
|
|
|
* 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.
|
2007-10-22 12:42:19 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
/* Sidebar file browser plugin. */
|
|
|
|
|
2011-08-03 15:20:26 +00:00
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
# include "config.h"
|
|
|
|
#endif
|
|
|
|
|
2009-07-14 15:06:20 +00:00
|
|
|
#include "geanyplugin.h"
|
2012-09-15 23:40:13 +02:00
|
|
|
#include "gtkcompat.h"
|
2008-05-23 17:08:58 +00:00
|
|
|
#include <string.h>
|
2007-10-22 12:42:19 +00:00
|
|
|
|
|
|
|
#include <gdk/gdkkeysyms.h>
|
|
|
|
|
2010-05-16 17:44:51 +00:00
|
|
|
#ifdef G_OS_WIN32
|
|
|
|
# include <windows.h>
|
2014-10-26 15:06:16 +00:00
|
|
|
|
|
|
|
# define OPEN_CMD "explorer \"%d\""
|
2015-01-08 22:34:14 +01:00
|
|
|
#elif defined(__APPLE__)
|
|
|
|
# define OPEN_CMD "open \"%d\""
|
2014-10-26 15:06:16 +00:00
|
|
|
#else
|
|
|
|
# define OPEN_CMD "nautilus \"%d\""
|
2010-05-16 17:44:51 +00:00
|
|
|
#endif
|
2007-10-22 12:42:19 +00:00
|
|
|
|
2010-06-18 12:22:00 +00:00
|
|
|
GeanyPlugin *geany_plugin;
|
|
|
|
GeanyData *geany_data;
|
|
|
|
GeanyFunctions *geany_functions;
|
2007-10-22 12:42:19 +00:00
|
|
|
|
|
|
|
|
2010-06-18 12:22:00 +00:00
|
|
|
PLUGIN_VERSION_CHECK(GEANY_API_VERSION)
|
2007-10-22 12:42:19 +00:00
|
|
|
|
2008-05-23 17:08:58 +00:00
|
|
|
PLUGIN_SET_INFO(_("File Browser"), _("Adds a file browser tab to the sidebar."), VERSION,
|
2007-11-20 18:15:46 +00:00
|
|
|
_("The Geany developer team"))
|
2007-10-22 12:42:19 +00:00
|
|
|
|
|
|
|
|
2008-04-03 16:06:41 +00:00
|
|
|
/* Keybinding(s) */
|
|
|
|
enum
|
|
|
|
{
|
|
|
|
KB_FOCUS_FILE_LIST,
|
|
|
|
KB_FOCUS_PATH_ENTRY,
|
|
|
|
KB_COUNT
|
|
|
|
};
|
|
|
|
|
|
|
|
PLUGIN_KEY_GROUP(file_browser, KB_COUNT)
|
|
|
|
|
|
|
|
|
2007-10-22 12:42:19 +00:00
|
|
|
enum
|
|
|
|
{
|
|
|
|
FILEVIEW_COLUMN_ICON = 0,
|
|
|
|
FILEVIEW_COLUMN_NAME,
|
2009-01-30 16:12:25 +00:00
|
|
|
FILEVIEW_COLUMN_FILENAME, /* the full filename, including path for display as tooltip */
|
2008-02-20 11:24:23 +00:00
|
|
|
FILEVIEW_N_COLUMNS
|
2007-10-22 12:42:19 +00:00
|
|
|
};
|
|
|
|
|
2009-02-01 18:48:09 +00:00
|
|
|
static gboolean fb_set_project_base_path = FALSE;
|
2010-06-18 12:22:00 +00:00
|
|
|
static gboolean fb_follow_path = FALSE;
|
2007-10-22 12:42:19 +00:00
|
|
|
static gboolean show_hidden_files = FALSE;
|
|
|
|
static gboolean hide_object_files = TRUE;
|
|
|
|
|
2010-06-18 12:22:00 +00:00
|
|
|
static GtkWidget *file_view_vbox;
|
|
|
|
static GtkWidget *file_view;
|
|
|
|
static GtkListStore *file_store;
|
|
|
|
static GtkTreeIter *last_dir_iter = NULL;
|
|
|
|
static GtkEntryCompletion *entry_completion = NULL;
|
2007-10-22 12:42:19 +00:00
|
|
|
|
2011-03-24 16:34:10 +00:00
|
|
|
static GtkWidget *filter_combo;
|
2010-06-18 12:22:00 +00:00
|
|
|
static GtkWidget *filter_entry;
|
|
|
|
static GtkWidget *path_combo;
|
|
|
|
static GtkWidget *path_entry;
|
|
|
|
static gchar *current_dir = NULL; /* in locale-encoding */
|
|
|
|
static gchar *open_cmd; /* in locale-encoding */
|
|
|
|
static gchar *config_file;
|
2011-02-21 19:09:34 +00:00
|
|
|
static gchar **filter = NULL;
|
2011-03-31 15:01:24 +00:00
|
|
|
static gchar *hidden_file_extensions = NULL;
|
2007-10-22 12:42:19 +00:00
|
|
|
|
2010-06-18 12:22:00 +00:00
|
|
|
static gint page_number = 0;
|
2008-12-07 19:12:27 +00:00
|
|
|
|
2007-12-28 17:35:58 +00:00
|
|
|
static struct
|
|
|
|
{
|
|
|
|
GtkWidget *open;
|
|
|
|
GtkWidget *open_external;
|
|
|
|
GtkWidget *find_in_files;
|
2010-04-19 12:03:32 +00:00
|
|
|
GtkWidget *show_hidden_files;
|
2007-12-28 17:35:58 +00:00
|
|
|
} popup_items;
|
|
|
|
|
2007-10-22 12:42:19 +00:00
|
|
|
|
2009-02-01 18:48:09 +00:00
|
|
|
static void project_change_cb(GObject *obj, GKeyFile *config, gpointer data);
|
|
|
|
|
2011-04-11 12:07:19 +00:00
|
|
|
/* note: other callbacks connected in plugin_init */
|
2009-02-01 18:48:09 +00:00
|
|
|
PluginCallback plugin_callbacks[] =
|
|
|
|
{
|
|
|
|
{ "project-open", (GCallback) &project_change_cb, TRUE, NULL },
|
|
|
|
{ "project-save", (GCallback) &project_change_cb, TRUE, NULL },
|
|
|
|
{ NULL, NULL, FALSE, NULL }
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2010-05-16 17:44:51 +00:00
|
|
|
#ifdef G_OS_WIN32
|
|
|
|
static gboolean win32_check_hidden(const gchar *filename)
|
|
|
|
{
|
|
|
|
DWORD attrs;
|
|
|
|
static wchar_t w_filename[MAX_PATH];
|
|
|
|
MultiByteToWideChar(CP_UTF8, 0, filename, -1, w_filename, sizeof(w_filename));
|
|
|
|
attrs = GetFileAttributesW(w_filename);
|
|
|
|
if (attrs != INVALID_FILE_ATTRIBUTES && attrs & FILE_ATTRIBUTE_HIDDEN)
|
|
|
|
return TRUE;
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
2008-02-27 13:17:29 +00:00
|
|
|
/* Returns: whether name should be hidden. */
|
2010-05-16 17:44:51 +00:00
|
|
|
static gboolean check_hidden(const gchar *filename, const gchar *base_name)
|
2007-10-22 12:42:19 +00:00
|
|
|
{
|
|
|
|
gsize len;
|
|
|
|
|
2010-05-16 17:44:51 +00:00
|
|
|
#ifdef G_OS_WIN32
|
|
|
|
if (win32_check_hidden(filename))
|
|
|
|
return TRUE;
|
|
|
|
#else
|
2007-10-28 20:54:25 +00:00
|
|
|
if (base_name[0] == '.')
|
2007-10-22 12:42:19 +00:00
|
|
|
return TRUE;
|
2010-05-16 17:44:51 +00:00
|
|
|
#endif
|
2007-10-22 12:42:19 +00:00
|
|
|
|
2007-10-28 20:54:25 +00:00
|
|
|
len = strlen(base_name);
|
2011-03-31 17:58:01 +00:00
|
|
|
return base_name[len - 1] == '~';
|
|
|
|
}
|
2007-10-22 12:42:19 +00:00
|
|
|
|
|
|
|
|
2011-03-31 17:58:01 +00:00
|
|
|
static gboolean check_object(const gchar *base_name)
|
|
|
|
{
|
|
|
|
gboolean ret = FALSE;
|
|
|
|
gchar **ptr;
|
|
|
|
gchar **exts = g_strsplit(hidden_file_extensions, " ", -1);
|
|
|
|
|
|
|
|
foreach_strv(ptr, exts)
|
|
|
|
{
|
|
|
|
if (g_str_has_suffix(base_name, *ptr))
|
2007-10-22 12:42:19 +00:00
|
|
|
{
|
2011-03-31 17:58:01 +00:00
|
|
|
ret = TRUE;
|
|
|
|
break;
|
2007-10-22 12:42:19 +00:00
|
|
|
}
|
|
|
|
}
|
2011-03-31 17:58:01 +00:00
|
|
|
g_strfreev(exts);
|
2011-03-31 15:01:24 +00:00
|
|
|
return ret;
|
2007-10-22 12:42:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-09-17 14:45:17 +00:00
|
|
|
/* Returns: whether filename should be removed. */
|
2008-04-22 15:14:30 +00:00
|
|
|
static gboolean check_filtered(const gchar *base_name)
|
|
|
|
{
|
2011-02-21 19:09:34 +00:00
|
|
|
gchar **filter_item;
|
2011-03-22 17:26:47 +00:00
|
|
|
|
2008-04-22 15:14:30 +00:00
|
|
|
if (filter == NULL)
|
|
|
|
return FALSE;
|
2011-03-22 17:26:47 +00:00
|
|
|
|
2011-03-31 17:28:03 +00:00
|
|
|
foreach_strv(filter_item, filter)
|
2008-04-22 15:14:30 +00:00
|
|
|
{
|
2011-03-31 17:28:03 +00:00
|
|
|
if (utils_str_equal(*filter_item, "*") || g_pattern_match_simple(*filter_item, base_name))
|
2011-02-21 19:09:34 +00:00
|
|
|
{
|
|
|
|
return FALSE;
|
|
|
|
}
|
2008-04-22 15:14:30 +00:00
|
|
|
}
|
2011-02-21 19:09:34 +00:00
|
|
|
return TRUE;
|
2008-04-22 15:14:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-02-27 13:17:29 +00:00
|
|
|
/* name is in locale encoding */
|
2007-10-22 12:42:19 +00:00
|
|
|
static void add_item(const gchar *name)
|
|
|
|
{
|
|
|
|
GtkTreeIter iter;
|
2010-04-25 17:43:09 +00:00
|
|
|
gchar *fname, *utf8_name, *utf8_fullname;
|
|
|
|
const gchar *sep;
|
2007-10-22 12:42:19 +00:00
|
|
|
gboolean dir;
|
|
|
|
|
2013-08-11 14:10:57 +01:00
|
|
|
if (G_UNLIKELY(EMPTY(name)))
|
2011-03-31 17:58:01 +00:00
|
|
|
return;
|
|
|
|
|
|
|
|
/* root directory doesn't need separator */
|
2009-01-30 16:12:25 +00:00
|
|
|
sep = (utils_str_equal(current_dir, "/")) ? "" : G_DIR_SEPARATOR_S;
|
|
|
|
fname = g_strconcat(current_dir, sep, name, NULL);
|
2007-10-22 12:42:19 +00:00
|
|
|
dir = g_file_test(fname, G_FILE_TEST_IS_DIR);
|
2009-01-30 16:12:25 +00:00
|
|
|
utf8_fullname = utils_get_locale_from_utf8(fname);
|
2009-05-08 16:13:29 +00:00
|
|
|
utf8_name = utils_get_utf8_from_locale(name);
|
2007-10-22 12:42:19 +00:00
|
|
|
g_free(fname);
|
|
|
|
|
2011-03-31 17:58:01 +00:00
|
|
|
if (! show_hidden_files && check_hidden(utf8_fullname, utf8_name))
|
|
|
|
goto done;
|
2010-05-16 17:44:51 +00:00
|
|
|
|
2007-10-22 12:42:19 +00:00
|
|
|
if (dir)
|
|
|
|
{
|
|
|
|
if (last_dir_iter == NULL)
|
|
|
|
gtk_list_store_prepend(file_store, &iter);
|
|
|
|
else
|
|
|
|
{
|
|
|
|
gtk_list_store_insert_after(file_store, &iter, last_dir_iter);
|
|
|
|
gtk_tree_iter_free(last_dir_iter);
|
|
|
|
}
|
|
|
|
last_dir_iter = gtk_tree_iter_copy(&iter);
|
|
|
|
}
|
|
|
|
else
|
2009-05-08 16:13:29 +00:00
|
|
|
{
|
2011-03-31 17:58:01 +00:00
|
|
|
if (! show_hidden_files && hide_object_files && check_object(utf8_name))
|
|
|
|
goto done;
|
2009-05-08 16:13:29 +00:00
|
|
|
if (check_filtered(utf8_name))
|
2011-03-31 17:58:01 +00:00
|
|
|
goto done;
|
|
|
|
|
2007-10-22 12:42:19 +00:00
|
|
|
gtk_list_store_append(file_store, &iter);
|
2009-05-08 16:13:29 +00:00
|
|
|
}
|
2007-10-22 12:42:19 +00:00
|
|
|
gtk_list_store_set(file_store, &iter,
|
|
|
|
FILEVIEW_COLUMN_ICON, (dir) ? GTK_STOCK_DIRECTORY : GTK_STOCK_FILE,
|
2009-01-30 16:12:25 +00:00
|
|
|
FILEVIEW_COLUMN_NAME, utf8_name,
|
|
|
|
FILEVIEW_COLUMN_FILENAME, utf8_fullname,
|
|
|
|
-1);
|
2011-03-31 17:58:01 +00:00
|
|
|
done:
|
2007-10-22 12:42:19 +00:00
|
|
|
g_free(utf8_name);
|
2009-01-30 16:12:25 +00:00
|
|
|
g_free(utf8_fullname);
|
2007-10-22 12:42:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-02-27 13:17:29 +00:00
|
|
|
/* adds ".." to the start of the file list */
|
2008-02-20 11:24:23 +00:00
|
|
|
static void add_top_level_entry(void)
|
2007-12-04 13:25:41 +00:00
|
|
|
{
|
|
|
|
GtkTreeIter iter;
|
2009-01-30 16:12:25 +00:00
|
|
|
gchar *utf8_dir;
|
2007-12-04 13:25:41 +00:00
|
|
|
|
2013-08-11 14:10:57 +01:00
|
|
|
if (EMPTY(g_path_skip_root(current_dir)))
|
2008-07-15 14:50:06 +00:00
|
|
|
return; /* ignore 'C:\' or '/' */
|
2007-12-04 13:25:41 +00:00
|
|
|
|
2009-01-30 16:12:25 +00:00
|
|
|
utf8_dir = g_path_get_dirname(current_dir);
|
2012-01-25 16:26:16 +00:00
|
|
|
SETPTR(utf8_dir, utils_get_utf8_from_locale(utf8_dir));
|
2009-01-30 16:12:25 +00:00
|
|
|
|
2007-12-04 13:25:41 +00:00
|
|
|
gtk_list_store_prepend(file_store, &iter);
|
|
|
|
last_dir_iter = gtk_tree_iter_copy(&iter);
|
|
|
|
|
|
|
|
gtk_list_store_set(file_store, &iter,
|
2009-01-30 16:12:25 +00:00
|
|
|
FILEVIEW_COLUMN_ICON, GTK_STOCK_DIRECTORY,
|
|
|
|
FILEVIEW_COLUMN_NAME, "..",
|
|
|
|
FILEVIEW_COLUMN_FILENAME, utf8_dir,
|
|
|
|
-1);
|
|
|
|
g_free(utf8_dir);
|
2007-12-04 13:25:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-02-20 11:24:23 +00:00
|
|
|
static void clear(void)
|
2007-10-22 12:42:19 +00:00
|
|
|
{
|
|
|
|
gtk_list_store_clear(file_store);
|
|
|
|
|
2008-02-27 13:17:29 +00:00
|
|
|
/* reset the directory item pointer */
|
2007-10-22 12:42:19 +00:00
|
|
|
if (last_dir_iter != NULL)
|
|
|
|
gtk_tree_iter_free(last_dir_iter);
|
|
|
|
last_dir_iter = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-02-27 13:17:29 +00:00
|
|
|
/* recreate the tree model from current_dir. */
|
2008-02-20 11:24:23 +00:00
|
|
|
static void refresh(void)
|
2007-10-22 12:42:19 +00:00
|
|
|
{
|
|
|
|
gchar *utf8_dir;
|
2009-09-22 17:53:07 +00:00
|
|
|
GSList *list, *node;
|
2007-10-22 12:42:19 +00:00
|
|
|
|
2008-02-27 13:17:29 +00:00
|
|
|
/* don't clear when the new path doesn't exist */
|
2007-12-02 10:52:19 +00:00
|
|
|
if (! g_file_test(current_dir, G_FILE_TEST_EXISTS))
|
|
|
|
return;
|
|
|
|
|
2007-10-22 12:42:19 +00:00
|
|
|
clear();
|
|
|
|
|
2008-12-04 17:05:36 +00:00
|
|
|
utf8_dir = utils_get_utf8_from_locale(current_dir);
|
2007-10-22 12:42:19 +00:00
|
|
|
gtk_entry_set_text(GTK_ENTRY(path_entry), utf8_dir);
|
2012-01-03 16:29:32 +00:00
|
|
|
gtk_widget_set_tooltip_text(path_entry, utf8_dir);
|
2012-09-15 23:40:13 +02:00
|
|
|
ui_combo_box_add_to_history(GTK_COMBO_BOX_TEXT(path_combo), utf8_dir, 0);
|
2007-10-22 12:42:19 +00:00
|
|
|
g_free(utf8_dir);
|
|
|
|
|
2008-07-15 14:50:06 +00:00
|
|
|
add_top_level_entry(); /* ".." item */
|
|
|
|
|
2008-12-04 17:05:36 +00:00
|
|
|
list = utils_get_file_list(current_dir, NULL, NULL);
|
2007-10-22 12:42:19 +00:00
|
|
|
if (list != NULL)
|
|
|
|
{
|
2010-06-18 14:20:10 +00:00
|
|
|
/* free filenames as we go through the list */
|
|
|
|
foreach_slist(node, list)
|
2009-09-17 14:45:17 +00:00
|
|
|
{
|
|
|
|
gchar *fname = node->data;
|
|
|
|
|
|
|
|
add_item(fname);
|
|
|
|
g_free(fname);
|
|
|
|
}
|
2010-06-18 14:20:10 +00:00
|
|
|
g_slist_free(list);
|
2007-10-22 12:42:19 +00:00
|
|
|
}
|
2009-09-17 14:45:17 +00:00
|
|
|
gtk_entry_completion_set_model(entry_completion, GTK_TREE_MODEL(file_store));
|
2007-10-22 12:42:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-02-20 11:24:23 +00:00
|
|
|
static void on_go_home(void)
|
2007-10-29 17:15:03 +00:00
|
|
|
{
|
2012-01-25 16:26:16 +00:00
|
|
|
SETPTR(current_dir, g_strdup(g_get_home_dir()));
|
2007-10-29 17:15:03 +00:00
|
|
|
refresh();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-07-07 12:30:47 +00:00
|
|
|
/* TODO: use utils_get_default_dir_utf8() */
|
2008-02-20 11:24:23 +00:00
|
|
|
static gchar *get_default_dir(void)
|
2007-11-13 16:41:59 +00:00
|
|
|
{
|
|
|
|
const gchar *dir = NULL;
|
2008-07-07 16:16:18 +00:00
|
|
|
GeanyProject *project = geany->app->project;
|
2007-11-13 16:41:59 +00:00
|
|
|
|
|
|
|
if (project)
|
|
|
|
dir = project->base_path;
|
2009-04-24 19:31:23 +00:00
|
|
|
else
|
|
|
|
dir = geany->prefs->default_open_path;
|
|
|
|
|
2013-08-11 14:10:57 +01:00
|
|
|
if (!EMPTY(dir))
|
2008-12-04 17:05:36 +00:00
|
|
|
return utils_get_locale_from_utf8(dir);
|
2007-11-13 16:41:59 +00:00
|
|
|
|
|
|
|
return g_get_current_dir();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-02-20 11:24:23 +00:00
|
|
|
static void on_current_path(void)
|
2007-10-22 12:42:19 +00:00
|
|
|
{
|
|
|
|
gchar *fname;
|
|
|
|
gchar *dir;
|
2008-12-04 17:05:36 +00:00
|
|
|
GeanyDocument *doc = document_get_current();
|
2007-10-22 12:42:19 +00:00
|
|
|
|
2008-06-12 20:09:57 +00:00
|
|
|
if (doc == NULL || doc->file_name == NULL || ! g_path_is_absolute(doc->file_name))
|
2007-10-24 11:02:43 +00:00
|
|
|
{
|
2012-01-25 16:26:16 +00:00
|
|
|
SETPTR(current_dir, get_default_dir());
|
2007-11-13 16:41:59 +00:00
|
|
|
refresh();
|
2007-10-29 17:15:03 +00:00
|
|
|
return;
|
2007-10-24 11:02:43 +00:00
|
|
|
}
|
2008-06-12 20:09:57 +00:00
|
|
|
fname = doc->file_name;
|
2008-12-04 17:05:36 +00:00
|
|
|
fname = utils_get_locale_from_utf8(fname);
|
2007-10-29 17:15:03 +00:00
|
|
|
dir = g_path_get_dirname(fname);
|
|
|
|
g_free(fname);
|
2007-10-22 12:42:19 +00:00
|
|
|
|
2012-01-25 16:26:16 +00:00
|
|
|
SETPTR(current_dir, dir);
|
2007-10-22 12:42:19 +00:00
|
|
|
refresh();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-02-20 11:24:23 +00:00
|
|
|
static void on_go_up(void)
|
2007-12-04 13:25:41 +00:00
|
|
|
{
|
2010-05-16 17:45:06 +00:00
|
|
|
gsize len = strlen(current_dir);
|
|
|
|
if (current_dir[len-1] == G_DIR_SEPARATOR)
|
|
|
|
current_dir[len-1] = '\0';
|
2008-02-27 13:17:29 +00:00
|
|
|
/* remove the highest directory part (which becomes the basename of current_dir) */
|
2012-01-25 16:26:16 +00:00
|
|
|
SETPTR(current_dir, g_path_get_dirname(current_dir));
|
2007-12-04 13:25:41 +00:00
|
|
|
refresh();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-12-28 17:02:07 +00:00
|
|
|
static gboolean check_single_selection(GtkTreeSelection *treesel)
|
|
|
|
{
|
|
|
|
if (gtk_tree_selection_count_selected_rows(treesel) == 1)
|
|
|
|
return TRUE;
|
|
|
|
|
2008-12-04 17:05:36 +00:00
|
|
|
ui_set_statusbar(FALSE, _("Too many items selected!"));
|
2007-12-28 17:02:07 +00:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Returns: TRUE if at least one of selected_items is a folder. */
|
|
|
|
static gboolean is_folder_selected(GList *selected_items)
|
2007-10-22 12:42:19 +00:00
|
|
|
{
|
|
|
|
GList *item;
|
|
|
|
GtkTreeModel *model = GTK_TREE_MODEL(file_store);
|
|
|
|
gboolean dir_found = FALSE;
|
|
|
|
|
2007-12-28 17:02:07 +00:00
|
|
|
for (item = selected_items; item != NULL; item = g_list_next(item))
|
2007-10-22 12:42:19 +00:00
|
|
|
{
|
|
|
|
gchar *icon;
|
2007-12-28 17:02:07 +00:00
|
|
|
GtkTreeIter iter;
|
|
|
|
GtkTreePath *treepath;
|
2007-10-22 12:42:19 +00:00
|
|
|
|
|
|
|
treepath = (GtkTreePath*) item->data;
|
|
|
|
gtk_tree_model_get_iter(model, &iter, treepath);
|
|
|
|
gtk_tree_model_get(model, &iter, FILEVIEW_COLUMN_ICON, &icon, -1);
|
|
|
|
|
2008-12-04 17:05:36 +00:00
|
|
|
if (utils_str_equal(icon, GTK_STOCK_DIRECTORY))
|
2007-10-22 12:42:19 +00:00
|
|
|
{
|
|
|
|
dir_found = TRUE;
|
|
|
|
g_free(icon);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
g_free(icon);
|
|
|
|
}
|
2007-12-28 17:02:07 +00:00
|
|
|
return dir_found;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Returns: the full filename in locale encoding. */
|
|
|
|
static gchar *get_tree_path_filename(GtkTreePath *treepath)
|
|
|
|
{
|
|
|
|
GtkTreeModel *model = GTK_TREE_MODEL(file_store);
|
|
|
|
GtkTreeIter iter;
|
|
|
|
gchar *name, *fname;
|
|
|
|
|
|
|
|
gtk_tree_model_get_iter(model, &iter, treepath);
|
2009-01-30 16:12:25 +00:00
|
|
|
gtk_tree_model_get(model, &iter, FILEVIEW_COLUMN_FILENAME, &name, -1);
|
2007-10-22 12:42:19 +00:00
|
|
|
|
2009-01-30 16:12:25 +00:00
|
|
|
fname = utils_get_locale_from_utf8(name);
|
2007-12-28 17:02:07 +00:00
|
|
|
g_free(name);
|
2007-10-22 12:42:19 +00:00
|
|
|
|
2007-12-28 17:02:07 +00:00
|
|
|
return fname;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void open_external(const gchar *fname, gboolean dir_found)
|
|
|
|
{
|
|
|
|
gchar *cmd;
|
|
|
|
gchar *locale_cmd;
|
|
|
|
gchar *dir;
|
|
|
|
GString *cmd_str = g_string_new(open_cmd);
|
|
|
|
GError *error = NULL;
|
|
|
|
|
|
|
|
if (! dir_found)
|
|
|
|
dir = g_path_get_dirname(fname);
|
|
|
|
else
|
|
|
|
dir = g_strdup(fname);
|
|
|
|
|
2008-12-04 17:05:36 +00:00
|
|
|
utils_string_replace_all(cmd_str, "%f", fname);
|
|
|
|
utils_string_replace_all(cmd_str, "%d", dir);
|
2007-12-28 17:02:07 +00:00
|
|
|
|
|
|
|
cmd = g_string_free(cmd_str, FALSE);
|
2008-12-04 17:05:36 +00:00
|
|
|
locale_cmd = utils_get_locale_from_utf8(cmd);
|
2007-12-28 17:02:07 +00:00
|
|
|
if (! g_spawn_command_line_async(locale_cmd, &error))
|
2007-10-22 12:42:19 +00:00
|
|
|
{
|
2007-12-28 17:02:07 +00:00
|
|
|
gchar *c = strchr(cmd, ' ');
|
|
|
|
|
|
|
|
if (c != NULL)
|
|
|
|
*c = '\0';
|
2008-12-04 17:05:36 +00:00
|
|
|
ui_set_statusbar(TRUE,
|
2007-12-28 17:02:07 +00:00
|
|
|
_("Could not execute configured external command '%s' (%s)."),
|
|
|
|
cmd, error->message);
|
|
|
|
g_error_free(error);
|
|
|
|
}
|
|
|
|
g_free(locale_cmd);
|
|
|
|
g_free(cmd);
|
|
|
|
g_free(dir);
|
|
|
|
}
|
2007-10-22 12:42:19 +00:00
|
|
|
|
|
|
|
|
2007-12-28 17:02:07 +00:00
|
|
|
static void on_external_open(GtkMenuItem *menuitem, gpointer user_data)
|
|
|
|
{
|
|
|
|
GtkTreeSelection *treesel;
|
|
|
|
GtkTreeModel *model;
|
|
|
|
GList *list;
|
|
|
|
gboolean dir_found;
|
2007-10-22 12:42:19 +00:00
|
|
|
|
2007-12-28 17:02:07 +00:00
|
|
|
treesel = gtk_tree_view_get_selection(GTK_TREE_VIEW(file_view));
|
|
|
|
|
|
|
|
list = gtk_tree_selection_get_selected_rows(treesel, &model);
|
|
|
|
dir_found = is_folder_selected(list);
|
|
|
|
|
|
|
|
if (! dir_found || check_single_selection(treesel))
|
|
|
|
{
|
|
|
|
GList *item;
|
|
|
|
|
|
|
|
for (item = list; item != NULL; item = g_list_next(item))
|
2007-10-22 12:42:19 +00:00
|
|
|
{
|
2007-12-28 17:02:07 +00:00
|
|
|
GtkTreePath *treepath = item->data;
|
|
|
|
gchar *fname = get_tree_path_filename(treepath);
|
|
|
|
|
|
|
|
open_external(fname, dir_found);
|
2007-10-22 12:42:19 +00:00
|
|
|
g_free(fname);
|
|
|
|
}
|
|
|
|
}
|
2007-12-28 17:02:07 +00:00
|
|
|
|
|
|
|
g_list_foreach(list, (GFunc) gtk_tree_path_free, NULL);
|
|
|
|
g_list_free(list);
|
2007-10-22 12:42:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-12-04 17:05:36 +00:00
|
|
|
/* We use document_open_files() as it's more efficient. */
|
2010-03-07 18:48:12 +00:00
|
|
|
static void open_selected_files(GList *list, gboolean do_not_focus)
|
2007-12-28 17:02:07 +00:00
|
|
|
{
|
2008-01-02 13:39:53 +00:00
|
|
|
GSList *files = NULL;
|
2007-12-28 17:02:07 +00:00
|
|
|
GList *item;
|
2010-03-07 18:43:31 +00:00
|
|
|
GeanyDocument *doc;
|
2007-12-28 17:02:07 +00:00
|
|
|
|
|
|
|
for (item = list; item != NULL; item = g_list_next(item))
|
|
|
|
{
|
|
|
|
GtkTreePath *treepath = item->data;
|
|
|
|
gchar *fname = get_tree_path_filename(treepath);
|
|
|
|
|
2011-03-10 22:27:04 +00:00
|
|
|
files = g_slist_prepend(files, fname);
|
2007-12-28 17:02:07 +00:00
|
|
|
}
|
2011-03-10 22:27:04 +00:00
|
|
|
files = g_slist_reverse(files);
|
2008-12-04 17:05:36 +00:00
|
|
|
document_open_files(files, FALSE, NULL, NULL);
|
2010-03-07 18:43:31 +00:00
|
|
|
doc = document_get_current();
|
2010-03-07 18:48:12 +00:00
|
|
|
if (doc != NULL && ! do_not_focus)
|
2010-03-07 18:43:31 +00:00
|
|
|
keybindings_send_command(GEANY_KEY_GROUP_FOCUS, GEANY_KEYS_FOCUS_EDITOR);
|
|
|
|
|
2008-02-27 13:17:29 +00:00
|
|
|
g_slist_foreach(files, (GFunc) g_free, NULL); /* free filenames */
|
2008-01-02 13:39:53 +00:00
|
|
|
g_slist_free(files);
|
2007-12-28 17:02:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void open_folder(GtkTreePath *treepath)
|
|
|
|
{
|
|
|
|
gchar *fname = get_tree_path_filename(treepath);
|
|
|
|
|
2012-01-25 16:26:16 +00:00
|
|
|
SETPTR(current_dir, fname);
|
2007-12-28 17:02:07 +00:00
|
|
|
refresh();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void on_open_clicked(GtkMenuItem *menuitem, gpointer user_data)
|
2007-12-02 10:52:19 +00:00
|
|
|
{
|
|
|
|
GtkTreeSelection *treesel;
|
|
|
|
GtkTreeModel *model;
|
|
|
|
GList *list;
|
2007-12-28 17:02:07 +00:00
|
|
|
gboolean dir_found;
|
2007-12-02 10:52:19 +00:00
|
|
|
|
|
|
|
treesel = gtk_tree_view_get_selection(GTK_TREE_VIEW(file_view));
|
|
|
|
|
|
|
|
list = gtk_tree_selection_get_selected_rows(treesel, &model);
|
2007-12-28 17:02:07 +00:00
|
|
|
dir_found = is_folder_selected(list);
|
|
|
|
|
|
|
|
if (dir_found)
|
|
|
|
{
|
|
|
|
if (check_single_selection(treesel))
|
|
|
|
{
|
2008-02-27 13:17:29 +00:00
|
|
|
GtkTreePath *treepath = list->data; /* first selected item */
|
2007-12-28 17:02:07 +00:00
|
|
|
|
|
|
|
open_folder(treepath);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
2010-03-07 18:48:12 +00:00
|
|
|
open_selected_files(list, GPOINTER_TO_INT(user_data));
|
2007-12-02 10:52:19 +00:00
|
|
|
|
|
|
|
g_list_foreach(list, (GFunc) gtk_tree_path_free, NULL);
|
|
|
|
g_list_free(list);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void on_find_in_files(GtkMenuItem *menuitem, gpointer user_data)
|
2007-10-22 12:42:19 +00:00
|
|
|
{
|
|
|
|
GtkTreeSelection *treesel;
|
|
|
|
GtkTreeModel *model;
|
|
|
|
GList *list;
|
2007-12-02 10:52:19 +00:00
|
|
|
gchar *dir;
|
|
|
|
gboolean is_dir = FALSE;
|
2007-10-22 12:42:19 +00:00
|
|
|
|
|
|
|
treesel = gtk_tree_view_get_selection(GTK_TREE_VIEW(file_view));
|
2010-06-18 17:03:35 +00:00
|
|
|
/* allow 0 or 1 selections */
|
|
|
|
if (gtk_tree_selection_count_selected_rows(treesel) > 0 &&
|
|
|
|
! check_single_selection(treesel))
|
2007-12-02 10:52:19 +00:00
|
|
|
return;
|
2007-10-22 12:42:19 +00:00
|
|
|
|
|
|
|
list = gtk_tree_selection_get_selected_rows(treesel, &model);
|
2007-12-28 17:02:07 +00:00
|
|
|
is_dir = is_folder_selected(list);
|
|
|
|
|
|
|
|
if (is_dir)
|
2007-12-02 10:52:19 +00:00
|
|
|
{
|
2008-02-27 13:17:29 +00:00
|
|
|
GtkTreePath *treepath = list->data; /* first selected item */
|
2007-12-02 10:52:19 +00:00
|
|
|
|
2007-12-28 17:02:07 +00:00
|
|
|
dir = get_tree_path_filename(treepath);
|
2007-12-02 10:52:19 +00:00
|
|
|
}
|
2007-12-28 17:02:07 +00:00
|
|
|
else
|
|
|
|
dir = g_strdup(current_dir);
|
2007-10-22 12:42:19 +00:00
|
|
|
|
|
|
|
g_list_foreach(list, (GFunc) gtk_tree_path_free, NULL);
|
|
|
|
g_list_free(list);
|
2007-12-02 10:52:19 +00:00
|
|
|
|
2012-01-25 16:26:16 +00:00
|
|
|
SETPTR(dir, utils_get_utf8_from_locale(dir));
|
2008-12-04 17:05:36 +00:00
|
|
|
search_show_find_in_files_dialog(dir);
|
2007-12-02 10:52:19 +00:00
|
|
|
g_free(dir);
|
2007-10-22 12:42:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-10-24 11:15:00 +00:00
|
|
|
static void on_hidden_files_clicked(GtkCheckMenuItem *item)
|
|
|
|
{
|
|
|
|
show_hidden_files = gtk_check_menu_item_get_active(item);
|
|
|
|
refresh();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-02-29 19:30:28 +00:00
|
|
|
static void on_hide_sidebar(void)
|
|
|
|
{
|
2008-12-04 17:05:36 +00:00
|
|
|
keybindings_send_command(GEANY_KEY_GROUP_VIEW, GEANY_KEYS_VIEW_SIDEBAR);
|
2008-02-29 19:30:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-09-27 14:07:24 +00:00
|
|
|
static void on_show_preferences(void)
|
|
|
|
{
|
|
|
|
plugin_show_configure(geany_plugin);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-02-20 11:24:23 +00:00
|
|
|
static GtkWidget *create_popup_menu(void)
|
2007-10-24 11:02:43 +00:00
|
|
|
{
|
2008-11-21 13:34:58 +00:00
|
|
|
GtkWidget *item, *menu;
|
2007-10-24 11:02:43 +00:00
|
|
|
|
|
|
|
menu = gtk_menu_new();
|
|
|
|
|
2014-05-01 00:35:16 +02:00
|
|
|
item = ui_image_menu_item_new(GTK_STOCK_OPEN, _("Open in _Geany"));
|
2007-10-24 11:02:43 +00:00
|
|
|
gtk_widget_show(item);
|
|
|
|
gtk_container_add(GTK_CONTAINER(menu), item);
|
2008-07-18 13:40:48 +00:00
|
|
|
g_signal_connect(item, "activate", G_CALLBACK(on_open_clicked), NULL);
|
2007-12-28 17:35:58 +00:00
|
|
|
popup_items.open = item;
|
2007-12-02 10:52:19 +00:00
|
|
|
|
2013-05-18 12:01:47 -04:00
|
|
|
item = ui_image_menu_item_new(GTK_STOCK_OPEN, _("Open _Externally"));
|
2007-12-02 10:52:19 +00:00
|
|
|
gtk_widget_show(item);
|
|
|
|
gtk_container_add(GTK_CONTAINER(menu), item);
|
2008-07-18 13:40:48 +00:00
|
|
|
g_signal_connect(item, "activate", G_CALLBACK(on_external_open), NULL);
|
2007-12-28 17:35:58 +00:00
|
|
|
popup_items.open_external = item;
|
2007-12-02 10:52:19 +00:00
|
|
|
|
2010-05-11 12:31:16 +00:00
|
|
|
item = gtk_separator_menu_item_new();
|
|
|
|
gtk_widget_show(item);
|
|
|
|
gtk_container_add(GTK_CONTAINER(menu), item);
|
|
|
|
|
|
|
|
item = gtk_image_menu_item_new_from_stock(GTK_STOCK_REFRESH, NULL);
|
|
|
|
gtk_widget_show(item);
|
|
|
|
gtk_container_add(GTK_CONTAINER(menu), item);
|
|
|
|
g_signal_connect(item, "activate", G_CALLBACK(refresh), NULL);
|
|
|
|
|
2013-05-19 22:58:25 +02:00
|
|
|
item = ui_image_menu_item_new(GTK_STOCK_FIND, _("_Find in Files..."));
|
2007-12-02 10:52:19 +00:00
|
|
|
gtk_widget_show(item);
|
|
|
|
gtk_container_add(GTK_CONTAINER(menu), item);
|
2008-07-18 13:40:48 +00:00
|
|
|
g_signal_connect(item, "activate", G_CALLBACK(on_find_in_files), NULL);
|
2007-12-28 17:35:58 +00:00
|
|
|
popup_items.find_in_files = item;
|
2007-10-24 11:02:43 +00:00
|
|
|
|
|
|
|
item = gtk_separator_menu_item_new();
|
|
|
|
gtk_widget_show(item);
|
|
|
|
gtk_container_add(GTK_CONTAINER(menu), item);
|
|
|
|
|
2007-11-08 16:21:46 +00:00
|
|
|
item = gtk_check_menu_item_new_with_mnemonic(_("Show _Hidden Files"));
|
2007-10-24 11:15:00 +00:00
|
|
|
gtk_widget_show(item);
|
|
|
|
gtk_container_add(GTK_CONTAINER(menu), item);
|
2008-07-18 13:40:48 +00:00
|
|
|
g_signal_connect(item, "activate", G_CALLBACK(on_hidden_files_clicked), NULL);
|
2010-04-19 12:03:32 +00:00
|
|
|
popup_items.show_hidden_files = item;
|
2007-10-24 11:15:00 +00:00
|
|
|
|
|
|
|
item = gtk_separator_menu_item_new();
|
|
|
|
gtk_widget_show(item);
|
|
|
|
gtk_container_add(GTK_CONTAINER(menu), item);
|
|
|
|
|
2009-09-27 14:07:24 +00:00
|
|
|
item = gtk_image_menu_item_new_from_stock(GTK_STOCK_PREFERENCES, NULL);
|
|
|
|
gtk_widget_show(item);
|
|
|
|
gtk_container_add(GTK_CONTAINER(menu), item);
|
|
|
|
g_signal_connect(item, "activate", G_CALLBACK(on_show_preferences), NULL);
|
|
|
|
|
|
|
|
item = gtk_separator_menu_item_new();
|
|
|
|
gtk_widget_show(item);
|
|
|
|
gtk_container_add(GTK_CONTAINER(menu), item);
|
|
|
|
|
2008-12-04 17:05:36 +00:00
|
|
|
item = ui_image_menu_item_new(GTK_STOCK_CLOSE, _("H_ide Sidebar"));
|
2007-10-24 11:02:43 +00:00
|
|
|
gtk_widget_show(item);
|
|
|
|
gtk_container_add(GTK_CONTAINER(menu), item);
|
2008-07-18 13:40:48 +00:00
|
|
|
g_signal_connect(item, "activate", G_CALLBACK(on_hide_sidebar), NULL);
|
2007-10-24 11:02:43 +00:00
|
|
|
|
|
|
|
return menu;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-01-28 17:22:34 +00:00
|
|
|
static void on_tree_selection_changed(GtkTreeSelection *selection, gpointer data)
|
2007-12-28 17:35:58 +00:00
|
|
|
{
|
2009-01-28 17:22:34 +00:00
|
|
|
gboolean have_sel = (gtk_tree_selection_count_selected_rows(selection) > 0);
|
|
|
|
gboolean multi_sel = (gtk_tree_selection_count_selected_rows(selection) > 1);
|
2007-12-28 17:35:58 +00:00
|
|
|
|
2009-01-28 17:22:34 +00:00
|
|
|
if (popup_items.open != NULL)
|
|
|
|
gtk_widget_set_sensitive(popup_items.open, have_sel);
|
|
|
|
if (popup_items.open_external != NULL)
|
|
|
|
gtk_widget_set_sensitive(popup_items.open_external, have_sel);
|
|
|
|
if (popup_items.find_in_files != NULL)
|
|
|
|
gtk_widget_set_sensitive(popup_items.find_in_files, have_sel && ! multi_sel);
|
2007-12-28 17:35:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-01-28 17:22:34 +00:00
|
|
|
static gboolean on_button_press(GtkWidget *widget, GdkEventButton *event, gpointer user_data)
|
2007-12-28 17:35:58 +00:00
|
|
|
{
|
2009-01-28 17:22:34 +00:00
|
|
|
if (event->button == 1 && event->type == GDK_2BUTTON_PRESS)
|
2009-02-08 19:51:31 +00:00
|
|
|
{
|
2009-01-28 17:22:34 +00:00
|
|
|
on_open_clicked(NULL, NULL);
|
2009-02-08 19:51:31 +00:00
|
|
|
return TRUE;
|
|
|
|
}
|
2009-01-28 17:22:34 +00:00
|
|
|
else if (event->button == 3)
|
2007-10-24 11:02:43 +00:00
|
|
|
{
|
|
|
|
static GtkWidget *popup_menu = NULL;
|
|
|
|
|
|
|
|
if (popup_menu == NULL)
|
|
|
|
popup_menu = create_popup_menu();
|
|
|
|
|
2010-04-19 12:03:32 +00:00
|
|
|
gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(popup_items.show_hidden_files),
|
|
|
|
show_hidden_files);
|
2009-02-08 19:51:31 +00:00
|
|
|
gtk_menu_popup(GTK_MENU(popup_menu), NULL, NULL, NULL, NULL, event->button, event->time);
|
|
|
|
/* don't return TRUE here, unless the selection won't be changed */
|
2007-10-24 11:02:43 +00:00
|
|
|
}
|
2007-10-22 12:42:19 +00:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static gboolean on_key_press(GtkWidget *widget, GdkEventKey *event, gpointer data)
|
|
|
|
{
|
2010-03-07 19:33:15 +00:00
|
|
|
if (ui_is_keyval_enter_or_return(event->keyval))
|
2009-02-08 19:51:31 +00:00
|
|
|
{
|
2007-12-28 17:02:07 +00:00
|
|
|
on_open_clicked(NULL, NULL);
|
2009-02-08 19:51:31 +00:00
|
|
|
return TRUE;
|
|
|
|
}
|
2007-10-22 12:42:19 +00:00
|
|
|
|
2010-03-07 18:48:12 +00:00
|
|
|
if (event->keyval == GDK_space)
|
|
|
|
{
|
|
|
|
on_open_clicked(NULL, GINT_TO_POINTER(TRUE));
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2012-12-13 10:45:08 -07:00
|
|
|
if (( (event->keyval == GDK_Up || event->keyval == GDK_KP_Up) && (event->state & GDK_MOD1_MASK)) || /* FIXME: Alt-Up doesn't seem to work! */
|
2012-12-16 10:21:01 +01:00
|
|
|
(event->keyval == GDK_BackSpace) )
|
2009-02-08 19:51:31 +00:00
|
|
|
{
|
2007-10-22 12:42:19 +00:00
|
|
|
on_go_up();
|
2009-02-08 19:51:31 +00:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((event->keyval == GDK_F10 && event->state & GDK_SHIFT_MASK) || event->keyval == GDK_Menu)
|
|
|
|
{
|
|
|
|
GdkEventButton button_event;
|
|
|
|
|
|
|
|
button_event.time = event->time;
|
|
|
|
button_event.button = 3;
|
|
|
|
|
|
|
|
on_button_press(widget, &button_event, data);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2007-10-22 12:42:19 +00:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-02-21 19:09:34 +00:00
|
|
|
static void clear_filter(void)
|
|
|
|
{
|
|
|
|
if (filter != NULL)
|
|
|
|
{
|
|
|
|
g_strfreev(filter);
|
|
|
|
filter = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-04-22 15:14:30 +00:00
|
|
|
static void on_clear_filter(GtkEntry *entry, gpointer user_data)
|
|
|
|
{
|
2011-02-21 19:09:34 +00:00
|
|
|
clear_filter();
|
2008-04-22 15:14:30 +00:00
|
|
|
|
|
|
|
gtk_entry_set_text(GTK_ENTRY(filter_entry), "");
|
|
|
|
|
|
|
|
refresh();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-12-02 10:52:19 +00:00
|
|
|
static void on_path_entry_activate(GtkEntry *entry, gpointer user_data)
|
|
|
|
{
|
|
|
|
gchar *new_dir = (gchar*) gtk_entry_get_text(entry);
|
2007-12-28 17:02:07 +00:00
|
|
|
|
2013-08-11 14:10:57 +01:00
|
|
|
if (!EMPTY(new_dir))
|
2007-12-04 13:25:41 +00:00
|
|
|
{
|
|
|
|
if (g_str_has_suffix(new_dir, ".."))
|
|
|
|
{
|
|
|
|
on_go_up();
|
|
|
|
return;
|
|
|
|
}
|
2009-01-30 16:12:25 +00:00
|
|
|
else if (new_dir[0] == '~')
|
|
|
|
{
|
|
|
|
GString *str = g_string_new(new_dir);
|
|
|
|
utils_string_replace_first(str, "~", g_get_home_dir());
|
|
|
|
new_dir = g_string_free(str, FALSE);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
new_dir = utils_get_locale_from_utf8(new_dir);
|
2007-12-04 13:25:41 +00:00
|
|
|
}
|
2007-12-02 10:52:19 +00:00
|
|
|
else
|
|
|
|
new_dir = g_strdup(g_get_home_dir());
|
|
|
|
|
2012-01-25 16:26:16 +00:00
|
|
|
SETPTR(current_dir, new_dir);
|
2008-04-22 15:14:30 +00:00
|
|
|
|
|
|
|
on_clear_filter(NULL, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-03-24 16:34:10 +00:00
|
|
|
static void ui_combo_box_changed(GtkComboBox *combo, gpointer user_data)
|
2010-06-18 12:22:00 +00:00
|
|
|
{
|
|
|
|
/* we get this callback on typing as well as choosing an item */
|
|
|
|
if (gtk_combo_box_get_active(combo) >= 0)
|
2011-10-11 21:30:28 -07:00
|
|
|
gtk_widget_activate(gtk_bin_get_child(GTK_BIN(combo)));
|
2010-06-18 12:22:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-04-22 15:14:30 +00:00
|
|
|
static void on_filter_activate(GtkEntry *entry, gpointer user_data)
|
|
|
|
{
|
2011-03-22 17:26:47 +00:00
|
|
|
/* We use spaces for consistency with Find in Files file patterns
|
|
|
|
* ';' also supported like original patch. */
|
|
|
|
filter = g_strsplit_set(gtk_entry_get_text(entry), "; ", -1);
|
2011-02-21 19:09:34 +00:00
|
|
|
if (filter == NULL || g_strv_length(filter) == 0)
|
2008-04-22 15:14:30 +00:00
|
|
|
{
|
2011-02-21 19:09:34 +00:00
|
|
|
clear_filter();
|
2008-04-22 15:14:30 +00:00
|
|
|
}
|
2012-09-15 23:40:13 +02:00
|
|
|
ui_combo_box_add_to_history(GTK_COMBO_BOX_TEXT(filter_combo), NULL, 0);
|
2007-12-02 10:52:19 +00:00
|
|
|
refresh();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-11-30 21:41:41 +00:00
|
|
|
static void on_filter_clear(GtkEntry *entry, gint icon_pos,
|
|
|
|
GdkEvent *event, gpointer data)
|
|
|
|
{
|
2011-02-21 19:09:34 +00:00
|
|
|
clear_filter();
|
2009-11-30 21:41:41 +00:00
|
|
|
refresh();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-02-20 11:24:23 +00:00
|
|
|
static void prepare_file_view(void)
|
2007-10-22 12:42:19 +00:00
|
|
|
{
|
|
|
|
GtkCellRenderer *text_renderer, *icon_renderer;
|
|
|
|
GtkTreeViewColumn *column;
|
2009-10-25 12:32:57 +00:00
|
|
|
GtkTreeSelection *selection;
|
2007-10-22 12:42:19 +00:00
|
|
|
|
2009-01-30 16:12:25 +00:00
|
|
|
file_store = gtk_list_store_new(FILEVIEW_N_COLUMNS, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
|
2007-10-22 12:42:19 +00:00
|
|
|
|
|
|
|
gtk_tree_view_set_model(GTK_TREE_VIEW(file_view), GTK_TREE_MODEL(file_store));
|
2008-10-07 18:51:50 +00:00
|
|
|
g_object_unref(file_store);
|
2007-10-22 12:42:19 +00:00
|
|
|
|
|
|
|
icon_renderer = gtk_cell_renderer_pixbuf_new();
|
|
|
|
text_renderer = gtk_cell_renderer_text_new();
|
|
|
|
column = gtk_tree_view_column_new();
|
2009-09-17 14:45:17 +00:00
|
|
|
gtk_tree_view_column_pack_start(column, icon_renderer, FALSE);
|
|
|
|
gtk_tree_view_column_set_attributes(column, icon_renderer, "stock-id", FILEVIEW_COLUMN_ICON, NULL);
|
|
|
|
gtk_tree_view_column_pack_start(column, text_renderer, TRUE);
|
|
|
|
gtk_tree_view_column_set_attributes(column, text_renderer, "text", FILEVIEW_COLUMN_NAME, NULL);
|
2007-10-22 12:42:19 +00:00
|
|
|
gtk_tree_view_append_column(GTK_TREE_VIEW(file_view), column);
|
|
|
|
gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(file_view), FALSE);
|
|
|
|
|
|
|
|
gtk_tree_view_set_enable_search(GTK_TREE_VIEW(file_view), TRUE);
|
|
|
|
gtk_tree_view_set_search_column(GTK_TREE_VIEW(file_view), FILEVIEW_COLUMN_NAME);
|
|
|
|
|
2009-10-25 12:32:57 +00:00
|
|
|
ui_widget_modify_font_from_string(file_view, geany->interface_prefs->tagbar_font);
|
2007-10-22 12:42:19 +00:00
|
|
|
|
2011-06-13 23:03:19 +00:00
|
|
|
/* tooltips */
|
2015-02-28 19:15:00 +01:00
|
|
|
ui_tree_view_set_tooltip_text_column(GTK_TREE_VIEW(file_view), FILEVIEW_COLUMN_FILENAME);
|
2009-01-30 16:12:25 +00:00
|
|
|
|
2008-02-27 13:17:29 +00:00
|
|
|
/* selection handling */
|
2009-10-25 12:32:57 +00:00
|
|
|
selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(file_view));
|
|
|
|
gtk_tree_selection_set_mode(selection, GTK_SELECTION_MULTIPLE);
|
2007-10-22 12:42:19 +00:00
|
|
|
|
2011-03-31 15:34:55 +00:00
|
|
|
/* Show the current path when the FB is first needed */
|
2009-01-28 17:22:34 +00:00
|
|
|
g_signal_connect(file_view, "realize", G_CALLBACK(on_current_path), NULL);
|
2009-10-25 12:32:57 +00:00
|
|
|
g_signal_connect(selection, "changed", G_CALLBACK(on_tree_selection_changed), NULL);
|
2008-07-18 13:40:48 +00:00
|
|
|
g_signal_connect(file_view, "button-press-event", G_CALLBACK(on_button_press), NULL);
|
|
|
|
g_signal_connect(file_view, "key-press-event", G_CALLBACK(on_key_press), NULL);
|
2007-10-22 12:42:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-02-20 11:24:23 +00:00
|
|
|
static GtkWidget *make_toolbar(void)
|
2007-10-22 12:42:19 +00:00
|
|
|
{
|
2007-10-24 11:02:43 +00:00
|
|
|
GtkWidget *wid, *toolbar;
|
2007-10-22 12:42:19 +00:00
|
|
|
|
|
|
|
toolbar = gtk_toolbar_new();
|
|
|
|
gtk_toolbar_set_icon_size(GTK_TOOLBAR(toolbar), GTK_ICON_SIZE_MENU);
|
2007-10-26 16:09:00 +00:00
|
|
|
gtk_toolbar_set_style(GTK_TOOLBAR(toolbar), GTK_TOOLBAR_ICONS);
|
2007-10-22 12:42:19 +00:00
|
|
|
|
2009-11-30 22:04:32 +00:00
|
|
|
wid = GTK_WIDGET(gtk_tool_button_new_from_stock(GTK_STOCK_GO_UP));
|
2011-06-13 18:41:50 +00:00
|
|
|
gtk_widget_set_tooltip_text(wid, _("Up"));
|
2008-07-18 13:40:48 +00:00
|
|
|
g_signal_connect(wid, "clicked", G_CALLBACK(on_go_up), NULL);
|
2007-10-22 12:42:19 +00:00
|
|
|
gtk_container_add(GTK_CONTAINER(toolbar), wid);
|
|
|
|
|
2009-11-30 22:04:32 +00:00
|
|
|
wid = GTK_WIDGET(gtk_tool_button_new_from_stock(GTK_STOCK_REFRESH));
|
2011-06-13 18:41:50 +00:00
|
|
|
gtk_widget_set_tooltip_text(wid, _("Refresh"));
|
2008-07-18 13:40:48 +00:00
|
|
|
g_signal_connect(wid, "clicked", G_CALLBACK(refresh), NULL);
|
2007-10-22 12:42:19 +00:00
|
|
|
gtk_container_add(GTK_CONTAINER(toolbar), wid);
|
|
|
|
|
2009-11-30 22:04:32 +00:00
|
|
|
wid = GTK_WIDGET(gtk_tool_button_new_from_stock(GTK_STOCK_HOME));
|
2011-06-13 18:41:50 +00:00
|
|
|
gtk_widget_set_tooltip_text(wid, _("Home"));
|
2008-07-18 13:40:48 +00:00
|
|
|
g_signal_connect(wid, "clicked", G_CALLBACK(on_go_home), NULL);
|
2007-10-22 12:42:19 +00:00
|
|
|
gtk_container_add(GTK_CONTAINER(toolbar), wid);
|
|
|
|
|
2009-11-30 22:04:32 +00:00
|
|
|
wid = GTK_WIDGET(gtk_tool_button_new_from_stock(GTK_STOCK_JUMP_TO));
|
2011-06-13 18:41:50 +00:00
|
|
|
gtk_widget_set_tooltip_text(wid, _("Set path from document"));
|
2008-07-18 13:40:48 +00:00
|
|
|
g_signal_connect(wid, "clicked", G_CALLBACK(on_current_path), NULL);
|
2007-10-22 12:42:19 +00:00
|
|
|
gtk_container_add(GTK_CONTAINER(toolbar), wid);
|
|
|
|
|
2007-10-24 11:02:43 +00:00
|
|
|
return toolbar;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-04-22 15:14:30 +00:00
|
|
|
static GtkWidget *make_filterbar(void)
|
|
|
|
{
|
|
|
|
GtkWidget *label, *filterbar;
|
|
|
|
|
|
|
|
filterbar = gtk_hbox_new(FALSE, 1);
|
|
|
|
|
|
|
|
label = gtk_label_new(_("Filter:"));
|
|
|
|
|
2012-09-15 23:40:13 +02:00
|
|
|
filter_combo = gtk_combo_box_text_new_with_entry();
|
2011-10-11 21:30:28 -07:00
|
|
|
filter_entry = gtk_bin_get_child(GTK_BIN(filter_combo));
|
2009-11-30 21:41:41 +00:00
|
|
|
|
2011-10-28 10:25:58 -07:00
|
|
|
ui_entry_add_clear_icon(GTK_ENTRY(filter_entry));
|
|
|
|
g_signal_connect(filter_entry, "icon-release", G_CALLBACK(on_filter_clear), NULL);
|
|
|
|
|
2011-06-13 18:41:50 +00:00
|
|
|
gtk_widget_set_tooltip_text(filter_entry,
|
2011-03-22 17:26:47 +00:00
|
|
|
_("Filter your files with the usual wildcards. Separate multiple patterns with a space."));
|
2008-07-18 13:40:48 +00:00
|
|
|
g_signal_connect(filter_entry, "activate", G_CALLBACK(on_filter_activate), NULL);
|
2011-03-24 16:34:10 +00:00
|
|
|
g_signal_connect(filter_combo, "changed", G_CALLBACK(ui_combo_box_changed), NULL);
|
2008-04-22 15:14:30 +00:00
|
|
|
|
|
|
|
gtk_box_pack_start(GTK_BOX(filterbar), label, FALSE, FALSE, 0);
|
2011-03-24 16:34:10 +00:00
|
|
|
gtk_box_pack_start(GTK_BOX(filterbar), filter_combo, TRUE, TRUE, 0);
|
2008-04-22 15:14:30 +00:00
|
|
|
|
|
|
|
return filterbar;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-12-04 13:25:41 +00:00
|
|
|
static gboolean completion_match_func(GtkEntryCompletion *completion, const gchar *key,
|
|
|
|
GtkTreeIter *iter, gpointer user_data)
|
|
|
|
{
|
|
|
|
gchar *str, *icon;
|
|
|
|
gboolean result = FALSE;
|
|
|
|
|
|
|
|
gtk_tree_model_get(GTK_TREE_MODEL(file_store), iter,
|
|
|
|
FILEVIEW_COLUMN_ICON, &icon, FILEVIEW_COLUMN_NAME, &str, -1);
|
|
|
|
|
2008-12-04 17:05:36 +00:00
|
|
|
if (str != NULL && icon != NULL && utils_str_equal(icon, GTK_STOCK_DIRECTORY) &&
|
2007-12-04 13:25:41 +00:00
|
|
|
! g_str_has_suffix(key, G_DIR_SEPARATOR_S))
|
|
|
|
{
|
2008-02-27 13:17:29 +00:00
|
|
|
/* key is something like "/tmp/te" and str is a filename like "test",
|
|
|
|
* so strip the path from key to make them comparable */
|
2007-12-04 13:25:41 +00:00
|
|
|
gchar *base_name = g_path_get_basename(key);
|
|
|
|
gchar *str_lowered = g_utf8_strdown(str, -1);
|
|
|
|
result = g_str_has_prefix(str_lowered, base_name);
|
|
|
|
g_free(base_name);
|
|
|
|
g_free(str_lowered);
|
|
|
|
}
|
|
|
|
g_free(str);
|
|
|
|
g_free(icon);
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static gboolean completion_match_selected(GtkEntryCompletion *widget, GtkTreeModel *model,
|
|
|
|
GtkTreeIter *iter, gpointer user_data)
|
|
|
|
{
|
|
|
|
gchar *str;
|
|
|
|
gtk_tree_model_get(model, iter, FILEVIEW_COLUMN_NAME, &str, -1);
|
|
|
|
if (str != NULL)
|
|
|
|
{
|
|
|
|
gchar *text = g_strconcat(current_dir, G_DIR_SEPARATOR_S, str, NULL);
|
|
|
|
gtk_entry_set_text(GTK_ENTRY(path_entry), text);
|
|
|
|
gtk_editable_set_position(GTK_EDITABLE(path_entry), -1);
|
2008-02-27 13:17:29 +00:00
|
|
|
/* force change of directory when completion is done */
|
2007-12-04 13:25:41 +00:00
|
|
|
on_path_entry_activate(GTK_ENTRY(path_entry), NULL);
|
|
|
|
g_free(text);
|
|
|
|
}
|
|
|
|
g_free(str);
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-02-20 11:24:23 +00:00
|
|
|
static void completion_create(void)
|
2007-12-04 13:25:41 +00:00
|
|
|
{
|
|
|
|
entry_completion = gtk_entry_completion_new();
|
|
|
|
|
|
|
|
gtk_entry_completion_set_inline_completion(entry_completion, FALSE);
|
|
|
|
gtk_entry_completion_set_popup_completion(entry_completion, TRUE);
|
|
|
|
gtk_entry_completion_set_text_column(entry_completion, FILEVIEW_COLUMN_NAME);
|
|
|
|
gtk_entry_completion_set_match_func(entry_completion, completion_match_func, NULL, NULL);
|
|
|
|
|
|
|
|
g_signal_connect(entry_completion, "match-selected",
|
|
|
|
G_CALLBACK(completion_match_selected), NULL);
|
|
|
|
|
|
|
|
gtk_entry_set_completion(GTK_ENTRY(path_entry), entry_completion);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-04-03 16:06:41 +00:00
|
|
|
static void load_settings(void)
|
2007-10-24 11:02:43 +00:00
|
|
|
{
|
2007-12-02 10:52:19 +00:00
|
|
|
GKeyFile *config = g_key_file_new();
|
2007-10-24 11:02:43 +00:00
|
|
|
|
2008-07-07 16:16:18 +00:00
|
|
|
config_file = g_strconcat(geany->app->configdir, G_DIR_SEPARATOR_S, "plugins", G_DIR_SEPARATOR_S,
|
2008-04-03 16:06:41 +00:00
|
|
|
"filebrowser", G_DIR_SEPARATOR_S, "filebrowser.conf", NULL);
|
|
|
|
g_key_file_load_from_file(config, config_file, G_KEY_FILE_NONE, NULL);
|
2011-03-30 16:18:47 +00:00
|
|
|
|
2014-10-26 15:06:16 +00:00
|
|
|
open_cmd = utils_get_setting_string(config, "filebrowser", "open_command", OPEN_CMD);
|
2011-03-31 15:34:55 +00:00
|
|
|
/* g_key_file_get_boolean defaults to FALSE */
|
2011-03-30 16:18:47 +00:00
|
|
|
show_hidden_files = g_key_file_get_boolean(config, "filebrowser", "show_hidden_files", NULL);
|
2011-03-31 15:34:55 +00:00
|
|
|
hide_object_files = utils_get_setting_boolean(config, "filebrowser", "hide_object_files", TRUE);
|
2011-03-31 15:01:24 +00:00
|
|
|
hidden_file_extensions = utils_get_setting_string(config, "filebrowser", "hidden_file_extensions",
|
|
|
|
".o .obj .so .dll .a .lib .pyc");
|
2011-03-30 16:18:47 +00:00
|
|
|
fb_follow_path = g_key_file_get_boolean(config, "filebrowser", "fb_follow_path", NULL);
|
|
|
|
fb_set_project_base_path = g_key_file_get_boolean(config, "filebrowser", "fb_set_project_base_path", NULL);
|
2008-04-03 16:06:41 +00:00
|
|
|
|
|
|
|
g_key_file_free(config);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-02-01 18:48:09 +00:00
|
|
|
static void project_change_cb(G_GNUC_UNUSED GObject *obj, G_GNUC_UNUSED GKeyFile *config,
|
|
|
|
G_GNUC_UNUSED gpointer data)
|
|
|
|
{
|
|
|
|
gchar *new_dir;
|
|
|
|
GeanyProject *project = geany->app->project;
|
|
|
|
|
2013-08-11 14:10:57 +01:00
|
|
|
if (! fb_set_project_base_path || project == NULL || EMPTY(project->base_path))
|
2009-02-01 18:48:09 +00:00
|
|
|
return;
|
|
|
|
|
|
|
|
/* TODO this is a copy of project_get_base_path(), add it to the plugin API */
|
|
|
|
if (g_path_is_absolute(project->base_path))
|
|
|
|
new_dir = g_strdup(project->base_path);
|
|
|
|
else
|
|
|
|
{ /* build base_path out of project file name's dir and base_path */
|
|
|
|
gchar *dir = g_path_get_dirname(project->file_name);
|
|
|
|
|
|
|
|
new_dir = g_strconcat(dir, G_DIR_SEPARATOR_S, project->base_path, NULL);
|
|
|
|
g_free(dir);
|
|
|
|
}
|
|
|
|
/* get it into locale encoding */
|
2012-01-25 16:26:16 +00:00
|
|
|
SETPTR(new_dir, utils_get_locale_from_utf8(new_dir));
|
2009-02-01 18:48:09 +00:00
|
|
|
|
|
|
|
if (! utils_str_equal(current_dir, new_dir))
|
|
|
|
{
|
2012-01-25 16:26:16 +00:00
|
|
|
SETPTR(current_dir, new_dir);
|
2009-02-01 18:48:09 +00:00
|
|
|
refresh();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
g_free(new_dir);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-04-11 12:07:19 +00:00
|
|
|
static gpointer last_activate_path = NULL;
|
|
|
|
|
2009-02-01 18:48:09 +00:00
|
|
|
static void document_activate_cb(G_GNUC_UNUSED GObject *obj, GeanyDocument *doc,
|
|
|
|
G_GNUC_UNUSED gpointer data)
|
|
|
|
{
|
|
|
|
gchar *new_dir;
|
|
|
|
|
2011-04-11 12:07:19 +00:00
|
|
|
last_activate_path = doc->real_path;
|
|
|
|
|
2009-02-08 19:52:43 +00:00
|
|
|
if (! fb_follow_path || doc->file_name == NULL || ! g_path_is_absolute(doc->file_name))
|
2009-02-01 18:48:09 +00:00
|
|
|
return;
|
|
|
|
|
|
|
|
new_dir = g_path_get_dirname(doc->file_name);
|
2012-01-25 16:26:16 +00:00
|
|
|
SETPTR(new_dir, utils_get_locale_from_utf8(new_dir));
|
2009-02-01 18:48:09 +00:00
|
|
|
|
|
|
|
if (! utils_str_equal(current_dir, new_dir))
|
|
|
|
{
|
2012-01-25 16:26:16 +00:00
|
|
|
SETPTR(current_dir, new_dir);
|
2009-02-01 18:48:09 +00:00
|
|
|
refresh();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
g_free(new_dir);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-04-11 12:07:19 +00:00
|
|
|
static void document_save_cb(GObject *obj, GeanyDocument *doc, gpointer user_data)
|
|
|
|
{
|
|
|
|
if (!last_activate_path)
|
|
|
|
document_activate_cb(obj, doc, user_data);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-04-03 16:06:41 +00:00
|
|
|
static void kb_activate(guint key_id)
|
|
|
|
{
|
2008-12-07 19:12:27 +00:00
|
|
|
gtk_notebook_set_current_page(GTK_NOTEBOOK(geany->main_widgets->sidebar_notebook), page_number);
|
2008-04-03 16:06:41 +00:00
|
|
|
switch (key_id)
|
|
|
|
{
|
|
|
|
case KB_FOCUS_FILE_LIST:
|
|
|
|
gtk_widget_grab_focus(file_view);
|
|
|
|
break;
|
|
|
|
case KB_FOCUS_PATH_ENTRY:
|
|
|
|
gtk_widget_grab_focus(path_entry);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-05-26 17:24:11 +00:00
|
|
|
void plugin_init(GeanyData *data)
|
2008-04-03 16:06:41 +00:00
|
|
|
{
|
2008-04-22 15:14:30 +00:00
|
|
|
GtkWidget *scrollwin, *toolbar, *filterbar;
|
|
|
|
|
|
|
|
filter = NULL;
|
2011-03-22 17:26:47 +00:00
|
|
|
|
2007-11-20 18:15:46 +00:00
|
|
|
file_view_vbox = gtk_vbox_new(FALSE, 0);
|
2007-10-24 11:02:43 +00:00
|
|
|
toolbar = make_toolbar();
|
2007-11-20 18:15:46 +00:00
|
|
|
gtk_box_pack_start(GTK_BOX(file_view_vbox), toolbar, FALSE, FALSE, 0);
|
2007-10-22 12:42:19 +00:00
|
|
|
|
2008-04-22 15:14:30 +00:00
|
|
|
filterbar = make_filterbar();
|
|
|
|
gtk_box_pack_start(GTK_BOX(file_view_vbox), filterbar, FALSE, FALSE, 0);
|
|
|
|
|
2012-09-15 23:40:13 +02:00
|
|
|
path_combo = gtk_combo_box_text_new_with_entry();
|
2010-06-18 12:22:00 +00:00
|
|
|
gtk_box_pack_start(GTK_BOX(file_view_vbox), path_combo, FALSE, FALSE, 2);
|
2011-03-24 16:34:10 +00:00
|
|
|
g_signal_connect(path_combo, "changed", G_CALLBACK(ui_combo_box_changed), NULL);
|
2011-10-11 21:30:28 -07:00
|
|
|
path_entry = gtk_bin_get_child(GTK_BIN(path_combo));
|
2008-07-18 13:40:48 +00:00
|
|
|
g_signal_connect(path_entry, "activate", G_CALLBACK(on_path_entry_activate), NULL);
|
2007-10-22 12:42:19 +00:00
|
|
|
|
2007-10-24 11:02:43 +00:00
|
|
|
file_view = gtk_tree_view_new();
|
|
|
|
prepare_file_view();
|
2007-12-04 13:25:41 +00:00
|
|
|
completion_create();
|
2007-10-24 11:02:43 +00:00
|
|
|
|
2009-01-28 17:22:34 +00:00
|
|
|
popup_items.open = popup_items.open_external = popup_items.find_in_files = NULL;
|
|
|
|
|
2007-10-22 12:42:19 +00:00
|
|
|
scrollwin = gtk_scrolled_window_new(NULL, NULL);
|
|
|
|
gtk_scrolled_window_set_policy(
|
|
|
|
GTK_SCROLLED_WINDOW(scrollwin),
|
|
|
|
GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
|
|
|
|
gtk_container_add(GTK_CONTAINER(scrollwin), file_view);
|
2012-09-28 03:27:35 +02:00
|
|
|
gtk_box_pack_start(GTK_BOX(file_view_vbox), scrollwin, TRUE, TRUE, 0);
|
2007-10-22 12:42:19 +00:00
|
|
|
|
2011-03-31 15:34:55 +00:00
|
|
|
/* load settings before file_view "realize" callback */
|
|
|
|
load_settings();
|
|
|
|
|
2007-11-20 18:15:46 +00:00
|
|
|
gtk_widget_show_all(file_view_vbox);
|
2008-12-07 19:12:27 +00:00
|
|
|
page_number = gtk_notebook_append_page(GTK_NOTEBOOK(geany->main_widgets->sidebar_notebook),
|
|
|
|
file_view_vbox, gtk_label_new(_("Files")));
|
2007-12-02 10:52:19 +00:00
|
|
|
|
2008-04-03 16:06:41 +00:00
|
|
|
/* setup keybindings */
|
2008-12-04 17:05:36 +00:00
|
|
|
keybindings_set_item(plugin_key_group, KB_FOCUS_FILE_LIST, kb_activate,
|
2008-04-03 16:06:41 +00:00
|
|
|
0, 0, "focus_file_list", _("Focus File List"), NULL);
|
2008-12-04 17:05:36 +00:00
|
|
|
keybindings_set_item(plugin_key_group, KB_FOCUS_PATH_ENTRY, kb_activate,
|
2008-04-03 16:06:41 +00:00
|
|
|
0, 0, "focus_path_entry", _("Focus Path Entry"), NULL);
|
2009-07-29 17:40:20 +00:00
|
|
|
|
|
|
|
plugin_signal_connect(geany_plugin, NULL, "document-activate", TRUE,
|
|
|
|
(GCallback) &document_activate_cb, NULL);
|
2011-04-11 12:07:19 +00:00
|
|
|
plugin_signal_connect(geany_plugin, NULL, "document-save", TRUE,
|
|
|
|
(GCallback) &document_save_cb, NULL);
|
2007-12-02 10:52:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-04-19 12:03:32 +00:00
|
|
|
static void save_settings(void)
|
|
|
|
{
|
|
|
|
GKeyFile *config = g_key_file_new();
|
|
|
|
gchar *data;
|
|
|
|
gchar *config_dir = g_path_get_dirname(config_file);
|
|
|
|
|
|
|
|
g_key_file_load_from_file(config, config_file, G_KEY_FILE_NONE, NULL);
|
|
|
|
|
|
|
|
g_key_file_set_string(config, "filebrowser", "open_command", open_cmd);
|
|
|
|
g_key_file_set_boolean(config, "filebrowser", "show_hidden_files", show_hidden_files);
|
|
|
|
g_key_file_set_boolean(config, "filebrowser", "hide_object_files", hide_object_files);
|
2011-03-31 15:01:24 +00:00
|
|
|
g_key_file_set_string(config, "filebrowser", "hidden_file_extensions", hidden_file_extensions);
|
2010-04-19 12:03:32 +00:00
|
|
|
g_key_file_set_boolean(config, "filebrowser", "fb_follow_path", fb_follow_path);
|
|
|
|
g_key_file_set_boolean(config, "filebrowser", "fb_set_project_base_path",
|
|
|
|
fb_set_project_base_path);
|
|
|
|
|
|
|
|
if (! g_file_test(config_dir, G_FILE_TEST_IS_DIR) && utils_mkdir(config_dir, TRUE) != 0)
|
|
|
|
{
|
|
|
|
dialogs_show_msgbox(GTK_MESSAGE_ERROR,
|
|
|
|
_("Plugin configuration directory could not be created."));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* write config to file */
|
|
|
|
data = g_key_file_to_data(config, NULL, NULL);
|
|
|
|
utils_write_file(config_file, data);
|
|
|
|
g_free(data);
|
|
|
|
}
|
|
|
|
g_free(config_dir);
|
|
|
|
g_key_file_free(config);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-05-28 13:05:09 +00:00
|
|
|
static struct
|
2007-12-02 10:52:19 +00:00
|
|
|
{
|
2008-05-28 13:05:09 +00:00
|
|
|
GtkWidget *open_cmd_entry;
|
|
|
|
GtkWidget *show_hidden_checkbox;
|
|
|
|
GtkWidget *hide_objects_checkbox;
|
2011-03-31 15:01:24 +00:00
|
|
|
GtkWidget *hidden_files_entry;
|
2009-02-01 18:48:09 +00:00
|
|
|
GtkWidget *follow_path_checkbox;
|
|
|
|
GtkWidget *set_project_base_path_checkbox;
|
2008-05-28 13:05:09 +00:00
|
|
|
}
|
|
|
|
pref_widgets;
|
|
|
|
|
|
|
|
static void
|
|
|
|
on_configure_response(GtkDialog *dialog, gint response, gpointer user_data)
|
|
|
|
{
|
|
|
|
if (response == GTK_RESPONSE_OK || response == GTK_RESPONSE_APPLY)
|
|
|
|
{
|
|
|
|
g_free(open_cmd);
|
|
|
|
open_cmd = g_strdup(gtk_entry_get_text(GTK_ENTRY(pref_widgets.open_cmd_entry)));
|
|
|
|
show_hidden_files = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(pref_widgets.show_hidden_checkbox));
|
|
|
|
hide_object_files = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(pref_widgets.hide_objects_checkbox));
|
2011-03-31 15:01:24 +00:00
|
|
|
g_free(hidden_file_extensions);
|
|
|
|
hidden_file_extensions = g_strdup(gtk_entry_get_text(GTK_ENTRY(pref_widgets.hidden_files_entry)));
|
2009-02-01 18:48:09 +00:00
|
|
|
fb_follow_path = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(pref_widgets.follow_path_checkbox));
|
|
|
|
fb_set_project_base_path = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(
|
|
|
|
pref_widgets.set_project_base_path_checkbox));
|
2008-05-28 13:05:09 +00:00
|
|
|
|
|
|
|
/* apply the changes */
|
|
|
|
refresh();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-03-31 15:01:24 +00:00
|
|
|
static void on_toggle_hidden(void)
|
|
|
|
{
|
|
|
|
gboolean enabled = !gtk_toggle_button_get_active(
|
|
|
|
GTK_TOGGLE_BUTTON(pref_widgets.show_hidden_checkbox));
|
|
|
|
|
|
|
|
gtk_widget_set_sensitive(pref_widgets.hide_objects_checkbox, enabled);
|
|
|
|
enabled &= gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(pref_widgets.hide_objects_checkbox));
|
|
|
|
gtk_widget_set_sensitive(pref_widgets.hidden_files_entry, enabled);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-05-28 13:05:09 +00:00
|
|
|
GtkWidget *plugin_configure(GtkDialog *dialog)
|
|
|
|
{
|
2009-02-01 18:48:09 +00:00
|
|
|
GtkWidget *label, *entry, *checkbox_of, *checkbox_hf, *checkbox_fp, *checkbox_pb, *vbox;
|
2011-03-31 15:01:24 +00:00
|
|
|
GtkWidget *box, *align;
|
2007-12-02 10:52:19 +00:00
|
|
|
|
2008-05-28 13:05:09 +00:00
|
|
|
vbox = gtk_vbox_new(FALSE, 6);
|
2009-10-26 15:31:00 +00:00
|
|
|
box = gtk_vbox_new(FALSE, 3);
|
2007-12-02 10:52:19 +00:00
|
|
|
|
2008-02-06 16:02:00 +00:00
|
|
|
label = gtk_label_new(_("External open command:"));
|
2007-12-02 10:52:19 +00:00
|
|
|
gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
|
2009-10-26 15:31:00 +00:00
|
|
|
gtk_box_pack_start(GTK_BOX(box), label, FALSE, FALSE, 0);
|
2007-12-02 10:52:19 +00:00
|
|
|
|
|
|
|
entry = gtk_entry_new();
|
|
|
|
if (open_cmd != NULL)
|
|
|
|
gtk_entry_set_text(GTK_ENTRY(entry), open_cmd);
|
2011-06-13 18:41:50 +00:00
|
|
|
gtk_widget_set_tooltip_text(entry,
|
2007-12-02 10:52:19 +00:00
|
|
|
_("The command to execute when using \"Open with\". You can use %f and %d wildcards.\n"
|
|
|
|
"%f will be replaced with the filename including full path\n"
|
2008-11-18 20:14:42 +00:00
|
|
|
"%d will be replaced with the path name of the selected file without the filename"));
|
2009-10-26 15:31:00 +00:00
|
|
|
gtk_box_pack_start(GTK_BOX(box), entry, FALSE, FALSE, 0);
|
2008-05-28 13:05:09 +00:00
|
|
|
pref_widgets.open_cmd_entry = entry;
|
2007-12-02 10:52:19 +00:00
|
|
|
|
2011-03-31 15:01:24 +00:00
|
|
|
gtk_box_pack_start(GTK_BOX(vbox), box, FALSE, FALSE, 3);
|
2009-10-26 15:31:00 +00:00
|
|
|
|
2007-12-02 10:52:19 +00:00
|
|
|
checkbox_hf = gtk_check_button_new_with_label(_("Show hidden files"));
|
|
|
|
gtk_button_set_focus_on_click(GTK_BUTTON(checkbox_hf), FALSE);
|
|
|
|
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(checkbox_hf), show_hidden_files);
|
2009-10-26 15:31:00 +00:00
|
|
|
gtk_box_pack_start(GTK_BOX(vbox), checkbox_hf, FALSE, FALSE, 0);
|
2008-05-28 13:05:09 +00:00
|
|
|
pref_widgets.show_hidden_checkbox = checkbox_hf;
|
2011-03-31 15:01:24 +00:00
|
|
|
g_signal_connect(checkbox_hf, "toggled", on_toggle_hidden, NULL);
|
2007-12-02 10:52:19 +00:00
|
|
|
|
2011-03-31 15:01:24 +00:00
|
|
|
box = gtk_vbox_new(FALSE, 3);
|
|
|
|
checkbox_of = gtk_check_button_new_with_label(_("Hide file extensions:"));
|
2007-12-02 10:52:19 +00:00
|
|
|
gtk_button_set_focus_on_click(GTK_BUTTON(checkbox_of), FALSE);
|
|
|
|
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(checkbox_of), hide_object_files);
|
2011-03-31 15:01:24 +00:00
|
|
|
gtk_box_pack_start(GTK_BOX(box), checkbox_of, FALSE, FALSE, 0);
|
2008-05-28 13:05:09 +00:00
|
|
|
pref_widgets.hide_objects_checkbox = checkbox_of;
|
2011-03-31 15:01:24 +00:00
|
|
|
g_signal_connect(checkbox_of, "toggled", on_toggle_hidden, NULL);
|
|
|
|
|
|
|
|
entry = gtk_entry_new();
|
|
|
|
if (hidden_file_extensions != NULL)
|
|
|
|
gtk_entry_set_text(GTK_ENTRY(entry), hidden_file_extensions);
|
|
|
|
gtk_box_pack_start(GTK_BOX(box), entry, FALSE, FALSE, 0);
|
|
|
|
pref_widgets.hidden_files_entry = entry;
|
|
|
|
|
|
|
|
align = gtk_alignment_new(1, 0.5, 1, 1);
|
|
|
|
gtk_alignment_set_padding(GTK_ALIGNMENT(align), 0, 0, 12, 0);
|
|
|
|
gtk_container_add(GTK_CONTAINER(align), box);
|
|
|
|
gtk_box_pack_start(GTK_BOX(vbox), align, FALSE, FALSE, 0);
|
|
|
|
on_toggle_hidden();
|
2007-12-02 10:52:19 +00:00
|
|
|
|
2009-02-01 18:48:09 +00:00
|
|
|
checkbox_fp = gtk_check_button_new_with_label(_("Follow the path of the current file"));
|
|
|
|
gtk_button_set_focus_on_click(GTK_BUTTON(checkbox_fp), FALSE);
|
|
|
|
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(checkbox_fp), fb_follow_path);
|
2009-10-26 15:31:00 +00:00
|
|
|
gtk_box_pack_start(GTK_BOX(vbox), checkbox_fp, FALSE, FALSE, 0);
|
2009-02-01 18:48:09 +00:00
|
|
|
pref_widgets.follow_path_checkbox = checkbox_fp;
|
|
|
|
|
2009-07-07 12:30:47 +00:00
|
|
|
checkbox_pb = gtk_check_button_new_with_label(_("Use the project's base directory"));
|
2009-02-01 18:48:09 +00:00
|
|
|
gtk_button_set_focus_on_click(GTK_BUTTON(checkbox_pb), FALSE);
|
|
|
|
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(checkbox_pb), fb_set_project_base_path);
|
2011-06-13 18:41:50 +00:00
|
|
|
gtk_widget_set_tooltip_text(checkbox_pb,
|
2009-02-01 18:48:09 +00:00
|
|
|
_("Change the directory to the base directory of the currently opened project"));
|
2009-10-26 15:31:00 +00:00
|
|
|
gtk_box_pack_start(GTK_BOX(vbox), checkbox_pb, FALSE, FALSE, 0);
|
2009-02-01 18:48:09 +00:00
|
|
|
pref_widgets.set_project_base_path_checkbox = checkbox_pb;
|
|
|
|
|
2007-12-02 10:52:19 +00:00
|
|
|
gtk_widget_show_all(vbox);
|
|
|
|
|
2008-05-28 13:05:09 +00:00
|
|
|
g_signal_connect(dialog, "response", G_CALLBACK(on_configure_response), NULL);
|
|
|
|
return vbox;
|
2007-10-22 12:42:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-05-26 17:24:11 +00:00
|
|
|
void plugin_cleanup(void)
|
2007-10-22 12:42:19 +00:00
|
|
|
{
|
2010-04-19 12:03:32 +00:00
|
|
|
save_settings();
|
|
|
|
|
2007-12-02 10:52:19 +00:00
|
|
|
g_free(config_file);
|
|
|
|
g_free(open_cmd);
|
2011-03-31 15:01:24 +00:00
|
|
|
g_free(hidden_file_extensions);
|
2011-02-21 19:09:34 +00:00
|
|
|
clear_filter();
|
2007-11-20 18:15:46 +00:00
|
|
|
gtk_widget_destroy(file_view_vbox);
|
2007-12-04 13:25:41 +00:00
|
|
|
g_object_unref(G_OBJECT(entry_completion));
|
2007-10-22 12:42:19 +00:00
|
|
|
}
|