summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/oox/helper/progressbar.hxx4
-rw-r--r--include/vcl/timer.hxx3
-rw-r--r--sc/source/filter/inc/worksheethelper.hxx11
-rw-r--r--sc/source/filter/oox/workbookfragment.cxx88
-rw-r--r--sc/source/filter/oox/worksheethelper.cxx59
5 files changed, 140 insertions, 25 deletions
diff --git a/include/oox/helper/progressbar.hxx b/include/oox/helper/progressbar.hxx
index 1f6105888b0b..cdcbd0f462e3 100644
--- a/include/oox/helper/progressbar.hxx
+++ b/include/oox/helper/progressbar.hxx
@@ -35,7 +35,7 @@ namespace oox {
/** Interface for progress bar classes.
*/
-class IProgressBar
+class OOX_DLLPUBLIC IProgressBar
{
public:
virtual ~IProgressBar();
@@ -66,7 +66,7 @@ typedef ::boost::shared_ptr< ISegmentProgressBar > ISegmentProgressBarRef;
/** Interface for a segment in a progress bar, that is able to create sub
segments from itself.
*/
-class ISegmentProgressBar : public IProgressBar
+class OOX_DLLPUBLIC ISegmentProgressBar : public IProgressBar
{
public:
virtual ~ISegmentProgressBar();
diff --git a/include/vcl/timer.hxx b/include/vcl/timer.hxx
index ff9a4cf5dcc0..a5b1c95b21fa 100644
--- a/include/vcl/timer.hxx
+++ b/include/vcl/timer.hxx
@@ -46,7 +46,8 @@ public:
void Start();
void Stop();
- void SetTimeout( sal_uLong nTimeout );
+ /// set the timeout in milliseconds
+ void SetTimeout( sal_uLong nTimeoutMs );
sal_uLong GetTimeout() const { return mnTimeout; }
sal_Bool IsActive() const { return mbActive ? sal_True : sal_False; }
diff --git a/sc/source/filter/inc/worksheethelper.hxx b/sc/source/filter/inc/worksheethelper.hxx
index bbcd152f6fc9..9e231615b795 100644
--- a/sc/source/filter/inc/worksheethelper.hxx
+++ b/sc/source/filter/inc/worksheethelper.hxx
@@ -180,6 +180,14 @@ struct ValidationModel
class WorksheetGlobals;
typedef ::boost::shared_ptr< WorksheetGlobals > WorksheetGlobalsRef;
+class IWorksheetProgress {
+public:
+ virtual ~IWorksheetProgress() {}
+ virtual ISegmentProgressBarRef getRowProgress() = 0;
+ virtual void setCustomRowProgress(
+ const ISegmentProgressBarRef &rxRowProgress ) = 0;
+};
+
class WorksheetHelper : public WorkbookHelper
{
public:
@@ -191,6 +199,9 @@ public:
WorksheetType eSheetType,
sal_Int16 nSheet );
+ // horrible accessor for hidden WorksheetGlobals ...
+ static IWorksheetProgress *getWorksheetInterface( const WorksheetGlobalsRef &xRef );
+
// ------------------------------------------------------------------------
/** Returns the type of this sheet. */
diff --git a/sc/source/filter/oox/workbookfragment.cxx b/sc/source/filter/oox/workbookfragment.cxx
index e666fa3093ec..2baf11d664dc 100644
--- a/sc/source/filter/oox/workbookfragment.cxx
+++ b/sc/source/filter/oox/workbookfragment.cxx
@@ -41,6 +41,7 @@
#include "viewsettings.hxx"
#include "workbooksettings.hxx"
#include "worksheetbuffer.hxx"
+#include "worksheethelper.hxx"
#include "worksheetfragment.hxx"
#include "sheetdatacontext.hxx"
#include "threadpool.hxx"
@@ -51,6 +52,7 @@
#include "calcconfig.hxx"
#include <vcl/svapp.hxx>
+#include <vcl/timer.hxx>
#include <oox/core/fastparser.hxx>
#include <comphelper/processfactory.hxx>
@@ -211,12 +213,15 @@ typedef std::vector<SheetFragmentHandler> SheetFragmentVector;
class WorkerThread : public ThreadTask
{
+ sal_Int32 &mrSheetsLeft;
WorkbookFragment& mrWorkbookHandler;
rtl::Reference<FragmentHandler> mxHandler;
public:
WorkerThread( WorkbookFragment& rWorkbookHandler,
- const rtl::Reference<FragmentHandler>& xHandler ) :
+ const rtl::Reference<FragmentHandler>& xHandler,
+ sal_Int32 &rSheetsLeft ) :
+ mrSheetsLeft( rSheetsLeft ),
mrWorkbookHandler( rWorkbookHandler ),
mxHandler( xHandler )
{
@@ -237,6 +242,61 @@ public:
SAL_INFO( "sc.filter", "start import\n" );
mrWorkbookHandler.importOoxFragment( mxHandler, *xParser );
SAL_INFO( "sc.filter", "end import, release solar\n" );
+ mrSheetsLeft--;
+ assert( mrSheetsLeft >= 0 );
+ if( mrSheetsLeft == 0 )
+ Application::EndYield();
+ }
+};
+
+class ProgressBarTimer : Timer
+{
+ // FIXME: really we should unify all sheet loading
+ // progress reporting into something pleasant.
+ class ProgressWrapper : public ISegmentProgressBar
+ {
+ double mfPosition;
+ ISegmentProgressBarRef mxWrapped;
+ public:
+ ProgressWrapper( const ISegmentProgressBarRef &xRef ) :
+ mxWrapped( xRef )
+ {
+ }
+ virtual ~ProgressWrapper() {}
+ // IProgressBar
+ virtual double getPosition() const { return mfPosition; }
+ virtual void setPosition( double fPosition ) { mfPosition = fPosition; }
+ // ISegmentProgressBar
+ virtual double getFreeLength() const { return 0.0; }
+ virtual ISegmentProgressBarRef createSegment( double /* fLength */ )
+ {
+ return ISegmentProgressBarRef();
+ }
+ void UpdateBar()
+ {
+ mxWrapped->setPosition( mfPosition );
+ }
+ };
+ std::vector< ISegmentProgressBarRef > aSegments;
+public:
+ ProgressBarTimer() : Timer()
+ {
+ SetTimeout( 500 );
+ }
+ virtual ~ProgressBarTimer()
+ {
+ aSegments.clear();
+ }
+ ISegmentProgressBarRef wrapProgress( const ISegmentProgressBarRef &xProgress )
+ {
+ aSegments.push_back( ISegmentProgressBarRef( new ProgressWrapper( xProgress ) ) );
+ return aSegments.back();
+ }
+ virtual void Timeout()
+ {
+ fprintf( stderr, "Progress bar update\n" );
+ for( size_t i = 0; i < aSegments.size(); i++)
+ static_cast< ProgressWrapper *>( aSegments[ i ].get() )->UpdateBar();
}
};
@@ -261,18 +321,30 @@ void importSheetFragments( WorkbookFragment& rWorkbookHandler, SheetFragmentVect
nThreads = 0;
ThreadPool aPool( nThreads );
+ sal_Int32 nSheetsLeft = 0;
+ ProgressBarTimer aProgressUpdater;
SheetFragmentVector::iterator it = rSheets.begin(), itEnd = rSheets.end();
for( ; it != itEnd; ++it )
- aPool.pushTask( new WorkerThread( rWorkbookHandler, it->second ) )
- ;
+ {
+ // getting at the WorksheetGlobals is rather unpleasant
+ IWorksheetProgress *pProgress = WorksheetHelper::getWorksheetInterface( it->first );
+ pProgress->setCustomRowProgress(
+ aProgressUpdater.wrapProgress(
+ pProgress->getRowProgress() ) );
+ aPool.pushTask( new WorkerThread( rWorkbookHandler, it->second,
+ /* ref */ nSheetsLeft ) );
+ nSheetsLeft++;
+ }
+ while( nSheetsLeft > 0)
{
- // Ideally no-one else but our worker threads can re-acquire that.
- // potentially if that causes a problem we might want to extend
- // the SolarMutex functionality to allow passing it around.
- SolarMutexReleaser aReleaser;
- aPool.waitUntilWorkersDone();
+ // This is a much more controlled re-enterancy hazard than
+ // allowing a yield deeper inside the filter code for progress
+ // bar updating.
+ Application::Yield();
}
+ // join all the threads:
+ aPool.waitUntilWorkersDone();
}
else
{
diff --git a/sc/source/filter/oox/worksheethelper.cxx b/sc/source/filter/oox/worksheethelper.cxx
index e3a4c897abe6..c19fe71ef590 100644
--- a/sc/source/filter/oox/worksheethelper.cxx
+++ b/sc/source/filter/oox/worksheethelper.cxx
@@ -96,18 +96,6 @@ using namespace ::com::sun::star::util;
namespace {
-void lclUpdateProgressBar( const ISegmentProgressBarRef& rxProgressBar, const CellRangeAddress& rUsedArea, sal_Int32 nRow )
-{
- if (!rxProgressBar || nRow < rUsedArea.StartRow || rUsedArea.EndRow < nRow)
- return;
-
- double fCurPos = rxProgressBar->getPosition();
- double fNewPos = static_cast<double>(nRow - rUsedArea.StartRow + 1.0) / (rUsedArea.EndRow - rUsedArea.StartRow + 1.0);
- if (fCurPos < fNewPos && (fNewPos - fCurPos) > 0.3)
- // Try not to re-draw progress bar too frequently.
- rxProgressBar->setPosition(fNewPos);
-}
-
void lclUpdateProgressBar( const ISegmentProgressBarRef& rxProgressBar, double fPosition )
{
if( rxProgressBar.get() )
@@ -228,7 +216,7 @@ void ValidationModel::setBiffErrorStyle( sal_uInt8 nErrorStyle )
// ============================================================================
// ============================================================================
-class WorksheetGlobals : public WorkbookHelper
+class WorksheetGlobals : public WorkbookHelper, public IWorksheetProgress
{
public:
explicit WorksheetGlobals(
@@ -236,6 +224,7 @@ public:
const ISegmentProgressBarRef& rxProgressBar,
WorksheetType eSheetType,
sal_Int16 nSheet );
+ virtual ~WorksheetGlobals() {}
/** Returns true, if this helper refers to an existing Calc sheet. */
inline bool isValidSheet() const { return mxSheet.is(); }
@@ -350,6 +339,17 @@ public:
void finalizeDrawingImport();
+ /// Allow the threaded importer to override our progress bar impl.
+ virtual ISegmentProgressBarRef getRowProgress()
+ {
+ return mxRowProgress;
+ }
+ virtual void setCustomRowProgress( const ISegmentProgressBarRef &rxRowProgress )
+ {
+ mxRowProgress = rxRowProgress;
+ mbFastRowProgress = true;
+ }
+
private:
typedef ::std::vector< sal_Int32 > OutlineLevelVec;
typedef ::std::pair< ColumnModel, sal_Int32 > ColumnModelRange;
@@ -387,6 +387,9 @@ private:
/** Imports the drawings of the sheet (DML, VML, DFF) and updates the used area. */
void finalizeDrawings();
+ /** Update the row import progress bar */
+ void UpdateRowProgress( const CellRangeAddress& rUsedArea, sal_Int32 nRow );
+
private:
typedef ::std::auto_ptr< VmlDrawing > VmlDrawingPtr;
typedef ::std::auto_ptr< BiffSheetDrawing > BiffSheetDrawingPtr;
@@ -417,6 +420,7 @@ private:
awt::Size maDrawPageSize; /// Current size of the drawing page in 1/100 mm.
awt::Rectangle maShapeBoundingBox; /// Bounding box for all shapes from all drawings.
ISegmentProgressBarRef mxProgressBar; /// Sheet progress bar.
+ bool mbFastRowProgress; /// Do we have a progress bar thread ?
ISegmentProgressBarRef mxRowProgress; /// Progress bar for row/cell processing.
ISegmentProgressBarRef mxFinalProgress; /// Progress bar for finalization.
WorksheetType meSheetType; /// Type of this sheet.
@@ -441,6 +445,7 @@ WorksheetGlobals::WorksheetGlobals( const WorkbookHelper& rHelper, const ISegmen
maPageSett( *this ),
maSheetViewSett( *this ),
mxProgressBar( rxProgressBar ),
+ mbFastRowProgress( false ),
meSheetType( eSheetType ),
mbHasDefWidth( false )
{
@@ -934,9 +939,30 @@ void WorksheetGlobals::setRowModel( const RowModel& rModel )
maSheetData.setColSpans( nRow, rModel.maColSpans );
}
}
- lclUpdateProgressBar( mxRowProgress, maUsedArea, nRow );
+
+ UpdateRowProgress( maUsedArea, nRow );
}
+// This is called at a higher frequency inside the (threaded) inner loop.
+void WorksheetGlobals::UpdateRowProgress( const CellRangeAddress& rUsedArea, sal_Int32 nRow )
+{
+ if (!mxRowProgress || nRow < rUsedArea.StartRow || rUsedArea.EndRow < nRow)
+ return;
+
+ double fNewPos = static_cast<double>(nRow - rUsedArea.StartRow + 1.0) / (rUsedArea.EndRow - rUsedArea.StartRow + 1.0);
+
+ if (mbFastRowProgress)
+ mxRowProgress->setPosition(fNewPos);
+ else
+ {
+ double fCurPos = mxRowProgress->getPosition();
+ if (fCurPos < fNewPos && (fNewPos - fCurPos) > 0.3)
+ // Try not to re-draw progress bar too frequently.
+ mxRowProgress->setPosition(fNewPos);
+ }
+}
+
+
void WorksheetGlobals::initializeWorksheetImport()
{
// set default cell style for unused cells
@@ -1395,6 +1421,11 @@ WorksheetHelper::WorksheetHelper( WorksheetGlobals& rSheetGlob ) :
return xSheetGlob;
}
+/* static */ IWorksheetProgress *WorksheetHelper::getWorksheetInterface( const WorksheetGlobalsRef &xRef )
+{
+ return static_cast< IWorksheetProgress *>( xRef.get() );
+}
+
WorksheetType WorksheetHelper::getSheetType() const
{
return mrSheetGlob.getSheetType();