[ghex: 1/2] findreplace: watch/busy feedback and cancellable
- From: Logan Rathbone <larathbone src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [ghex: 1/2] findreplace: watch/busy feedback and cancellable
- Date: Tue, 21 Dec 2021 22:09:25 +0000 (UTC)
commit c8cbc6f1c899e5947e692fe14d177b06ea46f626
Author: Logan Rathbone <poprocks gmail com>
Date: Tue Dec 21 01:40:38 2021 -0500
findreplace: watch/busy feedback and cancellable
nb: This doesn't work 100% perfectly at this stage. If you cancel, the
worker thread operation will continue in the background and then be
silently discarded. Thus CPU usage can continue to be high while a large
cancelled find/replace task completes in the background.
src/findreplace.c | 133 +++++++++++++++++++++++++++++++++++------------------
src/hex-document.c | 4 +-
2 files changed, 90 insertions(+), 47 deletions(-)
---
diff --git a/src/findreplace.c b/src/findreplace.c
index bfc4867..b0c346e 100644
--- a/src/findreplace.c
+++ b/src/findreplace.c
@@ -70,6 +70,7 @@ typedef struct {
GtkWidget *f_next, *f_prev, *f_clear;
GtkWidget *close;
gboolean found;
+ GCancellable *cancellable;
} FindDialogPrivate;
@@ -111,7 +112,8 @@ static void replace_all_cb (GtkButton *button, gpointer user_data);
static void replace_clear_cb (GtkButton *button, gpointer user_data);
static void goto_byte_cb (GtkButton *button, gpointer user_data);
static gint64 get_search_string (HexDocument *doc, gchar **str);
-
+static void pane_dialog_update_busy_state (PaneDialog *self);
+static void mark_gh_busy (GtkHex *gh, gboolean busy);
static GtkWidget *
create_hex_view (HexDocument *doc)
@@ -156,6 +158,15 @@ pane_dialog_real_close (PaneDialog *self)
gtk_widget_hide (GTK_WIDGET(self));
}
+static void
+find_cancel_cb (GtkButton *button, gpointer user_data)
+{
+ FindDialog *self = FIND_DIALOG(user_data);
+ FindDialogPrivate *f_priv = find_dialog_get_instance_private (self);
+
+ g_cancellable_cancel (f_priv->cancellable);
+}
+
static void
common_cancel_cb (GtkButton *button, gpointer user_data)
{
@@ -177,6 +188,37 @@ no_string_dialog (GtkWindow *parent)
_("No string provided."));
}
+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);
+ }
+}
+
+static void
+mark_gh_busy (GtkHex *gh, gboolean busy)
+{
+ set_watch_cursor (GTK_WIDGET(gh), busy);
+ g_object_set_data (G_OBJECT(gh), "busy", GINT_TO_POINTER(busy));
+}
+
+static gboolean
+gh_is_busy (GtkHex *gh)
+{
+ gpointer data = g_object_get_data (G_OBJECT(gh), "busy");
+
+ if (data)
+ return GPOINTER_TO_INT (data);
+ else
+ return FALSE;
+}
+
static void
find_ready_cb (GObject *source_object,
GAsyncResult *res,
@@ -191,6 +233,14 @@ find_ready_cb (GObject *source_object,
find_data = hex_document_find_finish (doc, res);
+ /* Typically this will be due to a cancellation - could theoretically be
+ * an error, but not much we can do to report a search error anyway.
+ */
+ if (! find_data)
+ goto out;
+
+ g_object_unref (res);
+
if (find_data->found)
{
f_priv->found = TRUE;
@@ -214,6 +264,10 @@ find_ready_cb (GObject *source_object,
f_priv->found = FALSE;
}
+
+out:
+ mark_gh_busy (priv->gh, FALSE);
+ pane_dialog_update_busy_state (PANE_DIALOG(self));
}
static void
@@ -253,6 +307,7 @@ find_common (FindDialog *self, enum FindDirection direction,
if (direction == FIND_FORWARD)
{
+ g_cancellable_reset (f_priv->cancellable);
hex_document_find_forward_async (doc,
f_priv->found == FALSE ? cursor_pos : cursor_pos + 1,
str,
@@ -260,7 +315,7 @@ find_common (FindDialog *self, enum FindDirection direction,
&offset,
found_msg,
not_found_msg,
- NULL, /* cancellable */
+ f_priv->cancellable,
find_ready_cb,
self);
}
@@ -278,43 +333,8 @@ find_common (FindDialog *self, enum FindDirection direction,
self);
}
-
-#if 0
- if (direction == FIND_FORWARD
- ?
- hex_document_find_forward (doc,
- found == FALSE ? cursor_pos : cursor_pos + 1,
- str, str_len, &offset)
-
- :
- hex_document_find_backward (doc,
- cursor_pos, str, str_len, &offset)
- )
-#endif
-
-#if 0
- {
- found = TRUE;
- gtk_hex_set_cursor (priv->gh, offset);
-
- /* If string found, insert auto-highlights of search string */
-
- if (priv->auto_highlight)
- gtk_hex_delete_autohighlight (priv->gh, priv->auto_highlight);
-
- priv->auto_highlight = NULL;
- priv->auto_highlight = gtk_hex_insert_autohighlight (priv->gh,
- str, str_len);
-
- gtk_widget_grab_focus (GTK_WIDGET(priv->gh));
- }
- else
- {
- display_info_dialog (parent, found ? found_msg : not_found_msg);
-
- found = FALSE;
- }
-#endif
+ mark_gh_busy (priv->gh, TRUE);
+ pane_dialog_update_busy_state (PANE_DIALOG(self));
}
static void
@@ -718,13 +738,31 @@ pane_dialog_class_init (PaneDialogClass *klass)
G_TYPE_NONE, 0);
}
+/* Helper */
+static void
+pane_dialog_update_busy_state (PaneDialog *self)
+{
+ PaneDialogPrivate *priv = pane_dialog_get_instance_private (self);
+
+ if (FIND_IS_DIALOG (self))
+ {
+ FindDialogPrivate *f_priv;
+ gboolean busy;
+
+ f_priv = find_dialog_get_instance_private (FIND_DIALOG(self));
+ busy = gh_is_busy (priv->gh);
+ gtk_widget_set_sensitive (f_priv->f_next, !busy);
+ gtk_widget_set_sensitive (f_priv->f_prev, !busy);
+ }
+}
+
void
pane_dialog_set_hex (PaneDialog *self, GtkHex *gh)
{
PaneDialogPrivate *priv;
- g_return_if_fail (PANE_IS_DIALOG(self));
- g_return_if_fail (GTK_IS_HEX(gh));
+ g_return_if_fail (PANE_IS_DIALOG (self));
+ g_return_if_fail (GTK_IS_HEX (gh));
priv = pane_dialog_get_instance_private (PANE_DIALOG(self));
@@ -735,6 +773,8 @@ pane_dialog_set_hex (PaneDialog *self, GtkHex *gh)
priv->auto_highlight = NULL;
priv->gh = gh;
+
+ pane_dialog_update_busy_state (self);
}
void
@@ -742,9 +782,7 @@ pane_dialog_close (PaneDialog *self)
{
g_return_if_fail (PANE_IS_DIALOG (self));
- g_signal_emit(self,
- signals[CLOSED],
- 0); /* GQuark detail (just set to 0 if unknown) */
+ g_signal_emit(self, signals[CLOSED], 0);
}
/* FindDialog */
@@ -754,6 +792,8 @@ find_dialog_init (FindDialog *self)
{
FindDialogPrivate *f_priv = find_dialog_get_instance_private (self);
+ f_priv->cancellable = g_cancellable_new ();
+
/* Setup our root container. */
f_priv->vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
gtk_widget_set_parent (f_priv->vbox, GTK_WIDGET(self));
@@ -805,6 +845,8 @@ find_dialog_init (FindDialog *self)
gtk_widget_set_halign (f_priv->close, GTK_ALIGN_END);
g_signal_connect (G_OBJECT (f_priv->close), "clicked",
G_CALLBACK(common_cancel_cb), self);
+ g_signal_connect (G_OBJECT (f_priv->close), "clicked",
+ G_CALLBACK(find_cancel_cb), self);
gtk_box_append (GTK_BOX(f_priv->hbox), f_priv->close);
gtk_accessible_update_property (GTK_ACCESSIBLE(f_priv->close),
GTK_ACCESSIBLE_PROPERTY_LABEL,
@@ -829,11 +871,12 @@ find_dialog_grab_focus (GtkWidget *widget)
}
static void
-find_dialog_dispose(GObject *object)
+find_dialog_dispose (GObject *object)
{
FindDialog *self = FIND_DIALOG(object);
FindDialogPrivate *f_priv = find_dialog_get_instance_private (self);
+ g_clear_object (&f_priv->cancellable);
g_clear_pointer (&f_priv->vbox, gtk_widget_unparent);
/* Boilerplate: chain up
diff --git a/src/hex-document.c b/src/hex-document.c
index 16d0c18..1b8e42a 100644
--- a/src/hex-document.c
+++ b/src/hex-document.c
@@ -842,9 +842,9 @@ hex_document_find_forward_async (HexDocument *doc,
find_data->not_found_msg = not_found_msg;
task = g_task_new (doc, cancellable, callback, user_data);
+ g_task_set_return_on_cancel (task, TRUE);
g_task_set_task_data (task, find_data, g_free);
g_task_run_in_thread (task, hex_document_find_forward_thread);
- g_object_unref (task); /* _run_in_thread takes a ref */
}
gboolean
@@ -905,9 +905,9 @@ hex_document_find_backward_async (HexDocument *doc,
find_data->not_found_msg = not_found_msg;
task = g_task_new (doc, cancellable, callback, user_data);
+ g_task_set_return_on_cancel (task, TRUE);
g_task_set_task_data (task, find_data, g_free);
g_task_run_in_thread (task, hex_document_find_backward_thread);
- g_object_unref (task); /* _run_in_thread takes a ref */
}
gboolean
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]