854 lines
26 KiB
C
854 lines
26 KiB
C
#include "cmd.h"
|
|
#include "sort.h"
|
|
#include "efm.h"
|
|
#include "efm_util.h"
|
|
#include "efm_back_end.h"
|
|
#include "efm_private.h"
|
|
|
|
void
|
|
_size_message(Evas_Object *o, double v)
|
|
{
|
|
Edje_Message_Float msg;
|
|
|
|
// display sqrt of 0.0-?1.0 so we don't have single huge files push every
|
|
// other bar out
|
|
if (v > 0.0) v = sqrt(v);
|
|
msg.val = v;
|
|
edje_object_message_send(o, EDJE_MESSAGE_FLOAT, 1, &msg);
|
|
edje_object_message_signal_process(o);
|
|
}
|
|
|
|
static void
|
|
_size_bars_update(Smart_Data *sd)
|
|
{
|
|
Eina_List *bl, *il;
|
|
Icon *icon;
|
|
Block *block;
|
|
const char *s;
|
|
|
|
if (sd->config.view_mode != EFM_VIEW_MODE_LIST_DETAILED) return;
|
|
EINA_LIST_FOREACH(sd->blocks, bl, block)
|
|
{
|
|
if (block->realized_num <= 0) continue;
|
|
EINA_LIST_FOREACH(block->icons, il, icon)
|
|
{
|
|
if (!icon->realized) continue;
|
|
s = cmd_key_find(icon->cmd, "size");
|
|
if (s)
|
|
{
|
|
unsigned long long size = atoll(s);
|
|
|
|
if (sd->file_max > 0)
|
|
_size_message(icon->o_list_detail_swallow2[0],
|
|
(double)size / (double)sd->file_max);
|
|
else _size_message(icon->o_list_detail_swallow2[0], 0.0);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
static void
|
|
_cb_size_bars_update_job(void *data)
|
|
{
|
|
Smart_Data *sd = data;
|
|
|
|
sd->size_bars_update_job = NULL;
|
|
_size_bars_update(sd);
|
|
}
|
|
|
|
static void
|
|
_size_bars_update_queue(Smart_Data *sd)
|
|
{
|
|
if (sd->size_bars_update_job) ecore_job_del(sd->size_bars_update_job);
|
|
sd->size_bars_update_job = ecore_job_add(_cb_size_bars_update_job, sd);
|
|
}
|
|
|
|
static void
|
|
_cb_size_max_update_job(void *data)
|
|
{
|
|
Smart_Data *sd = data;
|
|
Eina_List *il;
|
|
Icon *icon;
|
|
const char *s;
|
|
unsigned long long new_max = 0;
|
|
|
|
sd->size_max_update_job = NULL;
|
|
EINA_LIST_FOREACH(sd->icons, il, icon)
|
|
{
|
|
s = cmd_key_find(icon->cmd, "size");
|
|
if (s)
|
|
{
|
|
unsigned long long size = atoll(s);
|
|
|
|
if (size > new_max) new_max = size;
|
|
}
|
|
}
|
|
if (sd->file_max != new_max)
|
|
{
|
|
sd->file_max = new_max;
|
|
_size_bars_update_queue(sd);
|
|
}
|
|
}
|
|
|
|
static void
|
|
_size_bars_max_update_queue(Smart_Data *sd)
|
|
{
|
|
if (sd->size_max_update_job) ecore_job_del(sd->size_max_update_job);
|
|
sd->size_max_update_job = ecore_job_add(_cb_size_max_update_job, sd);
|
|
}
|
|
|
|
static void
|
|
_command(Smart_Data *sd, const char *cmd)
|
|
{
|
|
Cmd *c = cmd_parse(cmd);
|
|
Msg *msg;
|
|
void *ref;
|
|
|
|
if (!c) return;
|
|
// send the cmd to our thread to deal with
|
|
msg = eina_thread_queue_send(sd->thread_data->thq, sizeof(Msg), &ref);
|
|
msg->c = c;
|
|
eina_thread_queue_send_done(sd->thread_data->thq, ref);
|
|
}
|
|
|
|
static void
|
|
_process(Smart_Data_Thread *std, Ecore_Thread *th, Eina_List *batch)
|
|
{ // process a batch of commands that come from the back-end open process
|
|
Cmd *c, *c_tmp = NULL;
|
|
Eina_List *batch_new = NULL;
|
|
Eina_List *batch_tmp = NULL;
|
|
|
|
if (!batch) return;
|
|
|
|
// sort batch into batch_new where each set of things like add, mod, del
|
|
// if they are the same cmd then the files are sorted by path. we do this
|
|
// to speed up inserts in the main loop so we can assume a sorted list
|
|
// per batch. this speeds up file adds a lot as we can just do a walk of
|
|
// the batch (as long as commands stay the same like file-add) and then also
|
|
// walk the current file/icon list at the same time and skip to the insert
|
|
// spot which makes inserts very fast as both lists are known to be
|
|
// pre-sorted so at worst we walk N file icons in the current icon list
|
|
// per batch (and loading a dir is probably a series of batches of N
|
|
// file-add's where N is white reasonable
|
|
EINA_LIST_FREE(batch, c)
|
|
{
|
|
c->sort_mode = std->sd->config.sort_mode;
|
|
if (!batch_tmp)
|
|
{
|
|
batch_tmp = eina_list_append(batch_tmp, c);
|
|
c_tmp = c;
|
|
}
|
|
else if ((!strcmp(c->command, c_tmp->command)) &&
|
|
(!strcmp(c->command, "file-add")))
|
|
{
|
|
// works for file-add, file-del, file-mod
|
|
batch_tmp = eina_list_sorted_insert(batch_tmp, sort_cmd, c);
|
|
}
|
|
else
|
|
{
|
|
batch_tmp = eina_list_append(batch_tmp, c);
|
|
batch_new = eina_list_merge(batch_new, batch_tmp);
|
|
batch_tmp = NULL;
|
|
}
|
|
}
|
|
if (batch_tmp)
|
|
{
|
|
batch_new = eina_list_merge(batch_new, batch_tmp);
|
|
batch_tmp = NULL;
|
|
}
|
|
if (batch_new) ecore_thread_feedback(th, batch_new);
|
|
}
|
|
|
|
Eina_Bool
|
|
_cb_exe_del(void *data, int ev_type EINA_UNUSED, void *event)
|
|
{
|
|
Smart_Data *sd = data;
|
|
Ecore_Exe_Event_Del *ev = event;
|
|
Eina_List *l;
|
|
Pending_Exe_Del *pend;
|
|
|
|
// remove this exited slave process from our pending exe deletions
|
|
// this list should be pretty small of pending deletions so we don't
|
|
// need to optimize this with a hash or whatever
|
|
EINA_LIST_FOREACH(_pending_exe_dels, l, pend)
|
|
{
|
|
if (pend->exe == ev->exe)
|
|
{
|
|
pend->exe = NULL;
|
|
if (pend->timer)
|
|
{
|
|
ecore_timer_del(pend->timer);
|
|
pend->timer = NULL;
|
|
}
|
|
free(pend);
|
|
_pending_exe_dels = eina_list_remove_list(_pending_exe_dels, l);
|
|
break;
|
|
}
|
|
}
|
|
if (ev->exe == sd->exe_open)
|
|
{ // this process exiting is the back-end open process for active view
|
|
printf("ERROR: back-end open process died unexpectedly\n");
|
|
return ECORE_CALLBACK_DONE;
|
|
}
|
|
return ECORE_CALLBACK_PASS_ON;
|
|
}
|
|
|
|
Eina_Bool
|
|
_cb_exe_data(void *data, int ev_type EINA_UNUSED, void *event)
|
|
{
|
|
Smart_Data *sd = data;
|
|
Ecore_Exe_Event_Data *ev = event;
|
|
int i;
|
|
|
|
// if this exe doesn't match the view it is for - pass it on and skip
|
|
if (ev->exe != sd->exe_open) return ECORE_CALLBACK_PASS_ON;
|
|
// this exe data is for thijs view
|
|
for (i = 0; ev->lines[i].line; i++) _command(sd, ev->lines[i].line);
|
|
return ECORE_CALLBACK_DONE;
|
|
}
|
|
|
|
Eina_Bool
|
|
_cb_exe_pending_timer(void *data)
|
|
{ // timeout trying to kill off back-end open process
|
|
Pending_Exe_Del *pend = data;
|
|
|
|
pend->timer = NULL;
|
|
_pending_exe_dels = eina_list_remove(_pending_exe_dels, pend);
|
|
if (pend->exe)
|
|
{ // forcibly kill the back-end process as it did not exit on its own
|
|
ecore_exe_kill(pend->exe);
|
|
pend->exe = NULL;
|
|
}
|
|
free(pend);
|
|
return EINA_FALSE;
|
|
}
|
|
|
|
void
|
|
_cb_thread_main(void *data, Ecore_Thread *th)
|
|
{ // thread sits processing commands read from stdout from the back-end open
|
|
Smart_Data_Thread *std = data;
|
|
Msg *msg;
|
|
void *ref;
|
|
Cmd *c;
|
|
Eina_Bool block = EINA_FALSE;
|
|
const char *prev_cmd = NULL;
|
|
Eina_List *batch = NULL;
|
|
|
|
for (;;)
|
|
{ // sit in a loop soaking up commands on the input queue
|
|
if (ecore_thread_check(th)) break;
|
|
if (!block) msg = eina_thread_queue_poll(std->thq, &ref);
|
|
else
|
|
{
|
|
usleep(4000); // wait 4ms to collect more msg's
|
|
msg = eina_thread_queue_wait(std->thq, &ref);
|
|
block = EINA_FALSE;
|
|
}
|
|
if (msg)
|
|
{
|
|
if (!batch)
|
|
{
|
|
batch = eina_list_append(batch, msg->c);
|
|
eina_stringshare_replace(&(prev_cmd), msg->c->command);
|
|
}
|
|
else if ((prev_cmd) && (!strcmp(msg->c->command, prev_cmd)))
|
|
{
|
|
batch = eina_list_append(batch, msg->c);
|
|
}
|
|
else
|
|
{
|
|
_process(std, th, batch);
|
|
batch = NULL;
|
|
eina_stringshare_replace(&(prev_cmd), NULL);
|
|
batch = eina_list_append(batch, msg->c);
|
|
}
|
|
eina_thread_queue_wait_done(std->thq, ref);
|
|
}
|
|
else
|
|
{
|
|
block = EINA_TRUE;
|
|
_process(std, th, batch);
|
|
batch = NULL;
|
|
eina_stringshare_replace(&(prev_cmd), NULL);
|
|
}
|
|
}
|
|
EINA_LIST_FREE(batch, c) { cmd_free(c); }
|
|
eina_stringshare_replace(&(prev_cmd), NULL);
|
|
}
|
|
|
|
static void
|
|
_icon_xy_wh_get(Smart_Data *sd, Icon *icon, Cmd *c)
|
|
{
|
|
const char *s;
|
|
int x, y, w, h, raw_x = INVALID, raw_y = INVALID;
|
|
|
|
s = cmd_key_find(c, "meta.xy");
|
|
if (s)
|
|
{
|
|
if (sscanf(s, "%i,%i", &x, &y) == 2)
|
|
{
|
|
raw_x = x;
|
|
raw_y = y;
|
|
x *= _scale_get(sd);
|
|
y *= _scale_get(sd);
|
|
icon->geom.x = x;
|
|
icon->geom.y = y;
|
|
}
|
|
}
|
|
s = cmd_key_find(c, "meta.wh");
|
|
if (s)
|
|
{
|
|
if (sscanf(s, "%ix%i", &w, &h) == 2)
|
|
{
|
|
if (raw_x == INVALID)
|
|
{
|
|
w = ((raw_x + w) * _scale_get(sd)) - icon->geom.x;
|
|
h = ((raw_y + h) * _scale_get(sd)) - icon->geom.y;
|
|
}
|
|
else
|
|
{
|
|
w *= _scale_get(sd);
|
|
h *= _scale_get(sd);
|
|
}
|
|
icon->geom.w = w;
|
|
icon->geom.h = h;
|
|
}
|
|
}
|
|
}
|
|
|
|
static void
|
|
_max_size_recalc(Smart_Data *sd)
|
|
{
|
|
Icon *icon;
|
|
Eina_List *l;
|
|
|
|
sd->file_max = 0;
|
|
EINA_LIST_FOREACH(sd->icons, l, icon)
|
|
{
|
|
if (icon->info.size > sd->file_max) sd->file_max = icon->info.size;
|
|
}
|
|
}
|
|
|
|
static void
|
|
_icon_add_mod_props_get(Icon *icon, Cmd *c, const char *label)
|
|
{
|
|
const char *s;
|
|
unsigned long long size;
|
|
Eina_Bool recalc = EINA_FALSE, queue = EINA_FALSE;
|
|
|
|
eina_stringshare_replace(&(icon->info.label), label);
|
|
s = cmd_key_find(c, "label-clicked");
|
|
if (!s) s = cmd_key_find(c, "link-label-clicked");
|
|
eina_stringshare_replace(&(icon->info.label_clicked), s);
|
|
s = cmd_key_find(c, "label-selected");
|
|
if (!s) s = cmd_key_find(c, "link-label-selected");
|
|
eina_stringshare_replace(&(icon->info.label_selected), s);
|
|
s = cmd_key_find(c, "mime");
|
|
if (s) eina_stringshare_replace(&(icon->info.mime), s);
|
|
if (s) printf("XXXXX mime=%s\n", icon->info.mime);
|
|
s = cmd_key_find(c, "desktop-icon");
|
|
if (!s) s = cmd_key_find(c, "link-desktop-icon");
|
|
if (s) eina_stringshare_replace(&(icon->info.pre_lookup_icon), s);
|
|
s = cmd_key_find(c, "desktop-icon.lookup");
|
|
if (!s) s = cmd_key_find(c, "link-desktop-icon.lookup");
|
|
if (!s) s = cmd_key_find(c, "icon");
|
|
if ((s) && (s[0] == '/')) eina_stringshare_replace(&(icon->info.icon), s);
|
|
s = cmd_key_find(c, "link-desktop-icon-clicked");
|
|
if (!s) s = cmd_key_find(c, "desktop-icon-clicked");
|
|
if (s) eina_stringshare_replace(&(icon->info.icon_clicked), s);
|
|
s = cmd_key_find(c, "link-desktop-icon-selected");
|
|
if (!s) s = cmd_key_find(c, "desktop-icon-selected");
|
|
if (s) eina_stringshare_replace(&(icon->info.icon_selected), s);
|
|
s = cmd_key_find(c, "mime-icon");
|
|
if (s) eina_stringshare_replace(&(icon->info.mime_icon), s);
|
|
s = cmd_key_find(c, "thumb");
|
|
if (s) eina_stringshare_replace(&(icon->info.thumb), s);
|
|
s = cmd_key_find(c, "broken-link");
|
|
if ((s) && (!strcmp(s, "true"))) icon->info.broken = EINA_TRUE;
|
|
else icon->info.broken = EINA_FALSE;
|
|
s = cmd_key_find(c, "size");
|
|
if (s)
|
|
{
|
|
size = atoll(s);
|
|
|
|
if ((icon->info.size == icon->sd->file_max) && // icon already max size
|
|
(size < icon->sd->file_max)) // new size is now less
|
|
{
|
|
recalc = EINA_TRUE; // need to recalc what is max
|
|
queue = EINA_TRUE; // we need to also update all bars
|
|
}
|
|
icon->info.size = size;
|
|
if (size > icon->sd->file_max)
|
|
{ // new size is bigger than prev max size
|
|
icon->sd->file_max = size;
|
|
queue = EINA_TRUE; // queue all size bar updates
|
|
}
|
|
if (recalc) _max_size_recalc(icon->sd);
|
|
if (queue) _size_bars_update_queue(icon->sd);
|
|
}
|
|
}
|
|
|
|
static Eina_Bool
|
|
_cb_smart_timer(void *data)
|
|
{
|
|
Smart_Data_Timer *st = data;
|
|
Eina_Strbuf *buf = cmd_strbuf_new("timer");
|
|
|
|
cmd_strbuf_append(buf, "name", st->name);
|
|
cmd_strbuf_exe_consume(buf, st->sd->exe_open);
|
|
if (st->repeat) return EINA_TRUE;
|
|
st->sd->timers = eina_list_remove(st->sd->timers, st);
|
|
eina_stringshare_del(st->name);
|
|
free(st);
|
|
return EINA_FALSE;
|
|
}
|
|
|
|
void
|
|
_cb_thread_notify(void *data, Ecore_Thread *th EINA_UNUSED, void *msg)
|
|
{ // handle data from the view thread to the UI - this will be a batch of cmds
|
|
Smart_Data_Thread *std = data;
|
|
Smart_Data *sd = std->sd;
|
|
Eina_List *batch = msg;
|
|
Cmd *c, *cprev = NULL;
|
|
Eina_List *l, *il2, *il = NULL;
|
|
Icon *icon, *icon2;
|
|
Block *block;
|
|
const char *path, *file, *label, *s;
|
|
int file_adds = 0, file_dels = 0, tries = 0;
|
|
Eina_Bool found;
|
|
|
|
if (!sd)
|
|
{ // on cusp point - view gone but buffered thread feedback exists
|
|
EINA_LIST_FREE(batch, c) cmd_free(c);
|
|
return;
|
|
}
|
|
EINA_LIST_FOREACH(batch, l, c)
|
|
{
|
|
c->sort_mode = sd->config.sort_mode;
|
|
#define CMD_DONE \
|
|
cmd_free(c); \
|
|
continue
|
|
if (!strcmp(c->command, "list-begin"))
|
|
{
|
|
printf("XXXXX LIST BEGIN\n");
|
|
edje_object_part_text_set(sd->o_overlay_info, "e.text.busy_label",
|
|
"Loading");
|
|
edje_object_signal_emit(sd->o_overlay_info, "e,state,busy,start", "e");
|
|
CMD_DONE;
|
|
}
|
|
else if (!strcmp(c->command, "list-end"))
|
|
{
|
|
printf("XXXXX LIST END\n");
|
|
edje_object_signal_emit(sd->o_overlay_info, "e,state,busy,stop", "e");
|
|
// reblock on end of listing
|
|
if (sd->reblock_job) ecore_job_del(sd->reblock_job);
|
|
sd->reblock_job = ecore_job_add(_cb_reblock, sd);
|
|
sd->listing_done_reblock = EINA_TRUE;
|
|
CMD_DONE;
|
|
}
|
|
else if (!strcmp(c->command, "timer-add"))
|
|
{
|
|
const char *name = cmd_key_find(c, "name");
|
|
const char *delay = cmd_key_find(c, "delay");
|
|
const char *repeat = cmd_key_find(c, "repeat");
|
|
|
|
if (name && delay)
|
|
{
|
|
Smart_Data_Timer *st = calloc(1, sizeof(Smart_Data_Timer));
|
|
|
|
if (st)
|
|
{
|
|
st->sd = sd;
|
|
st->name = eina_stringshare_add(name);
|
|
st->repeat = repeat ? EINA_TRUE : EINA_FALSE;
|
|
st->delay = (double)atoi(delay) / 1000.0;
|
|
st->timer = ecore_timer_add(st->delay, _cb_smart_timer, st);
|
|
sd->timers = eina_list_append(sd->timers, st);
|
|
}
|
|
}
|
|
CMD_DONE;
|
|
}
|
|
else if (!strcmp(c->command, "timer-del"))
|
|
{
|
|
const char *name = cmd_key_find(c, "name");
|
|
Smart_Data_Timer *st;
|
|
Eina_List *l;
|
|
|
|
if (name)
|
|
{
|
|
EINA_LIST_FOREACH(sd->timers, l, st)
|
|
{
|
|
if (!strcmp(st->name, name))
|
|
{
|
|
sd->timers = eina_list_remove_list(sd->timers, l);
|
|
eina_stringshare_del(st->name);
|
|
ecore_timer_del(st->timer);
|
|
free(st);
|
|
}
|
|
}
|
|
}
|
|
CMD_DONE;
|
|
}
|
|
else if (!strcmp(c->command, "backend-set"))
|
|
{ // *** must call before list-begin
|
|
const char *backend = cmd_key_find(c, "backend");
|
|
|
|
if (backend)
|
|
{
|
|
eina_stringshare_replace(&(sd->config.backend), backend);
|
|
_reset(sd);
|
|
}
|
|
CMD_DONE;
|
|
}
|
|
else if (!strcmp(c->command, "viewmode-set"))
|
|
{ // must call before list-begin
|
|
const char *mode = cmd_key_find(c, "mode");
|
|
|
|
if (mode)
|
|
{
|
|
Efm_View_Mode view_mode = sd->config.view_mode;
|
|
|
|
if (!strcmp(mode, "icons"))
|
|
view_mode = EFM_VIEW_MODE_ICONS;
|
|
else if (!strcmp(mode, "icons_custom"))
|
|
view_mode = EFM_VIEW_MODE_ICONS_CUSTOM;
|
|
else if (!strcmp(mode, "list"))
|
|
view_mode = EFM_VIEW_MODE_LIST;
|
|
else if (!strcmp(mode, "list_detailed"))
|
|
view_mode = EFM_VIEW_MODE_LIST_DETAILED;
|
|
if (view_mode != sd->config.view_mode)
|
|
{
|
|
int i;
|
|
|
|
sd->config.view_mode = view_mode;
|
|
for (i = 0; i < 6; i++)
|
|
{
|
|
if (sd->config.view_mode == EFM_VIEW_MODE_LIST_DETAILED)
|
|
evas_object_show(sd->o_list_detail[i]);
|
|
else evas_object_hide(sd->o_list_detail[i]);
|
|
}
|
|
if (sd->header_change_job)
|
|
ecore_job_del(sd->header_change_job);
|
|
sd->header_change_job = ecore_job_add(_cb_header_change, sd);
|
|
}
|
|
}
|
|
CMD_DONE;
|
|
}
|
|
else if (!strcmp(c->command, "detail-header-set"))
|
|
{
|
|
const char *col = cmd_key_find(c, "col");
|
|
|
|
if (col)
|
|
{
|
|
int colnum = atoi(col);
|
|
|
|
if ((colnum >= 0) && (colnum <= 6))
|
|
{
|
|
const char *label = cmd_key_find(c, "label");
|
|
const char *size = cmd_key_find(c, "size");
|
|
// XXX: support icon in future?
|
|
|
|
if (label)
|
|
{
|
|
eina_stringshare_replace
|
|
(&(sd->config.detail_heading[colnum]), label);
|
|
if (sd->o_detail_header_item[colnum])
|
|
elm_object_text_set(sd->o_detail_header_item[colnum],
|
|
sd->config.detail_heading[colnum]);
|
|
}
|
|
if ((size) && (colnum >= 1))
|
|
{ // can't set width of col 0 - always "rest of width"
|
|
int sz = atoi(size);
|
|
|
|
sd->config.detail_min_w[colnum - 1] = sz;
|
|
_redo_detail_sizes(sd);
|
|
}
|
|
}
|
|
}
|
|
CMD_DONE;
|
|
}
|
|
|
|
// below commands all send a path for a specific file
|
|
path = file = cmd_key_find(c, "path");
|
|
printf("XXXXX [%s] [%s]\n", c->command, file);
|
|
if (file)
|
|
{
|
|
s = strrchr(file, '/');
|
|
if (s) file = s + 1;
|
|
if (file[0] == '.') // XXX filter dot files or not
|
|
{
|
|
CMD_DONE;
|
|
}
|
|
}
|
|
if ((!file) || (!file[0]))
|
|
{ // somehow we didn't get a sane filename from the back-end
|
|
CMD_DONE;
|
|
}
|
|
if (!strcmp(c->command, "dir-request"))
|
|
{
|
|
char *path2;
|
|
|
|
path2 = _sanitize_dir(path);
|
|
eina_stringshare_replace(&sd->config.path, path2);
|
|
free(path2);
|
|
_reset(sd);
|
|
CMD_DONE;
|
|
}
|
|
label = cmd_key_find(c, "link-label");
|
|
if (!label) label = cmd_key_find(c, "label");
|
|
|
|
if ((!cprev) || (!!strcmp(cprev->command, c->command)))
|
|
{ // we start a new batch of commands - these are sorted
|
|
il = sd->icons;
|
|
}
|
|
|
|
if (!strcmp(c->command, "file-add"))
|
|
{
|
|
icon = calloc(1, sizeof(Icon));
|
|
if (!icon) abort();
|
|
|
|
file_adds++;
|
|
// initial "invalid" xy for custom location - meta overrides
|
|
icon->geom.x = INVALID;
|
|
icon->geom.y = INVALID;
|
|
icon->geom.w = INVALID;
|
|
icon->geom.h = INVALID;
|
|
icon->sd = sd;
|
|
icon->cmd = c;
|
|
icon->changed = EINA_TRUE;
|
|
icon->info.file = eina_stringshare_add(file);
|
|
|
|
_icon_add_mod_props_get(icon, c, label);
|
|
|
|
// handle raw "stat" type and set mime accordingly if needed
|
|
// this can't change on a file - it'd have to be deleted and
|
|
// added again to do this.
|
|
s = cmd_key_find(c, "type");
|
|
if (s)
|
|
{
|
|
if (!strcmp(s, "link"))
|
|
{
|
|
icon->info.link = EINA_TRUE;
|
|
s = cmd_key_find(c, "link-type");
|
|
}
|
|
if (s)
|
|
{
|
|
if (!strcmp(s, "dir"))
|
|
{
|
|
icon->info.dir = EINA_TRUE;
|
|
eina_stringshare_replace((&icon->info.mime),
|
|
"inode/directory");
|
|
}
|
|
else if (!strcmp(s, "block"))
|
|
{
|
|
icon->info.special = EINA_TRUE;
|
|
eina_stringshare_replace((&icon->info.mime),
|
|
"inode/blockdevice");
|
|
}
|
|
else if (!strcmp(s, "char"))
|
|
{
|
|
icon->info.special = EINA_TRUE;
|
|
eina_stringshare_replace((&icon->info.mime),
|
|
"inode/chardevice");
|
|
}
|
|
else if (!strcmp(s, "fifo"))
|
|
{
|
|
icon->info.special = EINA_TRUE;
|
|
eina_stringshare_replace((&icon->info.mime), "inode/fifo");
|
|
}
|
|
else if (!strcmp(s, "socket"))
|
|
{
|
|
icon->info.special = EINA_TRUE;
|
|
eina_stringshare_replace((&icon->info.mime),
|
|
"inode/socket");
|
|
}
|
|
}
|
|
}
|
|
if (!icon->info.mime)
|
|
eina_stringshare_replace((&icon->info.mime), "inode/file");
|
|
|
|
_icon_xy_wh_get(sd, icon, c);
|
|
|
|
// insert the icon in the right place in the list
|
|
for (; il; il = il->next)
|
|
{
|
|
icon2 = il->data;
|
|
if (!strcmp(file, icon2->info.file))
|
|
{ // handle the case we get an add for an existing file
|
|
file_dels++;
|
|
il2 = il->next;
|
|
sd->icons = eina_list_remove_list(sd->icons, il);
|
|
il = il2;
|
|
if (sd->last_focused)
|
|
{
|
|
// XXX: select prev or next icon
|
|
}
|
|
s = cmd_key_find(icon->cmd, "size");
|
|
if (s)
|
|
{
|
|
unsigned long long size = atoll(s);
|
|
|
|
if (size == sd->file_max) _size_bars_max_update_queue(sd);
|
|
}
|
|
_icon_free(icon2);
|
|
if (il) icon2 = il->data;
|
|
else break;
|
|
}
|
|
if (sort_cmd(icon2->cmd, icon->cmd) > 0)
|
|
{
|
|
sd->icons
|
|
= eina_list_prepend_relative_list(sd->icons, icon, il);
|
|
break;
|
|
}
|
|
}
|
|
if (!il) sd->icons = eina_list_append(sd->icons, icon);
|
|
}
|
|
else if (!strcmp(c->command, "file-mod"))
|
|
{
|
|
for (found = EINA_FALSE, tries = 0; (!found) && (tries < 2); tries++)
|
|
{
|
|
for (; il; il = il->next)
|
|
{
|
|
icon = il->data;
|
|
if (!strcmp(file, icon->info.file))
|
|
{
|
|
icon->changed = EINA_TRUE;
|
|
|
|
_icon_add_mod_props_get(icon, c, label);
|
|
|
|
_icon_xy_wh_get(sd, icon, c);
|
|
|
|
cmd_free(icon->cmd);
|
|
icon->cmd = c;
|
|
found = EINA_TRUE;
|
|
break;
|
|
}
|
|
}
|
|
if (!il) il = sd->icons;
|
|
}
|
|
}
|
|
else if (!strcmp(c->command, "file-del"))
|
|
{
|
|
for (found = EINA_FALSE, tries = 0; (!found) && (tries < 2); tries++)
|
|
{
|
|
for (; il; il = il->next)
|
|
{
|
|
icon = il->data;
|
|
if (!strcmp(file, icon->info.file))
|
|
{
|
|
file_dels++;
|
|
il2 = il->next;
|
|
sd->icons = eina_list_remove_list(sd->icons, il);
|
|
il = il2;
|
|
if (sd->last_focused)
|
|
{
|
|
// XXX: select prev or next icon
|
|
}
|
|
if (icon->info.size == icon->sd->file_max)
|
|
{ // this icon is at max size in dir
|
|
_max_size_recalc(icon->sd); // find new max
|
|
_size_bars_update_queue(icon->sd); // redo all bars
|
|
}
|
|
_icon_free(icon);
|
|
found = EINA_TRUE;
|
|
break;
|
|
}
|
|
}
|
|
if (!il) il = sd->icons;
|
|
}
|
|
cmd_free(c);
|
|
c = NULL;
|
|
}
|
|
else if (!strcmp(c->command, "file-detail"))
|
|
{
|
|
int n;
|
|
const char *theme_edj_file;
|
|
char **plist;
|
|
char bufdetail[16];
|
|
|
|
theme_edj_file
|
|
= elm_theme_group_path_find(NULL, "e/fileman/default/icon/fixed");
|
|
for (found = EINA_FALSE, tries = 0; (!found) && (tries < 2); tries++)
|
|
{
|
|
for (n = 0; il; il = il->next, n++)
|
|
{
|
|
icon = il->data;
|
|
if (!strcmp(file, icon->info.file))
|
|
{
|
|
int i;
|
|
|
|
s = cmd_key_find(icon->cmd, "detail-format");
|
|
if (s)
|
|
{
|
|
plist = eina_str_split(s, ",", 6);
|
|
if (plist)
|
|
{
|
|
for (i = 0; plist[i];) i++;
|
|
if (i >= 6)
|
|
{
|
|
for (i = 1; i < 7; i++)
|
|
{
|
|
snprintf(bufdetail, sizeof(bufdetail),
|
|
"detail%i", i);
|
|
s = cmd_key_find(c, bufdetail);
|
|
if (s)
|
|
{
|
|
icon->cmd
|
|
= cmd_modify(icon->cmd, bufdetail, s);
|
|
if (icon->realized)
|
|
_icon_detail_add(
|
|
icon, icon->sd,
|
|
evas_object_evas_get(icon->o_base),
|
|
theme_edj_file, i - 1, s,
|
|
plist[i - 1]);
|
|
}
|
|
}
|
|
}
|
|
free(*plist);
|
|
free(plist);
|
|
}
|
|
}
|
|
found = EINA_TRUE;
|
|
break;
|
|
}
|
|
}
|
|
cmd_free(c);
|
|
c = NULL;
|
|
}
|
|
}
|
|
cprev = c;
|
|
}
|
|
eina_list_free(batch);
|
|
if ((sd->config.view_mode >= EFM_VIEW_MODE_LIST)
|
|
&& ((file_adds > 0) || (file_dels > 0)))
|
|
{ // if it's one of the list modes, unrealize realized icons
|
|
EINA_LIST_FOREACH(sd->blocks, l, block)
|
|
{
|
|
if (block->realized_num <= 0) continue;
|
|
EINA_LIST_FOREACH(block->icons, il, icon)
|
|
{ // unrealize the icon - list odd/even forces this
|
|
if (!icon->realized) continue;
|
|
icon->realized = EINA_FALSE;
|
|
icon->block->realized_num--;
|
|
_icon_object_clear(icon);
|
|
}
|
|
}
|
|
}
|
|
if (sd->reblock_job) ecore_job_del(sd->reblock_job);
|
|
sd->reblock_job = ecore_job_add(_cb_reblock, sd);
|
|
}
|
|
|
|
void
|
|
_cb_thread_done(void *data, Ecore_Thread *th EINA_UNUSED)
|
|
{
|
|
Smart_Data_Thread *std = data;
|
|
|
|
if (std->sd) std->sd->thread_data = NULL;
|
|
if (std->thq)
|
|
{
|
|
eina_thread_queue_free(std->thq);
|
|
std->thq = NULL;
|
|
}
|
|
free(std);
|
|
}
|