Fix wpa setup a little.
[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 "wpa.h"
30
31 static const char *copyright = "Copyright (c) 2009 Roy Marples";
32
33 static const char *authors[] = {
34         "Roy Marples <roy@marples.name>",
35         NULL
36 };
37
38 static void
39 on_quit(_unused GtkMenuItem *item, _unused gpointer data)
40 {
41         gtk_main_quit();
42 }
43
44 static void
45 on_help(_unused GtkMenuItem *item, _unused gpointer data)
46 {
47 }
48
49 static void
50 url_show(GtkAboutDialog *dialog, const char *url)
51 {
52         GdkScreen *screen;
53
54         screen = gtk_widget_get_screen(GTK_WIDGET(dialog));
55         gtk_show_uri(screen, url, GDK_CURRENT_TIME, NULL);
56 }
57
58 static void
59 email_hook(GtkAboutDialog *dialog, const char *url, _unused gpointer p)
60 {
61         char *address;
62
63         address = g_strdup_printf("mailto:%s", url);
64         url_show(dialog, address);
65         g_free(address);
66 }
67
68 static void
69 url_hook(GtkAboutDialog *dialog, const char *url, _unused gpointer p)
70 {
71         url_show(dialog, url);
72 }
73
74 static void
75 ssid_hook(_unused GtkMenuItem *item, gpointer data)
76 {
77         wpa_configure((const struct if_ap *)data);
78 }
79
80 static void
81 on_about(_unused GtkMenuItem *item, _unused gpointer data)
82 {
83         gtk_window_set_default_icon_name(GTK_STOCK_NETWORK);
84         gtk_about_dialog_set_email_hook(email_hook, NULL, NULL);
85         gtk_about_dialog_set_url_hook(url_hook, NULL, NULL);
86         gtk_show_about_dialog(NULL,
87                               "version", VERSION,
88                               "copyright", copyright,
89                               "website-label", "dhcpcd Website",
90                               "website", "http://roy.marples.name/projects/dhcpcd",
91                               "authors", authors,
92                               "logo-icon-name", GTK_STOCK_NETWORK,
93                               NULL);
94 }
95
96 static void
97 add_scan_results(GtkMenu *menu, const struct if_msg *ifm)
98 {
99         GSList *gl;
100         const struct if_ap *ifa;
101         GtkWidget *item, *image, *box, *label, *bar;
102         double perc;
103         int strength;
104         const char *icon;
105
106         for (gl = ifm->scan_results; gl; gl = gl->next) {
107                 ifa = (const struct if_ap *)gl->data;
108                 item = gtk_check_menu_item_new();
109                 gtk_check_menu_item_set_draw_as_radio(GTK_CHECK_MENU_ITEM(item), TRUE); 
110                 box = gtk_hbox_new(FALSE, 6);
111                 gtk_container_add(GTK_CONTAINER(item), box); 
112                 label = gtk_label_new(ifa->ssid);
113                 gtk_box_pack_start(GTK_BOX(box), label, TRUE, TRUE, 0);
114
115                 if (g_strcmp0(ifm->ssid, ifa->ssid) == 0)
116                         gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item), TRUE);
117                 if (ifa->flags == NULL)
118                         icon = "network-wireless";
119                 else
120                         icon = "network-wireless-encrypted";
121                 image = gtk_image_new_from_icon_name(icon,
122                                                      GTK_ICON_SIZE_MENU);
123                 gtk_box_pack_start(GTK_BOX(box), image, FALSE, FALSE, 0);
124
125                 bar = gtk_progress_bar_new();
126                 gtk_widget_set_size_request(bar, 100, -1);
127                 gtk_box_pack_end(GTK_BOX(box), bar, FALSE, TRUE, 0);
128                 strength = CLAMP(ifa->quality, 0, 100);
129                 perc = strength / 100.0;
130                 gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(bar), perc);
131
132                 gtk_widget_show(label);
133                 gtk_widget_show(bar);
134                 gtk_widget_show(image);
135                 gtk_widget_show(box);
136                 g_signal_connect(G_OBJECT(item), "activate",
137                                 G_CALLBACK(ssid_hook), gl->data);
138                 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
139         }
140 }
141
142 static void
143 on_activate(GtkStatusIcon *icon, _unused guint button, _unused guint32 atime, _unused gpointer data)
144 {
145         GtkMenu *menu;
146         const struct if_msg *ifm;
147         GList *gl;
148         size_t n;
149
150         notify_close();
151
152         n = 0;
153         for (gl = interfaces; gl; gl = gl->next) {
154                 ifm = (const struct if_msg *)gl->data;
155                 if (ifm->wireless)
156                         if (++n > 1)
157                                 break;
158         }
159         if (n == 0)
160                 return;
161
162         menu = (GtkMenu *)gtk_menu_new();
163
164         for (gl = interfaces; gl; gl = gl->next) {
165                 ifm = (const struct if_msg *)gl->data;
166                 if (!ifm->wireless)
167                         continue;
168                 if (n == 1) {
169                         add_scan_results(menu, ifm);
170                         break;
171                 }
172 #if 0
173                 item = gtk_image_menu_item_new_with_label(ifm->name);
174                 image = gtk_image_new_from_icon_name("network-wireless",
175                                                      GTK_ICON_SIZE_MENU);
176                 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item), image);
177
178                 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
179 #endif
180         }
181         gtk_widget_show_all(GTK_WIDGET(menu));
182         gtk_menu_popup(GTK_MENU(menu), NULL, NULL,
183                        gtk_status_icon_position_menu, icon,
184                        1, gtk_get_current_event_time());
185 }
186
187 static void
188 on_popup(GtkStatusIcon *icon, guint button, guint32 atime, gpointer data)
189 {
190         GtkMenu *menu;
191         GtkWidget *item, *image;
192
193         notify_close();
194
195         menu = (GtkMenu *)gtk_menu_new();
196
197         item = gtk_image_menu_item_new_with_mnemonic(_("_Quit"));
198         image = gtk_image_new_from_icon_name(GTK_STOCK_QUIT,
199                                              GTK_ICON_SIZE_MENU);
200         gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item), image);
201         g_signal_connect(G_OBJECT(item), "activate",
202                          G_CALLBACK(on_quit), icon);
203         gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
204
205         item = gtk_separator_menu_item_new();
206         gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
207
208         item = gtk_image_menu_item_new_with_mnemonic(_("_Help"));
209         image = gtk_image_new_from_icon_name(GTK_STOCK_HELP,
210                                              GTK_ICON_SIZE_MENU);
211         gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item), image);
212         g_signal_connect(G_OBJECT(item), "activate",
213                          G_CALLBACK(on_help), icon);
214         gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
215
216         item = gtk_image_menu_item_new_with_mnemonic(_("_About"));
217         image = gtk_image_new_from_icon_name(GTK_STOCK_ABOUT,
218                                              GTK_ICON_SIZE_MENU);
219         gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item), image);
220         g_signal_connect(G_OBJECT(item), "activate",
221                          G_CALLBACK(on_about), icon);
222         gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
223
224         gtk_widget_show_all(GTK_WIDGET(menu));
225         gtk_menu_popup(GTK_MENU(menu), NULL, NULL,
226                        gtk_status_icon_position_menu, data, button, atime);
227         if (button == 0)
228                 gtk_menu_shell_select_first(GTK_MENU_SHELL(menu), FALSE);
229 }
230
231 void
232 menu_init(GtkStatusIcon *icon)
233 {
234         g_signal_connect_object(G_OBJECT(icon), "activate",
235                                 G_CALLBACK(on_activate), icon, 0);
236         g_signal_connect_object(G_OBJECT(icon), "popup_menu",
237                                 G_CALLBACK(on_popup), icon, 0);
238 }