00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "KWOasisLoader.h"
00020 #include "KWDocument.h"
00021 #include "KWTextDocument.h"
00022 #include "KWTextFrameSet.h"
00023 #include "KWFrameSet.h"
00024 #include "KWPictureFrameSet.h"
00025 #include "KWLoadingInfo.h"
00026 #include "KWTableFrameSet.h"
00027 #include "KWPartFrameSet.h"
00028 #include "KWPageManager.h"
00029 #include "KWFormulaFrameSet.h"
00030
00031 #include <KoStore.h>
00032 #include <KoOasisContext.h>
00033 #include <KoOasisStyles.h>
00034 #include <KoOasisStore.h>
00035 #include <KoOasisSettings.h>
00036 #include <KoXmlNS.h>
00037 #include <KoDom.h>
00038 #include <KoXmlNS.h>
00039
00040 #include <kdebug.h>
00041 #include <klocale.h>
00042
00043 #include <qvaluelist.h>
00044 #include <qdom.h>
00045
00046 KWOasisLoader::KWOasisLoader( KWDocument* doc )
00047 : m_doc( doc )
00048 {
00049 }
00050
00051
00052
00053 QValueList<KWFrame *> KWOasisLoader::insertOasisData( KoStore* store, KoTextCursor* cursor )
00054 {
00055 QValueList<KWFrame *> frames;
00056 if ( store->bad() || !store->hasFile( "content.xml" ) )
00057 {
00058 kdError(32001) << "Invalid ZIP store in memory" << endl;
00059 if ( !store->hasFile( "content.xml" ) )
00060 kdError(32001) << "No content.xml file" << endl;
00061 return frames;
00062 }
00063 store->disallowNameExpansion();
00064
00065 KoOasisStore oasisStore( store );
00066 QDomDocument contentDoc;
00067 QString errorMessage;
00068 bool ok = oasisStore.loadAndParse( "content.xml", contentDoc, errorMessage );
00069 if ( !ok ) {
00070 kdError(32001) << "Error parsing content.xml: " << errorMessage << endl;
00071 return frames;
00072 }
00073
00074 KoOasisStyles oasisStyles;
00075 QDomDocument stylesDoc;
00076 (void)oasisStore.loadAndParse( "styles.xml", stylesDoc, errorMessage );
00077
00078 oasisStyles.createStyleMap( stylesDoc, true );
00079
00080 oasisStyles.createStyleMap( contentDoc, false );
00081
00082 m_doc->createLoadingInfo();
00083
00084 QDomElement content = contentDoc.documentElement();
00085
00086 QDomElement body( KoDom::namedItemNS( content, KoXmlNS::office, "body" ) );
00087 if ( body.isNull() ) {
00088 kdError(32001) << "No office:body found!" << endl;
00089 return frames;
00090 }
00091
00092
00093 QDomElement iter, realBody;
00094 forEachElement( iter, body ) {
00095 realBody = iter;
00096 }
00097 if ( realBody.isNull() ) {
00098 kdError(32001) << "No element found inside office:body!" << endl;
00099 return frames;
00100 }
00101
00102 KoOasisContext context( m_doc, *m_doc->variableCollection(), oasisStyles, store );
00103 if ( cursor )
00104 {
00105 KWTextDocument * textdoc = static_cast<KWTextDocument *>(cursor->parag()->document());
00106 KWTextFrameSet * textFs = textdoc->textFrameSet();
00107
00108 *cursor = textFs->textObject()->pasteOasisText( realBody, context, *cursor, m_doc->styleCollection() );
00109
00110 textFs->textObject()->setNeedSpellCheck( true );
00111 }
00112 else
00113 {
00114
00115
00116 QDomElement tag;
00117 forEachElement( tag, realBody )
00118 {
00119 context.styleStack().save();
00120 const QString bodyTagLocalName = tag.localName();
00121 kdDebug() << k_funcinfo << bodyTagLocalName << endl;
00122 if ( bodyTagLocalName == "frame" && tag.namespaceURI() == KoXmlNS::draw )
00123 {
00124 KWFrame * frame = loadFrame( tag, context, KoPoint( 10, 10 ) );
00125 if ( frame )
00126 {
00127 frames.append( frame );
00128 }
00129 }
00130 #if 0 // TODO OASIS table:table
00131 else if ( bodyTagLocalName == "table" && tag.namespaceURI() == KoXmlNS::table )
00132 ;
00133 #endif
00134 }
00135 }
00136
00137
00138 m_doc->completeOasisPasting();
00139 m_doc->deleteLoadingInfo();
00140 return frames;
00141 }
00142
00143 void KWOasisLoader::loadOasisSettings( const QDomDocument& settingsDoc )
00144 {
00145 KoOasisSettings settings( settingsDoc );
00146 KoOasisSettings::Items viewSettings = settings.itemSet( "view-settings" );
00147 if ( !viewSettings.isNull() )
00148 {
00149 m_doc->setUnit( KoUnit::unit(viewSettings.parseConfigItemString("unit")) );
00150 }
00151 loadOasisIgnoreList( settings );
00152 m_doc->variableCollection()->variableSetting()->loadOasis( settings );
00153 }
00154
00155 static QString headerTypeToFramesetName( const QString& localName, bool hasEvenOdd )
00156 {
00157 if ( localName == "header" )
00158 return hasEvenOdd ? i18n("Odd Pages Header") : i18n( "Header" );
00159 if ( localName == "header-left" )
00160 return i18n("Even Pages Header");
00161 if ( localName == "footer" )
00162 return hasEvenOdd ? i18n("Odd Pages Footer") : i18n( "Footer" );
00163 if ( localName == "footer-left" )
00164 return i18n("Even Pages Footer");
00165 if ( localName == "header-first" )
00166 return i18n("First Page Header");
00167 if ( localName == "footer-first" )
00168 return i18n("First Page Footer");
00169 kdWarning(32001) << "Unknown tag in headerTypeToFramesetName: " << localName << endl;
00170 return QString::null;
00171 }
00172
00173 static KWFrameSet::Info headerTypeToFrameInfo( const QString& localName, bool )
00174 {
00175 if ( localName == "header" )
00176 return KWFrameSet::FI_ODD_HEADER;
00177 if ( localName == "header-left" )
00178 return KWFrameSet::FI_EVEN_HEADER;
00179 if ( localName == "footer" )
00180 return KWFrameSet::FI_ODD_FOOTER;
00181 if ( localName == "footer-left" )
00182 return KWFrameSet::FI_EVEN_FOOTER;
00183
00184
00185
00186 if ( localName == "header-first" )
00187 return KWFrameSet::FI_FIRST_HEADER;
00188 if ( localName == "footer-first" )
00189 return KWFrameSet::FI_FIRST_FOOTER;
00190 return KWFrameSet::FI_BODY;
00191 }
00192
00193 void KWOasisLoader::loadOasisHeaderFooter( const QDomElement& headerFooter, bool hasEvenOdd, QDomElement& style, KoOasisContext& context )
00194 {
00195 const QString localName = headerFooter.localName();
00196 bool isHeader = localName.startsWith( "header" );
00197
00198 KWTextFrameSet *fs = new KWTextFrameSet( m_doc, headerTypeToFramesetName( localName, hasEvenOdd ) );
00199 fs->setFrameSetInfo( headerTypeToFrameInfo( localName, hasEvenOdd ) );
00200 m_doc->addFrameSet( fs, false );
00201
00202 if ( !style.isNull() )
00203 context.styleStack().push( style );
00204 KWFrame* frame = new KWFrame( fs, 29, isHeader?0:567, 798-29, 41 );
00205 frame->loadCommonOasisProperties( context, fs, "header-footer" );
00206 const QString minHeight = context.styleStack().attributeNS( KoXmlNS::fo, "min-height" );
00207 if ( !minHeight.isEmpty() )
00208 frame->setMinimumFrameHeight( KoUnit::parseValue( minHeight ) );
00209
00210 frame->setFrameBehavior( KWFrame::AutoExtendFrame );
00211 frame->setNewFrameBehavior( KWFrame::Copy );
00212 fs->addFrame( frame );
00213 if ( !style.isNull() )
00214 context.styleStack().pop();
00215
00216 context.setUseStylesAutoStyles( true );
00217 fs->loadOasisContent( headerFooter, context );
00218 context.setUseStylesAutoStyles( false );
00219
00220 if ( isHeader )
00221 m_doc->m_headerVisible = true;
00222 else
00223 m_doc->m_footerVisible = true;
00224 }
00225
00226 void KWOasisLoader::loadOasisIgnoreList( const KoOasisSettings& settings )
00227 {
00228 KoOasisSettings::Items configurationSettings = settings.itemSet( "configuration-settings" );
00229 if ( !configurationSettings.isNull() )
00230 {
00231 const QString ignorelist = configurationSettings.parseConfigItemString( "SpellCheckerIgnoreList" );
00232 kdDebug()<<" ignorelist :"<<ignorelist<<endl;
00233 m_doc->setSpellCheckIgnoreList( QStringList::split( ',', ignorelist ) );
00234 }
00235 }
00236
00237 KWFrame* KWOasisLoader::loadFrame( const QDomElement& frameTag, KoOasisContext& context, const KoPoint& offset )
00238 {
00239 KWFrame* frame = 0;
00240 QDomElement elem;
00241 forEachElement( elem, frameTag )
00242 {
00243 if ( elem.namespaceURI() != KoXmlNS::draw )
00244 continue;
00245 const QString localName = elem.localName();
00246 if ( localName == "text-box" )
00247 {
00248
00249 frame = loadOasisTextBox( frameTag, elem, context );
00250 break;
00251 }
00252 else if ( localName == "image" )
00253 {
00254 KWFrameSet* fs = new KWPictureFrameSet( m_doc, frameTag, elem, context );
00255 m_doc->addFrameSet( fs, false );
00256 frame = fs->frame(0);
00257 break;
00258 } else if ( localName == "object" )
00259 {
00260 QDomElement mathElem;
00261 QDomElement childElem;
00262 forEachElement( childElem, elem )
00263 {
00264 if ( childElem.localName() == "math"
00265 && childElem.namespaceURI() == KoXmlNS::math ) {
00266 mathElem = childElem;
00267 }
00268 }
00269 if ( !mathElem.isNull() ) {
00270 KWFormulaFrameSet* fs = new KWFormulaFrameSet( m_doc, frameTag, mathElem, context );
00271 m_doc->addFrameSet( fs, false );
00272 frame = fs->frame(0);
00273 } else {
00274 KWPartFrameSet* fs = new KWPartFrameSet( m_doc, frameTag, elem, context );
00275 m_doc->addFrameSet( fs, false );
00276 frame = fs->frame(0);
00277 }
00278 break;
00279 }
00280 }
00281 if ( frame ) {
00282 const QString anchorType = frameTag.attributeNS( KoXmlNS::text, "anchor-type", QString::null );
00283 if ( anchorType == "page" ) {
00284 double x = KoUnit::parseValue( frameTag.attributeNS( KoXmlNS::svg, "x", QString::null ) );
00285 double y = KoUnit::parseValue( frameTag.attributeNS( KoXmlNS::svg, "y", QString::null ) );
00286 int pageNum = frameTag.attributeNS( KoXmlNS::text, "anchor-page-number", QString::null ).toInt();
00287
00288 KWPageManager* pageManager = m_doc->pageManager();
00289 while ( pageNum > pageManager->lastPageNumber() )
00290 pageManager->appendPage();
00291 frame->moveTopLeft( KoPoint( x, y + pageManager->topOfPage(pageNum) ) );
00292 }
00293 frame->moveBy( offset.x(), offset.y() );
00294 }
00295 return frame;
00296 }
00297
00298 KWFrame* KWOasisLoader::loadOasisTextBox( const QDomElement& frameTag, const QDomElement& tag,
00299 KoOasisContext& context )
00300 {
00301
00302
00303
00304
00305
00306
00307
00308 KWLoadingInfo* loadingInfo = m_doc->loadingInfo();
00309 KWTextFrameSet* fs = 0;
00310 QString frameName = frameTag.attributeNS( KoXmlNS::draw, "name", QString::null );
00311 QString chainNextName = tag.attributeNS( KoXmlNS::draw, "chain-next-name", QString::null );
00312 if ( !chainNextName.isEmpty() && loadingInfo ) {
00313 kdDebug(32001) << "Loading " << frameName << " : next-in-chain=" << chainNextName << endl;
00314
00315 KWFrame* nextFrame = loadingInfo->frameByName( chainNextName );
00316 if ( nextFrame ) {
00317 fs = dynamic_cast<KWTextFrameSet *>( nextFrame->frameSet() );
00318 chainNextName = QString::null;
00319 kdDebug(32001) << " found " << nextFrame << " -> frameset " << ( fs ? fs->name() : QString::null ) << endl;
00320 }
00321 }
00322 KWFrame* prevFrame = loadingInfo->chainPrevFrame( frameName );
00323
00324 if ( prevFrame ) {
00325 if ( fs )
00326 Q_ASSERT( fs == prevFrame->frameSet() );
00327 fs = dynamic_cast<KWTextFrameSet *>( prevFrame->frameSet() );
00328
00329 }
00330 KWFrame* frame = 0;
00331 if ( !fs ) {
00332 fs = new KWTextFrameSet( m_doc, frameTag, context );
00333 m_doc->addFrameSet( fs, false );
00334 frame = fs->loadOasis( frameTag, tag, context );
00335 } else {
00336 context.styleStack().save();
00337 context.fillStyleStack( frameTag, KoXmlNS::draw, "style-name", "graphic" );
00338 frame = fs->loadOasisTextFrame( frameTag, tag, context );
00339 context.styleStack().restore();
00340 }
00341
00342 loadingInfo->storeFrameName( frame, frameName );
00343
00344 if ( !chainNextName.isEmpty() ) {
00345 loadingInfo->storeNextFrame( frame, chainNextName );
00346 }
00347 return frame;
00348 }
00349
00350 KWTableFrameSet* KWOasisLoader::loadOasisTable( const QDomElement& tag,
00351 KoOasisContext& context )
00352 {
00353 const QString name = tag.attributeNS( KoXmlNS::table, "name", i18n( "Unnamed Table" ) );
00354 KWTableFrameSet* table = new KWTableFrameSet( m_doc, name );
00355 table->loadOasis( tag, context );
00356 m_doc->addFrameSet(table, false);
00357 return table;
00358 }