diff --git a/ChangeLog b/ChangeLog index e9dc64a1880af20746d909d92a3649d642ed0f7d..f36d4c6ac40a2779495093154f4ab89165ec7549 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2008-10-29 Enrico Tröger <enrico(dot)troeger(at)uvena(dot)de> + + * Always clear the spell check dictionary list in the prefs dialog, + even if an empty or invalid spell check command was given. + * Add a combo box around the search field in the main window + to provide a history of previously searched words. + + 2008-10-28 Enrico Tröger <enrico(dot)troeger(at)uvena(dot)de> * Guess the default spell check dictionary based on the user's diff --git a/lib/Makefile.am b/lib/Makefile.am index a60adc187964b64e437922ef910338aaf91bb7e2..70c5f977661c5ea4604553d999f278770fd2b201 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -15,6 +15,8 @@ libdict_la_SOURCES = \ prefs.h \ sexy-icon-entry.c \ sexy-icon-entry.h \ + searchentry.c \ + searchentry.h \ spell.c \ spell.h \ wraplabel.c \ diff --git a/lib/common.c b/lib/common.c index 988a7bfe59953556f2a098e227062bc78e2cc14d..ad88ca643ecb3357a99fda00027df21d6ac8b6ae 100644 --- a/lib/common.c +++ b/lib/common.c @@ -41,6 +41,7 @@ #include "spell.h" #include "dictd.h" #include "gui.h" +#include "searchentry.h" @@ -222,6 +223,7 @@ void dict_search_word(DictData *dd, const gchar *word) } /* remove leading and trailing spaces */ g_strstrip(dd->searched_word); + xfd_search_entry_prepend_text(XFD_SEARCH_ENTRY(dd->main_combo), dd->searched_word); dict_gui_clear_text_buffer(dd); diff --git a/lib/common.h b/lib/common.h index edb8f83efee1e561f9e906c50fd0af4c5be32523..ca51bb051c67f20b8b912b36656d18be349e5ee9 100644 --- a/lib/common.h +++ b/lib/common.h @@ -91,6 +91,7 @@ typedef struct GtkWidget *close_button; GtkWidget *close_menu_item; GtkWidget *pref_menu_item; + GtkWidget *main_combo; GtkWidget *main_entry; GtkWidget *panel_entry; GtkWidget *main_textview; diff --git a/lib/gui.c b/lib/gui.c index 40dc434907aefa5654015f6392464fbec93310a8..2dbf58970c655e5e3ec9d0d3fa1678397a030c01 100644 --- a/lib/gui.c +++ b/lib/gui.c @@ -33,6 +33,7 @@ #include "common.h" #include "gui.h" #include "sexy-icon-entry.h" +#include "searchentry.h" #include "inline-icon.h" @@ -268,6 +269,16 @@ static void entry_icon_pressed_cb(SexyIconEntry *entry, gint icon_pos, gint butt } +static void combo_changed_cb(GtkComboBox *combo, DictData *dd) +{ + gchar *text = gtk_combo_box_get_active_text(combo); + + dict_search_word(dd, text); + + g_free(text); +} + + static void entry_changed_cb(GtkEditable *editable, DictData *dd) { entry_is_dirty = TRUE; @@ -477,14 +488,16 @@ void dict_gui_create_main_window(DictData *dd) gtk_widget_show(label_box); gtk_box_pack_start(GTK_BOX(entry_box), label_box, TRUE, TRUE, 0); - dd->main_entry = sexy_icon_entry_new_full("gtk-find", "gtk-clear"); - gtk_entry_set_text(GTK_ENTRY(dd->main_entry), _("Search term")); - gtk_widget_show(dd->main_entry); - gtk_box_pack_start(GTK_BOX(label_box), dd->main_entry, TRUE, TRUE, 0); - g_signal_connect(dd->main_entry, "button-press-event", G_CALLBACK(entry_button_press_cb), dd); - g_signal_connect(dd->main_entry, "activate", G_CALLBACK(entry_activate_cb), dd); + dd->main_combo = xfd_search_entry_new(_("Search term")); + gtk_widget_show(dd->main_combo); + gtk_box_pack_start(GTK_BOX(label_box), dd->main_combo, TRUE, TRUE, 0); + g_signal_connect(dd->main_combo, "active-changed", G_CALLBACK(combo_changed_cb), dd); + + dd->main_entry = gtk_bin_get_child(GTK_BIN(dd->main_combo)); g_signal_connect(dd->main_entry, "changed", G_CALLBACK(entry_changed_cb), dd); + g_signal_connect(dd->main_entry, "activate", G_CALLBACK(entry_activate_cb), dd); g_signal_connect(dd->main_entry, "icon_released", G_CALLBACK(entry_icon_pressed_cb), dd); + g_signal_connect(dd->main_entry, "button-press-event", G_CALLBACK(entry_button_press_cb), dd); update_search_button(dd, entry_box); diff --git a/lib/searchentry.c b/lib/searchentry.c new file mode 100644 index 0000000000000000000000000000000000000000..12786b7961c488d8c98e31466aef2a234f5d6e30 --- /dev/null +++ b/lib/searchentry.c @@ -0,0 +1,174 @@ +/* $Id$ + * + * Copyright 2008 Enrico Tröger <enrico(dot)troeger(at)uvena(dot)de> + * + * 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 Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + + +/* Subclass of a GtkComboBoxEntry which embeds a SexyIconEntry instead of + * a plain GtkEntry. */ + + +#include <gtk/gtk.h> +#include <string.h> +#include "searchentry.h" +#include "sexy-icon-entry.h" + + +static void xfd_search_entry_class_init (XfdSearchEntryClass *klass); +static void xfd_search_entry_init (XfdSearchEntry *self); + + +enum +{ + ACTIVE_CHANGED, + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL]; + + +GType xfd_search_entry_get_type(void) +{ + static GType self_type = 0; + if (! self_type) + { + static const GTypeInfo self_info = + { + sizeof(XfdSearchEntryClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc)xfd_search_entry_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof(XfdSearchEntry), + 0, + (GInstanceInitFunc)xfd_search_entry_init, + NULL /* value_table */ + }; + + self_type = g_type_register_static(GTK_TYPE_COMBO_BOX_ENTRY, "XfdSearchEntry", &self_info, 0); + } + + return self_type; +} + + +static void xfd_search_entry_class_init(XfdSearchEntryClass *klass) +{ + signals[ACTIVE_CHANGED] = g_signal_new("active-changed", + G_TYPE_FROM_CLASS (klass), + (GSignalFlags) (G_SIGNAL_RUN_LAST), + 0, + 0, + NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); +} + + +static void combo_changed_cb(GtkComboBox *combo_box, gpointer data) +{ + GtkTreeIter iter; + + if (gtk_combo_box_get_active_iter(combo_box, &iter)) + { + g_signal_emit(XFD_SEARCH_ENTRY(combo_box), signals[ACTIVE_CHANGED], 0); + } +} + + +static void xfd_search_entry_init(XfdSearchEntry *self) +{ + GtkWidget *entry; + GtkCellRenderer *text_renderer; + + /* we want the widget to have appears-as-list applied + * (code and idea stolen from Midori, thanks Christian) */ + gtk_rc_parse_string("style \"xfd-search-entry-style\" {\n" + " GtkComboBox::appears-as-list = 1\n }\n" + "widget_class \"*XfdSearchEntry\" " + "style \"xfd-search-entry-style\"\n"); + + entry = sexy_icon_entry_new_full("gtk-find", "gtk-clear"); + + gtk_widget_show(entry); + gtk_container_add(GTK_CONTAINER(self), entry); + + text_renderer = gtk_cell_renderer_text_new(); + gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(self), text_renderer, TRUE); + + gtk_combo_box_set_active(GTK_COMBO_BOX(self), -1); + + g_signal_connect(self, "changed", G_CALLBACK(combo_changed_cb), NULL); +} + + +GtkWidget *xfd_search_entry_new(const gchar *text) +{ + GtkWidget *widget; + GtkListStore *store; + + store = gtk_list_store_new(1, G_TYPE_STRING); + + widget = g_object_new(XFD_SEARCH_ENTRY_TYPE, "model", store, "text-column", 0, NULL); + + gtk_entry_set_text(GTK_ENTRY(gtk_bin_get_child(GTK_BIN(widget))), text); + + g_object_unref(store); + + return widget; +} + + +void xfd_search_entry_prepend_text(XfdSearchEntry *search_entry, const gchar *text) +{ + GtkTreeIter iter; + GtkListStore *store; + GtkTreeModel *model; + gint i, len; + gchar *str; + + g_return_if_fail(GTK_IS_COMBO_BOX(search_entry)); + g_return_if_fail(text != NULL); + + model = gtk_combo_box_get_model(GTK_COMBO_BOX(search_entry)); + store = GTK_LIST_STORE(model); + + /* check whether 'text' is already in the model */ + len = gtk_tree_model_iter_n_children(model, NULL); + for (i = 0; i < len; i++) + { + if (gtk_tree_model_iter_nth_child(model, &iter, NULL, i)) + { + gtk_tree_model_get(model, &iter, 0, &str, -1); + if (str != NULL && strcmp(str, text) == 0) + { + /* if we found 'text' in the model, move it to the top of the list and return */ + gtk_list_store_move_after(store, &iter, NULL); + + g_free(str); + return; + } + g_free(str); + } + } + + /* add 'text' to the model/store */ + gtk_list_store_prepend(store, &iter); + gtk_list_store_set(store, &iter, 0, text, -1); +} + diff --git a/lib/searchentry.h b/lib/searchentry.h new file mode 100644 index 0000000000000000000000000000000000000000..ef7392341d22bb05cf55fd27d49765beb108a163 --- /dev/null +++ b/lib/searchentry.h @@ -0,0 +1,56 @@ +/* $Id$ + * + * Copyright 2006-2008 Enrico Tröger <enrico(dot)troeger(at)uvena(dot)de> + * + * 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 Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + + + +#ifndef __SEARCHENTRY_H__ +#define __SEARCHENTRY_H__ + +G_BEGIN_DECLS + +#define XFD_SEARCH_ENTRY_TYPE (xfd_search_entry_get_type()) +#define XFD_SEARCH_ENTRY(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),\ + XFD_SEARCH_ENTRY_TYPE, XfdSearchEntry)) +#define XFD_SEARCH_ENTRY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),\ + XFD_SEARCH_ENTRY_TYPE, XfdSearchEntryClass)) +#define IS_XFD_SEARCH_ENTRY(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),\ + XFD_SEARCH_ENTRY_TYPE)) +#define IS_XFD_SEARCH_ENTRY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),\ + XFD_SEARCH_ENTRY_TYPE)) + +typedef struct _XfdSearchEntry XfdSearchEntry; +typedef struct _XfdSearchEntryClass XfdSearchEntryClass; + +struct _XfdSearchEntry +{ + GtkComboBoxEntry parent; +}; + +struct _XfdSearchEntryClass +{ + GtkComboBoxEntryClass parent_class; +}; + +GType xfd_search_entry_get_type (void); +GtkWidget* xfd_search_entry_new (const gchar *text); +void xfd_search_entry_prepend_text (XfdSearchEntry *search_entry, const gchar *text); + +G_END_DECLS + +#endif /* __SEARCHENTRY_H__ */