Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members  

Progress.h

00001 //  Progress - a wrapper around QProgressDialog
00002 //  Copyright (C) 2000-2003 bozo & sgbeal @users.sourceforge.net
00003 //
00004 //  This program is free software; you can redistribute it and/or
00005 //  modify it under the terms of the GNU General Public License
00006 //  as published by the Free Software Foundation; either version 2
00007 //  of the License, or (at your option) any later version.
00008 //
00009 //  This program is distributed in the hope that it will be useful,
00010 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012 //  GNU General Public License for more details.
00013 //
00014 //  You should have received a copy of the GNU General Public License
00015 //  along with this program; if not, write to the Free Software
00016 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00017 
00018 #ifndef _FUN_PROGRESS_H
00019 #define _FUN_PROGRESS_H
00020 
00021 #include <fun/fun.h>
00022 #include <sys/time.h>  //  for timeval
00023 
00024 namespace fun {
00025 
00026 /**
00027 *  This is a wrapper around QProgressDialog for classes which want to report
00028 *  progress information, but don't want to know whether there's a QApplication
00029 *  which needs to have processEvents() called, or whether other chunks of code
00030 *  already have a progress dialog up, etc.
00031 *
00032 *  If there are places where you notice multiple progress dialogs popping
00033 *  up in series, you can fix that by nesting them in an outer start()/finish()
00034 *  pair.  For example, when loubetomy loads a map, it performs three steps:
00035 *  <OL>
00036 *  <LI>creates a SerialTree from the given file.
00037 *  <LI>deserializes the HexMap from the resulting SerialTree.
00038 *  <LI>gives the resulting HexMap to HexMapView so that the necessary graphic
00039 *      bits can be created.
00040 *  </OL>
00041 *  All of those steps are performed by chunks of library code which don't
00042 *  know about each other--and loubetomy doesn't want to know which of them,
00043 *  if any, report progress information--so loubetomy calls Progress::start(),
00044 *  does the first step, calls Progress::update() (which tells it whether the
00045 *  user hit the cancel button while SerialTree was doing its thing), then
00046 *  deserializes the HexMap, then calls Progress::update() again (which,
00047 *  again, tells it whether the user hit the cancel button while the HexMap
00048 *  was deserializing itself), then gives the map to its HexMapView, & finally
00049 *  calls Progress::finish() to make the dialog go away (if one was displayed).
00050 *
00051 *  (If the library code was responsible for fondling the progress dialog
00052 *  itself, it would be more complicated, and either there would be gaps when
00053 *  the program was busy but no dialog was up, or there would be points when
00054 *  two progress dialogs were up, & in either case it would be messier for
00055 *  loubetomy to know whether the user had hit "cancel" in the dialog displayed
00056 *  by the library.)
00057 */
00058 class Progress
00059 {
00060     public:
00061     /**
00062     *  Indicates that some operation is starting for which progress will be
00063     *  reported.  Whether this does anything depends on a couple of things:
00064     *  <UL>
00065     *  <LI>If no QApplication has been passed to setQApplication(),
00066     *      this just notes the start time.  (It might not even do that.)
00067     *      Keeping this fast for non-interactive programs which don't care
00068     *      about popping up progress dialogs is important!
00069     *  <LI>Otherwise, if this call is nested inside another start/finish
00070     *      pair, then it updates the existing QProgressDialog, if any.
00071     *  <LI>Otherwise, this creates a QProgressDialog.  (Whether or not the
00072     *      dialog shows itself is up to the dialog.)
00073     *  </UL>
00074     *
00075     *  @param operation   A description of the operation being performed.  This
00076     *                     will be displayed in the progress dialog, if any.
00077     *  @param steps       The number of steps in this operation.
00078     *  @param canCancel   Whether or not this operation can be cancelled by the
00079     *                     user.
00080     * 
00081     */
00082     static void start(const QString &operation, int steps, bool canCancel = true);
00083 
00084     /**
00085     *  Same as start(), so that you don't have to remember whether it's
00086     *  "start" or "begin".
00087     */
00088     static void begin(const QString &operation, int steps, bool canCancel = true) { return start(operation, steps, canCancel); }
00089 
00090     /**
00091     *  This updates the existing progress dialog, if any.  If a progress
00092     *  dialog is up, and the user has hit cancel (or if the user hit cancel
00093     *  during some nested operation), this returns true; otherwise it returns
00094     *  false.
00095     *
00096     *  If the user has inidicated that they want to cancel the operation, you
00097     *  still need to call finish().
00098     *
00099     *  If no QApplication has been passed to setQApplication(), then update()
00100     *  doesn't do anything, and just returns false.
00101     *
00102     *  @param step   which step has been completed.
00103     */
00104     static bool update(int step);
00105 
00106     /**
00107     *  Indicates that the operation is done (even if it's "done" because it
00108     *  was cancelled by the user).  What this does depends on several things:
00109     *
00110     *  <UL>
00111     *  <LI>If no QApplication has been passed to setQApplication(),
00112     *      this might print the elapsed time, or do nothing.
00113     *  <LI>Otherwise, if this call is nested inside another start/finish
00114     *      pair, then it restores the existing QProgressDialog with the
00115     *      "outer" ("anti-nested"?) operation's values.
00116     *  <LI>Otherwise, this cleans up the progress dialog.
00117     *  </UL>
00118     */
00119     static void finish();
00120 
00121     /**
00122     *  Same as finish(), so that you don't have to remember whether it's
00123     *  "finish" or "end".
00124     */
00125     static void end() { finish(); }
00126 
00127     /**
00128     *  Causes the progress dialog, if any, to become hidden.  You want to
00129     *  do this if you need to pop up a confirmation dialog in the middle of
00130     *  some operation; otherwise the progress dialog is probably going to
00131     *  be rather rude about popping up in front of the confirmation dialog &
00132     *  demanding attention.  Regardless of subsequent calls to update(), the
00133     *  progress dialog will not be shown again until resume() or finish() is
00134     *  called.  (In the case of finish(), the dialog won't be shown again
00135     *  until the start of the next non-nested operation.)
00136     *
00137     *  suspend()/resume() pairs can be nested.  Calling suspend() before
00138     *  start() has no effect.
00139     */
00140     static void suspend();
00141 
00142     /**
00143     *  Prints a randomly-selected QUB developer's resum&eacute; on stdout.
00144     *  Err, wait, apparently it causes the progress dialog, if any, to resume
00145     *  being shown after a call to suspend().  (It may not actually show
00146     *  itself until the next call to update().)
00147     *
00148     *  Note that suspend()/resume() calls may be nested; the dialog will not
00149     *  actually be displayed until after the outermost resume() call.
00150     */
00151     static void resume();
00152 
00153     /**
00154     *  Returns true if this operation (or a nested one) has been cancelled.
00155     *  (The other way to find this out is from the return value from update().)
00156     */
00157     static bool cancelled();
00158 
00159     /**
00160     *  Sets the QApplication whose processEvents() will be called during
00161     *  update().  If you create a QApplication, just call this in your
00162     *  main() and forget about it.
00163     *
00164     *  If this is never called (or is called with a NULL QApplication), the
00165     *  other progress methods don't really do anything.
00166     */
00167     static void setQApplication(QApplication *);
00168 
00169     ~Progress();
00170 
00171     private:
00172     Progress(int, const QString &, bool);
00173 
00174     int steps;
00175     int step;
00176     bool canCancel;
00177     QString msg;
00178     timeval startTime;
00179 };
00180 
00181 }  //  namespace fun
00182 
00183 #endif  //  _FUN_PROGRESS_H

Generated on Mon Aug 11 14:06:55 2003 for libfunutil by doxygen1.2.18