forked from enlightenment/enlightenment
546 lines
12 KiB
C
546 lines
12 KiB
C
#include "file.h"
|
|
#include "desktops.h"
|
|
#include "e_dir.h"
|
|
#include "e_view_machine.h"
|
|
#include "view.h"
|
|
#include "icons.h"
|
|
#include "util.h"
|
|
#include "libefsd.h"
|
|
#include "e_file.h"
|
|
#include "globals.h"
|
|
|
|
static void e_dir_handle_fs_restart(void *data);
|
|
static void e_dir_handle_fs(EfsdEvent * ev);
|
|
static void e_dir_handle_efsd_event_reply(EfsdEvent * ev);
|
|
static void e_dir_handle_efsd_event_reply_stat(EfsdEvent * ev);
|
|
static void e_dir_handle_efsd_event_reply_readlink(EfsdEvent * ev);
|
|
static void e_dir_handle_efsd_event_reply_getfiletype(EfsdEvent * ev);
|
|
static void e_dir_handle_efsd_event_reply_getmeta(EfsdEvent * ev);
|
|
|
|
static void e_dir_cleanup(E_Dir * d);
|
|
|
|
void
|
|
e_dir_init(void)
|
|
{
|
|
D_ENTER;
|
|
e_fs_add_event_handler(e_dir_handle_fs);
|
|
D_RETURN;
|
|
}
|
|
|
|
static void
|
|
e_dir_cleanup(E_Dir * d)
|
|
{
|
|
D_ENTER;
|
|
|
|
if (!d)
|
|
D_RETURN;
|
|
|
|
efsd_stop_monitor(e_fs_get_connection(), d->dir, TRUE);
|
|
if (d->restarter)
|
|
e_fs_del_restart_handler(d->restarter);
|
|
|
|
d->restarter = NULL;
|
|
e_view_machine_unregister_dir(d);
|
|
|
|
e_object_cleanup(E_OBJECT(d));
|
|
|
|
D_RETURN;
|
|
}
|
|
|
|
E_Dir *
|
|
e_dir_new(void)
|
|
{
|
|
E_Dir *d;
|
|
|
|
D_ENTER;
|
|
|
|
d = NEW(E_Dir, 1);
|
|
ZERO(d, E_Dir, 1);
|
|
d->dir = NULL;
|
|
|
|
e_observee_init(E_OBSERVEE(d),
|
|
(E_Cleanup_Func) e_dir_cleanup);
|
|
|
|
e_view_machine_register_dir(d);
|
|
D_RETURN_(d);
|
|
}
|
|
|
|
static void
|
|
e_dir_handle_fs_restart(void *data) {
|
|
E_Dir *d;
|
|
|
|
D_ENTER;
|
|
|
|
D("e_dir_handle_fs_restart\n");
|
|
|
|
if((d = data)) {
|
|
if(d->dir&&*(d->dir)) {
|
|
if (e_fs_get_connection()) {
|
|
EfsdOptions *ops;
|
|
|
|
/* FIXME restart with metadata pending for views */
|
|
|
|
ops = efsd_ops(3,
|
|
efsd_op_get_stat(),
|
|
efsd_op_get_filetype(), efsd_op_list_all());
|
|
if((d->monitor_id=efsd_start_monitor(e_fs_get_connection(), d->dir,
|
|
ops, TRUE))<0) {
|
|
D("could not restart monitor (connx %p) for \"%s\" => %i\n",
|
|
e_fs_get_connection(), d->dir, d->monitor_id); }
|
|
else {
|
|
D("restarted monitor (connx %p) for \"%s\" => ID %i...\n",
|
|
e_fs_get_connection(), d->dir, d->monitor_id); }}
|
|
else {
|
|
D("could not restart, connection refused\n"); }}
|
|
else {
|
|
D("could not restart, no dir given!?\n"); }}
|
|
else {
|
|
D("could not restart, no data\n"); }
|
|
|
|
D_RETURN; }
|
|
|
|
void
|
|
e_dir_set_dir(E_Dir * d, char *dir)
|
|
{
|
|
D_ENTER;
|
|
|
|
if (!d) {
|
|
D("e_dir_set_dir -- no E_Dir!\n");
|
|
D_RETURN; }
|
|
|
|
/* stop monitoring old dir */
|
|
if ((d->dir) && (d->monitor_id))
|
|
{
|
|
efsd_stop_monitor(e_fs_get_connection(), d->dir, TRUE);
|
|
d->monitor_id = 0;
|
|
}
|
|
IF_FREE(d->dir);
|
|
|
|
if(!dir||!*dir) {
|
|
D("e_dir_set_dir -- no dir!\n");
|
|
D_RETURN; }
|
|
|
|
d->dir = e_file_realpath(dir);
|
|
|
|
if(!d->dir||!*(d->dir)) {
|
|
/* realpath failed. this would mean that we tried to set a monitor
|
|
on a non-existent (or inacessible) file. this may mean that the
|
|
programmer really meant "...and if it doesn't exist YET, tell me
|
|
if and when it is created", so rather than failing right here and
|
|
now, we'll forget about the realpath, stick in the path they
|
|
requested in the first place, and hope the backend actually supports
|
|
watching something it cannot determine an inode for... we'll still
|
|
throw a warning though, just for good measure. Azundris 2003/01/11 */
|
|
D("e_dir_set_dir -- e_file_realpath(\"%s\") failed...\n",dir);
|
|
if(d->dir)
|
|
free(d->dir);
|
|
if(!(d->dir=strdup(dir))) {
|
|
D("e_dir_set_dir: OOM\n");
|
|
D_RETURN; }}
|
|
|
|
/* start monitoring new dir */
|
|
d->restarter = e_fs_add_restart_handler(e_dir_handle_fs_restart, d);
|
|
if (e_fs_get_connection())
|
|
{
|
|
EfsdOptions *ops;
|
|
|
|
ops = efsd_ops(3,
|
|
efsd_op_get_stat(),
|
|
efsd_op_get_filetype(), efsd_op_list_all());
|
|
d->monitor_id = efsd_start_monitor(e_fs_get_connection(), d->dir,
|
|
ops, TRUE);
|
|
D("monitor id for \"%s\" = %i\n", d->dir, d->monitor_id);
|
|
}
|
|
D_RETURN;
|
|
}
|
|
|
|
static void
|
|
e_dir_handle_fs(EfsdEvent * ev)
|
|
{
|
|
D_ENTER;
|
|
|
|
if (!ev)
|
|
D_RETURN;
|
|
|
|
switch (ev->type)
|
|
{
|
|
case EFSD_EVENT_FILECHANGE:
|
|
switch (ev->efsd_filechange_event.changetype)
|
|
{
|
|
case EFSD_FILE_CREATED:
|
|
e_dir_file_added(ev->efsd_filechange_event.id,
|
|
ev->efsd_filechange_event.file);
|
|
break;
|
|
case EFSD_FILE_EXISTS:
|
|
e_dir_file_added(ev->efsd_filechange_event.id,
|
|
ev->efsd_filechange_event.file);
|
|
break;
|
|
case EFSD_FILE_DELETED:
|
|
e_dir_file_deleted(ev->efsd_filechange_event.id,
|
|
ev->efsd_filechange_event.file);
|
|
break;
|
|
case EFSD_FILE_CHANGED:
|
|
e_dir_file_changed(ev->efsd_filechange_event.id,
|
|
ev->efsd_filechange_event.file);
|
|
break;
|
|
case EFSD_FILE_MOVED:
|
|
e_dir_file_moved(ev->efsd_filechange_event.id,
|
|
ev->efsd_filechange_event.file);
|
|
break;
|
|
case EFSD_FILE_END_EXISTS:
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
break;
|
|
case EFSD_EVENT_REPLY:
|
|
e_dir_handle_efsd_event_reply(ev);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
D_RETURN;
|
|
}
|
|
|
|
static void
|
|
e_dir_handle_efsd_event_reply_getfiletype(EfsdEvent * ev)
|
|
{
|
|
E_File *f;
|
|
char *file = NULL;
|
|
E_Dir *dir;
|
|
|
|
char *m, *p;
|
|
char mime[PATH_MAX], base[PATH_MAX];
|
|
|
|
D_ENTER;
|
|
|
|
if (!ev)
|
|
D_RETURN;
|
|
|
|
if (!ev->efsd_reply_event.errorcode == 0)
|
|
D_RETURN;
|
|
|
|
if ((file = efsd_event_filename(ev)))
|
|
{
|
|
file = e_file_get_file(file);
|
|
}
|
|
dir = e_dir_find_by_monitor_id(efsd_event_id(ev));
|
|
f = e_file_get_by_name(dir->files, file);
|
|
|
|
/* if its not in the list we care about, its filetype is meaningless */
|
|
if (!f)
|
|
D_RETURN;
|
|
|
|
m = ev->efsd_reply_event.data;
|
|
p = strchr(m, '/');
|
|
if (p)
|
|
{
|
|
STRNCPY(base, m, PATH_MAX);
|
|
STRNCPY(mime, p + 1, PATH_MAX);
|
|
p = strchr(base, '/');
|
|
*p = 0;
|
|
}
|
|
else
|
|
{
|
|
STRNCPY(base, m, PATH_MAX);
|
|
strcpy(mime, "unknown");
|
|
}
|
|
e_file_set_mime(f, base, mime);
|
|
/* Try to update the GUI.
|
|
* It's just a try because we need to have the file's stat
|
|
* info as well. --cK.
|
|
*/
|
|
e_observee_notify_observers(E_OBSERVEE(dir), E_EVENT_FILE_INFO, f);
|
|
D_RETURN;
|
|
}
|
|
|
|
static void
|
|
e_dir_handle_efsd_event_reply_stat(EfsdEvent * ev)
|
|
{
|
|
E_Dir *d;
|
|
E_File *f;
|
|
|
|
D_ENTER;
|
|
|
|
if (!ev)
|
|
D_RETURN;
|
|
|
|
if (!ev->efsd_reply_event.errorcode == 0)
|
|
D_RETURN;
|
|
|
|
d = e_dir_find_by_monitor_id(efsd_event_id(ev));
|
|
f = e_file_get_by_name(d->files, e_file_get_file(efsd_event_filename(ev)));
|
|
/* if its not in the list we care about, return */
|
|
if (!f)
|
|
D_RETURN;
|
|
|
|
/* When everything went okay and we can find a dir,
|
|
* set the file stat data for the file and try to update the gui.
|
|
* It's just a try because we need to have received the filetype
|
|
* info too. --cK. */
|
|
f->stat = *((struct stat *)efsd_event_data(ev));
|
|
e_observee_notify_observers(E_OBSERVEE(d), E_EVENT_FILE_INFO, f);
|
|
|
|
D_RETURN;
|
|
}
|
|
|
|
static void
|
|
e_dir_handle_efsd_event_reply_readlink(EfsdEvent * ev)
|
|
{
|
|
E_Dir *d;
|
|
E_File *f;
|
|
|
|
D_ENTER;
|
|
|
|
if (!ev)
|
|
D_RETURN;
|
|
|
|
if (!ev->efsd_reply_event.errorcode == 0)
|
|
D_RETURN;
|
|
|
|
d = e_dir_find_by_monitor_id(efsd_event_id(ev));
|
|
f = e_file_get_by_name(d->files, e_file_get_file(efsd_event_filename(ev)));
|
|
if (f)
|
|
{
|
|
e_file_set_link(f, (char *)efsd_event_data(ev));
|
|
}
|
|
e_observee_notify_observers(E_OBSERVEE(d), E_EVENT_FILE_INFO, f);
|
|
|
|
D_RETURN;
|
|
}
|
|
|
|
static void
|
|
e_dir_handle_efsd_event_reply_getmeta(EfsdEvent * ev)
|
|
{
|
|
Evas_List * l;
|
|
EfsdCmdId cmd;
|
|
|
|
D_ENTER;
|
|
|
|
if (!ev)
|
|
D_RETURN;
|
|
|
|
cmd = efsd_event_id(ev);
|
|
for (l = VM->views; l; l = l->next)
|
|
{
|
|
E_View *v;
|
|
|
|
v = l->data;
|
|
/* ignore metadata for desktops */
|
|
if (v->is_desktop)
|
|
continue;
|
|
if (v->geom_get.x == cmd)
|
|
{
|
|
v->geom_get.x = 0;
|
|
if (efsd_metadata_get_type(ev) == EFSD_INT)
|
|
{
|
|
if (ev->efsd_reply_event.errorcode == 0)
|
|
efsd_metadata_get_int(ev, &(v->location.x));
|
|
else
|
|
v->location.x = 0;
|
|
}
|
|
}
|
|
else if (v->geom_get.y == cmd)
|
|
{
|
|
v->geom_get.y = 0;
|
|
if (efsd_metadata_get_type(ev) == EFSD_INT)
|
|
{
|
|
if (ev->efsd_reply_event.errorcode == 0)
|
|
efsd_metadata_get_int(ev, &(v->location.y));
|
|
else
|
|
v->location.y = 0;
|
|
|
|
}
|
|
}
|
|
else if (v->geom_get.w == cmd)
|
|
{
|
|
v->geom_get.w = 0;
|
|
if (efsd_metadata_get_type(ev) == EFSD_INT)
|
|
{
|
|
if (ev->efsd_reply_event.errorcode == 0)
|
|
efsd_metadata_get_int(ev, &(v->size.w));
|
|
else
|
|
v->size.w = 400;
|
|
}
|
|
}
|
|
else if (v->geom_get.h == cmd)
|
|
{
|
|
v->geom_get.h = 0;
|
|
if (ev->efsd_reply_event.errorcode == 0)
|
|
{
|
|
if (ev->efsd_reply_event.errorcode == 0)
|
|
efsd_metadata_get_int(ev, &(v->size.h));
|
|
else
|
|
v->size.h = 401;
|
|
}
|
|
}
|
|
/* We have received all metadata we need, display the view */
|
|
if ((!v->geom_get.x) &&
|
|
(!v->geom_get.y) &&
|
|
(!v->geom_get.w) && (!v->geom_get.h) && (v->geom_get.busy))
|
|
{
|
|
E_Border *b;
|
|
|
|
ecore_window_move_resize(v->win.base, v->location.x, v->location.y,
|
|
v->size.w, v->size.h);
|
|
ecore_window_set_xy_hints(v->win.base, v->location.x,
|
|
v->location.y);
|
|
v->size.force = 1;
|
|
v->geom_get.busy = 0;
|
|
if (v->bg)
|
|
e_bg_resize(v->bg, v->size.w, v->size.h);
|
|
if (v->options.back_pixmap)
|
|
e_view_update(v);
|
|
b = e_border_adopt(v->win.base, 1);
|
|
b->client.internal = 1;
|
|
e_border_remove_click_grab(b);
|
|
}
|
|
}
|
|
D_RETURN;
|
|
}
|
|
|
|
static void
|
|
e_dir_handle_efsd_event_reply(EfsdEvent * ev)
|
|
{
|
|
D_ENTER;
|
|
|
|
if (!ev)
|
|
D_RETURN;
|
|
|
|
switch (ev->efsd_reply_event.command.type)
|
|
{
|
|
case EFSD_CMD_REMOVE:
|
|
break;
|
|
case EFSD_CMD_MOVE:
|
|
break;
|
|
case EFSD_CMD_SYMLINK:
|
|
break;
|
|
case EFSD_CMD_LISTDIR:
|
|
break;
|
|
case EFSD_CMD_MAKEDIR:
|
|
break;
|
|
case EFSD_CMD_CHMOD:
|
|
break;
|
|
case EFSD_CMD_GETFILETYPE:
|
|
e_dir_handle_efsd_event_reply_getfiletype(ev);
|
|
break;
|
|
case EFSD_CMD_STAT:
|
|
e_dir_handle_efsd_event_reply_stat(ev);
|
|
break;
|
|
case EFSD_CMD_READLINK:
|
|
e_dir_handle_efsd_event_reply_readlink(ev);
|
|
break;
|
|
case EFSD_CMD_CLOSE:
|
|
break;
|
|
case EFSD_CMD_SETMETA:
|
|
break;
|
|
case EFSD_CMD_GETMETA:
|
|
e_dir_handle_efsd_event_reply_getmeta(ev);
|
|
break;
|
|
case EFSD_CMD_STARTMON_DIR:
|
|
break;
|
|
case EFSD_CMD_STARTMON_FILE:
|
|
break;
|
|
case EFSD_CMD_STOPMON_DIR:
|
|
break;
|
|
case EFSD_CMD_STOPMON_FILE:
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
D_RETURN;
|
|
}
|
|
|
|
void
|
|
e_dir_file_added(int id, char *file)
|
|
{
|
|
E_Dir *d;
|
|
E_File *f;
|
|
|
|
D_ENTER;
|
|
|
|
/* if we get a path - ignore it - its not a file in the dir */
|
|
if (!file || file[0] == '/')
|
|
D_RETURN;
|
|
d = e_dir_find_by_monitor_id(id);
|
|
if (file[0] != '.')
|
|
{
|
|
f = e_file_new(file);
|
|
d->files = evas_list_append(d->files, f);
|
|
/* tell all views for this dir about the new file */
|
|
e_observee_notify_observers(E_OBSERVEE(d), E_EVENT_FILE_ADD, f);
|
|
}
|
|
D_RETURN;
|
|
}
|
|
|
|
void
|
|
e_dir_file_deleted(int id, char *file)
|
|
{
|
|
E_File *f;
|
|
E_Dir *d;
|
|
|
|
D_ENTER;
|
|
|
|
if (!file || file[0] == '/')
|
|
D_RETURN;
|
|
|
|
d = e_dir_find_by_monitor_id(id);
|
|
f = e_file_get_by_name(d->files, file);
|
|
d->files = evas_list_remove(d->files, f);
|
|
|
|
if (file[0] != '.')
|
|
{
|
|
e_observee_notify_observers(E_OBSERVEE(d), E_EVENT_FILE_DELETE, f);
|
|
}
|
|
D_RETURN;
|
|
}
|
|
|
|
void
|
|
e_dir_file_changed(int id, char *file)
|
|
{
|
|
E_Dir *d;
|
|
E_File *f;
|
|
|
|
D_ENTER;
|
|
|
|
if (!file || file[0] == '/')
|
|
D_RETURN;
|
|
d = e_dir_find_by_monitor_id(id);
|
|
f = e_file_get_by_name(d->files, file);
|
|
if (file[0] != '.')
|
|
{
|
|
e_observee_notify_observers(E_OBSERVEE(d), E_EVENT_FILE_CHANGE, f);
|
|
}
|
|
D_RETURN;
|
|
}
|
|
|
|
void
|
|
e_dir_file_moved(int id, char *file)
|
|
{
|
|
E_Dir *d;
|
|
|
|
D_ENTER;
|
|
|
|
if (!file || file[0] == '/')
|
|
D_RETURN;
|
|
d = e_dir_find_by_monitor_id(id);
|
|
D_RETURN;
|
|
}
|
|
|
|
E_Dir *
|
|
e_dir_find_by_monitor_id(int id)
|
|
{
|
|
E_Dir *d;
|
|
Evas_List * l;
|
|
|
|
D_ENTER;
|
|
|
|
for (l = VM->dirs; l; l = l->next)
|
|
{
|
|
d = l->data;
|
|
if (d->monitor_id == id)
|
|
D_RETURN_(d);
|
|
}
|
|
D_RETURN_(NULL);
|
|
}
|