1 #include "e.h"
2 #include "e_fm_device.h"
3 #include "e_fm_op.h"
4
5 #define OVERCLIP 128
6 #define ICON_BOTTOM_SPACE 100
7
8 /* in order to check files (ie: extensions) use simpler and faster
9 * strcasecmp version that instead of checking case for each
10 * character, check just the first and if it's upper, assume
11 * everything is uppercase, otherwise assume everything is lowercase.
12 */
13 //#define E_FM2_SIMPLE_STRCASE_FILES 1
14
15 /* FIXME: this is NOT complete. in icon view dnd needs to be much better about placement of icons and
16 * being able to save/load icon placement. it doesn't support custom frames or icons yet
17 */
18
19 #define EFM_SMART_CHECK(args ...) \
20 E_Fm2_Smart_Data * sd; \
21 \
22 if (evas_object_smart_smart_get(obj) != _e_fm2_smart) SMARTERRNR() args; \
23 sd = evas_object_smart_data_get(obj); \
24 if ((!sd) || (e_util_strcmp(evas_object_type_get(obj), "e_fm"))) \
25 return args
26
27 typedef enum _E_Fm2_Action_Type
28 {
29 FILE_ADD,
30 FILE_DEL,
31 FILE_CHANGE
32 } E_Fm2_Action_Type;
33
34 typedef struct _E_Fm2_Smart_Data E_Fm2_Smart_Data;
35 typedef struct _E_Fm2_Region E_Fm2_Region;
36 typedef struct _E_Fm2_Finfo E_Fm2_Finfo;
37 typedef struct _E_Fm2_Action E_Fm2_Action;
38 typedef struct _E_Fm2_Client E_Fm2_Client;
39 typedef struct _E_Fm2_Uri E_Fm2_Uri;
40 typedef struct _E_Fm2_Context_Menu_Data E_Fm2_Context_Menu_Data;
41
42 struct _E_Fm2_Smart_Data
43 {
44 int id;
45 Evas_Coord x, y, w, h, pw, ph;
46 Eina_List *icons;
47 Evas_Object *obj;
48 Evas_Object *clip;
49 Evas_Object *underlay;
50 unsigned int overlay_count;
51 Evas_Object *overlay;
52 Evas_Object *overlay_clip;
53 Evas_Object *drop;
54 Evas_Object *drop_in;
55 Evas_Object *sel_rect;
56 const char *dev;
57 const char *path;
58 const char *realpath;
59
60 struct
61 {
62 Evas_Coord w, h;
63 } max, pmax, min; /* min is actually the size of the largest icon, updated each placement */
64 struct
65 {
66 Evas_Coord x, y;
67 } pos;
68 struct
69 {
70 Eina_List *list;
71 int member_max;
72 } regions;
73 struct
74 {
75 struct
76 {
77 E_Fm_Cb func;
78 void *data;
79 } start, end, replace;
80 E_Fm2_Menu_Flags flags;
81 } icon_menu;
82
83 struct
84 {
85 Ecore_Thread *thread;
86 const char *filename;
87 Eina_Bool done E_BITFIELD;
88 } new_file;
89
90 E_Fm2_Icon *last_selected;
91 E_Fm2_Icon *range_selected;
92 E_Fm2_Icon *range_select_anchor;
93 Eina_List *selected_icons;
94 Eina_List *icons_place;
95 Eina_List *queue;
96 Ecore_Timer *scan_timer;
97 Ecore_Idler *sort_idler;
98 Ecore_Job *scroll_job;
99 Ecore_Job *resize_job;
100 Ecore_Job *refresh_job;
101 E_Menu *menu;
102 Eina_List *rename_dialogs;
103 E_Entry_Dialog *entry_dialog;
104 E_Dialog *image_dialog;
105 Eina_Bool iconlist_changed E_BITFIELD;
106 Eina_Bool order_file E_BITFIELD;
107 Eina_Bool typebuf_visible E_BITFIELD;
108 Eina_Bool show_hidden_files E_BITFIELD;
109 Eina_Bool listing E_BITFIELD;
110 Eina_Bool inherited_dir_props E_BITFIELD;
111 signed char view_mode; /* -1 = unset */
112 signed short icon_size; /* -1 = unset */
113 E_Fm2_View_Flags view_flags;
114
115 E_Fm2_Icon *last_placed;
116 E_Fm2_Config *config;
117 const char *custom_theme;
118 const char *custom_theme_content;
119
120 struct
121 {
122 Evas_Object *obj, *obj2;
123 Eina_List *last_insert;
124 Eina_List **list_index;
125 int iter;
126 } tmp;
127
128 struct
129 {
130 Eina_List *actions;
131 Ecore_Idler *idler;
132 Ecore_Timer *timer;
133 Eina_Bool deletions E_BITFIELD;
134 } live;
135
136 struct
137 {
138 char *buf;
139 const char *start;
140 Ecore_Timer *timer;
141 unsigned int wildcard;
142 Eina_Bool setting E_BITFIELD;
143 Eina_Bool disabled E_BITFIELD;
144 } typebuf;
145
146 int busy_count;
147
148 E_Object *eobj;
149 Evas_Object *win;
150 E_Drop_Handler *drop_handler;
151 E_Fm2_Icon *drop_icon;
152 Ecore_Animator *dnd_scroller;
153 Evas_Point dnd_current;
154 Eina_List *mount_ops;
155 E_Fm2_Mount *mount;
156 signed char drop_after;
157 Eina_Bool drop_show E_BITFIELD;
158 Eina_Bool drop_in_show E_BITFIELD;
159 Eina_Bool drop_all E_BITFIELD;
160 Eina_Bool drag E_BITFIELD;
161 Eina_Bool selecting E_BITFIELD;
162 Eina_Bool toomany E_BITFIELD;
163 struct
164 {
165 int ox, oy;
166 int x, y, w, h;
167 } selrect;
168
169 E_Fm2_Icon *iop_icon;
170
171 Eina_List *handlers;
172 Efreet_Desktop *desktop;
173 };
174
175 struct _E_Fm2_Region
176 {
177 E_Fm2_Smart_Data *sd;
178 Evas_Coord x, y, w, h;
179 Eina_List *list;
180 Eina_Bool realized E_BITFIELD;
181 };
182
183 struct _E_Fm2_Icon
184 {
185 int saved_x, saved_y;
186 double selected_time;
187 E_Fm2_Smart_Data *sd;
188 E_Fm2_Region *region;
189 Evas_Coord x, y, w, h, min_w, min_h;
190 Evas_Object *obj, *obj_icon;
191 E_Menu *menu;
192 E_Entry_Dialog *entry_dialog;
193 Evas_Object *entry_widget;
194 E_Client_Hook *focus_hook;
195 Eio_File *eio;
196 Ecore_X_Window keygrab;
197 E_Config_Dialog *prop_dialog;
198 E_Dialog *dialog;
199
200 E_Fm2_Icon_Info info;
201 E_Fm2_Mount *mount; // for dnd into unmounted dirs
202 Ecore_Timer *mount_timer; // autounmount in 15s
203
204 struct
205 {
206 Evas_Coord x, y;
207 Ecore_Timer *dnd_end_timer; //we need this for XDirectSave drops so we don't lose the icon
208 Eina_Bool start E_BITFIELD;
209 Eina_Bool dnd E_BITFIELD; // currently dragging
210 Eina_Bool src E_BITFIELD; // drag source
211 Eina_Bool hidden E_BITFIELD; // dropped into different dir
212 } drag;
213
214 int saved_rel;
215
216 Eina_Bool realized E_BITFIELD;
217 Eina_Bool selected E_BITFIELD;
218 Eina_Bool last_selected E_BITFIELD;
219 Eina_Bool saved_pos E_BITFIELD;
220 Eina_Bool odd E_BITFIELD;
221 Eina_Bool down_sel E_BITFIELD;
222 Eina_Bool removable_state_change E_BITFIELD;
223 Eina_Bool thumb_failed E_BITFIELD;
224 Eina_Bool queued E_BITFIELD;
225 Eina_Bool inserted E_BITFIELD;
226 };
227
228 struct _E_Fm2_Finfo
229 {
230 struct stat st;
231 int broken_link;
232 const char *lnk;
233 const char *rlnk;
234 };
235
236 struct _E_Fm2_Action
237 {
238 E_Fm2_Action_Type type;
239 const char *file;
240 const char *file2;
241 int flags;
242 E_Fm2_Finfo finf;
243 };
244
245 struct _E_Fm2_Client
246 {
247 Ecore_Ipc_Client *cl;
248 int req;
249 };
250
251 struct _E_Fm2_Uri
252 {
253 const char *hostname;
254 const char *path;
255 };
256
257 struct _E_Fm2_Context_Menu_Data
258 {
259 E_Fm2_Icon *icon;
260 E_Fm2_Smart_Data *sd;
261 E_Fm2_Mime_Handler *handler;
262 };
263 static Eina_Bool _e_fm2_cb_drag_finished_show(E_Fm2_Icon *ic);
264 static const char *_e_fm2_dev_path_map(E_Fm2_Smart_Data *sd, const char *dev, const char *path);
265 static void _e_fm2_file_add(Evas_Object *obj, const char *file, int unique, Eina_Stringshare *file_rel, int after, E_Fm2_Finfo *finf);
266 static void _e_fm2_file_del(Evas_Object *obj, const char *file);
267 static void _e_fm2_queue_process(Evas_Object *obj);
268 static void _e_fm2_queue_free(Evas_Object *obj);
269 static void _e_fm2_regions_free(Evas_Object *obj);
270 static void _e_fm2_regions_populate(Evas_Object *obj);
271 static void _e_fm2_icons_place(Evas_Object *obj);
272 static void _e_fm2_icons_free(Evas_Object *obj);
273 static void _e_fm2_regions_eval(Evas_Object *obj);
274 static void _e_fm2_config_free(E_Fm2_Config *cfg);
275
276 static void _e_fm2_dir_load_props(E_Fm2_Smart_Data *sd);
277 static void _e_fm2_dir_save_props(E_Fm2_Smart_Data *sd);
278
279 static Eina_List *_e_fm2_file_fm2_find(const char *file);
280 static E_Fm2_Icon *_e_fm2_icon_find(Evas_Object *obj, const char *file);
281 static const char *_e_fm2_uri_escape(const char *path);
282 static Eina_List *_e_fm2_uri_selected_icon_list_get(Eina_List *uri);
283
284 static E_Fm2_Icon *_e_fm2_icon_new(E_Fm2_Smart_Data *sd, const char *file, E_Fm2_Finfo *finf);
285 static void _e_fm2_icon_unfill(E_Fm2_Icon *ic);
286 static int _e_fm2_icon_fill(E_Fm2_Icon *ic, E_Fm2_Finfo *finf);
287 static void _e_fm2_icon_free(E_Fm2_Icon *ic);
288 static void _e_fm2_icon_realize(E_Fm2_Icon *ic);
289 static void _e_fm2_icon_unrealize(E_Fm2_Icon *ic);
290 static Eina_Bool _e_fm2_icon_visible(const E_Fm2_Icon *ic);
291 static void _e_fm2_icon_label_set(E_Fm2_Icon *ic, Evas_Object *obj);
292 static Evas_Object *_e_fm2_icon_icon_direct_set(E_Fm2_Icon *ic, Evas_Object *o, Evas_Smart_Cb gen_func, void *data, int force_gen);
293 static void _e_fm2_icon_icon_set(E_Fm2_Icon *ic);
294 static void _e_fm2_icon_thumb(const E_Fm2_Icon *ic, Evas_Object *oic, int force);
295 static void _e_fm2_icon_select(E_Fm2_Icon *ic);
296 static void _e_fm2_icon_deselect(E_Fm2_Icon *ic);
297 static int _e_fm2_icon_desktop_load(E_Fm2_Icon *ic);
298
299 static E_Fm2_Region *_e_fm2_region_new(E_Fm2_Smart_Data *sd);
300 static void _e_fm2_region_free(E_Fm2_Region *rg);
301 static void _e_fm2_region_realize(E_Fm2_Region *rg);
302 static void _e_fm2_region_unrealize(E_Fm2_Region *rg);
303 static int _e_fm2_region_visible(E_Fm2_Region *rg);
304
305 static void _e_fm2_icon_make_visible(E_Fm2_Icon *ic);
306 static void _e_fm2_icon_desel_any(Evas_Object *obj);
307 static E_Fm2_Icon *_e_fm2_icon_first_selected_find(Evas_Object *obj);
308 static E_Fm2_Icon *_e_fm2_icon_next_find(Evas_Object *obj, int next, int (*match_func)(E_Fm2_Icon *ic, void *data), void *data);
309
310 static void _e_fm2_icon_sel_any(Evas_Object *obj);
311 static void _e_fm2_icon_sel_first(Evas_Object *obj, Eina_Bool add);
312 static void _e_fm2_icon_sel_last(Evas_Object *obj, Eina_Bool add);
313 static void _e_fm2_icon_sel_prev(Evas_Object *obj, Eina_Bool add);
314 static void _e_fm2_icon_sel_next(Evas_Object *obj, Eina_Bool add);
315 static void _e_fm2_icon_sel_down(Evas_Object *obj, Eina_Bool add);
316 static void _e_fm2_icon_sel_up(Evas_Object *obj, Eina_Bool add);
317 static void _e_fm2_icon_range_select(E_Fm2_Icon *ic);
318
319 static void _e_fm2_typebuf_show(Evas_Object *obj);
320 static void _e_fm2_typebuf_hide(Evas_Object *obj);
321 //static void _e_fm2_typebuf_history_prev(Evas_Object *obj);
322 //static void _e_fm2_typebuf_history_next(Evas_Object *obj);
323 static void _e_fm2_typebuf_run(Evas_Object *obj);
324 static E_Fm2_Icon *_e_fm2_typebuf_match(Evas_Object *obj, int next);
325 static void _e_fm2_typebuf_complete(Evas_Object *obj);
326 static void _e_fm2_typebuf_char_append(Evas_Object *obj, const char *ch);
327 static void _e_fm2_typebuf_char_backspace(Evas_Object *obj);
328
329 static void _e_fm2_cb_dnd_enter(void *data, const char *type, void *event);
330 static void _e_fm2_cb_dnd_move(void *data, const char *type, void *event);
331 static void _e_fm2_cb_dnd_leave(void *data, const char *type, void *event);
332 static void _e_fm2_cb_dnd_selection_notify(void *data, const char *type, void *event);
333 static void _e_fm2_cb_icon_mouse_down(void *data, Evas *e, Evas_Object *obj, void *event_info);
334 static void _e_fm2_cb_icon_mouse_up(void *data, Evas *e, Evas_Object *obj, void *event_info);
335 static void _e_fm2_cb_icon_mouse_move(void *data, Evas *e, Evas_Object *obj, void *event_info);
336 static void _e_fm2_cb_icon_mouse_in(void *data, Evas *e, Evas_Object *obj, void *event_info);
337 static void _e_fm2_cb_icon_mouse_out(void *data, Evas *e, Evas_Object *obj, void *event_info);
338 static void _e_fm2_cb_icon_thumb_dnd_gen(void *data, Evas_Object *obj, void *event_info);
339 static void _e_fm2_cb_icon_thumb_gen(void *data, Evas_Object *obj, void *event_info);
340 static void _e_fm2_cb_key_down(void *data, Evas *e, Evas_Object *obj, void *event_info);
341 static void _e_fm2_cb_mouse_down(void *data, Evas *e, Evas_Object *obj, void *event_info);
342 static void _e_fm2_cb_mouse_up(void *data, Evas *e, Evas_Object *obj, void *event_info);
343 static void _e_fm2_cb_mouse_move(void *data, Evas *e, Evas_Object *obj, void *event_info);
344 static void _e_fm2_cb_scroll_job(void *data);
345 static void _e_fm2_cb_resize_job(void *data);
346 static int _e_fm2_cb_icon_sort(const void *data1, const void *data2);
347 static Eina_Bool _e_fm2_cb_scan_timer(void *data);
348 static Eina_Bool _e_fm2_cb_sort_idler(void *data);
349 static Eina_Bool _e_fm2_cb_theme(void *data, int type EINA_UNUSED, void *event EINA_UNUSED);
350
351 static void _e_fm2_obj_icons_place(E_Fm2_Smart_Data *sd);
352
353 static void _e_fm2_smart_add(Evas_Object *object);
354 static void _e_fm2_smart_del(Evas_Object *object);
355 static void _e_fm2_smart_move(Evas_Object *object, Evas_Coord x, Evas_Coord y);
356 static void _e_fm2_smart_resize(Evas_Object *object, Evas_Coord w, Evas_Coord h);
357 static void _e_fm2_smart_show(Evas_Object *object);
358 static void _e_fm2_smart_hide(Evas_Object *object);
359 static void _e_fm2_smart_color_set(Evas_Object *obj, int r, int g, int b, int a);
360 static void _e_fm2_smart_clip_set(Evas_Object *obj, Evas_Object *clip);
361 static void _e_fm2_smart_clip_unset(Evas_Object *obj);
362
363 static void _e_fm2_menu(Evas_Object *obj, unsigned int timestamp);
364 static void _e_fm2_menu_post_cb(void *data, E_Menu *m);
365 static void _e_fm2_icon_menu(E_Fm2_Icon *ic, Evas_Object *obj, unsigned int timestamp);
366 static void _e_fm2_icon_menu_post_cb(void *data, E_Menu *m);
367 static void _e_fm2_icon_menu_item_cb(void *data, E_Menu *m, E_Menu_Item *mi);
368 static void _e_fm2_icon_view_menu_pre(void *data, E_Menu *m);
369 static void _e_fm2_options_menu_pre(void *data, E_Menu *m);
370 static void _e_fm2_add_menu_pre(void *data, E_Menu *m);
371 static void _e_fm2_toggle_inherit_dir_props(void *data, E_Menu *m, E_Menu_Item *mi);
372 static void _e_fm2_view_menu_pre(void *data, E_Menu *m);
373 static void _e_fm2_view_menu_grid_icons_cb(void *data, E_Menu *m, E_Menu_Item *mi);
374 static void _e_fm2_view_menu_custom_icons_cb(void *data, E_Menu *m, E_Menu_Item *mi);
375 static void _e_fm2_view_menu_list_cb(void *data, E_Menu *m, E_Menu_Item *mi);
376 static void _e_fm2_view_menu_use_default_cb(void *data, E_Menu *m, E_Menu_Item *mi);
377 static void _e_fm2_view_menu_set_background_cb(void *data, E_Menu *m, E_Menu_Item *mi);
378 static void _e_fm2_view_menu_set_overlay_cb(void *data, E_Menu *m, E_Menu_Item *mi);
379 static void _e_fm2_view_image_sel(E_Fm2_Smart_Data *sd, const char *title, void (*ok_cb)(void *data, E_Dialog *dia));
380 static void _e_fm2_view_image_sel_close(void *data, E_Dialog *dia);
381 static void _e_fm2_refresh(void *data, E_Menu *m, E_Menu_Item *mi);
382 static void _e_fm2_toggle_hidden_files(void *data, E_Menu *m, E_Menu_Item *mi);
383 static void _e_fm2_toggle_single_click(void *data, E_Menu *m, E_Menu_Item *mi);
384 static void _e_fm2_toggle_secure_rm(void *data, E_Menu *m, E_Menu_Item *mi);
385 static void _e_fm2_toggle_ordering(void *data, E_Menu *m, E_Menu_Item *mi);
386 static void _e_fm2_sort(void *data, E_Menu *m, E_Menu_Item *mi);
387 static void _e_fm2_new_directory(void *data, E_Menu *m, E_Menu_Item *mi);
388 static void _e_fm2_file_rename(void *data, E_Menu *m, E_Menu_Item *mi);
389 static void _e_fm2_file_rename_delete_cb(void *obj);
390 static void _e_fm2_file_rename_yes_cb(void *data, char *text);
391 static void _e_fm2_file_rename_no_cb(void *data);
392 static void _e_fm2_file_application_properties(void *data, E_Menu *m EINA_UNUSED, E_Menu_Item *mi EINA_UNUSED);
393 static void _e_fm2_file_properties(void *data, E_Menu *m, E_Menu_Item *mi);
394 static void _e_fm2_file_properties_delete_cb(void *obj);
395 static int _e_fm2_file_do_rename(const char *text, E_Fm2_Icon *ic);
396
397 static Evas_Object *_e_fm2_icon_entry_widget_add(E_Fm2_Icon *ic);
398 static void _e_fm2_icon_entry_widget_del(E_Fm2_Icon *ic);
399 static void _e_fm2_icon_entry_widget_cb_key_down(void *data, Evas *e, Evas_Object *obj, void *event_info);
400 static void _e_fm2_icon_entry_widget_accept(E_Fm2_Icon *ic);
401
402 static E_Dialog *_e_fm_retry_abort_dialog(int pid, const char *str);
403 static void _e_fm_retry_abort_retry_cb(void *data, E_Dialog *dialog);
404 static void _e_fm_retry_abort_abort_cb(void *data, E_Dialog *dialog);
405
406 static E_Dialog *_e_fm_overwrite_dialog(int pid, const char *str);
407 static void _e_fm_overwrite_no_cb(void *data, E_Dialog *dialog);
408 static void _e_fm_overwrite_no_all_cb(void *data, E_Dialog *dialog);
409 static void _e_fm_overwrite_rename(void *data, E_Dialog *dialog);
410 static void _e_fm_overwrite_yes_cb(void *data, E_Dialog *dialog);
411 static void _e_fm_overwrite_yes_all_cb(void *data, E_Dialog *dialog);
412
413 static E_Dialog *_e_fm_error_dialog(int pid, const char *str);
414 static void _e_fm_error_retry_cb(void *data, E_Dialog *dialog);
415 static void _e_fm_error_abort_cb(void *data, E_Dialog *dialog);
416 static void _e_fm_error_link_source(void *data, E_Dialog *dialog);
417 static void _e_fm_error_ignore_this_cb(void *data, E_Dialog *dialog);
418 static void _e_fm_error_ignore_all_cb(void *data, E_Dialog *dialog);
419
420 static void _e_fm_device_error_dialog(const char *title, const char *msg, const char *pstr);
421
422 static void _e_fm2_file_delete(Evas_Object *obj);
423 static void _e_fm2_file_delete_menu(void *data, E_Menu *m, E_Menu_Item *mi);
424 static void _e_fm2_file_delete_delete_cb(void *obj);
425 static void _e_fm2_file_delete_yes_cb(void *data, E_Dialog *dialog);
426 static void _e_fm2_file_delete_no_cb(void *data, E_Dialog *dialog);
427 static void _e_fm2_refresh_job_cb(void *data);
428 static void _e_fm_file_buffer_clear(void);
429 static void _e_fm2_file_cut(Evas_Object *obj);
430 static void _e_fm2_file_copy(Evas_Object *obj);
431 static void _e_fm2_file_paste(Evas_Object *obj);
432 static void _e_fm2_file_symlink(Evas_Object *obj);
433 static void _e_fm2_file_cut_menu(void *data, E_Menu *m, E_Menu_Item *mi);
434 static void _e_fm2_file_copy_menu(void *data, E_Menu *m, E_Menu_Item *mi);
435 static void _e_fm2_file_paste_menu(void *data, E_Menu *m, E_Menu_Item *mi);
436 static void _e_fm2_file_symlink_menu(void *data, E_Menu *m, E_Menu_Item *mi);
437
438 static void _e_fm2_live_file_add(Evas_Object *obj, const char *file, const char *file_rel, int after, E_Fm2_Finfo *finf);
439 static void _e_fm2_live_file_del(Evas_Object *obj, const char *file);
440 static void _e_fm2_live_file_changed(Evas_Object *obj, const char *file, E_Fm2_Finfo *finf);
441 static void _e_fm2_live_process_begin(Evas_Object *obj);
442 static void _e_fm2_live_process_end(Evas_Object *obj);
443 static void _e_fm2_live_process(Evas_Object *obj);
444 static Eina_Bool _e_fm2_cb_live_idler(void *data);
445 static Eina_Bool _e_fm2_cb_live_timer(void *data);
446
447 static int _e_fm2_theme_edje_object_set(E_Fm2_Smart_Data *sd, Evas_Object *o, const char *category, const char *group);
448 static int _e_fm2_theme_edje_icon_object_set(E_Fm2_Smart_Data *sd, Evas_Object *o, const char *category, const char *group);
449
450 static void _e_fm2_mouse_2_handler(E_Fm2_Icon *ic, void *evas_event);
451
452 static void _e_fm2_client_spawn(void);
453 static E_Fm2_Client *_e_fm2_client_get(void);
454 static int _e_fm2_client_monitor_add(const char *path);
455 static void _e_fm2_client_monitor_del(int id, const char *path);
456 static int _e_fm_client_file_del(const char *files, Eina_Bool secure, Evas_Object *e_fm);
457 //static int _e_fm2_client_file_trash(const char *path, Evas_Object *e_fm);
458 //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);
459
460 static void _e_fm2_sel_rect_update(void *data);
461 static void _e_fm2_context_menu_append(E_Fm2_Smart_Data *sd, const char *path, const Eina_List *l, E_Menu *mn, E_Fm2_Icon *ic);
462 static int _e_fm2_context_list_sort(const void *data1, const void *data2);
463
464 void _e_fm2_path_parent_set(Evas_Object *obj, const char *path);
465
466 static void _e_fm2_volume_mount(void *data, E_Menu *m, E_Menu_Item *mi);
467 static void _e_fm2_volume_unmount(void *data, E_Menu *m, E_Menu_Item *mi);
468 static void _e_fm2_volume_eject(void *data, E_Menu *m, E_Menu_Item *mi);
469
470 static void _e_fm2_icon_removable_update(E_Fm2_Icon *ic);
471 static void _e_fm2_volume_icon_update(E_Volume *v);
472 static int _e_fm2_desktop_open(E_Fm2_Smart_Data *sd);
473 static void _e_fm2_operation_abort_internal(E_Fm2_Op_Registry_Entry *ere);
474
475 static Eina_Bool _e_fm2_sys_suspend_hibernate(void *, int, void *);
476
477 static void _e_fm2_favorites_thread_cb(void *d, Ecore_Thread *et);
478 static void _e_fm2_thread_cleanup_cb(void *d, Ecore_Thread *et);
479
480 static void _e_fm2_new_file(void *data, E_Menu *m, E_Menu_Item *mi);
481
482 static Ecore_Exe *_e_fm2_exe = NULL;
483 static char *_e_fm2_meta_path = NULL;
484 static Evas_Smart *_e_fm2_smart = NULL;
485 static Eina_List *_e_fm2_list = NULL;
486 static Eina_List *_e_fm2_list_remove = NULL;
487 static int _e_fm2_list_walking = 0;
488 static Eina_List *_e_fm2_client_list = NULL;
489 static Eina_List *_e_fm2_menu_contexts = NULL;
490 static Eina_List *_e_fm_file_buffer = NULL; /* Files for copy&paste are saved here. */
491 static int _e_fm_file_buffer_copying = 0;
492 static const char *_e_fm2_icon_desktop_str = NULL;
493 static const char *_e_fm2_icon_thumb_str = NULL;
494 static const char *_e_fm2_mime_inode_directory = NULL;
495 static const char *_e_fm2_mime_app_desktop = NULL;
496 static const char *_e_fm2_mime_app_edje = NULL;
497 static const char *_e_fm2_mime_text_uri_list = NULL;
498 static const char *_e_fm2_mime_xmozurl = NULL;
499 static const char *_e_fm2_xds = NULL;
500
501 static Eina_List *_e_fm_handlers = NULL;
502
503 static const char **_e_fm2_dnd_types[] =
504 {
505 &_e_fm2_mime_text_uri_list,
506 &_e_fm2_xds,
507 &_e_fm2_mime_xmozurl,
508 NULL
509 };
510
511 static Ecore_Timer *_e_fm2_mime_flush = NULL;
512 static Ecore_Timer *_e_fm2_mime_clear = NULL;
513 static Ecore_Thread *_e_fm2_favorites_thread = NULL;
514
515 /* contains:
516 * _e_volume_edd
517 * _e_storage_edd
518 * _e_volume_free()
519 * _e_storage_free()
520 * _e_volume_edd_new()
521 * _e_storage_edd_new()
522 * _e_storage_volume_edd_init()
523 * _e_storage_volume_edd_shutdown()
524 */
525
526 #include "e_fm_shared_codec.h"
527
528 static inline Eina_Bool
_e_fm2_icon_realpath(const E_Fm2_Icon * ic,char * buf,int buflen)529 _e_fm2_icon_realpath(const E_Fm2_Icon *ic, char *buf, int buflen)
530 {
531 int r = snprintf(buf, buflen, "%s/%s", ic->sd->realpath, ic->info.file);
532 return r < buflen;
533 }
534
535 static inline Eina_Bool
_e_fm2_icon_path(const E_Fm2_Icon * ic,char * buf,int buflen)536 _e_fm2_icon_path(const E_Fm2_Icon *ic, char *buf, int buflen)
537 {
538 int r;
539
540 if (ic->info.real_link)
541 r = snprintf(buf, buflen, "%s", ic->info.real_link);
542 else
543 r = snprintf(buf, buflen, "%s/%s", ic->sd->path, ic->info.file);
544
545 return r < buflen;
546 }
547
548 static inline Eina_Bool
_e_fm2_ext_is_edje(const char * ext)549 _e_fm2_ext_is_edje(const char *ext)
550 {
551 #ifdef E_FM2_SIMPLE_STRCASE_FILES
552 if ((ext[0] == 'e') && (ext[1] == 'd') && (ext[2] == 'j'))
553 return 1;
554 else if ((ext[0] == 'E') && (ext[1] == 'D') && (ext[2] == 'J'))
555 return 1;
556 else
557 return 0;
558 #else
559 return strcasecmp(ext, "edj") == 0;
560 #endif
561 }
562
563 static inline Eina_Bool
_e_fm2_ext_is_desktop(const char * ext)564 _e_fm2_ext_is_desktop(const char *ext)
565 {
566 #ifdef E_FM2_SIMPLE_STRCASE_FILES
567 if ((ext[0] == 'd') &&
568 ((strcmp(ext + 1, "esktop") == 0) ||
569 (strcmp(ext + 1, "irectory") == 0)))
570 return 1;
571 else if ((ext[0] == 'D') &&
572 ((strcmp(ext + 1, "ESKTOP") == 0) ||
573 (strcmp(ext + 1, "IRECTORY") == 0)))
574 return 1;
575 else
576 return 0;
577 #else
578 if ((ext[0] != 'd') && (ext[0] != 'D'))
579 return 0;
580
581 ext++;
582 return (strcasecmp(ext, "esktop") == 0) ||
583 (strcasecmp(ext, "irectory") == 0);
584 #endif
585 }
586
587 static inline Eina_Bool
_e_fm2_ext_is_imc(const char * ext)588 _e_fm2_ext_is_imc(const char *ext)
589 {
590 #ifdef E_FM2_SIMPLE_STRCASE_FILES
591 if ((ext[0] == 'i') && (ext[1] == 'm') && (ext[2] == 'c'))
592 return 1;
593 else if ((ext[0] == 'I') && (ext[1] == 'M') && (ext[2] == 'C'))
594 return 1;
595 else
596 return 0;
597 #else
598 return strcasecmp(ext, "imc") == 0;
599 #endif
600 }
601
602 static inline Eina_Bool
_e_fm2_file_is_edje(const char * file)603 _e_fm2_file_is_edje(const char *file)
604 {
605 const char *p = strrchr(file, '.');
606 return (p) && (_e_fm2_ext_is_edje(p + 1));
607 }
608
609 static inline Eina_Bool
_e_fm2_file_is_desktop(const char * file)610 _e_fm2_file_is_desktop(const char *file)
611 {
612 const char *p = strrchr(file, '.');
613 return (p) && (_e_fm2_ext_is_desktop(p + 1));
614 }
615
616 static inline Eina_Bool
_e_fm2_toomany_get(const E_Fm2_Smart_Data * sd)617 _e_fm2_toomany_get(const E_Fm2_Smart_Data *sd)
618 {
619 char mode;
620
621 mode = sd->config->view.mode;
622 if (sd->view_mode > -1) mode = sd->view_mode;
623 if (((mode >= E_FM2_VIEW_MODE_CUSTOM_ICONS) &&
624 (mode <= E_FM2_VIEW_MODE_CUSTOM_SMART_GRID_ICONS)) &&
625 (eina_list_count(sd->icons) >= 500))
626 return EINA_TRUE;
627 return EINA_FALSE;
628 }
629
630 static inline char
_e_fm2_view_mode_get(const E_Fm2_Smart_Data * sd)631 _e_fm2_view_mode_get(const E_Fm2_Smart_Data *sd)
632 {
633 char mode;
634
635 mode = sd->config->view.mode;
636 if (sd->view_mode > -1) mode = sd->view_mode;
637 if ((sd->toomany) &&
638 ((mode >= E_FM2_VIEW_MODE_CUSTOM_ICONS) &&
639 (mode <= E_FM2_VIEW_MODE_CUSTOM_SMART_GRID_ICONS)))
640 return E_FM2_VIEW_MODE_GRID_ICONS;
641 return mode;
642 }
643
644 static inline Evas_Coord
_e_fm2_icon_w_get(const E_Fm2_Smart_Data * sd)645 _e_fm2_icon_w_get(const E_Fm2_Smart_Data *sd)
646 {
647 if (sd->icon_size > -1)
648 return sd->icon_size * e_scale;
649 if (sd->config->icon.icon.w)
650 return sd->config->icon.icon.w;
651 return sd->config->icon.list.w;
652 }
653
654 static inline Evas_Coord
_e_fm2_icon_h_get(const E_Fm2_Smart_Data * sd)655 _e_fm2_icon_h_get(const E_Fm2_Smart_Data *sd)
656 {
657 if (sd->icon_size > -1)
658 return sd->icon_size * e_scale;
659 if (sd->config->icon.icon.h)
660 return sd->config->icon.icon.h;
661 return sd->config->icon.list.h;
662 }
663
664 static inline unsigned int
_e_fm2_icon_mime_size_normalize(const E_Fm2_Icon * ic)665 _e_fm2_icon_mime_size_normalize(const E_Fm2_Icon *ic)
666 {
667 return e_util_icon_size_normalize(_e_fm2_icon_w_get(ic->sd));
668 }
669
670 static Eina_Bool
_e_fm2_mime_flush_cb(void * data EINA_UNUSED)671 _e_fm2_mime_flush_cb(void *data EINA_UNUSED)
672 {
673 efreet_mime_type_cache_flush();
674 return ECORE_CALLBACK_RENEW;
675 }
676
677 static Eina_Bool
_e_fm2_mime_clear_cb(void * data EINA_UNUSED)678 _e_fm2_mime_clear_cb(void *data EINA_UNUSED)
679 {
680 efreet_mime_type_cache_clear();
681 return ECORE_CALLBACK_RENEW;
682 }
683
684 static void
_e_fm2_op_registry_go_on(int id)685 _e_fm2_op_registry_go_on(int id)
686 {
687 E_Fm2_Op_Registry_Entry *ere = e_fm2_op_registry_entry_get(id);
688 if (!ere) return;
689 ere->status = E_FM2_OP_STATUS_IN_PROGRESS;
690 ere->needs_attention = 0;
691 ere->dialog = NULL;
692 e_fm2_op_registry_entry_changed(ere);
693 }
694
695 static void
_e_fm2_op_registry_aborted(int id)696 _e_fm2_op_registry_aborted(int id)
697 {
698 E_Fm2_Op_Registry_Entry *ere = e_fm2_op_registry_entry_get(id);
699 if (!ere) return;
700 ere->status = E_FM2_OP_STATUS_ABORTED;
701 ere->needs_attention = 0;
702 ere->dialog = NULL;
703 ere->finished = 1;
704 e_fm2_op_registry_entry_changed(ere);
705 // XXX e_fm2_op_registry_entry_del(id);
706 }
707
708 static void
_e_fm2_op_registry_error(int id,E_Dialog * dlg)709 _e_fm2_op_registry_error(int id, E_Dialog *dlg)
710 {
711 E_Fm2_Op_Registry_Entry *ere = e_fm2_op_registry_entry_get(id);
712 if (!ere) return;
713 ere->status = E_FM2_OP_STATUS_ERROR;
714 ere->needs_attention = 1;
715 ere->dialog = dlg;
716 e_fm2_op_registry_entry_changed(ere);
717 }
718
719 static void
_e_fm2_op_registry_needs_attention(int id,E_Dialog * dlg)720 _e_fm2_op_registry_needs_attention(int id, E_Dialog *dlg)
721 {
722 E_Fm2_Op_Registry_Entry *ere = e_fm2_op_registry_entry_get(id);
723 if (!ere) return;
724 ere->needs_attention = 1;
725 ere->dialog = dlg;
726 e_fm2_op_registry_entry_changed(ere);
727 }
728
729 /////////////// DBG:
730 static void
_e_fm2_op_registry_entry_print(const E_Fm2_Op_Registry_Entry * ere)731 _e_fm2_op_registry_entry_print(const E_Fm2_Op_Registry_Entry *ere)
732 {
733 const char *status_strings[] =
734 {
735 "UNKNOWN", "IN_PROGRESS", "SUCCESSFUL", "ABORTED", "ERROR"
736 };
737 const char *status;
738
739 if (ere->status <= E_FM2_OP_STATUS_ERROR)
740 status = status_strings[ere->status];
741 else
742 status = status_strings[0];
743
744 DBG("id: %8d, op: %2d [%s] finished: %hhu, needs_attention: %hhu\n"
745 " %3d%% (%" PRIi64 "/%" PRIi64 "), start_time: %10.0f, eta: %5ds, xwin: %#x\n"
746 " src=[%s]\n"
747 " dst=[%s]",
748 ere->id, ere->op, status, ere->finished, ere->needs_attention,
749 ere->percent, ere->done, ere->total, ere->start_time, ere->eta,
750 e_fm2_op_registry_entry_xwin_get(ere),
751 ere->src, ere->dst);
752 }
753
754 static Eina_Bool
_e_fm2_exe_del(void * data EINA_UNUSED,int type EINA_UNUSED,void * event)755 _e_fm2_exe_del(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
756 {
757 Ecore_Exe_Event_Del *ev = event;
758 if (ev->exe == _e_fm2_exe) _e_fm2_exe = NULL;
759 return ECORE_CALLBACK_RENEW;
760 }
761
762 static Eina_Bool
_e_fm2_op_registry_entry_add_cb(void * data EINA_UNUSED,int type EINA_UNUSED,void * event)763 _e_fm2_op_registry_entry_add_cb(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
764 {
765 const E_Fm2_Op_Registry_Entry *ere = event;
766 DBG("E FM OPERATION STARTED: id=%d, op=%d", ere->id, ere->op);
767 return ECORE_CALLBACK_RENEW;
768 }
769
770 static Eina_Bool
_e_fm2_op_registry_entry_del_cb(void * data EINA_UNUSED,int type EINA_UNUSED,void * event)771 _e_fm2_op_registry_entry_del_cb(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
772 {
773 const E_Fm2_Op_Registry_Entry *ere = event;
774 puts("E FM OPERATION FINISHED:");
775 _e_fm2_op_registry_entry_print(ere);
776 puts("---");
777 return ECORE_CALLBACK_RENEW;
778 }
779
780 static Eina_Bool
_e_fm2_op_registry_entry_changed_cb(void * data EINA_UNUSED,int type EINA_UNUSED,void * event)781 _e_fm2_op_registry_entry_changed_cb(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
782 {
783 const E_Fm2_Op_Registry_Entry *ere = event;
784 puts("E FM OPERATION CHANGED:");
785 _e_fm2_op_registry_entry_print(ere);
786 puts("---");
787 return ECORE_CALLBACK_RENEW;
788 }
789
790 /////////////// DBG:
791
792 /***/
793
794 EINTERN int
e_fm2_init(void)795 e_fm2_init(void)
796 {
797 char path[PATH_MAX];
798
799 eina_init();
800 ecore_init();
801 _e_storage_volume_edd_init();
802 e_user_dir_concat_static(path, "fileman/metadata");
803 ecore_file_mkpath(path);
804 _e_fm2_meta_path = strdup(path);
805
806 {
807 static const Evas_Smart_Class sc =
808 {
809 "e_fm",
810 EVAS_SMART_CLASS_VERSION,
811 _e_fm2_smart_add, /* add */
812 _e_fm2_smart_del, /* del */
813 _e_fm2_smart_move, /* move */
814 _e_fm2_smart_resize, /* resize */
815 _e_fm2_smart_show, /* show */
816 _e_fm2_smart_hide, /* hide */
817 _e_fm2_smart_color_set, /* color_set */
818 _e_fm2_smart_clip_set, /* clip_set */
819 _e_fm2_smart_clip_unset, /* clip_unset */
820 NULL,
821 NULL,
822 NULL,
823 NULL,
824 NULL,
825 NULL,
826 NULL
827 };
828 _e_fm2_smart = evas_smart_class_new(&sc);
829 }
830 // _e_fm2_client_spawn();
831 e_fm2_custom_file_init();
832 e_fm2_op_registry_init();
833 efreet_mime_init();
834
835 /* XXX: move this to a central/global place? */
836 _e_fm2_mime_flush = ecore_timer_loop_add(60.0, _e_fm2_mime_flush_cb, NULL);
837 _e_fm2_mime_clear = ecore_timer_loop_add(600.0, _e_fm2_mime_clear_cb, NULL);
838
839 _e_fm2_icon_desktop_str = eina_stringshare_add("DESKTOP");
840 _e_fm2_icon_thumb_str = eina_stringshare_add("THUMB");
841 _e_fm2_mime_inode_directory = eina_stringshare_add("inode/directory");
842 _e_fm2_mime_app_desktop = eina_stringshare_add("application/x-desktop");
843 _e_fm2_mime_app_edje = eina_stringshare_add("application/x-extension-edj");
844 _e_fm2_mime_text_uri_list = eina_stringshare_add("text/uri-list");
845 _e_fm2_xds = eina_stringshare_add("XdndDirectSave0");
846 _e_fm2_mime_xmozurl = eina_stringshare_add("text/x-moz-url");
847
848 _e_fm2_favorites_thread = ecore_thread_run(_e_fm2_favorites_thread_cb,
849 _e_fm2_thread_cleanup_cb,
850 _e_fm2_thread_cleanup_cb, NULL);
851
852 E_LIST_HANDLER_APPEND(_e_fm_handlers, ECORE_EXE_EVENT_DEL, _e_fm2_exe_del, NULL);
853 /// DBG
854 E_LIST_HANDLER_APPEND(_e_fm_handlers, E_EVENT_FM_OP_REGISTRY_ADD, _e_fm2_op_registry_entry_add_cb, NULL);
855 E_LIST_HANDLER_APPEND(_e_fm_handlers, E_EVENT_FM_OP_REGISTRY_DEL, _e_fm2_op_registry_entry_del_cb, NULL);
856 E_LIST_HANDLER_APPEND(_e_fm_handlers, E_EVENT_FM_OP_REGISTRY_CHANGED, _e_fm2_op_registry_entry_changed_cb, NULL);
857 /// DBG
858 E_LIST_HANDLER_APPEND(_e_fm_handlers, E_EVENT_SYS_HIBERNATE, _e_fm2_sys_suspend_hibernate, NULL);
859 E_LIST_HANDLER_APPEND(_e_fm_handlers, E_EVENT_SYS_RESUME, _e_fm2_sys_suspend_hibernate, NULL);
860
861 return 1;
862 }
863
864 EINTERN int
e_fm2_shutdown(void)865 e_fm2_shutdown(void)
866 {
867 e_fm2_die();
868
869 E_FREE_LIST(_e_fm2_list, evas_object_del);
870
871 eina_stringshare_replace(&_e_fm2_icon_desktop_str, NULL);
872 eina_stringshare_replace(&_e_fm2_icon_thumb_str, NULL);
873 eina_stringshare_replace(&_e_fm2_mime_inode_directory, NULL);
874 eina_stringshare_replace(&_e_fm2_mime_app_desktop, NULL);
875 eina_stringshare_replace(&_e_fm2_mime_app_edje, NULL);
876 eina_stringshare_replace(&_e_fm2_mime_text_uri_list, NULL);
877 eina_stringshare_replace(&_e_fm2_xds, NULL);
878 eina_stringshare_replace(&_e_fm2_mime_xmozurl, NULL);
879
880 E_FREE_LIST(_e_fm_handlers, ecore_event_handler_del);
881
882 ecore_timer_del(_e_fm2_mime_flush);
883 _e_fm2_mime_flush = NULL;
884 ecore_timer_del(_e_fm2_mime_clear);
885 _e_fm2_mime_clear = NULL;
886
887 if (_e_fm2_favorites_thread) ecore_thread_cancel(_e_fm2_favorites_thread);
888 _e_fm2_favorites_thread = NULL;
889
890 evas_smart_free(_e_fm2_smart);
891 _e_fm2_smart = NULL;
892 E_FREE(_e_fm2_meta_path);
893 e_fm2_custom_file_shutdown();
894 _e_storage_volume_edd_shutdown();
895 e_fm2_op_registry_shutdown();
896 efreet_mime_shutdown();
897 ecore_shutdown();
898 eina_shutdown();
899 return 1;
900 }
901
902 E_API void
e_fm2_die(void)903 e_fm2_die(void)
904 {
905 if (_e_fm2_exe)
906 {
907 ecore_exe_kill(_e_fm2_exe);
908 ecore_exe_free(_e_fm2_exe);
909 _e_fm2_exe = NULL;
910 }
911 }
912
913 E_API Evas_Object *
e_fm2_add(Evas * evas)914 e_fm2_add(Evas *evas)
915 {
916 return evas_object_smart_add(evas, _e_fm2_smart);
917 }
918
919 static Eina_Bool
_e_fm2_cb_dnd_drop(void * data,const char * type)920 _e_fm2_cb_dnd_drop(void *data, const char *type)
921 {
922 E_Fm2_Smart_Data *sd = data;
923 Eina_Bool allow;
924 char buf[PATH_MAX];
925
926 if (sd->config->view.link_drop && (type == _e_fm2_xds))
927 allow = EINA_FALSE;
928 else
929 {
930 if (sd->drop_icon)
931 {
932 snprintf(buf, sizeof(buf), "%s/%s", sd->realpath, sd->drop_icon->info.file);
933 allow = ecore_file_can_write(buf);
934 }
935 else
936 allow = (sd->realpath && ecore_file_can_write(sd->realpath));
937 }
938
939 e_drop_xds_update(allow, sd->drop_icon ? buf : sd->realpath);
940 if (sd->dnd_scroller) ecore_animator_del(sd->dnd_scroller);
941 sd->dnd_scroller = NULL;
942 sd->dnd_current.x = sd->dnd_current.y = 0;
943 return allow;
944 }
945
946 static void
_e_fm2_cb_mount_ok(void * data)947 _e_fm2_cb_mount_ok(void *data)
948 {
949 E_Fm2_Smart_Data *sd;
950
951 sd = evas_object_smart_data_get(data);
952 if (!sd) return; // safety
953
954 if (sd->mount->volume->efm_mode != EFM_MODE_USING_HAL_MOUNT)
955 {
956 /* Clean up typebuf. */
957 _e_fm2_typebuf_hide(data);
958 /* we only just now have the mount point so we should do stuff we couldn't do before */
959 eina_stringshare_replace(&sd->realpath, sd->mount->volume->mount_point);
960 eina_stringshare_replace(&sd->mount->mount_point, sd->mount->volume->mount_point);
961 _e_fm2_dir_load_props(sd);
962 }
963
964 if ((sd->realpath) && (strcmp(sd->mount->mount_point, sd->realpath)))
965 {
966 e_fm2_path_set(sd->obj, "/", sd->mount->mount_point);
967 }
968 else
969 {
970 sd->id = _e_fm2_client_monitor_add(sd->mount->mount_point);
971 sd->listing = EINA_TRUE;
972 evas_object_smart_callback_call(data, "dir_changed", NULL);
973 sd->tmp.iter = EINA_FALSE;
974 }
975 }
976
977 static void
_e_fm2_cb_mount_fail(void * data)978 _e_fm2_cb_mount_fail(void *data)
979 {
980 E_Fm2_Smart_Data *sd;
981
982 sd = evas_object_smart_data_get(data);
983 if (!sd) return; // safety
984 if (sd->mount)
985 {
986 // At this moment E_Fm2_Mount object already deleted in e_fm_device.c
987 sd->mount = NULL;
988 if (sd->config->view.open_dirs_in_place)
989 e_fm2_path_set(data, "favorites", "/");
990 else
991 evas_object_smart_callback_call(data, "dir_deleted", NULL);
992 }
993 }
994
995 static void
_e_fm2_cb_unmount_ok(void * data)996 _e_fm2_cb_unmount_ok(void *data)
997 {
998 E_Fm2_Smart_Data *sd;
999
1000 sd = evas_object_smart_data_get(data);
1001 if (!sd) return;
1002 if (sd->mount)
1003 {
1004 sd->mount = NULL;
1005 if (sd->config->view.open_dirs_in_place && sd->realpath)
1006 _e_fm2_path_parent_set(data, sd->realpath);
1007 else
1008 evas_object_smart_callback_call(data, "dir_deleted", NULL);
1009 }
1010 }
1011
1012 void
_e_fm2_path_parent_set(Evas_Object * obj,const char * path)1013 _e_fm2_path_parent_set(Evas_Object *obj, const char *path)
1014 {
1015 char buf[PATH_MAX], *p;
1016 int idx;
1017
1018 p = strrchr(path, '/');
1019 if (!p || (p == path))
1020 e_fm2_path_set(obj, "/", "/");
1021 else
1022 {
1023 idx = p - path;
1024 if (idx < PATH_MAX)
1025 {
1026 strncpy(buf, path, idx);
1027 buf[idx] = '\0';
1028 e_fm2_path_set(obj, "/", buf);
1029 }
1030 else
1031 e_fm2_path_set(obj, "/", "/");
1032 }
1033 }
1034
1035 static void
_e_fm2_favorites_thread_cb(void * d EINA_UNUSED,Ecore_Thread * et EINA_UNUSED)1036 _e_fm2_favorites_thread_cb(void *d EINA_UNUSED, Ecore_Thread *et EINA_UNUSED)
1037 {
1038 e_fm2_favorites_init();
1039 }
1040
1041 static void
_e_fm2_thread_cleanup_cb(void * d EINA_UNUSED,Ecore_Thread * et EINA_UNUSED)1042 _e_fm2_thread_cleanup_cb(void *d EINA_UNUSED, Ecore_Thread *et EINA_UNUSED)
1043 {
1044 _e_fm2_favorites_thread = NULL;
1045 }
1046
1047 E_API void
e_fm2_path_set(Evas_Object * obj,const char * dev,const char * path)1048 e_fm2_path_set(Evas_Object *obj, const char *dev, const char *path)
1049 {
1050 const char *real_path;
1051 EFM_SMART_CHECK();
1052
1053 /* internal config for now - don't see a point making this configurable */
1054 sd->regions.member_max = 64;
1055
1056 if (!sd->config)
1057 {
1058 sd->config = E_NEW(E_Fm2_Config, 1);
1059 if (!sd->config) return;
1060 // sd->config->view.mode = E_FM2_VIEW_MODE_ICONS;
1061 sd->config->view.mode = E_FM2_VIEW_MODE_LIST;
1062 sd->config->view.open_dirs_in_place = EINA_TRUE;
1063 sd->config->view.selector = EINA_TRUE;
1064 sd->config->view.single_click = e_config->filemanager_single_click;
1065 sd->config->view.single_click_delay = EINA_FALSE;
1066 sd->config->view.no_subdir_jump = EINA_FALSE;
1067 sd->config->icon.max_thumb_size = 5;
1068 sd->config->icon.icon.w = 128;
1069 sd->config->icon.icon.h = 128;
1070 sd->config->icon.list.w = 24;
1071 sd->config->icon.list.h = 24;
1072 sd->config->icon.fixed.w = EINA_TRUE;
1073 sd->config->icon.fixed.h = EINA_TRUE;
1074 sd->config->icon.extension.show = EINA_FALSE;
1075 sd->config->list.sort.no_case = EINA_TRUE;
1076 sd->config->list.sort.dirs.first = EINA_TRUE;
1077 sd->config->list.sort.dirs.last = EINA_FALSE;
1078 sd->config->selection.single = EINA_FALSE;
1079 sd->config->selection.windows_modifiers = EINA_FALSE;
1080 sd->config->theme.background = NULL;
1081 sd->config->theme.frame = NULL;
1082 sd->config->theme.icons = NULL;
1083 sd->config->theme.fixed = EINA_FALSE;
1084 }
1085
1086 real_path = _e_fm2_dev_path_map(sd, dev, path);
1087
1088 /* If the path doesn't exist, popup a dialog */
1089 if (dev && strncmp(dev, "removable:", 10)
1090 && !ecore_file_exists(real_path))
1091 {
1092 E_Dialog *dialog;
1093 char text[4096 + 256];
1094
1095 dialog = e_dialog_new(NULL, "E", "_fm_file_unexisting_path_dialog");
1096 e_dialog_button_add(dialog, _("Close"), NULL, NULL, dialog);
1097 e_dialog_button_focus_num(dialog, 0);
1098 e_dialog_title_set(dialog, _("Nonexistent path"));
1099 e_dialog_icon_set(dialog, "dialog-error", 64);
1100
1101 snprintf(text, sizeof(text), _("%s doesn't exist."), real_path);
1102
1103 e_dialog_text_set(dialog, text);
1104 elm_win_center(dialog->win, 1, 1);
1105 e_dialog_show(dialog);
1106 return;
1107 }
1108 if (real_path && (sd->realpath == real_path)) return;
1109
1110 E_FREE_FUNC(sd->scan_timer, ecore_timer_del);
1111 E_FREE_FUNC(sd->sort_idler, ecore_idler_del);
1112 if (sd->busy_count)
1113 sd->busy_count--;
1114 if (sd->busy_count == 0)
1115 {
1116 edje_object_signal_emit(sd->overlay, "e,state,busy,stop", "e");
1117 e_fm2_custom_file_flush();
1118 }
1119 if (sd->realpath) _e_fm2_client_monitor_del(sd->id, sd->realpath);
1120 sd->listing = EINA_FALSE;
1121 if (sd->new_file.thread) ecore_thread_cancel(sd->new_file.thread);
1122 sd->new_file.thread = NULL;
1123 eina_stringshare_replace(&sd->new_file.filename, NULL);
1124 eina_stringshare_replace(&sd->dev, dev);
1125 eina_stringshare_replace(&sd->path, path);
1126 eina_stringshare_del(sd->realpath);
1127 sd->realpath = real_path;
1128 _e_fm2_queue_free(obj);
1129 _e_fm2_regions_free(obj);
1130 _e_fm2_icons_free(obj);
1131 sd->overlay_count = 0;
1132 edje_object_part_text_set(sd->overlay, "e.text.busy_label", "");
1133
1134 _e_fm2_dir_load_props(sd);
1135
1136 /* If the path change from a mountpoint to something else, we fake-unmount */
1137 if (sd->mount && sd->mount->mount_point && real_path
1138 && strncmp(sd->mount->mount_point, sd->realpath,
1139 strlen(sd->mount->mount_point)))
1140 {
1141 e_fm2_device_unmount(sd->mount);
1142 sd->mount = NULL;
1143 }
1144
1145 /* Clean up typebuf. */
1146 _e_fm2_typebuf_hide(obj);
1147
1148 /* If the path is of type removable: we add a new mountpoint */
1149 if (sd->dev && !sd->mount && !strncmp(sd->dev, "removable:", 10))
1150 {
1151 E_Volume *v = NULL;
1152
1153 v = e_fm2_device_volume_find(sd->dev + sizeof("removable:") - 1);
1154 if (v)
1155 {
1156 sd->mount = e_fm2_device_mount(v, _e_fm2_cb_mount_ok, _e_fm2_cb_mount_fail,
1157 _e_fm2_cb_unmount_ok, NULL, obj);
1158 if ((v->efm_mode == EFM_MODE_USING_HAL_MOUNT) && (!sd->mount->mounted)) return;
1159 }
1160 }
1161 else if (sd->config->view.open_dirs_in_place == 0)
1162 {
1163 E_Fm2_Mount *m;
1164 m = e_fm2_device_mount_find(sd->realpath);
1165 if (m)
1166 {
1167 sd->mount = e_fm2_device_mount(m->volume,
1168 _e_fm2_cb_mount_ok, _e_fm2_cb_mount_fail,
1169 _e_fm2_cb_unmount_ok, NULL, obj);
1170 if ((m->volume->efm_mode != EFM_MODE_USING_HAL_MOUNT) && (!sd->mount->mounted)) return;
1171 }
1172 }
1173 if (!sd->realpath) return;
1174
1175 if (!sd->mount || sd->mount->mounted)
1176 {
1177 if (sd->dev && (!strcmp(sd->dev, "favorites")) && (!_e_fm2_favorites_thread))
1178 _e_fm2_favorites_thread = ecore_thread_run(_e_fm2_favorites_thread_cb,
1179 _e_fm2_thread_cleanup_cb,
1180 _e_fm2_thread_cleanup_cb, NULL);
1181 sd->id = _e_fm2_client_monitor_add(sd->realpath);
1182 sd->listing = EINA_TRUE;
1183 }
1184
1185 evas_object_smart_callback_call(obj, "dir_changed", NULL);
1186 sd->tmp.iter = EINA_FALSE;
1187 }
1188
1189 E_API void
e_fm2_underlay_show(Evas_Object * obj)1190 e_fm2_underlay_show(Evas_Object *obj)
1191 {
1192 EFM_SMART_CHECK();
1193 evas_object_show(sd->underlay);
1194 }
1195
1196 E_API void
e_fm2_underlay_hide(Evas_Object * obj)1197 e_fm2_underlay_hide(Evas_Object *obj)
1198 {
1199 EFM_SMART_CHECK();
1200 evas_object_hide(sd->underlay);
1201 }
1202
1203 E_API void
e_fm2_all_unsel(Evas_Object * obj)1204 e_fm2_all_unsel(Evas_Object *obj)
1205 {
1206 EFM_SMART_CHECK();
1207 _e_fm2_icon_desel_any(obj);
1208 }
1209
1210 E_API void
e_fm2_all_sel(Evas_Object * obj)1211 e_fm2_all_sel(Evas_Object *obj)
1212 {
1213 EFM_SMART_CHECK();
1214 _e_fm2_icon_sel_any(obj);
1215 }
1216
1217 E_API void
e_fm2_first_sel(Evas_Object * obj)1218 e_fm2_first_sel(Evas_Object *obj)
1219 {
1220 EFM_SMART_CHECK();
1221 _e_fm2_icon_sel_first(obj, EINA_FALSE);
1222 }
1223
1224 E_API void
e_fm2_last_sel(Evas_Object * obj)1225 e_fm2_last_sel(Evas_Object *obj)
1226 {
1227 EFM_SMART_CHECK();
1228 _e_fm2_icon_sel_last(obj, EINA_FALSE);
1229 }
1230
1231 E_API void
e_fm2_custom_theme_set(Evas_Object * obj,const char * path)1232 e_fm2_custom_theme_set(Evas_Object *obj, const char *path)
1233 {
1234 EFM_SMART_CHECK();
1235 eina_stringshare_replace(&sd->custom_theme, path);
1236 _e_fm2_theme_edje_object_set(sd, sd->drop, "base/theme/fileman",
1237 "list/drop_between");
1238 _e_fm2_theme_edje_object_set(sd, sd->drop_in, "base/theme/fileman",
1239 "list/drop_in");
1240 _e_fm2_theme_edje_object_set(sd, sd->overlay, "base/theme/fileman",
1241 "overlay");
1242 _e_fm2_theme_edje_object_set(sd, sd->sel_rect, "base/theme/fileman",
1243 "rubberband");
1244 }
1245
1246 E_API void
e_fm2_custom_theme_content_set(Evas_Object * obj,const char * content)1247 e_fm2_custom_theme_content_set(Evas_Object *obj, const char *content)
1248 {
1249 EFM_SMART_CHECK();
1250 eina_stringshare_replace(&sd->custom_theme_content, content);
1251 _e_fm2_theme_edje_object_set(sd, sd->drop, "base/theme/fileman",
1252 "list/drop_between");
1253 _e_fm2_theme_edje_object_set(sd, sd->drop_in, "base/theme/fileman",
1254 "list/drop_in");
1255 _e_fm2_theme_edje_object_set(sd, sd->overlay, "base/theme/fileman",
1256 "overlay");
1257 }
1258
1259 E_API void
e_fm2_path_get(Evas_Object * obj,const char ** dev,const char ** path)1260 e_fm2_path_get(Evas_Object *obj, const char **dev, const char **path)
1261 {
1262 if (dev) *dev = NULL;
1263 if (path) *path = NULL;
1264 EFM_SMART_CHECK();
1265 if (dev) *dev = sd->dev;
1266 if (path) *path = sd->path;
1267 }
1268
1269 static E_Fm2_Custom_File *
_e_fm2_dir_load_props_from_parent(const char * path)1270 _e_fm2_dir_load_props_from_parent(const char *path)
1271 {
1272 E_Fm2_Custom_File *cf;
1273 char *parent;
1274
1275 if ((!path) || (path[0] == '\0') || (strcmp(path, "/") == 0))
1276 return NULL;
1277
1278 parent = ecore_file_dir_get(path);
1279 cf = e_fm2_custom_file_get(parent);
1280 if (((cf) && (cf->dir) && (cf->dir->prop.in_use)) || (!strcmp(parent, path)))
1281 {
1282 free(parent);
1283 return cf;
1284 }
1285
1286 cf = _e_fm2_dir_load_props_from_parent(parent);
1287 free(parent);
1288 return cf;
1289 }
1290
1291 static void
_e_fm2_dir_load_props(E_Fm2_Smart_Data * sd)1292 _e_fm2_dir_load_props(E_Fm2_Smart_Data *sd)
1293 {
1294 E_Fm2_Custom_File *cf;
1295
1296 if (!sd->realpath) return; /* come back later */
1297 if (!(sd->view_flags & E_FM2_VIEW_LOAD_DIR_CUSTOM)) return;
1298
1299 cf = e_fm2_custom_file_get(sd->realpath);
1300 if ((cf) && (cf->dir))
1301 {
1302 Evas_Coord x, y;
1303
1304 if (sd->max.w - sd->w > 0)
1305 x = (sd->max.w - sd->w) * cf->dir->pos.x;
1306 else
1307 x = 0;
1308
1309 if (sd->max.h - sd->h > 0)
1310 y = (sd->max.h - sd->h) * cf->dir->pos.y;
1311 else
1312 y = 0;
1313
1314 e_fm2_pan_set(sd->obj, x, y);
1315
1316 if (cf->dir->prop.in_use)
1317 {
1318 sd->view_mode = cf->dir->prop.view_mode;
1319 sd->icon_size = cf->dir->prop.icon_size;
1320 sd->order_file = !!cf->dir->prop.order_file;
1321 sd->show_hidden_files = !!cf->dir->prop.show_hidden_files;
1322 sd->inherited_dir_props = EINA_FALSE;
1323 sd->config->list.sort.no_case = cf->dir->prop.sort.no_case;
1324 sd->config->list.sort.size = cf->dir->prop.sort.size;
1325 sd->config->list.sort.extension = cf->dir->prop.sort.extension;
1326 sd->config->list.sort.mtime = cf->dir->prop.sort.mtime;
1327 sd->config->list.sort.dirs.first = cf->dir->prop.sort.dirs.first;
1328 sd->config->list.sort.dirs.last = cf->dir->prop.sort.dirs.last;
1329 return;
1330 }
1331 }
1332 else
1333 {
1334 sd->pos.x = 0;
1335 sd->pos.y = 0;
1336 }
1337
1338 if (!(sd->view_flags & E_FM2_VIEW_INHERIT_DIR_CUSTOM))
1339 {
1340 sd->view_mode = -1;
1341 sd->icon_size = -1;
1342 sd->order_file = EINA_FALSE;
1343 sd->show_hidden_files = EINA_FALSE;
1344 sd->inherited_dir_props = EINA_FALSE;
1345 return;
1346 }
1347
1348 sd->inherited_dir_props = EINA_TRUE;
1349
1350 cf = _e_fm2_dir_load_props_from_parent(sd->realpath);
1351 if ((cf) && (cf->dir) && (cf->dir->prop.in_use))
1352 {
1353 sd->view_mode = cf->dir->prop.view_mode;
1354 sd->icon_size = cf->dir->prop.icon_size;
1355 sd->order_file = !!cf->dir->prop.order_file;
1356 sd->show_hidden_files = !!cf->dir->prop.show_hidden_files;
1357 sd->config->list.sort.no_case = cf->dir->prop.sort.no_case;
1358 sd->config->list.sort.size = cf->dir->prop.sort.size;
1359 sd->config->list.sort.extension = cf->dir->prop.sort.extension;
1360 sd->config->list.sort.mtime = cf->dir->prop.sort.mtime;
1361 sd->config->list.sort.dirs.first = cf->dir->prop.sort.dirs.first;
1362 sd->config->list.sort.dirs.last = cf->dir->prop.sort.dirs.last;
1363 }
1364 else
1365 {
1366 sd->view_mode = -1;
1367 sd->icon_size = -1;
1368 sd->order_file = EINA_FALSE;
1369 sd->show_hidden_files = EINA_FALSE;
1370 }
1371 }
1372
1373 static void
_e_fm2_dir_save_props(E_Fm2_Smart_Data * sd)1374 _e_fm2_dir_save_props(E_Fm2_Smart_Data *sd)
1375 {
1376 E_Fm2_Custom_File *cf, cf0;
1377 E_Fm2_Custom_Dir dir0;
1378
1379 if (!(sd->view_flags & E_FM2_VIEW_SAVE_DIR_CUSTOM)) return;
1380
1381 cf = e_fm2_custom_file_get(sd->realpath);
1382 if (!cf)
1383 {
1384 cf = &cf0;
1385 memset(cf, 0, sizeof(*cf));
1386 cf->dir = &dir0;
1387 }
1388 else if (!cf->dir)
1389 {
1390 E_Fm2_Custom_File *cf2 = cf;
1391 cf = &cf0;
1392 memcpy(cf, cf2, sizeof(*cf2));
1393 cf->dir = &dir0;
1394 }
1395
1396 if (sd->max.w - sd->w > 0)
1397 cf->dir->pos.x = sd->pos.x / (double)(sd->max.w - sd->w);
1398 else
1399 cf->dir->pos.x = 0.0;
1400
1401 if (sd->max.h - sd->h)
1402 cf->dir->pos.y = sd->pos.y / (double)(sd->max.h - sd->h);
1403 else
1404 cf->dir->pos.y = 0.0;
1405
1406 cf->dir->prop.icon_size = sd->icon_size;
1407 cf->dir->prop.view_mode = sd->view_mode;
1408 cf->dir->prop.order_file = sd->order_file;
1409 cf->dir->prop.show_hidden_files = sd->show_hidden_files;
1410 cf->dir->prop.in_use = !sd->inherited_dir_props;
1411
1412 if (sd->config)
1413 {
1414 cf->dir->prop.sort.no_case = sd->config->list.sort.no_case;
1415 cf->dir->prop.sort.size = sd->config->list.sort.size;
1416 cf->dir->prop.sort.extension = sd->config->list.sort.extension;
1417 cf->dir->prop.sort.mtime = sd->config->list.sort.mtime;
1418 cf->dir->prop.sort.dirs.first = sd->config->list.sort.dirs.first;
1419 cf->dir->prop.sort.dirs.last = sd->config->list.sort.dirs.last;
1420 }
1421
1422 e_fm2_custom_file_set(sd->realpath, cf);
1423 e_fm2_custom_file_flush();
1424 }
1425
1426 E_API void
e_fm2_refresh(Evas_Object * obj)1427 e_fm2_refresh(Evas_Object *obj)
1428 {
1429 EFM_SMART_CHECK();
1430
1431 evas_object_smart_callback_call(sd->obj, "changed", NULL);
1432
1433 _e_fm2_dir_save_props(sd);
1434
1435 _e_fm2_queue_free(obj);
1436 _e_fm2_regions_free(obj);
1437 _e_fm2_icons_free(obj);
1438
1439 sd->order_file = EINA_FALSE;
1440
1441 if (sd->realpath)
1442 {
1443 sd->listing = EINA_FALSE;
1444 _e_fm2_client_monitor_del(sd->id, sd->realpath);
1445 sd->id = _e_fm2_client_monitor_add(sd->realpath);
1446 sd->listing = EINA_TRUE;
1447 }
1448
1449 sd->tmp.iter = EINA_FALSE;
1450 }
1451
1452 E_API int
e_fm2_has_parent_get(Evas_Object * obj)1453 e_fm2_has_parent_get(Evas_Object *obj)
1454 {
1455 EFM_SMART_CHECK(0);
1456 if (!sd->path) return 0;
1457 if (strcmp(sd->path, "/")) return 1;
1458 if (!sd->realpath) return 0;
1459 if ((sd->realpath[0] == 0) || (!strcmp(sd->realpath, "/"))) return 0;
1460 return 1;
1461 }
1462
1463 E_API const char *
e_fm2_real_path_get(Evas_Object * obj)1464 e_fm2_real_path_get(Evas_Object *obj)
1465 {
1466 EFM_SMART_CHECK(NULL);
1467 return sd->realpath;
1468 }
1469
1470 E_API void
e_fm2_parent_go(Evas_Object * obj)1471 e_fm2_parent_go(Evas_Object *obj)
1472 {
1473 char *p, *path;
1474 char buf[PATH_MAX];
1475 EFM_SMART_CHECK();
1476 if (!sd->path) return;
1477 path = memcpy(buf, sd->path, strlen(sd->path) + 1);
1478 if ((p = strrchr(path, '/'))) *p = 0;
1479 if (*path)
1480 e_fm2_path_set(obj, sd->dev, path);
1481 else if (sd->realpath)
1482 {
1483 path = ecore_file_dir_get(sd->realpath);
1484 e_fm2_path_set(obj, "/", path);
1485 free(path);
1486 }
1487 }
1488
1489 E_API void
e_fm2_config_set(Evas_Object * obj,E_Fm2_Config * cfg)1490 e_fm2_config_set(Evas_Object *obj, E_Fm2_Config *cfg)
1491 {
1492 EFM_SMART_CHECK();
1493 if (sd->config == cfg) return;
1494 if (sd->config) _e_fm2_config_free(sd->config);
1495 sd->config = NULL;
1496 if (!cfg) return;
1497 sd->config = E_NEW(E_Fm2_Config, 1);
1498 if (!sd->config) return;
1499 memcpy(sd->config, cfg, sizeof(E_Fm2_Config));
1500 sd->config->icon.key_hint = eina_stringshare_add(cfg->icon.key_hint);
1501 sd->config->theme.background = eina_stringshare_add(cfg->theme.background);
1502 sd->config->theme.frame = eina_stringshare_add(cfg->theme.frame);
1503 sd->config->theme.icons = eina_stringshare_add(cfg->theme.icons);
1504 }
1505
1506 E_API E_Fm2_Config *
e_fm2_config_get(Evas_Object * obj)1507 e_fm2_config_get(Evas_Object *obj)
1508 {
1509 EFM_SMART_CHECK(NULL);
1510 return sd->config;
1511 }
1512
1513 E_API Eina_List *
e_fm2_selected_list_get(Evas_Object * obj)1514 e_fm2_selected_list_get(Evas_Object *obj)
1515 {
1516 Eina_List *list = NULL, *l;
1517 E_Fm2_Icon *ic;
1518
1519 EFM_SMART_CHECK(NULL);
1520 EINA_LIST_FOREACH(sd->selected_icons, l, ic)
1521 list = eina_list_append(list, &(ic->info));
1522 return list;
1523 }
1524
1525 E_API Eina_List *
e_fm2_all_list_get(Evas_Object * obj)1526 e_fm2_all_list_get(Evas_Object *obj)
1527 {
1528 Eina_List *list = NULL, *l;
1529 E_Fm2_Icon *ic;
1530
1531 EFM_SMART_CHECK(NULL);
1532 EINA_LIST_FOREACH(sd->icons, l, ic)
1533 {
1534 list = eina_list_append(list, &(ic->info));
1535 }
1536 return list;
1537 }
1538
1539 E_API E_Fm2_Icon_Info *
e_fm2_icon_file_get(Evas_Object * obj,const char * file)1540 e_fm2_icon_file_get(Evas_Object *obj, const char *file)
1541 {
1542 Eina_List *l;
1543 E_Fm2_Icon *ic;
1544
1545 EFM_SMART_CHECK(NULL);
1546 if (!file) return NULL;
1547 EINA_LIST_FOREACH(sd->icons, l, ic)
1548 {
1549 if ((ic->info.file) && (!strcmp(ic->info.file, file)))
1550 return &(ic->info);
1551 }
1552 return NULL;
1553 }
1554
1555 E_API void
e_fm2_deselect_all(Evas_Object * obj)1556 e_fm2_deselect_all(Evas_Object *obj)
1557 {
1558 EFM_SMART_CHECK();
1559 _e_fm2_icon_desel_any(obj);
1560 }
1561
1562 E_API void
e_fm2_select_set(Evas_Object * obj,const char * file,int select_)1563 e_fm2_select_set(Evas_Object *obj, const char *file, int select_)
1564 {
1565 Eina_List *l;
1566 E_Fm2_Icon *ic;
1567
1568 EFM_SMART_CHECK();
1569 EINA_LIST_FOREACH(sd->icons, l, ic)
1570 {
1571 if ((file) && (!strcmp(ic->info.file, file)))
1572 {
1573 if (select_) _e_fm2_icon_select(ic);
1574 else _e_fm2_icon_deselect(ic);
1575 }
1576 else
1577 {
1578 if (ic->sd->config->selection.single)
1579 _e_fm2_icon_deselect(ic);
1580 ic->last_selected = EINA_FALSE;
1581 }
1582 }
1583 }
1584
1585 E_API void
e_fm2_file_show(Evas_Object * obj,const char * file)1586 e_fm2_file_show(Evas_Object *obj, const char *file)
1587 {
1588 Eina_List *l;
1589 E_Fm2_Icon *ic;
1590
1591 EFM_SMART_CHECK();
1592 EINA_LIST_FOREACH(sd->icons, l, ic)
1593 {
1594 if (!strcmp(ic->info.file, file))
1595 {
1596 _e_fm2_icon_make_visible(ic);
1597 return;
1598 }
1599 }
1600 }
1601
1602 E_API void
e_fm2_icon_menu_replace_callback_set(Evas_Object * obj,E_Fm_Cb func,void * data)1603 e_fm2_icon_menu_replace_callback_set(Evas_Object *obj, E_Fm_Cb func, void *data)
1604 {
1605 EFM_SMART_CHECK();
1606 sd->icon_menu.replace.func = func;
1607 sd->icon_menu.replace.data = data;
1608 }
1609
1610 E_API void
e_fm2_icon_menu_start_extend_callback_set(Evas_Object * obj,E_Fm_Cb func,void * data)1611 e_fm2_icon_menu_start_extend_callback_set(Evas_Object *obj, E_Fm_Cb func, void *data)
1612 {
1613 EFM_SMART_CHECK();
1614 sd->icon_menu.start.func = func;
1615 sd->icon_menu.start.data = data;
1616 }
1617
1618 E_API void
e_fm2_icon_menu_end_extend_callback_set(Evas_Object * obj,E_Fm_Cb func,void * data)1619 e_fm2_icon_menu_end_extend_callback_set(Evas_Object *obj, E_Fm_Cb func, void *data)
1620 {
1621 EFM_SMART_CHECK();
1622 sd->icon_menu.end.func = func;
1623 sd->icon_menu.end.data = data;
1624 }
1625
1626 E_API void
e_fm2_icon_menu_flags_set(Evas_Object * obj,E_Fm2_Menu_Flags flags)1627 e_fm2_icon_menu_flags_set(Evas_Object *obj, E_Fm2_Menu_Flags flags)
1628 {
1629 EFM_SMART_CHECK();
1630 sd->icon_menu.flags = flags;
1631 }
1632
1633 E_API E_Fm2_Menu_Flags
e_fm2_icon_menu_flags_get(Evas_Object * obj)1634 e_fm2_icon_menu_flags_get(Evas_Object *obj)
1635 {
1636 EFM_SMART_CHECK(0);
1637 return sd->icon_menu.flags;
1638 }
1639
1640 E_API void
e_fm2_view_flags_set(Evas_Object * obj,E_Fm2_View_Flags flags)1641 e_fm2_view_flags_set(Evas_Object *obj, E_Fm2_View_Flags flags)
1642 {
1643 EFM_SMART_CHECK();
1644 sd->view_flags = flags;
1645 }
1646
1647 E_API E_Fm2_View_Flags
e_fm2_view_flags_get(Evas_Object * obj)1648 e_fm2_view_flags_get(Evas_Object *obj)
1649 {
1650 EFM_SMART_CHECK(0);
1651 return sd->view_flags;
1652 }
1653
1654 E_API E_Object *
e_fm2_window_object_get(Evas_Object * obj)1655 e_fm2_window_object_get(Evas_Object *obj)
1656 {
1657 EFM_SMART_CHECK(NULL);
1658 return sd->eobj;
1659 }
1660
1661 E_API void
e_fm2_window_object_set(Evas_Object * obj,E_Object * eobj)1662 e_fm2_window_object_set(Evas_Object *obj, E_Object *eobj)
1663 {
1664 const char *drop[] = {"text/uri-list", "text/x-moz-url", "XdndDirectSave0"};
1665
1666 EFM_SMART_CHECK();
1667 sd->eobj = eobj;
1668 sd->win = NULL;
1669 if (sd->drop_handler) e_drop_handler_del(sd->drop_handler);
1670 sd->drop_handler = e_drop_handler_add(sd->eobj, NULL,
1671 sd,
1672 _e_fm2_cb_dnd_enter,
1673 _e_fm2_cb_dnd_move,
1674 _e_fm2_cb_dnd_leave,
1675 _e_fm2_cb_dnd_selection_notify,
1676 drop, 3,
1677 sd->x, sd->y, sd->w, sd->h);
1678 e_drop_handler_responsive_set(sd->drop_handler);
1679 e_drop_handler_xds_set(sd->drop_handler, _e_fm2_cb_dnd_drop);
1680 }
1681
1682 E_API void
e_fm2_window_set(Evas_Object * obj,Evas_Object * win)1683 e_fm2_window_set(Evas_Object *obj, Evas_Object *win)
1684 {
1685 const char *drop[] = {"text/uri-list", "text/x-moz-url", "XdndDirectSave0"};
1686
1687 EFM_SMART_CHECK();
1688 sd->win = win;
1689 sd->eobj = NULL;
1690 if (sd->drop_handler) e_drop_handler_del(sd->drop_handler);
1691 sd->drop_handler = e_drop_handler_add(NULL, win,
1692 sd,
1693 _e_fm2_cb_dnd_enter,
1694 _e_fm2_cb_dnd_move,
1695 _e_fm2_cb_dnd_leave,
1696 _e_fm2_cb_dnd_selection_notify,
1697 drop, 3,
1698 sd->x, sd->y, sd->w, sd->h);
1699 e_drop_handler_responsive_set(sd->drop_handler);
1700 e_drop_handler_xds_set(sd->drop_handler, _e_fm2_cb_dnd_drop);
1701 }
1702
1703 static void
_e_fm2_icons_update_helper(E_Fm2_Smart_Data * sd,Eina_Bool icon_only)1704 _e_fm2_icons_update_helper(E_Fm2_Smart_Data *sd, Eina_Bool icon_only)
1705 {
1706 Eina_List *l;
1707 E_Fm2_Icon *ic;
1708 char buf[PATH_MAX], *pfile;
1709 int bufused, buffree;
1710
1711 if ((!sd->realpath) || (!sd->icons)) return;
1712 bufused = eina_strlcpy(buf, sd->realpath, sizeof(buf));
1713 if (bufused >= (int)(sizeof(buf) - 2))
1714 return;
1715
1716 if ((bufused > 0) && (buf[bufused - 1] != '/'))
1717 {
1718 buf[bufused] = '/';
1719 bufused++;
1720 }
1721
1722 pfile = buf + bufused;
1723 buffree = sizeof(buf) - bufused;
1724
1725 EINA_LIST_FOREACH(sd->icons, l, ic)
1726 {
1727 E_Fm2_Custom_File *cf;
1728
1729 eina_stringshare_del(ic->info.icon);
1730 ic->info.icon = NULL;
1731 ic->info.icon_type = EINA_FALSE;
1732
1733 if (_e_fm2_file_is_desktop(ic->info.file))
1734 _e_fm2_icon_desktop_load(ic);
1735
1736 if ((int)eina_strlcpy(pfile, ic->info.file, buffree) >= buffree)
1737 continue;
1738
1739 cf = e_fm2_custom_file_get(buf);
1740 if (cf)
1741 {
1742 if (cf->icon.valid)
1743 {
1744 eina_stringshare_replace(&ic->info.icon, cf->icon.icon);
1745 ic->info.icon_type = cf->icon.type;
1746 }
1747 }
1748
1749 if (!ic->realized) continue;
1750 if (icon_only)
1751 {
1752 E_FREE_FUNC(ic->obj_icon, evas_object_del);
1753 _e_fm2_icon_icon_set(ic);
1754 }
1755 else
1756 {
1757 _e_fm2_icon_unrealize(ic);
1758 _e_fm2_icon_realize(ic);
1759 }
1760 }
1761 e_fm2_custom_file_flush();
1762 }
1763
1764 E_API void
e_fm2_icons_update(Evas_Object * obj)1765 e_fm2_icons_update(Evas_Object *obj)
1766 {
1767 EFM_SMART_CHECK();
1768 _e_fm2_icons_update_helper(sd, EINA_FALSE);
1769 }
1770
1771 E_API void
e_fm2_pan_set(Evas_Object * obj,Evas_Coord x,Evas_Coord y)1772 e_fm2_pan_set(Evas_Object *obj, Evas_Coord x, Evas_Coord y)
1773 {
1774 EFM_SMART_CHECK();
1775 x = MIN(x, sd->max.w - sd->w);
1776 if (x < 0) x = 0;
1777 y = MIN(y, sd->max.h - sd->h);
1778 if (y < 0) y = 0;
1779 if ((sd->pos.x == x) && (sd->pos.y == y)) return;
1780 sd->pos.x = x;
1781 sd->pos.y = y;
1782 if (sd->scroll_job) ecore_job_del(sd->scroll_job);
1783 sd->scroll_job = ecore_job_add(_e_fm2_cb_scroll_job, obj);
1784 }
1785
1786 E_API void
e_fm2_pan_get(Evas_Object * obj,Evas_Coord * x,Evas_Coord * y)1787 e_fm2_pan_get(Evas_Object *obj, Evas_Coord *x, Evas_Coord *y)
1788 {
1789 EFM_SMART_CHECK();
1790 if (x) *x = sd->pos.x;
1791 if (y) *y = sd->pos.y;
1792 }
1793
1794 E_API void
e_fm2_pan_max_get(Evas_Object * obj,Evas_Coord * x,Evas_Coord * y)1795 e_fm2_pan_max_get(Evas_Object *obj, Evas_Coord *x, Evas_Coord *y)
1796 {
1797 Evas_Coord mx, my;
1798 EFM_SMART_CHECK();
1799 mx = sd->max.w - sd->w;
1800 if (mx < 0) mx = 0;
1801 my = sd->max.h - sd->h;
1802 if (my < 0) my = 0;
1803 if (x) *x = mx;
1804 if (y) *y = my;
1805 }
1806
1807 E_API void
e_fm2_pan_child_size_get(Evas_Object * obj,Evas_Coord * w,Evas_Coord * h)1808 e_fm2_pan_child_size_get(Evas_Object *obj, Evas_Coord *w, Evas_Coord *h)
1809 {
1810 EFM_SMART_CHECK();
1811 if (w) *w = sd->max.w;
1812 if (h) *h = sd->max.h;
1813 }
1814
1815 E_API void
e_fm2_all_icons_update(void)1816 e_fm2_all_icons_update(void)
1817 {
1818 Evas_Object *o;
1819 const Eina_List *l;
1820
1821 _e_fm2_list_walking++;
1822 EINA_LIST_FOREACH(_e_fm2_list, l, o)
1823 {
1824 if ((_e_fm2_list_walking > 0) &&
1825 (eina_list_data_find(_e_fm2_list_remove, o))) continue;
1826 e_fm2_icons_update(o);
1827 }
1828 _e_fm2_list_walking--;
1829 if (_e_fm2_list_walking == 0)
1830 {
1831 EINA_LIST_FREE(_e_fm2_list_remove, o)
1832 {
1833 _e_fm2_list = eina_list_remove(_e_fm2_list, o);
1834 }
1835 }
1836 }
1837
1838 static const char *
_e_fm2_path_join(char * buf,int buflen,const char * base,const char * component)1839 _e_fm2_path_join(char *buf, int buflen, const char *base, const char *component)
1840 {
1841 if ((!buf) || (!component))
1842 return NULL;
1843
1844 if (component[0] == '/')
1845 return component;
1846 else if (component[0] == '\0')
1847 return base;
1848 else if (component[0] == '.')
1849 {
1850 if (component[1] == '/')
1851 {
1852 component += 2;
1853
1854 if (!base)
1855 return component;
1856
1857 if (snprintf(buf, buflen, "%s/%s", base, component) < buflen)
1858 return buf;
1859 else
1860 return NULL;
1861 }
1862 else if ((component[1] == '.') && (component[2] == '/'))
1863 {
1864 const char *p;
1865 int len;
1866
1867 component += 3;
1868
1869 if (!base)
1870 return component;
1871
1872 p = strrchr(base, '/');
1873 if (!p)
1874 return component;
1875
1876 len = p - base;
1877 if (snprintf(buf, buflen, "%.*s/%s", len, base, component) < buflen)
1878 return buf;
1879 else
1880 return NULL;
1881 }
1882 }
1883
1884 if (snprintf(buf, buflen, "%s/%s", base, component) < buflen)
1885 return buf;
1886 else
1887 return NULL;
1888 }
1889
1890 /**
1891 * Explicitly set an Edje icon from the given icon path.
1892 *
1893 * @param iconpath path to edje file that contains 'icon' group.
1894 *
1895 * @see _e_fm2_icon_explicit_get()
1896 */
1897 static Evas_Object *
_e_fm2_icon_explicit_edje_get(Evas * evas,const E_Fm2_Icon * ic EINA_UNUSED,const char * iconpath,const char ** type_ret)1898 _e_fm2_icon_explicit_edje_get(Evas *evas, const E_Fm2_Icon *ic EINA_UNUSED, const char *iconpath, const char **type_ret)
1899 {
1900 Evas_Object *o = edje_object_add(evas);
1901 if (!o)
1902 return NULL;
1903
1904 if (!edje_object_file_set(o, iconpath, "icon"))
1905 {
1906 evas_object_del(o);
1907 return NULL;
1908 }
1909
1910 if (type_ret) *type_ret = "CUSTOM";
1911 return o;
1912 }
1913
1914 /**
1915 * Explicitly set icon from theme using its name.
1916 *
1917 * @param name will be prefixed by 'e/icons/' to form the group name in theme.
1918 *
1919 * @see e_util_edje_icon_set()
1920 * @see _e_fm2_icon_explicit_get()
1921 */
1922 static Evas_Object *
_e_fm2_icon_explicit_theme_icon_get(Evas * evas,const E_Fm2_Icon * ic EINA_UNUSED,const char * name,const char ** type_ret)1923 _e_fm2_icon_explicit_theme_icon_get(Evas *evas, const E_Fm2_Icon *ic EINA_UNUSED, const char *name, const char **type_ret)
1924 {
1925 Evas_Object *o = e_icon_add(evas);
1926
1927 if (!o) return NULL;
1928
1929 e_icon_scale_size_set(o, _e_fm2_icon_mime_size_normalize(ic));
1930
1931 if (!e_util_icon_theme_set(o, name))
1932 {
1933 evas_object_del(o);
1934 return NULL;
1935 }
1936
1937 if (type_ret) *type_ret = "THEME_ICON";
1938 return o;
1939 }
1940
1941 /**
1942 * Explicitly set icon from file manager theem using its name.
1943 *
1944 * @param name will be prefixed with 'base/theme/fileman' to form the
1945 * group name in theme.
1946 *
1947 * @see _e_fm2_theme_edje_icon_object_set()
1948 * @see _e_fm2_icon_explicit_get()
1949 */
1950 static Evas_Object *
_e_fm2_icon_explicit_theme_get(Evas * evas,const E_Fm2_Icon * ic,const char * name,const char ** type_ret)1951 _e_fm2_icon_explicit_theme_get(Evas *evas, const E_Fm2_Icon *ic, const char *name, const char **type_ret)
1952 {
1953 Evas_Object *o = edje_object_add(evas);
1954 if (!o)
1955 return NULL;
1956
1957 if (!_e_fm2_theme_edje_icon_object_set(ic->sd, o, "base/theme/fileman", name))
1958 {
1959 evas_object_del(o);
1960 return NULL;
1961 }
1962
1963 if (type_ret) *type_ret = "THEME";
1964 return o;
1965 }
1966
1967 /**
1968 * Explicitly set icon to given value.
1969 *
1970 * This will try to identify if icon is an edje or regular file or even
1971 * an icon name to get from icon set.
1972 *
1973 * @param icon might be an absolute or relative path, or icon name or edje path.
1974 */
1975 static Evas_Object *
_e_fm2_icon_explicit_get(Evas * evas,const E_Fm2_Icon * ic,const char * icon,const char ** type_ret)1976 _e_fm2_icon_explicit_get(Evas *evas, const E_Fm2_Icon *ic, const char *icon, const char **type_ret)
1977 {
1978 char buf[PATH_MAX];
1979 const char *iconpath;
1980
1981 iconpath = _e_fm2_path_join(buf, sizeof(buf), ic->sd->realpath, icon);
1982 if (!iconpath)
1983 {
1984 ERR("could not create icon \"%s\".", icon);
1985 return NULL;
1986 }
1987
1988 if (_e_fm2_file_is_edje(iconpath))
1989 return _e_fm2_icon_explicit_edje_get(evas, ic, iconpath, type_ret);
1990 else
1991 {
1992 Evas_Object *o = e_icon_add(evas);
1993 if (!o)
1994 return NULL;
1995
1996 e_icon_scale_size_set(o, _e_fm2_icon_mime_size_normalize(ic));
1997 e_icon_file_set(o, iconpath);
1998 e_icon_fill_inside_set(o, 1);
1999 if (type_ret) *type_ret = "CUSTOM";
2000 return o;
2001 }
2002
2003 return NULL;
2004 }
2005
2006 /**
2007 * Creates an icon that generates a thumbnail if required.
2008 *
2009 * @param group if given, will be used in e_thumb_icon_file_set()
2010 * @param cb function to callback when thumbnail generation is over.
2011 * @param data extra data to give to @p cb
2012 * @param force_gen whenever to force generation of thumbnails, even it exists.
2013 */
2014 static Evas_Object *
_e_fm2_icon_thumb_get(Evas * evas,const E_Fm2_Icon * ic,const char * group,Evas_Smart_Cb cb,void * data,int force_gen,const char ** type_ret)2015 _e_fm2_icon_thumb_get(Evas *evas, const E_Fm2_Icon *ic, const char *group, Evas_Smart_Cb cb, void *data, int force_gen, const char **type_ret)
2016 {
2017 Evas_Object *o;
2018 char buf[PATH_MAX];
2019
2020 if (ic->thumb_failed)
2021 return NULL;
2022
2023 if (!_e_fm2_icon_realpath(ic, buf, sizeof(buf)))
2024 return NULL;
2025
2026 o = e_thumb_icon_add(evas);
2027 if (!o)
2028 return NULL;
2029
2030 if (cb) evas_object_smart_callback_add(o, "e_thumb_gen", cb, data);
2031 e_thumb_icon_size_set(o, 256, 256);
2032 e_thumb_icon_file_set(o, buf, group);
2033 _e_fm2_icon_thumb(ic, o, force_gen);
2034 if (type_ret) *type_ret = "THUMB";
2035 return o;
2036 }
2037
2038 /**
2039 * Generates the thumbnail of the given edje file.
2040 *
2041 * It will use 'icon.key_hint' from config if set and then try some well
2042 * known groups like 'icon', 'e/desktop/background' and 'e/init/splash'.
2043 */
2044 static Evas_Object *
_e_fm2_icon_thumb_edje_get(Evas * evas,const E_Fm2_Icon * ic,Evas_Smart_Cb cb,void * data,int force_gen,const char ** type_ret)2045 _e_fm2_icon_thumb_edje_get(Evas *evas, const E_Fm2_Icon *ic, Evas_Smart_Cb cb, void *data, int force_gen, const char **type_ret)
2046 {
2047 char buf[PATH_MAX];
2048 const char **itr = NULL, *group = NULL;
2049 const char *known_groups[] = {
2050 NULL,
2051 "e/desktop/background",
2052 "icon",
2053 "e/init/splash",
2054 /* XXX TODO: add more? example 'screenshot', 'preview' */
2055 NULL
2056 };
2057 Evas_Object *o;
2058
2059 if (!_e_fm2_icon_realpath(ic, buf, sizeof(buf))) return NULL;
2060
2061 known_groups[0] = ic->sd->config->icon.key_hint;
2062 if (known_groups[0]) itr = known_groups;
2063 else itr = known_groups + 1;
2064
2065 for (; *itr; itr++)
2066 {
2067 if (edje_file_group_exists(buf, *itr)) break;
2068 }
2069
2070 if (*itr)
2071 group = eina_stringshare_add(*itr);
2072 else
2073 {
2074 Eina_List *l;
2075
2076 l = edje_file_collection_list(buf);
2077 group = eina_stringshare_ref(eina_list_data_get(l));
2078 edje_file_collection_list_free(l);
2079 }
2080 if (!group) return NULL;
2081 o = _e_fm2_icon_thumb_get(evas, ic, group, cb, data, force_gen, type_ret);
2082 eina_stringshare_del(group);
2083 return o;
2084 }
2085
2086 static Eina_Bool
_e_fm2_icon_cache_update(void * data,int type EINA_UNUSED,void * event EINA_UNUSED)2087 _e_fm2_icon_cache_update(void *data, int type EINA_UNUSED, void *event EINA_UNUSED)
2088 {
2089 _e_fm2_icons_update_helper(data, EINA_TRUE);
2090 return ECORE_CALLBACK_RENEW;
2091 }
2092
2093 /**
2094 * Machinery for _e_fm2_icon_desktop_get() and others with instances of desktop.
2095 */
2096 static Evas_Object *
_e_fm2_icon_desktop_get_internal(Evas * evas,const E_Fm2_Icon * ic,Efreet_Desktop * desktop,const char ** type_ret)2097 _e_fm2_icon_desktop_get_internal(Evas *evas, const E_Fm2_Icon *ic, Efreet_Desktop *desktop, const char **type_ret)
2098 {
2099 Evas_Object *o;
2100
2101 if (!desktop->icon)
2102 return NULL;
2103
2104 if (_e_fm2_file_is_edje(desktop->icon))
2105 return _e_fm2_icon_explicit_edje_get(evas, ic, desktop->icon, type_ret);
2106
2107 o = _e_fm2_icon_explicit_theme_icon_get(evas, ic, desktop->icon, type_ret);
2108 if (o) return o;
2109
2110 o = e_util_desktop_icon_add(desktop, 48, evas);
2111 // o = e_util_icon_theme_icon_add(desktop->icon, 48, evas);
2112 if (o && type_ret) *type_ret = "DESKTOP";
2113 return o;
2114 }
2115
2116 /**
2117 * Use freedesktop.org '.desktop' files to set icon.
2118 */
2119 static Evas_Object *
_e_fm2_icon_desktop_get(Evas * evas,const E_Fm2_Icon * ic,const char ** type_ret)2120 _e_fm2_icon_desktop_get(Evas *evas, const E_Fm2_Icon *ic, const char **type_ret)
2121 {
2122 Efreet_Desktop *ef;
2123 Evas_Object *o;
2124 char buf[PATH_MAX];
2125
2126 if (!ic->info.file) return NULL;
2127
2128 if (!_e_fm2_icon_realpath(ic, buf, sizeof(buf)))
2129 return NULL;
2130
2131 ef = efreet_desktop_new(buf);
2132 if (!ef) return NULL;
2133
2134 o = _e_fm2_icon_desktop_get_internal(evas, ic, ef, type_ret);
2135 efreet_desktop_free(ef);
2136 return o;
2137 }
2138
2139 static inline const char *
_e_fm2_icon_mime_type_special_match(const E_Fm2_Icon * ic)2140 _e_fm2_icon_mime_type_special_match(const E_Fm2_Icon *ic)
2141 {
2142 const Eina_List *l;
2143 const E_Config_Mime_Icon *mi;
2144 const char *mime = ic->info.mime;
2145
2146 EINA_LIST_FOREACH(e_config->mime_icons, l, mi)
2147 if (mi->mime == mime) /* both in the same stringshare pool */
2148 return mi->icon;
2149
2150 return NULL;
2151 }
2152
2153 static Evas_Object *
_e_fm2_icon_mime_fdo_get(Evas * evas,const E_Fm2_Icon * ic,const char ** type_ret)2154 _e_fm2_icon_mime_fdo_get(Evas *evas, const E_Fm2_Icon *ic, const char **type_ret)
2155 {
2156 const char *icon;
2157 unsigned int size;
2158
2159 size = _e_fm2_icon_mime_size_normalize(ic);
2160 icon = efreet_mime_type_icon_get(ic->info.mime, e_config->icon_theme, size);
2161 if (icon)
2162 return _e_fm2_icon_explicit_get(evas, ic, icon, type_ret);
2163 return NULL;
2164 }
2165
2166 static Evas_Object *
_e_fm2_icon_mime_theme_get(Evas * evas,const E_Fm2_Icon * ic,const char ** type_ret EINA_UNUSED)2167 _e_fm2_icon_mime_theme_get(Evas *evas, const E_Fm2_Icon *ic, const char **type_ret EINA_UNUSED)
2168 {
2169 char buf[1024];
2170 const char *file;
2171
2172 if (snprintf(buf, sizeof(buf), "e/icons/fileman/mime/%s", ic->info.mime) >=
2173 (int)sizeof(buf))
2174 return NULL;
2175
2176 file = e_theme_edje_file_get("base/theme/icons", buf);
2177 if (file && file[0])
2178 {
2179 Evas_Object *o = edje_object_add(evas);
2180 if (!o) return NULL;
2181 if (!edje_object_file_set(o, file, buf))
2182 {
2183 evas_object_del(o);
2184 return NULL;
2185 }
2186 return o;
2187 }
2188
2189 return NULL;
2190 }
2191
2192 /**
2193 * Use mime type information to set icon.
2194 */
2195 static Evas_Object *
_e_fm2_icon_mime_get(Evas * evas,const E_Fm2_Icon * ic,Evas_Smart_Cb gen_func EINA_UNUSED,void * data EINA_UNUSED,int force_gen EINA_UNUSED,const char ** type_ret)2196 _e_fm2_icon_mime_get(Evas *evas, const E_Fm2_Icon *ic, Evas_Smart_Cb gen_func EINA_UNUSED, void *data EINA_UNUSED, int force_gen EINA_UNUSED, const char **type_ret)
2197 {
2198 Evas_Object *o = NULL;
2199
2200 if (e_config->icon_theme_overrides)
2201 o = _e_fm2_icon_mime_fdo_get(evas, ic, type_ret);
2202 else
2203 o = _e_fm2_icon_mime_theme_get(evas, ic, type_ret);
2204
2205 if (o) return o;
2206
2207 if (!e_config->icon_theme_overrides)
2208 o = _e_fm2_icon_mime_fdo_get(evas, ic, type_ret);
2209 else
2210 o = _e_fm2_icon_mime_theme_get(evas, ic, type_ret);
2211
2212 return o;
2213 }
2214
2215 /**
2216 * Discovers the executable of Input Method Config file and set icon.
2217 */
2218 static Evas_Object *
_e_fm2_icon_imc_get(Evas * evas,const E_Fm2_Icon * ic,const char ** type_ret)2219 _e_fm2_icon_imc_get(Evas *evas, const E_Fm2_Icon *ic, const char **type_ret)
2220 {
2221 E_Input_Method_Config *imc;
2222 Efreet_Desktop *desktop;
2223 Eet_File *imc_ef;
2224 Evas_Object *o = NULL;
2225 char buf[PATH_MAX];
2226
2227 if (!ic->info.file)
2228 return NULL;
2229
2230 if (!_e_fm2_icon_realpath(ic, buf, sizeof(buf)))
2231 return NULL;
2232
2233 imc_ef = eet_open(buf, EET_FILE_MODE_READ);
2234 if (!imc_ef)
2235 return NULL;
2236
2237 imc = e_intl_input_method_config_read(imc_ef);
2238 eet_close(imc_ef);
2239
2240 if (!imc->e_im_setup_exec)
2241 {
2242 e_intl_input_method_config_free(imc);
2243 return NULL;
2244 }
2245
2246 desktop = efreet_util_desktop_exec_find(imc->e_im_setup_exec);
2247 if (desktop)
2248 {
2249 o = _e_fm2_icon_desktop_get_internal(evas, ic, desktop, type_ret);
2250 efreet_desktop_free(desktop);
2251 }
2252 e_intl_input_method_config_free(imc);
2253
2254 if ((o) && (type_ret)) *type_ret = "IMC";
2255 return o;
2256 }
2257
2258 /**
2259 * Use heuristics to discover and set icon.
2260 */
2261 static Evas_Object *
_e_fm2_icon_discover_get(Evas * evas,const E_Fm2_Icon * ic,Evas_Smart_Cb gen_func,void * data,int force_gen,const char ** type_ret)2262 _e_fm2_icon_discover_get(Evas *evas, const E_Fm2_Icon *ic, Evas_Smart_Cb gen_func, void *data, int force_gen, const char **type_ret)
2263 {
2264 const char *p;
2265
2266 p = strrchr(ic->info.file, '.');
2267 if (!p) return NULL;
2268
2269 p++;
2270 if (_e_fm2_ext_is_edje(p))
2271 return _e_fm2_icon_thumb_edje_get(evas, ic, gen_func,
2272 data, force_gen, type_ret);
2273 if (_e_fm2_ext_is_desktop(p))
2274 return _e_fm2_icon_desktop_get(evas, ic, type_ret);
2275 if (_e_fm2_ext_is_imc(p))
2276 return _e_fm2_icon_imc_get(evas, ic, type_ret);
2277 if (evas_object_image_extension_can_load_get(p - 1))
2278 return _e_fm2_icon_thumb_get(evas, ic, NULL, gen_func, data, force_gen, type_ret);
2279 return NULL;
2280 }
2281
2282 /**
2283 * Get the object representing the icon.
2284 *
2285 * @param evas canvas instance to use to store the icon.
2286 * @param ic icon to get information in order to find the icon.
2287 * @param gen_func if thumbnails need to be generated, call this function
2288 * when it's over.
2289 * @param data extra data to give to @p gen_func.
2290 * @param force_gen force thumbnail generation.
2291 * @param type_ret string that identifies type of icon.
2292 */
2293 E_API Evas_Object *
e_fm2_icon_get(Evas * evas,E_Fm2_Icon * ic,Evas_Smart_Cb gen_func,void * data,int force_gen,const char ** type_ret)2294 e_fm2_icon_get(Evas *evas, E_Fm2_Icon *ic,
2295 Evas_Smart_Cb gen_func,
2296 void *data, int force_gen, const char **type_ret)
2297 {
2298 const char *icon;
2299 Evas_Object *o = NULL;
2300
2301 if (ic->info.icon)
2302 {
2303 if ((ic->info.icon[0] == '/') ||
2304 ((ic->info.icon[0] == '.') &&
2305 ((ic->info.icon[1] == '/') ||
2306 ((ic->info.icon[1] == '.') && (ic->info.icon[2] == '/')))))
2307 {
2308 o = _e_fm2_icon_explicit_get(evas, ic, ic->info.icon, type_ret);
2309 if (o) return o;
2310 }
2311
2312 o = _e_fm2_icon_explicit_theme_icon_get(evas, ic, ic->info.icon, type_ret);
2313 if (o) return o;
2314 }
2315
2316 if (ic->sd->config->icon.max_thumb_size && (ic->info.statinfo.st_size > ic->sd->config->icon.max_thumb_size * 1024 * 1024))
2317 ic->thumb_failed = EINA_TRUE;
2318
2319 /* create thumbnails for edje files */
2320 if ((ic->info.file) && (_e_fm2_file_is_edje(ic->info.file)))
2321 {
2322 o = _e_fm2_icon_thumb_edje_get
2323 (evas, ic, gen_func, data, force_gen, type_ret);
2324 if (o) return o;
2325 }
2326
2327 /* disabled until everyone has edje in mime.types:
2328 * use mimetype to identify edje.
2329 * if (ic->info.mime == _e_fm2_mime_app_edje)
2330 * return _e_fm2_icon_thumb_edje_get
2331 * (evas, ic, gen_func, data, force_gen, type_ret); */
2332
2333 /* check user preferences */
2334 icon = _e_fm2_icon_mime_type_special_match(ic);
2335 if (icon)
2336 {
2337 if (icon == _e_fm2_icon_desktop_str)
2338 o = _e_fm2_icon_desktop_get(evas, ic, type_ret);
2339 else if (icon == _e_fm2_icon_thumb_str)
2340 {
2341 if (!ic->thumb_failed)
2342 o = _e_fm2_icon_thumb_get
2343 (evas, ic, NULL, gen_func, data, force_gen, type_ret);
2344 }
2345 else if (strncmp(icon, "e/icons/fileman/", 16) == 0)
2346 o = _e_fm2_icon_explicit_theme_get(evas, ic, icon + 16, type_ret);
2347 else
2348 o = _e_fm2_icon_explicit_get(evas, ic, icon, type_ret);
2349
2350 if (o) return o;
2351 }
2352
2353 if ((!ic->thumb_failed) && (ic->info.icon_type == 1))
2354 {
2355 o = _e_fm2_icon_thumb_get(evas, ic, NULL,
2356 gen_func, data, force_gen, type_ret);
2357 if (o) return o;
2358 }
2359
2360 if (ic->info.file)
2361 {
2362 o = _e_fm2_icon_discover_get(evas, ic, gen_func, data,
2363 force_gen, type_ret);
2364 if (o) return o;
2365 }
2366 if (ic->info.mime)
2367 {
2368 o = _e_fm2_icon_mime_get(evas, ic, gen_func, data, force_gen, type_ret);
2369 if (o) return o;
2370 }
2371
2372 //fallback:
2373 o = _e_fm2_icon_explicit_theme_icon_get(evas, ic, "unknown", type_ret);
2374 if (o) return o;
2375
2376 return _e_fm2_icon_explicit_theme_get(evas, ic, "text/plain", type_ret);
2377 }
2378
2379 E_API E_Fm2_Icon_Info *
e_fm2_icon_file_info_get(E_Fm2_Icon * ic)2380 e_fm2_icon_file_info_get(E_Fm2_Icon *ic)
2381 {
2382 if (!ic) return NULL;
2383 return &(ic->info);
2384 }
2385
2386 E_API void
e_fm2_icon_geometry_get(E_Fm2_Icon * ic,int * x,int * y,int * w,int * h)2387 e_fm2_icon_geometry_get(E_Fm2_Icon *ic, int *x, int *y, int *w, int *h)
2388 {
2389 int xx, yy, ww, hh;
2390
2391 if (x) *x = 0;
2392 if (y) *y = 0;
2393 if (w) *w = 0;
2394 if (h) *h = 0;
2395
2396 if (ic)
2397 {
2398 evas_object_geometry_get(ic->obj, &xx, &yy, &ww, &hh);
2399 if (x) *x = xx;
2400 if (y) *y = yy;
2401 if (w) *w = ww;
2402 if (h) *h = hh;
2403 }
2404 }
2405
2406 /* FIXME: track real exe with exe del events etc. */
2407 static int _e_fm2_client_spawning = 0;
2408
2409 static void
_e_fm2_client_spawn(void)2410 _e_fm2_client_spawn(void)
2411 {
2412 char buf[4096];
2413
2414 if (_e_fm2_client_spawning) return;
2415 if (e_sys_on_the_way_out_get()) return;
2416 snprintf(buf, sizeof(buf), "%s/enlightenment/utils/enlightenment_fm", e_prefix_lib_get());
2417 if (_e_fm2_exe) e_fm2_die();
2418 _e_fm2_exe = ecore_exe_pipe_run(buf, ECORE_EXE_NOT_LEADER | ECORE_EXE_TERM_WITH_PARENT, NULL);
2419 _e_fm2_client_spawning = 1;
2420 }
2421
2422 static E_Fm2_Client *
_e_fm2_client_get(void)2423 _e_fm2_client_get(void)
2424 {
2425 Eina_List *l;
2426 E_Fm2_Client *cl, *cl_chosen = NULL;
2427 int min_req = 0x7fffffff;
2428
2429 /* if we don't have a slave - spawn one */
2430 if (!_e_fm2_client_list)
2431 {
2432 _e_fm2_client_spawn();
2433 return NULL;
2434 }
2435 EINA_LIST_FOREACH(_e_fm2_client_list, l, cl)
2436 {
2437 if (cl->req < min_req)
2438 {
2439 min_req = cl->req;
2440 cl_chosen = cl;
2441 }
2442 }
2443 return cl_chosen;
2444 }
2445
2446 typedef struct _E_Fm2_Message E_Fm2_Message;
2447
2448 struct _E_Fm2_Message
2449 {
2450 int major, minor, ref, ref_to, response;
2451 void *data;
2452 int size;
2453 };
2454
2455 static Eina_List *_e_fm2_messages = NULL;
2456
2457 static void
_e_fm2_client_message_queue(int major,int minor,int ref,int ref_to,int response,const void * data,int size)2458 _e_fm2_client_message_queue(int major, int minor, int ref, int ref_to, int response, const void *data, int size)
2459 {
2460 E_Fm2_Message *msg;
2461
2462 msg = E_NEW(E_Fm2_Message, 1);
2463 if (!msg) return;
2464 msg->major = major;
2465 msg->minor = minor;
2466 msg->ref = ref;
2467 msg->ref_to = ref_to;
2468 msg->response = response;
2469 if (data)
2470 {
2471 msg->size = size;
2472 msg->data = malloc(size);
2473 if (msg->data)
2474 memcpy(msg->data, data, size);
2475 else
2476 {
2477 free(msg);
2478 return;
2479 }
2480 }
2481 _e_fm2_messages = eina_list_append(_e_fm2_messages, msg);
2482 }
2483
2484 static void
_e_fm2_client_message_flush(E_Fm2_Client * cl,E_Fm2_Message * msg)2485 _e_fm2_client_message_flush(E_Fm2_Client *cl, E_Fm2_Message *msg)
2486 {
2487 _e_fm2_messages = eina_list_remove(_e_fm2_messages, msg);
2488 ecore_ipc_client_send(cl->cl, msg->major, msg->minor,
2489 msg->ref, msg->ref_to, msg->response,
2490 msg->data, msg->size);
2491 cl->req++;
2492 free(msg->data);
2493 free(msg);
2494 }
2495
2496 static void
_e_fm2_client_messages_flush(void)2497 _e_fm2_client_messages_flush(void)
2498 {
2499 while (_e_fm2_messages)
2500 {
2501 E_Fm2_Client *cl;
2502
2503 cl = _e_fm2_client_get();
2504 if (!cl) break;
2505 _e_fm2_client_message_flush(cl, eina_list_data_get(_e_fm2_messages));
2506 }
2507 }
2508
2509 static int
_e_fm_client_send_new(int minor,void * data,int size)2510 _e_fm_client_send_new(int minor, void *data, int size)
2511 {
2512 static int id = 0;
2513 E_Fm2_Client *cl;
2514
2515 id++;
2516 cl = _e_fm2_client_get();
2517 if (!cl)
2518 {
2519 _e_fm2_client_message_queue(E_IPC_DOMAIN_FM, minor,
2520 id, 0, 0,
2521 data, size);
2522 }
2523 else
2524 {
2525 ecore_ipc_client_send(cl->cl, E_IPC_DOMAIN_FM, minor,
2526 id, 0, 0,
2527 data, size);
2528 cl->req++;
2529 }
2530
2531 return id;
2532 }
2533
2534 static int
_e_fm_client_send(int minor,int id,void * data,int size)2535 _e_fm_client_send(int minor, int id, void *data, int size)
2536 {
2537 E_Fm2_Client *cl;
2538
2539 cl = _e_fm2_client_get();
2540 if (!cl)
2541 {
2542 _e_fm2_client_message_queue(E_IPC_DOMAIN_FM, minor,
2543 id, 0, 0,
2544 data, size);
2545 }
2546 else
2547 {
2548 ecore_ipc_client_send(cl->cl, E_IPC_DOMAIN_FM, minor,
2549 id, 0, 0,
2550 data, size);
2551 cl->req++;
2552 }
2553
2554 return id;
2555 }
2556
2557 static int
_e_fm2_client_monitor_add(const char * path)2558 _e_fm2_client_monitor_add(const char *path)
2559 {
2560 return _e_fm_client_send_new(E_FM_OP_MONITOR_START, (void *)path, strlen(path) + 1);
2561 }
2562
2563 static void
_e_fm2_client_monitor_del(int id,const char * path)2564 _e_fm2_client_monitor_del(int id, const char *path)
2565 {
2566 _e_fm_client_send(E_FM_OP_MONITOR_END, id, (void *)path, strlen(path) + 1);
2567 }
2568
2569 static int
_e_fm_client_file_del(const char * files,Eina_Bool secure,Evas_Object * e_fm)2570 _e_fm_client_file_del(const char *files, Eina_Bool secure, Evas_Object *e_fm)
2571 {
2572 int id, op = E_FM_OP_REMOVE;
2573
2574 if (secure) op = E_FM_OP_SECURE_REMOVE;
2575
2576 id = _e_fm_client_send_new(op, (void *)files, strlen(files) + 1);
2577 e_fm2_op_registry_entry_add(id, e_fm, op, _e_fm2_operation_abort_internal);
2578 return id;
2579 }
2580
2581 #if 0
2582 static int
2583 _e_fm2_client_file_trash(const char *path, Evas_Object *e_fm)
2584 {
2585 int id = _e_fm_client_send_new(E_FM_OP_TRASH, (void *)path, strlen(path) + 1);
2586 e_fm2_op_registry_entry_add(id, e_fm, E_FM_OP_TRASH, _e_fm2_operation_abort_internal);
2587 return id;
2588 }
2589
2590 static int
2591 _e_fm2_client_file_mkdir(const char *path, const char *rel, int rel_to, int x, int y, int res_w EINA_UNUSED, int res_h EINA_UNUSED, Evas_Object *e_fm)
2592 {
2593 char *d;
2594 int l1, l2, l, id;
2595
2596 l1 = strlen(path);
2597 l2 = strlen(rel);
2598 l = l1 + 1 + l2 + 1 + (sizeof(int) * 3);
2599 d = alloca(l);
2600 strcpy(d, path);
2601 strcpy(d + l1 + 1, rel);
2602 memcpy(d + l1 + 1 + l2 + 1, &rel_to, sizeof(int));
2603 memcpy(d + l1 + 1 + l2 + 1 + sizeof(int), &x, sizeof(int));
2604 memcpy(d + l1 + 1 + l2 + 1 + (2 * sizeof(int)), &y, sizeof(int));
2605
2606 id = _e_fm_client_send_new(E_FM_OP_MKDIR, (void *)d, l);
2607 e_fm2_op_registry_entry_add(id, e_fm, E_FM_OP_MKDIR, _e_fm2_operation_abort_internal);
2608 return id;
2609 }
2610
2611 #endif
2612
2613 E_API int
e_fm2_client_file_move(Evas_Object * e_fm,const char * args)2614 e_fm2_client_file_move(Evas_Object *e_fm, const char *args)
2615 {
2616 int id;
2617 E_Fm_Op_Type op = e_config->filemanager_copy ? E_FM_OP_MOVE : E_FM_OP_RENAME;
2618
2619 id = _e_fm_client_send_new(op, (void *)args, strlen(args) + 1);
2620 e_fm2_op_registry_entry_add(id, e_fm, op, _e_fm2_operation_abort_internal);
2621 return id;
2622 }
2623
2624 E_API int
e_fm2_client_file_copy(Evas_Object * e_fm,const char * args)2625 e_fm2_client_file_copy(Evas_Object *e_fm, const char *args)
2626 {
2627 int id = _e_fm_client_send_new(E_FM_OP_COPY, (void *)args, strlen(args) + 1);
2628 e_fm2_op_registry_entry_add(id, e_fm, E_FM_OP_COPY, _e_fm2_operation_abort_internal);
2629 return id;
2630 }
2631
2632 E_API int
e_fm2_client_file_symlink(Evas_Object * e_fm,const char * args)2633 e_fm2_client_file_symlink(Evas_Object *e_fm, const char *args)
2634 {
2635 int id = _e_fm_client_send_new(E_FM_OP_SYMLINK, (void *)args, strlen(args) + 1);
2636 e_fm2_op_registry_entry_add(id, e_fm, E_FM_OP_SYMLINK, _e_fm2_operation_abort_internal);
2637 return id;
2638 }
2639
2640 E_API int
_e_fm2_client_mount(const char * udi,const char * mountpoint)2641 _e_fm2_client_mount(const char *udi, const char *mountpoint)
2642 {
2643 char *d;
2644 int l, l1, l2 = 0;
2645
2646 if (!udi)
2647 return 0;
2648
2649 l1 = strlen(udi);
2650 if (mountpoint)
2651 {
2652 l2 = strlen(mountpoint);
2653 l = l1 + 1 + l2 + 1;
2654 }
2655 else
2656 l = l1 + 1;
2657 d = alloca(l);
2658 strcpy(d, udi);
2659 if (mountpoint)
2660 strcpy(d + l1 + 1, mountpoint);
2661
2662 return _e_fm_client_send_new(E_FM_OP_MOUNT, (void *)d, l);
2663 }
2664
2665 E_API int
_e_fm2_client_unmount(const char * udi)2666 _e_fm2_client_unmount(const char *udi)
2667 {
2668 char *d;
2669 int l, l1;
2670
2671 if (!udi)
2672 return 0;
2673
2674 l1 = strlen(udi);
2675 l = l1 + 1;
2676 d = alloca(l);
2677 strcpy(d, udi);
2678
2679 _e_fm2_client_get();
2680
2681 elm_cache_all_flush();
2682 edje_file_cache_flush();
2683 edje_collection_cache_flush();
2684 if (e_comp)
2685 {
2686 evas_image_cache_flush(e_comp->evas);
2687 evas_font_cache_flush(e_comp->evas);
2688 }
2689
2690 return _e_fm_client_send_new(E_FM_OP_UNMOUNT, (void *)d, l);
2691 }
2692
2693 E_API int
_e_fm2_client_eject(const char * udi)2694 _e_fm2_client_eject(const char *udi)
2695 {
2696 char *data;
2697 int size;
2698
2699 if (!udi)
2700 return 0;
2701
2702 size = strlen(udi) + 1;
2703 data = alloca(size);
2704 strcpy(data, udi);
2705
2706 fprintf(stderr, "EJECT [%s]\n", udi); // udi == /dev/sdd1 :)
2707 return _e_fm_client_send_new(E_FM_OP_EJECT, data, size);
2708 }
2709
2710 static void
_e_fm2_client_monitor_list_end(Evas_Object * obj)2711 _e_fm2_client_monitor_list_end(Evas_Object *obj)
2712 {
2713 E_Fm2_Smart_Data *sd;
2714
2715 sd = evas_object_smart_data_get(obj);
2716 sd->busy_count--;
2717 if (sd->busy_count == 0)
2718 {
2719 edje_object_signal_emit(sd->overlay, "e,state,busy,stop", "e");
2720 e_fm2_custom_file_flush();
2721 }
2722 if (sd->tmp.obj)
2723 {
2724 evas_object_del(sd->tmp.obj);
2725 sd->tmp.obj = NULL;
2726 }
2727 if (sd->tmp.obj2)
2728 {
2729 evas_object_del(sd->tmp.obj2);
2730 sd->tmp.obj2 = NULL;
2731 }
2732 if (sd->scan_timer)
2733 {
2734 ecore_timer_del(sd->scan_timer);
2735 sd->scan_timer = NULL;
2736 }
2737 if (sd->sort_idler)
2738 {
2739 ecore_idler_del(sd->sort_idler);
2740 sd->sort_idler = NULL;
2741 }
2742 E_FREE(sd->tmp.list_index);
2743 _e_fm2_queue_free(obj);
2744 _e_fm2_obj_icons_place(sd);
2745 _e_fm2_live_process_begin(obj);
2746 }
2747
2748 E_API void
_e_fm2_file_force_update(const char * path)2749 _e_fm2_file_force_update(const char *path)
2750 {
2751 Evas_Object *o;
2752 char *dir;
2753 Eina_List *l;
2754
2755 dir = ecore_file_dir_get(path);
2756 if (!dir) return;
2757 EINA_LIST_FOREACH(_e_fm2_list, l, o)
2758 {
2759 const char *rp;
2760 if ((_e_fm2_list_walking > 0) &&
2761 (eina_list_data_find(_e_fm2_list_remove, o))) continue;
2762 rp = e_fm2_real_path_get(o);
2763 if (!rp) continue;
2764 if (!strcmp(rp, dir))
2765 {
2766 E_Fm2_Icon *ic;
2767
2768 ic = _e_fm2_icon_find(o, ecore_file_file_get(path));
2769 if (ic)
2770 {
2771 E_Fm2_Finfo finf;
2772
2773 memset(&finf, 0, sizeof(E_Fm2_Finfo));
2774 memcpy(&(finf.st), &(ic->info.statinfo),
2775 sizeof(struct stat));
2776 finf.broken_link = ic->info.broken_link;
2777 finf.lnk = ic->info.link;
2778 finf.rlnk = ic->info.real_link;
2779 ic->removable_state_change = EINA_TRUE;
2780 _e_fm2_live_file_changed(o, ecore_file_file_get(path),
2781 &finf);
2782 }
2783 }
2784 }
2785 free(dir);
2786 }
2787
2788 E_API void
e_fm2_client_data(Ecore_Ipc_Event_Client_Data * e)2789 e_fm2_client_data(Ecore_Ipc_Event_Client_Data *e)
2790 {
2791 Evas_Object *obj;
2792 Eina_List *l, *dels = NULL;
2793 E_Fm2_Client *cl;
2794
2795 if (e->major != 6 /*E_IPC_DOMAIN_FM*/) return;
2796 EINA_LIST_FOREACH(_e_fm2_client_list, l, cl)
2797 {
2798 if (cl->cl == e->client) break;
2799 }
2800 if (!l)
2801 {
2802 cl = E_NEW(E_Fm2_Client, 1);
2803 cl->cl = e->client;
2804 _e_fm2_client_list = eina_list_prepend(_e_fm2_client_list, cl);
2805 /* FIXME: new client - send queued msgs */
2806 _e_fm2_client_spawning = 0;
2807 _e_fm2_client_messages_flush();
2808 }
2809
2810 _e_fm2_list_walking++;
2811 EINA_LIST_FOREACH(_e_fm2_list, l, obj)
2812 {
2813 unsigned char *p;
2814 char *evdir;
2815 const char *dir, *path, *lnk, *rlnk, *file;
2816 struct stat st;
2817 int broken_link;
2818 E_Fm2_Smart_Data *sd;
2819
2820 if ((_e_fm2_list_walking > 0) &&
2821 (eina_list_data_find(_e_fm2_list_remove, obj))) continue;
2822 dir = e_fm2_real_path_get(obj);
2823 sd = evas_object_smart_data_get(obj);
2824 switch (e->minor)
2825 {
2826 case E_FM_OP_HELLO: /*hello*/
2827 // printf("E_FM_OP_HELLO\n");
2828 break;
2829
2830 case E_FM_OP_OK: /*req ok*/
2831 // printf("E_FM_OP_OK\n");
2832 cl->req--;
2833 break;
2834
2835 case E_FM_OP_FILE_ADD: /*file add*/
2836 // printf("E_FM_OP_FILE_ADD\n");
2837 case E_FM_OP_FILE_CHANGE: /*file change*/
2838 // printf("E_FM_OP_FILE_CHANGE\n");
2839 {
2840 E_Fm2_Finfo finf;
2841
2842 p = e->data;
2843 /* NOTE: i am NOT converting this data to portable arch/os independent
2844 * format. i am ASSUMING e_fm_main and e are local and built together
2845 * and thus this will work. if this ever changes this here needs to
2846 * change */
2847 memcpy(&st, p, sizeof(struct stat));
2848 p += sizeof(struct stat);
2849
2850 broken_link = p[0];
2851 p += 1;
2852
2853 path = (char *)p;
2854 p += strlen(path) + 1;
2855
2856 lnk = (char *)p;
2857 p += strlen(lnk) + 1;
2858
2859 rlnk = (char *)p;
2860
2861 memcpy(&(finf.st), &st, sizeof(struct stat));
2862 finf.broken_link = broken_link;
2863 finf.lnk = lnk;
2864 finf.rlnk = rlnk;
2865
2866 evdir = ecore_file_dir_get(path);
2867 if ((evdir) && (sd->id == e->ref_to) &&
2868 ((!strcmp(evdir, "") || ((dir) && (!strcmp(dir, evdir))))))
2869 {
2870 // printf(" ch/add response = %i\n", e->response);
2871 free(evdir);
2872 if (e->response == 0) /*live changes*/
2873 {
2874 if (e->minor == E_FM_OP_FILE_ADD) /*file add*/
2875 {
2876 _e_fm2_live_file_add
2877 (obj, ecore_file_file_get(path),
2878 NULL, 0, &finf);
2879 break;
2880 }
2881 if (e->minor == E_FM_OP_FILE_CHANGE) /*file change*/
2882 {
2883 _e_fm2_live_file_changed
2884 (obj, (char *)ecore_file_file_get(path),
2885 &finf);
2886 }
2887 break;
2888 }
2889 /*file add - listing*/
2890 if (e->minor == E_FM_OP_FILE_ADD) /*file add*/
2891 {
2892 if (!sd->scan_timer)
2893 {
2894 sd->scan_timer =
2895 ecore_timer_loop_add(0.5,
2896 _e_fm2_cb_scan_timer,
2897 sd->obj);
2898 sd->busy_count++;
2899 if (sd->busy_count == 1)
2900 edje_object_signal_emit(sd->overlay, "e,state,busy,start", "e");
2901 }
2902 else
2903 {
2904 if ((eina_list_count(sd->icons) > 50) && (ecore_timer_interval_get(sd->scan_timer) < 1.5))
2905 {
2906 /* increase timer interval when loading large directories to
2907 * dramatically improve load times
2908 */
2909 ecore_timer_interval_set(sd->scan_timer, 1.5);
2910 ecore_timer_loop_reset(sd->scan_timer);
2911 }
2912 }
2913 if (path[0] != 0)
2914 {
2915 file = ecore_file_file_get(path);
2916 if ((!strcmp(file, ".order")))
2917 sd->order_file = EINA_TRUE;
2918 else
2919 {
2920 unsigned int n;
2921
2922 n = eina_list_count(sd->queue) + eina_list_count(sd->icons);
2923 if (!((file[0] == '.') &&
2924 (!sd->show_hidden_files)))
2925 {
2926 char buf[1024];
2927
2928 _e_fm2_file_add(obj, file,
2929 sd->order_file,
2930 NULL, 0, &finf);
2931 if (n - sd->overlay_count > 150)
2932 {
2933 sd->overlay_count = n + 1;
2934 snprintf(buf, sizeof(buf), P_("%u file", "%u files", sd->overlay_count), sd->overlay_count);
2935 edje_object_part_text_set(sd->overlay, "e.text.busy_label", buf);
2936 }
2937 }
2938 }
2939 }
2940 if (e->response == 2) /* end of scan */
2941 {
2942 sd->listing = EINA_FALSE;
2943 if (sd->scan_timer)
2944 {
2945 ecore_timer_interval_set(sd->scan_timer, 0.0001);
2946 ecore_timer_loop_reset(sd->scan_timer);
2947 }
2948 else
2949 {
2950 _e_fm2_client_monitor_list_end(obj);
2951 }
2952 }
2953 }
2954 break;
2955 }
2956 free(evdir);
2957 // printf(" ...\n");
2958 if ((sd->id != e->ref_to) || (path[0] != 0)) break;
2959 // printf(" end response = %i\n", e->response);
2960 if (e->response == 2) /* end of scan */
2961 {
2962 sd->listing = EINA_FALSE;
2963 if (sd->scan_timer)
2964 {
2965 ecore_timer_del(sd->scan_timer);
2966 sd->scan_timer =
2967 ecore_timer_loop_add(0.0001,
2968 _e_fm2_cb_scan_timer,
2969 sd->obj);
2970 }
2971 else
2972 {
2973 _e_fm2_client_monitor_list_end(obj);
2974 }
2975 }
2976 }
2977 break;
2978
2979 case E_FM_OP_FILE_DEL: /*file del*/
2980 // printf("E_FM_OP_FILE_DEL\n");
2981 path = e->data;
2982 evdir = ecore_file_dir_get(path);
2983 if ((dir) && (evdir) && (sd->id == e->ref_to) && (!strcmp(dir, evdir)))
2984 {
2985 _e_fm2_live_file_del
2986 (obj, ecore_file_file_get(path));
2987 }
2988 free(evdir);
2989 break;
2990
2991 case E_FM_OP_MONITOR_END: /*mon dir del*/
2992 // printf("E_FM_OP_MONITOR_END\n");
2993 path = e->data;
2994 /* FIXME dir should not be null but can. fix segv
2995 when mounting cdrom with udisk here
2996 btw monitor end seems to be a strange event for
2997 mounting disks.
2998 */
2999 if ((dir) && (path) && (sd->id == e->ref_to) && (!strcmp(dir, path)))
3000 {
3001 dels = eina_list_append(dels, obj);
3002 }
3003 break;
3004
3005 default:
3006 break;
3007 }
3008 }
3009 EINA_LIST_FREE(dels, obj)
3010 {
3011 E_Fm2_Smart_Data *sd;
3012
3013 sd = evas_object_smart_data_get(obj);
3014 if ((_e_fm2_list_walking > 0) &&
3015 (eina_list_data_find(_e_fm2_list_remove, obj))) continue;
3016 if (sd->config->view.open_dirs_in_place)
3017 _e_fm2_path_parent_set(obj, sd->realpath);
3018 else
3019 evas_object_smart_callback_call(obj, "dir_deleted", NULL);
3020 }
3021 _e_fm2_list_walking--;
3022 if (_e_fm2_list_walking == 0)
3023 {
3024 EINA_LIST_FREE(_e_fm2_list_remove, obj)
3025 {
3026 _e_fm2_list = eina_list_remove(_e_fm2_list, obj);
3027 }
3028 }
3029 switch (e->minor)
3030 {
3031 case E_FM_OP_INIT:
3032 e_config->device_detect_mode = strtoul((char*)e->data, NULL, 10);
3033 break;
3034 case E_FM_OP_MONITOR_SYNC: /*mon list sync*/
3035 ecore_ipc_client_send(cl->cl, E_IPC_DOMAIN_FM, E_FM_OP_MONITOR_SYNC,
3036 0, 0, e->response,
3037 NULL, 0);
3038 break;
3039
3040 case E_FM_OP_STORAGE_ADD: /*storage add*/
3041 if ((e->data) && (e->size > 0))
3042 {
3043 E_Storage *s;
3044
3045 s = _e_fm_shared_codec_storage_decode(e->data, e->size);
3046 if (s) e_fm2_device_storage_add(s);
3047 }
3048 break;
3049
3050 case E_FM_OP_STORAGE_DEL: /*storage del*/
3051 if ((e->data) && (e->size > 0))
3052 {
3053 char *udi;
3054 E_Storage *s;
3055
3056 udi = e->data;
3057 s = e_fm2_device_storage_find(udi);
3058 if (s) e_fm2_device_storage_del(s);
3059 }
3060 break;
3061
3062 case E_FM_OP_VOLUME_LIST_DONE:
3063 e_fm2_device_check_desktop_icons();
3064 break;
3065
3066 case E_FM_OP_VOLUME_ADD: /*volume add*/
3067 if ((e->data) && (e->size > 0))
3068 {
3069 E_Volume *v;
3070
3071 v = _e_fm_shared_codec_volume_decode(e->data, e->size);
3072 if (!v) break;
3073 e_config->device_detect_mode = v->efm_mode;
3074 e_fm2_device_volume_add(v);
3075 if (v->mounted)
3076 e_fm2_device_mount(v, NULL, NULL, NULL, NULL, NULL);
3077 else if ((!starting) && e_config->device_auto_mount && v->first_time)
3078 {
3079 v->auto_unmount = !v->mounted;
3080 _e_fm2_client_mount(v->udi, v->mount_point);
3081 }
3082 if (e_config->device_desktop)
3083 e_fm2_device_show_desktop_icons();
3084 else
3085 e_fm2_device_hide_desktop_icons();
3086 v->first_time = 0;
3087 }
3088 break;
3089
3090 case E_FM_OP_VOLUME_DEL: /*volume del*/
3091 if ((e->data) && (e->size > 0))
3092 {
3093 char *udi;
3094 E_Volume *v;
3095
3096 udi = e->data;
3097 v = e_fm2_device_volume_find(udi);
3098 if (v) e_fm2_device_volume_del(v);
3099 }
3100 break;
3101
3102 case E_FM_OP_MOUNT_DONE: /*mount done*/
3103 if ((e->data) && (e->size > 1))
3104 {
3105 E_Volume *v;
3106 char *udi, *mountpoint = NULL;
3107
3108 udi = e->data;
3109 if ((unsigned int)e->size != (strlen(udi) + 1))
3110 mountpoint = udi + strlen(udi) + 1;
3111 v = e_fm2_device_volume_find(udi);
3112 if (v)
3113 {
3114 e_fm2_device_mount_add(v, mountpoint);
3115 _e_fm2_volume_icon_update(v);
3116 if (e_config->device_auto_open && !eina_list_count(v->mounts))
3117 {
3118 E_Action *a;
3119 unsigned int count;
3120
3121 a = e_action_find("fileman");
3122 count = eina_list_count(_e_fm2_list);
3123 if (a && a->func.go && mountpoint)
3124 {
3125 Evas_Object *fm;
3126 Eina_List *m;
3127 Eina_Bool auto_unmount = v->auto_unmount;
3128
3129 a->func.go(E_OBJECT(e_comp), mountpoint);
3130 if (count == eina_list_count(_e_fm2_list)) break;
3131 EINA_LIST_REVERSE_FOREACH(_e_fm2_list, m, fm)
3132 {
3133 E_Fm2_Smart_Data *sd = evas_object_smart_data_get(fm);
3134 if (e_util_strcmp(sd->realpath, mountpoint)) continue;
3135 if (sd->mount) break;
3136 sd->mount = e_fm2_device_mount(v, _e_fm2_cb_mount_ok,
3137 _e_fm2_cb_mount_fail,
3138 _e_fm2_cb_unmount_ok, NULL, fm);
3139 v->auto_unmount = auto_unmount;
3140 break;
3141 }
3142 }
3143 }
3144 }
3145 }
3146 break;
3147
3148 case E_FM_OP_UNMOUNT_DONE: /*unmount done*/
3149 if ((e->data) && (e->size > 1))
3150 {
3151 E_Volume *v;
3152 char *udi;
3153
3154 udi = e->data;
3155 v = e_fm2_device_volume_find(udi);
3156 if (v)
3157 {
3158 e_fm2_device_mount_del(v);
3159 _e_fm2_volume_icon_update(v);
3160 }
3161 }
3162 break;
3163
3164 case E_FM_OP_EJECT_DONE:
3165 break;
3166
3167 case E_FM_OP_MOUNT_ERROR: /*mount error*/
3168 if (e->data && (e->size > 1))
3169 {
3170 E_Volume *v;
3171 char *udi;
3172
3173 udi = e->data;
3174 v = e_fm2_device_volume_find(udi);
3175 if (v)
3176 {
3177 _e_fm_device_error_dialog(_("Mount Error"), _("Can't mount device"), e->data);
3178 e_fm2_device_mount_fail(v);
3179 }
3180 }
3181 break;
3182
3183 case E_FM_OP_UNMOUNT_ERROR: /*unmount error*/
3184 if (e->data && (e->size > 1))
3185 {
3186 E_Volume *v;
3187 char *udi;
3188
3189 udi = e->data;
3190 v = e_fm2_device_volume_find(udi);
3191 if (v)
3192 {
3193 _e_fm_device_error_dialog(_("Unmount Error"), _("Can't unmount device"), e->data);
3194 e_fm2_device_unmount_fail(v);
3195 }
3196 }
3197 break;
3198
3199 case E_FM_OP_EJECT_ERROR:
3200 if (e->data && (e->size > 1))
3201 {
3202 E_Volume *v;
3203 char *udi;
3204
3205 udi = e->data;
3206 v = e_fm2_device_volume_find(udi);
3207 if (v)
3208 _e_fm_device_error_dialog(_("Eject Error"), _("Can't eject device"), e->data);
3209 }
3210 break;
3211
3212 case E_FM_OP_ERROR: /*error*/
3213 {
3214 E_Dialog *dlg;
3215 ERR("Error from slave #%d: %s", e->ref, (char *)e->data);
3216 dlg = _e_fm_error_dialog(e->ref, e->data);
3217 _e_fm2_op_registry_error(e->ref, dlg);
3218 }
3219 break;
3220
3221 case E_FM_OP_ERROR_RETRY_ABORT: /*error*/
3222 {
3223 E_Dialog *dlg;
3224 ERR("Error from slave #%d: %s", e->ref, (char *)e->data);
3225 dlg = _e_fm_retry_abort_dialog(e->ref, (char *)e->data);
3226 _e_fm2_op_registry_error(e->ref, dlg);
3227 }
3228 break;
3229
3230 case E_FM_OP_OVERWRITE: /*overwrite*/
3231 {
3232 E_Dialog *dlg;
3233 ERR("Overwrite from slave #%d: %s", e->ref, (char *)e->data);
3234 dlg = _e_fm_overwrite_dialog(e->ref, (char *)e->data);
3235 _e_fm2_op_registry_needs_attention(e->ref, dlg);
3236 }
3237 break;
3238
3239 case E_FM_OP_PROGRESS: /*progress*/
3240 {
3241 int percent, seconds;
3242 off_t done, total;
3243 char *src = NULL;
3244 char *dst = NULL;
3245 char *p = e->data;
3246 E_Fm2_Op_Registry_Entry *ere;
3247
3248 if (!e->data) return;
3249
3250 #define UP(value, type) (value) = *(type *)(void *)p; p += sizeof(type)
3251 UP(percent, int);
3252 UP(seconds, int);
3253 UP(done, off_t);
3254 UP(total, off_t);
3255 #undef UP
3256 src = p;
3257 dst = p + strlen(src) + 1;
3258 // 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);
3259
3260 ere = e_fm2_op_registry_entry_get(e->ref);
3261 if (!ere) return;
3262 ere->percent = percent;
3263 ere->done = done;
3264 ere->total = total;
3265 ere->eta = seconds;
3266 e_fm2_op_registry_entry_files_set(ere, src, dst);
3267 if (ere->percent == 100)
3268 {
3269 ere->status = E_FM2_OP_STATUS_SUCCESSFUL;
3270 ere->finished = 1;
3271 }
3272 e_fm2_op_registry_entry_changed(ere);
3273 }
3274 break;
3275
3276 case E_FM_OP_QUIT: /*finished*/
3277 {
3278 E_Fm2_Op_Registry_Entry *ere = e_fm2_op_registry_entry_get(e->ref);
3279 if (ere)
3280 {
3281 ere->finished = 1;
3282 ere->eta = 0;
3283 e_fm2_op_registry_entry_changed(ere);
3284 }
3285 e_fm2_op_registry_entry_del(e->ref);
3286 }
3287 break;
3288
3289 default:
3290 break;
3291 }
3292 }
3293
3294 E_API void
e_fm2_client_del(Ecore_Ipc_Event_Client_Del * e)3295 e_fm2_client_del(Ecore_Ipc_Event_Client_Del *e)
3296 {
3297 Eina_List *l;
3298 E_Fm2_Client *cl;
3299
3300 EINA_LIST_FOREACH(_e_fm2_client_list, l, cl)
3301 {
3302 if (cl->cl == e->client)
3303 {
3304 _e_fm2_client_list = eina_list_remove_list(_e_fm2_client_list, l);
3305 free(cl);
3306 break;
3307 }
3308 }
3309 }
3310
3311 /* local subsystem functions */
3312 static const char *
_e_fm2_dev_path_map(E_Fm2_Smart_Data * sd,const char * dev,const char * path)3313 _e_fm2_dev_path_map(E_Fm2_Smart_Data *sd, const char *dev, const char *path)
3314 {
3315 char buf[PATH_MAX] = "", *s, *ss;
3316 int len;
3317
3318 /* map a device name to a mount point/path on the os (and append path) */
3319
3320 /* FIXME: load mappings from config and use them first - maybe device
3321 * discovery should be done through config and not the below (except
3322 * maybe for home directory and root fs and other simple thngs */
3323 /* FIXME: also add other virtualized dirs like "backgrounds", "themes",
3324 * "favorites" */
3325 #define CMP(x) ((dev) && (e_util_glob_case_match(dev, x)))
3326 #define PRT(args ...) snprintf(buf, sizeof(buf), ##args)
3327
3328 if (dev)
3329 {
3330 if (dev[0] == '/')
3331 {
3332 if (dev[1] == '\0')
3333 {
3334 if (eina_strlcpy(buf, path, sizeof(buf)) >=
3335 (int)sizeof(buf))
3336 return NULL;
3337 }
3338 else
3339 {
3340 if (PRT("%s/%s", dev, path) >= (int)sizeof(buf))
3341 return NULL;
3342 }
3343 }
3344 else if ((dev[0] == '~') && (dev[1] == '/') && (dev[2] == '\0'))
3345 {
3346 s = (char *)e_user_homedir_get();
3347 if (PRT("%s/%s", s, path) >= (int)sizeof(buf))
3348 return NULL;
3349 }
3350 else if (strcmp(dev, "favorites") == 0)
3351 {
3352 /* this is a virtual device - it's where your favorites list is
3353 * stored - a dir with
3354 .desktop files or symlinks (in fact anything
3355 * you like).
3356 */
3357 if (e_user_dir_concat_static(buf, "fileman/favorites") >= sizeof(buf))
3358 return NULL;
3359 if (sd && sd->config) sd->config->view.no_typebuf_set = EINA_TRUE;
3360 ecore_file_mkpath(buf);
3361 }
3362 else if (strcmp(dev, "desktop") == 0)
3363 {
3364 /* this is a virtual device - it's where your favorites list is
3365 * stored - a dir with
3366 .desktop files or symlinks (in fact anything
3367 * you like).
3368 */
3369 if ((!path) || (!path[0]) || (!strcmp(path, "/")))
3370 {
3371 snprintf(buf, sizeof(buf), "%s", efreet_desktop_dir_get());
3372 ecore_file_mkpath(buf);
3373 }
3374 else if (path[0] == '/')
3375 snprintf(buf, sizeof(buf), "%s/%s", efreet_desktop_dir_get(), path);
3376 else
3377 {
3378 snprintf(buf, sizeof(buf), "%s-%s", efreet_desktop_dir_get(), path);
3379 ecore_file_mkpath(buf);
3380 }
3381 }
3382 else if (strcmp(dev, "temp") == 0)
3383 PRT("/tmp");
3384 /* FIXME: replace all this removable, dvd and like with hal */
3385 else if (!strncmp(dev, "removable:", sizeof("removable:") - 1))
3386 {
3387 E_Volume *v;
3388
3389 v = e_fm2_device_volume_find(dev + strlen("removable:"));
3390 if (v)
3391 {
3392 if ((!v->mount_point) && (v->efm_mode == EFM_MODE_USING_HAL_MOUNT))
3393 v->mount_point = e_fm2_device_volume_mountpoint_get(v);
3394 else if (!v->mount_point)
3395 return NULL;
3396
3397 if (PRT("%s/%s", v->mount_point, path) >= (int)sizeof(buf))
3398 return NULL;
3399 }
3400 }
3401 /* else if (CMP("dvd") || CMP("dvd-*")) */
3402 /* { */
3403 /* /\* FIXME: find dvd mountpoint optionally for dvd no. X *\/ */
3404 /* /\* maybe make part of the device mappings config? *\/ */
3405 /* } */
3406 /* else if (CMP("cd") || CMP("cd-*") || CMP("cdrom") || CMP("cdrom-*") || */
3407 /* CMP("dvd") || CMP("dvd-*")) */
3408 /* { */
3409 /* /\* FIXME: find cdrom or dvd mountpoint optionally for cd/dvd no. X *\/ */
3410 /* /\* maybe make part of the device mappings config? *\/ */
3411 /* } */
3412 }
3413 /* FIXME: add code to find USB devices (multi-card readers or single,
3414 * usb thumb drives, other usb storage devices (usb hd's etc.)
3415 */
3416 /* maybe make part of the device mappings config? */
3417 /* FIXME: add code for finding nfs shares, smb shares etc. */
3418 /* maybe make part of the device mappings config? */
3419
3420 if (buf[0] == '\0')
3421 {
3422 if (eina_strlcpy(buf, path, sizeof(buf)) >= sizeof(buf))
3423 return NULL;
3424 }
3425
3426 /* strip out excess multiple slashes */
3427 s = buf;
3428 while (*s)
3429 {
3430 while ((s[0] == '/') && (s[1] == '/'))
3431 {
3432 ss = s;
3433 do
3434 {
3435 ss[0] = ss[1];
3436 ss++;
3437 }
3438 while (*ss);
3439 }
3440 s++;
3441 }
3442 /* strip out slashes at the end - unless its just "/" */
3443 len = s - buf;
3444 while ((len > 1) && (buf[len - 1] == '/'))
3445 {
3446 buf[len - 1] = 0;
3447 len--;
3448 }
3449 return eina_stringshare_add(buf);
3450 }
3451
3452 static void
_e_fm2_file_add(Evas_Object * obj,const char * file,int unique,Eina_Stringshare * file_rel,int after,E_Fm2_Finfo * finf)3453 _e_fm2_file_add(Evas_Object *obj, const char *file, int unique, Eina_Stringshare *file_rel, int after, E_Fm2_Finfo *finf)
3454 {
3455 E_Fm2_Smart_Data *sd;
3456 E_Fm2_Icon *ic, *ic2;
3457 Eina_List *l;
3458
3459 sd = evas_object_smart_data_get(obj);
3460 if (!sd) return;
3461 /* if we only want unique icon names - if it's there - ignore */
3462 if (unique)
3463 {
3464 EINA_LIST_FOREACH(sd->icons, l, ic)
3465 {
3466 if (!strcmp(ic->info.file, file))
3467 {
3468 sd->tmp.last_insert = NULL;
3469 return;
3470 }
3471 }
3472 EINA_LIST_FOREACH(sd->queue, l, ic)
3473 {
3474 if (!strcmp(ic->info.file, file))
3475 {
3476 sd->tmp.last_insert = NULL;
3477 return;
3478 }
3479 }
3480 }
3481 /* create icon obj and append to unsorted list */
3482 ic = _e_fm2_icon_new(sd, file, finf);
3483 if (ic)
3484 {
3485 if (!file_rel)
3486 {
3487 if (ic->queued) abort();
3488 if (ic->inserted) abort();
3489 /* respekt da ordah! */
3490 if (sd->order_file)
3491 sd->queue = eina_list_append(sd->queue, ic);
3492 else
3493 {
3494 /* insertion sort it here to spread the sort load into idle time */
3495 sd->queue = eina_list_sorted_insert(sd->queue, _e_fm2_cb_icon_sort, ic);
3496 }
3497 ic->queued = EINA_TRUE;
3498 }
3499 else
3500 {
3501 if (ic->queued) abort();
3502 if (ic->inserted) abort();
3503 EINA_LIST_FOREACH(sd->icons, l, ic2)
3504 {
3505 if (ic2->info.file == file_rel)
3506 {
3507 if (after)
3508 sd->icons = eina_list_append_relative(sd->icons, ic, ic2);
3509 else
3510 sd->icons = eina_list_prepend_relative(sd->icons, ic, ic2);
3511 ic->inserted = EINA_TRUE;
3512 break;
3513 }
3514 }
3515 if (ic->inserted)
3516 {
3517 sd->icons = eina_list_append(sd->icons, ic);
3518 ic->inserted = EINA_TRUE;
3519 }
3520 sd->icons_place = eina_list_append(sd->icons_place, ic);
3521 }
3522 sd->tmp.last_insert = NULL;
3523 sd->iconlist_changed = EINA_TRUE;
3524 }
3525 }
3526
3527 static void
_e_fm2_file_del(Evas_Object * obj,const char * file)3528 _e_fm2_file_del(Evas_Object *obj, const char *file)
3529 {
3530 E_Fm2_Smart_Data *sd;
3531 E_Fm2_Icon *ic;
3532 Eina_List *l;
3533
3534 sd = evas_object_smart_data_get(obj);
3535 if (!sd) return;
3536 EINA_LIST_FOREACH(sd->icons, l, ic)
3537 {
3538 if (!strcmp(ic->info.file, file))
3539 {
3540 if (!ic->inserted) abort();
3541 sd->icons = eina_list_remove_list(sd->icons, l);
3542 ic->inserted = EINA_FALSE;
3543 sd->icons_place = eina_list_remove(sd->icons_place, ic);
3544 if (ic->region)
3545 {
3546 ic->region->list = eina_list_remove(ic->region->list, ic);
3547 ic->region = NULL;
3548 }
3549 _e_fm2_icon_free(ic);
3550 return;
3551 }
3552 }
3553 EINA_LIST_FOREACH(sd->queue, l, ic)
3554 {
3555 if (!strcmp(ic->info.file, file))
3556 {
3557 INF("MATCH!");
3558 sd->queue = eina_list_remove_list(sd->queue, l);
3559 ic->queued = EINA_FALSE;
3560 _e_fm2_icon_free(ic);
3561 return;
3562 }
3563 }
3564 }
3565
3566 static void
_e_fm_file_buffer_clear(void)3567 _e_fm_file_buffer_clear(void)
3568 {
3569 const char *s;
3570 EINA_LIST_FREE(_e_fm_file_buffer, s)
3571 eina_stringshare_del(s);
3572
3573 _e_fm_file_buffer_copying = 0;
3574 }
3575
3576 static Eina_Bool
_e_fm2_buffer_fill(Evas_Object * obj)3577 _e_fm2_buffer_fill(Evas_Object *obj)
3578 {
3579 Eina_List *sel;
3580 char buf[PATH_MAX], *pfile;
3581 int bufused, buffree;
3582 const char *real_path;
3583 const E_Fm2_Icon_Info *ici;
3584
3585 sel = e_fm2_selected_list_get(obj);
3586 if (!sel) return EINA_FALSE;
3587
3588 real_path = e_fm2_real_path_get(obj);
3589 if (!real_path) return EINA_FALSE;
3590
3591 bufused = eina_strlcpy(buf, real_path, sizeof(buf));
3592 if (bufused >= (int)sizeof(buf) - 2) return EINA_FALSE;
3593
3594 if ((bufused > 0) && (buf[bufused - 1] != '/'))
3595 {
3596 buf[bufused] = '/';
3597 bufused++;
3598 }
3599
3600 pfile = buf + bufused;
3601 buffree = sizeof(buf) - bufused;
3602
3603 EINA_LIST_FREE(sel, ici)
3604 {
3605 if (!ici) continue;
3606 if ((int)eina_strlcpy(pfile, ici->file, buffree) >= buffree) continue;
3607 _e_fm_file_buffer = eina_list_append(_e_fm_file_buffer, _e_fm2_uri_escape(buf));
3608 }
3609
3610 return EINA_TRUE;
3611 }
3612
3613 static void
_e_fm2_file_cut(Evas_Object * obj)3614 _e_fm2_file_cut(Evas_Object *obj)
3615 {
3616 _e_fm_file_buffer_clear();
3617 _e_fm2_buffer_fill(obj);
3618 }
3619
3620 static void
_e_fm2_file_copy(Evas_Object * obj)3621 _e_fm2_file_copy(Evas_Object *obj)
3622 {
3623 _e_fm_file_buffer_clear();
3624 _e_fm_file_buffer_copying = _e_fm2_buffer_fill(obj);
3625 }
3626
3627 static void
_e_fm2_file_paste(Evas_Object * obj)3628 _e_fm2_file_paste(Evas_Object *obj)
3629 {
3630 E_Fm2_Smart_Data *sd;
3631 Eina_List *paths;
3632 const char *filepath;
3633 size_t length = 0;
3634 size_t size = 0;
3635 char *args = NULL;
3636 Eina_Bool memerr = EINA_FALSE;
3637
3638 sd = evas_object_smart_data_get(obj);
3639 if (!sd) return;
3640
3641 /* Convert URI list to a list of real paths. */
3642 paths = e_fm2_uri_path_list_get(_e_fm_file_buffer);
3643 if (!paths) return;
3644 EINA_LIST_FREE(paths, filepath)
3645 {
3646 /* Get file's full path. */
3647 if (!filepath) continue;
3648 /* Check if file is protected. */
3649 if (e_filereg_file_protected(filepath))
3650 {
3651 eina_stringshare_del(filepath);
3652 continue;
3653 }
3654 /* Put filepath into a string of args.
3655 * If there are more files, put an additional space.
3656 */
3657 if (!memerr)
3658 {
3659 args = e_util_string_append_quoted(args, &size, &length, filepath);
3660 if (!args) memerr = EINA_TRUE;
3661 else
3662 {
3663 args = e_util_string_append_char(args, &size, &length, ' ');
3664 if (!args) memerr = EINA_TRUE;
3665 }
3666 }
3667 eina_stringshare_del(filepath);
3668 }
3669 if (memerr) return;
3670
3671 /* Add destination to the arguments. */
3672 {
3673 E_Fm2_Icon *ic = NULL;
3674
3675 if (eina_list_count(sd->selected_icons) == 1)
3676 {
3677 ic = eina_list_data_get(sd->selected_icons);
3678 if (ic->info.link || (!S_ISDIR(ic->info.statinfo.st_mode))) ic = NULL;
3679 }
3680 if (ic)
3681 {
3682 args = e_util_string_append_quoted(args, &size, &length, sd->realpath);
3683 if (!args) return;
3684 args = e_util_string_append_char(args, &size, &length, '/');
3685 if (!args) return;
3686 args = e_util_string_append_quoted(args, &size, &length, ic->info.file);
3687 if (!args) return;
3688 }
3689 else
3690 {
3691 args = e_util_string_append_quoted(args, &size, &length, sd->realpath);
3692 if (!args) return;
3693 }
3694 }
3695
3696 /* Roll the operation! */
3697 if (_e_fm_file_buffer_copying)
3698 {
3699 if (sd->config->view.link_drop)
3700 e_fm2_client_file_symlink(sd->obj, args);
3701 else
3702 e_fm2_client_file_copy(sd->obj, args);
3703 }
3704 else
3705 {
3706 if (sd->config->view.link_drop)
3707 e_fm2_client_file_symlink(sd->obj, args);
3708 else
3709 e_fm2_client_file_move(sd->obj, args);
3710 _e_fm_file_buffer_clear();
3711 }
3712
3713 free(args);
3714 }
3715
3716 static void
_e_fm2_file_symlink(Evas_Object * obj)3717 _e_fm2_file_symlink(Evas_Object *obj)
3718 {
3719 E_Fm2_Smart_Data *sd;
3720 Eina_List *paths;
3721 const char *filepath;
3722 size_t length = 0;
3723 size_t size = 0;
3724 char *args = NULL;
3725 Eina_Bool memerr = EINA_FALSE;
3726
3727 sd = evas_object_smart_data_get(obj);
3728 if (!sd) return;
3729
3730 /* Convert URI list to a list of real paths. */
3731 paths = e_fm2_uri_path_list_get(_e_fm_file_buffer);
3732 EINA_LIST_FREE(paths, filepath)
3733 {
3734 /* Get file's full path. */
3735 if (!filepath)
3736 continue;
3737
3738 /* Check if file is protected. */
3739 if (e_filereg_file_protected(filepath))
3740 {
3741 eina_stringshare_del(filepath);
3742 continue;
3743 }
3744
3745 /* Put filepath into a string of args.
3746 * If there are more files, put an additional space.
3747 */
3748 if (!memerr)
3749 {
3750 args = e_util_string_append_quoted(args, &size, &length, filepath);
3751 if (!args) memerr = EINA_TRUE;
3752 else
3753 {
3754 args = e_util_string_append_char(args, &size, &length, ' ');
3755 if (!args) memerr = EINA_TRUE;
3756 }
3757 }
3758
3759 eina_stringshare_del(filepath);
3760 }
3761 if (memerr) return;
3762
3763 /* Add destination to the arguments. */
3764 args = e_util_string_append_quoted(args, &size, &length, sd->realpath);
3765 if (!args) return;
3766
3767 /* Roll the operation! */
3768 if (_e_fm_file_buffer_copying) e_fm2_client_file_symlink(sd->obj, args);
3769
3770 free(args);
3771 }
3772
3773 static void
_e_fm2_file_cut_menu(void * data,E_Menu * m EINA_UNUSED,E_Menu_Item * mi EINA_UNUSED)3774 _e_fm2_file_cut_menu(void *data, E_Menu *m EINA_UNUSED, E_Menu_Item *mi EINA_UNUSED)
3775 {
3776 E_Fm2_Smart_Data *sd = data;
3777 if (!sd) return;
3778 _e_fm2_file_cut(sd->obj);
3779 }
3780
3781 static void
_e_fm2_file_copy_menu(void * data,E_Menu * m EINA_UNUSED,E_Menu_Item * mi EINA_UNUSED)3782 _e_fm2_file_copy_menu(void *data, E_Menu *m EINA_UNUSED, E_Menu_Item *mi EINA_UNUSED)
3783 {
3784 E_Fm2_Smart_Data *sd = data;
3785 if (!sd) return;
3786 _e_fm2_file_copy(sd->obj);
3787 }
3788
3789 static void
_e_fm2_file_paste_menu(void * data,E_Menu * m EINA_UNUSED,E_Menu_Item * mi EINA_UNUSED)3790 _e_fm2_file_paste_menu(void *data, E_Menu *m EINA_UNUSED, E_Menu_Item *mi EINA_UNUSED)
3791 {
3792 E_Fm2_Smart_Data *sd = data;
3793 if (!sd) return;
3794 _e_fm2_file_paste(sd->obj);
3795 }
3796
3797 static void
_e_fm2_file_symlink_menu(void * data,E_Menu * m EINA_UNUSED,E_Menu_Item * mi EINA_UNUSED)3798 _e_fm2_file_symlink_menu(void *data, E_Menu *m EINA_UNUSED, E_Menu_Item *mi EINA_UNUSED)
3799 {
3800 E_Fm2_Smart_Data *sd = data;
3801 if (!sd) return;
3802 _e_fm2_file_symlink(sd->obj);
3803 }
3804
3805 static void
_e_fm2_queue_process(Evas_Object * obj)3806 _e_fm2_queue_process(Evas_Object *obj)
3807 {
3808 E_Fm2_Smart_Data *sd;
3809 E_Fm2_Icon *ic, *ic2;
3810 Eina_List *l, **ll;
3811 int added = 0, i, p0, p1, n, v;
3812 double t;
3813 char buf[4096];
3814
3815 sd = evas_object_smart_data_get(obj);
3816 if (!sd) return;
3817 if (!sd->queue)
3818 {
3819 if (sd->resize_job) ecore_job_del(sd->resize_job);
3820 sd->resize_job = ecore_job_add(_e_fm2_cb_resize_job, obj);
3821 evas_object_smart_callback_call(sd->obj, "changed", NULL);
3822 sd->tmp.last_insert = NULL;
3823 return;
3824 }
3825 // double tt = ecore_time_get();
3826 // int queued = eina_list_count(sd->queue);
3827 /* take unsorted and insert into the icon list - reprocess regions */
3828 t = ecore_time_get();
3829 if (!sd->tmp.last_insert)
3830 {
3831 #if 1
3832 n = eina_list_count(sd->icons);
3833 E_FREE(sd->tmp.list_index);
3834 if (n > 0)
3835 sd->tmp.list_index = calloc(n, sizeof(Eina_List *));
3836 if (sd->tmp.list_index)
3837 {
3838 ll = sd->tmp.list_index;
3839 for (l = sd->icons; l; l = eina_list_next(l))
3840 {
3841 *ll = l;
3842 ll++;
3843 }
3844 /* binary search first queue */
3845 ic = eina_list_data_get(sd->queue);
3846 p0 = 0; p1 = n;
3847 i = (p0 + p1) / 2;
3848 ll = sd->tmp.list_index;
3849 if (ll[i])
3850 do /* avoid garbage deref */
3851 {
3852 ic2 = eina_list_data_get(ll[i]);
3853 v = _e_fm2_cb_icon_sort(ic, ic2);
3854 if (v < 0) /* ic should go before ic2 */
3855 p1 = i;
3856 else /* ic should go at or after ic2 */
3857 p0 = i;
3858 i = (p0 + p1) / 2;
3859 l = ll[i];
3860 }
3861 while ((p1 - p0) > 1);
3862 }
3863 else
3864 #endif
3865 l = sd->icons;
3866 }
3867 else
3868 l = sd->tmp.last_insert;
3869 while (sd->queue)
3870 {
3871 ic = sd->queue->data;
3872 sd->queue = eina_list_remove_list(sd->queue, sd->queue);
3873 /* insertion sort - better than qsort for the way we are doing
3874 * things - incrimentally scan and sort as we go as we now know
3875 * that the queue files are in order, we speed up insertions to
3876 * a worst case of O(n) where n is the # of files in the list
3877 * so far
3878 */
3879 if (sd->order_file)
3880 {
3881 l = NULL;
3882 }
3883 else
3884 {
3885 EINA_LIST_FOREACH(l, l, ic2)
3886 {
3887 if (_e_fm2_cb_icon_sort(ic, ic2) < 0)
3888 {
3889 if (!ic->queued) abort();
3890 if (ic->inserted) abort();
3891 ic->queued = EINA_FALSE;
3892 ic->inserted = EINA_TRUE;
3893 if (l == sd->icons)
3894 sd->icons = eina_list_prepend(sd->icons, ic);
3895 else
3896 sd->icons = eina_list_prepend_relative_list(sd->icons,
3897 ic, l);
3898 sd->tmp.last_insert = l;
3899 break;
3900 }
3901 }
3902 }
3903 if (!l)
3904 {
3905 if (!ic->queued) abort();
3906 if (ic->inserted) abort();
3907 ic->queued = EINA_FALSE;
3908 ic->inserted = EINA_TRUE;
3909 sd->icons = eina_list_append(sd->icons, ic);
3910 sd->tmp.last_insert = eina_list_last(sd->icons);
3911 }
3912 sd->icons_place = eina_list_append(sd->icons_place, ic);
3913 added++;
3914 /* if we spent more than 1/20th of a second inserting - give up
3915 * for now */
3916 if ((_e_fm2_toomany_get(sd)) && (!sd->toomany))
3917 {
3918 sd->toomany = EINA_TRUE;
3919 break;
3920 }
3921 if ((ecore_time_get() - t) > 0.01) break;
3922 }
3923 // printf("FM: SORT %1.3f (%i files) (%i queued, %i added) [%i iter]\n",
3924 // ecore_time_get() - tt, eina_list_count(sd->icons), queued,
3925 // added, sd->tmp.iter);
3926 sd->overlay_count = eina_list_count(sd->icons);
3927 snprintf(buf, sizeof(buf), P_("%u file", "%u files", sd->overlay_count), sd->overlay_count);
3928 edje_object_part_text_set(sd->overlay, "e.text.busy_label", buf);
3929 if (sd->resize_job) ecore_job_del(sd->resize_job);
3930 // this will handle a relayout if we have too many icons
3931 sd->resize_job = ecore_job_add(_e_fm2_cb_resize_job, obj);
3932 evas_object_smart_callback_call(sd->obj, "changed", NULL);
3933 sd->tmp.iter++;
3934 }
3935
3936 static void
_e_fm2_queue_free(Evas_Object * obj)3937 _e_fm2_queue_free(Evas_Object *obj)
3938 {
3939 E_Fm2_Smart_Data *sd;
3940 E_Fm2_Icon *ic;
3941
3942 sd = evas_object_smart_data_get(obj);
3943 if (!sd) return;
3944 /* just free the icons in the queue and the queue itself */
3945 EINA_LIST_FREE(sd->queue, ic)
3946 {
3947 if (!ic->queued) abort();
3948 if (ic->inserted) abort();
3949 ic->queued = EINA_FALSE;
3950 _e_fm2_icon_free(ic);
3951 }
3952 }
3953
3954 static void
_e_fm2_regions_free(Evas_Object * obj)3955 _e_fm2_regions_free(Evas_Object *obj)
3956 {
3957 E_Fm2_Smart_Data *sd;
3958 E_Fm2_Region *rg;
3959
3960 sd = evas_object_smart_data_get(obj);
3961 if (!sd) return;
3962 /* free up all regions */
3963 EINA_LIST_FREE(sd->regions.list, rg)
3964 _e_fm2_region_free(rg);
3965 }
3966
3967 static void
_e_fm2_regions_populate(Evas_Object * obj)3968 _e_fm2_regions_populate(Evas_Object *obj)
3969 {
3970 E_Fm2_Smart_Data *sd;
3971 Eina_List *l;
3972 E_Fm2_Region *rg;
3973 E_Fm2_Icon *ic;
3974
3975 sd = evas_object_smart_data_get(obj);
3976 if (!sd) return;
3977 /* take the icon list and split into regions */
3978 rg = NULL;
3979 evas_event_freeze(evas_object_evas_get(obj));
3980 edje_freeze();
3981 EINA_LIST_FOREACH(sd->icons, l, ic)
3982 {
3983 if (!rg)
3984 {
3985 rg = _e_fm2_region_new(sd);
3986 sd->regions.list = eina_list_append(sd->regions.list, rg);
3987 }
3988 ic->region = rg;
3989 rg->list = eina_list_append(rg->list, ic);
3990 if (rg->w == 0)
3991 {
3992 rg->x = ic->x;
3993 rg->y = ic->y;
3994 rg->w = ic->w;
3995 rg->h = ic->h;
3996 }
3997 else
3998 {
3999 if (ic->x < rg->x)
4000 {
4001 rg->w += rg->x - ic->x;
4002 rg->x = ic->x;
4003 }
4004 if ((ic->x + ic->w) > (rg->x + rg->w))
4005 {
4006 rg->w += (ic->x + ic->w) - (rg->x + rg->w);
4007 }
4008 if (ic->y < rg->y)
4009 {
4010 rg->h += rg->y - ic->y;
4011 rg->y = ic->y;
4012 }
4013 if ((ic->y + ic->h) > (rg->y + rg->h))
4014 {
4015 rg->h += (ic->y + ic->h) - (rg->y + rg->h);
4016 }
4017 }
4018 if ((int)eina_list_count(rg->list) > sd->regions.member_max)
4019 rg = NULL;
4020 }
4021 _e_fm2_regions_eval(obj);
4022 EINA_LIST_FOREACH(sd->icons, l, ic)
4023 {
4024 if ((!ic->region->realized) && (ic->realized))
4025 _e_fm2_icon_unrealize(ic);
4026 }
4027 _e_fm2_obj_icons_place(sd);
4028 edje_thaw();
4029 evas_event_thaw(evas_object_evas_get(obj));
4030 }
4031
4032 static void
_e_fm2_icons_place_icons(E_Fm2_Smart_Data * sd)4033 _e_fm2_icons_place_icons(E_Fm2_Smart_Data *sd)
4034 {
4035 Eina_List *l;
4036 E_Fm2_Icon *ic;
4037 Evas_Coord x, y, rh;
4038
4039 x = 0; y = 0;
4040 rh = 0;
4041 EINA_LIST_FOREACH(sd->icons, l, ic)
4042 {
4043 if ((x > 0) && ((x + ic->w) > sd->w))
4044 {
4045 x = 0;
4046 y += rh;
4047 rh = 0;
4048 }
4049 ic->x = x;
4050 ic->y = y;
4051 x += ic->w;
4052 sd->min.w = MAX(ic->min_w, sd->min.w);
4053 sd->min.h = MAX(ic->min_h, sd->min.h);
4054 if (ic->h > rh) rh = ic->h;
4055 if ((ic->x + ic->w) > sd->max.w) sd->max.w = ic->x + ic->w;
4056 if ((ic->y + ic->h) > sd->max.h) sd->max.h = ic->y + ic->h;
4057 }
4058 }
4059
4060 static void
_e_fm2_icons_place_grid_icons(E_Fm2_Smart_Data * sd)4061 _e_fm2_icons_place_grid_icons(E_Fm2_Smart_Data *sd)
4062 {
4063 Eina_List *l;
4064 E_Fm2_Icon *ic;
4065 Evas_Coord x, y, gw, gh;
4066 int cols = 1, col;
4067
4068 gw = 0; gh = 0;
4069 EINA_LIST_FOREACH(sd->icons, l, ic)
4070 {
4071 if (ic->w > gw) gw = ic->w;
4072 if (ic->h > gh) gh = ic->h;
4073 }
4074 if (gw > 0) cols = sd->w / gw;
4075 if (cols < 1) cols = 1;
4076 x = 0; y = 0; col = 0;
4077 EINA_LIST_FOREACH(sd->icons, l, ic)
4078 {
4079 ic->x = x + ((gw - ic->w) / 2);
4080 ic->y = y + (gh - ic->h);
4081 x += gw;
4082 col++;
4083 if (col >= cols)
4084 {
4085 col = 0;
4086 x = 0;
4087 y += gh;
4088 }
4089 if ((ic->x + ic->w) > sd->max.w) sd->max.w = ic->x + ic->w;
4090 if ((ic->y + ic->h) > sd->max.h) sd->max.h = ic->y + ic->h;
4091 sd->min.w = MAX(ic->min_w, sd->min.w);
4092 sd->min.h = MAX(ic->min_h, sd->min.h);
4093 }
4094 }
4095
4096 static int
_e_fm2_icons_icon_overlaps(E_Fm2_Icon * ic)4097 _e_fm2_icons_icon_overlaps(E_Fm2_Icon *ic)
4098 {
4099 Eina_List *l;
4100 E_Fm2_Icon *ic2;
4101
4102 /* this is really slow... when we have a lot of icons */
4103 EINA_LIST_FOREACH(ic->sd->icons, l, ic2)
4104 {
4105 if ((ic2 != ic) && (ic2->saved_pos))
4106 {
4107 if (E_INTERSECTS(ic2->x, ic2->y, ic2->w, ic2->h,
4108 ic->x, ic->y, ic->w, ic->h))
4109 return 1;
4110 }
4111 }
4112 return 0;
4113 }
4114
4115 static int
_e_fm2_icons_icon_row_ok(E_Fm2_Icon * ic)4116 _e_fm2_icons_icon_row_ok(E_Fm2_Icon *ic)
4117 {
4118 if (ic->x + ic->w > ic->sd->w) return 0;
4119 if (ic->x < 0) return 0;
4120 if (ic->y < 0) return 0;
4121 return 1;
4122 }
4123
4124 static void
_e_fm2_icon_place_relative(E_Fm2_Icon * ic,E_Fm2_Icon * icr,int xrel,int yrel,int xa,int ya)4125 _e_fm2_icon_place_relative(E_Fm2_Icon *ic, E_Fm2_Icon *icr, int xrel, int yrel, int xa, int ya)
4126 {
4127 ic->x = icr->x;
4128 ic->y = icr->y;
4129
4130 if (xrel > 0) ic->x += icr->w;
4131 else if (xrel < 0)
4132 ic->x -= ic->w;
4133 else if (xa == 1)
4134 ic->x += (icr->w - ic->w) / 2;
4135 else if (xa == 2)
4136 ic->x += icr->w - ic->w;
4137
4138 if (yrel > 0) ic->y += icr->h;
4139 else if (yrel < 0)
4140 ic->y -= ic->h;
4141 else if (ya == 1)
4142 ic->y += (icr->h - ic->h) / 2;
4143 else if (ya == 2)
4144 ic->y += icr->h - ic->h;
4145 }
4146
4147 static void
_e_fm2_icons_place_icon(E_Fm2_Icon * ic)4148 _e_fm2_icons_place_icon(E_Fm2_Icon *ic)
4149 {
4150 Eina_List *l;
4151 E_Fm2_Icon *ic2;
4152
4153 ic->x = 0;
4154 ic->y = 0;
4155 ic->saved_pos = EINA_TRUE;
4156 /* ### BLAH ### */
4157 // if (!_e_fm2_icons_icon_overlaps(ic)) return;
4158 /*
4159 _e_fm2_icon_place_relative(ic, ic2, 1, 0, 0, 2);
4160 if (_e_fm2_icons_icon_row_ok(ic) && !_e_fm2_icons_icon_overlaps(ic)) return;
4161 _e_fm2_icon_place_relative(ic, ic2, 0, -1, 0, 0);
4162 if (_e_fm2_icons_icon_row_ok(ic) && !_e_fm2_icons_icon_overlaps(ic)) return;
4163 _e_fm2_icon_place_relative(ic, ic2, 0, -1, 1, 0);
4164 if (_e_fm2_icons_icon_row_ok(ic) && !_e_fm2_icons_icon_overlaps(ic)) return;
4165 _e_fm2_icon_place_relative(ic, ic2, 1, 0, 0, 0);
4166 if (_e_fm2_icons_icon_row_ok(ic) && !_e_fm2_icons_icon_overlaps(ic)) return;
4167 _e_fm2_icon_place_relative(ic, ic2, 1, 0, 0, 1);
4168 if (_e_fm2_icons_icon_row_ok(ic) && !_e_fm2_icons_icon_overlaps(ic)) return;
4169 _e_fm2_icon_place_relative(ic, ic2, 0, 1, 0, 0);
4170 if (_e_fm2_icons_icon_row_ok(ic) && !_e_fm2_icons_icon_overlaps(ic)) return;
4171 _e_fm2_icon_place_relative(ic, ic2, 0, 1, 1, 0);
4172 if (_e_fm2_icons_icon_row_ok(ic) && !_e_fm2_icons_icon_overlaps(ic)) return;
4173 */
4174 if ((ic->sd->last_placed) && (ic->sd->toomany))
4175 {
4176 ic2 = ic->sd->last_placed;
4177 // ###_
4178 _e_fm2_icon_place_relative(ic, ic2, 1, 0, 0, 2);
4179 if (_e_fm2_icons_icon_row_ok(ic) &&
4180 !_e_fm2_icons_icon_overlaps(ic)) goto done;
4181 // _###
4182 _e_fm2_icon_place_relative(ic, ic2, -1, 0, 0, 2);
4183 if (_e_fm2_icons_icon_row_ok(ic) &&
4184 !_e_fm2_icons_icon_overlaps(ic)) goto done;
4185 // ###
4186 // |
4187 _e_fm2_icon_place_relative(ic, ic2, 0, 1, 1, 0);
4188 if (_e_fm2_icons_icon_row_ok(ic) &&
4189 !_e_fm2_icons_icon_overlaps(ic)) goto done;
4190 // |
4191 // ###
4192 _e_fm2_icon_place_relative(ic, ic2, 0, -1, 1, 0);
4193 if (_e_fm2_icons_icon_row_ok(ic) &&
4194 !_e_fm2_icons_icon_overlaps(ic)) goto done;
4195 // do this anyway - dont care.
4196 // ###
4197 // |
4198 _e_fm2_icon_place_relative(ic, ic2, 0, 1, 1, 0);
4199 ic->x = 0;
4200 goto done;
4201 }
4202 EINA_LIST_FOREACH(ic->sd->icons, l, ic2)
4203 {
4204 if ((ic2 != ic) && (ic2->saved_pos))
4205 {
4206 // ###_
4207 _e_fm2_icon_place_relative(ic, ic2, 1, 0, 0, 2);
4208 if (_e_fm2_icons_icon_row_ok(ic) &&
4209 !_e_fm2_icons_icon_overlaps(ic)) goto done;
4210 // _###
4211 _e_fm2_icon_place_relative(ic, ic2, -1, 0, 0, 2);
4212 if (_e_fm2_icons_icon_row_ok(ic) &&
4213 !_e_fm2_icons_icon_overlaps(ic)) goto done;
4214 }
4215 }
4216
4217 EINA_LIST_FOREACH(ic->sd->icons, l, ic2)
4218 {
4219 if ((ic2 != ic) && (ic2->saved_pos))
4220 {
4221 // ###
4222 // |
4223 _e_fm2_icon_place_relative(ic, ic2, 0, 1, 1, 0);
4224 if (_e_fm2_icons_icon_row_ok(ic) &&
4225 !_e_fm2_icons_icon_overlaps(ic)) goto done;
4226 // |
4227 // ###
4228 _e_fm2_icon_place_relative(ic, ic2, 0, -1, 1, 0);
4229 if (_e_fm2_icons_icon_row_ok(ic) &&
4230 !_e_fm2_icons_icon_overlaps(ic)) goto done;
4231 }
4232 if ((ic2 != ic) && (ic2->saved_pos))
4233 {
4234 // TODO: if uncomment this, change EINA_LIST_FOREACH to EINA_LIST_FOREACH_SAFE!
4235 // ic->sd->icons_place = eina_list_remove_list(ic->sd->icons_place, pl);
4236 }
4237 }
4238 done:
4239 ic->sd->last_placed = ic;
4240 return;
4241 }
4242
4243 static void
_e_fm2_icons_place_custom_icons(E_Fm2_Smart_Data * sd)4244 _e_fm2_icons_place_custom_icons(E_Fm2_Smart_Data *sd)
4245 {
4246 Eina_List *l;
4247 E_Fm2_Icon *ic;
4248
4249 EINA_LIST_FOREACH(sd->icons, l, ic)
4250 {
4251 if (!ic->saved_pos)
4252 {
4253 /* FIXME: place using smart place fn */
4254 _e_fm2_icons_place_icon(ic);
4255 }
4256
4257 if ((ic->x + ic->w) > sd->max.w) sd->max.w = ic->x + ic->w;
4258 if ((ic->y + ic->h) > sd->max.h) sd->max.h = ic->y + ic->h;
4259 sd->min.w = MAX(ic->min_w, sd->min.w);
4260 sd->min.h = MAX(ic->min_h, sd->min.h);
4261 }
4262 }
4263
4264 static void
_e_fm2_icons_place_custom_grid_icons(E_Fm2_Smart_Data * sd)4265 _e_fm2_icons_place_custom_grid_icons(E_Fm2_Smart_Data *sd)
4266 {
4267 /* FIXME: not going to implement this at this stage */
4268 Eina_List *l;
4269 E_Fm2_Icon *ic;
4270
4271 EINA_LIST_FOREACH(sd->icons, l, ic)
4272 {
4273 if (!ic->saved_pos)
4274 {
4275 /* FIXME: place using grid fn */
4276 }
4277
4278 if ((ic->x + ic->w) > sd->max.w) sd->max.w = ic->x + ic->w;
4279 if ((ic->y + ic->h) > sd->max.h) sd->max.h = ic->y + ic->h;
4280 sd->min.w = MAX(ic->min_w, sd->min.w);
4281 sd->min.h = MAX(ic->min_h, sd->min.h);
4282 }
4283 }
4284
4285 static void
_e_fm2_icons_place_custom_smart_grid_icons(E_Fm2_Smart_Data * sd)4286 _e_fm2_icons_place_custom_smart_grid_icons(E_Fm2_Smart_Data *sd)
4287 {
4288 /* FIXME: not going to implement this at this stage */
4289 Eina_List *l;
4290 E_Fm2_Icon *ic;
4291
4292 EINA_LIST_FOREACH(sd->icons, l, ic)
4293 {
4294 if (!ic->saved_pos)
4295 {
4296 /* FIXME: place using smart grid fn */
4297 }
4298
4299 if ((ic->x + ic->w) > sd->max.w) sd->max.w = ic->x + ic->w;
4300 if ((ic->y + ic->h) > sd->max.h) sd->max.h = ic->y + ic->h;
4301 sd->min.w = MAX(ic->min_w, sd->min.w);
4302 sd->min.h = MAX(ic->min_h, sd->min.h);
4303 }
4304 }
4305
4306 static void
_e_fm2_icons_place_list(E_Fm2_Smart_Data * sd)4307 _e_fm2_icons_place_list(E_Fm2_Smart_Data *sd)
4308 {
4309 Eina_List *l;
4310 E_Fm2_Icon *ic;
4311 Evas_Coord x, y;
4312 int w, i;
4313
4314 w = i = x = y = 0;
4315 EINA_LIST_FOREACH(sd->icons, l, ic)
4316 {
4317 ic->x = x;
4318 ic->y = y;
4319 sd->min.w = MAX(ic->min_w, sd->min.w);
4320 sd->min.h = MAX(ic->min_h, sd->min.h);
4321 if (sd->w > ic->min_w)
4322 ic->w = sd->w;
4323 else
4324 ic->w = ic->min_w;
4325 y += ic->h;
4326 ic->odd = (i & 0x01);
4327 if ((ic->w != sd->w) && ((ic->x + ic->w) > sd->max.w)) sd->max.w = ic->x + ic->w;
4328 else if (ic->min_w > sd->max.w)
4329 sd->max.w = ic->min_w;
4330 if ((ic->y + ic->h) > sd->max.h) sd->max.h = ic->y + ic->h;
4331 w = MAX(w, ic->min_w);
4332 w = MAX(w, sd->w);
4333 i++;
4334 }
4335 EINA_LIST_FOREACH(sd->icons, l, ic)
4336 ic->w = w;
4337 }
4338
4339 static void
_e_fm2_icons_place(Evas_Object * obj)4340 _e_fm2_icons_place(Evas_Object *obj)
4341 {
4342 E_Fm2_Smart_Data *sd;
4343
4344 sd = evas_object_smart_data_get(obj);
4345 if (!sd) return;
4346 /* take the icon list and find a location for them */
4347 sd->max.w = 0;
4348 sd->max.h = 0;
4349 switch (_e_fm2_view_mode_get(sd))
4350 {
4351 case E_FM2_VIEW_MODE_ICONS:
4352 _e_fm2_icons_place_icons(sd);
4353 // sd->max.h += ICON_BOTTOM_SPACE;
4354 break;
4355
4356 case E_FM2_VIEW_MODE_GRID_ICONS:
4357 _e_fm2_icons_place_grid_icons(sd);
4358 // sd->max.h += ICON_BOTTOM_SPACE;
4359 break;
4360
4361 case E_FM2_VIEW_MODE_CUSTOM_ICONS:
4362 _e_fm2_icons_place_custom_icons(sd);
4363 // sd->max.h += ICON_BOTTOM_SPACE;
4364 break;
4365
4366 case E_FM2_VIEW_MODE_CUSTOM_GRID_ICONS:
4367 /* FIXME: not going to implement this at this stage */
4368 _e_fm2_icons_place_custom_grid_icons(sd);
4369 // sd->max.h += ICON_BOTTOM_SPACE;
4370 break;
4371
4372 case E_FM2_VIEW_MODE_CUSTOM_SMART_GRID_ICONS:
4373 /* FIXME: not going to implement this at this stage */
4374 _e_fm2_icons_place_custom_smart_grid_icons(sd);
4375 // sd->max.h += ICON_BOTTOM_SPACE;
4376 break;
4377
4378 case E_FM2_VIEW_MODE_LIST:
4379 _e_fm2_icons_place_list(sd);
4380 break;
4381
4382 default:
4383 break;
4384 }
4385 /* tell our parent scrollview - if any, that we have changed */
4386 evas_object_smart_callback_call(sd->obj, "changed", NULL);
4387 }
4388
4389 static void
_e_fm2_icons_free(Evas_Object * obj)4390 _e_fm2_icons_free(Evas_Object *obj)
4391 {
4392 E_Fm2_Smart_Data *sd;
4393 E_Fm2_Icon *ic;
4394
4395 sd = evas_object_smart_data_get(obj);
4396 if (!sd) return;
4397 _e_fm2_queue_free(obj);
4398 /* free all icons */
4399 EINA_LIST_FREE(sd->icons, ic)
4400 {
4401 if (ic->queued) abort();
4402 if (!ic->inserted) abort();
4403 ic->inserted = EINA_FALSE;
4404 _e_fm2_icon_free(ic);
4405 }
4406 sd->last_selected = NULL;
4407 sd->range_selected = NULL;
4408 eina_list_free(sd->icons_place);
4409 sd->icons_place = NULL;
4410 sd->tmp.last_insert = NULL;
4411 E_FREE(sd->tmp.list_index);
4412 }
4413
4414 static void
_e_fm2_regions_eval(Evas_Object * obj)4415 _e_fm2_regions_eval(Evas_Object *obj)
4416 {
4417 E_Fm2_Smart_Data *sd;
4418 Eina_List *l;
4419 E_Fm2_Region *rg;
4420
4421 sd = evas_object_smart_data_get(obj);
4422 if (!sd) return;
4423 EINA_LIST_FOREACH(sd->regions.list, l, rg)
4424 {
4425 if (_e_fm2_region_visible(rg))
4426 _e_fm2_region_realize(rg);
4427 else
4428 _e_fm2_region_unrealize(rg);
4429 }
4430 }
4431
4432 static void
_e_fm2_config_free(E_Fm2_Config * cfg)4433 _e_fm2_config_free(E_Fm2_Config *cfg)
4434 {
4435 if (cfg->icon.key_hint) eina_stringshare_del(cfg->icon.key_hint);
4436 if (cfg->theme.background) eina_stringshare_del(cfg->theme.background);
4437 if (cfg->theme.frame) eina_stringshare_del(cfg->theme.frame);
4438 if (cfg->theme.icons) eina_stringshare_del(cfg->theme.icons);
4439 free(cfg);
4440 }
4441
4442 static Eina_List *
_e_fm2_file_fm2_find(const char * file)4443 _e_fm2_file_fm2_find(const char *file)
4444 {
4445 char *dir;
4446 Eina_List *l, *ret = NULL;
4447 Evas_Object *obj;
4448
4449 dir = ecore_file_dir_get(file);
4450 if (!dir) return NULL;
4451 EINA_LIST_FOREACH(_e_fm2_list, l, obj)
4452 {
4453 if ((_e_fm2_list_walking > 0) &&
4454 (eina_list_data_find(_e_fm2_list_remove, obj))) continue;
4455 if (!strcmp(e_fm2_real_path_get(obj), dir))
4456 ret = eina_list_append(ret, obj);
4457 }
4458 free(dir);
4459 return ret;
4460 }
4461
4462 static E_Fm2_Icon *
_e_fm2_icon_find(Evas_Object * obj,const char * file)4463 _e_fm2_icon_find(Evas_Object *obj, const char *file)
4464 {
4465 E_Fm2_Smart_Data *sd;
4466 Eina_List *l;
4467 E_Fm2_Icon *ic;
4468
4469 sd = evas_object_smart_data_get(obj);
4470 if (!sd) return NULL;
4471 EINA_LIST_FOREACH(sd->icons, l, ic)
4472 {
4473 if (!strcmp(ic->info.file, file)) return ic;
4474 }
4475 return NULL;
4476 }
4477
4478 /* Escape illegal caracters within an uri and return an eina_stringshare */
4479 static const char *
_e_fm2_uri_escape(const char * path)4480 _e_fm2_uri_escape(const char *path)
4481 {
4482 char dest[PATH_MAX * 3 + 7];
4483 const char *p;
4484 int i;
4485
4486 if (!path) return NULL;
4487 memset(dest, 0, PATH_MAX * 3 + 7);
4488
4489 snprintf(dest, 8, "file://");
4490
4491 /* Most app doesn't handle the hostname in the uri so it's put to NULL */
4492 for (i = 7, p = path; *p != '\0'; p++, i++)
4493 {
4494 if (isalnum(*p) || strchr("/$-_.+!*'()", *p))
4495 dest[i] = *p;
4496 else
4497 {
4498 snprintf(&(dest[i]), 4, "%%%02X", (unsigned char)*p);
4499 i += 2;
4500 }
4501 }
4502
4503 return eina_stringshare_add(dest);
4504 }
4505
4506 /* Parse a single uri and return an E_Fm2_Uri struct.
4507 * If the parsing have failed it return NULL.
4508 * The E_Fm2_Uri may have hostname parameter and always a path.
4509 * If there's no hostname in the uri then the hostname parameter is NULL
4510 */
4511 static E_Fm2_Uri *
_e_fm2_uri_parse(const char * val)4512 _e_fm2_uri_parse(const char *val)
4513 {
4514 E_Fm2_Uri *uri;
4515 const char *p;
4516 char hostname[PATH_MAX], path[PATH_MAX];
4517 int i = 0;
4518
4519 /* if value is a raw path: /path/to/blah just return it */
4520 if (val[0] == '/')
4521 {
4522 uri = E_NEW(E_Fm2_Uri, 1);
4523 uri->hostname = NULL;
4524 uri->path = eina_stringshare_add(val);
4525 return uri;
4526 }
4527 /* The shortest possible path is file:///
4528 * anything smaller than that can't be a valid uri
4529 */
4530 if (strlen(val) <= 7 && strncmp(val, "file://", 7)) return NULL;
4531 memset(path, 0, PATH_MAX);
4532
4533 /* An uri should be in a form file://<hostname>/<path> */
4534 p = val + 7;
4535 if (*p != '/')
4536 {
4537 for (i = 0; *p != '/' && *p != '\0' && i < _POSIX_HOST_NAME_MAX; p++, i++)
4538 hostname[i] = *p;
4539 }
4540 hostname[i] = '\0';
4541
4542 /* See http://www.faqs.org/rfcs/rfc1738.html for the escaped chars */
4543 for (i = 0; (*p != '\0') && (i < (PATH_MAX - 1)); i++, p++)
4544 {
4545 if (*p == '%')
4546 {
4547 path[i] = *(++p);
4548 path[i + 1] = *(++p);
4549 path[i] = (char)strtol(&(path[i]), NULL, 16);
4550 path[i + 1] = '\0';
4551 }
4552 else
4553 path[i] = *p;
4554 }
4555
4556 uri = E_NEW(E_Fm2_Uri, 1);
4557 if (hostname[0]) uri->hostname = eina_stringshare_add(hostname);
4558 else uri->hostname = NULL;
4559 uri->path = eina_stringshare_add(path);
4560
4561 return uri;
4562 }
4563
4564 /* Takes an Eina_List of uri and return an Eina_List of real paths */
4565 static Eina_List *
_e_fm2_uri_selected_icon_list_get(Eina_List * uri)4566 _e_fm2_uri_selected_icon_list_get(Eina_List *uri)
4567 {
4568 Eina_List *icons = NULL;
4569 Eina_List *l;
4570 const char *path;
4571
4572 EINA_LIST_FOREACH(uri, l, path)
4573 {
4574 Eina_List *fms;
4575 Evas_Object *fm;
4576 E_Fm2_Icon *ic;
4577
4578 fms = _e_fm2_file_fm2_find(path);
4579 if (!fms) continue;
4580 ic = NULL;
4581 EINA_LIST_FREE(fms, fm)
4582 {
4583 ic = _e_fm2_icon_find(fm, ecore_file_file_get(path));
4584 if (!ic) continue;
4585 if (eina_list_data_find(ic->sd->selected_icons, ic)) break;
4586 ic = NULL;
4587 }
4588 if (ic) icons = eina_list_append(icons, ic);
4589 }
4590 return icons;
4591 }
4592
4593 /**************************/
4594
4595 static E_Fm2_Icon *
_e_fm2_icon_new(E_Fm2_Smart_Data * sd,const char * file,E_Fm2_Finfo * finf)4596 _e_fm2_icon_new(E_Fm2_Smart_Data *sd, const char *file, E_Fm2_Finfo *finf)
4597 {
4598 E_Fm2_Icon *ic;
4599
4600 /* create icon */
4601 ic = E_NEW(E_Fm2_Icon, 1);
4602 ic->info.fm = sd->obj;
4603 ic->info.ic = ic;
4604 ic->info.file = eina_stringshare_add(file);
4605 ic->sd = sd;
4606 if (!_e_fm2_icon_fill(ic, finf))
4607 {
4608 eina_stringshare_del(ic->info.file);
4609 free(ic);
4610 return NULL;
4611 }
4612 return ic;
4613 }
4614
4615 static void
_e_fm2_icon_unfill(E_Fm2_Icon * ic)4616 _e_fm2_icon_unfill(E_Fm2_Icon *ic)
4617 {
4618 eina_stringshare_del(ic->info.mime);
4619 eina_stringshare_del(ic->info.label);
4620 eina_stringshare_del(ic->info.comment);
4621 eina_stringshare_del(ic->info.generic);
4622 eina_stringshare_del(ic->info.icon);
4623 eina_stringshare_del(ic->info.link);
4624 eina_stringshare_del(ic->info.real_link);
4625 eina_stringshare_del(ic->info.category);
4626 ic->info.mime = NULL;
4627 ic->info.label = NULL;
4628 ic->info.comment = NULL;
4629 ic->info.generic = NULL;
4630 ic->info.icon = NULL;
4631 ic->info.link = NULL;
4632 ic->info.real_link = NULL;
4633 ic->info.mount = EINA_FALSE;
4634 ic->info.removable = EINA_FALSE;
4635 ic->info.removable_full = EINA_FALSE;
4636 ic->info.deleted = EINA_FALSE;
4637 ic->info.broken_link = EINA_FALSE;
4638 }
4639
4640 static void
_e_fm2_icon_geom_adjust(E_Fm2_Icon * ic,int saved_x,int saved_y,int saved_w EINA_UNUSED,int saved_h EINA_UNUSED,int saved_res_w,int saved_res_h)4641 _e_fm2_icon_geom_adjust(E_Fm2_Icon *ic, int saved_x, int saved_y, int saved_w EINA_UNUSED, int saved_h EINA_UNUSED, int saved_res_w, int saved_res_h)
4642 {
4643 int qx, qy, rx, ry, x, y;
4644
4645 if (!((_e_fm2_view_mode_get(ic->sd) == E_FM2_VIEW_MODE_CUSTOM_ICONS) &&
4646 (ic->sd->config->view.fit_custom_pos) &&
4647 (saved_res_w > 0) &&
4648 (saved_res_h > 0)))
4649 return;
4650 if (saved_res_w >= 3) qx = saved_x / (saved_res_w / 3);
4651 else qx = 0;
4652 rx = saved_x - ((saved_res_w / 2) * qx);
4653 x = ((ic->sd->w / 2) * qx) + rx;
4654 ic->x = x;
4655
4656 if (saved_res_h >= 3) qy = saved_y / (saved_res_h / 3);
4657 else qy = 0;
4658 ry = saved_y - ((saved_res_h / 2) * qy);
4659 y = ((ic->sd->h / 2) * qy) + ry;
4660 ic->y = y;
4661 }
4662
4663 static const char *
_mime_get(const char * path)4664 _mime_get(const char *path)
4665 {
4666 const char *mime = efreet_mime_special_type_get(path);
4667 if (!mime) mime = efreet_mime_globs_type_get(path);
4668 if (!mime) mime = efreet_mime_fallback_type_get(path);
4669 return mime;
4670 }
4671
4672 static int
_e_fm2_icon_fill(E_Fm2_Icon * ic,E_Fm2_Finfo * finf)4673 _e_fm2_icon_fill(E_Fm2_Icon *ic, E_Fm2_Finfo *finf)
4674 {
4675 Evas_Coord mw = 0, mh = 0;
4676 Evas_Object *obj, *obj2;
4677 char buf[PATH_MAX];
4678 const char *mime;
4679 E_Fm2_Custom_File *cf;
4680
4681 if (!finf) return 0;
4682 if (!_e_fm2_icon_realpath(ic, buf, sizeof(buf)))
4683 return 0;
4684 cf = e_fm2_custom_file_get(buf);
4685 memcpy(&(ic->info.statinfo), &(finf->st), sizeof(struct stat));
4686 if ((finf->lnk) && (finf->lnk[0]))
4687 ic->info.link = eina_stringshare_add(finf->lnk);
4688 else
4689 ic->info.link = NULL;
4690 if ((finf->rlnk) && (finf->rlnk[0]))
4691 ic->info.real_link = eina_stringshare_add(finf->rlnk);
4692 else
4693 ic->info.real_link = NULL;
4694 ic->info.broken_link = finf->broken_link;
4695
4696 if ((!ic->info.link) && (S_ISDIR(ic->info.statinfo.st_mode)))
4697 {
4698 ic->info.mime = eina_stringshare_ref(_e_fm2_mime_inode_directory);
4699 }
4700 else if (ic->info.real_link)
4701 {
4702 mime = _mime_get(ic->info.real_link);
4703 if (!mime)
4704 /* XXX REMOVE/DEPRECATE ME LATER */
4705 mime = e_fm_mime_filename_get(ic->info.file);
4706 if (mime) ic->info.mime = eina_stringshare_add(mime);
4707 }
4708
4709 if (!ic->info.mime)
4710 {
4711 mime = _mime_get(buf);
4712 if (!mime)
4713 /* XXX REMOVE/DEPRECATE ME LATER */
4714 mime = e_fm_mime_filename_get(ic->info.file);
4715 if (mime) ic->info.mime = eina_stringshare_add(mime);
4716 }
4717
4718 if (_e_fm2_file_is_desktop(ic->info.file))
4719 _e_fm2_icon_desktop_load(ic);
4720
4721 if (cf)
4722 {
4723 if (cf->icon.valid)
4724 {
4725 if (cf->icon.icon)
4726 {
4727 eina_stringshare_replace(&ic->info.icon, cf->icon.icon);
4728 }
4729 ic->info.icon_type = cf->icon.type;
4730 }
4731 if (cf->geom.valid)
4732 {
4733 ic->saved_pos = EINA_TRUE;
4734 ic->x = cf->geom.x;
4735 ic->y = cf->geom.y;
4736 if (cf->geom.w > 0) ic->w = cf->geom.w;
4737 if (cf->geom.h > 0) ic->h = cf->geom.h;
4738 _e_fm2_icon_geom_adjust(ic, cf->geom.x, cf->geom.y, cf->geom.w, cf->geom.h, cf->geom.res_w, cf->geom.res_h);
4739 }
4740 }
4741
4742 evas_event_freeze(evas_object_evas_get(ic->sd->obj));
4743 edje_freeze();
4744
4745 switch (_e_fm2_view_mode_get(ic->sd))
4746 {
4747 case E_FM2_VIEW_MODE_ICONS:
4748 case E_FM2_VIEW_MODE_GRID_ICONS:
4749 case E_FM2_VIEW_MODE_CUSTOM_ICONS:
4750 case E_FM2_VIEW_MODE_CUSTOM_GRID_ICONS:
4751 case E_FM2_VIEW_MODE_CUSTOM_SMART_GRID_ICONS:
4752 /* FIXME: need to define icon edjes. here goes:
4753 *
4754 * fileman/icon/fixed
4755 * fileman/icon/variable
4756 * fileman/list/fixed
4757 * fileman/list/variable
4758 * fileman/list_odd/fixed
4759 * fileman/list_odd/variable
4760 *
4761 */
4762 if ((!ic->sd->config->icon.fixed.w) || (!ic->sd->config->icon.fixed.h))
4763 {
4764 obj = ic->sd->tmp.obj;
4765 if (!obj)
4766 {
4767 obj = edje_object_add(evas_object_evas_get(ic->sd->obj));
4768 if ((ic->sd->config->icon.fixed.w) && (ic->sd->config->icon.fixed.h))
4769 _e_fm2_theme_edje_object_set(ic->sd, obj,
4770 "base/theme/fileman",
4771 "icon/fixed");
4772 else
4773 _e_fm2_theme_edje_object_set(ic->sd, obj,
4774 "base/theme/fileman",
4775 "icon/variable");
4776 ic->sd->tmp.obj = obj;
4777 }
4778 _e_fm2_icon_label_set(ic, obj);
4779 obj2 = ic->sd->tmp.obj2;
4780 if (!obj2)
4781 {
4782 obj2 = evas_object_rectangle_add(evas_object_evas_get(ic->sd->obj));
4783 ic->sd->tmp.obj2 = obj2;
4784 }
4785 /* FIXME: if icons are allowed to have their own size - use it */
4786 evas_object_size_hint_min_set(obj2, _e_fm2_icon_w_get(ic->sd), _e_fm2_icon_h_get(ic->sd));
4787 evas_object_size_hint_max_set(obj2, _e_fm2_icon_w_get(ic->sd), _e_fm2_icon_h_get(ic->sd));
4788 edje_object_part_swallow(obj, "e.swallow.icon", obj2);
4789 edje_object_size_min_calc(obj, &mw, &mh);
4790 }
4791 ic->w = mw;
4792 ic->h = mh;
4793 if (ic->sd->config->icon.fixed.w) ic->w = _e_fm2_icon_w_get(ic->sd);
4794 if (ic->sd->config->icon.fixed.h) ic->h = _e_fm2_icon_h_get(ic->sd);
4795 ic->min_w = mw;
4796 ic->min_h = mh;
4797 break;
4798
4799 case E_FM2_VIEW_MODE_LIST:
4800 obj = ic->sd->tmp.obj;
4801 if (!obj)
4802 {
4803 obj = edje_object_add(evas_object_evas_get(ic->sd->obj));
4804 // vairable sized list items are pretty usless - ignore.
4805 // if (ic->sd->config->icon.fixed.w)
4806 _e_fm2_theme_edje_object_set(ic->sd, obj,
4807 "base/theme/fileman",
4808 "list/fixed");
4809 // else
4810 // _e_fm2_theme_edje_object_set(ic->sd, obj, "base/theme/fileman",
4811 // "list/variable");
4812 ic->sd->tmp.obj = obj;
4813 }
4814 _e_fm2_icon_label_set(ic, obj);
4815 obj2 = ic->sd->tmp.obj2;
4816 if (!obj2)
4817 {
4818 obj2 = evas_object_rectangle_add(evas_object_evas_get(ic->sd->obj));
4819 ic->sd->tmp.obj2 = obj2;
4820 }
4821 evas_object_size_hint_min_set(obj2, ic->sd->config->icon.list.w, ic->sd->config->icon.list.h);
4822 evas_object_size_hint_max_set(obj2, ic->sd->config->icon.list.w, ic->sd->config->icon.list.h);
4823 edje_object_part_swallow(obj, "e.swallow.icon", obj2);
4824 edje_object_size_min_calc(obj, &mw, &mh);
4825 ic->w = MAX(mw, ic->sd->w);
4826 ic->h = mh;
4827 ic->min_w = mw;
4828 ic->min_h = mh;
4829 break;
4830
4831 default:
4832 break;
4833 }
4834 edje_thaw();
4835 evas_event_thaw(evas_object_evas_get(ic->sd->obj));
4836 return 1;
4837 }
4838
4839 static void
_e_fm2_icon_free(E_Fm2_Icon * ic)4840 _e_fm2_icon_free(E_Fm2_Icon *ic)
4841 {
4842 if (ic->queued) abort();
4843 if (ic->inserted) abort();
4844 if (ic->eio)
4845 {
4846 eio_file_cancel(ic->eio);
4847 ic->eio = NULL;
4848 }
4849 /* free icon, object data etc. etc. */
4850 if (ic->sd->last_placed == ic)
4851 {
4852 ic->sd->last_placed = NULL;
4853 }
4854 if (ic->sd->drop_icon == ic)
4855 {
4856 /* FIXME: call hide call */
4857 ic->sd->drop_icon = NULL;
4858 }
4859 _e_fm2_icon_unrealize(ic);
4860 if (ic->menu)
4861 {
4862 e_menu_post_deactivate_callback_set(ic->menu, NULL, NULL);
4863 e_object_del(E_OBJECT(ic->menu));
4864 ic->menu = NULL;
4865 }
4866 if (ic->dialog)
4867 {
4868 e_object_del(E_OBJECT(ic->dialog));
4869 ic->dialog = NULL;
4870 }
4871 if (ic->entry_dialog)
4872 {
4873 e_object_del(E_OBJECT(ic->entry_dialog));
4874 ic->entry_dialog = NULL;
4875 }
4876 if (ic->entry_widget)
4877 _e_fm2_icon_entry_widget_del(ic);
4878 if (ic->prop_dialog)
4879 {
4880 e_object_del(E_OBJECT(ic->prop_dialog));
4881 ic->prop_dialog = NULL;
4882 }
4883 if (ic->mount)
4884 e_fm2_device_unmount(ic->mount);
4885 if (ic->mount_timer) ecore_timer_del(ic->mount_timer);
4886 if (ic->selected)
4887 ic->sd->selected_icons = eina_list_remove(ic->sd->selected_icons, ic);
4888 if (ic->drag.dnd_end_timer)
4889 ecore_timer_del(ic->drag.dnd_end_timer);
4890 eina_stringshare_del(ic->info.file);
4891 eina_stringshare_del(ic->info.mime);
4892 eina_stringshare_del(ic->info.label);
4893 eina_stringshare_del(ic->info.comment);
4894 eina_stringshare_del(ic->info.generic);
4895 eina_stringshare_del(ic->info.icon);
4896 eina_stringshare_del(ic->info.link);
4897 eina_stringshare_del(ic->info.real_link);
4898 eina_stringshare_del(ic->info.category);
4899 memset(ic, 0xff, sizeof(*ic));
4900 free(ic);
4901 }
4902
4903 static void
_e_fm2_icon_label_click(void * data,Evas_Object * obj EINA_UNUSED,const char * emission EINA_UNUSED,const char * source EINA_UNUSED)4904 _e_fm2_icon_label_click(void *data, Evas_Object *obj EINA_UNUSED, const char *emission EINA_UNUSED, const char *source EINA_UNUSED)
4905 {
4906 E_Fm2_Icon *ic = data;
4907 if (ic->entry_widget || ic->entry_dialog) return;
4908 if (!ic->selected) return;
4909 if (ecore_loop_time_get() - ic->selected_time < 0.2) return;
4910
4911 if (ic->sd->config->view.no_click_rename) return;
4912 if (eina_list_count(ic->sd->selected_icons) != 1) return;
4913 if (eina_list_data_get(ic->sd->selected_icons) != ic) return;
4914 _e_fm2_file_rename(ic, NULL, NULL);
4915 }
4916
4917 static void
_e_fm2_icon_realize(E_Fm2_Icon * ic)4918 _e_fm2_icon_realize(E_Fm2_Icon *ic)
4919 {
4920 if (ic->realized) goto new_file;
4921 /* actually create evas objects etc. */
4922 ic->realized = EINA_TRUE;
4923 evas_event_freeze(evas_object_evas_get(ic->sd->obj));
4924 ic->obj = edje_object_add(evas_object_evas_get(ic->sd->obj));
4925 edje_object_freeze(ic->obj);
4926 evas_object_smart_member_add(ic->obj, ic->sd->obj);
4927 evas_object_stack_below(ic->obj, ic->sd->drop);
4928 if (_e_fm2_view_mode_get(ic->sd) == E_FM2_VIEW_MODE_LIST)
4929 {
4930 const char *stacking;
4931
4932 // if (ic->sd->config->icon.fixed.w)
4933 // {
4934 if (ic->odd)
4935 _e_fm2_theme_edje_object_set(ic->sd, ic->obj,
4936 "base/theme/widgets",
4937 "list_odd/fixed");
4938 else
4939 _e_fm2_theme_edje_object_set(ic->sd, ic->obj,
4940 "base/theme/widgets",
4941 "list/fixed");
4942 stacking = edje_object_data_get(ic->obj, "stacking");
4943 if (stacking)
4944 {
4945 if (!strcmp(stacking, "below"))
4946 evas_object_stack_above(ic->obj, ic->sd->underlay);
4947 else if (!strcmp(stacking, "above"))
4948 evas_object_stack_below(ic->obj, ic->sd->drop);
4949 }
4950
4951 // }
4952 // else
4953 // {
4954 // if (ic->odd)
4955 // _e_fm2_theme_edje_object_set(ic->sd, ic->obj, "base/theme/widgets",
4956 // "list_odd/variable");
4957 // else
4958 // _e_fm2_theme_edje_object_set(ic->sd, ic->obj, "base/theme/widgets",
4959 // "list/variable");
4960 // }
4961 }
4962 else
4963 {
4964 if (ic->sd->config->icon.fixed.w)
4965 _e_fm2_theme_edje_object_set(ic->sd, ic->obj,
4966 "base/theme/fileman",
4967 "icon/fixed");
4968 else
4969 _e_fm2_theme_edje_object_set(ic->sd, ic->obj,
4970 "base/theme/fileman",
4971 "icon/variable");
4972 }
4973 _e_fm2_icon_label_set(ic, ic->obj);
4974 evas_object_clip_set(ic->obj, ic->sd->clip);
4975 evas_object_move(ic->obj,
4976 ic->sd->x + ic->x - ic->sd->pos.x,
4977 ic->sd->y + ic->y - ic->sd->pos.y);
4978 evas_object_resize(ic->obj, ic->w, ic->h);
4979
4980 evas_object_event_callback_add(ic->obj, EVAS_CALLBACK_MOUSE_DOWN, _e_fm2_cb_icon_mouse_down, ic);
4981 evas_object_event_callback_add(ic->obj, EVAS_CALLBACK_MOUSE_UP, _e_fm2_cb_icon_mouse_up, ic);
4982 evas_object_event_callback_add(ic->obj, EVAS_CALLBACK_MOUSE_MOVE, _e_fm2_cb_icon_mouse_move, ic);
4983 evas_object_event_callback_add(ic->obj, EVAS_CALLBACK_MOUSE_IN, _e_fm2_cb_icon_mouse_in, ic);
4984 evas_object_event_callback_add(ic->obj, EVAS_CALLBACK_MOUSE_OUT, _e_fm2_cb_icon_mouse_out, ic);
4985 edje_object_signal_callback_add(ic->obj, "e,action,label,click", "e", _e_fm2_icon_label_click, ic);
4986
4987 _e_fm2_icon_icon_set(ic);
4988
4989 edje_object_thaw(ic->obj);
4990 evas_event_thaw(evas_object_evas_get(ic->sd->obj));
4991 evas_object_show(ic->obj);
4992
4993 if (ic->selected)
4994 {
4995 const char *selectraise;
4996
4997 /* FIXME: need new signal to INSTANTLY activate - no anim */
4998 /* FIXME: while listing dirs need to use icons in-place and not
4999 * unrealize and re-realize */
5000 edje_object_signal_emit(ic->obj, "e,state,selected", "e");
5001 selectraise = edje_object_data_get(ic->obj, "selectraise");
5002 if ((selectraise) && (!strcmp(selectraise, "on")))
5003 evas_object_stack_below(ic->obj, ic->sd->drop);
5004 }
5005
5006 if (ic->info.removable)
5007 _e_fm2_icon_removable_update(ic);
5008 new_file:
5009 if (ic->sd->new_file.thread && (!ic->sd->new_file.filename))
5010 {
5011 /* we got the file through the scanner :/ */
5012 const char *file = ecore_thread_global_data_find("efm_pending_filename");
5013
5014 if (!e_util_strcmp(ic->info.file, file))
5015 {
5016 _e_fm2_file_rename(ic, NULL, NULL);
5017 ic->sd->new_file.done = 1;
5018 }
5019 if (file)
5020 ecore_thread_global_data_del("efm_pending_filename");
5021 }
5022 if (ic->sd->new_file.filename)
5023 {
5024 if (ic->info.file == ic->sd->new_file.filename)
5025 {
5026 _e_fm2_file_rename(ic, NULL, NULL);
5027 eina_stringshare_replace(&ic->sd->new_file.filename, NULL);
5028 }
5029 }
5030 }
5031
5032 static void
_e_fm2_icon_unrealize(E_Fm2_Icon * ic)5033 _e_fm2_icon_unrealize(E_Fm2_Icon *ic)
5034 {
5035 if (!ic->realized) return;
5036 /* delete evas objects */
5037 ic->realized = EINA_FALSE;
5038 evas_object_event_callback_del_full(ic->obj, EVAS_CALLBACK_MOUSE_DOWN, _e_fm2_cb_icon_mouse_down, ic);
5039 evas_object_event_callback_del_full(ic->obj, EVAS_CALLBACK_MOUSE_UP, _e_fm2_cb_icon_mouse_up, ic);
5040 evas_object_event_callback_del_full(ic->obj, EVAS_CALLBACK_MOUSE_MOVE, _e_fm2_cb_icon_mouse_move, ic);
5041 evas_object_event_callback_del_full(ic->obj, EVAS_CALLBACK_MOUSE_IN, _e_fm2_cb_icon_mouse_in, ic);
5042 evas_object_event_callback_del_full(ic->obj, EVAS_CALLBACK_MOUSE_OUT, _e_fm2_cb_icon_mouse_out, ic);
5043 evas_object_del(ic->obj);
5044 ic->obj = NULL;
5045 evas_object_del(ic->obj_icon);
5046 ic->obj_icon = NULL;
5047 }
5048
5049 static Eina_Bool
_e_fm2_icon_visible(const E_Fm2_Icon * ic)5050 _e_fm2_icon_visible(const E_Fm2_Icon *ic)
5051 {
5052 /* return if the icon is visible */
5053 if (
5054 ((ic->x - ic->sd->pos.x) < (ic->sd->w + OVERCLIP)) &&
5055 ((ic->x + ic->w - ic->sd->pos.x) > (-OVERCLIP)) &&
5056 ((ic->y - ic->sd->pos.y) < (ic->sd->h + OVERCLIP)) &&
5057 ((ic->y + ic->h - ic->sd->pos.y) > (-OVERCLIP))
5058 )
5059 return 1;
5060 return 0;
5061 }
5062
5063 static void
_e_fm2_icon_label_set(E_Fm2_Icon * ic,Evas_Object * obj)5064 _e_fm2_icon_label_set(E_Fm2_Icon *ic, Evas_Object *obj)
5065 {
5066 char buf[4096], *p;
5067 int len;
5068 const char *lbl, *type;
5069
5070 if (ic->info.label)
5071 lbl = ic->info.label;
5072 else if ((ic->sd->config->icon.extension.show) || ((!ic->info.link) && (S_ISDIR(ic->info.statinfo.st_mode))))
5073 lbl = ic->info.file;
5074 else
5075 {
5076 /* remove extension. handle double extensions like .tar.gz too
5077 * also be fuzzy - up to 4 chars of extn is ok - eg .html but 5 or
5078 * more is considered part of the name
5079 */
5080 eina_strlcpy(buf, ic->info.file, sizeof(buf));
5081
5082 len = strlen(buf);
5083 p = strrchr(buf, '.');
5084 if ((p) && ((len - (p - buf)) < 6))
5085 {
5086 *p = 0;
5087
5088 len = strlen(buf);
5089 p = strrchr(buf, '.');
5090 if ((p) && ((len - (p - buf)) < 6)) *p = 0;
5091 }
5092 lbl = buf;
5093 }
5094 type = evas_object_type_get(edje_object_part_object_get(obj, "e.text.label"));
5095 if (!e_util_strcmp(type, "textblock"))
5096 {
5097 p = evas_textblock_text_utf8_to_markup(NULL, lbl);
5098 edje_object_part_text_set(obj, "e.text.label", p);
5099 free(p);
5100 }
5101 else
5102 edje_object_part_text_set(obj, "e.text.label", lbl);
5103 }
5104
5105 static Evas_Object *
_e_fm2_icon_icon_direct_set(E_Fm2_Icon * ic,Evas_Object * o,Evas_Smart_Cb gen_func,void * data,int force_gen)5106 _e_fm2_icon_icon_direct_set(E_Fm2_Icon *ic, Evas_Object *o, Evas_Smart_Cb gen_func, void *data, int force_gen)
5107 {
5108 Evas_Object *oic;
5109
5110 oic = e_fm2_icon_get(evas_object_evas_get(o), ic,
5111 gen_func, data, force_gen, NULL);
5112 if (oic)
5113 {
5114 edje_object_part_swallow(o, "e.swallow.icon", oic);
5115 evas_object_show(oic);
5116 }
5117 return oic;
5118 }
5119
5120 static void
_e_fm2_icon_icon_set(E_Fm2_Icon * ic)5121 _e_fm2_icon_icon_set(E_Fm2_Icon *ic)
5122 {
5123 if (!ic->realized) return;
5124 ic->obj_icon = _e_fm2_icon_icon_direct_set(ic, ic->obj,
5125 _e_fm2_cb_icon_thumb_gen,
5126 ic, 0);
5127 }
5128
5129 static void
_e_fm2_icon_thumb(const E_Fm2_Icon * ic,Evas_Object * oic,int force)5130 _e_fm2_icon_thumb(const E_Fm2_Icon *ic, Evas_Object *oic, int force)
5131 {
5132 if ((force) ||
5133 ((_e_fm2_icon_visible(ic)) &&
5134 (!ic->sd->queue) &&
5135 (!ic->sd->sort_idler) &&
5136 (!ic->sd->listing)))
5137 e_thumb_icon_begin(oic);
5138 }
5139
5140 static void
_e_fm2_icon_select(E_Fm2_Icon * ic)5141 _e_fm2_icon_select(E_Fm2_Icon *ic)
5142 {
5143 E_Fm2_Icon *prev;
5144 if (ic->selected) return;
5145 prev = eina_list_last_data_get(ic->sd->selected_icons);
5146 if (prev) prev->last_selected = EINA_FALSE;
5147 ic->selected = EINA_TRUE;
5148 ic->sd->range_selected = NULL;
5149 ic->sd->last_selected = ic;
5150 ic->sd->selected_icons = eina_list_append(ic->sd->selected_icons, ic);
5151 ic->last_selected = EINA_TRUE;
5152 ic->selected_time = ecore_loop_time_get();
5153 if (ic->realized)
5154 {
5155 const char *selectraise;
5156
5157 if (ic->sd->iop_icon)
5158 _e_fm2_icon_entry_widget_accept(ic->sd->iop_icon);
5159
5160 edje_object_signal_emit(ic->obj, "e,state,selected", "e");
5161 evas_object_stack_below(ic->obj, ic->sd->drop);
5162 selectraise = edje_object_data_get(ic->obj, "selectraise");
5163 if ((selectraise) && (!strcmp(selectraise, "on")))
5164 evas_object_stack_below(ic->obj, ic->sd->drop);
5165 }
5166 }
5167
5168 static void
_e_fm2_icon_deselect(E_Fm2_Icon * ic)5169 _e_fm2_icon_deselect(E_Fm2_Icon *ic)
5170 {
5171 if (!ic->selected) return;
5172 ic->selected = EINA_FALSE;
5173 ic->last_selected = EINA_FALSE;
5174 ic->sd->range_selected = NULL;
5175 if (ic->sd->last_selected == ic) ic->sd->last_selected = NULL;
5176 ic->sd->selected_icons = eina_list_remove(ic->sd->selected_icons, ic);
5177 ic->selected_time = 0.0;
5178 if (ic->realized)
5179 {
5180 const char *stacking, *selectraise;
5181
5182 if (ic->entry_widget)
5183 _e_fm2_icon_entry_widget_del(ic);
5184
5185 edje_object_signal_emit(ic->obj, "e,state,unselected", "e");
5186 stacking = edje_object_data_get(ic->obj, "stacking");
5187 selectraise = edje_object_data_get(ic->obj, "selectraise");
5188 if ((selectraise) && (!strcmp(selectraise, "on")))
5189 {
5190 if ((stacking) && (!strcmp(stacking, "below")))
5191 evas_object_stack_above(ic->obj, ic->sd->underlay);
5192 }
5193 }
5194 }
5195
5196 static const char *
_e_fm2_icon_desktop_url_eval(const char * val)5197 _e_fm2_icon_desktop_url_eval(const char *val)
5198 {
5199 const char *s;
5200 char *path, *p;
5201
5202 if (strlen(val) < 6) return NULL;
5203 if (strncmp(val, "file:", 5)) return NULL;
5204 path = (char *)val + 5;
5205 p = e_util_shell_env_path_eval(path);
5206 if (!p) return NULL;
5207 path = p;
5208 while (*path == '/')
5209 path++;
5210 path--;
5211 s = eina_stringshare_add(path);
5212 free(p);
5213 return s;
5214 }
5215
5216 E_API const char *
e_fm2_desktop_url_eval(const char * val)5217 e_fm2_desktop_url_eval(const char *val)
5218 {
5219 return _e_fm2_icon_desktop_url_eval(val);
5220 }
5221
5222 static void
_e_fm2_cb_eio_stat(void * data,Eio_File * handler EINA_UNUSED,const Eina_Stat * st)5223 _e_fm2_cb_eio_stat(void *data, Eio_File *handler EINA_UNUSED, const Eina_Stat *st)
5224 {
5225 E_Fm2_Icon *ic = data;
5226 ic->eio = NULL;
5227 #define FUCK_EINA_STAT_WHY_IS_IT_NOT_THE_SAME_AS_STAT(member) \
5228 ic->info.statinfo.st_##member = st->member
5229
5230 FUCK_EINA_STAT_WHY_IS_IT_NOT_THE_SAME_AS_STAT(dev);
5231 FUCK_EINA_STAT_WHY_IS_IT_NOT_THE_SAME_AS_STAT(ino);
5232 FUCK_EINA_STAT_WHY_IS_IT_NOT_THE_SAME_AS_STAT(mode);
5233 FUCK_EINA_STAT_WHY_IS_IT_NOT_THE_SAME_AS_STAT(nlink);
5234 FUCK_EINA_STAT_WHY_IS_IT_NOT_THE_SAME_AS_STAT(uid);
5235 FUCK_EINA_STAT_WHY_IS_IT_NOT_THE_SAME_AS_STAT(gid);
5236 FUCK_EINA_STAT_WHY_IS_IT_NOT_THE_SAME_AS_STAT(rdev);
5237 FUCK_EINA_STAT_WHY_IS_IT_NOT_THE_SAME_AS_STAT(size);
5238 FUCK_EINA_STAT_WHY_IS_IT_NOT_THE_SAME_AS_STAT(blksize);
5239 FUCK_EINA_STAT_WHY_IS_IT_NOT_THE_SAME_AS_STAT(blocks);
5240 FUCK_EINA_STAT_WHY_IS_IT_NOT_THE_SAME_AS_STAT(atime);
5241 FUCK_EINA_STAT_WHY_IS_IT_NOT_THE_SAME_AS_STAT(mtime);
5242 FUCK_EINA_STAT_WHY_IS_IT_NOT_THE_SAME_AS_STAT(ctime);
5243 }
5244
5245 static void
_e_fm2_cb_eio_err(void * data,Eio_File * handler EINA_UNUSED,int error EINA_UNUSED)5246 _e_fm2_cb_eio_err(void *data, Eio_File *handler EINA_UNUSED, int error EINA_UNUSED)
5247 {
5248 E_Fm2_Icon *ic = data;
5249 ic->eio = NULL;
5250 }
5251
5252 static int
_e_fm2_icon_desktop_load(E_Fm2_Icon * ic)5253 _e_fm2_icon_desktop_load(E_Fm2_Icon *ic)
5254 {
5255 char buf[PATH_MAX];
5256 Efreet_Desktop *desktop;
5257
5258 if (!_e_fm2_icon_realpath(ic, buf, sizeof(buf)))
5259 return 0;
5260
5261 desktop = efreet_desktop_new(buf);
5262 // printf("efreet_desktop_new(%s) = %p\n", buf, desktop);
5263 if (!desktop) goto error;
5264 // if (desktop->type != EFREET_DESKTOP_TYPE_LINK) goto error;
5265
5266 ic->info.removable = EINA_FALSE;
5267 ic->info.removable_full = EINA_FALSE;
5268 ic->info.label = eina_stringshare_add(desktop->name);
5269 ic->info.generic = eina_stringshare_add(desktop->generic_name);
5270 ic->info.comment = eina_stringshare_add(desktop->comment);
5271 ic->info.icon = eina_stringshare_add(desktop->icon);
5272 if (desktop->url)
5273 ic->info.link = _e_fm2_icon_desktop_url_eval(desktop->url);
5274 if (ic->info.link)
5275 {
5276 if (!ic->eio)
5277 ic->eio = eio_file_direct_stat(ic->info.link, _e_fm2_cb_eio_stat, _e_fm2_cb_eio_err, ic);
5278 }
5279 if (desktop->x)
5280 {
5281 const char *type;
5282
5283 type = eina_hash_find(desktop->x, "X-Enlightenment-Type");
5284 if (type)
5285 {
5286 if (!strcmp(type, "Mount")) ic->info.mount = EINA_TRUE;
5287 else if (!strcmp(type, "Removable"))
5288 {
5289 ic->info.removable = EINA_TRUE;
5290 if ((!e_fm2_device_storage_find(ic->info.link)) &&
5291 (!e_fm2_device_volume_find(ic->info.link)))
5292 {
5293 /* delete .desktop for non existing device */
5294 if (ecore_file_remove(buf))
5295 _e_fm2_live_file_del(ic->sd->obj, ic->info.file);
5296 else /* ignore */
5297 _e_fm2_file_del(ic->sd->obj, ic->info.file);
5298
5299 efreet_desktop_free(desktop);
5300 goto error;
5301 }
5302 }
5303 type = eina_hash_find(desktop->x, "X-Enlightenment-Removable-State");
5304 if (type)
5305 {
5306 if (!strcmp(type, "Full"))
5307 ic->info.removable_full = EINA_TRUE;
5308 }
5309 }
5310 }
5311 /* FIXME: get category */
5312 ic->info.category = NULL;
5313 efreet_desktop_free(desktop);
5314
5315 return 1;
5316 error:
5317 eina_stringshare_del(ic->info.label);
5318 eina_stringshare_del(ic->info.comment);
5319 eina_stringshare_del(ic->info.generic);
5320 eina_stringshare_del(ic->info.icon);
5321 eina_stringshare_del(ic->info.link);
5322 eina_stringshare_del(ic->info.category);
5323 ic->info.label = NULL;
5324 ic->info.comment = NULL;
5325 ic->info.generic = NULL;
5326 ic->info.icon = NULL;
5327 ic->info.link = NULL;
5328 ic->info.category = NULL;
5329 //Hack
5330 if (!strncmp(ic->info.file, "|storage_", 9)) ecore_file_unlink(buf);
5331 return 0;
5332 }
5333
5334 /**************************/
5335 static E_Fm2_Region *
_e_fm2_region_new(E_Fm2_Smart_Data * sd)5336 _e_fm2_region_new(E_Fm2_Smart_Data *sd)
5337 {
5338 E_Fm2_Region *rg;
5339
5340 rg = E_NEW(E_Fm2_Region, 1);
5341 rg->sd = sd;
5342 return rg;
5343 }
5344
5345 static void
_e_fm2_region_free(E_Fm2_Region * rg)5346 _e_fm2_region_free(E_Fm2_Region *rg)
5347 {
5348 E_Fm2_Icon *ic;
5349
5350 EINA_LIST_FREE(rg->list, ic)
5351 ic->region = NULL;
5352 free(rg);
5353 }
5354
5355 static void
_e_fm2_region_realize(E_Fm2_Region * rg)5356 _e_fm2_region_realize(E_Fm2_Region *rg)
5357 {
5358 const Eina_List *l;
5359 E_Fm2_Icon *ic;
5360
5361 if (rg->realized) return;
5362 /* actually create evas objects etc. */
5363 rg->realized = 1;
5364 edje_freeze();
5365 EINA_LIST_FOREACH(rg->list, l, ic)
5366 _e_fm2_icon_realize(ic);
5367 EINA_LIST_FOREACH(rg->list, l, ic)
5368 {
5369 if (ic->selected)
5370 evas_object_stack_below(ic->obj, ic->sd->drop);
5371 }
5372 edje_thaw();
5373 }
5374
5375 static void
_e_fm2_region_unrealize(E_Fm2_Region * rg)5376 _e_fm2_region_unrealize(E_Fm2_Region *rg)
5377 {
5378 Eina_List *l;
5379 E_Fm2_Icon *ic;
5380
5381 if (!rg->realized) return;
5382 /* delete evas objects */
5383 rg->realized = 0;
5384 edje_freeze();
5385 EINA_LIST_FOREACH(rg->list, l, ic)
5386 _e_fm2_icon_unrealize(ic);
5387 edje_thaw();
5388 }
5389
5390 static int
_e_fm2_region_visible(E_Fm2_Region * rg)5391 _e_fm2_region_visible(E_Fm2_Region *rg)
5392 {
5393 /* return if the icon is visible */
5394 if (
5395 ((rg->x - rg->sd->pos.x) < (rg->sd->w + OVERCLIP)) &&
5396 ((rg->x + rg->w - rg->sd->pos.x) > (-OVERCLIP)) &&
5397 ((rg->y - rg->sd->pos.y) < (rg->sd->h + OVERCLIP)) &&
5398 ((rg->y + rg->h - rg->sd->pos.y) > (-OVERCLIP))
5399 )
5400 return 1;
5401 return 0;
5402 }
5403
5404 static void
_e_fm2_icon_make_visible(E_Fm2_Icon * ic)5405 _e_fm2_icon_make_visible(E_Fm2_Icon *ic)
5406 {
5407 if (_e_fm2_view_mode_get(ic->sd) == E_FM2_VIEW_MODE_LIST)
5408 {
5409 if (
5410 ((ic->y - ic->sd->pos.y) >= 0) &&
5411 ((ic->y + ic->h - ic->sd->pos.y) <= (ic->sd->h))
5412 )
5413 return;
5414 if ((ic->y - ic->sd->pos.y) < 0)
5415 e_fm2_pan_set(ic->sd->obj, ic->sd->pos.x, ic->y);
5416 else
5417 e_fm2_pan_set(ic->sd->obj, ic->sd->pos.x, ic->y - ic->sd->h + ic->h);
5418 }
5419 else
5420 {
5421 Evas_Coord x, y;
5422
5423 if (
5424 ((ic->y - ic->sd->pos.y) >= 0) &&
5425 ((ic->y + ic->h /* + ICON_BOTTOM_SPACE*/ - ic->sd->pos.y) <= (ic->sd->h)) &&
5426 ((ic->x - ic->sd->pos.x) >= 0) &&
5427 ((ic->x + ic->w - ic->sd->pos.x) <= (ic->sd->w))
5428 )
5429 return;
5430 x = ic->sd->pos.x;
5431 if ((ic->x - ic->sd->pos.x) < 0)
5432 x = ic->x;
5433 else if ((ic->x + ic->w - ic->sd->pos.x) > (ic->sd->w))
5434 x = ic->x + ic->w - ic->sd->w;
5435 y = ic->sd->pos.y;
5436 if ((ic->y - ic->sd->pos.y) < 0)
5437 y = ic->y;
5438 else if ((ic->y + ic->h /* + ICON_BOTTOM_SPACE*/ - ic->sd->pos.y) > (ic->sd->h))
5439 y = ic->y + ic->h /* + ICON_BOTTOM_SPACE*/ - ic->sd->h;
5440 e_fm2_pan_set(ic->sd->obj, x, y);
5441 }
5442 evas_object_smart_callback_call(ic->sd->obj, "pan_changed", NULL);
5443 }
5444
5445 static void
_e_fm2_icon_desel_any(Evas_Object * obj)5446 _e_fm2_icon_desel_any(Evas_Object *obj)
5447 {
5448 E_Fm2_Smart_Data *sd;
5449 Eina_List *l, *ll;
5450 E_Fm2_Icon *ic;
5451
5452 sd = evas_object_smart_data_get(obj);
5453 if (!sd) return;
5454 EINA_LIST_FOREACH_SAFE(sd->selected_icons, l, ll, ic)
5455 _e_fm2_icon_deselect(ic);
5456 }
5457
5458 static E_Fm2_Icon *
_e_fm2_icon_first_selected_find(Evas_Object * obj)5459 _e_fm2_icon_first_selected_find(Evas_Object *obj)
5460 {
5461 E_Fm2_Smart_Data *sd;
5462
5463 sd = evas_object_smart_data_get(obj);
5464 if (!sd) return NULL;
5465 return eina_list_data_get(sd->selected_icons);
5466 }
5467
5468 static void
_e_fm2_icon_sel_first(Evas_Object * obj,Eina_Bool add)5469 _e_fm2_icon_sel_first(Evas_Object *obj, Eina_Bool add)
5470 {
5471 E_Fm2_Smart_Data *sd;
5472 E_Fm2_Icon *ic;
5473
5474 sd = evas_object_smart_data_get(obj);
5475 if (!sd) return;
5476 if (!sd->icons) return;
5477 if ((!add) || sd->config->selection.single)
5478 _e_fm2_icon_desel_any(obj);
5479 ic = eina_list_data_get(sd->icons);
5480 _e_fm2_icon_select(ic);
5481 evas_object_smart_callback_call(sd->obj, "selection_change", NULL);
5482 _e_fm2_icon_make_visible(ic);
5483 }
5484
5485 static void
_e_fm2_icon_sel_last(Evas_Object * obj,Eina_Bool add)5486 _e_fm2_icon_sel_last(Evas_Object *obj, Eina_Bool add)
5487 {
5488 E_Fm2_Smart_Data *sd;
5489 E_Fm2_Icon *ic;
5490
5491 sd = evas_object_smart_data_get(obj);
5492 if (!sd) return;
5493 if (!sd->icons) return;
5494 if ((!add) || sd->config->selection.single)
5495 _e_fm2_icon_desel_any(obj);
5496 ic = eina_list_last_data_get(sd->icons);
5497 _e_fm2_icon_select(ic);
5498 evas_object_smart_callback_call(sd->obj, "selection_change", NULL);
5499 _e_fm2_icon_make_visible(ic);
5500 }
5501
5502 static void
_e_fm2_icon_sel_any(Evas_Object * obj)5503 _e_fm2_icon_sel_any(Evas_Object *obj)
5504 {
5505 E_Fm2_Smart_Data *sd;
5506 E_Fm2_Icon *ic;
5507 Eina_List *l;
5508
5509 sd = evas_object_smart_data_get(obj);
5510 if (!sd) return;
5511 if (!sd->icons) return;
5512 EINA_LIST_FOREACH(sd->icons, l, ic)
5513 if (!ic->selected) _e_fm2_icon_select(ic);
5514 }
5515
5516 static E_Fm2_Icon *
_e_fm2_icon_next_find(Evas_Object * obj,int next,int (* match_func)(E_Fm2_Icon * ic,void * data),void * data)5517 _e_fm2_icon_next_find(Evas_Object *obj, int next, int (*match_func)(E_Fm2_Icon *ic, void *data), void *data)
5518 {
5519 E_Fm2_Smart_Data *sd;
5520 Eina_List *l;
5521 E_Fm2_Icon *ic, *ic_next;
5522 char view_mode;
5523 int x = 0, y = 0, custom = 0;
5524 int dist = 0, min = 65535;
5525
5526 sd = evas_object_smart_data_get(obj);
5527 if (!sd) return NULL;
5528 if (!sd->icons) return NULL;
5529
5530 l = eina_list_data_find_list(sd->icons, (sd->range_selected) ?
5531 sd->range_selected :
5532 sd->last_selected);
5533
5534 if (!next) return eina_list_data_get(l);
5535
5536 if (!l) return (next == 1) ? eina_list_data_get(sd->icons) :
5537 eina_list_last_data_get(sd->icons);
5538
5539 view_mode = _e_fm2_view_mode_get(sd);
5540 if ((view_mode == E_FM2_VIEW_MODE_CUSTOM_SMART_GRID_ICONS) ||
5541 (view_mode == E_FM2_VIEW_MODE_CUSTOM_GRID_ICONS) ||
5542 (view_mode == E_FM2_VIEW_MODE_CUSTOM_ICONS))
5543 custom = 1;
5544
5545 ic_next = NULL;
5546
5547 if (custom || match_func)
5548 {
5549 ic = eina_list_data_get(l);
5550 x = ic->x;
5551 y = ic->y;
5552
5553 EINA_LIST_FOREACH(sd->icons, l, ic)
5554 {
5555 if (match_func && !match_func(ic, data)) continue;
5556
5557 int dx = (ic->x - x);
5558 int dy = (ic->y - y);
5559 int sgnx = (dx) ? dx / abs(dx) : 0;
5560
5561 if ((next == sgnx) && (abs(dx) >= abs(dy)))
5562 {
5563 dist = abs(dy) + abs(dx);
5564 if (dist < min)
5565 {
5566 min = dist;
5567 ic_next = ic;
5568 }
5569 }
5570 }
5571 }
5572 else
5573 {
5574 ic_next = eina_list_data_get((next == 1) ? eina_list_next(l) :
5575 eina_list_prev(l));
5576 }
5577
5578 return ic_next;
5579 }
5580
5581 static void
_e_fm2_icon_sel_prev(Evas_Object * obj,Eina_Bool add)5582 _e_fm2_icon_sel_prev(Evas_Object *obj, Eina_Bool add)
5583 {
5584 E_Fm2_Icon *ic_prev;
5585
5586 ic_prev = _e_fm2_icon_next_find(obj, -1, NULL, NULL);
5587
5588 if (!ic_prev) return;
5589
5590 if ((!add) || ic_prev->sd->config->selection.single)
5591 {
5592 _e_fm2_icon_desel_any(obj);
5593 _e_fm2_icon_select(ic_prev);
5594 }
5595 else
5596 {
5597 _e_fm2_icon_range_select(ic_prev);
5598 }
5599
5600 evas_object_smart_callback_call(obj, "selection_change", NULL);
5601 _e_fm2_icon_make_visible(ic_prev);
5602 }
5603
5604 static void
_e_fm2_icon_sel_next(Evas_Object * obj,Eina_Bool add)5605 _e_fm2_icon_sel_next(Evas_Object *obj, Eina_Bool add)
5606 {
5607 E_Fm2_Icon *ic_next;
5608
5609 ic_next = _e_fm2_icon_next_find(obj, 1, NULL, NULL);
5610
5611 if (!ic_next) return;
5612
5613 if ((!add) || ic_next->sd->config->selection.single)
5614 {
5615 _e_fm2_icon_desel_any(obj);
5616 _e_fm2_icon_select(ic_next);
5617 }
5618 else
5619 {
5620 _e_fm2_icon_range_select(ic_next);
5621 }
5622 evas_object_smart_callback_call(obj, "selection_change", NULL);
5623 _e_fm2_icon_make_visible(ic_next);
5624 }
5625
5626 static void
_e_fm2_icon_sel_down(Evas_Object * obj,Eina_Bool add)5627 _e_fm2_icon_sel_down(Evas_Object *obj, Eina_Bool add)
5628 {
5629 E_Fm2_Smart_Data *sd;
5630 Eina_List *l;
5631 E_Fm2_Icon *ic, *ic2, *ic_down;
5632 int dist, min = 65535;
5633
5634 sd = evas_object_smart_data_get(obj);
5635 if (!sd) return;
5636 if (!sd->icons) return;
5637
5638 ic = (sd->range_selected) ? sd->range_selected : sd->last_selected;
5639
5640 if (ic)
5641 {
5642 ic_down = ic;
5643 EINA_LIST_FOREACH(sd->icons, l, ic2)
5644 {
5645 int dx = (ic2->x - ic->x);
5646 int dy = (ic2->y - ic->y);
5647
5648 if ((dy > 0) && (abs(dy) > abs(dx)))
5649 {
5650 dist = abs(dx)+abs(dy);
5651 if (dist < min)
5652 {
5653 min = dist;
5654 ic_down = ic2;
5655 }
5656 }
5657 }
5658 }
5659 else
5660 {
5661 ic_down = eina_list_data_get(sd->icons);
5662 }
5663
5664 if ((!add) || ic_down->sd->config->selection.single)
5665 {
5666 _e_fm2_icon_desel_any(obj);
5667 _e_fm2_icon_select(ic_down);
5668 }
5669 else
5670 {
5671 _e_fm2_icon_range_select(ic_down);
5672 }
5673
5674 evas_object_smart_callback_call(sd->obj, "selection_change", NULL);
5675 _e_fm2_icon_make_visible(ic_down);
5676 }
5677
5678 static void
_e_fm2_icon_sel_up(Evas_Object * obj,Eina_Bool add)5679 _e_fm2_icon_sel_up(Evas_Object *obj, Eina_Bool add)
5680 {
5681 E_Fm2_Smart_Data *sd;
5682 Eina_List *l;
5683 E_Fm2_Icon *ic, *ic2, *ic_down;
5684 int dist, min = 65535;
5685
5686 sd = evas_object_smart_data_get(obj);
5687 if (!sd) return;
5688 if (!sd->icons) return;
5689
5690 ic = (sd->range_selected) ? sd->range_selected : sd->last_selected;
5691
5692 if (ic)
5693 {
5694 ic_down = ic;
5695 EINA_LIST_FOREACH(sd->icons, l, ic2)
5696 {
5697 int dx = (ic2->x - ic->x);
5698 int dy = (ic2->y - ic->y);
5699
5700 if ((dy < 0) && (abs(dy) > abs(dx)))
5701 {
5702 dist = abs(dx) + abs(dy);
5703
5704 if (dist < min)
5705 {
5706 min = dist;
5707 ic_down = ic2;
5708 }
5709 }
5710 }
5711 }
5712 else
5713 {
5714 ic_down = eina_list_last_data_get(sd->icons);
5715 }
5716
5717 if ((!add) || ic_down->sd->config->selection.single)
5718 {
5719 _e_fm2_icon_desel_any(obj);
5720 _e_fm2_icon_select(ic_down);
5721 }
5722 else
5723 {
5724 _e_fm2_icon_range_select(ic_down);
5725 }
5726
5727 evas_object_smart_callback_call(sd->obj, "selection_change", NULL);
5728 _e_fm2_icon_make_visible(ic_down);
5729 }
5730
5731 static void
_e_fm2_icon_range_select(E_Fm2_Icon * ic)5732 _e_fm2_icon_range_select(E_Fm2_Icon *ic)
5733 {
5734 const Eina_List *l;
5735 E_Fm2_Icon *ic2;
5736 E_Fm2_Icon *last;
5737
5738 char view_mode = _e_fm2_view_mode_get(ic->sd);
5739
5740 if (!ic->sd->range_selected)
5741 {
5742 last = ic->sd->last_selected;
5743 ic->sd->range_select_anchor = last;
5744 }
5745 else
5746 {
5747 last = ic->sd->range_select_anchor;
5748 }
5749
5750 _e_fm2_icon_desel_any(ic->sd->obj);
5751
5752 if ((!last) || (last == ic))
5753 {
5754 _e_fm2_icon_select(ic);
5755 ic->sd->range_select_anchor = ic;
5756 }
5757 else if ((view_mode == E_FM2_VIEW_MODE_CUSTOM_SMART_GRID_ICONS) ||
5758 (view_mode == E_FM2_VIEW_MODE_CUSTOM_GRID_ICONS) ||
5759 (view_mode == E_FM2_VIEW_MODE_CUSTOM_ICONS))
5760 {
5761 int topx = (ic->x <= last->x) ? ic->x : last->x;
5762 int boundx = (ic->x < last->x) ? (last->x + last->w) : (ic->x + ic->w);
5763 int topy = (ic->y <= last->y) ? ic->y : last->y;
5764 int boundy = (ic->y < last->y) ? (last->y + last->h) : (ic->y + ic->h);
5765
5766 EINA_LIST_FOREACH(ic->sd->icons, l, ic2)
5767 {
5768 if ((ic2->x >= topx) && (ic2->x < boundx) &&
5769 (ic2->y >= topy) && (ic2->y < boundy))
5770 _e_fm2_icon_select(ic2);
5771 }
5772 }
5773 else
5774 {
5775 int trig = 2;
5776 EINA_LIST_FOREACH(ic->sd->icons, l, ic2)
5777 {
5778 if ((ic2 == last) || (ic2 == ic)) trig--;
5779 if ((trig < 2)) _e_fm2_icon_select(ic2);
5780 if (!trig) break;
5781 }
5782 }
5783
5784 ic->sd->range_selected = ic;
5785 }
5786
5787 /* FIXME: prototype */
5788 static void
_e_fm2_typebuf_show(Evas_Object * obj)5789 _e_fm2_typebuf_show(Evas_Object *obj)
5790 {
5791 E_Fm2_Smart_Data *sd;
5792
5793 sd = evas_object_smart_data_get(obj);
5794 if (!sd) return;
5795 if (sd->typebuf.disabled) return;
5796 E_FREE(sd->typebuf.buf);
5797 sd->typebuf.buf = strdup("");
5798 edje_object_part_text_set(sd->overlay, "e.text.typebuf_label", sd->typebuf.buf);
5799 edje_object_signal_emit(sd->overlay, "e,state,typebuf,start", "e");
5800 sd->typebuf_visible = EINA_TRUE;
5801 }
5802
5803 static void
_e_fm2_typebuf_hide(Evas_Object * obj)5804 _e_fm2_typebuf_hide(Evas_Object *obj)
5805 {
5806 E_Fm2_Smart_Data *sd;
5807
5808 sd = evas_object_smart_data_get(obj);
5809 if (!sd) return;
5810 if (!sd->typebuf_visible) return;
5811 if (sd->typebuf.setting) return;
5812 E_FREE(sd->typebuf.buf);
5813 edje_object_signal_emit(sd->overlay, "e,state,typebuf,stop", "e");
5814 eina_stringshare_replace(&sd->typebuf.start, NULL);
5815 sd->typebuf_visible = EINA_FALSE;
5816 sd->typebuf.wildcard = 0;
5817 if (sd->typebuf.timer) ecore_timer_del(sd->typebuf.timer);
5818 sd->typebuf.timer = NULL;
5819 }
5820
5821 #if 0
5822 static void
5823 _e_fm2_typebuf_history_prev(Evas_Object *obj)
5824 {
5825 E_Fm2_Smart_Data *sd;
5826
5827 sd = evas_object_smart_data_get(obj);
5828 if (!sd) return;
5829 /* FIXME: do */
5830 }
5831
5832 static void
5833 _e_fm2_typebuf_history_next(Evas_Object *obj)
5834 {
5835 E_Fm2_Smart_Data *sd;
5836
5837 sd = evas_object_smart_data_get(obj);
5838 if (!sd) return;
5839 /* FIXME: do */
5840 }
5841
5842 #endif
5843
5844 static int
_e_fm2_inplace_open(const E_Fm2_Icon * ic)5845 _e_fm2_inplace_open(const E_Fm2_Icon *ic)
5846 {
5847 char buf[PATH_MAX];
5848
5849 if (((!S_ISDIR(ic->info.statinfo.st_mode)) ||
5850 (ic->info.link && (!S_ISDIR(ic->info.statinfo.st_mode))) ||
5851 (!ic->sd->config->view.open_dirs_in_place) ||
5852 (ic->sd->config->view.no_subdir_jump)))
5853 return 0;
5854
5855 if (!_e_fm2_icon_path(ic, buf, sizeof(buf)))
5856 return -1;
5857
5858 e_fm2_path_set(ic->sd->obj,
5859 ic->info.real_link ? "/" : ic->sd->dev,
5860 buf);
5861
5862 return 1;
5863 }
5864
5865 static void
_e_fm2_typebuf_run(Evas_Object * obj)5866 _e_fm2_typebuf_run(Evas_Object *obj)
5867 {
5868 E_Fm2_Icon *ic;
5869
5870 _e_fm2_typebuf_hide(obj);
5871 ic = _e_fm2_icon_first_selected_find(obj);
5872 if (ic)
5873 {
5874 if (_e_fm2_inplace_open(ic) == 0)
5875 evas_object_smart_callback_call(ic->sd->obj, "selected", NULL);
5876 }
5877 }
5878
5879 static int
_e_fm2_typebuf_match_func(E_Fm2_Icon * ic,void * data)5880 _e_fm2_typebuf_match_func(E_Fm2_Icon *ic, void *data)
5881 {
5882 char *s, *tb = data;
5883 s = strrchr(tb, '/');
5884 if (s) tb = s + 1;
5885 return ((ic->info.label) &&
5886 (e_util_glob_case_match(ic->info.label, tb))) ||
5887 ((ic->info.file) &&
5888 (e_util_glob_case_match(ic->info.file, tb)));
5889 }
5890
5891 static Eina_Bool
_e_fm_typebuf_timer_cb(void * data)5892 _e_fm_typebuf_timer_cb(void *data)
5893 {
5894 E_Fm2_Smart_Data *sd = data;
5895
5896 if (!sd) return ECORE_CALLBACK_CANCEL;
5897 sd->typebuf.timer = NULL;
5898 if (!sd->typebuf_visible) return ECORE_CALLBACK_CANCEL;
5899
5900 _e_fm2_typebuf_hide(sd->obj);
5901 return ECORE_CALLBACK_CANCEL;
5902 }
5903
5904 static E_Fm2_Icon *
_e_fm2_typebuf_match(Evas_Object * obj,int next)5905 _e_fm2_typebuf_match(Evas_Object *obj, int next)
5906 {
5907 E_Fm2_Smart_Data *sd;
5908 E_Fm2_Icon *ic, *ic_match = NULL;
5909 Eina_List *l, *sel = NULL;
5910 char *tb;
5911 int tblen, x;
5912
5913 sd = evas_object_smart_data_get(obj);
5914 if (!sd) return NULL;
5915 if (sd->typebuf.disabled) return NULL;
5916 if (!sd->typebuf.buf) return NULL;
5917 if (!sd->icons) return NULL;
5918
5919 tblen = strlen(sd->typebuf.buf);
5920 if (sd->typebuf.buf[tblen - 1] != '*')
5921 {
5922 tb = alloca(tblen + 2);
5923 memcpy(tb, sd->typebuf.buf, tblen);
5924 tb[tblen] = '*';
5925 tb[tblen + 1] = '\0';
5926 }
5927 else
5928 {
5929 size_t blen = strlen(sd->typebuf.buf);
5930 tb = memcpy(alloca(blen + 1), sd->typebuf.buf, blen + 1);
5931 }
5932
5933 if (!next)
5934 {
5935 EINA_LIST_FOREACH(sd->icons, l, ic)
5936 {
5937 if (_e_fm2_typebuf_match_func(ic, tb))
5938 {
5939 sel = eina_list_append(sel, ic);
5940 if (!sd->typebuf.wildcard) break;
5941 }
5942 }
5943 if (eina_list_count(sel) == 1)
5944 ic_match = eina_list_data_get(sel);
5945 }
5946 else
5947 {
5948 ic_match = _e_fm2_icon_next_find(obj, next, &_e_fm2_typebuf_match_func, tb);
5949 }
5950
5951 for (x = 0; x < 2; x++)
5952 {
5953 switch (x)
5954 {
5955 case 0:
5956 if (!sd->selected_icons) continue;
5957 if (eina_list_count(sel) != eina_list_count(sd->selected_icons)) continue;
5958 EINA_LIST_FOREACH(sd->selected_icons, l, ic)
5959 if (!eina_list_data_find(sel, ic))
5960 {
5961 x++;
5962 break;
5963 }
5964 if (!x)
5965 {
5966 /* selections are identical, don't change */
5967 _e_fm2_icon_make_visible(eina_list_data_get(sel));
5968 sel = eina_list_free(sel);
5969 x++;
5970 break;
5971 }
5972 EINA_FALLTHROUGH;
5973 /* no break */
5974
5975 case 1:
5976 _e_fm2_icon_desel_any(obj);
5977 if (sel)
5978 {
5979 if (!ic_match) ic_match = eina_list_data_get(sel);
5980 _e_fm2_icon_make_visible(eina_list_data_get(sel));
5981 EINA_LIST_FREE(sel, ic)
5982 _e_fm2_icon_select(ic);
5983 }
5984 evas_object_smart_callback_call(obj, "selection_change", NULL);
5985 }
5986 } while (0)
5987 ;
5988
5989 if (sd->typebuf.timer) ecore_timer_loop_reset(sd->typebuf.timer);
5990 else sd->typebuf.timer = ecore_timer_loop_add(3.5, _e_fm_typebuf_timer_cb, sd);
5991 return ic_match;
5992 }
5993
5994 static void
_e_fm2_typebuf_complete(Evas_Object * obj)5995 _e_fm2_typebuf_complete(Evas_Object *obj)
5996 {
5997 E_Fm2_Smart_Data *sd;
5998 E_Fm2_Icon *ic;
5999
6000 sd = evas_object_smart_data_get(obj);
6001 if (!sd) return;
6002 if (sd->typebuf.disabled) return;
6003 if ((!sd->typebuf.buf) || (!sd->typebuf.buf[0])) return;
6004 ic = _e_fm2_typebuf_match(obj, 0);
6005 if (!ic) return;
6006 if ((sd->typebuf.buf[0] == '/') || (!memcmp(sd->typebuf.buf, "~/", 2)))
6007 {
6008 char *buf, *s;
6009 size_t size;
6010
6011 s = strrchr(sd->typebuf.buf, '/');
6012 if (!s) return;
6013 s++;
6014 s[0] = 0;
6015 size = s - sd->typebuf.buf + strlen(ic->info.file) + 1;
6016 buf = malloc(size);
6017 if (!buf) return;
6018 snprintf(buf, size, "%s%s", sd->typebuf.buf, ic->info.file);
6019 free(sd->typebuf.buf);
6020 sd->typebuf.buf = buf;
6021 edje_object_part_text_set(sd->overlay, "e.text.typebuf_label", sd->typebuf.buf);
6022 evas_object_smart_callback_call(sd->obj, "typebuf_changed", sd->typebuf.buf);
6023 }
6024 else
6025 {
6026 free(sd->typebuf.buf);
6027 sd->typebuf.buf = strdup(ic->info.file);
6028 if (!sd->typebuf.buf)
6029 {
6030 edje_object_part_text_set(sd->overlay, "e.text.typebuf_label", "");
6031 return;
6032 }
6033 eina_stringshare_replace(&sd->typebuf.start, sd->realpath);
6034 edje_object_part_text_set(sd->overlay, "e.text.typebuf_label", sd->typebuf.buf);
6035 evas_object_smart_callback_call(sd->obj, "typebuf_changed", sd->typebuf.buf);
6036 }
6037 }
6038
6039 static void
_e_fm2_typebuf_char_append(Evas_Object * obj,const char * ch)6040 _e_fm2_typebuf_char_append(Evas_Object *obj, const char *ch)
6041 {
6042 E_Fm2_Smart_Data *sd;
6043 char *ts;
6044 size_t len;
6045
6046 if ((!ch) || (!ch[0])) return;
6047 sd = evas_object_smart_data_get(obj);
6048 if (!sd) return;
6049 if (sd->typebuf.disabled) return;
6050 if (!sd->typebuf.buf) return;
6051 len = strlen(sd->typebuf.buf) + strlen(ch);
6052 ts = malloc(len + 1);
6053 if (!ts) return;
6054 strcpy(ts, sd->typebuf.buf);
6055 strcat(ts, ch);
6056 free(sd->typebuf.buf);
6057 sd->typebuf.buf = ts;
6058 if (ch[0] == '*')
6059 sd->typebuf.wildcard++;
6060 _e_fm2_typebuf_match(obj, 0);
6061 if ((!sd->config->view.no_typebuf_set) && (ch[0] == '/'))
6062 {
6063 if (sd->typebuf.buf[0] == '/')
6064 {
6065 if (ecore_file_is_dir(sd->typebuf.buf))
6066 {
6067 sd->typebuf.setting = EINA_TRUE;
6068 e_fm2_path_set(obj, "/", sd->typebuf.buf);
6069 sd->typebuf.setting = EINA_FALSE;
6070 }
6071 }
6072 else if (sd->typebuf.buf[0] != '~')
6073 {
6074 char buf[PATH_MAX];
6075
6076 if (!sd->typebuf.start) sd->typebuf.start = eina_stringshare_ref(sd->realpath);
6077 snprintf(buf, sizeof(buf), "%s/%s", sd->typebuf.start, sd->typebuf.buf);
6078 if (ecore_file_is_dir(buf))
6079 {
6080 sd->typebuf.setting = EINA_TRUE;
6081 e_fm2_path_set(obj, "/", buf);
6082 sd->typebuf.setting = EINA_FALSE;
6083 }
6084 }
6085 else if (!memcmp(sd->typebuf.buf, "~/", 2))
6086 {
6087 char buf[PATH_MAX];
6088
6089 snprintf(buf, sizeof(buf), "%s/%s", getenv("HOME"), sd->typebuf.buf + 2);
6090 if (ecore_file_is_dir(buf))
6091 {
6092 sd->typebuf.setting = EINA_TRUE;
6093 e_fm2_path_set(obj, "~/", sd->typebuf.buf + 1);
6094 sd->typebuf.setting = EINA_FALSE;
6095 }
6096 }
6097 }
6098 edje_object_part_text_set(sd->overlay, "e.text.typebuf_label", sd->typebuf.buf);
6099 evas_object_smart_callback_call(sd->obj, "typebuf_changed", sd->typebuf.buf);
6100 }
6101
6102 static void
_e_fm2_typebuf_char_backspace(Evas_Object * obj)6103 _e_fm2_typebuf_char_backspace(Evas_Object *obj)
6104 {
6105 E_Fm2_Smart_Data *sd;
6106 int len, p, dec;
6107
6108 sd = evas_object_smart_data_get(obj);
6109 if (!sd) return;
6110 if (sd->typebuf.disabled) return;
6111 if (!sd->typebuf.buf) return;
6112 len = strlen(sd->typebuf.buf);
6113 if (len == 0)
6114 {
6115 _e_fm2_typebuf_hide(obj);
6116 return;
6117 }
6118 p = evas_string_char_prev_get(sd->typebuf.buf, len, &dec);
6119 if (p < 0) return;
6120 sd->typebuf.buf[p] = 0;
6121 len--;
6122 if (dec == '*')
6123 sd->typebuf.wildcard--;
6124 if (len) _e_fm2_typebuf_match(obj, 0);
6125 if ((!sd->config->view.no_typebuf_set) && (dec == '/'))
6126 {
6127 if ((len > 1) || (sd->typebuf.buf[0] == '/'))
6128 {
6129 if (ecore_file_is_dir(sd->typebuf.buf))
6130 {
6131 sd->typebuf.setting = EINA_TRUE;
6132 e_fm2_path_set(obj, "/", sd->typebuf.buf);
6133 sd->typebuf.setting = EINA_FALSE;
6134 }
6135 }
6136 else if ((len > 1) || (sd->typebuf.buf[0] != '~'))
6137 {
6138 char buf[PATH_MAX];
6139
6140 if (!sd->typebuf.start) sd->typebuf.start = eina_stringshare_ref(sd->realpath);
6141 snprintf(buf, sizeof(buf), "%s/%s", sd->typebuf.start, sd->typebuf.buf);
6142 if (ecore_file_is_dir(buf))
6143 {
6144 sd->typebuf.setting = EINA_TRUE;
6145 e_fm2_path_set(obj, "/", buf);
6146 sd->typebuf.setting = EINA_FALSE;
6147 }
6148 }
6149 else if (!memcmp(sd->typebuf.buf, "~/", 2))
6150 {
6151 char buf[PATH_MAX];
6152
6153 snprintf(buf, sizeof(buf), "%s/%s", getenv("HOME"), sd->typebuf.buf + 2);
6154 if (ecore_file_is_dir(buf))
6155 {
6156 sd->typebuf.setting = EINA_TRUE;
6157 e_fm2_path_set(obj, "~/", sd->typebuf.buf + 1);
6158 sd->typebuf.setting = EINA_FALSE;
6159 }
6160 }
6161 }
6162 edje_object_part_text_set(sd->overlay, "e.text.typebuf_label", sd->typebuf.buf);
6163 evas_object_smart_callback_call(sd->obj, "typebuf_changed", sd->typebuf.buf);
6164 }
6165
6166 /**************************/
6167
6168 /* FIXME: prototype + reposition + implement */
6169 static void
_e_fm2_dnd_drop_configure(Evas_Object * obj)6170 _e_fm2_dnd_drop_configure(Evas_Object *obj)
6171 {
6172 E_Fm2_Smart_Data *sd;
6173
6174 sd = evas_object_smart_data_get(obj);
6175 if (!sd) return;
6176 if (!sd->drop_icon) return;
6177 if (sd->drop_after == -1)
6178 {
6179 evas_object_move(sd->drop_in,
6180 sd->x + sd->drop_icon->x - sd->pos.x,
6181 sd->y + sd->drop_icon->y - sd->pos.y);
6182 evas_object_resize(sd->drop_in, sd->drop_icon->w, sd->drop_icon->h);
6183 }
6184 else if (sd->drop_after)
6185 {
6186 evas_object_move(sd->drop,
6187 sd->x + sd->drop_icon->x - sd->pos.x,
6188 sd->y + sd->drop_icon->y - sd->pos.y + sd->drop_icon->h - 1);
6189 evas_object_resize(sd->drop, sd->drop_icon->w, 2);
6190 }
6191 else
6192 {
6193 evas_object_move(sd->drop,
6194 sd->x + sd->drop_icon->x - sd->pos.x,
6195 sd->y + sd->drop_icon->y - sd->pos.y - 1);
6196 evas_object_resize(sd->drop, sd->drop_icon->w, 2);
6197 }
6198 }
6199
6200 /* FIXME: prototype + reposition + implement */
6201 static void
_e_fm2_dnd_drop_all_show(Evas_Object * obj)6202 _e_fm2_dnd_drop_all_show(Evas_Object *obj)
6203 {
6204 E_Fm2_Smart_Data *sd;
6205
6206 sd = evas_object_smart_data_get(obj);
6207 if (!sd) return;
6208 if (sd->drop_show)
6209 {
6210 edje_object_signal_emit(sd->drop, "e,state,unselected", "e");
6211 sd->drop_show = EINA_FALSE;
6212 }
6213 if (sd->drop_in_show)
6214 {
6215 edje_object_signal_emit(sd->drop_in, "e,state,unselected", "e");
6216 sd->drop_in_show = EINA_FALSE;
6217 }
6218 if (!sd->drop_all)
6219 {
6220 edje_object_signal_emit(sd->overlay, "e,state,drop,start", "e");
6221 sd->drop_all = EINA_TRUE;
6222 }
6223 sd->drop_icon = NULL;
6224 sd->drop_after = EINA_FALSE;
6225 }
6226
6227 /* FIXME: prototype + reposition + implement */
6228 static void
_e_fm2_dnd_drop_all_hide(Evas_Object * obj)6229 _e_fm2_dnd_drop_all_hide(Evas_Object *obj)
6230 {
6231 E_Fm2_Smart_Data *sd;
6232
6233 sd = evas_object_smart_data_get(obj);
6234 if (!sd) return;
6235 if (sd->drop_all)
6236 {
6237 edje_object_signal_emit(sd->overlay, "e,state,drop,stop", "e");
6238 sd->drop_all = EINA_FALSE;
6239 }
6240 }
6241
6242 /* FIXME: prototype + reposition + implement */
6243 static void
_e_fm2_dnd_drop_show(E_Fm2_Icon * ic,int after)6244 _e_fm2_dnd_drop_show(E_Fm2_Icon *ic, int after)
6245 {
6246 int emit = 0;
6247
6248 if ((ic->sd->drop_icon == ic) &&
6249 (ic->sd->drop_after == after)) return;
6250 if (((!ic->sd->drop_icon)) ||
6251 ((after < 0) && (ic->sd->drop_after >= 0)) ||
6252 ((after >= 0) && (ic->sd->drop_after < 0)))
6253 emit = 1;
6254 evas_object_smart_callback_call(ic->sd->obj, "dnd_changed", &ic->info);
6255 ic->sd->drop_icon = ic;
6256 ic->sd->drop_after = after;
6257 if (emit)
6258 {
6259 if (ic->sd->drop_after != -1)
6260 {
6261 edje_object_signal_emit(ic->sd->drop_in, "e,state,unselected", "e");
6262 edje_object_signal_emit(ic->sd->drop, "e,state,selected", "e");
6263 ic->sd->drop_in_show = EINA_FALSE;
6264 ic->sd->drop_show = EINA_TRUE;
6265 }
6266 else
6267 {
6268 edje_object_signal_emit(ic->sd->drop, "e,state,unselected", "e");
6269 edje_object_signal_emit(ic->sd->drop_in, "e,state,selected", "e");
6270 ic->sd->drop_in_show = EINA_TRUE;
6271 ic->sd->drop_show = EINA_FALSE;
6272 }
6273 }
6274 _e_fm2_dnd_drop_all_hide(ic->sd->obj);
6275 _e_fm2_dnd_drop_configure(ic->sd->obj);
6276 }
6277
6278 /* FIXME: prototype + reposition + implement */
6279 static void
_e_fm2_dnd_drop_hide(Evas_Object * obj)6280 _e_fm2_dnd_drop_hide(Evas_Object *obj)
6281 {
6282 E_Fm2_Smart_Data *sd;
6283
6284 sd = evas_object_smart_data_get(obj);
6285 if (!sd) return;
6286 if (sd->drop_show)
6287 {
6288 edje_object_signal_emit(sd->drop, "e,state,unselected", "e");
6289 sd->drop_show = EINA_FALSE;
6290 }
6291 if (sd->drop_in_show)
6292 {
6293 edje_object_signal_emit(sd->drop_in, "e,state,unselected", "e");
6294 sd->drop_in_show = EINA_FALSE;
6295 }
6296 sd->drop_icon = NULL;
6297 sd->drop_after = EINA_FALSE;
6298 }
6299
6300 /* FIXME: prototype + reposition + implement */
6301 static Eina_Bool
_e_fm2_dnd_type_implemented(const char * type)6302 _e_fm2_dnd_type_implemented(const char *type)
6303 {
6304 const char ***t;
6305
6306 for (t = _e_fm2_dnd_types; *t; t++)
6307 {
6308 if (type == **t) return EINA_TRUE;
6309 }
6310 return EINA_FALSE;
6311 }
6312
6313 static void
_e_fm2_dnd_finish(Evas_Object * obj,int refresh)6314 _e_fm2_dnd_finish(Evas_Object *obj, int refresh)
6315 {
6316 E_Fm2_Smart_Data *sd;
6317 E_Fm2_Icon *ic;
6318 const Eina_List *l;
6319
6320 sd = evas_object_smart_data_get(obj);
6321 if (!sd) return;
6322 if (!sd->drag) return;
6323 sd->drag = EINA_FALSE;
6324 EINA_LIST_FOREACH(sd->icons, l, ic)
6325 {
6326 ic->drag.src = EINA_FALSE;
6327 if (ic->drag.hidden) continue;
6328 if (ic->obj) evas_object_show(ic->obj);
6329 if (ic->obj_icon) evas_object_show(ic->obj_icon);
6330 }
6331 if (refresh) e_fm2_refresh(obj);
6332 }
6333
6334 static Eina_Bool
_e_fm2_cb_dnd_scroller(E_Fm2_Smart_Data * sd)6335 _e_fm2_cb_dnd_scroller(E_Fm2_Smart_Data *sd)
6336 {
6337 int cx = 0, cy = 0;
6338 int x = 0, y = 0, w = 0, h = 0;
6339 int mx = 0, my = 0;
6340 double px = 0.0;
6341
6342 #undef EFM_MAX_PIXEL_DRAG
6343 #define EFM_MAX_PIXEL_DRAG 25
6344
6345 px = EFM_MAX_PIXEL_DRAG * ecore_animator_frametime_get();
6346 x = y = 500;
6347
6348 if (sd->w < 100)
6349 w = sd->w / 5;
6350 else if (sd->w < 500)
6351 w = sd->w / 8;
6352 else
6353 w = sd->w / 10;
6354
6355 if (sd->h < 100)
6356 h = sd->h / 5;
6357 else if (sd->h < 500)
6358 h = sd->h / 8;
6359 else
6360 h = sd->h / 10;
6361
6362 if (sd->dnd_current.x < w)
6363 {
6364 /* left scroll */
6365 x = lround((-px) * (double)(w - sd->dnd_current.x));
6366 }
6367 else if (sd->dnd_current.x > sd->w - w)
6368 {
6369 /* right scroll */
6370 x = lround((px) * (double)(sd->dnd_current.x - (sd->w - w)));
6371 }
6372
6373 if (sd->dnd_current.y < h)
6374 {
6375 /* up scroll */
6376 y = lround((-px) * (double)(h - sd->dnd_current.y));
6377 }
6378 else if (sd->dnd_current.y > sd->h - h)
6379 {
6380 /* down scroll */
6381 y = lround((px) * (double)(sd->dnd_current.y - (sd->h - h)));
6382 }
6383
6384 if ((x == 500) && (y == 500)) return EINA_TRUE;
6385
6386 e_fm2_pan_get(sd->obj, &cx, &cy);
6387 e_fm2_pan_max_get(sd->obj, &mx, &my);
6388 x = MIN(cx + x, mx);
6389 y = MIN(cy + y, my);
6390 x = MAX(0, x);
6391 y = MAX(0, y);
6392 e_fm2_pan_set(sd->obj, x, y);
6393 if ((sd->drop_icon) &&
6394 (!E_INSIDE(sd->dnd_current.x, sd->dnd_current.y,
6395 sd->drop_icon->x - sd->drop_icon->sd->pos.x,
6396 sd->drop_icon->y - sd->drop_icon->sd->pos.y,
6397 sd->drop_icon->w, sd->drop_icon->h)))
6398 _e_fm2_dnd_drop_hide(sd->obj);
6399 /*
6400 * FIXME: this is slow and doesn't do much, need a better way...
6401 if (!sd->drop_icon)
6402 _e_fm2_cb_dnd_move(sd, NULL, NULL);
6403 */
6404 #undef EFM_MAX_PIXEL_DRAG
6405 return EINA_TRUE;
6406 }
6407
6408 static void
_e_fm2_cb_dnd_enter(void * data,const char * type,void * event)6409 _e_fm2_cb_dnd_enter(void *data, const char *type, void *event)
6410 {
6411 E_Event_Dnd_Enter *ev;
6412 E_Fm2_Smart_Data *sd = data;
6413
6414 if (!_e_fm2_dnd_type_implemented(type)) return;
6415 ev = (E_Event_Dnd_Enter *)event;
6416 e_drop_handler_action_set(ev->action);
6417 if (!sd->dnd_scroller)
6418 sd->dnd_scroller = ecore_animator_add((Ecore_Task_Cb)_e_fm2_cb_dnd_scroller, sd);
6419 evas_object_smart_callback_call(sd->obj, "dnd_enter", NULL);
6420 }
6421
6422 static Eina_Bool
_e_fm2_cb_dnd_move_helper(E_Fm2_Smart_Data * sd,E_Fm2_Icon * ic,int dx,int dy)6423 _e_fm2_cb_dnd_move_helper(E_Fm2_Smart_Data *sd, E_Fm2_Icon *ic, int dx, int dy)
6424 {
6425 if (!E_INSIDE(dx, dy, ic->x - ic->sd->pos.x, ic->y - ic->sd->pos.y, ic->w, ic->h)) return EINA_FALSE;
6426 if (ic->drag.dnd) return EINA_FALSE;
6427 if (!S_ISDIR(ic->info.statinfo.st_mode))
6428 {
6429 if (ic->sd->drop_icon)
6430 _e_fm2_dnd_drop_hide(sd->obj);
6431 _e_fm2_dnd_drop_all_show(sd->obj);
6432 return EINA_TRUE;
6433 }
6434 /* if list view */
6435 if (_e_fm2_view_mode_get(ic->sd) == E_FM2_VIEW_MODE_LIST)
6436 {
6437 /* if there is a .order file - we can re-order files */
6438 if (ic->sd->order_file)
6439 {
6440 /* if dir: */
6441 if (!ic->sd->config->view.no_subdir_drop)
6442 {
6443 /* if bottom 25% or top 25% then insert between prev or next */
6444 /* if in middle 50% then put in dir */
6445 if (dy <= (ic->y - ic->sd->pos.y + (ic->h / 4)))
6446 _e_fm2_dnd_drop_show(ic, 0);
6447 else if (dy > (ic->y - ic->sd->pos.y + ((ic->h * 3) / 4)))
6448 _e_fm2_dnd_drop_show(ic, 1);
6449 else
6450 _e_fm2_dnd_drop_show(ic, -1);
6451 }
6452 else
6453 {
6454 /* if top 50% or bottom 50% then insert between prev or next */
6455 if (dy <= (ic->y - ic->sd->pos.y + (ic->h / 2)))
6456 _e_fm2_dnd_drop_show(ic, 0);
6457 else
6458 _e_fm2_dnd_drop_show(ic, 1);
6459 }
6460 }
6461 /* if we are over subdirs or files */
6462 else
6463 {
6464 /*
6465 * if it's over a dir - hilight as it will be dropped info
6466 * FIXME: should there be a separate highlighting function for files?
6467 * */
6468 if (!ic->sd->config->view.no_subdir_drop)
6469 _e_fm2_dnd_drop_show(ic, -1);
6470 }
6471 }
6472 else
6473 {
6474 /* if it's over a dir - hilight as it will be dropped in */
6475 if (!ic->sd->config->view.no_subdir_drop)
6476 _e_fm2_dnd_drop_show(ic, -1);
6477 }
6478 return EINA_TRUE;
6479 }
6480
6481 static void
_e_fm2_cb_dnd_move(void * data,const char * type,void * event)6482 _e_fm2_cb_dnd_move(void *data, const char *type, void *event)
6483 {
6484 E_Fm2_Smart_Data *sd;
6485 E_Event_Dnd_Move *ev;
6486 E_Fm2_Icon *ic;
6487 Eina_List *l;
6488 int dx, dy;
6489
6490 sd = data;
6491 /* also called from the scroll animator with only the first param */
6492 if (type && (!_e_fm2_dnd_type_implemented(type))) return;
6493 ev = (E_Event_Dnd_Move *)event;
6494 if (ev)
6495 {
6496 dx = ev->x - sd->x;
6497 dy = ev->y - sd->y;
6498 sd->dnd_current.x = dx, sd->dnd_current.y = dy;
6499 e_drop_handler_action_set(ev->action);
6500 }
6501 else
6502 dx = sd->dnd_current.x, dy = sd->dnd_current.y;
6503
6504 EINA_LIST_FOREACH(sd->icons, l, ic)
6505 if (_e_fm2_cb_dnd_move_helper(sd, ic, dx, dy)) return;
6506 /* FIXME: not over icon - is it within the fm view? if so drop there */
6507 if (E_INSIDE(dx, dy, 0, 0, sd->w, sd->h))
6508 {
6509 #if 0 //this is broken since we don't allow custom list sorting
6510 /* if listview - it is now after last file */
6511 if (_e_fm2_view_mode_get(sd) == E_FM2_VIEW_MODE_LIST)
6512 {
6513 /* if there is a .order file - we can re-order files */
6514 if (sd->order_file)
6515 {
6516 ic = eina_list_last_data_get(sd->icons);
6517 if (ic)
6518 {
6519 if (!ic->drag.dnd)
6520 _e_fm2_dnd_drop_show(ic, 1);
6521 else
6522 _e_fm2_dnd_drop_all_show(sd->obj);
6523 }
6524 else
6525 _e_fm2_dnd_drop_all_show(sd->obj);
6526 }
6527 else
6528 _e_fm2_dnd_drop_all_show(sd->obj);
6529 }
6530 else
6531 #endif
6532 _e_fm2_dnd_drop_all_show(sd->obj);
6533 return;
6534 }
6535 /* outside fm view */
6536 _e_fm2_dnd_drop_hide(sd->obj);
6537 }
6538
6539 static void
_e_fm2_cb_dnd_leave(void * data,const char * type,void * event EINA_UNUSED)6540 _e_fm2_cb_dnd_leave(void *data, const char *type, void *event EINA_UNUSED)
6541 {
6542 E_Fm2_Smart_Data *sd;
6543
6544 sd = data;
6545 if (!_e_fm2_dnd_type_implemented(type)) return;
6546 _e_fm2_dnd_drop_hide(sd->obj);
6547 _e_fm2_dnd_drop_all_hide(sd->obj);
6548 if (sd->dnd_scroller) ecore_animator_del(sd->dnd_scroller);
6549 sd->dnd_scroller = NULL;
6550 sd->dnd_current.x = sd->dnd_current.y = 0;
6551 evas_object_smart_callback_call(sd->obj, "dnd_leave", NULL);
6552 /* NOTE: DO NOT PERFORM ANY OPERATIONS USING sd AT THIS POINT!
6553 * things use this callback to delete the efm object
6554 */
6555 }
6556
6557 static void
_e_fm_file_reorder(const char * file,const char * dst,const char * relative,int after)6558 _e_fm_file_reorder(const char *file, const char *dst, const char *relative, int after)
6559 {
6560 unsigned int length = strlen(file) + 1 + strlen(dst) + 1 + strlen(relative) + 1 + sizeof(after);
6561 char *data, *p;
6562
6563 data = alloca(length);
6564 if (!data) return;
6565
6566 p = data;
6567
6568 #define P(s) memcpy(p, s, strlen(s) + 1); p += strlen(s) + 1
6569 P(file);
6570 P(dst);
6571 P(relative);
6572 #undef P
6573
6574 memcpy(p, &after, sizeof(int));
6575
6576 _e_fm_client_send_new(E_FM_OP_REORDER, data, length);
6577 }
6578
6579 static void
_e_fm_icon_save_position(const char * file,Evas_Coord x,Evas_Coord y,Evas_Coord w,Evas_Coord h)6580 _e_fm_icon_save_position(const char *file, Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_Coord h)
6581 {
6582 E_Fm2_Custom_File *cf, new;
6583
6584 if (!file) return;
6585
6586 cf = e_fm2_custom_file_get(file);
6587 if (!cf)
6588 {
6589 memset(&new, 0, sizeof(E_Fm2_Custom_File));
6590 cf = &new;
6591 }
6592
6593 cf->geom.x = x;
6594 cf->geom.y = y;
6595 cf->geom.res_w = w;
6596 cf->geom.res_h = h;
6597
6598 cf->geom.valid = 1;
6599 e_fm2_custom_file_set(file, cf);
6600 e_fm2_custom_file_flush();
6601 }
6602
6603 static Eina_Bool
_e_fm_drop_menu_queue(Evas_Object * e_fm,void * args,int op)6604 _e_fm_drop_menu_queue(Evas_Object *e_fm, void *args, int op)
6605 {
6606 E_Volume *vol;
6607 E_Fm2_Device_Mount_Op *mop = args;
6608
6609 vol = evas_object_data_del(e_fm, "dnd_queue");
6610 if (!vol) return EINA_FALSE;
6611 if (!vol->mounted)
6612 {
6613 /* this should get picked up by the post-mount callback */
6614 #ifndef HAVE_WAYLAND_ONLY
6615 switch (op)
6616 {
6617 case 0: //copy
6618 mop->action = ECORE_X_ATOM_XDND_ACTION_COPY;
6619 break;
6620
6621 case 1: //move
6622 mop->action = ECORE_X_ATOM_XDND_ACTION_MOVE;
6623 break;
6624
6625 case 2: //link
6626 mop->action = ECORE_X_ATOM_XDND_ACTION_LINK;
6627 break;
6628 }
6629 #endif
6630 return EINA_TRUE;
6631 }
6632 switch (op)
6633 {
6634 case 0: //copy
6635 e_fm2_client_file_copy(e_fm, mop->args);
6636 break;
6637
6638 case 1: //move
6639 e_fm2_client_file_move(e_fm, mop->args);
6640 break;
6641
6642 case 2: //link
6643 e_fm2_client_file_symlink(e_fm, mop->args);
6644 break;
6645 }
6646 vol->mount_ops = eina_inlist_remove(vol->mount_ops, EINA_INLIST_GET(mop));
6647 free(mop->args);
6648 free(mop);
6649 return EINA_TRUE;
6650 }
6651
6652 static void
_e_fm_drop_menu_copy_cb(void * data,E_Menu * m EINA_UNUSED,E_Menu_Item * mi EINA_UNUSED)6653 _e_fm_drop_menu_copy_cb(void *data, E_Menu *m EINA_UNUSED, E_Menu_Item *mi EINA_UNUSED)
6654 {
6655 char *args;
6656
6657 args = evas_object_data_del(data, "drop_menu_data");
6658 if (_e_fm_drop_menu_queue(data, args, 0)) return;
6659 e_fm2_client_file_copy(data, args);
6660 free(args);
6661 }
6662
6663 static void
_e_fm_drop_menu_move_cb(void * data,E_Menu * m EINA_UNUSED,E_Menu_Item * mi EINA_UNUSED)6664 _e_fm_drop_menu_move_cb(void *data, E_Menu *m EINA_UNUSED, E_Menu_Item *mi EINA_UNUSED)
6665 {
6666 char *args;
6667
6668 args = evas_object_data_del(data, "drop_menu_data");
6669 if (_e_fm_drop_menu_queue(data, args, 1)) return;
6670 e_fm2_client_file_move(data, args);
6671 free(args);
6672 }
6673
6674 static void
_e_fm_drop_menu_symlink_cb(void * data,E_Menu * m EINA_UNUSED,E_Menu_Item * mi EINA_UNUSED)6675 _e_fm_drop_menu_symlink_cb(void *data, E_Menu *m EINA_UNUSED, E_Menu_Item *mi EINA_UNUSED)
6676 {
6677 char *args;
6678
6679 args = evas_object_data_del(data, "drop_menu_data");
6680 if (_e_fm_drop_menu_queue(data, args, 2)) return;
6681 e_fm2_client_file_symlink(data, args);
6682 free(args);
6683 }
6684
6685 static void
_e_fm_drop_menu_abort_cb(void * data,E_Menu * m EINA_UNUSED,E_Menu_Item * mi EINA_UNUSED)6686 _e_fm_drop_menu_abort_cb(void *data, E_Menu *m EINA_UNUSED, E_Menu_Item *mi EINA_UNUSED)
6687 {
6688 free(evas_object_data_del(data, "drop_menu_data"));
6689 }
6690
6691 static void
_e_fm_drop_menu_free(void * data)6692 _e_fm_drop_menu_free(void *data)
6693 {
6694 Evas_Object *e_fm;
6695
6696 e_fm = e_object_data_get(data);
6697 if (!e_fm) return;
6698 evas_object_data_del(e_fm, "drop_menu_data");
6699 }
6700
6701 static void
_e_fm2_cb_dnd_selection_notify_post_mount_fail(E_Volume * vol)6702 _e_fm2_cb_dnd_selection_notify_post_mount_fail(E_Volume *vol)
6703 {
6704 E_Fm2_Device_Mount_Op *mop;
6705
6706 while (vol->mount_ops)
6707 {
6708 E_Fm2_Icon *ic;
6709
6710 mop = (E_Fm2_Device_Mount_Op *)vol->mount_ops;
6711 ic = mop->ic;
6712 vol->mount_ops = eina_inlist_remove(vol->mount_ops, EINA_INLIST_GET(mop));
6713 /* FIXME: this can be made more clear */
6714 e_util_dialog_show(_("Error"), _("The recent DND operation requested for '%s' has failed."), vol->label ? : vol->udi);
6715 evas_object_data_del(ic->sd->obj, "dnd_queue");
6716 free(mop->args);
6717 ic->sd->mount_ops = eina_list_remove(ic->sd->mount_ops, mop);
6718 free(mop);
6719 }
6720 }
6721
6722 static void
_e_fm2_cb_dnd_selection_notify_post_mount(E_Volume * vol)6723 _e_fm2_cb_dnd_selection_notify_post_mount(E_Volume *vol)
6724 {
6725 E_Fm2_Device_Mount_Op *mop = NULL;
6726 const char *mp;
6727 Eina_Inlist *l;
6728
6729 mp = e_fm2_device_volume_mountpoint_get(vol);
6730 EINA_INLIST_FOREACH_SAFE(vol->mount_ops, l, mop)
6731 {
6732 E_Fm2_Icon *ic = mop->ic;
6733
6734 if (mp)
6735 {
6736 mop->args = e_util_string_append_quoted(mop->args, &mop->size, &mop->length, mp);
6737 #ifndef HAVE_WAYLAND_ONLY
6738 if (mop->action == ECORE_X_ATOM_XDND_ACTION_ASK)
6739 continue;
6740 else if (mop->action == ECORE_X_ATOM_XDND_ACTION_MOVE)
6741 e_fm2_client_file_move(ic->sd->obj, mop->args);
6742 else if (mop->action == ECORE_X_ATOM_XDND_ACTION_COPY)
6743 e_fm2_client_file_copy(ic->sd->obj, mop->args);
6744 else if (mop->action == ECORE_X_ATOM_XDND_ACTION_LINK)
6745 e_fm2_client_file_symlink(ic->sd->obj, mop->args);
6746 #endif
6747 }
6748 else
6749 e_util_dialog_show(_("Error"), _("The recent DND operation requested for '%s' has failed."), vol->label ? : vol->udi);
6750 free(mop->args);
6751 vol->mount_ops = eina_inlist_remove(vol->mount_ops, EINA_INLIST_GET(mop));
6752 ic->sd->mount_ops = eina_list_remove(ic->sd->mount_ops, mop);
6753 free(mop);
6754 }
6755 eina_stringshare_del(mp);
6756 }
6757
6758 static void
_e_fm2_cb_dnd_selection_notify_post_umount(E_Volume * vol)6759 _e_fm2_cb_dnd_selection_notify_post_umount(E_Volume *vol)
6760 {
6761 E_Fm2_Device_Mount_Op *mop;
6762
6763 EINA_INLIST_FOREACH(vol->mount_ops, mop)
6764 {
6765 E_Fm2_Icon *ic = mop->ic;
6766
6767 if (!ic) continue;
6768 if (ic->mount_timer) ecore_timer_del(ic->mount_timer);
6769 ic->mount_timer = NULL;
6770 ic->mount = NULL;
6771 ic->sd->mount_ops = eina_list_remove(ic->sd->mount_ops, mop);
6772 }
6773 }
6774
6775 static Eina_Bool
_e_fm2_cb_dnd_selection_notify_post_mount_timer(E_Fm2_Icon * ic)6776 _e_fm2_cb_dnd_selection_notify_post_mount_timer(E_Fm2_Icon *ic)
6777 {
6778 e_fm2_device_unmount(ic->mount);
6779 ic->mount = NULL;
6780 ic->mount_timer = NULL;
6781 return EINA_FALSE;
6782 }
6783
6784 static void
_e_fm2_cb_dnd_selection_notify(void * data,const char * type,void * event)6785 _e_fm2_cb_dnd_selection_notify(void *data, const char *type, void *event)
6786 {
6787 E_Fm2_Smart_Data *sd = data;
6788 E_Event_Dnd_Drop *ev = event;
6789 E_Fm2_Icon *ic = NULL;
6790 Eina_List *fsel, *l, *ll, *il, *isel = NULL;
6791 char buf[PATH_MAX];
6792 const char *fp;
6793 Evas_Coord ox, oy;
6794 Evas_Object *obj;
6795 int adjust_icons = 0;
6796 char dirpath[PATH_MAX];
6797 char *args = NULL;
6798 size_t size = 0;
6799 size_t length = 0;
6800 Eina_Bool lnk = EINA_FALSE, memerr = EINA_FALSE, mnt = EINA_FALSE;
6801 E_Fm2_Device_Mount_Op *mop = NULL;
6802
6803 if (!_e_fm2_dnd_type_implemented(type)) return;
6804 if (type == _e_fm2_mime_xmozurl)
6805 {
6806 const char **name, *s;
6807 Efreet_Desktop *desktop;
6808 E_Dnd_X_Moz_Url *moz = ev->data;
6809 unsigned int x = 0;
6810
6811 EINA_INARRAY_FOREACH(moz->link_names, name)
6812 {
6813 int p;
6814
6815 s = *name;
6816 for (p = 0; p < 7; p++)
6817 {
6818 Eina_Bool done = EINA_FALSE;
6819
6820 if (!s[p]) break;
6821 if ((s[p] == ':') && (s[p + 1] == '/'))
6822 {
6823 s = ecore_file_file_get(s);
6824 done = EINA_TRUE;
6825 }
6826 if (done) break;
6827 }
6828 if (!s[0]) s = ecore_file_file_get(*name);
6829 if (!s)
6830 {
6831 s = *(char**)eina_inarray_nth(moz->links, x);
6832 s = ecore_file_file_get(s);
6833 }
6834 /* FIXME: should this filename be sanitized somehow? */
6835 if (sd->drop_icon && sd->drop_after == -1)
6836 {
6837 //into drop_icon
6838 if (S_ISDIR(sd->drop_icon->info.statinfo.st_mode))
6839 {
6840 if (sd->drop_icon->info.link)
6841 snprintf(dirpath, sizeof(dirpath), "%s/Link to %s.desktop", sd->drop_icon->info.link, s);
6842 else
6843 snprintf(dirpath, sizeof(dirpath), "%s/%s/Link to %s.desktop", sd->realpath, sd->drop_icon->info.file, s);
6844 }
6845 else
6846 snprintf(buf, sizeof(buf), "%s/Link to %s.desktop", sd->realpath, s);
6847 }
6848 else
6849 snprintf(buf, sizeof(buf), "%s/Link to %s.desktop", sd->realpath, s);
6850 if (ecore_file_exists(buf))
6851 {
6852 e_util_dialog_show(_("Error"), _("A link to the requested URL already exists!"));
6853 continue;
6854 }
6855 desktop = efreet_desktop_empty_new(buf);
6856 desktop->type = EFREET_DESKTOP_TYPE_LINK;
6857 snprintf(buf, sizeof(buf), "Link to %s", *name);
6858 desktop->name = strdup(buf);
6859 desktop->icon = strdup("text-html");
6860 desktop->url = strdup(*(char**)eina_inarray_nth(moz->links, x));
6861 efreet_desktop_save(desktop);
6862 efreet_desktop_free(desktop);
6863 x++;
6864 }
6865 return;
6866 }
6867 fsel = e_fm2_uri_path_list_get(ev->data);
6868 fp = eina_list_data_get(fsel);
6869 if (fp && sd->realpath && ((sd->drop_all) || (!sd->drop_icon)))
6870 {
6871 const char *f;
6872
6873 /* if we're dropping into a link_drop view, we need to stop here so we
6874 * don't accidentally replace an original file with a link!
6875 */
6876 f = ecore_file_file_get(fp);
6877 if ((((f - fp - 1 == 0) && (!strcmp(sd->realpath, "/"))) ||
6878 ((f - fp - 1 > 0) && (!strncmp(sd->realpath, fp, f - fp - 1)))) &&
6879 ((size_t)(f - fp - 1) == strlen(sd->realpath)))
6880 {
6881 #ifndef HAVE_WAYLAND_ONLY
6882 if ((e_drop_handler_action_get() == ECORE_X_ATOM_XDND_ACTION_MOVE) || (sd->config->view.link_drop))
6883 {
6884 lnk = EINA_TRUE;
6885 if (_e_fm2_view_mode_get(sd) != E_FM2_VIEW_MODE_CUSTOM_ICONS)
6886 goto end;
6887 memerr = EINA_TRUE; // prevent actual file move op
6888 }
6889 #endif
6890 }
6891 }
6892 if (!fsel)
6893 {
6894 #ifndef HAVE_WAYLAND_ONLY
6895 if (e_drop_handler_action_get() == ECORE_X_ATOM_XDND_ACTION_COPY)
6896 {
6897 /* most likely someone is trying to dnd some text to us */
6898 _e_fm2_new_file(sd, NULL, NULL);
6899 EINA_LIST_FOREACH(ev->data, l, fp)
6900 isel = eina_list_append(isel, strdup(fp));
6901 ecore_thread_global_data_add("efm_text_uri_list", isel, (Eina_Free_Cb)e_util_string_list_free, 0);
6902 }
6903 #endif
6904 /* no files, abort! */
6905 return;
6906 }
6907
6908 isel = _e_fm2_uri_selected_icon_list_get(fsel);
6909 ox = 0; oy = 0;
6910 EINA_LIST_FOREACH(isel, l, ic)
6911 {
6912 if (!ic) continue;
6913 if (ic->drag.src)
6914 {
6915 ox = ic->x;
6916 oy = ic->y;
6917 break;
6918 }
6919 }
6920
6921 /* note - logic.
6922 * if drop file prefix path matches extra_file_source then it can be
6923 * and indirect link - dont MOVE the file just add filename to list.
6924 * if not literally move the file in. if move can't work - try a copy.
6925 * on a literal move find any fm views for the dir of the dropped file
6926 * and refresh those, as well as refresh current target fm dir
6927 */
6928 if (sd->drop_all) /* drop arbitrarily into the dir */
6929 {
6930 Evas_Coord x, y;
6931
6932 /* move file into this fm dir */
6933 for (ll = fsel, il = isel; ll; ll = eina_list_next(ll), il = eina_list_next(il))
6934 {
6935 ic = eina_list_data_get(il);
6936 fp = eina_list_data_get(ll);
6937 if (!fp) continue;
6938
6939 if ((ic) && (_e_fm2_view_mode_get(sd) == E_FM2_VIEW_MODE_CUSTOM_ICONS))
6940 {
6941 /* dnd doesn't tell me all the co-ords of the icons being dragged so i can't place them accurately.
6942 * need to fix this. ev->data probably needs to become more compelx than a list of url's
6943 */
6944
6945 x = ev->x + (ic->x - ox) - ic->drag.x + sd->pos.x - sd->x;
6946 y = ev->y + (ic->y - oy) - ic->drag.y + sd->pos.y - sd->y;
6947
6948 if (x < 0) x = 0;
6949 if (y < 0) y = 0;
6950
6951 if (sd->config->view.fit_custom_pos)
6952 {
6953 if ((x + ic->w) > sd->w) x = (sd->w - ic->w);
6954 if ((y + ic->h) > sd->h) y = (sd->h - ic->h);
6955 }
6956
6957 if (ic->sd == sd)
6958 {
6959 ic->x = x;
6960 ic->y = y;
6961 ic->saved_pos = EINA_TRUE;
6962 adjust_icons = 1;
6963 }
6964
6965 snprintf(buf, sizeof(buf), "%s/%s",
6966 sd->realpath, ecore_file_file_get(fp));
6967 _e_fm_icon_save_position(buf, x, y, sd->w, sd->h);
6968 }
6969
6970 if (!memerr)
6971 {
6972 args = e_util_string_append_quoted(args, &size, &length, fp);
6973 if (!args) memerr = EINA_TRUE;
6974 else
6975 {
6976 args = e_util_string_append_char(args, &size, &length, ' ');
6977 if (!args) memerr = EINA_TRUE;
6978 else if (ic) ic->drag.hidden = EINA_TRUE;
6979 }
6980 }
6981 eina_stringshare_del(fp);
6982 }
6983 if (adjust_icons)
6984 {
6985 sd->max.w = 0;
6986 sd->max.h = 0;
6987 EINA_LIST_FOREACH(sd->icons, l, ic)
6988 {
6989 if ((ic->x + ic->w) > sd->max.w) sd->max.w = ic->x + ic->w;
6990 if ((ic->y + ic->h) > sd->max.h) sd->max.h = ic->y + ic->h;
6991 }
6992 _e_fm2_obj_icons_place(sd);
6993 evas_object_smart_callback_call(sd->obj, "changed", NULL);
6994 }
6995
6996 if (!memerr)
6997 args = e_util_string_append_quoted(args, &size, &length, sd->realpath);
6998 }
6999 else if (sd->drop_icon) /* into or before/after an icon */
7000 {
7001 if (sd->drop_after == -1) /* put into subdir/file in icon */
7002 {
7003 /* move file into dir that this icon is for */
7004 for (ll = fsel, il = isel; ll && il; ll = eina_list_next(ll), il = eina_list_next(il))
7005 {
7006 fp = eina_list_data_get(ll);
7007 if (!fp) continue;
7008 if (!memerr)
7009 {
7010 args = e_util_string_append_quoted(args, &size, &length, fp);
7011 if (!args) memerr = EINA_TRUE;
7012 else
7013 {
7014 args = e_util_string_append_char(args, &size, &length, ' ');
7015 if (!args) memerr = EINA_TRUE;
7016 else ic->drag.hidden = EINA_TRUE;
7017 }
7018 }
7019 eina_stringshare_del(fp);
7020 }
7021
7022 if (!memerr)
7023 {
7024 while (sd->drop_icon->info.removable)
7025 {
7026 /* we're dropping onto a device
7027 * cross your fingers and hope for good luck
7028 */
7029 E_Volume *vol;
7030 const char *mp;
7031
7032 vol = e_fm2_device_volume_find_fast(sd->drop_icon->info.link);
7033 if (!vol) break;
7034 if (vol->mounted)
7035 {
7036 mp = e_fm2_device_volume_mountpoint_get(vol);
7037 if (mp)
7038 {
7039 /* luuuuuuckkyyyyyyyyy */
7040 args = e_util_string_append_quoted(args, &size, &length, mp);
7041 if (!args) memerr = EINA_TRUE;
7042 eina_stringshare_del(mp);
7043 mnt = EINA_TRUE;
7044 break;
7045 }
7046 }
7047 else if (!sd->drop_icon->mount)
7048 sd->drop_icon->mount = e_fm2_device_mount(vol, (Ecore_Cb)_e_fm2_cb_dnd_selection_notify_post_mount,
7049 (Ecore_Cb)_e_fm2_cb_dnd_selection_notify_post_mount_fail, (Ecore_Cb)_e_fm2_cb_dnd_selection_notify_post_umount,
7050 NULL, vol);
7051
7052 if (sd->drop_icon->mount_timer) ecore_timer_loop_reset(sd->drop_icon->mount_timer);
7053 else sd->drop_icon->mount_timer = ecore_timer_loop_add(15., (Ecore_Task_Cb)_e_fm2_cb_dnd_selection_notify_post_mount_timer, sd->drop_icon);
7054 #ifndef HAVE_WAYLAND_ONLY
7055 if ((e_drop_handler_action_get() == ECORE_X_ATOM_XDND_ACTION_ASK) ||
7056 ((sd->config->view.link_drop) || (!sd->drop_icon)))
7057 /* this here's some buuuullshit */
7058 evas_object_data_set(sd->obj, "dnd_queue", vol);
7059 else if (e_drop_handler_action_get() == ECORE_X_ATOM_XDND_ACTION_MOVE)
7060 /* set copy if we're over a device */
7061 e_drop_handler_action_set(ECORE_X_ATOM_XDND_ACTION_COPY);
7062 #endif
7063 mop = e_fm2_device_mount_op_add(sd->drop_icon->mount, args, size, length);
7064 mop->ic = sd->drop_icon;
7065 mop->mnt = sd->drop_icon->mount;
7066 sd->mount_ops = eina_list_append(sd->mount_ops, mop);
7067 /*
7068 * set lnk here to prevent deleting the show timer
7069 */
7070 mnt = lnk = EINA_TRUE;
7071 break;
7072 }
7073 if (!mnt)
7074 {
7075 if (S_ISDIR(sd->drop_icon->info.statinfo.st_mode))
7076 {
7077 if (sd->drop_icon->info.link)
7078 snprintf(dirpath, sizeof(dirpath), "%s", sd->drop_icon->info.link);
7079 else
7080 snprintf(dirpath, sizeof(dirpath), "%s/%s", sd->realpath, sd->drop_icon->info.file);
7081 }
7082 else
7083 snprintf(dirpath, sizeof(dirpath), "%s", sd->realpath);
7084
7085 args = e_util_string_append_quoted(args, &size, &length, dirpath);
7086 if (!args) memerr = EINA_TRUE;
7087 }
7088 }
7089 }
7090 else if (sd->realpath)
7091 {
7092 if (_e_fm2_view_mode_get(sd) == E_FM2_VIEW_MODE_LIST && sd->order_file) /* list */
7093 {
7094 for (ll = fsel, il = isel; ll && il; ll = eina_list_next(ll), il = eina_list_next(il))
7095 {
7096 fp = eina_list_data_get(ll);
7097 if (!fp) continue;
7098 if (!memerr)
7099 {
7100 snprintf(buf, sizeof(buf), "%s/%s", sd->realpath, ecore_file_file_get(fp));
7101 args = e_util_string_append_quoted(args, &size, &length, fp);
7102 if (!args) memerr = EINA_TRUE;
7103 else
7104 {
7105 args = e_util_string_append_char(args, &size, &length, ' ');
7106 if (!args) memerr = EINA_TRUE;
7107 else ic->drag.hidden = EINA_TRUE;
7108 }
7109 }
7110
7111 _e_fm_file_reorder(ecore_file_file_get(fp), sd->realpath, sd->drop_icon->info.file, sd->drop_after);
7112
7113 eina_stringshare_del(fp);
7114 }
7115
7116 if (!memerr)
7117 {
7118 args = e_util_string_append_quoted(args, &size, &length, sd->realpath);
7119 if (!args) memerr = EINA_TRUE;
7120 }
7121 }
7122 else
7123 {
7124 for (ll = fsel, il = isel; ll && il; ll = eina_list_next(ll), il = eina_list_next(il))
7125 {
7126 fp = eina_list_data_get(ll);
7127 if (!fp) continue;
7128
7129 if (!memerr)
7130 {
7131 args = e_util_string_append_quoted(args, &size, &length, fp);
7132 if (!args) memerr = EINA_TRUE;
7133 else
7134 {
7135 args = e_util_string_append_char(args, &size, &length, ' ');
7136 if (!args) memerr = EINA_TRUE;
7137 else ic->drag.hidden = EINA_TRUE;
7138 }
7139 }
7140 eina_stringshare_del(fp);
7141 }
7142 if (!memerr)
7143 {
7144 args = e_util_string_append_quoted(args, &size, &length, sd->realpath);
7145 if (!args) memerr = EINA_TRUE;
7146 }
7147 }
7148 }
7149 }
7150
7151 if (args)
7152 {
7153 Eina_Bool do_lnk = EINA_FALSE, do_move = EINA_FALSE, do_copy = EINA_FALSE;
7154
7155 #ifndef HAVE_WAYLAND_ONLY
7156 if (e_drop_handler_action_get() == ECORE_X_ATOM_XDND_ACTION_COPY)
7157 {
7158 lnk = EINA_TRUE;
7159 if (sd->config->view.link_drop && (!sd->drop_icon))
7160 do_lnk = EINA_TRUE;
7161 else
7162 do_copy = EINA_TRUE;
7163 }
7164 else if (e_drop_handler_action_get() == ECORE_X_ATOM_XDND_ACTION_MOVE)
7165 {
7166 if (sd->config->view.link_drop)
7167 lnk = do_lnk = EINA_TRUE;
7168 else
7169 do_move = EINA_TRUE;
7170 }
7171 else if (e_drop_handler_action_get() == ECORE_X_ATOM_XDND_ACTION_ASK)
7172 {
7173 if (sd->config->view.link_drop && (!sd->drop_icon))
7174 do_lnk = lnk = EINA_TRUE;
7175 }
7176 if (mnt && mop)
7177 mop->action = (do_lnk * ECORE_X_ATOM_XDND_ACTION_LINK) +
7178 (do_copy * ECORE_X_ATOM_XDND_ACTION_COPY) + (do_move * ECORE_X_ATOM_XDND_ACTION_MOVE) +
7179 (((!do_copy) && (!do_move) && (!do_lnk)) * ECORE_X_ATOM_XDND_ACTION_ASK);
7180 else if (do_lnk)
7181 e_fm2_client_file_symlink(sd->obj, args);
7182 else if (do_copy)
7183 e_fm2_client_file_copy(sd->obj, args);
7184 else if (do_move)
7185 e_fm2_client_file_move(sd->obj, args);
7186 #endif
7187 if ((!do_lnk) && (!do_copy) && (!do_move))
7188 {
7189 e_fm2_drop_menu(sd->obj, args);
7190 if (mnt && mop)
7191 evas_object_data_set(sd->obj, "drop_menu_data", mop);
7192 E_LIST_FOREACH(isel, _e_fm2_cb_drag_finished_show);
7193 }
7194 if (((!mnt) || (!mop)) && (do_lnk || do_copy || do_move))
7195 free(args);
7196 }
7197 end:
7198 _e_fm2_dnd_drop_hide(sd->obj);
7199 _e_fm2_dnd_drop_all_hide(sd->obj);
7200 _e_fm2_list_walking++;
7201 EINA_LIST_FOREACH(_e_fm2_list, l, obj)
7202 {
7203 if ((_e_fm2_list_walking > 0) &&
7204 (eina_list_data_find(_e_fm2_list_remove, obj))) continue;
7205 _e_fm2_dnd_finish(obj, 0);
7206 }
7207 _e_fm2_list_walking--;
7208 if (_e_fm2_list_walking == 0)
7209 {
7210 EINA_LIST_FREE(_e_fm2_list_remove, obj)
7211 {
7212 _e_fm2_list = eina_list_remove(_e_fm2_list, obj);
7213 }
7214 }
7215 eina_list_free(fsel);
7216 EINA_LIST_FREE(isel, ic)
7217 if (ic->drag.dnd_end_timer && (!lnk))
7218 {
7219 ecore_timer_del(ic->drag.dnd_end_timer);
7220 ic->drag.dnd_end_timer = NULL;
7221 }
7222 }
7223
7224 static void
_e_fm2_mouse_2_handler(E_Fm2_Icon * ic,void * evas_event)7225 _e_fm2_mouse_2_handler(E_Fm2_Icon *ic, void *evas_event)
7226 {
7227 int multi_sel = 1;
7228 Eina_List *l;
7229 E_Fm2_Icon *ic2;
7230
7231 if (!evas_event) return;
7232
7233 if (ic->sd->config->selection.single)
7234 multi_sel = 0;
7235
7236 EINA_LIST_FOREACH(ic->sd->icons, l, ic2)
7237 ic2->last_selected = 0;
7238 if (ic->selected)
7239 _e_fm2_icon_deselect(ic);
7240 else
7241 {
7242 if (!multi_sel)
7243 {
7244 ic2 = eina_list_data_get(ic->sd->selected_icons);
7245 if (ic2) _e_fm2_icon_deselect(ic2);
7246 }
7247 _e_fm2_icon_select(ic);
7248 _e_fm2_icon_make_visible(ic);
7249 ic->last_selected = EINA_TRUE;
7250 }
7251 evas_object_smart_callback_call(ic->sd->obj, "selection_change", NULL);
7252 }
7253
7254 /* FIXME: prototype */
7255 static int
_e_fm2_mouse_1_handler(E_Fm2_Icon * ic,int up,void * evas_event)7256 _e_fm2_mouse_1_handler(E_Fm2_Icon *ic, int up, void *evas_event)
7257 {
7258 Evas_Event_Mouse_Down *ed = NULL;
7259 Evas_Event_Mouse_Up *eu = NULL;
7260 Evas_Modifier *modifiers;
7261 int multi_sel = 0, range_sel = 0, sel_change = 0;
7262 static unsigned int down_timestamp = 0;
7263
7264 if (!evas_event) return 0;
7265
7266 if (!up)
7267 {
7268 ed = evas_event;
7269 modifiers = ed->modifiers;
7270 }
7271 else
7272 {
7273 eu = evas_event;
7274 modifiers = eu->modifiers;
7275 }
7276 if (ed && ic->sd->config->view.single_click_delay)
7277 down_timestamp = ed->timestamp;
7278
7279 if (!ic->sd->config->selection.windows_modifiers)
7280 {
7281 if (evas_key_modifier_is_set(modifiers, "Shift"))
7282 range_sel = 1;
7283 else if (evas_key_modifier_is_set(modifiers, "Control"))
7284 multi_sel = 1;
7285 }
7286 else
7287 {
7288 if (evas_key_modifier_is_set(modifiers, "Control"))
7289 range_sel = 1;
7290 else if (evas_key_modifier_is_set(modifiers, "Shift"))
7291 multi_sel = 1;
7292 }
7293 if (ic->sd->config->selection.single)
7294 {
7295 multi_sel = 0;
7296 range_sel = 0;
7297 }
7298
7299 /*
7300 * On mouse up, check if we want to do in place open
7301 */
7302 if ((eu) &&
7303 (!multi_sel) &&
7304 (!range_sel) &&
7305 (ic->sd->config->view.single_click) &&
7306 ((eu->timestamp - down_timestamp) > ic->sd->config->view.single_click_delay))
7307 {
7308 if (_e_fm2_inplace_open(ic) == 1) return 1;
7309 }
7310
7311 if (range_sel)
7312 {
7313 if (!up) _e_fm2_icon_range_select(ic);
7314 }
7315 else if ((!multi_sel) && ((up) || ((!up) && (!ic->selected))))
7316 {
7317 const Eina_List *l;
7318 E_Fm2_Icon *ic2;
7319 /* desel others */
7320 EINA_LIST_FOREACH(ic->sd->icons, l, ic2)
7321 {
7322 if (ic2 != ic)
7323 {
7324 if (ic2->selected)
7325 {
7326 _e_fm2_icon_deselect(ic2);
7327 sel_change = 1;
7328 }
7329 }
7330 }
7331 }
7332 else
7333 {
7334 if (!up)
7335 {
7336 const Eina_List *l;
7337 E_Fm2_Icon *ic2;
7338 EINA_LIST_FOREACH(ic->sd->icons, l, ic2)
7339 ic2->last_selected = 0;
7340 }
7341 }
7342 if ((multi_sel) && (ic->selected))
7343 {
7344 if ((up) && (!ic->drag.dnd) && (!ic->down_sel))
7345 {
7346 sel_change = 1;
7347 _e_fm2_icon_deselect(ic);
7348 }
7349 }
7350 else
7351 {
7352 if (!up)
7353 {
7354 if (!ic->selected) sel_change = EINA_TRUE;
7355 _e_fm2_icon_select(ic);
7356 _e_fm2_icon_make_visible(ic);
7357 ic->down_sel = EINA_TRUE;
7358 ic->last_selected = EINA_TRUE;
7359 }
7360 }
7361 if (sel_change)
7362 evas_object_smart_callback_call(ic->sd->obj, "selection_change", NULL);
7363 if (ic->sd->config->view.single_click && (!range_sel) && (!multi_sel))
7364 {
7365 if (eu && (eu->timestamp - down_timestamp) > ic->sd->config->view.single_click_delay)
7366 {
7367 int icon_pos_x = ic->x + ic->sd->x - ic->sd->pos.x;
7368 int icon_pos_y = ic->y + ic->sd->y - ic->sd->pos.y;
7369
7370 if (eu->output.x >= icon_pos_x && eu->output.x <= (icon_pos_x + ic->w) &&
7371 eu->output.y >= icon_pos_y && eu->output.y <= (icon_pos_y + ic->h))
7372 evas_object_smart_callback_call(ic->sd->obj, "selected", NULL);
7373 }
7374 }
7375 return 0;
7376 }
7377
7378 static void
_e_fm2_cb_icon_mouse_down(void * data,Evas * e EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_info)7379 _e_fm2_cb_icon_mouse_down(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info)
7380 {
7381 Evas_Event_Mouse_Down *ev;
7382 E_Fm2_Icon *ic;
7383
7384 ic = data;
7385 ev = event_info;
7386
7387 if (ic->entry_widget)
7388 return;
7389
7390 _e_fm2_typebuf_hide(ic->sd->obj);
7391 if ((ev->button == 1) && (ev->flags & EVAS_BUTTON_DOUBLE_CLICK))
7392 {
7393 /* if its a directory && open dirs in-place is set then change the dir
7394 * to be the dir + file */
7395 if (ic->sd->config->view.single_click) return;
7396 if (_e_fm2_inplace_open(ic) == 0)
7397 evas_object_smart_callback_call(ic->sd->obj, "selected", NULL);
7398 /* if its in file selector mode then signal that a selection has
7399 * taken place and dont do anything more */
7400
7401 /* do the below per selected file */
7402 /* if its a directory and open dirs in-place is not set, then
7403 * signal owner that a new dir should be opened */
7404 /* if its a normal file - do what the mime type says to do with
7405 * that file type */
7406 }
7407 else if (ev->button < 3)
7408 {
7409 if (ev->button == 1)
7410 {
7411 if ((ic->sd->eobj || ic->sd->win))
7412 {
7413 ic->drag.x = ev->output.x - ic->x - ic->sd->x + ic->sd->pos.x;
7414 ic->drag.y = ev->output.y - ic->y - ic->sd->y + ic->sd->pos.y;
7415 ic->drag.start = EINA_TRUE;
7416 ic->drag.dnd = EINA_FALSE;
7417 ic->drag.src = EINA_TRUE;
7418 }
7419
7420 _e_fm2_mouse_1_handler(ic, 0, ev);
7421 }
7422 else
7423 _e_fm2_mouse_2_handler(ic, ev);
7424 }
7425 else if (ev->button == 3)
7426 {
7427 if (!ic->selected)
7428 {
7429 if (_e_fm2_mouse_1_handler(ic, 0, ev)) return;
7430 }
7431 _e_fm2_icon_menu(ic, ic->sd->obj, ev->timestamp);
7432 }
7433 }
7434
7435 static void
_e_fm2_cb_icon_mouse_up(void * data,Evas * e EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_info)7436 _e_fm2_cb_icon_mouse_up(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info)
7437 {
7438 Evas_Event_Mouse_Up *ev = event_info;
7439 E_Fm2_Icon *ic = data;
7440
7441 if (ic->sd->selecting) return;
7442 edje_object_message_signal_process(ic->obj);
7443 edje_object_message_signal_process(ic->obj);
7444
7445 _e_fm2_typebuf_hide(ic->sd->obj);
7446 if ((ev->button == 1) && (!ic->drag.dnd))
7447 {
7448 if (!(ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD))
7449 {
7450 if (!ic->entry_widget)
7451 {
7452 if (_e_fm2_mouse_1_handler(ic, 1, ev)) return;
7453 }
7454 }
7455 ic->drag.start = EINA_FALSE;
7456 ic->drag.dnd = EINA_FALSE;
7457 ic->drag.src = EINA_FALSE;
7458 ic->down_sel = EINA_FALSE;
7459 }
7460 }
7461
7462 static Eina_Bool
_e_fm2_cb_drag_finished_show(E_Fm2_Icon * ic)7463 _e_fm2_cb_drag_finished_show(E_Fm2_Icon *ic)
7464 {
7465 ic->drag.dnd = ic->drag.src = EINA_FALSE;
7466 if (ic->obj) evas_object_show(ic->obj);
7467 if (ic->obj_icon) evas_object_show(ic->obj_icon);
7468 ic->drag.dnd_end_timer = NULL;
7469 return EINA_FALSE;
7470 }
7471
7472 static void
_e_fm2_cb_drag_finished(E_Drag * drag,int dropped EINA_UNUSED)7473 _e_fm2_cb_drag_finished(E_Drag *drag, int dropped EINA_UNUSED)
7474 {
7475 E_Fm2_Uri *uri;
7476 const char *p;
7477 char buf[PATH_MAX * 3 + 7];
7478 Eina_List *fms;
7479 Evas_Object *fm;
7480 int i;
7481
7482 memset(buf, 0, sizeof(buf));
7483 for (p = drag->data, i = 0; p && *p != '\0'; p++, i++)
7484 {
7485 if (*p == '\r')
7486 {
7487 p++;
7488 i = -1;
7489 uri = _e_fm2_uri_parse(buf);
7490 memset(buf, 0, sizeof(buf));
7491 if (!uri) continue;
7492
7493 fms = _e_fm2_file_fm2_find(uri->path);
7494 if (fms)
7495 {
7496 const char *file;
7497 E_Fm2_Icon *ic;
7498
7499 file = ecore_file_file_get(uri->path);
7500 if (file)
7501 {
7502 EINA_LIST_FREE(fms, fm)
7503 {
7504 ic = _e_fm2_icon_find(fm, file);
7505 if (ic && ic->drag.dnd)
7506 {
7507 ic->drag.dnd = EINA_FALSE;
7508 if (ic->sd->dnd_scroller) ecore_animator_del(ic->sd->dnd_scroller);
7509 ic->sd->dnd_scroller = NULL;
7510 if (ic->drag.dnd_end_timer) ecore_timer_loop_reset(ic->drag.dnd_end_timer);
7511 else ic->drag.dnd_end_timer = ecore_timer_loop_add(0.2, (Ecore_Task_Cb)_e_fm2_cb_drag_finished_show, ic);
7512 /* NOTE:
7513 * do not touch ic after this callback; it's possible that it may have been deleted
7514 */
7515 evas_object_smart_callback_call(ic->sd->obj, "dnd_end", &ic->info);
7516 break;
7517 }
7518 }
7519 eina_list_free(fms);
7520 }
7521 }
7522
7523 if (uri->hostname) eina_stringshare_del(uri->hostname);
7524 eina_stringshare_del(uri->path);
7525 E_FREE(uri);
7526 }
7527 else
7528 buf[i] = *p;
7529 }
7530 free(drag->data);
7531 }
7532
7533 static void
_e_fm_drag_key_down_cb(E_Drag * drag,Ecore_Event_Key * e)7534 _e_fm_drag_key_down_cb(E_Drag *drag, Ecore_Event_Key *e)
7535 {
7536 #ifndef HAVE_WAYLAND_ONLY
7537 if (!strncmp(e->keyname, "Alt", 3))
7538 {
7539 ecore_x_dnd_source_action_set(ECORE_X_ATOM_XDND_ACTION_ASK);
7540 e_drop_handler_action_set(ECORE_X_ATOM_XDND_ACTION_ASK);
7541 edje_object_signal_emit(drag->object, "e,state,ask", "e");
7542 }
7543 else if (!strncmp(e->key, "Shift", 5))
7544 {
7545 if (e->modifiers == ECORE_EVENT_MODIFIER_CTRL)
7546 {
7547 ecore_x_dnd_source_action_set(ECORE_X_ATOM_XDND_ACTION_ASK);
7548 e_drop_handler_action_set(ECORE_X_ATOM_XDND_ACTION_ASK);
7549 edje_object_signal_emit(drag->object, "e,state,ask", "e");
7550 }
7551 else
7552 {
7553 ecore_x_dnd_source_action_set(ECORE_X_ATOM_XDND_ACTION_MOVE);
7554 e_drop_handler_action_set(ECORE_X_ATOM_XDND_ACTION_MOVE);
7555 edje_object_signal_emit(drag->object, "e,state,move", "e");
7556 }
7557 }
7558 else if (!strncmp(e->key, "Control", 7))
7559 {
7560 if (e->modifiers == ECORE_EVENT_MODIFIER_SHIFT)
7561 {
7562 ecore_x_dnd_source_action_set(ECORE_X_ATOM_XDND_ACTION_ASK);
7563 e_drop_handler_action_set(ECORE_X_ATOM_XDND_ACTION_ASK);
7564 edje_object_signal_emit(drag->object, "e,state,ask", "e");
7565 }
7566 else
7567 {
7568 ecore_x_dnd_source_action_set(ECORE_X_ATOM_XDND_ACTION_COPY);
7569 e_drop_handler_action_set(ECORE_X_ATOM_XDND_ACTION_COPY);
7570 edje_object_signal_emit(drag->object, "e,state,copy", "e");
7571 }
7572 }
7573 #endif
7574 }
7575
7576 static void
_e_fm_drag_key_up_cb(E_Drag * drag,Ecore_Event_Key * e)7577 _e_fm_drag_key_up_cb(E_Drag *drag, Ecore_Event_Key *e)
7578 {
7579 #ifndef HAVE_WAYLAND_ONLY
7580 Ecore_X_Atom act = ECORE_X_ATOM_XDND_ACTION_MOVE;
7581 /* Default action would be move. ;) */
7582
7583 if (!strncmp(e->key, "Alt", 3))
7584 act = ECORE_X_ATOM_XDND_ACTION_MOVE;
7585 else if (!strncmp(e->key, "Shift", 5))
7586 act = ECORE_X_ATOM_XDND_ACTION_MOVE;
7587 else if (!strncmp(e->key, "Control", 7))
7588 act = ECORE_X_ATOM_XDND_ACTION_MOVE;
7589
7590 ecore_x_dnd_source_action_set(act);
7591 e_drop_handler_action_set(act);
7592 #endif
7593
7594 edje_object_signal_emit(drag->object, "e,state,move", "e");
7595 }
7596
7597 static void
_e_fm2_cb_icon_mouse_in(void * data,Evas * e EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_info)7598 _e_fm2_cb_icon_mouse_in(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info)
7599 {
7600 Evas_Event_Mouse_In *ev;
7601 E_Fm2_Icon *ic;
7602
7603 ic = data;
7604 ev = event_info;
7605
7606 if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return;
7607 if (e_comp_util_mouse_grabbed()) return;
7608 evas_object_smart_callback_call(ic->sd->obj, "icon_mouse_in", &ic->info);
7609 }
7610
7611 static void
_e_fm2_cb_icon_mouse_out(void * data,Evas * e EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_info)7612 _e_fm2_cb_icon_mouse_out(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info)
7613 {
7614 Evas_Event_Mouse_Out *ev;
7615 E_Fm2_Icon *ic;
7616
7617 ic = data;
7618 ev = event_info;
7619
7620 if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return;
7621 evas_object_smart_callback_call(ic->sd->obj, "icon_mouse_out", &ic->info);
7622 }
7623
7624 static void
_e_fm2_cb_icon_mouse_move(void * data,Evas * e,Evas_Object * obj EINA_UNUSED,void * event_info)7625 _e_fm2_cb_icon_mouse_move(void *data, Evas *e, Evas_Object *obj EINA_UNUSED, void *event_info)
7626 {
7627 Evas_Event_Mouse_Move *ev;
7628 E_Fm2_Icon *ic;
7629 E_Fm2_Icon_Info *ici;
7630
7631 ic = data;
7632 ev = event_info;
7633
7634 if (ic->entry_widget) return;
7635
7636 if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return;
7637 if (ic->sd->selecting)
7638 {
7639 /* happens when clicking precisely between icons */
7640 ic->drag.x = ic->drag.y = 0;
7641 ic->drag.start = ic->drag.dnd = ic->drag.src = EINA_FALSE;
7642 return;
7643 }
7644 if ((ic->drag.start) && (ic->sd->eobj || ic->sd->win))
7645 {
7646 int dx, dy;
7647
7648 dx = ev->cur.output.x - (ic->drag.x + ic->x + ic->sd->x - ic->sd->pos.x);
7649 dy = ev->cur.output.y - (ic->drag.y + ic->y + ic->sd->y - ic->sd->pos.y);
7650 if (((dx * dx) + (dy * dy)) >
7651 (e_config->drag_resist * e_config->drag_resist))
7652 {
7653 E_Drag *d;
7654 Evas_Object *o = NULL, *o2 = NULL, *layout = NULL;
7655 const char *drag_types[] = { "text/uri-list" }, *real_path;
7656 char buf[PATH_MAX + 8], *p, *sel = NULL;
7657 Eina_Binbuf *sbuf;
7658 Eina_List *sl, *icons = NULL;
7659 size_t sel_length = 0, p_offset, p_length;
7660 int wx = 0, wy = 0;
7661
7662 ic->sd->drag = EINA_TRUE;
7663 ic->drag.start = EINA_FALSE;
7664 real_path = e_fm2_real_path_get(ic->sd->obj);
7665 p_offset = eina_strlcpy(buf, real_path, sizeof(buf));
7666 if ((p_offset < 1) || (p_offset >= (int)sizeof(buf) - 2)) return;
7667 if (buf[p_offset - 1] != '/')
7668 {
7669 buf[p_offset] = '/';
7670 p_offset++;
7671 }
7672 p = buf + p_offset;
7673 p_length = sizeof(buf) - p_offset - 1;
7674
7675 sl = e_fm2_selected_list_get(ic->sd->obj);
7676 if (eina_list_count(sl) > 1)
7677 {
7678 layout = e_layout_add(e_comp->evas);
7679 e_layout_freeze(layout);
7680 e_layout_virtual_size_set(layout, ic->sd->w, ic->sd->h);
7681 }
7682 sbuf = eina_binbuf_new();
7683 EINA_LIST_FREE(sl, ici)
7684 {
7685 const char *s;
7686 size_t s_len;
7687
7688 if (eina_strlcpy(p, ici->file, p_length) >= p_length)
7689 continue;
7690 s = _e_fm2_uri_escape(buf);
7691 if (!s) continue;
7692 s_len = strlen(s);
7693 eina_binbuf_append_length(sbuf, (void*)s, s_len);
7694 eina_binbuf_append_length(sbuf, (void*)"\r\n", 2);
7695 eina_stringshare_del(s);
7696
7697 ici->ic->drag.dnd = EINA_TRUE;
7698 if (ici->ic->obj) evas_object_hide(ici->ic->obj);
7699 if (ici->ic->obj_icon) evas_object_hide(ici->ic->obj_icon);
7700
7701 o = edje_object_add(e_comp->evas);
7702 if (_e_fm2_view_mode_get(ici->ic->sd) == E_FM2_VIEW_MODE_LIST)
7703 {
7704 if (ici->ic->sd->config->icon.fixed.w)
7705 {
7706 if (ici->ic->odd)
7707 _e_fm2_theme_edje_object_set(ici->ic->sd, o,
7708 "base/theme/widgets",
7709 "list_odd/fixed");
7710 else
7711 _e_fm2_theme_edje_object_set(ici->ic->sd, o,
7712 "base/theme/widgets",
7713 "list/fixed");
7714 }
7715 else
7716 {
7717 if (ici->ic->odd)
7718 _e_fm2_theme_edje_object_set(ici->ic->sd, o,
7719 "base/theme/widgets",
7720 "list_odd/variable");
7721 else
7722 _e_fm2_theme_edje_object_set(ici->ic->sd, o,
7723 "base/theme/widgets",
7724 "list/variable");
7725 }
7726 }
7727 else
7728 {
7729 if (ici->ic->sd->config->icon.fixed.w)
7730 _e_fm2_theme_edje_object_set(ici->ic->sd, o,
7731 "base/theme/fileman",
7732 "icon/fixed");
7733 else
7734 _e_fm2_theme_edje_object_set(ici->ic->sd, o,
7735 "base/theme/fileman",
7736 "icon/variable");
7737 }
7738 _e_fm2_icon_label_set(ici->ic, o);
7739 o2 = _e_fm2_icon_icon_direct_set(ici->ic, o,
7740 _e_fm2_cb_icon_thumb_dnd_gen, o,
7741 1);
7742 edje_object_signal_emit(o, "e,state,selected", "e");
7743 if (isedje(o2))
7744 edje_object_signal_emit(o2, "e,state,selected", "e");
7745 edje_object_signal_emit(o, "e,state,move", "e");
7746 if (layout)
7747 {
7748 e_layout_pack(layout, o);
7749 e_layout_child_move(o, ici->ic->x, ici->ic->y);
7750 e_layout_child_resize(o, ici->ic->w, ici->ic->h);
7751 evas_object_show(o);
7752 icons = eina_list_append(icons, o);
7753 }
7754 icons = eina_list_append(icons, o2);
7755 }
7756 eina_binbuf_append_char(sbuf, 0);
7757 sel_length = eina_binbuf_length_get(sbuf) - 1;
7758 sel = (char*)eina_binbuf_string_steal(sbuf);
7759 eina_binbuf_free(sbuf);
7760
7761 d = e_drag_new(0, 0, drag_types, 1,
7762 sel, sel_length, NULL, _e_fm2_cb_drag_finished);
7763 d->button_mask = evas_pointer_button_down_mask_get(e);
7764 if (ic->sd->win)
7765 evas_object_geometry_get(ic->sd->win, &wx, &wy, NULL, NULL);
7766 if (layout)
7767 d->x = ic->sd->x - ic->sd->pos.x, d->y = ic->sd->y - ic->sd->pos.y;
7768 else
7769 d->x = ic->x + ic->sd->x - ic->sd->pos.x, d->y = ic->y + ic->sd->y - ic->sd->pos.y;
7770 d->x += wx, d->y += wy;
7771 #ifndef HAVE_WAYLAND_ONLY
7772 e_drop_handler_action_set(ECORE_X_ATOM_XDND_ACTION_MOVE);
7773 #endif
7774 e_drag_object_set(d, layout ?: o);
7775 if (layout)
7776 {
7777 e_layout_thaw(layout);
7778 e_drag_resize(d, ic->sd->w, ic->sd->h);
7779 EINA_LIST_FREE(icons, o)
7780 e_comp_object_util_del_list_append(d->comp_object, o);
7781 }
7782 else
7783 {
7784 e_drag_resize(d, ic->w, ic->h);
7785 e_comp_object_util_del_list_append(d->comp_object, o2);
7786 }
7787 evas_object_smart_callback_call(ic->sd->obj, "dnd_begin", &ic->info);
7788
7789 e_drag_key_down_cb_set(d, _e_fm_drag_key_down_cb);
7790 e_drag_key_up_cb_set(d, _e_fm_drag_key_up_cb);
7791
7792 e_drag_xdnd_start(d,
7793 ic->drag.x + wx + ic->x + ic->sd->x - ic->sd->pos.x,
7794 ic->drag.y + wy + ic->y + ic->sd->y - ic->sd->pos.y);
7795 }
7796 }
7797 }
7798
7799 static void
_e_fm2_cb_icon_thumb_dnd_gen(void * data,Evas_Object * obj,void * event_info EINA_UNUSED)7800 _e_fm2_cb_icon_thumb_dnd_gen(void *data, Evas_Object *obj, void *event_info EINA_UNUSED)
7801 {
7802 Evas_Object *o;
7803 Evas_Coord w = 0, h = 0;
7804 int have_alpha;
7805
7806 o = data;
7807 e_icon_size_get(obj, &w, &h);
7808 if (w + h == 0) return;
7809 have_alpha = e_icon_alpha_get(obj);
7810 // if (_e_fm2_view_mode_get(ic->sd) == E_FM2_VIEW_MODE_LIST)
7811 {
7812 evas_object_size_hint_aspect_set(obj, EVAS_ASPECT_CONTROL_BOTH, w, h);
7813 }
7814 edje_object_part_swallow(o, "e.swallow.icon", obj);
7815 if (have_alpha)
7816 edje_object_signal_emit(o, "e,action,thumb,gen,alpha", "e");
7817 else
7818 edje_object_signal_emit(o, "e,action,thumb,gen", "e");
7819 }
7820
7821 static void
_e_fm2_cb_icon_thumb_gen(void * data,Evas_Object * obj,void * event_info EINA_UNUSED)7822 _e_fm2_cb_icon_thumb_gen(void *data, Evas_Object *obj, void *event_info EINA_UNUSED)
7823 {
7824 E_Fm2_Icon *ic;
7825 const char *file;
7826
7827 ic = data;
7828
7829 if (e_icon_file_get(obj, &file, NULL))
7830 {
7831 int w = 0, h = 0;
7832
7833 if (!ic->realized)
7834 return;
7835
7836 e_icon_size_get(obj, &w, &h);
7837 if (w && h)
7838 {
7839 Eina_Bool have_alpha;
7840 have_alpha = e_icon_alpha_get(obj);
7841 // if (_e_fm2_view_mode_get(ic->sd) == E_FM2_VIEW_MODE_LIST)
7842 {
7843 evas_object_size_hint_aspect_set(obj, EVAS_ASPECT_CONTROL_BOTH, w, h);
7844 }
7845 edje_object_part_swallow(ic->obj, "e.swallow.icon", obj);
7846 if (have_alpha)
7847 edje_object_signal_emit(ic->obj, "e,action,thumb,gen,alpha", "e");
7848 else
7849 edje_object_signal_emit(ic->obj, "e,action,thumb,gen", "e");
7850 return;
7851 }
7852 }
7853 ic->thumb_failed = EINA_TRUE;
7854 evas_object_del(obj);
7855
7856 if (ic->realized)
7857 _e_fm2_icon_icon_set(ic);
7858 }
7859
7860 #if 0
7861 static void
7862 _e_fm2_cb_focus_in(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
7863 {
7864 E_Fm2_Smart_Data *sd = data;
7865
7866 if (sd->iop_icon && sd->iop_icon->entry_widget)
7867 e_widget_focus_set(sd->iop_icon->entry_widget, 1);
7868 }
7869 #endif
7870
7871 static void
_e_fm2_cb_key_down(void * data,Evas * e EINA_UNUSED,Evas_Object * obj,void * event_info)7872 _e_fm2_cb_key_down(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info)
7873 {
7874 Evas_Event_Key_Down *ev = event_info;
7875 E_Fm2_Smart_Data *sd = data;
7876 E_Fm2_Icon *ic;
7877
7878 if (e_comp_util_kbd_grabbed()) return;
7879 if (sd->iop_icon) return;
7880
7881 if (evas_key_modifier_is_set(ev->modifiers, "Control"))
7882 {
7883 if (!strcmp(ev->key, "x"))
7884 {
7885 _e_fm2_file_cut(obj);
7886 return;
7887 }
7888 else if (!strcmp(ev->key, "c"))
7889 {
7890 _e_fm2_file_copy(obj);
7891 return;
7892 }
7893 else if (!strcmp(ev->key, "v"))
7894 {
7895 _e_fm2_file_paste(obj);
7896 return;
7897 }
7898 else if (!strcmp(ev->key, "h"))
7899 {
7900 if (sd->show_hidden_files)
7901 sd->show_hidden_files = EINA_FALSE;
7902 else
7903 sd->show_hidden_files = EINA_TRUE;
7904 sd->inherited_dir_props = EINA_FALSE;
7905 _e_fm2_refresh(data, NULL, NULL);
7906 return;
7907 }
7908 else if (!strcmp(ev->key, "1"))
7909 {
7910 if (_e_fm2_view_mode_get(sd) == E_FM2_VIEW_MODE_GRID_ICONS)
7911 return;
7912 sd->view_mode = E_FM2_VIEW_MODE_GRID_ICONS;
7913 sd->inherited_dir_props = EINA_FALSE;
7914 _e_fm2_refresh(sd, NULL, NULL);
7915 return;
7916 }
7917 else if (!strcmp(ev->key, "2"))
7918 {
7919 if (_e_fm2_view_mode_get(sd) == E_FM2_VIEW_MODE_LIST)
7920 return;
7921 sd->view_mode = E_FM2_VIEW_MODE_LIST;
7922 sd->inherited_dir_props = EINA_FALSE;
7923 _e_fm2_refresh(sd, NULL, NULL);
7924 return;
7925 }
7926 else if (!strcmp(ev->key, "3"))
7927 {
7928 if (_e_fm2_view_mode_get(sd) == E_FM2_VIEW_MODE_CUSTOM_ICONS)
7929 return;
7930 sd->view_mode = E_FM2_VIEW_MODE_CUSTOM_ICONS;
7931 sd->inherited_dir_props = EINA_FALSE;
7932 _e_fm2_refresh(sd, NULL, NULL);
7933 return;
7934 }
7935 }
7936
7937 if (!strcmp(ev->key, "Left"))
7938 {
7939 /* FIXME: icon mode, typebuf extras */
7940 /* list mode: scroll left n pix
7941 * icon mode: prev icon
7942 * typebuf mode: cursor left
7943 */
7944 _e_fm2_icon_sel_prev(obj, evas_key_modifier_is_set(ev->modifiers, "Shift"));
7945 }
7946 else if (!strcmp(ev->key, "Right"))
7947 {
7948 /* FIXME: icon mode, typebuf extras */
7949 /* list mode: scroll right n pix
7950 * icon mode: next icon
7951 * typebuf mode: cursor right
7952 */
7953 _e_fm2_icon_sel_next(obj, evas_key_modifier_is_set(ev->modifiers, "Shift"));
7954 }
7955 else if (!strcmp(ev->key, "Up"))
7956 {
7957 if (_e_fm2_view_mode_get(sd) == E_FM2_VIEW_MODE_LIST)
7958 _e_fm2_icon_sel_prev(obj, evas_key_modifier_is_set(ev->modifiers, "Shift"));
7959 else
7960 _e_fm2_icon_sel_up(obj, evas_key_modifier_is_set(ev->modifiers, "Shift"));
7961 }
7962 else if (!strcmp(ev->key, "Down"))
7963 {
7964 if (_e_fm2_view_mode_get(sd) == E_FM2_VIEW_MODE_LIST)
7965 _e_fm2_icon_sel_next(obj, evas_key_modifier_is_set(ev->modifiers, "Shift"));
7966 else
7967 _e_fm2_icon_sel_down(obj, evas_key_modifier_is_set(ev->modifiers, "Shift"));
7968 }
7969 else if (!strcmp(ev->key, "Home"))
7970 {
7971 /* FIXME: typebuf extras */
7972 /* go to first icon
7973 * typebuf mode: cursor to start
7974 */
7975 _e_fm2_icon_sel_first(obj, EINA_FALSE);
7976 }
7977 else if (!strcmp(ev->key, "End"))
7978 {
7979 /* FIXME: typebuf extras */
7980 /* go to last icon
7981 * typebuf mode: cursor to end
7982 */
7983 _e_fm2_icon_sel_last(obj, EINA_FALSE);
7984 }
7985 else if (!strcmp(ev->key, "Prior"))
7986 {
7987 /* up h * n pixels */
7988 e_fm2_pan_set(obj, sd->pos.x, sd->pos.y - sd->h);
7989 evas_object_smart_callback_call(sd->obj, "pan_changed", NULL);
7990 }
7991 else if (!strcmp(ev->key, "Next"))
7992 {
7993 /* down h * n pixels */
7994 e_fm2_pan_set(obj, sd->pos.x, sd->pos.y + sd->h);
7995 evas_object_smart_callback_call(sd->obj, "pan_changed", NULL);
7996 }
7997 else if (!strcmp(ev->key, "Escape"))
7998 {
7999 /* typebuf mode: end typebuf mode */
8000 if (sd->typebuf_visible)
8001 _e_fm2_typebuf_hide(obj);
8002 else if (sd->dev && (!strcmp(sd->dev, "desktop")))
8003 return;
8004 else
8005 {
8006 ic = _e_fm2_icon_first_selected_find(obj);
8007 if (ic)
8008 _e_fm2_icon_desel_any(obj);
8009 else
8010 {
8011 if (e_fm2_has_parent_get(obj))
8012 e_fm2_parent_go(obj);
8013 }
8014 }
8015 }
8016 else if ((!strcmp(ev->key, "Return")) || (!strcmp(ev->key, "KP_Enter")))
8017 {
8018 /* if selected - select callback.
8019 * typebuf mode: if nothing selected - run cmd
8020 */
8021 if (sd->typebuf_visible)
8022 _e_fm2_typebuf_run(obj);
8023 else
8024 {
8025 ic = _e_fm2_icon_first_selected_find(obj);
8026 if (ic)
8027 {
8028 if (_e_fm2_inplace_open(ic) == 0)
8029 evas_object_smart_callback_call(ic->sd->obj, "selected", NULL);
8030 }
8031 }
8032 }
8033 else if (!strcmp(ev->key, "F5"))
8034 e_fm2_refresh(obj);
8035 else if (!strcmp(ev->key, "F2"))
8036 {
8037 if (eina_list_count(sd->selected_icons) == 1)
8038 _e_fm2_file_rename(eina_list_data_get(sd->selected_icons), NULL, NULL);
8039 }
8040 else if (!strcmp(ev->key, "Insert"))
8041 {
8042 /* dunno what to do with this yet */
8043 }
8044 else if (!strcmp(ev->key, "Tab"))
8045 {
8046 /* typebuf mode: tab complete */
8047 if (sd->typebuf_visible)
8048 _e_fm2_typebuf_complete(obj);
8049 }
8050 else if (!strcmp(ev->key, "BackSpace"))
8051 {
8052 /* typebuf mode: backspace */
8053 if (sd->typebuf_visible)
8054 _e_fm2_typebuf_char_backspace(obj);
8055 else if (!sd->config->view.no_typebuf_set)
8056 {
8057 /* only allow this action when typebuf navigation is allowed in config */
8058 if (e_fm2_has_parent_get(obj))
8059 e_fm2_parent_go(obj);
8060 }
8061 }
8062 else if (!strcmp(ev->key, "Delete"))
8063 _e_fm2_file_delete(obj);
8064 else if (!evas_key_modifier_is_set(ev->modifiers, "Control") &&
8065 !evas_key_modifier_is_set(ev->modifiers, "Alt"))
8066 {
8067 if (ev->string)
8068 {
8069 if (!sd->typebuf_visible) _e_fm2_typebuf_show(obj);
8070 _e_fm2_typebuf_char_append(obj, ev->string);
8071 }
8072 }
8073 }
8074
8075 static void
_e_fm2_cb_mouse_down(void * data,Evas * e EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_info)8076 _e_fm2_cb_mouse_down(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info)
8077 {
8078 Evas_Event_Mouse_Down *ev;
8079 E_Fm2_Smart_Data *sd;
8080
8081 sd = data;
8082 ev = event_info;
8083 _e_fm2_typebuf_hide(sd->obj);
8084 if (sd->iop_icon)
8085 _e_fm2_icon_entry_widget_del(sd->iop_icon);
8086 if (ev->button == 1)
8087 {
8088 Eina_List *l;
8089 int multi_sel = 0, range_sel = 0, sel_change = 0;
8090
8091 if (!sd->config->selection.windows_modifiers)
8092 {
8093 if (evas_key_modifier_is_set(ev->modifiers, "Shift"))
8094 range_sel = 1;
8095 else if (evas_key_modifier_is_set(ev->modifiers, "Control"))
8096 multi_sel = 1;
8097 }
8098 else
8099 {
8100 if (evas_key_modifier_is_set(ev->modifiers, "Control"))
8101 range_sel = 1;
8102 else if (evas_key_modifier_is_set(ev->modifiers, "Shift"))
8103 multi_sel = 1;
8104 }
8105 if (sd->config->selection.single)
8106 {
8107 multi_sel = 0;
8108 range_sel = 0;
8109 }
8110 if ((!multi_sel) && (!range_sel))
8111 {
8112 E_Fm2_Icon *ic;
8113 EINA_LIST_FOREACH(sd->icons, l, ic)
8114 {
8115 if (ic->selected)
8116 {
8117 _e_fm2_icon_deselect(ic);
8118 sel_change = 1;
8119 }
8120 }
8121 }
8122 if (sel_change)
8123 evas_object_smart_callback_call(sd->obj, "selection_change", NULL);
8124
8125 if (!(ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD))
8126 {
8127 if (!sd->config->selection.single)
8128 {
8129 sd->selrect.ox = ev->canvas.x;
8130 sd->selrect.oy = ev->canvas.y;
8131 sd->selecting = EINA_TRUE;
8132 }
8133 }
8134 if (ev->flags & EVAS_BUTTON_DOUBLE_CLICK)
8135 evas_object_smart_callback_call(sd->obj, "double_clicked", NULL);
8136 }
8137 else if (ev->button == 3)
8138 {
8139 _e_fm2_menu(sd->obj, ev->timestamp);
8140 }
8141 }
8142
8143 static void
_e_fm2_cb_mouse_up(void * data,Evas * e EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_info EINA_UNUSED)8144 _e_fm2_cb_mouse_up(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
8145 {
8146 E_Fm2_Smart_Data *sd;
8147
8148 sd = data;
8149 _e_fm2_typebuf_hide(sd->obj);
8150 sd->selecting = EINA_FALSE;
8151 sd->selrect.ox = 0;
8152 sd->selrect.oy = 0;
8153 evas_object_hide(sd->sel_rect);
8154 }
8155
8156 static void
_e_fm2_cb_mouse_move(void * data,Evas * e EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_info)8157 _e_fm2_cb_mouse_move(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info)
8158 {
8159 Evas_Event_Mouse_Move *ev;
8160 E_Fm2_Smart_Data *sd;
8161 E_Fm2_Icon *ic;
8162 Eina_List *l = NULL;
8163 int x, y, w, h;
8164 int sel_change = 0;
8165
8166 sd = data;
8167 ev = event_info;
8168 if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD)
8169 {
8170 if (sd->selecting)
8171 {
8172 sd->selecting = EINA_FALSE;
8173 sd->selrect.ox = 0;
8174 sd->selrect.oy = 0;
8175 evas_object_hide(sd->sel_rect);
8176 }
8177 return;
8178 }
8179 if (!sd->selecting) return;
8180
8181 if (ev->cur.canvas.x < sd->selrect.ox)
8182 {
8183 sd->selrect.x = ev->cur.canvas.x;
8184 sd->selrect.w = (sd->selrect.ox - sd->selrect.x);
8185 }
8186 else
8187 {
8188 sd->selrect.x = MIN(sd->selrect.ox, ev->cur.canvas.x);
8189 sd->selrect.w = abs(sd->selrect.x - ev->cur.canvas.x);
8190 }
8191 if (ev->cur.canvas.y < sd->selrect.oy)
8192 {
8193 sd->selrect.y = ev->cur.canvas.y;
8194 sd->selrect.h = (sd->selrect.oy - sd->selrect.y);
8195 }
8196 else
8197 {
8198 sd->selrect.y = MIN(sd->selrect.oy, ev->cur.canvas.y);
8199 sd->selrect.h = abs(sd->selrect.y - ev->cur.canvas.y);
8200 }
8201 _e_fm2_sel_rect_update(sd);
8202
8203 evas_object_geometry_get(sd->sel_rect, &x, &y, &w, &h);
8204
8205 /*
8206 * Leave commented for now. Start of scrolling the sel_rect
8207 *
8208 int nx, ny, nw, nh;
8209
8210 nx = sd->pos.x;
8211 if ((x - sd->pos.x) < 0)
8212 nx = x;
8213 else if ((x + w - sd->pos.x) > (sd->w))
8214 nx = x + w - sd->w;
8215 ny = sd->pos.y;
8216 if ((y - sd->pos.y) < 0)
8217 ny = y;
8218 else if ((y + h - sd->pos.y) > (sd->h))
8219 ny = y + h - sd->h;
8220 e_fm2_pan_set(sd->obj, nx, ny);
8221 evas_object_smart_callback_call(sd->obj, "pan_changed", NULL);
8222 */
8223
8224 EINA_LIST_FOREACH(sd->icons, l, ic)
8225 {
8226 int ix, iy, iw, ih;
8227 int ix_t, iy_t, iw_t, ih_t;
8228
8229 if (!ic) continue;
8230 evas_object_geometry_get(ic->obj_icon, &ix, &iy, &iw, &ih);
8231 evas_object_geometry_get(edje_object_part_object_get(ic->obj,
8232 "e.text.label"),
8233 &ix_t, &iy_t, &iw_t, &ih_t);
8234 if (E_INTERSECTS(x, y, w, h, ix, iy, iw, ih) ||
8235 E_INTERSECTS(x, y, w, h, ix_t, iy_t, iw_t, ih_t))
8236 {
8237 if (!ic->selected)
8238 {
8239 _e_fm2_icon_select(ic);
8240 sel_change = 1;
8241 }
8242 }
8243 else
8244 {
8245 if (ic->selected)
8246 {
8247 _e_fm2_icon_deselect(ic);
8248 sel_change = 1;
8249 }
8250 }
8251 }
8252 if (sel_change)
8253 evas_object_smart_callback_call(sd->obj, "selection_change", NULL);
8254 }
8255
8256 static void
_e_fm2_sel_rect_update(void * data)8257 _e_fm2_sel_rect_update(void *data)
8258 {
8259 E_Fm2_Smart_Data *sd;
8260
8261 sd = data;
8262 evas_object_move(sd->sel_rect, sd->selrect.x, sd->selrect.y);
8263 evas_object_resize(sd->sel_rect, sd->selrect.w, sd->selrect.h);
8264 evas_object_show(sd->sel_rect);
8265 }
8266
8267 static void
_e_fm2_cb_scroll_job(void * data)8268 _e_fm2_cb_scroll_job(void *data)
8269 {
8270 E_Fm2_Smart_Data *sd;
8271
8272 sd = evas_object_smart_data_get(data);
8273 if (!sd) return;
8274 sd->scroll_job = NULL;
8275 evas_event_freeze(evas_object_evas_get(sd->obj));
8276 edje_freeze();
8277 _e_fm2_regions_eval(sd->obj);
8278 _e_fm2_obj_icons_place(sd);
8279 edje_thaw();
8280 evas_event_thaw(evas_object_evas_get(sd->obj));
8281 _e_fm2_dir_save_props(sd);
8282 }
8283
8284 static void
_e_fm2_cb_resize_job(void * data)8285 _e_fm2_cb_resize_job(void *data)
8286 {
8287 E_Fm2_Smart_Data *sd;
8288 Eina_List *l;
8289
8290 sd = evas_object_smart_data_get(data);
8291 if (!sd) return;
8292 sd->resize_job = NULL;
8293 evas_event_freeze(evas_object_evas_get(sd->obj));
8294 edje_freeze();
8295 switch (_e_fm2_view_mode_get(sd))
8296 {
8297 case E_FM2_VIEW_MODE_ICONS:
8298 _e_fm2_regions_free(sd->obj);
8299 _e_fm2_icons_place(sd->obj);
8300 _e_fm2_regions_populate(sd->obj);
8301 break;
8302
8303 case E_FM2_VIEW_MODE_GRID_ICONS:
8304 _e_fm2_regions_free(sd->obj);
8305 _e_fm2_icons_place(sd->obj);
8306 _e_fm2_regions_populate(sd->obj);
8307 break;
8308
8309 case E_FM2_VIEW_MODE_CUSTOM_ICONS:
8310 if (sd->config->view.fit_custom_pos)
8311 {
8312 E_Fm2_Icon *ic;
8313 EINA_LIST_FOREACH(sd->icons, l, ic)
8314 {
8315 ic->region = NULL;
8316 _e_fm2_icon_geom_adjust(ic, ic->x, ic->y, ic->w, ic->h, sd->pw, sd->ph);
8317 }
8318 }
8319 _e_fm2_regions_free(sd->obj);
8320 // _e_fm2_regions_eval(sd->obj);
8321 _e_fm2_icons_place(sd->obj);
8322 _e_fm2_regions_populate(sd->obj);
8323 break;
8324
8325 case E_FM2_VIEW_MODE_CUSTOM_GRID_ICONS:
8326 /* FIXME: not going to implement this at this stage */
8327 _e_fm2_regions_free(sd->obj);
8328 // _e_fm2_regions_eval(sd->obj);
8329 _e_fm2_icons_place(sd->obj);
8330 _e_fm2_regions_populate(sd->obj);
8331 break;
8332
8333 case E_FM2_VIEW_MODE_CUSTOM_SMART_GRID_ICONS:
8334 /* FIXME: not going to implement this at this stage */
8335 _e_fm2_regions_free(sd->obj);
8336 // _e_fm2_regions_eval(sd->obj);
8337 _e_fm2_icons_place(sd->obj);
8338 _e_fm2_regions_populate(sd->obj);
8339 break;
8340
8341 case E_FM2_VIEW_MODE_LIST:
8342 if (sd->iconlist_changed)
8343 {
8344 E_Fm2_Icon *ic;
8345 EINA_LIST_FOREACH(sd->icons, l, ic)
8346 {
8347 ic->region = NULL;
8348 // _e_fm2_icon_unrealize(ic);
8349 }
8350 }
8351 _e_fm2_regions_free(sd->obj);
8352 _e_fm2_icons_place(sd->obj);
8353 _e_fm2_regions_populate(sd->obj);
8354 break;
8355
8356 default:
8357 break;
8358 }
8359 edje_thaw();
8360 evas_event_thaw(evas_object_evas_get(sd->obj));
8361 sd->iconlist_changed = EINA_FALSE;
8362 sd->pw = sd->w;
8363 sd->ph = sd->h;
8364
8365 if ((sd->max.w > 0) && (sd->max.h > 0) && (sd->w > 0) && (sd->h > 0) && (sd->view_flags & E_FM2_VIEW_SAVE_DIR_CUSTOM))
8366 {
8367 E_Fm2_Custom_File *cf = e_fm2_custom_file_get(sd->realpath);
8368 if ((cf) && (cf->dir))
8369 {
8370 sd->pos.x = cf->dir->pos.x * (sd->max.w - sd->w);
8371 sd->pos.y = cf->dir->pos.y * (sd->max.h - sd->h);
8372 evas_object_smart_callback_call(sd->obj, "pan_changed", NULL);
8373 }
8374 }
8375 }
8376
8377 static int
_e_fm2_cb_icon_sort(const void * data1,const void * data2)8378 _e_fm2_cb_icon_sort(const void *data1, const void *data2)
8379 {
8380 const E_Fm2_Icon *ic1, *ic2;
8381 char *l1, *l2;
8382
8383 ic1 = data1;
8384 ic2 = data2;
8385 l1 = (char *)ic1->info.file;
8386 if (ic1->info.label) l1 = (char *)ic1->info.label;
8387 l2 = (char *)ic2->info.file;
8388 if (ic2->info.label) l2 = (char *)ic2->info.label;
8389 if (ic1->sd->config->list.sort.dirs.first)
8390 {
8391 if ((S_ISDIR(ic1->info.statinfo.st_mode)) !=
8392 (S_ISDIR(ic2->info.statinfo.st_mode)))
8393 {
8394 if (S_ISDIR(ic1->info.statinfo.st_mode)) return -1;
8395 return 1;
8396 }
8397 }
8398 else if (ic1->sd->config->list.sort.dirs.last)
8399 {
8400 if ((S_ISDIR(ic1->info.statinfo.st_mode)) !=
8401 (S_ISDIR(ic2->info.statinfo.st_mode)))
8402 {
8403 if (S_ISDIR(ic1->info.statinfo.st_mode)) return 1;
8404 return -1;
8405 }
8406 }
8407 if (ic1->sd->config->list.sort.mtime)
8408 {
8409 if (ic1->info.statinfo.st_mtime > ic2->info.statinfo.st_mtime)
8410 return -1;
8411 if (ic1->info.statinfo.st_mtime < ic2->info.statinfo.st_mtime)
8412 return 1;
8413 }
8414 if (ic1->sd->config->list.sort.extension)
8415 {
8416 int cmp;
8417 const char *f1, *f2;
8418 f1 = ecore_file_file_get(l1);
8419 f1 = strrchr(f1, '.');
8420 f2 = ecore_file_file_get(l2);
8421 f2 = strrchr(f2, '.');
8422 if (f1 && f2)
8423 {
8424 cmp = strcasecmp(f1, f2);
8425 if (cmp) return cmp;
8426 }
8427 else if (f1)
8428 return 1;
8429 else if (f2)
8430 return -1;
8431 }
8432 if (ic1->sd->config->list.sort.size)
8433 {
8434 if (ic1->info.link)
8435 {
8436 if (!ic2->info.link) return 1;
8437 }
8438 else
8439 {
8440 if (ic2->info.link) return -1;
8441 if (ic1->info.statinfo.st_size > ic2->info.statinfo.st_size)
8442 return -1;
8443 else if (ic1->info.statinfo.st_size < ic2->info.statinfo.st_size)
8444 return 1;
8445 }
8446 }
8447 if (ic1->sd->config->list.sort.no_case)
8448 return strcasecmp(l1, l2);
8449 return strcmp(l1, l2);
8450 }
8451
8452 static Eina_Bool
_e_fm2_cb_scan_timer(void * data)8453 _e_fm2_cb_scan_timer(void *data)
8454 {
8455 E_Fm2_Smart_Data *sd;
8456
8457 sd = evas_object_smart_data_get(data);
8458 if (!sd) return ECORE_CALLBACK_CANCEL;
8459 _e_fm2_queue_process(data);
8460 sd->scan_timer = NULL;
8461 if (!sd->listing)
8462 {
8463 _e_fm2_client_monitor_list_end(data);
8464 return ECORE_CALLBACK_CANCEL;
8465 }
8466 if (sd->busy_count > 0)
8467 sd->scan_timer = ecore_timer_loop_add(0.2, _e_fm2_cb_scan_timer, sd->obj);
8468 else
8469 {
8470 if (!sd->sort_idler)
8471 sd->sort_idler = ecore_idler_add(_e_fm2_cb_sort_idler, data);
8472 }
8473 return ECORE_CALLBACK_CANCEL;
8474 }
8475
8476 static Eina_Bool
_e_fm2_cb_sort_idler(void * data)8477 _e_fm2_cb_sort_idler(void *data)
8478 {
8479 E_Fm2_Smart_Data *sd;
8480
8481 sd = evas_object_smart_data_get(data);
8482 if (!sd) return ECORE_CALLBACK_CANCEL;
8483 _e_fm2_queue_process(data);
8484 if (!sd->listing)
8485 {
8486 sd->sort_idler = NULL;
8487 _e_fm2_client_monitor_list_end(data);
8488 return ECORE_CALLBACK_CANCEL;
8489 }
8490 return ECORE_CALLBACK_RENEW;
8491 }
8492
8493 static Eina_Bool
_e_fm2_cb_theme(void * data,int type EINA_UNUSED,void * event EINA_UNUSED)8494 _e_fm2_cb_theme(void *data, int type EINA_UNUSED, void *event EINA_UNUSED)
8495 {
8496 e_fm2_refresh(data);
8497 return ECORE_CALLBACK_RENEW;
8498 }
8499
8500 /**************************/
8501 static void
_e_fm2_obj_icons_place(E_Fm2_Smart_Data * sd)8502 _e_fm2_obj_icons_place(E_Fm2_Smart_Data *sd)
8503 {
8504 const Eina_List *l;
8505 E_Fm2_Region *rg;
8506
8507 evas_event_freeze(evas_object_evas_get(sd->obj));
8508 edje_freeze();
8509 EINA_LIST_FOREACH(sd->regions.list, l, rg)
8510 {
8511 if (rg->realized)
8512 {
8513 const Eina_List *ll;
8514 E_Fm2_Icon *ic;
8515
8516 EINA_LIST_FOREACH(rg->list, ll, ic)
8517 {
8518 const char *th[] =
8519 {
8520 "list/fixed",
8521 "list_odd/fixed",
8522 };
8523 Evas_Object *prev;
8524
8525 if (!ic->realized) continue;
8526 if (!_e_fm2_icon_visible(ic))
8527 {
8528 e_thumb_icon_end(ic->obj_icon);
8529 }
8530 evas_object_move(ic->obj,
8531 sd->x + ic->x - sd->pos.x,
8532 sd->y + ic->y - sd->pos.y);
8533 evas_object_resize(ic->obj, ic->w, ic->h);
8534 _e_fm2_icon_thumb(ic, ic->obj_icon, 0);
8535 if (_e_fm2_view_mode_get(ic->sd) != E_FM2_VIEW_MODE_LIST) continue;
8536 /* FIXME: this is probably something that should be unnecessary,
8537 * but currently we add icons in semi-randomly and it messes up ordering.
8538 * current process is:
8539 * 1 receive file info from slave
8540 * 2 create icon struct
8541 * 3 either directly add icon or queue it (usually queue)
8542 * 4 process queue on timer, determining even/odd for all icons at this time
8543 * 4.5 icons are realized, theme is set here <-- where bug occurs
8544 * 5 goto 1
8545 * 6 if icon is inserted into current viewport during 4.5, even/odd for surrounding items
8546 * will always be wrong (ticket #1579)
8547 */
8548
8549 prev = edje_object_part_swallow_get(ic->obj, "e.swallow.icon");
8550 _e_fm2_theme_edje_object_set(ic->sd, ic->obj,
8551 "base/theme/widgets",
8552 th[ic->odd]);
8553 edje_object_part_swallow(ic->obj, "e.swallow.icon", prev);
8554 _e_fm2_icon_label_set(ic, ic->obj);
8555 if (ic->selected)
8556 edje_object_signal_emit(ic->obj, "e,state,selected", "e");
8557 }
8558 }
8559 }
8560 edje_thaw();
8561 evas_event_thaw(evas_object_evas_get(sd->obj));
8562 }
8563
8564 /**************************/
8565
8566 static void
_e_fm2_smart_add(Evas_Object * obj)8567 _e_fm2_smart_add(Evas_Object *obj)
8568 {
8569 E_Fm2_Smart_Data *sd;
8570
8571 sd = E_NEW(E_Fm2_Smart_Data, 1);
8572 if (!sd) return;
8573
8574 sd->view_mode = -1; /* unset */
8575 sd->icon_size = -1; /* unset */
8576
8577 sd->obj = obj;
8578 sd->clip = evas_object_rectangle_add(evas_object_evas_get(obj));
8579 evas_object_smart_member_add(sd->clip, obj);
8580 evas_object_color_set(sd->clip, 255, 255, 255, 255);
8581
8582 sd->underlay = evas_object_rectangle_add(evas_object_evas_get(obj));
8583 evas_object_clip_set(sd->underlay, sd->clip);
8584 evas_object_smart_member_add(sd->underlay, obj);
8585 evas_object_color_set(sd->underlay, 0, 0, 0, 0);
8586 evas_object_show(sd->underlay);
8587
8588 evas_object_event_callback_add(obj, EVAS_CALLBACK_KEY_DOWN, _e_fm2_cb_key_down, sd);
8589 //evas_object_event_callback_add(obj, EVAS_CALLBACK_FOCUS_IN, _e_fm2_cb_focus_in, sd);
8590 evas_object_event_callback_add(sd->underlay, EVAS_CALLBACK_MOUSE_DOWN, _e_fm2_cb_mouse_down, sd);
8591 evas_object_event_callback_add(sd->underlay, EVAS_CALLBACK_MOUSE_UP, _e_fm2_cb_mouse_up, sd);
8592 evas_object_event_callback_add(sd->underlay, EVAS_CALLBACK_MOUSE_MOVE, _e_fm2_cb_mouse_move, sd);
8593
8594 sd->drop = edje_object_add(evas_object_evas_get(obj));
8595 evas_object_clip_set(sd->drop, sd->clip);
8596 _e_fm2_theme_edje_object_set(sd, sd->drop,
8597 "base/theme/fileman",
8598 "list/drop_between");
8599 evas_object_smart_member_add(sd->drop, obj);
8600 evas_object_show(sd->drop);
8601
8602 sd->drop_in = edje_object_add(evas_object_evas_get(obj));
8603 evas_object_clip_set(sd->drop_in, sd->clip);
8604 _e_fm2_theme_edje_object_set(sd, sd->drop_in,
8605 "base/theme/fileman",
8606 "list/drop_in");
8607 evas_object_smart_member_add(sd->drop_in, obj);
8608 evas_object_show(sd->drop_in);
8609
8610 sd->overlay = edje_object_add(evas_object_evas_get(obj));
8611 evas_object_clip_set(sd->overlay, sd->clip);
8612 _e_fm2_theme_edje_object_set(sd, sd->overlay,
8613 "base/theme/fileman",
8614 "overlay");
8615 evas_object_smart_member_add(sd->overlay, obj);
8616 evas_object_show(sd->overlay);
8617
8618 sd->sel_rect = edje_object_add(evas_object_evas_get(obj));
8619 evas_object_clip_set(sd->sel_rect, sd->clip);
8620 _e_fm2_theme_edje_object_set(sd, sd->sel_rect, "base/theme/fileman",
8621 "rubberband");
8622 evas_object_smart_member_add(sd->sel_rect, obj);
8623
8624 evas_object_smart_data_set(obj, sd);
8625 evas_object_move(obj, 0, 0);
8626 evas_object_resize(obj, 0, 0);
8627
8628 E_LIST_HANDLER_APPEND(sd->handlers, E_EVENT_CONFIG_ICON_THEME, _e_fm2_cb_theme, sd->obj);
8629 E_LIST_HANDLER_APPEND(sd->handlers, EFREET_EVENT_ICON_CACHE_UPDATE, _e_fm2_icon_cache_update, sd);
8630
8631 _e_fm2_list = eina_list_append(_e_fm2_list, sd->obj);
8632 }
8633
8634 static void
_e_fm2_smart_del(Evas_Object * obj)8635 _e_fm2_smart_del(Evas_Object *obj)
8636 {
8637 E_Fm2_Smart_Data *sd;
8638
8639 sd = evas_object_smart_data_get(obj);
8640 if (!sd) return;
8641
8642 E_FREE_LIST(sd->handlers, ecore_event_handler_del);
8643
8644 _e_fm2_client_monitor_list_end(obj);
8645 if (sd->realpath) _e_fm2_client_monitor_del(sd->id, sd->realpath);
8646 _e_fm2_live_process_end(obj);
8647 _e_fm2_queue_free(obj);
8648 _e_fm2_regions_free(obj);
8649 _e_fm2_icons_free(obj);
8650 if (sd->selected_icons) eina_list_free(sd->selected_icons);
8651 if (sd->menu)
8652 {
8653 e_menu_post_deactivate_callback_set(sd->menu, NULL, NULL);
8654 e_object_del(E_OBJECT(sd->menu));
8655 sd->menu = NULL;
8656 }
8657 if (sd->entry_dialog)
8658 {
8659 e_object_del(E_OBJECT(sd->entry_dialog));
8660 sd->entry_dialog = NULL;
8661 }
8662 if (sd->image_dialog)
8663 {
8664 e_object_del(E_OBJECT(sd->image_dialog));
8665 sd->image_dialog = NULL;
8666 }
8667 E_FREE_LIST(sd->rename_dialogs, e_object_del);
8668 if (sd->scroll_job) ecore_job_del(sd->scroll_job);
8669 if (sd->resize_job) ecore_job_del(sd->resize_job);
8670 if (sd->refresh_job) ecore_job_del(sd->refresh_job);
8671 eina_stringshare_del(sd->custom_theme);
8672 eina_stringshare_del(sd->custom_theme_content);
8673 sd->custom_theme = sd->custom_theme_content = NULL;
8674 eina_stringshare_del(sd->dev);
8675 eina_stringshare_del(sd->path);
8676 eina_stringshare_del(sd->realpath);
8677 eina_stringshare_del(sd->new_file.filename);
8678 sd->dev = sd->path = sd->realpath = NULL;
8679 if (sd->mount)
8680 {
8681 e_fm2_device_unmount(sd->mount);
8682 sd->mount = NULL;
8683 }
8684 if (sd->config) _e_fm2_config_free(sd->config);
8685
8686 E_FREE(sd->typebuf.buf);
8687 if (sd->typebuf.timer) ecore_timer_del(sd->typebuf.timer);
8688 sd->typebuf.timer = NULL;
8689 eina_list_free(sd->mount_ops);
8690
8691 evas_object_del(sd->underlay);
8692 evas_object_del(sd->overlay);
8693 evas_object_del(sd->drop);
8694 evas_object_del(sd->drop_in);
8695 evas_object_del(sd->sel_rect);
8696 evas_object_del(sd->clip);
8697 if (sd->drop_handler) e_drop_handler_del(sd->drop_handler);
8698 if (_e_fm2_list_walking == 0)
8699 _e_fm2_list = eina_list_remove(_e_fm2_list, sd->obj);
8700 else
8701 _e_fm2_list_remove = eina_list_append(_e_fm2_list_remove, sd->obj);
8702 if (sd->desktop) efreet_desktop_free(sd->desktop);
8703 sd->desktop = NULL;
8704 free(sd);
8705 e_fm2_custom_file_flush();
8706 }
8707
8708 static void
_e_fm2_smart_move(Evas_Object * obj,Evas_Coord x,Evas_Coord y)8709 _e_fm2_smart_move(Evas_Object *obj, Evas_Coord x, Evas_Coord y)
8710 {
8711 E_Fm2_Smart_Data *sd;
8712
8713 sd = evas_object_smart_data_get(obj);
8714 if (!sd) return;
8715 if ((sd->x == x) && (sd->y == y)) return;
8716 sd->x = x;
8717 sd->y = y;
8718 evas_object_move(sd->underlay, sd->x, sd->y);
8719 if (!sd->overlay_clip)
8720 evas_object_move(sd->overlay, sd->x, sd->y);
8721 _e_fm2_dnd_drop_configure(sd->obj);
8722 evas_object_move(sd->clip, sd->x - OVERCLIP, sd->y - OVERCLIP);
8723 _e_fm2_obj_icons_place(sd);
8724 if (sd->drop_handler)
8725 e_drop_handler_geometry_set(sd->drop_handler, sd->x, sd->y, sd->w, sd->h);
8726 }
8727
8728 static void
_e_fm2_smart_resize(Evas_Object * obj,Evas_Coord w,Evas_Coord h)8729 _e_fm2_smart_resize(Evas_Object *obj, Evas_Coord w, Evas_Coord h)
8730 {
8731 E_Fm2_Smart_Data *sd;
8732 Eina_Bool wch = EINA_FALSE;
8733
8734 sd = evas_object_smart_data_get(obj);
8735 if (!sd) return;
8736 if ((sd->w == w) && (sd->h == h)) return;
8737 if (w != sd->w) wch = EINA_TRUE;
8738 sd->w = w;
8739 sd->h = h;
8740 evas_object_resize(sd->underlay, sd->w, sd->h);
8741 if (!sd->overlay_clip)
8742 evas_object_resize(sd->overlay, sd->w, sd->h);
8743 _e_fm2_dnd_drop_configure(sd->obj);
8744 evas_object_resize(sd->clip, sd->w + (OVERCLIP * 2), sd->h + (OVERCLIP * 2));
8745
8746 /* for automatic layout - do this - NB; we could put this on a timer delay */
8747 if ((_e_fm2_view_mode_get(sd) == E_FM2_VIEW_MODE_LIST) ||
8748 (_e_fm2_view_mode_get(sd) == E_FM2_VIEW_MODE_GRID_ICONS))
8749 {
8750 if (wch)
8751 {
8752 if (sd->resize_job) ecore_job_del(sd->resize_job);
8753 sd->resize_job = ecore_job_add(_e_fm2_cb_resize_job, obj);
8754 }
8755 else
8756 {
8757 if (sd->scroll_job) ecore_job_del(sd->scroll_job);
8758 sd->scroll_job = ecore_job_add(_e_fm2_cb_scroll_job, obj);
8759 }
8760 }
8761 else if (_e_fm2_view_mode_get(sd) == E_FM2_VIEW_MODE_CUSTOM_ICONS)
8762 {
8763 if (sd->config->view.fit_custom_pos)
8764 {
8765 if (sd->resize_job) ecore_job_del(sd->resize_job);
8766 sd->resize_job = ecore_job_add(_e_fm2_cb_resize_job, obj);
8767 }
8768 else
8769 {
8770 if (sd->scroll_job) ecore_job_del(sd->scroll_job);
8771 sd->scroll_job = ecore_job_add(_e_fm2_cb_scroll_job, obj);
8772 }
8773 }
8774 if (sd->drop_handler)
8775 e_drop_handler_geometry_set(sd->drop_handler, sd->x, sd->y, sd->w, sd->h);
8776 }
8777
8778 static void
_e_fm2_smart_show(Evas_Object * obj)8779 _e_fm2_smart_show(Evas_Object *obj)
8780 {
8781 E_Fm2_Smart_Data *sd;
8782
8783 sd = evas_object_smart_data_get(obj);
8784 if (!sd) return;
8785 evas_object_show(sd->clip);
8786 }
8787
8788 static void
_e_fm2_smart_hide(Evas_Object * obj)8789 _e_fm2_smart_hide(Evas_Object *obj)
8790 {
8791 E_Fm2_Smart_Data *sd;
8792
8793 sd = evas_object_smart_data_get(obj);
8794 if (!sd) return;
8795 evas_object_hide(sd->clip);
8796 }
8797
8798 static void
_e_fm2_smart_color_set(Evas_Object * obj,int r,int g,int b,int a)8799 _e_fm2_smart_color_set(Evas_Object *obj, int r, int g, int b, int a)
8800 {
8801 E_Fm2_Smart_Data *sd;
8802
8803 sd = evas_object_smart_data_get(obj);
8804 if (!sd) return;
8805 evas_object_color_set(sd->clip, r, g, b, a);
8806 }
8807
8808 static void
_e_fm2_smart_clip_set(Evas_Object * obj,Evas_Object * clip)8809 _e_fm2_smart_clip_set(Evas_Object *obj, Evas_Object *clip)
8810 {
8811 E_Fm2_Smart_Data *sd;
8812
8813 sd = evas_object_smart_data_get(obj);
8814 if (!sd) return;
8815 evas_object_clip_set(sd->clip, clip);
8816 }
8817
8818 static void
_e_fm2_smart_clip_unset(Evas_Object * obj)8819 _e_fm2_smart_clip_unset(Evas_Object *obj)
8820 {
8821 E_Fm2_Smart_Data *sd;
8822
8823 sd = evas_object_smart_data_get(obj);
8824 if (!sd) return;
8825 evas_object_clip_unset(sd->clip);
8826 }
8827
8828 static void
_e_fm2_overlay_clip_resize(void * data,Evas * e EINA_UNUSED,Evas_Object * obj,void * event_info EINA_UNUSED)8829 _e_fm2_overlay_clip_resize(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
8830 {
8831 E_Fm2_Smart_Data *sd = data;
8832 int w, h;
8833
8834 evas_object_geometry_get(obj, NULL, NULL, &w, &h);
8835 evas_object_resize(sd->overlay, w, h);
8836 }
8837
8838 static void
_e_fm2_overlay_clip_move(void * data,Evas * e EINA_UNUSED,Evas_Object * obj,void * event_info EINA_UNUSED)8839 _e_fm2_overlay_clip_move(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
8840 {
8841 E_Fm2_Smart_Data *sd = data;
8842 int x, y;
8843
8844 evas_object_geometry_get(obj, &x, &y, NULL, NULL);
8845 evas_object_move(sd->overlay, x, y);
8846 }
8847
8848 static void
_e_fm2_view_menu_sorting_change_case(void * data,E_Menu * m EINA_UNUSED,E_Menu_Item * mi)8849 _e_fm2_view_menu_sorting_change_case(void *data, E_Menu *m EINA_UNUSED, E_Menu_Item *mi)
8850 {
8851 E_Fm2_Smart_Data *sd = data;
8852
8853 sd->config->list.sort.no_case = !mi->toggle;
8854 _e_fm2_refresh(sd, NULL, NULL);
8855 }
8856
8857 static void
_e_fm2_view_menu_sorting_change_size(void * data,E_Menu * m EINA_UNUSED,E_Menu_Item * mi)8858 _e_fm2_view_menu_sorting_change_size(void *data, E_Menu *m EINA_UNUSED, E_Menu_Item *mi)
8859 {
8860 E_Fm2_Smart_Data *sd = data;
8861
8862 sd->config->list.sort.size = mi->toggle;
8863 _e_fm2_refresh(sd, NULL, NULL);
8864 }
8865
8866 static void
_e_fm2_view_menu_sorting_change_mtime(void * data,E_Menu * m EINA_UNUSED,E_Menu_Item * mi)8867 _e_fm2_view_menu_sorting_change_mtime(void *data, E_Menu *m EINA_UNUSED, E_Menu_Item *mi)
8868 {
8869 E_Fm2_Smart_Data *sd = data;
8870
8871 sd->config->list.sort.mtime = mi->toggle;
8872 _e_fm2_refresh(sd, NULL, NULL);
8873 }
8874
8875 static void
_e_fm2_view_menu_sorting_change_extension(void * data,E_Menu * m EINA_UNUSED,E_Menu_Item * mi)8876 _e_fm2_view_menu_sorting_change_extension(void *data, E_Menu *m EINA_UNUSED, E_Menu_Item *mi)
8877 {
8878 E_Fm2_Smart_Data *sd = data;
8879
8880 sd->config->list.sort.extension = mi->toggle;
8881 _e_fm2_refresh(sd, NULL, NULL);
8882 }
8883
8884 static void
_e_fm2_view_menu_sorting_change_dirs_first(void * data,E_Menu * m EINA_UNUSED,E_Menu_Item * mi)8885 _e_fm2_view_menu_sorting_change_dirs_first(void *data, E_Menu *m EINA_UNUSED, E_Menu_Item *mi)
8886 {
8887 E_Fm2_Smart_Data *sd = data;
8888
8889 sd->config->list.sort.dirs.first = mi->toggle;
8890 if (mi->toggle && sd->config->list.sort.dirs.last)
8891 sd->config->list.sort.dirs.last = 0;
8892 _e_fm2_refresh(sd, NULL, NULL);
8893 }
8894
8895 static void
_e_fm2_view_menu_sorting_change_dirs_last(void * data,E_Menu * m EINA_UNUSED,E_Menu_Item * mi)8896 _e_fm2_view_menu_sorting_change_dirs_last(void *data, E_Menu *m EINA_UNUSED, E_Menu_Item *mi)
8897 {
8898 E_Fm2_Smart_Data *sd = data;
8899
8900 sd->config->list.sort.dirs.last = mi->toggle;
8901 if (mi->toggle && sd->config->list.sort.dirs.first)
8902 sd->config->list.sort.dirs.first = 0;
8903 _e_fm2_refresh(sd, NULL, NULL);
8904 }
8905
8906 static void
_e_fm2_view_menu_sorting_pre(void * data,E_Menu * m EINA_UNUSED,E_Menu_Item * mi)8907 _e_fm2_view_menu_sorting_pre(void *data, E_Menu *m EINA_UNUSED, E_Menu_Item *mi)
8908 {
8909 E_Fm2_Smart_Data *sd = data;
8910 E_Menu *subm;
8911
8912 subm = e_menu_new();
8913 e_menu_item_submenu_set(mi, subm);
8914
8915 mi = e_menu_item_new(subm);
8916 e_menu_item_label_set(mi, _("Case Sensitive"));
8917 e_menu_item_check_set(mi, 1);
8918 e_menu_item_toggle_set(mi, !sd->config->list.sort.no_case);
8919 e_menu_item_callback_set(mi, _e_fm2_view_menu_sorting_change_case, sd);
8920
8921 mi = e_menu_item_new(subm);
8922 e_menu_item_label_set(mi, _("Sort By Extension"));
8923 e_menu_item_check_set(mi, 1);
8924 e_menu_item_toggle_set(mi, sd->config->list.sort.extension);
8925 e_menu_item_callback_set(mi, _e_fm2_view_menu_sorting_change_extension, sd);
8926
8927 mi = e_menu_item_new(subm);
8928 e_menu_item_label_set(mi, _("Sort By Modification Time"));
8929 e_menu_item_check_set(mi, 1);
8930 e_menu_item_toggle_set(mi, sd->config->list.sort.mtime);
8931 e_menu_item_callback_set(mi, _e_fm2_view_menu_sorting_change_mtime, sd);
8932
8933 mi = e_menu_item_new(subm);
8934 e_menu_item_label_set(mi, _("Sort By Size"));
8935 e_menu_item_check_set(mi, 1);
8936 e_menu_item_toggle_set(mi, sd->config->list.sort.size);
8937 e_menu_item_callback_set(mi, _e_fm2_view_menu_sorting_change_size, sd);
8938
8939 mi = e_menu_item_new(subm);
8940 e_menu_item_separator_set(mi, 1);
8941
8942 mi = e_menu_item_new(subm);
8943 e_menu_item_label_set(mi, _("Directories First"));
8944 e_menu_item_check_set(mi, 1);
8945 e_menu_item_toggle_set(mi, sd->config->list.sort.dirs.first);
8946 e_menu_item_callback_set(mi, _e_fm2_view_menu_sorting_change_dirs_first, sd);
8947
8948 mi = e_menu_item_new(subm);
8949 e_menu_item_label_set(mi, _("Directories Last"));
8950 e_menu_item_check_set(mi, 1);
8951 e_menu_item_toggle_set(mi, sd->config->list.sort.dirs.last);
8952 e_menu_item_callback_set(mi, _e_fm2_view_menu_sorting_change_dirs_last, sd);
8953 }
8954
8955 static void
_e_fm2_menu(Evas_Object * obj,unsigned int timestamp)8956 _e_fm2_menu(Evas_Object *obj, unsigned int timestamp)
8957 {
8958 E_Fm2_Smart_Data *sd;
8959 E_Menu *mn, *sub;
8960 E_Menu_Item *mi;
8961 E_Zone *zone;
8962 int x, y;
8963
8964 sd = evas_object_smart_data_get(obj);
8965 if (!sd) return;
8966
8967 mn = e_menu_new();
8968 e_object_data_set(E_OBJECT(mn), obj);
8969 e_menu_category_set(mn, "e/fileman/action");
8970
8971 if (sd->icon_menu.replace.func)
8972 sd->icon_menu.replace.func(sd->icon_menu.replace.data, sd->obj, mn, NULL);
8973 else
8974 {
8975 if (sd->icon_menu.start.func)
8976 sd->icon_menu.start.func(sd->icon_menu.start.data, sd->obj, mn, NULL);
8977 if (!(sd->icon_menu.flags & E_FM2_MENU_NO_VIEW_MENU))
8978 {
8979 mi = e_menu_item_new(mn);
8980 e_menu_item_label_set(mi, _("View Mode"));
8981 e_util_menu_item_theme_icon_set(mi, "preferences-look");
8982 sub = e_menu_new();
8983 e_menu_item_submenu_set(mi, sub);
8984 e_object_unref(E_OBJECT(sub));
8985 e_object_data_set(E_OBJECT(sub), sd);
8986 e_menu_pre_activate_callback_set(sub, _e_fm2_view_menu_pre, sd);
8987
8988 mi = e_menu_item_new(mn);
8989 e_menu_item_label_set(mi, _("Sorting"));
8990 e_menu_item_submenu_pre_callback_set(mi, _e_fm2_view_menu_sorting_pre, sd);
8991 }
8992 if (!(sd->icon_menu.flags &
8993 (E_FM2_MENU_NO_SHOW_HIDDEN | E_FM2_MENU_NO_REMEMBER_ORDERING | E_FM2_MENU_NO_ACTIVATE_CHANGE)))
8994 {
8995 mi = e_menu_item_new(mn);
8996 e_menu_item_label_set(mi, _("Options"));
8997 e_util_menu_item_theme_icon_set(mi, "preferences-system");
8998 sub = e_menu_new();
8999 e_menu_item_submenu_set(mi, sub);
9000 e_object_unref(E_OBJECT(sub));
9001 e_object_data_set(E_OBJECT(sub), sd);
9002 e_menu_pre_activate_callback_set(sub, _e_fm2_options_menu_pre, sd);
9003 }
9004 if (!(sd->icon_menu.flags & E_FM2_MENU_NO_REFRESH))
9005 {
9006 mi = e_menu_item_new(mn);
9007 e_menu_item_label_set(mi, _("Refresh View"));
9008 e_util_menu_item_theme_icon_set(mi, "view-refresh");
9009 e_menu_item_callback_set(mi, _e_fm2_refresh, sd);
9010 }
9011
9012 if (!(sd->icon_menu.flags & E_FM2_MENU_NO_NEW))
9013 {
9014 mi = e_menu_item_new(mn);
9015 e_menu_item_separator_set(mi, 1);
9016
9017 mi = e_menu_item_new(mn);
9018 e_menu_item_label_set(mi, _("New..."));
9019 e_util_menu_item_theme_icon_set(mi, "add");
9020 sub = e_menu_new();
9021 e_menu_item_submenu_set(mi, sub);
9022 e_object_unref(E_OBJECT(sub));
9023 e_object_data_set(E_OBJECT(sub), sd);
9024 e_menu_pre_activate_callback_set(sub, _e_fm2_add_menu_pre, sd);
9025 }
9026
9027 if (sd->realpath)
9028 {
9029 const Eina_List *ll;
9030 /* see if we have any mime handlers registered for this file */
9031 ll = e_fm2_mime_handler_mime_handlers_get("inode/directory");
9032 if (ll)
9033 {
9034 mi = e_menu_item_new(mn);
9035 e_menu_item_separator_set(mi, 1);
9036
9037 mi = e_menu_item_new(mn);
9038 e_menu_item_label_set(mi, _("Actions..."));
9039 e_util_menu_item_theme_icon_set(mi, "preferences-plugin");
9040 sub = e_menu_new();
9041 e_menu_item_submenu_set(mi, sub);
9042 _e_fm2_context_menu_append(sd, sd->realpath, ll, sub, NULL);
9043 }
9044 }
9045
9046 if (((!(sd->icon_menu.flags & E_FM2_MENU_NO_PASTE)) ||
9047 (!(sd->icon_menu.flags & E_FM2_MENU_NO_SYMLINK))) &&
9048 (eina_list_count(_e_fm_file_buffer) > 0) &&
9049 ecore_file_can_write(sd->realpath))
9050 {
9051 mi = e_menu_item_new(mn);
9052 e_menu_item_separator_set(mi, 1);
9053
9054 if (!(sd->icon_menu.flags & E_FM2_MENU_NO_PASTE))
9055 {
9056 mi = e_menu_item_new(mn);
9057 e_menu_item_label_set(mi, _("Paste"));
9058 e_util_menu_item_theme_icon_set(mi, "edit-paste");
9059 e_menu_item_callback_set(mi, _e_fm2_file_paste_menu, sd);
9060 }
9061
9062 if (!(sd->icon_menu.flags & E_FM2_MENU_NO_SYMLINK))
9063 {
9064 mi = e_menu_item_new(mn);
9065 e_menu_item_label_set(mi, _("Link"));
9066 e_util_menu_item_theme_icon_set(mi, "emblem-symbolic-link");
9067 e_menu_item_callback_set(mi, _e_fm2_file_symlink_menu, sd);
9068 }
9069 }
9070
9071 if (sd->icon_menu.end.func)
9072 sd->icon_menu.end.func(sd->icon_menu.end.data, sd->obj, mn, NULL);
9073 }
9074
9075 ecore_evas_pointer_xy_get(e_comp->ee, &x, &y);
9076 zone = e_zone_current_get();
9077 if (!zone)
9078 {
9079 e_object_del(E_OBJECT(mn));
9080 return;
9081 }
9082 sd->menu = mn;
9083 e_menu_post_deactivate_callback_set(mn, _e_fm2_menu_post_cb, sd);
9084 e_menu_activate_mouse(mn, zone,
9085 x, y, 1, 1,
9086 E_MENU_POP_DIRECTION_DOWN, timestamp);
9087 }
9088
9089 static void
_e_fm2_menu_post_cb(void * data,E_Menu * m EINA_UNUSED)9090 _e_fm2_menu_post_cb(void *data, E_Menu *m EINA_UNUSED)
9091 {
9092 E_Fm2_Smart_Data *sd;
9093
9094 sd = data;
9095 sd->menu = NULL;
9096 }
9097
9098 static void
_e_fm2_icon_menu(E_Fm2_Icon * ic,Evas_Object * obj,unsigned int timestamp)9099 _e_fm2_icon_menu(E_Fm2_Icon *ic, Evas_Object *obj, unsigned int timestamp)
9100 {
9101 E_Fm2_Smart_Data *sd;
9102 E_Menu *mn, *sub;
9103 E_Menu_Item *mi;
9104 E_Zone *zone;
9105 Eina_List *sel;
9106 Eina_List *l = NULL;
9107 int x, y, can_w, can_w2, protect;
9108 char buf[PATH_MAX], *ext;
9109 Eina_Bool writable;
9110
9111 sd = ic->sd;
9112 if (ic->menu) return;
9113
9114 mn = e_menu_new();
9115 e_object_data_set(E_OBJECT(mn), obj);
9116 e_menu_category_set(mn, "e/fileman/action");
9117
9118 if (sd->icon_menu.replace.func)
9119 sd->icon_menu.replace.func(sd->icon_menu.replace.data, sd->obj, mn, &ic->info);
9120 else
9121 {
9122 writable = ecore_file_can_write(sd->realpath);
9123
9124 if (sd->icon_menu.start.func)
9125 sd->icon_menu.start.func(sd->icon_menu.start.data, sd->obj, mn, &ic->info);
9126 if (!(sd->icon_menu.flags & E_FM2_MENU_NO_VIEW_MENU))
9127 {
9128 mi = e_menu_item_new(mn);
9129 e_menu_item_label_set(mi, _("View Mode"));
9130 e_util_menu_item_theme_icon_set(mi, "preferences-look");
9131 sub = e_menu_new();
9132 e_menu_item_submenu_set(mi, sub);
9133 e_object_data_set(E_OBJECT(sub), sd);
9134 e_object_unref(E_OBJECT(sub));
9135 e_menu_pre_activate_callback_set(sub, _e_fm2_icon_view_menu_pre, sd);
9136
9137 mi = e_menu_item_new(mn);
9138 e_menu_item_label_set(mi, _("Sorting"));
9139 e_menu_item_submenu_pre_callback_set(mi, _e_fm2_view_menu_sorting_pre, sd);
9140 }
9141 if (!(sd->icon_menu.flags &
9142 (E_FM2_MENU_NO_SHOW_HIDDEN | E_FM2_MENU_NO_REMEMBER_ORDERING | E_FM2_MENU_NO_ACTIVATE_CHANGE)))
9143 {
9144 mi = e_menu_item_new(mn);
9145 e_menu_item_label_set(mi, _("Options"));
9146 e_util_menu_item_theme_icon_set(mi, "preferences-system");
9147 sub = e_menu_new();
9148 e_menu_item_submenu_set(mi, sub);
9149 e_object_unref(E_OBJECT(sub));
9150 e_object_data_set(E_OBJECT(sub), sd);
9151 e_menu_pre_activate_callback_set(sub, _e_fm2_options_menu_pre, sd);
9152 }
9153 if (!(sd->icon_menu.flags & E_FM2_MENU_NO_REFRESH))
9154 {
9155 mi = e_menu_item_new(mn);
9156 e_menu_item_label_set(mi, _("Refresh View"));
9157 e_util_menu_item_theme_icon_set(mi, "view-refresh");
9158 e_menu_item_callback_set(mi, _e_fm2_refresh, sd);
9159 }
9160
9161 /* FIXME: stat the dir itself - move to e_fm_main */
9162 if (writable && !(sd->icon_menu.flags & E_FM2_MENU_NO_NEW))
9163 {
9164 mi = e_menu_item_new(mn);
9165 e_menu_item_separator_set(mi, 1);
9166
9167 mi = e_menu_item_new(mn);
9168 e_menu_item_label_set(mi, _("New..."));
9169 e_util_menu_item_theme_icon_set(mi, "add");
9170 sub = e_menu_new();
9171 e_menu_item_submenu_set(mi, sub);
9172 e_object_unref(E_OBJECT(sub));
9173 e_object_data_set(E_OBJECT(sub), sd);
9174 e_menu_pre_activate_callback_set(sub, _e_fm2_add_menu_pre, sd);
9175 }
9176 {
9177 const Eina_List *ll = NULL;
9178 E_Menu *subm = NULL;
9179 if (ic->info.mime)
9180 {
9181 /* see if we have any mime handlers registered for this file */
9182 ll = e_fm2_mime_handler_mime_handlers_get(ic->info.mime);
9183 }
9184 if (ll || sd->realpath)
9185 {
9186 mi = e_menu_item_new(mn);
9187 e_menu_item_separator_set(mi, 1);
9188
9189 mi = e_menu_item_new(mn);
9190 e_menu_item_label_set(mi, _("Actions..."));
9191 e_util_menu_item_theme_icon_set(mi, "preferences-plugin");
9192 subm = e_menu_new();
9193 e_menu_item_submenu_set(mi, subm);
9194 _e_fm2_icon_realpath(ic, buf, sizeof(buf));
9195 }
9196 if (ll)
9197 _e_fm2_context_menu_append(sd, buf, ll, subm, ic);
9198 if (sd->realpath && (ic->info.mime != _e_fm2_mime_inode_directory))
9199 {
9200 ll = e_fm2_mime_handler_mime_handlers_get("inode/directory");
9201 _e_fm2_context_menu_append(sd, sd->realpath, ll, subm, ic);
9202 }
9203
9204 /* see if we have any glob handlers registered for this file */
9205 ext = strrchr(ic->info.file, '.');
9206 if (ext)
9207 {
9208 snprintf(buf, sizeof(buf), "*%s", ext);
9209 l = e_fm2_mime_handler_glob_handlers_get(buf);
9210 if (l)
9211 {
9212 if (subm)
9213 {
9214 if (subm->items)
9215 {
9216 mi = e_menu_item_new(mn);
9217 e_menu_item_separator_set(mi, 1);
9218 }
9219 }
9220 else
9221 {
9222 mi = e_menu_item_new(mn);
9223 e_menu_item_separator_set(mi, 1);
9224
9225 mi = e_menu_item_new(mn);
9226 e_menu_item_label_set(mi, _("Actions..."));
9227 e_util_menu_item_theme_icon_set(mi, "preferences-plugin");
9228 subm = e_menu_new();
9229 e_menu_item_submenu_set(mi, subm);
9230 }
9231 _e_fm2_icon_realpath(ic, buf, sizeof(buf));
9232 _e_fm2_context_menu_append(sd, buf, l, subm, ic);
9233 eina_list_free(l);
9234 }
9235 }
9236 }
9237 if (!ic->info.removable)
9238 {
9239 if (!(sd->icon_menu.flags & E_FM2_MENU_NO_CUT))
9240 {
9241 if (writable)
9242 {
9243 mi = e_menu_item_new(mn);
9244 e_menu_item_separator_set(mi, 1);
9245
9246 mi = e_menu_item_new(mn);
9247 e_menu_item_label_set(mi, _("Cut"));
9248 e_util_menu_item_theme_icon_set(mi, "edit-cut");
9249 e_menu_item_callback_set(mi, _e_fm2_file_cut_menu, sd);
9250 }
9251 }
9252 if (!(sd->icon_menu.flags & E_FM2_MENU_NO_COPY))
9253 {
9254 if (!writable)
9255 {
9256 mi = e_menu_item_new(mn);
9257 e_menu_item_separator_set(mi, 1);
9258 }
9259
9260 mi = e_menu_item_new(mn);
9261 e_menu_item_label_set(mi, _("Copy"));
9262 e_util_menu_item_theme_icon_set(mi, "edit-copy");
9263 e_menu_item_callback_set(mi, _e_fm2_file_copy_menu, sd);
9264 }
9265
9266 if (((!(sd->icon_menu.flags & E_FM2_MENU_NO_PASTE)) ||
9267 (!(sd->icon_menu.flags & E_FM2_MENU_NO_SYMLINK))) &&
9268 (eina_list_count(_e_fm_file_buffer) > 0) &&
9269 writable)
9270 {
9271 if (!(sd->icon_menu.flags & E_FM2_MENU_NO_PASTE))
9272 {
9273 mi = e_menu_item_new(mn);
9274 e_menu_item_label_set(mi, _("Paste"));
9275 e_util_menu_item_theme_icon_set(mi, "edit-paste");
9276 e_menu_item_callback_set(mi, _e_fm2_file_paste_menu, sd);
9277 }
9278
9279 if (!(sd->icon_menu.flags & E_FM2_MENU_NO_SYMLINK))
9280 {
9281 mi = e_menu_item_new(mn);
9282 e_menu_item_label_set(mi, _("Link"));
9283 e_util_menu_item_theme_icon_set(mi, "emblem-symbolic-link");
9284 e_menu_item_callback_set(mi, _e_fm2_file_symlink_menu, sd);
9285 }
9286 }
9287 }
9288
9289 can_w2 = 1;
9290 if (ic->sd->order_file)
9291 {
9292 snprintf(buf, sizeof(buf), "%s/.order", sd->realpath);
9293 /* FIXME: stat the .order itself - move to e_fm_main */
9294 // can_w2 = ecore_file_can_write(buf);
9295 }
9296 if (ic->info.link)
9297 {
9298 can_w = 1;
9299 /* struct stat st;
9300
9301 if (_e_fm2_icon_realpath(ic, buf, sizeof(buf)) &&
9302 (lstat(buf, &st) == 0))
9303 {
9304 if (st.st_uid == getuid())
9305 {
9306 if (st.st_mode & S_IWUSR) can_w = 1;
9307 }
9308 else if (st.st_gid == getgid())
9309 {
9310 if (st.st_mode & S_IWGRP) can_w = 1;
9311 }
9312 else
9313 {
9314 if (st.st_mode & S_IWOTH) can_w = 1;
9315 }
9316 }
9317 */ }
9318 else
9319 can_w = 1;
9320
9321 sel = e_fm2_selected_list_get(ic->sd->obj);
9322 if ((!sel) || eina_list_count(sel) == 1)
9323 {
9324 _e_fm2_icon_realpath(ic, buf, sizeof(buf));
9325 protect = e_filereg_file_protected(buf);
9326 }
9327 else
9328 protect = 0;
9329 eina_list_free(sel);
9330
9331 if ((can_w) && (can_w2) && !(protect) && !ic->info.removable)
9332 {
9333 if (!(sd->icon_menu.flags & E_FM2_MENU_NO_DELETE))
9334 {
9335 mi = e_menu_item_new(mn);
9336 e_menu_item_label_set(mi, _("Delete"));
9337 e_util_menu_item_theme_icon_set(mi, "edit-delete");
9338 e_menu_item_callback_set(mi, _e_fm2_file_delete_menu, ic);
9339 }
9340
9341 if (!(sd->icon_menu.flags & E_FM2_MENU_NO_RENAME))
9342 {
9343 mi = e_menu_item_new(mn);
9344 e_menu_item_label_set(mi, _("Rename"));
9345 e_util_menu_item_theme_icon_set(mi, "edit-rename");
9346 e_menu_item_callback_set(mi, _e_fm2_file_rename, ic);
9347 }
9348 }
9349
9350 if (ic->info.removable)
9351 {
9352 E_Volume *v;
9353
9354 v = e_fm2_device_volume_find(ic->info.link);
9355 if (v)
9356 {
9357 mi = e_menu_item_new(mn);
9358 e_menu_item_separator_set(mi, 1);
9359
9360 mi = e_menu_item_new(mn);
9361 if (v->mounted)
9362 {
9363 e_menu_item_label_set(mi, _("Unmount"));
9364 e_menu_item_callback_set(mi, _e_fm2_volume_unmount, v);
9365 }
9366 else
9367 {
9368 e_menu_item_label_set(mi, _("Mount"));
9369 e_menu_item_callback_set(mi, _e_fm2_volume_mount, v);
9370 }
9371
9372 mi = e_menu_item_new(mn);
9373 e_menu_item_label_set(mi, _("Eject"));
9374 e_util_menu_item_theme_icon_set(mi, "media-eject");
9375 e_menu_item_callback_set(mi, _e_fm2_volume_eject, v);
9376
9377 mi = e_menu_item_new(mn);
9378 e_menu_item_separator_set(mi, 1);
9379 }
9380 }
9381 mi = e_menu_item_new(mn);
9382 e_menu_item_separator_set(mi, 1);
9383
9384 if ((!ic->info.removable) && ic->info.file && (ic->info.file[0] != '|') && ic->info.mime && (!strcmp(ic->info.mime, "application/x-desktop")))
9385 {
9386 mi = e_menu_item_new(mn);
9387 e_menu_item_label_set(mi, _("Properties"));
9388 e_util_menu_item_theme_icon_set(mi, "document-properties");
9389 e_menu_item_callback_set(mi, _e_fm2_file_properties, ic);
9390 sub = e_menu_new();
9391 e_menu_item_submenu_set(mi, sub);
9392 e_object_unref(E_OBJECT(sub));
9393
9394 mi = e_menu_item_new(sub);
9395 e_menu_item_label_set(mi, _("Application Properties"));
9396 e_util_menu_item_theme_icon_set(mi, "configure");
9397 e_menu_item_callback_set(mi, _e_fm2_file_application_properties, ic);
9398 }
9399 else
9400 sub = NULL;
9401
9402 mi = e_menu_item_new(sub ? : mn);
9403 e_menu_item_label_set(mi, _("File Properties"));
9404 e_util_menu_item_theme_icon_set(mi, "document-properties");
9405 e_menu_item_callback_set(mi, _e_fm2_file_properties, ic);
9406
9407 if (sd->icon_menu.end.func)
9408 sd->icon_menu.end.func(sd->icon_menu.end.data, sd->obj, mn, &(ic->info));
9409 }
9410
9411 ecore_evas_pointer_xy_get(e_comp->ee, &x, &y);
9412 zone = e_zone_current_get();
9413 if (!zone)
9414 {
9415 e_object_del(E_OBJECT(mn));
9416 return;
9417 }
9418 ic->menu = mn;
9419 e_menu_post_deactivate_callback_set(mn, _e_fm2_icon_menu_post_cb, ic);
9420 e_menu_activate_mouse(mn, zone,
9421 x, y, 1, 1,
9422 E_MENU_POP_DIRECTION_DOWN, timestamp);
9423 }
9424
9425 static void
_e_fm2_context_menu_append(E_Fm2_Smart_Data * sd,const char * path,const Eina_List * list,E_Menu * mn,E_Fm2_Icon * ic)9426 _e_fm2_context_menu_append(E_Fm2_Smart_Data *sd, const char *path, const Eina_List *list, E_Menu *mn, E_Fm2_Icon *ic)
9427 {
9428 E_Fm2_Mime_Handler *handler;
9429 Eina_List *l;
9430
9431 if (!list) return;
9432
9433 l = eina_list_clone(list);
9434 l = eina_list_sort(l, -1, _e_fm2_context_list_sort);
9435
9436 EINA_LIST_FREE(l, handler)
9437 {
9438 E_Fm2_Context_Menu_Data *md = NULL;
9439 E_Menu_Item *mi;
9440
9441 if ((!handler) || (!handler->label) || (!e_fm2_mime_handler_test(handler, sd->obj, path)))
9442 continue;
9443
9444 md = E_NEW(E_Fm2_Context_Menu_Data, 1);
9445 if (!md) continue;
9446 md->icon = ic;
9447 md->handler = handler;
9448 md->sd = sd;
9449 _e_fm2_menu_contexts = eina_list_append(_e_fm2_menu_contexts, md);
9450
9451 mi = e_menu_item_new(mn);
9452 e_menu_item_label_set(mi, handler->label);
9453 if (handler->icon_group)
9454 {
9455 if (handler->icon_group[0] == '/')
9456 e_menu_item_icon_file_set(mi, handler->icon_group);
9457 else
9458 e_util_menu_item_theme_icon_set(mi, handler->icon_group);
9459 }
9460 e_menu_item_callback_set(mi, _e_fm2_icon_menu_item_cb, md);
9461 }
9462 }
9463
9464 static int
_e_fm2_context_list_sort(const void * data1,const void * data2)9465 _e_fm2_context_list_sort(const void *data1, const void *data2)
9466 {
9467 const E_Fm2_Mime_Handler *d1, *d2;
9468
9469 if (!data1) return 1;
9470 if (!data2) return -1;
9471 d1 = data1;
9472 if (!d1->label) return 1;
9473 d2 = data2;
9474 if (!d2->label) return -1;
9475 return strcmp(d1->label, d2->label);
9476 }
9477
9478 static void
_e_fm2_icon_menu_post_cb(void * data,E_Menu * m EINA_UNUSED)9479 _e_fm2_icon_menu_post_cb(void *data, E_Menu *m EINA_UNUSED)
9480 {
9481 E_Fm2_Context_Menu_Data *md;
9482 E_Fm2_Icon *ic;
9483
9484 ic = data;
9485 ic->menu = NULL;
9486 EINA_LIST_FREE(_e_fm2_menu_contexts, md)
9487 E_FREE(md);
9488 }
9489
9490 static void
_e_fm2_icon_menu_item_cb(void * data,E_Menu * m EINA_UNUSED,E_Menu_Item * mi EINA_UNUSED)9491 _e_fm2_icon_menu_item_cb(void *data, E_Menu *m EINA_UNUSED, E_Menu_Item *mi EINA_UNUSED)
9492 {
9493 E_Fm2_Context_Menu_Data *md = NULL;
9494 Evas_Object *obj = NULL;
9495 char buf[PATH_MAX];
9496
9497 md = data;
9498 if (!md) return;
9499 if (md->icon)
9500 {
9501 obj = md->icon->info.fm;
9502 if (!obj) return;
9503 snprintf(buf, sizeof(buf), "%s/%s",
9504 e_fm2_real_path_get(obj), md->icon->info.file);
9505 e_fm2_mime_handler_call(md->handler, obj, buf);
9506 }
9507 else
9508 e_fm2_mime_handler_call(md->handler, md->sd->obj, md->sd->realpath);
9509 }
9510
9511 struct e_fm2_view_menu_icon_size_data
9512 {
9513 E_Fm2_Smart_Data *sd;
9514 short size;
9515 };
9516
9517 static void
_e_fm2_view_menu_icon_size_data_free(void * obj)9518 _e_fm2_view_menu_icon_size_data_free(void *obj)
9519 {
9520 struct e_fm2_view_menu_icon_size_data *d = e_object_data_get(obj);
9521 free(d);
9522 }
9523
9524 static void
_e_fm2_view_menu_icon_size_change(void * data,E_Menu * m,E_Menu_Item * mi)9525 _e_fm2_view_menu_icon_size_change(void *data, E_Menu *m, E_Menu_Item *mi)
9526 {
9527 struct e_fm2_view_menu_icon_size_data *d = data;
9528 short current_size = _e_fm2_icon_w_get(d->sd);
9529 d->sd->icon_size = d->size;
9530 d->sd->inherited_dir_props = EINA_FALSE;
9531 if (current_size == d->size)
9532 return;
9533 _e_fm2_refresh(d->sd, m, mi);
9534 }
9535
9536 static void
_e_fm2_view_menu_icon_size_use_default(void * data,E_Menu * m,E_Menu_Item * mi)9537 _e_fm2_view_menu_icon_size_use_default(void *data, E_Menu *m, E_Menu_Item *mi)
9538 {
9539 E_Fm2_Smart_Data *sd = data;
9540 short old, new;
9541
9542 old = _e_fm2_icon_w_get(sd);
9543
9544 if (sd->icon_size == -1)
9545 sd->icon_size = sd->config->icon.icon.w;
9546 else
9547 sd->icon_size = -1;
9548
9549 new = _e_fm2_icon_w_get(sd);
9550 sd->inherited_dir_props = EINA_FALSE;
9551
9552 if (new == old)
9553 return;
9554
9555 _e_fm2_refresh(sd, m, mi);
9556 }
9557
9558 static void
_e_fm2_view_menu_icon_size_pre(void * data,E_Menu * m EINA_UNUSED,E_Menu_Item * mi)9559 _e_fm2_view_menu_icon_size_pre(void *data, E_Menu *m EINA_UNUSED, E_Menu_Item *mi)
9560 {
9561 E_Fm2_Smart_Data *sd = data;
9562 E_Menu *subm;
9563 const short *itr, sizes[] =
9564 {
9565 22, 32, 48, 64, 96, 128, 256, -1
9566 };
9567 short current_size = _e_fm2_icon_w_get(sd);
9568
9569 if (e_scale > 0.0)
9570 current_size /= e_scale;
9571
9572 subm = e_menu_new();
9573 e_menu_item_submenu_set(mi, subm);
9574
9575 for (itr = sizes; *itr > -1; itr++)
9576 {
9577 char buf[32];
9578 struct e_fm2_view_menu_icon_size_data *d;
9579
9580 d = malloc(sizeof(*d));
9581 if (!d)
9582 continue;
9583 d->sd = sd;
9584 d->size = *itr;
9585
9586 snprintf(buf, sizeof(buf), "%hd", *itr);
9587
9588 mi = e_menu_item_new(subm);
9589 e_object_data_set(E_OBJECT(mi), d);
9590 e_object_del_attach_func_set
9591 (E_OBJECT(mi), _e_fm2_view_menu_icon_size_data_free);
9592
9593 e_menu_item_label_set(mi, buf);
9594 e_menu_item_radio_group_set(mi, 1);
9595 e_menu_item_radio_set(mi, 1);
9596
9597 if (current_size == *itr)
9598 e_menu_item_toggle_set(mi, 1);
9599
9600 e_menu_item_callback_set(mi, _e_fm2_view_menu_icon_size_change, d);
9601 }
9602
9603 mi = e_menu_item_new(subm);
9604 e_menu_item_separator_set(mi, 1);
9605
9606 mi = e_menu_item_new(subm);
9607 e_menu_item_label_set(mi, _("Use default"));
9608 e_menu_item_check_set(mi, 1);
9609 e_menu_item_toggle_set(mi, sd->icon_size == -1);
9610 e_menu_item_callback_set(mi, _e_fm2_view_menu_icon_size_use_default, sd);
9611 }
9612
9613 static void
_e_fm2_toggle_inherit_dir_props(void * data,E_Menu * m,E_Menu_Item * mi)9614 _e_fm2_toggle_inherit_dir_props(void *data, E_Menu *m, E_Menu_Item *mi)
9615 {
9616 E_Fm2_Smart_Data *sd = data;
9617
9618 sd->inherited_dir_props = !sd->inherited_dir_props;
9619 _e_fm2_dir_save_props(sd);
9620 _e_fm2_dir_load_props(sd);
9621 _e_fm2_refresh(sd, m, mi);
9622 }
9623
9624 static void
_e_fm2_view_menu_common(E_Menu * subm,E_Fm2_Smart_Data * sd)9625 _e_fm2_view_menu_common(E_Menu *subm, E_Fm2_Smart_Data *sd)
9626 {
9627 char buf[64];
9628 E_Menu_Item *mi;
9629 char view_mode;
9630 int icon_size;
9631
9632 view_mode = _e_fm2_view_mode_get(sd);
9633 if (!(sd->icon_menu.flags & E_FM2_MENU_NO_VIEW_CHANGE))
9634 {
9635 mi = e_menu_item_new(subm);
9636 e_menu_item_label_set(mi, _("Grid Icons"));
9637 e_menu_item_radio_group_set(mi, 1);
9638 e_menu_item_radio_set(mi, 1);
9639 if (view_mode == E_FM2_VIEW_MODE_GRID_ICONS)
9640 e_menu_item_toggle_set(mi, 1);
9641 e_menu_item_callback_set(mi, _e_fm2_view_menu_grid_icons_cb, sd);
9642
9643 mi = e_menu_item_new(subm);
9644 e_menu_item_label_set(mi, _("Custom Icons"));
9645 e_menu_item_radio_group_set(mi, 1);
9646 e_menu_item_radio_set(mi, 1);
9647 if (view_mode == E_FM2_VIEW_MODE_CUSTOM_ICONS)
9648 e_menu_item_toggle_set(mi, 1);
9649 e_menu_item_callback_set(mi, _e_fm2_view_menu_custom_icons_cb, sd);
9650
9651 mi = e_menu_item_new(subm);
9652 e_menu_item_label_set(mi, _("List"));
9653 e_menu_item_radio_group_set(mi, 1);
9654 e_menu_item_radio_set(mi, 1);
9655 if (view_mode == E_FM2_VIEW_MODE_LIST)
9656 e_menu_item_toggle_set(mi, 1);
9657 e_menu_item_callback_set(mi, _e_fm2_view_menu_list_cb, sd);
9658
9659 mi = e_menu_item_new(subm);
9660 e_menu_item_label_set(mi, _("Default View"));
9661 e_menu_item_check_set(mi, 1);
9662 e_menu_item_toggle_set(mi, sd->view_mode == -1);
9663 e_menu_item_callback_set(mi, _e_fm2_view_menu_use_default_cb, sd);
9664
9665 mi = e_menu_item_new(subm);
9666 e_menu_item_separator_set(mi, 1);
9667 }
9668
9669 if (view_mode == E_FM2_VIEW_MODE_LIST)
9670 return;
9671
9672 mi = e_menu_item_new(subm);
9673 e_menu_item_separator_set(mi, 1);
9674
9675 icon_size = _e_fm2_icon_w_get(sd);
9676
9677 // show the icon size as selected (even if it might be influnced by e_scale)
9678 /* if (e_scale > 0.0)
9679 * icon_size /= e_scale; */
9680
9681 snprintf(buf, sizeof(buf), _("Icon Size (%d)"), icon_size);
9682
9683 mi = e_menu_item_new(subm);
9684 e_menu_item_label_set(mi, buf);
9685 e_menu_item_submenu_pre_callback_set(mi, _e_fm2_view_menu_icon_size_pre, sd);
9686 }
9687
9688 static void
_e_fm2_icon_view_menu_pre(void * data,E_Menu * subm)9689 _e_fm2_icon_view_menu_pre(void *data, E_Menu *subm)
9690 {
9691 E_Fm2_Smart_Data *sd;
9692
9693 sd = data;
9694 if (subm->items) return;
9695 _e_fm2_view_menu_common(subm, sd);
9696 }
9697
9698 static void
_e_fm2_new_dir_notify(void * data,Ecore_Thread * eth EINA_UNUSED,char * filename)9699 _e_fm2_new_dir_notify(void *data, Ecore_Thread *eth EINA_UNUSED, char *filename)
9700 {
9701 E_Fm2_Smart_Data *sd = data;
9702
9703 if (!sd->new_file.done)
9704 {
9705 if (filename)
9706 sd->new_file.filename = eina_stringshare_add(ecore_file_file_get(filename));
9707 else
9708 e_util_dialog_internal(_("Error"), _("Could not create a directory!"));
9709 }
9710 free(filename);
9711 }
9712
9713 static void
_e_fm2_new_file_notify(void * data,Ecore_Thread * eth EINA_UNUSED,char * filename)9714 _e_fm2_new_file_notify(void *data, Ecore_Thread *eth EINA_UNUSED, char *filename)
9715 {
9716 E_Fm2_Smart_Data *sd = data;
9717
9718 if (!sd->new_file.done)
9719 {
9720 if (filename)
9721 sd->new_file.filename = eina_stringshare_add(ecore_file_file_get(filename));
9722 else
9723 e_util_dialog_internal(_("Error"), _("Could not create a file!"));
9724 }
9725 free(filename);
9726 }
9727
9728 static void
_e_fm2_new_thread_helper(Ecore_Thread * eth,Eina_Bool dir)9729 _e_fm2_new_thread_helper(Ecore_Thread *eth, Eina_Bool dir)
9730 {
9731 char buf[PATH_MAX];
9732 char *path;
9733 struct stat st;
9734 unsigned int x;
9735 int fd;
9736 Eina_List *texts, *l;
9737
9738 path = ecore_thread_global_data_wait("path", 2.0);
9739 snprintf(buf, sizeof(buf), "%s/%s", path, dir ? _("New Directory") : _("New File"));
9740 errno = 0;
9741 if (stat(buf, &st) && (errno == ENOENT))
9742 {
9743 if (dir)
9744 {
9745 if (ecore_file_mkdir(buf))
9746 {
9747 ecore_thread_global_data_set("efm_pending_filename", strdup(buf), free);
9748 ecore_thread_feedback(eth, strdup(buf));
9749 return;
9750 }
9751 }
9752 else
9753 {
9754 fd = open(buf, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
9755 if (fd)
9756 {
9757 texts = ecore_thread_global_data_wait("efm_text_uri_list", 0.01);
9758 EINA_LIST_FOREACH(texts, l, path)
9759 {
9760 if (write(fd, path, strlen(path)) < 0)
9761 perror("write");
9762 if (write(fd, "\n", 1) < 0)
9763 perror("write");
9764 }
9765 close(fd);
9766 ecore_thread_global_data_set("efm_pending_filename", strdup(buf), free);
9767 ecore_thread_feedback(eth, strdup(buf));
9768 return;
9769 }
9770 }
9771 goto error;
9772 }
9773 else if (errno)
9774 goto error;
9775 for (x = 0; x < UINT_MAX; x++)
9776 {
9777 snprintf(buf, sizeof(buf), "%s/%s %u", path, dir ? _("New Directory") : _("New File"), x);
9778 errno = 0;
9779 if (stat(buf, &st) && (errno == ENOENT))
9780 {
9781 if (dir)
9782 {
9783 if (ecore_file_mkdir(buf))
9784 {
9785 ecore_thread_global_data_set("efm_pending_filename", strdup(buf), free);
9786 ecore_thread_feedback(eth, strdup(buf));
9787 return;
9788 }
9789 }
9790 else
9791 {
9792 fd = open(buf, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
9793 if (fd)
9794 {
9795 texts = ecore_thread_global_data_wait("efm_text_uri_list", 0.01);
9796 EINA_LIST_FOREACH(texts, l, path)
9797 {
9798 if (write(fd, path, strlen(path)) < 0)
9799 perror("write");
9800 if (write(fd, "\n", 1) < 0)
9801 perror("write");
9802 }
9803 close(fd);
9804 ecore_thread_global_data_set("efm_pending_filename", strdup(buf), free);
9805 ecore_thread_feedback(eth, strdup(buf));
9806 return;
9807 }
9808 }
9809 goto error;
9810 }
9811 else if (errno)
9812 goto error;
9813 }
9814 error:
9815 ecore_thread_feedback(eth, NULL);
9816 }
9817
9818 static void
_e_fm2_new_file_thread(void * data EINA_UNUSED,Ecore_Thread * eth)9819 _e_fm2_new_file_thread(void *data EINA_UNUSED, Ecore_Thread *eth)
9820 {
9821 _e_fm2_new_thread_helper(eth, EINA_FALSE);
9822 }
9823
9824 static void
_e_fm2_new_dir_thread(void * data EINA_UNUSED,Ecore_Thread * eth)9825 _e_fm2_new_dir_thread(void *data EINA_UNUSED, Ecore_Thread *eth)
9826 {
9827 _e_fm2_new_thread_helper(eth, EINA_TRUE);
9828 }
9829
9830 static void
_e_fm2_new_file_end(void * data,Ecore_Thread * eth EINA_UNUSED)9831 _e_fm2_new_file_end(void *data, Ecore_Thread *eth EINA_UNUSED)
9832 {
9833 E_Fm2_Smart_Data *sd = data;
9834 sd->new_file.thread = NULL;
9835 ecore_thread_global_data_del("path");
9836 ecore_thread_global_data_del("efm_text_uri_list");
9837 evas_object_unref(sd->obj);
9838 e_fm2_refresh(sd->obj);
9839 }
9840
9841 static void
_e_fm2_new_file_cancel(void * data,Ecore_Thread * eth EINA_UNUSED)9842 _e_fm2_new_file_cancel(void *data, Ecore_Thread *eth EINA_UNUSED)
9843 {
9844 E_Fm2_Smart_Data *sd = data;
9845 sd->new_file.thread = NULL;
9846 ecore_thread_global_data_del("path");
9847 ecore_thread_global_data_del("efm_text_uri_list");
9848 evas_object_unref(sd->obj);
9849 }
9850
9851 static void
_e_fm2_new_file(void * data,E_Menu * m EINA_UNUSED,E_Menu_Item * mi EINA_UNUSED)9852 _e_fm2_new_file(void *data, E_Menu *m EINA_UNUSED, E_Menu_Item *mi EINA_UNUSED)
9853 {
9854 E_Fm2_Smart_Data *sd = data;
9855
9856 if (sd->new_file.thread || sd->new_file.filename)
9857 {
9858 e_util_dialog_internal(_("Error"), _("Already creating a new file for this directory!"));
9859 return;
9860 }
9861 if (!ecore_file_can_write(sd->realpath))
9862 {
9863 e_util_dialog_show(_("Error"), _("%s can't be written to!"), sd->realpath);
9864 return;
9865 }
9866 sd->new_file.thread = ecore_thread_feedback_run(_e_fm2_new_file_thread, (Ecore_Thread_Notify_Cb)_e_fm2_new_file_notify,
9867 _e_fm2_new_file_end, _e_fm2_new_file_cancel, sd, EINA_FALSE);
9868 ecore_thread_global_data_add("path", (void *)eina_stringshare_ref(sd->realpath), (void *)eina_stringshare_del, EINA_FALSE);
9869 evas_object_ref(sd->obj);
9870 }
9871
9872 static void
_e_fm2_new_directory(void * data,E_Menu * m EINA_UNUSED,E_Menu_Item * mi EINA_UNUSED)9873 _e_fm2_new_directory(void *data, E_Menu *m EINA_UNUSED, E_Menu_Item *mi EINA_UNUSED)
9874 {
9875 E_Fm2_Smart_Data *sd = data;
9876
9877 if (sd->new_file.thread || sd->new_file.filename)
9878 {
9879 e_util_dialog_internal(_("Error"), _("Already creating a new file for this directory!"));
9880 return;
9881 }
9882 if (!ecore_file_can_write(sd->realpath))
9883 {
9884 e_util_dialog_show(_("Error"), _("%s can't be written to!"), sd->realpath);
9885 return;
9886 }
9887 sd->new_file.thread = ecore_thread_feedback_run(_e_fm2_new_dir_thread, (Ecore_Thread_Notify_Cb)_e_fm2_new_dir_notify,
9888 _e_fm2_new_file_end, _e_fm2_new_file_cancel, sd, EINA_FALSE);
9889 ecore_thread_global_data_add("path", (void *)eina_stringshare_ref(sd->realpath), (void *)eina_stringshare_del, EINA_FALSE);
9890 evas_object_ref(sd->obj);
9891 }
9892
9893 static void
_e_fm2_add_menu_pre(void * data,E_Menu * subm)9894 _e_fm2_add_menu_pre(void *data, E_Menu *subm)
9895 {
9896 E_Menu_Item *mi;
9897 E_Fm2_Smart_Data *sd;
9898
9899 sd = data;
9900 if (subm->items) return;
9901
9902 mi = e_menu_item_new(subm);
9903 e_menu_item_label_set(mi, _("Directory"));
9904 e_util_menu_item_theme_icon_set(mi, "folder-new");
9905 e_menu_item_callback_set(mi, _e_fm2_new_directory, sd);
9906
9907 mi = e_menu_item_new(subm);
9908 e_menu_item_label_set(mi, _("File"));
9909 e_util_menu_item_theme_icon_set(mi, "document-new");
9910 e_menu_item_callback_set(mi, _e_fm2_new_file, sd);
9911 }
9912
9913 static void
_e_fm2_settings_icon_item(void * data EINA_UNUSED,E_Menu * m EINA_UNUSED,E_Menu_Item * mi EINA_UNUSED)9914 _e_fm2_settings_icon_item(void *data EINA_UNUSED, E_Menu *m EINA_UNUSED, E_Menu_Item *mi EINA_UNUSED)
9915 {
9916 e_configure_registry_call("fileman/file_icons", NULL, NULL);
9917 }
9918
9919 static void
_e_fm2_settings_item(void * data EINA_UNUSED,E_Menu * m EINA_UNUSED,E_Menu_Item * mi EINA_UNUSED)9920 _e_fm2_settings_item(void *data EINA_UNUSED, E_Menu *m EINA_UNUSED, E_Menu_Item *mi EINA_UNUSED)
9921 {
9922 e_configure_registry_call("fileman/fileman", NULL, NULL);
9923 }
9924
9925 static void
_e_fm2_options_menu_pre(void * data,E_Menu * subm)9926 _e_fm2_options_menu_pre(void *data, E_Menu *subm)
9927 {
9928 E_Fm2_Smart_Data *sd;
9929 E_Menu_Item *mi;
9930
9931 sd = data;
9932
9933 if (subm->items) return;
9934
9935 if ((!(sd->icon_menu.flags & E_FM2_MENU_NO_INHERIT_PARENT)) &&
9936 (sd->view_flags & E_FM2_VIEW_INHERIT_DIR_CUSTOM))
9937 {
9938 mi = e_menu_item_new(subm);
9939 e_menu_item_label_set(mi, _("Inherit parent settings"));
9940 e_util_menu_item_theme_icon_set(mi, "view-inherit");
9941 e_menu_item_check_set(mi, 1);
9942 e_menu_item_toggle_set(mi, sd->inherited_dir_props);
9943 e_menu_item_callback_set(mi, _e_fm2_toggle_inherit_dir_props, sd);
9944 }
9945 if (!(sd->icon_menu.flags & E_FM2_MENU_NO_SHOW_HIDDEN))
9946 {
9947 mi = e_menu_item_new(subm);
9948 e_menu_item_label_set(mi, _("Show Hidden Files"));
9949 e_util_menu_item_theme_icon_set(mi, "view-refresh");
9950 e_menu_item_check_set(mi, 1);
9951 e_menu_item_toggle_set(mi, sd->show_hidden_files);
9952 e_menu_item_callback_set(mi, _e_fm2_toggle_hidden_files, sd);
9953 }
9954
9955 if (!(sd->icon_menu.flags & E_FM2_MENU_NO_REMEMBER_ORDERING))
9956 {
9957 if (!sd->config->view.always_order)
9958 {
9959 mi = e_menu_item_new(subm);
9960 e_menu_item_label_set(mi, _("Remember Ordering"));
9961 e_util_menu_item_theme_icon_set(mi, "view-order");
9962 e_menu_item_check_set(mi, 1);
9963 e_menu_item_toggle_set(mi, sd->order_file);
9964 e_menu_item_callback_set(mi, _e_fm2_toggle_ordering, sd);
9965 }
9966 if ((sd->order_file) || (sd->config->view.always_order))
9967 {
9968 mi = e_menu_item_new(subm);
9969 e_menu_item_label_set(mi, _("Sort Now"));
9970 e_util_menu_item_theme_icon_set(mi, "view-sort");
9971 e_menu_item_callback_set(mi, _e_fm2_sort, sd);
9972 }
9973 }
9974 if (!(sd->icon_menu.flags & E_FM2_MENU_NO_ACTIVATE_CHANGE))
9975 {
9976 mi = e_menu_item_new(subm);
9977 e_menu_item_label_set(mi, _("Single Click Activation"));
9978 e_util_menu_item_theme_icon_set(mi, "access");
9979 e_menu_item_check_set(mi, 1);
9980 e_menu_item_toggle_set(mi, sd->config->view.single_click);
9981 e_menu_item_callback_set(mi, _e_fm2_toggle_single_click, sd);
9982 }
9983
9984 if (!e_config->filemanager_secure_rm)
9985 {
9986 /* can't disable this if it's globally enabled */
9987 mi = e_menu_item_new(subm);
9988 e_menu_item_label_set(mi, _("Secure Deletion"));
9989 e_util_menu_item_theme_icon_set(mi, "security-high");
9990 e_menu_item_check_set(mi, 1);
9991 e_menu_item_toggle_set(mi, e_config->filemanager_secure_rm | sd->config->secure_rm);
9992 e_menu_item_callback_set(mi, _e_fm2_toggle_secure_rm, sd);
9993 }
9994
9995 if (!e_configure_registry_exists("fileman/fileman")) return;
9996
9997 mi = e_menu_item_new(subm);
9998 e_menu_item_separator_set(mi, 1);
9999
10000 mi = e_menu_item_new(subm);
10001 e_menu_item_label_set(mi, _("File Manager Settings"));
10002 e_util_menu_item_theme_icon_set(mi, "system-file-manager");
10003 e_menu_item_callback_set(mi, _e_fm2_settings_item, sd);
10004
10005 mi = e_menu_item_new(subm);
10006 e_menu_item_label_set(mi, _("File Icon Settings"));
10007 e_util_menu_item_theme_icon_set(mi, "preferences-file-icons");
10008 e_menu_item_callback_set(mi, _e_fm2_settings_icon_item, sd);
10009 }
10010
10011 static void
_custom_file_key_del(E_Fm2_Smart_Data * sd,const char * key)10012 _custom_file_key_del(E_Fm2_Smart_Data *sd, const char *key)
10013 {
10014 Efreet_Desktop *ef;
10015 char buf[PATH_MAX];
10016
10017 if (sd->desktop) ef = sd->desktop;
10018 else
10019 {
10020 snprintf(buf, sizeof(buf), "%s/.directory.desktop", sd->realpath);
10021 ef = efreet_desktop_new(buf);
10022 }
10023 if (!ef) return;
10024
10025 if (efreet_desktop_x_field_del(ef, key))
10026 efreet_desktop_save(ef);
10027
10028 if (!sd->desktop) efreet_desktop_free(ef);
10029 }
10030
10031 static void
_e_fm2_view_menu_del(void * data)10032 _e_fm2_view_menu_del(void *data)
10033 {
10034 E_Fm2_Smart_Data *sd = e_object_data_get(data);
10035
10036 if (!sd) return;
10037 if (sd->image_dialog) return;
10038 if (!sd->desktop) return;
10039 efreet_desktop_free(sd->desktop);
10040 sd->desktop = NULL;
10041 }
10042
10043 static void
_clear_background_cb(void * data,E_Menu * m EINA_UNUSED,E_Menu_Item * mi EINA_UNUSED)10044 _clear_background_cb(void *data, E_Menu *m EINA_UNUSED, E_Menu_Item *mi EINA_UNUSED)
10045 {
10046 E_Fm2_Smart_Data *sd;
10047
10048 sd = data;
10049 if (!sd) return;
10050
10051 _custom_file_key_del(sd, "X-Enlightenment-Directory-Wallpaper");
10052 evas_object_smart_callback_call(sd->obj, "dir_changed", NULL);
10053 }
10054
10055 static void
_clear_overlay_cb(void * data,E_Menu * m EINA_UNUSED,E_Menu_Item * mi EINA_UNUSED)10056 _clear_overlay_cb(void *data, E_Menu *m EINA_UNUSED, E_Menu_Item *mi EINA_UNUSED)
10057 {
10058 E_Fm2_Smart_Data *sd = data;
10059
10060 if (!sd) return;
10061
10062 _custom_file_key_del(sd, "X-Enlightenment-Directory-Overlay");
10063 evas_object_smart_callback_call(sd->obj, "dir_changed", NULL);
10064 }
10065
10066 static void
_e_fm2_view_menu_pre(void * data,E_Menu * subm)10067 _e_fm2_view_menu_pre(void *data, E_Menu *subm)
10068 {
10069 E_Fm2_Smart_Data *sd = data;
10070 E_Menu_Item *mi;
10071
10072 if (subm->items) return;
10073
10074 _e_fm2_view_menu_common(subm, sd);
10075
10076 if (_e_fm2_desktop_open(sd) < 0) return;
10077 e_object_data_set(E_OBJECT(subm), sd);
10078 e_object_del_attach_func_set(E_OBJECT(subm), _e_fm2_view_menu_del);
10079
10080 if (e_menu_item_nth(subm, 0) != NULL)
10081 {
10082 mi = e_menu_item_new(subm);
10083 e_menu_item_separator_set(mi, 1);
10084 }
10085
10086 mi = e_menu_item_new(subm);
10087 e_menu_item_label_set(mi, _("Set background..."));
10088 e_util_menu_item_theme_icon_set(mi, "preferences-desktop-wallpaper");
10089 e_menu_item_callback_set(mi, _e_fm2_view_menu_set_background_cb, sd);
10090
10091 while (sd->desktop)
10092 {
10093 if (!eina_hash_find(sd->desktop->x, "X-Enlightenment-Directory-Wallpaper")) break;
10094 mi = e_menu_item_new(subm);
10095 e_menu_item_label_set(mi, _("Clear background"));
10096 e_util_menu_item_theme_icon_set(mi, "preferences-desktop-wallpaper");
10097 e_menu_item_callback_set(mi, _clear_background_cb, sd);
10098 break;
10099 }
10100
10101 mi = e_menu_item_new(subm);
10102 e_menu_item_label_set(mi, _("Set overlay..."));
10103 e_menu_item_callback_set(mi, _e_fm2_view_menu_set_overlay_cb, sd);
10104
10105 if (!sd->desktop) return;
10106 if (!eina_hash_find(sd->desktop->x, "X-Enlightenment-Directory-Overlay")) return;
10107 mi = e_menu_item_new(subm);
10108 e_menu_item_label_set(mi, _("Clear overlay"));
10109 e_menu_item_callback_set(mi, _clear_overlay_cb, sd);
10110 }
10111
10112 static void
_e_fm2_view_menu_grid_icons_cb(void * data,E_Menu * m,E_Menu_Item * mi)10113 _e_fm2_view_menu_grid_icons_cb(void *data, E_Menu *m, E_Menu_Item *mi)
10114 {
10115 E_Fm2_Smart_Data *sd = data;
10116 char old;
10117
10118 old = _e_fm2_view_mode_get(sd);
10119 sd->view_mode = E_FM2_VIEW_MODE_GRID_ICONS;
10120 sd->inherited_dir_props = EINA_FALSE;
10121 if (old == E_FM2_VIEW_MODE_GRID_ICONS)
10122 return;
10123
10124 _e_fm2_refresh(sd, m, mi);
10125 }
10126
10127 static void
_e_fm2_view_menu_custom_icons_cb(void * data,E_Menu * m,E_Menu_Item * mi)10128 _e_fm2_view_menu_custom_icons_cb(void *data, E_Menu *m, E_Menu_Item *mi)
10129 {
10130 E_Fm2_Smart_Data *sd = data;
10131 char old;
10132
10133 old = _e_fm2_view_mode_get(sd);
10134 sd->view_mode = E_FM2_VIEW_MODE_CUSTOM_ICONS;
10135 sd->inherited_dir_props = EINA_FALSE;
10136 if (old == E_FM2_VIEW_MODE_CUSTOM_ICONS)
10137 return;
10138
10139 _e_fm2_refresh(sd, m, mi);
10140 }
10141
10142 static void
_e_fm2_view_menu_list_cb(void * data,E_Menu * m,E_Menu_Item * mi)10143 _e_fm2_view_menu_list_cb(void *data, E_Menu *m, E_Menu_Item *mi)
10144 {
10145 E_Fm2_Smart_Data *sd = data;
10146 char old;
10147
10148 old = _e_fm2_view_mode_get(sd);
10149 sd->view_mode = E_FM2_VIEW_MODE_LIST;
10150 sd->inherited_dir_props = EINA_FALSE;
10151 if (old == E_FM2_VIEW_MODE_LIST)
10152 return;
10153
10154 _e_fm2_refresh(sd, m, mi);
10155 }
10156
10157 static void
_e_fm2_view_menu_use_default_cb(void * data,E_Menu * m,E_Menu_Item * mi)10158 _e_fm2_view_menu_use_default_cb(void *data, E_Menu *m, E_Menu_Item *mi)
10159 {
10160 E_Fm2_Smart_Data *sd = data;
10161 char old, new;
10162
10163 old = _e_fm2_view_mode_get(sd);
10164
10165 if (sd->view_mode == -1)
10166 sd->view_mode = sd->config->view.mode;
10167 else
10168 sd->view_mode = -1;
10169
10170 new = _e_fm2_view_mode_get(sd);
10171 sd->inherited_dir_props = EINA_FALSE;
10172
10173 if (new == old)
10174 return;
10175
10176 _e_fm2_refresh(sd, m, mi);
10177 }
10178
10179 static void
_image_sel_del(void * data)10180 _image_sel_del(void *data)
10181 {
10182 E_Fm2_Smart_Data *sd;
10183
10184 sd = e_object_data_get(data);
10185 if (!sd) return;
10186 sd->image_dialog = NULL;
10187 if (sd->desktop) efreet_desktop_free(sd->desktop);
10188 sd->desktop = NULL;
10189 }
10190
10191 static void
_e_fm2_view_image_sel(E_Fm2_Smart_Data * sd,const char * title,void (* ok_cb)(void * data,E_Dialog * dia))10192 _e_fm2_view_image_sel(E_Fm2_Smart_Data *sd, const char *title,
10193 void (*ok_cb)(void *data, E_Dialog *dia))
10194 {
10195 E_Dialog *dia;
10196 Evas_Object *o;
10197 Evas_Coord w, h;
10198
10199 dia = e_dialog_new(NULL, "E", "_fm2_view_image_select_dialog");
10200 if (!dia) return;
10201 e_dialog_resizable_set(dia, 1);
10202 e_dialog_title_set(dia, title);
10203
10204 o = e_widget_fsel_add(evas_object_evas_get(dia->win), "/", sd->realpath, NULL, NULL, NULL, sd, NULL, sd, 1);
10205 evas_object_show(o);
10206 e_widget_size_min_get(o, &w, &h);
10207 e_dialog_content_set(dia, o, w, h);
10208 dia->data = o;
10209
10210 e_dialog_button_add(dia, _("OK"), NULL, ok_cb, sd);
10211 e_dialog_button_add(dia, _("Cancel"), NULL, _e_fm2_view_image_sel_close, sd);
10212 elm_win_center(dia->win, 1, 1);
10213 e_object_data_set(E_OBJECT(dia), sd);
10214 e_object_del_attach_func_set(E_OBJECT(dia), _image_sel_del);
10215 e_dialog_show(dia);
10216
10217 sd->image_dialog = dia;
10218 }
10219
10220 static void
_e_fm2_view_image_sel_close(void * data,E_Dialog * dia)10221 _e_fm2_view_image_sel_close(void *data, E_Dialog *dia)
10222 {
10223 E_Fm2_Smart_Data *sd;
10224
10225 sd = data;
10226 e_object_del(E_OBJECT(dia));
10227 sd->image_dialog = NULL;
10228 }
10229
10230 static int
_e_fm2_desktop_open(E_Fm2_Smart_Data * sd)10231 _e_fm2_desktop_open(E_Fm2_Smart_Data *sd)
10232 {
10233 Efreet_Desktop *ef;
10234 char buf[PATH_MAX];
10235 Eina_Bool ret;
10236
10237 snprintf(buf, sizeof(buf), "%s/.directory.desktop", sd->realpath);
10238 if (sd->desktop)
10239 {
10240 if (!e_util_strcmp(buf, sd->desktop->orig_path)) return 1;
10241 }
10242 ret = ecore_file_exists(buf) ? ecore_file_can_write(buf)
10243 : ecore_file_can_write(sd->realpath);
10244 if (!ret) return -1;
10245 ef = efreet_desktop_new(buf);
10246 if (!ef) return 0;
10247 efreet_desktop_free(sd->desktop);
10248 sd->desktop = ef;
10249 return 1;
10250 }
10251
10252 static void
_custom_file_key_set(E_Fm2_Smart_Data * sd,const char * key,const char * value)10253 _custom_file_key_set(E_Fm2_Smart_Data *sd, const char *key, const char *value)
10254 {
10255 Efreet_Desktop *ef;
10256 char buf[PATH_MAX];
10257 int len;
10258
10259 if (sd->desktop) ef = sd->desktop;
10260 else
10261 {
10262 snprintf(buf, sizeof(buf), "%s/.directory.desktop", sd->realpath);
10263 ef = efreet_desktop_new(buf);
10264 if (!ef)
10265 {
10266 ef = efreet_desktop_empty_new(buf);
10267 if (!ef) return;
10268 ef->type = EFREET_DESKTOP_TYPE_DIRECTORY;
10269 ef->name = strdup("Directory look and feel");
10270 }
10271 }
10272
10273 len = strlen(sd->realpath);
10274 if (!strncmp(value, sd->realpath, len))
10275 efreet_desktop_x_field_set(ef, key, value + len + 1);
10276 else
10277 efreet_desktop_x_field_set(ef, key, value);
10278
10279 efreet_desktop_save(ef);
10280 if (!sd->desktop) efreet_desktop_free(ef);
10281 }
10282
10283 static void
_set_background_cb(void * data,E_Dialog * dia)10284 _set_background_cb(void *data, E_Dialog *dia)
10285 {
10286 E_Fm2_Smart_Data *sd;
10287 const char *file;
10288
10289 sd = data;
10290 if (!sd) return;
10291
10292 file = e_widget_fsel_selection_path_get(dia->data);
10293
10294 if (file)
10295 _custom_file_key_set(sd, "X-Enlightenment-Directory-Wallpaper", file);
10296
10297 _e_fm2_view_image_sel_close(data, dia);
10298 evas_object_smart_callback_call(sd->obj, "dir_changed", NULL);
10299 }
10300
10301 static void
_e_fm2_view_menu_set_background_cb(void * data,E_Menu * m EINA_UNUSED,E_Menu_Item * mi EINA_UNUSED)10302 _e_fm2_view_menu_set_background_cb(void *data, E_Menu *m EINA_UNUSED, E_Menu_Item *mi EINA_UNUSED)
10303 {
10304 E_Fm2_Smart_Data *sd = data;
10305
10306 if (sd->image_dialog) return;
10307
10308 _e_fm2_view_image_sel(sd, _("Set background..."), _set_background_cb);
10309 }
10310
10311 static void
_set_overlay_cb(void * data,E_Dialog * dia)10312 _set_overlay_cb(void *data, E_Dialog *dia)
10313 {
10314 E_Fm2_Smart_Data *sd;
10315 const char *file;
10316
10317 sd = data;
10318 if (!sd) return;
10319
10320 file = e_widget_fsel_selection_path_get(dia->data);
10321
10322 if (file)
10323 _custom_file_key_set(sd, "X-Enlightenment-Directory-Overlay", file);
10324
10325 _e_fm2_view_image_sel_close(data, dia);
10326 evas_object_smart_callback_call(sd->obj, "dir_changed", NULL);
10327 }
10328
10329 static void
_e_fm2_view_menu_set_overlay_cb(void * data,E_Menu * m EINA_UNUSED,E_Menu_Item * mi EINA_UNUSED)10330 _e_fm2_view_menu_set_overlay_cb(void *data, E_Menu *m EINA_UNUSED, E_Menu_Item *mi EINA_UNUSED)
10331 {
10332 E_Fm2_Smart_Data *sd = data;
10333
10334 if (sd->image_dialog) return;
10335
10336 _e_fm2_view_image_sel(sd, _("Set overlay..."), _set_overlay_cb);
10337 }
10338
10339 static void
_e_fm2_refresh(void * data,E_Menu * m EINA_UNUSED,E_Menu_Item * mi EINA_UNUSED)10340 _e_fm2_refresh(void *data, E_Menu *m EINA_UNUSED, E_Menu_Item *mi EINA_UNUSED)
10341 {
10342 E_Fm2_Smart_Data *sd;
10343
10344 sd = data;
10345 if (sd->refresh_job) ecore_job_del(sd->refresh_job);
10346 sd->refresh_job = ecore_job_add(_e_fm2_refresh_job_cb, sd->obj);
10347 }
10348
10349 static void
_e_fm2_toggle_hidden_files(void * data,E_Menu * m,E_Menu_Item * mi)10350 _e_fm2_toggle_hidden_files(void *data, E_Menu *m, E_Menu_Item *mi)
10351 {
10352 E_Fm2_Smart_Data *sd;
10353
10354 sd = data;
10355 if (sd->show_hidden_files)
10356 sd->show_hidden_files = EINA_FALSE;
10357 else
10358 sd->show_hidden_files = EINA_TRUE;
10359
10360 sd->inherited_dir_props = EINA_FALSE;
10361 _e_fm2_refresh(data, m, mi);
10362 }
10363
10364 static void
_e_fm2_toggle_secure_rm(void * data,E_Menu * m EINA_UNUSED,E_Menu_Item * mi EINA_UNUSED)10365 _e_fm2_toggle_secure_rm(void *data, E_Menu *m EINA_UNUSED, E_Menu_Item *mi EINA_UNUSED)
10366 {
10367 E_Fm2_Smart_Data *sd = data;
10368
10369 sd->config->secure_rm = !sd->config->secure_rm;
10370 }
10371
10372 static void
_e_fm2_toggle_single_click(void * data,E_Menu * m EINA_UNUSED,E_Menu_Item * mi EINA_UNUSED)10373 _e_fm2_toggle_single_click(void *data, E_Menu *m EINA_UNUSED, E_Menu_Item *mi EINA_UNUSED)
10374 {
10375 E_Fm2_Smart_Data *sd;
10376
10377 sd = data;
10378 sd->config->view.single_click = !sd->config->view.single_click;
10379 }
10380
10381 static void
_e_fm2_toggle_ordering(void * data,E_Menu * m,E_Menu_Item * mi)10382 _e_fm2_toggle_ordering(void *data, E_Menu *m, E_Menu_Item *mi)
10383 {
10384 E_Fm2_Smart_Data *sd;
10385 char buf[4096];
10386
10387 sd = data;
10388 if (sd->order_file)
10389 {
10390 snprintf(buf, sizeof(buf), "%s/.order", sd->realpath);
10391 /* FIXME: move to e_fm_main */
10392 ecore_file_unlink(buf);
10393 }
10394 else
10395 {
10396 FILE *f;
10397
10398 snprintf(buf, sizeof(buf), "%s/.order", sd->realpath);
10399 f = fopen(buf, "w");
10400 if (f) fclose(f);
10401 }
10402 sd->inherited_dir_props = EINA_FALSE;
10403 _e_fm2_refresh(data, m, mi);
10404 }
10405
10406 static void
_e_fm2_sort(void * data,E_Menu * m,E_Menu_Item * mi)10407 _e_fm2_sort(void *data, E_Menu *m, E_Menu_Item *mi)
10408 {
10409 E_Fm2_Smart_Data *sd;
10410
10411 sd = data;
10412 sd->icons = eina_list_sort(sd->icons, eina_list_count(sd->icons),
10413 _e_fm2_cb_icon_sort);
10414 _e_fm2_refresh(data, m, mi);
10415 }
10416
10417 static void
_e_fm2_file_rename(void * data,E_Menu * m EINA_UNUSED,E_Menu_Item * mi EINA_UNUSED)10418 _e_fm2_file_rename(void *data, E_Menu *m EINA_UNUSED, E_Menu_Item *mi EINA_UNUSED)
10419 {
10420 E_Fm2_Icon *ic;
10421 char text[PATH_MAX + 256];
10422
10423 ic = data;
10424 if ((ic->entry_dialog) || (ic->entry_widget)) return;
10425 if (ic->sd->icon_menu.flags & E_FM2_MENU_NO_RENAME) return;
10426
10427 if (!_e_fm2_icon_entry_widget_add(ic))
10428 {
10429 snprintf(text, PATH_MAX + 256,
10430 _("Rename %s to:"),
10431 ic->info.file);
10432 ic->entry_dialog = e_entry_dialog_show(_("Rename File"), "edit-rename",
10433 text, ic->info.file, NULL, NULL,
10434 _e_fm2_file_rename_yes_cb,
10435 _e_fm2_file_rename_no_cb, ic);
10436 E_OBJECT(ic->entry_dialog)->data = ic;
10437 e_object_del_attach_func_set(E_OBJECT(ic->entry_dialog),
10438 _e_fm2_file_rename_delete_cb);
10439 }
10440 }
10441
10442 /* FIXME: this is a stupid hack because it's impossible to get a focus event
10443 * from e_widget_entry.
10444 */
10445 static void
_e_fm2_icon_entry_widget_focus_out(void * data,E_Client * ec)10446 _e_fm2_icon_entry_widget_focus_out(void *data, E_Client *ec)
10447 {
10448 E_Fm2_Icon *ic = data;
10449 Evas_Object *win;
10450
10451 win = e_win_evas_win_get(evas_object_evas_get(ic->obj));
10452 if ((win != e_comp->elm) && (ec == e_win_client_get(win))) return;
10453 if (ic->entry_widget)
10454 _e_fm2_icon_entry_widget_del(ic);
10455 }
10456
10457 static Evas_Object *
_e_fm2_icon_entry_widget_add(E_Fm2_Icon * ic)10458 _e_fm2_icon_entry_widget_add(E_Fm2_Icon *ic)
10459 {
10460 Evas *e;
10461
10462 if (ic->sd->iop_icon)
10463 _e_fm2_icon_entry_widget_accept(ic->sd->iop_icon);
10464
10465 if (!edje_object_part_exists(ic->obj, "e.swallow.entry"))
10466 return NULL;
10467
10468 e = evas_object_evas_get(ic->obj);
10469 ic->entry_widget = e_widget_entry_add(e_win_evas_win_get(e), NULL, NULL, NULL, NULL);
10470 evas_object_event_callback_add(ic->entry_widget, EVAS_CALLBACK_KEY_DOWN,
10471 _e_fm2_icon_entry_widget_cb_key_down, ic);
10472 if (e_comp->comp_type == E_PIXMAP_TYPE_X)
10473 evas_event_feed_mouse_out(evas_object_evas_get(ic->obj), 0, NULL);
10474 if (e_comp->evas == e)
10475 e_comp_grab_input(0, 1);
10476 ic->keygrab = (e_comp->evas == e);
10477 edje_object_part_swallow(ic->obj, "e.swallow.entry", ic->entry_widget);
10478 evas_object_show(ic->entry_widget);
10479 edje_object_signal_emit(ic->obj, "e,state,rename,on", "e");
10480 e_widget_entry_text_set(ic->entry_widget, ic->info.file);
10481 e_widget_focus_set(ic->entry_widget, 1);
10482 ic->focus_hook = e_client_hook_add(E_CLIENT_HOOK_FOCUS_SET, _e_fm2_icon_entry_widget_focus_out, ic);
10483 e_widget_entry_select_all(ic->entry_widget);
10484 ic->sd->iop_icon = ic;
10485 ic->sd->typebuf.disabled = EINA_TRUE;
10486 if (e_comp->comp_type == E_PIXMAP_TYPE_X)
10487 evas_event_feed_mouse_in(e, 0, NULL);
10488 return ic->entry_widget;
10489 }
10490
10491 static void
_e_fm2_icon_entry_widget_del(E_Fm2_Icon * ic)10492 _e_fm2_icon_entry_widget_del(E_Fm2_Icon *ic)
10493 {
10494 ic->sd->iop_icon = NULL;
10495 evas_object_focus_set(ic->sd->obj, 1);
10496 evas_object_del(ic->entry_widget);
10497 ic->entry_widget = NULL;
10498 E_FREE_FUNC(ic->focus_hook, e_client_hook_del);
10499 ic->sd->typebuf.disabled = EINA_FALSE;
10500 if (ic->keygrab)
10501 {
10502 if (evas_object_evas_get(ic->obj) == e_comp->evas)
10503 e_comp_ungrab_input(0, 1);
10504 }
10505 ic->keygrab = 0;
10506 _e_fm2_icon_select(ic);
10507 edje_object_signal_emit(ic->obj, "e,state,rename,off", "e");
10508 }
10509
10510 static void
_e_fm2_icon_entry_widget_cb_key_down(void * data,Evas * e EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_info)10511 _e_fm2_icon_entry_widget_cb_key_down(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info)
10512 {
10513 Evas_Event_Key_Down *ev;
10514 E_Fm2_Icon *ic;
10515
10516 ev = event_info;
10517 ic = data;
10518
10519 if (!strcmp(ev->key, "Escape"))
10520 _e_fm2_icon_entry_widget_del(ic);
10521 else if ((!strcmp(ev->key, "Return")) || (!strcmp(ev->key, "KP_Enter")))
10522 _e_fm2_icon_entry_widget_accept(ic);
10523 }
10524
10525 static void
_e_fm2_icon_entry_widget_accept(E_Fm2_Icon * ic)10526 _e_fm2_icon_entry_widget_accept(E_Fm2_Icon *ic)
10527 {
10528 const char *txt;
10529
10530 txt = e_widget_entry_text_get(ic->entry_widget);
10531 switch (_e_fm2_file_do_rename(txt, ic))
10532 {
10533 case -2:
10534 e_util_dialog_show(_("Error"), _("%s already exists!"), txt);
10535 return;
10536
10537 case -1:
10538 e_util_dialog_show(_("Error"), _("%s could not be renamed because it is protected"), ic->info.file);
10539 break;
10540
10541 case 0:
10542 e_util_dialog_show(_("Error"), _("Internal filemanager error :("));
10543
10544 default: /* success! */
10545 break;
10546 }
10547 _e_fm2_icon_entry_widget_del(ic);
10548 }
10549
10550 static void
_e_fm2_file_rename_delete_cb(void * obj)10551 _e_fm2_file_rename_delete_cb(void *obj)
10552 {
10553 E_Fm2_Icon *ic;
10554
10555 ic = E_OBJECT(obj)->data;
10556 ic->entry_dialog = NULL;
10557 }
10558
10559 static void
_e_fm2_file_rename_yes_cb(void * data,char * text)10560 _e_fm2_file_rename_yes_cb(void *data, char *text)
10561 {
10562 E_Fm2_Icon *ic;
10563
10564 ic = data;
10565 ic->entry_dialog = NULL;
10566
10567 switch (_e_fm2_file_do_rename(text, ic))
10568 {
10569 case -2:
10570 e_util_dialog_show(_("Error"), _("%s already exists!"), text);
10571 _e_fm2_file_rename(ic, NULL, NULL);
10572 break;
10573
10574 case -1:
10575 e_util_dialog_show(_("Error"), _("%s could not be renamed because it is protected"), ic->info.file);
10576 break;
10577
10578 case 0:
10579 e_util_dialog_show(_("Error"), _("Internal filemanager error :("));
10580
10581 default: /* success! */
10582 break;
10583 }
10584 }
10585
10586 static void
_e_fm2_file_rename_no_cb(void * data)10587 _e_fm2_file_rename_no_cb(void *data)
10588 {
10589 E_Fm2_Icon *ic;
10590
10591 ic = data;
10592 ic->entry_dialog = NULL;
10593 }
10594
10595 static int
_e_fm2_file_do_rename(const char * text,E_Fm2_Icon * ic)10596 _e_fm2_file_do_rename(const char *text, E_Fm2_Icon *ic)
10597 {
10598 char oldpath[PATH_MAX];
10599 char newpath[PATH_MAX];
10600 char *args = NULL;
10601 size_t size = 0;
10602 size_t length = 0;
10603
10604 if (!text) return 0;
10605 if (!strcmp(text, ic->info.file)) return EINA_TRUE;
10606 _e_fm2_icon_realpath(ic, oldpath, sizeof(oldpath));
10607 snprintf(newpath, sizeof(newpath), "%s/%s", ic->sd->realpath, text);
10608 if (e_filereg_file_protected(oldpath)) return -1;
10609 if (ecore_file_exists(newpath)) return -2;
10610
10611 args = e_util_string_append_quoted(args, &size, &length, oldpath);
10612 if (!args) return 0;
10613 args = e_util_string_append_char(args, &size, &length, ' ');
10614 if (!args) return 0;
10615 args = e_util_string_append_quoted(args, &size, &length, newpath);
10616 if (!args) return 0;
10617
10618 e_fm2_client_file_move(ic->sd->obj, args);
10619 free(args);
10620 return 1;
10621 }
10622
10623 static E_Dialog *
_e_fm_retry_abort_dialog(int pid,const char * str)10624 _e_fm_retry_abort_dialog(int pid, const char *str)
10625 {
10626 E_Dialog *dialog;
10627 void *id;
10628 char text[4096 + PATH_MAX];
10629
10630 id = (intptr_t *)(long)pid;
10631
10632 dialog = e_dialog_new(NULL, "E", "_fm_overwrite_dialog");
10633 E_OBJECT(dialog)->data = id;
10634 e_dialog_button_add(dialog, _("Retry"), NULL, _e_fm_retry_abort_retry_cb, NULL);
10635 e_dialog_button_add(dialog, _("Abort"), NULL, _e_fm_retry_abort_abort_cb, NULL);
10636
10637 e_dialog_button_focus_num(dialog, 0);
10638 e_dialog_title_set(dialog, _("Error"));
10639 e_dialog_icon_set(dialog, "dialog-error", 64);
10640 snprintf(text, sizeof(text),
10641 "%s",
10642 str);
10643
10644 e_dialog_text_set(dialog, text);
10645 elm_win_center(dialog->win, 1, 1);
10646 e_dialog_show(dialog);
10647 return dialog;
10648 }
10649
10650 static void
_e_fm_retry_abort_retry_cb(void * data EINA_UNUSED,E_Dialog * dialog)10651 _e_fm_retry_abort_retry_cb(void *data EINA_UNUSED, E_Dialog *dialog)
10652 {
10653 int id = (int)(intptr_t)E_OBJECT(dialog)->data;
10654 _e_fm2_op_registry_go_on(id);
10655 _e_fm_client_send(E_FM_OP_ERROR_RESPONSE_RETRY, id, NULL, 0);
10656 e_object_del(E_OBJECT(dialog));
10657 }
10658
10659 static void
_e_fm_retry_abort_abort_cb(void * data EINA_UNUSED,E_Dialog * dialog)10660 _e_fm_retry_abort_abort_cb(void *data EINA_UNUSED, E_Dialog *dialog)
10661 {
10662 int id = (int)(intptr_t)E_OBJECT(dialog)->data;
10663 _e_fm2_op_registry_aborted(id);
10664 _e_fm_client_send(E_FM_OP_ERROR_RESPONSE_ABORT, id, NULL, 0);
10665 e_object_del(E_OBJECT(dialog));
10666 }
10667
10668 static E_Dialog *
_e_fm_overwrite_dialog(int pid,const char * str)10669 _e_fm_overwrite_dialog(int pid, const char *str)
10670 {
10671 E_Dialog *dialog;
10672 void *id;
10673 char text[4096 + PATH_MAX];
10674 E_Fm2_Op_Registry_Entry *ere;
10675
10676 id = (intptr_t *)(long)pid;
10677 ere = e_fm2_op_registry_entry_get(pid);
10678 if (ere)
10679 {
10680 E_Fm2_Smart_Data *sd;
10681 Eina_List *fms;
10682 Evas_Object *fm;
10683
10684 fms = _e_fm2_file_fm2_find(ere->src);
10685 EINA_LIST_FREE(fms, fm)
10686 {
10687 sd = evas_object_smart_data_get(fm);
10688 E_LIST_FOREACH(sd->icons, _e_fm2_cb_drag_finished_show);
10689 }
10690 }
10691
10692 dialog = e_dialog_new(NULL, "E", "_fm_overwrite_dialog");
10693 E_OBJECT(dialog)->data = id;
10694 e_dialog_button_add(dialog, _("No"), NULL, _e_fm_overwrite_no_cb, NULL);
10695 e_dialog_button_add(dialog, _("No to all"), NULL, _e_fm_overwrite_no_all_cb, NULL);
10696 e_dialog_button_add(dialog, _("Rename"), NULL, _e_fm_overwrite_rename, NULL);
10697 e_dialog_button_add(dialog, _("Yes"), NULL, _e_fm_overwrite_yes_cb, NULL);
10698 e_dialog_button_add(dialog, _("Yes to all"), NULL, _e_fm_overwrite_yes_all_cb, NULL);
10699
10700 e_dialog_button_focus_num(dialog, 0);
10701 e_dialog_title_set(dialog, _("Warning"));
10702 e_dialog_icon_set(dialog, "dialog-warning", 64);
10703 snprintf(text, sizeof(text),
10704 _("File already exists, overwrite?<ps/><hilight>%s</hilight>"), str);
10705
10706 e_dialog_text_set(dialog, text);
10707 elm_win_center(dialog->win, 1, 1);
10708 e_dialog_show(dialog);
10709 return dialog;
10710 }
10711
10712 static void
_e_fm_overwrite_no_cb(void * data EINA_UNUSED,E_Dialog * dialog)10713 _e_fm_overwrite_no_cb(void *data EINA_UNUSED, E_Dialog *dialog)
10714 {
10715 int id = (int)(intptr_t)E_OBJECT(dialog)->data;
10716 _e_fm2_op_registry_go_on(id);
10717 _e_fm_client_send(E_FM_OP_OVERWRITE_RESPONSE_NO, id, NULL, 0);
10718 e_object_del(E_OBJECT(dialog));
10719 }
10720
10721 static void
_e_fm_overwrite_no_all_cb(void * data EINA_UNUSED,E_Dialog * dialog)10722 _e_fm_overwrite_no_all_cb(void *data EINA_UNUSED, E_Dialog *dialog)
10723 {
10724 int id = (int)(intptr_t)E_OBJECT(dialog)->data;
10725 _e_fm2_op_registry_go_on(id);
10726 _e_fm_client_send(E_FM_OP_OVERWRITE_RESPONSE_NO_ALL, id, NULL, 0);
10727 e_object_del(E_OBJECT(dialog));
10728 }
10729
10730 static void
_e_fm_overwrite_rename_del(void * data)10731 _e_fm_overwrite_rename_del(void *data)
10732 {
10733 E_Fm2_Op_Registry_Entry *ere;
10734 E_Fm2_Smart_Data *sd;
10735
10736 ere = e_object_data_get(data);
10737 if (!ere) return;
10738 sd = evas_object_smart_data_get(ere->e_fm);
10739 if (!sd) return;
10740 sd->rename_dialogs = eina_list_remove(sd->rename_dialogs, data);
10741 e_fm2_op_registry_entry_unref(ere);
10742 _e_fm_client_send(E_FM_OP_OVERWRITE_RESPONSE_NO, ere->id, NULL, 0);
10743 }
10744
10745 static void
_e_fm_overwrite_rename_yes_cb(void * data,char * text)10746 _e_fm_overwrite_rename_yes_cb(void *data, char *text)
10747 {
10748 E_Fm2_Op_Registry_Entry *ere = data;
10749 char newpath[PATH_MAX];
10750 char *args = NULL;
10751 const char *f;
10752 size_t size = 0;
10753 size_t length = 0;
10754
10755 if ((!text) || (!text[0])) return;
10756 if ((!ere->src) || (!ere->dst)) return;
10757 f = ecore_file_file_get(ere->dst);
10758 if (!f) return;
10759 length = strlen(text);
10760 if (f - ere->dst + length >= PATH_MAX) return;
10761
10762 newpath[0] = 0;
10763 strncat(newpath, ere->dst, f - ere->dst);
10764 strcat(newpath, text);
10765 if (e_filereg_file_protected(newpath)) return;
10766 length = 0;
10767 args = e_util_string_append_quoted(args, &size, &length, ere->src);
10768 if (!args) return;
10769 args = e_util_string_append_char(args, &size, &length, ' ');
10770 if (!args) return;
10771 args = e_util_string_append_quoted(args, &size, &length, newpath);
10772 if (!args) return;
10773
10774 e_fm2_client_file_copy(ere->e_fm, args);
10775 free(args);
10776 }
10777
10778 static void
_e_fm_overwrite_rename(void * data EINA_UNUSED,E_Dialog * dialog)10779 _e_fm_overwrite_rename(void *data EINA_UNUSED, E_Dialog *dialog)
10780 {
10781 char text[PATH_MAX + 256];
10782 int id = (int)(intptr_t)E_OBJECT(dialog)->data;
10783 E_Fm2_Op_Registry_Entry *ere;
10784 E_Entry_Dialog *ed;
10785 E_Fm2_Smart_Data *sd;
10786 const char *file;
10787
10788 ere = e_fm2_op_registry_entry_get(id);
10789 if (!ere) return;
10790 sd = evas_object_smart_data_get(ere->e_fm);
10791 e_object_del(E_OBJECT(dialog));
10792 file = ecore_file_file_get(ere->src);
10793 snprintf(text, sizeof(text), _("Rename %s to:"), file);
10794 ed = e_entry_dialog_show(_("Rename File"), "edit-rename",
10795 text, file, NULL, NULL,
10796 _e_fm_overwrite_rename_yes_cb,
10797 NULL, ere);
10798 sd->rename_dialogs = eina_list_append(sd->rename_dialogs, ed);
10799 e_object_del_attach_func_set(E_OBJECT(ed), _e_fm_overwrite_rename_del);
10800 E_OBJECT(ed)->data = ere;
10801 e_fm2_op_registry_entry_ref(ere);
10802 _e_fm2_op_registry_go_on(id);
10803 }
10804
10805 static void
_e_fm_overwrite_yes_cb(void * data EINA_UNUSED,E_Dialog * dialog)10806 _e_fm_overwrite_yes_cb(void *data EINA_UNUSED, E_Dialog *dialog)
10807 {
10808 int id = (int)(intptr_t)E_OBJECT(dialog)->data;
10809 _e_fm2_op_registry_go_on(id);
10810 _e_fm_client_send(E_FM_OP_OVERWRITE_RESPONSE_YES, id, NULL, 0);
10811 e_object_del(E_OBJECT(dialog));
10812 }
10813
10814 static void
_e_fm_overwrite_yes_all_cb(void * data EINA_UNUSED,E_Dialog * dialog)10815 _e_fm_overwrite_yes_all_cb(void *data EINA_UNUSED, E_Dialog *dialog)
10816 {
10817 int id = (int)(intptr_t)E_OBJECT(dialog)->data;
10818 _e_fm2_op_registry_go_on(id);
10819 _e_fm_client_send(E_FM_OP_OVERWRITE_RESPONSE_YES_ALL, id, NULL, 0);
10820 e_object_del(E_OBJECT(dialog));
10821 }
10822
10823 static E_Dialog *
_e_fm_error_dialog(int pid,const char * str)10824 _e_fm_error_dialog(int pid, const char *str)
10825 {
10826 E_Dialog *dialog;
10827 void *id;
10828 char text[4096 + PATH_MAX];
10829 E_Fm2_Op_Registry_Entry *ere;
10830 E_Fm2_Smart_Data *sd;
10831 E_Fm2_Mount *m;
10832 Eina_Bool devlink = EINA_FALSE;
10833
10834 id = (intptr_t *)(long)pid;
10835 ere = e_fm2_op_registry_entry_get(pid);
10836 if (!ere) return NULL;
10837 sd = evas_object_smart_data_get(ere->e_fm);
10838 E_LIST_FOREACH(sd->icons, _e_fm2_cb_drag_finished_show);
10839 while (sd->realpath)
10840 {
10841 /* trying to make or move a link onto a device will fail, create button for
10842 * moving source at this point if this is what failed
10843 */
10844 struct stat st;
10845 if (sd->config->view.link_drop) break;
10846 m = e_fm2_device_mount_find(sd->realpath);
10847 if (!m) break;
10848 if (ere->op == E_FM_OP_SYMLINK)
10849 {
10850 devlink = EINA_TRUE;
10851 break;
10852 }
10853 if (stat(ere->src, &st)) break;
10854 if (S_ISLNK(st.st_mode)) devlink = EINA_TRUE;
10855 break;
10856 }
10857
10858 dialog = e_dialog_new(NULL, "E", "_fm_error_dialog");
10859 E_OBJECT(dialog)->data = id;
10860 e_dialog_button_add(dialog, _("Retry"), NULL, _e_fm_error_retry_cb, NULL);
10861 e_dialog_button_add(dialog, _("Abort"), NULL, _e_fm_error_abort_cb, NULL);
10862 if (devlink)
10863 e_dialog_button_add(dialog, _("Move Source"), NULL, _e_fm_error_link_source, ere);
10864 e_dialog_button_add(dialog, _("Ignore this"), NULL, _e_fm_error_ignore_this_cb, NULL);
10865 e_dialog_button_add(dialog, _("Ignore all"), NULL, _e_fm_error_ignore_all_cb, NULL);
10866
10867 e_dialog_button_focus_num(dialog, 0);
10868 e_dialog_title_set(dialog, _("Error"));
10869 snprintf(text, sizeof(text),
10870 _("An error occurred while performing an operation.<ps/>"
10871 "%s"),
10872 str);
10873
10874 e_dialog_text_set(dialog, text);
10875 elm_win_center(dialog->win, 1, 1);
10876 e_dialog_show(dialog);
10877 return dialog;
10878 }
10879
10880 static void
_e_fm_error_retry_cb(void * data EINA_UNUSED,E_Dialog * dialog)10881 _e_fm_error_retry_cb(void *data EINA_UNUSED, E_Dialog *dialog)
10882 {
10883 int id = (int)(intptr_t)E_OBJECT(dialog)->data;
10884 _e_fm2_op_registry_go_on(id);
10885 _e_fm_client_send(E_FM_OP_ERROR_RESPONSE_RETRY, id, NULL, 0);
10886 e_object_del(E_OBJECT(dialog));
10887 }
10888
10889 static void
_e_fm_error_abort_cb(void * data EINA_UNUSED,E_Dialog * dialog)10890 _e_fm_error_abort_cb(void *data EINA_UNUSED, E_Dialog *dialog)
10891 {
10892 int id = (int)(intptr_t)E_OBJECT(dialog)->data;
10893 _e_fm2_op_registry_aborted(id);
10894 _e_fm_client_send(E_FM_OP_ERROR_RESPONSE_ABORT, id, NULL, 0);
10895 e_object_del(E_OBJECT(dialog));
10896 }
10897
10898 static void
_e_fm_error_link_source(void * data,E_Dialog * dialog)10899 _e_fm_error_link_source(void *data, E_Dialog *dialog)
10900 {
10901 E_Fm2_Op_Registry_Entry *ere = data;
10902 int id = (int)(intptr_t)E_OBJECT(dialog)->data;
10903 char *file;
10904 char newpath[PATH_MAX];
10905 char *args = NULL;
10906 const char *f;
10907 size_t size = 0;
10908 size_t length = 0;
10909
10910 file = ecore_file_readlink(ere->src);
10911 if (!file) file = (char *)ere->src;
10912
10913 f = ecore_file_file_get(file);
10914 if (!f) return;
10915 length = strlen(f);
10916 if (strlen(ere->dst) + length >= PATH_MAX) return;
10917
10918 newpath[0] = 0;
10919 strncat(newpath, ere->dst, f - ere->dst);
10920 strcat(newpath, f);
10921 if (e_filereg_file_protected(newpath)) return;
10922 length = 0;
10923 args = e_util_string_append_quoted(args, &size, &length, file);
10924 if (!args) return;
10925 args = e_util_string_append_char(args, &size, &length, ' ');
10926 if (!args) return;
10927 args = e_util_string_append_quoted(args, &size, &length, newpath);
10928 if (!args) return;
10929
10930 e_fm2_client_file_move(ere->e_fm, args);
10931 free(args);
10932 if (file != ere->src) free(file);
10933
10934 _e_fm2_op_registry_aborted(id);
10935 _e_fm_client_send(E_FM_OP_ERROR_RESPONSE_ABORT, id, NULL, 0);
10936 e_object_del(E_OBJECT(dialog));
10937 }
10938
10939 static void
_e_fm_error_ignore_this_cb(void * data EINA_UNUSED,E_Dialog * dialog)10940 _e_fm_error_ignore_this_cb(void *data EINA_UNUSED, E_Dialog *dialog)
10941 {
10942 int id = (int)(intptr_t)E_OBJECT(dialog)->data;
10943 _e_fm2_op_registry_go_on(id);
10944 _e_fm_client_send(E_FM_OP_ERROR_RESPONSE_IGNORE_THIS, id, NULL, 0);
10945 e_object_del(E_OBJECT(dialog));
10946 }
10947
10948 static void
_e_fm_error_ignore_all_cb(void * data EINA_UNUSED,E_Dialog * dialog)10949 _e_fm_error_ignore_all_cb(void *data EINA_UNUSED, E_Dialog *dialog)
10950 {
10951 int id = (int)(intptr_t)E_OBJECT(dialog)->data;
10952 _e_fm2_op_registry_go_on(id);
10953 _e_fm_client_send(E_FM_OP_ERROR_RESPONSE_IGNORE_ALL, id, NULL, 0);
10954 e_object_del(E_OBJECT(dialog));
10955 }
10956
10957 static void
_e_fm_device_error_dialog(const char * title,const char * msg,const char * pstr)10958 _e_fm_device_error_dialog(const char *title, const char *msg, const char *pstr)
10959 {
10960 E_Dialog *dialog;
10961 char text[PATH_MAX];
10962 const char *u, *d, *n, *m;
10963
10964 dialog = e_dialog_new(NULL, "E", "_fm_device_error_dialog");
10965 e_dialog_title_set(dialog, title);
10966 e_dialog_icon_set(dialog, "drive-harddisk", 64);
10967 e_dialog_button_add(dialog, _("OK"), NULL, NULL, NULL);
10968
10969 u = pstr;
10970 pstr += strlen(pstr) + 1;
10971 d = pstr;
10972 pstr += strlen(pstr) + 1;
10973 n = pstr;
10974 pstr += strlen(pstr) + 1;
10975 m = pstr;
10976 snprintf(text, sizeof(text), "%s<ps/>%s<ps/>%s<ps/>%s<ps/>%s", msg, u, d, n, m);
10977 e_dialog_text_set(dialog, text);
10978
10979 elm_win_center(dialog->win, 1, 1);
10980 e_dialog_button_focus_num(dialog, 0);
10981 e_dialog_show(dialog);
10982 }
10983
10984 static void
_e_fm2_file_application_properties(void * data,E_Menu * m EINA_UNUSED,E_Menu_Item * mi EINA_UNUSED)10985 _e_fm2_file_application_properties(void *data, E_Menu *m EINA_UNUSED, E_Menu_Item *mi EINA_UNUSED)
10986 {
10987 Efreet_Desktop *desktop;
10988 E_Fm2_Icon *ic;
10989 char buf[PATH_MAX];
10990
10991 ic = data;
10992 if (!_e_fm2_icon_realpath(ic, buf, sizeof(buf)))
10993 return;
10994 desktop = efreet_desktop_get(buf);
10995
10996 e_desktop_edit(desktop);
10997 }
10998
10999 static void
_e_fm2_file_properties(void * data,E_Menu * m EINA_UNUSED,E_Menu_Item * mi EINA_UNUSED)11000 _e_fm2_file_properties(void *data, E_Menu *m EINA_UNUSED, E_Menu_Item *mi EINA_UNUSED)
11001 {
11002 E_Fm2_Icon *ic;
11003
11004 ic = data;
11005 if ((ic->entry_dialog) || (ic->entry_widget)) return;
11006
11007 if (ic->prop_dialog) e_object_del(E_OBJECT(ic->prop_dialog));
11008 ic->prop_dialog = e_fm_prop_file(ic);
11009 E_OBJECT(ic->prop_dialog)->data = ic;
11010 e_object_del_attach_func_set(E_OBJECT(ic->prop_dialog), _e_fm2_file_properties_delete_cb);
11011 }
11012
11013 static void
_e_fm2_file_properties_delete_cb(void * obj)11014 _e_fm2_file_properties_delete_cb(void *obj)
11015 {
11016 E_Fm2_Icon *ic;
11017
11018 ic = E_OBJECT(obj)->data;
11019 ic->prop_dialog = NULL;
11020 }
11021
11022 static void
_e_fm2_file_delete_menu(void * data,E_Menu * m EINA_UNUSED,E_Menu_Item * mi EINA_UNUSED)11023 _e_fm2_file_delete_menu(void *data, E_Menu *m EINA_UNUSED, E_Menu_Item *mi EINA_UNUSED)
11024 {
11025 E_Fm2_Icon *ic = data;
11026 if ((!ic) || (!ic->sd)) return;
11027 _e_fm2_file_delete(ic->sd->obj);
11028 }
11029
11030 static void
_e_fm2_file_delete(Evas_Object * obj)11031 _e_fm2_file_delete(Evas_Object *obj)
11032 {
11033 E_Dialog *dialog;
11034 E_Fm2_Icon *ic;
11035 char text[4096 + 256];
11036 Eina_List *sel;
11037 int n = 0, folder_count = 0;
11038
11039 ic = _e_fm2_icon_first_selected_find(obj);
11040 if (!ic) return;
11041 if (ic->dialog) return;
11042 dialog = e_dialog_new(NULL, "E", "_fm_file_delete_dialog");
11043 ic->dialog = dialog;
11044 E_OBJECT(dialog)->data = ic;
11045 e_object_del_attach_func_set(E_OBJECT(dialog), _e_fm2_file_delete_delete_cb);
11046 e_dialog_button_add(dialog, _("Delete"), NULL, _e_fm2_file_delete_yes_cb, ic);
11047 e_dialog_button_add(dialog, _("No"), NULL, _e_fm2_file_delete_no_cb, ic);
11048 e_dialog_button_focus_num(dialog, 0);
11049 e_dialog_title_set(dialog, _("Confirm Delete"));
11050 e_dialog_icon_set(dialog, "dialog-warning", 64);
11051 sel = e_fm2_selected_list_get(obj);
11052 if (sel)
11053 {
11054 n = eina_list_count(sel);
11055 folder_count = eina_list_count(ic->sd->icons);
11056 }
11057 if ((!sel) || (n == 1))
11058 snprintf(text, sizeof(text),
11059 _("Are you sure you want to delete<ps/>"
11060 "<hilight>%s</hilight>?"),
11061 ic->info.file);
11062 else if (n == folder_count)
11063 snprintf(text, sizeof(text),
11064 _("Are you sure you want to delete<ps/>"
11065 "<hilight>all</hilight> the %d files in<ps/>"
11066 "<hilight>%s</hilight>?"),
11067 n, ic->sd->realpath);
11068 else
11069 {
11070 /* Here the singular version is not used in english, but plural support
11071 * is nonetheless needed for languages who have multiple plurals
11072 * depending on the number of files. */
11073 snprintf(text, sizeof(text),
11074 P_("Are you sure you want to delete<ps/>"
11075 "the %d selected file in<ps/>"
11076 "<hilight>%s</hilight>?",
11077 "Are you sure you want to delete<ps/>"
11078 "the %d selected files in<ps/>"
11079 "<hilight>%s</hilight>?", n),
11080 n, ic->sd->realpath);
11081 }
11082 if (sel) eina_list_free(sel);
11083 e_dialog_text_set(dialog, text);
11084 elm_win_center(dialog->win, 1, 1);
11085 e_dialog_show(dialog);
11086 }
11087
11088 static void
_e_fm2_file_delete_delete_cb(void * obj)11089 _e_fm2_file_delete_delete_cb(void *obj)
11090 {
11091 E_Fm2_Icon *ic;
11092
11093 ic = E_OBJECT(obj)->data;
11094 ic->dialog = NULL;
11095 }
11096
11097 static void
_e_fm2_file_delete_yes_cb(void * data,E_Dialog * dialog)11098 _e_fm2_file_delete_yes_cb(void *data, E_Dialog *dialog)
11099 {
11100 E_Fm2_Icon *ic, *ic_next;
11101 char buf[PATH_MAX];
11102 char *files = NULL;
11103 size_t size = 0;
11104 size_t len = 0;
11105 Eina_List *sel, *l;
11106 E_Fm2_Icon_Info *ici;
11107 Eina_Bool memerr = EINA_FALSE;
11108
11109 ic = data;
11110 ic->dialog = NULL;
11111
11112 e_object_del(E_OBJECT(dialog));
11113 ic_next = _e_fm2_icon_next_find(ic->sd->obj, 1, NULL, NULL);
11114 sel = e_fm2_selected_list_get(ic->sd->obj);
11115 if (sel && (eina_list_count(sel) != 1))
11116 {
11117 EINA_LIST_FOREACH(sel, l, ici)
11118 {
11119 if (ic_next && (&(ic_next->info) == ici))
11120 ic_next = NULL;
11121
11122 snprintf(buf, sizeof(buf), "%s/%s", ic->sd->realpath, ici->file);
11123 if (e_filereg_file_protected(buf)) continue;
11124
11125 if (!memerr)
11126 {
11127 files = e_util_string_append_quoted(files, &size, &len, buf);
11128 if (!files) memerr = EINA_TRUE;
11129 else
11130 {
11131 if (eina_list_next(l))
11132 {
11133 files = e_util_string_append_char(files, &size, &len, ' ');
11134 if (!files) memerr = EINA_TRUE;
11135 }
11136 }
11137 }
11138 evas_object_pass_events_set(ici->ic->obj, 1);
11139 }
11140 eina_list_free(sel);
11141 }
11142 else
11143 {
11144 if (sel) eina_list_free(sel);
11145 _e_fm2_icon_realpath(ic, buf, sizeof(buf));
11146 if (e_filereg_file_protected(buf)) return;
11147 evas_object_pass_events_set(ic->obj, 1);
11148 files = e_util_string_append_quoted(files, &size, &len, buf);
11149 }
11150 if (files)
11151 {
11152 _e_fm_client_file_del(files, e_config->filemanager_secure_rm | ic->sd->config->secure_rm, ic->sd->obj);
11153 free(files);
11154 }
11155
11156 if (ic_next)
11157 {
11158 _e_fm2_icon_select(ic_next);
11159 evas_object_smart_callback_call(ic_next->sd->obj, "selection_change", NULL);
11160 _e_fm2_icon_make_visible(ic_next);
11161 }
11162
11163 evas_object_smart_callback_call(ic->sd->obj, "files_deleted", NULL);
11164 }
11165
11166 static void
_e_fm2_file_delete_no_cb(void * data,E_Dialog * dialog)11167 _e_fm2_file_delete_no_cb(void *data, E_Dialog *dialog)
11168 {
11169 E_Fm2_Icon *ic;
11170
11171 ic = data;
11172 ic->dialog = NULL;
11173 e_object_del(E_OBJECT(dialog));
11174 }
11175
11176 static Eina_Bool
_e_fm2_sys_suspend_hibernate(void * d EINA_UNUSED,int type EINA_UNUSED,void * ev EINA_UNUSED)11177 _e_fm2_sys_suspend_hibernate(void *d EINA_UNUSED, int type EINA_UNUSED, void *ev EINA_UNUSED)
11178 {
11179 Eina_List *l, *ll, *lll;
11180 E_Volume *v;
11181 E_Fm2_Mount *m;
11182
11183 EINA_LIST_FOREACH(e_fm2_device_volume_list_get(), l, v)
11184 {
11185 EINA_LIST_FOREACH_SAFE(v->mounts, ll, lll, m)
11186 e_fm2_device_unmount(m);
11187 }
11188 return ECORE_CALLBACK_RENEW;
11189 }
11190
11191 static void
_e_fm2_refresh_job_cb(void * data)11192 _e_fm2_refresh_job_cb(void *data)
11193 {
11194 E_Fm2_Smart_Data *sd;
11195
11196 sd = evas_object_smart_data_get(data);
11197 if (!sd) return;
11198 e_fm2_refresh(data);
11199 sd->refresh_job = NULL;
11200 }
11201
11202 static void
_e_fm2_live_file_add(Evas_Object * obj,const char * file,const char * file_rel,int after,E_Fm2_Finfo * finf)11203 _e_fm2_live_file_add(Evas_Object *obj, const char *file, const char *file_rel, int after, E_Fm2_Finfo *finf)
11204 {
11205 E_Fm2_Smart_Data *sd;
11206 E_Fm2_Action *a;
11207
11208 sd = evas_object_smart_data_get(obj);
11209 if (!sd) return;
11210 a = E_NEW(E_Fm2_Action, 1);
11211 if (!a) return;
11212 sd->live.actions = eina_list_append(sd->live.actions, a);
11213 a->type = FILE_ADD;
11214 a->file = eina_stringshare_add(file);
11215 a->file2 = eina_stringshare_add(file_rel);
11216 a->flags = after;
11217 if (finf) memcpy(&(a->finf), finf, sizeof(E_Fm2_Finfo));
11218 a->finf.lnk = eina_stringshare_add(a->finf.lnk);
11219 a->finf.rlnk = eina_stringshare_add(a->finf.rlnk);
11220 _e_fm2_live_process_begin(obj);
11221 }
11222
11223 static void
_e_fm2_live_file_del(Evas_Object * obj,const char * file)11224 _e_fm2_live_file_del(Evas_Object *obj, const char *file)
11225 {
11226 E_Fm2_Smart_Data *sd;
11227 E_Fm2_Action *a;
11228
11229 sd = evas_object_smart_data_get(obj);
11230 if (!sd) return;
11231 a = E_NEW(E_Fm2_Action, 1);
11232 if (!a) return;
11233 sd->live.actions = eina_list_append(sd->live.actions, a);
11234 a->type = FILE_DEL;
11235 a->file = eina_stringshare_add(file);
11236 _e_fm2_live_process_begin(obj);
11237 }
11238
11239 static void
_e_fm2_live_file_changed(Evas_Object * obj,const char * file,E_Fm2_Finfo * finf)11240 _e_fm2_live_file_changed(Evas_Object *obj, const char *file, E_Fm2_Finfo *finf)
11241 {
11242 E_Fm2_Smart_Data *sd;
11243 E_Fm2_Action *a;
11244
11245 sd = evas_object_smart_data_get(obj);
11246 if (!sd) return;
11247 a = E_NEW(E_Fm2_Action, 1);
11248 if (!a) return;
11249 sd->live.actions = eina_list_append(sd->live.actions, a);
11250 a->type = FILE_CHANGE;
11251 a->file = eina_stringshare_add(file);
11252 if (finf) memcpy(&(a->finf), finf, sizeof(E_Fm2_Finfo));
11253 a->finf.lnk = eina_stringshare_add(a->finf.lnk);
11254 a->finf.rlnk = eina_stringshare_add(a->finf.rlnk);
11255 _e_fm2_live_process_begin(obj);
11256 }
11257
11258 static void
_e_fm2_live_process_begin(Evas_Object * obj)11259 _e_fm2_live_process_begin(Evas_Object *obj)
11260 {
11261 E_Fm2_Smart_Data *sd;
11262
11263 sd = evas_object_smart_data_get(obj);
11264 if (!sd->live.actions) return;
11265 if ((sd->live.idler) || (sd->live.timer) ||
11266 (sd->listing) || (sd->scan_timer)) return;
11267 sd->live.idler = ecore_idler_add(_e_fm2_cb_live_idler, obj);
11268 sd->live.timer = ecore_timer_loop_add(0.2, _e_fm2_cb_live_timer, obj);
11269 sd->tmp.last_insert = NULL;
11270 }
11271
11272 static void
_e_fm2_live_process_end(Evas_Object * obj)11273 _e_fm2_live_process_end(Evas_Object *obj)
11274 {
11275 E_Fm2_Smart_Data *sd;
11276 E_Fm2_Action *a;
11277
11278 sd = evas_object_smart_data_get(obj);
11279 EINA_LIST_FREE(sd->live.actions, a)
11280 {
11281 eina_stringshare_del(a->file);
11282 eina_stringshare_del(a->file2);
11283 eina_stringshare_del(a->finf.lnk);
11284 eina_stringshare_del(a->finf.rlnk);
11285 free(a);
11286 }
11287 if (sd->live.idler)
11288 {
11289 ecore_idler_del(sd->live.idler);
11290 sd->live.idler = NULL;
11291 }
11292 if (sd->live.timer)
11293 {
11294 ecore_timer_del(sd->live.timer);
11295 sd->live.timer = NULL;
11296 }
11297 sd->tmp.last_insert = NULL;
11298 }
11299
11300 static void
_e_fm2_live_process(Evas_Object * obj)11301 _e_fm2_live_process(Evas_Object *obj)
11302 {
11303 E_Fm2_Smart_Data *sd;
11304 E_Fm2_Action *a;
11305 Eina_List *l;
11306 E_Fm2_Icon *ic;
11307
11308 sd = evas_object_smart_data_get(obj);
11309 if (!sd->live.actions) return;
11310 a = eina_list_data_get(sd->live.actions);
11311 sd->live.actions = eina_list_remove_list(sd->live.actions, sd->live.actions);
11312 switch (a->type)
11313 {
11314 case FILE_ADD:
11315 /* new file to sort in place */
11316 if (!strcmp(a->file, ".order"))
11317 {
11318 sd->order_file = EINA_TRUE;
11319 /* FIXME: reload fm view */
11320 }
11321 else
11322 {
11323 if (!((a->file[0] == '.') && (!sd->show_hidden_files)))
11324 _e_fm2_file_add(obj, a->file, 1, a->file2, a->flags, &(a->finf));
11325 }
11326 break;
11327
11328 case FILE_DEL:
11329 if (!strcmp(a->file, ".order"))
11330 {
11331 sd->order_file = EINA_FALSE;
11332 /* FIXME: reload fm view */
11333 }
11334 else
11335 {
11336 if (!((a->file[0] == '.') && (!sd->show_hidden_files)))
11337 _e_fm2_file_del(obj, a->file);
11338 sd->live.deletions = EINA_TRUE;
11339 }
11340 break;
11341
11342 case FILE_CHANGE:
11343 if (!strcmp(a->file, ".order"))
11344 {
11345 /* FIXME: reload fm view - ignore for now */
11346 }
11347 else
11348 {
11349 if (!((a->file[0] == '.') && (!sd->show_hidden_files)))
11350 {
11351 EINA_LIST_FOREACH(sd->icons, l, ic)
11352 {
11353 if (!strcmp(ic->info.file, a->file))
11354 {
11355 if (ic->removable_state_change)
11356 {
11357 _e_fm2_icon_unfill(ic);
11358 _e_fm2_icon_fill(ic, &(a->finf));
11359 ic->removable_state_change = EINA_FALSE;
11360 if ((ic->realized) && (ic->obj_icon))
11361 {
11362 _e_fm2_icon_removable_update(ic);
11363 _e_fm2_icon_label_set(ic, ic->obj);
11364 }
11365 }
11366 else if (!eina_str_has_extension(ic->info.file, ".part"))
11367 {
11368 int realized;
11369
11370 realized = ic->realized;
11371 if (realized) _e_fm2_icon_unrealize(ic);
11372 _e_fm2_icon_unfill(ic);
11373 _e_fm2_icon_fill(ic, &(a->finf));
11374 if (realized) _e_fm2_icon_realize(ic);
11375 }
11376 break;
11377 }
11378 }
11379 }
11380 }
11381 break;
11382
11383 default:
11384 break;
11385 }
11386 eina_stringshare_del(a->file);
11387 eina_stringshare_del(a->file2);
11388 eina_stringshare_del(a->finf.lnk);
11389 eina_stringshare_del(a->finf.rlnk);
11390 free(a);
11391 }
11392
11393 static Eina_Bool
_e_fm2_cb_live_idler(void * data)11394 _e_fm2_cb_live_idler(void *data)
11395 {
11396 E_Fm2_Smart_Data *sd;
11397 double t;
11398
11399 sd = evas_object_smart_data_get(data);
11400 if (!sd) return ECORE_CALLBACK_CANCEL;
11401 t = ecore_time_get();
11402 do
11403 {
11404 if (!sd->live.actions) break;
11405 _e_fm2_live_process(data);
11406 }
11407 while ((ecore_time_get() - t) > 0.02);
11408 if (sd->live.actions) return ECORE_CALLBACK_RENEW;
11409 _e_fm2_live_process_end(data);
11410 _e_fm2_cb_live_timer(data);
11411 if ((sd->order_file) || (sd->config->view.always_order))
11412 {
11413 e_fm2_refresh(data);
11414 }
11415 sd->live.idler = NULL;
11416 return ECORE_CALLBACK_CANCEL;
11417 }
11418
11419 static Eina_Bool
_e_fm2_cb_live_timer(void * data)11420 _e_fm2_cb_live_timer(void *data)
11421 {
11422 E_Fm2_Smart_Data *sd;
11423
11424 sd = evas_object_smart_data_get(data);
11425 if (!sd) return ECORE_CALLBACK_CANCEL;
11426 if (sd->queue) _e_fm2_queue_process(data);
11427 else if (sd->iconlist_changed)
11428 {
11429 if (sd->resize_job) ecore_job_del(sd->resize_job);
11430 sd->resize_job = ecore_job_add(_e_fm2_cb_resize_job, sd->obj);
11431 }
11432 else
11433 {
11434 if (sd->live.deletions)
11435 {
11436 sd->iconlist_changed = EINA_TRUE;
11437 if (sd->resize_job) ecore_job_del(sd->resize_job);
11438 sd->resize_job = ecore_job_add(_e_fm2_cb_resize_job, sd->obj);
11439 }
11440 }
11441 sd->live.deletions = EINA_FALSE;
11442 sd->live.timer = NULL;
11443 if ((!sd->queue) && (!sd->live.idler)) return ECORE_CALLBACK_CANCEL;
11444 sd->live.timer = ecore_timer_loop_add(0.2, _e_fm2_cb_live_timer, data);
11445 return ECORE_CALLBACK_CANCEL;
11446 }
11447
11448 static int
_e_fm2_theme_edje_object_set(E_Fm2_Smart_Data * sd,Evas_Object * o,const char * category,const char * group)11449 _e_fm2_theme_edje_object_set(E_Fm2_Smart_Data *sd, Evas_Object *o, const char *category, const char *group)
11450 {
11451 char buf[1024];
11452 int ret;
11453
11454 if (sd->custom_theme_content)
11455 snprintf(buf, sizeof(buf), "e/fileman/%s/%s", sd->custom_theme_content, group);
11456 else
11457 snprintf(buf, sizeof(buf), "e/fileman/default/%s", group);
11458
11459 if (sd->custom_theme)
11460 {
11461 if (edje_object_file_set(o, sd->custom_theme, buf)) return 1;
11462 }
11463 if (sd->custom_theme)
11464 {
11465 if (!ecore_file_exists(sd->custom_theme))
11466 {
11467 eina_stringshare_del(sd->custom_theme);
11468 sd->custom_theme = NULL;
11469 }
11470 }
11471 ret = e_theme_edje_object_set(o, category, buf);
11472 return ret;
11473 }
11474
11475 static int
_e_fm2_theme_edje_icon_object_set(E_Fm2_Smart_Data * sd,Evas_Object * o,const char * category,const char * group)11476 _e_fm2_theme_edje_icon_object_set(E_Fm2_Smart_Data *sd, Evas_Object *o, const char *category, const char *group)
11477 {
11478 char buf[1024];
11479 int ret;
11480
11481 // if (sd->custom_theme_content)
11482 // snprintf(buf, sizeof(buf), "e/icons/fileman/%s/%s", sd->custom_theme_content, group);
11483 // else
11484 snprintf(buf, sizeof(buf), "e/icons/fileman/mime/%s", group);
11485
11486 if (sd->custom_theme)
11487 {
11488 if (edje_object_file_set(o, sd->custom_theme, buf)) return 1;
11489 }
11490 if (sd->custom_theme)
11491 {
11492 if (!ecore_file_exists(sd->custom_theme))
11493 {
11494 eina_stringshare_del(sd->custom_theme);
11495 sd->custom_theme = NULL;
11496 }
11497 }
11498 ret = e_theme_edje_object_set(o, category, buf);
11499 return ret;
11500 }
11501
11502 static void
_e_fm2_volume_mount(void * data,E_Menu * m EINA_UNUSED,E_Menu_Item * mi EINA_UNUSED)11503 _e_fm2_volume_mount(void *data, E_Menu *m EINA_UNUSED, E_Menu_Item *mi EINA_UNUSED)
11504 {
11505 E_Volume *v;
11506 const char *mp;
11507
11508 v = data;
11509 if (!v) return;
11510
11511 mp = e_fm2_device_volume_mountpoint_get(v);
11512 _e_fm2_client_mount(v->udi, mp);
11513 eina_stringshare_del(mp);
11514 }
11515
11516 static void
_e_fm2_volume_unmount(void * data,E_Menu * m EINA_UNUSED,E_Menu_Item * mi EINA_UNUSED)11517 _e_fm2_volume_unmount(void *data, E_Menu *m EINA_UNUSED, E_Menu_Item *mi EINA_UNUSED)
11518 {
11519 E_Volume *v;
11520
11521 v = data;
11522 if (!v) return;
11523
11524 v->auto_unmount = EINA_FALSE;
11525 _e_fm2_client_unmount(v->udi);
11526 }
11527
11528 static void
_e_fm2_volume_eject(void * data,E_Menu * m EINA_UNUSED,E_Menu_Item * mi EINA_UNUSED)11529 _e_fm2_volume_eject(void *data, E_Menu *m EINA_UNUSED, E_Menu_Item *mi EINA_UNUSED)
11530 {
11531 E_Volume *v;
11532
11533 v = data;
11534 if (!v) return;
11535
11536 v->auto_unmount = EINA_FALSE;
11537 _e_fm2_client_eject(v->udi);
11538 }
11539
11540 static void
_update_volume_icon(E_Volume * v,E_Fm2_Icon * ic)11541 _update_volume_icon(E_Volume *v, E_Fm2_Icon *ic)
11542 {
11543 Evas_Object *e = e_icon_edje_get(ic->obj_icon);
11544 if (e)
11545 {
11546 if (ic->info.removable_full)
11547 e_icon_edje_emit(ic->obj_icon, "e,state,removable,full", "e");
11548 else
11549 e_icon_edje_emit(ic->obj_icon, "e,state,removable,empty", "e");
11550 }
11551
11552 if (v)
11553 {
11554 if (v->mounted)
11555 edje_object_signal_emit(ic->obj, "e,state,volume,mounted", "e");
11556 else
11557 edje_object_signal_emit(ic->obj, "e,state,volume,unmounted", "e");
11558 }
11559 else
11560 edje_object_signal_emit(ic->obj, "e,state,volume,off", "e");
11561 }
11562
11563 static void
_e_fm2_volume_icon_update(E_Volume * v)11564 _e_fm2_volume_icon_update(E_Volume *v)
11565 {
11566 Evas_Object *o;
11567 char file[PATH_MAX], fav[PATH_MAX];
11568 const char *desk;
11569 Eina_List *l;
11570 E_Fm2_Icon *ic;
11571
11572 if (!v || !v->storage) return;
11573
11574 e_user_dir_snprintf(fav, sizeof(fav), "fileman/favorites");
11575 desk = efreet_desktop_dir_get();
11576 snprintf(file, sizeof(file), "|%s_%d.desktop",
11577 ecore_file_file_get(v->storage->udi), v->partition_number);
11578
11579 EINA_LIST_FOREACH(_e_fm2_list, l, o)
11580 {
11581 const char *rp;
11582
11583 if ((_e_fm2_list_walking > 0) &&
11584 (eina_list_data_find(_e_fm2_list_remove, o))) continue;
11585
11586 rp = e_fm2_real_path_get(o);
11587 if ((rp) && (strcmp(rp, fav)) && (strcmp(rp, desk))) continue;
11588
11589 ic = _e_fm2_icon_find(o, file);
11590 if (ic)
11591 _update_volume_icon(v, ic);
11592 }
11593 }
11594
11595 static void
_e_fm2_icon_removable_update(E_Fm2_Icon * ic)11596 _e_fm2_icon_removable_update(E_Fm2_Icon *ic)
11597 {
11598 E_Volume *v;
11599
11600 if (!ic) return;
11601 v = e_fm2_device_volume_find(ic->info.link);
11602 _update_volume_icon(v, ic);
11603 }
11604
11605 static void
_e_fm2_operation_abort_internal(E_Fm2_Op_Registry_Entry * ere)11606 _e_fm2_operation_abort_internal(E_Fm2_Op_Registry_Entry *ere)
11607 {
11608 ere->status = E_FM2_OP_STATUS_ABORTED;
11609 ere->finished = 1;
11610 ere->needs_attention = 0;
11611 ere->dialog = NULL;
11612 e_fm2_op_registry_entry_changed(ere);
11613 _e_fm_client_send(E_FM_OP_ABORT, ere->id, NULL, 0);
11614 }
11615
11616 E_API void
e_fm2_operation_abort(int id)11617 e_fm2_operation_abort(int id)
11618 {
11619 E_Fm2_Op_Registry_Entry *ere;
11620
11621 ere = e_fm2_op_registry_entry_get(id);
11622 if (!ere) return;
11623
11624 e_fm2_op_registry_entry_ref(ere);
11625 e_fm2_op_registry_entry_abort(ere);
11626 e_fm2_op_registry_entry_unref(ere);
11627 }
11628
11629 E_API Eina_Bool
e_fm2_optimal_size_calc(Evas_Object * obj,int minw,int maxw,int maxh,int * w,int * h)11630 e_fm2_optimal_size_calc(Evas_Object *obj, int minw, int maxw, int maxh, int *w, int *h)
11631 {
11632 int x, y, step_w, step_h;
11633 EFM_SMART_CHECK(EINA_FALSE);
11634 if ((!w) || (!h)) return EINA_FALSE;
11635 if (!sd->icons) return EINA_FALSE;
11636 if (maxw < 0) maxw = 0;
11637 if (maxh < 0) maxh = 0;
11638 step_w = sd->min.w + 5, step_h = sd->min.h + 5;
11639 switch (_e_fm2_view_mode_get(sd))
11640 {
11641 case E_FM2_VIEW_MODE_LIST:
11642 *w = MIN(step_w, maxw);
11643 *h = MIN(step_h * eina_list_count(sd->icons), (unsigned int)maxh);
11644 return EINA_TRUE;
11645
11646 default:
11647 break;
11648 }
11649 y = x = (int)sqrt(eina_list_count(sd->icons));
11650 if (maxw && (x * step_w > maxw))
11651 {
11652 x = maxw / step_w;
11653 y = (eina_list_count(sd->icons) / x) + ((maxw % step_w) ? 1 : 0);
11654 }
11655 if (minw && (x * step_w < minw))
11656 {
11657 x = minw / step_w;
11658 y = (eina_list_count(sd->icons) / x) + ((minw % step_w) ? 1 : 0);
11659 }
11660 *w = step_w * x;
11661 *w = MIN(*w, maxw);
11662 *h = step_h * y;
11663 *h = MIN(*h, maxh);
11664 return EINA_TRUE;
11665 }
11666
11667 E_API E_Fm2_View_Mode
e_fm2_view_mode_get(Evas_Object * obj)11668 e_fm2_view_mode_get(Evas_Object *obj)
11669 {
11670 EFM_SMART_CHECK(0);
11671 return _e_fm2_view_mode_get(sd);
11672 }
11673
11674 E_API Eina_Bool
e_fm2_typebuf_visible_get(Evas_Object * obj)11675 e_fm2_typebuf_visible_get(Evas_Object *obj)
11676 {
11677 EFM_SMART_CHECK(EINA_FALSE);
11678 return sd->typebuf_visible;
11679 }
11680
11681 E_API void
e_fm2_typebuf_clear(Evas_Object * obj)11682 e_fm2_typebuf_clear(Evas_Object *obj)
11683 {
11684 EFM_SMART_CHECK();
11685 _e_fm2_typebuf_hide(obj);
11686 }
11687
11688 E_API void
e_fm2_overlay_clip_to(Evas_Object * obj,Evas_Object * clip)11689 e_fm2_overlay_clip_to(Evas_Object *obj, Evas_Object *clip)
11690 {
11691 int x, y, w, h;
11692 EFM_SMART_CHECK();
11693 if (sd->overlay_clip)
11694 {
11695 evas_object_event_callback_del_full(sd->overlay_clip, EVAS_CALLBACK_MOVE, _e_fm2_overlay_clip_move, sd);
11696 evas_object_event_callback_del_full(sd->overlay_clip, EVAS_CALLBACK_RESIZE, _e_fm2_overlay_clip_resize, sd);
11697 }
11698 sd->overlay_clip = clip;
11699 if (clip)
11700 {
11701 evas_object_clip_set(sd->overlay, clip);
11702 evas_object_geometry_get(clip, &x, &y, &w, &h);
11703 evas_object_move(sd->overlay, x, y);
11704 evas_object_resize(sd->overlay, w, h);
11705 evas_object_event_callback_add(clip, EVAS_CALLBACK_MOVE, _e_fm2_overlay_clip_move, sd);
11706 evas_object_event_callback_add(clip, EVAS_CALLBACK_RESIZE, _e_fm2_overlay_clip_resize, sd);
11707 }
11708 else
11709 {
11710 evas_object_clip_set(sd->overlay, sd->clip);
11711 evas_object_move(sd->overlay, sd->x, sd->y);
11712 evas_object_resize(sd->overlay, sd->w, sd->h);
11713 }
11714 }
11715
11716 E_API const char *
e_fm2_real_path_map(const char * dev,const char * path)11717 e_fm2_real_path_map(const char *dev, const char *path)
11718 {
11719 return _e_fm2_dev_path_map(NULL, dev, path);
11720 }
11721
11722 E_API void
e_fm2_favorites_init(void)11723 e_fm2_favorites_init(void)
11724 {
11725 Eina_List *files;
11726 char buf[PATH_MAX], buf2[PATH_MAX], *file;
11727
11728 // make dir for favorites and install ones shipped
11729 e_user_dir_concat_static(buf, "fileman/favorites");
11730 ecore_file_mkpath(buf);
11731 if (!ecore_file_dir_is_empty(buf)) return;
11732 e_prefix_data_concat(buf, sizeof(buf), "data/favorites");
11733 files = ecore_file_ls(buf);
11734 if (!files) return;
11735 EINA_LIST_FREE(files, file)
11736 {
11737 e_prefix_data_snprintf(buf, sizeof(buf), "data/favorites/%s", file);
11738 snprintf(buf2, sizeof(buf2), "%s/fileman/favorites/%s",
11739 e_user_dir_get(), file);
11740 ecore_file_cp(buf, buf2);
11741 free(file);
11742 }
11743 }
11744
11745 E_API unsigned int
e_fm2_selected_count(Evas_Object * obj)11746 e_fm2_selected_count(Evas_Object *obj)
11747 {
11748 EFM_SMART_CHECK(0);
11749 return eina_list_count(sd->selected_icons);
11750 }
11751
11752 E_API E_Fm2_Icon_Info *
e_fm2_drop_icon_get(Evas_Object * obj)11753 e_fm2_drop_icon_get(Evas_Object *obj)
11754 {
11755 EFM_SMART_CHECK(NULL);
11756 return sd->drop_icon ? &sd->drop_icon->info : NULL;
11757 }
11758
11759 E_API Eina_List *
e_fm2_uri_path_list_get(const Eina_List * uri_list)11760 e_fm2_uri_path_list_get(const Eina_List *uri_list)
11761 {
11762 E_Fm2_Uri *uri;
11763 const Eina_List *l;
11764 Eina_List *path_list = NULL;
11765 char current_hostname[_POSIX_HOST_NAME_MAX];
11766 const char *uri_str;
11767
11768 if (gethostname(current_hostname, _POSIX_HOST_NAME_MAX) == -1)
11769 current_hostname[0] = '\0';
11770
11771 EINA_LIST_FOREACH(uri_list, l, uri_str)
11772 {
11773 if (!(uri = _e_fm2_uri_parse(uri_str)))
11774 continue;
11775
11776 if (!uri->hostname || !strcmp(uri->hostname, "localhost")
11777 || !strcmp(uri->hostname, current_hostname))
11778 {
11779 path_list = eina_list_append(path_list, uri->path);
11780 }
11781 else
11782 eina_stringshare_del(uri->path);
11783
11784 eina_stringshare_del(uri->hostname);
11785 E_FREE(uri);
11786 }
11787
11788 return path_list;
11789 }
11790
11791 E_API Efreet_Desktop *
e_fm2_desktop_get(Evas_Object * obj)11792 e_fm2_desktop_get(Evas_Object *obj)
11793 {
11794 EFM_SMART_CHECK(NULL);
11795 if (_e_fm2_desktop_open(sd) != 1) return NULL;
11796 return sd->desktop;
11797 }
11798
11799 E_API void
e_fm2_drop_menu(Evas_Object * obj,char * args)11800 e_fm2_drop_menu(Evas_Object *obj, char *args)
11801 {
11802 E_Menu *menu;
11803 E_Menu_Item *item;
11804 E_Zone *zone;
11805 int x, y;
11806
11807 EFM_SMART_CHECK();
11808
11809 EINA_SAFETY_ON_TRUE_RETURN(!!sd->menu);
11810 sd->menu = menu = e_menu_new();
11811 if (!menu) return;
11812
11813 e_menu_post_deactivate_callback_set(menu, _e_fm2_menu_post_cb, sd);
11814
11815 evas_object_data_set(obj, "drop_menu_data", args);
11816 e_object_data_set(E_OBJECT(menu), obj);
11817 e_object_free_attach_func_set(E_OBJECT(menu), _e_fm_drop_menu_free);
11818
11819 item = e_menu_item_new(menu);
11820 e_menu_item_label_set(item, _("Copy"));
11821 e_menu_item_callback_set(item, _e_fm_drop_menu_copy_cb, obj);
11822 e_util_menu_item_theme_icon_set(item, "edit-copy");
11823
11824 item = e_menu_item_new(menu);
11825 e_menu_item_label_set(item, _("Move"));
11826 e_menu_item_callback_set(item, _e_fm_drop_menu_move_cb, obj);
11827 e_menu_item_icon_edje_set(item,
11828 e_theme_edje_file_get("base/theme/fileman",
11829 "e/fileman/default/button/move"),
11830 "e/fileman/default/button/move");
11831
11832 item = e_menu_item_new(menu);
11833 e_menu_item_label_set(item, _("Link"));
11834 e_menu_item_callback_set(item, _e_fm_drop_menu_symlink_cb, obj);
11835 e_util_menu_item_theme_icon_set(item, "emblem-symbolic-link");
11836
11837 item = e_menu_item_new(menu);
11838 e_menu_item_separator_set(item, 1);
11839
11840 item = e_menu_item_new(menu);
11841 e_menu_item_label_set(item, _("Abort"));
11842 e_menu_item_callback_set(item, _e_fm_drop_menu_abort_cb, obj);
11843 e_menu_item_icon_edje_set(item,
11844 e_theme_edje_file_get("base/theme/fileman",
11845 "e/fileman/default/button/abort"),
11846 "e/fileman/default/button/abort");
11847
11848 ecore_evas_pointer_xy_get(e_comp->ee, &x, &y);
11849 zone = e_zone_current_get();
11850 if (!zone) goto error;
11851 e_menu_activate_mouse(menu, zone, x, y, 1, 1, E_MENU_POP_DIRECTION_DOWN, 0);
11852 return;
11853 error:
11854 e_object_del(E_OBJECT(menu));
11855 sd->menu = NULL;
11856 }
11857
11858 E_API E_Fm2_Icon *
e_fm2_icon_editing_get(Evas_Object * obj)11859 e_fm2_icon_editing_get(Evas_Object *obj)
11860 {
11861 EFM_SMART_CHECK(NULL);
11862 return sd->iop_icon;
11863 }
11864