[yelp] Fix up issues with reload, including reloading on theme change



commit afc64af7b6a3f02a4f10c323b21d3aea48227d99
Author: Shaun McCance <shaunm gnome org>
Date:   Tue Jan 11 11:56:35 2022 -0500

    Fix up issues with reload, including reloading on theme change
    
    Addresses part of https://gitlab.gnome.org/GNOME/yelp/-/issues/188

 libyelp/yelp-docbook-document.c |  8 +++++-
 libyelp/yelp-help-list.c        | 63 +++++++++++++++++++++++++++++++++++++----
 libyelp/yelp-mallard-document.c | 36 +++++++++++++++++++++--
 libyelp/yelp-view.c             | 15 ++++++++++
 4 files changed, 112 insertions(+), 10 deletions(-)
---
diff --git a/libyelp/yelp-docbook-document.c b/libyelp/yelp-docbook-document.c
index 18d05611..a511e9f4 100644
--- a/libyelp/yelp-docbook-document.c
+++ b/libyelp/yelp-docbook-document.c
@@ -228,7 +228,7 @@ yelp_docbook_document_new (YelpUri *uri)
         GFile *file;
         file = g_file_new_for_path (path[path_i]);
         priv->monitors[path_i] = g_file_monitor (file,
-                                                 G_FILE_MONITOR_SEND_MOVED,
+                                                 G_FILE_MONITOR_WATCH_MOVES,
                                                  NULL, NULL);
         g_signal_connect (priv->monitors[path_i], "changed",
                           G_CALLBACK (docbook_monitor_changed),
@@ -236,6 +236,12 @@ yelp_docbook_document_new (YelpUri *uri)
         g_object_unref (file);
     }
     g_strfreev (path);
+
+    g_signal_connect_swapped (yelp_settings_get_default (),
+                              "colors-changed",
+                              G_CALLBACK (docbook_reload),
+                              docbook);
+
     return (YelpDocument *) docbook;
 }
 
diff --git a/libyelp/yelp-help-list.c b/libyelp/yelp-help-list.c
index 9860d713..03cfeb26 100644
--- a/libyelp/yelp-help-list.c
+++ b/libyelp/yelp-help-list.c
@@ -49,6 +49,7 @@ static gboolean       help_list_request_page         (YelpDocument          *doc
                                                       gpointer               user_data,
                                                       GDestroyNotify         notify);
 static void           help_list_think                (YelpHelpList          *list);
+static void           help_list_reload               (YelpHelpList          *list);
 static void           help_list_handle_page          (YelpHelpList          *list,
                                                       const gchar           *page_id);
 static void           help_list_process_docbook      (YelpHelpList          *list,
@@ -128,8 +129,9 @@ yelp_help_list_init (YelpHelpList *list)
     YelpHelpListPrivate *priv = yelp_help_list_get_instance_private (list);
 
     g_mutex_init (&priv->mutex);
+    /* don't free the key, it belongs to the value struct */
     priv->entries = g_hash_table_new_full (g_str_hash, g_str_equal,
-                                           g_free,
+                                           NULL,
                                            (GDestroyNotify) help_list_entry_free);
 
     priv->get_docbook_title = xmlXPathCompile (BAD_CAST "normalize-space("
@@ -157,6 +159,8 @@ yelp_help_list_finalize (GObject *object)
 {
     YelpHelpListPrivate *priv = yelp_help_list_get_instance_private (YELP_HELP_LIST (object));
 
+    /* entry structs belong to hash table */
+    g_list_free (priv->all_entries);
     g_hash_table_destroy (priv->entries);
     g_mutex_clear (&priv->mutex);
 
@@ -180,7 +184,14 @@ yelp_help_list_finalize (GObject *object)
 YelpDocument *
 yelp_help_list_new (YelpUri *uri)
 {
-    return g_object_new (YELP_TYPE_HELP_LIST, NULL);
+    YelpHelpList *helplist = g_object_new (YELP_TYPE_HELP_LIST, NULL);
+
+    g_signal_connect_swapped (yelp_settings_get_default (),
+                              "colors-changed",
+                              G_CALLBACK (help_list_reload),
+                              helplist);
+
+    return (YelpDocument *) helplist;
 }
 
 /******************************************************************************/
@@ -285,7 +296,7 @@ help_list_think (YelpHelpList *list)
                                              NULL);
                 if (g_file_test (filename, G_FILE_TEST_IS_REGULAR)) {
                     entry = g_new0 (HelpListEntry, 1);
-                    entry->id = g_strdup (docid);
+                    entry->id = docid;
                     entry->filename = filename;
                     entry->type = YELP_URI_DOCUMENT_TYPE_MALLARD;
                     break;
@@ -301,7 +312,7 @@ help_list_think (YelpHelpList *list)
                 g_free (tmp);
                 if (g_file_test (filename, G_FILE_TEST_IS_REGULAR)) {
                     entry = g_new0 (HelpListEntry, 1);
-                    entry->id = g_strdup (docid);
+                    entry->id = docid;
                     entry->filename = filename;
                     entry->type = YELP_URI_DOCUMENT_TYPE_DOCBOOK;
                     break;
@@ -313,8 +324,9 @@ help_list_think (YelpHelpList *list)
                 g_hash_table_insert (priv->entries, docid, entry);
                 priv->all_entries = g_list_prepend (priv->all_entries, entry);
             }
-            else
+            else {
                 g_free (docid);
+            }
             g_object_unref (child);
         }
         g_object_unref (children);
@@ -376,13 +388,15 @@ help_list_think (YelpHelpList *list)
                 }
                 g_free (filename);
 
-                g_free (docid);
             found:
                 g_object_unref (child);
                 if (entry != NULL) {
                     g_hash_table_insert (priv->entries, docid, entry);
                     priv->all_entries = g_list_prepend (priv->all_entries, entry);
                 }
+                else {
+                    g_free (docid);
+                }
             }
 
             g_object_unref (children);
@@ -452,6 +466,43 @@ help_list_think (YelpHelpList *list)
 }
 
 
+static void
+help_list_reload (YelpHelpList *list)
+{
+    YelpHelpListPrivate *priv = yelp_help_list_get_instance_private (list);
+    gchar **ids;
+    gint i;
+
+    if (priv->process_running)
+        return;
+
+    g_mutex_lock (&priv->mutex);
+
+    ids = yelp_document_get_requests (YELP_DOCUMENT (list));
+    for (i = 0; ids[i]; i++) {
+        priv->pending = g_slist_prepend (priv->pending, ids[i]);
+    }
+    g_free (ids);
+
+    /* entry structs belong to hash table */
+    g_list_free (priv->all_entries);
+    priv->all_entries = NULL;
+    g_hash_table_remove_all (priv->entries);
+
+    yelp_document_clear_contents (YELP_DOCUMENT (list));
+
+    priv->process_ran = FALSE;
+    priv->process_running = TRUE;
+
+    g_object_ref (list);
+    priv->thread = g_thread_new ("helplist-page",
+                                 (GThreadFunc)(GCallback) help_list_think,
+                                 list);
+
+    g_mutex_unlock (&priv->mutex);
+}
+
+
 static void
 transform_chunk_ready (YelpTransform   *transform,
                        gchar           *chunk_id,
diff --git a/libyelp/yelp-mallard-document.c b/libyelp/yelp-mallard-document.c
index 6a5b643c..435ec519 100644
--- a/libyelp/yelp-mallard-document.c
+++ b/libyelp/yelp-mallard-document.c
@@ -103,6 +103,7 @@ static void           mallard_page_data_info    (MallardPageData      *page_data
                                                  xmlNodePtr            cache_node);
 static void           mallard_page_data_run     (MallardPageData      *page_data);
 static void           mallard_page_data_free    (MallardPageData      *page_data);
+static void           mallard_reload            (YelpMallardDocument  *mallard);
 static void           mallard_monitor_changed   (GFileMonitor         *monitor,
                                                  GFile                *file,
                                                  GFile                *other_file,
@@ -238,7 +239,7 @@ yelp_mallard_document_new (YelpUri *uri)
         GFile *file;
         file = g_file_new_for_path (path[path_i]);
         priv->monitors[path_i] = g_file_monitor (file,
-                                                 G_FILE_MONITOR_SEND_MOVED,
+                                                 G_FILE_MONITOR_WATCH_MOVES,
                                                  NULL, NULL);
         g_signal_connect (priv->monitors[path_i], "changed",
                           G_CALLBACK (mallard_monitor_changed),
@@ -247,6 +248,11 @@ yelp_mallard_document_new (YelpUri *uri)
     }
     g_strfreev (path);
 
+    g_signal_connect_swapped (yelp_settings_get_default (),
+                              "colors-changed",
+                              G_CALLBACK (mallard_reload),
+                              mallard);
+
     return (YelpDocument *) mallard;
 }
 
@@ -364,8 +370,15 @@ mallard_think (YelpMallardDocument *mallard)
             GFile *pagefile;
             filename = g_file_info_get_attribute_as_string (pageinfo,
                                                             G_FILE_ATTRIBUTE_STANDARD_NAME);
-            if (!g_str_has_suffix (filename, ".page") &&
-                !(editor_mode && g_str_has_suffix (filename, ".page.stub"))) {
+            /* Only .page files, or .page.stub files in editor mode.
+               Also, filenames with # really mess things up, and emacs
+               creates them in the background all the time.
+               FIXME: Let's add support for .stack files.
+             */
+            if (strchr(filename, '#') ||
+                ( !g_str_has_suffix (filename, ".page") &&
+                  !(editor_mode && g_str_has_suffix (filename, ".page.stub"))
+                  )) {
                 g_free (filename);
                 g_object_unref (pageinfo);
                 continue;
@@ -1140,6 +1153,23 @@ mallard_monitor_changed (GFileMonitor         *monitor,
                          GFile                *other_file,
                          GFileMonitorEvent     event_type,
                          YelpMallardDocument  *mallard)
+{
+    char *filename;
+
+    if (file) {
+        filename = g_file_get_path (file);
+        if (strchr(filename, '#')) {
+            /* ignore emacs tmp files that mess up our uri handling anyway */
+            g_free (filename);
+            return;
+        }
+        g_free (filename);
+        mallard_reload (mallard);
+    }
+}
+
+static void
+mallard_reload (YelpMallardDocument *mallard)
 {
     gchar **ids;
     gint i;
diff --git a/libyelp/yelp-view.c b/libyelp/yelp-view.c
index d4810fa5..32ae131e 100644
--- a/libyelp/yelp-view.c
+++ b/libyelp/yelp-view.c
@@ -176,6 +176,7 @@ struct _RequestAsyncData {
     WebKitURISchemeRequest *request;
     GFile *resource_file;
     gchar *page_id;
+    gboolean finished;
 };
 
 static RequestAsyncData *
@@ -186,6 +187,7 @@ request_async_data_new (WebKitURISchemeRequest *request, gchar *page_id)
     data = g_slice_new0 (RequestAsyncData);
     data->request = g_object_ref (request);
     data->page_id = g_strdup (page_id);
+    data->finished = FALSE;
     return data;
 }
 
@@ -771,7 +773,19 @@ document_callback (YelpDocument       *document,
     if (signal == YELP_DOCUMENT_SIGNAL_INFO)
         return;
 
+    if (data->finished) {
+        /* If this is set, this callback is because YelpDocument refreshed
+           the page, such as when a file changes. WebKit doesn't like us
+           to reuse the request object, so we do a fresh load.
+         */
+        YelpView *view = YELP_VIEW (webkit_uri_scheme_request_get_web_view (data->request));
+        YelpViewPrivate *priv = yelp_view_get_instance_private (view);
+        yelp_view_load_uri (view, priv->uri);
+        return;
+    }
+
     if (signal == YELP_DOCUMENT_SIGNAL_ERROR) {
+        data->finished = TRUE;
         webkit_uri_scheme_request_finish_error (data->request, error);
         return;
     }
@@ -786,6 +800,7 @@ document_callback (YelpDocument       *document,
         stream = g_memory_input_stream_new_from_data (g_strdup (contents), content_length, g_free);
         yelp_document_finish_read (document, contents);
 
+        data->finished = TRUE;
         webkit_uri_scheme_request_finish (data->request,
                                           stream,
                                           content_length,


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