2 * Utilities to use when constructing dialogs
6 * Wireshark - Network traffic analyzer
7 * By Gerald Combs <gerald@wireshark.org>
8 * Copyright 1998 Gerald Combs
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version 2
13 * of the License, or (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
33 #include "gtk/gtkglobals.h"
34 #include "gtk/gui_utils.h"
35 #include "gtk/dlg_utils.h"
36 #include "gtk/stock_icons.h"
38 #include "epan/filesystem.h"
42 dlg_activate (GtkWidget *widget, gpointer ok_button);
44 /* create a button for the button row (helper for dlg_button_row_new) */
46 dlg_button_new(GtkWidget *hbox, GtkWidget *button_hbox, const gchar *stock_id)
50 button = gtk_button_new_from_stock(stock_id);
51 #if GTK_CHECK_VERSION(2,18,0)
52 gtk_widget_set_can_default(button, TRUE);
54 GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
56 g_object_set_data(G_OBJECT(hbox), stock_id, button);
57 gtk_box_pack_end(GTK_BOX(button_hbox), button, FALSE, FALSE, 0);
58 gtk_widget_show(button);
63 * Set the focus and default for the nth item in a button row, with
64 * 0 being the first item.
66 #define BUTTON_HBOX_KEY "button_hbox"
68 dlg_button_focus_nth(GtkWidget *hbox, gint focus_item) {
69 GtkWidget *button_hbox, *button;
76 button_hbox = g_object_get_data(G_OBJECT(hbox), BUTTON_HBOX_KEY);
77 children = gtk_container_get_children(GTK_CONTAINER(button_hbox));
80 if (cur_item == focus_item) {
81 button = children->data;
82 gtk_widget_grab_focus(button);
83 gtk_widget_grab_default(button);
86 children = g_list_next(children);
90 g_list_free(children);
93 /* create a button row for a dialog */
95 /* The purpose of this is, to have one place available, where all button rows
96 * from all dialogs are laid out. This will:
98 * a.) keep the button layout more consistent over the different dialogs
99 * b.) being able to switch between different button layouts, e.g.:
100 * e.g. Win32: "OK" "Apply" "Cancel"
101 * e.g. GNOME: "Apply" "Cancel" "OK"
104 dlg_button_row_new(const gchar *stock_id_first, ...)
107 va_list stock_id_list;
108 const gchar *stock_id = stock_id_first;
110 GtkWidget *button_hbox;
111 GtkWidget *help_hbox;
114 const gchar *apply = NULL;
115 const gchar *cancel = NULL;
116 const gchar *cap_start = NULL;
117 const gchar *cap_stop = NULL;
118 const gchar *cap_options = NULL;
120 const gchar *cap_details = NULL;
122 const gchar *clear = NULL;
123 const gchar *close = NULL;
124 const gchar *copy = NULL;
125 const gchar *create_stat = NULL;
126 const gchar *delete = NULL;
127 const gchar *dont_save = NULL;
128 const gchar *filter_stream= NULL;
129 const gchar *find = NULL;
130 const gchar *help = NULL;
131 const gchar *jump = NULL;
132 const gchar *no = NULL;
133 const gchar *ok = NULL;
134 const gchar *print = NULL;
135 const gchar *save = NULL;
136 const gchar *save_as = NULL;
137 const gchar *save_all = NULL;
138 const gchar *stop = NULL;
139 const gchar *yes = NULL;
141 const gchar *map = NULL;
142 #endif /* HAVE_GEOIP */
143 const gchar *follow_stream = NULL;
146 va_start(stock_id_list, stock_id_first);
148 /* get all buttons needed */
149 while(stock_id != NULL) {
150 if (strcmp(stock_id, GTK_STOCK_OK) == 0) {
152 } else if (strcmp(stock_id, WIRESHARK_STOCK_CREATE_STAT) == 0) {
153 create_stat = stock_id;
154 } else if (strcmp(stock_id, GTK_STOCK_APPLY) == 0) {
156 } else if (strcmp(stock_id, GTK_STOCK_SAVE) == 0) {
158 } else if (strcmp(stock_id, GTK_STOCK_SAVE_AS) == 0) {
160 } else if (strcmp(stock_id, WIRESHARK_STOCK_SAVE_ALL) == 0) {
162 } else if (strcmp(stock_id, WIRESHARK_STOCK_DONT_SAVE) == 0) {
163 dont_save = stock_id;
164 } else if (strcmp(stock_id, WIRESHARK_STOCK_QUIT_DONT_SAVE) == 0) {
165 dont_save = stock_id;
166 } else if (strcmp(stock_id, GTK_STOCK_CANCEL) == 0) {
168 } else if (strcmp(stock_id, GTK_STOCK_CLOSE) == 0) {
170 } else if (strcmp(stock_id, GTK_STOCK_CLEAR) == 0) {
173 } else if (strcmp(stock_id, WIRESHARK_STOCK_CAPTURE_START) == 0) {
174 cap_start = stock_id;
175 } else if (strcmp(stock_id, WIRESHARK_STOCK_CAPTURE_STOP) == 0) {
177 } else if (strcmp(stock_id, WIRESHARK_STOCK_CAPTURE_OPTIONS) == 0) {
178 cap_options = stock_id;
180 } else if (strcmp(stock_id, WIRESHARK_STOCK_CAPTURE_DETAILS) == 0) {
181 cap_details = stock_id;
183 #endif /* HAVE_LIBPCAP */
185 } else if (strcmp(stock_id, WIRESHARK_STOCK_MAP) == 0) {
187 #endif /* HAVE_GEOIP */
188 } else if (strcmp(stock_id, WIRESHARK_STOCK_FOLLOW_STREAM) == 0) {
189 follow_stream = stock_id;
190 } else if (strcmp(stock_id, GTK_STOCK_STOP) == 0) {
192 } else if (strcmp(stock_id, GTK_STOCK_HELP) == 0) {
194 } else if (strcmp(stock_id, GTK_STOCK_PRINT) == 0) {
196 } else if (strcmp(stock_id, GTK_STOCK_FIND) == 0) {
198 } else if (strcmp(stock_id, GTK_STOCK_JUMP_TO) == 0) {
200 } else if (strcmp(stock_id, GTK_STOCK_YES) == 0) {
202 } else if (strcmp(stock_id, GTK_STOCK_NO) == 0) {
204 } else if (strcmp(stock_id, WIRESHARK_STOCK_FILTER_OUT_STREAM) == 0) {
205 filter_stream = stock_id;
206 } else if (strcmp(stock_id, GTK_STOCK_DELETE) == 0) {
208 } else if (strcmp(stock_id, GTK_STOCK_COPY) == 0) {
211 /* we don't know that button! */
212 g_assert_not_reached();
215 stock_id = va_arg(stock_id_list, gchar *);
217 va_end(stock_id_list);
219 hbox = gtk_hbox_new(FALSE, 0);
220 gtk_widget_show(hbox);
222 button_hbox = gtk_hbutton_box_new();
223 gtk_box_pack_end(GTK_BOX(hbox), button_hbox, TRUE, TRUE, 0);
224 g_object_set_data(G_OBJECT(hbox), BUTTON_HBOX_KEY, button_hbox);
225 gtk_widget_show(button_hbox);
226 gtk_box_set_spacing(GTK_BOX(button_hbox), 5);
228 help_hbox = gtk_hbutton_box_new();
229 gtk_box_pack_end(GTK_BOX(hbox), help_hbox, FALSE, FALSE, 0);
230 gtk_widget_show(help_hbox);
231 gtk_box_set_spacing(GTK_BOX(help_hbox), 5);
234 /* if no buttons wanted, simply do nothing */
239 /* if only one button, simply put it in the middle (default) */
240 dlg_button_new(hbox, button_hbox, stock_id_first);
244 /* do we have a help button? -> special handling for it */
246 button = gtk_button_new_from_stock(help);
247 #if GTK_CHECK_VERSION(2,18,0)
248 gtk_widget_set_can_default(button, TRUE);
250 GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
252 g_object_set_data(G_OBJECT(hbox), help, button);
253 gtk_box_pack_start(GTK_BOX(help_hbox), button, FALSE, FALSE, 0);
254 gtk_widget_show(button);
258 /* do we have a copy button? -> special handling for it */
260 button = gtk_button_new_from_stock(copy);
261 #if GTK_CHECK_VERSION(2,18,0)
262 gtk_widget_set_can_default(button, TRUE);
264 GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
266 g_object_set_data(G_OBJECT(hbox), copy, button);
267 gtk_box_pack_start(GTK_BOX(help_hbox), button, FALSE, FALSE, 0);
268 gtk_widget_show(button);
273 /* do we have a map button? -> special handling for it */
275 button = gtk_button_new_from_stock(map);
276 #if GTK_CHECK_VERSION(2,18,0)
277 gtk_widget_set_can_default(button, TRUE);
279 GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
281 g_object_set_data(G_OBJECT(hbox), map, button);
282 gtk_box_pack_start(GTK_BOX(help_hbox), button, FALSE, FALSE, 0);
283 gtk_widget_show(button);
286 #endif /* HAVE_GEOIP */
288 /* if more than one button, sort buttons from left to right */
289 /* (the whole button cluster will then be right aligned) */
290 gtk_button_box_set_layout (GTK_BUTTON_BOX(button_hbox), GTK_BUTTONBOX_END);
293 /* beware: sequence of buttons are important! */
295 /* XXX: this can be implemented more elegant of course, but it works as it should */
298 dlg_button_new(hbox, button_hbox, cancel);
299 dlg_button_new(hbox, button_hbox, ok);
302 if (print && cancel) {
303 dlg_button_new(hbox, button_hbox, cancel);
304 dlg_button_new(hbox, button_hbox, print);
307 if (find && cancel) {
308 dlg_button_new(hbox, button_hbox, cancel);
309 dlg_button_new(hbox, button_hbox, find);
312 if (jump && cancel) {
313 dlg_button_new(hbox, button_hbox, cancel);
314 dlg_button_new(hbox, button_hbox, jump);
317 if (save && cancel) {
318 dlg_button_new(hbox, button_hbox, cancel);
319 dlg_button_new(hbox, button_hbox, save);
323 dlg_button_new(hbox, button_hbox, clear);
324 dlg_button_new(hbox, button_hbox, ok);
328 dlg_button_new(hbox, button_hbox, close);
329 dlg_button_new(hbox, button_hbox, save);
332 if (create_stat && cancel) {
333 dlg_button_new(hbox, button_hbox, cancel);
334 dlg_button_new(hbox, button_hbox, create_stat);
337 if (cap_start && cancel) {
338 dlg_button_new(hbox, button_hbox, cancel);
339 dlg_button_new(hbox, button_hbox, cap_start);
342 if (cap_stop && cancel) {
343 dlg_button_new(hbox, button_hbox, cancel);
344 dlg_button_new(hbox, button_hbox, cap_stop);
347 if (delete && cancel) {
348 dlg_button_new(hbox, button_hbox, cancel);
349 dlg_button_new(hbox, button_hbox, delete);
354 if (ok && save && close) {
355 dlg_button_new(hbox, button_hbox, save);
356 dlg_button_new(hbox, button_hbox, close);
357 dlg_button_new(hbox, button_hbox, ok);
360 if (ok && apply && cancel) {
361 dlg_button_new(hbox, button_hbox, apply);
362 dlg_button_new(hbox, button_hbox, cancel);
363 dlg_button_new(hbox, button_hbox, ok);
366 if (apply && save && close) {
367 dlg_button_new(hbox, button_hbox, save);
368 dlg_button_new(hbox, button_hbox, close);
369 dlg_button_new(hbox, button_hbox, apply);
372 if (yes && no && cancel) {
373 dlg_button_new(hbox, button_hbox, no);
374 dlg_button_new(hbox, button_hbox, cancel);
375 dlg_button_new(hbox, button_hbox, yes);
378 if (save && dont_save && cancel) {
379 dlg_button_new(hbox, button_hbox, dont_save);
380 dlg_button_new(hbox, button_hbox, cancel);
381 dlg_button_new(hbox, button_hbox, save);
386 if (ok && apply && save && cancel) {
387 dlg_button_new(hbox, button_hbox, save);
388 dlg_button_new(hbox, button_hbox, apply);
389 dlg_button_new(hbox, button_hbox, cancel);
390 dlg_button_new(hbox, button_hbox, ok);
393 if (ok && apply && save && close) {
394 dlg_button_new(hbox, button_hbox, save);
395 dlg_button_new(hbox, button_hbox, apply);
396 dlg_button_new(hbox, button_hbox, close);
397 dlg_button_new(hbox, button_hbox, ok);
403 /* beware: sequence of buttons is important! */
404 if (ok != NULL) dlg_button_new(hbox, button_hbox, ok);
405 if (delete != NULL) dlg_button_new(hbox, button_hbox, delete);
406 if (jump != NULL) dlg_button_new(hbox, button_hbox, jump);
407 if (find != NULL) dlg_button_new(hbox, button_hbox, find);
408 if (print != NULL) dlg_button_new(hbox, button_hbox, print);
409 if (create_stat != NULL) dlg_button_new(hbox, button_hbox, create_stat);
410 if (apply != NULL) dlg_button_new(hbox, button_hbox, apply);
411 if (yes != NULL) dlg_button_new(hbox, button_hbox, yes);
412 if (no != NULL) dlg_button_new(hbox, button_hbox, no);
413 if (save != NULL) dlg_button_new(hbox, button_hbox, save);
414 if (save_as != NULL) dlg_button_new(hbox, button_hbox, save_as);
415 if (save_all != NULL) dlg_button_new(hbox, button_hbox, save_all);
416 if (dont_save != NULL) dlg_button_new(hbox, button_hbox, dont_save);
417 if (cap_start != NULL) dlg_button_new(hbox, button_hbox, cap_start);
418 if (cap_stop != NULL) dlg_button_new(hbox, button_hbox, cap_stop);
419 if (cap_options != NULL) dlg_button_new(hbox, button_hbox, cap_options);
421 if (cap_details != NULL) dlg_button_new(hbox, button_hbox, cap_details);
423 if (stop != NULL) dlg_button_new(hbox, button_hbox, stop);
424 if (clear != NULL) dlg_button_new(hbox, button_hbox, clear);
425 if (filter_stream!= NULL) dlg_button_new(hbox, button_hbox, filter_stream);
426 if (follow_stream != NULL) dlg_button_new(hbox, button_hbox, follow_stream);
427 if (close != NULL) dlg_button_new(hbox, button_hbox, close);
428 if (cancel != NULL) dlg_button_new(hbox, button_hbox, cancel);
434 /* Create a dialog box window that belongs to Wireshark's main window. */
436 dlg_window_new(const gchar *title)
440 win = window_new(GTK_WINDOW_TOPLEVEL, title);
443 * XXX - if we're running in the capture child process, we can't easily
444 * make this window transient for the main process's window. We just
447 * Perhaps the child process should only capture packets, write them to
448 * a file, and somehow notify the parent process and let *it* do all
449 * the GUI work. If we can do that efficiently (so that we don't drop
450 * more packets), perhaps we can also do so even when we're *not* doing
451 * an "Update list of packets in real time" capture. That'd let the
452 * child process run set-UID on platforms where you need that in order
453 * to capture, and might also simplify the job of having the GUI main
454 * loop wait both for user input and packet arrival.
457 * On Windows, making the dialogs transient to top_level behaves strangely.
458 * It is not possible any more to bring the top level window to front easily.
459 * So we don't do this on Windows.
463 gtk_window_set_transient_for(GTK_WINDOW(win), GTK_WINDOW(top_level));
470 /* Create a configuration dialog box window that belongs to Wireshark's
471 * main window and add the name of the current profile name to it's title bar
474 dlg_conf_window_new(const gchar *title)
476 const char *profile_name;
481 * Set window title to reflect which preferences profile we are
484 profile_name = get_profile_name();
486 win_name = g_strdup_printf("%s - Profile: %s", title, profile_name);
487 win = dlg_window_new(win_name);
494 /* Set the "activate" signal for a widget to call a routine to
495 activate the "OK" button for a dialog box.
497 XXX - there should be a way to specify that a GtkEntry widget
498 shouldn't itself handle the Return key, but should let it be
499 passed on to the parent, so that you don't have to do this
500 by hand for every GtkEntry widget in a dialog box, but, alas,
501 there isn't. (Does this problem exist for other widgets?
502 I.e., are there any others that seize the Return key? */
504 dlg_set_activate(GtkWidget *widget, GtkWidget *ok_button)
506 g_signal_connect(widget, "activate", G_CALLBACK(dlg_activate), ok_button);
510 dlg_activate (GtkWidget *widget _U_, gpointer ok_button)
512 gtk_widget_activate(GTK_WIDGET(ok_button));