00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <qstring.h>
00021 #include <qdict.h>
00022 #include <qfile.h>
00023 #include <qbuffer.h>
00024 #include <qcolor.h>
00025 #include <qimage.h>
00026
00027 #include <kdebug.h>
00028 #include <ktempfile.h>
00029 #include <kmimetype.h>
00030
00031 #include <kofficeversion.h>
00032 #include <KoStore.h>
00033 #include <KoStoreDevice.h>
00034 #include <KoXmlWriter.h>
00035 #include <KoGenStyles.h>
00036 #include <KoDocument.h>
00037
00038 #include "kword13formatother.h"
00039 #include "kword13picture.h"
00040 #include "kword13document.h"
00041
00042 #include "kword13oasisgenerator.h"
00043
00044 KWord13OasisGenerator::KWord13OasisGenerator( void ) : m_kwordDocument( 0 ), m_store( 0 ), m_manifestWriter( 0 )
00045 {
00046 }
00047
00048 KWord13OasisGenerator::~KWord13OasisGenerator( void )
00049 {
00050 }
00051
00052 void KWord13OasisGenerator::prepareTextFrameset( KWordTextFrameset* frameset )
00053 {
00054 if ( ! frameset )
00055 {
00056 kdWarning(30520) << "Tried to prepare a NULL text frameset!" << endl;
00057 return;
00058 }
00059
00060 for ( QValueList<KWord13Paragraph>::Iterator it = frameset->m_paragraphGroup.begin();
00061 it != frameset->m_paragraphGroup.end(); ++it)
00062 {
00063 declareLayout( (*it).m_layout );
00064 for ( KWord13Format* format = (*it).m_formats.first(); format; format = (*it).m_formats.next() )
00065 {
00066
00067 KWord13FormatOneData* data = format->getFormatOneData();
00068 if ( data )
00069 {
00070
00071 KoGenStyle gs( KoGenStyle::STYLE_AUTO, "text", (*it).m_layout.m_autoStyleName );
00072 fillGenStyleWithFormatOne( *data , gs, false );
00073 data->m_autoStyleName = m_oasisGenStyles.lookup( gs, "T" );
00074 kdDebug(30520) << "Format: Parent " << (*it).m_layout.m_autoStyleName << " => " << data->m_autoStyleName << endl;
00075 }
00076 }
00077 }
00078 }
00079
00080 void KWord13OasisGenerator::preparePageLayout( void )
00081 {
00082
00083 KoGenStyle style(KoGenStyle::STYLE_PAGELAYOUT);
00084 style.addPropertyPt("fo:page-width", positiveNumberOrNull ( m_kwordDocument->getProperty( "PAPER:width", "PAPER:ptWidth" ) ) );
00085 style.addPropertyPt("fo:page-height", positiveNumberOrNull ( m_kwordDocument->getProperty( "PAPER:height", "PAPER:ptHeight" ) ) );
00086 style.addPropertyPt("fo:margin-left", positiveNumberOrNull ( m_kwordDocument->getProperty( "PAPERBORDERS:left", "PAPERBORDERS:ptLeft" ) ) );
00087 style.addPropertyPt("fo:margin-right", positiveNumberOrNull ( m_kwordDocument->getProperty( "PAPERBORDERS:right", "PAPERBORDERS:ptRight" ) ) );
00088 style.addPropertyPt("fo:margin-top", positiveNumberOrNull ( m_kwordDocument->getProperty( "PAPERBORDERS:top", "PAPERBORDERS:ptTop" ) ) );
00089 style.addPropertyPt("fo:margin-bottom", positiveNumberOrNull ( m_kwordDocument->getProperty( "PAPERBORDERS:bottom", "PAPERBORDERS:ptBottom" ) ) );
00090 if ( m_kwordDocument->getProperty( "PAPER:orientation" ) == "1" )
00091 {
00092 style.addProperty("style:print-orientation", "landscape" );
00093 }
00094 else
00095 {
00096 style.addProperty("style:print-orientation", "portrait" );
00097 }
00098
00099
00100 bool ok = false;
00101 const int firstPageNumber = m_kwordDocument->getProperty( "VARIABLESETTINGS:startingPageNumber" ).toInt( &ok );
00102 style.addProperty("style:first-page-number", ( ( ok && firstPageNumber > 1 ) ? firstPageNumber : 1 ) );
00103
00104 const int columns = m_kwordDocument->getProperty( "PAPER:columns" ).toInt( &ok );
00105 if ( ok && columns > 1 )
00106 {
00107
00108 QBuffer buffer;
00109 buffer.open( IO_WriteOnly );
00110 KoXmlWriter element ( &buffer );
00111 element.startElement("style:columns");
00112 element.addAttribute( "fo:column-count", columns );
00113 element.addAttributePt( "fo:column-gap", positiveNumberOrNull( m_kwordDocument->getProperty( "PAPER:columnspacing", "PAPER:ptColumnspc" ) ) );
00114
00115 for ( int i=0; i < columns; ++i )
00116 {
00117 element.startElement( "style:column" );
00118 element.addAttribute( "style:rel-width", "1*" );
00119 element.addAttributePt( "fo:margin-left", 0.0 );
00120 element.addAttributePt( "fo:margin-right", 0.0 );
00121 element.endElement();
00122 }
00123
00124 element.endElement();
00125 buffer.close();
00126 const QString strElement( QString::fromUtf8( buffer.buffer(), buffer.buffer().size() ) );
00127 style.addChildElement( "style:columns", strElement );
00128 }
00129 const QString automaticPageStyle ( m_oasisGenStyles.lookup( style, "pm" ) );
00130 kdDebug(30520) << "Automatic page style: " << automaticPageStyle << endl;
00131 }
00132
00133
00134 bool KWord13OasisGenerator::prepare( KWord13Document& kwordDocument )
00135 {
00136 if ( m_kwordDocument && ( (void*) m_kwordDocument ) != ( (void*) &kwordDocument ) )
00137 {
00138 kdWarning(30520) << "KWord Document is different!" <<endl;
00139 }
00140
00141 m_kwordDocument = &kwordDocument;
00142
00143 preparePageLayout();
00144
00145
00146 for ( QValueList<KWord13Layout>::Iterator it = m_kwordDocument->m_styles.begin();
00147 it != m_kwordDocument->m_styles.end(); ++it)
00148 {
00149 declareStyle( *it );
00150 }
00151
00152
00153 prepareTextFrameset( m_kwordDocument->m_normalTextFramesetList.first() );
00154
00155
00156
00157 return true;
00158 }
00159
00160 double KWord13OasisGenerator::numberOrNull( const QString& str ) const
00161 {
00162 bool ok = false;
00163 const double d = str.toDouble( &ok );
00164 if ( ok )
00165 return d;
00166 else
00167 return 0.0;
00168 }
00169
00170 double KWord13OasisGenerator::positiveNumberOrNull( const QString& str ) const
00171 {
00172 bool ok = false;
00173 const double d = str.toDouble( &ok );
00174 if ( ok && d >= 0.0 )
00175 return d;
00176 else
00177 return 0.0;
00178 }
00179
00180
00181 void KWord13OasisGenerator::declareLayout( KWord13Layout& layout )
00182 {
00183 KoGenStyle gs( KoGenStyle::STYLE_AUTO, "paragraph", layout.m_name );
00184
00185
00186 #if 0
00187
00188 if ( m_paragLayout.counter && m_paragLayout.counter->depth() ) {
00189 if ( m_bOutline )
00190 gs.addAttribute( "style:default-outline-level", (int)m_paragLayout.counter->depth() + 1 );
00191 else
00192 gs.addAttribute( "style:default-level", (int)m_paragLayout.counter->depth() + 1 );
00193 }
00194 #endif
00195 fillGenStyleWithLayout( layout, gs, false );
00196 fillGenStyleWithFormatOne( layout.m_format , gs, false );
00197
00198 layout.m_autoStyleName = m_oasisGenStyles.lookup( gs, "P", true );
00199
00200 kdDebug(30520) << "Layout: Parent " << layout.m_name << " => " << layout.m_autoStyleName << endl;
00201 }
00202
00203
00204
00205 void KWord13OasisGenerator::declareStyle( KWord13Layout& layout )
00206 {
00207 KoGenStyle gs( KoGenStyle::STYLE_USER, "paragraph", QString::null );
00208
00209 gs.addAttribute( "style:display-name", layout.m_name );
00210 #if 0
00211
00212 if ( m_paragLayout.counter && m_paragLayout.counter->depth() ) {
00213 if ( m_bOutline )
00214 gs.addAttribute( "style:default-outline-level", (int)m_paragLayout.counter->depth() + 1 );
00215 else
00216 gs.addAttribute( "style:default-level", (int)m_paragLayout.counter->depth() + 1 );
00217 }
00218 #endif
00219 fillGenStyleWithLayout( layout, gs, true );
00220 fillGenStyleWithFormatOne( layout.m_format , gs, true );
00221
00222 layout.m_autoStyleName = m_oasisGenStyles.lookup( gs, layout.m_name, false );
00223
00224 kdDebug(30520) << "Style: " << layout.m_name << " => " << layout.m_autoStyleName << endl;
00225 }
00226
00227
00228
00229 void KWord13OasisGenerator::fillGenStyleWithFormatOne( const KWord13FormatOneData& one, KoGenStyle& gs, const bool style ) const
00230 {
00231 QString str;
00232
00233 KoGenStyle::PropertyType tt = KoGenStyle::TextType;
00234 bool redok = false, greenok = false, blueok = false, ok = false;
00235 const QColor color(
00236 one.getProperty( "COLOR:red" ).toInt( &redok ),
00237 one.getProperty( "COLOR:green" ).toInt( &greenok ),
00238 one.getProperty( "COLOR:blue" ).toInt( &blueok ) );
00239 if ( color.isValid() && redok && greenok && blueok )
00240 {
00241 gs.addProperty( "fo:color", color.name(), tt );
00242 }
00243 else if ( style )
00244 {
00245 gs.addProperty( "fo:color", "#000000", tt );
00246 }
00247
00248 str = one.getProperty( "FONT:name" );
00249 if ( !str.isEmpty() )
00250 {
00251 gs.addProperty( "style:font-name", str, tt );
00252 }
00253
00254
00255 double d = numberOrNull( one.getProperty( "SIZE:value" ) );
00256 if ( d >= 1.0 )
00257 {
00258 gs.addPropertyPt( "fo:font-size", d, tt );
00259 }
00260
00261
00262 ok = false;
00263 const int weight = one.getProperty( "WEIGHT:value" ).toInt( &ok );
00264 if ( ok && weight >=0 )
00265 {
00266 if ( weight == 50 )
00267 {
00268 gs.addProperty( "fo:font-weight", "normal", tt );
00269 }
00270 else if (weight == 75 )
00271 {
00272 gs.addProperty( "fo:font-weight", "bold", tt );
00273 }
00274 else
00275 {
00276 gs.addProperty( "fo:font-weight", QString::number( weight * 10 ), tt );
00277 }
00278 }
00279 else if ( style )
00280 {
00281 gs.addProperty( "fo:font-weight", "normal", tt );
00282 }
00283
00284 ok = false;
00285 const int italic = one.getProperty( "ITALIC:value" ).toInt( &ok );
00286 if ( ok && ( italic == 1 ) )
00287 {
00288 gs.addProperty( "fo:font-style", "italic", tt );
00289 }
00290 else if ( ( ok && ! italic ) || style )
00291 {
00292 gs.addProperty( "fo:font-style", "normal", tt );
00293 }
00294
00295
00296 #if 0
00297
00298 gs.addProperty( "style:text-underline-mode", d->m_bWordByWord ? "skip-white-space" : "continuous", tt );
00299 gs.addProperty( "style:text-underline-type", m_underlineType == U_NONE ? "none" :
00300 m_underlineType == U_DOUBLE ? "double" : "single", tt );
00301 QString styleline;
00302 if ( m_underlineType == U_WAVE )
00303 styleline = "wave";
00304 else
00305 styleline = exportOasisUnderline( m_underlineStyle );
00306 gs.addProperty( "style:text-underline-style", styleline, tt );
00307 gs.addProperty( "style:text-underline-color", m_textUnderlineColor.isValid() ? m_textUnderlineColor.name() : "font-color", tt );
00308
00309
00310 gs.addProperty( "style:text-line-through-type", m_strikeOutType == S_NONE ? "none" :
00311 m_strikeOutType == S_DOUBLE ? "double" : "single", tt );
00312
00313 styleline = exportOasisUnderline( (UnderlineStyle) m_strikeOutStyle );
00314 gs.addProperty( "style:text-line-through-style", styleline, tt );
00315
00316
00317 QString textPos;
00318 if ( d->m_offsetFromBaseLine != 0 )
00319 textPos = QString::number( 100 * d->m_offsetFromBaseLine / fn.pointSizeFloat() ) + '%';
00320 else if ( va == AlignSuperScript ) textPos = "super";
00321 else if ( va == AlignSubScript ) textPos = "sub";
00322 else textPos = "0%";
00323 textPos += ' ';
00324 textPos += QString::number( d->m_relativeTextSize * 100 );
00325 textPos += '%';
00326 gs.addProperty( "style:text-position", textPos, tt );
00327
00328 if ( m_attributeFont == ATT_SMALL_CAPS )
00329 gs.addProperty( "fo:font-variant", "small-caps", tt );
00330 else if ( m_attributeFont == ATT_UPPER )
00331 gs.addProperty( "fo:text-transform", "uppercase", tt );
00332 else if ( m_attributeFont == ATT_LOWER )
00333 gs.addProperty( "fo:text-transform", "lowercase", tt );
00334
00335 gs.addProperty( "fo:language", m_language == "en_US" ? QString("en") : m_language, tt );
00336 gs.addProperty( "fo:background-color",
00337 m_textBackColor.isValid() ? m_textBackColor.name() : "transparent", tt );
00338 gs.addProperty( "fo:text-shadow", shadowAsCss(), tt );
00339 gs.addProperty( "fo:hyphenate", d->m_bHyphenation, tt );
00340 #endif
00341 }
00342
00343
00344 void KWord13OasisGenerator::fillGenStyleWithLayout( const KWord13Layout& layout, KoGenStyle& gs, const bool style ) const
00345 {
00346
00347
00348 QString str;
00349
00350 str = layout.getProperty( "FLOW:align" );
00351 if ( str.isEmpty() && ! style)
00352 {
00353
00354 }
00355 else if ( ( str == "left" ) || ( str == "right") || ( str == "center" ) || ( str == "justify" ) )
00356 {
00357 gs.addProperty( "fo:text-align", str );
00358 }
00359 else
00360 {
00361 gs.addProperty( "fo:text-align", "start" );
00362 }
00363
00364 str = layout.getProperty( "FLOW:dir" );
00365 if ( str == "R" )
00366 {
00367 gs.addProperty( "style:writing-mode", "rl-tb" );
00368 }
00369 else if ( style )
00370 {
00371 gs.addProperty( "style:writing-mode", "lr-tb" );
00372 }
00373
00374
00375 gs.addPropertyPt( "fo:margin-left", numberOrNull( layout.getProperty( "INDENTS:left" ) ) );
00376 gs.addPropertyPt( "fo:margin-right", numberOrNull( layout.getProperty( "INDENTS:right" ) ) );
00377 gs.addPropertyPt( "fo:text-indent", numberOrNull( layout.getProperty( "INDENTS:first" ) ) );
00378 gs.addPropertyPt( "fo:margin-top", numberOrNull( layout.getProperty( "OFFSETS:before" ) ) );
00379 gs.addPropertyPt( "fo:margin-bottom", numberOrNull( layout.getProperty( "OFFSETS:after" ) ) );
00380
00381 #if 0
00382 switch ( lineSpacingType ) {
00383 case KoParagLayout::LS_SINGLE:
00384 gs.addProperty( "fo:line-height", "100%" );
00385 break;
00386 case KoParagLayout::LS_ONEANDHALF:
00387 gs.addProperty( "fo:line-height", "150%" );
00388 break;
00389 case KoParagLayout::LS_DOUBLE:
00390 gs.addProperty( "fo:line-height", "200%" );
00391 break;
00392 case KoParagLayout::LS_MULTIPLE:
00393 gs.addProperty( "fo:line-height", QString::number( lineSpacing * 100.0 ) + '%' );
00394 break;
00395 case KoParagLayout::LS_FIXED:
00396 gs.addPropertyPt( "fo:line-height", lineSpacing );
00397 break;
00398 case KoParagLayout::LS_CUSTOM:
00399 gs.addPropertyPt( "style:line-spacing", lineSpacing );
00400 break;
00401 case KoParagLayout::LS_AT_LEAST:
00402 gs.addPropertyPt( "style:line-height-at-least", lineSpacing );
00403 break;
00404 }
00405 #endif
00406
00407 #if 0
00408 QBuffer buffer;
00409 buffer.open( IO_WriteOnly );
00410 KoXmlWriter tabsWriter( &buffer, 4 );
00411 tabsWriter.startElement( "style:tab-stops" );
00412 KoTabulatorList::ConstIterator it = m_tabList.begin();
00413 for ( ; it != m_tabList.end() ; it++ )
00414 {
00415 tabsWriter.startElement( "style:tab-stop" );
00416 tabsWriter.addAttributePt( "style:position", (*it).ptPos );
00417
00418 switch ( (*it).type ) {
00419 case T_LEFT:
00420 tabsWriter.addAttribute( "style:type", "left" );
00421 break;
00422 case T_CENTER:
00423 tabsWriter.addAttribute( "style:type", "center" );
00424 break;
00425 case T_RIGHT:
00426 tabsWriter.addAttribute( "style:type", "right" );
00427 break;
00428 case T_DEC_PNT:
00429 tabsWriter.addAttribute( "style:type", "char" );
00430 tabsWriter.addAttribute( "style:char", QString( (*it).alignChar ) );
00431 break;
00432 case T_INVALID:
00433 break;
00434 }
00435 switch( (*it).filling ) {
00436 case TF_BLANK:
00437 tabsWriter.addAttribute( "style:leader-type", "none" );
00438 break;
00439 case TF_LINE:
00440 tabsWriter.addAttribute( "style:leader-type", "single" );
00441 tabsWriter.addAttribute( "style:leader-style", "solid" );
00442
00443 tabsWriter.addAttribute( "style:leader-text", "_" );
00444 break;
00445 case TF_DOTS:
00446 tabsWriter.addAttribute( "style:leader-type", "single" );
00447 tabsWriter.addAttribute( "style:leader-style", "dotted" );
00448
00449 tabsWriter.addAttribute( "style:leader-text", "." );
00450 break;
00451 case TF_DASH:
00452 tabsWriter.addAttribute( "style:leader-type", "single" );
00453 tabsWriter.addAttribute( "style:leader-style", "dash" );
00454
00455 tabsWriter.addAttribute( "style:leader-text", "_" );
00456 break;
00457 case TF_DASH_DOT:
00458 tabsWriter.addAttribute( "style:leader-type", "single" );
00459 tabsWriter.addAttribute( "style:leader-style", "dot-dash" );
00460
00461 tabsWriter.addAttribute( "style:leader-text", "." );
00462 break;
00463 case TF_DASH_DOT_DOT:
00464 tabsWriter.addAttribute( "style:leader-type", "single" );
00465 tabsWriter.addAttribute( "style:leader-style", "dot-dot-dash" );
00466
00467 tabsWriter.addAttribute( "style:leader-text", "." );
00468 break;
00469 }
00470 if ( (*it).filling != TF_BLANK )
00471 tabsWriter.addAttributePt( "style:leader-width", (*it).ptWidth );
00472
00473 tabsWriter.endElement();
00474 }
00475 tabsWriter.endElement();
00476 buffer.close();
00477 QString elementContents = QString::fromUtf8( buffer.buffer(), buffer.buffer().size() );
00478 gs.addChildElement( "style:tab-stops", elementContents );
00479 #endif
00480
00481 #if 0
00482 bool fourBordersEqual = leftBorder.penWidth() > 0 &&
00483 leftBorder == rightBorder && rightBorder == topBorder && topBorder == bottomBorder;
00484 if ( fourBordersEqual ) {
00485 gs.addProperty( "fo:border", leftBorder.saveFoBorder() );
00486 } else {
00487 if ( leftBorder.penWidth() > 0 )
00488 gs.addProperty( "fo:border-left", leftBorder.saveFoBorder() );
00489 if ( rightBorder.penWidth() > 0 )
00490 gs.addProperty( "fo:border-right", rightBorder.saveFoBorder() );
00491 if ( topBorder.penWidth() > 0 )
00492 gs.addProperty( "fo:border-top", topBorder.saveFoBorder() );
00493 if ( bottomBorder.penWidth() > 0 )
00494 gs.addProperty( "fo:border-bottom", bottomBorder.saveFoBorder() );
00495 }
00496 #endif
00497
00498 #if 0
00499 if ( pageBreaking & KoParagLayout::HardFrameBreakBefore )
00500 gs.addProperty( "fo:break-before", "column" );
00501 else if ( pageBreaking & KoParagLayout::HardFrameBreakAfter )
00502 gs.addProperty( "fo:break-after", "column" );
00503 if ( pageBreaking & KoParagLayout::KeepLinesTogether )
00504 gs.addProperty( "fo:keep-together", "always" );
00505 if ( pageBreaking & KoParagLayout::KeepWithNext )
00506 gs.addProperty( "fo:keep-with-next", "always" );
00507 #endif
00508 }
00509
00510
00511 void KWord13OasisGenerator::generateTextFrameset( KoXmlWriter& writer, KWordTextFrameset* frameset, bool )
00512 {
00513 if ( ! frameset )
00514 {
00515 kdWarning(30520) << "Tried to generate a NULL text frameset!" << endl;
00516 return;
00517 }
00518
00519 for ( QValueList<KWord13Paragraph>::Iterator it = frameset->m_paragraphGroup.begin();
00520 it != frameset->m_paragraphGroup.end(); ++it)
00521 {
00522
00523 writer.startElement( "text:p", false );
00524 writer.addAttribute( "text:style-name", (*it).m_layout.m_autoStyleName );
00525 #if 1
00526 const QString paragraphText( (*it).text() );
00527 int currentPos = 0;
00528
00529 for ( KWord13Format* format = (*it).m_formats.first(); format; format = (*it).m_formats.next() )
00530 {
00531
00532 const int pos = format->m_pos;
00533 const int length = format->length();
00534 if ( currentPos < pos )
00535 {
00536 writer.addTextSpan( paragraphText.mid( currentPos, pos - currentPos ) );
00537 currentPos = pos;
00538 }
00539
00540 KWord13FormatOneData* data = format->getFormatOneData();
00541 if ( data && format->m_id == 1 )
00542 {
00543 writer.startElement( "text:span" );
00544 writer.addAttribute( "text:style-name", data->m_autoStyleName );
00545 writer.addTextSpan( paragraphText.mid( pos, length ) );
00546 writer.endElement();
00547 }
00548 else if ( format->m_id == 3 )
00549 {
00550
00551 writer.addTextSpan("\t");
00552 }
00553 else if ( format->m_id == 4 )
00554 {
00555
00556 const QString text ( ( (KWord13FormatFour*) format ) -> m_text );
00557 if ( text.isEmpty() )
00558 writer.addTextNode( "#" );
00559 else
00560 writer.addTextSpan( text );
00561 }
00562 else
00563 {
00564
00565 writer.addTextNode("#");
00566 }
00567 currentPos += length;
00568 }
00569
00570 const QString tailText( paragraphText.mid( currentPos ) );
00571 if ( ! tailText.isEmpty() )
00572 writer.addTextSpan( tailText );
00573 #else
00574 writer.addTextSpan( (*it).text() );
00575 #endif
00576 writer.endElement();
00577 }
00578 }
00579
00580
00581 void KWord13OasisGenerator::writeStylesXml( void )
00582 {
00583 if ( !m_store || !m_kwordDocument )
00584 {
00585 kdError(30520) << "Not possible to generate style.xml" << endl;
00586 return;
00587 }
00588
00589 m_store->open("styles.xml");
00590 KoStoreDevice io ( m_store );
00591 io.open( IO_WriteOnly );
00592
00593 KoXmlWriter *stylesWriter = KoDocument::createOasisXmlWriter( &io, "office:document-styles" );
00594
00595 stylesWriter->startElement( "office:styles" );
00596 QValueList<KoGenStyles::NamedStyle> styles = m_oasisGenStyles.styles( KoGenStyle::STYLE_USER );
00597 QValueList<KoGenStyles::NamedStyle>::const_iterator it = styles.begin();
00598 for ( ; it != styles.end() ; ++it ) {
00599 (*it).style->writeStyle( stylesWriter, m_oasisGenStyles, "style:style", (*it).name, "style:paragraph-properties" );
00600 }
00601 stylesWriter->endElement();
00602
00603 stylesWriter->startElement( "office:automatic-styles" );
00604 #if 0
00605 styles = m_oasisGenStyles.styles( KWDocument::STYLE_FRAME );
00606 it = styles.begin();
00607 for ( ; it != styles.end() ; ++it ) {
00608 (*it).style->writeStyle( stylesWriter, m_oasisGenStyles, "style:style", (*it).name , "style:graphic-properties" );
00609 }
00610 #endif
00611
00612 QString pageLayoutName;
00613 styles = m_oasisGenStyles.styles( KoGenStyle::STYLE_PAGELAYOUT );
00614 Q_ASSERT( styles.count() == 1 );
00615 it = styles.begin();
00616 for ( ; it != styles.end() ; ++it ) {
00617 (*it).style->writeStyle( stylesWriter, m_oasisGenStyles, "style:page-layout", (*it).name, "style:page-layout-properties", false );
00618
00619
00620 stylesWriter->endElement();
00621 Q_ASSERT( pageLayoutName.isEmpty() );
00622 pageLayoutName = (*it).name;
00623 }
00624
00625
00626
00627 stylesWriter->endElement();
00628
00629 stylesWriter->startElement( "office:master-styles" );
00630 stylesWriter->startElement( "style:master-page" );
00631 stylesWriter->addAttribute( "style:name", "Standard" );
00632 stylesWriter->addAttribute( "style:page-layout-name", pageLayoutName );
00633 stylesWriter->endElement();
00634 stylesWriter->endElement();
00635
00636 stylesWriter->endElement();
00637 stylesWriter->endDocument();
00638 io.close();
00639 m_store->close();
00640 delete stylesWriter;
00641
00642 if ( m_manifestWriter )
00643 {
00644 m_manifestWriter->addManifestEntry( "styles.xml", "text/xml" );
00645 }
00646
00647 }
00648
00649
00650 void KWord13OasisGenerator::writeContentXml(void)
00651 {
00652 if ( !m_store || !m_kwordDocument )
00653 {
00654 kdError(30520) << "Not possible to generate content.xml" << endl;
00655 return;
00656 }
00657
00658 m_store->open("content.xml");
00659 KoStoreDevice io ( m_store );
00660 io.open( IO_WriteOnly );
00661
00662 KoXmlWriter *writer = KoDocument::createOasisXmlWriter( &io, "office:document-content" );
00663
00664
00665
00666 writer->startElement( "office:automatic-styles" );
00667 QValueList<KoGenStyles::NamedStyle> styles = m_oasisGenStyles.styles( KoGenStyle::STYLE_AUTO );
00668 QValueList<KoGenStyles::NamedStyle>::const_iterator it;
00669 for ( it = styles.begin(); it != styles.end() ; ++it ) {
00670 (*it).style->writeStyle( writer, m_oasisGenStyles, "style:style", (*it).name, "style:paragraph-properties" );
00671 }
00672 styles = m_oasisGenStyles.styles( KoGenStyle::STYLE_LIST );
00673 for ( it = styles.begin(); it != styles.end() ; ++it ) {
00674 (*it).style->writeStyle( writer, m_oasisGenStyles, "text:list-style", (*it).name, 0 );
00675 }
00676 writer->endElement();
00677
00678 writer->startElement( "office:body" );
00679 writer->startElement( "office:text" );
00680
00681
00682 generateTextFrameset( *writer, m_kwordDocument->m_normalTextFramesetList.first(), true );
00683
00684 writer->endElement();
00685 writer->endElement();
00686
00687
00688
00689
00690 writer->endElement();
00691 writer->endDocument();
00692 io.close();
00693 delete writer;
00694 m_store->close();
00695
00696 if ( m_manifestWriter )
00697 {
00698 m_manifestWriter->addManifestEntry( "content.xml", "text/xml" );
00699 }
00700 }
00701
00702 void KWord13OasisGenerator::writeMetaXml(void)
00703 {
00704 if ( !m_store || !m_kwordDocument )
00705 {
00706 kdError(30520) << "Not possible to generate meta.xml" << endl;
00707 return;
00708 }
00709
00710 m_store->open("meta.xml");
00711 KoStoreDevice io ( m_store );
00712 io.open( IO_WriteOnly );
00713
00714 KoXmlWriter *writer = KoDocument::createOasisXmlWriter( &io, "office:document-meta" );
00715
00716 writer->startElement( "office:meta" );
00717
00718
00719
00720 writer->startElement( "meta:generator" );
00721 QString strVersion;
00722 strVersion += "KWord-OneDotThree-Import-Filter/";
00723 strVersion += QString( "$Revision: 515673 $" ).mid( 10 ).remove( '$' ).stripWhiteSpace();
00724 strVersion += " KOffice/";
00725 strVersion += KOFFICE_VERSION_STRING;
00726 writer->addTextSpan( strVersion );
00727 writer->endElement();
00728
00729 QString str;
00730
00731 str = m_kwordDocument->getDocumentInfo( "about:title" );
00732 if ( !str.isEmpty() )
00733 {
00734 writer->startElement( "dc:title" );
00735 writer->addTextSpan( str );
00736 writer->endElement();
00737 }
00738
00739 str = m_kwordDocument->getDocumentInfo( "about:abstract" );
00740 if (!str.isEmpty())
00741 {
00742 writer->startElement( "dc:description");
00743 writer->addTextSpan( str );
00744 writer->endElement();
00745 }
00746
00747 str = m_kwordDocument->getDocumentInfo( "author:full-name" );
00748 if ( !str.isEmpty() )
00749 {
00750 writer->startElement( "dc:creator" );
00751 writer->addTextSpan( str );
00752 writer->endElement();
00753 }
00754
00755
00756
00757 QDateTime dt;
00758
00759 dt = m_kwordDocument->creationDate();
00760 if ( dt.isValid() )
00761 {
00762 writer->startElement( "meta:creation-date");
00763 writer->addTextNode( dt.toString( Qt::ISODate) );
00764 writer->endElement();
00765 }
00766
00767 dt = m_kwordDocument->modificationDate();
00768 if ( dt.isValid() )
00769 {
00770 writer->startElement( "dc:date");
00771 writer->addTextNode( dt.toString( Qt::ISODate) );
00772 writer->endElement();
00773 }
00774
00775 dt = m_kwordDocument->lastPrintingDate();
00776 if ( dt.isValid() )
00777 {
00778 writer->startElement( "meta:print-date");
00779 writer->addTextNode( dt.toString( Qt::ISODate) );
00780 writer->endElement();
00781 }
00782
00783 writer->startElement( "meta:document-statistic" );
00784
00785
00786 const int numPages = m_kwordDocument->getProperty( "PAPER:pages" ).toInt();
00787 if ( numPages > 0 )
00788 {
00789 writer->addAttribute( "meta:page-count", numPages );
00790 }
00791
00792 #if 0
00793 zipWriteData( " meta:image-count=\"" );
00794 #if 1
00795 zipWriteData( "0" );
00796 #else
00797 zipWriteData( QString::number ( m_pictureNumber ) );
00798 #endif
00799 zipWriteData( "\"" );
00800
00801 zipWriteData( " meta:table-count=\"" );
00802 #if 1
00803 zipWriteData( "0" );
00804 #else
00805 zipWriteData( QString::number ( m_tableNumber ) );
00806 #endif
00807 zipWriteData( "\"" );
00808 #endif
00809 writer->endElement();
00810 writer->endElement();
00811
00812 writer->endElement();
00813 writer->endDocument();
00814 delete writer;
00815
00816 io.close();
00817 m_store->close();
00818
00819 if ( m_manifestWriter )
00820 {
00821 m_manifestWriter->addManifestEntry( "meta.xml", "text/xml" );
00822 }
00823 }
00824
00825 void KWord13OasisGenerator::writePreviewFile(void)
00826 {
00827 if ( !m_store || !m_kwordDocument )
00828 {
00829 kdError(30520) << "Not possible to generate preview file" << endl;
00830 return;
00831 }
00832
00833
00834 QImage image( m_kwordDocument->m_previewFile->name() );
00835 if ( image.isNull() )
00836 {
00837 kdWarning(30520) << "Could not re-read preview from temp file!" << endl;
00838 return;
00839 }
00840
00841
00842 QImage preview( image.convertDepth( 32, Qt::ColorOnly ).smoothScale( 128, 128 ) );
00843 if ( preview.isNull() )
00844 {
00845 kdWarning(30520) << "Could not create preview!" << endl;
00846 return;
00847 }
00848 if ( !preview.hasAlphaBuffer() )
00849 {
00850 preview.setAlphaBuffer( true );
00851 }
00852 m_store->open("Thumbnails/thumbnail.png");
00853 KoStoreDevice io ( m_store );
00854 io.open( IO_WriteOnly );
00855 preview.save( &io, "PNG", 0 );
00856 io.close();
00857 m_store->close();
00858
00859
00860 }
00861
00862 void KWord13OasisGenerator::writePictures( void )
00863 {
00864 if ( !m_store || !m_kwordDocument )
00865 {
00866 kdError(30520) << "Not possible to generate preview file" << endl;
00867 return;
00868 }
00869
00870 for ( QDictIterator<KWord13Picture> it( m_kwordDocument->m_pictureDict ) ; it.current(); ++it )
00871 {
00872 if ( !it.current()->m_valid || !it.current()->m_tempFile )
00873 {
00874 kdDebug(30520) << "No data for picture: " << it.currentKey() << endl;
00875 continue;
00876 }
00877 const QString fileName( it.current()->m_tempFile->name() );
00878 const QString oasisName( it.current()->getOasisPictureName() );
00879 kdDebug(30520) << "Copying... " << it.currentKey() << endl << " => " << oasisName << endl;
00880 QFile file( fileName );
00881 if ( !file.open( IO_ReadOnly ) )
00882 {
00883 kdWarning(30520) << "Cannot open: " << fileName << endl;
00884 continue;
00885 }
00886 QByteArray array( file.readAll() );
00887 if ( array.isNull() )
00888 {
00889 kdWarning(30520) << "Null picture for " << fileName << endl;
00890 file.close();
00891 continue;
00892 }
00893 file.close();
00894
00895 m_store->open( oasisName );
00896 m_store->write( array );
00897 m_store->close();
00898
00899 if ( m_manifestWriter )
00900 {
00901 const QString mimeType ( KMimeType::findByContent( array, 0 )->name() );
00902 if ( mimeType == "application/octet-stream" )
00903 {
00904 kdWarning(30520) << "Generic mime type for " << it.currentKey() << endl;
00905
00906 }
00907 m_manifestWriter->addManifestEntry( oasisName, mimeType );
00908 }
00909
00910 }
00911
00912 }
00913
00914 bool KWord13OasisGenerator::generate ( const QString& fileName, KWord13Document& kwordDocument )
00915 {
00916 if ( m_kwordDocument && ( (void*) m_kwordDocument ) != ( (void*) &kwordDocument ) )
00917 {
00918 kdWarning(30520) << "KWord Document is different!" <<endl;
00919 }
00920
00921 m_kwordDocument = &kwordDocument;
00922
00923 m_store = KoStore::createStore( fileName, KoStore::Write, "application/vnd.sun.xml.writer", KoStore::Zip );
00924 if ( ! m_store )
00925 {
00926 kdError(30520) << "Cannot create output KoStore" << endl;
00927 return false;
00928 }
00929 m_store->disallowNameExpansion();
00930
00931
00932 QByteArray manifestData;
00933 QBuffer manifestBuffer( manifestData );
00934 manifestBuffer.open( IO_WriteOnly );
00935 m_manifestWriter = new KoXmlWriter( &manifestBuffer );
00936 m_manifestWriter->startDocument( "manifest:manifest" );
00937 m_manifestWriter->startElement( "manifest:manifest" );
00938 m_manifestWriter->addAttribute( "xmlns:manifest", "urn:oasis:names:tc:openoffice:xmlns:manifest:1.0" );
00939
00940
00941
00942 writeStylesXml();
00943 writeContentXml();
00944 writeMetaXml();
00945 writePictures();
00946
00947
00948 m_manifestWriter->endElement();
00949 m_manifestWriter->endDocument();
00950 delete m_manifestWriter;
00951 m_manifestWriter = 0;
00952 if ( m_store->open( "META-INF/manifest.xml" ) )
00953 {
00954 m_store->write( manifestData );
00955 m_store->close();
00956 }
00957
00958 if ( kwordDocument.m_previewFile )
00959 {
00960 writePreviewFile();
00961 }
00962 else
00963 {
00964 kdDebug(30520) << "No preview file available to make an OASIS thumbnail!" << endl;
00965 }
00966
00967
00968 # ifndef NDEBUG // DEBUG (out of specification)
00969
00970 if ( m_store->open("Debug/debug.xml") )
00971 {
00972 KoStoreDevice io ( m_store );
00973 io.open( IO_WriteOnly );
00974 kwordDocument.xmldump( &io );
00975 io.close();
00976 m_store->close();
00977 }
00978 # endif
00979
00980
00981 delete m_store;
00982 m_store = 0;
00983 return true;
00984 }
00985