Sequencer.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002  *   Copyright (c) 2004 Werner Mayer <wmayer[at]users.sourceforge.net>     *
00003  *                                                                         *
00004  *   This file is part of the FreeCAD CAx development system.              *
00005  *                                                                         *
00006  *   This library is free software; you can redistribute it and/or         *
00007  *   modify it under the terms of the GNU Library General Public           *
00008  *   License as published by the Free Software Foundation; either          *
00009  *   version 2 of the License, or (at your option) any later version.      *
00010  *                                                                         *
00011  *   This library  is distributed in the hope that it will be useful,      *
00012  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00013  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
00014  *   GNU Library General Public License for more details.                  *
00015  *                                                                         *
00016  *   You should have received a copy of the GNU Library General Public     *
00017  *   License along with this library; see the file COPYING.LIB. If not,    *
00018  *   write to the Free Software Foundation, Inc., 59 Temple Place,         *
00019  *   Suite 330, Boston, MA  02111-1307, USA                                *
00020  *                                                                         *
00021  ***************************************************************************/
00022 
00023 
00024 #include "PreCompiled.h"
00025 
00026 #ifndef _PreComp_
00027 # include <cstdio>
00028 # include <algorithm>
00029 # include <QMutex>
00030 # include <QMutexLocker>
00031 #endif
00032 
00033 #include "Sequencer.h"
00034 #include "Console.h"
00035 #include <CXX/Objects.hxx>
00036 
00037 using namespace Base;
00038 
00039 namespace Base {
00040     struct SequencerP {
00041         // members
00042         static std::vector<SequencerBase*> _instances; 
00043         static SequencerLauncher* _topLauncher; 
00044         static QMutex mutex; 
00048         static void appendInstance (SequencerBase* s)
00049         {
00050             _instances.push_back(s);
00051         }
00052         static void removeInstance (SequencerBase* s)
00053         {
00054             std::vector<SequencerBase*>::iterator it;
00055             it = std::find(_instances.begin(), _instances.end(), s);
00056             _instances.erase(it);
00057         }
00058         static SequencerBase& getInstance ()
00059         {
00060             return *_instances.back();
00061         }
00062     };
00063 
00068     std::vector<SequencerBase*> SequencerP::_instances;
00069     SequencerLauncher* SequencerP::_topLauncher = 0;
00070     QMutex SequencerP::mutex(QMutex::Recursive);
00071 };
00072 
00073 SequencerBase& SequencerBase::Instance ()
00074 {
00075     // not initialized?
00076     if (SequencerP::_instances.size() == 0) {
00077         new ConsoleSequencer();
00078     }
00079 
00080     return SequencerP::getInstance();
00081 }
00082 
00083 SequencerBase::SequencerBase()
00084   : nProgress(0), nTotalSteps(0), _bLocked(false), _bCanceled(false), _nLastPercentage(-1)
00085 {
00086     SequencerP::appendInstance(this);
00087 }
00088 
00089 SequencerBase::~SequencerBase()
00090 {
00091     SequencerP::removeInstance(this);
00092 }
00093 
00094 bool SequencerBase::start(const char* pszStr, size_t steps)
00095 {
00096     // reset current state of progress (in percent)
00097     this->_nLastPercentage = -1;
00098 
00099     this->nTotalSteps = steps;
00100     this->nProgress = 0;
00101     this->_bCanceled = false;
00102 
00103     setText(pszStr);
00104 
00105     // reimplemented in sub-classes
00106     if (!this->_bLocked)
00107         startStep();
00108 
00109     return true;
00110 }
00111 
00112 size_t SequencerBase::numberOfSteps() const
00113 {
00114     return this->nTotalSteps;
00115 }
00116 
00117 void SequencerBase::startStep()
00118 {
00119 }
00120 
00121 bool SequencerBase::next(bool canAbort)
00122 {
00123     this->nProgress++;
00124     float fDiv = this->nTotalSteps > 0 ? (float)this->nTotalSteps : 1000.0f;
00125     int perc = (int)((float)this->nProgress * (100.0f / fDiv));
00126 
00127     // do only an update if we have increased by one percent
00128     if (perc > this->_nLastPercentage) {
00129         this->_nLastPercentage = perc;
00130 
00131         // if not locked
00132         if (!this->_bLocked)
00133             nextStep(canAbort);
00134     }
00135 
00136     return this->nProgress < this->nTotalSteps;
00137 }
00138 
00139 void SequencerBase::nextStep( bool )
00140 {
00141 }
00142 
00143 void SequencerBase::setProgress(size_t)
00144 {
00145 }
00146 
00147 bool SequencerBase::stop()
00148 {
00149     resetData();
00150     return true;
00151 }
00152 
00153 void SequencerBase::pause()
00154 {
00155 }
00156 
00157 void SequencerBase::resume()
00158 {
00159 }
00160 
00161 bool SequencerBase::isBlocking() const
00162 {
00163     return true;
00164 }
00165 
00166 bool SequencerBase::setLocked(bool bLocked)
00167 {
00168     QMutexLocker locker(&SequencerP::mutex);
00169     bool old = this->_bLocked;
00170     this->_bLocked = bLocked;
00171     return old;
00172 }
00173 
00174 bool SequencerBase::isLocked() const
00175 {
00176     QMutexLocker locker(&SequencerP::mutex);
00177     return this->_bLocked;
00178 }
00179 
00180 bool SequencerBase::isRunning() const
00181 {
00182     QMutexLocker locker(&SequencerP::mutex);
00183     return (SequencerP::_topLauncher != 0);
00184 }
00185 
00186 bool SequencerBase::wasCanceled() const
00187 {
00188     QMutexLocker locker(&SequencerP::mutex);
00189     return this->_bCanceled;
00190 }
00191 
00192 void SequencerBase::tryToCancel()
00193 {
00194     this->_bCanceled = true;
00195 }
00196 
00197 void SequencerBase::rejectCancel()
00198 {
00199     this->_bCanceled = false;
00200 }
00201 
00202 int SequencerBase::progressInPercent() const
00203 {
00204     return this->_nLastPercentage;
00205 }
00206 
00207 void SequencerBase::resetData()
00208 {
00209     this->_bCanceled = false;
00210 }
00211 
00212 void SequencerBase::setText(const char*)
00213 {
00214 }
00215 
00216 // ---------------------------------------------------------
00217 
00218 EmptySequencer::EmptySequencer()
00219 {
00220 }
00221 
00222 EmptySequencer::~EmptySequencer()
00223 {
00224 }
00225 
00226 // ---------------------------------------------------------
00227 
00228 using Base::ConsoleSequencer;
00229 
00230 ConsoleSequencer::ConsoleSequencer ()
00231 {
00232 }
00233 
00234 ConsoleSequencer::~ConsoleSequencer ()
00235 {
00236 }
00237 
00238 void ConsoleSequencer::setText (const char* pszTxt)
00239 {
00240     printf("%s...\n", pszTxt);
00241 }
00242 
00243 void ConsoleSequencer::startStep()
00244 {
00245 }
00246 
00247 void ConsoleSequencer::nextStep( bool )
00248 {
00249     if (this->nTotalSteps != 0)
00250         printf("\t\t\t\t\t\t(%2.1f %%)\t\r", (float)progressInPercent());
00251 }
00252 
00253 void ConsoleSequencer::resetData()
00254 {
00255     SequencerBase::resetData();
00256     printf("\t\t\t\t\t\t\t\t\r");
00257 }
00258 
00259 // ---------------------------------------------------------
00260 
00261 SequencerLauncher::SequencerLauncher(const char* pszStr, size_t steps)
00262 {
00263     QMutexLocker locker(&SequencerP::mutex);
00264     // Have we already an instance of SequencerLauncher created?
00265     if (!SequencerP::_topLauncher) {
00266         SequencerBase::Instance().start(pszStr, steps);
00267         SequencerP::_topLauncher = this;
00268     }
00269 }
00270 
00271 SequencerLauncher::~SequencerLauncher()
00272 {
00273     QMutexLocker locker(&SequencerP::mutex);
00274     if (SequencerP::_topLauncher == this)
00275         SequencerBase::Instance().stop();
00276     if (SequencerP::_topLauncher == this) {
00277         SequencerP::_topLauncher = 0;
00278     }
00279 }
00280 
00281 void SequencerLauncher::setText (const char* pszTxt)
00282 {
00283     QMutexLocker locker(&SequencerP::mutex);
00284     SequencerBase::Instance().setText(pszTxt);
00285 }
00286 
00287 bool SequencerLauncher::next(bool canAbort)
00288 {
00289     QMutexLocker locker(&SequencerP::mutex);
00290     if (SequencerP::_topLauncher != this)
00291         return true; // ignore
00292     return SequencerBase::Instance().next(canAbort);
00293 }
00294 
00295 void SequencerLauncher::setProgress(size_t pos)
00296 {
00297     QMutexLocker locker(&SequencerP::mutex);
00298     SequencerBase::Instance().setProgress(pos);
00299 }
00300 
00301 size_t SequencerLauncher::numberOfSteps() const
00302 {
00303     QMutexLocker locker(&SequencerP::mutex);
00304     return SequencerBase::Instance().numberOfSteps();
00305 }
00306 
00307 bool SequencerLauncher::wasCanceled() const
00308 {
00309     return SequencerBase::Instance().wasCanceled();
00310 }
00311 
00312 // ---------------------------------------------------------
00313 
00314 void ProgressIndicatorPy::init_type()
00315 {
00316     behaviors().name("ProgressIndicator");
00317     behaviors().doc("Progress indicator");
00318     // you must have overwritten the virtual functions
00319     behaviors().supportRepr();
00320     behaviors().supportGetattr();
00321     behaviors().supportSetattr();
00322     behaviors().type_object()->tp_new = &PyMake;
00323 
00324     add_varargs_method("start",&ProgressIndicatorPy::start,"start(string,int)");
00325     add_varargs_method("next",&ProgressIndicatorPy::next,"next()");
00326     add_varargs_method("stop",&ProgressIndicatorPy::stop,"stop()");
00327 }
00328 
00329 PyObject *ProgressIndicatorPy::PyMake(struct _typeobject *, PyObject *, PyObject *)
00330 {
00331     return new ProgressIndicatorPy();
00332 }
00333 
00334 ProgressIndicatorPy::ProgressIndicatorPy()
00335 {
00336 }
00337 
00338 ProgressIndicatorPy::~ProgressIndicatorPy()
00339 {
00340 }
00341 
00342 Py::Object ProgressIndicatorPy::repr()
00343 {
00344     std::string s = "Base.ProgressIndicator";
00345     return Py::String(s);
00346 }
00347 
00348 Py::Object ProgressIndicatorPy::start(const Py::Tuple& args)
00349 {
00350     char* text;
00351     int steps;
00352     if (!PyArg_ParseTuple(args.ptr(), "si",&text,&steps))
00353         throw Py::Exception();
00354     if (!_seq.get())
00355         _seq.reset(new SequencerLauncher(text,steps));
00356     return Py::None();
00357 }
00358 
00359 Py::Object ProgressIndicatorPy::next(const Py::Tuple& args)
00360 {
00361     int b=0;
00362     if (!PyArg_ParseTuple(args.ptr(), "|i",&b))
00363         throw Py::Exception();
00364     if (_seq.get()) {
00365         try {
00366             _seq->next(b ? true : false);
00367         }
00368         catch (const Base::AbortException&) {
00369             _seq.reset();
00370             throw Py::Exception("abort progress indicator");
00371         }
00372     }
00373     return Py::None();
00374 }
00375 
00376 Py::Object ProgressIndicatorPy::stop(const Py::Tuple& args)
00377 {
00378     if (!PyArg_ParseTuple(args.ptr(), ""))
00379         throw Py::Exception();
00380     _seq.reset();
00381     return Py::None();
00382 }

Generated on Wed Nov 23 19:00:37 2011 for FreeCAD by  doxygen 1.6.1