From afc64af7b6a3f02a4f10c323b21d3aea48227d99 Mon Sep 17 00:00:00 2001 From: Shaun McCance Date: Tue, 11 Jan 2022 11:56:35 -0500 Subject: 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, -- cgit v1.2.1