00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include <assert.h>
00023 #include <ctype.h>
00024 #include <float.h>
00025 #include <math.h>
00026 #include <pwd.h>
00027 #include <stdlib.h>
00028 #include <unistd.h>
00029
00030 #include <qapplication.h>
00031 #include <qcheckbox.h>
00032 #include <qclipboard.h>
00033 #include <qlabel.h>
00034 #include <qlayout.h>
00035 #include <qlineedit.h>
00036 #include <qpicture.h>
00037 #include <qregexp.h>
00038 #include <qvbox.h>
00039 #include <qmap.h>
00040
00041 #include <kdebug.h>
00042 #include <kmdcodec.h>
00043 #include <kfind.h>
00044 #include <kfinddialog.h>
00045 #include <kmessagebox.h>
00046 #include <kreplace.h>
00047 #include <kreplacedialog.h>
00048 #include <kprinter.h>
00049 #include <kurl.h>
00050
00051 #include <koChart.h>
00052 #include <KoDom.h>
00053 #include <KoDocumentInfo.h>
00054 #include <KoOasisLoadingContext.h>
00055 #include <KoOasisSettings.h>
00056 #include <KoOasisStyles.h>
00057 #include <KoQueryTrader.h>
00058 #include <KoStyleStack.h>
00059 #include <KoUnit.h>
00060 #include <KoXmlNS.h>
00061 #include <KoXmlWriter.h>
00062
00063 #include "commands.h"
00064 #include "dependencies.h"
00065 #include "selection.h"
00066 #include "ksploadinginfo.h"
00067 #include "ksprsavinginfo.h"
00068 #include "kspread_canvas.h"
00069 #include "kspread_cluster.h"
00070 #include "kspread_condition.h"
00071 #include "kspread_doc.h"
00072 #include "kspread_global.h"
00073 #include "kspread_locale.h"
00074 #include "kspread_map.h"
00075 #include "kspread_object.h"
00076 #include "kspread_sheetprint.h"
00077 #include "kspread_style.h"
00078 #include "kspread_style_manager.h"
00079 #include "kspread_undo.h"
00080 #include "kspread_util.h"
00081 #include "kspread_view.h"
00082 #include "manipulator.h"
00083 #include "manipulator_data.h"
00084 #include "KSpreadTableIface.h"
00085
00086 #include "kspread_sheet.h"
00087 #include "kspread_sheet.moc"
00088
00089 #define NO_MODIFICATION_POSSIBLE \
00090 do { \
00091 KMessageBox::error( 0, i18n ( "You cannot change a protected sheet" ) ); return; \
00092 } while(0)
00093
00094 namespace KSpread {
00095
00096
00097
00098
00099
00100
00101
00102 CellBinding::CellBinding( Sheet *_sheet, const QRect& _area )
00103 {
00104 m_rctDataArea = _area;
00105
00106 m_pSheet = _sheet;
00107 m_pSheet->addCellBinding( this );
00108
00109 m_bIgnoreChanges = false;
00110 }
00111
00112 CellBinding::~CellBinding()
00113 {
00114 m_pSheet->removeCellBinding( this );
00115 }
00116
00117 void CellBinding::cellChanged( Cell *_cell )
00118 {
00119 if ( m_bIgnoreChanges )
00120 return;
00121
00122 emit changed( _cell );
00123 }
00124
00125 bool CellBinding::contains( int _x, int _y )
00126 {
00127 return m_rctDataArea.contains( QPoint( _x, _y ) );
00128 }
00129
00130
00131
00132
00133
00134
00135
00136 ChartBinding::ChartBinding( Sheet *_sheet, const QRect& _area, EmbeddedChart *_child )
00137 : CellBinding( _sheet, _area )
00138 {
00139 m_child = _child;
00140 }
00141
00142 ChartBinding::~ChartBinding()
00143 {
00144 }
00145
00146 void ChartBinding::cellChanged( Cell* )
00147 {
00148 if ( m_bIgnoreChanges )
00149 return;
00150
00151
00152
00153
00154 const QRect chartGeometry = m_child->geometry().toQRect();
00155
00156 double tmp;
00157 int left = sheet()->leftColumn( chartGeometry.left() , tmp );
00158 int top = sheet()->topRow( chartGeometry.top() , tmp );
00159 int right = sheet()->rightColumn( chartGeometry.right() );
00160 int bottom = sheet()->bottomRow( chartGeometry.bottom() );
00161
00162 sheet()->setRegionPaintDirty( QRect(left,top,right-left,bottom-top) );
00163
00164
00165
00166
00167
00168
00169 KoChart::Part *chart = m_child->chart();
00170 chart->resizeData( m_rctDataArea.height(), m_rctDataArea.width() );
00171
00172
00173
00174
00175
00176 Cell* cell;
00177 for ( int row = 0; row < m_rctDataArea.height(); row++ ) {
00178 for ( int col = 0; col < m_rctDataArea.width(); col++ ) {
00179 cell = m_pSheet->cellAt( m_rctDataArea.left() + col,
00180 m_rctDataArea.top() + row );
00181 if ( cell && cell->value().isNumber() )
00182 chart->setCellData( row, col, cell->value().asFloat() );
00183 else if ( cell )
00184 chart->setCellData( row, col, cell->value().asString() );
00185 else
00186 chart->setCellData( row, col, KoChart::Value() );
00187 }
00188 }
00189 chart->analyzeHeaders( );
00190
00191
00192 #if 0
00193 Chart::Range range;
00194 range.top = m_rctDataArea.top();
00195 range.left = m_rctDataArea.left();
00196 range.right = m_rctDataArea.right();
00197 range.bottom = m_rctDataArea.bottom();
00198 range.sheet = m_pSheet->name(); */
00199
00200
00201
00202
00203
00205 #endif
00206
00207 }
00208
00209
00210
00211
00212
00213
00214
00215 TextDrag::TextDrag( QWidget * dragSource, const char * name )
00216 : QTextDrag( dragSource, name )
00217 {
00218 }
00219
00220 TextDrag::~TextDrag()
00221 {
00222 }
00223
00224
00225 QByteArray TextDrag::encodedData( const char * mime ) const
00226 {
00227 if ( strcmp( selectionMimeType(), mime ) == 0)
00228 return m_kspread;
00229 else
00230 return QTextDrag::encodedData( mime );
00231 }
00232
00233 bool TextDrag::canDecode( QMimeSource* e )
00234 {
00235 if ( e->provides( selectionMimeType() ) )
00236 return true;
00237 return QTextDrag::canDecode(e);
00238 }
00239
00240 const char * TextDrag::format( int i ) const
00241 {
00242 if ( i < 4 )
00243 return QTextDrag::format(i);
00244 else if ( i == 4 )
00245 return selectionMimeType();
00246 else return 0;
00247 }
00248
00249 const char * TextDrag::selectionMimeType()
00250 {
00251 return "application/x-kspread-snippet";
00252 }
00253
00254
00255
00256
00257
00258
00259
00260 class Sheet::Private
00261 {
00262 public:
00263
00264 Map* workbook;
00265
00266 DCOPObject* dcop;
00267
00268 QString name;
00269 int id;
00270
00271 Sheet::LayoutDirection layoutDirection;
00272
00273
00274 bool hide;
00275
00276
00277 QCString password;
00278
00279
00280 bool showGrid;
00281 bool showFormula;
00282 bool showFormulaIndicator;
00283 bool showCommentIndicator;
00284 bool autoCalc;
00285 bool lcMode;
00286 bool showColumnNumber;
00287 bool hideZero;
00288 bool firstLetterUpper;
00289
00290
00291 Cluster cells;
00292 RowCluster rows;
00293 ColumnCluster columns;
00294
00295
00296 Cell* defaultCell;
00297 Format* defaultFormat;
00298 RowFormat* defaultRowFormat;
00299 ColumnFormat* defaultColumnFormat;
00300
00301
00302 SheetPrint* print;
00303
00304
00305 Region paintDirtyList;
00306
00307
00308 QPainter *painter;
00309 QWidget *widget;
00310
00311
00312
00313 QPtrList<CellBinding> cellBindings;
00314
00315
00316
00317 bool showPageBorders;
00318
00319
00320
00321
00322
00323 int maxRow;
00324 int maxColumn;
00325
00326
00327
00328 double sizeMaxX;
00329 double sizeMaxY;
00330
00331
00332 bool scrollBarUpdates;
00333
00334 QPen emptyPen;
00335 QBrush emptyBrush;
00336 QColor emptyColor;
00337
00338 int scrollPosX;
00339 int scrollPosY;
00340
00341 KSpread::DependencyManager *dependencies;
00342 };
00343
00344 int Sheet::s_id = 0L;
00345 QIntDict<Sheet>* Sheet::s_mapSheets;
00346
00347 Sheet* Sheet::find( int _id )
00348 {
00349 if ( !s_mapSheets )
00350 return 0L;
00351
00352 return (*s_mapSheets)[ _id ];
00353 }
00354
00355 Sheet::Sheet (Map* map,
00356 const QString &sheetName, const char *_name )
00357 : QObject( map, _name )
00358 {
00359 if ( s_mapSheets == 0L )
00360 s_mapSheets = new QIntDict<Sheet>;
00361 d = new Private;
00362
00363 d->workbook = map;
00364
00365 d->id = s_id++;
00366 s_mapSheets->insert( d->id, this );
00367
00368 d->layoutDirection = LeftToRight;
00369
00370 d->defaultFormat = new Format (this, d->workbook->doc()->styleManager()->defaultStyle());
00371 d->emptyPen.setStyle( Qt::NoPen );
00372 d->dcop = 0;
00373 d->name = sheetName;
00374
00375 dcopObject();
00376 d->cellBindings.setAutoDelete( false );
00377
00378
00379
00380 d->cells.setAutoDelete( true );
00381 d->rows.setAutoDelete( true );
00382 d->columns.setAutoDelete( true );
00383
00384 d->defaultCell = new Cell( this, d->workbook->doc()->styleManager()->defaultStyle(), 0, 0);
00385 d->defaultRowFormat = new RowFormat( this, 0 );
00386 d->defaultRowFormat->setDefault();
00387 d->defaultColumnFormat = new ColumnFormat( this, 0 );
00388 d->defaultColumnFormat->setDefault();
00389
00390 d->widget = new QWidget();
00391 d->painter = new QPainter;
00392 d->painter->begin( d->widget );
00393
00394 d->maxColumn = 256;
00395 d->maxRow = 256;
00396 d->sizeMaxX = KS_colMax * d->defaultColumnFormat->dblWidth();
00397 d->sizeMaxY = KS_rowMax * d->defaultRowFormat->dblHeight();
00398
00399 d->scrollBarUpdates = true;
00400
00401 setHidden( false );
00402 d->showGrid=true;
00403 d->showFormula=false;
00404 d->showFormulaIndicator=true;
00405 d->showCommentIndicator=true;
00406 d->showPageBorders = false;
00407
00408 d->lcMode=false;
00409 d->showColumnNumber=false;
00410 d->hideZero=false;
00411 d->firstLetterUpper=false;
00412 d->autoCalc=true;
00413
00414 if ( !_name )
00415 {
00416 QCString s;
00417 s.sprintf("Sheet%i", s_id );
00418 QObject::setName( s.data() );
00419 }
00420 d->print = new SheetPrint( this );
00421
00422
00423 d->dependencies = new KSpread::DependencyManager (this);
00424
00425
00426 QObject::connect( doc(), SIGNAL( sig_addAreaName( const QString & ) ),
00427 this, SLOT( slotAreaModified( const QString & ) ) );
00428
00429 QObject::connect( doc(), SIGNAL( sig_removeAreaName( const QString & ) ),
00430 this, SLOT( slotAreaModified( const QString & ) ) );
00431
00432
00433 }
00434
00435 QString Sheet::sheetName() const
00436 {
00437 return d->name;
00438 }
00439
00440 Map* Sheet::workbook() const
00441 {
00442 return d->workbook;
00443 }
00444
00445 Doc* Sheet::doc() const
00446 {
00447 return d->workbook->doc();
00448 }
00449
00450 int Sheet::id() const
00451 {
00452 return d->id;
00453 }
00454
00455 Sheet::LayoutDirection Sheet::layoutDirection() const
00456 {
00457 return d->layoutDirection;
00458 }
00459
00460 void Sheet::setLayoutDirection( LayoutDirection dir )
00461 {
00462 d->layoutDirection = dir;
00463 }
00464
00465 bool Sheet::isRightToLeft() const
00466 {
00467 return d->layoutDirection == RightToLeft;
00468 }
00469
00470 bool Sheet::isHidden() const
00471 {
00472 return d->hide;
00473 }
00474
00475 void Sheet::setHidden( bool hidden )
00476 {
00477 d->hide = hidden;
00478 }
00479
00480 bool Sheet::getShowGrid() const
00481 {
00482 return d->showGrid;
00483 }
00484
00485 void Sheet::setShowGrid( bool _showGrid )
00486 {
00487 d->showGrid=_showGrid;
00488 }
00489
00490 bool Sheet::getShowFormula() const
00491 {
00492 return d->showFormula;
00493 }
00494
00495 void Sheet::setShowFormula( bool _showFormula )
00496 {
00497 d->showFormula=_showFormula;
00498 }
00499
00500 bool Sheet::getShowFormulaIndicator() const
00501 {
00502 return d->showFormulaIndicator;
00503 }
00504
00505 void Sheet::setShowFormulaIndicator( bool _showFormulaIndicator )
00506 {
00507 d->showFormulaIndicator=_showFormulaIndicator;
00508 }
00509
00510 bool Sheet::getShowCommentIndicator() const
00511 {
00512 return d->showCommentIndicator;
00513 }
00514
00515 void Sheet::setShowCommentIndicator(bool _indic)
00516 {
00517 d->showCommentIndicator=_indic;
00518 }
00519
00520 bool Sheet::getLcMode() const
00521 {
00522 return d->lcMode;
00523 }
00524
00525 void Sheet::setLcMode( bool _lcMode )
00526 {
00527 d->lcMode=_lcMode;
00528 }
00529
00530 bool Sheet::getAutoCalc() const
00531 {
00532 return d->autoCalc;
00533 }
00534
00535 void Sheet::setAutoCalc( bool _AutoCalc )
00536 {
00537
00538 if (d->autoCalc == _AutoCalc)
00539 return;
00540
00541
00542 if (_AutoCalc == true)
00543 {
00544 updateAllDependencies();
00545 recalc();
00546 }
00547
00548 d->autoCalc=_AutoCalc;
00549
00550
00551 }
00552
00553 bool Sheet::getShowColumnNumber() const
00554 {
00555 return d->showColumnNumber;
00556 }
00557
00558 void Sheet::setShowColumnNumber( bool _showColumnNumber )
00559 {
00560 d->showColumnNumber=_showColumnNumber;
00561 }
00562
00563 bool Sheet::getHideZero() const
00564 {
00565 return d->hideZero;
00566 }
00567
00568 void Sheet::setHideZero( bool _hideZero )
00569 {
00570 d->hideZero=_hideZero;
00571 }
00572
00573 bool Sheet::getFirstLetterUpper() const
00574 {
00575 return d->firstLetterUpper;
00576 }
00577
00578 void Sheet::setFirstLetterUpper( bool _firstUpper )
00579 {
00580 d->firstLetterUpper=_firstUpper;
00581 }
00582
00583 bool Sheet::isShowPageBorders() const
00584 {
00585 return d->showPageBorders;
00586 }
00587
00588 bool Sheet::isEmpty( unsigned long int x, unsigned long int y ) const
00589 {
00590 const Cell* c = cellAt( x, y );
00591 if ( !c || c->isEmpty() )
00592 return true;
00593
00594 return false;
00595 }
00596
00597 Cell* Sheet::defaultCell() const
00598 {
00599 return d->defaultCell;
00600 }
00601
00602 Format* Sheet::defaultFormat()
00603 {
00604 return d->defaultFormat;
00605 }
00606
00607 const Format* Sheet::defaultFormat() const
00608 {
00609 return d->defaultFormat;
00610 }
00611
00612 const ColumnFormat* Sheet::columnFormat( int _column ) const
00613 {
00614 const ColumnFormat *p = d->columns.lookup( _column );
00615 if ( p != 0L )
00616 return p;
00617
00618 return d->defaultColumnFormat;
00619 }
00620
00621 ColumnFormat* Sheet::columnFormat( int _column )
00622 {
00623 ColumnFormat *p = d->columns.lookup( _column );
00624 if ( p != 0L )
00625 return p;
00626
00627 return d->defaultColumnFormat;
00628 }
00629
00630 const RowFormat* Sheet::rowFormat( int _row ) const
00631 {
00632 const RowFormat *p = d->rows.lookup( _row );
00633 if ( p != 0L )
00634 return p;
00635
00636 return d->defaultRowFormat;
00637 }
00638
00639 RowFormat* Sheet::rowFormat( int _row )
00640 {
00641 RowFormat *p = d->rows.lookup( _row );
00642 if ( p != 0L )
00643 return p;
00644
00645 return d->defaultRowFormat;
00646 }
00647
00648 Value Sheet::value (int col, int row) const
00649 {
00650 Cell *cell = d->cells.lookup (col, row);
00651 if (cell)
00652 return cell->value ();
00653 Value empty;
00654 return empty;
00655 }
00656
00657 Value Sheet::valueRange (int col1, int row1,
00658 int col2, int row2) const
00659 {
00660 return d->cells.valueRange (col1, row1, col2, row2);
00661 }
00662
00663 void Sheet::password( QCString & passwd ) const
00664 {
00665 passwd = d->password;
00666 }
00667
00668 bool Sheet::isProtected() const
00669 {
00670 return !d->password.isNull();
00671 }
00672
00673 void Sheet::setProtected( QCString const & passwd )
00674 {
00675 d->password = passwd;
00676 }
00677
00678 bool Sheet::checkPassword( QCString const & passwd ) const
00679 {
00680 return ( passwd == d->password );
00681 }
00682
00683 SheetPrint* Sheet::print() const
00684 {
00685 return d->print;
00686 }
00687
00688 QPainter& Sheet::painter()
00689 {
00690 return *d->painter;
00691 }
00692
00693 QWidget* Sheet::widget()const
00694 {
00695 return d->widget;
00696 }
00697
00698 CellBinding* Sheet::firstCellBinding()
00699 {
00700 return d->cellBindings.first();
00701 }
00702
00703 CellBinding* Sheet::nextCellBinding()
00704 {
00705 return d->cellBindings.next();
00706 }
00707
00708 void Sheet::setDefaultHeight( double height )
00709 {
00710 if ( isProtected() )
00711 NO_MODIFICATION_POSSIBLE;
00712
00713 d->defaultRowFormat->setDblHeight( height );
00714 }
00715
00716 void Sheet::setDefaultWidth( double width )
00717 {
00718 if ( isProtected() )
00719 NO_MODIFICATION_POSSIBLE;
00720
00721 d->defaultColumnFormat->setDblWidth( width );
00722 }
00723
00724 double Sheet::sizeMaxX() const
00725 {
00726 return d->sizeMaxX;
00727 }
00728
00729 double Sheet::sizeMaxY() const
00730 {
00731 return d->sizeMaxY;
00732 }
00733
00734 int Sheet::maxColumn() const
00735 {
00736 return d->maxColumn;
00737 }
00738
00739 int Sheet::maxRow() const
00740 {
00741 return d->maxRow;
00742 }
00743
00744 const QPen& Sheet::emptyPen() const
00745 {
00746 return d->emptyPen;
00747 }
00748
00749 const QBrush& Sheet::emptyBrush() const
00750 {
00751 return d->emptyBrush;
00752 }
00753
00754 const QColor& Sheet::emptyColor() const
00755 {
00756 return d->emptyColor;
00757 }
00758
00759 KSpread::DependencyManager *Sheet::dependencies ()
00760 {
00761 return d->dependencies;
00762 }
00763
00764 int Sheet::numSelected() const
00765 {
00766 int num = 0;
00767
00768 QPtrListIterator<EmbeddedObject> it( d->workbook->doc()->embeddedObjects() );
00769 for ( ; it.current() ; ++it )
00770 {
00771 if( it.current()->sheet() == this && it.current()->isSelected() )
00772 num++;
00773 }
00774
00775 return num;
00776 }
00777
00778 int Sheet::leftColumn( double _xpos, double &_left,
00779 const Canvas *_canvas ) const
00780 {
00781 if ( _canvas )
00782 {
00783 _xpos += _canvas->xOffset();
00784 _left = -_canvas->xOffset();
00785 }
00786 else
00787 _left = 0.0;
00788
00789 int col = 1;
00790 double x = columnFormat( col )->dblWidth( _canvas );
00791 while ( x < _xpos )
00792 {
00793
00794 if ( col >= KS_colMax )
00795 {
00796 kdDebug(36001) << "Sheet:leftColumn: invalid column (col: " << col + 1 << ")" << endl;
00797 return KS_colMax + 1;
00798 }
00799 _left += columnFormat( col )->dblWidth( _canvas );
00800 col++;
00801 x += columnFormat( col )->dblWidth( _canvas );
00802 }
00803
00804 return col;
00805 }
00806
00807 int Sheet::rightColumn( double _xpos, const Canvas *_canvas ) const
00808 {
00809 if ( _canvas )
00810 _xpos += _canvas->xOffset();
00811
00812 int col = 1;
00813 double x = 0.0;
00814 while ( x < _xpos )
00815 {
00816
00817 if ( col > KS_colMax )
00818 {
00819 kdDebug(36001) << "Sheet:rightColumn: invalid column (col: " << col << ")" << endl;
00820 return KS_colMax + 1;
00821 }
00822 x += columnFormat( col )->dblWidth( _canvas );
00823 col++;
00824 }
00825
00826 return col - 1;
00827 }
00828
00829 QRect Sheet::visibleRect( Canvas const * const _canvas ) const
00830 {
00831 int top = 0;
00832 int left = 0;
00833
00834 double x = 0;
00835 double y = 0;
00836 double width = 0;
00837 double height = 0;
00838
00839 if ( _canvas )
00840 {
00841 y += _canvas->yOffset() * _canvas->zoom();
00842 x += _canvas->xOffset() * _canvas->zoom();
00843 width = _canvas->width();
00844 height = _canvas->height();
00845 }
00846
00847 double yn = rowFormat( top )->dblHeight( _canvas );
00848 while ( yn < y )
00849 {
00850 if ( top >= KS_rowMax )
00851 break;
00852
00853 ++top;
00854 yn += rowFormat( top )->dblHeight( _canvas );
00855 }
00856
00857 int bottom = top + 1;
00858
00859 y += height;
00860 while ( yn < y )
00861 {
00862 if ( bottom > KS_rowMax )
00863 break;
00864
00865 ++bottom;
00866 yn += rowFormat( bottom )->dblHeight( _canvas );
00867 }
00868
00869 double xn = columnFormat( left )->dblWidth( _canvas );
00870 while ( xn < x )
00871 {
00872 if ( left >= KS_colMax )
00873 break;
00874
00875 ++left;
00876 xn += columnFormat( left )->dblWidth( _canvas );
00877 }
00878 x += width;
00879
00880 int right = left + 1;
00881
00882 while ( xn < x )
00883 {
00884 if ( right > KS_colMax )
00885 break;
00886
00887 ++right;
00888 xn += columnFormat( right )->dblWidth( _canvas );
00889 }
00890 x += width;
00891
00892 return QRect( left, top, right - left + 1, bottom - top + 1 );
00893 }
00894
00895 int Sheet::topRow( double _ypos, double & _top,
00896 const Canvas *_canvas ) const
00897 {
00898 if ( _canvas )
00899 {
00900 _ypos += _canvas->yOffset();
00901 _top = -_canvas->yOffset();
00902 }
00903 else
00904 _top = 0.0;
00905
00906 int row = 1;
00907 double y = rowFormat( row )->dblHeight( _canvas );
00908 while ( y < _ypos )
00909 {
00910
00911 if ( row >= KS_rowMax )
00912 {
00913 kdDebug(36001) << "Sheet:topRow: invalid row (row: " << row + 1 << ")" << endl;
00914 return KS_rowMax + 1;
00915 }
00916 _top += rowFormat( row )->dblHeight( _canvas );
00917 row++;
00918 y += rowFormat( row )->dblHeight( _canvas );
00919 }
00920
00921 return row;
00922 }
00923
00924 int Sheet::bottomRow( double _ypos, const Canvas *_canvas ) const
00925 {
00926 if ( _canvas )
00927 _ypos += _canvas->yOffset();
00928
00929 int row = 1;
00930 double y = 0.0;
00931 while ( y < _ypos )
00932 {
00933
00934 if ( row > KS_rowMax )
00935 {
00936 kdDebug(36001) << "Sheet:bottomRow: invalid row (row: " << row << ")" << endl;
00937 return KS_rowMax + 1;
00938 }
00939 y += rowFormat( row )->dblHeight( _canvas );
00940 row++;
00941 }
00942
00943 return row - 1;
00944 }
00945
00946 double Sheet::dblColumnPos( int _col, const Canvas *_canvas ) const
00947 {
00948 double x = 0.0;
00949 if ( _canvas )
00950 x -= _canvas->xOffset();
00951 for ( int col = 1; col < _col; col++ )
00952 {
00953
00954 if ( col > KS_colMax )
00955 {
00956 kdDebug(36001) << "Sheet:columnPos: invalid column (col: " << col << ")" << endl;
00957 return x;
00958 }
00959
00960 x += columnFormat( col )->dblWidth( _canvas );
00961 }
00962
00963 return x;
00964 }
00965
00966 int Sheet::columnPos( int _col, const Canvas *_canvas ) const
00967 {
00968 return (int)dblColumnPos( _col, _canvas );
00969 }
00970
00971
00972 double Sheet::dblRowPos( int _row, const Canvas *_canvas ) const
00973 {
00974 double y = 0.0;
00975 if ( _canvas )
00976 y -= _canvas->yOffset();
00977
00978 for ( int row = 1 ; row < _row ; row++ )
00979 {
00980
00981 if ( row > KS_rowMax )
00982 {
00983 kdDebug(36001) << "Sheet:rowPos: invalid row (row: " << row << ")" << endl;
00984 return y;
00985 }
00986
00987 y += rowFormat( row )->dblHeight( _canvas );
00988 }
00989
00990 return y;
00991 }
00992
00993 int Sheet::rowPos( int _row, const Canvas *_canvas ) const
00994 {
00995 return (int)dblRowPos( _row, _canvas );
00996 }
00997
00998
00999 void Sheet::adjustSizeMaxX ( double _x )
01000 {
01001 d->sizeMaxX += _x;
01002 }
01003
01004 void Sheet::adjustSizeMaxY ( double _y )
01005 {
01006 d->sizeMaxY += _y;
01007 }
01008
01009 Cell* Sheet::visibleCellAt( int _column, int _row, bool _scrollbar_update )
01010 {
01011 Cell* cell = cellAt( _column, _row, _scrollbar_update );
01012 if ( cell->obscuringCells().isEmpty() )
01013 return cell;
01014 else
01015 return cell->obscuringCells().last();
01016 }
01017
01018 Cell* Sheet::firstCell() const
01019 {
01020 return d->cells.firstCell();
01021 }
01022
01023 RowFormat* Sheet::firstRow() const
01024 {
01025 return d->rows.first();
01026 }
01027
01028 ColumnFormat* Sheet::firstCol() const
01029 {
01030 return d->columns.first();
01031 }
01032
01033 Cell* Sheet::cellAt( int _column, int _row ) const
01034 {
01035 Cell *p = d->cells.lookup( _column, _row );
01036 if ( p != 0L )
01037 return p;
01038
01039 return d->defaultCell;
01040 }
01041
01042 Cell* Sheet::cellAt( int _column, int _row, bool _scrollbar_update )
01043 {
01044 if ( _scrollbar_update && d->scrollBarUpdates )
01045 {
01046 checkRangeHBorder( _column );
01047 checkRangeVBorder( _row );
01048 }
01049
01050 Cell *p = d->cells.lookup( _column, _row );
01051 if ( p != 0L )
01052 return p;
01053
01054 return d->defaultCell;
01055 }
01056
01057 ColumnFormat* Sheet::nonDefaultColumnFormat( int _column, bool force_creation )
01058 {
01059 ColumnFormat *p = d->columns.lookup( _column );
01060 if ( p != 0L || !force_creation )
01061 return p;
01062
01063 p = new ColumnFormat( this, _column );
01064
01065 p->setDblWidth( d->defaultColumnFormat->dblWidth() );
01066
01067 d->columns.insertElement( p, _column );
01068
01069 return p;
01070 }
01071
01072 RowFormat* Sheet::nonDefaultRowFormat( int _row, bool force_creation )
01073 {
01074 RowFormat *p = d->rows.lookup( _row );
01075 if ( p != 0L || !force_creation )
01076 return p;
01077
01078 p = new RowFormat( this, _row );
01079
01080 p->setDblHeight( d->defaultRowFormat->dblHeight() );
01081
01082 d->rows.insertElement( p, _row );
01083
01084 return p;
01085 }
01086
01087 Cell* Sheet::nonDefaultCell( int _column, int _row,
01088 bool _scrollbar_update, Style * _style )
01089 {
01090
01091
01092
01093
01094 if ( _scrollbar_update && d->scrollBarUpdates )
01095 {
01096 checkRangeHBorder( _column );
01097 checkRangeVBorder( _row );
01098 }
01099
01100 Cell * p = d->cells.lookup( _column, _row );
01101 if ( p != 0L )
01102 return p;
01103
01104 Cell * cell = 0;
01105
01106 if ( _style )
01107 cell = new Cell( this, _style, _column, _row );
01108 else
01109 cell = new Cell( this, _column, _row );
01110
01111 insertCell( cell );
01112
01113 return cell;
01114 }
01115
01116 void Sheet::setText( int _row, int _column, const QString& _text, bool asString )
01117 {
01118 ProtectedCheck prot;
01119 prot.setSheet (this);
01120 prot.add (QPoint (_column, _row));
01121 if (prot.check())
01122 NO_MODIFICATION_POSSIBLE;
01123
01124 DataManipulator *dm = new DataManipulator ();
01125 dm->setSheet (this);
01126 dm->setValue (_text);
01127 dm->setParsing (!asString);
01128 dm->add (QPoint (_column, _row));
01129 dm->execute ();
01130
01131
01132
01133
01134
01135
01136
01137
01138
01139
01140
01141
01142
01143
01144 if(_text.at(0)=='!')
01145 emit sig_updateView( this, Region(_column,_row,_column,_row) );
01146 }
01147
01148 void Sheet::setArrayFormula (Selection *selectionInfo, const QString &_text)
01149 {
01150
01151 ProtectedCheck prot;
01152 prot.setSheet (this);
01153 prot.add (*selectionInfo);
01154 if (prot.check())
01155 NO_MODIFICATION_POSSIBLE;
01156
01157
01158 ArrayFormulaManipulator *afm = new ArrayFormulaManipulator;
01159 afm->setSheet (this);
01160 afm->setText (_text);
01161 afm->add (*selectionInfo);
01162 afm->execute ();
01163
01164
01165
01166
01167
01168
01169
01170
01171
01172
01173
01174
01175
01176
01177
01178
01179
01180
01181
01182
01183
01184
01185
01186
01187
01188
01189 }
01190
01191 void Sheet::setLayoutDirtyFlag()
01192 {
01193 Cell * c = d->cells.firstCell();
01194 for( ; c; c = c->nextCell() )
01195 c->setLayoutDirtyFlag();
01196 }
01197
01198 void Sheet::setCalcDirtyFlag()
01199 {
01200 Cell* c = d->cells.firstCell();
01201 for( ; c; c = c->nextCell() )
01202 {
01203 if ( !(c->isObscured() && c->isPartOfMerged()) )
01204 c->setCalcDirtyFlag();
01205 }
01206 }
01207
01208 void Sheet::updateAllDependencies()
01209 {
01210 for (Cell* cell = d->cells.firstCell() ; cell ; cell = cell->nextCell())
01211 {
01212 Point cellLocation;
01213 cellLocation.setSheet(cell->sheet());
01214 cellLocation.setRow(cell->row());
01215 cellLocation.setColumn(cell->column());
01216 d->dependencies->cellChanged(cellLocation);
01217 }
01218 }
01219
01220 void Sheet::recalc()
01221 {
01222 recalc(false);
01223 }
01224
01225 void Sheet::recalc( bool force )
01226 {
01227 ElapsedTime et( "Recalculating " + d->name, ElapsedTime::PrintOnlyTime );
01228
01229
01230 setCalcDirtyFlag();
01231
01232
01233
01234 if ( !getAutoCalc() && !force )
01235 return;
01236
01237
01238
01239
01240 if ( !getAutoCalc() )
01241 updateAllDependencies();
01242
01243
01244
01245
01246
01247
01248
01249
01250 Cell* c;
01251
01252 int count = 0;
01253 c = d->cells.firstCell();
01254 for( ; c; c = c->nextCell() )
01255 ++count;
01256
01257 int cur = 0;
01258 int percent = -1;
01259 c = d->cells.firstCell();
01260 for( ; c; c = c->nextCell() )
01261 {
01262 c->calc (false);
01263 cur++;
01264
01265 if (cur*100/count != percent) {
01266 percent = cur*100/count;
01267
01268 }
01269 }
01270
01271
01272 emit sig_updateView( this );
01273 }
01274
01275 void Sheet::valueChanged (Cell *cell)
01276 {
01277
01278
01279
01280
01281 Point c;
01282 c.setRow (cell->row());
01283 c.setColumn (cell->column());
01284 c.setSheet( this );
01285
01286
01287 if ( getAutoCalc() )
01288 d->dependencies->cellChanged (c);
01289
01290
01291
01292
01293 }
01294
01295
01296
01297
01298
01299
01300
01301
01302
01303
01304
01305
01306
01307
01308
01309
01310
01311
01312
01313
01314
01315
01316
01317
01318
01319
01320
01321
01322
01323
01324
01325
01326
01327
01328
01329
01330
01331
01332
01333
01334
01335
01336
01337
01338
01339
01340
01341
01342
01343
01344
01345
01346
01347
01348
01349
01350
01351
01352
01353
01354
01355
01356
01357
01358
01359
01360
01361
01362
01363
01364
01365
01366
01367
01368
01369
01370
01371
01372
01373
01374
01375
01376
01377
01378
01379
01380
01381
01382
01383
01384
01385
01386
01387
01388
01389 class UndoAction* Sheet::CellWorkerTypeA::createUndoAction( Doc* doc, Sheet* sheet, const KSpread::Region& region )
01390 {
01391 QString title = getUndoTitle();
01392 return new UndoCellFormat( doc, sheet, region, title );
01393 }
01394
01395
01396
01397
01398
01399
01400
01401
01402
01403
01404
01405
01406
01407
01408
01409
01410
01411
01412
01413
01414
01415
01416
01417
01418
01419
01420
01421
01422
01423
01424
01425
01426
01427
01428
01429
01430
01431
01432
01433
01434
01435
01436
01437
01438
01439
01440
01441
01442
01443
01444
01445
01446
01447
01448
01449
01450
01451
01452
01453
01454
01455
01456
01457
01458
01459
01460
01461
01462
01463
01464
01465
01466
01467
01468
01469
01470
01471
01472
01473
01474
01475
01476
01477
01478
01479
01480
01481
01482
01483
01484
01485
01486
01487
01488
01489
01490
01491
01492
01493
01494
01495
01496
01497
01498
01499
01500
01501
01502
01503
01504
01505
01506
01507
01508
01509
01510
01511
01512
01513
01514
01515
01516
01517
01518
01519
01520
01521
01522
01523
01524
01525
01526
01527
01528
01529
01530
01531
01532
01533
01534
01535
01536
01537
01538
01539
01540
01541
01542 Sheet::SelectionType Sheet::workOnCells( Selection* selectionInfo, CellWorker & worker )
01543 {
01544 Sheet::SelectionType result;
01545
01546 doc()->emitBeginOperation();
01547
01548
01549 bool selected = !(selectionInfo->isSingular());
01550
01551
01552 if ( !doc()->undoLocked() )
01553 {
01554 UndoAction* undo = worker.createUndoAction(doc(), this, *selectionInfo);
01555
01556 if ( undo != 0 )
01557 {
01558 doc()->addCommand( undo );
01559 }
01560 }
01561
01562 Region::ConstIterator endOfList(selectionInfo->constEnd());
01563 for (Region::ConstIterator it = selectionInfo->constBegin(); it != endOfList; ++it)
01564 {
01565
01566 QRect range = (*it)->rect().normalize();
01567
01568 int top = range.top();
01569 int left = range.left();
01570 int bottom = range.bottom();
01571 int right = range.right();
01572
01573
01574 Cell * cell;
01575 Style * s = doc()->styleManager()->defaultStyle();
01576
01577 if ( !worker.type_B && selected && util_isColumnSelected(range) )
01578 {
01579 for ( RowFormat * rw = d->rows.first(); rw; rw = rw->next() )
01580 {
01581 if ( worker.testCondition( rw ) )
01582 {
01583 for ( int col = left; col <= right; ++col )
01584 {
01585 cell = nonDefaultCell( col, rw->row(), false, s );
01586 }
01587 }
01588 }
01589 }
01590
01591
01592 if ( selected && util_isRowSelected(range) )
01593 {
01594 for ( int row = top; row <= bottom; ++row )
01595 {
01596 cell = getFirstCellRow( row );
01597 while ( cell )
01598 {
01599 if ( worker.testCondition( cell ) )
01600 {
01601 if ( worker.type_B )
01602 worker.doWork( cell, false, cell->column(), row );
01603 else
01604 worker.prepareCell( cell );
01605 }
01606 cell = getNextCellRight( cell->column(), row );
01607 }
01608 }
01609
01610 if ( worker.type_B )
01611 {
01612
01613 ;
01614 }
01615 else
01616 {
01617
01618 for ( int i = top; i <= bottom; ++i )
01619 {
01620 RowFormat * rw = nonDefaultRowFormat(i);
01621 worker.doWork( rw );
01622 }
01623
01624 for ( int row = top; row <= bottom; ++row )
01625 {
01626 cell = getFirstCellRow( row );
01627 while ( cell )
01628 {
01629 if ( worker.testCondition( cell ) )
01630 {
01631 worker.doWork( cell, false, cell->column(), row );
01632 }
01633 cell = getNextCellRight( cell->column(), row );
01634 }
01635 }
01636
01637 }
01638 result = CompleteRows;
01639 }
01640
01641 else if ( selected && util_isColumnSelected(range) )
01642 {
01643 for ( int col = range.left(); col <= right; ++col )
01644 {
01645 cell = getFirstCellColumn( col );
01646 while ( cell )
01647 {
01648 if ( worker.testCondition( cell ) )
01649 {
01650 if ( worker.type_B )
01651 worker.doWork( cell, false, col, cell->row() );
01652 else
01653 worker.prepareCell( cell );
01654 }
01655
01656 cell = getNextCellDown( col, cell->row() );
01657 }
01658 }
01659
01660 if ( worker.type_B )
01661 {
01662 ;
01663 }
01664 else
01665 {
01666
01667 for ( int i = left; i <= right; ++i )
01668 {
01669 ColumnFormat * cl = nonDefaultColumnFormat( i );
01670 worker.doWork( cl );
01671 }
01672
01673 for ( RowFormat * rw = d->rows.first(); rw; rw = rw->next() )
01674 {
01675 if ( worker.testCondition( rw ) )
01676 {
01677 for ( int i = left; i <= right; ++i )
01678 {
01679 cell = nonDefaultCell( i, rw->row(), false, s );
01680 worker.doWork( cell, false, i, rw->row() );
01681 }
01682 }
01683 }
01684 }
01685 result = CompleteColumns;
01686 }
01687
01688 else
01689 {
01690 for ( int x = left; x <= right; ++x )
01691 {
01692 enableScrollBarUpdates(false);
01693 for ( int y = top; y <= bottom; ++y )
01694 {
01695 cell = cellAt( x, y );
01696 if ( worker.testCondition( cell ) )
01697 {
01698 if ( cell == d->defaultCell && worker.create_if_default )
01699 {
01700 cell = new Cell( this, s, x, y );
01701 insertCell( cell );
01702 }
01703 if ( cell != d->defaultCell )
01704 {
01705
01706 worker.doWork( cell, true, x, y );
01707 }
01708 }
01709 }
01710 enableScrollBarUpdates(true);
01711 checkRangeVBorder(bottom);
01712 }
01713 checkRangeHBorder(right);
01714 result = CellRegion;
01715 }
01716
01717 }
01718
01719
01720 emit sig_updateView( this );
01721
01722 if (worker.emit_signal)
01723 {
01724 emit sig_updateView( this, *selectionInfo );
01725 }
01726
01727 return result;
01728 }
01729
01730 void Sheet::setSelectionFont( Selection* selectionInfo,
01731 const char *_font, int _size,
01732 signed char _bold, signed char _italic,
01733 signed char _underline, signed char _strike)
01734 {
01735 FontManipulator* manipulator = new FontManipulator();
01736 manipulator->setSheet(this);
01737 manipulator->setProperty(Format::PFont);
01738 manipulator->setFontFamily(_font);
01739 manipulator->setFontSize(_size);
01740 manipulator->setFontBold(_bold);
01741 manipulator->setFontItalic(_italic);
01742 manipulator->setFontStrike(_strike);
01743 manipulator->setFontUnderline(_underline);
01744 manipulator->add(*selectionInfo);
01745 manipulator->execute();
01746 }
01747
01748 void Sheet::setSelectionSize(Selection* selectionInfo,
01749 int _size)
01750 {
01751
01752 int size;
01753 Cell* c;
01754 QPoint marker(selectionInfo->marker());
01755 c = cellAt(marker);
01756 size = c->format()->textFontSize(marker.x(), marker.y());
01757
01758 FontManipulator* manipulator = new FontManipulator();
01759 manipulator->setSheet(this);
01760 manipulator->setProperty(Format::PFont);
01761 manipulator->setFontSize(_size+size);
01762 manipulator->add(*selectionInfo);
01763 manipulator->execute();
01764 }
01765
01766
01767 struct SetSelectionUpperLowerWorker : public Sheet::CellWorker {
01768 int _type;
01769 Sheet * _s;
01770 SetSelectionUpperLowerWorker( int type, Sheet * s )
01771 : Sheet::CellWorker( false ), _type( type ), _s( s ) { }
01772
01773 class UndoAction* createUndoAction( Doc* doc, Sheet* sheet, const KSpread::Region& region )
01774 {
01775 return new UndoChangeAreaTextCell( doc, sheet, region );
01776 }
01777 bool testCondition( Cell* c ) {
01778 return ( !c->value().isNumber() && !c->value().isBoolean() &&!c->isFormula() && !c->isDefault()
01779 && !c->text().isEmpty() && c->text()[0] != '*' && c->text()[0] != '!'
01780 && !c->isPartOfMerged() );
01781 }
01782 void doWork( Cell* cell, bool, int, int )
01783 {
01784 cell->setDisplayDirtyFlag();
01785 if ( _type == -1 )
01786 cell->setCellText( (cell->text().lower()));
01787 else if ( _type == 1 )
01788 cell->setCellText( (cell->text().upper()));
01789 cell->clearDisplayDirtyFlag();
01790 }
01791 };
01792
01793 void Sheet::setSelectionUpperLower( Selection* selectionInfo,
01794 int _type )
01795 {
01796 SetSelectionUpperLowerWorker w( _type, this );
01797 workOnCells( selectionInfo, w );
01798 }
01799
01800
01801 struct SetSelectionFirstLetterUpperWorker : public Sheet::CellWorker
01802 {
01803 Changes * _c;
01804 Sheet * _s;
01805 SetSelectionFirstLetterUpperWorker( Sheet * s )
01806 : Sheet::CellWorker( false ), _s( s ) { }
01807
01808 class UndoAction* createUndoAction( Doc* doc, Sheet* sheet, const KSpread::Region& region ) {
01809 return new UndoChangeAreaTextCell( doc, sheet, region );
01810 }
01811 bool testCondition( Cell* c ) {
01812 return ( !c->value().isNumber() && !c->value().isBoolean() &&!c->isFormula() && !c->isDefault()
01813 && !c->text().isEmpty() && c->text()[0] != '*' && c->text()[0] != '!'
01814 && !c->isPartOfMerged() );
01815 }
01816 void doWork( Cell* cell, bool, int, int )
01817 {
01818
01819 cell->setDisplayDirtyFlag();
01820 QString tmp = cell->text();
01821 int len = tmp.length();
01822 cell->setCellText( (tmp.at(0).upper()+tmp.right(len-1)) );
01823 cell->clearDisplayDirtyFlag();
01824 }
01825 };
01826
01827 void Sheet::setSelectionfirstLetterUpper( Selection* selectionInfo)
01828 {
01829 SetSelectionFirstLetterUpperWorker w( this );
01830 workOnCells( selectionInfo, w );
01831 }
01832
01833
01834 struct SetSelectionVerticalTextWorker : public Sheet::CellWorker {
01835 bool _b;
01836 SetSelectionVerticalTextWorker( bool b ) : Sheet::CellWorker( ), _b( b ) { }
01837
01838 class UndoAction* createUndoAction( Doc* doc, Sheet* sheet, const KSpread::Region& region ) {
01839 QString title=i18n("Vertical Text");
01840 return new UndoCellFormat( doc, sheet, region, title );
01841 }
01842 bool testCondition( Cell* cell ) {
01843 return ( !cell->isPartOfMerged() );
01844 }
01845 void doWork( Cell* cell, bool, int, int ) {
01846 cell->setDisplayDirtyFlag();
01847 cell->format()->setVerticalText( _b );
01848 cell->format()->setMultiRow( false );
01849 cell->format()->setAngle( 0 );
01850 cell->clearDisplayDirtyFlag();
01851 }
01852 };
01853
01854 void Sheet::setSelectionVerticalText( Selection* selectionInfo,
01855 bool _b )
01856 {
01857 SetSelectionVerticalTextWorker w( _b );
01858 workOnCells( selectionInfo, w );
01859 }
01860
01861
01862 struct SetSelectionCommentWorker : public Sheet::CellWorker {
01863 QString _comment;
01864 SetSelectionCommentWorker( QString comment ) : Sheet::CellWorker( ), _comment( comment ) { }
01865
01866 class UndoAction* createUndoAction( Doc* doc, Sheet* sheet, const KSpread::Region& region ) {
01867 QString title=i18n("Add Comment");
01868 return new UndoCellFormat( doc, sheet, region, title );
01869 }
01870 bool testCondition( Cell* cell ) {
01871 return ( !cell->isPartOfMerged() );
01872 }
01873 void doWork( Cell* cell, bool, int, int ) {
01874 cell->setDisplayDirtyFlag();
01875 cell->format()->setComment( _comment );
01876 cell->clearDisplayDirtyFlag();
01877 }
01878 };
01879
01880 void Sheet::setSelectionComment( Selection* selectionInfo,
01881 const QString &_comment)
01882 {
01883 SetSelectionCommentWorker w( _comment );
01884 workOnCells( selectionInfo, w );
01885 }
01886
01887
01888 void Sheet::setSelectionAngle( Selection* selectionInfo,
01889 int _value )
01890 {
01891 AngleManipulator* manipulator = new AngleManipulator();
01892 manipulator->setSheet(this);
01893 manipulator->setProperty(Format::PAngle);
01894 manipulator->setAngle(_value);
01895 manipulator->add(*selectionInfo);
01896 manipulator->execute();
01897 }
01898
01899 struct SetSelectionRemoveCommentWorker : public Sheet::CellWorker {
01900 SetSelectionRemoveCommentWorker( ) : Sheet::CellWorker( false ) { }
01901
01902 class UndoAction* createUndoAction( Doc* doc, Sheet* sheet, const KSpread::Region& region ) {
01903 QString title=i18n("Remove Comment");
01904 return new UndoCellFormat( doc, sheet, region, title );
01905 }
01906 bool testCondition( Cell* cell ) {
01907 return ( !cell->isPartOfMerged() );
01908 }
01909 void doWork( Cell* cell, bool, int, int ) {
01910 cell->setDisplayDirtyFlag();
01911 cell->format()->setComment( "" );
01912 cell->clearDisplayDirtyFlag();
01913 }
01914 };
01915
01916 void Sheet::setSelectionRemoveComment( Selection* selectionInfo )
01917 {
01918 if (areaIsEmpty(*selectionInfo, Comment))
01919 return;
01920
01921 SetSelectionRemoveCommentWorker w;
01922 workOnCells( selectionInfo, w );
01923 }
01924
01925
01926 void Sheet::setSelectionTextColor( Selection* selectionInfo,
01927 const QColor &tb_Color )
01928 {
01929 FontColorManipulator* manipulator = new FontColorManipulator();
01930 manipulator->setSheet(this);
01931 manipulator->setProperty(Format::PTextPen);
01932 manipulator->setTextColor(tb_Color);
01933 manipulator->add(*selectionInfo);
01934 manipulator->execute();
01935 }
01936
01937 void Sheet::setSelectionbgColor( Selection* selectionInfo,
01938 const QColor &bg_Color )
01939 {
01940 BackgroundColorManipulator* manipulator = new BackgroundColorManipulator();
01941 manipulator->setSheet(this);
01942 manipulator->setProperty(Format::PBackgroundColor);
01943 manipulator->setBackgroundColor(bg_Color);
01944 manipulator->add(*selectionInfo);
01945 manipulator->execute();
01946 }
01947
01948
01949 struct SetSelectionBorderColorWorker : public Sheet::CellWorker {
01950 const QColor& bd_Color;
01951 SetSelectionBorderColorWorker( const QColor& _bd_Color ) : Sheet::CellWorker( false ), bd_Color( _bd_Color ) { }
01952
01953 class UndoAction* createUndoAction( Doc* doc, Sheet* sheet, const KSpread::Region& region ) {
01954 QString title=i18n("Change Border Color");
01955 return new UndoCellFormat( doc, sheet, region, title );
01956 }
01957 bool testCondition( Cell* cell ) {
01958 return ( !cell->isPartOfMerged() );
01959 }
01960 void doWork( Cell* cell, bool, int, int ) {
01961 cell->setDisplayDirtyFlag();
01962 int it_Row = cell->row();
01963 int it_Col = cell->column();
01964 if ( cell->format()->topBorderStyle( it_Row, it_Col )!=Qt::NoPen )
01965 cell->format()->setTopBorderColor( bd_Color );
01966 if ( cell->format()->leftBorderStyle( it_Row, it_Col )!=Qt::NoPen )
01967 cell->format()->setLeftBorderColor( bd_Color );
01968 if ( cell->format()->fallDiagonalStyle( it_Row, it_Col )!=Qt::NoPen )
01969 cell->format()->setFallDiagonalColor( bd_Color );
01970 if ( cell->format()->goUpDiagonalStyle( it_Row, it_Col )!=Qt::NoPen )
01971 cell->format()->setGoUpDiagonalColor( bd_Color );
01972 if ( cell->format()->bottomBorderStyle( it_Row, it_Col )!=Qt::NoPen )
01973 cell->format()->setBottomBorderColor( bd_Color );
01974 if ( cell->format()->rightBorderStyle( it_Row, it_Col )!=Qt::NoPen )
01975 cell->format()->setRightBorderColor( bd_Color );
01976 cell->clearDisplayDirtyFlag();
01977 }
01978 };
01979
01980 void Sheet::setSelectionBorderColor( Selection* selectionInfo,
01981 const QColor &bd_Color )
01982 {
01983 SetSelectionBorderColorWorker w( bd_Color );
01984 workOnCells( selectionInfo, w );
01985 }
01986
01987
01988 void Sheet::setSeries( const QPoint &_marker, double start, double end, double step, Series mode, Series type)
01989 {
01990 doc()->emitBeginOperation();
01991
01992 QString cellText;
01993
01994 int x,y;
01995
01996
01997
01998
01999 int numberOfCells;
02000 if (end > start)
02001 numberOfCells = (int) ((end - start) / step + 1);
02002 else if ( end <start )
02003 numberOfCells = (int) ((start - end) / step + 1);
02004 else
02005 numberOfCells = 1;
02006 if (type == Geometric)
02007 {
02008
02009
02010
02011
02012 numberOfCells = (int)( (log((double)end) / log((double)start)) +
02013 DBL_EPSILON) + 1;
02014 }
02015
02016 Cell * cell = NULL;
02017
02018
02019
02020
02021 QRect undoRegion;
02022
02023 undoRegion.setLeft(_marker.x());
02024 undoRegion.setTop(_marker.y());
02025
02026
02027
02028
02029
02030
02031
02032
02033
02034
02035
02036
02037 if ( mode == Column )
02038 {
02039 for ( y = _marker.y(); y <= (_marker.y() + numberOfCells - 1), y <= KS_rowMax; y++ )
02040 {
02041 cell = cellAt( _marker.x(), y );
02042
02043 if ( cell->isPartOfMerged() )
02044 {
02045
02046 cell = cell->obscuringCells().first();
02047 undoRegion.setLeft(QMIN(undoRegion.left(), cell->column()));
02048 }
02049
02050
02051
02052
02053
02054 numberOfCells += cell->extraYCells();
02055 y += cell->extraYCells();
02056 }
02057 undoRegion.setRight( _marker.x() );
02058 undoRegion.setBottom( y - 1 );
02059
02060 checkRangeVBorder( undoRegion.bottom() );
02061 }
02062 else if(mode == Row)
02063 {
02064 for ( x = _marker.x(); x <=(_marker.x() + numberOfCells - 1), x <= KS_colMax; x++ )
02065 {
02066
02067
02068 cell = cellAt( x,_marker.y(), false );
02069
02070 if ( cell->isPartOfMerged() )
02071 {
02072 cell = cell->obscuringCells().first();
02073 undoRegion.setTop(QMIN(undoRegion.top(), cell->row()));
02074 }
02075 numberOfCells += cell->extraXCells();
02076 x += cell->extraXCells();
02077 }
02078 undoRegion.setBottom( _marker.y() );
02079 undoRegion.setRight( x - 1 );
02080
02081 checkRangeHBorder( undoRegion.right() );
02082 }
02083
02084 kdDebug() << "Saving undo information" << endl;
02085
02086 if ( !doc()->undoLocked() )
02087 {
02088 UndoChangeAreaTextCell *undo = new
02089 UndoChangeAreaTextCell( doc(), this, undoRegion );
02090 doc()->addCommand( undo );
02091 }
02092
02093 kdDebug() << "Saving undo information done" << endl;
02094
02095 setRegionPaintDirty( undoRegion );
02096
02097 x = _marker.x();
02098 y = _marker.y();
02099
02100
02101 double incr;
02102 Style * s = doc()->styleManager()->defaultStyle();
02103 if (step >= 0 && start < end)
02104 {
02105 for ( incr = start; incr <= end; )
02106 {
02107 cell = nonDefaultCell( x, y, false, s );
02108
02109 if ( cell->isPartOfMerged() )
02110 {
02111 cell = cell->obscuringCells().first();
02112 }
02113
02114
02115
02116 cell->setNumber( incr );
02117 if (mode == Column)
02118 {
02119 ++y;
02120 if (cell->doesMergeCells())
02121 {
02122 y += cell->extraYCells();
02123 }
02124 if ( y > KS_rowMax )
02125 {
02126 break;
02127 }
02128 }
02129 else if (mode == Row)
02130 {
02131 ++x;
02132 if (cell->doesMergeCells())
02133 {
02134 x += cell->extraXCells();
02135 }
02136 if ( x > KS_colMax )
02137 {
02138 break;
02139 }
02140 }
02141 else
02142 {
02143 kdDebug(36001) << "Error in Series::mode" << endl;
02144 return;
02145 }
02146
02147 if (type == Linear)
02148 incr = incr + step;
02149 else if (type == Geometric)
02150 incr = incr * step;
02151 else
02152 {
02153 kdDebug(36001) << "Error in Series::type" << endl;
02154 return;
02155 }
02156 }
02157 }
02158 else
02159 if (step >= 0 && start > end)
02160 {
02161 for ( incr = start; incr >= end; )
02162 {
02163 cell = nonDefaultCell( x, y, false, s );
02164
02165 if (cell->isPartOfMerged())
02166 {
02167 cell = cell->obscuringCells().first();
02168 }
02169
02170
02171 cell->setNumber( incr );
02172 if (mode == Column)
02173 {
02174 ++y;
02175 if (cell->doesMergeCells())
02176 {
02177 y += cell->extraYCells();
02178 }
02179 if ( y > KS_rowMax )
02180 {
02181 break;
02182 }
02183 }
02184 else if (mode == Row)
02185 {
02186 ++x;
02187 if (cell->doesMergeCells())
02188 {
02189 x += cell->extraXCells();
02190 }
02191 if ( x > KS_colMax )
02192 {
02193 break;
02194 }
02195 }
02196 else
02197 {
02198 kdDebug(36001) << "Error in Series::mode" << endl;
02199 return;
02200 }
02201
02202 if (type == Linear)
02203 incr = incr + step;
02204 else if (type == Geometric)
02205 incr = incr * step;
02206 else
02207 {
02208 kdDebug(36001) << "Error in Series::type" << endl;
02209 return;
02210 }
02211 }
02212 }
02213 else
02214 {
02215 for ( incr = start; incr <= end; )
02216 {
02217 cell = nonDefaultCell( x, y, false, s );
02218
02219 if (cell->isPartOfMerged())
02220 {
02221 cell = cell->obscuringCells().first();
02222 }
02223
02224
02225 cell->setNumber( incr );
02226 if (mode == Column)
02227 {
02228 ++y;
02229 if (cell->doesMergeCells())
02230 {
02231 y += cell->extraYCells();
02232 }
02233 if ( y > KS_rowMax )
02234 {
02235 break;
02236 }
02237 }
02238 else if (mode == Row)
02239 {
02240 ++x;
02241 if (cell->doesMergeCells())
02242 {
02243 x += cell->extraXCells();
02244 }
02245 if ( x > KS_colMax )
02246 {
02247 break;
02248 }
02249 }
02250 else
02251 {
02252 kdDebug(36001) << "Error in Series::mode" << endl;
02253 return;
02254 }
02255
02256 if (type == Linear)
02257 incr = incr + step;
02258 else if (type == Geometric)
02259 {
02260
02261 incr = incr * step;
02262
02263
02264 if (step == 1)
02265 return;
02266 }
02267 else
02268 {
02269 kdDebug(36001) << "Error in Series::type" << endl;
02270 return;
02271 }
02272 }
02273 }
02274
02275
02276
02277 emit sig_updateView( this );
02278 }
02279
02280
02281 struct SetSelectionPercentWorker : public Sheet::CellWorkerTypeA
02282 {
02283 bool b;
02284 SetSelectionPercentWorker( bool _b ) : b( _b ) { }
02285
02286 QString getUndoTitle() { return i18n("Format Percent"); }
02287 bool testCondition( RowFormat* ) {
02288
02289 return ( true );
02290 }
02291 void doWork( RowFormat* rw ) {
02292
02293 rw->setFormatType( b ? Percentage_format : Generic_format);
02294 }
02295 void doWork( ColumnFormat* cl ) {
02296 cl->setFormatType( b ? Percentage_format : Generic_format);
02297 }
02298 void prepareCell( Cell* cell ) {
02299 cell->format()->clearProperty(Format::PFormatType);
02300 cell->format()->clearNoFallBackProperties( Format::PFormatType );
02301 }
02302 bool testCondition( Cell* cell ) {
02303 return ( !cell->isPartOfMerged() );
02304 }
02305 void doWork( Cell* cell, bool cellRegion, int, int ) {
02306 if ( cellRegion )
02307 cell->setDisplayDirtyFlag();
02308 cell->format()->setFormatType( b ? Percentage_format : Generic_format);
02309 if ( cellRegion )
02310 cell->clearDisplayDirtyFlag();
02311 }
02312 };
02313
02314 void Sheet::setSelectionPercent( Selection* selectionInfo, bool b )
02315 {
02316 SetSelectionPercentWorker w( b );
02317 workOnCells( selectionInfo, w );
02318 }
02319
02320 void Sheet::slotAreaModified (const QString &name)
02321 {
02322 d->dependencies->areaModified (name);
02323 }
02324
02325
02326 void Sheet::refreshRemoveAreaName(const QString & _areaName)
02327 {
02328 Cell * c = d->cells.firstCell();
02329 QString tmp = "'" + _areaName + "'";
02330 for( ;c ; c = c->nextCell() )
02331 {
02332 if ( c->isFormula() )
02333 {
02334 if (c->text().find(tmp) != -1)
02335 {
02336 if ( !c->makeFormula() )
02337 kdError(36001) << "ERROR: Syntax ERROR" << endl;
02338 }
02339 }
02340 }
02341 }
02342
02343 void Sheet::refreshChangeAreaName(const QString & _areaName)
02344 {
02345 Cell * c = d->cells.firstCell();
02346 QString tmp = "'" + _areaName + "'";
02347 for( ;c ; c = c->nextCell() )
02348 {
02349 if ( c->isFormula() )
02350 {
02351 if (c->text().find(tmp) != -1)
02352 {
02353 if ( !c->makeFormula() )
02354 kdError(36001) << "ERROR: Syntax ERROR" << endl;
02355 else
02356 {
02357
02358 c->setCalcDirtyFlag();
02359 }
02360 }
02361 }
02362 }
02363 }
02364
02365 void Sheet::changeCellTabName( QString const & old_name, QString const & new_name )
02366 {
02367 Cell* c = d->cells.firstCell();
02368 for( ;c; c = c->nextCell() )
02369 {
02370 if( c->isFormula() )
02371 {
02372 if(c->text().find(old_name)!=-1)
02373 {
02374 int nb = c->text().contains(old_name+"!");
02375 QString tmp=old_name+"!";
02376 int len = tmp.length();
02377 tmp=c->text();
02378
02379 for( int i=0; i<nb; i++ )
02380 {
02381 int pos = tmp.find( old_name+"!" );
02382 tmp.replace( pos, len, new_name+"!" );
02383 }
02384 c->setCellText(tmp);
02385 }
02386 }
02387 }
02388 }
02389
02390 bool Sheet::shiftRow( const QRect &rect,bool makeUndo )
02391 {
02392 UndoInsertCellRow * undo = 0;
02393 if ( !doc()->undoLocked() &&makeUndo)
02394 {
02395 undo = new UndoInsertCellRow( doc(), this, rect );
02396 doc()->addCommand( undo );
02397 }
02398
02399 bool res=true;
02400 bool result;
02401 for( int i=rect.top(); i<=rect.bottom(); i++ )
02402 {
02403 for( int j=0; j<=(rect.right()-rect.left()); j++ )
02404 {
02405 result = d->cells.shiftRow( QPoint(rect.left(),i) );
02406 if( !result )
02407 res=false;
02408 }
02409 }
02410 QPtrListIterator<Sheet> it( workbook()->sheetList() );
02411 for( ; it.current(); ++it )
02412 {
02413 for(int i = rect.top(); i <= rect.bottom(); i++ )
02414 it.current()->changeNameCellRef( QPoint( rect.left(), i ), false,
02415 Sheet::ColumnInsert, name(),
02416 ( rect.right() - rect.left() + 1),
02417 undo);
02418 }
02419 refreshChart(QPoint(rect.left(),rect.top()), false, Sheet::ColumnInsert);
02420 refreshMergedCell();
02421 recalc();
02422 emit sig_updateView( this );
02423
02424 return res;
02425 }
02426
02427 bool Sheet::shiftColumn( const QRect& rect,bool makeUndo )
02428 {
02429 UndoInsertCellCol * undo = 0;
02430 if ( !doc()->undoLocked() &&makeUndo)
02431 {
02432 undo = new UndoInsertCellCol( doc(), this,rect);
02433 doc()->addCommand( undo );
02434 }
02435
02436 bool res=true;
02437 bool result;
02438 for( int i =rect.left(); i<=rect.right(); i++ )
02439 {
02440 for( int j=0; j<=(rect.bottom()-rect.top()); j++ )
02441 {
02442 result = d->cells.shiftColumn( QPoint(i,rect.top()) );
02443 if(!result)
02444 res=false;
02445 }
02446 }
02447
02448 QPtrListIterator<Sheet> it( workbook()->sheetList() );
02449 for( ; it.current(); ++it )
02450 {
02451 for(int i=rect.left();i<=rect.right();i++)
02452 it.current()->changeNameCellRef( QPoint( i, rect.top() ), false,
02453 Sheet::RowInsert, name(),
02454 ( rect.bottom() - rect.top() + 1 ),
02455 undo );
02456 }
02457 refreshChart(QPoint(rect.left(),rect.top()), false, Sheet::RowInsert);
02458 refreshMergedCell();
02459 recalc();
02460 emit sig_updateView( this );
02461
02462 return res;
02463 }
02464
02465 void Sheet::unshiftColumn( const QRect & rect,bool makeUndo )
02466 {
02467 UndoRemoveCellCol * undo = 0;
02468 if ( !doc()->undoLocked() && makeUndo )
02469 {
02470 undo = new UndoRemoveCellCol( doc(), this, rect );
02471 doc()->addCommand( undo );
02472 }
02473
02474 for(int i =rect.top();i<=rect.bottom();i++)
02475 for(int j=rect.left();j<=rect.right();j++)
02476 d->cells.remove(j,i);
02477
02478 for(int i =rect.left();i<=rect.right();i++)
02479 for(int j=0;j<=(rect.bottom()-rect.top());j++)
02480 d->cells.unshiftColumn( QPoint(i,rect.top()) );
02481
02482 QPtrListIterator<Sheet> it( workbook()->sheetList() );
02483 for( ; it.current(); ++it )
02484 for(int i=rect.left();i<=rect.right();i++)
02485 it.current()->changeNameCellRef( QPoint( i, rect.top() ), false,
02486 Sheet::RowRemove, name(),
02487 ( rect.bottom() - rect.top() + 1 ),
02488 undo );
02489
02490 refreshChart( QPoint(rect.left(),rect.top()), false, Sheet::RowRemove );
02491 refreshMergedCell();
02492 recalc();
02493 emit sig_updateView( this );
02494 }
02495
02496 void Sheet::unshiftRow( const QRect & rect,bool makeUndo )
02497 {
02498 UndoRemoveCellRow * undo = 0;
02499 if ( !doc()->undoLocked() && makeUndo )
02500 {
02501 undo = new UndoRemoveCellRow( doc(), this, rect );
02502 doc()->addCommand( undo );
02503 }
02504 for(int i =rect.top();i<=rect.bottom();i++)
02505 for(int j=rect.left();j<=rect.right();j++)
02506 d->cells.remove(j,i);
02507
02508 for(int i =rect.top();i<=rect.bottom();i++)
02509 for(int j=0;j<=(rect.right()-rect.left());j++)
02510 d->cells.unshiftRow( QPoint(rect.left(),i) );
02511
02512 QPtrListIterator<Sheet> it( workbook()->sheetList() );
02513 for( ; it.current(); ++it )
02514 for(int i=rect.top();i<=rect.bottom();i++)
02515 it.current()->changeNameCellRef( QPoint( rect.left(), i ), false,
02516 Sheet::ColumnRemove, name(),
02517 ( rect.right() - rect.left() + 1 ),
02518 undo);
02519
02520 refreshChart(QPoint(rect.left(),rect.top()), false, Sheet::ColumnRemove );
02521 refreshMergedCell();
02522 recalc();
02523 emit sig_updateView( this );
02524 }
02525
02526 bool Sheet::insertColumn( int col, int nbCol, bool makeUndo )
02527 {
02528 UndoInsertColumn * undo = 0;
02529 if ( !doc()->undoLocked() && makeUndo)
02530 {
02531 undo = new UndoInsertColumn( doc(), this, col, nbCol );
02532 doc()->addCommand( undo );
02533 }
02534
02535 bool res=true;
02536 bool result;
02537 for( int i=0; i<=nbCol; i++ )
02538 {
02539
02540 d->sizeMaxX -= columnFormat( KS_colMax )->dblWidth();
02541
02542 result = d->cells.insertColumn( col );
02543 d->columns.insertColumn( col );
02544 if(!result)
02545 res = false;
02546
02547
02548 d->sizeMaxX += columnFormat( col+i )->dblWidth();
02549 }
02550
02551 QPtrListIterator<Sheet> it( workbook()->sheetList() );
02552 for( ; it.current(); ++it )
02553 it.current()->changeNameCellRef( QPoint( col, 1 ), true,
02554 Sheet::ColumnInsert, name(),
02555 nbCol + 1, undo );
02556
02557
02558 d->print->insertColumn( col, nbCol );
02559
02560 refreshChart( QPoint( col, 1 ), true, Sheet::ColumnInsert );
02561 refreshMergedCell();
02562 recalc();
02563 emit sig_updateHBorder( this );
02564 emit sig_updateView( this );
02565
02566 return res;
02567 }
02568
02569 bool Sheet::insertRow( int row, int nbRow, bool makeUndo )
02570 {
02571 UndoInsertRow *undo = 0;
02572 if ( !doc()->undoLocked() && makeUndo)
02573 {
02574 undo = new UndoInsertRow( doc(), this, row, nbRow );
02575 doc()->addCommand( undo );
02576 }
02577
02578 bool res=true;
02579 bool result;
02580 for( int i=0; i<=nbRow; i++ )
02581 {
02582
02583 d->sizeMaxY -= rowFormat( KS_rowMax )->dblHeight();
02584
02585 result = d->cells.insertRow( row );
02586 d->rows.insertRow( row );
02587 if( !result )
02588 res = false;
02589
02590
02591 d->sizeMaxY += rowFormat( row )->dblHeight();
02592 }
02593
02594 QPtrListIterator<Sheet> it( workbook()->sheetList() );
02595 for( ; it.current(); ++it )
02596 it.current()->changeNameCellRef( QPoint( 1, row ), true,
02597 Sheet::RowInsert, name(),
02598 nbRow + 1, undo );
02599
02600
02601 d->print->insertRow( row, nbRow );
02602
02603 refreshChart( QPoint( 1, row ), true, Sheet::RowInsert );
02604 refreshMergedCell();
02605 recalc();
02606 emit sig_updateVBorder( this );
02607 emit sig_updateView( this );
02608
02609 return res;
02610 }
02611
02612 void Sheet::removeColumn( int col, int nbCol, bool makeUndo )
02613 {
02614 UndoRemoveColumn *undo = 0;
02615 if ( !doc()->undoLocked() && makeUndo)
02616 {
02617 undo = new UndoRemoveColumn( doc(), this, col, nbCol );
02618 doc()->addCommand( undo );
02619 }
02620
02621 for ( int i = 0; i <= nbCol; ++i )
02622 {
02623
02624 d->sizeMaxX -= columnFormat( col )->dblWidth();
02625
02626 d->cells.removeColumn( col );
02627 d->columns.removeColumn( col );
02628
02629
02630 d->sizeMaxX += columnFormat( KS_colMax )->dblWidth();
02631 }
02632
02633 QPtrListIterator<Sheet> it( workbook()->sheetList() );
02634 for( ; it.current(); ++it )
02635 it.current()->changeNameCellRef( QPoint( col, 1 ), true,
02636 Sheet::ColumnRemove, name(),
02637 nbCol + 1, undo );
02638
02639
02640 d->print->removeColumn( col, nbCol );
02641
02642 refreshChart( QPoint( col, 1 ), true, Sheet::ColumnRemove );
02643 refreshMergedCell();
02644 recalc();
02645 emit sig_updateHBorder( this );
02646 emit sig_updateView( this );
02647 }
02648
02649 void Sheet::removeRow( int row, int nbRow, bool makeUndo )
02650 {
02651 UndoRemoveRow *undo = 0;
02652 if ( !doc()->undoLocked() && makeUndo )
02653 {
02654 undo = new UndoRemoveRow( doc(), this, row, nbRow );
02655 doc()->addCommand( undo );
02656 }
02657
02658 for( int i=0; i<=nbRow; i++ )
02659 {
02660
02661 d->sizeMaxY -= rowFormat( row )->dblHeight();
02662
02663 d->cells.removeRow( row );
02664 d->rows.removeRow( row );
02665
02666
02667 d->sizeMaxY += rowFormat( KS_rowMax )->dblHeight();
02668 }
02669
02670 QPtrListIterator<Sheet> it( workbook()->sheetList() );
02671 for( ; it.current(); ++it )
02672 it.current()->changeNameCellRef( QPoint( 1, row ), true,
02673 Sheet::RowRemove, name(),
02674 nbRow + 1, undo );
02675
02676
02677 d->print->removeRow( row, nbRow );
02678
02679 refreshChart( QPoint( 1, row ), true, Sheet::RowRemove );
02680 refreshMergedCell();
02681 recalc();
02682 emit sig_updateVBorder( this );
02683 emit sig_updateView( this );
02684 }
02685
02686 void Sheet::hideRow(const Region& region)
02687 {
02688 HideShowManipulator* manipulator = new HideShowManipulator();
02689 manipulator->setSheet(this);
02690 manipulator->setManipulateRows(true);
02691 manipulator->add(region);
02692 manipulator->execute();
02693 }
02694
02695 void Sheet::emitHideRow()
02696 {
02697 emit sig_updateVBorder( this );
02698 emit sig_updateView( this );
02699 }
02700
02701 void Sheet::showRow(const Region& region)
02702 {
02703 HideShowManipulator* manipulator = new HideShowManipulator();
02704 manipulator->setSheet(this);
02705 manipulator->setManipulateRows(true);
02706 manipulator->setReverse(true);
02707 manipulator->add(region);
02708 manipulator->execute();
02709 }
02710
02711
02712 void Sheet::hideColumn(const Region& region)
02713 {
02714 HideShowManipulator* manipulator = new HideShowManipulator();
02715 manipulator->setSheet(this);
02716 manipulator->setManipulateColumns(true);
02717 manipulator->add(region);
02718 manipulator->execute();
02719 }
02720
02721 void Sheet::emitHideColumn()
02722 {
02723 emit sig_updateHBorder( this );
02724 emit sig_updateView( this );
02725 }
02726
02727 void Sheet::showColumn(const Region& region)
02728 {
02729 HideShowManipulator* manipulator = new HideShowManipulator();
02730 manipulator->setSheet(this);
02731 manipulator->setManipulateColumns(true);
02732 manipulator->setReverse(true);
02733 manipulator->add(region);
02734 manipulator->execute();
02735 }
02736
02737
02738 void Sheet::refreshChart(const QPoint & pos, bool fullRowOrColumn, ChangeRef ref)
02739 {
02740 Cell * c = d->cells.firstCell();
02741 for( ;c; c = c->nextCell() )
02742 {
02743 if ( (ref == ColumnInsert || ref == ColumnRemove) && fullRowOrColumn
02744 && c->column() >= (pos.x() - 1))
02745 {
02746 if (c->updateChart())
02747 return;
02748 }
02749 else if ( (ref == ColumnInsert || ref == ColumnRemove )&& !fullRowOrColumn
02750 && c->column() >= (pos.x() - 1) && c->row() == pos.y() )
02751 {
02752 if (c->updateChart())
02753 return;
02754 }
02755 else if ((ref == RowInsert || ref == RowRemove) && fullRowOrColumn
02756 && c->row() >= (pos.y() - 1))
02757 {
02758 if (c->updateChart())
02759 return;
02760 }
02761 else if ( (ref == RowInsert || ref == RowRemove) && !fullRowOrColumn
02762 && c->column() == pos.x() && c->row() >= (pos.y() - 1) )
02763 {
02764 if (c->updateChart())
02765 return;
02766 }
02767 }
02768
02769
02770
02771 if (c == 0L)
02772 {
02773 CellBinding * bind;
02774 for ( bind = firstCellBinding(); bind != 0L; bind = nextCellBinding() )
02775 {
02776 bind->cellChanged( 0 );
02777 }
02778
02779
02780
02781 }
02782
02783 }
02784
02785 void Sheet::refreshMergedCell()
02786 {
02787 Cell* c = d->cells.firstCell();
02788 for( ;c; c = c->nextCell() )
02789 {
02790 if(c->doesMergeCells())
02791 c->mergeCells( c->column(), c->row(), c->extraXCells(), c->extraYCells() );
02792 }
02793 }
02794
02795
02796 void Sheet::changeNameCellRef( const QPoint & pos, bool fullRowOrColumn,
02797 ChangeRef ref, QString tabname, int nbCol,
02798 UndoInsertRemoveAction * undo )
02799 {
02800 bool correctDefaultSheetName = (tabname == name());
02801 Cell* c = d->cells.firstCell();
02802 for( ;c; c = c->nextCell() )
02803 {
02804 if( c->isFormula() )
02805 {
02806 QString origText = c->text();
02807 unsigned int i = 0;
02808 bool error = false;
02809 QString newText;
02810
02811 bool correctSheetName = correctDefaultSheetName;
02812
02813 QChar origCh;
02814 for ( ; i < origText.length(); ++i )
02815 {
02816 origCh = origText[i];
02817 if ( origCh != ':' && origCh != '$' && !origCh.isLetter() )
02818 {
02819 newText += origCh;
02820
02821 correctSheetName = correctDefaultSheetName;
02822 }
02823 else
02824
02825 {
02826
02827 QString str;
02828 bool sheetNameFound = false;
02829 for( ; ( i < origText.length() ) &&
02830 ( ( origText[i].isLetter() || origText[i].isDigit() || origText[i] == '$' ) ||
02831 ( sheetNameFound && origText[i].isSpace() ) )
02832 ; ++i )
02833 {
02834 str += origText[i];
02835 if ( origText[i] == '!' )
02836 sheetNameFound = true;
02837 }
02838
02839 if ( origText[i] == '!' )
02840 {
02841 newText += str + '!';
02842
02843 correctSheetName = ( newText.right( tabname.length()+1 ) == tabname+"!" );
02844 }
02845 else
02846 {
02847
02848 Point point( str );
02849 if ( point.isValid() )
02850 {
02851 int col = point.pos().x();
02852 int row = point.pos().y();
02853 QString newPoint;
02854
02855
02856 if ( point.columnFixed() )
02857 newPoint = '$';
02858
02859 if( ref == ColumnInsert
02860 && correctSheetName
02861 && col + nbCol <= KS_colMax
02862 && col >= pos.x()
02863 && ( fullRowOrColumn || row == pos.y() ) )
02864 {
02865 newPoint += Cell::columnName( col + nbCol );
02866 }
02867 else if( ref == ColumnRemove
02868 && correctSheetName
02869 && col > pos.x()
02870 && ( fullRowOrColumn || row == pos.y() ) )
02871 {
02872 newPoint += Cell::columnName( col - nbCol );
02873 }
02874 else
02875 newPoint += Cell::columnName( col );
02876
02877
02878 if ( point.rowFixed() )
02879 newPoint += '$';
02880
02881 if( ref == RowInsert
02882 && correctSheetName
02883 && row + nbCol <= KS_rowMax
02884 && row >= pos.y()
02885 && ( fullRowOrColumn || col == pos.x() ) )
02886 {
02887 newPoint += QString::number( row + nbCol );
02888 }
02889 else if( ref == RowRemove
02890 && correctSheetName
02891 && row > pos.y()
02892 && ( fullRowOrColumn || col == pos.x() ) )
02893 {
02894 newPoint += QString::number( row - nbCol );
02895 }
02896 else
02897 newPoint += QString::number( row );
02898
02899 if( correctSheetName &&
02900 ( ( ref == ColumnRemove
02901 && col == pos.x()
02902 && ( fullRowOrColumn || row == pos.y() ) ) ||
02903 ( ref == RowRemove
02904 && row == pos.y()
02905 && ( fullRowOrColumn || col == pos.x() ) ) ||
02906 ( ref == ColumnInsert
02907 && col + nbCol > KS_colMax
02908 && col >= pos.x()
02909 && ( fullRowOrColumn || row == pos.y() ) ) ||
02910 ( ref == RowInsert
02911 && row + nbCol > KS_rowMax
02912 && row >= pos.y()
02913 && ( fullRowOrColumn || col == pos.x() ) ) ) )
02914 {
02915 newPoint = "#" + i18n("Dependency") + "!";
02916 error = true;
02917 }
02918
02919 newText += newPoint;
02920 }
02921 else
02922 {
02923 kdDebug(36001) << "Copying (unchanged) : '" << str << "'" << endl;
02924 newText += str;
02925 }
02926
02927 if ( i < origText.length() ) {
02928 newText += origText[i];
02929 if( origText[i] != ':' )
02930 correctSheetName = correctDefaultSheetName;
02931 }
02932 }
02933 }
02934 }
02935
02936 if ( error && undo != 0 )
02937 {
02938 QString formulaText = c->text();
02939 int origCol = c->column();
02940 int origRow = c->row();
02941
02942 if ( ref == ColumnInsert && origCol >= pos.x() )
02943 origCol -= nbCol;
02944 if ( ref == RowInsert && origRow >= pos.y() )
02945 origRow -= nbCol;
02946
02947 if ( ref == ColumnRemove && origCol >= pos.x() )
02948 origCol += nbCol;
02949 if ( ref == RowRemove && origRow >= pos.y() )
02950 origRow += nbCol;
02951
02952 undo->saveFormulaReference( this, origCol, origRow, formulaText );
02953 }
02954
02955 c->setCellText( newText );
02956 }
02957 }
02958 }
02959
02960 #if 0
02961 void Sheet::replace( const QString &_find, const QString &_replace, long options,
02962 Canvas *canvas )
02963 {
02964 Selection* selectionInfo = canvas->view()->selectionInfo();
02965
02966
02967 QRect region( selectionInfo->selection() );
02968 QPoint marker( selectionInfo->marker() );
02969
02970 if (options & KReplaceDialog::SelectedText)
02971 {
02972
02973
02974 if ( util_isRowSelected(region) )
02975 {
02976 }
02977
02978 else if ( util_isColumnSelected(region) )
02979 {
02980 }
02981 }
02982 else
02983 {
02984
02985 region.setCoords( 1, 1, d->maxRow, d->maxColumn );
02986 }
02987
02988
02989
02990 KReplace dialog( _find, _replace, options );
02991 QObject::connect(
02992 &dialog, SIGNAL( highlight( const QString &, int, int, const QRect & ) ),
02993 canvas, SLOT( highlight( const QString &, int, int, const QRect & ) ) );
02994 QObject::connect(
02995 &dialog, SIGNAL( replace( const QString &, int, int,int, const QRect & ) ),
02996 canvas, SLOT( replace( const QString &, int, int,int, const QRect & ) ) );
02997
02998
02999 if ( !doc()->undoLocked() )
03000 {
03001 UndoChangeAreaTextCell *undo = new UndoChangeAreaTextCell( doc(), this, region );
03002 doc()->addCommand( undo );
03003 }
03004
03005 QRect cellRegion( 0, 0, 0, 0 );
03006 bool bck = options & KFindDialog::FindBackwards;
03007
03008 int colStart = !bck ? region.left() : region.right();
03009 int colEnd = !bck ? region.right() : region.left();
03010 int rowStart = !bck ? region.top() :region.bottom();
03011 int rowEnd = !bck ? region.bottom() : region.top();
03012 if ( options & KFindDialog::FromCursor ) {
03013 colStart = marker.x();
03014 rowStart = marker.y();
03015 }
03016 Cell *cell;
03017 for (int row = rowStart ; !bck ? row < rowEnd : row > rowEnd ; !bck ? ++row : --row )
03018 {
03019 for(int col = colStart ; !bck ? col < colEnd : col > colEnd ; !bck ? ++col : --col )
03020 {
03021 cell = cellAt( col, row );
03022 if ( !cell->isDefault() && !cell->isObscured() && !cell->isFormula() )
03023 {
03024 QString text = cell->text();
03025 cellRegion.setTop( row );
03026 cellRegion.setLeft( col );
03027 if (!dialog.replace( text, cellRegion ))
03028 return;
03029 }
03030 }
03031 }
03032 }
03033 #endif
03034
03035 void Sheet::borderBottom( Selection* selectionInfo, const QColor &_color )
03036 {
03037 BorderManipulator* manipulator = new BorderManipulator();
03038 manipulator->setSheet(this);
03039 manipulator->setBottomBorderPen(QPen(_color, 1, Qt::SolidLine));
03040 manipulator->add(*selectionInfo);
03041 manipulator->execute();
03042 }
03043
03044 void Sheet::borderRight( Selection* selectionInfo, const QColor &_color )
03045 {
03046 BorderManipulator* manipulator = new BorderManipulator();
03047 manipulator->setSheet(this);
03048 manipulator->setRightBorderPen(QPen(_color, 1, Qt::SolidLine));
03049 manipulator->add(*selectionInfo);
03050 manipulator->execute();
03051 }
03052
03053 void Sheet::borderLeft( Selection* selectionInfo, const QColor &_color )
03054 {
03055 BorderManipulator* manipulator = new BorderManipulator();
03056 manipulator->setSheet(this);
03057 manipulator->setLeftBorderPen(QPen(_color, 1, Qt::SolidLine));
03058 manipulator->add(*selectionInfo);
03059 manipulator->execute();
03060 }
03061
03062 void Sheet::borderTop( Selection* selectionInfo, const QColor &_color )
03063 {
03064 BorderManipulator* manipulator = new BorderManipulator();
03065 manipulator->setSheet(this);
03066 manipulator->setTopBorderPen(QPen(_color, 1, Qt::SolidLine));
03067 manipulator->add(*selectionInfo);
03068 manipulator->execute();
03069 }
03070
03071 void Sheet::borderOutline( Selection* selectionInfo, const QColor &_color )
03072 {
03073 BorderManipulator* manipulator = new BorderManipulator();
03074 manipulator->setSheet(this);
03075 manipulator->setTopBorderPen(QPen(_color, 1, Qt::SolidLine));
03076 manipulator->setBottomBorderPen(QPen(_color, 1, Qt::SolidLine));
03077 manipulator->setLeftBorderPen(QPen(_color, 1, Qt::SolidLine));
03078 manipulator->setRightBorderPen(QPen(_color, 1, Qt::SolidLine));
03079 manipulator->add(*selectionInfo);
03080 manipulator->execute();
03081 }
03082
03083 void Sheet::borderAll( Selection * selectionInfo,
03084 const QColor & _color )
03085 {
03086 BorderManipulator* manipulator = new BorderManipulator();
03087 manipulator->setSheet(this);
03088 manipulator->setTopBorderPen(QPen(_color, 1, Qt::SolidLine));
03089 manipulator->setBottomBorderPen(QPen(_color, 1, Qt::SolidLine));
03090 manipulator->setLeftBorderPen(QPen(_color, 1, Qt::SolidLine));
03091 manipulator->setRightBorderPen(QPen(_color, 1, Qt::SolidLine));
03092 manipulator->setHorizontalPen(QPen(_color, 1, Qt::SolidLine));
03093 manipulator->setVerticalPen(QPen(_color, 1, Qt::SolidLine));
03094 manipulator->add(*selectionInfo);
03095 manipulator->execute();
03096 }
03097
03098 void Sheet::borderRemove( Selection* selectionInfo )
03099 {
03100 BorderManipulator* manipulator = new BorderManipulator();
03101 manipulator->setSheet(this);
03102 manipulator->setTopBorderPen(QPen(Qt::NoPen));
03103 manipulator->setBottomBorderPen(QPen(Qt::NoPen));
03104 manipulator->setLeftBorderPen(QPen(Qt::NoPen));
03105 manipulator->setRightBorderPen(QPen(Qt::NoPen));
03106 manipulator->setHorizontalPen(QPen(Qt::NoPen));
03107 manipulator->setVerticalPen(QPen(Qt::NoPen));
03108 manipulator->add(*selectionInfo);
03109 manipulator->execute();
03110 }
03111
03112
03113 void Sheet::sortByRow( const QRect &area, int ref_row, SortingOrder mode )
03114 {
03115 Point point;
03116 point.setSheet(this);
03117 point.setSheetName (d->name);
03118 point.setPos(area.topLeft());
03119 point.setColumnFixed(false);
03120 point.setRowFixed(false);
03121
03122 sortByRow( area, ref_row, 0, 0, mode, mode, mode, 0, false, false, point,true );
03123 }
03124
03125 void Sheet::sortByColumn( const QRect &area, int ref_column, SortingOrder mode )
03126 {
03127 Point point;
03128 point.setSheet(this);
03129 point.setSheetName(d->name);
03130 point.setPos(area.topLeft());
03131 point.setColumnFixed(false);
03132 point.setRowFixed(false);
03133
03134 sortByColumn( area, ref_column, 0, 0, mode, mode, mode, 0, false, false,
03135 point,true );
03136 }
03137
03138 void Sheet::checkCellContent(Cell * cell1, Cell * cell2, int & ret)
03139 {
03140 if ( cell1->isEmpty() )
03141 {
03142 ret = 1;
03143 return;
03144 }
03145 else if ( cell1->isObscured() && cell1->isPartOfMerged() )
03146 {
03147 ret = 1;
03148 return;
03149 }
03150 else if ( cell2->isEmpty() )
03151 {
03152 ret = 2;
03153 return;
03154 }
03155 ret = 0;
03156 }
03157
03158 void Sheet::sortByRow( const QRect &area, int key1, int key2, int key3,
03159 SortingOrder order1, SortingOrder order2,
03160 SortingOrder order3,
03161 QStringList const * firstKey, bool copyFormat,
03162 bool headerRow, Point const & outputPoint, bool respectCase )
03163 {
03164 QRect r( area );
03165 Map::respectCase = respectCase;
03166 Q_ASSERT( order1 == Increase || order1 == Decrease );
03167
03168
03169 Q_ASSERT( util_isColumnSelected(r) == false );
03170
03171
03172 if ( util_isRowSelected(r) )
03173 {
03174 r.setLeft( KS_colMax );
03175 r.setRight( 0 );
03176
03177
03178
03179
03180 for ( int row = r.top(); row <= r.bottom(); ++row )
03181 {
03182 Cell * c = getFirstCellRow( row );
03183 int col;
03184 while ( c )
03185 {
03186 col = c->column();
03187 if ( !c->isEmpty() )
03188 {
03189 if ( col > r.right() )
03190 r.rRight() = col;
03191 if ( col < r.left() )
03192 r.rLeft() = col;
03193 }
03194 c = getNextCellRight( col, row );
03195 }
03196 }
03197
03198
03199 if ( r.right() < r.left() )
03200 {
03201 Map::respectCase = true;
03202 return;
03203 }
03204 }
03205
03206 QRect target( outputPoint.pos().x(), outputPoint.pos().y(), r.width(), r.height() );
03207
03208 doc()->emitBeginOperation();
03209
03210 if ( !doc()->undoLocked() )
03211 {
03212 UndoSort *undo = new UndoSort( doc(), this, target );
03213 doc()->addCommand( undo );
03214 }
03215
03216 if (target.topLeft() != r.topLeft())
03217 {
03218 int targetLeft = target.left();
03219 int targetTop = target.top();
03220 int sourceTop = r.top();
03221 int sourceLeft = r.left();
03222
03223 key1 = key1 - sourceTop + targetTop;
03224 key2 = key2 - sourceTop + targetTop;
03225 key3 = key3 - sourceTop + targetTop;
03226
03227 for ( int x = 0; x < r.width(); ++x)
03228 {
03229 for ( int y = 0; y < r.height(); ++y )
03230 {
03231
03232 copyCells( sourceLeft + x, sourceTop + y,
03233 targetLeft + x, targetTop + y, copyFormat );
03234 }
03235 }
03236 }
03237
03238
03239
03240
03241 Cell * cell;
03242 Cell * cell1;
03243 Cell * cell2;
03244 Cell * bestCell;
03245 int status = 0;
03246
03247 for ( int d = target.left(); d <= target.right(); ++d )
03248 {
03249 cell1 = cellAt( d, key1 );
03250 if ( cell1->isObscured() && cell1->isPartOfMerged() )
03251 {
03252 Cell* obscuring = cell1->obscuringCells().first();
03253 cell = cellAt( obscuring->column(), key1 );
03254 cell1 = cellAt( obscuring->column() + cell->extraXCells() + 1,
03255 obscuring->column());
03256 d = obscuring->column() + cell->extraXCells() + 1;
03257 }
03258
03259
03260 bestCell = cell1;
03261 int bestX = d;
03262 for ( int x = d + 1 ; x <= target.right(); x++ )
03263 {
03264 cell2 = cellAt( x, key1 );
03265
03266 checkCellContent(cell2, bestCell, status);
03267 if (status == 1)
03268 continue;
03269 else if (status == 2)
03270 {
03271
03272 bestCell = cell2;
03273 bestX = x;
03274 continue;
03275 }
03276
03277 if ( firstKey )
03278 {
03279 int i1 = firstKey->findIndex( cell2->text() );
03280 int i2 = firstKey->findIndex( bestCell->text() );
03281
03282 if ( i1 != -1 && i2 != -1 )
03283 {
03284 if ( (order1 == Increase && i1 < i2 )
03285 || (order1 == Decrease && i1 > i2) )
03286 {
03287 bestCell = cell2;
03288 bestX = x;
03289 continue;
03290 }
03291
03292 if ( i1 == i2 )
03293 {
03294
03295 if (key2 <= 0)
03296 continue;
03297
03298 Cell * cell22 = cellAt( x, key2 );
03299 Cell * bestCell2 = cellAt( bestX, key2 );
03300
03301 if ( cell22->isEmpty() )
03302 {
03303
03304 continue;
03305 }
03306 else if ( cell22->isObscured() && cell22->isPartOfMerged() )
03307 {
03308
03309 continue;
03310 }
03311 else if ( bestCell2->isEmpty() )
03312 {
03313
03314 bestCell = cell2;
03315 bestX = x;
03316 continue;
03317 }
03318
03319 if ( (order2 == Increase && *cell22 < *bestCell2)
03320 || (order2 == Decrease && *cell22 > *bestCell2) )
03321 {
03322 bestCell = cell2;
03323 bestX = x;
03324 continue;
03325 }
03326 else if ( (order2 == Increase && *cell22 > *bestCell2)
03327 || (order2 == Decrease && *cell22 < *bestCell2) )
03328 {
03329
03330 continue;
03331 }
03332 else
03333 {
03334
03335 if (key3 <= 0)
03336 continue;
03337
03338 Cell * cell23 = cellAt( x, key3 );
03339 Cell * bestCell3 = cellAt( bestX, key3 );
03340
03341 if ( cell23->isEmpty() )
03342 {
03343
03344 continue;
03345 }
03346 else if ( cell23->isObscured() && cell23->isPartOfMerged() )
03347 {
03348
03349 continue;
03350 }
03351 else if ( bestCell3->isEmpty() )
03352 {
03353
03354 bestCell = cell2;
03355 bestX = x;
03356 continue;
03357 }
03358 if ( (order3 == Increase && *cell23 < *bestCell3)
03359 || (order3 == Decrease && *cell23 > *bestCell3) )
03360 {
03361
03362
03363 continue;
03364 }
03365 else
03366 {
03367 bestCell = cell2;
03368 bestX = x;
03369 continue;
03370 }
03371 }
03372 }
03373 continue;
03374 }
03375 else if ( i1 != -1 && i2 == -1 )
03376 {
03377
03378 bestCell = cell2;
03379 bestX = x;
03380 continue;
03381 }
03382 else if ( i2 != -1 && i1 == -1 )
03383 {
03384
03385
03386 continue;
03387 }
03388
03389
03390 }
03391
03392
03393 if ( (order1 == Increase && *cell2 < *bestCell)
03394 || (order1 == Decrease && *cell2 > *bestCell) )
03395 {
03396 bestCell = cell2;
03397 bestX = x;
03398 continue;
03399 }
03400 else if ( (order1 == Increase && *cell2 > *bestCell)
03401 || (order1 == Decrease && *cell2 < *bestCell) )
03402 {
03403
03404 continue;
03405 }
03406 else
03407 {
03408
03409
03410 if (key2 <= 0)
03411 continue;
03412 Cell * cell22 = cellAt( d, key2 );
03413 Cell * bestCell2 = cellAt( x, key2 );
03414
03415 checkCellContent(cell2, bestCell, status);
03416 if (status == 1)
03417 continue;
03418 else if (status == 2)
03419 {
03420
03421 bestCell = cell2;
03422 bestX = x;
03423 continue;
03424 }
03425
03426 if ( (order2 == Increase && *cell22 > *bestCell2)
03427 || (order2 == Decrease && *cell22 < *bestCell2) )
03428 {
03429 bestCell = cell2;
03430 bestX = x;
03431 continue;
03432 }
03433 else
03434 if ( (order2 == Increase && *cell22 > *bestCell2)
03435 || (order2 == Decrease && *cell22 < *bestCell2) )
03436 {
03437
03438 continue;
03439 }
03440 else
03441 {
03442
03443 if (key3 == 0)
03444 continue;
03445 Cell * cell23 = cellAt( d, key3 );
03446 Cell * bestCell3 = cellAt( x, key3 );
03447
03448 checkCellContent(cell2, bestCell, status);
03449 if (status == 1)
03450 continue;
03451 else if (status == 2)
03452 {
03453
03454 bestCell = cell2;
03455 bestX = x;
03456 continue;
03457 }
03458 if ( (order3 == Increase && *cell23 > *bestCell3)
03459 || (order3 == Decrease && *cell23 < *bestCell3) )
03460 {
03461 bestCell = cell2;
03462 bestX = x;
03463 continue;
03464 }
03465 else
03466 {
03467
03468
03469 continue;
03470 }
03471 }
03472 }
03473 }
03474
03475
03476 if ( d != bestX )
03477 {
03478 int top = target.top();
03479 if (headerRow)
03480 ++top;
03481
03482 for( int y = target.bottom(); y >= top; --y )
03483 {
03484 if ( y != key1 && y != key2 && y != key3 )
03485 swapCells( d, y, bestX, y, copyFormat );
03486 }
03487 if (key3 > 0)
03488 swapCells( d, key3, bestX, key3, copyFormat );
03489 if (key2 > 0)
03490 swapCells( d, key2, bestX, key2, copyFormat );
03491 swapCells( d, key1, bestX, key1, copyFormat );
03492 }
03493 }
03494 Map::respectCase = true;
03495
03496 emit sig_updateView( this );
03497 }
03498
03499 void Sheet::sortByColumn( const QRect &area, int key1, int key2, int key3,
03500 SortingOrder order1, SortingOrder order2,
03501 SortingOrder order3,
03502 QStringList const * firstKey, bool copyFormat,
03503 bool headerRow,
03504 Point const & outputPoint, bool respectCase )
03505 {
03506 QRect r( area );
03507 Map::respectCase = respectCase;
03508
03509 Q_ASSERT( order1 == Increase || order1 == Decrease );
03510
03511
03512 Q_ASSERT( util_isRowSelected(r) == false );
03513
03514
03515 if ( util_isColumnSelected(r) )
03516 {
03517 r.setTop( KS_rowMax );
03518 r.setBottom( 0 );
03519
03520
03521
03522
03523 for ( int col = r.left(); col <= r.right(); ++col )
03524 {
03525 Cell * c = getFirstCellColumn( col );
03526 int row;
03527 while ( c )
03528 {
03529 row = c->row();
03530 if ( !c->isEmpty() )
03531 {
03532 if ( row > r.bottom() )
03533 r.rBottom() = row;
03534 if ( row < r.top() )
03535 r.rTop() = row;
03536 }
03537 c = getNextCellDown( col, row );
03538 }
03539 }
03540
03541
03542 if ( r.bottom() < r.top() )
03543 {
03544 Map::respectCase = true;
03545 return;
03546 }
03547 }
03548 QRect target( outputPoint.pos().x(), outputPoint.pos().y(), r.width(), r.height() );
03549
03550 if ( !doc()->undoLocked() )
03551 {
03552 UndoSort *undo = new UndoSort( doc(), this, target );
03553 doc()->addCommand( undo );
03554 }
03555
03556 doc()->emitBeginOperation();
03557
03558 if (target.topLeft() != r.topLeft())
03559 {
03560 int targetLeft = target.left();
03561 int targetTop = target.top();
03562 int sourceTop = r.top();
03563 int sourceLeft = r.left();
03564
03565 key1 = key1 - sourceLeft + targetLeft;
03566 key2 = key2 - sourceLeft + targetLeft;
03567 key3 = key3 - sourceLeft + targetLeft;
03568
03569 for ( int x = 0; x < r.width(); ++x)
03570 {
03571 for ( int y = 0; y < r.height(); ++y )
03572 {
03573
03574 copyCells( sourceLeft + x, sourceTop + y,
03575 targetLeft + x, targetTop + y, copyFormat );
03576 }
03577 }
03578 }
03579
03580
03581
03582
03583
03584
03585 Cell * cell;
03586 Cell * cell1;
03587 Cell * cell2;
03588 Cell * bestCell;
03589 int status = 0;
03590
03591 int d = target.top();
03592
03593 if (headerRow)
03594 ++d;
03595
03596 for ( ; d <= target.bottom(); ++d )
03597 {
03598
03599 cell1 = cellAt( key1, d );
03600 if ( cell1->isObscured() && cell1->isPartOfMerged() )
03601 {
03602 Cell* obscuring = cell1->obscuringCells().first();
03603 cell = cellAt( key1, obscuring->row() );
03604 cell1 = cellAt( key1, obscuring->row() + cell->extraYCells() + 1 );
03605 d = obscuring->row() + cell->extraYCells() + 1;
03606 }
03607
03608 bestCell = cell1;
03609 int bestY = d;
03610
03611 for ( int y = d + 1 ; y <= target.bottom(); ++y )
03612 {
03613 cell2 = cellAt( key1, y );
03614
03615 if ( cell2->isEmpty() )
03616 {
03617
03618 continue;
03619 }
03620 else if ( cell2->isObscured() && cell2->isPartOfMerged() )
03621 {
03622
03623 continue;
03624 }
03625 else if ( bestCell->isEmpty() )
03626 {
03627
03628 bestCell = cell2;
03629 bestY = y;
03630 continue;
03631 }
03632
03633 if ( firstKey )
03634 {
03635 int i1 = firstKey->findIndex( cell2->text() );
03636 int i2 = firstKey->findIndex( bestCell->text() );
03637
03638 if ( i1 != -1 && i2 != -1 )
03639 {
03640 if ( (order1 == Increase && i1 < i2 )
03641 || (order1 == Decrease && i1 > i2) )
03642 {
03643 bestCell = cell2;
03644 bestY = y;
03645 continue;
03646 }
03647
03648 if ( i1 == i2 )
03649 {
03650
03651 if (key2 <= 0)
03652 continue;
03653 Cell * cell22 = cellAt( key2, d );
03654 Cell * bestCell2 = cellAt( key2, y );
03655
03656 if ( cell22->isEmpty() )
03657 {
03658
03659 continue;
03660 }
03661 else if ( cell22->isObscured() && cell22->isPartOfMerged() )
03662 {
03663
03664 continue;
03665 }
03666 else if ( bestCell2->isEmpty() )
03667 {
03668
03669 bestCell = cell2;
03670 bestY = y;
03671 continue;
03672 }
03673
03674 if ( (order2 == Increase && *cell22 > *bestCell2)
03675 || (order2 == Decrease && *cell22 < *bestCell2) )
03676 {
03677 bestCell = cell2;
03678 bestY = y;
03679 continue;
03680 }
03681 else if ( (order2 == Increase && *cell22 < *bestCell2)
03682 || (order2 == Decrease && *cell22 > *bestCell2) )
03683 {
03684
03685 continue;
03686 }
03687 else
03688 {
03689
03690 if (key3 <= 0)
03691 continue;
03692 Cell * cell23 = cellAt( key3, d );
03693 Cell * bestCell3 = cellAt( key3, y );
03694
03695 checkCellContent(cell2, bestCell, status);
03696 if (status == 1)
03697 continue;
03698 else if (status == 2)
03699 {
03700
03701 bestCell = cell2;
03702 bestY = y;
03703 continue;
03704 }
03705
03706 if ( (order3 == Increase && *cell23 < *bestCell3)
03707 || (order3 == Decrease && *cell23 > *bestCell3) )
03708 {
03709 bestCell = cell2;
03710 bestY = y;
03711 continue;
03712 }
03713 else
03714 {
03715
03716
03717 continue;
03718 }
03719 }
03720 }
03721 continue;
03722 }
03723 else if ( i1 != -1 && i2 == -1 )
03724 {
03725
03726 bestCell = cell2;
03727 bestY = y;
03728 continue;
03729 }
03730 else if ( i2 != -1 && i1 == -1 )
03731 {
03732
03733
03734 continue;
03735 }
03736
03737
03738 }
03739
03740
03741
03742 if ( (order1 == Increase && *cell2 < *bestCell)
03743 || (order1 == Decrease && *cell2 > *bestCell) )
03744 {
03745 bestCell = cell2;
03746 bestY = y;
03747 }
03748 else if ( (order1 == Increase && *cell2 > *bestCell)
03749 || (order1 == Decrease && *cell2 < *bestCell) )
03750 {
03751
03752 continue;
03753 }
03754 else
03755 {
03756
03757
03758 if (key2 == 0)
03759 continue;
03760 Cell * cell22 = cellAt( key2, y );
03761 Cell * bestCell2 = cellAt( key2, bestY );
03762
03763 if ( cell22->isEmpty() )
03764 {
03765
03766 continue;
03767 }
03768 else if ( cell22->isObscured() && cell22->isPartOfMerged() )
03769 {
03770
03771 continue;
03772 }
03773 else if ( bestCell2->isEmpty() )
03774 {
03775
03776 bestCell = cell2;
03777 bestY = y;
03778 continue;
03779 }
03780
03781 if ( (order2 == Increase && *cell22 < *bestCell2)
03782 || (order2 == Decrease && *cell22 > *bestCell2) )
03783 {
03784 bestCell = cell2;
03785 bestY = y;
03786 continue;
03787 }
03788 else if ( (order2 == Increase && *cell22 > *bestCell2)
03789 || (order2 == Decrease && *cell22 < *bestCell2) )
03790 {
03791 continue;
03792 }
03793 else
03794 {
03795
03796 if (key3 == 0)
03797 continue;
03798 Cell * cell23 = cellAt( key3, y );
03799 Cell * bestCell3 = cellAt( key3, bestY );
03800
03801 if ( cell23->isEmpty() )
03802 {
03803
03804 continue;
03805 }
03806 else if ( cell23->isObscured() && cell23->isPartOfMerged() )
03807 {
03808
03809 continue;
03810 }
03811 else if ( bestCell3->isEmpty() )
03812 {
03813
03814 bestCell = cell2;
03815 bestY = y;
03816 continue;
03817 }
03818
03819 if ( (order3 == Increase && *cell23 < *bestCell3)
03820 || (order3 == Decrease && *cell23 > *bestCell3) )
03821 {
03822 bestCell = cell2;
03823 bestY = y;
03824 continue;
03825 }
03826 else
03827 {
03828
03829
03830 continue;
03831 }
03832 }
03833 }
03834 }
03835
03836
03837 if ( d != bestY )
03838 {
03839 for (int x = target.left(); x <= target.right(); ++x)
03840 {
03841 if ( x != key1 && x != key2 && x != key3)
03842 swapCells( x, d, x, bestY, copyFormat );
03843 }
03844 if (key3 > 0)
03845 swapCells( key3, d, key3, bestY, copyFormat );
03846 if (key2 > 0)
03847 swapCells( key2, d, key2, bestY, copyFormat );
03848 swapCells( key1, d, key1, bestY, copyFormat );
03849 }
03850 }
03851
03852 Map::respectCase = true;
03853 emit sig_updateView( this );
03854 }
03855
03856
03857 void Sheet::copyCells( int x1, int y1, int x2, int y2, bool cpFormat )
03858 {
03859 Cell * sourceCell = cellAt( x1, y1 );
03860 Cell * targetCell = cellAt( x2, y2 );
03861
03862 if ( sourceCell->isDefault() && targetCell->isDefault())
03863 {
03864
03865 return;
03866 }
03867
03868 targetCell = nonDefaultCell(x2, y2);
03869
03870
03871 targetCell->copyContent( sourceCell );
03872
03873
03874
03875
03876
03877
03878
03879
03880
03881
03882
03883
03884
03885
03886 if (cpFormat)
03887 {
03888 targetCell->copyFormat( sourceCell );
03889
03890
03891
03892
03893
03894
03895
03896
03897
03898
03899
03900
03901
03902
03903
03904
03905
03906
03907
03908
03909
03910
03911
03912
03913
03914
03915
03916
03917 }
03918 }
03919
03920 void Sheet::swapCells( int x1, int y1, int x2, int y2, bool cpFormat )
03921 {
03922 Cell * ref1 = cellAt( x1, y1 );
03923 Cell * ref2 = cellAt( x2, y2 );
03924
03925 if ( ref1->isDefault() )
03926 {
03927 if ( !ref2->isDefault() )
03928 {
03929 ref1 = nonDefaultCell( x1, y1 );
03930
03931 }
03932 else
03933 return;
03934 }
03935 else
03936 if ( ref2->isDefault() )
03937 {
03938 ref2 = nonDefaultCell( x2, y2 );
03939
03940 }
03941
03942
03943
03944
03945
03946
03947 if (!ref1->isFormula() && !ref2->isFormula())
03948 {
03949 Cell *tmp = new Cell( this, -1, -1 );
03950
03951 tmp->copyContent( ref1 );
03952 ref1->copyContent( ref2 );
03953 ref2->copyContent( tmp );
03954
03955 delete tmp;
03956 }
03957 else
03958 if ( ref1->isFormula() && ref2->isFormula() )
03959 {
03960 QString d = ref1->encodeFormula();
03961 ref1->setCellText( ref1->decodeFormula( ref2->encodeFormula( ) ) );
03962 ref1->setCalcDirtyFlag();
03963 ref1->calc(false);
03964 ref2->setCellText( ref2->decodeFormula( d ) );
03965 ref2->setCalcDirtyFlag();
03966 ref2->calc(false);
03967 }
03968 else
03969 if (ref1->isFormula() && !ref2->isFormula() )
03970 {
03971 QString d = ref1->encodeFormula();
03972 ref1->setCellText(ref2->text());
03973 ref2->setCellText(ref2->decodeFormula(d));
03974 ref2->setCalcDirtyFlag();
03975 ref2->calc(false);
03976 }
03977 else
03978 if (!ref1->isFormula() && ref2->isFormula() )
03979 {
03980 QString d = ref2->encodeFormula();
03981 ref2->setCellText(ref1->text());
03982 ref1->setCellText(ref1->decodeFormula(d));
03983 ref1->setCalcDirtyFlag();
03984 ref1->calc(false);
03985 }
03986
03987 if (cpFormat)
03988 {
03989 Format::Align a = ref1->format()->align( ref1->column(), ref1->row() );
03990 ref1->format()->setAlign( ref2->format()->align( ref2->column(), ref2->row() ) );
03991 ref2->format()->setAlign(a);
03992
03993 Format::AlignY ay = ref1->format()->alignY( ref1->column(), ref1->row() );
03994 ref1->format()->setAlignY( ref2->format()->alignY( ref2->column(), ref2->row() ) );
03995 ref2->format()->setAlignY(ay);
03996
03997 QFont textFont = ref1->format()->textFont( ref1->column(), ref1->row() );
03998 ref1->format()->setTextFont( ref2->format()->textFont( ref2->column(), ref2->row() ) );
03999 ref2->format()->setTextFont(textFont);
04000
04001 QColor textColor = ref1->format()->textColor( ref1->column(), ref1->row() );
04002 ref1->format()->setTextColor( ref2->format()->textColor( ref2->column(), ref2->row() ) );
04003 ref2->format()->setTextColor(textColor);
04004
04005 QColor bgColor = ref1->bgColor( ref1->column(), ref1->row() );
04006 ref1->format()->setBgColor( ref2->bgColor( ref2->column(), ref2->row() ) );
04007 ref2->format()->setBgColor(bgColor);
04008
04009 QPen lbp = ref1->leftBorderPen( ref1->column(), ref1->row() );
04010 ref1->setLeftBorderPen( ref2->leftBorderPen( ref2->column(), ref2->row() ) );
04011 ref2->setLeftBorderPen(lbp);
04012
04013 QPen tbp = ref1->topBorderPen( ref1->column(), ref1->row() );
04014 ref1->setTopBorderPen( ref2->topBorderPen( ref2->column(), ref2->row() ) );
04015 ref2->setTopBorderPen(tbp);
04016
04017 QPen bbp = ref1->bottomBorderPen( ref1->column(), ref1->row() );
04018 ref1->setBottomBorderPen( ref2->bottomBorderPen( ref2->column(), ref2->row() ) );
04019 ref2->setBottomBorderPen(bbp);
04020
04021 QPen rbp = ref1->rightBorderPen( ref1->column(), ref1->row() );
04022 ref1->setRightBorderPen( ref2->rightBorderPen( ref2->column(), ref2->row() ) );
04023 ref2->setRightBorderPen(rbp);
04024
04025 QPen fdp = ref1->format()->fallDiagonalPen( ref1->column(), ref1->row() );
04026 ref1->format()->setFallDiagonalPen( ref2->format()->fallDiagonalPen( ref2->column(), ref2->row() ) );
04027 ref2->format()->setFallDiagonalPen(fdp);
04028
04029 QPen udp = ref1->format()->goUpDiagonalPen( ref1->column(), ref1->row() );
04030 ref1->format()->setGoUpDiagonalPen( ref2->format()->goUpDiagonalPen( ref2->column(), ref2->row() ) );
04031 ref2->format()->setGoUpDiagonalPen(udp);
04032
04033 QBrush bgBrush = ref1->backGroundBrush( ref1->column(), ref1->row() );
04034 ref1->format()->setBackGroundBrush( ref2->backGroundBrush( ref2->column(), ref2->row() ) );
04035 ref2->format()->setBackGroundBrush(bgBrush);
04036
04037 int pre = ref1->format()->precision( ref1->column(), ref1->row() );
04038 ref1->format()->setPrecision( ref2->format()->precision( ref2->column(), ref2->row() ) );
04039 ref2->format()->setPrecision(pre);
04040
04041 QString prefix = ref1->format()->prefix( ref1->column(), ref1->row() );
04042 ref1->format()->setPrefix( ref2->format()->prefix( ref2->column(), ref2->row() ) );
04043 ref2->format()->setPrefix(prefix);
04044
04045 QString postfix = ref1->format()->postfix( ref1->column(), ref1->row() );
04046 ref1->format()->setPostfix( ref2->format()->postfix( ref2->column(), ref2->row() ) );
04047 ref2->format()->setPostfix(postfix);
04048
04049 Format::FloatFormat f = ref1->format()->floatFormat( ref1->column(), ref1->row() );
04050 ref1->format()->setFloatFormat( ref2->format()->floatFormat( ref2->column(), ref2->row() ) );
04051 ref2->format()->setFloatFormat(f);
04052
04053 Format::FloatColor c = ref1->format()->floatColor( ref1->column(), ref1->row() );
04054 ref1->format()->setFloatColor( ref2->format()->floatColor( ref2->column(), ref2->row() ) );
04055 ref2->format()->setFloatColor(c);
04056
04057 bool multi = ref1->format()->multiRow( ref1->column(), ref1->row() );
04058 ref1->format()->setMultiRow( ref2->format()->multiRow( ref2->column(), ref2->row() ) );
04059 ref2->format()->setMultiRow(multi);
04060
04061 bool vert = ref1->format()->verticalText( ref1->column(), ref1->row() );
04062 ref1->format()->setVerticalText( ref2->format()->verticalText( ref2->column(), ref2->row() ) );
04063 ref2->format()->setVerticalText(vert);
04064
04065 bool print = ref1->format()->getDontprintText( ref1->column(), ref1->row() );
04066 ref1->format()->setDontPrintText( ref2->format()->getDontprintText( ref2->column(), ref2->row() ) );
04067 ref2->format()->setDontPrintText(print);
04068
04069 double ind = ref1->format()->getIndent( ref1->column(), ref1->row() );
04070 ref1->format()->setIndent( ref2->format()->getIndent( ref2->column(), ref2->row() ) );
04071 ref2->format()->setIndent( ind );
04072
04073 QValueList<Conditional> conditionList = ref1->conditionList();
04074 ref1->setConditionList(ref2->conditionList());
04075 ref2->setConditionList(conditionList);
04076
04077 QString com = ref1->format()->comment( ref1->column(), ref1->row() );
04078 ref1->format()->setComment( ref2->format()->comment( ref2->column(), ref2->row() ) );
04079 ref2->format()->setComment(com);
04080
04081 int angle = ref1->format()->getAngle( ref1->column(), ref1->row() );
04082 ref1->format()->setAngle( ref2->format()->getAngle( ref2->column(), ref2->row() ) );
04083 ref2->format()->setAngle(angle);
04084
04085 FormatType form = ref1->format()->getFormatType( ref1->column(), ref1->row() );
04086 ref1->format()->setFormatType( ref2->format()->getFormatType( ref2->column(), ref2->row() ) );
04087 ref2->format()->setFormatType(form);
04088 }
04089 }
04090
04091 void Sheet::refreshPreference()
04092 {
04093 if ( getAutoCalc() )
04094 recalc();
04095
04096 emit sig_updateHBorder( this );
04097 emit sig_updateView( this );
04098 }
04099
04100
04101 bool Sheet::areaIsEmpty(const Region& region, TestType _type)
04102 {
04103 Region::ConstIterator endOfList = region.constEnd();
04104 for (Region::ConstIterator it = region.constBegin(); it != endOfList; ++it)
04105 {
04106 QRect range = (*it)->rect().normalize();
04107
04108 if ((*it)->isRow())
04109 {
04110 for ( int row = range.top(); row <= range.bottom(); ++row )
04111 {
04112 Cell * c = getFirstCellRow( row );
04113 while ( c )
04114 {
04115 if ( !c->isPartOfMerged())
04116 {
04117 switch( _type )
04118 {
04119 case Text :
04120 if ( !c->text().isEmpty())
04121 return false;
04122 break;
04123 case Validity:
04124 if ( c->getValidity(0))
04125 return false;
04126 break;
04127 case Comment:
04128 if ( !c->format()->comment(c->column(), row).isEmpty())
04129 return false;
04130 break;
04131 case ConditionalCellAttribute:
04132 if ( c->conditionList().count()> 0)
04133 return false;
04134 break;
04135 }
04136 }
04137
04138 c = getNextCellRight( c->column(), row );
04139 }
04140 }
04141 }
04142
04143 else if ((*it)->isColumn())
04144 {
04145 for ( int col = range.left(); col <= range.right(); ++col )
04146 {
04147 Cell * c = getFirstCellColumn( col );
04148 while ( c )
04149 {
04150 if ( !c->isPartOfMerged() )
04151 {
04152 switch( _type )
04153 {
04154 case Text :
04155 if ( !c->text().isEmpty())
04156 return false;
04157 break;
04158 case Validity:
04159 if ( c->getValidity(0))
04160 return false;
04161 break;
04162 case Comment:
04163 if ( !c->format()->comment(col, c->row()).isEmpty())
04164 return false;
04165 break;
04166 case ConditionalCellAttribute:
04167 if ( c->conditionList().count()> 0)
04168 return false;
04169 break;
04170 }
04171 }
04172
04173 c = getNextCellDown( col, c->row() );
04174 }
04175 }
04176 }
04177 else
04178 {
04179 Cell * cell;
04180
04181 int right = range.right();
04182 int bottom = range.bottom();
04183 for ( int x = range.left(); x <= right; ++x )
04184 for ( int y = range.top(); y <= bottom; ++y )
04185 {
04186 cell = cellAt( x, y );
04187 if (!cell->isPartOfMerged() )
04188 {
04189 switch( _type )
04190 {
04191 case Text :
04192 if ( !cell->text().isEmpty())
04193 return false;
04194 break;
04195 case Validity:
04196 if ( cell->getValidity(0))
04197 return false;
04198 break;
04199 case Comment:
04200 if ( !cell->format()->comment(x, y).isEmpty())
04201 return false;
04202 break;
04203 case ConditionalCellAttribute:
04204 if ( cell->conditionList().count()> 0)
04205 return false;
04206 break;
04207 }
04208 }
04209 }
04210 }
04211 }
04212 return true;
04213 }
04214
04215 struct SetSelectionMultiRowWorker : public Sheet::CellWorker
04216 {
04217 bool enable;
04218 SetSelectionMultiRowWorker( bool _enable )
04219 : Sheet::CellWorker( ), enable( _enable ) { }
04220
04221 class UndoAction* createUndoAction( Doc * doc, Sheet * sheet, const KSpread::Region& region )
04222 {
04223 QString title = i18n("Multirow");
04224 return new UndoCellFormat( doc, sheet, region, title );
04225 }
04226
04227 bool testCondition( Cell * cell )
04228 {
04229 return ( !cell->isPartOfMerged() );
04230 }
04231
04232 void doWork( Cell * cell, bool, int, int )
04233 {
04234 cell->setDisplayDirtyFlag();
04235 cell->format()->setMultiRow( enable );
04236 cell->format()->setVerticalText( false );
04237 cell->format()->setAngle( 0 );
04238 cell->clearDisplayDirtyFlag();
04239 }
04240 };
04241
04242 void Sheet::setSelectionMultiRow( Selection* selectionInfo,
04243 bool enable )
04244 {
04245 SetSelectionMultiRowWorker w( enable );
04246 workOnCells( selectionInfo, w );
04247 }
04248
04249 QString Sheet::guessColumnTitle(QRect& area, int col)
04250 {
04251
04252 Range rg;
04253 rg.setRange(area);
04254 rg.setSheet(this);
04255
04256 if ( (!rg.isValid()) || (col < area.left()) || (col > area.right()))
04257 return QString();
04258
04259
04260
04261
04262
04263
04264
04265
04266
04267
04268
04269
04270
04271 Value cellValue=value(col,area.top());
04272 return cellValue.asString();
04273 }
04274
04275 QString Sheet::guessRowTitle(QRect& area, int row)
04276 {
04277
04278 Range rg;
04279 rg.setRange(area);
04280 rg.setSheet(this);
04281
04282 if ( (!rg.isValid()) || (row < area.top()) || (row > area.bottom()) )
04283 return QString();
04284
04285
04286
04287
04288
04289
04290
04291
04292
04293
04294
04295
04296 Value cellValue=value(area.left(),row);
04297 return cellValue.asString();
04298 }
04299
04300 void Sheet::setSelectionAlign( Selection* selectionInfo,
04301 Format::Align _align )
04302 {
04303 HorAlignManipulator* manipulator = new HorAlignManipulator();
04304 manipulator->setSheet(this);
04305 manipulator->setProperty(Format::PAlign);
04306 manipulator->setHorizontalAlignment(_align);
04307 manipulator->add(*selectionInfo);
04308 manipulator->execute();
04309 }
04310
04311 void Sheet::setSelectionAlignY( Selection* selectionInfo,
04312 Format::AlignY _alignY )
04313 {
04314 VerAlignManipulator* manipulator = new VerAlignManipulator();
04315 manipulator->setSheet(this);
04316 manipulator->setProperty(Format::PAlignY);
04317 manipulator->setVerticalAlignment(_alignY);
04318 manipulator->add(*selectionInfo);
04319 manipulator->execute();
04320 }
04321
04322
04323 struct SetSelectionPrecisionWorker : public Sheet::CellWorker {
04324 int _delta;
04325 SetSelectionPrecisionWorker( int delta ) : Sheet::CellWorker( ), _delta( delta ) { }
04326
04327 class UndoAction* createUndoAction( Doc* doc, Sheet* sheet, const KSpread::Region& region ) {
04328 QString title=i18n("Change Precision");
04329 return new UndoCellFormat( doc, sheet, region, title );
04330 }
04331 bool testCondition( Cell* cell ) {
04332 return ( !cell->isPartOfMerged() );
04333 }
04334 void doWork( Cell* cell, bool, int, int ) {
04335 cell->setDisplayDirtyFlag();
04336 if ( _delta == 1 )
04337 cell->incPrecision();
04338 else
04339 cell->decPrecision();
04340 cell->clearDisplayDirtyFlag();
04341 }
04342 };
04343
04344 void Sheet::setSelectionPrecision( Selection* selectionInfo,
04345 int _delta )
04346 {
04347 SetSelectionPrecisionWorker w( _delta );
04348 workOnCells( selectionInfo, w );
04349 }
04350
04351 struct SetSelectionStyleWorker : public Sheet::CellWorkerTypeA
04352 {
04353 Style * m_style;
04354 SetSelectionStyleWorker( Style * style )
04355 : m_style( style )
04356 {
04357 }
04358
04359 QString getUndoTitle()
04360 {
04361 return i18n("Apply Style");
04362 }
04363
04364 void doWork( RowFormat* rw )
04365 {
04366 rw->setStyle( m_style );
04367 }
04368
04369 void doWork( ColumnFormat* cl )
04370 {
04371 cl->setStyle( m_style );
04372 }
04373
04374 bool testCondition( Cell* cell )
04375 {
04376 return ( !cell->isPartOfMerged() && cell->format()->style() != m_style );
04377 }
04378
04379 void doWork( Cell* cell, bool cellRegion, int, int )
04380 {
04381 if ( cellRegion )
04382 cell->setDisplayDirtyFlag();
04383
04384 cell->format()->setStyle( m_style );
04385
04386 if ( cellRegion )
04387 cell->clearDisplayDirtyFlag();
04388 }
04389 };
04390
04391
04392 void Sheet::setSelectionStyle( Selection * selectionInfo, Style * style )
04393 {
04394 SetSelectionStyleWorker w( style );
04395 workOnCells( selectionInfo, w );
04396 }
04397
04398 struct SetSelectionMoneyFormatWorker : public Sheet::CellWorkerTypeA
04399 {
04400 bool b;
04401 Doc *m_pDoc;
04402 SetSelectionMoneyFormatWorker( bool _b,Doc* _doc ) : b( _b ), m_pDoc(_doc) { }
04403 QString getUndoTitle() { return i18n("Format Money"); }
04404 bool testCondition( RowFormat* rw ) {
04405 return ( rw->hasProperty( Format::PFormatType )
04406 || rw->hasProperty( Format::PPrecision ) );
04407 }
04408 void doWork( RowFormat* rw ) {
04409 rw->setFormatType( b ? Money_format : Generic_format );
04410 rw->setPrecision( b ? m_pDoc->locale()->fracDigits() : 0 );
04411 }
04412 void doWork( ColumnFormat* cl ) {
04413 cl->setFormatType( b ? Money_format : Generic_format );
04414 cl->setPrecision( b ? m_pDoc->locale()->fracDigits() : 0 );
04415 }
04416 void prepareCell( Cell* c ) {
04417 c->format()->clearProperty( Format::PPrecision );
04418 c->format()->clearNoFallBackProperties( Format::PPrecision );
04419 c->format()->clearProperty( Format::PFormatType );
04420 c->format()->clearNoFallBackProperties( Format::PFormatType );
04421 }
04422 bool testCondition( Cell* cell ) {
04423 return ( !cell->isPartOfMerged() );
04424 }
04425 void doWork( Cell* cell, bool cellRegion, int, int ) {
04426 if ( cellRegion )
04427 cell->setDisplayDirtyFlag();
04428 cell->format()->setFormatType( b ? Money_format : Generic_format );
04429 cell->format()->setPrecision( b ? m_pDoc->locale()->fracDigits() : 0 );
04430 if ( cellRegion )
04431 cell->clearDisplayDirtyFlag();
04432 }
04433 };
04434
04435
04436 void Sheet::setSelectionMoneyFormat( Selection* selectionInfo,
04437 bool b )
04438 {
04439 SetSelectionMoneyFormatWorker w( b,doc() );
04440 workOnCells( selectionInfo, w );
04441 }
04442
04443
04444 struct IncreaseIndentWorker : public Sheet::CellWorkerTypeA {
04445 double tmpIndent;
04446 double valIndent;
04447
04448 IncreaseIndentWorker( double _tmpIndent, double _valIndent )
04449 : tmpIndent( _tmpIndent ), valIndent( _valIndent ) { }
04450
04451 QString getUndoTitle() { return i18n("Increase Indent"); }
04452 bool testCondition( RowFormat* rw ) {
04453 return ( rw->hasProperty( Format::PIndent ) );
04454 }
04455
04456 void doWork( RowFormat* rw ) {
04457 rw->setIndent( tmpIndent+valIndent );
04458
04459 }
04460 void doWork( ColumnFormat* cl ) {
04461 cl->setIndent( tmpIndent+valIndent );
04462
04463 }
04464 void prepareCell( Cell* c ) {
04465 c->format()->clearProperty( Format::PIndent );
04466 c->format()->clearNoFallBackProperties( Format::PIndent );
04467
04468
04469 }
04470 bool testCondition( Cell* cell ) {
04471 return ( !cell->isPartOfMerged() );
04472 }
04473 void doWork( Cell* cell, bool cellRegion, int x, int y ) {
04474 if ( cellRegion ) {
04475 if(cell->format()->align(x,y)!=Format::Left)
04476 {
04477
04478
04479 }
04480 cell->setDisplayDirtyFlag();
04481 cell->format()->setIndent( cell->format()->getIndent(x,y) +valIndent );
04482 cell->clearDisplayDirtyFlag();
04483 } else {
04484 cell->format()->setIndent( tmpIndent+valIndent);
04485
04486 }
04487 }
04488 };
04489
04490
04491 void Sheet::increaseIndent(Selection* selectionInfo)
04492 {
04493 QPoint marker(selectionInfo->marker());
04494 double valIndent = doc()->getIndentValue();
04495 Cell *c = cellAt( marker );
04496 double tmpIndent = c->format()->getIndent( marker.x(), marker.y() );
04497
04498 IncreaseIndentWorker w( tmpIndent, valIndent );
04499 workOnCells( selectionInfo, w );
04500 }
04501
04502
04503 struct DecreaseIndentWorker : public Sheet::CellWorkerTypeA {
04504 double tmpIndent, valIndent;
04505 DecreaseIndentWorker( double _tmpIndent, double _valIndent ) : tmpIndent( _tmpIndent ), valIndent( _valIndent ) { }
04506 QString getUndoTitle() { return i18n("Decrease Indent"); }
04507 bool testCondition( RowFormat* rw ) {
04508 return ( rw->hasProperty( Format::PIndent ) );
04509 }
04510 void doWork( RowFormat* rw ) {
04511 rw->setIndent( QMAX( 0.0, tmpIndent - valIndent ) );
04512 }
04513 void doWork( ColumnFormat* cl ) {
04514 cl->setIndent( QMAX( 0.0, tmpIndent - valIndent ) );
04515 }
04516 void prepareCell( Cell* c ) {
04517 c->format()->clearProperty( Format::PIndent );
04518 c->format()->clearNoFallBackProperties( Format::PIndent );
04519 }
04520 bool testCondition( Cell* cell ) {
04521 return ( !cell->isPartOfMerged() );
04522 }
04523 void doWork( Cell* cell, bool cellRegion, int x, int y ) {
04524 if ( cellRegion ) {
04525 cell->setDisplayDirtyFlag();
04526 cell->format()->setIndent( QMAX( 0.0, cell->format()->getIndent( x, y ) - valIndent ) );
04527 cell->clearDisplayDirtyFlag();
04528 } else {
04529 cell->format()->setIndent( QMAX( 0.0, tmpIndent - valIndent ) );
04530 }
04531 }
04532 };
04533
04534
04535 void Sheet::decreaseIndent( Selection* selectionInfo )
04536 {
04537 double valIndent = doc()->getIndentValue();
04538 QPoint marker(selectionInfo->marker());
04539 Cell* c = cellAt( marker );
04540 double tmpIndent = c->format()->getIndent( marker.x(), marker.y() );
04541
04542 DecreaseIndentWorker w( tmpIndent, valIndent );
04543 workOnCells( selectionInfo, w );
04544 }
04545
04546
04547 int Sheet::adjustColumnHelper( Cell * c, int _col, int _row )
04548 {
04549 double long_max = 0.0;
04550 c->calculateTextParameters( painter(), _col, _row );
04551 if ( c->textWidth() > long_max )
04552 {
04553 double indent = 0.0;
04554 int a = c->format()->align( c->column(), c->row() );
04555 if ( a == Format::Undefined )
04556 {
04557 if ( c->value().isNumber() || c->isDate() || c->isTime())
04558 a = Format::Right;
04559 else
04560 a = Format::Left;
04561 }
04562
04563 if ( a == Format::Left )
04564 indent = c->format()->getIndent( c->column(), c->row() );
04565 long_max = indent + c->textWidth()
04566 + c->format()->leftBorderWidth( c->column(), c->row() )
04567 + c->format()->rightBorderWidth( c->column(), c->row() );
04568 }
04569 return (int)long_max;
04570 }
04571
04572 void Sheet::adjustArea(const Region& region)
04573 {
04574 AdjustColumnRowManipulator* manipulator = new AdjustColumnRowManipulator();
04575 manipulator->setSheet(this);
04576 manipulator->setAdjustColumn(true);
04577 manipulator->setAdjustRow(true);
04578 manipulator->add(region);
04579 manipulator->execute();
04580 }
04581
04582 void Sheet::adjustColumn(const Region& region)
04583 {
04584 AdjustColumnRowManipulator* manipulator = new AdjustColumnRowManipulator();
04585 manipulator->setSheet(this);
04586 manipulator->setAdjustColumn(true);
04587 manipulator->add(region);
04588 manipulator->execute();
04589 }
04590
04591 void Sheet::adjustRow(const Region& region)
04592 {
04593 AdjustColumnRowManipulator* manipulator = new AdjustColumnRowManipulator();
04594 manipulator->setSheet(this);
04595 manipulator->setAdjustRow(true);
04596 manipulator->add(region);
04597 manipulator->execute();
04598 }
04599
04600 struct ClearTextSelectionWorker : public Sheet::CellWorker {
04601 Sheet * _s;
04602
04603 ClearTextSelectionWorker( Sheet * s )
04604 : Sheet::CellWorker( ), _s( s ) { }
04605
04606 class UndoAction* createUndoAction( Doc* doc, Sheet* sheet, const KSpread::Region& region ) {
04607 return new UndoChangeAreaTextCell( doc, sheet, region );
04608 }
04609 bool testCondition( Cell* cell ) {
04610 return ( !cell->isObscured() );
04611 }
04612 void doWork( Cell* cell, bool, int, int )
04613 {
04614 cell->setCellText( "" );
04615 }
04616 };
04617
04618 void Sheet::clearTextSelection( Selection* selectionInfo )
04619 {
04620 if (areaIsEmpty(*selectionInfo))
04621 return;
04622
04623 ClearTextSelectionWorker w( this );
04624 workOnCells( selectionInfo, w );
04625 }
04626
04627
04628 struct ClearValiditySelectionWorker : public Sheet::CellWorker {
04629 ClearValiditySelectionWorker( ) : Sheet::CellWorker( ) { }
04630
04631 class UndoAction* createUndoAction( Doc* doc, Sheet* sheet, const KSpread::Region& region ) {
04632 return new UndoConditional( doc, sheet, region );
04633 }
04634 bool testCondition( Cell* cell ) {
04635 return ( !cell->isObscured() );
04636 }
04637 void doWork( Cell* cell, bool, int, int ) {
04638 cell->removeValidity();
04639 }
04640 };
04641
04642 void Sheet::clearValiditySelection( Selection* selectionInfo )
04643 {
04644 if (areaIsEmpty(*selectionInfo, Validity))
04645 return;
04646
04647 ClearValiditySelectionWorker w;
04648 workOnCells( selectionInfo, w );
04649 }
04650
04651
04652 struct ClearConditionalSelectionWorker : public Sheet::CellWorker
04653 {
04654 ClearConditionalSelectionWorker( ) : Sheet::CellWorker( ) { }
04655
04656 class UndoAction* createUndoAction( Doc* doc,
04657 Sheet* sheet,
04658 const KSpread::Region& region )
04659 {
04660 return new UndoConditional( doc, sheet, region );
04661 }
04662 bool testCondition( Cell* cell )
04663 {
04664 return ( !cell->isObscured() );
04665 }
04666 void doWork( Cell* cell, bool, int, int )
04667 {
04668 QValueList<Conditional> emptyList;
04669 cell->setConditionList(emptyList);
04670 }
04671 };
04672
04673 void Sheet::clearConditionalSelection( Selection* selectionInfo )
04674 {
04675 ClearConditionalSelectionWorker w;
04676 workOnCells( selectionInfo, w );
04677 }
04678
04679 void Sheet::fillSelection( Selection * selectionInfo, int direction )
04680 {
04681 QRect rct( selectionInfo->selection() );
04682 int right = rct.right();
04683 int bottom = rct.bottom();
04684 int left = rct.left();
04685 int top = rct.top();
04686 int width = rct.width();
04687 int height = rct.height();
04688
04689 QDomDocument undoDoc = saveCellRegion( rct );
04690 loadSelectionUndo( undoDoc, rct, left - 1, top - 1, false, 0 );
04691
04692 QDomDocument doc;
04693
04694 switch( direction )
04695 {
04696 case Right:
04697 doc = saveCellRegion( QRect( left, top, 1, height ) );
04698 break;
04699
04700 case Up:
04701 doc = saveCellRegion( QRect( left, bottom, width, 1 ) );
04702 break;
04703
04704 case Left:
04705 doc = saveCellRegion( QRect( right, top, 1, height ) );
04706 break;
04707
04708 case Down:
04709 doc = saveCellRegion( QRect( left, top, width, 1 ) );
04710 break;
04711 };
04712
04713
04714 QBuffer buffer;
04715 buffer.open( IO_WriteOnly );
04716 QTextStream str( &buffer );
04717 str.setEncoding( QTextStream::UnicodeUTF8 );
04718 str << doc;
04719 buffer.close();
04720
04721 int i;
04722 switch( direction )
04723 {
04724 case Right:
04725 for ( i = left + 1; i <= right; ++i )
04726 {
04727 paste( buffer.buffer(), QRect( i, top, 1, 1 ), false );
04728 }
04729 break;
04730
04731 case Up:
04732 for ( i = bottom + 1; i >= top; --i )
04733 {
04734 paste( buffer.buffer(), QRect( left, i, 1, 1 ), false );
04735 }
04736 break;
04737
04738 case Left:
04739 for ( i = right - 1; i >= left; --i )
04740 {
04741 paste( buffer.buffer(), QRect( i, top, 1, 1 ), false );
04742 }
04743 break;
04744
04745 case Down:
04746 for ( i = top + 1; i <= bottom; ++i )
04747 {
04748 paste( buffer.buffer(), QRect( left, i, 1, 1 ), false );
04749 }
04750 break;
04751 }
04752
04753 this->doc()->setModified( true );
04754 }
04755
04756
04757 struct DefaultSelectionWorker : public Sheet::CellWorker {
04758 DefaultSelectionWorker( ) : Sheet::CellWorker( true, false, true ) { }
04759
04760 class UndoAction* createUndoAction( Doc* doc, Sheet* sheet, const KSpread::Region& region ) {
04761 QString title=i18n("Default Parameters");
04762 return new UndoCellFormat( doc, sheet, region, title );
04763 }
04764 bool testCondition( Cell* ) {
04765 return true;
04766 }
04767 void doWork( Cell* cell, bool, int, int ) {
04768 cell->defaultStyle();
04769 }
04770 };
04771
04772 void Sheet::defaultSelection( Selection* selectionInfo )
04773 {
04774 QRect selection(selectionInfo->selection());
04775 DefaultSelectionWorker w;
04776 SelectionType st = workOnCells( selectionInfo, w );
04777 switch ( st ) {
04778 case CompleteRows:
04779 RowFormat *rw;
04780 for ( int i = selection.top(); i <= selection.bottom(); i++ ) {
04781 rw = nonDefaultRowFormat( i );
04782 rw->defaultStyleFormat();
04783 }
04784 emit sig_updateView( this, *selectionInfo );
04785 return;
04786 case CompleteColumns:
04787 ColumnFormat *cl;
04788 for ( int i = selection.left(); i <= selection.right(); i++ ) {
04789 cl=nonDefaultColumnFormat( i );
04790 cl->defaultStyleFormat();
04791 }
04792 emit sig_updateView( this, *selectionInfo );
04793 return;
04794 case CellRegion:
04795 emit sig_updateView( this, *selectionInfo );
04796 return;
04797 }
04798 }
04799
04800
04801 struct SetConditionalWorker : public Sheet::CellWorker
04802 {
04803 QValueList<Conditional> conditionList;
04804 SetConditionalWorker( QValueList<Conditional> _tmp ) :
04805 Sheet::CellWorker( ), conditionList( _tmp ) { }
04806
04807 class UndoAction* createUndoAction( Doc* doc,
04808 Sheet* sheet, const KSpread::Region& region )
04809 {
04810 return new UndoConditional( doc, sheet, region );
04811 }
04812
04813 bool testCondition( Cell* )
04814 {
04815 return true;
04816 }
04817
04818 void doWork( Cell* cell, bool, int, int )
04819 {
04820 if ( !cell->isObscured() )
04821 {
04822 cell->setConditionList(conditionList);
04823 cell->setDisplayDirtyFlag();
04824 }
04825 }
04826 };
04827
04828 void Sheet::setConditional( Selection* selectionInfo,
04829 QValueList<Conditional> const & newConditions)
04830 {
04831 if ( !doc()->undoLocked() )
04832 {
04833 UndoConditional * undo = new UndoConditional(doc(), this, *selectionInfo);
04834 doc()->addCommand( undo );
04835 }
04836
04837 Region::ConstIterator endOfList = selectionInfo->constEnd();
04838 for (Region::ConstIterator it = selectionInfo->constBegin(); it != endOfList; ++it)
04839 {
04840 QRect range = (*it)->rect().normalize();
04841
04842 int l = range.left();
04843 int r = range.right();
04844 int t = range.top();
04845 int b = range.bottom();
04846
04847 Cell * cell;
04848 Style * s = doc()->styleManager()->defaultStyle();
04849 for (int x = l; x <= r; ++x)
04850 {
04851 for (int y = t; y <= b; ++y)
04852 {
04853 cell = nonDefaultCell( x, y, false, s );
04854 cell->setConditionList( newConditions );
04855 cell->setDisplayDirtyFlag();
04856 }
04857 }
04858 }
04859
04860 emit sig_updateView( this, *selectionInfo );
04861 }
04862
04863
04864 struct SetValidityWorker : public Sheet::CellWorker {
04865 Validity tmp;
04866 SetValidityWorker( Validity _tmp ) : Sheet::CellWorker( ), tmp( _tmp ) { }
04867
04868 class UndoAction* createUndoAction( Doc* doc, Sheet* sheet, const KSpread::Region& region ) {
04869 return new UndoConditional( doc, sheet, region );
04870 }
04871 bool testCondition( Cell* ) {
04872 return true;
04873 }
04874 void doWork( Cell* cell, bool, int, int ) {
04875 if ( !cell->isObscured() ) {
04876 cell->setDisplayDirtyFlag();
04877 if ( tmp.m_restriction==Restriction::None )
04878 cell->removeValidity();
04879 else
04880 {
04881 Validity *tmpValidity = cell->getValidity();
04882 tmpValidity->message=tmp.message;
04883 tmpValidity->title=tmp.title;
04884 tmpValidity->valMin=tmp.valMin;
04885 tmpValidity->valMax=tmp.valMax;
04886 tmpValidity->m_cond=tmp.m_cond;
04887 tmpValidity->m_action=tmp.m_action;
04888 tmpValidity->m_restriction=tmp.m_restriction;
04889 tmpValidity->timeMin=tmp.timeMin;
04890 tmpValidity->timeMax=tmp.timeMax;
04891 tmpValidity->dateMin=tmp.dateMin;
04892 tmpValidity->dateMax=tmp.dateMax;
04893 tmpValidity->displayMessage=tmp.displayMessage;
04894 tmpValidity->allowEmptyCell=tmp.allowEmptyCell;
04895 tmpValidity->displayValidationInformation=tmp.displayValidationInformation;
04896 tmpValidity->titleInfo=tmp.titleInfo;
04897 tmpValidity->messageInfo=tmp.messageInfo;
04898 tmpValidity->listValidity=tmp.listValidity;
04899 }
04900 cell->clearDisplayDirtyFlag();
04901 }
04902 }
04903 };
04904
04905 void Sheet::setValidity(Selection* selectionInfo,
04906 KSpread::Validity tmp )
04907 {
04908 SetValidityWorker w( tmp );
04909 workOnCells( selectionInfo, w );
04910 }
04911
04912
04913 struct GetWordSpellingWorker : public Sheet::CellWorker {
04914 QString& listWord;
04915 GetWordSpellingWorker( QString& _listWord ) : Sheet::CellWorker( false, false, true ), listWord( _listWord ) { }
04916
04917 class UndoAction* createUndoAction( Doc*, Sheet*, const KSpread::Region& ) {
04918 return 0;
04919 }
04920 bool testCondition( Cell* ) {
04921 return true;
04922 }
04923 void doWork( Cell* c, bool cellRegion, int, int ) {
04924 if ( !c->isObscured() || cellRegion ) {
04925 if ( !c->isFormula() && !c->value().isNumber() && !c->value().asString().isEmpty() && !c->isTime()
04926 && !c->isDate()
04927 && !c->text().isEmpty())
04928 {
04929 listWord+=c->text()+'\n';
04930 }
04931 }
04932 }
04933 };
04934
04935 QString Sheet::getWordSpelling(Selection* selectionInfo )
04936 {
04937 QString listWord;
04938 GetWordSpellingWorker w( listWord );
04939 workOnCells( selectionInfo, w );
04940 return listWord;
04941 }
04942
04943
04944 struct SetWordSpellingWorker : public Sheet::CellWorker {
04945 QStringList& list;
04946 int pos;
04947 Sheet * sheet;
04948 SetWordSpellingWorker( QStringList & _list,Sheet * s )
04949 : Sheet::CellWorker( false, false, true ), list( _list ), pos( 0 ), sheet( s ) { }
04950
04951 class UndoAction* createUndoAction( Doc* doc, Sheet* sheet, const KSpread::Region& region ) {
04952 return new UndoChangeAreaTextCell( doc, sheet, region );
04953 }
04954 bool testCondition( Cell* ) {
04955 return true;
04956 }
04957 void doWork( Cell* c, bool cellRegion, int, int )
04958 {
04959 if ( !c->isObscured() || cellRegion ) {
04960 if ( !c->isFormula() && !c->value().isNumber() && !c->value().asString().isEmpty() && !c->isTime()
04961 && !c->isDate()
04962 && !c->text().isEmpty())
04963 {
04964
04965
04966 c->setCellText( list[pos] );
04967 pos++;
04968 }
04969 }
04970 }
04971 };
04972
04973 void Sheet::setWordSpelling(Selection* selectionInfo,
04974 const QString _listWord )
04975 {
04976 QStringList list = QStringList::split ( '\n', _listWord );
04977 SetWordSpellingWorker w( list, this );
04978 workOnCells( selectionInfo, w );
04979 }
04980
04981 static QString cellAsText( Cell* cell, unsigned int max )
04982 {
04983 QString result;
04984 if( !cell->isDefault() )
04985 {
04986 int l = max - cell->strOutText().length();
04987 if (cell->defineAlignX() == Format::Right )
04988 {
04989 for ( int i = 0; i < l; ++i )
04990 result += " ";
04991 result += cell->strOutText();
04992 }
04993 else if (cell->defineAlignX() == Format::Left )
04994 {
04995 result += " ";
04996 result += cell->strOutText();
04997
04998 for ( int i = 1; i < l; ++i )
04999 result += " ";
05000 }
05001 else
05002 {
05003 int i;
05004 int s = (int) l / 2;
05005 for ( i = 0; i < s; ++i )
05006 result += " ";
05007 result += cell->strOutText();
05008 for ( i = s; i < l; ++i )
05009 result += " ";
05010 }
05011 }
05012 else
05013 {
05014 for ( unsigned int i = 0; i < max; ++i )
05015 result += " ";
05016 }
05017
05018 return result;
05019 }
05020
05021 QString Sheet::copyAsText( Selection* selectionInfo )
05022 {
05023
05024 if ( selectionInfo->isSingular() )
05025 {
05026 Cell * cell = cellAt( selectionInfo->marker() );
05027 if( !cell->isDefault() )
05028 return cell->strOutText();
05029 return "";
05030 }
05031
05032 QRect selection(selectionInfo->selection());
05033
05034
05035 unsigned top = selection.bottom();
05036 unsigned bottom = selection.top();
05037 unsigned left = selection.right();
05038 unsigned right = selection.left();
05039
05040 unsigned max = 1;
05041 for( Cell *c = d->cells.firstCell();c; c = c->nextCell() )
05042 {
05043 if ( !c->isDefault() )
05044 {
05045 QPoint p( c->column(), c->row() );
05046 if ( selection.contains( p ) )
05047 {
05048 top = QMIN( top, (unsigned) c->row() );
05049 left = QMIN( left, (unsigned) c->column() );
05050 bottom = QMAX( bottom, (unsigned) c->row() );
05051 right = QMAX( right, (unsigned) c->column() );
05052
05053 if ( c->strOutText().length() > max )
05054 max = c->strOutText().length();
05055 }
05056 }
05057 }
05058
05059 ++max;
05060
05061 QString result;
05062 for ( unsigned y = top; y <= bottom; ++y)
05063 {
05064 for ( unsigned x = left; x <= right; ++x)
05065 {
05066 Cell *cell = cellAt( x, y );
05067 result += cellAsText( cell, max );
05068 }
05069 result += "\n";
05070 }
05071
05072 return result;
05073 }
05074
05075 void Sheet::copySelection( Selection* selectionInfo )
05076 {
05077 QDomDocument doc = saveCellRegion( *selectionInfo, true );
05078
05079
05080 QBuffer buffer;
05081 buffer.open( IO_WriteOnly );
05082 QTextStream str( &buffer );
05083 str.setEncoding( QTextStream::UnicodeUTF8 );
05084 str << doc;
05085 buffer.close();
05086
05087 TextDrag * kd = new TextDrag( 0L );
05088 kd->setPlain( copyAsText(selectionInfo) );
05089 kd->setKSpread( buffer.buffer() );
05090
05091 QApplication::clipboard()->setData( kd );
05092 }
05093
05094 void Sheet::cutSelection( Selection* selectionInfo )
05095 {
05096 QDomDocument doc = saveCellRegion(*selectionInfo, true, true);
05097
05098
05099 QBuffer buffer;
05100 buffer.open( IO_WriteOnly );
05101 QTextStream str( &buffer );
05102 str.setEncoding( QTextStream::UnicodeUTF8 );
05103 str << doc;
05104 buffer.close();
05105
05106 TextDrag * kd = new TextDrag( 0L );
05107 kd->setPlain( copyAsText(selectionInfo) );
05108 kd->setKSpread( buffer.buffer() );
05109
05110 QApplication::clipboard()->setData( kd );
05111
05112 deleteSelection( selectionInfo, true );
05113 }
05114
05115 void Sheet::paste( const QRect& pasteArea, bool makeUndo,
05116 Paste::Mode mode, Paste::Operation operation,
05117 bool insert, int insertTo, bool pasteFC,
05118 QClipboard::Mode clipboardMode )
05119 {
05120 QMimeSource * mime = QApplication::clipboard()->data( clipboardMode );
05121 if ( !mime )
05122 return;
05123
05124 QByteArray b;
05125
05126 if ( mime->provides( TextDrag::selectionMimeType() ) )
05127 {
05128 b = mime->encodedData( TextDrag::selectionMimeType() );
05129 }
05130 else if( mime->provides( "text/plain" ) )
05131 {
05132
05133
05134 QString _text = QApplication::clipboard()->text( clipboardMode );
05135 doc()->emitBeginOperation();
05136 pasteTextPlain( _text, pasteArea );
05137 emit sig_updateView( this );
05138
05139 return;
05140 }
05141 else
05142 return;
05143
05144
05145 doc()->emitBeginOperation();
05146 paste( b, pasteArea, makeUndo, mode, operation, insert, insertTo, pasteFC );
05147 emit sig_updateView( this );
05148
05149 }
05150
05151
05152 void Sheet::pasteTextPlain( QString &_text, QRect pasteArea)
05153 {
05154
05155
05156 if( _text.isEmpty() )
05157 return;
05158
05159 QString tmp = _text;
05160 int i;
05161 int mx = pasteArea.left();
05162 int my = pasteArea.top();
05163 int rows = 1;
05164 int len = tmp.length();
05165
05166
05167 for ( i = 0; i < len; ++i )
05168 {
05169 if ( tmp[i] == '\n' )
05170 ++rows;
05171 }
05172
05173 Cell * cell = nonDefaultCell( mx, my );
05174 if ( rows == 1 )
05175 {
05176 if ( !doc()->undoLocked() )
05177 {
05178 UndoSetText * undo = new UndoSetText( doc(), this , cell->text(), mx, my, cell->formatType() );
05179 doc()->addCommand( undo );
05180 }
05181 }
05182 else
05183 {
05184 QRect rect(mx, my, mx, my + rows - 1);
05185 UndoChangeAreaTextCell * undo = new UndoChangeAreaTextCell( doc(), this , rect );
05186 doc()->addCommand( undo );
05187 }
05188
05189 i = 0;
05190 QString rowtext;
05191
05192 while ( i < rows )
05193 {
05194 int p = 0;
05195
05196 p = tmp.find('\n');
05197
05198 if (p < 0)
05199 p = tmp.length();
05200
05201 rowtext = tmp.left(p);
05202
05203 if ( !isProtected() || cell->format()->notProtected( mx, my + i ) )
05204 {
05205 cell->setCellText( rowtext );
05206 cell->updateChart();
05207 }
05208
05209
05210 ++i;
05211 cell = nonDefaultCell( mx, my + i );
05212
05213 if (!cell || p == (int) tmp.length())
05214 break;
05215
05216
05217 tmp = tmp.right(tmp.length() - p - 1);
05218 }
05219
05220 if (!isLoading())
05221 refreshMergedCell();
05222
05223 emit sig_updateView( this );
05224 emit sig_updateHBorder( this );
05225 emit sig_updateVBorder( this );
05226 }
05227
05228 void Sheet::paste( const QByteArray& b, const QRect& pasteArea, bool makeUndo,
05229 Paste::Mode mode, Paste::Operation operation,
05230 bool insert, int insertTo, bool pasteFC )
05231 {
05232 kdDebug(36001) << "Parsing " << b.size() << " bytes" << endl;
05233
05234 QBuffer buffer( b );
05235 buffer.open( IO_ReadOnly );
05236 QDomDocument doc;
05237 doc.setContent( &buffer );
05238 buffer.close();
05239
05240
05241
05242 int mx = pasteArea.left();
05243 int my = pasteArea.top();
05244
05245 loadSelection( doc, pasteArea, mx - 1, my - 1, makeUndo,
05246 mode, operation, insert, insertTo, pasteFC );
05247 }
05248
05249 bool Sheet::loadSelection(const QDomDocument& doc, const QRect& pasteArea,
05250 int _xshift, int _yshift, bool makeUndo,
05251 Paste::Mode mode, Paste::Operation operation, bool insert,
05252 int insertTo, bool pasteFC)
05253 {
05254
05255
05256 if (!isLoading() && makeUndo)
05257 {
05258 loadSelectionUndo( doc, pasteArea, _xshift, _yshift, insert, insertTo );
05259 }
05260
05261 QDomElement root = doc.documentElement();
05262
05263 int rowsInClpbrd = root.attribute( "rows" ).toInt();
05264 int columnsInClpbrd = root.attribute( "columns" ).toInt();
05265
05266
05267 const int pasteWidth = ( pasteArea.width() >= columnsInClpbrd
05268 && util_isRowSelected(pasteArea) == false
05269 && root.namedItem( "rows" ).toElement().isNull() )
05270 ? pasteArea.width() : columnsInClpbrd;
05271 const int pasteHeight = ( pasteArea.height() >= rowsInClpbrd
05272 && util_isColumnSelected(pasteArea) == false
05273 && root.namedItem( "columns" ).toElement().isNull())
05274 ? pasteArea.height() : rowsInClpbrd;
05275
05276
05277
05278
05279
05280
05281
05282
05283 QDomElement e = root.firstChild().toElement();
05284 for (; !e.isNull(); e = e.nextSibling().toElement())
05285 {
05286
05287 if (e.tagName() == "columns" && !isProtected())
05288 {
05289 _yshift = 0;
05290
05291
05292 int col = e.attribute("column").toInt();
05293 int width = e.attribute("count").toInt();
05294 if (!insert)
05295 {
05296 for ( int i = col; i < col + width; ++i )
05297 {
05298 d->cells.clearColumn( _xshift + i );
05299 d->columns.removeElement( _xshift + i );
05300 }
05301 }
05302
05303
05304 QDomElement c = e.firstChild().toElement();
05305 for ( ; !c.isNull(); c = c.nextSibling().toElement() )
05306 {
05307 if ( c.tagName() == "column" )
05308 {
05309 ColumnFormat *cl = new ColumnFormat( this, 0 );
05310 if ( cl->load( c, _xshift, mode, pasteFC ) )
05311 insertColumnFormat( cl );
05312 else
05313 delete cl;
05314 }
05315 }
05316 }
05317
05318
05319 if (e.tagName() == "rows" && !isProtected())
05320 {
05321 _xshift = 0;
05322
05323
05324 int row = e.attribute("row").toInt();
05325 int height = e.attribute("count").toInt();
05326 if ( !insert )
05327 {
05328 for( int i = row; i < row + height; ++i )
05329 {
05330 d->cells.clearRow( _yshift + i );
05331 d->rows.removeElement( _yshift + i );
05332 }
05333 }
05334
05335
05336 QDomElement c = e.firstChild().toElement();
05337 for( ; !c.isNull(); c = c.nextSibling().toElement() )
05338 {
05339 if ( c.tagName() == "row" )
05340 {
05341 RowFormat *cl = new RowFormat( this, 0 );
05342 if ( cl->load( c, _yshift, mode, pasteFC ) )
05343 insertRowFormat( cl );
05344 else
05345 delete cl;
05346 }
05347 }
05348 }
05349
05350 Cell* refreshCell = 0;
05351 Cell *cell;
05352 Cell *cellBackup = NULL;
05353 if (e.tagName() == "cell")
05354 {
05355 int row = e.attribute( "row" ).toInt() + _yshift;
05356 int col = e.attribute( "column" ).toInt() + _xshift;
05357
05358
05359 for (int roff = 0; row + roff - _yshift <= pasteHeight; roff += rowsInClpbrd)
05360 {
05361 for (int coff = 0; col + coff - _xshift <= pasteWidth; coff += columnsInClpbrd)
05362 {
05363
05364
05365
05366
05367 cell = nonDefaultCell( col + coff, row + roff );
05368 if (isProtected() && !cell->format()->notProtected(col + coff, row + roff))
05369 {
05370 continue;
05371 }
05372
05373 cellBackup = new Cell(this, cell->column(), cell->row());
05374 cellBackup->copyAll(cell);
05375
05376 if (!cell->load(e, _xshift + coff, _yshift + roff, mode, operation, pasteFC))
05377 {
05378 cell->copyAll(cellBackup);
05379 }
05380 else
05381 {
05382 if (cell->isFormula())
05383 {
05384 cell->setCalcDirtyFlag();
05385 }
05386 }
05387
05388 delete cellBackup;
05389
05390
05391
05392 cell = cellAt( col + coff, row + roff );
05393 if( !refreshCell && cell->updateChart( false ) )
05394 {
05395 refreshCell = cell;
05396 }
05397 }
05398 }
05399 }
05400
05401
05402
05403
05404
05405
05406
05407
05408 if ( refreshCell )
05409 refreshCell->updateChart();
05410 }
05411 this->doc()->setModified( true );
05412
05413 if (!isLoading())
05414 refreshMergedCell();
05415
05416 emit sig_updateView( this );
05417 emit sig_updateHBorder( this );
05418 emit sig_updateVBorder( this );
05419
05420 return true;
05421 }
05422
05423 void Sheet::loadSelectionUndo(const QDomDocument& d, const QRect& loadArea,
05424 int _xshift, int _yshift,
05425 bool insert, int insertTo)
05426 {
05427 QDomElement root = d.documentElement();
05428
05429 int rowsInClpbrd = root.attribute( "rows" ).toInt();
05430 int columnsInClpbrd = root.attribute( "columns" ).toInt();
05431
05432
05433 const int pasteWidth = (loadArea.width() >= columnsInClpbrd &&
05434 util_isRowSelected(loadArea) == false &&
05435 root.namedItem( "rows" ).toElement().isNull())
05436 ? loadArea.width() : columnsInClpbrd;
05437 const int pasteHeight = (loadArea.height() >= rowsInClpbrd &&
05438 util_isColumnSelected(loadArea) == false &&
05439 root.namedItem( "columns" ).toElement().isNull())
05440 ? loadArea.height() : rowsInClpbrd;
05441
05442 uint numCols = 0;
05443 uint numRows = 0;
05444
05445 Region region;
05446 for (QDomNode n = root.firstChild(); !n.isNull(); n = n.nextSibling())
05447 {
05448 QDomElement e = n.toElement();
05449 if (e.tagName() == "columns")
05450 {
05451 _yshift = 0;
05452 int col = e.attribute("column").toInt();
05453 int width = e.attribute("count").toInt();
05454 for (int coff = 0; col + coff <= pasteWidth; coff += columnsInClpbrd)
05455 {
05456 uint overlap = QMAX(0, (col - 1 + coff + width) - pasteWidth);
05457 uint effWidth = width - overlap;
05458 region.add(QRect(_xshift + col + coff, 1, effWidth, KS_rowMax));
05459 numCols += effWidth;
05460 }
05461 }
05462 else if (e.tagName() == "rows")
05463 {
05464 _xshift = 0;
05465 int row = e.attribute("row").toInt();
05466 int height = e.attribute("count").toInt();
05467 for (int roff = 0; row + roff <= pasteHeight; roff += rowsInClpbrd)
05468 {
05469 uint overlap = QMAX(0, (row - 1 + roff + height) - pasteHeight);
05470 uint effHeight = height - overlap;
05471 region.add(QRect(1, _yshift + row + roff, KS_colMax, effHeight));
05472 numRows += effHeight;
05473 }
05474 }
05475 else if (!e.isNull())
05476 {
05477
05478 int col = e.attribute("column").toInt();
05479 int row = e.attribute("row").toInt();
05480 for (int coff = 0; col + coff <= pasteWidth; coff += columnsInClpbrd)
05481 {
05482 for (int roff = 0; row + roff <= pasteHeight; roff += rowsInClpbrd)
05483 {
05484 region.add(QPoint(_xshift + col + coff, _yshift + row + roff));
05485 }
05486 }
05487 }
05488 }
05489
05490 if (!doc()->undoLocked())
05491 {
05492 UndoCellPaste *undo = new UndoCellPaste( doc(), this, _xshift, _yshift, region, insert, insertTo );
05493 doc()->addCommand( undo );
05494 }
05495
05496 if (insert)
05497 {
05498 QRect rect = region.boundingRect();
05499
05500 if (insertTo == -1 && numCols == 0 && numRows == 0)
05501 {
05502 rect.setWidth(rect.width());
05503 shiftRow(rect, false);
05504 }
05505
05506 else if (insertTo == 1 && numCols == 0 && numRows == 0)
05507 {
05508 rect.setHeight(rect.height());
05509 shiftColumn( rect, false );
05510 }
05511
05512 else if (insertTo == 0 && numCols == 0 && numRows > 0)
05513 {
05514 insertRow(rect.top(), rect.height() - 1, false);
05515 }
05516
05517 else if (insertTo == 0 && numCols > 0 && numRows == 0)
05518 {
05519 insertColumn(rect.left(), rect.width() - 1, false);
05520 }
05521 }
05522 }
05523
05524 bool Sheet::testAreaPasteInsert()const
05525 {
05526 QMimeSource* mime = QApplication::clipboard()->data( QClipboard::Clipboard );
05527 if ( !mime )
05528 return false;
05529
05530 QByteArray b;
05531
05532 if ( mime->provides( "application/x-kspread-snippet" ) )
05533 b = mime->encodedData( "application/x-kspread-snippet" );
05534 else
05535 return false;
05536
05537 QBuffer buffer( b );
05538 buffer.open( IO_ReadOnly );
05539 QDomDocument d;
05540 d.setContent( &buffer );
05541 buffer.close();
05542
05543 QDomElement e = d.documentElement();
05544 if ( !e.namedItem( "columns" ).toElement().isNull() )
05545 return false;
05546
05547 if ( !e.namedItem( "rows" ).toElement().isNull() )
05548 return false;
05549
05550 QDomElement c = e.firstChild().toElement();
05551 for( ; !c.isNull(); c = c.nextSibling().toElement() )
05552 {
05553 if ( c.tagName() == "cell" )
05554 return true;
05555 }
05556 return false;
05557 }
05558
05559 void Sheet::deleteCells(const Region& region)
05560 {
05561
05562 QPtrStack<Cell> cellStack;
05563
05564 Region::ConstIterator endOfList = region.constEnd();
05565 for (Region::ConstIterator it = region.constBegin(); it != endOfList; ++it)
05566 {
05567 QRect range = (*it)->rect().normalize();
05568
05569 int right = range.right();
05570 int left = range.left();
05571 int bottom = range.bottom();
05572 int col;
05573 for ( int row = range.top(); row <= bottom; ++row )
05574 {
05575 Cell * c = getFirstCellRow( row );
05576 while ( c )
05577 {
05578 col = c->column();
05579 if ( col < left )
05580 {
05581 c = getNextCellRight( left - 1, row );
05582 continue;
05583 }
05584 if ( col > right )
05585 break;
05586
05587 if ( !c->isDefault() )
05588 cellStack.push( c );
05589
05590 c = getNextCellRight( col, row );
05591 }
05592 }
05593 }
05594
05595 d->cells.setAutoDelete( false );
05596
05597
05598 while ( !cellStack.isEmpty() )
05599 {
05600 Cell * cell = cellStack.pop();
05601
05602 d->cells.remove( cell->column(), cell->row() );
05603 cell->setCalcDirtyFlag();
05604 setRegionPaintDirty(cell->cellRect());
05605
05606 delete cell;
05607 }
05608
05609 d->cells.setAutoDelete( true );
05610
05611 setLayoutDirtyFlag();
05612
05613
05614
05615
05616 Cell * c = d->cells.firstCell();
05617 for( ;c; c = c->nextCell() )
05618 {
05619 if ( c->doesMergeCells() && !c->isDefault() )
05620 c->mergeCells( c->column(), c->row(),
05621 c->extraXCells(), c->extraYCells() );
05622 }
05623 doc()->setModified( true );
05624 }
05625
05626 void Sheet::deleteSelection( Selection* selectionInfo, bool undo )
05627 {
05628 if ( undo && !doc()->undoLocked() )
05629 {
05630 UndoDelete *undo = new UndoDelete( doc(), this, *selectionInfo );
05631 doc()->addCommand( undo );
05632 }
05633
05634 Region::ConstIterator endOfList = selectionInfo->constEnd();
05635 for (Region::ConstIterator it = selectionInfo->constBegin(); it != endOfList; ++it)
05636 {
05637 QRect range = (*it)->rect().normalize();
05638
05639
05640 if ( util_isRowSelected(range) )
05641 {
05642 for( int i = range.top(); i <= range.bottom(); ++i )
05643 {
05644 d->cells.clearRow( i );
05645 d->rows.removeElement( i );
05646 }
05647
05648 emit sig_updateVBorder( this );
05649 }
05650
05651 else if ( util_isColumnSelected(range) )
05652 {
05653 for( int i = range.left(); i <= range.right(); ++i )
05654 {
05655 d->cells.clearColumn( i );
05656 d->columns.removeElement( i );
05657 }
05658
05659 emit sig_updateHBorder( this );
05660 }
05661 else
05662 {
05663 setRegionPaintDirty( range );
05664 deleteCells( range );
05665 }
05666 }
05667 refreshMergedCell();
05668 emit sig_updateView( this );
05669 }
05670
05671 void Sheet::updateView()
05672 {
05673 emit sig_updateView( this );
05674 }
05675
05676 void Sheet::updateView( QRect const & rect )
05677 {
05678 emit sig_updateView( this, rect );
05679 }
05680
05681 void Sheet::updateView(Region* region)
05682 {
05683 emit sig_updateView( this, *region );
05684 }
05685
05686 void Sheet::refreshView( const Region& region )
05687 {
05688 Region tmpRegion;
05689 Region::ConstIterator endOfList = region.constEnd();
05690 for (Region::ConstIterator it = region.constBegin(); it != endOfList; ++it)
05691 {
05692 QRect range = (*it)->rect().normalize();
05693
05694 QRect tmp(range);
05695 Cell * c = d->cells.firstCell();
05696 for( ;c; c = c->nextCell() )
05697 {
05698 if ( !c->isDefault() &&
05699 c->row() >= range.top() && c->row() <= range.bottom() &&
05700 c->column() >= range.left() && c->column() <= range.right() )
05701 {
05702 if (c->doesMergeCells())
05703 {
05704 int right=QMAX(tmp.right(),c->column()+c->extraXCells());
05705 int bottom=QMAX(tmp.bottom(),c->row()+c->extraYCells());
05706
05707 tmp.setRight(right);
05708 tmp.setBottom(bottom);
05709 }
05710 }
05711 }
05712 deleteCells( range );
05713 tmpRegion.add(tmp);
05714 }
05715 emit sig_updateView( this, tmpRegion );
05716 }
05717
05718
05719 void Sheet::mergeCells(const Region& region, bool hor, bool ver)
05720 {
05721
05722 if( isProtected() )
05723 return;
05724 if( workbook()->isProtected() )
05725 return;
05726
05727 MergeManipulator* manipulator = new MergeManipulator();
05728 manipulator->setSheet(this);
05729 manipulator->setHorizontalMerge(hor);
05730 manipulator->setVerticalMerge(ver);
05731 manipulator->add(region);
05732 manipulator->execute();
05733 }
05734
05735 void Sheet::dissociateCells(const Region& region)
05736 {
05737
05738 if( isProtected() )
05739 return;
05740 if( workbook()->isProtected() )
05741 return;
05742
05743 Manipulator* manipulator = new MergeManipulator();
05744 manipulator->setSheet(this);
05745 manipulator->setReverse(true);
05746 manipulator->add(region);
05747 manipulator->execute();
05748 }
05749
05750 bool Sheet::testListChoose(Selection* selectionInfo)
05751 {
05752 QRect selection( selectionInfo->selection() );
05753 QPoint marker( selectionInfo->marker() );
05754
05755 Cell *cell = cellAt( marker.x(), marker.y() );
05756 QString tmp=cell->text();
05757
05758 Cell* c = firstCell();
05759 bool different=false;
05760 int col;
05761 for( ;c; c = c->nextCell() )
05762 {
05763 col = c->column();
05764 if ( selection.left() <= col && selection.right() >= col &&
05765 !c->isPartOfMerged() &&
05766 !(col==marker.x() && c->row()==marker.y()))
05767 {
05768 if(!c->isFormula() && !c->value().isNumber() && !c->value().asString().isEmpty()
05769 && !c->isTime() &&!c->isDate() )
05770 {
05771 if(c->text()!=tmp)
05772 different=true;
05773 }
05774
05775 }
05776 }
05777 return different;
05778 }
05779
05780
05781
05782 QDomDocument Sheet::saveCellRegion(const Region& region, bool copy, bool era)
05783 {
05784 QDomDocument dd( "spreadsheet-snippet" );
05785 dd.appendChild( dd.createProcessingInstruction( "xml", "version=\"1.0\" encoding=\"UTF-8\"" ) );
05786 QDomElement root = dd.createElement( "spreadsheet-snippet" );
05787 dd.appendChild(root);
05788
05789
05790 QRect boundingRect = region.boundingRect();
05791 int left = boundingRect.left();
05792 int top = boundingRect.top();
05793
05794
05795 root.setAttribute( "rows", boundingRect.height() );
05796 root.setAttribute( "columns", boundingRect.width() );
05797
05798 Region::ConstIterator endOfList = region.constEnd();
05799 for (Region::ConstIterator it = region.constBegin(); it != endOfList; ++it)
05800 {
05801 QRect range = (*it)->rect().normalize();
05802
05803
05804
05805
05806 if ((*it)->isRow())
05807 {
05808 QDomElement rows = dd.createElement("rows");
05809 rows.setAttribute( "count", range.height() );
05810 rows.setAttribute( "row", range.top() - top + 1 );
05811 root.appendChild( rows );
05812
05813
05814 for (Cell* cell = d->cells.firstCell(); cell; cell = cell->nextCell())
05815 {
05816 if (!cell->isDefault() && !cell->isPartOfMerged())
05817 {
05818 QPoint point(cell->column(), cell->row());
05819 if (range.contains(point))
05820 {
05821 root.appendChild(cell->save( dd, 0, top - 1, copy, copy, era));
05822 }
05823 }
05824 }
05825
05826
05827
05828 RowFormat* format;
05829 for (int row = range.top(); row <= range.bottom(); ++row)
05830 {
05831 format = rowFormat( row );
05832 if (format && !format->isDefault())
05833 {
05834 QDomElement e = format->save(dd, top - 1, copy);
05835 if (!e.isNull())
05836 {
05837 rows.appendChild( e );
05838 }
05839 }
05840 }
05841 continue;
05842 }
05843
05844
05845
05846
05847 if ((*it)->isColumn())
05848 {
05849 QDomElement columns = dd.createElement("columns");
05850 columns.setAttribute( "count", range.width() );
05851 columns.setAttribute( "column", range.left() - left + 1 );
05852 root.appendChild( columns );
05853
05854
05855 for (Cell* cell = d->cells.firstCell();cell; cell = cell->nextCell())
05856 {
05857 if (!cell->isDefault() && !cell->isPartOfMerged())
05858 {
05859 QPoint point(cell->column(), cell->row());
05860 if (range.contains(point))
05861 {
05862 root.appendChild(cell->save( dd, left - 1, 0, copy, copy, era));
05863 }
05864 }
05865 }
05866
05867
05868
05869 ColumnFormat* format;
05870 for (int col = range.left(); col <= range.right(); ++col)
05871 {
05872 format = columnFormat(col);
05873 if (format && !format->isDefault())
05874 {
05875 QDomElement e = format->save(dd, left - 1, copy);
05876 if (!e.isNull())
05877 {
05878 columns.appendChild(e);
05879 }
05880 }
05881 }
05882 continue;
05883 }
05884
05885
05886
05887
05888
05889
05890 Cell* cell;
05891 bool insert;
05892 enableScrollBarUpdates(false);
05893 for (int col = range.left(); col <= range.right(); ++col)
05894 {
05895 for (int row = range.top(); row <= range.bottom(); ++row)
05896 {
05897 insert = false;
05898 cell = cellAt(col, row);
05899 if (cell == d->defaultCell)
05900 {
05901 cell = new Cell(this, col, row);
05902 insertCell(cell);
05903 insert = true;
05904 }
05905 root.appendChild(cell->save(dd, left - 1, top - 1, true, copy, era));
05906 if (insert)
05907 {
05908 d->cells.remove(col, row);
05909 }
05910 }
05911 }
05912 enableScrollBarUpdates(true);
05913 }
05914 return dd;
05915 }
05916
05917 QDomElement Sheet::saveXML( QDomDocument& dd )
05918 {
05919 QDomElement sheet = dd.createElement( "table" );
05920 sheet.setAttribute( "name", d->name );
05921
05922
05923
05924 sheet.setAttribute( "layoutDirection", (d->layoutDirection == RightToLeft) ? "rtl" : "ltr" );
05925 sheet.setAttribute( "columnnumber", (int)d->showColumnNumber);
05926 sheet.setAttribute( "borders", (int)d->showPageBorders);
05927 sheet.setAttribute( "hide", (int)d->hide);
05928 sheet.setAttribute( "hidezero", (int)d->hideZero);
05929 sheet.setAttribute( "firstletterupper", (int)d->firstLetterUpper);
05930 sheet.setAttribute( "grid", (int)d->showGrid );
05931 sheet.setAttribute( "printGrid", (int)d->print->printGrid() );
05932 sheet.setAttribute( "printCommentIndicator", (int)d->print->printCommentIndicator() );
05933 sheet.setAttribute( "printFormulaIndicator", (int)d->print->printFormulaIndicator() );
05934 sheet.setAttribute( "showFormula", (int)d->showFormula);
05935 sheet.setAttribute( "showFormulaIndicator", (int)d->showFormulaIndicator);
05936 sheet.setAttribute( "showCommentIndicator", (int)d->showCommentIndicator);
05937 sheet.setAttribute( "lcmode", (int)d->lcMode);
05938 sheet.setAttribute( "autoCalc", (int)d->autoCalc);
05939 sheet.setAttribute( "borders1.2", 1);
05940 if ( !d->password.isNull() )
05941 {
05942 if ( d->password.size() > 0 )
05943 {
05944 QCString str = KCodecs::base64Encode( d->password );
05945 sheet.setAttribute( "protected", QString( str.data() ) );
05946 }
05947 else
05948 sheet.setAttribute( "protected", "" );
05949 }
05950
05951
05952 QDomElement paper = dd.createElement( "paper" );
05953 paper.setAttribute( "format", d->print->paperFormatString() );
05954 paper.setAttribute( "orientation", d->print->orientationString() );
05955 sheet.appendChild( paper );
05956
05957 QDomElement borders = dd.createElement( "borders" );
05958 borders.setAttribute( "left", d->print->leftBorder() );
05959 borders.setAttribute( "top", d->print->topBorder() );
05960 borders.setAttribute( "right", d->print->rightBorder() );
05961 borders.setAttribute( "bottom", d->print->bottomBorder() );
05962 paper.appendChild( borders );
05963
05964 QDomElement head = dd.createElement( "head" );
05965 paper.appendChild( head );
05966 if ( !d->print->headLeft().isEmpty() )
05967 {
05968 QDomElement left = dd.createElement( "left" );
05969 head.appendChild( left );
05970 left.appendChild( dd.createTextNode( d->print->headLeft() ) );
05971 }
05972 if ( !d->print->headMid().isEmpty() )
05973 {
05974 QDomElement center = dd.createElement( "center" );
05975 head.appendChild( center );
05976 center.appendChild( dd.createTextNode( d->print->headMid() ) );
05977 }
05978 if ( !d->print->headRight().isEmpty() )
05979 {
05980 QDomElement right = dd.createElement( "right" );
05981 head.appendChild( right );
05982 right.appendChild( dd.createTextNode( d->print->headRight() ) );
05983 }
05984 QDomElement foot = dd.createElement( "foot" );
05985 paper.appendChild( foot );
05986 if ( !d->print->footLeft().isEmpty() )
05987 {
05988 QDomElement left = dd.createElement( "left" );
05989 foot.appendChild( left );
05990 left.appendChild( dd.createTextNode( d->print->footLeft() ) );
05991 }
05992 if ( !d->print->footMid().isEmpty() )
05993 {
05994 QDomElement center = dd.createElement( "center" );
05995 foot.appendChild( center );
05996 center.appendChild( dd.createTextNode( d->print->footMid() ) );
05997 }
05998 if ( !d->print->footRight().isEmpty() )
05999 {
06000 QDomElement right = dd.createElement( "right" );
06001 foot.appendChild( right );
06002 right.appendChild( dd.createTextNode( d->print->footRight() ) );
06003 }
06004
06005
06006 QDomElement printrange = dd.createElement( "printrange-rect" );
06007 QRect _printRange = d->print->printRange();
06008 int left = _printRange.left();
06009 int right = _printRange.right();
06010 int top = _printRange.top();
06011 int bottom = _printRange.bottom();
06012
06013 if ( left == 1 && right == KS_colMax )
06014 {
06015 left = 0;
06016 right = 0;
06017 }
06018
06019 if ( top == 1 && bottom == KS_rowMax )
06020 {
06021 top = 0;
06022 bottom = 0;
06023 }
06024 printrange.setAttribute( "left-rect", left );
06025 printrange.setAttribute( "right-rect", right );
06026 printrange.setAttribute( "bottom-rect", bottom );
06027 printrange.setAttribute( "top-rect", top );
06028 sheet.appendChild( printrange );
06029
06030
06031 QDomElement printRepeatColumns = dd.createElement( "printrepeatcolumns" );
06032 printRepeatColumns.setAttribute( "left", d->print->printRepeatColumns().first );
06033 printRepeatColumns.setAttribute( "right", d->print->printRepeatColumns().second );
06034 sheet.appendChild( printRepeatColumns );
06035
06036
06037 QDomElement printRepeatRows = dd.createElement( "printrepeatrows" );
06038 printRepeatRows.setAttribute( "top", d->print->printRepeatRows().first );
06039 printRepeatRows.setAttribute( "bottom", d->print->printRepeatRows().second );
06040 sheet.appendChild( printRepeatRows );
06041
06042
06043 sheet.setAttribute( "printZoom", d->print->zoom() );
06044
06045
06046 sheet.setAttribute( "printPageLimitX", d->print->pageLimitX() );
06047 sheet.setAttribute( "printPageLimitY", d->print->pageLimitY() );
06048
06049
06050 Cell* c = d->cells.firstCell();
06051 for( ;c; c = c->nextCell() )
06052 {
06053 if ( !c->isDefault() )
06054 {
06055 QDomElement e = c->save( dd );
06056 if ( !e.isNull() )
06057 sheet.appendChild( e );
06058 }
06059 }
06060
06061
06062 RowFormat* rl = d->rows.first();
06063 for( ; rl; rl = rl->next() )
06064 {
06065 if ( !rl->isDefault() )
06066 {
06067 QDomElement e = rl->save( dd );
06068 if ( e.isNull() )
06069 return QDomElement();
06070 sheet.appendChild( e );
06071 }
06072 }
06073
06074
06075 ColumnFormat* cl = d->columns.first();
06076 for( ; cl; cl = cl->next() )
06077 {
06078 if ( !cl->isDefault() )
06079 {
06080 QDomElement e = cl->save( dd );
06081 if ( e.isNull() )
06082 return QDomElement();
06083 sheet.appendChild( e );
06084 }
06085 }
06086
06087 QPtrListIterator<EmbeddedObject> chl = doc()->embeddedObjects();
06088 for( ; chl.current(); ++chl )
06089 {
06090 if ( chl.current()->sheet() == this )
06091 {
06092 QDomElement e = chl.current()->save( dd );
06093
06094 if ( e.isNull() )
06095 return QDomElement();
06096 sheet.appendChild( e );
06097 }
06098 }
06099 return sheet;
06100 }
06101
06102 bool Sheet::isLoading()
06103 {
06104 return doc()->isLoading();
06105 }
06106
06107
06108 QPtrList<EmbeddedObject> Sheet::getSelectedObjects()
06109 {
06110 QPtrList<EmbeddedObject> objects;
06111 QPtrListIterator<EmbeddedObject> it = doc()->embeddedObjects();
06112 for ( ; it.current() ; ++it )
06113 {
06114 if( it.current()->isSelected()
06115 && it.current()->sheet() == this )
06116 {
06117 objects.append( it.current() );
06118 }
06119 }
06120 return objects;
06121 }
06122
06123 KoRect Sheet::getRealRect( bool all )
06124 {
06125 KoRect rect;
06126
06127 QPtrListIterator<EmbeddedObject> it( doc()->embeddedObjects() );
06128 for ( ; it.current() ; ++it )
06129 {
06130
06131 if ( all || ( it.current()->isSelected() && ! it.current()->isProtect() ) )
06132 rect |= it.current()->geometry();
06133 }
06134
06135 return rect;
06136 }
06137
06138
06139 KCommand *Sheet::moveObject(View *_view, double diffx, double diffy)
06140 {
06141 bool createCommand=false;
06142 MoveObjectByCmd *moveByCmd=0L;
06143 Canvas * canvas = _view->canvasWidget();
06144 QPtrList<EmbeddedObject> _objects;
06145 _objects.setAutoDelete( false );
06146 QPtrListIterator<EmbeddedObject> it( doc()->embeddedObjects() );
06147 for ( ; it.current() ; ++it )
06148 {
06149 if ( it.current()->isSelected() && !it.current()->isProtect())
06150 {
06151 _objects.append( it.current() );
06152 KoRect geometry = it.current()->geometry();
06153 geometry.moveBy( -canvas->xOffset(), -canvas->yOffset() );
06154 QRect br = doc()->zoomRect( geometry );
06155 br.moveBy( doc()->zoomItX( diffx ), doc()->zoomItY( diffy ) );
06156 br.moveBy( doc()->zoomItX( -canvas->xOffset() ), doc()->zoomItY( -canvas->yOffset() ) );
06157 canvas->repaint( br );
06158 canvas->repaintObject( it.current() );
06159 createCommand=true;
06160 }
06161 }
06162 if(createCommand) {
06163 moveByCmd = new MoveObjectByCmd( i18n( "Move Objects" ), KoPoint( diffx, diffy ),
06164 _objects, doc(), this );
06165
06166
06167 }
06168 return moveByCmd;
06169 }
06170
06171 KCommand *Sheet::moveObject(View *_view,const KoPoint &_move,bool key)
06172 {
06173 QPtrList<EmbeddedObject> _objects;
06174 _objects.setAutoDelete( false );
06175 MoveObjectByCmd *moveByCmd=0L;
06176 Canvas * canvas = _view->canvasWidget();
06177 QPtrListIterator<EmbeddedObject> it( doc()->embeddedObjects() );
06178 for ( ; it.current() ; ++it )
06179 {
06180 if ( it.current()->isSelected() && !it.current()->isProtect()) {
06181
06182 KoRect geometry = it.current()->geometry();
06183 geometry.moveBy( -canvas->xOffset(), -canvas->yOffset() );
06184 QRect oldBoundingRect = doc()->zoomRect( geometry );
06185
06186
06187 KoRect r = it.current()->geometry();
06188 r.moveBy( _move.x(), _move.y() );
06189
06190 it.current()->setGeometry( r );
06191 _objects.append( it.current() );
06192
06193 canvas->repaint( oldBoundingRect );
06194 canvas->repaintObject( it.current() );
06195 }
06196 }
06197
06198 if ( key && !_objects.isEmpty())
06199 moveByCmd = new MoveObjectByCmd( i18n( "Move Objects" ),
06200 KoPoint( _move ),
06201 _objects, doc() ,this );
06202
06203 return moveByCmd;
06204 }
06205
06206
06207
06208
06209 bool Sheet::objectNameExists( EmbeddedObject *object, QPtrList<EmbeddedObject> &list ) {
06210 QPtrListIterator<EmbeddedObject> it( list );
06211
06212 for ( it.toFirst(); it.current(); ++it ) {
06213
06214 if ( it.current()->getObjectName() == object->getObjectName() &&
06215 it.current() != object ) {
06216 return true;
06217 }
06218 }
06219 return false;
06220 }
06221
06222 void Sheet::unifyObjectName( EmbeddedObject *object ) {
06223 if ( object->getObjectName().isEmpty() ) {
06224 object->setObjectName( object->getTypeString() );
06225 }
06226 QString objectName( object->getObjectName() );
06227
06228 QPtrList<EmbeddedObject> list( doc()->embeddedObjects() );
06229
06230 int count = 1;
06231
06232 while ( objectNameExists( object, list ) ) {
06233 count++;
06234 QRegExp rx( " \\(\\d{1,3}\\)$" );
06235 if ( rx.search( objectName ) != -1 ) {
06236 objectName.remove( rx );
06237 }
06238 objectName += QString(" (%1)").arg( count );
06239 object->setObjectName( objectName );
06240 }
06241 }
06242
06243
06244 void Sheet::checkContentDirection( QString const & name )
06245 {
06246
06247 if ( (name.isRightToLeft()) )
06248 setLayoutDirection( RightToLeft );
06249 else
06250 setLayoutDirection( LeftToRight );
06251
06252 emit sig_refreshView();
06253 }
06254
06255 bool Sheet::loadSheetStyleFormat( QDomElement *style )
06256 {
06257 QString hleft, hmiddle, hright;
06258 QString fleft, fmiddle, fright;
06259 QDomNode header = KoDom::namedItemNS( *style, KoXmlNS::style, "header" );
06260
06261 if ( !header.isNull() )
06262 {
06263 kdDebug() << "Header exists" << endl;
06264 QDomNode part = KoDom::namedItemNS( header, KoXmlNS::style, "region-left" );
06265 if ( !part.isNull() )
06266 {
06267 hleft = getPart( part );
06268 kdDebug() << "Header left: " << hleft << endl;
06269 }
06270 else
06271 kdDebug() << "Style:region:left doesn't exist!" << endl;
06272 part = KoDom::namedItemNS( header, KoXmlNS::style, "region-center" );
06273 if ( !part.isNull() )
06274 {
06275 hmiddle = getPart( part );
06276 kdDebug() << "Header middle: " << hmiddle << endl;
06277 }
06278 part = KoDom::namedItemNS( header, KoXmlNS::style, "region-right" );
06279 if ( !part.isNull() )
06280 {
06281 hright = getPart( part );
06282 kdDebug() << "Header right: " << hright << endl;
06283 }
06284 }
06285
06286 QDomNode headerleft = KoDom::namedItemNS( *style, KoXmlNS::style, "header-left" );
06287 if ( !headerleft.isNull() )
06288 {
06289 QDomElement e = headerleft.toElement();
06290 if ( e.hasAttributeNS( KoXmlNS::style, "display" ) )
06291 kdDebug()<<"header.hasAttribute( style:display ) :"<<e.hasAttributeNS( KoXmlNS::style, "display" )<<endl;
06292 else
06293 kdDebug()<<"header left doesn't has attribute style:display \n";
06294 }
06295
06296 QDomNode footerleft = KoDom::namedItemNS( *style, KoXmlNS::style, "footer-left" );
06297 if ( !footerleft.isNull() )
06298 {
06299 QDomElement e = footerleft.toElement();
06300 if ( e.hasAttributeNS( KoXmlNS::style, "display" ) )
06301 kdDebug()<<"footer.hasAttribute( style:display ) :"<<e.hasAttributeNS( KoXmlNS::style, "display" )<<endl;
06302 else
06303 kdDebug()<<"footer left doesn't has attribute style:display \n";
06304 }
06305
06306 QDomNode footer = KoDom::namedItemNS( *style, KoXmlNS::style, "footer" );
06307
06308 if ( !footer.isNull() )
06309 {
06310 QDomNode part = KoDom::namedItemNS( footer, KoXmlNS::style, "region-left" );
06311 if ( !part.isNull() )
06312 {
06313 fleft = getPart( part );
06314 kdDebug() << "Footer left: " << fleft << endl;
06315 }
06316 part = KoDom::namedItemNS( footer, KoXmlNS::style, "region-center" );
06317 if ( !part.isNull() )
06318 {
06319 fmiddle = getPart( part );
06320 kdDebug() << "Footer middle: " << fmiddle << endl;
06321 }
06322 part = KoDom::namedItemNS( footer, KoXmlNS::style, "region-right" );
06323 if ( !part.isNull() )
06324 {
06325 fright = getPart( part );
06326 kdDebug() << "Footer right: " << fright << endl;
06327 }
06328 }
06329
06330 print()->setHeadFootLine( hleft, hmiddle, hright,
06331 fleft, fmiddle, fright );
06332 return true;
06333 }
06334
06335 void Sheet::replaceMacro( QString & text, const QString & old, const QString & newS )
06336 {
06337 int n = text.find( old );
06338 if ( n != -1 )
06339 text = text.replace( n, old.length(), newS );
06340 }
06341
06342
06343 QString Sheet::getPart( const QDomNode & part )
06344 {
06345 QString result;
06346 QDomElement e = KoDom::namedItemNS( part, KoXmlNS::text, "p" );
06347 while ( !e.isNull() )
06348 {
06349 QString text = e.text();
06350 kdDebug() << "PART: " << text << endl;
06351
06352 QDomElement macro = KoDom::namedItemNS( e, KoXmlNS::text, "time" );
06353 if ( !macro.isNull() )
06354 replaceMacro( text, macro.text(), "<time>" );
06355
06356 macro = KoDom::namedItemNS( e, KoXmlNS::text, "date" );
06357 if ( !macro.isNull() )
06358 replaceMacro( text, macro.text(), "<date>" );
06359
06360 macro = KoDom::namedItemNS( e, KoXmlNS::text, "page-number" );
06361 if ( !macro.isNull() )
06362 replaceMacro( text, macro.text(), "<page>" );
06363
06364 macro = KoDom::namedItemNS( e, KoXmlNS::text, "page-count" );
06365 if ( !macro.isNull() )
06366 replaceMacro( text, macro.text(), "<pages>" );
06367
06368 macro = KoDom::namedItemNS( e, KoXmlNS::text, "sheet-name" );
06369 if ( !macro.isNull() )
06370 replaceMacro( text, macro.text(), "<sheet>" );
06371
06372 macro = KoDom::namedItemNS( e, KoXmlNS::text, "title" );
06373 if ( !macro.isNull() )
06374 replaceMacro( text, macro.text(), "<name>" );
06375
06376 macro = KoDom::namedItemNS( e, KoXmlNS::text, "file-name" );
06377 if ( !macro.isNull() )
06378 replaceMacro( text, macro.text(), "<file>" );
06379
06380
06381 if ( !result.isEmpty() )
06382 result += '\n';
06383 result += text;
06384 e = e.nextSibling().toElement();
06385 }
06386
06387 return result;
06388 }
06389
06390
06391 bool Sheet::loadOasis( const QDomElement& sheetElement, KoOasisLoadingContext& oasisContext, QDict<Style>& styleMap )
06392 {
06393 d->layoutDirection = LeftToRight;
06394 if ( sheetElement.hasAttributeNS( KoXmlNS::table, "style-name" ) )
06395 {
06396 QString stylename = sheetElement.attributeNS( KoXmlNS::table, "style-name", QString::null );
06397
06398 const QDomElement *style = oasisContext.oasisStyles().findStyle( stylename, "table" );
06399 Q_ASSERT( style );
06400
06401 if ( style )
06402 {
06403 QDomElement properties( KoDom::namedItemNS( *style, KoXmlNS::style, "table-properties" ) );
06404 if ( !properties.isNull() )
06405 {
06406 if ( properties.hasAttributeNS( KoXmlNS::table, "display" ) )
06407 {
06408 bool visible = (properties.attributeNS( KoXmlNS::table, "display", QString::null ) == "true" ? true : false );
06409 d->hide = !visible;
06410 }
06411 }
06412 if ( style->hasAttributeNS( KoXmlNS::style, "master-page-name" ) )
06413 {
06414 QString masterPageStyleName = style->attributeNS( KoXmlNS::style, "master-page-name", QString::null );
06415
06416 QDomElement *masterStyle = oasisContext.oasisStyles().masterPages()[masterPageStyleName];
06417
06418 if ( masterStyle )
06419 {
06420 loadSheetStyleFormat( masterStyle );
06421 if ( masterStyle->hasAttributeNS( KoXmlNS::style, "page-layout-name" ) )
06422 {
06423 QString masterPageLayoutStyleName = masterStyle->attributeNS( KoXmlNS::style, "page-layout-name", QString::null );
06424
06425 const QDomElement *masterLayoutStyle = oasisContext.oasisStyles().findStyle( masterPageLayoutStyleName );
06426 if ( masterLayoutStyle )
06427 {
06428
06429 KoStyleStack styleStack;
06430 styleStack.setTypeProperties( "page-layout" );
06431 styleStack.push( *masterLayoutStyle );
06432 loadOasisMasterLayoutPage( styleStack );
06433 }
06434 }
06435 }
06436 }
06437 }
06438 }
06439
06440
06441 QMap<int,QString> defaultColumnCellStyles;
06442
06443 int rowIndex = 1;
06444 int indexCol = 1;
06445 QDomNode rowNode = sheetElement.firstChild();
06446
06447
06448
06449 while( !rowNode.isNull() && rowIndex <= KS_rowMax )
06450 {
06451 kdDebug()<<" rowIndex :"<<rowIndex<<" indexCol :"<<indexCol<<endl;
06452 QDomElement rowElement = rowNode.toElement();
06453 if( !rowElement.isNull() )
06454 {
06455 kdDebug()<<" Sheet::loadOasis rowElement.tagName() :"<<rowElement.localName()<<endl;
06456 if ( rowElement.namespaceURI() == KoXmlNS::table )
06457 {
06458 if ( rowElement.localName()=="table-column" && indexCol <= KS_colMax )
06459 {
06460 kdDebug ()<<" table-column found : index column before "<< indexCol<<endl;
06461 loadColumnFormat( rowElement, oasisContext.oasisStyles(), indexCol , styleMap);
06462 kdDebug ()<<" table-column found : index column after "<< indexCol<<endl;
06463 }
06464 else if ( rowElement.localName() == "table-header-rows" )
06465 {
06466 QDomNode headerRowNode = rowElement.firstChild();
06467 while ( !headerRowNode.isNull() )
06468 {
06469
06470
06471 loadRowFormat( headerRowNode.toElement(), rowIndex,
06472 oasisContext, styleMap );
06473 headerRowNode = headerRowNode.nextSibling();
06474 }
06475 }
06476 else if( rowElement.localName() == "table-row" )
06477 {
06478 kdDebug()<<" table-row found :index row before "<<rowIndex<<endl;
06479 loadRowFormat( rowElement, rowIndex, oasisContext, styleMap );
06480 kdDebug()<<" table-row found :index row after "<<rowIndex<<endl;
06481 }
06482 else if ( rowElement.localName() == "shapes" )
06483 loadOasisObjects( rowElement, oasisContext );
06484 }
06485 }
06486 rowNode = rowNode.nextSibling();
06487 }
06488
06489 if ( sheetElement.hasAttributeNS( KoXmlNS::table, "print-ranges" ) )
06490 {
06491
06492 QString range = sheetElement.attributeNS( KoXmlNS::table, "print-ranges", QString::null );
06493 range = Oasis::decodeFormula( range );
06494 Range p( range );
06495 if ( sheetName() == p.sheetName() )
06496 d->print->setPrintRange( p.range() );
06497 }
06498
06499
06500 if ( sheetElement.attributeNS( KoXmlNS::table, "protected", QString::null ) == "true" )
06501 {
06502 QCString passwd( "" );
06503 if ( sheetElement.hasAttributeNS( KoXmlNS::table, "protection-key" ) )
06504 {
06505 QString p = sheetElement.attributeNS( KoXmlNS::table, "protection-key", QString::null );
06506 QCString str( p.latin1() );
06507 kdDebug(30518) << "Decoding password: " << str << endl;
06508 passwd = KCodecs::base64Decode( str );
06509 }
06510 kdDebug(30518) << "Password hash: '" << passwd << "'" << endl;
06511 d->password = passwd;
06512 }
06513 return true;
06514 }
06515
06516
06517 void Sheet::loadOasisObjects( const QDomElement &parent, KoOasisLoadingContext& oasisContext )
06518 {
06519 QDomElement e;
06520 QDomNode n = parent.firstChild();
06521 while( !n.isNull() )
06522 {
06523 e = n.toElement();
06524 if ( e.localName() == "frame" && e.namespaceURI() == KoXmlNS::draw )
06525 {
06526 EmbeddedObject *obj = 0;
06527 QDomNode object = KoDom::namedItemNS( e, KoXmlNS::draw, "object" );
06528 if ( !object.isNull() )
06529 {
06530 if ( !object.toElement().attributeNS( KoXmlNS::draw, "notify-on-update-of-ranges", QString::null).isNull() )
06531 obj = new EmbeddedChart( doc(), this );
06532 else
06533 obj = new EmbeddedKOfficeObject( doc(), this );
06534 }
06535 else
06536 {
06537 QDomNode image = KoDom::namedItemNS( e, KoXmlNS::draw, "image" );
06538 if ( !image.isNull() )
06539 obj = new EmbeddedPictureObject( this, doc()->pictureCollection() );
06540 else
06541 kdDebug() << "Object type wasn't loaded!" << endl;
06542 }
06543
06544 if ( obj )
06545 {
06546 obj->loadOasis( e, oasisContext );
06547 insertObject( obj );
06548 }
06549 }
06550 n = n.nextSibling();
06551 }
06552 }
06553
06554
06555 void Sheet::loadOasisMasterLayoutPage( KoStyleStack &styleStack )
06556 {
06557
06558 float left = 20.0;
06559 float right = 20.0;
06560 float top = 20.0;
06561 float bottom = 20.0;
06562 float width = 210.0;
06563 float height = 297.0;
06564 QString orientation = "Portrait";
06565 QString format;
06566
06567
06568
06569
06570 if ( styleStack.hasAttributeNS( KoXmlNS::fo, "page-width" ) )
06571 {
06572 width = KoUnit::toMM(KoUnit::parseValue( styleStack.attributeNS( KoXmlNS::fo, "page-width" ) ) );
06573 }
06574 if ( styleStack.hasAttributeNS( KoXmlNS::fo, "page-height" ) )
06575 {
06576 height = KoUnit::toMM( KoUnit::parseValue( styleStack.attributeNS( KoXmlNS::fo, "page-height" ) ) );
06577 }
06578 if ( styleStack.hasAttributeNS( KoXmlNS::fo, "margin-top" ) )
06579 {
06580 top = KoUnit::toMM(KoUnit::parseValue( styleStack.attributeNS( KoXmlNS::fo, "margin-top" ) ) );
06581 }
06582 if ( styleStack.hasAttributeNS( KoXmlNS::fo, "margin-bottom" ) )
06583 {
06584 bottom = KoUnit::toMM(KoUnit::parseValue( styleStack.attributeNS( KoXmlNS::fo, "margin-bottom" ) ) );
06585 }
06586 if ( styleStack.hasAttributeNS( KoXmlNS::fo, "margin-left" ) )
06587 {
06588 left = KoUnit::toMM(KoUnit::parseValue( styleStack.attributeNS( KoXmlNS::fo, "margin-left" ) ) );
06589 }
06590 if ( styleStack.hasAttributeNS( KoXmlNS::fo, "margin-right" ) )
06591 {
06592 right = KoUnit::toMM(KoUnit::parseValue( styleStack.attributeNS( KoXmlNS::fo, "margin-right" ) ) );
06593 }
06594 if ( styleStack.hasAttributeNS( KoXmlNS::style, "writing-mode" ) )
06595 {
06596 kdDebug()<<"styleStack.hasAttribute( style:writing-mode ) :"<<styleStack.hasAttributeNS( KoXmlNS::style, "writing-mode" )<<endl;
06597 d->layoutDirection = ( styleStack.attributeNS( KoXmlNS::style, "writing-mode" )=="lr-tb" ) ? LeftToRight : RightToLeft;
06598
06599
06600
06601
06602
06603
06604
06605
06606
06607
06608 }
06609 if ( styleStack.hasAttributeNS( KoXmlNS::style, "print-orientation" ) )
06610 {
06611 orientation = ( styleStack.attributeNS( KoXmlNS::style, "print-orientation" )=="landscape" ) ? "Landscape" : "Portrait" ;
06612 }
06613 if ( styleStack.hasAttributeNS( KoXmlNS::style, "num-format" ) )
06614 {
06615
06616
06617
06618
06619 kdDebug()<<" num-format :"<<styleStack.attributeNS( KoXmlNS::style, "num-format" )<<endl;
06620
06621 }
06622 if ( styleStack.hasAttributeNS( KoXmlNS::fo, "background-color" ) )
06623 {
06624
06625 kdDebug()<<" fo:background-color :"<<styleStack.attributeNS( KoXmlNS::fo, "background-color" )<<endl;
06626 }
06627 if ( styleStack.hasAttributeNS( KoXmlNS::style, "print" ) )
06628 {
06629
06630 QString str = styleStack.attributeNS( KoXmlNS::style, "print" );
06631 kdDebug()<<" style:print :"<<str<<endl;
06632
06633 if (str.contains( "headers" ) )
06634 {
06635
06636 }
06637 if ( str.contains( "grid" ) )
06638 {
06639 d->print->setPrintGrid( true );
06640 }
06641 if ( str.contains( "annotations" ) )
06642 {
06643
06644 }
06645 if ( str.contains( "objects" ) )
06646 {
06647
06648 }
06649 if ( str.contains( "charts" ) )
06650 {
06651
06652 }
06653 if ( str.contains( "drawings" ) )
06654 {
06655
06656 }
06657 if ( str.contains( "formulas" ) )
06658 {
06659 d->showFormula = true;
06660 }
06661 if ( str.contains( "zero-values" ) )
06662 {
06663
06664 }
06665 }
06666 if ( styleStack.hasAttributeNS( KoXmlNS::style, "table-centering" ) )
06667 {
06668 QString str = styleStack.attributeNS( KoXmlNS::style, "table-centering" );
06669
06670 kdDebug()<<" styleStack.attribute( style:table-centering ) :"<<str<<endl;
06671 #if 0
06672 if ( str == "horizontal" )
06673 {
06674 }
06675 else if ( str == "vertical" )
06676 {
06677 }
06678 else if ( str == "both" )
06679 {
06680 }
06681 else if ( str == "none" )
06682 {
06683 }
06684 else
06685 kdDebug()<<" table-centering unknown :"<<str<<endl;
06686 #endif
06687 }
06688 format = QString( "%1x%2" ).arg( width ).arg( height );
06689 kdDebug()<<" format : "<<format<<endl;
06690 d->print->setPaperLayout( left, top, right, bottom, format, orientation );
06691
06692 kdDebug()<<" left margin :"<<left<<" right :"<<right<<" top :"<<top<<" bottom :"<<bottom<<endl;
06693
06694
06695
06696
06697
06698 }
06699
06700
06701 bool Sheet::loadColumnFormat(const QDomElement& column, const KoOasisStyles& oasisStyles, int & indexCol, const QDict<Style>& styleMap)
06702 {
06703 kdDebug()<<"bool Sheet::loadColumnFormat(const QDomElement& column, const KoOasisStyles& oasisStyles, unsigned int & indexCol ) index Col :"<<indexCol<<endl;
06704
06705 bool isNonDefaultColumn = false;
06706
06707 int number = 1;
06708 if ( column.hasAttributeNS( KoXmlNS::table, "number-columns-repeated" ) )
06709 {
06710 bool ok = true;
06711 int n = column.attributeNS( KoXmlNS::table, "number-columns-repeated", QString::null ).toInt( &ok );
06712 if ( ok )
06713
06714
06715
06716 number = QMIN( n, KS_colMax - indexCol + 1 );
06717 kdDebug() << "Repeated: " << number << endl;
06718 }
06719
06720 Format layout( this , doc()->styleManager()->defaultStyle() );
06721 if ( column.hasAttributeNS( KoXmlNS::table, "default-cell-style-name" ) )
06722 {
06723 const QString styleName = column.attributeNS( KoXmlNS::table, "default-cell-style-name", QString::null );
06724 if ( !styleName.isEmpty() )
06725 {
06726 Style* const style = styleMap[ styleName ];
06727 if ( style )
06728 {
06729 layout.setStyle( style );
06730 isNonDefaultColumn = true;
06731 }
06732 }
06733 }
06734
06735 bool collapsed = false;
06736 if ( column.hasAttributeNS( KoXmlNS::table, "visibility" ) )
06737 {
06738 const QString visibility = column.attributeNS( KoXmlNS::table, "visibility", QString::null );
06739 if ( visibility == "visible" )
06740 collapsed = false;
06741 else if ( visibility == "collapse" )
06742 collapsed = true;
06743 else if ( visibility == "filter" )
06744 collapsed = false;
06745 isNonDefaultColumn = true;
06746 }
06747
06748 KoStyleStack styleStack;
06749 if ( column.hasAttributeNS( KoXmlNS::table, "style-name" ) )
06750 {
06751 QString str = column.attributeNS( KoXmlNS::table, "style-name", QString::null );
06752 const QDomElement *style = oasisStyles.findStyle( str, "table-column" );
06753 if ( style )
06754 {
06755 styleStack.push( *style );
06756 isNonDefaultColumn = true;
06757 }
06758 }
06759 styleStack.setTypeProperties("table-column");
06760
06761 double width = -1.0;
06762 if ( styleStack.hasAttributeNS( KoXmlNS::style, "column-width" ) )
06763 {
06764 width = KoUnit::parseValue( styleStack.attributeNS( KoXmlNS::style, "column-width" ) , -1.0 );
06765 kdDebug()<<" style:column-width : width :"<<width<<endl;
06766 isNonDefaultColumn = true;
06767 }
06768
06769 bool insertPageBreak = false;
06770 if ( styleStack.hasAttributeNS( KoXmlNS::fo, "break-before" ) )
06771 {
06772 QString str = styleStack.attributeNS( KoXmlNS::fo, "break-before" );
06773 if ( str == "page" )
06774 {
06775 insertPageBreak = true;
06776 }
06777 else
06778 kdDebug()<<" str :"<<str<<endl;
06779 isNonDefaultColumn = true;
06780 }
06781
06782 for ( int i = 0; i < number; ++i )
06783 {
06784
06785
06786 ColumnFormat* columnFormat;
06787 if ( isNonDefaultColumn )
06788 {
06789 columnFormat = nonDefaultColumnFormat( indexCol );
06790
06791 if ( width != -1.0 )
06792 columnFormat->setWidth( (int) width );
06793
06794
06795 if ( collapsed )
06796 columnFormat->setHide( true );
06797 }
06798 else
06799 {
06800 columnFormat = this->columnFormat( indexCol );
06801 }
06802 columnFormat->copy( layout );
06803
06804 ++indexCol;
06805 }
06806
06807 return true;
06808 }
06809
06810
06811 bool Sheet::loadRowFormat( const QDomElement& row, int &rowIndex, KoOasisLoadingContext& oasisContext, QDict<Style>& styleMap )
06812 {
06813
06814
06815 int backupRow = rowIndex;
06816 bool isNonDefaultRow = false;
06817
06818 KoStyleStack styleStack;
06819 if ( row.hasAttributeNS( KoXmlNS::table, "style-name" ) )
06820 {
06821 QString str = row.attributeNS( KoXmlNS::table, "style-name", QString::null );
06822 const QDomElement *style = oasisContext.oasisStyles().findStyle( str, "table-row" );
06823 if ( style )
06824 {
06825 styleStack.push( *style );
06826 isNonDefaultRow = true;
06827 }
06828 }
06829 styleStack.setTypeProperties( "table-row" );
06830
06831 Format layout( this , doc()->styleManager()->defaultStyle() );
06832 if ( row.hasAttributeNS( KoXmlNS::table,"default-cell-style-name" ) )
06833 {
06834 const QString styleName = row.attributeNS( KoXmlNS::table, "default-cell-style-name", QString::null );
06835 if ( !styleName.isEmpty() )
06836 {
06837 Style* const style = styleMap[ styleName ];
06838 if ( style )
06839 {
06840 layout.setStyle( style );
06841 isNonDefaultRow = true;
06842 }
06843 }
06844 }
06845
06846 double height = -1.0;
06847 if ( styleStack.hasAttributeNS( KoXmlNS::style, "row-height" ) )
06848 {
06849 height = KoUnit::parseValue( styleStack.attributeNS( KoXmlNS::style, "row-height" ) , -1.0 );
06850
06851 isNonDefaultRow = true;
06852 }
06853
06854 int number = 1;
06855 if ( row.hasAttributeNS( KoXmlNS::table, "number-rows-repeated" ) )
06856 {
06857 bool ok = true;
06858 int n = row.attributeNS( KoXmlNS::table, "number-rows-repeated", QString::null ).toInt( &ok );
06859 if ( ok )
06860
06861
06862
06863 number = QMIN( n, KS_rowMax - rowIndex + 1 );
06864 }
06865
06866 bool collapse = false;
06867 if ( row.hasAttributeNS( KoXmlNS::table, "visibility" ) )
06868 {
06869 const QString visibility = row.attributeNS( KoXmlNS::table, "visibility", QString::null );
06870 if ( visibility == "visible" )
06871 collapse = false;
06872 else if ( visibility == "collapse" )
06873 collapse = true;
06874 else if ( visibility == "filter" )
06875 collapse = false;
06876 isNonDefaultRow = true;
06877 }
06878
06879 bool insertPageBreak = false;
06880 if ( styleStack.hasAttributeNS( KoXmlNS::fo, "break-before" ) )
06881 {
06882 QString str = styleStack.attributeNS( KoXmlNS::fo, "break-before" );
06883 if ( str == "page" )
06884 {
06885 insertPageBreak = true;
06886 }
06887
06888
06889 isNonDefaultRow = true;
06890 }
06891
06892
06893 for ( int i = 0; i < number; ++i )
06894 {
06895
06896
06897 RowFormat* rowFormat;
06898 if ( isNonDefaultRow )
06899 {
06900 rowFormat = nonDefaultRowFormat( rowIndex );
06901
06902 if ( height != -1.0 )
06903 rowFormat->setHeight( (int) height );
06904 if ( collapse )
06905 rowFormat->setHide( true );
06906 }
06907 else
06908 {
06909 rowFormat = this->rowFormat( rowIndex );
06910 }
06911 rowFormat->copy( layout );
06912
06913 ++rowIndex;
06914 }
06915
06916 int columnIndex = 0;
06917 QDomNode cellNode = row.firstChild();
06918 int endRow = min(backupRow+number,KS_rowMax);
06919
06920
06921 while ( !cellNode.isNull() )
06922 {
06923 QDomElement cellElement = cellNode.toElement();
06924 if ( !cellElement.isNull() )
06925 {
06926 columnIndex++;
06927 QString localName = cellElement.localName();
06928
06929 if ( ((localName == "table-cell") || (localName == "covered-table-cell")) && cellElement.namespaceURI() == KoXmlNS::table)
06930 {
06931
06932
06933 Style* style = 0;
06934 const bool cellHasStyle = cellElement.hasAttributeNS( KoXmlNS::table, "style-name" );
06935 if ( cellHasStyle )
06936 {
06937 style = styleMap[ cellElement.attributeNS( KoXmlNS::table , "style-name" , QString::null ) ];
06938 }
06939
06940 Cell* const cell = nonDefaultCell( columnIndex, backupRow );
06941 cell->loadOasis( cellElement, oasisContext, style );
06942
06943 int cols = 1;
06944
06945
06946
06947 if ( (number > 1) || cellElement.hasAttributeNS( KoXmlNS::table, "number-columns-repeated" ) )
06948 {
06949 bool ok = false;
06950 int n = cellElement.attributeNS( KoXmlNS::table, "number-columns-repeated", QString::null ).toInt( &ok );
06951
06952 if (ok)
06953
06954
06955
06956 cols = QMIN( n, KS_colMax - columnIndex + 1 );
06957
06958 if ( !cellHasStyle && ( cell->isEmpty() && cell->format()->comment( columnIndex, backupRow ).isEmpty() ) )
06959 {
06960
06961 columnIndex += cols - 1;
06962 }
06963 else
06964 {
06965 for ( int k = cols ; k ; --k )
06966 {
06967 if ( k != cols )
06968 columnIndex++;
06969
06970 for ( int newRow = backupRow; newRow < endRow; ++newRow )
06971 {
06972 Cell* target = nonDefaultCell( columnIndex, newRow );
06973
06974 if (cell != target)
06975 target->copyAll( cell );
06976 }
06977 }
06978 }
06979 }
06980 }
06981 }
06982 cellNode = cellNode.nextSibling();
06983 }
06984
06985 return true;
06986 }
06987
06988 void Sheet::maxRowCols( int & maxCols, int & maxRows )
06989 {
06990 const Cell * cell = firstCell();
06991 while ( cell )
06992 {
06993 if ( cell->column() > maxCols )
06994 maxCols = cell->column();
06995
06996 if ( cell->row() > maxRows )
06997 maxRows = cell->row();
06998
06999 cell = cell->nextCell();
07000 }
07001
07002 const RowFormat * row = firstRow();
07003 while ( row )
07004 {
07005 if ( row->row() > maxRows )
07006 maxRows = row->row();
07007
07008 row = row->next();
07009 }
07010 const ColumnFormat* col = firstCol();
07011 while ( col )
07012 {
07013 if ( col->column() > maxCols )
07014 maxCols = col->column();
07015
07016 col = col->next();
07017 }
07018 }
07019
07020
07021 bool Sheet::compareRows( int row1, int row2, int& maxCols ) const
07022 {
07023 if ( *rowFormat( row1 ) != *rowFormat( row2 ) )
07024 {
07025
07026 return false;
07027 }
07028
07029 for ( int col = 1; col <= maxCols; ++col )
07030 {
07031 if ( *cellAt( col, row1 ) != *cellAt( col, row2 ) )
07032 {
07033
07034 return false;
07035 }
07036 }
07037 return true;
07038 }
07039
07040
07041 void Sheet::saveOasisHeaderFooter( KoXmlWriter &xmlWriter ) const
07042 {
07043 QString headerLeft = print()->headLeft();
07044 QString headerCenter= print()->headMid();
07045 QString headerRight = print()->headRight();
07046
07047 QString footerLeft = print()->footLeft();
07048 QString footerCenter= print()->footMid();
07049 QString footerRight = print()->footRight();
07050
07051 xmlWriter.startElement( "style:header");
07052 if ( ( !headerLeft.isEmpty() )
07053 || ( !headerCenter.isEmpty() )
07054 || ( !headerRight.isEmpty() ) )
07055 {
07056 xmlWriter.startElement( "style:region-left" );
07057 xmlWriter.startElement( "text:p" );
07058 convertPart( headerLeft, xmlWriter );
07059 xmlWriter.endElement();
07060 xmlWriter.endElement();
07061
07062 xmlWriter.startElement( "style:region-center" );
07063 xmlWriter.startElement( "text:p" );
07064 convertPart( headerCenter, xmlWriter );
07065 xmlWriter.endElement();
07066 xmlWriter.endElement();
07067
07068 xmlWriter.startElement( "style:region-right" );
07069 xmlWriter.startElement( "text:p" );
07070 convertPart( headerRight, xmlWriter );
07071 xmlWriter.endElement();
07072 xmlWriter.endElement();
07073 }
07074 else
07075 {
07076 xmlWriter.startElement( "text:p" );
07077
07078 xmlWriter.startElement( "text:sheet-name" );
07079 xmlWriter.addTextNode( "???" );
07080 xmlWriter.endElement();
07081
07082 xmlWriter.endElement();
07083 }
07084 xmlWriter.endElement();
07085
07086
07087 xmlWriter.startElement( "style:footer");
07088 if ( ( !footerLeft.isEmpty() )
07089 || ( !footerCenter.isEmpty() )
07090 || ( !footerRight.isEmpty() ) )
07091 {
07092 xmlWriter.startElement( "style:region-left" );
07093 xmlWriter.startElement( "text:p" );
07094 convertPart( footerLeft, xmlWriter );
07095 xmlWriter.endElement();
07096 xmlWriter.endElement();
07097
07098 xmlWriter.startElement( "style:region-center" );
07099 xmlWriter.startElement( "text:p" );
07100 convertPart( footerCenter, xmlWriter );
07101 xmlWriter.endElement();
07102 xmlWriter.endElement();
07103
07104 xmlWriter.startElement( "style:region-right" );
07105 xmlWriter.startElement( "text:p" );
07106 convertPart( footerRight, xmlWriter );
07107 xmlWriter.endElement();
07108 xmlWriter.endElement();
07109 }
07110 else
07111 {
07112 xmlWriter.startElement( "text:p" );
07113
07114 xmlWriter.startElement( "text:sheet-name" );
07115 xmlWriter.addTextNode( "Page " );
07116 xmlWriter.endElement();
07117
07118 xmlWriter.startElement( "text:page-number" );
07119 xmlWriter.addTextNode( "1" );
07120 xmlWriter.endElement();
07121
07122 xmlWriter.endElement();
07123 }
07124 xmlWriter.endElement();
07125
07126
07127 }
07128
07129 void Sheet::addText( const QString & text, KoXmlWriter & writer ) const
07130 {
07131 if ( !text.isEmpty() )
07132 writer.addTextNode( text );
07133 }
07134
07135 void Sheet::convertPart( const QString & part, KoXmlWriter & xmlWriter ) const
07136 {
07137 QString text;
07138 QString var;
07139
07140 bool inVar = false;
07141 uint i = 0;
07142 uint l = part.length();
07143 while ( i < l )
07144 {
07145 if ( inVar || part[i] == '<' )
07146 {
07147 inVar = true;
07148 var += part[i];
07149 if ( part[i] == '>' )
07150 {
07151 inVar = false;
07152 if ( var == "<page>" )
07153 {
07154 addText( text, xmlWriter );
07155 xmlWriter.startElement( "text:page-number" );
07156 xmlWriter.addTextNode( "1" );
07157 xmlWriter.endElement();
07158 }
07159 else if ( var == "<pages>" )
07160 {
07161 addText( text, xmlWriter );
07162 xmlWriter.startElement( "text:page-count" );
07163 xmlWriter.addTextNode( "99" );
07164 xmlWriter.endElement();
07165 }
07166 else if ( var == "<date>" )
07167 {
07168 addText( text, xmlWriter );
07169
07170 #if 0 //FIXME
07171 QDomElement t = dd.createElement( "text:date" );
07172 t.setAttribute( "text:date-value", "0-00-00" );
07173
07174 t.appendChild( dd.createTextNode( QDate::currentDate().toString() ) );
07175 parent.appendChild( t );
07176 #endif
07177 }
07178 else if ( var == "<time>" )
07179 {
07180 addText( text, xmlWriter );
07181
07182 xmlWriter.startElement( "text:time" );
07183 xmlWriter.addTextNode( QTime::currentTime().toString() );
07184 xmlWriter.endElement();
07185 }
07186 else if ( var == "<file>" )
07187 {
07188 addText( text, xmlWriter );
07189 xmlWriter.startElement( "text:file-name" );
07190 xmlWriter.addAttribute( "text:display", "full" );
07191 xmlWriter.addTextNode( "???" );
07192 xmlWriter.endElement();
07193 }
07194 else if ( var == "<name>" )
07195 {
07196 addText( text, xmlWriter );
07197
07198 xmlWriter.startElement( "text:title" );
07199 xmlWriter.addTextNode( "???" );
07200 xmlWriter.endElement();
07201 }
07202 else if ( var == "<author>" )
07203 {
07204 Doc* sdoc = d->workbook->doc();
07205 KoDocumentInfo * docInfo = sdoc->documentInfo();
07206 KoDocumentInfoAuthor * authorPage = static_cast<KoDocumentInfoAuthor*>( docInfo->page( "author" ) );
07207
07208 text += authorPage->fullName();
07209
07210 addText( text, xmlWriter );
07211 }
07212 else if ( var == "<email>" )
07213 {
07214 Doc* sdoc = d->workbook->doc();
07215 KoDocumentInfo * docInfo = sdoc->documentInfo();
07216 KoDocumentInfoAuthor * authorPage = static_cast<KoDocumentInfoAuthor*>( docInfo->page( "author" ) );
07217
07218 text += authorPage->email();
07219 addText( text, xmlWriter );
07220
07221 }
07222 else if ( var == "<org>" )
07223 {
07224 Doc* sdoc = d->workbook->doc();
07225 KoDocumentInfo * docInfo = sdoc->documentInfo();
07226 KoDocumentInfoAuthor * authorPage = static_cast<KoDocumentInfoAuthor*>( docInfo->page( "author" ) );
07227
07228 text += authorPage->company();
07229 addText( text, xmlWriter );
07230
07231 }
07232 else if ( var == "<sheet>" )
07233 {
07234 addText( text, xmlWriter );
07235
07236 xmlWriter.startElement( "text:sheet-name" );
07237 xmlWriter.addTextNode( "???" );
07238 xmlWriter.endElement();
07239 }
07240 else
07241 {
07242
07243 text += var;
07244 addText( text, xmlWriter );
07245 }
07246
07247 text = "";
07248 var = "";
07249 }
07250 }
07251 else
07252 {
07253 text += part[i];
07254 }
07255 ++i;
07256 }
07257 if ( !text.isEmpty() || !var.isEmpty() )
07258 {
07259
07260 addText( text+var, xmlWriter );
07261 }
07262 kdDebug()<<" text end :"<<text<<" var :"<<var<<endl;
07263 }
07264
07265
07266 void Sheet::loadOasisSettings( const KoOasisSettings::NamedMap &settings )
07267 {
07268
07269 KoOasisSettings::Items items = settings.entry( d->name );
07270 if ( items.isNull() )
07271 return;
07272 d->hideZero = items.parseConfigItemBool( "ShowZeroValues" );
07273 d->showGrid = items.parseConfigItemBool( "ShowGrid" );
07274 d->firstLetterUpper = items.parseConfigItemBool( "FirstLetterUpper" );
07275
07276 int cursorX = items.parseConfigItemInt( "CursorPositionX" );
07277 int cursorY = items.parseConfigItemInt( "CursorPositionY" );
07278 doc()->loadingInfo()->setCursorPosition( this, QPoint( cursorX, cursorY ) );
07279
07280 double offsetX = items.parseConfigItemDouble( "xOffset" );
07281 double offsetY = items.parseConfigItemDouble( "yOffset" );
07282 doc()->loadingInfo()->setScrollingOffset( this, KoPoint( offsetX, offsetY ) );
07283
07284 d->showFormulaIndicator = items.parseConfigItemBool( "ShowFormulaIndicator" );
07285 d->showCommentIndicator = items.parseConfigItemBool( "ShowCommentIndicator" );
07286 d->showPageBorders = items.parseConfigItemBool( "ShowPageBorders" );
07287 d->lcMode = items.parseConfigItemBool( "lcmode" );
07288 d->autoCalc = items.parseConfigItemBool( "autoCalc" );
07289 d->showColumnNumber = items.parseConfigItemBool( "ShowColumnNumber" );
07290 }
07291
07292 void Sheet::saveOasisSettings( KoXmlWriter &settingsWriter ) const
07293 {
07294
07295 settingsWriter.addConfigItem( "ShowZeroValues", d->hideZero );
07296 settingsWriter.addConfigItem( "ShowGrid", d->showGrid );
07297
07298 settingsWriter.addConfigItem( "FirstLetterUpper", d->firstLetterUpper);
07299 settingsWriter.addConfigItem( "ShowFormulaIndicator", d->showFormulaIndicator );
07300 settingsWriter.addConfigItem( "ShowCommentIndicator", d->showCommentIndicator );
07301 settingsWriter.addConfigItem( "ShowPageBorders",d->showPageBorders );
07302 settingsWriter.addConfigItem( "lcmode", d->lcMode );
07303 settingsWriter.addConfigItem( "autoCalc", d->autoCalc );
07304 settingsWriter.addConfigItem( "ShowColumnNumber", d->showColumnNumber );
07305 }
07306
07307 bool Sheet::saveOasis( KoXmlWriter & xmlWriter, KoGenStyles &mainStyles, GenValidationStyles &valStyle, KoStore *store, KoXmlWriter* , int &indexObj, int &partIndexObj )
07308 {
07309 int maxCols= 1;
07310 int maxRows= 1;
07311 xmlWriter.startElement( "table:table" );
07312 xmlWriter.addAttribute( "table:name", d->name );
07313 xmlWriter.addAttribute( "table:style-name", saveOasisSheetStyleName(mainStyles ) );
07314 if ( !d->password.isEmpty() )
07315 {
07316 xmlWriter.addAttribute("table:protected", "true" );
07317 QCString str = KCodecs::base64Encode( d->password );
07318 xmlWriter.addAttribute("table:protection-key", QString( str.data() ) );
07319 }
07320 QRect _printRange = d->print->printRange();
07321 if ( _printRange != ( QRect( QPoint( 1, 1 ), QPoint( KS_colMax, KS_rowMax ) ) ) )
07322 {
07323 QString range= convertRangeToRef( d->name, _printRange );
07324 kdDebug()<<" range : "<<range<<endl;
07325 xmlWriter.addAttribute( "table:print-ranges", range );
07326 }
07327
07328 saveOasisObjects( store, xmlWriter, mainStyles, indexObj, partIndexObj );
07329 maxRowCols( maxCols, maxRows );
07330 saveOasisColRowCell( xmlWriter, mainStyles, maxCols, maxRows, valStyle );
07331 xmlWriter.endElement();
07332 return true;
07333 }
07334
07335 void Sheet::saveOasisPrintStyleLayout( KoGenStyle &style ) const
07336 {
07337 QString printParameter;
07338 if ( d->print->printGrid() )
07339 printParameter="grid ";
07340 if ( d->print->printObjects() )
07341 printParameter+="objects ";
07342 if ( d->print->printCharts() )
07343 printParameter+="charts ";
07344 if ( d->showFormula )
07345 printParameter+="formulas ";
07346 if ( !printParameter.isEmpty() )
07347 {
07348 printParameter+="drawings zero-values";
07349 style.addProperty( "style:print", printParameter );
07350 }
07351 }
07352
07353 QString Sheet::saveOasisSheetStyleName( KoGenStyles &mainStyles )
07354 {
07355 KoGenStyle pageStyle( Doc::STYLE_PAGE, "table" );
07356
07357 KoGenStyle pageMaster( Doc::STYLE_PAGEMASTER );
07358 pageMaster.addAttribute( "style:page-layout-name", d->print->saveOasisSheetStyleLayout( mainStyles ) );
07359
07360 QBuffer buffer;
07361 buffer.open( IO_WriteOnly );
07362 KoXmlWriter elementWriter( &buffer );
07363 saveOasisHeaderFooter(elementWriter);
07364
07365 QString elementContents = QString::fromUtf8( buffer.buffer(), buffer.buffer().size() );
07366 pageMaster.addChildElement( "headerfooter", elementContents );
07367 pageStyle.addAttribute( "style:master-page-name", mainStyles.lookup( pageMaster, "Standard" ) );
07368
07369 pageStyle.addProperty( "table:display", !d->hide );
07370 return mainStyles.lookup( pageStyle, "ta" );
07371 }
07372
07373
07374 void Sheet::saveOasisColRowCell( KoXmlWriter& xmlWriter, KoGenStyles &mainStyles,
07375 int maxCols, int maxRows, GenValidationStyles &valStyle )
07376 {
07377 kdDebug() << "Sheet::saveOasisColRowCell: " << d->name << endl;
07378 kdDebug() << "\t Sheet dimension: " << maxCols << " x " << maxRows << endl;
07379
07380
07381
07382 int i = 1;
07383 while ( i <= maxCols )
07384 {
07385
07386
07387
07388 ColumnFormat* column = columnFormat( i );
07389
07390 KoGenStyle currentColumnStyle( Doc::STYLE_COLUMN_AUTO, "table-column" );
07391 currentColumnStyle.addPropertyPt( "style:column-width", column->dblWidth() );
07392 currentColumnStyle.addProperty( "fo:break-before", "auto" );
07393
07394
07395 KoGenStyle currentDefaultCellStyle;
07396 QString currentDefaultCellStyleName = column->saveOasisCellStyle( currentDefaultCellStyle, mainStyles );
07397
07398
07399 bool hide = column->isHide();
07400 bool refColumnIsDefault = column->isDefault();
07401 int j = i;
07402 int repeated = 1;
07403
07404 while ( j <= maxCols )
07405 {
07406
07407
07408
07409 ColumnFormat* nextColumn = d->columns.next( j++ );
07410
07411
07412 if ( !nextColumn || nextColumn->column() != j )
07413 {
07414 if ( refColumnIsDefault )
07415 {
07416
07417
07418 if ( !nextColumn )
07419 {
07420 repeated = maxCols - i + 1;
07421 }
07422 else
07423 {
07424 repeated = nextColumn->column() - j + 1;
07425 }
07426 }
07427
07428
07429 break;
07430 }
07431 #if 0
07432 KoGenStyle nextColumnStyle( Doc::STYLE_COLUMN_AUTO, "table-column" );
07433 nextColumnStyle.addPropertyPt( "style:column-width", nextColumn->dblWidth() );
07434 nextColumnStyle.addProperty( "fo:break-before", "auto" );
07435
07436 KoGenStyle nextDefaultCellStyle;
07437 QString nextDefaultCellStyleName = nextColumn->saveOasisCellStyle( nextDefaultCellStyle, mainStyles );
07438
07439 if ( hide != nextColumn->isHide() ||
07440 nextDefaultCellStyleName != currentDefaultCellStyleName ||
07441 !( nextColumnStyle == currentColumnStyle ) )
07442 {
07443 break;
07444 }
07445 #endif
07446 if ( *column != *nextColumn )
07447 {
07448 break;
07449 }
07450 ++repeated;
07451 }
07452 xmlWriter.startElement( "table:table-column" );
07453 if ( !column->isDefault() )
07454 {
07455 xmlWriter.addAttribute( "table:style-name", mainStyles.lookup( currentColumnStyle, "co" ) );
07456
07457 if ( !currentDefaultCellStyle.isDefaultStyle() )
07458 xmlWriter.addAttribute( "table:default-cell-style-name", currentDefaultCellStyleName );
07459
07460 if ( hide )
07461 xmlWriter.addAttribute( "table:visibility", "collapse" );
07462 }
07463
07464 if ( repeated > 1 )
07465 xmlWriter.addAttribute( "table:number-columns-repeated", repeated );
07466
07467 xmlWriter.endElement();
07468
07469 kdDebug() << "Sheet::saveOasisColRowCell: column " << i << " "
07470 << "repeated " << repeated << " time(s)" << endl;
07471 i += repeated;
07472 }
07473
07474
07475
07476
07477 for ( i = 1; i <= maxRows; ++i )
07478 {
07479 RowFormat* const row = rowFormat( i );
07480
07481 KoGenStyle currentRowStyle( Doc::STYLE_ROW_AUTO, "table-row" );
07482 currentRowStyle.addPropertyPt( "style:row-height", row->dblHeight() );
07483 currentRowStyle.addProperty( "fo:break-before", "auto" );
07484
07485
07486 KoGenStyle currentDefaultCellStyle;
07487 QString currentDefaultCellStyleName = row->saveOasisCellStyle( currentDefaultCellStyle, mainStyles );
07488
07489 xmlWriter.startElement( "table:table-row" );
07490
07491 if ( !row->isDefault() )
07492 {
07493 xmlWriter.addAttribute( "table:style-name", mainStyles.lookup( currentRowStyle, "ro" ) );
07494 }
07495 int repeated = 1;
07496
07497 if ( !getFirstCellRow( i ) )
07498 {
07499
07500
07501
07502
07503 bool isDefault = row->isDefault();
07504 int j = i + 1;
07505
07506
07507
07508
07509
07510 while ( j <= maxRows && !getFirstCellRow( j ) )
07511 {
07512 RowFormat* const nextRow = rowFormat( j );
07513
07514
07515
07516
07517
07518 if ( isDefault )
07519 {
07520
07521 if ( !nextRow->isDefault() )
07522 break;
07523
07524 ++j;
07525 continue;
07526 }
07527 #if 0
07528
07529 KoGenStyle nextRowStyle( Doc::STYLE_ROW_AUTO, "table-row" );
07530 nextRowStyle.addPropertyPt( "style:row-height", nextRow->dblHeight() );
07531 nextRowStyle.addProperty( "fo:break-before", "auto" );
07532
07533
07534 KoGenStyle nextDefaultCellStyle;
07535 QString nextDefaultCellStyleName = nextRow->saveOasisCellStyle( nextDefaultCellStyle, mainStyles );
07536
07537
07538 if ( isHidden != nextRow->isHide() ||
07539 nextDefaultCellStyleName != currentDefaultCellStyleName ||
07540 !(nextRowStyle == currentRowStyle) )
07541 {
07542 break;
07543 }
07544 #endif
07545 if ( *row != *nextRow )
07546 {
07547 break;
07548 }
07549
07550 ++j;
07551 }
07552 repeated = j - i;
07553
07554 if ( repeated > 1 )
07555 xmlWriter.addAttribute( "table:number-rows-repeated", repeated );
07556 if ( !currentDefaultCellStyle.isDefaultStyle() )
07557 xmlWriter.addAttribute( "table:default-cell-style-name", currentDefaultCellStyleName );
07558 if ( row->isHide() )
07559 xmlWriter.addAttribute( "table:visibility", "collapse" );
07560
07561
07562
07563 xmlWriter.startElement( "table:table-cell" );
07564 xmlWriter.endElement();
07565
07566 kdDebug() << "Sheet::saveOasisColRowCell: empty row " << i << ' '
07567 << "repeated " << repeated << " time(s)" << endl;
07568
07569
07570 i = j - 1;
07571 }
07572 else
07573 {
07574 if ( !currentDefaultCellStyle.isDefaultStyle() )
07575 xmlWriter.addAttribute( "table:default-cell-style-name", currentDefaultCellStyleName );
07576 if ( row->isHide() )
07577 xmlWriter.addAttribute( "table:visibility", "collapse" );
07578
07579 int j = i + 1;
07580 while ( compareRows( i, j, maxCols ) && j <= maxRows )
07581 {
07582 j++;
07583 repeated++;
07584 }
07585 if ( repeated > 1 )
07586 {
07587 kdDebug() << "Sheet::saveOasisColRowCell: NON-empty row " << i << ' '
07588 << "repeated " << repeated << " times" << endl;
07589
07590 xmlWriter.addAttribute( "table:number-rows-repeated", repeated );
07591 }
07592
07593 saveOasisCells( xmlWriter, mainStyles, i, maxCols, valStyle );
07594
07595
07596 i = j - 1;
07597 }
07598 xmlWriter.endElement();
07599 }
07600 }
07601
07602 void Sheet::saveOasisCells( KoXmlWriter& xmlWriter, KoGenStyles &mainStyles, int row, int maxCols, GenValidationStyles &valStyle )
07603 {
07604 int i = 1;
07605 Cell* cell = cellAt( i, row );
07606 Cell* nextCell = getNextCellRight( i, row );
07607
07608
07609
07610
07611 while ( !cell->isDefault() || nextCell )
07612 {
07613 kdDebug() << "Sheet::saveOasisCells:"
07614 << " i: " << i
07615 << " column: " << (cell->isDefault() ? 0 : cell->column()) << endl;
07616 int repeated = 1;
07617 cell->saveOasis( xmlWriter, mainStyles, row, i, repeated, valStyle );
07618 i += repeated;
07619
07620 if ( i > maxCols )
07621 break;
07622 cell = cellAt( i, row );
07623 nextCell = getNextCellRight( i, row );
07624 }
07625 }
07626
07627 bool Sheet::loadXML( const QDomElement& sheet )
07628 {
07629 bool ok = false;
07630 if ( !doc()->loadingInfo() || !doc()->loadingInfo()->loadTemplate() )
07631 {
07632 d->name = sheet.attribute( "name" );
07633 if ( d->name.isEmpty() )
07634 {
07635 doc()->setErrorMessage( i18n("Invalid document. Sheet name is empty.") );
07636 return false;
07637 }
07638 }
07639
07640 bool detectDirection = true;
07641 d->layoutDirection = LeftToRight;
07642 QString layoutDir = sheet.attribute( "layoutDirection" );
07643 if( !layoutDir.isEmpty() )
07644 {
07645 if( layoutDir == "rtl" )
07646 {
07647 detectDirection = false;
07648 d->layoutDirection = RightToLeft;
07649 }
07650 else if( layoutDir == "ltr" )
07651 {
07652 detectDirection = false;
07653 d->layoutDirection = LeftToRight;
07654 }
07655 else
07656 kdDebug()<<" Direction not implemented : "<<layoutDir<<endl;
07657 }
07658 if( detectDirection )
07659 checkContentDirection( d->name );
07660
07661
07662
07663
07664
07665 if (d->name[0] == ' ')
07666 {
07667 d->name.remove(0,1);
07668 }
07669 for (unsigned int i=0; i < d->name.length(); i++)
07670 {
07671 if ( !(d->name[i].isLetterOrNumber() ||
07672 d->name[i] == ' ' || d->name[i] == '.' ||
07673 d->name[i] == '_'))
07674 {
07675 d->name[i] = '_';
07676 }
07677 }
07678
07679
07680 QString testName;
07681 QString baseName;
07682 int nameSuffix = 0;
07683
07684 testName = d->name;
07685 baseName = d->name;
07686
07687
07688 d->name = "";
07689 while (workbook()->findSheet(testName) != NULL)
07690 {
07691 nameSuffix++;
07692 testName = baseName + '_' + QString::number(nameSuffix);
07693 }
07694 d->name = testName;
07695
07696 kdDebug(36001)<<"Sheet::loadXML: table name="<<d->name<<endl;
07697 setName(d->name.utf8());
07698 (dynamic_cast<SheetIface*>(dcopObject()))->sheetNameHasChanged();
07699
07700 if( sheet.hasAttribute( "grid" ) )
07701 {
07702 d->showGrid = (int)sheet.attribute("grid").toInt( &ok );
07703
07704 }
07705 if( sheet.hasAttribute( "printGrid" ) )
07706 {
07707 d->print->setPrintGrid( (bool)sheet.attribute("printGrid").toInt( &ok ) );
07708
07709 }
07710 if( sheet.hasAttribute( "printCommentIndicator" ) )
07711 {
07712 d->print->setPrintCommentIndicator( (bool)sheet.attribute("printCommentIndicator").toInt( &ok ) );
07713
07714 }
07715 if( sheet.hasAttribute( "printFormulaIndicator" ) )
07716 {
07717 d->print->setPrintFormulaIndicator( (bool)sheet.attribute("printFormulaIndicator").toInt( &ok ) );
07718
07719 }
07720 if( sheet.hasAttribute( "hide" ) )
07721 {
07722 d->hide = (bool)sheet.attribute("hide").toInt( &ok );
07723
07724 }
07725 if( sheet.hasAttribute( "showFormula" ) )
07726 {
07727 d->showFormula = (bool)sheet.attribute("showFormula").toInt( &ok );
07728
07729 }
07730
07731 if( sheet.hasAttribute( "formular" ) )
07732 {
07733 d->showFormula = (bool)sheet.attribute("formular").toInt( &ok );
07734
07735 }
07736 if( sheet.hasAttribute( "showFormulaIndicator" ) )
07737 {
07738 d->showFormulaIndicator = (bool)sheet.attribute("showFormulaIndicator").toInt( &ok );
07739
07740 }
07741 if( sheet.hasAttribute( "showCommentIndicator" ) )
07742 {
07743 d->showCommentIndicator = (bool)sheet.attribute("showCommentIndicator").toInt( &ok );
07744
07745 }
07746 if( sheet.hasAttribute( "borders" ) )
07747 {
07748 d->showPageBorders = (bool)sheet.attribute("borders").toInt( &ok );
07749
07750 }
07751 if( sheet.hasAttribute( "lcmode" ) )
07752 {
07753 d->lcMode = (bool)sheet.attribute("lcmode").toInt( &ok );
07754
07755 }
07756 if ( sheet.hasAttribute( "autoCalc" ) )
07757 {
07758 d->autoCalc = ( bool )sheet.attribute( "autoCalc" ).toInt( &ok );
07759
07760 }
07761 if( sheet.hasAttribute( "columnnumber" ) )
07762 {
07763 d->showColumnNumber = (bool)sheet.attribute("columnnumber").toInt( &ok );
07764
07765 }
07766 if( sheet.hasAttribute( "hidezero" ) )
07767 {
07768 d->hideZero = (bool)sheet.attribute("hidezero").toInt( &ok );
07769
07770 }
07771 if( sheet.hasAttribute( "firstletterupper" ) )
07772 {
07773 d->firstLetterUpper = (bool)sheet.attribute("firstletterupper").toInt( &ok );
07774
07775 }
07776
07777
07778 QDomElement paper = sheet.namedItem( "paper" ).toElement();
07779 if ( !paper.isNull() )
07780 {
07781 QString format = paper.attribute( "format" );
07782 QString orientation = paper.attribute( "orientation" );
07783
07784
07785 QDomElement borders = paper.namedItem( "borders" ).toElement();
07786 if ( !borders.isNull() )
07787 {
07788 float left = borders.attribute( "left" ).toFloat();
07789 float right = borders.attribute( "right" ).toFloat();
07790 float top = borders.attribute( "top" ).toFloat();
07791 float bottom = borders.attribute( "bottom" ).toFloat();
07792 d->print->setPaperLayout( left, top, right, bottom, format, orientation );
07793 }
07794 QString hleft, hright, hcenter;
07795 QString fleft, fright, fcenter;
07796
07797 QDomElement head = paper.namedItem( "head" ).toElement();
07798 if ( !head.isNull() )
07799 {
07800 QDomElement left = head.namedItem( "left" ).toElement();
07801 if ( !left.isNull() )
07802 hleft = left.text();
07803 QDomElement center = head.namedItem( "center" ).toElement();
07804 if ( !center.isNull() )
07805 hcenter = center.text();
07806 QDomElement right = head.namedItem( "right" ).toElement();
07807 if ( !right.isNull() )
07808 hright = right.text();
07809 }
07810
07811 QDomElement foot = paper.namedItem( "foot" ).toElement();
07812 if ( !foot.isNull() )
07813 {
07814 QDomElement left = foot.namedItem( "left" ).toElement();
07815 if ( !left.isNull() )
07816 fleft = left.text();
07817 QDomElement center = foot.namedItem( "center" ).toElement();
07818 if ( !center.isNull() )
07819 fcenter = center.text();
07820 QDomElement right = foot.namedItem( "right" ).toElement();
07821 if ( !right.isNull() )
07822 fright = right.text();
07823 }
07824 d->print->setHeadFootLine( hleft, hcenter, hright, fleft, fcenter, fright);
07825 }
07826
07827
07828 QDomElement printrange = sheet.namedItem( "printrange-rect" ).toElement();
07829 if ( !printrange.isNull() )
07830 {
07831 int left = printrange.attribute( "left-rect" ).toInt();
07832 int right = printrange.attribute( "right-rect" ).toInt();
07833 int bottom = printrange.attribute( "bottom-rect" ).toInt();
07834 int top = printrange.attribute( "top-rect" ).toInt();
07835 if ( left == 0 )
07836 {
07837 left = 1;
07838 right = KS_colMax;
07839 }
07840 if ( top == 0 )
07841 {
07842 top = 1;
07843 bottom = KS_rowMax;
07844 }
07845 d->print->setPrintRange( QRect( QPoint( left, top ), QPoint( right, bottom ) ) );
07846 }
07847
07848
07849 if( sheet.hasAttribute( "printZoom" ) )
07850 {
07851 double zoom = sheet.attribute( "printZoom" ).toDouble( &ok );
07852 if ( ok )
07853 {
07854 d->print->setZoom( zoom );
07855 }
07856 }
07857
07858
07859 if( sheet.hasAttribute( "printPageLimitX" ) )
07860 {
07861 int pageLimit = sheet.attribute( "printPageLimitX" ).toInt( &ok );
07862 if ( ok )
07863 {
07864 d->print->setPageLimitX( pageLimit );
07865 }
07866 }
07867
07868
07869 if( sheet.hasAttribute( "printPageLimitY" ) )
07870 {
07871 int pageLimit = sheet.attribute( "printPageLimitY" ).toInt( &ok );
07872 if ( ok )
07873 {
07874 d->print->setPageLimitY( pageLimit );
07875 }
07876 }
07877
07878
07879 QDomNode n = sheet.firstChild();
07880 while( !n.isNull() )
07881 {
07882 QDomElement e = n.toElement();
07883 if ( !e.isNull() )
07884 {
07885 QString tagName=e.tagName();
07886 if ( tagName == "cell" )
07887 {
07888 Cell *cell = new Cell( this, 0, 0 );
07889 if ( cell->load( e, 0, 0 ) )
07890 insertCell( cell );
07891 else
07892 delete cell;
07893 }
07894 else if ( tagName == "row" )
07895 {
07896 RowFormat *rl = new RowFormat( this, 0 );
07897 if ( rl->load( e ) )
07898 insertRowFormat( rl );
07899 else
07900 delete rl;
07901 }
07902 else if ( tagName == "column" )
07903 {
07904 ColumnFormat *cl = new ColumnFormat( this, 0 );
07905 if ( cl->load( e ) )
07906 insertColumnFormat( cl );
07907 else
07908 delete cl;
07909 }
07910 else if ( tagName == "object" )
07911 {
07912 EmbeddedKOfficeObject *ch = new EmbeddedKOfficeObject( doc(), this );
07913 if ( ch->load( e ) )
07914 insertObject( ch );
07915 else
07916 {
07917 ch->embeddedObject()->setDeleted(true);
07918 delete ch;
07919 }
07920 }
07921 else if ( tagName == "chart" )
07922 {
07923 EmbeddedChart *ch = new EmbeddedChart( doc(), this );
07924 if ( ch->load( e ) )
07925 insertObject( ch );
07926 else
07927 {
07928 ch->embeddedObject()->setDeleted(true);
07929 delete ch;
07930 }
07931 }
07932 }
07933
07934 n = n.nextSibling();
07935 }
07936
07937
07938
07939 QDomElement printrepeatcolumns = sheet.namedItem( "printrepeatcolumns" ).toElement();
07940 if ( !printrepeatcolumns.isNull() )
07941 {
07942 int left = printrepeatcolumns.attribute( "left" ).toInt();
07943 int right = printrepeatcolumns.attribute( "right" ).toInt();
07944 d->print->setPrintRepeatColumns( qMakePair( left, right ) );
07945 }
07946
07947
07948 QDomElement printrepeatrows = sheet.namedItem( "printrepeatrows" ).toElement();
07949 if ( !printrepeatrows.isNull() )
07950 {
07951 int top = printrepeatrows.attribute( "top" ).toInt();
07952 int bottom = printrepeatrows.attribute( "bottom" ).toInt();
07953 d->print->setPrintRepeatRows( qMakePair( top, bottom ) );
07954 }
07955
07956 if( !sheet.hasAttribute( "borders1.2" ) )
07957 {
07958 convertObscuringBorders();
07959 }
07960
07961 if ( sheet.hasAttribute( "protected" ) )
07962 {
07963 QString passwd = sheet.attribute( "protected" );
07964
07965 if ( passwd.length() > 0 )
07966 {
07967 QCString str( passwd.latin1() );
07968 d->password = KCodecs::base64Decode( str );
07969 }
07970 else
07971 d->password = QCString( "" );
07972 }
07973
07974 return true;
07975 }
07976
07977
07978 bool Sheet::loadChildren( KoStore* _store )
07979 {
07980 QPtrListIterator<EmbeddedObject> it( doc()->embeddedObjects() );
07981 for( ; it.current(); ++it )
07982 {
07983 if ( it.current()->sheet() == this && ( it.current()->getType() == OBJECT_KOFFICE_PART || it.current()->getType() == OBJECT_CHART ) )
07984 {
07985 kdDebug() << "KSpreadSheet::loadChildren" << endl;
07986 if ( !dynamic_cast<EmbeddedKOfficeObject*>( it.current() )->embeddedObject()->loadDocument( _store ) )
07987 return false;
07988 }
07989 }
07990
07991 return true;
07992 }
07993
07994
07995 void Sheet::setShowPageBorders( bool b )
07996 {
07997 if ( b == d->showPageBorders )
07998 return;
07999
08000 d->showPageBorders = b;
08001 emit sig_updateView( this );
08002 }
08003
08004 void Sheet::addCellBinding( CellBinding *_bind )
08005 {
08006 d->cellBindings.append( _bind );
08007
08008 doc()->setModified( true );
08009 }
08010
08011 void Sheet::removeCellBinding( CellBinding *_bind )
08012 {
08013 d->cellBindings.removeRef( _bind );
08014
08015 doc()->setModified( true );
08016 }
08017
08018 Sheet* Sheet::findSheet( const QString & _name )
08019 {
08020 if ( !workbook() )
08021 return 0L;
08022
08023 return workbook()->findSheet( _name );
08024 }
08025
08026
08027 void Sheet::insertCell( Cell *_cell )
08028 {
08029
08030 d->cells.insert( _cell, _cell->column(), _cell->row() );
08031
08032
08033 if ( d->scrollBarUpdates )
08034 {
08035 checkRangeHBorder ( _cell->column() );
08036 checkRangeVBorder ( _cell->row() );
08037 }
08038 }
08039
08040 void Sheet::insertColumnFormat( ColumnFormat *l )
08041 {
08042 d->columns.insertElement( l, l->column() );
08043 }
08044
08045 void Sheet::insertRowFormat( RowFormat *l )
08046 {
08047 d->rows.insertElement( l, l->row() );
08048 }
08049
08050 void Sheet::update()
08051 {
08052 Cell* c = d->cells.firstCell();
08053 for( ;c; c = c->nextCell() )
08054 {
08055 updateCell(c, c->column(), c->row());
08056 }
08057 }
08058
08059 void Sheet::updateCellArea(const Region& cellArea)
08060 {
08061 if ( doc()->isLoading() || doc()->delayCalculation() || (!getAutoCalc()))
08062 return;
08063
08064 setRegionPaintDirty( cellArea );
08065 }
08066
08067 void Sheet::updateCell( Cell *, int _column, int _row )
08068 {
08069 QRect cellArea(QPoint(_column, _row), QPoint(_column, _row));
08070
08071 updateCellArea(cellArea);
08072 }
08073
08074 void Sheet::emit_updateRow( RowFormat *_format, int _row, bool repaint )
08075 {
08076 if ( doc()->isLoading() )
08077 return;
08078
08079 Cell* c = d->cells.firstCell();
08080 for( ;c; c = c->nextCell() )
08081 if ( c->row() == _row )
08082 c->setLayoutDirtyFlag( true );
08083
08084 if ( repaint )
08085 {
08086
08087
08088 setRegionPaintDirty( QRect( 0 , _row , KS_colMax , KS_rowMax) );
08089
08090 emit sig_updateVBorder( this );
08091 emit sig_updateView( this );
08092 }
08093 emit sig_maxRow(maxRow());
08094 _format->clearDisplayDirtyFlag();
08095 }
08096
08097 void Sheet::emit_updateColumn( ColumnFormat *_format, int _column )
08098 {
08099 if ( doc()->isLoading() )
08100 return;
08101
08102 Cell* c = d->cells.firstCell();
08103 for( ;c; c = c->nextCell() )
08104 if ( c->column() == _column )
08105 c->setLayoutDirtyFlag( true );
08106
08107
08108
08109 setRegionPaintDirty( QRect( _column , 0 , KS_colMax , KS_rowMax) );
08110
08111 emit sig_updateHBorder( this );
08112 emit sig_updateView( this );
08113 emit sig_maxColumn( maxColumn() );
08114
08115
08116
08117 _format->clearDisplayDirtyFlag();
08118 }
08119
08120 bool Sheet::insertChart( const KoRect& _rect, KoDocumentEntry& _e, const QRect& _data )
08121 {
08122 kdDebug(36001) << "Creating document" << endl;
08123 KoDocument* dd = _e.createDoc();
08124 kdDebug(36001) << "Created" << endl;
08125 if ( !dd )
08126
08127 return false;
08128
08129 kdDebug(36001) << "NOW FETCHING INTERFACE" << endl;
08130
08131 if ( !dd->initDoc(KoDocument::InitDocEmbedded) )
08132 return false;
08133
08134 EmbeddedChart * ch = new EmbeddedChart( doc(), this, dd, _rect );
08135 ch->setDataArea( _data );
08136 ch->update();
08137 ch->chart()->setCanChangeValue( false );
08138
08139 KoChart::WizardExtension * wiz = ch->chart()->wizardExtension();
08140
08141 Range dataRange;
08142 dataRange.setRange( _data );
08143 dataRange.setSheet( this );
08144
08145 QString rangeString=dataRange.toString();
08146
08147 if ( wiz )
08148 wiz->show( rangeString );
08149
08150 insertObject( ch );
08151
08152 return true;
08153 }
08154
08155 bool Sheet::insertChild( const KoRect& _rect, KoDocumentEntry& _e )
08156 {
08157 KoDocument* d = _e.createDoc( doc() );
08158 if ( !d )
08159 {
08160 kdDebug() << "Error inserting child!" << endl;
08161 return false;
08162 }
08163 if ( !d->initDoc(KoDocument::InitDocEmbedded) )
08164 return false;
08165
08166 EmbeddedKOfficeObject* ch = new EmbeddedKOfficeObject( doc(), this, d, _rect );
08167 insertObject( ch );
08168 return true;
08169 }
08170
08171 bool Sheet::insertPicture( const KoPoint& point , const KURL& url )
08172 {
08173 KoPicture picture = doc()->pictureCollection()->downloadPicture( url , 0 );
08174
08175 return insertPicture(point,picture);
08176 }
08177
08178 bool Sheet::insertPicture( const KoPoint& point , KoPicture& picture )
08179 {
08180
08181 if (picture.isNull())
08182 return false;
08183
08184 KoPictureKey key = picture.getKey();
08185
08186 KoRect destinationRect;
08187 destinationRect.setLeft( point.x() );
08188 destinationRect.setTop( point.y() );
08189
08190
08191
08192
08193
08194
08195
08196
08197
08198
08199
08200 KoSize destinationSize;
08201
08202 double inchWidth = (double)picture.getOriginalSize().width() / KoGlobal::dpiX();
08203 double inchHeight = (double)picture.getOriginalSize().height() / KoGlobal::dpiY();
08204
08205 destinationSize.setWidth( KoUnit::fromUserValue(inchWidth,KoUnit::U_INCH) );
08206 destinationSize.setHeight( KoUnit::fromUserValue(inchHeight,KoUnit::U_INCH) );
08207
08208 destinationRect.setSize( destinationSize);
08209
08210 EmbeddedPictureObject* object = new EmbeddedPictureObject( this, destinationRect, doc()->pictureCollection(),key);
08211
08212
08213 insertObject( object );
08214 return true;
08215 }
08216
08217 bool Sheet::insertPicture( const KoPoint& point, const QPixmap& pixmap )
08218 {
08219 QByteArray data;
08220 QBuffer buffer(data);
08221
08222 buffer.open( IO_ReadWrite );
08223 pixmap.save( &buffer , "PNG" );
08224
08225
08226
08227 buffer.reset();
08228
08229 KoPicture picture;
08230 picture.load( &buffer , "PNG" );
08231
08232 doc()->pictureCollection()->insertPicture(picture);
08233
08234 return insertPicture( point , picture );
08235 }
08236
08237 void Sheet::insertObject( EmbeddedObject *_obj )
08238 {
08239 doc()->insertObject( _obj );
08240 emit sig_updateView( _obj );
08241 }
08242
08243 void Sheet::changeChildGeometry( EmbeddedKOfficeObject *_child, const KoRect& _rect )
08244 {
08245 _child->setGeometry( _rect );
08246
08247 emit sig_updateChildGeometry( _child );
08248 }
08249
08250 bool Sheet::saveChildren( KoStore* _store, const QString &_path )
08251 {
08252 int i = 0;
08253
08254 QPtrListIterator<EmbeddedObject> it( doc()->embeddedObjects() );
08255 for( ; it.current(); ++it )
08256 {
08257 if ( it.current()->sheet() == this && ( it.current()->getType() == OBJECT_KOFFICE_PART || it.current()->getType() == OBJECT_CHART ) )
08258 {
08259 QString path = QString( "%1/%2" ).arg( _path ).arg( i++ );
08260 if ( !dynamic_cast<EmbeddedKOfficeObject*>( it.current() )->embeddedObject()->document()->saveToStore( _store, path ) )
08261 return false;
08262 }
08263 }
08264 return true;
08265 }
08266
08267 bool Sheet::saveOasisObjects( KoStore *, KoXmlWriter &xmlWriter, KoGenStyles& mainStyles, int & indexObj, int &partIndexObj )
08268 {
08269
08270 if ( doc()->embeddedObjects().isEmpty() )
08271 return true;
08272
08273 bool objectFound = false;
08274 EmbeddedObject::KSpreadOasisSaveContext sc( xmlWriter, mainStyles, indexObj, partIndexObj );
08275 QPtrListIterator<EmbeddedObject> it( doc()->embeddedObjects() );
08276 for( ; it.current(); ++it )
08277 {
08278 if ( it.current()->sheet() == this && ( doc()->savingWholeDocument() || it.current()->isSelected() ) )
08279 {
08280 if ( !objectFound )
08281 {
08282 xmlWriter.startElement( "table:shapes" );
08283 objectFound = true;
08284 }
08285 if ( !it.current()->saveOasisObject(sc) )
08286 {
08287 xmlWriter.endElement();
08288 return false;
08289 }
08290 ++indexObj;
08291 }
08292 }
08293 if ( objectFound )
08294 {
08295 xmlWriter.endElement();
08296 }
08297 return true;
08298 }
08299
08300 Sheet::~Sheet()
08301 {
08302
08303
08304
08305
08306
08307
08308 setAutoCalc(false);
08309
08310 s_mapSheets->remove( d->id );
08311
08312
08313
08314
08315 if( s_mapSheets->count()==0)
08316 s_id=0L;
08317
08318 Cell* c = d->cells.firstCell();
08319 for( ; c; c = c->nextCell() )
08320 c->sheetDies();
08321
08322 d->cells.clear();
08323
08324 d->painter->end();
08325 delete d->painter;
08326 delete d->widget;
08327
08328 delete d->defaultFormat;
08329 delete d->defaultCell;
08330 delete d->defaultRowFormat;
08331 delete d->defaultColumnFormat;
08332 delete d->print;
08333 delete d->dcop;
08334
08335 delete d->dependencies;
08336
08337 delete d;
08338
08339
08340 d=0;
08341 }
08342
08343 void Sheet::checkRangeHBorder ( int _column )
08344 {
08345 if ( d->scrollBarUpdates && _column > d->maxColumn )
08346 {
08347 d->maxColumn = _column;
08348 emit sig_maxColumn( _column );
08349 }
08350 }
08351
08352 void Sheet::checkRangeVBorder ( int _row )
08353 {
08354 if ( d->scrollBarUpdates && _row > d->maxRow )
08355 {
08356 d->maxRow = _row;
08357 emit sig_maxRow( _row );
08358 }
08359 }
08360
08361
08362 void Sheet::enableScrollBarUpdates( bool _enable )
08363 {
08364 d->scrollBarUpdates = _enable;
08365 }
08366
08367 DCOPObject* Sheet::dcopObject()
08368 {
08369 if ( !d->dcop )
08370 d->dcop = new SheetIface( this );
08371
08372 return d->dcop;
08373 }
08374
08375 void Sheet::hideSheet(bool _hide)
08376 {
08377 setHidden(_hide);
08378 if(_hide)
08379 emit sig_SheetHidden(this);
08380 else
08381 emit sig_SheetShown(this);
08382 }
08383
08384 void Sheet::removeSheet()
08385 {
08386 emit sig_SheetRemoved(this);
08387 }
08388
08389 bool Sheet::setSheetName( const QString& name, bool init, bool )
08390 {
08391 if ( workbook()->findSheet( name ) )
08392 return false;
08393
08394 if ( isProtected() )
08395 return false;
08396
08397 if ( d->name == name )
08398 return true;
08399
08400 QString old_name = d->name;
08401 d->name = name;
08402
08403 if ( init )
08404 return true;
08405
08406 QPtrListIterator<Sheet> it( workbook()->sheetList() );
08407 for ( ; it.current(); ++it )
08408 it.current()->changeCellTabName( old_name, name );
08409
08410 doc()->changeAreaSheetName( old_name, name );
08411 emit sig_nameChanged( this, old_name );
08412
08413 setName(name.utf8());
08414 (dynamic_cast<SheetIface*>(dcopObject()))->sheetNameHasChanged();
08415
08416 return true;
08417 }
08418
08419
08420 void Sheet::updateLocale()
08421 {
08422 doc()->emitBeginOperation(true);
08423 setRegionPaintDirty(QRect(QPoint(1,1), QPoint(KS_colMax, KS_rowMax)));
08424
08425 Cell* c = d->cells.firstCell();
08426 for( ;c; c = c->nextCell() )
08427 {
08428 QString _text = c->text();
08429 c->setCellText( _text );
08430 }
08431 emit sig_updateView( this );
08432
08433 }
08434
08435 Cell* Sheet::getFirstCellColumn(int col) const
08436 { return d->cells.getFirstCellColumn(col); }
08437
08438 Cell* Sheet::getLastCellColumn(int col) const
08439 { return d->cells.getLastCellColumn(col); }
08440
08441 Cell* Sheet::getFirstCellRow(int row) const
08442 { return d->cells.getFirstCellRow(row); }
08443
08444 Cell* Sheet::getLastCellRow(int row) const
08445 { return d->cells.getLastCellRow(row); }
08446
08447 Cell* Sheet::getNextCellUp(int col, int row) const
08448 { return d->cells.getNextCellUp(col, row); }
08449
08450 Cell* Sheet::getNextCellDown(int col, int row) const
08451 { return d->cells.getNextCellDown(col, row); }
08452
08453 Cell* Sheet::getNextCellLeft(int col, int row) const
08454 { return d->cells.getNextCellLeft(col, row); }
08455
08456 Cell* Sheet::getNextCellRight(int col, int row) const
08457 { return d->cells.getNextCellRight(col, row); }
08458
08459 void Sheet::convertObscuringBorders()
08460 {
08461
08462
08463
08464
08465
08466
08467
08468
08469
08470
08471
08472
08473
08474 Cell* c = d->cells.firstCell();
08475 QPen topPen, bottomPen, leftPen, rightPen;
08476 for( ;c; c = c->nextCell() )
08477 {
08478 if (c->extraXCells() > 0 || c->extraYCells() > 0)
08479 {
08480 topPen = c->topBorderPen(c->column(), c->row());
08481 leftPen = c->leftBorderPen(c->column(), c->row());
08482 rightPen = c->rightBorderPen(c->column(), c->row());
08483 bottomPen = c->bottomBorderPen(c->column(), c->row());
08484
08485 c->format()->setTopBorderStyle(Qt::NoPen);
08486 c->format()->setLeftBorderStyle(Qt::NoPen);
08487 c->format()->setRightBorderStyle(Qt::NoPen);
08488 c->format()->setBottomBorderStyle(Qt::NoPen);
08489
08490 for (int x = c->column(); x < c->column() + c->extraXCells(); x++)
08491 {
08492 nonDefaultCell( x, c->row() )->setTopBorderPen(topPen);
08493 nonDefaultCell( x, c->row() + c->extraYCells() )->
08494 setBottomBorderPen(bottomPen);
08495 }
08496 for (int y = c->row(); y < c->row() + c->extraYCells(); y++)
08497 {
08498 nonDefaultCell( c->column(), y )->setLeftBorderPen(leftPen);
08499 nonDefaultCell( c->column() + c->extraXCells(), y )->
08500 setRightBorderPen(rightPen);
08501 }
08502 }
08503 }
08504 }
08505
08506
08507
08508
08509
08510
08511 void Sheet::setRegionPaintDirty( Region const & region )
08512 {
08513 DilationManipulator manipulator;
08514 manipulator.setSheet(this);
08515 manipulator.add(region);
08516 manipulator.execute();
08517
08518 d->paintDirtyList.add(manipulator);
08519
08520 }
08521
08522 void Sheet::setRegionPaintDirty( QRect const & range )
08523 {
08524 DilationManipulator manipulator;
08525 manipulator.setSheet(this);
08526 manipulator.add(range);
08527 manipulator.execute();
08528
08529 d->paintDirtyList.add(manipulator);
08530
08531 }
08532
08533 void Sheet::clearPaintDirtyData()
08534 {
08535 d->paintDirtyList.clear();
08536 }
08537
08538 bool Sheet::cellIsPaintDirty( QPoint const & cell ) const
08539 {
08540 return d->paintDirtyList.contains(cell);
08541 }
08542
08543 #ifndef NDEBUG
08544 void Sheet::printDebug()
08545 {
08546 int iMaxColumn = maxColumn();
08547 int iMaxRow = maxRow();
08548
08549 kdDebug(36001) << "Cell | Content | DataT | Text" << endl;
08550 Cell *cell;
08551 for ( int currentrow = 1 ; currentrow < iMaxRow ; ++currentrow )
08552 {
08553 for ( int currentcolumn = 1 ; currentcolumn < iMaxColumn ; currentcolumn++ )
08554 {
08555 cell = cellAt( currentcolumn, currentrow );
08556 if ( !cell->isDefault() && !cell->isEmpty() )
08557 {
08558 QString cellDescr = Cell::name( currentcolumn, currentrow );
08559 cellDescr = cellDescr.rightJustify( 4,' ' );
08560
08561
08562
08563 cellDescr += " | ";
08564 cellDescr += cell->value().type();
08565 cellDescr += " | ";
08566 cellDescr += cell->text();
08567 if ( cell->isFormula() )
08568 cellDescr += QString(" [result: %1]").arg( cell->value().asString() );
08569 kdDebug(36001) << cellDescr << endl;
08570 }
08571 }
08572 }
08573 }
08574 #endif
08575
08576 }
08577