enlightenment/src/modules/everything/sources/evry_plug_apps.c

719 lines
14 KiB
C
Raw Normal View History

#include "Evry.h"
typedef struct _Plugin Plugin;
struct _Plugin
{
Evry_Plugin base;
Eina_Hash *added;
Eina_List *apps_mime;
Eina_List *apps_all;
const Evry_Item *candidate;
};
static Plugin *p1;
static Plugin *p2;
static Evry_Action *act;
static Evry_Action *act1;
static Evry_Action *act2;
static Evry_Action *act3;
static Evry_Action *act4;
static Eina_List *exe_path = NULL;
static void _hash_free(void *data)
{
ITEM_APP(app, data);
evry_item_free(EVRY_ITEM(app));
}
static Evry_Plugin *
_begin(Evry_Plugin *plugin, const Evry_Item *item)
{
PLUGIN(p, plugin);
const char *mime;
2009-08-12 12:00:25 -07:00
if (item)
{
ITEM_FILE(file, item);
Efreet_Desktop *desktop;
if (!file->uri) return NULL;
if (!file->mime)
mime = efreet_mime_type_get(file->uri);
else
mime = file->mime;
if (!mime) return NULL;
p->candidate = EVRY_ITEM(file);
p->apps_mime = efreet_util_desktop_mime_list(mime);
desktop = e_exehist_mime_desktop_get(mime);
if (desktop)
{
efreet_desktop_ref(desktop);
p->apps_mime = eina_list_prepend(p->apps_mime, desktop);
}
}
2009-08-12 12:00:25 -07:00
p->added = eina_hash_string_small_new(_hash_free);
return EVRY_PLUGIN(p);
}
static void
_item_free(Evry_Item *item)
{
ITEM_APP(app, item);
if (app->desktop)
efreet_desktop_free(app->desktop);
if (app->file)
eina_stringshare_del(app->file);
E_FREE(app);
}
static void
_cleanup(Evry_Plugin *plugin)
{
PLUGIN(p, plugin);
Efreet_Desktop *desktop;
eina_hash_free(p->added);
EVRY_PLUGIN_ITEMS_CLEAR(p);
2009-08-12 12:00:25 -07:00
EINA_LIST_FREE(p->apps_mime, desktop)
efreet_desktop_free(desktop);
EINA_LIST_FREE(p->apps_all, desktop)
efreet_desktop_free(desktop);
}
static int
_item_add(Plugin *p, Efreet_Desktop *desktop, char *file, int match)
{
Evry_Item_App *app;
Efreet_Desktop *d2;
int already_refd = 0;
2009-08-12 12:00:25 -07:00
if (desktop)
file = desktop->exec;
if (!file) return 0;
2009-08-12 12:00:25 -07:00
if ((app = eina_hash_find(p->added, file)) &&
(!desktop || (desktop == app->desktop)))
{
if (!eina_list_data_find_list(EVRY_PLUGIN(p)->items, app))
{
EVRY_ITEM(app)->fuzzy_match = match;
EVRY_PLUGIN_ITEM_APPEND(p, app);
}
return 1;
}
if (!desktop)
{
char match[4096];
Eina_List *l;
int len;
char *tmp;
len = strlen(file);
tmp = ecore_file_app_exe_get(file);
snprintf(match, sizeof(match), "%s*", tmp);
l = efreet_util_desktop_exec_glob_list(match);
EINA_LIST_FREE(l, d2)
{
if (!desktop && d2->exec && !strncmp(file, d2->exec, len))
{
desktop = d2;
already_refd = 1;
efreet_desktop_ref(desktop);
}
efreet_desktop_free(d2);
}
free(tmp);
}
if (desktop)
{
if (!already_refd)
efreet_desktop_ref(desktop);
}
app = E_NEW(Evry_Item_App, 1);
if (desktop)
evry_item_new(EVRY_ITEM(app), EVRY_PLUGIN(p), desktop->name, _item_free);
else
evry_item_new(EVRY_ITEM(app), EVRY_PLUGIN(p), file, _item_free);
2009-08-12 12:00:25 -07:00
app->desktop = desktop;
app->file = eina_stringshare_add(file);
EVRY_ITEM(app)->fuzzy_match = match;
EVRY_PLUGIN_ITEM_APPEND(p, app);
eina_hash_add(p->added, file, app);
return 1;
}
static void
_add_desktop_list(Plugin *p, Eina_List *apps, const char *input)
{
Efreet_Desktop *desktop;
Eina_List *l;
int m1, m2;
2009-08-12 12:00:25 -07:00
EINA_LIST_FOREACH(apps, l, desktop)
{
if (eina_list_count(EVRY_PLUGIN(p)->items) > 199) continue;
if (!desktop->name || !desktop->exec) continue;
2009-08-12 12:00:25 -07:00
char *exec = strrchr(desktop->exec, '/');
if (!exec++ || !exec) exec = desktop->exec;
m1 = evry_fuzzy_match(exec, input);
m2 = evry_fuzzy_match(desktop->name, input);
if (!m1 || (m2 && m2 < m1))
m1 = m2;
if (m1) _item_add(p, desktop, NULL, m1);
}
}
static int
_cb_sort(const void *data1, const void *data2)
{
const Evry_Item *it1 = data1;
const Evry_Item *it2 = data2;
const char *e1, *e2;
double t1, t2;
ITEM_APP(app1, it1);
ITEM_APP(app2, it2);
if (app1->desktop)
e1 = app1->desktop->exec;
else
e1 = app1->file;
if (app2->desktop)
e2 = app2->desktop->exec;
else
e2 = app2->file;
t1 = e_exehist_newest_run_get(e1);
t2 = e_exehist_newest_run_get(e2);
if (it1->fuzzy_match && !it2->fuzzy_match)
return -1;
if (!it1->fuzzy_match && it2->fuzzy_match)
return 1;
t1 = t1 / (double)it1->fuzzy_match;
t2 = t2 / (double)it2->fuzzy_match;
if ((int)(t2 - t1))
return (int)(t2 - t1);
if (it1->fuzzy_match - it2->fuzzy_match)
return (it1->fuzzy_match - it2->fuzzy_match);
else return 0;
}
static int
_fetch(Evry_Plugin *plugin, const char *input)
{
PLUGIN(p, plugin);
Eina_List *l;
Efreet_Desktop *desktop;
Evry_Item *it;
char *file;
int prio = 0;
EVRY_PLUGIN_ITEMS_CLEAR(p);
/* add apps for a given mimetype */
if (plugin->type == type_action)
{
if (input)
_add_desktop_list(p, p->apps_mime, input);
else
{
EINA_LIST_FOREACH(p->apps_mime, l, desktop)
_item_add(p, desktop, NULL, 1);
}
}
/* add apps matching input */
if (input)
{
if (!p->apps_all)
{
Eina_List *apps = NULL;
Eina_List *cats;
Eina_List *l, *ll;
apps = efreet_util_desktop_name_glob_list("*");
cats = efreet_util_desktop_category_list("Screensaver");
EINA_LIST_FOREACH(cats, l, desktop)
{
ll = eina_list_data_find_list(apps, desktop);
if (ll)
{
efreet_desktop_free(desktop);
apps = eina_list_remove_list(apps, ll);
}
}
p->apps_all = apps;
}
_add_desktop_list(p, p->apps_all, input);
}
/* add exe history items */
else if (!plugin->items)
{
l = e_exehist_list_get();
EINA_LIST_FREE(l, file)
2009-08-12 12:00:25 -07:00
_item_add(p, NULL, file, 1);
}
/* TODO make this an action */
/* show 'Run Command' item */
/* if (input)
* {
* int found = 0;
* char *end;
* char *dir;
* char cmd[1024];
* char path[1024];
*
* snprintf(cmd, sizeof(cmd), "%s", input);
*
* if ((end = strchr(input, ' ')))
* {
* int len = (end - input) + 1;
* if (len >= 0)
* snprintf(cmd, len, "%s", input);
* }
*
* EINA_LIST_FOREACH(exe_path, l, dir)
* {
* snprintf(path, sizeof(path), "%s/%s", dir, cmd);
* if (ecore_file_exists(path))
* {
* found = 1;
* break;
* }
* }
*
* if (found)
* {
* Evry_Item_App *app;
* app = E_NEW(Evry_Item_App, 1);
* evry_item_new(EVRY_ITEM(app), plugin, _("Run Command"), _item_free);
* app->file = eina_stringshare_add(input);
* EVRY_ITEM(app)->priority = 9999;
* EVRY_PLUGIN_ITEM_APPEND(p, app);
*
* snprintf(cmd, sizeof(cmd), "xterm -hold -e %s", input);
* app = E_NEW(Evry_Item_App, 1);
* evry_item_new(EVRY_ITEM(app), plugin, _("Run in Terminal"), _item_free);
* app->file = eina_stringshare_add(cmd);
* EVRY_ITEM(app)->priority = 1000;
* EVRY_PLUGIN_ITEM_APPEND(p, app);
* }
* } */
if (!plugin->items) return 0;
EVRY_PLUGIN_ITEMS_SORT(plugin, _cb_sort);
EINA_LIST_FOREACH(plugin->items, l, it)
it->priority = prio++;
return 1;
}
static Evas_Object *
_icon_get(Evry_Plugin *p __UNUSED__, const Evry_Item *it, Evas *e)
{
ITEM_APP(app, it);
Evas_Object *o = NULL;
/* Evry_App *app = it->data[0]; */
if (app->desktop)
o = e_util_desktop_icon_add(app->desktop, 64, e);
if (!o)
o = evry_icon_theme_get("system-run", e);
return o;
}
static int
_exec_app_check_item(Evry_Action *act __UNUSED__, const Evry_Item *it)
{
ITEM_APP(app, it);
if (app->desktop)
return 1;
if (app->file && strlen(app->file) > 0)
return 1;
return 0;
}
static int
_app_action(const Evry_Item *it1, const Evry_Item *it2)
{
E_Zone *zone;
Eina_List *files = NULL;
char *exe = NULL;
2009-08-12 12:00:25 -07:00
if (!it1) return 0;
ITEM_APP(app, it1);
2009-08-12 12:00:25 -07:00
zone = e_util_zone_current_get(e_manager_current_get());
2009-08-12 12:00:25 -07:00
if (app->desktop)
{
if (it2)
{
ITEM_FILE(file, it2);
Eina_List *l;
char *mime;
char *path = NULL;
int open_folder = 0;
if (!EVRY_ITEM(file)->browseable)
{
EINA_LIST_FOREACH(app->desktop->mime_types, l, mime)
{
if (!strcmp(mime, "x-directory/normal"))
{
open_folder = 1;
break;
}
}
}
if (open_folder)
{
path = ecore_file_dir_get(file->uri);
files = eina_list_append(files, path);
}
else
{
files = eina_list_append(files, file->uri);
}
2009-08-12 12:00:25 -07:00
e_exec(zone, app->desktop, NULL, files, NULL);
if (file && file->mime && !open_folder)
e_exehist_mime_desktop_add(file->mime, app->desktop);
if (files)
eina_list_free(files);
if (open_folder && path)
free(path);
}
else
e_exec(zone, app->desktop, NULL, NULL, "everything");
}
else if (app->file)
{
if (it2)
{
ITEM_FILE(file, it2);
int len;
len = strlen(app->file) + strlen(file->uri) + 2;
exe = malloc(len);
snprintf(exe, len, "%s %s", app->file, file->uri);
e_exec(zone, NULL, exe, NULL, NULL);
free(exe);
}
else
{
exe = (char *) app->file;
e_exec(zone, NULL, exe, NULL, NULL);
}
}
return 1;
}
static int
_exec_app_action(Evry_Action *act)
{
return _app_action(act->item1, act->item2);
}
static int
_open_with_action(Evry_Plugin *plugin, const Evry_Item *it)
{
PLUGIN(p, plugin);
if (p->candidate)
return _app_action(it, p->candidate);
return 0;
}
static int
_edit_app_check_item(Evry_Action *act __UNUSED__, const Evry_Item *it)
{
ITEM_APP(app, it);
if (app->desktop)
return 1;
return 0;
}
static int
_edit_app_action(Evry_Action *act)
{
Efreet_Desktop *desktop;
ITEM_APP(app, act->item1);
if (app->desktop)
desktop = app->desktop;
else
{
char buf[128];
snprintf(buf, 128, "%s/.local/share/applications/%s.desktop",
e_user_homedir_get(), app->file);
desktop = efreet_desktop_empty_new(eina_stringshare_add(buf));
/* XXX check if this is freed by efreet*/
2009-08-12 12:00:25 -07:00
desktop->exec = strdup(app->file);
}
e_desktop_edit(e_container_current_get(e_manager_current_get()), desktop);
2009-08-12 12:00:25 -07:00
return 1;
}
static int
_new_app_check_item(Evry_Action *act __UNUSED__, const Evry_Item *it)
{
ITEM_APP(app, it);
if (app->desktop)
return 1;
if (app->file && strlen(app->file) > 0)
return 1;
2009-08-12 12:00:25 -07:00
return 0;
}
static int
_new_app_action(Evry_Action *act)
{
char *name;
char buf[4096];
char *end;
Efreet_Desktop *desktop;
int i;
ITEM_APP(app, act->item1);
2009-08-12 12:00:25 -07:00
if (app->desktop)
name = strdup(app->desktop->name);
else
/* TODO replace '/' and remove other special characters */
name = strdup(app->file);
if ((end = strchr(name, ' ')))
name[end - name] = '\0';
2009-08-12 12:00:25 -07:00
for (i = 0; i < 10; i++)
{
snprintf(buf, 4096, "%s/.local/share/applications/%s-%d.desktop",
e_user_homedir_get(), name, i);
if (ecore_file_exists(buf))
{
buf[0] = '\0';
continue;
}
else break;
}
free(name);
2009-08-12 12:00:25 -07:00
if (strlen(buf) == 0)
return 0;
2009-08-12 12:00:25 -07:00
if (!app->desktop)
{
desktop = efreet_desktop_empty_new(buf);
desktop->exec = strdup(app->file);
}
2009-08-12 12:00:25 -07:00
else
{
efreet_desktop_save_as(app->desktop, buf);
desktop = efreet_desktop_new(buf);
}
2009-08-12 12:00:25 -07:00
e_desktop_edit(e_container_current_get(e_manager_current_get()), desktop);
return 1;
}
static int
_exec_border_check_item(Evry_Action *act __UNUSED__, const Evry_Item *it)
{
E_Border *bd = it->data;
E_OBJECT_CHECK_RETURN(bd, 0);
E_OBJECT_TYPE_CHECK_RETURN(bd, E_BORDER_TYPE, 0);
if ((bd->desktop && bd->desktop->exec) &&
((strstr(bd->desktop->exec, "%u")) ||
(strstr(bd->desktop->exec, "%U")) ||
(strstr(bd->desktop->exec, "%f")) ||
(strstr(bd->desktop->exec, "%F"))))
return 1;
return 0;
}
static int
_exec_border_action(Evry_Action *act)
{
return _app_action(act->item1, act->item2);
}
static int
_exec_border_intercept(Evry_Action *act)
{
Evry_Item_App *app = E_NEW(Evry_Item_App, 1);
E_Border *bd = act->item1->data;
app->desktop = bd->desktop;
act->item1 = EVRY_ITEM(app);
return 1;
}
static void
_exec_border_cleanup(Evry_Action *act)
{
ITEM_APP(app, act->item1);
E_FREE(app);
}
static Eina_Bool
_init(void)
{
char *path, *p, *last;
2009-08-12 12:00:25 -07:00
p1 = E_NEW(Plugin, 1);
evry_plugin_new(EVRY_PLUGIN(p1), "Applications", type_subject, "", "APPLICATION", 0, NULL, NULL,
_begin, _cleanup, _fetch, NULL, _icon_get, NULL, NULL);
p2 = E_NEW(Plugin, 1);
evry_plugin_new(EVRY_PLUGIN(p2), "Open With...", type_action, "FILE", "", 0, NULL, NULL,
_begin, _cleanup, _fetch, _open_with_action,
_icon_get, NULL, NULL);
evry_plugin_register(EVRY_PLUGIN(p1), 1);
evry_plugin_register(EVRY_PLUGIN(p2), 3);
act = evry_action_new("Launch", "APPLICATION", NULL, NULL,
"everything-launch",
_exec_app_action, _exec_app_check_item,
NULL, NULL,NULL);
act1 = evry_action_new("Open File...", "APPLICATION", "FILE", "APPLICATION",
"document-open",
_exec_app_action, _exec_app_check_item,
NULL, NULL, NULL);
act2 = evry_action_new("Edit Application Entry", "APPLICATION", NULL, NULL,
"everything-launch",
_edit_app_action, _edit_app_check_item,
NULL, NULL, NULL);
2009-08-12 12:00:25 -07:00
act3 = evry_action_new("New Application Entry", "APPLICATION", NULL, NULL,
"everything-launch",
_new_app_action, _new_app_check_item,
NULL, NULL, NULL);
act4 = evry_action_new("Open File...", "BORDER", "FILE", "APPLICATION",
"everything-launch",
_exec_border_action, _exec_border_check_item,
_exec_border_cleanup, _exec_border_intercept, NULL);
evry_action_register(act);
evry_action_register(act1);
evry_action_register(act2);
evry_action_register(act3);
evry_action_register(act4);
/* taken from e_exebuf.c */
path = getenv("PATH");
if (path)
{
path = strdup(path);
last = path;
for (p = path; p[0]; p++)
{
if (p[0] == ':') p[0] = '\0';
if (p[0] == 0)
{
exe_path = eina_list_append(exe_path, strdup(last));
last = p + 1;
}
}
if (p > last)
exe_path = eina_list_append(exe_path, strdup(last));
free(path);
}
2009-08-12 12:00:25 -07:00
return EINA_TRUE;
}
static void
_shutdown(void)
{
char *str;
2009-08-12 12:00:25 -07:00
EVRY_PLUGIN_FREE(p1);
EVRY_PLUGIN_FREE(p2);
evry_action_free(act);
evry_action_free(act1);
evry_action_free(act2);
evry_action_free(act3);
evry_action_free(act4);
EINA_LIST_FREE(exe_path, str)
free(str);
}
EINA_MODULE_INIT(_init);
EINA_MODULE_SHUTDOWN(_shutdown);