forked from enlightenment/enlightenment
efm - add a rfecent files menu (up to 30) wirth minimal mime icons
efm now tracks the most recent 30 files opened with timestamps in 100th of a second and a menu with these recent files under main menu -> navigate ... the icons are plain mime type icons and not thumbnails as the efm code isnmt really usafle to create icons in menus without a lot of work. something to keep in mind for the redo of efm... :) at least you can easily access recently opened files with efm now :) @feat
This commit is contained in:
parent
c7999bb789
commit
8b16ea75a0
154
src/bin/e_exec.c
154
src/bin/e_exec.c
|
@ -12,6 +12,7 @@
|
|||
typedef struct _E_Exec_Launch E_Exec_Launch;
|
||||
typedef struct _E_Exec_Search E_Exec_Search;
|
||||
typedef struct _E_Exec_Watch E_Exec_Watch;
|
||||
typedef struct _E_Exec_Recent E_Exec_Recent;
|
||||
|
||||
struct _E_Exec_Launch
|
||||
{
|
||||
|
@ -46,6 +47,11 @@ struct _E_Config_Dialog_Data
|
|||
char *label, *exit, *signal;
|
||||
};
|
||||
|
||||
struct _E_Exec_Recent
|
||||
{
|
||||
Eina_List *files;
|
||||
};
|
||||
|
||||
/* local subsystem functions */
|
||||
static E_Exec_Instance *_e_exec_cb_exec(void *data, Efreet_Desktop *desktop, char *exec, int remaining);
|
||||
static Eina_Bool _e_exec_cb_expire_timer(void *data);
|
||||
|
@ -82,6 +88,94 @@ E_API int E_EVENT_EXEC_NEW = -1;
|
|||
E_API int E_EVENT_EXEC_NEW_CLIENT = -1;
|
||||
E_API int E_EVENT_EXEC_DEL = -1;
|
||||
|
||||
static E_Exec_Recent * _e_exec_recent = NULL;
|
||||
static Ecore_Idler *_e_exec_recent_idler = NULL;
|
||||
|
||||
static Eina_Bool
|
||||
_e_exec_cb_recent_idler(void *data EINA_UNUSED)
|
||||
{
|
||||
char buf[4096];
|
||||
FILE *f;
|
||||
Eina_List *l;
|
||||
E_Exec_Recent_File *fl;
|
||||
|
||||
e_user_dir_snprintf(buf, sizeof(buf), "recent-files.txt");
|
||||
if ((_e_exec_recent) && (_e_exec_recent->files))
|
||||
{
|
||||
f = fopen(buf, "w");
|
||||
if (f)
|
||||
{
|
||||
EINA_LIST_FOREACH(_e_exec_recent->files, l, fl)
|
||||
{
|
||||
fprintf(f, "%1.0f %s\n", fl->timestamp * 100.0, fl->file);
|
||||
}
|
||||
fclose(f);
|
||||
}
|
||||
}
|
||||
_e_exec_recent_idler = NULL;
|
||||
return EINA_FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
_e_exec_recent_file_append(const char *file, double tim)
|
||||
{
|
||||
Eina_List *l;
|
||||
E_Exec_Recent_File *fl = calloc(1, sizeof(E_Exec_Recent_File));
|
||||
E_Exec_Recent_File *fl2;
|
||||
|
||||
if (!fl) return;
|
||||
if (!_e_exec_recent)
|
||||
_e_exec_recent = calloc(1, sizeof(E_Exec_Recent));
|
||||
if (!_e_exec_recent)
|
||||
{
|
||||
free(fl);
|
||||
return;
|
||||
}
|
||||
fl->file = eina_stringshare_add(file);
|
||||
fl->timestamp = tim;
|
||||
EINA_LIST_FOREACH(_e_exec_recent->files, l, fl2)
|
||||
{
|
||||
if (!strcmp(fl2->file, fl->file))
|
||||
{
|
||||
_e_exec_recent->files = eina_list_remove_list(_e_exec_recent->files, l);
|
||||
eina_stringshare_del(fl2->file);
|
||||
free(fl2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
_e_exec_recent->files = eina_list_prepend(_e_exec_recent->files, fl);
|
||||
if (eina_list_count(_e_exec_recent->files) > 30)
|
||||
{
|
||||
l = eina_list_last(_e_exec_recent->files);
|
||||
if (l)
|
||||
{
|
||||
fl = l->data;
|
||||
_e_exec_recent->files = eina_list_remove_list(_e_exec_recent->files, l);
|
||||
eina_stringshare_del(fl->file);
|
||||
free(fl);
|
||||
}
|
||||
}
|
||||
if (!_e_exec_recent_idler)
|
||||
_e_exec_recent_idler = ecore_idler_add(_e_exec_cb_recent_idler, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
_e_exec_recent_clean(void)
|
||||
{
|
||||
E_Exec_Recent_File *fl;
|
||||
|
||||
if (!_e_exec_recent) return;
|
||||
EINA_LIST_FREE(_e_exec_recent->files, fl)
|
||||
{
|
||||
eina_stringshare_del(fl->file);
|
||||
free(fl);
|
||||
}
|
||||
free(_e_exec_recent);
|
||||
_e_exec_recent = NULL;
|
||||
if (_e_exec_recent_idler) ecore_idler_del(_e_exec_recent_idler);
|
||||
_e_exec_recent_idler = NULL;
|
||||
}
|
||||
|
||||
/* externally accessible functions */
|
||||
EINTERN int
|
||||
e_exec_init(void)
|
||||
|
@ -102,6 +196,7 @@ e_exec_init(void)
|
|||
EINTERN int
|
||||
e_exec_shutdown(void)
|
||||
{
|
||||
_e_exec_recent_clean();
|
||||
if (_e_exec_exit_handler) ecore_event_handler_del(_e_exec_exit_handler);
|
||||
if (_e_exec_desktop_update_handler)
|
||||
ecore_event_handler_del(_e_exec_desktop_update_handler);
|
||||
|
@ -117,6 +212,43 @@ e_exec_executor_set(E_Exec_Instance *(*func)(void *data, E_Zone * zone, Efreet_D
|
|||
_e_exec_executor_data = (void *)data;
|
||||
}
|
||||
|
||||
E_API const Eina_List *
|
||||
e_exec_recent_files_get(void)
|
||||
{
|
||||
if (!_e_exec_recent)
|
||||
{
|
||||
FILE *f;
|
||||
char buf[4096];
|
||||
|
||||
e_user_dir_snprintf(buf, sizeof(buf), "recent-files.txt");
|
||||
f = fopen(buf, "r");
|
||||
if (f)
|
||||
{
|
||||
long long timi;
|
||||
|
||||
while (fscanf(f, "%lli %4095[^\n]\n", &timi, buf) == 2)
|
||||
{
|
||||
E_Exec_Recent_File *fl = calloc(1, sizeof(E_Exec_Recent_File));
|
||||
|
||||
if (!fl) free(fl);
|
||||
if (!_e_exec_recent)
|
||||
_e_exec_recent = calloc(1, sizeof(E_Exec_Recent));
|
||||
if (!_e_exec_recent)
|
||||
{
|
||||
free(fl);
|
||||
break;
|
||||
}
|
||||
fl->file = eina_stringshare_add(buf);
|
||||
fl->timestamp = (double)timi / 100.0;
|
||||
_e_exec_recent->files = eina_list_prepend(_e_exec_recent->files, fl);
|
||||
}
|
||||
fclose(f);
|
||||
}
|
||||
}
|
||||
if (!_e_exec_recent) return NULL;
|
||||
return _e_exec_recent->files;
|
||||
}
|
||||
|
||||
E_API E_Exec_Instance *
|
||||
e_exec(E_Zone *zone, Efreet_Desktop *desktop, const char *exec,
|
||||
Eina_List *files, const char *launch_method)
|
||||
|
@ -126,6 +258,28 @@ e_exec(E_Zone *zone, Efreet_Desktop *desktop, const char *exec,
|
|||
|
||||
if ((!desktop) && (!exec)) return NULL;
|
||||
|
||||
if (files)
|
||||
{
|
||||
const char *s;
|
||||
Eina_List *l;
|
||||
char buf[4096], buf2[8192+128];
|
||||
double tim;
|
||||
|
||||
if (getcwd(buf, sizeof(buf)))
|
||||
{
|
||||
tim = ecore_time_unix_get();
|
||||
EINA_LIST_FOREACH(files, l, s)
|
||||
{
|
||||
if (s[0] == '/')
|
||||
_e_exec_recent_file_append(s, tim);
|
||||
else
|
||||
{
|
||||
snprintf(buf2, sizeof(buf2), "%s/%s", buf, s);
|
||||
_e_exec_recent_file_append(buf2, tim);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (_e_exec_executor_func)
|
||||
return _e_exec_executor_func(_e_exec_executor_data, zone,
|
||||
desktop, exec, files, launch_method);
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#ifdef E_TYPEDEFS
|
||||
|
||||
typedef struct _E_Exec_Instance E_Exec_Instance;
|
||||
typedef struct _E_Exec_Recent_File E_Exec_Recent_File;
|
||||
|
||||
#else
|
||||
#ifndef E_EXEC_H
|
||||
|
@ -24,6 +25,12 @@ struct _E_Exec_Instance
|
|||
Eina_Bool deleted E_BITFIELD;
|
||||
};
|
||||
|
||||
struct _E_Exec_Recent_File
|
||||
{
|
||||
const char *file;
|
||||
double timestamp;
|
||||
};
|
||||
|
||||
typedef enum
|
||||
{
|
||||
E_EXEC_WATCH_STARTED,
|
||||
|
@ -44,6 +51,7 @@ E_API void e_exec_instance_found(E_Exec_Instance *inst);
|
|||
E_API void e_exec_instance_watcher_add(E_Exec_Instance *inst, void (*func) (void *data, E_Exec_Instance *inst, E_Exec_Watch_Type type), const void *data);
|
||||
E_API void e_exec_instance_watcher_del(E_Exec_Instance *inst, void (*func) (void *data, E_Exec_Instance *inst, E_Exec_Watch_Type type), const void *data);
|
||||
E_API const Eina_List *e_exec_desktop_instances_find(const Efreet_Desktop *desktop);
|
||||
E_API const Eina_List *e_exec_recent_files_get(void);
|
||||
|
||||
E_API const Eina_Hash *e_exec_instances_get(void);
|
||||
E_API void e_exec_instance_client_add(E_Exec_Instance *inst, E_Client *ec);
|
||||
|
|
|
@ -1275,8 +1275,8 @@ _e_fwin_defaults_apps_get(const char *mime, const char *path)
|
|||
return apps;
|
||||
}
|
||||
|
||||
static Eina_List *
|
||||
_e_fwin_suggested_apps_list_sort(const char *mime, Eina_List *desktops, Eina_Bool *has_default)
|
||||
Eina_List *
|
||||
e_fwin_suggested_apps_list_sort(const char *mime, Eina_List *desktops, Eina_Bool *has_default)
|
||||
{
|
||||
char path[PATH_MAX];
|
||||
Eina_List *order, *l;
|
||||
|
@ -1359,7 +1359,7 @@ _e_fwin_suggested_apps_list_get(Eina_List *files,
|
|||
|
||||
if (mime_list) *mime_list = eina_list_append(*mime_list, mime);
|
||||
|
||||
desktops = _e_fwin_suggested_apps_list_sort(mime, desktops, &hd);
|
||||
desktops = e_fwin_suggested_apps_list_sort(mime, desktops, &hd);
|
||||
if ((hd) && (has_default))
|
||||
*has_default = EINA_TRUE;
|
||||
|
||||
|
|
|
@ -131,6 +131,8 @@ Eina_Bool e_fwin_show (const char *dev, const char *path);
|
|||
Eina_Bool e_fwin_nav_init(void);
|
||||
Eina_Bool e_fwin_nav_shutdown(void);
|
||||
|
||||
Eina_List *e_fwin_suggested_apps_list_sort(const char *mime, Eina_List *desktops, Eina_Bool *has_default);
|
||||
|
||||
/**
|
||||
* @addtogroup Optional_Fileman
|
||||
* @{
|
||||
|
|
|
@ -391,6 +391,125 @@ _e_mod_fileman_parse_gtk_bookmarks(E_Menu *m,
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
_e_mod_menu_populate_cleanup_cb(void *obj)
|
||||
{
|
||||
eina_stringshare_del(e_object_data_get(E_OBJECT(obj)));
|
||||
}
|
||||
|
||||
static void
|
||||
_e_mod_menu_recent_cb(void *data EINA_UNUSED,
|
||||
E_Menu *m,
|
||||
E_Menu_Item *mi)
|
||||
{
|
||||
const char *file = e_object_data_get(E_OBJECT(mi));
|
||||
|
||||
if (file)
|
||||
{
|
||||
const char *mime = efreet_mime_type_get(file);
|
||||
|
||||
if (mime)
|
||||
{
|
||||
// XXX: need to share logic with _e_fileman_dbus_daemon_open_file_cb()
|
||||
// and _e_fwin_file_open_dialog
|
||||
Eina_List *handlers = efreet_util_desktop_mime_list(mime);
|
||||
if (handlers)
|
||||
{
|
||||
Efreet_Desktop *desktop;
|
||||
Eina_Bool hd = EINA_FALSE;
|
||||
|
||||
handlers = e_fwin_suggested_apps_list_sort(mime, handlers, &hd);
|
||||
desktop = handlers->data;
|
||||
if (desktop)
|
||||
{
|
||||
Eina_List *files = NULL;
|
||||
|
||||
files = eina_list_append(files, file);
|
||||
e_exec(m->zone, desktop, NULL, files, "fwin");
|
||||
files = eina_list_free(files);
|
||||
}
|
||||
EINA_LIST_FREE(handlers, desktop)
|
||||
{
|
||||
efreet_desktop_free(desktop);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
_e_mod_menu_populate_recent_cb(void *data EINA_UNUSED,
|
||||
E_Menu *m EINA_UNUSED,
|
||||
E_Menu_Item *mi EINA_UNUSED)
|
||||
{
|
||||
Eina_List *l;
|
||||
Eina_List *files = (Eina_List *)e_exec_recent_files_get();
|
||||
E_Exec_Recent_File *fl;
|
||||
E_Menu *subm;
|
||||
E_Menu_Item *mi2;
|
||||
|
||||
subm = e_menu_new();
|
||||
e_menu_item_submenu_set(mi, subm);
|
||||
e_menu_freeze(subm);
|
||||
EINA_LIST_FOREACH(files, l, fl)
|
||||
{
|
||||
const char *fname;
|
||||
|
||||
fname = ecore_file_file_get(fl->file);
|
||||
if (fname)
|
||||
{
|
||||
const char *mime = efreet_mime_type_get(fl->file);
|
||||
|
||||
mi2 = e_menu_item_new(subm);
|
||||
e_menu_item_label_set(mi2, fname);
|
||||
e_object_data_set(E_OBJECT(mi2), eina_stringshare_add(fl->file));
|
||||
e_object_free_attach_func_set(E_OBJECT(mi2),
|
||||
_e_mod_menu_populate_cleanup_cb);
|
||||
e_menu_item_callback_set(mi2, _e_mod_menu_recent_cb, NULL);
|
||||
if (mime)
|
||||
{
|
||||
char buf[1024];
|
||||
const char *icon_file, *edje_file;
|
||||
|
||||
snprintf(buf, sizeof(buf), "e/icons/fileman/mime/%s", mime);
|
||||
edje_file = e_theme_edje_file_get("base/theme/icons", buf);
|
||||
if (edje_file)
|
||||
{
|
||||
e_menu_item_icon_edje_set(mi2, edje_file, buf);
|
||||
}
|
||||
else
|
||||
{
|
||||
icon_file = efreet_mime_type_icon_get(mime, e_config->icon_theme, 48);
|
||||
e_menu_item_icon_file_set(mi2, icon_file);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
e_menu_thaw(subm);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
_e_mod_fileman_add_recent(E_Menu *m,
|
||||
Eina_Bool need_separator)
|
||||
{
|
||||
E_Menu_Item *mi;
|
||||
const Eina_List *files = e_exec_recent_files_get();
|
||||
|
||||
if (!files) return;
|
||||
|
||||
if (need_separator)
|
||||
{
|
||||
mi = e_menu_item_new(m);
|
||||
e_menu_item_separator_set(mi, 1);
|
||||
}
|
||||
mi = e_menu_item_new(m);
|
||||
e_menu_item_label_set(mi, _("Recent"));
|
||||
e_util_menu_item_theme_icon_set(mi, "folder");
|
||||
e_menu_item_submenu_pre_callback_set(mi, _e_mod_menu_populate_recent_cb, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
_e_mod_menu_free(void *data)
|
||||
{
|
||||
|
@ -528,6 +647,7 @@ _e_mod_menu_generate(void *data, E_Menu *m)
|
|||
}
|
||||
|
||||
_e_mod_fileman_parse_gtk_bookmarks(m, need_separator || volumes_visible > 0);
|
||||
_e_mod_fileman_add_recent(m, need_separator || volumes_visible > 0);
|
||||
|
||||
e_menu_pre_activate_callback_set(m, NULL, NULL);
|
||||
}
|
||||
|
|
|
@ -1491,7 +1491,9 @@ _pulse_connect(void *data)
|
|||
{
|
||||
pa_proplist *proplist;
|
||||
Context *c = data;
|
||||
Eina_Bool ret = ECORE_CALLBACK_DONE;
|
||||
|
||||
printf("PULSE CONN...\n");
|
||||
proplist = pa_proplist_new();
|
||||
pa_proplist_sets(proplist, PA_PROP_APPLICATION_NAME, "Efl Volume Control");
|
||||
pa_proplist_sets(proplist, PA_PROP_APPLICATION_ID,
|
||||
|
@ -1512,7 +1514,10 @@ _pulse_connect(void *data)
|
|||
{
|
||||
pa_context_set_state_callback(c->context, _pulse_pa_state_cb, c);
|
||||
if (pa_context_connect(c->context, NULL, PA_CONTEXT_NOFLAGS, NULL) < 0)
|
||||
ERR("Could not connect to pulse");
|
||||
{
|
||||
ret = EINA_TRUE;
|
||||
ERR("Could not connect to pulse");
|
||||
}
|
||||
}
|
||||
#if !defined(EMIXER_BUILD) && defined(HAVE_WAYLAND) && !defined(HAVE_WAYLAND_ONLY)
|
||||
if (e_comp->comp_type != E_PIXMAP_TYPE_X)
|
||||
|
@ -1526,7 +1531,7 @@ _pulse_connect(void *data)
|
|||
#endif
|
||||
|
||||
pa_proplist_free(proplist);
|
||||
return ECORE_CALLBACK_DONE;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static Eina_Bool pulse_started;
|
||||
|
|
Loading…
Reference in New Issue