/* This file is part of the KDE project Copyright (C) 2001 David Faure This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include #include #include #include #include #include #include #include #include #include typedef KGenericFactory KprKwordFactory; K_EXPORT_COMPONENT_FACTORY( libkprkword, KprKwordFactory( "kofficefilters" ) ) KprKword::KprKword(KoFilter *, const char *, const TQStringList&) : KoFilter(), outdoc( "DOC" ) { } // This filter can act as an import filter for KWord and as an export // filter for KPresenter (isn't our architecture really nice ? :) // This is why we use the file-to-file method, not a TQDomDoc one. KoFilter::ConversionStatus KprKword::convert( const TQCString& from, const TQCString& to ) { if(to!="application/x-kword" || from!="application/x-kpresenter") return KoFilter::NotImplemented; KoStoreDevice* inpdev = m_chain->storageFile( "root", KoStore::Read ); if ( !inpdev ) { kdError(30502) << "Unable to open input stream" << endl; return KoFilter::StorageCreationError; } inpdoc.setContent( inpdev ); outdoc.appendChild( outdoc.createProcessingInstruction( "xml", "version=\"1.0\" encoding=\"UTF-8\"" ) ); TQDomElement kwdoc = outdoc.createElement( "DOC" ); kwdoc.setAttribute( "editor", "KprKword converter" ); kwdoc.setAttribute( "mime", "application/x-kword" ); kwdoc.setAttribute( "syntaxVersion", 1 ); outdoc.appendChild( kwdoc ); TQDomElement paper = outdoc.createElement( "PAPER" ); kwdoc.appendChild( paper ); paper.setAttribute( "format", 1 ); // A4. How on earth could I know what the user really wants ? :) paper.setAttribute( "width", 595 ); paper.setAttribute( "height", 841 ); TQDomElement borders = outdoc.createElement( "PAPERBORDERS" ); paper.appendChild( borders ); borders.setAttribute( "left", 28 ); borders.setAttribute( "top", 42 ); borders.setAttribute( "right", 28 ); borders.setAttribute( "bottom", 42 ); TQDomElement framesets = outdoc.createElement( "FRAMESETS" ); kwdoc.appendChild( framesets ); frameset = outdoc.createElement( "FRAMESET" ); framesets.appendChild( frameset ); frameset.setAttribute( "frameType", 1 ); // text frameset.setAttribute( "frameInfo", 0 ); // body TQDomElement frame = outdoc.createElement( "FRAME" ); frameset.appendChild( frame ); frame.setAttribute( "left", 28 ); frame.setAttribute( "top", 42 ); frame.setAttribute( "right", 566 ); frame.setAttribute( "bottom", 798 ); frame.setAttribute( "autoCreateNewFrame", 1 ); frame.setAttribute( "newFrameBehaviour", 0 ); titleStyleName = i18n("Slide Title"); // Convert ! convert(); // Create a style for the slide titles TQDomElement styles = outdoc.createElement( "STYLES" ); kwdoc.appendChild( styles ); TQDomElement style = outdoc.createElement( "STYLE" ); styles.appendChild( style ); TQDomElement elem = outdoc.createElement( "NAME" ); style.appendChild( elem ); elem.setAttribute( "value", titleStyleName ); elem = outdoc.createElement( "FOLLOWING" ); style.appendChild( elem ); elem.setAttribute( "name", "Standard" ); // no i18n here! TQDomElement counter = outdoc.createElement( "COUNTER" ); style.appendChild( counter ); counter.setAttribute( "type", 1 ); // numbered counter.setAttribute( "depth", 0 ); counter.setAttribute( "start", 1 ); counter.setAttribute( "numberingtype", 1 ); // chapter counter.setAttribute( "righttext", "." ); TQDomElement format = outdoc.createElement( "FORMAT" ); style.appendChild( format ); TQDomElement font = outdoc.createElement( "FONT" ); format.appendChild( font ); font.setAttribute( "name", titleFont ); // found when reading the first title TQDomElement size = outdoc.createElement( "SIZE" ); format.appendChild( size ); size.setAttribute( "value", 24 ); TQDomElement bold = outdoc.createElement( "WEIGHT" ); format.appendChild( bold ); bold.setAttribute( "value", 75 ); // Create the standard style style = outdoc.createElement( "STYLE" ); styles.appendChild( style ); elem = outdoc.createElement( "NAME" ); style.appendChild( elem ); elem.setAttribute( "value", "Standard" ); // no i18n here! format = outdoc.createElement( "FORMAT" ); style.appendChild( format ); // empty format == use defaults // Write output file KoStoreDevice* out = m_chain->storageFile( "root", KoStore::Write ); if(!out) { kdError(30502) << "Unable to open output file!" << endl; return KoFilter::StorageCreationError; } TQCString cstring = outdoc.toCString(); // utf-8 already out->writeBlock( cstring.data(), cstring.length() ); return KoFilter::OK; } // This class is used to sort the objects by y position class KprObject { public: double y; TQDomElement elem; bool operator < ( const KprObject & c ) const { return y < c.y; } bool operator == ( const KprObject & c ) const { return y == c.y; } }; void KprKword::convert() { TQDomElement docElem = inpdoc.documentElement(); TQDomElement paper = docElem.namedItem( "PAPER" ).toElement(); int ptPageHeight = paper.attribute( "ptHeight" ).toInt(); TQDomElement objects = docElem.namedItem( "OBJECTS" ).toElement(); if ( objects.isNull() ) return; TQSortedList< KprObject > objList; objList.setAutoDelete( true ); TQDomNodeList lst = objects.elementsByTagName( "OBJECT" ); uint lstcount = lst.count(); for ( uint item = 0 ; item < lstcount ; ++item ) { TQDomElement object = lst.item( item ).toElement(); if ( object.attribute( "type" ).toInt() == 4 ) // we only care about text objs { TQDomElement orig = object.namedItem( "ORIG" ).toElement(); if ( !orig.isNull() ) { KprObject * obj = new KprObject; obj->y = orig.attribute( "y" ).toDouble(); obj->elem = object; objList.inSort( obj ); } } } int curPage = -1; //kdDebug() << "found " << objList.count() << " objects" << endl; for ( TQPtrListIterator it(objList); it.current(); ++it ) { TQDomElement elem = it.current()->elem; // Detect the first object of each page int page = int( it.current()->y / ptPageHeight ); bool isTitle = ( page > curPage ); //kdDebug() << "KprKword::convert y=" << it.current()->y << " ptPageHeight=" << ptPageHeight // << " isTitle=" << isTitle << endl; curPage = page; TQDomElement textObj = elem.namedItem( "TEXTOBJ" ).toElement(); if (textObj.isNull()) continue; // For each paragraph in this text object... TQDomNodeList lst = textObj.elementsByTagName( "P" ); uint lstcount = lst.count(); for ( uint item = 0; item < lstcount ; ++item ) { TQDomElement p = lst.item( item ).toElement(); // Create paragraph in KWord doc TQDomElement parag = outdoc.createElement( "PARAGRAPH" ); frameset.appendChild( parag ); TQDomElement outFormatsElem = outdoc.createElement( "FORMATS" ); TQString text; // For each text element in the paragraph... TQDomElement textElem = p.firstChild().toElement(); TQDomElement counter = p.namedItem( "COUNTER" ).toElement(); TQDomElement indent=p.namedItem("INDENTS").toElement(); TQDomElement lineSpacing=p.namedItem( "LINESPACING" ).toElement(); TQDomElement offset=p.namedItem("OFFSETS").toElement(); TQDomElement leftBorder = p.namedItem( "LEFTBORDER" ).toElement(); TQDomElement rightBorder = p.namedItem( "RIGHTBORDER" ).toElement(); TQDomElement topBorder = p.namedItem( "TOPBORDER" ).toElement(); TQDomElement bottomBorder = p.namedItem( "BOTTOMBORDER" ).toElement(); TQDomElement shadow=p.namedItem("SHADOW").toElement(); for ( ; !textElem.isNull() ; textElem = textElem.nextSibling().toElement() ) { int oldLen = text.length(); text += textElem.text(); //kdDebug() << "KprKword::convert text now " << text << endl; TQDomElement outFormatElem = outdoc.createElement( "FORMAT" ); if ( textElem.attribute( "italic" ).toInt() ) { TQDomElement e = outdoc.createElement("ITALIC"); e.setAttribute( "value", 1 ); outFormatElem.appendChild( e ); } TQColor underlineColor; if ( textElem.hasAttribute("underlinecolor" )) { underlineColor =TQColor(textElem.attribute("underlinecolor" )); } TQString underlineStyleLine; if ( textElem.hasAttribute("underlinestyleline")) { underlineStyleLine = textElem.attribute("underlinestyleline"); } if ( textElem.hasAttribute("underline" )) { TQDomElement e = outdoc.createElement("UNDERLINE"); TQString value = textElem.attribute( "underline" ); if ( value == "double" ) { e.setAttribute( "value", "double" ); } else if ( value == "single" ) { e.setAttribute( "value", "double" ); } else { e.setAttribute( "value", (bool)value.toInt() ? "1" :"0" ); } if ( underlineColor.isValid()) { e.setAttribute("underlinecolor", underlineColor.name()); } if ( !underlineStyleLine.isEmpty() ) e.setAttribute("styleline", underlineStyleLine); outFormatElem.appendChild( e ); } TQString strikeOutStyleLine; if ( textElem.hasAttribute("strikeoutstyleline")) { strikeOutStyleLine = textElem.attribute("strikeoutstyleline"); } TQString strikeOutValue; if ( textElem.hasAttribute("strikeOut")) { strikeOutValue = textElem.attribute("strikeOut"); } if( !strikeOutValue.isEmpty()) { TQDomElement e = outdoc.createElement("STRIKEOUT"); e.setAttribute( "value", strikeOutValue ); if ( !strikeOutStyleLine.isEmpty()) e.setAttribute("styleline", strikeOutStyleLine); outFormatElem.appendChild( e ); } /*if ( textElem.attribute( "bold" ).toInt() ) { TQDomElement e = outdoc.createElement("WEIGHT"); e.setAttribute( "value", 75 ); outFormatElem.appendChild( e ); }*/ // doesn't look good if ( titleFont.isEmpty() && isTitle ) titleFont = textElem.attribute( "family" ); // Family and point size are voluntarily NOT passed over. if ( !textElem.attribute( "color" ).isEmpty()) { TQColor col; col.setNamedColor(textElem.attribute( "color" )); TQDomElement e = outdoc.createElement("COLOR"); e.setAttribute( "red", col.red() ); e.setAttribute( "green", col.green() ); e.setAttribute( "blue", col.blue() ); outFormatElem.appendChild( e ); } if ( !textElem.attribute("textbackcolor").isEmpty()) { TQColor col; col.setNamedColor(textElem.attribute( "textbackcolor" )); TQDomElement e = outdoc.createElement("TEXTBACKGROUNDCOLOR"); e.setAttribute( "red", col.red() ); e.setAttribute( "green", col.green() ); e.setAttribute( "blue", col.blue() ); outFormatElem.appendChild( e ); } //before VERTICAL align double relative = 0; if( textElem.attribute("relativetextsize").toDouble()) { relative = textElem.attribute("relativetextsize").toDouble(); } if( textElem.attribute("VERTALIGN").toInt()) { TQDomElement e = outdoc.createElement("VERTALIGN"); e.setAttribute( "value", textElem.attribute("VERTALIGN").toInt() ); if ( relative != 0) e.setAttribute( "relativetextsize", relative ); outFormatElem.appendChild( e ); } if( textElem.hasAttribute("shadowtext")) { TQDomElement e = outdoc.createElement("SHADOWTEXT"); e.setAttribute( "value", textElem.attribute("shadowtext").toInt() ); outFormatElem.appendChild( e ); } if( textElem.hasAttribute("offsetfrombaseline")) { TQDomElement e = outdoc.createElement("OFFSETFROMBASELINE"); e.setAttribute( "value", textElem.attribute("offsetfrombaseline").toInt() ); outFormatElem.appendChild( e ); } if( textElem.hasAttribute("wordbyword")) { TQDomElement e = outdoc.createElement("WORDBYWORD"); e.setAttribute( "value", textElem.attribute("wordbyword").toInt() ); outFormatElem.appendChild( e ); } if( textElem.hasAttribute("fontattribute")) { TQDomElement e = outdoc.createElement("FONTATTRIBUTE"); e.setAttribute( "value", textElem.attribute("fontattribute") ); outFormatElem.appendChild( e ); } if( textElem.hasAttribute("language")) { TQDomElement e = outdoc.createElement("LANGUAGE"); e.setAttribute( "value", textElem.attribute("language") ); outFormatElem.appendChild( e ); } if ( !outFormatElem.firstChild().isNull() ) { outFormatElem.setAttribute( "id", 1 ); // normal exte outFormatElem.setAttribute( "pos", oldLen ); outFormatElem.setAttribute( "len", text.length() - oldLen ); outFormatsElem.appendChild( outFormatElem ); } } // end "for each text element" // KPresenter seems to save a trailing space (bug!) int len = text.length(); if ( len > 0 && text[ len - 1 ] == ' ' ) text.truncate( len - 1 ); TQDomElement outTextElem = outdoc.createElement( "TEXT" ); parag.appendChild( outTextElem ); outTextElem.appendChild( outdoc.createTextNode( text ) ); if ( !outFormatsElem.firstChild().isNull() ) // Do we have formats to save ? parag.appendChild( outFormatsElem ); TQDomElement layoutElem = outdoc.createElement( "LAYOUT" ); parag.appendChild( layoutElem ); TQDomElement nameElem = outdoc.createElement( "NAME" ); layoutElem.appendChild( nameElem ); nameElem.setAttribute( "value", isTitle ? titleStyleName : TQString("Standard") ); TQDomElement align=outdoc.createElement("FLOW"); if(p.hasAttribute("align")) { switch(p.attribute( "align" ).toInt()) { case 1: align.setAttribute( "align","left"); break; case 2: align.setAttribute( "align","right"); break; case 4: align.setAttribute( "align","center"); break; case 8: align.setAttribute( "align","justify"); break; } } if(!counter.isNull() ) layoutElem.appendChild( counter ); if(!indent.isNull()) layoutElem.appendChild( indent ); if(!lineSpacing.isNull()) layoutElem.appendChild( lineSpacing ); if(!offset.isNull()) layoutElem.appendChild( offset); if(!leftBorder.isNull()) layoutElem.appendChild(leftBorder); if(!rightBorder.isNull()) layoutElem.appendChild(rightBorder); if(!topBorder.isNull()) layoutElem.appendChild(topBorder); if(!bottomBorder.isNull()) layoutElem.appendChild(bottomBorder); if(!align.isNull()) layoutElem.appendChild(align); if(!shadow.isNull()) layoutElem.appendChild(shadow); // Only the first parag of the top text object is set to the 'title' style isTitle = false; } } } #include