[ghex] Busy state for file loads and lengthy searches



commit 9c6a60b1a8a0a73c84b17c57c9ed86e8d29ec3b1
Author: Logan Rathbone <poprocks gmail com>
Date:   Wed Dec 22 14:08:41 2021 -0500

    Busy state for file loads and lengthy searches

 src/findreplace.c             | 16 +++++++--------
 src/ghex-application-window.c | 30 ++++-----------------------
 src/gtkhex-layout-manager.c   | 20 ++++++++++++++++--
 src/gtkhex.c                  | 47 ++++++++++++++++++++++++++++++++++++++++++-
 src/hex-document.c            | 11 ++++++++++
 5 files changed, 87 insertions(+), 37 deletions(-)
---
diff --git a/src/findreplace.c b/src/findreplace.c
index b0c346e..2ec599e 100644
--- a/src/findreplace.c
+++ b/src/findreplace.c
@@ -191,14 +191,14 @@ no_string_dialog (GtkWindow *parent)
 static void
 set_watch_cursor (GtkWidget *widget, gboolean enabled)
 {
-  if (enabled)
-  {
-    gtk_widget_set_cursor_from_name (widget, "watch");
-  }
-  else
-  {
-    gtk_widget_set_cursor (widget, NULL);
-  }
+       if (enabled)
+       {
+               gtk_widget_set_cursor_from_name (widget, "watch");
+       }
+       else
+       {
+               gtk_widget_set_cursor (widget, NULL);
+       }
 }
 
 static void
diff --git a/src/ghex-application-window.c b/src/ghex-application-window.c
index 5d222ee..9defd25 100644
--- a/src/ghex-application-window.c
+++ b/src/ghex-application-window.c
@@ -70,7 +70,6 @@ struct _GHexApplicationWindow
 
        /* From GtkBuilder: */
        GtkWidget *no_doc_label;
-       GtkWidget *doc_loading_spinner;
        GtkWidget *hex_notebook;
        GtkWidget *conversions_box;
        GtkWidget *findreplace_box;
@@ -596,7 +595,7 @@ close_tab_shortcut_cb (GtkWidget *widget,
 
        g_return_val_if_fail (GHEX_IS_NOTEBOOK_TAB (tab), FALSE);
 
-       g_signal_emit_by_name (tab, "closed");
+       g_signal_emit_by_name (tab, "close-request");
 
        return TRUE;
 }
@@ -665,7 +664,6 @@ assess_can_save (HexDocument *doc)
 static void
 show_hex_notebook (GHexApplicationWindow *self)
 {
-       gtk_widget_hide (self->doc_loading_spinner);
        gtk_widget_hide (self->no_doc_label);
        gtk_widget_show (self->hex_notebook);
 }
@@ -674,18 +672,9 @@ static void
 show_no_file_loaded_label (GHexApplicationWindow *self)
 {
        gtk_widget_hide (self->hex_notebook);
-       gtk_widget_hide (self->doc_loading_spinner);
        gtk_widget_show (self->no_doc_label);
 }
 
-static void
-show_doc_loading_spinner (GHexApplicationWindow *self)
-{
-       gtk_widget_hide (self->no_doc_label);
-       gtk_widget_hide (self->hex_notebook);
-       gtk_widget_show (self->doc_loading_spinner);
-}
-
 static void
 file_saved_cb (HexDocument *doc,
                gpointer user_data)
@@ -717,7 +706,6 @@ file_loaded (HexDocument *doc, GHexApplicationWindow *self)
 {
        g_return_if_fail (GHEX_IS_APPLICATION_WINDOW (self));
        
-       show_hex_notebook (self);
        document_loaded_or_saved_common (self, doc);
        update_gui_data (self);
 }
@@ -1081,7 +1069,6 @@ save_as_response_cb (GtkNativeDialog *dialog,
 
        if (hex_document_set_file (doc, gfile))
        {
-               show_doc_loading_spinner (self);
                extra_user_data = ACTIVE_GH;
                hex_document_read_async (doc, NULL, doc_read_ready_cb, self);
        }
@@ -1150,7 +1137,6 @@ revert_response_cb (GtkDialog *dialog,
        doc = gtk_hex_get_document (ACTIVE_GH);
 
        extra_user_data = ACTIVE_GH;
-       show_doc_loading_spinner (self);
        hex_document_read_async (doc, NULL, doc_read_ready_cb, self);
 
 end:
@@ -1509,10 +1495,6 @@ ghex_application_window_init (GHexApplicationWindow *self)
 
        gtk_widget_init_template (widget);
 
-       /* FIXME - setting this property doesn't seem to work in the UI file?
-        * acc. to IRC, 2021-Dec -- KNOWN ISSUE w/ GTK. */
-       gtk_spinner_start (GTK_SPINNER(self->doc_loading_spinner));
-
        /* Cache system default of prefer-dark-mode; gtk does not do this. This
         * is run here as it cannot be done until we have a 'screen'. */
        get_sys_default_is_dark ();
@@ -1894,8 +1876,6 @@ 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,
@@ -1989,6 +1969,8 @@ ghex_application_window_add_hex (GHexApplicationWindow *self,
 
        g_signal_connect (doc, "file-saved",
                        G_CALLBACK(file_saved_cb), self);
+
+       show_hex_notebook (self);
 }
 
 #ifndef BACKEND_MMAP
@@ -2129,13 +2111,9 @@ ghex_application_window_open_file (GHexApplicationWindow *self, GFile *file)
 
                return;
        }
-       /* FIXME - this is kind of cheap and will block all the *other* tabs
-        * as well, even though there's no need to. But it will do for now.
-        */
-       show_doc_loading_spinner (self);
 
-       extra_user_data = gh;
        ghex_application_window_add_hex (self, gh);
+       extra_user_data = gh;
        hex_document_read_async (doc, NULL, doc_read_ready_cb, self);
 }
 
diff --git a/src/gtkhex-layout-manager.c b/src/gtkhex-layout-manager.c
index e853d3b..196f35d 100644
--- a/src/gtkhex-layout-manager.c
+++ b/src/gtkhex-layout-manager.c
@@ -204,6 +204,7 @@ gtk_hex_layout_measure (GtkLayoutManager *layout_manager,
                *natural = natural_size;
 }
 
+#define BASE_ALLOC {.x = 0, .y = 0, .width = 0, .height = full_height}
 static void
 gtk_hex_layout_allocate (GtkLayoutManager *layout_manager,
                GtkWidget        *widget,
@@ -215,12 +216,10 @@ gtk_hex_layout_allocate (GtkLayoutManager *layout_manager,
        GtkWidget *child;
        gboolean have_hex = FALSE;
        gboolean have_ascii = FALSE;
-#define BASE_ALLOC {.x = 0, .y = 0, .width = 0, .height = full_height}
        GtkAllocation off_alloc = BASE_ALLOC;
        GtkAllocation hex_alloc = BASE_ALLOC;
        GtkAllocation asc_alloc = BASE_ALLOC;
        GtkAllocation sbar_alloc = BASE_ALLOC;
-#undef BASE_ALLOC
 
        int avail_width = full_width;
        GtkWidget *hex = NULL, *ascii = NULL, *offsets = NULL, *scrollbar = NULL;
@@ -257,7 +256,23 @@ gtk_hex_layout_allocate (GtkLayoutManager *layout_manager,
                                break;
                        case SCROLLBAR_COLUMN:  scrollbar = child;
                                break;
+
                        case NO_COLUMN:
+                       {
+                               GtkRequisition child_req = {0};
+                               GtkAllocation alloc = BASE_ALLOC;
+
+                               /* just position the widget in the centre at its preferred
+                                * size. TODO: check v/halign and v/hexand
+                                */
+                               gtk_widget_get_preferred_size (child, &child_req, NULL);
+                               alloc.width = child_req.width;
+                               alloc.height = child_req.height;
+                               alloc.x = (full_width / 2) - (alloc.width / 2);
+                               alloc.y = (full_height / 2) - (alloc.height / 2);
+                               gtk_widget_size_allocate (child, &alloc, -1);
+                               return;
+                       }
                                break;
 
                                /* We won't test for this each loop. */
@@ -408,6 +423,7 @@ gtk_hex_layout_allocate (GtkLayoutManager *layout_manager,
        if (ascii)
                gtk_widget_size_allocate (ascii, &asc_alloc, -1);
 }
+#undef BASE_ALLOC
 
 static GtkSizeRequestMode
 gtk_hex_layout_get_request_mode (GtkLayoutManager *layout_manager,
diff --git a/src/gtkhex.c b/src/gtkhex.c
index 73c74c2..a1b3d1b 100644
--- a/src/gtkhex.c
+++ b/src/gtkhex.c
@@ -131,6 +131,8 @@ struct _GtkHex
        GtkWidget *offsets;                     /* DrawingArea */
        GtkWidget *scrollbar;
 
+       GtkWidget *busy_spinner;
+
        PangoLayout *xlayout, *alayout, *olayout;
 
        GtkWidget *context_menu;
@@ -2288,17 +2290,49 @@ gtk_hex_snapshot (GtkWidget *widget, GtkSnapshot *snapshot)
        g_signal_emit_by_name(G_OBJECT(gh), "draw-complete");
 }
 
+static void
+set_busy_state (GtkHex *gh, gboolean busy)
+{
+       GtkWidget *widget = GTK_WIDGET(gh);
+
+       if (busy)
+       {
+               gtk_widget_hide (gh->offsets);
+               gtk_widget_hide (gh->xdisp);
+               gtk_widget_hide (gh->adisp);
+               gtk_widget_hide (gh->scrollbar);
+               gtk_widget_show (gh->busy_spinner);
+       }
+       else
+       {
+               gtk_widget_hide (gh->busy_spinner);
+               gtk_widget_set_visible (gh->offsets, gh->show_offsets);
+               gtk_widget_show (gh->xdisp);
+               gtk_widget_show (gh->adisp);
+               gtk_widget_show (gh->scrollbar);
+       }
+}
+
+static void
+file_read_started_cb (HexDocument *doc, gpointer data)
+{
+       GtkHex *gh = GTK_HEX (data);
+
+       set_busy_state (gh, TRUE);
+}
+
 static void
 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));
 
+       set_busy_state (gh, FALSE);
+
        gtk_widget_queue_draw (GTK_WIDGET(gh));
 }
 
@@ -2330,6 +2364,7 @@ gtk_hex_dispose (GObject *object)
        g_clear_pointer (&gh->adisp, gtk_widget_unparent);
        g_clear_pointer (&gh->offsets, gtk_widget_unparent);
        g_clear_pointer (&gh->scrollbar, gtk_widget_unparent);
+       g_clear_pointer (&gh->busy_spinner, gtk_widget_unparent);
 
        /* FIXME - This results in assertion errors upon exit. I have been told
         * by ebassi on IRC (16-Dec-2021) that this may be a bug in gtk. See:
@@ -2708,6 +2743,13 @@ gtk_hex_init (GtkHex *gh)
                        (gh->layout_manager, gh->scrollbar));
        gtk_hex_layout_child_set_column (child_info, SCROLLBAR_COLUMN);
        
+       /* Setup busy spinner */
+
+       gh->busy_spinner = gtk_spinner_new ();
+       gtk_spinner_start (GTK_SPINNER(gh->busy_spinner));
+       gtk_widget_set_visible (gh->busy_spinner, FALSE);
+       gtk_widget_set_parent (gh->busy_spinner, widget);
+
        /* SETUP SIGNALS */
 
        g_signal_connect (widget, "state-flags-changed",
@@ -2833,6 +2875,9 @@ gtk_hex_new (HexDocument *owner)
 
        /* Setup document signals */
 
+    g_signal_connect (G_OBJECT (gh->document), "file-read-started",
+            G_CALLBACK (file_read_started_cb), gh);
+
     g_signal_connect (G_OBJECT (gh->document), "file-loaded",
             G_CALLBACK (file_loaded_cb), gh);
 
diff --git a/src/hex-document.c b/src/hex-document.c
index 74591ee..cd8344e 100644
--- a/src/hex-document.c
+++ b/src/hex-document.c
@@ -69,6 +69,7 @@ enum {
        UNDO_STACK_FORGET,
        FILE_NAME_CHANGED,
        FILE_SAVED,
+       FILE_READ_STARTED,
        FILE_LOADED,
        LAST_SIGNAL
 };
@@ -282,6 +283,15 @@ hex_document_class_init (HexDocumentClass *klass)
                                G_TYPE_NONE,
                                0);
 
+       hex_signals[FILE_READ_STARTED] =
+               g_signal_new_class_handler ("file-read-started",
+                               G_OBJECT_CLASS_TYPE (gobject_class),
+                               G_SIGNAL_RUN_FIRST,
+                               NULL,
+                               NULL, NULL, NULL,
+                               G_TYPE_NONE,
+                               0);
+
        hex_signals[FILE_LOADED] =
                g_signal_new_class_handler ("file-loaded",
                                G_OBJECT_CLASS_TYPE (gobject_class),
@@ -529,6 +539,7 @@ hex_document_read_async (HexDocument *doc,
 
        /* Read the actual file on disk into the buffer */
        hex_buffer_read_async (doc->buffer, NULL, document_ready_cb, task);
+       g_signal_emit (G_OBJECT(doc), hex_signals[FILE_READ_STARTED], 0);
 }
 
 gboolean


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]