You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
2827 lines
86 KiB
2827 lines
86 KiB
/* This file is part of the KDE project
|
|
Copyright (C) 2002 Norbert Andres <nandres@web.de>
|
|
Copyright (C) 2004 - 2005 Laurent Montel <montel@kde.org>
|
|
|
|
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 <float.h>
|
|
#include <math.h>
|
|
|
|
#include <tqcolor.h>
|
|
#include <tqfile.h>
|
|
#include <tqfont.h>
|
|
#include <tqpen.h>
|
|
#include <tqxml.h>
|
|
|
|
#include "opencalcimport.h"
|
|
|
|
#include <kdebug.h>
|
|
#include <KoDocumentInfo.h>
|
|
#include <kgenericfactory.h>
|
|
#include <kmessagebox.h>
|
|
#include <kmdcodec.h>
|
|
#include <KoFilterChain.h>
|
|
#include <KoGlobal.h>
|
|
#include <KoUnit.h>
|
|
#include <KoStyleStack.h>
|
|
#include <KoDom.h>
|
|
#include <ooutils.h>
|
|
|
|
#include <kspread_cell.h>
|
|
#include <kspread_condition.h>
|
|
#include <kspread_doc.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 <kspread_value.h>
|
|
|
|
#define SECSPERDAY (24 * 60 * 60)
|
|
|
|
using namespace KSpread;
|
|
|
|
class OpenCalcImportFactory : KGenericFactory<OpenCalcImport, KoFilter>
|
|
{
|
|
public:
|
|
OpenCalcImportFactory(void) : KGenericFactory<OpenCalcImport, KoFilter> ("kspreadopencalcimport")
|
|
{}
|
|
protected:
|
|
virtual void setupTranslations( void )
|
|
{
|
|
KGlobal::locale()->insertCatalogue( "kofficefilters" );
|
|
}
|
|
};
|
|
|
|
K_EXPORT_COMPONENT_FACTORY( libopencalcimport, OpenCalcImportFactory() )
|
|
|
|
OpenCalcImport::OpenCalcPoint::OpenCalcPoint( TQString const & str )
|
|
: isRange( false )
|
|
{
|
|
bool inQuote = false;
|
|
|
|
int l = str.length();
|
|
int colonPos = -1;
|
|
TQString range;
|
|
|
|
// tqreplace '.' with '!'
|
|
for ( int i = 0; i < l; ++i )
|
|
{
|
|
if ( str[i] == '$' )
|
|
continue;
|
|
if ( str[i] == '\'' )
|
|
{
|
|
inQuote = !inQuote;
|
|
}
|
|
else if ( str[i] == '.' )
|
|
{
|
|
if ( !inQuote )
|
|
{
|
|
if ( i != 0 && i != (colonPos + 1) ) // no empty table names
|
|
range += '!';
|
|
}
|
|
else
|
|
range += '.';
|
|
}
|
|
else if ( str[i] == ':' )
|
|
{
|
|
if ( !inQuote )
|
|
{
|
|
isRange = true;
|
|
colonPos = i;
|
|
}
|
|
range += ':';
|
|
}
|
|
else
|
|
range += str[i];
|
|
}
|
|
|
|
translation = range;
|
|
|
|
if ( isRange )
|
|
{
|
|
KSpread::Range newRange( range );
|
|
table = newRange.sheetName();
|
|
topLeft = newRange.range().topLeft();
|
|
botRight = newRange.range().bottomRight();
|
|
}
|
|
else
|
|
{
|
|
Point newPoint( range );
|
|
table = newPoint.sheetName();
|
|
topLeft = newPoint.pos();
|
|
botRight = newPoint.pos();
|
|
}
|
|
}
|
|
|
|
|
|
OpenCalcImport::OpenCalcImport( KoFilter *, const char *, const TQStringList & )
|
|
: KoFilter(),
|
|
m_styles( 17, true ),
|
|
m_defaultStyles( 17, true ),
|
|
m_formats( 17, true )
|
|
{
|
|
m_styles.setAutoDelete( true );
|
|
m_defaultStyles.setAutoDelete( true );
|
|
m_formats.setAutoDelete( true );
|
|
}
|
|
|
|
OpenCalcImport::~OpenCalcImport()
|
|
{
|
|
}
|
|
|
|
double timeToNum( int h, int m, int s )
|
|
{
|
|
int secs = h * 3600 + m * 60 + s;
|
|
return (double) secs / (double) SECSPERDAY;
|
|
}
|
|
|
|
bool OpenCalcImport::readRowFormat( TQDomElement & rowNode, TQDomElement * rowStyle,
|
|
Sheet * table, int & row, int & number,
|
|
bool isLast )
|
|
{
|
|
if ( rowNode.isNull() )
|
|
return false;
|
|
|
|
TQDomNode node;
|
|
if ( rowStyle )
|
|
{
|
|
node = rowStyle->firstChild();
|
|
kdDebug(30518) << "RowStyle: " << rowStyle << ", " << rowStyle->tagName() << endl;
|
|
}
|
|
|
|
double height = -1.0;
|
|
bool insertPageBreak = false;
|
|
Format tqlayout( table, table->doc()->styleManager()->defaultStyle() );
|
|
|
|
while( !node.isNull() )
|
|
{
|
|
TQDomElement property = node.toElement();
|
|
|
|
kdDebug(30518) << "Row: Child exists: " << property.tagName() << endl;
|
|
if ( !property.isNull() && property.localName() == "properties" && property.namespaceURI() == ooNS::style )
|
|
{
|
|
if ( property.hasAttributeNS( ooNS::style, "row-height" ) )
|
|
{
|
|
height = KoUnit::parseValue( property.attributeNS( ooNS::style, "row-height", TQString() ) , -1 );
|
|
}
|
|
|
|
if ( property.hasAttributeNS( ooNS::fo, "break-before" ) )
|
|
{
|
|
if ( property.attributeNS( ooNS::fo, "break-before", TQString() ) == "page" )
|
|
{
|
|
insertPageBreak = true;
|
|
}
|
|
}
|
|
|
|
loadStyleProperties( &tqlayout, property );
|
|
}
|
|
|
|
node = node.nextSibling();
|
|
}
|
|
|
|
if ( rowNode.hasAttributeNS( ooNS::table, "number-rows-repeated" ) )
|
|
{
|
|
bool ok = true;
|
|
int n = rowNode.attributeNS( ooNS::table, "number-rows-repeated", TQString() ).toInt( &ok );
|
|
if ( ok )
|
|
number = n;
|
|
kdDebug(30518) << "Row repeated: " << number << endl;
|
|
}
|
|
|
|
if ( isLast )
|
|
{
|
|
if ( number > 30 )
|
|
number = 30;
|
|
}
|
|
else
|
|
{
|
|
if ( number > 256 )
|
|
number = 256;
|
|
}
|
|
|
|
for ( int i = 0; i < number; ++i )
|
|
{
|
|
RowFormat * rowL = table->nonDefaultRowFormat( row );
|
|
rowL->copy( tqlayout );
|
|
|
|
if ( height != -1 )
|
|
{
|
|
kdDebug(30518) << "Setting row height to " << height << endl;
|
|
rowL->setHeight( int( height ) );
|
|
}
|
|
|
|
// if ( insertPageBreak ) TODO:
|
|
// rowL->setPageBreak( true )
|
|
|
|
// kdDebug(30518) << "Added RowFormat: " << row << endl;
|
|
++row;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
TQString OpenCalcImport::translatePar( TQString & par ) const
|
|
{
|
|
OpenCalcPoint point( par );
|
|
kdDebug(30518) << " Parameter: " << par << ", Translation: " << point.translation << endl;
|
|
|
|
return point.translation;
|
|
}
|
|
|
|
void OpenCalcImport::checkForNamedAreas( TQString & formula ) const
|
|
{
|
|
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.length() > 0 )
|
|
{
|
|
if ( m_namedAreas.tqfind( word ) != m_namedAreas.end() )
|
|
{
|
|
formula = formula.tqreplace( start, word.length(), "'" + word + "'" );
|
|
l = formula.length();
|
|
++i;
|
|
kdDebug(30518) << "Formula: " << formula << ", L: " << l << ", i: " << i + 1 <<endl;
|
|
}
|
|
}
|
|
|
|
++i;
|
|
word = "";
|
|
start = i;
|
|
}
|
|
if ( word.length() > 0 )
|
|
{
|
|
if ( m_namedAreas.tqfind( word ) != m_namedAreas.end() )
|
|
{
|
|
formula = formula.tqreplace( start, word.length(), "'" + word + "'" );
|
|
l = formula.length();
|
|
++i;
|
|
kdDebug(30518) << "Formula: " << formula << ", L: " << l << ", i: " << i + 1 <<endl;
|
|
}
|
|
}
|
|
}
|
|
|
|
void OpenCalcImport::convertFormula( TQString & text, TQString const & f ) const
|
|
{
|
|
kdDebug(30518) << "Parsing formula: " << f << endl;
|
|
|
|
TQString formula;
|
|
TQString parameter;
|
|
|
|
int l = f.length();
|
|
int p = 0;
|
|
|
|
while ( p < l )
|
|
{
|
|
if ( f[p] == '(' || f[p] == '[' )
|
|
{
|
|
break;
|
|
}
|
|
|
|
formula += f[p];
|
|
++p;
|
|
}
|
|
|
|
if ( parameter.isEmpty() )
|
|
{
|
|
checkForNamedAreas( formula );
|
|
}
|
|
|
|
kdDebug(30518) << "Formula: " << formula << ", Parameter: " << parameter << ", P: " << p << endl;
|
|
|
|
|
|
// replace formula names here
|
|
if ( formula == "=MULTIPLE.OPERATIONS" )
|
|
formula = "=MULTIPLEOPERATIONS";
|
|
|
|
TQString par;
|
|
bool isPar = false;
|
|
bool inQuote = false;
|
|
|
|
while ( p < l )
|
|
{
|
|
if ( f[p] == '"' )
|
|
{
|
|
inQuote = !inQuote;
|
|
parameter += '"';
|
|
}
|
|
else if ( f[p] == '[' )
|
|
{
|
|
if ( !inQuote )
|
|
isPar = true;
|
|
else
|
|
parameter += '[';
|
|
}
|
|
else if ( f[p] == ']' )
|
|
{
|
|
if ( inQuote )
|
|
{
|
|
parameter += ']';
|
|
continue;
|
|
}
|
|
|
|
isPar = false;
|
|
parameter += translatePar( par );
|
|
par = "";
|
|
}
|
|
else if ( isPar )
|
|
{
|
|
par += f[p];
|
|
}
|
|
else if ( f[p] == '=' ) // TODO: check if StarCalc has a '==' sometimes
|
|
{
|
|
if ( inQuote )
|
|
parameter += '=';
|
|
else
|
|
parameter += "==";
|
|
}
|
|
else if ( f[p] == ')' )
|
|
{
|
|
if ( !inQuote )
|
|
parameter += ")";
|
|
}
|
|
else
|
|
parameter += f[p];
|
|
|
|
++p;
|
|
if ( p == l )
|
|
checkForNamedAreas( parameter );
|
|
}
|
|
|
|
text = formula + parameter;
|
|
kdDebug(30518) << "New formula: " << text << endl;
|
|
}
|
|
|
|
bool OpenCalcImport::readCells( TQDomElement & rowNode, Sheet * table, int row, int & columns )
|
|
{
|
|
bool ok = true;
|
|
int spanC = 1;
|
|
int spanR = 1;
|
|
//Cell* defCell = table->defaultCell();
|
|
|
|
TQDomNode cellNode = KoDom::namedItemNS( rowNode, ooNS::table, "table-cell" );
|
|
|
|
while ( !cellNode.isNull() )
|
|
{
|
|
spanR = 1; spanC = 1;
|
|
|
|
TQDomElement e = cellNode.toElement();
|
|
if ( e.isNull() )
|
|
{
|
|
++columns;
|
|
|
|
cellNode = cellNode.nextSibling();
|
|
continue;
|
|
}
|
|
|
|
Cell* cell = 0;
|
|
|
|
kdDebug(30518) << " Cell: " << columns << ", " << row << endl;
|
|
|
|
// ="3" table:number-rows-spanned="1"
|
|
if ( e.hasAttributeNS( ooNS::table, "number-columns-spanned" ) )
|
|
{
|
|
int span = e.attributeNS( ooNS::table, "number-columns-spanned", TQString() ).toInt( &ok );
|
|
if ( ok )
|
|
spanC = span;
|
|
}
|
|
if ( e.hasAttributeNS( ooNS::table, "number-rows-spanned" ) )
|
|
{
|
|
int span = e.attributeNS( ooNS::table, "number-rows-spanned", TQString() ).toInt( &ok );
|
|
if ( ok )
|
|
spanR = span;
|
|
}
|
|
|
|
TQString text;
|
|
TQDomElement textP = KoDom::namedItemNS( e, ooNS::text, "p" );
|
|
if ( !textP.isNull() )
|
|
{
|
|
TQDomElement subText = textP.firstChild().toElement(); // ## wrong
|
|
if ( !subText.isNull() )
|
|
{
|
|
// something in <text:p>, e.g. links
|
|
text = subText.text();
|
|
|
|
if ( subText.hasAttributeNS( ooNS::xlink, "href" ) )
|
|
{
|
|
TQString link = subText.attributeNS( ooNS::xlink, "href", TQString() );
|
|
if ( link[0]=='#' )
|
|
link=link.remove( 0, 1 );
|
|
if ( !cell )
|
|
cell = table->nonDefaultCell( columns, row );
|
|
cell->setLink( link );
|
|
}
|
|
}
|
|
else
|
|
text = textP.text(); // our text, could contain formating for value or result of formula
|
|
}
|
|
TQDomElement annotation = KoDom::namedItemNS( e, ooNS::office, "annotation" );
|
|
if ( !annotation.isNull() )
|
|
{
|
|
TQString comment;
|
|
TQDomNode node = annotation.firstChild();
|
|
while( !node.isNull() )
|
|
{
|
|
TQDomElement commentElement = node.toElement();
|
|
if( !commentElement.isNull() )
|
|
if ( commentElement.localName() == "p" && e.namespaceURI()==ooNS::text)
|
|
{
|
|
if( !comment.isEmpty() ) comment.append( '\n' );
|
|
comment.append( commentElement.text() );
|
|
}
|
|
|
|
node = node.nextSibling();
|
|
}
|
|
|
|
if( !comment.isEmpty() )
|
|
{
|
|
if ( !cell )
|
|
cell = table->nonDefaultCell( columns, row );
|
|
kdDebug(30518)<<" columns :"<<columns<<" row :"<<row<<endl;
|
|
cell->format()->setComment( comment );
|
|
}
|
|
}
|
|
|
|
kdDebug(30518) << "Contains: " << text << endl;
|
|
bool isFormula = false;
|
|
|
|
if ( e.hasAttributeNS( ooNS::table, "style-name" ) )
|
|
{
|
|
if ( !cell )
|
|
cell = table->nonDefaultCell( columns, row );
|
|
|
|
TQString psName( "Default" );
|
|
if ( e.hasAttributeNS( ooNS::style, "tqparent-style-name" ) )
|
|
psName = e.attributeNS( ooNS::style, "tqparent-style-name", TQString() );
|
|
|
|
kdDebug(30518) << "Default style: " << psName << endl;
|
|
Format * tqlayout = m_defaultStyles[psName];
|
|
|
|
if ( tqlayout )
|
|
cell->format()->copy( *tqlayout );
|
|
|
|
TQDomElement * st = 0;
|
|
if ( e.hasAttributeNS( ooNS::table, "style-name" ) )
|
|
{
|
|
kdDebug(30518) << "Style: " << e.attributeNS( ooNS::table, "style-name", TQString() ) << endl;
|
|
st = m_styles[ e.attributeNS( ooNS::table, "style-name", TQString() ) ];
|
|
}
|
|
if ( st )
|
|
{
|
|
kdDebug(30518) << "Style: adapting " << endl;
|
|
TQDomNode node = st->firstChild();
|
|
bool foundValidation = false;
|
|
while( !node.isNull() )
|
|
{
|
|
TQDomElement property = node.toElement();
|
|
if ( !property.isNull() )
|
|
{
|
|
kdDebug(30518)<<"property.tagName() :"<<property.tagName()<<endl;
|
|
if ( property.localName()=="map" && property.namespaceURI() == ooNS::style && !foundValidation)
|
|
{
|
|
loadCondition( cell, property );
|
|
foundValidation = true;
|
|
}
|
|
if ( property.localName() == "properties" && property.namespaceURI() == ooNS::style )
|
|
{
|
|
loadStyleProperties( cell->format(), property );
|
|
if ( cell->format()->getAngle( columns, row ) != 0 )
|
|
{
|
|
TQFontMetrics fm( cell->format()->textFont( columns, row ) );
|
|
int tmpAngle = cell->format()->getAngle( columns, row );
|
|
int textHeight = static_cast<int>( cos( tmpAngle * M_PI / 180 )
|
|
* ( fm.ascent() + fm.descent() )
|
|
+ abs ( ( int )( fm.width( cell->strOutText() )
|
|
* sin( tmpAngle * M_PI / 180 ) ) ) );
|
|
/*
|
|
int textWidth = static_cast<int>( abs ( ( int ) ( sin( tmpAngle * M_PI / 180 )
|
|
* ( fm.ascent() + fm.descent() ) ) )
|
|
+ fm.width( cell->strOutText() )
|
|
* cos( tmpAngle * M_PI / 180 ) );
|
|
*/
|
|
kdDebug(30518) << "Rotation: height: " << textHeight << endl;
|
|
|
|
RowFormat * l = table->rowFormat( row );
|
|
if ( l->height() < textHeight )
|
|
{
|
|
if ( l->isDefault() )
|
|
l = table->nonDefaultRowFormat( row );
|
|
|
|
l->setHeight( textHeight + 2 );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
node = node.nextSibling();
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ( !cell )
|
|
cell = table->nonDefaultCell( columns, row );
|
|
|
|
TQString psName( "Default" );
|
|
kdDebug(30518) << "Default style: " << psName << endl;
|
|
Format * tqlayout = m_defaultStyles[psName];
|
|
|
|
if ( tqlayout )
|
|
cell->format()->copy( *tqlayout );
|
|
}
|
|
if ( e.hasAttributeNS( ooNS::table, "formula" ) )
|
|
{
|
|
isFormula = true;
|
|
TQString formula;
|
|
convertFormula( formula, e.attributeNS( ooNS::table, "formula", TQString() ) );
|
|
|
|
if ( !cell )
|
|
cell = table->nonDefaultCell( columns, row );
|
|
cell->setCellText( formula );
|
|
}
|
|
if ( e.hasAttributeNS( ooNS::table, "validation-name" ) )
|
|
{
|
|
kdDebug(30518)<<" Celle has a validation :"<<e.attributeNS( ooNS::table, "validation-name", TQString() )<<endl;
|
|
loadOasisValidation( cell->getValidity(), e.attributeNS( ooNS::table, "validation-name", TQString() ) );
|
|
}
|
|
if ( e.hasAttributeNS( ooNS::table, "value-type" ) )
|
|
{
|
|
if ( !cell )
|
|
cell = table->nonDefaultCell( columns, row );
|
|
|
|
cell->setCellText( text );
|
|
|
|
TQString value = e.attributeNS( ooNS::table, "value", TQString() );
|
|
TQString type = e.attributeNS( ooNS::table, "value-type", TQString() );
|
|
|
|
kdDebug(30518) << "Value: " << value << ", type: " << type << endl;
|
|
|
|
bool ok = false;
|
|
double dv = 0.0;
|
|
|
|
if ( ( type == "float" ) || ( type == "currency" ) )
|
|
{
|
|
dv = value.toDouble( &ok );
|
|
if ( ok )
|
|
{
|
|
if ( !isFormula )
|
|
cell->setValue( dv );
|
|
|
|
if ( type == "currency" )
|
|
{
|
|
cell->format()->setCurrency( 1, e.attributeNS( ooNS::table, "currency", TQString() ) );
|
|
cell->format()->setFormatType( Money_format );
|
|
}
|
|
}
|
|
}
|
|
else
|
|
if ( type == "percentage" )
|
|
{
|
|
dv = value.toDouble( &ok );
|
|
if ( ok )
|
|
{
|
|
if ( !isFormula )
|
|
cell->setValue( dv );
|
|
//TODO fixme
|
|
//cell->setFactor( 100 );
|
|
// TODO: replace with custom...
|
|
cell->format()->setFormatType( Percentage_format );
|
|
}
|
|
}
|
|
else if ( type == "boolean" )
|
|
{
|
|
if ( value.isEmpty() )
|
|
value = e.attributeNS( ooNS::table, "boolean-value", TQString() );
|
|
|
|
kdDebug(30518) << "Type: boolean" << endl;
|
|
if ( value == "true" )
|
|
cell->setValue( true );
|
|
else
|
|
cell->setValue( false );
|
|
ok = true;
|
|
cell->format()->setFormatType( Custom_format );
|
|
}
|
|
else if ( type == "date" )
|
|
{
|
|
if ( value.isEmpty() )
|
|
value = e.attributeNS( ooNS::table, "date-value", TQString() );
|
|
kdDebug(30518) << "Type: date, value: " << value << endl;
|
|
|
|
// "1980-10-15"
|
|
int year=0, month=0, day=0;
|
|
ok = false;
|
|
|
|
int p1 = value.tqfind( '-' );
|
|
if ( p1 > 0 )
|
|
year = value.left( p1 ).toInt( &ok );
|
|
|
|
kdDebug(30518) << "year: " << value.left( p1 ) << endl;
|
|
|
|
int p2 = value.tqfind( '-', ++p1 );
|
|
|
|
if ( ok )
|
|
month = value.mid( p1, p2 - p1 ).toInt( &ok );
|
|
|
|
kdDebug(30518) << "month: " << value.mid( p1, p2 - p1 ) << endl;
|
|
|
|
if ( ok )
|
|
day = value.right( value.length() - p2 - 1 ).toInt( &ok );
|
|
|
|
kdDebug(30518) << "day: " << value.right( value.length() - p2 ) << endl;
|
|
|
|
if ( ok )
|
|
{
|
|
TQDateTime dt( TQDate( year, month, day ) );
|
|
// KSpreadValue kval( dt );
|
|
// cell->setValue( kval );
|
|
cell->setValue( TQDate( year, month, day ) );
|
|
kdDebug(30518) << "Set TQDate: " << year << " - " << month << " - " << day << endl;
|
|
}
|
|
}
|
|
else if ( type == "time" )
|
|
{
|
|
if ( value.isEmpty() )
|
|
value = e.attributeNS( ooNS::table, "time-value", TQString() );
|
|
|
|
kdDebug(30518) << "Type: time: " << value << endl;
|
|
// "PT15H10M12S"
|
|
int hours=0, minutes=0, seconds=0;
|
|
int l = value.length();
|
|
TQString num;
|
|
|
|
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(30518) << "Num: " << num << endl;
|
|
|
|
num = "";
|
|
if ( !ok )
|
|
break;
|
|
}
|
|
|
|
kdDebug(30518) << "Hours: " << hours << ", " << minutes << ", " << seconds << endl;
|
|
|
|
if ( ok )
|
|
{
|
|
// KSpreadValue kval( timeToNum( hours, minutes, seconds ) );
|
|
// cell->setValue( kval );
|
|
cell->setValue( TQTime( hours % 24, minutes, seconds ) );
|
|
cell->format()->setFormatType( Custom_format );
|
|
}
|
|
}
|
|
|
|
|
|
if ( !ok ) // just in case we couldn't set the value directly
|
|
cell->setCellText( text );
|
|
}
|
|
else if ( !text.isEmpty() )
|
|
{
|
|
if ( !cell )
|
|
cell = table->nonDefaultCell( columns, row );
|
|
cell->setCellText( text );
|
|
}
|
|
|
|
if ( spanR > 1 || spanC > 1 )
|
|
{
|
|
if ( !cell )
|
|
cell = table->nonDefaultCell( columns, row );
|
|
cell->mergeCells( columns, row, spanC - 1, spanR - 1 );
|
|
}
|
|
|
|
cellNode = cellNode.nextSibling();
|
|
|
|
if ( e.hasAttributeNS( ooNS::table, "number-columns-repeated" ) )
|
|
{
|
|
// copy cell from left
|
|
bool ok = false;
|
|
int number = e.attributeNS( ooNS::table, "number-columns-repeated", TQString() ).toInt( &ok );
|
|
Cell* cellDest = 0;
|
|
|
|
// don't repeat more than 10 if it is the last cell and empty
|
|
if ( !ok || cellNode.isNull() )
|
|
{
|
|
if ( number > 10 )
|
|
number = 10;
|
|
}
|
|
|
|
for ( int i = 1; i < number; ++i )
|
|
{
|
|
++columns;
|
|
|
|
if ( cell )
|
|
{
|
|
cellDest = table->nonDefaultCell( columns, row );
|
|
cellDest->copyAll( cell );
|
|
}
|
|
}
|
|
}
|
|
|
|
++columns;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
void OpenCalcImport::loadCondition( Cell*cell,const TQDomElement &property )
|
|
{
|
|
kdDebug(30518)<<"void OpenCalcImport::loadCondition( Cell*cell,const TQDomElement &property )*******\n";
|
|
loadOasisCondition( cell, property );
|
|
}
|
|
|
|
void OpenCalcImport::loadOasisCondition(Cell*cell,const TQDomElement &property )
|
|
{
|
|
TQDomElement elementItem( property );
|
|
StyleManager * manager = cell->sheet()->doc()->styleManager();
|
|
|
|
TQValueList<Conditional> cond;
|
|
while ( !elementItem.isNull() )
|
|
{
|
|
kdDebug(30518)<<"elementItem.tagName() :"<<elementItem.tagName()<<endl;
|
|
|
|
if ( elementItem.localName()== "map" && property.namespaceURI() == ooNS::style )
|
|
{
|
|
bool ok = true;
|
|
kdDebug(30518)<<"elementItem.attribute(style:condition ) :"<<elementItem.attributeNS( ooNS::style, "condition", TQString() )<<endl;
|
|
Conditional newCondition;
|
|
loadOasisConditionValue( elementItem.attributeNS( ooNS::style, "condition", TQString() ), newCondition );
|
|
if ( elementItem.hasAttributeNS( ooNS::style, "apply-style-name" ) )
|
|
{
|
|
kdDebug(30518)<<"elementItem.attribute( style:apply-style-name ) :"<<elementItem.attributeNS( ooNS::style, "apply-style-name", TQString() )<<endl;
|
|
newCondition.styleName = new TQString( elementItem.attributeNS( ooNS::style, "apply-style-name", TQString() ) );
|
|
newCondition.style = manager->style( *newCondition.styleName );
|
|
if ( !newCondition.style )
|
|
ok = false;
|
|
else
|
|
ok = true;
|
|
}
|
|
|
|
if ( ok )
|
|
cond.append( newCondition );
|
|
else
|
|
kdDebug(30518) << "Error loading condition " << elementItem.nodeName()<< endl;
|
|
}
|
|
elementItem = elementItem.nextSibling().toElement();
|
|
}
|
|
if ( !cond.isEmpty() )
|
|
cell->setConditionList( cond );
|
|
}
|
|
|
|
void OpenCalcImport::loadOasisConditionValue( const TQString &styleCondition, Conditional &newCondition )
|
|
{
|
|
TQString val( styleCondition );
|
|
if ( val.tqcontains( "cell-content()" ) )
|
|
{
|
|
val = val.remove( "cell-content()" );
|
|
loadOasisCondition( val,newCondition );
|
|
}
|
|
//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 ( val.tqcontains( "cell-content-is-between(" ) )
|
|
{
|
|
val = val.remove( "cell-content-is-between(" );
|
|
val = val.remove( ")" );
|
|
TQStringList listVal = TQStringList::split( "," , val );
|
|
loadOasisValidationValue( listVal, newCondition );
|
|
newCondition.cond = Conditional::Between;
|
|
}
|
|
if ( val.tqcontains( "cell-content-is-not-between(" ) )
|
|
{
|
|
val = val.remove( "cell-content-is-not-between(" );
|
|
val = val.remove( ")" );
|
|
TQStringList listVal = TQStringList::split( ",", val );
|
|
loadOasisValidationValue( listVal,newCondition );
|
|
newCondition.cond = Conditional::Different;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
void OpenCalcImport::loadOasisCondition( TQString &valExpression, Conditional &newCondition )
|
|
{
|
|
TQString value;
|
|
if (valExpression.tqfind( "<=" )==0 )
|
|
{
|
|
value = valExpression.remove( 0,2 );
|
|
newCondition.cond = Conditional::InferiorEqual;
|
|
}
|
|
else if (valExpression.tqfind( ">=" )==0 )
|
|
{
|
|
value = valExpression.remove( 0,2 );
|
|
newCondition.cond = Conditional::SuperiorEqual;
|
|
}
|
|
else if (valExpression.tqfind( "!=" )==0 )
|
|
{
|
|
//add Differentto attribute
|
|
value = valExpression.remove( 0,2 );
|
|
newCondition.cond = Conditional::DifferentTo;
|
|
}
|
|
else if ( valExpression.tqfind( "<" )==0 )
|
|
{
|
|
value = valExpression.remove( 0,1 );
|
|
newCondition.cond = Conditional::Inferior;
|
|
}
|
|
else if(valExpression.tqfind( ">" )==0 )
|
|
{
|
|
value = valExpression.remove( 0,1 );
|
|
newCondition.cond = Conditional::Superior;
|
|
}
|
|
else if (valExpression.tqfind( "=" )==0 )
|
|
{
|
|
value = valExpression.remove( 0,1 );
|
|
newCondition.cond = Conditional::Equal;
|
|
}
|
|
else
|
|
kdDebug(30518)<<" I don't know how to parse it :"<<valExpression<<endl;
|
|
kdDebug(30518)<<" value :"<<value<<endl;
|
|
bool ok = false;
|
|
newCondition.val1 = value.toDouble(&ok);
|
|
if ( !ok )
|
|
{
|
|
newCondition.val1 = value.toInt(&ok);
|
|
if ( !ok )
|
|
{
|
|
newCondition.strVal1 = new TQString( value );
|
|
kdDebug(30518)<<" Try to parse this value :"<<value<<endl;
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
|
|
void OpenCalcImport::loadOasisValidationValue( const TQStringList &listVal, Conditional &newCondition )
|
|
{
|
|
bool ok = false;
|
|
kdDebug(30518)<<" listVal[0] :"<<listVal[0]<<" listVal[1] :"<<listVal[1]<<endl;
|
|
|
|
newCondition.val1 = listVal[0].toDouble(&ok);
|
|
if ( !ok )
|
|
{
|
|
newCondition.val1 = listVal[0].toInt(&ok);
|
|
if ( !ok )
|
|
{
|
|
newCondition.strVal1 = new TQString( listVal[0] );
|
|
kdDebug(30518)<<" Try to parse this value :"<<listVal[0]<<endl;
|
|
}
|
|
}
|
|
ok=false;
|
|
newCondition.val2 = listVal[1].toDouble(&ok);
|
|
if ( !ok )
|
|
{
|
|
newCondition.val2 = listVal[1].toInt(&ok);
|
|
if ( !ok )
|
|
{
|
|
newCondition.strVal2 = new TQString( listVal[1] );
|
|
kdDebug(30518)<<" Try to parse this value :"<<listVal[1]<<endl;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
bool OpenCalcImport::readRowsAndCells( TQDomElement & content, Sheet * table )
|
|
{
|
|
kdDebug(30518) << endl << "Reading in rows " << endl;
|
|
|
|
int i = 1;
|
|
int row = 1;
|
|
int columns = 1;
|
|
int backupRow = 1;
|
|
TQDomElement * rowStyle = 0;
|
|
//Cell* cell = 0;
|
|
//Cell* cellDest = 0;
|
|
//Cell* defCell = table->defaultCell();
|
|
TQDomNode rowNode = KoDom::namedItemNS( content, ooNS::table, "table-row" );
|
|
|
|
while ( !rowNode.isNull() )
|
|
{
|
|
bool collapsed = false;
|
|
|
|
int number = 1;
|
|
TQDomElement r = rowNode.toElement();
|
|
|
|
if ( r.isNull() )
|
|
return false;
|
|
|
|
if ( r.hasAttributeNS( ooNS::table, "style-name" ) )
|
|
{
|
|
TQString style = r.attributeNS( ooNS::table, "style-name", TQString() );
|
|
rowStyle = m_styles[ style ];
|
|
kdDebug(30518) << "Row style: " << style << endl;
|
|
}
|
|
|
|
collapsed = ( r.attributeNS( ooNS::table, "visibility", TQString() ) == "collapse" );
|
|
|
|
backupRow = row;
|
|
|
|
rowNode = rowNode.nextSibling();
|
|
|
|
if ( !readRowFormat( r, rowStyle, table, row, number, rowNode.isNull() ) ) // updates "row"
|
|
return false;
|
|
|
|
if ( !readCells( r, table, backupRow, columns ) )
|
|
return false;
|
|
|
|
RowFormat * srcLayout = table->nonDefaultRowFormat( backupRow );
|
|
RowFormat * tqlayout = 0;
|
|
|
|
if ( collapsed )
|
|
srcLayout->setHide( true );
|
|
|
|
for ( i = 1; i < number; ++i )
|
|
{
|
|
tqlayout = table->nonDefaultRowFormat( backupRow + i );
|
|
|
|
tqlayout->copy( *srcLayout );
|
|
|
|
/*
|
|
* TODO: Test: do we need to copy the cells, too?
|
|
* if so we will probably also need to copy them for repeated col layouts.
|
|
for ( j = 1; j <= columns; ++j )
|
|
{
|
|
Cell* cell = table->cellAt( j, backupRow );
|
|
|
|
kdDebug(30518) << "Cell: " << cell << "DefCell: " << defCell << endl;
|
|
if ( cell && (cell != defCell) )
|
|
{
|
|
cellDest = table->nonDefaultCell( j, backupRow + i );
|
|
cellDest->copyAll( cell );
|
|
}
|
|
}
|
|
*/
|
|
}
|
|
|
|
rowStyle = 0;
|
|
columns = 1;
|
|
}
|
|
|
|
kdDebug(30518) << "Reading in rows done" << endl << endl;
|
|
|
|
return true;
|
|
}
|
|
|
|
bool OpenCalcImport::readColLayouts( TQDomElement & content, Sheet * table )
|
|
{
|
|
kdDebug(30518) << endl << "Reading in columns..." << endl;
|
|
|
|
TQDomNode colLayout = KoDom::namedItemNS( content, ooNS::table, "table-column" );
|
|
int column = 1;
|
|
|
|
while ( !colLayout.isNull() )
|
|
{
|
|
if ( colLayout.nodeName() != "table:table-column" )
|
|
return true; // all cols read in.
|
|
|
|
TQDomElement e = colLayout.toElement();
|
|
|
|
if ( e.isNull() )
|
|
return false; // error, that's it...
|
|
|
|
kdDebug(30518) << "New column: " << column << endl;
|
|
|
|
int number = 1;
|
|
double width = -1.0;
|
|
bool collapsed = ( e.attributeNS( ooNS::table, "visibility", TQString() ) == "collapse" );
|
|
bool insertPageBreak = false;
|
|
Format styleLayout( table, table->doc()->styleManager()->defaultStyle() );
|
|
|
|
kdDebug(30518) << "Check table:number-columns-repeated" << endl;
|
|
if ( e.hasAttributeNS( ooNS::table, "number-columns-repeated" ) )
|
|
{
|
|
bool ok = true;
|
|
number = e.attributeNS( ooNS::table, "number-columns-repeated", TQString() ).toInt( &ok );
|
|
if ( !ok )
|
|
number = 1;
|
|
|
|
kdDebug(30518) << "Repeated: " << number << endl;
|
|
}
|
|
|
|
kdDebug(30518) << "Checking table:default-cell-style-name" << endl;
|
|
if ( e.hasAttributeNS( ooNS::table, "default-cell-style-name" ) )
|
|
{
|
|
TQString n( e.attributeNS( ooNS::table, "default-cell-style-name", TQString() ) );
|
|
kdDebug(30518) << "Has attribute default-cell-style-name: " << n << endl;
|
|
Format * defaultStyle = m_defaultStyles[ n ];
|
|
if ( !defaultStyle )
|
|
{
|
|
TQString name = e.attributeNS( ooNS::table, "default-cell-style-name", TQString() );
|
|
TQDomElement * st = m_styles[ name ];
|
|
|
|
kdDebug(30518) << "Default cell style: " << name << endl;
|
|
|
|
if ( st && !st->isNull() )
|
|
{
|
|
Format * tqlayout = new Format( 0, m_doc->styleManager()->defaultStyle() );
|
|
|
|
readInStyle( tqlayout, *st );
|
|
|
|
m_defaultStyles.insert( name, tqlayout );
|
|
kdDebug(30518) << "Insert default cell style: " << name << endl;
|
|
|
|
defaultStyle = tqlayout;
|
|
}
|
|
}
|
|
|
|
if ( defaultStyle )
|
|
{
|
|
// kdDebug(30518) << "Copying default style, Font: " << defaultStyle->font().toString() << endl;
|
|
styleLayout.copy( *defaultStyle );
|
|
}
|
|
}
|
|
|
|
TQDomElement * colStyle = 0;
|
|
if ( e.hasAttributeNS( ooNS::table, "style-name" ) )
|
|
{
|
|
TQString style = e.attributeNS( ooNS::table, "style-name", TQString() );
|
|
colStyle = m_styles[ style ];
|
|
|
|
kdDebug(30518) << "Col Style: " << style << endl;
|
|
}
|
|
|
|
TQDomNode node;
|
|
|
|
if ( colStyle )
|
|
node = colStyle->firstChild();
|
|
|
|
while( !node.isNull() )
|
|
{
|
|
TQDomElement property = node.toElement();
|
|
if ( !property.isNull() && property.localName() == "properties" && property.namespaceURI() == ooNS::style )
|
|
{
|
|
if ( property.hasAttributeNS( ooNS::style, "column-width" ) )
|
|
{
|
|
TQString sWidth = property.attributeNS( ooNS::style, "column-width", TQString() );
|
|
width = KoUnit::parseValue( property.attributeNS( ooNS::style, "column-width", TQString() ), width );
|
|
kdDebug(30518) << "Col Width: " << sWidth << endl;
|
|
}
|
|
|
|
if ( property.hasAttributeNS( ooNS::fo, "break-before" ) )
|
|
{
|
|
if ( property.attributeNS( ooNS::fo, "break-before", TQString() ) == "page" )
|
|
{
|
|
insertPageBreak = true;
|
|
}
|
|
}
|
|
|
|
loadStyleProperties( &styleLayout, property );
|
|
}
|
|
|
|
node = node.nextSibling();
|
|
}
|
|
|
|
colLayout = colLayout.nextSibling();
|
|
|
|
if ( colLayout.isNull() && ( number > 30 ) )
|
|
number = 30;
|
|
|
|
for ( int i = 0; i < number; ++i )
|
|
{
|
|
kdDebug(30518) << "Inserting colLayout: " << column << endl;
|
|
|
|
ColumnFormat * col = new ColumnFormat( table, column );
|
|
col->copy( styleLayout );
|
|
if ( width != -1.0 )
|
|
col->setWidth( int( width ) );
|
|
|
|
// if ( insertPageBreak )
|
|
// col->setPageBreak( true )
|
|
|
|
if ( collapsed )
|
|
col->setHide( true );
|
|
|
|
table->insertColumnFormat( col );
|
|
++column;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void replaceMacro( TQString & text, TQString const & old, TQString const & newS )
|
|
{
|
|
int n = text.tqfind( old );
|
|
if ( n != -1 )
|
|
text = text.tqreplace( n, old.length(), newS );
|
|
}
|
|
|
|
TQString getPart( TQDomNode const & part )
|
|
{
|
|
TQString result;
|
|
TQDomElement e = KoDom::namedItemNS( part, ooNS::text, "p" );
|
|
while ( !e.isNull() )
|
|
{
|
|
TQString text = e.text();
|
|
kdDebug(30518) << "PART: " << text << endl;
|
|
|
|
TQDomElement macro = KoDom::namedItemNS( e, ooNS::text, "time" );
|
|
if ( !macro.isNull() )
|
|
replaceMacro( text, macro.text(), "<time>" );
|
|
|
|
macro = KoDom::namedItemNS( e, ooNS::text, "date" );
|
|
if ( !macro.isNull() )
|
|
replaceMacro( text, macro.text(), "<date>" );
|
|
|
|
macro = KoDom::namedItemNS( e, ooNS::text, "page-number" );
|
|
if ( !macro.isNull() )
|
|
replaceMacro( text, macro.text(), "<page>" );
|
|
|
|
macro = KoDom::namedItemNS( e, ooNS::text, "page-count" );
|
|
if ( !macro.isNull() )
|
|
replaceMacro( text, macro.text(), "<pages>" );
|
|
|
|
macro = KoDom::namedItemNS( e, ooNS::text, "sheet-name" );
|
|
if ( !macro.isNull() )
|
|
replaceMacro( text, macro.text(), "<sheet>" );
|
|
|
|
macro = KoDom::namedItemNS( e, ooNS::text, "title" );
|
|
if ( !macro.isNull() )
|
|
replaceMacro( text, macro.text(), "<name>" );
|
|
|
|
macro = KoDom::namedItemNS( e, ooNS::text, "file-name" );
|
|
if ( !macro.isNull() )
|
|
replaceMacro( text, macro.text(), "<file>" );
|
|
|
|
if ( !result.isEmpty() )
|
|
result += '\n';
|
|
result += text;
|
|
e = e.nextSibling().toElement();
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
void OpenCalcImport::loadTableMasterStyle( Sheet * table,
|
|
TQString const & stylename )
|
|
{
|
|
kdDebug(30518) << "Loading table master style: " << stylename << endl;
|
|
|
|
TQDomElement * style = m_styles[ stylename ];
|
|
|
|
if ( !style )
|
|
{
|
|
kdDebug(30518) << "Master style not found! " << endl;
|
|
return;
|
|
}
|
|
|
|
TQDomNode header = KoDom::namedItemNS( *style, ooNS::style, "header" );
|
|
kdDebug(30518) << "Style header " << endl;
|
|
|
|
TQString hleft, hmiddle, hright;
|
|
TQString fleft, fmiddle, fright;
|
|
|
|
if ( !header.isNull() )
|
|
{
|
|
kdDebug(30518) << "Header exists" << endl;
|
|
TQDomNode part = KoDom::namedItemNS( header, ooNS::style, "region-left" );
|
|
if ( !part.isNull() )
|
|
{
|
|
hleft = getPart( part );
|
|
kdDebug(30518) << "Header left: " << hleft << endl;
|
|
}
|
|
else
|
|
kdDebug(30518) << "Style:region:left doesn't exist!" << endl;
|
|
part = KoDom::namedItemNS( header, ooNS::style, "region-center" );
|
|
if ( !part.isNull() )
|
|
{
|
|
hmiddle = getPart( part );
|
|
kdDebug(30518) << "Header middle: " << hmiddle << endl;
|
|
}
|
|
part = KoDom::namedItemNS( header, ooNS::style, "region-right" );
|
|
if ( !part.isNull() )
|
|
{
|
|
hright = getPart( part );
|
|
kdDebug(30518) << "Header right: " << hright << endl;
|
|
}
|
|
}
|
|
|
|
TQDomNode footer = KoDom::namedItemNS( *style, ooNS::style, "footer" );
|
|
|
|
if ( !footer.isNull() )
|
|
{
|
|
TQDomNode part = KoDom::namedItemNS( footer, ooNS::style, "region-left" );
|
|
if ( !part.isNull() )
|
|
{
|
|
fleft = getPart( part );
|
|
kdDebug(30518) << "Footer left: " << fleft << endl;
|
|
}
|
|
part = KoDom::namedItemNS( footer, ooNS::style, "region-center" );
|
|
if ( !part.isNull() )
|
|
{
|
|
fmiddle = getPart( part );
|
|
kdDebug(30518) << "Footer middle: " << fmiddle << endl;
|
|
}
|
|
part = KoDom::namedItemNS( footer, ooNS::style, "region-right" );
|
|
if ( !part.isNull() )
|
|
{
|
|
fright = getPart( part );
|
|
kdDebug(30518) << "Footer right: " << fright << endl;
|
|
}
|
|
}
|
|
|
|
table->print()->setHeadFootLine( hleft, hmiddle, hright,
|
|
fleft, fmiddle, fright );
|
|
if ( style->hasAttributeNS( ooNS::style, "page-master-name" ) )
|
|
{
|
|
TQString masterPageLayoutStyleName=style->attributeNS( ooNS::style, "page-master-name", TQString() );
|
|
kdDebug(30518)<<"masterPageLayoutStyleName :"<<masterPageLayoutStyleName<<endl;
|
|
TQDomElement *masterLayoutStyle = m_styles[masterPageLayoutStyleName];
|
|
kdDebug(30518)<<"masterLayoutStyle :"<<masterLayoutStyle<<endl;
|
|
if ( !masterLayoutStyle )
|
|
return;
|
|
KoStyleStack styleStack( ooNS::style, ooNS::fo );
|
|
styleStack.push( *masterLayoutStyle );
|
|
loadOasisMasterLayoutPage( table, styleStack );
|
|
}
|
|
}
|
|
|
|
void OpenCalcImport::loadOasisMasterLayoutPage( Sheet * table,KoStyleStack &styleStack )
|
|
{
|
|
float left = 0.0;
|
|
float right = 0.0;
|
|
float top = 0.0;
|
|
float bottom = 0.0;
|
|
float width = 0.0;
|
|
float height = 0.0;
|
|
TQString orientation = "Portrait";
|
|
TQString format;
|
|
|
|
// Laurent : Why we stored tqlayout information as Millimeter ?!!!!!
|
|
// kspread used point for all other attribute
|
|
// I don't understand :(
|
|
if ( styleStack.hasAttributeNS( ooNS::fo, "page-width" ) )
|
|
{
|
|
width = KoUnit::toMM(KoUnit::parseValue( styleStack.attributeNS( ooNS::fo, "page-width" ) ) );
|
|
}
|
|
if ( styleStack.hasAttributeNS( ooNS::fo, "page-height" ) )
|
|
{
|
|
height = KoUnit::toMM( KoUnit::parseValue( styleStack.attributeNS( ooNS::fo, "page-height" ) ) );
|
|
}
|
|
if ( styleStack.hasAttributeNS( ooNS::fo, "margin-top" ) )
|
|
{
|
|
top = KoUnit::toMM(KoUnit::parseValue( styleStack.attributeNS( ooNS::fo, "margin-top" ) ) );
|
|
}
|
|
if ( styleStack.hasAttributeNS( ooNS::fo, "margin-bottom" ) )
|
|
{
|
|
bottom = KoUnit::toMM(KoUnit::parseValue( styleStack.attributeNS( ooNS::fo, "margin-bottom" ) ) );
|
|
}
|
|
if ( styleStack.hasAttributeNS( ooNS::fo, "margin-left" ) )
|
|
{
|
|
left = KoUnit::toMM(KoUnit::parseValue( styleStack.attributeNS( ooNS::fo, "margin-left" ) ) );
|
|
}
|
|
if ( styleStack.hasAttributeNS( ooNS::fo, "margin-right" ) )
|
|
{
|
|
right = KoUnit::toMM(KoUnit::parseValue( styleStack.attributeNS( ooNS::fo, "margin-right" ) ) );
|
|
}
|
|
if ( styleStack.hasAttributeNS( ooNS::style, "writing-mode" ) )
|
|
{
|
|
kdDebug(30518)<<"styleStack.hasAttribute( style:writing-mode ) :"<<styleStack.hasAttributeNS( ooNS::style, "writing-mode" )<<endl;
|
|
}
|
|
if ( styleStack.hasAttributeNS( ooNS::style, "print-orientation" ) )
|
|
{
|
|
orientation = ( styleStack.attributeNS( ooNS::style, "print-orientation" )=="landscape" ) ? "Landscape" : "Portrait" ;
|
|
}
|
|
if ( styleStack.hasAttributeNS( ooNS::style, "num-format" ) )
|
|
{
|
|
kdDebug(30518)<<" num-format :"<<styleStack.attributeNS( ooNS::style, "num-format" )<<endl;
|
|
//todo fixme
|
|
}
|
|
if ( styleStack.hasAttributeNS( ooNS::fo, "background-color" ) )
|
|
{
|
|
//todo
|
|
kdDebug(30518)<<" fo:background-color :"<<styleStack.attributeNS( ooNS::fo, "background-color" )<<endl;
|
|
}
|
|
if ( styleStack.hasAttributeNS( ooNS::style, "print" ) )
|
|
{
|
|
//todo parsing
|
|
TQString str = styleStack.attributeNS( ooNS::style, "print" );
|
|
kdDebug(30518)<<" style:print :"<<str<<endl;
|
|
|
|
if (str.tqcontains( "headers" ) )
|
|
{
|
|
//todo implement it into kspread
|
|
}
|
|
if ( str.tqcontains( "grid" ) )
|
|
{
|
|
table->print()->setPrintGrid( true );
|
|
}
|
|
if ( str.tqcontains( "annotations" ) )
|
|
{
|
|
//todo it's not implemented
|
|
}
|
|
if ( str.tqcontains( "objects" ) )
|
|
{
|
|
//todo it's not implemented
|
|
}
|
|
if ( str.tqcontains( "charts" ) )
|
|
{
|
|
//todo it's not implemented
|
|
}
|
|
if ( str.tqcontains( "drawings" ) )
|
|
{
|
|
//todo it's not implemented
|
|
}
|
|
if ( str.tqcontains( "formulas" ) )
|
|
{
|
|
table->setShowFormula(true);
|
|
}
|
|
if ( str.tqcontains( "zero-values" ) )
|
|
{
|
|
//todo it's not implemented
|
|
}
|
|
}
|
|
if ( styleStack.hasAttributeNS( ooNS::style, "table-centering" ) )
|
|
{
|
|
TQString str = styleStack.attributeNS( ooNS::style, "table-centering" );
|
|
//not implemented into kspread
|
|
kdDebug(30518)<<" styleStack.attribute( style:table-centering ) :"<<str<<endl;
|
|
#if 0
|
|
if ( str == "horizontal" )
|
|
{
|
|
}
|
|
else if ( str == "vertical" )
|
|
{
|
|
}
|
|
else if ( str == "both" )
|
|
{
|
|
}
|
|
else if ( str == "none" )
|
|
{
|
|
}
|
|
else
|
|
kdDebug(30518)<<" table-centering unknown :"<<str<<endl;
|
|
#endif
|
|
}
|
|
format = TQString( "%1x%2" ).tqarg( width ).tqarg( height );
|
|
kdDebug(30518)<<" format : "<<format<<endl;
|
|
table->print()->setPaperLayout( left, top, right, bottom, format, orientation );
|
|
|
|
kdDebug(30518)<<" left margin :"<<left<<" right :"<<right<<" top :"<<top<<" bottom :"<<bottom<<endl;
|
|
//<style:properties fo:page-width="21.8cm" fo:page-height="28.801cm" fo:margin-top="2cm" fo:margin-bottom="2.799cm" fo:margin-left="1.3cm" fo:margin-right="1.3cm" style:writing-mode="lr-tb"/>
|
|
// TQString format = paper.attribute( "format" );
|
|
// TQString orientation = paper.attribute( "orientation" );
|
|
// m_pPrint->setPaperLayout( left, top, right, bottom, format, orientation );
|
|
// }
|
|
}
|
|
|
|
|
|
bool OpenCalcImport::parseBody( int numOfTables )
|
|
{
|
|
TQDomElement content = m_content.documentElement();
|
|
TQDomNode body = KoDom::namedItemNS( content, ooNS::office, "body" );
|
|
|
|
if ( body.isNull() )
|
|
return false;
|
|
|
|
loadOasisAreaName( body.toElement() );
|
|
loadOasisCellValidation( body.toElement() );
|
|
|
|
Sheet * table;
|
|
TQDomNode sheet = KoDom::namedItemNS( body, ooNS::table, "table" );
|
|
|
|
kdDebug()<<" sheet :"<<sheet.isNull()<<endl;
|
|
if ( sheet.isNull() )
|
|
return false;
|
|
|
|
while ( !sheet.isNull() )
|
|
{
|
|
TQDomElement t = sheet.toElement();
|
|
if ( t.isNull() )
|
|
{
|
|
sheet = sheet.nextSibling();
|
|
continue;
|
|
}
|
|
if ( t.nodeName() != "table:table" )
|
|
{
|
|
sheet = sheet.nextSibling();
|
|
continue;
|
|
}
|
|
|
|
table = m_doc->map()->addNewSheet();
|
|
|
|
table->setSheetName( t.attributeNS( ooNS::table, "name", TQString() ), true, false );
|
|
kdDebug()<<" table->name()"<<table->name()<<endl;
|
|
sheet = sheet.nextSibling();
|
|
}
|
|
|
|
sheet = body.firstChild();
|
|
|
|
int step = (int) ( 80 / numOfTables );
|
|
int progress = 15;
|
|
|
|
Format::setGlobalColWidth( MM_TO_POINT( 22.7 ) );
|
|
Format::setGlobalRowHeight( MM_TO_POINT( 4.3 ) );
|
|
kdDebug(30518) << "Global Height: " << MM_TO_POINT( 4.3 ) << ", Global width: " << MM_TO_POINT( 22.7) << endl;
|
|
|
|
while ( !sheet.isNull() )
|
|
{
|
|
TQDomElement t = sheet.toElement();
|
|
if ( t.isNull() )
|
|
{
|
|
KMessageBox::sorry( 0, i18n( "The file seems to be corrupt. Skipping a table." ) );
|
|
sheet = sheet.nextSibling();
|
|
continue;
|
|
}
|
|
if ( t.nodeName() != "table:table" )
|
|
{
|
|
sheet = sheet.nextSibling();
|
|
continue;
|
|
}
|
|
|
|
table = m_doc->map()->findSheet( t.attributeNS( ooNS::table, "name", TQString() ) );
|
|
if ( !table )
|
|
{
|
|
KMessageBox::sorry( 0, i18n( "Skipping a table." ) );
|
|
sheet = sheet.nextSibling();
|
|
continue;
|
|
}
|
|
|
|
Format * defaultStyle = m_defaultStyles[ "Default" ];
|
|
if ( defaultStyle )
|
|
{
|
|
Cell* defaultCell = table->defaultCell();
|
|
kdDebug(30518) << "Copy default style to default cell" << endl;
|
|
defaultCell->format()->copy( *defaultStyle );
|
|
}
|
|
table->setDefaultHeight( MM_TO_POINT( 4.3 ) );
|
|
table->setDefaultWidth( MM_TO_POINT( 22.7 ) );
|
|
|
|
kdDebug(30518) << "Added table: " << t.attributeNS( ooNS::table, "name", TQString() ) << endl;
|
|
|
|
if ( t.hasAttributeNS( ooNS::table, "style-name" ) )
|
|
{
|
|
TQString style = t.attributeNS( ooNS::table, "style-name", TQString() );
|
|
TQDomElement * tableStyle = m_styles[ style ];
|
|
|
|
TQDomNode node;
|
|
|
|
if ( tableStyle )
|
|
node = tableStyle->firstChild();
|
|
|
|
while( !node.isNull() )
|
|
{
|
|
TQDomElement property = node.toElement();
|
|
if ( property.localName() == "properties" && property.namespaceURI() == ooNS::style )
|
|
{
|
|
if ( property.hasAttributeNS( ooNS::table, "display" ) )
|
|
{
|
|
bool visible = (property.attributeNS( ooNS::table, "display", TQString() ) == "true" ? true : false );
|
|
table->hideSheet( !visible );
|
|
kdDebug(30518) << "Table: " << table->tableName() << ", hidden: " << !visible << endl;
|
|
}
|
|
}
|
|
|
|
node = node.nextSibling();
|
|
}
|
|
|
|
if ( tableStyle && tableStyle->hasAttributeNS( ooNS::style, "master-page-name" ) )
|
|
{
|
|
TQString stylename = "pm" + tableStyle->attributeNS( ooNS::style, "master-page-name", TQString() );
|
|
|
|
loadTableMasterStyle( table, stylename );
|
|
|
|
}
|
|
}
|
|
if ( t.hasAttributeNS( ooNS::table, "print-ranges" ) )
|
|
{
|
|
// e.g.: Sheet4.A1:Sheet4.E28
|
|
TQString range = t.attributeNS( ooNS::table, "print-ranges", TQString() );
|
|
OpenCalcPoint point( range );
|
|
|
|
kdDebug(30518) << "Print range: " << point.translation << endl;
|
|
KSpread::Range p( point.translation );
|
|
|
|
kdDebug(30518) << "Print table: " << p.sheetName() << endl;
|
|
|
|
if ( table->sheetName() == p.sheetName() )
|
|
table->print()->setPrintRange( p.range() );
|
|
}
|
|
|
|
if ( !readColLayouts( t, table ) )
|
|
return false;
|
|
|
|
if ( !readRowsAndCells( t, table ) )
|
|
return false;
|
|
|
|
if ( t.hasAttributeNS( ooNS::table, "protected" ) )
|
|
{
|
|
TQCString passwd( "" );
|
|
if ( t.hasAttributeNS( ooNS::table, "protection-key" ) )
|
|
{
|
|
TQString p = t.attributeNS( ooNS::table, "protection-key", TQString() );
|
|
TQCString str( p.latin1() );
|
|
kdDebug(30518) << "Decoding password: " << str << endl;
|
|
passwd = KCodecs::base64Decode( str );
|
|
}
|
|
kdDebug(30518) << "Password hash: '" << passwd << "'" << endl;
|
|
table->setProtected( passwd );
|
|
}
|
|
|
|
progress += step;
|
|
emit sigProgress( progress );
|
|
sheet = sheet.nextSibling();
|
|
}
|
|
|
|
TQDomElement b = body.toElement();
|
|
if ( b.hasAttributeNS( ooNS::table, "structure-protected" ) )
|
|
{
|
|
TQCString passwd( "" );
|
|
if ( b.hasAttributeNS( ooNS::table, "protection-key" ) )
|
|
{
|
|
TQString p = b.attributeNS( ooNS::table, "protection-key", TQString() );
|
|
TQCString str( p.latin1() );
|
|
kdDebug(30518) << "Decoding password: " << str << endl;
|
|
passwd = KCodecs::base64Decode( str );
|
|
}
|
|
kdDebug(30518) << "Password hash: '" << passwd << "'" << endl;
|
|
|
|
m_doc->map()->setProtected( passwd );
|
|
}
|
|
|
|
emit sigProgress( 98 );
|
|
|
|
return true;
|
|
}
|
|
|
|
void OpenCalcImport::insertStyles( TQDomElement const & element )
|
|
{
|
|
if ( element.isNull() )
|
|
return;
|
|
|
|
TQDomElement e;
|
|
forEachElement( e, element )
|
|
{
|
|
if ( e.isNull() || !e.hasAttributeNS( ooNS::style, "name" ) )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
TQString name = e.attributeNS( ooNS::style, "name", TQString() );
|
|
kdDebug(30518) << "Style: '" << name << "' loaded " << endl;
|
|
m_styles.insert( name, new TQDomElement( e ) );
|
|
}
|
|
}
|
|
|
|
|
|
void OpenCalcImport::loadOasisAreaName( const TQDomElement&body )
|
|
{
|
|
TQDomNode namedAreas = KoDom::namedItemNS( body, ooNS::table, "named-expressions" );
|
|
if ( !namedAreas.isNull() )
|
|
{
|
|
TQDomElement e;
|
|
forEachElement( e, namedAreas )
|
|
{
|
|
if ( e.isNull() || !e.hasAttributeNS( ooNS::table, "name" ) || !e.hasAttributeNS( ooNS::table, "cell-range-address" ) )
|
|
{
|
|
kdDebug(30518) << "Reading in named area failed" << endl;
|
|
continue;
|
|
}
|
|
|
|
// TODO: what is: table:base-cell-address
|
|
TQString name = e.attributeNS( ooNS::table, "name", TQString() );
|
|
TQString areaPoint = e.attributeNS( ooNS::table, "cell-range-address", TQString() );
|
|
|
|
m_namedAreas.append( name );
|
|
kdDebug(30518) << "Reading in named area, name: " << name << ", area: " << areaPoint << endl;
|
|
|
|
OpenCalcPoint point( areaPoint );
|
|
kdDebug(30518) << "Area: " << point.translation << endl;
|
|
|
|
TQString range( point.translation );
|
|
|
|
if ( point.translation.tqfind( ':' ) == -1 )
|
|
{
|
|
Point p( point.translation );
|
|
|
|
int n = range.tqfind( '!' );
|
|
if ( n > 0 )
|
|
range = range + ":" + range.right( range.length() - n - 1);
|
|
|
|
kdDebug(30518) << "=> Area: " << range << endl;
|
|
}
|
|
|
|
KSpread::Range p( range );
|
|
|
|
m_doc->addAreaName( p.range(), name, p.sheetName() );
|
|
kdDebug(30518) << "Area range: " << p.sheetName() << endl;
|
|
}
|
|
}
|
|
}
|
|
|
|
void OpenCalcImport::loadOasisCellValidation( const TQDomElement&body )
|
|
{
|
|
TQDomNode validation = KoDom::namedItemNS( body, ooNS::table, "content-validations" );
|
|
if ( !validation.isNull() )
|
|
{
|
|
TQDomElement element;
|
|
forEachElement( element, validation )
|
|
{
|
|
if ( element.localName() == "content-validation" ) {
|
|
m_validationList.insert( element.attributeNS( ooNS::table, "name", TQString() ), element);
|
|
kdDebug(30518)<<" validation found :"<<element.attributeNS( ooNS::table, "name", TQString() )<<endl;
|
|
}
|
|
else {
|
|
kdDebug(30518)<<" Tag not recognize :"<<element.tagName()<<endl;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
TQString * OpenCalcImport::loadFormat( TQDomElement * element,
|
|
FormatType & formatType,
|
|
TQString name )
|
|
{
|
|
if ( !element )
|
|
return 0;
|
|
|
|
int i;
|
|
bool ok;
|
|
|
|
TQString * format = 0;
|
|
TQDomElement e = element->firstChild( ).toElement();
|
|
int precision = 0;
|
|
int leadingZ = 1;
|
|
bool thousandsSep = false;
|
|
bool negRed = false;
|
|
|
|
if ( element->localName() == "time-style" )
|
|
formatType = Custom_format;
|
|
else if ( element->localName() == "date-style" )
|
|
formatType = Custom_format;
|
|
else if ( element->localName() == "percentage-style" )
|
|
formatType = Custom_format;
|
|
else if ( element->localName() == "number-style" )
|
|
formatType = Custom_format;
|
|
else if ( element->localName() == "currency-style" )
|
|
formatType = Custom_format;
|
|
else if ( element->localName() == "boolean-style" )
|
|
formatType = Custom_format;
|
|
|
|
if ( !e.isNull() )
|
|
format = new TQString();
|
|
|
|
// TODO (element):
|
|
// number:automatic-order="true"
|
|
// number:truncate-on-overflow="false"
|
|
// style:volatile="true"
|
|
|
|
while ( !e.isNull() )
|
|
{
|
|
if ( e.localName() == "properties" && e.namespaceURI() == ooNS::style )
|
|
{
|
|
if ( e.hasAttributeNS( ooNS::fo, "color" ) )
|
|
negRed = true; // we only support red...
|
|
}
|
|
else if ( e.localName() == "text" && e.namespaceURI()==ooNS::number)
|
|
{
|
|
if ( negRed && ( e.text() == "-" ) )
|
|
;
|
|
else
|
|
format->append( e.text() );
|
|
}
|
|
else if ( e.localName() == "currency-symbol" && e.namespaceURI()==ooNS::number)
|
|
{
|
|
TQString sym( e.text() );
|
|
kdDebug(30518) << "Currency: " << sym << endl;
|
|
format->append( sym );
|
|
// number:language="de" number:country="DE">€</number:currency-symbol>
|
|
}
|
|
else if ( e.localName() == "day-of-week" && e.namespaceURI()==ooNS::number)
|
|
{
|
|
if ( e.hasAttributeNS( ooNS::number, "style" ) )
|
|
{
|
|
if ( e.attributeNS( ooNS::number, "style", TQString() ) == "long" )
|
|
format->append( "dddd" );
|
|
else
|
|
format->append( "ddd" );
|
|
}
|
|
else
|
|
format->append( "ddd" );
|
|
}
|
|
else if ( e.localName() == "day" && e.namespaceURI()==ooNS::number)
|
|
{
|
|
if ( e.hasAttributeNS( ooNS::number, "style" ) )
|
|
{
|
|
if ( e.attributeNS( ooNS::number, "style", TQString() ) == "long" )
|
|
format->append( "dd" );
|
|
else
|
|
format->append( "d" );
|
|
}
|
|
else
|
|
format->append( "d" );
|
|
}
|
|
else if ( e.localName() == "month" && e.namespaceURI()==ooNS::number)
|
|
{
|
|
if ( e.hasAttributeNS( ooNS::number, "textual" ) )
|
|
{
|
|
if ( e.attributeNS( ooNS::number, "textual", TQString() ) == "true" )
|
|
format->append( "mm" );
|
|
}
|
|
|
|
if ( e.hasAttributeNS( ooNS::number, "style" ) )
|
|
{
|
|
if ( e.attributeNS( ooNS::number, "style", TQString() ) == "long" )
|
|
format->append( "mm" );
|
|
else
|
|
format->append( "m" );
|
|
}
|
|
else
|
|
format->append( "m" );
|
|
}
|
|
else if ( e.localName() == "year" && e.namespaceURI()==ooNS::number)
|
|
{
|
|
if ( e.hasAttributeNS( ooNS::number, "style" ) )
|
|
{
|
|
if ( e.attributeNS( ooNS::number, "style", TQString() ) == "long" )
|
|
format->append( "yyyy" );
|
|
else
|
|
format->append( "yy" );
|
|
}
|
|
else
|
|
format->append( "yy" );
|
|
}
|
|
else if ( e.localName() == "hours" && e.namespaceURI()==ooNS::number)
|
|
{
|
|
if ( e.hasAttributeNS( ooNS::number, "style" ) )
|
|
{
|
|
if ( e.attributeNS( ooNS::number, "style", TQString() ) == "long" )
|
|
format->append( "hh" );
|
|
else
|
|
format->append( "h" );
|
|
}
|
|
else
|
|
format->append( "h" );
|
|
}
|
|
else if ( e.localName() == "minutes" && e.namespaceURI()==ooNS::number)
|
|
{
|
|
if ( e.hasAttributeNS( ooNS::number, "style" ) )
|
|
{
|
|
if ( e.attributeNS( ooNS::number, "style", TQString() ) == "long" )
|
|
format->append( "mm" );
|
|
else
|
|
format->append( "m" );
|
|
}
|
|
else
|
|
format->append( "m" );
|
|
}
|
|
else if ( e.localName() == "seconds" && e.namespaceURI()==ooNS::number)
|
|
{
|
|
if ( e.hasAttributeNS( ooNS::number, "style" ) )
|
|
{
|
|
if ( e.attributeNS( ooNS::number, "style", TQString() ) == "long" )
|
|
format->append( "ss" );
|
|
else
|
|
format->append( "s" );
|
|
}
|
|
else
|
|
format->append( "s" );
|
|
}
|
|
else if ( e.localName() == "am-pm" && e.namespaceURI()==ooNS::number)
|
|
{
|
|
format->append( "AM/PM" );
|
|
}
|
|
else if ( e.localName() == "number" && e.namespaceURI()==ooNS::number)
|
|
{
|
|
// TODO: number:grouping="true"
|
|
|
|
if ( e.hasAttributeNS( ooNS::number, "decimal-places" ) )
|
|
{
|
|
int d = e.attributeNS( ooNS::number, "decimal-places", TQString() ).toInt( &ok );
|
|
if ( ok )
|
|
precision = d;
|
|
}
|
|
|
|
if ( e.hasAttributeNS( ooNS::number, "min-integer-digits" ) )
|
|
{
|
|
int d = e.attributeNS( ooNS::number, "min-integer-digits", TQString() ).toInt( &ok );
|
|
if ( ok )
|
|
leadingZ = d;
|
|
}
|
|
|
|
if ( thousandsSep && leadingZ <= 3 )
|
|
{
|
|
format->append( "#," );
|
|
for ( i = leadingZ; i <= 3; ++i )
|
|
format->append( '#' );
|
|
}
|
|
|
|
for ( i = 1; i <= leadingZ; ++i )
|
|
{
|
|
format->append( '0' );
|
|
if ( ( i % 3 == 0 ) && thousandsSep )
|
|
format->append( ',' );
|
|
}
|
|
|
|
format->append( '.' );
|
|
for ( i = 0; i < precision; ++i )
|
|
format->append( '0' );
|
|
}
|
|
else if ( e.localName() == "scientific-number" && e.namespaceURI()==ooNS::number)
|
|
{
|
|
int exp = 2;
|
|
|
|
if ( e.hasAttributeNS( ooNS::number, "decimal-places" ) )
|
|
{
|
|
int d = e.attributeNS( ooNS::number, "decimal-places", TQString() ).toInt( &ok );
|
|
if ( ok )
|
|
precision = d;
|
|
}
|
|
|
|
if ( e.hasAttributeNS( ooNS::number, "min-integer-digits" ) )
|
|
{
|
|
int d = e.attributeNS( ooNS::number, "min-integer-digits", TQString() ).toInt( &ok );
|
|
if ( ok )
|
|
leadingZ = d;
|
|
}
|
|
|
|
if ( e.hasAttributeNS( ooNS::number, "min-exponent-digits" ) )
|
|
{
|
|
int d = e.attributeNS( ooNS::number, "min-exponent-digits", TQString() ).toInt( &ok );
|
|
if ( ok )
|
|
exp = d;
|
|
if ( exp <= 0 )
|
|
exp = 1;
|
|
}
|
|
|
|
if ( thousandsSep && leadingZ <= 3 )
|
|
{
|
|
format->append( "#," );
|
|
for ( i = leadingZ; i <= 3; ++i )
|
|
format->append( '#' );
|
|
}
|
|
|
|
for ( i = 1; i <= leadingZ; ++i )
|
|
{
|
|
format->append( '0' );
|
|
if ( ( i % 3 == 0 ) && thousandsSep )
|
|
format->append( ',' );
|
|
}
|
|
|
|
format->append( '.' );
|
|
for ( i = 0; i < precision; ++i )
|
|
format->append( '0' );
|
|
|
|
format->append( "E+" );
|
|
for ( i = 0; i < exp; ++i )
|
|
format->append( '0' );
|
|
|
|
formatType = Custom_format;
|
|
}
|
|
else if ( e.localName() == "fraction" && e.namespaceURI()==ooNS::number)
|
|
{
|
|
int integer = 0;
|
|
int numerator = 1;
|
|
int denominator = 1;
|
|
|
|
if ( e.hasAttributeNS( ooNS::number, "min-integer-digits" ) )
|
|
{
|
|
int d = e.attributeNS( ooNS::number, "min-integer-digits", TQString() ).toInt( &ok );
|
|
if ( ok )
|
|
integer = d;
|
|
}
|
|
if ( e.hasAttributeNS( ooNS::number, "min-numerator-digits" ) )
|
|
{
|
|
int d = e.attributeNS( ooNS::number, "min-numerator-digits", TQString() ).toInt( &ok );
|
|
if ( ok )
|
|
numerator = d;
|
|
}
|
|
if ( e.hasAttributeNS( ooNS::number, "min-denominator-digits" ) )
|
|
{
|
|
int d = e.attributeNS( ooNS::number, "min-denominator-digits", TQString() ).toInt( &ok );
|
|
if ( ok )
|
|
denominator = d;
|
|
}
|
|
|
|
for ( i = 0; i <= integer; ++i )
|
|
format->append( '#' );
|
|
|
|
format->append( ' ' );
|
|
|
|
for ( i = 0; i <= numerator; ++i )
|
|
format->append( '?' );
|
|
|
|
format->append( '/' );
|
|
|
|
for ( i = 0; i <= denominator; ++i )
|
|
format->append( '?' );
|
|
}
|
|
// Not needed:
|
|
// <style:map style:condition="value()>=0" style:apply-style-name="N106P0"/>
|
|
// we handle painting negative numbers in red differently
|
|
|
|
e = e.nextSibling().toElement();
|
|
}
|
|
|
|
if ( negRed )
|
|
{
|
|
TQString f( *format );
|
|
format->append( ";[Red]" );
|
|
format->append( f );
|
|
}
|
|
|
|
kdDebug(30518) << "*** New FormatString: " << *format << endl << endl;
|
|
|
|
m_formats.insert( name, format );
|
|
|
|
return format;
|
|
}
|
|
|
|
void OpenCalcImport::loadFontStyle( Format * tqlayout, TQDomElement const * font ) const
|
|
{
|
|
if ( !font || !tqlayout )
|
|
return;
|
|
|
|
kdDebug(30518) << "Copy font style from the tqlayout " << font->tagName() << ", " << font->nodeName() << endl;
|
|
|
|
if ( font->hasAttributeNS( ooNS::fo, "font-family" ) )
|
|
tqlayout->setTextFontFamily( font->attributeNS( ooNS::fo, "font-family", TQString() ) );
|
|
if ( font->hasAttributeNS( ooNS::fo, "color" ) )
|
|
tqlayout->setTextColor( TQColor( font->attributeNS( ooNS::fo, "color", TQString() ) ) );
|
|
if ( font->hasAttributeNS( ooNS::fo, "font-size" ) )
|
|
tqlayout->setTextFontSize( int( KoUnit::parseValue( font->attributeNS( ooNS::fo, "font-size", TQString() ), 10 ) ) );
|
|
else
|
|
tqlayout->setTextFontSize( 10 );
|
|
if ( font->hasAttributeNS( ooNS::fo, "font-style" ) )
|
|
{
|
|
kdDebug(30518) << "italic" << endl;
|
|
tqlayout->setTextFontItalic( true ); // only thing we support
|
|
}
|
|
if ( font->hasAttributeNS( ooNS::fo, "font-weight" ) )
|
|
tqlayout->setTextFontBold( true ); // only thing we support
|
|
if ( font->hasAttributeNS( ooNS::fo, "text-underline" ) || font->hasAttributeNS( ooNS::style, "text-underline" ) )
|
|
tqlayout->setTextFontUnderline( true ); // only thing we support
|
|
if ( font->hasAttributeNS( ooNS::style, "text-crossing-out" ) )
|
|
tqlayout->setTextFontStrike( true ); // only thing we support
|
|
if ( font->hasAttributeNS( ooNS::style, "font-pitch" ) )
|
|
{
|
|
// TODO: possible values: fixed, variable
|
|
}
|
|
// TODO:
|
|
// text-underline-color
|
|
}
|
|
|
|
void OpenCalcImport::loadBorder( Format * tqlayout, TQString const & borderDef, bPos pos ) const
|
|
{
|
|
if ( borderDef == "none" )
|
|
return;
|
|
|
|
int p = borderDef.tqfind( ' ' );
|
|
if ( p < 0 )
|
|
return;
|
|
|
|
TQPen pen;
|
|
TQString w = borderDef.left( p );
|
|
pen.setWidth( (int) KoUnit::parseValue( w ) );
|
|
|
|
|
|
++p;
|
|
int p2 = borderDef.tqfind( ' ', p );
|
|
TQString s = borderDef.mid( p, p2 - p );
|
|
|
|
kdDebug(30518) << "Borderstyle: " << s << endl;
|
|
|
|
if ( s == "solid" || s == "double" )
|
|
pen.setStyle( Qt::SolidLine );
|
|
else
|
|
{
|
|
#if 0
|
|
// TODO: not supported by oocalc
|
|
pen.setStyle( Qt::DashLine );
|
|
pen.setStyle( Qt::DotLine );
|
|
pen.setStyle( Qt::DashDotLine );
|
|
pen.setStyle( Qt::DashDotDotLine );
|
|
#endif
|
|
pen.setStyle( Qt::SolidLine ); //default.
|
|
}
|
|
|
|
++p2;
|
|
p = borderDef.tqfind( ' ', p2 );
|
|
if ( p == -1 )
|
|
p = borderDef.length();
|
|
|
|
pen.setColor( TQColor( borderDef.right( p - p2 ) ) );
|
|
|
|
if ( pos == Left )
|
|
tqlayout->setLeftBorderPen( pen );
|
|
else if ( pos == Top )
|
|
tqlayout->setTopBorderPen( pen );
|
|
else if ( pos == Right )
|
|
tqlayout->setRightBorderPen( pen );
|
|
else if ( pos == Bottom )
|
|
tqlayout->setBottomBorderPen( pen );
|
|
else if ( pos == Border )
|
|
{
|
|
tqlayout->setLeftBorderPen( pen );
|
|
tqlayout->setTopBorderPen( pen );
|
|
tqlayout->setRightBorderPen( pen );
|
|
tqlayout->setBottomBorderPen( pen );
|
|
}
|
|
// TODO Diagonals not supported by oocalc
|
|
}
|
|
|
|
void OpenCalcImport::loadStyleProperties( Format * tqlayout, TQDomElement const & property ) const
|
|
{
|
|
kdDebug(30518) << "*** Loading style properties *****" << endl;
|
|
|
|
if ( property.hasAttributeNS( ooNS::style, "decimal-places" ) )
|
|
{
|
|
bool ok = false;
|
|
int p = property.attributeNS( ooNS::style, "decimal-places", TQString() ).toInt( &ok );
|
|
if (ok )
|
|
tqlayout->setPrecision( p );
|
|
}
|
|
|
|
if ( property.hasAttributeNS( ooNS::style, "font-name" ) )
|
|
{
|
|
TQDomElement * font = m_styles[ property.attributeNS( ooNS::style, "font-name", TQString() ) ];
|
|
loadFontStyle( tqlayout, font ); // generell font style
|
|
}
|
|
|
|
loadFontStyle( tqlayout, &property ); // specific font style
|
|
|
|
// TODO:
|
|
// diagonal: fall + goup
|
|
// fo:direction="ltr"
|
|
// style:text-align-source ("fix")
|
|
// style:shadow
|
|
// style:text-outline
|
|
// indents from right, top, bottom
|
|
// style:condition="cell-content()=15"
|
|
// => style:apply-style-name="Result" style:base-cell-address="Sheet6.A5"/>
|
|
|
|
if ( property.hasAttributeNS( ooNS::style, "rotation-angle" ) )
|
|
{
|
|
bool ok = false;
|
|
int a = property.attributeNS( ooNS::style, "rotation-angle", TQString() ).toInt( &ok );
|
|
if ( ok )
|
|
tqlayout->setAngle( -a + 1 );
|
|
}
|
|
|
|
if ( property.hasAttributeNS( ooNS::fo, "direction" ) )
|
|
{
|
|
tqlayout->setVerticalText( true );
|
|
}
|
|
if ( property.hasAttributeNS( ooNS::fo, "text-align" ) )
|
|
{
|
|
TQString s = property.attributeNS( ooNS::fo, "text-align", TQString() );
|
|
if ( s == "center" )
|
|
tqlayout->setAlign( Format::Center );
|
|
else if ( s == "end" )
|
|
tqlayout->setAlign( Format::Right );
|
|
else if ( s == "start" )
|
|
tqlayout->setAlign( Format::Left );
|
|
else if ( s == "justify" ) // TODO in KSpread!
|
|
tqlayout->setAlign( Format::Center );
|
|
}
|
|
if ( property.hasAttributeNS( ooNS::fo, "margin-left" ) )
|
|
{
|
|
kdDebug(30518)<<"margin-left :"<<KoUnit::parseValue( property.attributeNS( ooNS::fo, "margin-left", TQString() ),0.0 )<<endl;
|
|
tqlayout->setIndent( KoUnit::parseValue( property.attributeNS( ooNS::fo, "margin-left", TQString() ),0.0 ) );
|
|
}
|
|
if ( property.hasAttributeNS( ooNS::fo, "background-color" ) )
|
|
tqlayout->setBgColor( TQColor( property.attributeNS( ooNS::fo, "background-color", TQString() ) ) );
|
|
|
|
if ( property.hasAttributeNS( ooNS::style, "print-content" ) )
|
|
{
|
|
if ( property.attributeNS( ooNS::style, "print-content", TQString() ) == "false" )
|
|
tqlayout->setDontPrintText( false );
|
|
}
|
|
if ( property.hasAttributeNS( ooNS::style, "cell-protect" ) )
|
|
{
|
|
TQString prot( property.attributeNS( ooNS::style, "cell-protect", TQString() ) );
|
|
if ( prot == "none" )
|
|
{
|
|
tqlayout->setNotProtected( true );
|
|
tqlayout->setHideFormula( false );
|
|
tqlayout->setHideAll( false );
|
|
}
|
|
else if ( prot == "formula-hidden" )
|
|
{
|
|
tqlayout->setNotProtected( true );
|
|
tqlayout->setHideFormula( true );
|
|
tqlayout->setHideAll( false );
|
|
}
|
|
else if ( prot == "protected formula-hidden" )
|
|
{
|
|
tqlayout->setNotProtected( false );
|
|
tqlayout->setHideFormula( true );
|
|
tqlayout->setHideAll( false );
|
|
}
|
|
else if ( prot == "hidden-and-protected" )
|
|
{
|
|
tqlayout->setNotProtected( false );
|
|
tqlayout->setHideFormula( false );
|
|
tqlayout->setHideAll( true );
|
|
}
|
|
else if ( prot == "protected" )
|
|
{
|
|
tqlayout->setNotProtected( false );
|
|
tqlayout->setHideFormula( false );
|
|
tqlayout->setHideAll( false );
|
|
}
|
|
kdDebug(30518) << "Cell " << prot << endl;
|
|
}
|
|
|
|
if ( property.hasAttributeNS( ooNS::fo, "padding-left" ) )
|
|
tqlayout->setIndent( KoUnit::parseValue(property.attributeNS( ooNS::fo, "padding-left", TQString() ) ) );
|
|
|
|
if ( property.hasAttributeNS( ooNS::fo, "vertical-align" ) )
|
|
{
|
|
TQString s = property.attributeNS( ooNS::fo, "vertical-align", TQString() );
|
|
if ( s == "middle" )
|
|
tqlayout->setAlignY( Format::Middle );
|
|
else if ( s == "bottom" )
|
|
tqlayout->setAlignY( Format::Bottom );
|
|
else
|
|
tqlayout->setAlignY( Format::Top );
|
|
}
|
|
else
|
|
tqlayout->setAlignY( Format::Bottom );
|
|
|
|
if ( property.hasAttributeNS( ooNS::fo, "wrap-option" ) )
|
|
{
|
|
tqlayout->setMultiRow( true );
|
|
|
|
/* we do not support anything else yet
|
|
TQString s = property.attributeNS( ooNS::fo, "wrap-option", TQString() );
|
|
if ( s == "wrap" )
|
|
tqlayout->setMultiRow( true );
|
|
*/
|
|
}
|
|
|
|
if ( property.hasAttributeNS( ooNS::fo, "border-bottom" ) )
|
|
{
|
|
loadBorder( tqlayout, property.attributeNS( ooNS::fo, "border-bottom", TQString() ), Bottom );
|
|
// TODO: style:border-line-width-bottom if double!
|
|
}
|
|
|
|
if ( property.hasAttributeNS( ooNS::fo, "border-right" ) )
|
|
{
|
|
loadBorder( tqlayout, property.attributeNS( ooNS::fo, "border-right", TQString() ), Right );
|
|
// TODO: style:border-line-width-right
|
|
}
|
|
|
|
if ( property.hasAttributeNS( ooNS::fo, "border-top" ) )
|
|
{
|
|
loadBorder( tqlayout, property.attributeNS( ooNS::fo, "border-top", TQString() ), Top );
|
|
// TODO: style:border-line-width-top
|
|
}
|
|
|
|
if ( property.hasAttributeNS( ooNS::fo, "border-left" ) )
|
|
{
|
|
loadBorder( tqlayout, property.attributeNS( ooNS::fo, "border-left", TQString() ), Left );
|
|
// TODO: style:border-line-width-left
|
|
}
|
|
|
|
if ( property.hasAttributeNS( ooNS::fo, "border" ) )
|
|
{
|
|
loadBorder( tqlayout, property.attributeNS( ooNS::fo, "border", TQString() ), Border );
|
|
// TODO: style:border-line-width-left
|
|
}
|
|
}
|
|
|
|
void OpenCalcImport::readInStyle( Format * tqlayout, TQDomElement const & style )
|
|
{
|
|
kdDebug(30518) << "** Reading Style: " << style.tagName() << "; " << style.attributeNS( ooNS::style, "name", TQString()) << endl;
|
|
if ( style.localName() == "style" && style.namespaceURI()==ooNS::style)
|
|
{
|
|
if ( style.hasAttributeNS( ooNS::style, "tqparent-style-name" ) )
|
|
{
|
|
Format * cp
|
|
= m_defaultStyles.tqfind( style.attributeNS( ooNS::style, "tqparent-style-name", TQString() ) );
|
|
kdDebug(30518) << "Copying tqlayout from " << style.attributeNS( ooNS::style, "tqparent-style-name", TQString() ) << endl;
|
|
|
|
if ( cp != 0 )
|
|
tqlayout->copy( *cp );
|
|
}
|
|
else if ( style.hasAttributeNS( ooNS::style, "family") )
|
|
{
|
|
TQString name = style.attribute( "style-family" ) + "default";
|
|
Format * cp = m_defaultStyles.tqfind( name );
|
|
|
|
kdDebug(30518) << "Copying tqlayout from " << name << ", " << !cp << endl;
|
|
|
|
if ( cp != 0 )
|
|
tqlayout->copy( *cp );
|
|
}
|
|
|
|
if ( style.hasAttributeNS( ooNS::style, "data-style-name" ) )
|
|
{
|
|
TQString * format = m_formats[ style.attributeNS( ooNS::style, "data-style-name", TQString() ) ];
|
|
FormatType formatType;
|
|
|
|
if ( !format )
|
|
{
|
|
// load and convert it
|
|
TQString name( style.attributeNS( ooNS::style, "data-style-name", TQString() ) );
|
|
format = loadFormat( m_styles[ name ], formatType, name );
|
|
}
|
|
|
|
if ( format )
|
|
{
|
|
tqlayout->setFormatString( *format );
|
|
tqlayout->setFormatType( formatType );
|
|
}
|
|
|
|
// <number:currency-symbol number:language="de" number:country="DE">€</number:currency-symbol>
|
|
}
|
|
}
|
|
|
|
TQDomElement property;
|
|
forEachElement( property, style )
|
|
{
|
|
if ( property.localName() == "properties" && property.namespaceURI() == ooNS::style )
|
|
loadStyleProperties( tqlayout, property );
|
|
|
|
kdDebug(30518) << tqlayout->textFontFamily( 0, 0 ) << endl;
|
|
}
|
|
}
|
|
|
|
bool OpenCalcImport::createStyleMap( TQDomDocument const & styles )
|
|
{
|
|
TQDomElement content = styles.documentElement();
|
|
TQDomNode docStyles = KoDom::namedItemNS( content, ooNS::office, "document-styles" );
|
|
|
|
if ( content.hasAttributeNS( ooNS::office, "version" ) )
|
|
{
|
|
bool ok = true;
|
|
double d = content.attributeNS( ooNS::office, "version", TQString() ).toDouble( &ok );
|
|
|
|
if ( ok )
|
|
{
|
|
kdDebug(30518) << "OpenCalc version: " << d << endl;
|
|
if ( d > 1.0 )
|
|
{
|
|
TQString message( i18n("This document was created with OpenOffice.org version '%1'. This filter was written for version 1.0. Reading this file could cause strange behavior, crashes or incorrect display of the data. Do you want to continue converting the document?") );
|
|
message.tqarg( content.attributeNS( ooNS::office, "version", TQString() ) );
|
|
if ( KMessageBox::warningYesNo( 0, message, i18n( "Unsupported document version" ) ) == KMessageBox::No )
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
|
|
TQDomNode fontStyles = KoDom::namedItemNS( content, ooNS::office, "font-decls" );
|
|
|
|
if ( !fontStyles.isNull() )
|
|
{
|
|
kdDebug(30518) << "Starting reading in font-decl..." << endl;
|
|
|
|
insertStyles( fontStyles.toElement() );
|
|
}
|
|
else
|
|
kdDebug(30518) << "No items found" << endl;
|
|
|
|
kdDebug(30518) << "Starting reading in auto:styles" << endl;
|
|
|
|
TQDomNode autoStyles = KoDom::namedItemNS( content, ooNS::office, "automatic-styles" );
|
|
if ( !autoStyles.isNull() )
|
|
insertStyles( autoStyles.toElement() );
|
|
else
|
|
kdDebug(30518) << "No items found" << endl;
|
|
|
|
|
|
kdDebug(30518) << "Reading in master styles" << endl;
|
|
|
|
TQDomNode masterStyles = KoDom::namedItemNS( content, ooNS::office, "master-styles" );
|
|
|
|
if ( masterStyles.isNull() )
|
|
{
|
|
kdDebug(30518) << "Nothing found " << endl;
|
|
}
|
|
|
|
TQDomElement master = KoDom::namedItemNS( masterStyles, ooNS::style, "master-page");
|
|
if ( !master.isNull() )
|
|
{
|
|
TQString name( "pm" );
|
|
name += master.attributeNS( ooNS::style, "name", TQString() );
|
|
kdDebug(30518) << "Master style: '" << name << "' loaded " << endl;
|
|
m_styles.insert( name, new TQDomElement( master ) );
|
|
|
|
master = master.nextSibling().toElement();
|
|
}
|
|
|
|
|
|
kdDebug(30518) << "Starting reading in office:styles" << endl;
|
|
|
|
TQDomNode fixedStyles = KoDom::namedItemNS( content, ooNS::office, "styles" );
|
|
|
|
kdDebug(30518) << "Reading in default styles" << endl;
|
|
|
|
TQDomNode def = KoDom::namedItemNS( fixedStyles, ooNS::style, "default-style" );
|
|
kdDebug()<<" def !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! :"<<def.isNull()<<endl;
|
|
while ( !def.isNull() )
|
|
{
|
|
TQDomElement e = def.toElement();
|
|
kdDebug(30518) << "Style found " << e.nodeName() << ", tag: " << e.tagName() << endl;
|
|
|
|
if ( e.nodeName() != "style:default-style" )
|
|
{
|
|
def = def.nextSibling();
|
|
continue;
|
|
}
|
|
|
|
if ( !e.isNull() )
|
|
{
|
|
Format * tqlayout = new Format( 0, m_doc->styleManager()->defaultStyle() );
|
|
|
|
readInStyle( tqlayout, e );
|
|
kdDebug(30518) << "Default style " << e.attributeNS( ooNS::style, "family", TQString() ) << "default" << " loaded " << endl;
|
|
|
|
m_defaultStyles.insert( e.attributeNS( ooNS::style, "family", TQString() ) + "default", tqlayout );
|
|
// TQFont font = tqlayout->font();
|
|
// kdDebug(30518) << "Font: " << font.family() << ", " << font.toString() << endl;
|
|
}
|
|
|
|
def = def.nextSibling();
|
|
}
|
|
|
|
TQDomElement defs = KoDom::namedItemNS( fixedStyles, ooNS::style, "style" );
|
|
while ( !defs.isNull() )
|
|
{
|
|
if ( defs.nodeName() != "style:style" )
|
|
break; // done
|
|
|
|
if ( !defs.hasAttributeNS( ooNS::style, "name" ) )
|
|
{
|
|
// ups...
|
|
defs = defs.nextSibling().toElement();
|
|
continue;
|
|
}
|
|
|
|
Format * tqlayout = new Format( 0, m_doc->styleManager()->defaultStyle() );
|
|
readInStyle( tqlayout, defs );
|
|
kdDebug(30518) << "Default style " << defs.attributeNS( ooNS::style, "name", TQString() ) << " loaded " << endl;
|
|
|
|
m_defaultStyles.insert( defs.attributeNS( ooNS::style, "name", TQString() ), tqlayout );
|
|
// kdDebug(30518) << "Font: " << tqlayout->font().family() << ", " << tqlayout->font().toString() << endl;
|
|
|
|
defs = defs.nextSibling().toElement();
|
|
}
|
|
|
|
if ( !fixedStyles.isNull() )
|
|
insertStyles( fixedStyles.toElement() );
|
|
|
|
kdDebug(30518) << "Starting reading in automatic styles" << endl;
|
|
|
|
content = m_content.documentElement();
|
|
autoStyles = KoDom::namedItemNS( content, ooNS::office, "automatic-styles" );
|
|
|
|
if ( !autoStyles.isNull() )
|
|
insertStyles( autoStyles.toElement() );
|
|
|
|
fontStyles = KoDom::namedItemNS( content, ooNS::office, "font-decls" );
|
|
|
|
if ( !fontStyles.isNull() )
|
|
{
|
|
kdDebug(30518) << "Starting reading in special font decl" << endl;
|
|
|
|
insertStyles( fontStyles.toElement() );
|
|
}
|
|
|
|
kdDebug(30518) << "Styles read in." << endl;
|
|
|
|
return true;
|
|
}
|
|
|
|
void OpenCalcImport::loadOasisValidation( Validity* val, const TQString& validationName )
|
|
{
|
|
kdDebug(30518)<<"validationName:"<<validationName<<endl;
|
|
TQDomElement element = m_validationList[validationName];
|
|
if ( element.hasAttributeNS( ooNS::table, "condition" ) )
|
|
{
|
|
TQString valExpression = element.attributeNS( ooNS::table, "condition", TQString() );
|
|
kdDebug(30518)<<" 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.tqcontains( "cell-content-text-length()" ) )
|
|
{
|
|
//"cell-content-text-length()>45"
|
|
valExpression = valExpression.remove("cell-content-text-length()" );
|
|
kdDebug(30518)<<" valExpression = :"<<valExpression<<endl;
|
|
val->m_restriction = Restriction::TextLength;
|
|
|
|
loadOasisValidationCondition( val, valExpression );
|
|
}
|
|
//cell-content-text-length-is-between(Value, Value) | cell-content-text-length-is-not-between(Value, Value)
|
|
else if ( valExpression.tqcontains( "cell-content-text-length-is-between" ) )
|
|
{
|
|
val->m_restriction = Restriction::TextLength;
|
|
val->m_cond = Conditional::Between;
|
|
valExpression = valExpression.remove( "cell-content-text-length-is-between(" );
|
|
kdDebug(30518)<<" valExpression :"<<valExpression<<endl;
|
|
valExpression = valExpression.remove( ")" );
|
|
TQStringList listVal = TQStringList::split( ",", valExpression );
|
|
loadOasisValidationValue( val, listVal );
|
|
}
|
|
else if ( valExpression.tqcontains( "cell-content-text-length-is-not-between" ) )
|
|
{
|
|
val->m_restriction = Restriction::TextLength;
|
|
val->m_cond = Conditional::Different;
|
|
valExpression = valExpression.remove( "cell-content-text-length-is-not-between(" );
|
|
kdDebug(30518)<<" valExpression :"<<valExpression<<endl;
|
|
valExpression = valExpression.remove( ")" );
|
|
kdDebug(30518)<<" valExpression :"<<valExpression<<endl;
|
|
TQStringList listVal = TQStringList::split( ",", valExpression );
|
|
loadOasisValidationValue( val, listVal );
|
|
|
|
}
|
|
//TrueFunction ::= cell-content-is-whole-number() | cell-content-is-decimal-number() | cell-content-is-date() | cell-content-is-time()
|
|
else
|
|
{
|
|
if (valExpression.tqcontains( "cell-content-is-whole-number()" ) )
|
|
{
|
|
val->m_restriction = Restriction::Number;
|
|
valExpression = valExpression.remove( "cell-content-is-whole-number() and " );
|
|
}
|
|
else if (valExpression.tqcontains( "cell-content-is-decimal-number()" ) )
|
|
{
|
|
val->m_restriction = Restriction::Integer;
|
|
valExpression = valExpression.remove( "cell-content-is-decimal-number() and " );
|
|
}
|
|
else if (valExpression.tqcontains( "cell-content-is-date()" ) )
|
|
{
|
|
val->m_restriction = Restriction::Date;
|
|
valExpression = valExpression.remove( "cell-content-is-date() and " );
|
|
}
|
|
else if (valExpression.tqcontains( "cell-content-is-time()" ) )
|
|
{
|
|
val->m_restriction = Restriction::Time;
|
|
valExpression = valExpression.remove( "cell-content-is-time() and " );
|
|
}
|
|
kdDebug(30518)<<"valExpression :"<<valExpression<<endl;
|
|
|
|
if ( valExpression.tqcontains( "cell-content()" ) )
|
|
{
|
|
valExpression = valExpression.remove( "cell-content()" );
|
|
loadOasisValidationCondition( val, 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.tqcontains( "cell-content-is-between(" ) )
|
|
{
|
|
valExpression = valExpression.remove( "cell-content-is-between(" );
|
|
valExpression = valExpression.remove( ")" );
|
|
TQStringList listVal = TQStringList::split( "," , valExpression );
|
|
loadOasisValidationValue( val, listVal );
|
|
|
|
val->m_cond = Conditional::Between;
|
|
}
|
|
if ( valExpression.tqcontains( "cell-content-is-not-between(" ) )
|
|
{
|
|
valExpression = valExpression.remove( "cell-content-is-not-between(" );
|
|
valExpression = valExpression.remove( ")" );
|
|
TQStringList listVal = TQStringList::split( ",", valExpression );
|
|
loadOasisValidationValue( val, listVal );
|
|
val->m_cond = Conditional::Different;
|
|
}
|
|
}
|
|
}
|
|
if ( element.hasAttributeNS( ooNS::table, "allow-empty-cell" ) )
|
|
{
|
|
val->allowEmptyCell = ( ( element.attributeNS( ooNS::table, "allow-empty-cell", TQString() )=="true" ) ? true : false );
|
|
|
|
}
|
|
if ( element.hasAttributeNS( ooNS::table, "base-cell-address" ) )
|
|
{
|
|
//todo what is it ?
|
|
}
|
|
|
|
TQDomElement help = KoDom::namedItemNS( element, ooNS::table, "help-message" );
|
|
if ( !help.isNull() )
|
|
{
|
|
if ( help.hasAttributeNS( ooNS::table, "title" ) )
|
|
val->titleInfo = help.attributeNS( ooNS::table, "title", TQString() );
|
|
if ( help.hasAttributeNS( ooNS::table, "display" ) )
|
|
val->displayValidationInformation = ( ( help.attributeNS( ooNS::table, "display", TQString() )=="true" ) ? true : false );
|
|
TQDomElement attrText = KoDom::namedItemNS( help, ooNS::text, "p" );
|
|
if ( !attrText.isNull() )
|
|
val->messageInfo = attrText.text();
|
|
}
|
|
|
|
TQDomElement error = KoDom::namedItemNS( element, ooNS::table, "error-message" );
|
|
if ( !error.isNull() )
|
|
{
|
|
if ( error.hasAttributeNS( ooNS::table, "title" ) )
|
|
val->title = error.attributeNS( ooNS::table, "title", TQString() );
|
|
if ( error.hasAttributeNS( ooNS::table, "message-type" ) )
|
|
{
|
|
TQString str = error.attributeNS( ooNS::table, "message-type", TQString() );
|
|
if ( str == "warning" )
|
|
val->m_action = Action::Warning;
|
|
else if ( str == "information" )
|
|
val->m_action = Action::Information;
|
|
else if ( str == "stop" )
|
|
val->m_action = Action::Stop;
|
|
else
|
|
kdDebug(30518)<<"validation : message type unknown :"<<str<<endl;
|
|
}
|
|
|
|
if ( error.hasAttributeNS( ooNS::table, "display" ) )
|
|
{
|
|
kdDebug(30518)<<" display message :"<<error.attributeNS( ooNS::table, "display", TQString() )<<endl;
|
|
val->displayMessage = (error.attributeNS( ooNS::table, "display", TQString() )=="true");
|
|
}
|
|
TQDomElement attrText = KoDom::namedItemNS( error, ooNS::text, "p" );
|
|
if ( !attrText.isNull() )
|
|
val->message = attrText.text();
|
|
}
|
|
}
|
|
|
|
void OpenCalcImport::loadOasisValidationValue( Validity* val, const TQStringList &listVal )
|
|
{
|
|
bool ok = false;
|
|
kdDebug(30518)<<" listVal[0] :"<<listVal[0]<<" listVal[1] :"<<listVal[1]<<endl;
|
|
|
|
if ( val->m_restriction == Restriction::Date )
|
|
{
|
|
val->dateMin = TQDate::fromString( listVal[0] );
|
|
val->dateMax = TQDate::fromString( listVal[1] );
|
|
}
|
|
else if ( val->m_restriction == Restriction::Time )
|
|
{
|
|
val->timeMin = TQTime::fromString( listVal[0] );
|
|
val->timeMax = TQTime::fromString( listVal[1] );
|
|
}
|
|
else
|
|
{
|
|
val->valMin = listVal[0].toDouble(&ok);
|
|
if ( !ok )
|
|
{
|
|
val->valMin = listVal[0].toInt(&ok);
|
|
if ( !ok )
|
|
kdDebug(30518)<<" Try to parse this value :"<<listVal[0]<<endl;
|
|
|
|
#if 0
|
|
if ( !ok )
|
|
val->valMin = listVal[0];
|
|
#endif
|
|
}
|
|
ok=false;
|
|
val->valMax = listVal[1].toDouble(&ok);
|
|
if ( !ok )
|
|
{
|
|
val->valMax = listVal[1].toInt(&ok);
|
|
if ( !ok )
|
|
kdDebug(30518)<<" Try to parse this value :"<<listVal[1]<<endl;
|
|
|
|
#if 0
|
|
if ( !ok )
|
|
val->valMax = listVal[1];
|
|
#endif
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void OpenCalcImport::loadOasisValidationCondition( Validity* val,TQString &valExpression )
|
|
{
|
|
TQString value;
|
|
if (valExpression.tqcontains( "<=" ) )
|
|
{
|
|
value = valExpression.remove( "<=" );
|
|
val->m_cond = Conditional::InferiorEqual;
|
|
}
|
|
else if (valExpression.tqcontains( ">=" ) )
|
|
{
|
|
value = valExpression.remove( ">=" );
|
|
val->m_cond = Conditional::SuperiorEqual;
|
|
}
|
|
else if (valExpression.tqcontains( "!=" ) )
|
|
{
|
|
//add Differentto attribute
|
|
value = valExpression.remove( "!=" );
|
|
val->m_cond = Conditional::DifferentTo;
|
|
}
|
|
else if ( valExpression.tqcontains( "<" ) )
|
|
{
|
|
value = valExpression.remove( "<" );
|
|
val->m_cond = Conditional::Inferior;
|
|
}
|
|
else if(valExpression.tqcontains( ">" ) )
|
|
{
|
|
value = valExpression.remove( ">" );
|
|
val->m_cond = Conditional::Superior;
|
|
}
|
|
else if (valExpression.tqcontains( "=" ) )
|
|
{
|
|
value = valExpression.remove( "=" );
|
|
val->m_cond = Conditional::Equal;
|
|
}
|
|
else
|
|
kdDebug(30518)<<" I don't know how to parse it :"<<valExpression<<endl;
|
|
kdDebug(30518)<<" value :"<<value<<endl;
|
|
if ( val->m_restriction == Restriction::Date )
|
|
{
|
|
val->dateMin = TQDate::fromString( value );
|
|
}
|
|
else if ( val->m_restriction == Restriction::Date )
|
|
{
|
|
val->timeMin = TQTime::fromString( value );
|
|
}
|
|
else
|
|
{
|
|
bool ok = false;
|
|
val->valMin = value.toDouble(&ok);
|
|
if ( !ok )
|
|
{
|
|
val->valMin = value.toInt(&ok);
|
|
if ( !ok )
|
|
kdDebug(30518)<<" Try to parse this value :"<<value<<endl;
|
|
|
|
#if 0
|
|
if ( !ok )
|
|
val->valMin = value;
|
|
#endif
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
int OpenCalcImport::readMetaData()
|
|
{
|
|
int result = 5;
|
|
KoDocumentInfo * docInfo = m_doc->documentInfo();
|
|
KoDocumentInfoAbout * aboutPage = static_cast<KoDocumentInfoAbout *>(docInfo->page( "about" ));
|
|
KoDocumentInfoAuthor * authorPage = static_cast<KoDocumentInfoAuthor*>(docInfo->page( "author" ));
|
|
|
|
TQDomNode meta = KoDom::namedItemNS( m_meta, ooNS::office, "document-meta" );
|
|
TQDomNode office = KoDom::namedItemNS( meta, ooNS::office, "meta" );
|
|
|
|
if ( office.isNull() )
|
|
return 2;
|
|
|
|
TQDomElement e = KoDom::namedItemNS( office, ooNS::dc, "creator" );
|
|
if ( !e.isNull() && !e.text().isEmpty() )
|
|
authorPage->setFullName( e.text() );
|
|
|
|
e = KoDom::namedItemNS( office, ooNS::dc, "title" );
|
|
if ( !e.isNull() && !e.text().isEmpty() )
|
|
aboutPage->setTitle( e.text() );
|
|
|
|
e = KoDom::namedItemNS( office, ooNS::dc, "description" );
|
|
if ( !e.isNull() && !e.text().isEmpty() )
|
|
aboutPage->setAbstract( e.text() );
|
|
|
|
e = KoDom::namedItemNS( office, ooNS::dc, "subject" );
|
|
if ( !e.isNull() && !e.text().isEmpty() )
|
|
aboutPage->setSubject( e.text() );
|
|
|
|
e= KoDom::namedItemNS( office, ooNS::meta, "keywords" );
|
|
if ( !e.isNull() )
|
|
{
|
|
e = KoDom::namedItemNS( e, ooNS::meta, "keyword" );
|
|
if ( !e.isNull() && !e.text().isEmpty() )
|
|
aboutPage->setKeywords( e.text() );
|
|
}
|
|
|
|
e = KoDom::namedItemNS( office, ooNS::meta, "document-statistic" );
|
|
if ( !e.isNull() && e.hasAttributeNS( ooNS::meta, "table-count" ) )
|
|
{
|
|
bool ok = false;
|
|
result = e.attributeNS( ooNS::meta, "table-count", TQString() ).toInt( &ok );
|
|
if ( !ok )
|
|
result = 5;
|
|
}
|
|
|
|
m_meta.clear(); // not needed anymore
|
|
|
|
return result;
|
|
}
|
|
|
|
KoFilter::ConversiontqStatus OpenCalcImport::convert( TQCString const & from, TQCString const & to )
|
|
{
|
|
kdDebug(30518) << "Entering OpenCalc Import filter: " << from << " - " << to << endl;
|
|
|
|
KoDocument * document = m_chain->outputDocument();
|
|
if ( !document )
|
|
return KoFilter::StupidError;
|
|
|
|
if ( !::tqqt_cast<const KSpread::Doc *>( document ) ) // it's safer that way :)
|
|
{
|
|
kdWarning(30518) << "document isn't a KSpread::Doc but a " << document->className() << endl;
|
|
return KoFilter::NotImplemented;
|
|
}
|
|
|
|
if ( ( from != "application/vnd.sun.xml.calc" && from != "application/vnd.sun.xml.calc.template") || to != "application/x-kspread" )
|
|
{
|
|
kdWarning(30518) << "Invalid mimetypes " << from << " " << to << endl;
|
|
return KoFilter::NotImplemented;
|
|
}
|
|
|
|
m_doc = ( Doc * ) document;
|
|
|
|
if ( m_doc->mimeType() != "application/x-kspread" )
|
|
{
|
|
kdWarning(30518) << "Invalid document mimetype " << m_doc->mimeType() << endl;
|
|
return KoFilter::NotImplemented;
|
|
}
|
|
|
|
kdDebug(30518) << "Opening file " << endl;
|
|
|
|
KoFilter::ConversiontqStatus pretqStatus = openFile();
|
|
|
|
if ( pretqStatus != KoFilter::OK )
|
|
return pretqStatus;
|
|
|
|
emit sigProgress( 13 );
|
|
int tables = readMetaData();
|
|
|
|
emit sigProgress( 15 );
|
|
|
|
if ( !parseBody( tables ) )
|
|
return KoFilter::StupidError;
|
|
|
|
emit sigProgress( 100 );
|
|
return KoFilter::OK;
|
|
}
|
|
|
|
KoFilter::ConversiontqStatus OpenCalcImport::openFile()
|
|
{
|
|
KoStore * store = KoStore::createStore( m_chain->inputFile(), KoStore::Read);
|
|
|
|
kdDebug(30518) << "Store created" << endl;
|
|
|
|
if ( !store )
|
|
{
|
|
kdWarning(30518) << "Couldn't open the requested file." << endl;
|
|
return KoFilter::FileNotFound;
|
|
}
|
|
|
|
kdDebug(30518) << "Trying to open content.xml" << endl;
|
|
TQString messageError;
|
|
loadAndParse( m_content, "content.xml", store);
|
|
kdDebug(30518) << "Opened" << endl;
|
|
|
|
TQDomDocument styles;
|
|
kdDebug(30518) << "file content.xml loaded " << endl;
|
|
|
|
loadAndParse( styles, "styles.xml", store);
|
|
|
|
loadAndParse( m_meta, "meta.xml", store);
|
|
loadAndParse( m_settings, "settings.xml", store);
|
|
|
|
delete store;
|
|
|
|
emit sigProgress( 10 );
|
|
|
|
if ( !createStyleMap( styles ) )
|
|
return KoFilter::UserCancelled;
|
|
|
|
return KoFilter::OK;
|
|
}
|
|
|
|
KoFilter::ConversiontqStatus OpenCalcImport::loadAndParse( TQDomDocument& doc, const TQString& fileName,KoStore *m_store )
|
|
{
|
|
return OoUtils::loadAndParse( fileName, doc, m_store);
|
|
}
|
|
|
|
#include "opencalcimport.moc"
|
|
|