I want to choose a several files and write their path to TextView widget by click on the button. I have memory leaks and dont understand how to properly free memory. Sometimes my application is not starting at all, sometimes for second click I have segmentation fault. Also there are this errors every time:
GLib-CRITICAL **: 14:48:38.184: g_main_context_pop_thread_default: assertion 'g_queue_peek_head (stack) == context' failed
GLib-CRITICAL **: 14:48:42.576: g_hash_table_contains: assertion 'hash_table != NULL' failed
GLib-CRITICAL **: 14:48:42.586: g_hash_table_insert_internal: assertion 'hash_table != NULL' failed
Segmentation fault
Callback functions in C for file dialog is below:
static void
choseTargetFinish (GObject* source_object, GAsyncResult* res, gpointer data)
{
GtkFileDialog *dialog = GTK_FILE_DIALOG (source_object);
GListModel *files = gtk_file_dialog_open_multiple_finish(dialog, res, NULL);
if (files != NULL)
{
GtkTextIter *start;
GtkTextIter *end;
gtk_text_buffer_get_start_iter(targetPathBuffer, start);
gtk_text_buffer_get_end_iter(targetPathBuffer, end);
gtk_text_buffer_delete(targetPathBuffer, start, end);
GFile *file;
char *path;
int i = 0;
file = g_list_model_get_item(files, i);
end = start;
while (file != NULL)
{
path = g_file_get_path(file);
sprintf(path, "%s\n", path);
gtk_text_buffer_insert(targetPathBuffer, end, path, -1);
gtk_text_buffer_get_end_iter(targetPathBuffer, end);
i++;
file = g_list_model_get_item(files, i);
}
g_free(path);
}
}
static void
chooseTarget_cb (GtkWidget *widget)
{
GtkFileDialog *fd = gtk_file_dialog_new();
GAsyncResult* result;
gtk_file_dialog_open_multiple(fd, NULL, NULL, choseTargetFinish, NULL);
g_object_unref(fd);
}
I read docs and it says I should free GListModel and I tried to do it by g_object_unref.
It is always difficult to find a bug if you have only part of the program ahead of you.I have therefore taken my own approach, but it does exactly what is obviously expected by the program. - I hope so :-)
#include"multible-file.h"
GtkTextBuffer *buffer;
const gchar* list_to_string(GListModel* list) {
GObject* item;
GString* result = g_string_new("");
guint i = g_list_model_get_n_items(list);
for (guint i = 0; i < g_list_model_get_n_items(list); i++)
{
item = g_list_model_get_object(list, i);
const gchar* str = g_file_get_parse_name(G_FILE(item));
g_string_append(result,"\n");
g_string_append(result, str);
g_object_unref(item);
}
return g_string_free(result, FALSE);
}
static void
choseTargetFinish (GObject* source_object, GAsyncResult* res, gpointer data)
{
GtkFileDialog *dialog = GTK_FILE_DIALOG (source_object);
GListModel *files = gtk_file_dialog_open_multiple_finish(dialog, res, NULL);
const gchar *content = list_to_string(files);
gtk_text_buffer_set_text(buffer,content,-1);
g_free((gpointer)content);
g_object_unref(files);
}
static void
chooseTarget_cb (GtkWidget *widget)
{
GtkFileDialog *fd = gtk_file_dialog_new();
gtk_file_dialog_open_multiple(fd,NULL , NULL, choseTargetFinish, NULL);
g_object_unref(fd);
}
void activate (GtkApplication *app, gpointer data)
{
GtkWidget *window;
window =gtk_application_window_new(app);
gtk_widget_set_size_request(window,700,150);
GtkWidget *box = gtk_box_new(GTK_ORIENTATION_VERTICAL,10);
GtkWidget * button = gtk_button_new_with_label("FileDialog");
g_signal_connect(button,"clicked",G_CALLBACK(chooseTarget_cb),NULL);
GtkWidget *textview = gtk_text_view_new();
buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(textview));
gtk_box_append(GTK_BOX(box),button);
gtk_box_append(GTK_BOX(box),textview);
gtk_window_set_child(GTK_WINDOW(window),box);
gtk_widget_set_visible(window,TRUE);
}
Please note that the ListModel contends objects. In this case GFile-Objects. These must then be parsed to the string. For a better overview, I have this outsourced to its own function.