[geany/geany-plugins] fcaefc: Merge pull request #290 from eht16/spellcheck_suggestions_menu_issue_287
Frank Lanitz
git-noreply at xxxxx
Sun Oct 25 09:25:11 UTC 2015
Branch: refs/heads/master
Author: Frank Lanitz <frank at frank.uvena.de>
Committer: Frank Lanitz <frank at frank.uvena.de>
Date: Sun, 25 Oct 2015 09:25:11 UTC
Commit: fcaefcdad134e389629d43c74ba3927f9ba0ae02
https://github.com/geany/geany-plugins/commit/fcaefcdad134e389629d43c74ba3927f9ba0ae02
Log Message:
-----------
Merge pull request #290 from eht16/spellcheck_suggestions_menu_issue_287
Implement top-level spelling suggestions in editor menu (closes #287)
Modified Paths:
--------------
spellcheck/src/gui.c
spellcheck/src/gui.h
spellcheck/src/scplugin.c
spellcheck/src/scplugin.h
Modified: spellcheck/src/gui.c
254 lines changed, 178 insertions(+), 76 deletions(-)
===================================================================
@@ -238,17 +238,24 @@ static GtkWidget *image_menu_item_new(const gchar *stock_id, const gchar *label)
static GtkWidget *init_editor_submenu(void)
{
- if (sc_info->edit_menu_sub != NULL && GTK_IS_WIDGET(sc_info->edit_menu_sub))
- gtk_widget_destroy(sc_info->edit_menu_sub);
+ if (sc_info->show_editor_menu_item_sub_menu)
+ {
+ if (sc_info->edit_menu_sub != NULL && GTK_IS_WIDGET(sc_info->edit_menu_sub))
+ gtk_widget_destroy(sc_info->edit_menu_sub);
- sc_info->edit_menu_sub = gtk_menu_new();
- gtk_menu_item_set_submenu(GTK_MENU_ITEM(sc_info->edit_menu), sc_info->edit_menu_sub);
+ sc_info->edit_menu_sub = gtk_menu_new();
+ gtk_menu_item_set_submenu(GTK_MENU_ITEM(sc_info->edit_menu), sc_info->edit_menu_sub);
- gtk_widget_show(sc_info->edit_menu);
- gtk_widget_show(sc_info->edit_menu_sep);
- gtk_widget_show(sc_info->edit_menu_sub);
+ gtk_widget_show(sc_info->edit_menu);
+ gtk_widget_show(sc_info->edit_menu_sep);
+ gtk_widget_show(sc_info->edit_menu_sub);
- return sc_info->edit_menu_sub;
+ return sc_info->edit_menu_sub;
+ }
+ else
+ {
+ return geany->main_widgets->editor_menu;
+ }
}
@@ -286,6 +293,109 @@ void sc_gui_document_open_cb(GObject *obj, GeanyDocument *doc, gpointer user_dat
}
+static void menu_item_ref(GtkWidget *menu_item)
+{
+ if (! sc_info->show_editor_menu_item_sub_menu)
+ sc_info->edit_menu_items = g_slist_append(sc_info->edit_menu_items, menu_item);
+}
+
+
+static void update_editor_menu_items(const gchar *search_word, const gchar **suggs, gsize n_suggs)
+{
+ GtkWidget *menu_item, *menu, *sub_menu;
+ GSList *node;
+ gchar *label;
+ gsize i;
+
+ menu = init_editor_submenu();
+ sub_menu = menu;
+
+ /* display 5 suggestions on top level, 20 more in sub menu */
+ for (i = 0; i < MIN(n_suggs, 25); i++)
+ {
+ if (i >= 5 && menu == sub_menu)
+ {
+ /* create "More..." sub menu */
+ if (sc_info->show_editor_menu_item_sub_menu)
+ {
+ menu_item = gtk_separator_menu_item_new();
+ gtk_widget_show(menu_item);
+ gtk_menu_shell_append(GTK_MENU_SHELL(sub_menu), menu_item);
+ }
+
+ menu_item = gtk_menu_item_new_with_label(_("More..."));
+ gtk_widget_show(menu_item);
+ gtk_menu_shell_append(GTK_MENU_SHELL(sub_menu), menu_item);
+ menu_item_ref(menu_item);
+
+ sub_menu = gtk_menu_new();
+ gtk_menu_item_set_submenu(GTK_MENU_ITEM(menu_item), sub_menu);
+ }
+ menu_item = gtk_menu_item_new_with_label(suggs[i]);
+ gtk_widget_show(menu_item);
+ gtk_container_add(GTK_CONTAINER(sub_menu), menu_item);
+ if (menu == sub_menu)
+ {
+ /* Remember menu items to delete only for the top-level, the nested menu items are
+ * destroyed recursively via the sub menu */
+ menu_item_ref(menu_item);
+ }
+ g_signal_connect(menu_item, "activate", G_CALLBACK(menu_suggestion_item_activate_cb), NULL);
+ }
+ if (suggs == NULL)
+ {
+ menu_item = gtk_menu_item_new_with_label(_("(No Suggestions)"));
+ gtk_widget_set_sensitive(menu_item, FALSE);
+ gtk_widget_show(menu_item);
+ gtk_container_add(GTK_CONTAINER(menu), menu_item);
+ menu_item_ref(menu_item);
+ }
+ if (sc_info->show_editor_menu_item_sub_menu)
+ {
+ menu_item = gtk_separator_menu_item_new();
+ gtk_widget_show(menu_item);
+ gtk_container_add(GTK_CONTAINER(menu), menu_item);
+ }
+
+ label = g_strdup_printf(_("Add \"%s\" to Dictionary"), search_word);
+ menu_item = image_menu_item_new(GTK_STOCK_ADD, label);
+ gtk_widget_show(menu_item);
+ gtk_container_add(GTK_CONTAINER(menu), menu_item);
+ menu_item_ref(menu_item);
+ g_signal_connect(menu_item, "activate",
+ G_CALLBACK(menu_addword_item_activate_cb), GINT_TO_POINTER(FALSE));
+
+ menu_item = image_menu_item_new(GTK_STOCK_REMOVE, _("Ignore All"));
+ gtk_widget_show(menu_item);
+ gtk_container_add(GTK_CONTAINER(menu), menu_item);
+ menu_item_ref(menu_item);
+ g_signal_connect(menu_item, "activate",
+ G_CALLBACK(menu_addword_item_activate_cb), GINT_TO_POINTER(TRUE));
+
+ g_free(label);
+
+ /* re-order menu items: above all menu items are append but for the top-level menu items
+ * we want them to appear at the top of the editor menu */
+ if (! sc_info->show_editor_menu_item_sub_menu)
+ {
+ gpointer child;
+ /* final separator */
+ menu_item = gtk_separator_menu_item_new();
+ gtk_widget_show(menu_item);
+ gtk_container_add(GTK_CONTAINER(menu), menu_item);
+ menu_item_ref(menu_item);
+ /* re-order */
+ i = 0;
+ foreach_slist(node, sc_info->edit_menu_items)
+ {
+ child = node->data;
+ gtk_menu_reorder_child(GTK_MENU(menu), GTK_WIDGET(child), i);
+ i++;
+ }
+ }
+}
+
+
void sc_gui_update_editor_menu_cb(GObject *obj, const gchar *word, gint pos,
GeanyDocument *doc, gpointer user_data)
{
@@ -294,8 +404,16 @@ void sc_gui_update_editor_menu_cb(GObject *obj, const gchar *word, gint pos,
g_return_if_fail(doc != NULL && doc->is_valid);
/* hide the submenu in any case, we will reshow it again if we actually found something */
- gtk_widget_hide(sc_info->edit_menu);
- gtk_widget_hide(sc_info->edit_menu_sep);
+ if (sc_info->edit_menu != NULL)
+ gtk_widget_hide(sc_info->edit_menu);
+ if (sc_info->edit_menu_sep != NULL)
+ gtk_widget_hide(sc_info->edit_menu_sep);
+ /* clean previously added items to the editor menu */
+ if (sc_info->edit_menu_items != NULL)
+ {
+ g_slist_free_full(sc_info->edit_menu_items, (GDestroyNotify) gtk_widget_destroy);
+ sc_info->edit_menu_items = NULL;
+ }
if (! sc_info->show_editor_menu_item)
return;
@@ -320,18 +438,20 @@ void sc_gui_update_editor_menu_cb(GObject *obj, const gchar *word, gint pos,
/* ignore too long search words */
if (strlen(search_word) > 100)
{
- GtkWidget *menu_item;
+ GtkWidget *menu_item, *menu;
- init_editor_submenu();
+ menu = init_editor_submenu();
menu_item = gtk_menu_item_new_with_label(
_("Search term is too long to provide\nspelling suggestions in the editor menu."));
gtk_widget_set_sensitive(menu_item, FALSE);
gtk_widget_show(menu_item);
- gtk_container_add(GTK_CONTAINER(sc_info->edit_menu_sub), menu_item);
+ gtk_container_add(GTK_CONTAINER(menu), menu_item);
+ menu_item_ref(menu_item);
menu_item = gtk_menu_item_new_with_label(_("Perform Spell Check"));
gtk_widget_show(menu_item);
- gtk_container_add(GTK_CONTAINER(sc_info->edit_menu_sub), menu_item);
+ gtk_container_add(GTK_CONTAINER(menu), menu_item);
+ menu_item_ref(menu_item);
g_signal_connect(menu_item, "activate", G_CALLBACK(perform_spell_check_cb), doc);
g_free(search_word);
@@ -340,9 +460,7 @@ void sc_gui_update_editor_menu_cb(GObject *obj, const gchar *word, gint pos,
if (sc_speller_dict_check(search_word) != 0)
{
- GtkWidget *menu_item, *menu;
- gchar *label;
- gsize n_suggs, i;
+ gsize n_suggs;
gchar **suggs;
suggs = sc_speller_dict_suggest(search_word, &n_suggs);
@@ -351,61 +469,14 @@ void sc_gui_update_editor_menu_cb(GObject *obj, const gchar *word, gint pos,
clickinfo.doc = doc;
setptr(clickinfo.word, search_word);
- menu = init_editor_submenu();
-
- for (i = 0; i < n_suggs; i++)
- {
- if (i > 0 && i % 10 == 0)
- {
- menu_item = gtk_menu_item_new();
- gtk_widget_show(menu_item);
- gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item);
-
- menu_item = gtk_menu_item_new_with_label(_("More..."));
- gtk_widget_show(menu_item);
- gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item);
-
- menu = gtk_menu_new();
- gtk_menu_item_set_submenu(GTK_MENU_ITEM(menu_item), menu);
- }
- menu_item = gtk_menu_item_new_with_label(suggs[i]);
- gtk_widget_show(menu_item);
- gtk_container_add(GTK_CONTAINER(menu), menu_item);
- g_signal_connect(menu_item, "activate",
- G_CALLBACK(menu_suggestion_item_activate_cb), NULL);
- }
- if (suggs == NULL)
- {
- menu_item = gtk_menu_item_new_with_label(_("(No Suggestions)"));
- gtk_widget_set_sensitive(menu_item, FALSE);
- gtk_widget_show(menu_item);
- gtk_container_add(GTK_CONTAINER(sc_info->edit_menu_sub), menu_item);
- }
- menu_item = gtk_separator_menu_item_new();
- gtk_widget_show(menu_item);
- gtk_container_add(GTK_CONTAINER(sc_info->edit_menu_sub), menu_item);
-
- label = g_strdup_printf(_("Add \"%s\" to Dictionary"), search_word);
- menu_item = image_menu_item_new(GTK_STOCK_ADD, label);
- gtk_widget_show(menu_item);
- gtk_container_add(GTK_CONTAINER(sc_info->edit_menu_sub), menu_item);
- g_signal_connect(menu_item, "activate",
- G_CALLBACK(menu_addword_item_activate_cb), GINT_TO_POINTER(FALSE));
-
- menu_item = image_menu_item_new(GTK_STOCK_REMOVE, _("Ignore All"));
- gtk_widget_show(menu_item);
- gtk_container_add(GTK_CONTAINER(sc_info->edit_menu_sub), menu_item);
- g_signal_connect(menu_item, "activate",
- G_CALLBACK(menu_addword_item_activate_cb), GINT_TO_POINTER(TRUE));
+ update_editor_menu_items(search_word, (const gchar**) suggs, n_suggs);
if (suggs != NULL)
sc_speller_dict_free_string_list(suggs);
-
- g_free(label);
}
else
{
- g_free(search_word);
+ g_free(search_word); /* search_word is free'd via clickinfo.word otherwise */
}
}
@@ -602,17 +673,41 @@ void sc_gui_kb_toggle_typing_activate_cb(guint key_id)
}
-void sc_gui_create_edit_menu(void)
+static void free_editor_menu_items(void)
+{
+ if (sc_info->edit_menu != NULL)
+ {
+ gtk_widget_destroy(sc_info->edit_menu);
+ sc_info->edit_menu = NULL;
+ }
+ if (sc_info->edit_menu_sep != NULL)
+ {
+ gtk_widget_destroy(sc_info->edit_menu_sep);
+ sc_info->edit_menu_sep = NULL;
+ }
+ if (sc_info->edit_menu_items != NULL)
+ {
+ g_slist_free_full(sc_info->edit_menu_items, (GDestroyNotify) gtk_widget_destroy);
+ sc_info->edit_menu_items = NULL;
+ }
+}
+
+
+void sc_gui_recreate_editor_menu(void)
{
- sc_info->edit_menu = ui_image_menu_item_new(GTK_STOCK_SPELL_CHECK, _("Spelling Suggestions"));
- gtk_container_add(GTK_CONTAINER(geany->main_widgets->editor_menu), sc_info->edit_menu);
- gtk_menu_reorder_child(GTK_MENU(geany->main_widgets->editor_menu), sc_info->edit_menu, 0);
+ free_editor_menu_items();
+ if (sc_info->show_editor_menu_item_sub_menu)
+ {
+ sc_info->edit_menu = ui_image_menu_item_new(GTK_STOCK_SPELL_CHECK, _("Spelling Suggestions"));
+ gtk_container_add(GTK_CONTAINER(geany->main_widgets->editor_menu), sc_info->edit_menu);
+ gtk_menu_reorder_child(GTK_MENU(geany->main_widgets->editor_menu), sc_info->edit_menu, 0);
- sc_info->edit_menu_sep = gtk_separator_menu_item_new();
- gtk_container_add(GTK_CONTAINER(geany->main_widgets->editor_menu), sc_info->edit_menu_sep);
- gtk_menu_reorder_child(GTK_MENU(geany->main_widgets->editor_menu), sc_info->edit_menu_sep, 1);
+ sc_info->edit_menu_sep = gtk_separator_menu_item_new();
+ gtk_container_add(GTK_CONTAINER(geany->main_widgets->editor_menu), sc_info->edit_menu_sep);
+ gtk_menu_reorder_child(GTK_MENU(geany->main_widgets->editor_menu), sc_info->edit_menu_sep, 1);
- gtk_widget_show_all(sc_info->edit_menu);
+ gtk_widget_show_all(sc_info->edit_menu);
+ }
}
@@ -665,6 +760,12 @@ void sc_gui_update_menu(void)
void sc_gui_init(void)
{
clickinfo.word = NULL;
+ sc_info->edit_menu_items = NULL;
+ sc_info->edit_menu = NULL;
+ sc_info->edit_menu_sep = NULL;
+ sc_info->edit_menu_items = NULL;
+
+ sc_gui_recreate_editor_menu();
}
@@ -672,7 +773,8 @@ void sc_gui_free(void)
{
g_free(clickinfo.word);
if (check_line_data.check_while_typing_idle_source_id != 0)
- {
g_source_remove(check_line_data.check_while_typing_idle_source_id);
- }
+ if (sc_info->toolbar_button != NULL)
+ gtk_widget_destroy(GTK_WIDGET(sc_info->toolbar_button));
+ free_editor_menu_items();
}
Modified: spellcheck/src/gui.h
2 lines changed, 1 insertions(+), 1 deletions(-)
===================================================================
@@ -31,7 +31,7 @@ void sc_gui_kb_run_activate_cb(guint key_id);
void sc_gui_kb_toggle_typing_activate_cb(guint key_id);
-void sc_gui_create_edit_menu(void);
+void sc_gui_recreate_editor_menu(void);
void sc_gui_update_editor_menu_cb(GObject *obj, const gchar *word, gint pos,
GeanyDocument *doc, gpointer user_data);
Modified: spellcheck/src/scplugin.c
48 lines changed, 39 insertions(+), 9 deletions(-)
===================================================================
@@ -126,6 +126,9 @@ static void configure_response_cb(GtkDialog *dialog, gint response, gpointer use
sc_info->show_editor_menu_item = (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(
g_object_get_data(G_OBJECT(dialog), "check_editor_menu"))));
+ sc_info->show_editor_menu_item_sub_menu = (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(
+ g_object_get_data(G_OBJECT(dialog), "check_editor_menu_sub_menu"))));
+
g_key_file_load_from_file(config, sc_info->config_file, G_KEY_FILE_NONE, NULL);
if (sc_info->default_language != NULL) /* lang may be NULL */
g_key_file_set_string(config, "spellcheck", "language", sc_info->default_language);
@@ -139,10 +142,13 @@ static void configure_response_cb(GtkDialog *dialog, gint response, gpointer use
sc_info->show_toolbar_item);
g_key_file_set_boolean(config, "spellcheck", "show_editor_menu_item",
sc_info->show_editor_menu_item);
- if (sc_info->dictionary_dir != NULL)
+ g_key_file_set_boolean(config, "spellcheck", "show_editor_menu_item_sub_menu",
+ sc_info->show_editor_menu_item_sub_menu);
+ if (sc_info->dictionary_dir != NULL)
g_key_file_set_string(config, "spellcheck", "dictionary_dir",
sc_info->dictionary_dir);
+ sc_gui_recreate_editor_menu();
sc_gui_update_toolbar();
sc_gui_update_menu();
populate_dict_combo(combo);
@@ -188,6 +194,8 @@ void plugin_init(GeanyData *data)
"spellcheck", "show_toolbar_item", TRUE);
sc_info->show_editor_menu_item = utils_get_setting_boolean(config,
"spellcheck", "show_editor_menu_item", TRUE);
+ sc_info->show_editor_menu_item_sub_menu = utils_get_setting_boolean(config,
+ "spellcheck", "show_editor_menu_item_sub_menu", TRUE);
sc_info->dictionary_dir = utils_get_setting_string(config,
"spellcheck", "dictionary_dir", NULL);
sc_info->use_msgwin = utils_get_setting_boolean(config, "spellcheck", "use_msgwin", FALSE);
@@ -202,7 +210,6 @@ void plugin_init(GeanyData *data)
sc_gui_init();
sc_speller_init();
- sc_gui_create_edit_menu();
sc_gui_update_menu();
gtk_widget_show_all(sc_info->menu_item);
@@ -250,10 +257,21 @@ static void dictionary_dir_button_clicked_cb(GtkButton *button, gpointer item)
#endif
+static void configure_frame_editor_menu_toggled_cb(GtkToggleButton *togglebutton, gpointer data)
+{
+ gboolean sens = gtk_toggle_button_get_active(togglebutton);
+
+ gtk_widget_set_sensitive(g_object_get_data(G_OBJECT(data),
+ "check_editor_menu_sub_menu"), sens);
+}
+
+
GtkWidget *plugin_configure(GtkDialog *dialog)
{
GtkWidget *label_language, *label_dir, *vbox;
- GtkWidget *combo, *check_type, *check_on_open, *check_msgwin, *check_toolbar, *check_editor_menu;
+ GtkWidget *combo, *check_type, *check_on_open, *check_msgwin, *check_toolbar;
+ GtkWidget *frame_editor_menu, *check_editor_menu;
+ GtkWidget *check_editor_menu_sub_menu, *align_editor_menu_sub_menu;
GtkWidget *vbox_interface, *frame_interface, *label_interface;
GtkWidget *vbox_behavior, *frame_behavior, *label_behavior;
#ifdef HAVE_ENCHANT_1_5
@@ -271,13 +289,28 @@ GtkWidget *plugin_configure(GtkDialog *dialog)
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check_editor_menu),
sc_info->show_editor_menu_item);
+ check_editor_menu_sub_menu = gtk_check_button_new_with_label(
+ _("Show suggestions in a sub menu of the editor menu"));
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check_editor_menu_sub_menu),
+ sc_info->show_editor_menu_item_sub_menu);
+ align_editor_menu_sub_menu = gtk_alignment_new(0.5, 0.5, 1, 1);
+ gtk_alignment_set_padding(GTK_ALIGNMENT(align_editor_menu_sub_menu), 0, 0, 9, 0);
+ gtk_container_add(GTK_CONTAINER(align_editor_menu_sub_menu), check_editor_menu_sub_menu);
+
+ frame_editor_menu = gtk_frame_new(NULL);
+ gtk_frame_set_label_widget(GTK_FRAME(frame_editor_menu), check_editor_menu);
+ gtk_container_set_border_width(GTK_CONTAINER(frame_editor_menu), 3);
+ gtk_container_add(GTK_CONTAINER(frame_editor_menu), align_editor_menu_sub_menu);
+ g_signal_connect(check_editor_menu, "toggled",
+ G_CALLBACK(configure_frame_editor_menu_toggled_cb), dialog);
+
check_msgwin = gtk_check_button_new_with_label(
_("Print misspelled words and suggestions in the messages window"));
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check_msgwin), sc_info->use_msgwin);
vbox_interface = gtk_vbox_new(FALSE, 0);
gtk_box_pack_start(GTK_BOX(vbox_interface), check_toolbar, FALSE, FALSE, 3);
- gtk_box_pack_start(GTK_BOX(vbox_interface), check_editor_menu, TRUE, TRUE, 3);
+ gtk_box_pack_start(GTK_BOX(vbox_interface), frame_editor_menu, TRUE, TRUE, 3);
gtk_box_pack_start(GTK_BOX(vbox_interface), check_msgwin, TRUE, TRUE, 3);
label_interface = gtk_label_new(NULL);
@@ -362,8 +395,10 @@ GtkWidget *plugin_configure(GtkDialog *dialog)
g_object_set_data(G_OBJECT(dialog), "check_msgwin", check_msgwin);
g_object_set_data(G_OBJECT(dialog), "check_toolbar", check_toolbar);
g_object_set_data(G_OBJECT(dialog), "check_editor_menu", check_editor_menu);
+ g_object_set_data(G_OBJECT(dialog), "check_editor_menu_sub_menu", check_editor_menu_sub_menu);
g_signal_connect(dialog, "response", G_CALLBACK(configure_response_cb), NULL);
+ configure_frame_editor_menu_toggled_cb(GTK_TOGGLE_BUTTON(check_editor_menu), dialog);
gtk_widget_show_all(vbox);
return vbox;
@@ -391,11 +426,6 @@ void plugin_help(void)
void plugin_cleanup(void)
{
- gtk_widget_destroy(sc_info->edit_menu);
- gtk_widget_destroy(sc_info->edit_menu_sep);
- if (sc_info->toolbar_button != NULL)
- gtk_widget_destroy(GTK_WIDGET(sc_info->toolbar_button));
-
sc_gui_free();
sc_speller_free();
Modified: spellcheck/src/scplugin.h
2 lines changed, 2 insertions(+), 0 deletions(-)
===================================================================
@@ -38,6 +38,7 @@ typedef struct
gboolean check_on_document_open;
gboolean show_toolbar_item;
gboolean show_editor_menu_item;
+ gboolean show_editor_menu_item_sub_menu;
GPtrArray *dicts;
GtkWidget *main_menu;
GtkWidget *menu_item;
@@ -46,6 +47,7 @@ typedef struct
GtkWidget *edit_menu_sep;
GtkWidget *edit_menu_sub;
GtkToolItem *toolbar_button;
+ GSList *edit_menu_items;
} SpellCheck;
--------------
This E-Mail was brought to you by github_commit_mail.py (Source: https://github.com/geany/infrastructure).
More information about the Plugins-Commits
mailing list