/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 2 -*- */ /* Copyright (C) 2004 Carlos Garnacho * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. * * Authors: Carlos Garnacho Parro */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #ifdef HAVE_PTY_H #include #endif #include #include #include #include #include #include #ifdef __FreeBSD__ #include #include #include #endif #include "modem-applet.h" #define MODEM_APPLET_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), TYPE_MODEM_APPLET, ModemAppletPrivate)) #define NETWORK_TOOL "network-admin" #define END_OF_REQUEST "\n" #define BUF_SIZE 1024 typedef void (*DirectiveCallback) (ModemApplet*, xmlDoc*); typedef struct _BackendDirective BackendDirective; typedef struct _ModemAppletPrivate ModemAppletPrivate; struct _ModemAppletPrivate { /* applet UI stuff */ GtkBuilder *builder; GtkIconTheme *icon_theme; GdkPixbuf *icon; GtkWidget *image; GtkActionGroup *action_group; /* auth dialog */ GtkWidget *auth_dialog; GtkWidget *auth_dialog_label; GtkWidget *auth_dialog_entry; /* report window */ GtkWidget *report_window; GtkWidget *report_window_image; GtkWidget *report_window_progress; guint directives_id; guint progress_id; guint tooltip_id; guint info_id; guint timeout_id; /* for communicating with the backend */ gint config_id; gint pid; int read_fd; int write_fd; FILE *read_stream; FILE *write_stream; GSList *directives; gboolean directive_running; /* interface data */ gboolean configured; /* is configured? */ gboolean enabled; /* is enabled? */ gboolean is_isdn; /* is an isdn device? */ gchar *dev; /* device name */ gchar *lock_file; /* lock file */ gboolean has_root; }; struct _BackendDirective { DirectiveCallback callback; GSList *directive; gboolean show_report; }; static void modem_applet_class_init (ModemAppletClass *class); static void modem_applet_init (ModemApplet *applet); static void modem_applet_finalize (GObject *object); static gboolean update_tooltip (ModemApplet *applet); static gboolean dispatch_directives (ModemApplet *applet); static gboolean update_info (ModemApplet *applet); static void modem_applet_change_size (MatePanelApplet *applet, guint size); static void modem_applet_change_background (MatePanelApplet *app, MatePanelAppletBackgroundType type, GdkColor *colour, GdkPixmap *pixmap); static void on_modem_applet_about_clicked (GtkAction *action, ModemApplet *applet); static void on_modem_applet_activate (GtkAction *action, ModemApplet *applet); static void on_modem_applet_deactivate (GtkAction *action, ModemApplet *applet); static void on_modem_applet_properties_clicked (GtkAction *action, ModemApplet *applet); static void on_modem_applet_help_clicked (GtkAction *action, ModemApplet *applet); static void launch_backend (ModemApplet *applet, gboolean root_auth); static void shutdown_backend (ModemApplet *applet, gboolean backend_alive, gboolean already_waiting); static gpointer parent_class; static const GtkActionEntry menu_actions[] = { { "Activate", GTK_STOCK_EXECUTE, N_("_Activate"), NULL, NULL, G_CALLBACK (on_modem_applet_activate) }, { "Deactivate", GTK_STOCK_STOP, N_("_Deactivate"), NULL, NULL, G_CALLBACK (on_modem_applet_deactivate) }, { "Properties", GTK_STOCK_PROPERTIES, N_("_Properties"), NULL, NULL, G_CALLBACK (on_modem_applet_properties_clicked) }, { "Help", GTK_STOCK_HELP, N_("_Help"), NULL, NULL, G_CALLBACK (on_modem_applet_help_clicked) }, { "About", GTK_STOCK_ABOUT, N_("_About"), NULL, NULL, G_CALLBACK (on_modem_applet_about_clicked) } }; G_DEFINE_TYPE (ModemApplet, modem_applet, PANEL_TYPE_APPLET) static void modem_applet_class_init (ModemAppletClass *class) { GObjectClass *object_class; MatePanelAppletClass *applet_class; object_class = G_OBJECT_CLASS (class); applet_class = MATE_PANEL_APPLET_CLASS (class); parent_class = g_type_class_peek_parent (class); object_class->finalize = modem_applet_finalize; applet_class->change_size = modem_applet_change_size; applet_class->change_background = modem_applet_change_background; g_type_class_add_private (object_class, sizeof (ModemAppletPrivate)); } static void modem_applet_init (ModemApplet *applet) { ModemAppletPrivate *priv; GdkPixbuf *pixbuf; g_set_application_name ( _("Modem Monitor")); priv = MODEM_APPLET_GET_PRIVATE (applet); priv->builder = gtk_builder_new (); gtk_builder_add_from_file (priv->builder, GTK_BUILDERDIR "/modemlights.ui", NULL); priv->icon = NULL; priv->icon_theme = gtk_icon_theme_get_default (); priv->image = gtk_image_new (); priv->auth_dialog = GTK_WIDGET (gtk_builder_get_object (priv->builder, "auth_dialog")); priv->auth_dialog_label = GTK_WIDGET (gtk_builder_get_object (priv->builder, "auth_dialog_label")); priv->auth_dialog_entry = GTK_WIDGET (gtk_builder_get_object (priv->builder, "auth_dialog_entry")); priv->report_window = GTK_WIDGET (gtk_builder_get_object (priv->builder, "report_window")); priv->report_window_image = GTK_WIDGET (gtk_builder_get_object (priv->builder, "report_window_image")); priv->report_window_progress = GTK_WIDGET (gtk_builder_get_object (priv->builder, "report_window_progress")); g_signal_connect (G_OBJECT (priv->report_window), "delete-event", G_CALLBACK (gtk_widget_hide), NULL); pixbuf = gtk_icon_theme_load_icon (priv->icon_theme, "mate-modem-monitor-applet", 48, 0, NULL); gtk_image_set_from_pixbuf (GTK_IMAGE (priv->report_window_image), pixbuf); g_object_unref (pixbuf); priv->configured = FALSE; priv->enabled = FALSE; priv->dev = NULL; priv->lock_file = NULL; priv->has_root = FALSE; priv->directives = NULL; priv->directives_id = g_timeout_add (250, (GSourceFunc) dispatch_directives, applet); priv->directive_running = FALSE; priv->tooltip_id = g_timeout_add_seconds (1, (GSourceFunc) update_tooltip, applet); launch_backend (applet, FALSE); gtk_container_add (GTK_CONTAINER (applet), priv->image); } static void modem_applet_finalize (GObject *object) { ModemAppletPrivate *priv = MODEM_APPLET_GET_PRIVATE (object); if (priv) { shutdown_backend (MODEM_APPLET (object), TRUE, TRUE); gtk_widget_destroy (priv->auth_dialog); gtk_widget_destroy (priv->report_window); g_object_unref (priv->icon); g_object_unref (priv->action_group); g_free (priv->dev); g_free (priv->lock_file); } if (G_OBJECT_CLASS (parent_class)->finalize) (* G_OBJECT_CLASS (parent_class)->finalize) (object); } static void modem_applet_change_size (MatePanelApplet *applet, guint size) { ModemAppletPrivate *priv = MODEM_APPLET_GET_PRIVATE (applet); if (priv->icon) g_object_unref (priv->icon); /* this might be too much overload, maybe should we get just one icon size and scale? */ priv->icon = gtk_icon_theme_load_icon (priv->icon_theme, "mate-modem", size, 0, NULL); gtk_image_set_from_pixbuf (GTK_IMAGE (priv->image), priv->icon); } static void modem_applet_change_background (MatePanelApplet *app, MatePanelAppletBackgroundType type, GdkColor *colour, GdkPixmap *pixmap) { ModemApplet *applet = MODEM_APPLET (app); GtkRcStyle *rc_style; GtkStyle *style; /* reset style */ gtk_widget_set_style (GTK_WIDGET (applet), NULL); rc_style = gtk_rc_style_new (); gtk_widget_modify_style (GTK_WIDGET (applet), rc_style); g_object_unref (rc_style); switch (type) { case PANEL_NO_BACKGROUND: break; case PANEL_COLOR_BACKGROUND: gtk_widget_modify_bg (GTK_WIDGET (applet), GTK_STATE_NORMAL, colour); break; case PANEL_PIXMAP_BACKGROUND: style = gtk_style_copy (GTK_WIDGET (applet)->style); if (style->bg_pixmap[GTK_STATE_NORMAL]) g_object_unref (style->bg_pixmap[GTK_STATE_NORMAL]); style->bg_pixmap[GTK_STATE_NORMAL] = g_object_ref (pixmap); gtk_widget_set_style (GTK_WIDGET (applet), style); g_object_unref (style); break; } } static gboolean pulse_progressbar (GtkWidget *progressbar) { gtk_progress_bar_pulse (GTK_PROGRESS_BAR (progressbar)); return TRUE; } /* XML manipulation functions */ static xmlNodePtr get_root_node (xmlDoc *doc) { return xmlDocGetRootElement (doc); } static xmlNodePtr find_first_element (xmlNodePtr node, const gchar *name) { xmlNodePtr n; g_return_val_if_fail (node != NULL, NULL); g_return_val_if_fail (name != NULL, NULL); for (n = node->children; n; n = n->next) if (n->name && (strcmp (name, (char *) n->name) == 0)) break; return n; } static xmlNodePtr find_next_element (xmlNodePtr node, const gchar *name) { xmlNodePtr n; g_return_val_if_fail (node != NULL, NULL); g_return_val_if_fail (name != NULL, NULL); for (n = node->next; n; n = n->next) if (n->name && (strcmp (name, (char *) n->name) == 0)) break; return n; } static guchar * element_get_attribute (xmlNodePtr node, const gchar *attribute) { xmlAttrPtr a; g_return_val_if_fail (node != NULL, NULL); a = node->properties; while (a) { if (a->name && (strcmp ((char *) a->name, attribute) == 0)) return xmlNodeGetContent (a->children); a = a->next; } return NULL; } static guchar * element_get_child_content (xmlNodePtr node, const gchar *tag) { xmlNodePtr child, n; child = find_first_element (node, tag); if (!child) return NULL; for (n = child->children; n; n = n->next) if (n->type == XML_TEXT_NODE) return xmlNodeGetContent (n); return NULL; } static xmlNodePtr find_dialup_interface_node (xmlNodePtr root) { xmlNodePtr node; gchar *type; node = find_first_element (root, "interface"); while (node) { type = (char *) element_get_attribute (node, "type"); if (type && (strcmp (type, "modem") == 0 || strcmp (type, "isdn") == 0)) { g_free (type); return node; } g_free (type); node = find_next_element (node, "interface"); } return NULL; } /* backend communication functions */ static gchar * compose_directive_string (GSList *directive) { GString *dir; gchar *arg, *s, *str; GSList *elem; elem = directive; dir = g_string_new (""); while (elem) { arg = elem->data; for (s = arg; *s; s++) { /* escape needed chars */ if ((*s == '\\') || ((*s == ':') && (* (s + 1) == ':'))) g_string_append_c (dir, '\\'); g_string_append_c (dir, *s); } g_string_append (dir, "::"); elem = elem->next; } g_string_append_c (dir, '\n'); str = dir->str; g_string_free (dir, FALSE); return str; } static void poll_backend (ModemAppletPrivate *priv) { struct pollfd fd; fd.fd = priv->read_fd; fd.events = POLLIN || POLLPRI; while (poll (&fd, 1, 100) <= 0) { while (gtk_events_pending ()) gtk_main_iteration (); } } static xmlDoc* read_xml (ModemApplet *applet, gboolean show_report) { ModemAppletPrivate *priv = MODEM_APPLET_GET_PRIVATE (applet); gchar buffer[BUF_SIZE], *s; GString *str; xmlDoc *doc = NULL; gboolean backend_alive; str = g_string_new (""); backend_alive = (waitpid (priv->pid, NULL, WNOHANG) == 0); /* if show_report, create pulse timeout and show window */ if (show_report) { priv->progress_id = g_timeout_add (200, (GSourceFunc) pulse_progressbar, priv->report_window_progress); gtk_window_set_screen (GTK_WINDOW (priv->report_window), gtk_widget_get_screen (GTK_WIDGET (applet))); gtk_widget_show (priv->report_window); } while (backend_alive && !g_strrstr (str->str, END_OF_REQUEST)) { poll_backend (priv); fgets (buffer, BUF_SIZE, priv->read_stream); g_string_append (str, buffer); while (gtk_events_pending ()) gtk_main_iteration (); backend_alive = (waitpid (priv->pid, NULL, WNOHANG) == 0); } /* if show_report, hide window and so */ if (show_report) { g_source_remove (priv->progress_id); priv->progress_id = 0; gtk_widget_hide (priv->report_window); } s = str->str; while (*s && (*s != '<')) s++; if (strcmp (s, END_OF_REQUEST) != 0) doc = xmlParseDoc ((xmlChar *) s); g_string_free (str, TRUE); return doc; } static void queue_directive (ModemApplet *applet, DirectiveCallback callback, gboolean show_report, const gchar *dir, ...) { ModemAppletPrivate *priv = MODEM_APPLET_GET_PRIVATE (applet); BackendDirective *directive; GSList *list = NULL; va_list ap; gchar *arg; list = g_slist_prepend (list, g_strdup (dir)); va_start (ap, dir); while ((arg = va_arg (ap, gchar *)) != NULL) list = g_slist_prepend (list, g_strdup (arg)); va_end (ap); list = g_slist_reverse (list); directive = g_new0 (BackendDirective, 1); directive->callback = callback; directive->directive = list; directive->show_report = show_report; priv->directives = g_slist_append (priv->directives, directive); } static gboolean dispatch_directives (ModemApplet *applet) { ModemAppletPrivate *priv = MODEM_APPLET_GET_PRIVATE (applet); BackendDirective *directive; xmlDoc *doc; gchar *dir; GSList *elem; if (priv->directive_running) return TRUE; priv->directive_running = TRUE; elem = priv->directives; while (elem) { directive = elem->data; dir = compose_directive_string (directive->directive); fputs (dir, priv->write_stream); g_free (dir); doc = read_xml (applet, directive->show_report); if (directive->callback) directive->callback (applet, doc); if (doc) xmlFreeDoc (doc); g_slist_foreach (directive->directive, (GFunc) g_free, NULL); g_slist_free (directive->directive); elem = elem->next; } g_slist_foreach (priv->directives, (GFunc) g_free, NULL); g_slist_free (priv->directives); priv->directives = NULL; priv->directive_running = FALSE; return TRUE; } static void shutdown_backend (ModemApplet *applet, gboolean backend_alive, gboolean already_waiting) { ModemAppletPrivate *priv = MODEM_APPLET_GET_PRIVATE (applet); if (priv->info_id) { g_source_remove (priv->info_id); priv->info_id = 0; } if (priv->timeout_id) { g_source_remove (priv->timeout_id); priv->timeout_id = 0; } if (priv->tooltip_id) { g_source_remove (priv->tooltip_id); priv->tooltip_id = 0; } if (backend_alive) kill (priv->pid, 9); if (!already_waiting) { /* don't leave zombies */ while (waitpid (priv->pid, NULL, WNOHANG) <= 0) { usleep (2000); while (gtk_events_pending ()) gtk_main_iteration (); } } /* close remaining streams and fds */ fclose (priv->read_stream); fclose (priv->write_stream); close (priv->read_fd); close (priv->write_fd); } /* functions for extracting the interface information from the XML */ static void update_popup_buttons (ModemApplet *applet) { GtkAction *action; ModemAppletPrivate *priv = MODEM_APPLET_GET_PRIVATE (applet); action = gtk_action_group_get_action (priv->action_group, "Activate"); gtk_action_set_sensitive (action, priv->configured && !priv->enabled); action = gtk_action_group_get_action (priv->action_group, "Deactivate"); gtk_action_set_sensitive (action, priv->configured && priv->enabled); } static void get_interface_data (ModemApplet *applet, xmlNodePtr iface) { ModemAppletPrivate *priv = MODEM_APPLET_GET_PRIVATE (applet); xmlNodePtr configuration; gchar *text, *device; g_return_if_fail (iface != NULL); text = (char *) element_get_child_content (iface, "enabled"); priv->enabled = (*text == '1'); g_free (text); g_free (priv->dev); priv->dev = (char *) element_get_child_content (iface, "dev"); g_free (priv->lock_file); configuration = find_first_element (iface, "configuration"); if (configuration) { priv->configured = TRUE; text = (char *) element_get_child_content (configuration, "serial_port"); if (text) { /* Modem device */ device = strrchr (text, '/'); priv->lock_file = g_strdup_printf ("/var/lock/LCK..%s", device + 1); g_free (text); priv->is_isdn = FALSE; } else { /* isdn device */ priv->lock_file = g_strdup ("/var/lock/LCK..capi_0"); priv->is_isdn = TRUE; } } else { priv->lock_file = NULL; priv->configured = FALSE; } } static gint get_connection_time (const gchar *lock_file) { struct stat st; if (stat (lock_file, &st) == 0) return (gint) (time (NULL) - st.st_mtime); return 0; } static gboolean update_tooltip (ModemApplet *applet) { ModemAppletPrivate *priv = MODEM_APPLET_GET_PRIVATE (applet); gchar *text; gint t, t1, t2; if (priv->enabled) { if (!priv->lock_file) text = g_strdup (_("Connection active, but could not get connection time")); else { t = get_connection_time (priv->lock_file); if (t < (60 * 60 * 24)) { t1 = t / 3600; /* hours */ t2 = (t - (t1 * 3600)) / 60; /* minutes */ } else { t1 = t / (3600 * 24); /* days */ t2 = (t - (t1 * 3600 * 24)) / 3600; /* hours */ } text = g_strdup_printf (_("Time connected: %.1d:%.2d"), t1, t2); } } else text = g_strdup (_("Not connected")); gtk_widget_set_tooltip_text (GTK_WIDGET (applet), text); g_free (text); return TRUE; } static void rerun_backend_callback (ModemApplet *applet, xmlDoc *doc) { ModemAppletPrivate *priv = MODEM_APPLET_GET_PRIVATE (applet); gchar *text, *password; gint response; gboolean enable; shutdown_backend (applet, FALSE, FALSE); launch_backend (applet, TRUE); enable = !priv->enabled; text = (enable) ? _("To connect to your Internet service provider, you need administrator privileges") : _("To disconnect from your Internet service provider, you need administrator privileges"); gtk_label_set_text (GTK_LABEL (priv->auth_dialog_label), text); gtk_window_set_screen (GTK_WINDOW (priv->auth_dialog), gtk_widget_get_screen (GTK_WIDGET (applet))); gtk_widget_grab_focus (priv->auth_dialog_entry); response = gtk_dialog_run (GTK_DIALOG (priv->auth_dialog)); gtk_widget_hide (priv->auth_dialog); password = (gchar *) gtk_entry_get_text (GTK_ENTRY (priv->auth_dialog_entry)); if (response == GTK_RESPONSE_OK) { password = (gchar *) gtk_entry_get_text (GTK_ENTRY (priv->auth_dialog_entry)); fputs (password, priv->write_stream); fputs ("\n", priv->write_stream); while (fflush (priv->write_stream) != 0); queue_directive (applet, NULL, enable, "enable_iface", priv->dev, (enable) ? "1" : "0", NULL); } else { shutdown_backend (applet, TRUE, FALSE); launch_backend (applet, FALSE); } /* stab the root password */ memset (password, ' ', sizeof (password)); gtk_entry_set_text (GTK_ENTRY (priv->auth_dialog_entry), ""); } static void update_info_callback (ModemApplet *applet, xmlDoc *doc) { xmlNodePtr iface; if (!doc) return; iface = find_dialup_interface_node (get_root_node (doc)); if (!iface) return; get_interface_data (applet, iface); update_popup_buttons (applet); } static gboolean update_info (ModemApplet *applet) { queue_directive (applet, update_info_callback, FALSE, "get", NULL); return TRUE; } static gboolean check_backend (ModemApplet *applet) { ModemAppletPrivate *priv = MODEM_APPLET_GET_PRIVATE (applet); gint status, pid = -1; GtkWidget *dialog; pid = waitpid (priv->pid, &status, WNOHANG); if (pid != 0) { if (errno == ECHILD || ((WIFEXITED (status)) && (WEXITSTATUS (status)) && (WEXITSTATUS(status) < 255))) { dialog = gtk_message_dialog_new (NULL, GTK_DIALOG_MODAL, GTK_MESSAGE_WARNING, GTK_BUTTONS_CLOSE, _("The entered password is invalid")); gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog), _("Check that you have typed it correctly and that " "you haven't activated the \"caps lock\" key")); gtk_dialog_run (GTK_DIALOG (dialog)); gtk_widget_destroy (dialog); } priv->timeout_id = 0; shutdown_backend (applet, FALSE, TRUE); launch_backend (applet, FALSE); return FALSE; } return TRUE; } static void launch_backend (ModemApplet *applet, gboolean root_auth) { ModemAppletPrivate *priv = MODEM_APPLET_GET_PRIVATE (applet); gchar *non_auth_args[] = { STB_SCRIPTS_DIR "/network-conf", NULL }; gchar *auth_args[] = { SU_PATH, "-c", STB_SCRIPTS_DIR "/network-conf", NULL }; gchar **args; int p[2]; pipe (p); priv->pid = forkpty (&priv->write_fd, NULL, NULL, NULL); args = (root_auth) ? auth_args : non_auth_args; if (priv->pid < 0) g_warning ("Could not spawn GST backend"); else { if (priv->pid == 0) { /* child process */ unsetenv("LC_ALL"); unsetenv("LC_MESSAGES"); unsetenv("LANG"); unsetenv("LANGUAGE"); dup2 (p[1], 1); dup2 (p[1], 2); close (p[0]); execv (args[0], args); exit (255); } else { close (p[1]); priv->read_fd = p[0]; priv->timeout_id = g_timeout_add_seconds (1, (GSourceFunc) check_backend, applet); priv->info_id = g_timeout_add_seconds (3, (GSourceFunc) update_info, applet); priv->read_stream = fdopen (priv->read_fd, "r"); priv->write_stream = fdopen (priv->write_fd, "w"); priv->has_root = root_auth; setvbuf (priv->read_stream, NULL, _IONBF, 0); fcntl (priv->read_fd, F_SETFL, 0); } } } static gboolean launch_config_tool (GdkScreen *screen, gboolean is_isdn) { gchar *argv[4], *application; gboolean ret; application = g_find_program_in_path (NETWORK_TOOL); if (!application) return FALSE; argv[0] = application; argv[1] = "--configure-type"; argv[2] = (is_isdn) ? "isdn" : "modem"; argv[3] = NULL; ret = gdk_spawn_on_screen (screen, NULL, argv, NULL, 0, NULL, NULL, NULL, NULL); g_free (application); return ret; } static void toggle_interface_non_root (ModemApplet *applet, gboolean enable) { queue_directive (applet, rerun_backend_callback, FALSE, "end", NULL); } static void toggle_interface_root (ModemApplet *applet, gboolean enable) { ModemAppletPrivate *priv = MODEM_APPLET_GET_PRIVATE (applet); GtkWidget *dialog; gchar *text; text = (enable) ? _("Do you want to connect?") : _("Do you want to disconnect?"); dialog = gtk_message_dialog_new (NULL, GTK_DIALOG_MODAL, GTK_MESSAGE_QUESTION, GTK_BUTTONS_NONE, text); gtk_dialog_add_buttons (GTK_DIALOG (dialog), GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, (enable) ? _("C_onnect") : _("_Disconnect"), GTK_RESPONSE_OK, NULL); gtk_window_set_screen (GTK_WINDOW (dialog), gtk_widget_get_screen (GTK_WIDGET (applet))); if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) queue_directive (applet, NULL, enable, "enable_iface", priv->dev, (enable) ? "1" : "0", NULL); gtk_widget_destroy (dialog); } static void toggle_interface (ModemApplet *applet, gboolean enable) { ModemAppletPrivate *priv = MODEM_APPLET_GET_PRIVATE (applet); if (priv->has_root) toggle_interface_root (applet, enable); else toggle_interface_non_root (applet, enable); } static void on_modem_applet_activate (GtkAction *action, ModemApplet *applet) { toggle_interface (applet, TRUE); } static void on_modem_applet_deactivate (GtkAction *action, ModemApplet *applet) { toggle_interface (applet, FALSE); } static void on_modem_applet_properties_clicked (GtkAction *action, ModemApplet *applet) { ModemAppletPrivate *priv = MODEM_APPLET_GET_PRIVATE (applet); GdkScreen *screen; GtkWidget *dialog; screen = gtk_widget_get_screen (GTK_WIDGET (applet)); if (!launch_config_tool (screen, priv->is_isdn)) { dialog = gtk_message_dialog_new (NULL, GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, _("Could not launch network configuration tool")); gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog), _("Check that it's installed in the correct path " "and that it has the correct permissions")); gtk_dialog_run (GTK_DIALOG (dialog)); gtk_widget_destroy (dialog); } } static void on_modem_applet_about_clicked (GtkAction *action, ModemApplet *applet) { const gchar *authors[] = { "Carlos Garnacho Parro ", NULL }; /* const gchar *documenters[] = { NULL }; */ gtk_show_about_dialog (NULL, "version", VERSION, "copyright", "Copyright \xC2\xA9 2004 Free Software Foundation. Inc.", "comments", _("Applet for activating and monitoring a dial-up network connection."), "authors", authors, /* "documenters", documenters, */ "translator-credits", _("translator-credits"), "logo_icon_name", "mate-modem-monitor-applet", NULL); } static void on_modem_applet_help_clicked (GtkAction *action, ModemApplet *applet) { gtk_show_uri (gtk_widget_get_screen (GTK_WIDGET (applet)), "ghelp:modemlights", gtk_get_current_event_time (), NULL); } static gboolean modem_applet_fill (ModemApplet *applet) { ModemAppletPrivate *priv = MODEM_APPLET_GET_PRIVATE (applet); gchar *ui_path; g_return_val_if_fail (PANEL_IS_APPLET (applet), FALSE); gtk_widget_show_all (GTK_WIDGET (applet)); priv->action_group = gtk_action_group_new ("ModemLights Applet Actions"); gtk_action_group_set_translation_domain (priv->action_group, GETTEXT_PACKAGE); gtk_action_group_add_actions (priv->action_group, menu_actions, G_N_ELEMENTS (menu_actions), applet); update_popup_buttons (applet); ui_path = g_build_filename (MODEM_MENU_UI_DIR, "modem-applet-menu.xml", NULL); mate_panel_applet_setup_menu_from_file (MATE_PANEL_APPLET (applet), ui_path, priv->action_group); g_free (ui_path); return TRUE; } static gboolean modem_applet_factory (MatePanelApplet *applet, const gchar *iid, gpointer data) { gboolean retval = FALSE; if (!strcmp (iid, "ModemLightsApplet")) retval = modem_applet_fill (MODEM_APPLET (applet)); return retval; } MATE_PANEL_APPLET_OUT_PROCESS_FACTORY ("ModemAppletFactory", TYPE_MODEM_APPLET, "modem", modem_applet_factory, NULL)