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