From ac524bb13afca3d28003954d2fbbde0e262ae6f4 Mon Sep 17 00:00:00 2001 From: Benjamin Otte Date: Tue, 30 Jun 2020 23:31:49 +0200 Subject: [PATCH] demo: Make words listview load async And add an "Open" button (why are filechooser buttons such a catastrophe that I can't make them smaller?). --- demos/gtk-demo/listview_words.c | 123 +++++++++++++++++++++++++++++--- 1 file changed, 115 insertions(+), 8 deletions(-) diff --git a/demos/gtk-demo/listview_words.c b/demos/gtk-demo/listview_words.c index c8aab2360d..1d6676e85c 100644 --- a/demos/gtk-demo/listview_words.c +++ b/demos/gtk-demo/listview_words.c @@ -45,30 +45,134 @@ update_title_cb (GtkFilterListModel *model) g_free (title); } +static void +read_lines_cb (GObject *object, + GAsyncResult *result, + gpointer data) +{ + GBufferedInputStream *stream = G_BUFFERED_INPUT_STREAM (object); + GtkStringList *stringlist = data; + GError *error = NULL; + gsize size; + GPtrArray *lines; + gssize n_filled; + const char *buffer, *newline; + + n_filled = g_buffered_input_stream_fill_finish (stream, result, &error); + if (n_filled < 0) + { + g_print ("Could not read data: %s\n", error->message); + g_clear_error (&error); + return; + } + + buffer = g_buffered_input_stream_peek_buffer (stream, &size); + + if (n_filled == 0) + { + if (size) + gtk_string_list_take (stringlist, g_utf8_make_valid (buffer, size)); + return; + } + + lines = NULL; + while ((newline = memchr (buffer, '\n', size))) + { + if (newline > buffer) + { + if (lines == NULL) + lines = g_ptr_array_new_with_free_func (g_free); + g_ptr_array_add (lines, g_utf8_make_valid (buffer, newline - buffer)); + } + if (g_input_stream_skip (G_INPUT_STREAM (stream), newline - buffer + 1, NULL, &error) < 0) + { + g_clear_error (&error); + break; + } + buffer = g_buffered_input_stream_peek_buffer (stream, &size); + } + if (lines == NULL) + { + g_buffered_input_stream_set_buffer_size (stream, g_buffered_input_stream_get_buffer_size (stream) + 4096); + } + else + { + g_ptr_array_add (lines, NULL); + gtk_string_list_splice (stringlist, g_list_model_get_n_items (G_LIST_MODEL (stringlist)), 0, (const char **) lines->pdata); + g_ptr_array_free (lines, TRUE); + } + + g_buffered_input_stream_fill_async (stream, -1, G_PRIORITY_HIGH_IDLE, NULL, read_lines_cb, data); +} + +static void +file_is_open_cb (GObject *file, + GAsyncResult *result, + gpointer data) +{ + GError *error = NULL; + GFileInputStream *file_stream; + GBufferedInputStream *stream; + + file_stream = g_file_read_finish (G_FILE (file), result, &error); + if (file_stream == NULL) + { + g_print ("Could not open file: %s\n", error->message); + g_error_free (error); + return; + } + + stream = G_BUFFERED_INPUT_STREAM (g_buffered_input_stream_new (G_INPUT_STREAM (file_stream))); + g_buffered_input_stream_fill_async (stream, -1, G_PRIORITY_HIGH_IDLE, NULL, read_lines_cb, data); + g_object_unref (stream); +} + +static void +load_file (GtkStringList *list, + GFile *file) +{ + gtk_string_list_splice (list, 0, g_list_model_get_n_items (G_LIST_MODEL (list)), NULL); + g_file_read_async (file, G_PRIORITY_HIGH_IDLE, NULL, file_is_open_cb, list); +} + +static void +file_selected_cb (GtkWidget *button, + GtkStringList *stringlist) +{ + GFile *file = gtk_file_chooser_get_file (GTK_FILE_CHOOSER (button)); + + if (file) + { + load_file (stringlist, file); + g_object_unref (file); + } +} + GtkWidget * do_listview_words (GtkWidget *do_widget) { if (window == NULL) { - GtkWidget *header, *listview, *sw, *vbox, *search_entry; + GtkWidget *header, *listview, *sw, *vbox, *search_entry, *open_button; GtkFilterListModel *filter_model; GtkStringList *stringlist; GtkFilter *filter; - char **words; - char *usr_dict_words; GtkExpression *expression; + GFile *file; - if (g_file_get_contents ("/usr/share/dict/words", &usr_dict_words, NULL, NULL)) + file = g_file_new_for_path ("/usr/share/dict/words"); + if (g_file_query_exists (file, NULL)) { - words = g_strsplit (usr_dict_words, "\n", -1); - g_free (usr_dict_words); + stringlist = gtk_string_list_new (NULL); + load_file (stringlist, file); } else { + char **words; words = g_strsplit ("lorem ipsum dolor sit amet consectetur adipisci elit sed eiusmod tempor incidunt labore et dolore magna aliqua ut enim ad minim veniam quis nostrud exercitation ullamco laboris nisi ut aliquid ex ea commodi consequat", " ", -1); + stringlist = gtk_string_list_new ((const char **) words); + g_strfreev (words); } - stringlist = gtk_string_list_new ((const char **) words); - g_strfreev (words); filter = gtk_string_filter_new (); expression = gtk_property_expression_new (GTK_TYPE_STRING_OBJECT, NULL, "string"); @@ -81,6 +185,9 @@ do_listview_words (GtkWidget *do_widget) gtk_window_set_title (GTK_WINDOW (window), "Words"); header = gtk_header_bar_new (); gtk_header_bar_set_show_title_buttons (GTK_HEADER_BAR (header), TRUE); + open_button = gtk_file_chooser_button_new ("_Open", GTK_FILE_CHOOSER_ACTION_OPEN); + g_signal_connect (open_button, "file-set", G_CALLBACK (file_selected_cb), stringlist); + gtk_header_bar_pack_start (GTK_HEADER_BAR (header), open_button); gtk_window_set_titlebar (GTK_WINDOW (window), header); gtk_window_set_display (GTK_WINDOW (window),