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