Decrease the refresh time to 100ms. This seems to make the splash
[obnox/wireshark/wip.git] / gtk / about_dlg.c
1 /* about_dlg.c
2  *
3  * $Id$
4  *
5  * Ulf Lamping <ulf.lamping@web.de>
6  *
7  * Wireshark - Network traffic analyzer
8  * By Gerald Combs <gerald@wireshark.org>
9  * Copyright 2000 Gerald Combs
10  *
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License
13  * as published by the Free Software Foundation; either version 2
14  * of the License, or (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
24  */
25
26 #ifdef HAVE_CONFIG_H
27 # include "config.h"
28 #endif
29
30 #include <gtk/gtk.h>
31 #include <string.h>
32
33 #include <epan/filesystem.h>
34 #include <epan/plugins.h>
35 #include "about_dlg.h"
36 #include "gui_utils.h"
37 #include "dlg_utils.h"
38 #include "file_dlg.h"
39 #include "compat_macros.h"
40 #include "globals.h"
41 #if GTK_MAJOR_VERSION >= 2 || GTK_MINOR_VERSION >= 3
42 #include "text_page.h"
43 #endif
44
45 #include "../image/wssplash.xpm"
46 #include "gtkglobals.h"
47 #include "version_info.h"
48 #include "main.h"
49 #include "plugins_dlg.h"
50
51 static void about_wireshark_destroy_cb(GtkWidget *, gpointer);
52
53
54 /*
55  * Keep a static pointer to the current "About Wireshark" window, if any, so
56  * that if somebody tries to do "About Wireshark" while there's already an
57  * "About Wireshark" window up, we just pop up the existing one, rather than
58  * creating a new one.
59  */
60 static GtkWidget *about_wireshark_w;
61
62
63 static void
64 about_wireshark(GtkWidget *parent, GtkWidget *main_vb, const char *title)
65 {
66   GtkWidget   *msg_label, *icon;
67 #if GTK_MAJOR_VERSION >= 2
68   gchar       *message;
69 #endif
70
71   icon = xpm_to_widget_from_parent(parent, wssplash_xpm);
72   gtk_container_add(GTK_CONTAINER(main_vb), icon);
73
74   msg_label = gtk_label_new(title);
75 #if GTK_MAJOR_VERSION >= 2
76   message = g_strdup_printf("<span size=\"x-large\" weight=\"bold\">%s</span>", title);
77   gtk_label_set_markup(GTK_LABEL(msg_label), message);
78   g_free(message);
79 #endif
80   gtk_container_add(GTK_CONTAINER(main_vb), msg_label);
81 }
82
83 static void
84 splash_update_label(GtkWidget *win, char *message)
85 {
86     GtkWidget *main_lb;
87
88     if (win == NULL) return;
89
90     main_lb = OBJECT_GET_DATA(win, "splash_label");
91     gtk_label_set_text(GTK_LABEL(main_lb), message);
92
93     /* Process all pending GUI events before continuing, so that
94        the splash screen window gets updated. */
95     while (gtk_events_pending()) gtk_main_iteration();
96 }
97
98 GtkWidget*
99 splash_new(char *message)
100 {
101     GtkWidget *win;
102     GtkWidget *main_lb;
103
104     GtkWidget *main_vb;
105     GtkWidget *percentage_hb;
106     GtkWidget *prog_bar;
107     GtkWidget *percentage_lb;
108
109     win = splash_window_new();
110
111     /* When calling about_wireshark(), we must realize the top-level
112        widget for the window, otherwise GTK will throw a warning
113        because we don't have a colormap associated with that window and
114        can't handle the pixmap. */
115     gtk_widget_realize(win);
116
117     main_vb = gtk_vbox_new(FALSE, 6);
118     gtk_container_border_width(GTK_CONTAINER(main_vb), 24);
119     gtk_container_add(GTK_CONTAINER(win), main_vb);
120
121     about_wireshark(win, main_vb, "Network Protocol Analyzer");
122
123     main_lb = gtk_label_new(message);
124     gtk_container_add(GTK_CONTAINER(main_vb), main_lb);
125     OBJECT_SET_DATA(win, "splash_label", main_lb);
126
127     main_lb = gtk_label_new("");
128     gtk_container_add(GTK_CONTAINER(main_vb), main_lb);
129     OBJECT_SET_DATA(win, "protocol_label", main_lb);
130
131     percentage_hb = gtk_hbox_new(FALSE, 1);
132     gtk_box_pack_start(GTK_BOX(main_vb), percentage_hb, FALSE, TRUE, 3);
133
134     prog_bar = gtk_progress_bar_new();
135 #if GTK_MAJOR_VERSION < 2
136     gtk_progress_set_activity_mode(GTK_PROGRESS(prog_bar), FALSE);
137 #endif
138     gtk_box_pack_start(GTK_BOX(percentage_hb), prog_bar, FALSE, TRUE, 3);
139     OBJECT_SET_DATA(win, "progress_bar", prog_bar);
140
141     percentage_lb = gtk_label_new("  0%");
142     gtk_misc_set_alignment(GTK_MISC(percentage_lb), 0.0, 0.0);
143     gtk_box_pack_start(GTK_BOX(percentage_hb), percentage_lb, FALSE, TRUE, 3);
144     OBJECT_SET_DATA(win, "percentage_label", percentage_lb);
145
146     gtk_widget_show_all(win);
147
148     splash_update_label(win, message);
149
150     return win;
151 }
152
153 #define REGISTER_FREQ 100 /* Milliseconds */
154
155 void
156 splash_update(register_action_e action, char *message, gpointer client_data)
157 {
158     GtkWidget *win;
159     GtkWidget *main_lb;
160     GtkWidget *prog_bar;
161     GtkWidget *percentage_lb;
162     gfloat    percentage;
163     gulong    ul_percentage;
164     gchar     tmp[100];
165     char      *action_msg;
166
167     static gulong ul_sofar = 0;
168     static gulong ul_count = 0;
169
170     static register_action_e last_action = RA_NONE;
171
172     static GTimeVal cur_tv;
173     static GTimeVal next_tv = {0, 0};
174
175     win = (GtkWidget *)client_data;
176
177     if (win == NULL) return;
178
179     g_get_current_time(&cur_tv);
180     if (cur_tv.tv_sec <= next_tv.tv_sec && cur_tv.tv_usec <= next_tv.tv_usec && ul_sofar < ul_count - 1) {
181       /* Only update every REGISTER_FREQ milliseconds */
182       ul_sofar++;
183       return;
184     }
185     memcpy(&next_tv, &cur_tv, sizeof(next_tv));
186     next_tv.tv_usec += REGISTER_FREQ * 1000;
187     if (next_tv.tv_usec >= 1000000) {
188         next_tv.tv_sec++;
189         next_tv.tv_usec -= 1000000;
190     }
191
192     if(last_action != action) {
193       /* the action has changed */
194       switch(action) {
195       case RA_DISSECTORS:
196         action_msg = "Initializing dissectors ...";
197         break;
198       case RA_LISTENERS:
199         action_msg = "Initializing tap listeners ...";
200         break;
201       case RA_REGISTER:
202         action_msg = "Registering dissector ...";
203         break;
204       case RA_PLUGIN_REGISTER:
205         action_msg = "Registering plugins ...";
206         break;
207       case RA_HANDOFF:
208         action_msg = "Handing off dissector ...";
209         break;
210       case RA_PLUGIN_HANDOFF:
211         action_msg = "Handing off plugins ...";
212         break;
213       case RA_PREFERENCES:
214         action_msg = "Loading module preferences ...";
215         break;
216       case RA_CONFIGURATION:
217         action_msg = "Loading configuration files ...";
218         break;
219       default:
220         action_msg = "(Unknown action)";;
221         break;
222       }
223       splash_update_label(win, action_msg);
224       last_action = action;
225     }
226
227     if(ul_count == 0) /* get the count of dissectors */
228       ul_count = register_count() + 6; /* additional 6 for:
229                                           dissectors, listeners,
230                                           registering plugins, handingoff plugins,
231                                           preferences and configuration */
232
233     main_lb = OBJECT_GET_DATA(win, "protocol_label");
234     /* make_dissector_reg.py changed -
235        so we need to strip off the leading elements to get back to the protocol */
236     if(message) {
237       if(!strncmp(message, "proto_register_", 15))
238         message += 15;
239       else if(!strncmp(message, "proto_reg_handoff_", 18))
240         message += 18;
241     }
242     gtk_label_set_text(GTK_LABEL(main_lb), message ? message : "");
243
244     ul_sofar++;
245
246     g_assert (ul_sofar <= ul_count);
247
248     percentage = (gfloat)ul_sofar/(gfloat)ul_count;
249     ul_percentage = (gulong)(percentage * 100);
250
251     /* update progress bar */
252     prog_bar = OBJECT_GET_DATA(win, "progress_bar");
253 #if GTK_MAJOR_VERSION < 2
254     gtk_progress_bar_update(GTK_PROGRESS_BAR(prog_bar), percentage);
255 #else
256     gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(prog_bar), percentage);
257 #endif
258
259     percentage_lb = OBJECT_GET_DATA(win, "percentage_label");
260     g_snprintf(tmp, sizeof(tmp), "%lu%%", ul_percentage);
261     gtk_label_set_text((GtkLabel*)percentage_lb, tmp);
262
263     /* Process all pending GUI events before continuing, so that
264        the splash screen window gets updated. */
265     while (gtk_events_pending()) gtk_main_iteration();
266
267 }
268
269 guint
270 splash_destroy(GtkWidget *win)
271 {
272     if (win == NULL) return FALSE;
273
274     gtk_widget_destroy(win);
275     return FALSE;
276 }
277
278
279 static GtkWidget *
280 about_wireshark_page_new(void)
281 {
282   GtkWidget   *main_vb, *msg_label /*, *icon*/;
283   gchar       *message;
284   const char   title[] = "Network Protocol Analyzer";
285
286   main_vb = gtk_vbox_new(FALSE, 6);
287   gtk_container_border_width(GTK_CONTAINER(main_vb), 12);
288
289   about_wireshark(top_level, main_vb, title);
290
291   /* Construct the message string */
292   message = g_strdup_printf(
293        "Version " VERSION "%s\n"
294        "\n"
295        "%s"
296        "\n"
297        "%s"
298        "\n"
299        "%s"
300        "\n"
301        "Wireshark is Open Source Software released under the GNU General Public License.\n"
302        "\n"
303        "Check the man page and http://www.wireshark.org for more information.",
304        wireshark_svnversion, get_copyright_info(), comp_info_str->str,
305        runtime_info_str->str);
306
307   msg_label = gtk_label_new(message);
308   g_free(message);
309   gtk_label_set_justify(GTK_LABEL(msg_label), GTK_JUSTIFY_FILL);
310 #if GTK_MAJOR_VERSION >= 2
311   gtk_label_set_selectable(GTK_LABEL(msg_label), TRUE);
312 #endif
313   gtk_container_add(GTK_CONTAINER(main_vb), msg_label);
314
315   return main_vb;
316 }
317
318 #if GTK_MAJOR_VERSION >= 2 || GTK_MINOR_VERSION >= 3
319 static GtkWidget *
320 about_authors_page_new(void)
321 {
322   GtkWidget   *page;
323   char *absolute_path;
324
325   absolute_path = get_datafile_path("AUTHORS-SHORT");
326   page = text_page_new(absolute_path);
327
328   return page;
329 }
330 #endif
331
332 static void
333 about_folders_row(GtkWidget *table, const char *label, const char *dir, const char *tip)
334 {
335   simple_list_append(table, 0, label, 1, dir, 2, tip, -1);
336 }
337
338
339 static GtkWidget *
340 about_folders_page_new(void)
341 {
342   GtkWidget   *table;
343   const char *constpath;
344   char *path;
345   const gchar *titles[] = { "Name", "Folder", "Typical Files"};
346   GtkWidget *scrolledwindow;
347
348   scrolledwindow = scrolled_window_new(NULL, NULL);
349 #if GTK_MAJOR_VERSION >= 2
350   gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolledwindow),
351                                    GTK_SHADOW_IN);
352 #endif
353
354   /* Container for our data */
355   table = simple_list_new(3, titles);
356
357   /* "file open" */
358   about_folders_row(table, "\"File\" dialogs", get_last_open_dir(),
359       "capture files");
360
361   /* temp */
362   path = get_tempfile_path("");
363   about_folders_row(table, "Temp", path,
364       "untitled capture files");
365   g_free((void *) path);
366
367   /* pers conf */
368   path = get_persconffile_path("", FALSE);
369   about_folders_row(table, "Personal configuration", path,
370       "\"dfilters\", \"preferences\", \"ethers\", ...");
371   g_free((void *) path);
372
373   /* global conf */
374   constpath = get_datafile_dir();
375   if (constpath != NULL) {
376     about_folders_row(table, "Global configuration", constpath,
377         "\"dfilters\", \"preferences\", \"manuf\", ...");
378   }
379
380   /* system */
381   constpath = get_systemfile_dir();
382   about_folders_row(table, "System", constpath,
383       "\"ethers\", \"ipxnets\"");
384
385   /* program */
386   constpath = get_progfile_dir();
387   about_folders_row(table, "Program", constpath,
388       "program files");
389
390 #ifdef HAVE_PLUGINS
391   /* pers plugins */
392   path = get_plugins_pers_dir();
393   about_folders_row(table, "Personal Plugins", path,
394       "dissector plugins");
395   g_free((void *) path);
396
397   /* global plugins */
398   about_folders_row(table, "Global Plugins", get_plugin_dir(),
399       "dissector plugins");
400 #endif
401
402   gtk_container_add(GTK_CONTAINER(scrolledwindow), table);
403
404   return scrolledwindow;
405 }
406
407 #if GTK_MAJOR_VERSION >= 2 || GTK_MINOR_VERSION >= 3
408 static GtkWidget *
409 about_license_page_new(void)
410 {
411   GtkWidget   *page;
412   char *absolute_path;
413
414   absolute_path = get_datafile_path("COPYING");
415   page = text_page_new(absolute_path);
416
417   return page;
418 }
419 #endif
420
421 void
422 about_wireshark_cb( GtkWidget *w _U_, gpointer data _U_ )
423 {
424   GtkWidget   *main_vb, *main_nb, *bbox, *ok_btn;
425
426   GtkWidget   *page_lb, *about_page, *folders_page, *plugins_page;
427 #if GTK_MAJOR_VERSION >= 2 || GTK_MINOR_VERSION >= 3
428   GtkWidget   *authors_page, *license_page;
429 #endif
430
431   if (about_wireshark_w != NULL) {
432     /* There's already an "About Wireshark" dialog box; reactivate it. */
433     reactivate_window(about_wireshark_w);
434     return;
435   }
436
437   /*
438    * XXX - use GtkDialog?  The GNOME 2.x GnomeAbout widget does.
439    * Should we use GtkDialog for simple_dialog() as well?  Or
440    * is the GTK+ 2.x GtkDialog appropriate but the 1.2[.x] one
441    * not?  (The GNOME 1.x GnomeAbout widget uses GnomeDialog.)
442    */
443   about_wireshark_w = dlg_window_new("About Wireshark");
444   /* set the initial position (must be done, before show is called!) */
445   /* default position is not appropriate for the about dialog */
446 #if GTK_MAJOR_VERSION >= 2
447   gtk_window_set_position(GTK_WINDOW(about_wireshark_w), GTK_WIN_POS_CENTER_ON_PARENT);
448 #else
449   gtk_window_set_position(GTK_WINDOW(about_wireshark_w), GTK_WIN_POS_CENTER);
450 #endif
451   /* setting the size is dangerous here, as making it too short will
452    * clip content on GTK1, so simply use the natural size */
453   /*gtk_window_set_default_size(GTK_WINDOW(about_wireshark_w), 600, 400);*/
454   gtk_container_border_width(GTK_CONTAINER(about_wireshark_w), 6);
455
456   main_vb = gtk_vbox_new(FALSE, 12);
457   gtk_container_border_width(GTK_CONTAINER(main_vb), 6);
458   gtk_container_add(GTK_CONTAINER(about_wireshark_w), main_vb);
459
460   main_nb = gtk_notebook_new();
461   gtk_box_pack_start(GTK_BOX(main_vb), main_nb, TRUE, TRUE, 0);
462
463   about_page = about_wireshark_page_new();
464   page_lb = gtk_label_new("Wireshark");
465   gtk_notebook_append_page(GTK_NOTEBOOK(main_nb), about_page, page_lb);
466
467 #if GTK_MAJOR_VERSION >= 2 || GTK_MINOR_VERSION >= 3
468   authors_page = about_authors_page_new();
469   page_lb = gtk_label_new("Authors");
470   gtk_notebook_append_page(GTK_NOTEBOOK(main_nb), authors_page, page_lb);
471 #endif
472
473   folders_page = about_folders_page_new();
474   page_lb = gtk_label_new("Folders");
475   gtk_notebook_append_page(GTK_NOTEBOOK(main_nb), folders_page, page_lb);
476
477 #ifdef HAVE_PLUGINS
478   plugins_page = about_plugins_page_new();
479   page_lb = gtk_label_new("Plugins");
480   gtk_notebook_append_page(GTK_NOTEBOOK(main_nb), plugins_page, page_lb);
481 #endif
482
483 #if GTK_MAJOR_VERSION >= 2 || GTK_MINOR_VERSION >= 3
484   license_page = about_license_page_new();
485   page_lb = gtk_label_new("License");
486   /* set a minmum width to avoid a lot of line breaks at the wrong places */
487   WIDGET_SET_SIZE(license_page, 600, -1);
488   gtk_notebook_append_page(GTK_NOTEBOOK(main_nb), license_page, page_lb);
489 #endif
490
491   /* Button row */
492   bbox = dlg_button_row_new(GTK_STOCK_OK, NULL);
493   gtk_box_pack_start(GTK_BOX(main_vb), bbox, FALSE, FALSE, 0);
494
495   ok_btn = OBJECT_GET_DATA(bbox, GTK_STOCK_OK);
496   gtk_widget_grab_focus(ok_btn);
497   gtk_widget_grab_default(ok_btn);
498   window_set_cancel_button(about_wireshark_w, ok_btn, window_cancel_button_cb);
499
500   SIGNAL_CONNECT(about_wireshark_w, "delete_event", window_delete_event_cb, NULL);
501   SIGNAL_CONNECT(about_wireshark_w, "destroy", about_wireshark_destroy_cb, NULL);
502
503   gtk_widget_show_all(about_wireshark_w);
504   window_present(about_wireshark_w);
505 }
506
507 static void
508 about_wireshark_destroy_cb(GtkWidget *win _U_, gpointer user_data _U_)
509 {
510   /* Note that we no longer have an "About Wireshark" dialog box. */
511   about_wireshark_w = NULL;
512 }
513
514