How do you measure your progress ? Part 3


Performance considerations
Using progress indicator obviously adds certain overhead as calculating current position and redrawing a widget eats some CPU time. So, be careful to not abuse an indicator by updating it after every tiny operation. Instead you might prefer to request its update after some chunks of operations (e.g. after every 10th).

int aNbOps = ...;
int aThreshold = 10;
int aNbChunks = aNbOps / aThreshold;

anIndicator->SetRange (0, aNbChunks);
for (i = 1; i <= aNbOps; i++) {
if (i % aThreshold)

Inserting your indicator into Open CASCADE algorithms
Once you have implemented your subclass, you can pass it to OCC algorithms. As I said above, at the moment, Open CASCADE currently supports progress indicators in IGES, STEP and BRep readers and writers.
Here are examples of how you can provide your indicators into IGES and BRep readers.

IGESCAFControl_Reader aReader;
Handle(Message_ProgressIndicator) anIndicator = ...;

//to make progress indicator work more smoothly divide the transfer into
//two steps: loading (30%) and mapping (70%), including shape healing
anIndicator->NewScope (30, (Standard_CString)qApp->translate ("Exchanger", "Loading file").toAscii());
Standard_Boolean aRes = (aReader.ReadFile (theFileName.ToCString()) == IFSelect_RetDone);
anIndicator->EndScope ();
if (aRes) {
//setting progress into the reader object to track every entity
//(using TransientProcess() is possible only after ReadFile())
aReader.WS()->MapReader()->SetProgress (anIndicator);
anIndicator->NewScope (70, (Standard_CString)qApp->translate ("Exchanger", "Translating file").toAscii());
aRes = aReader.Transfer (theDoc);
anIndicator->EndScope ();
//work-around to decremenet reference counter inside TransientProcess
aReader.WS()->MapReader()->SetProgress (NULL);

Importing native BRep file is more straightforward:
Standard_Boolean aResult = BRepTools::Read (aShape, theFileName.ToCString(), aBuilder, anIndicator);

Multi-threading issues
In its current implementation Message_ProgressIndicator is exclusively tailored for use within a single thread. This stems from its implementation concept based on a stack of nested sub-ranges – every time you signal a progress (e.g. with Increment() or EndScope()) it applies to the current open sub-range. This makes it unusable for multi-threaded environment where concurrent threads can perform their own chunks of tasks and report progress. I first encountered this working on parallelizing IGES import.

Upon part 1 publication, Andrey from OCC was very kind to let me know that they are prototyping multi-threaded version of the progress indicator. So chances are it can appear in near releases. Anyway, as long as you use the indicator in a single thread even within a multi-threaded environment (e.g. if your OCC-based algorithms run in a separate worker thread) you are safe to go.

So, go and plan your goal, set your range, make your next step and report how closer you are now ;-).


  1. Roman,

    Any plans to publish QOLib - it would be good to consolidate the various OCC widgets someday.


  2. Hi Peter,
    I'm currently resurrecting QOLib porting it to Qt4 and OCC6.3 aggressively simplifying and refactoring the code. Initial version was on Qt3 and OCC5, and included a tutorial in addition to thorough documentation, which paid me off only now ;-). I'm doing so as gradually developing some application I consider distributing on a free of charge basis.
    As for QOLib itself I'm thinking of some permissive license - MIT or BSD. Another option is to adopt something more restrictive to demand modifications back under the same license, i.e. LGPL at most or something in between. Recommendations are welcome.

  3. Just a small errata corrige :)

    if (i % aThreshold)

    runs every time except the one you want !

    Maybe it should be if ((i % aThreshold) == 0) !

    Nice posts , I'll use the code to adapt my IGES reader (actually I use a marquee). In fact users are happy to wait when there's a moving indicator somewhere in the UI and not just the hourglass!

    (With marquee I mean the moving ahead and back progress bar like this one : http://www.sweetpotatosoftware.com/SPSBlog/content/binary/MarqueeProgressbar.png

    Byeee QbProg :)

  4. if ((i % aThreshold) == 0) - yes, of course! thanks for pointing this.

    Now understood regarding Marquee. Thanks. By the way, do you know if there's a Qt implementation of it ?

  5. No, I don't know :) I don't use Qt very much, but I'm looking at it with interest due to the new LGPL licensing!

  6. I put QtOPENCASCADE out under LGPL, as it was the simpest way to enable some of the qtocc team to help develop OS, yet still be able to use the library in any closed source apps they might develop (using Qt commercial) and it was compatible the the Qt GPL execptions. With Qt 4.5 going to LGPL as well, it seems logical to keep this license.

  7. Is it possible to show the progress of loading an ocaf document?

  8. No. OCAF persistence mechanism does not (currently) support progress indicators. Usually load/save operations should be rather fast (<3-5 secs) and thus this does not justify a need for an indicator. Is your case different ?