From 793fd5e84775931cf491bf81ccbbee174feda05c Mon Sep 17 00:00:00 2001 From: Sebastian Dransfeld Date: Thu, 25 Sep 2014 08:47:18 +0200 Subject: [PATCH] efreet: Implement fields added by desktop spec 1.1 --- src/bin/efreet/efreet_desktop_cache_create.c | 7 + src/lib/efreet/efreet_cache.c | 26 ++++ src/lib/efreet/efreet_cache_private.h | 2 +- src/lib/efreet/efreet_desktop.c | 146 +++++++++++++++++++ src/lib/efreet/efreet_desktop.h | 26 ++++ 5 files changed, 206 insertions(+), 1 deletion(-) diff --git a/src/bin/efreet/efreet_desktop_cache_create.c b/src/bin/efreet/efreet_desktop_cache_create.c index ff0a106437..4fa3ef4397 100644 --- a/src/bin/efreet/efreet_desktop_cache_create.c +++ b/src/bin/efreet/efreet_desktop_cache_create.c @@ -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) { diff --git a/src/lib/efreet/efreet_cache.c b/src/lib/efreet/efreet_cache.c index db29e17b4b..23c9e4462f 100644 --- a/src/lib/efreet/efreet_cache.c +++ b/src/lib/efreet/efreet_cache.c @@ -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); } diff --git a/src/lib/efreet/efreet_cache_private.h b/src/lib/efreet/efreet_cache_private.h index 9729215f9e..af178baaad 100644 --- a/src/lib/efreet/efreet_cache_private.h +++ b/src/lib/efreet/efreet_cache_private.h @@ -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 diff --git a/src/lib/efreet/efreet_desktop.c b/src/lib/efreet/efreet_desktop.c index 6f0be5b422..f857de8fa7 100644 --- a/src/lib/efreet/efreet_desktop.c +++ b/src/lib/efreet/efreet_desktop.c @@ -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,9 +751,59 @@ 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 @@ -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; } + diff --git a/src/lib/efreet/efreet_desktop.h b/src/lib/efreet/efreet_desktop.h index fae8bac256..8f2c30a4e6 100644 --- a/src/lib/efreet/efreet_desktop.h +++ b/src/lib/efreet/efreet_desktop.h @@ -29,6 +29,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 */ @@ -61,12 +67,26 @@ 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 */ }; -- 2.34.1