raster pushed a commit to branch master.

http://git.enlightenment.org/core/enlightenment.git/commit/?id=8b16ea75a0ad4a81055b76ae4d3404542da836da

commit 8b16ea75a0ad4a81055b76ae4d3404542da836da
Author: Carsten Haitzler <[email protected]>
Date:   Sat Oct 9 11:59:59 2021 +0100

    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
---
 src/bin/e_exec.c                                  | 154 ++++++++++++++++++++++
 src/bin/e_exec.h                                  |   8 ++
 src/modules/fileman/e_fwin.c                      |   6 +-
 src/modules/fileman/e_mod_main.h                  |   2 +
 src/modules/fileman/e_mod_menu.c                  | 120 +++++++++++++++++
 src/modules/mixer/lib/backends/pulseaudio/pulse.c |   9 +-
 6 files changed, 294 insertions(+), 5 deletions(-)

diff --git a/src/bin/e_exec.c b/src/bin/e_exec.c
index 40cd0f344..13ae1ed3b 100644
--- a/src/bin/e_exec.c
+++ b/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);
diff --git a/src/bin/e_exec.h b/src/bin/e_exec.h
index c6de54c5e..905216f20 100644
--- a/src/bin/e_exec.h
+++ b/src/bin/e_exec.h
@@ -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);
diff --git a/src/modules/fileman/e_fwin.c b/src/modules/fileman/e_fwin.c
index c991879b5..0df9c8b59 100644
--- a/src/modules/fileman/e_fwin.c
+++ b/src/modules/fileman/e_fwin.c
@@ -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;
 
diff --git a/src/modules/fileman/e_mod_main.h b/src/modules/fileman/e_mod_main.h
index 7b01e2f42..f5d930dd0 100644
--- a/src/modules/fileman/e_mod_main.h
+++ b/src/modules/fileman/e_mod_main.h
@@ -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
  * @{
diff --git a/src/modules/fileman/e_mod_menu.c b/src/modules/fileman/e_mod_menu.c
index e4446b375..6b2af064a 100644
--- a/src/modules/fileman/e_mod_menu.c
+++ b/src/modules/fileman/e_mod_menu.c
@@ -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);
 }
diff --git a/src/modules/mixer/lib/backends/pulseaudio/pulse.c 
b/src/modules/mixer/lib/backends/pulseaudio/pulse.c
index 7ac3be0de..327a58f46 100644
--- a/src/modules/mixer/lib/backends/pulseaudio/pulse.c
+++ b/src/modules/mixer/lib/backends/pulseaudio/pulse.c
@@ -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;

-- 


Reply via email to