summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVivien Kraus <vivien@planete-kraus.eu>2023-03-12 12:20:30 +0100
committerVivien Kraus <vivien@planete-kraus.eu>2023-03-12 19:11:24 +0100
commit258d8d016f4b1dca38cf2d03b7faa0cb09f5496f (patch)
tree309df7810985170136b4b8d465ea8ebf3c6a1c4a
parentcf0a29d1d72d104d99386293ac4763619f8e0fc2 (diff)
Add a widget to display a cache entry.
-rw-r--r--include/disfluid.h4
-rw-r--r--po/POTFILES.in2
-rw-r--r--src/adwaita/Makefile.am1
-rw-r--r--src/adwaita/disfluid-adwaita.h15
-rw-r--r--src/adwaita/disfluid-cache-entry.c249
-rw-r--r--src/adwaita/disfluid-g-cache-entry.c9
-rw-r--r--src/adwaita/disfluid-window.c19
-rw-r--r--src/libdisfluid/disfluid-cache-entry.h14
8 files changed, 293 insertions, 20 deletions
diff --git a/include/disfluid.h b/include/disfluid.h
index 3eff069..c4ddcc8 100644
--- a/include/disfluid.h
+++ b/include/disfluid.h
@@ -143,8 +143,8 @@ extern "C"
*disfluid_cache_entry_from_fd (int fd);
LIBDISFLUID_API LIBDISFLUID_DEALLOC_AS_CACHE_ENTRY
- extern struct disfluid_cache_entry *
- disfluid_cache_entry_dup (const struct disfluid_cache_entry *entry);
+ extern struct disfluid_cache_entry
+ *disfluid_cache_entry_dup (const struct disfluid_cache_entry *entry);
LIBDISFLUID_API extern void
disfluid_cache_entry_set_request_date (struct disfluid_cache_entry *entry,
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 371f070..4397e1f 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -1,8 +1,8 @@
desktop/eu.planete_kraus.Disfluid.Devel.desktop.in
desktop/eu.planete_kraus.Disfluid.desktop.in
src/adwaita/disfluid-about.c
+src/adwaita/disfluid-cache-entry.c
src/adwaita/disfluid-menus.c
-src/adwaita/disfluid-window.c
src/libdisfluid/disfluid-authors.h
src/libdisfluid/disfluid-tests.h
src/libdisfluid/disfluid-version.h
diff --git a/src/adwaita/Makefile.am b/src/adwaita/Makefile.am
index c496d47..41f0bb0 100644
--- a/src/adwaita/Makefile.am
+++ b/src/adwaita/Makefile.am
@@ -5,6 +5,7 @@ noinst_LTLIBRARIES += %D%/libdisfluid-adwaita.la
%D%/disfluid-about.c \
%D%/disfluid-application.c \
%D%/disfluid-g-cache-entry.c \
+ %D%/disfluid-cache-entry.c \
%D%/disfluid-menus.c \
%D%/disfluid-window.c
diff --git a/src/adwaita/disfluid-adwaita.h b/src/adwaita/disfluid-adwaita.h
index b5f6e83..e589c75 100644
--- a/src/adwaita/disfluid-adwaita.h
+++ b/src/adwaita/disfluid-adwaita.h
@@ -5,12 +5,13 @@
# include <glib-object.h>
# include <gtk/gtk.h>
# include <adwaita.h>
+# include <disfluid.h>
/* *INDENT-OFF* */
G_BEGIN_DECLS
/* *INDENT-ON* */
-#define DISFLUID_TYPE_CACHE_ENTRY \
+# define DISFLUID_TYPE_CACHE_ENTRY \
disfluid_cache_entry_get_type ()
# define DISFLUID_ADW_TYPE_APPLICATION \
@@ -19,6 +20,9 @@ G_BEGIN_DECLS
# define DISFLUID_ADW_TYPE_WINDOW \
disfluid_adw_window_get_type ()
+# define DISFLUID_ADW_TYPE_CACHE_ENTRY \
+ disfluid_adw_cache_entry_get_type ()
+
/* *INDENT-OFF* */
G_DECLARE_FINAL_TYPE (DisfluidAdwApplication,
disfluid_adw_application,
@@ -28,6 +32,10 @@ G_DECLARE_FINAL_TYPE (DisfluidAdwWindow,
disfluid_adw_window,
DISFLUID_ADW, WINDOW,
AdwApplicationWindow)
+G_DECLARE_FINAL_TYPE (DisfluidAdwCacheEntry,
+ disfluid_adw_cache_entry,
+ DISFLUID_ADW, CACHE_ENTRY,
+ AdwPreferencesGroup)
G_END_DECLS
/* *INDENT-ON* */
@@ -45,4 +53,9 @@ GMenuItem *disfluid_adw_menu_item_about (void);
GMenu *disfluid_adw_main_menu (void);
+void disfluid_adw_cache_entry_set_cache_entry (DisfluidAdwCacheEntry *
+ cache_entry,
+ struct disfluid_cache_entry
+ *value);
+
#endif /* not H_DISFLUID_ADWAITA_INCLUDED */
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 <config.h>
+
+#include "attribute.h"
+#include <disfluid-adwaita.h>
+
+#define STREQ(a, b) (strcmp ((a), (b)) == 0)
+#define STRNEQ(a, b) (! (STREQ (a, b)))
+
+#include <locale.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <assert.h>
+#include "gettext.h"
+#include "relocatable.h"
+
+#define _(String) dgettext (PACKAGE, (String))
+#define N_(String) (String)
+
+#include <disfluid.h>
+#include <glib-object.h>
+#include <adwaita.h>
+#include <gtk/gtk.h>
+
+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"));
+ }
+}
diff --git a/src/adwaita/disfluid-g-cache-entry.c b/src/adwaita/disfluid-g-cache-entry.c
index d7820cc..8fe7141 100644
--- a/src/adwaita/disfluid-g-cache-entry.c
+++ b/src/adwaita/disfluid-g-cache-entry.c
@@ -18,7 +18,8 @@
#include <glib-object.h>
-G_DEFINE_BOXED_TYPE (disfluid_cache_entry,
- disfluid_cache_entry,
- disfluid_cache_entry_dup,
- disfluid_cache_entry_free)
+typedef struct disfluid_cache_entry DisfluidCacheEntry;
+
+G_DEFINE_BOXED_TYPE (DisfluidCacheEntry,
+ disfluid_cache_entry,
+ disfluid_cache_entry_dup, disfluid_cache_entry_free)
diff --git a/src/adwaita/disfluid-window.c b/src/adwaita/disfluid-window.c
index c3d1053..d1943f5 100644
--- a/src/adwaita/disfluid-window.c
+++ b/src/adwaita/disfluid-window.c
@@ -53,11 +53,20 @@ disfluid_adw_window_init (DisfluidAdwWindow * self)
G_MENU_MODEL (main_menu));
g_object_unref (main_menu);
adw_header_bar_pack_end (ADW_HEADER_BAR (header_bar), menu_button);
- GtkWidget *main_page = adw_status_page_new ();
- adw_status_page_set_icon_name (ADW_STATUS_PAGE (main_page), "face-smile");
- adw_status_page_set_title (ADW_STATUS_PAGE (main_page), _("Hello, world!"));
- adw_status_page_set_description (ADW_STATUS_PAGE (main_page), _("\
-There is nothing here yet, please come back later."));
+ struct disfluid_cache_entry *cache_entry = disfluid_cache_entry_alloc ();
+ if (cache_entry == NULL)
+ {
+ abort ();
+ }
+ GtkWidget *unique_content =
+ g_object_new (DISFLUID_ADW_TYPE_CACHE_ENTRY, NULL);
+ disfluid_adw_cache_entry_set_cache_entry (DISFLUID_ADW_CACHE_ENTRY
+ (unique_content), cache_entry);
+ disfluid_cache_entry_free (cache_entry);
+ GtkWidget *main_page = g_object_new (ADW_TYPE_PREFERENCES_PAGE,
+ NULL);
+ adw_preferences_page_add (ADW_PREFERENCES_PAGE (main_page),
+ ADW_PREFERENCES_GROUP (unique_content));
GtkWidget *content = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
gtk_box_append (GTK_BOX (content), header_bar);
gtk_box_append (GTK_BOX (content), main_page);
diff --git a/src/libdisfluid/disfluid-cache-entry.h b/src/libdisfluid/disfluid-cache-entry.h
index 2371515..3f9123c 100644
--- a/src/libdisfluid/disfluid-cache-entry.h
+++ b/src/libdisfluid/disfluid-cache-entry.h
@@ -11,8 +11,8 @@ MAYBE_UNUSED static struct disfluid_cache_entry
MAYBE_UNUSED static struct disfluid_cache_entry *cache_entry_from_fd (int fd);
-MAYBE_UNUSED static struct disfluid_cache_entry *
-cache_entry_dup (const struct disfluid_cache_entry *entry);
+MAYBE_UNUSED static struct disfluid_cache_entry
+ *cache_entry_dup (const struct disfluid_cache_entry *entry);
MAYBE_UNUSED static int
cache_entry_save_other_file_name (const struct disfluid_cache_entry *entry,
@@ -115,14 +115,14 @@ static struct disfluid_cache_entry *
cache_entry_dup (const struct disfluid_cache_entry *entry)
{
struct disfluid_cache_entry *ret = cache_entry_alloc ();
- if (ret != NULL)
+ if (ret != NULL && entry->fd >= 0)
{
ret->fd = dup (entry->fd);
if (ret->fd < 0)
- {
- cache_entry_free (ret);
- ret = NULL;
- }
+ {
+ cache_entry_free (ret);
+ ret = NULL;
+ }
}
if (ret != NULL)
{