set SVN properties
[obnox/wireshark/wip.git] / gtk / main_welcome.c
1 /* main_welcome.c
2  *
3  * $Id$
4  *
5  * Wireshark - Network traffic analyzer
6  * By Gerald Combs <gerald@wireshark.org>
7  * Copyright 1998 Gerald Combs
8  *
9  *
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.
14  *
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.
19  *
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.
23  */
24
25
26 #include <gtk/gtk.h>
27
28 #include "gui_utils.h"
29 #include "recent.h"
30 #include "main_welcome.h"
31
32
33 #ifdef SHOW_WELCOME_PAGE
34 #include "../image/wssplash.xpm"
35 #endif
36
37
38 /*#define SHOW_WELCOME_PAGE*/
39 #ifdef SHOW_WELCOME_PAGE
40 /* XXX - There seems to be some disagreement about if and how this feature should be implemented.
41    As I currently don't have the time to continue this, it's temporarily disabled. - ULFL */
42 GtkWidget *
43 welcome_item(const gchar *stock_item, const gchar * label, const gchar * message, const gchar * tooltip,
44                          GtkSignalFunc callback, void *callback_data)
45 {
46     GtkWidget *w, *item_hb;
47 #if GTK_MAJOR_VERSION >= 2
48     gchar *formatted_message;
49     GtkTooltips *tooltips;
50
51     tooltips = gtk_tooltips_new();
52 #endif
53
54     item_hb = gtk_hbox_new(FALSE, 1);
55
56     w = BUTTON_NEW_FROM_STOCK(stock_item);
57     WIDGET_SET_SIZE(w, 80, 40);
58 #if GTK_MAJOR_VERSION >= 2
59     gtk_button_set_label(GTK_BUTTON(w), label);
60     gtk_tooltips_set_tip(tooltips, w, tooltip, NULL);
61 #endif
62     gtk_box_pack_start(GTK_BOX(item_hb), w, FALSE, FALSE, 0);
63     SIGNAL_CONNECT(w, "clicked", callback, callback_data);
64
65     w = gtk_label_new(message);
66     gtk_misc_set_alignment (GTK_MISC(w), 0.0, 0.5);
67 #if GTK_MAJOR_VERSION >= 2
68     formatted_message = g_strdup_printf("<span weight=\"bold\" size=\"x-large\">%s</span>", message);
69     gtk_label_set_markup(GTK_LABEL(w), formatted_message);
70     g_free(formatted_message);
71 #endif
72
73     gtk_box_pack_start(GTK_BOX(item_hb), w, FALSE, FALSE, 10);
74
75     return item_hb;
76 }
77
78
79 GtkWidget *
80 welcome_header_new(void)
81 {
82     GtkWidget *item_vb;
83     GtkWidget *item_hb;
84     GtkWidget *eb;
85     GdkColor bg;
86     GtkWidget *icon;
87     gchar *message;
88     GtkWidget *w;
89
90
91     /* background color of the header bar */
92     bg.pixel = 0;
93     bg.red = 154 * 255;
94     bg.green = 210 * 255;
95     bg.blue = 229 * 255;
96
97     item_vb = gtk_vbox_new(FALSE, 0);
98
99     /* colorize vbox */
100     get_color(&bg);
101     eb = gtk_event_box_new();
102     gtk_container_add(GTK_CONTAINER(eb), item_vb);
103 #if GTK_MAJOR_VERSION >= 2
104     gtk_widget_modify_bg(eb, GTK_STATE_NORMAL, &bg);
105 #endif
106
107     item_hb = gtk_hbox_new(FALSE, 0);
108     gtk_box_pack_start(GTK_BOX(item_vb), item_hb, FALSE, FALSE, 10);
109
110     icon = xpm_to_widget_from_parent(top_level, wssplash_xpm);
111     /*icon = xpm_to_widget_from_parent(top_level, wsicon64_xpm);*/
112     gtk_box_pack_start(GTK_BOX(item_hb), icon, FALSE, FALSE, 10);
113
114 #if GTK_MAJOR_VERSION < 2
115     message = "The World's Most Popular Network Protocol Analyzer";
116 #else
117     message = "<span weight=\"bold\" size=\"x-large\">" "The World's Most Popular Network Protocol Analyzer" "</span>";
118 #endif
119     w = gtk_label_new(message);
120 #if GTK_MAJOR_VERSION >= 2
121     gtk_label_set_markup(GTK_LABEL(w), message);
122 #endif
123     gtk_misc_set_alignment (GTK_MISC(w), 0.0, 0.5);
124     gtk_box_pack_start(GTK_BOX(item_hb), w, TRUE, TRUE, 5);
125
126     gtk_widget_show_all(eb);
127
128     return eb;
129 }
130
131 GtkWidget *
132 welcome_topic_header_new(const char *header)
133 {
134     GtkWidget *w;
135     GdkColor bg;
136     GtkWidget *eb;
137 #if GTK_MAJOR_VERSION >= 2
138     gchar *formatted_message;
139 #endif
140
141
142     w = gtk_label_new(header);
143 #if GTK_MAJOR_VERSION >= 2
144     formatted_message = g_strdup_printf("<span weight=\"bold\" size=\"x-large\">%s</span>", header);
145     gtk_label_set_markup(GTK_LABEL(w), formatted_message);
146     g_free(formatted_message);
147 #endif
148
149     /* topic header background color */
150     bg.pixel = 0;
151     bg.red = 24 * 255;
152     bg.green = 151 * 255;
153     bg.blue = 192 * 255;
154
155     /* colorize vbox */
156     get_color(&bg);
157     eb = gtk_event_box_new();
158     gtk_container_add(GTK_CONTAINER(eb), w);
159 #if GTK_MAJOR_VERSION >= 2
160     gtk_widget_modify_bg(eb, GTK_STATE_NORMAL, &bg);
161 #endif
162
163     return eb;
164 }
165
166
167 GtkWidget *
168 welcome_topic_new(const char *header, GtkWidget **to_fill)
169 {
170     GtkWidget *topic_vb;
171     GtkWidget *layout_vb;
172     GtkWidget *topic_eb;
173     GtkWidget *topic_header;
174     GdkColor bg;
175
176     topic_vb = gtk_vbox_new(FALSE, 0);
177
178         /* topic content background color */
179     bg.pixel = 0;
180     bg.red = 221 * 255;
181     bg.green = 226 * 255;
182     bg.blue = 228 * 255;
183
184     topic_header = welcome_topic_header_new(header);
185     gtk_box_pack_start(GTK_BOX(topic_vb), topic_header, FALSE, FALSE, 0);
186
187     layout_vb = gtk_vbox_new(FALSE, 5);
188     gtk_container_border_width(GTK_CONTAINER(layout_vb), 10);
189     gtk_box_pack_start(GTK_BOX(topic_vb), layout_vb, FALSE, FALSE, 0);
190
191     /* colorize vbox (we need an event box for this!) */
192     get_color(&bg);
193     topic_eb = gtk_event_box_new();
194     gtk_container_add(GTK_CONTAINER(topic_eb), topic_vb);
195 #if GTK_MAJOR_VERSION >= 2
196     gtk_widget_modify_bg(topic_eb, GTK_STATE_NORMAL, &bg);
197 #endif
198     *to_fill = layout_vb;
199
200     return topic_eb;
201 }
202
203
204 #if GTK_MAJOR_VERSION >= 2
205 static gboolean
206 welcome_link_enter_cb(GtkWidget *widget _U_, GdkEventCrossing *event _U_, gpointer user_data)
207 {
208     gchar *message;
209     GtkWidget *w = user_data;
210
211     message = g_strdup_printf("<span foreground='blue' underline='single'>%s</span>", OBJECT_GET_DATA(w,"TEXT"));
212 #if GTK_MAJOR_VERSION >= 2
213     gtk_label_set_markup(GTK_LABEL(w), message);
214 #endif
215     g_free(message);
216
217     return FALSE;
218 }
219
220 static gboolean
221 welcome_link_leave_cb(GtkWidget *widget _U_, GdkEvent *event _U_, gpointer user_data)
222 {
223     gchar *message;
224     GtkWidget *w = user_data;
225
226     message = g_strdup_printf("<span foreground='blue'>%s</span>", OBJECT_GET_DATA(w,"TEXT"));
227 #if GTK_MAJOR_VERSION >= 2
228     gtk_label_set_markup(GTK_LABEL(w), message);
229 #endif
230     g_free(message);
231
232     return FALSE;
233 }
234 #endif
235
236
237 static gboolean
238 welcome_link_press_cb(GtkWidget *widget _U_, GdkEvent *event _U_, gpointer data _U_) {
239
240     g_warning("TBD: link pressed");
241
242     return FALSE;
243 }
244
245 GtkWidget *
246 welcome_link_new(const gchar *text, GtkWidget **label /*, void *callback, void *private_data */)
247 {
248     gchar *message;
249     GtkWidget *w;
250     GtkWidget *eb;
251
252 #if GTK_MAJOR_VERSION < 2
253     message = g_strdup(text);
254 #else
255     message = g_strdup_printf("<span foreground='blue'>%s</span>", text);
256 #endif
257     w = gtk_label_new(message);
258     *label = w;
259 #if GTK_MAJOR_VERSION >= 2
260     gtk_label_set_markup(GTK_LABEL(w), message);
261 #endif
262     g_free(message);
263
264         /* event box */
265     eb = gtk_event_box_new();
266     gtk_container_add(GTK_CONTAINER(eb), w);
267
268 #if GTK_MAJOR_VERSION >= 2
269     SIGNAL_CONNECT(eb, "enter-notify-event", welcome_link_enter_cb, w);
270     SIGNAL_CONNECT(eb, "leave-notify-event", welcome_link_leave_cb, w);
271 #endif
272     SIGNAL_CONNECT(eb, "button-press-event", welcome_link_press_cb, w);
273
274     /* XXX - memleak */
275     OBJECT_SET_DATA(w, "TEXT", g_strdup(text));
276
277     return eb;
278 }
279
280 GtkWidget *
281 welcome_filename_link_new(const char *filename, GtkWidget **label)
282 {
283     GString             *str;
284     GtkWidget   *w;
285     const unsigned int max = 60;
286
287
288     str = g_string_new(filename);
289
290     if(str->len > max) {
291         g_string_erase(str, 0, str->len-max /*cut*/);
292         g_string_prepend(str, "... ");
293     }
294
295     w = welcome_link_new(str->str, label);
296
297     g_string_free(str, TRUE);
298
299     return w;
300 }
301
302
303 GtkWidget *
304 welcome_if_new(const char *if_name, GdkColor *topic_bg, gboolean active)
305 {
306     GtkWidget *interface_hb;
307     GtkWidget *w;
308     GtkWidget *label;
309     GtkTooltips *tooltips;
310     GString   *message;
311
312
313     tooltips = gtk_tooltips_new();
314
315     interface_hb = gtk_hbox_new(FALSE, 5);
316
317     w = welcome_link_new("START", &label);
318     gtk_tooltips_set_tip(tooltips, w, "Immediately start a capture on this interface", NULL);
319 #if GTK_MAJOR_VERSION >= 2
320     gtk_widget_modify_bg(w, GTK_STATE_NORMAL, topic_bg);
321 #endif
322     gtk_misc_set_alignment (GTK_MISC(label), 0.0, 0.0);
323     gtk_box_pack_start(GTK_BOX(interface_hb), w, FALSE, FALSE, 0);
324
325     w = welcome_link_new("OPTIONS", &label);
326     gtk_tooltips_set_tip(tooltips, w, "Show the capture options of this interface", NULL);
327 #if GTK_MAJOR_VERSION >= 2
328     gtk_widget_modify_bg(w, GTK_STATE_NORMAL, topic_bg);
329 #endif
330     gtk_misc_set_alignment (GTK_MISC(label), 0.0, 0.0);
331     gtk_box_pack_start(GTK_BOX(interface_hb), w, FALSE, FALSE, 0);
332
333     w = welcome_link_new("DETAILS", &label);
334     gtk_tooltips_set_tip(tooltips, w, "Show detailed information about this interface", NULL);
335 #if GTK_MAJOR_VERSION >= 2
336     gtk_widget_modify_bg(w, GTK_STATE_NORMAL, topic_bg);
337 #endif
338     gtk_misc_set_alignment (GTK_MISC(label), 0.0, 0.0);
339     gtk_box_pack_start(GTK_BOX(interface_hb), w, FALSE, FALSE, 0);
340
341     message = g_string_new(if_name);
342
343     /* truncate string if it's too long */
344     if(message->len > 38) {
345         g_string_truncate(message, 35);
346         g_string_append  (message, " ...");
347     }
348 #if GTK_MAJOR_VERSION >= 2
349     /* if this is the "active" interface, display it bold */
350     if(active) {
351         g_string_prepend(message, "<span weight=\"bold\">");
352         g_string_append (message, "</span>");
353         }
354 #endif
355     w = gtk_label_new(message->str);
356 #if GTK_MAJOR_VERSION >= 2
357     gtk_label_set_markup(GTK_LABEL(w), message->str);
358 #endif
359     g_string_free(message, TRUE);
360
361     gtk_misc_set_alignment (GTK_MISC(w), 0.0, 0.0);
362     gtk_box_pack_start(GTK_BOX(interface_hb), w, FALSE, FALSE, 0);
363
364     return interface_hb;
365 }
366
367 /* XXX - the layout has to be improved */
368 GtkWidget *
369 welcome_new(void)
370 {
371     GtkWidget *welcome_scrollw;
372     GtkWidget *welcome_vb;
373     GtkWidget *welcome_hb;
374     GtkWidget *column_vb;
375     GtkWidget *item_hb;
376     GtkWidget *w;
377     GtkWidget *label;
378     GtkWidget *header;
379     GtkWidget *topic_vb;
380     GtkWidget *topic_to_fill;
381     GtkWidget *interface_hb;
382     GdkColor  topic_bg;
383
384
385     /* topic content background color */
386     topic_bg.pixel = 0;
387     topic_bg.red = 221 * 255;
388     topic_bg.green = 226 * 255;
389     topic_bg.blue = 228 * 255;
390
391     welcome_scrollw = scrolled_window_new(NULL, NULL);
392
393     welcome_vb = gtk_vbox_new(FALSE, 0);
394
395     /* header */
396     header = welcome_header_new();
397     gtk_box_pack_start(GTK_BOX(welcome_vb), header, FALSE, FALSE, 0);
398
399     /* content */
400     welcome_hb = gtk_hbox_new(FALSE, 10);
401     gtk_container_border_width(GTK_CONTAINER(welcome_hb), 10);
402     gtk_box_pack_start(GTK_BOX(welcome_vb), welcome_hb, TRUE, TRUE, 0);
403
404     /* column capture */
405     column_vb = gtk_vbox_new(FALSE, 10);
406     gtk_box_pack_start(GTK_BOX(welcome_hb), column_vb, TRUE, TRUE, 0);
407
408     /* capture topic */
409     topic_vb = welcome_topic_new("Capture", &topic_to_fill);
410     gtk_box_pack_start(GTK_BOX(column_vb), topic_vb, TRUE, TRUE, 0);
411
412 #ifdef HAVE_LIBPCAP
413     item_hb = welcome_item(WIRESHARK_STOCK_CAPTURE_INTERFACES,
414         "Interfaces...",
415         "Interface Life List",
416                 "Show a life list of the available capture interfaces",
417         GTK_SIGNAL_FUNC(capture_if_cb), NULL);
418     gtk_box_pack_start(GTK_BOX(topic_to_fill), item_hb, FALSE, FALSE, 5);
419 #endif
420
421     w = gtk_label_new("Available Interfaces:");
422     gtk_misc_set_alignment (GTK_MISC(w), 0.0, 0.0);
423     gtk_box_pack_start(GTK_BOX(topic_to_fill), w, FALSE, FALSE, 5);
424
425     interface_hb = welcome_if_new("Generic dialup adapter", &topic_bg, FALSE);
426     gtk_box_pack_start(GTK_BOX(topic_to_fill), interface_hb, FALSE, FALSE, 0);
427
428     /* Marvell interface (currently "active") */
429     interface_hb = welcome_if_new("Marvell Gigabit Ethernet Controller", &topic_bg, TRUE);
430     gtk_box_pack_start(GTK_BOX(topic_to_fill), interface_hb, FALSE, FALSE, 0);
431
432     /* Wireless interface */
433     interface_hb = welcome_if_new("Intel(R) PRO/Wireless 3945ABG Network Connection", &topic_bg, FALSE);
434     gtk_box_pack_start(GTK_BOX(topic_to_fill), interface_hb, FALSE, FALSE, 0);
435
436
437     /* capture help topic */
438     topic_vb = welcome_topic_new("Capture Help", &topic_to_fill);
439     gtk_box_pack_start(GTK_BOX(column_vb), topic_vb, TRUE, TRUE, 0);
440
441 #ifdef HAVE_LIBPCAP
442     item_hb = welcome_item(WIRESHARK_STOCK_CAPTURE_START,
443         "Setup",
444                 "How To: Setup a Capture",
445                 "How To: Setup a Capture (online from the Wiki)",
446         GTK_SIGNAL_FUNC(topic_cb), GINT_TO_POINTER(ONLINEPAGE_USERGUIDE));
447     gtk_box_pack_start(GTK_BOX(topic_to_fill), item_hb, FALSE, FALSE, 5);
448
449     item_hb = welcome_item(WIRESHARK_STOCK_CAPTURE_START,
450         "Examples",
451                 "Capture Filter Examples",
452                 "Capture Filter Examples (online from the Wiki)",
453         GTK_SIGNAL_FUNC(topic_cb), GINT_TO_POINTER(ONLINEPAGE_USERGUIDE));
454     gtk_box_pack_start(GTK_BOX(topic_to_fill), item_hb, FALSE, FALSE, 5);
455 #endif
456
457     /* fill bottom space */
458     w = gtk_label_new("");
459     gtk_box_pack_start(GTK_BOX(topic_to_fill), w, TRUE, TRUE, 0);
460
461
462     /* column files */
463     topic_vb = welcome_topic_new("Files", &topic_to_fill);
464     gtk_box_pack_start(GTK_BOX(welcome_hb), topic_vb, TRUE, TRUE, 0);
465
466     item_hb = welcome_item(GTK_STOCK_OPEN,
467         "Open...",
468         "Open a Capture File",
469                 "Open a previously captured file",
470         GTK_SIGNAL_FUNC(file_open_cmd_cb), NULL);
471     gtk_box_pack_start(GTK_BOX(topic_to_fill), item_hb, FALSE, FALSE, 5);
472
473     item_hb = welcome_item(GTK_STOCK_OPEN,
474         "Examples",
475         "Download Examples",
476                 "Download Example Capture Files (from the Wiki)",
477         GTK_SIGNAL_FUNC(topic_cb), GINT_TO_POINTER(ONLINEPAGE_USERGUIDE));
478     gtk_box_pack_start(GTK_BOX(topic_to_fill), item_hb, FALSE, FALSE, 5);
479
480     w = gtk_label_new("Recent Files:");
481     gtk_misc_set_alignment (GTK_MISC(w), 0.0, 0.0);
482     gtk_box_pack_start(GTK_BOX(topic_to_fill), w, FALSE, FALSE, 5);
483
484     w = welcome_link_new("C:\\Testfiles\\hello.pcap", &label);
485 #if GTK_MAJOR_VERSION >= 2
486     gtk_widget_modify_bg(w, GTK_STATE_NORMAL, &topic_bg);
487 #endif
488     gtk_misc_set_alignment (GTK_MISC(label), 0.0, 0.0);
489     gtk_box_pack_start(GTK_BOX(topic_to_fill), w, FALSE, FALSE, 0);
490
491     w = welcome_filename_link_new("C:\\Testfiles\\hello2.pcap", &label);
492 #if GTK_MAJOR_VERSION >= 2
493     gtk_widget_modify_bg(w, GTK_STATE_NORMAL, &topic_bg);
494 #endif
495     gtk_misc_set_alignment (GTK_MISC(label), 0.0, 0.0);
496     gtk_box_pack_start(GTK_BOX(topic_to_fill), w, FALSE, FALSE, 0);
497
498     w = welcome_filename_link_new(
499                 "C:\\Testfiles\\to avoid screen garbage\\Unfortunately this is a very long filename which had to be truncated.pcap",
500                 &label);
501 #if GTK_MAJOR_VERSION >= 2
502     gtk_widget_modify_bg(w, GTK_STATE_NORMAL, &topic_bg);
503 #endif
504     gtk_misc_set_alignment (GTK_MISC(label), 0.0, 0.0);
505     gtk_box_pack_start(GTK_BOX(topic_to_fill), w, FALSE, FALSE, 0);
506
507     w = gtk_label_new("");
508     gtk_box_pack_start(GTK_BOX(topic_to_fill), w, TRUE, TRUE, 0);
509
510
511     /* column online */
512     column_vb = gtk_vbox_new(FALSE, 10);
513     gtk_box_pack_start(GTK_BOX(welcome_hb), column_vb, TRUE, TRUE, 0);
514
515     /* topic online */
516     topic_vb = welcome_topic_new("Online", &topic_to_fill);
517     gtk_box_pack_start(GTK_BOX(column_vb), topic_vb, TRUE, TRUE, 0);
518
519 #if (GLIB_MAJOR_VERSION >= 2)
520     item_hb = welcome_item(WIRESHARK_STOCK_WEB_SUPPORT,
521         "Help",
522         "Show the User's Guide",
523                 "Show the User's Guide (local version, if available)",
524         GTK_SIGNAL_FUNC(topic_cb), GINT_TO_POINTER(ONLINEPAGE_USERGUIDE));
525     gtk_box_pack_start(GTK_BOX(topic_to_fill), item_hb, FALSE, FALSE, 5);
526
527     item_hb = welcome_item(GTK_STOCK_HOME,
528         "Home",
529         "Projects Home Page",
530                 "Visit www.wireshark.org, the project's home page",
531         GTK_SIGNAL_FUNC(topic_cb), GINT_TO_POINTER(ONLINEPAGE_HOME));
532     gtk_box_pack_start(GTK_BOX(topic_to_fill), item_hb, FALSE, FALSE, 5);
533 #endif
534
535     /* topic updates */
536     topic_vb = welcome_topic_new("Updates", &topic_to_fill);
537     gtk_box_pack_start(GTK_BOX(column_vb), topic_vb, TRUE, TRUE, 0);
538
539     w = gtk_label_new("No updates available!");
540     gtk_box_pack_start(GTK_BOX(topic_to_fill), w, TRUE, TRUE, 0);
541
542
543     /* the end */
544     gtk_widget_show_all(welcome_vb);
545
546     gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(welcome_scrollw),
547                                           welcome_vb);
548     gtk_widget_show_all(welcome_scrollw);
549
550     return welcome_scrollw;
551 }
552 #else
553 GtkWidget *
554 welcome_new(void)
555 {
556     /* this is just a dummy to fill up window space, simply showing nothing */
557     return scrolled_window_new(NULL, NULL);
558 }
559 #endif
560
561