launcher.c 22.3 KB
Newer Older
1 2
/*
 * GNOME panel launcher module.
3 4
 * (C) 1997,1998,1999,2000 The Free Software Foundation
 * (C) 2000 Eazel, Inc.
5 6 7
 *
 * Authors: Miguel de Icaza
 *          Federico Mena
8
 * CORBAized by George Lebl
Jiri (George) Lebl's avatar
Jiri (George) Lebl committed
9
 * de-CORBAized by George Lebl
10 11 12 13
 */

#include <config.h>
#include <stdio.h>
14
#include <sys/types.h>
15 16 17 18
#include <sys/stat.h>
#include <unistd.h>
#include <dirent.h>
#include <string.h>
Mark McLoughlin's avatar
Mark McLoughlin committed
19 20 21

#include <libgnome/libgnome.h>
#include <libgnomeui/libgnomeui.h>
22
#include <libgnomevfs/gnome-vfs.h>
23

Mark McLoughlin's avatar
Mark McLoughlin committed
24 25 26 27 28 29 30 31
#include "launcher.h"

#include "basep-widget.h"
#include "button-widget.h"
#include "drawer-widget.h"
#include "menu-fentry.h"
#include "menu.h"
#include "panel-util.h"
32
#include "panel-config-global.h"
Mark McLoughlin's avatar
Mark McLoughlin committed
33
#include "session.h"
34
#include "xstuff.h"
Mark McLoughlin's avatar
Mark McLoughlin committed
35

36 37
#include "gnome-desktop-item.h"
#include "gnome-ditem-edit.h"
38
#include "quick-desktop-reader.h"
39

40
#undef LAUNCHER_DEBUG
41

42
static void properties_apply (Launcher *launcher);
43

Jiri (George) Lebl's avatar
Jiri (George) Lebl committed
44
extern GtkTooltips *panel_tooltips;
45

46
extern GSList *applets;
47

48
static char *default_app_pixmap = NULL;
49

50
extern GlobalConfig global_config;
51
extern gboolean commie_mode;
52

53
enum {
54
	REVERT_BUTTON
55 56
};

57
static void
58
launch_url (Launcher *launcher)
59
{
60
	GnomeDesktopItem *item;
61 62
	const char *url;
	GError *error = NULL;
63

64 65
	g_return_if_fail (launcher != NULL);
	g_return_if_fail (launcher->ditem != NULL);
66

67
	item = launcher->ditem;
68 69 70 71 72 73 74
	url = gnome_desktop_item_get_string (item,
					     GNOME_DESKTOP_ITEM_URL);

	if (url == NULL) {
		panel_error_dialog ("no_url_dialog",
				    _("This launch icon does not "
				      "specify a url to show"));
75
		return;
76
	}
77

78 79 80 81 82
	gnome_url_show (url, &error);
	if (error != NULL) {
		panel_error_dialog ("cant_show_url_dialog",
				    _("Cannot show %s\n%s"),
				    url, error->message);
83
		g_clear_error (&error);
84 85
	}
}
86

87

88
static void
89
launch (Launcher *launcher)
90 91 92
{
	GnomeDesktopItem *item;
	GnomeDesktopItemType type;
93

94 95 96 97 98
	g_return_if_fail(launcher != NULL);
	g_return_if_fail(launcher->ditem != NULL);

	item = launcher->ditem;
	type = gnome_desktop_item_get_entry_type (item);
99

100
	if (type == GNOME_DESKTOP_ITEM_TYPE_LINK) {
101 102 103
		launch_url (launcher);
	} else {
		GError *error = NULL;
104 105 106 107
		gnome_desktop_item_launch (item,
					   NULL /* file_list */,
					   0 /* flags */,
					   &error);
108 109 110 111
		if (error != NULL) {
			panel_error_dialog ("cannot_launch_icon",
					    _("Cannot launch icon\n%s"),
					    error->message);
112
			g_clear_error (&error);
113
		}
114
	}
115 116 117
	
	if(global_config.drawer_auto_close) {
		GtkWidget *parent =
118
			PANEL_WIDGET(launcher->button->parent)->panel_parent;
119
		g_return_if_fail(parent!=NULL);
120
		if(DRAWER_IS_WIDGET(parent)) {
121 122
			BasePWidget *basep = BASEP_WIDGET(parent);
			GtkWidget *grandparent = PANEL_WIDGET(basep->panel)->master_widget->parent;
123 124
			GtkWidget *grandparentw =
				PANEL_WIDGET(grandparent)->panel_parent;
125
			drawer_widget_close_drawer (DRAWER_WIDGET (parent),
126
						    grandparentw);
127
		}
128
	}
129 130
}

131 132 133
static void
launch_cb (GtkWidget *widget, gpointer data)
{
134
	launch (data);
135 136 137 138 139 140 141 142 143 144 145 146
}

static void
drag_data_received_cb (GtkWidget        *widget,
		       GdkDragContext   *context,
		       gint              x,
		       gint              y,
		       GtkSelectionData *selection_data,
		       guint             info,
		       guint             time,
		       Launcher         *launcher)
{
147
	GError *error = NULL;
148

149 150 151 152
	gnome_desktop_item_drop_uri_list (launcher->ditem,
					  (const char *)selection_data->data,
					  0 /* flags */,
					  &error);
153 154 155 156
	if (error != NULL) {
		panel_error_dialog ("cannot_launch_icon",
				    _("Cannot launch icon\n%s"),
				    error->message);
157
		g_clear_error (&error);
158
	}
159

160
	gtk_drag_finish (context, TRUE, FALSE, time);
161 162
}

163
static void
164
destroy_launcher (GtkWidget *widget, gpointer data)
165 166
{
	Launcher *launcher = data;
167
	GtkWidget *prop_dialog = launcher->prop_dialog;
168 169 170

	launcher->prop_dialog = NULL;

171 172 173 174 175
	if (prop_dialog != NULL)
		gtk_widget_destroy (prop_dialog);
}

static void
Jiri (George) Lebl's avatar
Jiri (George) Lebl committed
176
free_launcher (gpointer data)
177 178 179
{
	Launcher *launcher = data;

180
	gnome_desktop_item_unref (launcher->ditem);
181
	launcher->ditem = NULL;
182

183
	if (launcher->revert_ditem != NULL)
184
		gnome_desktop_item_unref (launcher->revert_ditem);
185
	launcher->revert_ditem = NULL;
186

187
	g_free (launcher);
188 189
}

190
static gboolean
191 192
is_this_drop_ok (GtkWidget      *widget,
		 GdkDragContext *context)
193
{
194 195 196
	static GdkAtom  text_uri_list = GDK_NONE;
	GList           *l;
	GtkWidget       *source;
197

198
	source = gtk_drag_get_source_widget (context);
199

200
	if (source == widget)
201 202
		return FALSE;

203
	if (!(context->actions & GDK_ACTION_COPY))
204 205
		return FALSE;

206
	if (!text_uri_list)
207 208
		text_uri_list = gdk_atom_intern ("text/uri-list", FALSE);

209 210
	for (l = context->targets; l; l = l->next) {
		if (GDK_POINTER_TO_ATOM (l->data) == text_uri_list)
211 212 213
			break;
	}

214
	return l ? TRUE : FALSE;
215 216 217 218 219 220 221 222
}

static void  
drag_leave_cb(GtkWidget	       *widget,
	      GdkDragContext   *context,
	      guint             time,
	      Launcher *launcher)
{
223
	button_widget_set_dnd_highlight(BUTTON_WIDGET(widget), FALSE);
224 225 226
}


227 228 229 230 231 232 233 234
static gboolean
drag_motion_cb(GtkWidget *widget,
	       GdkDragContext *context,
	       gint x,
	       gint y,
	       guint time,
	       Launcher *launcher)
{
235
	if ( ! is_this_drop_ok (widget, context))
236
		return FALSE;
237

238 239
	gdk_drag_status (context, GDK_ACTION_COPY, time);

240
	button_widget_set_dnd_highlight(BUTTON_WIDGET(widget), TRUE);
241 242 243

	return TRUE;
}
244 245

static gboolean
246 247 248 249 250 251
drag_drop_cb (GtkWidget	        *widget,
	      GdkDragContext    *context,
	      gint               x,
	      gint               y,
	      guint              time,
	      Launcher          *launcher)
252 253 254
{
	static GdkAtom text_uri_list = 0;

255
	if ( ! is_this_drop_ok (widget, context))
256 257
		return FALSE;

258
	if (text_uri_list == 0)
259 260
		text_uri_list = gdk_atom_intern ("text/uri-list", FALSE);

261
	gtk_drag_get_data (widget, context, text_uri_list, time);
262 263 264 265

	return TRUE;
}

266 267 268 269 270
enum {
	TARGET_ICON_INTERNAL,
	TARGET_URI_LIST
};

271

272
static void  
273 274 275 276 277 278
drag_data_get_cb (GtkWidget          *widget,
		  GdkDragContext     *context,
		  GtkSelectionData   *selection_data,
		  guint               info,
		  guint               time,
		  Launcher           *launcher)
279
{
280 281
	char *uri_list;
	const char *location;
282
	
283
	g_return_if_fail (launcher != NULL);
284 285 286
	g_return_if_fail (launcher->ditem != NULL);

	location = gnome_desktop_item_get_location (launcher->ditem);
287

288
	if (location == NULL)
289
		launcher_save (launcher);
290

291
	if (info == TARGET_URI_LIST) {
292
		uri_list = g_strconcat ("file:", location, "\r\n", NULL);
293 294 295 296 297 298 299 300

		gtk_selection_data_set (selection_data,
					selection_data->target, 8, (guchar *)uri_list,
					strlen (uri_list));
		g_free(uri_list);
	} else if (info == TARGET_ICON_INTERNAL) {
		gtk_selection_data_set (selection_data,
					selection_data->target, 8,
301
					location, strlen (location));
302
	}
303 304 305
}


306

307
static Launcher *
308
create_launcher (const char *parameters, GnomeDesktopItem *ditem)
309 310
{
	Launcher *launcher;
311
        static GtkTargetEntry dnd_targets[] = {
312 313
		{ "application/x-panel-icon-internal", 0, TARGET_ICON_INTERNAL },
		{ "text/uri-list", 0, TARGET_URI_LIST }
314
	};
315

316
	if (!default_app_pixmap)
317 318
		default_app_pixmap = panel_pixmap_discovery ("gnome-unknown.png",
							     FALSE /* fallback */);
319 320 321
#ifdef LAUNCHER_DEBUG
	printf ("Creating Launcher %s\n", parameters);
#endif
322
	if (ditem == NULL) {
323
		if (parameters == NULL) {
324
			return NULL;
325
		}
326
#ifdef LAUNCHER_DEBUG
327
	printf ("Creating gnome_desktop_item_new_from_uri\n");
328 329 330 331
#endif
		ditem = gnome_desktop_item_new_from_uri (parameters,
							 0 /* flags */,
							 NULL /* error */);
332 333 334

		
		if (ditem == NULL) {
335
			gchar *entry;
336 337

			entry = gnome_program_locate_file (NULL, GNOME_FILE_DOMAIN_DATADIR, 
338
							   parameters, TRUE, NULL);
339

340
			if (!entry)
341
				return NULL;
342

343 344
			ditem = gnome_desktop_item_new_from_file (entry, 0, NULL);

345 346
			g_free (entry);
		}
347
	}
348
	if (ditem == NULL)
349 350
		return NULL; /*button is null*/

351
	launcher = g_new0 (Launcher, 1);
352

353
	launcher->info = NULL;
354
	launcher->button = NULL;
355
	launcher->dedit = NULL;
356 357
	launcher->prop_dialog = NULL;

Jiri (George) Lebl's avatar
Jiri (George) Lebl committed
358 359 360
	/* Icon/Text will be setup later */
	launcher->button = button_widget_new (NULL /* icon */,
					      -1,
361
					      LAUNCHER_POBJECT,
Jiri (George) Lebl's avatar
Jiri (George) Lebl committed
362
					      FALSE,
363
					      PANEL_ORIENT_UP,
Jiri (George) Lebl's avatar
Jiri (George) Lebl committed
364 365
					      NULL /* text */);

366 367
	gtk_widget_show (launcher->button);

368
	/*A hack since this function only pretends to work on window
369 370 371 372
	  widgets (which we actually kind of are) this will select
	  some (already selected) events on the panel instead of
	  the launcher window (where they are also selected) but
	  we don't mind*/
373
	GTK_WIDGET_UNSET_FLAGS (launcher->button, GTK_NO_WINDOW);
374 375
	gtk_drag_source_set(launcher->button,
			    GDK_BUTTON1_MASK,
376 377 378
			    dnd_targets, 2,
			    GDK_ACTION_COPY | GDK_ACTION_MOVE);
	GTK_WIDGET_SET_FLAGS (launcher->button, GTK_NO_WINDOW);
379
	
380
	/*gtk_drag_dest_set (GTK_WIDGET (launcher->button),
381
			   GTK_DEST_DEFAULT_ALL,
382
			   dnd_targets, 2,
383 384 385
			   GDK_ACTION_COPY);*/
	gtk_drag_dest_set (GTK_WIDGET (launcher->button),
			   0, NULL, 0, 0);
386

387 388
	g_signal_connect (G_OBJECT(launcher->button), "drag_data_get",
			   G_CALLBACK(drag_data_get_cb),
389
			   launcher);
390 391
	g_signal_connect (G_OBJECT(launcher->button), "drag_data_received",
			   G_CALLBACK(drag_data_received_cb),
392
			   launcher);
393 394
	g_signal_connect (G_OBJECT(launcher->button), "drag_motion",
			   G_CALLBACK(drag_motion_cb),
395
			   launcher);
396 397
	g_signal_connect (G_OBJECT(launcher->button), "drag_drop",
			   G_CALLBACK(drag_drop_cb),
398
			   launcher);
399 400
	g_signal_connect (G_OBJECT(launcher->button), "drag_leave",
			   G_CALLBACK(drag_leave_cb),
401 402
			   launcher);

403

404
	g_signal_connect (G_OBJECT(launcher->button), "clicked",
405 406
			    (GtkSignalFunc) launch_cb,
			    launcher);
407
	
408 409
	g_signal_connect (G_OBJECT(launcher->button), "destroy",
			    G_CALLBACK(destroy_launcher),
410
			    launcher);
411 412 413

	gtk_object_set_user_data(GTK_OBJECT(launcher->button), launcher);

414
	launcher->ditem = ditem;
415 416 417 418 419

	return launcher;
}

static void
Jiri (George) Lebl's avatar
Jiri (George) Lebl committed
420
setup_button (Launcher *launcher)
421
{
Jiri (George) Lebl's avatar
Jiri (George) Lebl committed
422 423 424 425 426
	const char *comment;
	const char *name;
	const char *docpath;
	char *real_docpath;
	char *str;
427
	char *icon;
428 429
	
	g_return_if_fail (launcher != NULL);
430

431 432 433 434
	name = gnome_desktop_item_get_localestring (launcher->ditem,
						    GNOME_DESKTOP_ITEM_NAME);
	comment = gnome_desktop_item_get_localestring (launcher->ditem,
						       GNOME_DESKTOP_ITEM_COMMENT);
435

Jiri (George) Lebl's avatar
Jiri (George) Lebl committed
436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458
	/* Setup tooltip */
	if (comment != NULL)
		str = g_strdup_printf ("%s\n%s", name, comment);
	else
		str = g_strdup (name);
	gtk_tooltips_set_tip (panel_tooltips, launcher->button,
			      str, NULL);
	g_free (str);

	/* Setup text */
	button_widget_set_text (BUTTON_WIDGET (launcher->button), name);

	/* Setup icon */
	icon = gnome_desktop_item_get_icon (launcher->ditem);
	if (icon == NULL ||
	    ! button_widget_set_pixmap (BUTTON_WIDGET (launcher->button),
					icon, -1))
		button_widget_set_pixmap (BUTTON_WIDGET (launcher->button),
					  default_app_pixmap, -1);

	/* Setup help */
	docpath = gnome_desktop_item_get_string (launcher->ditem,
						 "DocPath");
459 460 461

	panel_applet_remove_callback (launcher->info, "help_on_app");

Jiri (George) Lebl's avatar
Jiri (George) Lebl committed
462 463
	real_docpath = panel_gnome_kde_help_path (docpath);
	if (real_docpath != NULL) {
464 465
		char *title;

Jiri (George) Lebl's avatar
Jiri (George) Lebl committed
466
		g_free (real_docpath);
467

468
		title = g_strdup_printf (_("Help on %s Application"), name);
469

470 471 472 473
		panel_applet_add_callback (launcher->info,
					   "help_on_app",
					    GTK_STOCK_HELP,
					    title);
474 475
		g_free (title);
	}
Jiri (George) Lebl's avatar
Jiri (George) Lebl committed
476 477 478 479 480 481 482 483
}


static void
properties_apply (Launcher *launcher)
{
	char *location;

484
	/* save location */
Jiri (George) Lebl's avatar
Jiri (George) Lebl committed
485 486
	location = g_strdup (gnome_desktop_item_get_location (launcher->ditem));

487
	gnome_desktop_item_unref (launcher->ditem);
Jiri (George) Lebl's avatar
Jiri (George) Lebl committed
488 489 490 491 492 493 494 495 496 497 498

	launcher->ditem =
		gnome_ditem_edit_get_ditem (GNOME_DITEM_EDIT (launcher->dedit));
	launcher->ditem = gnome_desktop_item_copy (launcher->ditem);

	/* restore location */
	gnome_desktop_item_set_location (launcher->ditem, location);
	g_free (location);

	/* Setup the button look */
	setup_button (launcher);
499 500
}

501
static void
502
properties_close_callback(GtkWidget *widget, gpointer data)
503
{
504
	Launcher *launcher = data;
505 506

	launcher->prop_dialog = NULL;
507
	launcher->dedit = NULL;
508

509
	if (launcher->revert_ditem != NULL)
Jiri (George) Lebl's avatar
Jiri (George) Lebl committed
510
		gnome_desktop_item_unref (launcher->revert_ditem);
511
	launcher->revert_ditem = NULL;
512

513
	panel_config_sync_schedule ();
514 515
}

516
static void
517
window_response (GtkWidget *w, int response, gpointer data)
518
{
519 520
	Launcher *launcher = data;

521
	if (response == GTK_RESPONSE_HELP) {
522
		panel_show_help ("launchers", NULL);
523
	} else if (response == REVERT_BUTTON) { /* revert */
524
		gnome_ditem_edit_set_ditem (GNOME_DITEM_EDIT (launcher->dedit),
Jiri (George) Lebl's avatar
Jiri (George) Lebl committed
525
					    launcher->revert_ditem);
526
	} else {
527
		gtk_widget_destroy (w);
528 529 530 531 532 533 534 535 536 537 538
	}
}

static void
launcher_changed (GtkObject *dedit, gpointer data)
{
	Launcher *launcher = data;

	properties_apply (launcher);
}

539
static GtkWidget *
540
create_properties_dialog (Launcher *launcher)
541
{
542
	GtkWidget *dialog;
543

544
	/* watch the enum at the top of the file */
545 546 547
	dialog = gtk_dialog_new_with_buttons (_("Launcher properties"),
					      NULL /* parent */,
					      0 /* flags */,
548 549
					      GTK_STOCK_HELP,
					      GTK_RESPONSE_HELP,
550 551
					      GTK_STOCK_REVERT_TO_SAVED,
					      REVERT_BUTTON,
552 553
					      GTK_STOCK_CLOSE,
					      GTK_RESPONSE_CLOSE,
554
					      NULL);
555

Jiri (George) Lebl's avatar
Jiri (George) Lebl committed
556
	launcher->dedit = gnome_ditem_edit_new ();
557
	gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox),
Jiri (George) Lebl's avatar
Jiri (George) Lebl committed
558
			    launcher->dedit, TRUE, TRUE, 0);
559

Jiri (George) Lebl's avatar
Jiri (George) Lebl committed
560
	gtk_window_set_wmclass (GTK_WINDOW (dialog),
561
			       "launcher_properties", "Panel");
Jiri (George) Lebl's avatar
Jiri (George) Lebl committed
562
	gtk_window_set_policy (GTK_WINDOW (dialog), FALSE, FALSE, TRUE);
563
	
564
	if (launcher->revert_ditem != NULL)
Jiri (George) Lebl's avatar
Jiri (George) Lebl committed
565 566
		gnome_desktop_item_unref (launcher->revert_ditem);
	launcher->revert_ditem = gnome_desktop_item_copy (launcher->ditem);
567

568
	gnome_ditem_edit_set_ditem (GNOME_DITEM_EDIT (launcher->dedit),
Jiri (George) Lebl's avatar
Jiri (George) Lebl committed
569
				    launcher->ditem);
570

571 572
	g_signal_connect (G_OBJECT (launcher->dedit), "changed",
			    G_CALLBACK (launcher_changed),
573
			    launcher);
574

575 576
	g_signal_connect (G_OBJECT (dialog), "destroy",
			    G_CALLBACK (properties_close_callback),
577 578
			    launcher);

579
	gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_CLOSE);
580

581 582
	g_signal_connect (G_OBJECT (dialog), "response",
			    G_CALLBACK (window_response),
583
			    launcher);
584

Jiri (George) Lebl's avatar
Jiri (George) Lebl committed
585
	gnome_ditem_edit_grab_focus (GNOME_DITEM_EDIT (launcher->dedit));
586

587 588 589
	return dialog;
}

Jiri (George) Lebl's avatar
Jiri (George) Lebl committed
590
void
591
launcher_properties (Launcher *launcher)
592
{
593
	if (launcher->prop_dialog != NULL) {
594
		xstuff_window_raise_on_current_wspace (launcher->prop_dialog);
595 596 597
		return;
	}

598
	launcher->prop_dialog = create_properties_dialog (launcher);
599
	gtk_widget_show_all (launcher->prop_dialog);
600
}
601

602
Launcher *
603
load_launcher_applet_full (const char *params, GnomeDesktopItem *ditem,
604
			   PanelWidget *panel, int pos, gboolean exactpos)
605
{
606
	Launcher   *launcher;
607

608
	launcher = create_launcher (params, ditem);
609

Jiri (George) Lebl's avatar
Jiri (George) Lebl committed
610
	if (launcher == NULL)
611 612
		return NULL;

613 614 615 616
	launcher->info = panel_applet_register (launcher->button, launcher,
						free_launcher, panel, pos, 
						exactpos, APPLET_LAUNCHER);
	if (!launcher->info) {
617 618 619 620 621
		/* 
		 * Don't free launcher here, the button has 
		 * been destroyed above and the launcher 
		 * structure freed.
		 */
622 623
		return NULL;
	}
624

625
	if (!commie_mode)
626 627 628 629
		panel_applet_add_callback (launcher->info,
					   "properties",
					   GTK_STOCK_PROPERTIES,
					   _("Properties..."));
630

631
	panel_applet_add_callback (launcher->info, "help", GTK_STOCK_HELP, _("Help"));
632

Jiri (George) Lebl's avatar
Jiri (George) Lebl committed
633 634
	/* setup button according to ditem */
	setup_button (launcher);
635 636

	return launcher;
637
}
638 639

static void
640
really_add_launcher (GtkWidget *dialog, int response, gpointer data)
641
{
642
	GnomeDItemEdit *dedit = GNOME_DITEM_EDIT(data);
643 644 645
	int pos = GPOINTER_TO_INT(gtk_object_get_data(GTK_OBJECT(dialog),"pos"));
	gboolean exactpos = GPOINTER_TO_INT(gtk_object_get_data(GTK_OBJECT(dialog),"exactpos"));
	PanelWidget *panel = gtk_object_get_data(GTK_OBJECT(dialog),"panel");
646
	GnomeDesktopItem *ditem;
647
	
648
	if (response == GTK_RESPONSE_OK) {
649 650
		Launcher *launcher;

Jiri (George) Lebl's avatar
Jiri (George) Lebl committed
651 652
		ditem = gnome_ditem_edit_get_ditem (dedit);
		ditem = gnome_desktop_item_copy (ditem);
653

654
		launcher = load_launcher_applet_full (NULL, ditem, panel, pos, exactpos);
655
		if (launcher != NULL)
656
			launcher_hoard (launcher);
657

658
		panel_config_sync_schedule ();
659
	} else if (response == GTK_RESPONSE_HELP) {
660
		panel_show_help ("launchers", "LAUNCHERS");
661 662
		/* just return as we don't want to close */
		return;
663
	}
664

665
	gtk_widget_destroy (dialog);
666 667 668
}

void
669
ask_about_launcher (const char *file, PanelWidget *panel, int pos, gboolean exactpos)
670
{
671
	GtkWidget *dialog;
Jiri (George) Lebl's avatar
Jiri (George) Lebl committed
672 673
	GnomeDItemEdit *dee;
	GnomeDesktopItem *ditem;
674

675 676 677
	dialog = gtk_dialog_new_with_buttons (_("Create launcher applet"),
					      NULL /* parent */,
					      0 /* flags */,
678 679
					      GTK_STOCK_HELP,
					      GTK_RESPONSE_HELP,
680
					      GTK_STOCK_CANCEL,
681
					      GTK_RESPONSE_CANCEL,
682
					      GTK_STOCK_OK,
683
					      GTK_RESPONSE_OK,
684 685
					      NULL);

686 687 688
	gtk_window_set_wmclass (GTK_WINDOW (dialog),
				"create_launcher", "Panel");
	gtk_window_set_policy (GTK_WINDOW (dialog), FALSE, FALSE, TRUE);
689
	
Jiri (George) Lebl's avatar
Jiri (George) Lebl committed
690
	dee = GNOME_DITEM_EDIT (gnome_ditem_edit_new ());
691
	gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox),
Jiri (George) Lebl's avatar
Jiri (George) Lebl committed
692
			    GTK_WIDGET (dee),
693
			    TRUE, TRUE, GNOME_PAD_SMALL);
694

Jiri (George) Lebl's avatar
Jiri (George) Lebl committed
695 696
	ditem = gnome_desktop_item_new ();
	gnome_desktop_item_set_string (ditem, GNOME_DESKTOP_ITEM_EXEC, file);
697
	gnome_desktop_item_set_entry_type (ditem, GNOME_DESKTOP_ITEM_TYPE_APPLICATION);
Jiri (George) Lebl's avatar
Jiri (George) Lebl committed
698 699 700 701

	gnome_ditem_edit_set_ditem (dee, ditem);

	gnome_desktop_item_unref (ditem);
702
	
703 704 705 706
	gtk_object_set_data (GTK_OBJECT(dialog), "pos", GINT_TO_POINTER (pos));
	gtk_object_set_data (GTK_OBJECT(dialog), "exactpos",
			     GINT_TO_POINTER (exactpos));
	gtk_object_set_data (GTK_OBJECT (dialog), "panel", panel);
707

708 709
	g_signal_connect (G_OBJECT (dialog), "response",
			    G_CALLBACK (really_add_launcher),
710
			    dee);
711

712
	gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
713

714
	gtk_widget_show_all (dialog);
715

Jiri (George) Lebl's avatar
Jiri (George) Lebl committed
716
	gnome_ditem_edit_grab_focus (dee);
717 718
}

Jiri (George) Lebl's avatar
Jiri (George) Lebl committed
719 720 721 722 723
static void
ditem_set_icon (GnomeDesktopItem *ditem, const char *icon)
{
	if (icon != NULL &&
	    icon[0] != G_DIR_SEPARATOR) {
724
		char *full = quick_desktop_item_find_icon (icon);
Jiri (George) Lebl's avatar
Jiri (George) Lebl committed
725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741
		if (full != NULL) {
			gnome_desktop_item_set_string (ditem,
						       GNOME_DESKTOP_ITEM_ICON,
						       full);
			g_free (full);
		} else {
			gnome_desktop_item_set_string (ditem,
						       GNOME_DESKTOP_ITEM_ICON,
						       icon);
		}
	} else {
		gnome_desktop_item_set_string (ditem, GNOME_DESKTOP_ITEM_ICON,
					       icon);
	}
}


742
Launcher *
743
load_launcher_applet_from_info (const char *name, const char *comment,
Jiri (George) Lebl's avatar
Jiri (George) Lebl committed
744
				const char *exec, const char *icon,
745 746
				PanelWidget *panel, int pos,
				gboolean exactpos)
747
{
748
	GnomeDesktopItem *ditem;
749 750
	Launcher *launcher;

Jiri (George) Lebl's avatar
Jiri (George) Lebl committed
751
	ditem = gnome_desktop_item_new ();
752 753
	/* set current language and the "C" locale to this name,
	 * this is kind of evil... */
Jiri (George) Lebl's avatar
Jiri (George) Lebl committed
754 755
	gnome_desktop_item_set_string (ditem, GNOME_DESKTOP_ITEM_NAME, name);
	gnome_desktop_item_set_string (ditem, GNOME_DESKTOP_ITEM_COMMENT, comment);
756 757 758
	gnome_desktop_item_set_localestring (ditem, GNOME_DESKTOP_ITEM_NAME, name);
	gnome_desktop_item_set_localestring (ditem, GNOME_DESKTOP_ITEM_COMMENT, comment);

Jiri (George) Lebl's avatar
Jiri (George) Lebl committed
759 760
	gnome_desktop_item_set_string (ditem, GNOME_DESKTOP_ITEM_EXEC, exec);
	ditem_set_icon (ditem, icon);
761 762
	gnome_desktop_item_set_entry_type (ditem,
					   GNOME_DESKTOP_ITEM_TYPE_APPLICATION);
763

764
	launcher = load_launcher_applet_full (NULL, ditem, panel, pos, exactpos);
765 766 767
	if (launcher != NULL)
		launcher_save (launcher);

768
	panel_config_sync_schedule ();
769 770

	return launcher;
771 772
}

773
Launcher *
774 775
load_launcher_applet_from_info_url (const char *name, const char *comment,
				    const char *url, const char *icon,
776 777
				    PanelWidget *panel, int pos,
				    gboolean exactpos)
778
{
779
	GnomeDesktopItem *ditem;
780 781
	Launcher *launcher;

Jiri (George) Lebl's avatar
Jiri (George) Lebl committed
782
	ditem = gnome_desktop_item_new ();
783 784
	/* set current language and the "C" locale to this name,
	 * this is kind of evil... */
Jiri (George) Lebl's avatar
Jiri (George) Lebl committed
785
	gnome_desktop_item_set_string (ditem, GNOME_DESKTOP_ITEM_NAME, name);
786 787 788 789
	gnome_desktop_item_set_string (ditem, GNOME_DESKTOP_ITEM_COMMENT, comment);
	gnome_desktop_item_set_localestring (ditem, GNOME_DESKTOP_ITEM_NAME, name);
	gnome_desktop_item_set_localestring (ditem, GNOME_DESKTOP_ITEM_COMMENT, comment);

Jiri (George) Lebl's avatar
Jiri (George) Lebl committed
790 791
	ditem_set_icon (ditem, icon);
	gnome_desktop_item_set_string (ditem, GNOME_DESKTOP_ITEM_URL, url);
792 793
	gnome_desktop_item_set_entry_type (ditem,
					   GNOME_DESKTOP_ITEM_TYPE_LINK);
794

795
	launcher = load_launcher_applet_full (NULL, ditem, panel, pos, exactpos);
796 797 798
	if (launcher != NULL)
		launcher_save (launcher);

799
	panel_config_sync_schedule ();
800 801

	return launcher;
802
}
803

804
Launcher *
805
load_launcher_applet (const char *params, PanelWidget *panel, int pos,
806
		      gboolean exactpos)
807
{
808
	return load_launcher_applet_full (params, NULL, panel, pos, exactpos);
809 810 811
}

static char *
812
launcher_get_unique_uri (void)
813 814
{
	int rnd, word;
815
	char *uri;
816
#define NUM_OF_WORDS 12
817 818 819 820 821 822 823
	char *words[] = {
		"foo",
		"bar",
		"blah",
		"gegl",
		"frobate",
		"hadjaha",
824 825 826 827 828 829
		"greasy",
		"hammer",
		"eek",
		"larry",
		"curly",
		"moe",
830 831 832 833 834 835 836 837 838 839 840 841
		NULL};
	char *fname, *full;

	for (;;) {
		rnd = rand ();
		word = rand () % NUM_OF_WORDS;
		fname = g_strdup_printf ("%s-%010x.desktop",
					 words[word],
					 (guint)rnd);
		full = launcher_file_name (fname);
		g_free (fname);

842 843 844 845 846
		if ( ! g_file_test (full, G_FILE_TEST_EXISTS)) {
			uri = gnome_vfs_get_uri_from_local_path (full);
			g_free (full);
			return uri;
		}
847 848 849 850 851 852 853 854 855
	}

	g_assert_not_reached ();
	return NULL;
}

char *
launcher_file_name (const char *base)
{
856 857
	char *tmp, *retval;

858
	g_return_val_if_fail (base != NULL, NULL);
859 860

	tmp = gnome_util_home_file (PANEL_CONFIG_PATH "launchers");
861 862 863 864 865
	/* Make sure the launcher directory exists */
	if (!g_file_test (tmp, G_FILE_TEST_EXISTS)) {
		mkdir (tmp, 0700);
	}

866 867 868 869
	retval = g_build_filename (tmp, base, NULL);

	g_free (tmp);
	return retval;
870 871 872 873 874 875
}


void
launcher_save (Launcher *launcher)
{
876 877
	GError *error;

878
	g_return_if_fail (launcher != NULL);
879
	g_return_if_fail (launcher->ditem != NULL);
880

Jiri (George) Lebl's avatar
Jiri (George) Lebl committed
881 882
	if (gnome_desktop_item_get_location (launcher->ditem) == NULL)
		gnome_desktop_item_set_location (launcher->ditem,
883
						 launcher_get_unique_uri ());
884

885
	error = NULL;
Jiri (George) Lebl's avatar
Jiri (George) Lebl committed
886 887 888
	gnome_desktop_item_save (launcher->ditem,
				 NULL /* under */,
				 TRUE /* force */,
889 890 891 892 893 894 895 896 897
				 &error);
	if (error != NULL) {
		panel_error_dialog ("cannot_save_launcher" /* class */,
				    _("Cannot save launcher to disk, "
				      "the following error occured:\n\n"
				      "%s"),
				    error->message);
		g_clear_error (&error);
	}
898 899 900 901 902 903
}

void
launcher_hoard (Launcher *launcher)
{
	g_return_if_fail (launcher != NULL);
904
	g_return_if_fail (launcher->ditem != NULL);
905

Jiri (George) Lebl's avatar
Jiri (George) Lebl committed
906
	gnome_desktop_item_set_location (launcher->ditem, NULL);
907 908

	launcher_save (launcher);
909
}
910 911 912 913 914 915 916 917 918 919

Launcher *
find_launcher (const char *path)
{
	GSList *li;

	g_return_val_if_fail (path != NULL, NULL);

	for (li = applets; li != NULL; li = li->next) {
		AppletInfo *info = li->data;
Jiri (George) Lebl's avatar
Jiri (George) Lebl committed
920 921
		Launcher *launcher;
		const char *location;
922

Jiri (George) Lebl's avatar
Jiri (George) Lebl committed
923 924 925 926 927 928 929 930 931 932 933 934 935
		if (info->type != APPLET_LAUNCHER)
			continue;

		launcher = info->data;

		if (launcher->ditem == NULL)
			continue;

		location = gnome_desktop_item_get_location (launcher->ditem);

		if (location != NULL &&
		    strcmp (location, path) == 0)
			return launcher;
936 937 938 939
	}

	return NULL;
}