2 * Routines for capture file summary window
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
32 #include <epan/strutil.h>
34 #include <wiretap/wtap.h>
36 #include "../globals.h"
38 #include "../summary.h"
39 #include "../capture-pcap-util.h"
41 #include "../capture.h"
42 #include "ui/capture_globals.h"
44 #include "ui/gtk/main.h"
45 #include "ui/gtk/summary_dlg.h"
46 #include "ui/gtk/dlg_utils.h"
47 #include "ui/gtk/gui_utils.h"
48 #include "ui/gtk/help_dlg.h"
50 #define SUM_STR_MAX 1024
51 #define FILTER_SNIP_LEN 50
52 #define SHB_STR_SNIP_LEN 50
54 static GtkWidget *summary_dlg = NULL;
57 add_string_to_table_sensitive(GtkWidget *list, guint *row, const gchar *title, const gchar *value, gboolean sensitive)
62 if(strlen(value) != 0) {
63 indent = g_strdup_printf(" %s", title);
65 indent = g_strdup(title);
67 label = gtk_label_new(indent);
68 if (strlen(value) == 0) {
69 gchar *message = g_strdup_printf("<span weight=\"bold\">%s</span>", title);
70 gtk_label_set_markup(GTK_LABEL(label), message);
74 gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f);
75 gtk_widget_set_sensitive(label, sensitive);
76 gtk_table_attach_defaults(GTK_TABLE(list), label, 0, 1, *row, *row+1);
78 label = gtk_label_new(value);
79 gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f);
80 gtk_widget_set_sensitive(label, sensitive);
81 gtk_table_attach_defaults(GTK_TABLE(list), label, 1, 2, *row, *row+1);
87 add_string_to_table(GtkWidget *list, guint *row, const gchar *title, const gchar *value)
89 add_string_to_table_sensitive(list, row, title, value, TRUE);
94 add_string_to_list(GtkWidget *list, const gchar *title, gchar *captured, gchar *displayed, gchar *marked)
96 simple_list_append(list, 0, title, 1, captured, 2, displayed, 3, marked, -1);
100 time_to_string(char *string_buff, gulong string_buff_size, time_t ti_time)
105 /* calling localtime() on MSVC 2005 with huge values causes it to crash */
106 /* XXX - find the exact value that still does work */
107 /* XXX - using _USE_32BIT_TIME_T might be another way to circumvent this problem */
108 if (ti_time > 2000000000) {
112 ti_tm = localtime(&ti_time);
114 g_snprintf(string_buff, string_buff_size, "Not representable");
117 g_snprintf(string_buff, string_buff_size,
118 "%04d-%02d-%02d %02d:%02d:%02d",
119 ti_tm->tm_year + 1900,
128 summary_ok_cb(GtkWidget *w _U_, GtkWidget *view)
130 GtkTextBuffer *buffer;
131 GtkTextIter start_iter;
132 GtkTextIter end_iter;
133 gchar *new_comment = NULL;
135 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));
136 gtk_text_buffer_get_start_iter (buffer, &start_iter);
137 gtk_text_buffer_get_end_iter (buffer, &end_iter);
139 new_comment = gtk_text_buffer_get_text (buffer, &start_iter, &end_iter, FALSE /* whether to include invisible text */);
141 cf_update_capture_comment(&cfile, new_comment);
143 /* Update the main window */
144 main_update_for_unsaved_changes(&cfile);
146 window_destroy(summary_dlg);
150 summary_destroy_cb(GtkWidget *win _U_, gpointer user_data _U_)
152 /* Note that we no longer have a Summary dialog box. */
157 summary_open_cb(GtkWidget *w _U_, gpointer d _U_)
159 summary_tally summary;
160 GtkWidget *main_vb, *bbox, *cancel_bt, *ok_bt, *help_bt;
161 GtkWidget *table, *scrolled_window;
162 GtkWidget *list, *treeview;
163 GtkWidget *comment_view, *comment_frame, *comment_vbox;
164 GtkTextBuffer *buffer = NULL;
168 GtkCellRenderer *renderer;
169 GtkTreeViewColumn *column;
170 static const char *titles[] = { "Traffic", "Captured", "Displayed", "Marked" };
172 gchar string_buff[SUM_STR_MAX];
173 gchar string_buff2[SUM_STR_MAX];
174 gchar string_buff3[SUM_STR_MAX];
175 gchar string_buff4[SUM_STR_MAX];
176 gchar string_buff5[SUM_STR_MAX];
180 double marked_seconds;
187 unsigned int elapsed_time;
191 if (summary_dlg != NULL) {
192 /* There's already a Summary dialog box; reactivate it. */
193 reactivate_window(summary_dlg);
197 /* initial computations */
198 summary_fill_in(&cfile, &summary);
200 summary_fill_in_capture(&cfile, &global_capture_opts, &summary);
203 * Note: the start and stop times are initialized to 0, so if we
204 * have zero or one packets of the type in question that have
205 * time stamps, the elapsed times will be zero, just as if we
206 * have both start and stop time stamps but they're the same.
207 * That means we can avoid some checks for whether we have more
208 * than one packet of the type in question with time stamps.
210 seconds = summary.stop_time - summary.start_time;
211 disp_seconds = summary.filtered_stop - summary.filtered_start;
212 marked_seconds = summary.marked_stop - summary.marked_start;
214 summary_dlg = window_new(GTK_WINDOW_TOPLEVEL, "Wireshark: Summary");
216 /* Container for each row of widgets */
217 main_vb = ws_gtk_box_new(GTK_ORIENTATION_VERTICAL, 12, FALSE);
218 gtk_container_set_border_width(GTK_CONTAINER(main_vb), 12);
219 gtk_container_add(GTK_CONTAINER(summary_dlg), main_vb);
222 table = gtk_table_new(1, 2, FALSE);
223 gtk_table_set_col_spacings(GTK_TABLE(table), 6);
224 gtk_table_set_row_spacings(GTK_TABLE(table), 3);
225 gtk_box_pack_start(GTK_BOX(main_vb), table, TRUE, TRUE, 0);
230 add_string_to_table(table, &row, "File", "");
233 g_snprintf(string_buff, SUM_STR_MAX, "%s", summary.filename);
234 add_string_to_table(table, &row, "Name:", string_buff);
237 g_snprintf(string_buff, SUM_STR_MAX, "%" G_GINT64_MODIFIER "d bytes",
238 summary.file_length);
239 add_string_to_table(table, &row, "Length:", string_buff);
242 g_snprintf(string_buff, SUM_STR_MAX, "%s%s",
243 wtap_file_type_string(summary.file_type),
244 summary.iscompressed? " (gzip compressed)" : "");
245 add_string_to_table(table, &row, "Format:", string_buff);
248 if (summary.file_encap_type == WTAP_ENCAP_PER_PACKET) {
249 for (i = 0; i < summary.packet_encap_types->len; i++) {
250 g_snprintf(string_buff, SUM_STR_MAX, "%s",
251 wtap_encap_string(g_array_index(summary.packet_encap_types, int, i)));
252 add_string_to_table(table, &row, (i == 0) ? "Encapsulation:" : "",
256 g_snprintf(string_buff, SUM_STR_MAX, "%s", wtap_encap_string(summary.file_encap_type));
257 add_string_to_table(table, &row, "Encapsulation:", string_buff);
259 if (summary.has_snap) {
260 /* snapshot length */
261 g_snprintf(string_buff, SUM_STR_MAX, "%u bytes", summary.snap);
262 add_string_to_table(table, &row, "Packet size limit:", string_buff);
265 /* Capture file comment area */
266 comment_frame = gtk_frame_new("Capture file comments");
267 gtk_frame_set_shadow_type(GTK_FRAME(comment_frame), GTK_SHADOW_ETCHED_IN);
268 gtk_box_pack_start(GTK_BOX(main_vb), comment_frame, TRUE, TRUE, 0);
269 gtk_widget_show(comment_frame);
271 comment_vbox = ws_gtk_box_new(GTK_ORIENTATION_VERTICAL, 0, FALSE);
272 gtk_container_add(GTK_CONTAINER(comment_frame), comment_vbox);
273 gtk_widget_show(comment_vbox);
275 comment_view = gtk_text_view_new();
276 gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(comment_view), GTK_WRAP_WORD);
277 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (comment_view));
278 if(summary.opt_comment == NULL) {
279 gtk_text_buffer_set_text (buffer, "", -1);
281 buf_str = g_strdup_printf("%s", summary.opt_comment);
282 gtk_text_buffer_set_text (buffer, buf_str, -1);
285 gtk_box_pack_start(GTK_BOX(comment_vbox), comment_view, TRUE, TRUE, 0);
286 gtk_widget_show (comment_view);
289 * We must have no un-time-stamped packets (i.e., the number of
290 * time-stamped packets must be the same as the number of packets),
291 * and at least one time-stamped packet, in order for the start
292 * and stop times to be valid.
294 if (summary.packet_count_ts == summary.packet_count &&
295 summary.packet_count >= 1) {
297 add_string_to_table(table, &row, "", "");
298 add_string_to_table(table, &row, "Time", "");
301 time_to_string(string_buff, SUM_STR_MAX, (time_t)summary.start_time);
302 add_string_to_table(table, &row, "First packet:", string_buff);
305 time_to_string(string_buff, SUM_STR_MAX, (time_t)summary.stop_time);
306 add_string_to_table(table, &row, "Last packet:", string_buff);
309 * We must have at least two time-stamped packets for the elapsed time
312 if (summary.packet_count_ts >= 2) {
313 /* elapsed seconds */
314 elapsed_time = (unsigned int)summary.elapsed_time;
315 if(elapsed_time/86400) {
316 g_snprintf(string_buff, SUM_STR_MAX, "%02u days %02u:%02u:%02u",
317 elapsed_time/86400, elapsed_time%86400/3600, elapsed_time%3600/60, elapsed_time%60);
319 g_snprintf(string_buff, SUM_STR_MAX, "%02u:%02u:%02u",
320 elapsed_time%86400/3600, elapsed_time%3600/60, elapsed_time%60);
322 add_string_to_table(table, &row, "Elapsed:", string_buff);
327 add_string_to_table(table, &row, "", "");
328 add_string_to_table_sensitive(table, &row, "Capture", "", (summary.ifaces->len > 0));
329 if(summary.shb_hardware){
330 /* trucate the string to a reasonable length */
331 g_snprintf(string_buff, SHB_STR_SNIP_LEN, "%s",summary.shb_hardware);
332 add_string_to_table(table, &row, "Capture HW:",string_buff);
335 /* trucate the strings to a reasonable length */
336 g_snprintf(string_buff, SHB_STR_SNIP_LEN, "%s",summary.shb_os);
337 add_string_to_table(table, &row, "OS:", string_buff);
339 if(summary.shb_user_appl){
340 /* trucate the string to a reasonable length */
341 g_snprintf(string_buff, SHB_STR_SNIP_LEN, "%s",summary.shb_user_appl);
342 add_string_to_table(table, &row, "Capture application:", string_buff);
344 scrolled_window = gtk_scrolled_window_new (NULL, NULL);
345 gtk_container_set_border_width (GTK_CONTAINER (scrolled_window), 5);
346 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
347 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
348 gtk_widget_set_size_request(scrolled_window, -1, 120);
350 treeview = gtk_tree_view_new();
351 renderer = gtk_cell_renderer_text_new();
352 column = gtk_tree_view_column_new_with_attributes("Interface", renderer, "text", 0, NULL);
353 gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), column);
354 renderer = gtk_cell_renderer_text_new();
355 column = gtk_tree_view_column_new_with_attributes("Dropped Packets", renderer, "text", 1, NULL);
356 gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), column);
357 renderer = gtk_cell_renderer_text_new();
358 column = gtk_tree_view_column_new_with_attributes("Capture Filter", renderer, "text", 2, NULL);
359 gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), column);
360 renderer = gtk_cell_renderer_text_new();
361 column = gtk_tree_view_column_new_with_attributes("Link type", renderer, "text", 3, NULL);
362 gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), column);
363 renderer = gtk_cell_renderer_text_new();
364 column = gtk_tree_view_column_new_with_attributes("Packet size limit", renderer, "text", 4, NULL);
365 gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), column);
367 store = gtk_list_store_new(5, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
368 for (i = 0; i < summary.ifaces->len; i++) {
369 iface = g_array_index(summary.ifaces, iface_options, i);
372 g_snprintf(string_buff, SUM_STR_MAX, "%s", iface.descr);
373 } else if (iface.name) {
374 g_snprintf(string_buff, SUM_STR_MAX, "%s", iface.name);
376 g_snprintf(string_buff, SUM_STR_MAX, "unknown");
379 if (iface.drops_known) {
380 g_snprintf(string_buff2, SUM_STR_MAX, "%" G_GINT64_MODIFIER "u", iface.drops);
382 g_snprintf(string_buff2, SUM_STR_MAX, "unknown");
385 if (iface.cfilter && iface.cfilter[0] != '\0') {
386 g_snprintf(string_buff3, SUM_STR_MAX, "%s", iface.cfilter);
389 g_snprintf(string_buff3, SUM_STR_MAX, "none");
391 g_snprintf(string_buff3, SUM_STR_MAX, "unknown");
394 g_snprintf(string_buff4, SUM_STR_MAX, "%s", wtap_encap_string(iface.encap_type));
395 g_snprintf(string_buff5, SUM_STR_MAX, "%u bytes", iface.snap);
396 gtk_list_store_append(store, &iter);
397 gtk_list_store_set(store, &iter, 0, string_buff, 1, string_buff2, 2, string_buff3, 3, string_buff4, 4, string_buff5,-1);
399 gtk_tree_view_set_model(GTK_TREE_VIEW(treeview), GTK_TREE_MODEL(store));
400 g_object_unref (store);
401 gtk_container_add(GTK_CONTAINER(scrolled_window), treeview);
402 gtk_box_pack_start(GTK_BOX(main_vb), scrolled_window, TRUE, TRUE, 0);
403 gtk_widget_show_all(scrolled_window);
404 table = gtk_table_new(1, 2, FALSE);
405 gtk_table_set_col_spacings(GTK_TABLE(table), 6);
406 gtk_table_set_row_spacings(GTK_TABLE(table), 3);
407 gtk_box_pack_start(GTK_BOX(main_vb), table, TRUE, TRUE, 0);
412 add_string_to_table(table, &row, "", "");
413 add_string_to_table(table, &row, "Display", "");
415 if (summary.dfilter) {
417 /* limit each row to some reasonable length */
418 str_dup = g_strdup_printf("%s", summary.dfilter);
419 str_work = g_strdup(str_dup);
422 while(strlen(str_work) > FILTER_SNIP_LEN) {
423 str_work[FILTER_SNIP_LEN] = '\0';
424 add_string_to_table(table, &row, (snip == 0) ? "Display filter:" : "", str_work);
426 offset+=FILTER_SNIP_LEN;
427 str_work = g_strdup(&str_dup[offset]);
431 add_string_to_table(table, &row, (snip == 0) ? "Display filter:" : "", str_work);
436 add_string_to_table(table, &row, "Display filter:", "none");
439 /* Ignored packet count */
440 g_snprintf(string_buff, SUM_STR_MAX, "%i", summary.ignored_count);
441 add_string_to_table(table, &row, "Ignored packets:", string_buff);
444 list = simple_list_new(4, titles);
445 gtk_box_pack_start(GTK_BOX(main_vb), list, TRUE, TRUE, 0);
448 g_snprintf(string_buff, SUM_STR_MAX, "%i", summary.packet_count);
449 if (summary.dfilter) {
450 g_snprintf(string_buff2, SUM_STR_MAX, "%i", summary.filtered_count);
452 g_strlcpy(string_buff2, string_buff, SUM_STR_MAX);
454 g_snprintf(string_buff3, SUM_STR_MAX, "%i", summary.marked_count);
455 add_string_to_list(list, "Packets", string_buff, string_buff2, string_buff3);
457 /* Time between first and last */
459 g_snprintf(string_buff, SUM_STR_MAX, "%.3f sec", seconds);
461 string_buff[0] = '\0';
463 if (summary.dfilter && disp_seconds > 0) {
464 g_snprintf(string_buff2, SUM_STR_MAX, "%.3f sec", disp_seconds);
466 string_buff2[0] = '\0';
468 if (summary.marked_count && marked_seconds > 0) {
469 g_snprintf(string_buff3, SUM_STR_MAX, "%.3f sec", marked_seconds);
471 string_buff3[0] = '\0';
473 if (string_buff[0] != '\0' || string_buff2[0] != '\0' || string_buff3[0] != '\0')
474 add_string_to_list(list, "Between first and last packet", string_buff, string_buff2, string_buff3);
476 /* Packets per second */
478 g_snprintf(string_buff, SUM_STR_MAX, "%.3f", summary.packet_count/seconds);
480 string_buff[0] = '\0';
482 if(summary.dfilter && disp_seconds > 0) {
483 g_snprintf(string_buff2, SUM_STR_MAX, "%.3f", summary.filtered_count/disp_seconds);
485 string_buff2[0] = '\0';
487 if(summary.marked_count && marked_seconds > 0) {
488 g_snprintf(string_buff3, SUM_STR_MAX, "%.3f", summary.marked_count/marked_seconds);
490 string_buff3[0] = '\0';
492 if (string_buff[0] != '\0' || string_buff2[0] != '\0' || string_buff3[0] != '\0')
493 add_string_to_list(list, "Avg. packets/sec", string_buff, string_buff2, string_buff3);
496 if (summary.packet_count > 1) {
497 g_snprintf(string_buff, SUM_STR_MAX, "%.3f bytes",
498 /* MSVC cannot convert from unsigned __int64 to float, so first convert to signed __int64 */
499 (float) ((gint64) summary.bytes)/summary.packet_count);
501 string_buff[0] = '\0';
503 if (summary.dfilter && summary.filtered_count > 1) {
504 g_snprintf(string_buff2, SUM_STR_MAX, "%.3f bytes",
505 /* MSVC cannot convert from unsigned __int64 to float, so first convert to signed __int64 */
506 (float) ((gint64) summary.filtered_bytes)/summary.filtered_count);
508 string_buff2[0] = '\0';
510 if (summary.marked_count > 1) {
511 g_snprintf(string_buff3, SUM_STR_MAX, "%.3f bytes",
512 /* MSVC cannot convert from unsigned __int64 to float, so first convert to signed __int64 */
513 (float) ((gint64) summary.marked_bytes)/summary.marked_count);
515 string_buff3[0] = '\0';
517 if (string_buff[0] != '\0' || string_buff2[0] != '\0' || string_buff3[0] != '\0')
518 add_string_to_list(list, "Avg. packet size", string_buff, string_buff2, string_buff3);
521 g_snprintf(string_buff, SUM_STR_MAX, "%" G_GINT64_MODIFIER "u", summary.bytes);
522 if (summary.dfilter && summary.filtered_count > 0) {
523 g_snprintf(string_buff2, SUM_STR_MAX, "%" G_GINT64_MODIFIER "u", summary.filtered_bytes);
525 string_buff2[0] = '\0';
527 if (summary.marked_count) {
528 g_snprintf(string_buff3, SUM_STR_MAX, "%" G_GINT64_MODIFIER "u", summary.marked_bytes);
530 string_buff3[0] = '\0';
532 if (string_buff[0] != '\0' || string_buff2[0] != '\0' || string_buff3[0] != '\0')
533 add_string_to_list(list, "Bytes", string_buff, string_buff2, string_buff3);
535 /* Bytes per second */
537 /* MSVC cannot convert from unsigned __int64 to float, so first convert to signed __int64 */
538 g_snprintf(string_buff, SUM_STR_MAX, "%.3f", ((gint64) summary.bytes)/seconds);
540 string_buff[0] = '\0';
542 if (summary.dfilter && disp_seconds > 0) {
543 /* MSVC cannot convert from unsigned __int64 to float, so first convert to signed __int64 */
544 g_snprintf(string_buff2, SUM_STR_MAX, "%.3f", ((gint64) summary.filtered_bytes)/disp_seconds);
546 string_buff2[0] = '\0';
548 if (summary.marked_count && marked_seconds > 0) {
549 /* MSVC cannot convert from unsigned __int64 to float, so first convert to signed __int64 */
550 g_snprintf(string_buff3, SUM_STR_MAX, "%.3f", ((gint64) summary.marked_bytes)/marked_seconds);
552 string_buff3[0] = '\0';
554 if (string_buff[0] != '\0' || string_buff2[0] != '\0' || string_buff3[0] != '\0')
555 add_string_to_list(list, "Avg. bytes/sec", string_buff, string_buff2, string_buff3);
557 /* MBit per second */
559 g_snprintf(string_buff, SUM_STR_MAX, "%.3f",
560 /* MSVC cannot convert from unsigned __int64 to float, so first convert to signed __int64 */
561 ((gint64) summary.bytes) * 8.0 / (seconds * 1000.0 * 1000.0));
563 string_buff[0] = '\0';
565 if (summary.dfilter && disp_seconds > 0) {
566 g_snprintf(string_buff2, SUM_STR_MAX, "%.3f",
567 /* MSVC cannot convert from unsigned __int64 to float, so first convert to signed __int64 */
568 ((gint64) summary.filtered_bytes) * 8.0 / (disp_seconds * 1000.0 * 1000.0));
570 string_buff2[0] = '\0';
572 if (summary.marked_count && marked_seconds > 0) {
573 g_snprintf(string_buff3, SUM_STR_MAX, "%.3f",
574 /* MSVC cannot convert from unsigned __int64 to float, so first convert to signed __int64 */
575 ((gint64) summary.marked_bytes) * 8.0 / (marked_seconds * 1000.0 * 1000.0));
577 string_buff3[0] = '\0';
579 if (string_buff[0] != '\0' || string_buff2[0] != '\0' || string_buff3[0] != '\0')
580 add_string_to_list(list, "Avg. MBit/sec", string_buff, string_buff2, string_buff3);
584 bbox = dlg_button_row_new(GTK_STOCK_CANCEL, GTK_STOCK_OK, GTK_STOCK_HELP, NULL);
585 gtk_box_pack_start(GTK_BOX(main_vb), bbox, TRUE, TRUE, 0);
587 cancel_bt = g_object_get_data(G_OBJECT(bbox), GTK_STOCK_CANCEL);
588 window_set_cancel_button(summary_dlg, cancel_bt, window_cancel_button_cb);
590 ok_bt = g_object_get_data(G_OBJECT(bbox), GTK_STOCK_OK);
591 g_signal_connect (ok_bt, "clicked",
592 G_CALLBACK(summary_ok_cb), comment_view);
593 gtk_widget_grab_focus(ok_bt);
595 help_bt = g_object_get_data(G_OBJECT(bbox), GTK_STOCK_HELP);
596 g_signal_connect(help_bt, "clicked", G_CALLBACK(topic_cb), (gpointer)HELP_STATS_SUMMARY_DIALOG);
599 g_signal_connect(summary_dlg, "delete_event", G_CALLBACK(window_delete_event_cb), NULL);
600 g_signal_connect(summary_dlg, "destroy", G_CALLBACK(summary_destroy_cb), NULL);
602 gtk_widget_show_all(summary_dlg);
603 window_present(summary_dlg);