load desktop files in idle time
authorVladimir Nadvornik <nadvornik@suse.cz>
Sun, 6 Sep 2009 14:01:03 +0000 (14:01 +0000)
committerVladimir Nadvornik <nadvornik@suse.cz>
Sun, 6 Sep 2009 14:01:03 +0000 (14:01 +0000)
- scanning all desktop files takes a lot of time because of hdd seek
- this change moves the scanning to idle time
- the editors appears in the menus some time after startup

https://sourceforge.net/tracker/index.php?func=detail&aid=2852522&group_id=222125&atid=1054680

src/desktop_file.c
src/editors.c
src/editors.h
src/layout_util.c
src/layout_util.h
src/main.c
src/rcfile.c

index 0a7ddd0..b6b47db 100644 (file)
@@ -95,7 +95,9 @@ static gboolean editor_window_save(EditorWindow *ew)
        g_free(path);
        g_free(dir);
        g_free(text);
-       layout_editors_reload_all();
+       layout_editors_reload_start();
+       /* idle function is not needed, everything should be cached */
+       layout_editors_reload_finish(); 
        return ret;
 }
 
@@ -290,7 +292,9 @@ static void editor_list_window_delete_dlg_ok_cb(GenericDialog *gd, gpointer data
        else
                {
                /* refresh list */
-               layout_editors_reload_all();
+               layout_editors_reload_start();
+               /* idle function is not needed, everything should be cached */
+               layout_editors_reload_finish(); 
                }
 
        editor_list_window_delete_dlg_cancel(gd, data);
index 31fd05e..f4dc2ac 100644 (file)
@@ -17,6 +17,7 @@
 #include "filedata.h"
 #include "filefilter.h"
 #include "misc.h"
+#include "pixbuf_util.h"
 #include "ui_fileops.h"
 #include "ui_spinner.h"
 #include "ui_utildlg.h"
@@ -69,7 +70,7 @@ static EditorFlags editor_command_done(EditorData *ed);
 
 GHashTable *editors = NULL;
 GtkListStore *desktop_file_list;
-
+gboolean editors_finished = FALSE;
 
 #ifdef G_KEY_FILE_DESKTOP_GROUP
 #define DESKTOP_GROUP G_KEY_FILE_DESKTOP_GROUP
@@ -147,7 +148,7 @@ static GList *editor_mime_types_to_extensions(gchar **mime_types)
        return list;
 }
 
-static gboolean editor_read_desktop_file(const gchar *path)
+gboolean editor_read_desktop_file(const gchar *path)
 {
        GKeyFile *key_file;
        EditorDescription *editor;
@@ -283,6 +284,11 @@ static gboolean editor_read_desktop_file(const gchar *path)
                        *ext = '\0';
                        }
                }
+       if (editor->icon && !register_theme_icon_as_stock(editor->key, editor->icon))
+               {
+               g_free(editor->icon);
+               editor->icon = NULL;
+               }
 
        editor->exec = g_key_file_get_string(key_file, DESKTOP_GROUP, "Exec", NULL);
        
@@ -338,7 +344,31 @@ static gboolean editor_remove_desktop_file_cb(gpointer key, gpointer value, gpoi
        return editor->hidden || editor->ignored;
 }
 
-static void editor_read_desktop_dir(const gchar *path)
+void editor_table_finish(void)
+{
+       g_hash_table_foreach_remove(editors, editor_remove_desktop_file_cb, NULL);
+       editors_finished = TRUE;
+}
+
+void editor_table_clear(void)
+{
+       if (desktop_file_list)
+               {
+               gtk_list_store_clear(desktop_file_list);
+               }
+       else 
+               {
+               desktop_file_list = gtk_list_store_new(DESKTOP_FILE_COLUMN_COUNT, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_BOOLEAN, G_TYPE_BOOLEAN, G_TYPE_STRING);
+               }
+       if (editors)
+               {
+               g_hash_table_destroy(editors);
+               }
+       editors = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, (GDestroyNotify)editor_description_free);
+       editors_finished = FALSE;
+}
+
+static GList *editor_add_desktop_dir(GList *list, const gchar *path)
 {
        DIR *dp;
        struct dirent *dir;
@@ -350,7 +380,7 @@ static void editor_read_desktop_dir(const gchar *path)
        if (!dp)
                {
                /* dir not found */
-               return;
+               return list;
                }
        while ((dir = readdir(dp)) != NULL)
                {
@@ -360,36 +390,23 @@ static void editor_read_desktop_dir(const gchar *path)
                        {
                        gchar *name = path_to_utf8(namel);
                        gchar *dpath = g_build_filename(path, name, NULL);
-                       editor_read_desktop_file(dpath);
-                       g_free(dpath);
+                       list = g_list_prepend(list, dpath);
                        g_free(name);
                        }       
                }
        closedir(dp);
+       return list;
 }
 
-void editor_load_descriptions(void)
+GList *editor_get_desktop_files(void)
 {
        gchar *path;
        gchar *xdg_data_dirs;
        gchar *all_dirs;
        gchar **split_dirs;
        gint i;
+       GList *list = NULL;
        
-       if (desktop_file_list)
-               {
-               gtk_list_store_clear(desktop_file_list);
-               }
-       else 
-               {
-               desktop_file_list = gtk_list_store_new(DESKTOP_FILE_COLUMN_COUNT, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_BOOLEAN, G_TYPE_BOOLEAN, G_TYPE_STRING);
-               }
-       if (editors)
-               {
-               g_hash_table_destroy(editors);
-               }
-       editors = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, (GDestroyNotify)editor_description_free);
-
        xdg_data_dirs = getenv("XDG_DATA_DIRS");
        if (xdg_data_dirs && xdg_data_dirs[0])
                xdg_data_dirs = path_to_utf8(xdg_data_dirs);
@@ -404,16 +421,16 @@ void editor_load_descriptions(void)
        
        g_free(all_dirs);
 
-       for (i = 0; split_dirs[i]; i++)
+       for (i = 0; split_dirs[i]; i++);
+       for (--i; i >= 0; i--)
                {
                path = g_build_filename(split_dirs[i], "applications", NULL);
-               editor_read_desktop_dir(path);
+               list = editor_add_desktop_dir(list, path);
                g_free(path);
                }
                
        g_strfreev(split_dirs);
-       
-       g_hash_table_foreach_remove(editors, editor_remove_desktop_file_cb, NULL);
+       return g_list_reverse(list);
 }
 
 static void editor_list_add_cb(gpointer key, gpointer value, gpointer data)
@@ -446,6 +463,9 @@ static gint editor_sort(gconstpointer a, gconstpointer b)
 GList *editor_list_get(void)
 {
        GList *editors_list = NULL;
+       
+       if (!editors_finished) return NULL;
+       
        g_hash_table_foreach(editors, editor_list_add_cb, &editors_list);
        editors_list = g_list_sort(editors_list, editor_sort);
 
index 1201fc9..f185194 100644 (file)
@@ -78,7 +78,11 @@ extern GtkListStore *desktop_file_list;
 
 extern GHashTable *editors;
 
-void editor_load_descriptions(void);
+void editor_table_finish(void);
+void editor_table_clear(void);
+GList *editor_get_desktop_files(void);
+gboolean editor_read_desktop_file(const gchar *path);
+
 GList *editor_list_get(void);
 
 
index c77c5aa..fbbc5d4 100644 (file)
@@ -1801,6 +1801,11 @@ static void layout_actions_setup_editors(LayoutWindow *lw)
        GList *old_path;
        GString *desc;
        
+       if (lw->action_group_editors)
+               {
+               gtk_ui_manager_remove_action_group(lw->ui_manager, lw->action_group_editors);
+               g_object_unref(lw->action_group_editors);
+               }
        lw->action_group_editors = gtk_action_group_new("MenuActionsExternal");
        gtk_ui_manager_insert_action_group(lw->ui_manager, lw->action_group_editors, 1);
 
@@ -1824,7 +1829,7 @@ static void layout_actions_setup_editors(LayoutWindow *lw)
                                         editor->comment ? editor->comment : editor->name,
                                         G_CALLBACK(layout_menu_edit_cb) };
                
-               if (editor->icon && register_theme_icon_as_stock(editor->key, editor->icon))
+               if (editor->icon)
                        {
                        entry.stock_id = editor->key;
                        }
@@ -1927,11 +1932,56 @@ void layout_actions_setup(LayoutWindow *lw)
        DEBUG_1("%s layout_actions_setup: end", get_exec_time());
 }
 
-void layout_editors_reload_all(void)
+static gint layout_editors_reload_idle_id = -1;
+static GList *layout_editors_desktop_files = NULL;
+
+static gboolean layout_editors_reload_idle_cb(gpointer data)
+{
+       if (!layout_editors_desktop_files)
+               {
+               DEBUG_1("%s layout_editors_reload_idle_cb: get_desktop_files", get_exec_time());
+               layout_editors_desktop_files = editor_get_desktop_files();
+               return TRUE;
+               }
+       
+       editor_read_desktop_file(layout_editors_desktop_files->data);
+       g_free(layout_editors_desktop_files->data);
+       layout_editors_desktop_files = g_list_delete_link(layout_editors_desktop_files, layout_editors_desktop_files);
+       
+       
+       if (!layout_editors_desktop_files)
+               {
+               GList *work;
+               DEBUG_1("%s layout_editors_reload_idle_cb: setup_editors", get_exec_time());
+               editor_table_finish();
+
+               work = layout_window_list;
+               while (work)
+                       {
+                       LayoutWindow *lw = work->data;
+                       work = work->next;
+                       layout_actions_setup_editors(lw);
+                       }
+
+               DEBUG_1("%s layout_editors_reload_idle_cb: setup_editors done", get_exec_time());
+               
+               layout_editors_reload_idle_id = -1;
+               return FALSE;
+               }
+       return TRUE;
+}
+
+void layout_editors_reload_start(void)
 {
        GList *work;
 
-       DEBUG_1("%s layout_editors_reload_all: start", get_exec_time());
+       DEBUG_1("%s layout_editors_reload_start", get_exec_time());
+
+       if (layout_editors_reload_idle_id != -1)
+               {
+               g_source_remove(layout_editors_reload_idle_id);
+               string_list_free(layout_editors_desktop_files);
+               }
 
        work = layout_window_list;
        while (work)
@@ -1942,20 +1992,23 @@ void layout_editors_reload_all(void)
                gtk_ui_manager_remove_ui(lw->ui_manager, lw->ui_editors_id);
                gtk_ui_manager_remove_action_group(lw->ui_manager, lw->action_group_editors);
                g_object_unref(lw->action_group_editors);
+               lw->action_group_editors = NULL;
                }
+       editor_table_clear();
+       layout_editors_reload_idle_id = g_idle_add(layout_editors_reload_idle_cb, NULL);
+}
        
-       DEBUG_1("%s layout_editors_reload_all: editor_load_descriptions", get_exec_time());
-       editor_load_descriptions();
-       
-       DEBUG_1("%s layout_editors_reload_all: setup_editors", get_exec_time());
-       work = layout_window_list;
-       while (work)
+void layout_editors_reload_finish(void)
+{
+       if (layout_editors_reload_idle_id != -1)
                {
-               LayoutWindow *lw = work->data;
-               work = work->next;
-               layout_actions_setup_editors(lw);
+               DEBUG_1("%s layout_editors_reload_finish", get_exec_time());
+               g_source_remove(layout_editors_reload_idle_id);
+               while (layout_editors_reload_idle_id != -1)
+                       {
+                       layout_editors_reload_idle_cb(NULL);
+                       }
                }
-       DEBUG_1("%s layout_editors_reload_all: end", get_exec_time());
 }
 
 void layout_actions_add_window(LayoutWindow *lw, GtkWidget *window)
@@ -2032,6 +2085,29 @@ void layout_toolbar_add(LayoutWindow *lw, ToolbarType type, const gchar *action)
                        break;
                }
        
+       
+       if (g_str_has_suffix(action, ".desktop"))
+               {
+               /* this may be called before the external editors are read
+                  create a dummy action for now */
+                 
+               if (!lw->action_group_editors)
+                       {
+                       lw->action_group_editors = gtk_action_group_new("MenuActionsExternal");
+                       gtk_ui_manager_insert_action_group(lw->ui_manager, lw->action_group_editors, 1);
+                       }
+               if (!gtk_action_group_get_action(lw->action_group_editors, action))
+                       {
+                       GtkActionEntry entry = { action, 
+                                                GTK_STOCK_MISSING_IMAGE,
+                                                action,
+                                                NULL, 
+                                                NULL,
+                                                NULL };
+                       DEBUG_1("Creating temporary action %s", action);
+                       gtk_action_group_add_actions(lw->action_group_editors, &entry, 1, lw);
+                       }
+               }
        gtk_ui_manager_add_ui(lw->ui_manager, lw->toolbar_merge_id[type], path, action, action, GTK_UI_MANAGER_TOOLITEM, FALSE); 
        lw->toolbar_actions[type] = g_list_append(lw->toolbar_actions[type], g_strdup(action));
 }
index 5d82d5f..bec469b 100644 (file)
@@ -33,7 +33,8 @@ void layout_recent_add_path(const gchar *path);
 
 void layout_copy_path_update_all(void);
 
-void layout_editors_reload_all(void);
+void layout_editors_reload_start(void);
+void layout_editors_reload_finish(void);
 void layout_actions_setup(LayoutWindow *lw);
 void layout_actions_add_window(LayoutWindow *lw, GtkWidget *window);
 GtkWidget *layout_actions_menu_bar(LayoutWindow *lw);
index cdcba1c..6b6456c 100644 (file)
@@ -31,6 +31,7 @@
 #include "image-overlay.h"
 #include "layout.h"
 #include "layout_image.h"
+#include "layout_util.h"
 #include "options.h"
 #include "remote.h"
 #include "secure_save.h"
@@ -605,6 +606,9 @@ static void exit_program_final(void)
 {
        LayoutWindow *lw = NULL;
 
+        /* make sure that external editors are loaded, we would save incomplete configuration otherwise */
+       layout_editors_reload_finish();
+
        remote_close(remote_connection);
 
        collect_manager_flush();
@@ -816,8 +820,6 @@ gint main(gint argc, gchar *argv[])
                /* load_options calls these functions after it parses global options, we have to call it here if it fails */
                filter_add_defaults();
                filter_rebuild(); 
-
-               editor_load_descriptions();
                }
 
        /* handle missing config file and commandline additions*/
@@ -827,6 +829,8 @@ gint main(gint argc, gchar *argv[])
                layout_new_from_config(NULL, NULL, TRUE);
                }
 
+       layout_editors_reload_start();
+
        if (command_line->collection_list && !command_line->startup_command_line_collection)
                {
                GList *work;
index bf20987..4053b58 100644 (file)
@@ -884,9 +884,6 @@ static void options_parse_global_end(GQParserData *parser_data, GMarkupParseCont
        options->metadata.write_orientation = FALSE;
        DEBUG_1("compiled without Exiv2 - disabling XMP write support");
 #endif
-
-       /* on startup there are no layout windows and this just loads the editors */
-       layout_editors_reload_all();
 }
 
 static void options_parse_pane_exif(GQParserData *parser_data, GMarkupParseContext *context, const gchar *element_name, const gchar **attribute_names, const gchar **attribute_values, gpointer data, GError **error)