diff --git a/commander/src/commander-plugin.c b/commander/src/commander-plugin.c index 62b0fb7ca..de1b1f6eb 100644 --- a/commander/src/commander-plugin.c +++ b/commander/src/commander-plugin.c @@ -1,20 +1,20 @@ /* - * + * * Copyright (C) 2012 Colomban Wendling - * + * * 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 3 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, see . - * + * */ #include "config.h" @@ -90,7 +90,7 @@ struct { GtkWidget *view; GtkListStore *store; GtkTreeModel *sort; - + GtkTreePath *last_path; } plugin_data = { NULL, NULL, NULL, @@ -133,7 +133,7 @@ get_score (const gchar *needle, } else if (! *needle || ! *haystack) { return *needle == 0; } - + if (IS_SEPARATOR (*haystack)) { return get_score (needle + IS_SEPARATOR (*needle), haystack + 1); } @@ -145,7 +145,7 @@ get_score (const gchar *needle, if (*needle == *haystack) { gint a = get_score (needle + 1, haystack + 1) + 1 + IS_SEPARATOR (haystack[1]); gint b = get_score (needle, next_separator (haystack)); - + return MAX (a, b); } else { return get_score (needle, next_separator (haystack)); @@ -174,12 +174,12 @@ key_score (const gchar *key_, gchar *text = g_utf8_casefold (text_, -1); gchar *key = g_utf8_casefold (key_, -1); gint score; - + score = get_score (key, text) + get_score (key, path_basename (text)) / 2; - + g_free (text); g_free (key); - + return score; } @@ -188,7 +188,7 @@ get_key (gint *type_) { gint type = COL_TYPE_ANY; const gchar *key = gtk_entry_get_text (GTK_ENTRY (plugin_data.entry)); - + if (g_str_has_prefix (key, "f:")) { key += 2; type = COL_TYPE_FILE; @@ -196,11 +196,11 @@ get_key (gint *type_) key += 2; type = COL_TYPE_MENU_ITEM; } - + if (type_) { *type_ = type; } - + return key; } @@ -209,7 +209,7 @@ 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); @@ -224,7 +224,7 @@ tree_view_move_focus (GtkTreeView *view, 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); @@ -234,14 +234,14 @@ tree_view_move_focus (GtkTreeView *view, 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; - + case GTK_MOVEMENT_PAGES: /* FIXME: move by page */ case GTK_MOVEMENT_DISPLAY_LINES: @@ -253,19 +253,19 @@ tree_view_move_focus (GtkTreeView *view, } 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 { @@ -278,7 +278,7 @@ 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); @@ -293,7 +293,7 @@ store_populate_menu_items (GtkListStore *store, { GList *children; GList *node; - + children = gtk_container_get_children (GTK_CONTAINER (menu)); for (node = children; node; node = node->next) { if (GTK_IS_SEPARATOR_MENU_ITEM (node->data) || @@ -305,7 +305,7 @@ store_populate_menu_items (GtkListStore *store, gchar *item_label; gboolean use_underline; GtkStockItem item; - + /* GtkStock is deprectaed since GTK 3.10, but we have to use it in order * to get the actual label of the menu item */ G_GNUC_BEGIN_IGNORE_DEPRECATIONS @@ -319,25 +319,25 @@ store_populate_menu_items (GtkListStore *store, use_underline = gtk_menu_item_get_use_underline (node->data); } G_GNUC_END_IGNORE_DEPRECATIONS - + /* remove underlines */ if (use_underline) { gchar *p = item_label; gsize len = strlen (p); - + while ((p = strchr (p, '_')) != NULL) { len -= (gsize) (p - item_label); - + memmove (p, p + 1, len); } } - + if (parent_path) { path = g_strconcat (parent_path, PATH_SEPARATOR, item_label, NULL); } else { path = g_strdup (item_label); } - + submenu = gtk_menu_item_get_submenu (node->data); if (submenu) { /* go deeper in the menus... */ @@ -345,28 +345,39 @@ store_populate_menu_items (GtkListStore *store, } else { gchar *tmp; gchar *tooltip; - gchar *label = g_markup_printf_escaped ("%s", item_label); - + gchar *basename = g_path_get_basename (item_label); + gchar *dirname = g_path_get_dirname (item_label); + gchar *dirname_basename = g_path_get_basename(dirname); + gchar *label; + if (g_strcmp0(".", dirname_basename) == 0) { + label = g_markup_printf_escaped ("%s", basename); + } else { + label = g_markup_printf_escaped ("%s/%s", dirname_basename, basename); + } + tooltip = gtk_widget_get_tooltip_markup (node->data); if (tooltip) { SETPTR (label, g_strconcat (label, "\n", tooltip, "", NULL)); g_free (tooltip); } - + tmp = g_markup_escape_text (path, -1); SETPTR (label, g_strconcat (label, "\n", tmp, "", NULL)); g_free (tmp); - + gtk_list_store_insert_with_values (store, NULL, -1, COL_LABEL, label, COL_PATH, path, COL_TYPE, COL_TYPE_MENU_ITEM, COL_WIDGET, node->data, -1); - + g_free (label); + g_free (basename); + g_free (dirname); + g_free (dirname_basename); } - + g_free (item_label); g_free (path); } else { @@ -383,7 +394,7 @@ find_menubar (GtkContainer *container) GList *children; GList *node; GtkWidget *menubar = NULL; - + children = gtk_container_get_children (container); for (node = children; ! menubar && node; node = node->next) { if (GTK_IS_MENU_BAR (node->data)) { @@ -393,7 +404,7 @@ find_menubar (GtkContainer *container) } } g_list_free (children); - + return menubar; } @@ -402,19 +413,22 @@ fill_store (GtkListStore *store) { GtkWidget *menubar; guint i = 0; - + /* menu items */ menubar = find_menubar (GTK_CONTAINER (geany_data->main_widgets->window)); store_populate_menu_items (store, GTK_MENU_SHELL (menubar), NULL); - + /* open files */ foreach_document (i) { gchar *basename = g_path_get_basename (DOC_FILENAME (documents[i])); - gchar *label = g_markup_printf_escaped ("%s\n" + gchar *dirname = g_path_get_dirname (DOC_FILENAME (documents[i])); + gchar *dirname_basename = g_path_get_basename(dirname); + gchar *label = g_markup_printf_escaped ("%s/%s\n" "%s", + dirname_basename, basename, DOC_FILENAME (documents[i])); - + gtk_list_store_insert_with_values (store, NULL, -1, COL_LABEL, label, COL_PATH, DOC_FILENAME (documents[i]), @@ -422,6 +436,8 @@ fill_store (GtkListStore *store) COL_DOCUMENT, documents[i], -1); g_free (basename); + g_free (dirname); + g_free (dirname_basename); g_free (label); } } @@ -440,23 +456,23 @@ sort_func (GtkTreeModel *model, gint typeb; gint type; const gchar *key = get_key (&type); - + gtk_tree_model_get (model, a, COL_PATH, &patha, COL_TYPE, &typea, -1); gtk_tree_model_get (model, b, COL_PATH, &pathb, COL_TYPE, &typeb, -1); - + scorea = key_score (key, patha); scoreb = key_score (key, pathb); - + if (! (typea & type)) { scorea -= 0xf000; } if (! (typeb & type)) { scoreb -= 0xf000; } - + g_free (patha); g_free (pathb); - + return scoreb - scorea; } @@ -469,24 +485,24 @@ on_panel_key_press_event (GtkWidget *widget, 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 (plugin_data.view)); return TRUE; - + case GDK_KEY_Page_Up: case GDK_KEY_Page_Down: tree_view_move_focus (GTK_TREE_VIEW (plugin_data.view), GTK_MOVEMENT_PAGES, event->keyval == GDK_KEY_Page_Up ? -1 : 1); return TRUE; - + case GDK_KEY_Up: case GDK_KEY_Down: { tree_view_move_focus (GTK_TREE_VIEW (plugin_data.view), @@ -495,7 +511,7 @@ on_panel_key_press_event (GtkWidget *widget, return TRUE; } } - + return FALSE; } @@ -507,7 +523,7 @@ on_entry_text_notify (GObject *object, GtkTreeIter iter; GtkTreeView *view = GTK_TREE_VIEW (plugin_data.view); GtkTreeModel *model = gtk_tree_view_get_model (view); - + /* we force re-sorting the whole model from how it was before, and the * back to the new filter. this is somewhat hackish but since we don't * know the original sorting order, and GtkTreeSortable don't have a @@ -515,7 +531,7 @@ on_entry_text_notify (GObject *object, gtk_tree_model_sort_reset_default_sort_func (GTK_TREE_MODEL_SORT (model)); gtk_tree_sortable_set_default_sort_func (GTK_TREE_SORTABLE (model), sort_func, NULL, NULL); - + if (gtk_tree_model_get_iter_first (model, &iter)) { tree_view_set_cursor_from_iter (view, &iter); } @@ -533,13 +549,13 @@ on_panel_hide (GtkWidget *widget, gpointer dummy) { GtkTreeView *view = GTK_TREE_VIEW (plugin_data.view); - + if (plugin_data.last_path) { gtk_tree_path_free (plugin_data.last_path); plugin_data.last_path = NULL; } gtk_tree_view_get_cursor (view, &plugin_data.last_path, NULL); - + gtk_list_store_clear (plugin_data.store); } @@ -549,11 +565,11 @@ on_panel_show (GtkWidget *widget, { GtkTreePath *path; GtkTreeView *view = GTK_TREE_VIEW (plugin_data.view); - + fill_store (plugin_data.store); - + gtk_widget_grab_focus (plugin_data.entry); - + if (plugin_data.last_path) { gtk_tree_view_set_cursor (view, plugin_data.last_path, NULL, FALSE); gtk_tree_view_scroll_to_cell (view, plugin_data.last_path, NULL, @@ -565,7 +581,7 @@ on_panel_show (GtkWidget *widget, gtk_tree_path_free (path); } else { GtkTreeIter iter; - + if (gtk_tree_model_get_iter_first (gtk_tree_view_get_model (view), &iter)) { tree_view_set_cursor_from_iter (GTK_TREE_VIEW (plugin_data.view), &iter); } @@ -580,31 +596,31 @@ on_view_row_activated (GtkTreeView *view, { GtkTreeModel *model = gtk_tree_view_get_model (view); GtkTreeIter iter; - + if (gtk_tree_model_get_iter (model, &iter, path)) { gint type; - + gtk_tree_model_get (model, &iter, COL_TYPE, &type, -1); - + switch (type) { case COL_TYPE_FILE: { GeanyDocument *doc; gint page; - + gtk_tree_model_get (model, &iter, COL_DOCUMENT, &doc, -1); page = document_get_notebook_page (doc); gtk_notebook_set_current_page (GTK_NOTEBOOK (geany_data->main_widgets->notebook), page); break; } - + case COL_TYPE_MENU_ITEM: { GtkMenuItem *item; - + gtk_tree_model_get (model, &iter, COL_WIDGET, &item, -1); gtk_menu_item_activate (item); g_object_unref (item); - + break; } } @@ -627,24 +643,24 @@ score_cell_data (GtkTreeViewColumn *column, gint type; gint width, old_width; const gchar *key = get_key (&type); - + gtk_tree_model_get (model, iter, COL_PATH, &path, COL_TYPE, &pathtype, -1); - + score = key_score (key, path); if (! (pathtype & type)) { score -= 0xf000; } - + text = g_strdup_printf ("%d", score); g_object_set (cell, "text", text, NULL); - + /* automatic column sizing is buggy, so just make an acceptable wild guess */ width = 8 + strlen (text) * 10; old_width = gtk_tree_view_column_get_fixed_width (col); if (old_width < width) { gtk_tree_view_column_set_fixed_width (col, width); } - + g_free (text); g_free (path); } @@ -658,10 +674,17 @@ create_panel (void) GtkWidget *scroll; GtkTreeViewColumn *col; GtkCellRenderer *cell; - + + int window_width; + int window_height; + gtk_window_get_size(GTK_WINDOW(geany_data->main_widgets->window), &window_width, &window_height); + if (window_width >= 500) { + window_width = window_width / 2; + } + plugin_data.panel = g_object_new (GTK_TYPE_WINDOW, "decorated", FALSE, - "default-width", 500, + "default-width", window_width, "default-height", 200, "transient-for", geany_data->main_widgets->window, "window-position", GTK_WIN_POS_CENTER_ON_PARENT, @@ -677,35 +700,35 @@ create_panel (void) G_CALLBACK (on_panel_hide), NULL); g_signal_connect (plugin_data.panel, "key-press-event", G_CALLBACK (on_panel_key_press_event), NULL); - + frame = gtk_frame_new (NULL); gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN); gtk_container_add (GTK_CONTAINER (plugin_data.panel), frame); - + box = gtk_vbox_new (FALSE, 0); gtk_container_add (GTK_CONTAINER (frame), box); - + plugin_data.entry = gtk_entry_new (); gtk_box_pack_start (GTK_BOX (box), plugin_data.entry, FALSE, TRUE, 0); - + plugin_data.store = gtk_list_store_new (COL_COUNT, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INT, GTK_TYPE_WIDGET, G_TYPE_POINTER); - + plugin_data.sort = gtk_tree_model_sort_new_with_model (GTK_TREE_MODEL (plugin_data.store)); gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (plugin_data.sort), GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID, GTK_SORT_ASCENDING); - + 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), scroll, TRUE, TRUE, 0); - + plugin_data.view = gtk_tree_view_new_with_model (GTK_TREE_MODEL (plugin_data.sort)); gtk_widget_set_can_focus (plugin_data.view, FALSE); gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (plugin_data.view), FALSE); @@ -725,13 +748,13 @@ create_panel (void) g_signal_connect (plugin_data.view, "row-activated", G_CALLBACK (on_view_row_activated), NULL); gtk_container_add (GTK_CONTAINER (scroll), plugin_data.view); - + /* connect entry signals after the view is created as they use it */ g_signal_connect (plugin_data.entry, "notify::text", G_CALLBACK (on_entry_text_notify), NULL); g_signal_connect (plugin_data.entry, "activate", G_CALLBACK (on_entry_activate), NULL); - + gtk_widget_show_all (frame); } @@ -741,12 +764,12 @@ on_kb_show_panel (GeanyKeyBinding *kb, gpointer data) { const gchar *prefix = data; - + gtk_widget_show (plugin_data.panel); - + if (prefix) { const gchar *key = gtk_entry_get_text (GTK_ENTRY (plugin_data.entry)); - + if (! g_str_has_prefix (key, prefix)) { gtk_entry_set_text (GTK_ENTRY (plugin_data.entry), prefix); } @@ -754,7 +777,7 @@ on_kb_show_panel (GeanyKeyBinding *kb, gtk_editable_select_region (GTK_EDITABLE (plugin_data.entry), g_utf8_strlen (prefix, -1), -1); } - + return TRUE; } @@ -762,7 +785,7 @@ static gboolean on_plugin_idle_init (gpointer dummy) { create_panel (); - + return FALSE; } @@ -770,7 +793,7 @@ void plugin_init (GeanyData *data) { GeanyKeyGroup *group; - + group = plugin_set_key_group (geany_plugin, "commander", KB_COUNT, NULL); keybindings_set_item_full (group, KB_SHOW_PANEL, 0, 0, "show_panel", _("Show Command Panel"), NULL, @@ -783,7 +806,7 @@ plugin_init (GeanyData *data) "show_panel_files", _("Show Command Panel (Files Only)"), NULL, on_kb_show_panel, (gpointer) "f:", NULL); - + /* delay for other plugins to have a chance to load before, so we will * include their items */ plugin_idle_add (geany_plugin, on_plugin_idle_init, NULL);