Gtk entry completion

 ( malcolm | 2006. február 26., vasárnap - 13:17 )

Sziasztok!

Gtk/Gnome alá fejlesztek egy progit. Nemrég beépítettem a beviteli mezőkbe a completion funkciót.
Ki is próbáltam, tökéletesen működött. Aztán egyszercsak, amikor be akartam írni a beviteli mezőbe valamit, a következő hibaüzenetet kaptam:

GLib-CRITICAL **: g_utf8_casefold: assertion `str != NULL' failed

Mivel én ezt a függvényt nem használom, gondoltam újratelepítem a glib-et (jelenleg Gentoo-t használok).
Semmi sem változott. Sőt, a poén az, hogy egy debianos gépen tökéletesen működik.

Segítsetek légyszives! Merre induljak el?

Köszi. Üdv

Hozzászólás megjelenítési lehetőségek

A választott hozzászólás megjelenítési mód a „Beállítás” gombbal rögzíthető.

Amennyiben a program futasa leall, egyszeru a valasz a glib-2.9.x (x=2 szerintem) verzio ota minden critical-warning uzenet eseten megszakitja a program futasat.
Ha ez fenn all gdb-vel konnyen tudsz debuggolni. Csak egy backtrace kell. A hiba a te programodban lesz. Egy kodreszlet segitene.
Glibet nem kell ujratelepiteni egy ilyen miatt. Kozvetlenul nem hivod ezt a fv-t te attol meg meghivodik.
Egyelore ennyi irj valami kodot, nezzuk at.

A gdb backtrace ezt mondja:

(gdb) backtrace
#0 0xb6f7b0d6 in strncmp () from /lib/tls/libc.so.6
#1 0xb764b67f in gtk_entry_completion_get_type ()
from /usr/lib/libgtk-x11-2.0.so.0
#2 0xb764b72c in gtk_entry_completion_get_type ()
from /usr/lib/libgtk-x11-2.0.so.0
#3 0xb7790360 in gtk_tree_model_filter_get_type ()
from /usr/lib/libgtk-x11-2.0.so.0
#4 0xb7790b3a in gtk_tree_model_filter_get_type ()
from /usr/lib/libgtk-x11-2.0.so.0
#5 0xb7793ea6 in gtk_tree_model_filter_convert_path_to_child_path ()
from /usr/lib/libgtk-x11-2.0.so.0
#6 0xb778eabb in gtk_tree_model_rows_reordered ()
from /usr/lib/libgtk-x11-2.0.so.0
#7 0xb778ebdd in gtk_tree_model_foreach () from /usr/lib/libgtk-x11-2.0.so.0
#8 0xb7793f09 in gtk_tree_model_filter_refilter ()
from /usr/lib/libgtk-x11-2.0.so.0
#9 0xb764c1c7 in gtk_entry_completion_complete ()
from /usr/lib/libgtk-x11-2.0.so.0
#10 0xb764918a in gtk_entry_get_alignment () from /usr/lib/libgtk-x11-2.0.so.0
#11 0xb7172a0c in g_main_context_wakeup () from /usr/lib/libglib-2.0.so.0
#12 0xb717041f in g_main_depth () from /usr/lib/libglib-2.0.so.0
#13 0xb7171412 in g_main_context_dispatch () from /usr/lib/libglib-2.0.so.0
#14 0xb717174b in g_main_context_dispatch () from /usr/lib/libglib-2.0.so.0
---Type to continue, or q to quit---
#15 0xb7171cc1 in g_main_loop_run () from /usr/lib/libglib-2.0.so.0
#16 0xb76c2e93 in gtk_main () from /usr/lib/libgtk-x11-2.0.so.0
#17 0x0805bc3f in main (argc=0, argv=0x0) at main.c:65

Ezzel sajnos nem tudok mit kezdeni. A gdb-vel is csak most ismerkedem.

Milyen kódrészletet adjak meg? Azt, amelyik a completion-t intézi?
A gond az, hogy nem eközben áll le, hanem ha beírok a gtk_entry-be valamit.

Köszi a segítséget! Várom a válaszodat!

Üdv

Igen jo lenne tudni, hogy mit is csinalsz pontosan. Egy kis kodreszletet megoszthatnal.

Mi kell ide?
1 GtkEntry*
2 GtkTreeModel*
3 GtkEntryCompletion*

Ezeket kell letrehozni, osszekapcsolni.
Akkor is leall ha nem kapcsolsz a GtkEntry widgetedhez completion-t?

A beviteli mezőket glade-ből hozom létre. Ezután egy gombbal (bár ez később automatikus lesz) feltölti MySQL-ből az entryket.

A gombnyomásra meghívódó függvény részlete:

comboboxentry_feltoltes("SELECT DISTINCT eloado_nev FROM Eloado ORDER BY eloado_nev;", "comboboxentry_lekerdezes_eloado");

ez hívódik meg minden egyes entryre.

A függyvény pedig:

void comboboxentry_feltoltes(gchar * query, gchar * comboboxentry)
{
	GtkListStore *store;
	GtkTreeIter iter;
	GtkEntryCompletion *completion;
	
	completion = gtk_entry_completion_new();
	gtk_entry_set_completion (GTK_ENTRY(GTK_BIN(glade_xml_get_widget(gui_foablak, comboboxentry))->child), completion);
	g_object_unref(completion);
	
	store = gtk_list_store_new (1, G_TYPE_STRING);
	
	if (mysql_query(&mysql, query))
	{
		mia_mysql_error(&mysql, query);
	}
	else
	{
		result = mysql_store_result(&mysql);
		
		if (result)
		{
			while ((row = mysql_fetch_row(result)) != NULL)
			{
				if (row[0])
				{
					gtk_list_store_append (store, &iter);
					gtk_list_store_set (store, &iter, 0, gmia_conv_to_utf8(row[0]), -1);
				}
			}
			gtk_entry_completion_set_model (completion, GTK_TREE_MODEL(store));
			g_object_unref (store);
			gtk_entry_completion_set_text_column (completion, 0);
			//gtk_entry_completion_set_inline_completion (completion, TRUE);
			//gtk_entry_completion_insert_prefix(completion);
		}
		else
		{
			mia_mysql_error(&mysql, query);
		}
	}
}

Ennyi. Minden példában, tutorialban ezt írják. Meg mondom: debian alatt megy a dolog.

A két commentezett sort élesítve is hibával áll le.
Ha nem kapcsolom a completiont a GtkEntry widgethez, akkor nem áll le, viszont nem látom a lehetőségeket. :(

Az talán feltűnik a kódból, hogy konkrétan GtkEntry-t használok, hanem GtkComboBoxEntry-t, melynek egy gyermeke az entry.

Ezt próbáltam már GtkEntry-re is lecserélni, úgyanúgy hibás, úgyhogy visszatértem rá.

Köszi a segítséget!

Üdv

Közben újrafogattam a gtk+-t 2.8.12-re. Változatlan a helyzet.
Érdemes lenne glib-et is frissíteni?

A progimban nem hiszem, hogy tovább jutok...

Nem lehet hogy a gmia_conv_to_utf8() fuggvenyed csinal valamit amivel a completion nem tud mit kezdeni?
Mert fix sztringekkel teljesen mukodokepes a kodod.

Itt a gmia_conv_to_utf8 függvény:

gchar* gmia_conv_to_utf8(gchar * text)
{
	gchar *utf8;
	gboolean utf8valid;
	
	utf8 = g_locale_to_utf8(text, -1, NULL, NULL, NULL);
	if (utf8)
	{
		utf8valid = g_utf8_validate(utf8, -1, NULL);
		return utf8;
	}
	else
	{
		return text;
	}
	
	g_free(utf8);
}

Ezt már régóta így használom. Tulajdonképpen a MySQL és a Gnome közötti karakterkészlet-váltáshoz kell. Van egy párja is _from_utf8() néven.

Esetleg tudnátok segíteni gdb-vel felderíteni a hibát?
Mostanában kezdek ismerkedni vele, sok alap leírást olvastam már, de érdemben még nem tudtam használni.

Ha glib-et és gtk-t debug kapcsolókkal fordítottam, nem lehetne abban is lekövetni, mit csinál?

En egyszeruen -ggdb opcioval forditok gdb-hez. Ha crash van "bt" vagy "bt full" legtobbszor eleg is.

Most is ugy gondolom, hogy a hiba ott lesz, hogy g_locale_to_utf8 NULL-al ter vissza (hiba) es visszadod a text-et a listaba, amivel a gtk nem tud mit kezdeni. Ide vonatkozo reszlet:

void
gtk_entry_completion_complete (GtkEntryCompletion *completion)
{
  gchar *tmp;

  g_return_if_fail (GTK_IS_ENTRY_COMPLETION (completion));

  if (!completion->priv->filter_model)
    return;
  
  if (completion->priv->case_normalized_key)
    g_free (completion->priv->case_normalized_key);

  tmp = g_utf8_normalize (gtk_entry_get_text (GTK_ENTRY (completion->priv->entry)),
                          -1, G_NORMALIZE_ALL);
  completion->priv->case_normalized_key = g_utf8_casefold (tmp, -1);
  g_free (tmp);

  gtk_tree_model_filter_refilter (completion->priv->filter_model);

  if (GTK_WIDGET_VISIBLE (completion->priv->popup_window))
    _gtk_entry_completion_resize_popup (completion);
}

tmp = g_utf8_normalize ->NULL, g_utf8_casefold ->crash
szvsz.

Probald ki hogy: return text; helyett return "x";
vagy irass ki valamit konzolra, hogy tenyleg ez-e a rossz.

Azt nem ertem miert kell a g_utf8_validate miutan mar atpakoltad UTF8-ba.
inkabb:

GError *error = NULL;
if (text && !g_utf8_validate(text, -1, NULL)) {
    utf8 = g_locale_to_utf8 (text, -1, NULL, NULL, &error)
    if (!utf8) {
        g_warning ("%s", error->message);
        g_error_free (error);
        return NULL;
    }
    return utf8;
}
return text;

Valami ilyesmire gondoltam, de ne vedd keszpenznek, faradok.;)

A fo programban:

if (row[0]) {
    gchar *text;
    text = gmia_conv_to_utf8(row[0]);
    gtk_list_store_append (store, &iter);
    gtk_list_store_set (store, &iter, 0, text, -1);
    g_free (text);
}

A GtkListStore lemasolja maganak a sztringet.

Tényleg nem kell a g_utf8_validate!

Lecseréltem a kérdéses kódrészt a fentire, és működik. :)))
Nagyon szépen köszönöm!

Egy szépséghibája azonban van a dolognak:
"Érvénytelen bájtsorrend az átalakítás bemenetében" üzenetet kapok megszámlálhatatlan mennyiségben.
Mindenképpen utánanézek én is, de ez mitől lehet?

Mégegyszer nagyon köszi!

Üdv

ctrl/alt/backspace elvitte amit elobb irtam.
Gyorsan, roviden meg egyszer.

g_warning helyett g_printf()-el irasd ki a bejovo sztringet, akkor meglatjuk melyik recordnal nem tud konvertalni.
Masik: g_locale_to_utf8 helyett g_convert.
Lehet hogy a mysql kodkeszlete elter a rendszeretol.
Nezd meg a mysqlt es annak fvnyeben g_convert(), ott lehet varialni az input/ouput kodkeszleteket.

hajra!

> Érdemes lenne glib-et is frissíteni?
Nem.