Add preliminary support for adding wireless networks to the menu. This doesn't actual...
[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
30 static const char *copyright = "Copyright (c) 2009 Roy Marples";
31
32 static const char *authors[] = {
33         "Roy Marples <roy@marples.name>",
34         NULL
35 };
36 static const char *license =
37         "Licensed under the 2 clause BSD license.\n"
38         "\n"
39         "Redistribution and use in source and binary forms, with or without\n"
40         "modification, are permitted provided that the following conditions\n"
41         "are met:\n"
42         "1. Redistributions of source code must retain the above copyright\n"
43         "   notice, this list of conditions and the following disclaimer.\n"
44         "2. Redistributions in binary form must reproduce the above copyright\n"
45         "   notice, this list of conditions and the following disclaimer in the\n"
46         "   documentation and/or other materials provided with the distribution.\n"
47         "\n"
48         "THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND\n"
49         "ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n"
50         "IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n"
51         "ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE\n"
52         "FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n"
53         "DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\n"
54         "OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n"
55         "HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\n"
56         "LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\n"
57         "OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\n"
58         "SUCH DAMAGE.";
59
60 static void
61 on_quit(_unused GtkMenuItem *item, _unused gpointer data)
62 {
63         gtk_main_quit();
64 }
65
66 static void
67 on_help(_unused GtkMenuItem *item, _unused gpointer data)
68 {
69 }
70
71 static void
72 url_show(GtkAboutDialog *dialog, const char *url)
73 {
74         GdkScreen *screen;
75
76         screen = gtk_widget_get_screen(GTK_WIDGET(dialog));
77         gtk_show_uri(screen, url, GDK_CURRENT_TIME, NULL);
78 }
79
80 static void
81 email_hook(GtkAboutDialog *dialog, const char *url, _unused gpointer p)
82 {
83         char *address;
84
85         address = g_strdup_printf("mailto:%s", url);
86         url_show(dialog, address);
87         g_free(address);
88 }
89
90 static void
91 url_hook(GtkAboutDialog *dialog, const char *url, _unused gpointer p)
92 {
93         url_show(dialog, url);
94 }
95
96 static void
97 on_about(_unused GtkMenuItem *item, _unused gpointer data)
98 {
99         gtk_window_set_default_icon_name(GTK_STOCK_NETWORK);
100         gtk_about_dialog_set_email_hook(email_hook, NULL, NULL);
101         gtk_about_dialog_set_url_hook(url_hook, NULL, NULL);
102         gtk_show_about_dialog(NULL,
103                               "version", VERSION,
104                               "copyright", copyright,
105                               "license", license,
106                               "website-label", "dhcpcd Website",
107                               "website", "http://roy.marples.name/projects/dhcpcd",
108                               "authors", authors,
109                               "wrap-license", TRUE,
110                               "logo-icon-name", GTK_STOCK_NETWORK,
111                               NULL);
112 }
113
114 static void
115 add_scan_results(GtkMenu *menu, const struct if_msg *ifm)
116 {
117         GList *gl;
118         const struct if_ap *ifa;
119         GtkWidget *item, *image;
120
121         for (gl = ifm->scan_results; gl; gl = gl->next) {
122                 ifa = (const struct if_ap *)gl->data;
123                 item = gtk_image_menu_item_new_with_label(ifa->ssid);
124                 image = gtk_image_new_from_icon_name("network-wireless",
125                                                      GTK_ICON_SIZE_MENU);
126                 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item), image);
127                 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
128         }
129 }
130
131 static void
132 on_activate(GtkStatusIcon *icon, _unused guint button, guint32 atime, gpointer data)
133 {
134         GtkMenu *menu, *sub;
135         GtkWidget *item, *image;
136         const struct if_msg *ifm;
137         GList *gl;
138         size_t n;
139
140         notify_close();
141
142         n = 0;
143         for (gl = interfaces; gl; gl = gl->next) {
144                 ifm = (const struct if_msg *)gl->data;
145                 if (ifm->wireless)
146                         if (++n > 1)
147                                 break;
148         }
149         if (n == 0)
150                 return;
151
152         menu = (GtkMenu *)gtk_menu_new();
153
154         for (gl = interfaces; gl; gl = gl->next) {
155                 ifm = (const struct if_msg *)gl->data;
156                 if (!ifm->wireless)
157                         continue;
158                 if (n == 1) {
159                         add_scan_results(menu, ifm);
160                         break;
161                 }
162 #if 0
163                 item = gtk_image_menu_item_new_with_label(ifm->name);
164                 image = gtk_image_new_from_icon_name("network-wireless",
165                                                      GTK_ICON_SIZE_MENU);
166                 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item), image);
167
168                 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
169 #endif
170         }
171         gtk_widget_show_all(GTK_WIDGET(menu));
172         gtk_menu_popup(GTK_MENU(menu), NULL, NULL,
173                        gtk_status_icon_position_menu, icon,
174                        1, gtk_get_current_event_time());
175 }
176
177 static void
178 on_popup(GtkStatusIcon *icon, guint button, guint32 atime, gpointer data)
179 {
180         GtkMenu *menu;
181         GtkWidget *item, *image;
182
183         notify_close();
184
185         menu = (GtkMenu *)gtk_menu_new();
186
187         item = gtk_image_menu_item_new_with_mnemonic("_Quit");
188         image = gtk_image_new_from_icon_name(GTK_STOCK_QUIT,
189                                              GTK_ICON_SIZE_MENU);
190         gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item), image);
191         g_signal_connect(G_OBJECT(item), "activate",
192                          G_CALLBACK(on_quit), icon);
193         gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
194
195         item = gtk_separator_menu_item_new();
196         gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
197
198         item = gtk_image_menu_item_new_with_mnemonic("_Help");
199         image = gtk_image_new_from_icon_name(GTK_STOCK_HELP,
200                                              GTK_ICON_SIZE_MENU);
201         gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item), image);
202         g_signal_connect(G_OBJECT(item), "activate",
203                          G_CALLBACK(on_help), icon);
204         gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
205
206         item = gtk_image_menu_item_new_with_mnemonic("_About");
207         image = gtk_image_new_from_icon_name(GTK_STOCK_ABOUT,
208                                              GTK_ICON_SIZE_MENU);
209         gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item), image);
210         g_signal_connect(G_OBJECT(item), "activate",
211                          G_CALLBACK(on_about), icon);
212         gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
213
214         gtk_widget_show_all(GTK_WIDGET(menu));
215         gtk_menu_popup(GTK_MENU(menu), NULL, NULL,
216                        gtk_status_icon_position_menu, data, button, atime);
217         if (button == 0)
218                 gtk_menu_shell_select_first(GTK_MENU_SHELL(menu), FALSE);
219 }
220
221 void
222 menu_init(GtkStatusIcon *icon)
223 {
224         g_signal_connect_object(G_OBJECT(icon), "activate",
225                                 G_CALLBACK(on_activate), icon, 0);
226         g_signal_connect_object(G_OBJECT(icon), "popup_menu",
227                                 G_CALLBACK(on_popup), icon, 0);
228 }