summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorVivien Kraus <vivien@planete-kraus.eu>2023-03-26 14:31:52 +0200
committerVivien Kraus <vivien@planete-kraus.eu>2023-04-02 23:53:56 +0200
commitc1ef27c64cab1b48308cb56515027bf09a8ad11f (patch)
tree7adea1997a8a0872a1649477b70d4cf3da8c8e85 /src
parentac95860f1f8817e3a589682db6d98ff77f36d995 (diff)
Start a vala user interface
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am21
-rw-r--r--src/gir/Makefile.am30
-rw-r--r--src/libdisfluid/Makefile.am1
-rw-r--r--src/libdisfluid/disfluid-authors.h66
-rw-r--r--src/libdisfluid/disfluid-cache-entry.h65
-rw-r--r--src/libdisfluid/disfluid-ui.h23
-rw-r--r--src/libdisfluid/main.c54
-rw-r--r--src/vala/Makefile.am37
-rw-r--r--src/vala/about.vala51
-rw-r--r--src/vala/main.vala26
-rw-r--r--src/vala/main_window.vala55
11 files changed, 404 insertions, 25 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index 5bd97d6..7925ce8 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -5,25 +5,12 @@ RELOCATABLE_LIBRARY_PATH = $(libdir)
include %D%/libdisfluid/Makefile.am
include %D%/gobject/Makefile.am
+include %D%/gir/Makefile.am
include %D%/vala/Makefile.am
DISTCLEANFILES += $(defexec_DATA)
-EXTRA_DIST += %D%/introspection-files %D%/introspection-libraries
+.PHONY: update-introspected-libs
-if BUILD_GOBJECT
-
-%D%/introspection-files: $(INTROSPECTION_LISTS) $(INTROSPECTION_SRC)
- $(AM_V_GEN) (for src in $(INTROSPECTED_FILES) ; do echo "$$src" ; done) > %D%/introspection-files-t && mv %D%/introspection-files-t $(srcdir)/%D%/introspection-files
-
-%D%/introspection-libraries: $(INTROSPECTION_LISTS) $(INTROSPECTION_SRC)
- $(AM_V_GEN) (for lib in $(INTROSPECTED_LIBS) ; do echo "$$lib" ; done) > %D%/introspection-libraries-t && mv %D%/introspection-libraries-t %D%/introspection-libraries
-
-else # not BUILD_GOBJECT
-
-%D%/introspection-files: $(INTROSPECTION_LISTS) $(INTROSPECTION_SRC)
- @(>&2 echo "The introspected files have changed, but gobject compilation is disabled." ; exit 1)
-%D%/introspection-libraries: $(INTROSPECTION_LISTS) $(INTROSPECTION_SRC)
- @(>&2 echo "The introspected files have changed, but gobject compilation is disabled." ; exit 1)
-
-endif # not BUILD_GOBJECT
+update-introspected-libs: $(INTROSPECTED_LIBS)
+ @true
diff --git a/src/gir/Makefile.am b/src/gir/Makefile.am
new file mode 100644
index 0000000..860b2f0
--- /dev/null
+++ b/src/gir/Makefile.am
@@ -0,0 +1,30 @@
+girdir = $(datarootdir)/gir-1.0
+
+dist_gir_DATA = $(srcdir)/%D%/Disfluid-$(DLL_VERSION).gir
+
+AM_G_IR_SCANNER_FLAGS = \
+ --format=gir -i GLib-2.0 -I$(abs_top_srcdir)/include
+
+if BUILD_GOBJECT
+
+# The rule to build the .gir file recursively make the libraries. If
+# you run "make -j all", and the libraries are not up to date, then
+# there is a race to build the libraries by this call, and by the
+# recursive calls due to the gir rules.
+
+# The introspection/Makefile.am is executed early and tries to make
+# sure that the recursive call is a no-op. However, if you bypass the
+# subdir order by executing "make -j src/gir/Disfluid-….gir", with the
+# dll version as …, then the race is still there. Automated build
+# scripts usually don’t do this, so it’s fine.
+
+%D%/Disfluid-$(DLL_VERSION).gir: $(INTROSPECTION_LISTS) $(INTROSPECTION_SRC)
+ $(MAKE) $(AM_MAKEFLAGS) $(INTROSPECTED_LIBS)
+ $(AM_V_GEN) $(G_IR_SCANNER) $(AM_G_IR_SCANNER_FLAGS) $(G_IR_SCANNER_FLAGS) --c-include=disfluid.h --c-include=disfluid/cache_entry.h --c-include=disfluid-gobject.h -n Disfluid --nsversion=$(DLL_VERSION) --symbol-prefix=disfluid_ --output=%D%/Disfluid-$(DLL_VERSION).gir-t $$(for lib in $(INTROSPECTED_LIBS) ; do echo "--library=$$lib" ; done) --cflags-begin $(GOBJECT_CFLAGS) --cflags-end $(INTROSPECTED_FILES) && $(SED) 's/shared-library="[^"]*"/shared-library=""/g' %D%/Disfluid-$(DLL_VERSION).gir-t > %D%/Disfluid-$(DLL_VERSION).gir-fixed && rm %D%/Disfluid-$(DLL_VERSION).gir-t && mv %D%/Disfluid-$(DLL_VERSION).gir-fixed $(srcdir)/%D%/Disfluid-$(DLL_VERSION).gir
+
+else # not BUILD_GOBJECT
+
+%D%/Disfluid-$(DLL_VERSION).gir: $(INTROSPECTION_LISTS) $(INTROSPECTION_SRC)
+ @>&2 echo "The introspection sources changed, so the gir file must be updated. Please configure with gobject." ; exit 1
+
+endif # not BUILD_GOBJECT
diff --git a/src/libdisfluid/Makefile.am b/src/libdisfluid/Makefile.am
index 431fa2d..01a5945 100644
--- a/src/libdisfluid/Makefile.am
+++ b/src/libdisfluid/Makefile.am
@@ -7,6 +7,7 @@ lib_LTLIBRARIES += %D%/libdisfluid.la
%D%/disfluid-cache-entry-hash.h \
%D%/disfluid-init.h \
%D%/disfluid-tests.h \
+ %D%/disfluid-ui.h \
%D%/disfluid-version.h \
%D%/main.c
diff --git a/src/libdisfluid/disfluid-authors.h b/src/libdisfluid/disfluid-authors.h
index 149a556..6ccb8fe 100644
--- a/src/libdisfluid/disfluid-authors.h
+++ b/src/libdisfluid/disfluid-authors.h
@@ -1,6 +1,8 @@
#ifndef DISFLUID_AUTHORS_INCLUDED
# define DISFLUID_AUTHORS_INCLUDED
+# include "safe-alloc.h"
+
static inline size_t count_authors (void);
static inline const char *author_name (size_t i);
@@ -17,6 +19,8 @@ static inline bool author_is_documenter (size_t i);
static inline const char *translation_credits (void);
+static inline char *copyright_statement (void);
+
# include "disfluid-init.h"
struct disfluid_author
@@ -32,7 +36,7 @@ struct disfluid_author
static struct disfluid_author disfluid_authors[] = {
{
- .name = "Vivien Kraus",
+ .name = N_("Vivien Kraus"),
.email = "vivien@planete-kraus.eu",
.uri = NULL,
.is_developer = true,
@@ -59,7 +63,7 @@ author_name (size_t i)
{
if (i < sizeof (disfluid_authors) / sizeof (disfluid_authors[0]))
{
- return disfluid_authors[i].name;
+ return _(disfluid_authors[i].name);
}
return NULL;
}
@@ -131,4 +135,62 @@ translation_credits (void)
return _("translator-credits");
}
+static inline char *
+copyright_statement (void)
+{
+ ensure_init ();
+ int error = 0;
+ char *ret = NULL;
+ char *purpose;
+ error = asprintf (&purpose, _("disfluid interoperable web stack"));
+ if (error < 0)
+ {
+ goto cleanup;
+ }
+ char *copyright_line;
+ error =
+ asprintf (&copyright_line,
+ _("Copyright © %s the respective authors"), "2023");
+ if (error < 0)
+ {
+ goto cleanup_purpose;
+ }
+ char *disclaimer;
+ error = asprintf (&disclaimer,
+ _("This program is free software: "
+ "you can redistribute it and/or modify it "
+ "under the terms of the GNU Affero General Public License "
+ "as published by the Free Software Foundation, "
+ "either version 3 of the License, "
+ "or (at your option) any later version.\n"
+ "This program is distributed in the hope that it will be useful, "
+ "but WITHOUT ANY WARRANTY; "
+ "without even the implied warranty of MERCHANTABILITY "
+ "or FITNESS FOR A PARTICULAR PURPOSE. "
+ "See the GNU Affero General Public License for more details.\n"
+ "You should have received a copy "
+ "of the GNU Affero General Public License "
+ "along with this program. "
+ "If not, see <https://www.gnu.org/licenses/>.\n"));
+ if (error < 0)
+ {
+ goto cleanup_copyright_line;
+ }
+ error = asprintf (&ret, "%s\n%s\n%s", purpose, copyright_line, disclaimer);
+ if (error < 0)
+ {
+ FREE (ret);
+ ret = NULL;
+ goto cleanup_disclaimer;
+ }
+cleanup_disclaimer:
+ FREE (disclaimer);
+cleanup_copyright_line:
+ FREE (copyright_line);
+cleanup_purpose:
+ FREE (purpose);
+cleanup:
+ return ret;
+}
+
#endif /* DISFLUID_AUTHORS_INCLUDED */
diff --git a/src/libdisfluid/disfluid-cache-entry.h b/src/libdisfluid/disfluid-cache-entry.h
index ea76217..eb78a6c 100644
--- a/src/libdisfluid/disfluid-cache-entry.h
+++ b/src/libdisfluid/disfluid-cache-entry.h
@@ -115,6 +115,14 @@ cache_entry_write (const struct disfluid_cache_entry *entry, int fd);
MAYBE_UNUSED static int
cache_entry_fwrite (const struct disfluid_cache_entry *entry, FILE * f);
+MAYBE_UNUSED static int
+cache_entry_describe_request_date (const struct disfluid_cache_entry *entry,
+ char **description);
+
+MAYBE_UNUSED static int
+cache_entry_describe_response_date (const struct disfluid_cache_entry *entry,
+ char **description);
+
# include <assert.h>
# include <flexmember.h>
@@ -198,7 +206,7 @@ cache_entry_init (struct disfluid_cache_entry *entry, size_t max_key,
entry->header_length = 0;
entry->body_length = 0;
char *key = cache_entry_key (entry);
- char *header = cache_entry_key (entry);
+ char *header = cache_entry_header (entry);
*key = '\0';
*header = '\0';
}
@@ -260,14 +268,17 @@ cache_entry_copy (struct disfluid_cache_entry *restrict dest,
{
strcpy (dest_key, src_key);
}
+ dest->key_length = src_key_size;
if (!(src->flags & HEADER_NOT_LOADED))
{
strcpy (dest_header, src_header);
}
+ dest->header_length = src_header_size;
if (!(src->flags & BODY_NOT_LOADED))
{
memcpy (dest_body, src_body, src_body_size);
}
+ dest->body_length = src_body_size;
}
return -flags;
}
@@ -1023,4 +1034,56 @@ cache_entry_fwrite (const struct disfluid_cache_entry *entry, FILE * f)
return cache_entry_save (entry, disfluid_cache_entry_saver_fwrite, f);
}
+static int
+cache_entry_describe_date (const struct timespec *ts, const char *format,
+ char **description)
+{
+ struct tm date;
+ struct tm *result = localtime_r (&(ts->tv_sec), &date);
+ if (result == NULL)
+ {
+ return -1;
+ }
+ char buffer[256];
+ size_t n_buffer = strftime (buffer, sizeof (buffer), "%c", &date);
+ if (n_buffer == 0)
+ {
+ return -1;
+ }
+ if (n_buffer >= sizeof (buffer))
+ {
+ buffer[n_buffer - 1] = '\0';
+ }
+ else
+ {
+ buffer[n_buffer] = '\0';
+ }
+ /* TRANSLATORS: the argument is a date in the preferred format for
+ the locale. */
+ int error = asprintf (description, format, buffer);
+ if (error < 0)
+ {
+ return -2;
+ }
+ return 0;
+}
+
+static int
+cache_entry_describe_request_date (const struct disfluid_cache_entry *entry,
+ char **description)
+{
+ struct timespec ts;
+ cache_entry_get_request_date (entry, &ts);
+ return cache_entry_describe_date (&ts, _("Requested %s"), description);
+}
+
+static int
+cache_entry_describe_response_date (const struct disfluid_cache_entry *entry,
+ char **description)
+{
+ struct timespec ts;
+ cache_entry_get_response_date (entry, &ts);
+ return cache_entry_describe_date (&ts, _("Responded %s"), description);
+}
+
#endif /* DISFLUID_DISFLUID_CACHE_ENTRY_INCLUDED */
diff --git a/src/libdisfluid/disfluid-ui.h b/src/libdisfluid/disfluid-ui.h
new file mode 100644
index 0000000..3555664
--- /dev/null
+++ b/src/libdisfluid/disfluid-ui.h
@@ -0,0 +1,23 @@
+#ifndef DISFLUID_UI_INCLUDED
+# define DISFLUID_UI_INCLUDED
+
+static inline const char *greet_world (void);
+static inline const char *metaphor_name (void);
+
+# include "disfluid-init.h"
+
+static inline const char *
+greet_world (void)
+{
+ ensure_init ();
+ return _("Hello, world!");
+}
+
+static inline const char *
+metaphor_name (void)
+{
+ ensure_init ();
+ return _("Experiences");
+}
+
+#endif /* DISFLUID_UI_INCLUDED */
diff --git a/src/libdisfluid/main.c b/src/libdisfluid/main.c
index 6b21295..5aab482 100644
--- a/src/libdisfluid/main.c
+++ b/src/libdisfluid/main.c
@@ -25,6 +25,7 @@
#include "disfluid-cache-entry-key.h"
#include "disfluid-cache-entry-hash.h"
#include "disfluid-tests.h"
+#include "disfluid-ui.h"
#include "disfluid-version.h"
const char *
@@ -117,6 +118,12 @@ disfluid_translation_credits (void)
return translation_credits ();
}
+char *
+disfluid_copyright_statement (void)
+{
+ return copyright_statement ();
+}
+
size_t
disfluid_cache_entry_size (size_t max_key, size_t max_header, size_t max_body)
{
@@ -238,6 +245,27 @@ disfluid_cache_entry_is_invalidated (const struct disfluid_cache_entry *entry)
return cache_entry_is_invalidated (entry);
}
+size_t
+disfluid_cache_entry_get_key (const struct disfluid_cache_entry *entry,
+ size_t start, size_t max, char *key)
+{
+ return cache_entry_get_key (entry, start, max, key);
+}
+
+size_t
+disfluid_cache_entry_get_header (const struct disfluid_cache_entry *entry,
+ size_t start, size_t max, char *header)
+{
+ return cache_entry_get_header (entry, start, max, header);
+}
+
+size_t
+disfluid_cache_entry_get_body (const struct disfluid_cache_entry *entry,
+ size_t start, size_t max, char *body)
+{
+ return cache_entry_get_body (entry, start, max, body);
+}
+
int
disfluid_cache_entry_load (struct disfluid_cache_entry *entry,
int load_key,
@@ -307,3 +335,29 @@ disfluid_hash_primary_cache_key (const char *method,
return hash_primary_cache_key (method, uri, password, password_length,
max_hash, hash);
}
+
+const char *
+disfluid_greet_world (void)
+{
+ return greet_world ();
+}
+
+const char *
+disfluid_metaphor_name (void)
+{
+ return metaphor_name ();
+}
+
+int
+disfluid_cache_entry_describe_request_date (const struct disfluid_cache_entry
+ *entry, char **description)
+{
+ return cache_entry_describe_request_date (entry, description);
+}
+
+int
+disfluid_cache_entry_describe_response_date (const struct disfluid_cache_entry
+ *entry, char **description)
+{
+ return cache_entry_describe_response_date (entry, description);
+}
diff --git a/src/vala/Makefile.am b/src/vala/Makefile.am
index acbb494..a0e4279 100644
--- a/src/vala/Makefile.am
+++ b/src/vala/Makefile.am
@@ -1,6 +1,3 @@
-introspection/Disfluid-$(DLL_VERSION).gir:
- $(MAKE) $(AM_MAKEFLAGS) -C introspection Disfluid-$(DLL_VERSION).gir
-
vapidir = $(datarootdir)/vala/vapi
dist_vapi_DATA = %D%/disfluid-$(DLL_VERSION).vapi
@@ -10,5 +7,35 @@ VAPIGEN_VERBOSE_ = $(VAPIGEN_VERBOSE_@AM_DEFAULT_V@)
VAPIGEN_VERBOSE_1 = $(VAPIGEN)
VAPIGEN_VERBOSE_0 = @echo " VAPIGEN " $@; $(VAPIGEN) --quiet
-%D%/disfluid-$(DLL_VERSION).vapi: introspection/Disfluid-$(DLL_VERSION).gir
- $(AM_VAPIGEN) --library=disfluid-$(DLL_VERSION) -d $(srcdir)/%D% $(srcdir)/introspection/Disfluid-$(DLL_VERSION).gir
+%D%/disfluid-$(DLL_VERSION).vapi: $(dist_gir_DATA)
+ @$(MKDIR_P) %D%/vapi-t
+ $(AM_VAPIGEN) --library=disfluid-$(DLL_VERSION) -d %D%/vapi-t $(dist_gir_DATA) && mv %D%/vapi-t/disfluid-$(DLL_VERSION).vapi %D%/disfluid-$(DLL_VERSION).vapi-t && rmdir %D%/vapi-t && mv %D%/disfluid-$(DLL_VERSION).vapi-t $(srcdir)/%D%/disfluid-$(DLL_VERSION).vapi
+
+AM_VALAFLAGS = --pkg gtk4 --pkg libadwaita-1
+
+if WITH_GTK
+bin_PROGRAMS += %D%/disfluid
+
+%C%_disfluid_SOURCES = \
+ %D%/main.vala \
+ %D%/about.vala \
+ %D%/cache_entry_widget.vala \
+ %D%/main_window.vala \
+ %D%/disfluid-$(DLL_VERSION).vapi
+
+%C%_disfluid_CPPFLAGS = \
+ -I include -I $(srcdir)/include \
+ -I %D% -I $(srcdir)/%D% \
+ -include config.h \
+ $(GTK_CFLAGS) $(GOBJECT_CFLAGS) $(ADW_CFLAGS)
+
+%C%_disfluid_CFLAGS = \
+ $(GTK_CFLAGS) $(GOBJECT_CFLAGS) $(ADW_CFLAGS)
+
+%C%_disfluid_LDADD = \
+ src/libdisfluid/libdisfluid.la \
+ src/gobject/libdisfluid-gobject.la
+
+%C%_disfluid_LDFLAGS = \
+ $(GTK_LIBS) $(GOBJECT_LIBS) $(ADW_LIBS)
+endif
diff --git a/src/vala/about.vala b/src/vala/about.vala
new file mode 100644
index 0000000..14ff2e8
--- /dev/null
+++ b/src/vala/about.vala
@@ -0,0 +1,51 @@
+namespace Disfluid {
+ Adw.AboutWindow make_about_window () {
+ string appid = "eu.planete_kraus.Disfluid";
+ if (Disfluid.is_nightly ()) {
+ appid += ".Devel";
+ }
+ var window = new Adw.AboutWindow ();
+ window.set_application_icon (appid);
+ window.set_application_name (appid);
+ window.set_version (Disfluid.version ());
+ window.set_release_notes (Disfluid.whats_new ());
+ window.set_release_notes_version (Disfluid.major_version ());
+ window.set_website (Disfluid.website ());
+ var n_authors = Disfluid.count_authors ();
+ string[] developers = new string[0];
+ string[] designers = new string[0];
+ string[] artists = new string[0];
+ string[] documenters = new string[0];
+ for (size_t i = 0; i < n_authors; i++) {
+ var email = Disfluid.author_email (i);
+ var uri = Disfluid.author_uri (i);
+ string full_name = Disfluid.author_name (i);
+ if (email != null) {
+ full_name += " <" + email + ">";
+ } else if (uri != null) {
+ full_name += " " + uri;
+ }
+ if (Disfluid.author_is_developer (i)) {
+ developers += full_name;
+ }
+ if (Disfluid.author_is_designer (i)) {
+ designers += full_name;
+ }
+ if (Disfluid.author_is_artist (i)) {
+ artists += full_name;
+ }
+ if (Disfluid.author_is_documenter (i)) {
+ documenters += full_name;
+ }
+ }
+ window.set_developers (developers);
+ window.set_designers (designers);
+ window.set_artists (artists);
+ window.set_documenters (documenters);
+ var translation_credits = Disfluid.translation_credits ();
+ window.set_translator_credits (translation_credits);
+ window.set_copyright (Disfluid.copyright_statement ());
+ window.set_license_type (Gtk.License.AGPL_3_0);
+ return window;
+ }
+}
diff --git a/src/vala/main.vala b/src/vala/main.vala
new file mode 100644
index 0000000..535baf6
--- /dev/null
+++ b/src/vala/main.vala
@@ -0,0 +1,26 @@
+int main (string[] args) {
+ Intl.setlocale (LocaleCategory.ALL, "");
+ var name = "eu.planete_kraus.Disfluid";
+ if (Disfluid.is_nightly ()) {
+ name += ".Devel";
+ }
+ var app = new Adw.Application(
+ name,
+ ApplicationFlags.FLAGS_NONE
+ );
+ app.activate.connect(() => {
+ var cache_entry = new Disfluid.CacheEntry.alloc (512, 4096, 2 * 1024 * 1024);
+ cache_entry.set_request_gdate (new GLib.DateTime.utc (2023, 03, 26, 19, 38, 00));
+ cache_entry.set_response_gdate (new GLib.DateTime.now ());
+ cache_entry.set_key ("GET https://example.com\r\n");
+ cache_entry.set_response_header ("HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\n");
+ cache_entry.set_response_body ((char[]) "Hello");
+ var cache_entry_view = new Disfluid.CacheEntryView.with_value ("/tmp/test.cache", cache_entry);
+ var cache_view = new Adw.PreferencesPage ();
+ cache_view.add (cache_entry_view);
+ var window = new Disfluid.MainWindow (cache_view);
+ window.set_application (app);
+ window.present();
+ });
+ return app.run(args);
+}
diff --git a/src/vala/main_window.vala b/src/vala/main_window.vala
new file mode 100644
index 0000000..d4dec0d
--- /dev/null
+++ b/src/vala/main_window.vala
@@ -0,0 +1,55 @@
+namespace Disfluid {
+ class MainWindow: Adw.ApplicationWindow {
+ private Adw.WindowTitle _window_title;
+ private Gtk.Box _layout;
+
+ private string? _subtitle = null;
+ private Gtk.Widget? _disfluid_content = null;
+
+ public string? subtitle {
+ get {
+ return this._subtitle;
+ }
+ set {
+ this._subtitle = value;
+ this._window_title.subtitle = value;
+ }
+ }
+
+ public Gtk.Widget? disfluid_content {
+ get {
+ return this._disfluid_content;
+ }
+ set {
+ if (this._disfluid_content != null) {
+ this._layout.remove (this._disfluid_content);
+ }
+ this._disfluid_content = value;
+ if (value != null) {
+ this._layout.append (value);
+ }
+ }
+ }
+
+ construct {
+ this._window_title = new Adw.WindowTitle (Disfluid.metaphor_name (), this._subtitle);
+ var bar = new Adw.HeaderBar ();
+ bar.centering_policy = Adw.CenteringPolicy.STRICT;
+ bar.title_widget = this._window_title;
+ this._layout = new Gtk.Box (Gtk.Orientation.VERTICAL, 0);
+ this._layout.append (bar);
+ if (this._disfluid_content != null) {
+ this._layout.append (this._disfluid_content);
+ }
+ this.content = this._layout;
+ }
+
+ public MainWindow (Gtk.Widget? content) {
+ Object (subtitle: null, disfluid_content: content);
+ }
+
+ public MainWindow.specific (string subtitle, Gtk.Widget? content) {
+ Object (subtitle: subtitle, disfluid_content: content);
+ }
+ }
+}