Enlightenment CVS committal

Author  : englebass
Project : e17
Module  : libs/efreet

Dir     : e17/libs/efreet/src/lib


Modified Files:
        efreet_utils.c efreet_utils.h 


Log Message:
Add caching for system .desktop files.

===================================================================
RCS file: /cvs/e/e17/libs/efreet/src/lib/efreet_utils.c,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -3 -r1.6 -r1.7
--- efreet_utils.c      25 Mar 2007 10:49:04 -0000      1.6
+++ efreet_utils.c      25 Mar 2007 12:47:59 -0000      1.7
@@ -2,15 +2,80 @@
 #include "Efreet.h"
 #include "efreet_private.h"
 
+typedef struct _Efreet_Cache_Fill     Efreet_Cache_Fill;
+typedef struct _Efreet_Cache_Fill_Dir Efreet_Cache_Fill_Dir;
+
+struct _Efreet_Cache_Fill
+{
+    Ecore_List            *dirs;
+    Efreet_Cache_Fill_Dir *current;
+    DIR  *files;
+};
+
+struct _Efreet_Cache_Fill_Dir
+{
+    char *path;
+    char *file_id;
+};
+
+static int  _efreet_util_cache_fill(void *data);
+static void _efreet_util_cache_dir_free(void *data);
+
+static Ecore_Hash *desktop_by_file_id = NULL;
+static Ecore_Hash *desktop_by_exec = NULL;
+static Ecore_Hash *file_id_by_desktop_path = NULL;
+
+static Ecore_Idler *idler = NULL;
+
 int
 efreet_util_init(void)
 {
+    Efreet_Cache_Fill *fill;
+    Ecore_List *dirs;
+
+    desktop_by_file_id = ecore_hash_new(ecore_str_hash, ecore_str_compare);
+    ecore_hash_set_free_key(desktop_by_file_id, 
ECORE_FREE_CB(ecore_string_release));
+    desktop_by_exec = ecore_hash_new(ecore_str_hash, ecore_str_compare);
+    file_id_by_desktop_path = ecore_hash_new(ecore_str_hash, 
ecore_str_compare);
+
+    fill = NEW(Efreet_Cache_Fill, 1);
+    fill->dirs = ecore_list_new();
+    ecore_list_set_free_cb(fill->dirs, _efreet_util_cache_dir_free);
+    dirs = efreet_default_dirs_get(efreet_data_home_get(), 
efreet_data_dirs_get(),
+                                                                    
"applications");
+    if (dirs)
+    {
+        Efreet_Cache_Fill_Dir *dir;
+        char *path;
+
+        while ((path = ecore_list_remove_first(dirs)))
+        {
+            dir = NEW(Efreet_Cache_Fill_Dir, 1);
+            dir->path = path;
+            ecore_list_append(fill->dirs, dir);
+        }
+        ecore_list_destroy(dirs);
+        ecore_list_goto_first(fill->dirs);
+    }
+    idler = ecore_idler_add(_efreet_util_cache_fill, fill);
     return 1;
 }
 
 void
 efreet_util_shutdown(void)
 {
+    if (idler)
+    {
+        Efreet_Cache_Fill *fill;
+        fill = ecore_idler_del(idler);
+        IF_FREE_LIST(fill->dirs);
+        free(fill);
+    }
+    idler = NULL;
+
+    IF_FREE_HASH(desktop_by_file_id);
+    IF_FREE_HASH(desktop_by_exec);
+    IF_FREE_HASH(file_id_by_desktop_path);
 }
 
 char *
@@ -44,10 +109,13 @@
 efreet_util_path_to_file_id(const char *path)
 {
     size_t len;
-    char *id, *p;
+    char *file_id, *p;
     char *base;
 
     if (!path) return NULL;
+    file_id = ecore_hash_get(file_id_by_desktop_path, path);
+    if (file_id) return file_id;
+
     base = efreet_util_path_in_default("applications", path);
     if (!base) return NULL;
 
@@ -63,15 +131,17 @@
         return NULL;
     }
 
-    id = strdup(path + len + 1);
-    p = id;
+    file_id = strdup(path + len + 1);
+    p = file_id;
     while (*p)
     {
         if (*p == '/') *p = '-';
         p++;
     }
     free(base);
-    return id;
+    if (file_id) ecore_hash_set(file_id_by_desktop_path, (void 
*)ecore_string_instance(path),
+                                                        (void 
*)ecore_string_instance(file_id));
+    return file_id;
 }
 
 Efreet_Desktop *
@@ -82,6 +152,9 @@
     const char *dir;
 
     if (!file_id) return NULL;
+    desktop = ecore_hash_get(desktop_by_file_id, file_id);
+    if (desktop) return desktop;
+    desktop = NULL;
 
     dirs = efreet_default_dirs_get(efreet_data_home_get(), 
efreet_data_dirs_get(),
                                                                     
"applications");
@@ -108,5 +181,146 @@
         if (desktop) break;
     }
     ecore_list_destroy(dirs);
+    if (desktop) ecore_hash_set(desktop_by_file_id, (void 
*)ecore_string_instance(file_id), desktop);
     return desktop;
+}
+
+Efreet_Desktop *
+efreet_util_desktop_by_exec_get(const char *exec)
+{
+    Efreet_Desktop *desktop = NULL;
+
+    if (!exec) return NULL;
+    desktop = ecore_hash_get(desktop_by_exec, exec);
+    if (desktop) return desktop;
+    desktop = NULL;
+
+    /* TODO: Try to search for the .desktop file. But if it isn't in the cache 
it will be
+     * timeconsuming.*/
+
+    if (desktop) ecore_hash_set(desktop_by_exec, (void 
*)ecore_string_instance(exec), desktop);
+    return NULL;
+}
+
+#if 0
+static void
+dump(void *value, void *data __UNUSED__)
+{
+    Ecore_Hash_Node *node;
+    node = value;
+    printf("%s -> %p\n", (char *)node->key, node->value);
+}
+#endif
+
+static int
+_efreet_util_cache_fill(void *data)
+{
+    Efreet_Cache_Fill *fill;
+    struct dirent *file = NULL;
+    double start;
+    char buf[PATH_MAX];
+
+    fill = data;
+    if (!fill->dirs)
+    {
+        free(fill);
+        idler = NULL;
+        return 0;
+    }
+    if (!fill->current)
+    {
+        fill->current = ecore_list_remove_first(fill->dirs);
+        if (!fill->current)
+        {
+            IF_FREE_LIST(fill->dirs);
+            free(fill);
+            idler = NULL;
+#if 0
+            ecore_hash_for_each_node(desktop_by_file_id, dump, NULL);
+            ecore_hash_for_each_node(desktop_by_exec, dump, NULL);
+            ecore_hash_for_each_node(file_id_by_desktop_path, dump, NULL);
+            printf("%d\n", ecore_hash_count(desktop_by_file_id));
+#endif
+            return 0;
+        }
+    }
+
+    start = ecore_time_get();
+    if (!fill->files) fill->files = opendir(fill->current->path);
+    if (!fill->files)
+    {
+        /* Couldn't open this dir, continue to next */
+        fill->current = NULL;
+    }
+    else
+    {
+        while ((ecore_time_get() - start) < 0.01)
+        {
+            char file_id[PATH_MAX];
+
+            file = readdir(fill->files);
+            if (!file) break;
+            if (!strcmp(file->d_name, ".") || !strcmp(file->d_name, "..")) 
continue;
+
+            snprintf(buf, PATH_MAX, "%s/%s", fill->current->path, 
file->d_name);
+            if (fill->current->file_id)
+                snprintf(file_id, PATH_MAX, "%s-%s", fill->current->file_id, 
file->d_name);
+            else
+                strcpy(file_id, file->d_name);
+
+            if (ecore_file_is_dir(buf))
+            {
+                Efreet_Cache_Fill_Dir *dir;
+
+                dir = NEW(Efreet_Cache_Fill_Dir, 1);
+                dir->path = strdup(buf);
+                dir->file_id = strdup(file_id);
+                ecore_list_append(fill->dirs, dir);
+            }
+            else
+            {
+                Efreet_Desktop *desktop;
+                char *ext;
+                char *exec;
+
+                ext = strrchr(buf, '.');
+                if (!ext || strcmp(ext, ".desktop")) continue;
+                desktop = efreet_desktop_get(buf);
+
+                if (!desktop || desktop->type != 
EFREET_DESKTOP_TYPE_APPLICATION) continue;
+                ecore_hash_set(desktop_by_file_id, (void 
*)ecore_string_instance(file_id), desktop);
+                exec = ecore_file_app_exe_get(desktop->exec);
+                if (exec)
+                {
+                    /* TODO: exec can be with and without full path, we should 
handle that */
+                    ecore_hash_set(desktop_by_exec, (void 
*)ecore_string_instance(exec), desktop);
+                    free(exec);
+                }
+                ecore_hash_set(file_id_by_desktop_path,
+                        (void *)ecore_string_instance(desktop->orig_path),
+                        (void *)ecore_string_instance(file_id));
+            }
+        }
+        if (!file)
+        {
+            /* This dir has been search through */
+            _efreet_util_cache_dir_free(fill->current);
+            fill->current = NULL;
+            closedir(fill->files);
+            fill->files = NULL;
+        }
+    }
+
+    return 1;
+}
+
+static void
+_efreet_util_cache_dir_free(void *data)
+{
+    Efreet_Cache_Fill_Dir *dir;
+
+    dir = data;
+    IF_FREE(dir->path);
+    IF_FREE(dir->file_id);
+    free(dir);
 }
===================================================================
RCS file: /cvs/e/e17/libs/efreet/src/lib/efreet_utils.h,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -3 -r1.4 -r1.5
--- efreet_utils.h      25 Mar 2007 10:49:04 -0000      1.4
+++ efreet_utils.h      25 Mar 2007 12:47:59 -0000      1.5
@@ -5,5 +5,6 @@
 char           *efreet_util_path_in_default(const char *section, const char 
*path);
 char           *efreet_util_path_to_file_id(const char *path);
 Efreet_Desktop *efreet_util_desktop_by_file_id_get(const char *file_id);
+Efreet_Desktop *efreet_util_desktop_by_exec_get(const char *exec);
 
 #endif



-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys-and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
_______________________________________________
enlightenment-cvs mailing list
enlightenment-cvs@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/enlightenment-cvs

Reply via email to