r20272 - gnucash/trunk/src/business/business-gnome - Implement auto-completion on the addr2/addr3 lines of the "New Customer" dialog box.
Christian Stimming
cstim at code.gnucash.org
Thu Feb 10 16:49:30 EST 2011
Author: cstim
Date: 2011-02-10 16:49:29 -0500 (Thu, 10 Feb 2011)
New Revision: 20272
Trac: http://svn.gnucash.org/trac/changeset/20272
Modified:
gnucash/trunk/src/business/business-gnome/dialog-customer.c
gnucash/trunk/src/business/business-gnome/glade/customer.glade
Log:
Implement auto-completion on the addr2/addr3 lines of the "New Customer" dialog box.
Modified: gnucash/trunk/src/business/business-gnome/dialog-customer.c
===================================================================
--- gnucash/trunk/src/business/business-gnome/dialog-customer.c 2011-02-10 21:49:12 UTC (rev 20271)
+++ gnucash/trunk/src/business/business-gnome/dialog-customer.c 2011-02-10 21:49:29 UTC (rev 20272)
@@ -25,6 +25,7 @@
#include <gtk/gtk.h>
#include <glib/gi18n.h>
+#include <gdk/gdkkeysyms.h>
#include "dialog-utils.h"
#include "gnc-amount-edit.h"
@@ -37,6 +38,8 @@
#include "dialog-search.h"
#include "search-param.h"
+#include "app-utils/QuickFill.h"
+#include "app-utils/gnc-addr-quickfill.h"
#include "gncAddress.h"
#include "gncCustomer.h"
@@ -62,7 +65,21 @@
void gnc_customer_window_help_cb (GtkWidget *widget, gpointer data);
void gnc_customer_window_destroy_cb (GtkWidget *widget, gpointer data);
void gnc_customer_name_changed_cb (GtkWidget *widget, gpointer data);
+void gnc_customer_addr2_insert_cb(GtkEditable *editable,
+ gchar *new_text, gint new_text_length,
+ gint *position, gpointer user_data);
+void gnc_customer_addr3_insert_cb(GtkEditable *editable,
+ gchar *new_text, gint new_text_length,
+ gint *position, gpointer user_data);
+gboolean
+gnc_customer_addr2_key_press_cb( GtkEntry *entry, GdkEventKey *event,
+ gpointer user_data );
+gboolean
+gnc_customer_addr3_key_press_cb( GtkEntry *entry, GdkEventKey *event,
+ gpointer user_data );
+#define ADDR_QUICKFILL "GncAddress-Quickfill"
+
typedef enum
{
NEW_CUSTOMER,
@@ -121,6 +138,17 @@
GncCustomer * created_customer;
GncTaxTable * taxtable;
+
+ /* stored data for the description quickfill selection function */
+ QuickFill *addr2_quickfill;
+ gint addr2_start_selection;
+ gint addr2_end_selection;
+ guint addr2_selection_source_id;
+
+ QuickFill *addr3_quickfill;
+ gint addr3_start_selection;
+ gint addr3_end_selection;
+ guint addr3_selection_source_id;
};
void
@@ -353,6 +381,11 @@
cw->customer_guid = *guid_null ();
}
+ if (cw->addr2_selection_source_id)
+ g_source_remove (cw->addr2_selection_source_id);
+ if (cw->addr3_selection_source_id)
+ g_source_remove (cw->addr3_selection_source_id);
+
gnc_unregister_gui_component (cw->component_id);
gnc_resume_gui_refresh ();
@@ -629,6 +662,10 @@
gncCustomerGetTaxTableOverride (cust));
gnc_customer_taxtable_check_cb (GTK_TOGGLE_BUTTON (cw->taxtable_check), cw);
+ /* Set up the addr line quickfill */
+ cw->addr2_quickfill = gnc_get_shared_address_addr2_quickfill(cw->book, ADDR_QUICKFILL);
+ cw->addr3_quickfill = gnc_get_shared_address_addr3_quickfill(cw->book, ADDR_QUICKFILL);
+
/* Set the Discount, and Credit amounts */
gnc_amount_edit_set_amount (GNC_AMOUNT_EDIT (cw->discount_amount),
gncCustomerGetDiscount (cust));
@@ -872,3 +909,202 @@
return NULL;
}
+
+static gboolean
+idle_select_region_addr2(gpointer user_data)
+{
+ CustomerWindow *wdata = user_data;
+ g_return_val_if_fail(user_data, FALSE);
+
+ gtk_editable_select_region(GTK_EDITABLE(wdata->addr2_entry),
+ wdata->addr2_start_selection,
+ wdata->addr2_end_selection);
+
+ wdata->addr2_selection_source_id = 0;
+ return FALSE;
+}
+
+static gboolean
+idle_select_region_addr3(gpointer user_data)
+{
+ CustomerWindow *wdata = user_data;
+ g_return_val_if_fail(user_data, FALSE);
+
+ gtk_editable_select_region(GTK_EDITABLE(wdata->addr3_entry),
+ wdata->addr3_start_selection,
+ wdata->addr3_end_selection);
+
+ wdata->addr3_selection_source_id = 0;
+ return FALSE;
+}
+
+/* Implementation of the steps common to all address lines. Returns
+ * TRUE if anything was inserted by quickfill, otherwise FALSE. */
+static gboolean
+gnc_customer_addr_common_insert_cb(GtkEditable *editable,
+ gchar *new_text, gint new_text_length,
+ gint *position, gpointer user_data, QuickFill *qf)
+{
+ CustomerWindow *wdata = user_data;
+ gchar *concatenated_text;
+ QuickFill *match;
+ const gchar *match_str;
+ gint prefix_len, concatenated_text_len;
+
+ if (new_text_length <= 0)
+ return FALSE;
+
+ /*g_warning("In gnc_customer_addr_common_insert_cb");*/
+
+ {
+ gchar *suffix = gtk_editable_get_chars(editable, *position, -1);
+ /* If we are inserting in the middle, do nothing */
+ if (*suffix)
+ {
+ g_free(suffix);
+ return FALSE;
+ }
+ g_free(suffix);
+ }
+
+ {
+ gchar *prefix = gtk_editable_get_chars(editable, 0, *position);
+ prefix_len = strlen(prefix);
+ concatenated_text = g_strconcat(prefix, new_text, (gchar*) NULL);
+ concatenated_text_len = prefix_len + new_text_length;
+ g_free(prefix);
+ }
+
+ match = gnc_quickfill_get_string_match(qf, concatenated_text);
+ g_free(concatenated_text);
+ if (match)
+ {
+ const char* match_str = gnc_quickfill_string(match);
+ if (match_str)
+ {
+ gint match_str_len = strlen(match_str);
+ if (match_str_len > concatenated_text_len)
+ {
+ g_signal_handlers_block_matched (G_OBJECT (editable),
+ G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, user_data);
+
+ gtk_editable_insert_text(editable,
+ match_str + prefix_len,
+ match_str_len - prefix_len,
+ position);
+
+ g_signal_handlers_unblock_matched (G_OBJECT (editable),
+ G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, user_data);
+
+ /* stop the current insert */
+ g_signal_stop_emission_by_name (G_OBJECT (editable), "insert_text");
+
+ /* set the position */
+ *position = g_utf8_strlen(concatenated_text, -1);
+
+ return TRUE;
+ }
+ }
+ }
+ return FALSE;
+}
+
+void gnc_customer_addr2_insert_cb(GtkEditable *editable,
+ gchar *new_text, gint new_text_length,
+ gint *position, gpointer user_data)
+{
+ CustomerWindow *wdata = user_data;
+ gboolean r;
+
+ /*g_warning("In gnc_customer_addr2_insert_cb");*/
+
+ /* The handling common to all address lines is done in this other
+ * function. */
+ r = gnc_customer_addr_common_insert_cb(editable, new_text, new_text_length,
+ position, user_data, wdata->addr2_quickfill);
+
+ /* Did we insert something? Then set up the correct idle handler */
+ if (r)
+ {
+ /* select region on idle, because it would be reset once this function
+ finishes */
+ wdata->addr2_start_selection = *position;
+ wdata->addr2_end_selection = -1;
+ wdata->addr2_selection_source_id = g_idle_add(idle_select_region_addr2,
+ user_data);
+ }
+}
+
+void gnc_customer_addr3_insert_cb(GtkEditable *editable,
+ gchar *new_text, gint new_text_length,
+ gint *position, gpointer user_data)
+{
+ CustomerWindow *wdata = user_data;
+ gboolean r;
+
+ /*g_warning("In gnc_customer_addr3_insert_cb");*/
+
+ /* The handling common to all address lines is done in this other
+ * function. */
+ r = gnc_customer_addr_common_insert_cb(editable, new_text, new_text_length,
+ position, user_data, wdata->addr3_quickfill);
+
+ /* Did we insert something? Then set up the correct idle handler */
+ if (r)
+ {
+ /* select region on idle, because it would be reset once this function
+ finishes */
+ wdata->addr3_start_selection = *position;
+ wdata->addr3_end_selection = -1;
+ wdata->addr3_selection_source_id = g_idle_add(idle_select_region_addr3,
+ user_data);
+ }
+}
+
+static gboolean
+gnc_customer_common_key_press_cb( GtkEntry *entry,
+ GdkEventKey *event,
+ gpointer user_data, GtkWidget* editable )
+{
+ gboolean done_with_input = FALSE;
+
+ /* Most "special" keys are allowed to be handled directly by
+ * the entry's key press handler, but in some cases that doesn't
+ * seem to work right, so handle them here.
+ */
+ switch ( event->keyval )
+ {
+ case GDK_Tab:
+ case GDK_ISO_Left_Tab:
+ if ( !( event->state & GDK_SHIFT_MASK) ) /* Complete on Tab,
+ * but not Shift-Tab */
+ {
+ /* NOT done with input, though, since we need to focus to the next
+ * field. Unselect the current field, though.
+ */
+ gtk_editable_select_region( GTK_EDITABLE(editable),
+ 0, 0 );
+ }
+ break;
+ }
+
+ return( done_with_input );
+}
+gboolean
+gnc_customer_addr2_key_press_cb( GtkEntry *entry,
+ GdkEventKey *event,
+ gpointer user_data )
+{
+ CustomerWindow *wdata = user_data;
+ return gnc_customer_common_key_press_cb(entry, event, user_data,
+ wdata->addr2_entry);
+}
+gboolean
+gnc_customer_addr3_key_press_cb( GtkEntry *entry,
+ GdkEventKey *event,
+ gpointer user_data )
+{
+ CustomerWindow *wdata = user_data;
+ return gnc_customer_common_key_press_cb(entry, event, user_data,
+ wdata->addr3_entry);
+}
Modified: gnucash/trunk/src/business/business-gnome/glade/customer.glade
===================================================================
--- gnucash/trunk/src/business/business-gnome/glade/customer.glade 2011-02-10 21:49:12 UTC (rev 20271)
+++ gnucash/trunk/src/business/business-gnome/glade/customer.glade 2011-02-10 21:49:29 UTC (rev 20272)
@@ -303,6 +303,8 @@
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="activates_default">True</property>
+ <signal name="insert_text" handler="gnc_customer_addr2_insert_cb"/>
+ <signal name="key_press_event" handler="gnc_customer_addr2_key_press_cb"/>
</widget>
<packing>
<property name="expand">False</property>
@@ -315,6 +317,8 @@
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="activates_default">True</property>
+ <signal name="insert_text" handler="gnc_customer_addr3_insert_cb"/>
+ <signal name="key_press_event" handler="gnc_customer_addr3_key_press_cb"/>
</widget>
<packing>
<property name="expand">False</property>
More information about the gnucash-changes
mailing list