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

Progress.cpp

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 #include <assert.h>
00019 
00020 #include <fun/Progress.h>
00021 #include "ProgressI.h"
00022 #include <qapplication.h>
00023 #include <qcursor.h>
00024 #include <qptrstack.h>
00025 #include <qprogressdialog.h>
00026 #include <qpushbutton.h>
00027 
00028 //  True if you want this to print elapsed times to cerr, false if not.
00029 //  Maybe finish() should take a timeval * or something for returning the
00030 //  elapsed time?
00031 #define ELAPSED_TIME_TO_CERR 1
00032 
00033 using namespace fun;
00034 
00035 static QApplication *g_qApp = NULL;
00036 static QProgressDialog *g_pd = NULL;
00037 static QPtrStack<Progress> g_stack;
00038 static bool g_cancelled = false;
00039 static int g_suspended = 0;
00040 static bool g_showOnResume = false;
00041 static QPushButton *g_cancelBtn = NULL;
00042 static InternalProgressHelper *g_helper = NULL;
00043 
00044 Progress::Progress(int s, const QString &op, bool cc)
00045  :  steps(s),
00046     step(0),
00047     canCancel(cc),
00048     msg(op)
00049 {
00050     if (msg.isNull()) msg = "Busy, busy, busy.  I'm a busy program.";
00051 #if ELAPSED_TIME_TO_CERR
00052     gettimeofday(&startTime, NULL);
00053 #endif
00054 }
00055 
00056 Progress::~Progress()
00057 {
00058 #if ELAPSED_TIME_TO_CERR
00059     if (g_cancelled) return;
00060     timeval tv;
00061     gettimeofday(&tv, NULL);
00062     tv.tv_sec -= startTime.tv_sec;
00063     tv.tv_usec -= startTime.tv_usec;
00064     if (tv.tv_usec < 0)
00065     {
00066         --tv.tv_sec;
00067         tv.tv_usec += 1000000;
00068     }
00069     cerr << __FILE__ << " " << dec << __LINE__ << ": ";
00070     for (int ii = g_stack.count(); ii > 0; --ii) cerr << "  ";
00071     cerr << "\"" << msg << "\" elapsed: " << tv.tv_sec << "s " << tv.tv_usec << "us\n";
00072 #endif
00073 }
00074 
00075 void
00076 Progress::start(const QString &msg, int steps, bool canCancel)
00077 {
00078     Progress *p = new Progress(steps, msg, canCancel);
00079     g_stack.push(p);
00080     if (g_qApp && !g_pd)
00081     {
00082         QApplication::setOverrideCursor(Qt::WaitCursor);
00083         if (!g_helper) g_helper = new InternalProgressHelper();
00084         g_pd = new QProgressDialog(NULL, NULL, true);
00085         g_cancelled = false;
00086         g_suspended = 0;
00087         g_showOnResume = false;
00088         //  When the progress dialog finds out the cancel button has been hit,
00089         //  it hides itself.  To keep that from happening, we create our own
00090         //  cancel button, and disconnect its signals from the progress
00091         //  dialog's slots.  Keeping a pointer to the button also lets us
00092         //  enable/disable it as needed.
00093         g_cancelBtn = new QPushButton("Cancel", g_pd);
00094         g_pd->setCancelButton(g_cancelBtn);
00095         g_cancelBtn->disconnect(SIGNAL(clicked()));
00096         g_helper->connect(g_cancelBtn, SIGNAL(clicked()), SLOT(cancelBtnClicked()));
00097         g_helper->connect(g_cancelBtn, SIGNAL(destroyed()), SLOT(cancelBtnDeleted()));
00098         g_helper->connect(g_pd, SIGNAL(destroyed()), SLOT(dialogDeleted()));
00099         g_pd->setAutoReset(false);
00100         g_pd->setAutoClose(false);
00101     }
00102     if (g_pd && (!g_cancelled) && (!g_suspended))
00103     {
00104         g_pd->setLabelText(msg);
00105         g_pd->setTotalSteps(steps);
00106         g_pd->setProgress(0);
00107         if (g_cancelBtn) g_cancelBtn->setEnabled(canCancel);
00108     }
00109 }
00110 
00111 bool
00112 Progress::update(int step)
00113 {
00114     assert(g_stack.top());
00115     if (g_pd)
00116     {
00117         if ((!g_cancelled) && (!g_suspended))
00118         {
00119             g_stack.top()->step = step;
00120             g_pd->setProgress(step);
00121         }
00122         g_qApp->processEvents();
00123         return g_cancelled;
00124     }
00125     return false;
00126 }
00127 
00128 void
00129 Progress::suspend()
00130 {
00131     if ((!g_suspended) && g_pd)
00132     {
00133         g_showOnResume = g_pd->isVisible();
00134         g_pd->hide();
00135         QApplication::restoreOverrideCursor();
00136     }
00137     ++g_suspended;
00138 }
00139 
00140 void
00141 Progress::resume()
00142 {
00143     if (g_suspended) --g_suspended;
00144     if ((!g_suspended) && g_pd)
00145     {
00146         QApplication::setOverrideCursor(Qt::WaitCursor);
00147         if (g_showOnResume) g_pd->show();
00148     }
00149 }
00150 
00151 void
00152 Progress::finish()
00153 {
00154     Progress *p = g_stack.pop();
00155     assert(p);
00156     delete p;
00157     if (!g_pd) return;
00158     p = g_stack.top();
00159     if (p)
00160     {
00161         if ((!g_cancelled) && (!g_suspended))
00162         {
00163             //  We finished a nested operation; put things back the way the
00164             //  parent operation had them.
00165             if (g_pd)
00166             {
00167                 g_pd->setLabelText(p->msg);
00168                 g_pd->setTotalSteps(p->steps);
00169                 g_pd->setProgress(p->step);
00170             }
00171             if (g_cancelBtn) g_cancelBtn->setEnabled(p->canCancel);
00172         }
00173     }
00174     else
00175     {
00176         //  We're done!  Close the dialog.
00177         QProgressDialog *tp = g_pd;
00178         g_pd = NULL;
00179         g_cancelBtn = NULL;  //  it will get deleted by the dialog anyway.
00180         if (g_helper) g_helper->disconnect();
00181         delete tp;
00182         QApplication::restoreOverrideCursor();
00183     }
00184 }
00185 
00186 bool
00187 Progress::cancelled() { return g_cancelled; }
00188 
00189 void
00190 Progress::setQApplication(QApplication *qapp)
00191 {
00192     g_qApp = qapp;
00193     if (!qapp)
00194     {
00195         NOT_DONE("setQApplication() doesn't make sure dialog is down etc.");
00196     }
00197 }
00198 
00199 void
00200 InternalProgressHelper::dialogDeleted()
00201 {
00202     g_pd = NULL;
00203 }
00204 
00205 void
00206 InternalProgressHelper::cancelBtnClicked()
00207 {
00208     if (g_cancelled) return;
00209     g_cancelled = true;
00210     if (g_cancelBtn) g_cancelBtn->setEnabled(false);
00211     if (g_pd) g_pd->setLabelText("Oooh, wise guy, eh?");
00212 }
00213 
00214 void
00215 InternalProgressHelper::cancelBtnDeleted()
00216 {
00217     g_cancelBtn = NULL;
00218 }

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