/* This file is part of the KDE project Copyright (C) 2000 David Faure Copyright (C) 2000 Norbert Andres Copyright (C) 2005 Laurent Montel 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace KSpread; typedef TQValueList AreaList; class OpenCalcExportFactory : KGenericFactory { public: OpenCalcExportFactory(void) : KGenericFactory ("kspreadopencalcexport") {} protected: virtual void setupTranslations( void ) { TDEGlobal::locale()->insertCatalogue( "kofficefilters" ); } }; K_EXPORT_COMPONENT_FACTORY( libopencalcexport, OpenCalcExportFactory() ) #define STOPEXPORT \ do \ { \ delete store; \ return false; \ } while(0) OpenCalcExport::OpenCalcExport( KoFilter *, const char *, const TQStringList & ) : KoFilter(), m_locale( 0 ) { } KoFilter::ConversionStatus OpenCalcExport::convert( const TQCString & from, const TQCString & to ) { /* later... KSpreadLeader * leader = new KSpreadLeader( m_chain ); OpenCalcWorker * worker = new OpenCalcWorker(); leader->setWorker( worker ); KoFilter::ConversionStatus status = leader->convert(); delete worker; delete leader; return status; */ KoDocument * document = m_chain->inputDocument(); if ( !document ) return KoFilter::StupidError; if ( !::tqqt_cast( document ) ) { kdWarning(30518) << "document isn't a KSpread::Doc but a " << document->className() << endl; return KoFilter::NotImplemented; } if ( ( to != "application/vnd.sun.xml.calc") || (from != "application/x-kspread" ) ) { kdWarning(30518) << "Invalid mimetypes " << to << " " << from << endl; return KoFilter::NotImplemented; } const Doc * ksdoc = static_cast(document); if ( ksdoc->mimeType() != "application/x-kspread" ) { kdWarning(30518) << "Invalid document mimetype " << ksdoc->mimeType() << endl; return KoFilter::NotImplemented; } m_locale = static_cast(document)->locale(); if ( !writeFile( ksdoc ) ) return KoFilter::CreationError; emit sigProgress( 100 ); return KoFilter::OK; } bool OpenCalcExport::writeFile( const Doc * ksdoc ) { KoStore * store = KoStore::createStore( m_chain->outputFile(), KoStore::Write, "", KoStore::Zip ); if ( !store ) return false; uint filesWritten = 0; if ( !exportContent( store, ksdoc ) ) STOPEXPORT; else filesWritten |= contentXML; // TODO: pass sheet number and cell number if ( !exportDocInfo( store, ksdoc ) ) STOPEXPORT; else filesWritten |= metaXML; if ( !exportStyles( store, ksdoc ) ) STOPEXPORT; else filesWritten |= stylesXML; if ( !exportSettings( store, ksdoc ) ) STOPEXPORT; else filesWritten |= settingsXML; if ( !writeMetaFile( store, filesWritten ) ) STOPEXPORT; // writes zip file to disc delete store; store = 0; return true; } bool OpenCalcExport::exportDocInfo( KoStore * store, const Doc* ksdoc ) { if ( !store->open( "meta.xml" ) ) return false; KoDocumentInfo * docInfo = ksdoc->documentInfo(); KoDocumentInfoAbout * aboutPage = static_cast( docInfo->page( "about" ) ); KoDocumentInfoAuthor * authorPage = static_cast( docInfo->page( "author" ) ); TQDomDocument meta; meta.appendChild( meta.createProcessingInstruction( "xml","version=\"1.0\" encoding=\"UTF-8\"" ) ); TQDomElement content = meta.createElement( "office:document-meta" ); content.setAttribute( "xmlns:office", "http://openoffice.org/2000/office"); content.setAttribute( "xmlns:xlink", "http://www.w3.org/1999/xlink" ); content.setAttribute( "xmlns:dc", "http://purl.org/dc/elements/1.1/" ); content.setAttribute( "xmlns:meta", "http://openoffice.org/2000/meta" ); content.setAttribute( "office:version", "1.0" ); TQDomNode officeMeta = meta.createElement( "office:meta" ); TQDomElement data = meta.createElement( "meta:generator" ); TQString app( "KSpread " ); app += KSpread::version; data.appendChild( meta.createTextNode( app ) ); officeMeta.appendChild( data ); data = meta.createElement( "meta:initial-creator" ); data.appendChild( meta.createTextNode( authorPage->fullName() ) ); officeMeta.appendChild( data ); data = meta.createElement( "meta:creator" ); data.appendChild( meta.createTextNode( authorPage->fullName() ) ); officeMeta.appendChild( data ); data = meta.createElement( "dc:description" ); data.appendChild( meta.createTextNode( aboutPage->abstract() ) ); officeMeta.appendChild( data ); data = meta.createElement( "meta:keywords" ); TQDomElement dataItem = meta.createElement( "meta:keyword" ); dataItem.appendChild( meta.createTextNode( aboutPage->keywords() ) ); data.appendChild( dataItem ); officeMeta.appendChild( data ); data = meta.createElement( "dc:title" ); data.appendChild( meta.createTextNode( aboutPage->title() ) ); officeMeta.appendChild( data ); data = meta.createElement( "dc:subject" ); data.appendChild( meta.createTextNode( aboutPage->subject() ) ); officeMeta.appendChild( data ); const TQDateTime dt ( TQDateTime::currentDateTime() ); if ( dt.isValid() ) { data = meta.createElement( "dc:date" ); data.appendChild( meta.createTextNode( dt.toString( Qt::ISODate ) ) ); officeMeta.appendChild( data ); } /* TODO: 2003-01-08T23:57:31 en-US 2 PT38S */ data = meta.createElement( "meta:document-statistic" ); data.setAttribute( "meta:table-count", TQString::number( ksdoc->map()->count() ) ); // TODO: data.setAttribute( "meta:cell-count", ); officeMeta.appendChild( data ); content.appendChild( officeMeta ); meta.appendChild( content ); TQCString doc( meta.toCString() ); kdDebug(30518) << "Meta: " << doc << endl; store->write( doc, doc.length() ); if ( !store->close() ) return false; return true; } bool OpenCalcExport::exportSettings( KoStore * store, const Doc * ksdoc ) { if ( !store->open( "settings.xml" ) ) return false; TQDomDocument doc; doc.appendChild( doc.createProcessingInstruction( "xml","version=\"1.0\" encoding=\"UTF-8\"" ) ); TQDomElement settings = doc.createElement( "office:document-settings" ); settings.setAttribute( "xmlns:office", "http://openoffice.org/2000/office"); settings.setAttribute( "xmlns:xlink", "http://www.w3.org/1999/xlink" ); settings.setAttribute( "xmlns:config", "http://openoffice.org/2001/config" ); settings.setAttribute( "office:version", "1.0" ); TQDomElement begin = doc.createElement( "office:settings" ); TQDomElement configItem = doc.createElement("config:config-item-set" ); configItem.setAttribute( "config:name", "view-settings" ); TQDomElement mapIndexed = doc.createElement( "config:config-item-map-indexed" ); mapIndexed.setAttribute("config:name", "Views" ); configItem.appendChild( mapIndexed ); TQDomElement mapItem = doc.createElement("config:config-item-map-entry" ); TQDomElement attribute = doc.createElement("config:config-item" ); attribute.setAttribute( "config:name", "ActiveTable" ); attribute.setAttribute( "config:type", "string" ); View * view = static_cast( ksdoc->views().getFirst()); TQString activeTable; if ( view ) // no view if embedded document { Canvas * canvas = view->canvasWidget(); activeTable = canvas->activeSheet()->sheetName(); // save current sheet selection before to save marker, otherwise current pos is not saved view->saveCurrentSheetSelection(); } attribute.appendChild( doc.createTextNode( activeTable ) ); mapItem.appendChild( attribute ); TQDomElement configmaped = doc.createElement( "config:config-item-map-named" ); configmaped.setAttribute( "config:name","Tables" ); TQPtrListIterator it( ksdoc->map()->sheetList() ); for( ; it.current(); ++it ) { TQPoint marker; if ( view ) { marker = view->markerFromSheet( *it ); } TQDomElement tmpItemMapNamed = doc.createElement( "config:config-item-map-entry" ); tmpItemMapNamed.setAttribute( "config:name", ( *it )->tableName() ); TQDomElement sheetAttribute = doc.createElement( "config:config-item" ); sheetAttribute.setAttribute( "config:name", "CursorPositionX" ); sheetAttribute.setAttribute( "config:type", "int" ); sheetAttribute.appendChild( doc.createTextNode( TQString::number(marker.x() ) ) ); tmpItemMapNamed.appendChild( sheetAttribute ); sheetAttribute = doc.createElement( "config:config-item" ); sheetAttribute.setAttribute( "config:name", "CursorPositionY" ); sheetAttribute.setAttribute( "config:type", "int" ); sheetAttribute.appendChild( doc.createTextNode( TQString::number(marker.y() ) ) ); tmpItemMapNamed.appendChild( sheetAttribute ); configmaped.appendChild( tmpItemMapNamed ); } mapItem.appendChild( configmaped ); mapIndexed.appendChild( mapItem ); begin.appendChild( configItem ); settings.appendChild( begin ); doc.appendChild( settings ); TQCString f( doc.toCString() ); kdDebug(30518) << "Settings: " << (char const * ) f << endl; store->write( f, f.length() ); if ( !store->close() ) return false; return true; } bool OpenCalcExport::exportContent( KoStore * store, const Doc * ksdoc ) { if ( !store->open( "content.xml" ) ) return false; createDefaultStyles(); TQDomDocument doc; doc.appendChild( doc.createProcessingInstruction( "xml","version=\"1.0\" encoding=\"UTF-8\"" ) ); TQDomElement content = doc.createElement( "office:document-content" ); content.setAttribute( "xmlns:office", "http://openoffice.org/2000/office"); content.setAttribute( "xmlns:style", "http://openoffice.org/2000/style" ); content.setAttribute( "xmlns:text", "http://openoffice.org/2000/text" ); content.setAttribute( "xmlns:table", "http://openoffice.org/2000/table" ); content.setAttribute( "xmlns:draw", "http://openoffice.org/2000/drawing" ); content.setAttribute( "xmlns:fo", "http://www.w3.org/1999/XSL/Format" ); content.setAttribute( "xmlns:xlink", "http://www.w3.org/1999/xlink" ); content.setAttribute( "xmlns:number", "http://openoffice.org/2000/datastyle" ); content.setAttribute( "xmlns:svg", "http://www.w3.org/2000/svg" ); content.setAttribute( "xmlns:chart", "http://openoffice.org/2000/chart" ); content.setAttribute( "xmlns:dr3d", "http://openoffice.org/2000/dr3d" ); content.setAttribute( "xmlns:math", "http://www.w3.org/1998/Math/MathML" ); content.setAttribute( "xmlns:form", "http://openoffice.org/2000/form" ); content.setAttribute( "xmlns:script", "http://openoffice.org/2000/script" ); content.setAttribute( "office:class", "spreadsheet" ); content.setAttribute( "office:version", "1.0" ); TQDomElement data = doc.createElement( "office:script" ); content.appendChild( data ); if ( !exportBody( doc, content, ksdoc ) ) return false; doc.appendChild( content ); TQCString f( doc.toCString() ); kdDebug(30518) << "Content: " << (char const * ) f << endl; store->write( f, f.length() ); if ( !store->close() ) return false; return true; } void exportNamedExpr( TQDomDocument & doc, TQDomElement & parent, AreaList const & namedAreas ) { AreaList::const_iterator it = namedAreas.begin(); AreaList::const_iterator end = namedAreas.end(); while ( it != end ) { TQDomElement namedRange = doc.createElement( "table:named-range" ); Reference ref = *it; namedRange.setAttribute( "table:name", ref.ref_name ); namedRange.setAttribute( "table:base-cell-address", convertRefToBase( ref.sheet_name, ref.rect ) ); namedRange.setAttribute( "table:cell-range-address", convertRefToRange( ref.sheet_name, ref.rect ) ); parent.appendChild( namedRange ); ++it; } } bool OpenCalcExport::exportBody( TQDomDocument & doc, TQDomElement & content, const Doc * ksdoc ) { TQDomElement fontDecls = doc.createElement( "office:font-decls" ); TQDomElement autoStyles = doc.createElement( "office:automatic-styles" ); TQDomElement body = doc.createElement( "office:body" ); if ( ksdoc->map()->isProtected() ) { body.setAttribute( "table:structure-protected", "true" ); TQCString passwd; ksdoc->map()->password( passwd ); if ( passwd.length() > 0 ) { TQCString str( KCodecs::base64Encode( passwd ) ); body.setAttribute( "table:protection-key", TQString( str.data() ) ); } } TQPtrListIterator it( ksdoc->map()->sheetList() ); for( it.toFirst(); it.current(); ++it ) { SheetStyle ts; int maxCols = 1; int maxRows = 1; Sheet * sheet = it.current(); ts.visible = !sheet->isHidden(); TQDomElement tabElem = doc.createElement( "table:table" ); tabElem.setAttribute( "table:style-name", m_styles.sheetStyle( ts ) ); if ( sheet->isProtected() ) { tabElem.setAttribute( "table:protected", "true" ); TQCString passwd; sheet->password( passwd ); if ( passwd.length() > 0 ) { TQCString str( KCodecs::base64Encode( passwd ) ); tabElem.setAttribute( "table:protection-key", TQString( str.data() ) ); } } TQString name( sheet->tableName() ); int n = name.find( ' ' ); if ( n != -1 ) { kdDebug(30518) << "Sheet name converting: " << name << endl; name[n] == '_'; kdDebug(30518) << "Sheet name converted: " << name << endl; } name = name.replace( ' ', "_" ); TQRect _printRange = sheet->print()->printRange(); if ( _printRange != ( TQRect( TQPoint( 1, 1 ), TQPoint( KS_colMax, KS_rowMax ) ) ) ) { TQString range= convertRangeToRef( name, _printRange ); //kdDebug(30518)<<" range : "<inputDocument(); Doc * kspreadDoc = static_cast( document ); AreaList namedAreas = kspreadDoc->listArea(); if ( namedAreas.count() > 0 ) { TQDomElement namedExpr = doc.createElement( "table:named-expressions" ); exportNamedExpr( doc, namedExpr, namedAreas ); body.appendChild( namedExpr ); } m_styles.writeStyles( doc, autoStyles ); m_styles.writeFontDecl( doc, fontDecls ); content.appendChild( fontDecls ); content.appendChild( autoStyles ); content.appendChild( body ); return true; } void OpenCalcExport::exportSheet( TQDomDocument & doc, TQDomElement & tabElem, const Sheet * sheet, int maxCols, int maxRows ) { kdDebug(30518) << "exportSheet: " << sheet->tableName() << endl; int i = 1; while ( i <= maxCols ) { const ColumnFormat * column = sheet->columnFormat( i ); ColumnStyle cs; cs.breakB = ::Style::automatic; cs.size = column->mmWidth() / 10; bool hide = column->isHide(); int j = i + 1; int repeated = 1; while ( j <= maxCols ) { const ColumnFormat *c = sheet->columnFormat( j ); ColumnStyle cs1; cs1.breakB = ::Style::automatic; cs1.size = c->mmWidth() / 10; if ( ColumnStyle::isEqual( &cs, cs1 ) && ( hide == c->isHide() ) ) ++repeated; else break; ++j; } TQDomElement colElem = doc.createElement( "table:table-column" ); colElem.setAttribute( "table:style-name", m_styles.columnStyle( cs ) ); colElem.setAttribute( "table:default-cell-style-name", "Default" );//todo fixme create style from cell if ( hide ) colElem.setAttribute( "table:visibility", "collapse" ); if ( repeated > 1 ) colElem.setAttribute( "table:number-columns-repeated", TQString::number( repeated ) ); tabElem.appendChild( colElem ); i += repeated; } for ( i = 1; i <= maxRows; ++i ) { const RowFormat * row = sheet->rowFormat( i ); RowStyle rs; rs.breakB = ::Style::automatic; rs.size = row->mmHeight() / 10; TQDomElement rowElem = doc.createElement( "table:table-row" ); rowElem.setAttribute( "table:style-name", m_styles.rowStyle( rs ) ); if ( row->isHide() ) rowElem.setAttribute( "table:visibility", "collapse" ); exportCells( doc, rowElem, sheet, i, maxCols ); tabElem.appendChild( rowElem ); } } void OpenCalcExport::exportCells( TQDomDocument & doc, TQDomElement & rowElem, const Sheet *sheet, int row, int maxCols ) { int i = 1; while ( i <= maxCols ) { int repeated = 1; bool hasComment = false; const Cell* cell = sheet->cellAt( i, row ); TQDomElement cellElem; if ( !cell->isPartOfMerged() ) cellElem = doc.createElement( "table:table-cell" ); else cellElem = doc.createElement( "table:covered-table-cell" ); 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; } CellStyle c; CellStyle::loadData( c, cell ); // TODO: number style cellElem.setAttribute( "table:style-name", m_styles.cellStyle( c ) ); // group empty cells with the same style if ( cell->isEmpty() && !hasComment && !cell->isPartOfMerged() && !cell->doesMergeCells() ) { int j = i + 1; while ( j <= maxCols ) { const Cell *cell1 = sheet->cellAt( j, row ); CellStyle c1; CellStyle::loadData( c1, cell1 ); // TODO: number style if ( cell1->isEmpty() && !cell->format()->hasProperty( Format::PComment ) && CellStyle::isEqual( &c, c1 ) && !cell->isPartOfMerged() && !cell->doesMergeCells() ) ++repeated; else break; ++j; } if ( repeated > 1 ) cellElem.setAttribute( "table:number-columns-repeated", TQString::number( repeated ) ); } if ( value.isBoolean() ) { kdDebug(30518) << "Type: Boolean" << endl; cellElem.setAttribute( "table:value-type", "boolean" ); cellElem.setAttribute( "table:boolean-value", ( value.asBoolean() ? "true" : "false" ) ); } else if ( value.isNumber() ) { kdDebug(30518) << "Type: Number" << endl; FormatType type = cell->format()->getFormatType( i, row ); if ( type == Percentage_format ) cellElem.setAttribute( "table:value-type", "percentage" ); else cellElem.setAttribute( "table:value-type", "float" ); cellElem.setAttribute( "table:value", TQString::number( value.asFloat() ) ); } else { kdDebug(30518) << "Type: " << value.type() << endl; } if ( cell->isFormula() ) { kdDebug(30518) << "Formula found" << endl; TQString formula( convertFormula( cell->text() ) ); cellElem.setAttribute( "table:formula", formula ); } else if ( !cell->link().isEmpty() ) { TQDomElement link = doc.createElement( "text:p" ); TQDomElement linkref = doc.createElement( "text:a" ); TQString tmp = cell->link(); if ( localReferenceAnchor( tmp ) ) linkref.setAttribute( "xlink:href", ( "#"+tmp ) ); else linkref.setAttribute( "xlink:href", tmp ); linkref.appendChild( doc.createTextNode( cell->text() ) ); link.appendChild( linkref ); cellElem.appendChild( link ); } else if ( !cell->isEmpty() ) { TQDomElement textElem = doc.createElement( "text:p" ); textElem.appendChild( doc.createTextNode( cell->strOutText() ) ); cellElem.appendChild( textElem ); kdDebug(30518) << "Cell StrOut: " << cell->strOutText() << endl; } if ( cell->doesMergeCells() ) { int colSpan = cell->mergedXCells() + 1; int rowSpan = cell->mergedYCells() + 1; if ( colSpan > 1 ) cellElem.setAttribute( "table:number-columns-spanned", TQString::number( colSpan ) ); if ( rowSpan > 1 ) cellElem.setAttribute( "table:number-rows-spanned", TQString::number( rowSpan ) ); } if ( hasComment ) { TQString comment( cell->format()->comment( i, row ) ); TQDomElement annotation = doc.createElement( "office:annotation" ); TQDomElement text = doc.createElement( "text:p" ); text.appendChild( doc.createTextNode( comment ) ); annotation.appendChild( text ); cellElem.appendChild( annotation ); } rowElem.appendChild( cellElem ); i += repeated; } } void OpenCalcExport::maxRowCols( const Sheet *sheet, int & maxCols, int & maxRows ) { Cell const * cell = sheet->firstCell(); while ( cell ) { if ( cell->column() > maxCols ) maxCols = cell->column(); if ( cell->row() > maxRows ) maxRows = cell->row(); cell = cell->nextCell(); } RowFormat const * row = sheet->firstRow(); while ( row ) { if ( row->row() > maxRows ) maxRows = row->row(); row = row->next(); } ColumnFormat const * col = sheet->firstCol(); while ( col ) { if ( col->column() > maxCols ) maxCols = col->column(); col = col->next(); } } bool OpenCalcExport::exportStyles( KoStore * store, const Doc *ksdoc ) { if ( !store->open( "styles.xml" ) ) return false; TQDomDocument doc; doc.appendChild( doc.createProcessingInstruction( "xml","version=\"1.0\" encoding=\"UTF-8\"" ) ); TQDomElement content = doc.createElement( "office:document-styles" ); content.setAttribute( "xmlns:office", "http://openoffice.org/2000/office" ); content.setAttribute( "xmlns:style", "http://openoffice.org/2000/style" ); content.setAttribute( "xmlns:text", "http://openoffice.org/2000/text" ); content.setAttribute( "xmlns:table", "http://openoffice.org/2000/table" ); content.setAttribute( "xmlns:draw", "http://openoffice.org/2000/drawing" ); content.setAttribute( "xmlns:fo", "http://www.w3.org/1999/XSL/Format" ); content.setAttribute( "xmlns:xlink", "http://www.w3.org/1999/xlink" ); content.setAttribute( "xmlns:number", "http://openoffice.org/2000/datastyle" ); content.setAttribute( "xmlns:svg", "http://www.w3.org/2000/svg" ); content.setAttribute( "xmlns:chart", "http://openoffice.org/2000/chart" ); content.setAttribute( "xmlns:dr3d", "http://openoffice.org/2000/dr3d" ); content.setAttribute( "xmlns:math", "http://www.w3.org/1998/Math/MathML" ); content.setAttribute( "xmlns:form", "http://openoffice.org/2000/form" ); content.setAttribute( "xmlns:script", "http://openoffice.org/2000/script" ); content.setAttribute( "office:version", "1.0" ); // order important here! TQDomElement officeStyles = doc.createElement( "office:styles" ); exportDefaultCellStyle( doc, officeStyles ); TQDomElement fontDecls = doc.createElement( "office:font-decls" ); m_styles.writeFontDecl( doc, fontDecls ); // TODO: needs in new number/date/time parser... // exportDefaultNumberStyles( doc, officeStyles ); TQDomElement defaultStyle = doc.createElement( "style:style" ); defaultStyle.setAttribute( "style:name", "Default" ); defaultStyle.setAttribute( "style:family", "table-cell" ); officeStyles.appendChild( defaultStyle ); TQDomElement autoStyles = doc.createElement( "office:automatic-styles" ); exportPageAutoStyles( doc, autoStyles, ksdoc ); TQDomElement masterStyles = doc.createElement( "office:master-styles" ); exportMasterStyles( doc, masterStyles, ksdoc ); content.appendChild( fontDecls ); content.appendChild( officeStyles ); content.appendChild( autoStyles ); content.appendChild( masterStyles ); doc.appendChild( content ); TQCString f( doc.toCString() ); kdDebug(30518) << "Content: " << (char const * ) f << endl; store->write( f, f.length() ); if ( !store->close() ) return false; return true; } void OpenCalcExport::exportDefaultCellStyle( TQDomDocument & doc, TQDomElement & officeStyles ) { TQDomElement defStyle = doc.createElement( "style:default-style" ); defStyle.setAttribute( "style:family", "table-cell" ); KoDocument * document = m_chain->inputDocument(); Doc * ksdoc = static_cast(document); Format * format = new Format( 0, ksdoc->styleManager()->defaultStyle() ); const KLocale *locale = ksdoc->locale(); TQString language; TQString country; TQString charSet; TQString l( locale->language() ); KLocale::splitLocale( l, language, country, charSet ); TQFont font( format->font() ); m_styles.addFont( font, true ); TQDomElement style = doc.createElement( "style:properties" ); style.setAttribute( "style:font-name", font.family() ); style.setAttribute( "fo:font-size", TQString( "%1pt" ).arg( font.pointSize() ) ); style.setAttribute( "style:decimal-places", TQString::number( locale->fracDigits() ) ); style.setAttribute( "fo:language", language ); style.setAttribute( "fo:country", country ); style.setAttribute( "style:font-name-asian", "HG Mincho Light J" ); style.setAttribute( "style:language-asian", "none" ); style.setAttribute( "style:country-asian", "none" ); style.setAttribute( "style:font-name-complex", "Arial Unicode MS" ); style.setAttribute( "style:language-complex", "none" ); style.setAttribute( "style:country-complex", "none" ); style.setAttribute( "style:tab-stop-distance", "1.25cm" ); defStyle.appendChild( style ); officeStyles.appendChild( defStyle ); delete format; } void OpenCalcExport::createDefaultStyles() { // TODO: default number styles, currency styles,... } void OpenCalcExport::exportPageAutoStyles( TQDomDocument & doc, TQDomElement & autoStyles, const Doc *ksdoc ) { TQPtrListIterator it( ksdoc->map()->sheetList() ); const Sheet * sheet = it.toFirst(); float width = 20.999; float height = 29.699; if ( sheet ) { width = sheet->print()->paperWidth() / 10; height = sheet->print()->paperHeight() / 10; } TQString sWidth = TQString( "%1cm" ).arg( width ); TQString sHeight = TQString( "%1cm" ).arg( height ); TQDomElement pageMaster = doc.createElement( "style:page-master" ); pageMaster.setAttribute( "style:name", "pm1" ); TQDomElement properties = doc.createElement( "style:properties" ); properties.setAttribute( "fo:page-width", sWidth ); properties.setAttribute( "fo:page-height", sHeight ); properties.setAttribute( "fo:border", "0.002cm solid #000000" ); properties.setAttribute( "fo:padding", "0cm" ); properties.setAttribute( "fo:background-color", "transparent" ); pageMaster.appendChild( properties ); TQDomElement header = doc.createElement( "style:header-style" ); properties = doc.createElement( "style:properties" ); properties.setAttribute( "fo:min-height", "0.75cm" ); properties.setAttribute( "fo:margin-left", "0cm" ); properties.setAttribute( "fo:margin-right", "0cm" ); properties.setAttribute( "fo:margin-bottom", "0.25cm" ); header.appendChild( properties ); TQDomElement footer = doc.createElement( "style:header-style" ); properties = doc.createElement( "style:properties" ); properties.setAttribute( "fo:min-height", "0.75cm" ); properties.setAttribute( "fo:margin-left", "0cm" ); properties.setAttribute( "fo:margin-right", "0cm" ); properties.setAttribute( "fo:margin-bottom", "0.25cm" ); footer.appendChild( properties ); pageMaster.appendChild( header ); pageMaster.appendChild( footer ); autoStyles.appendChild( pageMaster ); } void OpenCalcExport::exportMasterStyles( TQDomDocument & doc, TQDomElement & masterStyles, const Doc * ksdoc ) { TQDomElement masterPage = doc.createElement( "style:master-page" ); masterPage.setAttribute( "style:name", "Default" ); masterPage.setAttribute( "style:page-master-name", "pm1" ); TQPtrListIterator it( ksdoc->map()->sheetList() ); const Sheet * sheet = it.toFirst(); TQString headerLeft; TQString headerCenter; TQString headerRight; TQString footerLeft; TQString footerCenter; TQString footerRight; if ( sheet ) { headerLeft = sheet->print()->headLeft(); headerCenter = sheet->print()->headMid(); headerRight = sheet->print()->headRight(); footerLeft = sheet->print()->footLeft(); footerCenter = sheet->print()->footMid(); footerRight = sheet->print()->footRight(); } if ( ( headerLeft.length() > 0 ) || ( headerCenter.length() > 0 ) || ( headerRight.length() > 0 ) ) { TQDomElement header = doc.createElement( "style:header" ); TQDomElement left = doc.createElement( "style:region-left" ); TQDomElement text = doc.createElement( "text:p" ); convertPart( headerLeft, doc, text, ksdoc ); left.appendChild( text ); TQDomElement center = doc.createElement( "style:region-center" ); TQDomElement text1 = doc.createElement( "text:p" ); convertPart( headerCenter, doc, text1, ksdoc ); center.appendChild( text1 ); TQDomElement right = doc.createElement( "style:region-right" ); TQDomElement text2 = doc.createElement( "text:p" ); convertPart( headerRight, doc, text2, ksdoc ); right.appendChild( text2 ); header.appendChild( left ); header.appendChild( center ); header.appendChild( right ); masterPage.appendChild( header ); } else { TQDomElement header = doc.createElement( "style:header" ); TQDomElement text = doc.createElement( "text:p" ); TQDomElement name = doc.createElement( "text:sheet-name" ); name.appendChild( doc.createTextNode( "???" ) ); text.appendChild( name ); header.appendChild( text ); masterPage.appendChild( header ); } if ( ( footerLeft.length() > 0 ) || ( footerCenter.length() > 0 ) || ( footerRight.length() > 0 ) ) { TQDomElement footer = doc.createElement( "style:footer" ); TQDomElement left = doc.createElement( "style:region-left" ); TQDomElement text = doc.createElement( "text:p" ); convertPart( footerLeft, doc, text, ksdoc ); left.appendChild( text ); TQDomElement center = doc.createElement( "style:region-center" ); TQDomElement text1 = doc.createElement( "text:p" ); convertPart( footerCenter, doc, text1, ksdoc ); center.appendChild( text1 ); TQDomElement right = doc.createElement( "style:region-right" ); TQDomElement text2 = doc.createElement( "text:p" ); convertPart( footerRight, doc, text2, ksdoc ); right.appendChild( text2 ); footer.appendChild( left ); footer.appendChild( center ); footer.appendChild( right ); masterPage.appendChild( footer ); } else { TQDomElement footer = doc.createElement( "style:footer" ); TQDomElement text = doc.createElement( "text:p" ); text.appendChild( doc.createTextNode( i18n( "Page " ) ) ); TQDomElement number = doc.createElement( "text:page-number" ); number.appendChild( doc.createTextNode( "1" ) ); text.appendChild( number ); footer.appendChild( text ); masterPage.appendChild( footer ); } masterStyles.appendChild( masterPage ); } void OpenCalcExport::addText( TQString const & text, TQDomDocument & doc, TQDomElement & parent ) { if (text.length() > 0 ) parent.appendChild( doc.createTextNode( text ) ); } void OpenCalcExport::convertPart( TQString const & part, TQDomDocument & doc, TQDomElement & parent, const Doc * ksdoc ) { TQString text; TQString var; bool inVar = false; uint i = 0; uint l = part.length(); while ( i < l ) { if ( inVar || part[i] == '<' ) { inVar = true; var += part[i]; if ( part[i] == '>' ) { inVar = false; if ( var == "" ) { addText( text, doc, parent ); TQDomElement page = doc.createElement( "text:page-number" ); page.appendChild( doc.createTextNode( "1" ) ); parent.appendChild( page ); } else if ( var == "" ) { addText( text, doc, parent ); TQDomElement page = doc.createElement( "text:page-count" ); page.appendChild( doc.createTextNode( "99" ) ); parent.appendChild( page ); } else if ( var == "" ) { addText( text, doc, parent ); TQDomElement t = doc.createElement( "text:date" ); t.setAttribute( "text:date-value", "0-00-00" ); // todo: "style:data-style-name", "N2" t.appendChild( doc.createTextNode( TQDate::currentDate().toString() ) ); parent.appendChild( t ); } else if ( var == "