static E_Fm2_Client *_e_fm2_client_get(void);
static int _e_fm2_client_monitor_add(const char *path);
static void _e_fm2_client_monitor_del(int id, const char *path);
-static int _e_fm_client_file_del(const char *args);
-static int _e_fm2_client_file_trash(const char *path);
-static int _e_fm2_client_file_mkdir(const char *path, const char *rel, int rel_to, int x, int y, int res_w, int res_h);
-static int _e_fm_client_file_move(const char *args);
-static int _e_fm2_client_file_symlink(const char *path, const char *dest, const char *rel, int rel_to, int x, int y, int res_w, int res_h);
-static int _e_fm_client_file_copy(const char *args);
-static int _e_fm_client_file_symlink(const char *args);
+static int _e_fm_client_file_del(const char *args, Evas_Object *e_fm);
+static int _e_fm2_client_file_trash(const char *path, Evas_Object *e_fm);
+static int _e_fm2_client_file_mkdir(const char *path, const char *rel, int rel_to, int x, int y, int res_w, int res_h, Evas_Object *e_fm);
+static int _e_fm_client_file_move(const char *args, Evas_Object *e_fm);
+static int _e_fm2_client_file_symlink(const char *path, const char *dest, const char *rel, int rel_to, int x, int y, int res_w, int res_h, Evas_Object *e_fm);
+static int _e_fm_client_file_copy(const char *args, Evas_Object *e_fm);
+static int _e_fm_client_file_symlink(const char *args, Evas_Object *e_fm);
static void _e_fm2_sel_rect_update(void *data);
static inline void _e_fm2_context_menu_append(Evas_Object *obj, const char *path, Eina_List *l, E_Menu *mn, E_Fm2_Icon *ic);
return 1;
}
+static void
+_e_fm2_op_registry_go_on(int id)
+{
+ E_Fm2_Op_Registry_Entry *ere = e_fm2_op_registry_entry_get(id);
+ if (!ere) return;
+ ere->status = E_FM2_OP_STATUS_IN_PROGRESS;
+ ere->needs_attention = 0;
+ e_fm2_op_registry_entry_changed(ere);
+}
+
+static void
+_e_fm2_op_registry_aborted(int id)
+{
+ E_Fm2_Op_Registry_Entry *ere = e_fm2_op_registry_entry_get(id);
+ if (!ere) return;
+ ere->status = E_FM2_OP_STATUS_ABORTED;
+ ere->needs_attention = 0;
+ ere->finished = 1;
+ e_fm2_op_registry_entry_changed(ere);
+ // XXX e_fm2_op_registry_entry_del(id);
+}
+
+static void
+_e_fm2_op_registry_error(int id)
+{
+ E_Fm2_Op_Registry_Entry *ere = e_fm2_op_registry_entry_get(id);
+ if (!ere) return;
+ ere->status = E_FM2_OP_STATUS_ERROR;
+ ere->needs_attention = 1;
+ e_fm2_op_registry_entry_changed(ere);
+}
+
+static void
+_e_fm2_op_registry_needs_attention(int id)
+{
+ E_Fm2_Op_Registry_Entry *ere = e_fm2_op_registry_entry_get(id);
+ if (!ere) return;
+ ere->needs_attention = 1;
+ e_fm2_op_registry_entry_changed(ere);
+}
+
+/////////////// DBG:
+static void
+_e_fm2_op_registry_entry_print(const E_Fm2_Op_Registry_Entry *ere)
+{
+ const char *status_strings[] = {
+ "UNKNOWN", "IN_PROGRESS", "SUCCESSFUL", "ABORTED", "ERROR"
+ };
+ const char *status;
+
+ if ((ere->status >= 0) &&
+ (ere->status < sizeof(status_strings)/sizeof(status_strings[0])))
+ status = status_strings[ere->status];
+ else
+ status = status_strings[0];
+
+ printf("id: %8d, op: %2d [%s] finished: %hhu, needs_attention: %hhu\n"
+ " %3d%% (%8zd/%8zd), time: %10.0f + %5ds, xwin: %#x\n"
+ " src=[%s]\n"
+ " dst=[%s]\n",
+ ere->id, ere->op, status, ere->finished, ere->needs_attention,
+ ere->percent, ere->done, ere->total, ere->start_time, ere->duration,
+ e_fm2_op_registry_entry_xwin_get(ere),
+ ere->src, ere->dst);
+}
+
+static int
+_e_fm2_op_registry_entry_add_cb(void *data, int type, void *event)
+{
+ const E_Fm2_Op_Registry_Entry *ere = event;
+ printf("E FM OPERATION STARTED: id=%d, op=%d\n", ere->id, ere->op);
+ return ECORE_CALLBACK_RENEW;
+}
+
+static int
+_e_fm2_op_registry_entry_del_cb(void *data, int type, void *event)
+{
+ const E_Fm2_Op_Registry_Entry *ere = event;
+ puts("E FM OPERATION FINISHED:");
+ _e_fm2_op_registry_entry_print(ere);
+ puts("---");
+ return ECORE_CALLBACK_RENEW;
+}
+
+static int
+_e_fm2_op_registry_entry_changed_cb(void *data, int type, void *event)
+{
+ const E_Fm2_Op_Registry_Entry *ere = event;
+ puts("E FM OPERATION CHANGED:");
+ _e_fm2_op_registry_entry_print(ere);
+ puts("---");
+ return ECORE_CALLBACK_RENEW;
+}
+
+static Ecore_Event_Handler *_e_fm2_op_registry_entry_add_handler = NULL;
+static Ecore_Event_Handler *_e_fm2_op_registry_entry_del_handler = NULL;
+static Ecore_Event_Handler *_e_fm2_op_registry_entry_changed_handler = NULL;
+/////////////// DBG:
+
/***/
EAPI int
}
// _e_fm2_client_spawn();
e_fm2_custom_file_init();
+ e_fm2_op_registry_init();
efreet_mime_init();
/* XXX: move this to a central/global place? */
_e_fm2_mime_app_desktop = eina_stringshare_add("application/x-desktop");
_e_fm2_mime_app_edje = eina_stringshare_add("application/x-edje");
+ /// DBG
+ if (!_e_fm2_op_registry_entry_add_handler)
+ _e_fm2_op_registry_entry_add_handler =
+ ecore_event_handler_add(E_EVENT_FM_OP_REGISTRY_ADD,
+ _e_fm2_op_registry_entry_add_cb, NULL);
+ if (!_e_fm2_op_registry_entry_del_handler)
+ _e_fm2_op_registry_entry_del_handler =
+ ecore_event_handler_add(E_EVENT_FM_OP_REGISTRY_DEL,
+ _e_fm2_op_registry_entry_del_cb, NULL);
+ if (!_e_fm2_op_registry_entry_changed_handler)
+ _e_fm2_op_registry_entry_changed_handler =
+ ecore_event_handler_add(E_EVENT_FM_OP_REGISTRY_CHANGED,
+ _e_fm2_op_registry_entry_changed_cb, NULL);
+ /// DBG
+
return 1;
}
_eina_stringshare_replace(&_e_fm2_mime_app_desktop, NULL);
_eina_stringshare_replace(&_e_fm2_mime_app_edje, NULL);
+ /// DBG
+ if (_e_fm2_op_registry_entry_add_handler)
+ {
+ ecore_event_handler_del(_e_fm2_op_registry_entry_add_handler);
+ _e_fm2_op_registry_entry_add_handler = NULL;
+ }
+ if (_e_fm2_op_registry_entry_del_handler)
+ {
+ ecore_event_handler_del(_e_fm2_op_registry_entry_del_handler);
+ _e_fm2_op_registry_entry_del_handler = NULL;
+ }
+ if (_e_fm2_op_registry_entry_changed_handler)
+ {
+ ecore_event_handler_del(_e_fm2_op_registry_entry_changed_handler);
+ _e_fm2_op_registry_entry_changed_handler = NULL;
+ }
+ /// DBG
+
ecore_timer_del(_e_fm2_mime_flush);
_e_fm2_mime_flush = NULL;
ecore_timer_del(_e_fm2_mime_clear);
E_FREE(_e_fm2_meta_path);
e_fm2_custom_file_shutdown();
_e_storage_volume_edd_shutdown();
+ e_fm2_op_registry_shutdown();
efreet_mime_shutdown();
ecore_job_shutdown();
eina_stringshare_shutdown();
}
static int
-_e_fm_client_file_del(const char *files)
+_e_fm_client_file_del(const char *files, Evas_Object *e_fm)
{
- return _e_fm_client_send_new(E_FM_OP_REMOVE, (void *)files, strlen(files) + 1);
+ int id = _e_fm_client_send_new(E_FM_OP_REMOVE, (void *)files, strlen(files) + 1);
+ e_fm2_op_registry_entry_add(id, e_fm, E_FM_OP_REMOVE);
+ return id;
}
static int
-_e_fm2_client_file_trash(const char *path)
+_e_fm2_client_file_trash(const char *path, Evas_Object *e_fm)
{
- return _e_fm_client_send_new(E_FM_OP_TRASH, (void *)path, strlen(path) + 1);
+ int id = _e_fm_client_send_new(E_FM_OP_TRASH, (void *)path, strlen(path) + 1);
+ e_fm2_op_registry_entry_add(id, e_fm, E_FM_OP_TRASH);
+ return id;
}
static int
-_e_fm2_client_file_mkdir(const char *path, const char *rel, int rel_to, int x, int y, int res_w, int res_h)
+_e_fm2_client_file_mkdir(const char *path, const char *rel, int rel_to, int x, int y, int res_w, int res_h, Evas_Object *e_fm)
{
char *d;
- int l1, l2, l;
+ int l1, l2, l, id;
l1 = strlen(path);
l2 = strlen(rel);
memcpy(d + l1 + 1 + l2 + 1 + sizeof(int), &x, sizeof(int));
memcpy(d + l1 + 1 + l2 + 1 + (2 * sizeof(int)), &y, sizeof(int));
- return _e_fm_client_send_new(E_FM_OP_MKDIR, (void *)d, l);
+ id = _e_fm_client_send_new(E_FM_OP_MKDIR, (void *)d, l);
+ e_fm2_op_registry_entry_add(id, e_fm, E_FM_OP_MKDIR);
+ return id;
}
static int
-_e_fm_client_file_move(const char *args)
+_e_fm_client_file_move(const char *args, Evas_Object *e_fm)
{
- return _e_fm_client_send_new(E_FM_OP_MOVE, (void *)args, strlen(args) + 1);
+ int id = _e_fm_client_send_new(E_FM_OP_MOVE, (void *)args, strlen(args) + 1);
+ printf("REQUEST CLIENT TO MOVE: %s, id=%d, op=%d\n", args, id, E_FM_OP_MOVE);
+ e_fm2_op_registry_entry_add(id, e_fm, E_FM_OP_MOVE);
+ return id;
}
static int
-_e_fm2_client_file_symlink(const char *path, const char *dest, const char *rel, int rel_to, int x, int y, int res_w, int res_h)
+_e_fm2_client_file_symlink(const char *path, const char *dest, const char *rel, int rel_to, int x, int y, int res_w, int res_h, Evas_Object *e_fm)
{
#if 0
char *d;
- int l1, l2, l3, l;
+ int l1, l2, l3, l, id;
l1 = strlen(path);
l2 = strlen(dest);
e_fm2_custom_file_flush();
}
- return _e_fm_client_send_new(E_FM_OP_SYMLINK, (void *)d, l);
+ id = _e_fm_client_send_new(E_FM_OP_SYMLINK, (void *)d, l);
+ e_fm2_op_registry_entry_add(id, e_fm, E_FM_OP_SYMLINK);
+ return id;
#else
char *args = NULL;
size_t size = 0, length = 0;
args = _e_fm_string_append_quoted(args, &size, &length, dest);
fputs("WARNING: using new E_FM_OP_SYMLINK, remove deprecated ASAP\n", stderr);
- int r = _e_fm_client_file_symlink(args);
+ int r = _e_fm_client_file_symlink(args, e_fm);
free(args);
return r;
#endif
}
static int
-_e_fm_client_file_copy(const char *args)
+_e_fm_client_file_copy(const char *args, Evas_Object *e_fm)
{
- return _e_fm_client_send_new(E_FM_OP_COPY, (void *)args, strlen(args) + 1);
+ int id = _e_fm_client_send_new(E_FM_OP_COPY, (void *)args, strlen(args) + 1);
+ printf("REQUEST CLIENT TO COPY: %s, id=%d, op=%d\n", args, id, E_FM_OP_COPY);
+ e_fm2_op_registry_entry_add(id, e_fm, E_FM_OP_COPY);
+ return id;
}
static int
-_e_fm_client_file_symlink(const char *args)
+_e_fm_client_file_symlink(const char *args, Evas_Object *e_fm)
{
- return _e_fm_client_send_new(E_FM_OP_SYMLINK, (void *)args, strlen(args) + 1);
+ int id = _e_fm_client_send_new(E_FM_OP_SYMLINK, (void *)args, strlen(args) + 1);
+ e_fm2_op_registry_entry_add(id, e_fm, E_FM_OP_SYMLINK);
+ return id;
}
EAPI int
break;
case E_FM_OP_ERROR:/*error*/
- printf("%s:%s(%d) Error from slave #%d: %s\n", __FILE__, __FUNCTION__, __LINE__, e->ref, (char *)e->data);
- _e_fm_error_dialog(e->ref, e->data);
+ printf("%s:%s(%d) Error from slave #%d: %s\n", __FILE__, __FUNCTION__, __LINE__, e->ref, (char *)e->data);
+ _e_fm_error_dialog(e->ref, e->data);
+ _e_fm2_op_registry_error(e->ref);
break;
case E_FM_OP_ERROR_RETRY_ABORT:/*error*/
- printf("%s:%s(%d) Error from slave #%d: %s\n", __FILE__, __FUNCTION__, __LINE__, e->ref, (char *)e->data);
- _e_fm_retry_abort_dialog(e->ref, (char *)e->data);
+ printf("%s:%s(%d) Error from slave #%d: %s\n", __FILE__, __FUNCTION__, __LINE__, e->ref, (char *)e->data);
+ _e_fm_retry_abort_dialog(e->ref, (char *)e->data);
+ _e_fm2_op_registry_error(e->ref);
break;
case E_FM_OP_OVERWRITE:/*overwrite*/
- printf("%s:%s(%d) Overwrite from slave #%d: %s\n", __FILE__, __FUNCTION__, __LINE__, e->ref, (char *)e->data);
- _e_fm_overwrite_dialog(e->ref, (char *)e->data);
+ printf("%s:%s(%d) Overwrite from slave #%d: %s\n", __FILE__, __FUNCTION__, __LINE__, e->ref, (char *)e->data);
+ _e_fm_overwrite_dialog(e->ref, (char *)e->data);
+ _e_fm2_op_registry_needs_attention(e->ref);
break;
case E_FM_OP_PROGRESS:/*progress*/
#undef UP
src = p;
dst = p + strlen(src) + 1;
- printf("%s:%s(%d) Progress from slave #%d:\n\t%d%% done,\n\t%d seconds left,\n\t%d done,\n\t%d total,\n\tsrc = %s,\n\tdst = %s.\n", __FILE__, __FUNCTION__, __LINE__, e->ref, percent, seconds, done, total, src, dst);
+ // printf("%s:%s(%d) Progress from slave #%d:\n\t%d%% done,\n\t%d seconds left,\n\t%zd done,\n\t%zd total,\n\tsrc = %s,\n\tdst = %s.\n", __FILE__, __FUNCTION__, __LINE__, e->ref, percent, seconds, done, total, src, dst);
+
+ E_Fm2_Op_Registry_Entry *ere = e_fm2_op_registry_entry_get(e->ref);
+ if (!ere) return;
+ ere->percent = percent;
+ ere->done = done;
+ ere->total = total;
+ ere->duration = seconds;
+ e_fm2_op_registry_entry_files_set(ere, src, dst);
+ if (ere->percent == 100)
+ {
+ ere->status = E_FM2_OP_STATUS_SUCCESSFUL;
+ ere->finished = 1;
+ }
+ e_fm2_op_registry_entry_changed(ere);
}
break;
+ case E_FM_OP_QUIT:/*finished*/
+ e_fm2_op_registry_entry_del(e->ref);
+ break;
+
default:
break;
}
int bufused, buffree;
const char *realpath;
const E_Fm2_Icon_Info *ici;
+ Eina_Bool ret;
sel = e_fm2_selected_list_get(obj);
if (!sel) return 0;
pfile = buf + bufused;
buffree = sizeof(buf) - bufused;
+ ret = !!sel;
EINA_LIST_FREE(sel, ici)
{
if (!ici) continue;
_e_fm_file_buffer = eina_list_append(_e_fm_file_buffer, _e_fm2_uri_escape(buf));
}
- return !!sel;
+ return ret;
}
static void
/* Roll the operation! */
if (_e_fm_file_buffer_copying)
{
- _e_fm_client_file_copy(args);
+ _e_fm_client_file_copy(args, sd->obj);
}
else
{
- _e_fm_client_file_move(args);
+ _e_fm_client_file_move(args, sd->obj);
}
free(args);
/* Roll the operation! */
if (_e_fm_file_buffer_copying)
- _e_fm_client_file_symlink(args);
+ _e_fm_client_file_symlink(args, sd->obj);
free(args);
}
e_fm2_custom_file_flush();
}
+struct e_fm_drop_menu_data
+{
+ Evas_Object *e_fm;
+ char *args;
+};
+
static void
_e_fm_drop_menu_copy_cb(void *data, E_Menu *m, E_Menu_Item *mi)
{
- char *args = data;
-
- if (!data) return;
-
- _e_fm_client_file_copy(args);
+ struct e_fm_drop_menu_data *d = data;
+ if (!d) return;
+ _e_fm_client_file_copy(d->args, d->e_fm);
}
static void
_e_fm_drop_menu_move_cb(void *data, E_Menu *m, E_Menu_Item *mi)
{
- char *args = data;
-
- if (!data) return;
-
- _e_fm_client_file_move(args);
+ struct e_fm_drop_menu_data *d = data;
+ if (!d) return;
+ _e_fm_client_file_move(d->args, d->e_fm);
}
static void
_e_fm_drop_menu_symlink_cb(void *data, E_Menu *m, E_Menu_Item *mi)
{
- char *args = data;
-
- if (!data) return;
-
- _e_fm_client_file_symlink(args);
+ struct e_fm_drop_menu_data *d = data;
+ if (!d) return;
+ _e_fm_client_file_symlink(d->args, d->e_fm);
}
static void
_e_fm_drop_menu_abort_cb(void *data, E_Menu *m, E_Menu_Item *mi)
{
- if (!data) return;
}
static void
-_e_fm_drop_menu_post_cb(void *data, E_Menu *m)
+_e_fm_drop_menu_free(void *data)
{
- char *args = data;
-
- if (!data) return;
-
- free(args);
+ struct e_fm_drop_menu_data *d = e_object_data_get(data);
+ if (!d) return;
+ free(d->args);
+ free(d);
}
static void
-_e_fm_drop_menu(char *args)
+_e_fm_drop_menu(char *args, Evas_Object *e_fm)
{
+ struct e_fm_drop_menu_data *d;
E_Menu *menu = e_menu_new();
E_Menu_Item *item = NULL;
E_Manager *man = NULL;
if (!menu) return;
+ d = malloc(sizeof(*d));
+ if (!d)
+ {
+ e_object_del(E_OBJECT(menu));
+ return;
+ }
+
+ d->e_fm = e_fm;
+ d->args = args;
+
+ e_object_data_set(E_OBJECT(menu), d);
+ e_object_free_attach_func_set(E_OBJECT(menu), _e_fm_drop_menu_free);
+
item = e_menu_item_new(menu);
e_menu_item_label_set(item, _("Copy"));
- e_menu_item_callback_set(item, _e_fm_drop_menu_copy_cb, args);
+ e_menu_item_callback_set(item, _e_fm_drop_menu_copy_cb, d);
e_util_menu_item_theme_icon_set(item, "edit-copy");
item = e_menu_item_new(menu);
e_menu_item_label_set(item, _("Move"));
- e_menu_item_callback_set(item, _e_fm_drop_menu_move_cb, args);
+ e_menu_item_callback_set(item, _e_fm_drop_menu_move_cb, d);
e_menu_item_icon_edje_set(item,
e_theme_edje_file_get("base/theme/fileman",
"e/fileman/default/button/move"),
item = e_menu_item_new(menu);
e_menu_item_label_set(item, _("Link"));
- e_menu_item_callback_set(item, _e_fm_drop_menu_symlink_cb, args);
+ e_menu_item_callback_set(item, _e_fm_drop_menu_symlink_cb, d);
e_util_menu_item_theme_icon_set(item, "emblem-symbolic-link");
item = e_menu_item_new(menu);
item = e_menu_item_new(menu);
e_menu_item_label_set(item, _("Abort"));
- e_menu_item_callback_set(item, _e_fm_drop_menu_abort_cb, args);
+ e_menu_item_callback_set(item, _e_fm_drop_menu_abort_cb, d);
e_menu_item_icon_edje_set(item,
e_theme_edje_file_get("base/theme/fileman",
"e/fileman/default/button/abort"),
"e/fileman/default/button/abort");
man = e_manager_current_get();
- if (!man)
- {
- e_object_del(E_OBJECT(menu));
- return;
- }
+ if (!man) goto error;
con = e_container_current_get(man);
- if (!con)
- {
- e_object_del(E_OBJECT(menu));
- return;
- }
+ if (!con) goto error;
ecore_x_pointer_xy_get(con->win, &x, &y);
zone = e_util_zone_current_get(man);
- if (!zone)
- {
- e_object_del(E_OBJECT(menu));
- return;
- }
- e_menu_post_deactivate_callback_set(menu, _e_fm_drop_menu_post_cb, args);
- e_menu_activate_mouse(menu, zone,
- x, y, 1, 1,
- E_MENU_POP_DIRECTION_DOWN, 0);
+ if (!zone) goto error;
+ e_menu_activate_mouse(menu, zone, x, y, 1, 1, E_MENU_POP_DIRECTION_DOWN, 0);
+
+ error:
+ e_object_del(E_OBJECT(menu));
}
static void
sd->realpath, ecore_file_file_get(fp));
if (sd->config->view.link_drop)
{
- _e_fm2_client_file_symlink(buf, fp, sd->drop_icon->info.file, sd->drop_after, -9999, -9999, sd->h, sd->h);
+ _e_fm2_client_file_symlink(buf, fp, sd->drop_icon->info.file, sd->drop_after, -9999, -9999, sd->h, sd->h, sd->obj);
}
else
{
if (e_drop_handler_action_get() == ECORE_X_ATOM_XDND_ACTION_COPY)
{
- _e_fm_client_file_copy(args);
+ _e_fm_client_file_copy(args, sd->obj);
free(args);
}
else if (e_drop_handler_action_get() == ECORE_X_ATOM_XDND_ACTION_MOVE)
{
- _e_fm_client_file_move(args);
+ _e_fm_client_file_move(args, sd->obj);
free(args);
}
else if (e_drop_handler_action_get() == ECORE_X_ATOM_XDND_ACTION_ASK)
{
- _e_fm_drop_menu(args);
+ _e_fm_drop_menu(args, sd->obj);
}
_e_fm2_dnd_drop_hide(sd->obj);
free(drag->data);
}
-void
+static void
_e_fm_drag_key_down_cb(E_Drag *drag, Ecore_Event_Key *e)
{
if (!strncmp(e->keyname, "Alt", 3))
}
}
-void
+static void
_e_fm_drag_key_up_cb(E_Drag *drag, Ecore_Event_Key *e)
{
/* Default action would be move. ;) */
{
snprintf(buf, sizeof(buf), "%s/%s", sd->realpath, text);
- _e_fm2_client_file_mkdir(buf, "", 0, 0, 0, sd->w, sd->h);
+ _e_fm2_client_file_mkdir(buf, "", 0, 0, 0, sd->w, sd->h, sd->obj);
}
}
args = _e_fm_string_append_char(args, &size, &length, ' ');
args = _e_fm_string_append_quoted(args, &size, &length, newpath);
- _e_fm_client_file_move(args);
+ _e_fm_client_file_move(args, ic->sd->obj);
free(args);
}
}
static void _e_fm_retry_abort_retry_cb(void *data, E_Dialog *dialog)
{
int *id = E_OBJECT(dialog)->data;
+ _e_fm2_op_registry_go_on(*id);
_e_fm_client_send(E_FM_OP_ERROR_RESPONSE_RETRY, *id, NULL, 0);
e_object_del(E_OBJECT(dialog));
}
static void _e_fm_retry_abort_abort_cb(void *data, E_Dialog *dialog)
{
int *id = E_OBJECT(dialog)->data;
+ _e_fm2_op_registry_aborted(*id);
_e_fm_client_send(E_FM_OP_ERROR_RESPONSE_ABORT, *id, NULL, 0);
e_object_del(E_OBJECT(dialog));
}
_e_fm_overwrite_no_cb(void *data, E_Dialog *dialog)
{
int *id = E_OBJECT(dialog)->data;
+ _e_fm2_op_registry_go_on(*id);
_e_fm_client_send(E_FM_OP_OVERWRITE_RESPONSE_NO, *id, NULL, 0);
e_object_del(E_OBJECT(dialog));
}
_e_fm_overwrite_no_all_cb(void *data, E_Dialog *dialog)
{
int *id = E_OBJECT(dialog)->data;
+ _e_fm2_op_registry_go_on(*id);
_e_fm_client_send(E_FM_OP_OVERWRITE_RESPONSE_NO_ALL, *id, NULL, 0);
e_object_del(E_OBJECT(dialog));
}
_e_fm_overwrite_yes_cb(void *data, E_Dialog *dialog)
{
int *id = E_OBJECT(dialog)->data;
+ _e_fm2_op_registry_go_on(*id);
_e_fm_client_send(E_FM_OP_OVERWRITE_RESPONSE_YES, *id, NULL, 0);
e_object_del(E_OBJECT(dialog));
}
_e_fm_overwrite_yes_all_cb(void *data, E_Dialog *dialog)
{
int *id = E_OBJECT(dialog)->data;
+ _e_fm2_op_registry_go_on(*id);
_e_fm_client_send(E_FM_OP_OVERWRITE_RESPONSE_YES_ALL, *id, NULL, 0);
e_object_del(E_OBJECT(dialog));
}
_e_fm_error_retry_cb(void *data, E_Dialog *dialog)
{
int *id = E_OBJECT(dialog)->data;
+ _e_fm2_op_registry_go_on(*id);
_e_fm_client_send(E_FM_OP_ERROR_RESPONSE_RETRY, *id, NULL, 0);
e_object_del(E_OBJECT(dialog));
}
_e_fm_error_abort_cb(void *data, E_Dialog *dialog)
{
int *id = E_OBJECT(dialog)->data;
+ _e_fm2_op_registry_aborted(*id);
_e_fm_client_send(E_FM_OP_ERROR_RESPONSE_ABORT, *id, NULL, 0);
e_object_del(E_OBJECT(dialog));
}
_e_fm_error_ignore_this_cb(void *data, E_Dialog *dialog)
{
int *id = E_OBJECT(dialog)->data;
+ _e_fm2_op_registry_go_on(*id);
_e_fm_client_send(E_FM_OP_ERROR_RESPONSE_IGNORE_THIS, *id, NULL, 0);
e_object_del(E_OBJECT(dialog));
}
_e_fm_error_ignore_all_cb(void *data, E_Dialog *dialog)
{
int *id = E_OBJECT(dialog)->data;
+ _e_fm2_op_registry_go_on(*id);
_e_fm_client_send(E_FM_OP_ERROR_RESPONSE_IGNORE_ALL, *id, NULL, 0);
e_object_del(E_OBJECT(dialog));
}
files = _e_fm_string_append_quoted(files, &size, &len, buf);
}
- _e_fm_client_file_del(files);
+ _e_fm_client_file_del(files, ic->sd->obj);
free(files);
--- /dev/null
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+#include "e.h"
+
+EAPI int E_EVENT_FM_OP_REGISTRY_ADD = 0;
+EAPI int E_EVENT_FM_OP_REGISTRY_DEL = 0;
+EAPI int E_EVENT_FM_OP_REGISTRY_CHANGED = 0;
+
+static Eina_Hash *_e_fm2_op_registry = NULL;
+static unsigned int _e_fm2_init_count = 0;
+
+typedef struct _E_Fm2_Op_Registry_Entry_Listener E_Fm2_Op_Registry_Entry_Listener;
+typedef struct _E_Fm2_Op_Registry_Entry_Internal E_Fm2_Op_Registry_Entry_Internal;
+
+struct _E_Fm2_Op_Registry_Entry_Listener
+{
+ EINA_INLIST;
+ void (*cb)(void *data, const E_Fm2_Op_Registry_Entry *entry);
+ void *data;
+ void (*free_data)(void *data);
+};
+
+struct _E_Fm2_Op_Registry_Entry_Internal
+{
+ E_Fm2_Op_Registry_Entry entry;
+ Eina_Inlist *listeners;
+ int references;
+ Ecore_Event *changed_event;
+};
+
+static void
+_e_fm2_op_registry_entry_e_fm_deleted(void *data, Evas *evas, Evas_Object *e_fm, void *event)
+{
+ E_Fm2_Op_Registry_Entry *entry = data;
+
+ entry->e_fm = NULL;
+ e_fm2_op_registry_entry_changed(entry);
+}
+
+static void
+_e_fm2_op_registry_entry_e_fm_monitor_start(const E_Fm2_Op_Registry_Entry *entry)
+{
+ if (!entry->e_fm) return;
+ evas_object_event_callback_add
+ (entry->e_fm, EVAS_CALLBACK_DEL,
+ _e_fm2_op_registry_entry_e_fm_deleted, entry);
+}
+
+static void
+_e_fm2_op_registry_entry_e_fm_monitor_stop(const E_Fm2_Op_Registry_Entry *entry)
+{
+ if (!entry->e_fm) return;
+ evas_object_event_callback_del_full
+ (entry->e_fm, EVAS_CALLBACK_DEL,
+ _e_fm2_op_registry_entry_e_fm_deleted, entry);
+}
+
+
+static inline E_Fm2_Op_Registry_Entry_Internal *
+_e_fm2_op_registry_entry_internal_get(const E_Fm2_Op_Registry_Entry *entry)
+{
+ return (E_Fm2_Op_Registry_Entry_Internal *)entry;
+}
+
+static void
+_e_fm2_op_registry_entry_internal_free(E_Fm2_Op_Registry_Entry_Internal *e)
+{
+ _e_fm2_op_registry_entry_e_fm_monitor_stop(&(e->entry));
+
+ while (e->listeners)
+ {
+ E_Fm2_Op_Registry_Entry_Listener *listener = (void *)e->listeners;
+ e->listeners = eina_inlist_remove(e->listeners, e->listeners);
+
+ if (listener->free_data) listener->free_data(listener->data);
+ free(listener);
+ }
+
+ eina_stringshare_del(e->entry.src);
+ eina_stringshare_del(e->entry.dst);
+ free(e);
+}
+
+static inline int
+_e_fm2_op_registry_entry_internal_unref(E_Fm2_Op_Registry_Entry_Internal *e)
+{
+ if (e->references < 1)
+ return 0;
+
+ e->references--;
+ if (e->references > 0)
+ return e->references;
+
+ _e_fm2_op_registry_entry_internal_free(e);
+ return 0;
+}
+
+static inline int
+_e_fm2_op_registry_entry_internal_ref(E_Fm2_Op_Registry_Entry_Internal *e)
+{
+ e->references++;
+ return e->references;
+}
+
+static void
+_e_fm2_op_registry_entry_listeners_call(const E_Fm2_Op_Registry_Entry_Internal *e)
+{
+ E_Fm2_Op_Registry_Entry_Listener *l, **shadow;
+ const E_Fm2_Op_Registry_Entry *entry;
+ unsigned int i, count;
+
+ /* NB: iterate on a copy in order to allow listeners to be deleted
+ * from callbacks. number of listeners should be small, so the
+ * following should do fine.
+ */
+ count = eina_inlist_count(e->listeners);
+ if (count < 1) return;
+
+ shadow = alloca(sizeof(*shadow) * count);
+ if (!shadow) return;
+
+ i = 0;
+ EINA_INLIST_FOREACH(e->listeners, l)
+ shadow[i++] = l;
+
+ entry = &(e->entry);
+ for (i = 0; i < count; i++)
+ shadow[i]->cb(shadow[i]->data, entry);
+}
+
+static void
+_e_fm2_op_registry_entry_internal_unref_on_event(void *data, void *event __UNUSED__)
+{
+ E_Fm2_Op_Registry_Entry_Internal *e = data;
+ _e_fm2_op_registry_entry_internal_unref(e);
+}
+
+static void
+_e_fm2_op_registry_entry_internal_event(E_Fm2_Op_Registry_Entry_Internal *e, int event_type)
+{
+ _e_fm2_op_registry_entry_internal_ref(e);
+ ecore_event_add(event_type, &(e->entry),
+ _e_fm2_op_registry_entry_internal_unref_on_event, e);
+}
+
+Eina_Bool
+e_fm2_op_registry_entry_add(int id, Evas_Object *e_fm, E_Fm_Op_Type op)
+{
+ E_Fm2_Op_Registry_Entry_Internal *e;
+
+ e = E_NEW(E_Fm2_Op_Registry_Entry_Internal, 1);
+ if (!e) return 0;
+
+ e->entry.id = id;
+ e->entry.e_fm = e_fm;
+ e->entry.start_time = ecore_loop_time_get();
+ e->entry.op = op;
+ e->entry.status = E_FM2_OP_STATUS_IN_PROGRESS;
+ e->references = 1;
+
+ if (!eina_hash_add(_e_fm2_op_registry, &id, e))
+ {
+ free(e);
+ return 0;
+ }
+
+ _e_fm2_op_registry_entry_e_fm_monitor_start(&(e->entry));
+ _e_fm2_op_registry_entry_internal_event(e, E_EVENT_FM_OP_REGISTRY_ADD);
+
+ return 1;
+}
+
+Eina_Bool
+e_fm2_op_registry_entry_del(int id)
+{
+ E_Fm2_Op_Registry_Entry_Internal *e;
+
+ e = eina_hash_find(_e_fm2_op_registry, &id);
+ if (!e) return 0;
+ eina_hash_del_by_key(_e_fm2_op_registry, &id);
+
+ _e_fm2_op_registry_entry_internal_event(e, E_EVENT_FM_OP_REGISTRY_DEL);
+ _e_fm2_op_registry_entry_internal_unref(e);
+
+ return 1;
+}
+
+static void
+_e_fm2_op_registry_entry_internal_unref_on_changed_event(void *data, void *event __UNUSED__)
+{
+ E_Fm2_Op_Registry_Entry_Internal *e = data;
+ e->changed_event = NULL;
+ _e_fm2_op_registry_entry_internal_unref(e);
+}
+
+void
+e_fm2_op_registry_entry_changed(const E_Fm2_Op_Registry_Entry *entry)
+{
+ E_Fm2_Op_Registry_Entry_Internal *e;
+
+ if (!entry) return;
+ e = _e_fm2_op_registry_entry_internal_get(entry);
+
+ _e_fm2_op_registry_entry_listeners_call(e);
+
+ if (e->changed_event) return;
+ _e_fm2_op_registry_entry_internal_ref(e);
+ e->changed_event = ecore_event_add
+ (E_EVENT_FM_OP_REGISTRY_CHANGED, &(e->entry),
+ _e_fm2_op_registry_entry_internal_unref_on_changed_event, e);
+}
+
+/**
+ * Set the new e_fm for this operation.
+ *
+ * Use this call instead of directly setting in order to have the
+ * object to be monitored, when it is gone, the pointer will be made
+ * NULL.
+ *
+ * @note: it will not call any listener or add any event, please use
+ * e_fm2_op_registry_entry_changed().
+ */
+void
+e_fm2_op_registry_entry_e_fm_set(E_Fm2_Op_Registry_Entry *entry, Evas_Object *e_fm)
+{
+ if (!entry) return;
+ _e_fm2_op_registry_entry_e_fm_monitor_stop(entry);
+ entry->e_fm = e_fm;
+ _e_fm2_op_registry_entry_e_fm_monitor_start(entry);
+}
+
+/**
+ * Set the new files for this operation.
+ *
+ * Use this call instead of directly setting in order to have
+ * stringshare references right.
+ *
+ * @note: it will not call any listener or add any event, please use
+ * e_fm2_op_registry_entry_changed().
+ */
+void
+e_fm2_op_registry_entry_files_set(E_Fm2_Op_Registry_Entry *entry, const char *src, const char *dst)
+{
+ if (!entry) return;
+
+ src = eina_stringshare_add(src);
+ dst = eina_stringshare_add(dst);
+
+ eina_stringshare_del(entry->src);
+ eina_stringshare_del(entry->dst);
+
+ entry->src = src;
+ entry->dst = dst;
+}
+
+/**
+ * Adds a reference to given entry.
+ *
+ * @return: new number of references after operation or -1 on error.
+ */
+EAPI int
+e_fm2_op_registry_entry_ref(E_Fm2_Op_Registry_Entry *entry)
+{
+ E_Fm2_Op_Registry_Entry_Internal *e;
+
+ if (!entry) return -1;
+
+ e = _e_fm2_op_registry_entry_internal_get(entry);
+ return _e_fm2_op_registry_entry_internal_ref(e);
+}
+
+/**
+ * Releases a reference to given entry.
+ *
+ * @return: new number of references after operation or -1 on error,
+ * if 0 the entry was freed and pointer is then invalid.
+ */
+EAPI int
+e_fm2_op_registry_entry_unref(E_Fm2_Op_Registry_Entry *entry)
+{
+ E_Fm2_Op_Registry_Entry_Internal *e;
+
+ if (!entry) return -1;
+
+ e = _e_fm2_op_registry_entry_internal_get(entry);
+ return _e_fm2_op_registry_entry_internal_unref(e);
+}
+
+/**
+ * Returns the X window associated to this operation.
+ *
+ * This will handle all bureaucracy to get X window based on e_fm evas
+ * object.
+ *
+ * @return: 0 if no window, window identifier otherwise.
+ */
+EAPI Ecore_X_Window
+e_fm2_op_registry_entry_xwin_get(const E_Fm2_Op_Registry_Entry *entry)
+{
+ Evas *e;
+ Ecore_Evas *ee;
+
+ if (!entry) return 0;
+ if (!entry->e_fm) return 0;
+
+ e = evas_object_evas_get(entry->e_fm);
+ if (!e) return 0;
+
+ ee = evas_data_attach_get(e);
+ if (!ee) return 0;
+
+ return (Ecore_X_Window)(long)ecore_evas_window_get(ee);
+}
+
+/**
+ * Discover entry based on its identifier.
+ *
+ * @note: does not increment reference.
+ */
+EAPI E_Fm2_Op_Registry_Entry *
+e_fm2_op_registry_entry_get(int id)
+{
+ return eina_hash_find(_e_fm2_op_registry, &id);
+}
+
+/**
+ * Adds a function to be called when entry changes.
+ *
+ * When entry changes any attribute this function will be called.
+ *
+ * @param: entry entry to operate on.
+ * @param: cb function to callback on changes.
+ * @param: data extra data to give to @p cb
+ * @param: free_data function to call when listener is removed, entry
+ * is deleted or any error occur in this function and listener
+ * cannot be added.
+ *
+ * @note: does not increment reference.
+ * @note: on errors, @p free_data will be called.
+ */
+EAPI void
+e_fm2_op_registry_entry_listener_add(E_Fm2_Op_Registry_Entry *entry, void (*cb)(void *data, const E_Fm2_Op_Registry_Entry *entry), const void *data, void (*free_data)(void *data))
+{
+ E_Fm2_Op_Registry_Entry_Internal *e;
+ E_Fm2_Op_Registry_Entry_Listener *listener;
+ Eina_Error err;
+
+ if ((!entry) || (!cb))
+ {
+ if (free_data) free_data((void *)data);
+ return;
+ }
+
+ listener = malloc(sizeof(*listener));
+ if (!listener)
+ {
+ if (free_data) free_data((void *)data);
+ return;
+ }
+ listener->cb = cb;
+ listener->data = (void *)data;
+ listener->free_data = free_data;
+
+ e = _e_fm2_op_registry_entry_internal_get(entry);
+ e->listeners = eina_inlist_append(e->listeners, EINA_INLIST_GET(listener));
+ err = eina_error_get();
+ if (err)
+ {
+ EINA_ERROR_PERR("could not add listener: %s\n",
+ eina_error_msg_get(err));
+
+ if (free_data) free_data((void *)data);
+ free(listener);
+ return;
+ }
+}
+
+/**
+ * Removes the function to be called when entry changes.
+ *
+ * @param: entry entry to operate on.
+ * @param: cb function to callback on changes.
+ * @param: data extra data to give to @p cb
+ *
+ * @note: does not decrement reference.
+ * @see: e_fm2_op_registry_entry_listener_add()
+ */
+EAPI void
+e_fm2_op_registry_entry_listener_del(E_Fm2_Op_Registry_Entry *entry, void (*cb)(void *data, const E_Fm2_Op_Registry_Entry *entry), const void *data)
+{
+ E_Fm2_Op_Registry_Entry_Internal *e;
+ E_Fm2_Op_Registry_Entry_Listener *l;
+
+ if ((!entry) || (!cb)) return;
+ e = _e_fm2_op_registry_entry_internal_get(entry);
+
+ EINA_INLIST_FOREACH(e->listeners, l)
+ if ((l->cb == cb) && (l->data == data))
+ {
+ e->listeners = eina_inlist_remove(e->listeners, EINA_INLIST_GET(l));
+ if (l->free_data) l->free_data(l->data);
+ return;
+ }
+}
+
+/**
+ * Returns an iterator over all the entries in the fm operations registry.
+ *
+ * @warning: this iterator is just valid until new entries are added
+ * or removed (usually happens from main loop). This is because
+ * when system is back to main loop it can report new events and
+ * operations can be added or removed from this registry. In other
+ * words, it is fine to call this function, immediately walk the
+ * iterator and do something, then free the iterator. You can use
+ * it to create a shadow list if you wish.
+ *
+ * @see e_fm2_op_registry_get_all()
+ */
+EAPI Eina_Iterator *
+e_fm2_op_registry_iterator_new(void)
+{
+ return eina_hash_iterator_data_new(_e_fm2_op_registry);
+}
+
+/**
+ * Returns a shadow list with all entries in the registry.
+ *
+ * All entries will have references incremented, so you must free the
+ * list with e_fm2_op_registry_get_all_free() to free the list and
+ * release these references.
+ *
+ * @note: List is unsorted!
+ * @note: if you need a simple, immediate walk, use
+ * e_fm2_op_registry_iterator_new()
+ */
+EAPI Eina_List *
+e_fm2_op_registry_get_all(void)
+{
+ Eina_List *list;
+ Eina_Iterator *it;
+ E_Fm2_Op_Registry_Entry_Internal *e;
+
+ list = NULL;
+ it = eina_hash_iterator_data_new(_e_fm2_op_registry);
+ EINA_ITERATOR_FOREACH(it, e)
+ {
+ _e_fm2_op_registry_entry_internal_ref(e);
+ list = eina_list_append(list, &(e->entry));
+ }
+ eina_iterator_free(it);
+
+ return list;
+}
+
+EAPI void
+e_fm2_op_registry_get_all_free(Eina_List *list)
+{
+ E_Fm2_Op_Registry_Entry *entry;
+ EINA_LIST_FREE(list, entry)
+ e_fm2_op_registry_entry_unref(entry);
+}
+
+EAPI unsigned int
+e_fm2_op_registry_init(void)
+{
+ _e_fm2_init_count++;
+ if (_e_fm2_init_count > 1) return _e_fm2_init_count;
+
+ _e_fm2_op_registry = eina_hash_int32_new(NULL);
+ if (!_e_fm2_op_registry)
+ {
+ _e_fm2_init_count = 0;
+ return 0;
+ }
+
+ if (E_EVENT_FM_OP_REGISTRY_ADD == 0)
+ E_EVENT_FM_OP_REGISTRY_ADD = ecore_event_type_new();
+ if (E_EVENT_FM_OP_REGISTRY_DEL == 0)
+ E_EVENT_FM_OP_REGISTRY_DEL = ecore_event_type_new();
+ if (E_EVENT_FM_OP_REGISTRY_CHANGED == 0)
+ E_EVENT_FM_OP_REGISTRY_CHANGED = ecore_event_type_new();
+
+ return 1;
+}
+
+EAPI unsigned int
+e_fm2_op_registry_shutdown(void)
+{
+ if (_e_fm2_init_count == 0) return 0;
+ _e_fm2_init_count--;
+ if (_e_fm2_init_count > 0) return _e_fm2_init_count;
+
+ eina_hash_free(_e_fm2_op_registry);
+ _e_fm2_op_registry = NULL;
+
+ return 0;
+}