You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
koffice/filters/kpresenter/kword/kprkword.cc

467 lines
18 KiB

/* This file is part of the KDE project
Copyright (C) 2001 David Faure <faure@kde.org>
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 <config.h>
#include <kgenericfactory.h>
#include <KoStoreDevice.h>
#include <KoFilterChain.h>
#include <KoGlobal.h>
#include <kprkword.h>
#include <tdelocale.h>
#include <kdebug.h>
#include <tqsortedlist.h>
#include <tqcolor.h>
typedef KGenericFactory<KprKword, KoFilter> 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<KprObject> 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 <kprkword.moc>