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