// -*- Mode: c++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 4; -*- /* This file is part of the KDE project Copyright (C) 2002 Laurent Montel Copyright (c) 2003 Lukas Tinkl This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include "ooimpressimport.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include typedef KGenericFactory OoImpressImportFactory; K_EXPORT_COMPONENT_FACTORY( libooimpressimport, OoImpressImportFactory( "kofficefilters" ) ) OoImpressImport::OoImpressImport( KoFilter *, const char *, const TQStringList & ) : KoFilter(), m_numPicture( 1 ), m_numSound(1), m_styles( 23, true ), m_styleStack( ooNS::style, ooNS::fo ) { m_styles.setAutoDelete( true ); m_listStyles.setAutoDelete( true ); } OoImpressImport::~OoImpressImport() { TQDictIterator it( m_animations ); // See TQDictIterator for( ; it.current(); ++it ) { delete it.current()->element; } m_animations.clear(); } KoFilter::ConversiontqStatus OoImpressImport::convert( TQCString const & from, TQCString const & to ) { kdDebug(30518) << "Entering Ooimpress Import filter: " << from << " - " << to << endl; if ( (from != "application/vnd.sun.xml.impress" && from != "application/vnd.sun.xml.impress.template" ) || to != "application/x-kpresenter" ) { kdWarning(30518) << "Invalid mimetypes " << from << " " << to << endl; return KoFilter::NotImplemented; } m_zip = new KZip( m_chain->inputFile() ); if ( !m_zip->open( IO_ReadOnly ) ) { kdError(30518) << "Couldn't open the requested file "<< m_chain->inputFile() << endl; delete m_zip; return KoFilter::FileNotFound; } KoFilter::ConversiontqStatus pretqStatus = openFile(); if ( pretqStatus != KoFilter::OK ) { m_zip->close(); delete m_zip; return pretqStatus; } TQDomDocument docinfo; createDocumentInfo( docinfo ); // store document info KoStoreDevice* out = m_chain->storageFile( "documentinfo.xml", KoStore::Write ); if( out ) { TQCString info = docinfo.toCString(); //kdDebug(30518) << " info :" << info << endl; // WARNING: we cannot use KoStore::write(const TQByteArray&) because it gives an extra NULL character at the end. out->writeBlock( info , info.length() ); } TQDomDocument doccontent; createDocumentContent( doccontent ); // store document content out = m_chain->storageFile( "maindoc.xml", KoStore::Write ); if( out ) { TQCString content = doccontent.toCString(); kdDebug(30518) << " content :" << content << endl; out->writeBlock( content , content.length() ); } m_zip->close(); delete m_zip; kdDebug(30518) << "######################## OoImpressImport::convert done ####################" << endl; return KoFilter::OK; } // Very related to OoWriterImport::openFile() KoFilter::ConversiontqStatus OoImpressImport::openFile() { KoFilter::ConversiontqStatus status = loadAndParse( "content.xml", m_content ); if ( status != KoFilter::OK ) { kdError(30518) << "Content.xml could not be parsed correctly! Aborting!" << endl; return status; } // We do not stop if the following calls fail. TQDomDocument styles; loadAndParse( "styles.xml", styles ); loadAndParse( "meta.xml", m_meta ); loadAndParse( "settings.xml", m_settings ); emit sigProgress( 10 ); createStyleMap( styles ); return KoFilter::OK; } KoFilter::ConversiontqStatus OoImpressImport::loadAndParse(const TQString& filename, TQDomDocument& doc) { return OoUtils::loadAndParse( filename, doc, m_zip); } // Very related to OoWriterImport::createDocumentInfo void OoImpressImport::createDocumentInfo( TQDomDocument &docinfo ) { docinfo = KoDocument::createDomDocument( "document-info" /*DTD name*/, "document-info" /*tag name*/, "1.1" ); OoUtils::createDocumentInfo(m_meta, docinfo); //kdDebug(30518) << " meta-info :" << m_meta.toCString() << endl; } void OoImpressImport::createDocumentContent( TQDomDocument &doccontent ) { TQDomDocument doc = KoDocument::createDomDocument( "kpresenter", "DOC", "1.2" ); TQDomElement docElement = doc.documentElement(); docElement.setAttribute( "editor", "KPresenter" ); docElement.setAttribute( "mime", "application/x-kpresenter" ); docElement.setAttribute( "syntaxVersion", "2" ); TQDomElement content = m_content.documentElement(); // content.xml contains some automatic-styles that we need to store TQDomNode automaticStyles = KoDom::namedItemNS( content, ooNS::office, "automatic-styles" ); if ( !automaticStyles.isNull() ) insertStyles( automaticStyles.toElement() ); TQDomNode body = KoDom::namedItemNS( content, ooNS::office, "body" ); if ( body.isNull() ) return; TQDomElement customSlideShow = doc.createElement( "CUSTOMSLIDESHOWCONFIG" ); // presentation settings TQDomElement settings = KoDom::namedItemNS( body, ooNS::presentation, "settings"); if (!settings.isNull()) { if (settings.attributeNS( ooNS::presentation, "endless", TQString())=="true") { TQDomElement infElem = doc.createElement("INFINITLOOP"); infElem.setAttribute("value", 1); docElement.appendChild(infElem); } if (settings.attributeNS( ooNS::presentation, "show-end-of-presentation-slide", TQString())=="true") { TQDomElement infElem = doc.createElement("SHOWENDOFPRESENTATIONSLIDE"); infElem.setAttribute("value", 1); docElement.appendChild(infElem); } if (settings.attributeNS( ooNS::presentation, "force-manual", TQString())=="true") { TQDomElement manualElem = doc.createElement("MANUALSWITCH"); manualElem.setAttribute("value", 1); docElement.appendChild(manualElem); } if ( settings.hasAttributeNS( ooNS::presentation, "show") ) { TQDomElement defaultPage = doc.createElement("DEFAULTCUSTOMSLIDESHOWNAME"); defaultPage.setAttribute("name", settings.attributeNS( ooNS::presentation, "show", TQString()) ); docElement.appendChild(defaultPage); } } TQDomElement presentationShow; forEachElement( presentationShow, settings ) { if ( presentationShow.localName()=="show" && presentationShow.namespaceURI() == ooNS::presentation ) { if ( presentationShow.hasAttributeNS( ooNS::presentation, "pages") && presentationShow.hasAttributeNS( ooNS::presentation, "name")) { TQDomElement slide=doc.createElement("CUSTOMSLIDESHOW"); slide.setAttribute( "pages", presentationShow.attributeNS( ooNS::presentation, "pages", TQString() )); slide.setAttribute( "name", presentationShow.attributeNS( ooNS::presentation, "name", TQString() )); customSlideShow.appendChild( slide ); } } } // it seems that ooimpress has different paper-settings for every slide. // we take the settings of the first slide for the whole document. TQDomElement drawPage = KoDom::namedItemNS( body, ooNS::draw, "page" ); if ( drawPage.isNull() ) // no slides? give up. return; TQDomElement objectElement = doc.createElement( "OBJECTS" ); TQDomElement pictureElement = doc.createElement( "PICTURES" ); TQDomElement pageTitleElement = doc.createElement( "PAGETITLES" ); TQDomElement pageNoteElement = doc.createElement( "PAGENOTES" ); TQDomElement backgroundElement = doc.createElement( "BACKGROUND" ); TQDomElement soundElement = doc.createElement( "SOUNDS" ); TQDomElement selSlideElement = doc.createElement( "SELSLIDES" ); TQDomElement helpLineElement = doc.createElement( "HELPLINES" ); TQDomElement attributeElement = doc.createElement( "ATTRIBUTES" ); TQDomElement *master = m_styles[drawPage.attributeNS( ooNS::draw, "master-page-name", TQString() )]; appendObject(*master, doc, soundElement,pictureElement,pageNoteElement,objectElement, 0, true); TQDomElement *style = m_styles[master->attributeNS( ooNS::style, "page-master-name", TQString() )]; TQDomElement properties = KoDom::namedItemNS( *style, ooNS::style, "properties" ); //kdDebug(30518)<<" master->attribute( draw:style-name ) :"<attributeNS( ooNS::draw, "style-name", TQString() )<attributeNS( ooNS::draw, "style-name", TQString() ).isEmpty() ? "Standard-background" : master->attributeNS( ooNS::draw, "style-name", TQString() ) ]; //kdDebug(30518)<<" backgroundStyle :"<V7939H1139 //by default show line if ( !firstView.isNull() ) { TQString str = firstView.parseConfigItemString( "SnapLinesDrawing" ); if ( !str.isEmpty() ) { parseHelpLine( doc, helpLineElement, str ); //display it by default helpLineElement.setAttribute( "show", true ); foundElement = true; } int gridX = firstView.parseConfigItemInt( "GridFineWidth" ); int gridY = firstView.parseConfigItemInt( "GridFineHeight" ); bool snapToGrid = firstView.parseConfigItemBool( "IsSnapToGrid" ); int selectedPage = firstView.parseConfigItemInt( "SelectedPage" ); attributeElement.setAttribute( "activePage", selectedPage ); attributeElement.setAttribute( "gridx", MM_TO_POINT( gridX / 100.0 ) ); attributeElement.setAttribute( "gridy", MM_TO_POINT( gridY / 100.0 ) ); attributeElement.setAttribute( "snaptogrid", (int)snapToGrid ); } //kdDebug(30518)<<" gridX :"<=0;--pos ) { if ( text[pos]=='P' ) { //point str = text.mid( pos+1, ( newPos-pos ) ); TQDomElement point=doc.createElement("HelpPoint"); //kdDebug(30518)<<" point element :"<< str < x2 && y1 > y2 ) ) linetype.setAttribute( "value", 2 ); else linetype.setAttribute( "value", 3 ); e.appendChild( linetype ); return (x1 < x2); } void OoImpressImport::appendPen( TQDomDocument& doc, TQDomElement& e ) { if ( m_styleStack.hasAttributeNS( ooNS::draw, "stroke" )) { TQDomElement pen = doc.createElement( "PEN" ); if ( m_styleStack.attributeNS( ooNS::draw, "stroke" ) == "none" ) pen.setAttribute( "style", 0 ); else if ( m_styleStack.attributeNS( ooNS::draw, "stroke" ) == "solid" ) pen.setAttribute( "style", 1 ); else if ( m_styleStack.attributeNS( ooNS::draw, "stroke" ) == "dash" ) { TQString style = m_styleStack.attributeNS( ooNS::draw, "stroke-dash" ); if ( style == "Ultrafine Dashed" || style == "Fine Dashed" || style == "Fine Dashed (var)" || style == "Dashed (var)" ) pen.setAttribute( "style", 2 ); else if ( style == "Fine Dotted" || style == "Ultrafine Dotted (var)" || style == "Line with Fine Dots" ) pen.setAttribute( "style", 3 ); else if ( style == "3 Dashes 3 Dots (var)" || style == "Ultrafine 2 Dots 3 Dashes" ) pen.setAttribute( "style", 4 ); else if ( style == "2 Dots 1 Dash" ) pen.setAttribute( "style", 5 ); } if ( m_styleStack.hasAttributeNS( ooNS::svg, "stroke-width" ) ) pen.setAttribute( "width", (int) KoUnit::parseValue( m_styleStack.attributeNS( ooNS::svg, "stroke-width" ) ) ); if ( m_styleStack.hasAttributeNS( ooNS::svg, "stroke-color" ) ) pen.setAttribute( "color", m_styleStack.attributeNS( ooNS::svg, "stroke-color" ) ); e.appendChild( pen ); } } void OoImpressImport::appendBrush( TQDomDocument& doc, TQDomElement& e ) { if ( m_styleStack.hasAttributeNS( ooNS::draw, "fill" ) ) { const TQString fill = m_styleStack.attributeNS( ooNS::draw, "fill" ); //kdDebug(30518)<<"void OoImpressImport::appendBrush( TQDomDocument& doc, TQDomElement& e ) :"<= 94 && value <= 99 ) { brush.setAttribute( "style", 2 ); } else if ( value>=64 && value <= 93 ) { brush.setAttribute( "style", 3 ); } else if ( value>=51 && value <= 63 ) { brush.setAttribute( "style", 4 ); } else if ( value>=38 && value <= 50 ) { brush.setAttribute( "style", 5 ); } else if ( value>=13 && value <= 37 ) { brush.setAttribute( "style", 6 ); } else if ( value>=7 && value <= 12 ) { brush.setAttribute( "style", 7 ); } else if ( value>=1 && value <= 6 ) { brush.setAttribute( "style", 8 ); } } else brush.setAttribute( "style", 1 ); if ( m_styleStack.hasAttributeNS( ooNS::draw, "fill-color" ) ) brush.setAttribute( "color", m_styleStack.attributeNS( ooNS::draw, "fill-color" ) ); e.appendChild( brush ); } else if ( fill == "hatch" ) { TQDomElement brush = doc.createElement( "BRUSH" ); TQString style = m_styleStack.attributeNS( ooNS::draw, "fill-hatch-name" ); TQDomElement* draw = m_draws[style]; if ( draw ) { if( draw->hasAttributeNS( ooNS::draw, "color" ) ) brush.setAttribute( "color", draw->attributeNS( ooNS::draw, "color", TQString() ) ); int angle = 0; if( draw->hasAttributeNS( ooNS::draw, "rotation" )) { angle = (draw->attributeNS( ooNS::draw, "rotation", TQString() ).toInt())/10; kdDebug(30518)<<"angle :"<hasAttributeNS( ooNS::draw, "style" )) { TQString styleHash = draw->attributeNS( ooNS::draw, "style", TQString() ); if( styleHash == "single") { switch( angle ) { case 0: case 180: brush.setAttribute( "style", 9 ); break; case 45: case 225: brush.setAttribute( "style", 12 ); break; case 90: case 270: brush.setAttribute( "style", 10 ); break; case 135: case 315: brush.setAttribute( "style", 13 ); break; default: //todo fixme when we will have a kopaint kdDebug(30518)<<" draw:rotation 'angle' : "<attributeNS( ooNS::draw, "start-color", TQString() ) ); gradient.setAttribute( "color2", draw->attributeNS( ooNS::draw, "end-color", TQString() ) ); TQString type = draw->attributeNS( ooNS::draw, "style", TQString() ); //kdDebug(30518)<<" type !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! :"<attributeNS( ooNS::draw, "angle", TQString() ).toInt() / 10; // make sure the angle is between 0 and 359 angle = abs( angle ); angle -= ( (int) ( angle / 360 ) ) * 360; // What we are trying to do here is to find out if the given // angle belongs to a horizontal, vertical or diagonal gradient. int lower, upper, nearAngle = 0; for ( lower = 0, upper = 45; upper < 360; lower += 45, upper += 45 ) { if ( upper >= angle ) { int distanceToUpper = abs( angle - upper ); int distanceToLower = abs( angle - lower ); nearAngle = distanceToUpper > distanceToLower ? lower : upper; break; } } kdDebug(30518)<<"nearAngle :"<hasAttributeNS( ooNS::draw, "cx" ) ) x = draw->attributeNS( ooNS::draw, "cx", TQString() ).remove( '%' ).toInt(); else x = 50; if ( draw->hasAttributeNS( ooNS::draw, "cy" ) ) y = draw->attributeNS( ooNS::draw, "cy", TQString() ).remove( '%' ).toInt(); else y = 50; if ( x == 50 && y == 50 ) { gradient.setAttribute( "unbalanced", 0 ); gradient.setAttribute( "xfactor", 100 ); gradient.setAttribute( "yfactor", 100 ); } else { gradient.setAttribute( "unbalanced", 1 ); // map 0 - 100% to -200 - 200 gradient.setAttribute( "xfactor", 4 * x - 200 ); gradient.setAttribute( "yfactor", 4 * y - 200 ); } } e.appendChild( gradient ); TQDomElement fillType = doc.createElement( "FILLTYPE" ); fillType.setAttribute( "value", 1 ); e.appendChild( fillType ); } } } void OoImpressImport::appendPie( TQDomDocument& doc, TQDomElement& e, const TQDomElement& object ) { TQDomElement angle = doc.createElement( "PIEANGLE" ); int start = (int) ( object.attributeNS( ooNS::draw, "start-angle", TQString() ).toDouble() ); angle.setAttribute( "value", start * 16 ); e.appendChild( angle ); TQDomElement length = doc.createElement( "PIELENGTH" ); int end = (int) ( object.attributeNS( ooNS::draw, "end-angle", TQString() ).toDouble() ); if ( end < start ) length.setAttribute( "value", ( 360 - start + end ) * 16 ); else length.setAttribute( "value", ( end - start ) * 16 ); e.appendChild( length ); } void OoImpressImport::appendImage( TQDomDocument& doc, TQDomElement& e, TQDomElement& p, const TQDomElement& object ) { TQString fileName = storeImage( object ); // create a key for the picture TQTime time = TQTime::currentTime(); TQDate date = TQDate::tqcurrentDate(); TQDomElement image = doc.createElement( "KEY" ); image.setAttribute( "msec", time.msec() ); image.setAttribute( "second", time.second() ); image.setAttribute( "minute", time.minute() ); image.setAttribute( "hour", time.hour() ); image.setAttribute( "day", date.day() ); image.setAttribute( "month", date.month() ); image.setAttribute( "year", date.year() ); image.setAttribute( "filename", fileName ); e.appendChild( image ); TQDomElement settings = doc.createElement( "PICTURESETTINGS" ); if ( m_styleStack.hasAttributeNS( ooNS::draw, "color-mode" ) && ( m_styleStack.attributeNS( ooNS::draw, "color-mode" )=="greyscale" ) ) settings.setAttribute( "grayscal", 1 ); else settings.setAttribute( "grayscal", 0 ); if ( m_styleStack.hasAttributeNS( ooNS::draw, "luminance" ) ) { TQString str( m_styleStack.attributeNS( ooNS::draw, "luminance" ) ); str = str.remove( '%' ); settings.setAttribute( "bright", str ); } else settings.setAttribute( "bright", 0 ); settings.setAttribute( "mirrorType", 0 ); settings.setAttribute( "swapRGB", 0 ); settings.setAttribute( "depth", 0 ); e.appendChild( settings ); TQDomElement effects = doc.createElement( "EFFECTS" ); bool hasEffect = false; if ( m_styleStack.hasAttributeNS( ooNS::draw, "contrast" ) ) { TQString str( m_styleStack.attributeNS( ooNS::draw, "contrast" ) ); str = str.remove( '%' ); int val = str.toInt(); val = ( int )( 255.0 *val/100.0 ); effects.setAttribute( "type", "5" ); effects.setAttribute( "param1", TQString::number( val ) ); hasEffect = true; } if ( hasEffect ) e.appendChild( effects ); TQDomElement key = image.cloneNode().toElement(); key.setAttribute( "name", "pictures/" + fileName ); p.appendChild( key ); } void OoImpressImport::appendBackgroundImage( TQDomDocument& doc, TQDomElement& e, TQDomElement& p, const TQDomElement& object ) { TQString fileName = storeImage( object ); // create a key for the picture TQTime time = TQTime::currentTime(); TQDate date = TQDate::tqcurrentDate(); TQDomElement image = doc.createElement( "BACKPICTUREKEY" ); image.setAttribute( "msec", time.msec() ); image.setAttribute( "second", time.second() ); image.setAttribute( "minute", time.minute() ); image.setAttribute( "hour", time.hour() ); image.setAttribute( "day", date.day() ); image.setAttribute( "month", date.month() ); image.setAttribute( "year", date.year() ); image.setAttribute( "filename", fileName ); e.appendChild( image ); TQDomElement key = image.cloneNode().toElement(); key.setTagName( "KEY" ); key.setAttribute( "name", "pictures/" + fileName ); p.appendChild( key ); } void OoImpressImport::appendBackgroundGradient( TQDomDocument& doc, TQDomElement& e, const TQDomElement& object ) { TQDomElement backColor1 = doc.createElement( "BACKCOLOR1" ); backColor1.setAttribute( "color", object.attributeNS( ooNS::draw, "start-color", TQString() ) ); e.appendChild( backColor1 ); TQDomElement backColor2 = doc.createElement( "BACKCOLOR2" ); backColor2.setAttribute( "color", object.attributeNS( ooNS::draw, "end-color", TQString() ) ); e.appendChild( backColor2 ); TQDomElement backType = doc.createElement( "BACKTYPE" ); backType.setAttribute( "value", 0 ); // color/gradient e.appendChild( backType ); TQDomElement bcType = doc.createElement( "BCTYPE" ); TQString type = object.attributeNS( ooNS::draw, "style", TQString() ); if ( type == "linear" ) { int angle = object.attributeNS( ooNS::draw, "angle", TQString() ).toInt() / 10; // make sure the angle is between 0 and 359 angle = abs( angle ); angle -= ( (int) ( angle / 360 ) ) * 360; // What we are trying to do here is to find out if the given // angle belongs to a horizontal, vertical or diagonal gradient. int lower, upper, nearAngle = 0; for ( lower = 0, upper = 45; upper < 360; lower += 45, upper += 45 ) { if ( upper >= angle ) { int distanceToUpper = abs( angle - upper ); int distanceToLower = abs( angle - lower ); nearAngle = distanceToUpper > distanceToLower ? lower : upper; break; } } // nearAngle should now be one of: 0, 45, 90, 135, 180... if ( nearAngle == 0 || nearAngle == 180 ) bcType.setAttribute( "value", 1 ); // horizontal else if ( nearAngle == 90 || nearAngle == 270 ) bcType.setAttribute( "value", 2 ); // vertical else if ( nearAngle == 45 || nearAngle == 225 ) bcType.setAttribute( "value", 3 ); // diagonal 1 else if ( nearAngle == 135 || nearAngle == 315 ) bcType.setAttribute( "value", 4 ); // diagonal 2 } else if ( type == "radial" || type == "ellipsoid" ) bcType.setAttribute( "value", 5 ); // circle else if ( type == "square" || type == "rectangular" ) bcType.setAttribute( "value", 6 ); // rectangle else if ( type == "axial" ) bcType.setAttribute( "value", 7 ); // pipecross e.appendChild( bcType ); TQDomElement bGradient = doc.createElement( "BGRADIENT" ); // Hard to map between x- and y-center settings of ooimpress // and (un-)balanced settings of kpresenter. Let's try it. int x, y; if ( object.hasAttributeNS( ooNS::draw, "cx" ) ) x = object.attributeNS( ooNS::draw, "cx", TQString() ).remove( '%' ).toInt(); else x = 50; if ( object.hasAttributeNS( ooNS::draw, "cy" ) ) y = object.attributeNS( ooNS::draw, "cy", TQString() ).remove( '%' ).toInt(); else y = 50; if ( x == 50 && y == 50 ) { bGradient.setAttribute( "unbalanced", 0 ); bGradient.setAttribute( "xfactor", 100 ); bGradient.setAttribute( "yfactor", 100 ); } else { bGradient.setAttribute( "unbalanced", 1 ); // map 0 - 100% to -200 - 200 bGradient.setAttribute( "xfactor", 4 * x - 200 ); bGradient.setAttribute( "yfactor", 4 * y - 200 ); } e.appendChild( bGradient ); } void OoImpressImport::appendRounding( TQDomDocument& doc, TQDomElement& e, const TQDomElement& object ) { if ( object.hasAttributeNS( ooNS::draw, "corner-radius" ) ) { // kpresenter uses percent, ooimpress uses cm ... hmm? TQDomElement rounding = doc.createElement( "RNDS" ); int corner = static_cast(KoUnit::parseValue(object.attributeNS( ooNS::draw, "corner-radius", TQString()))); rounding.setAttribute( "x", corner ); rounding.setAttribute( "y", corner ); e.appendChild( rounding ); } } void OoImpressImport::appendShadow( TQDomDocument& doc, TQDomElement& e ) { // Note that ooimpress makes a difference between shadowed text and // a shadowed object while kpresenter only knows the attribute 'shadow'. // This means that a shadowed textobject in kpresenter will always show // a shadowed text but no shadow for the object itself. // make sure this is a textobject or textspan if ( !e.hasAttribute( "type" ) || ( e.hasAttribute( "type" ) && e.attribute( "type" ) == "4" ) ) { if ( m_styleStack.hasAttributeNS( ooNS::fo, "text-shadow" ) && m_styleStack.attributeNS( ooNS::fo, "text-shadow" ) != "none" ) { // use the shadow attribute to indicate a text-shadow TQDomElement shadow = doc.createElement( "SHADOW" ); TQString distance = m_styleStack.attributeNS( ooNS::fo, "text-shadow" ); distance.truncate( distance.tqfind( ' ' ) ); shadow.setAttribute( "distance", KoUnit::parseValue( distance ) ); shadow.setAttribute( "direction", 5 ); shadow.setAttribute( "color", "#a0a0a0" ); e.appendChild( shadow ); } } else if ( m_styleStack.hasAttributeNS( ooNS::draw, "shadow" ) && m_styleStack.attributeNS( ooNS::draw, "shadow" ) == "visible" ) { // use the shadow attribute to indicate an object-shadow TQDomElement shadow = doc.createElement( "SHADOW" ); double x = KoUnit::parseValue( m_styleStack.attributeNS( ooNS::draw, "shadow-offset-x" ) ); double y = KoUnit::parseValue( m_styleStack.attributeNS( ooNS::draw, "shadow-offset-y" ) ); if ( x < 0 && y < 0 ) { shadow.setAttribute( "direction", 1 ); shadow.setAttribute( "distance", (int) fabs ( x ) ); } else if ( x == 0 && y < 0 ) { shadow.setAttribute( "direction", 2 ); shadow.setAttribute( "distance", (int) fabs ( y ) ); } else if ( x > 0 && y < 0 ) { shadow.setAttribute( "direction", 3 ); shadow.setAttribute( "distance", (int) fabs ( x ) ); } else if ( x > 0 && y == 0 ) { shadow.setAttribute( "direction", 4 ); shadow.setAttribute( "distance", (int) fabs ( x ) ); } else if ( x > 0 && y > 0 ) { shadow.setAttribute( "direction", 5 ); shadow.setAttribute( "distance", (int) fabs ( x ) ); } else if ( x == 0 && y > 0 ) { shadow.setAttribute( "direction", 6 ); shadow.setAttribute( "distance", (int) fabs ( y ) ); } else if ( x < 0 && y > 0 ) { shadow.setAttribute( "direction", 7 ); shadow.setAttribute( "distance", (int) fabs ( x ) ); } else if ( x < 0 && y == 0 ) { shadow.setAttribute( "direction", 8 ); shadow.setAttribute( "distance", (int) fabs ( x ) ); } if ( m_styleStack.hasAttributeNS( ooNS::draw, "shadow-color" ) ) shadow.setAttribute( "color", m_styleStack.attributeNS( ooNS::draw, "shadow-color" ) ); e.appendChild( shadow ); } if ( m_styleStack.hasAttributeNS( ooNS::draw, "size-protect" ) || m_styleStack.hasAttributeNS( ooNS::draw, "move-protect" ) ) { bool b = ( m_styleStack.attributeNS( ooNS::draw, "size-protect" ) == "true" ) || ( m_styleStack.attributeNS( ooNS::draw, "move-protect" ) == "true" ); if ( b ) { TQDomElement protect = doc.createElement( "PROTECT" ); protect.setAttribute("state" , b); e.appendChild(protect); } } } void OoImpressImport::appendLineEnds( TQDomDocument& doc, TQDomElement& e, bool orderEndStartLine) { const char* attr = orderEndStartLine ? "marker-start" : "marker-end"; if ( m_styleStack.hasAttributeNS( ooNS::draw, attr ) ) { TQDomElement lineBegin = doc.createElement( "LINEBEGIN" ); TQString type = m_styleStack.attributeNS( ooNS::draw, attr ); if ( type == "Arrow" || type == "Small Arrow" || type == "Rounded short Arrow" || type == "Symmetric Arrow" || type == "Rounded large Arrow" || type == "Arrow concave" ) lineBegin.setAttribute( "value", 1 ); else if ( type == "Square" ) lineBegin.setAttribute( "value", 2 ); else if ( type == "Circle" || type == "Square 45" ) lineBegin.setAttribute( "value", 3 ); else if ( type == "Line Arrow" ) lineBegin.setAttribute( "value", 4 ); else if ( type == "Dimension Lines" ) lineBegin.setAttribute( "value", 5 ); else if ( type == "Double Arrow" ) lineBegin.setAttribute( "value", 6 ); e.appendChild( lineBegin ); } attr = orderEndStartLine ? "marker-end" : "marker-start"; if ( m_styleStack.hasAttributeNS( ooNS::draw, attr ) ) { TQDomElement lineEnd = doc.createElement( "LINEEND" ); TQString type = m_styleStack.attributeNS( ooNS::draw, attr ); if ( type == "Arrow" || type == "Small Arrow" || type == "Rounded short Arrow" || type == "Symmetric Arrow" || type == "Rounded large Arrow" || type == "Arrow concave" ) lineEnd.setAttribute( "value", 1 ); else if ( type == "Square" ) lineEnd.setAttribute( "value", 2 ); else if ( type == "Circle" || type == "Square 45" ) lineEnd.setAttribute( "value", 3 ); else if ( type == "Line Arrow" ) lineEnd.setAttribute( "value", 4 ); else if ( type == "Dimension Lines" ) lineEnd.setAttribute( "value", 5 ); else if ( type == "Double Arrow" ) lineEnd.setAttribute( "value", 6 ); e.appendChild( lineEnd ); } } void OoImpressImport::appendTextObjectMargin( TQDomDocument& /*doc*/, TQDomElement& e ) { if ( m_styleStack.hasAttributeNS( ooNS::fo, "padding" ) ) { double tmpValue = KoUnit::parseValue(m_styleStack.attributeNS( ooNS::fo, "padding" ) ); e.setAttribute( "btoppt", tmpValue ); e.setAttribute( "bbottompt", tmpValue ); e.setAttribute( "bleftpt", tmpValue ); e.setAttribute( "brightpt", tmpValue ); } else { if( m_styleStack.hasAttributeNS( ooNS::fo, "padding-top" ) ) e.setAttribute( "btoppt", KoUnit::parseValue( m_styleStack.attributeNS( ooNS::fo, "padding-top" ) ) ); if( m_styleStack.hasAttributeNS( ooNS::fo, "padding-bottom" ) ) e.setAttribute( "bbottompt", KoUnit::parseValue( m_styleStack.attributeNS( ooNS::fo, "padding-bottom" ) ) ); if( m_styleStack.hasAttributeNS( ooNS::fo, "padding-left" ) ) e.setAttribute( "bleftpt", KoUnit::parseValue( m_styleStack.attributeNS( ooNS::fo, "padding-left" ) ) ); if( m_styleStack.hasAttributeNS( ooNS::fo, "padding-right" ) ) e.setAttribute( "brightpt", KoUnit::parseValue( m_styleStack.attributeNS( ooNS::fo, "padding-right" ) ) ); } } TQDomElement OoImpressImport::parseTextBox( TQDomDocument& doc, const TQDomElement& textBox ) { TQDomElement textObjectElement = doc.createElement( "TEXTOBJ" ); appendTextObjectMargin( doc, textObjectElement ); // vertical tqalignment if ( m_styleStack.hasAttributeNS( ooNS::draw, "textarea-vertical-align" ) ) { TQString tqalignment = m_styleStack.attributeNS( ooNS::draw, "textarea-vertical-align" ); if ( tqalignment == "top" ) textObjectElement.setAttribute( "verticalAlign", "top" ); else if ( tqalignment == "middle" ) textObjectElement.setAttribute( "verticalAlign", "center" ); else if ( tqalignment == "bottom" ) textObjectElement.setAttribute( "verticalAlign", "bottom" ); textObjectElement.setAttribute("verticalValue", 0.0); } parseParagraphs( doc, textObjectElement, textBox ); return textObjectElement; } void OoImpressImport::parseParagraphs( TQDomDocument& doc, TQDomElement& textObjectElement, const TQDomElement& tqparent ) { TQDomElement t; forEachElement( t, tqparent ) { m_styleStack.save(); const TQString localName = t.localName(); const TQString ns = t.namespaceURI(); const bool isTextNS = ns == ooNS::text; TQDomElement e; if ( isTextNS && localName == "p" ) // text paragraph e = parseParagraph( doc, t ); else if ( isTextNS && localName == "h" ) // heading - can this happen in ooimpress? { e = parseParagraph( doc, t ); } else if ( isTextNS && ( localName == "unordered-list" || localName == "ordered-list" ) ) { parseList( doc, textObjectElement, t ); m_styleStack.restore(); continue; } // TODO text:sequence-decls else { kdDebug(30518) << "Unsupported texttype '" << localName << "'" << endl; } if ( !e.isNull() ) textObjectElement.appendChild( e ); m_styleStack.restore(); // remove the styles added by the paragraph or list } } void OoImpressImport::applyListStyle( TQDomElement& paragraph ) { // Spec: see 3.3.5 p137 if ( m_listStyleStack.hasListStyle() && m_nextItemIsListItem ) { //const TQDomElement listStyle = m_listStyleStack.currentListStyle(); //bool heading = paragraph.localName() == "h"; m_nextItemIsListItem = false; /*int level = heading ? paragraph.attributeNS( ooNS::text, "level", TQString() ).toInt() : m_listStyleStack.level();*/ TQDomElement counter = paragraph.ownerDocument().createElement( "COUNTER" ); counter.setAttribute( "numberingtype", 0 ); counter.setAttribute( "depth", 0 ); if ( m_insideOrderedList ) counter.setAttribute( "type", 1 ); else counter.setAttribute( "type", 10 ); // a disc bullet paragraph.appendChild( counter ); } } static TQDomElement findListLevelStyle( TQDomElement& fullListStyle, int level ) { TQDomElement listLevelItem; forEachElement( listLevelItem, fullListStyle ) { if ( listLevelItem.attributeNS( ooNS::text, "level", TQString() ).toInt() == level ) return listLevelItem; } return TQDomElement(); } bool OoImpressImport::pushListLevelStyle( const TQString& listStyleName, int level ) { TQDomElement* fullListStyle = m_listStyles[listStyleName]; if ( !fullListStyle ) { kdWarning(30518) << "List style " << listStyleName << " not found!" << endl; return false; } else return pushListLevelStyle( listStyleName, *fullListStyle, level ); } bool OoImpressImport::pushListLevelStyle( const TQString& listStyleName, // for debug only TQDomElement& fullListStyle, int level ) { // Find applicable list-level-style for level int i = level; TQDomElement listLevelStyle; while ( i > 0 && listLevelStyle.isNull() ) { listLevelStyle = findListLevelStyle( fullListStyle, i ); --i; } if ( listLevelStyle.isNull() ) { kdWarning(30518) << "List level style for level " << level << " in list style " << listStyleName << " not found!" << endl; return false; } kdDebug(30518) << "Pushing list-level-style from list-style " << listStyleName << " level " << level << endl; m_listStyleStack.push( listLevelStyle ); return true; } void OoImpressImport::parseList( TQDomDocument& doc, TQDomElement& textObjectElement, const TQDomElement& list ) { //kdDebug(30518) << k_funcinfo << "parseList"<< endl; m_insideOrderedList = ( list.localName() == "ordered-list" ); TQString oldListStyleName = m_currentListStyleName; if ( list.hasAttributeNS( ooNS::text, "style-name" ) ) m_currentListStyleName = list.attributeNS( ooNS::text, "style-name", TQString() ); bool listOK = !m_currentListStyleName.isEmpty(); const int level = m_listStyleStack.level() + 1; //kdDebug(30518) << k_funcinfo << " listOK=" << listOK << " level=" << level << endl; if ( listOK ) listOK = pushListLevelStyle( m_currentListStyleName, level ); // Iterate over list items TQDomElement listItem; forEachElement( listItem, list ) { // It's either list-header (normal text on top of list) or list-item m_nextItemIsListItem = ( listItem.localName() != "list-header" ); m_restartNumbering = -1; if ( listItem.hasAttributeNS( ooNS::text, "start-value" ) ) m_restartNumbering = listItem.attributeNS( ooNS::text, "start-value", TQString() ).toInt(); // ### Oasis: can be p h or list only. parseParagraphs( doc, textObjectElement, listItem ); m_restartNumbering = -1; } if ( listOK ) m_listStyleStack.pop(); m_currentListStyleName = oldListStyleName; } TQDomElement OoImpressImport::parseParagraph( TQDomDocument& doc, const TQDomElement& paragraph ) { TQDomElement p = doc.createElement( "P" ); // parse the paragraph-properties fillStyleStack( paragraph ); // Style name TQString styleName = m_styleStack.userStyleName("paragraph"); if ( !styleName.isEmpty() ) { TQDomElement nameElem = doc.createElement("NAME"); nameElem.setAttribute("value", styleName); p.appendChild(nameElem); } // Paragraph tqalignment if ( m_styleStack.hasAttributeNS( ooNS::fo, "text-align" ) ) { TQString align = m_styleStack.attributeNS( ooNS::fo, "text-align" ); if ( align == "center" ) p.setAttribute( "align", 4 ); else if ( align == "justify" ) p.setAttribute( "align", 8 ); else if ( align == "start" ) p.setAttribute( "align", 0 ); else if ( align == "end" ) p.setAttribute( "align", 2 ); } else p.setAttribute( "align", 0 ); // use left aligned as default // Offset before and after paragraph OoUtils::importTopBottomMargin( p, m_styleStack ); // Indentation (margins) OoUtils::importIndents( p, m_styleStack ); // Line spacing OoUtils::importLineSpacing( p, m_styleStack ); // Tabulators OoUtils::importTabulators( p, m_styleStack ); // Borders OoUtils::importBorders( p, m_styleStack ); applyListStyle( p ); uint pos = 0; m_styleStack.save(); // parse every childnode of the paragraph parseSpanOrSimilar( doc, paragraph, p, pos); m_styleStack.restore(); // remove possible garbage (should not be needed) return p; } void OoImpressImport::parseSpanOrSimilar( TQDomDocument& doc, const TQDomElement& tqparent, TQDomElement& outputParagraph, uint& pos) { // Parse every child node of the tqparent // Can't use forEachElement here since we also care about text nodes for( TQDomNode node = tqparent.firstChild(); !node.isNull(); node = node.nextSibling() ) { TQDomElement ts = node.toElement(); TQString textData; const TQString localName( ts.localName() ); const TQString ns = ts.namespaceURI(); const bool isTextNS = ns == ooNS::text; TQDomText t = node.toText(); // Try to keep the order of the tag names by probability of happening if ( isTextNS && localName == "span" ) // text:span { m_styleStack.save(); fillStyleStack( ts ); parseSpanOrSimilar( doc, ts, outputParagraph, pos); m_styleStack.restore(); } else if ( isTextNS && localName == "s" ) // text:s { textData = OoUtils::expandWhitespace(ts); } else if ( isTextNS && localName == "tab-stop" ) // text:tab-stop { // KPresenter currently uses \t. // Known bug: a line with only \t\t\t\t isn't loaded - XML (TQDom) strips out whitespace. // One more good reason to switch to instead... textData = '\t'; } else if ( isTextNS && localName == "line-break" ) { textData = '\n'; } else if ( localName == "image" && ns == ooNS::draw ) { textData = '#'; // anchor placeholder // TODO } else if ( isTextNS && localName == "a" ) { m_styleStack.save(); TQString href( ts.attributeNS( ooNS::xlink, "href", TQString()) ); if ( href.startsWith("#") ) { // We have a reference to a bookmark (### TODO) // As we do not support it now, treat it as a without formatting parseSpanOrSimilar( doc, ts, outputParagraph, pos); } else { #if 0 // TODO // The problem is that KPresenter's hyperlink text is not inside the normal text, but for OOWriter it is nearly a // So we have to fake. TQDomElement fakeParagraph, fakeFormats; uint fakePos=0; TQString text; parseSpanOrSimilar( doc, ts, fakeParagraph, fakeFormats, text, fakePos); textData = '#'; // hyperlink placeholder TQDomElement linkElement (doc.createElement("LINK")); linkElement.setAttribute("hrefName",ts.attributeNS( ooNS::xlink, "href", TQString())); linkElement.setAttribute("linkName",text); appendVariable(doc, ts, pos, "STRING", 9, text, linkElement); #endif } m_styleStack.restore(); } else if ( isTextNS && (localName == "date" // fields || localName == "time" || localName == "page-number" || localName == "file-name" || localName == "author-name" || localName == "author-initials" ) ) { textData = "#"; // field placeholder appendField(doc, outputParagraph, ts, pos); } else if ( t.isNull() ) // no textnode, we must ignore { kdWarning(30518) << "Ignoring tag " << ts.tagName() << endl; continue; } else textData = t.data(); pos += textData.length(); TQDomElement text = saveHelper(textData, doc); kdDebug(30518) << k_funcinfo << "Para text is: " << textData << endl; if (m_styleStack.hasAttributeNS( ooNS::fo, "language" )) { TQString lang = m_styleStack.attributeNS( ooNS::fo, "language" ); if (lang=="en") text.setAttribute("language", "en_US"); else text.setAttribute("language", lang); } // parse the text-properties if ( m_styleStack.hasAttributeNS( ooNS::fo, "color" ) ) { kdDebug(30518) << "color=" << m_styleStack.attributeNS( ooNS::fo, "color" ) << endl; text.setAttribute( "color", m_styleStack.attributeNS( ooNS::fo, "color" ) ); } if ( m_styleStack.hasAttributeNS( ooNS::fo, "font-family" ) // 3.10.9 || m_styleStack.hasAttributeNS( ooNS::style, "font-name") )//3.10.8 { // 'Thorndale/Albany' are not known outside OpenOffice so we substitute them // with 'Times New Roman/Arial' that look nearly the same. if ( m_styleStack.attributeNS( ooNS::fo, "font-family" ) == "Thorndale" ) text.setAttribute( "family", "Times New Roman" ); else if ( m_styleStack.attributeNS( ooNS::fo, "font-family" ) == "Albany" ) text.setAttribute( "family", "Arial" ); else text.setAttribute( "family", m_styleStack.attributeNS( ooNS::fo, "font-family" ).remove( "'" ) ); } if ( m_styleStack.hasAttributeNS( ooNS::fo, "font-size" ) ) { double pointSize = m_styleStack.fontSize(); text.setAttribute( "pointSize", tqRound(pointSize) ); // KPresenter uses toInt()! } if ( m_styleStack.hasAttributeNS( ooNS::fo, "font-weight" ) ) // 3.10.24 if ( m_styleStack.attributeNS( ooNS::fo, "font-weight" ) == "bold" ) text.setAttribute( "bold", 1 ); if ( m_styleStack.hasAttributeNS( ooNS::fo, "font-style" ) ) if ( m_styleStack.attributeNS( ooNS::fo, "font-style" ) == "italic" ) text.setAttribute( "italic", 1 ); if ( m_styleStack.hasAttributeNS( ooNS::style, "text-position" ) ) // 3.10.17 { TQString text_position = m_styleStack.attributeNS( ooNS::style, "text-position"); TQString value; TQString relativetextsize; OoUtils::importTextPosition( text_position, value, relativetextsize ); text.setAttribute( "VERTALIGN", value ); if ( !relativetextsize.isEmpty() ) text.setAttribute( "relativetextsize", relativetextsize ); } bool wordByWord = (m_styleStack.hasAttributeNS( ooNS::fo, "score-spaces"))// 3.10.25 && (m_styleStack.attributeNS( ooNS::fo, "score-spaces") == "false"); // strikeout if ( m_styleStack.hasAttributeNS( ooNS::style, "text-crossing-out")// 3.10.6 && m_styleStack.attributeNS( ooNS::style, "text-crossing-out") != "none") { TQString strikeOutType = m_styleStack.attributeNS( ooNS::style, "text-crossing-out" ); if ( strikeOutType =="double-line" ) { text.setAttribute( "strikeOut", "double" ); text.setAttribute( "strikeoutstyleline", "solid" ); } else if ( strikeOutType =="thick-line" ) { text.setAttribute( "strikeOut", "single-bold" ); text.setAttribute( "strikeoutstyleline", "solid" ); } else //if ( strikeOutType == "single-line" ) //fall back to the default strikeout { text.setAttribute( "strikeOut", "single" ); text.setAttribute( "strikeoutstyleline", "solid" ); } if (wordByWord) text.setAttribute("wordbyword", 1); } // underlining if ( m_styleStack.hasAttributeNS( ooNS::style, "text-underline" ) ) // 3.10.22 { TQString underline; TQString styleline; OoUtils::importUnderline( m_styleStack.attributeNS( ooNS::style, "text-underline" ), underline, styleline ); TQString underLineColor = m_styleStack.attributeNS( ooNS::style, "text-underline-color" );// 3.10.23 text.setAttribute( "value", underline ); text.setAttribute( "styleline", styleline ); if ( !underLineColor.isEmpty() && underLineColor != "font-color" ) text.setAttribute("underlinecolor", underLineColor); if ( wordByWord ) text.setAttribute("wordbyword", 1); } #if 0 // strange ooimpress doesn't implement it // Small caps, lowercase, uppercase if ( m_styleStack.hasAttributeNS( ooNS::fo, "font-variant" ) // 3.10.1 || m_styleStack.hasAttributeNS( ooNS::fo, "text-transform" ) ) // 3.10.2 { TQDomElement fontAttrib( doc.createElement( "FONTATTRIBUTE" ) ); bool smallCaps = m_styleStack.attributeNS( ooNS::fo, "font-variant" ) == "small-caps"; if ( smallCaps ) { text.setAttribute( "fontattribute", "smallcaps" ); } else { // Both KWord/KPresenter and OO use "uppercase" and "lowercase". // TODO in KWord: "capitalize". text.setAttribute( "fontattribute", m_styleStack.attributeNS( ooNS::fo, "text-transform" ) ); } } #endif // background color (property of the paragraph in OOo, of the text in kword/kpresenter) if (m_styleStack.hasAttributeNS( ooNS::fo, "background-color" )) { TQString bgColor = m_styleStack.attributeNS( ooNS::fo, "background-color"); if (bgColor != "transparent") text.setAttribute("textbackcolor", bgColor); } appendShadow( doc, outputParagraph ); // this is necessary to take care of shadowed paragraphs outputParagraph.appendChild( text ); } // for each text span } void OoImpressImport::createStyleMap( TQDomDocument &docstyles ) { TQDomElement styles = docstyles.documentElement(); if ( styles.isNull() ) return; TQDomNode fixedStyles = KoDom::namedItemNS( styles, ooNS::office, "styles" ); if ( !fixedStyles.isNull() ) { insertDraws( fixedStyles.toElement() ); insertStyles( fixedStyles.toElement() ); insertStylesPresentation( fixedStyles.toElement() ); } TQDomNode automaticStyles = KoDom::namedItemNS( styles, ooNS::office, "automatic-styles" ); if ( !automaticStyles.isNull() ) { insertStyles( automaticStyles.toElement() ); insertStylesPresentation( automaticStyles.toElement() ); } TQDomNode masterStyles = KoDom::namedItemNS( styles, ooNS::office, "master-styles" ); if ( !masterStyles.isNull() ) insertStyles( masterStyles.toElement() ); } void OoImpressImport::insertDraws( const TQDomElement& styles ) { TQDomElement e; forEachElement( e, styles ) { if ( !e.hasAttributeNS( ooNS::draw, "name" ) ) continue; TQString name = e.attributeNS( ooNS::draw, "name", TQString() ); m_draws.insert( name, new TQDomElement( e ) ); } } void OoImpressImport::insertStyles( const TQDomElement& styles ) { TQDomElement e; forEachElement( e, styles ) { const TQString localName = e.localName(); const TQString ns = e.namespaceURI(); if ( !e.hasAttributeNS( ooNS::style, "name" ) ) continue; const TQString name = e.attributeNS( ooNS::style, "name", TQString() ); if ( localName == "list-style" && ns == ooNS::text ) { TQDomElement* ep = new TQDomElement( e ); m_listStyles.insert( name, ep ); kdDebug(30518) << "List style: '" << name << "' loaded " << endl; } else { m_styles.insert( name, new TQDomElement( e ) ); kdDebug(30518) << "Style: '" << name << "' loaded " << endl; } } } void OoImpressImport::insertStylesPresentation( const TQDomElement& styles ) { TQDomElement e; forEachElement( e, styles ) { if ( !e.hasAttributeNS( ooNS::style, "name" ) ) continue; TQString name = e.attributeNS( ooNS::style, "name", TQString() ); m_stylesPresentation.insert( name, new TQDomElement( e ) ); //kdDebug(30518) << "Style: '" << name << "' loaded " << endl; } } void OoImpressImport::fillStyleStack( const TQDomElement& object, bool sticky ) { // find all styles associated with an object and push them on the stack if ( object.hasAttributeNS( ooNS::presentation, "style-name" ) ) { kdDebug(30518)<<" presentation:style-name **************************** :"<attributeNS( ooNS::style, "name", TQString() ) <hasAttributeNS( ooNS::style, "tqparent-style-name" ) ) { //kdDebug(30518)<<"m_styles[style->attribute( style:tqparent-style-name )] :"<attributeNS( ooNS::style, "tqparent-style-name", TQString() )]<attributeNS( ooNS::style, "tqparent-style-name", TQString() )] ); } //kdDebug(30518)<<" void OoImpressImport::addStyles( const TQDomElement* style ) :"<directory()->entry( url ); TQString extension = url.mid( url.tqfind( '.' ) ); TQString fileName = TQString( "picture%1" ).tqarg( m_numPicture++ ) + extension; KoStoreDevice* out = m_chain->storageFile( "pictures/" + fileName, KoStore::Write ); if ( file && out ) { TQByteArray buffer = file->data(); out->writeBlock( buffer.data(), buffer.size() ); } return fileName; } TQString OoImpressImport::storeSound(const TQDomElement & object, TQDomElement & p, TQDomDocument & doc) { TQFileInfo fi(m_chain->inputFile()); // handle relative URLs TQDir::setCurrent(fi.dirPath(true)); fi.setFile(object.attributeNS( ooNS::xlink, "href", TQString())); TQString url = fi.absFilePath(); //kdDebug(30518) << "Sound URL: " << url << endl; TQFile file(url); if (!file.exists()) return TQString(); TQString extension = url.mid( url.tqfind( '.' ) ); TQString fileName = TQString( "sound%1" ).tqarg( m_numSound++ ) + extension; fileName = "sounds/" + fileName; KoStoreDevice* out = m_chain->storageFile( fileName, KoStore::Write ); if (out) { if (!file.open(IO_ReadOnly)) return TQString(); TQByteArray data(8*1024); uint total = 0; for ( int block = 0; ( block = file.readBlock(data.data(), data.size()) ) > 0; total += block ) out->writeBlock(data.data(), data.size()); Q_ASSERT(total == fi.size()); file.close(); } else return TQString(); TQDomElement key = doc.createElement("FILE"); key.setAttribute("name", fileName); key.setAttribute("filename", url); p.appendChild(key); return url; } TQDomElement OoImpressImport::saveHelper(const TQString &tmpText, TQDomDocument &doc) { TQDomElement element=doc.createElement("TEXT"); if(tmpText.stripWhiteSpace().isEmpty()) // ### careful, this also strips \t and \n .... // working around a bug in TQDom element.setAttribute("whitespace", tmpText.length()); element.appendChild(doc.createTextNode(tmpText)); return element; } void OoImpressImport::appendPoints(TQDomDocument& doc, TQDomElement& e, const TQDomElement& object) { TQDomElement ptsElem = doc.createElement("POINTS"); TQStringList ptList = TQStringList::split(' ', object.attributeNS( ooNS::draw, "points", TQString())); TQString pt_x, pt_y; double tmp_x, tmp_y; for (TQStringList::Iterator it = ptList.begin(); it != ptList.end(); ++it) { TQDomElement point = doc.createElement("Point"); tmp_x = (*it).section(',',0,0).toInt() / 100; tmp_y = (*it).section(',',1,1).toInt() / 100; pt_x.setNum(tmp_x); pt_x+="mm"; pt_y.setNum(tmp_y); pt_y+="mm"; point.setAttribute("point_x", KoUnit::parseValue(pt_x)); point.setAttribute("point_y", KoUnit::parseValue(pt_y)); ptsElem.appendChild(point); } e.appendChild(ptsElem); } void OoImpressImport::appendField(TQDomDocument& doc, TQDomElement& e, const TQDomElement& object, uint pos) { const TQString tag = object.localName(); const TQString ns = object.namespaceURI(); const bool isTextNS = ns == ooNS::text; TQDomElement custom = doc.createElement("CUSTOM"); custom.setAttribute("pos", pos); TQDomElement variable = doc.createElement("VARIABLE"); if (isTextNS && tag == "date") { TQDateTime dt(TQDate::fromString(object.attributeNS( ooNS::text, "date-value", TQString()), Qt::ISODate)); bool fixed = (object.hasAttributeNS( ooNS::text, "fixed") && object.attributeNS( ooNS::text, "fixed", TQString())=="true"); if (!dt.isValid()) { dt = TQDateTime::tqcurrentDateTime(); // OOo docs say so :) fixed = false; } TQDomElement typeElem = doc.createElement("TYPE"); typeElem.setAttribute("key", "DATE0locale"); // ### find out the correlation between KOffice and OOo date/time types typeElem.setAttribute("type", 0); // VT_DATE typeElem.setAttribute("text", object.text()); variable.appendChild(typeElem); const TQDate date(dt.date()); const TQTime time(dt.time()); TQDomElement dateElement = doc.createElement("DATE"); dateElement.setAttribute("subtype", fixed ? 0 : 1); // VST_DATE_FIX, VST_DATE_CURRENT dateElement.setAttribute("fix", fixed ? 1 : 0); dateElement.setAttribute("day", date.day()); dateElement.setAttribute("month", date.month()); dateElement.setAttribute("year", date.year()); dateElement.setAttribute("hour", time.hour()); dateElement.setAttribute("minute", time.minute()); dateElement.setAttribute("second", time.second()); if (object.hasAttributeNS( ooNS::text, "date-adjust")) dateElement.setAttribute("correct", object.attributeNS( ooNS::text, "date-adjust", TQString())); variable.appendChild(dateElement); } else if (isTextNS && tag == "time") { // Use TQDateTime to work around a possible problem of TQTime::FromString in TQt 3.2.2 TQDateTime dt(TQDateTime::fromString(object.attributeNS( ooNS::text, "time-value", TQString()), Qt::ISODate)); bool fixed = (object.hasAttributeNS( ooNS::text, "fixed") && object.attributeNS( ooNS::text, "fixed", TQString())=="true"); if (!dt.isValid()) { dt = TQDateTime::tqcurrentDateTime(); // OOo docs say so :) fixed = false; } TQDomElement typeElem = doc.createElement("TYPE"); typeElem.setAttribute("key", "TIMElocale"); // ### find out the correlation between KOffice and OOo date/time types typeElem.setAttribute("type", 2); // VT_TIME typeElem.setAttribute("text", object.text()); variable.appendChild(typeElem); const TQTime time(dt.time()); TQDomElement timeElement = doc.createElement("TIME"); timeElement.setAttribute("subtype", fixed ? 0 : 1); // VST_TIME_FIX, VST_TIME_CURRENT timeElement.setAttribute("fix", fixed ? 1 : 0); timeElement.setAttribute("hour", time.hour()); timeElement.setAttribute("minute", time.minute()); timeElement.setAttribute("second", time.second()); /*if (object.hasAttributeNS( ooNS::text, "time-adjust")) timeElem.setAttribute("correct", object.attributeNS( ooNS::text, "time-adjust", TQString()));*/ // ### TODO variable.appendChild(timeElement); } else if (isTextNS && tag == "page-number") { TQDomElement typeElem = doc.createElement("TYPE"); typeElem.setAttribute("key", "NUMBER"); typeElem.setAttribute("type", 4); // VT_PGNUM typeElem.setAttribute("text", object.text()); variable.appendChild(typeElem); TQDomElement pgNumElem = doc.createElement("PGNUM"); int subtype = 0; // VST_PGNUM_CURRENT if (object.hasAttributeNS( ooNS::text, "select-page")) { const TQString select = object.attributeNS( ooNS::text, "select-page", TQString()); if (select == "previous") subtype = 3; // VST_PGNUM_PREVIOUS else if (select == "next") subtype = 4; // VST_PGNUM_NEXT else subtype = 0; // VST_PGNUM_CURRENT } pgNumElem.setAttribute("subtype", subtype); pgNumElem.setAttribute("value", object.text()); variable.appendChild(pgNumElem); } else if (isTextNS && tag == "file-name") { TQDomElement typeElem = doc.createElement("TYPE"); typeElem.setAttribute("key", "STRING"); typeElem.setAttribute("type", 8); // VT_FIELD typeElem.setAttribute("text", object.text()); variable.appendChild(typeElem); int subtype = 5; if (object.hasAttributeNS( ooNS::text, "display")) { const TQString display = object.attributeNS( ooNS::text, "display", TQString()); if (display == "path") subtype = 1; // VST_DIRECTORYNAME else if (display == "name") subtype = 6; // VST_FILENAMEWITHOUTEXTENSION else if (display == "name-and-extension") subtype = 0; // VST_FILENAME else subtype = 5; // VST_PATHFILENAME } TQDomElement fileNameElem = doc.createElement("FIELD"); fileNameElem.setAttribute("subtype", subtype); fileNameElem.setAttribute("value", object.text()); variable.appendChild(fileNameElem); } else if (isTextNS && tag == "author-name" || isTextNS && tag == "author-initials") { TQDomElement typeElem = doc.createElement("TYPE"); typeElem.setAttribute("key", "STRING"); typeElem.setAttribute("type", 8); // VT_FIELD typeElem.setAttribute("text", object.text()); variable.appendChild(typeElem); int subtype = 2; // VST_AUTHORNAME if (isTextNS && tag == "author-initials") subtype = 16; // VST_INITIAL TQDomElement authorElem = doc.createElement("FIELD"); authorElem.setAttribute("subtype", subtype); authorElem.setAttribute("value", object.text()); variable.appendChild(authorElem); } custom.appendChild(variable); e.appendChild(custom); } void OoImpressImport::createPresentationAnimation(const TQDomElement& element) { int order = 0; TQDomElement e; forEachElement( e, element ) { const TQString localName = e.localName(); const TQString ns = e.namespaceURI(); if ( ns == ooNS::presentation && localName == "show-tqshape" && e.hasAttributeNS( ooNS::draw, "tqshape-id" ) ) { TQString name = e.attributeNS( ooNS::draw, "tqshape-id", TQString() ); //kdDebug(30518)<<" insert animation style : name :"<element = ep; lst->order = order; m_animations.insert( name, lst ); ++order; } } } TQDomElement OoImpressImport::findAnimationByObjectID(const TQString & id, int & order) { kdDebug(30518)<<"TQDomElement OoImpressImport::findAnimationByObjectID(const TQString & id) :"<element ); !node.isNull(); node = node.nextSibling()) { TQDomElement e = node.toElement(); order = animation->order; kdDebug(30518)<<"e.tagName() :"<