[ghex] HexBuffer{Iface,Mmap}: implement _read_async API
- From: Logan Rathbone <larathbone src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [ghex] HexBuffer{Iface,Mmap}: implement _read_async API
- Date: Sat, 18 Dec 2021 03:29:05 +0000 (UTC)
commit 21a984cb63f8f47a5457eaa5a814a3c6e87aeb72
Author: Logan Rathbone <poprocks gmail com>
Date: Fri Dec 17 05:33:18 2021 -0500
HexBuffer{Iface,Mmap}: implement _read_async API
src/ghex-application-window.c | 64 +++++++++++++++++++++++++++++++--------
src/ghex-application-window.ui.in | 14 ++++++++-
src/gtkhex.c | 26 +++++++++++++---
src/hex-buffer-iface.c | 30 +++++++++++++++++-
src/hex-buffer-iface.h | 15 +++++++++
src/hex-buffer-mmap.c | 55 ++++++++++++++++++++++++++++++++-
src/hex-document.c | 52 +++++++++++++++++++++++--------
src/hex-document.h | 2 +-
8 files changed, 224 insertions(+), 34 deletions(-)
---
diff --git a/src/ghex-application-window.c b/src/ghex-application-window.c
index 51c1113..5b4075e 100644
--- a/src/ghex-application-window.c
+++ b/src/ghex-application-window.c
@@ -68,6 +68,7 @@ struct _GHexApplicationWindow
/* From GtkBuilder: */
GtkWidget *no_doc_label;
+ GtkWidget *doc_loading_spinner;
GtkWidget *hex_notebook;
GtkWidget *conversions_box;
GtkWidget *findreplace_box;
@@ -657,7 +658,17 @@ assess_can_save (HexDocument *doc)
}
static void
-ghex_application_window_file_saved_cb (HexDocument *doc,
+do_doc_loading_spinner (GHexApplicationWindow *self)
+{
+ gtk_widget_hide (self->no_doc_label);
+ gtk_widget_hide (self->hex_notebook);
+
+ gtk_spinner_start (GTK_SPINNER(self->doc_loading_spinner));
+ gtk_widget_show (self->doc_loading_spinner);
+}
+
+static void
+file_saved_cb (HexDocument *doc,
gpointer user_data)
{
GHexApplicationWindow *self = GHEX_APPLICATION_WINDOW(user_data);
@@ -668,13 +679,9 @@ ghex_application_window_file_saved_cb (HexDocument *doc,
}
static void
-ghex_application_window_document_changed_cb (HexDocument *doc,
- gpointer change_data,
- gboolean push_undo,
- gpointer user_data)
+document_loaded_or_saved_common (GHexApplicationWindow *self,
+ HexDocument *doc)
{
- GHexApplicationWindow *self = GHEX_APPLICATION_WINDOW(user_data);
-
g_return_if_fail (GHEX_IS_APPLICATION_WINDOW (self));
/* The appwindow as a whole not interested in any document changes that
@@ -686,6 +693,31 @@ ghex_application_window_document_changed_cb (HexDocument *doc,
ghex_application_window_set_can_save (self, assess_can_save (doc));
}
+static void
+file_loaded_cb (HexDocument *doc, gpointer user_data)
+{
+ GHexApplicationWindow *self = GHEX_APPLICATION_WINDOW(user_data);
+
+ gtk_spinner_stop (GTK_SPINNER(self->doc_loading_spinner));
+ gtk_widget_hide (self->doc_loading_spinner);
+ gtk_widget_hide (self->no_doc_label);
+ gtk_widget_show (self->hex_notebook);
+
+ document_loaded_or_saved_common (self, doc);
+}
+
+
+static void
+document_changed_cb (HexDocument *doc,
+ gpointer change_data,
+ gboolean push_undo,
+ gpointer user_data)
+{
+ GHexApplicationWindow *self = GHEX_APPLICATION_WINDOW(user_data);
+
+ document_loaded_or_saved_common (self, doc);
+}
+
static void
tab_close_request_cb (GHexNotebookTab *tab,
gpointer user_data)
@@ -739,8 +771,7 @@ notebook_page_added_cb (GtkNotebook *notebook,
/* Let's play this super dumb. If a page is added, that will generally
* mean we don't have to count the pages to see if we have > 0.
*/
- gtk_widget_show (self->hex_notebook);
- gtk_widget_hide (self->no_doc_label);
+ do_doc_loading_spinner (self);
enable_main_actions (self, TRUE);
}
@@ -761,7 +792,10 @@ notebook_page_removed_cb (GtkNotebook *notebook,
ghex_application_window_set_show_jump (self, FALSE);
ghex_application_window_set_show_chartable (self, FALSE);
ghex_application_window_set_show_converter (self, FALSE);
+
gtk_widget_hide (self->hex_notebook);
+ gtk_widget_hide (self->doc_loading_spinner);
+ gtk_spinner_stop (GTK_SPINNER(self->doc_loading_spinner));
gtk_widget_show (self->no_doc_label);
}
}
@@ -1035,7 +1069,7 @@ save_as_response_cb (GtkNativeDialog *dialog,
if (hex_document_set_file (doc, gfile))
{
- hex_document_read (doc);
+ do_doc_loading_spinner (self);
}
else
{
@@ -1093,6 +1127,7 @@ revert_response_cb (GtkDialog *dialog,
doc = gtk_hex_get_document (ACTIVE_GH);
+ do_doc_loading_spinner (self);
hex_document_read (doc);
end:
@@ -1870,6 +1905,8 @@ ghex_application_window_class_init(GHexApplicationWindowClass *klass)
gtk_widget_class_bind_template_child (widget_class, GHexApplicationWindow,
no_doc_label);
+ gtk_widget_class_bind_template_child (widget_class, GHexApplicationWindow,
+ doc_loading_spinner);
gtk_widget_class_bind_template_child (widget_class, GHexApplicationWindow,
hex_notebook);
gtk_widget_class_bind_template_child (widget_class, GHexApplicationWindow,
@@ -1958,11 +1995,14 @@ ghex_application_window_add_hex (GHexApplicationWindow *self,
g_signal_connect (gh, "cursor-moved",
G_CALLBACK(cursor_moved_cb), self);
+ g_signal_connect (doc, "file-loaded",
+ G_CALLBACK(file_loaded_cb), self);
+
g_signal_connect (doc, "document-changed",
- G_CALLBACK(ghex_application_window_document_changed_cb), self);
+ G_CALLBACK(document_changed_cb), self);
g_signal_connect (doc, "file-saved",
- G_CALLBACK(ghex_application_window_file_saved_cb), self);
+ G_CALLBACK(file_saved_cb), self);
}
#ifndef EXPERIMENTAL_MMAP
diff --git a/src/ghex-application-window.ui.in b/src/ghex-application-window.ui.in
index a8923f4..ecafbfb 100644
--- a/src/ghex-application-window.ui.in
+++ b/src/ghex-application-window.ui.in
@@ -213,7 +213,19 @@
<property name="hexpand">true</property>
<property name="vexpand">true</property>
</object>
- </child> <!-- label showing no doc loaded -->
+ </child> <!-- /no_doc_label -->
+
+ <child> <!-- label showing no doc loaded -->
+ <object class="GtkSpinner" id="doc_loading_spinner">
+ <property name="spinning">true</property>
<!-- doesn't seem to work -->
+ <property name="halign">center</property>
+ <property name="valign">center</property>
+ <property name="hexpand">true</property>
+ <property name="vexpand">true</property>
+ <!-- invisible by default to show the
no_doc_label -->
+ <property name="visible">false</property>
+ </object>
+ </child> <!-- /doc_loading_spinner -->
<child> <!-- hex_notebook - tabs for GtkHex widget -->
<object class="GtkNotebook" id="hex_notebook">
diff --git a/src/gtkhex.c b/src/gtkhex.c
index b856994..7c6e367 100644
--- a/src/gtkhex.c
+++ b/src/gtkhex.c
@@ -2225,7 +2225,21 @@ gtk_hex_snapshot (GtkWidget *widget, GtkSnapshot *snapshot)
}
static void
-gtk_hex_document_changed (HexDocument* doc, gpointer change_data,
+file_loaded_cb (HexDocument *doc, gpointer data)
+{
+ GtkHex *gh = GTK_HEX(data);
+ g_return_if_fail (GTK_IS_HEX (gh));
+
+ gtk_widget_action_set_enabled (GTK_WIDGET(gh),
+ "gtkhex.undo", hex_document_can_undo (doc));
+ gtk_widget_action_set_enabled (GTK_WIDGET(gh),
+ "gtkhex.redo", hex_document_can_redo (doc));
+
+ gtk_widget_queue_draw (GTK_WIDGET(gh));
+}
+
+static void
+document_changed_cb (HexDocument* doc, gpointer change_data,
gboolean push_undo, gpointer data)
{
GtkHex *gh = GTK_HEX(data);
@@ -2754,11 +2768,13 @@ gtk_hex_new (HexDocument *owner)
gh->document = owner;
- /* Setup document signals
- * (can't do in _init because we don't have access to that object yet).
- */
+ /* Setup document signals */
+
+ g_signal_connect (G_OBJECT (gh->document), "file-loaded",
+ G_CALLBACK (file_loaded_cb), gh);
+
g_signal_connect (G_OBJECT (gh->document), "document-changed",
- G_CALLBACK (gtk_hex_document_changed), gh);
+ G_CALLBACK (document_changed_cb), gh);
g_signal_connect (G_OBJECT (gh->document), "undo",
G_CALLBACK (doc_undo_redo_cb), gh);
diff --git a/src/hex-buffer-iface.c b/src/hex-buffer-iface.c
index 1a5baf1..91d69e4 100644
--- a/src/hex-buffer-iface.c
+++ b/src/hex-buffer-iface.c
@@ -76,7 +76,6 @@ hex_buffer_set_file (HexBuffer *self, GFile *file)
return iface->set_file (self, file);
}
-
gboolean
hex_buffer_read (HexBuffer *self)
{
@@ -89,6 +88,35 @@ hex_buffer_read (HexBuffer *self)
return iface->read (self);
}
+void
+hex_buffer_read_async (HexBuffer *self,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ HexBufferInterface *iface;
+
+ g_return_if_fail (HEX_IS_BUFFER (self));
+ iface = HEX_BUFFER_GET_IFACE (self);
+ g_return_if_fail (iface->read_async != NULL);
+
+ iface->read_async (self, cancellable, callback, user_data);
+}
+
+gboolean
+hex_buffer_read_finish (HexBuffer *self,
+ GAsyncResult *result,
+ GError **error)
+{
+ HexBufferInterface *iface;
+
+ g_return_val_if_fail (HEX_IS_BUFFER (self), FALSE);
+ iface = HEX_BUFFER_GET_IFACE (self);
+ g_return_val_if_fail (iface->read_finish != NULL, FALSE);
+
+ return iface->read_finish (self, result, error);
+}
+
gboolean
hex_buffer_write_to_file (HexBuffer *self, GFile *file)
{
diff --git a/src/hex-buffer-iface.h b/src/hex-buffer-iface.h
index d61d495..43e9516 100644
--- a/src/hex-buffer-iface.h
+++ b/src/hex-buffer-iface.h
@@ -45,6 +45,15 @@ struct _HexBufferInterface
gboolean (*read) (HexBuffer *self);
+ void (*read_async) (HexBuffer *self,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+ gboolean (*read_finish) (HexBuffer *self,
+ GAsyncResult *result,
+ GError **error);
+
gboolean (*write_to_file) (HexBuffer *self,
GFile *file);
@@ -75,6 +84,12 @@ gboolean hex_buffer_set_file (HexBuffer *self,
gboolean hex_buffer_read (HexBuffer *self);
+void hex_buffer_read_async (HexBuffer *buf, GCancellable *cancellable,
+ GAsyncReadyCallback callback, gpointer user_data);
+
+gboolean hex_buffer_read_finish (HexBuffer *buf, GAsyncResult *result,
+ GError **error);
+
gboolean hex_buffer_write_to_file (HexBuffer *self,
GFile *file);
diff --git a/src/hex-buffer-mmap.c b/src/hex-buffer-mmap.c
index 31193e7..8cac6df 100644
--- a/src/hex-buffer-mmap.c
+++ b/src/hex-buffer-mmap.c
@@ -563,6 +563,57 @@ hex_buffer_mmap_read (HexBuffer *buf)
return TRUE;
}
+static gboolean
+hex_buffer_mmap_read_finish (HexBuffer *buf,
+ GAsyncResult *result,
+ GError **error)
+{
+ HexBufferMmap *self = HEX_BUFFER_MMAP (buf);
+
+ g_return_val_if_fail (g_task_is_valid (result, G_OBJECT(self)), FALSE);
+
+ return g_task_propagate_boolean (G_TASK(result), error);
+}
+
+static void
+hex_buffer_mmap_thread (GTask *task,
+ gpointer source_object,
+ gpointer task_data,
+ GCancellable *cancellable)
+{
+ HexBufferMmap *self = HEX_BUFFER_MMAP (source_object);
+ gboolean success;
+
+ success = hex_buffer_mmap_read (HEX_BUFFER(self));
+ if (success)
+ g_task_return_boolean (task, TRUE);
+ else
+ g_task_return_error (task, self->error);
+}
+
+
+static void
+hex_buffer_mmap_read_async (HexBuffer *buf,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ HexBufferMmap *self = HEX_BUFFER_MMAP (buf);
+ GTask *task;
+
+ task = g_task_new (self, cancellable, callback, user_data);
+ g_task_run_in_thread (task, hex_buffer_mmap_thread);
+ g_object_unref (task); /* _run_in_thread takes a ref */
+}
+
+
+
+
+
+
+
+
+
static gboolean hex_buffer_mmap_set_data (HexBuffer *buf,
size_t offset,
size_t len,
@@ -594,7 +645,7 @@ static gboolean hex_buffer_mmap_write_to_file (HexBuffer *buf,
hex_buffer_mmap_raw (self, &raw, 0, self->payload);
- retval = g_file_replace_contents (self->file,
+ retval = g_file_replace_contents (file,
/* const char* contents, */ raw,
/* gsize length, */ self->payload,
/* const char* etag, */ NULL,
@@ -634,6 +685,8 @@ hex_buffer_mmap_iface_init (HexBufferInterface *iface)
iface->set_data = hex_buffer_mmap_set_data;
iface->set_file = hex_buffer_mmap_set_file;
iface->read = hex_buffer_mmap_read;
+ iface->read_async = hex_buffer_mmap_read_async;
+ iface->read_finish = hex_buffer_mmap_read_finish;
iface->write_to_file = hex_buffer_mmap_write_to_file;
iface->get_payload_size = hex_buffer_mmap_get_payload_size;
}
diff --git a/src/hex-document.c b/src/hex-document.c
index e5a5e1f..d81b80c 100644
--- a/src/hex-document.c
+++ b/src/hex-document.c
@@ -71,6 +71,7 @@ enum {
UNDO_STACK_FORGET,
FILE_NAME_CHANGED,
FILE_SAVED,
+ FILE_LOADED,
LAST_SIGNAL
};
@@ -283,6 +284,15 @@ hex_document_class_init (HexDocumentClass *klass)
NULL, NULL, NULL,
G_TYPE_NONE,
0);
+
+ hex_signals[FILE_LOADED] =
+ g_signal_new_class_handler ("file-loaded",
+ G_OBJECT_CLASS_TYPE (gobject_class),
+ G_SIGNAL_RUN_FIRST,
+ NULL,
+ NULL, NULL, NULL,
+ G_TYPE_NONE,
+ 0);
}
static void
@@ -325,11 +335,7 @@ hex_document_set_file (HexDocument *doc, GFile *file)
if (had_prev_file)
g_signal_emit (G_OBJECT(doc), hex_signals[FILE_NAME_CHANGED], 0);
- if (! hex_document_read (doc))
- {
- g_debug ("%s: Unable to load/read file", __func__);
- return FALSE;
- }
+ hex_document_read (doc);
return TRUE;
}
@@ -458,17 +464,25 @@ hex_document_delete_data(HexDocument *doc, guint offset, guint len, gboolean und
hex_document_set_data (doc, offset, 0, len, NULL, undoable);
}
-gboolean
-hex_document_read (HexDocument *doc)
-{
+void
+document_ready_cb (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ gboolean success;
+ GError *local_error = NULL;
+ HexBuffer *buf = HEX_BUFFER(source_object);
+ HexDocument *doc = HEX_DOCUMENT(user_data);
static HexChangeData change_data;
size_t payload;
- g_return_val_if_fail (G_IS_FILE (doc->file), FALSE);
+ success = hex_buffer_read_finish (buf, res, &local_error);
+ g_debug ("%s: DONE -- result: %d", __func__, success);
- /* Read the actual file on disk into the buffer */
- if (!hex_buffer_read (doc->buffer))
- return FALSE;
+ if (local_error)
+ g_warning (local_error->message);
+
+ /* Initialize data for new doc */
undo_stack_free(doc);
@@ -476,10 +490,22 @@ hex_document_read (HexDocument *doc)
change_data.start = 0;
change_data.end = payload - 1;
+
doc->changed = FALSE;
hex_document_changed (doc, &change_data, FALSE);
+ g_signal_emit (G_OBJECT(doc), hex_signals[FILE_LOADED], 0);
+}
- return TRUE;
+void
+hex_document_read (HexDocument *doc)
+{
+ static HexChangeData change_data;
+ size_t payload;
+
+ g_return_if_fail (G_IS_FILE (doc->file));
+
+ /* Read the actual file on disk into the buffer */
+ hex_buffer_read_async (doc->buffer, NULL, document_ready_cb, doc);
}
gboolean
diff --git a/src/hex-document.h b/src/hex-document.h
index bedccc0..f9337af 100644
--- a/src/hex-document.h
+++ b/src/hex-document.h
@@ -69,7 +69,7 @@ void hex_document_set_data(HexDocument *doc, size_t offset, size_t len, s
void hex_document_set_byte(HexDocument *doc, char val, size_t offset, gboolean insert, gboolean
undoable);
void hex_document_set_nibble(HexDocument *doc, char val, size_t offset, gboolean lower_nibble,
gboolean insert, gboolean undoable);
void hex_document_delete_data(HexDocument *doc, guint offset, guint len, gboolean undoable);
-gboolean hex_document_read (HexDocument *doc);
+void hex_document_read (HexDocument *doc);
gboolean hex_document_write(HexDocument *doc);
gboolean hex_document_write_to_file (HexDocument *doc, GFile *file);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]