summaryrefslogtreecommitdiffstats
path: root/kspread/kspread_cell.cc
diff options
context:
space:
mode:
authorMichele Calgaro <[email protected]>2021-05-23 20:48:35 +0900
committerMichele Calgaro <[email protected]>2021-05-29 15:16:28 +0900
commit8b78a8791bc539bcffe7159f9d9714d577cb3d7d (patch)
tree1328291f966f19a22d7b13657d3f01a588eb1083 /kspread/kspread_cell.cc
parent95834e2bdc5e01ae1bd21ac0dfa4fa1d2417fae9 (diff)
downloadkoffice-8b78a8791bc539bcffe7159f9d9714d577cb3d7d.tar.gz
koffice-8b78a8791bc539bcffe7159f9d9714d577cb3d7d.zip
Renaming of files in preparation for code style tools.
Signed-off-by: Michele Calgaro <[email protected]>
Diffstat (limited to 'kspread/kspread_cell.cc')
-rw-r--r--kspread/kspread_cell.cc7348
1 files changed, 0 insertions, 7348 deletions
diff --git a/kspread/kspread_cell.cc b/kspread/kspread_cell.cc
deleted file mode 100644
index fca76bbe..00000000
--- a/kspread/kspread_cell.cc
+++ /dev/null
@@ -1,7348 +0,0 @@
-/* This file is part of the KDE project
-
- Copyright 2006 Stefan Nikolaus <[email protected]>
- Copyright 2005 Raphael Langerhorst <[email protected]>
- Copyright 2004-2005 Tomas Mecir <[email protected]>
- Copyright 2004-2006 Inge Wallin <[email protected]>
- Copyright 1999-2002,2004,2005 Laurent Montel <[email protected]>
- Copyright 2002-2005 Ariya Hidayat <[email protected]>
- Copyright 2001-2003 Philipp Mueller <[email protected]>
- Copyright 2002-2003 Norbert Andres <[email protected]>
- Copyright 2003 Reinhart Geiser <[email protected]>
- Copyright 2003-2005 Meni Livne <[email protected]>
- Copyright 2003 Peter Simonsson <[email protected]>
- Copyright 1999-2002 David Faure <[email protected]>
- Copyright 2000-2002 Werner Trobin <[email protected]>
- Copyright 1999,2002 Harri Porten <[email protected]>
- Copyright 2002 John Dailey <[email protected]>
- Copyright 1998-2000 Torben Weis <[email protected]>
- Copyright 2000 Bernd Wuebben <[email protected]>
- Copyright 2000 Simon Hausmann <[email protected]
- Copyright 1999 Stephan Kulow <[email protected]>
- Copyright 1999 Michael Reiher <michael.reiher.gmx.de>
- Copyright 1999 Boris Wedl <[email protected]>
- Copyright 1998-1999 Reginald Stadlbauer <[email protected]>
-
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public License
- along with this library; see the file COPYING.LIB. If not, write to
- the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
-*/
-
-#include <stdlib.h>
-#include <ctype.h>
-#include <float.h>
-#include <math.h>
-
-#include <tqapplication.h>
-#include <tqpopupmenu.h>
-#include <tqregexp.h>
-
-#include "kspread_canvas.h"
-#include "kspread_condition.h"
-#include "kspread_doc.h"
-#include "kspread_format.h"
-#include "kspread_global.h"
-#include "kspread_map.h"
-#include "kspread_sheet.h"
-#include "kspread_sheetprint.h"
-#include "kspread_style.h"
-#include "kspread_style_manager.h"
-#include "kspread_util.h"
-#include "ksploadinginfo.h"
-#include "kspread_genvalidationstyle.h"
-#include "kspread_locale.h"
-#include "kspread_value.h"
-#include "kspread_view.h"
-#include "kspread_value.h"
-#include "formula.h"
-#include "selection.h"
-#include "valueconverter.h"
-#include "valueformatter.h"
-#include "valueparser.h"
-
-#include <KoStyleStack.h>
-#include <KoRect.h>
-#include <KoXmlNS.h>
-#include <KoDom.h>
-#include <KoXmlWriter.h>
-#include <KoOasisStyles.h>
-
-#include <tdemessagebox.h>
-
-#include <kdebug.h>
-
-using namespace KSpread;
-
-#define BORDER_SPACE 1
-
-
-/**
- * A pointer to the decimal separator
- */
-
-namespace Cell_LNS
-{
- TQChar decimal_point = '\0';
-}
-
-using namespace Cell_LNS;
-
-
-// Some variables are placed in Cell::Extra because normally they're
-// not required in simple case of cell(s). For example, most plain
-// text cells don't need to store information about spanned columns
-// and rows, as this is only the case with merged cells.
-//
-// When the cell is getting complex (e.g. merged with other cells,
-// contains rich text, has validation criteria, etc), this Cell::Extra
-// is allocated by Cell::Private and starts to be
-// available. Otherwise, it won't exist at all.
-
-class Cell::Extra
-{
-public:
- Extra() {}
-
- // Not empty when the cell holds a link
- TQString link;
-
- // Number of cells explicitly merged by the user in X and Y directions.
- int mergedXCells;
- int mergedYCells;
-
- // Number of additional cells.
- int extraXCells;
- int extraYCells;
-
- // If this cell overlaps other cells, then we have the cells width and
- // height stored here. These values do not mean anything unless
- // extraXCells and/or extraYCells are different from 0.
- double extraWidth;
- double extraHeight;
-
- // A list of cells that obscure this one.
- // If this list is not empty, then this cell is obscured by another
- // enlarged object. This means that we have to call this object in order
- // of painting it for example instead of painting 'this'.
- //
- // FIXME (comment): If the list consists of more than one obscuring
- // element, then is there an order between them that
- // is important?
- TQValueList<Cell*> obscuringCells;
-
- // If non-NULL, contains a pointer to a condition or a validity test.
- Conditions *conditions;
- Validity *validity;
-
- // Store the number of line when multirow is used (default is 0)
- int nbLines;
-
-private:
- // Don't allow implicit copy.
- Extra& operator=( const Extra& );
-};
-
-
-class Cell::Private
-{
-public:
-
- Private();
- ~Private();
-
-public:
-
- // This cell's row and column. If either of them is 0, this is the
- // default cell and its row/column can not be determined. Note that
- // in the isDefault() method, only column is tested.
- int row;
- int column;
-
- // Value of the cell, either typed by user or as result of formula
- Value value;
-
- // Holds the user's input.
- //
- // FIXME:
- // Eventually, we'll want to get rid of strText and generate
- // user's input on-the-fly. Then, for normal cells, we'll generate
- // this string using converter()->asString
- // (value()).
- //
- // Here the problem is, that strText also holds the formula -
- // we'll need to provide some method to generate it from the
- // parsed version, created in KSpread::Formula. Hence, we won't be
- // able to get rid of strText until we switch to the new formula
- // parser and until we write some method that re-generates the
- // input formula...
- //
- // Alternately, we can keep using strText for formulas and
- // generate it dynamically for static cells...
- //
- // /Tomas
- //
- TQString strText;
-
- // This is the text we want to display. Not necessarily the same
- // as strText, e.g. strText="1" and strOutText="1.00" Also holds
- // value that we got from calculation, formerly known as
- // strFormulaOut
- TQString strOutText;
-
- // the Formula object for the cell
- KSpread::Formula *formula;
-
- // Position and dimension of displayed text.
- // FIXME (comment): Which coordinate system? pixels? mm/cm? zoom?
- double textX;
- double textY;
- double textWidth;
- double textHeight;
-
- // result of "fm.ascent()" in makeLayout. used in offsetAlign.
- int fmAscent;
-
- // Pointers to neighboring cells.
- // FIXME (comment): Which order?
- Cell *nextCell;
- Cell *previousCell;
-
- bool hasExtra() const { return (cellExtra != 0); };
- Extra *extra();
-
- Format *format;
- TQ_UINT32 flags;
-
-private:
- // "Extra stuff", see explanation for Cell::Extra.
- Extra *cellExtra;
-};
-
-
-Cell::Private::Private()
-{
- // Some basic data.
- row = 0;
- column = 0;
- value = Value::empty();
- formula = 0;
-
- // Formatting
- textX = 0.0;
- textY = 0.0;
- textWidth = 0.0;
- textHeight = 0.0;
- fmAscent = 0;
-
- nextCell = 0;
- previousCell = 0;
-
- // Default is to not have the "extra" stuff in a cell.
- cellExtra = 0;
- format = 0;
- flags = 0;
-}
-
-
-Cell::Private::~Private()
-{
- delete cellExtra;
- delete formula;
-}
-
-
-Cell::Extra* Cell::Private::extra()
-{
- if ( !cellExtra ) {
- cellExtra = new Extra;
- cellExtra->conditions = 0;
- cellExtra->validity = 0;
-
- cellExtra->mergedXCells = 0;
- cellExtra->mergedYCells = 0;
- cellExtra->extraXCells = 0;
- cellExtra->extraYCells = 0;
- cellExtra->extraWidth = 0.0;
- cellExtra->extraHeight = 0.0;
- cellExtra->nbLines = 0;
-// cellExtra->highlight = TQColor(0,0,0);
- }
-
- return cellExtra;
-}
-
-
-/*****************************************************************************
- *
- * Cell
- *
- *****************************************************************************/
-
-
-Cell::Cell( Sheet * _sheet, int _column, int _row )
-{
- d = new Private;
- d->row = _row;
- d->column = _column;
- d->format = new Format(_sheet, _sheet->doc()->styleManager()->defaultStyle());
- d->format->setCell(this);
- clearAllErrors();
-}
-
-
-Cell::Cell( Sheet * _sheet, Style * _style, int _column, int _row )
-{
- d = new Private;
- d->row = _row;
- d->column = _column;
- d->format = new Format( _sheet, _style );
- d->format->setCell(this);
-
- clearAllErrors();
-}
-
-Format* Cell::format() const
-{
- return d->format;
-}
-
-// Return the sheet that this cell belongs to.
-Sheet * Cell::sheet() const
-{
- return d->format->sheet();
-}
-
-// Return true if this is the default cell.
-bool Cell::isDefault() const
-{
- return ( d->column == 0 );
-}
-
-// Return the row number of this cell.
-int Cell::row() const
-{
- // Make sure this isn't called for the default cell. This assert
- // can save you (could have saved me!) the hassle of some very
- // obscure bugs.
-
- if ( isDefault() )
- {
- kdWarning(36001) << "Error: Calling Cell::row() for default cell" << endl;
- return 0;
- }
-
- return d->row;
-}
-
-
-// Return the column number of this cell.
-//
-int Cell::column() const
-{
- // Make sure this isn't called for the default cell. This assert
- // can save you (could have saved me!) the hassle of some very
- // obscure bugs.
- if ( isDefault() )
- {
- kdWarning(36001) << "Error: Calling Cell::column() for default cell" << endl;
- return 0;
- }
- return d->column;
-}
-
-
-// Return the name of this cell, i.e. the string that the user would
-// use to reference it. Example: A1, BZ16
-//
-TQString Cell::name() const
-{
- return name( d->column, d->row );
-}
-
-
-// Return the name of any cell given by (col, row).
-//
-TQString Cell::name( int col, int row )
-{
- return columnName( col ) + TQString::number( row );
-}
-
-
-// Return the name of this cell, including the sheet name.
-// Example: sheet1!A5
-//
-TQString Cell::fullName() const
-{
- return fullName( sheet(), d->column, d->row );
-}
-
-
-// Return the full name of any cell given a sheet and (col, row).
-//
-TQString Cell::fullName( const Sheet* s, int col, int row )
-{
- return s->sheetName() + "!" + name( col, row );
-}
-
-
-// Return the symbolic name of the column of this cell. Examples: A, BB.
-//
-TQString Cell::columnName() const
-{
- return columnName( d->column );
-}
-
-TDELocale* Cell::locale() const
-{
- return d->format->sheet()->doc()->locale();
-}
-
-// Return the symbolic name of any column.
-//
-TQString Cell::columnName( uint column )
-{
- TQString str;
- unsigned digits = 1;
- unsigned offset = 0;
-
- column--;
-
- if( column > 4058115285U ) return TQString("@@@");
-
- for( unsigned limit = 26; column >= limit+offset; limit *= 26, digits++ )
- offset += limit;
-
- for( unsigned c = column - offset; digits; --digits, c/=26 )
- str.prepend( TQChar( 'A' + (c%26) ) );
-
- return str;
-}
-
-
-// Return true if this cell is a formula.
-//
-bool Cell::isFormula() const
-{
- return d->strText[0] == '=';
-}
-
-
-// Return the input text of this cell. This could, for instance, be a
-// formula.
-//
-// FIXME: These two functions are inconsistently named. It should be
-// either text() and outText() or strText() and strOutText().
-//
-TQString Cell::text() const
-{
- return d->strText;
-}
-
-
-// Return the out text, i.e. the text that is visible in the cells
-// square when shown. This could, for instance, be the calculated
-// result of a formula.
-//
-TQString Cell::strOutText() const
-{
- return d->strOutText;
-}
-
-Formula *Cell::formula () const
-{
- return d->formula;
-}
-
-
-// Return the value of this cell.
-//
-const Value Cell::value() const
-{
- return d->value;
-}
-
-
-// Set the value of this cell. It also clears all errors if the value
-// itself is not an error.
-//
-// In addition to this, it calculates the outstring and sets the dirty
-// flags so that a redraw is forced.
-//
-void Cell::setValue( const Value& v )
-{
- if (v.type() != Value::Error)
- clearAllErrors();
-
- //If the value has not changed then we don't need to do anything
- //(ie. no need to relayout, update dependant cells etc.),
- //unless this cell contains a formula, in which case its dependancies might have changed
- //even though the value has not. For example, if this cell was previously empty (and its value is
- //therefore empty) and a new dependency upon an empty cell has been added. The new value would still
- //be empty, but the dependencies need to be updated (via the call to valueChanged() below).
- if ( ( d->value == v ) && ( !isFormula() ) )
- return;
-
- d->value = v;
-
- setFlag(Flag_LayoutDirty);
- setFlag(Flag_TextFormatDirty);
-
- // Format and set the outText.
- setOutputText();
-
- // Set the displayed text, if we hold an error value.
- if (d->value.type() == Value::Error)
- d->strOutText = d->value.errorMessage ();
-
- // Value of the cell has changed - trigger necessary actions
- valueChanged ();
-
- if ( !format()->sheet()->isLoading() )
- format()->sheet()->setRegionPaintDirty(cellRect());
-}
-
-void Cell::setCellValue (const Value &v, FormatType fmtType, const TQString &txt)
-{
- if ( !txt.isNull() )
- {
- d->strText = txt;
- if ( isFormula() )
- makeFormula();
- }
- else if ( !isFormula() )
- d->strText = sheet()->doc()->converter()->asString (v).asString();
- if (fmtType != No_format)
- format()->setFormatType (fmtType);
- setValue (v);
-}
-
-// FIXME: Continue commenting and cleaning here (ingwa)
-
-
-Cell* Cell::previousCell() const
-{
- return d->previousCell;
-}
-
-Cell* Cell::nextCell() const
-{
- return d->nextCell;
-}
-
-void Cell::setPreviousCell( Cell* c )
-{
- d->previousCell = c;
-}
-
-void Cell::setNextCell( Cell* c )
-{
- d->nextCell = c;
-}
-
-Validity* Cell::getValidity( int newStruct )
-{
- if ( (!newStruct) && (!d->hasExtra()))
- //we don't have validity struct and we don't want one
- return 0;
-
- if( ( d->extra()->validity == 0 ) && ( newStruct == -1 ) )
- d->extra()->validity = new Validity;
- return d->extra()->validity;
-}
-
-void Cell::removeValidity()
-{
- if (!d->hasExtra())
- return;
-
- delete d->extra()->validity;
- d->extra()->validity = 0;
-}
-
-
-void Cell::copyFormat( const int column , const int row )
-{
- const Cell * cell = format()->sheet()->cellAt( column , row );
-
- copyFormat( cell );
-}
-
-void Cell::copyFormat( const Cell* cell )
-{
-
- Q_ASSERT(cell);
-
- d->value.setFormat(cell->d->value.format());
- format()->copy(*(cell->format()));
-
- /*format()->setAlign( cell->format()->align( _column, _row ) );
- format()->setAlignY( cell->format()->alignY( _column, _row ) );
- format()->setTextFont( cell->format()->textFont( _column, _row ) );
- format()->setTextColor( cell->format()->textColor( _column, _row ) );
- format()->setBgColor( cell->bgColor( _column, _row) );
- setLeftBorderPen( cell->leftBorderPen( _column, _row ) );
- setTopBorderPen( cell->topBorderPen( _column, _row ) );
- setBottomBorderPen( cell->bottomBorderPen( _column, _row ) );
- setRightBorderPen( cell->rightBorderPen( _column, _row ) );
- format()->setFallDiagonalPen( cell->format()->fallDiagonalPen( _column, _row ) );
- format()->setGoUpDiagonalPen( cell->format()->goUpDiagonalPen( _column, _row ) );
- format()->setBackGroundBrush( cell->backGroundBrush( _column, _row) );
- format()->setPrecision( cell->format()->precision( _column, _row ) );
- format()->setPrefix( cell->format()->prefix( _column, _row ) );
- format()->setPostfix( cell->format()->postfix( _column, _row ) );
- format()->setFloatFormat( cell->format()->floatFormat( _column, _row ) );
- format()->setFloatColor( cell->format()->floatColor( _column, _row ) );
- format()->setMultiRow( cell->format()->multiRow( _column, _row ) );
- format()->setVerticalText( cell->format()->verticalText( _column, _row ) );
- format()->setDontPrintText( cell->format()->getDontprintText(_column, _row ) );
- format()->setNotProtected( cell->format()->notProtected(_column, _row ) );
- format()->setHideAll(cell->format()->isHideAll(_column, _row ) );
- format()->setHideFormula(cell->format()->isHideFormula(_column, _row ) );
- format()->setIndent( cell->format()->getIndent(_column, _row ) );
- format()->setAngle( cell->format()->getAngle(_column, _row) );
- format()->setFormatType( cell->format()->getFormatType(_column, _row) );
- Format::Currency c;
- if ( cell->format()->currencyInfo( c ) )
- format()->setCurrency( c );*/
-
- TQValueList<Conditional> conditionList = cell->conditionList();
- if (d->hasExtra())
- delete d->extra()->conditions;
- if ( cell->d->hasExtra() && cell->d->extra()->conditions )
- setConditionList( conditionList );
- else
- if (d->hasExtra())
- d->extra()->conditions = 0;
-
- /*format()->setComment( cell->format()->comment( _column, _row ) );*/
-}
-
-void Cell::copyAll( Cell *cell )
-{
- Q_ASSERT( !isDefault() ); // trouble ahead...
- copyFormat( cell );
- copyContent( cell );
-}
-
-void Cell::copyContent( const Cell* cell )
-{
- Q_ASSERT( !isDefault() ); // trouble ahead...
-
- if (cell->isFormula() && cell->column() > 0 && cell->row() > 0)
- {
- // change all the references, e.g. from A1 to A3 if copying
- // from e.g. B2 to B4
- TQString d = cell->encodeFormula();
- setCellText( cell->decodeFormula( d ) );
- }
- else
- setCellText( cell->text() );
-
-}
-
-void Cell::defaultStyle()
-{
- format()->defaultStyleFormat();
-
- if (!d->hasExtra())
- return;
-
- if ( d->extra()->conditions )
- {
- delete d->extra()->conditions;
- d->extra()->conditions = 0;
- }
-
- delete d->extra()->validity;
- d->extra()->validity = 0L;
-}
-
-
-// Merge a number of cells, i.e. make this cell obscure a number of
-// other cells. If _x and _y == 0, then the merging is removed.
-
-void Cell::mergeCells( int _col, int _row, int _x, int _y )
-{
- // Start by unobscuring the cells that we obscure right now
- int extraXCells = d->hasExtra() ? d->extra()->extraXCells : 0;
- int extraYCells = d->hasExtra() ? d->extra()->extraYCells : 0;
- for ( int x = _col; x <= _col + extraXCells; ++x ) {
- for ( int y = _row; y <= _row + extraYCells; ++y ) {
- if ( x != _col || y != _row )
- format()->sheet()->nonDefaultCell( x, y )->unobscure(this);
- }
- }
-
- // If no merging, then remove all traces, and return.
- if ( _x == 0 && _y == 0 ) {
- clearFlag( Flag_Merged );
- if (d->hasExtra()) {
- d->extra()->extraXCells = 0;
- d->extra()->extraYCells = 0;
- d->extra()->extraWidth = 0.0;
- d->extra()->extraHeight = 0.0;
- d->extra()->mergedXCells = 0;
- d->extra()->mergedYCells = 0;
- }
-
- // Refresh the layout
- setFlag( Flag_LayoutDirty );
- return;
- }
-
- // At this point, we know that we will merge some cells.
- setFlag(Flag_Merged);
- d->extra()->extraXCells = _x;
- d->extra()->extraYCells = _y;
- d->extra()->mergedXCells = _x;
- d->extra()->mergedYCells = _y;
-
- // Obscure the cells
- for ( int x = _col; x <= _col + _x; ++x ) {
- for ( int y = _row; y <= _row + _y; ++y ) {
- if ( x != _col || y != _row )
- format()->sheet()->nonDefaultCell( x, y )->obscure( this, true );
- }
- }
-
- // Refresh the layout
- setFlag( Flag_LayoutDirty );
-}
-
-void Cell::move( int col, int row )
-{
- setLayoutDirtyFlag();
- setCalcDirtyFlag();
- setDisplayDirtyFlag();
-
- //int ex = extraXCells();
- //int ey = d->extra()->extraYCells();
-
- if (d->hasExtra())
- d->extra()->obscuringCells.clear();
-
- // Unobscure the objects we obscure right now
- int extraXCells = d->hasExtra() ? d->extra()->extraXCells : 0;
- int extraYCells = d->hasExtra() ? d->extra()->extraYCells : 0;
- for( int x = d->column; x <= d->column + extraXCells; ++x )
- for( int y = d->row; y <= d->row + extraYCells; ++y )
- if ( x != d->column || y != d->row )
- {
- Cell *cell = format()->sheet()->nonDefaultCell( x, y );
- cell->unobscure(this);
- }
-
- d->column = col;
- d->row = row;
-
- if (d->hasExtra())
- {
- // d->extra()->extraXCells = 0;
- // d->extra()->extraYCells = 0;
- d->extra()->mergedXCells = 0;
- d->extra()->mergedYCells = 0;
- }
-
- // Cell value has been changed (because we're another cell now).
- valueChanged ();
-}
-
-void Cell::setLayoutDirtyFlag( bool format )
-{
- setFlag( Flag_LayoutDirty );
- if ( format )
- setFlag( Flag_TextFormatDirty );
-
- if (!d->hasExtra())
- return;
-
- TQValueList<Cell*>::iterator it = d->extra()->obscuringCells.begin();
- TQValueList<Cell*>::iterator end = d->extra()->obscuringCells.end();
- for ( ; it != end; ++it ) {
- (*it)->setLayoutDirtyFlag( format );
- }
-}
-
-bool Cell::needsPrinting() const
-{
- if ( isDefault() )
- return false;
-
- if ( !d->strText.stripWhiteSpace().isEmpty() ) {
- return true;
- }
-
- // Cell borders?
- if ( format()->hasProperty( Format::PTopBorder )
- || format()->hasProperty( Format::PLeftBorder )
- || format()->hasProperty( Format::PRightBorder )
- || format()->hasProperty( Format::PBottomBorder )
- || format()->hasProperty( Format::PFallDiagonal )
- || format()->hasProperty( Format::PGoUpDiagonal ) ) {
- return true;
- }
-
- // Background color or brush?
- if ( format()->hasProperty( Format::PBackgroundBrush ) ) {
-
- const TQBrush& brush=backGroundBrush(column(),row());
-
- //Only brushes that are visible (ie. they have a brush style and are not white)
- //need to be drawn
- if ( (brush.style() != TQt::NoBrush) &&
- (brush.color() != TQt::white || brush.pixmap()) )
- return true;
-
- }
-
- if ( format()->hasProperty( Format::PBackgroundColor ) ) {
- kdDebug() << "needsPrinting: Has background colour" << endl;
- TQColor backgroundColor=bgColor(column(),row());
-
- //We don't need to print anything if the background is white
- if (backgroundColor != TQt::white)
- return true;
- }
-
- return false;
-}
-
-bool Cell::isEmpty() const
-{
- return isDefault() || d->strText.isEmpty();
-}
-
-
-// Return true if this cell is obscured by some other cell.
-
-bool Cell::isObscured() const
-{
- if (!d->hasExtra())
- return false;
-
- return !( d->extra()->obscuringCells.isEmpty() );
-}
-
-
-// Return true if this cell is part of a merged cell, but not the
-// master cell.
-
-bool Cell::isPartOfMerged() const
-{
- if (!d->hasExtra())
- return false;
-
- TQValueList<Cell*>::const_iterator it = d->extra()->obscuringCells.begin();
- TQValueList<Cell*>::const_iterator end = d->extra()->obscuringCells.end();
- for ( ; it != end; ++it ) {
- Cell *cell = *it;
-
- if (cell->doesMergeCells()) {
- // The cell might merge extra cells, and then overlap even
- // beyond that so just knowing that the obscuring cell merges
- // extra isn't enough. We have to know that this cell is one of
- // the ones it is forcing over.
- if (column() <= cell->column() + cell->d->extra()->mergedXCells
- && row() <= cell->row() + cell->mergedYCells() )
- return true;
- }
- }
-
- return false;
-}
-
-
-// Return the cell that obscures this one. If no cell is obscuring,
-// then return this. This method is slightly complicated because we
-// can have several layers of obscuring.
-//
-// Update: it seems that if we do an actual merge, then the obscuring
-// cell is prepended and if just expanding, then it is appended. This
-// means that we should be able to just look at the first one.
-
-Cell *Cell::ultimateObscuringCell() const
-{
- if (!d->hasExtra())
- return (Cell *) this;
-
- else if (d->extra()->obscuringCells.isEmpty())
- return (Cell *) this;
-
- else
- return d->extra()->obscuringCells.first();
-
-#if 0
- TQValueList<Cell*>::const_iterator it = d->extra()->obscuringCells.begin();
- TQValueList<Cell*>::const_iterator end = d->extra()->obscuringCells.end();
- for ( ; it != end; ++it ) {
- Cell *cell = *it;
-
- if (cell->doesMergeCells()) {
- // The cell might merge extra cells, and then overlap even
- // beyond that so just knowing that the obscuring cell merges
- // extra isn't enough. We have to know that this cell is one of
- // the ones it is forcing over.
- if (column() <= cell->column() + cell->d->extra()->mergedXCells
- && row() <= cell->row() + cell->mergedYCells() )
- return true;
- }
- }
-
- return false;
-#endif
-}
-
-
-TQValueList<Cell*> Cell::obscuringCells() const
-{
- if (!d->hasExtra())
- {
- TQValueList<Cell*> empty;
- return empty;
- }
- return d->extra()->obscuringCells;
-}
-
-void Cell::clearObscuringCells()
-{
- if (!d->hasExtra())
- return;
- d->extra()->obscuringCells.clear();
-}
-
-void Cell::obscure( Cell *cell, bool isForcing )
-{
- if (d->hasExtra())
- {
- d->extra()->obscuringCells.remove( cell ); // removes *all* occurrences
- cell->clearObscuringCells();
- }
- if ( isForcing )
- {
- d->extra()->obscuringCells.prepend( cell );
- }
- else
- {
- d->extra()->obscuringCells.append( cell );
- }
- setFlag(Flag_LayoutDirty);
- format()->sheet()->setRegionPaintDirty( cellRect() );
-}
-
-void Cell::unobscure( Cell * cell )
-{
- if (d->hasExtra())
- d->extra()->obscuringCells.remove( cell );
- setFlag( Flag_LayoutDirty );
- format()->sheet()->setRegionPaintDirty( cellRect() );
-}
-
-TQString Cell::encodeFormula( bool _era, int _col, int _row ) const
-{
- if ( _col == -1 )
- _col = d->column;
- if ( _row == -1 )
- _row = d->row;
-
- TQString erg = "";
-
- if(d->strText.isEmpty())
- return d->strText;
-
- bool fix1 = false;
- bool fix2 = false;
- bool onNumber = false;
- unsigned int pos = 0;
- const unsigned int length = d->strText.length();
-
- // All this can surely be made 10 times faster, but I just "ported" it to TQString
- // without any attempt to optimize things -- this is really brittle (Werner)
- while ( pos < length )
- {
- if ( d->strText[pos] == '"' )
- {
- erg += d->strText[pos++];
- while ( pos < length && d->strText[pos] != '"' ) // till the end of the world^H^H^H "string"
- {
- erg += d->strText[pos++];
- // Allow escaped double quotes (\")
- if ( pos < length && d->strText[pos] == '\\' && d->strText[pos+1] == '"' )
- {
- erg += d->strText[pos++];
- erg += d->strText[pos++];
- }
- }
- if ( pos < length ) // also copy the trailing double quote
- erg += d->strText[pos++];
-
- onNumber = false;
- }
- else if ( d->strText[pos].isDigit() )
- {
- erg += d->strText[pos++];
- fix1 = fix2 = false;
- onNumber = true;
- }
- else if ( d->strText[pos] != '$' && !d->strText[pos].isLetter() )
- {
- erg += d->strText[pos++];
- fix1 = fix2 = false;
- onNumber = false;
- }
- else
- {
- TQString tmp = "";
- if ( d->strText[pos] == '$' )
- {
- tmp = "$";
- pos++;
- fix1 = true;
- }
- if ( d->strText[pos].isLetter() )
- {
- TQString buffer;
- unsigned int pos2 = 0;
- while ( pos < length && d->strText[pos].isLetter() )
- {
- tmp += d->strText[pos];
- buffer[pos2++] = d->strText[pos++];
- }
- if ( d->strText[pos] == '$' )
- {
- tmp += "$";
- pos++;
- fix2 = true;
- }
- if ( d->strText[pos].isDigit() )
- {
- const unsigned int oldPos = pos;
- while ( pos < length && d->strText[pos].isDigit() ) ++pos;
- int row = 0;
- if ( pos != oldPos )
- row = d->strText.mid(oldPos, pos-oldPos).toInt();
- // Is it a sheet name || is it a function name like DEC2HEX
- /* or if we're parsing a number, this could just be the
- exponential part of it (1.23E4) */
- if ( ( d->strText[pos] == '!' ) ||
- d->strText[pos].isLetter() ||
- onNumber )
- {
- erg += tmp;
- fix1 = fix2 = false;
- pos = oldPos;
- }
- else // It must be a cell identifier
- {
- //now calculate the row as integer value
- int col = 0;
- col = util_decodeColumnLabelText( buffer );
- if ( fix1 )
- erg += TQString( "$%1" ).arg( col );
- else
- if (_era)
- erg += TQChar(0xA7) + TQString( "%1" ).arg( col );
- else
- erg += TQString( "#%1" ).arg( col - _col );
-
- if ( fix2 )
- erg += TQString( "$%1#").arg( row );
- else
- if (_era)
- erg += TQChar(0xA7) + TQString( "%1#" ).arg( row );
- else
- erg += TQString( "#%1#" ).arg( row - _row );
- }
- }
- else
- {
- erg += tmp;
- fix1 = fix2 = false;
- }
- }
- else
- {
- erg += tmp;
- fix1 = false;
- }
- onNumber = false;
- }
- }
-
- return erg;
-}
-
-TQString Cell::decodeFormula( const TQString &_text, int _col, int _row) const
-{
- if ( _col == -1 )
- _col = d->column;
- if ( _row == -1 )
- _row = d->row;
-
- TQString erg = "";
- unsigned int pos = 0;
- const unsigned int length = _text.length();
-
- if ( _text.isEmpty() )
- return TQString();
-
- while ( pos < length )
- {
- if ( _text[pos] == '"' )
- {
- erg += _text[pos++];
- while ( pos < length && _text[pos] != '"' )
- {
- erg += _text[pos++];
- // Allow escaped double quotes (\")
- if ( pos < length && _text[pos] == '\\' && _text[pos+1] == '"' )
- {
- erg += _text[pos++];
- erg += _text[pos++];
- }
- }
- if ( pos < length )
- erg += _text[pos++];
- }
- else if ( _text[pos] == '#' || _text[pos] == '$' || _text[pos] == TQChar(0xA7))
- {
- bool abs1 = false;
- bool abs2 = false;
- bool era1 = false; // if 1st is relative but encoded absolutely
- bool era2 = false;
-
- TQChar _t = _text[pos++];
- if ( _t == '$' )
- abs1 = true;
- else if ( _t == TQChar(0xA7) )
- era1 = true;
-
- int col = 0;
- unsigned int oldPos = pos;
- while ( pos < length && ( _text[pos].isDigit() || _text[pos] == '-' ) ) ++pos;
- if ( pos != oldPos )
- col = _text.mid(oldPos, pos-oldPos).toInt();
- if ( !abs1 && !era1 )
- col += _col;
- // Skip '#' or '$'
-
- _t = _text[pos++];
- if ( _t == '$' )
- abs2 = true;
- else if ( _t == TQChar(0xA7) )
- era2 = true;
-
- int row = 0;
- oldPos = pos;
- while ( pos < length && ( _text[pos].isDigit() || _text[pos] == '-' ) ) ++pos;
- if ( pos != oldPos )
- row = _text.mid(oldPos, pos-oldPos).toInt();
- if ( !abs2 && !era2)
- row += _row;
- // Skip '#' or '$'
- ++pos;
- if ( row < 1 || col < 1 || row > KS_rowMax || col > KS_colMax )
- {
- kdDebug(36001) << "Cell::decodeFormula: row or column out of range (col: " << col << " | row: " << row << ")" << endl;
- erg = "=\"#### " + i18n("REFERENCE TO COLUMN OR ROW IS OUT OF RANGE") + "\"";
- return erg;
- }
- if ( abs1 )
- erg += "$";
- erg += Cell::columnName(col); //Get column text
-
- if ( abs2 )
- erg += "$";
- erg += TQString::number( row );
- }
- else
- erg += _text[pos++];
- }
-
- return erg;
-}
-
-
-void Cell::freeAllObscuredCells()
-{
- //
- // Free all obscured cells.
- //
-
- if (!d->hasExtra())
- return;
-
- for ( int x = d->column + d->extra()->mergedXCells;
- x <= d->column + d->extra()->extraXCells; ++x ) {
- for ( int y = d->row + d->extra()->mergedYCells;
- y <= d->row + d->extra()->extraYCells; ++y ) {
- if ( x != d->column || y != d->row ) {
- Cell *cell = format()->sheet()->cellAt( x, y );
- cell->unobscure(this);
- }
- }
- }
-
- d->extra()->extraXCells = d->extra()->mergedXCells;
- d->extra()->extraYCells = d->extra()->mergedYCells;
-
-}
-
-
-// ----------------------------------------------------------------
-// Layout
-
-
-// Recalculate the entire layout. This includes the following members:
-//
-// d->textX, d->textY
-// d->textWidth, d->textHeight
-// d->fmAscent
-// d->extra()->extraXCells, d->extra()->extraYCells
-// d->extra()->extraWidth, d->extra()->extraHeight
-// d->extra()->nbLines (if multirow)
-//
-// and, of course,
-//
-// d->strOutText
-//
-
-void Cell::makeLayout( TQPainter &_painter, int _col, int _row )
-{
- // Are _col and _row really needed ?
- //
- // Yes they are: they are useful if this is the default layout, in
- // which case d->row and d->column are 0 and 0, but _col and _row
- // are the real coordinates of the cell.
-
- // There is no need to remake the layout if it hasn't changed.
- if ( !testFlag( Flag_LayoutDirty ) )
- return;
-
- // Some initializations.
- if (d->hasExtra())
- d->extra()->nbLines = 0;
- clearFlag( Flag_CellTooShortX );
- clearFlag( Flag_CellTooShortY );
-
- // Initiate the cells that this one is obscuring to the ones that
- // are actually merged.
- freeAllObscuredCells();
- if (d->hasExtra())
- mergeCells( d->column, d->row,
- d->extra()->mergedXCells, d->extra()->mergedYCells );
-
- // If the column for this cell is hidden or the row is too low,
- // there is no use in remaking the layout.
- ColumnFormat *cl1 = format()->sheet()->columnFormat( _col );
- RowFormat *rl1 = format()->sheet()->rowFormat( _row );
- if ( cl1->isHide()
- || ( rl1->dblHeight() <= format()->sheet()->doc()->unzoomItY( 2 ) ) ) {
- clearFlag( Flag_LayoutDirty );
- return;
- }
-
- // Recalculate the output text, d->strOutText.
- setOutputText();
-
- // Empty text? Reset the outstring and, if this is the default
- // cell, return.
- if ( d->strOutText.isEmpty() ) {
- d->strOutText = TQString();
-
- if ( isDefault() ) {
- clearFlag( Flag_LayoutDirty );
- return;
- }
- }
-
- // Up to here, we have just cared about the contents, not the
- // painting of it. Now it is time to see if the contents fits into
- // the cell and, if not, maybe rearrange the outtext a bit.
- //
- // First, Determine the correct font with zoom taken into account,
- // and apply it to _painter. Then calculate text dimensions, i.e.
- // d->textWidth and d->textHeight.
- applyZoomedFont( _painter, _col, _row );
- textSize( _painter );
-
- //
- // Calculate the size of the cell
- //
- RowFormat *rl = format()->sheet()->rowFormat( d->row );
- ColumnFormat *cl = format()->sheet()->columnFormat( d->column );
-
- double width = cl->dblWidth();
- double height = rl->dblHeight();
-
- // Calculate extraWidth and extraHeight if we have a merged cell.
- if ( testFlag( Flag_Merged ) ) {
- int extraXCells = d->hasExtra() ? d->extra()->extraXCells : 0;
- int extraYCells = d->hasExtra() ? d->extra()->extraYCells : 0;
-
- // FIXME: Introduce double extraWidth/Height here and use them
- // instead (see FIXME about this in paintCell()).
-
- for ( int x = _col + 1; x <= _col + extraXCells; x++ )
- width += format()->sheet()->columnFormat( x )->dblWidth();
-
- for ( int y = _row + 1; y <= _row + extraYCells; y++ )
- height += format()->sheet()->rowFormat( y )->dblHeight();
- }
-
- // Cache the newly calculated extraWidth and extraHeight if we have
- // already allocated a struct for it. Otherwise it will be zero, so
- // don't bother.
- if (d->hasExtra()) {
- d->extra()->extraWidth = width;
- d->extra()->extraHeight = height;
- }
-
- TQFontMetrics fm = _painter.fontMetrics();
- d->fmAscent = fm.ascent();
-
- // Check if we need to break the line into multiple lines and are
- // allowed to do so. If so, set `lines' to the number of lines that
- // are needed to fit into the total width of the combined cell.
- //
- // Also recalculate d->textHeight, d->textWidth, d->extra->nbLines
- // and d->strOutText.
- //
- int lines = 1;
- if ( d->textWidth > (width - 2 * BORDER_SPACE
- - format()->leftBorderWidth( _col, _row )
- - format()->rightBorderWidth( _col, _row ) )
- && format()->multiRow( _col, _row ) )
- {
- // Copy of d->strOutText but without the newlines.
-// TQString o = d->strOutText.replace( TQChar('\n'), " " );
-
- // don't remove the existing LF, these are intended line wraps (whishlist #9881)
- TQString o = d->strOutText;
-
- // Break the line at appropriate places, i.e. spaces, if
- // necessary. This means to change the spaces where breaks occur
- // into newlines.
- if ( o.find(' ') != -1 )
- {
- d->strOutText = "";
-
- // Make sure that we have a space at the end.
- o += ' ';
-
- int start = 0; // Start of the line we are handling now
- int breakpos = 0; // The next candidate pos to break the string
- int pos1 = 0;
- int availableWidth = (int) ( width - 2 * BORDER_SPACE
- - format()->leftBorderWidth( _col, _row )
- - format()->rightBorderWidth( _col, _row ) );
-
- do {
-
- breakpos = o.find( ' ', breakpos );
- int linefeed = o.find( '\n', pos1 );
-
-// kdDebug() << "start: " << start << "; breakpos: " << breakpos << "; pos1: " << pos1 << "; linefeed: " << linefeed << endl;
-
- //don't miss LF as a position to calculate current lineWidth
- int work_breakpos = breakpos;
- if (pos1 < linefeed && linefeed < breakpos)
- work_breakpos = linefeed;
-
- double lineWidth = format()->sheet()->doc()
- ->unzoomItX( fm.width( d->strOutText.mid( start, (pos1 - start) )
- + o.mid( pos1, work_breakpos - pos1 ) ) );
-
- //linefeed could be -1 when no linefeed is found!
- if (breakpos > linefeed && linefeed > 0)
- {
-// kdDebug() << "applying linefeed to start;" << endl;
- start = linefeed;
- lines++;
- }
-
- if ( lineWidth <= availableWidth ) {
- // We have room for the rest of the line. End it here.
- d->strOutText += o.mid( pos1, breakpos - pos1 );
- pos1 = breakpos;
- }
- else {
- // Still not enough room. Try to split further.
- if ( o.at( pos1 ) == ' ' )
- pos1++;
-
- if ( pos1 != 0 && breakpos != -1 ) {
- d->strOutText += "\n" + o.mid( pos1, breakpos - pos1 );
- lines++;
- }
- else
- d->strOutText += o.mid( pos1, breakpos - pos1 );
-
- start = pos1;
- pos1 = breakpos;
- }
-
- breakpos++;
- } while( o.find( ' ', breakpos ) != -1 );
- }
- else
- {
- lines = o.contains('\n');
- }
-
- d->textHeight *= lines;
- if (lines > 1)
- d->extra()->nbLines = lines;
-
- d->textX = 0.0;
-
- // Calculate the maximum width, taking into account linebreaks,
- // and put it in d->textWidth.
- TQString t;
- int i;
- int pos = 0;
- d->textWidth = 0.0;
- do {
- i = d->strOutText.find( "\n", pos );
-
- if ( i == -1 )
- t = d->strOutText.mid( pos, d->strOutText.length() - pos );
- else {
- t = d->strOutText.mid( pos, i - pos );
- pos = i + 1;
- }
-
- double tw = format()->sheet()->doc()->unzoomItX( fm.width( t ) );
- if ( tw > d->textWidth )
- d->textWidth = tw;
- } while ( i != -1 );
- }
-
- // Calculate d->textX and d->textY
- offsetAlign( _col, _row );
-
- int a = effAlignX();
-
- // Get indentation. This is only used for left aligned text.
- double indent = 0.0;
- if ( a == Format::Left && !isEmpty() )
- indent = format()->getIndent( _col, _row );
-
- // Set Flag_CellTooShortX if the text is vertical or angled, and too
- // high for the cell.
- if ( format()->verticalText( _col, _row ) || format()->getAngle( _col, _row ) != 0 ) {
- //RowFormat *rl = format()->sheet()->rowFormat( _row );
-
- if ( d->textHeight >= height/*rl->dblHeight()*/ )
- setFlag( Flag_CellTooShortX );
- }
-
- // Do we have to occupy additional cells to the right? This is only
- // done for cells that have no merged cells in the Y direction.
- //
- // FIXME: Check if all cells along the merged edge to the right are
- // empty and use the extra space? No, probably not.
- //
- if ( d->textWidth + indent > ( width - 2 * BORDER_SPACE
- - format()->leftBorderWidth( _col, _row )
- - format()->rightBorderWidth( _col, _row ) )
- && ( !d->hasExtra() || d->extra()->mergedYCells == 0 ) )
- {
- int c = d->column;
-
- // Find free cells to the right of this one.
- int end = 0;
- while ( !end ) {
- ColumnFormat *cl2 = format()->sheet()->columnFormat( c + 1 );
- Cell *cell = format()->sheet()->visibleCellAt( c + 1, d->row );
-
- if ( cell->isEmpty() ) {
- width += cl2->dblWidth() - 1;
- c++;
-
- // Enough space?
- if ( d->textWidth + indent <= ( width - 2 * BORDER_SPACE
- - format()->leftBorderWidth( _col, _row )
- - format()->rightBorderWidth( _col, _row ) ) )
- end = 1;
- }
- else
- // Not enough space, but the next cell is not empty
- end = -1;
- }
-
- // Try to use additional space from the neighboring cells that
- // were calculated in the last step. This is the place that we
- // set d->extra()->extraXCells and d->extra()->extraWidth.
- //
- // Currently this is only done for left aligned cells. We have to
- // check to make sure we haven't already force-merged enough cells
- //
- // FIXME: Why not right/center aligned text?
- //
- // FIXME: Shouldn't we check to see if end == -1 here before
- // setting Flag_CellTooShortX?
- //
- if ( format()->align( _col, _row ) == Format::Left
- || ( format()->align( _col, _row ) == Format::Undefined
- && !value().isNumber() ) )
- {
- if ( c - d->column > d->extra()->mergedXCells ) {
- d->extra()->extraXCells = c - d->column;
- d->extra()->extraWidth = width;
- for ( int i = d->column + 1; i <= c; ++i ) {
- Cell *cell = format()->sheet()->nonDefaultCell( i, d->row );
- cell->obscure( this );
- }
-
- // Not enough space
- if ( end == -1 )
- setFlag( Flag_CellTooShortX );
- }
- else
- setFlag( Flag_CellTooShortX );
- }
- else
- setFlag( Flag_CellTooShortX );
- }
-
- // Do we have to occupy additional cells at the bottom ?
- //
- // FIXME: Setting to make the current cell grow.
- //
- if ( format()->multiRow( _col, _row )
- && d->textHeight > ( height - 2 * BORDER_SPACE
- - format()->topBorderWidth( _col, _row )
- - format()->bottomBorderWidth( _col, _row ) ) )
- {
- int r = d->row;
- int end = 0;
-
- // Find free cells bottom to this one
- while ( !end ) {
- RowFormat *rl2 = format()->sheet()->rowFormat( r + 1 );
- Cell *cell = format()->sheet()->visibleCellAt( d->column, r + 1 );
-
- if ( cell->isEmpty() ) {
- height += rl2->dblHeight() - 1.0;
- r++;
-
- // Enough space ?
- if ( d->textHeight <= ( height - 2 * BORDER_SPACE
- - format()->topBorderWidth( _col, _row )
- - format()->bottomBorderWidth( _col, _row ) ) )
- end = 1;
- }
- else
- // Not enough space, but the next cell is not empty.
- end = -1;
- }
-
- // Check to make sure we haven't already force-merged enough cells.
- if ( r - d->row > d->extra()->mergedYCells )
- {
- d->extra()->extraYCells = r - d->row;
- d->extra()->extraHeight = height;
-
- for ( int i = d->row + 1; i <= r; ++i )
- {
- Cell *cell = format()->sheet()->nonDefaultCell( d->column, i );
- cell->obscure( this );
- }
-
- // Not enough space?
- if ( end == -1 )
- setFlag( Flag_CellTooShortY );
- }
- else
- setFlag( Flag_CellTooShortY );
- }
-
- clearFlag( Flag_LayoutDirty );
-
- return;
-}
-
-
-void Cell::valueChanged ()
-{
- update();
-
- format()->sheet()->valueChanged (this);
-}
-
-
-// Recalculate d->strOutText.
-//
-
-void Cell::setOutputText()
-{
- if ( isDefault() ) {
- d->strOutText = TQString();
-
- if ( d->hasExtra() && d->extra()->conditions )
- d->extra()->conditions->checkMatches();
-
- return;
- }
-
- // If nothing has changed, we don't need to remake the text layout.
- if ( !testFlag(Flag_TextFormatDirty) )
- return;
-
- // We don't want to remake the layout unnecessarily.
- clearFlag( Flag_TextFormatDirty );
-
- // Display a formula if warranted. If not, display the value instead;
- // this is the most common case.
- if ( (!hasError()) && isFormula() && format()->sheet()->getShowFormula()
- && !( format()->sheet()->isProtected() && format()->isHideFormula( d->column, d->row ) )
- || isEmpty() )
- d->strOutText = d->strText;
- else {
- d->strOutText = sheet()->doc()->formatter()->formatText (this,
- formatType());
- }
-
- // Check conditions if needed.
- if ( d->hasExtra() && d->extra()->conditions )
- d->extra()->conditions->checkMatches();
-}
-
-
-// Recalculate d->textX and d->textY.
-//
-// Used in makeLayout() and calculateTextParameters().
-//
-
-void Cell::offsetAlign( int _col, int _row )
-{
- int a;
- Format::AlignY ay;
- int tmpAngle;
- bool tmpVerticalText;
- bool tmpMultiRow;
-
- if ( d->hasExtra()
- && d->extra()->conditions
- && d->extra()->conditions->matchedStyle() )
- {
- Style *style = d->extra()->conditions->matchedStyle();
-
- if ( style->hasFeature( Style::SAlignX, true ) )
- a = style->alignX();
- else
- a = format()->align( _col, _row );
-
- if ( style->hasFeature( Style::SVerticalText, true ) )
- tmpVerticalText = style->hasProperty( Style::PVerticalText );
- else
- tmpVerticalText = format()->verticalText( _col, _row );
-
- if ( style->hasFeature( Style::SMultiRow, true ) )
- tmpMultiRow = style->hasProperty( Style::PMultiRow );
- else
- tmpMultiRow = format()->multiRow( _col, _row );
-
- if ( style->hasFeature( Style::SAlignY, true ) )
- ay = style->alignY();
- else
- ay = format()->alignY( _col, _row );
-
- if ( style->hasFeature( Style::SAngle, true ) )
- tmpAngle = style->rotateAngle();
- else
- tmpAngle = format()->getAngle( _col, _row );
- }
- else {
- a = format()->align( _col, _row );
- ay = format()->alignY( _col, _row );
- tmpAngle = format()->getAngle( _col, _row );
- tmpVerticalText = format()->verticalText( _col, _row );
- tmpMultiRow = format()->multiRow( _col, _row );
- }
-
- RowFormat *rl = format()->sheet()->rowFormat( _row );
- ColumnFormat *cl = format()->sheet()->columnFormat( _col );
-
- double w = cl->dblWidth();
- double h = rl->dblHeight();
-
- if ( d->hasExtra() ) {
- if ( d->extra()->extraXCells ) w = d->extra()->extraWidth;
- if ( d->extra()->extraYCells ) h = d->extra()->extraHeight;
- }
-
- const double effTop = BORDER_SPACE + 0.5 * effTopBorderPen( _col, _row ).width();
- const double effBottom = h - BORDER_SPACE - 0.5 * effBottomBorderPen( _col, _row ).width();
-
- // Calculate d->textY based on the vertical alignment and a few
- // other inputs.
- switch( ay )
- {
- case Format::Top:
- {
- if ( tmpAngle == 0 )
- {
- d->textY = effTop + (double) d->fmAscent / format()->sheet()->doc()->zoomedResolutionY();
- }
- else if ( tmpAngle < 0 )
- {
- d->textY = effTop;
- }
- else
- {
- d->textY = effTop
- + (double) d->fmAscent * cos( tmpAngle * M_PI / 180 ) / format()->sheet()->doc()->zoomedResolutionY();
- }
- break;
- }
- case Format::Bottom:
- {
- if ( !tmpVerticalText && !tmpMultiRow && !tmpAngle )
- {
- d->textY = effBottom;
- }
- else if ( tmpAngle != 0 )
- {
- // Is enough place available?
- if ( effBottom - effTop - d->textHeight > 0 )
- {
- if ( tmpAngle < 0 )
- {
- d->textY = effBottom - d->textHeight;
- }
- else
- {
- d->textY = effBottom - d->textHeight
- + ( (double) d->fmAscent * cos( tmpAngle * M_PI / 180 ) / format()->sheet()->doc()->zoomedResolutionY() );
- }
- }
- else
- {
- if ( tmpAngle < 0 )
- {
- d->textY = effTop;
- }
- else
- {
- d->textY = effTop
- + ( (double) d->fmAscent * cos( tmpAngle * M_PI / 180 )
- / format()->sheet()->doc()->zoomedResolutionY() );
- }
- }
- }
- else if ( tmpMultiRow && !tmpVerticalText )
- {
- // Is enough place available?
- if ( effBottom - effTop - d->textHeight > 0 )
- {
- d->textY = effBottom - d->textHeight
- + (double)d->fmAscent / format()->sheet()->doc()->zoomedResolutionY();
- }
- else
- {
- d->textY = effTop
- + (double) d->fmAscent / format()->sheet()->doc()->zoomedResolutionY();
- }
- }
- else
- {
- // Is enough place available?
- if ( effBottom - effTop - d->textHeight > 0 )
- {
- d->textY = effBottom - d->textHeight
- + (double)d->fmAscent / format()->sheet()->doc()->zoomedResolutionY();
- }
- else
- {
- d->textY = effTop
- + (double) d->fmAscent / format()->sheet()->doc()->zoomedResolutionY();
- }
- }
- break;
- }
- case Format::Middle:
- case Format::UndefinedY:
- {
- if ( !tmpVerticalText && !tmpMultiRow && !tmpAngle )
- {
- d->textY = ( h - d->textHeight ) / 2
- + (double) d->fmAscent / format()->sheet()->doc()->zoomedResolutionY();
- }
- else if ( tmpAngle != 0 )
- {
- // Is enough place available?
- if ( effBottom - effTop - d->textHeight > 0 )
- {
- if ( tmpAngle < 0 )
- {
- d->textY = ( h - d->textHeight ) / 2;
- }
- else
- {
- d->textY = ( h - d->textHeight ) / 2
- + (double) d->fmAscent * cos( tmpAngle * M_PI / 180 ) / format()->sheet()->doc()->zoomedResolutionY();
- }
- }
- else
- {
- if ( tmpAngle < 0 )
- {
- d->textY = effTop;
- }
- else
- {
- d->textY = effTop
- + ( (double)d->fmAscent * cos( tmpAngle * M_PI / 180 ) / format()->sheet()->doc()->zoomedResolutionY() );
- }
- }
- }
- else if ( tmpMultiRow && !tmpVerticalText )
- {
- // Is enough place available?
- if ( effBottom - effTop - d->textHeight > 0 )
- {
- d->textY = ( h - d->textHeight ) / 2
- + (double) d->fmAscent / format()->sheet()->doc()->zoomedResolutionY();
- }
- else
- {
- d->textY = effTop
- + (double) d->fmAscent / format()->sheet()->doc()->zoomedResolutionY();
- }
- }
- else
- {
- // Is enough place available?
- if ( effBottom - effTop - d->textHeight > 0 )
- {
- d->textY = ( h - d->textHeight ) / 2
- + (double) d->fmAscent / format()->sheet()->doc()->zoomedResolutionY();
- }
- else
- d->textY = effTop
- + (double)d->fmAscent / format()->sheet()->doc()->zoomedResolutionY();
- }
- break;
- }
- }
-
- a = effAlignX();
- if ( format()->sheet()->getShowFormula() &&
- !( format()->sheet()->isProtected() && format()->isHideFormula( _col, _row ) ) )
- {
- a = Format::Left;
- }
-
- // Calculate d->textX based on alignment and textwidth.
- switch ( a ) {
- case Format::Left:
- d->textX = 0.5 * effLeftBorderPen( _col, _row ).width() + BORDER_SPACE;
- break;
- case Format::Right:
- d->textX = w - BORDER_SPACE - d->textWidth
- - 0.5 * effRightBorderPen( _col, _row ).width();
- break;
- case Format::Center:
- d->textX = 0.5 * ( w - BORDER_SPACE - d->textWidth -
- 0.5 * effRightBorderPen( _col, _row ).width() );
- break;
- }
-}
-
-
-// Recalculate the current text dimensions, i.e. d->textWidth and
-// d->textHeight.
-//
-// Used in makeLayout() and calculateTextParameters().
-//
-void Cell::textSize( TQPainter &_paint )
-{
- TQFontMetrics fm = _paint.fontMetrics();
- // Horizontal text ?
-
- int tmpAngle;
- int _row = row();
- int _col = column();
- bool tmpVerticalText;
- bool fontUnderlined;
- Format::AlignY ay;
-
- // Set tmpAngle, tmpeVerticalText, ay and fontUnderlined according
- // to if there is a matching condition or not.
- if ( d->hasExtra()
- && d->extra()->conditions
- && d->extra()->conditions->matchedStyle() )
- {
- Style *style = d->extra()->conditions->matchedStyle();
-
- if ( style->hasFeature( Style::SAngle, true ) )
- tmpAngle = style->rotateAngle();
- else
- tmpAngle = format()->getAngle( _col, _row );
-
- if ( style->hasFeature( Style::SVerticalText, true ) )
- tmpVerticalText = style->hasProperty( Style::PVerticalText );
- else
- tmpVerticalText = format()->verticalText( _col, _row );
-
- if ( style->hasFeature( Style::SAlignY, true ) )
- ay = style->alignY();
- else
- ay = format()->alignY( _col, _row );
-
- if ( style->hasFeature( Style::SFontFlag, true ) )
- fontUnderlined = ( style->fontFlags() & (uint) Style::FUnderline );
- else
- fontUnderlined = format()->textFontUnderline( _col, _row );
- }
- else {
- // The cell has no condition with a maxed style.
- tmpAngle = format()->getAngle( _col, _row );
- tmpVerticalText = format()->verticalText( _col, _row );
- ay = format()->alignY( _col, _row );
- fontUnderlined = format()->textFontUnderline( _col, _row );
- }
-
- // Set d->textWidth and d->textHeight to correct values according to
- // if the text is horizontal, vertical or rotated.
- if ( !tmpVerticalText && !tmpAngle ) {
- // Horizontal text.
-
- d->textWidth = format()->sheet()->doc()->unzoomItX( fm.width( d->strOutText ) );
- int offsetFont = 0;
- if ( ( ay == Format::Bottom ) && fontUnderlined ) {
- offsetFont = fm.underlinePos() + 1;
- }
-
- d->textHeight = format()->sheet()->doc()->unzoomItY( fm.ascent() + fm.descent()
- + offsetFont );
- }
- else if ( tmpAngle!= 0 ) {
- // Rotated text.
-
- d->textHeight = format()->sheet()->doc()
- ->unzoomItY( int( cos( tmpAngle * M_PI / 180 )
- * ( fm.ascent() + fm.descent() )
- + abs( int( ( fm.width( d->strOutText )
- * sin( tmpAngle * M_PI / 180 ) ) ) ) ) );
-
- d->textWidth = format()->sheet()->doc()
- ->unzoomItX( int( abs( int( ( sin( tmpAngle * M_PI / 180 )
- * ( fm.ascent() + fm.descent() ) ) ) )
- + fm.width( d->strOutText )
- * cos ( tmpAngle * M_PI / 180 ) ) );
- }
- else {
- // Vertical text.
- int width = 0;
- for ( unsigned int i = 0; i < d->strOutText.length(); i++ )
- width = TQMAX( width, fm.width( d->strOutText.at( i ) ) );
-
- d->textWidth = format()->sheet()->doc()->unzoomItX( width );
- d->textHeight = format()->sheet()->doc()->unzoomItY( ( fm.ascent() + fm.descent() )
- * d->strOutText.length() );
- }
-}
-
-
-// Get the effective font to use after the zooming and apply it to `painter'.
-//
-// Used in makeLayout() and calculateTextParameters().
-//
-
-void Cell::applyZoomedFont( TQPainter &painter, int _col, int _row )
-{
- TQFont tmpFont( format()->textFont( _col, _row ) );
-
- // If there is a matching condition on this cell then set the
- // according style parameters.
- if ( d->hasExtra()
- && d->extra()->conditions
- && d->extra()->conditions->matchedStyle() ) {
-
- Style * s = d->extra()->conditions->matchedStyle();
-
- // Other size?
- if ( s->hasFeature( Style::SFontSize, true ) )
- tmpFont.setPointSizeFloat( s->fontSize() );
-
- // Other attributes?
- if ( s->hasFeature( Style::SFontFlag, true ) ) {
- uint flags = s->fontFlags();
-
- tmpFont.setBold( flags & (uint) Style::FBold );
- tmpFont.setUnderline( flags & (uint) Style::FUnderline );
- tmpFont.setItalic( flags & (uint) Style::FItalic );
- tmpFont.setStrikeOut( flags & (uint) Style::FStrike );
- }
-
- // Other family?
- if ( s->hasFeature( Style::SFontFamily, true ) )
- tmpFont.setFamily( s->fontFamily() );
- }
-#if 0
- else
- /*
- * could somebody please explaint why we check for isProtected or isHideFormula here
- */
- if ( d->extra()->conditions
- && d->extra()->conditions->currentCondition( condition )
- && !(format()->sheet()->getShowFormula()
- && !( format()->sheet()->isProtected()
- && format()->isHideFormula( d->column, d->row ) ) ) )
- {
- if ( condition.fontcond )
- tmpFont = *(condition.fontcond);
- else
- tmpFont = condition.style->font();
- }
-#endif
-
- // Scale the font size according to the current zoom.
- tmpFont.setPointSizeFloat( 0.01 * format()->sheet()->doc()->zoom()
- * tmpFont.pointSizeFloat() );
-
- painter.setFont( tmpFont );
-}
-
-
-//used in Sheet::adjustColumnHelper and Sheet::adjustRow
-void Cell::calculateTextParameters( TQPainter &_painter,
- int _col, int _row )
-{
- // Apply the correct font to _painter.
- applyZoomedFont( _painter, _col, _row );
-
- // Recalculate d->textWidth and d->textHeight
- textSize( _painter );
-
- // Recalculate d->textX and d->textY.
- offsetAlign( _col, _row );
-}
-
-
-// ----------------------------------------------------------------
-// Formula handling
-
-
-bool Cell::makeFormula()
-{
- clearFormula ();
-
- d->formula = new KSpread::Formula (sheet(), this);
- d->formula->setExpression (d->strText);
-
- if (!d->formula->isValid ()) {
- // Did a syntax error occur ?
- clearFormula();
-
- if (format()->sheet()->doc()->getShowMessageError())
- {
- TQString tmp(i18n("Error in cell %1\n\n"));
- tmp = tmp.arg( fullName() );
- KMessageBox::error( (TQWidget*)0L, tmp);
- }
- setFlag(Flag_ParseError);
- Value v;
- v.setError ( "####" );
- setValue (v);
- return false;
- }
-
- // we must recalc
- setCalcDirtyFlag ();
-
- return true;
-}
-
-void Cell::clearFormula()
-{
- delete d->formula;
- d->formula = 0L;
-}
-
-bool Cell::calc(bool delay)
-{
- if ( !isFormula() )
- return true;
-
- if (d->formula == 0)
- {
- if ( testFlag( Flag_ParseError ) ) // there was a parse error
- return false;
- else
- {
- /* we were probably at a "isLoading() = true" state when we originally
- * parsed
- */
- makeFormula ();
-
- if ( d->formula == 0 ) // there was a parse error
- return false;
- }
- }
-
- if ( !testFlag( Flag_CalcDirty ) )
- return true;
-
- if ( delay )
- {
- if ( format()->sheet()->doc()->delayCalculation() )
- return true;
- }
-
- setFlag(Flag_LayoutDirty);
- setFlag(Flag_TextFormatDirty);
- clearFlag(Flag_CalcDirty);
-
- Value result = d->formula->eval ();
- setValue (result);
- if (result.isNumber())
- checkNumberFormat(); // auto-chooses number or scientific
-
- clearFlag(Flag_CalcDirty);
- setFlag(Flag_LayoutDirty);
-
- return true;
-}
-
-
-// ================================================================
-// Painting
-
-
-// Paint the cell. This is the main function that calls a lot of
-// helper functions.
-//
-// `rect' is the rectangle that we should paint on. If the cell
-// does not overlap this rectangle, we can return immediately.
-// `coordinate' is the origin (the upper left) of the cell in document
-// coordinates.
-//
-
-void Cell::paintCell( const KoRect &rect, TQPainter & painter,
- View *view,
- const KoPoint &coordinate,
- const TQPoint &cellRef,
- int paintBorder,
- TQPen & rightPen, TQPen & bottomPen,
- TQPen & leftPen, TQPen & topPen,
- TQValueList<TQPoint> &mergedCellsPainted,
- bool drawCursor )
-{
- bool paintBorderRight = paintBorder & Border_Right;
- bool paintBorderBottom = paintBorder & Border_Bottom;
- bool paintBorderLeft = paintBorder & Border_Left;
- bool paintBorderTop = paintBorder & Border_Top;
-
- // If we are already painting this cell, then return immediately.
- // This avoids infinite recursion.
- if ( testFlag( Flag_PaintingCell ) )
- return;
-
- // Indicate that we are painting this cell now.
- setFlag( Flag_PaintingCell );
-
- // This flag indicates that we are working on drawing the cells that
- // another cell is obscuring. The value is the number of levels down we
- // are currently working -- i.e. a cell obscured by a cell which is
- // obscured by a cell.
- static int paintingObscured = 0;
-
-#if 0
- if (paintingObscured == 0)
- kdDebug(36001) << "painting cell " << name() << endl;
- else
- kdDebug(36001) << " painting obscured cell " << name() << endl;
-#endif
-
- // Sanity check: If we're working on drawing an obscured cell, that
- // means this cell should have a cell that obscures it.
- Q_ASSERT(!(paintingObscured > 0 && d->extra()->obscuringCells.isEmpty()));
-
- // The parameter cellref should be *this, unless this is the default cell.
- Q_ASSERT(isDefault()
- || (((cellRef.x() == d->column) && (cellRef.y() == d->row))));
-
- Sheet::LayoutDirection sheetDir = format()->sheet()->layoutDirection();
-
- double left = coordinate.x();
-
- ColumnFormat * colFormat = format()->sheet()->columnFormat( cellRef.x() );
- RowFormat * rowFormat = format()->sheet()->rowFormat( cellRef.y() );
-
- // Set width, height to the total width and height that this cell
- // covers, including obscured cells, and width0, height0 to the
- // width and height of this cell, maybe merged but never implicitly
- // extended.
- double width0 = colFormat->dblWidth();
- double height0 = rowFormat->dblHeight();
- double width = width0;
- double height = height0;
-
- // Handle right-to-left layout.
- // In an RTL sheet the cells have to be painted at their opposite horizontal
- // location on the canvas, meaning that column A will be the rightmost column
- // on screen, column B will be to the left of it and so on. Here we change
- // the horizontal coordinate at which we start painting the cell in case the
- // sheet's direction is RTL. We do this only if paintingObscured is 0,
- // otherwise the cell's painting location will flip back and forth in
- // consecutive calls to paintCell when painting obscured cells.
- if ( sheetDir == Sheet::RightToLeft && paintingObscured == 0
- && view && view->canvasWidget() )
- {
- double dwidth = view->doc()->unzoomItX(view->canvasWidget()->width());
- left = dwidth - coordinate.x() - width;
- }
-
- // See if this cell is merged or has overflown into neighbor cells.
- // In that case, the width/height is greater than just the cell
- // itself.
- if (d->hasExtra()) {
- if (d->extra()->mergedXCells > 0 || d->extra()->mergedYCells > 0) {
- // merged cell extends to the left if sheet is RTL
- if ( sheetDir == Sheet::RightToLeft ) {
- left -= d->extra()->extraWidth - width;
- }
- width0 = d->extra()->extraWidth;
- height0 = d->extra()->extraHeight;
- width = d->extra()->extraWidth;
- height = d->extra()->extraHeight;
- }
- else {
-#if 0
- width += d->extra()->extraXCells ? d->extra()->extraWidth : 0;
- height += d->extra()->extraYCells ? d->extra()->extraHeight : 0;
-#else
- // FIXME: Make extraWidth/Height really contain the *extra* width/height.
- if ( d->extra()->extraXCells )
- width = d->extra()->extraWidth;
- if ( d->extra()->extraYCells )
- height = d->extra()->extraHeight;
-#endif
- }
- }
-
- // Check if the cell is "selected", i.e. it should be drawn with the
- // color that indicates selection (dark blue). If more than one
- // square is selected, the last one uses the ordinary colors. In
- // that case, "selected" will be set to false even though the cell
- // itself really is selected.
- bool selected = false;
- if ( view != NULL ) {
- selected = view->selectionInfo()->contains( cellRef );
-
- // But the cell doesn't look selected if this is the marker cell.
- Cell *cell = format()->sheet()->cellAt( view->selectionInfo()->marker() );
- TQPoint bottomRight( view->selectionInfo()->marker().x() + cell->extraXCells(),
- view->selectionInfo()->marker().y() + cell->extraYCells() );
- TQRect markerArea( view->selectionInfo()->marker(), bottomRight );
- selected = selected && !( markerArea.contains( cellRef ) );
-
- // Don't draw any selection at all when printing.
- if ( painter.device()->isExtDev() || !drawCursor )
- selected = false;
- }
-
- // Need to make a new layout ?
- //
- // FIXME: We have already used (at least) extraWidth/Height above,
- // and now we are recalculating the layout. This has to be
- // moved up above all uses.
- //
- // FIXME: This needs to be taken out eventually - it is done in
- // canvas::paintUpdates().
- if ( testFlag( Flag_LayoutDirty ) )
- makeLayout( painter, cellRef.x(), cellRef.y() );
-
- // ---------------- Start the actual painting. ----------------
-
- // If the rect of this cell doesn't intersect the rect that should
- // be painted, we can skip the rest and return. (Note that we need
- // to calculate `left' first before we can do this.)
- const KoRect cellRect( left, coordinate.y(), width, height );
- const KoRect cellRect0( left, coordinate.y(), width0, height0 );
- if ( !cellRect.intersects( rect ) ) {
- clearFlag( Flag_PaintingCell );
- return;
- }
-
- // Get the background color.
- //
- // If there is a condition giving the background color for this cell
- // (and it matches), use that one, otherwise get the standard
- // background.
- TQColor backgroundColor;
- if ( d->hasExtra() && d->extra()->conditions
- && d->extra()->conditions->matchedStyle()
- && d->extra()->conditions->matchedStyle()->hasFeature( Style::SBackgroundColor, true ) )
- backgroundColor = d->extra()->conditions->matchedStyle()->bgColor();
- else
- backgroundColor = bgColor( cellRef.x(), cellRef.y() );
-
- // 1. Paint the background.
- if ( !isPartOfMerged() )
- paintBackground( painter, cellRect0, cellRef, selected, backgroundColor );
-
- // 2. Paint the default borders if we are on screen or if we are printing
- // and the checkbox to do this is checked.
- if ( painter.device()->devType() != TQInternal::Printer
- || format()->sheet()->print()->printGrid())
- paintDefaultBorders( painter, rect, cellRect, cellRef,
- paintBorderRight, paintBorderBottom,
- paintBorderLeft, paintBorderTop,
- rightPen, bottomPen, leftPen, topPen );
-
- // 3. Paint all the cells that this one obscures. They may only be
- // partially obscured.
- //
- // The `paintingObscured' variable is used to avoid infinite
- // recursion since cells sometimes paint their obscuring cell as
- // well.
- paintingObscured++;
-
- if (d->hasExtra() && (d->extra()->extraXCells > 0
- || d->extra()->extraYCells > 0)) {
- //kdDebug(36001) << "painting obscured cells for " << name() << endl;
-
- paintObscuredCells( rect, painter, view, cellRect, cellRef,
- paintBorderRight, paintBorderBottom,
- paintBorderLeft, paintBorderTop,
- rightPen, bottomPen, leftPen, topPen,
- mergedCellsPainted);
-
- // FIXME: Is this the right place for this?
- if ( d->extra()->mergedXCells > 0 || d->extra()->mergedYCells > 0 )
- mergedCellsPainted.prepend( cellRef );
- }
- paintingObscured--;
-
- // 4. Paint the borders of the cell if no other cell is forcing this
- // one, i.e. this cell is not part of a merged cell.
- //
-
- // If we print pages, then we disable clipping, otherwise borders are
- // cut in the middle at the page borders.
- if ( painter.device()->isExtDev() )
- painter.setClipping( false );
-
- // Paint the borders if this cell is not part of another merged cell.
- if ( !isPartOfMerged() ) {
- // if (!testFlag(Flag_Highlight))
- paintCellBorders( painter, rect, cellRect0,
- cellRef,
- paintBorderRight, paintBorderBottom,
- paintBorderLeft, paintBorderTop,
- rightPen, bottomPen, leftPen, topPen );
- }
-
- // Turn clipping back on.
- if ( painter.device()->isExtDev() )
- painter.setClipping( true );
-
- // 5. Paint diagonal lines and page borders.
- paintCellDiagonalLines( painter, cellRect0, cellRef );
-
- paintPageBorders( painter, cellRect0, cellRef,
- paintBorderRight, paintBorderBottom );
-
-
- // 6. Now paint the content, if this cell isn't obscured.
- if ( !isObscured() ) {
-
- // 6a. Paint possible comment indicator.
- if ( !painter.device()->isExtDev()
- || format()->sheet()->print()->printCommentIndicator() )
- paintCommentIndicator( painter, cellRect, cellRef, backgroundColor );
-
- // 6b. Paint possible formula indicator.
- if ( !painter.device()->isExtDev()
- || format()->sheet()->print()->printFormulaIndicator() )
- paintFormulaIndicator( painter, cellRect, backgroundColor );
-
- // 6c. Paint possible indicator for clipped text.
- paintMoreTextIndicator( painter, cellRect, backgroundColor );
-
- //6c. Paint cell highlight
-#if 0
- if (highlightBorder != Border_None)
- paintCellHighlight ( painter, cellRect, cellRef, highlightBorder,
- rightHighlightPen, bottomHighlightPen,
- leftHighlightPen, topHighlightPen );
-#endif
-
- // 6d. Paint the text in the cell unless:
- // a) it is empty
- // b) something indicates that the text should not be painted
- // c) the sheet is protected and the cell is hidden.
- if ( !d->strOutText.isEmpty()
- && ( !painter.device()->isExtDev()
- || !format()->getDontprintText( cellRef.x(), cellRef.y() ) )
- && !( format()->sheet()->isProtected()
- && format()->isHideAll( cellRef.x(), cellRef.y() ) ) )
- {
- paintText( painter, cellRect, cellRef );
- }
- }
-
- // 7. If this cell is obscured and we are not already painting obscured
- // cells, then paint the obscuring cell(s). Otherwise don't do
- // anything so that we don't cause an infinite loop.
- if ( isObscured() && paintingObscured == 0 &&
- !( sheetDir == Sheet::RightToLeft && painter.device()->isExtDev() ) )
- {
-
- //kdDebug(36001) << "painting cells that obscure " << name() << endl;
-
- // Store the obscuringCells list in a list of TQPoint(column, row)
- // This avoids crashes during the iteration through
- // obscuringCells, when the cells may get non valid or the list
- // itself gets changed during a call of obscuringCell->paintCell
- // (this happens e.g. when there is an updateDepend)
- if (d->hasExtra()) {
- TQValueList<TQPoint> listPoints;
- TQValueList<Cell*>::iterator it = d->extra()->obscuringCells.begin();
- TQValueList<Cell*>::iterator end = d->extra()->obscuringCells.end();
- for ( ; it != end; ++it ) {
- Cell *obscuringCell = *it;
-
- listPoints.append( TQPoint( obscuringCell->column(), obscuringCell->row() ) );
- }
-
- TQValueList<TQPoint>::iterator it1 = listPoints.begin();
- TQValueList<TQPoint>::iterator end1 = listPoints.end();
- for ( ; it1 != end1; ++it1 ) {
- TQPoint obscuringCellRef = *it1;
-
- // Only paint those obscuring cells that haven't been already
- // painted yet.
- //
- // This optimization removes an O(n^4) behaviour where n is
- // the number of cells on one edge in a merged cell.
- if ( mergedCellsPainted.contains( obscuringCellRef ) )
- continue;
-
- Cell *obscuringCell = format()->sheet()->cellAt( obscuringCellRef.x(),
- obscuringCellRef.y() );
-
- if ( obscuringCell != 0 ) {
- double x = format()->sheet()->dblColumnPos( obscuringCellRef.x() );
- double y = format()->sheet()->dblRowPos( obscuringCellRef.y() );
- if ( view != 0 ) {
- x -= view->canvasWidget()->xOffset();
- y -= view->canvasWidget()->yOffset();
- }
-
- KoPoint corner( x, y );
- painter.save();
-
- // Get the effective pens for the borders. These are
- // determined by possible conditions on the cell with
- // associated styles.
- TQPen rp( obscuringCell->effRightBorderPen( obscuringCellRef.x(),
- obscuringCellRef.y() ) );
- TQPen bp( obscuringCell->effBottomBorderPen( obscuringCellRef.x(),
- obscuringCellRef.y() ) );
- TQPen lp( obscuringCell->effLeftBorderPen( obscuringCellRef.x(),
- obscuringCellRef.y() ) );
- TQPen tp( obscuringCell->effTopBorderPen( obscuringCellRef.x(),
- obscuringCellRef.y() ) );
-
-
- //kdDebug(36001) << " painting obscuring cell "
- // << obscuringCell->name() << endl;
- // TQPen highlightPen;
-
- //Note: Painting of highlight isn't quite right. If several
- // cells are merged, then the whole merged cell will be
- // painted with the colour of the last cell referenced
- // which is inside the merged range.
- obscuringCell->paintCell( rect, painter, view,
- corner, obscuringCellRef,
- Border_Left|Border_Top|Border_Right|Border_Bottom,
- rp, bp, lp, tp,
- mergedCellsPainted); // new pens
- painter.restore();
- }
- }
- }
- }
-
- // We are done with the painting, so remove the flag on the cell.
- clearFlag( Flag_PaintingCell );
-}
-
-
-
-// The following code was commented out in the above function. I'll
-// leave it here in case this functionality is ever re-implemented and
-// someone wants some code to start from.
-//
-#if 0
-
- /**
- * Modification for drawing the button
- */
- if ( d->style == Cell::ST_Button ) {
- TQBrush fill( TQt::lightGray );
- TQApplication::style().drawControl( TQStyle::CE_PushButton, &_painter, this,
- TQRect( _tx + 1, _ty + 1, w2 - 1, h2 - 1 ),
- defaultColorGroup ); //, selected, &fill );
- }
-
- /**
- * Modification for drawing the combo box
- */
- else if ( d->style == Cell::ST_Select ) {
- TQApplication::style().drawComboButton( &_painter, _tx + 1, _ty + 1,
- w2 - 1, h2 - 1,
- defaultColorGroup, selected );
- }
-#endif
-
-
-#if 0
- void Cell::paintCellHighlight(TQPainter& painter,
- const KoRect& cellRect,
- const TQPoint& cellRef,
- const int highlightBorder,
- const TQPen& rightPen,
- const TQPen& bottomPen,
- const TQPen& leftPen,
- const TQPen& topPen
- )
-{
- //painter.drawLine(cellRect.left(),cellRect.top(),cellRect.right(),cellRect.bottom());
- //TQPen pen(d->extra()->highlight);
- //painter.setPen(highlightPen);
-
- TQBrush nullBrush;
- painter.setBrush(nullBrush);
-
- TQRect zoomedCellRect = sheet()->doc()->zoomRect( cellRect );
-
- //The highlight rect is just inside the main cell rect
- //This saves the hassle of repainting nearby cells when the highlight is changed as the highlight areas
- //do not overlap
- zoomedCellRect.setLeft(zoomedCellRect.left()+1);
- //zoomedCellRect.setRight(zoomedCellRect.right()-1);
- zoomedCellRect.setTop(zoomedCellRect.top()+1);
- //zoomedCellRect.setBottom(zoomedCellRect.bottom()-1);
-
- if ( cellRef.x() != KS_colMax )
- zoomedCellRect.setWidth( zoomedCellRect.width() - 1 );
- if ( cellRef.y() != KS_rowMax )
- zoomedCellRect.setHeight( zoomedCellRect.height() - 1 );
-
- if (highlightBorder & Border_Top)
- {
- painter.setPen(topPen);
- painter.drawLine(zoomedCellRect.left(),zoomedCellRect.top(),zoomedCellRect.right(),zoomedCellRect.top());
- }
- if (highlightBorder & Border_Left)
- {
- painter.setPen(leftPen);
- painter.drawLine(zoomedCellRect.left(),zoomedCellRect.top(),zoomedCellRect.left(),zoomedCellRect.bottom());
- }
- if (highlightBorder & Border_Right)
- {
- painter.setPen(rightPen);
- painter.drawLine(zoomedCellRect.right(),zoomedCellRect.top(),zoomedCellRect.right(),zoomedCellRect.bottom());
- }
- if (highlightBorder & Border_Bottom)
- {
- painter.setPen(bottomPen);
- painter.drawLine(zoomedCellRect.left(),zoomedCellRect.bottom(),zoomedCellRect.right(),zoomedCellRect.bottom());
- }
-
- if (highlightBorder & Border_SizeGrip)
- {
- TQBrush brush(rightPen.color());
- painter.setBrush(brush);
- painter.setPen(rightPen);
- painter.drawRect(zoomedCellRect.right()-3,zoomedCellRect.bottom()-3,4,4);
- }
-
- //painter.drawRect(zoomedCellRect.left(),zoomedCellRect.top(),zoomedCellRect.width(),zoomedCellRect.height());
-}
-#endif
-
-
-// Paint all the cells that this cell obscures (helper function to paintCell).
-//
-void Cell::paintObscuredCells(const KoRect& rect, TQPainter& painter,
- View* view,
- const KoRect &cellRect,
- const TQPoint &cellRef,
- bool paintBorderRight,
- bool _paintBorderBottom,
- bool paintBorderLeft,
- bool _paintBorderTop,
- TQPen & rightPen, TQPen & _bottomPen,
- TQPen & leftPen, TQPen & _topPen,
- TQValueList<TQPoint> &mergedCellsPainted)
-{
- // If there are no obscured cells, return.
- if ( !extraXCells() && !extraYCells() )
- return;
-
- double ypos = cellRect.y();
- int maxY = extraYCells();
- int maxX = extraXCells();
-
- // Loop through the rectangle of squares that we obscure and paint them.
- for ( int y = 0; y <= maxY; ++y ) {
- double xpos = cellRect.x();
- RowFormat* rl = format()->sheet()->rowFormat( cellRef.y() + y );
-
- for( int x = 0; x <= maxX; ++ x ) {
- ColumnFormat * cl = format()->sheet()->columnFormat( cellRef.x() + x );
- if ( y != 0 || x != 0 ) {
- uint column = cellRef.x() + x;
- uint row = cellRef.y() + y;
-
- TQPen topPen;
- TQPen bottomPen;
- bool paintBorderTop;
- bool paintBorderBottom;
-
- Cell *cell = format()->sheet()->cellAt( column, row );
- KoPoint corner( xpos, ypos );
-
- // Check if the upper and lower borders should be painted, and
- // if so which pens we should use. There used to be a nasty
- // bug here (#61452).
- // Check top pen. Only check if this is not on the top row.
- topPen = _topPen;
- paintBorderTop = _paintBorderTop;
- if ( row > 1 && !cell->isPartOfMerged() ) {
- Cell *cellUp = format()->sheet()->cellAt( column, row - 1 );
-
- if ( cellUp->isDefault() )
- paintBorderTop = false;
- else {
- // If the cell towards the top is part of a merged cell, get
- // the pointer to the master cell.
- cellUp = cellUp->ultimateObscuringCell();
-
- topPen = cellUp->effBottomBorderPen( cellUp->column(),
- cellUp->row() );
-
-#if 0
- int penWidth = TQMAX(1, sheet()->doc()->zoomItY( topPen.width() ));
- topPen.setWidth( penWidth );
-#endif
- }
- }
-
- // FIXME: I thought we had to check bottom pen as well.
- // However, it looks as if we don't need to. It works anyway.
- bottomPen = _bottomPen;
- paintBorderBottom = _paintBorderBottom;
-
- int paintBorder = Border_None;
- if (paintBorderLeft) paintBorder |= Cell::Border_Left;
- if (paintBorderRight) paintBorder |= Cell::Border_Right;
- if (paintBorderTop) paintBorder |= Cell::Border_Top;
- if (paintBorderBottom) paintBorder |= Cell::Border_Bottom;
-
- /*Cell::BorderSides highlightBorder = Border_None;
- TQPen highlightPen;*/
-
-
- //kdDebug(36001) << "calling paintcell for obscured cell "
- // << cell->name() << endl;
- cell->paintCell( rect, painter, view,
- corner,
- TQPoint( cellRef.x() + x, cellRef.y() + y ),
- paintBorder,
- rightPen, bottomPen, leftPen, topPen,
- mergedCellsPainted);
- }
- xpos += cl->dblWidth();
- }
-
- ypos += rl->dblHeight();
- }
-}
-
-
-// Paint the background of this cell.
-//
-void Cell::paintBackground( TQPainter& painter, const KoRect &cellRect,
- const TQPoint &cellRef, bool selected,
- TQColor &backgroundColor )
-{
- TQColorGroup defaultColorGroup = TQApplication::palette().active();
- TQRect zoomedCellRect = sheet()->doc()->zoomRect( cellRect );
-
- // If this is not the KS_rowMax and/or KS_colMax, then we reduce
- // width and/or height by one. This is due to the fact that the
- // right/bottom most pixel is shared with the left/top most pixel of
- // the following cell. Only in the case of KS_colMax/KS_rowMax we
- // need to draw even this pixel, as there isn't a following cell to
- // draw the background pixel.
- if ( cellRef.x() != KS_colMax )
- zoomedCellRect.setWidth( zoomedCellRect.width() - 1 );
- if ( cellRef.y() != KS_rowMax )
- zoomedCellRect.setHeight( zoomedCellRect.height() - 1 );
-
- // Determine the correct background color
- if ( selected )
- {
- //If the cell's background color is too bright, use the default highlight color
- //Otherwise use a lighter version of the cell's background color.
- TQColor c;
-
- int averageColor = (backgroundColor.red() + backgroundColor.green() + backgroundColor.blue()) / 3;
-
- if (averageColor > 180)
- if (averageColor > 225)
- c = View::highlightColor();
- else
- c = backgroundColor.light( 115 ); //15% lighter
- else
- c = backgroundColor.light( 125 ); //25% lighter
-
- painter.setBackgroundColor( c );
- }
- else {
- TQColor bg( backgroundColor );
-
- // Handle printers separately.
- if ( !painter.device()->isExtDev() ) {
- if ( bg.isValid() )
- painter.setBackgroundColor( bg );
- else
- painter.setBackgroundColor( defaultColorGroup.base() );
- }
- else {
- //bad hack but there is a qt bug
- //so I can print backgroundcolor
- TQBrush bb( bg );
- if ( !bg.isValid() )
- bb.setColor( TQt::white );
-
- painter.fillRect( zoomedCellRect, bb );
- return;
- }
- }
-
- // Erase the background of the cell.
- if ( !painter.device()->isExtDev() )
- painter.eraseRect( zoomedCellRect );
-
- // Get a background brush
- TQBrush bb;
- if ( d->hasExtra()
- && d->extra()->conditions
- && d->extra()->conditions->matchedStyle()
- && d->extra()->conditions->matchedStyle()->hasFeature( Style::SBackgroundBrush, true ) )
- bb = d->extra()->conditions->matchedStyle()->backGroundBrush();
- else
- bb = backGroundBrush( cellRef.x(), cellRef.y() );
-
- // Draw background pattern if necessary.
- if ( bb.style() != TQt::NoBrush )
- painter.fillRect( zoomedCellRect, bb );
-
- backgroundColor = painter.backgroundColor();
-}
-
-
-// Paint the standard light grey borders that are always visible.
-//
-void Cell::paintDefaultBorders( TQPainter& painter, const KoRect &rect,
- const KoRect &cellRect,
- const TQPoint &cellRef,
- bool paintBorderRight, bool /*paintBorderBottom*/,
- bool paintBorderLeft, bool paintBorderTop,
- TQPen const & rightPen, TQPen const & /*bottomPen*/,
- TQPen const & leftPen, TQPen const & topPen )
-{
- /*
- *** Notes about optimisation ***
-
- This function was painting the top , left , right & bottom lines in almost all cells previously, contrary to what the comment
- below says should happen. There doesn't appear to be a UI option to enable or disable showing of the grid when printing at the moment,
- so I have disabled drawing of right and bottom borders for all cells.
-
- I also couldn't work out under what conditions the variables dt / db would come out as anything other than 0 in the code
- for painting the various borders. The effTopBorderPen / effBottomBorderPen calls were taking up a lot of time
- according some profiling I did. If that code really is necessary, we need to find a more efficient way of getting the widths
- than grabbing the whole TQPen object and asking it.
-
-
- --Robert Knight ([email protected])
- */
- Doc* doc = sheet()->doc();
-
- Sheet::LayoutDirection sheetDir = format()->sheet()->layoutDirection();
- bool paintingToExternalDevice = painter.device()->isExtDev();
-
- // Each cell is responsible for drawing it's top and left portions
- // of the "default" grid. --Or not drawing it if it shouldn't be
- // there. It's also responsible to paint the right and bottom, if
- // it is the last cell on a print out.
-
- bool paintTop;
- bool paintLeft;
- bool paintBottom=false;
- bool paintRight=false;
-
- paintLeft = ( paintBorderLeft && leftPen.style() == TQt::NoPen
- && sheet()->getShowGrid() && sheetDir==Sheet::LeftToRight );
- paintRight = ( paintBorderRight && rightPen.style() == TQt::NoPen
- && sheet()->getShowGrid() && sheetDir==Sheet::RightToLeft );
- paintTop = ( paintBorderTop && topPen.style() == TQt::NoPen
- && sheet()->getShowGrid() );
-// paintBottom = ( paintBorderBottom && sheet()->getShowGrid()
-// && bottomPen.style() == TQt::NoPen );
-
-
- //Set the single-pixel with pen for drawing the borders with.
- painter.setPen( TQPen( sheet()->doc()->gridColor(), 1, TQt::SolidLine ) );
-
- // If there are extra cells, there might be more conditions.
- if (d->hasExtra()) {
- TQValueList<Cell*>::const_iterator it = d->extra()->obscuringCells.begin();
- TQValueList<Cell*>::const_iterator end = d->extra()->obscuringCells.end();
- for ( ; it != end; ++it ) {
- Cell *cell = *it;
-
- paintTop = paintTop && ( cell->row() == cellRef.y() );
- paintBottom = false;
-
- if ( sheetDir == Sheet::RightToLeft ) {
- paintRight = paintRight && ( cell->column() == cellRef.x() );
- paintLeft = false;
- }
- else {
- paintLeft = paintLeft && ( cell->column() == cellRef.x() );
- paintRight = false;
- }
- }
- }
-
- // The left border.
- if ( paintLeft ) {
- int dt = 0;
- int db = 0;
-
- #if 0
- if ( cellRef.x() > 1 ) {
- Cell *cell_west = format()->sheet()->cellAt( cellRef.x() - 1,
- cellRef.y() );
- TQPen t = cell_west->effTopBorderPen( cellRef.x() - 1, cellRef.y() );
- TQPen b = cell_west->effBottomBorderPen( cellRef.x() - 1, cellRef.y() );
-
- if ( t.style() != TQt::NoPen )
- dt = ( t.width() + 1 )/2;
- if ( b.style() != TQt::NoPen )
- db = ( t.width() / 2);
- }
- #endif
-
- // If we are on paper printout, we limit the length of the lines.
- // On paper, we always have full cells, on screen not.
- if ( paintingToExternalDevice ) {
- if ( sheetDir == Sheet::RightToLeft )
- painter.drawLine( doc->zoomItX( TQMAX( rect.left(), cellRect.right() ) ),
- doc->zoomItY( TQMAX( rect.top(), cellRect.y() + dt ) ),
- doc->zoomItX( TQMIN( rect.right(), cellRect.right() ) ),
- doc->zoomItY( TQMIN( rect.bottom(), cellRect.bottom() - db ) ) );
- else
- painter.drawLine( doc->zoomItX( TQMAX( rect.left(), cellRect.x() ) ),
- doc->zoomItY( TQMAX( rect.top(), cellRect.y() + dt ) ),
- doc->zoomItX( TQMIN( rect.right(), cellRect.x() ) ),
- doc->zoomItY( TQMIN( rect.bottom(), cellRect.bottom() - db ) ) );
- }
- else {
- if ( sheetDir == Sheet::RightToLeft )
- painter.drawLine( doc->zoomItX( cellRect.right() ),
- doc->zoomItY( cellRect.y() + dt ),
- doc->zoomItX( cellRect.right() ),
- doc->zoomItY( cellRect.bottom() - db ) );
- else
- painter.drawLine( doc->zoomItX( cellRect.x() ),
- doc->zoomItY( cellRect.y() + dt ),
- doc->zoomItX( cellRect.x() ),
- doc->zoomItY( cellRect.bottom() - db ) );
- }
- }
-
-
- // The top border.
- if ( paintTop ) {
- int dl = 0;
- int dr = 0;
-
- #if 0
- if ( cellRef.y() > 1 ) {
- Cell *cell_north = format()->sheet()->cellAt( cellRef.x(),
- cellRef.y() - 1 );
-
- TQPen l = cell_north->effLeftBorderPen( cellRef.x(), cellRef.y() - 1 );
- TQPen r = cell_north->effRightBorderPen( cellRef.x(), cellRef.y() - 1 );
-
- if ( l.style() != TQt::NoPen )
- dl = ( l.width() - 1 ) / 2 + 1;
- if ( r.style() != TQt::NoPen )
- dr = r.width() / 2;
- }
- #endif
-
-
-
- // If we are on paper printout, we limit the length of the lines.
- // On paper, we always have full cells, on screen not.
- if ( paintingToExternalDevice ) {
- painter.drawLine( doc->zoomItX( TQMAX( rect.left(), cellRect.x() + dl ) ),
- doc->zoomItY( TQMAX( rect.top(), cellRect.y() ) ),
- doc->zoomItX( TQMIN( rect.right(), cellRect.right() - dr ) ),
- doc->zoomItY( TQMIN( rect.bottom(), cellRect.y() ) ) );
- }
- else {
- painter.drawLine( doc->zoomItX( cellRect.x() + dl ),
- doc->zoomItY( cellRect.y() ),
- doc->zoomItX( cellRect.right() - dr ),
- doc->zoomItY( cellRect.y() ) );
- }
- }
-
-
- // The right border.
- if ( paintRight ) {
- int dt = 0;
- int db = 0;
-
- #if 0
- if ( cellRef.x() < KS_colMax ) {
- Cell *cell_east = format()->sheet()->cellAt( cellRef.x() + 1,
- cellRef.y() );
-
- TQPen t = cell_east->effTopBorderPen( cellRef.x() + 1, cellRef.y() );
- TQPen b = cell_east->effBottomBorderPen( cellRef.x() + 1, cellRef.y() );
-
- if ( t.style() != TQt::NoPen )
- dt = ( t.width() + 1 ) / 2;
- if ( b.style() != TQt::NoPen )
- db = ( t.width() / 2);
- }
- #endif
-
- //painter.setPen( TQPen( sheet()->doc()->gridColor(), 1, TQt::SolidLine ) );
-
- // If we are on paper printout, we limit the length of the lines.
- // On paper, we always have full cells, on screen not.
- if ( painter.device()->isExtDev() ) {
- if ( sheetDir == Sheet::RightToLeft )
- painter.drawLine( doc->zoomItX( TQMAX( rect.left(), cellRect.x() ) ),
- doc->zoomItY( TQMAX( rect.top(), cellRect.y() + dt ) ),
- doc->zoomItX( TQMIN( rect.right(), cellRect.x() ) ),
- doc->zoomItY( TQMIN( rect.bottom(), cellRect.bottom() - db ) ) );
- else
- painter.drawLine( doc->zoomItX( TQMAX( rect.left(), cellRect.right() ) ),
- doc->zoomItY( TQMAX( rect.top(), cellRect.y() + dt ) ),
- doc->zoomItX( TQMIN( rect.right(), cellRect.right() ) ),
- doc->zoomItY( TQMIN( rect.bottom(), cellRect.bottom() - db ) ) );
- }
- else {
- if ( sheetDir == Sheet::RightToLeft )
- painter.drawLine( doc->zoomItX( cellRect.x() ),
- doc->zoomItY( cellRect.y() + dt ),
- doc->zoomItX( cellRect.x() ),
- doc->zoomItY( cellRect.bottom() - db ) );
- else
- painter.drawLine( doc->zoomItX( cellRect.right() ),
- doc->zoomItY( cellRect.y() + dt ),
- doc->zoomItX( cellRect.right() ),
- doc->zoomItY( cellRect.bottom() - db ) );
- }
- }
-
- // The bottom border.
- /*if ( paintBottom ) {
- int dl = 0;
- int dr = 0;
- if ( cellRef.y() < KS_rowMax ) {
- Cell *cell_south = format()->sheet()->cellAt( cellRef.x(),
- cellRef.y() + 1 );
-
- TQPen l = cell_south->effLeftBorderPen( cellRef.x(), cellRef.y() + 1 );
- TQPen r = cell_south->effRightBorderPen( cellRef.x(), cellRef.y() + 1 );
-
- if ( l.style() != TQt::NoPen )
- dl = ( l.width() - 1 ) / 2 + 1;
- if ( r.style() != TQt::NoPen )
- dr = r.width() / 2;
- }
-
- painter.setPen( TQPen( sheet()->doc()->gridColor(), 1, TQt::SolidLine ) );
-
- // If we are on paper printout, we limit the length of the lines.
- // On paper, we always have full cells, on screen not.
- if ( painter.device()->isExtDev() ) {
- painter.drawLine( doc->zoomItX( TQMAX( rect.left(), cellRect.x() + dl ) ),
- doc->zoomItY( TQMAX( rect.top(), cellRect.bottom() ) ),
- doc->zoomItX( TQMIN( rect.right(), cellRect.right() - dr ) ),
- doc->zoomItY( TQMIN( rect.bottom(), cellRect.bottom() ) ) );
- }
- else {
- painter.drawLine( doc->zoomItX( cellRect.x() + dl ),
- doc->zoomItY( cellRect.bottom() ),
- doc->zoomItX( cellRect.right() - dr ),
- doc->zoomItY( cellRect.bottom() ) );
- }
- }*/
-}
-
-
-// Paint a comment indicator if the cell has a comment.
-//
-void Cell::paintCommentIndicator( TQPainter& painter,
- const KoRect &cellRect,
- const TQPoint &/*cellRef*/,
- TQColor &backgroundColor )
-{
- Doc * doc = sheet()->doc();
-
- // Point the little corner if there is a comment attached
- // to this cell.
- if ( ( format()->propertiesMask() & (uint) Format::PComment )
- && cellRect.width() > 10.0
- && cellRect.height() > 10.0
- && ( sheet()->print()->printCommentIndicator()
- || ( !painter.device()->isExtDev() && sheet()->getShowCommentIndicator() ) ) ) {
- TQColor penColor = TQt::red;
-
- // If background has high red part, switch to blue.
- if ( tqRed( backgroundColor.rgb() ) > 127 &&
- tqGreen( backgroundColor.rgb() ) < 80 &&
- tqBlue( backgroundColor.rgb() ) < 80 )
- {
- penColor = TQt::blue;
- }
-
- // Get the triangle.
- TQPointArray point( 3 );
- if ( format()->sheet()->layoutDirection()==Sheet::RightToLeft ) {
- point.setPoint( 0, doc->zoomItX( cellRect.x() + 6.0 ),
- doc->zoomItY( cellRect.y() ) );
- point.setPoint( 1, doc->zoomItX( cellRect.x() ),
- doc->zoomItY( cellRect.y() ) );
- point.setPoint( 2, doc->zoomItX( cellRect.x() ),
- doc->zoomItY( cellRect.y() + 6.0 ) );
- }
- else {
- point.setPoint( 0, doc->zoomItX( cellRect.right() - 5.0 ),
- doc->zoomItY( cellRect.y() ) );
- point.setPoint( 1, doc->zoomItX( cellRect.right() ),
- doc->zoomItY( cellRect.y() ) );
- point.setPoint( 2, doc->zoomItX( cellRect.right() ),
- doc->zoomItY( cellRect.y() + 5.0 ) );
- }
-
- // And draw it.
- painter.setBrush( TQBrush( penColor ) );
- painter.setPen( TQt::NoPen );
- painter.drawPolygon( point );
- }
-}
-
-
-
-// Paint a small rectangle if this cell holds a formula.
-//
-void Cell::paintFormulaIndicator( TQPainter& painter,
- const KoRect &cellRect,
- TQColor &backgroundColor )
-{
- if ( isFormula() &&
- format()->sheet()->getShowFormulaIndicator() &&
- cellRect.width() > 10.0 &&
- cellRect.height() > 10.0 )
- {
- Doc* doc = sheet()->doc();
-
- TQColor penColor = TQt::blue;
- // If background has high blue part, switch to red.
- if ( tqRed( backgroundColor.rgb() ) < 80 &&
- tqGreen( backgroundColor.rgb() ) < 80 &&
- tqBlue( backgroundColor.rgb() ) > 127 )
- {
- penColor = TQt::red;
- }
-
- // Get the triangle...
- TQPointArray point( 3 );
- if ( format()->sheet()->layoutDirection()==Sheet::RightToLeft ) {
- point.setPoint( 0, doc->zoomItX( cellRect.right() - 6.0 ),
- doc->zoomItY( cellRect.bottom() ) );
- point.setPoint( 1, doc->zoomItX( cellRect.right() ),
- doc->zoomItY( cellRect.bottom() ) );
- point.setPoint( 2, doc->zoomItX( cellRect.right() ),
- doc->zoomItY( cellRect.bottom() - 6.0 ) );
- }
- else {
- point.setPoint( 0, doc->zoomItX( cellRect.x() ),
- doc->zoomItY( cellRect.bottom() - 6.0 ) );
- point.setPoint( 1, doc->zoomItX( cellRect.x() ),
- doc->zoomItY( cellRect.bottom() ) );
- point.setPoint( 2, doc->zoomItX( cellRect.x() + 6.0 ),
- doc->zoomItY( cellRect.bottom() ) );
- }
-
- // ...and draw it.
- painter.setBrush( TQBrush( penColor ) );
- painter.setPen( TQt::NoPen );
- painter.drawPolygon( point );
- }
-}
-
-
-// Paint an indicator that the text in the cell is cut.
-//
-void Cell::paintMoreTextIndicator( TQPainter& painter,
- const KoRect &cellRect,
- TQColor &backgroundColor )
-{
- // Show a red triangle when it's not possible to write all text in cell.
- // Don't print the red triangle if we're printing.
- if( testFlag( Flag_CellTooShortX ) &&
- !painter.device()->isExtDev() &&
- cellRect.height() > 4.0 &&
- cellRect.width() > 4.0 )
- {
- Doc* doc = sheet()->doc();
-
- TQColor penColor = TQt::red;
- // If background has high red part, switch to blue.
- if ( tqRed( backgroundColor.rgb() ) > 127
- && tqGreen( backgroundColor.rgb() ) < 80
- && tqBlue( backgroundColor.rgb() ) < 80 )
- {
- penColor = TQt::blue;
- }
-
- // Get the triangle...
- TQPointArray point( 3 );
- if ( d->strOutText.isRightToLeft() ) {
- point.setPoint( 0, doc->zoomItX( cellRect.left() + 4.0 ),
- doc->zoomItY( cellRect.y() + cellRect.height() / 2.0 -4.0 ) );
- point.setPoint( 1, doc->zoomItX( cellRect.left() ),
- doc->zoomItY( cellRect.y() + cellRect.height() / 2.0 ));
- point.setPoint( 2, doc->zoomItX( cellRect.left() + 4.0 ),
- doc->zoomItY( cellRect.y() + cellRect.height() / 2.0 +4.0 ) );
- }
- else {
- point.setPoint( 0, doc->zoomItX( cellRect.right() - 4.0 ),
- doc->zoomItY( cellRect.y() + cellRect.height() / 2.0 - 4.0 ) );
- point.setPoint( 1, doc->zoomItX( cellRect.right() ),
- doc->zoomItY( cellRect.y() + cellRect.height() / 2.0 ) );
- point.setPoint( 2, doc->zoomItX( cellRect.right() - 4.0 ),
- doc->zoomItY( cellRect.y() + cellRect.height() / 2.0 + 4.0 ) );
- }
-
- // ...and paint it.
- painter.setBrush( TQBrush( penColor ) );
- painter.setPen( TQt::NoPen );
- painter.drawPolygon( point );
- }
-}
-
-
-// Paint the real contents of a cell - the text.
-//
-void Cell::paintText( TQPainter& painter,
- const KoRect &cellRect,
- const TQPoint &cellRef )
-{
- Doc *doc = sheet()->doc();
-
- ColumnFormat *colFormat = format()->sheet()->columnFormat( cellRef.x() );
-
- TQColorGroup defaultColorGroup = TQApplication::palette().active();
- TQColor textColorPrint = effTextColor( cellRef.x(), cellRef.y() );
-
- // Resolve the text color if invalid (=default).
- if ( !textColorPrint.isValid() ) {
- if ( painter.device()->isExtDev() )
- textColorPrint = TQt::black;
- else
- textColorPrint = TQApplication::palette().active().text();
- }
-
- TQPen tmpPen( textColorPrint );
-
- // Set the font according to the current zoom.
- applyZoomedFont( painter, cellRef.x(), cellRef.y() );
-
- // Check for red font color for negative values.
- if ( !d->hasExtra()
- || !d->extra()->conditions
- || !d->extra()->conditions->matchedStyle() ) {
- if ( value().isNumber()
- && !( format()->sheet()->getShowFormula()
- && !( format()->sheet()->isProtected()
- && format()->isHideFormula( d->column, d->row ) ) ) )
- {
- double v = value().asFloat();
- if ( format()->floatColor( cellRef.x(), cellRef.y()) == Format::NegRed
- && v < 0.0 )
- tmpPen.setColor( TQt::red );
- }
- }
-
- // Check for blue color, for hyperlink.
- if ( !link().isEmpty() ) {
- tmpPen.setColor( TQApplication::palette().active().link() );
- TQFont f = painter.font();
- f.setUnderline( true );
- painter.setFont( f );
- }
-
-#if 0
-/****
-
- For now I am commenting this out -- with the default color display you
- can read normal text through a highlighted background. Maybe this isn't
- always the case, though, and we can put the highlighted text color back in.
- In that case, we need to somewhere in here figure out if the text overlaps
- another cell outside of the selection, otherwise that portion of the text
- will be printed white on white. So just that portion would need to be
- painted again in the normal color.
-
- This should probably be done eventually, anyway, because I like using the
- reverse text color for highlighted cells. I just don't like extending the
- cell 'highlight' background outside of the selection rectangle because it
- looks REALLY ugly.
-*/
-
- if ( selected && ( cellRef.x() != marker.x() || cellRef.y() != marker.y() ) )
- {
- TQPen p( tmpPen );
- p.setColor( defaultColorGroup.highlightedText() );
- painter.setPen( p );
- }
- else {
- painter.setPen(tmpPen);
- }
-#endif
- painter.setPen( tmpPen );
-
- TQString tmpText = d->strOutText;
- double tmpHeight = d->textHeight;
- double tmpWidth = d->textWidth;
-
- // If the cell is to narrow to paint the whole contents, then pick
- // out a part of the content that we paint. The result of this is
- // dependent on the data type of the content.
- //
- // FIXME: Make this dependent on the height as well.
- //
- if ( testFlag( Flag_CellTooShortX ) ) {
- d->strOutText = textDisplaying( painter );
-
- // Recalculate the text width and the offset.
- textSize( painter );
- offsetAlign( column(), row() );
- }
-
- // Hide zero.
- if ( format()->sheet()->getHideZero()
- && value().isNumber()
- && value().asFloat() == 0 ) {
- d->strOutText = TQString();
- }
-
- // Clear extra cell if column or row is hidden
- //
- // FIXME: I think this should be done before the call to
- // textDisplaying() above.
- //
- if ( colFormat->isHide() || ( cellRect.height() <= 2 ) ) {
- freeAllObscuredCells(); /* TODO: This looks dangerous...must check when I
- have time */
- d->strOutText = "";
- }
-
- double indent = 0.0;
- double offsetCellTooShort = 0.0;
- int a = effAlignX();
-
- // Apply indent if text is align to left not when text is at right or middle.
- if ( a == Format::Left && !isEmpty() ) {
- // FIXME: The following condition should be remade into a call to
- // a new convenience function:
- // if ( hasConditionStyleFeature( Style::SIndent, true )...
- // This should be done throughout the entire file.
- //
- if ( d->hasExtra()
- && d->extra()->conditions
- && d->extra()->conditions->matchedStyle()
- && d->extra()->conditions->matchedStyle()->hasFeature( Style::SIndent, true ) )
- indent = d->extra()->conditions->matchedStyle()->indent();
- else
- indent = format()->getIndent( column(), row() );
- }
-
- // Made an offset, otherwise ### is under red triangle.
- if ( a == Format::Right && !isEmpty() && testFlag( Flag_CellTooShortX ) )
- offsetCellTooShort = format()->sheet()->doc()->unzoomItX( 4 );
-
- TQFontMetrics fm2 = painter.fontMetrics();
- double offsetFont = 0.0;
-
- if ( format()->alignY( column(), row() ) == Format::Bottom
- && format()->textFontUnderline( column(), row() ) )
- offsetFont = format()->sheet()->doc()->unzoomItX( fm2.underlinePos() + 1 );
-
- int tmpAngle;
- bool tmpMultiRow;
- bool tmpVerticalText;
-
- // Check for angled or vertical text.
- if ( d->hasExtra()
- && d->extra()->conditions
- && d->extra()->conditions->matchedStyle() )
- {
- Style *matchedStyle = d->extra()->conditions->matchedStyle();
-
- if ( matchedStyle->hasFeature( Style::SAngle, true ) )
- tmpAngle = d->extra()->conditions->matchedStyle()->rotateAngle();
- else
- tmpAngle = format()->getAngle( cellRef.x(), cellRef.y() );
-
- if ( matchedStyle->hasFeature( Style::SVerticalText, true ) )
- tmpVerticalText = matchedStyle->hasProperty( Style::PVerticalText );
- else
- tmpVerticalText = format()->verticalText( cellRef.x(), cellRef.y() );
-
- if ( matchedStyle->hasFeature( Style::SMultiRow, true ) )
- tmpMultiRow = matchedStyle->hasProperty( Style::PMultiRow );
- else
- tmpMultiRow = format()->multiRow( cellRef.x(), cellRef.y() );
- }
- else {
- tmpAngle = format()->getAngle( cellRef.x(), cellRef.y() );
- tmpVerticalText = format()->verticalText( cellRef.x(), cellRef.y() );
- tmpMultiRow = format()->multiRow( cellRef.x(), cellRef.y() );
- }
-
- // Actually paint the text.
- // There are 4 possible cases:
- // - One line of text , horizontal
- // - Angled text
- // - Multiple rows of text , horizontal
- // - Vertical text
- if ( !tmpMultiRow && !tmpVerticalText && !tmpAngle ) {
- // Case 1: The simple case, one line, no angle.
-
- painter.drawText( doc->zoomItX( indent + cellRect.x() + d->textX - offsetCellTooShort ),
- doc->zoomItY( cellRect.y() + d->textY - offsetFont ), d->strOutText );
- }
- else if ( tmpAngle != 0 ) {
- // Case 2: an angle.
-
- int angle = tmpAngle;
- TQFontMetrics fm = painter.fontMetrics();
-
- painter.rotate( angle );
- double x;
- if ( angle > 0 )
- x = indent + cellRect.x() + d->textX;
- else
- x = indent + cellRect.x() + d->textX
- - doc->unzoomItX((int) (( fm.descent() + fm.ascent() ) * sin( angle * M_PI / 180 )));
- double y;
- if ( angle > 0 )
- y = cellRect.y() + d->textY;
- else
- y = cellRect.y() + d->textY + d->textHeight;
- painter.drawText( doc->zoomItX( x * cos( angle * M_PI / 180 ) +
- y * sin( angle * M_PI / 180 ) ),
- doc->zoomItY( -x * sin( angle * M_PI / 180 ) +
- y * cos( angle * M_PI / 180 ) ),
- d->strOutText );
- painter.rotate( -angle );
- }
- else if ( tmpMultiRow && !tmpVerticalText ) {
- // Case 3: Multiple rows, but horizontal.
-
- TQString t;
- int i;
- int pos = 0;
- double dy = 0.0;
- TQFontMetrics fm = painter.fontMetrics();
- do {
- i = d->strOutText.find( "\n", pos );
- if ( i == -1 )
- t = d->strOutText.mid( pos, d->strOutText.length() - pos );
- else {
- t = d->strOutText.mid( pos, i - pos );
- pos = i + 1;
- }
-
- int align = effAlignX();
- if ( format()->sheet()->getShowFormula()
- && !( format()->sheet()->isProtected()
- && format()->isHideFormula( d->column, d->row ) ) )
- align = Format::Left;
-
- // #### Torben: This looks duplicated for me
- switch ( align ) {
- case Format::Left:
- d->textX = effLeftBorderPen( cellRef.x(), cellRef.y() ).width() + BORDER_SPACE;
- break;
-
- case Format::Right:
- d->textX = cellRect.width() - BORDER_SPACE - doc->unzoomItX( fm.width( t ) )
- - effRightBorderPen( cellRef.x(), cellRef.y() ).width();
- break;
-
- case Format::Center:
- d->textX = ( cellRect.width() - doc->unzoomItX( fm.width( t ) ) ) / 2;
- }
-
- painter.drawText( doc->zoomItX( indent + cellRect.x() + d->textX ),
- doc->zoomItY( cellRect.y() + d->textY + dy ), t );
- dy += doc->unzoomItY( fm.descent() + fm.ascent() );
- } while ( i != -1 );
- }
- else if ( tmpVerticalText && !d->strOutText.isEmpty() ) {
- // Case 4: Vertical text.
-
- TQString t;
- int i = 0;
- int len = 0;
- double dy = 0.0;
- TQFontMetrics fm = painter.fontMetrics();
- do {
- len = d->strOutText.length();
- t = d->strOutText.at( i );
- painter.drawText( doc->zoomItX( indent + cellRect.x() + d->textX ),
- doc->zoomItY( cellRect.y() + d->textY + dy ), t );
- dy += doc->unzoomItY( fm.descent() + fm.ascent() );
- i++;
- } while ( i != len );
- }
-
- // Check for too short cell and set the outText for future reference.
- if ( testFlag( Flag_CellTooShortX ) ) {
- d->strOutText = tmpText;
- d->textHeight = tmpHeight;
- d->textWidth = tmpWidth;
- }
-
- if ( format()->sheet()->getHideZero() && value().isNumber()
- && value().asFloat() == 0 )
- d->strOutText = tmpText;
-
- if ( colFormat->isHide() || ( cellRect.height() <= 2 ) )
- d->strOutText = tmpText;
-}
-
-
-// Paint page borders on the page. Only do this on the screen.
-//
-void Cell::paintPageBorders( TQPainter& painter,
- const KoRect &cellRect,
- const TQPoint &cellRef,
- bool paintBorderRight,
- bool paintBorderBottom )
-{
- // Not screen? Return immediately.
- if ( painter.device()->isExtDev() )
- return;
-
- if ( ! format()->sheet()->isShowPageBorders() )
- return;
-
- SheetPrint* print = format()->sheet()->print();
-
- Sheet::LayoutDirection sheetDir = format()->sheet()->layoutDirection();
-
- Doc* doc = sheet()->doc();
- int zcellRect_left = doc->zoomItX (cellRect.left());
- int zcellRect_right = doc->zoomItX (cellRect.right());
- int zcellRect_top = doc->zoomItY (cellRect.top());
- int zcellRect_bottom = doc->zoomItY (cellRect.bottom());
-
- // Draw page borders
-
- if ( cellRef.x() >= print->printRange().left()
- && cellRef.x() <= print->printRange().right() + 1
- && cellRef.y() >= print->printRange().top()
- && cellRef.y() <= print->printRange().bottom() + 1 )
- {
- if ( print->isOnNewPageX( cellRef.x() )
- && cellRef.y() <= print->printRange().bottom() )
- {
- painter.setPen( sheet()->doc()->pageBorderColor() );
-
- if ( sheetDir == Sheet::RightToLeft )
- painter.drawLine( zcellRect_right, zcellRect_top,
- zcellRect_right, zcellRect_bottom );
- else
- painter.drawLine( zcellRect_left, zcellRect_top,
- zcellRect_left, zcellRect_bottom );
- }
-
- if ( print->isOnNewPageY( cellRef.y() ) &&
- ( cellRef.x() <= print->printRange().right() ) )
- {
- painter.setPen( sheet()->doc()->pageBorderColor() );
- painter.drawLine( zcellRect_left, zcellRect_top,
- zcellRect_right, zcellRect_top );
- }
-
- if ( paintBorderRight ) {
- if ( print->isOnNewPageX( cellRef.x() + 1 )
- && cellRef.y() <= print->printRange().bottom() ) {
- painter.setPen( sheet()->doc()->pageBorderColor() );
-
- if ( sheetDir == Sheet::RightToLeft )
- painter.drawLine( zcellRect_left, zcellRect_top,
- zcellRect_left, zcellRect_bottom );
- else
- painter.drawLine( zcellRect_right, zcellRect_top,
- zcellRect_right, zcellRect_bottom );
- }
- }
-
- if ( paintBorderBottom ) {
- if ( print->isOnNewPageY( cellRef.y() + 1 )
- && cellRef.x() <= print->printRange().right() ) {
- painter.setPen( sheet()->doc()->pageBorderColor() );
- painter.drawLine( zcellRect_left, zcellRect_bottom,
- zcellRect_right, zcellRect_bottom );
- }
- }
- }
-}
-
-
-// Paint the cell borders.
-//
-void Cell::paintCellBorders( TQPainter& painter, const KoRect& rect,
- const KoRect &cellRect,
- const TQPoint &cellRef,
- bool paintRight, bool paintBottom,
- bool paintLeft, bool paintTop,
- TQPen & _rightPen, TQPen & _bottomPen,
- TQPen & _leftPen, TQPen & _topPen )
-{
-
- //Sanity check: If we are not painting any of the borders then the function
- //really shouldn't be called at all.
- if ( (!paintLeft) && (!paintRight) && (!paintTop) && (!paintBottom) )
- return;
-
- Doc * doc = sheet()->doc();
-
- Sheet::LayoutDirection sheetDir = format()->sheet()->layoutDirection();
-
- // compute zoomed rectangles
- // I don't use KoRect, because that ends up producing lots of warnings
- // about double->int conversions in calls to painter.drawLine
- int zrect_left (doc->zoomItX (rect.left()));
- int zrect_right (doc->zoomItX (rect.right()));
- int zrect_top (doc->zoomItY (rect.top()));
- int zrect_bottom (doc->zoomItY (rect.bottom()));
- int zcellRect_left (doc->zoomItX (cellRect.left()));
- int zcellRect_right (doc->zoomItX (cellRect.right()));
- int zcellRect_top (doc->zoomItY (cellRect.top()));
- int zcellRect_bottom (doc->zoomItY (cellRect.bottom()));
-
- /* we might not paint some borders if this cell is merged with another in
- that direction
- bool paintLeft = paintBorderLeft;
- bool paintRight = paintBorderRight;
- bool paintTop = paintBorderTop;
- bool paintBottom = paintBorderBottom;
- */
-
- // paintRight = paintRight && ( extraXCells() == 0 );
- // paintBottom = paintBottom && ( d->extra()->extraYCells() == 0 );
-
- if (d->hasExtra()) {
- TQValueList<Cell*>::const_iterator it = d->extra()->obscuringCells.begin();
- TQValueList<Cell*>::const_iterator end = d->extra()->obscuringCells.end();
- for ( ; it != end; ++it ) {
- Cell* cell = *it;
-
- int xDiff = cellRef.x() - cell->column();
- int yDiff = cellRef.y() - cell->row();
- paintLeft = paintLeft && xDiff == 0;
- paintTop = paintTop && yDiff == 0;
-
- // Paint the border(s) if either this one should or if we have a
- // merged cell with this cell as its border.
- paintRight = paintRight && cell->mergedXCells() == xDiff;
- paintBottom = paintBottom && cell->mergedYCells() == yDiff;
- }
- }
-
- // Must create copies of these since otherwise the zoomIt()
- // operation will be performed on them repeatedly.
- TQPen leftPen( _leftPen );
- TQPen rightPen( _rightPen );
- TQPen topPen( _topPen );
- TQPen bottomPen( _bottomPen );
-
- // Determine the pens that should be used for drawing
- // the borders.
- //
- int left_penWidth = TQMAX( 1, doc->zoomItX( leftPen.width() ) );
- int right_penWidth = TQMAX( 1, doc->zoomItX( rightPen.width() ) );
- int top_penWidth = TQMAX( 1, doc->zoomItY( topPen.width() ) );
- int bottom_penWidth = TQMAX( 1, doc->zoomItY( bottomPen.width() ) );
-
- leftPen.setWidth( left_penWidth );
- rightPen.setWidth( right_penWidth );
- topPen.setWidth( top_penWidth );
- bottomPen.setWidth( bottom_penWidth );
-
- if ( paintLeft && leftPen.style() != TQt::NoPen ) {
- int top = ( TQMAX( 0, -1 + top_penWidth ) ) / 2 +
- ( ( TQMAX( 0, -1 + top_penWidth ) ) % 2 );
- int bottom = ( TQMAX( 0, -1 + bottom_penWidth ) ) / 2 + 1;
-
- painter.setPen( leftPen );
-
- //kdDebug(36001) << " painting left border of cell " << name() << endl;
-
- // If we are on paper printout, we limit the length of the lines.
- // On paper, we always have full cells, on screen not.
- if ( painter.device()->isExtDev() ) {
- // FIXME: There is probably Cut&Paste bugs here as well as below.
- // The TQMIN/TQMAX and left/right pairs don't really make sense.
- //
- // UPDATE: In fact, most of these TQMIN/TQMAX combinations
- // are TOTALLY BOGUS. For one thing, the idea
- // that we always have full cells on paper is wrong
- // since we can have embedded sheets in e.g. kword,
- // and those can be arbitrarily clipped. WE HAVE TO
- // REVISE THIS WHOLE BORDER PAINTING SECTION!
- //
- if ( sheetDir == Sheet::RightToLeft )
- painter.drawLine( TQMIN( zrect_right, zcellRect_right ),
- TQMAX( zrect_top, zcellRect_top - top ),
- TQMIN( zrect_right, zcellRect_right ),
- TQMIN( zrect_bottom, zcellRect_bottom + bottom ) );
- else
- painter.drawLine( TQMAX( zrect_left, zcellRect_left ),
- TQMAX( zrect_top, zcellRect_top - top ),
- TQMAX( zrect_left, zcellRect_left ),
- TQMIN( zrect_bottom, zcellRect_bottom + bottom ) );
- }
- else {
- if ( sheetDir == Sheet::RightToLeft )
- painter.drawLine( zcellRect_right,
- zcellRect_top - top,
- zcellRect_right,
- zcellRect_bottom + bottom );
- else
- painter.drawLine( zcellRect_left,
- zcellRect_top - top,
- zcellRect_left,
- zcellRect_bottom + bottom );
- }
- }
-
- if ( paintRight && rightPen.style() != TQt::NoPen ) {
- int top = ( TQMAX( 0, -1 + top_penWidth ) ) / 2 +
- ( ( TQMAX( 0, -1 + top_penWidth ) ) % 2 );
- int bottom = ( TQMAX( 0, -1 + bottom_penWidth ) ) / 2 + 1;
-
- painter.setPen( rightPen );
-
- //kdDebug(36001) << " painting right border of cell " << name() << endl;
-
- // If we are on paper printout, we limit the length of the lines.
- // On paper, we always have full cells, on screen not.
- if ( painter.device()->isExtDev() ) {
- if ( sheetDir == Sheet::RightToLeft )
- painter.drawLine( TQMAX( zrect_left, zcellRect_left ),
- TQMAX( zrect_top, zcellRect_top - top ),
- TQMAX( zrect_left, zcellRect_left ),
- TQMIN( zrect_bottom, zcellRect_bottom + bottom ) );
- else {
- // FIXME: This is the way all these things should look.
- // Make it so.
- //
- // Only print the right border if it is visible.
- if ( zcellRect_right <= zrect_right + right_penWidth / 2)
- painter.drawLine( zcellRect_right,
- TQMAX( zrect_top, zcellRect_top - top ),
- zcellRect_right,
- TQMIN( zrect_bottom, zcellRect_bottom + bottom ) );
- }
- }
- else {
- if ( sheetDir == Sheet::RightToLeft )
- painter.drawLine( zcellRect_left,
- zcellRect_top - top,
- zcellRect_left,
- zcellRect_bottom + bottom );
- else
- painter.drawLine( zcellRect_right,
- zcellRect_top - top,
- zcellRect_right,
- zcellRect_bottom + bottom );
- }
- }
-
- if ( paintTop && topPen.style() != TQt::NoPen ) {
- painter.setPen( topPen );
-
- //kdDebug(36001) << " painting top border of cell " << name()
- // << " [" << zcellRect_left << "," << zcellRect_right
- // << ": " << zcellRect_right - zcellRect_left << "]" << endl;
-
- // If we are on paper printout, we limit the length of the lines.
- // On paper, we always have full cells, on screen not.
- if ( painter.device()->isExtDev() ) {
- if ( zcellRect_top >= zrect_top + top_penWidth / 2)
- painter.drawLine( TQMAX( zrect_left, zcellRect_left ),
- zcellRect_top,
- TQMIN( zrect_right, zcellRect_right ),
- zcellRect_top );
- }
- else {
- painter.drawLine( zcellRect_left, zcellRect_top,
- zcellRect_right, zcellRect_top );
- }
- }
-
- if ( paintBottom && bottomPen.style() != TQt::NoPen ) {
- painter.setPen( bottomPen );
-
- //kdDebug(36001) << " painting bottom border of cell " << name()
- // << " [" << zcellRect_left << "," << zcellRect_right
- // << ": " << zcellRect_right - zcellRect_left << "]" << endl;
-
- // If we are on paper printout, we limit the length of the lines.
- // On paper, we always have full cells, on screen not.
- if ( painter.device()->isExtDev() ) {
- if ( zcellRect_bottom <= zrect_bottom + bottom_penWidth / 2)
- painter.drawLine( TQMAX( zrect_left, zcellRect_left ),
- zcellRect_bottom,
- TQMIN( zrect_right, zcellRect_right ),
- zcellRect_bottom );
- }
- else {
- painter.drawLine( zcellRect_left, zcellRect_bottom,
- zcellRect_right, zcellRect_bottom );
- }
- }
-
- // FIXME: Look very closely at when the following code is really needed.
- // I can't really see any case, but I might be wrong.
- // Since the code below is buggy, and incredibly complex,
- // I am currently disabling it. If somebody wants to enable
- // it again, then please also solve bug 68977: "Embedded KSpread
- // document printing problem" at the same time.
- return;
-
-#if 0
- // Look at the cells on our corners. It may happen that we
- // just erased parts of their borders corner, so we might need
- // to repaint these corners.
- //
- TQPen vert_pen, horz_pen;
- int vert_penWidth, horz_penWidth;
-
- // Some useful referenses.
- Cell *cell_north = format()->sheet()->cellAt( cellRef.x(),
- cellRef.y() - 1 );
- Cell *cell_northwest = format()->sheet()->cellAt( cellRef.x() - 1,
- cellRef.y() - 1 );
- Cell *cell_west = format()->sheet()->cellAt( cellRef.x() - 1,
- cellRef.y() );
- Cell *cell_northeast = format()->sheet()->cellAt( cellRef.x() + 1,
- cellRef.y() - 1 );
- Cell *cell_east = format()->sheet()->cellAt( cellRef.x() + 1,
- cellRef.y() );
- Cell *cell_south = format()->sheet()->cellAt( cellRef.x(),
- cellRef.y() + 1 );
- Cell *cell_southwest = format()->sheet()->cellAt( cellRef.x() - 1,
- cellRef.y() + 1 );
- Cell *cell_southeast = format()->sheet()->cellAt( cellRef.x() + 1,
- cellRef.y() + 1 );
-
- // Fix the borders which meet at the top left corner
- if ( cell_north->effLeftBorderValue( cellRef.x(), cellRef.y() - 1 )
- >= cell_northwest->effRightBorderValue( cellRef.x() - 1, cellRef.y() - 1 ) )
- vert_pen = cell_north->effLeftBorderPen( cellRef.x(), cellRef.y() - 1 );
- else
- vert_pen = cell_northwest->effRightBorderPen( cellRef.x() - 1,
- cellRef.y() - 1 );
-
- vert_penWidth = TQMAX( 1, doc->zoomItX( vert_pen.width() ) );
- vert_pen.setWidth( vert_penWidth );
-
- if ( vert_pen.style() != TQt::NoPen ) {
- if ( cell_west->effTopBorderValue( cellRef.x() - 1, cellRef.y() )
- >= cell_northwest->effBottomBorderValue( cellRef.x() - 1, cellRef.y() - 1 ) )
- horz_pen = cell_west->effTopBorderPen( cellRef.x() - 1, cellRef.y() );
- else
- horz_pen = cell_northwest->effBottomBorderPen( cellRef.x() - 1,
- cellRef.y() - 1 );
-
- horz_penWidth = TQMAX( 1, doc->zoomItY( horz_pen.width() ) );
- int bottom = ( TQMAX( 0, -1 + horz_penWidth ) ) / 2 + 1;
-
- painter.setPen( vert_pen );
- // If we are on paper printout, we limit the length of the lines.
- // On paper, we always have full cells, on screen not.
- if ( painter.device()->isExtDev() ) {
- if ( sheetDir == Sheet::RightToLeft )
- painter.drawLine( TQMAX( zrect_left, zcellRect_right ),
- TQMAX( zrect_top, zcellRect_top ),
- TQMIN( zrect_right, zcellRect_right ),
- TQMIN( zrect_bottom, zcellRect_top + bottom ) );
- else
- painter.drawLine( TQMAX( zrect_left, zcellRect_left ),
- TQMAX( zrect_top, zcellRect_top ),
- TQMIN( zrect_right, zcellRect_left ),
- TQMIN( zrect_bottom, zcellRect_top + bottom ) );
- }
- else {
- if ( sheetDir == Sheet::RightToLeft )
- painter.drawLine( zcellRect_right, zcellRect_top,
- zcellRect_right, zcellRect_top + bottom );
- else
- painter.drawLine( zcellRect_left, zcellRect_top,
- zcellRect_left, zcellRect_top + bottom );
- }
- }
-
- // Fix the borders which meet at the top right corner
- if ( cell_north->effRightBorderValue( cellRef.x(), cellRef.y() - 1 )
- >= cell_northeast->effLeftBorderValue( cellRef.x() + 1,
- cellRef.y() - 1 ) )
- vert_pen = cell_north->effRightBorderPen( cellRef.x(), cellRef.y() - 1 );
- else
- vert_pen = cell_northeast->effLeftBorderPen( cellRef.x() + 1,
- cellRef.y() - 1 );
-
- // vert_pen = effRightBorderPen( cellRef.x(), cellRef.y() - 1 );
- vert_penWidth = TQMAX( 1, doc->zoomItX( vert_pen.width() ) );
- vert_pen.setWidth( vert_penWidth );
- if ( ( vert_pen.style() != TQt::NoPen ) && ( cellRef.x() < KS_colMax ) ) {
- if ( cell_east->effTopBorderValue( cellRef.x() + 1, cellRef.y() )
- >= cell_northeast->effBottomBorderValue( cellRef.x() + 1,
- cellRef.y() - 1 ) )
- horz_pen = cell_east->effTopBorderPen( cellRef.x() + 1, cellRef.y() );
- else
- horz_pen = cell_northeast->effBottomBorderPen( cellRef.x() + 1,
- cellRef.y() - 1 );
-
- // horz_pen = effTopBorderPen( cellRef.x() + 1, cellRef.y() );
- horz_penWidth = TQMAX( 1, doc->zoomItY( horz_pen.width() ) );
- int bottom = ( TQMAX( 0, -1 + horz_penWidth ) ) / 2 + 1;
-
- painter.setPen( vert_pen );
- //If we are on paper printout, we limit the length of the lines
- //On paper, we always have full cells, on screen not
- if ( painter.device()->isExtDev() ) {
- if ( sheetDir == Sheet::RightToLeft )
- painter.drawLine( TQMAX( zrect_left, zcellRect_left ),
- TQMAX( zrect_top, zcellRect_top ),
- TQMIN( zrect_right, zcellRect_left ),
- TQMIN( zrect_bottom, zcellRect_top + bottom ) );
- else
- painter.drawLine( TQMAX( zrect_left, zcellRect_right ),
- TQMAX( zrect_top, zcellRect_top ),
- TQMIN( zrect_right, zcellRect_right ),
- TQMIN( zrect_bottom, zcellRect_top + bottom ) );
- }
- else {
- if ( sheetDir == Sheet::RightToLeft )
- painter.drawLine( zcellRect_left, zcellRect_top,
- zcellRect_left, zcellRect_top + bottom );
- else
- painter.drawLine( zcellRect_right, zcellRect_top,
- zcellRect_right, zcellRect_top + bottom );
- }
- }
-
- // Bottom
- if ( cellRef.y() < KS_rowMax ) {
- // Fix the borders which meet at the bottom left corner
- if ( cell_south->effLeftBorderValue( cellRef.x(), cellRef.y() + 1 )
- >= cell_southwest->effRightBorderValue( cellRef.x() - 1,
- cellRef.y() + 1 ) )
- vert_pen = cell_south->effLeftBorderPen( cellRef.x(), cellRef.y() + 1 );
- else
- vert_pen = cell_southwest->effRightBorderPen( cellRef.x() - 1,
- cellRef.y() + 1 );
-
- // vert_pen = effLeftBorderPen( cellRef.x(), cellRef.y() + 1 );
- vert_penWidth = TQMAX( 1, doc->zoomItY( vert_pen.width() ) );
- vert_pen.setWidth( vert_penWidth );
- if ( vert_pen.style() != TQt::NoPen ) {
- if ( cell_west->effBottomBorderValue( cellRef.x() - 1, cellRef.y() )
- >= cell_southwest->effTopBorderValue( cellRef.x() - 1,
- cellRef.y() + 1 ) )
- horz_pen = cell_west->effBottomBorderPen( cellRef.x() - 1,
- cellRef.y() );
- else
- horz_pen = cell_southwest->effTopBorderPen( cellRef.x() - 1,
- cellRef.y() + 1 );
-
- // horz_pen = effBottomBorderPen( cellRef.x() - 1, cellRef.y() );
- horz_penWidth = TQMAX( 1, doc->zoomItX( horz_pen.width() ) );
- int bottom = ( TQMAX( 0, -1 + horz_penWidth ) ) / 2;
-
- painter.setPen( vert_pen );
- // If we are on paper printout, we limit the length of the lines.
- // On paper, we always have full cells, on screen not.
- if ( painter.device()->isExtDev() ) {
- if ( sheetDir == Sheet::RightToLeft )
- painter.drawLine( TQMAX( zrect_left, zcellRect_right ),
- TQMAX( zrect_top, zcellRect_bottom - bottom ),
- TQMIN( zrect_right, zcellRect_right ),
- TQMIN( zrect_bottom, zcellRect_bottom ) );
- else
- painter.drawLine( TQMAX( zrect_left, zcellRect_left ),
- TQMAX( zrect_top, zcellRect_bottom - bottom ),
- TQMIN( zrect_right, zcellRect_left ),
- TQMIN( zrect_bottom, zcellRect_bottom ) );
- }
- else {
- if ( sheetDir == Sheet::RightToLeft )
- painter.drawLine( zcellRect_right, zcellRect_bottom - bottom,
- zcellRect_right, zcellRect_bottom );
- else
- painter.drawLine( zcellRect_left, zcellRect_bottom - bottom,
- zcellRect_left, zcellRect_bottom );
- }
- }
-
- // Fix the borders which meet at the bottom right corner
- if ( cell_south->effRightBorderValue( cellRef.x(), cellRef.y() + 1 )
- >= cell_southeast->effLeftBorderValue( cellRef.x() + 1,
- cellRef.y() + 1 ) )
- vert_pen = cell_south->effRightBorderPen( cellRef.x(), cellRef.y() + 1 );
- else
- vert_pen = cell_southeast->effLeftBorderPen( cellRef.x() + 1,
- cellRef.y() + 1 );
-
- // vert_pen = effRightBorderPen( cellRef.x(), cellRef.y() + 1 );
- vert_penWidth = TQMAX( 1, doc->zoomItY( vert_pen.width() ) );
- vert_pen.setWidth( vert_penWidth );
- if ( ( vert_pen.style() != TQt::NoPen ) && ( cellRef.x() < KS_colMax ) ) {
- if ( cell_east ->effBottomBorderValue( cellRef.x() + 1, cellRef.y() )
- >= cell_southeast->effTopBorderValue( cellRef.x() + 1,
- cellRef.y() + 1 ) )
-
- horz_pen = format()->sheet()->cellAt( cellRef.x() + 1, cellRef.y() )
- ->effBottomBorderPen( cellRef.x() + 1, cellRef.y() );
- else
- horz_pen = format()->sheet()->cellAt( cellRef.x() + 1, cellRef.y() + 1 )
- ->effTopBorderPen( cellRef.x() + 1, cellRef.y() + 1 );
-
- // horz_pen = effBottomBorderPen( cellRef.x() + 1, cellRef.y() );
- horz_penWidth = TQMAX( 1, doc->zoomItX( horz_pen.width() ) );
- int bottom = ( TQMAX( 0, -1 + horz_penWidth ) ) / 2;
-
- painter.setPen( vert_pen );
- // If we are on paper printout, we limit the length of the lines.
- // On paper, we always have full cells, on screen not.
- if ( painter.device()->isExtDev() ) {
- if ( sheetDir == Sheet::RightToLeft )
- painter.drawLine( TQMAX( zrect_left, zcellRect_left ),
- TQMAX( zrect_top, zcellRect_bottom - bottom ),
- TQMIN( zrect_right, zcellRect_left ),
- TQMIN( zrect_bottom, zcellRect_bottom ) );
- else
- painter.drawLine( TQMAX( zrect_left, zcellRect_right ),
- TQMAX( zrect_top, zcellRect_bottom - bottom ),
- TQMIN( zrect_right, zcellRect_right ),
- TQMIN( zrect_bottom, zcellRect_bottom ) );
- }
- else {
- if ( sheetDir == Sheet::RightToLeft )
- painter.drawLine( zcellRect_left, zcellRect_bottom - bottom,
- zcellRect_left, zcellRect_bottom );
- else
- painter.drawLine( zcellRect_right, zcellRect_bottom - bottom,
- zcellRect_right, zcellRect_bottom );
- }
- }
- }
- #endif
-}
-
-
-// Paint diagonal lines through the cell.
-//
-void Cell::paintCellDiagonalLines( TQPainter& painter,
- const KoRect &cellRect,
- const TQPoint &cellRef )
-{
- if ( isPartOfMerged() )
- return;
-
- Doc* doc = sheet()->doc();
-
- if ( effFallDiagonalPen( cellRef.x(), cellRef.y() ).style() != TQt::NoPen ) {
- painter.setPen( effFallDiagonalPen( cellRef.x(), cellRef.y() ) );
- painter.drawLine( doc->zoomItX( cellRect.x() ),
- doc->zoomItY( cellRect.y() ),
- doc->zoomItX( cellRect.right() ),
- doc->zoomItY( cellRect.bottom() ) );
- }
-
- if ( effGoUpDiagonalPen( cellRef.x(), cellRef.y() ).style() != TQt::NoPen ) {
- painter.setPen( effGoUpDiagonalPen( cellRef.x(), cellRef.y() ) );
- painter.drawLine( doc->zoomItX( cellRect.x() ),
- doc->zoomItY( cellRect.bottom() ),
- doc->zoomItX( cellRect.right() ),
- doc->zoomItY( cellRect.y() ) );
- }
-}
-
-
-// End of Painting
-// ================================================================
-
-
-int Cell::defineAlignX()
-{
- int a = format()->align( column(), row() );
- if ( a == Format::Undefined )
- {
- //numbers should be right-aligned by default, as well as BiDi text
- if ((formatType() == Text_format) || value().isString())
- a = (d->strOutText.isRightToLeft()) ?
- Format::Right : Format::Left;
- else {
- Value val = value();
- while (val.isArray()) val = val.element (0, 0);
- if (val.isBoolean() || val.isNumber())
- a = Format::Right;
- else
- a = Format::Left;
- }
- }
- return a;
-}
-
-int Cell::effAlignX()
-{
- if ( d->hasExtra() && d->extra()->conditions
- && d->extra()->conditions->matchedStyle()
- && d->extra()->conditions->matchedStyle()->hasFeature( Style::SAlignX, true ) )
- return d->extra()->conditions->matchedStyle()->alignX();
-
- return defineAlignX();
-}
-
-// Cut strOutText, so that it only holds the part that can be displayed.
-//
-// Used in paintText().
-//
-
-TQString Cell::textDisplaying( TQPainter &_painter )
-{
- TQFontMetrics fm = _painter.fontMetrics();
- int a = format()->align( column(), row() );
-
- bool isNumeric = value().isNumber();
-
- if ( !format()->verticalText( column(),row() ) ) {
- // Non-vertical text: the ordinary case.
-
- // Not enough space but align to left
- double len = 0.0;
- int extraXCells = d->hasExtra() ? d->extra()->extraXCells : 0;
-
- for ( int i = column(); i <= column() + extraXCells; i++ ) {
- ColumnFormat *cl2 = format()->sheet()->columnFormat( i );
- len += cl2->dblWidth() - 1.0; //-1.0 because the pixel in between 2 cells is shared between both cells
- }
-
- TQString tmp;
- double tmpIndent = 0.0;
- if ( !isEmpty() )
- tmpIndent = format()->getIndent( column(), row() );
-
- // Start out with the whole text, cut one character at a time, and
- // when the text finally fits, return it.
- for ( int i = d->strOutText.length(); i != 0; i-- )
- {
- //Note that numbers are always treated as left-aligned since if we have to cut digits off, they should
- //always be the least significant ones at the end of the string
- if ( a == Format::Left || a == Format::Undefined || isNumeric)
- tmp = d->strOutText.left(i);
- else if ( a == Format::Right)
- tmp = d->strOutText.right(i);
- else
- tmp = d->strOutText.mid( ( d->strOutText.length() - i ) / 2, i);
-
- if (isNumeric)
- {
- //For numeric values, we can cut off digits after the decimal point to make it fit,
- //but not the integer part of the number.
- //If this number still contains a fraction part then we don't need to do anything, if we have run
- //out of space to fit even the integer part of the number then display #########
- //TODO Perhaps try to display integer part in standard form if there is not enough room for it?
-
- if (!tmp.contains('.'))
- d->strOutText=TQString().fill('#',20);
- }
-
- // 4 equal length of red triangle +1 point.
- if ( format()->sheet()->doc()->unzoomItX( fm.width( tmp ) ) + tmpIndent
- < len - 4.0 - 1.0 )
- {
- if ( format()->getAngle( column(), row() ) != 0 )
- {
- TQString tmp2;
- RowFormat *rl = format()->sheet()->rowFormat( row() );
- if ( d->textHeight > rl->dblHeight() )
- {
- for ( int j = d->strOutText.length(); j != 0; j-- )
- {
- tmp2 = d->strOutText.left( j );
- if ( format()->sheet()->doc()->unzoomItY( fm.width( tmp2 ) ) < rl->dblHeight() - 1.0 )
- {
- return d->strOutText.left( TQMIN( tmp.length(), tmp2.length() ) );
- }
- }
- }
- else
- return tmp;
-
- }
- else
- return tmp;
- }
- }
- return TQString( "" );
- }
- else if ( format()->verticalText( column(), row() ) ) {
- // Vertical text.
-
- RowFormat *rl = format()->sheet()->rowFormat( row() );
- double tmpIndent = 0.0;
-
- // Not enough space but align to left.
- double len = 0.0;
- int extraXCells = d->hasExtra() ? d->extra()->extraXCells : 0;
-
- for ( int i = column(); i <= column() + extraXCells; i++ ) {
- ColumnFormat *cl2 = format()->sheet()->columnFormat( i );
-
- // -1.0 because the pixel in between 2 cells is shared between both cells
- len += cl2->dblWidth() - 1.0;
- }
-
- if ( !isEmpty() )
- tmpIndent = format()->getIndent( column(), row() );
-
- if ( ( d->textWidth + tmpIndent > len ) || d->textWidth == 0.0 )
- return TQString( "" );
-
- for ( int i = d->strOutText.length(); i != 0; i-- ) {
- if ( format()->sheet()->doc()->unzoomItY( fm.ascent() + fm.descent() ) * i
- < rl->dblHeight() - 1.0 )
- return d->strOutText.left( i );
- }
-
- return TQString( "" );
- }
-
- ColumnFormat *cl = format()->sheet()->columnFormat( column() );
- double w = cl->dblWidth();
-
- if ( d->hasExtra() && (d->extra()->extraWidth != 0.0) )
- w = d->extra()->extraWidth;
-
- TQString tmp;
- for ( int i = d->strOutText.length(); i != 0; i-- ) {
- tmp = d->strOutText.left( i );
-
- // 4 equals length of red triangle +1 pixel
- if ( format()->sheet()->doc()->unzoomItX( fm.width( tmp ) ) < w - 4.0 - 1.0 )
- return tmp;
- }
-
- return TQString();
-}
-
-
-double Cell::dblWidth( int _col, const Canvas *_canvas ) const
-{
- if ( _col < 0 )
- _col = d->column;
-
- if ( _canvas )
- {
- if ( testFlag(Flag_Merged) )
- return d->extra()->extraWidth;
-
- const ColumnFormat *cl = format()->sheet()->columnFormat( _col );
- return cl->dblWidth( _canvas );
- }
-
- if ( testFlag(Flag_Merged) )
- return d->extra()->extraWidth;
-
- const ColumnFormat *cl = format()->sheet()->columnFormat( _col );
- return cl->dblWidth();
-}
-
-int Cell::width( int _col, const Canvas *_canvas ) const
-{
- return int( dblWidth( _col, _canvas ) );
-}
-
-double Cell::dblHeight( int _row, const Canvas *_canvas ) const
-{
- if ( _row < 0 )
- _row = d->row;
-
- if ( _canvas )
- {
- if ( testFlag(Flag_Merged) )
- return d->extra()->extraHeight;
-
- const RowFormat *rl = format()->sheet()->rowFormat( _row );
- return rl->dblHeight( _canvas );
- }
-
- if ( testFlag(Flag_Merged) )
- return d->extra()->extraHeight;
-
- const RowFormat *rl = format()->sheet()->rowFormat( _row );
- return rl->dblHeight();
-}
-
-int Cell::height( int _row, const Canvas *_canvas ) const
-{
- return int( dblHeight( _row, _canvas ) );
-}
-
-///////////////////////////////////////////
-//
-// Misc Properties.
-// Reimplementation of Format methods.
-//
-///////////////////////////////////////////
-
-const TQBrush& Cell::backGroundBrush( int _col, int _row ) const
-{
- if ( d->hasExtra() && (!d->extra()->obscuringCells.isEmpty()) )
- {
- const Cell* cell = d->extra()->obscuringCells.first();
- return cell->backGroundBrush( cell->column(), cell->row() );
- }
-
- return format()->backGroundBrush( _col, _row );
-}
-
-const TQColor& Cell::bgColor( int _col, int _row ) const
-{
- if ( d->hasExtra() && (!d->extra()->obscuringCells.isEmpty()) )
- {
- const Cell* cell = d->extra()->obscuringCells.first();
- return cell->bgColor( cell->column(), cell->row() );
- }
-
- return format()->bgColor( _col, _row );
-}
-
-///////////////////////////////////////////
-//
-// Borders.
-// Reimplementation of Format methods.
-//
-///////////////////////////////////////////
-
-void Cell::setLeftBorderPen( const TQPen& p )
-{
- if ( column() == 1 )
- {
- Cell* cell = format()->sheet()->cellAt( column() - 1, row() );
- if ( cell && cell->format()->hasProperty( Format::PRightBorder )
- && format()->sheet()->cellAt( column(), row() ) == this )
- cell->format()->clearProperty( Format::PRightBorder );
- }
-
- format()->setLeftBorderPen( p );
-}
-
-void Cell::setTopBorderPen( const TQPen& p )
-{
- if ( row() == 1 )
- {
- Cell* cell = format()->sheet()->cellAt( column(), row() - 1 );
- if ( cell && cell->format()->hasProperty( Format::PBottomBorder )
- && format()->sheet()->cellAt( column(), row() ) == this )
- cell->format()->clearProperty( Format::PBottomBorder );
- }
- format()->setTopBorderPen( p );
-}
-
-void Cell::setRightBorderPen( const TQPen& p )
-{
- Cell* cell = 0L;
- if ( column() < KS_colMax )
- cell = format()->sheet()->cellAt( column() + 1, row() );
-
- if ( cell && cell->format()->hasProperty( Format::PLeftBorder )
- && format()->sheet()->cellAt( column(), row() ) == this )
- cell->format()->clearProperty( Format::PLeftBorder );
-
- format()->setRightBorderPen( p );
-}
-
-void Cell::setBottomBorderPen( const TQPen& p )
-{
- Cell* cell = 0L;
- if ( row() < KS_rowMax )
- cell = format()->sheet()->cellAt( column(), row() + 1 );
-
- if ( cell && cell->format()->hasProperty( Format::PTopBorder )
- && format()->sheet()->cellAt( column(), row() ) == this )
- cell->format()->clearProperty( Format::PTopBorder );
-
- format()->setBottomBorderPen( p );
-}
-
-const TQPen& Cell::rightBorderPen( int _col, int _row ) const
-{
- if ( !format()->hasProperty( Format::PRightBorder ) && ( _col < KS_colMax ) )
- {
- Cell * cell = format()->sheet()->cellAt( _col + 1, _row );
- if ( cell && cell->format()->hasProperty( Format::PLeftBorder ) )
- return cell->leftBorderPen( _col + 1, _row );
- }
-
- return format()->rightBorderPen( _col, _row );
-}
-
-const TQPen& Cell::leftBorderPen( int _col, int _row ) const
-{
- if ( !format()->hasProperty( Format::PLeftBorder ) )
- {
- const Cell * cell = format()->sheet()->cellAt( _col - 1, _row );
- if ( cell && cell->format()->hasProperty( Format::PRightBorder ) )
- return cell->rightBorderPen( _col - 1, _row );
- }
-
- return format()->leftBorderPen( _col, _row );
-}
-
-const TQPen& Cell::bottomBorderPen( int _col, int _row ) const
-{
- if ( !format()->hasProperty( Format::PBottomBorder ) && ( _row < KS_rowMax ) )
- {
- const Cell * cell = format()->sheet()->cellAt( _col, _row + 1 );
- if ( cell && cell->format()->hasProperty( Format::PTopBorder ) )
- return cell->topBorderPen( _col, _row + 1 );
- }
-
- return format()->bottomBorderPen( _col, _row );
-}
-
-const TQPen& Cell::topBorderPen( int _col, int _row ) const
-{
- if ( !format()->hasProperty( Format::PTopBorder ) )
- {
- const Cell * cell = format()->sheet()->cellAt( _col, _row - 1 );
- if ( cell->format()->hasProperty( Format::PBottomBorder ) )
- return cell->bottomBorderPen( _col, _row - 1 );
- }
-
- return format()->topBorderPen( _col, _row );
-}
-
-const TQColor & Cell::effTextColor( int col, int row ) const
-{
- if ( d->hasExtra() && d->extra()->conditions
- && d->extra()->conditions->matchedStyle()
- && d->extra()->conditions->matchedStyle()->hasFeature( Style::STextPen, true ) )
- return d->extra()->conditions->matchedStyle()->pen().color();
-
- return format()->textColor( col, row );
-}
-
-const TQPen& Cell::effLeftBorderPen( int col, int row ) const
-{
- if ( isPartOfMerged() )
- {
- Cell * cell = d->extra()->obscuringCells.first();
- return cell->effLeftBorderPen( cell->column(), cell->row() );
- }
-
- if ( d->hasExtra() && d->extra()->conditions
- && d->extra()->conditions->matchedStyle()
- && d->extra()->conditions->matchedStyle()->hasFeature( Style::SLeftBorder, true ) )
- return d->extra()->conditions->matchedStyle()->leftBorderPen();
-
- return leftBorderPen( col, row );
-}
-
-const TQPen& Cell::effTopBorderPen( int col, int row ) const
-{
- if ( isPartOfMerged() )
- {
- Cell * cell = d->extra()->obscuringCells.first();
- return cell->effTopBorderPen( cell->column(), cell->row() );
- }
-
- if ( d->hasExtra() && d->extra()->conditions
- && d->extra()->conditions->matchedStyle()
- && d->extra()->conditions->matchedStyle()->hasFeature( Style::STopBorder, true ) )
- return d->extra()->conditions->matchedStyle()->topBorderPen();
-
- return topBorderPen( col, row );
-}
-
-const TQPen& Cell::effRightBorderPen( int col, int row ) const
-{
- if ( isPartOfMerged() )
- {
- Cell * cell = d->extra()->obscuringCells.first();
- return cell->effRightBorderPen( cell->column(), cell->row() );
- }
-
- if ( d->hasExtra() && d->extra()->conditions
- && d->extra()->conditions->matchedStyle()
- && d->extra()->conditions->matchedStyle()->hasFeature( Style::SRightBorder, true ) )
- return d->extra()->conditions->matchedStyle()->rightBorderPen();
-
- return rightBorderPen( col, row );
-}
-
-const TQPen& Cell::effBottomBorderPen( int col, int row ) const
-{
- if ( isPartOfMerged() )
- {
- Cell * cell = d->extra()->obscuringCells.first();
- return cell->effBottomBorderPen( cell->column(), cell->row() );
- }
-
- if ( d->hasExtra() && d->extra()->conditions
- && d->extra()->conditions->matchedStyle()
- && d->extra()->conditions->matchedStyle()->hasFeature( Style::SBottomBorder, true ) )
- return d->extra()->conditions->matchedStyle()->bottomBorderPen();
-
- return bottomBorderPen( col, row );
-}
-
-const TQPen & Cell::effGoUpDiagonalPen( int col, int row ) const
-{
- if ( d->hasExtra() && d->extra()->conditions
- && d->extra()->conditions->matchedStyle()
- && d->extra()->conditions->matchedStyle()->hasFeature( Style::SGoUpDiagonal, true ) )
- return d->extra()->conditions->matchedStyle()->goUpDiagonalPen();
-
- return format()->goUpDiagonalPen( col, row );
-}
-
-const TQPen & Cell::effFallDiagonalPen( int col, int row ) const
-{
- if ( d->hasExtra() && d->extra()->conditions
- && d->extra()->conditions->matchedStyle()
- && d->extra()->conditions->matchedStyle()->hasFeature( Style::SFallDiagonal, true ) )
- return d->extra()->conditions->matchedStyle()->fallDiagonalPen();
-
- return format()->fallDiagonalPen( col, row );
-}
-
-uint Cell::effBottomBorderValue( int col, int row ) const
-{
- if ( isPartOfMerged() )
- {
- Cell * cell = d->extra()->obscuringCells.first();
- return cell->effBottomBorderValue( cell->column(), cell->row() );
- }
-
- if ( d->hasExtra() && d->extra()->conditions
- && d->extra()->conditions->matchedStyle() )
- return d->extra()->conditions->matchedStyle()->bottomPenValue();
-
- return format()->bottomBorderValue( col, row );
-}
-
-uint Cell::effRightBorderValue( int col, int row ) const
-{
- if ( isPartOfMerged() )
- {
- Cell * cell = d->extra()->obscuringCells.first();
- return cell->effRightBorderValue( cell->column(), cell->row() );
- }
-
- if ( d->hasExtra() && d->extra()->conditions
- && d->extra()->conditions->matchedStyle() )
- return d->extra()->conditions->matchedStyle()->rightPenValue();
-
- return format()->rightBorderValue( col, row );
-}
-
-uint Cell::effLeftBorderValue( int col, int row ) const
-{
- if ( isPartOfMerged() )
- {
- Cell * cell = d->extra()->obscuringCells.first();
- return cell->effLeftBorderValue( cell->column(), cell->row() );
- }
-
- if ( d->hasExtra() && d->extra()->conditions
- && d->extra()->conditions->matchedStyle() )
- return d->extra()->conditions->matchedStyle()->leftPenValue();
-
- return format()->leftBorderValue( col, row );
-}
-
-uint Cell::effTopBorderValue( int col, int row ) const
-{
- if ( isPartOfMerged() )
- {
- Cell * cell = d->extra()->obscuringCells.first();
- return cell->effTopBorderValue( cell->column(), cell->row() );
- }
-
- if ( d->hasExtra() && d->extra()->conditions
- && d->extra()->conditions->matchedStyle() )
- return d->extra()->conditions->matchedStyle()->topPenValue();
-
- return format()->topBorderValue( col, row );
-}
-
-///////////////////////////////////////////
-//
-// Precision
-//
-///////////////////////////////////////////
-
-void Cell::incPrecision()
-{
- //TODO: This is ugly. Why not simply regenerate the text to display? Tomas
-
- if ( !value().isNumber() )
- return;
- int tmpPreci = format()->precision( column(), row() );
-
- if ( tmpPreci == -1 )
- {
- int pos = d->strOutText.find(decimal_point);
- if ( pos == -1 )
- pos = d->strOutText.find('.');
- if ( pos == -1 )
- format()->setPrecision(1);
- else
- {
- int start = 0;
- if ( d->strOutText.find('%') != -1 )
- start = 2;
- else if ( d->strOutText.find(locale()->currencySymbol()) == ((int)(d->strOutText.length()-locale()->currencySymbol().length())) )
- start = locale()->currencySymbol().length() + 1;
- else if ( (start=d->strOutText.find('E')) != -1 )
- start = d->strOutText.length() - start;
-
- //kdDebug(36001) << "start=" << start << " pos=" << pos << " length=" << d->strOutText.length() << endl;
- format()->setPrecision( TQMAX( 0, (int)d->strOutText.length() - start - pos ) );
- }
- }
- else if ( tmpPreci < 10 )
- {
- format()->setPrecision( ++tmpPreci );
- }
- setFlag(Flag_LayoutDirty);
-}
-
-void Cell::decPrecision()
-{
- //TODO: This is ugly. Why not simply regenerate the text to display? Tomas
-
- if ( !value().isNumber() )
- return;
- int preciTmp = format()->precision( column(), row() );
-// kdDebug(36001) << "decPrecision: tmpPreci = " << tmpPreci << endl;
- if ( format()->precision(column(),row()) == -1 )
- {
- int pos = d->strOutText.find( decimal_point );
- int start = 0;
- if ( d->strOutText.find('%') != -1 )
- start = 2;
- else if ( d->strOutText.find(locale()->currencySymbol()) == ((int)(d->strOutText.length()-locale()->currencySymbol().length())) )
- start = locale()->currencySymbol().length() + 1;
- else if ( (start = d->strOutText.find('E')) != -1 )
- start = d->strOutText.length() - start;
- else
- start = 0;
-
- if ( pos == -1 )
- return;
-
- format()->setPrecision(d->strOutText.length() - pos - 2 - start);
- // if ( preciTmp < 0 )
- // format()->setPrecision( preciTmp );
- }
- else if ( preciTmp > 0 )
- {
- format()->setPrecision( --preciTmp );
- }
- setFlag( Flag_LayoutDirty );
-}
-
-//set numerical value
-//used in Sheet::setSeries (nowhere else yet)
-void Cell::setNumber( double number )
-{
- setValue( Value( number ) );
-
- d->strText.setNum( number );
- setDisplayText(d->strText);
- checkNumberFormat();
-}
-
-void Cell::setCellText( const TQString& _text, bool asText )
-{
- // TQString ctext = _text;
-
-// (Tomas) is this trim necessary for anything ?
-// if( ctext.length() > 5000 )
-// ctext = ctext.left( 5000 );
-
- // empty string ?
- if (_text.length() == 0) {
- d->strOutText = d->strText = "";
- setValue (Value::empty());
- return;
- }
-
- // as text ?
- if (asText) {
- d->strOutText = _text;
- d->strText = _text;
- setValue (Value (_text));
-
- return;
- }
-
- TQString oldText = d->strText;
- setDisplayText( _text );
- if(!format()->sheet()->isLoading() && !testValidity() )
- {
- //reapply old value if action == stop
- setDisplayText( oldText );
- }
-}
-
-void Cell::setDisplayText( const TQString& _text )
-{
- bool isLoading = format()->sheet()->isLoading();
-
- if (!isLoading)
- format()->sheet()->doc()->emitBeginOperation( false );
-
- d->strText = _text;
-
- /**
- * A real formula "=A1+A2*3" was entered.
- */
- if ( !d->strText.isEmpty() && d->strText[0] == '=' )
- {
- setFlag(Flag_LayoutDirty);
- setFlag(Flag_TextFormatDirty);
-
- if ( !makeFormula() )
- kdError(36001) << "ERROR: Syntax ERROR" << endl;
- setCalcDirtyFlag ();
- }
-
- /**
- * Some numeric value or a string.
- */
- else
- {
- // Find out what data type it is
- checkTextInput();
-
- setFlag(Flag_LayoutDirty);
- setFlag(Flag_TextFormatDirty);
- }
-
- if ( !isLoading )
- format()->sheet()->doc()->emitEndOperation( TQRect( d->column, d->row, 1, 1 ) );
-}
-
-void Cell::setLink( const TQString& link )
-{
- d->extra()->link = link;
-
- if( !link.isEmpty() && d->strText.isEmpty() )
- setCellText( link );
-}
-
-TQString Cell::link() const
-{
- return d->hasExtra() ? d->extra()->link : TQString();
-}
-
-void Cell::update()
-{
- /* those obscuring us need to redo their layout cause they can't obscure us
- now that we've got text.
- This includes cells obscuring cells that we are obscuring
- */
- for (int x = d->column; x <= d->column + extraXCells(); x++)
- {
- for (int y = d->row; y <= d->row + extraYCells(); y++)
- {
- Cell* cell = format()->sheet()->cellAt(x,y);
- cell->setLayoutDirtyFlag();
- }
- }
-
- setCalcDirtyFlag();
-
- /* TODO - is this a good place for this? */
- updateChart(true);
-}
-
-bool Cell::testValidity() const
-{
- bool valid = false;
- if( d->hasExtra() && d->extra()->validity && d->extra()->validity->m_restriction != Restriction::None )
- {
- //fixme
- if ( d->extra()->validity->allowEmptyCell && d->strText.isEmpty() )
- return true;
-
- if( value().isNumber() &&
- (d->extra()->validity->m_restriction == Restriction::Number ||
- (d->extra()->validity->m_restriction == Restriction::Integer &&
- value().asFloat() == ceil(value().asFloat()))))
- {
- switch( d->extra()->validity->m_cond)
- {
- case Conditional::Equal:
- valid = ( value().asFloat() - d->extra()->validity->valMin < DBL_EPSILON
- && value().asFloat() - d->extra()->validity->valMin >
- (0.0 - DBL_EPSILON));
- break;
- case Conditional::DifferentTo:
- valid = !( ( value().asFloat() - d->extra()->validity->valMin < DBL_EPSILON
- && value().asFloat() - d->extra()->validity->valMin >
- (0.0 - DBL_EPSILON)) );
- break;
- case Conditional::Superior:
- valid = ( value().asFloat() > d->extra()->validity->valMin);
- break;
- case Conditional::Inferior:
- valid = ( value().asFloat() <d->extra()->validity->valMin);
- break;
- case Conditional::SuperiorEqual:
- valid = ( value().asFloat() >= d->extra()->validity->valMin);
- break;
- case Conditional::InferiorEqual:
- valid = (value().asFloat() <= d->extra()->validity->valMin);
- break;
- case Conditional::Between:
- valid = ( value().asFloat() >= d->extra()->validity->valMin &&
- value().asFloat() <= d->extra()->validity->valMax);
- break;
- case Conditional::Different:
- valid = (value().asFloat() < d->extra()->validity->valMin ||
- value().asFloat() > d->extra()->validity->valMax);
- break;
- default :
- break;
- }
- }
- else if(d->extra()->validity->m_restriction==Restriction::Text)
- {
- valid = value().isString();
- }
- else if ( d->extra()->validity->m_restriction == Restriction::List )
- {
- //test int value
- if ( value().isString() && d->extra()->validity->listValidity.contains( value().asString() ) )
- valid = true;
- }
- else if(d->extra()->validity->m_restriction==Restriction::TextLength)
- {
- if( value().isString() )
- {
- int len = d->strOutText.length();
- switch( d->extra()->validity->m_cond)
- {
- case Conditional::Equal:
- if (len == d->extra()->validity->valMin)
- valid = true;
- break;
- case Conditional::DifferentTo:
- if (len != d->extra()->validity->valMin)
- valid = true;
- break;
- case Conditional::Superior:
- if(len > d->extra()->validity->valMin)
- valid = true;
- break;
- case Conditional::Inferior:
- if(len < d->extra()->validity->valMin)
- valid = true;
- break;
- case Conditional::SuperiorEqual:
- if(len >= d->extra()->validity->valMin)
- valid = true;
- break;
- case Conditional::InferiorEqual:
- if(len <= d->extra()->validity->valMin)
- valid = true;
- break;
- case Conditional::Between:
- if(len >= d->extra()->validity->valMin && len <= d->extra()->validity->valMax)
- valid = true;
- break;
- case Conditional::Different:
- if(len <d->extra()->validity->valMin || len >d->extra()->validity->valMax)
- valid = true;
- break;
- default :
- break;
- }
- }
- }
- else if(d->extra()->validity->m_restriction == Restriction::Time && isTime())
- {
- switch( d->extra()->validity->m_cond)
- {
- case Conditional::Equal:
- valid = (value().asTime() == d->extra()->validity->timeMin);
- break;
- case Conditional::DifferentTo:
- valid = (value().asTime() != d->extra()->validity->timeMin);
- break;
- case Conditional::Superior:
- valid = (value().asTime() > d->extra()->validity->timeMin);
- break;
- case Conditional::Inferior:
- valid = (value().asTime() < d->extra()->validity->timeMin);
- break;
- case Conditional::SuperiorEqual:
- valid = (value().asTime() >= d->extra()->validity->timeMin);
- break;
- case Conditional::InferiorEqual:
- valid = (value().asTime() <= d->extra()->validity->timeMin);
- break;
- case Conditional::Between:
- valid = (value().asTime() >= d->extra()->validity->timeMin &&
- value().asTime() <= d->extra()->validity->timeMax);
- break;
- case Conditional::Different:
- valid = (value().asTime() < d->extra()->validity->timeMin ||
- value().asTime() > d->extra()->validity->timeMax);
- break;
- default :
- break;
-
- }
- }
- else if(d->extra()->validity->m_restriction == Restriction::Date && isDate())
- {
- switch( d->extra()->validity->m_cond)
- {
- case Conditional::Equal:
- valid = (value().asDate() == d->extra()->validity->dateMin);
- break;
- case Conditional::DifferentTo:
- valid = (value().asDate() != d->extra()->validity->dateMin);
- break;
- case Conditional::Superior:
- valid = (value().asDate() > d->extra()->validity->dateMin);
- break;
- case Conditional::Inferior:
- valid = (value().asDate() < d->extra()->validity->dateMin);
- break;
- case Conditional::SuperiorEqual:
- valid = (value().asDate() >= d->extra()->validity->dateMin);
- break;
- case Conditional::InferiorEqual:
- valid = (value().asDate() <= d->extra()->validity->dateMin);
- break;
- case Conditional::Between:
- valid = (value().asDate() >= d->extra()->validity->dateMin &&
- value().asDate() <= d->extra()->validity->dateMax);
- break;
- case Conditional::Different:
- valid = (value().asDate() < d->extra()->validity->dateMin ||
- value().asDate() > d->extra()->validity->dateMax);
- break;
- default :
- break;
-
- }
- }
- }
- else
- {
- valid= true;
- }
-
- if(!valid &&d->extra()->validity != NULL && d->extra()->validity->displayMessage)
- {
- switch (d->extra()->validity->m_action )
- {
- case Action::Stop:
- KMessageBox::error((TQWidget*)0L, d->extra()->validity->message,
- d->extra()->validity->title);
- break;
- case Action::Warning:
- KMessageBox::warningYesNo((TQWidget*)0L, d->extra()->validity->message,
- d->extra()->validity->title);
- break;
- case Action::Information:
- KMessageBox::information((TQWidget*)0L, d->extra()->validity->message,
- d->extra()->validity->title);
- break;
- }
- }
- if (!d->hasExtra())
- return true; //okay if there's no validity
- return (valid || d->extra()->validity == NULL || d->extra()->validity->m_action != Action::Stop);
-}
-
-FormatType Cell::formatType() const
-{
- return format()->getFormatType( d->column, d->row );
-}
-
-double Cell::textWidth() const
-{
- return d->textWidth;
-}
-
-double Cell::textHeight() const
-{
- return d->textHeight;
-}
-
-int Cell::mergedXCells() const
-{
- return d->hasExtra() ? d->extra()->mergedXCells : 0;
-}
-
-int Cell::mergedYCells() const
-{
- return d->hasExtra() ? d->extra()->mergedYCells : 0;
-}
-
-int Cell::extraXCells() const
-{
- return d->hasExtra() ? d->extra()->extraXCells : 0;
-}
-
-int Cell::extraYCells() const
-{
- return d->hasExtra() ? d->extra()->extraYCells : 0;
-}
-
-double Cell::extraWidth() const
-{
- return d->hasExtra() ? d->extra()->extraWidth : 0;
-}
-
-double Cell::extraHeight() const
-{
- return d->hasExtra() ? d->extra()->extraHeight : 0;
-}
-
-
-bool Cell::isDate() const
-{
- FormatType ft = formatType();
-
- return (formatIsDate (ft) || ((ft == Generic_format) &&
- (value().format() == Value::fmt_Date)));
-}
-
-bool Cell::isTime() const
-{
- FormatType ft = formatType();
-
- return (formatIsTime (ft) || ((ft == Generic_format) &&
- (value().format() == Value::fmt_Time)));
-}
-
-void Cell::setCalcDirtyFlag()
-{
- if ( !isFormula() )
- {
- //don't set the flag if we don't hold a formula
- clearFlag(Flag_CalcDirty);
- return;
- }
- setFlag(Flag_CalcDirty);
- format()->sheet()->setRegionPaintDirty(cellRect());
-}
-
-
-bool Cell::updateChart(bool refresh)
-{
- // Update a chart for example if it depends on this cell.
- if ( d->row != 0 && d->column != 0 )
- {
- CellBinding *bind;
- for ( bind = format()->sheet()->firstCellBinding(); bind != 0L; bind = format()->sheet()->nextCellBinding() )
- {
- if ( bind->contains( d->column, d->row ) )
- {
- if (!refresh)
- return true;
-
- bind->cellChanged( this );
- }
- }
- return true;
- }
- return false;
-
-}
-
-double Cell::getDouble ()
-{
- if (isDefault())
- return 0.0;
- //(Tomas) umm can't we simply call value().asFloat() ?
- if (isDate())
- {
- TQDate date = value().asDate();
- TQDate dummy (1900, 1, 1);
- return (dummy.daysTo (date) + 1);
- }
- if (isTime())
- {
- TQTime time = value().asTime();
- TQTime dummy;
- return dummy.secsTo( time );
- }
- if (value().isNumber())
- return value().asFloat();
-
- return 0.0;
-}
-
-void Cell::convertToDouble ()
-{
- if (isDefault())
- return;
-
- setValue (getDouble ());
-}
-
-void Cell::convertToPercent ()
-{
- if (isDefault())
- return;
-
- setValue (getDouble ());
- d->value.setFormat (Value::fmt_Percent);
-}
-
-void Cell::convertToMoney ()
-{
- if (isDefault())
- return;
-
- setValue (getDouble ());
- d->value.setFormat (Value::fmt_Money);
- format()->setPrecision (locale()->fracDigits());
-}
-
-void Cell::convertToTime ()
-{
- //(Tomas) This is weird. And I mean *REALLY* weird. First, we
- //generate a time (TQTime), then we convert it to text, then
- //we give the text to the cell and ask it to parse it. Weird...
-
- if (isDefault() || isEmpty())
- return;
-
- setValue (getDouble ());
- TQTime time = value().asDateTime().time();
- int msec = (int) ( (value().asFloat() - (int) value().asFloat()) * 1000 );
- time = time.addMSecs( msec );
- setCellText( time.toString() );
-}
-
-void Cell::convertToDate ()
-{
- //(Tomas) This is weird. And I mean *REALLY* weird. First, we
- //generate a date (TQDate), then we convert it to text, then
- //we give the text to the cell and ask it to parse it. Weird...
-
- if (isDefault() || isEmpty())
- return;
-
- setValue (getDouble ());
-
- //TODO: why did we call setValue(), when we override it here?
- TQDate date(1900, 1, 1);
- date = date.addDays( (int) value().asFloat() - 1 );
- date = value().asDateTime().date();
- setCellText (locale()->formatDate (date, true));
-}
-
-void Cell::checkTextInput()
-{
- // Goal of this method: determine the value of the cell
- clearAllErrors();
-
- d->value = Value::empty();
-
- // Get the text from that cell
- TQString str = d->strText;
-
- sheet()->doc()->parser()->parse (str, this);
-
- // Parsing as time acts like an autoformat: we even change d->strText
- // [h]:mm:ss -> might get set by ValueParser
- if (isTime() && (formatType() != Time_format7))
- d->strText = locale()->formatTime( value().asDateTime().time(), true);
-
- // convert first letter to uppercase ?
- if (format()->sheet()->getFirstLetterUpper() && value().isString() &&
- (!d->strText.isEmpty()))
- {
- TQString str = value().asString();
- setValue( Value( str[0].upper() + str.right( str.length()-1 ) ) );
- }
-}
-
-//used in calc, setNumber, ValueParser
-void Cell::checkNumberFormat()
-{
- if ( formatType() == Number_format && value().isNumber() )
- {
- if ( value().asFloat() > 1e+10 )
- format()->setFormatType( Scientific_format );
- }
-}
-
-
-// ================================================================
-// Saving and loading
-
-
-TQDomElement Cell::save( TQDomDocument& doc,
- int _x_offset, int _y_offset,
- bool force, bool copy, bool era )
-{
- // Save the position of this cell
- TQDomElement cell = doc.createElement( "cell" );
- cell.setAttribute( "row", d->row - _y_offset );
- cell.setAttribute( "column", d->column - _x_offset );
- //
- // Save the formatting information
- //
- TQDomElement formatElement = format()->save( doc, d->column, d->row, force, copy );
- if ( formatElement.hasChildNodes() || formatElement.attributes().length() ) // don't save empty tags
- cell.appendChild( formatElement );
-
- if ( doesMergeCells() )
- {
- if ( extraXCells() )
- formatElement.setAttribute( "colspan", extraXCells() );
- if ( extraYCells() )
- formatElement.setAttribute( "rowspan", extraYCells() );
- }
-
- if ( d->hasExtra() && d->extra()->conditions )
- {
- TQDomElement conditionElement = d->extra()->conditions->saveConditions( doc );
-
- if ( !conditionElement.isNull() )
- cell.appendChild( conditionElement );
- }
-
- if ( d->hasExtra() && (d->extra()->validity != 0) )
- {
- TQDomElement validity = doc.createElement("validity");
-
- TQDomElement param=doc.createElement("param");
- param.setAttribute("cond",(int)d->extra()->validity->m_cond);
- param.setAttribute("action",(int)d->extra()->validity->m_action);
- param.setAttribute("allow",(int)d->extra()->validity->m_restriction);
- param.setAttribute("valmin",d->extra()->validity->valMin);
- param.setAttribute("valmax",d->extra()->validity->valMax);
- param.setAttribute("displaymessage",d->extra()->validity->displayMessage);
- param.setAttribute("displayvalidationinformation",d->extra()->validity->displayValidationInformation);
- param.setAttribute("allowemptycell",d->extra()->validity->allowEmptyCell);
- if ( !d->extra()->validity->listValidity.isEmpty() )
- param.setAttribute( "listvalidity", d->extra()->validity->listValidity.join( ";" ) );
- validity.appendChild(param);
- TQDomElement title = doc.createElement( "title" );
- title.appendChild( doc.createTextNode( d->extra()->validity->title ) );
- validity.appendChild( title );
- TQDomElement message = doc.createElement( "message" );
- message.appendChild( doc.createCDATASection( d->extra()->validity->message ) );
- validity.appendChild( message );
-
- TQDomElement inputTitle = doc.createElement( "inputtitle" );
- inputTitle.appendChild( doc.createTextNode( d->extra()->validity->titleInfo ) );
- validity.appendChild( inputTitle );
-
- TQDomElement inputMessage = doc.createElement( "inputmessage" );
- inputMessage.appendChild( doc.createTextNode( d->extra()->validity->messageInfo ) );
- validity.appendChild( inputMessage );
-
-
-
- TQString tmp;
- if ( d->extra()->validity->timeMin.isValid() )
- {
- TQDomElement timeMin = doc.createElement( "timemin" );
- tmp=d->extra()->validity->timeMin.toString();
- timeMin.appendChild( doc.createTextNode( tmp ) );
- validity.appendChild( timeMin );
- }
- if ( d->extra()->validity->timeMax.isValid() )
- {
- TQDomElement timeMax = doc.createElement( "timemax" );
- tmp=d->extra()->validity->timeMax.toString();
- timeMax.appendChild( doc.createTextNode( tmp ) );
- validity.appendChild( timeMax );
- }
-
- if ( d->extra()->validity->dateMin.isValid() )
- {
- TQDomElement dateMin = doc.createElement( "datemin" );
- TQString tmp("%1/%2/%3");
- tmp = tmp.arg(d->extra()->validity->dateMin.year()).arg(d->extra()->validity->dateMin.month()).arg(d->extra()->validity->dateMin.day());
- dateMin.appendChild( doc.createTextNode( tmp ) );
- validity.appendChild( dateMin );
- }
- if ( d->extra()->validity->dateMax.isValid() )
- {
- TQDomElement dateMax = doc.createElement( "datemax" );
- TQString tmp("%1/%2/%3");
- tmp = tmp.arg(d->extra()->validity->dateMax.year()).arg(d->extra()->validity->dateMax.month()).arg(d->extra()->validity->dateMax.day());
- dateMax.appendChild( doc.createTextNode( tmp ) );
- validity.appendChild( dateMax );
- }
-
- cell.appendChild( validity );
- }
-
- if ( format()->comment() )
- {
- TQDomElement comment = doc.createElement( "comment" );
- comment.appendChild( doc.createCDATASection( *format()->comment() ) );
- cell.appendChild( comment );
- }
-
- //
- // Save the text
- //
- if ( !d->strText.isEmpty() )
- {
- // Formulas need to be encoded to ensure that they
- // are position independent.
- if ( isFormula() )
- {
- TQDomElement text = doc.createElement( "text" );
- // if we are cutting to the clipboard, relative references need to be encoded absolutely
- text.appendChild( doc.createTextNode( encodeFormula( era ) ) );
- cell.appendChild( text );
-
- /* we still want to save the results of the formula */
- TQDomElement formulaResult = doc.createElement( "result" );
- saveCellResult( doc, formulaResult, d->strOutText );
- cell.appendChild( formulaResult );
-
- }
- else if ( !link().isEmpty() )
- {
- // KSpread pre 1.4 saves link as rich text, marked with first char '
- // Have to be saved in some CDATA section because of too many special charatcers.
- TQDomElement text = doc.createElement( "text" );
- TQString qml = "!<a href=\"" + link() + "\">" + d->strText + "</a>";
- text.appendChild( doc.createCDATASection( qml ) );
- cell.appendChild( text );
- }
- else
- {
- // Save the cell contents (in a locale-independent way)
- TQDomElement text = doc.createElement( "text" );
- saveCellResult( doc, text, d->strText );
- cell.appendChild( text );
- }
- }
- if ( cell.hasChildNodes() || cell.attributes().length() > 2 ) // don't save empty tags
- // (the >2 is due to "row" and "column" attributes)
- return cell;
- else
- return TQDomElement();
-}
-
-bool Cell::saveCellResult( TQDomDocument& doc, TQDomElement& result,
- TQString str )
-{
- TQString dataType = "Other"; // fallback
-
- if ( value().isNumber() )
- {
- if ( isDate() )
- {
- // serial number of date
- TQDate dd = value().asDateTime().date();
- dataType = "Date";
- str = "%1/%2/%3";
- str = str.arg(dd.year()).arg(dd.month()).arg(dd.day());
- }
- else if( isTime() )
- {
- // serial number of time
- dataType = "Time";
- str = value().asDateTime().time().toString();
- }
- else
- {
- // real number
- dataType = "Num";
- if (value().isInteger())
- str = TQString::number(value().asInteger());
- else
- str = TQString::number(value().asFloat(), 'g', DBL_DIG);
- }
- }
-
- if ( value().isBoolean() )
- {
- dataType = "Bool";
- str = value().asBoolean() ? "true" : "false";
- }
-
- if ( value().isString() )
- {
- dataType = "Str";
- str = value().asString();
- }
-
- result.setAttribute( "dataType", dataType );
- if ( !d->strOutText.isEmpty() )
- result.setAttribute( "outStr", d->strOutText );
- result.appendChild( doc.createTextNode( str ) );
-
- return true; /* really isn't much of a way for this function to fail */
-}
-
-void Cell::saveOasisAnnotation( KoXmlWriter &xmlwriter )
-{
- if ( format()->comment() )
- {
- //<office:annotation draw:style-name="gr1" draw:text-style-name="P1" svg:width="2.899cm" svg:height="2.691cm" svg:x="2.858cm" svg:y="0.001cm" draw:caption-point-x="-2.858cm" draw:caption-point-y="-0.001cm">
- xmlwriter.startElement( "office:annotation" );
- TQStringList text = TQStringList::split( "\n", *format()->comment() );
- for ( TQStringList::Iterator it = text.begin(); it != text.end(); ++it ) {
- xmlwriter.startElement( "text:p" );
- xmlwriter.addTextNode( *it );
- xmlwriter.endElement();
- }
- xmlwriter.endElement();
- }
-}
-
-
-
-TQString Cell::saveOasisCellStyle( KoGenStyle &currentCellStyle, KoGenStyles &mainStyles )
-{
- if ( d->hasExtra() && d->extra()->conditions )
- {
- // this has to be an automatic style
- currentCellStyle = KoGenStyle( Doc::STYLE_CELL_AUTO, "table-cell" );
- d->extra()->conditions->saveOasisConditions( currentCellStyle );
- }
- return format()->saveOasisCellStyle( currentCellStyle, mainStyles );
-}
-
-
-bool Cell::saveOasis( KoXmlWriter& xmlwriter, KoGenStyles &mainStyles,
- int row, int column, int &repeated,
- GenValidationStyles &valStyle )
-{
- if ( !isPartOfMerged() )
- xmlwriter.startElement( "table:table-cell" );
- else
- xmlwriter.startElement( "table:covered-table-cell" );
-#if 0
- //add font style
- TQFont font;
- Value const value( cell->value() );
- if ( !cell->isDefault() )
- {
- font = cell->format()->textFont( i, row );
- m_styles.addFont( font );
-
- if ( cell->format()->hasProperty( Format::PComment ) )
- hasComment = true;
- }
-#endif
- // NOTE save the value before the style as long as the Formatter does not work correctly
- if ( link().isEmpty() )
- saveOasisValue (xmlwriter);
-
- KoGenStyle currentCellStyle; // the type determined in saveOasisCellStyle
- saveOasisCellStyle( currentCellStyle,mainStyles );
- // skip 'table:style-name' attribute for the default style
- if ( !currentCellStyle.isDefaultStyle() )
- xmlwriter.addAttribute( "table:style-name", mainStyles.styles()[currentCellStyle] );
-
- // group empty cells with the same style
- if ( isEmpty() && !format()->hasProperty( Format::PComment ) &&
- !isPartOfMerged() && !doesMergeCells() )
- {
- bool refCellIsDefault = isDefault();
- int j = column + 1;
- Cell *nextCell = format()->sheet()->getNextCellRight( column, row );
- while ( nextCell )
- {
- // if
- // the next cell is not the adjacent one
- // or
- // the next cell is not empty
- if ( nextCell->column() != j || !nextCell->isEmpty() )
- {
- if ( refCellIsDefault )
- {
- // if the origin cell was a default cell,
- // we count the default cells
- repeated = nextCell->column() - j + 1;
- }
- // otherwise we just stop here to process the adjacent
- // cell in the next iteration of the outer loop
- // (in Sheet::saveOasisCells)
- break;
- }
-
- KoGenStyle nextCellStyle; // the type is determined in saveOasisCellStyle
- nextCell->saveOasisCellStyle( nextCellStyle,mainStyles );
-
- if ( nextCell->isPartOfMerged() || nextCell->doesMergeCells() ||
- nextCell->format()->hasProperty( Format::PComment ) ||
- !(nextCellStyle == currentCellStyle) )
- {
- break;
- }
- ++repeated;
- // get the next cell and set the index to the adjacent cell
- nextCell = format()->sheet()->getNextCellRight( j++, row );
- }
- kdDebug() << "Cell::saveOasis: empty cell in column " << column << " "
- << "repeated " << repeated << " time(s)" << endl;
-
- if ( repeated > 1 )
- xmlwriter.addAttribute( "table:number-columns-repeated", TQString::number( repeated ) );
- }
-
-
- if (d->hasExtra() && d->extra()->validity)
- {
- GenValidationStyle styleVal(d->extra()->validity);
- xmlwriter.addAttribute( "table:validation-name", valStyle.lookup( styleVal ) );
- }
- if ( isFormula() )
- {
- //kdDebug() << "Formula found" << endl;
- TQString formula( convertFormulaToOasisFormat( text() ) );
- xmlwriter.addAttribute( "table:formula", formula );
- }
- else if ( !link().isEmpty() )
- {
- //kdDebug()<<"Link found \n";
- xmlwriter.startElement( "text:p" );
- xmlwriter.startElement( "text:a" );
- //Reference cell is started by "#"
- if ( localReferenceAnchor( link() ) )
- xmlwriter.addAttribute( " xlink:href", ( "#"+link() ) );
- else
- xmlwriter.addAttribute( " xlink:href", link() );
- xmlwriter.addTextNode( text() );
- xmlwriter.endElement();
- xmlwriter.endElement();
- }
-
- if ( doesMergeCells() )
- {
- int colSpan = mergedXCells() + 1;
- int rowSpan = mergedYCells() + 1;
-
- if ( colSpan > 1 )
- xmlwriter.addAttribute( "table:number-columns-spanned", TQString::number( colSpan ) );
-
- if ( rowSpan > 1 )
- xmlwriter.addAttribute( "table:number-rows-spanned", TQString::number( rowSpan ) );
- }
-
- if ( !isEmpty() && link().isEmpty() )
- {
- xmlwriter.startElement( "text:p" );
- xmlwriter.addTextNode( strOutText().utf8() );
- xmlwriter.endElement();
- }
-
- saveOasisAnnotation( xmlwriter );
-
- xmlwriter.endElement();
- return true;
-}
-
-void Cell::saveOasisValue (KoXmlWriter &xmlWriter)
-{
- switch (value().format())
- {
- case Value::fmt_None: break; //NOTHING HERE
- case Value::fmt_Boolean:
- {
- xmlWriter.addAttribute( "office:value-type", "boolean" );
- xmlWriter.addAttribute( "office:boolean-value", ( value().asBoolean() ?
- "true" : "false" ) );
- break;
- }
- case Value::fmt_Number:
- {
- xmlWriter.addAttribute( "office:value-type", "float" );
- if (value().isInteger())
- xmlWriter.addAttribute( "office:value", TQString::number( value().asInteger() ) );
- else
- xmlWriter.addAttribute( "office:value", TQString::number( value().asFloat(), 'g', DBL_DIG ) );
- break;
- }
- case Value::fmt_Percent:
- {
- xmlWriter.addAttribute( "office:value-type", "percentage" );
- xmlWriter.addAttribute( "office:value",
- TQString::number( value().asFloat() ) );
- break;
- }
- case Value::fmt_Money:
- {
- xmlWriter.addAttribute( "office:value-type", "currency" );
- Format::Currency currency;
- if (format()->currencyInfo(currency))
- xmlWriter.addAttribute( "office:currency", Currency::getCurrencyCode(currency.type) );
- xmlWriter.addAttribute( "office:value",
- TQString::number( value().asFloat() ) );
- break;
- }
- case Value::fmt_DateTime: break; //NOTHING HERE
- case Value::fmt_Date:
- {
- xmlWriter.addAttribute( "office:value-type", "date" );
- xmlWriter.addAttribute( "office:date-value",
- value().asDate().toString( Qt::ISODate ) );
- break;
- }
- case Value::fmt_Time:
- {
- xmlWriter.addAttribute( "office:value-type", "time" );
- xmlWriter.addAttribute( "office:time-value",
- value().asTime().toString( "PThhHmmMssS" ) );
- break;
- }
- case Value::fmt_String:
- {
- xmlWriter.addAttribute( "office:value-type", "string" );
- xmlWriter.addAttribute( "office:string-value", value().asString() );
- break;
- }
- };
-}
-
-TQString Cell::convertFormulaToOasisFormat( const TQString & formula ) const
-{
- TQString s;
- TQRegExp exp("(\\$?)([a-zA-Z]+)(\\$?)([0-9]+)");
- int n = exp.search( formula, 0 );
- kdDebug() << "Exp: " << formula << ", n: " << n << ", Length: " << formula.length()
- << ", Matched length: " << exp.matchedLength() << endl;
-
- bool inQuote1 = false;
- bool inQuote2 = false;
- int i = 0;
- int l = (int) formula.length();
- if ( l <= 0 )
- return formula;
- while ( i < l )
- {
- if ( ( n != -1 ) && ( n < i ) )
- {
- n = exp.search( formula, i );
- kdDebug() << "Exp: " << formula.right( l - i ) << ", n: " << n << endl;
- }
- if ( formula[i] == '"' )
- {
- inQuote1 = !inQuote1;
- s += formula[i];
- ++i;
- continue;
- }
- if ( formula[i] == '\'' )
- {
- // named area
- inQuote2 = !inQuote2;
- ++i;
- continue;
- }
- if ( inQuote1 || inQuote2 )
- {
- s += formula[i];
- ++i;
- continue;
- }
- if ( ( formula[i] == '=' ) && ( formula[i + 1] == '=' ) )
- {
- s += '=';
- ++i;++i;
- continue;
- }
- if ( formula[i] == '!' )
- {
- insertBracket( s );
- s += '.';
- ++i;
- continue;
- }
- if ( formula[i] == ',' )
- {
- s += '.';
- ++i;
- continue;
- }
- if ( n == i )
- {
- int ml = exp.matchedLength();
- if ( formula[ i + ml ] == '!' )
- {
- kdDebug() << "No cell ref but sheet name" << endl;
- s += formula[i];
- ++i;
- continue;
- }
- if ( ( i > 0 ) && ( formula[i - 1] != '!' ) )
- s += "[.";
- for ( int j = 0; j < ml; ++j )
- {
- s += formula[i];
- ++i;
- }
- s += ']';
- continue;
- }
-
- s += formula[i];
- ++i;
- }
-
- return s;
-}
-
-void Cell::loadOasisConditional( TQDomElement * style )
-{
- if ( style )//safe
- {
- TQDomElement e;
- forEachElement( e, style->toElement() )
- {
- if ( e.localName() == "map" && e.namespaceURI() == KoXmlNS::style )
- {
- if (d->hasExtra())
- delete d->extra()->conditions;
- d->extra()->conditions = new Conditions( this );
- d->extra()->conditions->loadOasisConditions( e );
- d->extra()->conditions->checkMatches();
- // break here
- // Conditions::loadOasisConditions finishes the iteration
- break;
- }
- }
- }
-}
-
-bool Cell::loadOasis( const TQDomElement& element , KoOasisLoadingContext& oasisContext , Style* style )
-{
- kdDebug() << "*** Loading cell properties ***** at " << column() << "," << row () << endl;
-
- if ( element.hasAttributeNS( KoXmlNS::table, "style-name" ) )
- {
- kdDebug()<<" table:style-name: "<<element.attributeNS( KoXmlNS::table, "style-name", TQString() )<<endl;
- oasisContext.fillStyleStack( element, KoXmlNS::table, "styleName", "table-cell" );
-
- TQString str = element.attributeNS( KoXmlNS::table, "style-name", TQString() );
- const TQDomElement* cellStyle = oasisContext.oasisStyles().findStyle( str, "table-cell" );
-
- if ( cellStyle )
- loadOasisConditional( const_cast<TQDomElement *>( cellStyle ) );
- }
-
- if (style)
- {
- format()->setStyle( style );
- }
-
- //Search and load each paragraph of text. Each paragraph is separated by a line break.
- loadOasisCellText( element );
-
- //
- // formula
- //
- bool isFormula = false;
- if ( element.hasAttributeNS( KoXmlNS::table, "formula" ) )
- {
- kdDebug()<<" formula :"<<element.attributeNS( KoXmlNS::table, "formula", TQString() )<<endl;
- isFormula = true;
- TQString oasisFormula( element.attributeNS( KoXmlNS::table, "formula", TQString() ) );
- //necessary to remove it to load formula from oocalc2.0 (use namespace)
- if (oasisFormula.startsWith( "oooc:" ) )
- oasisFormula= oasisFormula.mid( 5 );
- else if (oasisFormula.startsWith( "kspr:" ) )
- oasisFormula= oasisFormula.mid( 5 );
- // TODO Stefan: merge this into Oasis::decodeFormula
- checkForNamedAreas( oasisFormula );
- oasisFormula = Oasis::decodeFormula( oasisFormula, locale() );
- setCellText( oasisFormula );
- }
- else if ( d->strText.at(0) == '=' ) //prepend ' to the text to avoid = to be painted
- d->strText.prepend('\'');
-
- //
- // validation
- //
- if ( element.hasAttributeNS( KoXmlNS::table, "validation-name" ) )
- {
- kdDebug()<<" validation-name: "<<element.attributeNS( KoXmlNS::table, "validation-name", TQString() )<<endl;
- loadOasisValidation( element.attributeNS( KoXmlNS::table, "validation-name", TQString() ) );
- }
-
- //
- // value type
- //
- if( element.hasAttributeNS( KoXmlNS::office, "value-type" ) )
- {
- TQString valuetype = element.attributeNS( KoXmlNS::office, "value-type", TQString() );
- kdDebug()<<" value-type: " << valuetype << endl;
- if( valuetype == "boolean" )
- {
- TQString val = element.attributeNS( KoXmlNS::office, "boolean-value", TQString() ).lower();
- if( ( val == "true" ) || ( val == "false" ) )
- {
- bool value = val == "true";
- setCellValue( value );
- }
- }
-
- // integer and floating-point value
- else if( valuetype == "float" )
- {
- bool ok = false;
- double value = element.attributeNS( KoXmlNS::office, "value", TQString() ).toDouble( &ok );
- if( ok )
- setCellValue( value );
-
- if ( !isFormula && d->strText.isEmpty())
- {
- TQString str = locale()->formatNumber( value, 15 );
- setCellText( str );
- }
- }
-
- // currency value
- else if( valuetype == "currency" )
- {
- bool ok = false;
- double value = element.attributeNS( KoXmlNS::office, "value", TQString() ).toDouble( &ok );
- if( ok )
- {
- setCellValue( value, Money_format );
-
- if (element.hasAttributeNS( KoXmlNS::office, "currency" ) )
- {
- Currency currency(element.attributeNS( KoXmlNS::office, "currency", TQString() ) );
- format()->setCurrency( currency.getIndex(), currency.getDisplayCode() );
- }
- }
- }
- else if( valuetype == "percentage" )
- {
- bool ok = false;
- double v = element.attributeNS( KoXmlNS::office, "value", TQString() ).toDouble( &ok );
- if( ok )
- {
- Value value;
- value.setValue (v);
- value.setFormat (Value::fmt_Percent);
- setCellValue( value );
-
- if ( !isFormula && d->strText.isEmpty())
- {
- TQString str = locale()->formatNumber( v, 15 );
- setCellText( str );
- }
-
- format()->setFormatType (Percentage_format);
- }
- }
- else if ( valuetype == "date" )
- {
- TQString value = element.attributeNS( KoXmlNS::office, "value", TQString() );
- if ( value.isEmpty() )
- value = element.attributeNS( KoXmlNS::office, "date-value", TQString() );
- kdDebug() << "Type: date, value: " << value << endl;
-
- // "1980-10-15"
- int year = 0, month = 0, day = 0;
- bool ok = false;
-
- int p1 = value.find( '-' );
- if ( p1 > 0 )
- year = value.left( p1 ).toInt( &ok );
-
- kdDebug() << "year: " << value.left( p1 ) << endl;
-
- int p2 = value.find( '-', ++p1 );
-
- if ( ok )
- month = value.mid( p1, p2 - p1 ).toInt( &ok );
-
- kdDebug() << "month: " << value.mid( p1, p2 - p1 ) << endl;
-
- if ( ok )
- day = value.right( value.length() - p2 - 1 ).toInt( &ok );
-
- kdDebug() << "day: " << value.right( value.length() - p2 ) << endl;
-
- if ( ok )
- {
- setCellValue( TQDate( year, month, day ) );
- if ( style )
- format()->setFormatType (style->formatType());
- kdDebug() << "Set TQDate: " << year << " - " << month << " - " << day << endl;
- }
-
- }
- else if ( valuetype == "time" )
- {
- TQString value = element.attributeNS( KoXmlNS::office, "value", TQString() );
- if ( value.isEmpty() )
- value = element.attributeNS( KoXmlNS::office, "time-value", TQString() );
- kdDebug() << "Type: time: " << value << endl;
- // "PT15H10M12S"
- int hours = 0, minutes = 0, seconds = 0;
- int l = value.length();
- TQString num;
- bool ok = false;
- for ( int i = 0; i < l; ++i )
- {
- if ( value[i].isNumber() )
- {
- num += value[i];
- continue;
- }
- else if ( value[i] == 'H' )
- hours = num.toInt( &ok );
- else if ( value[i] == 'M' )
- minutes = num.toInt( &ok );
- else if ( value[i] == 'S' )
- seconds = num.toInt( &ok );
- else
- continue;
-
- kdDebug() << "Num: " << num << endl;
-
- num = "";
- if ( !ok )
- break;
- }
- kdDebug() << "Hours: " << hours << ", " << minutes << ", " << seconds << endl;
-
- if ( ok )
- {
- // Value kval( timeToNum( hours, minutes, seconds ) );
- // cell->setValue( kval );
- setCellValue( TQTime( hours % 24, minutes, seconds ) );
- if ( style )
- format()->setFormatType (style->formatType());
- }
- }
- else if( valuetype == "string" )
- {
- TQString value = element.attributeNS( KoXmlNS::office, "value", TQString() );
- if ( value.isEmpty() && element.hasAttributeNS( KoXmlNS::office, "string-value" ))
- {
- //if there is not string-value entry don't overwrite value stored into <text:p>
- value = element.attributeNS( KoXmlNS::office, "string-value", TQString() );
- setCellValue( value );
- }
- format()->setFormatType (Text_format);
- }
- else
- kdDebug()<<" type of value found : "<<valuetype<<endl;
- }
-
- //
- // merged cells ?
- //
- int colSpan = 1;
- int rowSpan = 1;
- if ( element.hasAttributeNS( KoXmlNS::table, "number-columns-spanned" ) )
- {
- bool ok = false;
- int span = element.attributeNS( KoXmlNS::table, "number-columns-spanned", TQString() ).toInt( &ok );
- if( ok ) colSpan = span;
- }
- if ( element.hasAttributeNS( KoXmlNS::table, "number-rows-spanned" ) )
- {
- bool ok = false;
- int span = element.attributeNS( KoXmlNS::table, "number-rows-spanned", TQString() ).toInt( &ok );
- if( ok ) rowSpan = span;
- }
- if ( colSpan > 1 || rowSpan > 1 )
- mergeCells( d->column, d->row, colSpan - 1, rowSpan - 1 );
-
- //
- // cell comment/annotation
- //
- TQDomElement annotationElement = KoDom::namedItemNS( element, KoXmlNS::office, "annotation" );
- if ( !annotationElement.isNull() )
- {
- TQString comment;
- TQDomNode node = annotationElement.firstChild();
- while( !node.isNull() )
- {
- TQDomElement commentElement = node.toElement();
- if( !commentElement.isNull() )
- if( commentElement.localName() == "p" && commentElement.namespaceURI() == KoXmlNS::text )
- {
- if( !comment.isEmpty() ) comment.append( '\n' );
- comment.append( commentElement.text() );
- }
-
- node = node.nextSibling();
- }
-
- if( !comment.isEmpty() )
- format()->setComment( comment );
- }
-
- TQDomElement frame = KoDom::namedItemNS( element, KoXmlNS::draw, "frame" );
- if ( !frame.isNull() )
- loadOasisObjects( frame, oasisContext );
-
- if (isFormula)
- setCalcDirtyFlag (); // formulas must be recalculated
-
- return true;
-}
-
-void Cell::loadOasisCellText( const TQDomElement& parent )
-{
- //Search and load each paragraph of text. Each paragraph is separated by a line break
- TQDomElement textParagraphElement;
- TQString cellText;
-
- bool multipleTextParagraphsFound=false;
-
- forEachElement( textParagraphElement , parent )
- {
- if ( textParagraphElement.localName()=="p" &&
- textParagraphElement.namespaceURI()== KoXmlNS::text )
- {
- // our text, could contain formating for value or result of formul
- if (cellText.isEmpty())
- cellText = textParagraphElement.text();
- else
- {
- cellText += "\n"+textParagraphElement.text();
- multipleTextParagraphsFound=true;
- }
-
- TQDomElement textA = KoDom::namedItemNS( textParagraphElement, KoXmlNS::text, "a" );
- if( !textA.isNull() )
- {
- if ( textA.hasAttributeNS( KoXmlNS::xlink, "href" ) )
- {
- TQString link = textA.attributeNS( KoXmlNS::xlink, "href", TQString() );
- cellText = textA.text();
- setCellText( cellText );
- setValue( cellText );
- if ( link[0]=='#' )
- link=link.remove( 0, 1 );
- setLink( link );
- }
- }
- }
- }
-
- if (!cellText.isNull())
- {
- setCellText( cellText );
- setValue( cellText );
- }
-
- //Enable word wrapping if multiple lines of text have been found.
- if ( multipleTextParagraphsFound )
- {
- format()->setMultiRow(true);
- }
-}
-
-void Cell::loadOasisObjects( const TQDomElement &parent, KoOasisLoadingContext& oasisContext )
-{
- for( TQDomElement e = parent; !e.isNull(); e = e.nextSibling().toElement() )
- {
- if ( e.localName() == "frame" && e.namespaceURI() == KoXmlNS::draw )
- {
- EmbeddedObject *obj = 0;
- TQDomNode object = KoDom::namedItemNS( e, KoXmlNS::draw, "object" );
- if ( !object.isNull() )
- {
- if ( !object.toElement().attributeNS( KoXmlNS::draw, "notify-on-update-of-ranges", TQString()).isNull() )
- obj = new EmbeddedChart( sheet()->doc(), sheet() );
- else
- obj = new EmbeddedKOfficeObject( sheet()->doc(), sheet() );
- }
- else
- {
- TQDomNode image = KoDom::namedItemNS( e, KoXmlNS::draw, "image" );
- if ( !image.isNull() )
- obj = new EmbeddedPictureObject( sheet(), sheet()->doc()->pictureCollection() );
- else
- kdDebug() << "Object type wasn't loaded!" << endl;
- }
-
- if ( obj )
- {
- obj->loadOasis( e, oasisContext );
- sheet()->doc()->insertObject( obj );
-
- TQString ref = e.attributeNS( KoXmlNS::table, "end-cell-address", TQString() );
- if ( ref.isNull() )
- continue;
-
- ref = Oasis::decodeFormula( ref );
- Point point( ref );
- if ( !point.isValid() )
- continue;
-
- KoRect geometry = obj->geometry();
- geometry.setLeft( geometry.left() + sheet()->columnPos( d->column, 0 ) );
- geometry.setTop( geometry.top() + sheet()->rowPos( d->row, 0 ) );
-
- TQString str = e.attributeNS( KoXmlNS::table, "end-x", TQString() );
- if ( !str.isNull() )
- {
- uint end_x = (uint) KoUnit::parseValue( str );
- geometry.setRight( sheet()->columnPos( point.column(), 0) + end_x );
- }
-
- str = e.attributeNS( KoXmlNS::table, "end-y", TQString() );
- if ( !str.isNull() )
- {
- uint end_y = (uint) KoUnit::parseValue( str );
- geometry.setBottom( sheet()->rowPos( point.row(), 0) + end_y );
- }
-
- obj->setGeometry( geometry );
- }
- }
- }
-}
-
-void Cell::loadOasisValidation( const TQString& validationName )
-{
- TQDomElement element = sheet()->doc()->loadingInfo()->validation( validationName);
- if (d->hasExtra())
- delete d->extra()->validity;
- d->extra()->validity = new Validity;
- if ( element.hasAttributeNS( KoXmlNS::table, "condition" ) )
- {
- TQString valExpression = element.attributeNS( KoXmlNS::table, "condition", TQString() );
- kdDebug()<<" element.attribute( table:condition ) "<<valExpression<<endl;
- //Condition ::= ExtendedTrueCondition | TrueFunction 'and' TrueCondition
- //TrueFunction ::= cell-content-is-whole-number() | cell-content-is-decimal-number() | cell-content-is-date() | cell-content-is-time()
- //ExtendedTrueCondition ::= ExtendedGetFunction | cell-content-text-length() Operator Value
- //TrueCondition ::= GetFunction | cell-content() Operator Value
- //GetFunction ::= cell-content-is-between(Value, Value) | cell-content-is-not-between(Value, Value)
- //ExtendedGetFunction ::= cell-content-text-length-is-between(Value, Value) | cell-content-text-length-is-not-between(Value, Value)
- //Operator ::= '<' | '>' | '<=' | '>=' | '=' | '!='
- //Value ::= NumberValue | String | Formula
- //A Formula is a formula without an equals (=) sign at the beginning. See section 8.1.3 for more information.
- //A String comprises one or more characters surrounded by quotation marks.
- //A NumberValue is a whole or decimal number. It must not contain comma separators for numbers of 1000 or greater.
-
- //ExtendedTrueCondition
- if ( valExpression.contains( "cell-content-text-length()" ) )
- {
- //"cell-content-text-length()>45"
- valExpression = valExpression.remove("oooc:cell-content-text-length()" );
- kdDebug()<<" valExpression = :"<<valExpression<<endl;
- d->extra()->validity->m_restriction = Restriction::TextLength;
-
- loadOasisValidationCondition( valExpression );
- }
- else if ( valExpression.contains( "cell-content-is-text()" ) )
- {
- d->extra()->validity->m_restriction = Restriction::Text;
- }
- //cell-content-text-length-is-between(Value, Value) | cell-content-text-length-is-not-between(Value, Value) | cell-content-is-in-list( StringList )
- else if ( valExpression.contains( "cell-content-text-length-is-between" ) )
- {
- d->extra()->validity->m_restriction = Restriction::TextLength;
- d->extra()->validity->m_cond = Conditional::Between;
- valExpression = valExpression.remove( "oooc:cell-content-text-length-is-between(" );
- kdDebug()<<" valExpression :"<<valExpression<<endl;
- valExpression = valExpression.remove( ")" );
- TQStringList listVal = TQStringList::split( ",", valExpression );
- loadOasisValidationValue( listVal );
- }
- else if ( valExpression.contains( "cell-content-text-length-is-not-between" ) )
- {
- d->extra()->validity->m_restriction = Restriction::TextLength;
- d->extra()->validity->m_cond = Conditional::Different;
- valExpression = valExpression.remove( "oooc:cell-content-text-length-is-not-between(" );
- kdDebug()<<" valExpression :"<<valExpression<<endl;
- valExpression = valExpression.remove( ")" );
- kdDebug()<<" valExpression :"<<valExpression<<endl;
- TQStringList listVal = TQStringList::split( ",", valExpression );
- loadOasisValidationValue( listVal );
- }
- else if ( valExpression.contains( "cell-content-is-in-list(" ) )
- {
- d->extra()->validity->m_restriction = Restriction::List;
- valExpression = valExpression.remove( "oooc:cell-content-is-in-list(" );
- kdDebug()<<" valExpression :"<<valExpression<<endl;
- valExpression = valExpression.remove( ")" );
- d->extra()->validity->listValidity = TQStringList::split( ";", valExpression );
-
- }
- //TrueFunction ::= cell-content-is-whole-number() | cell-content-is-decimal-number() | cell-content-is-date() | cell-content-is-time()
- else
- {
- if (valExpression.contains( "cell-content-is-whole-number()" ) )
- {
- d->extra()->validity->m_restriction = Restriction::Number;
- valExpression = valExpression.remove( "oooc:cell-content-is-whole-number() and " );
- }
- else if (valExpression.contains( "cell-content-is-decimal-number()" ) )
- {
- d->extra()->validity->m_restriction = Restriction::Integer;
- valExpression = valExpression.remove( "oooc:cell-content-is-decimal-number() and " );
- }
- else if (valExpression.contains( "cell-content-is-date()" ) )
- {
- d->extra()->validity->m_restriction = Restriction::Date;
- valExpression = valExpression.remove( "oooc:cell-content-is-date() and " );
- }
- else if (valExpression.contains( "cell-content-is-time()" ) )
- {
- d->extra()->validity->m_restriction = Restriction::Time;
- valExpression = valExpression.remove( "oooc:cell-content-is-time() and " );
- }
- kdDebug()<<"valExpression :"<<valExpression<<endl;
-
- if ( valExpression.contains( "cell-content()" ) )
- {
- valExpression = valExpression.remove( "cell-content()" );
- loadOasisValidationCondition( valExpression );
- }
- //GetFunction ::= cell-content-is-between(Value, Value) | cell-content-is-not-between(Value, Value)
- //for the moment we support just int/double value, not text/date/time :(
- if ( valExpression.contains( "cell-content-is-between(" ) )
- {
- valExpression = valExpression.remove( "cell-content-is-between(" );
- valExpression = valExpression.remove( ")" );
- TQStringList listVal = TQStringList::split( "," , valExpression );
- loadOasisValidationValue( listVal );
- d->extra()->validity->m_cond = Conditional::Between;
- }
- if ( valExpression.contains( "cell-content-is-not-between(" ) )
- {
- valExpression = valExpression.remove( "cell-content-is-not-between(" );
- valExpression = valExpression.remove( ")" );
- TQStringList listVal = TQStringList::split( ",", valExpression );
- loadOasisValidationValue( listVal );
- d->extra()->validity->m_cond = Conditional::Different;
- }
- }
- }
- if ( element.hasAttributeNS( KoXmlNS::table, "allow-empty-cell" ) )
- {
- kdDebug()<<" element.hasAttribute( table:allow-empty-cell ) :"<<element.hasAttributeNS( KoXmlNS::table, "allow-empty-cell" )<<endl;
- d->extra()->validity->allowEmptyCell = ( ( element.attributeNS( KoXmlNS::table, "allow-empty-cell", TQString() )=="true" ) ? true : false );
- }
- if ( element.hasAttributeNS( KoXmlNS::table, "base-cell-address" ) )
- {
- //todo what is it ?
- }
-
- TQDomElement help = KoDom::namedItemNS( element, KoXmlNS::table, "help-message" );
- if ( !help.isNull() )
- {
- if ( help.hasAttributeNS( KoXmlNS::table, "title" ) )
- {
- kdDebug()<<"help.attribute( table:title ) :"<<help.attributeNS( KoXmlNS::table, "title", TQString() )<<endl;
- d->extra()->validity->titleInfo = help.attributeNS( KoXmlNS::table, "title", TQString() );
- }
- if ( help.hasAttributeNS( KoXmlNS::table, "display" ) )
- {
- kdDebug()<<"help.attribute( table:display ) :"<<help.attributeNS( KoXmlNS::table, "display", TQString() )<<endl;
- d->extra()->validity->displayValidationInformation = ( ( help.attributeNS( KoXmlNS::table, "display", TQString() )=="true" ) ? true : false );
- }
- TQDomElement attrText = KoDom::namedItemNS( help, KoXmlNS::text, "p" );
- if ( !attrText.isNull() )
- {
- kdDebug()<<"help text :"<<attrText.text()<<endl;
- d->extra()->validity->messageInfo = attrText.text();
- }
- }
-
- TQDomElement error = KoDom::namedItemNS( element, KoXmlNS::table, "error-message" );
- if ( !error.isNull() )
- {
- if ( error.hasAttributeNS( KoXmlNS::table, "title" ) )
- d->extra()->validity->title = error.attributeNS( KoXmlNS::table, "title", TQString() );
- if ( error.hasAttributeNS( KoXmlNS::table, "message-type" ) )
- {
- TQString str = error.attributeNS( KoXmlNS::table, "message-type", TQString() );
- if ( str == "warning" )
- d->extra()->validity->m_action = Action::Warning;
- else if ( str == "information" )
- d->extra()->validity->m_action = Action::Information;
- else if ( str == "stop" )
- d->extra()->validity->m_action = Action::Stop;
- else
- kdDebug()<<"validation : message type unknown :"<<str<<endl;
- }
-
- if ( error.hasAttributeNS( KoXmlNS::table, "display" ) )
- {
- kdDebug()<<" display message :"<<error.attributeNS( KoXmlNS::table, "display", TQString() )<<endl;
- d->extra()->validity->displayMessage = (error.attributeNS( KoXmlNS::table, "display", TQString() )=="true");
- }
- TQDomElement attrText = KoDom::namedItemNS( error, KoXmlNS::text, "p" );
- if ( !attrText.isNull() )
- d->extra()->validity->message = attrText.text();
- }
-}
-
-
-void Cell::loadOasisValidationValue( const TQStringList &listVal )
-{
- bool ok = false;
- kdDebug()<<" listVal[0] :"<<listVal[0]<<" listVal[1] :"<<listVal[1]<<endl;
-
- if ( d->extra()->validity->m_restriction == Restriction::Date )
- {
- d->extra()->validity->dateMin = TQDate::fromString( listVal[0] );
- d->extra()->validity->dateMax = TQDate::fromString( listVal[1] );
- }
- else if ( d->extra()->validity->m_restriction == Restriction::Time )
- {
- d->extra()->validity->timeMin = TQTime::fromString( listVal[0] );
- d->extra()->validity->timeMax = TQTime::fromString( listVal[1] );
- }
- else
- {
- d->extra()->validity->valMin = listVal[0].toDouble(&ok);
- if ( !ok )
- {
- d->extra()->validity->valMin = listVal[0].toInt(&ok);
- if ( !ok )
- kdDebug()<<" Try to parse this value :"<<listVal[0]<<endl;
-
-#if 0
- if ( !ok )
- d->extra()->validity->valMin = listVal[0];
-#endif
- }
- ok=false;
- d->extra()->validity->valMax = listVal[1].toDouble(&ok);
- if ( !ok )
- {
- d->extra()->validity->valMax = listVal[1].toInt(&ok);
- if ( !ok )
- kdDebug()<<" Try to parse this value :"<<listVal[1]<<endl;
-
-#if 0
- if ( !ok )
- d->extra()->validity->valMax = listVal[1];
-#endif
- }
- }
-}
-
-void Cell::loadOasisValidationCondition( TQString &valExpression )
-{
- TQString value;
- if (valExpression.find( "<=" )==0 )
- {
- value = valExpression.remove( 0,2 );
- d->extra()->validity->m_cond = Conditional::InferiorEqual;
- }
- else if (valExpression.find( ">=" )==0 )
- {
- value = valExpression.remove( 0,2 );
- d->extra()->validity->m_cond = Conditional::SuperiorEqual;
- }
- else if (valExpression.find( "!=" )==0 )
- {
- //add Differentto attribute
- value = valExpression.remove( 0,2 );
- d->extra()->validity->m_cond = Conditional::DifferentTo;
- }
- else if ( valExpression.find( "<" )==0 )
- {
- value = valExpression.remove( 0,1 );
- d->extra()->validity->m_cond = Conditional::Inferior;
- }
- else if(valExpression.find( ">" )==0 )
- {
- value = valExpression.remove( 0,1 );
- d->extra()->validity->m_cond = Conditional::Superior;
- }
- else if (valExpression.find( "=" )==0 )
- {
- value = valExpression.remove( 0,1 );
- d->extra()->validity->m_cond = Conditional::Equal;
- }
- else
- kdDebug()<<" I don't know how to parse it :"<<valExpression<<endl;
- if ( d->extra()->validity->m_restriction == Restriction::Date )
- {
- d->extra()->validity->dateMin = TQDate::fromString( value );
- }
- else if (d->extra()->validity->m_restriction == Restriction::Date )
- {
- d->extra()->validity->timeMin = TQTime::fromString( value );
- }
- else
- {
- bool ok = false;
- d->extra()->validity->valMin = value.toDouble(&ok);
- if ( !ok )
- {
- d->extra()->validity->valMin = value.toInt(&ok);
- if ( !ok )
- kdDebug()<<" Try to parse this value :"<<value<<endl;
-
-#if 0
- if ( !ok )
- d->extra()->validity->valMin = value;
-#endif
- }
- }
-}
-
-
-bool Cell::load( const TQDomElement & cell, int _xshift, int _yshift,
- Paste::Mode pm, Paste::Operation op, bool paste )
-{
- bool ok;
-
- //
- // First of all determine in which row and column this
- // cell belongs.
- //
- d->row = cell.attribute( "row" ).toInt( &ok ) + _yshift;
- if ( !ok ) return false;
- d->column = cell.attribute( "column" ).toInt( &ok ) + _xshift;
- if ( !ok ) return false;
-
- // Validation
- if ( d->row < 1 || d->row > KS_rowMax )
- {
- kdDebug(36001) << "Cell::load: Value out of Range Cell:row=" << d->row << endl;
- return false;
- }
- if ( d->column < 1 || d->column > KS_colMax )
- {
- kdDebug(36001) << "Cell::load: Value out of Range Cell:column=" << d->column << endl;
- return false;
- }
-
- //
- // Load formatting information.
- //
- TQDomElement f = cell.namedItem( "format" ).toElement();
- if ( !f.isNull()
- && ( (pm == Paste::Normal) || (pm == Paste::Format) || (pm == Paste::NoBorder) ) )
- {
- // send pm parameter. Didn't load Borders if pm==NoBorder
-
- if ( !format()->load( f, pm, paste ) )
- return false;
-
- if ( f.hasAttribute( "colspan" ) )
- {
- int i = f.attribute("colspan").toInt( &ok );
- if ( !ok ) return false;
- // Validation
- if ( i < 0 || i > KS_spanMax )
- {
- kdDebug(36001) << "Value out of range Cell::colspan=" << i << endl;
- return false;
- }
- if (i || d->hasExtra())
- d->extra()->extraXCells = i;
- if ( i > 0 )
- {
- setFlag(Flag_Merged);
- }
- }
-
- if ( f.hasAttribute( "rowspan" ) )
- {
- int i = f.attribute("rowspan").toInt( &ok );
- if ( !ok ) return false;
- // Validation
- if ( i < 0 || i > KS_spanMax )
- {
- kdDebug(36001) << "Value out of range Cell::rowspan=" << i << endl;
- return false;
- }
- if (i || d->hasExtra())
- d->extra()->extraYCells = i;
- if ( i > 0 )
- {
- setFlag(Flag_Merged);
- }
- }
-
- if ( testFlag( Flag_Merged ) )
- {
- if (d->hasExtra())
- mergeCells( d->column, d->row, d->extra()->extraXCells, d->extra()->extraYCells );
- }
-
- }
-
- //
- // Load the condition section of a cell.
- //
- TQDomElement conditionsElement = cell.namedItem( "condition" ).toElement();
- if ( !conditionsElement.isNull())
- {
- if (d->hasExtra())
- delete d->extra()->conditions;
- d->extra()->conditions = new Conditions( this );
- d->extra()->conditions->loadConditions( conditionsElement );
- d->extra()->conditions->checkMatches();
- }
- else if ((pm == Paste::Normal) || (pm == Paste::NoBorder))
- {
- //clear the conditional formatting
- if (d->hasExtra())
- {
- delete d->extra()->conditions;
- d->extra()->conditions = 0;
- }
- }
-
- TQDomElement validity = cell.namedItem( "validity" ).toElement();
- if ( !validity.isNull())
- {
- TQDomElement param = validity.namedItem( "param" ).toElement();
- if(!param.isNull())
- {
- d->extra()->validity = new Validity;
- if ( param.hasAttribute( "cond" ) )
- {
- d->extra()->validity->m_cond = (Conditional::Type) param.attribute("cond").toInt( &ok );
- if ( !ok )
- return false;
- }
- if ( param.hasAttribute( "action" ) )
- {
- d->extra()->validity->m_action = (Action::Type) param.attribute("action").toInt( &ok );
- if ( !ok )
- return false;
- }
- if ( param.hasAttribute( "allow" ) )
- {
- d->extra()->validity->m_restriction = (Restriction::Type) param.attribute("allow").toInt( &ok );
- if ( !ok )
- return false;
- }
- if ( param.hasAttribute( "valmin" ) )
- {
- d->extra()->validity->valMin = param.attribute("valmin").toDouble( &ok );
- if ( !ok )
- return false;
- }
- if ( param.hasAttribute( "valmax" ) )
- {
- d->extra()->validity->valMax = param.attribute("valmax").toDouble( &ok );
- if ( !ok )
- return false;
- }
- if ( param.hasAttribute( "displaymessage" ) )
- {
- d->extra()->validity->displayMessage = ( bool )param.attribute("displaymessage").toInt();
- }
- if ( param.hasAttribute( "displayvalidationinformation" ) )
- {
- d->extra()->validity->displayValidationInformation = ( bool )param.attribute("displayvalidationinformation").toInt();
- }
- if ( param.hasAttribute( "allowemptycell" ) )
- {
- d->extra()->validity->allowEmptyCell = ( bool )param.attribute("allowemptycell").toInt();
- }
- if ( param.hasAttribute("listvalidity") )
- {
- d->extra()->validity->listValidity=TQStringList::split(";", param.attribute("listvalidity") );
- }
- }
- TQDomElement inputTitle = validity.namedItem( "inputtitle" ).toElement();
- if (!inputTitle.isNull())
- {
- d->extra()->validity->titleInfo = inputTitle.text();
- }
- TQDomElement inputMessage = validity.namedItem( "inputmessage" ).toElement();
- if (!inputMessage.isNull())
- {
- d->extra()->validity->messageInfo = inputMessage.text();
- }
-
- TQDomElement title = validity.namedItem( "title" ).toElement();
- if (!title.isNull())
- {
- d->extra()->validity->title = title.text();
- }
- TQDomElement message = validity.namedItem( "message" ).toElement();
- if (!message.isNull())
- {
- d->extra()->validity->message = message.text();
- }
- TQDomElement timeMin = validity.namedItem( "timemin" ).toElement();
- if ( !timeMin.isNull() )
- {
- d->extra()->validity->timeMin = toTime(timeMin);
- }
- TQDomElement timeMax = validity.namedItem( "timemax" ).toElement();
- if ( !timeMax.isNull() )
- {
- d->extra()->validity->timeMax = toTime(timeMax);
- }
- TQDomElement dateMin = validity.namedItem( "datemin" ).toElement();
- if ( !dateMin.isNull() )
- {
- d->extra()->validity->dateMin = toDate(dateMin);
- }
- TQDomElement dateMax = validity.namedItem( "datemax" ).toElement();
- if ( !dateMax.isNull() )
- {
- d->extra()->validity->dateMax = toDate(dateMax);
- }
- }
- else if ((pm == Paste::Normal) || (pm == Paste::NoBorder))
- {
- // clear the validity
- removeValidity();
- }
-
- //
- // Load the comment
- //
- TQDomElement comment = cell.namedItem( "comment" ).toElement();
- if ( !comment.isNull() && ( pm == Paste::Normal || pm == Paste::Comment || pm == Paste::NoBorder ))
- {
- TQString t = comment.text();
- //t = t.stripWhiteSpace();
- format()->setComment( t );
- }
-
- //
- // The real content of the cell is loaded here. It is stored in
- // the "text" tag, which contains either a text or a CDATA section.
- //
- // TODO: make this suck less. We set data twice, in loadCellData, and
- // also here. Not good.
- TQDomElement text = cell.namedItem( "text" ).toElement();
-
- if ( !text.isNull() &&
- ( pm == Paste::Normal || pm == Paste::Text || pm == Paste::NoBorder || pm == Paste::Result ) )
- {
- /* older versions mistakenly put the datatype attribute on the cell
- instead of the text. Just move it over in case we're parsing
- an old document */
- if ( cell.hasAttribute( "dataType" ) ) // new docs
- text.setAttribute( "dataType", cell.attribute( "dataType" ) );
-
- TQDomElement result = cell.namedItem( "result" ).toElement();
- TQString txt = text.text();
- if ((pm == Paste::Result) && (txt[0] == '='))
- // paste text of the element, if we want to paste result
- // and the source cell contains a formula
- // note that we mustn't use setCellValue after this, or else we lose
- // all the formulas ...
- d->strText = result.text();
- else
- //otherwise copy everything
- loadCellData(text, op);
-
- if ( !result.isNull() )
- {
- TQString dataType;
- TQString t = result.text();
-
- if ( result.hasAttribute( "dataType" ) )
- dataType = result.attribute( "dataType" );
- if ( result.hasAttribute( "outStr" ) )
- {
- d->strOutText = result.attribute( "outStr" );
- if ( !d->strOutText.isEmpty() )
- clearFlag( Flag_TextFormatDirty );
- }
-
- bool clear = true;
- // boolean ?
- if( dataType == "Bool" )
- {
- if ( t == "false" )
- setValue( false );
- else if ( t == "true" )
- setValue( true );
- else
- clear = false;
- }
- else if( dataType == "Num" )
- {
- bool ok = false;
- double dd = t.toDouble( &ok );
- if ( ok )
- setValue ( dd );
- else
- clear = false;
- }
- else if( dataType == "Date" )
- {
- bool ok = false;
- double dd = t.toDouble( &ok );
- if ( ok )
- setValue ( dd );
- else
- {
- int pos = t.find( '/' );
- int year = t.mid( 0, pos ).toInt();
- int pos1 = t.find( '/', pos + 1 );
- int month = t.mid( pos + 1, ( ( pos1 - 1 ) - pos ) ).toInt();
- int day = t.right( t.length() - pos1 - 1 ).toInt();
- TQDate date( year, month, day );
- if ( date.isValid() )
- setValue( date );
- else
- clear = false;
- }
- }
- else if( dataType == "Time" )
- {
- bool ok = false;
- double dd = t.toDouble( &ok );
- if ( ok )
- setCellValue( dd );
- else
- {
- int hours = -1;
- int minutes = -1;
- int second = -1;
- int pos, pos1;
- pos = t.find( ':' );
- hours = t.mid( 0, pos ).toInt();
- pos1 = t.find( ':', pos + 1 );
- minutes = t.mid( pos + 1, ( ( pos1 - 1 ) - pos ) ).toInt();
- second = t.right( t.length() - pos1 - 1 ).toInt();
- TQTime time( hours, minutes, second );
- if ( time.isValid() )
- setValue( time );
- else
- clear = false;
- }
- }
- else
- {
- setValue( t );
- }
-
- // if ( clear )
- // clearFlag( Flag_CalcDirty );
- }
- }
-
- return true;
-}
-
-bool Cell::loadCellData(const TQDomElement & text, Paste::Operation op )
-{
- //TODO: use converter()->asString() to generate strText
-
- TQString t = text.text();
- t = t.stripWhiteSpace();
-
- setFlag(Flag_LayoutDirty);
- setFlag(Flag_TextFormatDirty);
-
- // A formula like =A1+A2 ?
- if( t[0] == '=' )
- {
- t = decodeFormula( t, d->column, d->row );
- setCellText (pasteOperation( t, d->strText, op ));
-
- setFlag(Flag_CalcDirty);
- clearAllErrors();
-
- if ( !makeFormula() )
- kdError(36001) << "ERROR: Syntax ERROR" << endl;
- }
- // rich text ?
- else if (t[0] == '!' )
- {
- // KSpread pre 1.4 stores hyperlink as rich text (first char is '!')
- // extract the link and the correspoding text
- // This is a rather dirty hack, but enough for KSpread generated XML
- bool inside_tag = false;
- TQString qml_text;
- TQString tag;
- TQString qml_link;
-
- for( unsigned i = 1; i < t.length(); i++ )
- {
- TQChar ch = t[i];
- if( ch == '<' )
- {
- if( !inside_tag )
- {
- inside_tag = true;
- tag = TQString();
- }
- }
- else if( ch == '>' )
- {
- if( inside_tag )
- {
- inside_tag = false;
- if( tag.startsWith( "a href=\"", true ) )
- if( tag.endsWith( "\"" ) )
- qml_link = tag.mid( 8, tag.length()-9 );
- tag = TQString();
- }
- }
- else
- {
- if( !inside_tag )
- qml_text += ch;
- else
- tag += ch;
- }
- }
-
- if( !qml_link.isEmpty() )
- d->extra()->link = qml_link;
- d->strText = qml_text;
- setValue( d->strText );
- }
- else
- {
- bool newStyleLoading = true;
- TQString dataType;
-
- if ( text.hasAttribute( "dataType" ) ) // new docs
- {
- dataType = text.attribute( "dataType" );
- }
- else // old docs: do the ugly solution of calling checkTextInput to parse the text
- {
- // ...except for date/time
- if (isDate() && ( t.contains('/') == 2 ))
- dataType = "Date";
- else if (isTime() && ( t.contains(':') == 2 ) )
- dataType = "Time";
- else
- {
- d->strText = pasteOperation( t, d->strText, op );
- checkTextInput();
- //kdDebug(36001) << "Cell::load called checkTextInput, got dataType=" << dataType << " t=" << t << endl;
- newStyleLoading = false;
- }
- }
-
- if ( newStyleLoading )
- {
- d->value = Value::empty();
- clearAllErrors();
-
- // boolean ?
- if( dataType == "Bool" )
- {
- bool val = (t.lower() == "true");
- setCellValue (val);
- }
-
- // number ?
- else if( dataType == "Num" )
- {
- bool ok = false;
- if (t.contains('.'))
- setValue ( Value( t.toDouble(&ok) ) ); // We save in non-localized format
- else
- setValue ( Value( t.toLong(&ok) ) );
- if ( !ok )
- {
- kdWarning(36001) << "Couldn't parse '" << t << "' as number." << endl;
- }
- /* We will need to localize the text version of the number */
- TDELocale* locale = format()->sheet()->doc()->locale();
-
- /* TDELocale::formatNumber requires the precision we want to return.
- */
- int precision = t.length() - t.find('.') - 1;
-
- if ( formatType() == Percentage_format )
- {
- if (value().isInteger())
- t = locale->formatNumber( value().asInteger() * 100 );
- else
- t = locale->formatNumber( value().asFloat() * 100.0, precision );
- d->strText = pasteOperation( t, d->strText, op );
- d->strText += '%';
- }
- else
- {
- if (value().isInteger())
- t = locale->formatLong(value().asInteger());
- else
- t = locale->formatNumber(value().asFloat(), precision);
- d->strText = pasteOperation( t, d->strText, op );
- }
- }
-
- // date ?
- else if( dataType == "Date" )
- {
- int pos = t.find('/');
- int year = t.mid(0,pos).toInt();
- int pos1 = t.find('/',pos+1);
- int month = t.mid(pos+1,((pos1-1)-pos)).toInt();
- int day = t.right(t.length()-pos1-1).toInt();
- setValue( TQDate(year,month,day) );
- if ( value().asDate().isValid() ) // Should always be the case for new docs
- d->strText = locale()->formatDate( value().asDate(), true );
- else // This happens with old docs, when format is set wrongly to date
- {
- d->strText = pasteOperation( t, d->strText, op );
- checkTextInput();
- }
- }
-
- // time ?
- else if( dataType == "Time" )
- {
- int hours = -1;
- int minutes = -1;
- int second = -1;
- int pos, pos1;
- pos = t.find(':');
- hours = t.mid(0,pos).toInt();
- pos1 = t.find(':',pos+1);
- minutes = t.mid(pos+1,((pos1-1)-pos)).toInt();
- second = t.right(t.length()-pos1-1).toInt();
- setValue( TQTime(hours,minutes,second) );
- if ( value().asTime().isValid() ) // Should always be the case for new docs
- d->strText = locale()->formatTime( value().asTime(), true );
- else // This happens with old docs, when format is set wrongly to time
- {
- d->strText = pasteOperation( t, d->strText, op );
- checkTextInput();
- }
- }
-
- else
- {
- // Set the cell's text
- d->strText = pasteOperation( t, d->strText, op );
- setValue( d->strText );
- }
- }
- }
-
- if ( text.hasAttribute( "outStr" ) ) // very new docs
- {
- d->strOutText = text.attribute( "outStr" );
- if ( !d->strOutText.isEmpty() )
- clearFlag( Flag_TextFormatDirty );
- }
-
- if ( !format()->sheet()->isLoading() )
- setCellText( d->strText );
-
- if ( d->hasExtra() && d->extra()->conditions )
- d->extra()->conditions->checkMatches();
-
- return true;
-}
-
-TQTime Cell::toTime(const TQDomElement &element)
-{
- //TODO: can't we use tryParseTime (after modification) instead?
- TQString t = element.text();
- t = t.stripWhiteSpace();
- int hours = -1;
- int minutes = -1;
- int second = -1;
- int pos, pos1;
- pos = t.find(':');
- hours = t.mid(0,pos).toInt();
- pos1 = t.find(':',pos+1);
- minutes = t.mid(pos+1,((pos1-1)-pos)).toInt();
- second = t.right(t.length()-pos1-1).toInt();
- setValue( Value( TQTime(hours,minutes,second)) );
- return value().asTime();
-}
-
-TQDate Cell::toDate(const TQDomElement &element)
-{
- TQString t = element.text();
- int pos;
- int pos1;
- int year = -1;
- int month = -1;
- int day = -1;
- pos = t.find('/');
- year = t.mid(0,pos).toInt();
- pos1 = t.find('/',pos+1);
- month = t.mid(pos+1,((pos1-1)-pos)).toInt();
- day = t.right(t.length()-pos1-1).toInt();
- setValue( Value( TQDate(year,month,day) ) );
- return value().asDate();
-}
-
-TQString Cell::pasteOperation( const TQString &new_text, const TQString &old_text, Paste::Operation op )
-{
- if ( op == Paste::OverWrite )
- return new_text;
-
- TQString tmp_op;
- TQString tmp;
- TQString old;
-
- if( !new_text.isEmpty() && new_text[0] == '=' )
- {
- tmp = new_text.right( new_text.length() - 1 );
- }
- else
- {
- tmp = new_text;
- }
-
- if ( old_text.isEmpty() &&
- ( op == Paste::Add || op == Paste::Mul || op == Paste::Sub || op == Paste::Div ) )
- {
- old = "=0";
- }
-
- if( !old_text.isEmpty() && old_text[0] == '=' )
- {
- old = old_text.right( old_text.length() - 1 );
- }
- else
- {
- old = old_text;
- }
-
- bool b1, b2;
- tmp.toDouble( &b1 );
- old.toDouble( &b2 );
- if (b1 && !b2 && old.length() == 0)
- {
- old = "0";
- b2 = true;
- }
-
- if( b1 && b2 )
- {
- switch( op )
- {
- case Paste::Add:
- tmp_op = TQString::number(old.toDouble()+tmp.toDouble());
- break;
- case Paste::Mul :
- tmp_op = TQString::number(old.toDouble()*tmp.toDouble());
- break;
- case Paste::Sub:
- tmp_op = TQString::number(old.toDouble()-tmp.toDouble());
- break;
- case Paste::Div:
- tmp_op = TQString::number(old.toDouble()/tmp.toDouble());
- break;
- default:
- Q_ASSERT( 0 );
- }
-
- setFlag(Flag_LayoutDirty);
- clearAllErrors();
-
- return tmp_op;
- }
- else if ( ( new_text[0] == '=' && old_text[0] == '=' ) ||
- ( b1 && old_text[0] == '=' ) || ( new_text[0] == '=' && b2 ) )
- {
- switch( op )
- {
- case Paste::Add :
- tmp_op="=("+old+")+"+"("+tmp+")";
- break;
- case Paste::Mul :
- tmp_op="=("+old+")*"+"("+tmp+")";
- break;
- case Paste::Sub:
- tmp_op="=("+old+")-"+"("+tmp+")";
- break;
- case Paste::Div:
- tmp_op="=("+old+")/"+"("+tmp+")";
- break;
- default :
- Q_ASSERT( 0 );
- }
-
- tmp_op = decodeFormula( tmp_op, d->column, d->row );
- setFlag(Flag_LayoutDirty);
- clearAllErrors();
-
- return tmp_op;
- }
-
- tmp = decodeFormula( new_text, d->column, d->row );
- setFlag(Flag_LayoutDirty);
- clearAllErrors();
-
- return tmp;
-}
-
-TQString Cell::testAnchor( int x, int y ) const
-{
- if( link().isEmpty() )
- return TQString();
-
- const Doc* doc = format()->sheet()->doc();
- int x1 = doc->zoomItX( d->textX );
- int y1 = doc->zoomItX( d->textY - d->textHeight );
- int x2 = doc->zoomItX( d->textX + d->textWidth );
- int y2 = doc->zoomItX( d->textY );
-
- if( x > x1 ) if( x < x2 )
- if( y > y1 ) if( y < y2 )
- return link();
-
- return TQString();
-}
-
-void Cell::sheetDies()
-{
- // Avoid unobscuring the cells in the destructor.
- if (d->hasExtra())
- {
- d->extra()->extraXCells = 0;
- d->extra()->extraYCells = 0;
- d->extra()->mergedXCells = 0;
- d->extra()->mergedYCells = 0;
- }
-
- //d->nextCell = 0;
- //d->previousCell = 0;
-}
-
-Cell::~Cell()
-{
- if ( d->nextCell )
- d->nextCell->setPreviousCell( d->previousCell );
- if ( d->previousCell )
- d->previousCell->setNextCell( d->nextCell );
-
- if (d->hasExtra())
- {
- delete d->extra()->validity;
- }
-
- // Unobscure cells.
- int extraXCells = d->hasExtra() ? d->extra()->extraXCells : 0;
- int extraYCells = d->hasExtra() ? d->extra()->extraYCells : 0;
- for( int x = 0; x <= extraXCells; ++x )
- for( int y = (x == 0) ? 1 : 0; // avoid looking at (+0,+0)
- y <= extraYCells; ++y )
- {
- Cell* cell = format()->sheet()->cellAt( d->column + x, d->row + y );
- if ( cell )
- cell->unobscure(this);
- }
-
- d->value = Value::empty();
-
- if (!isDefault())
- valueChanged (); //our value has been changed (is now null), but only if we aren't default
-
- delete d->format;
- delete d;
-}
-
-bool Cell::operator > ( const Cell & cell ) const
-{
- if ( value().isNumber() ) // ### what about bools ?
- {
- if ( cell.value().isNumber() )
- return value().asFloat() > cell.value().asFloat();
- else
- return false; // numbers are always < than texts
- }
- else if(isDate())
- {
- if( cell.isDate() )
- return value().asDate() > cell.value().asDate();
- else if (cell.value().isNumber())
- return true;
- else
- return false; //date are always < than texts and time
- }
- else if(isTime())
- {
- if( cell.isTime() )
- return value().asTime() > cell.value().asTime();
- else if( cell.isDate())
- return true; //time are always > than date
- else if( cell.value().isNumber())
- return true;
- else
- return false; //time are always < than texts
- }
- else
- {
- if ( Map::respectCase )
- return value().asString().compare(cell.value().asString()) > 0;
- else
- return ( value().asString() ).lower().compare(cell.value().asString().lower()) > 0;
- }
-}
-
-bool Cell::operator < ( const Cell & cell ) const
-{
- if ( value().isNumber() )
- {
- if ( cell.value().isNumber() )
- return value().asFloat() < cell.value().asFloat();
- else
- return true; // numbers are always < than texts
- }
- else if(isDate())
- {
- if( cell.isDate() )
- return value().asDateTime().date() < cell.value().asDateTime().date();
- else if( cell.value().isNumber())
- return false;
- else
- return true; //date are always < than texts and time
- }
- else if(isTime())
- {
- if( cell.isTime() )
- return value().asDateTime().time() < cell.value().asDateTime().time();
- else if(cell.isDate())
- return false; //time are always > than date
- else if( cell.value().isNumber())
- return false;
- else
- return true; //time are always < than texts
- }
- else
- {
- if ( Map::respectCase )
- return value().asString().compare(cell.value().asString()) < 0;
- else
- return ( value().asString() ).lower().compare(cell.value().asString().lower()) < 0;
- }
-}
-
-bool Cell::operator==( const Cell& other ) const
-{
- if ( d->strText != other.d->strText )
- return false;
- if ( d->value != other.d->value )
- return false;
- if ( *d->format != *other.d->format )
- return false;
- if ( d->hasExtra() )
- {
- if ( !other.d->hasExtra() )
- return false;
- if ( d->extra()->link != other.d->extra()->link )
- return false;
- if ( d->extra()->mergedXCells != other.d->extra()->mergedXCells )
- return false;
- if ( d->extra()->mergedYCells != other.d->extra()->mergedYCells )
- return false;
- if ( d->extra()->conditions )
- {
- if ( !other.d->extra()->conditions )
- return false;
- if ( *d->extra()->conditions != *other.d->extra()->conditions )
- return false;
- }
- if ( d->extra()->validity )
- {
- if ( !other.d->extra()->validity )
- return false;
- if ( *d->extra()->validity != *other.d->extra()->validity )
- return false;
- }
- }
- return true;
-}
-
-TQRect Cell::cellRect()
-{
- Q_ASSERT(!isDefault());
- return TQRect(TQPoint(d->column, d->row), TQPoint(d->column, d->row));
-}
-
-TQValueList<Conditional> Cell::conditionList() const
-{
- if ( !d->hasExtra() || !d->extra()->conditions )
- {
- TQValueList<Conditional> emptyList;
- return emptyList;
- }
-
- return d->extra()->conditions->conditionList();
-}
-
-void Cell::setConditionList( const TQValueList<Conditional> & newList )
-{
- if (d->hasExtra())
- delete d->extra()->conditions;
- d->extra()->conditions = new Conditions( this );
- d->extra()->conditions->setConditionList( newList );
- d->extra()->conditions->checkMatches();
-}
-
-bool Cell::hasError() const
-{
- return ( testFlag(Flag_ParseError) ||
- testFlag(Flag_CircularCalculation) ||
- testFlag(Flag_DependancyError));
-}
-
-void Cell::clearAllErrors()
-{
- clearFlag( Flag_ParseError );
- clearFlag( Flag_CircularCalculation );
- clearFlag( Flag_DependancyError );
-}
-
-bool Cell::calcDirtyFlag()
-{
- return isFormula() ? testFlag( Flag_CalcDirty ) : false;
-}
-
-bool Cell::layoutDirtyFlag() const
-{
- return testFlag( Flag_LayoutDirty );
-}
-
-void Cell::clearDisplayDirtyFlag()
-{
- clearFlag( Flag_DisplayDirty );
-}
-
-void Cell::setDisplayDirtyFlag()
-{
- setFlag( Flag_DisplayDirty );
-}
-
-bool Cell::doesMergeCells() const
-{
- return testFlag( Flag_Merged );
-}
-
-void Cell::clearFlag( CellFlags flag )
-{
- d->flags &= ~(TQ_UINT32)flag;
-}
-
-void Cell::setFlag( CellFlags flag )
-{
- d->flags |= (TQ_UINT32)flag;
-}
-
-bool Cell::testFlag( CellFlags flag ) const
-{
- return ( d->flags & (TQ_UINT32)flag );
-}
-
-
-void Cell::checkForNamedAreas( TQString & formula ) const
-{
- KSPLoadingInfo* loadinginfo = sheet()->doc()->loadingInfo();
- if(! loadinginfo) {
- kdDebug() << "Cell::checkForNamedAreas loadinginfo is NULL" << endl;
- return;
- }
-
- int l = formula.length();
- int i = 0;
- TQString word;
- int start = 0;
- while ( i < l )
- {
- if ( formula[i].isLetterOrNumber() )
- {
- word += formula[i];
- ++i;
- continue;
- }
- if ( !word.isEmpty() )
- {
- if ( loadinginfo->findWordInAreaList(word) )
- {
- formula = formula.replace( start, word.length(), "'" + word + "'" );
- l = formula.length();
- ++i;
- kdDebug() << "Formula: " << formula << ", L: " << l << ", i: " << i + 1 <<endl;
- }
- }
-
- ++i;
- word = "";
- start = i;
- }
- if ( !word.isEmpty() )
- {
- if ( loadinginfo->findWordInAreaList(word) )
- {
- formula = formula.replace( start, word.length(), "'" + word + "'" );
- l = formula.length();
- ++i;
- kdDebug() << "Formula: " << formula << ", L: " << l << ", i: " << i + 1 <<endl;
- }
- }
-}