efreet: Implement fields added by desktop spec 1.1
authorSebastian Dransfeld <sd@tango.flipp.net>
Thu, 25 Sep 2014 06:47:18 +0000 (08:47 +0200)
committerSebastian Dransfeld <sd@tango.flipp.net>
Thu, 25 Sep 2014 06:47:45 +0000 (08:47 +0200)
src/bin/efreet/efreet_desktop_cache_create.c
src/lib/efreet/efreet_cache.c
src/lib/efreet/efreet_cache_private.h
src/lib/efreet/efreet_desktop.c
src/lib/efreet/efreet_desktop.h

index ff0a106..4fa3ef4 100644 (file)
@@ -40,6 +40,7 @@ static Eina_Hash *generic_name = NULL;
 static Eina_Hash *comment = NULL;
 static Eina_Hash *exec = NULL;
 static Eina_Hash *environments = NULL;
+static Eina_Hash *keywords = NULL;
 
 static int
 cache_add(const char *path, const char *file_id, int priority EINA_UNUSED, int *changed)
@@ -112,6 +113,7 @@ cache_add(const char *path, const char *file_id, int priority EINA_UNUSED, int *
             array->array[array->array_count++] = desk->orig_path; \
             eina_hash_set((hash), data, array); \
         }
+        /* Desktop Spec 1.0 */
         ADD_LIST(desk->mime_types, mime_types);
         ADD_LIST(desk->categories, categories);
         ADD_ELEM(desk->startup_wm_class, startup_wm_class);
@@ -123,6 +125,8 @@ cache_add(const char *path, const char *file_id, int priority EINA_UNUSED, int *
         ADD_LIST(desk->not_show_in, environments);
         eina_hash_add(file_ids, file_id, desk->orig_path);
         eina_hash_add(desktops, desk->orig_path, desk);
+        /* Desktop Spec 1.1 */
+        ADD_LIST(desk->keywords, keywords);
     }
     else
         efreet_desktop_free(desk);
@@ -388,6 +392,7 @@ main(int argc, char **argv)
     comment = eina_hash_string_superfast_new(EINA_FREE_CB(efreet_cache_array_string_free));
     exec = eina_hash_string_superfast_new(EINA_FREE_CB(efreet_cache_array_string_free));
     environments = eina_hash_string_superfast_new(EINA_FREE_CB(efreet_cache_array_string_free));
+    keywords = eina_hash_string_superfast_new(EINA_FREE_CB(efreet_cache_array_string_free));
 
     dirs = efreet_default_dirs_get(efreet_data_home_get(), efreet_data_dirs_get(),
                                                                     "applications");
@@ -438,6 +443,7 @@ main(int argc, char **argv)
     STORE_HASH_ARRAY(comment);
     STORE_HASH_ARRAY(exec);
     STORE_HASH_ARRAY(environments);
+    STORE_HASH_ARRAY(keywords);
     if (eina_hash_population(file_ids) > 0)
     {
         hash.hash = file_ids;
@@ -452,6 +458,7 @@ main(int argc, char **argv)
     eina_hash_free(comment);
     eina_hash_free(exec);
     eina_hash_free(environments);
+    eina_hash_free(keywords);
 
     if (old_file_ids)
     {
index db29e17..23c9e44 100644 (file)
@@ -71,6 +71,7 @@ static const char          *theme_name = NULL;
 
 static Eet_Data_Descriptor *version_edd = NULL;
 static Eet_Data_Descriptor *desktop_edd = NULL;
+static Eet_Data_Descriptor *desktop_action_edd = NULL;
 static Eet_Data_Descriptor *hash_array_string_edd = NULL;
 static Eet_Data_Descriptor *array_string_edd = NULL;
 static Eet_Data_Descriptor *hash_string_edd = NULL;
@@ -429,6 +430,7 @@ efreet_cache_edd_shutdown(void)
 {
     EDD_SHUTDOWN(version_edd);
     EDD_SHUTDOWN(desktop_edd);
+    EDD_SHUTDOWN(desktop_action_edd);
     EDD_SHUTDOWN(hash_array_string_edd);
     EDD_SHUTDOWN(array_string_edd);
     EDD_SHUTDOWN(hash_string_edd);
@@ -607,10 +609,21 @@ efreet_desktop_edd(void)
 
     if (desktop_edd) return desktop_edd;
 
+    EET_EINA_FILE_DATA_DESCRIPTOR_CLASS_SET(&eddc, Efreet_Desktop_Action);
+    desktop_action_edd = eet_data_descriptor_file_new(&eddc);
+    if (!desktop_action_edd) return NULL;
+
+    /* Desktop Spec 1.1 */
+    EET_DATA_DESCRIPTOR_ADD_BASIC(desktop_action_edd, Efreet_Desktop_Action, "key", key, EET_T_STRING);
+    EET_DATA_DESCRIPTOR_ADD_BASIC(desktop_action_edd, Efreet_Desktop_Action, "name", name, EET_T_STRING);
+    EET_DATA_DESCRIPTOR_ADD_BASIC(desktop_action_edd, Efreet_Desktop_Action, "icon", icon, EET_T_STRING);
+    EET_DATA_DESCRIPTOR_ADD_BASIC(desktop_action_edd, Efreet_Desktop_Action, "exec", exec, EET_T_STRING);
+
     EET_EINA_FILE_DATA_DESCRIPTOR_CLASS_SET(&eddc, Efreet_Cache_Desktop);
     desktop_edd = eet_data_descriptor_file_new(&eddc);
     if (!desktop_edd) return NULL;
 
+    /* Desktop Spec 1.0 */
     EET_DATA_DESCRIPTOR_ADD_BASIC(desktop_edd, Efreet_Cache_Desktop, "type", desktop.type, EET_T_INT);
     EET_DATA_DESCRIPTOR_ADD_BASIC(desktop_edd, Efreet_Cache_Desktop, "version", desktop.version, EET_T_STRING);
     EET_DATA_DESCRIPTOR_ADD_BASIC(desktop_edd, Efreet_Cache_Desktop, "orig_path", desktop.orig_path, EET_T_STRING);
@@ -634,6 +647,13 @@ efreet_desktop_edd(void)
     EET_DATA_DESCRIPTOR_ADD_BASIC(desktop_edd, Efreet_Cache_Desktop, "terminal", desktop.terminal, EET_T_UCHAR);
     EET_DATA_DESCRIPTOR_ADD_BASIC(desktop_edd, Efreet_Cache_Desktop, "startup_notify", desktop.startup_notify, EET_T_UCHAR);
 
+    /* Desktop Spec 1.1 */
+    EET_DATA_DESCRIPTOR_ADD_BASIC(desktop_edd, Efreet_Cache_Desktop, "dbus_activatable", desktop.dbus_activatable, EET_T_UCHAR);
+    EET_DATA_DESCRIPTOR_ADD_LIST(desktop_edd, Efreet_Cache_Desktop,
+                                 "actions", desktop.actions, desktop_action_edd);
+    eet_data_descriptor_element_add(desktop_edd, "implements", EET_T_STRING, EET_G_LIST, offsetof(Efreet_Cache_Desktop, desktop.implements), 0, NULL, NULL);
+    eet_data_descriptor_element_add(desktop_edd, "keywords", EET_T_STRING, EET_G_LIST, offsetof(Efreet_Cache_Desktop, desktop.keywords), 0, NULL, NULL);
+
     return desktop_edd;
 }
 
@@ -886,11 +906,17 @@ efreet_cache_desktop_free(Efreet_Desktop *desktop)
         }
     }
 
+    /* Desktop Spec 1.0 */
     eina_list_free(desktop->only_show_in);
     eina_list_free(desktop->not_show_in);
     eina_list_free(desktop->categories);
     eina_list_free(desktop->mime_types);
     IF_FREE_HASH(desktop->x);
+    /* Desktop Spec 1.1 */
+    eina_list_free(desktop->actions);
+    eina_list_free(desktop->implements);
+    eina_list_free(desktop->keywords);
+
     free(desktop);
     eina_lock_release(&_lock);
 }
index 9729215..af178ba 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef EFREET_CACHE_PRIVATE_H
 #define EFREET_CACHE_PRIVATE_H
 
-#define EFREET_DESKTOP_CACHE_MAJOR 1
+#define EFREET_DESKTOP_CACHE_MAJOR 2
 #define EFREET_DESKTOP_CACHE_MINOR 0
 #define EFREET_DESKTOP_UTILS_CACHE_MAJOR 1
 #define EFREET_DESKTOP_UTILS_CACHE_MINOR 0
index 6f0be5b..f857de8 100644 (file)
@@ -52,8 +52,11 @@ static Efreet_Desktop_Type_Info *efreet_desktop_type_parse(const char *type_str)
 static void efreet_desktop_type_info_free(Efreet_Desktop_Type_Info *info);
 static void *efreet_desktop_application_fields_parse(Efreet_Desktop *desktop,
                                                     Efreet_Ini *ini);
+static Eina_List *efreet_desktop_action_fields_parse(Efreet_Ini *ini, const char *val);
 static void efreet_desktop_application_fields_save(Efreet_Desktop *desktop,
                                                     Efreet_Ini *ini);
+static void efreet_desktop_action_fields_save(Efreet_Desktop *desktop,
+                                              Efreet_Ini *ini);
 static void *efreet_desktop_link_fields_parse(Efreet_Desktop *desktop,
                                                 Efreet_Ini *ini);
 static void efreet_desktop_link_fields_save(Efreet_Desktop *desktop,
@@ -349,6 +352,9 @@ efreet_desktop_free(Efreet_Desktop *desktop)
     }
     else
     {
+        Efreet_Desktop_Action *action;
+
+        /* Desktop Spec 1.0 */
         IF_FREE(desktop->orig_path);
 
         IF_FREE(desktop->version);
@@ -378,6 +384,19 @@ efreet_desktop_free(Efreet_Desktop *desktop)
             if (info->free_func)
                 info->free_func(desktop->type_data);
         }
+
+        /* Desktop Spec 1.1 */
+        EINA_LIST_FREE(desktop->actions, action)
+        {
+            free(action->key);
+            free(action->name);
+            free(action->icon);
+            free(action->exec);
+            free(action);
+        }
+        IF_FREE_LIST(desktop->implements, eina_stringshare_del);
+        IF_FREE_LIST(desktop->keywords, eina_stringshare_del);
+
         free(desktop);
     }
     eina_lock_release(&_lock);
@@ -710,6 +729,7 @@ efreet_desktop_application_fields_parse(Efreet_Desktop *desktop, Efreet_Ini *ini
 {
     const char *val;
 
+    /* Desktop Spec 1.0 */
     val = efreet_ini_string_get(ini, "TryExec");
     if (val) desktop->try_exec = strdup(val);
 
@@ -731,11 +751,61 @@ efreet_desktop_application_fields_parse(Efreet_Desktop *desktop, Efreet_Ini *ini
     desktop->terminal = efreet_ini_boolean_get(ini, "Terminal");
     desktop->startup_notify = efreet_ini_boolean_get(ini, "StartupNotify");
 
+    /* Desktop Spec 1.1 */
+    val = efreet_ini_string_get(ini, "Actions");
+    if (val)
+        desktop->actions = efreet_desktop_action_fields_parse(ini, val);
+    val = efreet_ini_string_get(ini, "Keywords");
+    if (val)
+        desktop->keywords = efreet_desktop_string_list_parse(val);
+
     return NULL;
 }
 
 /**
  * @internal
+ * @param key the key to look up Desktop Action entry
+ * @return list of Desktop Actions
+ */
+static Eina_List *
+efreet_desktop_action_fields_parse(Efreet_Ini *ini, const char *actions)
+{
+    Eina_List *l;
+    Eina_List *ret = NULL;
+    const char *section;
+    const char *key;
+
+    // TODO: section = efreet_ini_section_get(ini);
+    section = "Desktop Entry";
+
+    l = efreet_desktop_string_list_parse(actions);
+    EINA_LIST_FREE(l, key)
+    {
+        char entry[4096];
+        Efreet_Desktop_Action *act;
+
+        snprintf(entry, sizeof(entry), "Desktop Action %s", key);
+
+        if (!efreet_ini_section_set(ini, entry)) continue;
+
+        act = NEW(Efreet_Desktop_Action, 1);
+        if (!act) continue;
+        ret = eina_list_append(ret, act);
+        act->key = strdup(key);
+        act->name = eina_strdup(efreet_ini_localestring_get(ini, "Name"));
+        act->icon = eina_strdup(efreet_ini_localestring_get(ini, "Icon"));
+        act->exec = eina_strdup(efreet_ini_string_get(ini, "Exec"));
+
+        /* TODO: Non-standard keys OnlyShowIn, NotShowIn used by Unity */
+
+        eina_stringshare_del(key);
+    }
+    efreet_ini_section_set(ini, section);
+    return ret;
+}
+
+/**
+ * @internal
  * @param desktop the Efreet_Desktop to save fields from
  * @param ini the Efreet_Ini to save fields to
  * @return Returns no value
@@ -746,6 +816,7 @@ efreet_desktop_application_fields_save(Efreet_Desktop *desktop, Efreet_Ini *ini)
 {
     char *val;
 
+    /* Desktop Spec 1.0 */
     if (desktop->try_exec)
         efreet_ini_string_set(ini, "TryExec", desktop->try_exec);
 
@@ -780,6 +851,60 @@ efreet_desktop_application_fields_save(Efreet_Desktop *desktop, Efreet_Ini *ini)
 
     efreet_ini_boolean_set(ini, "Terminal", desktop->terminal);
     efreet_ini_boolean_set(ini, "StartupNotify", desktop->startup_notify);
+
+    /* Desktop Spec 1.1 */
+    if (desktop->actions)
+        efreet_desktop_action_fields_save(desktop, ini);
+    if (desktop->keywords)
+    {
+        val = efreet_desktop_string_list_join(desktop->keywords);
+        if (val)
+        {
+            efreet_ini_string_set(ini, "Keywords", val);
+            free(val);
+        }
+    }
+}
+
+/**
+ * @internal
+ * @param desktop the Efreet_Desktop to save fields from
+ * @param ini the Efreet_Ini to save fields to
+ * @return Returns no value
+ * @brief Save action specific desktop fields
+ */
+static void
+efreet_desktop_action_fields_save(Efreet_Desktop *desktop, Efreet_Ini *ini)
+{
+    Eina_List *actions = NULL, *l;
+    const char *section;
+    char *join;
+    Efreet_Desktop_Action *action;
+
+    // TODO: section = efreet_ini_section_get(ini);
+    section = "Desktop Entry";
+
+    EINA_LIST_FOREACH(desktop->actions, l, action)
+    {
+        char entry[4096];
+
+        actions = eina_list_append(actions, action->key);
+        snprintf(entry, sizeof(entry), "Desktop Action %s", action->key);
+        efreet_ini_section_add(ini, entry);
+        efreet_ini_section_set(ini, entry);
+
+        efreet_ini_localestring_set(ini, "Name", action->name);
+        efreet_ini_localestring_set(ini, "Icon", action->icon);
+        efreet_ini_string_set(ini, "Exec", action->exec);
+    }
+    efreet_ini_section_set(ini, section);
+    join = efreet_desktop_string_list_join(actions);
+    if (join)
+    {
+        efreet_ini_string_set(ini, "Actions", join);
+        free(join);
+    }
+    eina_list_free(actions);
 }
 
 /**
@@ -824,6 +949,7 @@ efreet_desktop_generic_fields_parse(Efreet_Desktop *desktop, Efreet_Ini *ini)
 {
     const char *val;
 
+    /* Desktop Spec 1.0 */
     val = efreet_ini_localestring_get(ini, "Name");
 #ifndef STRICT_SPEC
     if (!val) val = efreet_ini_localestring_get(ini, "_Name");
@@ -855,6 +981,10 @@ efreet_desktop_generic_fields_parse(Efreet_Desktop *desktop, Efreet_Ini *ini)
     val = efreet_ini_string_get(ini, "NotShowIn");
     if (val) desktop->not_show_in = efreet_desktop_string_list_parse(val);
 
+    /* Desktop Spec 1.1 */
+    desktop->dbus_activatable = efreet_ini_boolean_get(ini, "DBusActivatable");
+    val = efreet_ini_string_get(ini, "Implements");
+    if (val) desktop->implements = efreet_desktop_string_list_parse(val);
     return 1;
 }
 
@@ -870,6 +1000,7 @@ efreet_desktop_generic_fields_save(Efreet_Desktop *desktop, Efreet_Ini *ini)
 {
     const char *val;
 
+    /* Desktop Spec 1.0 */
     if (desktop->name)
     {
         efreet_ini_localestring_set(ini, "Name", desktop->name);
@@ -904,6 +1035,20 @@ efreet_desktop_generic_fields_save(Efreet_Desktop *desktop, Efreet_Ini *ini)
 
     if (desktop->x) eina_hash_foreach(desktop->x, efreet_desktop_x_fields_save,
                                         ini);
+
+    /* Desktop Spec 1.1 */
+    efreet_ini_boolean_set(ini, "DBusActivatable", desktop->dbus_activatable);
+    if (desktop->implements)
+    {
+        char *join;
+
+        join = efreet_desktop_string_list_join(desktop->implements);
+        if (join)
+        {
+           efreet_ini_string_set(ini, "Implements", join);
+           free(join);
+        }
+    }
 }
 
 /**
@@ -997,3 +1142,4 @@ efreet_desktop_environment_check(Efreet_Desktop *desktop)
 
     return 1;
 }
+
index fae8bac..8f2c30a 100644 (file)
@@ -30,6 +30,12 @@ EAPI extern int EFREET_EVENT_DESKTOP_CACHE_UPDATE;
 EAPI extern int EFREET_EVENT_DESKTOP_CACHE_BUILD;
 
 /**
+ * Efreet_Desktop_Action
+ * @since 1.12
+ */
+typedef struct _Efreet_Desktop_Action Efreet_Desktop_Action;
+
+/**
  * Efreet_Desktop
  */
 typedef struct _Efreet_Desktop Efreet_Desktop;
@@ -62,11 +68,25 @@ typedef void (*Efreet_Desktop_Type_Save_Cb) (Efreet_Desktop *desktop, Efreet_Ini
 typedef void *(*Efreet_Desktop_Type_Free_Cb) (void *data);
 
 /**
+ * Efreet_Desktop_Action
+ * @brief an action described in a .desktop file
+ * @since 1.12
+ */
+struct _Efreet_Desktop_Action
+{
+    char *key;  /**< Key to identify the action */
+    char *name; /**< Specific name of the action */
+    char *icon; /**< Icon to display */
+    char *exec; /**< Program to execute */
+};
+
+/**
  * Efreet_Desktop
  * @brief a parsed representation of a .desktop file
  */
 struct _Efreet_Desktop
 {
+    /* Desktop Spec 1.0 */
     int type;               /**< type of desktop file */
 
     int ref;                /**< reference count - internal */
@@ -102,6 +122,12 @@ struct _Efreet_Desktop
 
     Eina_Hash *x; /**< Keep track of all user extensions, keys that begin with X- */
     void *type_data; /**< Type specific data for custom types */
+
+    /* Desktop Spec 1.1 */
+    unsigned char dbus_activatable; /**< Activate application by dbus, not Exec. @since 1.12 */
+    Eina_List *actions;             /**< List of Efreet_Desktop_Actions, application actions. @since 1.12 */
+    Eina_List *implements;          /**< Interfaces which is file implements. @since 1.12 */
+    Eina_List *keywords;            /**< Keywords which describe this entry. @since 1.12 */
 };