diff --git a/data/themes/default.edc b/data/themes/default.edc index 0bf68d561..45592b857 100644 --- a/data/themes/default.edc +++ b/data/themes/default.edc @@ -13669,6 +13669,9 @@ collections { /* begin the collection of edje groups that are in this file */ image: "icon_efm_dnd_copy.png" COMP; image: "icon_efm_dnd_ask.png" COMP; image: "icon_efm_dnd_move.png" COMP; + + image: "icon_efm_vol_unmounted.png" COMP; + image: "icon_efm_vol_mounted.png" COMP; } parts { part { name: "label2"; @@ -13952,6 +13955,36 @@ collections { /* begin the collection of edje groups that are in this file */ color: 0 0 0 0; } } + part { name: "vol_state"; + type: IMAGE; + mouse_events: 0; + repeat_events: 0; + description { state: "default" 0.0; + color: 0 0 0 0; + } + description { state: "visible" 0.0; + aspect: 1.0 1.0; + aspect_preference: BOTH; + align: 1.0 1.0; + min: 16 16; + rel1 { + relative: 0.75 0.0; + to: "icon"; + } + rel2 { + relative: 1.0 1.0; + to: "icon"; + } + } + description { state: "unmounted" 0.0; + inherit: "visible" 0.0; + image.normal: "icon_efm_vol_unmounted.png"; + } + description { state: "mounted" 0.0; + inherit: "visible" 0.0; + image.normal: "icon_efm_vol_mounted.png"; + } + } part { name: "dnd_action"; type: IMAGE; mouse_events: 0; @@ -14029,6 +14062,24 @@ collections { /* begin the collection of edje groups that are in this file */ action: STATE_SET "copy" 0.0; target: "dnd_action"; } + program { name: "vol_off"; + signal: "e,state,volume,off"; + source: "e"; + action: STATE_SET "default" 0.0; + target: "vol_state"; + } + program { name: "vol_unmounted"; + signal: "e,state,volume,unmounted"; + source: "e"; + action: STATE_SET "unmounted" 0.0; + target: "vol_state"; + } + program { name: "vol_mounted"; + signal: "e,state,volume,mounted"; + source: "e"; + action: STATE_SET "mounted" 0.0; + target: "vol_state"; + } program { name: "thumb_gen"; signal: "e,action,thumb,gen"; source: "e"; @@ -14089,6 +14140,9 @@ collections { /* begin the collection of edje groups that are in this file */ image: "icon_efm_dnd_copy.png" COMP; image: "icon_efm_dnd_ask.png" COMP; image: "icon_efm_dnd_move.png" COMP; + + image: "icon_efm_vol_unmounted.png" COMP; + image: "icon_efm_vol_mounted.png" COMP; } parts { part { name: "label2"; @@ -14372,6 +14426,36 @@ collections { /* begin the collection of edje groups that are in this file */ color: 0 0 0 0; } } + part { name: "vol_state"; + type: IMAGE; + mouse_events: 0; + repeat_events: 0; + description { state: "default" 0.0; + color: 0 0 0 0; + } + description { state: "visible" 0.0; + aspect: 1.0 1.0; + aspect_preference: BOTH; + align: 1.0 1.0; + min: 16 16; + rel1 { + relative: 0.75 0.0; + to: "icon"; + } + rel2 { + relative: 1.0 1.0; + to: "icon"; + } + } + description { state: "unmounted" 0.0; + inherit: "visible" 0.0; + image.normal: "icon_efm_vol_unmounted.png"; + } + description { state: "mounted" 0.0; + inherit: "visible" 0.0; + image.normal: "icon_efm_vol_mounted.png"; + } + } part { name: "dnd_action"; type: IMAGE; mouse_events: 0; @@ -14449,6 +14533,24 @@ collections { /* begin the collection of edje groups that are in this file */ action: STATE_SET "copy" 0.0; target: "dnd_action"; } + program { name: "vol_off"; + signal: "e,state,volume,off"; + source: "e"; + action: STATE_SET "default" 0.0; + target: "vol_state"; + } + program { name: "vol_unmounted"; + signal: "e,state,volume,unmounted"; + source: "e"; + action: STATE_SET "unmounted" 0.0; + target: "vol_state"; + } + program { name: "vol_mounted"; + signal: "e,state,volume,mounted"; + source: "e"; + action: STATE_SET "mounted" 0.0; + target: "vol_state"; + } program { name: "thumb_gen"; signal: "e,action,thumb,gen"; source: "e"; @@ -14509,6 +14611,9 @@ collections { /* begin the collection of edje groups that are in this file */ image: "icon_efm_dnd_copy.png" COMP; image: "icon_efm_dnd_ask.png" COMP; image: "icon_efm_dnd_move.png" COMP; + + image: "icon_efm_vol_unmounted.png" COMP; + image: "icon_efm_vol_mounted.png" COMP; } parts { part { name: "bg"; @@ -14768,6 +14873,36 @@ collections { /* begin the collection of edje groups that are in this file */ color: 0 0 0 0; } } + part { name: "vol_state"; + type: IMAGE; + mouse_events: 0; + repeat_events: 0; + description { state: "default" 0.0; + color: 0 0 0 0; + } + description { state: "visible" 0.0; + aspect: 1.0 1.0; + aspect_preference: BOTH; + align: 1.0 1.0; + min: 16 16; + rel1 { + relative: 0.75 0.0; + to: "icon"; + } + rel2 { + relative: 1.0 1.0; + to: "icon"; + } + } + description { state: "unmounted" 0.0; + inherit: "visible" 0.0; + image.normal: "icon_efm_vol_unmounted.png"; + } + description { state: "mounted" 0.0; + inherit: "visible" 0.0; + image.normal: "icon_efm_vol_mounted.png"; + } + } part { name: "dnd_action"; type: IMAGE; mouse_events: 0; @@ -14836,6 +14971,24 @@ collections { /* begin the collection of edje groups that are in this file */ action: STATE_SET "copy" 0.0; target: "dnd_action"; } + program { name: "vol_off"; + signal: "e,state,volume,off"; + source: "e"; + action: STATE_SET "default" 0.0; + target: "vol_state"; + } + program { name: "vol_unmounted"; + signal: "e,state,volume,unmounted"; + source: "e"; + action: STATE_SET "unmounted" 0.0; + target: "vol_state"; + } + program { name: "vol_mounted"; + signal: "e,state,volume,mounted"; + source: "e"; + action: STATE_SET "mounted" 0.0; + target: "vol_state"; + } program { name: "thumb_gen"; signal: "e,action,thumb,gen"; source: "e"; @@ -14896,6 +15049,9 @@ collections { /* begin the collection of edje groups that are in this file */ image: "icon_efm_dnd_copy.png" COMP; image: "icon_efm_dnd_ask.png" COMP; image: "icon_efm_dnd_move.png" COMP; + + image: "icon_efm_vol_unmounted.png" COMP; + image: "icon_efm_vol_mounted.png" COMP; } parts { part { name: "bg"; @@ -15155,6 +15311,36 @@ collections { /* begin the collection of edje groups that are in this file */ color: 0 0 0 0; } } + part { name: "vol_state"; + type: IMAGE; + mouse_events: 0; + repeat_events: 0; + description { state: "default" 0.0; + color: 0 0 0 0; + } + description { state: "visible" 0.0; + aspect: 1.0 1.0; + aspect_preference: BOTH; + align: 1.0 1.0; + min: 16 16; + rel1 { + relative: 0.75 0.0; + to: "icon"; + } + rel2 { + relative: 1.0 1.0; + to: "icon"; + } + } + description { state: "unmounted" 0.0; + inherit: "visible" 0.0; + image.normal: "icon_efm_vol_unmounted.png"; + } + description { state: "mounted" 0.0; + inherit: "visible" 0.0; + image.normal: "icon_efm_vol_mounted.png"; + } + } part { name: "dnd_action"; type: IMAGE; mouse_events: 0; @@ -15223,6 +15409,24 @@ collections { /* begin the collection of edje groups that are in this file */ action: STATE_SET "copy" 0.0; target: "dnd_action"; } + program { name: "vol_off"; + signal: "e,state,volume,off"; + source: "e"; + action: STATE_SET "default" 0.0; + target: "vol_state"; + } + program { name: "vol_unmounted"; + signal: "e,state,volume,unmounted"; + source: "e"; + action: STATE_SET "unmounted" 0.0; + target: "vol_state"; + } + program { name: "vol_mounted"; + signal: "e,state,volume,mounted"; + source: "e"; + action: STATE_SET "mounted" 0.0; + target: "vol_state"; + } program { name: "thumb_gen"; signal: "e,action,thumb,gen"; source: "e"; @@ -15287,6 +15491,9 @@ collections { /* begin the collection of edje groups that are in this file */ image: "icon_efm_dnd_copy.png" COMP; image: "icon_efm_dnd_ask.png" COMP; image: "icon_efm_dnd_move.png" COMP; + + image: "icon_efm_vol_unmounted.png" COMP; + image: "icon_efm_vol_mounted.png" COMP; } parts { part { @@ -15599,6 +15806,35 @@ collections { /* begin the collection of edje groups that are in this file */ color: 255 255 255 255; } } + part { name: "vol_state"; + type: IMAGE; + mouse_events: 0; + repeat_events: 0; + description { state: "default" 0.0; + color: 0 0 0 0; + } + description { state: "visible" 0.0; + aspect: 1.0 1.0; + aspect_preference: BOTH; + align: 1.0 1.0; + rel1 { + relative: 0.5 0.0; + to: "icon"; + } + rel2 { + relative: 1.0 1.0; + to: "icon"; + } + } + description { state: "unmounted" 0.0; + inherit: "visible" 0.0; + image.normal: "icon_efm_vol_unmounted.png"; + } + description { state: "mounted" 0.0; + inherit: "visible" 0.0; + image.normal: "icon_efm_vol_mounted.png"; + } + } part { name: "dnd_action"; type: IMAGE; mouse_events: 0; @@ -15695,6 +15931,24 @@ collections { /* begin the collection of edje groups that are in this file */ action: STATE_SET "copy" 0.0; target: "dnd_action"; } + program { name: "vol_off"; + signal: "e,state,volume,off"; + source: "e"; + action: STATE_SET "default" 0.0; + target: "vol_state"; + } + program { name: "vol_unmounted"; + signal: "e,state,volume,unmounted"; + source: "e"; + action: STATE_SET "unmounted" 0.0; + target: "vol_state"; + } + program { name: "vol_mounted"; + signal: "e,state,volume,mounted"; + source: "e"; + action: STATE_SET "mounted" 0.0; + target: "vol_state"; + } program { name: "thumb_gen"; signal: "e,action,thumb,gen"; source: "e"; @@ -15759,6 +16013,9 @@ collections { /* begin the collection of edje groups that are in this file */ image: "icon_efm_dnd_copy.png" COMP; image: "icon_efm_dnd_ask.png" COMP; image: "icon_efm_dnd_move.png" COMP; + + image: "icon_efm_vol_unmounted.png" COMP; + image: "icon_efm_vol_mounted.png" COMP; } parts { part { @@ -16071,6 +16328,35 @@ collections { /* begin the collection of edje groups that are in this file */ color: 255 255 255 255; } } + part { name: "vol_state"; + type: IMAGE; + mouse_events: 0; + repeat_events: 0; + description { state: "default" 0.0; + color: 0 0 0 0; + } + description { state: "visible" 0.0; + aspect: 1.0 1.0; + aspect_preference: BOTH; + align: 1.0 1.0; + rel1 { + relative: 0.5 0.0; + to: "icon"; + } + rel2 { + relative: 1.0 1.0; + to: "icon"; + } + } + description { state: "unmounted" 0.0; + inherit: "visible" 0.0; + image.normal: "icon_efm_vol_unmounted.png"; + } + description { state: "mounted" 0.0; + inherit: "visible" 0.0; + image.normal: "icon_efm_vol_mounted.png"; + } + } part { name: "dnd_action"; type: IMAGE; mouse_events: 0; @@ -16167,6 +16453,24 @@ collections { /* begin the collection of edje groups that are in this file */ action: STATE_SET "copy" 0.0; target: "dnd_action"; } + program { name: "vol_off"; + signal: "e,state,volume,off"; + source: "e"; + action: STATE_SET "default" 0.0; + target: "vol_state"; + } + program { name: "vol_unmounted"; + signal: "e,state,volume,unmounted"; + source: "e"; + action: STATE_SET "unmounted" 0.0; + target: "vol_state"; + } + program { name: "vol_mounted"; + signal: "e,state,volume,mounted"; + source: "e"; + action: STATE_SET "mounted" 0.0; + target: "vol_state"; + } program { name: "thumb_gen"; signal: "e,action,thumb,gen"; source: "e"; @@ -16232,6 +16536,9 @@ collections { /* begin the collection of edje groups that are in this file */ image: "icon_efm_dnd_copy.png" COMP; image: "icon_efm_dnd_ask.png" COMP; image: "icon_efm_dnd_move.png" COMP; + + image: "icon_efm_vol_unmounted.png" COMP; + image: "icon_efm_vol_mounted.png" COMP; } parts { part { @@ -16545,6 +16852,35 @@ collections { /* begin the collection of edje groups that are in this file */ color: 255 255 255 255; } } + part { name: "vol_state"; + type: IMAGE; + mouse_events: 0; + repeat_events: 0; + description { state: "default" 0.0; + color: 0 0 0 0; + } + description { state: "visible" 0.0; + aspect: 1.0 1.0; + aspect_preference: BOTH; + align: 1.0 1.0; + rel1 { + relative: 0.5 0.0; + to: "icon"; + } + rel2 { + relative: 1.0 1.0; + to: "icon"; + } + } + description { state: "unmounted" 0.0; + inherit: "visible" 0.0; + image.normal: "icon_efm_vol_unmounted.png"; + } + description { state: "mounted" 0.0; + inherit: "visible" 0.0; + image.normal: "icon_efm_vol_mounted.png"; + } + } part { name: "dnd_action"; type: IMAGE; mouse_events: 0; @@ -16641,6 +16977,24 @@ collections { /* begin the collection of edje groups that are in this file */ action: STATE_SET "copy" 0.0; target: "dnd_action"; } + program { name: "vol_off"; + signal: "e,state,volume,off"; + source: "e"; + action: STATE_SET "default" 0.0; + target: "vol_state"; + } + program { name: "vol_unmounted"; + signal: "e,state,volume,unmounted"; + source: "e"; + action: STATE_SET "unmounted" 0.0; + target: "vol_state"; + } + program { name: "vol_mounted"; + signal: "e,state,volume,mounted"; + source: "e"; + action: STATE_SET "mounted" 0.0; + target: "vol_state"; + } program { name: "thumb_gen"; signal: "e,action,thumb,gen"; source: "e"; @@ -16706,6 +17060,9 @@ collections { /* begin the collection of edje groups that are in this file */ image: "icon_efm_dnd_copy.png" COMP; image: "icon_efm_dnd_ask.png" COMP; image: "icon_efm_dnd_move.png" COMP; + + image: "icon_efm_vol_unmounted.png" COMP; + image: "icon_efm_vol_mounted.png" COMP; } parts { part { @@ -17018,6 +17375,35 @@ collections { /* begin the collection of edje groups that are in this file */ color: 255 255 255 255; } } + part { name: "vol_state"; + type: IMAGE; + mouse_events: 0; + repeat_events: 0; + description { state: "default" 0.0; + color: 0 0 0 0; + } + description { state: "visible" 0.0; + aspect: 1.0 1.0; + aspect_preference: BOTH; + align: 1.0 1.0; + rel1 { + relative: 0.5 0.0; + to: "icon"; + } + rel2 { + relative: 1.0 1.0; + to: "icon"; + } + } + description { state: "unmounted" 0.0; + inherit: "visible" 0.0; + image.normal: "icon_efm_vol_unmounted.png"; + } + description { state: "mounted" 0.0; + inherit: "visible" 0.0; + image.normal: "icon_efm_vol_mounted.png"; + } + } part { name: "dnd_action"; type: IMAGE; mouse_events: 0; @@ -17114,6 +17500,24 @@ collections { /* begin the collection of edje groups that are in this file */ action: STATE_SET "copy" 0.0; target: "dnd_action"; } + program { name: "vol_off"; + signal: "e,state,volume,off"; + source: "e"; + action: STATE_SET "default" 0.0; + target: "vol_state"; + } + program { name: "vol_unmounted"; + signal: "e,state,volume,unmounted"; + source: "e"; + action: STATE_SET "unmounted" 0.0; + target: "vol_state"; + } + program { name: "vol_mounted"; + signal: "e,state,volume,mounted"; + source: "e"; + action: STATE_SET "mounted" 0.0; + target: "vol_state"; + } program { name: "thumb_gen"; signal: "e,action,thumb,gen"; source: "e"; @@ -23758,6 +24162,9 @@ ICON("computer","icon_efm_root.png", 64) // "fileman/root ICON("drive-harddisk","icon_efm_hdd.png", 128) // "fileman/hd" "fileman/hdd" ICON("drive-optical","icon_efm_cd.png", 128) // "fileman/??" ICON("media-flash","icon_efm_flash.png", 128) // "fileman/??" +ICON("drive-removable-media","icon_efm_usbmedia.png", 128); + +ICON("media-eject","icon_efm_eject.png", 64) /* End of FreeDesktop.Org icons */ diff --git a/po/ru.po b/po/ru.po index c77cab1d7..8c63e837b 100644 --- a/po/ru.po +++ b/po/ru.po @@ -7469,3 +7469,23 @@ msgstr "Система" #~ msgid "Add To Favorites Menu" #~ msgstr "Добавить в Избранное" + +#: ../src/bin/e_fm.c:8045 +msgid "Mount" +msgstr "Подключить" + +#: ../src/bin/e_fm.c:8040 +msgid "Unmount" +msgstr "Отключить" + +#: ../src/bin/e_fm.c:8050 +msgid "Eject" +msgstr "Извлечь" + +#: ../src/modules/fileman/e_mod_config.c:273 +msgid "Mount volumes on insert" +msgstr "Монтировать тома при подключении" + +#: ../src/modules/fileman/e_mod_config.c:276 +msgid "Open filemanager on mount" +msgstr "Открыть менеджер файлов при монтировании" diff --git a/src/bin/e_config.c b/src/bin/e_config.c index b74c7d387..fe5a48e28 100644 --- a/src/bin/e_config.c +++ b/src/bin/e_config.c @@ -656,6 +656,8 @@ e_config_init(void) E_CONFIG_VAL(D, T, thumbscroll_friction, DOUBLE); E_CONFIG_VAL(D, T, hal_desktop, INT); + E_CONFIG_VAL(D, T, hal_auto_mount, INT); + E_CONFIG_VAL(D, T, hal_auto_open, INT); E_CONFIG_VAL(D, T, border_keyboard.timeout, DOUBLE); E_CONFIG_VAL(D, T, border_keyboard.move.dx, UCHAR); @@ -663,8 +665,6 @@ e_config_init(void) E_CONFIG_VAL(D, T, border_keyboard.resize.dx, UCHAR); E_CONFIG_VAL(D, T, border_keyboard.resize.dy, UCHAR); - E_CONFIG_VAL(D, T, hal_desktop, INT); - E_CONFIG_VAL(D, T, scale.min, DOUBLE); E_CONFIG_VAL(D, T, scale.max, DOUBLE); E_CONFIG_VAL(D, T, scale.factor, DOUBLE); diff --git a/src/bin/e_config.h b/src/bin/e_config.h index 2fac4c87f..53d7f3156 100644 --- a/src/bin/e_config.h +++ b/src/bin/e_config.h @@ -302,6 +302,8 @@ struct _E_Config double thumbscroll_friction; // GUI int hal_desktop; + int hal_auto_mount; + int hal_auto_open; struct { double timeout; diff --git a/src/bin/e_fm.c b/src/bin/e_fm.c index 644ff040e..07f9a2c15 100644 --- a/src/bin/e_fm.c +++ b/src/bin/e_fm.c @@ -359,6 +359,8 @@ static void _e_fm_error_abort_cb(void *data, E_Dialog *dialog); static void _e_fm_error_ignore_this_cb(void *data, E_Dialog *dialog); static void _e_fm_error_ignore_all_cb(void *data, E_Dialog *dialog); +static void _e_fm_hal_error_dialog(const char *title, const char *msg, const char *pstr); + static void _e_fm2_file_delete(Evas_Object *obj); static void _e_fm2_file_delete_menu(void *data, E_Menu *m, E_Menu_Item *mi); static void _e_fm2_file_delete_delete_cb(void *obj); @@ -408,6 +410,15 @@ static int _e_fm2_context_list_sort(const void *data1, const void *data2); static char *_e_fm_string_append_char(char *str, size_t *size, size_t *len, char c); static char *_e_fm_string_append_quoted(char *str, size_t *size, size_t *len, const char *src); +void _e_fm2_path_parent_set(Evas_Object *obj, const char *path); + +static void _e_fm2_volume_mount(void *data, E_Menu *m, E_Menu_Item *mi); +static void _e_fm2_volume_unmount(void *data, E_Menu *m, E_Menu_Item *mi); +static void _e_fm2_volume_eject(void *data, E_Menu *m, E_Menu_Item *mi); + +static void _e_fm2_icon_removable_update(E_Fm2_Icon *ic); +static void _e_fm2_volume_icon_update(E_Volume *v); + static char *_e_fm2_meta_path = NULL; static Evas_Smart *_e_fm2_smart = NULL; static Eina_List *_e_fm2_list = NULL; @@ -809,12 +820,31 @@ _e_fm2_cb_mount_fail(void *data) sd = evas_object_smart_data_get(data); if (!sd) return; // safety - /* FIXME; some dialog */ if (sd->mount) { - e_fm2_hal_unmount(sd->mount); + // At this moment E_Fm2_Mount object already deleted in e_fm_hal.c sd->mount = NULL; - evas_object_smart_callback_call(data, "dir_deleted", NULL); + if (sd->config->view.open_dirs_in_place) + e_fm2_path_set(data, "favorites", "/"); + else + evas_object_smart_callback_call(data, "dir_deleted", NULL); + } +} + +static void +_e_fm2_cb_unmount_ok(void *data) +{ + E_Fm2_Smart_Data *sd; + + sd = evas_object_smart_data_get(data); + if (!sd) return; + if (sd->mount) + { + sd->mount = NULL; + if (sd->config->view.open_dirs_in_place) + _e_fm2_path_parent_set(data, sd->realpath); + else + evas_object_smart_callback_call(data, "dir_deleted", NULL); } } @@ -945,7 +975,7 @@ e_fm2_path_set(Evas_Object *obj, const char *dev, const char *path) if (v) sd->mount = e_fm2_hal_mount(v, _e_fm2_cb_mount_ok, _e_fm2_cb_mount_fail, - NULL, NULL, obj); + _e_fm2_cb_unmount_ok, NULL, obj); } else if (sd->config->view.open_dirs_in_place == 0) { @@ -954,7 +984,7 @@ e_fm2_path_set(Evas_Object *obj, const char *dev, const char *path) if (m) sd->mount = e_fm2_hal_mount(m->volume, _e_fm2_cb_mount_ok, _e_fm2_cb_mount_fail, - NULL, NULL, obj); + _e_fm2_cb_unmount_ok, NULL, obj); } if (!sd->mount || sd->mount->mounted) @@ -2578,6 +2608,19 @@ _e_fm2_client_unmount(const char *udi) return _e_fm_client_send_new(E_FM_OP_UNMOUNT, (void *)d, l); } +EAPI int +_e_fm2_client_eject(const char *udi) +{ + char *data; + int size; + + size = strlen(udi) + 1; + data = alloca(size); + strcpy(data, udi); + + return _e_fm_client_send_new(E_FM_OP_EJECT, data, size); +} + static void _e_fm2_client_monitor_list_end(Evas_Object *obj) { @@ -2907,7 +2950,13 @@ e_fm2_client_data(Ecore_Ipc_Event_Client_Data *e) E_Volume *v; v = eet_data_descriptor_decode(_e_volume_edd, e->data, e->size); - if (v) e_fm2_hal_volume_add(v); + if (v) + { + e_fm2_hal_volume_add(v); + if (e_config->hal_auto_mount && !v->mounted && !v->first_time) + _e_fm2_client_mount(v->udi, v->mount_point); + v->first_time = 0; + } } break; @@ -2932,7 +2981,21 @@ e_fm2_client_data(Ecore_Ipc_Event_Client_Data *e) udi = e->data; mountpoint = udi + strlen(udi) + 1; v = e_fm2_hal_volume_find(udi); - if (v) e_fm2_hal_mount_add(v, mountpoint); + if (v) + { + e_fm2_hal_mount_add(v, mountpoint); + _e_fm2_volume_icon_update(v); + if (e_config->hal_auto_open && !eina_list_count(v->mounts)) + { + E_Action *a; + Eina_List *m; + + a = e_action_find("fileman"); + m = e_manager_list(); + if (a && a->func.go && m && m->data) + a->func.go(E_OBJECT(m->data), mountpoint); + } + } } break; @@ -2944,15 +3007,62 @@ e_fm2_client_data(Ecore_Ipc_Event_Client_Data *e) udi = e->data; v = e_fm2_hal_volume_find(udi); - if (v) - { - v->mounted = 0; - if (v->mount_point) free(v->mount_point); - v->mount_point = NULL; - } + if (v) + { + e_fm2_hal_mount_del(v); + _e_fm2_volume_icon_update(v); + } } break; + case E_FM_OP_EJECT_DONE: + break; + + case E_FM_OP_MOUNT_ERROR:/*mount error*/ + if (e->data && (e->size > 1)) + { + E_Volume *v; + char *udi; + + udi = e->data; + v = e_fm2_hal_volume_find(udi); + if (v) + { + _e_fm_hal_error_dialog(_("Mount Error"), _("Can't mount device"), e->data); + e_fm2_hal_mount_fail(v); + } + } + break; + + case E_FM_OP_UNMOUNT_ERROR:/*unmount error*/ + if (e->data && (e->size > 1)) + { + E_Volume *v; + char *udi; + + udi = e->data; + v = e_fm2_hal_volume_find(udi); + if (v) + { + _e_fm_hal_error_dialog(_("Unmount Error"), _("Can't unmount device"), e->data); + e_fm2_hal_unmount_fail(v); + } + } + break; + + case E_FM_OP_EJECT_ERROR: + if (e->data && (e->size > 1)) + { + E_Volume *v; + char *udi; + + udi = e->data; + v = e_fm2_hal_volume_find(udi); + if (v) + _e_fm_hal_error_dialog(_("Eject Error"), _("Can't eject device"), e->data); + } + 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); @@ -4601,10 +4711,9 @@ _e_fm2_icon_realize(E_Fm2_Icon *ic) if ((selectraise) && (!strcmp(selectraise, "on"))) evas_object_stack_below(ic->obj, ic->sd->drop); } - if (ic->info.removable_full) - edje_object_signal_emit(ic->obj_icon, "e,state,removable,full", "e"); -// else -// edje_object_signal_emit(ic->obj_icon, "e,state,removable,empty", "e"); + + if (ic->info.removable) + _e_fm2_icon_removable_update(ic); } static void @@ -7817,6 +7926,7 @@ _e_fm2_icon_menu(E_Fm2_Icon *ic, Evas_Object *obj, unsigned int timestamp) e_menu_item_callback_set(mi, _e_fm2_new_directory, sd); } } + if (!ic->info.removable) { if (!(sd->icon_menu.flags & E_FM2_MENU_NO_CUT)) { if (ecore_file_can_write(sd->realpath)) @@ -7865,7 +7975,8 @@ _e_fm2_icon_menu(E_Fm2_Icon *ic, Evas_Object *obj, unsigned int timestamp) e_menu_item_callback_set(mi, _e_fm2_file_symlink_menu, sd); } } - + } + can_w = 0; can_w2 = 1; if (ic->sd->order_file) @@ -7909,7 +8020,7 @@ _e_fm2_icon_menu(E_Fm2_Icon *ic, Evas_Object *obj, unsigned int timestamp) protect = 0; sel = eina_list_free(sel); - if ((can_w) && (can_w2) && !(protect)) + if ((can_w) && (can_w2) && !(protect) && !ic->info.removable) { mi = e_menu_item_new(mn); e_menu_item_separator_set(mi, 1); @@ -7931,10 +8042,42 @@ _e_fm2_icon_menu(E_Fm2_Icon *ic, Evas_Object *obj, unsigned int timestamp) } } - mi = e_menu_item_new(mn); - e_menu_item_label_set(mi, _("Properties")); - e_util_menu_item_theme_icon_set(mi, "document-properties"); - e_menu_item_callback_set(mi, _e_fm2_file_properties, ic); + if (ic->info.removable) + { + E_Volume *v; + + v = e_fm2_hal_volume_find(ic->info.link); + if (v) + { + mi = e_menu_item_new(mn); + e_menu_item_separator_set(mi, 1); + + mi = e_menu_item_new(mn); + if (v->mounted) + { + e_menu_item_label_set(mi, _("Unmount")); + e_menu_item_callback_set(mi, _e_fm2_volume_unmount, v); + } + else + { + e_menu_item_label_set(mi, _("Mount")); + e_menu_item_callback_set(mi, _e_fm2_volume_mount, v); + } + + mi = e_menu_item_new(mn); + e_menu_item_label_set(mi, _("Eject")); + e_util_menu_item_theme_icon_set(mi, "media-eject"); + e_menu_item_callback_set(mi, _e_fm2_volume_eject, v); + + mi = e_menu_item_new(mn); + e_menu_item_separator_set(mi, 1); + } + } + + mi = e_menu_item_new(mn); + e_menu_item_label_set(mi, _("Properties")); + e_util_menu_item_theme_icon_set(mi, "document-properties"); + e_menu_item_callback_set(mi, _e_fm2_file_properties, ic); if (ic->info.mime) { @@ -9001,6 +9144,37 @@ _e_fm_error_ignore_all_cb(void *data, E_Dialog *dialog) e_object_del(E_OBJECT(dialog)); } +static void +_e_fm_hal_error_dialog(const char *title, const char *msg, const char *pstr) +{ + E_Manager *man; + E_Container *con; + E_Dialog *dialog; + char text[4096]; + const char *u, *d, *n, *m; + + man = e_manager_current_get(); + if (!man) return; + con = e_container_current_get(man); + if (!con) return; + + dialog = e_dialog_new(con, "E", "_fm_hal_error_dialog"); + e_dialog_title_set(dialog, title); + e_dialog_icon_set(dialog, "drive-harddisk", 64); + e_dialog_button_add(dialog, _("OK"), NULL, NULL, NULL); + + u = pstr; + d = pstr += strlen(pstr) + 1; + n = pstr += strlen(pstr) + 1; + m = pstr += strlen(pstr) + 1; + snprintf(text, sizeof(text), "%s
%s
%s
%s
%s", msg, u, d, n, m); + e_dialog_text_set(dialog, text); + + e_win_centered_set(dialog->win, 1); + e_dialog_button_focus_num(dialog, 0); + e_dialog_show(dialog); +} + static void _e_fm2_file_properties(void *data, E_Menu *m, E_Menu_Item *mi) { @@ -9369,10 +9543,7 @@ _e_fm2_live_process(Evas_Object *obj) ic->removable_state_change = 0; if ((ic->realized) && (ic->obj_icon)) { - if (ic->info.removable_full) - edje_object_signal_emit(ic->obj_icon, "e,state,removable,full", "e"); - else - edje_object_signal_emit(ic->obj_icon, "e,state,removable,empty", "e"); + _e_fm2_icon_removable_update(ic); _e_fm2_icon_label_set(ic, ic->obj); } } @@ -9510,3 +9681,101 @@ _e_fm2_theme_edje_icon_object_set(E_Fm2_Smart_Data *sd, Evas_Object *o, const ch ret = e_theme_edje_object_set(o, category, buf); return ret; } + +static void +_e_fm2_volume_mount(void *data, E_Menu *m, E_Menu_Item *mi) +{ + E_Volume *v; + char *mp; + + v = data; + if (!v) return; + + mp = e_fm2_hal_volume_mountpoint_get(v); + _e_fm2_client_mount(v->udi, mp); + free(mp); +} + +static void +_e_fm2_volume_unmount(void *data, E_Menu *m, E_Menu_Item *mi) +{ + E_Volume *v; + + v = data; + if (!v) return; + + v->auto_unmount = 0; + _e_fm2_client_unmount(v->udi); +} + +static void +_e_fm2_volume_eject(void *data, E_Menu *m, E_Menu_Item *mi) +{ + E_Volume *v; + + v = data; + if (!v) return; + + v->auto_unmount = 0; + _e_fm2_client_eject(v->udi); +} + +static void +_update_volume_icon(E_Volume *v, E_Fm2_Icon *ic) +{ + if (ic->info.removable_full) + edje_object_signal_emit(ic->obj_icon, "e,state,removable,full", "e"); + else + edje_object_signal_emit(ic->obj_icon, "e,state,removable,empty", "e"); + + if (v) + { + if (v->mounted) + edje_object_signal_emit(ic->obj, "e,state,volume,mounted", "e"); + else + edje_object_signal_emit(ic->obj, "e,state,volume,unmounted", "e"); + } + else + edje_object_signal_emit(ic->obj, "e,state,volume,off", "e"); +} + +static void +_e_fm2_volume_icon_update(E_Volume *v) +{ + Evas_Object *o; + char file[PATH_MAX], fav[PATH_MAX], desk[PATH_MAX]; + Eina_List *l; + E_Fm2_Icon *ic; + + if (!v || !v->storage) return; + + e_user_dir_snprintf(fav, sizeof(fav), "fileman/favorites"); + e_user_homedir_snprintf(desk, sizeof(desk), "Desktop"); + snprintf(file, sizeof(file), "|%s_%d.desktop", + ecore_file_file_get(v->storage->udi), v->partition_number); + + EINA_LIST_FOREACH(_e_fm2_list, l, o) + { + const char *rp; + + if ((_e_fm2_list_walking > 0) && + (eina_list_data_find(_e_fm2_list_remove, o))) continue; + + rp = e_fm2_real_path_get(o); + if (strcmp(rp, fav) && strcmp(rp, desk)) continue; + + ic = _e_fm2_icon_find(l->data, file); + if (ic) + _update_volume_icon(v, ic); + } +} + +static void +_e_fm2_icon_removable_update(E_Fm2_Icon *ic) +{ + E_Volume *v; + + if (!ic) return; + v = e_fm2_hal_volume_find(ic->info.link); + _update_volume_icon(v, ic); +} diff --git a/src/bin/e_fm_hal.c b/src/bin/e_fm_hal.c index 76044d0ec..9cfa396d2 100644 --- a/src/bin/e_fm_hal.c +++ b/src/bin/e_fm_hal.c @@ -9,8 +9,11 @@ static void _e_fm2_volume_write(E_Volume *v) EINA_ARG_NONNULL(1); static void _e_fm2_volume_erase(E_Volume *v) EINA_ARG_NONNULL(1); +static void _e_fm2_hal_mount_free(E_Fm2_Mount *m); EINA_ARG_NONNULL(1); static void _e_fm2_hal_mount_ok(E_Fm2_Mount *m) EINA_ARG_NONNULL(1); -static int _e_fm2_hal_mount_timeout(E_Fm2_Mount *m) EINA_ARG_NONNULL(1); +static void _e_fm2_hal_mount_fail(E_Fm2_Mount *m) EINA_ARG_NONNULL(1); +static void _e_fm2_hal_unmount_ok(E_Fm2_Mount *m) EINA_ARG_NONNULL(1); +static void _e_fm2_hal_unmount_fail(E_Fm2_Mount *m) EINA_ARG_NONNULL(1); static Eina_List *_e_stores = NULL; static Eina_List *_e_vols = NULL; @@ -268,11 +271,20 @@ e_fm2_hal_volume_add(E_Volume *v) EAPI void e_fm2_hal_volume_del(E_Volume *v) { + Eina_List *l, *l_nxt; + E_Fm2_Mount *m; + // printf("VOL- %s\n", v->udi); if (v->storage) v->storage->volumes = eina_list_remove(v->storage->volumes, v); _e_vols = eina_list_remove(_e_vols, v); _e_fm2_volume_erase(v); + EINA_LIST_FOREACH_SAFE(v->mounts, l, l_nxt, m) + { + _e_fm2_hal_unmount_ok(m); + v->mounts = eina_list_remove_list(v->mounts, l); + _e_fm2_hal_mount_free(m); + } _e_volume_free(v); } @@ -403,7 +415,12 @@ e_fm2_hal_mount_add(E_Volume *v, const char *mountpoint) Eina_List *l; v->mounted = 1; - v->mount_point = strdup(mountpoint); + if (mountpoint && (*mountpoint != 0)) + { + if (v->mount_point) + free(v->mount_point); + v->mount_point = strdup(mountpoint); + } for (l = v->mounts; l; l = l->next) _e_fm2_hal_mount_ok(l->data); @@ -412,18 +429,34 @@ e_fm2_hal_mount_add(E_Volume *v, const char *mountpoint) } EAPI void -e_fm2_hal_mount_del(E_Fm2_Mount *m) +e_fm2_hal_mount_del(E_Volume *v) +{ + Eina_List *l, *l_nxt; + E_Fm2_Mount *m; + + v->mounted = 0; + if (v->mount_point) + { + free(v->mount_point); + v->mount_point = NULL; + } + + EINA_LIST_FOREACH_SAFE(v->mounts, l, l_nxt, m) + { + _e_fm2_hal_unmount_ok(m); + v->mounts = eina_list_remove_list(v->mounts, l); + _e_fm2_hal_mount_free(m); + } +} + +EAPI void +_e_fm2_hal_mount_free(E_Fm2_Mount *m) { if (!m) return; if (m->udi) eina_stringshare_del(m->udi); if (m->mount_point) eina_stringshare_del(m->mount_point); - if (m->timeout) - { - ecore_timer_del(m->timeout); - m->timeout = NULL; - } free(m); } @@ -469,16 +502,42 @@ e_fm2_hal_mount(E_Volume *v, v->mounts = eina_list_prepend(v->mounts, m); // printf("BEGIN MOUNT %p '%s'\n", m, v->mount_point); - + if (!v->mounted) { - if (m->timeout) ecore_timer_del(m->timeout); - m->timeout = ecore_timer_add(10.0, (int (*)(void*))_e_fm2_hal_mount_timeout, m); + v->auto_unmount = 1; _e_fm2_client_mount(v->udi, v->mount_point); } + else + { + v->auto_unmount = 0; + m->mount_point = eina_stringshare_add(v->mount_point); + } + return m; } +EAPI void +e_fm2_hal_mount_fail(E_Volume *v) +{ + Eina_List *l, *l_nxt; + E_Fm2_Mount *m; + + v->mounted = 0; + if (v->mount_point) + { + free(v->mount_point); + v->mount_point = NULL; + } + + EINA_LIST_FOREACH_SAFE(v->mounts, l, l_nxt, m) + { + _e_fm2_hal_mount_fail(m); + v->mounts = eina_list_remove_list(v->mounts, l); + _e_fm2_hal_mount_free(m); + } +} + EAPI void e_fm2_hal_unmount(E_Fm2_Mount *m) { @@ -486,32 +545,66 @@ e_fm2_hal_unmount(E_Fm2_Mount *m) if (!(v = m->volume)) return; v->mounts = eina_list_remove(v->mounts, m); - e_fm2_hal_mount_del(m); + _e_fm2_hal_mount_free(m); - if (!eina_list_count(v->mounts)) + if (v->auto_unmount && v->mounted && !eina_list_count(v->mounts)) _e_fm2_client_unmount(v->udi); } +EAPI void +e_fm2_hal_unmount_fail(E_Volume *v) +{ + Eina_List *l; + + v->mounted = 1; + + for (l = v->mounts; l; l = l->next) + _e_fm2_hal_unmount_fail(l->data); +} + static void _e_fm2_hal_mount_ok(E_Fm2_Mount *m) { m->mounted = 1; - if (m->volume) m->mount_point = eina_stringshare_add(m->volume->mount_point); - if (m->timeout) - { - ecore_timer_del(m->timeout); - m->timeout = NULL; - } - if (m->mount_ok) m->mount_ok(m->data); + if (m->volume) + m->mount_point = eina_stringshare_add(m->volume->mount_point); + if (m->mount_ok) + m->mount_ok(m->data); // printf("MOUNT OK '%s'\n", m->mount_point); } -static int -_e_fm2_hal_mount_timeout(E_Fm2_Mount *m) +static void +_e_fm2_hal_mount_fail(E_Fm2_Mount *m) { - m->mount_fail(m->data); - m->timeout = NULL; - return 0; + m->mounted = 0; + if (m->mount_point) + { + eina_stringshare_del(m->mount_point); + m->mount_point = NULL; + } + if (m->mount_fail) + m->mount_fail(m->data); +} + +static void +_e_fm2_hal_unmount_ok(E_Fm2_Mount *m) +{ + m->mounted = 0; + if (m->mount_point) + { + eina_stringshare_del(m->mount_point); + m->mount_point = NULL; + } + if (m->unmount_ok) + m->unmount_ok(m->data); +} + +static void +_e_fm2_hal_unmount_fail(E_Fm2_Mount *m) +{ + m->mounted = 1; + if (m->unmount_fail) + m->unmount_fail(m->data); } EAPI void diff --git a/src/bin/e_fm_hal.h b/src/bin/e_fm_hal.h index 9c7e708b4..521daa4b3 100644 --- a/src/bin/e_fm_hal.h +++ b/src/bin/e_fm_hal.h @@ -17,13 +17,15 @@ EAPI E_Volume *e_fm2_hal_volume_find(const char *udi); EAPI char *e_fm2_hal_volume_mountpoint_get(E_Volume *v); EAPI void e_fm2_hal_mount_add(E_Volume *v, const char *mountpoint); -EAPI void e_fm2_hal_mount_del(E_Fm2_Mount *m); +EAPI void e_fm2_hal_mount_del(E_Volume *v); EAPI E_Fm2_Mount *e_fm2_hal_mount_find(const char *path); EAPI E_Fm2_Mount *e_fm2_hal_mount(E_Volume *v, void (*mount_ok) (void *data), void (*mount_fail) (void *data), void (*unmount_ok) (void *data), void (*unmount_fail) (void *data), void *data); +EAPI void e_fm2_hal_mount_fail(E_Volume *v); EAPI void e_fm2_hal_unmount(E_Fm2_Mount *m); +EAPI void e_fm2_hal_unmount_fail(E_Volume *v); EAPI void e_fm2_hal_show_desktop_icons(void); EAPI void e_fm2_hal_hide_desktop_icons(void); diff --git a/src/bin/e_fm_main.c b/src/bin/e_fm_main.c index 158d69b52..60386fb9c 100644 --- a/src/bin/e_fm_main.c +++ b/src/bin/e_fm_main.c @@ -58,6 +58,10 @@ #define DEF_ROUND_TRIP_TOLERANCE 0.01 #define DEF_MOD_BACKOFF 0.2 +#define E_FM_MOUNT_TIMEOUT 30.0 +#define E_FM_UNMOUNT_TIMEOUT 60.0 +#define E_FM_EJECT_TIMEOUT 15.0 + typedef struct _E_Dir E_Dir; typedef struct _E_Fop E_Fop; typedef struct _E_Mod E_Mod; @@ -189,17 +193,26 @@ static void _e_dbus_cb_vol_prop(void *data, void *reply_data, DBusError *error); static void _e_dbus_cb_vol_prop_mount_modified(void *data, void *reply_data, DBusError *error); static void _e_dbus_cb_vol_mounted(void *user_data, void *method_return, DBusError *error); static void _e_dbus_cb_vol_unmounted(void *user_data, void *method_return, DBusError *error); +static void _e_dbus_cb_vol_unmounted_before_eject(void *user_data, void *method_return, DBusError *error); +static int _e_dbus_vb_vol_ejecting_after_unmount(void *data); +static void _e_dbus_cb_vol_ejected(void *user_data, void *method_return, DBusError *error); +static int _e_dbus_format_error_msg(char **buf, E_Volume *v, DBusError *error); + +static int _e_dbus_vol_mount_timeout(void *data); +static int _e_dbus_vol_unmount_timeout(void *data); +static int _e_dbus_vol_eject_timeout(void *data); EAPI E_Storage *e_storage_add(const char *udi); EAPI void e_storage_del(const char *udi); EAPI E_Storage *e_storage_find(const char *udi); -EAPI E_Volume *e_volume_add(const char *udi); +EAPI E_Volume *e_volume_add(const char *udi, char first_time); EAPI void e_volume_del(const char *udi); EAPI E_Volume *e_volume_find(const char *udi); EAPI void e_volume_mount(E_Volume *v); EAPI void e_volume_unmount(E_Volume *v); +EAPI void e_volume_eject(E_Volume *v); /* local subsystem globals */ static Ecore_Ipc_Server *_e_ipc_server = NULL; @@ -366,7 +379,7 @@ _e_dbus_cb_dev_vol(void *user_data, void *reply_data, DBusError *error) EINA_LIST_FOREACH(ret->strings, l, device) { // printf("DB VOL+: %s\n", device); - e_volume_add(device); + e_volume_add(device, 1); } } @@ -407,7 +420,7 @@ _e_dbus_cb_vol_is(void *user_data, void *reply_data, DBusError *error) if (ret && ret->boolean) { // printf("DB VOL IS+: %s\n", udi); - e_volume_add(udi); + e_volume_add(udi, 0); } error: @@ -720,6 +733,26 @@ _e_dbus_cb_vol_prop(void *data, void *reply_data, DBusError *error) return; } +static int +_e_dbus_format_error_msg(char **buf, E_Volume *v, DBusError *error) +{ + int size, vu, vm, en; + char *tmp; + + vu = strlen(v->udi) + 1; + vm = strlen(v->mount_point) + 1; + en = strlen(error->name) + 1; + size = vu + vm + en + strlen(error->message) + 1; + tmp = *buf = malloc(size); + + strcpy(tmp, v->udi); + strcpy(tmp += vu, v->mount_point); + strcpy(tmp += vm, error->name); + strcpy(tmp += en, error->message); + + return size; +} + static void _e_dbus_cb_vol_prop_mount_modified(void *data, void *reply_data, DBusError *error) { @@ -730,7 +763,18 @@ _e_dbus_cb_vol_prop_mount_modified(void *data, void *reply_data, DBusError *erro if (!ret) return; if (dbus_error_is_set(error)) { + char *buf; + int size; + + size = _e_dbus_format_error_msg(&buf, v, error); + if (v->mounted) + ecore_ipc_server_send(_e_ipc_server, 6/*E_IPC_DOMAIN_FM*/, E_FM_OP_UNMOUNT_ERROR, + 0, 0, 0, buf, size); + else + ecore_ipc_server_send(_e_ipc_server, 6/*E_IPC_DOMAIN_FM*/, E_FM_OP_MOUNT_ERROR, + 0, 0, 0, buf, size); dbus_error_free(error); + free(buf); return; } @@ -767,7 +811,7 @@ _e_dbus_cb_vol_prop_mount_modified(void *data, void *reply_data, DBusError *erro static Eina_List *_e_vols = NULL; EAPI E_Volume * -e_volume_add(const char *udi) +e_volume_add(const char *udi, char first_time) { E_Volume *v; @@ -778,6 +822,7 @@ e_volume_add(const char *udi) // printf("VOL+ %s\n", udi); v->udi = strdup(udi); v->icon = NULL; + v->first_time = first_time; _e_vols = eina_list_append(_e_vols, v); e_hal_device_get_all_properties(_e_dbus_conn, v->udi, _e_dbus_cb_vol_prop, v); @@ -785,7 +830,8 @@ e_volume_add(const char *udi) udi, "org.freedesktop.Hal.Device", "PropertyModified", _e_dbus_cb_prop_modified, v); - + v->guard = NULL; + return v; } @@ -796,6 +842,11 @@ e_volume_del(const char *udi) v = e_volume_find(udi); if (!v) return; + if (v->guard) + { + ecore_timer_del(v->guard); + v->guard = NULL; + } if (v->prop_handler) e_dbus_signal_handler_del(_e_dbus_conn, v->prop_handler); if (v->validated) { @@ -825,6 +876,26 @@ e_volume_find(const char *udi) return NULL; } +static int +_e_dbus_vol_mount_timeout(void *data) +{ + E_Volume *v = data; + DBusError error; + char *buf; + int size; + + v->guard = NULL; + dbus_pending_call_cancel(v->op); + error.name = "org.enlightenment.fm2.MountTimeout"; + error.message = "Unable to mount the volume with specified time-out."; + size = _e_dbus_format_error_msg(&buf, v, &error); + ecore_ipc_server_send(_e_ipc_server, 6/*E_IPC_DOMAIN_FM*/, E_FM_OP_MOUNT_ERROR, + 0, 0, 0, buf, size); + free(buf); + + return 0; +} + static void _e_dbus_cb_vol_mounted(void *user_data, void *method_return, DBusError *error) { @@ -832,11 +903,23 @@ _e_dbus_cb_vol_mounted(void *user_data, void *method_return, DBusError *error) char *buf; int size; + if (v->guard) + { + ecore_timer_del(v->guard); + v->guard = NULL; + } + if (dbus_error_is_set(error)) { - dbus_error_free(error); - return; + size = _e_dbus_format_error_msg(&buf, v, error); + ecore_ipc_server_send(_e_ipc_server, 6/*E_IPC_DOMAIN_FM*/, E_FM_OP_MOUNT_ERROR, + 0, 0, 0, buf, size); + dbus_error_free(error); + free(buf); + return; } + +/* v->mounted = 1; // printf("MOUNT: %s from %s\n", v->udi, v->mount_point); size = strlen(v->udi) + 1 + strlen(v->mount_point) + 1; @@ -844,9 +927,10 @@ _e_dbus_cb_vol_mounted(void *user_data, void *method_return, DBusError *error) strcpy(buf, v->udi); strcpy(buf + strlen(buf) + 1, v->mount_point); ecore_ipc_server_send(_e_ipc_server, - 6/*E_IPC_DOMAIN_FM*/, + 6/*E_IPC_DOMAIN_FM*//*, E_FM_OP_MOUNT_DONE, 0, 0, 0, buf, size); +*/ } EAPI void @@ -856,7 +940,7 @@ e_volume_mount(E_Volume *v) char *mount_point; Eina_List *opt = NULL; - if (!v || !v->mount_point || strncmp(v->mount_point, "/media/", 7)) + if (!v || v->guard || !v->mount_point || strncmp(v->mount_point, "/media/", 7)) return; mount_point = v->mount_point + 7; @@ -869,11 +953,32 @@ e_volume_mount(E_Volume *v) snprintf(buf, sizeof(buf), "uid=%i", (int)getuid()); opt = eina_list_append(opt, buf); } - e_hal_device_volume_mount(_e_dbus_conn, v->udi, mount_point, - v->fstype, opt, NULL, v); + v->guard = ecore_timer_add(E_FM_MOUNT_TIMEOUT, _e_dbus_vol_mount_timeout, v); + v->op = e_hal_device_volume_mount(_e_dbus_conn, v->udi, mount_point, + v->fstype, opt, _e_dbus_cb_vol_mounted, v); opt = eina_list_free(opt); } +static int +_e_dbus_vol_unmount_timeout(void *data) +{ + E_Volume *v = data; + DBusError error; + char *buf; + int size; + + v->guard = NULL; + dbus_pending_call_cancel(v->op); + error.name = "org.enlightenment.fm2.UnmountTimeout"; + error.message = "Unable to unmount the volume with specified time-out."; + size = _e_dbus_format_error_msg(&buf, v, &error); + ecore_ipc_server_send(_e_ipc_server, 6/*E_IPC_DOMAIN_FM*/, E_FM_OP_UNMOUNT_ERROR, + 0, 0, 0, buf, size); + free(buf); + + return 0; +} + static void _e_dbus_cb_vol_unmounted(void *user_data, void *method_return, DBusError *error) { @@ -881,11 +986,23 @@ _e_dbus_cb_vol_unmounted(void *user_data, void *method_return, DBusError *error) char *buf; int size; + if (v->guard) + { + ecore_timer_del(v->guard); + v->guard = NULL; + } + if (dbus_error_is_set(error)) { - dbus_error_free(error); - return; + size = _e_dbus_format_error_msg(&buf, v, error); + ecore_ipc_server_send(_e_ipc_server, 6/*E_IPC_DOMAIN_FM*/, E_FM_OP_UNMOUNT_ERROR, + 0, 0, 0, buf, size); + dbus_error_free(error); + free(buf); + return; } + +/* v->mounted = 0; // printf("UNMOUNT: %s from %s\n", v->udi, v->mount_point); size = strlen(v->udi) + 1 + strlen(v->mount_point) + 1; @@ -893,17 +1010,118 @@ _e_dbus_cb_vol_unmounted(void *user_data, void *method_return, DBusError *error) strcpy(buf, v->udi); strcpy(buf + strlen(buf) + 1, v->mount_point); ecore_ipc_server_send(_e_ipc_server, - 6/*E_IPC_DOMAIN_FM*/, + 6/*E_IPC_DOMAIN_FM*//*, E_FM_OP_UNMOUNT_DONE, 0, 0, 0, buf, size); +*/ } EAPI void e_volume_unmount(E_Volume *v) { // printf("unmount %s %s\n", v->udi, v->mount_point); - e_hal_device_volume_unmount(_e_dbus_conn, v->udi, NULL, - _e_dbus_cb_vol_unmounted, v); + if (!v || v->guard) return; + + v->guard = ecore_timer_add(E_FM_UNMOUNT_TIMEOUT, _e_dbus_vol_unmount_timeout, v); + v->op = e_hal_device_volume_unmount(_e_dbus_conn, v->udi, NULL, + _e_dbus_cb_vol_unmounted, v); +} + +static int +_e_dbus_vol_eject_timeout(void *data) +{ + E_Volume *v = data; + DBusError error; + char *buf; + int size; + + v->guard = NULL; + dbus_pending_call_cancel(v->op); + error.name = "org.enlightenment.fm2.EjectTimeout"; + error.message = "Unable to eject the media with specified time-out."; + size = _e_dbus_format_error_msg(&buf, v, &error); + ecore_ipc_server_send(_e_ipc_server, 6/*E_IPC_DOMAIN_FM*/, E_FM_OP_EJECT_ERROR, + 0, 0, 0, buf, size); + free(buf); + + return 0; +} + +static int +_e_dbus_vb_vol_ejecting_after_unmount(void *data) +{ + E_Volume *v = data; + + v->guard = ecore_timer_add(E_FM_EJECT_TIMEOUT, _e_dbus_vol_eject_timeout, v); + v->op = e_hal_device_volume_eject(_e_dbus_conn, v->udi, NULL, + _e_dbus_cb_vol_ejected, v); + + return 0; +} + +static void +_e_dbus_cb_vol_unmounted_before_eject(void *user_data, void *method_return, DBusError *error) +{ + E_Volume *v = user_data; + char err; + + err = dbus_error_is_set(error) ? 1 : 0; + _e_dbus_cb_vol_unmounted(user_data, method_return, error); + + // delay is required for all message handlers were executed after unmount + if (!err) + ecore_timer_add(1.0, _e_dbus_vb_vol_ejecting_after_unmount, v); +} + +static void +_e_dbus_cb_vol_ejected(void *user_data, void *method_return, DBusError *error) +{ + E_Volume *v = user_data; + char *buf; + int size; + + if (v->guard) + { + ecore_timer_del(v->guard); + v->guard = NULL; + } + + if (dbus_error_is_set(error)) + { + size = _e_dbus_format_error_msg(&buf, v, error); + ecore_ipc_server_send(_e_ipc_server, 6/*E_IPC_DOMAIN_FM*/, E_FM_OP_EJECT_ERROR, + 0, 0, 0, buf, size); + dbus_error_free(error); + free(buf); + return; + } + + size = strlen(v->udi) + 1; + buf = alloca(size); + strcpy(buf, v->udi); + ecore_ipc_server_send(_e_ipc_server, + 6/*E_IPC_DOMAIN_FM*/, + E_FM_OP_EJECT_DONE, + 0, 0, 0, buf, size); +} + +EAPI void +e_volume_eject(E_Volume *v) +{ + if (!v || v->guard) return; + + if (v->mounted) + { + v->guard = ecore_timer_add(E_FM_UNMOUNT_TIMEOUT, _e_dbus_vol_unmount_timeout, v); + v->op = e_hal_device_volume_unmount(_e_dbus_conn, v->udi, NULL, + _e_dbus_cb_vol_unmounted_before_eject, v); + } + else + { + v->guard = ecore_timer_add(E_FM_EJECT_TIMEOUT, _e_dbus_vol_eject_timeout, v); + v->op = e_hal_device_volume_eject(_e_dbus_conn, v->udi, NULL, + _e_dbus_cb_vol_ejected, v); + } } /* local subsystem functions */ @@ -1376,6 +1594,17 @@ _e_ipc_cb_server_data(void *data, int type, void *event) } } break; + case E_FM_OP_EJECT:/* eject udi */ + { + E_Volume *v; + const char *udi; + + udi = e->data; + v = e_volume_find(udi); + if (v) + e_volume_eject(v); + } + break; case E_FM_OP_QUIT: /* quit */ ecore_main_loop_quit(); break; diff --git a/src/bin/e_fm_op.h b/src/bin/e_fm_op.h index f7f8d9746..08af888e0 100644 --- a/src/bin/e_fm_op.h +++ b/src/bin/e_fm_op.h @@ -47,7 +47,12 @@ typedef enum _E_Fm_Op_Type E_FM_OP_SYMLINK, E_FM_OP_OK, E_FM_OP_ERROR_RETRY_ABORT, - E_FM_OP_REORDER + E_FM_OP_REORDER, + E_FM_OP_MOUNT_ERROR, + E_FM_OP_UNMOUNT_ERROR, + E_FM_OP_EJECT, + E_FM_OP_EJECT_DONE, + E_FM_OP_EJECT_ERROR } E_Fm_Op_Type; #else diff --git a/src/bin/e_fm_shared.h b/src/bin/e_fm_shared.h index 849cb5093..4c5e9b094 100644 --- a/src/bin/e_fm_shared.h +++ b/src/bin/e_fm_shared.h @@ -58,6 +58,11 @@ struct _E_Volume Eina_List *mounts; unsigned char validated; + + char auto_unmount; // unmount, when last associated fm window closed + char first_time; // volume discovery in init sequence + Ecore_Timer *guard; // operation guard timer + DBusPendingCall *op; // d-bus call handle }; struct _E_Fm2_Mount @@ -65,7 +70,6 @@ struct _E_Fm2_Mount const char *udi; const char *mount_point; - Ecore_Timer *timeout; void (*mount_ok) (void *data); void (*mount_fail) (void *data); void (*unmount_ok) (void *data); @@ -161,6 +165,7 @@ _e_volume_edd_new(void) DAT("mounted", mounted, EET_T_CHAR); DAT("mount_point", mount_point, EET_T_STRING); DAT("parent", parent, EET_T_STRING); + DAT("first_time", first_time, EET_T_CHAR); #undef DAT return edd; } diff --git a/src/modules/fileman/e_mod_config.c b/src/modules/fileman/e_mod_config.c index 330a7ab99..f68a0cb29 100644 --- a/src/modules/fileman/e_mod_config.c +++ b/src/modules/fileman/e_mod_config.c @@ -65,6 +65,8 @@ struct _E_Config_Dialog_Data struct { int desktop; + int auto_mount; + int auto_open; } hal; E_Config_Dialog *cfd; @@ -124,6 +126,8 @@ _fill_data(E_Config_Dialog_Data *cfdata) cfdata->list.sort.dirs.first = fileman_config->list.sort.dirs.first; cfdata->list.sort.case_sen = !(fileman_config->list.sort.no_case); cfdata->hal.desktop = e_config->hal_desktop; + cfdata->hal.auto_mount = e_config->hal_auto_mount; + cfdata->hal.auto_open = e_config->hal_auto_open; } static void @@ -159,7 +163,10 @@ _basic_apply(E_Config_Dialog *cfd, E_Config_Dialog_Data *cfdata) e_fm2_hal_show_desktop_icons(); else e_fm2_hal_hide_desktop_icons(); - + + e_config->hal_auto_mount = cfdata->hal.auto_mount; + e_config->hal_auto_open = cfdata->hal.auto_open; + e_config_save_queue(); /* FIXME: reload/refresh existing fm's */ @@ -184,7 +191,9 @@ _basic_check_changed(E_Config_Dialog *cfd, E_Config_Dialog_Data *cfdata) (fileman_config->list.sort.dirs.first != cfdata->list.sort.dirs.first) || (fileman_config->list.sort.dirs.last != !(cfdata->list.sort.dirs.first)) || (fileman_config->list.sort.no_case != !(cfdata->list.sort.case_sen)) || - (e_config->hal_desktop != cfdata->hal.desktop)); + (e_config->hal_desktop != cfdata->hal.desktop) || + (e_config->hal_auto_mount != cfdata->hal.auto_mount) || + (e_config->hal_auto_open != cfdata->hal.auto_open)); } static Evas_Object * @@ -254,12 +263,22 @@ _basic_create(E_Config_Dialog *cfd, Evas *evas, E_Config_Dialog_Data *cfdata) ob = e_widget_check_add(evas, _("Show Toolbar"), &(cfdata->view.show_toolbar)); e_widget_list_object_append(o, ob, 1, 1, 0.5); - ob = e_widget_check_add(evas, _("Show HAL icons on desktop"), - &(cfdata->hal.desktop)); - e_widget_list_object_append(o, ob, 1, 1, 0.5); e_widget_toolbook_page_append(otb, NULL, _("Behavior"), o, 0, 0, 0, 0, 0.5, 0.0); + o = e_widget_list_add(evas, 2, 0); + ob = e_widget_check_add(evas, _("Show HAL icons on desktop"), + &(cfdata->hal.desktop)); + e_widget_list_object_append(o, ob, 1, 1, 0.5); + ob = e_widget_check_add(evas, _("Mount volumes on insert"), + &(cfdata->hal.auto_mount)); + e_widget_list_object_append(o, ob, 1, 1, 0.5); + ob = e_widget_check_add(evas, _("Open filemanager on mount"), + &(cfdata->hal.auto_open)); + e_widget_list_object_append(o, ob, 1, 1, 0.5); + + e_widget_toolbook_page_append(otb, NULL, _("HAL"), o, 0, 0, 0, 0, 0.5, 0.0); + e_widget_toolbook_page_show(otb, 0); return otb; } diff --git a/src/modules/fileman/e_mod_main.c b/src/modules/fileman/e_mod_main.c index 6d69e3cc8..588c01ac1 100644 --- a/src/modules/fileman/e_mod_main.c +++ b/src/modules/fileman/e_mod_main.c @@ -215,21 +215,6 @@ _e_mod_action_fileman_cb(E_Object *obj, const char *params) //~ ecore_idle_enterer_add(_e_mod_fileman_defer_cb, m->zone); //~ } -static void -_mount_ok(void *data) -{ - E_Volume *vol = data; - e_fwin_new(e_container_current_get(e_manager_current_get()), - NULL, vol->mount_point); -} - -static void -_mount_fail(void *data) -{ - //TODO make a better dialog - e_util_dialog_internal(_("Mount error"), _("Mount of device failed")); -} - static void _e_mod_menu_gtk_cb(void *data, E_Menu *m, E_Menu_Item *mi) { @@ -253,8 +238,13 @@ _e_mod_menu_volume_cb(void *data, E_Menu *m, E_Menu_Item *mi) if (m->zone) e_fwin_new(m->zone->container, NULL, vol->mount_point); } - else //TODO need to remove the mount? - e_fm2_hal_mount(vol, _mount_ok, _mount_fail, NULL, NULL, vol); + else + { + char buf[PATH_MAX]; + snprintf(buf, sizeof(buf), "removable:%s", vol->udi); + e_fwin_new(e_container_current_get(e_manager_current_get()), + buf, "/"); + } } static void