Compare commits

...

3 Commits

Author SHA1 Message Date
Matthias Clasen
0fb009235b Refine the colors demo
Make the repopulation triggered from the ui, show
the current model size in the header, and do the
incremental refilling a bit faster by not going
one-item-per-frame, but use 4ms of each frame to
add items.
2020-06-20 14:34:03 -04:00
Matthias Clasen
a0fc293d1e gtk-demo: Make the colors demo populate incrementally too 2020-06-20 12:37:13 -04:00
Matthias Clasen
00f0177d25 gtk-demo: Populate the weather demo incrementally
This tests how robust the listview machinery is to
frequent model changes.
2020-06-20 12:22:22 -04:00
2 changed files with 203 additions and 59 deletions

View File

@@ -242,30 +242,54 @@ gtk_color_new (const char *name,
return result;
}
static GListModel *
create_colors_model (void)
typedef struct
{
GListStore *result;
GtkColor *color;
GtkWidget *widget;
GBytes *data;
GListStore *store;
char **lines;
guint n;
guint i;
} ColorData;
result = g_list_store_new (GTK_TYPE_COLOR);
data = g_resources_lookup_data ("/listview_colors/color.names.txt", 0, NULL);
lines = g_strsplit (g_bytes_get_data (data, NULL), "\n", 0);
static void
free_color_data (gpointer data)
{
ColorData *cd = data;
for (i = 0; lines[i]; i++)
if (cd->widget)
gtk_widget_set_sensitive (cd->widget, TRUE);
g_bytes_unref (cd->data);
g_object_unref (cd->store);
g_strfreev (cd->lines);
g_free (cd);
}
static gboolean
add_color (GtkWidget *widget,
GdkFrameClock *clock,
gpointer data)
{
ColorData *cd = data;
const char *name;
char **fields;
int red, green, blue;
int h, s, v;
GtkColor *color;
guint64 start, now;
start = g_get_monotonic_time ();
while (cd->i < cd->n)
{
const char *name;
char **fields;
int red, green, blue;
int h, s, v;
const char *line = cd->lines[cd->i];
if (lines[i][0] == '#' || lines[i][0] == '\0')
cd->i++;
if (line[0] == '#' || line[0] == '\0')
continue;
fields = g_strsplit (lines[i], " ", 0);
fields = g_strsplit (line, " ", 0);
name = fields[1];
red = atoi (fields[3]);
green = atoi (fields[4]);
@@ -275,16 +299,67 @@ create_colors_model (void)
v = atoi (fields[11]);
color = gtk_color_new (name, red / 255., green / 255., blue / 255., h, s, v);
g_list_store_append (result, color);
g_list_store_append (cd->store, color);
g_object_unref (color);
g_strfreev (fields);
now = g_get_monotonic_time ();
if (now > start + 4000)
return G_SOURCE_CONTINUE;
}
g_strfreev (lines);
g_bytes_unref (data);
return G_SOURCE_REMOVE;
}
return G_LIST_MODEL (result);
static void
populate_colors_model (GtkWidget *widget,
GListStore *store)
{
ColorData *cd;
cd = g_new (ColorData, 1);
gtk_widget_set_sensitive (widget, FALSE);
cd->widget = widget;
cd->store = g_object_ref (store);
cd->data = g_resources_lookup_data ("/listview_colors/color.names.txt", 0, NULL);
cd->lines = g_strsplit (g_bytes_get_data (cd->data, NULL), "\n", 0);
cd->n = g_strv_length (cd->lines);
cd->i = 0;
gtk_widget_add_tick_callback (widget, add_color, cd, free_color_data);
}
static void
fill (GtkWidget *view,
GListStore *store)
{
ColorData *cd;
gboolean res;
cd = g_new (ColorData, 1);
cd->widget = NULL;
cd->store = g_object_ref (store);
cd->data = g_resources_lookup_data ("/listview_colors/color.names.txt", 0, NULL);
cd->lines = g_strsplit (g_bytes_get_data (cd->data, NULL), "\n", 0);
cd->n = g_strv_length (cd->lines);
cd->i = 0;
do {
res = add_color (view, NULL, cd);
} while (res == G_SOURCE_CONTINUE);
free_color_data (cd);
}
static void
refill (GtkWidget *button,
GListStore *store)
{
g_list_store_remove_all (store);
populate_colors_model (button, store);
}
static char *
@@ -425,6 +500,7 @@ create_color_grid (void)
GtkWidget *gridview;
GtkListItemFactory *factory;
GListModel *model, *selection;
GListStore *store;
gridview = gtk_grid_view_new ();
gtk_scrollable_set_hscroll_policy (GTK_SCROLLABLE (gridview), GTK_SCROLL_NATURAL);
@@ -438,15 +514,34 @@ create_color_grid (void)
gtk_grid_view_set_max_columns (GTK_GRID_VIEW (gridview), 24);
gtk_grid_view_set_enable_rubberband (GTK_GRID_VIEW (gridview), TRUE);
model = G_LIST_MODEL (gtk_sort_list_model_new (create_colors_model (), NULL));
store = g_list_store_new (GTK_TYPE_COLOR);
fill (gridview, store);
model = G_LIST_MODEL (gtk_sort_list_model_new (G_LIST_MODEL (store), NULL));
selection = G_LIST_MODEL (gtk_property_selection_new (model, "selected"));
gtk_grid_view_set_model (GTK_GRID_VIEW (gridview), selection);
g_object_unref (selection);
g_object_unref (model);
g_object_unref (store);
return gridview;
}
static void
items_changed_cb (GListModel *model,
guint position,
guint removed,
guint added,
GtkWidget *label)
{
guint n = g_list_model_get_n_items (model);
char *text;
text = g_strdup_printf ("%u items", n);
gtk_label_set_label (GTK_LABEL (label), text);
g_free (text);
}
static GtkWidget *window = NULL;
GtkWidget *
@@ -458,11 +553,12 @@ do_listview_colors (GtkWidget *do_widget)
GtkListItemFactory *factory;
GListStore *factories;
GListModel *model;
GtkSorter *sorter;
GtkSorter *multi_sorter;
GListStore *sorters;
GtkExpression *expression;
GtkWidget *button;
GtkWidget *label;
window = gtk_window_new ();
gtk_window_set_title (GTK_WINDOW (window), "Colors");
@@ -483,6 +579,18 @@ do_listview_colors (GtkWidget *do_widget)
model = gtk_grid_view_get_model (GTK_GRID_VIEW (gridview));
g_object_get (model, "model", &model, NULL);
button = gtk_button_new_with_mnemonic ("_Refill");
g_signal_connect (button, "clicked",
G_CALLBACK (refill),
gtk_sort_list_model_get_model (GTK_SORT_LIST_MODEL (model)));
gtk_header_bar_pack_start (GTK_HEADER_BAR (header), button);
label = gtk_label_new ("0 items");
g_signal_connect (gtk_grid_view_get_model (GTK_GRID_VIEW (gridview)),
"items-changed", G_CALLBACK (items_changed_cb), label);
gtk_header_bar_pack_start (GTK_HEADER_BAR (header), label);
sorters = g_list_store_new (GTK_TYPE_SORTER);
sorter = gtk_string_sorter_new (gtk_property_expression_new (GTK_TYPE_COLOR, NULL, "name"));

View File

@@ -70,7 +70,6 @@ gtk_weather_info_new (GDateTime *timestamp,
{
result->temperature = copy_from->temperature;
result->weather_type = copy_from->weather_type;
g_object_unref (copy_from);
}
return result;
@@ -142,53 +141,88 @@ parse_temperature (const char *s,
return d;
}
static GListModel *
create_weather_model (void)
typedef struct
{
GListStore *store;
GTimeZone *utc;
GDateTime *timestamp;
GtkWeatherInfo *info;
GTimeZone *utc;
GBytes *data;
char **lines;
guint n;
guint i;
GtkWeatherInfo *info;
} WeatherData;
store = g_list_store_new (GTK_TYPE_WEATHER_INFO);
data = g_resources_lookup_data ("/listview_weather/listview_weather.txt", 0, NULL);
lines = g_strsplit (g_bytes_get_data (data, NULL), "\n", 0);
static void
free_weather_data (gpointer data)
{
WeatherData *wd = data;
utc = g_time_zone_new_utc ();
timestamp = g_date_time_new (utc, 2011, 1, 1, 0, 0, 0);
info = gtk_weather_info_new (timestamp, NULL);
g_list_store_append (store, info);
g_object_unref (wd->store);
g_date_time_unref (wd->timestamp);
g_time_zone_unref (wd->utc);
g_bytes_unref (wd->data);
g_strfreev (wd->lines);
for (i = 0; lines[i] != NULL && *lines[i]; i++)
g_free (wd);
}
static gboolean
add_one_item (GtkWidget *widget,
GdkFrameClock *frame_clock,
gpointer user_data)
{
WeatherData *wd = user_data;
char **fields;
GDateTime *date;
g_print ("%d/%d\n", wd->i, wd->n);
fields = g_strsplit (wd->lines[wd->i], ",", 0);
date = parse_timestamp (fields[0], wd->utc);
while (g_date_time_difference (date, wd->timestamp) > 30 * G_TIME_SPAN_MINUTE)
{
char **fields;
GDateTime *date;
fields = g_strsplit (lines[i], ",", 0);
date = parse_timestamp (fields[0], utc);
while (g_date_time_difference (date, timestamp) > 30 * G_TIME_SPAN_MINUTE)
{
GDateTime *new_timestamp = g_date_time_add_hours (timestamp, 1);
g_date_time_unref (timestamp);
timestamp = new_timestamp;
info = gtk_weather_info_new (timestamp, info);
g_list_store_append (store, info);
}
info->temperature = parse_temperature (fields[1], info->temperature);
info->weather_type = parse_weather_type (fields[2], fields[3], info->weather_type);
g_date_time_unref (date);
g_strfreev (fields);
GDateTime *new_timestamp = g_date_time_add_hours (wd->timestamp, 1);
g_date_time_unref (wd->timestamp);
wd->timestamp = new_timestamp;
wd->info = gtk_weather_info_new (wd->timestamp, wd->info);
g_list_store_append (wd->store, wd->info);
g_object_unref (wd->info);
}
g_strfreev (lines);
g_bytes_unref (data);
g_time_zone_unref (utc);
wd->info->temperature = parse_temperature (fields[1], wd->info->temperature);
wd->info->weather_type = parse_weather_type (fields[2], fields[3], wd->info->weather_type);
return G_LIST_MODEL (store);
g_date_time_unref (date);
g_strfreev (fields);
wd->i++;
if (wd->i == wd->n)
return G_SOURCE_REMOVE;
return G_SOURCE_CONTINUE;
}
static void
populate_weather_model (GtkWidget *view, GListStore *store)
{
WeatherData *wd;
wd = g_new (WeatherData, 1);
wd->data = g_resources_lookup_data ("/listview_weather/listview_weather.txt", 0, NULL);
wd->lines = g_strsplit (g_bytes_get_data (wd->data, NULL), "\n", 0);
wd->n = g_strv_length (wd->lines);
wd->i = 0;
wd->store = g_object_ref (store);
wd->utc = g_time_zone_new_utc ();
wd->timestamp = g_date_time_new (wd->utc, 2011, 1, 1, 0, 0, 0);
wd->info = gtk_weather_info_new (wd->timestamp, NULL);
g_list_store_append (wd->store, wd->info);
g_object_unref (wd->info);
gtk_widget_add_tick_callback (view, add_one_item, wd, free_weather_data);
}
static void
@@ -279,7 +313,8 @@ GtkWidget *
create_weather_view (void)
{
GtkWidget *listview;
GListModel *model, *selection;
GListStore *store;
GListModel *selection;
listview = gtk_list_view_new_with_factory (
gtk_functions_list_item_factory_new (setup_widget,
@@ -287,11 +322,12 @@ create_weather_view (void)
NULL, NULL));
gtk_orientable_set_orientation (GTK_ORIENTABLE (listview), GTK_ORIENTATION_HORIZONTAL);
gtk_list_view_set_show_separators (GTK_LIST_VIEW (listview), TRUE);
model = create_weather_model ();
selection = G_LIST_MODEL (gtk_no_selection_new (model));
store = g_list_store_new (GTK_TYPE_WEATHER_INFO);
selection = G_LIST_MODEL (gtk_no_selection_new (G_LIST_MODEL (store)));
gtk_list_view_set_model (GTK_LIST_VIEW (listview), selection);
populate_weather_model (listview, store);
g_object_unref (selection);
g_object_unref (model);
g_object_unref (store);
return listview;
}