source: trunk/third/gnome-applets/drivemount/drivemount.c @ 20910

Revision 20910, 27.4 KB checked in by ghudson, 20 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r20909, which included commits to RCS files with non-trunk default branches.
Line 
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
28#include "drivemount.h"
29#include "properties.h"
30
31#include "floppy_v_in.xpm"
32#include "floppy_v_out.xpm"
33#include "floppy_h_in.xpm"
34#include "floppy_h_out.xpm"
35
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
41#include "cdburn_v_in.xpm"
42#include "cdburn_v_out.xpm"
43#include "cdburn_h_in.xpm"
44#include "cdburn_h_out.xpm"
45
46#include "zipdrive_v_in.xpm"
47#include "zipdrive_v_out.xpm"
48#include "zipdrive_h_in.xpm"
49#include "zipdrive_h_out.xpm"
50
51#include "harddisk_v_in.xpm"
52#include "harddisk_v_out.xpm"
53#include "harddisk_h_in.xpm"
54#include "harddisk_h_out.xpm"
55
56#include "jazdrive_h_in.xpm"
57#include "jazdrive_h_out.xpm"
58#include "jazdrive_v_in.xpm"
59#include "jazdrive_v_out.xpm"
60
61#include "usbstick_v_in.xpm"
62#include "usbstick_v_out.xpm"
63#include "usbstick_h_in.xpm"
64#include "usbstick_h_out.xpm"
65
66
67static gboolean applet_factory (PanelApplet *applet, const gchar *iid,
68                                gpointer data);
69static gboolean applet_fill (PanelApplet *applet);
70static DriveData *create_drive_widget (PanelApplet *applet);
71static void dnd_init (DriveData *dd);
72static void dnd_drag_begin_cb (GtkWidget *widget, GdkDragContext *context,
73                               gpointer data);
74static void dnd_set_data_cb (GtkWidget *widget, GdkDragContext *context,
75                             GtkSelectionData *selection_data, guint info,
76                             guint time, gpointer data);
77static void applet_change_orient (GtkWidget *w, PanelAppletOrient o,
78                                  gpointer data);
79static void applet_change_pixel_size (GtkWidget *w, int size, gpointer data);
80static gboolean button_press_hack (GtkWidget      *widget,
81                                   GdkEventButton *event,
82                                   GtkWidget      *applet);
83static void destroy_drive_widget (GtkWidget *widget, gpointer data);
84static gint device_is_in_mountlist (DriveData *dd);
85static gint get_device (const gchar *file);
86static gint device_is_mounted (DriveData *dd);
87static void update_pixmap (DriveData *dd, gint t);
88static gint drive_update_cb (gpointer data);
89static void mount_cb (GtkWidget *widget, DriveData *dd);
90static void eject (DriveData *dd);
91static gboolean key_press_cb (GtkWidget *widget, GdkEventKey *event, DriveData *dd);
92
93static void browse_cb (BonoboUIComponent *uic,
94                       DriveData         *drivemount,
95                       const char        *verb);
96static void eject_cb  (BonoboUIComponent *uic,
97                       DriveData         *drivemount,
98                       const char        *verb);
99static void help_cb   (BonoboUIComponent *uic,
100                       DriveData         *drivemount,
101                       const char        *verb);
102static void about_cb  (BonoboUIComponent *uic,
103                       DriveData         *drivemount,
104                       const char        *verb);
105
106/*
107 *-------------------------------------------------------------------------
108 *icon struct
109 *-------------------------------------------------------------------------
110 */
111
112typedef struct _IconData IconData;
113struct _IconData {
114        char **pmap_h_in;
115        char **pmap_h_out;
116        char **pmap_v_in;
117        char **pmap_v_out;
118};
119
120static IconData icon_list[] = {
121        {
122         floppy_h_in_xpm,
123         floppy_h_out_xpm,
124         floppy_v_in_xpm,
125         floppy_v_out_xpm},
126        {
127         cdrom_h_in_xpm,
128         cdrom_h_out_xpm,
129         cdrom_v_in_xpm,
130         cdrom_v_out_xpm},
131        {
132         cdburn_h_in_xpm,
133         cdburn_h_out_xpm,
134         cdburn_v_in_xpm,
135         cdburn_v_out_xpm},
136        {
137         zipdrive_h_in_xpm,
138         zipdrive_h_out_xpm,
139         zipdrive_v_in_xpm,
140         zipdrive_v_out_xpm},
141        {
142         harddisk_h_in_xpm,
143         harddisk_h_out_xpm,
144         harddisk_v_in_xpm,
145         harddisk_v_out_xpm},
146        {
147         jazdrive_h_in_xpm,
148         jazdrive_h_out_xpm,
149         jazdrive_v_in_xpm,
150         jazdrive_v_out_xpm},
151        {
152         usbstick_h_in_xpm,
153         usbstick_h_out_xpm,
154         usbstick_v_in_xpm,
155         usbstick_v_out_xpm},
156        {
157         NULL,
158         NULL,
159         NULL,
160         NULL}
161};
162
163const int icon_list_count = 7;
164
165/* Bonobo Verbs for our popup menu */
166static const BonoboUIVerb applet_menu_verbs [] = {
167        BONOBO_UI_UNSAFE_VERB ("Browse", browse_cb),
168        BONOBO_UI_UNSAFE_VERB ("Eject", eject_cb),
169        BONOBO_UI_UNSAFE_VERB ("Properties", properties_show),
170        BONOBO_UI_UNSAFE_VERB ("Help", help_cb),
171        BONOBO_UI_UNSAFE_VERB ("About", about_cb),
172        BONOBO_UI_VERB_END
173};
174
175enum {
176        TARGET_URI_LIST,
177        TARGET_TEXT_PLAIN
178};
179
180static GtkTargetEntry button_drag_types[] = {
181        {"text/uri-list", 0, TARGET_URI_LIST},
182        {"text/plain", 0, TARGET_TEXT_PLAIN}
183};
184static gint n_button_drag_types = 2;
185
186
187PANEL_APPLET_BONOBO_FACTORY ("OAFIID:GNOME_DriveMountApplet_Factory", PANEL_TYPE_APPLET,
188                             "Drive-Mount-Applet", "0", applet_factory, NULL)
189
190static gboolean
191applet_factory (PanelApplet *applet,
192                const gchar *iid, gpointer data)
193{
194        gboolean retval = FALSE;
195
196        if (!strcmp (iid, "OAFIID:GNOME_DriveMountApplet")) {
197                retval = applet_fill (applet);
198        }
199        return retval;
200}
201
202static gboolean
203applet_fill (PanelApplet *applet)
204{
205        DriveData *dd;
206        BonoboUIComponent *component;
207        gchar *tmp_path;
208        AtkObject *atk_obj;
209       
210        gnome_window_icon_set_default_from_file (GNOME_ICONDIR"/drivemount-applet.png");
211        panel_applet_set_flags (applet, PANEL_APPLET_EXPAND_MINOR);
212       
213        panel_applet_add_preferences (applet,
214                                      "/schemas/apps/drivemount-applet/prefs",
215                                      NULL);
216        dd = create_drive_widget (applet);
217
218        gtk_container_add (GTK_CONTAINER (applet), dd->button);
219
220        dd->applet = GTK_WIDGET (applet);
221        dd->tooltips = gtk_tooltips_new ();
222        dd->orient = panel_applet_get_orient (PANEL_APPLET (applet));
223        dd->sizehint = panel_applet_get_size (PANEL_APPLET (applet));
224        g_signal_connect (G_OBJECT (dd->button), "button_press_event",
225                          G_CALLBACK (button_press_hack), applet);
226
227        g_signal_connect (G_OBJECT (applet), "change_orient",
228                          G_CALLBACK (applet_change_orient), dd);
229        g_signal_connect (G_OBJECT (applet), "change_size",
230                          G_CALLBACK (applet_change_pixel_size), dd);
231        g_signal_connect (GTK_OBJECT (applet), "destroy",
232                          G_CALLBACK (destroy_drive_widget), dd);
233                         
234        g_signal_connect (applet, "key_press_event",
235                                  G_CALLBACK (key_press_cb), dd);
236
237        panel_applet_setup_menu_from_file (PANEL_APPLET (applet),
238                                           NULL,
239                                           "GNOME_DriveMountApplet.xml",
240                                           NULL,
241                                           applet_menu_verbs,
242                                           dd);
243
244        if (panel_applet_get_locked_down (PANEL_APPLET (applet))) {
245                BonoboUIComponent *popup_component;
246
247                popup_component = panel_applet_get_popup_component (PANEL_APPLET (applet));
248
249                bonobo_ui_component_set_prop (popup_component,
250                                              "/commands/Properties",
251                                              "hidden", "1",
252                                              NULL);
253        }
254
255        component = panel_applet_get_popup_component (PANEL_APPLET (applet));
256
257        tmp_path = gnome_is_program_in_path ("eject");
258        if (!tmp_path)
259                bonobo_ui_component_set_prop (component, "/commands/Eject",
260                                              "hidden", "1", NULL);
261        else
262                g_free (tmp_path);
263
264        redraw_pixmap (dd);
265
266        atk_obj = gtk_widget_get_accessible (dd->button);
267        atk_object_set_name (atk_obj, _("Disk Mounter"));
268
269        gtk_widget_show (GTK_WIDGET (applet));
270        start_callback_update (dd);
271        return TRUE;
272}
273
274static DriveData *
275create_drive_widget (PanelApplet *applet)
276{
277        DriveData *dd;
278
279        dd = g_new0 (DriveData, 1);
280        dd->applet = GTK_WIDGET (applet);
281
282        dd->about_dialog = NULL;
283        dd->prop_dialog = NULL;
284
285        properties_load (dd);
286
287        dd->button = gtk_button_new ();
288        gtk_widget_show (dd->button);
289        g_signal_connect (G_OBJECT (dd->button), "clicked",
290                          G_CALLBACK (mount_cb), dd);
291        dnd_init (dd);
292        return dd;
293}
294
295/* This is a hack around the fact that gtk+ doesn't
296 * propogate button presses on button2/3.
297 */
298static gboolean
299button_press_hack (GtkWidget      *widget,
300                   GdkEventButton *event,
301                   GtkWidget      *applet)
302{
303    if (event->button == 3 || event->button == 2) {
304        gtk_propagate_event (applet, (GdkEvent *) event);
305
306        return TRUE;
307    }
308
309    return FALSE;
310}
311
312static void
313dnd_init (DriveData *dd)
314{
315        gtk_drag_source_set (dd->button, GDK_BUTTON1_MASK,
316                             button_drag_types, n_button_drag_types,
317                             GDK_ACTION_COPY | GDK_ACTION_LINK |
318                             GDK_ACTION_ASK);
319        g_signal_connect (G_OBJECT (dd->button), "drag_data_get",
320                          G_CALLBACK (dnd_set_data_cb), dd);
321        g_signal_connect (G_OBJECT (dd->button), "drag_begin",
322                          G_CALLBACK (dnd_drag_begin_cb), dd);
323}
324
325static void
326dnd_drag_begin_cb (GtkWidget *widget, GdkDragContext *context, gpointer data)
327{
328        DriveData *dd = data;
329
330        gtk_drag_set_icon_pixbuf (context,
331                                  gtk_image_get_pixbuf (GTK_IMAGE
332                                                        (dd->button_pixmap)),
333                                  -5, -5);
334}
335
336static void
337dnd_set_data_cb (GtkWidget *widget, GdkDragContext *context,
338                 GtkSelectionData *selection_data, guint info,
339                 guint time, gpointer data)
340{
341        DriveData *dd = data;
342
343        if (dd && dd->mount_point) {
344                gchar *text = NULL;
345
346                switch (info) {
347                case TARGET_URI_LIST:
348                        text = g_strconcat ("file:", dd->mount_point, "\r\n",
349                                            NULL);
350                        break;
351                case TARGET_TEXT_PLAIN:
352                        text = g_strdup (dd->mount_point);
353                        break;
354                }
355                gtk_selection_data_set (selection_data, selection_data->target,
356                                        8, text, strlen (text));
357                g_free (text);
358        } else {
359                gtk_selection_data_set (selection_data, selection_data->target,
360                                        8, NULL, 0);
361        }
362}
363
364void
365start_callback_update (DriveData *dd)
366{
367        gint delay;
368
369        delay = dd->interval *1000;
370        if (dd->timeout_id)
371                gtk_timeout_remove (dd->timeout_id);
372        dd->timeout_id =
373                gtk_timeout_add (delay, (GtkFunction) drive_update_cb, dd);
374}
375
376static void
377applet_change_orient (GtkWidget *w, PanelAppletOrient o, gpointer data)
378{
379        /* resize the applet and set the proper pixmaps */
380        DriveData *dd = data;
381
382        if (dd->orient == o)
383                return;
384
385        dd->orient = o;
386
387        redraw_pixmap (dd);
388}
389
390static void
391applet_change_pixel_size (GtkWidget *w, int size, gpointer data)
392{
393        DriveData *dd = data;
394
395        if (dd->sizehint != size) {
396                dd->sizehint = size;
397                redraw_pixmap (dd);
398        }
399}
400
401static void
402destroy_drive_widget (GtkWidget *widget, gpointer data)
403{
404        DriveData *dd = data;
405
406        gtk_timeout_remove (dd->timeout_id);
407
408        if (dd->error_dialog != NULL)
409                gtk_widget_destroy (dd->error_dialog);
410
411        if (dd->about_dialog != NULL)
412                gtk_widget_destroy (dd->about_dialog);
413
414        if (dd->prop_dialog != NULL)
415                gtk_widget_destroy (dd->prop_dialog);
416
417        g_free (dd->custom_icon_in);
418        g_free (dd->custom_icon_out);
419
420        g_free (dd->mount_point);
421        g_free (dd->mount_base);
422        g_free (dd);
423}
424
425static void
426browse_cb (BonoboUIComponent *uic,
427           DriveData         *drivemount,
428           const char        *verb)
429{
430        GError *error = NULL;
431        char   *command;
432
433        if (!drivemount->mounted)
434                mount_cb (NULL, drivemount);
435
436        if (!drivemount->mounted)
437                return;
438
439        command = g_strdup_printf ("nautilus %s", drivemount->mount_point);
440
441        gdk_spawn_command_line_on_screen (gtk_widget_get_screen (GTK_WIDGET (drivemount->applet)),
442                        command, &error);
443
444        g_free (command);
445
446        if (error) {
447                GtkWidget *dialog;
448                char *msg;
449
450                msg = g_strdup_printf (_("There was an error executing %s: %s"),
451                                       command,
452                                       error->message);
453                dialog = hig_dialog_new (NULL /* parent */,
454                                         0 /* flags */,
455                                         GTK_MESSAGE_ERROR,
456                                         GTK_BUTTONS_OK,
457                                         _("Cannot browse device"),
458                                         msg);
459                g_free (msg);
460
461                g_signal_connect (dialog, "response",
462                                  G_CALLBACK (gtk_widget_destroy),
463                                  NULL);
464
465                gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE);
466                gtk_window_set_screen (GTK_WINDOW (dialog),
467                                       gtk_widget_get_screen (drivemount->applet));
468
469                gtk_widget_show (dialog);
470
471                g_error_free (error);
472        }
473}
474
475static void
476eject_cb (BonoboUIComponent *uic,
477          DriveData         *drivemount,
478          const char        *verb)
479{
480        eject (drivemount);
481}
482
483static void
484help_cb (BonoboUIComponent *uic,
485         DriveData         *drivemount,
486         const char        *verb)
487
488{
489        GError *error = NULL;
490        static GnomeProgram *applet_program = NULL;
491       
492        if (!applet_program) {
493                int argc = 1;
494                char *argv[2] = { "drivemount" };
495                applet_program = gnome_program_init ("drivemount", VERSION,
496                                                      LIBGNOME_MODULE, argc, argv,
497                                                      GNOME_PROGRAM_STANDARD_PROPERTIES, NULL);
498        }
499
500        gnome_help_display_desktop_on_screen (
501                        applet_program, "drivemount", "drivemount", NULL,
502                        gtk_widget_get_screen (GTK_WIDGET (drivemount->applet)),
503                        &error);
504
505        if (error) {
506                GtkWidget *error_dialog;
507                char *msg;
508
509                msg = g_strdup_printf (_("There was an error displaying help: %s"),
510                                       error->message);
511                error_dialog = hig_dialog_new (NULL /* parent */,
512                                               0 /* flags */,
513                                               GTK_MESSAGE_ERROR,
514                                               GTK_BUTTONS_OK,
515                                               _("Error displaying help"),
516                                               msg);
517                g_free (msg);
518
519                g_signal_connect (error_dialog, "response",
520                                  G_CALLBACK (gtk_widget_destroy),
521                                  NULL);
522
523                gtk_window_set_resizable (GTK_WINDOW (error_dialog), FALSE);
524                gtk_window_set_screen (GTK_WINDOW (error_dialog),
525                                       gtk_widget_get_screen (GTK_WIDGET (uic)));
526                gtk_widget_show (error_dialog);
527                g_error_free (error);
528        }
529}
530
531static void
532about_cb (BonoboUIComponent *uic,
533          DriveData         *drivemount,
534          const char        *verb)
535{
536        GdkPixbuf        *pixbuf;
537        GError           *error = NULL;
538        gchar            *file;
539       
540        static const gchar *authors[] = {
541                "John Ellis <johne@bellatlantic.net>",
542                "Chris Phelps <chicane@renient.com>",
543                NULL
544        };
545
546        const gchar *documenters[] = {
547                "Dan Mueth <muet@alumni.uchicago.edu>",
548                "John Fleck <jfleck@inkstain.net>",
549                NULL
550        };
551
552        const gchar *translator_credits = _("translator_credits");
553
554        if (drivemount->about_dialog) {
555                gtk_window_set_screen (GTK_WINDOW (drivemount->about_dialog),
556                                       gtk_widget_get_screen (GTK_WIDGET (drivemount->applet)));
557       
558                gtk_window_present (GTK_WINDOW (drivemount->about_dialog));
559                return;
560        }
561
562        file = gnome_program_locate_file (NULL, GNOME_FILE_DOMAIN_PIXMAP, "drivemount-applet.png", FALSE, NULL);
563        pixbuf = gdk_pixbuf_new_from_file (file, &error);
564        g_free (file);
565   
566        if (error) {
567                g_warning (G_STRLOC ": cannot open %s: %s", file, error->message);
568                g_error_free (error);
569        }
570
571        drivemount->about_dialog = gnome_about_new (_("Disk Mounter"), VERSION,
572                                 _("(C) 1999-2001 The GNOME Hackers\n"),
573                                 _
574                                 ("Applet for mounting and unmounting block volumes."),
575                                 authors,
576                                 documenters,
577                                 strcmp (translator_credits, "translator_credits") != 0 ? translator_credits : NULL,
578                                 pixbuf);
579        if (pixbuf)
580                gdk_pixbuf_unref (pixbuf);
581   
582        gtk_window_set_wmclass (GTK_WINDOW (drivemount->about_dialog), "disk mounter", "Disk Mounter");
583        gtk_window_set_screen (GTK_WINDOW (drivemount->about_dialog),
584                               gtk_widget_get_screen (drivemount->applet));
585
586        g_signal_connect (G_OBJECT (drivemount->about_dialog), "destroy",
587                          G_CALLBACK (gtk_widget_destroyed), &drivemount->about_dialog);
588
589        gtk_widget_show (drivemount->about_dialog);
590}
591
592/*
593 *-------------------------------------------------------------------------
594 *mount status checks
595 *-------------------------------------------------------------------------
596 */
597
598static gint
599device_is_in_mountlist (DriveData *dd)
600{
601        FILE *fp;
602        gchar *command_line = "mount";
603        gchar buf[256];
604        gint found = FALSE;
605
606        if (!dd->mount_point)
607                return FALSE;
608
609        fp = popen (command_line, "r");
610        if (!fp) {
611                g_print ("unable to run command: %s\n", command_line);
612                return FALSE;
613        }
614        while (fgets (buf, sizeof (buf), fp)) {
615                gchar *ptr;
616                ptr = strstr (buf, dd->mount_point);
617                if (ptr != NULL) {
618                        gchar *p;
619                        p = ptr + strlen (dd->mount_point);
620                        if (*p == ' ' || *p == '\0' || *p == '\n') {
621                                found = TRUE;
622                                break;
623                        }
624                }
625        }
626        pclose (fp);
627        return found;
628}
629
630static gint
631get_device (const gchar *file)
632{
633        struct stat file_info;
634        gint t;
635
636        if (stat (file, &file_info) == -1)
637                t = -1;
638        else
639                t = (gint) file_info.st_dev;
640        return t;
641}
642
643static gint
644device_is_mounted (DriveData *dd)
645{
646        if (!dd->mount_point || !dd->mount_base)
647                return FALSE;
648
649        if (!dd->autofs_friendly) {
650                gint b, p;
651
652                b = get_device (dd->mount_base);
653                p = get_device (dd->mount_point);
654                if (b == p || p == -1 || b == -1)
655                        return FALSE;
656                else
657                        return TRUE;
658        } else {
659                if (device_is_in_mountlist (dd))
660                        return TRUE;
661                else
662                        return FALSE;
663        }
664}
665
666/*
667 *-------------------------------------------------------------------------
668 *image / widget setup and size changes
669 *-------------------------------------------------------------------------
670 */
671
672static void
673update_pixmap (DriveData *dd, gint t)
674{
675        GdkPixbuf *pixbuf;
676        GdkPixbuf *scaled;
677        char **pmap_d_in;
678        char **pmap_d_out;
679        gint pixmap;
680
681        gint width;
682        gint height;
683
684        gchar *tiptext;
685        gchar *text;
686
687        gint hint = dd->sizehint;
688
689        pixmap = dd->device_pixmap;
690        if (dd->device_pixmap > icon_list_count - 1)
691                pixmap = 0;
692        if (dd->device_pixmap < 0
693            && (!dd->custom_icon_in || !dd->custom_icon_out))
694                pixmap = 0;
695
696        if (!dd->button_pixmap) {
697                dd->button_pixmap = gtk_image_new ();
698                gtk_container_add (GTK_CONTAINER (dd->button),
699                                   dd->button_pixmap);
700                gtk_widget_show (dd->button_pixmap);
701        }
702
703        if (pixmap < 0) {
704                if (t) {
705                        pixbuf = gdk_pixbuf_new_from_file (dd->custom_icon_in,
706                                                           NULL);
707                } else {
708                        pixbuf = gdk_pixbuf_new_from_file (dd->custom_icon_out,
709                                                           NULL);
710                }
711
712                if (pixbuf) {
713                        width = gdk_pixbuf_get_width (pixbuf);
714                        height = gdk_pixbuf_get_height (pixbuf);
715
716                        if (dd->orient == PANEL_APPLET_ORIENT_LEFT
717                            || dd->orient == PANEL_APPLET_ORIENT_RIGHT) {
718                                if (width > hint || dd->scale_applet) {
719                                        height = (float) height *hint / width;
720
721                                        width = hint;
722                                }
723                        } else {
724                                if (height > hint || dd->scale_applet) {
725                                        width = (float) width *hint / height;
726
727                                        height = hint;
728                                }
729                        }
730                        scaled = gdk_pixbuf_scale_simple (pixbuf, width, height,
731                                                          GDK_INTERP_BILINEAR);
732                        gtk_image_set_from_pixbuf (GTK_IMAGE
733                                                   (dd->button_pixmap), scaled);
734                        g_object_unref (G_OBJECT (pixbuf));
735                        g_object_unref (scaled);
736                }
737        } else {
738                if (dd->scale_applet) {
739                        width = hint;
740                        height = (float) hint / ICON_WIDTH *ICON_HEIGHT;
741                } else {
742                        width = ICON_WIDTH;
743                        height = ICON_HEIGHT;
744                }
745
746                if ((dd->orient == PANEL_APPLET_ORIENT_LEFT
747                     || dd->orient == PANEL_APPLET_ORIENT_RIGHT) && hint > 36) {
748                        pmap_d_in = icon_list[pixmap].pmap_h_in;
749                        pmap_d_out = icon_list[pixmap].pmap_h_out;
750                } else if ((dd->orient == PANEL_APPLET_ORIENT_UP
751                     || dd->orient == PANEL_APPLET_ORIENT_DOWN) && hint <= 36) {
752                        pmap_d_in = icon_list[pixmap].pmap_h_in;
753                        pmap_d_out = icon_list[pixmap].pmap_h_out;
754                } else {
755                        gint tmp;
756
757                        tmp = width;
758                        width = height;
759                        height = tmp;
760
761                        pmap_d_in = icon_list[pixmap].pmap_v_in;
762                        pmap_d_out = icon_list[pixmap].pmap_v_out;
763                }
764
765                if (t)
766                        pixbuf = gdk_pixbuf_new_from_xpm_data ((const char **)
767                                                               pmap_d_in);
768                else
769                        pixbuf = gdk_pixbuf_new_from_xpm_data ((const char **)
770                                                               pmap_d_out);
771                scaled = gdk_pixbuf_scale_simple (pixbuf, width, height,
772                                                  GDK_INTERP_BILINEAR);
773                gtk_image_set_from_pixbuf (GTK_IMAGE (dd->button_pixmap),
774                                           scaled);
775                g_object_unref (G_OBJECT (pixbuf));
776                g_object_unref (scaled);
777        }
778
779        if (t) {
780                text = _(" mounted");
781        } else {
782                text = _(" not mounted");
783        }
784        tiptext = g_strconcat (dd->mount_point, text, NULL);
785        gtk_tooltips_set_tip (dd->tooltips, dd->button, tiptext, NULL);
786        g_free (tiptext);
787}
788
789void
790redraw_pixmap (DriveData *dd)
791{
792        if (!device_is_mounted (dd)) {
793                update_pixmap (dd, FALSE);
794                dd->mounted = FALSE;
795        } else {
796                update_pixmap (dd, TRUE);
797                dd->mounted = TRUE;
798        }
799}
800
801/*
802 *-------------------------------------------------------------------------
803 *main callback loop
804 *-------------------------------------------------------------------------
805 */
806
807static gint
808drive_update_cb (gpointer data)
809{
810        DriveData *dd = data;
811
812        if (!device_is_mounted (dd)) {
813                /* device not mounted */
814                if (dd->mounted) {
815                        update_pixmap (dd, FALSE);
816                        dd->mounted = FALSE;
817                }
818        } else {
819                /* device mounted */
820                if (!dd->mounted) {
821                        update_pixmap (dd, TRUE);
822                        dd->mounted = TRUE;
823                }
824        }
825        return TRUE;
826}
827
828/*
829 *-------------------------------------------------------------------------
830 *mount calls
831 *-------------------------------------------------------------------------
832 */
833
834static void
835mount_cb (GtkWidget *widget,
836          DriveData *dd)
837{
838        gchar *command_line;
839        gchar buf[512];
840        FILE *fp;
841        GString *str;
842        gint check = device_is_mounted (dd);
843
844        /* Stop the user from displaying zillions of error messages */
845        if (dd->error_dialog) {
846                gtk_window_set_screen (GTK_WINDOW (dd->error_dialog),
847                                       gtk_widget_get_screen (dd->applet));
848                gtk_window_present (GTK_WINDOW (dd->error_dialog));
849                return;
850        }
851
852        if (!check) {
853                command_line =
854                        g_strdup_printf ("mount %s 2>&1", dd->mount_point);
855        } else {
856                command_line =
857                        g_strdup_printf ("umount %s 2>&1", dd->mount_point);
858        }
859
860        fp = popen (command_line, "r");
861
862        if (!fp) {
863                printf ("unable to run command: %s\n", command_line);
864                g_free (command_line);
865                return;
866        }
867
868        str = g_string_new (NULL);
869
870        while (fgets (buf, sizeof (buf), fp) != NULL) {
871                gchar *b = buf;
872                const gchar *charset;
873                if (!g_get_charset (&charset)) {
874                        b = g_convert (buf, -1, "UTF-8", charset, NULL, NULL, NULL);
875                } else {
876                        b =g_strdup (buf);
877                }
878                g_string_append (str, b);
879                g_free (b);
880        }
881        pclose (fp);
882
883        dd->mounted = device_is_mounted (dd);
884
885        if (check != dd->mounted) {
886                /* success! */
887                update_pixmap (dd, dd->mounted);
888
889                /* eject after unmounting, if enabled */
890                if (check && dd->auto_eject) {
891                        eject (dd);
892                }
893        } else {
894                g_string_prepend (str, _("\" reported:\n"));
895                g_string_prepend (str, command_line);
896                g_string_prepend (str, _("Drivemount command failed.\n\""));
897
898                dd->error_dialog = hig_dialog_new (NULL /* parent */,
899                                                   GTK_DIALOG_MODAL /* flags */,
900                                                   GTK_MESSAGE_ERROR,
901                                                   GTK_BUTTONS_OK,
902                                                   _("Cannot mount device"),
903                                                   str->str);
904                gtk_window_set_screen (GTK_WINDOW (dd->error_dialog),
905                                       gtk_widget_get_screen (dd->applet));
906
907                gtk_widget_show_all (dd->error_dialog);
908                gtk_dialog_run (GTK_DIALOG (dd->error_dialog));
909                gtk_widget_destroy (dd->error_dialog);
910                dd->error_dialog = NULL;
911        }
912        g_string_free (str, TRUE);
913        g_free (command_line);
914        return;
915}
916
917static void
918eject (DriveData *dd)
919{
920        gchar *command_line;
921        gchar buffer[512];
922        gchar dn[256];          /* Devicename */
923        gchar mp[256];          /* Mountpoint */
924        FILE *ml;               /* Mountlist */
925        gint found = FALSE;
926
927        if (!dd->mount_point)
928                return;
929
930        /*
931         * Search the output of mount for dd->mount_point
932         * and use the corresponting device name
933         * as argument for eject
934         * if the device is not mounted currently, use
935         * /etc/fstab for the check
936         */
937
938        if (dd->mounted) {
939                ml = popen ("mount", "r");
940                while (ml && fgets (buffer, sizeof (buffer), ml)) {
941                        if (sscanf (buffer, "%255s %*s %255s", dn, mp) == 2 &&
942                            (mp && strcmp (mp, dd->mount_point) == 0)) {
943                                found = TRUE;
944                                break;
945                        }
946                }
947                if (ml)
948                        pclose (ml);
949        } else {
950                ml = fopen ("/etc/fstab", "r");
951               
952                while (ml && fgets (buffer, sizeof (buffer), ml)) {
953                        if (sscanf (buffer, "%255s %255s", dn, mp) == 2 &&
954                            strcmp (mp, dd->mount_point) == 0) {
955                                found = TRUE;
956                                break;
957                        }
958                }
959                if (ml)
960                        fclose (ml);
961        }
962
963        if (!found) {           /* mp != dd->mount_point */
964                printf ("WARNING: drivemount.c ... dd->mount_point not found in list\
965                         (output of mount, or /etc/fstab) \n");
966                return;
967        }
968
969        if (dd->mounted) {
970                command_line = g_strdup_printf ("eject -u '%s'", dn);
971                /* perhaps it doesn't like the -u option */
972                if (system (command_line) != 0) {
973                        g_free (command_line);
974                        command_line = g_strdup_printf ("eject '%s'", dn);
975                        gnome_execute_shell (NULL, command_line);
976                }
977                g_free (command_line);
978        } else {
979                command_line = g_strdup_printf ("eject '%s'", dn);
980                gnome_execute_shell (NULL, command_line);
981                g_free (command_line);
982        }
983}
984
985static gboolean
986key_press_cb (GtkWidget *widget, GdkEventKey *event, DriveData *dd)
987{
988        if (event->state != GDK_CONTROL_MASK)
989                return FALSE;
990        else {
991                switch (event->keyval) {
992       
993                case GDK_e:
994                        eject (dd);
995                        return TRUE;
996                case GDK_b:
997                        browse_cb (NULL, dd, NULL);
998                        return TRUE;
999                default:
1000                        break;
1001                }
1002        }
1003
1004        return FALSE;
1005
1006
1007}
1008
1009/* stolen from gsearchtool */
1010GtkWidget*
1011hig_dialog_new (GtkWindow      *parent,
1012                GtkDialogFlags flags,
1013                GtkMessageType type,
1014                GtkButtonsType buttons,
1015                const gchar    *header,
1016                const gchar    *message)
1017{
1018        GtkWidget *dialog;
1019        GtkWidget *dialog_vbox;
1020        GtkWidget *dialog_action_area;
1021        GtkWidget *hbox;
1022        GtkWidget *vbox;
1023        GtkWidget *label;
1024        GtkWidget *button;
1025        GtkWidget *image;
1026        gchar     *title;
1027
1028        dialog = gtk_dialog_new ();
1029       
1030        gtk_dialog_set_has_separator (GTK_DIALOG (dialog), FALSE);
1031        gtk_container_set_border_width (GTK_CONTAINER (dialog), 5);
1032        gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE);
1033        gtk_window_set_title (GTK_WINDOW (dialog), "");
1034 
1035        dialog_vbox = GTK_DIALOG (dialog)->vbox;
1036        gtk_box_set_spacing (GTK_BOX (dialog_vbox), 14);
1037
1038        hbox = gtk_hbox_new (FALSE, 12);
1039        gtk_box_pack_start (GTK_BOX (dialog_vbox), hbox, FALSE, FALSE, 0);
1040        gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
1041        gtk_widget_show (hbox);
1042
1043        if (type == GTK_MESSAGE_ERROR) {
1044                image = gtk_image_new_from_stock ("gtk-dialog-error", GTK_ICON_SIZE_DIALOG);
1045        } else if (type == GTK_MESSAGE_QUESTION) {
1046                image = gtk_image_new_from_stock ("gtk-dialog-question", GTK_ICON_SIZE_DIALOG);
1047        } else {
1048                g_assert_not_reached ();
1049        }
1050        gtk_box_pack_start (GTK_BOX (hbox), image, FALSE, FALSE, 0);
1051        gtk_widget_show (image);
1052
1053        vbox = gtk_vbox_new (FALSE, 6);
1054        gtk_box_pack_start (GTK_BOX (hbox), vbox, TRUE, TRUE, 0);
1055        gtk_widget_show (vbox);
1056       
1057        title = g_strconcat ("<b>", header, "</b>", NULL);
1058        label = gtk_label_new (title); 
1059        gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
1060        gtk_label_set_use_markup (GTK_LABEL (label), TRUE);
1061        gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT);
1062        gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
1063        gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
1064        gtk_widget_show (label);
1065        g_free (title);
1066       
1067        label = gtk_label_new (message);
1068        gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
1069        gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT);
1070        gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
1071        gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
1072        gtk_widget_show (label);
1073       
1074        dialog_action_area = GTK_DIALOG (dialog)->action_area;
1075        gtk_button_box_set_layout (GTK_BUTTON_BOX (dialog_action_area), GTK_BUTTONBOX_END);
1076
1077        switch (buttons)
1078        {               
1079                case GTK_BUTTONS_OK_CANCEL:
1080       
1081                        button = gtk_button_new_from_stock ("gtk-cancel");
1082                        gtk_widget_show (button);
1083                        gtk_dialog_add_action_widget (GTK_DIALOG (dialog), button, GTK_RESPONSE_CANCEL);
1084                        GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
1085
1086                        button = gtk_button_new_from_stock ("gtk-ok");
1087                        gtk_widget_show (button);
1088                        gtk_dialog_add_action_widget (GTK_DIALOG (dialog), button, GTK_RESPONSE_OK);
1089                        GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
1090                        break;
1091               
1092                case GTK_BUTTONS_OK:
1093               
1094                        button = gtk_button_new_from_stock ("gtk-ok");
1095                        gtk_dialog_add_action_widget (GTK_DIALOG (dialog), button, GTK_RESPONSE_OK);
1096                        GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
1097                        gtk_widget_show (button);
1098                        break;
1099               
1100                default:
1101                        g_warning ("Unhandled GtkButtonsType");
1102                        break;
1103        }
1104
1105        if (parent != NULL) {
1106                gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (parent));
1107        }
1108        if (flags & GTK_DIALOG_MODAL) {
1109                gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
1110        }
1111        if (flags & GTK_DIALOG_DESTROY_WITH_PARENT) {
1112                gtk_window_set_destroy_with_parent (GTK_WINDOW (dialog), TRUE);
1113        }
1114       
1115        return dialog;
1116}
1117
Note: See TracBrowser for help on using the repository browser.