[gtk/wip/otte/json: 21/21] demos: Add a simple JSON demo
- From: Benjamin Otte <otte src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk/wip/otte/json: 21/21] demos: Add a simple JSON demo
- Date: Sun, 5 Dec 2021 21:10:01 +0000 (UTC)
commit ba612edcb6ed5695d3f6c8aedf36b8ed04bbbdee
Author: Benjamin Otte <otte redhat com>
Date: Mon Nov 29 09:46:49 2021 +0100
demos: Add a simple JSON demo
Download the GTK releases from the gitlab REST API and display them in a
list.
Much creative.
demos/gtk-demo/demo.gresource.xml | 4 +
demos/gtk-demo/listview_releases.c | 240 ++++++++++++++++++++++++++++++++++++
demos/gtk-demo/listview_releases.ui | 93 ++++++++++++++
demos/gtk-demo/meson.build | 4 +-
4 files changed, 340 insertions(+), 1 deletion(-)
---
diff --git a/demos/gtk-demo/demo.gresource.xml b/demos/gtk-demo/demo.gresource.xml
index 83e798fd25..d2599abb1f 100644
--- a/demos/gtk-demo/demo.gresource.xml
+++ b/demos/gtk-demo/demo.gresource.xml
@@ -192,6 +192,9 @@
<file>listview_minesweeper.ui</file>
<file>listview_minesweeper_cell.ui</file>
</gresource>
+ <gresource prefix="/listview_releases">
+ <file>listview_releases.ui</file>
+ </gresource>
<gresource prefix="/listview_settings">
<file>listview_settings.ui</file>
</gresource>
@@ -304,6 +307,7 @@
<file>listview_clocks.c</file>
<file>listview_filebrowser.c</file>
<file>listview_minesweeper.c</file>
+ <file>listview_releases.c</file>
<file>listview_settings.c</file>
<file>listview_ucd.c</file>
<file>listview_weather.c</file>
diff --git a/demos/gtk-demo/listview_releases.c b/demos/gtk-demo/listview_releases.c
new file mode 100644
index 0000000000..f2f086f990
--- /dev/null
+++ b/demos/gtk-demo/listview_releases.c
@@ -0,0 +1,240 @@
+/* Lists/Application launcher
+ * #Keywords: GtkListItemFactory, GListModel,JSON
+ *
+ * This demo downloads GTK's latest release and displays them in a list.
+ *
+ * It shows how hard it still is to get JSON into lists.
+ */
+
+#include <gtk/gtk.h>
+
+#include "gtk/json/gtkjsonparserprivate.h"
+
+#define GTK_TYPE_RELEASE (gtk_release_get_type ())
+
+G_DECLARE_FINAL_TYPE (GtkRelease, gtk_release, GTK, RELEASE, GObject)
+
+struct _GtkRelease
+{
+ GObject parent_instance;
+
+ char *name;
+ GDateTime *timestamp;
+};
+
+struct _GtkReleaseClass
+{
+ GObjectClass parent_class;
+};
+
+enum {
+ PROP_0,
+ PROP_NAME,
+ PROP_TIMESTAMP,
+
+ N_PROPS
+};
+
+G_DEFINE_TYPE (GtkRelease, gtk_release, G_TYPE_OBJECT)
+static GParamSpec *properties[N_PROPS] = { NULL, };
+
+static void
+gtk_release_finalize (GObject *object)
+{
+ GtkRelease *self = GTK_RELEASE (object);
+
+ g_free (self->name);
+ g_clear_pointer (&self->timestamp, g_date_time_unref);
+
+ G_OBJECT_CLASS (gtk_release_parent_class)->finalize (object);
+}
+
+static void
+gtk_release_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GtkRelease *self = GTK_RELEASE (object);
+
+ switch (property_id)
+ {
+ case PROP_NAME:
+ g_value_set_string (value, self->name);
+ break;
+
+ case PROP_TIMESTAMP:
+ {
+ if (self->timestamp)
+ g_value_take_string (value, g_date_time_format (self->timestamp, "%x"));
+ else
+ g_value_set_string (value, "---");
+ }
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ break;
+ }
+}
+
+static void
+gtk_release_class_init (GtkReleaseClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+ gobject_class->finalize = gtk_release_finalize;
+ gobject_class->get_property = gtk_release_get_property;
+
+ properties[PROP_NAME] =
+ g_param_spec_string ("name", NULL, NULL, NULL, G_PARAM_READABLE);
+ properties[PROP_TIMESTAMP] =
+ g_param_spec_string ("timestamp", NULL, NULL, NULL, G_PARAM_READABLE);
+
+ g_object_class_install_properties (gobject_class, N_PROPS, properties);
+}
+
+static void
+gtk_release_init (GtkRelease *self)
+{
+}
+
+static GtkRelease *
+gtk_release_new (const char *name,
+ GDateTime *timestamp)
+{
+ GtkRelease *result;
+
+ result = g_object_new (GTK_TYPE_RELEASE, NULL);
+
+ result->name = g_strdup (name);
+ if (timestamp)
+ result->timestamp = g_date_time_ref (timestamp);
+
+ return result;
+}
+
+static void
+loaded_some_releases_cb (GObject *file,
+ GAsyncResult *res,
+ gpointer userdata)
+{
+ GListStore *store = userdata;
+ GBytes *bytes;
+ GtkJsonParser *parser;
+ GError *error = NULL;
+
+ bytes = g_file_load_bytes_finish (G_FILE (file), res, NULL, &error);
+ if (bytes == NULL)
+ {
+ g_printerr ("Error loading: %s\n", error->message);
+ g_clear_error (&error);
+ return;
+ }
+
+ parser = gtk_json_parser_new_for_bytes (bytes);
+ g_bytes_unref (bytes);
+
+ gtk_json_parser_start_array (parser);
+ do
+ {
+ enum { NAME, COMMIT };
+ static const char *options[] = { "name", "commit", NULL };
+ GDateTime *created = NULL;
+ char *name = NULL;
+
+ gtk_json_parser_start_object (parser);
+ do
+ {
+ switch (gtk_json_parser_select_member (parser, options))
+ {
+ case NAME:
+ g_clear_pointer (&name, g_free);
+ name = gtk_json_parser_get_string (parser);
+ break;
+ case COMMIT:
+ g_clear_pointer (&created, g_date_time_unref);
+ gtk_json_parser_start_object (parser);
+ if (gtk_json_parser_find_member (parser, "created_at"))
+ {
+ char *created_string = gtk_json_parser_get_string (parser);
+ created = g_date_time_new_from_iso8601 (created_string, NULL);
+ g_free (created_string);
+ }
+ gtk_json_parser_end (parser);
+ break;
+ default:
+ break;
+ }
+ }
+ while (gtk_json_parser_next (parser));
+ gtk_json_parser_end (parser);
+
+ if (name)
+ {
+ GtkRelease *release = gtk_release_new (name, created);
+ g_list_store_append (store, release);
+ g_object_unref (release);
+ }
+ g_clear_pointer (&name, g_free);
+ g_clear_pointer (&created, g_date_time_unref);
+ }
+ while (gtk_json_parser_next (parser));
+ gtk_json_parser_end (parser);
+
+ if (gtk_json_parser_get_error (parser))
+ {
+ const GError *json_error = gtk_json_parser_get_error (parser);
+
+ g_printerr ("Error parsing: %s\n", json_error->message);
+ }
+ gtk_json_parser_free (parser);
+}
+
+static void
+load_some_releases (GListStore *store)
+{
+ GFile *file = g_file_new_for_uri ("https://gitlab.gnome.org/api/v4/projects/665/repository/tags");
+
+ g_file_load_bytes_async (file, NULL, loaded_some_releases_cb, store);
+ g_object_unref (file);
+}
+
+static GtkWidget *window = NULL;
+
+GtkWidget *
+do_listview_releases (GtkWidget *do_widget)
+{
+ if (window == NULL)
+ {
+ GtkBuilderScope *scope;
+ GtkBuilder *builder;
+ GListStore *list;
+
+ g_type_ensure (GTK_TYPE_RELEASE);
+
+ scope = gtk_builder_cscope_new ();
+ gtk_builder_cscope_add_callback_symbol (GTK_BUILDER_CSCOPE (scope), "load_some_releases",
(GCallback)load_some_releases);
+
+ builder = gtk_builder_new ();
+ gtk_builder_set_scope (builder, scope);
+ g_object_unref (scope);
+
+ gtk_builder_add_from_resource (builder, "/listview_releases/listview_releases.ui", NULL);
+
+ window = GTK_WIDGET (gtk_builder_get_object (builder, "window"));
+ gtk_window_set_display (GTK_WINDOW (window),
+ gtk_widget_get_display (do_widget));
+ g_object_add_weak_pointer (G_OBJECT (window), (gpointer *) &window);
+
+ list = G_LIST_STORE (gtk_builder_get_object (builder, "list"));
+ load_some_releases (list);
+ }
+
+ if (!gtk_widget_get_visible (window))
+ gtk_widget_show (window);
+ else
+ gtk_window_destroy (GTK_WINDOW (window));
+
+ return window;
+}
diff --git a/demos/gtk-demo/listview_releases.ui b/demos/gtk-demo/listview_releases.ui
new file mode 100644
index 0000000000..961a4486d9
--- /dev/null
+++ b/demos/gtk-demo/listview_releases.ui
@@ -0,0 +1,93 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <object class="GListStore" id="list">
+ <property name="item-type">GtkRelease</property>
+ </object>
+ <object class="GtkWindow" id="window">
+ <property name="title" translatable="yes">Releases</property>
+ <property name="default-width">640</property>
+ <property name="default-height">480</property>
+ <child type="titlebar">
+ <object class="GtkHeaderBar">
+ <child type="end">
+ <object class="GtkToggleButton" id="search_button">
+ <property name="icon-name">system-search-symbolic</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkScrolledWindow">
+ <property name="hexpand">1</property>
+ <property name="vexpand">1</property>
+ <child>
+ <object class="GtkColumnView" id="columnview">
+ <property name="model">
+ <object class="GtkSingleSelection">
+ <property name="model">list</property>
+ </object>
+ </property>
+ <style>
+ <class name="data-table"/>
+ </style>
+ <child>
+ <object class="GtkColumnViewColumn" id="name_column">
+ <property name="title">Name</property>
+ <property name="resizable">1</property>
+ <property name="factory">
+ <object class="GtkBuilderListItemFactory">
+ <property name="bytes"><![CDATA[
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <template class="GtkListItem">
+ <property name="child">
+ <object class="GtkLabel">
+ <property name="xalign">0</property>
+ <binding name="label">
+ <lookup name="name" type="GtkRelease">
+ <lookup name="item">GtkListItem</lookup>
+ </lookup>
+ </binding>
+ </object>
+ </property>
+ </template>
+</interface>
+ ]]></property>
+ </object>
+ </property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkColumnViewColumn">
+ <property name="title">Date</property>
+ <property name="resizable">1</property>
+ <property name="expand">1</property>
+ <property name="factory">
+ <object class="GtkBuilderListItemFactory">
+ <property name="bytes"><![CDATA[
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <template class="GtkListItem">
+ <property name="child">
+ <object class="GtkLabel">
+ <property name="xalign">0</property>
+ <binding name="label">
+ <lookup name="timestamp" type="GtkRelease">
+ <lookup name="item">GtkListItem</lookup>
+ </lookup>
+ </binding>
+ </object>
+ </property>
+ </template>
+</interface>
+ ]]></property>
+ </object>
+ </property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+</interface>
diff --git a/demos/gtk-demo/meson.build b/demos/gtk-demo/meson.build
index 3576399f04..4328643373 100644
--- a/demos/gtk-demo/meson.build
+++ b/demos/gtk-demo/meson.build
@@ -55,6 +55,7 @@ demos = files([
'listview_filebrowser.c',
'listview_minesweeper.c',
'dropdown.c',
+ 'listview_releases.c',
'listview_settings.c',
'listview_ucd.c',
'listview_weather.c',
@@ -100,7 +101,7 @@ demos = files([
'video_player.c',
])
-gtkdemo_deps = [ libgtk_dep, ]
+gtkdemo_deps = [ libgtk_dep, libgtk_json_dep ]
extra_demo_sources = files([
'main.c',
@@ -244,6 +245,7 @@ executable('gtk4-demo',
include_directories: confinc,
gui_app: true,
link_args: extra_demo_ldflags,
+ link_with: [ libgtk_json, ],
install: true,
)
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]