kspread

CellStorage.cpp

Go to the documentation of this file.
00001 /* This file is part of the KDE project
00002    Copyright 2007 Stefan Nikolaus <stefan.nikolaus@kdemail.net>
00003 
00004    This library is free software; you can redistribute it and/or
00005    modify it under the terms of the GNU Library General Public
00006    License as published by the Free Software Foundation; either
00007    version 2 of the License, or (at your option) any later version.
00008 
00009    This library is distributed in the hope that it will be useful,
00010    but WITHOUT ANY WARRANTY; without even the implied warranty of
00011    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012    Library General Public License for more details.
00013 
00014    You should have received a copy of the GNU Library General Public License
00015    along with this library; see the file COPYING.LIB.  If not, write to
00016    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00017    Boston, MA 02110-1301, USA.
00018 */
00019 
00020 // Local
00021 #include "CellStorage.h"
00022 #include "CellStorage_p.h"
00023 
00024 // KDE
00025 #include <klocale.h>
00026 
00027 // KOffice
00028 #include <KoXmlWriter.h>
00029 
00030 // KSpread
00031 #include "BindingStorage.h"
00032 #include "ConditionsStorage.h"
00033 #include "Damages.h"
00034 #include "DependencyManager.h"
00035 #include "FormulaStorage.h"
00036 #include "Map.h"
00037 #include "RecalcManager.h"
00038 #include "RectStorage.h"
00039 #include "Sheet.h"
00040 #include "StyleStorage.h"
00041 #include "ValidityStorage.h"
00042 #include "ValueStorage.h"
00043 
00044 // database
00045 #include "database/DatabaseStorage.h"
00046 #include "database/DatabaseManager.h"
00047 
00048 using namespace KSpread;
00049 
00050 typedef RectStorage<QString> NamedAreaStorage;
00051 
00052 class CellStorage::Private
00053 {
00054 public:
00055     Private( Sheet* sheet )
00056         : sheet( sheet )
00057         , bindingStorage( new BindingStorage(sheet->map()) )
00058         , commentStorage( new CommentStorage(sheet->map()) )
00059         , conditionsStorage( new ConditionsStorage(sheet->map()) )
00060         , databaseStorage( new DatabaseStorage(sheet->map()) )
00061         , formulaStorage( new FormulaStorage() )
00062         , fusionStorage( new FusionStorage(sheet->map()) )
00063         , linkStorage( new LinkStorage() )
00064         , matrixStorage( new MatrixStorage(sheet->map()) )
00065         , namedAreaStorage( new NamedAreaStorage(sheet->map()) )
00066         , styleStorage( new StyleStorage(sheet->map()) )
00067         , userInputStorage( new UserInputStorage() )
00068         , validityStorage( new ValidityStorage(sheet->map()) )
00069         , valueStorage( new ValueStorage() )
00070         , undoData( 0 ) {}
00071 
00072     Private(const Private& other, Sheet* sheet)
00073         : sheet(sheet)
00074         , bindingStorage(new BindingStorage(*other.bindingStorage))
00075         , commentStorage(new CommentStorage(*other.commentStorage))
00076         , conditionsStorage(new ConditionsStorage(*other.conditionsStorage))
00077         , databaseStorage(new DatabaseStorage(*other.databaseStorage))
00078         , formulaStorage(new FormulaStorage(*other.formulaStorage))
00079         , fusionStorage(new FusionStorage(*other.fusionStorage))
00080         , linkStorage(new LinkStorage(*other.linkStorage))
00081         , matrixStorage(new MatrixStorage(*other.matrixStorage))
00082         , namedAreaStorage(new NamedAreaStorage(*other.namedAreaStorage))
00083         , styleStorage(new StyleStorage(*other.styleStorage))
00084         , userInputStorage(new UserInputStorage(*other.userInputStorage))
00085         , validityStorage(new ValidityStorage(*other.validityStorage))
00086         , valueStorage(new ValueStorage(*other.valueStorage))
00087         , undoData(0) {}
00088 
00089     ~Private()
00090     {
00091         delete bindingStorage;
00092         delete commentStorage;
00093         delete conditionsStorage;
00094         delete databaseStorage;
00095         delete formulaStorage;
00096         delete fusionStorage;
00097         delete linkStorage;
00098         delete matrixStorage;
00099         delete namedAreaStorage;
00100         delete styleStorage;
00101         delete userInputStorage;
00102         delete validityStorage;
00103         delete valueStorage;
00104     }
00105 
00106     Sheet*                  sheet;
00107     BindingStorage*         bindingStorage;
00108     CommentStorage*         commentStorage;
00109     ConditionsStorage*      conditionsStorage;
00110     DatabaseStorage*        databaseStorage;
00111     FormulaStorage*         formulaStorage;
00112     FusionStorage*          fusionStorage;
00113     LinkStorage*            linkStorage;
00114     MatrixStorage*          matrixStorage;
00115     NamedAreaStorage*       namedAreaStorage;
00116     StyleStorage*           styleStorage;
00117     UserInputStorage*       userInputStorage;
00118     ValidityStorage*        validityStorage;
00119     ValueStorage*           valueStorage;
00120     CellStorageUndoData*    undoData;
00121 };
00122 
00123 CellStorage::CellStorage( Sheet* sheet )
00124     : QObject( sheet )
00125     , d( new Private( sheet ) )
00126 {
00127 }
00128 
00129 CellStorage::CellStorage( const CellStorage& other )
00130     : QObject( other.d->sheet )
00131     , d( new Private( *other.d ) )
00132 {
00133 }
00134 
00135 CellStorage::CellStorage(const CellStorage& other, Sheet* sheet)
00136     : QObject(sheet)
00137     , d(new Private(*other.d, sheet))
00138 {
00139 }
00140 
00141 CellStorage::~CellStorage()
00142 {
00143     delete d;
00144 }
00145 
00146 void CellStorage::take( int col, int row )
00147 {
00148     Formula oldFormula;
00149     QString oldLink;
00150     QString oldUserInput;
00151     Value oldValue;
00152 
00153     oldFormula = d->formulaStorage->take( col, row );
00154     oldLink = d->linkStorage->take( col, row );
00155     oldUserInput = d->userInputStorage->take( col, row );
00156     oldValue = d->valueStorage->take( col, row );
00157 
00158     if (!d->sheet->map()->isLoading())
00159     {
00160         // Trigger a recalculation of the consuming cells.
00161         CellDamage::Changes changes = CellDamage:: Binding | CellDamage::Formula | CellDamage::Value;
00162         d->sheet->map()->addDamage(new CellDamage(Cell(d->sheet, col, row), changes));
00163     }
00164 
00165     // recording undo?
00166     if ( d->undoData )
00167     {
00168         d->undoData->formulas   << qMakePair( QPoint( col, row ), oldFormula );
00169         d->undoData->links      << qMakePair( QPoint( col, row ), oldLink );
00170         d->undoData->userInputs << qMakePair( QPoint( col, row ), oldUserInput );
00171         d->undoData->values     << qMakePair( QPoint( col, row ), oldValue );
00172     }
00173 }
00174 
00175 Binding CellStorage::binding( int column, int row ) const
00176 {
00177     return d->bindingStorage->contains( QPoint( column, row ) );
00178 }
00179 
00180 void CellStorage::setBinding( const Region& region, const Binding& binding )
00181 {
00182     // recording undo?
00183     if ( d->undoData )
00184         d->undoData->bindings << d->bindingStorage->undoData( region );
00185 
00186     d->bindingStorage->insert( region, binding );
00187 }
00188 
00189 void CellStorage::removeBinding(const Region& region, const Binding& binding)
00190 {
00191     // recording undo?
00192     if (d->undoData) {
00193         d->undoData->bindings << d->bindingStorage->undoData(region);
00194     }
00195     d->bindingStorage->remove(region, binding);
00196 }
00197 
00198 QString CellStorage::comment( int column, int row ) const
00199 {
00200     return d->commentStorage->contains( QPoint( column, row ) );
00201 }
00202 
00203 void CellStorage::setComment( const Region& region, const QString& comment )
00204 {
00205     // recording undo?
00206     if ( d->undoData )
00207         d->undoData->comments << d->commentStorage->undoData( region );
00208 
00209     d->commentStorage->insert( region, comment );
00210 }
00211 
00212 Conditions CellStorage::conditions( int column, int row ) const
00213 {
00214     return d->conditionsStorage->contains( QPoint( column, row ) );
00215 }
00216 
00217 void CellStorage::setConditions( const Region& region, Conditions conditions )
00218 {
00219     // recording undo?
00220     if ( d->undoData )
00221         d->undoData->conditions << d->conditionsStorage->undoData( region );
00222 
00223     d->conditionsStorage->insert( region, conditions );
00224 }
00225 
00226 Database CellStorage::database( int column, int row ) const
00227 {
00228     QPair<QRectF, Database> pair = d->databaseStorage->containedPair( QPoint( column, row ) );
00229     if ( pair.first.isEmpty() )
00230         return Database();
00231     if ( pair.second.isEmpty() )
00232         return Database();
00233     // update the range, which might get changed
00234     Database database = pair.second;
00235     database.setRange( Region( pair.first.toRect(), d->sheet ) );
00236     return database;
00237 }
00238 
00239 QList< QPair<QRectF, Database> > CellStorage::databases(const Region& region) const
00240 {
00241     return d->databaseStorage->intersectingPairs(region);
00242 }
00243 
00244 void CellStorage::setDatabase( const Region& region, const Database& database )
00245 {
00246     // recording undo?
00247     if ( d->undoData )
00248         d->undoData->databases << d->databaseStorage->undoData( region );
00249 
00250     d->databaseStorage->insert( region, database );
00251 }
00252 
00253 Formula CellStorage::formula( int column, int row ) const
00254 {
00255     return d->formulaStorage->lookup( column, row );
00256 }
00257 
00258 void CellStorage::setFormula( int column, int row, const Formula& formula )
00259 {
00260     Formula old;
00261     if ( formula.expression().isEmpty() )
00262         old = d->formulaStorage->take( column, row );
00263     else
00264         old = d->formulaStorage->insert( column, row, formula );
00265 
00266     // formula changed?
00267     if ( formula != old )
00268     {
00269         if ( !d->sheet->map()->isLoading() )
00270         {
00271             // trigger an update of the dependencies and a recalculation
00272             d->sheet->map()->addDamage( new CellDamage( Cell( d->sheet, column, row ), CellDamage::Formula | CellDamage::Value ) );
00273         }
00274         // recording undo?
00275         if ( d->undoData )
00276         {
00277             d->undoData->formulas << qMakePair( QPoint( column, row ), old );
00278             // Also store the old value, if there wasn't a formula before,
00279             // because the new value is calculated later by the damage
00280             // processing and is not recorded for undoing.
00281             if ( old == Formula() )
00282                 d->undoData->values << qMakePair( QPoint( column, row ), value( column, row ) );
00283         }
00284     }
00285 }
00286 
00287 QString CellStorage::link( int column, int row ) const
00288 {
00289     return d->linkStorage->lookup( column, row );
00290 }
00291 
00292 void CellStorage::setLink( int column, int row, const QString& link )
00293 {
00294     QString old;
00295     if ( link.isEmpty() )
00296         old = d->linkStorage->take( column, row );
00297     else
00298         old = d->linkStorage->insert( column, row, link );
00299 
00300     // recording undo?
00301     if ( d->undoData && link != old )
00302         d->undoData->links << qMakePair( QPoint( column, row ), old );
00303 }
00304 
00305 QString CellStorage::namedArea( int column, int row ) const
00306 {
00307     QPair<QRectF, QString> pair = d->namedAreaStorage->containedPair( QPoint( column, row ) );
00308     if ( pair.first.isEmpty() )
00309         return QString();
00310     if ( pair.second.isEmpty() )
00311         return QString();
00312     return pair.second;
00313 }
00314 
00315 QList< QPair<QRectF, QString> > CellStorage::namedAreas(const Region& region) const
00316 {
00317     return d->namedAreaStorage->intersectingPairs(region);
00318 }
00319 
00320 void CellStorage::setNamedArea( const Region& region, const QString& namedArea )
00321 {
00322     // recording undo?
00323     if ( d->undoData )
00324         d->undoData->namedAreas << d->namedAreaStorage->undoData( region );
00325 
00326     d->namedAreaStorage->insert( region, namedArea );
00327 }
00328 
00329 Style CellStorage::style( int column, int row ) const
00330 {
00331     return d->styleStorage->contains( QPoint( column, row ) );
00332 }
00333 
00334 Style CellStorage::style( const QRect& rect ) const
00335 {
00336     return d->styleStorage->contains( rect );
00337 }
00338 
00339 void CellStorage::setStyle( const Region& region, const Style& style )
00340 {
00341     // recording undo?
00342     if ( d->undoData )
00343         d->undoData->styles << d->styleStorage->undoData( region );
00344 
00345     d->styleStorage->insert( region, style );
00346 }
00347 
00348 QString CellStorage::userInput( int column, int row ) const
00349 {
00350     return d->userInputStorage->lookup( column, row );
00351 }
00352 
00353 void CellStorage::setUserInput( int column, int row, const QString& userInput )
00354 {
00355     QString old;
00356     if ( userInput.isEmpty() )
00357         old = d->userInputStorage->take( column, row );
00358     else
00359         old = d->userInputStorage->insert( column, row, userInput );
00360 
00361     // recording undo?
00362     if ( d->undoData && userInput != old )
00363         d->undoData->userInputs << qMakePair( QPoint( column, row ), old );
00364 }
00365 
00366 Validity CellStorage::validity( int column, int row ) const
00367 {
00368     return d->validityStorage->contains( QPoint( column, row ) );
00369 }
00370 
00371 void CellStorage::setValidity( const Region& region, Validity validity )
00372 {
00373     // recording undo?
00374     if ( d->undoData )
00375         d->undoData->validities << d->validityStorage->undoData( region );
00376 
00377     d->validityStorage->insert( region, validity );
00378 }
00379 
00380 Value CellStorage::value( int column, int row ) const
00381 {
00382     return d->valueStorage->lookup( column, row );
00383 }
00384 
00385 Value CellStorage::valueRegion( const Region& region ) const
00386 {
00387     // create a subStorage with adjusted origin
00388     return Value( d->valueStorage->subStorage( region, false ) );
00389 }
00390 
00391 void CellStorage::setValue( int column, int row, const Value& value )
00392 {
00393     // release any lock
00394     unlockCells( column, row );
00395 
00396     Value old;
00397     if ( value.isEmpty() )
00398         old = d->valueStorage->take( column, row );
00399     else
00400         old = d->valueStorage->insert( column, row, value );
00401 
00402     // value changed?
00403     if ( value != old )
00404     {
00405         if ( !d->sheet->map()->isLoading() )
00406         {
00407             // Always trigger a repainting and a binding update.
00408             CellDamage::Changes changes = CellDamage::Appearance | CellDamage::Binding;
00409             // Trigger a recalculation of the consuming cells, only if we are not
00410             // already in a recalculation process.
00411             if ( !d->sheet->map()->recalcManager()->isActive() )
00412                 changes |= CellDamage::Value;
00413             d->sheet->map()->addDamage( new CellDamage( Cell( d->sheet, column, row ), changes ) );
00414             // Also trigger a relayouting of the first non-empty cell to the left of this one
00415             int prevCol;
00416             Value v = d->valueStorage->prevInRow( column, row, &prevCol );
00417             if ( !v.isEmpty() )
00418                 d->sheet->map()->addDamage( new CellDamage( Cell( d->sheet, prevCol, row ), CellDamage::Appearance ) );
00419         }
00420         // recording undo?
00421         if ( d->undoData )
00422             d->undoData->values << qMakePair( QPoint( column, row ), old );
00423     }
00424 }
00425 
00426 bool CellStorage::doesMergeCells( int column, int row ) const
00427 {
00428     const QPair<QRectF,bool> pair = d->fusionStorage->containedPair( QPoint( column, row ) );
00429     if ( pair.first.isNull() )
00430         return false;
00431     if ( pair.second == false )
00432         return false;
00433     // master cell?
00434     if ( pair.first.toRect().topLeft() != QPoint( column, row ) )
00435         return false;
00436     return true;
00437 }
00438 
00439 bool CellStorage::isPartOfMerged( int column, int row ) const
00440 {
00441     const QPair<QRectF,bool> pair = d->fusionStorage->containedPair( QPoint( column, row ) );
00442     if ( pair.first.isNull() )
00443         return false;
00444     if ( pair.second == false )
00445         return false;
00446     // master cell?
00447     if ( pair.first.toRect().topLeft() == QPoint( column, row ) )
00448         return false;
00449     return true;
00450 }
00451 
00452 void CellStorage::mergeCells( int column, int row, int numXCells, int numYCells )
00453 {
00454     // Start by unmerging the cells that we merge right now
00455     const QPair<QRectF,bool> pair = d->fusionStorage->containedPair( QPoint( column, row ) );
00456     if ( !pair.first.isNull() )
00457         d->fusionStorage->insert( Region( pair.first.toRect() ), false );
00458     // Merge the cells
00459     if ( numXCells != 0 || numYCells != 0 )
00460         d->fusionStorage->insert( Region( column, row, numXCells + 1, numYCells + 1 ), true );
00461 }
00462 
00463 Cell CellStorage::masterCell( int column, int row ) const
00464 {
00465     const QPair<QRectF,bool> pair = d->fusionStorage->containedPair( QPoint( column, row ) );
00466     if ( pair.first.isNull() )
00467         return Cell( d->sheet, column, row );
00468     if ( pair.second == false )
00469         return Cell( d->sheet, column, row );
00470     return Cell( d->sheet, pair.first.toRect().topLeft() );
00471 }
00472 
00473 int CellStorage::mergedXCells( int column, int row ) const
00474 {
00475     const QPair<QRectF,bool> pair = d->fusionStorage->containedPair( QPoint( column, row ) );
00476     if ( pair.first.isNull() )
00477         return 0;
00478     // Not the master cell?
00479     if ( pair.first.topLeft() != QPoint( column, row ) )
00480         return 0;
00481     return pair.first.toRect().width() - 1;
00482 }
00483 
00484 int CellStorage::mergedYCells( int column, int row ) const
00485 {
00486     const QPair<QRectF,bool> pair = d->fusionStorage->containedPair( QPoint( column, row ) );
00487     if ( pair.first.isNull() )
00488         return 0;
00489     // Not the master cell?
00490     if ( pair.first.topLeft() != QPoint( column, row ) )
00491         return 0;
00492     return pair.first.toRect().height() - 1;
00493 }
00494 
00495 QList<Cell> CellStorage::masterCells(const Region& region) const
00496 {
00497     const QList<QPair<QRectF, bool> > pairs = d->fusionStorage->intersectingPairs(region);
00498     if (pairs.isEmpty())
00499         return QList<Cell>();
00500     QList<Cell> masterCells;
00501     for (int i = 0; i < pairs.count(); ++i)
00502     {
00503         if (pairs[i].first.isNull())
00504             continue;
00505         if (pairs[i].second == false)
00506             continue;
00507         masterCells.append(Cell(d->sheet, pairs[i].first.toRect().topLeft()));
00508     }
00509     return masterCells;
00510 }
00511 
00512 bool CellStorage::locksCells( int column, int row ) const
00513 {
00514     const QPair<QRectF,bool> pair = d->matrixStorage->containedPair( QPoint( column, row ) );
00515     if ( pair.first.isNull() )
00516         return false;
00517     if ( pair.second == false )
00518         return false;
00519     // master cell?
00520     if ( pair.first.toRect().topLeft() != QPoint( column, row ) )
00521         return false;
00522     return true;
00523 }
00524 
00525 bool CellStorage::isLocked( int column, int row ) const
00526 {
00527     const QPair<QRectF,bool> pair = d->matrixStorage->containedPair( QPoint( column, row ) );
00528     if ( pair.first.isNull() )
00529         return false;
00530     if ( pair.second == false )
00531         return false;
00532     // master cell?
00533     if ( pair.first.toRect().topLeft() == QPoint( column, row ) )
00534         return false;
00535     return true;
00536 }
00537 
00538 void CellStorage::lockCells( const QRect& rect )
00539 {
00540     // Start by unlocking the cells that we lock right now
00541     const QPair<QRectF,bool> pair = d->matrixStorage->containedPair( rect.topLeft() ); // FIXME
00542     if ( !pair.first.isNull() )
00543         d->matrixStorage->insert( Region( pair.first.toRect() ), false );
00544     // Lock the cells
00545     if ( rect.width() > 1 || rect.height() > 1 )
00546         d->matrixStorage->insert( Region( rect ), true );
00547 }
00548 
00549 void CellStorage::unlockCells( int column, int row )
00550 {
00551     const QPair<QRectF,bool> pair = d->matrixStorage->containedPair( QPoint( column, row ) );
00552     if ( pair.first.isNull() )
00553         return;
00554     if ( pair.second == false )
00555         return;
00556     if ( pair.first.toRect().topLeft() != QPoint( column, row ) )
00557         return;
00558     const QRect rect = pair.first.toRect();
00559     d->matrixStorage->insert( Region( rect ), false );
00560     // clear the values
00561     for ( int r = rect.top(); r <= rect.bottom(); ++r )
00562     {
00563         for ( int c = rect.left(); c <= rect.right(); ++c )
00564         {
00565             if ( r != rect.top() || c != rect.left() )
00566                 setValue( c, r, Value() );
00567         }
00568     }
00569     // recording undo?
00570     if ( d->undoData )
00571         d->undoData->matrices << pair;
00572 }
00573 
00574 QRect CellStorage::lockedCells( int column, int row ) const
00575 {
00576     const QPair<QRectF,bool> pair = d->matrixStorage->containedPair( QPoint( column, row ) );
00577     if ( pair.first.isNull() )
00578         return QRect( column, row, 1, 1 );
00579     if ( pair.second == false )
00580         return QRect( column, row, 1, 1 );
00581     if ( pair.first.toRect().topLeft() != QPoint( column, row ) )
00582         return QRect( column, row, 1, 1 );
00583     return pair.first.toRect();
00584 }
00585 
00586 void CellStorage::insertColumns( int position, int number )
00587 {
00588     // Trigger a dependency update of the cells, which have a formula. (old positions)
00589     // FIXME Stefan: Would it be better to directly alter the dependency tree?
00590     // TODO Stefan: Optimize: Avoid the double creation of the sub-storages, but don't process
00591     //              formulas, that will get out of bounds after the operation.
00592     const Region invalidRegion(QRect(QPoint(position, 1), QPoint(KS_colMax, KS_rowMax)), d->sheet);
00593     PointStorage<Formula> subStorage = d->formulaStorage->subStorage(invalidRegion);
00594     Cell cell;
00595     for (int i = 0; i < subStorage.count(); ++i)
00596     {
00597         cell = Cell(d->sheet, subStorage.col(i), subStorage.row(i));
00598         d->sheet->map()->addDamage(new CellDamage(cell, CellDamage::Formula));
00599     }
00600     // Trigger an update of the bindings and the named areas.
00601     d->sheet->map()->addDamage(new CellDamage(d->sheet, invalidRegion, CellDamage::Binding | CellDamage::NamedArea));
00602 
00603     QList< QPair<QRectF,Binding> > bindings = d->bindingStorage->insertColumns( position, number );
00604     QList< QPair<QRectF,QString> > comments = d->commentStorage->insertColumns( position, number );
00605     QList< QPair<QRectF,Conditions> > conditions = d->conditionsStorage->insertColumns( position, number );
00606     QList< QPair<QRectF,Database> > databases = d->databaseStorage->insertColumns( position, number );
00607     QVector< QPair<QPoint,Formula> > formulas = d->formulaStorage->insertColumns( position, number );
00608     QList< QPair<QRectF,bool> > fusions = d->fusionStorage->insertColumns( position, number );
00609     QVector< QPair<QPoint,QString> > links = d->linkStorage->insertColumns( position, number );
00610     QList< QPair<QRectF,bool> > matrices = d->matrixStorage->insertColumns( position, number );
00611     QList< QPair<QRectF,QString> > namedAreas = d->namedAreaStorage->insertColumns( position, number );
00612     QList< QPair<QRectF,SharedSubStyle> > styles = d->styleStorage->insertColumns( position, number );
00613     QVector< QPair<QPoint,QString> > userInputs = d->userInputStorage->insertColumns( position, number );
00614     QList< QPair<QRectF,Validity> > validities = d->validityStorage->insertColumns( position, number );
00615     QVector< QPair<QPoint,Value> > values = d->valueStorage->insertColumns( position, number );
00616     // recording undo?
00617     if ( d->undoData )
00618     {
00619         d->undoData->bindings   << bindings;
00620         d->undoData->comments   << comments;
00621         d->undoData->conditions << conditions;
00622         d->undoData->databases  << databases;
00623         d->undoData->formulas   << formulas;
00624         d->undoData->fusions    << fusions;
00625         d->undoData->links      << links;
00626         d->undoData->matrices   << matrices;
00627         d->undoData->namedAreas << namedAreas;
00628         d->undoData->styles     << styles;
00629         d->undoData->userInputs << userInputs;
00630         d->undoData->validities << validities;
00631         d->undoData->values     << values;
00632     }
00633 
00634     // Trigger a dependency update of the cells, which have a formula. (new positions)
00635     subStorage = d->formulaStorage->subStorage(invalidRegion);
00636     for (int i = 0; i < subStorage.count(); ++i)
00637     {
00638         cell = Cell(d->sheet, subStorage.col(i), subStorage.row(i));
00639         d->sheet->map()->addDamage(new CellDamage(cell, CellDamage::Formula));
00640     }
00641     // Trigger a recalculation only for the cells, that depend on values in the changed region.
00642     Region providers = d->sheet->map()->dependencyManager()->reduceToProvidingRegion(invalidRegion);
00643     d->sheet->map()->addDamage(new CellDamage(d->sheet, providers, CellDamage::Value));
00644 }
00645 
00646 void CellStorage::removeColumns( int position, int number )
00647 {
00648     // Trigger a dependency update of the cells, which have a formula. (old positions)
00649     const Region invalidRegion(QRect(QPoint(position, 1), QPoint(KS_colMax, KS_rowMax)), d->sheet);
00650     PointStorage<Formula> subStorage = d->formulaStorage->subStorage(invalidRegion);
00651     Cell cell;
00652     for (int i = 0; i < subStorage.count(); ++i)
00653     {
00654         cell = Cell(d->sheet, subStorage.col(i), subStorage.row(i));
00655         d->sheet->map()->addDamage(new CellDamage(cell, CellDamage::Formula));
00656     }
00657     // Trigger an update of the bindings and the named areas.
00658     const Region region(QRect(QPoint(position - 1, 1), QPoint(KS_colMax, KS_rowMax)), d->sheet);
00659     d->sheet->map()->addDamage(new CellDamage(d->sheet, region, CellDamage::Binding | CellDamage::NamedArea));
00660 
00661     QList< QPair<QRectF,Binding> > bindings = d->bindingStorage->removeColumns( position, number );
00662     QList< QPair<QRectF,QString> > comments = d->commentStorage->removeColumns( position, number );
00663     QList< QPair<QRectF,Conditions> > conditions = d->conditionsStorage->removeColumns( position, number );
00664     QList< QPair<QRectF,Database> > databases = d->databaseStorage->removeColumns( position, number );
00665     QVector< QPair<QPoint,Formula> > formulas = d->formulaStorage->removeColumns( position, number );
00666     QList< QPair<QRectF,bool> > fusions = d->fusionStorage->removeColumns( position, number );
00667     QVector< QPair<QPoint,QString> > links = d->linkStorage->removeColumns( position, number );
00668     QList< QPair<QRectF,bool> > matrices = d->matrixStorage->removeColumns( position, number );
00669     QList< QPair<QRectF,QString> > namedAreas = d->namedAreaStorage->removeColumns( position, number );
00670     QList< QPair<QRectF,SharedSubStyle> > styles = d->styleStorage->removeColumns( position, number );
00671     QVector< QPair<QPoint,QString> > userInputs = d->userInputStorage->removeColumns( position, number );
00672     QList< QPair<QRectF,Validity> > validities = d->validityStorage->removeColumns( position, number );
00673     QVector< QPair<QPoint,Value> > values = d->valueStorage->removeColumns( position, number );
00674     // recording undo?
00675     if ( d->undoData )
00676     {
00677         d->undoData->bindings   << bindings;
00678         d->undoData->comments   << comments;
00679         d->undoData->conditions << conditions;
00680         d->undoData->databases  << databases;
00681         d->undoData->formulas   << formulas;
00682         d->undoData->fusions    << fusions;
00683         d->undoData->links      << links;
00684         d->undoData->matrices   << matrices;
00685         d->undoData->namedAreas << namedAreas;
00686         d->undoData->styles     << styles;
00687         d->undoData->userInputs << userInputs;
00688         d->undoData->validities << validities;
00689         d->undoData->values     << values;
00690     }
00691 
00692     // Trigger a dependency update of the cells, which have a formula. (new positions)
00693     subStorage = d->formulaStorage->subStorage(invalidRegion);
00694     for (int i = 0; i < subStorage.count(); ++i)
00695     {
00696         cell = Cell(d->sheet, subStorage.col(i), subStorage.row(i));
00697         d->sheet->map()->addDamage(new CellDamage(cell, CellDamage::Formula));
00698     }
00699     // Trigger a recalculation only for the cells, that depend on values in the changed region.
00700     Region providers = d->sheet->map()->dependencyManager()->reduceToProvidingRegion(invalidRegion);
00701     d->sheet->map()->addDamage(new CellDamage(d->sheet, providers, CellDamage::Value));
00702 }
00703 
00704 void CellStorage::insertRows( int position, int number )
00705 {
00706     // Trigger a dependency update of the cells, which have a formula. (old positions)
00707     const Region invalidRegion(QRect(QPoint(1, position), QPoint(KS_colMax, KS_rowMax)), d->sheet);
00708     PointStorage<Formula> subStorage = d->formulaStorage->subStorage(invalidRegion);
00709     Cell cell;
00710     for (int i = 0; i < subStorage.count(); ++i)
00711     {
00712         cell = Cell(d->sheet, subStorage.col(i), subStorage.row(i));
00713         d->sheet->map()->addDamage(new CellDamage(cell, CellDamage::Formula));
00714     }
00715     // Trigger an update of the bindings and the named areas.
00716     d->sheet->map()->addDamage(new CellDamage(d->sheet, invalidRegion, CellDamage::Binding | CellDamage::NamedArea));
00717 
00718     QList< QPair<QRectF,Binding> > bindings = d->bindingStorage->insertRows( position, number );
00719     QList< QPair<QRectF,QString> > comments = d->commentStorage->insertRows( position, number );
00720     QList< QPair<QRectF,Conditions> > conditions = d->conditionsStorage->insertRows( position, number );
00721     QList< QPair<QRectF,Database> > databases = d->databaseStorage->insertRows( position, number );
00722     QVector< QPair<QPoint,Formula> > formulas = d->formulaStorage->insertRows( position, number );
00723     QList< QPair<QRectF,bool> > fusions = d->fusionStorage->insertRows( position, number );
00724     QVector< QPair<QPoint,QString> > links = d->linkStorage->insertRows( position, number );
00725     QList< QPair<QRectF,bool> > matrices = d->matrixStorage->insertRows( position, number );
00726     QList< QPair<QRectF,QString> > namedAreas = d->namedAreaStorage->insertRows( position, number );
00727     QList< QPair<QRectF,SharedSubStyle> > styles = d->styleStorage->insertRows( position, number );
00728     QVector< QPair<QPoint,QString> > userInputs = d->userInputStorage->insertRows( position, number );
00729     QList< QPair<QRectF,Validity> > validities = d->validityStorage->insertRows( position, number );
00730     QVector< QPair<QPoint,Value> > values = d->valueStorage->insertRows( position, number );
00731     // recording undo?
00732     if ( d->undoData )
00733     {
00734         d->undoData->bindings   << bindings;
00735         d->undoData->comments   << comments;
00736         d->undoData->conditions << conditions;
00737         d->undoData->databases  << databases;
00738         d->undoData->formulas   << formulas;
00739         d->undoData->fusions    << fusions;
00740         d->undoData->links      << links;
00741         d->undoData->matrices   << matrices;
00742         d->undoData->namedAreas << namedAreas;
00743         d->undoData->styles     << styles;
00744         d->undoData->userInputs << userInputs;
00745         d->undoData->validities << validities;
00746         d->undoData->values     << values;
00747     }
00748 
00749     // Trigger a dependency update of the cells, which have a formula. (new positions)
00750     subStorage = d->formulaStorage->subStorage(invalidRegion);
00751     for (int i = 0; i < subStorage.count(); ++i)
00752     {
00753         cell = Cell(d->sheet, subStorage.col(i), subStorage.row(i));
00754         d->sheet->map()->addDamage(new CellDamage(cell, CellDamage::Formula));
00755     }
00756     // Trigger a recalculation only for the cells, that depend on values in the changed region.
00757     Region providers = d->sheet->map()->dependencyManager()->reduceToProvidingRegion(invalidRegion);
00758     d->sheet->map()->addDamage(new CellDamage(d->sheet, providers, CellDamage::Value));
00759 }
00760 
00761 void CellStorage::removeRows( int position, int number )
00762 {
00763     // Trigger a dependency update of the cells, which have a formula. (old positions)
00764     const Region invalidRegion(QRect(QPoint(1, position), QPoint(KS_colMax, KS_rowMax)), d->sheet);
00765     PointStorage<Formula> subStorage = d->formulaStorage->subStorage(invalidRegion);
00766     Cell cell;
00767     for (int i = 0; i < subStorage.count(); ++i)
00768     {
00769         cell = Cell(d->sheet, subStorage.col(i), subStorage.row(i));
00770         d->sheet->map()->addDamage(new CellDamage(cell, CellDamage::Formula));
00771     }
00772     // Trigger an update of the bindings and the named areas.
00773     const Region region(QRect(QPoint(1, position - 1), QPoint(KS_colMax, KS_rowMax)), d->sheet);
00774     d->sheet->map()->addDamage(new CellDamage(d->sheet, region, CellDamage::Binding | CellDamage::NamedArea));
00775 
00776     QList< QPair<QRectF,Binding> > bindings = d->bindingStorage->removeRows( position, number );
00777     QList< QPair<QRectF,QString> > comments = d->commentStorage->removeRows( position, number );
00778     QList< QPair<QRectF,Conditions> > conditions = d->conditionsStorage->removeRows( position, number );
00779     QList< QPair<QRectF,Database> > databases = d->databaseStorage->removeRows( position, number );
00780     QVector< QPair<QPoint,Formula> > formulas = d->formulaStorage->removeRows( position, number );
00781     QList< QPair<QRectF,bool> > fusions = d->fusionStorage->removeRows( position, number );
00782     QVector< QPair<QPoint,QString> > links = d->linkStorage->removeRows( position, number );
00783     QList< QPair<QRectF,bool> > matrices = d->matrixStorage->removeRows( position, number );
00784     QList< QPair<QRectF,QString> > namedAreas = d->namedAreaStorage->removeRows( position, number );
00785     QList< QPair<QRectF,SharedSubStyle> > styles = d->styleStorage->removeRows( position, number );
00786     QVector< QPair<QPoint,QString> > userInputs = d->userInputStorage->removeRows( position, number );
00787     QList< QPair<QRectF,Validity> > validities = d->validityStorage->removeRows( position, number );
00788     QVector< QPair<QPoint,Value> > values = d->valueStorage->removeRows( position, number );
00789     // recording undo?
00790     if ( d->undoData )
00791     {
00792         d->undoData->bindings   << bindings;
00793         d->undoData->comments   << comments;
00794         d->undoData->conditions << conditions;
00795         d->undoData->databases  << databases;
00796         d->undoData->formulas   << formulas;
00797         d->undoData->fusions    << fusions;
00798         d->undoData->links      << links;
00799         d->undoData->matrices   << matrices;
00800         d->undoData->namedAreas << namedAreas;
00801         d->undoData->styles     << styles;
00802         d->undoData->userInputs << userInputs;
00803         d->undoData->validities << validities;
00804         d->undoData->values     << values;
00805     }
00806 
00807     // Trigger a dependency update of the cells, which have a formula. (new positions)
00808     subStorage = d->formulaStorage->subStorage(invalidRegion);
00809     for (int i = 0; i < subStorage.count(); ++i)
00810     {
00811         cell = Cell(d->sheet, subStorage.col(i), subStorage.row(i));
00812         d->sheet->map()->addDamage(new CellDamage(cell, CellDamage::Formula));
00813     }
00814     // Trigger a recalculation only for the cells, that depend on values in the changed region.
00815     Region providers = d->sheet->map()->dependencyManager()->reduceToProvidingRegion(invalidRegion);
00816     d->sheet->map()->addDamage(new CellDamage(d->sheet, providers, CellDamage::Value));
00817 }
00818 
00819 void CellStorage::removeShiftLeft( const QRect& rect )
00820 {
00821     // Trigger a dependency update of the cells, which have a formula. (old positions)
00822     const Region invalidRegion(QRect(rect.topLeft(), QPoint(KS_colMax, rect.bottom())), d->sheet);
00823     PointStorage<Formula> subStorage = d->formulaStorage->subStorage(invalidRegion);
00824     Cell cell;
00825     for (int i = 0; i < subStorage.count(); ++i)
00826     {
00827         cell = Cell(d->sheet, subStorage.col(i), subStorage.row(i));
00828         d->sheet->map()->addDamage(new CellDamage(cell, CellDamage::Formula));
00829     }
00830     // Trigger an update of the bindings and the named areas.
00831     const Region region(QRect(rect.topLeft() - QPoint(1, 0), QPoint(KS_colMax, rect.bottom())), d->sheet);
00832     d->sheet->map()->addDamage(new CellDamage(d->sheet, region, CellDamage::Binding | CellDamage::NamedArea));
00833 
00834     QList< QPair<QRectF,Binding> > bindings = d->bindingStorage->removeShiftLeft( rect );
00835     QList< QPair<QRectF,QString> > comments = d->commentStorage->removeShiftLeft( rect );
00836     QList< QPair<QRectF,Conditions> > conditions = d->conditionsStorage->removeShiftLeft( rect );
00837     QList< QPair<QRectF,Database> > databases = d->databaseStorage->removeShiftLeft( rect );
00838     QVector< QPair<QPoint,Formula> > formulas = d->formulaStorage->removeShiftLeft( rect );
00839     QList< QPair<QRectF,bool> > fusions = d->fusionStorage->removeShiftLeft( rect );
00840     QVector< QPair<QPoint,QString> > links = d->linkStorage->removeShiftLeft( rect );
00841     QList< QPair<QRectF,bool> > matrices = d->matrixStorage->removeShiftLeft( rect );
00842     QList< QPair<QRectF,QString> > namedAreas = d->namedAreaStorage->removeShiftLeft( rect );
00843     QList< QPair<QRectF,SharedSubStyle> > styles = d->styleStorage->removeShiftLeft( rect );
00844     QVector< QPair<QPoint,QString> > userInputs = d->userInputStorage->removeShiftLeft( rect );
00845     QList< QPair<QRectF,Validity> > validities = d->validityStorage->removeShiftLeft( rect );
00846     QVector< QPair<QPoint,Value> > values = d->valueStorage->removeShiftLeft( rect );
00847     // recording undo?
00848     if ( d->undoData )
00849     {
00850         d->undoData->bindings   << bindings;
00851         d->undoData->comments   << comments;
00852         d->undoData->conditions << conditions;
00853         d->undoData->databases  << databases;
00854         d->undoData->formulas   << formulas;
00855         d->undoData->fusions    << fusions;
00856         d->undoData->links      << links;
00857         d->undoData->matrices   << matrices;
00858         d->undoData->namedAreas << namedAreas;
00859         d->undoData->styles     << styles;
00860         d->undoData->userInputs << userInputs;
00861         d->undoData->validities << validities;
00862         d->undoData->values     << values;
00863     }
00864 
00865     // Trigger a dependency update of the cells, which have a formula. (new positions)
00866     subStorage = d->formulaStorage->subStorage(invalidRegion);
00867     for (int i = 0; i < subStorage.count(); ++i)
00868     {
00869         cell = Cell(d->sheet, subStorage.col(i), subStorage.row(i));
00870         d->sheet->map()->addDamage(new CellDamage(cell, CellDamage::Formula));
00871     }
00872     // Trigger a recalculation only for the cells, that depend on values in the changed region.
00873     Region providers = d->sheet->map()->dependencyManager()->reduceToProvidingRegion(invalidRegion);
00874     d->sheet->map()->addDamage(new CellDamage(d->sheet, providers, CellDamage::Value));
00875 }
00876 
00877 void CellStorage::insertShiftRight( const QRect& rect )
00878 {
00879     // Trigger a dependency update of the cells, which have a formula. (old positions)
00880     const Region invalidRegion(QRect(rect.topLeft(), QPoint(KS_colMax, rect.bottom())), d->sheet);
00881     PointStorage<Formula> subStorage = d->formulaStorage->subStorage(invalidRegion);
00882     Cell cell;
00883     for (int i = 0; i < subStorage.count(); ++i)
00884     {
00885         cell = Cell(d->sheet, subStorage.col(i), subStorage.row(i));
00886         d->sheet->map()->addDamage(new CellDamage(cell, CellDamage::Formula));
00887     }
00888     // Trigger an update of the bindings and the named areas.
00889     d->sheet->map()->addDamage(new CellDamage(d->sheet, invalidRegion, CellDamage::Binding | CellDamage::NamedArea));
00890 
00891     QList< QPair<QRectF,Binding> > bindings = d->bindingStorage->insertShiftRight( rect );
00892     QList< QPair<QRectF,QString> > comments = d->commentStorage->insertShiftRight( rect );
00893     QList< QPair<QRectF,Conditions> > conditions = d->conditionsStorage->insertShiftRight( rect );
00894     QList< QPair<QRectF,Database> > databases = d->databaseStorage->insertShiftRight( rect );
00895     QVector< QPair<QPoint,Formula> > formulas = d->formulaStorage->insertShiftRight( rect );
00896     QList< QPair<QRectF,bool> > fusions = d->fusionStorage->insertShiftRight( rect );
00897     QVector< QPair<QPoint,QString> > links = d->linkStorage->insertShiftRight( rect );
00898     QList< QPair<QRectF,bool> > matrices = d->matrixStorage->insertShiftRight( rect );
00899     QList< QPair<QRectF,QString> > namedAreas = d->namedAreaStorage->insertShiftRight( rect );
00900     QList< QPair<QRectF,SharedSubStyle> > styles = d->styleStorage->insertShiftRight( rect );
00901     QVector< QPair<QPoint,QString> > userInputs = d->userInputStorage->insertShiftRight( rect );
00902     QList< QPair<QRectF,Validity> > validities = d->validityStorage->insertShiftRight( rect );
00903     QVector< QPair<QPoint,Value> > values = d->valueStorage->insertShiftRight( rect );
00904     // recording undo?
00905     if ( d->undoData )
00906     {
00907         d->undoData->bindings   << bindings;
00908         d->undoData->comments   << comments;
00909         d->undoData->conditions << conditions;
00910         d->undoData->databases  << databases;
00911         d->undoData->formulas   << formulas;
00912         d->undoData->fusions    << fusions;
00913         d->undoData->links      << links;
00914         d->undoData->matrices   << matrices;
00915         d->undoData->namedAreas << namedAreas;
00916         d->undoData->styles     << styles;
00917         d->undoData->userInputs << userInputs;
00918         d->undoData->validities << validities;
00919         d->undoData->values     << values;
00920     }
00921 
00922     // Trigger a dependency update of the cells, which have a formula. (new positions)
00923     subStorage = d->formulaStorage->subStorage(invalidRegion);
00924     for (int i = 0; i < subStorage.count(); ++i)
00925     {
00926         cell = Cell(d->sheet, subStorage.col(i), subStorage.row(i));
00927         d->sheet->map()->addDamage(new CellDamage(cell, CellDamage::Formula));
00928     }
00929     // Trigger a recalculation only for the cells, that depend on values in the changed region.
00930     Region providers = d->sheet->map()->dependencyManager()->reduceToProvidingRegion(invalidRegion);
00931     d->sheet->map()->addDamage(new CellDamage(d->sheet, providers, CellDamage::Value));
00932 }
00933 
00934 void CellStorage::removeShiftUp( const QRect& rect )
00935 {
00936     // Trigger a dependency update of the cells, which have a formula. (old positions)
00937     const Region invalidRegion(QRect(rect.topLeft(), QPoint(rect.right(), KS_rowMax)), d->sheet);
00938     PointStorage<Formula> subStorage = d->formulaStorage->subStorage(invalidRegion);
00939     Cell cell;
00940     for (int i = 0; i < subStorage.count(); ++i)
00941     {
00942         cell = Cell(d->sheet, subStorage.col(i), subStorage.row(i));
00943         d->sheet->map()->addDamage(new CellDamage(cell, CellDamage::Formula));
00944     }
00945     // Trigger an update of the bindings and the named areas.
00946     const Region region(QRect(rect.topLeft() - QPoint(0, 1), QPoint(rect.right(), KS_rowMax)), d->sheet);
00947     d->sheet->map()->addDamage(new CellDamage(d->sheet, region, CellDamage::Binding | CellDamage::NamedArea));
00948 
00949     QList< QPair<QRectF,Binding> > bindings = d->bindingStorage->removeShiftUp( rect );
00950     QList< QPair<QRectF,QString> > comments = d->commentStorage->removeShiftUp( rect );
00951     QList< QPair<QRectF,Conditions> > conditions = d->conditionsStorage->removeShiftUp( rect );
00952     QList< QPair<QRectF,Database> > databases = d->databaseStorage->removeShiftUp( rect );
00953     QVector< QPair<QPoint,Formula> > formulas = d->formulaStorage->removeShiftUp( rect );
00954     QList< QPair<QRectF,bool> > fusions = d->fusionStorage->removeShiftUp( rect );
00955     QVector< QPair<QPoint,QString> > links = d->linkStorage->removeShiftUp( rect );
00956     QList< QPair<QRectF,bool> > matrices = d->matrixStorage->removeShiftUp( rect );
00957     QList< QPair<QRectF,QString> > namedAreas = d->namedAreaStorage->removeShiftUp( rect );
00958     QList< QPair<QRectF,SharedSubStyle> > styles = d->styleStorage->removeShiftUp( rect );
00959     QVector< QPair<QPoint,QString> > userInputs = d->userInputStorage->removeShiftUp( rect );
00960     QList< QPair<QRectF,Validity> > validities = d->validityStorage->removeShiftUp( rect );
00961     QVector< QPair<QPoint,Value> > values = d->valueStorage->removeShiftUp( rect );
00962     // recording undo?
00963     if ( d->undoData )
00964     {
00965         d->undoData->bindings   << bindings;
00966         d->undoData->comments   << comments;
00967         d->undoData->conditions << conditions;
00968         d->undoData->databases  << databases;
00969         d->undoData->formulas   << formulas;
00970         d->undoData->fusions    << fusions;
00971         d->undoData->links      << links;
00972         d->undoData->matrices   << matrices;
00973         d->undoData->namedAreas << namedAreas;
00974         d->undoData->styles     << styles;
00975         d->undoData->userInputs << userInputs;
00976         d->undoData->validities << validities;
00977         d->undoData->values     << values;
00978     }
00979 
00980     // Trigger a dependency update of the cells, which have a formula. (new positions)
00981     subStorage = d->formulaStorage->subStorage(invalidRegion);
00982     for (int i = 0; i < subStorage.count(); ++i)
00983     {
00984         cell = Cell(d->sheet, subStorage.col(i), subStorage.row(i));
00985         d->sheet->map()->addDamage(new CellDamage(cell, CellDamage::Formula));
00986     }
00987     // Trigger a recalculation only for the cells, that depend on values in the changed region.
00988     Region providers = d->sheet->map()->dependencyManager()->reduceToProvidingRegion(invalidRegion);
00989     d->sheet->map()->addDamage(new CellDamage(d->sheet, providers, CellDamage::Value));
00990 }
00991 
00992 void CellStorage::insertShiftDown( const QRect& rect )
00993 {
00994     // Trigger a dependency update of the cells, which have a formula. (old positions)
00995     const Region invalidRegion(QRect(rect.topLeft(), QPoint(rect.right(), KS_rowMax)), d->sheet);
00996     PointStorage<Formula> subStorage = d->formulaStorage->subStorage(invalidRegion);
00997     Cell cell;
00998     for (int i = 0; i < subStorage.count(); ++i)
00999     {
01000         cell = Cell(d->sheet, subStorage.col(i), subStorage.row(i));
01001         d->sheet->map()->addDamage(new CellDamage(cell, CellDamage::Formula));
01002     }
01003     // Trigger an update of the bindings and the named areas.
01004     d->sheet->map()->addDamage(new CellDamage(d->sheet, invalidRegion, CellDamage::Binding | CellDamage::NamedArea));
01005 
01006     QList< QPair<QRectF,Binding> > bindings = d->bindingStorage->insertShiftDown( rect );
01007     QList< QPair<QRectF,QString> > comments = d->commentStorage->insertShiftDown( rect );
01008     QList< QPair<QRectF,Conditions> > conditions = d->conditionsStorage->insertShiftDown( rect );
01009     QList< QPair<QRectF,Database> > databases = d->databaseStorage->insertShiftDown( rect );
01010     QVector< QPair<QPoint,Formula> > formulas = d->formulaStorage->insertShiftDown( rect );
01011     QList< QPair<QRectF,bool> > fusions = d->fusionStorage->insertShiftDown( rect );
01012     QVector< QPair<QPoint,QString> > links = d->linkStorage->insertShiftDown( rect );
01013     QList< QPair<QRectF,bool> > matrices = d->matrixStorage->insertShiftDown( rect );
01014     QList< QPair<QRectF,QString> > namedAreas = d->namedAreaStorage->insertShiftDown( rect );
01015     QList< QPair<QRectF,SharedSubStyle> > styles = d->styleStorage->insertShiftDown( rect );
01016     QVector< QPair<QPoint,QString> > userInputs = d->userInputStorage->insertShiftDown( rect );
01017     QList< QPair<QRectF,Validity> > validities = d->validityStorage->insertShiftDown( rect );
01018     QVector< QPair<QPoint,Value> > values = d->valueStorage->insertShiftDown( rect );
01019     // recording undo?
01020     if ( d->undoData )
01021     {
01022         d->undoData->bindings   << bindings;
01023         d->undoData->comments   << comments;
01024         d->undoData->conditions << conditions;
01025         d->undoData->databases  << databases;
01026         d->undoData->formulas   << formulas;
01027         d->undoData->fusions    << fusions;
01028         d->undoData->links      << links;
01029         d->undoData->matrices   << matrices;
01030         d->undoData->namedAreas << namedAreas;
01031         d->undoData->styles     << styles;
01032         d->undoData->userInputs << userInputs;
01033         d->undoData->validities << validities;
01034         d->undoData->values     << values;
01035     }
01036 
01037     // Trigger a dependency update of the cells, which have a formula. (new positions)
01038     subStorage = d->formulaStorage->subStorage(invalidRegion);
01039     for (int i = 0; i < subStorage.count(); ++i)
01040     {
01041         cell = Cell(d->sheet, subStorage.col(i), subStorage.row(i));
01042         d->sheet->map()->addDamage(new CellDamage(cell, CellDamage::Formula));
01043     }
01044     // Trigger a recalculation only for the cells, that depend on values in the changed region.
01045     Region providers = d->sheet->map()->dependencyManager()->reduceToProvidingRegion(invalidRegion);
01046     d->sheet->map()->addDamage(new CellDamage(d->sheet, providers, CellDamage::Value));
01047 }
01048 
01049 Cell CellStorage::firstInColumn(int col, Visiting visiting) const
01050 {
01051     Q_UNUSED(visiting);
01052     
01053     int newRow = 0;
01054     int tmpRow = 0;
01055     d->formulaStorage->firstInColumn( col, &tmpRow );
01056     newRow = tmpRow;
01057     d->valueStorage->firstInColumn( col, &tmpRow );
01058     if ( tmpRow )
01059         newRow = newRow ? qMin( newRow, tmpRow ) : tmpRow;
01060     if ( !newRow )
01061         return Cell();
01062     return Cell( d->sheet, col, newRow );
01063 }
01064 
01065 Cell CellStorage::firstInRow(int row, Visiting visiting) const
01066 {
01067     int newCol = 0;
01068     int tmpCol = 0;
01069     d->formulaStorage->firstInRow( row, &tmpCol );
01070     newCol = tmpCol;
01071     d->valueStorage->firstInRow( row, &tmpCol );
01072     if ( tmpCol )
01073         newCol = newCol ? qMin( newCol, tmpCol ) : tmpCol;
01074     if (visiting == VisitAll)
01075     {
01076         tmpCol = d->styleStorage->firstColumnIndexInRow(row);
01077         if (tmpCol)
01078             newCol = newCol ? qMin(newCol, tmpCol) : tmpCol;
01079     }
01080     if ( !newCol )
01081         return Cell();
01082     return Cell( d->sheet, newCol, row );
01083 }
01084 
01085 Cell CellStorage::lastInColumn(int col, Visiting visiting) const
01086 {
01087     int newRow = 0;
01088     int tmpRow = 0;
01089     d->formulaStorage->lastInColumn( col, &tmpRow );
01090     newRow = tmpRow;
01091     d->valueStorage->lastInColumn( col, &tmpRow );
01092     newRow = qMax( newRow, tmpRow );
01093     if ( !newRow )
01094         return Cell();
01095     return Cell( d->sheet, col, newRow );
01096 }
01097 
01098 Cell CellStorage::lastInRow(int row, Visiting visiting) const
01099 {
01100     int newCol = 0;
01101     int tmpCol = 0;
01102     d->formulaStorage->lastInRow( row, &tmpCol );
01103     newCol = tmpCol;
01104     d->valueStorage->lastInRow( row, &tmpCol );
01105     newCol = qMax( newCol, tmpCol );
01106     if ( !newCol )
01107         return Cell();
01108     return Cell( d->sheet, newCol, row );
01109 }
01110 
01111 Cell CellStorage::nextInColumn(int col, int row, Visiting visiting) const
01112 {
01113     int newRow = 0;
01114     int tmpRow = 0;
01115     d->formulaStorage->nextInColumn( col, row, &tmpRow );
01116     newRow = tmpRow;
01117     d->valueStorage->nextInColumn( col, row, &tmpRow );
01118     if ( tmpRow )
01119         newRow = newRow ? qMin( newRow, tmpRow ) : tmpRow;
01120     if ( !newRow )
01121         return Cell();
01122     return Cell( d->sheet, col, newRow );
01123 }
01124 
01125 Cell CellStorage::nextInRow(int col, int row, Visiting visiting) const
01126 {
01127     int newCol = 0;
01128     int tmpCol = 0;
01129     d->formulaStorage->nextInRow( col, row, &tmpCol );
01130     newCol = tmpCol;
01131     d->valueStorage->nextInRow( col, row, &tmpCol );
01132     if ( tmpCol )
01133         newCol = newCol ? qMin( newCol, tmpCol ) : tmpCol;
01134     if (visiting == VisitAll)
01135     {
01136         tmpCol = d->styleStorage->nextColumnIndexInRow(col, row);
01137         if (tmpCol)
01138             newCol = newCol ? qMin(newCol, tmpCol) : tmpCol;
01139     }
01140     if ( !newCol )
01141         return Cell();
01142     return Cell( d->sheet, newCol, row );
01143 }
01144 
01145 Cell CellStorage::prevInColumn(int col, int row, Visiting visiting) const
01146 {
01147     int newRow = 0;
01148     int tmpRow = 0;
01149     d->formulaStorage->prevInColumn( col, row, &tmpRow );
01150     newRow = tmpRow;
01151     d->valueStorage->prevInColumn( col, row, &tmpRow );
01152     newRow = qMax( newRow, tmpRow );
01153     if ( !newRow )
01154         return Cell();
01155     return Cell( d->sheet, col, newRow );
01156 }
01157 
01158 Cell CellStorage::prevInRow(int col, int row, Visiting visiting) const
01159 {
01160     int newCol = 0;
01161     int tmpCol = 0;
01162     d->formulaStorage->prevInRow( col, row, &tmpCol );
01163     newCol = tmpCol;
01164     d->valueStorage->prevInRow( col, row, &tmpCol );
01165     newCol = qMax( newCol, tmpCol );
01166     if ( !newCol )
01167         return Cell();
01168     return Cell( d->sheet, newCol, row );
01169 }
01170 
01171 int CellStorage::columns() const
01172 {
01173     int max = 0;
01174     max = qMax( max, d->bindingStorage->usedArea().right() );
01175     max = qMax( max, d->commentStorage->usedArea().right() );
01176     max = qMax( max, d->conditionsStorage->usedArea().right() );
01177     max = qMax( max, d->fusionStorage->usedArea().right() );
01178     max = qMax( max, d->styleStorage->usedArea().right() );
01179     max = qMax( max, d->validityStorage->usedArea().right() );
01180     max = qMax( max, d->formulaStorage->columns() );
01181     max = qMax( max, d->linkStorage->columns() );
01182     max = qMax( max, d->valueStorage->columns() );
01183     return max;
01184 }
01185 
01186 int CellStorage::rows() const
01187 {
01188     int max = 0;
01189     max = qMax( max, d->bindingStorage->usedArea().bottom() );
01190     max = qMax( max, d->commentStorage->usedArea().bottom() );
01191     max = qMax( max, d->conditionsStorage->usedArea().bottom() );
01192     max = qMax( max, d->fusionStorage->usedArea().bottom() );
01193     max = qMax( max, d->styleStorage->usedArea().bottom() );
01194     max = qMax( max, d->validityStorage->usedArea().bottom() );
01195     max = qMax( max, d->formulaStorage->rows() );
01196     max = qMax( max, d->linkStorage->rows() );
01197     max = qMax( max, d->valueStorage->rows() );
01198     return max;
01199 }
01200 
01201 CellStorage CellStorage::subStorage( const Region& region ) const
01202 {
01203     CellStorage subStorage( d->sheet );
01204     *subStorage.d->formulaStorage = d->formulaStorage->subStorage( region );
01205     *subStorage.d->linkStorage = d->linkStorage->subStorage( region );
01206     *subStorage.d->valueStorage = d->valueStorage->subStorage( region );
01207     return subStorage;
01208 }
01209 
01210 const BindingStorage* CellStorage::bindingStorage() const
01211 {
01212     return d->bindingStorage;
01213 }
01214 
01215 const CommentStorage* CellStorage::commentStorage() const
01216 {
01217     return d->commentStorage;
01218 }
01219 
01220 const ConditionsStorage* CellStorage::conditionsStorage() const
01221 {
01222     return d->conditionsStorage;
01223 }
01224 
01225 const FormulaStorage* CellStorage::formulaStorage() const
01226 {
01227     return d->formulaStorage;
01228 }
01229 
01230 const FusionStorage* CellStorage::fusionStorage() const
01231 {
01232     return d->fusionStorage;
01233 }
01234 
01235 const LinkStorage* CellStorage::linkStorage() const
01236 {
01237     return d->linkStorage;
01238 }
01239 
01240 StyleStorage* CellStorage::styleStorage() const
01241 {
01242     return d->styleStorage;
01243 }
01244 
01245 const ValidityStorage* CellStorage::validityStorage() const
01246 {
01247     return d->validityStorage;
01248 }
01249 
01250 const ValueStorage* CellStorage::valueStorage() const
01251 {
01252     return d->valueStorage;
01253 }
01254 
01255 void CellStorage::startUndoRecording()
01256 {
01257     // If undoData is not null, the recording wasn't stopped.
01258     // Should not happen, hence this assertion.
01259     Q_ASSERT( d->undoData == 0 );
01260     d->undoData = new CellStorageUndoData();
01261 }
01262 
01263 CellStorageUndoData* CellStorage::stopUndoRecording()
01264 {
01265     // If undoData is null, the recording wasn't started.
01266     // Should not happen, hence this assertion.
01267     Q_ASSERT( d->undoData != 0 );
01268     CellStorageUndoData* undoData = d->undoData;
01269     d->undoData = 0;
01270     for (int i = 0; i < undoData->namedAreas.count(); ++i)
01271         emit namedAreaRemoved(undoData->namedAreas[i].second);
01272     // do not store an object unnecessarily
01273     if ( undoData->isEmpty() )
01274     {
01275         delete undoData;
01276         undoData = 0;
01277     }
01278     return undoData;
01279 }
01280 
01281 void CellStorage::undo( CellStorageUndoData* data )
01282 {
01283     if ( !data ) // nothing to do?
01284         return;
01285     for ( int i = 0; i < data->formulas.count(); ++i )
01286         setFormula( data->formulas[i].first.x(), data->formulas[i].first.y(), data->formulas[i].second );
01287     for ( int i = 0; i < data->values.count(); ++i )
01288         setValue( data->values[i].first.x(), data->values[i].first.y(), data->values[i].second );
01289     for ( int i = 0; i < data->userInputs.count(); ++i )
01290         setUserInput( data->userInputs[i].first.x(), data->userInputs[i].first.y(), data->userInputs[i].second );
01291     for ( int i = 0; i < data->links.count(); ++i )
01292         setLink( data->links[i].first.x(), data->links[i].first.y(), data->links[i].second );
01293     for ( int i = 0; i < data->fusions.count(); ++i )
01294         d->fusionStorage->insert( Region(data->fusions[i].first.toRect()), data->fusions[i].second );
01295     for ( int i = 0; i < data->matrices.count(); ++i )
01296         d->matrixStorage->insert( Region(data->matrices[i].first.toRect()), data->matrices[i].second );
01297     for ( int i = 0; i < data->namedAreas.count(); ++i )
01298         emit insertNamedArea(Region(data->namedAreas[i].first.toRect(), d->sheet), data->namedAreas[i].second);
01299     for ( int i = 0; i < data->styles.count(); ++i )
01300         d->styleStorage->insert( data->styles[i].first.toRect(), data->styles[i].second );
01301     for ( int i = 0; i < data->bindings.count(); ++i )
01302         setBinding( Region(data->bindings[i].first.toRect()), data->bindings[i].second );
01303     for ( int i = 0; i < data->comments.count(); ++i )
01304         setComment( Region(data->comments[i].first.toRect()), data->comments[i].second );
01305     for ( int i = 0; i < data->conditions.count(); ++i )
01306         setConditions( Region(data->conditions[i].first.toRect()), data->conditions[i].second );
01307     for ( int i = 0; i < data->databases.count(); ++i )
01308         setDatabase( Region(data->databases[i].first.toRect()), data->databases[i].second );
01309     for ( int i = 0; i < data->validities.count(); ++i )
01310         setValidity( Region(data->validities[i].first.toRect()), data->validities[i].second );
01311 }
01312 
01313 #include "CellStorage.moc"