2

I'm writing an app using SFML and I want to use GTK+ to create file chooser dialogs. I have this code:

gtk_init(&argc, &argv);

GtkWidget *dialog;
dialog = gtk_file_chooser_dialog_new ("Open file...", NULL, GTK_FILE_CHOOSER_ACTION_OPEN, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, NULL);
gtk_dialog_run (GTK_DIALOG (dialog));

And the dialog is showing, but it doesn't get destroyed :(

m4tx
  • 4,139
  • 5
  • 37
  • 61

1 Answers1

2

In the gtk_dialog_run documentation there is a note

After gtk_dialog_run() returns, you are responsible for hiding or destroying the dialog if you wish to do so.

So the dialog should not get destroyed automaticaly, the programmer must do it.


EDIT:

The another problem is that you are not running GTK main loop (gtk_main() or its variant) so the GTK can not deal with events necessary to destroy a widget (no part of GTK is running in the time the events are present). The sollution for this is in answer to another question using gtk_idle_add() to invoke function after gtk_main() is called. In this function the dialog is shown, the result is given to the caller, the dialog is destroyed and gtk_main_quit() is called to terminate GTK main loop.

However, gtk_idle_add() is deprecated in GTK+2.6 and is not present in GTK+3.0, so g_idle_add() should be used instead. Your code could be somethink like

struct fch_result {
    gint response;
    // other information to return like filename,...
};

static gboolean fch_dialog(gpointer user_data)
{
    struct fch_result *result = (struct fch_result *) user_data;
    GtkWidget *dialog = gtk_file_chooser_dialog_new ( ... );
    result->response = gtk_dialog_run (GTK_DIALOG(dialog));
    // now add other information to result

    gtk_widget_destroy(dialog);
    gtk_main_quit();  // terminate the gtk_main loop called from caller
    return FALSE;
}

int main(int argc, char** argv)
{
    gtk_init(&argc, &argv);

    struct fch_result data;
    g_idle_add(fch_dialog, &data);

    gtk_main();

    // continue with the program
    return 0;
}
Community
  • 1
  • 1
Michy
  • 623
  • 9
  • 15
  • I added `gtk_widget_destroy(dialog);` but it's still not destroying :( – m4tx Aug 01 '11 at 06:31
  • @m4tx I have extended my answer, please check if it solves your problem now. – Michy Aug 01 '11 at 10:11
  • Ok, thanks, but I have now this problem: `error: invalid conversion from ‘void*’ to ‘fch_result*’` I don't know how to solve it. The error is in `struct fch_result *result = user_data;` – m4tx Aug 01 '11 at 10:24
  • Ok, I solved it. I changed `struct fch_result *result = user_data;` to `struct fch_result *result = (fch_result*) user_data;` and it works. Thanks! – m4tx Aug 01 '11 at 10:30
  • Sorry, I didn't notified the C++ flag, in C the implicit conversion happends (it happends only for void pointers, the sollution worked in C because gpointer is defined as void*), in C++ the explicit conversion is necessary. I have included this correction to my answer. – Michy Aug 01 '11 at 10:34