filters

opencalcexport.cc

00001 /* This file is part of the KDE project
00002    Copyright (C) 2000 David Faure <faure@kde.org>
00003    Copyright (C) 2000 Norbert Andres <nandres@web.de>
00004    Copyright (C) 2005 Laurent Montel <montel@kde.org>
00005 
00006    This library is free software; you can redistribute it and/or
00007    modify it under the terms of the GNU Library General Public
00008    License as published by the Free Software Foundation; either
00009    version 2 of the License, or (at your option) any later version.
00010 
00011    This library is distributed in the hope that it will be useful,
00012    but WITHOUT ANY WARRANTY; without even the implied warranty of
00013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014    Library General Public License for more details.
00015 
00016    You should have received a copy of the GNU Library General Public License
00017    along with this library; see the file COPYING.LIB.  If not, write to
00018    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00019  * Boston, MA 02110-1301, USA.
00020 */
00021 
00022 #include <float.h>
00023 #include <math.h>
00024 
00025 #include <opencalcexport.h>
00026 
00027 #include <qdatetime.h>
00028 #include <qdom.h>
00029 #include <qfile.h>
00030 #include <qregexp.h>
00031 #include <qvaluelist.h>
00032 
00033 #include <kdebug.h>
00034 #include <kmessagebox.h>
00035 #include <kmdcodec.h>
00036 #include <kgenericfactory.h>
00037 #include <klocale.h>
00038 
00039 #include <KoDocumentInfo.h>
00040 #include <KoFilterChain.h>
00041 #include <KoGlobal.h>
00042 
00043 #include <kspread_aboutdata.h>
00044 #include <kspread_cell.h>
00045 #include <kspread_doc.h>
00046 #include <kspread_format.h>
00047 #include <kspread_map.h>
00048 #include <kspread_view.h>
00049 #include <kspread_canvas.h>
00050 #include <kspread_sheet.h>
00051 #include <kspread_sheetprint.h>
00052 #include <kspread_style.h>
00053 #include <kspread_style_manager.h>
00054 #include <kspread_util.h>
00055 
00056 using namespace KSpread;
00057 
00058 typedef QValueList<Reference> AreaList;
00059 
00060 class OpenCalcExportFactory : KGenericFactory<OpenCalcExport, KoFilter>
00061 {
00062 public:
00063     OpenCalcExportFactory(void) : KGenericFactory<OpenCalcExport, KoFilter> ("kspreadopencalcexport")
00064     {}
00065 protected:
00066     virtual void setupTranslations( void )
00067     {
00068         KGlobal::locale()->insertCatalogue( "kofficefilters" );
00069     }
00070 };
00071 
00072 K_EXPORT_COMPONENT_FACTORY( libopencalcexport, OpenCalcExportFactory() )
00073 
00074 #define STOPEXPORT \
00075   do \
00076   { \
00077     delete store; \
00078     return false; \
00079   } while(0)
00080 
00081 OpenCalcExport::OpenCalcExport( KoFilter *, const char *, const QStringList & )
00082   : KoFilter(), m_locale( 0 )
00083 {
00084 }
00085 
00086 KoFilter::ConversionStatus OpenCalcExport::convert( const QCString & from,
00087                                                     const QCString & to )
00088 {
00089   /* later...
00090      KSpreadLeader  * leader = new KSpreadLeader( m_chain );
00091      OpenCalcWorker * worker = new OpenCalcWorker();
00092      leader->setWorker( worker );
00093 
00094      KoFilter::ConversionStatus status = leader->convert();
00095 
00096      delete worker;
00097      delete leader;
00098 
00099      return status;
00100   */
00101 
00102   KoDocument * document = m_chain->inputDocument();
00103 
00104   if ( !document )
00105     return KoFilter::StupidError;
00106 
00107   if (  !::qt_cast<const KSpread::Doc *>( document ) )
00108   {
00109     kdWarning(30518) << "document isn't a KSpread::Doc but a "
00110                      << document->className() << endl;
00111     return KoFilter::NotImplemented;
00112   }
00113 
00114   if ( ( to != "application/vnd.sun.xml.calc") || (from != "application/x-kspread" ) )
00115   {
00116     kdWarning(30518) << "Invalid mimetypes " << to << " " << from << endl;
00117     return KoFilter::NotImplemented;
00118   }
00119 
00120   const Doc * ksdoc = static_cast<const Doc *>(document);
00121 
00122   if ( ksdoc->mimeType() != "application/x-kspread" )
00123   {
00124     kdWarning(30518) << "Invalid document mimetype " << ksdoc->mimeType() << endl;
00125     return KoFilter::NotImplemented;
00126   }
00127 
00128   m_locale = static_cast<Doc*>(document)->locale();
00129   if ( !writeFile( ksdoc ) )
00130     return KoFilter::CreationError;
00131 
00132   emit sigProgress( 100 );
00133 
00134   return KoFilter::OK;
00135 }
00136 
00137 bool OpenCalcExport::writeFile( const Doc * ksdoc )
00138 {
00139   KoStore * store = KoStore::createStore( m_chain->outputFile(), KoStore::Write, "", KoStore::Zip );
00140 
00141   if ( !store )
00142     return false;
00143 
00144   uint filesWritten = 0;
00145 
00146   if ( !exportContent( store, ksdoc ) )
00147     STOPEXPORT;
00148   else
00149     filesWritten |= contentXML;
00150 
00151   // TODO: pass sheet number and cell number
00152   if ( !exportDocInfo( store, ksdoc ) )
00153     STOPEXPORT;
00154   else
00155     filesWritten |= metaXML;
00156 
00157   if ( !exportStyles( store, ksdoc ) )
00158     STOPEXPORT;
00159   else
00160     filesWritten |= stylesXML;
00161 
00162   if ( !exportSettings( store, ksdoc ) )
00163     STOPEXPORT;
00164   else
00165     filesWritten |= settingsXML;
00166 
00167   if ( !writeMetaFile( store, filesWritten ) )
00168     STOPEXPORT;
00169 
00170   // writes zip file to disc
00171   delete store;
00172   store = 0;
00173 
00174   return true;
00175 }
00176 
00177 bool OpenCalcExport::exportDocInfo( KoStore * store, const Doc* ksdoc )
00178 {
00179   if ( !store->open( "meta.xml" ) )
00180     return false;
00181 
00182   KoDocumentInfo       * docInfo    = ksdoc->documentInfo();
00183   KoDocumentInfoAbout  * aboutPage  = static_cast<KoDocumentInfoAbout *>( docInfo->page( "about" ) );
00184   KoDocumentInfoAuthor * authorPage = static_cast<KoDocumentInfoAuthor*>( docInfo->page( "author" ) );
00185 
00186   QDomDocument meta;
00187   meta.appendChild( meta.createProcessingInstruction( "xml","version=\"1.0\" encoding=\"UTF-8\"" ) );
00188 
00189   QDomElement content = meta.createElement( "office:document-meta" );
00190   content.setAttribute( "xmlns:office", "http://openoffice.org/2000/office");
00191   content.setAttribute( "xmlns:xlink", "http://www.w3.org/1999/xlink" );
00192   content.setAttribute( "xmlns:dc", "http://purl.org/dc/elements/1.1/" );
00193   content.setAttribute( "xmlns:meta", "http://openoffice.org/2000/meta" );
00194   content.setAttribute( "office:version", "1.0" );
00195 
00196   QDomNode officeMeta = meta.createElement( "office:meta" );
00197 
00198   QDomElement data = meta.createElement( "meta:generator" );
00199   QString app( "KSpread " );
00200   app += KSpread::version;
00201   data.appendChild( meta.createTextNode( app ) );
00202   officeMeta.appendChild( data );
00203 
00204   data = meta.createElement( "meta:initial-creator" );
00205   data.appendChild( meta.createTextNode( authorPage->fullName() ) );
00206   officeMeta.appendChild( data );
00207 
00208   data = meta.createElement( "meta:creator" );
00209   data.appendChild( meta.createTextNode( authorPage->fullName() ) );
00210   officeMeta.appendChild( data );
00211 
00212   data = meta.createElement( "dc:description" );
00213   data.appendChild( meta.createTextNode( aboutPage->abstract() ) );
00214   officeMeta.appendChild( data );
00215 
00216   data = meta.createElement( "meta:keywords" );
00217   QDomElement dataItem = meta.createElement( "meta:keyword" );
00218   dataItem.appendChild( meta.createTextNode( aboutPage->keywords() ) );
00219   data.appendChild( dataItem );
00220   officeMeta.appendChild( data );
00221 
00222   data = meta.createElement( "dc:title" );
00223   data.appendChild( meta.createTextNode( aboutPage->title() ) );
00224   officeMeta.appendChild( data );
00225 
00226   data = meta.createElement( "dc:subject" );
00227   data.appendChild( meta.createTextNode( aboutPage->subject() ) );
00228   officeMeta.appendChild( data );
00229 
00230   const QDateTime dt ( QDateTime::currentDateTime() );
00231   if ( dt.isValid() )
00232   {
00233     data = meta.createElement( "dc:date" );
00234     data.appendChild( meta.createTextNode( dt.toString( Qt::ISODate ) ) );
00235     officeMeta.appendChild( data );
00236   }
00237 
00238   /* TODO:
00239     <meta:creation-date>2003-01-08T23:57:31</meta:creation-date>
00240     <dc:language>en-US</dc:language>
00241     <meta:editing-cycles>2</meta:editing-cycles>
00242     <meta:editing-duration>PT38S</meta:editing-duration>
00243     <meta:user-defined meta:name="Info 3"/>
00244     <meta:user-defined meta:name="Info 4"/>
00245   */
00246 
00247   data = meta.createElement( "meta:document-statistic" );
00248   data.setAttribute( "meta:table-count", QString::number( ksdoc->map()->count() ) );
00249   //  TODO: data.setAttribute( "meta:cell-count",  );
00250   officeMeta.appendChild( data );
00251 
00252   content.appendChild( officeMeta );
00253   meta.appendChild( content );
00254 
00255   QCString doc( meta.toCString() );
00256   kdDebug(30518) << "Meta: " << doc << endl;
00257 
00258   store->write( doc, doc.length() );
00259 
00260   if ( !store->close() )
00261     return false;
00262 
00263   return true;
00264 }
00265 
00266 bool OpenCalcExport::exportSettings( KoStore * store, const Doc * ksdoc )
00267 {
00268   if ( !store->open( "settings.xml" ) )
00269     return false;
00270 
00271   QDomDocument doc;
00272   doc.appendChild( doc.createProcessingInstruction( "xml","version=\"1.0\" encoding=\"UTF-8\"" ) );
00273 
00274   QDomElement settings = doc.createElement( "office:document-settings" );
00275   settings.setAttribute( "xmlns:office", "http://openoffice.org/2000/office");
00276   settings.setAttribute( "xmlns:xlink", "http://www.w3.org/1999/xlink" );
00277   settings.setAttribute( "xmlns:config", "http://openoffice.org/2001/config" );
00278   settings.setAttribute( "office:version", "1.0" );
00279 
00280   QDomElement begin = doc.createElement( "office:settings" );
00281 
00282   QDomElement configItem = doc.createElement("config:config-item-set" );
00283   configItem.setAttribute( "config:name", "view-settings" );
00284 
00285   QDomElement mapIndexed = doc.createElement( "config:config-item-map-indexed" );
00286   mapIndexed.setAttribute("config:name", "Views" );
00287   configItem.appendChild( mapIndexed );
00288 
00289   QDomElement mapItem = doc.createElement("config:config-item-map-entry" );
00290 
00291   QDomElement attribute =  doc.createElement("config:config-item" );
00292   attribute.setAttribute( "config:name", "ActiveTable" );
00293   attribute.setAttribute( "config:type", "string" );
00294 
00295   View * view = static_cast<View*>( ksdoc->views().getFirst());
00296   QString activeTable;
00297   if ( view ) // no view if embedded document
00298   {
00299       Canvas * canvas = view->canvasWidget();
00300       activeTable = canvas->activeSheet()->sheetName();
00301       // save current sheet selection before to save marker, otherwise current pos is not saved
00302       view->saveCurrentSheetSelection();
00303   }
00304   attribute.appendChild( doc.createTextNode( activeTable ) );
00305   mapItem.appendChild( attribute );
00306 
00307   QDomElement configmaped = doc.createElement( "config:config-item-map-named" );
00308   configmaped.setAttribute( "config:name","Tables" );
00309 
00310   QPtrListIterator<Sheet> it( ksdoc->map()->sheetList() );
00311   for( ; it.current(); ++it )
00312   {
00313       QPoint marker;
00314       if ( view )
00315       {
00316           marker = view->markerFromSheet( *it );
00317       }
00318       QDomElement tmpItemMapNamed = doc.createElement( "config:config-item-map-entry" );
00319       tmpItemMapNamed.setAttribute( "config:name", ( *it )->tableName() );
00320 
00321       QDomElement sheetAttribute = doc.createElement( "config:config-item" );
00322       sheetAttribute.setAttribute( "config:name", "CursorPositionX" );
00323       sheetAttribute.setAttribute( "config:type", "int" );
00324       sheetAttribute.appendChild( doc.createTextNode( QString::number(marker.x() )  ) );
00325       tmpItemMapNamed.appendChild( sheetAttribute );
00326 
00327       sheetAttribute = doc.createElement( "config:config-item" );
00328       sheetAttribute.setAttribute( "config:name", "CursorPositionY" );
00329       sheetAttribute.setAttribute( "config:type", "int" );
00330       sheetAttribute.appendChild( doc.createTextNode( QString::number(marker.y() )  ) );
00331       tmpItemMapNamed.appendChild( sheetAttribute );
00332 
00333       configmaped.appendChild( tmpItemMapNamed );
00334   }
00335   mapItem.appendChild( configmaped );
00336 
00337 
00338 
00339   mapIndexed.appendChild( mapItem );
00340 
00341   begin.appendChild( configItem );
00342 
00343   settings.appendChild( begin );
00344 
00345   doc.appendChild( settings );
00346 
00347   QCString f( doc.toCString() );
00348   kdDebug(30518) << "Settings: " << (char const * ) f << endl;
00349 
00350   store->write( f, f.length() );
00351 
00352   if ( !store->close() )
00353     return false;
00354 
00355   return true;
00356 }
00357 
00358 bool OpenCalcExport::exportContent( KoStore * store, const Doc * ksdoc )
00359 {
00360   if ( !store->open( "content.xml" ) )
00361     return false;
00362 
00363   createDefaultStyles();
00364 
00365   QDomDocument doc;
00366   doc.appendChild( doc.createProcessingInstruction( "xml","version=\"1.0\" encoding=\"UTF-8\"" ) );
00367 
00368   QDomElement content = doc.createElement( "office:document-content" );
00369   content.setAttribute( "xmlns:office", "http://openoffice.org/2000/office");
00370   content.setAttribute( "xmlns:style", "http://openoffice.org/2000/style" );
00371   content.setAttribute( "xmlns:text", "http://openoffice.org/2000/text" );
00372   content.setAttribute( "xmlns:table", "http://openoffice.org/2000/table" );
00373   content.setAttribute( "xmlns:draw", "http://openoffice.org/2000/drawing" );
00374   content.setAttribute( "xmlns:fo", "http://www.w3.org/1999/XSL/Format" );
00375   content.setAttribute( "xmlns:xlink", "http://www.w3.org/1999/xlink" );
00376   content.setAttribute( "xmlns:number", "http://openoffice.org/2000/datastyle" );
00377   content.setAttribute( "xmlns:svg", "http://www.w3.org/2000/svg" );
00378   content.setAttribute( "xmlns:chart", "http://openoffice.org/2000/chart" );
00379   content.setAttribute( "xmlns:dr3d", "http://openoffice.org/2000/dr3d" );
00380   content.setAttribute( "xmlns:math", "http://www.w3.org/1998/Math/MathML" );
00381   content.setAttribute( "xmlns:form", "http://openoffice.org/2000/form" );
00382   content.setAttribute( "xmlns:script", "http://openoffice.org/2000/script" );
00383   content.setAttribute( "office:class", "spreadsheet" );
00384   content.setAttribute( "office:version", "1.0" );
00385 
00386   QDomElement data = doc.createElement( "office:script" );
00387   content.appendChild( data );
00388 
00389   if ( !exportBody( doc, content, ksdoc ) )
00390     return false;
00391 
00392   doc.appendChild( content );
00393 
00394   QCString f( doc.toCString() );
00395   kdDebug(30518) << "Content: " << (char const * ) f << endl;
00396 
00397   store->write( f, f.length() );
00398 
00399   if ( !store->close() )
00400     return false;
00401 
00402   return true;
00403 }
00404 
00405 void exportNamedExpr( QDomDocument & doc, QDomElement & parent,
00406                       AreaList const & namedAreas )
00407 {
00408   AreaList::const_iterator it  = namedAreas.begin();
00409   AreaList::const_iterator end = namedAreas.end();
00410 
00411   while ( it != end )
00412   {
00413     QDomElement namedRange = doc.createElement( "table:named-range" );
00414 
00415     Reference ref = *it;
00416 
00417     namedRange.setAttribute( "table:name", ref.ref_name );
00418     namedRange.setAttribute( "table:base-cell-address", convertRefToBase( ref.sheet_name, ref.rect ) );
00419     namedRange.setAttribute( "table:cell-range-address", convertRefToRange( ref.sheet_name, ref.rect ) );
00420 
00421     parent.appendChild( namedRange );
00422 
00423     ++it;
00424   }
00425 }
00426 
00427 bool OpenCalcExport::exportBody( QDomDocument & doc, QDomElement & content, const Doc * ksdoc )
00428 {
00429   QDomElement fontDecls  = doc.createElement( "office:font-decls" );
00430   QDomElement autoStyles = doc.createElement( "office:automatic-styles" );
00431   QDomElement body       = doc.createElement( "office:body" );
00432 
00433   if ( ksdoc->map()->isProtected() )
00434   {
00435     body.setAttribute( "table:structure-protected", "true" );
00436 
00437     QCString passwd;
00438     ksdoc->map()->password( passwd );
00439     if ( passwd.length() > 0 )
00440     {
00441       QCString str( KCodecs::base64Encode( passwd ) );
00442       body.setAttribute( "table:protection-key", QString( str.data() ) );
00443     }
00444   }
00445 
00446 
00447 
00448   QPtrListIterator<Sheet> it( ksdoc->map()->sheetList() );
00449 
00450   for( it.toFirst(); it.current(); ++it )
00451   {
00452     SheetStyle ts;
00453     int maxCols         = 1;
00454     int maxRows         = 1;
00455     Sheet * sheet = it.current();
00456 
00457     ts.visible = !sheet->isHidden();
00458 
00459     QDomElement tabElem = doc.createElement( "table:table" );
00460     tabElem.setAttribute( "table:style-name", m_styles.sheetStyle( ts ) );
00461 
00462     if ( sheet->isProtected() )
00463     {
00464       tabElem.setAttribute( "table:protected", "true" );
00465 
00466       QCString passwd;
00467       sheet->password( passwd );
00468       if ( passwd.length() > 0 )
00469       {
00470         QCString str( KCodecs::base64Encode( passwd ) );
00471         tabElem.setAttribute( "table:protection-key", QString( str.data() ) );
00472       }
00473     }
00474 
00475     QString name( sheet->tableName() );
00476 
00477     int n = name.find( ' ' );
00478     if ( n != -1 )
00479     {
00480       kdDebug(30518) << "Sheet name converting: " << name << endl;
00481       name[n] == '_';
00482       kdDebug(30518) << "Sheet name converted: " << name << endl;
00483     }
00484     name = name.replace( ' ', "_" );
00485 
00486     QRect _printRange = sheet->print()->printRange();
00487     if ( _printRange != ( QRect( QPoint( 1, 1 ), QPoint( KS_colMax, KS_rowMax ) ) ) )
00488     {
00489         QString range= convertRangeToRef( name, _printRange );
00490         //kdDebug(30518)<<" range : "<<range<<endl;
00491         tabElem.setAttribute( "table:print-ranges", range );
00492     }
00493 
00494 
00495     tabElem.setAttribute( "table:name", name );
00496 
00497     maxRowCols( sheet, maxCols, maxRows );
00498 
00499     exportSheet( doc, tabElem, sheet, maxCols, maxRows );
00500 
00501     body.appendChild( tabElem );
00502   }
00503 
00504   KoDocument * document   = m_chain->inputDocument();
00505   Doc * kspreadDoc = static_cast<Doc *>( document );
00506 
00507   AreaList namedAreas = kspreadDoc->listArea();
00508   if ( namedAreas.count() > 0 )
00509   {
00510     QDomElement namedExpr = doc.createElement( "table:named-expressions" );
00511     exportNamedExpr( doc, namedExpr, namedAreas );
00512 
00513     body.appendChild( namedExpr );
00514   }
00515 
00516   m_styles.writeStyles( doc, autoStyles );
00517   m_styles.writeFontDecl( doc, fontDecls );
00518 
00519   content.appendChild( fontDecls );
00520   content.appendChild( autoStyles );
00521   content.appendChild( body );
00522 
00523   return true;
00524 }
00525 
00526 void OpenCalcExport::exportSheet( QDomDocument & doc, QDomElement & tabElem,
00527                                   const Sheet * sheet, int maxCols, int maxRows )
00528 {
00529   kdDebug(30518) << "exportSheet: " << sheet->tableName() << endl;
00530   int i = 1;
00531 
00532   while ( i <= maxCols )
00533   {
00534     const ColumnFormat * column = sheet->columnFormat( i );
00535     ColumnStyle cs;
00536     cs.breakB = ::Style::automatic;
00537     cs.size   = column->mmWidth() / 10;
00538     bool hide = column->isHide();
00539 
00540     int j        = i + 1;
00541     int repeated = 1;
00542     while ( j <= maxCols )
00543     {
00544       const ColumnFormat *c = sheet->columnFormat( j );
00545       ColumnStyle cs1;
00546       cs1.breakB = ::Style::automatic;
00547       cs1.size   = c->mmWidth() / 10;
00548 
00549       if ( ColumnStyle::isEqual( &cs, cs1 ) && ( hide == c->isHide() ) )
00550         ++repeated;
00551       else
00552         break;
00553       ++j;
00554     }
00555 
00556     QDomElement colElem = doc.createElement( "table:table-column" );
00557     colElem.setAttribute( "table:style-name", m_styles.columnStyle( cs ) );
00558     colElem.setAttribute( "table:default-cell-style-name", "Default" );//todo fixme create style from cell
00559     if ( hide )
00560       colElem.setAttribute( "table:visibility", "collapse" );
00561 
00562     if ( repeated > 1 )
00563       colElem.setAttribute( "table:number-columns-repeated", QString::number( repeated ) );
00564 
00565     tabElem.appendChild( colElem );
00566     i += repeated;
00567   }
00568 
00569   for ( i = 1; i <= maxRows; ++i )
00570   {
00571     const RowFormat * row = sheet->rowFormat( i );
00572     RowStyle rs;
00573     rs.breakB = ::Style::automatic;
00574     rs.size   = row->mmHeight() / 10;
00575 
00576     QDomElement rowElem = doc.createElement( "table:table-row" );
00577     rowElem.setAttribute( "table:style-name", m_styles.rowStyle( rs ) );
00578     if ( row->isHide() )
00579       rowElem.setAttribute( "table:visibility", "collapse" );
00580 
00581     exportCells( doc, rowElem, sheet, i, maxCols );
00582 
00583     tabElem.appendChild( rowElem );
00584   }
00585 }
00586 
00587 void OpenCalcExport::exportCells( QDomDocument & doc, QDomElement & rowElem,
00588                                   const Sheet *sheet, int row, int maxCols )
00589 {
00590   int i = 1;
00591   while ( i <= maxCols )
00592   {
00593     int  repeated = 1;
00594     bool hasComment = false;
00595     const Cell* cell = sheet->cellAt( i, row );
00596     QDomElement cellElem;
00597 
00598     if ( !cell->isPartOfMerged() )
00599       cellElem = doc.createElement( "table:table-cell" );
00600     else
00601       cellElem = doc.createElement( "table:covered-table-cell" );
00602 
00603     QFont font;
00604     Value const value( cell->value() );
00605     if ( !cell->isDefault() )
00606     {
00607       font = cell->format()->textFont( i, row );
00608       m_styles.addFont( font );
00609 
00610       if ( cell->format()->hasProperty( Format::PComment ) )
00611         hasComment = true;
00612     }
00613 
00614     CellStyle c;
00615     CellStyle::loadData( c, cell ); // TODO: number style
00616 
00617     cellElem.setAttribute( "table:style-name", m_styles.cellStyle( c ) );
00618 
00619     // group empty cells with the same style
00620     if ( cell->isEmpty() && !hasComment && !cell->isPartOfMerged() && !cell->doesMergeCells() )
00621     {
00622       int j = i + 1;
00623       while ( j <= maxCols )
00624       {
00625         const Cell *cell1 = sheet->cellAt( j, row );
00626 
00627         CellStyle c1;
00628         CellStyle::loadData( c1, cell1 ); // TODO: number style
00629 
00630         if ( cell1->isEmpty() && !cell->format()->hasProperty( Format::PComment )
00631              && CellStyle::isEqual( &c, c1 ) && !cell->isPartOfMerged() && !cell->doesMergeCells() )
00632           ++repeated;
00633         else
00634           break;
00635         ++j;
00636       }
00637       if ( repeated > 1 )
00638         cellElem.setAttribute( "table:number-columns-repeated", QString::number( repeated ) );
00639     }
00640 
00641     if ( value.isBoolean() )
00642     {
00643       kdDebug(30518) << "Type: Boolean" << endl;
00644       cellElem.setAttribute( "table:value-type", "boolean" );
00645       cellElem.setAttribute( "table:boolean-value", ( value.asBoolean() ? "true" : "false" ) );
00646     }
00647     else if ( value.isNumber() )
00648     {
00649       kdDebug(30518) << "Type: Number" << endl;
00650       FormatType type = cell->format()->getFormatType( i, row );
00651 
00652       if ( type == Percentage_format )
00653         cellElem.setAttribute( "table:value-type", "percentage" );
00654       else
00655         cellElem.setAttribute( "table:value-type", "float" );
00656 
00657       cellElem.setAttribute( "table:value", QString::number( value.asFloat() ) );
00658     }
00659     else
00660     {
00661       kdDebug(30518) << "Type: " << value.type() << endl;
00662     }
00663 
00664     if ( cell->isFormula() )
00665     {
00666       kdDebug(30518) << "Formula found" << endl;
00667 
00668       QString formula( convertFormula( cell->text() ) );
00669       cellElem.setAttribute( "table:formula", formula );
00670     }
00671     else if ( !cell->link().isEmpty() )
00672     {
00673       QDomElement link = doc.createElement( "text:p" );
00674       QDomElement linkref = doc.createElement( "text:a" );
00675 
00676       QString tmp = cell->link();
00677        if ( localReferenceAnchor( tmp ) )
00678            linkref.setAttribute( "xlink:href", ( "#"+tmp ) );
00679        else
00680            linkref.setAttribute( "xlink:href", tmp  );
00681 
00682        linkref.appendChild( doc.createTextNode( cell->text() ) );
00683 
00684        link.appendChild( linkref );
00685        cellElem.appendChild( link );
00686     }
00687     else if ( !cell->isEmpty() )
00688     {
00689       QDomElement textElem = doc.createElement( "text:p" );
00690       textElem.appendChild( doc.createTextNode( cell->strOutText() ) );
00691 
00692       cellElem.appendChild( textElem );
00693       kdDebug(30518) << "Cell StrOut: " << cell->strOutText() << endl;
00694     }
00695 
00696     if ( cell->doesMergeCells() )
00697     {
00698       int colSpan = cell->mergedXCells() + 1;
00699       int rowSpan = cell->mergedYCells() + 1;
00700 
00701       if ( colSpan > 1 )
00702         cellElem.setAttribute( "table:number-columns-spanned", QString::number( colSpan ) );
00703 
00704       if ( rowSpan > 1 )
00705         cellElem.setAttribute( "table:number-rows-spanned", QString::number( rowSpan ) );
00706     }
00707 
00708     if ( hasComment )
00709     {
00710       QString comment( cell->format()->comment( i, row ) );
00711       QDomElement annotation = doc.createElement( "office:annotation" );
00712       QDomElement text = doc.createElement( "text:p" );
00713       text.appendChild( doc.createTextNode( comment ) );
00714 
00715       annotation.appendChild( text );
00716       cellElem.appendChild( annotation );
00717     }
00718 
00719     rowElem.appendChild( cellElem );
00720 
00721     i += repeated;
00722   }
00723 }
00724 
00725 void OpenCalcExport::maxRowCols( const Sheet *sheet,
00726                                  int & maxCols, int & maxRows )
00727 {
00728   Cell const * cell = sheet->firstCell();
00729 
00730   while ( cell )
00731   {
00732     if ( cell->column() > maxCols )
00733       maxCols = cell->column();
00734 
00735     if ( cell->row() > maxRows )
00736       maxRows = cell->row();
00737 
00738     cell = cell->nextCell();
00739   }
00740 
00741   RowFormat const * row = sheet->firstRow();
00742 
00743   while ( row )
00744   {
00745     if ( row->row() > maxRows )
00746       maxRows = row->row();
00747 
00748     row = row->next();
00749   }
00750 
00751   ColumnFormat const * col = sheet->firstCol();
00752   while ( col )
00753   {
00754     if ( col->column() > maxCols )
00755       maxCols = col->column();
00756 
00757     col = col->next();
00758   }
00759 
00760 }
00761 
00762 bool OpenCalcExport::exportStyles( KoStore * store, const Doc *ksdoc )
00763 {
00764   if ( !store->open( "styles.xml" ) )
00765     return false;
00766 
00767   QDomDocument doc;
00768   doc.appendChild( doc.createProcessingInstruction( "xml","version=\"1.0\" encoding=\"UTF-8\"" ) );
00769 
00770   QDomElement content = doc.createElement( "office:document-styles" );
00771   content.setAttribute( "xmlns:office", "http://openoffice.org/2000/office" );
00772   content.setAttribute( "xmlns:style", "http://openoffice.org/2000/style" );
00773   content.setAttribute( "xmlns:text", "http://openoffice.org/2000/text" );
00774   content.setAttribute( "xmlns:table", "http://openoffice.org/2000/table" );
00775   content.setAttribute( "xmlns:draw", "http://openoffice.org/2000/drawing" );
00776   content.setAttribute( "xmlns:fo", "http://www.w3.org/1999/XSL/Format" );
00777   content.setAttribute( "xmlns:xlink", "http://www.w3.org/1999/xlink" );
00778   content.setAttribute( "xmlns:number", "http://openoffice.org/2000/datastyle" );
00779   content.setAttribute( "xmlns:svg", "http://www.w3.org/2000/svg" );
00780   content.setAttribute( "xmlns:chart", "http://openoffice.org/2000/chart" );
00781   content.setAttribute( "xmlns:dr3d", "http://openoffice.org/2000/dr3d" );
00782   content.setAttribute( "xmlns:math", "http://www.w3.org/1998/Math/MathML" );
00783   content.setAttribute( "xmlns:form", "http://openoffice.org/2000/form" );
00784   content.setAttribute( "xmlns:script", "http://openoffice.org/2000/script" );
00785   content.setAttribute( "office:version", "1.0" );
00786 
00787   // order important here!
00788   QDomElement officeStyles = doc.createElement( "office:styles" );
00789   exportDefaultCellStyle( doc, officeStyles );
00790 
00791   QDomElement fontDecls = doc.createElement( "office:font-decls" );
00792   m_styles.writeFontDecl( doc, fontDecls );
00793 
00794   // TODO: needs in new number/date/time parser...
00795   //  exportDefaultNumberStyles( doc, officeStyles );
00796 
00797   QDomElement defaultStyle = doc.createElement( "style:style" );
00798   defaultStyle.setAttribute( "style:name", "Default" );
00799   defaultStyle.setAttribute( "style:family", "table-cell" );
00800   officeStyles.appendChild( defaultStyle );
00801 
00802   QDomElement autoStyles = doc.createElement( "office:automatic-styles" );
00803   exportPageAutoStyles( doc, autoStyles, ksdoc );
00804 
00805   QDomElement masterStyles = doc.createElement( "office:master-styles" );
00806   exportMasterStyles( doc, masterStyles, ksdoc );
00807 
00808   content.appendChild( fontDecls );
00809   content.appendChild( officeStyles );
00810   content.appendChild( autoStyles );
00811   content.appendChild( masterStyles );
00812 
00813   doc.appendChild( content );
00814 
00815   QCString f( doc.toCString() );
00816   kdDebug(30518) << "Content: " << (char const * ) f << endl;
00817 
00818   store->write( f, f.length() );
00819 
00820   if ( !store->close() )
00821     return false;
00822 
00823   return true;
00824 }
00825 
00826 void OpenCalcExport::exportDefaultCellStyle( QDomDocument & doc, QDomElement & officeStyles )
00827 {
00828   QDomElement defStyle = doc.createElement( "style:default-style" );
00829   defStyle.setAttribute( "style:family", "table-cell" );
00830 
00831   KoDocument * document = m_chain->inputDocument();
00832   Doc * ksdoc    = static_cast<Doc *>(document);
00833 
00834   Format * format = new Format( 0, ksdoc->styleManager()->defaultStyle() );
00835   const KLocale *locale = ksdoc->locale();
00836   QString language;
00837   QString country;
00838   QString charSet;
00839 
00840   QString l( locale->language() );
00841   KLocale::splitLocale( l, language, country, charSet );
00842   QFont font( format->font() );
00843   m_styles.addFont( font, true );
00844 
00845   QDomElement style = doc.createElement( "style:properties" );
00846   style.setAttribute( "style:font-name", font.family() );
00847   style.setAttribute( "fo:font-size", QString( "%1pt" ).arg( font.pointSize() ) );
00848   style.setAttribute( "style:decimal-places", QString::number( locale->fracDigits() ) );
00849   style.setAttribute( "fo:language", language );
00850   style.setAttribute( "fo:country", country );
00851   style.setAttribute( "style:font-name-asian", "HG Mincho Light J" );
00852   style.setAttribute( "style:language-asian", "none" );
00853   style.setAttribute( "style:country-asian", "none" );
00854   style.setAttribute( "style:font-name-complex", "Arial Unicode MS" );
00855   style.setAttribute( "style:language-complex", "none" );
00856   style.setAttribute( "style:country-complex", "none" );
00857   style.setAttribute( "style:tab-stop-distance", "1.25cm" );
00858 
00859   defStyle.appendChild( style );
00860   officeStyles.appendChild( defStyle );
00861   delete format;
00862 }
00863 
00864 void OpenCalcExport::createDefaultStyles()
00865 {
00866   // TODO: default number styles, currency styles,...
00867 }
00868 
00869 void OpenCalcExport::exportPageAutoStyles( QDomDocument & doc, QDomElement & autoStyles,
00870                                            const Doc *ksdoc )
00871 {
00872   QPtrListIterator<Sheet> it( ksdoc->map()->sheetList() );
00873   const Sheet * sheet = it.toFirst();
00874 
00875   float width  = 20.999;
00876   float height = 29.699;
00877 
00878   if ( sheet )
00879   {
00880     width  = sheet->print()->paperWidth() / 10;
00881     height = sheet->print()->paperHeight() / 10;
00882   }
00883 
00884   QString sWidth  = QString( "%1cm" ).arg( width  );
00885   QString sHeight = QString( "%1cm" ).arg( height );
00886 
00887   QDomElement pageMaster = doc.createElement( "style:page-master" );
00888   pageMaster.setAttribute( "style:name", "pm1" );
00889 
00890   QDomElement properties = doc.createElement( "style:properties" );
00891   properties.setAttribute( "fo:page-width",  sWidth  );
00892   properties.setAttribute( "fo:page-height", sHeight );
00893   properties.setAttribute( "fo:border", "0.002cm solid #000000" );
00894   properties.setAttribute( "fo:padding", "0cm" );
00895   properties.setAttribute( "fo:background-color", "transparent" );
00896 
00897   pageMaster.appendChild( properties );
00898 
00899   QDomElement header = doc.createElement( "style:header-style" );
00900   properties = doc.createElement( "style:properties" );
00901   properties.setAttribute( "fo:min-height", "0.75cm" );
00902   properties.setAttribute( "fo:margin-left", "0cm" );
00903   properties.setAttribute( "fo:margin-right", "0cm" );
00904   properties.setAttribute( "fo:margin-bottom", "0.25cm" );
00905 
00906   header.appendChild( properties );
00907 
00908   QDomElement footer = doc.createElement( "style:header-style" );
00909   properties = doc.createElement( "style:properties" );
00910   properties.setAttribute( "fo:min-height", "0.75cm" );
00911   properties.setAttribute( "fo:margin-left", "0cm" );
00912   properties.setAttribute( "fo:margin-right", "0cm" );
00913   properties.setAttribute( "fo:margin-bottom", "0.25cm" );
00914 
00915   footer.appendChild( properties );
00916 
00917   pageMaster.appendChild( header );
00918   pageMaster.appendChild( footer );
00919 
00920   autoStyles.appendChild( pageMaster );
00921 }
00922 
00923 void OpenCalcExport::exportMasterStyles( QDomDocument & doc, QDomElement & masterStyles,
00924                                          const Doc * ksdoc )
00925 {
00926   QDomElement masterPage = doc.createElement( "style:master-page" );
00927   masterPage.setAttribute( "style:name", "Default" );
00928   masterPage.setAttribute( "style:page-master-name", "pm1" );
00929 
00930   QPtrListIterator<Sheet> it( ksdoc->map()->sheetList() );
00931   const Sheet * sheet = it.toFirst();
00932 
00933   QString headerLeft;
00934   QString headerCenter;
00935   QString headerRight;
00936   QString footerLeft;
00937   QString footerCenter;
00938   QString footerRight;
00939 
00940   if ( sheet )
00941   {
00942     headerLeft   = sheet->print()->headLeft();
00943     headerCenter = sheet->print()->headMid();
00944     headerRight  = sheet->print()->headRight();
00945     footerLeft   = sheet->print()->footLeft();
00946     footerCenter = sheet->print()->footMid();
00947     footerRight  = sheet->print()->footRight();
00948   }
00949 
00950   if ( ( headerLeft.length() > 0 ) || ( headerCenter.length() > 0 )
00951        || ( headerRight.length() > 0 ) )
00952   {
00953     QDomElement header = doc.createElement( "style:header" );
00954     QDomElement left   = doc.createElement( "style:region-left" );
00955     QDomElement text   = doc.createElement( "text:p" );
00956     convertPart( headerLeft, doc, text, ksdoc );
00957     left.appendChild( text );
00958 
00959     QDomElement center = doc.createElement( "style:region-center" );
00960     QDomElement text1  = doc.createElement( "text:p" );
00961     convertPart( headerCenter, doc, text1, ksdoc );
00962     center.appendChild( text1 );
00963 
00964     QDomElement right = doc.createElement( "style:region-right" );
00965     QDomElement text2 = doc.createElement( "text:p" );
00966     convertPart( headerRight, doc, text2, ksdoc );
00967     right.appendChild( text2 );
00968 
00969     header.appendChild( left   );
00970     header.appendChild( center );
00971     header.appendChild( right  );
00972 
00973     masterPage.appendChild( header );
00974   }
00975   else
00976   {
00977     QDomElement header = doc.createElement( "style:header" );
00978     QDomElement text   = doc.createElement( "text:p" );
00979     QDomElement name   = doc.createElement( "text:sheet-name" );
00980     name.appendChild( doc.createTextNode( "???" ) );
00981     text.appendChild( name );
00982     header.appendChild( text );
00983 
00984     masterPage.appendChild( header );
00985   }
00986 
00987   if ( ( footerLeft.length() > 0 ) || ( footerCenter.length() > 0 )
00988        || ( footerRight.length() > 0 ) )
00989   {
00990     QDomElement footer = doc.createElement( "style:footer" );
00991     QDomElement left   = doc.createElement( "style:region-left" );
00992     QDomElement text   = doc.createElement( "text:p" );
00993     convertPart( footerLeft, doc, text, ksdoc );
00994     left.appendChild( text );
00995 
00996     QDomElement center = doc.createElement( "style:region-center" );
00997     QDomElement text1  = doc.createElement( "text:p" );
00998     convertPart( footerCenter, doc, text1, ksdoc );
00999     center.appendChild( text1 );
01000 
01001     QDomElement right = doc.createElement( "style:region-right" );
01002     QDomElement text2  = doc.createElement( "text:p" );
01003     convertPart( footerRight, doc, text2, ksdoc );
01004     right.appendChild( text2 );
01005 
01006     footer.appendChild( left   );
01007     footer.appendChild( center );
01008     footer.appendChild( right  );
01009 
01010     masterPage.appendChild( footer );
01011   }
01012   else
01013   {
01014     QDomElement footer = doc.createElement( "style:footer" );
01015     QDomElement text   = doc.createElement( "text:p" );
01016     text.appendChild( doc.createTextNode( i18n( "Page " ) ) );
01017     QDomElement number = doc.createElement( "text:page-number" );
01018     number.appendChild( doc.createTextNode( "1" ) );
01019     text.appendChild( number );
01020     footer.appendChild( text );
01021 
01022     masterPage.appendChild( footer );
01023   }
01024 
01025   masterStyles.appendChild( masterPage );
01026 }
01027 
01028 void OpenCalcExport::addText( QString const & text, QDomDocument & doc,
01029                               QDomElement & parent )
01030 {
01031   if (text.length() > 0 )
01032     parent.appendChild( doc.createTextNode( text ) );
01033 }
01034 
01035 void OpenCalcExport::convertPart( QString const & part, QDomDocument & doc,
01036                                   QDomElement & parent, const Doc * ksdoc )
01037 {
01038   QString text;
01039   QString var;
01040 
01041   bool inVar = false;
01042   uint i = 0;
01043   uint l = part.length();
01044   while ( i < l )
01045   {
01046     if ( inVar || part[i] == '<' )
01047     {
01048       inVar = true;
01049       var += part[i];
01050       if ( part[i] == '>' )
01051       {
01052         inVar = false;
01053         if ( var == "<page>" )
01054         {
01055           addText( text, doc, parent );
01056 
01057           QDomElement page = doc.createElement( "text:page-number" );
01058           page.appendChild( doc.createTextNode( "1" ) );
01059           parent.appendChild( page );
01060         }
01061         else if ( var == "<pages>" )
01062         {
01063           addText( text, doc, parent );
01064 
01065           QDomElement page = doc.createElement( "text:page-count" );
01066           page.appendChild( doc.createTextNode( "99" ) );
01067           parent.appendChild( page );
01068         }
01069         else if ( var == "<date>" )
01070         {
01071           addText( text, doc, parent );
01072 
01073           QDomElement t = doc.createElement( "text:date" );
01074           t.setAttribute( "text:date-value", "0-00-00" );
01075           // todo: "style:data-style-name", "N2"
01076           t.appendChild( doc.createTextNode( QDate::currentDate().toString() ) );
01077           parent.appendChild( t );
01078         }
01079         else if ( var == "<time>" )
01080         {
01081           addText( text, doc, parent );
01082 
01083           QDomElement t = doc.createElement( "text:time" );
01084           t.appendChild( doc.createTextNode( QTime::currentTime().toString() ) );
01085           parent.appendChild( t );
01086         }
01087         else if ( var == "<file>" ) // filepath + name
01088         {
01089           addText( text, doc, parent );
01090 
01091           QDomElement t = doc.createElement( "text:file-name" );
01092           t.setAttribute( "text:display", "full" );
01093           t.appendChild( doc.createTextNode( "???" ) );
01094           parent.appendChild( t );
01095         }
01096         else if ( var == "<name>" ) // filename
01097         {
01098           addText( text, doc, parent );
01099 
01100           QDomElement t = doc.createElement( "text:title" );
01101           t.appendChild( doc.createTextNode( "???" ) );
01102           parent.appendChild( t );
01103         }
01104         else if ( var == "<author>" )
01105         {
01106           KoDocumentInfo       * docInfo    = ksdoc->documentInfo();
01107           KoDocumentInfoAuthor * authorPage = static_cast<KoDocumentInfoAuthor*>( docInfo->page( "author" ) );
01108 
01109           text += authorPage->fullName();
01110 
01111           addText( text, doc, parent );
01112         }
01113         else if ( var == "<email>" )
01114         {
01115           KoDocumentInfo       * docInfo    = ksdoc->documentInfo();
01116           KoDocumentInfoAuthor * authorPage = static_cast<KoDocumentInfoAuthor*>( docInfo->page( "author" ) );
01117 
01118           text += authorPage->email();
01119 
01120           addText( text, doc, parent );
01121         }
01122         else if ( var == "<org>" )
01123         {
01124           KoDocumentInfo       * docInfo    = ksdoc->documentInfo();
01125           KoDocumentInfoAuthor * authorPage = static_cast<KoDocumentInfoAuthor*>( docInfo->page( "author" ) );
01126 
01127           text += authorPage->company();
01128 
01129           addText( text, doc, parent );
01130         }
01131         else if ( var == "<sheet>" )
01132         {
01133           addText( text, doc, parent );
01134 
01135           QDomElement s = doc.createElement( "text:sheet-name" );
01136           s.appendChild( doc.createTextNode( "???" ) );
01137           parent.appendChild( s );
01138         }
01139         else
01140         {
01141           // no known variable:
01142           text += var;
01143           addText( text, doc, parent );
01144         }
01145 
01146         text = "";
01147         var  = "";
01148       }
01149     }
01150     else
01151     {
01152       text += part[i];
01153     }
01154     ++i;
01155   }
01156   if ( !text.isEmpty() || !var.isEmpty() )
01157   {
01158       //we don't have var at the end =>store it
01159       addText( text+var, doc, parent );
01160   }
01161 }
01162 
01163 QString OpenCalcExport::convertFormula( QString const & formula ) const
01164 {
01165   QChar decimalSymbol( '.' );
01166   if ( m_locale )
01167   {
01168     const QString decimal ( m_locale->decimalSymbol() );
01169     if ( !decimal.isEmpty() )
01170     {
01171         decimalSymbol = decimal.at( 0 );
01172     }
01173   }
01174 
01175   QString s;
01176   QRegExp exp("(\\$?)([a-zA-Z]+)(\\$?)([0-9]+)");
01177   int n = exp.search( formula, 0 );
01178   kdDebug(30518) << "Exp: " << formula << ", n: " << n << ", Length: " << formula.length()
01179             << ", Matched length: " << exp.matchedLength() << endl;
01180 
01181   bool inQuote1 = false;
01182   bool inQuote2 = false;
01183   int i = 0;
01184   int l = (int) formula.length();
01185   if ( l <= 0 )
01186     return formula;
01187   while ( i < l )
01188   {
01189     if ( ( n != -1 ) && ( n < i ) )
01190     {
01191       n = exp.search( formula, i );
01192       kdDebug(30518) << "Exp: " << formula.right( l - i ) << ", n: " << n << endl;
01193     }
01194     if ( formula[i] == '"' )
01195     {
01196       inQuote1 = !inQuote1;
01197       s += formula[i];
01198       ++i;
01199       continue;
01200     }
01201     if ( formula[i] == '\'' )
01202     {
01203       // named area
01204       inQuote2 = !inQuote2;
01205       ++i;
01206       continue;
01207     }
01208     if ( inQuote1 || inQuote2 )
01209     {
01210       s += formula[i];
01211       ++i;
01212       continue;
01213     }
01214     if ( ( formula[i] == '=' ) && ( formula[i + 1] == '=' ) )
01215     {
01216       s += '=';
01217       ++i;++i;
01218       continue;
01219     }
01220     if ( formula[i] == '!' )
01221     {
01222       insertBracket( s );
01223       s += '.';
01224       ++i;
01225       continue;
01226     }
01227     else if ( formula[i] == decimalSymbol )
01228     {
01229       s += '.'; // decimal point
01230       ++i;
01231       continue;
01232     }
01233     if ( n == i )
01234     {
01235       int ml = exp.matchedLength();
01236       if ( formula[ i + ml ] == '!' )
01237       {
01238         kdDebug(30518) << "No cell ref but sheet name" << endl;
01239         s += formula[i];
01240         ++i;
01241         continue;
01242       }
01243       if ( ( i > 0 ) && ( formula[i - 1] != '!' ) )
01244         s += "[.";
01245       for ( int j = 0; j < ml; ++j )
01246       {
01247         s += formula[i];
01248         ++i;
01249       }
01250       s += ']';
01251       continue;
01252     }
01253 
01254     s += formula[i];
01255     ++i;
01256   }
01257 
01258   return s;
01259 }
01260 
01261 bool OpenCalcExport::writeMetaFile( KoStore * store, uint filesWritten )
01262 {
01263     store->enterDirectory( "META-INF" );
01264   if ( !store->open( "manifest.xml" ) )
01265     return false;
01266 
01267   QDomImplementation impl;
01268   QDomDocumentType type( impl.createDocumentType( "manifest:manifest", "-//OpenOffice.org//DTD Manifest 1.0//EN", "Manifest.dtd" ) );
01269 
01270   QDomDocument meta( type );
01271   meta.appendChild( meta.createProcessingInstruction( "xml","version=\"1.0\" encoding=\"UTF-8\"" ) );
01272 
01273   QDomElement content = meta.createElement( "manifest:manifest" );
01274   content.setAttribute( "xmlns:manifest", "http://openoffice.org/2001/manifest" );
01275 
01276   QDomElement entry = meta.createElement( "manifest:file-entry" );
01277   entry.setAttribute( "manifest:media-type", "application/vnd.sun.xml.calc" );
01278   entry.setAttribute( "manifest:full-path", "/" );
01279   content.appendChild( entry );
01280 
01281   entry = meta.createElement( "manifest:file-entry" );
01282   content.appendChild( entry );
01283 
01284   if ( filesWritten & contentXML )
01285   {
01286     entry = meta.createElement( "manifest:file-entry" );
01287     entry.setAttribute( "manifest:media-type", "text/xml" );
01288     entry.setAttribute( "manifest:full-path", "content.xml" );
01289     content.appendChild( entry );
01290   }
01291 
01292   if ( filesWritten & stylesXML )
01293   {
01294     entry = meta.createElement( "manifest:file-entry" );
01295     entry.setAttribute( "manifest:media-type", "text/xml" );
01296     entry.setAttribute( "manifest:full-path", "styles.xml" );
01297     content.appendChild( entry );
01298   }
01299 
01300   if ( filesWritten & metaXML )
01301   {
01302     entry = meta.createElement( "manifest:file-entry" );
01303     entry.setAttribute( "manifest:media-type", "text/xml" );
01304     entry.setAttribute( "manifest:full-path", "meta.xml" );
01305     content.appendChild( entry );
01306   }
01307 
01308   if ( filesWritten & settingsXML )
01309   {
01310     entry = meta.createElement( "manifest:file-entry" );
01311     entry.setAttribute( "manifest:media-type", "text/xml" );
01312     entry.setAttribute( "manifest:full-path", "settings.xml" );
01313     content.appendChild( entry );
01314   }
01315 
01316   meta.appendChild( content );
01317 
01318   QCString doc( meta.toCString() );
01319   kdDebug(30518) << "Manifest: " << doc << endl;
01320 
01321   store->write( doc, doc.length() );
01322 
01323   if ( !store->close() )
01324     return false;
01325 
01326   return true;
01327 }
01328 
01329 #include <opencalcexport.moc>
KDE Home | KDE Accessibility Home | Description of Access Keys