00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
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
00029
00030
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
00089
00090
00091
00092
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
00164
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
00177 QProgressDialog *tp = g_pd;
00178 g_pd = NULL;
00179 g_cancelBtn = NULL;
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 }