23#include <KoDocument.h>
24#include <KoStyleStack.h>
35const char*
const ooNS::office=
"http://openoffice.org/2000/office";
36const char*
const ooNS::style=
"http://openoffice.org/2000/style";
37const char*
const ooNS::text=
"http://openoffice.org/2000/text";
38const char*
const ooNS::table=
"http://openoffice.org/2000/table";
39const char*
const ooNS::draw=
"http://openoffice.org/2000/drawing";
40const char*
const ooNS::presentation=
"http://openoffice.org/2000/presentation";
41const char*
const ooNS::fo=
"http://www.w3.org/1999/XSL/Format";
42const char*
const ooNS::xlink=
"http://www.w3.org/1999/xlink";
43const char*
const ooNS::number=
"http://openoffice.org/2000/datastyle";
44const char*
const ooNS::svg=
"http://www.w3.org/2000/svg";
45const char*
const ooNS::dc=
"http://purl.org/dc/elements/1.1/";
46const char*
const ooNS::meta=
"http://openoffice.org/2000/meta";
47const char*
const ooNS::config=
"http://openoffice.org/2001/config";
49TQString OoUtils::expandWhitespace(
const TQDomElement& tag)
54 if (tag.hasAttributeNS( ooNS::text,
"c"))
55 howmany = tag.attributeNS( ooNS::text,
"c", TQString()).toInt();
58 return result.fill(32, howmany);
61bool OoUtils::parseBorder(
const TQString & tag,
double * width,
int * style, TQColor * color)
65 if (tag.isEmpty() || tag==
"none" || tag==
"hidden")
68 TQString _width = tag.section(
' ', 0, 0);
69 TQString _style = tag.section(
' ', 1, 1);
70 TQString _color = tag.section(
' ', 2, 2);
72 *width = KoUnit::parseValue(_width, 1.0);
74 if ( _style ==
"dashed" )
76 else if ( _style ==
"dotted" )
78 else if ( _style ==
"dot-dash" )
80 else if ( _style ==
"dot-dot-dash" )
82 else if ( _style ==
"double" )
90 color->setNamedColor(_color);
95void OoUtils::importIndents( TQDomElement& parentElement,
const KoStyleStack& styleStack )
97 if ( styleStack.hasAttributeNS( ooNS::fo,
"margin-left" ) ||
98 styleStack.hasAttributeNS( ooNS::fo,
"margin-right" ) )
101 double marginLeft = KoUnit::parseValue( styleStack.attributeNS( ooNS::fo,
"margin-left" ) );
102 double marginRight = KoUnit::parseValue( styleStack.attributeNS( ooNS::fo,
"margin-right" ) );
104 if (styleStack.attributeNS( ooNS::style,
"auto-text-indent") ==
"true")
109 else if (styleStack.hasAttributeNS( ooNS::fo,
"text-indent"))
110 first = KoUnit::parseValue( styleStack.attributeNS( ooNS::fo,
"text-indent"));
112 if ( marginLeft != 0 || marginRight != 0 || first != 0 )
114 TQDomElement indent = parentElement.ownerDocument().createElement(
"INDENTS" );
115 if( marginLeft != 0 )
116 indent.setAttribute(
"left", marginLeft );
117 if( marginRight != 0 )
118 indent.setAttribute(
"right", marginRight );
120 indent.setAttribute(
"first", first );
121 parentElement.appendChild( indent );
126void OoUtils::importLineSpacing( TQDomElement& parentElement,
const KoStyleStack& styleStack )
128 if( styleStack.hasAttributeNS( ooNS::fo,
"line-height") )
131 TQString value = styleStack.attributeNS( ooNS::fo,
"line-height" );
132 if ( value !=
"normal" )
134 TQDomElement lineSpacing = parentElement.ownerDocument().createElement(
"LINESPACING" );
136 if ( value.endsWith(
"%" ) )
138 double percent = value.left(value.length()-1).toDouble();
140 lineSpacing.setAttribute(
"type",
"single");
141 else if( percent == 150 )
142 lineSpacing.setAttribute(
"type",
"oneandhalf");
143 else if( percent == 200 )
144 lineSpacing.setAttribute(
"type",
"double");
147 lineSpacing.setAttribute(
"type",
"multiple");
148 lineSpacing.setAttribute(
"spacingvalue", percent/100);
153 kdWarning(30519) <<
"Unhandled value for fo:line-height: " << value << endl;
154 lineSpacing.setAttribute(
"type",
"single");
156 parentElement.appendChild( lineSpacing );
160 else if ( styleStack.hasAttributeNS( ooNS::style,
"line-height-at-least") )
162 TQString value = styleStack.attributeNS( ooNS::style,
"line-height-at-least" );
168 TQDomElement lineSpacing = parentElement.ownerDocument().createElement(
"LINESPACING");
169 lineSpacing.setAttribute(
"type",
"atleast");
170 lineSpacing.setAttribute(
"spacingvalue", KoUnit::parseValue(value));
171 parentElement.appendChild(lineSpacing);
174 else if ( styleStack.hasAttributeNS( ooNS::style,
"line-spacing") )
176 double value = KoUnit::parseValue( styleStack.attributeNS( ooNS::style,
"line-spacing" ) );
179 TQDomElement lineSpacing = parentElement.ownerDocument().createElement(
"LINESPACING" );
180 lineSpacing.setAttribute(
"type",
"custom" );
181 lineSpacing.setAttribute(
"spacingvalue", value );
182 parentElement.appendChild( lineSpacing );
188void OoUtils::importTopBottomMargin( TQDomElement& parentElement,
const KoStyleStack& styleStack )
190 if( styleStack.hasAttributeNS( ooNS::fo,
"margin-top") ||
191 styleStack.hasAttributeNS( ooNS::fo,
"margin-bottom"))
193 double mtop = KoUnit::parseValue( styleStack.attributeNS( ooNS::fo,
"margin-top" ) );
194 double mbottom = KoUnit::parseValue( styleStack.attributeNS( ooNS::fo,
"margin-bottom" ) );
195 if( mtop != 0 || mbottom != 0 )
197 TQDomElement offset = parentElement.ownerDocument().createElement(
"OFFSETS" );
199 offset.setAttribute(
"before", mtop );
201 offset.setAttribute(
"after", mbottom );
202 parentElement.appendChild( offset );
207void OoUtils::importTabulators( TQDomElement& parentElement,
const KoStyleStack& styleStack )
209 if ( !styleStack.hasChildNodeNS( ooNS::style,
"tab-stops" ) )
211 TQDomElement tabStops = styleStack.childNodeNS( ooNS::style,
"tab-stops" );
213 for ( TQDomNode it = tabStops.firstChild(); !it.isNull(); it = it.nextSibling() )
215 TQDomElement tabStop = it.toElement();
216 Q_ASSERT( tabStop.tagName() ==
"style:tab-stop" );
217 TQString type = tabStop.attributeNS( ooNS::style,
"type", TQString() );
219 TQDomElement elem = parentElement.ownerDocument().createElement(
"TABULATOR" );
221 if ( type ==
"left" )
223 else if ( type ==
"center" )
225 else if ( type ==
"right" )
227 else if ( type ==
"char" ) {
228 TQString delimiterChar = tabStop.attributeNS( ooNS::style,
"char", TQString() );
229 elem.setAttribute(
"alignchar", delimiterChar );
233 elem.setAttribute(
"type", kOfficeType );
235 double pos = KoUnit::parseValue( tabStop.attributeNS( ooNS::style,
"position", TQString() ) );
236 elem.setAttribute(
"ptpos", pos );
240 TQString leaderChar = tabStop.attributeNS( ooNS::style,
"leader-char", TQString() );
241 if ( !leaderChar.isEmpty() )
244 TQChar ch = leaderChar[0];
245 switch (ch.latin1()) {
256 elem.setAttribute(
"filling", filling );
258 parentElement.appendChild( elem );
263void OoUtils::importBorders( TQDomElement& parentElement,
const KoStyleStack& styleStack )
265 if (styleStack.hasAttributeNS( ooNS::fo,
"border",
"left"))
270 if (OoUtils::parseBorder(styleStack.attributeNS( ooNS::fo,
"border",
"left"), &width, &style, &color))
272 TQDomElement lbElem = parentElement.ownerDocument().createElement(
"LEFTBORDER");
273 lbElem.setAttribute(
"width", width);
274 lbElem.setAttribute(
"style", style);
275 if (color.isValid()) {
276 lbElem.setAttribute(
"red", color.red());
277 lbElem.setAttribute(
"green", color.green());
278 lbElem.setAttribute(
"blue", color.blue());
280 parentElement.appendChild(lbElem);
284 if (styleStack.hasAttributeNS( ooNS::fo,
"border",
"right"))
289 if (OoUtils::parseBorder(styleStack.attributeNS( ooNS::fo,
"border",
"right"), &width, &style, &color))
291 TQDomElement lbElem = parentElement.ownerDocument().createElement(
"RIGHTBORDER");
292 lbElem.setAttribute(
"width", width);
293 lbElem.setAttribute(
"style", style);
294 if (color.isValid()) {
295 lbElem.setAttribute(
"red", color.red());
296 lbElem.setAttribute(
"green", color.green());
297 lbElem.setAttribute(
"blue", color.blue());
299 parentElement.appendChild(lbElem);
303 if (styleStack.hasAttributeNS( ooNS::fo,
"border",
"top"))
308 if (OoUtils::parseBorder(styleStack.attributeNS( ooNS::fo,
"border",
"top"), &width, &style, &color))
310 TQDomElement lbElem = parentElement.ownerDocument().createElement(
"TOPBORDER");
311 lbElem.setAttribute(
"width", width);
312 lbElem.setAttribute(
"style", style);
313 if (color.isValid()) {
314 lbElem.setAttribute(
"red", color.red());
315 lbElem.setAttribute(
"green", color.green());
316 lbElem.setAttribute(
"blue", color.blue());
318 parentElement.appendChild(lbElem);
322 if (styleStack.hasAttributeNS( ooNS::fo,
"border",
"bottom"))
327 if (OoUtils::parseBorder(styleStack.attributeNS( ooNS::fo,
"border",
"bottom"), &width, &style, &color))
329 TQDomElement lbElem = parentElement.ownerDocument().createElement(
"BOTTOMBORDER");
330 lbElem.setAttribute(
"width", width);
331 lbElem.setAttribute(
"style", style);
332 if (color.isValid()) {
333 lbElem.setAttribute(
"red", color.red());
334 lbElem.setAttribute(
"green", color.green());
335 lbElem.setAttribute(
"blue", color.blue());
337 parentElement.appendChild(lbElem);
342void OoUtils::importUnderline(
const TQString& in, TQString& underline, TQString& styleline )
344 underline =
"single";
347 else if ( in ==
"single" )
349 else if ( in ==
"double" )
354 else if ( in ==
"dotted" || in ==
"bold-dotted" )
356 else if ( in ==
"dash"
360 || in ==
"bold-long-dash"
363 else if ( in ==
"dot-dash"
364 || in ==
"bold-dot-dash")
365 styleline =
"dashdot";
366 else if ( in ==
"dot-dot-dash"
367 || in ==
"bold-dot-dot-dash")
368 styleline =
"dashdotdot";
369 else if ( in ==
"wave"
371 || in ==
"double-wave"
372 || in ==
"small-wave" )
377 else if( in ==
"bold" )
379 underline =
"single-bold";
383 kdWarning(30519) << k_funcinfo <<
" unsupported text-underline value: " << in << endl;
386void OoUtils::importTextPosition(
const TQString& text_position, TQString& value, TQString& relativetextsize )
391 TQStringList lst = TQStringList::split(
' ', text_position );
392 if ( !lst.isEmpty() )
394 TQString textPos = lst.front().stripWhiteSpace();
397 if ( !lst.isEmpty() )
398 textSize = lst.front().stripWhiteSpace();
399 if ( !lst.isEmpty() )
400 kdWarning(30519) <<
"Strange text position: " << text_position << endl;
401 bool super = textPos ==
"super";
402 bool sub = textPos ==
"sub";
403 if ( textPos.endsWith(
"%") )
405 textPos.truncate( textPos.length() - 1 );
408 double val = textPos.toDouble();
420 if ( !textSize.isEmpty() && textSize.endsWith(
"%") )
422 textSize.truncate( textSize.length() - 1 );
423 double textSizeValue = textSize.toDouble() / 100;
424 relativetextsize = TQString::number( textSizeValue );
431void OoUtils::createDocumentInfo(TQDomDocument &_meta, TQDomDocument & docinfo)
433 TQDomNode meta = KoDom::namedItemNS( _meta, ooNS::office,
"document-meta" );
434 TQDomNode office = KoDom::namedItemNS( meta, ooNS::office,
"meta" );
436 if ( office.isNull() )
438 TQDomElement elementDocInfo = docinfo.documentElement();
440 TQDomElement e = KoDom::namedItemNS( office, ooNS::dc,
"creator" );
441 if ( !e.isNull() && !e.text().isEmpty() )
443 TQDomElement author = docinfo.createElement(
"author" );
444 TQDomElement t = docinfo.createElement(
"full-name" );
445 author.appendChild( t );
446 t.appendChild( docinfo.createTextNode( e.text() ) );
447 elementDocInfo.appendChild( author);
450 e = KoDom::namedItemNS( office, ooNS::dc,
"title" );
451 if ( !e.isNull() && !e.text().isEmpty() )
453 TQDomElement about = docinfo.createElement(
"about" );
454 TQDomElement title = docinfo.createElement(
"title" );
455 about.appendChild( title );
456 title.appendChild( docinfo.createTextNode( e.text() ) );
457 elementDocInfo.appendChild( about );
460 e = KoDom::namedItemNS( office, ooNS::dc,
"description" );
461 if ( !e.isNull() && !e.text().isEmpty() )
463 TQDomElement about = elementDocInfo.namedItem(
"about" ).toElement();
464 if ( about.isNull() ) {
465 about = docinfo.createElement(
"about" );
466 elementDocInfo.appendChild( about );
468 TQDomElement title = docinfo.createElement(
"abstract" );
469 about.appendChild( title );
470 title.appendChild( docinfo.createTextNode( e.text() ) );
472 e = KoDom::namedItemNS( office, ooNS::dc,
"subject" );
473 if ( !e.isNull() && !e.text().isEmpty() )
475 TQDomElement about = elementDocInfo.namedItem(
"about" ).toElement();
476 if ( about.isNull() ) {
477 about = docinfo.createElement(
"about" );
478 elementDocInfo.appendChild( about );
480 TQDomElement subject = docinfo.createElement(
"subject" );
481 about.appendChild( subject );
482 subject.appendChild( docinfo.createTextNode( e.text() ) );
484 e = KoDom::namedItemNS( office, ooNS::meta,
"keywords" );
487 TQDomElement about = elementDocInfo.namedItem(
"about" ).toElement();
488 if ( about.isNull() ) {
489 about = docinfo.createElement(
"about" );
490 elementDocInfo.appendChild( about );
492 TQDomElement tmp = KoDom::namedItemNS( e, ooNS::meta,
"keyword" );
493 if ( !tmp.isNull() && !tmp.text().isEmpty() )
495 TQDomElement keyword = docinfo.createElement(
"keyword" );
496 about.appendChild( keyword );
497 keyword.appendChild( docinfo.createTextNode( tmp.text() ) );
502KoFilter::ConversionStatus OoUtils::loadAndParse(
const TQString& fileName, TQDomDocument& doc, KoStore *m_store )
504 kdDebug(30518) <<
"loadAndParse: Trying to open " << fileName << endl;
506 if (!m_store->open(fileName))
508 kdWarning(30519) <<
"Entry " << fileName <<
" not found!" << endl;
509 return KoFilter::FileNotFound;
511 KoFilter::ConversionStatus convertStatus = loadAndParse( m_store->device(),doc, fileName );
513 return convertStatus;
517KoFilter::ConversionStatus OoUtils::loadAndParse(TQIODevice* io, TQDomDocument& doc,
const TQString & fileName)
519 TQXmlInputSource source( io );
521 TQXmlSimpleReader reader;
522 KoDocument::setupXmlReader( reader,
true );
526 int errorLine, errorColumn;
527 if ( !doc.setContent( &source, &reader, &errorMsg, &errorLine, &errorColumn ) )
529 kdError(30519) <<
"Parsing error in " << fileName <<
"! Aborting!" << endl
530 <<
" In line: " << errorLine <<
", column: " << errorColumn << endl
531 <<
" Error message: " << errorMsg << endl;
532 return KoFilter::ParsingError;
535 kdDebug(30519) <<
"File " << fileName <<
" loaded and parsed!" << endl;
541KoFilter::ConversionStatus OoUtils::loadAndParse(
const TQString& filename, TQDomDocument& doc, KZip * m_zip)
543 kdDebug(30519) <<
"Trying to open " << filename << endl;
547 kdError(30519) <<
"No ZIP file!" << endl;
548 return KoFilter::CreationError;
551 const KArchiveEntry* entry = m_zip->directory()->entry( filename );
554 kdWarning(30519) <<
"Entry " << filename <<
" not found!" << endl;
555 return KoFilter::FileNotFound;
557 if (entry->isDirectory())
559 kdWarning(30519) <<
"Entry " << filename <<
" is a directory!" << endl;
560 return KoFilter::WrongFormat;
562 const KZipFileEntry* f =
static_cast<const KZipFileEntry *
>(entry);
563 kdDebug(30519) <<
"Entry " << filename <<
" has size " << f->size() << endl;
564 TQIODevice* io = f->device();
565 KoFilter::ConversionStatus convertStatus = loadAndParse( io,doc, filename );
567 return convertStatus;
570KoFilter::ConversionStatus OoUtils::loadThumbnail( TQImage& thumbnail, KZip * m_zip )
572 const TQString filename(
"Thumbnails/thumbnail.png" );
573 kdDebug(30519) <<
"Trying to open thumbnail " << filename << endl;
577 kdError(30519) <<
"No ZIP file!" << endl;
578 return KoFilter::CreationError;
581 const KArchiveEntry* entry = m_zip->directory()->entry( filename );
584 kdWarning(30519) <<
"Entry " << filename <<
" not found!" << endl;
585 return KoFilter::FileNotFound;
587 if (entry->isDirectory())
589 kdWarning(30519) <<
"Entry " << filename <<
" is a directory!" << endl;
590 return KoFilter::WrongFormat;
592 const KZipFileEntry* f =
static_cast<const KZipFileEntry *
>(entry);
593 TQIODevice* io=f->device();
594 kdDebug(30519) <<
"Entry " << filename <<
" has size " << f->size() << endl;
596 if ( ! io->open( IO_ReadOnly ) )
598 kdWarning(30519) <<
"Thumbnail could not be opened!" <<endl;
600 return KoFilter::StupidError;
603 TQImageIO imageIO( io,
"PNG" );
604 if ( ! imageIO.read() )
606 kdWarning(30519) <<
"Thumbnail could not be read!" <<endl;
608 return KoFilter::StupidError;
613 thumbnail = imageIO.image();
615 if ( thumbnail.isNull() )
617 kdWarning(30519) <<
"Read thumbnail is null!" <<endl;
619 return KoFilter::StupidError;
624 kdDebug(30519) <<
"File " << filename <<
" loaded!" << endl;