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 | |
---|
25 | static void properties_apply (Launcher *launcher); |
---|
26 | |
---|
27 | extern GtkTooltips *panel_tooltips; |
---|
28 | |
---|
29 | extern GSList *applets; |
---|
30 | extern GSList *applets_last; |
---|
31 | extern int applet_count; |
---|
32 | |
---|
33 | static char *default_app_pixmap = NULL; |
---|
34 | |
---|
35 | extern GlobalConfig global_config; |
---|
36 | extern gboolean commie_mode; |
---|
37 | |
---|
38 | extern char *merge_merge_dir; |
---|
39 | |
---|
40 | extern GSList *panels; |
---|
41 | |
---|
42 | enum { |
---|
43 | HELP_BUTTON = 0, |
---|
44 | REVERT_BUTTON, |
---|
45 | CLOSE_BUTTON |
---|
46 | }; |
---|
47 | |
---|
48 | |
---|
49 | static void |
---|
50 | launch (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 | |
---|
117 | static void |
---|
118 | launch_cb (GtkWidget *widget, gpointer data) |
---|
119 | { |
---|
120 | launch(data,0,NULL); |
---|
121 | } |
---|
122 | |
---|
123 | static void |
---|
124 | drag_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 | |
---|
156 | static void |
---|
157 | destroy_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 | |
---|
168 | static void |
---|
169 | free_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 | |
---|
183 | static gboolean |
---|
184 | is_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 | |
---|
212 | static void |
---|
213 | drag_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 | |
---|
222 | static gboolean |
---|
223 | drag_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 | |
---|
240 | static gboolean |
---|
241 | drag_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 | |
---|
261 | enum { |
---|
262 | TARGET_ICON_INTERNAL, |
---|
263 | TARGET_URI_LIST |
---|
264 | }; |
---|
265 | |
---|
266 | |
---|
267 | static void |
---|
268 | drag_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 | |
---|
301 | static Launcher * |
---|
302 | create_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 | |
---|
441 | static void |
---|
442 | properties_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 | |
---|
508 | static void |
---|
509 | properties_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 | |
---|
523 | static void |
---|
524 | window_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 | |
---|
538 | static void |
---|
539 | launcher_changed (GtkObject *dedit, gpointer data) |
---|
540 | { |
---|
541 | Launcher *launcher = data; |
---|
542 | |
---|
543 | properties_apply (launcher); |
---|
544 | } |
---|
545 | |
---|
546 | static GtkWidget * |
---|
547 | create_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 | |
---|
634 | void |
---|
635 | launcher_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 | |
---|
648 | Launcher * |
---|
649 | load_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 | |
---|
704 | static void |
---|
705 | really_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 | |
---|
736 | void |
---|
737 | ask_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 | |
---|
811 | Launcher * |
---|
812 | load_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 | |
---|
842 | Launcher * |
---|
843 | load_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 | |
---|
874 | Launcher * |
---|
875 | load_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 */ |
---|
883 | static void |
---|
884 | convert_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 | |
---|
910 | static char * |
---|
911 | launcher_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 | |
---|
948 | char * |
---|
949 | launcher_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 | |
---|
966 | void |
---|
967 | launcher_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 | |
---|
981 | void |
---|
982 | launcher_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 | |
---|
995 | Launcher * |
---|
996 | find_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 | } |
---|