Search code examples
c++gtkgtk3filechooser

GTK+ 3 native file chooser - allowed file types and default file name


I am using GTK+ to create a C++ program. For choosing files I used native file chooser as the gtk file chooser has a memory leak.

Here is my question: How can I set a default file name for the native file chooser in GTK+ (while saving) and how can I setup a file filter for it - to be able to open or save only specific file extensions?

My program works on Win32. Sample code:

static void cb_SaveFileAs(GtkWidget *caller)
{
    GtkWindow *parent_window = GTK_WINDOW(caller);
    GtkFileChooserNative *native;
    GtkFileChooserAction action = GTK_FILE_CHOOSER_ACTION_SAVE;
    gint res;

    native = gtk_file_chooser_native_new("Save File",
                                         parent_window,
                                         action,
                                         "_Save",
                                         "_Cancel");

    res = gtk_native_dialog_run(GTK_NATIVE_DIALOG(native));
    if (res == GTK_RESPONSE_ACCEPT)
    {
        char *filename;
        GtkFileChooser *chooser = GTK_FILE_CHOOSER(native);
        filename = gtk_file_chooser_get_filename(chooser);

        // save the file 
        save_to_file(filename);

        g_free(filename);
    }

    g_object_unref(native);
}

Solution

  • Here is an example of setting a GtkFileFilter with the *.cpp pattern to only show C++ files. It also sets the default document name to test.cpp.

    compiling with : g++ filechooser.cpp `pkg-config --cflags gtk+-3.0` `pkg-config --libs gtk+-3.0`

    #include <gtk/gtk.h>
    
    static void dialog_result(GtkWidget *dialog, gint resp, gpointer data)
    {
        if (resp == GTK_RESPONSE_OK) {
            // do nothing
        } else {
            gtk_widget_destroy(dialog);
        }
    }
    
    static void open_dialog(GtkWidget *button, gpointer window)
    {
        GtkWidget *dialog;
        GtkFileFilter *filter;
    
        dialog = gtk_file_chooser_dialog_new("Choose a file:", GTK_WINDOW(window), 
                            GTK_FILE_CHOOSER_ACTION_SAVE, GTK_STOCK_SAVE,
                             GTK_RESPONSE_OK, GTK_STOCK_CANCEL,
                             GTK_RESPONSE_CANCEL, NULL);
    
        filter = gtk_file_filter_new();
        gtk_file_filter_add_pattern(filter, "*.cpp");
        gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(dialog), filter);
        gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(dialog), "test.cpp");
        gtk_widget_show_all(dialog);
        gint resp = gtk_dialog_run(GTK_DIALOG(dialog));
        if (resp == GTK_RESPONSE_OK)
            g_print("%s\n", gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog)));
        else
            g_print("You pressed the cancel\n");
        gtk_widget_destroy(dialog);
    }
    
    int main()
    {
        gtk_init(NULL, NULL);
        GtkWidget *window, *button;
        window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
        g_signal_connect(window, "delete_event", G_CALLBACK(gtk_main_quit), NULL);
        button = gtk_button_new_with_label("Save");
        g_signal_connect(button, "clicked", G_CALLBACK(open_dialog), window);
        gtk_container_set_border_width(GTK_CONTAINER(window), 100);
        gtk_container_add(GTK_CONTAINER(window), button);
        gtk_widget_show_all(window);
        gtk_main();
    }