1 | /* |
---|
2 | * This program is free software; you can redistribute it and/or modify |
---|
3 | * it under the terms of the GNU General Public License as published by |
---|
4 | * the Free Software Foundation; either version 2 of the License, or |
---|
5 | * (at your option) any later version. |
---|
6 | * |
---|
7 | * This program is distributed in the hope that it will be useful, |
---|
8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
---|
10 | * GNU General Public License for more details. |
---|
11 | * |
---|
12 | * You should have received a copy of the GNU General Public License |
---|
13 | * along with this program; if not, write to the Free Software |
---|
14 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
---|
15 | */ |
---|
16 | |
---|
17 | #ifdef HAVE_CONFIG_H |
---|
18 | #include <config.h> |
---|
19 | #endif |
---|
20 | |
---|
21 | #include <stdio.h> |
---|
22 | #include <glib.h> |
---|
23 | #include <gtk/gtk.h> |
---|
24 | #include <libgnome/libgnome.h> |
---|
25 | #include <libgnomeui/libgnomeui.h> |
---|
26 | #include <panel-applet.h> |
---|
27 | #include <egg-screen-exec.h> |
---|
28 | |
---|
29 | #include "drivemount.h" |
---|
30 | #include "properties.h" |
---|
31 | |
---|
32 | #include "floppy_v_in.xpm" |
---|
33 | #include "floppy_v_out.xpm" |
---|
34 | #include "floppy_h_in.xpm" |
---|
35 | #include "floppy_h_out.xpm" |
---|
36 | #include "cdrom_v_in.xpm" |
---|
37 | #include "cdrom_v_out.xpm" |
---|
38 | #include "cdrom_h_in.xpm" |
---|
39 | #include "cdrom_h_out.xpm" |
---|
40 | #include "cdburn_v_in.xpm" |
---|
41 | #include "cdburn_v_out.xpm" |
---|
42 | #include "cdburn_h_in.xpm" |
---|
43 | #include "cdburn_h_out.xpm" |
---|
44 | #include "zipdrive_v_in.xpm" |
---|
45 | #include "zipdrive_v_out.xpm" |
---|
46 | #include "zipdrive_h_in.xpm" |
---|
47 | #include "zipdrive_h_out.xpm" |
---|
48 | #include "harddisk_v_in.xpm" |
---|
49 | #include "harddisk_v_out.xpm" |
---|
50 | #include "harddisk_h_in.xpm" |
---|
51 | #include "harddisk_h_out.xpm" |
---|
52 | |
---|
53 | #include "jazdrive_h_in.xpm" |
---|
54 | #include "jazdrive_h_out.xpm" |
---|
55 | #include "jazdrive_v_in.xpm" |
---|
56 | #include "jazdrive_v_out.xpm" |
---|
57 | |
---|
58 | |
---|
59 | static gboolean applet_factory (PanelApplet *applet, const gchar *iid, |
---|
60 | gpointer data); |
---|
61 | static gboolean applet_fill (PanelApplet *applet); |
---|
62 | static DriveData *create_drive_widget (PanelApplet *applet); |
---|
63 | static void dnd_init (DriveData *dd); |
---|
64 | static void dnd_drag_begin_cb (GtkWidget *widget, GdkDragContext *context, |
---|
65 | gpointer data); |
---|
66 | static void dnd_set_data_cb (GtkWidget *widget, GdkDragContext *context, |
---|
67 | GtkSelectionData *selection_data, guint info, |
---|
68 | guint time, gpointer data); |
---|
69 | static void applet_change_orient (GtkWidget *w, PanelAppletOrient o, |
---|
70 | gpointer data); |
---|
71 | static void applet_change_pixel_size (GtkWidget *w, int size, gpointer data); |
---|
72 | static gboolean button_press_hack (GtkWidget *widget, |
---|
73 | GdkEventButton *event, |
---|
74 | GtkWidget *applet); |
---|
75 | static void destroy_drive_widget (GtkWidget *widget, gpointer data); |
---|
76 | static gint device_is_in_mountlist (DriveData *dd); |
---|
77 | static gint get_device (const gchar *file); |
---|
78 | static gint device_is_mounted (DriveData *dd); |
---|
79 | static void update_pixmap (DriveData *dd, gint t); |
---|
80 | static gint drive_update_cb (gpointer data); |
---|
81 | static void mount_cb (GtkWidget *widget, DriveData *dd); |
---|
82 | static void eject (DriveData *dd); |
---|
83 | |
---|
84 | static void browse_cb (BonoboUIComponent *uic, |
---|
85 | DriveData *drivemount, |
---|
86 | const char *verb); |
---|
87 | static void eject_cb (BonoboUIComponent *uic, |
---|
88 | DriveData *drivemount, |
---|
89 | const char *verb); |
---|
90 | static void help_cb (BonoboUIComponent *uic, |
---|
91 | DriveData *drivemount, |
---|
92 | const char *verb); |
---|
93 | static void about_cb (BonoboUIComponent *uic, |
---|
94 | DriveData *drivemount, |
---|
95 | const char *verb); |
---|
96 | |
---|
97 | /* |
---|
98 | *------------------------------------------------------------------------- |
---|
99 | *icon struct |
---|
100 | *------------------------------------------------------------------------- |
---|
101 | */ |
---|
102 | |
---|
103 | typedef struct _IconData IconData; |
---|
104 | struct _IconData { |
---|
105 | char **pmap_h_in; |
---|
106 | char **pmap_h_out; |
---|
107 | char **pmap_v_in; |
---|
108 | char **pmap_v_out; |
---|
109 | }; |
---|
110 | |
---|
111 | static IconData icon_list[] = { |
---|
112 | { |
---|
113 | floppy_h_in_xpm, |
---|
114 | floppy_h_out_xpm, |
---|
115 | floppy_v_in_xpm, |
---|
116 | floppy_v_out_xpm}, |
---|
117 | { |
---|
118 | cdrom_h_in_xpm, |
---|
119 | cdrom_h_out_xpm, |
---|
120 | cdrom_v_in_xpm, |
---|
121 | cdrom_v_out_xpm}, |
---|
122 | { |
---|
123 | cdburn_h_in_xpm, |
---|
124 | cdburn_h_out_xpm, |
---|
125 | cdburn_v_in_xpm, |
---|
126 | cdburn_v_out_xpm}, |
---|
127 | { |
---|
128 | zipdrive_h_in_xpm, |
---|
129 | zipdrive_h_out_xpm, |
---|
130 | zipdrive_v_in_xpm, |
---|
131 | zipdrive_v_out_xpm}, |
---|
132 | { |
---|
133 | harddisk_h_in_xpm, |
---|
134 | harddisk_h_out_xpm, |
---|
135 | harddisk_v_in_xpm, |
---|
136 | harddisk_v_out_xpm}, |
---|
137 | { |
---|
138 | jazdrive_h_in_xpm, |
---|
139 | jazdrive_h_out_xpm, |
---|
140 | jazdrive_v_in_xpm, |
---|
141 | jazdrive_v_out_xpm}, |
---|
142 | { |
---|
143 | NULL, |
---|
144 | NULL, |
---|
145 | NULL, |
---|
146 | NULL} |
---|
147 | }; |
---|
148 | |
---|
149 | static gint icon_list_count = 6; |
---|
150 | |
---|
151 | /* Bonobo Verbs for our popup menu */ |
---|
152 | static const BonoboUIVerb applet_menu_verbs [] = { |
---|
153 | BONOBO_UI_UNSAFE_VERB ("Browse", browse_cb), |
---|
154 | BONOBO_UI_UNSAFE_VERB ("Eject", eject_cb), |
---|
155 | BONOBO_UI_UNSAFE_VERB ("Properties", properties_show), |
---|
156 | BONOBO_UI_UNSAFE_VERB ("Help", help_cb), |
---|
157 | BONOBO_UI_UNSAFE_VERB ("About", about_cb), |
---|
158 | BONOBO_UI_VERB_END |
---|
159 | }; |
---|
160 | |
---|
161 | enum { |
---|
162 | TARGET_URI_LIST, |
---|
163 | TARGET_TEXT_PLAIN |
---|
164 | }; |
---|
165 | |
---|
166 | static GtkTargetEntry button_drag_types[] = { |
---|
167 | {"text/uri-list", 0, TARGET_URI_LIST}, |
---|
168 | {"text/plain", 0, TARGET_TEXT_PLAIN} |
---|
169 | }; |
---|
170 | static gint n_button_drag_types = 2; |
---|
171 | |
---|
172 | |
---|
173 | PANEL_APPLET_BONOBO_FACTORY ("OAFIID:GNOME_DriveMountApplet_Factory", PANEL_TYPE_APPLET, |
---|
174 | "Drive-Mount-Applet", "0", applet_factory, NULL) |
---|
175 | |
---|
176 | static gboolean |
---|
177 | applet_factory (PanelApplet *applet, |
---|
178 | const gchar *iid, gpointer data) |
---|
179 | { |
---|
180 | gboolean retval = FALSE; |
---|
181 | |
---|
182 | if (!strcmp (iid, "OAFIID:GNOME_DriveMountApplet")) { |
---|
183 | retval = applet_fill (applet); |
---|
184 | } |
---|
185 | return retval; |
---|
186 | } |
---|
187 | |
---|
188 | static gboolean |
---|
189 | applet_fill (PanelApplet *applet) |
---|
190 | { |
---|
191 | DriveData *dd; |
---|
192 | BonoboUIComponent *component; |
---|
193 | gchar *tmp_path; |
---|
194 | |
---|
195 | gnome_window_icon_set_default_from_file (GNOME_ICONDIR"/drivemount-applet.png"); |
---|
196 | |
---|
197 | panel_applet_add_preferences (applet, |
---|
198 | "/schemas/apps/drivemount-applet/prefs", |
---|
199 | NULL); |
---|
200 | dd = create_drive_widget (applet); |
---|
201 | |
---|
202 | gtk_container_add (GTK_CONTAINER (applet), dd->button); |
---|
203 | |
---|
204 | dd->applet = GTK_WIDGET (applet); |
---|
205 | dd->tooltips = gtk_tooltips_new (); |
---|
206 | dd->orient = panel_applet_get_orient (PANEL_APPLET (applet)); |
---|
207 | dd->sizehint = panel_applet_get_size (PANEL_APPLET (applet)); |
---|
208 | g_signal_connect (G_OBJECT (dd->button), "button_press_event", |
---|
209 | G_CALLBACK (button_press_hack), applet); |
---|
210 | |
---|
211 | g_signal_connect (G_OBJECT (applet), "change_orient", |
---|
212 | G_CALLBACK (applet_change_orient), dd); |
---|
213 | g_signal_connect (G_OBJECT (applet), "change_size", |
---|
214 | G_CALLBACK (applet_change_pixel_size), dd); |
---|
215 | g_signal_connect (GTK_OBJECT (applet), "destroy", |
---|
216 | G_CALLBACK (destroy_drive_widget), dd); |
---|
217 | |
---|
218 | panel_applet_setup_menu_from_file (PANEL_APPLET (applet), |
---|
219 | NULL, |
---|
220 | "GNOME_DriveMountApplet.xml", |
---|
221 | NULL, |
---|
222 | applet_menu_verbs, |
---|
223 | dd); |
---|
224 | |
---|
225 | component = panel_applet_get_popup_component (PANEL_APPLET (applet)); |
---|
226 | |
---|
227 | tmp_path = gnome_is_program_in_path ("eject"); |
---|
228 | if (!tmp_path) |
---|
229 | bonobo_ui_component_set_prop (component, "/commands/Eject", |
---|
230 | "hidden", "1", NULL); |
---|
231 | else |
---|
232 | g_free (tmp_path); |
---|
233 | |
---|
234 | redraw_pixmap (dd); |
---|
235 | gtk_widget_show (GTK_WIDGET (applet)); |
---|
236 | start_callback_update (dd); |
---|
237 | return TRUE; |
---|
238 | } |
---|
239 | |
---|
240 | static DriveData * |
---|
241 | create_drive_widget (PanelApplet *applet) |
---|
242 | { |
---|
243 | DriveData *dd; |
---|
244 | |
---|
245 | dd = g_new0 (DriveData, 1); |
---|
246 | dd->applet = GTK_WIDGET (applet); |
---|
247 | |
---|
248 | properties_load (dd); |
---|
249 | |
---|
250 | dd->button = gtk_button_new (); |
---|
251 | gtk_widget_show (dd->button); |
---|
252 | g_signal_connect (G_OBJECT (dd->button), "clicked", |
---|
253 | G_CALLBACK (mount_cb), dd); |
---|
254 | dnd_init (dd); |
---|
255 | return dd; |
---|
256 | } |
---|
257 | |
---|
258 | /* This is a hack around the fact that gtk+ doesn't |
---|
259 | * propogate button presses on button2/3. |
---|
260 | */ |
---|
261 | static gboolean |
---|
262 | button_press_hack (GtkWidget *widget, |
---|
263 | GdkEventButton *event, |
---|
264 | GtkWidget *applet) |
---|
265 | { |
---|
266 | if (event->button == 3 || event->button == 2) { |
---|
267 | gtk_propagate_event (applet, (GdkEvent *) event); |
---|
268 | |
---|
269 | return TRUE; |
---|
270 | } |
---|
271 | |
---|
272 | return FALSE; |
---|
273 | } |
---|
274 | |
---|
275 | static void |
---|
276 | dnd_init (DriveData *dd) |
---|
277 | { |
---|
278 | gtk_drag_source_set (dd->button, GDK_BUTTON1_MASK, |
---|
279 | button_drag_types, n_button_drag_types, |
---|
280 | GDK_ACTION_COPY | GDK_ACTION_LINK | |
---|
281 | GDK_ACTION_ASK); |
---|
282 | g_signal_connect (G_OBJECT (dd->button), "drag_data_get", |
---|
283 | G_CALLBACK (dnd_set_data_cb), dd); |
---|
284 | g_signal_connect (G_OBJECT (dd->button), "drag_begin", |
---|
285 | G_CALLBACK (dnd_drag_begin_cb), dd); |
---|
286 | } |
---|
287 | |
---|
288 | static void |
---|
289 | dnd_drag_begin_cb (GtkWidget *widget, GdkDragContext *context, gpointer data) |
---|
290 | { |
---|
291 | DriveData *dd = data; |
---|
292 | |
---|
293 | gtk_drag_set_icon_pixbuf (context, |
---|
294 | gtk_image_get_pixbuf (GTK_IMAGE |
---|
295 | (dd->button_pixmap)), |
---|
296 | -5, -5); |
---|
297 | } |
---|
298 | |
---|
299 | static void |
---|
300 | dnd_set_data_cb (GtkWidget *widget, GdkDragContext *context, |
---|
301 | GtkSelectionData *selection_data, guint info, |
---|
302 | guint time, gpointer data) |
---|
303 | { |
---|
304 | DriveData *dd = data; |
---|
305 | |
---|
306 | if (dd && dd->mount_point) { |
---|
307 | gchar *text = NULL; |
---|
308 | |
---|
309 | switch (info) { |
---|
310 | case TARGET_URI_LIST: |
---|
311 | text = g_strconcat ("file:", dd->mount_point, "\r\n", |
---|
312 | NULL); |
---|
313 | break; |
---|
314 | case TARGET_TEXT_PLAIN: |
---|
315 | text = g_strdup (dd->mount_point); |
---|
316 | break; |
---|
317 | } |
---|
318 | gtk_selection_data_set (selection_data, selection_data->target, |
---|
319 | 8, text, strlen (text)); |
---|
320 | g_free (text); |
---|
321 | } else { |
---|
322 | gtk_selection_data_set (selection_data, selection_data->target, |
---|
323 | 8, NULL, 0); |
---|
324 | } |
---|
325 | } |
---|
326 | |
---|
327 | void |
---|
328 | start_callback_update (DriveData *dd) |
---|
329 | { |
---|
330 | gint delay; |
---|
331 | |
---|
332 | delay = dd->interval *1000; |
---|
333 | if (dd->timeout_id) |
---|
334 | gtk_timeout_remove (dd->timeout_id); |
---|
335 | dd->timeout_id = |
---|
336 | gtk_timeout_add (delay, (GtkFunction) drive_update_cb, dd); |
---|
337 | } |
---|
338 | |
---|
339 | static void |
---|
340 | applet_change_orient (GtkWidget *w, PanelAppletOrient o, gpointer data) |
---|
341 | { |
---|
342 | /* resize the applet and set the proper pixmaps */ |
---|
343 | DriveData *dd = data; |
---|
344 | |
---|
345 | if (dd->orient == o) |
---|
346 | return; |
---|
347 | |
---|
348 | dd->orient = o; |
---|
349 | |
---|
350 | redraw_pixmap (dd); |
---|
351 | } |
---|
352 | |
---|
353 | static void |
---|
354 | applet_change_pixel_size (GtkWidget *w, int size, gpointer data) |
---|
355 | { |
---|
356 | DriveData *dd = data; |
---|
357 | |
---|
358 | if (dd->sizehint != size) { |
---|
359 | dd->sizehint = size; |
---|
360 | redraw_pixmap (dd); |
---|
361 | } |
---|
362 | } |
---|
363 | |
---|
364 | static void |
---|
365 | destroy_drive_widget (GtkWidget *widget, gpointer data) |
---|
366 | { |
---|
367 | DriveData *dd = data; |
---|
368 | |
---|
369 | g_free (dd->mount_point); |
---|
370 | g_free (dd->mount_base); |
---|
371 | g_free (dd); |
---|
372 | } |
---|
373 | |
---|
374 | static void |
---|
375 | browse_cb (BonoboUIComponent *uic, |
---|
376 | DriveData *drivemount, |
---|
377 | const char *verb) |
---|
378 | { |
---|
379 | GError *error = NULL; |
---|
380 | char *command; |
---|
381 | |
---|
382 | if (!drivemount->mounted) |
---|
383 | mount_cb (NULL, drivemount); |
---|
384 | |
---|
385 | if (!drivemount->mounted) |
---|
386 | return; |
---|
387 | |
---|
388 | command = g_strdup_printf ("nautilus %s", drivemount->mount_point); |
---|
389 | egg_screen_execute_command_line_async ( |
---|
390 | gtk_widget_get_screen (drivemount->applet), command, &error); |
---|
391 | g_free (command); |
---|
392 | if (error) { |
---|
393 | GtkWidget *dialog; |
---|
394 | |
---|
395 | dialog = gtk_message_dialog_new (NULL, |
---|
396 | GTK_DIALOG_DESTROY_WITH_PARENT, |
---|
397 | GTK_MESSAGE_ERROR, |
---|
398 | GTK_BUTTONS_CLOSE, |
---|
399 | _("There was an error executing '%s' : %s"), |
---|
400 | command, |
---|
401 | error->message); |
---|
402 | |
---|
403 | g_signal_connect (dialog, "response", |
---|
404 | G_CALLBACK (gtk_widget_destroy), |
---|
405 | NULL); |
---|
406 | |
---|
407 | gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE); |
---|
408 | gtk_window_set_screen (GTK_WINDOW (dialog), |
---|
409 | gtk_widget_get_screen (drivemount->applet)); |
---|
410 | |
---|
411 | gtk_widget_show (dialog); |
---|
412 | |
---|
413 | g_error_free (error); |
---|
414 | } |
---|
415 | } |
---|
416 | |
---|
417 | static void |
---|
418 | eject_cb (BonoboUIComponent *uic, |
---|
419 | DriveData *drivemount, |
---|
420 | const char *verb) |
---|
421 | { |
---|
422 | eject (drivemount); |
---|
423 | } |
---|
424 | |
---|
425 | static void |
---|
426 | help_cb (BonoboUIComponent *uic, |
---|
427 | DriveData *drivemount, |
---|
428 | const char *verb) |
---|
429 | |
---|
430 | { |
---|
431 | } |
---|
432 | |
---|
433 | static void |
---|
434 | about_cb (BonoboUIComponent *uic, |
---|
435 | DriveData *drivemount, |
---|
436 | const char *verb) |
---|
437 | { |
---|
438 | static GtkWidget *about = NULL; |
---|
439 | GdkPixbuf *pixbuf; |
---|
440 | GError *error = NULL; |
---|
441 | gchar *file; |
---|
442 | |
---|
443 | static const gchar *authors[] = { |
---|
444 | "John Ellis <johne@bellatlantic.net>", |
---|
445 | "Chris Phelps <chicane@renient.com>", |
---|
446 | NULL |
---|
447 | }; |
---|
448 | |
---|
449 | const gchar *documenters[] = { |
---|
450 | NULL |
---|
451 | }; |
---|
452 | |
---|
453 | const gchar *translator_credits = _("translator_credits"); |
---|
454 | |
---|
455 | if (about) { |
---|
456 | gtk_window_set_screen (GTK_WINDOW (about), |
---|
457 | gtk_widget_get_screen (drivemount->applet)); |
---|
458 | gtk_window_present (GTK_WINDOW (about)); |
---|
459 | return; |
---|
460 | } |
---|
461 | |
---|
462 | file = gnome_program_locate_file (NULL, GNOME_FILE_DOMAIN_PIXMAP, "drivemount-applet.png", FALSE, NULL); |
---|
463 | pixbuf = gdk_pixbuf_new_from_file (file, &error); |
---|
464 | g_free (file); |
---|
465 | |
---|
466 | if (error) { |
---|
467 | g_warning (G_STRLOC ": cannot open %s: %s", file, error->message); |
---|
468 | g_error_free (error); |
---|
469 | } |
---|
470 | |
---|
471 | about = gnome_about_new (_("Disk Mounter"), VERSION, |
---|
472 | _("(C) 1999-2001 The GNOME Hackers\n"), |
---|
473 | _ |
---|
474 | ("Applet for mounting and unmounting block volumes."), |
---|
475 | authors, |
---|
476 | documenters, |
---|
477 | strcmp (translator_credits, "translator_credits") != 0 ? translator_credits : NULL, |
---|
478 | pixbuf); |
---|
479 | if (pixbuf) |
---|
480 | gdk_pixbuf_unref (pixbuf); |
---|
481 | |
---|
482 | gtk_window_set_wmclass (GTK_WINDOW (about), "disk mounter", "Disk Mounter"); |
---|
483 | gtk_window_set_screen (GTK_WINDOW (about), |
---|
484 | gtk_widget_get_screen (drivemount->applet)); |
---|
485 | g_signal_connect (G_OBJECT (about), "destroy", |
---|
486 | G_CALLBACK (gtk_widget_destroyed), &about); |
---|
487 | gtk_widget_show (about); |
---|
488 | } |
---|
489 | |
---|
490 | /* |
---|
491 | *------------------------------------------------------------------------- |
---|
492 | *mount status checks |
---|
493 | *------------------------------------------------------------------------- |
---|
494 | */ |
---|
495 | |
---|
496 | static gint |
---|
497 | device_is_in_mountlist (DriveData *dd) |
---|
498 | { |
---|
499 | FILE *fp; |
---|
500 | gchar *command_line = "mount"; |
---|
501 | gchar buf[256]; |
---|
502 | gint found = FALSE; |
---|
503 | |
---|
504 | if (!dd->mount_point) |
---|
505 | return FALSE; |
---|
506 | |
---|
507 | fp = popen (command_line, "r"); |
---|
508 | if (!fp) { |
---|
509 | g_print ("unable to run command: %s\n", command_line); |
---|
510 | return FALSE; |
---|
511 | } |
---|
512 | while (fgets (buf, sizeof (buf), fp)) { |
---|
513 | gchar *ptr; |
---|
514 | ptr = strstr (buf, dd->mount_point); |
---|
515 | if (ptr != NULL) { |
---|
516 | gchar *p; |
---|
517 | p = ptr + strlen (dd->mount_point); |
---|
518 | if (*p == ' ' || *p == '\0' || *p == '\n') { |
---|
519 | found = TRUE; |
---|
520 | break; |
---|
521 | } |
---|
522 | } |
---|
523 | } |
---|
524 | pclose (fp); |
---|
525 | return found; |
---|
526 | } |
---|
527 | |
---|
528 | static gint |
---|
529 | get_device (const gchar *file) |
---|
530 | { |
---|
531 | struct stat file_info; |
---|
532 | gint t; |
---|
533 | |
---|
534 | if (stat (file, &file_info) == -1) |
---|
535 | t = -1; |
---|
536 | else |
---|
537 | t = (gint) file_info.st_dev; |
---|
538 | return t; |
---|
539 | } |
---|
540 | |
---|
541 | static gint |
---|
542 | device_is_mounted (DriveData *dd) |
---|
543 | { |
---|
544 | if (!dd->mount_point || !dd->mount_base) |
---|
545 | return FALSE; |
---|
546 | |
---|
547 | if (!dd->autofs_friendly) { |
---|
548 | gint b, p; |
---|
549 | |
---|
550 | b = get_device (dd->mount_base); |
---|
551 | p = get_device (dd->mount_point); |
---|
552 | if (b == p || p == -1 || b == -1) |
---|
553 | return FALSE; |
---|
554 | else |
---|
555 | return TRUE; |
---|
556 | } else { |
---|
557 | if (device_is_in_mountlist (dd)) |
---|
558 | return TRUE; |
---|
559 | else |
---|
560 | return FALSE; |
---|
561 | } |
---|
562 | } |
---|
563 | |
---|
564 | /* |
---|
565 | *------------------------------------------------------------------------- |
---|
566 | *image / widget setup and size changes |
---|
567 | *------------------------------------------------------------------------- |
---|
568 | */ |
---|
569 | |
---|
570 | static void |
---|
571 | update_pixmap (DriveData *dd, gint t) |
---|
572 | { |
---|
573 | GdkPixbuf *pixbuf; |
---|
574 | GdkPixbuf *scaled; |
---|
575 | char **pmap_d_in; |
---|
576 | char **pmap_d_out; |
---|
577 | |
---|
578 | gint width; |
---|
579 | gint height; |
---|
580 | |
---|
581 | gchar *tiptext; |
---|
582 | gchar *text; |
---|
583 | |
---|
584 | gint hint = dd->sizehint; |
---|
585 | |
---|
586 | if (dd->device_pixmap > icon_list_count - 1) |
---|
587 | dd->device_pixmap = 0; |
---|
588 | if (dd->device_pixmap < 0 |
---|
589 | && (!dd->custom_icon_in || !dd->custom_icon_out)) |
---|
590 | dd->device_pixmap = 0; |
---|
591 | |
---|
592 | if (!dd->button_pixmap) { |
---|
593 | dd->button_pixmap = gtk_image_new (); |
---|
594 | gtk_container_add (GTK_CONTAINER (dd->button), |
---|
595 | dd->button_pixmap); |
---|
596 | gtk_widget_show (dd->button_pixmap); |
---|
597 | } |
---|
598 | |
---|
599 | if (dd->device_pixmap < 0) { |
---|
600 | if (t) { |
---|
601 | pixbuf = gdk_pixbuf_new_from_file (dd->custom_icon_in, |
---|
602 | NULL); |
---|
603 | } else { |
---|
604 | pixbuf = gdk_pixbuf_new_from_file (dd->custom_icon_out, |
---|
605 | NULL); |
---|
606 | } |
---|
607 | |
---|
608 | if (pixbuf) { |
---|
609 | width = gdk_pixbuf_get_width (pixbuf); |
---|
610 | height = gdk_pixbuf_get_width (pixbuf); |
---|
611 | |
---|
612 | if (dd->orient == PANEL_APPLET_ORIENT_LEFT |
---|
613 | || dd->orient == PANEL_APPLET_ORIENT_RIGHT) { |
---|
614 | if (width > hint || dd->scale_applet) { |
---|
615 | height = (float) height *hint / width; |
---|
616 | |
---|
617 | width = hint; |
---|
618 | } |
---|
619 | } else { |
---|
620 | if (height > hint || dd->scale_applet) { |
---|
621 | width = (float) width *hint / height; |
---|
622 | |
---|
623 | height = hint; |
---|
624 | } |
---|
625 | } |
---|
626 | scaled = gdk_pixbuf_scale_simple (pixbuf, width, height, |
---|
627 | GDK_INTERP_BILINEAR); |
---|
628 | gtk_image_set_from_pixbuf (GTK_IMAGE |
---|
629 | (dd->button_pixmap), scaled); |
---|
630 | g_object_unref (G_OBJECT (pixbuf)); |
---|
631 | g_object_unref (scaled); |
---|
632 | } |
---|
633 | } else { |
---|
634 | if (dd->scale_applet) { |
---|
635 | width = hint; |
---|
636 | height = (float) hint / ICON_WIDTH *ICON_HEIGHT; |
---|
637 | } else { |
---|
638 | width = ICON_WIDTH; |
---|
639 | height = ICON_HEIGHT; |
---|
640 | } |
---|
641 | |
---|
642 | if (dd->orient == PANEL_APPLET_ORIENT_LEFT |
---|
643 | || dd->orient == PANEL_APPLET_ORIENT_RIGHT || hint <= 36) { |
---|
644 | pmap_d_in = icon_list[dd->device_pixmap].pmap_h_in; |
---|
645 | pmap_d_out = icon_list[dd->device_pixmap].pmap_h_out; |
---|
646 | } else { |
---|
647 | gint tmp; |
---|
648 | |
---|
649 | tmp = width; |
---|
650 | width = height; |
---|
651 | height = tmp; |
---|
652 | |
---|
653 | pmap_d_in = icon_list[dd->device_pixmap].pmap_v_in; |
---|
654 | pmap_d_out = icon_list[dd->device_pixmap].pmap_v_out; |
---|
655 | } |
---|
656 | |
---|
657 | if (t) |
---|
658 | pixbuf = gdk_pixbuf_new_from_xpm_data ((const char **) |
---|
659 | pmap_d_in); |
---|
660 | else |
---|
661 | pixbuf = gdk_pixbuf_new_from_xpm_data ((const char **) |
---|
662 | pmap_d_out); |
---|
663 | scaled = gdk_pixbuf_scale_simple (pixbuf, width, height, |
---|
664 | GDK_INTERP_BILINEAR); |
---|
665 | gtk_image_set_from_pixbuf (GTK_IMAGE (dd->button_pixmap), |
---|
666 | scaled); |
---|
667 | g_object_unref (G_OBJECT (pixbuf)); |
---|
668 | g_object_unref (scaled); |
---|
669 | } |
---|
670 | |
---|
671 | if (t) { |
---|
672 | text = _(" mounted"); |
---|
673 | } else { |
---|
674 | text = _(" not mounted"); |
---|
675 | } |
---|
676 | tiptext = g_strconcat (dd->mount_point, text, NULL); |
---|
677 | gtk_tooltips_set_tip (dd->tooltips, dd->applet, tiptext, NULL); |
---|
678 | g_free (tiptext); |
---|
679 | } |
---|
680 | |
---|
681 | void |
---|
682 | redraw_pixmap (DriveData *dd) |
---|
683 | { |
---|
684 | if (!device_is_mounted (dd)) { |
---|
685 | update_pixmap (dd, FALSE); |
---|
686 | dd->mounted = FALSE; |
---|
687 | } else { |
---|
688 | update_pixmap (dd, TRUE); |
---|
689 | dd->mounted = TRUE; |
---|
690 | } |
---|
691 | } |
---|
692 | |
---|
693 | /* |
---|
694 | *------------------------------------------------------------------------- |
---|
695 | *main callback loop |
---|
696 | *------------------------------------------------------------------------- |
---|
697 | */ |
---|
698 | |
---|
699 | static gint |
---|
700 | drive_update_cb (gpointer data) |
---|
701 | { |
---|
702 | DriveData *dd = data; |
---|
703 | |
---|
704 | if (!device_is_mounted (dd)) { |
---|
705 | /* device not mounted */ |
---|
706 | if (dd->mounted) { |
---|
707 | update_pixmap (dd, FALSE); |
---|
708 | dd->mounted = FALSE; |
---|
709 | } |
---|
710 | } else { |
---|
711 | /* device mounted */ |
---|
712 | if (!dd->mounted) { |
---|
713 | update_pixmap (dd, TRUE); |
---|
714 | dd->mounted = TRUE; |
---|
715 | } |
---|
716 | } |
---|
717 | return TRUE; |
---|
718 | } |
---|
719 | |
---|
720 | /* |
---|
721 | *------------------------------------------------------------------------- |
---|
722 | *mount calls |
---|
723 | *------------------------------------------------------------------------- |
---|
724 | */ |
---|
725 | |
---|
726 | static void |
---|
727 | mount_cb (GtkWidget *widget, |
---|
728 | DriveData *dd) |
---|
729 | { |
---|
730 | gchar *command_line; |
---|
731 | gchar buf[512]; |
---|
732 | FILE *fp; |
---|
733 | GString *str; |
---|
734 | gint check = device_is_mounted (dd); |
---|
735 | GtkWidget *hbox; |
---|
736 | GtkWidget *label; |
---|
737 | GtkWidget *image; |
---|
738 | |
---|
739 | /* Stop the user from displaying zillions of error messages */ |
---|
740 | if (dd->error_dialog) { |
---|
741 | gtk_window_set_screen (GTK_WINDOW (dd->error_dialog), |
---|
742 | gtk_widget_get_screen (dd->applet)); |
---|
743 | gtk_window_present (GTK_WINDOW (dd->error_dialog)); |
---|
744 | return; |
---|
745 | } |
---|
746 | |
---|
747 | if (!check) { |
---|
748 | command_line = |
---|
749 | g_strdup_printf ("mount %s 2>&1", dd->mount_point); |
---|
750 | } else { |
---|
751 | command_line = |
---|
752 | g_strdup_printf ("umount %s 2>&1", dd->mount_point); |
---|
753 | } |
---|
754 | |
---|
755 | fp = popen (command_line, "r"); |
---|
756 | |
---|
757 | if (!fp) { |
---|
758 | printf ("unable to run command: %s\n", command_line); |
---|
759 | g_free (command_line); |
---|
760 | return; |
---|
761 | } |
---|
762 | |
---|
763 | str = g_string_new (NULL); |
---|
764 | |
---|
765 | while (fgets (buf, sizeof (buf), fp) != NULL) { |
---|
766 | gchar *b = buf; |
---|
767 | |
---|
768 | g_string_append (str, b); |
---|
769 | } |
---|
770 | |
---|
771 | pclose (fp); |
---|
772 | |
---|
773 | dd->mounted = device_is_mounted (dd); |
---|
774 | |
---|
775 | if (check != dd->mounted) { |
---|
776 | /* success! */ |
---|
777 | update_pixmap (dd, dd->mounted); |
---|
778 | |
---|
779 | /* eject after unmounting, if enabled */ |
---|
780 | if (check && dd->auto_eject) { |
---|
781 | eject (dd); |
---|
782 | } |
---|
783 | } else { |
---|
784 | dd->error_dialog = |
---|
785 | gtk_dialog_new_with_buttons (_ |
---|
786 | ("Drive Mount Applet Warning"), |
---|
787 | NULL, GTK_DIALOG_MODAL, |
---|
788 | GTK_STOCK_OK, |
---|
789 | GTK_RESPONSE_OK, NULL); |
---|
790 | gtk_window_set_screen (GTK_WINDOW (dd->error_dialog), |
---|
791 | gtk_widget_get_screen (dd->applet)); |
---|
792 | hbox = gtk_hbox_new (FALSE, 0); |
---|
793 | gtk_box_pack_start (GTK_BOX |
---|
794 | (GTK_DIALOG (dd->error_dialog)->vbox), hbox, |
---|
795 | FALSE, FALSE, 10); |
---|
796 | g_string_prepend (str, _("\" reported:\n")); |
---|
797 | g_string_prepend (str, command_line); |
---|
798 | g_string_prepend (str, _("Drivemount command failed.\n\"")); |
---|
799 | image = gtk_image_new_from_stock (GTK_STOCK_DIALOG_ERROR, |
---|
800 | GTK_ICON_SIZE_DIALOG); |
---|
801 | gtk_box_pack_start (GTK_BOX (hbox), image, FALSE, FALSE, 10); |
---|
802 | label = gtk_label_new (str->str); |
---|
803 | gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 10); |
---|
804 | gtk_widget_show_all (dd->error_dialog); |
---|
805 | gtk_dialog_run (GTK_DIALOG (dd->error_dialog)); |
---|
806 | gtk_widget_destroy (dd->error_dialog); |
---|
807 | dd->error_dialog = NULL; |
---|
808 | } |
---|
809 | g_string_free (str, TRUE); |
---|
810 | g_free (command_line); |
---|
811 | return; |
---|
812 | } |
---|
813 | |
---|
814 | static void |
---|
815 | eject (DriveData *dd) |
---|
816 | { |
---|
817 | gchar *command_line; |
---|
818 | gchar buffer[512]; |
---|
819 | gchar dn[256]; /* Devicename */ |
---|
820 | gchar mp[256]; /* Mountpoint */ |
---|
821 | FILE *ml; /* Mountlist */ |
---|
822 | gint found = FALSE; |
---|
823 | |
---|
824 | if (!dd->mount_point) |
---|
825 | return; |
---|
826 | |
---|
827 | /* |
---|
828 | * Search the output of mount for dd->mount_point |
---|
829 | * and use the corresponting device name |
---|
830 | * as argument for eject |
---|
831 | * if the device is not mounted currently, use |
---|
832 | * /etc/fstab for the check |
---|
833 | */ |
---|
834 | |
---|
835 | if (dd->mounted) { |
---|
836 | ml = popen ("mount", "r"); |
---|
837 | while (ml && fgets (buffer, sizeof (buffer), ml)) { |
---|
838 | if (sscanf (buffer, "%255s %*s %255s", dn, mp) == 2 && |
---|
839 | (mp && strcmp (mp, dd->mount_point) == 0)) { |
---|
840 | found = TRUE; |
---|
841 | break; |
---|
842 | } |
---|
843 | } |
---|
844 | if (ml) |
---|
845 | pclose (ml); |
---|
846 | } else { |
---|
847 | ml = fopen ("/etc/fstab", "r"); |
---|
848 | |
---|
849 | while (ml && fgets (buffer, sizeof (buffer), ml)) { |
---|
850 | if (sscanf (buffer, "%255s %255s", dn, mp) == 2 && |
---|
851 | strcmp (mp, dd->mount_point) == 0) { |
---|
852 | found = TRUE; |
---|
853 | break; |
---|
854 | } |
---|
855 | } |
---|
856 | if (ml) |
---|
857 | fclose (ml); |
---|
858 | } |
---|
859 | |
---|
860 | if (!found) { /* mp != dd->mount_point */ |
---|
861 | printf ("WARNING: drivemount.c ... dd->mount_point not found in list\ |
---|
862 | (output of mount, or /etc/fstab) \n"); |
---|
863 | return; |
---|
864 | } |
---|
865 | |
---|
866 | if (dd->mounted) { |
---|
867 | command_line = g_strdup_printf ("eject -u '%s'", dn); |
---|
868 | /* perhaps it doesn't like the -u option */ |
---|
869 | if (system (command_line) != 0) { |
---|
870 | g_free (command_line); |
---|
871 | command_line = g_strdup_printf ("eject '%s'", dn); |
---|
872 | gnome_execute_shell (NULL, command_line); |
---|
873 | } |
---|
874 | g_free (command_line); |
---|
875 | } else { |
---|
876 | command_line = g_strdup_printf ("eject '%s'", dn); |
---|
877 | gnome_execute_shell (NULL, command_line); |
---|
878 | g_free (command_line); |
---|
879 | } |
---|
880 | } |
---|