Typo
[dhcpcd-ui] / menu.c
1 /*
2  * dhcpcd-gtk
3  * Copyright 2009 Roy Marples <roy@marples.name>
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  */
26
27 #include "dhcpcd-gtk.h"
28 #include "menu.h"
29 #include "prefs.h"
30 #include "wpa.h"
31
32 static const char *copyright = "Copyright (c) 2009 Roy Marples";
33 static const char *authors[] = { "Roy Marples <roy@marples.name>", NULL };
34
35 static void
36 on_pref(_unused GtkMenuItem *item, _unused gpointer data)
37 {
38         dhcpcd_prefs_show();
39 }
40
41
42 static void
43 on_quit(_unused GtkMenuItem *item, _unused gpointer data)
44 {
45         gtk_main_quit();
46 }
47
48 static void
49 on_help(_unused GtkMenuItem *item, _unused gpointer data)
50 {
51 }
52
53 static void
54 url_show(GtkAboutDialog *dialog, const char *url)
55 {
56         GdkScreen *screen;
57
58         screen = gtk_widget_get_screen(GTK_WIDGET(dialog));
59         gtk_show_uri(screen, url, GDK_CURRENT_TIME, NULL);
60 }
61
62 static void
63 email_hook(GtkAboutDialog *dialog, const char *url, _unused gpointer p)
64 {
65         char *address;
66
67         address = g_strdup_printf("mailto:%s", url);
68         url_show(dialog, address);
69         g_free(address);
70 }
71
72 static void
73 url_hook(GtkAboutDialog *dialog, const char *url, _unused gpointer p)
74 {
75         url_show(dialog, url);
76 }
77
78 static void
79 ssid_hook(_unused GtkMenuItem *item, gpointer data)
80 {
81         wpa_configure((const struct if_ap *)data);
82 }
83
84 static void
85 on_about(_unused GtkMenuItem *item, _unused gpointer data)
86 {
87         gtk_window_set_default_icon_name(GTK_STOCK_NETWORK);
88         gtk_about_dialog_set_email_hook(email_hook, NULL, NULL);
89         gtk_about_dialog_set_url_hook(url_hook, NULL, NULL);
90         gtk_show_about_dialog(NULL,
91             "version", VERSION,
92             "copyright", copyright,
93             "website-label", "dhcpcd Website",
94             "website", "http://roy.marples.name/projects/dhcpcd",
95             "authors", authors,
96             "logo-icon-name", GTK_STOCK_NETWORK,
97             NULL);
98 }
99
100 static void
101 add_scan_results(GtkMenu *menu, const struct if_msg *ifm)
102 {
103         GSList *gl;
104         const struct if_ap *ifa;
105         GtkWidget *item, *image, *box, *label, *bar;
106         double perc;
107         int strength;
108         const char *icon;
109         char *tip;
110
111         for (gl = ifm->scan_results; gl; gl = gl->next) {
112                 ifa = (const struct if_ap *)gl->data;
113                 item = gtk_check_menu_item_new();
114                 gtk_check_menu_item_set_draw_as_radio(GTK_CHECK_MENU_ITEM(item), TRUE); 
115                 box = gtk_hbox_new(FALSE, 6);
116                 gtk_container_add(GTK_CONTAINER(item), box); 
117                 label = gtk_label_new(ifa->ssid);
118                 gtk_box_pack_start(GTK_BOX(box), label, TRUE, TRUE, 0);
119
120                 if (g_strcmp0(ifm->ssid, ifa->ssid) == 0)
121                         gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item), TRUE);
122                 if (ifa->flags == NULL)
123                         icon = "network-wireless";
124                 else
125                         icon = "network-wireless-encrypted";
126                 image = gtk_image_new_from_icon_name(icon,
127                     GTK_ICON_SIZE_MENU);
128                 gtk_box_pack_start(GTK_BOX(box), image, FALSE, FALSE, 0);
129
130                 bar = gtk_progress_bar_new();
131                 gtk_widget_set_size_request(bar, 100, -1);
132                 gtk_box_pack_end(GTK_BOX(box), bar, FALSE, TRUE, 0);
133                 strength = CLAMP(ifa->quality, 0, 100);
134                 perc = strength / 100.0;
135                 gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(bar), perc);
136
137                 tip = g_strconcat(ifa->bssid, " ", ifa->flags, NULL);
138                 gtk_widget_set_tooltip_text(item, tip);
139                 g_free(tip);
140
141                 gtk_widget_show(label);
142                 gtk_widget_show(bar);
143                 gtk_widget_show(image);
144                 gtk_widget_show(box);
145                 g_signal_connect(G_OBJECT(item), "activate",
146                     G_CALLBACK(ssid_hook), gl->data);
147                 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
148         }
149 }
150
151 static void
152 on_activate(GtkStatusIcon *icon, _unused guint button, _unused guint32 atime, _unused gpointer data)
153 {
154         GtkMenu *menu;
155         const struct if_msg *ifm;
156         GSList *l;
157         size_t n, na;
158
159         notify_close();
160
161         n = na =0;
162         for (l = interfaces; l; l = l->next) {
163                 ifm = (const struct if_msg *)l->data;
164                 if (ifm->wireless) {
165                         if (ifm->scan_results != NULL)
166                                 ++na;
167                         if (++n > 1 && na != 0)
168                                 break;
169                 }
170         }
171         if (n == 0 || (n == 1 && na == 0))
172                 return;
173
174         menu = (GtkMenu *)gtk_menu_new();
175
176         for (l = interfaces; l; l = l->next) {
177                 ifm = (const struct if_msg *)l->data;
178                 if (!ifm->wireless)
179                         continue;
180                 if (n == 1) {
181                         add_scan_results(menu, ifm);
182                         break;
183                 }
184 #if 0
185                 item = gtk_image_menu_item_new_with_label(ifm->name);
186                 image = gtk_image_new_from_icon_name("network-wireless",
187                     GTK_ICON_SIZE_MENU);
188                 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item), image);
189
190                 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
191 #endif
192         }
193         gtk_widget_show_all(GTK_WIDGET(menu));
194         gtk_menu_popup(GTK_MENU(menu), NULL, NULL,
195             gtk_status_icon_position_menu, icon,
196             1, gtk_get_current_event_time());
197 }
198
199 static void
200 on_popup(GtkStatusIcon *icon, guint button, guint32 atime, gpointer data)
201 {
202         GtkMenu *menu;
203         GtkWidget *item, *image;
204
205         notify_close();
206
207         menu = (GtkMenu *)gtk_menu_new();
208
209         item = gtk_image_menu_item_new_with_mnemonic(_("_Preferences"));
210         image = gtk_image_new_from_icon_name(GTK_STOCK_PREFERENCES,
211             GTK_ICON_SIZE_MENU);
212         gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item), image);
213         g_signal_connect(G_OBJECT(item), "activate",
214             G_CALLBACK(on_pref), icon);
215         gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
216
217         item = gtk_separator_menu_item_new();
218         gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
219
220         item = gtk_image_menu_item_new_with_mnemonic(_("_Help"));
221         image = gtk_image_new_from_icon_name(GTK_STOCK_HELP,
222             GTK_ICON_SIZE_MENU);
223         gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item), image);
224         g_signal_connect(G_OBJECT(item), "activate",
225             G_CALLBACK(on_help), icon);
226         gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
227
228         item = gtk_image_menu_item_new_with_mnemonic(_("_About"));
229         image = gtk_image_new_from_icon_name(GTK_STOCK_ABOUT,
230             GTK_ICON_SIZE_MENU);
231         gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item), image);
232         g_signal_connect(G_OBJECT(item), "activate",
233             G_CALLBACK(on_about), icon);
234         gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
235
236         item = gtk_image_menu_item_new_with_mnemonic(_("_Quit"));
237         image = gtk_image_new_from_icon_name(GTK_STOCK_QUIT,
238             GTK_ICON_SIZE_MENU);
239         gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item), image);
240         g_signal_connect(G_OBJECT(item), "activate",
241             G_CALLBACK(on_quit), icon);
242         gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
243
244         gtk_widget_show_all(GTK_WIDGET(menu));
245         gtk_menu_popup(GTK_MENU(menu), NULL, NULL,
246             gtk_status_icon_position_menu, data, button, atime);
247         if (button == 0)
248                 gtk_menu_shell_select_first(GTK_MENU_SHELL(menu), FALSE);
249 }
250
251 void
252 menu_init(GtkStatusIcon *icon)
253 {
254         g_signal_connect_object(G_OBJECT(icon), "activate",
255             G_CALLBACK(on_activate), icon, 0);
256         g_signal_connect_object(G_OBJECT(icon), "popup_menu",
257             G_CALLBACK(on_popup), icon, 0);
258 }