SVN commit 629355 by nikolaus: Cleanup Move the calculation related methods to RecalcManager. SVN_SILENT M +4 -80 DependencyManager.cpp M +6 -21 DependencyManager.h M +124 -21 RecalcManager.cpp --- trunk/koffice/kspread/DependencyManager.cpp #629354:629355 @@ -111,11 +111,6 @@ void removeCircularDependencyFlags(const Region& region); /** - * Helper function for DependencyManager::cellsToCalculate(). - */ - void cellsToCalculate( const Region& region, QSet& cells ) const; - - /** * For debugging/testing purposes. */ void dump() const; @@ -282,57 +277,16 @@ } } -KSpread::Region DependencyManager::consumingRegion(const Cell& cell) const +QHash DependencyManager::depths() const { - return d->consumingRegion(cell); + return d->depths; } -QMap DependencyManager::cellsToCalculate( const Region& region ) const +KSpread::Region DependencyManager::consumingRegion(const Cell& cell) const { - if (region.isEmpty()) - return QMap(); - - QSet cells; - d->cellsToCalculate( region, cells ); - QMap depths; - foreach ( Cell cell, cells ) - depths.insertMulti( d->depths[cell], cell ); - return depths; + return d->consumingRegion(cell); } -QMap DependencyManager::cellsToCalculate( Sheet* sheet ) const -{ - // NOTE Stefan: It's necessary, that the cells are filled in row-wise; - // beginning with the top left; ending with the bottom right. - // This ensures, that the value storage is processed the same - // way, which boosts performance (using PointStorage) for an - // empty storage (on loading). For an already filled value - // storage, the speed gain is not that sensible. - QMap cells; - Cell cell; - if ( !sheet ) // map recalculation - { - for ( int s = 0; s < d->map->count(); ++s ) - { - sheet = d->map->sheet( s ); - for ( int c = 0; c < sheet->formulaStorage()->count(); ++c ) - { - cell = Cell( sheet, sheet->formulaStorage()->col( c ), sheet->formulaStorage()->row( c ) ); - cells.insertMulti( d->depths[cell], cell ); - } - } - } - else // sheet recalculation - { - for ( int c = 0; c < sheet->formulaStorage()->count(); ++c ) - { - cell = Cell( sheet, sheet->formulaStorage()->col( c ), sheet->formulaStorage()->row( c ) ); - cells.insertMulti( d->depths[cell], cell ); - } - } - return cells; -} - void DependencyManager::regionMoved( const Region& movedRegion, const Region::Point& destination ) { Region::Point locationOffset( destination.pos() - movedRegion.boundingRect().topLeft() ); @@ -726,33 +680,3 @@ } } } - -void DependencyManager::Private::cellsToCalculate( const Region& region, QSet& cells ) const -{ - Region::ConstIterator end(region.constEnd()); - for (Region::ConstIterator it(region.constBegin()); it != end; ++it) - { - const QRect range = (*it)->rect(); - const Sheet* sheet = (*it)->sheet(); - for (int col = range.left(); col <= range.right(); ++col) - { - for (int row = range.top(); row <= range.bottom(); ++row) - { - Cell cell( sheet,col, row); - // Even empty cells may act as value - // providers and need to be processed. - - // check for already processed cells - if ( cells.contains( cell ) ) - continue; - - // add it to the list - if ( cell.isFormula() ) - cells.insert( cell ); - - // add its consumers to the list - cellsToCalculate( consumingRegion( cell ), cells ); - } - } - } -} --- trunk/koffice/kspread/DependencyManager.h #629354:629355 @@ -55,6 +55,12 @@ void updateAllDependencies(const Map* map); /** + * Returns the cell depths. + * \return the cell depths + */ + QHash depths() const; + + /** * Returns the region, that consumes the value of \p cell. * \return region consuming \p cell 's value */ @@ -70,27 +76,6 @@ protected: /** - * Finds all cells in region and their dependents, that need recalculation. - * - * \return the cells, that need recalculation, ordered by reference depth - * - * \see RecalcManager::regionChanged - */ - QMap cellsToCalculate( const Region& region ) const; - - /** - * Finds all cells in \p sheet , that have got a formula and hence need - * recalculation. - * If \p sheet is zero, all cells in the Map a returned. - * - * \return the cells, that need recalculation, ordered by reference depth - * - * \see RecalcManager::recalcMap - * \see RecalcManager::recalcSheet - */ - QMap cellsToCalculate( Sheet* sheet = 0 ) const; - - /** * \param cell the cell which formula should be altered * \param oldLocation the location/range, that was cut * \param offset the relative movement and new sheet, if applicable --- trunk/koffice/kspread/RecalcManager.cpp #629354:629355 @@ -22,6 +22,7 @@ #include #include "Cell.h" +#include "CellStorage.h" #include "DependencyManager.h" #include "Formula.h" #include "Map.h" @@ -37,26 +38,128 @@ class RecalcManager::Private { public: - /** - * Stores cells ordered by its reference depth. - * Depth means the maximum depth of all cells this cell depends on plus one, - * while a cell which has a formula without cell references has a depth - * of zero. - * - * Examples: - * \li A1: '=1.0' - * \li A2: '=A1+A1' - * \li A3: '=A1+A1+A2' - * - * \li depth(A1) = 0 - * \li depth(A2) = 1 - * \li depth(A3) = 2 - */ - QMap cells; - const Map* map; - bool busy; + /** + * Finds all cells in region and their dependents, that need recalculation. + * + * \see RecalcManager::regionChanged + */ + void cellsToCalculate( const Region& region ); + + /** + * Finds all cells in \p sheet , that have got a formula and hence need + * recalculation. + * If \p sheet is zero, all cells in the Map a returned. + * + * \see RecalcManager::recalcMap + * \see RecalcManager::recalcSheet + */ + void cellsToCalculate( Sheet* sheet = 0 ); + + /** + * Helper function for cellsToCalculate(const Region&) and cellsToCalculate(Sheet*). + */ + void cellsToCalculate( const Region& region, QSet& cells ) const; + + /* + * Stores cells ordered by its reference depth. + * Depth means the maximum depth of all cells this cell depends on plus one, + * while a cell which has a formula without cell references has a depth + * of zero. + * + * Examples: + * \li A1: '=1.0' + * \li A2: '=A1+A1' + * \li A3: '=A1+A1+A2' + * + * \li depth(A1) = 0 + * \li depth(A2) = 1 + * \li depth(A3) = 2 + */ + QMap cells; + const Map* map; + bool busy; }; +void RecalcManager::Private::cellsToCalculate( const Region& region ) +{ + if (region.isEmpty()) + return; + + // retrieve the cell depths + QHash depths = map->dependencyManager()->depths(); + + // create the cell map ordered by depth + QSet cells; + cellsToCalculate( region, cells ); + const QSet::ConstIterator end( cells.end() ); + for ( QSet::ConstIterator it( cells.begin() ); it != end; ++it ) + this->cells.insertMulti( depths[*it], *it ); +} + +void RecalcManager::Private::cellsToCalculate( Sheet* sheet ) +{ + // retrieve the cell depths + QHash depths = map->dependencyManager()->depths(); + + // NOTE Stefan: It's necessary, that the cells are filled in row-wise; + // beginning with the top left; ending with the bottom right. + // This ensures, that the value storage is processed the same + // way, which boosts performance (using PointStorage) for an + // empty storage (on loading). For an already filled value + // storage, the speed gain is not that sensible. + Cell cell; + if ( !sheet ) // map recalculation + { + for ( int s = 0; s < map->count(); ++s ) + { + sheet = map->sheet( s ); + for ( int c = 0; c < sheet->formulaStorage()->count(); ++c ) + { + cell = Cell( sheet, sheet->formulaStorage()->col( c ), sheet->formulaStorage()->row( c ) ); + cells.insertMulti( depths[cell], cell ); + } + } + } + else // sheet recalculation + { + for ( int c = 0; c < sheet->formulaStorage()->count(); ++c ) + { + cell = Cell( sheet, sheet->formulaStorage()->col( c ), sheet->formulaStorage()->row( c ) ); + cells.insertMulti( depths[cell], cell ); + } + } +} + +void RecalcManager::Private::cellsToCalculate( const Region& region, QSet& cells ) const +{ + Region::ConstIterator end(region.constEnd()); + for (Region::ConstIterator it(region.constBegin()); it != end; ++it) + { + const QRect range = (*it)->rect(); + const Sheet* sheet = (*it)->sheet(); + for (int col = range.left(); col <= range.right(); ++col) + { + for (int row = range.top(); row <= range.bottom(); ++row) + { + Cell cell( sheet,col, row); + // Even empty cells may act as value + // providers and need to be processed. + + // check for already processed cells + if ( cells.contains( cell ) ) + continue; + + // add it to the list + if ( cell.isFormula() ) + cells.insert( cell ); + + // add its consumers to the list + cellsToCalculate( map->dependencyManager()->consumingRegion( cell ), cells ); + } + } + } +} + RecalcManager::RecalcManager( const Map* map ) : d(new Private) { @@ -76,7 +179,7 @@ d->busy = true; kDebug(36002) << "RecalcManager::regionChanged " << region.name() << endl; ElapsedTime et( "Overall region recalculation", ElapsedTime::PrintOnlyTime ); - d->cells = d->map->dependencyManager()->cellsToCalculate( region ); + d->cellsToCalculate( region ); recalc(); d->busy = false; } @@ -87,7 +190,7 @@ return; d->busy = true; ElapsedTime et( "Overall sheet recalculation", ElapsedTime::PrintOnlyTime ); - d->cells = d->map->dependencyManager()->cellsToCalculate( sheet ); + d->cellsToCalculate( sheet ); recalc(); d->busy = false; } @@ -98,7 +201,7 @@ return; d->busy = true; ElapsedTime et( "Overall map recalculation", ElapsedTime::PrintOnlyTime ); - d->cells = d->map->dependencyManager()->cellsToCalculate(); + d->cellsToCalculate(); recalc(); d->busy = false; }