~ubuntu-branches/ubuntu/maverick/gnome-panel/maverick

1.2.5 by Josselin Mouette
Import upstream version 2.28.0
1
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
2
 *
1.1.1 by Sebastien Bacher
Import upstream version 2.13.3
3
 * Copyright (C) 2005 Vincent Untz
4
 *
5
 * This program is free software; you can redistribute it and/or
6
 * modify it under the terms of the GNU General Public License as
7
 * published by the Free Software Foundation; either version 2 of the
8
 * License, or (at your option) any later version.
9
 *
10
 * This program is distributed in the hope that it will be useful, but
11
 * WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13
 * General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU General Public License
16
 * along with this program; if not, write to the Free Software
17
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
18
 * 02111-1307, USA.
19
 *
20
 * Authors:
21
 *	Vincent Untz <vincent@vuntz.net>
22
 *
23
 * Based on code from panel-menu-bar.c
24
 */
25
26
/*
27
 * TODO:
28
 *   + drag and drop loses icon for URIs
29
 *   + drag and drop of bookmarks/network places/removable media should create
30
 *     a menu button
31
 *   + if a menu is open and gets updated, it should reappear and not just
32
 *     disappear
33
 */
34
35
#include <config.h>
36
37
#include "panel-menu-items.h"
38
39
#include <string.h>
40
#include <glib/gi18n.h>
1.1.31 by Sebastien Bacher
Import upstream version 2.21.91
41
#include <gio/gio.h>
1.1.1 by Sebastien Bacher
Import upstream version 2.13.3
42
1.1.41 by Sebastien Bacher
Import upstream version 2.23.6
43
#include <libpanel-util/panel-error.h>
1.1.40 by Sebastien Bacher
Import upstream version 2.23.5
44
#include <libpanel-util/panel-glib.h>
1.1.39 by Sebastien Bacher
Import upstream version 2.23.4
45
#include <libpanel-util/panel-keyfile.h>
1.1.48 by Sebastien Bacher
Import upstream version 2.25.3
46
#include <libpanel-util/panel-launch.h>
1.1.41 by Sebastien Bacher
Import upstream version 2.23.6
47
#include <libpanel-util/panel-show.h>
1.2.1 by Josselin Mouette
Import upstream version 2.20.3
48
1.1.1 by Sebastien Bacher
Import upstream version 2.13.3
49
#include "menu.h"
50
#include "panel-action-button.h"
51
#include "panel-globals.h"
1.1.20 by Sebastien Bacher
Import upstream version 2.19.2
52
#include "panel-icon-names.h"
1.1.1 by Sebastien Bacher
Import upstream version 2.13.3
53
#include "panel-lockdown.h"
54
#include "panel-recent.h"
55
#include "panel-stock-icons.h"
56
#include "panel-util.h"
183 by Robert Ancell
* Rebase on Debian unstable, remaining Ubuntu changes:
57
#include "applet-signaler.h"
1.1.1 by Sebastien Bacher
Import upstream version 2.13.3
58
59
#define BOOKMARKS_FILENAME      ".gtk-bookmarks"
60
#define DESKTOP_IS_HOME_DIR_DIR "/apps/nautilus/preferences"
61
#define DESKTOP_IS_HOME_DIR_KEY "/apps/nautilus/preferences/desktop_is_home_dir"
62
#define NAMES_DIR               "/apps/nautilus/desktop"
63
#define HOME_NAME_KEY           "/apps/nautilus/desktop/home_icon_name"
64
#define COMPUTER_NAME_KEY       "/apps/nautilus/desktop/computer_icon_name"
183 by Robert Ancell
* Rebase on Debian unstable, remaining Ubuntu changes:
65
#define MAX_ITEMS_OR_SUBMENU    8
1.13.1 by Sebastien Bacher
Import upstream version 2.29.5.1
66
#define MAX_BOOKMARK_ITEMS      100
1.1.1 by Sebastien Bacher
Import upstream version 2.13.3
67
1.1.40 by Sebastien Bacher
Import upstream version 2.23.5
68
G_DEFINE_TYPE (PanelPlaceMenuItem, panel_place_menu_item, GTK_TYPE_IMAGE_MENU_ITEM)
69
G_DEFINE_TYPE (PanelDesktopMenuItem, panel_desktop_menu_item, GTK_TYPE_IMAGE_MENU_ITEM)
1.1.17 by Sebastien Bacher
Import upstream version 2.17.92
70
1.1.1 by Sebastien Bacher
Import upstream version 2.13.3
71
#define PANEL_PLACE_MENU_ITEM_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), PANEL_TYPE_PLACE_MENU_ITEM, PanelPlaceMenuItemPrivate))
72
#define PANEL_DESKTOP_MENU_ITEM_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), PANEL_TYPE_DESKTOP_MENU_ITEM, PanelDesktopMenuItemPrivate))
73
74
struct _PanelPlaceMenuItemPrivate {
75
	GtkWidget   *menu;
76
	PanelWidget *panel;
77
1.1.10 by Sebastien Bacher
Import upstream version 2.15.91
78
	GtkRecentManager *recent_manager;
1.1.1 by Sebastien Bacher
Import upstream version 2.13.3
79
1.1.31 by Sebastien Bacher
Import upstream version 2.21.91
80
	GFileMonitor *bookmarks_monitor;
1.1.1 by Sebastien Bacher
Import upstream version 2.13.3
81
1.1.31 by Sebastien Bacher
Import upstream version 2.21.91
82
	GVolumeMonitor *volume_monitor;
83
	gulong       drive_changed_id;
84
	gulong       drive_connected_id;
85
	gulong       drive_disconnected_id;
86
	gulong       volume_added_id;
87
	gulong       volume_changed_id;
88
	gulong       volume_removed_id;
89
	gulong       mount_added_id;
90
	gulong       mount_changed_id;
91
	gulong       mount_removed_id;
1.1.1 by Sebastien Bacher
Import upstream version 2.13.3
92
93
	guint        use_image : 1;
94
};
95
96
struct _PanelDesktopMenuItemPrivate {
97
	GtkWidget   *menu;
98
	PanelWidget *panel;
99
100
	guint        use_image : 1;
101
	guint        append_lock_logout : 1;
102
};
103
104
static void
1.1.41 by Sebastien Bacher
Import upstream version 2.23.6
105
activate_uri_on_screen (const char *uri,
1.1.38 by Sebastien Bacher
Import upstream version 2.22.2
106
			GdkScreen  *screen)
1.1.1 by Sebastien Bacher
Import upstream version 2.13.3
107
{
1.1.41 by Sebastien Bacher
Import upstream version 2.23.6
108
	panel_show_uri (screen, uri, gtk_get_current_event_time (), NULL);
1.1.1 by Sebastien Bacher
Import upstream version 2.13.3
109
}
1.1.22 by Sebastien Bacher
Import upstream version 2.19.4
110
111
static void
1.1.38 by Sebastien Bacher
Import upstream version 2.22.2
112
activate_uri (GtkWidget  *menuitem,
1.1.41 by Sebastien Bacher
Import upstream version 2.23.6
113
	      const char *uri)
114
{
115
	activate_uri_on_screen (uri, menuitem_to_screen (menuitem));
116
}
117
118
static void
119
activate_path (GtkWidget  *menuitem,
120
	       const char *path)
121
{
122
	char *uri;
123
124
	uri = g_filename_to_uri (path, NULL, NULL);
125
	activate_uri_on_screen (uri, menuitem_to_screen (menuitem));
126
	g_free (uri);
1.1.38 by Sebastien Bacher
Import upstream version 2.22.2
127
}
128
129
static void
1.1.23 by Sebastien Bacher
Import upstream version 2.19.5
130
activate_home_uri (GtkWidget *menuitem,
131
		   gpointer   data)
132
{
1.1.41 by Sebastien Bacher
Import upstream version 2.23.6
133
	activate_path (menuitem, g_get_home_dir ());
1.1.23 by Sebastien Bacher
Import upstream version 2.19.5
134
}
135
136
static void
1.1.22 by Sebastien Bacher
Import upstream version 2.19.4
137
activate_desktop_uri (GtkWidget *menuitem,
138
		      gpointer   data)
139
{
1.1.41 by Sebastien Bacher
Import upstream version 2.23.6
140
	activate_path (menuitem,
141
		       g_get_user_special_dir (G_USER_DIRECTORY_DESKTOP));
1.1.22 by Sebastien Bacher
Import upstream version 2.19.4
142
}
1.1.1 by Sebastien Bacher
Import upstream version 2.13.3
143
 
144
static void
145
panel_menu_items_append_from_desktop (GtkWidget *menu,
146
				      char      *path,
1.2.5 by Josselin Mouette
Import upstream version 2.28.0
147
				      char      *force_name,
148
                                      gboolean   use_icon)
1.1.1 by Sebastien Bacher
Import upstream version 2.13.3
149
{
150
	GKeyFile  *key_file;
151
	gboolean   loaded;
152
	GtkWidget *item;
153
	char      *path_freeme;
154
	char      *full_path;
1.1.11 by Sebastien Bacher
Import upstream version 2.15.92
155
	char      *uri;
1.1.49 by Sebastien Bacher
Import upstream version 2.25.5
156
	char      *type;
157
	gboolean   is_application;
158
	char      *tryexec;
1.1.1 by Sebastien Bacher
Import upstream version 2.13.3
159
	char      *icon;
160
	char      *name;
161
	char      *comment;
162
163
	path_freeme = NULL;
164
165
	key_file = g_key_file_new ();
166
167
	if (g_path_is_absolute (path)) {
168
		loaded = g_key_file_load_from_file (key_file, path,
169
						    G_KEY_FILE_NONE, NULL);
170
		full_path = path;
171
	} else {
172
		char *lookup_file;
173
		char *desktop_path;
174
175
		if (!g_str_has_suffix (path, ".desktop")) {
176
			desktop_path = g_strconcat (path, ".desktop", NULL);
177
		} else {
178
			desktop_path = path;
179
		}
180
181
		lookup_file = g_strconcat ("applications", G_DIR_SEPARATOR_S,
182
					   desktop_path, NULL);
183
		loaded = g_key_file_load_from_data_dirs (key_file, lookup_file,
184
							 &path_freeme,
185
							 G_KEY_FILE_NONE,
186
							 NULL);
187
		full_path = path_freeme;
188
		g_free (lookup_file);
189
190
		if (desktop_path != path)
191
			g_free (desktop_path);
192
	}
193
194
	if (!loaded) {
195
		g_key_file_free (key_file);
196
		if (path_freeme)
197
			g_free (path_freeme);
198
		return;
199
	}
200
1.1.49 by Sebastien Bacher
Import upstream version 2.25.5
201
	/* For Application desktop files, respect TryExec */
202
	type = panel_key_file_get_string (key_file, "Type");
203
	if (!type) {
204
		g_key_file_free (key_file);
205
		if (path_freeme)
206
			g_free (path_freeme);
207
		return;
208
	}
209
	is_application = (strcmp (type, "Application") == 0);
210
	g_free (type);
211
212
	if (is_application) {
213
		tryexec = panel_key_file_get_string (key_file, "TryExec");
214
		if (tryexec) {
215
			char *prog;
216
217
			prog = g_find_program_in_path (tryexec);
218
			g_free (tryexec);
219
220
			if (!prog) {
221
				/* FIXME: we could add some file monitor magic,
222
				 * so that the menu items appears when the
223
				 * program appears, but that's really complex
224
				 * for not a huge benefit */
225
				g_key_file_free (key_file);
226
				if (path_freeme)
227
					g_free (path_freeme);
228
				return;
229
			}
230
231
			g_free (prog);
232
		}
233
	}
234
235
	/* Now, simply build the menu item */
1.1.39 by Sebastien Bacher
Import upstream version 2.23.4
236
	icon    = panel_key_file_get_locale_string (key_file, "Icon");
237
	comment = panel_key_file_get_locale_string (key_file, "Comment");
1.1.1 by Sebastien Bacher
Import upstream version 2.13.3
238
1.1.40 by Sebastien Bacher
Import upstream version 2.23.5
239
	if (PANEL_GLIB_STR_EMPTY (force_name))
1.1.39 by Sebastien Bacher
Import upstream version 2.23.4
240
		name = panel_key_file_get_locale_string (key_file, "Name");
1.1.1 by Sebastien Bacher
Import upstream version 2.13.3
241
	else
242
		name = g_strdup (force_name);
243
1.2.5 by Josselin Mouette
Import upstream version 2.28.0
244
	if (use_icon) {
245
		item = panel_image_menu_item_new ();
246
        } else {
247
		item = gtk_image_menu_item_new ();
248
	}
249
1.1.1 by Sebastien Bacher
Import upstream version 2.13.3
250
	setup_menu_item_with_icon (item, panel_menu_icon_get_size (),
1.1.32 by Sebastien Bacher
Import upstream version 2.21.92
251
				   icon, NULL, NULL, name);
1.1.1 by Sebastien Bacher
Import upstream version 2.13.3
252
1.1.23 by Sebastien Bacher
Import upstream version 2.19.5
253
	panel_util_set_tooltip_text (item, comment);
1.1.1 by Sebastien Bacher
Import upstream version 2.13.3
254
255
	gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
256
	g_signal_connect_data (item, "activate",
257
			       G_CALLBACK (panel_menu_item_activate_desktop_file),
258
			       g_strdup (full_path),
259
			       (GClosureNotify) g_free, 0);
260
	g_signal_connect (G_OBJECT (item), "button_press_event",
261
			  G_CALLBACK (menu_dummy_button_press_event), NULL);
1.1.11 by Sebastien Bacher
Import upstream version 2.15.92
262
1.1.31 by Sebastien Bacher
Import upstream version 2.21.91
263
	uri = g_filename_to_uri (full_path, NULL, NULL);
264
183 by Robert Ancell
* Rebase on Debian unstable, remaining Ubuntu changes:
265
	setup_uri_drag (item, uri, icon, GDK_ACTION_COPY);
1.1.11 by Sebastien Bacher
Import upstream version 2.15.92
266
	g_free (uri);
1.1.1 by Sebastien Bacher
Import upstream version 2.13.3
267
268
	g_key_file_free (key_file);
269
270
	if (icon)
271
		g_free (icon);
272
273
	if (name)
274
		g_free (name);
275
276
	if (comment)
277
		g_free (comment);
278
279
	if (path_freeme)
280
		g_free (path_freeme);
281
}
282
283
static void
284
panel_menu_items_append_place_item (const char *icon_name,
1.1.32 by Sebastien Bacher
Import upstream version 2.21.92
285
				    GIcon      *gicon,
1.1.1 by Sebastien Bacher
Import upstream version 2.13.3
286
				    const char *title,
287
				    const char *tooltip,
288
				    GtkWidget  *menu,
289
				    GCallback   callback,
290
				    const char *uri)
291
{
292
	GtkWidget *item;
293
	char      *user_data;
294
1.2.5 by Josselin Mouette
Import upstream version 2.28.0
295
	item = panel_image_menu_item_new ();
1.1.1 by Sebastien Bacher
Import upstream version 2.13.3
296
	setup_menu_item_with_icon (item,
297
				   panel_menu_icon_get_size (),
1.1.32 by Sebastien Bacher
Import upstream version 2.21.92
298
				   icon_name, NULL, gicon,
1.1.23 by Sebastien Bacher
Import upstream version 2.19.5
299
				   title);
1.1.1 by Sebastien Bacher
Import upstream version 2.13.3
300
1.1.23 by Sebastien Bacher
Import upstream version 2.19.5
301
	panel_util_set_tooltip_text (item, tooltip);
1.1.1 by Sebastien Bacher
Import upstream version 2.13.3
302
303
	gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
304
305
	user_data = g_strdup (uri);
306
	g_signal_connect_data (item, "activate", callback, user_data,
307
			       (GClosureNotify) g_free, 0);
308
309
	g_signal_connect (G_OBJECT (item), "button_press_event",
310
			  G_CALLBACK (menu_dummy_button_press_event), NULL);
311
183 by Robert Ancell
* Rebase on Debian unstable, remaining Ubuntu changes:
312
	if (g_str_has_prefix (uri, "file:")) /*Links only work for local files*/
313
		setup_uri_drag (item, uri, icon_name, GDK_ACTION_LINK);
1.1.1 by Sebastien Bacher
Import upstream version 2.13.3
314
}
315
1.1.4 by Daniel Holbach
Import upstream version 2.13.90
316
static GtkWidget *
317
panel_menu_items_create_action_item_full (PanelActionButtonType  action_type,
318
					  const char            *label,
319
					  const char            *tooltip)
320
{
321
	GtkWidget *item;
322
323
	if (panel_action_get_is_disabled (action_type))
324
		return NULL;
325
1.2.1 by Josselin Mouette
Import upstream version 2.20.3
326
	item = gtk_image_menu_item_new ();
1.1.4 by Daniel Holbach
Import upstream version 2.13.90
327
        setup_menu_item_with_icon (item,
328
				   panel_menu_icon_get_size (),
329
				   panel_action_get_icon_name (action_type),
1.1.32 by Sebastien Bacher
Import upstream version 2.21.92
330
				   NULL, NULL,
1.1.23 by Sebastien Bacher
Import upstream version 2.19.5
331
				   label ? label : panel_action_get_text (action_type));
1.1.4 by Daniel Holbach
Import upstream version 2.13.90
332
1.1.23 by Sebastien Bacher
Import upstream version 2.19.5
333
	panel_util_set_tooltip_text (item,
334
				     tooltip ?
335
					tooltip :
336
					panel_action_get_tooltip (action_type));
1.1.4 by Daniel Holbach
Import upstream version 2.13.90
337
338
	g_signal_connect (item, "activate",
339
			  panel_action_get_invoke (action_type), NULL);
340
	g_signal_connect (G_OBJECT (item), "button_press_event",
341
			  G_CALLBACK (menu_dummy_button_press_event), NULL);
342
	setup_internal_applet_drag (item, action_type);
343
344
	return item;
345
}
346
347
static GtkWidget *
348
panel_menu_items_create_action_item (PanelActionButtonType action_type)
349
{
350
	return panel_menu_items_create_action_item_full (action_type,
351
							 NULL, NULL);
352
}
353
1.1.1 by Sebastien Bacher
Import upstream version 2.13.3
354
static void
355
panel_place_menu_item_append_gtk_bookmarks (GtkWidget *menu)
356
{
357
	typedef struct {
1.1.21 by Fernando Ribeiro
Import upstream version 2.19.3
358
		char *full_uri;
359
		char *label;
1.1.1 by Sebastien Bacher
Import upstream version 2.13.3
360
	} PanelBookmark;
361
362
	GtkWidget   *add_menu;
363
	char        *filename;
1.13.1 by Sebastien Bacher
Import upstream version 2.29.5.1
364
	GIOChannel  *io_channel;
1.1.1 by Sebastien Bacher
Import upstream version 2.13.3
365
	GHashTable  *table;
366
	int          i;
1.13.1 by Sebastien Bacher
Import upstream version 2.29.5.1
367
	GSList      *lines = NULL;
1.1.1 by Sebastien Bacher
Import upstream version 2.13.3
368
	GSList      *add_bookmarks, *l;
369
	PanelBookmark *bookmark;
370
371
	filename = g_build_filename (g_get_home_dir (),
372
				     BOOKMARKS_FILENAME, NULL);
373
1.13.1 by Sebastien Bacher
Import upstream version 2.29.5.1
374
	io_channel = g_io_channel_new_file (filename, "r", NULL);
1.1.1 by Sebastien Bacher
Import upstream version 2.13.3
375
	g_free (filename);
376
1.13.1 by Sebastien Bacher
Import upstream version 2.29.5.1
377
	if (!io_channel)
378
		return;
379
380
	/* We use a hard limit to avoid having users shooting their
381
	 * own feet, and to avoid crashing the system if a misbehaving
382
	 * application creates a big bookmars file.
383
	 */
384
	for (i = 0; i < MAX_BOOKMARK_ITEMS; i++) {
385
		char      *contents;
386
		gsize      length;
387
		gsize      terminator_pos;
388
		GIOStatus  status;
389
390
		status = g_io_channel_read_line (io_channel, &contents, &length, &terminator_pos, NULL);
391
392
		if (status != G_IO_STATUS_NORMAL)
393
			break;
394
395
		if (length == 0)
396
			break;
397
398
		/* Clear the line terminator (\n), if any */
399
		if (terminator_pos > 0)
400
			contents[terminator_pos] = '\0';
401
402
		lines = g_slist_prepend (lines, contents);
403
	}
404
405
	g_io_channel_shutdown (io_channel, FALSE, NULL);
406
	g_io_channel_unref (io_channel);
407
408
	if (!lines)
409
		return;
410
411
	lines = g_slist_reverse (lines);
1.1.1 by Sebastien Bacher
Import upstream version 2.13.3
412
413
	table = g_hash_table_new (g_str_hash, g_str_equal);
414
	add_bookmarks = NULL;
415
1.13.1 by Sebastien Bacher
Import upstream version 2.29.5.1
416
	for (l = lines; l; l = l->next) {
417
		char *line = (char*) l->data;
418
419
		if (line[0] && !g_hash_table_lookup (table, line)) {
1.1.31 by Sebastien Bacher
Import upstream version 2.21.91
420
			GFile    *file;
421
			char     *space;
422
			char     *label;
423
			gboolean  keep;
1.1.1 by Sebastien Bacher
Import upstream version 2.13.3
424
1.13.1 by Sebastien Bacher
Import upstream version 2.29.5.1
425
			g_hash_table_insert (table, line, line);
1.1.1 by Sebastien Bacher
Import upstream version 2.13.3
426
1.13.1 by Sebastien Bacher
Import upstream version 2.29.5.1
427
			space = strchr (line, ' ');
1.1.1 by Sebastien Bacher
Import upstream version 2.13.3
428
			if (space) {
429
				*space = '\0';
430
				label = g_strdup (space + 1);
431
			} else {
432
				label = NULL;
433
			}
434
1.1.21 by Fernando Ribeiro
Import upstream version 2.19.3
435
			keep = FALSE;
436
1.13.1 by Sebastien Bacher
Import upstream version 2.29.5.1
437
			if (g_str_has_prefix (line, "x-nautilus-search:"))
1.1.21 by Fernando Ribeiro
Import upstream version 2.19.3
438
				keep = TRUE;
439
440
			if (!keep) {
1.13.1 by Sebastien Bacher
Import upstream version 2.29.5.1
441
				file = g_file_new_for_uri (line);
1.1.31 by Sebastien Bacher
Import upstream version 2.21.91
442
				keep = !g_file_is_native (file) ||
443
				       g_file_query_exists (file, NULL);
444
				g_object_unref (file);
1.1.21 by Fernando Ribeiro
Import upstream version 2.19.3
445
			}
446
447
			if (!keep) {
1.1.1 by Sebastien Bacher
Import upstream version 2.13.3
448
				if (label)
449
					g_free (label);
450
				continue;
451
			}
452
453
			bookmark = g_malloc (sizeof (PanelBookmark));
1.13.1 by Sebastien Bacher
Import upstream version 2.29.5.1
454
			bookmark->full_uri = g_strdup (line);
1.1.1 by Sebastien Bacher
Import upstream version 2.13.3
455
			bookmark->label = label;
456
			add_bookmarks = g_slist_prepend (add_bookmarks, bookmark);
457
		}
458
	}
459
460
	g_hash_table_destroy (table);
1.13.1 by Sebastien Bacher
Import upstream version 2.29.5.1
461
	g_slist_foreach (lines, (GFunc) g_free, NULL);
462
	g_slist_free (lines);
1.1.1 by Sebastien Bacher
Import upstream version 2.13.3
463
464
	add_bookmarks = g_slist_reverse (add_bookmarks);
465
466
	if (g_slist_length (add_bookmarks) <= MAX_ITEMS_OR_SUBMENU) {
467
		add_menu = menu;
468
	} else {
469
		GtkWidget *item;
470
1.2.1 by Josselin Mouette
Import upstream version 2.20.3
471
		item = gtk_image_menu_item_new ();
1.1.1 by Sebastien Bacher
Import upstream version 2.13.3
472
		setup_menu_item_with_icon (item, panel_menu_icon_get_size (),
1.1.32 by Sebastien Bacher
Import upstream version 2.21.92
473
					   PANEL_ICON_BOOKMARKS, NULL, NULL,
1.1.23 by Sebastien Bacher
Import upstream version 2.19.5
474
					   _("Bookmarks"));
1.1.1 by Sebastien Bacher
Import upstream version 2.13.3
475
476
		gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
477
		gtk_widget_show (item);
478
479
		add_menu = create_empty_menu ();
480
		gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), add_menu);
481
	}
482
483
	for (l = add_bookmarks; l; l = l->next) {
1.1.31 by Sebastien Bacher
Import upstream version 2.21.91
484
		char *display_name;
1.1.1 by Sebastien Bacher
Import upstream version 2.13.3
485
		char *tooltip;
486
		char *label;
1.1.21 by Fernando Ribeiro
Import upstream version 2.19.3
487
		char *icon;
1.1.31 by Sebastien Bacher
Import upstream version 2.21.91
488
		GFile *file;
1.13.4 by Sebastien Bacher
Import upstream version 2.29.92
489
		GIcon *gicon;
1.1.1 by Sebastien Bacher
Import upstream version 2.13.3
490
491
		bookmark = l->data;
1.1.31 by Sebastien Bacher
Import upstream version 2.21.91
492
		
493
		file = g_file_new_for_uri (bookmark->full_uri);
494
		display_name = g_file_get_parse_name (file);
495
		g_object_unref (file);
1.1.1 by Sebastien Bacher
Import upstream version 2.13.3
496
		/* Translators: %s is a URI */
1.1.31 by Sebastien Bacher
Import upstream version 2.21.91
497
		tooltip = g_strdup_printf (_("Open '%s'"), display_name);
498
		g_free (display_name);
1.1.1 by Sebastien Bacher
Import upstream version 2.13.3
499
500
		label = NULL;
501
		if (bookmark->label) {
502
			label = g_strdup (g_strstrip (bookmark->label));
503
			if (!label [0]) {
504
				g_free (label);
505
				label = NULL;
506
			}
507
		}
508
509
		if (!label) {
1.1.21 by Fernando Ribeiro
Import upstream version 2.19.3
510
			label = panel_util_get_label_for_uri (bookmark->full_uri);
511
512
			if (!label) {
513
				g_free (tooltip);
514
				g_free (bookmark->full_uri);
515
				if (bookmark->label)
516
					g_free (bookmark->label);
517
				g_free (bookmark);
518
				continue;
1.1.1 by Sebastien Bacher
Import upstream version 2.13.3
519
			}
520
		}
521
1.1.21 by Fernando Ribeiro
Import upstream version 2.19.3
522
		icon = panel_util_get_icon_for_uri (bookmark->full_uri);
1.1.32 by Sebastien Bacher
Import upstream version 2.21.92
523
		/*FIXME: we should probably get a GIcon if possible, so that we
524
		 * have customized icons for cd-rom, eg */
1.1.21 by Fernando Ribeiro
Import upstream version 2.19.3
525
		if (!icon)
526
			icon = g_strdup (PANEL_ICON_FOLDER);
527
1.13.4 by Sebastien Bacher
Import upstream version 2.29.92
528
		gicon = g_themed_icon_new_with_default_fallbacks (icon);
529
1.1.21 by Fernando Ribeiro
Import upstream version 2.19.3
530
		//FIXME: drag and drop will be broken for x-nautilus-search uris
1.13.4 by Sebastien Bacher
Import upstream version 2.29.92
531
		panel_menu_items_append_place_item (icon, gicon,
1.1.1 by Sebastien Bacher
Import upstream version 2.13.3
532
						    label,
533
						    tooltip,
534
						    add_menu,
535
						    G_CALLBACK (activate_uri),
1.1.21 by Fernando Ribeiro
Import upstream version 2.19.3
536
						    bookmark->full_uri);
1.1.1 by Sebastien Bacher
Import upstream version 2.13.3
537
1.1.21 by Fernando Ribeiro
Import upstream version 2.19.3
538
		g_free (icon);
1.13.4 by Sebastien Bacher
Import upstream version 2.29.92
539
		g_object_unref (gicon);
1.1.1 by Sebastien Bacher
Import upstream version 2.13.3
540
		g_free (tooltip);
541
		g_free (label);
1.1.21 by Fernando Ribeiro
Import upstream version 2.19.3
542
		g_free (bookmark->full_uri);
1.1.1 by Sebastien Bacher
Import upstream version 2.13.3
543
		if (bookmark->label)
544
			g_free (bookmark->label);
545
		g_free (bookmark);
546
	}
547
548
	g_slist_free (add_bookmarks);
549
}
550
551
static void
1.1.31 by Sebastien Bacher
Import upstream version 2.21.91
552
drive_poll_for_media_cb (GObject      *source_object,
553
			 GAsyncResult *res,
554
			 gpointer      user_data)
555
{
556
	GdkScreen *screen;
557
	GError    *error;
558
	char      *primary;
559
	char      *name;
560
561
	error = NULL;
562
	if (!g_drive_poll_for_media_finish (G_DRIVE (source_object),
563
					    res, &error)) {
564
		if (error->code != G_IO_ERROR_FAILED_HANDLED) {
565
			screen = GDK_SCREEN (user_data);
566
567
			name = g_drive_get_name (G_DRIVE (source_object));
568
			primary = g_strdup_printf (_("Unable to scan %s for media changes"),
569
						   name);
570
			g_free (name);
571
			panel_error_dialog (NULL, screen,
572
					    "cannot_scan_drive", TRUE,
573
					    primary, error->message);
574
			g_free (primary);
575
		}
576
		g_error_free (error);
577
	}
578
579
	//FIXME: should we mount the volume and activate the root of the new
580
	//mount?
581
}
582
583
static void
584
panel_menu_item_rescan_drive (GtkWidget *menuitem,
585
			      GDrive    *drive)
586
{
587
	g_drive_poll_for_media (drive, NULL,
588
				drive_poll_for_media_cb,
589
				menuitem_to_screen (menuitem));
590
}
591
592
static void
593
panel_menu_item_append_drive (GtkWidget *menu,
594
			      GDrive    *drive)
595
{
596
	GtkWidget *item;
597
	GIcon     *icon;
598
	char      *title;
599
	char      *tooltip;
600
601
	icon = g_drive_get_icon (drive);
602
	title = g_drive_get_name (drive);
603
1.2.5 by Josselin Mouette
Import upstream version 2.28.0
604
	item = panel_image_menu_item_new ();
1.1.31 by Sebastien Bacher
Import upstream version 2.21.91
605
	setup_menu_item_with_icon (item,
606
				   panel_menu_icon_get_size (),
1.1.32 by Sebastien Bacher
Import upstream version 2.21.92
607
				   NULL, NULL, icon,
1.1.31 by Sebastien Bacher
Import upstream version 2.21.91
608
				   title);
1.1.32 by Sebastien Bacher
Import upstream version 2.21.92
609
	g_object_unref (icon);
1.1.31 by Sebastien Bacher
Import upstream version 2.21.91
610
611
	tooltip = g_strdup_printf (_("Rescan %s"), title);
612
	panel_util_set_tooltip_text (item, tooltip);
613
	g_free (tooltip);
614
615
	g_free (title);
616
617
	gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
618
619
	g_signal_connect_data (item, "activate",
620
			       G_CALLBACK (panel_menu_item_rescan_drive),
621
			       g_object_ref (drive),
622
			       (GClosureNotify) g_object_unref, 0);
623
624
	g_signal_connect (G_OBJECT (item), "button_press_event",
625
			  G_CALLBACK (menu_dummy_button_press_event), NULL);
626
}
627
628
typedef struct {
629
	GdkScreen       *screen;
630
	GMountOperation *mount_op;
631
} PanelVolumeMountData;
632
633
static void
634
volume_mount_cb (GObject      *source_object,
635
		 GAsyncResult *res,
636
		 gpointer      user_data)
637
{
638
	PanelVolumeMountData *mount_data = user_data;
639
	GError *error;
640
641
	error = NULL;
642
	if (!g_volume_mount_finish (G_VOLUME (source_object), res, &error)) {
1.1.38 by Sebastien Bacher
Import upstream version 2.22.2
643
		char *primary;
644
		char *name;
645
1.1.31 by Sebastien Bacher
Import upstream version 2.21.91
646
		if (error->code != G_IO_ERROR_FAILED_HANDLED) {
647
			name = g_volume_get_name (G_VOLUME (source_object));
648
			primary = g_strdup_printf (_("Unable to mount %s"),
649
						   name);
650
			g_free (name);
651
652
			panel_error_dialog (NULL, mount_data->screen,
653
					    "cannot_mount_volume", TRUE,
654
					    primary, error->message);
655
			g_free (primary);
656
		}
657
		g_error_free (error);
1.1.38 by Sebastien Bacher
Import upstream version 2.22.2
658
	} else {
659
		GMount *mount;
660
		GFile  *root;
1.1.41 by Sebastien Bacher
Import upstream version 2.23.6
661
		char   *rooturi;
1.1.38 by Sebastien Bacher
Import upstream version 2.22.2
662
663
		mount = g_volume_get_mount (G_VOLUME (source_object));
664
		root = g_mount_get_root (mount);
1.1.41 by Sebastien Bacher
Import upstream version 2.23.6
665
		rooturi = g_file_get_uri (root);
666
		activate_uri_on_screen (rooturi, mount_data->screen);
1.1.38 by Sebastien Bacher
Import upstream version 2.22.2
667
		g_object_unref (mount);
668
		g_object_unref (root);
1.1.41 by Sebastien Bacher
Import upstream version 2.23.6
669
		g_free (rooturi);
1.1.31 by Sebastien Bacher
Import upstream version 2.21.91
670
	}
671
672
	g_object_unref (mount_data->mount_op);
673
	g_slice_free (PanelVolumeMountData, mount_data);
674
}
675
676
static void
677
panel_menu_item_mount_volume (GtkWidget *menuitem,
678
			      GVolume   *volume)
679
{
680
	PanelVolumeMountData *mount_data;
681
682
	mount_data = g_slice_new (PanelVolumeMountData);
683
	mount_data->screen = menuitem_to_screen (menuitem);
1.1.41 by Sebastien Bacher
Import upstream version 2.23.6
684
	mount_data->mount_op = gtk_mount_operation_new (NULL);
685
	gtk_mount_operation_set_screen (GTK_MOUNT_OPERATION (mount_data->mount_op),
686
					mount_data->screen);
1.1.31 by Sebastien Bacher
Import upstream version 2.21.91
687
688
	g_volume_mount (volume, G_MOUNT_MOUNT_NONE, mount_data->mount_op, NULL,
689
			volume_mount_cb, mount_data);
690
}
691
692
static void
693
panel_menu_item_append_volume (GtkWidget *menu,
694
			       GVolume   *volume)
695
{
696
	GtkWidget *item;
697
	GIcon     *icon;
698
	char      *title;
699
	char      *tooltip;
700
701
	icon = g_volume_get_icon (volume);
702
	title = g_volume_get_name (volume);
703
1.2.5 by Josselin Mouette
Import upstream version 2.28.0
704
	item = panel_image_menu_item_new ();
1.1.31 by Sebastien Bacher
Import upstream version 2.21.91
705
	setup_menu_item_with_icon (item,
706
				   panel_menu_icon_get_size (),
1.1.32 by Sebastien Bacher
Import upstream version 2.21.92
707
				   NULL, NULL, icon,
1.1.31 by Sebastien Bacher
Import upstream version 2.21.91
708
				   title);
1.1.32 by Sebastien Bacher
Import upstream version 2.21.92
709
	g_object_unref (icon);
1.1.31 by Sebastien Bacher
Import upstream version 2.21.91
710
711
	tooltip = g_strdup_printf (_("Mount %s"), title);
712
	panel_util_set_tooltip_text (item, tooltip);
713
	g_free (tooltip);
714
715
	g_free (title);
716
717
	gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
718
719
	g_signal_connect_data (item, "activate",
720
			       G_CALLBACK (panel_menu_item_mount_volume),
721
			       g_object_ref (volume),
722
			       (GClosureNotify) g_object_unref, 0);
723
724
	g_signal_connect (G_OBJECT (item), "button_press_event",
725
			  G_CALLBACK (menu_dummy_button_press_event), NULL);
726
}
727
728
static void
729
panel_menu_item_append_mount (GtkWidget *menu,
730
			      GMount    *mount)
731
{
732
	GFile  *root;
733
	GIcon  *icon;
734
	char   *display_name;
735
	char   *activation_uri;
736
737
	icon = g_mount_get_icon (mount);
738
	display_name = g_mount_get_name (mount);
739
740
	root = g_mount_get_root (mount);
741
	activation_uri = g_file_get_uri (root);
742
	g_object_unref (root);
743
1.1.32 by Sebastien Bacher
Import upstream version 2.21.92
744
	panel_menu_items_append_place_item (NULL, icon,
1.1.31 by Sebastien Bacher
Import upstream version 2.21.91
745
					    display_name,
746
					    display_name, //FIXME tooltip
747
					    menu,
748
					    G_CALLBACK (activate_uri),
749
					    activation_uri);
750
1.1.32 by Sebastien Bacher
Import upstream version 2.21.92
751
	g_object_unref (icon);
1.1.31 by Sebastien Bacher
Import upstream version 2.21.91
752
	g_free (display_name);
753
	g_free (activation_uri);
754
}
755
756
typedef enum {
757
	PANEL_GIO_DRIVE,
758
	PANEL_GIO_VOLUME,
759
	PANEL_GIO_MOUNT
760
} PanelGioItemType;
761
762
typedef struct {
763
	PanelGioItemType type;
764
	union {
765
		GDrive *drive;
766
		GVolume *volume;
767
		GMount *mount;
768
	} u;
769
} PanelGioItem;
770
771
/* this is loosely based on update_places() from nautilus-places-sidebar.c */
772
static void
773
panel_place_menu_item_append_local_gio (PanelPlaceMenuItem *place_item,
774
					GtkWidget          *menu)
775
{
776
	GList   *l;
777
	GList   *ll;
778
	GList   *drives;
779
	GDrive  *drive;
780
	GList   *volumes;
781
	GVolume *volume;
782
	GList   *mounts;
783
	GMount  *mount;
784
	GSList       *items;
785
	GSList       *sl;
786
	PanelGioItem *item;
1.1.1 by Sebastien Bacher
Import upstream version 2.13.3
787
	GtkWidget *add_menu;
1.1.31 by Sebastien Bacher
Import upstream version 2.21.91
788
789
	items = NULL;
790
791
	/* first go through all connected drives */
792
	drives = g_volume_monitor_get_connected_drives (place_item->priv->volume_monitor);
793
	for (l = drives; l != NULL; l = l->next) {
794
		drive = l->data;
795
796
		volumes = g_drive_get_volumes (drive);
797
		if (volumes != NULL) {
798
			for (ll = volumes; ll != NULL; ll = ll->next) {
799
				volume = ll->data;
800
				mount = g_volume_get_mount (volume);
801
				item = g_slice_new (PanelGioItem);
802
				if (mount != NULL) {
803
					item->type = PANEL_GIO_MOUNT;
804
					item->u.mount = mount;
805
				} else {
806
					/* Do show the unmounted volumes; this
807
					 * is so the user can mount it (in case
808
					 * automounting is off).
809
					 *
810
					 * Also, even if automounting is
811
					 * enabled, this gives a visual cue
812
					 * that the user should remember to
813
					 * yank out the media if he just
814
					 * unmounted it.
815
					 */
816
					item->type = PANEL_GIO_VOLUME;
817
					item->u.volume = g_object_ref (volume);
818
				}
819
				items = g_slist_prepend (items, item);
820
				g_object_unref (volume);
821
			}
822
			g_list_free (volumes);
823
		} else {
824
			if (g_drive_is_media_removable (drive) &&
825
			    !g_drive_is_media_check_automatic (drive)) {
826
				/* If the drive has no mountable volumes and we
827
				 * cannot detect media change.. we display the
828
				 * drive so the user can manually poll the
829
				 * drive by clicking on it..."
830
				 *
831
				 * This is mainly for drives like floppies
832
				 * where media detection doesn't work.. but
833
				 * it's also for human beings who like to turn
834
				 * off media detection in the OS to save
835
				 * battery juice.
836
				 */
837
				item = g_slice_new (PanelGioItem);
838
				item->type = PANEL_GIO_DRIVE;
839
				item->u.drive = g_object_ref (drive);
840
				items = g_slist_prepend (items, item);
841
			}
842
		}
843
		g_object_unref (drive);
844
	}
845
	g_list_free (drives);
846
847
	/* add all volumes that is not associated with a drive */
848
	volumes = g_volume_monitor_get_volumes (place_item->priv->volume_monitor);
849
	for (l = volumes; l != NULL; l = l->next) {
850
		volume = l->data;
851
		drive = g_volume_get_drive (volume);
852
		if (drive != NULL) {
853
		    	g_object_unref (volume);
854
			g_object_unref (drive);
855
			continue;
856
		}
857
		mount = g_volume_get_mount (volume);
858
		item = g_slice_new (PanelGioItem);
859
		if (mount != NULL) {
860
			item->type = PANEL_GIO_MOUNT;
861
			item->u.mount = mount;
862
		} else {
863
			/* see comment above in why we add an icon for an
864
			 * unmounted mountable volume */
865
			item->type = PANEL_GIO_VOLUME;
866
			item->u.volume = g_object_ref (volume);
867
		}
868
		items = g_slist_prepend (items, item);
869
		g_object_unref (volume);
870
	}
871
	g_list_free (volumes);
872
873
	/* add mounts that has no volume (/etc/mtab mounts, ftp, sftp,...) */
874
	mounts = g_volume_monitor_get_mounts (place_item->priv->volume_monitor);
875
	for (l = mounts; l != NULL; l = l->next) {
876
		GFile *root;
877
878
		mount = l->data;
879
1.1.54 by Sebastien Bacher
Import upstream version 2.26.0
880
		if (g_mount_is_shadowed (mount)) {
881
			g_object_unref (mount);
882
			continue;
883
		}
884
1.1.31 by Sebastien Bacher
Import upstream version 2.21.91
885
		volume = g_mount_get_volume (mount);
886
		if (volume != NULL) {
887
			g_object_unref (volume);
888
			g_object_unref (mount);
889
			continue;
890
		}
891
892
		root = g_mount_get_root (mount);
893
		if (!g_file_is_native (root)) {
894
			g_object_unref (root);
895
			g_object_unref (mount);
896
			continue;
897
		}
898
		g_object_unref (root);
899
900
		item = g_slice_new (PanelGioItem);
901
		item->type = PANEL_GIO_MOUNT;
902
		item->u.mount = mount;
903
		items = g_slist_prepend (items, item);
904
	}
905
	g_list_free (mounts);
906
907
	/* now that we have everything, add the items inline or in a submenu */
908
	items = g_slist_reverse (items);
909
910
	if (g_slist_length (items) <= MAX_ITEMS_OR_SUBMENU) {
911
		add_menu = menu;
912
	} else {
913
		GtkWidget  *item;
914
1.3.1 by Josselin Mouette
Import upstream version 2.24.2
915
		item = gtk_image_menu_item_new ();
1.1.31 by Sebastien Bacher
Import upstream version 2.21.91
916
		setup_menu_item_with_icon (item, panel_menu_icon_get_size (),
1.1.32 by Sebastien Bacher
Import upstream version 2.21.92
917
					   PANEL_ICON_REMOVABLE_MEDIA,
918
					   NULL, NULL,
1.1.31 by Sebastien Bacher
Import upstream version 2.21.91
919
					   _("Removable Media"));
920
921
		gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
922
		gtk_widget_show (item);
923
924
		add_menu = create_empty_menu ();
925
		gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), add_menu);
926
	}
927
928
	for (sl = items; sl; sl = sl->next) {
929
		item = sl->data;
930
		switch (item->type) {
931
		case PANEL_GIO_DRIVE:
932
			panel_menu_item_append_drive (add_menu, item->u.drive);
933
			g_object_unref (item->u.drive);
934
			break;
935
		case PANEL_GIO_VOLUME:
936
			panel_menu_item_append_volume (add_menu, item->u.volume);
937
			g_object_unref (item->u.volume);
938
			break;
939
		case PANEL_GIO_MOUNT:
940
			panel_menu_item_append_mount (add_menu, item->u.mount);
941
			g_object_unref (item->u.mount);
1.1.1 by Sebastien Bacher
Import upstream version 2.13.3
942
			break;
943
		default:
1.1.31 by Sebastien Bacher
Import upstream version 2.21.91
944
			g_assert_not_reached ();
945
		}
946
		g_slice_free (PanelGioItem, item);
947
	}
948
949
	g_slist_free (items);
950
}
951
952
/* this is loosely based on update_places() from nautilus-places-sidebar.c */
953
static void
954
panel_place_menu_item_append_remote_gio (PanelPlaceMenuItem *place_item,
955
					 GtkWidget          *menu)
956
{
957
	GtkWidget *add_menu;
958
	GList     *mounts, *l;
959
	GMount    *mount;
960
	GSList    *add_mounts, *sl;
961
962
	/* add mounts that has no volume (/etc/mtab mounts, ftp, sftp,...) */
963
	mounts = g_volume_monitor_get_mounts (place_item->priv->volume_monitor);
964
	add_mounts = NULL;
965
966
	for (l = mounts; l; l = l->next) {
967
		GVolume *volume;
968
		GFile   *root;
969
970
		mount = l->data;
1.1.54 by Sebastien Bacher
Import upstream version 2.26.0
971
972
		if (g_mount_is_shadowed (mount)) {
973
			g_object_unref (mount);
974
			continue;
975
		}
976
1.1.31 by Sebastien Bacher
Import upstream version 2.21.91
977
		volume = g_mount_get_volume (mount);
978
		if (volume != NULL) {
979
			g_object_unref (volume);
980
			g_object_unref (mount);
981
			continue;
982
		}
983
984
		root = g_mount_get_root (mount);
985
		if (g_file_is_native (root)) {
986
			g_object_unref (root);
987
			g_object_unref (mount);
988
			continue;
989
		}
990
		g_object_unref (root);
991
992
993
		add_mounts = g_slist_prepend (add_mounts, mount);
994
	}
995
	add_mounts = g_slist_reverse (add_mounts);
996
997
	if (g_slist_length (add_mounts) <= MAX_ITEMS_OR_SUBMENU) {
1.1.1 by Sebastien Bacher
Import upstream version 2.13.3
998
		add_menu = menu;
999
	} else {
1000
		GtkWidget  *item;
1001
1.2.5 by Josselin Mouette
Import upstream version 2.28.0
1002
		item = panel_image_menu_item_new ();
1.1.1 by Sebastien Bacher
Import upstream version 2.13.3
1003
		setup_menu_item_with_icon (item, panel_menu_icon_get_size (),
1.1.32 by Sebastien Bacher
Import upstream version 2.21.92
1004
					   PANEL_ICON_NETWORK_SERVER,
1005
					   NULL, NULL,
1.1.31 by Sebastien Bacher
Import upstream version 2.21.91
1006
					   _("Network Places"));
1.1.1 by Sebastien Bacher
Import upstream version 2.13.3
1007
1008
		gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
1009
		gtk_widget_show (item);
1010
1011
		add_menu = create_empty_menu ();
1012
		gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), add_menu);
1013
	}
1014
1.1.31 by Sebastien Bacher
Import upstream version 2.21.91
1015
	for (sl = add_mounts; sl; sl = sl->next) {
1016
		mount = sl->data;
1017
		panel_menu_item_append_mount (add_menu, mount);
1018
		g_object_unref (mount);
1.1.1 by Sebastien Bacher
Import upstream version 2.13.3
1019
	}
1020
1.1.31 by Sebastien Bacher
Import upstream version 2.21.91
1021
	g_slist_free (add_mounts);
1022
	g_list_free (mounts);
1.1.1 by Sebastien Bacher
Import upstream version 2.13.3
1023
}
1024
1025
1026
static GtkWidget *
1.1.10 by Sebastien Bacher
Import upstream version 2.15.91
1027
panel_place_menu_item_create_menu (PanelPlaceMenuItem *place_item)
1.1.1 by Sebastien Bacher
Import upstream version 2.13.3
1028
{
1029
	GtkWidget *places_menu;
1030
	GtkWidget *item;
1031
	char      *gconf_name;
1.1.31 by Sebastien Bacher
Import upstream version 2.21.91
1032
	char      *name;
183 by Robert Ancell
* Rebase on Debian unstable, remaining Ubuntu changes:
1033
	char      *path;
1.1.23 by Sebastien Bacher
Import upstream version 2.19.5
1034
	char      *uri;
1.1.31 by Sebastien Bacher
Import upstream version 2.21.91
1035
	GFile     *file;
1.1.1 by Sebastien Bacher
Import upstream version 2.13.3
1036
1037
	places_menu = panel_create_menu ();
1038
1.1.31 by Sebastien Bacher
Import upstream version 2.21.91
1039
	file = g_file_new_for_path (g_get_home_dir ());
1040
	uri = g_file_get_uri (file);
1041
	name = panel_util_get_label_for_uri (uri);
1042
	g_object_unref (file);
1043
	
1.1.32 by Sebastien Bacher
Import upstream version 2.21.92
1044
	panel_menu_items_append_place_item (PANEL_ICON_HOME, NULL,
1.1.31 by Sebastien Bacher
Import upstream version 2.21.91
1045
					    name,
1.1.23 by Sebastien Bacher
Import upstream version 2.19.5
1046
					    _("Open your personal folder"),
1047
					    places_menu,
1048
					    G_CALLBACK (activate_home_uri),
1049
					    uri);
1.1.31 by Sebastien Bacher
Import upstream version 2.21.91
1050
	g_free (name);
1.1.23 by Sebastien Bacher
Import upstream version 2.19.5
1051
	g_free (uri);
1052
1.1.1 by Sebastien Bacher
Import upstream version 2.13.3
1053
	if (!gconf_client_get_bool (panel_gconf_get_client (),
1054
				    DESKTOP_IS_HOME_DIR_KEY,
1.1.11 by Sebastien Bacher
Import upstream version 2.15.92
1055
				    NULL)) {
1.1.31 by Sebastien Bacher
Import upstream version 2.21.91
1056
		file = g_file_new_for_path (g_get_user_special_dir (G_USER_DIRECTORY_DESKTOP));
1057
		uri = g_file_get_uri (file);
1058
		g_object_unref (file);
1059
		
1.1.1 by Sebastien Bacher
Import upstream version 2.13.3
1060
		panel_menu_items_append_place_item (
1.1.32 by Sebastien Bacher
Import upstream version 2.21.92
1061
				PANEL_ICON_DESKTOP, NULL,
1.1.1 by Sebastien Bacher
Import upstream version 2.13.3
1062
				/* Translators: Desktop is used here as in
1063
				 * "Desktop Folder" (this is not the Desktop
1.1.48 by Sebastien Bacher
Import upstream version 2.25.3
1064
				 * environment). */
1065
				C_("Desktop Folder", "Desktop"),
1.1.15 by Sebastien Bacher
Import upstream version 2.17.90
1066
				_("Open the contents of your desktop in a folder"),
1.1.1 by Sebastien Bacher
Import upstream version 2.13.3
1067
				places_menu,
1.1.22 by Sebastien Bacher
Import upstream version 2.19.4
1068
				G_CALLBACK (activate_desktop_uri),
1.1.23 by Sebastien Bacher
Import upstream version 2.19.5
1069
				/* FIXME: if the dir changes, we'd need to update the drag data since the uri is not the same */
1070
				uri);
1071
		g_free (uri);
1.1.11 by Sebastien Bacher
Import upstream version 2.15.92
1072
	}
1.1.1 by Sebastien Bacher
Import upstream version 2.13.3
1073
1074
	panel_place_menu_item_append_gtk_bookmarks (places_menu);
1075
	add_menu_separator (places_menu);
1076
1077
	gconf_name = gconf_client_get_string (panel_gconf_get_client (),
1078
					      COMPUTER_NAME_KEY,
1079
					      NULL);
1080
	panel_menu_items_append_from_desktop (places_menu,
1081
					      "nautilus-computer.desktop",
1.2.5 by Josselin Mouette
Import upstream version 2.28.0
1082
					      gconf_name,
1083
                                              TRUE);
1.1.1 by Sebastien Bacher
Import upstream version 2.13.3
1084
	if (gconf_name)
1085
		g_free (gconf_name);
1086
1.1.31 by Sebastien Bacher
Import upstream version 2.21.91
1087
	panel_place_menu_item_append_local_gio (place_item, places_menu);
1.1.1 by Sebastien Bacher
Import upstream version 2.13.3
1088
	add_menu_separator (places_menu);
1089
1090
	panel_menu_items_append_from_desktop (places_menu,
1091
					      "network-scheme.desktop",
1.2.5 by Josselin Mouette
Import upstream version 2.28.0
1092
					      NULL,
1093
                                              TRUE);
1.1.31 by Sebastien Bacher
Import upstream version 2.21.91
1094
	panel_place_menu_item_append_remote_gio (place_item, places_menu);
1.1.1 by Sebastien Bacher
Import upstream version 2.13.3
1095
1096
	if (panel_is_program_in_path ("nautilus-connect-server")) {
1097
		item = panel_menu_items_create_action_item (PANEL_ACTION_CONNECT_SERVER);
1098
		if (item != NULL)
1099
			gtk_menu_shell_append (GTK_MENU_SHELL (places_menu),
1100
					       item);
1101
	}
1102
1103
	add_menu_separator (places_menu);
1104
1105
	panel_menu_items_append_from_desktop (places_menu,
1106
					      "gnome-search-tool.desktop",
1.2.5 by Josselin Mouette
Import upstream version 2.28.0
1107
					      NULL,
1108
                                              FALSE);
1.1.1 by Sebastien Bacher
Import upstream version 2.13.3
1109
1.1.10 by Sebastien Bacher
Import upstream version 2.15.91
1110
	panel_recent_append_documents_menu (places_menu,
1111
					    place_item->priv->recent_manager);
1.1.1 by Sebastien Bacher
Import upstream version 2.13.3
1112
1113
	return places_menu;
1114
}
1115
1116
static void
1117
panel_place_menu_item_recreate_menu (GtkWidget *widget)
1118
{
1119
	PanelPlaceMenuItem *place_item;
1120
1121
	place_item = PANEL_PLACE_MENU_ITEM (widget);
1122
1123
	if (place_item->priv->menu) {
1124
		gtk_widget_destroy (place_item->priv->menu);
1.1.10 by Sebastien Bacher
Import upstream version 2.15.91
1125
		place_item->priv->menu = panel_place_menu_item_create_menu (place_item);
1.1.1 by Sebastien Bacher
Import upstream version 2.13.3
1126
		gtk_menu_item_set_submenu (GTK_MENU_ITEM (place_item),
1127
					   place_item->priv->menu);
1128
		panel_applet_menu_set_recurse (GTK_MENU (place_item->priv->menu),
1129
					       "menu_panel",
1130
					       place_item->priv->panel);
1131
	}
1132
}
1133
1134
static void
1135
panel_place_menu_item_key_changed (GConfClient *client,
1136
				   guint        cnxn_id,
1137
				   GConfEntry  *entry,
1138
				   GtkWidget   *place_item)
1139
{
1140
	panel_place_menu_item_recreate_menu (place_item);
1141
}
1142
1143
static void
1.1.31 by Sebastien Bacher
Import upstream version 2.21.91
1144
panel_place_menu_item_gtk_bookmarks_changed (GFileMonitor *handle,
1145
					     GFile        *file,
1146
					     GFile        *other_file,
1147
					     GFileMonitorEvent event,
1148
					     gpointer      user_data)
1.1.1 by Sebastien Bacher
Import upstream version 2.13.3
1149
{
1150
	panel_place_menu_item_recreate_menu (GTK_WIDGET (user_data));
1151
}
1152
1153
static void
1.1.31 by Sebastien Bacher
Import upstream version 2.21.91
1154
panel_place_menu_item_drives_changed (GVolumeMonitor *monitor,
1155
				      GDrive         *drive,
1156
				      GtkWidget      *place_menu)
1157
{
1158
	panel_place_menu_item_recreate_menu (place_menu);
1159
}
1160
1161
static void
1162
panel_place_menu_item_volumes_changed (GVolumeMonitor *monitor,
1163
				       GVolume        *volume,
1164
				       GtkWidget      *place_menu)
1165
{
1166
	panel_place_menu_item_recreate_menu (place_menu);
1167
}
1168
1169
static void
1170
panel_place_menu_item_mounts_changed (GVolumeMonitor *monitor,
1171
				      GMount         *mount,
1172
				      GtkWidget      *place_menu)
1.1.1 by Sebastien Bacher
Import upstream version 2.13.3
1173
{
1174
	panel_place_menu_item_recreate_menu (place_menu);
1175
}
1176
1.1.16 by Sebastien Bacher
Import upstream version 2.17.91
1177
static void
1178
panel_desktop_menu_item_append_menu (GtkWidget *menu,
1179
				     gpointer   data)
1180
{
1181
	PanelDesktopMenuItem *parent;
1182
	gboolean              add_separator;
1183
	GList                *children;
1184
	GList                *last;
1185
1186
	parent = PANEL_DESKTOP_MENU_ITEM (data);
1187
1188
	add_separator = FALSE;
1189
	children = gtk_container_get_children (GTK_CONTAINER (menu));
1190
	last = g_list_last (children);
1191
1192
	if (last != NULL)
1193
		add_separator = !GTK_IS_SEPARATOR (GTK_WIDGET (last->data));
1194
1195
	g_list_free (children);
1196
1197
	if (add_separator)
1198
		add_menu_separator (menu);
1199
183 by Robert Ancell
* Rebase on Debian unstable, remaining Ubuntu changes:
1200
	panel_menu_items_append_from_desktop (menu, "yelp.desktop", _("Help and Support"), FALSE);
1201
1.2.5 by Josselin Mouette
Import upstream version 2.28.0
1202
	panel_menu_items_append_from_desktop (menu, "gnome-about.desktop", NULL, FALSE);
1.1.16 by Sebastien Bacher
Import upstream version 2.17.91
1203
183 by Robert Ancell
* Rebase on Debian unstable, remaining Ubuntu changes:
1204
	if (g_file_test (DATADIR"/omf/about-ubuntu/about-ubuntu-C.omf",
1205
			 G_FILE_TEST_IS_REGULAR))
1206
	  panel_menu_items_append_from_desktop (menu, "ubuntu-about.desktop", NULL, FALSE);
1207
1208
	if (g_file_test (DATADIR"/omf/about-edubuntu/about-edubuntu-C.omf",
1209
			 G_FILE_TEST_IS_REGULAR))
1210
	  panel_menu_items_append_from_desktop (menu, "edubuntu-about.desktop", NULL, FALSE);
1211
1.1.16 by Sebastien Bacher
Import upstream version 2.17.91
1212
	if (parent->priv->append_lock_logout)
1213
		panel_menu_items_append_lock_logout (menu);
1214
}
1215
1.1.1 by Sebastien Bacher
Import upstream version 2.13.3
1216
static GtkWidget *
1217
panel_desktop_menu_item_create_menu (PanelDesktopMenuItem *desktop_item)
1218
{
1219
	GtkWidget *desktop_menu;
1220
159 by Sebastien Bacher
* New upstream version:
1221
	desktop_menu = create_applications_menu ("settings.menu", NULL, FALSE);
1.1.16 by Sebastien Bacher
Import upstream version 2.17.91
1222
1223
	g_object_set_data (G_OBJECT (desktop_menu),
1224
			   "panel-menu-append-callback",
1225
			   panel_desktop_menu_item_append_menu);
1226
	g_object_set_data (G_OBJECT (desktop_menu),
1227
			   "panel-menu-append-callback-data",
1228
			   desktop_item);
1.1.1 by Sebastien Bacher
Import upstream version 2.13.3
1229
1230
	return desktop_menu;
1231
}
1232
1233
static void
1234
panel_desktop_menu_item_recreate_menu (PanelDesktopMenuItem *desktop_item)
1235
{
1236
	if (desktop_item->priv->menu) {
1237
		gtk_widget_destroy (desktop_item->priv->menu);
1238
		desktop_item->priv->menu = panel_desktop_menu_item_create_menu (desktop_item);
1239
		gtk_menu_item_set_submenu (GTK_MENU_ITEM (desktop_item),
1240
					   desktop_item->priv->menu);
1241
		panel_applet_menu_set_recurse (GTK_MENU (desktop_item->priv->menu),
1242
					       "menu_panel",
1243
					       desktop_item->priv->panel);
1244
	}
1245
}
1246
1247
static void
1248
panel_place_menu_item_finalize (GObject *object)
1249
{
1250
	PanelPlaceMenuItem *menuitem = (PanelPlaceMenuItem *) object;
1251
1252
	gconf_client_remove_dir (panel_gconf_get_client (),
1253
				 DESKTOP_IS_HOME_DIR_DIR,
1254
				 NULL);
1255
	gconf_client_remove_dir (panel_gconf_get_client (),
1256
				 NAMES_DIR,
1257
				 NULL);
1258
1.1.31 by Sebastien Bacher
Import upstream version 2.21.91
1259
	if (menuitem->priv->bookmarks_monitor != NULL) {
1260
		g_file_monitor_cancel (menuitem->priv->bookmarks_monitor);
1261
		g_object_unref (menuitem->priv->bookmarks_monitor);
1262
	}
1.1.1 by Sebastien Bacher
Import upstream version 2.13.3
1263
	menuitem->priv->bookmarks_monitor = NULL;
1264
1.1.31 by Sebastien Bacher
Import upstream version 2.21.91
1265
	if (menuitem->priv->drive_changed_id)
1266
		g_signal_handler_disconnect (menuitem->priv->volume_monitor,
1267
					     menuitem->priv->drive_changed_id);
1268
	menuitem->priv->drive_changed_id = 0;
1269
1270
	if (menuitem->priv->drive_connected_id)
1271
		g_signal_handler_disconnect (menuitem->priv->volume_monitor,
1272
					     menuitem->priv->drive_connected_id);
1273
	menuitem->priv->drive_connected_id = 0;
1274
1275
	if (menuitem->priv->drive_disconnected_id)
1276
		g_signal_handler_disconnect (menuitem->priv->volume_monitor,
1277
					     menuitem->priv->drive_disconnected_id);
1278
	menuitem->priv->drive_disconnected_id = 0;
1279
1280
	if (menuitem->priv->volume_added_id)
1281
		g_signal_handler_disconnect (menuitem->priv->volume_monitor,
1282
					     menuitem->priv->volume_added_id);
1283
	menuitem->priv->volume_added_id = 0;
1284
1285
	if (menuitem->priv->volume_changed_id)
1286
		g_signal_handler_disconnect (menuitem->priv->volume_monitor,
1287
					     menuitem->priv->volume_changed_id);
1288
	menuitem->priv->volume_changed_id = 0;
1289
1290
	if (menuitem->priv->volume_removed_id)
1291
		g_signal_handler_disconnect (menuitem->priv->volume_monitor,
1292
					     menuitem->priv->volume_removed_id);
1293
	menuitem->priv->volume_removed_id = 0;
1294
1295
	if (menuitem->priv->mount_added_id)
1296
		g_signal_handler_disconnect (menuitem->priv->volume_monitor,
1297
					     menuitem->priv->mount_added_id);
1298
	menuitem->priv->mount_added_id = 0;
1299
1300
	if (menuitem->priv->mount_changed_id)
1301
		g_signal_handler_disconnect (menuitem->priv->volume_monitor,
1302
					     menuitem->priv->mount_changed_id);
1303
	menuitem->priv->mount_changed_id = 0;
1304
1305
	if (menuitem->priv->mount_removed_id)
1306
		g_signal_handler_disconnect (menuitem->priv->volume_monitor,
1307
					     menuitem->priv->mount_removed_id);
1308
	menuitem->priv->mount_removed_id = 0;
1309
1310
	if (menuitem->priv->volume_monitor != NULL)
1311
		g_object_unref (menuitem->priv->volume_monitor);
1312
	menuitem->priv->volume_monitor = NULL;
1.1.1 by Sebastien Bacher
Import upstream version 2.13.3
1313
1.1.17 by Sebastien Bacher
Import upstream version 2.17.92
1314
	G_OBJECT_CLASS (panel_place_menu_item_parent_class)->finalize (object);
1.1.1 by Sebastien Bacher
Import upstream version 2.13.3
1315
}
1316
1317
static void
1318
panel_desktop_menu_item_finalize (GObject *object)
1319
{
1320
	PanelDesktopMenuItem *menuitem = (PanelDesktopMenuItem *) object;
1321
1322
	if (menuitem->priv->append_lock_logout)
1323
		panel_lockdown_notify_remove (G_CALLBACK (panel_desktop_menu_item_recreate_menu),
1324
					      menuitem);
1.1.17 by Sebastien Bacher
Import upstream version 2.17.92
1325
	G_OBJECT_CLASS (panel_desktop_menu_item_parent_class)->finalize (object);
1.1.1 by Sebastien Bacher
Import upstream version 2.13.3
1326
}
1327
1328
static void
1.1.17 by Sebastien Bacher
Import upstream version 2.17.92
1329
panel_place_menu_item_init (PanelPlaceMenuItem *menuitem)
1.1.1 by Sebastien Bacher
Import upstream version 2.13.3
1330
{
1.1.31 by Sebastien Bacher
Import upstream version 2.21.91
1331
	GFile *bookmark;
1332
	char  *bookmarks_filename;
1333
	GError *error;
1.1.1 by Sebastien Bacher
Import upstream version 2.13.3
1334
1335
	menuitem->priv = PANEL_PLACE_MENU_ITEM_GET_PRIVATE (menuitem);
1336
1337
	gconf_client_add_dir (panel_gconf_get_client (),
1338
			      DESKTOP_IS_HOME_DIR_DIR,
1339
			      GCONF_CLIENT_PRELOAD_NONE,
1340
			      NULL);
1341
	gconf_client_add_dir (panel_gconf_get_client (),
1342
			      NAMES_DIR,
1343
			      GCONF_CLIENT_PRELOAD_NONE,
1344
			      NULL);
1345
1346
	panel_gconf_notify_add_while_alive (HOME_NAME_KEY,
1347
					    (GConfClientNotifyFunc) panel_place_menu_item_key_changed,
1348
					    G_OBJECT (menuitem));
1349
	panel_gconf_notify_add_while_alive (DESKTOP_IS_HOME_DIR_KEY,
1350
					    (GConfClientNotifyFunc) panel_place_menu_item_key_changed,
1351
					    G_OBJECT (menuitem));
1352
	panel_gconf_notify_add_while_alive (COMPUTER_NAME_KEY,
1353
					    (GConfClientNotifyFunc) panel_place_menu_item_key_changed,
1354
					    G_OBJECT (menuitem));
1355
1.1.10 by Sebastien Bacher
Import upstream version 2.15.91
1356
	menuitem->priv->recent_manager = gtk_recent_manager_get_default ();
1357
1.1.1 by Sebastien Bacher
Import upstream version 2.13.3
1358
	bookmarks_filename = g_build_filename (g_get_home_dir (),
1359
					       BOOKMARKS_FILENAME, NULL);
1.1.31 by Sebastien Bacher
Import upstream version 2.21.91
1360
	bookmark = g_file_new_for_path (bookmarks_filename);
1361
1362
	error = NULL;
1363
	menuitem->priv->bookmarks_monitor = g_file_monitor_file 
1364
        						(bookmark,
1365
        						G_FILE_MONITOR_NONE,
1366
        						NULL,
1367
        						&error);
1368
	if (error) {
1369
		g_warning ("Failed to add file monitor for %s: %s\n",
1370
			   bookmarks_filename, error->message);
1371
		g_error_free (error);
1.1.1 by Sebastien Bacher
Import upstream version 2.13.3
1372
	} else {
1.1.31 by Sebastien Bacher
Import upstream version 2.21.91
1373
		g_signal_connect (G_OBJECT (menuitem->priv->bookmarks_monitor), 
1374
				  "changed", 
1375
				  (GCallback) panel_place_menu_item_gtk_bookmarks_changed,
1376
				  menuitem);
1.1.1 by Sebastien Bacher
Import upstream version 2.13.3
1377
	}
1378
1.1.31 by Sebastien Bacher
Import upstream version 2.21.91
1379
	g_object_unref (bookmark);
1.1.1 by Sebastien Bacher
Import upstream version 2.13.3
1380
	g_free (bookmarks_filename);
1381
1.1.31 by Sebastien Bacher
Import upstream version 2.21.91
1382
	menuitem->priv->volume_monitor = g_volume_monitor_get ();
1.1.1 by Sebastien Bacher
Import upstream version 2.13.3
1383
1.1.31 by Sebastien Bacher
Import upstream version 2.21.91
1384
	menuitem->priv->drive_changed_id = g_signal_connect (menuitem->priv->volume_monitor,
1385
							   "drive-changed",
1386
							   G_CALLBACK (panel_place_menu_item_drives_changed),
1387
							   menuitem);
1388
	menuitem->priv->drive_connected_id = g_signal_connect (menuitem->priv->volume_monitor,
1389
							     "drive-connected",
1390
							     G_CALLBACK (panel_place_menu_item_drives_changed),
1391
							     menuitem);
1392
	menuitem->priv->drive_disconnected_id = g_signal_connect (menuitem->priv->volume_monitor,
1393
							     "drive-disconnected",
1394
							     G_CALLBACK (panel_place_menu_item_drives_changed),
1395
							     menuitem);
1396
	menuitem->priv->volume_added_id = g_signal_connect (menuitem->priv->volume_monitor,
1397
							   "volume-added",
1398
							   G_CALLBACK (panel_place_menu_item_volumes_changed),
1399
							   menuitem);
1400
	menuitem->priv->volume_changed_id = g_signal_connect (menuitem->priv->volume_monitor,
1401
							     "volume-changed",
1402
							     G_CALLBACK (panel_place_menu_item_volumes_changed),
1403
							     menuitem);
1404
	menuitem->priv->volume_removed_id = g_signal_connect (menuitem->priv->volume_monitor,
1405
							     "volume-removed",
1406
							     G_CALLBACK (panel_place_menu_item_volumes_changed),
1407
							     menuitem);
1408
	menuitem->priv->mount_added_id = g_signal_connect (menuitem->priv->volume_monitor,
1409
							   "mount-added",
1410
							   G_CALLBACK (panel_place_menu_item_mounts_changed),
1411
							   menuitem);
1412
	menuitem->priv->mount_changed_id = g_signal_connect (menuitem->priv->volume_monitor,
1413
							     "mount-changed",
1414
							     G_CALLBACK (panel_place_menu_item_mounts_changed),
1415
							     menuitem);
1416
	menuitem->priv->mount_removed_id = g_signal_connect (menuitem->priv->volume_monitor,
1417
							     "mount-removed",
1418
							     G_CALLBACK (panel_place_menu_item_mounts_changed),
1419
							     menuitem);
1.1.1 by Sebastien Bacher
Import upstream version 2.13.3
1420
1421
}
1422
1423
static void
1.1.17 by Sebastien Bacher
Import upstream version 2.17.92
1424
panel_desktop_menu_item_init (PanelDesktopMenuItem *menuitem)
1.1.1 by Sebastien Bacher
Import upstream version 2.13.3
1425
{
1426
	menuitem->priv = PANEL_DESKTOP_MENU_ITEM_GET_PRIVATE (menuitem);
1427
}
1428
1429
static void
1430
panel_place_menu_item_class_init (PanelPlaceMenuItemClass *klass)
1431
{
1432
	GObjectClass *gobject_class = (GObjectClass   *) klass;
1433
1434
	gobject_class->finalize  = panel_place_menu_item_finalize;
1435
1436
	g_type_class_add_private (klass, sizeof (PanelPlaceMenuItemPrivate));
1437
}
1438
1439
static void
1440
panel_desktop_menu_item_class_init (PanelDesktopMenuItemClass *klass)
1441
{
1442
	GObjectClass *gobject_class = (GObjectClass   *) klass;
1443
1444
	gobject_class->finalize  = panel_desktop_menu_item_finalize;
1445
1446
	g_type_class_add_private (klass, sizeof (PanelDesktopMenuItemPrivate));
1447
}
1448
1449
GtkWidget *
1450
panel_place_menu_item_new (gboolean use_image)
1451
{
1452
	PanelPlaceMenuItem *menuitem;
1.1.17 by Sebastien Bacher
Import upstream version 2.17.92
1453
	GtkWidget          *image;
1.1.1 by Sebastien Bacher
Import upstream version 2.13.3
1454
1455
	menuitem = g_object_new (PANEL_TYPE_PLACE_MENU_ITEM, NULL);
1456
1.1.17 by Sebastien Bacher
Import upstream version 2.17.92
1457
	if (use_image)
1.1.20 by Sebastien Bacher
Import upstream version 2.19.2
1458
		image = gtk_image_new_from_icon_name (PANEL_ICON_FOLDER,
1.1.1 by Sebastien Bacher
Import upstream version 2.13.3
1459
						      panel_menu_icon_get_size ());
1.1.17 by Sebastien Bacher
Import upstream version 2.17.92
1460
	else
1461
		image = NULL;
1462
1463
	setup_menuitem (GTK_WIDGET (menuitem),
1.1.18 by Sebastien Bacher
Import upstream version 2.18.0
1464
			image ? panel_menu_icon_get_size () : GTK_ICON_SIZE_INVALID,
1.1.17 by Sebastien Bacher
Import upstream version 2.17.92
1465
			image,
1.1.23 by Sebastien Bacher
Import upstream version 2.19.5
1466
			_("Places"));
1.1.17 by Sebastien Bacher
Import upstream version 2.17.92
1467
1468
	menuitem->priv->use_image = use_image;
1.1.1 by Sebastien Bacher
Import upstream version 2.13.3
1469
1.1.10 by Sebastien Bacher
Import upstream version 2.15.91
1470
	menuitem->priv->menu = panel_place_menu_item_create_menu (menuitem);
1.1.1 by Sebastien Bacher
Import upstream version 2.13.3
1471
	gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem),
1472
				   menuitem->priv->menu);
1473
1474
	return GTK_WIDGET (menuitem);
1475
}
1476
1477
GtkWidget *
1478
panel_desktop_menu_item_new (gboolean use_image,
1479
			     gboolean append_lock_logout)
1480
{
1481
	PanelDesktopMenuItem *menuitem;
1.1.17 by Sebastien Bacher
Import upstream version 2.17.92
1482
	GtkWidget            *image;
1.1.1 by Sebastien Bacher
Import upstream version 2.13.3
1483
1484
	menuitem = g_object_new (PANEL_TYPE_DESKTOP_MENU_ITEM, NULL);
1485
1.1.17 by Sebastien Bacher
Import upstream version 2.17.92
1486
	if (use_image)
1.1.15 by Sebastien Bacher
Import upstream version 2.17.90
1487
		image = gtk_image_new_from_icon_name ("computer",
1.1.1 by Sebastien Bacher
Import upstream version 2.13.3
1488
						      panel_menu_icon_get_size ());
1.1.17 by Sebastien Bacher
Import upstream version 2.17.92
1489
	else
1490
		image = NULL;
1491
1492
	setup_menuitem (GTK_WIDGET (menuitem),
1.1.18 by Sebastien Bacher
Import upstream version 2.18.0
1493
			image ? panel_menu_icon_get_size () : GTK_ICON_SIZE_INVALID,
1.1.17 by Sebastien Bacher
Import upstream version 2.17.92
1494
			image,
1.1.23 by Sebastien Bacher
Import upstream version 2.19.5
1495
			_("System"));
1.1.17 by Sebastien Bacher
Import upstream version 2.17.92
1496
1497
	menuitem->priv->use_image = use_image;
1.1.1 by Sebastien Bacher
Import upstream version 2.13.3
1498
1499
	menuitem->priv->append_lock_logout = append_lock_logout;
1500
	if (append_lock_logout)
1501
		panel_lockdown_notify_add (G_CALLBACK (panel_desktop_menu_item_recreate_menu),
1502
					   menuitem);
1503
1504
	menuitem->priv->menu = panel_desktop_menu_item_create_menu (menuitem);
1505
	gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem),
1506
				   menuitem->priv->menu);
1507
1508
	return GTK_WIDGET (menuitem);
1509
}
1510
1511
void
1512
panel_place_menu_item_set_panel (GtkWidget   *item,
1513
				 PanelWidget *panel)
1514
{
1515
	PanelPlaceMenuItem *place_item;
1516
1517
	place_item = PANEL_PLACE_MENU_ITEM (item);
1518
1519
	place_item->priv->panel = panel;
1520
	panel_applet_menu_set_recurse (GTK_MENU (place_item->priv->menu),
1521
				       "menu_panel", panel);
1522
}
1523
1524
void
1525
panel_desktop_menu_item_set_panel (GtkWidget   *item,
1526
				   PanelWidget *panel)
1527
{
1528
	PanelDesktopMenuItem *desktop_item;
1529
1530
	desktop_item = PANEL_DESKTOP_MENU_ITEM (item);
1531
1532
	desktop_item->priv->panel = panel;
1533
	panel_applet_menu_set_recurse (GTK_MENU (desktop_item->priv->menu),
1534
				       "menu_panel", panel);
1535
}
1536
183 by Robert Ancell
* Rebase on Debian unstable, remaining Ubuntu changes:
1537
#define FUSA_APPLET_IID "OAFIID:GNOME_FastUserSwitchApplet"
1538
1539
static void
1540
panel_menu_items_hide_on_fusa (PanelAppletSignaler * pas, AppletInfo * info, GtkWidget * widget)
1541
{
1542
	/* check if we are running stracciatella session */
1543
	if (g_strcmp0(g_getenv("GDMSESSION"), "gnome-stracciatella") == 0) {
1544
	        g_debug("Running stracciatella GNOME session, not touching menu items");
1545
	        return TRUE;
1546
	}
1547
1548
	const char * iid = panel_applet_get_iid(info);
1549
	if (iid == NULL)
1550
		return;
1551
1552
	if (!strcmp(iid, FUSA_APPLET_IID))
1553
		gtk_widget_hide(widget);
1554
1555
	return;
1556
}
1557
1558
static void
1559
panel_menu_items_show_on_fusa (PanelAppletSignaler * pas, AppletInfo * info, GtkWidget * widget)
1560
{
1561
	/* check if we are running stracciatella session */
1562
	if (g_strcmp0(g_getenv("GDMSESSION"), "gnome-stracciatella") == 0) {
1563
	        g_debug("Running stracciatella GNOME session, not touching menu items");
1564
	        return TRUE;
1565
	}
1566
1567
	const char * iid = panel_applet_get_iid(info);
1568
	if (iid == NULL)
1569
		return;
1570
1571
	if (!strcmp(iid, FUSA_APPLET_IID))
1572
		gtk_widget_show(widget);
1573
1574
	return;
1575
}
1576
1577
static void
1578
disconnect_signalers (PanelAppletSignaler *signaler,
1579
                      GtkWidget           *widget)
1580
{
1581
        g_signal_handlers_disconnect_by_func (signaler,
1582
                                              panel_menu_items_hide_on_fusa,
1583
                                              widget);
1584
        g_signal_handlers_disconnect_by_func (signaler,
1585
                                              panel_menu_items_show_on_fusa,
1586
                                              widget);
1587
}
1588
1.1.1 by Sebastien Bacher
Import upstream version 2.13.3
1589
void
1590
panel_menu_items_append_lock_logout (GtkWidget *menu)
1591
{
1.1.4 by Daniel Holbach
Import upstream version 2.13.90
1592
	gboolean    separator_inserted;
1593
	GList      *children;
1.1.14 by Sebastien Bacher
Import upstream version 2.16.2
1594
	GList      *last;
1.1.4 by Daniel Holbach
Import upstream version 2.13.90
1595
	GtkWidget  *item;
1596
	const char *translate;
1597
	char       *label;
1598
	char       *tooltip;
183 by Robert Ancell
* Rebase on Debian unstable, remaining Ubuntu changes:
1599
	GtkWidget  *separator = NULL;
1600
	AppletInfo *fusa = NULL;
1601
	PanelAppletSignaler *signaler = panel_applet_signaler_get_default ();
1602
1603
	fusa = panel_applet_get_by_iid(FUSA_APPLET_IID);
1.1.1 by Sebastien Bacher
Import upstream version 2.13.3
1604
1605
	separator_inserted = FALSE;
1606
	children = gtk_container_get_children (GTK_CONTAINER (menu));
1.1.14 by Sebastien Bacher
Import upstream version 2.16.2
1607
	last = g_list_last (children);
1608
	if (last != NULL) {
1609
		separator_inserted = GTK_IS_SEPARATOR (GTK_WIDGET (last->data));
1.1.1 by Sebastien Bacher
Import upstream version 2.13.3
1610
	}
183 by Robert Ancell
* Rebase on Debian unstable, remaining Ubuntu changes:
1611
	if (separator_inserted) {
1612
		g_object_weak_ref (G_OBJECT (last->data),
1613
                                   (GWeakNotify) disconnect_signalers,
1614
                                   signaler);
1615
1616
		g_signal_connect(signaler, PANEL_APPLET_SIGNALER_SIGNAL_APPLET_ADDED,
1617
				 G_CALLBACK(panel_menu_items_hide_on_fusa), last->data);
1618
		g_signal_connect(signaler, PANEL_APPLET_SIGNALER_SIGNAL_APPLET_REMOVED,
1619
				 G_CALLBACK(panel_menu_items_show_on_fusa), last->data);
1620
		if (fusa != NULL) {
1621
			gtk_widget_hide(GTK_WIDGET(last->data));
1622
		}
1623
	}
1.1.14 by Sebastien Bacher
Import upstream version 2.16.2
1624
	g_list_free (children);
1.1.1 by Sebastien Bacher
Import upstream version 2.13.3
1625
1626
	if (panel_lock_screen_action_available ("lock")) {
1627
		item = panel_menu_items_create_action_item (PANEL_ACTION_LOCK);
1628
		if (item != NULL) {
1629
			if (!separator_inserted) {
183 by Robert Ancell
* Rebase on Debian unstable, remaining Ubuntu changes:
1630
				separator = add_menu_separator (menu);
1.1.1 by Sebastien Bacher
Import upstream version 2.13.3
1631
				separator_inserted = TRUE;
1632
			}
1633
1634
			gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
183 by Robert Ancell
* Rebase on Debian unstable, remaining Ubuntu changes:
1635
1636
			g_object_weak_ref (G_OBJECT (item),
1637
                                           (GWeakNotify) disconnect_signalers,
1638
                                           signaler);
1639
1640
			g_signal_connect(signaler, PANEL_APPLET_SIGNALER_SIGNAL_APPLET_ADDED,
1641
			                 G_CALLBACK(panel_menu_items_hide_on_fusa), item);
1642
			g_signal_connect(signaler, PANEL_APPLET_SIGNALER_SIGNAL_APPLET_REMOVED,
1643
			                 G_CALLBACK(panel_menu_items_show_on_fusa), item);
1644
			if (fusa != NULL) {
1645
				gtk_widget_hide(GTK_WIDGET(item));
1646
			}
1.1.1 by Sebastien Bacher
Import upstream version 2.13.3
1647
		}
1648
	}
1649
1.1.41 by Sebastien Bacher
Import upstream version 2.23.6
1650
	if (panel_lockdown_get_disable_log_out ())
1651
		return;
1652
	/* Below this, we only have log out/shutdown items */
1653
1.1.48 by Sebastien Bacher
Import upstream version 2.25.3
1654
	/* Translators: translate "1" (msgctxt: "panel:showusername") to anything
1.1.4 by Daniel Holbach
Import upstream version 2.13.90
1655
	 * but "1" if "Log Out %s" doesn't make any sense in your
1656
	 * language (where %s is a username).
1657
	 */
1.1.48 by Sebastien Bacher
Import upstream version 2.25.3
1658
	translate = C_("panel:showusername", "1");
1.1.4 by Daniel Holbach
Import upstream version 2.13.90
1659
	if (strcmp (translate, "1") == 0) {
1660
		const char *user_name;
1661
1662
		user_name = g_get_real_name ();
1663
		if (!user_name || !user_name [0])
1664
			user_name = g_get_user_name ();
1665
1666
		/* keep those strings in sync with the ones in
1667
		 * panel-action-button.c */
1668
		/* Translators: this string is used ONLY if you translated
1.1.48 by Sebastien Bacher
Import upstream version 2.25.3
1669
		 * "1" (msgctxt: "panel:showusername") to "1" */
1.1.5 by Daniel Holbach
Import upstream version 2.13.91
1670
		label = g_strdup_printf (_("Log Out %s..."),
1671
					 g_get_user_name ());
1.1.4 by Daniel Holbach
Import upstream version 2.13.90
1672
		/* Translators: this string is used ONLY if you translated
1.1.48 by Sebastien Bacher
Import upstream version 2.25.3
1673
		 * "1" (msgctxt: "panel:showusername") to "1" */
1.1.4 by Daniel Holbach
Import upstream version 2.13.90
1674
		tooltip = g_strdup_printf (_("Log out %s of this session to "
1.1.5 by Daniel Holbach
Import upstream version 2.13.91
1675
					     "log in as a different user"),
1.1.4 by Daniel Holbach
Import upstream version 2.13.90
1676
					   user_name);
1677
	} else {
1678
		label   = NULL;
1679
		tooltip = NULL;
1680
	}
1681
1682
	item = panel_menu_items_create_action_item_full (PANEL_ACTION_LOGOUT,
1683
							 label, tooltip);
1684
	g_free (label);
1685
	g_free (tooltip);
1686
1.1.1 by Sebastien Bacher
Import upstream version 2.13.3
1687
	if (item != NULL) {
1.1.41 by Sebastien Bacher
Import upstream version 2.23.6
1688
		if (!separator_inserted) {
183 by Robert Ancell
* Rebase on Debian unstable, remaining Ubuntu changes:
1689
			separator = add_menu_separator (menu);
1.1.41 by Sebastien Bacher
Import upstream version 2.23.6
1690
			separator_inserted = TRUE;
1691
		}
1.1.1 by Sebastien Bacher
Import upstream version 2.13.3
1692
1693
		gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
183 by Robert Ancell
* Rebase on Debian unstable, remaining Ubuntu changes:
1694
1695
		g_object_weak_ref (G_OBJECT (item),
1696
                                   (GWeakNotify) disconnect_signalers,
1697
                                   signaler);
1698
1699
		g_signal_connect(signaler, PANEL_APPLET_SIGNALER_SIGNAL_APPLET_ADDED,
1700
				 G_CALLBACK(panel_menu_items_hide_on_fusa), item);
1701
		g_signal_connect(signaler, PANEL_APPLET_SIGNALER_SIGNAL_APPLET_REMOVED,
1702
				 G_CALLBACK(panel_menu_items_show_on_fusa), item);
1703
		if (fusa != NULL) {
1704
			gtk_widget_hide(GTK_WIDGET(item));
1705
		}
1.1.1 by Sebastien Bacher
Import upstream version 2.13.3
1706
	}
1.1.3 by Sebastian Dröge
Import upstream version 2.13.5
1707
1708
	item = panel_menu_items_create_action_item (PANEL_ACTION_SHUTDOWN);
183 by Robert Ancell
* Rebase on Debian unstable, remaining Ubuntu changes:
1709
	if (item != NULL && !g_getenv("LTSP_CLIENT")){
1.1.3 by Sebastian Dröge
Import upstream version 2.13.5
1710
		if (!separator_inserted)
183 by Robert Ancell
* Rebase on Debian unstable, remaining Ubuntu changes:
1711
			separator = add_menu_separator (menu);
1.1.3 by Sebastian Dröge
Import upstream version 2.13.5
1712
1713
		gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
183 by Robert Ancell
* Rebase on Debian unstable, remaining Ubuntu changes:
1714
1715
		g_object_weak_ref (G_OBJECT (item),
1716
                                   (GWeakNotify) disconnect_signalers,
1717
                                   signaler);
1718
1719
		g_signal_connect(signaler, PANEL_APPLET_SIGNALER_SIGNAL_APPLET_ADDED,
1720
				 G_CALLBACK(panel_menu_items_hide_on_fusa), item);
1721
		g_signal_connect(signaler, PANEL_APPLET_SIGNALER_SIGNAL_APPLET_REMOVED,
1722
				 G_CALLBACK(panel_menu_items_show_on_fusa), item);
1723
		if (fusa != NULL) {
1724
			gtk_widget_hide(GTK_WIDGET(item));
1725
		}
1726
	}
1727
1728
	/* Okay, this is confusing, but required to make the patch
1729
	 * smaller.  Basically if the seperator was created externally it
1730
	 * gets the signal handlers added when it is detected, but the
1731
	 * local variable remains NULL.  This allows the return in the
1732
	 * middle to still work.  But, if the seperator gets built in the
1733
	 * remainder of this function then the signal handlers get added
1734
	 * on here as the local variable becomes a pointer to that created
1735
	 * seperator.  Whew.  */
1736
	if (separator != NULL) {
1737
		g_object_weak_ref (G_OBJECT (separator),
1738
                                   (GWeakNotify) disconnect_signalers,
1739
                                   signaler);
1740
1741
		g_signal_connect(signaler, PANEL_APPLET_SIGNALER_SIGNAL_APPLET_ADDED,
1742
				 G_CALLBACK(panel_menu_items_hide_on_fusa), separator);
1743
		g_signal_connect(signaler, PANEL_APPLET_SIGNALER_SIGNAL_APPLET_REMOVED,
1744
				 G_CALLBACK(panel_menu_items_show_on_fusa), separator);
1745
		if (fusa != NULL) {
1746
			gtk_widget_hide(GTK_WIDGET(separator));
1747
		}
1.1.3 by Sebastian Dröge
Import upstream version 2.13.5
1748
	}
1.1.1 by Sebastien Bacher
Import upstream version 2.13.3
1749
}
1750
1751
void
1752
panel_menu_item_activate_desktop_file (GtkWidget  *menuitem,
1753
				       const char *path)
1754
{
1.1.48 by Sebastien Bacher
Import upstream version 2.25.3
1755
	panel_launch_desktop_file (path, menuitem_to_screen (menuitem), NULL);
1.1.1 by Sebastien Bacher
Import upstream version 2.13.3
1756
}