diff --git a/src/sdgui.c b/src/sdgui.c index 81d17db..993d1f5 100644 --- a/src/sdgui.c +++ b/src/sdgui.c @@ -42,6 +42,8 @@ static struct gint last; ///< The last dictionary index GPtrArray *dictionaries; ///< All open dictionaries + gboolean loading; ///< Dictionaries are being loaded + gboolean watch_selection; ///< Following X11 PRIMARY? } g; @@ -49,19 +51,19 @@ g; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - static void -init (gchar **filenames) +load_from_filenames (GPtrArray *out, gchar **filenames) { for (gsize i = 0; filenames[i]; i++) { Dictionary *dict = g_malloc0 (sizeof *dict); dict->filename = g_strdup (filenames[i]); - g_ptr_array_add (g.dictionaries, dict); + g_ptr_array_add (out, dict); } } // TODO: try to deduplicate, similar to app_load_config_values() static gboolean -init_from_key_file (GKeyFile *kf, GError **error) +load_from_key_file (GPtrArray *out, GKeyFile *kf, GError **error) { const gchar *dictionaries = "Dictionaries"; gchar **names = g_key_file_get_keys (kf, dictionaries, NULL, NULL); @@ -72,13 +74,13 @@ init_from_key_file (GKeyFile *kf, GError **error) { Dictionary *dict = g_malloc0 (sizeof *dict); dict->name = names[i]; - g_ptr_array_add (g.dictionaries, dict); + g_ptr_array_add (out, dict); } g_free (names); - for (gsize i = 0; i < g.dictionaries->len; i++) + for (gsize i = 0; i < out->len; i++) { - Dictionary *dict = g_ptr_array_index (g.dictionaries, i); + Dictionary *dict = g_ptr_array_index (out, i); gchar *path = g_key_file_get_string (kf, dictionaries, dict->name, error); if (!path) @@ -95,13 +97,13 @@ init_from_key_file (GKeyFile *kf, GError **error) } static gboolean -init_from_config (GError **error) +load_from_config (GPtrArray *out, GError **error) { GKeyFile *key_file = load_project_config_file (error); if (!key_file) return FALSE; - gboolean result = init_from_key_file (key_file, error); + gboolean result = load_from_key_file (out, key_file, error); g_key_file_free (key_file); return result; } @@ -111,6 +113,8 @@ search (Dictionary *dict) { GtkEntryBuffer *buf = gtk_entry_get_buffer (GTK_ENTRY (g.entry)); const gchar *input_utf8 = gtk_entry_buffer_get_text (buf); + if (!dict->dict) + return; StardictIterator *iterator = stardict_dict_search (dict->dict, input_utf8, NULL); @@ -295,20 +299,68 @@ show_error_dialog (GError *error) g_error_free (error); } -static gboolean -reload_dictionaries (GPtrArray *new_dictionaries, GError **error) +static void +on_new_dictionaries_loaded (G_GNUC_UNUSED GObject* source_object, + GAsyncResult* res, G_GNUC_UNUSED gpointer user_data) { - if (!load_dictionaries (new_dictionaries, error)) - return FALSE; + g.loading = FALSE; + + GError *error = NULL; + GPtrArray *new_dictionaries = + g_task_propagate_pointer (G_TASK (res), &error); + if (!new_dictionaries) + { + show_error_dialog (error); + return; + } while (gtk_notebook_get_n_pages (GTK_NOTEBOOK (g.notebook))) gtk_notebook_remove_page (GTK_NOTEBOOK (g.notebook), -1); g.dictionary = -1; + if (g.dictionaries) + g_ptr_array_free (g.dictionaries, TRUE); + stardict_view_set_position (STARDICT_VIEW (g.view), NULL, 0); - g_ptr_array_free (g.dictionaries, TRUE); g.dictionaries = new_dictionaries; init_tabs (); +} + +static void +on_reload_dictionaries_task (GTask *task, G_GNUC_UNUSED gpointer source_object, + gpointer task_data, G_GNUC_UNUSED GCancellable *cancellable) +{ + GError *error = NULL; + if (load_dictionaries (task_data, &error)) + { + g_task_return_pointer (task, + g_ptr_array_ref (task_data), (GDestroyNotify) g_ptr_array_unref); + } + else + g_task_return_error (task, error); +} + +static gboolean +reload_dictionaries (GPtrArray *new_dictionaries, GError **error) +{ + // TODO: We could cancel that task. + if (g.loading) + { + g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, + "already loading dictionaries"); + return FALSE; + } + + // TODO: Some other kind of indication. + // Note that "action widgets" aren't visible without GtkNotebook tabs. + g.loading = TRUE; + + GTask *task = g_task_new (NULL, NULL, on_new_dictionaries_loaded, NULL); + g_task_set_name (task, __func__); + g_task_set_task_data (task, + new_dictionaries, (GDestroyNotify) g_ptr_array_unref); + g_task_run_in_thread (task, on_reload_dictionaries_task); + g_object_unref (task); return TRUE; } @@ -429,19 +481,19 @@ main (int argc, char *argv[]) gtk_window_set_default_icon_name (PROJECT_NAME); - g.dictionaries = + GPtrArray *new_dictionaries = g_ptr_array_new_with_free_func ((GDestroyNotify) dictionary_destroy); if (filenames) - init (filenames); - else if (!init_from_config (&error) && error) + { + load_from_filenames (new_dictionaries, filenames); + g_strfreev (filenames); + } + else if (!load_from_config (new_dictionaries, &error) && error) die_with_dialog (error->message); - g_strfreev (filenames); - if (!g.dictionaries->len) + if (!new_dictionaries->len) die_with_dialog (_("No dictionaries found either in " "the configuration or on the command line")); - if (!load_dictionaries (g.dictionaries, &error)) - die_with_dialog (error->message); // Some Adwaita stupidity, plus defaults for our own widget. // All the named colours have been there since GNOME 3.4 @@ -530,7 +582,6 @@ main (int argc, char *argv[]) g.view = stardict_view_new (); gtk_box_pack_end (GTK_BOX (superbox), g.view, TRUE, TRUE, 0); - init_tabs (); GtkClipboard *clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY); g_signal_connect (clipboard, "owner-change", @@ -544,6 +595,9 @@ main (int argc, char *argv[]) g_signal_connect (g.view, "send", G_CALLBACK (on_send), NULL); + if (!reload_dictionaries (new_dictionaries, &error)) + die_with_dialog (error->message); + gtk_widget_show_all (g.window); gtk_main (); return 0; diff --git a/src/utils.c b/src/utils.c index 6a32bda..5542202 100644 --- a/src/utils.c +++ b/src/utils.c @@ -269,7 +269,6 @@ load_dictionaries_sequentially (GPtrArray *dictionaries, GError **e) } // Parallelize dictionary loading if possible, because of collation reindexing -#if GLIB_CHECK_VERSION (2, 36, 0) static void load_worker (gpointer data, gpointer user_data) { @@ -304,10 +303,3 @@ load_dictionaries (GPtrArray *dictionaries, GError **e) g_async_queue_unref (error_queue); return result; } -#else // GLib < 2.36 -gboolean -load_dictionaries (GPtrArray *dictionaries, GError **e) -{ - return load_dictionaries_sequentially (dictionaries, e); -} -#endif // GLib < 2.36