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