It might be worth putting your list in a database and have the database do the filtering. Then update a liststore with a short list that the completion can use. That way you don’t have to load a lot of data at startup and the database should be pretty fast filtering.
This is a little sqlite program to try out with the idea.
Eric
//gcc -Wall completion1.c -o completion1 `pkg-config --cflags --libs gtk+-3.0` -lsqlite3
//Ubuntu18.04 with GTK3.22
#include<gtk/gtk.h>
#include<sqlite3.h>
static sqlite3 *db=NULL;
static void get_sql_list(GtkEditable *entry, gpointer user_data);
static void initialize_database();
static void close_program(GtkWidget *widget, gpointer data);
int main(int argc, char *argv[])
{
gtk_init(&argc, &argv);
GtkWidget *window=gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_title(GTK_WINDOW(window), "Entry Completion");
gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
gtk_container_set_border_width(GTK_CONTAINER(window), 10);
gtk_window_set_default_size(GTK_WINDOW(window), 300, 100);
g_signal_connect(window, "destroy", G_CALLBACK(close_program), NULL);
initialize_database();
GtkEntryCompletion *completion=gtk_entry_completion_new();
GtkWidget *entry=gtk_entry_new();
gtk_widget_set_hexpand(entry, TRUE);
gtk_entry_set_completion(GTK_ENTRY(entry), completion);
g_signal_connect(entry, "changed", G_CALLBACK(get_sql_list), completion);
GtkWidget *grid=gtk_grid_new();
gtk_grid_attach(GTK_GRID(grid), entry, 0, 0, 1, 1);
gtk_container_add(GTK_CONTAINER(window), grid);
gtk_widget_show_all(window);
gtk_main();
return 0;
}
static void get_sql_list(GtkEditable *entry, gpointer user_data)
{
GtkTreeIter iter;
gint ret_val=0;
sqlite3_stmt *stmt1=NULL;
GtkListStore *new_store=NULL;
//Build a SQL string.
gchar *sql_string=g_strdup_printf("SELECT CritterName FROM Critters WHERE CritterName LIKE'%s%%' LIMIT 5;", gtk_entry_get_text(GTK_ENTRY(entry)));
//g_print("%s\n", sql_string);
//Prepare the SQL statement.
sqlite3_prepare_v2(db, sql_string, -1, &stmt1, 0);
new_store=gtk_list_store_new(1, G_TYPE_STRING);
g_free(sql_string);
//Load the list store.
if(stmt1!=NULL)
{
ret_val=sqlite3_step(stmt1);
while(ret_val==SQLITE_ROW)
{
gtk_list_store_append(new_store, &iter);
//g_print("Append %s\n", sqlite3_column_text(stmt1, 0));
gtk_list_store_set(new_store, &iter, 0, sqlite3_column_text(stmt1, 0), -1);
ret_val=sqlite3_step(stmt1);
}
}
if(stmt1!=NULL) sqlite3_finalize(stmt1);
//Set up the completion.
gtk_entry_completion_set_model(GTK_ENTRY_COMPLETION(user_data), GTK_TREE_MODEL(new_store));
g_object_unref(new_store);
gtk_entry_set_completion(GTK_ENTRY(entry), GTK_ENTRY_COMPLETION(user_data));
gtk_entry_completion_set_text_column(GTK_ENTRY_COMPLETION(user_data), 0);
gtk_entry_completion_complete(GTK_ENTRY_COMPLETION(user_data));
}
static void initialize_database()
{
gchar *err_msg=NULL;
gint rc=sqlite3_open(":memory:", &db);
if(rc!=SQLITE_OK)
{
g_print("Cannot open database: %s\n", sqlite3_errmsg(db));
sqlite3_close(db);
}
//Add some test data.
gchar *sql="CREATE TABLE Critters(CritterId INTEGER PRIMARY KEY, CritterName TEXT);"
"INSERT INTO Critters VALUES(1, 'Parrot');"
"INSERT INTO Critters VALUES(2, 'Chimpanzee');"
"INSERT INTO Critters VALUES(3, 'Crow');"
"INSERT INTO Critters VALUES(4, 'Dolphin');"
"INSERT INTO Critters VALUES(5, 'Alligator');"
"INSERT INTO Critters VALUES(6, 'Whale');"
"INSERT INTO Critters VALUES(7, 'Zebra');"
"INSERT INTO Critters VALUES(8, 'Owl');"
"INSERT INTO Critters VALUES(9, 'Leopard');"
"INSERT INTO Critters VALUES(10, 'Koala');"
"INSERT INTO Critters VALUES(11, 'Eagle');"
"INSERT INTO Critters VALUES(12, 'Frog');"
"INSERT INTO Critters VALUES(13, 'Moose');"
"INSERT INTO Critters VALUES(14, 'Kangaroo');"
"INSERT INTO Critters VALUES(15, 'Tortoise');"
"INSERT INTO Critters VALUES(16, 'Bear');"
"INSERT INTO Critters VALUES(17, 'Shark');"
"INSERT INTO Critters VALUES(18, 'Panda');"
"INSERT INTO Critters VALUES(19, 'Penguin');"
"INSERT INTO Critters VALUES(20, 'Walrus');"
"INSERT INTO Critters VALUES(21, 'Wolf');"
"INSERT INTO Critters VALUES(22, 'Woodpecker');"
"INSERT INTO Critters VALUES(23, 'Piranha');"
"INSERT INTO Critters VALUES(24, 'Wolvirine');"
"INSERT INTO Critters VALUES(25, 'Elephant');";
rc=sqlite3_exec(db, sql, 0, 0, &err_msg);
if (rc!=SQLITE_OK)
{
g_print("Failed to create table\n");
g_print("SQL error: %s\n", err_msg);
sqlite3_free(err_msg);
}
}
static void close_program(GtkWidget *widget, gpointer data)
{
sqlite3_close(db);
gtk_main_quit();
}