summaryrefslogtreecommitdiff
path: root/netspeed/src
diff options
context:
space:
mode:
authormonsta <[email protected]>2015-12-11 13:43:46 +0300
committermonsta <[email protected]>2015-12-14 16:41:47 +0300
commit8aabf4f0797f7cb4a56b194b66b7c41537fcbc69 (patch)
tree4a8ced2d14dbb2e39cca6e7af7d12d8ef9554406 /netspeed/src
parent33c414812425341777454444904cecf8a525c13a (diff)
downloadmate-applets-8aabf4f0797f7cb4a56b194b66b7c41537fcbc69.tar.bz2
mate-applets-8aabf4f0797f7cb4a56b194b66b7c41537fcbc69.tar.xz
merge netspeed applet from mate-netspeed repo
Diffstat (limited to 'netspeed/src')
-rw-r--r--netspeed/src/Makefile.am18
-rw-r--r--netspeed/src/backend.c330
-rw-r--r--netspeed/src/backend.h95
-rw-r--r--netspeed/src/netspeed.c1812
4 files changed, 2255 insertions, 0 deletions
diff --git a/netspeed/src/Makefile.am b/netspeed/src/Makefile.am
new file mode 100644
index 00000000..02e439cb
--- /dev/null
+++ b/netspeed/src/Makefile.am
@@ -0,0 +1,18 @@
+AM_CPPFLAGS = -I$(top_srcdir) -I$(includedir) \
+ $(GIO_CFLAGS) $(GTOP_APPLETS_CFLAGS) \
+ $(MATE_APPLETS4_CFLAGS) $(MATEDESKTOP_CFLAGS) \
+ -DMATELOCALEDIR=\""$(datadir)/locale"\" \
+ -DDATADIR=\""$(datadir)/"\" \
+ -DPREFIX=\""$(prefix)/"\" \
+ -DLIBDIR=\""$(libdir)/"\" \
+ -DSYSCONFDIR=\""$(sysconfdir)/"\" \
+ -DNETSPEED_MENU_UI_DIR=\""$(datadir)/mate/ui"\"
+
+libexec_PROGRAMS = mate-netspeed-applet
+
+mate_netspeed_applet_SOURCES = backend.h backend.c netspeed.c
+
+mate_netspeed_applet_LDADD = $(GIO_LIBS) $(GTOP_APPLETS_LIBS) \
+ $(MATE_APPLETS4_LIBS) $(MATEDESKTOP_LIBS) \
+ $(IWLIB) $(INTLLIBS) -lm
+
diff --git a/netspeed/src/backend.c b/netspeed/src/backend.c
new file mode 100644
index 00000000..17bbef24
--- /dev/null
+++ b/netspeed/src/backend.c
@@ -0,0 +1,330 @@
+/* backend.c
+ *
+ * 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 Library 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.
+ *
+ * Netspeed Applet was writen by Jörgen Scheibengruber <[email protected]>
+ *
+ * Mate Netspeed Applet migrated by Stefano Karapetsas <[email protected]>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#if defined(sun) && defined(__SVR4)
+#include <sys/sockio.h>
+#endif
+
+#include <glibtop/netlist.h>
+#include <glibtop/netload.h>
+
+#ifdef HAVE_IW
+ #include <iwlib.h>
+#endif /* HAVE_IW */
+
+#include "backend.h"
+
+gboolean
+is_dummy_device(const char* device)
+{
+ glibtop_netload netload;
+ glibtop_get_netload(&netload, device);
+
+ if (netload.if_flags & (1 << GLIBTOP_IF_FLAGS_LOOPBACK))
+ return TRUE;
+
+ /* Skip interfaces without any IPv4/IPv6 address (or
+ those with only a LINK ipv6 addr) However we need to
+ be able to exclude these while still keeping the
+ value so when they get online (with NetworkManager
+ for example) we don't get a suddent peak. Once we're
+ able to get this, ignoring down interfaces will be
+ possible too. */
+ if (!(netload.flags & (1 << GLIBTOP_NETLOAD_ADDRESS6)
+ && netload.scope6 != GLIBTOP_IF_IN6_SCOPE_LINK)
+ && !(netload.flags & (1 << GLIBTOP_NETLOAD_ADDRESS)))
+ return TRUE;
+
+ return FALSE;
+}
+
+
+/* Check for all available devices. This really should be
+ * portable for at least all plattforms using the gnu c lib
+ * TODO: drop it, use glibtop_get_netlist directly / gchar**
+ */
+GList*
+get_available_devices(void)
+{
+ glibtop_netlist buf;
+ char **devices, **dev;
+ GList *device_glist = NULL;
+
+ devices = glibtop_get_netlist(&buf);
+
+ for(dev = devices; *dev; ++dev) {
+ device_glist = g_list_prepend(device_glist, g_strdup(*dev));
+ }
+
+ g_strfreev(devices);
+
+ return device_glist;
+}
+
+const gchar*
+get_default_route(void)
+{
+ FILE *fp;
+ static char device[50];
+
+ fp = fopen("/proc/net/route", "r");
+
+ if (fp == NULL) return NULL;
+
+ while (!feof(fp)) {
+ char buffer[1024];
+ unsigned int ip, gw, flags, ref, use, metric, mask, mtu, window, irtt;
+ int retval;
+ char *rv;
+
+ rv = fgets(buffer, 1024, fp);
+ if (!rv) {
+ break;
+ }
+
+ retval = sscanf(buffer, "%49s %x %x %x %u %u %u %x %u %u %u",
+ device, &ip, &gw, &flags, &ref, &use, &metric, &mask, &mtu, &window, &irtt);
+
+ if (retval != 11) continue;
+
+ if (gw == 0 && !is_dummy_device(device)) {
+ fclose(fp);
+ return device;
+ }
+ }
+ fclose(fp);
+ return NULL;
+}
+
+
+void
+free_devices_list(GList *list)
+{
+ g_list_foreach(list, (GFunc)g_free, NULL);
+ g_list_free(list);
+}
+
+
+/* Frees a DevInfo struct and all the stuff it contains
+ */
+void
+free_device_info(DevInfo *devinfo)
+{
+ g_free(devinfo->name);
+ g_free(devinfo->ip);
+ g_free(devinfo->netmask);
+ g_free(devinfo->ptpip);
+ g_free(devinfo->hwaddr);
+ g_free(devinfo->ipv6);
+ g_free(devinfo->essid);
+ g_free(devinfo->tx_rate);
+ g_free(devinfo->rx_rate);
+ g_free(devinfo->sum_rate);
+}
+
+
+
+
+static char*
+format_ipv4(guint32 ip)
+{
+ char *str = g_malloc(INET_ADDRSTRLEN);
+ inet_ntop(AF_INET, &ip, str, INET_ADDRSTRLEN);
+ return str;
+}
+
+
+static char*
+format_ipv6(const guint8 ip[16])
+{
+ char *str = g_malloc(INET6_ADDRSTRLEN);
+ inet_ntop(AF_INET6, ip, str, INET6_ADDRSTRLEN);
+ return str;
+}
+
+
+/* TODO:
+ these stuff are not portable because of ioctl
+*/
+static void
+get_ptp_info(DevInfo *devinfo)
+{
+ int fd = -1;
+ struct ifreq request = {};
+
+ g_strlcpy(request.ifr_name, devinfo->name, sizeof request.ifr_name);
+
+ if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
+ return;
+
+ if (ioctl(fd, SIOCGIFDSTADDR, &request) >= 0) {
+ struct sockaddr_in* addr;
+ addr = (struct sockaddr_in*)&request.ifr_dstaddr;
+ devinfo->ptpip = format_ipv4(addr->sin_addr.s_addr);
+ }
+
+ close(fd);
+}
+
+
+
+
+void
+get_device_info(const char *device, DevInfo *devinfo)
+{
+ glibtop_netload netload;
+ guint8 *hw;
+
+ g_assert(device);
+
+ memset(devinfo, 0, sizeof *devinfo);
+
+ devinfo->name = g_strdup(device);
+ devinfo->type = DEV_UNKNOWN;
+
+ glibtop_get_netload(&netload, device);
+ devinfo->tx = netload.bytes_out;
+ devinfo->rx = netload.bytes_in;
+
+ devinfo->up = (netload.if_flags & (1L << GLIBTOP_IF_FLAGS_UP) ? TRUE : FALSE);
+ devinfo->running = (netload.if_flags & (1L << GLIBTOP_IF_FLAGS_RUNNING) ? TRUE : FALSE);
+
+ devinfo->ip = format_ipv4(netload.address);
+ devinfo->netmask = format_ipv4(netload.subnet);
+ devinfo->ipv6 = format_ipv6(netload.address6);
+ devinfo->qual = 0;
+ devinfo->essid = NULL;
+
+ hw = netload.hwaddress;
+ if (hw[6] || hw[7]) {
+ devinfo->hwaddr = g_strdup_printf(
+ "%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X",
+ hw[0], hw[1], hw[2], hw[3],
+ hw[4], hw[5], hw[6], hw[7]);
+ } else {
+ devinfo->hwaddr = g_strdup_printf(
+ "%02X:%02X:%02X:%02X:%02X:%02X",
+ hw[0], hw[1], hw[2],
+ hw[3], hw[4], hw[5]);
+ }
+ /* stolen from gnome-applets/multiload/linux-proc.c */
+
+ if(netload.if_flags & (1L << GLIBTOP_IF_FLAGS_LOOPBACK)) {
+ devinfo->type = DEV_LO;
+ }
+
+#ifdef HAVE_IW
+
+ else if (netload.if_flags & (1L << GLIBTOP_IF_FLAGS_WIRELESS)) {
+ devinfo->type = DEV_WIRELESS;
+ get_wireless_info (devinfo);
+ }
+
+#endif /* HAVE_IW */
+
+ else if(netload.if_flags & (1L << GLIBTOP_IF_FLAGS_POINTOPOINT)) {
+ if (g_str_has_prefix(device, "plip")) {
+ devinfo->type = DEV_PLIP;
+ }
+ else if (g_str_has_prefix(device, "sl")) {
+ devinfo->type = DEV_SLIP;
+ }
+ else {
+ devinfo->type = DEV_PPP;
+ }
+
+ get_ptp_info(devinfo);
+ }
+ else {
+ devinfo->type = DEV_ETHERNET;
+ }
+}
+
+gboolean
+compare_device_info(const DevInfo *a, const DevInfo *b)
+{
+ g_assert(a && b);
+ g_assert(a->name && b->name);
+
+ if (!g_str_equal(a->name, b->name)) return TRUE;
+ if (a->ip && b->ip) {
+ if (!g_str_equal(a->ip, b->ip)) return TRUE;
+ } else {
+ if (a->ip || b->ip) return TRUE;
+ }
+ /* Ignore hwaddr, ptpip and netmask... I think this is ok */
+ if (a->up != b->up) return TRUE;
+ if (a->running != b->running) return TRUE;
+
+ return FALSE;
+}
+#ifdef HAVE_IW
+void
+get_wireless_info (DevInfo *devinfo)
+{
+ int fd;
+ int newqual;
+ wireless_info info = {0};
+
+ fd = iw_sockets_open ();
+
+ if (fd < 0)
+ return;
+
+ if (iw_get_basic_config (fd, devinfo->name, &info.b) < 0)
+ goto out;
+
+ if (info.b.has_essid) {
+ if ((!devinfo->essid) || (strcmp (devinfo->essid, info.b.essid) != 0)) {
+ devinfo->essid = g_strdup (info.b.essid);
+ }
+ } else {
+ devinfo->essid = NULL;
+ }
+
+ if (iw_get_stats (fd, devinfo->name, &info.stats, &info.range, info.has_range) >= 0)
+ info.has_stats = 1;
+
+ if (info.has_stats) {
+ if ((iw_get_range_info(fd, devinfo->name, &info.range) >= 0) && (info.range.max_qual.qual > 0)) {
+ newqual = 0.5f + (100.0f * info.stats.qual.qual) / (1.0f * info.range.max_qual.qual);
+ } else {
+ newqual = info.stats.qual.qual;
+ }
+
+ newqual = CLAMP(newqual, 0, 100);
+ if (devinfo->qual != newqual)
+ devinfo->qual = newqual;
+
+ } else {
+ devinfo->qual = 0;
+ }
+
+ goto out;
+out:
+ if (fd != -1)
+ close (fd);
+}
+#endif /* HAVE_IW */
diff --git a/netspeed/src/backend.h b/netspeed/src/backend.h
new file mode 100644
index 00000000..7abccdf2
--- /dev/null
+++ b/netspeed/src/backend.h
@@ -0,0 +1,95 @@
+/* backend.h
+ *
+ * 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 Library 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.
+ *
+ * Netspeed Applet was writen by Jörgen Scheibengruber <[email protected]>
+ */
+
+#ifndef _BACKEND_H
+#define _BACKEND_H
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <ctype.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <net/if.h>
+#include <sys/ioctl.h>
+#include <glib.h>
+#include <glibtop/netload.h>
+
+/* copied from <linux/wireless.h> */
+#define SIOCGIWNAME 0x8B01 /* get name == wireless protocol */
+#define SIOCGIWENCODE 0x8B2B /* get encoding token & mode */
+
+/* Different types of interfaces */
+typedef enum
+{
+ DEV_LO,
+ DEV_ETHERNET,
+ DEV_WIRELESS,
+ DEV_PPP,
+ DEV_PLIP,
+ DEV_SLIP,
+ DEV_UNKNOWN // this has to be the last one
+} DevType;
+
+/* Some information about the selected network device
+ */
+typedef struct
+{
+ DevType type;
+ char *name;
+ char *ip;
+ char *netmask;
+ char *hwaddr;
+ char *ptpip;
+ char *ipv6;
+ char *essid;
+ gboolean up, running;
+ guint64 tx, rx;
+ int qual;
+ char *tx_rate;
+ char *rx_rate;
+ char *sum_rate;
+} DevInfo;
+
+GList*
+get_available_devices(void);
+
+const gchar*
+get_default_route(void);
+
+gboolean
+is_dummy_device(const char* device);
+
+void
+free_devices_list(GList *list);
+
+void
+free_device_info(DevInfo *devinfo);
+
+void
+get_device_info(const char *device, DevInfo *info);
+
+gboolean
+compare_device_info(const DevInfo *a, const DevInfo *b);
+
+void
+get_wireless_info (DevInfo *devinfo);
+#endif /* _BACKEND_H */
diff --git a/netspeed/src/netspeed.c b/netspeed/src/netspeed.c
new file mode 100644
index 00000000..98d486d6
--- /dev/null
+++ b/netspeed/src/netspeed.c
@@ -0,0 +1,1812 @@
+ /* netspeed.c
+ *
+ * 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 Library 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.
+ *
+ * Netspeed Applet was writen by Jörgen Scheibengruber <[email protected]>
+ *
+ * Mate Netspeed Applet migrated by Stefano Karapetsas <[email protected]>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <math.h>
+#include <gtk/gtk.h>
+#include <mate-panel-applet.h>
+#include <mate-panel-applet-gsettings.h>
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <gio/gio.h>
+#include <libmate-desktop/mate-aboutdialog.h>
+#include <libmate-desktop/mate-colorbutton.h>
+
+#include "backend.h"
+
+#if GTK_CHECK_VERSION (3, 0, 0)
+#define gtk_vbox_new(X,Y) gtk_box_new(GTK_ORIENTATION_VERTICAL,Y)
+#define gtk_hbox_new(X,Y) gtk_box_new(GTK_ORIENTATION_HORIZONTAL,Y)
+#endif
+
+ /* Icons for the interfaces */
+static const char* const dev_type_icon[DEV_UNKNOWN + 1] = {
+ "mate-netspeed-loopback", /* DEV_LO */
+ "network-wired", /* DEV_ETHERNET */
+ "network-wireless", /* DEV_WIRELESS */
+ "mate-netspeed-ppp", /* DEV_PPP */
+ "mate-netspeed-plip", /* DEV_PLIP */
+ "mate-netspeed-plip", /* DEV_SLIP */
+ "network-workgroup", /* DEV_UNKNOWN */
+};
+
+static const char* wireless_quality_icon[] = {
+ "mate-netspeed-wireless-25",
+ "mate-netspeed-wireless-50",
+ "mate-netspeed-wireless-75",
+ "mate-netspeed-wireless-100"
+};
+
+static const char IN_ICON[] = "go-down";
+static const char OUT_ICON[] = "go-up";
+static const char ERROR_ICON[] = "gtk-dialog-error";
+static const char LOGO_ICON[] = "mate-netspeed-applet";
+
+/* How many old in out values do we store?
+ * The value actually shown in the applet is the average
+ * of these values -> prevents the value from
+ * "jumping around like crazy"
+ */
+#define OLD_VALUES 5
+#define GRAPH_VALUES 180
+#define GRAPH_LINES 4
+
+/* A struct containing all the "global" data of the
+ * applet
+ */
+typedef struct
+{
+ MatePanelApplet *applet;
+ GtkWidget *box, *pix_box,
+ *in_box, *in_label, *in_pix,
+ *out_box, *out_label, *out_pix,
+ *sum_box, *sum_label, *dev_pix, *qual_pix;
+ GdkPixbuf *qual_pixbufs[4];
+
+ GtkWidget *signalbar;
+
+ gboolean labels_dont_shrink;
+
+ DevInfo devinfo;
+ gboolean device_has_changed;
+
+ guint timeout_id;
+ int refresh_time;
+ char *up_cmd, *down_cmd;
+ gboolean show_sum, show_bits;
+ gboolean change_icon, auto_change_device;
+ gboolean show_icon, short_unit;
+ gboolean show_quality_icon;
+ GdkColor in_color, out_color;
+ int width;
+
+ GtkWidget *inbytes_text, *outbytes_text;
+ GtkDialog *details, *settings;
+ GtkDrawingArea *drawingarea;
+ GtkWidget *network_device_combo;
+
+ guint index_old;
+ guint64 in_old[OLD_VALUES], out_old[OLD_VALUES];
+ double max_graph, in_graph[GRAPH_VALUES], out_graph[GRAPH_VALUES];
+ int index_graph;
+
+ GtkWidget *connect_dialog;
+
+ gboolean show_tooltip;
+
+ GSettings *gsettings;
+} MateNetspeedApplet;
+
+static void
+update_tooltip(MateNetspeedApplet* applet);
+
+static void
+device_change_cb(GtkComboBox *combo, MateNetspeedApplet *applet);
+
+/* Adds a Pango markup "size" to a bytestring
+ */
+static void
+add_markup_size(char **string, int size)
+{
+ char *tmp = *string;
+ *string = g_strdup_printf("<span size=\"%d\">%s</span>", size * 1000, tmp);
+ g_free(tmp);
+}
+
+/* Adds a Pango markup "foreground" to a bytestring
+ */
+static void
+add_markup_fgcolor(char **string, const char *color)
+{
+ char *tmp = *string;
+ *string = g_strdup_printf("<span foreground=\"%s\">%s</span>", color, tmp);
+ g_free(tmp);
+}
+
+/* Here some rearangement of the icons and the labels occurs
+ * according to the panelsize and wether we show in and out
+ * or just the sum
+ */
+static void
+applet_change_size_or_orient(MatePanelApplet *applet_widget, int arg1, MateNetspeedApplet *applet)
+{
+ int size;
+ MatePanelAppletOrient orient;
+
+ g_assert(applet);
+
+ size = mate_panel_applet_get_size(applet_widget);
+ orient = mate_panel_applet_get_orient(applet_widget);
+
+ g_object_ref(applet->pix_box);
+ g_object_ref(applet->in_pix);
+ g_object_ref(applet->in_label);
+ g_object_ref(applet->out_pix);
+ g_object_ref(applet->out_label);
+ g_object_ref(applet->sum_label);
+
+ if (applet->in_box) {
+ gtk_container_remove(GTK_CONTAINER(applet->in_box), applet->in_label);
+ gtk_container_remove(GTK_CONTAINER(applet->in_box), applet->in_pix);
+ gtk_widget_destroy(applet->in_box);
+ }
+ if (applet->out_box) {
+ gtk_container_remove(GTK_CONTAINER(applet->out_box), applet->out_label);
+ gtk_container_remove(GTK_CONTAINER(applet->out_box), applet->out_pix);
+ gtk_widget_destroy(applet->out_box);
+ }
+ if (applet->sum_box) {
+ gtk_container_remove(GTK_CONTAINER(applet->sum_box), applet->sum_label);
+ gtk_widget_destroy(applet->sum_box);
+ }
+ if (applet->box) {
+ gtk_container_remove(GTK_CONTAINER(applet->box), applet->pix_box);
+ gtk_widget_destroy(applet->box);
+ }
+
+ if (orient == MATE_PANEL_APPLET_ORIENT_LEFT || orient == MATE_PANEL_APPLET_ORIENT_RIGHT) {
+ applet->box = gtk_vbox_new(FALSE, 0);
+ if (size > 64) {
+ applet->sum_box = gtk_hbox_new(FALSE, 2);
+ applet->in_box = gtk_hbox_new(FALSE, 1);
+ applet->out_box = gtk_hbox_new(FALSE, 1);
+ } else {
+ applet->sum_box = gtk_vbox_new(FALSE, 0);
+ applet->in_box = gtk_vbox_new(FALSE, 0);
+ applet->out_box = gtk_vbox_new(FALSE, 0);
+ }
+ applet->labels_dont_shrink = FALSE;
+ } else {
+ applet->in_box = gtk_hbox_new(FALSE, 1);
+ applet->out_box = gtk_hbox_new(FALSE, 1);
+ if (size < 48) {
+ applet->sum_box = gtk_hbox_new(FALSE, 2);
+ applet->box = gtk_hbox_new(FALSE, 1);
+ applet->labels_dont_shrink = TRUE;
+ } else {
+ applet->sum_box = gtk_vbox_new(FALSE, 0);
+ applet->box = gtk_vbox_new(FALSE, 0);
+ applet->labels_dont_shrink = !applet->show_sum;
+ }
+ }
+
+ gtk_box_pack_start(GTK_BOX(applet->in_box), applet->in_pix, FALSE, FALSE, 0);
+ gtk_box_pack_start(GTK_BOX(applet->in_box), applet->in_label, TRUE, TRUE, 0);
+ gtk_box_pack_start(GTK_BOX(applet->out_box), applet->out_pix, FALSE, FALSE, 0);
+ gtk_box_pack_start(GTK_BOX(applet->out_box), applet->out_label, TRUE, TRUE, 0);
+ gtk_box_pack_start(GTK_BOX(applet->sum_box), applet->sum_label, TRUE, TRUE, 0);
+ gtk_box_pack_start(GTK_BOX(applet->box), applet->pix_box, FALSE, FALSE, 0);
+
+ g_object_unref(applet->pix_box);
+ g_object_unref(applet->in_pix);
+ g_object_unref(applet->in_label);
+ g_object_unref(applet->out_pix);
+ g_object_unref(applet->out_label);
+ g_object_unref(applet->sum_label);
+
+ if (applet->show_sum) {
+ gtk_box_pack_start(GTK_BOX(applet->box), applet->sum_box, TRUE, TRUE, 0);
+ } else {
+ gtk_box_pack_start(GTK_BOX(applet->box), applet->in_box, TRUE, TRUE, 0);
+ gtk_box_pack_start(GTK_BOX(applet->box), applet->out_box, TRUE, TRUE, 0);
+ }
+
+ gtk_widget_show_all(applet->box);
+ if (!applet->show_icon) {
+ gtk_widget_hide(applet->dev_pix);
+ }
+ gtk_container_add(GTK_CONTAINER(applet->applet), applet->box);
+}
+
+/* Change the icons according to the selected device
+ */
+static void
+change_icons(MateNetspeedApplet *applet)
+{
+ GdkPixbuf *dev, *down;
+ GdkPixbuf *in_arrow, *out_arrow;
+ GtkIconTheme *icon_theme;
+
+ icon_theme = gtk_icon_theme_get_default();
+
+ /* If the user wants a different icon than current, we load it */
+ if (applet->show_icon && applet->change_icon) {
+ dev = gtk_icon_theme_load_icon(icon_theme,
+ dev_type_icon[applet->devinfo.type],
+ 16, 0, NULL);
+ } else {
+ dev = gtk_icon_theme_load_icon(icon_theme,
+ dev_type_icon[DEV_UNKNOWN],
+ 16, 0, NULL);
+ }
+
+ /* We need a fallback */
+ if (dev == NULL)
+ dev = gtk_icon_theme_load_icon(icon_theme,
+ dev_type_icon[DEV_UNKNOWN],
+ 16, 0, NULL);
+
+ in_arrow = gtk_icon_theme_load_icon(icon_theme, IN_ICON, 16, 0, NULL);
+ out_arrow = gtk_icon_theme_load_icon(icon_theme, OUT_ICON, 16, 0, NULL);
+
+ /* Set the windowmanager icon for the applet */
+ gtk_window_set_default_icon_name(LOGO_ICON);
+
+ gtk_image_set_from_pixbuf(GTK_IMAGE(applet->out_pix), out_arrow);
+ gtk_image_set_from_pixbuf(GTK_IMAGE(applet->in_pix), in_arrow);
+ g_object_unref(in_arrow);
+ g_object_unref(out_arrow);
+
+ if (applet->devinfo.running) {
+ gtk_widget_show(applet->in_box);
+ gtk_widget_show(applet->out_box);
+ } else {
+ GdkPixbuf *copy;
+ gtk_widget_hide(applet->in_box);
+ gtk_widget_hide(applet->out_box);
+
+ /* We're not allowed to modify "dev" */
+ copy = gdk_pixbuf_copy(dev);
+
+ down = gtk_icon_theme_load_icon(icon_theme, ERROR_ICON, 16, 0, NULL);
+ gdk_pixbuf_composite(down, copy, 8, 8, 8, 8, 8, 8, 0.5, 0.5, GDK_INTERP_BILINEAR, 0xFF);
+ g_object_unref(down);
+ g_object_unref(dev);
+ dev = copy;
+ }
+
+ if (applet->show_icon) {
+ gtk_widget_show(applet->dev_pix);
+ gtk_image_set_from_pixbuf(GTK_IMAGE(applet->dev_pix), dev);
+ } else {
+ gtk_widget_hide(applet->dev_pix);
+ }
+ g_object_unref(dev);
+}
+
+/* Change visibility of signal quality icon for wireless devices
+ */
+static void
+change_quality_icon(MateNetspeedApplet *applet)
+{
+ if (applet->devinfo.type == DEV_WIRELESS &&
+ applet->devinfo.up && applet->show_quality_icon) {
+ gtk_widget_show(applet->qual_pix);
+ } else {
+ gtk_widget_hide(applet->qual_pix);
+ }
+}
+
+static void
+update_quality_icon(MateNetspeedApplet *applet)
+{
+ if (!applet->show_quality_icon) {
+ return;
+ }
+
+ unsigned int q;
+
+ q = (applet->devinfo.qual);
+ q /= 25;
+ q = CLAMP(q, 0, 3); /* q out of range would crash when accessing qual_pixbufs[q] */
+ gtk_image_set_from_pixbuf (GTK_IMAGE(applet->qual_pix), applet->qual_pixbufs[q]);
+}
+
+static void
+init_quality_pixbufs(MateNetspeedApplet *applet)
+{
+ GtkIconTheme *icon_theme;
+ int i;
+ GdkPixbuf *pixbuf;
+
+ icon_theme = gtk_icon_theme_get_default();
+
+ for (i = 0; i < 4; i++) {
+ if (applet->qual_pixbufs[i])
+ g_object_unref(applet->qual_pixbufs[i]);
+ pixbuf = gtk_icon_theme_load_icon(icon_theme,
+ wireless_quality_icon[i], 24, 0, NULL);
+ if (pixbuf) {
+ applet->qual_pixbufs[i] = gdk_pixbuf_copy(pixbuf);
+ g_object_unref(pixbuf);
+ }
+ else {
+ applet->qual_pixbufs[i] = NULL;
+ }
+ }
+}
+
+
+static void
+icon_theme_changed_cb(GtkIconTheme *icon_theme, gpointer user_data)
+{
+ MateNetspeedApplet *applet = (MateNetspeedApplet*)user_data;
+
+ init_quality_pixbufs(user_data);
+ if (applet->devinfo.type == DEV_WIRELESS && applet->devinfo.up)
+ update_quality_icon(user_data);
+ change_icons(user_data);
+}
+
+/* Converts a number of bytes into a human
+ * readable string - in [M/k]bytes[/s]
+ * The string has to be freed
+ */
+static char*
+bytes_to_string(double bytes, gboolean per_sec, gboolean bits, gboolean shortened)
+{
+ const char *format;
+ const char *unit;
+ guint kilo; /* no really a kilo : a kilo or kibi */
+
+ if (bits) {
+ bytes *= 8;
+ kilo = 1000;
+ } else
+ kilo = 1024;
+
+ if (bytes < kilo) {
+
+ format = "%.0f %s";
+
+ if (per_sec)
+ if (shortened) {
+ unit = bits ? /* translators: bits (short) */ N_("b"): /* translators: Bytes (short) */ N_("B");
+ } else {
+ unit = bits ? N_("b/s") : N_("B/s");
+ }
+ else
+ unit = bits ? N_("bits") : N_("bytes");
+
+ } else if (bytes < (kilo * kilo)) {
+ format = (bytes < (100 * kilo)) ? "%.1f %s" : "%.0f %s";
+ bytes /= kilo;
+
+ if (per_sec)
+ if (shortened) {
+ unit = bits ? /* translators: kilobits (short) */ N_("k") : /* translators: Kilobytes (short) */ N_("K");
+ } else {
+ unit = bits ? N_("kb/s") : N_("KiB/s");
+ }
+ else
+ unit = bits ? N_("kb") : N_("KiB");
+
+ } else {
+
+ format = "%.1f %s";
+
+ bytes /= kilo * kilo;
+
+ if (per_sec)
+ if (shortened) {
+ unit = bits ? /* translators: megabits (short) */ N_("m") : /* translators: Megabytes (short) */ N_("M");
+ } else {
+ unit = bits ? N_("Mb/s") : N_("MiB/s");
+ }
+ else
+ unit = bits ? N_("Mb") : N_("MiB");
+ }
+
+ return g_strdup_printf(format, bytes, gettext(unit));
+}
+
+
+/* Redraws the graph drawingarea
+ * Some really black magic is going on in here ;-)
+ */
+static void
+redraw_graph(MateNetspeedApplet *applet, cairo_t *cr)
+{
+ GtkWidget *da = GTK_WIDGET(applet->drawingarea);
+#if GTK_CHECK_VERSION (3, 0, 0)
+ GtkStyleContext *stylecontext = gtk_widget_get_style_context (da);
+#else
+ GtkStyle *style = gtk_widget_get_style (da);
+#endif
+ GdkWindow *real_window = gtk_widget_get_window (da);
+ GdkRectangle ra;
+ GtkStateType state;
+ GdkPoint in_points[GRAPH_VALUES], out_points[GRAPH_VALUES];
+ PangoLayout *layout;
+ PangoRectangle logical_rect;
+ char *text;
+ int i, offset, w, h;
+ double max_val;
+ double dash[2] = { 1.0, 2.0 };
+
+ w = gdk_window_get_width (real_window);
+ h = gdk_window_get_height (real_window);
+
+ /* the graph hight should be: hight/2 <= applet->max_graph < hight */
+ for (max_val = 1; max_val < applet->max_graph; max_val *= 2) ;
+
+ /* calculate the polygons (GdkPoint[]) for the graphs */
+ offset = 0;
+ for (i = (applet->index_graph + 1) % GRAPH_VALUES; applet->in_graph[i] < 0; i = (i + 1) % GRAPH_VALUES)
+ offset++;
+ for (i = offset + 1; i < GRAPH_VALUES; i++)
+ {
+ int index = (applet->index_graph + i) % GRAPH_VALUES;
+ out_points[i].x = in_points[i].x = ((w - 6) * i) / GRAPH_VALUES + 4;
+ in_points[i].y = h - 6 - (int)((h - 8) * applet->in_graph[index] / max_val);
+ out_points[i].y = h - 6 - (int)((h - 8) * applet->out_graph[index] / max_val);
+ }
+ in_points[offset].x = out_points[offset].x = ((w - 6) * offset) / GRAPH_VALUES + 4;
+ in_points[offset].y = in_points[(offset + 1) % GRAPH_VALUES].y;
+ out_points[offset].y = out_points[(offset + 1) % GRAPH_VALUES].y;
+
+ /* draw the background */
+ cairo_set_source_rgb (cr, 1.0, 1.0, 1.0);
+ cairo_rectangle (cr, 02, 2, w - 6, h - 6);
+ cairo_fill (cr);
+
+ cairo_set_line_width(cr, 1.0);
+ cairo_set_dash (cr, dash, 2, 0);
+
+ cairo_set_source_rgb (cr, 0.0, 0.0, 0.0);
+ cairo_rectangle (cr, 2, 2, w - 6, h - 6);
+ cairo_stroke (cr);
+
+ for (i = 0; i < GRAPH_LINES; i++) {
+ int y = 2 + ((h - 6) * i) / GRAPH_LINES;
+ cairo_move_to (cr, 2, y);
+ cairo_line_to (cr, w - 4, y);
+ }
+ cairo_stroke (cr);
+
+ /* draw the polygons */
+ cairo_set_dash (cr, dash, 0, 1);
+ cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND);
+ cairo_set_line_join (cr, CAIRO_LINE_JOIN_ROUND);
+
+ gdk_cairo_set_source_color (cr, &applet->in_color);
+ for (i = offset; i < GRAPH_VALUES; i++) {
+ cairo_line_to (cr, in_points[i].x, in_points[i].y);
+ }
+ cairo_stroke (cr);
+
+ gdk_cairo_set_source_color (cr, &applet->out_color);
+ for (i = offset; i < GRAPH_VALUES; i++) {
+ cairo_line_to (cr, out_points[i].x, out_points[i].y);
+ }
+ cairo_stroke (cr);
+
+ /* draw the 2 labels */
+ state = GTK_STATE_NORMAL;
+ ra.x = 0; ra.y = 0;
+ ra.width = w; ra.height = h;
+
+ text = bytes_to_string(max_val, TRUE, applet->show_bits, applet->short_unit);
+ add_markup_fgcolor(&text, "black");
+ layout = gtk_widget_create_pango_layout (da, NULL);
+ pango_layout_set_markup(layout, text, -1);
+ g_free (text);
+#if GTK_CHECK_VERSION (3, 0, 0)
+ gtk_render_layout(stylecontext, cr, 3, 2, layout);
+#else
+ gtk_paint_layout(style, real_window, state, FALSE, &ra, da, "max_graph", 3, 2, layout);
+#endif
+ g_object_unref(G_OBJECT(layout));
+
+ text = bytes_to_string(0.0, TRUE, applet->show_bits, applet->short_unit);
+ add_markup_fgcolor(&text, "black");
+ layout = gtk_widget_create_pango_layout (da, NULL);
+ pango_layout_set_markup(layout, text, -1);
+ pango_layout_get_pixel_extents (layout, NULL, &logical_rect);
+ g_free (text);
+#if GTK_CHECK_VERSION (3, 0, 0)
+ gtk_render_layout(stylecontext, cr, 3, h - 4 - logical_rect.height, layout);
+#else
+ gtk_paint_layout(style, real_window, state, FALSE, &ra, da, "max_graph", 3, h - 4 - logical_rect.height, layout);
+#endif
+ g_object_unref(G_OBJECT(layout));
+}
+
+static gboolean
+set_applet_devinfo(MateNetspeedApplet* applet, const char* iface)
+{
+ DevInfo info;
+
+ get_device_info(iface, &info);
+
+ if (info.running) {
+ free_device_info(&applet->devinfo);
+ applet->devinfo = info;
+ applet->device_has_changed = TRUE;
+ return TRUE;
+ }
+
+ free_device_info(&info);
+ return FALSE;
+}
+
+/* Find the first available device, that is running and != lo */
+static void
+search_for_up_if(MateNetspeedApplet *applet)
+{
+ const gchar *default_route;
+ GList *devices, *tmp;
+ DevInfo info;
+
+ default_route = get_default_route();
+
+ if (default_route != NULL) {
+ if (set_applet_devinfo(applet, default_route))
+ return;
+ }
+
+ devices = get_available_devices();
+ for (tmp = devices; tmp; tmp = g_list_next(tmp)) {
+ if (is_dummy_device(tmp->data))
+ continue;
+ if (set_applet_devinfo(applet, tmp->data))
+ break;
+ }
+ free_devices_list(devices);
+}
+
+/* Here happens the really interesting stuff */
+static void
+update_applet(MateNetspeedApplet *applet)
+{
+ guint64 indiff, outdiff;
+ double inrate, outrate;
+ char *inbytes, *outbytes;
+ int i;
+ DevInfo oldinfo;
+
+ if (!applet) return;
+
+ /* First we try to figure out if the device has changed */
+ oldinfo = applet->devinfo;
+ get_device_info(oldinfo.name, &applet->devinfo);
+ if (compare_device_info(&applet->devinfo, &oldinfo))
+ applet->device_has_changed = TRUE;
+ free_device_info(&oldinfo);
+
+ /* If the device has changed, reintialize stuff */
+ if (applet->device_has_changed) {
+ change_icons(applet);
+ change_quality_icon(applet);
+ for (i = 0; i < OLD_VALUES; i++)
+ {
+ applet->in_old[i] = applet->devinfo.rx;
+ applet->out_old[i] = applet->devinfo.tx;
+ }
+ for (i = 0; i < GRAPH_VALUES; i++)
+ {
+ applet->in_graph[i] = -1;
+ applet->out_graph[i] = -1;
+ }
+ applet->max_graph = 0;
+ applet->index_graph = 0;
+ applet->device_has_changed = FALSE;
+ }
+
+ /* create the strings for the labels and tooltips */
+ if (applet->devinfo.running)
+ {
+ if (applet->devinfo.rx < applet->in_old[applet->index_old]) indiff = 0;
+ else indiff = applet->devinfo.rx - applet->in_old[applet->index_old];
+ if (applet->devinfo.tx < applet->out_old[applet->index_old]) outdiff = 0;
+ else outdiff = applet->devinfo.tx - applet->out_old[applet->index_old];
+
+ inrate = indiff * 1000.0;
+ inrate /= (double)(applet->refresh_time * OLD_VALUES);
+ outrate = outdiff * 1000.0;
+ outrate /= (double)(applet->refresh_time * OLD_VALUES);
+
+ applet->in_graph[applet->index_graph] = inrate;
+ applet->out_graph[applet->index_graph] = outrate;
+ applet->max_graph = MAX(inrate, applet->max_graph);
+ applet->max_graph = MAX(outrate, applet->max_graph);
+
+ applet->devinfo.rx_rate = bytes_to_string(inrate, TRUE, applet->show_bits, applet->short_unit);
+ applet->devinfo.tx_rate = bytes_to_string(outrate, TRUE, applet->show_bits, applet->short_unit);
+ applet->devinfo.sum_rate = bytes_to_string(inrate + outrate, TRUE, applet->show_bits, applet->short_unit);
+ } else {
+ applet->devinfo.rx_rate = g_strdup("");
+ applet->devinfo.tx_rate = g_strdup("");
+ applet->devinfo.sum_rate = g_strdup("");
+ applet->in_graph[applet->index_graph] = 0;
+ applet->out_graph[applet->index_graph] = 0;
+ }
+
+ if (applet->devinfo.type == DEV_WIRELESS) {
+ if (applet->devinfo.up)
+ update_quality_icon(applet);
+
+ if (applet->signalbar) {
+ float quality;
+ char *text;
+
+ quality = applet->devinfo.qual / 100.0f;
+ if (quality > 1.0)
+ quality = 1.0;
+
+ text = g_strdup_printf ("%d %%", applet->devinfo.qual);
+ gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (applet->signalbar), quality);
+ gtk_progress_bar_set_text (GTK_PROGRESS_BAR (applet->signalbar), text);
+ g_free(text);
+ }
+ }
+
+ update_tooltip(applet);
+
+ /* Refresh the text of the labels and tooltip */
+ if (applet->show_sum) {
+ gtk_label_set_markup(GTK_LABEL(applet->sum_label), applet->devinfo.sum_rate);
+ } else {
+ gtk_label_set_markup(GTK_LABEL(applet->in_label), applet->devinfo.rx_rate);
+ gtk_label_set_markup(GTK_LABEL(applet->out_label), applet->devinfo.tx_rate);
+ }
+
+ /* Refresh the values of the Infodialog */
+ if (applet->inbytes_text) {
+ inbytes = bytes_to_string((double)applet->devinfo.rx, FALSE, FALSE, FALSE);
+ gtk_label_set_text(GTK_LABEL(applet->inbytes_text), inbytes);
+ g_free(inbytes);
+ }
+ if (applet->outbytes_text) {
+ outbytes = bytes_to_string((double)applet->devinfo.tx, FALSE, FALSE, FALSE);
+ gtk_label_set_text(GTK_LABEL(applet->outbytes_text), outbytes);
+ g_free(outbytes);
+ }
+ /* Redraw the graph of the Infodialog */
+ if (applet->drawingarea)
+ gtk_widget_queue_draw (GTK_WIDGET (applet->drawingarea));
+
+ /* Save old values... */
+ applet->in_old[applet->index_old] = applet->devinfo.rx;
+ applet->out_old[applet->index_old] = applet->devinfo.tx;
+ applet->index_old = (applet->index_old + 1) % OLD_VALUES;
+
+ /* Move the graphindex. Check if we can scale down again */
+ applet->index_graph = (applet->index_graph + 1) % GRAPH_VALUES;
+ if (applet->index_graph % 20 == 0)
+ {
+ double max = 0;
+ for (i = 0; i < GRAPH_VALUES; i++)
+ {
+ max = MAX(max, applet->in_graph[i]);
+ max = MAX(max, applet->out_graph[i]);
+ }
+ applet->max_graph = max;
+ }
+
+ /* Always follow the default route */
+ if (applet->auto_change_device) {
+ gboolean change_device_now = !applet->devinfo.running;
+ if (!change_device_now) {
+ const gchar *default_route;
+ default_route = get_default_route();
+ change_device_now = (default_route != NULL
+ && strcmp(default_route,
+ applet->devinfo.name));
+ }
+ if (change_device_now) {
+ search_for_up_if(applet);
+ }
+ }
+}
+
+static gboolean
+timeout_function(MateNetspeedApplet *applet)
+{
+ if (!applet)
+ return FALSE;
+ if (!applet->timeout_id)
+ return FALSE;
+
+ update_applet(applet);
+ return TRUE;
+}
+
+/* Display a section of netspeed help
+ */
+static void
+display_help (GtkWidget *dialog, const gchar *section)
+{
+ GdkScreen *screen;
+ GError *error = NULL;
+ gboolean ret;
+ char *uri;
+
+ if (section)
+ uri = g_strdup_printf ("help:mate-netspeed-applet/%s", section);
+ else
+ uri = g_strdup ("help:mate-netspeed-applet");
+
+ screen = gtk_widget_get_screen (dialog);
+ ret = gtk_show_uri (screen, uri, gtk_get_current_event_time (), &error);
+ g_free (uri);
+
+ if (ret == FALSE) {
+ GtkWidget *error_dialog = gtk_message_dialog_new (NULL,
+ GTK_DIALOG_MODAL,
+ GTK_MESSAGE_ERROR,
+ GTK_BUTTONS_OK,
+ _("There was an error displaying help:\n%s"),
+ error->message);
+ g_signal_connect (error_dialog, "response",
+ G_CALLBACK (gtk_widget_destroy), NULL);
+
+ gtk_window_set_resizable (GTK_WINDOW (error_dialog), FALSE);
+ gtk_window_set_screen (GTK_WINDOW (error_dialog), gtk_widget_get_screen (dialog));
+ gtk_widget_show (error_dialog);
+ g_error_free (error);
+ }
+}
+
+/* Opens gnome help application
+ */
+static void
+help_cb (GtkAction *action, MateNetspeedApplet *ap)
+{
+ display_help (GTK_WIDGET (ap->applet), NULL);
+}
+
+/* Just the about window... If it's already open, just fokus it
+ */
+static void
+about_cb(GtkAction *action, gpointer data)
+{
+ const char *authors[] =
+ {
+ "Jörgen Scheibengruber <[email protected]>",
+ "Dennis Cranston <[email protected]>",
+ "Pedro Villavicencio Garrido <[email protected]>",
+ "Benoît Dejean <[email protected]>",
+ "Stefano Karapetsas <[email protected]>",
+ "Perberos <[email protected]>",
+ NULL
+ };
+
+ mate_show_about_dialog (NULL,
+ "version", VERSION,
+ "copyright", "Copyright 2002 - 2003 Jörgen Scheibengruber\nCopyright 2011-2014 Stefano Karapetsas",
+ "comments", _("A little applet that displays some information on the traffic on the specified network device"),
+ "authors", authors,
+ "documenters", NULL,
+ "translator-credits", _("translator-credits"),
+ "website", "http://www.mate-desktop.org/",
+ "logo-icon-name", LOGO_ICON,
+ NULL);
+
+}
+
+/* this basically just retrieves the new devicestring
+ * and then calls applet_device_change() and change_icons()
+ */
+static void
+device_change_cb(GtkComboBox *combo, MateNetspeedApplet *applet)
+{
+ GList *devices;
+ int i, active;
+
+ g_assert(combo);
+ devices = g_object_get_data(G_OBJECT(combo), "devices");
+ active = gtk_combo_box_get_active(combo);
+ g_assert(active > -1);
+
+ if (0 == active) {
+ if (applet->auto_change_device)
+ return;
+ applet->auto_change_device = TRUE;
+ } else {
+ applet->auto_change_device = FALSE;
+ for (i = 1; i < active; i++) {
+ devices = g_list_next(devices);
+ }
+ if (g_str_equal(devices->data, applet->devinfo.name))
+ return;
+ free_device_info(&applet->devinfo);
+ get_device_info(devices->data, &applet->devinfo);
+ }
+
+ applet->device_has_changed = TRUE;
+ update_applet(applet);
+}
+
+
+/* Handle preference dialog response event
+ */
+static void
+pref_response_cb (GtkDialog *dialog, gint id, gpointer data)
+{
+ MateNetspeedApplet *applet = data;
+
+ if(id == GTK_RESPONSE_HELP){
+ display_help (GTK_WIDGET (dialog), "netspeed_applet-settings");
+ return;
+ }
+ g_settings_delay (applet->gsettings);
+ g_settings_set_string (applet->gsettings, "device", applet->devinfo.name);
+ g_settings_set_boolean (applet->gsettings, "show-sum", applet->show_sum);
+ g_settings_set_boolean (applet->gsettings, "show-bits", applet->show_bits);
+ g_settings_set_boolean (applet->gsettings, "short-unit", applet->short_unit);
+ g_settings_set_boolean (applet->gsettings, "show-icon", applet->show_icon);
+ g_settings_set_boolean (applet->gsettings, "show-quality-icon", applet->show_quality_icon);
+ g_settings_set_boolean (applet->gsettings, "change-icon", applet->change_icon);
+ g_settings_set_boolean (applet->gsettings, "auto-change-device", applet->auto_change_device);
+ g_settings_apply (applet->gsettings);
+
+ gtk_widget_destroy(GTK_WIDGET(applet->settings));
+ applet->settings = NULL;
+}
+
+/* Called when the showsum checkbutton is toggled...
+ */
+static void
+showsum_change_cb(GtkToggleButton *togglebutton, MateNetspeedApplet *applet)
+{
+ applet->show_sum = gtk_toggle_button_get_active(togglebutton);
+ applet_change_size_or_orient(applet->applet, -1, (gpointer)applet);
+ change_icons(applet);
+}
+
+/* Called when the showbits checkbutton is toggled...
+ */
+static void
+showbits_change_cb(GtkToggleButton *togglebutton, MateNetspeedApplet *applet)
+{
+ applet->show_bits = gtk_toggle_button_get_active(togglebutton);
+}
+
+/* Called when the shortunit checkbutton is toggled...
+ */
+static void
+shortunit_change_cb(GtkToggleButton *togglebutton, MateNetspeedApplet *applet)
+{
+ applet->short_unit = gtk_toggle_button_get_active(togglebutton);
+}
+
+/* Called when the showicon checkbutton is toggled...
+ */
+static void
+showicon_change_cb(GtkToggleButton *togglebutton, MateNetspeedApplet *applet)
+{
+ applet->show_icon = gtk_toggle_button_get_active(togglebutton);
+ change_icons(applet);
+}
+
+/* Called when the showqualityicon checkbutton is toggled...
+ */
+static void
+showqualityicon_change_cb(GtkToggleButton *togglebutton, MateNetspeedApplet *applet)
+{
+ applet->show_quality_icon = gtk_toggle_button_get_active(togglebutton);
+ change_quality_icon(applet);
+}
+
+/* Called when the changeicon checkbutton is toggled...
+ */
+static void
+changeicon_change_cb(GtkToggleButton *togglebutton, MateNetspeedApplet *applet)
+{
+ applet->change_icon = gtk_toggle_button_get_active(togglebutton);
+ change_icons(applet);
+}
+
+/* Creates the settings dialog
+ * After its been closed, take the new values and store
+ * them in the gsettings database
+ */
+static void
+settings_cb(GtkAction *action, gpointer data)
+{
+ MateNetspeedApplet *applet = (MateNetspeedApplet*)data;
+ GtkWidget *vbox;
+ GtkWidget *hbox;
+ GtkWidget *categories_vbox;
+ GtkWidget *category_vbox;
+ GtkWidget *controls_vbox;
+ GtkWidget *category_header_label;
+ GtkWidget *network_device_hbox;
+ GtkWidget *network_device_label;
+ GtkWidget *indent_label;
+ GtkWidget *show_sum_checkbutton;
+ GtkWidget *show_bits_checkbutton;
+ GtkWidget *short_unit_checkbutton;
+ GtkWidget *show_icon_checkbutton;
+ GtkWidget *show_quality_icon_checkbutton;
+ GtkWidget *change_icon_checkbutton;
+ GtkSizeGroup *category_label_size_group;
+ gchar *header_str;
+ GList *ptr, *devices;
+ int i, active = -1;
+
+ g_assert(applet);
+
+ if (applet->settings)
+ {
+ gtk_window_present(GTK_WINDOW(applet->settings));
+ return;
+ }
+
+ category_label_size_group = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
+
+ applet->settings = GTK_DIALOG(gtk_dialog_new_with_buttons(_("Mate Netspeed Preferences"),
+ NULL,
+ GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_STOCK_HELP, GTK_RESPONSE_HELP,
+ GTK_STOCK_CLOSE, GTK_RESPONSE_ACCEPT,
+ NULL));
+
+ gtk_window_set_resizable(GTK_WINDOW(applet->settings), FALSE);
+ gtk_window_set_screen(GTK_WINDOW(applet->settings),
+ gtk_widget_get_screen(GTK_WIDGET(applet->settings)));
+
+ gtk_dialog_set_default_response(GTK_DIALOG(applet->settings), GTK_RESPONSE_CLOSE);
+
+ vbox = gtk_vbox_new(FALSE, 0);
+ gtk_container_set_border_width(GTK_CONTAINER(vbox), 12);
+
+ categories_vbox = gtk_vbox_new(FALSE, 18);
+ gtk_box_pack_start(GTK_BOX (vbox), categories_vbox, TRUE, TRUE, 0);
+
+ category_vbox = gtk_vbox_new(FALSE, 6);
+ gtk_box_pack_start(GTK_BOX (categories_vbox), category_vbox, TRUE, TRUE, 0);
+
+ header_str = g_strconcat("<span weight=\"bold\">", _("General Settings"), "</span>", NULL);
+ category_header_label = gtk_label_new(header_str);
+ gtk_label_set_use_markup(GTK_LABEL(category_header_label), TRUE);
+ gtk_label_set_justify(GTK_LABEL(category_header_label), GTK_JUSTIFY_LEFT);
+#if GTK_CHECK_VERSION (3, 0, 0)
+ gtk_widget_set_halign (category_header_label, GTK_ALIGN_START);
+ gtk_widget_set_valign (category_header_label, GTK_ALIGN_CENTER);
+#else
+ gtk_misc_set_alignment(GTK_MISC (category_header_label), 0, 0.5);
+#endif
+ gtk_box_pack_start(GTK_BOX (category_vbox), category_header_label, FALSE, FALSE, 0);
+ g_free(header_str);
+
+ hbox = gtk_hbox_new(FALSE, 0);
+ gtk_box_pack_start(GTK_BOX (category_vbox), hbox, TRUE, TRUE, 0);
+
+ indent_label = gtk_label_new(" ");
+ gtk_label_set_justify(GTK_LABEL (indent_label), GTK_JUSTIFY_LEFT);
+ gtk_box_pack_start(GTK_BOX (hbox), indent_label, FALSE, FALSE, 0);
+
+ controls_vbox = gtk_vbox_new(FALSE, 10);
+ gtk_box_pack_start(GTK_BOX(hbox), controls_vbox, TRUE, TRUE, 0);
+
+ network_device_hbox = gtk_hbox_new(FALSE, 6);
+ gtk_box_pack_start(GTK_BOX(controls_vbox), network_device_hbox, TRUE, TRUE, 0);
+
+ network_device_label = gtk_label_new_with_mnemonic(_("Network _device:"));
+ gtk_label_set_justify(GTK_LABEL(network_device_label), GTK_JUSTIFY_LEFT);
+#if GTK_CHECK_VERSION (3, 0, 0)
+ gtk_widget_set_halign (network_device_label, GTK_ALIGN_START);
+ gtk_widget_set_valign (network_device_label, GTK_ALIGN_CENTER);
+#else
+ gtk_misc_set_alignment(GTK_MISC(network_device_label), 0.0f, 0.5f);
+#endif
+ gtk_size_group_add_widget(category_label_size_group, network_device_label);
+ gtk_box_pack_start(GTK_BOX (network_device_hbox), network_device_label, FALSE, FALSE, 0);
+
+ applet->network_device_combo = gtk_combo_box_text_new();
+ gtk_label_set_mnemonic_widget(GTK_LABEL(network_device_label), applet->network_device_combo);
+ gtk_box_pack_start (GTK_BOX (network_device_hbox), applet->network_device_combo, TRUE, TRUE, 0);
+
+ /* Default means device with default route set */
+ gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(applet->network_device_combo), _("Default"));
+ ptr = devices = get_available_devices();
+ for (i = 0; ptr; ptr = g_list_next(ptr)) {
+ gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(applet->network_device_combo), ptr->data);
+ if (g_str_equal(ptr->data, applet->devinfo.name)) active = (i + 1);
+ ++i;
+ }
+ if (active < 0 || applet->auto_change_device) {
+ active = 0;
+ }
+ gtk_combo_box_set_active(GTK_COMBO_BOX(applet->network_device_combo), active);
+ g_object_set_data_full(G_OBJECT(applet->network_device_combo), "devices", devices, (GDestroyNotify)free_devices_list);
+
+ show_sum_checkbutton = gtk_check_button_new_with_mnemonic(_("Show _sum instead of in & out"));
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(show_sum_checkbutton), applet->show_sum);
+ gtk_box_pack_start(GTK_BOX(controls_vbox), show_sum_checkbutton, FALSE, FALSE, 0);
+
+ show_bits_checkbutton = gtk_check_button_new_with_mnemonic(_("Show _bits instead of bytes"));
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(show_bits_checkbutton), applet->show_bits);
+ gtk_box_pack_start(GTK_BOX(controls_vbox), show_bits_checkbutton, FALSE, FALSE, 0);
+
+ short_unit_checkbutton = gtk_check_button_new_with_mnemonic(_("Shorten _unit legend"));
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(short_unit_checkbutton), applet->short_unit);
+ gtk_box_pack_start(GTK_BOX(controls_vbox), short_unit_checkbutton, FALSE, FALSE, 0);
+
+ change_icon_checkbutton = gtk_check_button_new_with_mnemonic(_("_Change icon according to the selected device"));
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(change_icon_checkbutton), applet->change_icon);
+ gtk_box_pack_start(GTK_BOX(controls_vbox), change_icon_checkbutton, FALSE, FALSE, 0);
+
+ show_icon_checkbutton = gtk_check_button_new_with_mnemonic(_("Show _icon"));
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(show_icon_checkbutton), applet->show_icon);
+ gtk_box_pack_start(GTK_BOX(controls_vbox), show_icon_checkbutton, FALSE, FALSE, 0);
+
+ show_quality_icon_checkbutton = gtk_check_button_new_with_mnemonic(_("Show signal _quality icon for wireless devices"));
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(show_quality_icon_checkbutton), applet->show_quality_icon);
+ gtk_box_pack_start(GTK_BOX(controls_vbox), show_quality_icon_checkbutton, FALSE, FALSE, 0);
+
+ g_signal_connect(G_OBJECT (applet->network_device_combo), "changed",
+ G_CALLBACK(device_change_cb), (gpointer)applet);
+
+ g_signal_connect(G_OBJECT (show_sum_checkbutton), "toggled",
+ G_CALLBACK(showsum_change_cb), (gpointer)applet);
+
+ g_signal_connect(G_OBJECT (show_bits_checkbutton), "toggled",
+ G_CALLBACK(showbits_change_cb), (gpointer)applet);
+
+ g_signal_connect(G_OBJECT (short_unit_checkbutton), "toggled",
+ G_CALLBACK(shortunit_change_cb), (gpointer)applet);
+
+ g_signal_connect(G_OBJECT (show_icon_checkbutton), "toggled",
+ G_CALLBACK(showicon_change_cb), (gpointer)applet);
+
+ g_signal_connect(G_OBJECT (show_quality_icon_checkbutton), "toggled",
+ G_CALLBACK(showqualityicon_change_cb), (gpointer)applet);
+
+ g_signal_connect(G_OBJECT (change_icon_checkbutton), "toggled",
+ G_CALLBACK(changeicon_change_cb), (gpointer)applet);
+
+ g_signal_connect(G_OBJECT (applet->settings), "response",
+ G_CALLBACK(pref_response_cb), (gpointer)applet);
+
+ gtk_container_add(GTK_CONTAINER(gtk_dialog_get_content_area (applet->settings)), vbox);
+
+ gtk_widget_show_all(GTK_WIDGET(applet->settings));
+}
+
+static gboolean
+#if GTK_CHECK_VERSION (3, 0, 0)
+da_draw(GtkWidget *widget, cairo_t *cr, gpointer data)
+#else
+da_expose_event(GtkWidget *widget, GdkEventExpose *event, gpointer data)
+#endif
+{
+ MateNetspeedApplet *applet = (MateNetspeedApplet*)data;
+
+#if !GTK_CHECK_VERSION (3, 0, 0)
+ cairo_t *cr;
+ cr = gdk_cairo_create (event->window);
+ gdk_cairo_region (cr, event->region);
+ cairo_clip (cr);
+#endif
+ redraw_graph(applet, cr);
+#if !GTK_CHECK_VERSION (3, 0, 0)
+ cairo_destroy (cr);
+#endif
+
+ return FALSE;
+}
+
+static void
+incolor_changed_cb (MateColorButton *cb, gpointer data)
+{
+ MateNetspeedApplet *applet = (MateNetspeedApplet*)data;
+ gchar *color;
+ GdkColor clr;
+
+ mate_color_button_get_color (cb, &clr);
+ applet->in_color = clr;
+
+ color = g_strdup_printf ("#%04x%04x%04x", clr.red, clr.green, clr.blue);
+ g_settings_set_string (applet->gsettings, "in-color", color);
+ g_free (color);
+}
+
+static void
+outcolor_changed_cb (MateColorButton *cb, gpointer data)
+{
+ MateNetspeedApplet *applet = (MateNetspeedApplet*)data;
+ gchar *color;
+ GdkColor clr;
+
+ mate_color_button_get_color (cb, &clr);
+ applet->out_color = clr;
+
+ color = g_strdup_printf ("#%04x%04x%04x", clr.red, clr.green, clr.blue);
+ g_settings_set_string (applet->gsettings, "out-color", color);
+ g_free (color);
+}
+
+/* Handle info dialog response event
+ */
+static void
+info_response_cb (GtkDialog *dialog, gint id, MateNetspeedApplet *applet)
+{
+
+ if(id == GTK_RESPONSE_HELP){
+ display_help (GTK_WIDGET (dialog), "netspeed_applet-details");
+ return;
+ }
+
+ gtk_widget_destroy(GTK_WIDGET(applet->details));
+
+ applet->details = NULL;
+ applet->inbytes_text = NULL;
+ applet->outbytes_text = NULL;
+ applet->drawingarea = NULL;
+ applet->signalbar = NULL;
+}
+
+/* Creates the details dialog
+ */
+static void
+showinfo_cb(GtkAction *action, gpointer data)
+{
+ MateNetspeedApplet *applet = (MateNetspeedApplet*)data;
+ GtkWidget *box, *hbox;
+ GtkWidget *table, *da_frame;
+ GtkWidget *ip_label, *netmask_label;
+ GtkWidget *hwaddr_label, *ptpip_label;
+ GtkWidget *ip_text, *netmask_text;
+ GtkWidget *hwaddr_text, *ptpip_text;
+ GtkWidget *inbytes_label, *outbytes_label;
+ GtkWidget *incolor_sel, *incolor_label;
+ GtkWidget *outcolor_sel, *outcolor_label;
+ char *title;
+
+ g_assert(applet);
+
+ if (applet->details)
+ {
+ gtk_window_present(GTK_WINDOW(applet->details));
+ return;
+ }
+
+ title = g_strdup_printf(_("Device Details for %s"), applet->devinfo.name);
+ applet->details = GTK_DIALOG(gtk_dialog_new_with_buttons(title,
+ NULL,
+ GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_STOCK_CLOSE, GTK_RESPONSE_ACCEPT,
+ GTK_STOCK_HELP, GTK_RESPONSE_HELP,
+ NULL));
+ g_free(title);
+
+ gtk_dialog_set_default_response(GTK_DIALOG(applet->details), GTK_RESPONSE_CLOSE);
+
+ box = gtk_vbox_new(FALSE, 10);
+ gtk_container_set_border_width(GTK_CONTAINER(box), 12);
+
+ table = gtk_table_new(4, 4, FALSE);
+ gtk_table_set_row_spacings(GTK_TABLE(table), 10);
+ gtk_table_set_col_spacings(GTK_TABLE(table), 15);
+
+ da_frame = gtk_frame_new(NULL);
+ gtk_frame_set_shadow_type(GTK_FRAME(da_frame), GTK_SHADOW_NONE);
+ applet->drawingarea = GTK_DRAWING_AREA(gtk_drawing_area_new());
+ gtk_widget_set_size_request(GTK_WIDGET(applet->drawingarea), -1, 180);
+ gtk_container_add(GTK_CONTAINER(da_frame), GTK_WIDGET(applet->drawingarea));
+
+ hbox = gtk_hbox_new(FALSE, 5);
+ incolor_label = gtk_label_new_with_mnemonic(_("_In graph color"));
+ outcolor_label = gtk_label_new_with_mnemonic(_("_Out graph color"));
+
+ incolor_sel = mate_color_button_new ();
+ outcolor_sel = mate_color_button_new ();
+
+ mate_color_button_set_color (MATE_COLOR_BUTTON (incolor_sel), &applet->in_color);
+ mate_color_button_set_color (MATE_COLOR_BUTTON (outcolor_sel), &applet->out_color);
+
+ gtk_label_set_mnemonic_widget(GTK_LABEL(incolor_label), incolor_sel);
+ gtk_label_set_mnemonic_widget(GTK_LABEL(outcolor_label), outcolor_sel);
+
+ gtk_box_pack_start(GTK_BOX(hbox), incolor_sel, FALSE, FALSE, 0);
+ gtk_box_pack_start(GTK_BOX(hbox), incolor_label, FALSE, FALSE, 0);
+ gtk_box_pack_start(GTK_BOX(hbox), outcolor_sel, FALSE, FALSE, 0);
+ gtk_box_pack_start(GTK_BOX(hbox), outcolor_label, FALSE, FALSE, 0);
+
+ ip_label = gtk_label_new(_("Internet Address:"));
+ netmask_label = gtk_label_new(_("Netmask:"));
+ hwaddr_label = gtk_label_new(_("Hardware Address:"));
+ ptpip_label = gtk_label_new(_("P-t-P Address:"));
+ inbytes_label = gtk_label_new(_("Bytes in:"));
+ outbytes_label = gtk_label_new(_("Bytes out:"));
+
+ ip_text = gtk_label_new(applet->devinfo.ip ? applet->devinfo.ip : _("none"));
+ netmask_text = gtk_label_new(applet->devinfo.netmask ? applet->devinfo.netmask : _("none"));
+ hwaddr_text = gtk_label_new(applet->devinfo.hwaddr ? applet->devinfo.hwaddr : _("none"));
+ ptpip_text = gtk_label_new(applet->devinfo.ptpip ? applet->devinfo.ptpip : _("none"));
+ applet->inbytes_text = gtk_label_new("0 byte");
+ applet->outbytes_text = gtk_label_new("0 byte");
+
+ gtk_label_set_selectable(GTK_LABEL(ip_text), TRUE);
+ gtk_label_set_selectable(GTK_LABEL(netmask_text), TRUE);
+ gtk_label_set_selectable(GTK_LABEL(hwaddr_text), TRUE);
+ gtk_label_set_selectable(GTK_LABEL(ptpip_text), TRUE);
+
+#if GTK_CHECK_VERSION (3, 0, 0)
+ gtk_widget_set_halign (ip_label, GTK_ALIGN_START);
+ gtk_widget_set_valign (ip_label, GTK_ALIGN_CENTER);
+ gtk_widget_set_halign (ip_text, GTK_ALIGN_START);
+ gtk_widget_set_valign (ip_text, GTK_ALIGN_CENTER);
+ gtk_widget_set_halign (netmask_label, GTK_ALIGN_START);
+ gtk_widget_set_valign (netmask_label, GTK_ALIGN_CENTER);
+ gtk_widget_set_halign (netmask_text, GTK_ALIGN_START);
+ gtk_widget_set_valign (netmask_text, GTK_ALIGN_CENTER);
+ gtk_widget_set_halign (hwaddr_label, GTK_ALIGN_START);
+ gtk_widget_set_valign (hwaddr_label, GTK_ALIGN_CENTER);
+ gtk_widget_set_halign (hwaddr_text, GTK_ALIGN_START);
+ gtk_widget_set_valign (hwaddr_text, GTK_ALIGN_CENTER);
+ gtk_widget_set_halign (ptpip_label, GTK_ALIGN_START);
+ gtk_widget_set_valign (ptpip_label, GTK_ALIGN_CENTER);
+ gtk_widget_set_halign (ptpip_text, GTK_ALIGN_START);
+ gtk_widget_set_valign (ptpip_text, GTK_ALIGN_CENTER);
+ gtk_widget_set_halign (inbytes_label, GTK_ALIGN_START);
+ gtk_widget_set_valign (inbytes_label, GTK_ALIGN_CENTER);
+ gtk_widget_set_halign (applet->inbytes_text, GTK_ALIGN_START);
+ gtk_widget_set_valign (applet->inbytes_text, GTK_ALIGN_CENTER);
+ gtk_widget_set_halign (inbytes_label, GTK_ALIGN_START);
+ gtk_widget_set_valign (inbytes_label, GTK_ALIGN_CENTER);
+ gtk_widget_set_halign (applet->outbytes_text, GTK_ALIGN_START);
+ gtk_widget_set_valign (applet->outbytes_text, GTK_ALIGN_CENTER);
+ gtk_widget_set_halign (outbytes_label, GTK_ALIGN_START);
+ gtk_widget_set_valign (outbytes_label, GTK_ALIGN_CENTER);
+#else
+ gtk_misc_set_alignment(GTK_MISC(ip_label), 0.0f, 0.5f);
+ gtk_misc_set_alignment(GTK_MISC(ip_text), 0.0f, 0.5f);
+ gtk_misc_set_alignment(GTK_MISC(netmask_label), 0.0f, 0.5f);
+ gtk_misc_set_alignment(GTK_MISC(netmask_text), 0.0f, 0.5f);
+ gtk_misc_set_alignment(GTK_MISC(hwaddr_label), 0.0f, 0.5f);
+ gtk_misc_set_alignment(GTK_MISC(hwaddr_text), 0.0f, 0.5f);
+ gtk_misc_set_alignment(GTK_MISC(ptpip_label), 0.0f, 0.5f);
+ gtk_misc_set_alignment(GTK_MISC(ptpip_text), 0.0f, 0.5f);
+ gtk_misc_set_alignment(GTK_MISC(inbytes_label), 0.0f, 0.5f);
+ gtk_misc_set_alignment(GTK_MISC(applet->inbytes_text), 0.0f, 0.5f);
+ gtk_misc_set_alignment(GTK_MISC(outbytes_label), 0.0f, 0.5f);
+ gtk_misc_set_alignment(GTK_MISC(applet->outbytes_text), 0.0f, 0.5f);
+#endif
+
+ gtk_table_attach_defaults(GTK_TABLE(table), ip_label, 0, 1, 0, 1);
+ gtk_table_attach_defaults(GTK_TABLE(table), ip_text, 1, 2, 0, 1);
+ gtk_table_attach_defaults(GTK_TABLE(table), netmask_label, 2, 3, 0, 1);
+ gtk_table_attach_defaults(GTK_TABLE(table), netmask_text, 3, 4, 0, 1);
+ gtk_table_attach_defaults(GTK_TABLE(table), hwaddr_label, 0, 1, 1, 2);
+ gtk_table_attach_defaults(GTK_TABLE(table), hwaddr_text, 1, 2, 1, 2);
+ gtk_table_attach_defaults(GTK_TABLE(table), ptpip_label, 2, 3, 1, 2);
+ gtk_table_attach_defaults(GTK_TABLE(table), ptpip_text, 3, 4, 1, 2);
+ gtk_table_attach_defaults(GTK_TABLE(table), inbytes_label, 0, 1, 2, 3);
+ gtk_table_attach_defaults(GTK_TABLE(table), applet->inbytes_text, 1, 2, 2, 3);
+ gtk_table_attach_defaults(GTK_TABLE(table), outbytes_label, 2, 3, 2, 3);
+ gtk_table_attach_defaults(GTK_TABLE(table), applet->outbytes_text, 3, 4, 2, 3);
+
+ /* check if we got an ipv6 address */
+ if (applet->devinfo.ipv6 && (strlen (applet->devinfo.ipv6) > 2)) {
+ GtkWidget *ipv6_label, *ipv6_text;
+
+ ipv6_label = gtk_label_new (_("IPV6 Address:"));
+ ipv6_text = gtk_label_new (applet->devinfo.ipv6);
+
+ gtk_label_set_selectable (GTK_LABEL (ipv6_text), TRUE);
+
+#if GTK_CHECK_VERSION (3, 0, 0)
+ gtk_widget_set_halign (ipv6_label, GTK_ALIGN_START);
+ gtk_widget_set_valign (ipv6_label, GTK_ALIGN_CENTER);
+ gtk_widget_set_halign (ipv6_text, GTK_ALIGN_START);
+ gtk_widget_set_valign (ipv6_text, GTK_ALIGN_CENTER);
+#else
+ gtk_misc_set_alignment (GTK_MISC (ipv6_label), 0.0f, 0.5f);
+ gtk_misc_set_alignment (GTK_MISC (ipv6_text), 0.0f, 0.5f);
+#endif
+
+ gtk_table_attach_defaults (GTK_TABLE (table), ipv6_label, 0, 1, 3, 4);
+ gtk_table_attach_defaults (GTK_TABLE (table), ipv6_text, 1, 2, 3, 4);
+ }
+
+ if (applet->devinfo.type == DEV_WIRELESS) {
+ GtkWidget *signal_label;
+ GtkWidget *essid_label;
+ GtkWidget *essid_text;
+ float quality;
+ char *text;
+
+ /* _maybe_ we can add the encrypted icon between the essid and the signal bar. */
+
+ applet->signalbar = gtk_progress_bar_new ();
+
+ quality = applet->devinfo.qual / 100.0f;
+ if (quality > 1.0)
+ quality = 1.0;
+
+ text = g_strdup_printf ("%d %%", applet->devinfo.qual);
+ gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (applet->signalbar), quality);
+ gtk_progress_bar_set_text (GTK_PROGRESS_BAR (applet->signalbar), text);
+ g_free(text);
+
+ signal_label = gtk_label_new (_("Signal Strength:"));
+ essid_label = gtk_label_new (_("ESSID:"));
+ essid_text = gtk_label_new (applet->devinfo.essid);
+
+#if GTK_CHECK_VERSION (3, 0, 0)
+ gtk_widget_set_halign (signal_label, GTK_ALIGN_START);
+ gtk_widget_set_valign (signal_label, GTK_ALIGN_CENTER);
+ gtk_widget_set_halign (essid_label, GTK_ALIGN_START);
+ gtk_widget_set_valign (essid_label, GTK_ALIGN_CENTER);
+ gtk_widget_set_halign (essid_text, GTK_ALIGN_START);
+ gtk_widget_set_valign (essid_text, GTK_ALIGN_CENTER);
+#else
+ gtk_misc_set_alignment (GTK_MISC (signal_label), 0.0f, 0.5f);
+ gtk_misc_set_alignment (GTK_MISC (essid_label), 0.0f, 0.5f);
+ gtk_misc_set_alignment (GTK_MISC (essid_text), 0.0f, 0.5f);
+#endif
+
+ gtk_label_set_selectable (GTK_LABEL (essid_text), TRUE);
+
+ gtk_table_attach_defaults (GTK_TABLE (table), signal_label, 2, 3, 4, 5);
+ gtk_table_attach_defaults (GTK_TABLE (table), GTK_WIDGET (applet->signalbar), 3, 4, 4, 5);
+ gtk_table_attach_defaults (GTK_TABLE (table), essid_label, 0, 3, 4, 5);
+ gtk_table_attach_defaults (GTK_TABLE (table), essid_text, 1, 4, 4, 5);
+ }
+
+#if GTK_CHECK_VERSION (3, 0, 0)
+ g_signal_connect(G_OBJECT(applet->drawingarea), "draw",
+ G_CALLBACK(da_draw),
+ (gpointer)applet);
+#else
+ g_signal_connect(G_OBJECT(applet->drawingarea), "expose_event",
+ G_CALLBACK(da_expose_event),
+ (gpointer)applet);
+#endif
+
+ g_signal_connect(G_OBJECT(incolor_sel), "color_set",
+ G_CALLBACK(incolor_changed_cb),
+ (gpointer)applet);
+
+ g_signal_connect(G_OBJECT(outcolor_sel), "color_set",
+ G_CALLBACK(outcolor_changed_cb),
+ (gpointer)applet);
+
+ g_signal_connect(G_OBJECT(applet->details), "response",
+ G_CALLBACK(info_response_cb), (gpointer)applet);
+
+ gtk_box_pack_start(GTK_BOX(box), da_frame, TRUE, TRUE, 0);
+ gtk_box_pack_start(GTK_BOX(box), hbox, FALSE, FALSE, 0);
+ gtk_box_pack_start(GTK_BOX(box), table, FALSE, FALSE, 0);
+
+ gtk_container_add(GTK_CONTAINER(gtk_dialog_get_content_area (applet->details)), box);
+ gtk_widget_show_all(GTK_WIDGET(applet->details));
+}
+
+static const GtkActionEntry mate_netspeed_applet_menu_actions [] = {
+ { "MateNetspeedAppletDetails", GTK_STOCK_INFO, N_("Device _Details"),
+ NULL, NULL, G_CALLBACK (showinfo_cb) },
+ { "MateNetspeedAppletProperties", GTK_STOCK_PROPERTIES, N_("Preferences..."),
+ NULL, NULL, G_CALLBACK (settings_cb) },
+ { "MateNetspeedAppletHelp", GTK_STOCK_HELP, N_("Help"),
+ NULL, NULL, G_CALLBACK (help_cb) },
+ { "MateNetspeedAppletAbout", GTK_STOCK_ABOUT, N_("About..."),
+ NULL, NULL, G_CALLBACK (about_cb) }
+};
+
+/* Block the size_request signal emit by the label if the
+ * text changes. Only if the label wants to grow, we give
+ * permission. This will eventually result in the maximal
+ * size of the applet and prevents the icons and labels from
+ * "jumping around" in the mate_panel which looks uggly
+ */
+static void
+label_size_request_cb(GtkWidget *widget, GtkRequisition *requisition, MateNetspeedApplet *applet)
+{
+ if (applet->labels_dont_shrink) {
+ if (requisition->width <= applet->width)
+ requisition->width = applet->width;
+ else
+ applet->width = requisition->width;
+ }
+}
+
+static gboolean
+applet_button_press(GtkWidget *widget, GdkEventButton *event, MateNetspeedApplet *applet)
+{
+ if (event->button == 1)
+ {
+ GError *error = NULL;
+
+ if (applet->connect_dialog)
+ {
+ gtk_window_present(GTK_WINDOW(applet->connect_dialog));
+ return FALSE;
+ }
+
+ if (applet->up_cmd && applet->down_cmd)
+ {
+ const char *question;
+ int response;
+
+ if (applet->devinfo.up)
+ {
+ question = _("Do you want to disconnect %s now?");
+ }
+ else
+ {
+ question = _("Do you want to connect %s now?");
+ }
+
+ applet->connect_dialog = gtk_message_dialog_new(NULL,
+ GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_QUESTION, GTK_BUTTONS_YES_NO,
+ question,
+ applet->devinfo.name);
+ response = gtk_dialog_run(GTK_DIALOG(applet->connect_dialog));
+ gtk_widget_destroy (applet->connect_dialog);
+ applet->connect_dialog = NULL;
+
+ if (response == GTK_RESPONSE_YES)
+ {
+ GtkWidget *dialog;
+ char *command;
+
+ command = g_strdup_printf("%s %s",
+ applet->devinfo.up ? applet->down_cmd : applet->up_cmd,
+ applet->devinfo.name);
+
+ if (!g_spawn_command_line_async(command, &error))
+ {
+
+ dialog = gtk_message_dialog_new_with_markup(NULL,
+ GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_ERROR, GTK_BUTTONS_OK,
+ _("<b>Running command %s failed</b>\n%s"),
+ command,
+ error->message);
+ gtk_dialog_run (GTK_DIALOG (dialog));
+ gtk_widget_destroy (dialog);
+ g_error_free (error);
+ }
+ g_free(command);
+ }
+ }
+ }
+
+ return FALSE;
+}
+
+/* Frees the applet and all the data it contains
+ * Removes the timeout_cb
+ */
+static void
+applet_destroy(MatePanelApplet *applet_widget, MateNetspeedApplet *applet)
+{
+ GtkIconTheme *icon_theme;
+
+ g_assert(applet);
+
+ icon_theme = gtk_icon_theme_get_default();
+ g_object_disconnect(G_OBJECT(icon_theme), "changed",
+ G_CALLBACK(icon_theme_changed_cb), (gpointer)applet,
+ NULL);
+
+ g_source_remove(applet->timeout_id);
+ applet->timeout_id = 0;
+
+ if (applet->up_cmd)
+ g_free(applet->up_cmd);
+ if (applet->down_cmd)
+ g_free(applet->down_cmd);
+ if (applet->gsettings)
+ g_object_unref (applet->gsettings);
+
+ /* Should never be NULL */
+ free_device_info(&applet->devinfo);
+ g_free(applet);
+ return;
+}
+
+
+
+static void
+update_tooltip(MateNetspeedApplet* applet)
+{
+ GString* tooltip;
+
+ if (!applet->show_tooltip)
+ return;
+
+ tooltip = g_string_new("");
+
+ if (!applet->devinfo.running)
+ g_string_printf(tooltip, _("%s is down"), applet->devinfo.name);
+ else {
+ if (applet->show_sum) {
+ g_string_printf(
+ tooltip,
+ _("%s: %s\nin: %s out: %s"),
+ applet->devinfo.name,
+ applet->devinfo.ip ? applet->devinfo.ip : _("has no ip"),
+ applet->devinfo.rx_rate,
+ applet->devinfo.tx_rate
+ );
+ } else {
+ g_string_printf(
+ tooltip,
+ _("%s: %s\nsum: %s"),
+ applet->devinfo.name,
+ applet->devinfo.ip ? applet->devinfo.ip : _("has no ip"),
+ applet->devinfo.sum_rate
+ );
+ }
+ if (applet->devinfo.type == DEV_WIRELESS)
+ g_string_append_printf(
+ tooltip,
+ _("\nESSID: %s\nStrength: %d %%"),
+ applet->devinfo.essid ? applet->devinfo.essid : _("unknown"),
+ applet->devinfo.qual
+ );
+
+ }
+
+ gtk_widget_set_tooltip_text(GTK_WIDGET(applet->applet), tooltip->str);
+ gtk_widget_trigger_tooltip_query(GTK_WIDGET(applet->applet));
+ g_string_free(tooltip, TRUE);
+}
+
+
+static gboolean
+mate_netspeed_enter_cb(GtkWidget *widget, GdkEventCrossing *event, gpointer data)
+{
+ MateNetspeedApplet *applet = data;
+
+ applet->show_tooltip = TRUE;
+ update_tooltip(applet);
+
+ return TRUE;
+}
+
+static gboolean
+mate_netspeed_leave_cb(GtkWidget *widget, GdkEventCrossing *event, gpointer data)
+{
+ MateNetspeedApplet *applet = data;
+
+ applet->show_tooltip = FALSE;
+ return TRUE;
+}
+
+/* The "main" function of the applet
+ */
+static gboolean
+mate_netspeed_applet_factory(MatePanelApplet *applet_widget, const gchar *iid, gpointer data)
+{
+ MateNetspeedApplet *applet;
+ int i;
+ char* menu_string;
+ GtkIconTheme *icon_theme;
+ GtkWidget *spacer, *spacer_box;
+
+ /* Have our background automatically painted. */
+ mate_panel_applet_set_background_widget(MATE_PANEL_APPLET(applet_widget),
+ GTK_WIDGET(applet_widget));
+
+ if (strcmp (iid, "NetspeedApplet"))
+ return FALSE;
+
+ glibtop_init();
+ g_set_application_name (_("Mate Netspeed"));
+
+ icon_theme = gtk_icon_theme_get_default();
+
+ /* Alloc the applet. The "NULL-setting" is really redudant
+ * but aren't we paranoid?
+ */
+ applet = g_malloc0(sizeof(MateNetspeedApplet));
+ applet->applet = applet_widget;
+ memset(&applet->devinfo, 0, sizeof(DevInfo));
+ applet->refresh_time = 1000.0;
+ applet->show_sum = FALSE;
+ applet->show_bits = FALSE;
+ applet->short_unit = FALSE;
+ applet->show_icon = TRUE;
+ applet->show_quality_icon = TRUE;
+ applet->change_icon = TRUE;
+ applet->auto_change_device = TRUE;
+
+ /* Set the default colors of the graph
+ */
+ applet->in_color.red = 0xdf00;
+ applet->in_color.green = 0x2800;
+ applet->in_color.blue = 0x4700;
+ applet->out_color.red = 0x3700;
+ applet->out_color.green = 0x2800;
+ applet->out_color.blue = 0xdf00;
+
+ for (i = 0; i < GRAPH_VALUES; i++)
+ {
+ applet->in_graph[i] = -1;
+ applet->out_graph[i] = -1;
+ }
+
+ applet->gsettings = mate_panel_applet_settings_new (applet_widget, "org.mate.panel.applet.netspeed");
+
+ /* Get stored settings from gsettings
+ */
+ char *tmp = NULL;
+
+ applet->show_sum = g_settings_get_boolean (applet->gsettings, "show-sum");
+ applet->show_bits = g_settings_get_boolean (applet->gsettings, "show-bits");
+ applet->short_unit = g_settings_get_boolean (applet->gsettings, "short-unit");
+ applet->show_icon = g_settings_get_boolean (applet->gsettings, "show-icon");
+ applet->show_quality_icon = g_settings_get_boolean (applet->gsettings, "show-quality-icon");
+ applet->change_icon = g_settings_get_boolean (applet->gsettings, "change-icon");
+ applet->auto_change_device = g_settings_get_boolean (applet->gsettings, "auto-change-device");
+
+ tmp = g_settings_get_string (applet->gsettings, "device");
+ if (tmp && strcmp(tmp, ""))
+ {
+ get_device_info(tmp, &applet->devinfo);
+ g_free(tmp);
+ }
+ tmp = g_settings_get_string (applet->gsettings, "up-command");
+ if (tmp && strcmp(tmp, ""))
+ {
+ applet->up_cmd = g_strdup(tmp);
+ g_free(tmp);
+ }
+ tmp = g_settings_get_string (applet->gsettings, "down-command");
+ if (tmp && strcmp(tmp, ""))
+ {
+ applet->down_cmd = g_strdup(tmp);
+ g_free(tmp);
+ }
+
+ tmp = g_settings_get_string (applet->gsettings, "in-color");
+ if (tmp)
+ {
+ gdk_color_parse(tmp, &applet->in_color);
+ g_free(tmp);
+ }
+ tmp = g_settings_get_string (applet->gsettings, "out-color");
+ if (tmp)
+ {
+ gdk_color_parse(tmp, &applet->out_color);
+ g_free(tmp);
+ }
+
+ if (!applet->devinfo.name) {
+ GList *ptr, *devices = get_available_devices();
+ ptr = devices;
+ while (ptr) {
+ if (!g_str_equal(ptr->data, "lo")) {
+ get_device_info(ptr->data, &applet->devinfo);
+ break;
+ }
+ ptr = g_list_next(ptr);
+ }
+ free_devices_list(devices);
+ }
+ if (!applet->devinfo.name)
+ get_device_info("lo", &applet->devinfo);
+ applet->device_has_changed = TRUE;
+
+ applet->in_label = gtk_label_new("");
+ applet->out_label = gtk_label_new("");
+ applet->sum_label = gtk_label_new("");
+
+ applet->in_pix = gtk_image_new();
+ applet->out_pix = gtk_image_new();
+ applet->dev_pix = gtk_image_new();
+ applet->qual_pix = gtk_image_new();
+
+ applet->pix_box = gtk_hbox_new(FALSE, 0);
+ spacer = gtk_label_new("");
+ gtk_box_pack_start(GTK_BOX(applet->pix_box), spacer, TRUE, TRUE, 0);
+ spacer = gtk_label_new("");
+ gtk_box_pack_end(GTK_BOX(applet->pix_box), spacer, TRUE, TRUE, 0);
+
+ spacer_box = gtk_hbox_new(FALSE, 2);
+ gtk_box_pack_start(GTK_BOX(applet->pix_box), spacer_box, FALSE, FALSE, 0);
+ gtk_box_pack_start(GTK_BOX(spacer_box), applet->qual_pix, FALSE, FALSE, 0);
+ gtk_box_pack_start(GTK_BOX(spacer_box), applet->dev_pix, FALSE, FALSE, 0);
+
+ init_quality_pixbufs(applet);
+
+ applet_change_size_or_orient(applet_widget, -1, (gpointer)applet);
+ gtk_widget_show_all(GTK_WIDGET(applet_widget));
+ update_applet(applet);
+
+ mate_panel_applet_set_flags(applet_widget, MATE_PANEL_APPLET_EXPAND_MINOR);
+
+ applet->timeout_id = g_timeout_add(applet->refresh_time,
+ (GSourceFunc)timeout_function,
+ (gpointer)applet);
+
+ g_signal_connect(G_OBJECT(applet_widget), "change_size",
+ G_CALLBACK(applet_change_size_or_orient),
+ (gpointer)applet);
+
+ g_signal_connect(G_OBJECT(icon_theme), "changed",
+ G_CALLBACK(icon_theme_changed_cb),
+ (gpointer)applet);
+
+ g_signal_connect(G_OBJECT(applet_widget), "change_orient",
+ G_CALLBACK(applet_change_size_or_orient),
+ (gpointer)applet);
+
+ g_signal_connect(G_OBJECT(applet->in_label), "size_request",
+ G_CALLBACK(label_size_request_cb),
+ (gpointer)applet);
+
+ g_signal_connect(G_OBJECT(applet->out_label), "size_request",
+ G_CALLBACK(label_size_request_cb),
+ (gpointer)applet);
+
+ g_signal_connect(G_OBJECT(applet->sum_label), "size_request",
+ G_CALLBACK(label_size_request_cb),
+ (gpointer)applet);
+
+ g_signal_connect(G_OBJECT(applet_widget), "destroy",
+ G_CALLBACK(applet_destroy),
+ (gpointer)applet);
+
+ g_signal_connect(G_OBJECT(applet_widget), "button-press-event",
+ G_CALLBACK(applet_button_press),
+ (gpointer)applet);
+
+ g_signal_connect(G_OBJECT(applet_widget), "leave_notify_event",
+ G_CALLBACK(mate_netspeed_leave_cb),
+ (gpointer)applet);
+
+ g_signal_connect(G_OBJECT(applet_widget), "enter_notify_event",
+ G_CALLBACK(mate_netspeed_enter_cb),
+ (gpointer)applet);
+
+ GtkActionGroup *action_group;
+ gchar *ui_path;
+ action_group = gtk_action_group_new ("Netspeed Applet Actions");
+ gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
+ gtk_action_group_add_actions (action_group,
+ mate_netspeed_applet_menu_actions,
+ G_N_ELEMENTS (mate_netspeed_applet_menu_actions),
+ applet);
+ ui_path = g_build_filename (NETSPEED_MENU_UI_DIR, "netspeed-menu.xml", NULL);
+ mate_panel_applet_setup_menu_from_file (MATE_PANEL_APPLET (applet->applet), ui_path, action_group);
+ g_free (ui_path);
+ g_object_unref (action_group);
+
+ return TRUE;
+}
+
+MATE_PANEL_APPLET_OUT_PROCESS_FACTORY("NetspeedAppletFactory",
+ PANEL_TYPE_APPLET,
+ "NetspeedApplet",
+ mate_netspeed_applet_factory,
+ NULL)