From 258d8d016f4b1dca38cf2d03b7faa0cb09f5496f Mon Sep 17 00:00:00 2001 From: Vivien Kraus Date: Sun, 12 Mar 2023 12:20:30 +0100 Subject: Add a widget to display a cache entry. --- src/adwaita/disfluid-cache-entry.c | 249 +++++++++++++++++++++++++++++++++++++ 1 file changed, 249 insertions(+) create mode 100644 src/adwaita/disfluid-cache-entry.c (limited to 'src/adwaita/disfluid-cache-entry.c') diff --git a/src/adwaita/disfluid-cache-entry.c b/src/adwaita/disfluid-cache-entry.c new file mode 100644 index 0000000..e0245c4 --- /dev/null +++ b/src/adwaita/disfluid-cache-entry.c @@ -0,0 +1,249 @@ +#include + +#include "attribute.h" +#include + +#define STREQ(a, b) (strcmp ((a), (b)) == 0) +#define STRNEQ(a, b) (! (STREQ (a, b))) + +#include +#include +#include +#include +#include "gettext.h" +#include "relocatable.h" + +#define _(String) dgettext (PACKAGE, (String)) +#define N_(String) (String) + +#include +#include +#include +#include + +struct _DisfluidAdwCacheEntry +{ + AdwPreferencesGroup parent_instance; + struct disfluid_cache_entry *cache_entry; + GtkLabel *row_request_date; + GtkLabel *row_response_date; + GtkLabel *row_invalidation_status; +}; + +struct _DisfluidAdwCacheEntryClass +{ + AdwPreferencesGroupClass parent_instance; +}; + +/* *INDENT-OFF* */ +G_DEFINE_TYPE (DisfluidAdwCacheEntry, + disfluid_adw_cache_entry, + ADW_TYPE_PREFERENCES_GROUP) +/* *INDENT-ON* */ + +typedef enum +{ + PROP_CACHE_ENTRY = 1, + + /* ... */ + N_PROPERTIES +} DisfluidAdwCacheEntryProperty; + +static GParamSpec *obj_properties[N_PROPERTIES] = { NULL, }; + +static void +disfluid_adw_cache_entry_set_property (GObject * object, + guint property_id, + const GValue * value, + GParamSpec * pspec) +{ + DisfluidAdwCacheEntry *self = DISFLUID_ADW_CACHE_ENTRY (object); + switch ((DisfluidAdwCacheEntryProperty) property_id) + { + case PROP_CACHE_ENTRY: + assert (G_VALUE_TYPE (value) == DISFLUID_TYPE_CACHE_ENTRY); + disfluid_adw_cache_entry_set_cache_entry (self, + g_value_get_boxed (value)); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static void +disfluid_adw_cache_entry_get_property (GObject * object, + guint property_id, + GValue * value, GParamSpec * pspec) +{ + DisfluidAdwCacheEntry *self = DISFLUID_ADW_CACHE_ENTRY (object); + switch ((DisfluidAdwCacheEntryProperty) property_id) + { + case PROP_CACHE_ENTRY: + if (self->cache_entry != NULL) + { + g_value_set_boxed (value, + disfluid_cache_entry_dup (self->cache_entry)); + } + else + { + g_value_set_boxed (value, NULL); + } + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static void +disfluid_adw_cache_entry_finalize (GObject * obj) +{ + DisfluidAdwCacheEntry *self = DISFLUID_ADW_CACHE_ENTRY (obj); + disfluid_cache_entry_free (self->cache_entry); + G_OBJECT_CLASS (disfluid_adw_cache_entry_parent_class)->finalize (obj); +} + +static void +disfluid_adw_cache_entry_class_init (DisfluidAdwCacheEntryClass * klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + object_class->set_property = disfluid_adw_cache_entry_set_property; + object_class->get_property = disfluid_adw_cache_entry_get_property; + object_class->finalize = disfluid_adw_cache_entry_finalize; + obj_properties[PROP_CACHE_ENTRY] = + g_param_spec_boxed ("cache-entry", + _("Cache entry"), _("Value of the cache entry \ +that is to be displayed by this widget"), DISFLUID_TYPE_CACHE_ENTRY, G_PARAM_READWRITE); + g_object_class_install_properties (object_class, N_PROPERTIES, + obj_properties); +} + +static void +disfluid_adw_cache_entry_init (DisfluidAdwCacheEntry * self) +{ + /* Perform default initialization of self. */ + self->cache_entry = NULL; + self->row_request_date = GTK_LABEL (gtk_label_new (_("Unset"))); + self->row_response_date = GTK_LABEL (gtk_label_new (_("Unset"))); + self->row_invalidation_status = GTK_LABEL (gtk_label_new (_("Unset"))); + GtkLabel *my_labels[3] = { self->row_request_date, self->row_response_date, + self->row_invalidation_status + }; + for (size_t i = 0; i < sizeof (my_labels) / sizeof (my_labels[0]); i++) + { + gtk_label_set_wrap (my_labels[i], true); + const int margin = 8; + gtk_widget_set_margin_top (GTK_WIDGET (my_labels[i]), margin); + gtk_widget_set_margin_bottom (GTK_WIDGET (my_labels[i]), margin); + gtk_widget_set_margin_start (GTK_WIDGET (my_labels[i]), margin); + gtk_widget_set_margin_end (GTK_WIDGET (my_labels[i]), margin); + } + GtkListBoxRow *row_request_date = + GTK_LIST_BOX_ROW (g_object_new (ADW_TYPE_PREFERENCES_ROW, + "title", _("Request date"), + "child", self->row_request_date, + "selectable", false, + NULL)); + GtkListBoxRow *row_response_date = + GTK_LIST_BOX_ROW (g_object_new (ADW_TYPE_PREFERENCES_ROW, + "title", _("Response date"), + "child", self->row_response_date, + "selectable", false, + NULL)); + GtkListBoxRow *row_invalidation_status = + GTK_LIST_BOX_ROW (g_object_new (ADW_TYPE_PREFERENCES_ROW, + "title", _("Invalidation status"), + "child", self->row_invalidation_status, + "selectable", false, + NULL)); + adw_preferences_group_set_title (ADW_PREFERENCES_GROUP (self), + _("Unknown cache entry")); + adw_preferences_group_set_description (ADW_PREFERENCES_GROUP (self), + _("Unknown URI")); + adw_preferences_group_add (ADW_PREFERENCES_GROUP (self), + GTK_WIDGET (row_request_date)); + adw_preferences_group_add (ADW_PREFERENCES_GROUP (self), + GTK_WIDGET (row_response_date)); + adw_preferences_group_add (ADW_PREFERENCES_GROUP (self), + GTK_WIDGET (row_invalidation_status)); +} + +void +disfluid_adw_cache_entry_set_cache_entry (DisfluidAdwCacheEntry * self, + struct disfluid_cache_entry *value) +{ + disfluid_cache_entry_free (self->cache_entry); + if (value != NULL) + { + self->cache_entry = disfluid_cache_entry_dup (value); + struct timespec request_ts, response_ts; + disfluid_cache_entry_get_request_date (self->cache_entry, &request_ts); + disfluid_cache_entry_get_response_date (self->cache_entry, + &response_ts); + GDateTime *request_date_gross = + g_date_time_new_from_unix_local (request_ts.tv_sec); + const double request_frac = request_ts.tv_nsec * 1e-9; + GDateTime *request_date = g_date_time_add_seconds (request_date_gross, + request_frac); + g_date_time_unref (request_date_gross); + GDateTime *response_date_gross = + g_date_time_new_from_unix_local (response_ts.tv_sec); + const double response_frac = response_ts.tv_nsec * 1e-9; + GDateTime *response_date = g_date_time_add_seconds (response_date_gross, + response_frac); + g_date_time_unref (response_date_gross); + gchar *request_format = g_date_time_format (request_date, "%c"); + gchar *response_format = g_date_time_format (response_date, "%c"); + g_date_time_unref (request_date); + g_date_time_unref (response_date); + char *request_title; + char *response_title; + char *invalidation_status_title; + /* TRANSLATORS: The argument is a date and time. */ + if (asprintf (&request_title, _("Requested %s"), request_format) < 0) + { + abort (); + } + /* TRANSLATORS: The argument is a date and time. */ + if (asprintf (&response_title, _("Responded %s"), response_format) < 0) + { + abort (); + } + if (disfluid_cache_entry_invalidated (self->cache_entry)) + { + if (asprintf + (&invalidation_status_title, + _("This response has been invalidated.")) < 0) + { + abort (); + } + } + else + { + if (asprintf + (&invalidation_status_title, + _("This response is still valid.")) < 0) + { + abort (); + } + } + g_free (request_format); + g_free (response_format); + gtk_label_set_label (self->row_request_date, request_title); + gtk_label_set_label (self->row_response_date, response_title); + gtk_label_set_label (self->row_invalidation_status, + invalidation_status_title); + g_free (request_title); + g_free (response_title); + g_free (invalidation_status_title); + } + else + { + self->cache_entry = NULL; + gtk_label_set_label (self->row_request_date, _("No content")); + gtk_label_set_label (self->row_response_date, _("No content")); + gtk_label_set_label (self->row_invalidation_status, _("No content")); + } +} -- cgit v1.2.3