69a2246a7dabda91c080be0b5e5782eeb11e0786
[framework/uifw/e17.git] / src / bin / e_eap_editor.c
1 #include "e.h"
2
3 struct _E_Config_Dialog_Data
4 {
5    Efreet_Desktop *desktop;
6    int type; /* desktop type */
7
8    char *name; /* app name (e.g. Firefox) */
9    char *generic_name; /* generic app name (e.g. Web Browser) */
10    char *comment; /* a longer description */
11    char *exec; /* command to execute */
12    char *try_exec; /* executable to test for an apps existence */
13    char *url; /* url to open */
14
15    char *startup_wm_class; /* window class */
16    char *categories; /* list of category names that app is in */
17    char *mimes; /* list of mimes this app can handle */
18    char *icon;  /* absolute path to file or icon name */
19
20    int startup_notify;
21    int terminal;
22    int show_in_menus;
23
24    E_Desktop_Edit *editor;
25
26    char *orig_path; /* informational only */
27    Evas_Object *orig_path_entry; /* to set when info changes */
28    Evas_Object *icon_entry; /* to set when icon changes */
29
30    /* speed up check_changed tests */
31    Eina_Bool changed_categories;
32    Eina_Bool changed_mimes;
33    Eina_Bool edited_categories;
34    Eina_Bool edited_mimes;
35 };
36
37 /* local subsystem functions */
38
39 static int          _e_desktop_edit_view_create(E_Desktop_Edit *editor, E_Container *con);
40 static void         _e_desktop_edit_free(E_Desktop_Edit *editor);
41 static void        *_e_desktop_edit_create_data(E_Config_Dialog *cfd);
42 static void         _e_desktop_edit_free_data(E_Config_Dialog *cfd, E_Config_Dialog_Data *data);
43 static int          _e_desktop_edit_basic_apply_data(E_Config_Dialog *cfd, E_Config_Dialog_Data *data);
44 static int          _e_desktop_edit_basic_check_changed(E_Config_Dialog *cfd, E_Config_Dialog_Data *data);
45 static Evas_Object *_e_desktop_edit_basic_create_widgets(E_Config_Dialog *cfd, Evas *evas, E_Config_Dialog_Data *data);
46 static void         _e_desktop_editor_cb_icon_select(void *data1, void *data2);
47 static void         _e_desktop_edit_cb_icon_select_destroy(void *obj);
48 static void         _e_desktop_edit_cb_icon_select_ok(void *data, E_Dialog *dia);
49 static void         _e_desktop_edit_cb_icon_select_cancel(void *data, E_Dialog *dia);
50 static void         _e_desktop_editor_icon_update(E_Config_Dialog_Data *cfdata);
51 static void         _e_desktop_editor_cb_exec_select(void *data1, void *data2);
52 static void         _e_desktop_edit_cb_exec_select_destroy(void *obj);
53 static void         _e_desktop_edit_cb_exec_select_ok(void *data, E_Dialog *dia);
54 static void         _e_desktop_edit_cb_exec_select_cancel(void *data, E_Dialog *dia);
55 static void         _e_desktop_editor_exec_update(E_Config_Dialog_Data *cfdata);
56 static void         _e_desktop_edit_select_cb(void *data, Evas_Object *obj);
57 static void         _e_desktop_editor_icon_entry_changed(void *data, Evas_Object *obj);
58
59 #define IFADD(src, dst) if (src) dst = eina_stringshare_add(src); else dst = NULL
60 #define IFDEL(src) if (src) eina_stringshare_del(src);  src = NULL;
61 #define IFDUP(src, dst) if (src) dst = strdup(src); else dst = NULL
62 #define IFFREE(src) if (src) free(src);  src = NULL;
63
64 /* externally accessible functions */
65
66 EAPI Efreet_Desktop *
67 e_desktop_border_create(E_Border *bd)
68 {
69    Efreet_Desktop *desktop = NULL;
70    const char *desktop_dir, *icon_dir;
71    const char *bname, *bclass, *btitle;
72    char path[PATH_MAX];
73
74    bname = bd->client.icccm.name;
75    if ((bname) && (bname[0] == 0)) bname = NULL;
76    bclass = bd->client.icccm.class;
77    if ((bclass) && (bclass[0] == 0)) bclass = NULL;
78    btitle = e_border_name_get(bd);
79    
80    desktop_dir = e_user_desktop_dir_get();
81
82    if ((!desktop_dir) || (!e_util_dir_check(desktop_dir))) return NULL;
83
84    icon_dir = e_user_icon_dir_get();
85    if ((!icon_dir) || (!e_util_dir_check(icon_dir))) return NULL;
86
87    if (bname) 
88      {
89         snprintf(path, sizeof(path), "%s/%s.desktop", desktop_dir, bname);
90         desktop = efreet_desktop_empty_new(path);
91      }
92    else
93      {
94         int i;
95         
96         for (i = 1; i < 65536; i++)
97           {
98              snprintf(path, sizeof(path), "%s/_new_app-%i.desktop",
99                       desktop_dir, i);
100              if (!ecore_file_exists(path))
101                {
102                   desktop = efreet_desktop_empty_new(path);
103                   break;
104                }
105           }
106         if (!desktop)
107           {
108              snprintf(path, sizeof(path), "%s/_rename_me-%i.desktop",
109                       desktop_dir, (int)ecore_time_get());
110              desktop = efreet_desktop_empty_new(NULL);
111           }
112      }
113
114    if (!desktop)
115      {
116         //XXX out of memory?
117         return NULL;
118      }
119    if (bclass) desktop->name = strdup(bclass);
120    else if (bname) desktop->name = strdup(bname);
121    else if (btitle) desktop->name = strdup(btitle);
122    
123    if (btitle) desktop->comment = strdup(btitle);
124    
125    if (bclass) desktop->startup_wm_class = strdup(bclass);
126    if (bd->client.icccm.command.argc > 0)
127      // FIXME this should concat the entire argv array together
128      desktop->exec = strdup(bd->client.icccm.command.argv[0]);
129    else if (bname)
130      desktop->exec = strdup(bname); 
131
132 // disable this   
133 //   if (bd->client.netwm.startup_id > 0) desktop->startup_notify = 1;
134    if (bd->client.netwm.icons)
135      {
136         /* FIXME
137          * - Find the icon with the best size
138          * - Should use mkstemp
139          */
140         snprintf(path, sizeof(path), "%s/%s-%.6f.png", icon_dir, bname, ecore_time_get());
141         if (e_util_icon_save(&(bd->client.netwm.icons[0]), path))
142           desktop->icon = strdup(path);
143         else
144           fprintf(stderr, "Could not save file from ARGB: %s\n", path);
145      }
146    return desktop;
147 }
148
149 EAPI E_Desktop_Edit *
150 e_desktop_border_edit(E_Container *con, E_Border *bd)
151 {
152    E_Desktop_Edit *editor;
153    int new_desktop = 0;
154
155    if (!con) return NULL;
156    editor = E_OBJECT_ALLOC(E_Desktop_Edit, E_DESKTOP_EDIT_TYPE, _e_desktop_edit_free);
157    if (!editor) return NULL;
158    if (bd->desktop)
159      editor->desktop = bd->desktop;
160
161    /* the border does not yet have a desktop entry. add one and pre-populate
162       it with values from the border */
163    if (!editor->desktop)
164      {
165         editor->desktop = e_desktop_border_create(bd);
166         if ((editor->desktop) && (editor->desktop->icon))
167           editor->tmp_image_path = strdup(editor->desktop->icon);
168         new_desktop = 1;
169      }
170
171 #if 0
172    if ((!bname) && (!bclass))
173      {
174         e_util_dialog_show(_("Incomplete Window Properties"),
175                            _("The window you are creating an icon for<br>"
176                              "does not contain window name and class<br>"
177                              "properties, so the needed properties for<br>"
178                              "the icon so that it will be used for this<br>"
179                              "window cannot be guessed. You will need to<br>"
180                              "use the window title instead. This will only<br>"
181                              "work if the window title is the same at<br>"
182                              "the time the window starts up, and does not<br>"
183                              "change."));
184      }
185 #endif 
186    if (!_e_desktop_edit_view_create(editor, con))
187      {
188         e_object_del(E_OBJECT(editor));
189         editor = NULL;
190      }
191    else 
192         e_config_dialog_changed_set(editor->cfd, new_desktop);
193
194    return editor;
195 }
196
197 EAPI E_Desktop_Edit *
198 e_desktop_edit(E_Container *con, Efreet_Desktop *desktop)
199 {
200    E_Desktop_Edit *editor;
201
202    if (!con) return NULL;
203    editor = E_OBJECT_ALLOC(E_Desktop_Edit, E_DESKTOP_EDIT_TYPE, _e_desktop_edit_free);
204    if (!editor) return NULL;
205    if (desktop) editor->desktop = desktop;
206    if (!_e_desktop_edit_view_create(editor, con))
207      {
208         e_object_del(E_OBJECT(editor));
209         editor = NULL;
210      }
211    return editor;
212 }
213
214 static int
215 _e_desktop_edit_view_create(E_Desktop_Edit *editor, E_Container *con)
216 {
217    E_Config_Dialog_View *v;
218
219    v = E_NEW(E_Config_Dialog_View, 1);
220    if (!v) return 0;
221
222    /* view methods */
223    v->create_cfdata           = _e_desktop_edit_create_data;
224    v->free_cfdata             = _e_desktop_edit_free_data;
225    v->basic.apply_cfdata      = _e_desktop_edit_basic_apply_data;
226    v->basic.create_widgets    = _e_desktop_edit_basic_create_widgets;
227    v->basic.check_changed     = _e_desktop_edit_basic_check_changed;
228
229    editor->cfd = 
230      e_config_dialog_new(con, _("Desktop Entry Editor"), "E", 
231                          "applications/new_application",
232                          "preferences-applications", 0, v, editor);
233    
234    if (!editor->cfd)
235      {
236         E_FREE(v);
237         return 0;
238      }
239    
240    return 1;
241 }
242
243 /* local subsystem functions */
244 static void
245 _e_desktop_edit_free(E_Desktop_Edit *editor)
246 {
247    if (!editor) return;
248    E_OBJECT_CHECK(editor);
249    E_OBJECT_TYPE_CHECK(editor, E_EAP_EDIT_TYPE);
250
251    IFFREE(editor->tmp_image_path);
252    E_FREE(editor);
253 }
254
255 /**
256  * Populates the config dialog's data from the .desktop file passed in 
257  */
258 static void *
259 _e_desktop_edit_create_data(E_Config_Dialog *cfd)
260 {
261    E_Config_Dialog_Data *cfdata;
262    Efreet_Desktop *desktop = NULL; 
263    char path[PATH_MAX];
264
265    cfdata = E_NEW(E_Config_Dialog_Data, 1);
266    if (!cfdata) return NULL;
267    cfdata->editor = cfd->data;
268
269    /* 
270     * If we can't write to the file on it's current location,
271     * we always save to the user's applications dir.
272     * If the file is already there, then edit it directly. Otherwise, create
273     * a new empty desktop entry there. 
274     *
275     * cfdata->editor->desktop is the the desktop passed in
276     * cfdata->desktop is the desktop to save
277     * desktop is the desktop to load
278     */
279    path[0] = '\0';
280    if (cfdata->editor->desktop) 
281      {
282         char dir[PATH_MAX];
283         const char *file;
284
285         if (ecore_file_can_write (cfdata->editor->desktop->orig_path))
286           cfdata->desktop = efreet_desktop_uncached_new(cfdata->editor->desktop->orig_path);
287         else
288           {
289              snprintf(dir, sizeof(dir), "%s/applications", efreet_data_home_get());
290              if (!strncmp(dir, cfdata->editor->desktop->orig_path, strlen(dir)))
291                cfdata->desktop = efreet_desktop_uncached_new(cfdata->editor->desktop->orig_path);
292              else
293                {
294                   /* file not in user's dir, so create new desktop that points there */
295                   if (!ecore_file_exists(dir)) ecore_file_mkdir(dir);
296                   file = ecore_file_file_get(cfdata->editor->desktop->orig_path);
297                   snprintf(path, sizeof(path), "%s/%s", dir, file);
298                   /*
299                    * if a file already exists in the user dir with this name, we
300                    * fetch the pointer to it, so the caches stay consistent (this
301                    * probably will never return non null, since the ui shouldn't
302                    * provide a means to edit a file in a system dir when one 
303                    * exists in the user's
304                    */
305                   cfdata->desktop = efreet_desktop_uncached_new(path);
306                }
307           }
308         desktop = cfdata->editor->desktop;
309      }
310
311    if (!cfdata->desktop)
312         cfdata->desktop = efreet_desktop_empty_new(path);
313
314    if (!desktop) desktop = cfdata->desktop;
315
316    IFDUP(desktop->name, cfdata->name);
317    IFDUP(desktop->generic_name, cfdata->generic_name);
318    IFDUP(desktop->comment, cfdata->comment);
319    IFDUP(desktop->exec, cfdata->exec);
320    IFDUP(desktop->try_exec, cfdata->try_exec);
321    IFDUP(desktop->url, cfdata->url);
322    IFDUP(desktop->startup_wm_class, cfdata->startup_wm_class);
323    IFDUP(desktop->orig_path, cfdata->orig_path);
324
325    if (desktop->categories)
326      cfdata->categories = efreet_desktop_string_list_join(desktop->categories);
327    if (desktop->mime_types)
328      cfdata->mimes = efreet_desktop_string_list_join(desktop->mime_types);
329    
330    IFDUP(desktop->icon, cfdata->icon);
331
332    cfdata->startup_notify = desktop->startup_notify;
333    cfdata->terminal = desktop->terminal;
334    cfdata->show_in_menus = !desktop->no_display;
335
336    if (cfdata->exec && *cfdata->exec)
337      cfdata->type = 0;
338    else if (cfdata->url && *cfdata->url)
339      cfdata->type = 1;
340
341    return cfdata;
342 }
343
344 /**
345  * Frees the config dialog data
346  */
347 static void
348 _e_desktop_edit_free_data(E_Config_Dialog *cfd __UNUSED__, E_Config_Dialog_Data *cfdata)
349 {
350    if (cfdata->editor->tmp_image_path) 
351      {
352         if ((!cfdata->desktop) || (!cfdata->editor->saved) || 
353             (!cfdata->desktop->icon) ||
354             (strcmp(cfdata->editor->tmp_image_path, cfdata->desktop->icon)))
355           {
356              ecore_file_unlink(cfdata->editor->tmp_image_path);
357           }
358      }
359    if (cfdata->desktop) efreet_desktop_free(cfdata->desktop);
360
361    IFFREE(cfdata->name);
362    IFFREE(cfdata->generic_name);
363    IFFREE(cfdata->comment);
364    IFFREE(cfdata->exec);
365    IFFREE(cfdata->try_exec);
366    IFFREE(cfdata->url);
367    IFFREE(cfdata->startup_wm_class);
368    IFFREE(cfdata->categories);
369    IFFREE(cfdata->icon);
370    IFFREE(cfdata->mimes);
371    IFFREE(cfdata->orig_path);
372
373    if (cfdata->editor->icon_fsel_dia) 
374      e_object_del(E_OBJECT(cfdata->editor->icon_fsel_dia));
375
376    e_object_del(E_OBJECT(cfdata->editor));
377    free(cfdata);
378 }
379
380 static void
381 _e_desktop_edit_user_local_desktop_filename_generate(E_Config_Dialog_Data *cfdata, char *path)
382 {
383    char basename[PATH_MAX];
384    const char *name;
385    unsigned int i;
386    int prefix;
387
388    if ((cfdata->name) && (cfdata->name[0]))
389      name = cfdata->name;
390    else if ((cfdata->desktop) && (cfdata->desktop->name) &&
391             (cfdata->desktop->name[0]))
392      name = cfdata->name;
393    else
394      name = NULL;
395
396    if (name)
397      {
398         const char *s = name;
399         for (i = 0; i < sizeof(basename) && s[i]; i++)
400           {
401              if (isalnum(s[i]))
402                basename[i] = s[i];
403              else
404                basename[i] = '_';
405           }
406         basename[i] = '\0';
407      }
408    else
409      eina_strlcpy(basename, "unnamed_desktop", sizeof(basename));
410
411    i = snprintf(path, PATH_MAX, "%s/applications/%s.desktop",
412                 efreet_data_home_get(), basename);
413    if (i >= PATH_MAX)
414      {
415         path[0] = '\0';
416         return;
417      }
418    prefix = i - (sizeof(".desktop") - 1);
419
420    for (i = 0; ecore_file_exists(path); i++)
421      snprintf(path + prefix, PATH_MAX - prefix, "-%u.desktop", i);
422 }
423
424 static void
425 _e_desktop_edit_update_orig_path(E_Config_Dialog_Data *cfdata)
426 {
427    const char *orig_path;
428    char path[PATH_MAX];
429
430    if ((cfdata->desktop->orig_path) && (cfdata->desktop->orig_path[0]))
431      orig_path = cfdata->desktop->orig_path;
432    else
433      {
434         _e_desktop_edit_user_local_desktop_filename_generate(cfdata, path);
435         orig_path = cfdata->orig_path = strdup(path);
436      }
437
438    if (cfdata->orig_path_entry)
439      e_widget_entry_text_set(cfdata->orig_path_entry, orig_path);
440 }
441
442 /**
443  * Apply the basic config dialog
444  */
445 static int
446 _e_desktop_edit_basic_apply_data(E_Config_Dialog *cfd __UNUSED__, E_Config_Dialog_Data *cfdata)
447 {
448    E_Desktop_Edit *editor;
449    char *str;
450
451    editor = cfdata->editor;
452
453    IFFREE(cfdata->desktop->name);
454    IFDUP(cfdata->name, cfdata->desktop->name);
455    IFFREE(cfdata->desktop->comment);
456    IFDUP(cfdata->comment, cfdata->desktop->comment);
457
458    switch (cfdata->type)
459      {
460         case 1:
461           IFFREE(cfdata->desktop->url);
462           IFDUP(cfdata->url, cfdata->desktop->url);
463           break;
464         default:
465           IFFREE(cfdata->desktop->exec);
466           IFDUP(cfdata->exec, cfdata->desktop->exec);
467           IFFREE(cfdata->desktop->try_exec);
468           IFDUP(cfdata->try_exec, cfdata->desktop->try_exec);
469           break;
470      }
471
472    IFFREE(cfdata->desktop->generic_name);
473    IFDUP(cfdata->generic_name, cfdata->desktop->generic_name);
474    IFFREE(cfdata->desktop->startup_wm_class);
475    IFDUP(cfdata->startup_wm_class, cfdata->desktop->startup_wm_class);
476
477    EINA_LIST_FREE(cfdata->desktop->categories, str)
478      eina_stringshare_del(str);
479    cfdata->desktop->categories = efreet_desktop_string_list_parse(cfdata->categories);
480
481    EINA_LIST_FREE(cfdata->desktop->mime_types, str)
482      eina_stringshare_del(str);
483    cfdata->desktop->mime_types = efreet_desktop_string_list_parse(cfdata->mimes);
484
485    IFFREE(cfdata->desktop->icon);
486    IFDUP(cfdata->icon, cfdata->desktop->icon);
487
488    cfdata->desktop->startup_notify = cfdata->startup_notify;
489    cfdata->desktop->terminal = cfdata->terminal;
490    cfdata->desktop->no_display = !cfdata->show_in_menus;
491
492    if (cfdata->desktop->orig_path && cfdata->desktop->orig_path[0])
493      cfdata->editor->saved = efreet_desktop_save(cfdata->desktop);
494    else
495      {
496         _e_desktop_edit_update_orig_path(cfdata);
497         cfdata->editor->saved = efreet_desktop_save_as
498           (cfdata->desktop, cfdata->orig_path);
499      }
500    return 1;
501 }
502
503 static int
504 _e_desktop_edit_basic_check_changed(E_Config_Dialog *cfd __UNUSED__, E_Config_Dialog_Data *cfdata)
505 {
506    int ret;
507
508    if ((cfdata->startup_notify != cfdata->desktop->startup_notify) ||
509        (cfdata->terminal != cfdata->desktop->terminal) ||
510        (cfdata->show_in_menus != !cfdata->desktop->no_display))
511      return 1;
512
513 #define CHECK(k)                                                \
514    do                                                           \
515      {                                                          \
516         const char *__k;                                        \
517         if (cfdata->desktop->k)                                 \
518           __k = cfdata->desktop->k;                             \
519         else if ((cfdata->editor) && (cfdata->editor->desktop)) \
520           __k = cfdata->editor->desktop->k;                     \
521         else                                                    \
522           __k = NULL;                                           \
523         if ((cfdata->k && !__k) || (!cfdata->k && __k) ||       \
524             (cfdata->k && __k && strcmp(cfdata->k, __k) != 0))  \
525           return 1;                                             \
526      }                                                          \
527    while (0)
528
529    CHECK(name);
530    CHECK(exec);
531    CHECK(try_exec);
532    CHECK(url);
533    CHECK(comment);
534    CHECK(generic_name);
535    CHECK(startup_wm_class);
536    CHECK(icon);
537 #undef CHECK
538
539    ret = 0;
540
541    if (cfdata->edited_categories)
542      {
543         const char *str;
544         Eina_List *lst, *old_lst;
545
546         cfdata->edited_categories = EINA_FALSE;
547         cfdata->changed_categories = EINA_FALSE;
548
549         if (cfdata->desktop->categories)
550           old_lst = cfdata->desktop->categories;
551         else if ((cfdata->editor) && (cfdata->editor->desktop))
552           old_lst = cfdata->editor->desktop->categories;
553         else
554           old_lst = NULL;
555
556         lst = efreet_desktop_string_list_parse(cfdata->categories);
557         if (eina_list_count(lst) != eina_list_count(old_lst))
558           cfdata->changed_categories = EINA_TRUE;
559
560         EINA_LIST_FREE(lst, str)
561           {
562              if (!cfdata->changed_categories)
563                {
564                   Eina_List *n;
565                   const char *old;
566                   Eina_Bool found = EINA_FALSE;
567                   EINA_LIST_FOREACH(old_lst, n, old)
568                     {
569                        if (strcmp(str, old) == 0)
570                          {
571                             found = EINA_TRUE;
572                             break;
573                          }
574                     }
575                   if (!found)
576                     cfdata->changed_categories = EINA_TRUE;
577                }
578              eina_stringshare_del(str);
579           }
580      }
581    ret |= cfdata->changed_categories;
582
583    if (!ret)
584      {
585         if (cfdata->edited_mimes)
586           {
587              const char *str;
588              Eina_List *lst, *old_lst;
589
590              cfdata->edited_mimes = EINA_FALSE;
591              cfdata->changed_mimes = EINA_FALSE;
592
593              if (cfdata->desktop->mime_types)
594                old_lst = cfdata->desktop->mime_types;
595              else if ((cfdata->editor) && (cfdata->editor->desktop))
596                old_lst = cfdata->editor->desktop->mime_types;
597              else
598                old_lst = NULL;
599
600              lst = efreet_desktop_string_list_parse(cfdata->mimes);
601              if (eina_list_count(lst) != eina_list_count(old_lst))
602                cfdata->changed_mimes = EINA_TRUE;
603
604              EINA_LIST_FREE(lst, str)
605                {
606                   if (!cfdata->changed_mimes)
607                     {
608                        Eina_List *n;
609                        const char *old;
610                        Eina_Bool found = EINA_FALSE;
611                        EINA_LIST_FOREACH(old_lst, n, old)
612                          {
613                             if (strcmp(str, old) == 0)
614                               {
615                                  found = EINA_TRUE;
616                                  break;
617                               }
618                          }
619                        if (!found)
620                          cfdata->changed_mimes = EINA_TRUE;
621                     }
622                   eina_stringshare_del(str);
623                }
624
625           }
626         ret |= cfdata->changed_mimes;
627      }
628
629    return ret;
630 }
631
632 static void
633 _e_desktop_editor_name_changed(void *data, Evas_Object *obj __UNUSED__)
634 {
635    E_Config_Dialog_Data *cfdata = data;
636    _e_desktop_edit_update_orig_path(cfdata);
637 }
638
639 static void
640 _e_desktop_editor_categories_changed(void *data, Evas_Object *obj __UNUSED__)
641 {
642    E_Config_Dialog_Data *cfdata = data;
643    cfdata->edited_categories = EINA_TRUE;
644 }
645
646 static void
647 _e_desktop_editor_icon_entry_changed(void *data, Evas_Object *obj __UNUSED__)
648 {
649    E_Config_Dialog_Data *cfdata = data;
650    _e_desktop_editor_icon_update(cfdata);
651 }
652
653 static void
654 _e_desktop_editor_mimes_changed(void *data, Evas_Object *obj __UNUSED__)
655 {
656    E_Config_Dialog_Data *cfdata = data;
657    cfdata->edited_mimes = EINA_TRUE;
658 }
659
660 static Evas_Object *
661 _e_desktop_edit_basic_create_widgets(E_Config_Dialog *cfd __UNUSED__, Evas *evas, E_Config_Dialog_Data *cfdata)
662 {
663    E_Desktop_Edit *editor = cfdata->editor;
664    E_Radio_Group *rg;
665    Evas_Object *otb, *ol, *o, *ot;
666    Evas_Coord mw, mh;
667
668    editor->evas = evas;
669
670    otb = e_widget_toolbook_add(evas, 48 * e_scale, 48 * e_scale);
671
672    ot = e_widget_table_add(evas, 0);
673
674    o = e_widget_label_add(evas, _("Name"));
675    e_widget_table_object_append(ot, o, 0, 0, 1, 1, 1, 1, 0, 0);
676
677    o = e_widget_entry_add(evas, &(cfdata->name), NULL, NULL, NULL);
678    e_widget_size_min_get(o, &mw, &mh);
679    if (mw < 220) mw = 220;
680    e_widget_size_min_set(o, mw, mh);
681    if ((!cfdata->desktop->orig_path) || (!cfdata->desktop->orig_path[0]))
682      e_widget_on_change_hook_set(o, _e_desktop_editor_name_changed, cfdata);
683    e_widget_table_object_append(ot, o, 1, 0, 1, 1, 1, 1, 1, 0);
684
685    o = e_widget_label_add(evas, _("Comment"));
686    e_widget_table_object_append(ot, o, 0, 1, 1, 1, 1, 1, 0, 0);
687
688    o = e_widget_entry_add(evas, &(cfdata->comment), NULL, NULL, NULL);
689    e_widget_table_object_append(ot, o, 1, 1, 1, 1, 1, 1, 1, 0);
690
691    rg = e_widget_radio_group_new(&(cfdata->type));
692
693    // desktop type: application
694
695    o = e_widget_radio_add(evas, _("Application"), 0, rg);
696    e_widget_table_object_append(ot, o, 0, 2, 1, 1, 1, 1, 0, 0);
697
698    editor->entry_widget_exec = e_widget_entry_add
699      (evas, &(cfdata->exec), NULL, NULL, NULL);
700    e_widget_table_object_append(ot, editor->entry_widget_exec, 1, 2, 1, 1, 1, 1, 1, 0);
701
702    o = e_widget_button_add
703      (evas, "...", NULL, _e_desktop_editor_cb_exec_select, cfdata, editor);
704    e_widget_table_object_append(ot, o, 2, 2, 1, 1, 0, 0, 0, 0);
705
706    // desktop type: url
707    o = e_widget_radio_add(evas, _("URL"), 1, rg);
708    e_widget_table_object_append(ot, o, 0, 3, 1, 1, 1, 1, 0, 0);
709
710    editor->entry_widget_url = e_widget_entry_add
711      (evas, &(cfdata->url), NULL, NULL, NULL);
712    e_widget_table_object_append(ot, editor->entry_widget_url, 1, 3, 1, 1, 1, 1, 1, 0);
713    // FIXME: add url selection dialog (file:/etc/..)
714
715    e_widget_toolbook_page_append
716      (otb, NULL, _("Basic"), ot, 1, 0, 1, 0, 0.5, 0.0);
717
718    /* e_widget_size_min_get(ol, &mw, &mh); */
719
720    ot = e_widget_table_add(evas, 0);
721    
722    editor->img_widget = e_widget_button_add
723      (evas, "", NULL, _e_desktop_editor_cb_icon_select, cfdata, editor);
724    _e_desktop_editor_icon_update(cfdata);
725    e_widget_size_min_set(editor->img_widget, 192, 192);
726
727    e_widget_table_object_append(ot, editor->img_widget, 0, 0, 2, 1, 1, 1, 0, 0);
728
729    o = e_widget_label_add(evas, _("Icon"));
730    e_widget_table_object_append(ot, o, 0, 1, 1, 1, 1, 1, 0, 0);
731
732    o = e_widget_entry_add(evas, &(cfdata->icon), NULL, NULL, NULL);
733    cfdata->icon_entry = o;
734    e_widget_on_change_hook_set(o, _e_desktop_editor_icon_entry_changed, cfdata);
735    e_widget_table_object_append(ot, o, 1, 1, 1, 1, 1, 1, 1, 0);
736
737    e_widget_toolbook_page_append
738      (otb, NULL, _("Icon"), ot, 0, 0, 0, 0, 0.5, 0.5);
739    
740    ot = e_widget_table_add(evas, 0);
741
742    o = e_widget_label_add(evas, _("Generic Name"));
743    e_widget_table_object_append(ot, o, 0, 0, 1, 1, 1, 1, 0, 0);
744
745    o = e_widget_entry_add(evas, &(cfdata->generic_name), NULL, NULL, NULL);
746    e_widget_table_object_append(ot, o, 1, 0, 1, 1, 1, 1, 1, 0);
747
748    o = e_widget_label_add(evas, _("Window Class"));
749    e_widget_table_object_append(ot, o, 0, 1, 1, 1, 1, 1, 0, 0);
750
751    o = e_widget_entry_add(evas, &(cfdata->startup_wm_class), NULL, NULL, NULL);
752    e_widget_table_object_append(ot, o, 1, 1, 1, 1, 1, 1, 1, 0);
753
754    o = e_widget_label_add(evas, _("Categories"));
755    e_widget_table_object_append(ot, o, 0, 2, 1, 1, 1, 1, 0, 0);
756
757    o = e_widget_entry_add(evas, &(cfdata->categories), NULL, NULL, NULL);
758    e_widget_on_change_hook_set(o, _e_desktop_editor_categories_changed, cfdata);
759    e_widget_table_object_append(ot, o, 1, 2, 1, 1, 1, 1, 1, 0);
760
761    o = e_widget_label_add(evas, _("Mime Types"));
762    e_widget_table_object_append(ot, o, 0, 3, 1, 1, 1, 1, 0, 0);
763
764    o = e_widget_entry_add(evas, &(cfdata->mimes), NULL, NULL, NULL);
765    e_widget_on_change_hook_set(o, _e_desktop_editor_mimes_changed, cfdata);
766    e_widget_table_object_append(ot, o, 1, 3, 1, 1, 1, 1, 1, 0);
767
768    o = e_widget_label_add(evas, _("Desktop file"));
769    e_widget_table_object_append(ot, o, 0, 4, 1, 1, 1, 1, 0, 0);
770
771    o = e_widget_entry_add(evas, NULL, NULL, NULL, NULL);
772    e_widget_table_object_append(ot, o, 1, 4, 1, 1, 1, 1, 1, 0);
773    e_widget_disabled_set(o, 1);
774    cfdata->orig_path_entry = o;
775    _e_desktop_edit_update_orig_path(cfdata);
776
777    e_widget_toolbook_page_append
778      (otb, NULL, _("General"), ot, 1, 0, 1, 0, 0.5, 0.0);
779
780
781    ol = e_widget_list_add(evas, 0, 0);
782    o = e_widget_check_add(evas, _("Startup Notify"), &(cfdata->startup_notify));
783    e_widget_list_object_append(ol, o, 1, 0, 0.0);
784    o = e_widget_check_add(evas, _("Run in Terminal"), &(cfdata->terminal));
785    e_widget_list_object_append(ol, o, 1, 0, 0.0);
786    o = e_widget_check_add(evas, _("Show in Menus"), &(cfdata->show_in_menus));
787    e_widget_list_object_append(ol, o, 1, 0, 0.0);
788    e_widget_toolbook_page_append
789      (otb, NULL, _("Options"), ol, 1, 0, 1, 0, 0.5, 0.0);
790
791    e_widget_toolbook_page_show(otb, 0);
792
793    e_dialog_resizable_set(cfd->dia, 1);
794    e_util_win_auto_resize_fill(cfd->dia->win);
795    e_win_centered_set(cfd->dia->win, 1);
796
797    return otb;
798 }
799
800 static void
801 _e_desktop_editor_cb_icon_select(void *data1, void *data2)
802 {
803    E_Config_Dialog_Data *cfdata;
804    E_Dialog *dia;
805    Evas_Object *o;
806    Evas_Coord mw, mh;
807    E_Desktop_Edit *editor;
808    char *path = NULL;
809    const char *icon_path = NULL;
810
811    editor = data2;
812    cfdata = data1;
813
814    if (editor->icon_fsel_dia) return;
815
816    dia = e_dialog_new(cfdata->editor->cfd->con, "E", "_eap_icon_select_dialog");
817    if (!dia) return;
818    e_object_del_attach_func_set(E_OBJECT(dia), 
819                                 _e_desktop_edit_cb_icon_select_destroy);
820    e_dialog_title_set(dia, _("Select an Icon"));
821    dia->data = cfdata;
822
823    /* absolute path to icon */
824    /* XXX change this to a generic icon selector (that can do either
825     * files from a dir, or icons in the current theme */
826    if (cfdata->icon) 
827      {
828         if (ecore_file_exists(cfdata->icon))
829           icon_path = cfdata->icon;
830         else
831           icon_path = efreet_icon_path_find(e_config->icon_theme, cfdata->icon, 64);
832
833         if (icon_path)
834           path = ecore_file_dir_get(icon_path);
835      }
836
837    if (path)
838      {
839         o = e_widget_fsel_add(dia->win->evas, "/", path, NULL, NULL,
840                               _e_desktop_edit_select_cb, cfdata, 
841                               NULL, cfdata, 1);
842         free(path);
843      }
844    else
845      {
846         o = e_widget_fsel_add(dia->win->evas, "~/", "/", NULL, NULL,
847                               _e_desktop_edit_select_cb, cfdata,
848                               NULL, cfdata, 1);
849      }
850    
851    evas_object_show(o);
852    editor->icon_fsel = o;
853    e_widget_size_min_get(o, &mw, &mh);
854    e_dialog_content_set(dia, o, mw, mh);
855
856    /* buttons at the bottom */
857    e_dialog_button_add(dia, _("OK"), NULL, 
858                        _e_desktop_edit_cb_icon_select_ok, cfdata);
859    e_dialog_button_add(dia, _("Cancel"), NULL, 
860                        _e_desktop_edit_cb_icon_select_cancel, cfdata);
861    e_dialog_resizable_set(dia, 1);
862    e_win_centered_set(dia->win, 1);
863    e_dialog_show(dia);
864    editor->icon_fsel_dia = dia;
865 }
866
867 static void
868 _e_desktop_editor_cb_exec_select(void *data1, void *data2)
869 {
870    E_Config_Dialog_Data *cfdata;
871    E_Dialog *dia;
872    Evas_Object *o;
873    Evas_Coord mw, mh;
874    E_Desktop_Edit *editor;
875    char *path = NULL;
876
877    editor = data2;
878    cfdata = data1;
879
880    if (editor->exec_fsel_dia) return;
881
882    dia = e_dialog_new(cfdata->editor->cfd->con, "E", "_eap_exec_select_dialog");
883    if (!dia) return;
884    e_object_del_attach_func_set(E_OBJECT(dia), 
885                                 _e_desktop_edit_cb_exec_select_destroy);
886    e_dialog_title_set(dia, _("Select an Executable"));
887    dia->data = cfdata;
888
889    /* absolute path to exe */
890    if (cfdata->exec) 
891      {
892         path = ecore_file_dir_get(cfdata->exec);
893         if (path && !ecore_file_exists(path))
894           {
895              free(path);
896              path = NULL;
897           }
898      }
899
900    if (path)
901      {
902         o = e_widget_fsel_add(dia->win->evas, "/", path, NULL, NULL,
903                               _e_desktop_edit_select_cb, cfdata,
904                               NULL, cfdata, 1);
905         free(path);
906         path = NULL;
907      }
908    else
909      {
910         o = e_widget_fsel_add(dia->win->evas, "~/", "/", NULL, NULL,
911                               _e_desktop_edit_select_cb, cfdata,
912                               NULL, cfdata, 1);
913      }
914    
915    evas_object_show(o);
916    editor->exec_fsel = o;
917    e_widget_size_min_get(o, &mw, &mh);
918    e_dialog_content_set(dia, o, mw, mh);
919
920    /* buttons at the bottom */
921    e_dialog_button_add(dia, _("OK"), NULL, 
922                        _e_desktop_edit_cb_exec_select_ok, cfdata);
923    e_dialog_button_add(dia, _("Cancel"), NULL, 
924                        _e_desktop_edit_cb_exec_select_cancel, cfdata);
925    e_dialog_resizable_set(dia, 1);
926    e_win_centered_set(dia->win, 1);
927    e_dialog_show(dia);
928    editor->exec_fsel_dia = dia;
929 }
930
931 static void
932 _e_desktop_edit_select_cb(void *data __UNUSED__, Evas_Object *obj __UNUSED__)
933 {
934 }
935
936 static void
937 _e_desktop_edit_cb_icon_select_destroy(void *obj)
938 {
939    E_Dialog *dia = obj;
940    E_Config_Dialog_Data *cfdata = dia->data;
941
942 /* extra unref isn't needed - there is no extra ref() anywhere i saw */   
943 /*   e_object_unref(E_OBJECT(dia));*/
944    _e_desktop_edit_cb_icon_select_cancel(cfdata, NULL);
945 }
946
947 static void
948 _e_desktop_edit_cb_icon_select_ok(void *data, E_Dialog *dia)
949 {
950    E_Config_Dialog_Data *cfdata;
951    const char *file;
952
953    cfdata = data;
954    file = e_widget_fsel_selection_path_get(cfdata->editor->icon_fsel);
955
956    IFFREE(cfdata->icon);
957    IFDUP(file, cfdata->icon);
958    e_widget_entry_text_set(cfdata->icon_entry, cfdata->icon);
959
960    _e_desktop_edit_cb_icon_select_cancel(data, dia);
961 }
962
963 static void
964 _e_desktop_edit_cb_icon_select_cancel(void *data, E_Dialog *dia)
965 {
966    E_Config_Dialog_Data *cfdata;
967
968    cfdata = data;
969    if (dia) e_util_defer_object_del(E_OBJECT(dia));
970    cfdata->editor->icon_fsel_dia = NULL;
971    _e_desktop_editor_icon_update(cfdata);
972 }
973
974 static void
975 _e_desktop_editor_icon_update(E_Config_Dialog_Data *cfdata)
976 {
977    Evas_Object *o;
978
979    if (!cfdata->editor->img_widget) return;
980    o = e_util_icon_theme_icon_add(cfdata->icon, 128, cfdata->editor->evas);
981
982    /* NB this takes care of freeing any previous icon object */
983    e_widget_button_icon_set(cfdata->editor->img_widget, o);
984    e_widget_change(cfdata->editor->img_widget);
985 }
986
987 static void
988 _e_desktop_edit_cb_exec_select_destroy(void *obj)
989 {
990    E_Dialog *dia = obj;
991    E_Config_Dialog_Data *cfdata = dia->data;
992
993 /* guess it should work like _e_desktop_edit_cb_icon_select_destroy */
994 /*    e_object_unref(E_OBJECT(dia)); */
995    _e_desktop_edit_cb_exec_select_cancel(cfdata, NULL);
996 }
997
998 static void
999 _e_desktop_edit_cb_exec_select_ok(void *data, E_Dialog *dia)
1000 {
1001    E_Config_Dialog_Data *cfdata;
1002    const char *file;
1003
1004    cfdata = data;
1005    file = e_widget_fsel_selection_path_get(cfdata->editor->exec_fsel);
1006
1007    IFFREE(cfdata->exec);
1008    IFDUP(file, cfdata->exec);
1009
1010    _e_desktop_edit_cb_exec_select_cancel(data, dia);
1011 }
1012
1013 static void
1014 _e_desktop_edit_cb_exec_select_cancel(void *data, E_Dialog *dia)
1015 {
1016    E_Config_Dialog_Data *cfdata;
1017
1018    cfdata = data;
1019    if (dia) e_util_defer_object_del(E_OBJECT(dia));
1020    cfdata->editor->exec_fsel_dia = NULL;
1021    _e_desktop_editor_exec_update(cfdata);
1022 }
1023
1024 static void
1025 _e_desktop_editor_exec_update(E_Config_Dialog_Data *cfdata)
1026 {
1027    if (!cfdata->editor->entry_widget_exec) return;
1028    e_widget_entry_text_set(cfdata->editor->entry_widget_exec, cfdata->exec);
1029 }