GnuCash 2.4.99
gnc-gtk-utils.c
00001 /********************************************************************\
00002  * gnc-gtk-utils.c -- utility functions based on glib functions     *
00003  * Copyright (C) 2006 David Hampton <hampton@employees.org>         *
00004  *                                                                  *
00005  * This program is free software; you can redistribute it and/or    *
00006  * modify it under the terms of the GNU General Public License as   *
00007  * published by the Free Software Foundation; either version 2 of   *
00008  * the License, or (at your option) any later version.              *
00009  *                                                                  *
00010  * This program is distributed in the hope that it will be useful,  *
00011  * but WITHOUT ANY WARRANTY; without even the implied warranty of   *
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    *
00013  * GNU General Public License for more details.                     *
00014  *                                                                  *
00015  * You should have received a copy of the GNU General Public License*
00016  * along with this program; if not, contact:                        *
00017  *                                                                  *
00018  * Free Software Foundation           Voice:  +1-617-542-5942       *
00019  * 51 Franklin Street, Fifth Floor    Fax:    +1-617-542-2652       *
00020  * Boston, MA  02110-1301,  USA       gnu@gnu.org                   *
00021  *                                                                  *
00022 \********************************************************************/
00023 
00024 #include "config.h"
00025 
00026 #include "gnc-gtk-utils.h"
00027 
00028 #define LAST_INDEX "last_index"
00029 #define CHANGED_ID "changed_id"
00030 
00031 
00040 void
00041 gnc_cbe_set_by_string(GtkComboBoxEntry *cbe,
00042                       const gchar *text)
00043 {
00044     GtkTreeModel *model;
00045     GtkTreeIter iter;
00046     gchar *tree_string;
00047     gint column, index, id;
00048     gboolean match;
00049 
00050     model = gtk_combo_box_get_model(GTK_COMBO_BOX(cbe));
00051     if (!gtk_tree_model_get_iter_first(model, &iter))
00052     {
00053         /* empty tree */
00054         gtk_combo_box_set_active(GTK_COMBO_BOX(cbe), -1);
00055         return;
00056     }
00057 
00058     column = gtk_combo_box_entry_get_text_column(cbe);
00059     do
00060     {
00061         gtk_tree_model_get(model, &iter, column, &tree_string, -1);
00062         match = g_utf8_collate(text, tree_string) == 0;
00063         g_free(tree_string);
00064         if (!match)
00065             continue;
00066 
00067         /* Found a matching string */
00068         id = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(cbe), CHANGED_ID));
00069         g_signal_handler_block(cbe, id);
00070         gtk_combo_box_set_active_iter(GTK_COMBO_BOX(cbe), &iter);
00071         g_signal_handler_unblock(cbe, id);
00072 
00073         index = gtk_combo_box_get_active(GTK_COMBO_BOX(cbe));
00074         g_object_set_data(G_OBJECT(cbe), LAST_INDEX, GINT_TO_POINTER(index));
00075         return;
00076     }
00077     while (gtk_tree_model_iter_next(model, &iter));
00078 }
00079 
00080 
00088 static void
00089 gnc_cbe_changed_cb (GtkComboBox *widget,
00090                     GtkComboBoxEntry *cbe)
00091 {
00092     gint index;
00093 
00094     index = gtk_combo_box_get_active(widget);
00095     if (index == -1)
00096         return;
00097     g_object_set_data(G_OBJECT(cbe), LAST_INDEX, GINT_TO_POINTER(index));
00098 }
00099 
00100 
00117 static gboolean
00118 gnc_cbe_match_selected_cb (GtkEntryCompletion *completion,
00119                            GtkTreeModel       *comp_model,
00120                            GtkTreeIter        *comp_iter,
00121                            GtkComboBoxEntry   *cbe)
00122 {
00123     gint column;
00124     gchar *text;
00125 
00126     column = gtk_combo_box_entry_get_text_column(cbe);
00127     gtk_tree_model_get(comp_model, comp_iter, column, &text, -1);
00128     gnc_cbe_set_by_string(cbe, text);
00129     g_free(text);
00130     return FALSE;
00131 }
00132 
00133 
00146 static gboolean
00147 gnc_cbe_focus_out_cb (GtkEntry *entry,
00148                       GdkEventFocus *event,
00149                       GtkComboBoxEntry *cbe)
00150 {
00151     const gchar *text;
00152     gint index;
00153 
00154     /* Make a final attempt to match the current text. */
00155     text = gtk_entry_get_text(entry);
00156     gnc_cbe_set_by_string(cbe, text);
00157 
00158     /* Get the last known index (which may have just been set). */
00159     index = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(cbe), LAST_INDEX));
00160     gtk_combo_box_set_active(GTK_COMBO_BOX(cbe), index);
00161     return FALSE;
00162 }
00163 
00164 void
00165 gnc_cbe_add_completion (GtkComboBoxEntry *cbe)
00166 {
00167     GtkEntry *entry;
00168     GtkEntryCompletion *completion;
00169     GtkTreeModel *model;
00170 
00171     entry = GTK_ENTRY(gtk_bin_get_child(GTK_BIN(cbe)));
00172     completion = gtk_entry_get_completion(entry);
00173     if (completion)
00174         return;
00175 
00176     /* No completion yet? Set one up. */
00177     completion = gtk_entry_completion_new();
00178     model = gtk_combo_box_get_model(GTK_COMBO_BOX(cbe));
00179     gtk_entry_completion_set_model(completion, model);
00180     gtk_entry_completion_set_text_column(completion, 0);
00181     gtk_entry_completion_set_inline_completion(completion, TRUE);
00182     gtk_entry_set_completion(entry, completion);
00183     g_object_unref(completion);
00184 }
00185 
00186 void
00187 gnc_cbe_require_list_item (GtkComboBoxEntry *cbe)
00188 {
00189     GtkEntry *entry;
00190     GtkEntryCompletion *completion;
00191     GtkTreeModel *model;
00192     GtkTreeIter iter;
00193     gint index, id;
00194 
00195     /* Ensure completion is set up. */
00196     gnc_cbe_add_completion(cbe);
00197 
00198     /* If an item in the combo box isn't already selected, then force
00199      * select the first item. Take care, the combo box may not have been
00200      * filled yet.  */
00201     entry = GTK_ENTRY(gtk_bin_get_child(GTK_BIN(cbe)));
00202     completion = gtk_entry_get_completion(entry);
00203     index = gtk_combo_box_get_active(GTK_COMBO_BOX(cbe));
00204     if (index == -1)
00205     {
00206         model = gtk_entry_completion_get_model(completion);
00207         if (gtk_tree_model_get_iter_first(model, &iter))
00208         {
00209             gtk_combo_box_set_active(GTK_COMBO_BOX(cbe), 0);
00210             index = 0;
00211         }
00212     }
00213     g_object_set_data(G_OBJECT(cbe), LAST_INDEX, GINT_TO_POINTER(index));
00214 
00215     /* Now the signals to make sure the user can't leave the
00216        widget without a valid match. */
00217     id = g_signal_connect(cbe, "changed",
00218                           G_CALLBACK(gnc_cbe_changed_cb), cbe);
00219     g_signal_connect(completion, "match_selected",
00220                      G_CALLBACK(gnc_cbe_match_selected_cb), cbe);
00221     g_signal_connect(entry, "focus-out-event",
00222                      G_CALLBACK(gnc_cbe_focus_out_cb), cbe);
00223 
00224     g_object_set_data(G_OBJECT(cbe), CHANGED_ID, GINT_TO_POINTER(id));
00225 }
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines