filters

kprkword.cc

00001 /* This file is part of the KDE project
00002    Copyright (C) 2001 David Faure <faure@kde.org>
00003 
00004    This library is free software; you can redistribute it and/or
00005    modify it under the terms of the GNU Library General Public
00006    License as published by the Free Software Foundation; either
00007    version 2 of the License, or (at your option) any later version.
00008 
00009    This library is distributed in the hope that it will be useful,
00010    but WITHOUT ANY WARRANTY; without even the implied warranty of
00011    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012    Library General Public License for more details.
00013 
00014    You should have received a copy of the GNU Library General Public License
00015    along with this library; see the file COPYING.LIB.  If not, write to
00016    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00017  * Boston, MA 02110-1301, USA.
00018 */
00019 
00020 #include <config.h>
00021 
00022 #include <kgenericfactory.h>
00023 #include <KoStoreDevice.h>
00024 #include <KoFilterChain.h>
00025 #include <KoGlobal.h>
00026 #include <kprkword.h>
00027 #include <klocale.h>
00028 #include <kdebug.h>
00029 #include <qsortedlist.h>
00030 #include <qcolor.h>
00031 
00032 typedef KGenericFactory<KprKword, KoFilter> KprKwordFactory;
00033 K_EXPORT_COMPONENT_FACTORY( libkprkword, KprKwordFactory( "kofficefilters" ) )
00034 
00035 KprKword::KprKword(KoFilter *, const char *, const QStringList&) :
00036     KoFilter(),
00037     outdoc( "DOC" )
00038 {
00039 }
00040 
00041 // This filter can act as an import filter for KWord and as an export
00042 // filter for KPresenter (isn't our architecture really nice ? :)
00043 // This is why we use the file-to-file method, not a QDomDoc one.
00044 KoFilter::ConversionStatus KprKword::convert( const QCString& from, const QCString& to )
00045 {
00046     if(to!="application/x-kword" || from!="application/x-kpresenter")
00047         return KoFilter::NotImplemented;
00048 
00049     KoStoreDevice* inpdev = m_chain->storageFile( "root", KoStore::Read );
00050     if ( !inpdev )
00051     {
00052         kdError(30502) << "Unable to open input stream" << endl;
00053         return KoFilter::StorageCreationError;
00054     }
00055 
00056     inpdoc.setContent( inpdev );
00057 
00058 
00059     outdoc.appendChild( outdoc.createProcessingInstruction( "xml", "version=\"1.0\" encoding=\"UTF-8\"" ) );
00060     QDomElement kwdoc = outdoc.createElement( "DOC" );
00061     kwdoc.setAttribute( "editor", "KprKword converter" );
00062     kwdoc.setAttribute( "mime", "application/x-kword" );
00063     kwdoc.setAttribute( "syntaxVersion", 1 );
00064     outdoc.appendChild( kwdoc );
00065 
00066     QDomElement paper = outdoc.createElement( "PAPER" );
00067     kwdoc.appendChild( paper );
00068     paper.setAttribute( "format", 1 ); // A4. How on earth could I know what the user really wants ? :)
00069     paper.setAttribute( "width", 595 );
00070     paper.setAttribute( "height", 841 );
00071     QDomElement borders = outdoc.createElement( "PAPERBORDERS" );
00072     paper.appendChild( borders );
00073     borders.setAttribute( "left", 28 );
00074     borders.setAttribute( "top", 42 );
00075     borders.setAttribute( "right", 28 );
00076     borders.setAttribute( "bottom", 42 );
00077 
00078     QDomElement framesets = outdoc.createElement( "FRAMESETS" );
00079     kwdoc.appendChild( framesets );
00080 
00081     frameset = outdoc.createElement( "FRAMESET" );
00082     framesets.appendChild( frameset );
00083     frameset.setAttribute( "frameType", 1 ); // text
00084     frameset.setAttribute( "frameInfo", 0 ); // body
00085     QDomElement frame = outdoc.createElement( "FRAME" );
00086     frameset.appendChild( frame );
00087     frame.setAttribute( "left", 28 );
00088     frame.setAttribute( "top", 42 );
00089     frame.setAttribute( "right", 566 );
00090     frame.setAttribute( "bottom", 798 );
00091     frame.setAttribute( "autoCreateNewFrame", 1 );
00092     frame.setAttribute( "newFrameBehaviour", 0 );
00093 
00094     titleStyleName = i18n("Slide Title");
00095 
00096     // Convert !
00097 
00098     convert();
00099 
00100     // Create a style for the slide titles
00101 
00102     QDomElement styles = outdoc.createElement( "STYLES" );
00103     kwdoc.appendChild( styles );
00104 
00105     QDomElement style = outdoc.createElement( "STYLE" );
00106     styles.appendChild( style );
00107     QDomElement elem = outdoc.createElement( "NAME" );
00108     style.appendChild( elem );
00109     elem.setAttribute( "value", titleStyleName );
00110     elem = outdoc.createElement( "FOLLOWING" );
00111     style.appendChild( elem );
00112     elem.setAttribute( "name", "Standard" ); // no i18n here!
00113 
00114     QDomElement counter = outdoc.createElement( "COUNTER" );
00115     style.appendChild( counter );
00116     counter.setAttribute( "type", 1 ); // numbered
00117     counter.setAttribute( "depth", 0 );
00118     counter.setAttribute( "start", 1 );
00119     counter.setAttribute( "numberingtype", 1 ); // chapter
00120     counter.setAttribute( "righttext", "." );
00121 
00122     QDomElement format = outdoc.createElement( "FORMAT" );
00123     style.appendChild( format );
00124     QDomElement font = outdoc.createElement( "FONT" );
00125     format.appendChild( font );
00126     font.setAttribute( "name", titleFont ); // found when reading the first title
00127     QDomElement size = outdoc.createElement( "SIZE" );
00128     format.appendChild( size );
00129     size.setAttribute( "value", 24 );
00130     QDomElement bold = outdoc.createElement( "WEIGHT" );
00131     format.appendChild( bold );
00132     bold.setAttribute( "value", 75 );
00133 
00134     // Create the standard style
00135     style = outdoc.createElement( "STYLE" );
00136     styles.appendChild( style );
00137     elem = outdoc.createElement( "NAME" );
00138     style.appendChild( elem );
00139     elem.setAttribute( "value", "Standard" ); // no i18n here!
00140     format = outdoc.createElement( "FORMAT" );
00141     style.appendChild( format ); // empty format == use defaults
00142 
00143     // Write output file
00144 
00145     KoStoreDevice* out = m_chain->storageFile( "root", KoStore::Write );
00146     if(!out) {
00147         kdError(30502) << "Unable to open output file!" << endl;
00148         return KoFilter::StorageCreationError;
00149     }
00150     QCString cstring = outdoc.toCString(); // utf-8 already
00151     out->writeBlock( cstring.data(), cstring.length() );
00152     return KoFilter::OK;
00153 }
00154 
00155 // This class is used to sort the objects by y position
00156 class KprObject {
00157  public:
00158     double y;
00159     QDomElement elem;
00160     bool operator < ( const KprObject & c ) const
00161     {
00162         return y < c.y;
00163     }
00164     bool operator == ( const KprObject & c ) const
00165     {
00166         return y == c.y;
00167     }
00168 };
00169 
00170 void KprKword::convert()
00171 {
00172     QDomElement docElem = inpdoc.documentElement();
00173     QDomElement paper = docElem.namedItem( "PAPER" ).toElement();
00174     int ptPageHeight = paper.attribute( "ptHeight" ).toInt();
00175 
00176     QDomElement objects = docElem.namedItem( "OBJECTS" ).toElement();
00177     if ( objects.isNull() )
00178         return;
00179 
00180     QSortedList< KprObject > objList;
00181     objList.setAutoDelete( true );
00182 
00183     QDomNodeList lst = objects.elementsByTagName( "OBJECT" );
00184     uint lstcount = lst.count();
00185     for ( uint item = 0 ; item < lstcount ; ++item )
00186     {
00187         QDomElement object = lst.item( item ).toElement();
00188         if ( object.attribute( "type" ).toInt() == 4 ) // we only care about text objs
00189         {
00190             QDomElement orig = object.namedItem( "ORIG" ).toElement();
00191             if ( !orig.isNull() )
00192             {
00193                 KprObject * obj = new KprObject;
00194                 obj->y = orig.attribute( "y" ).toDouble();
00195                 obj->elem = object;
00196                 objList.inSort( obj );
00197             }
00198         }
00199     }
00200 
00201     int curPage = -1;
00202     //kdDebug() << "found " << objList.count() << " objects" << endl;
00203 
00204     for ( QPtrListIterator<KprObject> it(objList); it.current(); ++it )
00205     {
00206         QDomElement elem = it.current()->elem;
00207         // Detect the first object of each page
00208         int page = int( it.current()->y / ptPageHeight );
00209         bool isTitle = ( page > curPage );
00210         //kdDebug() << "KprKword::convert y=" << it.current()->y << " ptPageHeight=" << ptPageHeight
00211         //          << " isTitle=" << isTitle << endl;
00212         curPage = page;
00213 
00214         QDomElement textObj = elem.namedItem( "TEXTOBJ" ).toElement();
00215         if (textObj.isNull())
00216             continue;
00217         // For each paragraph in this text object...
00218         QDomNodeList lst = textObj.elementsByTagName( "P" );
00219         uint lstcount = lst.count();
00220         for ( uint item = 0; item < lstcount ; ++item )
00221         {
00222             QDomElement p = lst.item( item ).toElement();
00223 
00224             // Create paragraph in KWord doc
00225             QDomElement parag = outdoc.createElement( "PARAGRAPH" );
00226             frameset.appendChild( parag );
00227 
00228             QDomElement outFormatsElem = outdoc.createElement( "FORMATS" );
00229 
00230             QString text;
00231             // For each text element in the paragraph...
00232             QDomElement textElem = p.firstChild().toElement();
00233 
00234             QDomElement counter = p.namedItem( "COUNTER" ).toElement();
00235             QDomElement indent=p.namedItem("INDENTS").toElement();
00236             QDomElement lineSpacing=p.namedItem( "LINESPACING" ).toElement();
00237             QDomElement offset=p.namedItem("OFFSETS").toElement();
00238             QDomElement leftBorder = p.namedItem( "LEFTBORDER" ).toElement();
00239             QDomElement rightBorder = p.namedItem( "RIGHTBORDER" ).toElement();
00240             QDomElement topBorder = p.namedItem( "TOPBORDER" ).toElement();
00241             QDomElement bottomBorder = p.namedItem( "BOTTOMBORDER" ).toElement();
00242 
00243             QDomElement shadow=p.namedItem("SHADOW").toElement();
00244 
00245             for ( ; !textElem.isNull() ; textElem = textElem.nextSibling().toElement() )
00246             {
00247                 int oldLen = text.length();
00248                 text += textElem.text();
00249                 //kdDebug() << "KprKword::convert text now " << text << endl;
00250                 QDomElement outFormatElem = outdoc.createElement( "FORMAT" );
00251 
00252                 if ( textElem.attribute( "italic" ).toInt() )
00253                 {
00254                     QDomElement e = outdoc.createElement("ITALIC");
00255                     e.setAttribute( "value", 1 );
00256                     outFormatElem.appendChild( e );
00257                 }
00258                 QColor underlineColor;
00259                 if ( textElem.hasAttribute("underlinecolor" ))
00260                 {
00261                     underlineColor =QColor(textElem.attribute("underlinecolor" ));
00262                 }
00263                 QString underlineStyleLine;
00264                 if ( textElem.hasAttribute("underlinestyleline"))
00265                 {
00266                     underlineStyleLine = textElem.attribute("underlinestyleline");
00267                 }
00268                 if ( textElem.hasAttribute("underline" ))
00269                 {
00270                     QDomElement e = outdoc.createElement("UNDERLINE");
00271                     QString value = textElem.attribute( "underline" );
00272                      if ( value == "double" )
00273                      {
00274                          e.setAttribute( "value", "double" );
00275                      }
00276                      else if ( value == "single" )
00277                      {
00278                          e.setAttribute( "value", "double" );
00279                      }
00280                      else
00281                      {
00282                          e.setAttribute( "value", (bool)value.toInt() ? "1" :"0" );
00283                      }
00284                      if ( underlineColor.isValid())
00285                      {
00286                          e.setAttribute("underlinecolor", underlineColor.name());
00287                      }
00288                      if ( !underlineStyleLine.isEmpty() )
00289                          e.setAttribute("styleline", underlineStyleLine);
00290                      outFormatElem.appendChild( e );
00291 
00292                 }
00293 
00294                 QString strikeOutStyleLine;
00295                 if ( textElem.hasAttribute("strikeoutstyleline"))
00296                 {
00297                     strikeOutStyleLine = textElem.attribute("strikeoutstyleline");
00298                 }
00299                 QString strikeOutValue;
00300                 if ( textElem.hasAttribute("strikeOut"))
00301                 {
00302                     strikeOutValue = textElem.attribute("strikeOut");
00303                 }
00304 
00305                 if( !strikeOutValue.isEmpty())
00306                 {
00307                     QDomElement e = outdoc.createElement("STRIKEOUT");
00308                     e.setAttribute( "value", strikeOutValue );
00309                     if ( !strikeOutStyleLine.isEmpty())
00310                         e.setAttribute("styleline", strikeOutStyleLine);
00311                     outFormatElem.appendChild( e );
00312                 }
00313                 /*if ( textElem.attribute( "bold" ).toInt() )
00314                 {
00315                     QDomElement e = outdoc.createElement("WEIGHT");
00316                     e.setAttribute( "value", 75 );
00317                     outFormatElem.appendChild( e );
00318                 }*/ // doesn't look good
00319                 if ( titleFont.isEmpty() && isTitle )
00320                     titleFont = textElem.attribute( "family" );
00321 
00322                 // Family and point size are voluntarily NOT passed over.
00323                 if ( !textElem.attribute( "color" ).isEmpty())
00324                 {
00325                     QColor col;
00326                     col.setNamedColor(textElem.attribute( "color" ));
00327                     QDomElement e = outdoc.createElement("COLOR");
00328                     e.setAttribute( "red", col.red() );
00329                     e.setAttribute( "green", col.green() );
00330                     e.setAttribute( "blue", col.blue() );
00331                     outFormatElem.appendChild( e );
00332                 }
00333                 if ( !textElem.attribute("textbackcolor").isEmpty())
00334                 {
00335                     QColor col;
00336                     col.setNamedColor(textElem.attribute( "textbackcolor" ));
00337                     QDomElement e = outdoc.createElement("TEXTBACKGROUNDCOLOR");
00338                     e.setAttribute( "red", col.red() );
00339                     e.setAttribute( "green", col.green() );
00340                     e.setAttribute( "blue", col.blue() );
00341                     outFormatElem.appendChild( e );
00342                 }
00343 
00344                 //before VERTICAL align
00345                 double relative = 0;
00346                 if( textElem.attribute("relativetextsize").toDouble())
00347                 {
00348                     relative = textElem.attribute("relativetextsize").toDouble();
00349                 }
00350 
00351 
00352                 if( textElem.attribute("VERTALIGN").toInt())
00353                 {
00354                     QDomElement e = outdoc.createElement("VERTALIGN");
00355                     e.setAttribute( "value", textElem.attribute("VERTALIGN").toInt() );
00356                     if ( relative != 0)
00357                         e.setAttribute( "relativetextsize", relative );
00358                     outFormatElem.appendChild( e );
00359                 }
00360 
00361                 if( textElem.hasAttribute("shadowtext"))
00362                 {
00363                     QDomElement e = outdoc.createElement("SHADOWTEXT");
00364                     e.setAttribute( "value", textElem.attribute("shadowtext").toInt() );
00365                     outFormatElem.appendChild( e );
00366                 }
00367 
00368                 if( textElem.hasAttribute("offsetfrombaseline"))
00369                 {
00370                     QDomElement e = outdoc.createElement("OFFSETFROMBASELINE");
00371                     e.setAttribute( "value", textElem.attribute("offsetfrombaseline").toInt() );
00372                     outFormatElem.appendChild( e );
00373                 }
00374 
00375                 if( textElem.hasAttribute("wordbyword"))
00376                 {
00377                     QDomElement e = outdoc.createElement("WORDBYWORD");
00378                     e.setAttribute( "value", textElem.attribute("wordbyword").toInt() );
00379                     outFormatElem.appendChild( e );
00380                 }
00381 
00382                 if( textElem.hasAttribute("fontattribute"))
00383                 {
00384                     QDomElement e = outdoc.createElement("FONTATTRIBUTE");
00385                     e.setAttribute( "value", textElem.attribute("fontattribute") );
00386                     outFormatElem.appendChild( e );
00387                 }
00388                 if( textElem.hasAttribute("language"))
00389                 {
00390                     QDomElement e = outdoc.createElement("LANGUAGE");
00391                     e.setAttribute( "value", textElem.attribute("language") );
00392                     outFormatElem.appendChild( e );
00393                 }
00394                 if ( !outFormatElem.firstChild().isNull() )
00395                 {
00396                     outFormatElem.setAttribute( "id", 1 ); // normal exte
00397                     outFormatElem.setAttribute( "pos", oldLen );
00398                     outFormatElem.setAttribute( "len", text.length() - oldLen );
00399                     outFormatsElem.appendChild( outFormatElem );
00400                 }
00401 
00402             } // end "for each text element"
00403 
00404             // KPresenter seems to save a trailing space (bug!)
00405             int len = text.length();
00406             if ( len > 0 && text[ len - 1 ] == ' ' )
00407                 text.truncate( len - 1 );
00408 
00409             QDomElement outTextElem = outdoc.createElement( "TEXT" );
00410             parag.appendChild( outTextElem );
00411             outTextElem.appendChild( outdoc.createTextNode( text ) );
00412 
00413             if ( !outFormatsElem.firstChild().isNull() ) // Do we have formats to save ?
00414                 parag.appendChild( outFormatsElem );
00415 
00416             QDomElement layoutElem = outdoc.createElement( "LAYOUT" );
00417             parag.appendChild( layoutElem );
00418             QDomElement nameElem = outdoc.createElement( "NAME" );
00419             layoutElem.appendChild( nameElem );
00420             nameElem.setAttribute( "value", isTitle ? titleStyleName : QString("Standard") );
00421             QDomElement align=outdoc.createElement("FLOW");
00422             if(p.hasAttribute("align"))
00423             {
00424                 switch(p.attribute( "align" ).toInt())
00425                 {
00426                 case 1:
00427                     align.setAttribute( "align","left");
00428                     break;
00429                 case 2:
00430                     align.setAttribute( "align","right");
00431                     break;
00432                 case 4:
00433                     align.setAttribute( "align","center");
00434                     break;
00435                 case 8:
00436                     align.setAttribute( "align","justify");
00437                     break;
00438                 }
00439             }
00440             if(!counter.isNull() )
00441                 layoutElem.appendChild( counter );
00442             if(!indent.isNull())
00443                 layoutElem.appendChild( indent );
00444             if(!lineSpacing.isNull())
00445                 layoutElem.appendChild( lineSpacing );
00446             if(!offset.isNull())
00447                 layoutElem.appendChild( offset);
00448             if(!leftBorder.isNull())
00449                 layoutElem.appendChild(leftBorder);
00450             if(!rightBorder.isNull())
00451                 layoutElem.appendChild(rightBorder);
00452             if(!topBorder.isNull())
00453                 layoutElem.appendChild(topBorder);
00454             if(!bottomBorder.isNull())
00455                 layoutElem.appendChild(bottomBorder);
00456             if(!align.isNull())
00457                 layoutElem.appendChild(align);
00458             if(!shadow.isNull())
00459                 layoutElem.appendChild(shadow);
00460             // Only the first parag of the top text object is set to the 'title' style
00461             isTitle = false;
00462         }
00463     }
00464 }
00465 
00466 #include <kprkword.moc>
KDE Home | KDE Accessibility Home | Description of Access Keys