source: trunk/third/gnome-core/panel/launcher.c @ 17152

Revision 17152, 24.5 KB checked in by ghudson, 23 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r17151, which included commits to RCS files with non-trunk default branches.
Line 
1/*
2 * GNOME panel launcher module.
3 * (C) 1997,1998,1999,2000 The Free Software Foundation
4 * (C) 2000 Eazel, Inc.
5 *
6 * Authors: Miguel de Icaza
7 *          Federico Mena
8 * CORBAized by George Lebl
9 * de-CORBAized by George Lebl
10 */
11
12#include <config.h>
13#include <stdio.h>
14#include <sys/types.h>
15#include <sys/stat.h>
16#include <unistd.h>
17#include <dirent.h>
18#include <string.h>
19#include <gnome.h>
20
21#include "panel-include.h"
22
23#include "icon-entry-hack.h"
24
25static void properties_apply (Launcher *launcher);
26
27extern GtkTooltips *panel_tooltips;
28
29extern GSList *applets;
30extern GSList *applets_last;
31extern int applet_count;
32
33static char *default_app_pixmap = NULL;
34
35extern GlobalConfig global_config;
36extern gboolean commie_mode;
37
38extern char *merge_merge_dir;
39
40extern GSList *panels;
41
42enum {
43        HELP_BUTTON = 0,
44        REVERT_BUTTON,
45        CLOSE_BUTTON
46};
47
48
49static void
50launch (Launcher *launcher, int argc, char *argv[])
51{
52        GnomeDesktopEntry *item;
53
54        g_return_if_fail(launcher != NULL);
55        g_return_if_fail(launcher->dentry != NULL);
56
57        item = launcher->dentry;
58       
59        if(!item->exec) {
60                GtkWidget *dlg;
61                dlg = gnome_message_box_new(_("This launch icon does not "
62                                              "specify a program to run"),
63                                            GNOME_MESSAGE_BOX_ERROR,
64                                            GNOME_STOCK_BUTTON_CLOSE,
65                                            NULL);
66                gtk_window_set_wmclass(GTK_WINDOW(dlg),
67                                       "no_exec_dialog","Panel");
68                gtk_widget_show_all (dlg);
69                panel_set_dialog_layer (dlg);
70                return;
71        }
72       
73        if (item->type && strcmp (item->type, "URL") == 0) {
74                char *s;
75                s = g_strjoinv (" ",item->exec);
76                gnome_url_show (s);
77                g_free (s);
78        } else if (item->type && strcmp (item->type, "PanelApplet") == 0) {
79                char *goad_id;
80
81                goad_id = get_applet_goad_id_from_dentry (item);
82
83                if (goad_id != NULL) {
84                        load_extern_applet (goad_id, NULL,
85                                            NULL, -1,
86                                            FALSE, FALSE);
87                } else {
88                        g_warning (_("Can't get goad_id from desktop entry!"));
89                }
90
91                g_free (goad_id);
92        } else {
93                char *curdir = g_get_current_dir ();
94                chdir (g_get_home_dir ());
95
96                gnome_desktop_entry_launch_with_args (item, argc, argv);
97
98                chdir (curdir);
99                g_free (curdir);
100        }
101       
102        if(global_config.drawer_auto_close) {
103                GtkWidget *parent =
104                        PANEL_WIDGET(launcher->button->parent)->panel_parent;
105                g_return_if_fail(parent!=NULL);
106                if(IS_DRAWER_WIDGET(parent)) {
107                        BasePWidget *basep = BASEP_WIDGET(parent);
108                        GtkWidget *grandparent = PANEL_WIDGET(basep->panel)->master_widget->parent;
109                        GtkWidget *grandparentw =
110                                PANEL_WIDGET(grandparent)->panel_parent;
111                        drawer_widget_close_drawer (DRAWER_WIDGET (parent),
112                                                    grandparentw);
113                }
114        }
115}
116
117static void
118launch_cb (GtkWidget *widget, gpointer data)
119{
120        launch(data,0,NULL);
121}
122
123static void
124drag_data_received_cb (GtkWidget        *widget,
125                       GdkDragContext   *context,
126                       gint              x,
127                       gint              y,
128                       GtkSelectionData *selection_data,
129                       guint             info,
130                       guint             time,
131                       Launcher         *launcher)
132{
133
134        GList *li, *files;
135        int argc;
136        char **argv;
137        int i;
138
139        g_return_if_fail(launcher!=NULL);
140
141        files = gnome_uri_list_extract_filenames((char *)selection_data->data);
142        argc = g_list_length(files);
143        argv = g_new(char *,argc+1);
144        argv[argc] = NULL;
145
146        for(i=0,li = files; li; i++,li = g_list_next(li))
147                argv[i]=li->data;
148       
149        launch(launcher,argc,argv);
150        gnome_uri_list_free_strings (files);
151        g_free(argv);
152
153        gtk_drag_finish(context,TRUE,FALSE,time);
154}
155
156static void
157destroy_launcher(GtkWidget *widget, gpointer data)
158{
159        Launcher *launcher = data;
160        GtkWidget *prop_dialog = launcher->prop_dialog;
161
162        launcher->prop_dialog = NULL;
163
164        if (prop_dialog != NULL)
165                gtk_widget_destroy (prop_dialog);
166}
167
168static void
169free_launcher(gpointer data)
170{
171        Launcher *launcher = data;
172
173        gnome_desktop_entry_free(launcher->dentry);
174        launcher->dentry = NULL;
175
176        if (launcher->revert_dentry != NULL)
177                gnome_desktop_entry_free(launcher->revert_dentry);
178        launcher->revert_dentry = NULL;
179
180        g_free(launcher);
181}
182
183static gboolean
184is_this_drop_ok (GtkWidget *widget, GdkDragContext *context)
185{
186        static GdkAtom text_uri_list = 0;
187        GList *li;
188        GtkWidget *wid;
189
190        wid = gtk_drag_get_source_widget(context);
191
192        if(wid == widget)
193                return FALSE;
194
195        if(!(context->actions & GDK_ACTION_COPY))
196                return FALSE;
197
198        if (text_uri_list == 0)
199                text_uri_list = gdk_atom_intern ("text/uri-list", FALSE);
200
201        for (li = context->targets; li; li = li->next) {
202                if (GPOINTER_TO_INT (li->data) == text_uri_list)
203                        break;
204        }
205        /* if we haven't found it */
206        if (li == NULL)
207                return FALSE;
208
209        return TRUE;
210}
211
212static void 
213drag_leave_cb(GtkWidget        *widget,
214              GdkDragContext   *context,
215              guint             time,
216              Launcher *launcher)
217{
218        button_widget_set_dnd_highlight(BUTTON_WIDGET(widget), FALSE);
219}
220
221
222static gboolean
223drag_motion_cb(GtkWidget *widget,
224               GdkDragContext *context,
225               gint x,
226               gint y,
227               guint time,
228               Launcher *launcher)
229{
230        if ( ! is_this_drop_ok (widget, context))
231                return FALSE;
232
233        gdk_drag_status (context, GDK_ACTION_COPY, time);
234
235        button_widget_set_dnd_highlight(BUTTON_WIDGET(widget), TRUE);
236
237        return TRUE;
238}
239
240static gboolean
241drag_drop_cb (GtkWidget         *widget,
242              GdkDragContext    *context,
243              gint               x,
244              gint               y,
245              guint              time,
246              Launcher          *launcher)
247{
248        static GdkAtom text_uri_list = 0;
249
250        if ( ! is_this_drop_ok (widget, context))
251                return FALSE;
252
253        if (text_uri_list == 0)
254                text_uri_list = gdk_atom_intern ("text/uri-list", FALSE);
255
256        gtk_drag_get_data (widget, context, text_uri_list, time);
257
258        return TRUE;
259}
260
261enum {
262        TARGET_ICON_INTERNAL,
263        TARGET_URI_LIST
264};
265
266
267static void 
268drag_data_get_cb (GtkWidget          *widget,
269                  GdkDragContext     *context,
270                  GtkSelectionData   *selection_data,
271                  guint               info,
272                  guint               time,
273                  Launcher           *launcher)
274{
275        gchar *uri_list;
276       
277        g_return_if_fail (launcher != NULL);
278        g_return_if_fail (launcher->dentry != NULL);
279
280        if (launcher->dentry->location == NULL)
281                launcher_save (launcher);
282
283        if (info == TARGET_URI_LIST) {
284                uri_list = g_strconcat ("file:", launcher->dentry->location,
285                                        "\r\n", NULL);
286
287                gtk_selection_data_set (selection_data,
288                                        selection_data->target, 8, (guchar *)uri_list,
289                                        strlen (uri_list));
290                g_free(uri_list);
291        } else if (info == TARGET_ICON_INTERNAL) {
292                gtk_selection_data_set (selection_data,
293                                        selection_data->target, 8,
294                                        launcher->dentry->location,
295                                        strlen (launcher->dentry->location));
296        }
297}
298
299
300
301static Launcher *
302create_launcher (const char *parameters, GnomeDesktopEntry *dentry)
303{
304        char *icon;
305        Launcher *launcher;
306        static GtkTargetEntry dnd_targets[] = {
307                { "application/x-panel-icon-internal", 0, TARGET_ICON_INTERNAL },
308                { "text/uri-list", 0, TARGET_URI_LIST }
309        };
310
311        if (default_app_pixmap == NULL)
312                default_app_pixmap = gnome_pixmap_file ("gnome-unknown.png");
313
314        if(dentry == NULL) {
315                if (parameters == NULL) {
316                        return NULL;
317                } else if (*parameters == '/') {
318                        dentry = gnome_desktop_entry_load_unconditional (parameters);
319                } else {
320                        char *apps_par, *entry, *extension;
321
322                        if (strstr (parameters, ".desktop"))
323                                extension = NULL;
324                        else
325                                extension = ".desktop";
326
327                        apps_par = g_strconcat ("gnome/apps/", parameters,
328                                                extension, NULL);
329                        entry = gnome_datadir_file (apps_par);
330                        g_free (apps_par);
331
332                        if (entry == NULL) {
333                                /* perhaps just datadir? */
334                                entry = gnome_datadir_file (parameters);
335                        }
336
337                        if (entry == NULL && merge_merge_dir != NULL) {
338                                /* the merge dir? */
339                                entry = g_strconcat (merge_merge_dir, "/",
340                                                     parameters,
341                                                     extension, NULL);
342                                if ( ! panel_file_exists (entry)) {
343                                        g_free (entry);
344                                        entry = NULL;
345                                }
346                        }
347
348                        /* eek, not found */
349                        if (entry == NULL) {
350                                return NULL;
351                        }
352
353                        dentry = gnome_desktop_entry_load_unconditional (entry);
354                        g_free (entry);
355                }
356        }
357        if (dentry == NULL)
358                return NULL; /*button is null*/
359
360        launcher = g_new0 (Launcher, 1);
361
362        launcher->info = NULL;
363        launcher->button = NULL;
364        launcher->dedit = NULL;
365        launcher->prop_dialog = NULL;
366
367        icon = dentry->icon;
368        if (icon && *icon) {
369                /* Sigh, now we need to make them local to the gnome install */
370                if (*icon != '/') {
371                        dentry->icon = gnome_pixmap_file (icon);
372                        g_free (icon);
373                }
374                launcher->button = button_widget_new(dentry->icon,
375                                                     -1,
376                                                     LAUNCHER_TILE,
377                                                     FALSE,
378                                                     ORIENT_UP,
379                                                     dentry->name);
380        }
381        if (!launcher->button) {
382                launcher->button =
383                        button_widget_new(default_app_pixmap,-1,
384                                          LAUNCHER_TILE,
385                                          FALSE,ORIENT_UP,
386                                          _("App"));
387        }
388        gtk_widget_show (launcher->button);
389
390        /*A hack since this function only pretends to work on window
391          widgets (which we actually kind of are) this will select
392          some (already selected) events on the panel instead of
393          the launcher window (where they are also selected) but
394          we don't mind*/
395        GTK_WIDGET_UNSET_FLAGS (launcher->button, GTK_NO_WINDOW);
396        gtk_drag_source_set(launcher->button,
397                            GDK_BUTTON1_MASK,
398                            dnd_targets, 2,
399                            GDK_ACTION_COPY | GDK_ACTION_MOVE);
400        GTK_WIDGET_SET_FLAGS (launcher->button, GTK_NO_WINDOW);
401       
402        /*gtk_drag_dest_set (GTK_WIDGET (launcher->button),
403                           GTK_DEST_DEFAULT_ALL,
404                           dnd_targets, 2,
405                           GDK_ACTION_COPY);*/
406        gtk_drag_dest_set (GTK_WIDGET (launcher->button),
407                           0, NULL, 0, 0);
408
409        gtk_signal_connect(GTK_OBJECT(launcher->button), "drag_data_get",
410                           GTK_SIGNAL_FUNC(drag_data_get_cb),
411                           launcher);
412        gtk_signal_connect(GTK_OBJECT(launcher->button), "drag_data_received",
413                           GTK_SIGNAL_FUNC(drag_data_received_cb),
414                           launcher);
415        gtk_signal_connect(GTK_OBJECT(launcher->button), "drag_motion",
416                           GTK_SIGNAL_FUNC(drag_motion_cb),
417                           launcher);
418        gtk_signal_connect(GTK_OBJECT(launcher->button), "drag_drop",
419                           GTK_SIGNAL_FUNC(drag_drop_cb),
420                           launcher);
421        gtk_signal_connect(GTK_OBJECT(launcher->button), "drag_leave",
422                           GTK_SIGNAL_FUNC(drag_leave_cb),
423                           launcher);
424
425
426        gtk_signal_connect (GTK_OBJECT(launcher->button), "clicked",
427                            (GtkSignalFunc) launch_cb,
428                            launcher);
429       
430        gtk_signal_connect (GTK_OBJECT(launcher->button), "destroy",
431                            GTK_SIGNAL_FUNC(destroy_launcher),
432                            launcher);
433
434        gtk_object_set_user_data(GTK_OBJECT(launcher->button), launcher);
435
436        launcher->dentry = dentry;
437
438        return launcher;
439}
440
441static void
442properties_apply (Launcher *launcher)
443{
444        char *icon;
445        char *location;
446        char *docpath;
447
448        /* save (steal) location */
449        location = launcher->dentry->location;
450        launcher->dentry->location = NULL;
451
452        gnome_desktop_entry_free(launcher->dentry);
453
454        launcher->dentry =
455                gnome_dentry_get_dentry(GNOME_DENTRY_EDIT(launcher->dedit));
456
457        /* restore location */
458        launcher->dentry->location = location;
459
460        if (string_empty (launcher->dentry->name)) {
461                g_free (launcher->dentry->name);
462                launcher->dentry->name = g_strdup ("???");
463        }
464
465        gtk_tooltips_set_tip (panel_tooltips,launcher->button,
466                              launcher->dentry->comment,NULL);
467       
468        button_widget_set_text (BUTTON_WIDGET(launcher->button),
469                                launcher->dentry->name);
470        icon = launcher->dentry->icon;
471        if ( ! string_empty (icon)) {
472                /* Sigh, now we need to make them local to the gnome
473                   install */
474                if (*icon != '/') {
475                        launcher->dentry->icon = gnome_pixmap_file (icon);
476                        g_free (icon);
477                }
478                if(!button_widget_set_pixmap (BUTTON_WIDGET(launcher->button),
479                                              launcher->dentry->icon,
480                                              -1))
481                        button_widget_set_pixmap (BUTTON_WIDGET(launcher->button),
482                                                  default_app_pixmap,
483                                                  -1);
484        } else {
485                button_widget_set_pixmap(BUTTON_WIDGET(launcher->button),
486                                         default_app_pixmap, -1);
487        }
488
489        applet_remove_callback (launcher->info, "help_on_app");
490        docpath = panel_gnome_kde_help_path (launcher->dentry->docpath);
491        if (docpath != NULL) {
492                char *title;
493
494                g_free (docpath);
495
496                title = g_strdup_printf (_("Help on %s"),
497                                         launcher->dentry->name != NULL ?
498                                         launcher->dentry->name :
499                                         _("Application"));
500
501                applet_add_callback (launcher->info, "help_on_app",
502                                     GNOME_STOCK_PIXMAP_HELP,
503                                     title);
504                g_free (title);
505        }
506}
507
508static void
509properties_close_callback(GtkWidget *widget, gpointer data)
510{
511        Launcher *launcher = data;
512
513        launcher->prop_dialog = NULL;
514        launcher->dedit = NULL;
515
516        if (launcher->revert_dentry != NULL)
517                gnome_desktop_entry_free (launcher->revert_dentry);
518        launcher->revert_dentry = NULL;
519
520        panel_config_sync_schedule ();
521}
522
523static void
524window_clicked (GtkWidget *w, int button, gpointer data)
525{
526        Launcher *launcher = data;
527
528        if (button == HELP_BUTTON) {
529                panel_show_help ("launchers.html");
530        } else if (button == REVERT_BUTTON) { /* revert */
531                gnome_dentry_edit_set_dentry (GNOME_DENTRY_EDIT (launcher->dedit),
532                                              launcher->revert_dentry);
533        } else {
534                gnome_dialog_close (GNOME_DIALOG (w));
535        }
536}
537
538static void
539launcher_changed (GtkObject *dedit, gpointer data)
540{
541        Launcher *launcher = data;
542
543        properties_apply (launcher);
544}
545
546static GtkWidget *
547create_properties_dialog (Launcher *launcher)
548{
549        GtkWidget *dialog;
550        GtkWidget *notebook;
551        GList *types;
552
553        /* watch the enum at the top of the file */
554        dialog = gnome_dialog_new (_("Launcher properties"),
555                                   GNOME_STOCK_BUTTON_HELP,
556                                   _("Revert"),
557                                   GNOME_STOCK_BUTTON_CLOSE,
558                                   NULL);
559        gnome_dialog_set_close (GNOME_DIALOG (dialog),
560                                FALSE /* click_closes */);
561
562        notebook = gtk_notebook_new ();
563        gtk_box_pack_start (GTK_BOX (GNOME_DIALOG (dialog)->vbox),
564                            notebook, TRUE, TRUE, 0);
565
566        gtk_window_set_wmclass(GTK_WINDOW(dialog),
567                               "launcher_properties", "Panel");
568        gtk_window_set_policy(GTK_WINDOW(dialog), FALSE, FALSE, TRUE);
569       
570        launcher->dedit =
571                gnome_dentry_edit_new_notebook(GTK_NOTEBOOK(notebook));
572        hack_dentry_edit (GNOME_DENTRY_EDIT (launcher->dedit));
573       
574        types = NULL;
575        types = g_list_append (types, "Application");
576        types = g_list_append (types, "URL");
577        types = g_list_append (types, "PanelApplet");
578        gtk_combo_set_popdown_strings (GTK_COMBO (GNOME_DENTRY_EDIT (launcher->dedit)->type_combo), types);
579        g_list_free (types);
580        types = NULL;
581
582        if (launcher->revert_dentry != NULL)
583                gnome_desktop_entry_free (launcher->revert_dentry);
584        launcher->revert_dentry = gnome_desktop_entry_copy (launcher->dentry);
585
586        gnome_dentry_edit_set_dentry (GNOME_DENTRY_EDIT (launcher->dedit),
587                                      launcher->dentry);
588
589        /* This sucks, but there is no other way to do this with the current
590           GnomeDEntry API.  */
591
592#define SETUP_EDITABLE(entry_name)                                      \
593        gnome_dialog_editable_enters                                    \
594                (GNOME_DIALOG (dialog),                                 \
595                 GTK_EDITABLE (gnome_dentry_get_##entry_name##_entry    \
596                               (GNOME_DENTRY_EDIT (launcher->dedit))));
597
598        SETUP_EDITABLE (name);
599        SETUP_EDITABLE (comment);
600        SETUP_EDITABLE (exec);
601        SETUP_EDITABLE (tryexec);
602        SETUP_EDITABLE (doc);
603
604#undef SETUP_EDITABLE
605       
606        gtk_signal_connect (GTK_OBJECT (launcher->dedit), "changed",
607                            GTK_SIGNAL_FUNC (launcher_changed),
608                            launcher);
609
610        gtk_signal_connect (GTK_OBJECT (dialog), "destroy",
611                            GTK_SIGNAL_FUNC (properties_close_callback),
612                            launcher);
613
614        /* YAIKES, the problem here is that the notebook will attempt
615         * to destroy the dedit, so if we unref it in the close handler,
616         * it will be finalized by the time the notebook will destroy it,
617         * dedit is just a horrible thing */
618        gtk_signal_connect (GTK_OBJECT (launcher->dedit), "destroy",
619                            GTK_SIGNAL_FUNC (gtk_object_unref),
620                            NULL);
621
622
623        gtk_signal_connect (GTK_OBJECT (dialog), "clicked",
624                            GTK_SIGNAL_FUNC (window_clicked),
625                            launcher);
626
627        gtk_widget_grab_focus
628                (gnome_dentry_get_name_entry
629                 (GNOME_DENTRY_EDIT (launcher->dedit)));
630
631        return dialog;
632}
633
634void
635launcher_properties (Launcher *launcher)
636{
637        if (launcher->prop_dialog != NULL) {
638                gtk_widget_show_now (launcher->prop_dialog);
639                gdk_window_raise (launcher->prop_dialog->window);
640                return;
641        }
642
643        launcher->prop_dialog = create_properties_dialog (launcher);
644        gtk_widget_show_all (launcher->prop_dialog);
645        panel_set_dialog_layer (launcher->prop_dialog);
646}
647
648Launcher *
649load_launcher_applet_full (const char *params, GnomeDesktopEntry *dentry,
650                           PanelWidget *panel, int pos, gboolean exactpos)
651{
652        Launcher *launcher;
653        char *docpath;
654
655        launcher = create_launcher (params, dentry);
656
657        if(!launcher)
658                return NULL;
659
660        if(!register_toy(launcher->button,
661                         launcher, free_launcher,
662                         panel, pos, exactpos,
663                         APPLET_LAUNCHER)) {
664                /* Don't free launcher here, the button has been destroyed
665                   above and the launcher structure freed */
666                return NULL;
667        }
668
669        launcher->info = applets_last->data;
670
671        gtk_tooltips_set_tip (panel_tooltips,
672                              launcher->button,
673                              launcher->dentry->comment,
674                              NULL);
675
676        if ( ! commie_mode)
677                applet_add_callback (applets_last->data,"properties",
678                                     GNOME_STOCK_MENU_PROP,
679                                     _("Properties..."));
680        applet_add_callback (applets_last->data, "help",
681                             GNOME_STOCK_PIXMAP_HELP,
682                             _("Help"));
683
684        docpath = panel_gnome_kde_help_path (launcher->dentry->docpath);
685        if (docpath != NULL) {
686                char *title;
687
688                g_free (docpath);
689
690                title = g_strdup_printf (_("Help on %s"),
691                                         launcher->dentry->name != NULL ?
692                                         launcher->dentry->name :
693                                         _("Application"));
694
695                applet_add_callback (applets_last->data, "help_on_app",
696                                     GNOME_STOCK_PIXMAP_HELP,
697                                     title);
698                g_free (title);
699        }
700
701        return launcher;
702}
703
704static void
705really_add_launcher(GtkWidget *dialog, int button, gpointer data)
706{
707        GnomeDEntryEdit *dedit = GNOME_DENTRY_EDIT(data);
708        int pos = GPOINTER_TO_INT(gtk_object_get_data(GTK_OBJECT(dialog),"pos"));
709        gboolean exactpos = GPOINTER_TO_INT(gtk_object_get_data(GTK_OBJECT(dialog),"exactpos"));
710        PanelWidget *panel = gtk_object_get_data(GTK_OBJECT(dialog),"panel");
711        GnomeDesktopEntry *dentry;
712       
713        if(button == 0/*ok*/) {
714                Launcher *launcher;
715
716                dentry = gnome_dentry_get_dentry(dedit);
717
718                if (string_empty (dentry->name)) {
719                        g_free (dentry->name);
720                        dentry->name = g_strdup ("???");
721                }
722                launcher = load_launcher_applet_full (NULL, dentry, panel, pos, exactpos);
723                if (launcher != NULL)
724                        launcher_hoard (launcher);
725
726                panel_config_sync_schedule ();
727        } else if(button == 2/*help*/) {
728                panel_show_help ("launchers.html#LAUNCHERS");
729                /* just return as we don't want to close */
730                return;
731        }
732
733        gtk_widget_destroy (dialog);
734}
735
736void
737ask_about_launcher (const char *file, PanelWidget *panel, int pos, gboolean exactpos)
738{
739        GtkWidget *dialog;
740        GtkWidget *notebook;
741        GnomeDEntryEdit *dee;
742        GList *types;
743
744        dialog = gnome_dialog_new (_("Create launcher applet"),
745                                   GNOME_STOCK_BUTTON_OK,
746                                   GNOME_STOCK_BUTTON_CANCEL,
747                                   GNOME_STOCK_BUTTON_HELP,
748                                   NULL);
749        gtk_window_set_wmclass (GTK_WINDOW (dialog),
750                                "create_launcher", "Panel");
751        gtk_window_set_policy (GTK_WINDOW (dialog), FALSE, FALSE, TRUE);
752       
753        notebook = gtk_notebook_new ();
754        gtk_box_pack_start (GTK_BOX(GNOME_DIALOG(dialog)->vbox), notebook,
755                            TRUE, TRUE, GNOME_PAD_SMALL);
756        dee = GNOME_DENTRY_EDIT(gnome_dentry_edit_new_notebook(GTK_NOTEBOOK(notebook)));
757        hack_dentry_edit (dee);
758
759        types = NULL;
760        types = g_list_append(types, "Application");
761        types = g_list_append(types, "URL");
762        types = g_list_append(types, "PanelApplet");
763        gtk_combo_set_popdown_strings(GTK_COMBO(dee->type_combo), types);
764        g_list_free(types);
765        types = NULL;
766
767#define SETUP_EDITABLE(entry_name)                                      \
768        gnome_dialog_editable_enters                                    \
769                (GNOME_DIALOG (dialog),                                 \
770                 GTK_EDITABLE (gnome_dentry_get_##entry_name##_entry (dee)));
771
772        SETUP_EDITABLE (name);
773        SETUP_EDITABLE (comment);
774        SETUP_EDITABLE (exec);
775        SETUP_EDITABLE (tryexec);
776        SETUP_EDITABLE (doc);
777
778#undef SETUP_EDITABLE
779       
780        if (file != NULL)
781                gtk_entry_set_text(GTK_ENTRY(dee->exec_entry), file);
782        gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(dee->type_combo)->entry),
783                           "Application");
784       
785       
786        gtk_object_set_data (GTK_OBJECT(dialog), "pos", GINT_TO_POINTER (pos));
787        gtk_object_set_data (GTK_OBJECT(dialog), "exactpos",
788                             GINT_TO_POINTER (exactpos));
789        gtk_object_set_data (GTK_OBJECT (dialog), "panel", panel);
790
791        gtk_signal_connect (GTK_OBJECT (dialog), "clicked",
792                            GTK_SIGNAL_FUNC (really_add_launcher),
793                            dee);
794        /* YAIKES, the problem here is that the notebook will attempt
795         * to destroy the dedit, so if we unref it in the close handler,
796         * it will be finalized by the time the notebook will destroy it,
797         * dedit is just a horrible thing */
798        gtk_signal_connect (GTK_OBJECT (dee), "destroy",
799                            GTK_SIGNAL_FUNC (gtk_object_unref), NULL);
800
801        gnome_dialog_close_hides(GNOME_DIALOG(dialog),FALSE);
802
803        gnome_dialog_set_default(GNOME_DIALOG(dialog),0);
804
805        gtk_widget_show_all (dialog);
806        panel_set_dialog_layer (dialog);
807
808        gtk_widget_grab_focus (gnome_dentry_get_name_entry (dee));
809}
810
811Launcher *
812load_launcher_applet_from_info (const char *name, const char *comment,
813                                char **exec, int execn, const char *icon,
814                                PanelWidget *panel, int pos,
815                                gboolean exactpos)
816{
817        GnomeDesktopEntry *dentry = g_new0 (GnomeDesktopEntry, 1);
818        Launcher *launcher;
819
820        dentry->name = g_strdup (name);
821        dentry->comment = g_strdup (comment);
822        dentry->exec_length = execn;
823        dentry->exec = g_copy_vector (exec);
824
825        if (icon != NULL &&
826            icon[0] != '/')
827                dentry->icon = gnome_pixmap_file (icon);
828        else
829                dentry->icon = g_strdup (icon);
830       
831        dentry->type = g_strdup ("Application");
832
833        launcher = load_launcher_applet_full (NULL, dentry, panel, pos, exactpos);
834        if (launcher != NULL)
835                launcher_save (launcher);
836
837        panel_config_sync_schedule ();
838
839        return launcher;
840}
841
842Launcher *
843load_launcher_applet_from_info_url (const char *name, const char *comment,
844                                    const char *url, const char *icon,
845                                    PanelWidget *panel, int pos,
846                                    gboolean exactpos)
847{
848        char *exec[] = { NULL, NULL };
849        GnomeDesktopEntry *dentry = g_new0 (GnomeDesktopEntry, 1);
850        Launcher *launcher;
851
852        dentry->name = g_strdup (name);
853        dentry->comment = g_strdup (comment);
854        dentry->exec_length = 1;
855        exec[0] = (char *)url;
856        dentry->exec = g_copy_vector (exec);
857
858        if (icon != NULL &&
859            icon[0] != '/')
860                dentry->icon = gnome_pixmap_file (icon);
861        else
862                dentry->icon = g_strdup (icon);
863        dentry->type = g_strdup ("URL");
864
865        launcher = load_launcher_applet_full (NULL, dentry, panel, pos, exactpos);
866        if (launcher != NULL)
867                launcher_save (launcher);
868
869        panel_config_sync_schedule ();
870
871        return launcher;
872}
873
874Launcher *
875load_launcher_applet (const char *params, PanelWidget *panel, int pos,
876                      gboolean exactpos)
877{
878        return load_launcher_applet_full (params, NULL, panel, pos, exactpos);
879}
880
881/* an imperfect conversion to gnome style, it's mostly the same but not
882 * completely, this should work for 90% of cases */
883static void
884convert_dentry_to_gnome (GnomeDesktopEntry *dentry)
885{
886        int i;
887
888        dentry->is_kde = FALSE;
889        for (i = 0; i < dentry->exec_length; i++) {
890                if (strcmp (dentry->exec[i], "\"%c\"") == 0 ||
891                    strcmp (dentry->exec[i], "%c") == 0) {
892                        g_free (dentry->exec[i]);
893                        dentry->exec[i] = g_strdup_printf ("'%s'",
894                                                           sure_string (dentry->name));
895                } else if (dentry->exec[i][0] == '%' &&
896                           strlen(dentry->exec[i]) == 2) {
897                        g_free (dentry->exec[i]);
898                        dentry->exec[i] = g_strdup ("");
899                }
900        }
901
902        if (dentry->type != NULL &&
903            strcmp (dentry->type, "KonsoleApplication") == 0) {
904                g_free (dentry->type);
905                dentry->type = g_strdup ("Application");
906                dentry->terminal = 1;
907        }
908}
909
910static char *
911launcher_get_unique_file (void)
912{
913        int rnd, word;
914#define NUM_OF_WORDS 12
915        char *words[] = {
916                "foo",
917                "bar",
918                "blah",
919                "gegl",
920                "frobate",
921                "hadjaha",
922                "greasy",
923                "hammer",
924                "eek",
925                "larry",
926                "curly",
927                "moe",
928                NULL};
929        char *fname, *full;
930
931        for (;;) {
932                rnd = rand ();
933                word = rand () % NUM_OF_WORDS;
934                fname = g_strdup_printf ("%s-%010x.desktop",
935                                         words[word],
936                                         (guint)rnd);
937                full = launcher_file_name (fname);
938                g_free (fname);
939
940                if ( ! panel_file_exists (full))
941                        return full;
942        }
943
944        g_assert_not_reached ();
945        return NULL;
946}
947
948char *
949launcher_file_name (const char *base)
950{
951#ifdef PER_SESSION_CONFIGURATION
952        /* FIXME: this needs to do stuff, or perhaps just ignore per session
953         * configs */
954#ifdef __GNUC__
955#warning FIXME: per session config must be done for launchers
956#endif
957#else
958        g_return_val_if_fail (base != NULL, NULL);
959        return g_strdup_printf ("%s/.gnome/panel.d/default/launchers/%s",
960                                g_get_home_dir (),
961                                base);
962#endif
963}
964
965
966void
967launcher_save (Launcher *launcher)
968{
969        g_return_if_fail (launcher != NULL);
970        g_return_if_fail (launcher->dentry != NULL);
971
972        if (launcher->dentry->is_kde)
973                convert_dentry_to_gnome (launcher->dentry);
974
975        if (launcher->dentry->location == NULL)
976                launcher->dentry->location = launcher_get_unique_file ();
977
978        gnome_desktop_entry_save (launcher->dentry);
979}
980
981void
982launcher_hoard (Launcher *launcher)
983{
984        g_return_if_fail (launcher != NULL);
985        g_return_if_fail (launcher->dentry != NULL);
986
987        if (launcher->dentry->location != NULL) {
988                g_free (launcher->dentry->location);
989                launcher->dentry->location = NULL;
990        }
991
992        launcher_save (launcher);
993}
994
995Launcher *
996find_launcher (const char *path)
997{
998        GSList *li;
999
1000        g_return_val_if_fail (path != NULL, NULL);
1001
1002        for (li = applets; li != NULL; li = li->next) {
1003                AppletInfo *info = li->data;
1004                if (info->type == APPLET_LAUNCHER) {
1005                        Launcher *launcher = info->data;
1006
1007                        if (launcher->dentry != NULL &&
1008                            launcher->dentry->location != NULL &&
1009                            strcmp (launcher->dentry->location, path) == 0)
1010                                return launcher;
1011                }
1012        }
1013
1014        return NULL;
1015}
Note: See TracBrowser for help on using the repository browser.