(gtk1.2) Making autocomplete with a GTK_COMBO(widget)->entry



Hello all,

Disclaimer: I'm a newbie. Mock me if you feel that you must.

I am making a simple application that keeps data about a soccer league.
It's actually coming along pretty well, and I am keeping it at gtk 1.2
until the basic GUI framework is complete so I can get the full benefit
of porting it to gtk 2.0, all in one go. :)

The topic today is a small dialog where we want the user to add a match
to a list. There are of course two teams in a soccer match, so there are
two GtkCombo boxes, with all the team names listed as their possible
choices, and I also used a gtk_combo_set_value_in_list() to ensure the
user doesn't try to enter anything that isn't "allowed" (i.e. only teams
that exist in a league can play matches there). Now, since I use this
program to keep statistical information about quite some soccer leagues,
I like to be able to choose my matches quickly and painlessly. Wouldn't
it be nice if the "Add match" window just opened up, with the focus on
the first widget, so that I could type the first few letters of the home
team name, then press tab once to get to the away team, type a few
letters, then enter, and all done! Yeah, I like it! So I tried. Grabbing
the focus when the window is opened is not a problem. The autocomplete
is a bit of a problem.

Here is the function I connect to the GtkEditable "changed" signal for
the entry widget of both the GtkCombos:

-----

gint me_addmatch_autocomplete_cb( GtkWidget *widget, gpointer userdata )
{
        GList *li;
        struct team *curteam = NULL;
        gchar *partialname;
        gboolean found = FALSE;
        gint curpos;
        
        if( !widget )
                return( FALSE );

        if( SwallowNextChangedSignal )
        {
                SwallowNextChangedSignal = FALSE;
                return( FALSE );
        }               
        partialname = gtk_editable_get_chars( GTK_EDITABLE(widget), 0, -1 );
        curpos = strlen( partialname );
        if( !curpos )
        {
                g_free( partialname );
                return( FALSE );
        }
        li = OpenLeague->teamlist;
        while( li && !found )
        {
                curteam = (struct team *) li->data;
                if( strncasecmp( curteam->name, partialname, curpos ) == 0 )
                        found = TRUE;
                else
                        li = li->next;
        }
        if( found )
        {
                if( strcmp( partialname, curteam->name ) )
                {
                        SwallowNextChangedSignal = TRUE;
                        gtk_entry_set_text( GTK_ENTRY(widget), curteam->name );
                        gtk_editable_select_region( GTK_EDITABLE(widget), curpos, -1 );
                }
        }
        g_free( partialname );
        return( TRUE );
}

-----

Things to know before you laugh and beat me with properly sized sticks:

1. SwallowNextChangedSignal is a silly invention to get rid of an
endless loop; Of course, when I autocomplete with the first team I find
that starts with the letters the user has typed in, another changed
signal will fire off, etc. Is this the right way to avoid the problem?

2. Notice that I use gtk_editable_select_region() to try to set the
autocompleted part of the word (i.e. everything that the user didn't
type) as selected - this does nothing. In another callback (the one that
is called when these widgets grab focus), I use the same function to set
the region (0, -1) as selected. This works.

3. There are probably many logical flaws in my implementation. I will
find out and move on. However, if you spot anything obvious, feel free
to comment.

4. OpenLeague is a global pointer to a league structure. struct team is
a team definition structure that among other things contains a team
name.

I hope someone can shed some light on any of my questions. 

Thank you very much for the patience.

Best regards,

Rune Jacobsen





[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]