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 ( _column > KS_colMax ) {
01045 _column = KS_colMax;
01046 kdDebug (36001) << "Sheet::cellAt: column range: (col: " << _column << ")" << endl;
01047 }
01048 if ( _row > KS_rowMax) {
01049 kdDebug (36001) << "Sheet::cellAt: row out of range: (row: " << _row << ")" << endl;
01050 _row = KS_rowMax;
01051 }
01052
01053 if ( _scrollbar_update && d->scrollBarUpdates )
01054 {
01055 checkRangeHBorder( _column );
01056 checkRangeVBorder( _row );
01057 }
01058
01059 Cell *p = d->cells.lookup( _column, _row );
01060 if ( p != 0L )
01061 return p;
01062
01063 return d->defaultCell;
01064 }
01065
01066 ColumnFormat* Sheet::nonDefaultColumnFormat( int _column, bool force_creation )
01067 {
01068 ColumnFormat *p = d->columns.lookup( _column );
01069 if ( p != 0L || !force_creation )
01070 return p;
01071
01072 p = new ColumnFormat( this, _column );
01073
01074 p->setDblWidth( d->defaultColumnFormat->dblWidth() );
01075
01076 d->columns.insertElement( p, _column );
01077
01078 return p;
01079 }
01080
01081 RowFormat* Sheet::nonDefaultRowFormat( int _row, bool force_creation )
01082 {
01083 RowFormat *p = d->rows.lookup( _row );
01084 if ( p != 0L || !force_creation )
01085 return p;
01086
01087 p = new RowFormat( this, _row );
01088
01089 p->setDblHeight( d->defaultRowFormat->dblHeight() );
01090
01091 d->rows.insertElement( p, _row );
01092
01093 return p;
01094 }
01095
01096 Cell* Sheet::nonDefaultCell( int _column, int _row,
01097 bool _scrollbar_update, Style * _style )
01098 {
01099 if ( _scrollbar_update && d->scrollBarUpdates )
01100 {
01101 checkRangeHBorder( _column );
01102 checkRangeVBorder( _row );
01103 }
01104
01105 Cell * p = d->cells.lookup( _column, _row );
01106 if ( p != 0L )
01107 return p;
01108
01109 Cell * cell = 0;
01110
01111 if ( _style )
01112 cell = new Cell( this, _style, _column, _row );
01113 else
01114 cell = new Cell( this, _column, _row );
01115
01116 insertCell( cell );
01117
01118 return cell;
01119 }
01120
01121 void Sheet::setText( int _row, int _column, const QString& _text, bool asString )
01122 {
01123 ProtectedCheck prot;
01124 prot.setSheet (this);
01125 prot.add (QPoint (_column, _row));
01126 if (prot.check())
01127 NO_MODIFICATION_POSSIBLE;
01128
01129 DataManipulator *dm = new DataManipulator ();
01130 dm->setSheet (this);
01131 dm->setValue (_text);
01132 dm->setParsing (!asString);
01133 dm->add (QPoint (_column, _row));
01134 dm->execute ();
01135
01136
01137
01138
01139
01140
01141
01142
01143
01144
01145
01146
01147
01148
01149 if(_text.at(0)=='!')
01150 emit sig_updateView( this, Region(_column,_row,_column,_row) );
01151 }
01152
01153 void Sheet::setArrayFormula (Selection *selectionInfo, const QString &_text)
01154 {
01155
01156 ProtectedCheck prot;
01157 prot.setSheet (this);
01158 prot.add (*selectionInfo);
01159 if (prot.check())
01160 NO_MODIFICATION_POSSIBLE;
01161
01162
01163 ArrayFormulaManipulator *afm = new ArrayFormulaManipulator;
01164 afm->setSheet (this);
01165 afm->setText (_text);
01166 afm->add (*selectionInfo);
01167 afm->execute ();
01168
01169
01170
01171
01172
01173
01174
01175
01176
01177
01178
01179
01180
01181
01182
01183
01184
01185
01186
01187
01188
01189
01190
01191
01192
01193
01194 }
01195
01196 void Sheet::setLayoutDirtyFlag()
01197 {
01198 Cell * c = d->cells.firstCell();
01199 for( ; c; c = c->nextCell() )
01200 c->setLayoutDirtyFlag();
01201 }
01202
01203 void Sheet::setCalcDirtyFlag()
01204 {
01205 Cell* c = d->cells.firstCell();
01206 for( ; c; c = c->nextCell() )
01207 {
01208 if ( !(c->isObscured() && c->isPartOfMerged()) )
01209 c->setCalcDirtyFlag();
01210 }
01211 }
01212
01213 void Sheet::updateAllDependencies()
01214 {
01215 for (Cell* cell = d->cells.firstCell() ; cell ; cell = cell->nextCell())
01216 {
01217 Point cellLocation;
01218 cellLocation.setSheet(cell->sheet());
01219 cellLocation.setRow(cell->row());
01220 cellLocation.setColumn(cell->column());
01221 d->dependencies->cellChanged(cellLocation);
01222 }
01223 }
01224
01225 void Sheet::recalc()
01226 {
01227 recalc(false);
01228 }
01229
01230 void Sheet::recalc( bool force )
01231 {
01232
01233
01234 setCalcDirtyFlag();
01235
01236
01237
01238 if ( !getAutoCalc() && !force )
01239 return;
01240
01241
01242
01243
01244 if ( !getAutoCalc() )
01245 updateAllDependencies();
01246
01247
01248
01249
01250
01251
01252
01253
01254 Cell* c;
01255
01256 int count = 0;
01257 c = d->cells.firstCell();
01258 for( ; c; c = c->nextCell() )
01259 ++count;
01260
01261 int cur = 0;
01262 int percent = -1;
01263 c = d->cells.firstCell();
01264 for( ; c; c = c->nextCell() )
01265 {
01266 c->calc (false);
01267 cur++;
01268
01269 if (cur*100/count != percent) {
01270 percent = cur*100/count;
01271 kdDebug() << "Recalc: " << percent << "%" << endl;
01272 }
01273 }
01274
01275
01276 emit sig_updateView( this );
01277 }
01278
01279 void Sheet::valueChanged (Cell *cell)
01280 {
01281
01282
01283
01284
01285 Point c;
01286 c.setRow (cell->row());
01287 c.setColumn (cell->column());
01288 c.setSheet( this );
01289
01290
01291 if ( getAutoCalc() )
01292 d->dependencies->cellChanged (c);
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
01390
01391
01392
01393 class UndoAction* Sheet::CellWorkerTypeA::createUndoAction( Doc* doc, Sheet* sheet, const KSpread::Region& region )
01394 {
01395 QString title = getUndoTitle();
01396 return new UndoCellFormat( doc, sheet, region, title );
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
01543
01544
01545
01546 Sheet::SelectionType Sheet::workOnCells( Selection* selectionInfo, CellWorker & worker )
01547 {
01548 Sheet::SelectionType result;
01549
01550 doc()->emitBeginOperation();
01551
01552
01553 bool selected = !(selectionInfo->isSingular());
01554
01555
01556 if ( !doc()->undoLocked() )
01557 {
01558 UndoAction* undo = worker.createUndoAction(doc(), this, *selectionInfo);
01559
01560 if ( undo != 0 )
01561 {
01562 doc()->addCommand( undo );
01563 }
01564 }
01565
01566 Region::ConstIterator endOfList(selectionInfo->constEnd());
01567 for (Region::ConstIterator it = selectionInfo->constBegin(); it != endOfList; ++it)
01568 {
01569
01570 QRect range = (*it)->rect().normalize();
01571
01572 int top = range.top();
01573 int left = range.left();
01574 int bottom = range.bottom();
01575 int right = range.right();
01576
01577
01578 Cell * cell;
01579 Style * s = doc()->styleManager()->defaultStyle();
01580
01581 if ( !worker.type_B && selected && util_isColumnSelected(range) )
01582 {
01583 for ( RowFormat * rw = d->rows.first(); rw; rw = rw->next() )
01584 {
01585 if ( worker.testCondition( rw ) )
01586 {
01587 for ( int col = left; col <= right; ++col )
01588 {
01589 cell = nonDefaultCell( col, rw->row(), false, s );
01590 }
01591 }
01592 }
01593 }
01594
01595
01596 if ( selected && util_isRowSelected(range) )
01597 {
01598 for ( int row = top; row <= bottom; ++row )
01599 {
01600 cell = getFirstCellRow( row );
01601 while ( cell )
01602 {
01603 if ( worker.testCondition( cell ) )
01604 {
01605 if ( worker.type_B )
01606 worker.doWork( cell, false, cell->column(), row );
01607 else
01608 worker.prepareCell( cell );
01609 }
01610 cell = getNextCellRight( cell->column(), row );
01611 }
01612 }
01613
01614 if ( worker.type_B )
01615 {
01616
01617 ;
01618 }
01619 else
01620 {
01621
01622 for ( int i = top; i <= bottom; ++i )
01623 {
01624 RowFormat * rw = nonDefaultRowFormat(i);
01625 worker.doWork( rw );
01626 }
01627
01628 for ( int row = top; row <= bottom; ++row )
01629 {
01630 cell = getFirstCellRow( row );
01631 while ( cell )
01632 {
01633 if ( worker.testCondition( cell ) )
01634 {
01635 worker.doWork( cell, false, cell->column(), row );
01636 }
01637 cell = getNextCellRight( cell->column(), row );
01638 }
01639 }
01640
01641 }
01642 result = CompleteRows;
01643 }
01644
01645 else if ( selected && util_isColumnSelected(range) )
01646 {
01647 for ( int col = range.left(); col <= right; ++col )
01648 {
01649 cell = getFirstCellColumn( col );
01650 while ( cell )
01651 {
01652 if ( worker.testCondition( cell ) )
01653 {
01654 if ( worker.type_B )
01655 worker.doWork( cell, false, col, cell->row() );
01656 else
01657 worker.prepareCell( cell );
01658 }
01659
01660 cell = getNextCellDown( col, cell->row() );
01661 }
01662 }
01663
01664 if ( worker.type_B )
01665 {
01666 ;
01667 }
01668 else
01669 {
01670
01671 for ( int i = left; i <= right; ++i )
01672 {
01673 ColumnFormat * cl = nonDefaultColumnFormat( i );
01674 worker.doWork( cl );
01675 }
01676
01677 for ( RowFormat * rw = d->rows.first(); rw; rw = rw->next() )
01678 {
01679 if ( worker.testCondition( rw ) )
01680 {
01681 for ( int i = left; i <= right; ++i )
01682 {
01683 cell = nonDefaultCell( i, rw->row(), false, s );
01684 worker.doWork( cell, false, i, rw->row() );
01685 }
01686 }
01687 }
01688 }
01689 result = CompleteColumns;
01690 }
01691
01692 else
01693 {
01694 for ( int x = left; x <= right; ++x )
01695 {
01696 for ( int y = top; y <= bottom; ++y )
01697 {
01698 cell = cellAt( x, y );
01699 if ( worker.testCondition( cell ) )
01700 {
01701 if ( cell == d->defaultCell && worker.create_if_default )
01702 {
01703 cell = new Cell( this, s, x, y );
01704 insertCell( cell );
01705 }
01706 if ( cell != d->defaultCell )
01707 {
01708
01709 worker.doWork( cell, true, x, y );
01710 }
01711 }
01712 }
01713 }
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++ )
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 else if(mode == Row)
02061 {
02062 for ( x = _marker.x(); x <=(_marker.x() + numberOfCells - 1); x++ )
02063 {
02064
02065
02066 cell = cellAt( x,_marker.y() );
02067
02068 if ( cell->isPartOfMerged() )
02069 {
02070 cell = cell->obscuringCells().first();
02071 undoRegion.setTop(QMIN(undoRegion.top(), cell->row()));
02072 }
02073 numberOfCells += cell->extraXCells();
02074 x += cell->extraXCells();
02075 }
02076 undoRegion.setBottom( _marker.y() );
02077 undoRegion.setRight( x - 1 );
02078 }
02079
02080 kdDebug() << "Saving undo information" << endl;
02081
02082 if ( !doc()->undoLocked() )
02083 {
02084 UndoChangeAreaTextCell *undo = new
02085 UndoChangeAreaTextCell( doc(), this, undoRegion );
02086 doc()->addCommand( undo );
02087 }
02088
02089 kdDebug() << "Saving undo information done" << endl;
02090
02091 x = _marker.x();
02092 y = _marker.y();
02093
02094
02095 double incr;
02096 Style * s = doc()->styleManager()->defaultStyle();
02097 if (step >= 0 && start < end)
02098 {
02099 for ( incr = start; incr <= end; )
02100 {
02101 cell = nonDefaultCell( x, y, false, s );
02102
02103 if ( cell->isPartOfMerged() )
02104 {
02105 cell = cell->obscuringCells().first();
02106 }
02107
02108
02109
02110 cell->setNumber( incr );
02111 if (mode == Column)
02112 {
02113 ++y;
02114 if (cell->doesMergeCells())
02115 {
02116 y += cell->extraYCells();
02117 }
02118 }
02119 else if (mode == Row)
02120 {
02121 ++x;
02122 if (cell->doesMergeCells())
02123 {
02124 x += cell->extraXCells();
02125 }
02126 }
02127 else
02128 {
02129 kdDebug(36001) << "Error in Series::mode" << endl;
02130 return;
02131 }
02132
02133 if (type == Linear)
02134 incr = incr + step;
02135 else if (type == Geometric)
02136 incr = incr * step;
02137 else
02138 {
02139 kdDebug(36001) << "Error in Series::type" << endl;
02140 return;
02141 }
02142 }
02143 }
02144 else
02145 if (step >= 0 && start > end)
02146 {
02147 for ( incr = start; incr >= end; )
02148 {
02149 cell = nonDefaultCell( x, y, false, s );
02150
02151 if (cell->isPartOfMerged())
02152 {
02153 cell = cell->obscuringCells().first();
02154 }
02155
02156
02157 cell->setNumber( incr );
02158 if (mode == Column)
02159 {
02160 ++y;
02161 if (cell->doesMergeCells())
02162 {
02163 y += cell->extraYCells();
02164 }
02165 }
02166 else if (mode == Row)
02167 {
02168 ++x;
02169 if (cell->doesMergeCells())
02170 {
02171 x += cell->extraXCells();
02172 }
02173 }
02174 else
02175 {
02176 kdDebug(36001) << "Error in Series::mode" << endl;
02177 return;
02178 }
02179
02180 if (type == Linear)
02181 incr = incr + step;
02182 else if (type == Geometric)
02183 incr = incr * step;
02184 else
02185 {
02186 kdDebug(36001) << "Error in Series::type" << endl;
02187 return;
02188 }
02189 }
02190 }
02191 else
02192 {
02193 for ( incr = start; incr <= end; )
02194 {
02195 cell = nonDefaultCell( x, y, false, s );
02196
02197 if (cell->isPartOfMerged())
02198 {
02199 cell = cell->obscuringCells().first();
02200 }
02201
02202
02203 cell->setNumber( incr );
02204 if (mode == Column)
02205 {
02206 ++y;
02207 if (cell->doesMergeCells())
02208 {
02209 y += cell->extraYCells();
02210 }
02211 }
02212 else if (mode == Row)
02213 {
02214 ++x;
02215 if (cell->doesMergeCells())
02216 {
02217 x += cell->extraXCells();
02218 }
02219 }
02220 else
02221 {
02222 kdDebug(36001) << "Error in Series::mode" << endl;
02223 return;
02224 }
02225
02226 if (type == Linear)
02227 incr = incr + step;
02228 else if (type == Geometric)
02229 {
02230
02231 incr = incr * step;
02232
02233
02234 if (step == 1)
02235 return;
02236 }
02237 else
02238 {
02239 kdDebug(36001) << "Error in Series::type" << endl;
02240 return;
02241 }
02242 }
02243 }
02244
02245 setRegionPaintDirty( undoRegion );
02246
02247
02248 emit sig_updateView( this );
02249 }
02250
02251
02252 struct SetSelectionPercentWorker : public Sheet::CellWorkerTypeA
02253 {
02254 bool b;
02255 SetSelectionPercentWorker( bool _b ) : b( _b ) { }
02256
02257 QString getUndoTitle() { return i18n("Format Percent"); }
02258 bool testCondition( RowFormat* ) {
02259
02260 return ( true );
02261 }
02262 void doWork( RowFormat* rw ) {
02263
02264 rw->setFormatType( b ? Percentage_format : Generic_format);
02265 }
02266 void doWork( ColumnFormat* cl ) {
02267 cl->setFormatType( b ? Percentage_format : Generic_format);
02268 }
02269 void prepareCell( Cell* cell ) {
02270 cell->format()->clearProperty(Format::PFormatType);
02271 cell->format()->clearNoFallBackProperties( Format::PFormatType );
02272 }
02273 bool testCondition( Cell* cell ) {
02274 return ( !cell->isPartOfMerged() );
02275 }
02276 void doWork( Cell* cell, bool cellRegion, int, int ) {
02277 if ( cellRegion )
02278 cell->setDisplayDirtyFlag();
02279 cell->format()->setFormatType( b ? Percentage_format : Generic_format);
02280 if ( cellRegion )
02281 cell->clearDisplayDirtyFlag();
02282 }
02283 };
02284
02285 void Sheet::setSelectionPercent( Selection* selectionInfo, bool b )
02286 {
02287 SetSelectionPercentWorker w( b );
02288 workOnCells( selectionInfo, w );
02289 }
02290
02291 void Sheet::slotAreaModified (const QString &name)
02292 {
02293 d->dependencies->areaModified (name);
02294 }
02295
02296
02297 void Sheet::refreshRemoveAreaName(const QString & _areaName)
02298 {
02299 Cell * c = d->cells.firstCell();
02300 QString tmp = "'" + _areaName + "'";
02301 for( ;c ; c = c->nextCell() )
02302 {
02303 if ( c->isFormula() )
02304 {
02305 if (c->text().find(tmp) != -1)
02306 {
02307 if ( !c->makeFormula() )
02308 kdError(36001) << "ERROR: Syntax ERROR" << endl;
02309 }
02310 }
02311 }
02312 }
02313
02314 void Sheet::refreshChangeAreaName(const QString & _areaName)
02315 {
02316 Cell * c = d->cells.firstCell();
02317 QString tmp = "'" + _areaName + "'";
02318 for( ;c ; c = c->nextCell() )
02319 {
02320 if ( c->isFormula() )
02321 {
02322 if (c->text().find(tmp) != -1)
02323 {
02324 if ( !c->makeFormula() )
02325 kdError(36001) << "ERROR: Syntax ERROR" << endl;
02326 else
02327 {
02328
02329 c->setCalcDirtyFlag();
02330 }
02331 }
02332 }
02333 }
02334 }
02335
02336 void Sheet::changeCellTabName( QString const & old_name, QString const & new_name )
02337 {
02338 Cell* c = d->cells.firstCell();
02339 for( ;c; c = c->nextCell() )
02340 {
02341 if( c->isFormula() )
02342 {
02343 if(c->text().find(old_name)!=-1)
02344 {
02345 int nb = c->text().contains(old_name+"!");
02346 QString tmp=old_name+"!";
02347 int len = tmp.length();
02348 tmp=c->text();
02349
02350 for( int i=0; i<nb; i++ )
02351 {
02352 int pos = tmp.find( old_name+"!" );
02353 tmp.replace( pos, len, new_name+"!" );
02354 }
02355 c->setCellText(tmp);
02356 }
02357 }
02358 }
02359 }
02360
02361 bool Sheet::shiftRow( const QRect &rect,bool makeUndo )
02362 {
02363 UndoInsertCellRow * undo = 0;
02364 if ( !doc()->undoLocked() &&makeUndo)
02365 {
02366 undo = new UndoInsertCellRow( doc(), this, rect );
02367 doc()->addCommand( undo );
02368 }
02369
02370 bool res=true;
02371 bool result;
02372 for( int i=rect.top(); i<=rect.bottom(); i++ )
02373 {
02374 for( int j=0; j<=(rect.right()-rect.left()); j++ )
02375 {
02376 result = d->cells.shiftRow( QPoint(rect.left(),i) );
02377 if( !result )
02378 res=false;
02379 }
02380 }
02381 QPtrListIterator<Sheet> it( workbook()->sheetList() );
02382 for( ; it.current(); ++it )
02383 {
02384 for(int i = rect.top(); i <= rect.bottom(); i++ )
02385 it.current()->changeNameCellRef( QPoint( rect.left(), i ), false,
02386 Sheet::ColumnInsert, name(),
02387 ( rect.right() - rect.left() + 1),
02388 undo);
02389 }
02390 refreshChart(QPoint(rect.left(),rect.top()), false, Sheet::ColumnInsert);
02391 refreshMergedCell();
02392 recalc();
02393 emit sig_updateView( this );
02394
02395 return res;
02396 }
02397
02398 bool Sheet::shiftColumn( const QRect& rect,bool makeUndo )
02399 {
02400 UndoInsertCellCol * undo = 0;
02401 if ( !doc()->undoLocked() &&makeUndo)
02402 {
02403 undo = new UndoInsertCellCol( doc(), this,rect);
02404 doc()->addCommand( undo );
02405 }
02406
02407 bool res=true;
02408 bool result;
02409 for( int i =rect.left(); i<=rect.right(); i++ )
02410 {
02411 for( int j=0; j<=(rect.bottom()-rect.top()); j++ )
02412 {
02413 result = d->cells.shiftColumn( QPoint(i,rect.top()) );
02414 if(!result)
02415 res=false;
02416 }
02417 }
02418
02419 QPtrListIterator<Sheet> it( workbook()->sheetList() );
02420 for( ; it.current(); ++it )
02421 {
02422 for(int i=rect.left();i<=rect.right();i++)
02423 it.current()->changeNameCellRef( QPoint( i, rect.top() ), false,
02424 Sheet::RowInsert, name(),
02425 ( rect.bottom() - rect.top() + 1 ),
02426 undo );
02427 }
02428 refreshChart(QPoint(rect.left(),rect.top()), false, Sheet::RowInsert);
02429 refreshMergedCell();
02430 recalc();
02431 emit sig_updateView( this );
02432
02433 return res;
02434 }
02435
02436 void Sheet::unshiftColumn( const QRect & rect,bool makeUndo )
02437 {
02438 UndoRemoveCellCol * undo = 0;
02439 if ( !doc()->undoLocked() && makeUndo )
02440 {
02441 undo = new UndoRemoveCellCol( doc(), this, rect );
02442 doc()->addCommand( undo );
02443 }
02444
02445 for(int i =rect.top();i<=rect.bottom();i++)
02446 for(int j=rect.left();j<=rect.right();j++)
02447 d->cells.remove(j,i);
02448
02449 for(int i =rect.left();i<=rect.right();i++)
02450 for(int j=0;j<=(rect.bottom()-rect.top());j++)
02451 d->cells.unshiftColumn( QPoint(i,rect.top()) );
02452
02453 QPtrListIterator<Sheet> it( workbook()->sheetList() );
02454 for( ; it.current(); ++it )
02455 for(int i=rect.left();i<=rect.right();i++)
02456 it.current()->changeNameCellRef( QPoint( i, rect.top() ), false,
02457 Sheet::RowRemove, name(),
02458 ( rect.bottom() - rect.top() + 1 ),
02459 undo );
02460
02461 refreshChart( QPoint(rect.left(),rect.top()), false, Sheet::RowRemove );
02462 refreshMergedCell();
02463 recalc();
02464 emit sig_updateView( this );
02465 }
02466
02467 void Sheet::unshiftRow( const QRect & rect,bool makeUndo )
02468 {
02469 UndoRemoveCellRow * undo = 0;
02470 if ( !doc()->undoLocked() && makeUndo )
02471 {
02472 undo = new UndoRemoveCellRow( doc(), this, rect );
02473 doc()->addCommand( undo );
02474 }
02475 for(int i =rect.top();i<=rect.bottom();i++)
02476 for(int j=rect.left();j<=rect.right();j++)
02477 d->cells.remove(j,i);
02478
02479 for(int i =rect.top();i<=rect.bottom();i++)
02480 for(int j=0;j<=(rect.right()-rect.left());j++)
02481 d->cells.unshiftRow( QPoint(rect.left(),i) );
02482
02483 QPtrListIterator<Sheet> it( workbook()->sheetList() );
02484 for( ; it.current(); ++it )
02485 for(int i=rect.top();i<=rect.bottom();i++)
02486 it.current()->changeNameCellRef( QPoint( rect.left(), i ), false,
02487 Sheet::ColumnRemove, name(),
02488 ( rect.right() - rect.left() + 1 ),
02489 undo);
02490
02491 refreshChart(QPoint(rect.left(),rect.top()), false, Sheet::ColumnRemove );
02492 refreshMergedCell();
02493 recalc();
02494 emit sig_updateView( this );
02495 }
02496
02497 bool Sheet::insertColumn( int col, int nbCol, bool makeUndo )
02498 {
02499 UndoInsertColumn * undo = 0;
02500 if ( !doc()->undoLocked() && makeUndo)
02501 {
02502 undo = new UndoInsertColumn( doc(), this, col, nbCol );
02503 doc()->addCommand( undo );
02504 }
02505
02506 bool res=true;
02507 bool result;
02508 for( int i=0; i<=nbCol; i++ )
02509 {
02510
02511 d->sizeMaxX -= columnFormat( KS_colMax )->dblWidth();
02512
02513 result = d->cells.insertColumn( col );
02514 d->columns.insertColumn( col );
02515 if(!result)
02516 res = false;
02517
02518
02519 d->sizeMaxX += columnFormat( col+i )->dblWidth();
02520 }
02521
02522 QPtrListIterator<Sheet> it( workbook()->sheetList() );
02523 for( ; it.current(); ++it )
02524 it.current()->changeNameCellRef( QPoint( col, 1 ), true,
02525 Sheet::ColumnInsert, name(),
02526 nbCol + 1, undo );
02527
02528
02529 d->print->insertColumn( col, nbCol );
02530
02531 refreshChart( QPoint( col, 1 ), true, Sheet::ColumnInsert );
02532 refreshMergedCell();
02533 recalc();
02534 emit sig_updateHBorder( this );
02535 emit sig_updateView( this );
02536
02537 return res;
02538 }
02539
02540 bool Sheet::insertRow( int row, int nbRow, bool makeUndo )
02541 {
02542 UndoInsertRow *undo = 0;
02543 if ( !doc()->undoLocked() && makeUndo)
02544 {
02545 undo = new UndoInsertRow( doc(), this, row, nbRow );
02546 doc()->addCommand( undo );
02547 }
02548
02549 bool res=true;
02550 bool result;
02551 for( int i=0; i<=nbRow; i++ )
02552 {
02553
02554 d->sizeMaxY -= rowFormat( KS_rowMax )->dblHeight();
02555
02556 result = d->cells.insertRow( row );
02557 d->rows.insertRow( row );
02558 if( !result )
02559 res = false;
02560
02561
02562 d->sizeMaxY += rowFormat( row )->dblHeight();
02563 }
02564
02565 QPtrListIterator<Sheet> it( workbook()->sheetList() );
02566 for( ; it.current(); ++it )
02567 it.current()->changeNameCellRef( QPoint( 1, row ), true,
02568 Sheet::RowInsert, name(),
02569 nbRow + 1, undo );
02570
02571
02572 d->print->insertRow( row, nbRow );
02573
02574 refreshChart( QPoint( 1, row ), true, Sheet::RowInsert );
02575 refreshMergedCell();
02576 recalc();
02577 emit sig_updateVBorder( this );
02578 emit sig_updateView( this );
02579
02580 return res;
02581 }
02582
02583 void Sheet::removeColumn( int col, int nbCol, bool makeUndo )
02584 {
02585 UndoRemoveColumn *undo = 0;
02586 if ( !doc()->undoLocked() && makeUndo)
02587 {
02588 undo = new UndoRemoveColumn( doc(), this, col, nbCol );
02589 doc()->addCommand( undo );
02590 }
02591
02592 for ( int i = 0; i <= nbCol; ++i )
02593 {
02594
02595 d->sizeMaxX -= columnFormat( col )->dblWidth();
02596
02597 d->cells.removeColumn( col );
02598 d->columns.removeColumn( col );
02599
02600
02601 d->sizeMaxX += columnFormat( KS_colMax )->dblWidth();
02602 }
02603
02604 QPtrListIterator<Sheet> it( workbook()->sheetList() );
02605 for( ; it.current(); ++it )
02606 it.current()->changeNameCellRef( QPoint( col, 1 ), true,
02607 Sheet::ColumnRemove, name(),
02608 nbCol + 1, undo );
02609
02610
02611 d->print->removeColumn( col, nbCol );
02612
02613 refreshChart( QPoint( col, 1 ), true, Sheet::ColumnRemove );
02614 refreshMergedCell();
02615 recalc();
02616 emit sig_updateHBorder( this );
02617 emit sig_updateView( this );
02618 }
02619
02620 void Sheet::removeRow( int row, int nbRow, bool makeUndo )
02621 {
02622 UndoRemoveRow *undo = 0;
02623 if ( !doc()->undoLocked() && makeUndo )
02624 {
02625 undo = new UndoRemoveRow( doc(), this, row, nbRow );
02626 doc()->addCommand( undo );
02627 }
02628
02629 for( int i=0; i<=nbRow; i++ )
02630 {
02631
02632 d->sizeMaxY -= rowFormat( row )->dblHeight();
02633
02634 d->cells.removeRow( row );
02635 d->rows.removeRow( row );
02636
02637
02638 d->sizeMaxY += rowFormat( KS_rowMax )->dblHeight();
02639 }
02640
02641 QPtrListIterator<Sheet> it( workbook()->sheetList() );
02642 for( ; it.current(); ++it )
02643 it.current()->changeNameCellRef( QPoint( 1, row ), true,
02644 Sheet::RowRemove, name(),
02645 nbRow + 1, undo );
02646
02647
02648 d->print->removeRow( row, nbRow );
02649
02650 refreshChart( QPoint( 1, row ), true, Sheet::RowRemove );
02651 refreshMergedCell();
02652 recalc();
02653 emit sig_updateVBorder( this );
02654 emit sig_updateView( this );
02655 }
02656
02657 void Sheet::hideRow(const Region& region)
02658 {
02659 HideShowManipulator* manipulator = new HideShowManipulator();
02660 manipulator->setSheet(this);
02661 manipulator->setManipulateRows(true);
02662 manipulator->add(region);
02663 manipulator->execute();
02664 }
02665
02666 void Sheet::emitHideRow()
02667 {
02668 emit sig_updateVBorder( this );
02669 emit sig_updateView( this );
02670 }
02671
02672 void Sheet::showRow(const Region& region)
02673 {
02674 HideShowManipulator* manipulator = new HideShowManipulator();
02675 manipulator->setSheet(this);
02676 manipulator->setManipulateRows(true);
02677 manipulator->setReverse(true);
02678 manipulator->add(region);
02679 manipulator->execute();
02680 }
02681
02682
02683 void Sheet::hideColumn(const Region& region)
02684 {
02685 HideShowManipulator* manipulator = new HideShowManipulator();
02686 manipulator->setSheet(this);
02687 manipulator->setManipulateColumns(true);
02688 manipulator->add(region);
02689 manipulator->execute();
02690 }
02691
02692 void Sheet::emitHideColumn()
02693 {
02694 emit sig_updateHBorder( this );
02695 emit sig_updateView( this );
02696 }
02697
02698 void Sheet::showColumn(const Region& region)
02699 {
02700 HideShowManipulator* manipulator = new HideShowManipulator();
02701 manipulator->setSheet(this);
02702 manipulator->setManipulateColumns(true);
02703 manipulator->setReverse(true);
02704 manipulator->add(region);
02705 manipulator->execute();
02706 }
02707
02708
02709 void Sheet::refreshChart(const QPoint & pos, bool fullRowOrColumn, ChangeRef ref)
02710 {
02711 Cell * c = d->cells.firstCell();
02712 for( ;c; c = c->nextCell() )
02713 {
02714 if ( (ref == ColumnInsert || ref == ColumnRemove) && fullRowOrColumn
02715 && c->column() >= (pos.x() - 1))
02716 {
02717 if (c->updateChart())
02718 return;
02719 }
02720 else if ( (ref == ColumnInsert || ref == ColumnRemove )&& !fullRowOrColumn
02721 && c->column() >= (pos.x() - 1) && c->row() == pos.y() )
02722 {
02723 if (c->updateChart())
02724 return;
02725 }
02726 else if ((ref == RowInsert || ref == RowRemove) && fullRowOrColumn
02727 && c->row() >= (pos.y() - 1))
02728 {
02729 if (c->updateChart())
02730 return;
02731 }
02732 else if ( (ref == RowInsert || ref == RowRemove) && !fullRowOrColumn
02733 && c->column() == pos.x() && c->row() >= (pos.y() - 1) )
02734 {
02735 if (c->updateChart())
02736 return;
02737 }
02738 }
02739
02740
02741
02742 if (c == 0L)
02743 {
02744 CellBinding * bind;
02745 for ( bind = firstCellBinding(); bind != 0L; bind = nextCellBinding() )
02746 {
02747 bind->cellChanged( 0 );
02748 }
02749
02750
02751
02752 }
02753
02754 }
02755
02756 void Sheet::refreshMergedCell()
02757 {
02758 Cell* c = d->cells.firstCell();
02759 for( ;c; c = c->nextCell() )
02760 {
02761 if(c->doesMergeCells())
02762 c->mergeCells( c->column(), c->row(), c->extraXCells(), c->extraYCells() );
02763 }
02764 }
02765
02766
02767 void Sheet::changeNameCellRef( const QPoint & pos, bool fullRowOrColumn,
02768 ChangeRef ref, QString tabname, int nbCol,
02769 UndoInsertRemoveAction * undo )
02770 {
02771 bool correctDefaultSheetName = (tabname == name());
02772 Cell* c = d->cells.firstCell();
02773 for( ;c; c = c->nextCell() )
02774 {
02775 if( c->isFormula() )
02776 {
02777 QString origText = c->text();
02778 unsigned int i = 0;
02779 bool error = false;
02780 QString newText;
02781
02782 bool correctSheetName = correctDefaultSheetName;
02783
02784 QChar origCh;
02785 for ( ; i < origText.length(); ++i )
02786 {
02787 origCh = origText[i];
02788 if ( origCh != ':' && origCh != '$' && !origCh.isLetter() )
02789 {
02790 newText += origCh;
02791
02792 correctSheetName = correctDefaultSheetName;
02793 }
02794 else
02795
02796 {
02797
02798 QString str;
02799 bool sheetNameFound = false;
02800 for( ; ( i < origText.length() ) &&
02801 ( ( origText[i].isLetter() || origText[i].isDigit() || origText[i] == '$' ) ||
02802 ( sheetNameFound && origText[i].isSpace() ) )
02803 ; ++i )
02804 {
02805 str += origText[i];
02806 if ( origText[i] == '!' )
02807 sheetNameFound = true;
02808 }
02809
02810 if ( origText[i] == '!' )
02811 {
02812 newText += str + '!';
02813
02814 correctSheetName = ( newText.right( tabname.length()+1 ) == tabname+"!" );
02815 }
02816 else
02817 {
02818
02819 Point point( str );
02820 if ( point.isValid() )
02821 {
02822 int col = point.pos().x();
02823 int row = point.pos().y();
02824 QString newPoint;
02825
02826
02827 if ( point.columnFixed() )
02828 newPoint = '$';
02829
02830 if( ref == ColumnInsert
02831 && correctSheetName
02832 && col + nbCol <= KS_colMax
02833 && col >= pos.x()
02834 && ( fullRowOrColumn || row == pos.y() ) )
02835 {
02836 newPoint += Cell::columnName( col + nbCol );
02837 }
02838 else if( ref == ColumnRemove
02839 && correctSheetName
02840 && col > pos.x()
02841 && ( fullRowOrColumn || row == pos.y() ) )
02842 {
02843 newPoint += Cell::columnName( col - nbCol );
02844 }
02845 else
02846 newPoint += Cell::columnName( col );
02847
02848
02849 if ( point.rowFixed() )
02850 newPoint += '$';
02851
02852 if( ref == RowInsert
02853 && correctSheetName
02854 && row + nbCol <= KS_rowMax
02855 && row >= pos.y()
02856 && ( fullRowOrColumn || col == pos.x() ) )
02857 {
02858 newPoint += QString::number( row + nbCol );
02859 }
02860 else if( ref == RowRemove
02861 && correctSheetName
02862 && row > pos.y()
02863 && ( fullRowOrColumn || col == pos.x() ) )
02864 {
02865 newPoint += QString::number( row - nbCol );
02866 }
02867 else
02868 newPoint += QString::number( row );
02869
02870 if( correctSheetName &&
02871 ( ( ref == ColumnRemove
02872 && col == pos.x()
02873 && ( fullRowOrColumn || row == pos.y() ) ) ||
02874 ( ref == RowRemove
02875 && row == pos.y()
02876 && ( fullRowOrColumn || col == pos.x() ) ) ||
02877 ( ref == ColumnInsert
02878 && col + nbCol > KS_colMax
02879 && col >= pos.x()
02880 && ( fullRowOrColumn || row == pos.y() ) ) ||
02881 ( ref == RowInsert
02882 && row + nbCol > KS_rowMax
02883 && row >= pos.y()
02884 && ( fullRowOrColumn || col == pos.x() ) ) ) )
02885 {
02886 newPoint = "#" + i18n("Dependency") + "!";
02887 error = true;
02888 }
02889
02890 newText += newPoint;
02891 }
02892 else
02893 {
02894 kdDebug(36001) << "Copying (unchanged) : '" << str << "'" << endl;
02895 newText += str;
02896 }
02897
02898 if ( i < origText.length() ) {
02899 newText += origText[i];
02900 if( origText[i] != ':' )
02901 correctSheetName = correctDefaultSheetName;
02902 }
02903 }
02904 }
02905 }
02906
02907 if ( error && undo != 0 )
02908 {
02909 QString formulaText = c->text();
02910 int origCol = c->column();
02911 int origRow = c->row();
02912
02913 if ( ref == ColumnInsert && origCol >= pos.x() )
02914 origCol -= nbCol;
02915 if ( ref == RowInsert && origRow >= pos.y() )
02916 origRow -= nbCol;
02917
02918 if ( ref == ColumnRemove && origCol >= pos.x() )
02919 origCol += nbCol;
02920 if ( ref == RowRemove && origRow >= pos.y() )
02921 origRow += nbCol;
02922
02923 undo->saveFormulaReference( this, origCol, origRow, formulaText );
02924 }
02925
02926 c->setCellText( newText );
02927 }
02928 }
02929 }
02930
02931 #if 0
02932 void Sheet::replace( const QString &_find, const QString &_replace, long options,
02933 Canvas *canvas )
02934 {
02935 Selection* selectionInfo = canvas->view()->selectionInfo();
02936
02937
02938 QRect region( selectionInfo->selection() );
02939 QPoint marker( selectionInfo->marker() );
02940
02941 if (options & KReplaceDialog::SelectedText)
02942 {
02943
02944
02945 if ( util_isRowSelected(region) )
02946 {
02947 }
02948
02949 else if ( util_isColumnSelected(region) )
02950 {
02951 }
02952 }
02953 else
02954 {
02955
02956 region.setCoords( 1, 1, d->maxRow, d->maxColumn );
02957 }
02958
02959
02960
02961 KReplace dialog( _find, _replace, options );
02962 QObject::connect(
02963 &dialog, SIGNAL( highlight( const QString &, int, int, const QRect & ) ),
02964 canvas, SLOT( highlight( const QString &, int, int, const QRect & ) ) );
02965 QObject::connect(
02966 &dialog, SIGNAL( replace( const QString &, int, int,int, const QRect & ) ),
02967 canvas, SLOT( replace( const QString &, int, int,int, const QRect & ) ) );
02968
02969
02970 if ( !doc()->undoLocked() )
02971 {
02972 UndoChangeAreaTextCell *undo = new UndoChangeAreaTextCell( doc(), this, region );
02973 doc()->addCommand( undo );
02974 }
02975
02976 QRect cellRegion( 0, 0, 0, 0 );
02977 bool bck = options & KFindDialog::FindBackwards;
02978
02979 int colStart = !bck ? region.left() : region.right();
02980 int colEnd = !bck ? region.right() : region.left();
02981 int rowStart = !bck ? region.top() :region.bottom();
02982 int rowEnd = !bck ? region.bottom() : region.top();
02983 if ( options & KFindDialog::FromCursor ) {
02984 colStart = marker.x();
02985 rowStart = marker.y();
02986 }
02987 Cell *cell;
02988 for (int row = rowStart ; !bck ? row < rowEnd : row > rowEnd ; !bck ? ++row : --row )
02989 {
02990 for(int col = colStart ; !bck ? col < colEnd : col > colEnd ; !bck ? ++col : --col )
02991 {
02992 cell = cellAt( col, row );
02993 if ( !cell->isDefault() && !cell->isObscured() && !cell->isFormula() )
02994 {
02995 QString text = cell->text();
02996 cellRegion.setTop( row );
02997 cellRegion.setLeft( col );
02998 if (!dialog.replace( text, cellRegion ))
02999 return;
03000 }
03001 }
03002 }
03003 }
03004 #endif
03005
03006 void Sheet::borderBottom( Selection* selectionInfo, const QColor &_color )
03007 {
03008 BorderManipulator* manipulator = new BorderManipulator();
03009 manipulator->setSheet(this);
03010 manipulator->setBottomBorderPen(QPen(_color, 1, Qt::SolidLine));
03011 manipulator->add(*selectionInfo);
03012 manipulator->execute();
03013 }
03014
03015 void Sheet::borderRight( Selection* selectionInfo, const QColor &_color )
03016 {
03017 BorderManipulator* manipulator = new BorderManipulator();
03018 manipulator->setSheet(this);
03019 manipulator->setRightBorderPen(QPen(_color, 1, Qt::SolidLine));
03020 manipulator->add(*selectionInfo);
03021 manipulator->execute();
03022 }
03023
03024 void Sheet::borderLeft( Selection* selectionInfo, const QColor &_color )
03025 {
03026 BorderManipulator* manipulator = new BorderManipulator();
03027 manipulator->setSheet(this);
03028 manipulator->setLeftBorderPen(QPen(_color, 1, Qt::SolidLine));
03029 manipulator->add(*selectionInfo);
03030 manipulator->execute();
03031 }
03032
03033 void Sheet::borderTop( Selection* selectionInfo, const QColor &_color )
03034 {
03035 BorderManipulator* manipulator = new BorderManipulator();
03036 manipulator->setSheet(this);
03037 manipulator->setTopBorderPen(QPen(_color, 1, Qt::SolidLine));
03038 manipulator->add(*selectionInfo);
03039 manipulator->execute();
03040 }
03041
03042 void Sheet::borderOutline( Selection* selectionInfo, const QColor &_color )
03043 {
03044 BorderManipulator* manipulator = new BorderManipulator();
03045 manipulator->setSheet(this);
03046 manipulator->setTopBorderPen(QPen(_color, 1, Qt::SolidLine));
03047 manipulator->setBottomBorderPen(QPen(_color, 1, Qt::SolidLine));
03048 manipulator->setLeftBorderPen(QPen(_color, 1, Qt::SolidLine));
03049 manipulator->setRightBorderPen(QPen(_color, 1, Qt::SolidLine));
03050 manipulator->add(*selectionInfo);
03051 manipulator->execute();
03052 }
03053
03054 void Sheet::borderAll( Selection * selectionInfo,
03055 const QColor & _color )
03056 {
03057 BorderManipulator* manipulator = new BorderManipulator();
03058 manipulator->setSheet(this);
03059 manipulator->setTopBorderPen(QPen(_color, 1, Qt::SolidLine));
03060 manipulator->setBottomBorderPen(QPen(_color, 1, Qt::SolidLine));
03061 manipulator->setLeftBorderPen(QPen(_color, 1, Qt::SolidLine));
03062 manipulator->setRightBorderPen(QPen(_color, 1, Qt::SolidLine));
03063 manipulator->setHorizontalPen(QPen(_color, 1, Qt::SolidLine));
03064 manipulator->setVerticalPen(QPen(_color, 1, Qt::SolidLine));
03065 manipulator->add(*selectionInfo);
03066 manipulator->execute();
03067 }
03068
03069 void Sheet::borderRemove( Selection* selectionInfo )
03070 {
03071 BorderManipulator* manipulator = new BorderManipulator();
03072 manipulator->setSheet(this);
03073 manipulator->setTopBorderPen(QPen(Qt::NoPen));
03074 manipulator->setBottomBorderPen(QPen(Qt::NoPen));
03075 manipulator->setLeftBorderPen(QPen(Qt::NoPen));
03076 manipulator->setRightBorderPen(QPen(Qt::NoPen));
03077 manipulator->setHorizontalPen(QPen(Qt::NoPen));
03078 manipulator->setVerticalPen(QPen(Qt::NoPen));
03079 manipulator->add(*selectionInfo);
03080 manipulator->execute();
03081 }
03082
03083
03084 void Sheet::sortByRow( const QRect &area, int ref_row, SortingOrder mode )
03085 {
03086 Point point;
03087 point.setSheet(this);
03088 point.setSheetName (d->name);
03089 point.setPos(area.topLeft());
03090 point.setColumnFixed(false);
03091 point.setRowFixed(false);
03092
03093 sortByRow( area, ref_row, 0, 0, mode, mode, mode, 0, false, false, point,true );
03094 }
03095
03096 void Sheet::sortByColumn( const QRect &area, int ref_column, SortingOrder mode )
03097 {
03098 Point point;
03099 point.setSheet(this);
03100 point.setSheetName(d->name);
03101 point.setPos(area.topLeft());
03102 point.setColumnFixed(false);
03103 point.setRowFixed(false);
03104
03105 sortByColumn( area, ref_column, 0, 0, mode, mode, mode, 0, false, false,
03106 point,true );
03107 }
03108
03109 void Sheet::checkCellContent(Cell * cell1, Cell * cell2, int & ret)
03110 {
03111 if ( cell1->isEmpty() )
03112 {
03113 ret = 1;
03114 return;
03115 }
03116 else if ( cell1->isObscured() && cell1->isPartOfMerged() )
03117 {
03118 ret = 1;
03119 return;
03120 }
03121 else if ( cell2->isEmpty() )
03122 {
03123 ret = 2;
03124 return;
03125 }
03126 ret = 0;
03127 }
03128
03129 void Sheet::sortByRow( const QRect &area, int key1, int key2, int key3,
03130 SortingOrder order1, SortingOrder order2,
03131 SortingOrder order3,
03132 QStringList const * firstKey, bool copyFormat,
03133 bool headerRow, Point const & outputPoint, bool respectCase )
03134 {
03135 QRect r( area );
03136 Map::respectCase = respectCase;
03137 Q_ASSERT( order1 == Increase || order1 == Decrease );
03138
03139
03140 Q_ASSERT( util_isColumnSelected(r) == false );
03141
03142
03143 if ( util_isRowSelected(r) )
03144 {
03145 r.setLeft( KS_colMax );
03146 r.setRight( 0 );
03147
03148
03149
03150
03151 for ( int row = r.top(); row <= r.bottom(); ++row )
03152 {
03153 Cell * c = getFirstCellRow( row );
03154 int col;
03155 while ( c )
03156 {
03157 col = c->column();
03158 if ( !c->isEmpty() )
03159 {
03160 if ( col > r.right() )
03161 r.rRight() = col;
03162 if ( col < r.left() )
03163 r.rLeft() = col;
03164 }
03165 c = getNextCellRight( col, row );
03166 }
03167 }
03168
03169
03170 if ( r.right() < r.left() )
03171 {
03172 Map::respectCase = true;
03173 return;
03174 }
03175 }
03176
03177 QRect target( outputPoint.pos().x(), outputPoint.pos().y(), r.width(), r.height() );
03178
03179 doc()->emitBeginOperation();
03180
03181 if ( !doc()->undoLocked() )
03182 {
03183 UndoSort *undo = new UndoSort( doc(), this, target );
03184 doc()->addCommand( undo );
03185 }
03186
03187 if (target.topLeft() != r.topLeft())
03188 {
03189 int targetLeft = target.left();
03190 int targetTop = target.top();
03191 int sourceTop = r.top();
03192 int sourceLeft = r.left();
03193
03194 key1 = key1 - sourceTop + targetTop;
03195 key2 = key2 - sourceTop + targetTop;
03196 key3 = key3 - sourceTop + targetTop;
03197
03198 for ( int x = 0; x < r.width(); ++x)
03199 {
03200 for ( int y = 0; y < r.height(); ++y )
03201 {
03202
03203 copyCells( sourceLeft + x, sourceTop + y,
03204 targetLeft + x, targetTop + y, copyFormat );
03205 }
03206 }
03207 }
03208
03209
03210
03211
03212 Cell * cell;
03213 Cell * cell1;
03214 Cell * cell2;
03215 Cell * bestCell;
03216 int status = 0;
03217
03218 for ( int d = target.left(); d <= target.right(); ++d )
03219 {
03220 cell1 = cellAt( d, key1 );
03221 if ( cell1->isObscured() && cell1->isPartOfMerged() )
03222 {
03223 Cell* obscuring = cell1->obscuringCells().first();
03224 cell = cellAt( obscuring->column(), key1 );
03225 cell1 = cellAt( obscuring->column() + cell->extraXCells() + 1,
03226 obscuring->column());
03227 d = obscuring->column() + cell->extraXCells() + 1;
03228 }
03229
03230
03231 bestCell = cell1;
03232 int bestX = d;
03233 for ( int x = d + 1 ; x <= target.right(); x++ )
03234 {
03235 cell2 = cellAt( x, key1 );
03236
03237 checkCellContent(cell2, bestCell, status);
03238 if (status == 1)
03239 continue;
03240 else if (status == 2)
03241 {
03242
03243 bestCell = cell2;
03244 bestX = x;
03245 continue;
03246 }
03247
03248 if ( firstKey )
03249 {
03250 int i1 = firstKey->findIndex( cell2->text() );
03251 int i2 = firstKey->findIndex( bestCell->text() );
03252
03253 if ( i1 != -1 && i2 != -1 )
03254 {
03255 if ( (order1 == Increase && i1 < i2 )
03256 || (order1 == Decrease && i1 > i2) )
03257 {
03258 bestCell = cell2;
03259 bestX = x;
03260 continue;
03261 }
03262
03263 if ( i1 == i2 )
03264 {
03265
03266 if (key2 <= 0)
03267 continue;
03268
03269 Cell * cell22 = cellAt( x, key2 );
03270 Cell * bestCell2 = cellAt( bestX, key2 );
03271
03272 if ( cell22->isEmpty() )
03273 {
03274
03275 continue;
03276 }
03277 else if ( cell22->isObscured() && cell22->isPartOfMerged() )
03278 {
03279
03280 continue;
03281 }
03282 else if ( bestCell2->isEmpty() )
03283 {
03284
03285 bestCell = cell2;
03286 bestX = x;
03287 continue;
03288 }
03289
03290 if ( (order2 == Increase && *cell22 < *bestCell2)
03291 || (order2 == Decrease && *cell22 > *bestCell2) )
03292 {
03293 bestCell = cell2;
03294 bestX = x;
03295 continue;
03296 }
03297 else if ( (order2 == Increase && *cell22 > *bestCell2)
03298 || (order2 == Decrease && *cell22 < *bestCell2) )
03299 {
03300
03301 continue;
03302 }
03303 else
03304 {
03305
03306 if (key3 <= 0)
03307 continue;
03308
03309 Cell * cell23 = cellAt( x, key3 );
03310 Cell * bestCell3 = cellAt( bestX, key3 );
03311
03312 if ( cell23->isEmpty() )
03313 {
03314
03315 continue;
03316 }
03317 else if ( cell23->isObscured() && cell23->isPartOfMerged() )
03318 {
03319
03320 continue;
03321 }
03322 else if ( bestCell3->isEmpty() )
03323 {
03324
03325 bestCell = cell2;
03326 bestX = x;
03327 continue;
03328 }
03329 if ( (order3 == Increase && *cell23 < *bestCell3)
03330 || (order3 == Decrease && *cell23 > *bestCell3) )
03331 {
03332
03333
03334 continue;
03335 }
03336 else
03337 {
03338 bestCell = cell2;
03339 bestX = x;
03340 continue;
03341 }
03342 }
03343 }
03344 continue;
03345 }
03346 else if ( i1 != -1 && i2 == -1 )
03347 {
03348
03349 bestCell = cell2;
03350 bestX = x;
03351 continue;
03352 }
03353 else if ( i2 != -1 && i1 == -1 )
03354 {
03355
03356
03357 continue;
03358 }
03359
03360
03361 }
03362
03363
03364 if ( (order1 == Increase && *cell2 < *bestCell)
03365 || (order1 == Decrease && *cell2 > *bestCell) )
03366 {
03367 bestCell = cell2;
03368 bestX = x;
03369 continue;
03370 }
03371 else if ( (order1 == Increase && *cell2 > *bestCell)
03372 || (order1 == Decrease && *cell2 < *bestCell) )
03373 {
03374
03375 continue;
03376 }
03377 else
03378 {
03379
03380
03381 if (key2 <= 0)
03382 continue;
03383 Cell * cell22 = cellAt( d, key2 );
03384 Cell * bestCell2 = cellAt( x, key2 );
03385
03386 checkCellContent(cell2, bestCell, status);
03387 if (status == 1)
03388 continue;
03389 else if (status == 2)
03390 {
03391
03392 bestCell = cell2;
03393 bestX = x;
03394 continue;
03395 }
03396
03397 if ( (order2 == Increase && *cell22 > *bestCell2)
03398 || (order2 == Decrease && *cell22 < *bestCell2) )
03399 {
03400 bestCell = cell2;
03401 bestX = x;
03402 continue;
03403 }
03404 else
03405 if ( (order2 == Increase && *cell22 > *bestCell2)
03406 || (order2 == Decrease && *cell22 < *bestCell2) )
03407 {
03408
03409 continue;
03410 }
03411 else
03412 {
03413
03414 if (key3 == 0)
03415 continue;
03416 Cell * cell23 = cellAt( d, key3 );
03417 Cell * bestCell3 = cellAt( x, key3 );
03418
03419 checkCellContent(cell2, bestCell, status);
03420 if (status == 1)
03421 continue;
03422 else if (status == 2)
03423 {
03424
03425 bestCell = cell2;
03426 bestX = x;
03427 continue;
03428 }
03429 if ( (order3 == Increase && *cell23 > *bestCell3)
03430 || (order3 == Decrease && *cell23 < *bestCell3) )
03431 {
03432 bestCell = cell2;
03433 bestX = x;
03434 continue;
03435 }
03436 else
03437 {
03438
03439
03440 continue;
03441 }
03442 }
03443 }
03444 }
03445
03446
03447 if ( d != bestX )
03448 {
03449 int top = target.top();
03450 if (headerRow)
03451 ++top;
03452
03453 for( int y = target.bottom(); y >= top; --y )
03454 {
03455 if ( y != key1 && y != key2 && y != key3 )
03456 swapCells( d, y, bestX, y, copyFormat );
03457 }
03458 if (key3 > 0)
03459 swapCells( d, key3, bestX, key3, copyFormat );
03460 if (key2 > 0)
03461 swapCells( d, key2, bestX, key2, copyFormat );
03462 swapCells( d, key1, bestX, key1, copyFormat );
03463 }
03464 }
03465 Map::respectCase = true;
03466
03467 emit sig_updateView( this );
03468 }
03469
03470 void Sheet::sortByColumn( const QRect &area, int key1, int key2, int key3,
03471 SortingOrder order1, SortingOrder order2,
03472 SortingOrder order3,
03473 QStringList const * firstKey, bool copyFormat,
03474 bool headerRow,
03475 Point const & outputPoint, bool respectCase )
03476 {
03477 QRect r( area );
03478 Map::respectCase = respectCase;
03479
03480 Q_ASSERT( order1 == Increase || order1 == Decrease );
03481
03482
03483 Q_ASSERT( util_isRowSelected(r) == false );
03484
03485
03486 if ( util_isColumnSelected(r) )
03487 {
03488 r.setTop( KS_rowMax );
03489 r.setBottom( 0 );
03490
03491
03492
03493
03494 for ( int col = r.left(); col <= r.right(); ++col )
03495 {
03496 Cell * c = getFirstCellColumn( col );
03497 int row;
03498 while ( c )
03499 {
03500 row = c->row();
03501 if ( !c->isEmpty() )
03502 {
03503 if ( row > r.bottom() )
03504 r.rBottom() = row;
03505 if ( row < r.top() )
03506 r.rTop() = row;
03507 }
03508 c = getNextCellDown( col, row );
03509 }
03510 }
03511
03512
03513 if ( r.bottom() < r.top() )
03514 {
03515 Map::respectCase = true;
03516 return;
03517 }
03518 }
03519 QRect target( outputPoint.pos().x(), outputPoint.pos().y(), r.width(), r.height() );
03520
03521 if ( !doc()->undoLocked() )
03522 {
03523 UndoSort *undo = new UndoSort( doc(), this, target );
03524 doc()->addCommand( undo );
03525 }
03526
03527 doc()->emitBeginOperation();
03528
03529 if (target.topLeft() != r.topLeft())
03530 {
03531 int targetLeft = target.left();
03532 int targetTop = target.top();
03533 int sourceTop = r.top();
03534 int sourceLeft = r.left();
03535
03536 key1 = key1 - sourceLeft + targetLeft;
03537 key2 = key2 - sourceLeft + targetLeft;
03538 key3 = key3 - sourceLeft + targetLeft;
03539
03540 for ( int x = 0; x < r.width(); ++x)
03541 {
03542 for ( int y = 0; y < r.height(); ++y )
03543 {
03544
03545 copyCells( sourceLeft + x, sourceTop + y,
03546 targetLeft + x, targetTop + y, copyFormat );
03547 }
03548 }
03549 }
03550
03551
03552
03553
03554
03555
03556 Cell * cell;
03557 Cell * cell1;
03558 Cell * cell2;
03559 Cell * bestCell;
03560 int status = 0;
03561
03562 int d = target.top();
03563
03564 if (headerRow)
03565 ++d;
03566
03567 for ( ; d <= target.bottom(); ++d )
03568 {
03569
03570 cell1 = cellAt( key1, d );
03571 if ( cell1->isObscured() && cell1->isPartOfMerged() )
03572 {
03573 Cell* obscuring = cell1->obscuringCells().first();
03574 cell = cellAt( key1, obscuring->row() );
03575 cell1 = cellAt( key1, obscuring->row() + cell->extraYCells() + 1 );
03576 d = obscuring->row() + cell->extraYCells() + 1;
03577 }
03578
03579 bestCell = cell1;
03580 int bestY = d;
03581
03582 for ( int y = d + 1 ; y <= target.bottom(); ++y )
03583 {
03584 cell2 = cellAt( key1, y );
03585
03586 if ( cell2->isEmpty() )
03587 {
03588
03589 continue;
03590 }
03591 else if ( cell2->isObscured() && cell2->isPartOfMerged() )
03592 {
03593
03594 continue;
03595 }
03596 else if ( bestCell->isEmpty() )
03597 {
03598
03599 bestCell = cell2;
03600 bestY = y;
03601 continue;
03602 }
03603
03604 if ( firstKey )
03605 {
03606 int i1 = firstKey->findIndex( cell2->text() );
03607 int i2 = firstKey->findIndex( bestCell->text() );
03608
03609 if ( i1 != -1 && i2 != -1 )
03610 {
03611 if ( (order1 == Increase && i1 < i2 )
03612 || (order1 == Decrease && i1 > i2) )
03613 {
03614 bestCell = cell2;
03615 bestY = y;
03616 continue;
03617 }
03618
03619 if ( i1 == i2 )
03620 {
03621
03622 if (key2 <= 0)
03623 continue;
03624 Cell * cell22 = cellAt( key2, d );
03625 Cell * bestCell2 = cellAt( key2, y );
03626
03627 if ( cell22->isEmpty() )
03628 {
03629
03630 continue;
03631 }
03632 else if ( cell22->isObscured() && cell22->isPartOfMerged() )
03633 {
03634
03635 continue;
03636 }
03637 else if ( bestCell2->isEmpty() )
03638 {
03639
03640 bestCell = cell2;
03641 bestY = y;
03642 continue;
03643 }
03644
03645 if ( (order2 == Increase && *cell22 > *bestCell2)
03646 || (order2 == Decrease && *cell22 < *bestCell2) )
03647 {
03648 bestCell = cell2;
03649 bestY = y;
03650 continue;
03651 }
03652 else if ( (order2 == Increase && *cell22 < *bestCell2)
03653 || (order2 == Decrease && *cell22 > *bestCell2) )
03654 {
03655
03656 continue;
03657 }
03658 else
03659 {
03660
03661 if (key3 <= 0)
03662 continue;
03663 Cell * cell23 = cellAt( key3, d );
03664 Cell * bestCell3 = cellAt( key3, y );
03665
03666 checkCellContent(cell2, bestCell, status);
03667 if (status == 1)
03668 continue;
03669 else if (status == 2)
03670 {
03671
03672 bestCell = cell2;
03673 bestY = y;
03674 continue;
03675 }
03676
03677 if ( (order3 == Increase && *cell23 < *bestCell3)
03678 || (order3 == Decrease && *cell23 > *bestCell3) )
03679 {
03680 bestCell = cell2;
03681 bestY = y;
03682 continue;
03683 }
03684 else
03685 {
03686
03687
03688 continue;
03689 }
03690 }
03691 }
03692 continue;
03693 }
03694 else if ( i1 != -1 && i2 == -1 )
03695 {
03696
03697 bestCell = cell2;
03698 bestY = y;
03699 continue;
03700 }
03701 else if ( i2 != -1 && i1 == -1 )
03702 {
03703
03704
03705 continue;
03706 }
03707
03708
03709 }
03710
03711
03712
03713 if ( (order1 == Increase && *cell2 < *bestCell)
03714 || (order1 == Decrease && *cell2 > *bestCell) )
03715 {
03716 bestCell = cell2;
03717 bestY = y;
03718 }
03719 else if ( (order1 == Increase && *cell2 > *bestCell)
03720 || (order1 == Decrease && *cell2 < *bestCell) )
03721 {
03722
03723 continue;
03724 }
03725 else
03726 {
03727
03728
03729 if (key2 == 0)
03730 continue;
03731 Cell * cell22 = cellAt( key2, y );
03732 Cell * bestCell2 = cellAt( key2, bestY );
03733
03734 if ( cell22->isEmpty() )
03735 {
03736
03737 continue;
03738 }
03739 else if ( cell22->isObscured() && cell22->isPartOfMerged() )
03740 {
03741
03742 continue;
03743 }
03744 else if ( bestCell2->isEmpty() )
03745 {
03746
03747 bestCell = cell2;
03748 bestY = y;
03749 continue;
03750 }
03751
03752 if ( (order2 == Increase && *cell22 < *bestCell2)
03753 || (order2 == Decrease && *cell22 > *bestCell2) )
03754 {
03755 bestCell = cell2;
03756 bestY = y;
03757 continue;
03758 }
03759 else if ( (order2 == Increase && *cell22 > *bestCell2)
03760 || (order2 == Decrease && *cell22 < *bestCell2) )
03761 {
03762 continue;
03763 }
03764 else
03765 {
03766
03767 if (key3 == 0)
03768 continue;
03769 Cell * cell23 = cellAt( key3, y );
03770 Cell * bestCell3 = cellAt( key3, bestY );
03771
03772 if ( cell23->isEmpty() )
03773 {
03774
03775 continue;
03776 }
03777 else if ( cell23->isObscured() && cell23->isPartOfMerged() )
03778 {
03779
03780 continue;
03781 }
03782 else if ( bestCell3->isEmpty() )
03783 {
03784
03785 bestCell = cell2;
03786 bestY = y;
03787 continue;
03788 }
03789
03790 if ( (order3 == Increase && *cell23 < *bestCell3)
03791 || (order3 == Decrease && *cell23 > *bestCell3) )
03792 {
03793 bestCell = cell2;
03794 bestY = y;
03795 continue;
03796 }
03797 else
03798 {
03799
03800
03801 continue;
03802 }
03803 }
03804 }
03805 }
03806
03807
03808 if ( d != bestY )
03809 {
03810 for (int x = target.left(); x <= target.right(); ++x)
03811 {
03812 if ( x != key1 && x != key2 && x != key3)
03813 swapCells( x, d, x, bestY, copyFormat );
03814 }
03815 if (key3 > 0)
03816 swapCells( key3, d, key3, bestY, copyFormat );
03817 if (key2 > 0)
03818 swapCells( key2, d, key2, bestY, copyFormat );
03819 swapCells( key1, d, key1, bestY, copyFormat );
03820 }
03821 }
03822
03823 Map::respectCase = true;
03824 emit sig_updateView( this );
03825 }
03826
03827
03828 void Sheet::copyCells( int x1, int y1, int x2, int y2, bool cpFormat )
03829 {
03830 Cell * sourceCell = cellAt( x1, y1 );
03831 Cell * targetCell = cellAt( x2, y2 );
03832
03833 if ( sourceCell->isDefault() && targetCell->isDefault())
03834 {
03835
03836 return;
03837 }
03838
03839 targetCell = nonDefaultCell(x2, y2);
03840
03841
03842 targetCell->copyContent( sourceCell );
03843
03844
03845
03846
03847
03848
03849
03850
03851
03852
03853
03854
03855
03856
03857 if (cpFormat)
03858 {
03859 targetCell->copyFormat( sourceCell );
03860
03861
03862
03863
03864
03865
03866
03867
03868
03869
03870
03871
03872
03873
03874
03875
03876
03877
03878
03879
03880
03881
03882
03883
03884
03885
03886
03887
03888 }
03889 }
03890
03891 void Sheet::swapCells( int x1, int y1, int x2, int y2, bool cpFormat )
03892 {
03893 Cell * ref1 = cellAt( x1, y1 );
03894 Cell * ref2 = cellAt( x2, y2 );
03895
03896 if ( ref1->isDefault() )
03897 {
03898 if ( !ref2->isDefault() )
03899 {
03900 ref1 = nonDefaultCell( x1, y1 );
03901
03902 }
03903 else
03904 return;
03905 }
03906 else
03907 if ( ref2->isDefault() )
03908 {
03909 ref2 = nonDefaultCell( x2, y2 );
03910
03911 }
03912
03913
03914
03915
03916
03917
03918 if (!ref1->isFormula() && !ref2->isFormula())
03919 {
03920 Cell *tmp = new Cell( this, -1, -1 );
03921
03922 tmp->copyContent( ref1 );
03923 ref1->copyContent( ref2 );
03924 ref2->copyContent( tmp );
03925
03926 delete tmp;
03927 }
03928 else
03929 if ( ref1->isFormula() && ref2->isFormula() )
03930 {
03931 QString d = ref1->encodeFormula();
03932 ref1->setCellText( ref1->decodeFormula( ref2->encodeFormula( ) ) );
03933 ref1->setCalcDirtyFlag();
03934 ref1->calc(false);
03935 ref2->setCellText( ref2->decodeFormula( d ) );
03936 ref2->setCalcDirtyFlag();
03937 ref2->calc(false);
03938 }
03939 else
03940 if (ref1->isFormula() && !ref2->isFormula() )
03941 {
03942 QString d = ref1->encodeFormula();
03943 ref1->setCellText(ref2->text());
03944 ref2->setCellText(ref2->decodeFormula(d));
03945 ref2->setCalcDirtyFlag();
03946 ref2->calc(false);
03947 }
03948 else
03949 if (!ref1->isFormula() && ref2->isFormula() )
03950 {
03951 QString d = ref2->encodeFormula();
03952 ref2->setCellText(ref1->text());
03953 ref1->setCellText(ref1->decodeFormula(d));
03954 ref1->setCalcDirtyFlag();
03955 ref1->calc(false);
03956 }
03957
03958 if (cpFormat)
03959 {
03960 Format::Align a = ref1->format()->align( ref1->column(), ref1->row() );
03961 ref1->format()->setAlign( ref2->format()->align( ref2->column(), ref2->row() ) );
03962 ref2->format()->setAlign(a);
03963
03964 Format::AlignY ay = ref1->format()->alignY( ref1->column(), ref1->row() );
03965 ref1->format()->setAlignY( ref2->format()->alignY( ref2->column(), ref2->row() ) );
03966 ref2->format()->setAlignY(ay);
03967
03968 QFont textFont = ref1->format()->textFont( ref1->column(), ref1->row() );
03969 ref1->format()->setTextFont( ref2->format()->textFont( ref2->column(), ref2->row() ) );
03970 ref2->format()->setTextFont(textFont);
03971
03972 QColor textColor = ref1->format()->textColor( ref1->column(), ref1->row() );
03973 ref1->format()->setTextColor( ref2->format()->textColor( ref2->column(), ref2->row() ) );
03974 ref2->format()->setTextColor(textColor);
03975
03976 QColor bgColor = ref1->bgColor( ref1->column(), ref1->row() );
03977 ref1->format()->setBgColor( ref2->bgColor( ref2->column(), ref2->row() ) );
03978 ref2->format()->setBgColor(bgColor);
03979
03980 QPen lbp = ref1->leftBorderPen( ref1->column(), ref1->row() );
03981 ref1->setLeftBorderPen( ref2->leftBorderPen( ref2->column(), ref2->row() ) );
03982 ref2->setLeftBorderPen(lbp);
03983
03984 QPen tbp = ref1->topBorderPen( ref1->column(), ref1->row() );
03985 ref1->setTopBorderPen( ref2->topBorderPen( ref2->column(), ref2->row() ) );
03986 ref2->setTopBorderPen(tbp);
03987
03988 QPen bbp = ref1->bottomBorderPen( ref1->column(), ref1->row() );
03989 ref1->setBottomBorderPen( ref2->bottomBorderPen( ref2->column(), ref2->row() ) );
03990 ref2->setBottomBorderPen(bbp);
03991
03992 QPen rbp = ref1->rightBorderPen( ref1->column(), ref1->row() );
03993 ref1->setRightBorderPen( ref2->rightBorderPen( ref2->column(), ref2->row() ) );
03994 ref2->setRightBorderPen(rbp);
03995
03996 QPen fdp = ref1->format()->fallDiagonalPen( ref1->column(), ref1->row() );
03997 ref1->format()->setFallDiagonalPen( ref2->format()->fallDiagonalPen( ref2->column(), ref2->row() ) );
03998 ref2->format()->setFallDiagonalPen(fdp);
03999
04000 QPen udp = ref1->format()->goUpDiagonalPen( ref1->column(), ref1->row() );
04001 ref1->format()->setGoUpDiagonalPen( ref2->format()->goUpDiagonalPen( ref2->column(), ref2->row() ) );
04002 ref2->format()->setGoUpDiagonalPen(udp);
04003
04004 QBrush bgBrush = ref1->backGroundBrush( ref1->column(), ref1->row() );
04005 ref1->format()->setBackGroundBrush( ref2->backGroundBrush( ref2->column(), ref2->row() ) );
04006 ref2->format()->setBackGroundBrush(bgBrush);
04007
04008 int pre = ref1->format()->precision( ref1->column(), ref1->row() );
04009 ref1->format()->setPrecision( ref2->format()->precision( ref2->column(), ref2->row() ) );
04010 ref2->format()->setPrecision(pre);
04011
04012 QString prefix = ref1->format()->prefix( ref1->column(), ref1->row() );
04013 ref1->format()->setPrefix( ref2->format()->prefix( ref2->column(), ref2->row() ) );
04014 ref2->format()->setPrefix(prefix);
04015
04016 QString postfix = ref1->format()->postfix( ref1->column(), ref1->row() );
04017 ref1->format()->setPostfix( ref2->format()->postfix( ref2->column(), ref2->row() ) );
04018 ref2->format()->setPostfix(postfix);
04019
04020 Format::FloatFormat f = ref1->format()->floatFormat( ref1->column(), ref1->row() );
04021 ref1->format()->setFloatFormat( ref2->format()->floatFormat( ref2->column(), ref2->row() ) );
04022 ref2->format()->setFloatFormat(f);
04023
04024 Format::FloatColor c = ref1->format()->floatColor( ref1->column(), ref1->row() );
04025 ref1->format()->setFloatColor( ref2->format()->floatColor( ref2->column(), ref2->row() ) );
04026 ref2->format()->setFloatColor(c);
04027
04028 bool multi = ref1->format()->multiRow( ref1->column(), ref1->row() );
04029 ref1->format()->setMultiRow( ref2->format()->multiRow( ref2->column(), ref2->row() ) );
04030 ref2->format()->setMultiRow(multi);
04031
04032 bool vert = ref1->format()->verticalText( ref1->column(), ref1->row() );
04033 ref1->format()->setVerticalText( ref2->format()->verticalText( ref2->column(), ref2->row() ) );
04034 ref2->format()->setVerticalText(vert);
04035
04036 bool print = ref1->format()->getDontprintText( ref1->column(), ref1->row() );
04037 ref1->format()->setDontPrintText( ref2->format()->getDontprintText( ref2->column(), ref2->row() ) );
04038 ref2->format()->setDontPrintText(print);
04039
04040 double ind = ref1->format()->getIndent( ref1->column(), ref1->row() );
04041 ref1->format()->setIndent( ref2->format()->getIndent( ref2->column(), ref2->row() ) );
04042 ref2->format()->setIndent( ind );
04043
04044 QValueList<Conditional> conditionList = ref1->conditionList();
04045 ref1->setConditionList(ref2->conditionList());
04046 ref2->setConditionList(conditionList);
04047
04048 QString com = ref1->format()->comment( ref1->column(), ref1->row() );
04049 ref1->format()->setComment( ref2->format()->comment( ref2->column(), ref2->row() ) );
04050 ref2->format()->setComment(com);
04051
04052 int angle = ref1->format()->getAngle( ref1->column(), ref1->row() );
04053 ref1->format()->setAngle( ref2->format()->getAngle( ref2->column(), ref2->row() ) );
04054 ref2->format()->setAngle(angle);
04055
04056 FormatType form = ref1->format()->getFormatType( ref1->column(), ref1->row() );
04057 ref1->format()->setFormatType( ref2->format()->getFormatType( ref2->column(), ref2->row() ) );
04058 ref2->format()->setFormatType(form);
04059 }
04060 }
04061
04062 void Sheet::refreshPreference()
04063 {
04064 if ( getAutoCalc() )
04065 recalc();
04066
04067 emit sig_updateHBorder( this );
04068 emit sig_updateView( this );
04069 }
04070
04071
04072 bool Sheet::areaIsEmpty(const Region& region, TestType _type)
04073 {
04074 Region::ConstIterator endOfList = region.constEnd();
04075 for (Region::ConstIterator it = region.constBegin(); it != endOfList; ++it)
04076 {
04077 QRect range = (*it)->rect().normalize();
04078
04079 if ((*it)->isRow())
04080 {
04081 for ( int row = range.top(); row <= range.bottom(); ++row )
04082 {
04083 Cell * c = getFirstCellRow( row );
04084 while ( c )
04085 {
04086 if ( !c->isPartOfMerged())
04087 {
04088 switch( _type )
04089 {
04090 case Text :
04091 if ( !c->text().isEmpty())
04092 return false;
04093 break;
04094 case Validity:
04095 if ( c->getValidity(0))
04096 return false;
04097 break;
04098 case Comment:
04099 if ( !c->format()->comment(c->column(), row).isEmpty())
04100 return false;
04101 break;
04102 case ConditionalCellAttribute:
04103 if ( c->conditionList().count()> 0)
04104 return false;
04105 break;
04106 }
04107 }
04108
04109 c = getNextCellRight( c->column(), row );
04110 }
04111 }
04112 }
04113
04114 else if ((*it)->isColumn())
04115 {
04116 for ( int col = range.left(); col <= range.right(); ++col )
04117 {
04118 Cell * c = getFirstCellColumn( col );
04119 while ( c )
04120 {
04121 if ( !c->isPartOfMerged() )
04122 {
04123 switch( _type )
04124 {
04125 case Text :
04126 if ( !c->text().isEmpty())
04127 return false;
04128 break;
04129 case Validity:
04130 if ( c->getValidity(0))
04131 return false;
04132 break;
04133 case Comment:
04134 if ( !c->format()->comment(col, c->row()).isEmpty())
04135 return false;
04136 break;
04137 case ConditionalCellAttribute:
04138 if ( c->conditionList().count()> 0)
04139 return false;
04140 break;
04141 }
04142 }
04143
04144 c = getNextCellDown( col, c->row() );
04145 }
04146 }
04147 }
04148 else
04149 {
04150 Cell * cell;
04151
04152 int right = range.right();
04153 int bottom = range.bottom();
04154 for ( int x = range.left(); x <= right; ++x )
04155 for ( int y = range.top(); y <= bottom; ++y )
04156 {
04157 cell = cellAt( x, y );
04158 if (!cell->isPartOfMerged() )
04159 {
04160 switch( _type )
04161 {
04162 case Text :
04163 if ( !cell->text().isEmpty())
04164 return false;
04165 break;
04166 case Validity:
04167 if ( cell->getValidity(0))
04168 return false;
04169 break;
04170 case Comment:
04171 if ( !cell->format()->comment(x, y).isEmpty())
04172 return false;
04173 break;
04174 case ConditionalCellAttribute:
04175 if ( cell->conditionList().count()> 0)
04176 return false;
04177 break;
04178 }
04179 }
04180 }
04181 }
04182 }
04183 return true;
04184 }
04185
04186 struct SetSelectionMultiRowWorker : public Sheet::CellWorker
04187 {
04188 bool enable;
04189 SetSelectionMultiRowWorker( bool _enable )
04190 : Sheet::CellWorker( ), enable( _enable ) { }
04191
04192 class UndoAction* createUndoAction( Doc * doc, Sheet * sheet, const KSpread::Region& region )
04193 {
04194 QString title = i18n("Multirow");
04195 return new UndoCellFormat( doc, sheet, region, title );
04196 }
04197
04198 bool testCondition( Cell * cell )
04199 {
04200 return ( !cell->isPartOfMerged() );
04201 }
04202
04203 void doWork( Cell * cell, bool, int, int )
04204 {
04205 cell->setDisplayDirtyFlag();
04206 cell->format()->setMultiRow( enable );
04207 cell->format()->setVerticalText( false );
04208 cell->format()->setAngle( 0 );
04209 cell->clearDisplayDirtyFlag();
04210 }
04211 };
04212
04213 void Sheet::setSelectionMultiRow( Selection* selectionInfo,
04214 bool enable )
04215 {
04216 SetSelectionMultiRowWorker w( enable );
04217 workOnCells( selectionInfo, w );
04218 }
04219
04220 QString Sheet::guessColumnTitle(QRect& area, int col)
04221 {
04222
04223 Range rg;
04224 rg.setRange(area);
04225 rg.setSheet(this);
04226
04227 if ( (!rg.isValid()) || (col < area.left()) || (col > area.right()))
04228 return QString();
04229
04230
04231
04232
04233
04234
04235
04236
04237
04238
04239
04240
04241
04242 Value cellValue=value(col,area.top());
04243 return cellValue.asString();
04244 }
04245
04246 QString Sheet::guessRowTitle(QRect& area, int row)
04247 {
04248
04249 Range rg;
04250 rg.setRange(area);
04251 rg.setSheet(this);
04252
04253 if ( (!rg.isValid()) || (row < area.top()) || (row > area.bottom()) )
04254 return QString();
04255
04256
04257
04258
04259
04260
04261
04262
04263
04264
04265
04266
04267 Value cellValue=value(area.left(),row);
04268 return cellValue.asString();
04269 }
04270
04271 void Sheet::setSelectionAlign( Selection* selectionInfo,
04272 Format::Align _align )
04273 {
04274 HorAlignManipulator* manipulator = new HorAlignManipulator();
04275 manipulator->setSheet(this);
04276 manipulator->setProperty(Format::PAlign);
04277 manipulator->setHorizontalAlignment(_align);
04278 manipulator->add(*selectionInfo);
04279 manipulator->execute();
04280 }
04281
04282 void Sheet::setSelectionAlignY( Selection* selectionInfo,
04283 Format::AlignY _alignY )
04284 {
04285 VerAlignManipulator* manipulator = new VerAlignManipulator();
04286 manipulator->setSheet(this);
04287 manipulator->setProperty(Format::PAlignY);
04288 manipulator->setVerticalAlignment(_alignY);
04289 manipulator->add(*selectionInfo);
04290 manipulator->execute();
04291 }
04292
04293
04294 struct SetSelectionPrecisionWorker : public Sheet::CellWorker {
04295 int _delta;
04296 SetSelectionPrecisionWorker( int delta ) : Sheet::CellWorker( ), _delta( delta ) { }
04297
04298 class UndoAction* createUndoAction( Doc* doc, Sheet* sheet, const KSpread::Region& region ) {
04299 QString title=i18n("Change Precision");
04300 return new UndoCellFormat( doc, sheet, region, title );
04301 }
04302 bool testCondition( Cell* cell ) {
04303 return ( !cell->isPartOfMerged() );
04304 }
04305 void doWork( Cell* cell, bool, int, int ) {
04306 cell->setDisplayDirtyFlag();
04307 if ( _delta == 1 )
04308 cell->incPrecision();
04309 else
04310 cell->decPrecision();
04311 cell->clearDisplayDirtyFlag();
04312 }
04313 };
04314
04315 void Sheet::setSelectionPrecision( Selection* selectionInfo,
04316 int _delta )
04317 {
04318 SetSelectionPrecisionWorker w( _delta );
04319 workOnCells( selectionInfo, w );
04320 }
04321
04322 struct SetSelectionStyleWorker : public Sheet::CellWorkerTypeA
04323 {
04324 Style * m_style;
04325 SetSelectionStyleWorker( Style * style )
04326 : m_style( style )
04327 {
04328 }
04329
04330 QString getUndoTitle()
04331 {
04332 return i18n("Apply Style");
04333 }
04334
04335 void doWork( RowFormat* rw )
04336 {
04337 rw->setStyle( m_style );
04338 }
04339
04340 void doWork( ColumnFormat* cl )
04341 {
04342 cl->setStyle( m_style );
04343 }
04344
04345 bool testCondition( Cell* cell )
04346 {
04347 return ( !cell->isPartOfMerged() && cell->format()->style() != m_style );
04348 }
04349
04350 void doWork( Cell* cell, bool cellRegion, int, int )
04351 {
04352 if ( cellRegion )
04353 cell->setDisplayDirtyFlag();
04354
04355 cell->format()->setStyle( m_style );
04356
04357 if ( cellRegion )
04358 cell->clearDisplayDirtyFlag();
04359 }
04360 };
04361
04362
04363 void Sheet::setSelectionStyle( Selection * selectionInfo, Style * style )
04364 {
04365 SetSelectionStyleWorker w( style );
04366 workOnCells( selectionInfo, w );
04367 }
04368
04369 struct SetSelectionMoneyFormatWorker : public Sheet::CellWorkerTypeA
04370 {
04371 bool b;
04372 Doc *m_pDoc;
04373 SetSelectionMoneyFormatWorker( bool _b,Doc* _doc ) : b( _b ), m_pDoc(_doc) { }
04374 QString getUndoTitle() { return i18n("Format Money"); }
04375 bool testCondition( RowFormat* rw ) {
04376 return ( rw->hasProperty( Format::PFormatType )
04377 || rw->hasProperty( Format::PPrecision ) );
04378 }
04379 void doWork( RowFormat* rw ) {
04380 rw->setFormatType( b ? Money_format : Generic_format );
04381 rw->setPrecision( b ? m_pDoc->locale()->fracDigits() : 0 );
04382 }
04383 void doWork( ColumnFormat* cl ) {
04384 cl->setFormatType( b ? Money_format : Generic_format );
04385 cl->setPrecision( b ? m_pDoc->locale()->fracDigits() : 0 );
04386 }
04387 void prepareCell( Cell* c ) {
04388 c->format()->clearProperty( Format::PPrecision );
04389 c->format()->clearNoFallBackProperties( Format::PPrecision );
04390 c->format()->clearProperty( Format::PFormatType );
04391 c->format()->clearNoFallBackProperties( Format::PFormatType );
04392 }
04393 bool testCondition( Cell* cell ) {
04394 return ( !cell->isPartOfMerged() );
04395 }
04396 void doWork( Cell* cell, bool cellRegion, int, int ) {
04397 if ( cellRegion )
04398 cell->setDisplayDirtyFlag();
04399 cell->format()->setFormatType( b ? Money_format : Generic_format );
04400 cell->format()->setPrecision( b ? m_pDoc->locale()->fracDigits() : 0 );
04401 if ( cellRegion )
04402 cell->clearDisplayDirtyFlag();
04403 }
04404 };
04405
04406
04407 void Sheet::setSelectionMoneyFormat( Selection* selectionInfo,
04408 bool b )
04409 {
04410 SetSelectionMoneyFormatWorker w( b,doc() );
04411 workOnCells( selectionInfo, w );
04412 }
04413
04414
04415 struct IncreaseIndentWorker : public Sheet::CellWorkerTypeA {
04416 double tmpIndent;
04417 double valIndent;
04418
04419 IncreaseIndentWorker( double _tmpIndent, double _valIndent )
04420 : tmpIndent( _tmpIndent ), valIndent( _valIndent ) { }
04421
04422 QString getUndoTitle() { return i18n("Increase Indent"); }
04423 bool testCondition( RowFormat* rw ) {
04424 return ( rw->hasProperty( Format::PIndent ) );
04425 }
04426
04427 void doWork( RowFormat* rw ) {
04428 rw->setIndent( tmpIndent+valIndent );
04429
04430 }
04431 void doWork( ColumnFormat* cl ) {
04432 cl->setIndent( tmpIndent+valIndent );
04433
04434 }
04435 void prepareCell( Cell* c ) {
04436 c->format()->clearProperty( Format::PIndent );
04437 c->format()->clearNoFallBackProperties( Format::PIndent );
04438
04439
04440 }
04441 bool testCondition( Cell* cell ) {
04442 return ( !cell->isPartOfMerged() );
04443 }
04444 void doWork( Cell* cell, bool cellRegion, int x, int y ) {
04445 if ( cellRegion ) {
04446 if(cell->format()->align(x,y)!=Format::Left)
04447 {
04448
04449
04450 }
04451 cell->setDisplayDirtyFlag();
04452 cell->format()->setIndent( cell->format()->getIndent(x,y) +valIndent );
04453 cell->clearDisplayDirtyFlag();
04454 } else {
04455 cell->format()->setIndent( tmpIndent+valIndent);
04456
04457 }
04458 }
04459 };
04460
04461
04462 void Sheet::increaseIndent(Selection* selectionInfo)
04463 {
04464 QPoint marker(selectionInfo->marker());
04465 double valIndent = doc()->getIndentValue();
04466 Cell *c = cellAt( marker );
04467 double tmpIndent = c->format()->getIndent( marker.x(), marker.y() );
04468
04469 IncreaseIndentWorker w( tmpIndent, valIndent );
04470 workOnCells( selectionInfo, w );
04471 }
04472
04473
04474 struct DecreaseIndentWorker : public Sheet::CellWorkerTypeA {
04475 double tmpIndent, valIndent;
04476 DecreaseIndentWorker( double _tmpIndent, double _valIndent ) : tmpIndent( _tmpIndent ), valIndent( _valIndent ) { }
04477 QString getUndoTitle() { return i18n("Decrease Indent"); }
04478 bool testCondition( RowFormat* rw ) {
04479 return ( rw->hasProperty( Format::PIndent ) );
04480 }
04481 void doWork( RowFormat* rw ) {
04482 rw->setIndent( QMAX( 0.0, tmpIndent - valIndent ) );
04483 }
04484 void doWork( ColumnFormat* cl ) {
04485 cl->setIndent( QMAX( 0.0, tmpIndent - valIndent ) );
04486 }
04487 void prepareCell( Cell* c ) {
04488 c->format()->clearProperty( Format::PIndent );
04489 c->format()->clearNoFallBackProperties( Format::PIndent );
04490 }
04491 bool testCondition( Cell* cell ) {
04492 return ( !cell->isPartOfMerged() );
04493 }
04494 void doWork( Cell* cell, bool cellRegion, int x, int y ) {
04495 if ( cellRegion ) {
04496 cell->setDisplayDirtyFlag();
04497 cell->format()->setIndent( QMAX( 0.0, cell->format()->getIndent( x, y ) - valIndent ) );
04498 cell->clearDisplayDirtyFlag();
04499 } else {
04500 cell->format()->setIndent( QMAX( 0.0, tmpIndent - valIndent ) );
04501 }
04502 }
04503 };
04504
04505
04506 void Sheet::decreaseIndent( Selection* selectionInfo )
04507 {
04508 double valIndent = doc()->getIndentValue();
04509 QPoint marker(selectionInfo->marker());
04510 Cell* c = cellAt( marker );
04511 double tmpIndent = c->format()->getIndent( marker.x(), marker.y() );
04512
04513 DecreaseIndentWorker w( tmpIndent, valIndent );
04514 workOnCells( selectionInfo, w );
04515 }
04516
04517
04518 int Sheet::adjustColumnHelper( Cell * c, int _col, int _row )
04519 {
04520 double long_max = 0.0;
04521 c->calculateTextParameters( painter(), _col, _row );
04522 if ( c->textWidth() > long_max )
04523 {
04524 double indent = 0.0;
04525 int a = c->format()->align( c->column(), c->row() );
04526 if ( a == Format::Undefined )
04527 {
04528 if ( c->value().isNumber() || c->isDate() || c->isTime())
04529 a = Format::Right;
04530 else
04531 a = Format::Left;
04532 }
04533
04534 if ( a == Format::Left )
04535 indent = c->format()->getIndent( c->column(), c->row() );
04536 long_max = indent + c->textWidth()
04537 + c->format()->leftBorderWidth( c->column(), c->row() )
04538 + c->format()->rightBorderWidth( c->column(), c->row() );
04539 }
04540 return (int)long_max;
04541 }
04542
04543 void Sheet::adjustArea(const Region& region)
04544 {
04545 AdjustColumnRowManipulator* manipulator = new AdjustColumnRowManipulator();
04546 manipulator->setSheet(this);
04547 manipulator->setAdjustColumn(true);
04548 manipulator->setAdjustRow(true);
04549 manipulator->add(region);
04550 manipulator->execute();
04551 }
04552
04553 void Sheet::adjustColumn(const Region& region)
04554 {
04555 AdjustColumnRowManipulator* manipulator = new AdjustColumnRowManipulator();
04556 manipulator->setSheet(this);
04557 manipulator->setAdjustColumn(true);
04558 manipulator->add(region);
04559 manipulator->execute();
04560 }
04561
04562 void Sheet::adjustRow(const Region& region)
04563 {
04564 AdjustColumnRowManipulator* manipulator = new AdjustColumnRowManipulator();
04565 manipulator->setSheet(this);
04566 manipulator->setAdjustRow(true);
04567 manipulator->add(region);
04568 manipulator->execute();
04569 }
04570
04571 struct ClearTextSelectionWorker : public Sheet::CellWorker {
04572 Sheet * _s;
04573
04574 ClearTextSelectionWorker( Sheet * s )
04575 : Sheet::CellWorker( ), _s( s ) { }
04576
04577 class UndoAction* createUndoAction( Doc* doc, Sheet* sheet, const KSpread::Region& region ) {
04578 return new UndoChangeAreaTextCell( doc, sheet, region );
04579 }
04580 bool testCondition( Cell* cell ) {
04581 return ( !cell->isObscured() );
04582 }
04583 void doWork( Cell* cell, bool, int, int )
04584 {
04585 cell->setCellText( "" );
04586 }
04587 };
04588
04589 void Sheet::clearTextSelection( Selection* selectionInfo )
04590 {
04591 if (areaIsEmpty(*selectionInfo))
04592 return;
04593
04594 ClearTextSelectionWorker w( this );
04595 workOnCells( selectionInfo, w );
04596 }
04597
04598
04599 struct ClearValiditySelectionWorker : public Sheet::CellWorker {
04600 ClearValiditySelectionWorker( ) : Sheet::CellWorker( ) { }
04601
04602 class UndoAction* createUndoAction( Doc* doc, Sheet* sheet, const KSpread::Region& region ) {
04603 return new UndoConditional( doc, sheet, region );
04604 }
04605 bool testCondition( Cell* cell ) {
04606 return ( !cell->isObscured() );
04607 }
04608 void doWork( Cell* cell, bool, int, int ) {
04609 cell->removeValidity();
04610 }
04611 };
04612
04613 void Sheet::clearValiditySelection( Selection* selectionInfo )
04614 {
04615 if (areaIsEmpty(*selectionInfo, Validity))
04616 return;
04617
04618 ClearValiditySelectionWorker w;
04619 workOnCells( selectionInfo, w );
04620 }
04621
04622
04623 struct ClearConditionalSelectionWorker : public Sheet::CellWorker
04624 {
04625 ClearConditionalSelectionWorker( ) : Sheet::CellWorker( ) { }
04626
04627 class UndoAction* createUndoAction( Doc* doc,
04628 Sheet* sheet,
04629 const KSpread::Region& region )
04630 {
04631 return new UndoConditional( doc, sheet, region );
04632 }
04633 bool testCondition( Cell* cell )
04634 {
04635 return ( !cell->isObscured() );
04636 }
04637 void doWork( Cell* cell, bool, int, int )
04638 {
04639 QValueList<Conditional> emptyList;
04640 cell->setConditionList(emptyList);
04641 }
04642 };
04643
04644 void Sheet::clearConditionalSelection( Selection* selectionInfo )
04645 {
04646 ClearConditionalSelectionWorker w;
04647 workOnCells( selectionInfo, w );
04648 }
04649
04650 void Sheet::fillSelection( Selection * selectionInfo, int direction )
04651 {
04652 QRect rct( selectionInfo->selection() );
04653 int right = rct.right();
04654 int bottom = rct.bottom();
04655 int left = rct.left();
04656 int top = rct.top();
04657 int width = rct.width();
04658 int height = rct.height();
04659
04660 QDomDocument undoDoc = saveCellRegion( rct );
04661 loadSelectionUndo( undoDoc, rct, left - 1, top - 1, false, 0 );
04662
04663 QDomDocument doc;
04664
04665 switch( direction )
04666 {
04667 case Right:
04668 doc = saveCellRegion( QRect( left, top, 1, height ) );
04669 break;
04670
04671 case Up:
04672 doc = saveCellRegion( QRect( left, bottom, width, 1 ) );
04673 break;
04674
04675 case Left:
04676 doc = saveCellRegion( QRect( right, top, 1, height ) );
04677 break;
04678
04679 case Down:
04680 doc = saveCellRegion( QRect( left, top, width, 1 ) );
04681 break;
04682 };
04683
04684
04685 QBuffer buffer;
04686 buffer.open( IO_WriteOnly );
04687 QTextStream str( &buffer );
04688 str.setEncoding( QTextStream::UnicodeUTF8 );
04689 str << doc;
04690 buffer.close();
04691
04692 int i;
04693 switch( direction )
04694 {
04695 case Right:
04696 for ( i = left + 1; i <= right; ++i )
04697 {
04698 paste( buffer.buffer(), QRect( i, top, 1, 1 ), false );
04699 }
04700 break;
04701
04702 case Up:
04703 for ( i = bottom + 1; i >= top; --i )
04704 {
04705 paste( buffer.buffer(), QRect( left, i, 1, 1 ), false );
04706 }
04707 break;
04708
04709 case Left:
04710 for ( i = right - 1; i >= left; --i )
04711 {
04712 paste( buffer.buffer(), QRect( i, top, 1, 1 ), false );
04713 }
04714 break;
04715
04716 case Down:
04717 for ( i = top + 1; i <= bottom; ++i )
04718 {
04719 paste( buffer.buffer(), QRect( left, i, 1, 1 ), false );
04720 }
04721 break;
04722 }
04723
04724 this->doc()->setModified( true );
04725 }
04726
04727
04728 struct DefaultSelectionWorker : public Sheet::CellWorker {
04729 DefaultSelectionWorker( ) : Sheet::CellWorker( true, false, true ) { }
04730
04731 class UndoAction* createUndoAction( Doc* doc, Sheet* sheet, const KSpread::Region& region ) {
04732 QString title=i18n("Default Parameters");
04733 return new UndoCellFormat( doc, sheet, region, title );
04734 }
04735 bool testCondition( Cell* ) {
04736 return true;
04737 }
04738 void doWork( Cell* cell, bool, int, int ) {
04739 cell->defaultStyle();
04740 }
04741 };
04742
04743 void Sheet::defaultSelection( Selection* selectionInfo )
04744 {
04745 QRect selection(selectionInfo->selection());
04746 DefaultSelectionWorker w;
04747 SelectionType st = workOnCells( selectionInfo, w );
04748 switch ( st ) {
04749 case CompleteRows:
04750 RowFormat *rw;
04751 for ( int i = selection.top(); i <= selection.bottom(); i++ ) {
04752 rw = nonDefaultRowFormat( i );
04753 rw->defaultStyleFormat();
04754 }
04755 emit sig_updateView( this, *selectionInfo );
04756 return;
04757 case CompleteColumns:
04758 ColumnFormat *cl;
04759 for ( int i = selection.left(); i <= selection.right(); i++ ) {
04760 cl=nonDefaultColumnFormat( i );
04761 cl->defaultStyleFormat();
04762 }
04763 emit sig_updateView( this, *selectionInfo );
04764 return;
04765 case CellRegion:
04766 emit sig_updateView( this, *selectionInfo );
04767 return;
04768 }
04769 }
04770
04771
04772 struct SetConditionalWorker : public Sheet::CellWorker
04773 {
04774 QValueList<Conditional> conditionList;
04775 SetConditionalWorker( QValueList<Conditional> _tmp ) :
04776 Sheet::CellWorker( ), conditionList( _tmp ) { }
04777
04778 class UndoAction* createUndoAction( Doc* doc,
04779 Sheet* sheet, const KSpread::Region& region )
04780 {
04781 return new UndoConditional( doc, sheet, region );
04782 }
04783
04784 bool testCondition( Cell* )
04785 {
04786 return true;
04787 }
04788
04789 void doWork( Cell* cell, bool, int, int )
04790 {
04791 if ( !cell->isObscured() )
04792 {
04793 cell->setConditionList(conditionList);
04794 cell->setDisplayDirtyFlag();
04795 }
04796 }
04797 };
04798
04799 void Sheet::setConditional( Selection* selectionInfo,
04800 QValueList<Conditional> const & newConditions)
04801 {
04802 if ( !doc()->undoLocked() )
04803 {
04804 UndoConditional * undo = new UndoConditional(doc(), this, *selectionInfo);
04805 doc()->addCommand( undo );
04806 }
04807
04808 Region::ConstIterator endOfList = selectionInfo->constEnd();
04809 for (Region::ConstIterator it = selectionInfo->constBegin(); it != endOfList; ++it)
04810 {
04811 QRect range = (*it)->rect().normalize();
04812
04813 int l = range.left();
04814 int r = range.right();
04815 int t = range.top();
04816 int b = range.bottom();
04817
04818 Cell * cell;
04819 Style * s = doc()->styleManager()->defaultStyle();
04820 for (int x = l; x <= r; ++x)
04821 {
04822 for (int y = t; y <= b; ++y)
04823 {
04824 cell = nonDefaultCell( x, y, false, s );
04825 cell->setConditionList( newConditions );
04826 cell->setDisplayDirtyFlag();
04827 }
04828 }
04829 }
04830
04831 emit sig_updateView( this, *selectionInfo );
04832 }
04833
04834
04835 struct SetValidityWorker : public Sheet::CellWorker {
04836 Validity tmp;
04837 SetValidityWorker( Validity _tmp ) : Sheet::CellWorker( ), tmp( _tmp ) { }
04838
04839 class UndoAction* createUndoAction( Doc* doc, Sheet* sheet, const KSpread::Region& region ) {
04840 return new UndoConditional( doc, sheet, region );
04841 }
04842 bool testCondition( Cell* ) {
04843 return true;
04844 }
04845 void doWork( Cell* cell, bool, int, int ) {
04846 if ( !cell->isObscured() ) {
04847 cell->setDisplayDirtyFlag();
04848 if ( tmp.m_restriction==Restriction::None )
04849 cell->removeValidity();
04850 else
04851 {
04852 Validity *tmpValidity = cell->getValidity();
04853 tmpValidity->message=tmp.message;
04854 tmpValidity->title=tmp.title;
04855 tmpValidity->valMin=tmp.valMin;
04856 tmpValidity->valMax=tmp.valMax;
04857 tmpValidity->m_cond=tmp.m_cond;
04858 tmpValidity->m_action=tmp.m_action;
04859 tmpValidity->m_restriction=tmp.m_restriction;
04860 tmpValidity->timeMin=tmp.timeMin;
04861 tmpValidity->timeMax=tmp.timeMax;
04862 tmpValidity->dateMin=tmp.dateMin;
04863 tmpValidity->dateMax=tmp.dateMax;
04864 tmpValidity->displayMessage=tmp.displayMessage;
04865 tmpValidity->allowEmptyCell=tmp.allowEmptyCell;
04866 tmpValidity->displayValidationInformation=tmp.displayValidationInformation;
04867 tmpValidity->titleInfo=tmp.titleInfo;
04868 tmpValidity->messageInfo=tmp.messageInfo;
04869 tmpValidity->listValidity=tmp.listValidity;
04870 }
04871 cell->clearDisplayDirtyFlag();
04872 }
04873 }
04874 };
04875
04876 void Sheet::setValidity(Selection* selectionInfo,
04877 KSpread::Validity tmp )
04878 {
04879 SetValidityWorker w( tmp );
04880 workOnCells( selectionInfo, w );
04881 }
04882
04883
04884 struct GetWordSpellingWorker : public Sheet::CellWorker {
04885 QString& listWord;
04886 GetWordSpellingWorker( QString& _listWord ) : Sheet::CellWorker( false, false, true ), listWord( _listWord ) { }
04887
04888 class UndoAction* createUndoAction( Doc*, Sheet*, const KSpread::Region& ) {
04889 return 0;
04890 }
04891 bool testCondition( Cell* ) {
04892 return true;
04893 }
04894 void doWork( Cell* c, bool cellRegion, int, int ) {
04895 if ( !c->isObscured() || cellRegion ) {
04896 if ( !c->isFormula() && !c->value().isNumber() && !c->value().asString().isEmpty() && !c->isTime()
04897 && !c->isDate()
04898 && !c->text().isEmpty())
04899 {
04900 listWord+=c->text()+'\n';
04901 }
04902 }
04903 }
04904 };
04905
04906 QString Sheet::getWordSpelling(Selection* selectionInfo )
04907 {
04908 QString listWord;
04909 GetWordSpellingWorker w( listWord );
04910 workOnCells( selectionInfo, w );
04911 return listWord;
04912 }
04913
04914
04915 struct SetWordSpellingWorker : public Sheet::CellWorker {
04916 QStringList& list;
04917 int pos;
04918 Sheet * sheet;
04919 SetWordSpellingWorker( QStringList & _list,Sheet * s )
04920 : Sheet::CellWorker( false, false, true ), list( _list ), pos( 0 ), sheet( s ) { }
04921
04922 class UndoAction* createUndoAction( Doc* doc, Sheet* sheet, const KSpread::Region& region ) {
04923 return new UndoChangeAreaTextCell( doc, sheet, region );
04924 }
04925 bool testCondition( Cell* ) {
04926 return true;
04927 }
04928 void doWork( Cell* c, bool cellRegion, int, int )
04929 {
04930 if ( !c->isObscured() || cellRegion ) {
04931 if ( !c->isFormula() && !c->value().isNumber() && !c->value().asString().isEmpty() && !c->isTime()
04932 && !c->isDate()
04933 && !c->text().isEmpty())
04934 {
04935
04936
04937 c->setCellText( list[pos] );
04938 pos++;
04939 }
04940 }
04941 }
04942 };
04943
04944 void Sheet::setWordSpelling(Selection* selectionInfo,
04945 const QString _listWord )
04946 {
04947 QStringList list = QStringList::split ( '\n', _listWord );
04948 SetWordSpellingWorker w( list, this );
04949 workOnCells( selectionInfo, w );
04950 }
04951
04952 static QString cellAsText( Cell* cell, unsigned int max )
04953 {
04954 QString result;
04955 if( !cell->isDefault() )
04956 {
04957 int l = max - cell->strOutText().length();
04958 if (cell->defineAlignX() == Format::Right )
04959 {
04960 for ( int i = 0; i < l; ++i )
04961 result += " ";
04962 result += cell->strOutText();
04963 }
04964 else if (cell->defineAlignX() == Format::Left )
04965 {
04966 result += " ";
04967 result += cell->strOutText();
04968
04969 for ( int i = 1; i < l; ++i )
04970 result += " ";
04971 }
04972 else
04973 {
04974 int i;
04975 int s = (int) l / 2;
04976 for ( i = 0; i < s; ++i )
04977 result += " ";
04978 result += cell->strOutText();
04979 for ( i = s; i < l; ++i )
04980 result += " ";
04981 }
04982 }
04983 else
04984 {
04985 for ( unsigned int i = 0; i < max; ++i )
04986 result += " ";
04987 }
04988
04989 return result;
04990 }
04991
04992 QString Sheet::copyAsText( Selection* selectionInfo )
04993 {
04994
04995 if ( selectionInfo->isSingular() )
04996 {
04997 Cell * cell = cellAt( selectionInfo->marker() );
04998 if( !cell->isDefault() )
04999 return cell->strOutText();
05000 return "";
05001 }
05002
05003 QRect selection(selectionInfo->selection());
05004
05005
05006 unsigned top = selection.bottom();
05007 unsigned bottom = selection.top();
05008 unsigned left = selection.right();
05009 unsigned right = selection.left();
05010
05011 unsigned max = 1;
05012 for( Cell *c = d->cells.firstCell();c; c = c->nextCell() )
05013 {
05014 if ( !c->isDefault() )
05015 {
05016 QPoint p( c->column(), c->row() );
05017 if ( selection.contains( p ) )
05018 {
05019 top = QMIN( top, (unsigned) c->row() );
05020 left = QMIN( left, (unsigned) c->column() );
05021 bottom = QMAX( bottom, (unsigned) c->row() );
05022 right = QMAX( right, (unsigned) c->column() );
05023
05024 if ( c->strOutText().length() > max )
05025 max = c->strOutText().length();
05026 }
05027 }
05028 }
05029
05030 ++max;
05031
05032 QString result;
05033 for ( unsigned y = top; y <= bottom; ++y)
05034 {
05035 for ( unsigned x = left; x <= right; ++x)
05036 {
05037 Cell *cell = cellAt( x, y );
05038 result += cellAsText( cell, max );
05039 }
05040 result += "\n";
05041 }
05042
05043 return result;
05044 }
05045
05046 void Sheet::copySelection( Selection* selectionInfo )
05047 {
05048 QDomDocument doc = saveCellRegion( *selectionInfo, true );
05049
05050
05051 QBuffer buffer;
05052 buffer.open( IO_WriteOnly );
05053 QTextStream str( &buffer );
05054 str.setEncoding( QTextStream::UnicodeUTF8 );
05055 str << doc;
05056 buffer.close();
05057
05058 TextDrag * kd = new TextDrag( 0L );
05059 kd->setPlain( copyAsText(selectionInfo) );
05060 kd->setKSpread( buffer.buffer() );
05061
05062 QApplication::clipboard()->setData( kd );
05063 }
05064
05065 void Sheet::cutSelection( Selection* selectionInfo )
05066 {
05067 QDomDocument doc = saveCellRegion(*selectionInfo, true, true);
05068
05069
05070 QBuffer buffer;
05071 buffer.open( IO_WriteOnly );
05072 QTextStream str( &buffer );
05073 str.setEncoding( QTextStream::UnicodeUTF8 );
05074 str << doc;
05075 buffer.close();
05076
05077 TextDrag * kd = new TextDrag( 0L );
05078 kd->setPlain( copyAsText(selectionInfo) );
05079 kd->setKSpread( buffer.buffer() );
05080
05081 QApplication::clipboard()->setData( kd );
05082
05083 deleteSelection( selectionInfo, true );
05084 }
05085
05086 void Sheet::paste( const QRect& pasteArea, bool makeUndo,
05087 Paste::Mode mode, Paste::Operation operation,
05088 bool insert, int insertTo, bool pasteFC,
05089 QClipboard::Mode clipboardMode )
05090 {
05091 QMimeSource * mime = QApplication::clipboard()->data( clipboardMode );
05092 if ( !mime )
05093 return;
05094
05095 QByteArray b;
05096
05097 if ( mime->provides( TextDrag::selectionMimeType() ) )
05098 {
05099 b = mime->encodedData( TextDrag::selectionMimeType() );
05100 }
05101 else if( mime->provides( "text/plain" ) )
05102 {
05103
05104
05105 QString _text = QApplication::clipboard()->text( clipboardMode );
05106 doc()->emitBeginOperation();
05107 pasteTextPlain( _text, pasteArea );
05108 emit sig_updateView( this );
05109
05110 return;
05111 }
05112 else
05113 return;
05114
05115
05116 doc()->emitBeginOperation();
05117 paste( b, pasteArea, makeUndo, mode, operation, insert, insertTo, pasteFC );
05118 emit sig_updateView( this );
05119
05120 }
05121
05122
05123 void Sheet::pasteTextPlain( QString &_text, QRect pasteArea)
05124 {
05125
05126
05127 if( _text.isEmpty() )
05128 return;
05129
05130 QString tmp = _text;
05131 int i;
05132 int mx = pasteArea.left();
05133 int my = pasteArea.top();
05134 int rows = 1;
05135 int len = tmp.length();
05136
05137
05138 for ( i = 0; i < len; ++i )
05139 {
05140 if ( tmp[i] == '\n' )
05141 ++rows;
05142 }
05143
05144 Cell * cell = nonDefaultCell( mx, my );
05145 if ( rows == 1 )
05146 {
05147 if ( !doc()->undoLocked() )
05148 {
05149 UndoSetText * undo = new UndoSetText( doc(), this , cell->text(), mx, my, cell->formatType() );
05150 doc()->addCommand( undo );
05151 }
05152 }
05153 else
05154 {
05155 QRect rect(mx, my, mx, my + rows - 1);
05156 UndoChangeAreaTextCell * undo = new UndoChangeAreaTextCell( doc(), this , rect );
05157 doc()->addCommand( undo );
05158 }
05159
05160 i = 0;
05161 QString rowtext;
05162
05163 while ( i < rows )
05164 {
05165 int p = 0;
05166
05167 p = tmp.find('\n');
05168
05169 if (p < 0)
05170 p = tmp.length();
05171
05172 rowtext = tmp.left(p);
05173
05174 if ( !isProtected() || cell->format()->notProtected( mx, my + i ) )
05175 {
05176 cell->setCellText( rowtext );
05177 cell->updateChart();
05178 }
05179
05180
05181 ++i;
05182 cell = nonDefaultCell( mx, my + i );
05183
05184 if (!cell || p == (int) tmp.length())
05185 break;
05186
05187
05188 tmp = tmp.right(tmp.length() - p - 1);
05189 }
05190
05191 if (!isLoading())
05192 refreshMergedCell();
05193
05194 emit sig_updateView( this );
05195 emit sig_updateHBorder( this );
05196 emit sig_updateVBorder( this );
05197 }
05198
05199 void Sheet::paste( const QByteArray& b, const QRect& pasteArea, bool makeUndo,
05200 Paste::Mode mode, Paste::Operation operation,
05201 bool insert, int insertTo, bool pasteFC )
05202 {
05203 kdDebug(36001) << "Parsing " << b.size() << " bytes" << endl;
05204
05205 QBuffer buffer( b );
05206 buffer.open( IO_ReadOnly );
05207 QDomDocument doc;
05208 doc.setContent( &buffer );
05209 buffer.close();
05210
05211
05212
05213 int mx = pasteArea.left();
05214 int my = pasteArea.top();
05215
05216 loadSelection( doc, pasteArea, mx - 1, my - 1, makeUndo,
05217 mode, operation, insert, insertTo, pasteFC );
05218 }
05219
05220 bool Sheet::loadSelection(const QDomDocument& doc, const QRect& pasteArea,
05221 int _xshift, int _yshift, bool makeUndo,
05222 Paste::Mode mode, Paste::Operation operation, bool insert,
05223 int insertTo, bool pasteFC)
05224 {
05225
05226
05227 if (!isLoading() && makeUndo)
05228 {
05229 loadSelectionUndo( doc, pasteArea, _xshift, _yshift, insert, insertTo );
05230 }
05231
05232 QDomElement root = doc.documentElement();
05233
05234 int rowsInClpbrd = root.attribute( "rows" ).toInt();
05235 int columnsInClpbrd = root.attribute( "columns" ).toInt();
05236
05237
05238 const int pasteWidth = ( pasteArea.width() >= columnsInClpbrd
05239 && util_isRowSelected(pasteArea) == false
05240 && root.namedItem( "rows" ).toElement().isNull() )
05241 ? pasteArea.width() : columnsInClpbrd;
05242 const int pasteHeight = ( pasteArea.height() >= rowsInClpbrd
05243 && util_isColumnSelected(pasteArea) == false
05244 && root.namedItem( "columns" ).toElement().isNull())
05245 ? pasteArea.height() : rowsInClpbrd;
05246
05247
05248
05249
05250
05251
05252
05253
05254 QDomElement e = root.firstChild().toElement();
05255 for (; !e.isNull(); e = e.nextSibling().toElement())
05256 {
05257
05258 if (e.tagName() == "columns" && !isProtected())
05259 {
05260 _yshift = 0;
05261
05262
05263 int col = e.attribute("column").toInt();
05264 int width = e.attribute("count").toInt();
05265 for ( int i = col; i < col + width; ++i )
05266 {
05267 if (!insert)
05268 {
05269 d->cells.clearColumn( _xshift + i );
05270 d->columns.removeElement( _xshift + i );
05271 }
05272 }
05273
05274
05275 QDomElement c = e.firstChild().toElement();
05276 for ( ; !c.isNull(); c = c.nextSibling().toElement() )
05277 {
05278 if ( c.tagName() == "column" )
05279 {
05280 ColumnFormat *cl = new ColumnFormat( this, 0 );
05281 if ( cl->load( c, _xshift, mode, pasteFC ) )
05282 insertColumnFormat( cl );
05283 else
05284 delete cl;
05285 }
05286 }
05287 }
05288
05289
05290 if (e.tagName() == "rows" && !isProtected())
05291 {
05292 _xshift = 0;
05293
05294
05295 int row = e.attribute("row").toInt();
05296 int height = e.attribute("count").toInt();
05297 for( int i = row; i < row + height; ++i )
05298 {
05299 if (!insert)
05300 {
05301 d->cells.clearRow( _yshift + i );
05302 d->rows.removeElement( _yshift + i );
05303 }
05304 }
05305
05306
05307 QDomElement c = e.firstChild().toElement();
05308 for( ; !c.isNull(); c = c.nextSibling().toElement() )
05309 {
05310 if ( c.tagName() == "row" )
05311 {
05312 RowFormat *cl = new RowFormat( this, 0 );
05313 if ( cl->load( c, _yshift, mode, pasteFC ) )
05314 insertRowFormat( cl );
05315 else
05316 delete cl;
05317 }
05318 }
05319 }
05320
05321 Cell* refreshCell = 0;
05322 Cell *cell;
05323 Cell *cellBackup = NULL;
05324 if (e.tagName() == "cell")
05325 {
05326 int row = e.attribute( "row" ).toInt() + _yshift;
05327 int col = e.attribute( "column" ).toInt() + _xshift;
05328
05329
05330 for (int roff = 0; row + roff - _yshift <= pasteHeight; roff += rowsInClpbrd)
05331 {
05332 for (int coff = 0; col + coff - _xshift <= pasteWidth; coff += columnsInClpbrd)
05333 {
05334
05335
05336
05337
05338 cell = nonDefaultCell( col + coff, row + roff );
05339 if (isProtected() && !cell->format()->notProtected(col + coff, row + roff))
05340 {
05341 continue;
05342 }
05343
05344 cellBackup = new Cell(this, cell->column(), cell->row());
05345 cellBackup->copyAll(cell);
05346
05347 if (!cell->load(e, _xshift + coff, _yshift + roff, mode, operation, pasteFC))
05348 {
05349 cell->copyAll(cellBackup);
05350 }
05351 else
05352 {
05353 if (cell->isFormula())
05354 {
05355 cell->setCalcDirtyFlag();
05356 }
05357 }
05358
05359 delete cellBackup;
05360
05361
05362
05363 cell = cellAt( col + coff, row + roff );
05364 if( !refreshCell && cell->updateChart( false ) )
05365 {
05366 refreshCell = cell;
05367 }
05368 }
05369 }
05370 }
05371
05372
05373
05374
05375
05376
05377
05378
05379 if ( refreshCell )
05380 refreshCell->updateChart();
05381 }
05382 this->doc()->setModified( true );
05383
05384 if (!isLoading())
05385 refreshMergedCell();
05386
05387 emit sig_updateView( this );
05388 emit sig_updateHBorder( this );
05389 emit sig_updateVBorder( this );
05390
05391 return true;
05392 }
05393
05394 void Sheet::loadSelectionUndo(const QDomDocument& d, const QRect& loadArea,
05395 int _xshift, int _yshift,
05396 bool insert, int insertTo)
05397 {
05398 QDomElement root = d.documentElement();
05399
05400 int rowsInClpbrd = root.attribute( "rows" ).toInt();
05401 int columnsInClpbrd = root.attribute( "columns" ).toInt();
05402
05403
05404 const int pasteWidth = (loadArea.width() >= columnsInClpbrd &&
05405 util_isRowSelected(loadArea) == false &&
05406 root.namedItem( "rows" ).toElement().isNull())
05407 ? loadArea.width() : columnsInClpbrd;
05408 const int pasteHeight = (loadArea.height() >= rowsInClpbrd &&
05409 util_isColumnSelected(loadArea) == false &&
05410 root.namedItem( "columns" ).toElement().isNull())
05411 ? loadArea.height() : rowsInClpbrd;
05412
05413 uint numCols = 0;
05414 uint numRows = 0;
05415 Region region;
05416 for (QDomNode n = root.firstChild(); !n.isNull(); n = n.nextSibling())
05417 {
05418 QDomElement e = n.toElement();
05419 if (e.tagName() == "columns")
05420 {
05421 _yshift = 0;
05422 int col = e.attribute("column").toInt();
05423 int width = e.attribute("count").toInt();
05424 for (int coff = 0; col + coff <= pasteWidth; coff += columnsInClpbrd)
05425 {
05426 uint overlap = QMAX(0, (col + coff + width) - pasteWidth);
05427 uint effWidth = width - overlap;
05428 region.add(QRect(_xshift + col + coff, 1, effWidth, KS_rowMax));
05429 numCols += effWidth;
05430 }
05431 }
05432 else if (e.tagName() == "rows")
05433 {
05434 _xshift = 0;
05435 int row = e.attribute("row").toInt();
05436 int height = e.attribute("count").toInt();
05437 for (int roff = 0; row + roff <= pasteHeight; roff += rowsInClpbrd)
05438 {
05439 uint overlap = QMAX(0, (row + roff + height) - pasteHeight);
05440 uint effHeight = height - overlap;
05441 region.add(QRect(1, _yshift + row + roff, KS_colMax, effHeight));
05442 numRows += effHeight;
05443 }
05444 }
05445 else if (!e.isNull())
05446 {
05447
05448 int col = e.attribute("column").toInt();
05449 int row = e.attribute("row").toInt();
05450 for (int coff = 0; col + coff <= pasteWidth; coff += columnsInClpbrd)
05451 {
05452 for (int roff = 0; row + roff <= pasteHeight; roff += rowsInClpbrd)
05453 {
05454 region.add(QPoint(_xshift + col + coff, _yshift + row + roff));
05455 }
05456 }
05457 }
05458 }
05459
05460 if (!doc()->undoLocked())
05461 {
05462 UndoCellPaste *undo = new UndoCellPaste( doc(), this, _xshift, _yshift, region, insert, insertTo );
05463 doc()->addCommand( undo );
05464 }
05465
05466 if (insert)
05467 {
05468 QRect rect = region.boundingRect();
05469 if (insertTo == -1 || (insertTo == 0 && numRows == 0))
05470 {
05471 rect.setWidth(rect.width() - numCols);
05472 shiftRow(rect, false);
05473 }
05474 else if (insertTo == 1 || (insertTo == 0 && numCols == 0))
05475 {
05476 rect.setHeight(rect.height() - numRows);
05477 shiftColumn(rect, false);
05478 }
05479
05480 for (QDomNode n = root.firstChild(); !n.isNull(); n = n.nextSibling())
05481 {
05482 QDomElement e = n.toElement();
05483 if (e.tagName() == "columns")
05484 {
05485 insertColumn(_xshift+1, e.attribute("count").toInt()-1, false);
05486 }
05487 else if (e.tagName() == "rows")
05488 {
05489 insertRow(_yshift+1, e.attribute("count").toInt()-1, false);
05490 }
05491 }
05492 }
05493 }
05494
05495 bool Sheet::testAreaPasteInsert()const
05496 {
05497 QMimeSource* mime = QApplication::clipboard()->data( QClipboard::Clipboard );
05498 if ( !mime )
05499 return false;
05500
05501 QByteArray b;
05502
05503 if ( mime->provides( "application/x-kspread-snippet" ) )
05504 b = mime->encodedData( "application/x-kspread-snippet" );
05505 else
05506 return false;
05507
05508 QBuffer buffer( b );
05509 buffer.open( IO_ReadOnly );
05510 QDomDocument d;
05511 d.setContent( &buffer );
05512 buffer.close();
05513
05514 QDomElement e = d.documentElement();
05515 if ( !e.namedItem( "columns" ).toElement().isNull() )
05516 return false;
05517
05518 if ( !e.namedItem( "rows" ).toElement().isNull() )
05519 return false;
05520
05521 QDomElement c = e.firstChild().toElement();
05522 for( ; !c.isNull(); c = c.nextSibling().toElement() )
05523 {
05524 if ( c.tagName() == "cell" )
05525 return true;
05526 }
05527 return false;
05528 }
05529
05530 void Sheet::deleteCells(const Region& region)
05531 {
05532
05533 QPtrStack<Cell> cellStack;
05534
05535 Region::ConstIterator endOfList = region.constEnd();
05536 for (Region::ConstIterator it = region.constBegin(); it != endOfList; ++it)
05537 {
05538 QRect range = (*it)->rect().normalize();
05539
05540 int right = range.right();
05541 int left = range.left();
05542 int bottom = range.bottom();
05543 int col;
05544 for ( int row = range.top(); row <= bottom; ++row )
05545 {
05546 Cell * c = getFirstCellRow( row );
05547 while ( c )
05548 {
05549 col = c->column();
05550 if ( col < left )
05551 {
05552 c = getNextCellRight( left - 1, row );
05553 continue;
05554 }
05555 if ( col > right )
05556 break;
05557
05558 if ( !c->isDefault() )
05559 cellStack.push( c );
05560
05561 c = getNextCellRight( col, row );
05562 }
05563 }
05564 }
05565
05566 d->cells.setAutoDelete( false );
05567
05568
05569 while ( !cellStack.isEmpty() )
05570 {
05571 Cell * cell = cellStack.pop();
05572
05573 d->cells.remove( cell->column(), cell->row() );
05574 cell->setCalcDirtyFlag();
05575 setRegionPaintDirty(cell->cellRect());
05576
05577 delete cell;
05578 }
05579
05580 d->cells.setAutoDelete( true );
05581
05582 setLayoutDirtyFlag();
05583
05584
05585
05586
05587 Cell * c = d->cells.firstCell();
05588 for( ;c; c = c->nextCell() )
05589 {
05590 if ( c->doesMergeCells() && !c->isDefault() )
05591 c->mergeCells( c->column(), c->row(),
05592 c->extraXCells(), c->extraYCells() );
05593 }
05594 doc()->setModified( true );
05595 }
05596
05597 void Sheet::deleteSelection( Selection* selectionInfo, bool undo )
05598 {
05599 if ( undo && !doc()->undoLocked() )
05600 {
05601 UndoDelete *undo = new UndoDelete( doc(), this, *selectionInfo );
05602 doc()->addCommand( undo );
05603 }
05604
05605 Region::ConstIterator endOfList = selectionInfo->constEnd();
05606 for (Region::ConstIterator it = selectionInfo->constBegin(); it != endOfList; ++it)
05607 {
05608 QRect range = (*it)->rect().normalize();
05609
05610
05611 if ( util_isRowSelected(range) )
05612 {
05613 for( int i = range.top(); i <= range.bottom(); ++i )
05614 {
05615 d->cells.clearRow( i );
05616 d->rows.removeElement( i );
05617 }
05618
05619 emit sig_updateVBorder( this );
05620 }
05621
05622 else if ( util_isColumnSelected(range) )
05623 {
05624 for( int i = range.left(); i <= range.right(); ++i )
05625 {
05626 d->cells.clearColumn( i );
05627 d->columns.removeElement( i );
05628 }
05629
05630 emit sig_updateHBorder( this );
05631 }
05632 else
05633 {
05634 setRegionPaintDirty( range );
05635 deleteCells( range );
05636 }
05637 }
05638 refreshMergedCell();
05639 emit sig_updateView( this );
05640 }
05641
05642 void Sheet::updateView()
05643 {
05644 emit sig_updateView( this );
05645 }
05646
05647 void Sheet::updateView( QRect const & rect )
05648 {
05649 emit sig_updateView( this, rect );
05650 }
05651
05652 void Sheet::updateView(Region* region)
05653 {
05654 emit sig_updateView( this, *region );
05655 }
05656
05657 void Sheet::refreshView( const Region& region )
05658 {
05659 Region tmpRegion;
05660 Region::ConstIterator endOfList = region.constEnd();
05661 for (Region::ConstIterator it = region.constBegin(); it != endOfList; ++it)
05662 {
05663 QRect range = (*it)->rect().normalize();
05664
05665 QRect tmp(range);
05666 Cell * c = d->cells.firstCell();
05667 for( ;c; c = c->nextCell() )
05668 {
05669 if ( !c->isDefault() &&
05670 c->row() >= range.top() && c->row() <= range.bottom() &&
05671 c->column() >= range.left() && c->column() <= range.right() )
05672 {
05673 if (c->doesMergeCells())
05674 {
05675 int right=QMAX(tmp.right(),c->column()+c->extraXCells());
05676 int bottom=QMAX(tmp.bottom(),c->row()+c->extraYCells());
05677
05678 tmp.setRight(right);
05679 tmp.setBottom(bottom);
05680 }
05681 }
05682 }
05683 deleteCells( range );
05684 tmpRegion.add(tmp);
05685 }
05686 emit sig_updateView( this, tmpRegion );
05687 }
05688
05689
05690 void Sheet::mergeCells(const Region& region, bool hor, bool ver)
05691 {
05692
05693 if( isProtected() )
05694 return;
05695 if( workbook()->isProtected() )
05696 return;
05697
05698 MergeManipulator* manipulator = new MergeManipulator();
05699 manipulator->setSheet(this);
05700 manipulator->setHorizontalMerge(hor);
05701 manipulator->setVerticalMerge(ver);
05702 manipulator->add(region);
05703 manipulator->execute();
05704 }
05705
05706 void Sheet::dissociateCells(const Region& region)
05707 {
05708
05709 if( isProtected() )
05710 return;
05711 if( workbook()->isProtected() )
05712 return;
05713
05714 Manipulator* manipulator = new MergeManipulator();
05715 manipulator->setSheet(this);
05716 manipulator->setReverse(true);
05717 manipulator->add(region);
05718 manipulator->execute();
05719 }
05720
05721 bool Sheet::testListChoose(Selection* selectionInfo)
05722 {
05723 QRect selection( selectionInfo->selection() );
05724 QPoint marker( selectionInfo->marker() );
05725
05726 Cell *cell = cellAt( marker.x(), marker.y() );
05727 QString tmp=cell->text();
05728
05729 Cell* c = firstCell();
05730 bool different=false;
05731 int col;
05732 for( ;c; c = c->nextCell() )
05733 {
05734 col = c->column();
05735 if ( selection.left() <= col && selection.right() >= col &&
05736 !c->isPartOfMerged() &&
05737 !(col==marker.x() && c->row()==marker.y()))
05738 {
05739 if(!c->isFormula() && !c->value().isNumber() && !c->value().asString().isEmpty()
05740 && !c->isTime() &&!c->isDate() )
05741 {
05742 if(c->text()!=tmp)
05743 different=true;
05744 }
05745
05746 }
05747 }
05748 return different;
05749 }
05750
05751
05752
05753 QDomDocument Sheet::saveCellRegion(const Region& region, bool copy, bool era)
05754 {
05755 QDomDocument dd( "spreadsheet-snippet" );
05756 dd.appendChild( dd.createProcessingInstruction( "xml", "version=\"1.0\" encoding=\"UTF-8\"" ) );
05757 QDomElement root = dd.createElement( "spreadsheet-snippet" );
05758 dd.appendChild(root);
05759
05760
05761 QRect boundingRect = region.boundingRect();
05762 int left = boundingRect.left();
05763 int top = boundingRect.top();
05764
05765
05766 root.setAttribute( "rows", boundingRect.height() );
05767 root.setAttribute( "columns", boundingRect.width() );
05768
05769 Region::ConstIterator endOfList = region.constEnd();
05770 for (Region::ConstIterator it = region.constBegin(); it != endOfList; ++it)
05771 {
05772 QRect range = (*it)->rect().normalize();
05773
05774
05775
05776
05777 if ((*it)->isRow())
05778 {
05779 QDomElement rows = dd.createElement("rows");
05780 rows.setAttribute( "count", range.height() );
05781 rows.setAttribute( "row", range.top() - top + 1 );
05782 root.appendChild( rows );
05783
05784
05785 for (Cell* cell = d->cells.firstCell(); cell; cell = cell->nextCell())
05786 {
05787 if (!cell->isDefault() && !cell->isPartOfMerged())
05788 {
05789 QPoint point(cell->column(), cell->row());
05790 if (range.contains(point))
05791 {
05792 root.appendChild(cell->save( dd, 0, top - 1, copy, copy, era));
05793 }
05794 }
05795 }
05796
05797
05798
05799 RowFormat* format;
05800 for (int row = range.top(); row <= range.bottom(); ++row)
05801 {
05802 format = rowFormat( row );
05803 if (format && !format->isDefault())
05804 {
05805 QDomElement e = format->save(dd, top - 1, copy);
05806 if (!e.isNull())
05807 {
05808 rows.appendChild( e );
05809 }
05810 }
05811 }
05812 continue;
05813 }
05814
05815
05816
05817
05818 if ((*it)->isColumn())
05819 {
05820 QDomElement columns = dd.createElement("columns");
05821 columns.setAttribute( "count", range.width() );
05822 columns.setAttribute( "column", range.left() - left + 1 );
05823 root.appendChild( columns );
05824
05825
05826 for (Cell* cell = d->cells.firstCell();cell; cell = cell->nextCell())
05827 {
05828 if (!cell->isDefault() && !cell->isPartOfMerged())
05829 {
05830 QPoint point(cell->column(), cell->row());
05831 if (range.contains(point))
05832 {
05833 root.appendChild(cell->save( dd, left - 1, 0, copy, copy, era));
05834 }
05835 }
05836 }
05837
05838
05839
05840 ColumnFormat* format;
05841 for (int col = range.left(); col <= range.right(); ++col)
05842 {
05843 format = columnFormat(col);
05844 if (format && !format->isDefault())
05845 {
05846 QDomElement e = format->save(dd, left - 1, copy);
05847 if (!e.isNull())
05848 {
05849 columns.appendChild(e);
05850 }
05851 }
05852 }
05853 continue;
05854 }
05855
05856
05857
05858
05859
05860
05861 Cell* cell;
05862 bool insert;
05863 for (int col = range.left(); col <= range.right(); ++col)
05864 {
05865 for (int row = range.top(); row <= range.bottom(); ++row)
05866 {
05867 insert = false;
05868 cell = cellAt(col, row);
05869 if (cell == d->defaultCell)
05870 {
05871 cell = new Cell(this, col, row);
05872 insertCell(cell);
05873 insert = true;
05874 }
05875 root.appendChild(cell->save(dd, left - 1, top - 1, true, copy, era));
05876 if (insert)
05877 {
05878 d->cells.remove(col, row);
05879 }
05880 }
05881 }
05882 }
05883 return dd;
05884 }
05885
05886 QDomElement Sheet::saveXML( QDomDocument& dd )
05887 {
05888 QDomElement sheet = dd.createElement( "table" );
05889 sheet.setAttribute( "name", d->name );
05890
05891
05892
05893 sheet.setAttribute( "layoutDirection", (d->layoutDirection == RightToLeft) ? "rtl" : "ltr" );
05894 sheet.setAttribute( "columnnumber", (int)d->showColumnNumber);
05895 sheet.setAttribute( "borders", (int)d->showPageBorders);
05896 sheet.setAttribute( "hide", (int)d->hide);
05897 sheet.setAttribute( "hidezero", (int)d->hideZero);
05898 sheet.setAttribute( "firstletterupper", (int)d->firstLetterUpper);
05899 sheet.setAttribute( "grid", (int)d->showGrid );
05900 sheet.setAttribute( "printGrid", (int)d->print->printGrid() );
05901 sheet.setAttribute( "printCommentIndicator", (int)d->print->printCommentIndicator() );
05902 sheet.setAttribute( "printFormulaIndicator", (int)d->print->printFormulaIndicator() );
05903 sheet.setAttribute( "showFormula", (int)d->showFormula);
05904 sheet.setAttribute( "showFormulaIndicator", (int)d->showFormulaIndicator);
05905 sheet.setAttribute( "showCommentIndicator", (int)d->showCommentIndicator);
05906 sheet.setAttribute( "lcmode", (int)d->lcMode);
05907 sheet.setAttribute( "autoCalc", (int)d->autoCalc);
05908 sheet.setAttribute( "borders1.2", 1);
05909 if ( !d->password.isNull() )
05910 {
05911 if ( d->password.size() > 0 )
05912 {
05913 QCString str = KCodecs::base64Encode( d->password );
05914 sheet.setAttribute( "protected", QString( str.data() ) );
05915 }
05916 else
05917 sheet.setAttribute( "protected", "" );
05918 }
05919
05920
05921 QDomElement paper = dd.createElement( "paper" );
05922 paper.setAttribute( "format", d->print->paperFormatString() );
05923 paper.setAttribute( "orientation", d->print->orientationString() );
05924 sheet.appendChild( paper );
05925
05926 QDomElement borders = dd.createElement( "borders" );
05927 borders.setAttribute( "left", d->print->leftBorder() );
05928 borders.setAttribute( "top", d->print->topBorder() );
05929 borders.setAttribute( "right", d->print->rightBorder() );
05930 borders.setAttribute( "bottom", d->print->bottomBorder() );
05931 paper.appendChild( borders );
05932
05933 QDomElement head = dd.createElement( "head" );
05934 paper.appendChild( head );
05935 if ( !d->print->headLeft().isEmpty() )
05936 {
05937 QDomElement left = dd.createElement( "left" );
05938 head.appendChild( left );
05939 left.appendChild( dd.createTextNode( d->print->headLeft() ) );
05940 }
05941 if ( !d->print->headMid().isEmpty() )
05942 {
05943 QDomElement center = dd.createElement( "center" );
05944 head.appendChild( center );
05945 center.appendChild( dd.createTextNode( d->print->headMid() ) );
05946 }
05947 if ( !d->print->headRight().isEmpty() )
05948 {
05949 QDomElement right = dd.createElement( "right" );
05950 head.appendChild( right );
05951 right.appendChild( dd.createTextNode( d->print->headRight() ) );
05952 }
05953 QDomElement foot = dd.createElement( "foot" );
05954 paper.appendChild( foot );
05955 if ( !d->print->footLeft().isEmpty() )
05956 {
05957 QDomElement left = dd.createElement( "left" );
05958 foot.appendChild( left );
05959 left.appendChild( dd.createTextNode( d->print->footLeft() ) );
05960 }
05961 if ( !d->print->footMid().isEmpty() )
05962 {
05963 QDomElement center = dd.createElement( "center" );
05964 foot.appendChild( center );
05965 center.appendChild( dd.createTextNode( d->print->footMid() ) );
05966 }
05967 if ( !d->print->footRight().isEmpty() )
05968 {
05969 QDomElement right = dd.createElement( "right" );
05970 foot.appendChild( right );
05971 right.appendChild( dd.createTextNode( d->print->footRight() ) );
05972 }
05973
05974
05975 QDomElement printrange = dd.createElement( "printrange-rect" );
05976 QRect _printRange = d->print->printRange();
05977 int left = _printRange.left();
05978 int right = _printRange.right();
05979 int top = _printRange.top();
05980 int bottom = _printRange.bottom();
05981
05982 if ( left == 1 && right == KS_colMax )
05983 {
05984 left = 0;
05985 right = 0;
05986 }
05987
05988 if ( top == 1 && bottom == KS_rowMax )
05989 {
05990 top = 0;
05991 bottom = 0;
05992 }
05993 printrange.setAttribute( "left-rect", left );
05994 printrange.setAttribute( "right-rect", right );
05995 printrange.setAttribute( "bottom-rect", bottom );
05996 printrange.setAttribute( "top-rect", top );
05997 sheet.appendChild( printrange );
05998
05999
06000 QDomElement printRepeatColumns = dd.createElement( "printrepeatcolumns" );
06001 printRepeatColumns.setAttribute( "left", d->print->printRepeatColumns().first );
06002 printRepeatColumns.setAttribute( "right", d->print->printRepeatColumns().second );
06003 sheet.appendChild( printRepeatColumns );
06004
06005
06006 QDomElement printRepeatRows = dd.createElement( "printrepeatrows" );
06007 printRepeatRows.setAttribute( "top", d->print->printRepeatRows().first );
06008 printRepeatRows.setAttribute( "bottom", d->print->printRepeatRows().second );
06009 sheet.appendChild( printRepeatRows );
06010
06011
06012 sheet.setAttribute( "printZoom", d->print->zoom() );
06013
06014
06015 sheet.setAttribute( "printPageLimitX", d->print->pageLimitX() );
06016 sheet.setAttribute( "printPageLimitY", d->print->pageLimitY() );
06017
06018
06019 Cell* c = d->cells.firstCell();
06020 for( ;c; c = c->nextCell() )
06021 {
06022 if ( !c->isDefault() )
06023 {
06024 QDomElement e = c->save( dd );
06025 if ( !e.isNull() )
06026 sheet.appendChild( e );
06027 }
06028 }
06029
06030
06031 RowFormat* rl = d->rows.first();
06032 for( ; rl; rl = rl->next() )
06033 {
06034 if ( !rl->isDefault() )
06035 {
06036 QDomElement e = rl->save( dd );
06037 if ( e.isNull() )
06038 return QDomElement();
06039 sheet.appendChild( e );
06040 }
06041 }
06042
06043
06044 ColumnFormat* cl = d->columns.first();
06045 for( ; cl; cl = cl->next() )
06046 {
06047 if ( !cl->isDefault() )
06048 {
06049 QDomElement e = cl->save( dd );
06050 if ( e.isNull() )
06051 return QDomElement();
06052 sheet.appendChild( e );
06053 }
06054 }
06055
06056 QPtrListIterator<EmbeddedObject> chl = doc()->embeddedObjects();
06057 for( ; chl.current(); ++chl )
06058 {
06059 if ( chl.current()->sheet() == this )
06060 {
06061 QDomElement e = chl.current()->save( dd );
06062
06063 if ( e.isNull() )
06064 return QDomElement();
06065 sheet.appendChild( e );
06066 }
06067 }
06068 return sheet;
06069 }
06070
06071 bool Sheet::isLoading()
06072 {
06073 return doc()->isLoading();
06074 }
06075
06076
06077 QPtrList<EmbeddedObject> Sheet::getSelectedObjects()
06078 {
06079 QPtrList<EmbeddedObject> objects;
06080 QPtrListIterator<EmbeddedObject> it = doc()->embeddedObjects();
06081 for ( ; it.current() ; ++it )
06082 {
06083 if( it.current()->isSelected()
06084 && it.current()->sheet() == this )
06085 {
06086 objects.append( it.current() );
06087 }
06088 }
06089 return objects;
06090 }
06091
06092 KoRect Sheet::getRealRect( bool all )
06093 {
06094 KoRect rect;
06095
06096 QPtrListIterator<EmbeddedObject> it( doc()->embeddedObjects() );
06097 for ( ; it.current() ; ++it )
06098 {
06099
06100 if ( all || ( it.current()->isSelected() && ! it.current()->isProtect() ) )
06101 rect |= it.current()->geometry();
06102 }
06103
06104 return rect;
06105 }
06106
06107
06108 KCommand *Sheet::moveObject(View *_view, double diffx, double diffy)
06109 {
06110 bool createCommand=false;
06111 MoveObjectByCmd *moveByCmd=0L;
06112 Canvas * canvas = _view->canvasWidget();
06113 QPtrList<EmbeddedObject> _objects;
06114 _objects.setAutoDelete( false );
06115 QPtrListIterator<EmbeddedObject> it( doc()->embeddedObjects() );
06116 for ( ; it.current() ; ++it )
06117 {
06118 if ( it.current()->isSelected() && !it.current()->isProtect())
06119 {
06120 _objects.append( it.current() );
06121 KoRect geometry = it.current()->geometry();
06122 geometry.moveBy( -canvas->xOffset(), -canvas->yOffset() );
06123 QRect br = doc()->zoomRect( geometry );
06124 br.moveBy( doc()->zoomItX( diffx ), doc()->zoomItY( diffy ) );
06125 br.moveBy( doc()->zoomItX( -canvas->xOffset() ), doc()->zoomItY( -canvas->yOffset() ) );
06126 canvas->repaint( br );
06127 canvas->repaintObject( it.current() );
06128 createCommand=true;
06129 }
06130 }
06131 if(createCommand) {
06132 moveByCmd = new MoveObjectByCmd( i18n( "Move Objects" ), KoPoint( diffx, diffy ),
06133 _objects, doc(), this );
06134
06135
06136 }
06137 return moveByCmd;
06138 }
06139
06140 KCommand *Sheet::moveObject(View *_view,const KoPoint &_move,bool key)
06141 {
06142 QPtrList<EmbeddedObject> _objects;
06143 _objects.setAutoDelete( false );
06144 MoveObjectByCmd *moveByCmd=0L;
06145 Canvas * canvas = _view->canvasWidget();
06146 QPtrListIterator<EmbeddedObject> it( doc()->embeddedObjects() );
06147 for ( ; it.current() ; ++it )
06148 {
06149 if ( it.current()->isSelected() && !it.current()->isProtect()) {
06150
06151 KoRect geometry = it.current()->geometry();
06152 geometry.moveBy( -canvas->xOffset(), -canvas->yOffset() );
06153 QRect oldBoundingRect = doc()->zoomRect( geometry );
06154
06155
06156 KoRect r = it.current()->geometry();
06157 r.moveBy( _move.x(), _move.y() );
06158
06159 it.current()->setGeometry( r );
06160 _objects.append( it.current() );
06161
06162 canvas->repaint( oldBoundingRect );
06163 canvas->repaintObject( it.current() );
06164 }
06165 }
06166
06167 if ( key && !_objects.isEmpty())
06168 moveByCmd = new MoveObjectByCmd( i18n( "Move Objects" ),
06169 KoPoint( _move ),
06170 _objects, doc() ,this );
06171
06172 return moveByCmd;
06173 }
06174
06175
06176
06177
06178 bool Sheet::objectNameExists( EmbeddedObject *object, QPtrList<EmbeddedObject> &list ) {
06179 QPtrListIterator<EmbeddedObject> it( list );
06180
06181 for ( it.toFirst(); it.current(); ++it ) {
06182
06183 if ( it.current()->getObjectName() == object->getObjectName() &&
06184 it.current() != object ) {
06185 return true;
06186 }
06187 }
06188 return false;
06189 }
06190
06191 void Sheet::unifyObjectName( EmbeddedObject *object ) {
06192 if ( object->getObjectName().isEmpty() ) {
06193 object->setObjectName( object->getTypeString() );
06194 }
06195 QString objectName( object->getObjectName() );
06196
06197 QPtrList<EmbeddedObject> list( doc()->embeddedObjects() );
06198
06199 int count = 1;
06200
06201 while ( objectNameExists( object, list ) ) {
06202 count++;
06203 QRegExp rx( " \\(\\d{1,3}\\)$" );
06204 if ( rx.search( objectName ) != -1 ) {
06205 objectName.remove( rx );
06206 }
06207 objectName += QString(" (%1)").arg( count );
06208 object->setObjectName( objectName );
06209 }
06210 }
06211
06212
06213 void Sheet::checkContentDirection( QString const & name )
06214 {
06215
06216 if ( (name.isRightToLeft()) )
06217 setLayoutDirection( RightToLeft );
06218 else
06219 setLayoutDirection( LeftToRight );
06220
06221 emit sig_refreshView();
06222 }
06223
06224 bool Sheet::loadSheetStyleFormat( QDomElement *style )
06225 {
06226 QString hleft, hmiddle, hright;
06227 QString fleft, fmiddle, fright;
06228 QDomNode header = KoDom::namedItemNS( *style, KoXmlNS::style, "header" );
06229
06230 if ( !header.isNull() )
06231 {
06232 kdDebug() << "Header exists" << endl;
06233 QDomNode part = KoDom::namedItemNS( header, KoXmlNS::style, "region-left" );
06234 if ( !part.isNull() )
06235 {
06236 hleft = getPart( part );
06237 kdDebug() << "Header left: " << hleft << endl;
06238 }
06239 else
06240 kdDebug() << "Style:region:left doesn't exist!" << endl;
06241 part = KoDom::namedItemNS( header, KoXmlNS::style, "region-center" );
06242 if ( !part.isNull() )
06243 {
06244 hmiddle = getPart( part );
06245 kdDebug() << "Header middle: " << hmiddle << endl;
06246 }
06247 part = KoDom::namedItemNS( header, KoXmlNS::style, "region-right" );
06248 if ( !part.isNull() )
06249 {
06250 hright = getPart( part );
06251 kdDebug() << "Header right: " << hright << endl;
06252 }
06253 }
06254
06255 QDomNode headerleft = KoDom::namedItemNS( *style, KoXmlNS::style, "header-left" );
06256 if ( !headerleft.isNull() )
06257 {
06258 QDomElement e = headerleft.toElement();
06259 if ( e.hasAttributeNS( KoXmlNS::style, "display" ) )
06260 kdDebug()<<"header.hasAttribute( style:display ) :"<<e.hasAttributeNS( KoXmlNS::style, "display" )<<endl;
06261 else
06262 kdDebug()<<"header left doesn't has attribute style:display \n";
06263 }
06264
06265 QDomNode footerleft = KoDom::namedItemNS( *style, KoXmlNS::style, "footer-left" );
06266 if ( !footerleft.isNull() )
06267 {
06268 QDomElement e = footerleft.toElement();
06269 if ( e.hasAttributeNS( KoXmlNS::style, "display" ) )
06270 kdDebug()<<"footer.hasAttribute( style:display ) :"<<e.hasAttributeNS( KoXmlNS::style, "display" )<<endl;
06271 else
06272 kdDebug()<<"footer left doesn't has attribute style:display \n";
06273 }
06274
06275 QDomNode footer = KoDom::namedItemNS( *style, KoXmlNS::style, "footer" );
06276
06277 if ( !footer.isNull() )
06278 {
06279 QDomNode part = KoDom::namedItemNS( footer, KoXmlNS::style, "region-left" );
06280 if ( !part.isNull() )
06281 {
06282 fleft = getPart( part );
06283 kdDebug() << "Footer left: " << fleft << endl;
06284 }
06285 part = KoDom::namedItemNS( footer, KoXmlNS::style, "region-center" );
06286 if ( !part.isNull() )
06287 {
06288 fmiddle = getPart( part );
06289 kdDebug() << "Footer middle: " << fmiddle << endl;
06290 }
06291 part = KoDom::namedItemNS( footer, KoXmlNS::style, "region-right" );
06292 if ( !part.isNull() )
06293 {
06294 fright = getPart( part );
06295 kdDebug() << "Footer right: " << fright << endl;
06296 }
06297 }
06298
06299 print()->setHeadFootLine( hleft, hmiddle, hright,
06300 fleft, fmiddle, fright );
06301 return true;
06302 }
06303
06304 void Sheet::replaceMacro( QString & text, const QString & old, const QString & newS )
06305 {
06306 int n = text.find( old );
06307 if ( n != -1 )
06308 text = text.replace( n, old.length(), newS );
06309 }
06310
06311
06312 QString Sheet::getPart( const QDomNode & part )
06313 {
06314 QString result;
06315 QDomElement e = KoDom::namedItemNS( part, KoXmlNS::text, "p" );
06316 while ( !e.isNull() )
06317 {
06318 QString text = e.text();
06319 kdDebug() << "PART: " << text << endl;
06320
06321 QDomElement macro = KoDom::namedItemNS( e, KoXmlNS::text, "time" );
06322 if ( !macro.isNull() )
06323 replaceMacro( text, macro.text(), "<time>" );
06324
06325 macro = KoDom::namedItemNS( e, KoXmlNS::text, "date" );
06326 if ( !macro.isNull() )
06327 replaceMacro( text, macro.text(), "<date>" );
06328
06329 macro = KoDom::namedItemNS( e, KoXmlNS::text, "page-number" );
06330 if ( !macro.isNull() )
06331 replaceMacro( text, macro.text(), "<page>" );
06332
06333 macro = KoDom::namedItemNS( e, KoXmlNS::text, "page-count" );
06334 if ( !macro.isNull() )
06335 replaceMacro( text, macro.text(), "<pages>" );
06336
06337 macro = KoDom::namedItemNS( e, KoXmlNS::text, "sheet-name" );
06338 if ( !macro.isNull() )
06339 replaceMacro( text, macro.text(), "<sheet>" );
06340
06341 macro = KoDom::namedItemNS( e, KoXmlNS::text, "title" );
06342 if ( !macro.isNull() )
06343 replaceMacro( text, macro.text(), "<name>" );
06344
06345 macro = KoDom::namedItemNS( e, KoXmlNS::text, "file-name" );
06346 if ( !macro.isNull() )
06347 replaceMacro( text, macro.text(), "<file>" );
06348
06349
06350 if ( !result.isEmpty() )
06351 result += '\n';
06352 result += text;
06353 e = e.nextSibling().toElement();
06354 }
06355
06356 return result;
06357 }
06358
06359
06360 bool Sheet::loadOasis( const QDomElement& sheetElement, KoOasisLoadingContext& oasisContext, QDict<Style>& styleMap )
06361 {
06362 d->layoutDirection = LeftToRight;
06363 if ( sheetElement.hasAttributeNS( KoXmlNS::table, "style-name" ) )
06364 {
06365 QString stylename = sheetElement.attributeNS( KoXmlNS::table, "style-name", QString::null );
06366 kdDebug()<<" style of table :"<<stylename<<endl;
06367 const QDomElement *style = oasisContext.oasisStyles().findStyle( stylename, "table" );
06368 Q_ASSERT( style );
06369 kdDebug()<<" style :"<<style<<endl;
06370 if ( style )
06371 {
06372 QDomElement properties( KoDom::namedItemNS( *style, KoXmlNS::style, "table-properties" ) );
06373 if ( !properties.isNull() )
06374 {
06375 if ( properties.hasAttributeNS( KoXmlNS::table, "display" ) )
06376 {
06377 bool visible = (properties.attributeNS( KoXmlNS::table, "display", QString::null ) == "true" ? true : false );
06378 d->hide = !visible;
06379 }
06380 }
06381 if ( style->hasAttributeNS( KoXmlNS::style, "master-page-name" ) )
06382 {
06383 QString masterPageStyleName = style->attributeNS( KoXmlNS::style, "master-page-name", QString::null );
06384 kdDebug()<<"style->attribute( style:master-page-name ) :"<<masterPageStyleName <<endl;
06385 QDomElement *masterStyle = oasisContext.oasisStyles().masterPages()[masterPageStyleName];
06386 kdDebug()<<"oasisStyles.styles()[masterPageStyleName] :"<<masterStyle<<endl;
06387 if ( masterStyle )
06388 {
06389 loadSheetStyleFormat( masterStyle );
06390 if ( masterStyle->hasAttributeNS( KoXmlNS::style, "page-layout-name" ) )
06391 {
06392 QString masterPageLayoutStyleName = masterStyle->attributeNS( KoXmlNS::style, "page-layout-name", QString::null );
06393 kdDebug()<<"masterPageLayoutStyleName :"<<masterPageLayoutStyleName<<endl;
06394 const QDomElement *masterLayoutStyle = oasisContext.oasisStyles().findStyle( masterPageLayoutStyleName );
06395 if ( masterLayoutStyle )
06396 {
06397 kdDebug()<<"masterLayoutStyle :"<<masterLayoutStyle<<endl;
06398 KoStyleStack styleStack;
06399 styleStack.setTypeProperties( "page-layout" );
06400 styleStack.push( *masterLayoutStyle );
06401 loadOasisMasterLayoutPage( styleStack );
06402 }
06403 }
06404 }
06405 }
06406 }
06407 }
06408
06409
06410 QMap<int,QString> defaultColumnCellStyles;
06411
06412 int rowIndex = 1;
06413 int indexCol = 1;
06414 QDomNode rowNode = sheetElement.firstChild();
06415
06416
06417
06418 while( !rowNode.isNull() && indexCol <= KS_colMax && rowIndex <= KS_rowMax )
06419 {
06420 kdDebug()<<" rowIndex :"<<rowIndex<<" indexCol :"<<indexCol<<endl;
06421 QDomElement rowElement = rowNode.toElement();
06422 if( !rowElement.isNull() )
06423 {
06424 kdDebug()<<" Sheet::loadOasis rowElement.tagName() :"<<rowElement.localName()<<endl;
06425 if ( rowElement.namespaceURI() == KoXmlNS::table )
06426 {
06427 if ( rowElement.localName()=="table-column" )
06428 {
06429 kdDebug ()<<" table-column found : index column before "<< indexCol<<endl;
06430 loadColumnFormat( rowElement, oasisContext.oasisStyles(), indexCol , styleMap);
06431 kdDebug ()<<" table-column found : index column after "<< indexCol<<endl;
06432 }
06433 else if( rowElement.localName() == "table-row" )
06434 {
06435 kdDebug()<<" table-row found :index row before "<<rowIndex<<endl;
06436 loadRowFormat( rowElement, rowIndex, oasisContext, styleMap );
06437 kdDebug()<<" table-row found :index row after "<<rowIndex<<endl;
06438 }
06439 else if ( rowElement.localName() == "shapes" )
06440 loadOasisObjects( rowElement, oasisContext );
06441 }
06442 }
06443 rowNode = rowNode.nextSibling();
06444 }
06445
06446 if ( sheetElement.hasAttributeNS( KoXmlNS::table, "print-ranges" ) )
06447 {
06448
06449 QString range = sheetElement.attributeNS( KoXmlNS::table, "print-ranges", QString::null );
06450 range = Oasis::decodeFormula( range );
06451 Range p( range );
06452 if ( sheetName() == p.sheetName() )
06453 d->print->setPrintRange( p.range() );
06454 }
06455
06456
06457 if ( sheetElement.attributeNS( KoXmlNS::table, "protected", QString::null ) == "true" )
06458 {
06459 QCString passwd( "" );
06460 if ( sheetElement.hasAttributeNS( KoXmlNS::table, "protection-key" ) )
06461 {
06462 QString p = sheetElement.attributeNS( KoXmlNS::table, "protection-key", QString::null );
06463 QCString str( p.latin1() );
06464 kdDebug(30518) << "Decoding password: " << str << endl;
06465 passwd = KCodecs::base64Decode( str );
06466 }
06467 kdDebug(30518) << "Password hash: '" << passwd << "'" << endl;
06468 d->password = passwd;
06469 }
06470 return true;
06471 }
06472
06473
06474 void Sheet::loadOasisObjects( const QDomElement &parent, KoOasisLoadingContext& oasisContext )
06475 {
06476 QDomElement e;
06477 QDomNode n = parent.firstChild();
06478 while( !n.isNull() )
06479 {
06480 e = n.toElement();
06481 if ( e.localName() == "frame" && e.namespaceURI() == KoXmlNS::draw )
06482 {
06483 EmbeddedObject *obj = 0;
06484 QDomNode object = KoDom::namedItemNS( e, KoXmlNS::draw, "object" );
06485 if ( !object.isNull() )
06486 {
06487 if ( !object.toElement().attributeNS( KoXmlNS::draw, "notify-on-update-of-ranges", QString::null).isNull() )
06488 obj = new EmbeddedChart( doc(), this );
06489 else
06490 obj = new EmbeddedKOfficeObject( doc(), this );
06491 }
06492 else
06493 {
06494 QDomNode image = KoDom::namedItemNS( e, KoXmlNS::draw, "image" );
06495 if ( !image.isNull() )
06496 obj = new EmbeddedPictureObject( this, doc()->pictureCollection() );
06497 else
06498 kdDebug() << "Object type wasn't loaded!" << endl;
06499 }
06500
06501 if ( obj )
06502 {
06503 obj->loadOasis( e, oasisContext );
06504 insertObject( obj );
06505 }
06506 }
06507 n = n.nextSibling();
06508 }
06509 }
06510
06511
06512 void Sheet::loadOasisMasterLayoutPage( KoStyleStack &styleStack )
06513 {
06514
06515 float left = 20.0;
06516 float right = 20.0;
06517 float top = 20.0;
06518 float bottom = 20.0;
06519 float width = 210.0;
06520 float height = 297.0;
06521 QString orientation = "Portrait";
06522 QString format;
06523
06524
06525
06526
06527 if ( styleStack.hasAttributeNS( KoXmlNS::fo, "page-width" ) )
06528 {
06529 width = KoUnit::toMM(KoUnit::parseValue( styleStack.attributeNS( KoXmlNS::fo, "page-width" ) ) );
06530 }
06531 if ( styleStack.hasAttributeNS( KoXmlNS::fo, "page-height" ) )
06532 {
06533 height = KoUnit::toMM( KoUnit::parseValue( styleStack.attributeNS( KoXmlNS::fo, "page-height" ) ) );
06534 }
06535 if ( styleStack.hasAttributeNS( KoXmlNS::fo, "margin-top" ) )
06536 {
06537 top = KoUnit::toMM(KoUnit::parseValue( styleStack.attributeNS( KoXmlNS::fo, "margin-top" ) ) );
06538 }
06539 if ( styleStack.hasAttributeNS( KoXmlNS::fo, "margin-bottom" ) )
06540 {
06541 bottom = KoUnit::toMM(KoUnit::parseValue( styleStack.attributeNS( KoXmlNS::fo, "margin-bottom" ) ) );
06542 }
06543 if ( styleStack.hasAttributeNS( KoXmlNS::fo, "margin-left" ) )
06544 {
06545 left = KoUnit::toMM(KoUnit::parseValue( styleStack.attributeNS( KoXmlNS::fo, "margin-left" ) ) );
06546 }
06547 if ( styleStack.hasAttributeNS( KoXmlNS::fo, "margin-right" ) )
06548 {
06549 right = KoUnit::toMM(KoUnit::parseValue( styleStack.attributeNS( KoXmlNS::fo, "margin-right" ) ) );
06550 }
06551 if ( styleStack.hasAttributeNS( KoXmlNS::style, "writing-mode" ) )
06552 {
06553 kdDebug()<<"styleStack.hasAttribute( style:writing-mode ) :"<<styleStack.hasAttributeNS( KoXmlNS::style, "writing-mode" )<<endl;
06554 d->layoutDirection = ( styleStack.attributeNS( KoXmlNS::style, "writing-mode" )=="lr-tb" ) ? LeftToRight : RightToLeft;
06555
06556
06557
06558
06559
06560
06561
06562
06563
06564
06565 }
06566 if ( styleStack.hasAttributeNS( KoXmlNS::style, "print-orientation" ) )
06567 {
06568 orientation = ( styleStack.attributeNS( KoXmlNS::style, "print-orientation" )=="landscape" ) ? "Landscape" : "Portrait" ;
06569 }
06570 if ( styleStack.hasAttributeNS( KoXmlNS::style, "num-format" ) )
06571 {
06572
06573
06574
06575
06576 kdDebug()<<" num-format :"<<styleStack.attributeNS( KoXmlNS::style, "num-format" )<<endl;
06577
06578 }
06579 if ( styleStack.hasAttributeNS( KoXmlNS::fo, "background-color" ) )
06580 {
06581
06582 kdDebug()<<" fo:background-color :"<<styleStack.attributeNS( KoXmlNS::fo, "background-color" )<<endl;
06583 }
06584 if ( styleStack.hasAttributeNS( KoXmlNS::style, "print" ) )
06585 {
06586
06587 QString str = styleStack.attributeNS( KoXmlNS::style, "print" );
06588 kdDebug()<<" style:print :"<<str<<endl;
06589
06590 if (str.contains( "headers" ) )
06591 {
06592
06593 }
06594 if ( str.contains( "grid" ) )
06595 {
06596 d->print->setPrintGrid( true );
06597 }
06598 if ( str.contains( "annotations" ) )
06599 {
06600
06601 }
06602 if ( str.contains( "objects" ) )
06603 {
06604
06605 }
06606 if ( str.contains( "charts" ) )
06607 {
06608
06609 }
06610 if ( str.contains( "drawings" ) )
06611 {
06612
06613 }
06614 if ( str.contains( "formulas" ) )
06615 {
06616 d->showFormula = true;
06617 }
06618 if ( str.contains( "zero-values" ) )
06619 {
06620
06621 }
06622 }
06623 if ( styleStack.hasAttributeNS( KoXmlNS::style, "table-centering" ) )
06624 {
06625 QString str = styleStack.attributeNS( KoXmlNS::style, "table-centering" );
06626
06627 kdDebug()<<" styleStack.attribute( style:table-centering ) :"<<str<<endl;
06628 #if 0
06629 if ( str == "horizontal" )
06630 {
06631 }
06632 else if ( str == "vertical" )
06633 {
06634 }
06635 else if ( str == "both" )
06636 {
06637 }
06638 else if ( str == "none" )
06639 {
06640 }
06641 else
06642 kdDebug()<<" table-centering unknown :"<<str<<endl;
06643 #endif
06644 }
06645 format = QString( "%1x%2" ).arg( width ).arg( height );
06646 kdDebug()<<" format : "<<format<<endl;
06647 d->print->setPaperLayout( left, top, right, bottom, format, orientation );
06648
06649 kdDebug()<<" left margin :"<<left<<" right :"<<right<<" top :"<<top<<" bottom :"<<bottom<<endl;
06650
06651
06652
06653
06654
06655 }
06656
06657
06658 bool Sheet::loadColumnFormat(const QDomElement& column, const KoOasisStyles& oasisStyles, int & indexCol, const QDict<Style>& styleMap)
06659 {
06660 kdDebug()<<"bool Sheet::loadColumnFormat(const QDomElement& column, const KoOasisStyles& oasisStyles, unsigned int & indexCol ) index Col :"<<indexCol<<endl;
06661
06662 bool collapsed = ( column.attributeNS( KoXmlNS::table, "visibility", QString::null ) == "collapse" );
06663 Format layout( this , doc()->styleManager()->defaultStyle() );
06664 int number = 1;
06665 double width = 10;
06666 if ( column.hasAttributeNS( KoXmlNS::table, "number-columns-repeated" ) )
06667 {
06668 bool ok = true;
06669 int n = column.attributeNS( KoXmlNS::table, "number-columns-repeated", QString::null ).toInt( &ok );
06670 if ( ok )
06671
06672
06673
06674 number = QMIN( n, KS_colMax - indexCol + 1 );
06675 kdDebug() << "Repeated: " << number << endl;
06676 }
06677
06678 KoStyleStack styleStack;
06679 styleStack.setTypeProperties("table-column");
06680 if ( column.hasAttributeNS( KoXmlNS::table, "default-cell-style-name" ) )
06681 {
06682 QString str = column.attributeNS( KoXmlNS::table, "default-cell-style-name", QString::null );
06683 kdDebug()<<" default-cell-style-name:"<<str<<" for column " << indexCol <<endl;
06684
06685
06686
06687
06688 }
06689
06690 styleStack.setTypeProperties("table-column");
06691 if ( column.hasAttributeNS( KoXmlNS::table, "style-name" ) )
06692 {
06693 QString str = column.attributeNS( KoXmlNS::table, "style-name", QString::null );
06694 const QDomElement *style = oasisStyles.findStyle( str, "table-column" );
06695 if (style)
06696 {
06697 styleStack.push( *style );
06698
06699
06700
06701 }
06702
06703 kdDebug()<<" style column:"<<style<<"style name : "<<str<<endl;
06704 }
06705
06706 if ( styleStack.hasAttributeNS( KoXmlNS::style, "column-width" ) )
06707 {
06708 width = KoUnit::parseValue( styleStack.attributeNS( KoXmlNS::style, "column-width" ) , -1 );
06709 kdDebug()<<" style:column-width : width :"<<width<<endl;
06710 }
06711
06712 bool insertPageBreak = false;
06713 if ( styleStack.hasAttributeNS( KoXmlNS::fo, "break-before" ) )
06714 {
06715 QString str = styleStack.attributeNS( KoXmlNS::fo, "break-before" );
06716 if ( str == "page" )
06717 {
06718 insertPageBreak = true;
06719 }
06720 else
06721 kdDebug()<<" str :"<<str<<endl;
06722 }
06723
06724
06725
06726
06727
06728 for ( int i = 0; i < number; ++i )
06729 {
06730 kdDebug()<<" insert new column: pos :"<<indexCol<<" width :"<<width<<" hidden ? "<<collapsed<<endl;
06731 ColumnFormat * col = new ColumnFormat( this, indexCol );
06732 col->copy( layout );
06733 if ( width != -1 )
06734 col->setWidth( (int) width );
06735
06736
06737
06738
06739 if ( collapsed )
06740 col->setHide( true );
06741
06742 insertColumnFormat( col );
06743 ++indexCol;
06744 }
06745 kdDebug()<<" after index column !!!!!!!!!!!!!!!!!! :"<<indexCol<<endl;
06746 return true;
06747 }
06748
06749
06750 bool Sheet::loadRowFormat( const QDomElement& row, int &rowIndex, KoOasisLoadingContext& oasisContext, QDict<Style>& styleMap )
06751 {
06752
06753 double height = -1.0;
06754 Format layout( this , doc()->styleManager()->defaultStyle() );
06755 KoStyleStack styleStack;
06756 styleStack.setTypeProperties( "table-row" );
06757 int backupRow = rowIndex;
06758
06759 if ( row.hasAttributeNS( KoXmlNS::table, "style-name" ) )
06760 {
06761 QString str = row.attributeNS( KoXmlNS::table, "style-name", QString::null );
06762 const QDomElement *style = oasisContext.oasisStyles().findStyle( str, "table-row" );
06763 if ( style )
06764 styleStack.push( *style );
06765
06766 }
06767
06768 if ( row.hasAttributeNS( KoXmlNS::table,"default-cell-style-name" ) )
06769 {
06770 QString str = row.attributeNS( KoXmlNS::table, "default-cell-style-name", QString::null );
06771
06772
06773
06774
06775 }
06776
06777 layout.loadOasisStyleProperties( styleStack, oasisContext.oasisStyles() );
06778 styleStack.setTypeProperties( "table-row" );
06779 if ( styleStack.hasAttributeNS( KoXmlNS::style, "row-height" ) )
06780 {
06781 height = KoUnit::parseValue( styleStack.attributeNS( KoXmlNS::style, "row-height" ) , -1 );
06782
06783 }
06784
06785 int number = 1;
06786 if ( row.hasAttributeNS( KoXmlNS::table, "number-rows-repeated" ) )
06787 {
06788 bool ok = true;
06789 int n = row.attributeNS( KoXmlNS::table, "number-rows-repeated", QString::null ).toInt( &ok );
06790 if ( ok )
06791
06792
06793
06794 number = QMIN( n, KS_rowMax - rowIndex + 1 );
06795 }
06796 bool collapse = false;
06797 if ( row.hasAttributeNS( KoXmlNS::table, "visibility" ) )
06798 {
06799 QString visible = row.attributeNS( KoXmlNS::table, "visibility", QString::null );
06800
06801 if ( visible == "collapse" )
06802 collapse=true;
06803 else
06804 kdDebug()<<" visible row not implemented/supported : "<<visible<<endl;
06805
06806 }
06807
06808 bool insertPageBreak = false;
06809 if ( styleStack.hasAttributeNS( KoXmlNS::fo, "break-before" ) )
06810 {
06811 QString str = styleStack.attributeNS( KoXmlNS::fo, "break-before" );
06812 if ( str == "page" )
06813 {
06814 insertPageBreak = true;
06815 }
06816
06817
06818 }
06819
06820
06821 for ( int i = 0; i < number; ++i )
06822 {
06823
06824 RowFormat * rowL = nonDefaultRowFormat( rowIndex );
06825 rowL->copy( layout );
06826 if ( height != -1 )
06827 {
06828
06829 rowL->setHeight( (int) height );
06830 }
06831 if ( collapse )
06832 rowL->setHide( true );
06833
06834 ++rowIndex;
06835 }
06836
06837 int columnIndex = 0;
06838 QDomNode cellNode = row.firstChild();
06839 int endRow = min(backupRow+number,KS_rowMax);
06840
06841
06842 while( !cellNode.isNull() )
06843 {
06844 QDomElement cellElement = cellNode.toElement();
06845 if( !cellElement.isNull() )
06846 {
06847 columnIndex++;
06848 QString localName = cellElement.localName();
06849
06850 if( ((localName == "table-cell") || (localName == "covered-table-cell")) && cellElement.namespaceURI() == KoXmlNS::table)
06851 {
06852
06853
06854 Cell* cell = nonDefaultCell( columnIndex, backupRow );
06855 bool cellHasStyle = cellElement.hasAttributeNS( KoXmlNS::table, "style-name" );
06856
06857 Style* style = 0;
06858
06859 if ( cellHasStyle )
06860 {
06861 style = styleMap[ cellElement.attributeNS( KoXmlNS::table , "style-name" , QString::null ) ];
06862 }
06863
06864 cell->loadOasis( cellElement, oasisContext, style );
06865
06866
06867 bool haveStyle = cellHasStyle;
06868 int cols = 1;
06869
06870
06871
06872 if( (number > 1) || cellElement.hasAttributeNS( KoXmlNS::table, "number-columns-repeated" ) )
06873 {
06874 bool ok = false;
06875 int n = cellElement.attributeNS( KoXmlNS::table, "number-columns-repeated", QString::null ).toInt( &ok );
06876
06877 if (ok)
06878
06879
06880
06881 cols = QMIN( n, KS_colMax - columnIndex + 1 );
06882
06883 if ( !haveStyle && ( cell->isEmpty() && cell->format()->comment( columnIndex, backupRow ).isEmpty() ) )
06884 {
06885
06886 columnIndex +=cols - 1;
06887 }
06888 else
06889 {
06890 for(int k = cols ; k ; --k )
06891 {
06892 if (k != cols)
06893 columnIndex++;
06894
06895 Style* targetStyle = style;
06896
06897 for ( int newRow = backupRow; newRow < endRow;++newRow )
06898 {
06899 if ( targetStyle && (targetStyle->features() != 0 ) )
06900 {
06901 Cell* target = nonDefaultCell( columnIndex, newRow );
06902
06903 if (cell != target)
06904 target->copyAll( cell );
06905 }
06906 }
06907 }
06908 }
06909 }
06910 }
06911 }
06912 cellNode = cellNode.nextSibling();
06913 }
06914
06915 return true;
06916 }
06917
06918 void Sheet::maxRowCols( int & maxCols, int & maxRows )
06919 {
06920 const Cell * cell = firstCell();
06921 while ( cell )
06922 {
06923 if ( cell->column() > maxCols )
06924 maxCols = cell->column();
06925
06926 if ( cell->row() > maxRows )
06927 maxRows = cell->row();
06928
06929 cell = cell->nextCell();
06930 }
06931
06932 const RowFormat * row = firstRow();
06933 while ( row )
06934 {
06935 if ( row->row() > maxRows )
06936 maxRows = row->row();
06937
06938 row = row->next();
06939 }
06940 const ColumnFormat* col = firstCol();
06941 while ( col )
06942 {
06943 if ( col->column() > maxCols )
06944 maxCols = col->column();
06945
06946 col = col->next();
06947 }
06948 }
06949
06950
06951 void Sheet::saveOasisHeaderFooter( KoXmlWriter &xmlWriter ) const
06952 {
06953 QString headerLeft = print()->headLeft();
06954 QString headerCenter= print()->headMid();
06955 QString headerRight = print()->headRight();
06956
06957 QString footerLeft = print()->footLeft();
06958 QString footerCenter= print()->footMid();
06959 QString footerRight = print()->footRight();
06960
06961 xmlWriter.startElement( "style:header");
06962 if ( ( !headerLeft.isEmpty() )
06963 || ( !headerCenter.isEmpty() )
06964 || ( !headerRight.isEmpty() ) )
06965 {
06966 xmlWriter.startElement( "style:region-left" );
06967 xmlWriter.startElement( "text:p" );
06968 convertPart( headerLeft, xmlWriter );
06969 xmlWriter.endElement();
06970 xmlWriter.endElement();
06971
06972 xmlWriter.startElement( "style:region-center" );
06973 xmlWriter.startElement( "text:p" );
06974 convertPart( headerCenter, xmlWriter );
06975 xmlWriter.endElement();
06976 xmlWriter.endElement();
06977
06978 xmlWriter.startElement( "style:region-right" );
06979 xmlWriter.startElement( "text:p" );
06980 convertPart( headerRight, xmlWriter );
06981 xmlWriter.endElement();
06982 xmlWriter.endElement();
06983 }
06984 else
06985 {
06986 xmlWriter.startElement( "text:p" );
06987
06988 xmlWriter.startElement( "text:sheet-name" );
06989 xmlWriter.addTextNode( "???" );
06990 xmlWriter.endElement();
06991
06992 xmlWriter.endElement();
06993 }
06994 xmlWriter.endElement();
06995
06996
06997 xmlWriter.startElement( "style:footer");
06998 if ( ( !footerLeft.isEmpty() )
06999 || ( !footerCenter.isEmpty() )
07000 || ( !footerRight.isEmpty() ) )
07001 {
07002 xmlWriter.startElement( "style:region-left" );
07003 xmlWriter.startElement( "text:p" );
07004 convertPart( footerLeft, xmlWriter );
07005 xmlWriter.endElement();
07006 xmlWriter.endElement();
07007
07008 xmlWriter.startElement( "style:region-center" );
07009 xmlWriter.startElement( "text:p" );
07010 convertPart( footerCenter, xmlWriter );
07011 xmlWriter.endElement();
07012 xmlWriter.endElement();
07013
07014 xmlWriter.startElement( "style:region-right" );
07015 xmlWriter.startElement( "text:p" );
07016 convertPart( footerRight, xmlWriter );
07017 xmlWriter.endElement();
07018 xmlWriter.endElement();
07019 }
07020 else
07021 {
07022
07023 xmlWriter.startElement( "text:p" );
07024
07025 xmlWriter.startElement( "text:sheet-name" );
07026 xmlWriter.addTextNode( "Page " );
07027
07028 xmlWriter.startElement( "text:page-number" );
07029 xmlWriter.addTextNode( "1" );
07030 xmlWriter.endElement();
07031
07032
07033 xmlWriter.endElement();
07034
07035 xmlWriter.endElement();
07036 }
07037 xmlWriter.endElement();
07038
07039
07040 }
07041
07042 void Sheet::addText( const QString & text, KoXmlWriter & writer ) const
07043 {
07044 if ( !text.isEmpty() )
07045 writer.addTextNode( text );
07046 }
07047
07048 void Sheet::convertPart( const QString & part, KoXmlWriter & xmlWriter ) const
07049 {
07050 QString text;
07051 QString var;
07052
07053 bool inVar = false;
07054 uint i = 0;
07055 uint l = part.length();
07056 while ( i < l )
07057 {
07058 if ( inVar || part[i] == '<' )
07059 {
07060 inVar = true;
07061 var += part[i];
07062 if ( part[i] == '>' )
07063 {
07064 inVar = false;
07065 if ( var == "<page>" )
07066 {
07067 addText( text, xmlWriter );
07068 xmlWriter.startElement( "text:page-number" );
07069 xmlWriter.addTextNode( "1" );
07070 xmlWriter.endElement();
07071 }
07072 else if ( var == "<pages>" )
07073 {
07074 addText( text, xmlWriter );
07075 xmlWriter.startElement( "text:page-count" );
07076 xmlWriter.addTextNode( "99" );
07077 xmlWriter.endElement();
07078 }
07079 else if ( var == "<date>" )
07080 {
07081 addText( text, xmlWriter );
07082
07083 #if 0 //FIXME
07084 QDomElement t = dd.createElement( "text:date" );
07085 t.setAttribute( "text:date-value", "0-00-00" );
07086
07087 t.appendChild( dd.createTextNode( QDate::currentDate().toString() ) );
07088 parent.appendChild( t );
07089 #endif
07090 }
07091 else if ( var == "<time>" )
07092 {
07093 addText( text, xmlWriter );
07094
07095 xmlWriter.startElement( "text:time" );
07096 xmlWriter.addTextNode( QTime::currentTime().toString() );
07097 xmlWriter.endElement();
07098 }
07099 else if ( var == "<file>" )
07100 {
07101 addText( text, xmlWriter );
07102 xmlWriter.startElement( "text:file-name" );
07103 xmlWriter.addAttribute( "text:display", "full" );
07104 xmlWriter.addTextNode( "???" );
07105 xmlWriter.endElement();
07106 }
07107 else if ( var == "<name>" )
07108 {
07109 addText( text, xmlWriter );
07110
07111 xmlWriter.startElement( "text:title" );
07112 xmlWriter.addTextNode( "???" );
07113 xmlWriter.endElement();
07114 }
07115 else if ( var == "<author>" )
07116 {
07117 Doc* sdoc = d->workbook->doc();
07118 KoDocumentInfo * docInfo = sdoc->documentInfo();
07119 KoDocumentInfoAuthor * authorPage = static_cast<KoDocumentInfoAuthor*>( docInfo->page( "author" ) );
07120
07121 text += authorPage->fullName();
07122
07123 addText( text, xmlWriter );
07124 }
07125 else if ( var == "<email>" )
07126 {
07127 Doc* sdoc = d->workbook->doc();
07128 KoDocumentInfo * docInfo = sdoc->documentInfo();
07129 KoDocumentInfoAuthor * authorPage = static_cast<KoDocumentInfoAuthor*>( docInfo->page( "author" ) );
07130
07131 text += authorPage->email();
07132 addText( text, xmlWriter );
07133
07134 }
07135 else if ( var == "<org>" )
07136 {
07137 Doc* sdoc = d->workbook->doc();
07138 KoDocumentInfo * docInfo = sdoc->documentInfo();
07139 KoDocumentInfoAuthor * authorPage = static_cast<KoDocumentInfoAuthor*>( docInfo->page( "author" ) );
07140
07141 text += authorPage->company();
07142 addText( text, xmlWriter );
07143
07144 }
07145 else if ( var == "<sheet>" )
07146 {
07147 addText( text, xmlWriter );
07148
07149 xmlWriter.startElement( "text:sheet-name" );
07150 xmlWriter.addTextNode( "???" );
07151 xmlWriter.endElement();
07152 }
07153 else
07154 {
07155
07156 text += var;
07157 addText( text, xmlWriter );
07158 }
07159
07160 text = "";
07161 var = "";
07162 }
07163 }
07164 else
07165 {
07166 text += part[i];
07167 }
07168 ++i;
07169 }
07170 if ( !text.isEmpty() || !var.isEmpty() )
07171 {
07172
07173 addText( text+var, xmlWriter );
07174 }
07175 kdDebug()<<" text end :"<<text<<" var :"<<var<<endl;
07176 }
07177
07178
07179 void Sheet::loadOasisSettings( const KoOasisSettings::NamedMap &settings )
07180 {
07181
07182 KoOasisSettings::Items items = settings.entry( d->name );
07183 if ( items.isNull() )
07184 return;
07185 d->hideZero = items.parseConfigItemBool( "ShowZeroValues" );
07186 d->showGrid = items.parseConfigItemBool( "ShowGrid" );
07187 d->firstLetterUpper = items.parseConfigItemBool( "FirstLetterUpper" );
07188
07189 int cursorX = items.parseConfigItemInt( "CursorPositionX" );
07190 int cursorY = items.parseConfigItemInt( "CursorPositionY" );
07191
07192 doc()->loadingInfo()->addMarkerSelection( this, QPoint( cursorX, cursorY ) );
07193 kdDebug()<<"d->hideZero :"<<d->hideZero<<" d->showGrid :"<<d->showGrid<<" d->firstLetterUpper :"<<d->firstLetterUpper<<" cursorX :"<<cursorX<<" cursorY :"<<cursorY<< endl;
07194
07195 d->showFormulaIndicator = items.parseConfigItemBool( "ShowFormulaIndicator" );
07196 d->showCommentIndicator = items.parseConfigItemBool( "ShowCommentIndicator" );
07197 d->showPageBorders = items.parseConfigItemBool( "ShowPageBorders" );
07198 d->lcMode = items.parseConfigItemBool( "lcmode" );
07199 d->autoCalc = items.parseConfigItemBool( "autoCalc" );
07200 d->showColumnNumber = items.parseConfigItemBool( "ShowColumnNumber" );
07201 d->firstLetterUpper = items.parseConfigItemBool( "FirstLetterUpper" );
07202 }
07203
07204 void Sheet::saveOasisSettings( KoXmlWriter &settingsWriter, const QPoint& marker ) const
07205 {
07206
07207 settingsWriter.addConfigItem( "ShowZeroValues", d->hideZero );
07208 settingsWriter.addConfigItem( "ShowGrid", d->showGrid );
07209
07210
07211 settingsWriter.addConfigItem( "FirstLetterUpper", d->firstLetterUpper);
07212
07213
07214
07215 settingsWriter.addConfigItem( "CursorPositionX", marker.x() );
07216 settingsWriter.addConfigItem( "CursorPositionY", marker.y() );
07217
07218 settingsWriter.addConfigItem( "ShowFormulaIndicator", d->showFormulaIndicator );
07219 settingsWriter.addConfigItem( "ShowCommentIndicator", d->showCommentIndicator );
07220 settingsWriter.addConfigItem( "ShowPageBorders",d->showPageBorders );
07221 settingsWriter.addConfigItem( "lcmode", d->lcMode );
07222 settingsWriter.addConfigItem( "autoCalc", d->autoCalc );
07223 settingsWriter.addConfigItem( "ShowColumnNumber", d->showColumnNumber );
07224 settingsWriter.addConfigItem( "FirstLetterUpper", d->firstLetterUpper );
07225 }
07226
07227
07228 bool Sheet::saveOasis( KoXmlWriter & xmlWriter, KoGenStyles &mainStyles, GenValidationStyles &valStyle, KoStore *store, KoXmlWriter* , int &indexObj, int &partIndexObj )
07229 {
07230 int maxCols= 1;
07231 int maxRows= 1;
07232 xmlWriter.startElement( "table:table" );
07233 xmlWriter.addAttribute( "table:name", d->name );
07234 xmlWriter.addAttribute( "table:style-name", saveOasisSheetStyleName(mainStyles ) );
07235 if ( !d->password.isEmpty() )
07236 {
07237 xmlWriter.addAttribute("table:protected", "true" );
07238 QCString str = KCodecs::base64Encode( d->password );
07239 xmlWriter.addAttribute("table:protection-key", QString( str.data() ) );
07240 }
07241 QRect _printRange = d->print->printRange();
07242 if ( _printRange != ( QRect( QPoint( 1, 1 ), QPoint( KS_colMax, KS_rowMax ) ) ) )
07243 {
07244 QString range= convertRangeToRef( d->name, _printRange );
07245 kdDebug()<<" range : "<<range<<endl;
07246 xmlWriter.addAttribute( "table:print-ranges", range );
07247 }
07248
07249 saveOasisObjects( store, xmlWriter, mainStyles, indexObj, partIndexObj );
07250 maxRowCols( maxCols, maxRows );
07251 saveOasisColRowCell( xmlWriter, mainStyles, maxCols, maxRows, valStyle );
07252 xmlWriter.endElement();
07253 return true;
07254 }
07255
07256 void Sheet::saveOasisPrintStyleLayout( KoGenStyle &style ) const
07257 {
07258 QString printParameter;
07259 if ( d->print->printGrid() )
07260 printParameter="grid ";
07261 if ( d->print->printObjects() )
07262 printParameter+="objects ";
07263 if ( d->print->printCharts() )
07264 printParameter+="charts ";
07265 if ( d->showFormula )
07266 printParameter+="formulas ";
07267 if ( !printParameter.isEmpty() )
07268 {
07269 printParameter+="drawings zero-values";
07270 style.addProperty( "style:print", printParameter );
07271 }
07272 }
07273
07274 QString Sheet::saveOasisSheetStyleName( KoGenStyles &mainStyles )
07275 {
07276 KoGenStyle pageStyle( Doc::STYLE_PAGE, "table" );
07277
07278 KoGenStyle pageMaster( Doc::STYLE_PAGEMASTER );
07279 pageMaster.addAttribute( "style:page-layout-name", d->print->saveOasisSheetStyleLayout( mainStyles ) );
07280
07281 QBuffer buffer;
07282 buffer.open( IO_WriteOnly );
07283 KoXmlWriter elementWriter( &buffer );
07284 saveOasisHeaderFooter(elementWriter);
07285
07286 QString elementContents = QString::fromUtf8( buffer.buffer(), buffer.buffer().size() );
07287 pageMaster.addChildElement( "headerfooter", elementContents );
07288 pageStyle.addAttribute( "style:master-page-name", mainStyles.lookup( pageMaster, "Standard" ) );
07289
07290 pageStyle.addProperty( "table:display", !d->hide );
07291 return mainStyles.lookup( pageStyle, "ta" );
07292 }
07293
07294
07295 void Sheet::saveOasisColRowCell( KoXmlWriter& xmlWriter, KoGenStyles& mainStyles,
07296 int maxCols, int maxRows, GenValidationStyles& valStyle )
07297 {
07298 Q_UNUSED( maxCols );
07299 kdDebug() << "Sheet::saveOasisColRowCell: " << d->name << endl;
07300 int i = 1;
07301 ColumnFormat* column = columnFormat( i );
07302 ColumnFormat* nextColumn = d->columns.next( i );
07303 while ( !column->isDefault() || nextColumn )
07304 {
07305
07306
07307
07308 KoGenStyle currentColumnStyle( Doc::STYLE_COLUMN, "table-column" );
07309 currentColumnStyle.addPropertyPt( "style:column-width", column->dblWidth() );
07310 currentColumnStyle.addProperty( "fo:break-before", "auto" );
07311
07312
07313 KoGenStyle currentDefaultCellStyle;
07314 QString currentDefaultCellStyleName = column->saveOasisCellStyle( currentDefaultCellStyle, mainStyles );
07315
07316 bool hide = column->isHide();
07317 int j = i + 1;
07318 int repeated = 1;
07319
07320 while ( nextColumn )
07321 {
07322
07323
07324
07325
07326 if ( nextColumn->column() != j )
07327 {
07328 if ( column->isDefault() )
07329 {
07330
07331
07332 repeated = nextColumn->column() - j + 1;
07333 }
07334
07335
07336 break;
07337 }
07338
07339 KoGenStyle nextColumnStyle( Doc::STYLE_COLUMN, "table-column" );
07340 nextColumnStyle.addPropertyPt( "style:column-width", nextColumn->dblWidth() );
07341 nextColumnStyle.addProperty( "fo:break-before", "auto" );
07342
07343 KoGenStyle nextDefaultCellStyle;
07344 QString nextDefaultCellStyleName = nextColumn->saveOasisCellStyle( nextDefaultCellStyle, mainStyles );
07345
07346 if ( hide != nextColumn->isHide() ||
07347 nextDefaultCellStyleName != currentDefaultCellStyleName ||
07348 !( nextColumnStyle == currentColumnStyle ) )
07349 {
07350 break;
07351 }
07352
07353 ++repeated;
07354 nextColumn = d->columns.next( j++ );
07355 }
07356
07357 xmlWriter.startElement( "table:table-column" );
07358 xmlWriter.addAttribute( "table:style-name", mainStyles.lookup( currentColumnStyle, "co" ) );
07359
07360
07361
07362
07363 if ( !currentDefaultCellStyle.isDefaultStyle() )
07364 xmlWriter.addAttribute( "table:default-cell-style-name", currentDefaultCellStyleName );
07365
07366 if ( hide )
07367 xmlWriter.addAttribute( "table:visibility", "collapse" );
07368
07369 if ( repeated > 1 )
07370 xmlWriter.addAttribute( "table:number-columns-repeated", repeated );
07371
07372 xmlWriter.endElement();
07373
07374 kdDebug() << "Sheet::saveOasisColRowCell: column " << i << " "
07375 << "repeated " << repeated << " time(s)" << endl;
07376 i += repeated;
07377 column = columnFormat( i );
07378 nextColumn = d->columns.next( i );
07379 }
07380
07381
07382 for ( i = 1; i <= maxRows; ++i )
07383 {
07384
07385 const RowFormat* row = rowFormat( i );
07386
07387 KoGenStyle currentRowStyle( Doc::STYLE_ROW, "table-row" );
07388 currentRowStyle.addPropertyPt( "style:row-height", row->dblHeight());
07389 currentRowStyle.addProperty( "fo:break-before", "auto" );
07390
07391 xmlWriter.startElement( "table:table-row" );
07392
07393
07394
07395 xmlWriter.addAttribute( "table:style-name", mainStyles.lookup( currentRowStyle, "ro" ) );
07396 int repeated = 1;
07397
07398 if ( !getFirstCellRow( i ) )
07399 {
07400 bool hide = row->isHide();
07401 int j = i + 1;
07402 RowFormat *nextRow = d->rows.next( i );
07403 while ( nextRow )
07404 {
07405
07406
07407
07408
07409 if ( nextRow->row() != j )
07410 {
07411 if ( row->isDefault() )
07412 {
07413
07414
07415 repeated = nextRow->row() - j + 1;
07416 }
07417
07418
07419 break;
07420 }
07421
07422 KoGenStyle nextRowStyle( Doc::STYLE_ROW, "table-row" );
07423 nextRowStyle.addPropertyPt( "style:row-height", nextRow->dblHeight() );
07424 nextRowStyle.addProperty( "fo:break-before", "auto" );
07425
07426
07427
07428 if ( hide != nextRow->isHide() ||
07429 !(nextRowStyle == currentRowStyle) )
07430 {
07431 break;
07432 }
07433
07434 ++repeated;
07435 nextRow = d->rows.next( j++ );
07436 }
07437
07438 kdDebug() << "Sheet::saveOasisColRowCell: empty row " << i << " "
07439 << "repeated " << repeated << " time(s)" << endl;
07440 i += repeated - 1;
07441
07442 if ( repeated > 1 )
07443 xmlWriter.addAttribute( "table:number-rows-repeated", repeated );
07444 }
07445 else
07446 {
07447 saveOasisCells( xmlWriter, mainStyles, i, valStyle );
07448 }
07449
07450 if ( row->isHide() )
07451 xmlWriter.addAttribute( "table:visibility", "collapse" );
07452
07453 xmlWriter.endElement();
07454 }
07455 }
07456
07457 void Sheet::saveOasisCells( KoXmlWriter& xmlWriter, KoGenStyles& mainStyles,
07458 int row, GenValidationStyles& valStyle )
07459 {
07460 int i = 1;
07461 Cell* cell = cellAt( i, row );
07462 Cell* nextCell = getNextCellRight( i, row );
07463 while ( !cell->isDefault() || nextCell )
07464 {
07465
07466
07467
07468 int repeated = 1;
07469 cell->saveOasis( xmlWriter, mainStyles, row, i, repeated, valStyle );
07470 i += repeated;
07471 cell = cellAt( i, row );
07472 nextCell = getNextCellRight( i, row );
07473 }
07474 }
07475
07476 bool Sheet::loadXML( const QDomElement& sheet )
07477 {
07478 bool ok = false;
07479 if ( !doc()->loadingInfo() || !doc()->loadingInfo()->loadTemplate() )
07480 {
07481 d->name = sheet.attribute( "name" );
07482 if ( d->name.isEmpty() )
07483 {
07484 doc()->setErrorMessage( i18n("Invalid document. Sheet name is empty.") );
07485 return false;
07486 }
07487 }
07488
07489 bool detectDirection = true;
07490 d->layoutDirection = LeftToRight;
07491 QString layoutDir = sheet.attribute( "layoutDirection" );
07492 if( !layoutDir.isEmpty() )
07493 {
07494 if( layoutDir == "rtl" )
07495 {
07496 detectDirection = false;
07497 d->layoutDirection = RightToLeft;
07498 }
07499 else if( layoutDir == "ltr" )
07500 {
07501 detectDirection = false;
07502 d->layoutDirection = LeftToRight;
07503 }
07504 else
07505 kdDebug()<<" Direction not implemented : "<<layoutDir<<endl;
07506 }
07507 if( detectDirection )
07508 checkContentDirection( d->name );
07509
07510
07511
07512
07513
07514 if (d->name[0] == ' ')
07515 {
07516 d->name.remove(0,1);
07517 }
07518 for (unsigned int i=0; i < d->name.length(); i++)
07519 {
07520 if ( !(d->name[i].isLetterOrNumber() ||
07521 d->name[i] == ' ' || d->name[i] == '.' ||
07522 d->name[i] == '_'))
07523 {
07524 d->name[i] = '_';
07525 }
07526 }
07527
07528
07529 QString testName;
07530 QString baseName;
07531 int nameSuffix = 0;
07532
07533 testName = d->name;
07534 baseName = d->name;
07535
07536
07537 d->name = "";
07538 while (workbook()->findSheet(testName) != NULL)
07539 {
07540 nameSuffix++;
07541 testName = baseName + '_' + QString::number(nameSuffix);
07542 }
07543 d->name = testName;
07544
07545 kdDebug(36001)<<"Sheet::loadXML: table name="<<d->name<<endl;
07546 setName(d->name.utf8());
07547 (dynamic_cast<SheetIface*>(dcopObject()))->sheetNameHasChanged();
07548
07549 if( sheet.hasAttribute( "grid" ) )
07550 {
07551 d->showGrid = (int)sheet.attribute("grid").toInt( &ok );
07552
07553 }
07554 if( sheet.hasAttribute( "printGrid" ) )
07555 {
07556 d->print->setPrintGrid( (bool)sheet.attribute("printGrid").toInt( &ok ) );
07557
07558 }
07559 if( sheet.hasAttribute( "printCommentIndicator" ) )
07560 {
07561 d->print->setPrintCommentIndicator( (bool)sheet.attribute("printCommentIndicator").toInt( &ok ) );
07562
07563 }
07564 if( sheet.hasAttribute( "printFormulaIndicator" ) )
07565 {
07566 d->print->setPrintFormulaIndicator( (bool)sheet.attribute("printFormulaIndicator").toInt( &ok ) );
07567
07568 }
07569 if( sheet.hasAttribute( "hide" ) )
07570 {
07571 d->hide = (bool)sheet.attribute("hide").toInt( &ok );
07572
07573 }
07574 if( sheet.hasAttribute( "showFormula" ) )
07575 {
07576 d->showFormula = (bool)sheet.attribute("showFormula").toInt( &ok );
07577
07578 }
07579
07580 if( sheet.hasAttribute( "formular" ) )
07581 {
07582 d->showFormula = (bool)sheet.attribute("formular").toInt( &ok );
07583
07584 }
07585 if( sheet.hasAttribute( "showFormulaIndicator" ) )
07586 {
07587 d->showFormulaIndicator = (bool)sheet.attribute("showFormulaIndicator").toInt( &ok );
07588
07589 }
07590 if( sheet.hasAttribute( "showCommentIndicator" ) )
07591 {
07592 d->showCommentIndicator = (bool)sheet.attribute("showCommentIndicator").toInt( &ok );
07593
07594 }
07595 if( sheet.hasAttribute( "borders" ) )
07596 {
07597 d->showPageBorders = (bool)sheet.attribute("borders").toInt( &ok );
07598
07599 }
07600 if( sheet.hasAttribute( "lcmode" ) )
07601 {
07602 d->lcMode = (bool)sheet.attribute("lcmode").toInt( &ok );
07603
07604 }
07605 if ( sheet.hasAttribute( "autoCalc" ) )
07606 {
07607 d->autoCalc = ( bool )sheet.attribute( "autoCalc" ).toInt( &ok );
07608
07609 }
07610 if( sheet.hasAttribute( "columnnumber" ) )
07611 {
07612 d->showColumnNumber = (bool)sheet.attribute("columnnumber").toInt( &ok );
07613
07614 }
07615 if( sheet.hasAttribute( "hidezero" ) )
07616 {
07617 d->hideZero = (bool)sheet.attribute("hidezero").toInt( &ok );
07618
07619 }
07620 if( sheet.hasAttribute( "firstletterupper" ) )
07621 {
07622 d->firstLetterUpper = (bool)sheet.attribute("firstletterupper").toInt( &ok );
07623
07624 }
07625
07626
07627 QDomElement paper = sheet.namedItem( "paper" ).toElement();
07628 if ( !paper.isNull() )
07629 {
07630 QString format = paper.attribute( "format" );
07631 QString orientation = paper.attribute( "orientation" );
07632
07633
07634 QDomElement borders = paper.namedItem( "borders" ).toElement();
07635 if ( !borders.isNull() )
07636 {
07637 float left = borders.attribute( "left" ).toFloat();
07638 float right = borders.attribute( "right" ).toFloat();
07639 float top = borders.attribute( "top" ).toFloat();
07640 float bottom = borders.attribute( "bottom" ).toFloat();
07641 d->print->setPaperLayout( left, top, right, bottom, format, orientation );
07642 }
07643 QString hleft, hright, hcenter;
07644 QString fleft, fright, fcenter;
07645
07646 QDomElement head = paper.namedItem( "head" ).toElement();
07647 if ( !head.isNull() )
07648 {
07649 QDomElement left = head.namedItem( "left" ).toElement();
07650 if ( !left.isNull() )
07651 hleft = left.text();
07652 QDomElement center = head.namedItem( "center" ).toElement();
07653 if ( !center.isNull() )
07654 hcenter = center.text();
07655 QDomElement right = head.namedItem( "right" ).toElement();
07656 if ( !right.isNull() )
07657 hright = right.text();
07658 }
07659
07660 QDomElement foot = paper.namedItem( "foot" ).toElement();
07661 if ( !foot.isNull() )
07662 {
07663 QDomElement left = foot.namedItem( "left" ).toElement();
07664 if ( !left.isNull() )
07665 fleft = left.text();
07666 QDomElement center = foot.namedItem( "center" ).toElement();
07667 if ( !center.isNull() )
07668 fcenter = center.text();
07669 QDomElement right = foot.namedItem( "right" ).toElement();
07670 if ( !right.isNull() )
07671 fright = right.text();
07672 }
07673 d->print->setHeadFootLine( hleft, hcenter, hright, fleft, fcenter, fright);
07674 }
07675
07676
07677 QDomElement printrange = sheet.namedItem( "printrange-rect" ).toElement();
07678 if ( !printrange.isNull() )
07679 {
07680 int left = printrange.attribute( "left-rect" ).toInt();
07681 int right = printrange.attribute( "right-rect" ).toInt();
07682 int bottom = printrange.attribute( "bottom-rect" ).toInt();
07683 int top = printrange.attribute( "top-rect" ).toInt();
07684 if ( left == 0 )
07685 {
07686 left = 1;
07687 right = KS_colMax;
07688 }
07689 if ( top == 0 )
07690 {
07691 top = 1;
07692 bottom = KS_rowMax;
07693 }
07694 d->print->setPrintRange( QRect( QPoint( left, top ), QPoint( right, bottom ) ) );
07695 }
07696
07697
07698 if( sheet.hasAttribute( "printZoom" ) )
07699 {
07700 double zoom = sheet.attribute( "printZoom" ).toDouble( &ok );
07701 if ( ok )
07702 {
07703 d->print->setZoom( zoom );
07704 }
07705 }
07706
07707
07708 if( sheet.hasAttribute( "printPageLimitX" ) )
07709 {
07710 int pageLimit = sheet.attribute( "printPageLimitX" ).toInt( &ok );
07711 if ( ok )
07712 {
07713 d->print->setPageLimitX( pageLimit );
07714 }
07715 }
07716
07717
07718 if( sheet.hasAttribute( "printPageLimitY" ) )
07719 {
07720 int pageLimit = sheet.attribute( "printPageLimitY" ).toInt( &ok );
07721 if ( ok )
07722 {
07723 d->print->setPageLimitY( pageLimit );
07724 }
07725 }
07726
07727
07728 QDomNode n = sheet.firstChild();
07729 while( !n.isNull() )
07730 {
07731 QDomElement e = n.toElement();
07732 if ( !e.isNull() )
07733 {
07734 QString tagName=e.tagName();
07735 if ( tagName == "cell" )
07736 {
07737 Cell *cell = new Cell( this, 0, 0 );
07738 if ( cell->load( e, 0, 0 ) )
07739 insertCell( cell );
07740 else
07741 delete cell;
07742 }
07743 else if ( tagName == "row" )
07744 {
07745 RowFormat *rl = new RowFormat( this, 0 );
07746 if ( rl->load( e ) )
07747 insertRowFormat( rl );
07748 else
07749 delete rl;
07750 }
07751 else if ( tagName == "column" )
07752 {
07753 ColumnFormat *cl = new ColumnFormat( this, 0 );
07754 if ( cl->load( e ) )
07755 insertColumnFormat( cl );
07756 else
07757 delete cl;
07758 }
07759 else if ( tagName == "object" )
07760 {
07761 EmbeddedKOfficeObject *ch = new EmbeddedKOfficeObject( doc(), this );
07762 if ( ch->load( e ) )
07763 insertObject( ch );
07764 else
07765 {
07766 ch->embeddedObject()->setDeleted(true);
07767 delete ch;
07768 }
07769 }
07770 else if ( tagName == "chart" )
07771 {
07772 EmbeddedChart *ch = new EmbeddedChart( doc(), this );
07773 if ( ch->load( e ) )
07774 insertObject( ch );
07775 else
07776 {
07777 ch->embeddedObject()->setDeleted(true);
07778 delete ch;
07779 }
07780 }
07781 }
07782
07783 n = n.nextSibling();
07784 }
07785
07786
07787
07788 QDomElement printrepeatcolumns = sheet.namedItem( "printrepeatcolumns" ).toElement();
07789 if ( !printrepeatcolumns.isNull() )
07790 {
07791 int left = printrepeatcolumns.attribute( "left" ).toInt();
07792 int right = printrepeatcolumns.attribute( "right" ).toInt();
07793 d->print->setPrintRepeatColumns( qMakePair( left, right ) );
07794 }
07795
07796
07797 QDomElement printrepeatrows = sheet.namedItem( "printrepeatrows" ).toElement();
07798 if ( !printrepeatrows.isNull() )
07799 {
07800 int top = printrepeatrows.attribute( "top" ).toInt();
07801 int bottom = printrepeatrows.attribute( "bottom" ).toInt();
07802 d->print->setPrintRepeatRows( qMakePair( top, bottom ) );
07803 }
07804
07805 if( !sheet.hasAttribute( "borders1.2" ) )
07806 {
07807 convertObscuringBorders();
07808 }
07809
07810 if ( sheet.hasAttribute( "protected" ) )
07811 {
07812 QString passwd = sheet.attribute( "protected" );
07813
07814 if ( passwd.length() > 0 )
07815 {
07816 QCString str( passwd.latin1() );
07817 d->password = KCodecs::base64Decode( str );
07818 }
07819 else
07820 d->password = QCString( "" );
07821 }
07822
07823 return true;
07824 }
07825
07826
07827 bool Sheet::loadChildren( KoStore* _store )
07828 {
07829 QPtrListIterator<EmbeddedObject> it( doc()->embeddedObjects() );
07830 for( ; it.current(); ++it )
07831 {
07832 if ( it.current()->sheet() == this && ( it.current()->getType() == OBJECT_KOFFICE_PART || it.current()->getType() == OBJECT_CHART ) )
07833 {
07834 kdDebug() << "KSpreadSheet::loadChildren" << endl;
07835 if ( !dynamic_cast<EmbeddedKOfficeObject*>( it.current() )->embeddedObject()->loadDocument( _store ) )
07836 return false;
07837 }
07838 }
07839
07840 return true;
07841 }
07842
07843
07844 void Sheet::setShowPageBorders( bool b )
07845 {
07846 if ( b == d->showPageBorders )
07847 return;
07848
07849 d->showPageBorders = b;
07850 emit sig_updateView( this );
07851 }
07852
07853 void Sheet::addCellBinding( CellBinding *_bind )
07854 {
07855 d->cellBindings.append( _bind );
07856
07857 doc()->setModified( true );
07858 }
07859
07860 void Sheet::removeCellBinding( CellBinding *_bind )
07861 {
07862 d->cellBindings.removeRef( _bind );
07863
07864 doc()->setModified( true );
07865 }
07866
07867 Sheet* Sheet::findSheet( const QString & _name )
07868 {
07869 if ( !workbook() )
07870 return 0L;
07871
07872 return workbook()->findSheet( _name );
07873 }
07874
07875
07876 void Sheet::insertCell( Cell *_cell )
07877 {
07878
07879 d->cells.insert( _cell, _cell->column(), _cell->row() );
07880
07881 if ( d->scrollBarUpdates )
07882 {
07883 checkRangeHBorder ( _cell->column() );
07884 checkRangeVBorder ( _cell->row() );
07885 }
07886 }
07887
07888 void Sheet::insertColumnFormat( ColumnFormat *l )
07889 {
07890 d->columns.insertElement( l, l->column() );
07891 }
07892
07893 void Sheet::insertRowFormat( RowFormat *l )
07894 {
07895 d->rows.insertElement( l, l->row() );
07896 }
07897
07898 void Sheet::update()
07899 {
07900 Cell* c = d->cells.firstCell();
07901 for( ;c; c = c->nextCell() )
07902 {
07903 updateCell(c, c->column(), c->row());
07904 }
07905 }
07906
07907 void Sheet::updateCellArea(const Region& cellArea)
07908 {
07909 if ( doc()->isLoading() || doc()->delayCalculation() || (!getAutoCalc()))
07910 return;
07911
07912 setRegionPaintDirty( cellArea );
07913 }
07914
07915 void Sheet::updateCell( Cell *, int _column, int _row )
07916 {
07917 QRect cellArea(QPoint(_column, _row), QPoint(_column, _row));
07918
07919 updateCellArea(cellArea);
07920 }
07921
07922 void Sheet::emit_updateRow( RowFormat *_format, int _row, bool repaint )
07923 {
07924 if ( doc()->isLoading() )
07925 return;
07926
07927 Cell* c = d->cells.firstCell();
07928 for( ;c; c = c->nextCell() )
07929 if ( c->row() == _row )
07930 c->setLayoutDirtyFlag( true );
07931
07932 if ( repaint )
07933 {
07934
07935
07936 setRegionPaintDirty( QRect( 0 , _row , KS_colMax , KS_rowMax) );
07937
07938 emit sig_updateVBorder( this );
07939 emit sig_updateView( this );
07940 }
07941 emit sig_maxRow(maxRow());
07942 _format->clearDisplayDirtyFlag();
07943 }
07944
07945 void Sheet::emit_updateColumn( ColumnFormat *_format, int _column )
07946 {
07947 if ( doc()->isLoading() )
07948 return;
07949
07950 Cell* c = d->cells.firstCell();
07951 for( ;c; c = c->nextCell() )
07952 if ( c->column() == _column )
07953 c->setLayoutDirtyFlag( true );
07954
07955
07956
07957 setRegionPaintDirty( QRect( _column , 0 , KS_colMax , KS_rowMax) );
07958
07959 emit sig_updateHBorder( this );
07960 emit sig_updateView( this );
07961 emit sig_maxColumn( maxColumn() );
07962
07963
07964
07965 _format->clearDisplayDirtyFlag();
07966 }
07967
07968 bool Sheet::insertChart( const KoRect& _rect, KoDocumentEntry& _e, const QRect& _data )
07969 {
07970 kdDebug(36001) << "Creating document" << endl;
07971 KoDocument* dd = _e.createDoc();
07972 kdDebug(36001) << "Created" << endl;
07973 if ( !dd )
07974
07975 return false;
07976
07977 kdDebug(36001) << "NOW FETCHING INTERFACE" << endl;
07978
07979 if ( !dd->initDoc(KoDocument::InitDocEmbedded) )
07980 return false;
07981
07982 EmbeddedChart * ch = new EmbeddedChart( doc(), this, dd, _rect );
07983 ch->setDataArea( _data );
07984 ch->update();
07985 ch->chart()->setCanChangeValue( false );
07986
07987 KoChart::WizardExtension * wiz = ch->chart()->wizardExtension();
07988
07989 Range dataRange;
07990 dataRange.setRange( _data );
07991 dataRange.setSheet( this );
07992
07993 QString rangeString=dataRange.toString();
07994
07995 if ( wiz )
07996 wiz->show( rangeString );
07997
07998 insertObject( ch );
07999
08000 return true;
08001 }
08002
08003 bool Sheet::insertChild( const KoRect& _rect, KoDocumentEntry& _e )
08004 {
08005 KoDocument* d = _e.createDoc( doc() );
08006 if ( !d )
08007 {
08008 kdDebug() << "Error inserting child!" << endl;
08009 return false;
08010 }
08011 if ( !d->initDoc(KoDocument::InitDocEmbedded) )
08012 return false;
08013
08014 EmbeddedKOfficeObject* ch = new EmbeddedKOfficeObject( doc(), this, d, _rect );
08015 insertObject( ch );
08016 return true;
08017 }
08018
08019 bool Sheet::insertPicture( const KoPoint& point , const KURL& url )
08020 {
08021 KoPicture picture = doc()->pictureCollection()->downloadPicture( url , 0 );
08022
08023 return insertPicture(point,picture);
08024 }
08025
08026 bool Sheet::insertPicture( const KoPoint& point , KoPicture& picture )
08027 {
08028
08029 if (picture.isNull())
08030 return false;
08031
08032 KoPictureKey key = picture.getKey();
08033
08034 KoRect destinationRect;
08035 destinationRect.setLeft( point.x() );
08036 destinationRect.setTop( point.y() );
08037
08038
08039
08040
08041
08042
08043
08044
08045
08046
08047
08048 KoSize destinationSize;
08049
08050 double inchWidth = (double)picture.getOriginalSize().width() / KoGlobal::dpiX();
08051 double inchHeight = (double)picture.getOriginalSize().height() / KoGlobal::dpiY();
08052
08053 destinationSize.setWidth( KoUnit::fromUserValue(inchWidth,KoUnit::U_INCH) );
08054 destinationSize.setHeight( KoUnit::fromUserValue(inchHeight,KoUnit::U_INCH) );
08055
08056 destinationRect.setSize( destinationSize);
08057
08058 EmbeddedPictureObject* object = new EmbeddedPictureObject( this, destinationRect, doc()->pictureCollection(),key);
08059
08060
08061 insertObject( object );
08062 return true;
08063 }
08064
08065 bool Sheet::insertPicture( const KoPoint& point, const QPixmap& pixmap )
08066 {
08067 QByteArray data;
08068 QBuffer buffer(data);
08069
08070 buffer.open( IO_ReadWrite );
08071 pixmap.save( &buffer , "PNG" );
08072
08073
08074
08075 buffer.reset();
08076
08077 KoPicture picture;
08078 picture.load( &buffer , "PNG" );
08079
08080 doc()->pictureCollection()->insertPicture(picture);
08081
08082 return insertPicture( point , picture );
08083 }
08084
08085 void Sheet::insertObject( EmbeddedObject *_obj )
08086 {
08087 doc()->insertObject( _obj );
08088 emit sig_updateView( _obj );
08089 }
08090
08091 void Sheet::changeChildGeometry( EmbeddedKOfficeObject *_child, const KoRect& _rect )
08092 {
08093 _child->setGeometry( _rect );
08094
08095 emit sig_updateChildGeometry( _child );
08096 }
08097
08098 bool Sheet::saveChildren( KoStore* _store, const QString &_path )
08099 {
08100 int i = 0;
08101
08102 QPtrListIterator<EmbeddedObject> it( doc()->embeddedObjects() );
08103 for( ; it.current(); ++it )
08104 {
08105 if ( it.current()->sheet() == this && ( it.current()->getType() == OBJECT_KOFFICE_PART || it.current()->getType() == OBJECT_CHART ) )
08106 {
08107 QString path = QString( "%1/%2" ).arg( _path ).arg( i++ );
08108 if ( !dynamic_cast<EmbeddedKOfficeObject*>( it.current() )->embeddedObject()->document()->saveToStore( _store, path ) )
08109 return false;
08110 }
08111 }
08112 return true;
08113 }
08114
08115 bool Sheet::saveOasisObjects( KoStore *, KoXmlWriter &xmlWriter, KoGenStyles& mainStyles, int & indexObj, int &partIndexObj )
08116 {
08117
08118 if ( doc()->embeddedObjects().isEmpty() )
08119 return true;
08120
08121 bool objectFound = false;
08122 EmbeddedObject::KSpreadOasisSaveContext sc( xmlWriter, mainStyles, indexObj, partIndexObj );
08123 QPtrListIterator<EmbeddedObject> it( doc()->embeddedObjects() );
08124 for( ; it.current(); ++it )
08125 {
08126 if ( it.current()->sheet() == this && ( doc()->savingWholeDocument() || it.current()->isSelected() ) )
08127 {
08128 if ( !objectFound )
08129 {
08130 xmlWriter.startElement( "table:shapes" );
08131 objectFound = true;
08132 }
08133 if ( !it.current()->saveOasisObject(sc) )
08134 {
08135 xmlWriter.endElement();
08136 return false;
08137 }
08138 ++indexObj;
08139 }
08140 }
08141 if ( objectFound )
08142 {
08143 xmlWriter.endElement();
08144 }
08145 return true;
08146 }
08147
08148 Sheet::~Sheet()
08149 {
08150
08151
08152
08153
08154
08155
08156 setAutoCalc(false);
08157
08158 s_mapSheets->remove( d->id );
08159
08160
08161
08162
08163 if( s_mapSheets->count()==0)
08164 s_id=0L;
08165
08166 Cell* c = d->cells.firstCell();
08167 for( ; c; c = c->nextCell() )
08168 c->sheetDies();
08169
08170 d->cells.clear();
08171
08172 d->painter->end();
08173 delete d->painter;
08174 delete d->widget;
08175
08176 delete d->defaultFormat;
08177 delete d->defaultCell;
08178 delete d->defaultRowFormat;
08179 delete d->defaultColumnFormat;
08180 delete d->print;
08181 delete d->dcop;
08182
08183 delete d->dependencies;
08184
08185 delete d;
08186
08187
08188 d=0;
08189 }
08190
08191 void Sheet::checkRangeHBorder ( int _column )
08192 {
08193 if ( d->scrollBarUpdates && _column > d->maxColumn )
08194 {
08195 d->maxColumn = _column;
08196 emit sig_maxColumn( _column );
08197 }
08198 }
08199
08200 void Sheet::checkRangeVBorder ( int _row )
08201 {
08202 if ( d->scrollBarUpdates && _row > d->maxRow )
08203 {
08204 d->maxRow = _row;
08205 emit sig_maxRow( _row );
08206 }
08207 }
08208
08209
08210 void Sheet::enableScrollBarUpdates( bool _enable )
08211 {
08212 d->scrollBarUpdates = _enable;
08213 }
08214
08215 DCOPObject* Sheet::dcopObject()
08216 {
08217 if ( !d->dcop )
08218 d->dcop = new SheetIface( this );
08219
08220 return d->dcop;
08221 }
08222
08223 void Sheet::hideSheet(bool _hide)
08224 {
08225 setHidden(_hide);
08226 if(_hide)
08227 emit sig_SheetHidden(this);
08228 else
08229 emit sig_SheetShown(this);
08230 }
08231
08232 void Sheet::removeSheet()
08233 {
08234 emit sig_SheetRemoved(this);
08235 }
08236
08237 bool Sheet::setSheetName( const QString& name, bool init, bool )
08238 {
08239 if ( workbook()->findSheet( name ) )
08240 return false;
08241
08242 if ( isProtected() )
08243 return false;
08244
08245 if ( d->name == name )
08246 return true;
08247
08248 QString old_name = d->name;
08249 d->name = name;
08250
08251 if ( init )
08252 return true;
08253
08254 QPtrListIterator<Sheet> it( workbook()->sheetList() );
08255 for ( ; it.current(); ++it )
08256 it.current()->changeCellTabName( old_name, name );
08257
08258 doc()->changeAreaSheetName( old_name, name );
08259 emit sig_nameChanged( this, old_name );
08260
08261 setName(name.utf8());
08262 (dynamic_cast<SheetIface*>(dcopObject()))->sheetNameHasChanged();
08263
08264 return true;
08265 }
08266
08267
08268 void Sheet::updateLocale()
08269 {
08270 doc()->emitBeginOperation(true);
08271 setRegionPaintDirty(QRect(QPoint(1,1), QPoint(KS_colMax, KS_rowMax)));
08272
08273 Cell* c = d->cells.firstCell();
08274 for( ;c; c = c->nextCell() )
08275 {
08276 QString _text = c->text();
08277 c->setCellText( _text );
08278 }
08279 emit sig_updateView( this );
08280
08281 }
08282
08283 Cell* Sheet::getFirstCellColumn(int col) const
08284 { return d->cells.getFirstCellColumn(col); }
08285
08286 Cell* Sheet::getLastCellColumn(int col) const
08287 { return d->cells.getLastCellColumn(col); }
08288
08289 Cell* Sheet::getFirstCellRow(int row) const
08290 { return d->cells.getFirstCellRow(row); }
08291
08292 Cell* Sheet::getLastCellRow(int row) const
08293 { return d->cells.getLastCellRow(row); }
08294
08295 Cell* Sheet::getNextCellUp(int col, int row) const
08296 { return d->cells.getNextCellUp(col, row); }
08297
08298 Cell* Sheet::getNextCellDown(int col, int row) const
08299 { return d->cells.getNextCellDown(col, row); }
08300
08301 Cell* Sheet::getNextCellLeft(int col, int row) const
08302 { return d->cells.getNextCellLeft(col, row); }
08303
08304 Cell* Sheet::getNextCellRight(int col, int row) const
08305 { return d->cells.getNextCellRight(col, row); }
08306
08307 void Sheet::convertObscuringBorders()
08308 {
08309
08310
08311
08312
08313
08314
08315
08316
08317
08318
08319
08320
08321
08322 Cell* c = d->cells.firstCell();
08323 QPen topPen, bottomPen, leftPen, rightPen;
08324 for( ;c; c = c->nextCell() )
08325 {
08326 if (c->extraXCells() > 0 || c->extraYCells() > 0)
08327 {
08328 topPen = c->topBorderPen(c->column(), c->row());
08329 leftPen = c->leftBorderPen(c->column(), c->row());
08330 rightPen = c->rightBorderPen(c->column(), c->row());
08331 bottomPen = c->bottomBorderPen(c->column(), c->row());
08332
08333 c->format()->setTopBorderStyle(Qt::NoPen);
08334 c->format()->setLeftBorderStyle(Qt::NoPen);
08335 c->format()->setRightBorderStyle(Qt::NoPen);
08336 c->format()->setBottomBorderStyle(Qt::NoPen);
08337
08338 for (int x = c->column(); x < c->column() + c->extraXCells(); x++)
08339 {
08340 nonDefaultCell( x, c->row() )->setTopBorderPen(topPen);
08341 nonDefaultCell( x, c->row() + c->extraYCells() )->
08342 setBottomBorderPen(bottomPen);
08343 }
08344 for (int y = c->row(); y < c->row() + c->extraYCells(); y++)
08345 {
08346 nonDefaultCell( c->column(), y )->setLeftBorderPen(leftPen);
08347 nonDefaultCell( c->column() + c->extraXCells(), y )->
08348 setRightBorderPen(rightPen);
08349 }
08350 }
08351 }
08352 }
08353
08354
08355
08356
08357
08358
08359 void Sheet::setRegionPaintDirty( Region const & region )
08360 {
08361 Manipulator* manipulator = new DilationManipulator();
08362 manipulator->setSheet(this);
08363 manipulator->add(region);
08364 manipulator->execute();
08365
08366 d->paintDirtyList.add(*manipulator);
08367 kdDebug() << "setRegionPaintDirty "<< static_cast<Region*>(manipulator)->name(this) << endl;
08368 delete manipulator;
08369 }
08370
08371 void Sheet::setRegionPaintDirty( QRect const & range )
08372 {
08373
08374 d->paintDirtyList.add(range);
08375
08376 }
08377
08378 void Sheet::clearPaintDirtyData()
08379 {
08380 d->paintDirtyList.clear();
08381 }
08382
08383 bool Sheet::cellIsPaintDirty( QPoint const & cell ) const
08384 {
08385 return d->paintDirtyList.contains(cell);
08386 }
08387
08388 #ifndef NDEBUG
08389 void Sheet::printDebug()
08390 {
08391 int iMaxColumn = maxColumn();
08392 int iMaxRow = maxRow();
08393
08394 kdDebug(36001) << "Cell | Content | DataT | Text" << endl;
08395 Cell *cell;
08396 for ( int currentrow = 1 ; currentrow < iMaxRow ; ++currentrow )
08397 {
08398 for ( int currentcolumn = 1 ; currentcolumn < iMaxColumn ; currentcolumn++ )
08399 {
08400 cell = cellAt( currentcolumn, currentrow );
08401 if ( !cell->isDefault() && !cell->isEmpty() )
08402 {
08403 QString cellDescr = Cell::name( currentcolumn, currentrow );
08404 cellDescr = cellDescr.rightJustify( 4,' ' );
08405
08406
08407
08408 cellDescr += " | ";
08409 cellDescr += cell->value().type();
08410 cellDescr += " | ";
08411 cellDescr += cell->text();
08412 if ( cell->isFormula() )
08413 cellDescr += QString(" [result: %1]").arg( cell->value().asString() );
08414 kdDebug(36001) << cellDescr << endl;
08415 }
08416 }
08417 }
08418 }
08419 #endif
08420
08421 }
08422