filters

document.cpp

00001 /* This file is part of the KOffice project
00002    Copyright (C) 2002 Werner Trobin <trobin@kde.org>
00003    Copyright (C) 2002 David Faure <faure@kde.org>
00004 
00005    This program is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU General Public
00007    License version 2 as published by the Free Software Foundation.
00008 
00009    This program 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     General Public License for more details.
00013 
00014    You should have received a copy of the GNU General Public License
00015    along with this program; see the file COPYING.  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 "document.h"
00021 #include "conversion.h"
00022 #include "texthandler.h"
00023 #include "graphicshandler.h"
00024 #include "versionmagic.h"
00025 
00026 #include <KoRect.h>
00027 #include <KoUnit.h>
00028 #include <KoPageLayout.h>
00029 #include <kdebug.h>
00030 
00031 #include <wv2/styles.h>
00032 #include <wv2/ustring.h>
00033 #include <wv2/word97_generated.h>
00034 #include <wv2/parser.h>
00035 #include <wv2/parserfactory.h>
00036 #include <wv2/paragraphproperties.h>
00037 #include <wv2/associatedstrings.h>
00038 #include <klocale.h>
00039 #include <KoStore.h>
00040 #include <KoFilterChain.h>
00041 
00042 
00043 Document::Document( const std::string& fileName, QDomDocument& mainDocument, QDomDocument& documentInfo, QDomElement& framesetsElement, KoFilterChain* chain )
00044     : m_mainDocument( mainDocument ), m_documentInfo ( documentInfo ),
00045       m_framesetsElement( framesetsElement ),
00046       m_replacementHandler( new KWordReplacementHandler ), m_tableHandler( new KWordTableHandler ),
00047       m_pictureHandler( new KWordPictureHandler( this ) ), m_textHandler( 0 ),
00048       m_chain( chain ),
00049       m_parser( wvWare::ParserFactory::createParser( fileName ) ), m_headerFooters( 0 ), m_bodyFound( false ),
00050       m_footNoteNumber( 0 ), m_endNoteNumber( 0 )
00051 {
00052     if ( m_parser ) // 0 in case of major error (e.g. unsupported format)
00053     {
00054         m_textHandler = new KWordTextHandler( m_parser );
00055         connect( m_textHandler, SIGNAL( subDocFound( const wvWare::FunctorBase*, int ) ),
00056                  this, SLOT( slotSubDocFound( const wvWare::FunctorBase*, int ) ) );
00057         connect( m_textHandler, SIGNAL( tableFound( const KWord::Table& ) ),
00058                  this, SLOT( slotTableFound( const KWord::Table& ) ) );
00059         connect( m_textHandler, SIGNAL( pictureFound( const QString&, const QString&, const wvWare::FunctorBase* ) ),
00060                  this, SLOT( slotPictureFound( const QString&, const QString&, const wvWare::FunctorBase* ) ) );
00061         m_parser->setSubDocumentHandler( this );
00062         m_parser->setTextHandler( m_textHandler );
00063         m_parser->setTableHandler( m_tableHandler );
00064 #ifdef IMAGE_IMPORT
00065         m_parser->setPictureHandler( m_pictureHandler );
00066 #endif
00067         m_parser->setInlineReplacementHandler( m_replacementHandler );
00068         processStyles();
00069         processAssociatedStrings();
00070         connect( m_tableHandler, SIGNAL( sigTableCellStart( int, int, int, int, const KoRect&, const QString&, const wvWare::Word97::BRC&, const wvWare::Word97::BRC&, const wvWare::Word97::BRC&, const wvWare::Word97::BRC&, const wvWare::Word97::SHD& ) ),
00071                  this, SLOT( slotTableCellStart( int, int, int, int, const KoRect&, const QString&, const wvWare::Word97::BRC&, const wvWare::Word97::BRC&, const wvWare::Word97::BRC&, const wvWare::Word97::BRC&, const wvWare::Word97::SHD& ) ) );
00072         connect( m_tableHandler, SIGNAL( sigTableCellEnd() ),
00073                  this, SLOT( slotTableCellEnd() ) );
00074     }
00075 }
00076 
00077 Document::~Document()
00078 {
00079     delete m_textHandler;
00080     delete m_pictureHandler;
00081     delete m_tableHandler;
00082     delete m_replacementHandler;
00083 }
00084 
00085 void Document::finishDocument()
00086 {
00087     const wvWare::Word97::DOP& dop = m_parser->dop();
00088 
00089     QDomElement elementDoc = m_mainDocument.documentElement();
00090 
00091     QDomElement element;
00092     element = m_mainDocument.createElement("ATTRIBUTES");
00093     element.setAttribute("processing",0); // WP
00094     char allHeaders = ( wvWare::HeaderData::HeaderEven |
00095                         wvWare::HeaderData::HeaderOdd |
00096                         wvWare::HeaderData::HeaderFirst );
00097     element.setAttribute("hasHeader", m_headerFooters & allHeaders ? 1 : 0 );
00098     char allFooters = ( wvWare::HeaderData::FooterEven |
00099                         wvWare::HeaderData::FooterOdd |
00100                         wvWare::HeaderData::FooterFirst );
00101     element.setAttribute("hasFooter", m_headerFooters & allFooters ? 1 : 0 );
00102     //element.setAttribute("unit","mm"); // How to figure out the unit to use?
00103 
00104     element.setAttribute("tabStopValue", (double)dop.dxaTab / 20.0 );
00105     elementDoc.appendChild(element);
00106 
00107     element = m_mainDocument.createElement("FOOTNOTESETTING");
00108     elementDoc.appendChild(element);
00109     element.setAttribute( "start", dop.nFtn ); // initial footnote number for document. Starts at 1.
00110     element.setAttribute( "type", Conversion::numberFormatCode( dop.nfcFtnRef2 ) );
00111 
00112     element = m_mainDocument.createElement("ENDNOTESETTING");
00113     elementDoc.appendChild(element);
00114     element.setAttribute( "start", dop.nEdn ); // initial endnote number for document. Starts at 1.
00115     element.setAttribute( "type", Conversion::numberFormatCode( dop.nfcEdnRef2 ) );
00116 
00117     // Done at the end: write the type of headers/footers,
00118     // depending on which kind of headers and footers we received.
00119     QDomElement paperElement = elementDoc.namedItem("PAPER").toElement();
00120     Q_ASSERT ( !paperElement.isNull() ); // slotFirstSectionFound should have been called!
00121     if ( !paperElement.isNull() )
00122     {
00123         kdDebug(30513) << k_funcinfo << "m_headerFooters=" << m_headerFooters << endl;
00124         paperElement.setAttribute("hType", Conversion::headerMaskToHType( m_headerFooters ) );
00125         paperElement.setAttribute("fType", Conversion::headerMaskToFType( m_headerFooters ) );
00126     }
00127 
00128     // Write out <PICTURES> tag
00129     QDomElement picturesElem = m_mainDocument.createElement("PICTURES");
00130     elementDoc.appendChild( picturesElem );
00131     for( QStringList::Iterator it = m_pictureList.begin(); it != m_pictureList.end(); ++it ) {
00132         QDomElement keyElem = m_mainDocument.createElement("KEY");
00133         picturesElem.appendChild( keyElem );
00134         keyElem.setAttribute( "filename", *it );
00135         keyElem.setAttribute( "name", *it );
00136     }
00137 }
00138 
00139 void Document::processAssociatedStrings() {
00140     wvWare::AssociatedStrings strings( m_parser->associatedStrings() );
00141 
00142     QDomElement infodoc = m_documentInfo.createElement( "document-info" );
00143     QDomElement author = m_documentInfo.createElement( "author" );
00144     QDomElement fullname = m_documentInfo.createElement( "full-name" );
00145     QDomElement title = m_documentInfo.createElement( "title" );
00146     QDomElement about = m_documentInfo.createElement( "about" );
00147 
00148     m_documentInfo.appendChild(infodoc);
00149 
00150     if ( !strings.author().isNull()) {
00151     fullname.appendChild(
00152         m_documentInfo.createTextNode(
00153         Conversion::string (
00154             strings.author()
00155             ).string()));
00156     author.appendChild(fullname);
00157     infodoc.appendChild(author);
00158     }
00159 
00160     if ( !strings.title().isNull()) {
00161     title.appendChild(
00162         m_documentInfo.createTextNode(
00163         Conversion::string (
00164             strings.title()
00165             ).string()));
00166     about.appendChild(title);
00167     infodoc.appendChild(about);
00168     }
00169 
00170 }
00171 
00172 void Document::processStyles()
00173 {
00174     QDomElement stylesElem = m_mainDocument.createElement( "STYLES" );
00175     m_mainDocument.documentElement().appendChild( stylesElem );
00176 
00177     m_textHandler->setFrameSetElement( stylesElem ); 
00178     const wvWare::StyleSheet& styles = m_parser->styleSheet();
00179     unsigned int count = styles.size();
00180     //kdDebug(30513) << k_funcinfo << "styles count=" << count << endl;
00181     for ( unsigned int i = 0; i < count ; ++i )
00182     {
00183         const wvWare::Style* style = styles.styleByIndex( i );
00184         Q_ASSERT( style );
00185         //kdDebug(30513) << k_funcinfo << "style " << i << " " << style << endl;
00186         if ( style && style->type() == wvWare::Style::sgcPara )
00187         {
00188             QDomElement styleElem = m_mainDocument.createElement("STYLE");
00189             stylesElem.appendChild( styleElem );
00190 
00191             QConstString name = Conversion::string( style->name() );
00192             QDomElement element = m_mainDocument.createElement("NAME");
00193             element.setAttribute( "value", name.string() );
00194             styleElem.appendChild( element );
00195 
00196             kdDebug(30513) << k_funcinfo << "Style " << i << ": " << name.string() << endl;
00197 
00198             const wvWare::Style* followingStyle = styles.styleByID( style->followingStyle() );
00199             if ( followingStyle && followingStyle != style )
00200             {
00201                 QConstString followingName = Conversion::string( followingStyle->name() );
00202                 element = m_mainDocument.createElement("FOLLOWING");
00203                 element.setAttribute( "name", followingName.string() );
00204                 styleElem.appendChild( element );
00205             }
00206 
00207             m_textHandler->paragLayoutBegin(); // new style, reset some vars
00208 
00209             // It's important to do that one first, for m_shadowTextFound
00210             m_textHandler->writeFormat( styleElem, &style->chp(), 0L /*all of it, no ref chp*/, 0, 0, 1, 0L );
00211 
00212             m_textHandler->writeLayout( styleElem, style->paragraphProperties(), style );
00213         }
00214         // KWord doesn't support character styles yet
00215     }
00216 }
00217 
00218 bool Document::parse()
00219 {
00220     if ( m_parser )
00221         return m_parser->parse();
00222     return false;
00223 }
00224 
00225 void Document::bodyStart()
00226 {
00227     kdDebug(30513) << k_funcinfo << endl;
00228 
00229     QDomElement mainFramesetElement = m_mainDocument.createElement("FRAMESET");
00230     mainFramesetElement.setAttribute("frameType",1);
00231     mainFramesetElement.setAttribute("frameInfo",0);
00232     // TODO: "name" attribute (needs I18N)
00233     m_framesetsElement.appendChild(mainFramesetElement);
00234 
00235     // Those values are unused. The paper margins make recalcFrames() resize this frame.
00236     createInitialFrame( mainFramesetElement, 29, 798, 42, 566, false, Reconnect );
00237 
00238     m_textHandler->setFrameSetElement( mainFramesetElement );
00239     connect( m_textHandler, SIGNAL( firstSectionFound( wvWare::SharedPtr<const wvWare::Word97::SEP> ) ),
00240              this, SLOT( slotFirstSectionFound( wvWare::SharedPtr<const wvWare::Word97::SEP> ) ) );
00241     m_bodyFound = true;
00242 }
00243 
00244 void Document::bodyEnd()
00245 {
00246     kdDebug(30513) << k_funcinfo << endl;
00247     disconnect( m_textHandler, SIGNAL( firstSectionFound( wvWare::SharedPtr<const wvWare::Word97::SEP> ) ),
00248              this, SLOT( slotFirstSectionFound( wvWare::SharedPtr<const wvWare::Word97::SEP> ) ) );
00249 }
00250 
00251 
00252 void Document::slotFirstSectionFound( wvWare::SharedPtr<const wvWare::Word97::SEP> sep )
00253 {
00254     kdDebug(30513) << k_funcinfo << endl;
00255     QDomElement elementDoc = m_mainDocument.documentElement();
00256 
00257     QDomElement elementPaper = m_mainDocument.createElement("PAPER");
00258     bool landscape = (sep->dmOrientPage == 2);
00259     double width = (double)sep->xaPage / 20.0;
00260     double height = (double)sep->yaPage / 20.0;
00261     elementPaper.setAttribute("width", width);
00262     elementPaper.setAttribute("height", height);
00263 
00264     // guessFormat takes millimeters
00265     width = POINT_TO_MM( width );
00266     height = POINT_TO_MM( height );
00267     KoFormat paperFormat = KoPageFormat::guessFormat( landscape ? height : width, landscape ? width : height );
00268     elementPaper.setAttribute("format",paperFormat);
00269 
00270     elementPaper.setAttribute("orientation", landscape ? PG_LANDSCAPE : PG_PORTRAIT );
00271     elementPaper.setAttribute("columns", sep->ccolM1 + 1 );
00272     elementPaper.setAttribute("columnspacing", (double)sep->dxaColumns / 20.0);
00273     elementPaper.setAttribute("spHeadBody", (double)sep->dyaHdrTop / 20.0);
00274     elementPaper.setAttribute("spFootBody", (double)sep->dyaHdrBottom / 20.0);
00275     // elementPaper.setAttribute("zoom",100); // not a doc property in kword
00276     elementDoc.appendChild(elementPaper);
00277 
00278     QDomElement element = m_mainDocument.createElement("PAPERBORDERS");
00279     element.setAttribute("left", (double)sep->dxaLeft / 20.0);
00280     element.setAttribute("top",(double)sep->dyaTop / 20.0);
00281     element.setAttribute("right", (double)sep->dxaRight / 20.0);
00282     element.setAttribute("bottom", (double)sep->dyaBottom / 20.0);
00283     elementPaper.appendChild(element);
00284 
00285     // TODO apply brcTop/brcLeft etc. to the main FRAME
00286     // TODO use sep->fEndNote to set the 'use endnotes or footnotes' flag
00287 }
00288 
00289 void Document::headerStart( wvWare::HeaderData::Type type )
00290 {
00291     kdDebug(30513) << "startHeader type=" << type << " (" << Conversion::headerTypeToFramesetName( type ) << ")" << endl;
00292     // Werner says the headers are always emitted in the order of the Type enum.
00293 
00294     QDomElement framesetElement = m_mainDocument.createElement("FRAMESET");
00295     framesetElement.setAttribute( "frameType", 1 );
00296     framesetElement.setAttribute( "frameInfo", Conversion::headerTypeToFrameInfo( type ) );
00297     framesetElement.setAttribute( "name", Conversion::headerTypeToFramesetName( type ) );
00298     m_framesetsElement.appendChild(framesetElement);
00299 
00300     bool isHeader = Conversion::isHeader( type );
00301 
00302     createInitialFrame( framesetElement, 29, 798, isHeader?0:567, isHeader?41:567+41, true, Copy );
00303 
00304     m_textHandler->setFrameSetElement( framesetElement );
00305 
00306     m_headerFooters |= type;
00307 
00308     /*if ( Conversion::isHeader( type ) )
00309         m_hasHeader = true;
00310     else
00311         m_hasFooter = true;*/
00312 }
00313 
00314 void Document::headerEnd()
00315 {
00316     m_textHandler->setFrameSetElement( QDomElement() );
00317 }
00318 
00319 void Document::footnoteStart()
00320 {
00321     // Grab data that was stored with the functor, that triggered this parsing
00322     SubDocument subdoc( m_subdocQueue.front() );
00323     int type = subdoc.data;
00324 
00325     // Create footnote/endnote frameset
00326     QDomElement framesetElement = m_mainDocument.createElement("FRAMESET");
00327     framesetElement.setAttribute( "frameType", 1 /* text */ );
00328     framesetElement.setAttribute( "frameInfo", 7 /* footnote/endnote */ );
00329     if ( type == wvWare::FootnoteData::Endnote )
00330         // Keep name in sync with KWordTextHandler::footnoteFound
00331         framesetElement.setAttribute("name", i18n("Endnote %1").arg( ++m_endNoteNumber ) );
00332     else
00333         // Keep name in sync with KWordTextHandler::footnoteFound
00334         framesetElement.setAttribute("name", i18n("Footnote %1").arg( ++m_footNoteNumber ) );
00335     m_framesetsElement.appendChild(framesetElement);
00336 
00337     createInitialFrame( framesetElement, 29, 798, 567, 567+41, true, NoFollowup );
00338 
00339     m_textHandler->setFrameSetElement( framesetElement );
00340 }
00341 
00342 void Document::footnoteEnd()
00343 {
00344     kdDebug(30513) << k_funcinfo << endl;
00345     m_textHandler->setFrameSetElement( QDomElement() );
00346 }
00347 
00348 void Document::slotTableCellStart( int row, int column, int rowSpan, int columnSpan, const KoRect& cellRect, const QString& tableName, const wvWare::Word97::BRC& brcTop, const wvWare::Word97::BRC& brcBottom, const wvWare::Word97::BRC& brcLeft, const wvWare::Word97::BRC& brcRight, const wvWare::Word97::SHD& shd )
00349 {
00350     // Create footnote/endnote frameset
00351     QDomElement framesetElement = m_mainDocument.createElement("FRAMESET");
00352     framesetElement.setAttribute( "frameType", 1 /* text */ );
00353     framesetElement.setAttribute( "frameInfo", 0 /* normal text */ );
00354     framesetElement.setAttribute( "grpMgr", tableName );
00355     QString name = i18n("Table_Name Cell row,column", "%1 Cell %2,%3").arg(tableName).arg(row).arg(column);
00356     framesetElement.setAttribute( "name", name );
00357     framesetElement.setAttribute( "row", row );
00358     framesetElement.setAttribute( "col", column );
00359     framesetElement.setAttribute( "rows", rowSpan );
00360     framesetElement.setAttribute( "cols", columnSpan );
00361     m_framesetsElement.appendChild(framesetElement);
00362 
00363     QDomElement frameElem = createInitialFrame( framesetElement, cellRect.left(), cellRect.right(), cellRect.top(), cellRect.bottom(), true, NoFollowup );
00364     generateFrameBorder( frameElem, brcTop, brcBottom, brcLeft, brcRight, shd );
00365 
00366     m_textHandler->setFrameSetElement( framesetElement );
00367 }
00368 
00369 void Document::slotTableCellEnd()
00370 {
00371     m_textHandler->setFrameSetElement( QDomElement() );
00372 }
00373 
00374 QDomElement Document::createInitialFrame( QDomElement& parentFramesetElem, double left, double right, double top, double bottom, bool autoExtend, NewFrameBehavior nfb )
00375 {
00376     QDomElement frameElementOut = parentFramesetElem.ownerDocument().createElement("FRAME");
00377     frameElementOut.setAttribute( "left", left );
00378     frameElementOut.setAttribute( "right", right );
00379     frameElementOut.setAttribute( "top", top );
00380     frameElementOut.setAttribute( "bottom", bottom );
00381     frameElementOut.setAttribute( "runaround", 1 );
00382     // AutoExtendFrame for header/footer/footnote/endnote, AutoCreateNewFrame for body text
00383     frameElementOut.setAttribute( "autoCreateNewFrame", autoExtend ? 0 : 1 );
00384     frameElementOut.setAttribute( "newFrameBehavior", nfb );
00385     parentFramesetElem.appendChild( frameElementOut );
00386     return frameElementOut;
00387 }
00388 
00389 void Document::generateFrameBorder( QDomElement& frameElementOut, const wvWare::Word97::BRC& brcTop, const wvWare::Word97::BRC& brcBottom, const wvWare::Word97::BRC& brcLeft, const wvWare::Word97::BRC& brcRight, const wvWare::Word97::SHD& shd )
00390 {
00391     // Frame borders
00392 
00393     if ( brcTop.ico != 255 && brcTop.dptLineWidth != 255 ) // see tablehandler.cpp
00394         Conversion::setBorderAttributes( frameElementOut, brcTop, "t" );
00395     if ( brcBottom.ico != 255 && brcBottom.dptLineWidth != 255 ) // see tablehandler.cpp
00396         Conversion::setBorderAttributes( frameElementOut, brcBottom, "b" );
00397     if ( brcLeft.ico != 255 && brcLeft.dptLineWidth != 255 ) // could still be 255, for first column
00398         Conversion::setBorderAttributes( frameElementOut, brcLeft, "l" );
00399     if ( brcRight.ico != 255 && brcRight.dptLineWidth != 255 ) // could still be 255, for last column
00400         Conversion::setBorderAttributes( frameElementOut, brcRight, "r" );
00401 
00402     // Frame background brush (color and fill style)
00403     if ( shd.icoFore != 0 || shd.icoBack != 0 )
00404     {
00405         // If ipat = 0 (solid fill), icoBack is the background color.
00406         // But otherwise, icoFore is the one we need to set as bkColor
00407         // (and icoBack is usually white; it's the other colour of the pattern,
00408         // something that we can't set in Qt apparently).
00409         int bkColor = shd.ipat ? shd.icoFore : shd.icoBack;
00410         kdDebug(30513) << "generateFrameBorder: " << " icoFore=" << shd.icoFore << " icoBack=" << shd.icoBack << " ipat=" << shd.ipat << " -> bkColor=" << bkColor << endl;
00411 
00412         // Reverse-engineer MSWord's own hackery: it models various gray levels
00413         // using dithering. But this looks crappy with Qt. So we go back to a QColor.
00414         bool grayHack = ( shd.ipat && shd.icoFore == 1 && shd.icoBack == 8 );
00415         if ( grayHack )
00416         {
00417             bool ok;
00418             int grayLevel = Conversion::ditheringToGray( shd.ipat, &ok );
00419             if ( ok )
00420             {
00421                 QColor color( 0, 0, grayLevel, QColor::Hsv );
00422                 QString prefix = "bk";
00423                 frameElementOut.setAttribute( "bkRed", color.red() );
00424                 frameElementOut.setAttribute( "bkBlue", color.blue() );
00425                 frameElementOut.setAttribute( "bkGreen", color.green() );
00426             }
00427             else grayHack = false;
00428         }
00429         if ( !grayHack )
00430         {
00431             Conversion::setColorAttributes( frameElementOut, bkColor, "bk", true );
00432             // Fill style
00433             int brushStyle = Conversion::fillPatternStyle( shd.ipat );
00434             frameElementOut.setAttribute( "bkStyle", brushStyle );
00435         }
00436     }
00437 }
00438 
00439 void Document::slotSubDocFound( const wvWare::FunctorBase* functor, int data )
00440 {
00441     SubDocument subdoc( functor, data, QString::null, QString::null );
00442     m_subdocQueue.push( subdoc );
00443 }
00444 
00445 void Document::slotTableFound( const KWord::Table& table )
00446 {
00447     m_tableQueue.push( table );
00448 }
00449 
00450 void Document::slotPictureFound( const QString& frameName, const QString& pictureName,
00451                                  const wvWare::FunctorBase* pictureFunctor )
00452 {
00453     SubDocument subdoc( pictureFunctor, 0, frameName, pictureName );
00454     m_subdocQueue.push( subdoc );
00455 }
00456 
00457 void Document::processSubDocQueue()
00458 {
00459     // Table cells can contain footnotes, and footnotes can contain tables [without footnotes though]
00460     // This is why we need to repeat until there's nothing more do to (#79024)
00461     while ( !m_subdocQueue.empty() || !m_tableQueue.empty() )
00462     {
00463         while ( !m_subdocQueue.empty() )
00464         {
00465             SubDocument subdoc( m_subdocQueue.front() );
00466             Q_ASSERT( subdoc.functorPtr );
00467             (*subdoc.functorPtr)(); // call it
00468             delete subdoc.functorPtr; // delete it
00469             m_subdocQueue.pop();
00470         }
00471         while ( !m_tableQueue.empty() )
00472         {
00473             KWord::Table& table = m_tableQueue.front();
00474             m_tableHandler->tableStart( &table );
00475             QValueList<KWord::Row> &rows = table.rows;
00476             for( QValueList<KWord::Row>::Iterator it = rows.begin(); it != rows.end(); ++it ) {
00477                 KWord::TableRowFunctorPtr f = (*it).functorPtr;
00478                 Q_ASSERT( f );
00479                 (*f)(); // call it
00480                 delete f; // delete it
00481             }
00482             m_tableHandler->tableEnd();
00483             m_tableQueue.pop();
00484         }
00485     }
00486 }
00487 
00488 KoStoreDevice* Document::createPictureFrameSet( const KoSize& size )
00489 {
00490     // Grab data that was stored with the functor, that triggered this parsing
00491     SubDocument subdoc( m_subdocQueue.front() );
00492 
00493     QDomElement framesetElement = m_mainDocument.createElement("FRAMESET");
00494     framesetElement.setAttribute( "frameType", 2 /*picture*/ );
00495     framesetElement.setAttribute( "frameInfo", 0 );
00496     framesetElement.setAttribute( "name", subdoc.name );
00497     m_framesetsElement.appendChild(framesetElement);
00498 
00499     // The position doesn't matter as long as the picture is inline
00500     // FIXME for non-inline pics ####
00501     // To determine the size, look at OOo's filter (WW8PicDesc in ww8graf2.cxx, version 1.50, line 406)
00502     // Hint: #i17200#, a bit of guesswork I'm afraid
00503     //        if (aPic.dxaGoal == 1000 && aPic.mx == 1)  //100% hack ? (from ww8graf2.cxx)
00504     createInitialFrame( framesetElement, 0, size.width(), 0, size.height(), false, NoFollowup );
00505 
00506     QDomElement pictureElem = m_mainDocument.createElement("PICTURE");
00507     framesetElement.appendChild( pictureElem );
00508 
00509     QDomElement keyElem = m_mainDocument.createElement("KEY");
00510     pictureElem.appendChild( keyElem );
00511     keyElem.setAttribute( "filename", subdoc.extraName );
00512     m_pictureList.append( subdoc.extraName );
00513 
00514     kdDebug(30513) << "Preparing to write picture for '" << subdoc.name << "' into " << subdoc.extraName << endl;
00515     return m_chain->storageFile( subdoc.extraName, KoStore::Write );
00516 }
00517 
00518 
00519 #include "document.moc"
KDE Home | KDE Accessibility Home | Description of Access Keys