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 if ( style )
05842 format()->setFormatType (style->formatType());
05843 kdDebug() << "Set QDate: " << year << " - " << month << " - " << day << endl;
05844 }
05845
05846 }
05847 else if ( valuetype == "time" )
05848 {
05849 QString value = element.attributeNS( KoXmlNS::office, "value", QString::null );
05850 if ( value.isEmpty() )
05851 value = element.attributeNS( KoXmlNS::office, "time-value", QString::null );
05852 kdDebug() << "Type: time: " << value << endl;
05853
05854 int hours = 0, minutes = 0, seconds = 0;
05855 int l = value.length();
05856 QString num;
05857 bool ok = false;
05858 for ( int i = 0; i < l; ++i )
05859 {
05860 if ( value[i].isNumber() )
05861 {
05862 num += value[i];
05863 continue;
05864 }
05865 else if ( value[i] == 'H' )
05866 hours = num.toInt( &ok );
05867 else if ( value[i] == 'M' )
05868 minutes = num.toInt( &ok );
05869 else if ( value[i] == 'S' )
05870 seconds = num.toInt( &ok );
05871 else
05872 continue;
05873
05874 kdDebug() << "Num: " << num << endl;
05875
05876 num = "";
05877 if ( !ok )
05878 break;
05879 }
05880 kdDebug() << "Hours: " << hours << ", " << minutes << ", " << seconds << endl;
05881
05882 if ( ok )
05883 {
05884
05885
05886 setCellValue( QTime( hours % 24, minutes, seconds ) );
05887 if ( style )
05888 format()->setFormatType (style->formatType());
05889 }
05890 }
05891 else if( valuetype == "string" )
05892 {
05893 QString value = element.attributeNS( KoXmlNS::office, "value", QString::null );
05894 if ( value.isEmpty() && element.hasAttributeNS( KoXmlNS::office, "string-value" ))
05895 {
05896
05897 value = element.attributeNS( KoXmlNS::office, "string-value", QString::null );
05898 setCellValue( value );
05899 }
05900 format()->setFormatType (Text_format);
05901 }
05902 else
05903 kdDebug()<<" type of value found : "<<valuetype<<endl;
05904 }
05905
05906
05907
05908
05909 int colSpan = 1;
05910 int rowSpan = 1;
05911 if ( element.hasAttributeNS( KoXmlNS::table, "number-columns-spanned" ) )
05912 {
05913 bool ok = false;
05914 int span = element.attributeNS( KoXmlNS::table, "number-columns-spanned", QString::null ).toInt( &ok );
05915 if( ok ) colSpan = span;
05916 }
05917 if ( element.hasAttributeNS( KoXmlNS::table, "number-rows-spanned" ) )
05918 {
05919 bool ok = false;
05920 int span = element.attributeNS( KoXmlNS::table, "number-rows-spanned", QString::null ).toInt( &ok );
05921 if( ok ) rowSpan = span;
05922 }
05923 if ( colSpan > 1 || rowSpan > 1 )
05924 mergeCells( d->column, d->row, colSpan - 1, rowSpan - 1 );
05925
05926
05927
05928
05929 QDomElement annotationElement = KoDom::namedItemNS( element, KoXmlNS::office, "annotation" );
05930 if ( !annotationElement.isNull() )
05931 {
05932 QString comment;
05933 QDomNode node = annotationElement.firstChild();
05934 while( !node.isNull() )
05935 {
05936 QDomElement commentElement = node.toElement();
05937 if( !commentElement.isNull() )
05938 if( commentElement.localName() == "p" && commentElement.namespaceURI() == KoXmlNS::text )
05939 {
05940 if( !comment.isEmpty() ) comment.append( '\n' );
05941 comment.append( commentElement.text() );
05942 }
05943
05944 node = node.nextSibling();
05945 }
05946
05947 if( !comment.isEmpty() )
05948 format()->setComment( comment );
05949 }
05950
05951 QDomElement frame = KoDom::namedItemNS( element, KoXmlNS::draw, "frame" );
05952 if ( !frame.isNull() )
05953 loadOasisObjects( frame, oasisContext );
05954
05955 if (isFormula)
05956 setCalcDirtyFlag ();
05957
05958 return true;
05959 }
05960
05961 void Cell::loadOasisCellText( const QDomElement& parent )
05962 {
05963
05964 QDomElement textParagraphElement;
05965 QString cellText;
05966
05967 bool multipleTextParagraphsFound=false;
05968
05969 forEachElement( textParagraphElement , parent )
05970 {
05971 if ( textParagraphElement.localName()=="p" &&
05972 textParagraphElement.namespaceURI()== KoXmlNS::text )
05973 {
05974
05975 if (cellText.isEmpty())
05976 cellText = textParagraphElement.text();
05977 else
05978 {
05979 cellText += "\n"+textParagraphElement.text();
05980 multipleTextParagraphsFound=true;
05981 }
05982
05983 QDomElement textA = KoDom::namedItemNS( textParagraphElement, KoXmlNS::text, "a" );
05984 if( !textA.isNull() )
05985 {
05986 if ( textA.hasAttributeNS( KoXmlNS::xlink, "href" ) )
05987 {
05988 QString link = textA.attributeNS( KoXmlNS::xlink, "href", QString::null );
05989 cellText = textA.text();
05990 setCellText( cellText );
05991 setValue( cellText );
05992 if ( link[0]=='#' )
05993 link=link.remove( 0, 1 );
05994 setLink( link );
05995 }
05996 }
05997 }
05998 }
05999
06000 if (!cellText.isNull())
06001 {
06002 setCellText( cellText );
06003 setValue( cellText );
06004 }
06005
06006
06007 if ( multipleTextParagraphsFound )
06008 {
06009 format()->setMultiRow(true);
06010 }
06011 }
06012
06013 void Cell::loadOasisObjects( const QDomElement &parent, KoOasisLoadingContext& oasisContext )
06014 {
06015 for( QDomElement e = parent; !e.isNull(); e = e.nextSibling().toElement() )
06016 {
06017 if ( e.localName() == "frame" && e.namespaceURI() == KoXmlNS::draw )
06018 {
06019 EmbeddedObject *obj = 0;
06020 QDomNode object = KoDom::namedItemNS( e, KoXmlNS::draw, "object" );
06021 if ( !object.isNull() )
06022 {
06023 if ( !object.toElement().attributeNS( KoXmlNS::draw, "notify-on-update-of-ranges", QString::null).isNull() )
06024 obj = new EmbeddedChart( sheet()->doc(), sheet() );
06025 else
06026 obj = new EmbeddedKOfficeObject( sheet()->doc(), sheet() );
06027 }
06028 else
06029 {
06030 QDomNode image = KoDom::namedItemNS( e, KoXmlNS::draw, "image" );
06031 if ( !image.isNull() )
06032 obj = new EmbeddedPictureObject( sheet(), sheet()->doc()->pictureCollection() );
06033 else
06034 kdDebug() << "Object type wasn't loaded!" << endl;
06035 }
06036
06037 if ( obj )
06038 {
06039 obj->loadOasis( e, oasisContext );
06040 sheet()->doc()->insertObject( obj );
06041
06042 QString ref = e.attributeNS( KoXmlNS::table, "end-cell-address", QString::null );
06043 if ( ref.isNull() )
06044 continue;
06045
06046 ref = Oasis::decodeFormula( ref );
06047 Point point( ref );
06048 if ( !point.isValid() )
06049 continue;
06050
06051 KoRect geometry = obj->geometry();
06052 geometry.setLeft( geometry.left() + sheet()->columnPos( d->column, 0 ) );
06053 geometry.setTop( geometry.top() + sheet()->rowPos( d->row, 0 ) );
06054
06055 QString str = e.attributeNS( KoXmlNS::table, "end-x", QString::null );
06056 if ( !str.isNull() )
06057 {
06058 uint end_x = (uint) KoUnit::parseValue( str );
06059 geometry.setRight( sheet()->columnPos( point.column(), 0) + end_x );
06060 }
06061
06062 str = e.attributeNS( KoXmlNS::table, "end-y", QString::null );
06063 if ( !str.isNull() )
06064 {
06065 uint end_y = (uint) KoUnit::parseValue( str );
06066 geometry.setBottom( sheet()->rowPos( point.row(), 0) + end_y );
06067 }
06068
06069 obj->setGeometry( geometry );
06070 }
06071 }
06072 }
06073 }
06074
06075 void Cell::loadOasisValidation( const QString& validationName )
06076 {
06077 QDomElement element = sheet()->doc()->loadingInfo()->validation( validationName);
06078 if (d->hasExtra())
06079 delete d->extra()->validity;
06080 d->extra()->validity = new Validity;
06081 if ( element.hasAttributeNS( KoXmlNS::table, "condition" ) )
06082 {
06083 QString valExpression = element.attributeNS( KoXmlNS::table, "condition", QString::null );
06084 kdDebug()<<" element.attribute( table:condition ) "<<valExpression<<endl;
06085
06086
06087
06088
06089
06090
06091
06092
06093
06094
06095
06096
06097
06098 if ( valExpression.contains( "cell-content-text-length()" ) )
06099 {
06100
06101 valExpression = valExpression.remove("oooc:cell-content-text-length()" );
06102 kdDebug()<<" valExpression = :"<<valExpression<<endl;
06103 d->extra()->validity->m_restriction = Restriction::TextLength;
06104
06105 loadOasisValidationCondition( valExpression );
06106 }
06107 else if ( valExpression.contains( "cell-content-is-text()" ) )
06108 {
06109 d->extra()->validity->m_restriction = Restriction::Text;
06110 }
06111
06112 else if ( valExpression.contains( "cell-content-text-length-is-between" ) )
06113 {
06114 d->extra()->validity->m_restriction = Restriction::TextLength;
06115 d->extra()->validity->m_cond = Conditional::Between;
06116 valExpression = valExpression.remove( "oooc:cell-content-text-length-is-between(" );
06117 kdDebug()<<" valExpression :"<<valExpression<<endl;
06118 valExpression = valExpression.remove( ")" );
06119 QStringList listVal = QStringList::split( ",", valExpression );
06120 loadOasisValidationValue( listVal );
06121 }
06122 else if ( valExpression.contains( "cell-content-text-length-is-not-between" ) )
06123 {
06124 d->extra()->validity->m_restriction = Restriction::TextLength;
06125 d->extra()->validity->m_cond = Conditional::Different;
06126 valExpression = valExpression.remove( "oooc:cell-content-text-length-is-not-between(" );
06127 kdDebug()<<" valExpression :"<<valExpression<<endl;
06128 valExpression = valExpression.remove( ")" );
06129 kdDebug()<<" valExpression :"<<valExpression<<endl;
06130 QStringList listVal = QStringList::split( ",", valExpression );
06131 loadOasisValidationValue( listVal );
06132 }
06133 else if ( valExpression.contains( "cell-content-is-in-list(" ) )
06134 {
06135 d->extra()->validity->m_restriction = Restriction::List;
06136 valExpression = valExpression.remove( "oooc:cell-content-is-in-list(" );
06137 kdDebug()<<" valExpression :"<<valExpression<<endl;
06138 valExpression = valExpression.remove( ")" );
06139 d->extra()->validity->listValidity = QStringList::split( ";", valExpression );
06140
06141 }
06142
06143 else
06144 {
06145 if (valExpression.contains( "cell-content-is-whole-number()" ) )
06146 {
06147 d->extra()->validity->m_restriction = Restriction::Number;
06148 valExpression = valExpression.remove( "oooc:cell-content-is-whole-number() and " );
06149 }
06150 else if (valExpression.contains( "cell-content-is-decimal-number()" ) )
06151 {
06152 d->extra()->validity->m_restriction = Restriction::Integer;
06153 valExpression = valExpression.remove( "oooc:cell-content-is-decimal-number() and " );
06154 }
06155 else if (valExpression.contains( "cell-content-is-date()" ) )
06156 {
06157 d->extra()->validity->m_restriction = Restriction::Date;
06158 valExpression = valExpression.remove( "oooc:cell-content-is-date() and " );
06159 }
06160 else if (valExpression.contains( "cell-content-is-time()" ) )
06161 {
06162 d->extra()->validity->m_restriction = Restriction::Time;
06163 valExpression = valExpression.remove( "oooc:cell-content-is-time() and " );
06164 }
06165 kdDebug()<<"valExpression :"<<valExpression<<endl;
06166
06167 if ( valExpression.contains( "cell-content()" ) )
06168 {
06169 valExpression = valExpression.remove( "cell-content()" );
06170 loadOasisValidationCondition( valExpression );
06171 }
06172
06173
06174 if ( valExpression.contains( "cell-content-is-between(" ) )
06175 {
06176 valExpression = valExpression.remove( "cell-content-is-between(" );
06177 valExpression = valExpression.remove( ")" );
06178 QStringList listVal = QStringList::split( "," , valExpression );
06179 loadOasisValidationValue( listVal );
06180 d->extra()->validity->m_cond = Conditional::Between;
06181 }
06182 if ( valExpression.contains( "cell-content-is-not-between(" ) )
06183 {
06184 valExpression = valExpression.remove( "cell-content-is-not-between(" );
06185 valExpression = valExpression.remove( ")" );
06186 QStringList listVal = QStringList::split( ",", valExpression );
06187 loadOasisValidationValue( listVal );
06188 d->extra()->validity->m_cond = Conditional::Different;
06189 }
06190 }
06191 }
06192 if ( element.hasAttributeNS( KoXmlNS::table, "allow-empty-cell" ) )
06193 {
06194 kdDebug()<<" element.hasAttribute( table:allow-empty-cell ) :"<<element.hasAttributeNS( KoXmlNS::table, "allow-empty-cell" )<<endl;
06195 d->extra()->validity->allowEmptyCell = ( ( element.attributeNS( KoXmlNS::table, "allow-empty-cell", QString::null )=="true" ) ? true : false );
06196 }
06197 if ( element.hasAttributeNS( KoXmlNS::table, "base-cell-address" ) )
06198 {
06199
06200 }
06201
06202 QDomElement help = KoDom::namedItemNS( element, KoXmlNS::table, "help-message" );
06203 if ( !help.isNull() )
06204 {
06205 if ( help.hasAttributeNS( KoXmlNS::table, "title" ) )
06206 {
06207 kdDebug()<<"help.attribute( table:title ) :"<<help.attributeNS( KoXmlNS::table, "title", QString::null )<<endl;
06208 d->extra()->validity->titleInfo = help.attributeNS( KoXmlNS::table, "title", QString::null );
06209 }
06210 if ( help.hasAttributeNS( KoXmlNS::table, "display" ) )
06211 {
06212 kdDebug()<<"help.attribute( table:display ) :"<<help.attributeNS( KoXmlNS::table, "display", QString::null )<<endl;
06213 d->extra()->validity->displayValidationInformation = ( ( help.attributeNS( KoXmlNS::table, "display", QString::null )=="true" ) ? true : false );
06214 }
06215 QDomElement attrText = KoDom::namedItemNS( help, KoXmlNS::text, "p" );
06216 if ( !attrText.isNull() )
06217 {
06218 kdDebug()<<"help text :"<<attrText.text()<<endl;
06219 d->extra()->validity->messageInfo = attrText.text();
06220 }
06221 }
06222
06223 QDomElement error = KoDom::namedItemNS( element, KoXmlNS::table, "error-message" );
06224 if ( !error.isNull() )
06225 {
06226 if ( error.hasAttributeNS( KoXmlNS::table, "title" ) )
06227 d->extra()->validity->title = error.attributeNS( KoXmlNS::table, "title", QString::null );
06228 if ( error.hasAttributeNS( KoXmlNS::table, "message-type" ) )
06229 {
06230 QString str = error.attributeNS( KoXmlNS::table, "message-type", QString::null );
06231 if ( str == "warning" )
06232 d->extra()->validity->m_action = Action::Warning;
06233 else if ( str == "information" )
06234 d->extra()->validity->m_action = Action::Information;
06235 else if ( str == "stop" )
06236 d->extra()->validity->m_action = Action::Stop;
06237 else
06238 kdDebug()<<"validation : message type unknown :"<<str<<endl;
06239 }
06240
06241 if ( error.hasAttributeNS( KoXmlNS::table, "display" ) )
06242 {
06243 kdDebug()<<" display message :"<<error.attributeNS( KoXmlNS::table, "display", QString::null )<<endl;
06244 d->extra()->validity->displayMessage = (error.attributeNS( KoXmlNS::table, "display", QString::null )=="true");
06245 }
06246 QDomElement attrText = KoDom::namedItemNS( error, KoXmlNS::text, "p" );
06247 if ( !attrText.isNull() )
06248 d->extra()->validity->message = attrText.text();
06249 }
06250 }
06251
06252
06253 void Cell::loadOasisValidationValue( const QStringList &listVal )
06254 {
06255 bool ok = false;
06256 kdDebug()<<" listVal[0] :"<<listVal[0]<<" listVal[1] :"<<listVal[1]<<endl;
06257
06258 if ( d->extra()->validity->m_restriction == Restriction::Date )
06259 {
06260 d->extra()->validity->dateMin = QDate::fromString( listVal[0] );
06261 d->extra()->validity->dateMax = QDate::fromString( listVal[1] );
06262 }
06263 else if ( d->extra()->validity->m_restriction == Restriction::Time )
06264 {
06265 d->extra()->validity->timeMin = QTime::fromString( listVal[0] );
06266 d->extra()->validity->timeMax = QTime::fromString( listVal[1] );
06267 }
06268 else
06269 {
06270 d->extra()->validity->valMin = listVal[0].toDouble(&ok);
06271 if ( !ok )
06272 {
06273 d->extra()->validity->valMin = listVal[0].toInt(&ok);
06274 if ( !ok )
06275 kdDebug()<<" Try to parse this value :"<<listVal[0]<<endl;
06276
06277 #if 0
06278 if ( !ok )
06279 d->extra()->validity->valMin = listVal[0];
06280 #endif
06281 }
06282 ok=false;
06283 d->extra()->validity->valMax = listVal[1].toDouble(&ok);
06284 if ( !ok )
06285 {
06286 d->extra()->validity->valMax = listVal[1].toInt(&ok);
06287 if ( !ok )
06288 kdDebug()<<" Try to parse this value :"<<listVal[1]<<endl;
06289
06290 #if 0
06291 if ( !ok )
06292 d->extra()->validity->valMax = listVal[1];
06293 #endif
06294 }
06295 }
06296 }
06297
06298 void Cell::loadOasisValidationCondition( QString &valExpression )
06299 {
06300 QString value;
06301 if (valExpression.find( "<=" )==0 )
06302 {
06303 value = valExpression.remove( 0,2 );
06304 d->extra()->validity->m_cond = Conditional::InferiorEqual;
06305 }
06306 else if (valExpression.find( ">=" )==0 )
06307 {
06308 value = valExpression.remove( 0,2 );
06309 d->extra()->validity->m_cond = Conditional::SuperiorEqual;
06310 }
06311 else if (valExpression.find( "!=" )==0 )
06312 {
06313
06314 value = valExpression.remove( 0,2 );
06315 d->extra()->validity->m_cond = Conditional::DifferentTo;
06316 }
06317 else if ( valExpression.find( "<" )==0 )
06318 {
06319 value = valExpression.remove( 0,1 );
06320 d->extra()->validity->m_cond = Conditional::Inferior;
06321 }
06322 else if(valExpression.find( ">" )==0 )
06323 {
06324 value = valExpression.remove( 0,1 );
06325 d->extra()->validity->m_cond = Conditional::Superior;
06326 }
06327 else if (valExpression.find( "=" )==0 )
06328 {
06329 value = valExpression.remove( 0,1 );
06330 d->extra()->validity->m_cond = Conditional::Equal;
06331 }
06332 else
06333 kdDebug()<<" I don't know how to parse it :"<<valExpression<<endl;
06334 if ( d->extra()->validity->m_restriction == Restriction::Date )
06335 {
06336 d->extra()->validity->dateMin = QDate::fromString( value );
06337 }
06338 else if (d->extra()->validity->m_restriction == Restriction::Date )
06339 {
06340 d->extra()->validity->timeMin = QTime::fromString( value );
06341 }
06342 else
06343 {
06344 bool ok = false;
06345 d->extra()->validity->valMin = value.toDouble(&ok);
06346 if ( !ok )
06347 {
06348 d->extra()->validity->valMin = value.toInt(&ok);
06349 if ( !ok )
06350 kdDebug()<<" Try to parse this value :"<<value<<endl;
06351
06352 #if 0
06353 if ( !ok )
06354 d->extra()->validity->valMin = value;
06355 #endif
06356 }
06357 }
06358 }
06359
06360
06361 bool Cell::load( const QDomElement & cell, int _xshift, int _yshift,
06362 Paste::Mode pm, Paste::Operation op, bool paste )
06363 {
06364 bool ok;
06365
06366
06367
06368
06369
06370 d->row = cell.attribute( "row" ).toInt( &ok ) + _yshift;
06371 if ( !ok ) return false;
06372 d->column = cell.attribute( "column" ).toInt( &ok ) + _xshift;
06373 if ( !ok ) return false;
06374
06375
06376 if ( d->row < 1 || d->row > KS_rowMax )
06377 {
06378 kdDebug(36001) << "Cell::load: Value out of Range Cell:row=" << d->row << endl;
06379 return false;
06380 }
06381 if ( d->column < 1 || d->column > KS_colMax )
06382 {
06383 kdDebug(36001) << "Cell::load: Value out of Range Cell:column=" << d->column << endl;
06384 return false;
06385 }
06386
06387
06388
06389
06390 QDomElement f = cell.namedItem( "format" ).toElement();
06391 if ( !f.isNull()
06392 && ( (pm == Paste::Normal) || (pm == Paste::Format) || (pm == Paste::NoBorder) ) )
06393 {
06394
06395
06396 if ( !format()->load( f, pm, paste ) )
06397 return false;
06398
06399 if ( f.hasAttribute( "colspan" ) )
06400 {
06401 int i = f.attribute("colspan").toInt( &ok );
06402 if ( !ok ) return false;
06403
06404 if ( i < 0 || i > KS_spanMax )
06405 {
06406 kdDebug(36001) << "Value out of range Cell::colspan=" << i << endl;
06407 return false;
06408 }
06409 if (i || d->hasExtra())
06410 d->extra()->extraXCells = i;
06411 if ( i > 0 )
06412 {
06413 setFlag(Flag_Merged);
06414 }
06415 }
06416
06417 if ( f.hasAttribute( "rowspan" ) )
06418 {
06419 int i = f.attribute("rowspan").toInt( &ok );
06420 if ( !ok ) return false;
06421
06422 if ( i < 0 || i > KS_spanMax )
06423 {
06424 kdDebug(36001) << "Value out of range Cell::rowspan=" << i << endl;
06425 return false;
06426 }
06427 if (i || d->hasExtra())
06428 d->extra()->extraYCells = i;
06429 if ( i > 0 )
06430 {
06431 setFlag(Flag_Merged);
06432 }
06433 }
06434
06435 if ( testFlag( Flag_Merged ) )
06436 {
06437 if (d->hasExtra())
06438 mergeCells( d->column, d->row, d->extra()->extraXCells, d->extra()->extraYCells );
06439 }
06440
06441 }
06442
06443
06444
06445
06446 QDomElement conditionsElement = cell.namedItem( "condition" ).toElement();
06447 if ( !conditionsElement.isNull())
06448 {
06449 if (d->hasExtra())
06450 delete d->extra()->conditions;
06451 d->extra()->conditions = new Conditions( this );
06452 d->extra()->conditions->loadConditions( conditionsElement );
06453 d->extra()->conditions->checkMatches();
06454 }
06455 else if ((pm == Paste::Normal) || (pm == Paste::NoBorder))
06456 {
06457
06458 if (d->hasExtra())
06459 {
06460 delete d->extra()->conditions;
06461 d->extra()->conditions = 0;
06462 }
06463 }
06464
06465 QDomElement validity = cell.namedItem( "validity" ).toElement();
06466 if ( !validity.isNull())
06467 {
06468 QDomElement param = validity.namedItem( "param" ).toElement();
06469 if(!param.isNull())
06470 {
06471 d->extra()->validity = new Validity;
06472 if ( param.hasAttribute( "cond" ) )
06473 {
06474 d->extra()->validity->m_cond = (Conditional::Type) param.attribute("cond").toInt( &ok );
06475 if ( !ok )
06476 return false;
06477 }
06478 if ( param.hasAttribute( "action" ) )
06479 {
06480 d->extra()->validity->m_action = (Action::Type) param.attribute("action").toInt( &ok );
06481 if ( !ok )
06482 return false;
06483 }
06484 if ( param.hasAttribute( "allow" ) )
06485 {
06486 d->extra()->validity->m_restriction = (Restriction::Type) param.attribute("allow").toInt( &ok );
06487 if ( !ok )
06488 return false;
06489 }
06490 if ( param.hasAttribute( "valmin" ) )
06491 {
06492 d->extra()->validity->valMin = param.attribute("valmin").toDouble( &ok );
06493 if ( !ok )
06494 return false;
06495 }
06496 if ( param.hasAttribute( "valmax" ) )
06497 {
06498 d->extra()->validity->valMax = param.attribute("valmax").toDouble( &ok );
06499 if ( !ok )
06500 return false;
06501 }
06502 if ( param.hasAttribute( "displaymessage" ) )
06503 {
06504 d->extra()->validity->displayMessage = ( bool )param.attribute("displaymessage").toInt();
06505 }
06506 if ( param.hasAttribute( "displayvalidationinformation" ) )
06507 {
06508 d->extra()->validity->displayValidationInformation = ( bool )param.attribute("displayvalidationinformation").toInt();
06509 }
06510 if ( param.hasAttribute( "allowemptycell" ) )
06511 {
06512 d->extra()->validity->allowEmptyCell = ( bool )param.attribute("allowemptycell").toInt();
06513 }
06514 if ( param.hasAttribute("listvalidity") )
06515 {
06516 d->extra()->validity->listValidity=QStringList::split(";", param.attribute("listvalidity") );
06517 }
06518 }
06519 QDomElement inputTitle = validity.namedItem( "inputtitle" ).toElement();
06520 if (!inputTitle.isNull())
06521 {
06522 d->extra()->validity->titleInfo = inputTitle.text();
06523 }
06524 QDomElement inputMessage = validity.namedItem( "inputmessage" ).toElement();
06525 if (!inputMessage.isNull())
06526 {
06527 d->extra()->validity->messageInfo = inputMessage.text();
06528 }
06529
06530 QDomElement title = validity.namedItem( "title" ).toElement();
06531 if (!title.isNull())
06532 {
06533 d->extra()->validity->title = title.text();
06534 }
06535 QDomElement message = validity.namedItem( "message" ).toElement();
06536 if (!message.isNull())
06537 {
06538 d->extra()->validity->message = message.text();
06539 }
06540 QDomElement timeMin = validity.namedItem( "timemin" ).toElement();
06541 if ( !timeMin.isNull() )
06542 {
06543 d->extra()->validity->timeMin = toTime(timeMin);
06544 }
06545 QDomElement timeMax = validity.namedItem( "timemax" ).toElement();
06546 if ( !timeMax.isNull() )
06547 {
06548 d->extra()->validity->timeMax = toTime(timeMax);
06549 }
06550 QDomElement dateMin = validity.namedItem( "datemin" ).toElement();
06551 if ( !dateMin.isNull() )
06552 {
06553 d->extra()->validity->dateMin = toDate(dateMin);
06554 }
06555 QDomElement dateMax = validity.namedItem( "datemax" ).toElement();
06556 if ( !dateMax.isNull() )
06557 {
06558 d->extra()->validity->dateMax = toDate(dateMax);
06559 }
06560 }
06561 else if ((pm == Paste::Normal) || (pm == Paste::NoBorder))
06562 {
06563
06564 removeValidity();
06565 }
06566
06567
06568
06569
06570 QDomElement comment = cell.namedItem( "comment" ).toElement();
06571 if ( !comment.isNull() && ( pm == Paste::Normal || pm == Paste::Comment || pm == Paste::NoBorder ))
06572 {
06573 QString t = comment.text();
06574
06575 format()->setComment( t );
06576 }
06577
06578
06579
06580
06581
06582
06583
06584 QDomElement text = cell.namedItem( "text" ).toElement();
06585
06586 if ( !text.isNull() &&
06587 ( pm == Paste::Normal || pm == Paste::Text || pm == Paste::NoBorder || pm == Paste::Result ) )
06588 {
06589
06590
06591
06592 if ( cell.hasAttribute( "dataType" ) )
06593 text.setAttribute( "dataType", cell.attribute( "dataType" ) );
06594
06595 QDomElement result = cell.namedItem( "result" ).toElement();
06596 QString txt = text.text();
06597 if ((pm == Paste::Result) && (txt[0] == '='))
06598
06599
06600
06601
06602 d->strText = result.text();
06603 else
06604
06605 loadCellData(text, op);
06606
06607 if ( !result.isNull() )
06608 {
06609 QString dataType;
06610 QString t = result.text();
06611
06612 if ( result.hasAttribute( "dataType" ) )
06613 dataType = result.attribute( "dataType" );
06614 if ( result.hasAttribute( "outStr" ) )
06615 {
06616 d->strOutText = result.attribute( "outStr" );
06617 if ( !d->strOutText.isEmpty() )
06618 clearFlag( Flag_TextFormatDirty );
06619 }
06620
06621 bool clear = true;
06622
06623 if( dataType == "Bool" )
06624 {
06625 if ( t == "false" )
06626 setValue( false );
06627 else if ( t == "true" )
06628 setValue( true );
06629 else
06630 clear = false;
06631 }
06632 else if( dataType == "Num" )
06633 {
06634 bool ok = false;
06635 double dd = t.toDouble( &ok );
06636 if ( ok )
06637 setValue ( dd );
06638 else
06639 clear = false;
06640 }
06641 else if( dataType == "Date" )
06642 {
06643 bool ok = false;
06644 double dd = t.toDouble( &ok );
06645 if ( ok )
06646 setValue ( dd );
06647 else
06648 {
06649 int pos = t.find( '/' );
06650 int year = t.mid( 0, pos ).toInt();
06651 int pos1 = t.find( '/', pos + 1 );
06652 int month = t.mid( pos + 1, ( ( pos1 - 1 ) - pos ) ).toInt();
06653 int day = t.right( t.length() - pos1 - 1 ).toInt();
06654 QDate date( year, month, day );
06655 if ( date.isValid() )
06656 setValue( date );
06657 else
06658 clear = false;
06659 }
06660 }
06661 else if( dataType == "Time" )
06662 {
06663 bool ok = false;
06664 double dd = t.toDouble( &ok );
06665 if ( ok )
06666 setCellValue( dd );
06667 else
06668 {
06669 int hours = -1;
06670 int minutes = -1;
06671 int second = -1;
06672 int pos, pos1;
06673 pos = t.find( ':' );
06674 hours = t.mid( 0, pos ).toInt();
06675 pos1 = t.find( ':', pos + 1 );
06676 minutes = t.mid( pos + 1, ( ( pos1 - 1 ) - pos ) ).toInt();
06677 second = t.right( t.length() - pos1 - 1 ).toInt();
06678 QTime time( hours, minutes, second );
06679 if ( time.isValid() )
06680 setValue( time );
06681 else
06682 clear = false;
06683 }
06684 }
06685 else
06686 {
06687 setValue( t );
06688 }
06689
06690
06691
06692 }
06693 }
06694
06695 return true;
06696 }
06697
06698 bool Cell::loadCellData(const QDomElement & text, Paste::Operation op )
06699 {
06700
06701
06702 QString t = text.text();
06703 t = t.stripWhiteSpace();
06704
06705 setFlag(Flag_LayoutDirty);
06706 setFlag(Flag_TextFormatDirty);
06707
06708
06709 if( t[0] == '=' )
06710 {
06711 t = decodeFormula( t, d->column, d->row );
06712 setCellText (pasteOperation( t, d->strText, op ));
06713
06714 setFlag(Flag_CalcDirty);
06715 clearAllErrors();
06716
06717 if ( !makeFormula() )
06718 kdError(36001) << "ERROR: Syntax ERROR" << endl;
06719 }
06720
06721 else if (t[0] == '!' )
06722 {
06723
06724
06725
06726 bool inside_tag = false;
06727 QString qml_text;
06728 QString tag;
06729 QString qml_link;
06730
06731 for( unsigned i = 1; i < t.length(); i++ )
06732 {
06733 QChar ch = t[i];
06734 if( ch == '<' )
06735 {
06736 if( !inside_tag )
06737 {
06738 inside_tag = true;
06739 tag = QString::null;
06740 }
06741 }
06742 else if( ch == '>' )
06743 {
06744 if( inside_tag )
06745 {
06746 inside_tag = false;
06747 if( tag.startsWith( "a href=\"", true ) )
06748 if( tag.endsWith( "\"" ) )
06749 qml_link = tag.mid( 8, tag.length()-9 );
06750 tag = QString::null;
06751 }
06752 }
06753 else
06754 {
06755 if( !inside_tag )
06756 qml_text += ch;
06757 else
06758 tag += ch;
06759 }
06760 }
06761
06762 if( !qml_link.isEmpty() )
06763 d->extra()->link = qml_link;
06764 d->strText = qml_text;
06765 setValue( d->strText );
06766 }
06767 else
06768 {
06769 bool newStyleLoading = true;
06770 QString dataType;
06771
06772 if ( text.hasAttribute( "dataType" ) )
06773 {
06774 dataType = text.attribute( "dataType" );
06775 }
06776 else
06777 {
06778
06779 if (isDate() && ( t.contains('/') == 2 ))
06780 dataType = "Date";
06781 else if (isTime() && ( t.contains(':') == 2 ) )
06782 dataType = "Time";
06783 else
06784 {
06785 d->strText = pasteOperation( t, d->strText, op );
06786 checkTextInput();
06787
06788 newStyleLoading = false;
06789 }
06790 }
06791
06792 if ( newStyleLoading )
06793 {
06794 d->value = Value::empty();
06795 clearAllErrors();
06796
06797
06798 if( dataType == "Bool" )
06799 {
06800 bool val = (t.lower() == "true");
06801 setCellValue (val);
06802 }
06803
06804
06805 else if( dataType == "Num" )
06806 {
06807 bool ok = false;
06808 if (t.contains('.'))
06809 setValue ( Value( t.toDouble(&ok) ) );
06810 else
06811 setValue ( Value( t.toLong(&ok) ) );
06812 if ( !ok )
06813 {
06814 kdWarning(36001) << "Couldn't parse '" << t << "' as number." << endl;
06815 }
06816
06817 KLocale* locale = format()->sheet()->doc()->locale();
06818
06819
06820
06821 int precision = t.length() - t.find('.') - 1;
06822
06823 if ( formatType() == Percentage_format )
06824 {
06825 if (value().isInteger())
06826 t = locale->formatNumber( value().asInteger() * 100 );
06827 else
06828 t = locale->formatNumber( value().asFloat() * 100.0, precision );
06829 d->strText = pasteOperation( t, d->strText, op );
06830 d->strText += '%';
06831 }
06832 else
06833 {
06834 if (value().isInteger())
06835 t = locale->formatLong(value().asInteger());
06836 else
06837 t = locale->formatNumber(value().asFloat(), precision);
06838 d->strText = pasteOperation( t, d->strText, op );
06839 }
06840 }
06841
06842
06843 else if( dataType == "Date" )
06844 {
06845 int pos = t.find('/');
06846 int year = t.mid(0,pos).toInt();
06847 int pos1 = t.find('/',pos+1);
06848 int month = t.mid(pos+1,((pos1-1)-pos)).toInt();
06849 int day = t.right(t.length()-pos1-1).toInt();
06850 setValue( QDate(year,month,day) );
06851 if ( value().asDate().isValid() )
06852 d->strText = locale()->formatDate( value().asDate(), true );
06853 else
06854 {
06855 d->strText = pasteOperation( t, d->strText, op );
06856 checkTextInput();
06857 }
06858 }
06859
06860
06861 else if( dataType == "Time" )
06862 {
06863 int hours = -1;
06864 int minutes = -1;
06865 int second = -1;
06866 int pos, pos1;
06867 pos = t.find(':');
06868 hours = t.mid(0,pos).toInt();
06869 pos1 = t.find(':',pos+1);
06870 minutes = t.mid(pos+1,((pos1-1)-pos)).toInt();
06871 second = t.right(t.length()-pos1-1).toInt();
06872 setValue( QTime(hours,minutes,second) );
06873 if ( value().asTime().isValid() )
06874 d->strText = locale()->formatTime( value().asTime(), true );
06875 else
06876 {
06877 d->strText = pasteOperation( t, d->strText, op );
06878 checkTextInput();
06879 }
06880 }
06881
06882 else
06883 {
06884
06885 d->strText = pasteOperation( t, d->strText, op );
06886 setValue( d->strText );
06887 }
06888 }
06889 }
06890
06891 if ( text.hasAttribute( "outStr" ) )
06892 {
06893 d->strOutText = text.attribute( "outStr" );
06894 if ( !d->strOutText.isEmpty() )
06895 clearFlag( Flag_TextFormatDirty );
06896 }
06897
06898 if ( !format()->sheet()->isLoading() )
06899 setCellText( d->strText );
06900
06901 if ( d->hasExtra() && d->extra()->conditions )
06902 d->extra()->conditions->checkMatches();
06903
06904 return true;
06905 }
06906
06907 QTime Cell::toTime(const QDomElement &element)
06908 {
06909
06910 QString t = element.text();
06911 t = t.stripWhiteSpace();
06912 int hours = -1;
06913 int minutes = -1;
06914 int second = -1;
06915 int pos, pos1;
06916 pos = t.find(':');
06917 hours = t.mid(0,pos).toInt();
06918 pos1 = t.find(':',pos+1);
06919 minutes = t.mid(pos+1,((pos1-1)-pos)).toInt();
06920 second = t.right(t.length()-pos1-1).toInt();
06921 setValue( Value( QTime(hours,minutes,second)) );
06922 return value().asTime();
06923 }
06924
06925 QDate Cell::toDate(const QDomElement &element)
06926 {
06927 QString t = element.text();
06928 int pos;
06929 int pos1;
06930 int year = -1;
06931 int month = -1;
06932 int day = -1;
06933 pos = t.find('/');
06934 year = t.mid(0,pos).toInt();
06935 pos1 = t.find('/',pos+1);
06936 month = t.mid(pos+1,((pos1-1)-pos)).toInt();
06937 day = t.right(t.length()-pos1-1).toInt();
06938 setValue( Value( QDate(year,month,day) ) );
06939 return value().asDate();
06940 }
06941
06942 QString Cell::pasteOperation( const QString &new_text, const QString &old_text, Paste::Operation op )
06943 {
06944 if ( op == Paste::OverWrite )
06945 return new_text;
06946
06947 QString tmp_op;
06948 QString tmp;
06949 QString old;
06950
06951 if( !new_text.isEmpty() && new_text[0] == '=' )
06952 {
06953 tmp = new_text.right( new_text.length() - 1 );
06954 }
06955 else
06956 {
06957 tmp = new_text;
06958 }
06959
06960 if ( old_text.isEmpty() &&
06961 ( op == Paste::Add || op == Paste::Mul || op == Paste::Sub || op == Paste::Div ) )
06962 {
06963 old = "=0";
06964 }
06965
06966 if( !old_text.isEmpty() && old_text[0] == '=' )
06967 {
06968 old = old_text.right( old_text.length() - 1 );
06969 }
06970 else
06971 {
06972 old = old_text;
06973 }
06974
06975 bool b1, b2;
06976 tmp.toDouble( &b1 );
06977 old.toDouble( &b2 );
06978 if (b1 && !b2 && old.length() == 0)
06979 {
06980 old = "0";
06981 b2 = true;
06982 }
06983
06984 if( b1 && b2 )
06985 {
06986 switch( op )
06987 {
06988 case Paste::Add:
06989 tmp_op = QString::number(old.toDouble()+tmp.toDouble());
06990 break;
06991 case Paste::Mul :
06992 tmp_op = QString::number(old.toDouble()*tmp.toDouble());
06993 break;
06994 case Paste::Sub:
06995 tmp_op = QString::number(old.toDouble()-tmp.toDouble());
06996 break;
06997 case Paste::Div:
06998 tmp_op = QString::number(old.toDouble()/tmp.toDouble());
06999 break;
07000 default:
07001 Q_ASSERT( 0 );
07002 }
07003
07004 setFlag(Flag_LayoutDirty);
07005 clearAllErrors();
07006
07007 return tmp_op;
07008 }
07009 else if ( ( new_text[0] == '=' && old_text[0] == '=' ) ||
07010 ( b1 && old_text[0] == '=' ) || ( new_text[0] == '=' && b2 ) )
07011 {
07012 switch( op )
07013 {
07014 case Paste::Add :
07015 tmp_op="=("+old+")+"+"("+tmp+")";
07016 break;
07017 case Paste::Mul :
07018 tmp_op="=("+old+")*"+"("+tmp+")";
07019 break;
07020 case Paste::Sub:
07021 tmp_op="=("+old+")-"+"("+tmp+")";
07022 break;
07023 case Paste::Div:
07024 tmp_op="=("+old+")/"+"("+tmp+")";
07025 break;
07026 default :
07027 Q_ASSERT( 0 );
07028 }
07029
07030 tmp_op = decodeFormula( tmp_op, d->column, d->row );
07031 setFlag(Flag_LayoutDirty);
07032 clearAllErrors();
07033
07034 return tmp_op;
07035 }
07036
07037 tmp = decodeFormula( new_text, d->column, d->row );
07038 setFlag(Flag_LayoutDirty);
07039 clearAllErrors();
07040
07041 return tmp;
07042 }
07043
07044 QString Cell::testAnchor( int x, int y ) const
07045 {
07046 if( link().isEmpty() )
07047 return QString::null;
07048
07049 const Doc* doc = format()->sheet()->doc();
07050 int x1 = doc->zoomItX( d->textX );
07051 int y1 = doc->zoomItX( d->textY - d->textHeight );
07052 int x2 = doc->zoomItX( d->textX + d->textWidth );
07053 int y2 = doc->zoomItX( d->textY );
07054
07055 if( x > x1 ) if( x < x2 )
07056 if( y > y1 ) if( y < y2 )
07057 return link();
07058
07059 return QString::null;
07060 }
07061
07062 void Cell::sheetDies()
07063 {
07064
07065 if (d->hasExtra())
07066 {
07067 d->extra()->extraXCells = 0;
07068 d->extra()->extraYCells = 0;
07069 d->extra()->mergedXCells = 0;
07070 d->extra()->mergedYCells = 0;
07071 }
07072
07073
07074
07075 }
07076
07077 Cell::~Cell()
07078 {
07079 if ( d->nextCell )
07080 d->nextCell->setPreviousCell( d->previousCell );
07081 if ( d->previousCell )
07082 d->previousCell->setNextCell( d->nextCell );
07083
07084 if (d->hasExtra())
07085 {
07086 delete d->extra()->validity;
07087 }
07088
07089
07090 int extraXCells = d->hasExtra() ? d->extra()->extraXCells : 0;
07091 int extraYCells = d->hasExtra() ? d->extra()->extraYCells : 0;
07092 for( int x = 0; x <= extraXCells; ++x )
07093 for( int y = (x == 0) ? 1 : 0;
07094 y <= extraYCells; ++y )
07095 {
07096 Cell* cell = format()->sheet()->cellAt( d->column + x, d->row + y );
07097 if ( cell )
07098 cell->unobscure(this);
07099 }
07100
07101 d->value = Value::empty();
07102
07103 if (!isDefault())
07104 valueChanged ();
07105
07106 delete d->format;
07107 delete d;
07108 }
07109
07110 bool Cell::operator > ( const Cell & cell ) const
07111 {
07112 if ( value().isNumber() )
07113 {
07114 if ( cell.value().isNumber() )
07115 return value().asFloat() > cell.value().asFloat();
07116 else
07117 return false;
07118 }
07119 else if(isDate())
07120 {
07121 if( cell.isDate() )
07122 return value().asDate() > cell.value().asDate();
07123 else if (cell.value().isNumber())
07124 return true;
07125 else
07126 return false;
07127 }
07128 else if(isTime())
07129 {
07130 if( cell.isTime() )
07131 return value().asTime() > cell.value().asTime();
07132 else if( cell.isDate())
07133 return true;
07134 else if( cell.value().isNumber())
07135 return true;
07136 else
07137 return false;
07138 }
07139 else
07140 {
07141 if ( Map::respectCase )
07142 return value().asString().compare(cell.value().asString()) > 0;
07143 else
07144 return ( value().asString() ).lower().compare(cell.value().asString().lower()) > 0;
07145 }
07146 }
07147
07148 bool Cell::operator < ( const Cell & cell ) const
07149 {
07150 if ( value().isNumber() )
07151 {
07152 if ( cell.value().isNumber() )
07153 return value().asFloat() < cell.value().asFloat();
07154 else
07155 return true;
07156 }
07157 else if(isDate())
07158 {
07159 if( cell.isDate() )
07160 return value().asDateTime().date() < cell.value().asDateTime().date();
07161 else if( cell.value().isNumber())
07162 return false;
07163 else
07164 return true;
07165 }
07166 else if(isTime())
07167 {
07168 if( cell.isTime() )
07169 return value().asDateTime().time() < cell.value().asDateTime().time();
07170 else if(cell.isDate())
07171 return false;
07172 else if( cell.value().isNumber())
07173 return false;
07174 else
07175 return true;
07176 }
07177 else
07178 {
07179 if ( Map::respectCase )
07180 return value().asString().compare(cell.value().asString()) < 0;
07181 else
07182 return ( value().asString() ).lower().compare(cell.value().asString().lower()) < 0;
07183 }
07184 }
07185
07186 bool Cell::operator==( const Cell& other ) const
07187 {
07188 if ( d->strText != other.d->strText )
07189 return false;
07190 if ( d->value != other.d->value )
07191 return false;
07192 if ( *d->format != *other.d->format )
07193 return false;
07194 if ( d->hasExtra() )
07195 {
07196 if ( !other.d->hasExtra() )
07197 return false;
07198 if ( d->extra()->link != other.d->extra()->link )
07199 return false;
07200 if ( d->extra()->mergedXCells != other.d->extra()->mergedXCells )
07201 return false;
07202 if ( d->extra()->mergedYCells != other.d->extra()->mergedYCells )
07203 return false;
07204 if ( d->extra()->conditions )
07205 {
07206 if ( !other.d->extra()->conditions )
07207 return false;
07208 if ( *d->extra()->conditions != *other.d->extra()->conditions )
07209 return false;
07210 }
07211 if ( d->extra()->validity )
07212 {
07213 if ( !other.d->extra()->validity )
07214 return false;
07215 if ( *d->extra()->validity != *other.d->extra()->validity )
07216 return false;
07217 }
07218 }
07219 return true;
07220 }
07221
07222 QRect Cell::cellRect()
07223 {
07224 Q_ASSERT(!isDefault());
07225 return QRect(QPoint(d->column, d->row), QPoint(d->column, d->row));
07226 }
07227
07228 QValueList<Conditional> Cell::conditionList() const
07229 {
07230 if ( !d->hasExtra() || !d->extra()->conditions )
07231 {
07232 QValueList<Conditional> emptyList;
07233 return emptyList;
07234 }
07235
07236 return d->extra()->conditions->conditionList();
07237 }
07238
07239 void Cell::setConditionList( const QValueList<Conditional> & newList )
07240 {
07241 if (d->hasExtra())
07242 delete d->extra()->conditions;
07243 d->extra()->conditions = new Conditions( this );
07244 d->extra()->conditions->setConditionList( newList );
07245 d->extra()->conditions->checkMatches();
07246 }
07247
07248 bool Cell::hasError() const
07249 {
07250 return ( testFlag(Flag_ParseError) ||
07251 testFlag(Flag_CircularCalculation) ||
07252 testFlag(Flag_DependancyError));
07253 }
07254
07255 void Cell::clearAllErrors()
07256 {
07257 clearFlag( Flag_ParseError );
07258 clearFlag( Flag_CircularCalculation );
07259 clearFlag( Flag_DependancyError );
07260 }
07261
07262 bool Cell::calcDirtyFlag()
07263 {
07264 return isFormula() ? testFlag( Flag_CalcDirty ) : false;
07265 }
07266
07267 bool Cell::layoutDirtyFlag() const
07268 {
07269 return testFlag( Flag_LayoutDirty );
07270 }
07271
07272 void Cell::clearDisplayDirtyFlag()
07273 {
07274 clearFlag( Flag_DisplayDirty );
07275 }
07276
07277 void Cell::setDisplayDirtyFlag()
07278 {
07279 setFlag( Flag_DisplayDirty );
07280 }
07281
07282 bool Cell::doesMergeCells() const
07283 {
07284 return testFlag( Flag_Merged );
07285 }
07286
07287 void Cell::clearFlag( CellFlags flag )
07288 {
07289 d->flags &= ~(Q_UINT32)flag;
07290 }
07291
07292 void Cell::setFlag( CellFlags flag )
07293 {
07294 d->flags |= (Q_UINT32)flag;
07295 }
07296
07297 bool Cell::testFlag( CellFlags flag ) const
07298 {
07299 return ( d->flags & (Q_UINT32)flag );
07300 }
07301
07302
07303 void Cell::checkForNamedAreas( QString & formula ) const
07304 {
07305 KSPLoadingInfo* loadinginfo = sheet()->doc()->loadingInfo();
07306 if(! loadinginfo) {
07307 kdDebug() << "Cell::checkForNamedAreas loadinginfo is NULL" << endl;
07308 return;
07309 }
07310
07311 int l = formula.length();
07312 int i = 0;
07313 QString word;
07314 int start = 0;
07315 while ( i < l )
07316 {
07317 if ( formula[i].isLetterOrNumber() )
07318 {
07319 word += formula[i];
07320 ++i;
07321 continue;
07322 }
07323 if ( !word.isEmpty() )
07324 {
07325 if ( loadinginfo->findWordInAreaList(word) )
07326 {
07327 formula = formula.replace( start, word.length(), "'" + word + "'" );
07328 l = formula.length();
07329 ++i;
07330 kdDebug() << "Formula: " << formula << ", L: " << l << ", i: " << i + 1 <<endl;
07331 }
07332 }
07333
07334 ++i;
07335 word = "";
07336 start = i;
07337 }
07338 if ( !word.isEmpty() )
07339 {
07340 if ( loadinginfo->findWordInAreaList(word) )
07341 {
07342 formula = formula.replace( start, word.length(), "'" + word + "'" );
07343 l = formula.length();
07344 ++i;
07345 kdDebug() << "Formula: " << formula << ", L: " << l << ", i: " << i + 1 <<endl;
07346 }
07347 }
07348 }