00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040 #include <stdlib.h>
00041 #include <ctype.h>
00042 #include <float.h>
00043 #include <math.h>
00044
00045 #include <qapplication.h>
00046 #include <qregexp.h>
00047 #include <qpopupmenu.h>
00048 #include <koStyleStack.h>
00049
00050 #include "kspread_canvas.h"
00051 #include "kspread_doc.h"
00052 #include "kspread_format.h"
00053 #include "kspread_global.h"
00054 #include "kspread_map.h"
00055 #include "kspread_sheetprint.h"
00056 #include "kspread_style.h"
00057 #include "kspread_style_manager.h"
00058 #include "kspread_util.h"
00059 #include "ksploadinginfo.h"
00060 #include "kspread_genvalidationstyle.h"
00061 #include "kspread_interpreter.h"
00062 #include "kspread_locale.h"
00063 #include "kspread_view.h"
00064 #include "kspread_value.h"
00065 #include "valueformatter.h"
00066 #include "valueparser.h"
00067
00068 #include <koxmlns.h>
00069 #include <kodom.h>
00070 #include <koxmlwriter.h>
00071
00072 #include <kmessagebox.h>
00073
00074 #include <kdebug.h>
00075
00076 #define BORDER_SPACE 1
00077
00078
00083 namespace KSpreadCell_LNS
00084 {
00085 QChar decimal_point = '\0';
00086 }
00087
00088 using namespace KSpreadCell_LNS;
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100 class CellExtra
00101 {
00102 public:
00103
00104
00105 QString link;
00106
00107
00108 int mergedXCells;
00109 int mergedYCells;
00110
00111
00112 int extraXCells;
00113 int extraYCells;
00114
00115
00116
00117
00118 double extraWidth;
00119 double extraHeight;
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129 QValueList<KSpreadCell*> obscuringCells;
00130
00131
00132 KSpreadConditions *conditions;
00133 KSpreadValidity *validity;
00134
00135
00136 int nbLines;
00137
00138 private:
00139
00140 CellExtra& operator=( const CellExtra& );
00141 };
00142
00143
00144 class CellPrivate
00145 {
00146 public:
00147
00148 CellPrivate();
00149 ~CellPrivate();
00150
00151 public:
00152
00153
00154
00155
00156 int row;
00157 int column;
00158
00159
00160 KSpreadValue value;
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182 QString strText;
00183
00184
00185
00186
00187
00188 QString strOutText;
00189
00190
00191 KSParseNode *code;
00192
00193
00194
00195 double textX;
00196 double textY;
00197 double textWidth;
00198 double textHeight;
00199
00200
00201 int fmAscent;
00202
00203
00204
00205 KSpreadCell *nextCell;
00206 KSpreadCell *previousCell;
00207
00208 bool hasExtra() const { return (cellExtra != 0); };
00209 CellExtra *extra();
00210
00211 private:
00212
00213 CellExtra *cellExtra;
00214 };
00215
00216
00217 CellPrivate::CellPrivate()
00218 {
00219
00220 row = 0;
00221 column = 0;
00222 value = KSpreadValue::empty();
00223 code = 0;
00224
00225
00226 textX = 0.0;
00227 textY = 0.0;
00228 textWidth = 0.0;
00229 textHeight = 0.0;
00230 fmAscent = 0;
00231
00232 nextCell = 0;
00233 previousCell = 0;
00234
00235
00236 cellExtra = 0;
00237 }
00238
00239
00240 CellPrivate::~CellPrivate()
00241 {
00242 delete cellExtra;
00243 }
00244
00245
00246 CellExtra* CellPrivate::extra()
00247 {
00248 if ( !cellExtra ) {
00249 cellExtra = new CellExtra;
00250 cellExtra->conditions = 0;
00251 cellExtra->validity = 0;
00252
00253 cellExtra->mergedXCells = 0;
00254 cellExtra->mergedYCells = 0;
00255 cellExtra->extraXCells = 0;
00256 cellExtra->extraYCells = 0;
00257 cellExtra->extraWidth = 0.0;
00258 cellExtra->extraHeight = 0.0;
00259 cellExtra->nbLines = 0;
00260 }
00261
00262 return cellExtra;
00263 }
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273 KSpreadCell::KSpreadCell( KSpreadSheet * _sheet, int _column, int _row )
00274 : KSpreadFormat (_sheet, _sheet->doc()->styleManager()->defaultStyle())
00275 {
00276 d = new CellPrivate;
00277 d->row = _row;
00278 d->column = _column;
00279 clearAllErrors();
00280 }
00281
00282
00283 KSpreadCell::KSpreadCell( KSpreadSheet * _sheet,
00284 KSpreadStyle * _style, int _column, int _row )
00285 : KSpreadFormat( _sheet, _style )
00286 {
00287 d = new CellPrivate;
00288 d->row = _row;
00289 d->column = _column;
00290 clearAllErrors();
00291 }
00292
00293
00294 KSpreadSheet * KSpreadCell::sheet() const
00295 {
00296 return m_pSheet;
00297 }
00298
00299
00300 bool KSpreadCell::isDefault() const
00301 {
00302 return ( d->column == 0 );
00303 }
00304
00305
00306 int KSpreadCell::row() const
00307 {
00308
00309
00310
00311
00312 if ( isDefault() )
00313 {
00314 kdWarning(36001) << "Error: Calling KSpreadCell::row() for default cell" << endl;
00315 return 0;
00316 }
00317
00318 return d->row;
00319 }
00320
00321
00322
00323
00324 int KSpreadCell::column() const
00325 {
00326
00327
00328
00329 if ( isDefault() )
00330 {
00331 kdWarning(36001) << "Error: Calling KSpreadCell::column() for default cell" << endl;
00332 return 0;
00333 }
00334 return d->column;
00335 }
00336
00337
00338
00339
00340
00341 QString KSpreadCell::name() const
00342 {
00343 return name( d->column, d->row );
00344 }
00345
00346
00347
00348
00349 QString KSpreadCell::name( int col, int row )
00350 {
00351 return columnName( col ) + QString::number( row );
00352 }
00353
00354
00355
00356
00357
00358 QString KSpreadCell::fullName() const
00359 {
00360 return fullName( sheet(), d->column, d->row );
00361 }
00362
00363
00364
00365
00366 QString KSpreadCell::fullName( const KSpreadSheet* s, int col, int row )
00367 {
00368 return s->sheetName() + "!" + name( col, row );
00369 }
00370
00371
00372
00373
00374 QString KSpreadCell::columnName() const
00375 {
00376 return columnName( d->column );
00377 }
00378
00379 KLocale* KSpreadCell::locale()
00380 {
00381 return m_pSheet->doc()->locale();
00382 }
00383
00384
00385
00386 QString KSpreadCell::columnName( uint column )
00387 {
00388 QString str;
00389 unsigned digits = 1;
00390 unsigned offset = 0;
00391
00392 column--;
00393
00394 if( column > 4058115285U ) return QString("@@@");
00395
00396 for( unsigned limit = 26; column >= limit+offset; limit *= 26, digits++ )
00397 offset += limit;
00398
00399 for( unsigned c = column - offset; digits; --digits, c/=26 )
00400 str.prepend( QChar( 'A' + (c%26) ) );
00401
00402 return str;
00403 }
00404
00405
00406
00407
00408 bool KSpreadCell::isFormula() const
00409 {
00410 return d->strText[0] == '=';
00411 }
00412
00413
00414
00415
00416
00417
00418
00419
00420 QString KSpreadCell::text() const
00421 {
00422 return d->strText;
00423 }
00424
00425
00426
00427
00428
00429
00430 QString KSpreadCell::strOutText() const
00431 {
00432 return d->strOutText;
00433 }
00434
00435
00436
00437
00438 const KSpreadValue KSpreadCell::value() const
00439 {
00440 return d->value;
00441 }
00442
00443
00444
00445
00446
00447
00448
00449
00450 void KSpreadCell::setValue( const KSpreadValue& v )
00451 {
00452 if (v.type() != KSpreadValue::Error)
00453 clearAllErrors();
00454
00455 d->value = v;
00456
00457 setFlag(Flag_LayoutDirty);
00458 setFlag(Flag_TextFormatDirty);
00459
00460
00461 setOutputText();
00462
00463
00464 if (d->value.type() == KSpreadValue::Error)
00465 d->strOutText = d->value.errorMessage ();
00466
00467
00468 valueChanged ();
00469
00470 m_pSheet->setRegionPaintDirty(cellRect());
00471 }
00472
00473
00474
00475
00476 KSpreadCell* KSpreadCell::previousCell() const
00477 {
00478 return d->previousCell;
00479 }
00480
00481 KSpreadCell* KSpreadCell::nextCell() const
00482 {
00483 return d->nextCell;
00484 }
00485
00486 void KSpreadCell::setPreviousCell( KSpreadCell* c )
00487 {
00488 d->previousCell = c;
00489 }
00490
00491 void KSpreadCell::setNextCell( KSpreadCell* c )
00492 {
00493 d->nextCell = c;
00494 }
00495
00496 KSpreadValidity* KSpreadCell::getValidity( int newStruct )
00497 {
00498 if ( (!newStruct) && (!d->hasExtra()))
00499
00500 return 0;
00501
00502 if( ( d->extra()->validity == 0 ) && ( newStruct == -1 ) )
00503 d->extra()->validity = new KSpreadValidity;
00504 return d->extra()->validity;
00505 }
00506
00507 void KSpreadCell::removeValidity()
00508 {
00509 if (!d->hasExtra())
00510 return;
00511
00512 delete d->extra()->validity;
00513 d->extra()->validity = 0;
00514 }
00515
00516
00517 void KSpreadCell::copyFormat( KSpreadCell * _cell )
00518 {
00519 copyFormat( _cell->column(), _cell->row() );
00520 }
00521
00522 void KSpreadCell::copyFormat( int _column, int _row )
00523 {
00524 const KSpreadCell * cell = m_pSheet->cellAt( _column, _row );
00525
00526 setAlign( cell->align( _column, _row ) );
00527 setAlignY( cell->alignY( _column, _row ) );
00528 setTextFont( cell->textFont( _column, _row ) );
00529 setTextColor( cell->textColor( _column, _row ) );
00530 setBgColor( cell->bgColor( _column, _row) );
00531 setLeftBorderPen( cell->leftBorderPen( _column, _row ) );
00532 setTopBorderPen( cell->topBorderPen( _column, _row ) );
00533 setBottomBorderPen( cell->bottomBorderPen( _column, _row ) );
00534 setRightBorderPen( cell->rightBorderPen( _column, _row ) );
00535 setFallDiagonalPen( cell->fallDiagonalPen( _column, _row ) );
00536 setGoUpDiagonalPen( cell->goUpDiagonalPen( _column, _row ) );
00537 setBackGroundBrush( cell->backGroundBrush( _column, _row) );
00538 setPrecision( cell->precision( _column, _row ) );
00539 setPrefix( cell->prefix( _column, _row ) );
00540 setPostfix( cell->postfix( _column, _row ) );
00541 setFloatFormat( cell->floatFormat( _column, _row ) );
00542 setFloatColor( cell->floatColor( _column, _row ) );
00543 setMultiRow( cell->multiRow( _column, _row ) );
00544 setVerticalText( cell->verticalText( _column, _row ) );
00545 setDontPrintText( cell->getDontprintText(_column, _row ) );
00546 setNotProtected( cell->notProtected(_column, _row ) );
00547 setHideAll(cell->isHideAll(_column, _row ) );
00548 setHideFormula(cell->isHideFormula(_column, _row ) );
00549 setIndent( cell->getIndent(_column, _row ) );
00550 setAngle( cell->getAngle(_column, _row) );
00551 setFormatType( cell->getFormatType(_column, _row) );
00552 Currency c;
00553 if ( cell->currencyInfo( c ) )
00554 KSpreadFormat::setCurrency( c );
00555
00556 QValueList<KSpreadConditional> conditionList = cell->conditionList();
00557 if (d->hasExtra())
00558 delete d->extra()->conditions;
00559 if ( cell->d->hasExtra() && cell->d->extra()->conditions )
00560 setConditionList( conditionList );
00561 else
00562 if (d->hasExtra())
00563 d->extra()->conditions = 0;
00564
00565 setComment( cell->comment( _column, _row ) );
00566 }
00567
00568 void KSpreadCell::copyAll( KSpreadCell *cell )
00569 {
00570 Q_ASSERT( !isDefault() );
00571 copyFormat( cell );
00572 copyContent( cell );
00573 }
00574
00575 void KSpreadCell::copyContent( KSpreadCell* cell )
00576 {
00577 Q_ASSERT( !isDefault() );
00578
00579 if (cell->isFormula() && cell->column() > 0 && cell->row() > 0)
00580 {
00581
00582
00583 QString d = cell->encodeFormula();
00584 setCellText( cell->decodeFormula( d ) );
00585 }
00586 else
00587 setCellText( cell->text() );
00588
00589 }
00590
00591 void KSpreadCell::defaultStyle()
00592 {
00593 defaultStyleFormat();
00594
00595 if (!d->hasExtra())
00596 return;
00597
00598 if ( d->extra()->conditions )
00599 {
00600 delete d->extra()->conditions;
00601 d->extra()->conditions = 0;
00602 }
00603
00604 delete d->extra()->validity;
00605 d->extra()->validity = 0L;
00606 }
00607
00608 void KSpreadCell::formatChanged()
00609 {
00610 setFlag( Flag_LayoutDirty );
00611 setFlag( Flag_TextFormatDirty );
00612 }
00613
00614 KSpreadFormat * KSpreadCell::fallbackFormat( int, int row )
00615 {
00616 return sheet()->rowFormat( row );
00617 }
00618
00619 const KSpreadFormat * KSpreadCell::fallbackFormat( int, int row ) const
00620 {
00621 return sheet()->rowFormat( row );
00622 }
00623
00624
00625
00626
00627 void KSpreadCell::forceExtraCells( int _col, int _row, int _x, int _y )
00628 {
00629
00630 int extraXCells = d->hasExtra() ? d->extra()->extraXCells : 0;
00631 int extraYCells = d->hasExtra() ? d->extra()->extraYCells : 0;
00632 for ( int x = _col; x <= _col + extraXCells; ++x )
00633 for ( int y = _row; y <= _row + extraYCells; ++y ) {
00634 if ( x != _col || y != _row )
00635 m_pSheet->nonDefaultCell( x, y )->unobscure(this);
00636 }
00637
00638
00639 if ( _x == 0 && _y == 0 ) {
00640 clearFlag( Flag_ForceExtra );
00641 if (d->hasExtra()) {
00642 d->extra()->extraXCells = 0;
00643 d->extra()->extraYCells = 0;
00644 d->extra()->extraWidth = 0.0;
00645 d->extra()->extraHeight = 0.0;
00646 d->extra()->mergedXCells = 0;
00647 d->extra()->mergedYCells = 0;
00648 }
00649
00650
00651 setFlag( Flag_LayoutDirty );
00652 return;
00653 }
00654
00655
00656 setFlag(Flag_ForceExtra);
00657 d->extra()->extraXCells = _x;
00658 d->extra()->extraYCells = _y;
00659 d->extra()->mergedXCells = _x;
00660 d->extra()->mergedYCells = _y;
00661
00662
00663 for ( int x = _col; x <= _col + _x; ++x )
00664 for ( int y = _row; y <= _row + _y; ++y ) {
00665 if ( x != _col || y != _row )
00666 m_pSheet->nonDefaultCell( x, y )->obscure( this, true );
00667 }
00668
00669
00670 setFlag( Flag_LayoutDirty );
00671 }
00672
00673 void KSpreadCell::move( int col, int row )
00674 {
00675 setLayoutDirtyFlag();
00676 setCalcDirtyFlag();
00677 setDisplayDirtyFlag();
00678
00679
00680
00681
00682 if (d->hasExtra())
00683 d->extra()->obscuringCells.clear();
00684
00685
00686 int extraXCells = d->hasExtra() ? d->extra()->extraXCells : 0;
00687 int extraYCells = d->hasExtra() ? d->extra()->extraYCells : 0;
00688 for( int x = d->column; x <= d->column + extraXCells; ++x )
00689 for( int y = d->row; y <= d->row + extraYCells; ++y )
00690 if ( x != d->column || y != d->row )
00691 {
00692 KSpreadCell *cell = m_pSheet->nonDefaultCell( x, y );
00693 cell->unobscure(this);
00694 }
00695
00696 d->column = col;
00697 d->row = row;
00698
00699 if (d->hasExtra())
00700 {
00701
00702
00703 d->extra()->mergedXCells = 0;
00704 d->extra()->mergedYCells = 0;
00705 }
00706
00707
00708 valueChanged ();
00709
00710
00711
00712
00713 }
00714
00715 void KSpreadCell::setLayoutDirtyFlag( bool format )
00716 {
00717 setFlag( Flag_LayoutDirty );
00718 if ( format )
00719 setFlag( Flag_TextFormatDirty );
00720
00721 if (!d->hasExtra())
00722 return;
00723
00724 QValueList<KSpreadCell*>::iterator it = d->extra()->obscuringCells.begin();
00725 QValueList<KSpreadCell*>::iterator end = d->extra()->obscuringCells.end();
00726 for ( ; it != end; ++it )
00727 {
00728 (*it)->setLayoutDirtyFlag( format );
00729 }
00730 }
00731
00732 bool KSpreadCell::needsPrinting() const
00733 {
00734 if ( isDefault() )
00735 return FALSE;
00736
00737 if ( !d->strText.isEmpty() ) {
00738
00739 return TRUE;
00740 }
00741
00742
00743 if ( hasProperty( PTopBorder ) || hasProperty( PLeftBorder ) ||
00744 hasProperty( PRightBorder ) || hasProperty( PBottomBorder ) ||
00745 hasProperty( PFallDiagonal ) || hasProperty( PGoUpDiagonal ) ) {
00746
00747
00748 return TRUE;
00749 }
00750
00751
00752 if ( hasProperty( PBackgroundBrush ) ) {
00753
00754
00755 return TRUE;
00756 }
00757
00758 if ( hasProperty( PBackgroundColor ) ) {
00759
00760
00761
00762 return TRUE;
00763 }
00764
00765 return FALSE;
00766 }
00767
00768 bool KSpreadCell::isEmpty() const
00769 {
00770 return isDefault() || d->strText.isEmpty();
00771 }
00772
00773
00774
00775
00776 bool KSpreadCell::isObscured() const
00777 {
00778 if (!d->hasExtra())
00779 return false;
00780
00781 return !( d->extra()->obscuringCells.isEmpty() );
00782 }
00783
00784
00785
00786
00787
00788
00789
00790 bool KSpreadCell::isObscuringForced() const
00791 {
00792 if (!d->hasExtra())
00793 return false;
00794
00795 QValueList<KSpreadCell*>::const_iterator it = d->extra()->obscuringCells.begin();
00796 QValueList<KSpreadCell*>::const_iterator end = d->extra()->obscuringCells.end();
00797 for ( ; it != end; ++it ) {
00798 KSpreadCell *cell = *it;
00799
00800 if (cell->isForceExtraCells()) {
00801
00802
00803
00804
00805 if (column() <= cell->column() + cell->d->extra()->mergedXCells
00806 && row() <= cell->row() + cell->mergedYCells() )
00807 return true;
00808 }
00809 }
00810
00811 return false;
00812 }
00813
00814
00815
00816
00817
00818
00819
00820
00821
00822
00823 KSpreadCell *KSpreadCell::ultimateObscuringCell() const
00824 {
00825 if (!d->hasExtra())
00826 return (KSpreadCell *) this;
00827
00828 else if (d->extra()->obscuringCells.isEmpty())
00829 return (KSpreadCell *) this;
00830
00831 else
00832 return d->extra()->obscuringCells.first();
00833
00834 #if 0
00835 QValueList<KSpreadCell*>::const_iterator it = d->extra()->obscuringCells.begin();
00836 QValueList<KSpreadCell*>::const_iterator end = d->extra()->obscuringCells.end();
00837 for ( ; it != end; ++it ) {
00838 KSpreadCell *cell = *it;
00839
00840 if (cell->isForceExtraCells()) {
00841
00842
00843
00844
00845 if (column() <= cell->column() + cell->d->extra()->mergedXCells
00846 && row() <= cell->row() + cell->mergedYCells() )
00847 return true;
00848 }
00849 }
00850
00851 return false;
00852 #endif
00853 }
00854
00855
00856 QValueList<KSpreadCell*> KSpreadCell::obscuringCells() const
00857 {
00858 if (!d->hasExtra())
00859 {
00860 QValueList<KSpreadCell*> empty;
00861 return empty;
00862 }
00863 return d->extra()->obscuringCells;
00864 }
00865
00866 void KSpreadCell::clearObscuringCells()
00867 {
00868 if (!d->hasExtra())
00869 return;
00870 d->extra()->obscuringCells.clear();
00871 }
00872
00873 void KSpreadCell::obscure( KSpreadCell *cell, bool isForcing )
00874 {
00875 if (d->hasExtra())
00876 {
00877 d->extra()->obscuringCells.remove( cell );
00878 cell->clearObscuringCells();
00879 }
00880 if ( isForcing )
00881 {
00882 d->extra()->obscuringCells.prepend( cell );
00883 }
00884 else
00885 {
00886 d->extra()->obscuringCells.append( cell );
00887 }
00888 setFlag(Flag_LayoutDirty);
00889 m_pSheet->setRegionPaintDirty( cellRect() );
00890 }
00891
00892 void KSpreadCell::unobscure( KSpreadCell * cell )
00893 {
00894 if (d->hasExtra())
00895 d->extra()->obscuringCells.remove( cell );
00896 setFlag( Flag_LayoutDirty );
00897 m_pSheet->setRegionPaintDirty( cellRect() );
00898 }
00899
00900 void KSpreadCell::clicked( KSpreadCanvas* )
00901 {
00902 return;
00903 }
00904
00905 QString KSpreadCell::encodeFormula( bool _era, int _col, int _row )
00906 {
00907 if ( _col == -1 )
00908 _col = d->column;
00909 if ( _row == -1 )
00910 _row = d->row;
00911
00912 QString erg = "";
00913
00914 if(d->strText.isEmpty())
00915 return d->strText;
00916
00917 bool fix1 = FALSE;
00918 bool fix2 = FALSE;
00919 bool onNumber = false;
00920 unsigned int pos = 0;
00921 const unsigned int length = d->strText.length();
00922
00923
00924
00925 while ( pos < length )
00926 {
00927 if ( d->strText[pos] == '"' )
00928 {
00929 erg += d->strText[pos++];
00930 while ( pos < length && d->strText[pos] != '"' )
00931 {
00932 erg += d->strText[pos++];
00933
00934 if ( pos < length && d->strText[pos] == '\\' && d->strText[pos+1] == '"' )
00935 {
00936 erg += d->strText[pos++];
00937 erg += d->strText[pos++];
00938 }
00939 }
00940 if ( pos < length )
00941 erg += d->strText[pos++];
00942
00943 onNumber = false;
00944 }
00945 else if ( d->strText[pos].isDigit() )
00946 {
00947 erg += d->strText[pos++];
00948 fix1 = fix2 = FALSE;
00949 onNumber = true;
00950 }
00951 else if ( d->strText[pos] != '$' && !d->strText[pos].isLetter() )
00952 {
00953 erg += d->strText[pos++];
00954 fix1 = fix2 = FALSE;
00955 onNumber = false;
00956 }
00957 else
00958 {
00959 QString tmp = "";
00960 if ( d->strText[pos] == '$' )
00961 {
00962 tmp = "$";
00963 pos++;
00964 fix1 = TRUE;
00965 }
00966 if ( d->strText[pos].isLetter() )
00967 {
00968 QString buffer;
00969 unsigned int pos2 = 0;
00970 while ( pos < length && d->strText[pos].isLetter() )
00971 {
00972 tmp += d->strText[pos];
00973 buffer[pos2++] = d->strText[pos++];
00974 }
00975 if ( d->strText[pos] == '$' )
00976 {
00977 tmp += "$";
00978 pos++;
00979 fix2 = TRUE;
00980 }
00981 if ( d->strText[pos].isDigit() )
00982 {
00983 const unsigned int oldPos = pos;
00984 while ( pos < length && d->strText[pos].isDigit() ) ++pos;
00985 int row = 0;
00986 if ( pos != oldPos )
00987 row = d->strText.mid(oldPos, pos-oldPos).toInt();
00988
00989
00990
00991 if ( ( d->strText[pos] == '!' ) ||
00992 d->strText[pos].isLetter() ||
00993 onNumber )
00994 {
00995 erg += tmp;
00996 fix1 = fix2 = FALSE;
00997 pos = oldPos;
00998 }
00999 else
01000 {
01001
01002 int col = 0;
01003 col = util_decodeColumnLabelText( buffer );
01004 if ( fix1 )
01005 erg += QString( "$%1" ).arg( col );
01006 else
01007 if (_era)
01008 erg += QChar(0xA7) + QString( "%1" ).arg( col );
01009 else
01010 erg += QString( "#%1" ).arg( col - _col );
01011
01012 if ( fix2 )
01013 erg += QString( "$%1#").arg( row );
01014 else
01015 if (_era)
01016 erg += QChar(0xA7) + QString( "%1#" ).arg( row );
01017 else
01018 erg += QString( "#%1#" ).arg( row - _row );
01019 }
01020 }
01021 else
01022 {
01023 erg += tmp;
01024 fix1 = fix2 = FALSE;
01025 }
01026 }
01027 else
01028 {
01029 erg += tmp;
01030 fix1 = FALSE;
01031 }
01032 onNumber = false;
01033 }
01034 }
01035
01036 return erg;
01037 }
01038
01039 QString KSpreadCell::decodeFormula( const QString &_text, int _col, int _row )
01040 {
01041 if ( _col == -1 )
01042 _col = d->column;
01043 if ( _row == -1 )
01044 _row = d->row;
01045
01046 QString erg = "";
01047 unsigned int pos = 0;
01048 const unsigned int length = _text.length();
01049
01050 if ( _text.isEmpty() )
01051 return QString();
01052
01053 while ( pos < length )
01054 {
01055 if ( _text[pos] == '"' )
01056 {
01057 erg += _text[pos++];
01058 while ( pos < length && _text[pos] != '"' )
01059 {
01060 erg += _text[pos++];
01061
01062 if ( pos < length && _text[pos] == '\\' && _text[pos+1] == '"' )
01063 {
01064 erg += _text[pos++];
01065 erg += _text[pos++];
01066 }
01067 }
01068 if ( pos < length )
01069 erg += _text[pos++];
01070 }
01071 else if ( _text[pos] == '#' || _text[pos] == '$' || _text[pos] == QChar(0xA7))
01072 {
01073 bool abs1 = FALSE;
01074 bool abs2 = FALSE;
01075 bool era1 = FALSE;
01076 bool era2 = FALSE;
01077
01078 QChar _t = _text[pos++];
01079 if ( _t == '$' )
01080 abs1 = TRUE;
01081 else if ( _t == QChar(0xA7) )
01082 era1 = TRUE;
01083
01084 int col = 0;
01085 unsigned int oldPos = pos;
01086 while ( pos < length && ( _text[pos].isDigit() || _text[pos] == '-' ) ) ++pos;
01087 if ( pos != oldPos )
01088 col = _text.mid(oldPos, pos-oldPos).toInt();
01089 if ( !abs1 && !era1 )
01090 col += _col;
01091
01092
01093 _t = _text[pos++];
01094 if ( _t == '$' )
01095 abs2 = TRUE;
01096 else if ( _t == QChar(0xA7) )
01097 era2 = TRUE;
01098
01099 int row = 0;
01100 oldPos = pos;
01101 while ( pos < length && ( _text[pos].isDigit() || _text[pos] == '-' ) ) ++pos;
01102 if ( pos != oldPos )
01103 row = _text.mid(oldPos, pos-oldPos).toInt();
01104 if ( !abs2 && !era2)
01105 row += _row;
01106
01107 ++pos;
01108 if ( row < 1 || col < 1 || row > KS_rowMax || col > KS_colMax )
01109 {
01110 kdDebug(36001) << "KSpreadCell::decodeFormula: row or column out of range (col: " << col << " | row: " << row << ")" << endl;
01111 erg = "=\"#### " + i18n("REFERENCE TO COLUMN OR ROW IS OUT OF RANGE") + "\"";
01112 return erg;
01113 }
01114 if ( abs1 )
01115 erg += "$";
01116 erg += KSpreadCell::columnName(col);
01117
01118 if ( abs2 )
01119 erg += "$";
01120 erg += QString::number( row );
01121 }
01122 else
01123 erg += _text[pos++];
01124 }
01125
01126 return erg;
01127 }
01128
01129
01130 void KSpreadCell::freeAllObscuredCells()
01131 {
01132
01133
01134
01135
01136 if (!d->hasExtra())
01137 return;
01138
01139 for ( int x = d->column + d->extra()->mergedXCells;
01140 x <= d->column + d->extra()->extraXCells; ++x ) {
01141 for ( int y = d->row + d->extra()->mergedYCells;
01142 y <= d->row + d->extra()->extraYCells; ++y ) {
01143 if ( x != d->column || y != d->row ) {
01144 KSpreadCell *cell = m_pSheet->cellAt( x, y );
01145 cell->unobscure(this);
01146 }
01147 }
01148 }
01149
01150 d->extra()->extraXCells = d->extra()->mergedXCells;
01151 d->extra()->extraYCells = d->extra()->mergedYCells;
01152
01153 }
01154
01155
01156
01157
01158
01159
01160
01161
01162
01163
01164
01165
01166
01167
01168
01169
01170
01171
01172
01173
01174 void KSpreadCell::makeLayout( QPainter &_painter, int _col, int _row )
01175 {
01176
01177
01178
01179
01180
01181
01182
01183 if ( !testFlag( Flag_LayoutDirty ) )
01184 return;
01185
01186
01187 if (d->hasExtra())
01188 d->extra()->nbLines = 0;
01189 clearFlag( Flag_CellTooShortX );
01190 clearFlag( Flag_CellTooShortY );
01191
01192
01193
01194 freeAllObscuredCells();
01195 if (d->hasExtra())
01196 forceExtraCells( d->column, d->row,
01197 d->extra()->mergedXCells, d->extra()->mergedYCells );
01198
01199
01200
01201 ColumnFormat *cl1 = m_pSheet->columnFormat( _col );
01202 RowFormat *rl1 = m_pSheet->rowFormat( _row );
01203 if ( cl1->isHide()
01204 || ( rl1->dblHeight() <= m_pSheet->doc()->unzoomItY( 2 ) ) ) {
01205 clearFlag( Flag_LayoutDirty );
01206 return;
01207 }
01208
01209
01210 setOutputText();
01211
01212
01213
01214 if ( d->strOutText.isEmpty() ) {
01215 d->strOutText = QString::null;
01216
01217 if ( isDefault() ) {
01218 clearFlag( Flag_LayoutDirty );
01219 return;
01220 }
01221 }
01222
01223
01224
01225
01226
01227
01228
01229
01230 applyZoomedFont( _painter, _col, _row );
01231 textSize( _painter );
01232
01233
01234
01235
01236 RowFormat *rl = m_pSheet->rowFormat( d->row );
01237 ColumnFormat *cl = m_pSheet->columnFormat( d->column );
01238
01239 double width = cl->dblWidth();
01240 double height = rl->dblHeight();
01241
01242
01243 if ( testFlag( Flag_ForceExtra ) ) {
01244 int extraXCells = d->hasExtra() ? d->extra()->extraXCells : 0;
01245 int extraYCells = d->hasExtra() ? d->extra()->extraYCells : 0;
01246
01247
01248
01249
01250 for ( int x = _col + 1; x <= _col + extraXCells; x++ )
01251 width += m_pSheet->columnFormat( x )->dblWidth();
01252
01253 for ( int y = _row + 1; y <= _row + extraYCells; y++ )
01254 height += m_pSheet->rowFormat( y )->dblHeight();
01255 }
01256
01257
01258
01259
01260 if (d->hasExtra()) {
01261 d->extra()->extraWidth = width;
01262 d->extra()->extraHeight = height;
01263 }
01264
01265 QFontMetrics fm = _painter.fontMetrics();
01266 d->fmAscent = fm.ascent();
01267
01268
01269
01270
01271
01272
01273
01274
01275 int lines = 1;
01276 if ( d->textWidth > (width - 2 * BORDER_SPACE
01277 - leftBorderWidth( _col, _row )
01278 - rightBorderWidth( _col, _row ) )
01279 && multiRow( _col, _row ) )
01280 {
01281
01282 QString o = d->strOutText.replace( QChar('\n'), " " );
01283
01284
01285
01286
01287 if ( o.find(' ') != -1 ) {
01288 d->strOutText = "";
01289
01290
01291 o += ' ';
01292
01293 int start = 0;
01294 int breakpos = 0;
01295 int pos1 = 0;
01296 int availableWidth = ( width - 2 * BORDER_SPACE
01297 - leftBorderWidth( _col, _row )
01298 - rightBorderWidth( _col, _row ) );
01299
01300 do {
01301 breakpos = o.find( ' ', breakpos );
01302 double lineWidth = m_pSheet->doc()
01303 ->unzoomItX( fm.width( d->strOutText.mid( start, (pos1 - start) )
01304 + o.mid( pos1, breakpos - pos1 ) ) );
01305
01306 if ( lineWidth <= availableWidth ) {
01307
01308 d->strOutText += o.mid( pos1, breakpos - pos1 );
01309 pos1 = breakpos;
01310 }
01311 else {
01312
01313 if ( o.at( pos1 ) == ' ' )
01314 pos1++;
01315
01316 if ( pos1 != 0 && breakpos != -1 ) {
01317 d->strOutText += "\n" + o.mid( pos1, breakpos - pos1 );
01318 lines++;
01319 }
01320 else
01321 d->strOutText += o.mid( pos1, breakpos - pos1 );
01322
01323 start = pos1;
01324 pos1 = breakpos;
01325 }
01326
01327 breakpos++;
01328 } while( o.find( ' ', breakpos ) != -1 );
01329 }
01330
01331 d->textHeight *= lines;
01332 if (lines > 1)
01333 d->extra()->nbLines = lines;
01334
01335 d->textX = 0.0;
01336
01337
01338
01339 QString t;
01340 int i;
01341 int pos = 0;
01342 d->textWidth = 0.0;
01343 do {
01344 i = d->strOutText.find( "\n", pos );
01345
01346 if ( i == -1 )
01347 t = d->strOutText.mid( pos, d->strOutText.length() - pos );
01348 else {
01349 t = d->strOutText.mid( pos, i - pos );
01350 pos = i + 1;
01351 }
01352
01353 double tw = m_pSheet->doc()->unzoomItX( fm.width( t ) );
01354 if ( tw > d->textWidth )
01355 d->textWidth = tw;
01356 } while ( i != -1 );
01357 }
01358
01359
01360 offsetAlign( _col, _row );
01361
01362 int a = effAlignX();
01363
01364
01365 double indent = 0.0;
01366 if ( a == KSpreadCell::Left && !isEmpty() )
01367 indent = getIndent( _col, _row );
01368
01369
01370
01371 if ( verticalText( _col, _row ) || getAngle( _col, _row ) != 0 ) {
01372 RowFormat *rl = m_pSheet->rowFormat( _row );
01373
01374 if ( d->textHeight >= rl->dblHeight() )
01375 setFlag( Flag_CellTooShortX );
01376 }
01377
01378
01379
01380
01381
01382
01383
01384 if ( d->textWidth + indent > ( width - 2 * BORDER_SPACE
01385 - leftBorderWidth( _col, _row )
01386 - rightBorderWidth( _col, _row ) )
01387 && ( !d->hasExtra() || d->extra()->mergedYCells == 0 ) )
01388 {
01389 int c = d->column;
01390
01391
01392 int end = 0;
01393 while ( !end ) {
01394 ColumnFormat *cl2 = m_pSheet->columnFormat( c + 1 );
01395 KSpreadCell *cell = m_pSheet->visibleCellAt( c + 1, d->row );
01396
01397 if ( cell->isEmpty() ) {
01398 width += cl2->dblWidth() - 1;
01399 c++;
01400
01401
01402 if ( d->textWidth + indent <= ( width - 2 * BORDER_SPACE
01403 - leftBorderWidth( _col, _row )
01404 - rightBorderWidth( _col, _row ) ) )
01405 end = 1;
01406 }
01407 else
01408
01409 end = -1;
01410 }
01411
01412
01413
01414
01415
01416
01417
01418
01419
01420
01421
01422
01423
01424 if ( align( _col, _row ) == KSpreadCell::Left
01425 || ( align( _col, _row ) == KSpreadCell::Undefined
01426 && !value().isNumber() ) )
01427 {
01428 if ( c - d->column > d->extra()->mergedXCells ) {
01429 d->extra()->extraXCells = c - d->column;
01430 d->extra()->extraWidth = width;
01431 for ( int i = d->column + 1; i <= c; ++i ) {
01432 KSpreadCell *cell = m_pSheet->nonDefaultCell( i, d->row );
01433 cell->obscure( this );
01434 }
01435
01436
01437 if ( end == -1 )
01438 setFlag( Flag_CellTooShortX );
01439 }
01440 else
01441 setFlag( Flag_CellTooShortX );
01442 }
01443 else
01444 setFlag( Flag_CellTooShortX );
01445 }
01446
01447
01448
01449
01450
01451 if ( multiRow( _col, _row )
01452 && d->textHeight > ( height - 2 * BORDER_SPACE
01453 - topBorderWidth( _col, _row )
01454 - bottomBorderWidth( _col, _row ) ) )
01455 {
01456 int r = d->row;
01457 int end = 0;
01458
01459
01460 while ( !end ) {
01461 RowFormat *rl2 = m_pSheet->rowFormat( r + 1 );
01462 KSpreadCell *cell = m_pSheet->visibleCellAt( d->column, r + 1 );
01463
01464 if ( cell->isEmpty() ) {
01465 height += rl2->dblHeight() - 1.0;
01466 r++;
01467
01468
01469 if ( d->textHeight <= ( height - 2 * BORDER_SPACE
01470 - topBorderWidth( _col, _row )
01471 - bottomBorderWidth( _col, _row ) ) )
01472 end = 1;
01473 }
01474 else
01475
01476 end = -1;
01477 }
01478
01479
01480 if ( r - d->row > d->extra()->mergedYCells ) {
01481 d->extra()->extraYCells = r - d->row;
01482 d->extra()->extraHeight = height;
01483
01484 for ( int i = d->row + 1; i <= r; ++i ) {
01485 KSpreadCell *cell = m_pSheet->nonDefaultCell( d->column, i );
01486 cell->obscure( this );
01487 }
01488
01489
01490 if ( end == -1 )
01491 setFlag( Flag_CellTooShortY );
01492 }
01493 else
01494 setFlag( Flag_CellTooShortY );
01495 }
01496
01497 clearFlag( Flag_LayoutDirty );
01498
01499 return;
01500 }
01501
01502
01503 void KSpreadCell::valueChanged ()
01504 {
01505 update();
01506
01507 m_pSheet->valueChanged (this);
01508 }
01509
01510
01511
01512
01513
01514 void KSpreadCell::setOutputText()
01515 {
01516 if ( isDefault() ) {
01517 d->strOutText = QString::null;
01518
01519 if ( d->hasExtra() && d->extra()->conditions )
01520 d->extra()->conditions->checkMatches();
01521
01522 return;
01523 }
01524
01525
01526 if ( !testFlag( Flag_TextFormatDirty ) )
01527 return;
01528
01529
01530 clearFlag( Flag_TextFormatDirty );
01531
01532
01533
01534 if ( (!hasError()) && isFormula() && m_pSheet->getShowFormula()
01535 && !( m_pSheet->isProtected() && isHideFormula( d->column, d->row ) ) )
01536 d->strOutText = d->strText;
01537 else {
01538 d->strOutText = sheet()->doc()->formatter()->formatText (this,
01539 formatType());
01540 }
01541
01542
01543 if ( d->hasExtra() && d->extra()->conditions )
01544 d->extra()->conditions->checkMatches();
01545 }
01546
01547
01548
01549
01550
01551
01552
01553 void KSpreadCell::offsetAlign( int _col, int _row )
01554 {
01555 int a;
01556 AlignY ay;
01557 int tmpAngle;
01558 bool tmpVerticalText;
01559 bool tmpMultiRow;
01560 int tmpTopBorderWidth = effTopBorderPen( _col, _row ).width();
01561
01562 if ( d->hasExtra()
01563 && d->extra()->conditions
01564 && d->extra()->conditions->matchedStyle() )
01565 {
01566 KSpreadStyle *style = d->extra()->conditions->matchedStyle();
01567
01568 if ( style->hasFeature( KSpreadStyle::SAlignX, true ) )
01569 a = style->alignX();
01570 else
01571 a = align( _col, _row );
01572
01573 if ( style->hasFeature( KSpreadStyle::SVerticalText, true ) )
01574 tmpVerticalText = style->hasProperty( KSpreadStyle::PVerticalText );
01575 else
01576 tmpVerticalText = verticalText( _col, _row );
01577
01578 if ( style->hasFeature( KSpreadStyle::SMultiRow, true ) )
01579 tmpMultiRow = style->hasProperty( KSpreadStyle::PMultiRow );
01580 else
01581 tmpMultiRow = multiRow( _col, _row );
01582
01583 if ( style->hasFeature( KSpreadStyle::SAlignY, true ) )
01584 ay = style->alignY();
01585 else
01586 ay = alignY( _col, _row );
01587
01588 if ( style->hasFeature( KSpreadStyle::SAngle, true ) )
01589 tmpAngle = style->rotateAngle();
01590 else
01591 tmpAngle = getAngle( _col, _row );
01592 }
01593 else {
01594 a = align( _col, _row );
01595 ay = alignY( _col, _row );
01596 tmpAngle = getAngle( _col, _row );
01597 tmpVerticalText = verticalText( _col, _row );
01598 tmpMultiRow = multiRow( _col, _row );
01599 }
01600
01601 RowFormat *rl = m_pSheet->rowFormat( _row );
01602 ColumnFormat *cl = m_pSheet->columnFormat( _col );
01603
01604 double w = cl->dblWidth();
01605 double h = rl->dblHeight();
01606
01607 if ( d->hasExtra() ) {
01608 if ( d->extra()->extraXCells ) w = d->extra()->extraWidth;
01609 if ( d->extra()->extraYCells ) h = d->extra()->extraHeight;
01610 }
01611
01612
01613
01614 switch( ay ) {
01615 case KSpreadCell::Top:
01616 if ( tmpAngle == 0 )
01617 d->textY = tmpTopBorderWidth + BORDER_SPACE
01618 + (double) d->fmAscent / m_pSheet->doc()->zoomedResolutionY();
01619 else if ( tmpAngle < 0 )
01620 d->textY = tmpTopBorderWidth + BORDER_SPACE;
01621 else
01622 d->textY = tmpTopBorderWidth + BORDER_SPACE
01623 + ( (double)d->fmAscent * cos( tmpAngle * M_PI / 180 )
01624 / m_pSheet->doc()->zoomedResolutionY() );
01625 break;
01626
01627 case KSpreadCell::Bottom:
01628 if ( !tmpVerticalText && !tmpMultiRow && !tmpAngle ) {
01629 d->textY = h - BORDER_SPACE - effBottomBorderPen( _col, _row ).width();
01630 }
01631 else if ( tmpAngle != 0 ) {
01632 if ( h - BORDER_SPACE - d->textHeight
01633 - effBottomBorderPen( _col, _row ).width() > 0 )
01634 {
01635 if ( tmpAngle < 0 )
01636 d->textY = h - BORDER_SPACE - d->textHeight
01637 - effBottomBorderPen( _col, _row ).width();
01638 else
01639 d->textY = h - BORDER_SPACE - d->textHeight
01640 - effBottomBorderPen( _col, _row ).width()
01641 + ( (double) d->fmAscent * cos( tmpAngle * M_PI / 180 )
01642 / m_pSheet->doc()->zoomedResolutionY() );
01643 }
01644 else if ( tmpAngle < 0 )
01645 d->textY = tmpTopBorderWidth + BORDER_SPACE ;
01646 else
01647 d->textY = tmpTopBorderWidth + BORDER_SPACE
01648 + ( (double) d->fmAscent * cos( tmpAngle * M_PI / 180 )
01649 / m_pSheet->doc()->zoomedResolutionY() );
01650 }
01651 else if ( tmpMultiRow ) {
01652 int tmpline = d->hasExtra() ? d->extra()->nbLines : 0;
01653 if ( tmpline > 1 )
01654 tmpline--;
01655
01656 if ( h - BORDER_SPACE - d->textHeight * d->extra()->nbLines
01657 - effBottomBorderPen( _col, _row ).width() > 0 )
01658 d->textY = h - BORDER_SPACE - d->textHeight * tmpline
01659 - effBottomBorderPen( _col, _row ).width();
01660 else
01661 d->textY = tmpTopBorderWidth + BORDER_SPACE
01662 + (double) d->fmAscent / m_pSheet->doc()->zoomedResolutionY();
01663 }
01664 else {
01665 if ( h - BORDER_SPACE - d->textHeight
01666 - effBottomBorderPen( _col, _row ).width() > 0 )
01667 d->textY = h - BORDER_SPACE - d->textHeight
01668 - effBottomBorderPen( _col, _row ).width()
01669 + (double)d->fmAscent / m_pSheet->doc()->zoomedResolutionY();
01670 else
01671 d->textY = tmpTopBorderWidth + BORDER_SPACE
01672 + (double) d->fmAscent / m_pSheet->doc()->zoomedResolutionY();
01673 }
01674 break;
01675
01676 case KSpreadCell::Middle:
01677 case KSpreadCell::UndefinedY:
01678 if ( !tmpVerticalText && !tmpMultiRow && !tmpAngle ) {
01679 d->textY = ( h - d->textHeight ) / 2
01680 + (double) d->fmAscent / m_pSheet->doc()->zoomedResolutionY();
01681 }
01682 else if ( tmpAngle != 0 ) {
01683 if ( h - d->textHeight > 0 ) {
01684 if ( tmpAngle < 0 )
01685 d->textY = ( h - d->textHeight ) / 2 ;
01686 else
01687 d->textY = ( h - d->textHeight ) / 2 +
01688 (double) d->fmAscent * cos( tmpAngle * M_PI / 180 ) /
01689 m_pSheet->doc()->zoomedResolutionY();
01690 }
01691 else {
01692 if ( tmpAngle < 0 )
01693 d->textY = tmpTopBorderWidth + BORDER_SPACE;
01694 else
01695 d->textY = tmpTopBorderWidth + BORDER_SPACE
01696 + ( (double)d->fmAscent * cos( tmpAngle * M_PI / 180 )
01697 / m_pSheet->doc()->zoomedResolutionY() );
01698 }
01699 }
01700 else if ( tmpMultiRow ) {
01701 int tmpline = d->hasExtra() ? d->extra()->nbLines : 0;
01702 if ( tmpline == 0 )
01703 tmpline = 1;
01704
01705 if ( h - d->textHeight * tmpline > 0 )
01706 d->textY = ( h - d->textHeight * tmpline ) / 2
01707 + (double) d->fmAscent / m_pSheet->doc()->zoomedResolutionY();
01708 else
01709 d->textY = tmpTopBorderWidth + BORDER_SPACE
01710 + (double) d->fmAscent / m_pSheet->doc()->zoomedResolutionY();
01711 }
01712 else {
01713 if ( h - d->textHeight > 0 )
01714 d->textY = ( h - d->textHeight ) / 2
01715 + (double)d->fmAscent / m_pSheet->doc()->zoomedResolutionY();
01716 else
01717 d->textY = tmpTopBorderWidth + BORDER_SPACE
01718 + (double)d->fmAscent / m_pSheet->doc()->zoomedResolutionY();
01719 }
01720 break;
01721 }
01722
01723 a = effAlignX();
01724 if ( m_pSheet->getShowFormula()
01725 && !( m_pSheet->isProtected() && isHideFormula( _col, _row ) ) )
01726 a = KSpreadCell::Left;
01727
01728
01729 switch ( a ) {
01730 case KSpreadCell::Left:
01731 d->textX = effLeftBorderPen( _col, _row ).width() + BORDER_SPACE;
01732 break;
01733 case KSpreadCell::Right:
01734 d->textX = ( w - BORDER_SPACE - d->textWidth
01735 - effRightBorderPen( _col, _row ).width() );
01736 break;
01737 case KSpreadCell::Center:
01738 d->textX = ( w - d->textWidth ) / 2;
01739 break;
01740 }
01741 }
01742
01743
01744
01745
01746
01747
01748
01749 void KSpreadCell::textSize( QPainter &_paint )
01750 {
01751 QFontMetrics fm = _paint.fontMetrics();
01752
01753
01754 int tmpAngle;
01755 int _row = row();
01756 int _col = column();
01757 bool tmpVerticalText;
01758 bool fontUnderlined;
01759 AlignY ay;
01760
01761
01762
01763 if ( d->hasExtra()
01764 && d->extra()->conditions
01765 && d->extra()->conditions->matchedStyle() )
01766 {
01767 KSpreadStyle *style = d->extra()->conditions->matchedStyle();
01768
01769 if ( style->hasFeature( KSpreadStyle::SAngle, true ) )
01770 tmpAngle = style->rotateAngle();
01771 else
01772 tmpAngle = getAngle( _col, _row );
01773
01774 if ( style->hasFeature( KSpreadStyle::SVerticalText, true ) )
01775 tmpVerticalText = style->hasProperty( KSpreadStyle::PVerticalText );
01776 else
01777 tmpVerticalText = verticalText( _col, _row );
01778
01779 if ( style->hasFeature( KSpreadStyle::SAlignY, true ) )
01780 ay = style->alignY();
01781 else
01782 ay = alignY( _col, _row );
01783
01784 if ( style->hasFeature( KSpreadStyle::SFontFlag, true ) )
01785 fontUnderlined = ( style->fontFlags()
01786
01787 && (uint) KSpreadStyle::FUnderline );
01788 else
01789 fontUnderlined = textFontUnderline( _col, _row );
01790 }
01791 else {
01792
01793 tmpAngle = getAngle( _col, _row );
01794 tmpVerticalText = verticalText( _col, _row );
01795 ay = alignY( _col, _row );
01796 fontUnderlined = textFontUnderline( _col, _row );
01797 }
01798
01799
01800
01801 if ( !tmpVerticalText && !tmpAngle ) {
01802
01803
01804 d->textWidth = m_pSheet->doc()->unzoomItX( fm.width( d->strOutText ) );
01805 int offsetFont = 0;
01806 if ( ( ay == KSpreadCell::Bottom ) && fontUnderlined ) {
01807 offsetFont = fm.underlinePos() + 1;
01808 }
01809
01810 d->textHeight = m_pSheet->doc()->unzoomItY( fm.ascent() + fm.descent()
01811 + offsetFont );
01812 }
01813 else if ( tmpAngle!= 0 ) {
01814
01815
01816 d->textHeight = m_pSheet->doc()
01817 ->unzoomItY( int( cos( tmpAngle * M_PI / 180 )
01818 * ( fm.ascent() + fm.descent() )
01819 + abs( int( ( fm.width( d->strOutText )
01820 * sin( tmpAngle * M_PI / 180 ) ) ) ) ) );
01821
01822 d->textWidth = m_pSheet->doc()
01823 ->unzoomItX( int( abs( int( ( sin( tmpAngle * M_PI / 180 )
01824 * ( fm.ascent() + fm.descent() ) ) ) )
01825 + fm.width( d->strOutText )
01826 * cos ( tmpAngle * M_PI / 180 ) ) );
01827 }
01828 else {
01829
01830 int width = 0;
01831 for ( unsigned int i = 0; i < d->strOutText.length(); i++ )
01832 width = QMAX( width, fm.width( d->strOutText.at( i ) ) );
01833
01834 d->textWidth = m_pSheet->doc()->unzoomItX( width );
01835 d->textHeight = m_pSheet->doc()->unzoomItY( ( fm.ascent() + fm.descent() )
01836 * d->strOutText.length() );
01837 }
01838 }
01839
01840
01841
01842
01843
01844
01845
01846 void KSpreadCell::applyZoomedFont( QPainter &painter, int _col, int _row )
01847 {
01848 QFont tmpFont( textFont( _col, _row ) );
01849
01850
01851
01852 if ( d->hasExtra()
01853 && d->extra()->conditions
01854 && d->extra()->conditions->matchedStyle() ) {
01855
01856 KSpreadStyle * s = d->extra()->conditions->matchedStyle();
01857
01858
01859 if ( s->hasFeature( KSpreadStyle::SFontSize, true ) )
01860 tmpFont.setPointSizeFloat( s->fontSize() );
01861
01862
01863 if ( s->hasFeature( KSpreadStyle::SFontFlag, true ) ) {
01864 uint flags = s->fontFlags();
01865
01866 tmpFont.setBold( flags & (uint) KSpreadStyle::FBold );
01867 tmpFont.setUnderline( flags & (uint) KSpreadStyle::FUnderline );
01868 tmpFont.setItalic( flags & (uint) KSpreadStyle::FItalic );
01869 tmpFont.setStrikeOut( flags & (uint) KSpreadStyle::FStrike );
01870 }
01871
01872
01873 if ( s->hasFeature( KSpreadStyle::SFontFamily, true ) )
01874 tmpFont.setFamily( s->fontFamily() );
01875 }
01876 #if 0
01877 else
01878
01879
01880
01881 if ( d->extra()->conditions
01882 && d->extra()->conditions->currentCondition( condition )
01883 && !(m_pSheet->getShowFormula()
01884 && !( m_pSheet->isProtected()
01885 && isHideFormula( d->column, d->row ) ) ) )
01886 {
01887 if ( condition.fontcond )
01888 tmpFont = *(condition.fontcond);
01889 else
01890 tmpFont = condition.style->font();
01891 }
01892 #endif
01893
01894
01895 tmpFont.setPointSizeFloat( 0.01 * m_pSheet->doc()->zoom()
01896 * tmpFont.pointSizeFloat() );
01897
01898 painter.setFont( tmpFont );
01899 }
01900
01901
01902
01903 void KSpreadCell::calculateTextParameters( QPainter &_painter,
01904 int _col, int _row )
01905 {
01906
01907 applyZoomedFont( _painter, _col, _row );
01908
01909
01910 textSize( _painter );
01911
01912
01913 offsetAlign( _col, _row );
01914 }
01915
01916
01917
01918
01919
01920
01921 bool KSpreadCell::makeFormula()
01922 {
01923 clearFormula();
01924
01925 KSContext context;
01926
01927
01928
01929
01930
01931
01932
01933
01934
01935
01936
01937
01938
01939
01940
01941
01942
01943
01944
01945
01946
01947
01948
01949
01950
01951
01952
01953
01954
01955
01956 d->code = m_pSheet->doc()->interpreter()->parse( context, m_pSheet, d->strText );
01957
01958 if ( context.exception() )
01959 {
01960 clearFormula();
01961
01962 setFlag(Flag_ParseError);
01963 KSpreadValue v;
01964 v.setError ( "####" );
01965 setValue (v);
01966 if (m_pSheet->doc()->getShowMessageError())
01967 {
01968 QString tmp(i18n("Error in cell %1\n\n"));
01969 tmp = tmp.arg( fullName() );
01970 tmp += context.exception()->toString( context );
01971 KMessageBox::error( (QWidget*)0L, tmp);
01972 }
01973 return false;
01974 }
01975
01976
01977
01978 valueChanged ();
01979
01980 return true;
01981 }
01982
01983 void KSpreadCell::clearFormula()
01984 {
01985 delete d->code;
01986 d->code = 0L;
01987 }
01988
01989 bool KSpreadCell::calc(bool delay)
01990 {
01991 if ( !isFormula() )
01992 return true;
01993
01994 if ( d->code == 0 )
01995 {
01996 if ( testFlag( Flag_ParseError ) )
01997 return false;
01998 else
01999 {
02000
02001
02002
02003 makeFormula();
02004
02005 if ( d->code == 0 )
02006 return false;
02007 }
02008 }
02009
02010 if ( !testFlag( Flag_CalcDirty ) )
02011 return true;
02012
02013 if ( delay )
02014 {
02015 if ( m_pSheet->doc()->delayCalculation() )
02016 return true;
02017 }
02018
02019 setFlag(Flag_LayoutDirty);
02020 setFlag(Flag_TextFormatDirty);
02021 clearFlag(Flag_CalcDirty);
02022
02023 KSContext& context = m_pSheet->doc()->context();
02024 if ( !m_pSheet->doc()->interpreter()->evaluate( context, d->code, m_pSheet, this ) )
02025 {
02026
02027 setFlag(Flag_ParseError);
02028 setFlag(Flag_LayoutDirty);
02029 KSpreadValue v;
02030 v.setError( "####" );
02031 setValue (v);
02032
02033 if ( context.exception() && m_pSheet->doc()->getShowMessageError())
02034 {
02035 QString tmp(i18n("Error in cell %1\n\n"));
02036 tmp = tmp.arg( fullName() );
02037 tmp += context.exception()->toString( context );
02038 KMessageBox::error( (QWidget*)0L, tmp);
02039 }
02040
02041
02042 clearFlag(Flag_CalcDirty);
02043
02044 return false;
02045 }
02046
02047
02048 else if ( context.value()->type() == KSValue::DoubleType )
02049 {
02050 setValue ( KSpreadValue( context.value()->doubleValue() ) );
02051 checkNumberFormat();
02052 }
02053 else if ( context.value()->type() == KSValue::IntType )
02054 {
02055 setValue ( KSpreadValue( (int)context.value()->intValue() ) );
02056 checkNumberFormat();
02057 }
02058 else if ( context.value()->type() == KSValue::BoolType )
02059 {
02060 setValue ( KSpreadValue( context.value()->boolValue() ) );
02061 }
02062 else if ( context.value()->type() == KSValue::TimeType )
02063 {
02064 setValue( KSpreadValue( context.value()->timeValue() ) );
02065 }
02066 else if ( context.value()->type() == KSValue::DateType)
02067 {
02068 setValue ( KSpreadValue( context.value()->dateValue() ) );
02069 }
02070 else if ( context.value()->type() == KSValue::Empty )
02071 {
02072 setValue (KSpreadValue::empty());
02073 }
02074 else
02075 {
02076
02077 QString str = context.value()->toString( context );
02078 setValue (KSpreadValue (str));
02079 }
02080
02081 clearFlag(Flag_CalcDirty);
02082 setFlag(Flag_LayoutDirty);
02083
02084 return true;
02085 }
02086
02087
02088
02089
02090
02091
02092
02093
02094
02095
02096
02097
02098
02099
02100 void KSpreadCell::paintCell( const KoRect &rect, QPainter & painter,
02101 KSpreadView *view,
02102 const KoPoint &coordinate,
02103 const QPoint &cellRef,
02104 bool paintBorderRight, bool paintBorderBottom,
02105 bool paintBorderLeft, bool paintBorderTop,
02106 QPen & rightPen, QPen & bottomPen,
02107 QPen & leftPen, QPen & topPen,
02108 bool drawCursor )
02109 {
02110
02111
02112 if ( testFlag( Flag_PaintingCell ) )
02113 return;
02114
02115
02116 setFlag( Flag_PaintingCell );
02117
02118
02119
02120
02121
02122 static int paintingObscured = 0;
02123
02124 #if 0
02125 if (paintingObscured == 0)
02126 kdDebug(36001) << "painting cell " << name() << endl;
02127 else
02128 kdDebug(36001) << " painting obscured cell " << name() << endl;
02129 #endif
02130
02131
02132
02133 Q_ASSERT(!(paintingObscured > 0 && d->extra()->obscuringCells.isEmpty()));
02134
02135
02136 Q_ASSERT(isDefault()
02137 || (((cellRef.x() == d->column) && (cellRef.y() == d->row))));
02138
02139 KSpreadSheet::LayoutDirection sheetDir = m_pSheet->layoutDirection();
02140
02141 double left = coordinate.x();
02142
02143 ColumnFormat * colFormat = m_pSheet->columnFormat( cellRef.x() );
02144 RowFormat * rowFormat = m_pSheet->rowFormat( cellRef.y() );
02145
02146
02147
02148
02149
02150 double width0 = colFormat->dblWidth();
02151 double height0 = rowFormat->dblHeight();
02152 double width = width0;
02153 double height = height0;
02154
02155
02156
02157
02158
02159
02160
02161
02162
02163 if ( sheetDir == KSpreadSheet::RightToLeft && paintingObscured == 0
02164 && view && view->canvasWidget() )
02165 {
02166 double dwidth = view->doc()->unzoomItX(view->canvasWidget()->width());
02167 left = dwidth - coordinate.x() - width;
02168 }
02169
02170
02171
02172
02173 if (d->hasExtra()) {
02174 if (d->extra()->mergedXCells > 0 || d->extra()->mergedYCells > 0) {
02175
02176 if ( sheetDir == KSpreadSheet::RightToLeft )
02177 {
02178 left -= d->extra()->extraWidth - width;
02179 }
02180 width0 = d->extra()->extraWidth;
02181 height0 = d->extra()->extraHeight;
02182 width = d->extra()->extraWidth;
02183 height = d->extra()->extraHeight;
02184 }
02185 else {
02186 #if 0
02187 width += d->extra()->extraXCells ? d->extra()->extraWidth : 0;
02188 height += d->extra()->extraYCells ? d->extra()->extraHeight : 0;
02189 #else
02190
02191 if ( d->extra()->extraXCells )
02192 width = d->extra()->extraWidth;
02193 if ( d->extra()->extraYCells )
02194 height = d->extra()->extraHeight;
02195 #endif
02196 }
02197 }
02198
02199
02200
02201
02202
02203
02204 bool selected = false;
02205 if ( view != NULL ) {
02206 selected = view->selection().contains( cellRef );
02207
02208
02209 KSpreadCell *cell = m_pSheet->cellAt( view->marker() );
02210 QPoint bottomRight( view->marker().x() + cell->extraXCells(),
02211 view->marker().y() + cell->extraYCells() );
02212 QRect markerArea( view->marker(), bottomRight );
02213 selected = selected && !( markerArea.contains( cellRef ) );
02214
02215
02216 if ( painter.device()->isExtDev() || !drawCursor )
02217 selected = false;
02218 }
02219
02220
02221
02222
02223
02224
02225
02226
02227
02228 if ( testFlag( Flag_LayoutDirty ) )
02229 makeLayout( painter, cellRef.x(), cellRef.y() );
02230
02231
02232
02233
02234
02235
02236 const KoRect cellRect( left, coordinate.y(), width, height );
02237 const KoRect cellRect0( left, coordinate.y(), width0, height0 );
02238 if ( !cellRect.intersects( rect ) ) {
02239 clearFlag( Flag_PaintingCell );
02240 return;
02241 }
02242
02243
02244
02245
02246
02247
02248 QColor backgroundColor;
02249 if ( d->hasExtra() && d->extra()->conditions
02250 && d->extra()->conditions->matchedStyle()
02251 && d->extra()->conditions->matchedStyle()->hasFeature( KSpreadStyle::SBackgroundColor, true ) )
02252 backgroundColor = d->extra()->conditions->matchedStyle()->bgColor();
02253 else
02254 backgroundColor = bgColor( cellRef.x(), cellRef.y() );
02255
02256
02257 if ( !isObscuringForced() )
02258 paintBackground( painter, cellRect0, cellRef, selected, backgroundColor );
02259
02260
02261
02262 if ( painter.device()->devType() != QInternal::Printer
02263 || m_pSheet->print()->printGrid())
02264 paintDefaultBorders( painter, rect, cellRect, cellRef,
02265 paintBorderRight, paintBorderBottom,
02266 paintBorderLeft, paintBorderTop,
02267 rightPen, bottomPen, leftPen, topPen );
02268
02269
02270
02271
02272
02273
02274
02275 paintingObscured++;
02276
02277 if (d->hasExtra() && (d->extra()->extraXCells > 0
02278 || d->extra()->extraYCells > 0))
02279
02280
02281 paintObscuredCells( rect, painter, view, cellRect, cellRef,
02282 paintBorderRight, paintBorderBottom,
02283 paintBorderLeft, paintBorderTop,
02284 rightPen, bottomPen, leftPen, topPen );
02285 paintingObscured--;
02286
02287
02288
02289 if ( painter.device()->isExtDev() )
02290 painter.setClipping( false );
02291
02292
02293
02294
02295
02296 if ( !isObscuringForced() )
02297 paintCellBorders( painter, rect, cellRect0,
02298 cellRef,
02299 paintBorderRight, paintBorderBottom,
02300 paintBorderLeft, paintBorderTop,
02301 rightPen, bottomPen, leftPen, topPen );
02302
02303 if ( painter.device()->isExtDev() )
02304 painter.setClipping( true );
02305
02306
02307 paintCellDiagonalLines( painter, cellRect0, cellRef );
02308 paintPageBorders( painter, cellRect0, cellRef,
02309 paintBorderRight, paintBorderBottom );
02310
02311
02312 if ( !isObscured() ) {
02313
02314
02315 if ( !painter.device()->isExtDev()
02316 || m_pSheet->print()->printCommentIndicator() )
02317 paintCommentIndicator( painter, cellRect, cellRef, backgroundColor );
02318
02319
02320 if ( !painter.device()->isExtDev()
02321 || m_pSheet->print()->printFormulaIndicator() )
02322 paintFormulaIndicator( painter, cellRect, backgroundColor );
02323
02324
02325 paintMoreTextIndicator( painter, cellRect, backgroundColor );
02326
02327
02328
02329
02330
02331 if ( !d->strOutText.isEmpty()
02332 && ( !painter.device()->isExtDev() || !getDontprintText( cellRef.x(),
02333 cellRef.y() ) )
02334 && !( m_pSheet->isProtected() && isHideAll( cellRef.x(), cellRef.y() ) ) )
02335 {
02336 paintText( painter, cellRect, cellRef );
02337 }
02338 }
02339
02340
02341
02342
02343 if ( isObscured() && paintingObscured == 0 &&
02344 !( sheetDir == KSpreadSheet::RightToLeft && painter.device()->isExtDev() ) )
02345 {
02346
02347
02348
02349
02350
02351
02352
02353
02354 if (d->hasExtra()) {
02355 QValueList<QPoint> listPoints;
02356 QValueList<KSpreadCell*>::iterator it = d->extra()->obscuringCells.begin();
02357 QValueList<KSpreadCell*>::iterator end = d->extra()->obscuringCells.end();
02358 for ( ; it != end; ++it ) {
02359 KSpreadCell *obscuringCell = *it;
02360
02361 listPoints.append( QPoint( obscuringCell->column(),
02362 obscuringCell->row() ) );
02363 }
02364
02365 QValueList<QPoint>::iterator it1 = listPoints.begin();
02366 QValueList<QPoint>::iterator end1 = listPoints.end();
02367 for ( ; it1 != end1; ++it1 ) {
02368 QPoint obscuringCellRef = *it1;
02369 KSpreadCell *obscuringCell = m_pSheet->cellAt( obscuringCellRef.x(),
02370 obscuringCellRef.y() );
02371
02372 if ( obscuringCell != 0 ) {
02373 double x = m_pSheet->dblColumnPos( obscuringCellRef.x() );
02374 double y = m_pSheet->dblRowPos( obscuringCellRef.y() );
02375 if ( view != 0 ) {
02376 x -= view->canvasWidget()->xOffset();
02377 y -= view->canvasWidget()->yOffset();
02378 }
02379
02380 KoPoint corner( x, y );
02381 painter.save();
02382
02383
02384
02385
02386 QPen rp( obscuringCell->effRightBorderPen( obscuringCellRef.x(),
02387 obscuringCellRef.y() ) );
02388 QPen bp( obscuringCell->effBottomBorderPen( obscuringCellRef.x(),
02389 obscuringCellRef.y() ) );
02390 QPen lp( obscuringCell->effLeftBorderPen( obscuringCellRef.x(),
02391 obscuringCellRef.y() ) );
02392 QPen tp( obscuringCell->effTopBorderPen( obscuringCellRef.x(),
02393 obscuringCellRef.y() ) );
02394
02395
02396
02397 obscuringCell->paintCell( rect, painter, view,
02398 corner, obscuringCellRef,
02399 true, true, true, true,
02400 rp, bp, lp, tp );
02401 painter.restore();
02402 }
02403 }
02404 }
02405 }
02406
02407
02408 clearFlag( Flag_PaintingCell );
02409 }
02410
02411
02412
02413
02414
02415 #if 0
02416
02420 if ( d->style == KSpreadCell::ST_Button )
02421 {
02422
02423 QBrush fill( Qt::lightGray );
02424 QApplication::style().drawControl( QStyle::CE_PushButton, &_painter, this,
02425 QRect( _tx + 1, _ty + 1, w2 - 1, h2 - 1 ),
02426 defaultColorGroup );
02427
02428 }
02429
02433 else if ( d->style == KSpreadCell::ST_Select )
02434 {
02435 QApplication::style().drawComboButton( &_painter, _tx + 1, _ty + 1,
02436 w2 - 1, h2 - 1,
02437 defaultColorGroup, selected );
02438 }
02439 #endif
02440
02441
02442
02443
02444 void KSpreadCell::paintObscuredCells(const KoRect& rect, QPainter& painter,
02445 KSpreadView* view,
02446 const KoRect &cellRect,
02447 const QPoint &cellRef,
02448 bool paintBorderRight,
02449 bool _paintBorderBottom,
02450 bool paintBorderLeft,
02451 bool _paintBorderTop,
02452 QPen & rightPen, QPen & _bottomPen,
02453 QPen & leftPen, QPen & _topPen )
02454 {
02455
02456 if ( !extraXCells() && !extraYCells() )
02457 return;
02458
02459 double ypos = cellRect.y();
02460 int maxY = extraYCells();
02461 int maxX = extraXCells();
02462
02463
02464 for ( int y = 0; y <= maxY; ++y ) {
02465 double xpos = cellRect.x();
02466 RowFormat* rl = m_pSheet->rowFormat( cellRef.y() + y );
02467
02468 for( int x = 0; x <= maxX; ++ x ) {
02469 ColumnFormat * cl = m_pSheet->columnFormat( cellRef.x() + x );
02470 if ( y != 0 || x != 0 ) {
02471 uint column = cellRef.x() + x;
02472 uint row = cellRef.y() + y;
02473
02474 QPen topPen;
02475 QPen bottomPen;
02476 bool paintBorderTop;
02477 bool paintBorderBottom;
02478
02479 KSpreadCell *cell = m_pSheet->cellAt( column, row );
02480 KoPoint corner( xpos, ypos );
02481
02482
02483
02484
02485
02486 topPen = _topPen;
02487 paintBorderTop = _paintBorderTop;
02488 if ( row > 1 && !cell->isObscuringForced() ) {
02489 KSpreadCell *cellUp = m_pSheet->cellAt( column, row - 1 );
02490
02491 if ( cellUp->isDefault() )
02492 paintBorderTop = false;
02493 else {
02494
02495
02496 cellUp = cellUp->ultimateObscuringCell();
02497
02498 topPen = cellUp->effBottomBorderPen( cellUp->column(),
02499 cellUp->row() );
02500
02501 #if 0
02502 int penWidth = QMAX(1, sheet()->doc()->zoomItY( topPen.width() ));
02503 topPen.setWidth( penWidth );
02504 #endif
02505 }
02506 }
02507
02508
02509
02510 bottomPen = _bottomPen;
02511 paintBorderBottom = _paintBorderBottom;
02512
02513 cell->paintCell( rect, painter, view,
02514 corner,
02515 QPoint( cellRef.x() + x, cellRef.y() + y ),
02516 paintBorderRight, paintBorderBottom,
02517 paintBorderLeft, paintBorderTop,
02518 rightPen, bottomPen, leftPen, topPen );
02519 }
02520 xpos += cl->dblWidth();
02521 }
02522
02523 ypos += rl->dblHeight();
02524 }
02525 }
02526
02527
02528
02529
02530 void KSpreadCell::paintBackground( QPainter& painter, const KoRect &cellRect,
02531 const QPoint &cellRef, bool selected,
02532 QColor &backgroundColor )
02533 {
02534 QColorGroup defaultColorGroup = QApplication::palette().active();
02535 QRect zoomedCellRect = sheet()->doc()->zoomRect( cellRect );
02536
02537
02538
02539
02540
02541
02542
02543 if ( cellRef.x() != KS_colMax )
02544 zoomedCellRect.setWidth( zoomedCellRect.width() - 1 );
02545 if ( cellRef.y() != KS_rowMax )
02546 zoomedCellRect.setHeight( zoomedCellRect.height() - 1 );
02547
02548
02549 if ( selected )
02550 {
02551 QColor c = defaultColorGroup.highlight().light();
02552 painter.setBackgroundColor( c );
02553 }
02554 else {
02555 QColor bg( backgroundColor );
02556
02557
02558 if ( !painter.device()->isExtDev() ) {
02559 if ( bg.isValid() )
02560 painter.setBackgroundColor( bg );
02561 else
02562 painter.setBackgroundColor( defaultColorGroup.base() );
02563 }
02564 else {
02565
02566
02567 QBrush bb( bg );
02568 if ( !bg.isValid() )
02569 bb.setColor( Qt::white );
02570
02571 painter.fillRect( zoomedCellRect, bb );
02572 return;
02573 }
02574 }
02575
02576
02577 if ( !painter.device()->isExtDev() )
02578 painter.eraseRect( zoomedCellRect );
02579
02580
02581 QBrush bb;
02582 if ( d->hasExtra()
02583 && d->extra()->conditions
02584 && d->extra()->conditions->matchedStyle()
02585 && d->extra()->conditions->matchedStyle()->hasFeature( KSpreadStyle::SBackgroundBrush, true ) )
02586 bb = d->extra()->conditions->matchedStyle()->backGroundBrush();
02587 else
02588 bb = backGroundBrush( cellRef.x(), cellRef.y() );
02589
02590
02591 if ( bb.style() != Qt::NoBrush )
02592 painter.fillRect( zoomedCellRect, bb );
02593
02594 backgroundColor = painter.backgroundColor();
02595 }
02596
02597
02598
02599
02600 void KSpreadCell::paintDefaultBorders( QPainter& painter, const KoRect &rect,
02601 const KoRect &cellRect,
02602 const QPoint &cellRef,
02603 bool paintBorderRight, bool paintBorderBottom,
02604 bool paintBorderLeft, bool paintBorderTop,
02605 QPen const & rightPen, QPen const & bottomPen,
02606 QPen const & leftPen, QPen const & topPen )
02607 {
02608 KSpreadDoc* doc = sheet()->doc();
02609
02610 KSpreadSheet::LayoutDirection sheetDir = m_pSheet->layoutDirection();
02611
02612
02613
02614
02615
02616
02617 bool paintTop;
02618 bool paintLeft;
02619 bool paintBottom;
02620 bool paintRight;
02621
02622 paintLeft = ( paintBorderLeft && leftPen.style() == Qt::NoPen
02623 && sheet()->getShowGrid() );
02624 paintRight = ( paintBorderRight && rightPen.style() == Qt::NoPen
02625 && sheet()->getShowGrid() );
02626 paintTop = ( paintBorderTop && topPen.style() == Qt::NoPen
02627 && sheet()->getShowGrid() );
02628 paintBottom = ( paintBorderBottom && sheet()->getShowGrid()
02629 && bottomPen.style() == Qt::NoPen );
02630
02631
02632 if (d->hasExtra()) {
02633 QValueList<KSpreadCell*>::const_iterator it = d->extra()->obscuringCells.begin();
02634 QValueList<KSpreadCell*>::const_iterator end = d->extra()->obscuringCells.end();
02635 for ( ; it != end; ++it ) {
02636 KSpreadCell *cell = *it;
02637
02638 paintTop = paintTop && ( cell->row() == cellRef.y() );
02639 paintBottom = false;
02640
02641 if ( sheetDir == KSpreadSheet::RightToLeft )
02642 {
02643 paintRight = paintRight && ( cell->column() == cellRef.x() );
02644 paintLeft = false;
02645 }
02646 else
02647 {
02648 paintLeft = paintLeft && ( cell->column() == cellRef.x() );
02649 paintRight = false;
02650 }
02651 }
02652 }
02653
02654
02655 if ( paintLeft ) {
02656 int dt = 0;
02657 int db = 0;
02658
02659 if ( cellRef.x() > 1 ) {
02660 KSpreadCell *cell_west = m_pSheet->cellAt( cellRef.x() - 1,
02661 cellRef.y() );
02662 QPen t = cell_west->effTopBorderPen( cellRef.x() - 1, cellRef.y() );
02663 QPen b = cell_west->effBottomBorderPen( cellRef.x() - 1, cellRef.y() );
02664
02665 if ( t.style() != Qt::NoPen )
02666 dt = ( t.width() + 1 )/2;
02667 if ( b.style() != Qt::NoPen )
02668 db = ( t.width() / 2);
02669 }
02670
02671 painter.setPen( QPen( sheet()->doc()->gridColor(), 1, Qt::SolidLine ) );
02672
02673
02674
02675 if ( painter.device()->isExtDev() ) {
02676 if ( sheetDir == KSpreadSheet::RightToLeft )
02677 painter.drawLine( doc->zoomItX( QMAX( rect.left(), cellRect.right() ) ),
02678 doc->zoomItY( QMAX( rect.top(), cellRect.y() + dt ) ),
02679 doc->zoomItX( QMIN( rect.right(), cellRect.right() ) ),
02680 doc->zoomItY( QMIN( rect.bottom(), cellRect.bottom() - db ) ) );
02681 else
02682 painter.drawLine( doc->zoomItX( QMAX( rect.left(), cellRect.x() ) ),
02683 doc->zoomItY( QMAX( rect.top(), cellRect.y() + dt ) ),
02684 doc->zoomItX( QMIN( rect.right(), cellRect.x() ) ),
02685 doc->zoomItY( QMIN( rect.bottom(), cellRect.bottom() - db ) ) );
02686 }
02687 else {
02688 if ( sheetDir == KSpreadSheet::RightToLeft )
02689 painter.drawLine( doc->zoomItX( cellRect.right() ),
02690 doc->zoomItY( cellRect.y() + dt ),
02691 doc->zoomItX( cellRect.right() ),
02692 doc->zoomItY( cellRect.bottom() - db ) );
02693 else
02694 painter.drawLine( doc->zoomItX( cellRect.x() ),
02695 doc->zoomItY( cellRect.y() + dt ),
02696 doc->zoomItX( cellRect.x() ),
02697 doc->zoomItY( cellRect.bottom() - db ) );
02698 }
02699 }
02700
02701
02702 if ( paintRight ) {
02703 int dt = 0;
02704 int db = 0;
02705
02706 if ( cellRef.x() < KS_colMax ) {
02707 KSpreadCell *cell_east = m_pSheet->cellAt( cellRef.x() + 1,
02708 cellRef.y() );
02709
02710 QPen t = cell_east->effTopBorderPen( cellRef.x() + 1, cellRef.y() );
02711 QPen b = cell_east->effBottomBorderPen( cellRef.x() + 1, cellRef.y() );
02712
02713 if ( t.style() != Qt::NoPen )
02714 dt = ( t.width() + 1 ) / 2;
02715 if ( b.style() != Qt::NoPen )
02716 db = ( t.width() / 2);
02717 }
02718
02719 painter.setPen( QPen( sheet()->doc()->gridColor(), 1, Qt::SolidLine ) );
02720
02721
02722
02723 if ( painter.device()->isExtDev() ) {
02724 if ( sheetDir == KSpreadSheet::RightToLeft )
02725 painter.drawLine( doc->zoomItX( QMAX( rect.left(), cellRect.x() ) ),
02726 doc->zoomItY( QMAX( rect.top(), cellRect.y() + dt ) ),
02727 doc->zoomItX( QMIN( rect.right(), cellRect.x() ) ),
02728 doc->zoomItY( QMIN( rect.bottom(), cellRect.bottom() - db ) ) );
02729 else
02730 painter.drawLine( doc->zoomItX( QMAX( rect.left(), cellRect.right() ) ),
02731 doc->zoomItY( QMAX( rect.top(), cellRect.y() + dt ) ),
02732 doc->zoomItX( QMIN( rect.right(), cellRect.right() ) ),
02733 doc->zoomItY( QMIN( rect.bottom(), cellRect.bottom() - db ) ) );
02734 }
02735 else {
02736 if ( sheetDir == KSpreadSheet::RightToLeft )
02737 painter.drawLine( doc->zoomItX( cellRect.x() ),
02738 doc->zoomItY( cellRect.y() + dt ),
02739 doc->zoomItX( cellRect.x() ),
02740 doc->zoomItY( cellRect.bottom() - db ) );
02741 else
02742 painter.drawLine( doc->zoomItX( cellRect.right() ),
02743 doc->zoomItY( cellRect.y() + dt ),
02744 doc->zoomItX( cellRect.right() ),
02745 doc->zoomItY( cellRect.bottom() - db ) );
02746 }
02747 }
02748
02749
02750 if ( paintTop ) {
02751 int dl = 0;
02752 int dr = 0;
02753 if ( cellRef.y() > 1 ) {
02754 KSpreadCell *cell_north = m_pSheet->cellAt( cellRef.x(),
02755 cellRef.y() - 1 );
02756
02757 QPen l = cell_north->effLeftBorderPen( cellRef.x(), cellRef.y() - 1 );
02758 QPen r = cell_north->effRightBorderPen( cellRef.x(), cellRef.y() - 1 );
02759
02760 if ( l.style() != Qt::NoPen )
02761 dl = ( l.width() - 1 ) / 2 + 1;
02762 if ( r.style() != Qt::NoPen )
02763 dr = r.width() / 2;
02764 }
02765
02766 painter.setPen( QPen( sheet()->doc()->gridColor(), 1, Qt::SolidLine ) );
02767
02768
02769
02770 if ( painter.device()->isExtDev() ) {
02771 painter.drawLine( doc->zoomItX( QMAX( rect.left(), cellRect.x() + dl ) ),
02772 doc->zoomItY( QMAX( rect.top(), cellRect.y() ) ),
02773 doc->zoomItX( QMIN( rect.right(), cellRect.right() - dr ) ),
02774 doc->zoomItY( QMIN( rect.bottom(), cellRect.y() ) ) );
02775 }
02776 else {
02777 painter.drawLine( doc->zoomItX( cellRect.x() + dl ),
02778 doc->zoomItY( cellRect.y() ),
02779 doc->zoomItX( cellRect.right() - dr ),
02780 doc->zoomItY( cellRect.y() ) );
02781 }
02782 }
02783
02784
02785 if ( paintBottom ) {
02786 int dl = 0;
02787 int dr = 0;
02788 if ( cellRef.y() < KS_rowMax ) {
02789 KSpreadCell *cell_south = m_pSheet->cellAt( cellRef.x(),
02790 cellRef.y() + 1 );
02791
02792 QPen l = cell_south->effLeftBorderPen( cellRef.x(), cellRef.y() + 1 );
02793 QPen r = cell_south->effRightBorderPen( cellRef.x(), cellRef.y() + 1 );
02794
02795 if ( l.style() != Qt::NoPen )
02796 dl = ( l.width() - 1 ) / 2 + 1;
02797 if ( r.style() != Qt::NoPen )
02798 dr = r.width() / 2;
02799 }
02800
02801 painter.setPen( QPen( sheet()->doc()->gridColor(), 1, Qt::SolidLine ) );
02802
02803
02804
02805 if ( painter.device()->isExtDev() ) {
02806 painter.drawLine( doc->zoomItX( QMAX( rect.left(), cellRect.x() + dl ) ),
02807 doc->zoomItY( QMAX( rect.top(), cellRect.bottom() ) ),
02808 doc->zoomItX( QMIN( rect.right(), cellRect.right() - dr ) ),
02809 doc->zoomItY( QMIN( rect.bottom(), cellRect.bottom() ) ) );
02810 }
02811 else {
02812 painter.drawLine( doc->zoomItX( cellRect.x() + dl ),
02813 doc->zoomItY( cellRect.bottom() ),
02814 doc->zoomItX( cellRect.right() - dr ),
02815 doc->zoomItY( cellRect.bottom() ) );
02816 }
02817 }
02818 }
02819
02820
02821
02822
02823 void KSpreadCell::paintCommentIndicator( QPainter& painter,
02824 const KoRect &cellRect,
02825 const QPoint &,
02826 QColor &backgroundColor )
02827 {
02828 KSpreadDoc * doc = sheet()->doc();
02829
02830
02831
02832 if ( ( m_mask & (uint) PComment )
02833 && cellRect.width() > 10.0
02834 && cellRect.height() > 10.0
02835 && ( sheet()->print()->printCommentIndicator()
02836 || ( !painter.device()->isExtDev() && doc->getShowCommentIndicator() ) ) ) {
02837 QColor penColor = Qt::red;
02838
02839
02840 if ( qRed( backgroundColor.rgb() ) > 127 &&
02841 qGreen( backgroundColor.rgb() ) < 80 &&
02842 qBlue( backgroundColor.rgb() ) < 80 )
02843 {
02844 penColor = Qt::blue;
02845 }
02846
02847
02848 QPointArray point( 3 );
02849 if ( m_pSheet->layoutDirection()==KSpreadSheet::RightToLeft ) {
02850 point.setPoint( 0, doc->zoomItX( cellRect.x() + 6.0 ),
02851 doc->zoomItY( cellRect.y() ) );
02852 point.setPoint( 1, doc->zoomItX( cellRect.x() ),
02853 doc->zoomItY( cellRect.y() ) );
02854 point.setPoint( 2, doc->zoomItX( cellRect.x() ),
02855 doc->zoomItY( cellRect.y() + 6.0 ) );
02856 }
02857 else {
02858 point.setPoint( 0, doc->zoomItX( cellRect.right() - 5.0 ),
02859 doc->zoomItY( cellRect.y() ) );
02860 point.setPoint( 1, doc->zoomItX( cellRect.right() ),
02861 doc->zoomItY( cellRect.y() ) );
02862 point.setPoint( 2, doc->zoomItX( cellRect.right() ),
02863 doc->zoomItY( cellRect.y() + 5.0 ) );
02864 }
02865
02866
02867 painter.setBrush( QBrush( penColor ) );
02868 painter.setPen( Qt::NoPen );
02869 painter.drawPolygon( point );
02870 }
02871 }
02872
02873
02874
02875
02876
02877 void KSpreadCell::paintFormulaIndicator( QPainter& painter,
02878 const KoRect &cellRect,
02879 QColor &backgroundColor )
02880 {
02881 if ( isFormula() &&
02882 m_pSheet->getShowFormulaIndicator() &&
02883 cellRect.width() > 10.0 &&
02884 cellRect.height() > 10.0 )
02885 {
02886 KSpreadDoc* doc = sheet()->doc();
02887
02888 QColor penColor = Qt::blue;
02889
02890 if ( qRed( backgroundColor.rgb() ) < 80 &&
02891 qGreen( backgroundColor.rgb() ) < 80 &&
02892 qBlue( backgroundColor.rgb() ) > 127 )
02893 {
02894 penColor = Qt::red;
02895 }
02896
02897
02898 QPointArray point( 3 );
02899 if ( m_pSheet->layoutDirection()==KSpreadSheet::RightToLeft ) {
02900 point.setPoint( 0, doc->zoomItX( cellRect.right() - 6.0 ),
02901 doc->zoomItY( cellRect.bottom() ) );
02902 point.setPoint( 1, doc->zoomItX( cellRect.right() ),
02903 doc->zoomItY( cellRect.bottom() ) );
02904 point.setPoint( 2, doc->zoomItX( cellRect.right() ),
02905 doc->zoomItY( cellRect.bottom() - 6.0 ) );
02906 }
02907 else {
02908 point.setPoint( 0, doc->zoomItX( cellRect.x() ),
02909 doc->zoomItY( cellRect.bottom() - 6.0 ) );
02910 point.setPoint( 1, doc->zoomItX( cellRect.x() ),
02911 doc->zoomItY( cellRect.bottom() ) );
02912 point.setPoint( 2, doc->zoomItX( cellRect.x() + 6.0 ),
02913 doc->zoomItY( cellRect.bottom() ) );
02914 }
02915
02916
02917 painter.setBrush( QBrush( penColor ) );
02918 painter.setPen( Qt::NoPen );
02919 painter.drawPolygon( point );
02920 }
02921 }
02922
02923
02924
02925
02926 void KSpreadCell::paintMoreTextIndicator( QPainter& painter,
02927 const KoRect &cellRect,
02928 QColor &backgroundColor )
02929 {
02930
02931
02932 if( testFlag( Flag_CellTooShortX ) &&
02933 !painter.device()->isExtDev() &&
02934 cellRect.height() > 4.0 &&
02935 cellRect.width() > 4.0 )
02936 {
02937 KSpreadDoc* doc = sheet()->doc();
02938
02939 QColor penColor = Qt::red;
02940
02941 if ( qRed( backgroundColor.rgb() ) > 127 &&
02942 qGreen( backgroundColor.rgb() ) < 80 &&
02943 qBlue( backgroundColor.rgb() ) < 80 )
02944 {
02945 penColor = Qt::blue;
02946 }
02947
02948
02949 QPointArray point( 3 );
02950 if ( d->strOutText.isRightToLeft() ) {
02951 point.setPoint( 0, doc->zoomItX( cellRect.left() + 4.0 ),
02952 doc->zoomItY( cellRect.y() + cellRect.height() / 2.0 -4.0 ) );
02953 point.setPoint( 1, doc->zoomItX( cellRect.left() ),
02954 doc->zoomItY( cellRect.y() + cellRect.height() / 2.0 ));
02955 point.setPoint( 2, doc->zoomItX( cellRect.left() + 4.0 ),
02956 doc->zoomItY( cellRect.y() + cellRect.height() / 2.0 +4.0 ) );
02957 }
02958 else {
02959 point.setPoint( 0, doc->zoomItX( cellRect.right() - 4.0 ),
02960 doc->zoomItY( cellRect.y() + cellRect.height() / 2.0 - 4.0 ) );
02961 point.setPoint( 1, doc->zoomItX( cellRect.right() ),
02962 doc->zoomItY( cellRect.y() + cellRect.height() / 2.0 ) );
02963 point.setPoint( 2, doc->zoomItX( cellRect.right() - 4.0 ),
02964 doc->zoomItY( cellRect.y() + cellRect.height() / 2.0 + 4.0 ) );
02965 }
02966
02967
02968 painter.setBrush( QBrush( penColor ) );
02969 painter.setPen( Qt::NoPen );
02970 painter.drawPolygon( point );
02971 }
02972 }
02973
02974
02975
02976
02977 void KSpreadCell::paintText( QPainter& painter,
02978 const KoRect &cellRect,
02979 const QPoint &cellRef )
02980 {
02981 KSpreadDoc *doc = sheet()->doc();
02982
02983 ColumnFormat *colFormat = m_pSheet->columnFormat( cellRef.x() );
02984
02985 QColorGroup defaultColorGroup = QApplication::palette().active();
02986 QColor textColorPrint = effTextColor( cellRef.x(), cellRef.y() );
02987
02988
02989 if ( !textColorPrint.isValid() ) {
02990 if ( painter.device()->isExtDev() )
02991 textColorPrint = Qt::black;
02992 else
02993 textColorPrint = QApplication::palette().active().text();
02994 }
02995
02996 QPen tmpPen( textColorPrint );
02997
02998
02999 applyZoomedFont( painter, cellRef.x(), cellRef.y() );
03000
03001
03002 if ( !d->hasExtra()
03003 || !d->extra()->conditions
03004 || !d->extra()->conditions->matchedStyle() ) {
03005 if ( value().isNumber()
03006 && !( m_pSheet->getShowFormula()
03007 && !( m_pSheet->isProtected()
03008 && isHideFormula( d->column, d->row ) ) ) )
03009 {
03010 double v = value().asFloat();
03011 if ( floatColor( cellRef.x(), cellRef.y()) == KSpreadCell::NegRed
03012 && v < 0.0 )
03013 tmpPen.setColor( Qt::red );
03014 }
03015 }
03016
03017
03018 if ( !link().isEmpty() ) {
03019 tmpPen.setColor( QApplication::palette().active().link() );
03020 QFont f = painter.font();
03021 f.setUnderline( true );
03022 painter.setFont( f );
03023 }
03024
03025 #if 0
03026
03027
03028
03029
03030
03031
03032
03033
03034
03035
03036
03037
03038
03039
03040
03041
03042 if ( selected && ( cellRef.x() != marker.x() || cellRef.y() != marker.y() ) )
03043 {
03044 QPen p( tmpPen );
03045 p.setColor( defaultColorGroup.highlightedText() );
03046 painter.setPen( p );
03047 }
03048 else {
03049 painter.setPen(tmpPen);
03050 }
03051 #endif
03052 painter.setPen( tmpPen );
03053
03054 QString tmpText = d->strOutText;
03055 double tmpHeight = d->textHeight;
03056 double tmpWidth = d->textWidth;
03057
03058
03059
03060
03061
03062
03063
03064 if ( testFlag( Flag_CellTooShortX ) ) {
03065 d->strOutText = textDisplaying( painter );
03066
03067
03068 textSize( painter );
03069 offsetAlign( column(), row() );
03070 }
03071
03072
03073 if ( m_pSheet->getHideZero()
03074 && value().isNumber()
03075 && value().asFloat() == 0 ) {
03076 d->strOutText = QString::null;
03077 }
03078
03079
03080
03081
03082
03083
03084 if ( colFormat->isHide() || ( cellRect.height() <= 2 ) ) {
03085 freeAllObscuredCells();
03086
03087 d->strOutText = "";
03088 }
03089
03090 double indent = 0.0;
03091 double offsetCellTooShort = 0.0;
03092 int a = effAlignX();
03093
03094
03095 if ( a == KSpreadCell::Left && !isEmpty() ) {
03096
03097
03098
03099
03100
03101 if ( d->hasExtra()
03102 && d->extra()->conditions
03103 && d->extra()->conditions->matchedStyle()
03104 && d->extra()->conditions->matchedStyle()->hasFeature( KSpreadStyle::SIndent, true ) )
03105 indent = d->extra()->conditions->matchedStyle()->indent();
03106 else
03107 indent = getIndent( column(), row() );
03108 }
03109
03110
03111 if ( a == KSpreadCell::Right && !isEmpty() && testFlag( Flag_CellTooShortX ) )
03112 offsetCellTooShort = m_pSheet->doc()->unzoomItX( 4 );
03113
03114 QFontMetrics fm2 = painter.fontMetrics();
03115 double offsetFont = 0.0;
03116
03117 if ( alignY( column(), row() ) == KSpreadCell::Bottom
03118 && textFontUnderline( column(), row() ) )
03119 offsetFont = m_pSheet->doc()->unzoomItX( fm2.underlinePos() + 1 );
03120
03121 int tmpAngle;
03122 bool tmpMultiRow;
03123 bool tmpVerticalText;
03124
03125
03126 if ( d->hasExtra()
03127 && d->extra()->conditions
03128 && d->extra()->conditions->matchedStyle() )
03129 {
03130 KSpreadStyle *matchedStyle = d->extra()->conditions->matchedStyle();
03131
03132 if ( matchedStyle->hasFeature( KSpreadStyle::SAngle, true ) )
03133 tmpAngle = d->extra()->conditions->matchedStyle()->rotateAngle();
03134 else
03135 tmpAngle = getAngle( cellRef.x(), cellRef.y() );
03136
03137 if ( matchedStyle->hasFeature( KSpreadStyle::SVerticalText, true ) )
03138 tmpVerticalText = matchedStyle->hasProperty( KSpreadStyle::PVerticalText );
03139 else
03140 tmpVerticalText = verticalText( cellRef.x(), cellRef.y() );
03141
03142 if ( matchedStyle->hasFeature( KSpreadStyle::SMultiRow, true ) )
03143 tmpMultiRow = matchedStyle->hasProperty( KSpreadStyle::PMultiRow );
03144 else
03145 tmpMultiRow = multiRow( cellRef.x(), cellRef.y() );
03146 }
03147 else {
03148 tmpAngle = getAngle( cellRef.x(), cellRef.y() );
03149 tmpVerticalText = verticalText( cellRef.x(), cellRef.y() );
03150 tmpMultiRow = multiRow( cellRef.x(), cellRef.y() );
03151 }
03152
03153
03154
03155 if ( !tmpMultiRow && !tmpVerticalText && !tmpAngle ) {
03156
03157
03158 painter.drawText( doc->zoomItX( indent + cellRect.x() + d->textX - offsetCellTooShort ),
03159 doc->zoomItY( cellRect.y() + d->textY - offsetFont ), d->strOutText );
03160 }
03161 else if ( tmpAngle != 0 ) {
03162
03163
03164 int angle = tmpAngle;
03165 QFontMetrics fm = painter.fontMetrics();
03166
03167 painter.rotate( angle );
03168 double x;
03169 if ( angle > 0 )
03170 x = indent + cellRect.x() + d->textX;
03171 else
03172 x = indent + cellRect.x() + d->textX
03173 - doc->unzoomItX(( fm.descent() + fm.ascent() ) * sin( angle * M_PI / 180 ));
03174 double y;
03175 if ( angle > 0 )
03176 y = cellRect.y() + d->textY;
03177 else
03178 y = cellRect.y() + d->textY + d->textHeight;
03179 painter.drawText( doc->zoomItX( x * cos( angle * M_PI / 180 ) +
03180 y * sin( angle * M_PI / 180 ) ),
03181 doc->zoomItY( -x * sin( angle * M_PI / 180 ) +
03182 y * cos( angle * M_PI / 180 ) ),
03183 d->strOutText );
03184 painter.rotate( -angle );
03185 }
03186 else if ( tmpMultiRow && !tmpVerticalText ) {
03187
03188
03189 QString t;
03190 int i;
03191 int pos = 0;
03192 double dy = 0.0;
03193 QFontMetrics fm = painter.fontMetrics();
03194 do {
03195 i = d->strOutText.find( "\n", pos );
03196 if ( i == -1 )
03197 t = d->strOutText.mid( pos, d->strOutText.length() - pos );
03198 else {
03199 t = d->strOutText.mid( pos, i - pos );
03200 pos = i + 1;
03201 }
03202
03203 int align = effAlignX();
03204 if ( m_pSheet->getShowFormula()
03205 && !( m_pSheet->isProtected()
03206 && isHideFormula( d->column, d->row ) ) )
03207 align = KSpreadCell::Left;
03208
03209
03210 switch ( align ) {
03211 case KSpreadCell::Left:
03212 d->textX = effLeftBorderPen( cellRef.x(), cellRef.y() ).width() + BORDER_SPACE;
03213 break;
03214
03215 case KSpreadCell::Right:
03216 d->textX = cellRect.width() - BORDER_SPACE - doc->unzoomItX( fm.width( t ) )
03217 - effRightBorderPen( cellRef.x(), cellRef.y() ).width();
03218 break;
03219
03220 case KSpreadCell::Center:
03221 d->textX = ( cellRect.width() - doc->unzoomItX( fm.width( t ) ) ) / 2;
03222 }
03223
03224 painter.drawText( doc->zoomItX( indent + cellRect.x() + d->textX ),
03225 doc->zoomItY( cellRect.y() + d->textY + dy ), t );
03226 dy += doc->unzoomItY( fm.descent() + fm.ascent() );
03227 } while ( i != -1 );
03228 }
03229 else if ( tmpVerticalText && !d->strOutText.isEmpty() ) {
03230
03231
03232 QString t;
03233 int i = 0;
03234 int len = 0;
03235 double dy = 0.0;
03236 QFontMetrics fm = painter.fontMetrics();
03237 do {
03238 len = d->strOutText.length();
03239 t = d->strOutText.at( i );
03240 painter.drawText( doc->zoomItX( indent + cellRect.x() + d->textX ),
03241 doc->zoomItY( cellRect.y() + d->textY + dy ), t );
03242 dy += doc->unzoomItY( fm.descent() + fm.ascent() );
03243 i++;
03244 } while ( i != len );
03245 }
03246
03247
03248 if ( testFlag( Flag_CellTooShortX ) ) {
03249 d->strOutText = tmpText;
03250 d->textHeight = tmpHeight;
03251 d->textWidth = tmpWidth;
03252 }
03253
03254 if ( m_pSheet->getHideZero() && value().isNumber()
03255 && value().asFloat() == 0 )
03256 d->strOutText = tmpText;
03257
03258 if ( colFormat->isHide() || ( cellRect.height() <= 2 ) )
03259 d->strOutText = tmpText;
03260 }
03261
03262
03263
03264
03265 void KSpreadCell::paintPageBorders( QPainter& painter,
03266 const KoRect &cellRect,
03267 const QPoint &cellRef,
03268 bool paintBorderRight,
03269 bool paintBorderBottom )
03270 {
03271
03272 if ( painter.device()->isExtDev() )
03273 return;
03274
03275 if ( ! m_pSheet->isShowPageBorders() )
03276 return;
03277
03278 KSpreadSheetPrint* print = m_pSheet->print();
03279
03280 KSpreadSheet::LayoutDirection sheetDir = m_pSheet->layoutDirection();
03281
03282 KSpreadDoc* doc = sheet()->doc();
03283 int zcellRect_left = doc->zoomItX (cellRect.left());
03284 int zcellRect_right = doc->zoomItX (cellRect.right());
03285 int zcellRect_top = doc->zoomItY (cellRect.top());
03286 int zcellRect_bottom = doc->zoomItY (cellRect.bottom());
03287
03288
03289
03290 if ( cellRef.x() >= print->printRange().left() &&
03291 cellRef.x() <= print->printRange().right() + 1 &&
03292 cellRef.y() >= print->printRange().top() &&
03293 cellRef.y() <= print->printRange().bottom() + 1 )
03294 {
03295 if ( print->isOnNewPageX( cellRef.x() ) &&
03296 ( cellRef.y() <= print->printRange().bottom() ) )
03297 {
03298 painter.setPen( sheet()->doc()->pageBorderColor() );
03299
03300 if ( sheetDir == KSpreadSheet::RightToLeft )
03301 painter.drawLine( zcellRect_right, zcellRect_top,
03302 zcellRect_right, zcellRect_bottom );
03303 else
03304 painter.drawLine( zcellRect_left, zcellRect_top,
03305 zcellRect_left, zcellRect_bottom );
03306 }
03307
03308 if ( print->isOnNewPageY( cellRef.y() ) &&
03309 ( cellRef.x() <= print->printRange().right() ) )
03310 {
03311 painter.setPen( sheet()->doc()->pageBorderColor() );
03312 painter.drawLine( zcellRect_left, zcellRect_top,
03313 zcellRect_right, zcellRect_top );
03314 }
03315
03316 if ( paintBorderRight ) {
03317 if ( print->isOnNewPageX( cellRef.x() + 1 )
03318 && ( cellRef.y() <= print->printRange().bottom() ) ) {
03319 painter.setPen( sheet()->doc()->pageBorderColor() );
03320
03321 if ( sheetDir == KSpreadSheet::RightToLeft )
03322 painter.drawLine( zcellRect_left, zcellRect_top,
03323 zcellRect_left, zcellRect_bottom );
03324 else
03325 painter.drawLine( zcellRect_right, zcellRect_top,
03326 zcellRect_right, zcellRect_bottom );
03327 }
03328 }
03329
03330 if ( paintBorderBottom ) {
03331 if ( print->isOnNewPageY( cellRef.y() + 1 )
03332 && ( cellRef.x() <= print->printRange().right() ) ) {
03333 painter.setPen( sheet()->doc()->pageBorderColor() );
03334 painter.drawLine( zcellRect_left, zcellRect_bottom,
03335 zcellRect_right, zcellRect_bottom );
03336 }
03337 }
03338 }
03339 }
03340
03341
03342
03343
03344 void KSpreadCell::paintCellBorders( QPainter& painter, const KoRect& rect,
03345 const KoRect &cellRect,
03346 const QPoint &cellRef,
03347 bool paintRight, bool paintBottom,
03348 bool paintLeft, bool paintTop,
03349 QPen & _rightPen, QPen & _bottomPen,
03350 QPen & _leftPen, QPen & _topPen )
03351 {
03352 KSpreadDoc * doc = sheet()->doc();
03353
03354 KSpreadSheet::LayoutDirection sheetDir = m_pSheet->layoutDirection();
03355
03356
03357
03358
03359 int zrect_left (doc->zoomItX (rect.left()));
03360 int zrect_right (doc->zoomItX (rect.right()));
03361 int zrect_top (doc->zoomItY (rect.top()));
03362 int zrect_bottom (doc->zoomItY (rect.bottom()));
03363 int zcellRect_left (doc->zoomItX (cellRect.left()));
03364 int zcellRect_right (doc->zoomItX (cellRect.right()));
03365 int zcellRect_top (doc->zoomItY (cellRect.top()));
03366 int zcellRect_bottom (doc->zoomItY (cellRect.bottom()));
03367
03368
03369
03370
03371
03372
03373
03374
03375
03376
03377
03378
03379 if (d->hasExtra()) {
03380 QValueList<KSpreadCell*>::const_iterator it = d->extra()->obscuringCells.begin();
03381 QValueList<KSpreadCell*>::const_iterator end = d->extra()->obscuringCells.end();
03382 for ( ; it != end; ++it ) {
03383 KSpreadCell* cell = *it;
03384
03385 int xDiff = cellRef.x() - cell->column();
03386 int yDiff = cellRef.y() - cell->row();
03387 paintLeft = paintLeft && xDiff == 0;
03388 paintTop = paintTop && yDiff == 0;
03389
03390
03391
03392 paintRight = paintRight && cell->mergedXCells() == xDiff;
03393 paintBottom = paintBottom && cell->mergedYCells() == yDiff;
03394 }
03395 }
03396
03397
03398
03399 QPen leftPen( _leftPen );
03400 QPen rightPen( _rightPen );
03401 QPen topPen( _topPen );
03402 QPen bottomPen( _bottomPen );
03403
03404
03405
03406
03407 int left_penWidth = QMAX( 1, doc->zoomItX( leftPen.width() ) );
03408 int right_penWidth = QMAX( 1, doc->zoomItX( rightPen.width() ) );
03409 int top_penWidth = QMAX( 1, doc->zoomItY( topPen.width() ) );
03410 int bottom_penWidth = QMAX( 1, doc->zoomItY( bottomPen.width() ) );
03411
03412 leftPen.setWidth( left_penWidth );
03413 rightPen.setWidth( right_penWidth );
03414 topPen.setWidth( top_penWidth );
03415 bottomPen.setWidth( bottom_penWidth );
03416
03417 if ( paintLeft && leftPen.style() != Qt::NoPen ) {
03418 int top = ( QMAX( 0, -1 + top_penWidth ) ) / 2 +
03419 ( ( QMAX( 0, -1 + top_penWidth ) ) % 2 );
03420 int bottom = ( QMAX( 0, -1 + bottom_penWidth ) ) / 2 + 1;
03421
03422 painter.setPen( leftPen );
03423
03424
03425
03426
03427
03428 if ( painter.device()->isExtDev() ) {
03429
03430
03431
03432
03433
03434
03435
03436
03437
03438
03439 if ( sheetDir == KSpreadSheet::RightToLeft )
03440 painter.drawLine( QMIN( zrect_right, zcellRect_right ),
03441 QMAX( zrect_top, zcellRect_top - top ),
03442 QMIN( zrect_right, zcellRect_right ),
03443 QMIN( zrect_bottom, zcellRect_bottom + bottom ) );
03444 else
03445 painter.drawLine( QMAX( zrect_left, zcellRect_left ),
03446 QMAX( zrect_top, zcellRect_top - top ),
03447 QMAX( zrect_left, zcellRect_left ),
03448 QMIN( zrect_bottom, zcellRect_bottom + bottom ) );
03449 }
03450 else {
03451 if ( sheetDir == KSpreadSheet::RightToLeft )
03452 painter.drawLine( zcellRect_right,
03453 zcellRect_top - top,
03454 zcellRect_right,
03455 zcellRect_bottom + bottom );
03456 else
03457 painter.drawLine( zcellRect_left,
03458 zcellRect_top - top,
03459 zcellRect_left,
03460 zcellRect_bottom + bottom );
03461 }
03462 }
03463
03464 if ( paintRight && rightPen.style() != Qt::NoPen ) {
03465 int top = ( QMAX( 0, -1 + top_penWidth ) ) / 2 +
03466 ( ( QMAX( 0, -1 + top_penWidth ) ) % 2 );
03467 int bottom = ( QMAX( 0, -1 + bottom_penWidth ) ) / 2 + 1;
03468
03469 painter.setPen( rightPen );
03470
03471
03472
03473
03474
03475 if ( painter.device()->isExtDev() ) {
03476 if ( sheetDir == KSpreadSheet::RightToLeft )
03477 painter.drawLine( QMAX( zrect_left, zcellRect_left ),
03478 QMAX( zrect_top, zcellRect_top - top ),
03479 QMAX( zrect_left, zcellRect_left ),
03480 QMIN( zrect_bottom, zcellRect_bottom + bottom ) );
03481 else {
03482
03483
03484
03485
03486 if ( zcellRect_right <= zrect_right + right_penWidth / 2)
03487 painter.drawLine( zcellRect_right,
03488 QMAX( zrect_top, zcellRect_top - top ),
03489 zcellRect_right,
03490 QMIN( zrect_bottom, zcellRect_bottom + bottom ) );
03491 }
03492 }
03493 else {
03494 if ( sheetDir == KSpreadSheet::RightToLeft )
03495 painter.drawLine( zcellRect_left,
03496 zcellRect_top - top,
03497 zcellRect_left,
03498 zcellRect_bottom + bottom );
03499 else
03500 painter.drawLine( zcellRect_right,
03501 zcellRect_top - top,
03502 zcellRect_right,
03503 zcellRect_bottom + bottom );
03504 }
03505 }
03506
03507 if ( paintTop && topPen.style() != Qt::NoPen ) {
03508 painter.setPen( topPen );
03509
03510
03511
03512
03513
03514
03515
03516 if ( painter.device()->isExtDev() ) {
03517 if ( zcellRect_top >= zrect_top + top_penWidth / 2)
03518 painter.drawLine( QMAX( zrect_left, zcellRect_left ),
03519 zcellRect_top,
03520 QMIN( zrect_right, zcellRect_right ),
03521 zcellRect_top );
03522 }
03523 else {
03524 painter.drawLine( zcellRect_left, zcellRect_top,
03525 zcellRect_right, zcellRect_top );
03526 }
03527 }
03528
03529 if ( paintBottom && bottomPen.style() != Qt::NoPen ) {
03530 painter.setPen( bottomPen );
03531
03532
03533
03534
03535
03536
03537
03538 if ( painter.device()->isExtDev() ) {
03539 if ( zcellRect_bottom <= zrect_bottom + bottom_penWidth / 2)
03540 painter.drawLine( QMAX( zrect_left, zcellRect_left ),
03541 zcellRect_bottom,
03542 QMIN( zrect_right, zcellRect_right ),
03543 zcellRect_bottom );
03544 }
03545 else {
03546 painter.drawLine( zcellRect_left, zcellRect_bottom,
03547 zcellRect_right, zcellRect_bottom );
03548 }
03549 }
03550
03551
03552
03553
03554
03555
03556
03557 return;
03558
03559
03560
03561
03562
03563 QPen vert_pen, horz_pen;
03564 int vert_penWidth, horz_penWidth;
03565
03566
03567 KSpreadCell *cell_north = m_pSheet->cellAt( cellRef.x(),
03568 cellRef.y() - 1 );
03569 KSpreadCell *cell_northwest = m_pSheet->cellAt( cellRef.x() - 1,
03570 cellRef.y() - 1 );
03571 KSpreadCell *cell_west = m_pSheet->cellAt( cellRef.x() - 1,
03572 cellRef.y() );
03573 KSpreadCell *cell_northeast = m_pSheet->cellAt( cellRef.x() + 1,
03574 cellRef.y() - 1 );
03575 KSpreadCell *cell_east = m_pSheet->cellAt( cellRef.x() + 1,
03576 cellRef.y() );
03577 KSpreadCell *cell_south = m_pSheet->cellAt( cellRef.x(),
03578 cellRef.y() + 1 );
03579 KSpreadCell *cell_southwest = m_pSheet->cellAt( cellRef.x() - 1,
03580 cellRef.y() + 1 );
03581 KSpreadCell *cell_southeast = m_pSheet->cellAt( cellRef.x() + 1,
03582 cellRef.y() + 1 );
03583
03584
03585 if ( cell_north->effLeftBorderValue( cellRef.x(), cellRef.y() - 1 )
03586 >= cell_northwest->effRightBorderValue( cellRef.x() - 1, cellRef.y() - 1 ) )
03587 vert_pen = cell_north->effLeftBorderPen( cellRef.x(), cellRef.y() - 1 );
03588 else
03589 vert_pen = cell_northwest->effRightBorderPen( cellRef.x() - 1,
03590 cellRef.y() - 1 );
03591
03592 vert_penWidth = QMAX( 1, doc->zoomItX( vert_pen.width() ) );
03593 vert_pen.setWidth( vert_penWidth );
03594
03595 if ( vert_pen.style() != Qt::NoPen ) {
03596 if ( cell_west->effTopBorderValue( cellRef.x() - 1, cellRef.y() )
03597 >= cell_northwest->effBottomBorderValue( cellRef.x() - 1, cellRef.y() - 1 ) )
03598 horz_pen = cell_west->effTopBorderPen( cellRef.x() - 1, cellRef.y() );
03599 else
03600 horz_pen = cell_northwest->effBottomBorderPen( cellRef.x() - 1,
03601 cellRef.y() - 1 );
03602
03603 horz_penWidth = QMAX( 1, doc->zoomItY( horz_pen.width() ) );
03604 int bottom = ( QMAX( 0, -1 + horz_penWidth ) ) / 2 + 1;
03605
03606 painter.setPen( vert_pen );
03607
03608
03609 if ( painter.device()->isExtDev() ) {
03610 if ( sheetDir == KSpreadSheet::RightToLeft )
03611 painter.drawLine( QMAX( zrect_left, zcellRect_right ),
03612 QMAX( zrect_top, zcellRect_top ),
03613 QMIN( zrect_right, zcellRect_right ),
03614 QMIN( zrect_bottom, zcellRect_top + bottom ) );
03615 else
03616 painter.drawLine( QMAX( zrect_left, zcellRect_left ),
03617 QMAX( zrect_top, zcellRect_top ),
03618 QMIN( zrect_right, zcellRect_left ),
03619 QMIN( zrect_bottom, zcellRect_top + bottom ) );
03620 }
03621 else {
03622 if ( sheetDir == KSpreadSheet::RightToLeft )
03623 painter.drawLine( zcellRect_right, zcellRect_top,
03624 zcellRect_right, zcellRect_top + bottom );
03625 else
03626 painter.drawLine( zcellRect_left, zcellRect_top,
03627 zcellRect_left, zcellRect_top + bottom );
03628 }
03629 }
03630
03631
03632 if ( cell_north->effRightBorderValue( cellRef.x(), cellRef.y() - 1 )
03633 >= cell_northeast->effLeftBorderValue( cellRef.x() + 1,
03634 cellRef.y() - 1 ) )
03635 vert_pen = cell_north->effRightBorderPen( cellRef.x(), cellRef.y() - 1 );
03636 else
03637 vert_pen = cell_northeast->effLeftBorderPen( cellRef.x() + 1,
03638 cellRef.y() - 1 );
03639
03640
03641 vert_penWidth = QMAX( 1, doc->zoomItX( vert_pen.width() ) );
03642 vert_pen.setWidth( vert_penWidth );
03643 if ( ( vert_pen.style() != Qt::NoPen ) && ( cellRef.x() < KS_colMax ) ) {
03644 if ( cell_east->effTopBorderValue( cellRef.x() + 1, cellRef.y() )
03645 >= cell_northeast->effBottomBorderValue( cellRef.x() + 1,
03646 cellRef.y() - 1 ) )
03647 horz_pen = cell_east->effTopBorderPen( cellRef.x() + 1, cellRef.y() );
03648 else
03649 horz_pen = cell_northeast->effBottomBorderPen( cellRef.x() + 1,
03650 cellRef.y() - 1 );
03651
03652
03653 horz_penWidth = QMAX( 1, doc->zoomItY( horz_pen.width() ) );
03654 int bottom = ( QMAX( 0, -1 + horz_penWidth ) ) / 2 + 1;
03655
03656 painter.setPen( vert_pen );
03657
03658
03659 if ( painter.device()->isExtDev() ) {
03660 if ( sheetDir == KSpreadSheet::RightToLeft )
03661 painter.drawLine( QMAX( zrect_left, zcellRect_left ),
03662 QMAX( zrect_top, zcellRect_top ),
03663 QMIN( zrect_right, zcellRect_left ),
03664 QMIN( zrect_bottom, zcellRect_top + bottom ) );
03665 else
03666 painter.drawLine( QMAX( zrect_left, zcellRect_right ),
03667 QMAX( zrect_top, zcellRect_top ),
03668 QMIN( zrect_right, zcellRect_right ),
03669 QMIN( zrect_bottom, zcellRect_top + bottom ) );
03670 }
03671 else {
03672 if ( sheetDir == KSpreadSheet::RightToLeft )
03673 painter.drawLine( zcellRect_left, zcellRect_top,
03674 zcellRect_left, zcellRect_top + bottom );
03675 else
03676 painter.drawLine( zcellRect_right, zcellRect_top,
03677 zcellRect_right, zcellRect_top + bottom );
03678 }
03679 }
03680
03681
03682 if ( cellRef.y() < KS_rowMax ) {
03683
03684 if ( cell_south->effLeftBorderValue( cellRef.x(), cellRef.y() + 1 )
03685 >= cell_southwest->effRightBorderValue( cellRef.x() - 1,
03686 cellRef.y() + 1 ) )
03687 vert_pen = cell_south->effLeftBorderPen( cellRef.x(), cellRef.y() + 1 );
03688 else
03689 vert_pen = cell_southwest->effRightBorderPen( cellRef.x() - 1,
03690 cellRef.y() + 1 );
03691
03692
03693 vert_penWidth = QMAX( 1, doc->zoomItY( vert_pen.width() ) );
03694 vert_pen.setWidth( vert_penWidth );
03695 if ( vert_pen.style() != Qt::NoPen ) {
03696 if ( cell_west->effBottomBorderValue( cellRef.x() - 1, cellRef.y() )
03697 >= cell_southwest->effTopBorderValue( cellRef.x() - 1,
03698 cellRef.y() + 1 ) )
03699 horz_pen = cell_west->effBottomBorderPen( cellRef.x() - 1,
03700 cellRef.y() );
03701 else
03702 horz_pen = cell_southwest->effTopBorderPen( cellRef.x() - 1,
03703 cellRef.y() + 1 );
03704
03705
03706 horz_penWidth = QMAX( 1, doc->zoomItX( horz_pen.width() ) );
03707 int bottom = ( QMAX( 0, -1 + horz_penWidth ) ) / 2;
03708
03709 painter.setPen( vert_pen );
03710
03711
03712 if ( painter.device()->isExtDev() ) {
03713 if ( sheetDir == KSpreadSheet::RightToLeft )
03714 painter.drawLine( QMAX( zrect_left, zcellRect_right ),
03715 QMAX( zrect_top, zcellRect_bottom - bottom ),
03716 QMIN( zrect_right, zcellRect_right ),
03717 QMIN( zrect_bottom, zcellRect_bottom ) );
03718 else
03719 painter.drawLine( QMAX( zrect_left, zcellRect_left ),
03720 QMAX( zrect_top, zcellRect_bottom - bottom ),
03721 QMIN( zrect_right, zcellRect_left ),
03722 QMIN( zrect_bottom, zcellRect_bottom ) );
03723 }
03724 else {
03725 if ( sheetDir == KSpreadSheet::RightToLeft )
03726 painter.drawLine( zcellRect_right, zcellRect_bottom - bottom,
03727 zcellRect_right, zcellRect_bottom );
03728 else
03729 painter.drawLine( zcellRect_left, zcellRect_bottom - bottom,
03730 zcellRect_left, zcellRect_bottom );
03731 }
03732 }
03733
03734
03735 if ( cell_south->effRightBorderValue( cellRef.x(), cellRef.y() + 1 )
03736 >= cell_southeast->effLeftBorderValue( cellRef.x() + 1,
03737 cellRef.y() + 1 ) )
03738 vert_pen = cell_south->effRightBorderPen( cellRef.x(), cellRef.y() + 1 );
03739 else
03740 vert_pen = cell_southeast->effLeftBorderPen( cellRef.x() + 1,
03741 cellRef.y() + 1 );
03742
03743
03744 vert_penWidth = QMAX( 1, doc->zoomItY( vert_pen.width() ) );
03745 vert_pen.setWidth( vert_penWidth );
03746 if ( ( vert_pen.style() != Qt::NoPen ) && ( cellRef.x() < KS_colMax ) ) {
03747 if ( cell_east ->effBottomBorderValue( cellRef.x() + 1, cellRef.y() )
03748 >= cell_southeast->effTopBorderValue( cellRef.x() + 1,
03749 cellRef.y() + 1 ) )
03750
03751 horz_pen = m_pSheet->cellAt( cellRef.x() + 1, cellRef.y() )
03752 ->effBottomBorderPen( cellRef.x() + 1, cellRef.y() );
03753 else
03754 horz_pen = m_pSheet->cellAt( cellRef.x() + 1, cellRef.y() + 1 )
03755 ->effTopBorderPen( cellRef.x() + 1, cellRef.y() + 1 );
03756
03757
03758 horz_penWidth = QMAX( 1, doc->zoomItX( horz_pen.width() ) );
03759 int bottom = ( QMAX( 0, -1 + horz_penWidth ) ) / 2;
03760
03761 painter.setPen( vert_pen );
03762
03763
03764 if ( painter.device()->isExtDev() ) {
03765 if ( sheetDir == KSpreadSheet::RightToLeft )
03766 painter.drawLine( QMAX( zrect_left, zcellRect_left ),
03767 QMAX( zrect_top, zcellRect_bottom - bottom ),
03768 QMIN( zrect_right, zcellRect_left ),
03769 QMIN( zrect_bottom, zcellRect_bottom ) );
03770 else
03771 painter.drawLine( QMAX( zrect_left, zcellRect_right ),
03772 QMAX( zrect_top, zcellRect_bottom - bottom ),
03773 QMIN( zrect_right, zcellRect_right ),
03774 QMIN( zrect_bottom, zcellRect_bottom ) );
03775 }
03776 else {
03777 if ( sheetDir == KSpreadSheet::RightToLeft )
03778 painter.drawLine( zcellRect_left, zcellRect_bottom - bottom,
03779 zcellRect_left, zcellRect_bottom );
03780 else
03781 painter.drawLine( zcellRect_right, zcellRect_bottom - bottom,
03782 zcellRect_right, zcellRect_bottom );
03783 }
03784 }
03785 }
03786 }
03787
03788
03789
03790
03791 void KSpreadCell::paintCellDiagonalLines( QPainter& painter,
03792 const KoRect &cellRect,
03793 const QPoint &cellRef )
03794 {
03795 if ( isObscuringForced() )
03796 return;
03797
03798 KSpreadDoc* doc = sheet()->doc();
03799
03800 if ( effFallDiagonalPen( cellRef.x(), cellRef.y() ).style() != Qt::NoPen ) {
03801 painter.setPen( effFallDiagonalPen( cellRef.x(), cellRef.y() ) );
03802 painter.drawLine( doc->zoomItX( cellRect.x() ),
03803 doc->zoomItY( cellRect.y() ),
03804 doc->zoomItX( cellRect.right() ),
03805 doc->zoomItY( cellRect.bottom() ) );
03806 }
03807
03808 if ( effGoUpDiagonalPen( cellRef.x(), cellRef.y() ).style() != Qt::NoPen ) {
03809 painter.setPen( effGoUpDiagonalPen( cellRef.x(), cellRef.y() ) );
03810 painter.drawLine( doc->zoomItX( cellRect.x() ),
03811 doc->zoomItY( cellRect.bottom() ),
03812 doc->zoomItX( cellRect.right() ),
03813 doc->zoomItY( cellRect.y() ) );
03814 }
03815 }
03816
03817
03818
03819
03820
03821
03822 int KSpreadCell::defineAlignX()
03823 {
03824 int a = align( column(), row() );
03825 if ( a == KSpreadCell::Undefined )
03826 {
03827
03828 if ((formatType() == Text_format) || value().isString())
03829 a = (d->strOutText.isRightToLeft()) ?
03830 KSpreadCell::Right : KSpreadCell::Left;
03831 else
03832 if (value().isBoolean() || value().isNumber())
03833 a = KSpreadCell::Right;
03834 else
03835 a = KSpreadCell::Left;
03836 }
03837 return a;
03838 }
03839
03840 int KSpreadCell::effAlignX()
03841 {
03842 if ( d->hasExtra() && d->extra()->conditions
03843 && d->extra()->conditions->matchedStyle()
03844 && d->extra()->conditions->matchedStyle()->hasFeature( KSpreadStyle::SAlignX, true ) )
03845 return d->extra()->conditions->matchedStyle()->alignX();
03846
03847 return defineAlignX();
03848 }
03849
03850
03851
03852
03853
03854
03855 QString KSpreadCell::textDisplaying( QPainter &_painter )
03856 {
03857 QFontMetrics fm = _painter.fontMetrics();
03858 int a = align( column(), row() );
03859
03860
03861
03862
03863
03864 if ( value().isNumber() )
03865 d->strOutText = "#####################################################";
03866
03867 if ( !verticalText( column(),row() ) ) {
03868
03869
03870
03871 double len = 0.0;
03872 int extraXCells = d->hasExtra() ? d->extra()->extraXCells : 0;
03873
03874 for ( int i = column(); i <= column() + extraXCells; i++ ) {
03875 ColumnFormat *cl2 = m_pSheet->columnFormat( i );
03876 len += cl2->dblWidth() - 1.0;
03877 }
03878
03879 QString tmp;
03880 double tmpIndent = 0.0;
03881 if ( !isEmpty() )
03882 tmpIndent = getIndent( column(), row() );
03883
03884
03885
03886 for ( int i = d->strOutText.length(); i != 0; i-- ) {
03887 if ( a == KSpreadCell::Left || a == KSpreadCell::Undefined )
03888 tmp = d->strOutText.left(i);
03889 else if ( a == KSpreadCell::Right)
03890 tmp = d->strOutText.right(i);
03891 else
03892 tmp = d->strOutText.mid( ( d->strOutText.length() - i ) / 2, i);
03893
03894
03895 if ( m_pSheet->doc()->unzoomItX( fm.width( tmp ) ) + tmpIndent
03896 < len - 4.0 - 1.0 )
03897 {
03898 if ( getAngle( column(), row() ) != 0 ) {
03899 QString tmp2;
03900 RowFormat *rl = m_pSheet->rowFormat( row() );
03901 if ( d->textHeight > rl->dblHeight() ) {
03902 for ( int j = d->strOutText.length(); j != 0; j-- ) {
03903 tmp2 = d->strOutText.left( j );
03904 if ( m_pSheet->doc()->unzoomItY( fm.width( tmp2 ) )
03905 < rl->dblHeight() - 1.0 )
03906 {
03907 return d->strOutText.left( QMIN( tmp.length(), tmp2.length() ) );
03908 }
03909 }
03910 }
03911 else
03912 return tmp;
03913
03914 }
03915 else
03916 return tmp;
03917 }
03918 }
03919 return QString( "" );
03920 }
03921 else if ( verticalText( column(), row() ) ) {
03922
03923
03924 RowFormat *rl = m_pSheet->rowFormat( row() );
03925 double tmpIndent = 0.0;
03926
03927
03928 double len = 0.0;
03929 int extraXCells = d->hasExtra() ? d->extra()->extraXCells : 0;
03930
03931 for ( int i = column(); i <= column() + extraXCells; i++ ) {
03932 ColumnFormat *cl2 = m_pSheet->columnFormat( i );
03933
03934
03935 len += cl2->dblWidth() - 1.0;
03936 }
03937
03938 if ( !isEmpty() )
03939 tmpIndent = getIndent( column(), row() );
03940
03941 if ( ( d->textWidth + tmpIndent > len ) || d->textWidth == 0.0 )
03942 return QString( "" );
03943
03944 for ( int i = d->strOutText.length(); i != 0; i-- ) {
03945 if ( m_pSheet->doc()->unzoomItY( fm.ascent() + fm.descent() ) * i
03946 < rl->dblHeight() - 1.0 )
03947 return d->strOutText.left( i );
03948 }
03949
03950 return QString( "" );
03951 }
03952
03953 ColumnFormat *cl = m_pSheet->columnFormat( column() );
03954 double w = cl->dblWidth();
03955
03956 if ( d->hasExtra() && (d->extra()->extraWidth != 0.0) )
03957 w = d->extra()->extraWidth;
03958
03959 QString tmp;
03960 for ( int i = d->strOutText.length(); i != 0; i-- ) {
03961 tmp = d->strOutText.left( i );
03962
03963
03964 if ( m_pSheet->doc()->unzoomItX( fm.width( tmp ) ) < w - 4.0 - 1.0 )
03965 return tmp;
03966 }
03967
03968 return QString::null;
03969 }
03970
03971
03972 double KSpreadCell::dblWidth( int _col, const KSpreadCanvas *_canvas ) const
03973 {
03974 if ( _col < 0 )
03975 _col = d->column;
03976
03977 if ( _canvas )
03978 {
03979 if ( testFlag(Flag_ForceExtra) )
03980 return d->extra()->extraWidth;
03981
03982 const ColumnFormat *cl = m_pSheet->columnFormat( _col );
03983 return cl->dblWidth( _canvas );
03984 }
03985
03986 if ( testFlag(Flag_ForceExtra) )
03987 return d->extra()->extraWidth;
03988
03989 const ColumnFormat *cl = m_pSheet->columnFormat( _col );
03990 return cl->dblWidth();
03991 }
03992
03993 int KSpreadCell::width( int _col, const KSpreadCanvas *_canvas ) const
03994 {
03995 return int( dblWidth( _col, _canvas ) );
03996 }
03997
03998 double KSpreadCell::dblHeight( int _row, const KSpreadCanvas *_canvas ) const
03999 {
04000 if ( _row < 0 )
04001 _row = d->row;
04002
04003 if ( _canvas )
04004 {
04005 if ( testFlag(Flag_ForceExtra) )
04006 return d->extra()->extraHeight;
04007
04008 const RowFormat *rl = m_pSheet->rowFormat( _row );
04009 return rl->dblHeight( _canvas );
04010 }
04011
04012 if ( testFlag(Flag_ForceExtra) )
04013 return d->extra()->extraHeight;
04014
04015 const RowFormat *rl = m_pSheet->rowFormat( _row );
04016 return rl->dblHeight();
04017 }
04018
04019 int KSpreadCell::height( int _row, const KSpreadCanvas *_canvas ) const
04020 {
04021 return int( dblHeight( _row, _canvas ) );
04022 }
04023
04025
04026
04027
04028
04030
04031 const QBrush& KSpreadCell::backGroundBrush( int _col, int _row ) const
04032 {
04033 if ( d->hasExtra() && (!d->extra()->obscuringCells.isEmpty()) )
04034 {
04035 const KSpreadCell* cell = d->extra()->obscuringCells.first();
04036 return cell->backGroundBrush( cell->column(), cell->row() );
04037 }
04038
04039 return KSpreadFormat::backGroundBrush( _col, _row );
04040 }
04041
04042 const QColor& KSpreadCell::bgColor( int _col, int _row ) const
04043 {
04044 if ( d->hasExtra() && (!d->extra()->obscuringCells.isEmpty()) )
04045 {
04046 const KSpreadCell* cell = d->extra()->obscuringCells.first();
04047 return cell->bgColor( cell->column(), cell->row() );
04048 }
04049
04050 return KSpreadFormat::bgColor( _col, _row );
04051 }
04052
04054
04055
04056
04057
04059
04060 void KSpreadCell::setLeftBorderPen( const QPen& p )
04061 {
04062 if ( column() == 1 )
04063 {
04064 KSpreadCell* cell = m_pSheet->cellAt( column() - 1, row() );
04065 if ( cell && cell->hasProperty( PRightBorder )
04066 && m_pSheet->cellAt( column(), row() ) == this )
04067 cell->clearProperty( PRightBorder );
04068 }
04069
04070 KSpreadFormat::setLeftBorderPen( p );
04071 }
04072
04073 void KSpreadCell::setTopBorderPen( const QPen& p )
04074 {
04075 if ( row() == 1 )
04076 {
04077 KSpreadCell* cell = m_pSheet->cellAt( column(), row() - 1 );
04078 if ( cell && cell->hasProperty( PBottomBorder )
04079 && m_pSheet->cellAt( column(), row() ) == this )
04080 cell->clearProperty( PBottomBorder );
04081 }
04082 KSpreadFormat::setTopBorderPen( p );
04083 }
04084
04085 void KSpreadCell::setRightBorderPen( const QPen& p )
04086 {
04087 KSpreadCell* cell = 0L;
04088 if ( column() < KS_colMax )
04089 cell = m_pSheet->cellAt( column() + 1, row() );
04090
04091 if ( cell && cell->hasProperty( PLeftBorder )
04092 && m_pSheet->cellAt( column(), row() ) == this )
04093 cell->clearProperty( PLeftBorder );
04094
04095 KSpreadFormat::setRightBorderPen( p );
04096 }
04097
04098 void KSpreadCell::setBottomBorderPen( const QPen& p )
04099 {
04100 KSpreadCell* cell = 0L;
04101 if ( row() < KS_rowMax )
04102 cell = m_pSheet->cellAt( column(), row() + 1 );
04103
04104 if ( cell && cell->hasProperty( PTopBorder )
04105 && m_pSheet->cellAt( column(), row() ) == this )
04106 cell->clearProperty( PTopBorder );
04107
04108 KSpreadFormat::setBottomBorderPen( p );
04109 }
04110
04111 const QPen& KSpreadCell::rightBorderPen( int _col, int _row ) const
04112 {
04113 if ( !hasProperty( PRightBorder ) && ( _col < KS_colMax ) )
04114 {
04115 KSpreadCell * cell = m_pSheet->cellAt( _col + 1, _row );
04116 if ( cell && cell->hasProperty( PLeftBorder ) )
04117 return cell->leftBorderPen( _col + 1, _row );
04118 }
04119
04120 return KSpreadFormat::rightBorderPen( _col, _row );
04121 }
04122
04123 const QPen& KSpreadCell::leftBorderPen( int _col, int _row ) const
04124 {
04125 if ( !hasProperty( PLeftBorder ) )
04126 {
04127 const KSpreadCell * cell = m_pSheet->cellAt( _col - 1, _row );
04128 if ( cell && cell->hasProperty( PRightBorder ) )
04129 return cell->rightBorderPen( _col - 1, _row );
04130 }
04131
04132 return KSpreadFormat::leftBorderPen( _col, _row );
04133 }
04134
04135 const QPen& KSpreadCell::bottomBorderPen( int _col, int _row ) const
04136 {
04137 if ( !hasProperty( PBottomBorder ) && ( _row < KS_rowMax ) )
04138 {
04139 const KSpreadCell * cell = m_pSheet->cellAt( _col, _row + 1 );
04140 if ( cell && cell->hasProperty( PTopBorder ) )
04141 return cell->topBorderPen( _col, _row + 1 );
04142 }
04143
04144 return KSpreadFormat::bottomBorderPen( _col, _row );
04145 }
04146
04147 const QPen& KSpreadCell::topBorderPen( int _col, int _row ) const
04148 {
04149 if ( !hasProperty( PTopBorder ) )
04150 {
04151 const KSpreadCell * cell = m_pSheet->cellAt( _col, _row - 1 );
04152 if ( cell->hasProperty( PBottomBorder ) )
04153 return cell->bottomBorderPen( _col, _row - 1 );
04154 }
04155
04156 return KSpreadFormat::topBorderPen( _col, _row );
04157 }
04158
04159 const QColor & KSpreadCell::effTextColor( int col, int row ) const
04160 {
04161 if ( d->hasExtra() && d->extra()->conditions
04162 && d->extra()->conditions->matchedStyle()
04163 && d->extra()->conditions->matchedStyle()->hasFeature( KSpreadStyle::STextPen, true ) )
04164 return d->extra()->conditions->matchedStyle()->pen().color();
04165
04166 return textColor( col, row );
04167 }
04168
04169 const QPen& KSpreadCell::effLeftBorderPen( int col, int row ) const
04170 {
04171 if ( isObscuringForced() )
04172 {
04173 KSpreadCell * cell = d->extra()->obscuringCells.first();
04174 return cell->effLeftBorderPen( cell->column(), cell->row() );
04175 }
04176
04177 if ( d->hasExtra() && d->extra()->conditions
04178 && d->extra()->conditions->matchedStyle()
04179 && d->extra()->conditions->matchedStyle()->hasFeature( KSpreadStyle::SLeftBorder, true ) )
04180 return d->extra()->conditions->matchedStyle()->leftBorderPen();
04181
04182 return KSpreadFormat::leftBorderPen( col, row );
04183 }
04184
04185 const QPen& KSpreadCell::effTopBorderPen( int col, int row ) const
04186 {
04187 if ( isObscuringForced() )
04188 {
04189 KSpreadCell * cell = d->extra()->obscuringCells.first();
04190 return cell->effTopBorderPen( cell->column(), cell->row() );
04191 }
04192
04193 if ( d->hasExtra() && d->extra()->conditions
04194 && d->extra()->conditions->matchedStyle()
04195 && d->extra()->conditions->matchedStyle()->hasFeature( KSpreadStyle::STopBorder, true ) )
04196 return d->extra()->conditions->matchedStyle()->topBorderPen();
04197
04198 return KSpreadFormat::topBorderPen( col, row );
04199 }
04200
04201 const QPen& KSpreadCell::effRightBorderPen( int col, int row ) const
04202 {
04203 if ( isObscuringForced() )
04204 {
04205 KSpreadCell * cell = d->extra()->obscuringCells.first();
04206 return cell->effRightBorderPen( cell->column(), cell->row() );
04207 }
04208
04209 if ( d->hasExtra() && d->extra()->conditions
04210 && d->extra()->conditions->matchedStyle()
04211 && d->extra()->conditions->matchedStyle()->hasFeature( KSpreadStyle::SRightBorder, true ) )
04212 return d->extra()->conditions->matchedStyle()->rightBorderPen();
04213
04214 return KSpreadFormat::rightBorderPen( col, row );
04215 }
04216
04217 const QPen& KSpreadCell::effBottomBorderPen( int col, int row ) const
04218 {
04219 if ( isObscuringForced() )
04220 {
04221 KSpreadCell * cell = d->extra()->obscuringCells.first();
04222 return cell->effBottomBorderPen( cell->column(), cell->row() );
04223 }
04224
04225 if ( d->hasExtra() && d->extra()->conditions
04226 && d->extra()->conditions->matchedStyle()
04227 && d->extra()->conditions->matchedStyle()->hasFeature( KSpreadStyle::SBottomBorder, true ) )
04228 return d->extra()->conditions->matchedStyle()->bottomBorderPen();
04229
04230 return KSpreadFormat::bottomBorderPen( col, row );
04231 }
04232
04233 const QPen & KSpreadCell::effGoUpDiagonalPen( int col, int row ) const
04234 {
04235 if ( d->hasExtra() && d->extra()->conditions
04236 && d->extra()->conditions->matchedStyle()
04237 && d->extra()->conditions->matchedStyle()->hasFeature( KSpreadStyle::SGoUpDiagonal, true ) )
04238 return d->extra()->conditions->matchedStyle()->goUpDiagonalPen();
04239
04240 return KSpreadFormat::goUpDiagonalPen( col, row );
04241 }
04242
04243 const QPen & KSpreadCell::effFallDiagonalPen( int col, int row ) const
04244 {
04245 if ( d->hasExtra() && d->extra()->conditions
04246 && d->extra()->conditions->matchedStyle()
04247 && d->extra()->conditions->matchedStyle()->hasFeature( KSpreadStyle::SFallDiagonal, true ) )
04248 return d->extra()->conditions->matchedStyle()->fallDiagonalPen();
04249
04250 return KSpreadFormat::fallDiagonalPen( col, row );
04251 }
04252
04253 uint KSpreadCell::effBottomBorderValue( int col, int row ) const
04254 {
04255 if ( isObscuringForced() )
04256 {
04257 KSpreadCell * cell = d->extra()->obscuringCells.first();
04258 return cell->effBottomBorderValue( cell->column(), cell->row() );
04259 }
04260
04261 if ( d->hasExtra() && d->extra()->conditions
04262 && d->extra()->conditions->matchedStyle() )
04263 return d->extra()->conditions->matchedStyle()->bottomPenValue();
04264
04265 return KSpreadFormat::bottomBorderValue( col, row );
04266 }
04267
04268 uint KSpreadCell::effRightBorderValue( int col, int row ) const
04269 {
04270 if ( isObscuringForced() )
04271 {
04272 KSpreadCell * cell = d->extra()->obscuringCells.first();
04273 return cell->effRightBorderValue( cell->column(), cell->row() );
04274 }
04275
04276 if ( d->hasExtra() && d->extra()->conditions
04277 && d->extra()->conditions->matchedStyle() )
04278 return d->extra()->conditions->matchedStyle()->rightPenValue();
04279
04280 return KSpreadFormat::rightBorderValue( col, row );
04281 }
04282
04283 uint KSpreadCell::effLeftBorderValue( int col, int row ) const
04284 {
04285 if ( isObscuringForced() )
04286 {
04287 KSpreadCell * cell = d->extra()->obscuringCells.first();
04288 return cell->effLeftBorderValue( cell->column(), cell->row() );
04289 }
04290
04291 if ( d->hasExtra() && d->extra()->conditions
04292 && d->extra()->conditions->matchedStyle() )
04293 return d->extra()->conditions->matchedStyle()->leftPenValue();
04294
04295 return KSpreadFormat::leftBorderValue( col, row );
04296 }
04297
04298 uint KSpreadCell::effTopBorderValue( int col, int row ) const
04299 {
04300 if ( isObscuringForced() )
04301 {
04302 KSpreadCell * cell = d->extra()->obscuringCells.first();
04303 return cell->effTopBorderValue( cell->column(), cell->row() );
04304 }
04305
04306 if ( d->hasExtra() && d->extra()->conditions
04307 && d->extra()->conditions->matchedStyle() )
04308 return d->extra()->conditions->matchedStyle()->topPenValue();
04309
04310 return KSpreadFormat::topBorderValue( col, row );
04311 }
04312
04313
04314 void KSpreadCell::setCurrency( int type, QString const & symbol )
04315 {
04316 Currency c;
04317
04318 c.symbol = symbol.simplifyWhiteSpace();
04319 c.type = type;
04320
04321 if (c.symbol.length() == 0)
04322 {
04323 c.type = 0;
04324 c.symbol = locale()->currencySymbol();
04325 }
04326 m_pStyle = m_pStyle->setCurrency( c );
04327
04328 }
04329
04331
04332
04333
04335
04336 void KSpreadCell::incPrecision()
04337 {
04338
04339
04340 if ( !value().isNumber() )
04341 return;
04342 int tmpPreci = precision( column(), row() );
04343
04344 if ( tmpPreci == -1 )
04345 {
04346 int pos = d->strOutText.find(decimal_point);
04347 if ( pos == -1 )
04348 pos = d->strOutText.find('.');
04349 if ( pos == -1 )
04350 setPrecision(1);
04351 else
04352 {
04353 int start = 0;
04354 if ( d->strOutText.find('%') != -1 )
04355 start = 2;
04356 else if ( d->strOutText.find(locale()->currencySymbol()) == ((int)(d->strOutText.length()-locale()->currencySymbol().length())) )
04357 start = locale()->currencySymbol().length() + 1;
04358 else if ( (start=d->strOutText.find('E')) != -1 )
04359 start = d->strOutText.length() - start;
04360
04361
04362 setPrecision( QMAX( 0, (int)d->strOutText.length() - start - pos ) );
04363 }
04364 }
04365 else if ( tmpPreci < 10 )
04366 {
04367 setPrecision( ++tmpPreci );
04368 }
04369 setFlag(Flag_LayoutDirty);
04370 }
04371
04372 void KSpreadCell::decPrecision()
04373 {
04374
04375
04376 if ( !value().isNumber() )
04377 return;
04378 int preciTmp = precision( column(), row() );
04379
04380 if ( precision(column(),row()) == -1 )
04381 {
04382 int pos = d->strOutText.find( decimal_point );
04383 int start = 0;
04384 if ( d->strOutText.find('%') != -1 )
04385 start = 2;
04386 else if ( d->strOutText.find(locale()->currencySymbol()) == ((int)(d->strOutText.length()-locale()->currencySymbol().length())) )
04387 start = locale()->currencySymbol().length() + 1;
04388 else if ( (start = d->strOutText.find('E')) != -1 )
04389 start = d->strOutText.length() - start;
04390 else
04391 start = 0;
04392
04393 if ( pos == -1 )
04394 return;
04395
04396 setPrecision(d->strOutText.length() - pos - 2 - start);
04397
04398
04399 }
04400 else if ( preciTmp > 0 )
04401 {
04402 setPrecision( --preciTmp );
04403 }
04404 setFlag( Flag_LayoutDirty );
04405 }
04406
04407
04408
04409 void KSpreadCell::setNumber( double number )
04410 {
04411 setValue( KSpreadValue( number ) );
04412
04413 d->strText.setNum( number );
04414 checkNumberFormat();
04415 }
04416
04417 void KSpreadCell::setCellText( const QString& _text, bool asText )
04418 {
04419 QString ctext = _text;
04420 if( ctext.length() > 5000 )
04421 ctext = ctext.left( 5000 );
04422
04423 if ( asText )
04424 {
04425 d->strOutText = ctext;
04426 d->strText = ctext;
04427 setValue( KSpreadValue( ctext ) );
04428
04429 return;
04430 }
04431
04432 QString oldText = d->strText;
04433 setDisplayText( ctext );
04434 if(!m_pSheet->isLoading() && !testValidity() )
04435 {
04436
04437 setDisplayText( oldText );
04438 }
04439 }
04440
04441
04442
04443 void KSpreadCell::setDisplayText( const QString& _text )
04444 {
04445 m_pSheet->doc()->emitBeginOperation( false );
04446 d->strText = _text;
04447
04451 if ( !d->strText.isEmpty() && d->strText[0] == '=' )
04452 {
04453 setFlag(Flag_LayoutDirty);
04454 setFlag(Flag_TextFormatDirty);
04455
04456 if ( !m_pSheet->isLoading() )
04457 {
04458 if ( !makeFormula() )
04459 {
04460 kdError(36001) << "ERROR: Syntax ERROR" << endl;
04461 }
04462 }
04463 }
04464
04468 else
04469 {
04470
04471 checkTextInput();
04472
04473 setFlag(Flag_LayoutDirty);
04474 setFlag(Flag_TextFormatDirty);
04475 }
04476
04477 m_pSheet->doc()->emitEndOperation( QRect( d->column, d->row, 1, 1 ) );
04478 }
04479
04480 void KSpreadCell::setLink( const QString& link )
04481 {
04482 d->extra()->link = link;
04483
04484 if( !link.isEmpty() && d->strText.isEmpty() )
04485 setCellText( link );
04486 }
04487
04488 QString KSpreadCell::link() const
04489 {
04490 return d->hasExtra() ? d->extra()->link : QString::null;
04491 }
04492
04493 void KSpreadCell::update()
04494 {
04495
04496
04497
04498
04499 for (int x = d->column; x <= d->column + extraXCells(); x++)
04500 {
04501 for (int y = d->row; y <= d->row + extraYCells(); y++)
04502 {
04503 KSpreadCell* cell = m_pSheet->cellAt(x,y);
04504 cell->setLayoutDirtyFlag();
04505 }
04506 }
04507
04508 setCalcDirtyFlag();
04509
04510
04511 updateChart(true);
04512 }
04513
04514 bool KSpreadCell::testValidity() const
04515 {
04516 bool valid = false;
04517 if( d->hasExtra() && d->extra()->validity && d->extra()->validity->m_allow != Allow_All )
04518 {
04519
04520 if ( d->extra()->validity->allowEmptyCell && d->strText.isEmpty() )
04521 return true;
04522
04523 if( value().isNumber() &&
04524 (d->extra()->validity->m_allow == Allow_Number ||
04525 (d->extra()->validity->m_allow == Allow_Integer &&
04526 value().asFloat() == ceil(value().asFloat()))))
04527 {
04528 switch( d->extra()->validity->m_cond)
04529 {
04530 case Equal:
04531 valid = ( value().asFloat() - d->extra()->validity->valMin < DBL_EPSILON
04532 && value().asFloat() - d->extra()->validity->valMin >
04533 (0.0 - DBL_EPSILON));
04534 break;
04535 case DifferentTo:
04536 valid = !( ( value().asFloat() - d->extra()->validity->valMin < DBL_EPSILON
04537 && value().asFloat() - d->extra()->validity->valMin >
04538 (0.0 - DBL_EPSILON)) );
04539 break;
04540 case Superior:
04541 valid = ( value().asFloat() > d->extra()->validity->valMin);
04542 break;
04543 case Inferior:
04544 valid = ( value().asFloat() <d->extra()->validity->valMin);
04545 break;
04546 case SuperiorEqual:
04547 valid = ( value().asFloat() >= d->extra()->validity->valMin);
04548 break;
04549 case InferiorEqual:
04550 valid = (value().asFloat() <= d->extra()->validity->valMin);
04551 break;
04552 case Between:
04553 valid = ( value().asFloat() >= d->extra()->validity->valMin &&
04554 value().asFloat() <= d->extra()->validity->valMax);
04555 break;
04556 case Different:
04557 valid = (value().asFloat() < d->extra()->validity->valMin ||
04558 value().asFloat() > d->extra()->validity->valMax);
04559 break;
04560 default :
04561 break;
04562 }
04563 }
04564 else if(d->extra()->validity->m_allow==Allow_Text)
04565 {
04566 valid = value().isString();
04567 }
04568 else if ( d->extra()->validity->m_allow == Allow_List )
04569 {
04570
04571 if ( value().isString() && d->extra()->validity->listValidity.contains( value().asString() ) )
04572 valid = true;
04573 }
04574 else if(d->extra()->validity->m_allow==Allow_TextLength)
04575 {
04576 if( value().isString() )
04577 {
04578 int len = d->strOutText.length();
04579 switch( d->extra()->validity->m_cond)
04580 {
04581 case Equal:
04582 if (len == d->extra()->validity->valMin)
04583 valid = true;
04584 break;
04585 case DifferentTo:
04586 if (len != d->extra()->validity->valMin)
04587 valid = true;
04588 break;
04589 case Superior:
04590 if(len > d->extra()->validity->valMin)
04591 valid = true;
04592 break;
04593 case Inferior:
04594 if(len < d->extra()->validity->valMin)
04595 valid = true;
04596 break;
04597 case SuperiorEqual:
04598 if(len >= d->extra()->validity->valMin)
04599 valid = true;
04600 break;
04601 case InferiorEqual:
04602 if(len <= d->extra()->validity->valMin)
04603 valid = true;
04604 break;
04605 case Between:
04606 if(len >= d->extra()->validity->valMin && len <= d->extra()->validity->valMax)
04607 valid = true;
04608 break;
04609 case Different:
04610 if(len <d->extra()->validity->valMin || len >d->extra()->validity->valMax)
04611 valid = true;
04612 break;
04613 default :
04614 break;
04615 }
04616 }
04617 }
04618 else if(d->extra()->validity->m_allow == Allow_Time && isTime())
04619 {
04620 switch( d->extra()->validity->m_cond)
04621 {
04622 case Equal:
04623 valid = (value().asTime() == d->extra()->validity->timeMin);
04624 break;
04625 case DifferentTo:
04626 valid = (value().asTime() != d->extra()->validity->timeMin);
04627 break;
04628 case Superior:
04629 valid = (value().asTime() > d->extra()->validity->timeMin);
04630 break;
04631 case Inferior:
04632 valid = (value().asTime() < d->extra()->validity->timeMin);
04633 break;
04634 case SuperiorEqual:
04635 valid = (value().asTime() >= d->extra()->validity->timeMin);
04636 break;
04637 case InferiorEqual:
04638 valid = (value().asTime() <= d->extra()->validity->timeMin);
04639 break;
04640 case Between:
04641 valid = (value().asTime() >= d->extra()->validity->timeMin &&
04642 value().asTime() <= d->extra()->validity->timeMax);
04643 break;
04644 case Different:
04645 valid = (value().asTime() < d->extra()->validity->timeMin ||
04646 value().asTime() > d->extra()->validity->timeMax);
04647 break;
04648 default :
04649 break;
04650
04651 }
04652 }
04653 else if(d->extra()->validity->m_allow == Allow_Date && isDate())
04654 {
04655 switch( d->extra()->validity->m_cond)
04656 {
04657 case Equal:
04658 valid = (value().asDate() == d->extra()->validity->dateMin);
04659 break;
04660 case DifferentTo:
04661 valid = (value().asDate() != d->extra()->validity->dateMin);
04662 break;
04663 case Superior:
04664 valid = (value().asDate() > d->extra()->validity->dateMin);
04665 break;
04666 case Inferior:
04667 valid = (value().asDate() < d->extra()->validity->dateMin);
04668 break;
04669 case SuperiorEqual:
04670 valid = (value().asDate() >= d->extra()->validity->dateMin);
04671 break;
04672 case InferiorEqual:
04673 valid = (value().asDate() <= d->extra()->validity->dateMin);
04674 break;
04675 case Between:
04676 valid = (value().asDate() >= d->extra()->validity->dateMin &&
04677 value().asDate() <= d->extra()->validity->dateMax);
04678 break;
04679 case Different:
04680 valid = (value().asDate() < d->extra()->validity->dateMin ||
04681 value().asDate() > d->extra()->validity->dateMax);
04682 break;
04683 default :
04684 break;
04685
04686 }
04687 }
04688 }
04689 else
04690 {
04691 valid= true;
04692 }
04693
04694 if(!valid &&d->extra()->validity != NULL && d->extra()->validity->displayMessage)
04695 {
04696 switch (d->extra()->validity->m_action )
04697 {
04698 case Stop:
04699 KMessageBox::error((QWidget*)0L, d->extra()->validity->message,
04700 d->extra()->validity->title);
04701 break;
04702 case Warning:
04703 KMessageBox::warningYesNo((QWidget*)0L, d->extra()->validity->message,
04704 d->extra()->validity->title);
04705 break;
04706 case Information:
04707 KMessageBox::information((QWidget*)0L, d->extra()->validity->message,
04708 d->extra()->validity->title);
04709 break;
04710 }
04711 }
04712 if (!d->hasExtra())
04713 return true;
04714 return (valid || d->extra()->validity == NULL || d->extra()->validity->m_action != Stop);
04715 }
04716
04717 FormatType KSpreadCell::formatType() const
04718 {
04719 return getFormatType( d->column, d->row );
04720 }
04721
04722 double KSpreadCell::textWidth() const
04723 {
04724 return d->textWidth;
04725 }
04726
04727 double KSpreadCell::textHeight() const
04728 {
04729 return d->textHeight;
04730 }
04731
04732 int KSpreadCell::mergedXCells() const
04733 {
04734 return d->hasExtra() ? d->extra()->mergedXCells : 0;
04735 }
04736
04737 int KSpreadCell::mergedYCells() const
04738 {
04739 return d->hasExtra() ? d->extra()->mergedYCells : 0;
04740 }
04741
04742 int KSpreadCell::extraXCells() const
04743 {
04744 return d->hasExtra() ? d->extra()->extraXCells : 0;
04745 }
04746
04747 int KSpreadCell::extraYCells() const
04748 {
04749 return d->hasExtra() ? d->extra()->extraYCells : 0;
04750 }
04751
04752 double KSpreadCell::extraWidth() const
04753 {
04754 return d->hasExtra() ? d->extra()->extraWidth : 0;
04755 }
04756
04757 double KSpreadCell::extraHeight() const
04758 {
04759 return d->hasExtra() ? d->extra()->extraHeight : 0;
04760 }
04761
04762
04763 bool KSpreadCell::isDate() const
04764 {
04765 FormatType ft = formatType();
04766
04767 return (formatIsTime (ft) || ((ft == Generic_format) &&
04768 (value().format() == KSpreadValue::fmt_Date)));
04769 }
04770
04771 bool KSpreadCell::isTime() const
04772 {
04773 FormatType ft = formatType();
04774
04775 return (formatIsTime (ft) || ((ft == Generic_format) &&
04776 (value().format() == KSpreadValue::fmt_Time)));
04777 }
04778
04779 void KSpreadCell::setCalcDirtyFlag()
04780 {
04781 if ( !isFormula() )
04782 {
04783
04784 clearFlag(Flag_CalcDirty);
04785 return;
04786 }
04787 setFlag(Flag_CalcDirty);
04788 m_pSheet->setRegionPaintDirty(cellRect());
04789 }
04790
04791
04792 bool KSpreadCell::updateChart(bool refresh)
04793 {
04794
04795 if ( d->row != 0 && d->column != 0 )
04796 {
04797 CellBinding *bind;
04798 for ( bind = m_pSheet->firstCellBinding(); bind != 0L; bind = m_pSheet->nextCellBinding() )
04799 {
04800 if ( bind->contains( d->column, d->row ) )
04801 {
04802 if (!refresh)
04803 return true;
04804
04805 bind->cellChanged( this );
04806 }
04807 }
04808 return true;
04809 }
04810 return false;
04811
04812 }
04813
04814 double KSpreadCell::getDouble ()
04815 {
04816 if (isDefault())
04817 return 0.0;
04818
04819 if (isDate())
04820 {
04821 QDate date = value().asDate();
04822 QDate dummy (1900, 1, 1);
04823 return (dummy.daysTo (date) + 1);
04824 }
04825 if (isTime())
04826 {
04827 QTime time = value().asTime();
04828 QTime dummy;
04829 return dummy.secsTo( time );
04830 }
04831 if (value().isNumber())
04832 return value().asFloat();
04833
04834 return 0.0;
04835 }
04836
04837 void KSpreadCell::convertToDouble ()
04838 {
04839 if (isDefault())
04840 return;
04841
04842 setValue (getDouble ());
04843 }
04844
04845 void KSpreadCell::convertToPercent ()
04846 {
04847 if (isDefault())
04848 return;
04849
04850 setValue (getDouble ());
04851 d->value.setFormat (KSpreadValue::fmt_Percent);
04852 }
04853
04854 void KSpreadCell::convertToMoney ()
04855 {
04856 if (isDefault())
04857 return;
04858
04859 setValue (getDouble ());
04860 d->value.setFormat (KSpreadValue::fmt_Money);
04861 setPrecision (locale()->fracDigits());
04862 }
04863
04864 void KSpreadCell::convertToTime ()
04865 {
04866
04867
04868
04869
04870 if (isDefault() || isEmpty())
04871 return;
04872
04873 setValue (getDouble ());
04874 QTime time = value().asDateTime().time();
04875 int msec = (int) ( (value().asFloat() - (int) value().asFloat()) * 1000 );
04876 time = time.addMSecs( msec );
04877 setCellText( time.toString() );
04878 }
04879
04880 void KSpreadCell::convertToDate ()
04881 {
04882
04883
04884
04885
04886 if (isDefault() || isEmpty())
04887 return;
04888
04889 setValue (getDouble ());
04890
04891
04892 QDate date(1900, 1, 1);
04893 date = date.addDays( (int) value().asFloat() - 1 );
04894 date = value().asDateTime().date();
04895 setCellText (locale()->formatDate (date, true));
04896 }
04897
04898 void KSpreadCell::checkTextInput()
04899 {
04900
04901 clearAllErrors();
04902
04903 d->value = KSpreadValue::empty();
04904
04905
04906 QString str = d->strText;
04907
04908 sheet()->doc()->parser()->parse (str, this);
04909
04910
04911
04912 if (isTime() && (formatType() != Time_format7))
04913 d->strText = locale()->formatTime( value().asDateTime().time(), true);
04914
04915
04916 if (m_pSheet->getFirstLetterUpper() && value().isString() &&
04917 (!d->strText.isEmpty()))
04918 {
04919 QString str = value().asString();
04920 setValue( KSpreadValue( str[0].upper() + str.right( str.length()-1 ) ) );
04921 }
04922 }
04923
04924
04925 void KSpreadCell::checkNumberFormat()
04926 {
04927 if ( formatType() == Number_format && value().isNumber() )
04928 {
04929 if ( value().asFloat() > 1e+10 )
04930 setFormatType( Scientific_format );
04931 }
04932 }
04933
04934
04935
04936
04937
04938
04939 QDomElement KSpreadCell::save( QDomDocument& doc,
04940 int _x_offset, int _y_offset,
04941 bool force, bool copy, bool era )
04942 {
04943
04944 QDomElement cell = doc.createElement( "cell" );
04945 cell.setAttribute( "row", d->row - _y_offset );
04946 cell.setAttribute( "column", d->column - _x_offset );
04947
04948
04949
04950
04951 QDomElement format = KSpreadFormat::save( doc, d->column, d->row, force, copy );
04952 if ( format.hasChildNodes() || format.attributes().length() )
04953 cell.appendChild( format );
04954
04955 if ( isForceExtraCells() )
04956 {
04957 if ( extraXCells() )
04958 format.setAttribute( "colspan", extraXCells() );
04959 if ( extraYCells() )
04960 format.setAttribute( "rowspan", extraYCells() );
04961 }
04962
04963 if ( d->hasExtra() && d->extra()->conditions )
04964 {
04965 QDomElement conditionElement = d->extra()->conditions->saveConditions( doc );
04966
04967 if ( !conditionElement.isNull() )
04968 cell.appendChild( conditionElement );
04969 }
04970
04971 if ( d->hasExtra() && (d->extra()->validity != 0) )
04972 {
04973 QDomElement validity = doc.createElement("validity");
04974
04975 QDomElement param=doc.createElement("param");
04976 param.setAttribute("cond",(int)d->extra()->validity->m_cond);
04977 param.setAttribute("action",(int)d->extra()->validity->m_action);
04978 param.setAttribute("allow",(int)d->extra()->validity->m_allow);
04979 param.setAttribute("valmin",d->extra()->validity->valMin);
04980 param.setAttribute("valmax",d->extra()->validity->valMax);
04981 param.setAttribute("displaymessage",d->extra()->validity->displayMessage);
04982 param.setAttribute("displayvalidationinformation",d->extra()->validity->displayValidationInformation);
04983 param.setAttribute("allowemptycell",d->extra()->validity->allowEmptyCell);
04984 if ( !d->extra()->validity->listValidity.isEmpty() )
04985 param.setAttribute( "listvalidity", d->extra()->validity->listValidity.join( ";" ) );
04986 validity.appendChild(param);
04987 QDomElement title = doc.createElement( "title" );
04988 title.appendChild( doc.createTextNode( d->extra()->validity->title ) );
04989 validity.appendChild( title );
04990 QDomElement message = doc.createElement( "message" );
04991 message.appendChild( doc.createCDATASection( d->extra()->validity->message ) );
04992 validity.appendChild( message );
04993
04994 QDomElement inputTitle = doc.createElement( "inputtitle" );
04995 inputTitle.appendChild( doc.createTextNode( d->extra()->validity->titleInfo ) );
04996 validity.appendChild( inputTitle );
04997
04998 QDomElement inputMessage = doc.createElement( "inputmessage" );
04999 inputMessage.appendChild( doc.createTextNode( d->extra()->validity->messageInfo ) );
05000 validity.appendChild( inputMessage );
05001
05002
05003
05004 QString tmp;
05005 if ( d->extra()->validity->timeMin.isValid() )
05006 {
05007 QDomElement timeMin = doc.createElement( "timemin" );
05008 tmp=d->extra()->validity->timeMin.toString();
05009 timeMin.appendChild( doc.createTextNode( tmp ) );
05010 validity.appendChild( timeMin );
05011 }
05012 if ( d->extra()->validity->timeMax.isValid() )
05013 {
05014 QDomElement timeMax = doc.createElement( "timemax" );
05015 tmp=d->extra()->validity->timeMax.toString();
05016 timeMax.appendChild( doc.createTextNode( tmp ) );
05017 validity.appendChild( timeMax );
05018 }
05019
05020 if ( d->extra()->validity->dateMin.isValid() )
05021 {
05022 QDomElement dateMin = doc.createElement( "datemin" );
05023 QString tmp("%1/%2/%3");
05024 tmp = tmp.arg(d->extra()->validity->dateMin.year()).arg(d->extra()->validity->dateMin.month()).arg(d->extra()->validity->dateMin.day());
05025 dateMin.appendChild( doc.createTextNode( tmp ) );
05026 validity.appendChild( dateMin );
05027 }
05028 if ( d->extra()->validity->dateMax.isValid() )
05029 {
05030 QDomElement dateMax = doc.createElement( "datemax" );
05031 QString tmp("%1/%2/%3");
05032 tmp = tmp.arg(d->extra()->validity->dateMax.year()).arg(d->extra()->validity->dateMax.month()).arg(d->extra()->validity->dateMax.day());
05033 dateMax.appendChild( doc.createTextNode( tmp ) );
05034 validity.appendChild( dateMax );
05035 }
05036
05037 cell.appendChild( validity );
05038 }
05039
05040 if ( m_strComment )
05041 {
05042 QDomElement comment = doc.createElement( "comment" );
05043 comment.appendChild( doc.createCDATASection( *m_strComment ) );
05044 cell.appendChild( comment );
05045 }
05046
05047
05048
05049
05050 if ( !d->strText.isEmpty() )
05051 {
05052
05053
05054 if ( isFormula() )
05055 {
05056 QDomElement text = doc.createElement( "text" );
05057
05058 text.appendChild( doc.createTextNode( encodeFormula( era ) ) );
05059 cell.appendChild( text );
05060
05061
05062 QDomElement formulaResult = doc.createElement( "result" );
05063 saveCellResult( doc, formulaResult, d->strOutText );
05064 cell.appendChild( formulaResult );
05065
05066 }
05067 else if ( !link().isEmpty() )
05068 {
05069
05070
05071 QDomElement text = doc.createElement( "text" );
05072 QString qml = "!<a href=\"" + link() + "\">" + d->strText + "</a>";
05073 text.appendChild( doc.createCDATASection( qml ) );
05074 cell.appendChild( text );
05075 }
05076 else
05077 {
05078
05079 QDomElement text = doc.createElement( "text" );
05080 saveCellResult( doc, text, d->strText );
05081 cell.appendChild( text );
05082 }
05083 }
05084 if ( cell.hasChildNodes() || cell.attributes().length() > 2 )
05085
05086 return cell;
05087 else
05088 return QDomElement();
05089 }
05090
05091 bool KSpreadCell::saveCellResult( QDomDocument& doc, QDomElement& result,
05092 QString str )
05093 {
05094 QString dataType = "Other";
05095
05096 if ( value().isNumber() )
05097 {
05098 if ( isDate() )
05099 {
05100
05101 QDate dd = value().asDateTime().date();
05102 dataType = "Date";
05103 str = "%1/%2/%3";
05104 str = str.arg(dd.year()).arg(dd.month()).arg(dd.day());
05105 }
05106 else if( isTime() )
05107 {
05108
05109 dataType = "Time";
05110 str = value().asDateTime().time().toString();
05111 }
05112 else
05113 {
05114
05115 dataType = "Num";
05116 str = QString::number(value().asFloat(), 'g', DBL_DIG);
05117 }
05118 }
05119
05120 if ( value().isBoolean() )
05121 {
05122 dataType = "Bool";
05123 str = value().asBoolean() ? "true" : "false";
05124 }
05125
05126 if ( value().isString() )
05127 {
05128 dataType = "Str";
05129 str = value().asString();
05130 }
05131
05132 result.setAttribute( "dataType", dataType );
05133 if ( !d->strOutText.isEmpty() )
05134 result.setAttribute( "outStr", d->strOutText );
05135 result.appendChild( doc.createTextNode( str ) );
05136
05137 return true;
05138 }
05139
05140 void KSpreadCell::saveOasisAnnotation( KoXmlWriter &xmlwriter )
05141 {
05142 if ( m_strComment )
05143 {
05144
05145 xmlwriter.startElement( "office:annotation" );
05146 QStringList text = QStringList::split( "\n", *m_strComment );
05147 for ( QStringList::Iterator it = text.begin(); it != text.end(); ++it ) {
05148 xmlwriter.startElement( "text:p" );
05149 xmlwriter.addTextNode( *it );
05150 xmlwriter.endElement();
05151 }
05152 xmlwriter.endElement();
05153 }
05154 }
05155
05156
05157
05158 QString KSpreadCell::saveOasisCellStyle( KoGenStyle ¤tCellStyle, KoGenStyles &mainStyles, bool force, bool copy)
05159 {
05160 kdDebug()<<" QString KSpreadCell::saveOasisCellStyle( KoGenStyle ¤tCellStyle, KoGenStyles &mainStyles)***********\n";
05161 QString formatCellStyle = KSpreadFormat::saveOasisCellStyle( currentCellStyle, mainStyles, column(), row(), force, copy );
05162 if ( d->hasExtra() && d->extra()->conditions )
05163 d->extra()->conditions->saveOasisConditions( currentCellStyle );
05164 kdDebug()<<" formatCellStyle :"<<formatCellStyle<<endl;
05165 return formatCellStyle;
05166 }
05167
05168
05169 bool KSpreadCell::saveOasis( KoXmlWriter& xmlwriter, KoGenStyles &mainStyles, int row, int column, int maxCols, int &repeated, KSpreadGenValidationStyles &valStyle )
05170 {
05171 if ( !isObscuringForced() )
05172 xmlwriter.startElement( "table:table-cell" );
05173 else
05174 xmlwriter.startElement( "table:covered-table-cell" );
05175 #if 0
05176
05177 QFont font;
05178 KSpreadValue const value( cell->value() );
05179 if ( !cell->isDefault() )
05180 {
05181 font = cell->textFont( i, row );
05182 m_styles.addFont( font );
05183
05184 if ( cell->hasProperty( KSpreadFormat::PComment ) )
05185 hasComment = true;
05186 }
05187 #endif
05188 KoGenStyle currentCellStyle( KSpreadDoc::STYLE_CELL,"table-cell" );
05189 QString cellNumericStyle = saveOasisCellStyle( currentCellStyle,mainStyles );
05190 xmlwriter.addAttribute( "table:style-name", mainStyles.lookup( currentCellStyle, "ce" ) );
05191 if ( !cellNumericStyle.isEmpty() )
05192 xmlwriter.addAttribute( "style:data-style-name", cellNumericStyle );
05193
05194
05195 if ( isEmpty() && !hasProperty( KSpreadFormat::PComment ) && !isObscuringForced() && !isForceExtraCells() )
05196 {
05197 int j = column + 1;
05198 while ( j <= maxCols )
05199 {
05200 KSpreadCell *nextCell = m_pSheet->cellAt( j, row );
05201 KoGenStyle nextCellStyle( KSpreadDoc::STYLE_CELL,"table-cell" );
05202 nextCell->saveOasisCellStyle( nextCellStyle,mainStyles );
05203
05204 if ( nextCell->isEmpty() && !nextCell->hasProperty( KSpreadFormat::PComment )
05205 && ( nextCellStyle==currentCellStyle ) && !isObscuringForced() && !isForceExtraCells() )
05206 ++repeated;
05207 else
05208 break;
05209 ++j;
05210 }
05211 if ( repeated > 1 )
05212 xmlwriter.addAttribute( "table:number-columns-repeated", QString::number( repeated ) );
05213 }
05214
05215
05216 if ( link().isEmpty() )
05217 saveOasisValue (xmlwriter);
05218
05219 if (d->hasExtra() && d->extra()->validity)
05220 {
05221 KSpreadGenValidationStyle styleVal(d->extra()->validity);
05222 xmlwriter.addAttribute( "table:validation-name", valStyle.lookup( styleVal ) );
05223 }
05224 if ( isFormula() )
05225 {
05226 kdDebug() << "Formula found" << endl;
05227 QString formula( convertFormulaToOasisFormat( text() ) );
05228 xmlwriter.addAttribute( "table:formula", formula );
05229 }
05230 else if ( !link().isEmpty() )
05231 {
05232 kdDebug()<<"Link found \n";
05233 xmlwriter.startElement( "text:p" );
05234 xmlwriter.startElement( "text:a" );
05235
05236 if ( localReferenceAnchor( link() ) )
05237 xmlwriter.addAttribute( " xlink:href", ( "#"+link() ) );
05238 else
05239 xmlwriter.addAttribute( " xlink:href", link() );
05240 xmlwriter.addTextNode( text() );
05241 xmlwriter.endElement();
05242 xmlwriter.endElement();
05243 }
05244
05245 if ( isForceExtraCells() )
05246 {
05247 int colSpan = mergedXCells() + 1;
05248 int rowSpan = mergedYCells() + 1;
05249
05250 if ( colSpan > 1 )
05251 xmlwriter.addAttribute( "table:number-columns-spanned", QString::number( colSpan ) );
05252
05253 if ( rowSpan > 1 )
05254 xmlwriter.addAttribute( "table:number-rows-spanned", QString::number( rowSpan ) );
05255 }
05256
05257 if ( !isEmpty() && link().isEmpty() )
05258 {
05259 xmlwriter.startElement( "text:p" );
05260 xmlwriter.addTextNode(strOutText());
05261 xmlwriter.endElement();
05262 }
05263
05264 saveOasisAnnotation( xmlwriter );
05265
05266 xmlwriter.endElement();
05267 return true;
05268 }
05269
05270 void KSpreadCell::saveOasisValue (KoXmlWriter &xmlWriter)
05271 {
05272 switch (value().format())
05273 {
05274 case KSpreadValue::fmt_None: break;
05275 case KSpreadValue::fmt_Boolean:
05276 {
05277 xmlWriter.addAttribute( "office:value-type", "boolean" );
05278 xmlWriter.addAttribute( "office:boolean-value", ( value().asBoolean() ?
05279 "true" : "false" ) );
05280 break;
05281 }
05282 case KSpreadValue::fmt_Number:
05283 {
05284 xmlWriter.addAttribute( "office:value-type", "float" );
05285 xmlWriter.addAttribute( "office:value", QString::number( value().asFloat() ) );
05286 break;
05287 }
05288 case KSpreadValue::fmt_Percent:
05289 {
05290 xmlWriter.addAttribute( "office:value-type", "percentage" );
05291 xmlWriter.addAttribute( "office:value",
05292 QString::number( value().asFloat() ) );
05293 break;
05294 }
05295 case KSpreadValue::fmt_Money:
05296 {
05297 xmlWriter.addAttribute( "office:value-type", "currency" );
05298
05299
05300
05301 xmlWriter.addAttribute( "office:value",
05302 QString::number( value().asFloat() ) );
05303 break;
05304 }
05305 case KSpreadValue::fmt_DateTime: break;
05306 case KSpreadValue::fmt_Date:
05307 {
05308 xmlWriter.addAttribute( "office:value-type", "date" );
05309 xmlWriter.addAttribute( "office:date-value",
05310 value().asDate().toString( Qt::ISODate ) );
05311 break;
05312 }
05313 case KSpreadValue::fmt_Time:
05314 {
05315 xmlWriter.addAttribute( "office:value-type", "time" );
05316 xmlWriter.addAttribute( "office:time-value",
05317 value().asTime().toString( "PThhHmmMssS" ) );
05318 break;
05319 }
05320 case KSpreadValue::fmt_String:
05321 {
05322 xmlWriter.addAttribute( "office:value-type", "string" );
05323 xmlWriter.addAttribute( "office:string-value", value().asString() );
05324 break;
05325 }
05326 };
05327 }
05328
05329 QString KSpreadCell::convertFormulaToOasisFormat( const QString & formula ) const
05330 {
05331 QString s;
05332 QRegExp exp("(\\$?)([a-zA-Z]+)(\\$?)([0-9]+)");
05333 int n = exp.search( formula, 0 );
05334 kdDebug() << "Exp: " << formula << ", n: " << n << ", Length: " << formula.length()
05335 << ", Matched length: " << exp.matchedLength() << endl;
05336
05337 bool inQuote1 = false;
05338 bool inQuote2 = false;
05339 int i = 0;
05340 int l = (int) formula.length();
05341 if ( l <= 0 )
05342 return formula;
05343 while ( i < l )
05344 {
05345 if ( ( n != -1 ) && ( n < i ) )
05346 {
05347 n = exp.search( formula, i );
05348 kdDebug() << "Exp: " << formula.right( l - i ) << ", n: " << n << endl;
05349 }
05350 if ( formula[i] == '"' )
05351 {
05352 inQuote1 = !inQuote1;
05353 s += formula[i];
05354 ++i;
05355 continue;
05356 }
05357 if ( formula[i] == '\'' )
05358 {
05359
05360 inQuote2 = !inQuote2;
05361 ++i;
05362 continue;
05363 }
05364 if ( inQuote1 || inQuote2 )
05365 {
05366 s += formula[i];
05367 ++i;
05368 continue;
05369 }
05370 if ( ( formula[i] == '=' ) && ( formula[i + 1] == '=' ) )
05371 {
05372 s += '=';
05373 ++i;++i;
05374 continue;
05375 }
05376 if ( formula[i] == '!' )
05377 {
05378 insertBracket( s );
05379 s += '.';
05380 ++i;
05381 continue;
05382 }
05383 if ( formula[i] == ',' )
05384 {
05385 s += '.';
05386 ++i;
05387 continue;
05388 }
05389 if ( n == i )
05390 {
05391 int ml = exp.matchedLength();
05392 if ( formula[ i + ml ] == '!' )
05393 {
05394 kdDebug() << "No cell ref but sheet name" << endl;
05395 s += formula[i];
05396 ++i;
05397 continue;
05398 }
05399 if ( ( i > 0 ) && ( formula[i - 1] != '!' ) )
05400 s += "[.";
05401 for ( int j = 0; j < ml; ++j )
05402 {
05403 s += formula[i];
05404 ++i;
05405 }
05406 s += ']';
05407 continue;
05408 }
05409
05410 s += formula[i];
05411 ++i;
05412 }
05413
05414 return s;
05415 }
05416
05417 void KSpreadCell::loadOasisConditional( QDomElement * style )
05418 {
05419 kdDebug()<<" void KSpreadCell::loadOasisConditional( QDomElement * style :"<<style<<endl;
05420 if ( style )
05421 {
05422
05423 QDomElement e;
05424 forEachElement( e, style->toElement() )
05425 {
05426 kdDebug()<<"e.localName() :"<<e.localName()<<endl;
05427 if ( e.localName() == "map" && e.namespaceURI() == KoXmlNS::style )
05428 {
05429 if (d->hasExtra())
05430 delete d->extra()->conditions;
05431 d->extra()->conditions = new KSpreadConditions( this );
05432 d->extra()->conditions->loadOasisConditions( e );
05433 d->extra()->conditions->checkMatches();
05434 break;
05435 }
05436 }
05437
05438 }
05439 }
05440
05441 bool KSpreadCell::loadOasis( const QDomElement &element, const KoOasisStyles& oasisStyles )
05442 {
05443 QString text;
05444 kdDebug()<<" table:style-name :"<<element.attributeNS( KoXmlNS::table, "style-name", QString::null )<<endl;
05445 if ( element.hasAttributeNS( KoXmlNS::table, "style-name" ) )
05446 {
05447
05448 QString str = element.attributeNS( KoXmlNS::table, "style-name", QString::null );
05449 kdDebug()<<" bool KSpreadCell::loadOasis( const QDomElement &element, const KoOasisStyles& oasisStyles ) str :"<<str<<endl;
05450 QDomElement * style = oasisStyles.styles()[str];
05451 kdDebug()<<" style :"<<style<<endl;
05452 KoStyleStack styleStack;
05453 styleStack.push( *style );
05454 styleStack.setTypeProperties( "table-cell" );
05455 loadOasisStyleProperties( styleStack, oasisStyles );
05456 loadOasisConditional( style );
05457 }
05458 QDomElement textP = KoDom::namedItemNS( element, KoXmlNS::text, "p" );
05459 if ( !textP.isNull() )
05460 {
05461 text = textP.text();
05462 setCellText( text );
05463 setValue( text );
05464
05465 QDomElement textA = KoDom::namedItemNS( textP, KoXmlNS::text, "a" );
05466 if( !textA.isNull() )
05467 {
05468 if ( textA.hasAttributeNS( KoXmlNS::xlink, "href" ) )
05469 {
05470 QString link = textA.attributeNS( KoXmlNS::xlink, "href", QString::null );
05471 text = textA.text();
05472 setCellText( text );
05473 setValue( text );
05474 if ( link[0]=='#' )
05475 link=link.remove( 0, 1 );
05476 setLink( link );
05477 }
05478 }
05479 }
05480
05481 bool isFormula = false;
05482 if ( element.hasAttributeNS( KoXmlNS::table, "formula" ) )
05483 {
05484 kdDebug()<<" formula :"<<element.attributeNS( KoXmlNS::table, "formula", QString::null )<<endl;
05485 isFormula = true;
05486 QString formula;
05487 QString oasisFormula( element.attributeNS( KoXmlNS::table, "formula", QString::null ) );
05488
05489 if (oasisFormula.startsWith( "oooc:" ) )
05490 oasisFormula= oasisFormula.mid(5 );
05491 else if (oasisFormula.startsWith( "kspr:" ) )
05492 oasisFormula= oasisFormula.mid( 5 );
05493 convertFormula( formula, oasisFormula);
05494 setCellText( formula );
05495 }
05496 if ( element.hasAttributeNS( KoXmlNS::table, "validation-name" ) )
05497 {
05498 kdDebug()<<" Cel has a validation :"<<element.attributeNS( KoXmlNS::table, "validation-name", QString::null )<<endl;
05499 loadOasisValidation( element.attributeNS( KoXmlNS::table, "validation-name", QString::null ) );
05500 }
05501 if( element.hasAttributeNS( KoXmlNS::office, "value-type" ) )
05502 {
05503 QString valuetype = element.attributeNS( KoXmlNS::office, "value-type", QString::null );
05504 if( valuetype == "boolean" )
05505 {
05506 QString val = element.attributeNS( KoXmlNS::office, "boolean-value", QString::null );
05507 if( ( val == "true" ) || ( val == "false" ) )
05508 {
05509 bool value = val == "true";
05510 setValue( value );
05511 setCellText( value ? i18n("True") : i18n("False" ) );
05512 }
05513 }
05514
05515
05516 else if( valuetype == "float" )
05517 {
05518 bool ok = false;
05519 double value = element.attributeNS( KoXmlNS::office, "value", QString::null ).toDouble( &ok );
05520 if ( !isFormula )
05521 if( ok )
05522 setValue( value );
05523 }
05524
05525
05526 else if( valuetype == "currency" )
05527 {
05528 bool ok = false;
05529 double value = element.attributeNS( KoXmlNS::office, "value", QString::null ).toDouble( &ok );
05530 if( ok )
05531 {
05532 if ( !isFormula )
05533 setValue( value );
05534 setCurrency( 1, element.attributeNS( KoXmlNS::office, "currency", QString::null ) );
05535 setFormatType (Money_format);
05536 }
05537 }
05538 else if( valuetype == "percentage" )
05539 {
05540 bool ok = false;
05541 double value = element.attributeNS( KoXmlNS::office, "value", QString::null ).toDouble( &ok );
05542 if( ok )
05543 {
05544 if ( !isFormula )
05545 setValue( value );
05546 setFormatType (Percentage_format);
05547 }
05548 }
05549 else if ( valuetype == "date" )
05550 {
05551 QString value = element.attributeNS( KoXmlNS::office, "value", QString::null );
05552 if ( value.isEmpty() )
05553 value = element.attributeNS( KoXmlNS::office, "date-value", QString::null );
05554 kdDebug() << "Type: date, value: " << value << endl;
05555
05556
05557 int year = 0, month = 0, day = 0;
05558 bool ok = false;
05559
05560 int p1 = value.find( '-' );
05561 if ( p1 > 0 )
05562 year = value.left( p1 ).toInt( &ok );
05563
05564 kdDebug() << "year: " << value.left( p1 ) << endl;
05565
05566 int p2 = value.find( '-', ++p1 );
05567
05568 if ( ok )
05569 month = value.mid( p1, p2 - p1 ).toInt( &ok );
05570
05571 kdDebug() << "month: " << value.mid( p1, p2 - p1 ) << endl;
05572
05573 if ( ok )
05574 day = value.right( value.length() - p2 - 1 ).toInt( &ok );
05575
05576 kdDebug() << "day: " << value.right( value.length() - p2 ) << endl;
05577
05578 if ( ok )
05579 {
05580 setValue( QDate( year, month, day ) );
05581 setFormatType (ShortDate_format);
05582 kdDebug() << "Set QDate: " << year << " - " << month << " - " << day << endl;
05583 }
05584
05585 }
05586 else if ( valuetype == "time" )
05587 {
05588 QString value = element.attributeNS( KoXmlNS::office, "value", QString::null );
05589 if ( value.isEmpty() )
05590 value = element.attributeNS( KoXmlNS::office, "time-value", QString::null );
05591 kdDebug() << "Type: time: " << value << endl;
05592
05593 int hours = 0, minutes = 0, seconds = 0;
05594 int l = value.length();
05595 QString num;
05596 bool ok = false;
05597 for ( int i = 0; i < l; ++i )
05598 {
05599 if ( value[i].isNumber() )
05600 {
05601 num += value[i];
05602 continue;
05603 }
05604 else if ( value[i] == 'H' )
05605 hours = num.toInt( &ok );
05606 else if ( value[i] == 'M' )
05607 minutes = num.toInt( &ok );
05608 else if ( value[i] == 'S' )
05609 seconds = num.toInt( &ok );
05610 else
05611 continue;
05612
05613 kdDebug() << "Num: " << num << endl;
05614
05615 num = "";
05616 if ( !ok )
05617 break;
05618 }
05619 kdDebug() << "Hours: " << hours << ", " << minutes << ", " << seconds << endl;
05620
05621 if ( ok )
05622 {
05623
05624
05625 setValue( QTime( hours % 24, minutes, seconds ) );
05626 setFormatType (Time_format);
05627 }
05628 }
05629 else if( valuetype == "string" )
05630 {
05631 QString value = element.attributeNS( KoXmlNS::office, "value", QString::null );
05632 if ( value.isEmpty() && element.hasAttributeNS( KoXmlNS::office, "string-value" ))
05633 {
05634
05635 value = element.attributeNS( KoXmlNS::office, "string-value", QString::null );
05636 setValue( value );
05637 }
05638 setFormatType (Text_format);
05639 }
05640 else
05641 kdDebug()<<" type of value found : "<<valuetype<<endl;
05642 }
05643
05644 int colSpan = 1;
05645 int rowSpan = 1;
05646 if ( element.hasAttributeNS( KoXmlNS::table, "number-columns-spanned" ) )
05647 {
05648 bool ok = false;
05649 int span = element.attributeNS( KoXmlNS::table, "number-columns-spanned", QString::null ).toInt( &ok );
05650 if( ok ) colSpan = span;
05651 }
05652 if ( element.hasAttributeNS( KoXmlNS::table, "number-rows-spanned" ) )
05653 {
05654 bool ok = false;
05655 int span = element.attributeNS( KoXmlNS::table, "number-rows-spanned", QString::null ).toInt( &ok );
05656 if( ok ) rowSpan = span;
05657 }
05658 if ( colSpan > 1 || rowSpan > 1 )
05659 forceExtraCells( d->column, d->row, colSpan - 1, rowSpan - 1 );
05660
05661 QDomElement annotationElement = KoDom::namedItemNS( element, KoXmlNS::office, "annotation" );
05662 if ( !annotationElement.isNull() )
05663 {
05664 QString comment;
05665 QDomNode node = annotationElement.firstChild();
05666 while( !node.isNull() )
05667 {
05668 QDomElement commentElement = node.toElement();
05669 if( !commentElement.isNull() )
05670 if( commentElement.localName() == "p" && commentElement.namespaceURI() == KoXmlNS::text )
05671 {
05672 if( !comment.isEmpty() ) comment.append( '\n' );
05673 comment.append( commentElement.text() );
05674 }
05675
05676 node = node.nextSibling();
05677 }
05678
05679 if( !comment.isEmpty() )
05680 setComment( comment );
05681 }
05682
05683 if ( element.hasAttributeNS( KoXmlNS::style, "data-style-name" ) )
05684 {
05685 QString str = element.attributeNS( KoXmlNS::style, "data-style-name", QString::null );
05686 kdDebug()<<" data-style-name !"<<str<<endl;
05687 kdDebug()<< " oasisStyles.dataFormats()[...] :"<< oasisStyles.dataFormats()[str].formatStr<<endl;
05688 kdDebug()<< " oasisStyles.dataFormats()[...] prefix :"<< oasisStyles.dataFormats()[str].prefix<<endl;
05689 kdDebug()<< " oasisStyles.dataFormats()[...] suffix :"<< oasisStyles.dataFormats()[str].suffix<<endl;
05690 setPrefix( oasisStyles.dataFormats()[str].prefix );
05691 setPostfix( oasisStyles.dataFormats()[str].suffix );
05692 setFormatType( KSpreadStyle::formatType( oasisStyles.dataFormats()[str].formatStr ) );
05693 }
05694 return true;
05695 }
05696
05697 void KSpreadCell::loadOasisValidation( const QString& validationName )
05698 {
05699 kdDebug()<<"validationName:"<<validationName<<endl;
05700 QDomElement element = sheet()->doc()->loadingInfo()->validation( validationName);
05701 if (d->hasExtra())
05702 delete d->extra()->validity;
05703 d->extra()->validity = new KSpreadValidity;
05704 if ( element.hasAttributeNS( KoXmlNS::table, "condition" ) )
05705 {
05706 QString valExpression = element.attributeNS( KoXmlNS::table, "condition", QString::null );
05707 kdDebug()<<" element.attribute( table:condition ) "<<valExpression<<endl;
05708
05709
05710
05711
05712
05713
05714
05715
05716
05717
05718
05719
05720
05721 if ( valExpression.contains( "cell-content-text-length()" ) )
05722 {
05723
05724 valExpression = valExpression.remove("oooc:cell-content-text-length()" );
05725 kdDebug()<<" valExpression = :"<<valExpression<<endl;
05726 d->extra()->validity->m_allow = Allow_TextLength;
05727
05728 loadOasisValidationCondition( valExpression );
05729 }
05730 else if ( valExpression.contains( "cell-content-is-text()" ) )
05731 {
05732 d->extra()->validity->m_allow = Allow_Text;
05733 }
05734
05735 else if ( valExpression.contains( "cell-content-text-length-is-between" ) )
05736 {
05737 d->extra()->validity->m_allow = Allow_TextLength;
05738 d->extra()->validity->m_cond = Between;
05739 valExpression = valExpression.remove( "oooc:cell-content-text-length-is-between(" );
05740 kdDebug()<<" valExpression :"<<valExpression<<endl;
05741 valExpression = valExpression.remove( ")" );
05742 QStringList listVal = QStringList::split( ",", valExpression );
05743 loadOasisValidationValue( listVal );
05744 }
05745 else if ( valExpression.contains( "cell-content-text-length-is-not-between" ) )
05746 {
05747 d->extra()->validity->m_allow = Allow_TextLength;
05748 d->extra()->validity->m_cond = Different;
05749 valExpression = valExpression.remove( "oooc:cell-content-text-length-is-not-between(" );
05750 kdDebug()<<" valExpression :"<<valExpression<<endl;
05751 valExpression = valExpression.remove( ")" );
05752 kdDebug()<<" valExpression :"<<valExpression<<endl;
05753 QStringList listVal = QStringList::split( ",", valExpression );
05754 loadOasisValidationValue( listVal );
05755 }
05756 else if ( valExpression.contains( "cell-content-is-in-list(" ) )
05757 {
05758 d->extra()->validity->m_allow = Allow_List;
05759 valExpression = valExpression.remove( "oooc:cell-content-is-in-list(" );
05760 kdDebug()<<" valExpression :"<<valExpression<<endl;
05761 valExpression = valExpression.remove( ")" );
05762 d->extra()->validity->listValidity = QStringList::split( ";", valExpression );
05763
05764 }
05765
05766 else
05767 {
05768 if (valExpression.contains( "cell-content-is-whole-number()" ) )
05769 {
05770 d->extra()->validity->m_allow = Allow_Number;
05771 valExpression = valExpression.remove( "oooc:cell-content-is-whole-number() and " );
05772 }
05773 else if (valExpression.contains( "cell-content-is-decimal-number()" ) )
05774 {
05775 d->extra()->validity->m_allow = Allow_Integer;
05776 valExpression = valExpression.remove( "oooc:cell-content-is-decimal-number() and " );
05777 }
05778 else if (valExpression.contains( "cell-content-is-date()" ) )
05779 {
05780 d->extra()->validity->m_allow = Allow_Date;
05781 valExpression = valExpression.remove( "oooc:cell-content-is-date() and " );
05782 }
05783 else if (valExpression.contains( "cell-content-is-time()" ) )
05784 {
05785 d->extra()->validity->m_allow = Allow_Time;
05786 valExpression = valExpression.remove( "oooc:cell-content-is-time() and " );
05787 }
05788 kdDebug()<<"valExpression :"<<valExpression<<endl;
05789
05790 if ( valExpression.contains( "cell-content()" ) )
05791 {
05792 valExpression = valExpression.remove( "cell-content()" );
05793 loadOasisValidationCondition( valExpression );
05794 }
05795
05796
05797 if ( valExpression.contains( "cell-content-is-between(" ) )
05798 {
05799 valExpression = valExpression.remove( "cell-content-is-between(" );
05800 valExpression = valExpression.remove( ")" );
05801 QStringList listVal = QStringList::split( "," , valExpression );
05802 loadOasisValidationValue( listVal );
05803 d->extra()->validity->m_cond = Between;
05804 }
05805 if ( valExpression.contains( "cell-content-is-not-between(" ) )
05806 {
05807 valExpression = valExpression.remove( "cell-content-is-not-between(" );
05808 valExpression = valExpression.remove( ")" );
05809 QStringList listVal = QStringList::split( ",", valExpression );
05810 loadOasisValidationValue( listVal );
05811 d->extra()->validity->m_cond = Different;
05812 }
05813 }
05814 }
05815 if ( element.hasAttributeNS( KoXmlNS::table, "allow-empty-cell" ) )
05816 {
05817 kdDebug()<<" element.hasAttribute( table:allow-empty-cell ) :"<<element.hasAttributeNS( KoXmlNS::table, "allow-empty-cell" )<<endl;
05818 d->extra()->validity->allowEmptyCell = ( ( element.attributeNS( KoXmlNS::table, "allow-empty-cell", QString::null )=="true" ) ? true : false );
05819 }
05820 if ( element.hasAttributeNS( KoXmlNS::table, "base-cell-address" ) )
05821 {
05822
05823 }
05824
05825 QDomElement help = KoDom::namedItemNS( element, KoXmlNS::table, "help-message" );
05826 if ( !help.isNull() )
05827 {
05828 if ( help.hasAttributeNS( KoXmlNS::table, "title" ) )
05829 {
05830 kdDebug()<<"help.attribute( table:title ) :"<<help.attributeNS( KoXmlNS::table, "title", QString::null )<<endl;
05831 d->extra()->validity->titleInfo = help.attributeNS( KoXmlNS::table, "title", QString::null );
05832 }
05833 if ( help.hasAttributeNS( KoXmlNS::table, "display" ) )
05834 {
05835 kdDebug()<<"help.attribute( table:display ) :"<<help.attributeNS( KoXmlNS::table, "display", QString::null )<<endl;
05836 d->extra()->validity->displayValidationInformation = ( ( help.attributeNS( KoXmlNS::table, "display", QString::null )=="true" ) ? true : false );
05837 }
05838 QDomElement attrText = KoDom::namedItemNS( help, KoXmlNS::text, "p" );
05839 if ( !attrText.isNull() )
05840 {
05841 kdDebug()<<"help text :"<<attrText.text()<<endl;
05842 d->extra()->validity->messageInfo = attrText.text();
05843 }
05844 }
05845
05846 QDomElement error = KoDom::namedItemNS( element, KoXmlNS::table, "error-message" );
05847 if ( !error.isNull() )
05848 {
05849 if ( error.hasAttributeNS( KoXmlNS::table, "title" ) )
05850 d->extra()->validity->title = error.attributeNS( KoXmlNS::table, "title", QString::null );
05851 if ( error.hasAttributeNS( KoXmlNS::table, "message-type" ) )
05852 {
05853 QString str = error.attributeNS( KoXmlNS::table, "message-type", QString::null );
05854 if ( str == "warning" )
05855 d->extra()->validity->m_action = Warning;
05856 else if ( str == "information" )
05857 d->extra()->validity->m_action = Information;
05858 else if ( str == "stop" )
05859 d->extra()->validity->m_action = Stop;
05860 else
05861 kdDebug()<<"validation : message type unknown :"<<str<<endl;
05862 }
05863
05864 if ( error.hasAttributeNS( KoXmlNS::table, "display" ) )
05865 {
05866 kdDebug()<<" display message :"<<error.attributeNS( KoXmlNS::table, "display", QString::null )<<endl;
05867 d->extra()->validity->displayMessage = (error.attributeNS( KoXmlNS::table, "display", QString::null )=="true");
05868 }
05869 QDomElement attrText = KoDom::namedItemNS( error, KoXmlNS::text, "p" );
05870 if ( !attrText.isNull() )
05871 d->extra()->validity->message = attrText.text();
05872 }
05873 }
05874
05875
05876 void KSpreadCell::loadOasisValidationValue( const QStringList &listVal )
05877 {
05878 bool ok = false;
05879 kdDebug()<<" listVal[0] :"<<listVal[0]<<" listVal[1] :"<<listVal[1]<<endl;
05880
05881 if ( d->extra()->validity->m_allow == Allow_Date )
05882 {
05883 d->extra()->validity->dateMin = QDate::fromString( listVal[0] );
05884 d->extra()->validity->dateMax = QDate::fromString( listVal[1] );
05885 }
05886 else if ( d->extra()->validity->m_allow == Allow_Time )
05887 {
05888 d->extra()->validity->timeMin = QTime::fromString( listVal[0] );
05889 d->extra()->validity->timeMax = QTime::fromString( listVal[1] );
05890 }
05891 else
05892 {
05893 d->extra()->validity->valMin = listVal[0].toDouble(&ok);
05894 if ( !ok )
05895 {
05896 d->extra()->validity->valMin = listVal[0].toInt(&ok);
05897 if ( !ok )
05898 kdDebug()<<" Try to parse this value :"<<listVal[0]<<endl;
05899
05900 #if 0
05901 if ( !ok )
05902 d->extra()->validity->valMin = listVal[0];
05903 #endif
05904 }
05905 ok=false;
05906 d->extra()->validity->valMax = listVal[1].toDouble(&ok);
05907 if ( !ok )
05908 {
05909 d->extra()->validity->valMax = listVal[1].toInt(&ok);
05910 if ( !ok )
05911 kdDebug()<<" Try to parse this value :"<<listVal[1]<<endl;
05912
05913 #if 0
05914 if ( !ok )
05915 d->extra()->validity->valMax = listVal[1];
05916 #endif
05917 }
05918 }
05919 }
05920
05921 void KSpreadCell::loadOasisValidationCondition( QString &valExpression )
05922 {
05923 QString value;
05924 if (valExpression.find( "<=" )==0 )
05925 {
05926 value = valExpression.remove( 0,2 );
05927 d->extra()->validity->m_cond = InferiorEqual;
05928 }
05929 else if (valExpression.find( ">=" )==0 )
05930 {
05931 value = valExpression.remove( 0,2 );
05932 d->extra()->validity->m_cond = SuperiorEqual;
05933 }
05934 else if (valExpression.find( "!=" )==0 )
05935 {
05936
05937 value = valExpression.remove( 0,2 );
05938 d->extra()->validity->m_cond = DifferentTo;
05939 }
05940 else if ( valExpression.find( "<" )==0 )
05941 {
05942 value = valExpression.remove( 0,1 );
05943 d->extra()->validity->m_cond = Inferior;
05944 }
05945 else if(valExpression.find( ">" )==0 )
05946 {
05947 value = valExpression.remove( 0,1 );
05948 d->extra()->validity->m_cond = Superior;
05949 }
05950 else if (valExpression.find( "=" )==0 )
05951 {
05952 value = valExpression.remove( 0,1 );
05953 d->extra()->validity->m_cond = Equal;
05954 }
05955 else
05956 kdDebug()<<" I don't know how to parse it :"<<valExpression<<endl;
05957 kdDebug()<<" value :"<<value<<endl;
05958 if ( d->extra()->validity->m_allow == Allow_Date )
05959 {
05960 d->extra()->validity->dateMin = QDate::fromString( value );
05961 }
05962 else if (d->extra()->validity->m_allow == Allow_Date )
05963 {
05964 d->extra()->validity->timeMin = QTime::fromString( value );
05965 }
05966 else
05967 {
05968 bool ok = false;
05969 d->extra()->validity->valMin = value.toDouble(&ok);
05970 if ( !ok )
05971 {
05972 d->extra()->validity->valMin = value.toInt(&ok);
05973 if ( !ok )
05974 kdDebug()<<" Try to parse this value :"<<value<<endl;
05975
05976 #if 0
05977 if ( !ok )
05978 d->extra()->validity->valMin = value;
05979 #endif
05980 }
05981 }
05982 }
05983
05984
05985 bool KSpreadCell::load( const QDomElement & cell, int _xshift, int _yshift,
05986 PasteMode pm, Operation op, bool paste )
05987 {
05988 bool ok;
05989
05990
05991
05992
05993
05994 d->row = cell.attribute( "row" ).toInt( &ok ) + _yshift;
05995 if ( !ok ) return false;
05996 d->column = cell.attribute( "column" ).toInt( &ok ) + _xshift;
05997 if ( !ok ) return false;
05998
05999
06000 if ( d->row < 1 || d->row > KS_rowMax )
06001 {
06002 kdDebug(36001) << "KSpreadCell::load: Value out of Range Cell:row=" << d->row << endl;
06003 return false;
06004 }
06005 if ( d->column < 1 || d->column > KS_colMax )
06006 {
06007 kdDebug(36001) << "KSpreadCell::load: Value out of Range Cell:column=" << d->column << endl;
06008 return false;
06009 }
06010
06011
06012
06013
06014 QDomElement f = cell.namedItem( "format" ).toElement();
06015 if ( !f.isNull()
06016 && ( (pm == Normal) || (pm == Format) || (pm == NoBorder) ) )
06017 {
06018
06019
06020 if ( !KSpreadFormat::load( f, pm, paste ) )
06021 return false;
06022
06023 if ( f.hasAttribute( "colspan" ) )
06024 {
06025 int i = f.attribute("colspan").toInt( &ok );
06026 if ( !ok ) return false;
06027
06028 if ( i < 0 || i > KS_spanMax )
06029 {
06030 kdDebug(36001) << "Value out of range Cell::colspan=" << i << endl;
06031 return false;
06032 }
06033 if (i || d->hasExtra())
06034 d->extra()->extraXCells = i;
06035 if ( i > 0 )
06036 {
06037 setFlag(Flag_ForceExtra);
06038 }
06039 }
06040
06041 if ( f.hasAttribute( "rowspan" ) )
06042 {
06043 int i = f.attribute("rowspan").toInt( &ok );
06044 if ( !ok ) return false;
06045
06046 if ( i < 0 || i > KS_spanMax )
06047 {
06048 kdDebug(36001) << "Value out of range Cell::rowspan=" << i << endl;
06049 return false;
06050 }
06051 if (i || d->hasExtra())
06052 d->extra()->extraYCells = i;
06053 if ( i > 0 )
06054 {
06055 setFlag(Flag_ForceExtra);
06056 }
06057 }
06058
06059 if ( testFlag( Flag_ForceExtra ) )
06060 {
06061 if (d->hasExtra())
06062 forceExtraCells( d->column, d->row, d->extra()->extraXCells, d->extra()->extraYCells );
06063 }
06064
06065 }
06066
06067
06068
06069
06070 QDomElement conditionsElement = cell.namedItem( "condition" ).toElement();
06071 if ( !conditionsElement.isNull())
06072 {
06073 if (d->hasExtra())
06074 delete d->extra()->conditions;
06075 d->extra()->conditions = new KSpreadConditions( this );
06076 d->extra()->conditions->loadConditions( conditionsElement );
06077 d->extra()->conditions->checkMatches();
06078 }
06079
06080 QDomElement validity = cell.namedItem( "validity" ).toElement();
06081 if ( !validity.isNull())
06082 {
06083 QDomElement param = validity.namedItem( "param" ).toElement();
06084 if(!param.isNull())
06085 {
06086 d->extra()->validity = new KSpreadValidity;
06087 if ( param.hasAttribute( "cond" ) )
06088 {
06089 d->extra()->validity->m_cond = (Conditional) param.attribute("cond").toInt( &ok );
06090 if ( !ok )
06091 return false;
06092 }
06093 if ( param.hasAttribute( "action" ) )
06094 {
06095 d->extra()->validity->m_action = (Action) param.attribute("action").toInt( &ok );
06096 if ( !ok )
06097 return false;
06098 }
06099 if ( param.hasAttribute( "allow" ) )
06100 {
06101 d->extra()->validity->m_allow = (Allow) param.attribute("allow").toInt( &ok );
06102 if ( !ok )
06103 return false;
06104 }
06105 if ( param.hasAttribute( "valmin" ) )
06106 {
06107 d->extra()->validity->valMin = param.attribute("valmin").toDouble( &ok );
06108 if ( !ok )
06109 return false;
06110 }
06111 if ( param.hasAttribute( "valmax" ) )
06112 {
06113 d->extra()->validity->valMax = param.attribute("valmax").toDouble( &ok );
06114 if ( !ok )
06115 return false;
06116 }
06117 if ( param.hasAttribute( "displaymessage" ) )
06118 {
06119 d->extra()->validity->displayMessage = ( bool )param.attribute("displaymessage").toInt();
06120 }
06121 if ( param.hasAttribute( "displayvalidationinformation" ) )
06122 {
06123 d->extra()->validity->displayValidationInformation = ( bool )param.attribute("displayvalidationinformation").toInt();
06124 }
06125 if ( param.hasAttribute( "allowemptycell" ) )
06126 {
06127 d->extra()->validity->allowEmptyCell = ( bool )param.attribute("allowemptycell").toInt();
06128 }
06129 if ( param.hasAttribute("listvalidity") )
06130 {
06131 d->extra()->validity->listValidity=QStringList::split(";", param.attribute("listvalidity") );
06132 }
06133 }
06134 QDomElement inputTitle = validity.namedItem( "inputtitle" ).toElement();
06135 if (!inputTitle.isNull())
06136 {
06137 d->extra()->validity->titleInfo = inputTitle.text();
06138 }
06139 QDomElement inputMessage = validity.namedItem( "inputmessage" ).toElement();
06140 if (!inputMessage.isNull())
06141 {
06142 d->extra()->validity->messageInfo = inputMessage.text();
06143 }
06144
06145 QDomElement title = validity.namedItem( "title" ).toElement();
06146 if (!title.isNull())
06147 {
06148 d->extra()->validity->title = title.text();
06149 }
06150 QDomElement message = validity.namedItem( "message" ).toElement();
06151 if (!message.isNull())
06152 {
06153 d->extra()->validity->message = message.text();
06154 }
06155 QDomElement timeMin = validity.namedItem( "timemin" ).toElement();
06156 if ( !timeMin.isNull() )
06157 {
06158 d->extra()->validity->timeMin = toTime(timeMin);
06159 }
06160 QDomElement timeMax = validity.namedItem( "timemax" ).toElement();
06161 if ( !timeMax.isNull() )
06162 {
06163 d->extra()->validity->timeMax = toTime(timeMax);
06164 }
06165 QDomElement dateMin = validity.namedItem( "datemin" ).toElement();
06166 if ( !dateMin.isNull() )
06167 {
06168 d->extra()->validity->dateMin = toDate(dateMin);
06169 }
06170 QDomElement dateMax = validity.namedItem( "datemax" ).toElement();
06171 if ( !dateMax.isNull() )
06172 {
06173 d->extra()->validity->dateMax = toDate(dateMax);
06174 }
06175 }
06176
06177
06178
06179
06180 QDomElement comment = cell.namedItem( "comment" ).toElement();
06181 if ( !comment.isNull() && ( pm == ::Normal || pm == ::Comment || pm == ::NoBorder ))
06182 {
06183 QString t = comment.text();
06184
06185 setComment( t );
06186 }
06187
06188
06189
06190
06191
06192 QDomElement text = cell.namedItem( "text" ).toElement();
06193
06194 if ( !text.isNull() && ( pm == ::Normal || pm == ::Text || pm == ::NoBorder || pm == ::Result ) )
06195 {
06196
06197
06198
06199 if ( cell.hasAttribute( "dataType" ) )
06200 {
06201 text.setAttribute( "dataType", cell.attribute( "dataType" ) );
06202 }
06203 QDomElement result = cell.namedItem( "result" ).toElement();
06204 QString txt = text.text();
06205 if ((pm == ::Result) && (txt[0] == '='))
06206
06207
06208 d->strText = result.text();
06209 else
06210
06211 loadCellData(text, op);
06212
06213 if ( !result.isNull() )
06214 {
06215 QString dataType;
06216 QString t = result.text();
06217
06218 if ( result.hasAttribute( "dataType" ) )
06219 dataType = result.attribute( "dataType" );
06220 if ( result.hasAttribute( "outStr" ) )
06221 {
06222 d->strOutText = result.attribute( "outStr" );
06223 if ( !d->strOutText.isEmpty() )
06224 clearFlag( Flag_TextFormatDirty );
06225 }
06226
06227 bool clear = true;
06228
06229 if( dataType == "Bool" )
06230 {
06231 if ( t == "false" )
06232 setValue( true );
06233 else if ( t == "true" )
06234 setValue( false );
06235 else
06236 clear = false;
06237 }
06238 else if( dataType == "Num" )
06239 {
06240 bool ok = false;
06241 double dd = t.toDouble( &ok );
06242 if ( ok )
06243 setValue ( dd );
06244 else
06245 clear = false;
06246 }
06247 else if( dataType == "Date" )
06248 {
06249 bool ok = false;
06250 double dd = t.toDouble( &ok );
06251 if ( ok )
06252 setValue ( dd );
06253 else
06254 {
06255 int pos = t.find( '/' );
06256 int year = t.mid( 0, pos ).toInt();
06257 int pos1 = t.find( '/', pos + 1 );
06258 int month = t.mid( pos + 1, ( ( pos1 - 1 ) - pos ) ).toInt();
06259 int day = t.right( t.length() - pos1 - 1 ).toInt();
06260 QDate date( year, month, day );
06261 if ( date.isValid() )
06262 setValue( date );
06263 else
06264 clear = false;
06265 }
06266 }
06267 else if( dataType == "Time" )
06268 {
06269 bool ok = false;
06270 double dd = t.toDouble( &ok );
06271 if ( ok )
06272 setValue( dd );
06273 else
06274 {
06275 int hours = -1;
06276 int minutes = -1;
06277 int second = -1;
06278 int pos, pos1;
06279 pos = t.find( ':' );
06280 hours = t.mid( 0, pos ).toInt();
06281 pos1 = t.find( ':', pos + 1 );
06282 minutes = t.mid( pos + 1, ( ( pos1 - 1 ) - pos ) ).toInt();
06283 second = t.right( t.length() - pos1 - 1 ).toInt();
06284 QTime time( hours, minutes, second );
06285 if ( time.isValid() )
06286 setValue( time );
06287 else
06288 clear = false;
06289 }
06290 }
06291 else
06292 {
06293 setValue( t );
06294 }
06295
06296 if ( clear )
06297 clearFlag( Flag_CalcDirty );
06298 }
06299 }
06300
06301 return true;
06302 }
06303
06304 bool KSpreadCell::loadCellData(const QDomElement & text, Operation op )
06305 {
06306
06307
06308 QString t = text.text();
06309 t = t.stripWhiteSpace();
06310
06311 setFlag(Flag_LayoutDirty);
06312 setFlag(Flag_TextFormatDirty);
06313
06314
06315 if( t[0] == '=' )
06316 {
06317 t = decodeFormula( t, d->column, d->row );
06318 d->strText = pasteOperation( t, d->strText, op );
06319
06320 setFlag(Flag_CalcDirty);
06321 clearAllErrors();
06322
06323 if ( !m_pSheet->isLoading() )
06324 if ( !makeFormula() )
06325 kdError(36001) << "ERROR: Syntax ERROR" << endl;
06326 }
06327
06328 else if (t[0] == '!' )
06329 {
06330
06331
06332
06333 bool inside_tag = false;
06334 QString qml_text;
06335 QString tag;
06336 QString qml_link;
06337
06338 for( unsigned i = 1; i < t.length(); i++ )
06339 {
06340 QChar ch = t[i];
06341 if( ch == '<' )
06342 {
06343 if( !inside_tag )
06344 {
06345 inside_tag = true;
06346 tag = QString::null;
06347 }
06348 }
06349 else if( ch == '>' )
06350 {
06351 if( inside_tag )
06352 {
06353 inside_tag = false;
06354 if( tag.startsWith( "a href=\"", true ) )
06355 if( tag.endsWith( "\"" ) )
06356 qml_link = tag.mid( 8, tag.length()-9 );
06357 tag = QString::null;
06358 }
06359 }
06360 else
06361 {
06362 if( !inside_tag )
06363 qml_text += ch;
06364 else
06365 tag += ch;
06366 }
06367 }
06368
06369 if( !qml_link.isEmpty() )
06370 d->extra()->link = qml_link;
06371 d->strText = qml_text;
06372 setValue( d->strText );
06373 }
06374 else
06375 {
06376 bool newStyleLoading = true;
06377 QString dataType;
06378
06379 if ( text.hasAttribute( "dataType" ) )
06380 {
06381 dataType = text.attribute( "dataType" );
06382 }
06383 else
06384 {
06385
06386 if (isDate() && ( t.contains('/') == 2 ))
06387 dataType = "Date";
06388 else if (isTime() && ( t.contains(':') == 2 ) )
06389 dataType = "Time";
06390 else
06391 {
06392 d->strText = pasteOperation( t, d->strText, op );
06393 checkTextInput();
06394
06395 newStyleLoading = false;
06396 }
06397 }
06398
06399 if ( newStyleLoading )
06400 {
06401 d->value = KSpreadValue::empty();
06402 clearAllErrors();
06403
06404
06405 if( dataType == "Bool" )
06406 {
06407 if ( t == "false" )
06408 setValue( true );
06409 else if ( t == "true" )
06410 setValue( false );
06411 else
06412 kdWarning() << "Cell with BoolData, should be true or false: " << t << endl;
06413 }
06414
06415
06416 else if( dataType == "Num" )
06417 {
06418 bool ok = false;
06419 setValue ( KSpreadValue( t.toDouble(&ok) ) );
06420 if ( !ok )
06421 {
06422 kdWarning(36001) << "Couldn't parse '" << t << "' as number." << endl;
06423 }
06424
06425 KLocale* locale = m_pSheet->doc()->locale();
06426
06427
06428
06429 int precision = t.length() - t.find('.') - 1;
06430
06431 if ( formatType() == Percentage_format )
06432 {
06433 t = locale->formatNumber( value().asFloat() * 100.0, precision );
06434 d->strText = pasteOperation( t, d->strText, op );
06435 d->strText += '%';
06436 }
06437 else
06438 {
06439 t = locale->formatNumber(value().asFloat(), precision);
06440 d->strText = pasteOperation( t, d->strText, op );
06441 }
06442 }
06443
06444
06445 else if( dataType == "Date" )
06446 {
06447 int pos = t.find('/');
06448 int year = t.mid(0,pos).toInt();
06449 int pos1 = t.find('/',pos+1);
06450 int month = t.mid(pos+1,((pos1-1)-pos)).toInt();
06451 int day = t.right(t.length()-pos1-1).toInt();
06452 setValue( QDate(year,month,day) );
06453 if ( value().asDate().isValid() )
06454 d->strText = locale()->formatDate( value().asDate(), true );
06455 else
06456 {
06457 d->strText = pasteOperation( t, d->strText, op );
06458 checkTextInput();
06459 }
06460 }
06461
06462
06463 else if( dataType == "Time" )
06464 {
06465 int hours = -1;
06466 int minutes = -1;
06467 int second = -1;
06468 int pos, pos1;
06469 pos = t.find(':');
06470 hours = t.mid(0,pos).toInt();
06471 pos1 = t.find(':',pos+1);
06472 minutes = t.mid(pos+1,((pos1-1)-pos)).toInt();
06473 second = t.right(t.length()-pos1-1).toInt();
06474 setValue( QTime(hours,minutes,second) );
06475 if ( value().asTime().isValid() )
06476 d->strText = locale()->formatTime( value().asTime(), true );
06477 else
06478 {
06479 d->strText = pasteOperation( t, d->strText, op );
06480 checkTextInput();
06481 }
06482 }
06483
06484 else
06485 {
06486
06487 d->strText = pasteOperation( t, d->strText, op );
06488 setValue( d->strText );
06489 }
06490 }
06491 }
06492
06493 if ( text.hasAttribute( "outStr" ) )
06494 {
06495 d->strOutText = text.attribute( "outStr" );
06496 if ( !d->strOutText.isEmpty() )
06497 clearFlag( Flag_TextFormatDirty );
06498 }
06499
06500 if ( !m_pSheet->isLoading() )
06501 setCellText( d->strText );
06502
06503 if ( d->hasExtra() && d->extra()->conditions )
06504 d->extra()->conditions->checkMatches();
06505
06506 return true;
06507 }
06508
06509 QTime KSpreadCell::toTime(const QDomElement &element)
06510 {
06511
06512 QString t = element.text();
06513 t = t.stripWhiteSpace();
06514 int hours = -1;
06515 int minutes = -1;
06516 int second = -1;
06517 int pos, pos1;
06518 pos = t.find(':');
06519 hours = t.mid(0,pos).toInt();
06520 pos1 = t.find(':',pos+1);
06521 minutes = t.mid(pos+1,((pos1-1)-pos)).toInt();
06522 second = t.right(t.length()-pos1-1).toInt();
06523 setValue( KSpreadValue( QTime(hours,minutes,second)) );
06524 return value().asTime();
06525 }
06526
06527 QDate KSpreadCell::toDate(const QDomElement &element)
06528 {
06529 QString t = element.text();
06530 int pos;
06531 int pos1;
06532 int year = -1;
06533 int month = -1;
06534 int day = -1;
06535 pos = t.find('/');
06536 year = t.mid(0,pos).toInt();
06537 pos1 = t.find('/',pos+1);
06538 month = t.mid(pos+1,((pos1-1)-pos)).toInt();
06539 day = t.right(t.length()-pos1-1).toInt();
06540 setValue( KSpreadValue( QDate(year,month,day) ) );
06541 return value().asDate();
06542 }
06543
06544 QString KSpreadCell::pasteOperation( const QString &new_text, const QString &old_text, Operation op )
06545 {
06546 if ( op == OverWrite )
06547 return new_text;
06548
06549 QString tmp_op;
06550 QString tmp;
06551 QString old;
06552
06553 if( !new_text.isEmpty() && new_text[0] == '=' )
06554 {
06555 tmp = new_text.right( new_text.length() - 1 );
06556 }
06557 else
06558 {
06559 tmp = new_text;
06560 }
06561
06562 if ( old_text.isEmpty() && ( op == Add || op == Mul
06563 || op == Sub || op == Div ) )
06564 {
06565 old = "=0";
06566 }
06567
06568 if( !old_text.isEmpty() && old_text[0] == '=' )
06569 {
06570 old = old_text.right( old_text.length() - 1 );
06571 }
06572 else
06573 {
06574 old = old_text;
06575 }
06576
06577 bool b1, b2;
06578 tmp.toDouble( &b1 );
06579 old.toDouble( &b2 );
06580 if (b1 && !b2 && old.length() == 0)
06581 {
06582 old = "0";
06583 b2 = true;
06584 }
06585
06586 if( b1 && b2 )
06587 {
06588 switch( op )
06589 {
06590 case Add:
06591 tmp_op = QString::number(old.toDouble()+tmp.toDouble());
06592 break;
06593 case Mul :
06594 tmp_op = QString::number(old.toDouble()*tmp.toDouble());
06595 break;
06596 case Sub:
06597 tmp_op = QString::number(old.toDouble()-tmp.toDouble());
06598 break;
06599 case Div:
06600 tmp_op = QString::number(old.toDouble()/tmp.toDouble());
06601 break;
06602 default:
06603 Q_ASSERT( 0 );
06604 }
06605
06606 setFlag(Flag_LayoutDirty);
06607 clearAllErrors();
06608
06609 return tmp_op;
06610 }
06611 else if ( ( new_text[0] == '=' && old_text[0] == '=' ) ||
06612 ( b1 && old_text[0] == '=' ) || ( new_text[0] == '=' && b2 ) )
06613 {
06614 switch( op )
06615 {
06616 case Add:
06617 tmp_op="=("+old+")+"+"("+tmp+")";
06618 break;
06619 case Mul :
06620 tmp_op="=("+old+")*"+"("+tmp+")";
06621 break;
06622 case Sub:
06623 tmp_op="=("+old+")-"+"("+tmp+")";
06624 break;
06625 case Div:
06626 tmp_op="=("+old+")/"+"("+tmp+")";
06627 break;
06628 default :
06629 Q_ASSERT( 0 );
06630 }
06631
06632 tmp_op = decodeFormula( tmp_op, d->column, d->row );
06633 setFlag(Flag_LayoutDirty);
06634 clearAllErrors();
06635
06636 return tmp_op;
06637 }
06638
06639 tmp = decodeFormula( new_text, d->column, d->row );
06640 setFlag(Flag_LayoutDirty);
06641 clearAllErrors();
06642
06643 return tmp;
06644 }
06645
06646 QString KSpreadCell::testAnchor( int x, int y ) const
06647 {
06648 if( link().isEmpty() )
06649 return QString::null;
06650
06651 KSpreadDoc* doc = m_pSheet->doc();
06652 int x1 = doc->zoomItX( d->textX );
06653 int y1 = doc->zoomItX( d->textY - d->textHeight );
06654 int x2 = doc->zoomItX( d->textX + d->textWidth );
06655 int y2 = doc->zoomItX( d->textY );
06656
06657 if( x > x1 ) if( x < x2 )
06658 if( y > y1 ) if( y < y2 )
06659 return link();
06660
06661 return QString::null;
06662 }
06663
06664 void KSpreadCell::sheetDies()
06665 {
06666
06667 if (d->hasExtra())
06668 {
06669 d->extra()->extraXCells = 0;
06670 d->extra()->extraYCells = 0;
06671 d->extra()->mergedXCells = 0;
06672 d->extra()->mergedYCells = 0;
06673 }
06674 d->nextCell = 0;
06675 d->previousCell = 0;
06676 }
06677
06678 KSpreadCell::~KSpreadCell()
06679 {
06680 if ( d->nextCell )
06681 d->nextCell->setPreviousCell( d->previousCell );
06682 if ( d->previousCell )
06683 d->previousCell->setNextCell( d->nextCell );
06684
06685 if (d->hasExtra())
06686 {
06687 delete d->extra()->validity;
06688 }
06689 delete d->code;
06690
06691
06692 int extraXCells = d->hasExtra() ? d->extra()->extraXCells : 0;
06693 int extraYCells = d->hasExtra() ? d->extra()->extraYCells : 0;
06694 for( int x = 0; x <= extraXCells; ++x )
06695 for( int y = (x == 0) ? 1 : 0;
06696 y <= extraYCells; ++y )
06697 {
06698 KSpreadCell* cell = m_pSheet->cellAt( d->column + x, d->row + y );
06699 if ( cell )
06700 cell->unobscure(this);
06701 }
06702
06703 d->value = KSpreadValue::empty();
06704
06705 if (!isDefault())
06706 valueChanged ();
06707
06708 delete d;
06709 }
06710
06711 bool KSpreadCell::operator > ( const KSpreadCell & cell ) const
06712 {
06713 if ( value().isNumber() )
06714 {
06715 if ( cell.value().isNumber() )
06716 return value().asFloat() > cell.value().asFloat();
06717 else
06718 return false;
06719 }
06720 else if(isDate())
06721 {
06722 if( cell.isDate() )
06723 return value().asDate() > cell.value().asDate();
06724 else if (cell.value().isNumber())
06725 return true;
06726 else
06727 return false;
06728 }
06729 else if(isTime())
06730 {
06731 if( cell.isTime() )
06732 return value().asTime() > cell.value().asTime();
06733 else if( cell.isDate())
06734 return true;
06735 else if( cell.value().isNumber())
06736 return true;
06737 else
06738 return false;
06739 }
06740 else
06741 {
06742 if ( KSpreadMap::respectCase )
06743 return value().asString().compare(cell.value().asString()) > 0;
06744 else
06745 return ( value().asString() ).lower().compare(cell.value().asString().lower()) > 0;
06746 }
06747 }
06748
06749 bool KSpreadCell::operator < ( const KSpreadCell & cell ) const
06750 {
06751 if ( value().isNumber() )
06752 {
06753 if ( cell.value().isNumber() )
06754 return value().asFloat() < cell.value().asFloat();
06755 else
06756 return true;
06757 }
06758 else if(isDate())
06759 {
06760 if( cell.isDate() )
06761 return value().asDateTime().date() < cell.value().asDateTime().date();
06762 else if( cell.value().isNumber())
06763 return false;
06764 else
06765 return true;
06766 }
06767 else if(isTime())
06768 {
06769 if( cell.isTime() )
06770 return value().asDateTime().time() < cell.value().asDateTime().time();
06771 else if(cell.isDate())
06772 return false;
06773 else if( cell.value().isNumber())
06774 return false;
06775 else
06776 return true;
06777 }
06778 else
06779 {
06780 if ( KSpreadMap::respectCase )
06781 return value().asString().compare(cell.value().asString()) < 0;
06782 else
06783 return ( value().asString() ).lower().compare(cell.value().asString().lower()) < 0;
06784 }
06785 }
06786
06787 QRect KSpreadCell::cellRect()
06788 {
06789 Q_ASSERT(!isDefault());
06790 return QRect(QPoint(d->column, d->row), QPoint(d->column, d->row));
06791 }
06792
06793 QValueList<KSpreadConditional> KSpreadCell::conditionList() const
06794 {
06795 if ( !d->hasExtra() || !d->extra()->conditions )
06796 {
06797 QValueList<KSpreadConditional> emptyList;
06798 return emptyList;
06799 }
06800
06801 return d->extra()->conditions->conditionList();
06802 }
06803
06804 void KSpreadCell::setConditionList( const QValueList<KSpreadConditional> & newList )
06805 {
06806 if (d->hasExtra())
06807 delete d->extra()->conditions;
06808 d->extra()->conditions = new KSpreadConditions( this );
06809 d->extra()->conditions->setConditionList( newList );
06810 d->extra()->conditions->checkMatches();
06811 }
06812
06813 bool KSpreadCell::hasError() const
06814 {
06815 return ( testFlag(Flag_ParseError) ||
06816 testFlag(Flag_CircularCalculation) ||
06817 testFlag(Flag_DependancyError));
06818 }
06819
06820 void KSpreadCell::clearAllErrors()
06821 {
06822 clearFlag( Flag_ParseError );
06823 clearFlag( Flag_CircularCalculation );
06824 clearFlag( Flag_DependancyError );
06825 }
06826
06827 bool KSpreadCell::calcDirtyFlag()
06828 {
06829 return isFormula() ? testFlag( Flag_CalcDirty ) : false;
06830 }
06831
06832 bool KSpreadCell::layoutDirtyFlag() const
06833 {
06834 return testFlag( Flag_LayoutDirty );
06835 }
06836
06837 void KSpreadCell::clearDisplayDirtyFlag()
06838 {
06839 clearFlag( Flag_DisplayDirty );
06840 }
06841
06842 void KSpreadCell::setDisplayDirtyFlag()
06843 {
06844 setFlag( Flag_DisplayDirty );
06845 }
06846
06847 bool KSpreadCell::isForceExtraCells() const
06848 {
06849 return testFlag( Flag_ForceExtra );
06850 }
06851
06852 void KSpreadCell::clearFlag( CellFlags flag )
06853 {
06854 m_flagsMask &= ~(Q_UINT32)flag;
06855 }
06856
06857 void KSpreadCell::setFlag( CellFlags flag )
06858 {
06859 m_flagsMask |= (Q_UINT32)flag;
06860 }
06861
06862 bool KSpreadCell::testFlag( CellFlags flag ) const
06863 {
06864 return ( m_flagsMask & (Q_UINT32)flag );
06865 }
06866
06867
06868 void KSpreadCell::checkForNamedAreas( QString & formula ) const
06869 {
06870 int l = formula.length();
06871 int i = 0;
06872 QString word;
06873 int start = 0;
06874 while ( i < l )
06875 {
06876 if ( formula[i].isLetterOrNumber() )
06877 {
06878 word += formula[i];
06879 ++i;
06880 continue;
06881 }
06882 if ( !word.isEmpty() )
06883 {
06884 if ( sheet()->doc()->loadingInfo()->findWordInAreaList(word) )
06885 {
06886 formula = formula.replace( start, word.length(), "'" + word + "'" );
06887 l = formula.length();
06888 ++i;
06889 kdDebug() << "Formula: " << formula << ", L: " << l << ", i: " << i + 1 <<endl;
06890 }
06891 }
06892
06893 ++i;
06894 word = "";
06895 start = i;
06896 }
06897 if ( !word.isEmpty() )
06898 {
06899 if ( sheet()->doc()->loadingInfo()->findWordInAreaList(word) )
06900 {
06901 formula = formula.replace( start, word.length(), "'" + word + "'" );
06902 l = formula.length();
06903 ++i;
06904 kdDebug() << "Formula: " << formula << ", L: " << l << ", i: " << i + 1 <<endl;
06905 }
06906 }
06907 }
06908
06909 void KSpreadCell::convertFormula( QString & text, const QString & f ) const
06910 {
06911 kdDebug() << "Parsing formula: " << f << endl;
06912
06913 QString formula;
06914 QString parameter;
06915
06916 int l = f.length();
06917 int p = 0;
06918
06919 while ( p < l )
06920 {
06921 if ( f[p] == '(' )
06922 {
06923 break;
06924 }
06925 else if ( f[p] == '[' )
06926 break;
06927
06928 formula += f[p];
06929 ++p;
06930 }
06931
06932 if ( parameter.isEmpty() )
06933 {
06934 checkForNamedAreas( formula );
06935 }
06936
06937 kdDebug() << "Formula: " << formula << ", Parameter: " << parameter << ", P: " << p << endl;
06938
06939 #if 0 //TODO replace formula name from oocalc if it's necessary (code from oo/import)
06940
06941 if ( formula == "=MULTIPLE.OPERATIONS" )
06942 formula = "=MULTIPLEOPERATIONS";
06943 #endif
06944 QString par;
06945 bool isPar = false;
06946 bool inQuote = false;
06947
06948 while ( p < l )
06949 {
06950 if ( f[p] == '"' )
06951 {
06952 inQuote = !inQuote;
06953 parameter += '"';
06954 }
06955 else if ( f[p] == '[' )
06956 {
06957 if ( !inQuote )
06958 isPar = true;
06959 else
06960 parameter += '[';
06961 }
06962 else if ( f[p] == ']' )
06963 {
06964 if ( inQuote )
06965 {
06966 parameter += ']';
06967 continue;
06968 }
06969
06970 isPar = false;
06971 parameter += KSpreadSheet::translateOpenCalcPoint( par );
06972 par = "";
06973 }
06974 else if ( isPar )
06975 {
06976 par += f[p];
06977 }
06978 else if ( f[p] == '=' )
06979 {
06980 if ( inQuote )
06981 parameter += '=';
06982 else
06983 parameter += "==";
06984 }
06985 else if ( f[p] == ')' )
06986 {
06987 if ( !inQuote )
06988 parameter += ")";
06989 }
06990 else if ( f[p] == '.' && f[p+1].isNumber() )
06991 parameter += ',';
06992 else
06993 parameter += f[p];
06994
06995 ++p;
06996 if ( p == l )
06997 checkForNamedAreas( parameter );
06998 }
06999
07000 text = formula + parameter;
07001 kdDebug() << "New formula: " << text << endl;
07002 }