1a658088277aba983d3c6feafe98b00c4d688f02
[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
37 static void
38 on_quit(_unused GtkMenuItem *item, _unused gpointer data)
39 {
40         gtk_main_quit();
41 }
42
43 static void
44 on_help(_unused GtkMenuItem *item, _unused gpointer data)
45 {
46 }
47
48 static void
49 url_show(GtkAboutDialog *dialog, const char *url)
50 {
51         GdkScreen *screen;
52
53         screen = gtk_widget_get_screen(GTK_WIDGET(dialog));
54         gtk_show_uri(screen, url, GDK_CURRENT_TIME, NULL);
55 }
56
57 static void
58 email_hook(GtkAboutDialog *dialog, const char *url, _unused gpointer p)
59 {
60         char *address;
61
62         address = g_strdup_printf("mailto:%s", url);
63         url_show(dialog, address);
64         g_free(address);
65 }
66
67 static void
68 url_hook(GtkAboutDialog *dialog, const char *url, _unused gpointer p)
69 {
70         url_show(dialog, url);
71 }
72
73 static void
74 on_about(_unused GtkMenuItem *item, _unused gpointer data)
75 {
76         gtk_window_set_default_icon_name(GTK_STOCK_NETWORK);
77         gtk_about_dialog_set_email_hook(email_hook, NULL, NULL);
78         gtk_about_dialog_set_url_hook(url_hook, NULL, NULL);
79         gtk_show_about_dialog(NULL,
80                               "version", VERSION,
81                               "copyright", copyright,
82                               "website-label", "dhcpcd Website",
83                               "website", "http://roy.marples.name/projects/dhcpcd",
84                               "authors", authors,
85                               "logo-icon-name", GTK_STOCK_NETWORK,
86                               NULL);
87 }
88
89 static void
90 add_scan_results(GtkMenu *menu, const struct if_msg *ifm)
91 {
92         GSList *gl;
93         const struct if_ap *ifa;
94         GtkWidget *item, *image;
95
96         for (gl = ifm->scan_results; gl; gl = gl->next) {
97                 ifa = (const struct if_ap *)gl->data;
98                 item = gtk_image_menu_item_new_with_label(ifa->ssid);
99                 image = NULL;
100                 if (g_strcmp0(ifm->ssid, ifa->ssid) == 0)
101                         image = gtk_image_new_from_icon_name("network-wireless",
102                                                              GTK_ICON_SIZE_MENU);
103                 if (!image && ifa->flags != NULL)
104                         image = gtk_image_new_from_icon_name("lock",
105                                                              GTK_ICON_SIZE_MENU);
106                 if (image)
107                         gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item),
108                                                       image);
109                 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
110         }
111 }
112
113 static void
114 on_activate(GtkStatusIcon *icon, _unused guint button, _unused guint32 atime, _unused gpointer data)
115 {
116         GtkMenu *menu;
117         const struct if_msg *ifm;
118         GList *gl;
119         size_t n;
120
121         notify_close();
122
123         n = 0;
124         for (gl = interfaces; gl; gl = gl->next) {
125                 ifm = (const struct if_msg *)gl->data;
126                 if (ifm->wireless)
127                         if (++n > 1)
128                                 break;
129         }
130         if (n == 0)
131                 return;
132
133         menu = (GtkMenu *)gtk_menu_new();
134
135         for (gl = interfaces; gl; gl = gl->next) {
136                 ifm = (const struct if_msg *)gl->data;
137                 if (!ifm->wireless)
138                         continue;
139                 if (n == 1) {
140                         add_scan_results(menu, ifm);
141                         break;
142                 }
143 #if 0
144                 item = gtk_image_menu_item_new_with_label(ifm->name);
145                 image = gtk_image_new_from_icon_name("network-wireless",
146                                                      GTK_ICON_SIZE_MENU);
147                 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item), image);
148
149                 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
150 #endif
151         }
152         gtk_widget_show_all(GTK_WIDGET(menu));
153         gtk_menu_popup(GTK_MENU(menu), NULL, NULL,
154                        gtk_status_icon_position_menu, icon,
155                        1, gtk_get_current_event_time());
156 }
157
158 static void
159 on_popup(GtkStatusIcon *icon, guint button, guint32 atime, gpointer data)
160 {
161         GtkMenu *menu;
162         GtkWidget *item, *image;
163
164         notify_close();
165
166         menu = (GtkMenu *)gtk_menu_new();
167
168         item = gtk_image_menu_item_new_with_mnemonic(_("_Quit"));
169         image = gtk_image_new_from_icon_name(GTK_STOCK_QUIT,
170                                              GTK_ICON_SIZE_MENU);
171         gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item), image);
172         g_signal_connect(G_OBJECT(item), "activate",
173                          G_CALLBACK(on_quit), icon);
174         gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
175
176         item = gtk_separator_menu_item_new();
177         gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
178
179         item = gtk_image_menu_item_new_with_mnemonic(_("_Help"));
180         image = gtk_image_new_from_icon_name(GTK_STOCK_HELP,
181                                              GTK_ICON_SIZE_MENU);
182         gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item), image);
183         g_signal_connect(G_OBJECT(item), "activate",
184                          G_CALLBACK(on_help), icon);
185         gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
186
187         item = gtk_image_menu_item_new_with_mnemonic(_("_About"));
188         image = gtk_image_new_from_icon_name(GTK_STOCK_ABOUT,
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_about), icon);
193         gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
194
195         gtk_widget_show_all(GTK_WIDGET(menu));
196         gtk_menu_popup(GTK_MENU(menu), NULL, NULL,
197                        gtk_status_icon_position_menu, data, button, atime);
198         if (button == 0)
199                 gtk_menu_shell_select_first(GTK_MENU_SHELL(menu), FALSE);
200 }
201
202 void
203 menu_init(GtkStatusIcon *icon)
204 {
205         g_signal_connect_object(G_OBJECT(icon), "activate",
206                                 G_CALLBACK(on_activate), icon, 0);
207         g_signal_connect_object(G_OBJECT(icon), "popup_menu",
208                                 G_CALLBACK(on_popup), icon, 0);
209 }