GTK+ szignálküldés: delete-event

Fórumok

Van egy programom, amelyben feldolgozom az alkalmazás főablakára irányuló delete_event szignált:

gboolean main_window_delete_event (GtkWidget * widget, GdkEvent * event, gpointer user_data) {
g_print ("delete-event\n");
return FALSE;
}

A szigálkezelő függvény a FALSE visszatérési értékkel jelzi, hogy az alkalmazás kiléphet, ha pedig a visszatérési érték TRUE, akkor az alkalmazás fut tovább.

Azt szerettem volna, hogy ha a program menűjéből kiválaszták a kilépés menűpontot, akkor egyszerűen küldje el a főablaknak a "delete-event" szignált, így az egész kilépési folyamatot csak egyszer kell megírnom, és a lehetőségekhez képest még szabályos is maradok:

void menuitem_quit_activate (GtkMenuItem * menuitem, gpointer user_data) {
/* a foablaknak kuldunk egy "delete_event" szignalt */
gboolean teszt;

g_signal_emit_by_name (G_OBJECT(main_window), "delete_event", G_TYPE_NONE, &teszt);
g_print ("eredmeny: %d\n", teszt);
}

Ha ez a szignálkezelő függvény végrehajtódik, akkor sikeresen elküldi a főablaknak a szignált (vagyis kiíródik a "delete-event" szöveg), a "teszt" változóban visszakapom annak a szignálkezelő függvénynek a visszatérési értékét, de a program nem lép ki, hanem továbbfut. Hiába játszadoztam a "delete-event" szignál visszatérési értékével, nem jutottam tovább.

Mi lehet a hiba, és a helyes megoldás?

Hozzászólások

g_signal_emit_by_name

helyett ezzel?:

g_signal_connect_swapped(G_OBJECT(menu_item), "activate", G_CALLBACK(main_window_delete_event), G_OBJECT(main_window));

a main_window delete_event -jere van g_signal_connect?

gboolean main_window_delete_event (GtkWidget * widget, GdkEvent * event, gpointer user_data) {
g_print ("delete-event\n");
return FALSE;
}


g_signal_connect(G_OBJECT(main_window), "delete_event", G_CALLBACK(main_window_delete_event), NULL);

void menuitem_quit_activate (GtkMenuItem * menuitem, gpointer user_data) {
/* a foablaknak kuldunk egy "delete_event" szignalt */
gboolean teszt;

g_signal_emit_by_name (G_OBJECT(main_window), "delete_event", G_TYPE_NONE, &teszt);
g_print ("eredmeny: %d\n", teszt);
}

gboolean ret;
g_signal_emit_by_name (G_OBJECT(main_window), "delete_event", main_window, &ret);

Bar ezt most csak emlekezetbol.
vagy ez nem jo?
gtk_widget_destroy (main_window);

A gtk_widget_destroy (main_window) azért nem jó, mert ha a felhasználó nem mentette a munkáját, akkor lehetőséget szeretnék neki adni erre.
Bár, ha jobban belegondolok, akkor amikor az lefut, elméletileg meghívodna a "delete_event" is.

Mindenesetre, talán rosszul gondolom, de úgy lenne igazán szép a megoldás, ha küldenék a main_window -nak szignált, ahogy eredetileg terveztem.

csinálsz egy cleanup függvényt amiben elvégzed a program kilépés előtti műveleteket, mondjuk így:


gboolean cleanup(GtkWidget *widget, GdkEvent *event, gpointer data)
{
  amit akarsz a kilépés előtt;
  gtk_widget_destroy(foablakod_neve);
  return FALSE;
}

Sima g_signal_connect-tel hozzácsatolod a főablakodhoz a "delete-event" signallal, majd csinálsz még egy csatolást a kilépéshez, pl.:


g_signal_connect(G_OBJECT(foablakod_neve), "destroy",
    G_CALLBACK(gtk_main_quit), NULL);

A menüből pedig a cleanup függvényt hívod.

Visszavonok szinte mindent. eleg a gtk_widget_destroy(window);
Ha a destroy signalhoz van callback fuggveny meghivodik. tehat akkor eleg lesz ott elvegezni a dolgokat.
Az menu action-jeben meg csak destroy();

Igen,attól függ mi is pontosan a cél.

A "destroy" mindenképp "kiléptet", de előbb lefuttatja a callback függvényét.

A "delete_event" a visszatérési értékétől függően:

FALSE esetén meghívódik a destroy,
TRUE esetén már nem kerül sor a destroy -ra, (nem záródik az alkalm.)

Tipikusan "Biztos kilépsz ebből a jó programból ?" jellegű dolgok esetén van értelme.

A kiinduló probléma esetében a legegyszerűbb a g_signal_connect_swapped(...)
lenne szerintem.

[...]

gboolean main_window_delete_event (GtkWidget * widget, GdkEvent * event, gpointer user_data) {
g_print ("delete-event\n");
return FALSE;
}

g_signal_connect(G_OBJECT(main_window), "delete_event", G_CALLBACK(main_window_delete_event), NULL);

g_signal_connect_swapped(G_OBJECT(menu_item), "activate", G_CALLBACK(main_window_delete_event), G_OBJECT(main_window));

[...]

Ha olyan eseménykezelésre van szükség amit menüből és toolbarról is hívni kell, akkor inkább az "actionXXX" függvények, ill: libbonobo...

szerk: egy gtk_main_quit(); is jól jöhet

Kipróbáltam tegnap a három dolgot, amiket írtatok, az eredmények:

g_signal_emit_by_name (G_OBJECT(main_window), "delete_event", main_window, &ret);

Nem jó, ugyanazt a hibát produkálja, mint a nyitó hozzászólásban írt megoldásom.

g_signal_connect_swapped(G_OBJECT(menuitem), "activate", G_CALLBACK(main_window_delete_event), G_OBJECT(main_window));

Ha a menűben először kattintok a kilépésre, nem történik semmi, utána való kattintáskor lefut a "delete_event", de nem lép ki a program.

gtk_widget_destroy (main_window);

Nem fut le a "delete_event", hanem szó nélkül kilép a program.

A többi dolgot, amit írtatok, ma tudom kipróbálni.