From Graeme Hewson:
authorguy <guy@f5534014-38df-0310-8fa8-9805f1628bb7>
Tue, 30 Jul 2002 10:13:16 +0000 (10:13 +0000)
committerguy <guy@f5534014-38df-0310-8fa8-9805f1628bb7>
Tue, 30 Jul 2002 10:13:16 +0000 (10:13 +0000)
Ethereal sometimes creates a progress dialog bar and then, if
the processing is fast, quickly destroys it.  The resulting
"flash" can be disconcerting.  This set of patches ensures a
progress bar is either not created or is displayed for a minimum
time.

git-svn-id: http://anonsvn.wireshark.org/wireshark/trunk@5916 f5534014-38df-0310-8fa8-9805f1628bb7

AUTHORS
file.c
gtk/progress_dlg.c
progress_dlg.h
proto_hier_stats.c

diff --git a/AUTHORS b/AUTHORS
index 4b5605a3089022f8895aa0a3ba0dbf4f831ae9be..696039ca00d09a1d3059a409e67263a2a60589aa 100644 (file)
--- a/AUTHORS
+++ b/AUTHORS
@@ -913,6 +913,7 @@ Graeme Hewson <graeme.hewson[AT]oracle.com> {
        Add some sanity checks to DNS dissector to avoid loops
        Command-line interface cleanups
        Varargs code cleanup in "simple_dialog.c"
+       Make dialog box pop up only after a minimum period of time
 }
 
 Pasi Eronen <pasi.eronen[at]nixu.com> {
diff --git a/file.c b/file.c
index 995ceb77f536f2ebc99df6019eb39667b20f6731..b50c929ef0c149f43d0294853ed8c48badec4b2a 100644 (file)
--- a/file.c
+++ b/file.c
@@ -1,7 +1,7 @@
 /* file.c
  * File I/O routines
  *
- * $Id: file.c,v 1.283 2002/07/21 16:54:22 sharpe Exp $
+ * $Id: file.c,v 1.284 2002/07/30 10:13:14 guy Exp $
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@ethereal.com>
@@ -317,12 +317,13 @@ read_cap_file(capture_file *cf, int *err)
   char        errmsg_errno[1024+1];
   gchar       err_str[2048+1];
   long        data_offset;
-  progdlg_t  *progbar;
+  progdlg_t  *progbar = NULL;
   gboolean    stop_flag;
   int         file_pos;
   float       prog_val;
   int         fd;
   struct stat cf_stat;
+  GTimeVal    start_time;
 
   name_ptr = get_basename(cf->filename);
 
@@ -344,8 +345,7 @@ read_cap_file(capture_file *cf, int *err)
   freeze_clist(cf);
 
   stop_flag = FALSE;
-  progbar = create_progress_dlg(load_msg, "Stop", &stop_flag);
-  g_free(load_msg);
+  g_get_current_time(&start_time);
 
   while ((wtap_read(cf->wth, err, &data_offset))) {
     /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
@@ -371,7 +371,15 @@ read_cap_file(capture_file *cf, int *err)
           if (prog_val > 1.0)
             prog_val = 1.0;
         }
-        update_progress_dlg(progbar, prog_val);
+        if (progbar == NULL) {
+          /* Create the progress bar if necessary */
+          progbar = delayed_create_progress_dlg(load_msg, "Stop",
+            &stop_flag, &start_time, prog_val);
+          if (progbar != NULL)
+            g_free(load_msg);
+        }
+        if (progbar != NULL)
+          update_progress_dlg(progbar, prog_val);
         cf->progbar_nextstep += cf->progbar_quantum;
     }
 
@@ -388,8 +396,11 @@ read_cap_file(capture_file *cf, int *err)
     read_packet(cf, data_offset);
   }
 
-  /* We're done reading the file; destroy the progress bar. */
-  destroy_progress_dlg(progbar);
+  /* We're done reading the file; destroy the progress bar if it was created. */
+  if (progbar == NULL)
+    g_free(load_msg);
+  else
+    destroy_progress_dlg(progbar);
 
   /* We're done reading sequentially through the file. */
   cf->state = FILE_READ_DONE;
@@ -911,15 +922,15 @@ rescan_packets(capture_file *cf, const char *action, gboolean refilter,
                gboolean redissect)
 {
   frame_data *fdata;
-  progdlg_t *progbar;
-  gboolean stop_flag;
-  guint32 progbar_quantum;
-  guint32 progbar_nextstep;
-  unsigned int count;
-  int err;
+  progdlg_t  *progbar = NULL;
+  gboolean    stop_flag;
+  long        count;
+  int         err;
   frame_data *selected_frame;
-  int selected_row;
-  int row;
+  int         selected_row;
+  int         row;
+  float       prog_val;
+  GTimeVal    start_time;
 
   /* Which frame, if any, is the currently selected frame?
      XXX - should the selected frame or the focus frame be the "current"
@@ -961,15 +972,15 @@ rescan_packets(capture_file *cf, const char *action, gboolean refilter,
   prevusec = 0;
 
   /* Update the progress bar when it gets to this value. */
-  progbar_nextstep = 0;
+  cf->progbar_nextstep = 0;
   /* When we reach the value that triggers a progress bar update,
      bump that value by this amount. */
-  progbar_quantum = cf->count/N_PROGBAR_UPDATES;
+  cf->progbar_quantum = cf->count/N_PROGBAR_UPDATES;
   /* Count of packets at which we've looked. */
   count = 0;
 
   stop_flag = FALSE;
-  progbar = create_progress_dlg(action, "Stop", &stop_flag);
+  g_get_current_time(&start_time);
 
   for (fdata = cf->plist; fdata != NULL; fdata = fdata->next) {
     /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
@@ -977,15 +988,22 @@ rescan_packets(capture_file *cf, const char *action, gboolean refilter,
        to repaint what's pending, and doing so may involve an "ioctl()"
        to see if there's any pending input from an X server, and doing
        that for every packet can be costly, especially on a big file. */
-    if (count >= progbar_nextstep) {
+    if (count >= cf->progbar_nextstep) {
       /* let's not divide by zero. I should never be started
        * with count == 0, so let's assert that
        */
       g_assert(cf->count > 0);
+      prog_val = (gfloat) count / cf->count;
 
-      update_progress_dlg(progbar, (gfloat) count / cf->count);
+      if (progbar == NULL)
+        /* Create the progress bar if necessary */
+        progbar = delayed_create_progress_dlg(action, "Stop", &stop_flag,
+          &start_time, prog_val);
 
-      progbar_nextstep += progbar_quantum;
+      if (progbar != NULL)
+        update_progress_dlg(progbar, prog_val);
+
+      cf->progbar_nextstep += cf->progbar_quantum;
     }
 
     if (stop_flag) {
@@ -1047,8 +1065,10 @@ rescan_packets(capture_file *cf, const char *action, gboolean refilter,
     }
   }
 
-  /* We're done filtering the packets; destroy the progress bar. */
-  destroy_progress_dlg(progbar);
+  /* We're done filtering the packets; destroy the progress bar if it
+     was created. */
+  if (progbar != NULL)
+    destroy_progress_dlg(progbar);
 
   /* Unfreeze the packet list. */
   gtk_clist_thaw(GTK_CLIST(packet_list));
@@ -1071,11 +1091,9 @@ print_packets(capture_file *cf, print_args_t *print_args)
 {
   int         i;
   frame_data *fdata;
-  progdlg_t  *progbar;
+  progdlg_t  *progbar = NULL;
   gboolean    stop_flag;
-  guint32     progbar_quantum;
-  guint32     progbar_nextstep;
-  guint32     count;
+  long        count;
   int         err;
   gint       *col_widths = NULL;
   gint        data_width;
@@ -1086,6 +1104,8 @@ print_packets(capture_file *cf, print_args_t *print_args)
   int         column_len;
   int         line_len;
   epan_dissect_t *edt = NULL;
+  float       prog_val;
+  GTimeVal    start_time;
 
   cf->print_fh = open_print_dest(print_args->to_file, print_args->dest);
   if (cf->print_fh == NULL)
@@ -1144,15 +1164,15 @@ print_packets(capture_file *cf, print_args_t *print_args)
   print_separator = FALSE;
 
   /* Update the progress bar when it gets to this value. */
-  progbar_nextstep = 0;
+  cf->progbar_nextstep = 0;
   /* When we reach the value that triggers a progress bar update,
      bump that value by this amount. */
-  progbar_quantum = cf->count/N_PROGBAR_UPDATES;
+  cf->progbar_quantum = cf->count/N_PROGBAR_UPDATES;
   /* Count of packets at which we've looked. */
   count = 0;
 
   stop_flag = FALSE;
-  progbar = create_progress_dlg("Printing", "Stop", &stop_flag);
+  g_get_current_time(&start_time);
 
   /* Iterate through the list of packets, printing the packets that
      were selected by the current display filter.  */
@@ -1162,15 +1182,22 @@ print_packets(capture_file *cf, print_args_t *print_args)
        to repaint what's pending, and doing so may involve an "ioctl()"
        to see if there's any pending input from an X server, and doing
        that for every packet can be costly, especially on a big file. */
-    if (count >= progbar_nextstep) {
+    if (count >= cf->progbar_nextstep) {
       /* let's not divide by zero. I should never be started
        * with count == 0, so let's assert that
        */
       g_assert(cf->count > 0);
+      prog_val = (gfloat) count / cf->count;
 
-      update_progress_dlg(progbar, (gfloat) count / cf->count);
+      if (progbar == NULL)
+        /* Create the progress bar if necessary */
+        progbar = delayed_create_progress_dlg("Printing", "Stop", &stop_flag,
+          &start_time, prog_val);
 
-      progbar_nextstep += progbar_quantum;
+      if (progbar != NULL)
+        update_progress_dlg(progbar, prog_val);
+
+      cf->progbar_nextstep += cf->progbar_quantum;
     }
 
     if (stop_flag) {
@@ -1250,8 +1277,10 @@ print_packets(capture_file *cf, print_args_t *print_args)
     }
   }
 
-  /* We're done printing the packets; destroy the progress bar. */
-  destroy_progress_dlg(progbar);
+  /* We're done printing the packets; destroy the progress bar if
+     it was created. */
+  if (progbar != NULL)
+    destroy_progress_dlg(progbar);
 
   if (col_widths != NULL)
     g_free(col_widths);
@@ -1274,14 +1303,14 @@ void
 change_time_formats(capture_file *cf)
 {
   frame_data *fdata;
-  progdlg_t *progbar;
-  gboolean stop_flag;
-  guint32 progbar_quantum;
-  guint32 progbar_nextstep;
-  unsigned int count;
-  int row;
-  int i;
-  GtkStyle  *pl_style;
+  progdlg_t  *progbar = NULL;
+  gboolean    stop_flag;
+  long        count;
+  int         row;
+  int         i;
+  GtkStyle   *pl_style;
+  float       prog_val;
+  GTimeVal    start_time;
 
   /* Are there any columns with time stamps in the "command-line-specified"
      format?
@@ -1300,15 +1329,15 @@ change_time_formats(capture_file *cf)
   freeze_clist(cf);
 
   /* Update the progress bar when it gets to this value. */
-  progbar_nextstep = 0;
+  cf->progbar_nextstep = 0;
   /* When we reach the value that triggers a progress bar update,
      bump that value by this amount. */
-  progbar_quantum = cf->count/N_PROGBAR_UPDATES;
+  cf->progbar_quantum = cf->count/N_PROGBAR_UPDATES;
   /* Count of packets at which we've looked. */
   count = 0;
 
   stop_flag = FALSE;
-  progbar = create_progress_dlg("Changing time display", "Stop", &stop_flag);
+  g_get_current_time(&start_time);
 
   /* Iterate through the list of packets, checking whether the packet
      is in a row of the summary list and, if so, whether there are
@@ -1320,15 +1349,23 @@ change_time_formats(capture_file *cf)
        to repaint what's pending, and doing so may involve an "ioctl()"
        to see if there's any pending input from an X server, and doing
        that for every packet can be costly, especially on a big file. */
-    if (count >= progbar_nextstep) {
+    if (count >= cf->progbar_nextstep) {
       /* let's not divide by zero. I should never be started
        * with count == 0, so let's assert that
        */
       g_assert(cf->count > 0);
 
-      update_progress_dlg(progbar, (gfloat) count / cf->count);
+      prog_val = (gfloat) count / cf->count;
 
-      progbar_nextstep += progbar_quantum;
+      if (progbar == NULL)
+        /* Create the progress bar if necessary */
+        progbar = delayed_create_progress_dlg("Changing time display", "Stop",
+          &stop_flag, &start_time, prog_val);
+
+      if (progbar != NULL)
+        update_progress_dlg(progbar, prog_val);
+
+      cf->progbar_nextstep += cf->progbar_quantum;
     }
 
     if (stop_flag) {
@@ -1361,8 +1398,10 @@ change_time_formats(capture_file *cf)
     }
   }
 
-  /* We're done redisplaying the packets; destroy the progress bar. */
-  destroy_progress_dlg(progbar);
+  /* We're done redisplaying the packets; destroy the progress bar if it
+     was created. */
+  if (progbar != NULL)
+    destroy_progress_dlg(progbar);
 
   /* Set the column widths of those columns that show the time in
      "command-line-specified" format. */
@@ -1384,15 +1423,15 @@ find_packet(capture_file *cf, dfilter_t *sfcode)
   frame_data *start_fd;
   frame_data *fdata;
   frame_data *new_fd = NULL;
-  progdlg_t *progbar = NULL;
-  gboolean stop_flag;
-  guint32 progbar_quantum;
-  guint32 progbar_nextstep;
-  unsigned int count;
-  int err;
-  gboolean frame_matched;
-  int row;
+  progdlg_t  *progbar = NULL;
+  gboolean    stop_flag;
+  long        count;
+  int         err;
+  gboolean    frame_matched;
+  int         row;
   epan_dissect_t       *edt;
+  float       prog_val;
+  GTimeVal    start_time;
 
   start_fd = cf->current_frame;
   if (start_fd != NULL)  {
@@ -1402,18 +1441,13 @@ find_packet(capture_file *cf, dfilter_t *sfcode)
     count = 0;
     fdata = start_fd;
 
-    /* Update the progress bar when it gets to this value.  We start at
-       20, not 0, so that we don't get a progress bar until we've
-       checked at least that many frames, so that a very quick search
-       doesn't pop up and immediately destroy a progress bar.
-
-       XXX - should use a timer?  Like 50 ms. */
-    progbar_nextstep = 20;
+    cf->progbar_nextstep = 0;
     /* When we reach the value that triggers a progress bar update,
        bump that value by this amount. */
-    progbar_quantum = cf->count/N_PROGBAR_UPDATES;
+    cf->progbar_quantum = cf->count/N_PROGBAR_UPDATES;
 
     stop_flag = FALSE;
+    g_get_current_time(&start_time);
 
     fdata = start_fd;
     for (;;) {
@@ -1422,21 +1456,23 @@ find_packet(capture_file *cf, dfilter_t *sfcode)
          to repaint what's pending, and doing so may involve an "ioctl()"
          to see if there's any pending input from an X server, and doing
          that for every packet can be costly, especially on a big file. */
-      if (count >= progbar_nextstep) {
+      if (count >= cf->progbar_nextstep) {
         /* let's not divide by zero. I should never be started
          * with count == 0, so let's assert that
          */
         g_assert(cf->count > 0);
 
-        /* Create the progress bar if it doesn't exist; we don't create it
-           immediately, so that we don't have it appear and immediately
-           disappear if the search is quick. */
+        prog_val = (gfloat) count / cf->count;
+
+        /* Create the progress bar if necessary */
         if (progbar == NULL)
-           progbar = create_progress_dlg("Searching", "Cancel", &stop_flag);
+           progbar = delayed_create_progress_dlg("Searching", "Cancel",
+             &stop_flag, &start_time, prog_val);
         
-        update_progress_dlg(progbar, (gfloat) count / cf->count);
+        if (progbar != NULL)
+          update_progress_dlg(progbar, prog_val);
 
-        progbar_nextstep += progbar_quantum;
+        cf->progbar_nextstep += cf->progbar_quantum;
       }
 
       if (stop_flag) {
@@ -1485,8 +1521,8 @@ find_packet(capture_file *cf, dfilter_t *sfcode)
       }
     }
 
-    /* We're done scanning the packets; destroy the progress bar, if
-       we created it. */
+    /* We're done scanning the packets; destroy the progress bar if it
+       was created. */
     if (progbar != NULL)
       destroy_progress_dlg(progbar);
   }
index 08583709ea9f6c20535fd366e0e58fad5d1b0cb3..81a6ca1be021e6daabf42bad9c854eaaf38e292f 100644 (file)
@@ -1,7 +1,7 @@
 /* progress_dlg.c
  * Routines for progress-bar (modal) dialog
  *
- * $Id: progress_dlg.c,v 1.10 2002/03/05 11:56:00 guy Exp $
+ * $Id: progress_dlg.c,v 1.11 2002/07/30 10:13:16 guy Exp $
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@zing.org>
@@ -138,6 +138,66 @@ create_progress_dlg(const gchar *title, const gchar *stop_title,
        return dlg;
 }
 
+progdlg_t *
+delayed_create_progress_dlg(const gchar *title, const gchar *stop_title,
+    gboolean *stop_flag, GTimeVal *start_time, gfloat progress)
+{
+  GTimeVal    time_now;
+  gfloat      delta_time;
+  gfloat      min_display;
+
+#define INIT_DELAY          0.5 * 1e6
+#define MIN_DISPLAY_DEFAULT 2.0 * 1e6
+
+/* Create a progress dialog, but only if it's not likely to disappear
+ * immediately, which can be disconcerting for the user.
+ *
+ * Arguments are as for create_progress_dlg(), plus:
+ *
+ * (a) A pointer to a GTimeVal structure which holds the time at which
+ *     the caller started to process the data.
+ * (b) The current progress as a real number between 0 and 1.
+ */
+
+  g_get_current_time(&time_now);
+
+  /* Get the time elapsed since the caller started processing the data */
+
+  delta_time = (time_now.tv_sec - start_time->tv_sec) * 1e6 +
+    time_now.tv_usec - start_time->tv_usec;
+
+  /* Do nothing for the first INIT_DELAY microseconds */
+
+  if (delta_time < INIT_DELAY)
+    return NULL;
+
+  /* If we create the progress dialog we want it to be displayed for a
+   * minimum of MIN_DISPLAY_DEFAULT microseconds.  However, if we
+   * previously estimated that the progress dialog didn't need to be
+   * created and the caller's processing is slowing down (perhaps due
+   * to the action of the operating system's scheduler on a compute-
+   * intensive task), we tail off the minimum display time such that
+   * the progress dialog will always be created after
+   * 2*MIN_DISPLAY_DEFAULT microseconds.
+   */
+
+  if (delta_time <= INIT_DELAY + MIN_DISPLAY_DEFAULT)
+    min_display = MIN_DISPLAY_DEFAULT;
+  else
+    min_display = 2 * MIN_DISPLAY_DEFAULT - delta_time;
+             /* = MIN_DISPLAY_DEFAULT - (delta_time - MIN_DISPLAY_DEFAULT) */
+  /* Assuming the progress increases linearly, see if the progress
+   * dialog would be displayed for at least min_display microseconds if
+   * we created it now.
+   */
+
+  if (progress >= (delta_time / (delta_time + min_display)))
+    return NULL;
+
+  return create_progress_dlg(title, stop_title, stop_flag);
+}
+
 /*
  * Called when the dialog box is to be deleted.
  * Set the "stop" flag to TRUE, and return TRUE - we don't want the dialog
index b40a069c0709009f9b6151c44e52dc7969132330..2afb7ef31a3dc3d6e4405642073b38f38f64b93b 100644 (file)
@@ -1,7 +1,7 @@
 /* progress_dlg.h
  * Definitions for progress dialog box routines
  *
- * $Id: progress_dlg.h,v 1.1 2001/03/24 02:07:20 guy Exp $
+ * $Id: progress_dlg.h,v 1.2 2002/07/30 10:13:14 guy Exp $
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@zing.org>
@@ -48,6 +48,18 @@ typedef struct progdlg progdlg_t;
 progdlg_t *create_progress_dlg(const gchar *title, const gchar *stop_title,
     gboolean *stop_flag);
 
+/* Create a progress dialog, but only if it's not likely to disappear
+ * immediately, which can be disconcerting for the user.
+ *
+ * The first three arguments are as for create_progress_dlg().
+ * Following those is a pointer to a GTimeVal structure which holds
+ * the time at which the caller started to process the data, and the
+ * current progress (0..1).
+ */
+progdlg_t *delayed_create_progress_dlg(const gchar *title,
+    const gchar *stop_title, gboolean *stop_flag, GTimeVal *start_time,
+    gfloat progress);
+
 /*
  * Set the percentage value of the progress bar.
  */
index 28bc8e6b9f7fd8ab24ac1e850110b6ab821240d4..db2e65ab9110022af9562bfc29f0f5d3d0c9017a 100644 (file)
@@ -1,7 +1,7 @@
 /* proto_hier_stats.c
  * Routines for calculating statistics based on protocol.
  *
- * $Id: proto_hier_stats.c,v 1.13 2002/03/31 20:37:48 guy Exp $
+ * $Id: proto_hier_stats.c,v 1.14 2002/07/30 10:13:14 guy Exp $
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@ethereal.com>
@@ -152,11 +152,11 @@ ph_stats_new(void)
        ph_stats_t      *ps;
        frame_data      *frame;
        guint           tot_packets, tot_bytes;
-       progdlg_t       *progbar;
+       progdlg_t       *progbar = NULL;
        gboolean        stop_flag;
-       guint32         progbar_quantum;
-       guint32         progbar_nextstep;
-       unsigned int    count;
+       long            count;
+       float           prog_val;
+       GTimeVal        start_time;
 
        /* Initialize the data */
        ps = g_new(ph_stats_t, 1);
@@ -165,16 +165,15 @@ ph_stats_new(void)
        ps->stats_tree = g_node_new(NULL);
 
        /* Update the progress bar when it gets to this value. */
-       progbar_nextstep = 0;
+       cfile.progbar_nextstep = 0;
        /* When we reach the value that triggers a progress bar update,
           bump that value by this amount. */
-       progbar_quantum = cfile.count/N_PROGBAR_UPDATES;
+       cfile.progbar_quantum = cfile.count/N_PROGBAR_UPDATES;
        /* Count of packets at which we've looked. */
        count = 0;
 
        stop_flag = FALSE;
-       progbar = create_progress_dlg("Computing protocol statistics", "Stop",
-           &stop_flag);
+       g_get_current_time(&start_time);
 
        tot_packets = 0;
        tot_bytes = 0;
@@ -186,16 +185,24 @@ ph_stats_new(void)
                   may involve an "ioctl()" to see if there's any pending
                   input from an X server, and doing that for every packet
                   can be costly, especially on a big file. */
-               if (count >= progbar_nextstep) {
+               if (count >= cfile.progbar_nextstep) {
                        /* let's not divide by zero. I should never be started
                         * with count == 0, so let's assert that
                         */
                        g_assert(cfile.count > 0);
 
-                       update_progress_dlg(progbar,
-                           (gfloat) count / cfile.count);
+                       prog_val = (gfloat) count / cfile.count;
 
-                       progbar_nextstep += progbar_quantum;
+                       if (progbar == NULL)
+                               /* Create the progress bar if necessary */
+                               progbar = delayed_create_progress_dlg(
+                                   "Computing protocol statistics", "Stop",
+                                   &stop_flag, &start_time, prog_val);
+
+                       if (progbar != NULL)
+                               update_progress_dlg(progbar, prog_val);
+
+                       cfile.progbar_nextstep += cfile.progbar_quantum;
                }
 
                if (stop_flag) {
@@ -219,8 +226,10 @@ ph_stats_new(void)
                count++;
        }
 
-       /* We're done calculating the statistics; destroy the progress bar. */
-       destroy_progress_dlg(progbar);
+       /* We're done calculating the statistics; destroy the progress bar
+           if it was created. */
+       if (progbar != NULL)
+               destroy_progress_dlg(progbar);
 
        if (stop_flag) {
                /*