diff --git a/projectorganizer/src/prjorg-menu.c b/projectorganizer/src/prjorg-menu.c
index e7e0c1400..76b213a34 100644
--- a/projectorganizer/src/prjorg-menu.c
+++ b/projectorganizer/src/prjorg-menu.c
@@ -49,7 +49,46 @@ enum
static GtkWidget *s_fif_item, *s_ff_item, *s_ft_item, *s_shs_item, *s_sep_item, *s_context_osf_item, *s_context_sep_item;
+/* GTK compatibility functions/macros */
+
+#if ! GTK_CHECK_VERSION (2, 18, 0)
+# define gtk_widget_get_visible(w) \
+ (GTK_WIDGET_VISIBLE (w))
+# define gtk_widget_set_can_focus(w, v) \
+ G_STMT_START { \
+ GtkWidget *widget = (w); \
+ if (v) { \
+ GTK_WIDGET_SET_FLAGS (widget, GTK_CAN_FOCUS); \
+ } else { \
+ GTK_WIDGET_UNSET_FLAGS (widget, GTK_CAN_FOCUS); \
+ } \
+ } G_STMT_END
+#endif
+
+#if ! GTK_CHECK_VERSION (2, 21, 8)
+# define GDK_KEY_Down GDK_Down
+# define GDK_KEY_Escape GDK_Escape
+# define GDK_KEY_ISO_Enter GDK_ISO_Enter
+# define GDK_KEY_KP_Enter GDK_KP_Enter
+# define GDK_KEY_Page_Down GDK_Page_Down
+# define GDK_KEY_Page_Up GDK_Page_Up
+# define GDK_KEY_Return GDK_Return
+# define GDK_KEY_Tab GDK_Tab
+# define GDK_KEY_Up GDK_Up
+#endif
+struct {
+ GtkWidget *scroll;
+ GtkWidget *panel;
+ GtkWidget *entry;
+ GtkWidget *view;
+ GtkListStore *store;
+ GtkTreeModel *filter;
+} kb_find_file = {
+ NULL, NULL,
+ NULL, NULL,
+ NULL, NULL
+};
static gboolean try_swap_header_source(gchar *utf8_file_name, gboolean is_header, GSList *file_list, GSList *header_patterns, GSList *source_patterns)
{
gchar *name_pattern;
@@ -87,7 +126,6 @@ static gboolean try_swap_header_source(gchar *utf8_file_name, gboolean is_header
return found;
}
-
static void on_swap_header_source(G_GNUC_UNUSED GtkMenuItem * menuitem, G_GNUC_UNUSED gpointer user_data)
{
GSList *header_patterns, *source_patterns;
@@ -194,12 +232,323 @@ static void on_find_in_project(G_GNUC_UNUSED GtkMenuItem * menuitem, G_GNUC_UNUS
g_free(utf8_base_path);
}
}
+static void
+on_view_row_activated (GtkTreeView *view,
+ GtkTreePath *path,
+ GtkTreeViewColumn *column,
+ gpointer dummy)
+{
+ GtkTreeModel *model = gtk_tree_view_get_model (view);
+ GtkTreeIter iter;
+ gchar *utf8_path;
+
+ if (gtk_tree_model_get_iter (model, &iter, path)) {
+ gtk_tree_model_get (model, &iter, COL_FILE_NAME, &utf8_path, -1);
+ open_file(utf8_path);
+ gtk_widget_hide (kb_find_file.panel);
+ }
+}
+static void
+tree_view_set_cursor_from_iter (GtkTreeView *view,
+ GtkTreeIter *iter)
+{
+ GtkTreePath *path;
+
+ path = gtk_tree_model_get_path (gtk_tree_view_get_model (view), iter);
+ gtk_tree_view_set_cursor (view, path, NULL, FALSE);
+ gtk_tree_path_free (path);
+}
+
+static void
+tree_view_move_focus (GtkTreeView *view,
+ GtkMovementStep step,
+ gint amount)
+{
+ GtkTreeIter iter;
+ GtkTreePath *path;
+ GtkTreeModel *model = gtk_tree_view_get_model (view);
+ gboolean valid = FALSE;
+
+ gtk_tree_view_get_cursor (view, &path, NULL);
+ if (! path) {
+ valid = gtk_tree_model_get_iter_first (model, &iter);
+ } else {
+ switch (step) {
+ case GTK_MOVEMENT_BUFFER_ENDS:
+ valid = gtk_tree_model_get_iter_first (model, &iter);
+ if (valid && amount > 0) {
+ GtkTreeIter prev;
+
+ do {
+ prev = iter;
+ } while (gtk_tree_model_iter_next (model, &iter));
+ iter = prev;
+ }
+ break;
+
+ /* FIXME: move by page */
+ case GTK_MOVEMENT_DISPLAY_LINES:
+ gtk_tree_model_get_iter (model, &iter, path);
+ if (amount > 0) {
+ while ((valid = gtk_tree_model_iter_next (model, &iter)) &&
+ --amount > 0)
+ ;
+ } else if (amount < 0) {
+ while ((valid = gtk_tree_path_prev (path)) && --amount > 0)
+ ;
+
+ if (valid) {
+ gtk_tree_model_get_iter (model, &iter, path);
+ }
+ }
+ break;
+
+ default:
+ g_assert_not_reached ();
+ }
+ gtk_tree_path_free (path);
+ }
+
+ if (valid) {
+ tree_view_set_cursor_from_iter (view, &iter);
+ } else {
+ gtk_widget_error_bell (GTK_WIDGET (view));
+ }
+}
+
+static void
+tree_view_activate_focused_row (GtkTreeView *view)
+{
+ GtkTreePath *path;
+ GtkTreeViewColumn *column;
+
+ gtk_tree_view_get_cursor (view, &path, &column);
+ if (path) {
+ gtk_tree_view_row_activated (view, path, column);
+ gtk_tree_path_free (path);
+ }
+}
+static gboolean
+on_panel_key_press_event (GtkWidget *widget,
+ GdkEventKey *event,
+ gpointer dummy)
+{
+ switch (event->keyval) {
+ case GDK_KEY_Escape:
+ gtk_widget_hide (widget);
+ return TRUE;
+
+ case GDK_KEY_Tab:
+ /* avoid leaving the entry */
+ return TRUE;
+
+ case GDK_KEY_Return:
+ case GDK_KEY_KP_Enter:
+ case GDK_KEY_ISO_Enter:
+ tree_view_activate_focused_row (GTK_TREE_VIEW (kb_find_file.view));
+ return TRUE;
+
+ case GDK_KEY_Up:
+ case GDK_KEY_Down: {
+ tree_view_move_focus (GTK_TREE_VIEW (kb_find_file.view),
+ GTK_MOVEMENT_DISPLAY_LINES,
+ event->keyval == GDK_KEY_Up ? -1 : 1);
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+static void
+on_panel_show (GtkWidget *widget,
+ gpointer dummy)
+{
+ gtk_widget_grab_focus (GTK_ENTRY(kb_find_file.entry));
+}
+static void
+on_panel_hide (GtkWidget *widget,
+ gpointer dummy)
+{
+ GtkTreeView *view = GTK_TREE_VIEW (kb_find_file.view);
+ gtk_list_store_clear (kb_find_file.store);
+}
+static gboolean
+visible_func (GtkTreeModel *model,
+ GtkTreeIter *iter,
+ gpointer data)
+{
+ gchar *paths;
+ gtk_tree_model_get (model, iter, COL_FILE_NAME, &paths, -1);
+ gchar *haystack = g_utf8_casefold (paths, -1);
+ gchar *needle = g_utf8_casefold (data, -1);
+ gboolean score = TRUE;
+
+ if (data == NULL || haystack == NULL ||
+ *needle == '\0' || *haystack == '\0') {
+ return score;
+ }
+ score = (strstr(haystack, needle) == NULL)?FALSE:TRUE;
+ g_free (needle);
+ g_free (haystack);
+ g_free(paths);
+ return score;
+}
+static void
+on_entry_activate (GtkEntry *entry,
+ gpointer dummy)
+{
+ tree_view_activate_focused_row (GTK_TREE_VIEW (kb_find_file.view));
+}
+static void
+on_entry_text_notify (GObject *object,
+ GParamSpec *pspec,
+ gpointer dummy)
+{
+ guint16 key_length;
+ const gchar *key = gtk_entry_get_text (GTK_ENTRY (kb_find_file.entry));
+ key_length = gtk_entry_get_text_length(GTK_ENTRY (kb_find_file.entry));
+ if (key_length > 2)
+ {
+ GtkTreeIter iter;
+ GtkTreeView *view = GTK_TREE_VIEW (kb_find_file.view);
+ GtkTreeModel *model = gtk_tree_view_get_model (view);
+ gtk_tree_model_filter_refilter(GTK_TREE_MODEL_FILTER(model));
+ gtk_tree_model_filter_set_visible_func(GTK_TREE_MODEL_FILTER(model), visible_func, key, NULL);
+ if (gtk_tree_model_get_iter_first (model, &iter)) {
+ tree_view_set_cursor_from_iter (view, &iter);
+ }
+ }
+ else
+ {
+ if (key_length == 0){
+ on_panel_hide(NULL, NULL);
+ // gtk_window_resize(GTK_WINDOW(kb_find_file.panel), 100, 30);
+ // gtk_widget_hide(kb_find_file.scroll);
+ }
+ else if(key_length > 1){
+
+ GtkTreeViewColumn *col;
+ GtkCellRenderer *cell;
+ gchar *pattern_str;
+ GPatternSpec *pattern;
+ pattern_str = g_strconcat("*", key, "*", NULL);
+ SETPTR(pattern_str, g_utf8_strdown(pattern_str, -1));
+ gtk_window_resize(GTK_WINDOW(kb_find_file.panel), 100, 150);
+ pattern = g_pattern_spec_new(pattern_str);
+ prjorg_kb_find_file_in_active(pattern, kb_find_file.store);
+ kb_find_file.filter = gtk_tree_model_filter_new(GTK_TREE_MODEL (kb_find_file.store), NULL);
+ kb_find_file.view = gtk_tree_view_new_with_model (GTK_TREE_MODEL (kb_find_file.filter));
+ gtk_tree_model_filter_set_visible_func(GTK_TREE_MODEL_FILTER(kb_find_file.filter), visible_func, key, NULL);
+ g_signal_connect (kb_find_file.view, "row-activated",
+ G_CALLBACK (on_view_row_activated), NULL);
+ gtk_widget_set_can_focus (kb_find_file.view, FALSE);
+ gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (kb_find_file.view), FALSE);
+ cell = gtk_cell_renderer_text_new ();
+ g_object_set (cell, "ellipsize", PANGO_ELLIPSIZE_END, NULL);
+ col = gtk_tree_view_column_new_with_attributes (NULL, cell,
+ "markup", COL_FILE_LABEL,
+ NULL);
+ gtk_tree_view_append_column (kb_find_file.view, col);
+ gtk_container_add (GTK_CONTAINER (kb_find_file.scroll), kb_find_file.view);
+ gtk_widget_show_all(kb_find_file.scroll);
+ g_pattern_spec_free(pattern);
+ g_free(pattern_str);
+ }
+ }
+}
+static void
+fill_store (GtkListStore *store)
+{
+ //gchar *root_path = get_project_base_path();
+ GSList *elem = NULL;
+ foreach_slist (elem, prj_org->roots)
+ {
+ GHashTableIter iter;
+ gpointer key, value;
+ PrjOrgRoot *root = elem->data;
+ g_hash_table_iter_init(&iter, root->file_table);
+ while (g_hash_table_iter_next(&iter, &key, &value))
+ {
+ gchar *name = g_path_get_basename(key);
+ gchar *label = g_markup_printf_escaped ("%s\n"
+ "%s",
+ name,
+ key);
+
+
+ gtk_list_store_insert_with_values (store, NULL, -1,
+ COL_FILE_LABEL, label,
+ COL_FILE_NAME, key,
+ -1);
+ g_free (label);
+ g_free (name);
+ }
+}
+}
+
+static void
+create_panel (void)
+{
+ GtkWidget *frame;
+ GtkWidget *box;
+ kb_find_file.panel = g_object_new (GTK_TYPE_WINDOW,
+ "decorated", FALSE,
+ "default-width", 100,
+ "default-height", 30,
+ "transient-for", geany_data->main_widgets->window,
+ "window-position", GTK_WIN_POS_CENTER_ON_PARENT,
+ "type-hint", GDK_WINDOW_TYPE_HINT_DIALOG,
+ "skip-taskbar-hint", TRUE,
+ "skip-pager-hint", TRUE,
+ NULL);
+ frame = gtk_frame_new (NULL);
+ gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
+ g_signal_connect (kb_find_file.panel, "focus-out-event",
+ G_CALLBACK (gtk_widget_hide), NULL);
+ g_signal_connect (kb_find_file.panel, "show",
+ G_CALLBACK (on_panel_show), NULL);
+ g_signal_connect (kb_find_file.panel, "hide",
+ G_CALLBACK (on_panel_hide), NULL);
+ g_signal_connect (kb_find_file.panel, "key-press-event",
+ G_CALLBACK (on_panel_key_press_event), NULL);
+
+ gtk_container_add (GTK_CONTAINER (kb_find_file.panel), frame);
+ kb_find_file.store = gtk_list_store_new (COL_FILE_COUNT,
+ G_TYPE_STRING,
+ G_TYPE_STRING);
+ fill_store(kb_find_file.store);
+ box = gtk_vbox_new (FALSE, 0);
+ gtk_container_add (GTK_CONTAINER (frame), box);
+ kb_find_file.entry = gtk_entry_new();
+ gtk_box_pack_start (box, kb_find_file.entry, FALSE, TRUE, 0);
+ gtk_entry_set_width_chars(GTK_ENTRY(kb_find_file.entry), 40);
+ ui_entry_add_clear_icon(GTK_ENTRY(kb_find_file.entry));
+ gtk_entry_set_activates_default(GTK_ENTRY(kb_find_file.entry), TRUE);
+
+ g_signal_connect (kb_find_file.entry, "notify::text",
+ G_CALLBACK (on_entry_text_notify), NULL);
+ // g_signal_connect (kb_find_file.entry, "preedit-changed",
+ // G_CALLBACK (on_entry_preedit_notify), NULL);
+ g_signal_connect (kb_find_file.entry, "activate",
+ G_CALLBACK (on_entry_activate), NULL);
+ kb_find_file.scroll = g_object_new (GTK_TYPE_SCROLLED_WINDOW,
+ "hscrollbar-policy", GTK_POLICY_AUTOMATIC,
+ "vscrollbar-policy", GTK_POLICY_AUTOMATIC,
+ NULL);
+ gtk_box_pack_start ( GTK_BOX(box), kb_find_file.scroll, TRUE, TRUE, 0);
+ gtk_widget_show_all (frame);
+ gtk_widget_hide(kb_find_file.scroll);
+
+}
static void on_find_file(G_GNUC_UNUSED GtkMenuItem * menuitem, G_GNUC_UNUSED gpointer user_data)
{
- if (geany_data->app->project)
- prjorg_sidebar_find_file_in_active();
+ if (geany_data->app->project){
+ create_panel();
+ gtk_widget_show(kb_find_file.panel);
+
+ }
}
diff --git a/projectorganizer/src/prjorg-sidebar.c b/projectorganizer/src/prjorg-sidebar.c
index 3355e33ee..733cdd47f 100644
--- a/projectorganizer/src/prjorg-sidebar.c
+++ b/projectorganizer/src/prjorg-sidebar.c
@@ -518,7 +518,7 @@ static void on_delete(G_GNUC_UNUSED GtkMenuItem *menuitem, G_GNUC_UNUSED gpointe
}
-static void find_file_recursive(GtkTreeIter *iter, gboolean case_sensitive, gboolean full_path, GPatternSpec *pattern)
+static void find_file_recursive(GtkTreeIter *iter, gboolean case_sensitive, gboolean full_path, GPatternSpec *pattern, GtkListStore *find_file_store)
{
GtkTreeModel *model = GTK_TREE_MODEL(s_file_store);
GtkTreeIter child;
@@ -529,7 +529,7 @@ static void find_file_recursive(GtkTreeIter *iter, gboolean case_sensitive, gboo
{
while (iterate)
{
- find_file_recursive(&child, case_sensitive, full_path, pattern);
+ find_file_recursive(&child, case_sensitive, full_path, pattern, find_file_store);
iterate = gtk_tree_model_iter_next(model, &child);
}
}
@@ -593,7 +593,7 @@ static void find_file(GtkTreeIter *iter)
msgwin_clear_tab(MSG_MESSAGE);
msgwin_set_messages_dir(locale_base_path);
- find_file_recursive(iter, case_sensitive, is_full_path, pattern);
+ find_file_recursive(iter, case_sensitive, is_full_path, pattern, NULL);
msgwin_switch_tab(MSG_MESSAGE, TRUE);
g_free(utf8_base_path);
g_free(locale_base_path);
@@ -1480,6 +1480,14 @@ void prjorg_sidebar_update(gboolean reload)
plugin_idle_add(geany_plugin, (GSourceFunc)expand_on_idle, expand_data);
}
+void prjorg_kb_find_file_in_active(GPatternSpec *pattern, GtkListStore *find_file_store)
+{
+ // gchar *path = build_path(NULL);
+ if (pattern == NULL || find_file_store == NULL)
+ return;
+ find_file_recursive(NULL, FALSE, TRUE, pattern, find_file_store);
+ // g_free(path);
+}
void prjorg_sidebar_find_file_in_active(void)
{
diff --git a/projectorganizer/src/prjorg-sidebar.h b/projectorganizer/src/prjorg-sidebar.h
index 1b51fe211..82caecdf7 100644
--- a/projectorganizer/src/prjorg-sidebar.h
+++ b/projectorganizer/src/prjorg-sidebar.h
@@ -19,11 +19,15 @@
#ifndef __PRJORG_SIDEBAR_H__
#define __PRJORG_SIDEBAR_H__
-
+enum {
+ COL_FILE_LABEL,
+ COL_FILE_NAME,
+ COL_FILE_COUNT
+};
void prjorg_sidebar_init(void);
void prjorg_sidebar_cleanup(void);
void prjorg_sidebar_activate(gboolean activate);
-
+void prjorg_kb_find_file_in_active(GPatternSpec *pattern, GtkListStore *find_file_store);
void prjorg_sidebar_find_file_in_active(void);
void prjorg_sidebar_find_tag_in_active(void);