[18371] | 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> |
---|
[18646] | 27 | #include <egg-screen-exec.h> |
---|
[18371] | 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); |
---|
[18646] | 389 | egg_screen_execute_command_line_async ( |
---|
| 390 | gtk_widget_get_screen (drivemount->applet), command, &error); |
---|
[18371] | 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); |
---|
[18646] | 408 | gtk_window_set_screen (GTK_WINDOW (dialog), |
---|
| 409 | gtk_widget_get_screen (drivemount->applet)); |
---|
[18371] | 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) { |
---|
[18646] | 456 | gtk_window_set_screen (GTK_WINDOW (about), |
---|
| 457 | gtk_widget_get_screen (drivemount->applet)); |
---|
[18371] | 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"); |
---|
[18646] | 483 | gtk_window_set_screen (GTK_WINDOW (about), |
---|
| 484 | gtk_widget_get_screen (drivemount->applet)); |
---|
[18371] | 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) { |
---|
[18646] | 741 | gtk_window_set_screen (GTK_WINDOW (dd->error_dialog), |
---|
| 742 | gtk_widget_get_screen (dd->applet)); |
---|
[18371] | 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); |
---|
[18646] | 790 | gtk_window_set_screen (GTK_WINDOW (dd->error_dialog), |
---|
| 791 | gtk_widget_get_screen (dd->applet)); |
---|
[18371] | 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 | } |
---|