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