/* This file is part of the KDE project Copyright (C) 1998, 1999 Reginald Stadlbauer Copyright (C) 2002-2006 David Faure Copyright (C) 2005 Thomas Zander 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 "KWDocument.h" #include "KWordDocIface.h" #include "KWBgSpellCheck.h" #include "KoTextBookmark.h" #include "KWCanvas.h" #include "KWCommand.h" #include "KWFormulaFrameSet.h" #include "KWFrameLayout.h" #include "KWPictureFrameSet.h" #include "KWPartFrameSet.h" #include "KWTableFrameSet.h" #include "KWTableStyle.h" #include "KWTableTemplate.h" #include "KWTextImage.h" #include "KWVariable.h" #include "KWView.h" #include "KWViewMode.h" #include "KWMailMergeDataBase.h" #include "KWLoadingInfo.h" #include "KWCollectFramesetsVisitor.h" #include "KWOasisLoader.h" #include "KWOasisSaver.h" #include "KWFrameList.h" #include "KWPageManager.h" #include "KWPage.h" #include "KWFrameView.h" #include "KWFrameViewManager.h" #include "KWStartupWidget.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include //#define DEBUG_PAGES //#define DEBUG_SPEED // Make sure an appropriate DTD is available in www/koffice/DTD if changing this value static const char * CURRENT_DTD_VERSION = "1.2"; /******************************************************************/ /* Class: KWCommandHistory */ /******************************************************************/ class KWCommandHistory : public KoCommandHistory { public: KWCommandHistory( KWDocument * doc ) : KoCommandHistory( doc->actionCollection(), true ), m_pDoc( doc ) {} public /*slots*/: // They are already slots in the parent. Running moc on the inherited class shouldn't be necessary AFAICS. virtual void undo(); virtual void redo(); private: KWDocument * m_pDoc; }; void KWCommandHistory::undo() { m_pDoc->clearUndoRedoInfos(); KoCommandHistory::undo(); } void KWCommandHistory::redo() { m_pDoc->clearUndoRedoInfos(); KoCommandHistory::redo(); } /******************************************************************/ /* Class: KWDocument */ /******************************************************************/ void KWDocument::clearUndoRedoInfos() { TQPtrListIterator fit = framesetsIterator(); for ( ; fit.current() ; ++fit ) { KWTextFrameSet *fs = dynamic_cast( fit.current() ); if ( fs ) fs->clearUndoRedoInfo(); } } /** * Temporary storage for the initial edition info * (activeFrameset, cursorParagraph and cursorIndex attributes of the XML) */ class KWDocument::InitialEditing { public: TQString m_initialFrameSet; int m_initialCursorParag; int m_initialCursorIndex; }; const int KWDocument::CURRENT_SYNTAX_VERSION = 3; KWDocument::KWDocument(TQWidget *parentWidget, const char *widname, TQObject* parent, const char* name, bool singleViewMode ) : KoDocument( parentWidget, widname, parent, name, singleViewMode ), m_urlIntern() { KWStatisticVariable::setExtendedType( true ); dcop = 0; m_framesChangedHandler = 0; m_pageManager = new KWPageManager(); m_pageManager->appendPage(); m_loadingInfo = 0L; m_tabStop = MM_TO_POINT( 15.0 ); m_processingType = WP; // varFormats.setAutoDelete(true); m_lstFrameSet.setAutoDelete( true ); // m_textImageRequests does not create or delete the KWTextImage classes m_textImageRequests.setAutoDelete(false); m_styleColl = new KoStyleCollection(); m_frameStyleColl = new KWFrameStyleCollection(); m_tableStyleColl = new KWTableStyleCollection(); m_tableTemplateColl = new KWTableTemplateCollection(); m_pictureCollection = new KoPictureCollection(); m_personalExpressionPath = KWFactory::instance()->dirs()->resourceDirs("expression"); m_bShowGrid = false; m_bSnapToGrid = false; setInstance( KWFactory::instance(), false ); setTemplateType( "kword_template" ); m_gridX = m_gridY = MM_TO_POINT(5.0 ); m_indent = MM_TO_POINT( 10.0 ); m_iNbPagePerRow = 4; m_maxRecentFiles = 10; m_bShowRuler = true; m_footNoteSeparatorLinePos=SLP_LEFT; m_viewFormattingChars = false; m_viewFormattingEndParag = true; m_viewFormattingSpace = true; m_viewFormattingTabs = true; m_viewFormattingBreak = true; m_viewFrameBorders = true; m_repaintAllViewsPending = false; m_recalcFramesPending = -1; m_bShowDocStruct = true; m_bShowRuler = true; m_bShowStatusBar = true; m_bAllowAutoFormat = true; m_pgUpDownMovesCaret = true; m_bShowScrollBar = true; m_cursorInProtectectedArea = true; m_bHasEndNotes = false; m_bInsertDirectCursor=false; m_globalLanguage = TDEGlobal::locale()->language(); m_bGlobalHyphenation = false; m_bGeneratingPreview = false; m_viewModeType="ModeNormal"; m_layoutViewMode = 0; m_commandHistory = new KWCommandHistory( this ); connect( m_commandHistory, TQ_SIGNAL( documentRestored() ), this, TQ_SLOT( slotDocumentRestored() ) ); connect( m_commandHistory, TQ_SIGNAL( commandExecuted() ), this, TQ_SLOT( slotCommandExecuted() ) ); //styleMask = U_FONT_FAMILY_ALL_SIZE | U_COLOR | U_BORDER | U_INDENT | // U_NUMBERING | U_ALIGN | U_TABS | U_SMART; m_headerVisible = false; m_footerVisible = false; m_pasteFramesetsMap = 0L; m_initialEditing = 0L; m_bufPixmap = 0L; m_varFormatCollection = new KoVariableFormatCollection; m_varColl = new KWVariableCollection( new KWVariableSettings(), m_varFormatCollection ); m_autoFormat = new KoAutoFormat(this,m_varColl,m_varFormatCollection ); m_bgSpellCheck = new KWBgSpellCheck(this); m_slDataBase = new KWMailMergeDataBase( this ); m_bookmarkList = new KoTextBookmarkList; slRecordNum = -1; m_syntaxVersion = CURRENT_SYNTAX_VERSION; m_hasTOC=false; // It's important to call this to have the kformula actions // created. The real document is still to be created if needed. m_formulaDocumentWrapper = new KFormula::DocumentWrapper( instance()->config(), actionCollection(), m_commandHistory ); setEmpty(); setModified(false); initConfig(); // Get default font from the KWord config file TDEConfig *config = KWFactory::instance()->config(); config->setGroup("Document defaults" ); TQString defaultFontname=config->readEntry("DefaultFont"); if ( !defaultFontname.isEmpty() ) m_defaultFont.fromString( defaultFontname ); // If not found, we automatically fallback to the application font (the one from KControl's font module) // Try to force a scalable font. m_defaultFont.setStyleStrategy( TQFont::ForceOutline ); int ptSize = m_defaultFont.pointSize(); if ( ptSize == -1 ) // specified with a pixel size ? ptSize = TQFontInfo(m_defaultFont).pointSize(); //kdDebug() << "Default font: requested family: " << m_defaultFont.family() << endl; //kdDebug() << "Default font: real family: " << TQFontInfo(m_defaultFont).family() << endl; if ( name ) dcopObject(); } DCOPObject* KWDocument::dcopObject() { if ( !dcop ) dcop = new KWordDocIface( this ); return dcop; } KWDocument::~KWDocument() { //don't save config when kword is embedded into konqueror if(isReadWrite()) saveConfig(); // formula frames have to be deleted before m_formulaDocumentWrapper m_lstFrameSet.clear(); delete m_loadingInfo; delete m_autoFormat; delete m_formulaDocumentWrapper; delete m_commandHistory; delete m_varColl; delete m_varFormatCollection; delete m_slDataBase; delete dcop; delete m_bgSpellCheck; delete m_styleColl; delete m_frameStyleColl; delete m_tableStyleColl; delete m_tableTemplateColl; delete m_layoutViewMode; delete m_bufPixmap; delete m_pictureCollection; delete m_pageManager; delete m_bookmarkList; } void KWDocument::initConfig() { TDEConfig *config = KWFactory::instance()->config(); if( config->hasGroup("KSpell kword" ) ) { config->setGroup( "KSpell kword" ); // Default is false for spellcheck, but the spell-check config dialog // should write out "true" when the user configures spell checking. if ( isReadWrite() ) m_bgSpellCheck->setEnabled(config->readBoolEntry( "SpellCheck", false )); else m_bgSpellCheck->setEnabled( false ); } if(config->hasGroup("Interface" ) ) { config->setGroup( "Interface" ); setGridY(TQMAX( config->readDoubleNumEntry("GridY",MM_TO_POINT(5.0) ), 0.1)); setGridX(TQMAX( config->readDoubleNumEntry("GridX",MM_TO_POINT(5.0) ), 0.1)); setCursorInProtectedArea( config->readBoolEntry( "cursorInProtectArea", true )); // Config-file value in mm, default 10 pt double indent = config->readDoubleNumEntry("Indent", MM_TO_POINT(10.0) ) ; setIndentValue(indent); setShowRuler(config->readBoolEntry("Rulers",true)); int defaultAutoSave = KoDocument::defaultAutoSave()/60; // in minutes setAutoSave(config->readNumEntry("AutoSave",defaultAutoSave)*60); // read key in minutes, call setAutoSave(seconds) setBackupFile( config->readBoolEntry("BackupFile", true) ); setNbPagePerRow(config->readNumEntry("nbPagePerRow",4)); m_maxRecentFiles = config->readNumEntry( "NbRecentFile", 10 ); m_viewFormattingChars = config->readBoolEntry( "ViewFormattingChars", false ); m_viewFormattingBreak = config->readBoolEntry( "ViewFormattingBreaks", true ); m_viewFormattingSpace = config->readBoolEntry( "ViewFormattingSpace", true ); m_viewFormattingEndParag = config->readBoolEntry( "ViewFormattingEndParag", true ); m_viewFormattingTabs = config->readBoolEntry( "ViewFormattingTabs", true ); m_viewFrameBorders = config->readBoolEntry( "ViewFrameBorders", true ); m_zoom = config->readNumEntry( "Zoom", 100 ); m_zoomMode = static_cast ( config->readNumEntry( "ZoomMode", KoZoomMode::ZOOM_CONSTANT ) ); m_bShowDocStruct = config->readBoolEntry( "showDocStruct", true ); m_viewModeType = config->readEntry( "viewmode", "ModeNormal" ); setShowStatusBar( config->readBoolEntry( "ShowStatusBar" , true ) ); setAllowAutoFormat( config->readBoolEntry( "AllowAutoFormat" , true ) ); setShowScrollBar( config->readBoolEntry( "ShowScrollBar", true ) ); if ( isEmbedded() ) m_bShowDocStruct = false; // off by default for embedded docs, but still toggleable m_pgUpDownMovesCaret = config->readBoolEntry( "PgUpDownMovesCaret", true ); m_bInsertDirectCursor= config->readBoolEntry( "InsertDirectCursor", false ); m_globalLanguage=config->readEntry("language", TDEGlobal::locale()->language()); m_bGlobalHyphenation=config->readBoolEntry("hyphenation", false); setShowGrid( config->readBoolEntry( "ShowGrid" , false )); setSnapToGrid( config->readBoolEntry( "SnapToGrid", false )); setGridX( config->readDoubleNumEntry( "ResolutionX", MM_TO_POINT( 5.0 ) )); setGridY( config->readDoubleNumEntry( "ResolutionY", MM_TO_POINT( 5.0 ) )); } else { m_zoom = 100; m_zoomMode = KoZoomMode::ZOOM_WIDTH; } int undo=30; if(config->hasGroup("Misc" ) ) { config->setGroup( "Misc" ); undo=config->readNumEntry("UndoRedo",-1); //load default unit setting - this is only used for new files (from templates) or empty files if ( config->hasKey( "Units" ) ) setUnit( KoUnit::unit( config->readEntry("Units") ) ); m_defaultColumnSpacing = config->readDoubleNumEntry( "ColumnSpacing", 3.0 ); } if(undo!=-1) setUndoRedoLimit(undo); setZoomAndResolution( m_zoom, KoGlobal::dpiX(), KoGlobal::dpiY() ); //text mode view is not a good default for a readonly document... if ( !isReadWrite() && m_viewModeType =="ModeText" ) m_viewModeType= "ModeNormal"; m_layoutViewMode = KWViewMode::create( m_viewModeType, this, 0 /*no canvas*/); if(config->hasGroup("Kword Path" ) ) { config->setGroup( "Kword Path" ); if ( config->hasKey( "expression path" ) ) m_personalExpressionPath = config->readPathListEntry( "expression path" ); setBackupPath(config->readPathEntry( "backup path" )); } // Load personal dict TDEConfigGroup group( KoGlobal::kofficeConfig(), "Spelling" ); m_spellCheckPersonalDict = group.readListEntry( "PersonalDict" ); } void KWDocument::saveConfig() { if ( !isReadWrite() ) return; TDEConfigGroup group( KoGlobal::kofficeConfig(), "Spelling" ); group.writeEntry( "PersonalDict", m_spellCheckPersonalDict ); if ( !isEmbedded() ) { // Only save the config that is manipulated by the UI directly. // The config from the config dialog is saved by the dialog itself. TDEConfig *config = KWFactory::instance()->config(); config->setGroup( "Interface" ); config->writeEntry( "ViewFormattingChars", m_viewFormattingChars ); config->writeEntry( "ViewFormattingBreaks", m_viewFormattingBreak ); config->writeEntry( "ViewFormattingEndParag", m_viewFormattingEndParag ); config->writeEntry( "ViewFormattingTabs", m_viewFormattingTabs ); config->writeEntry( "ViewFormattingSpace", m_viewFormattingSpace ); config->writeEntry( "ViewFrameBorders", m_viewFrameBorders ); config->writeEntry( "Zoom", m_zoom ); config->writeEntry( "ZoomMode", m_zoomMode ); config->writeEntry( "showDocStruct", m_bShowDocStruct ); config->writeEntry( "Rulers", m_bShowRuler ); config->writeEntry( "viewmode", m_viewModeType) ; config->writeEntry( "AllowAutoFormat", m_bAllowAutoFormat ); config->writeEntry( "ShowGrid" , m_bShowGrid ); config->writeEntry( "SnapToGrid" , m_bSnapToGrid ); config->writeEntry( "ResolutionX", m_gridX ); config->writeEntry( "ResolutionY", m_gridY ); } } void KWDocument::setZoomAndResolution( int zoom, int dpiX, int dpiY ) { KoTextZoomHandler::setZoomAndResolution( zoom, dpiX, dpiY ); if ( KFormula::Document* formulaDocument = m_formulaDocumentWrapper->document() ) formulaDocument->setZoomAndResolution( zoom, dpiX, dpiY ); } KWTextFrameSet * KWDocument::textFrameSet ( unsigned int num ) const { unsigned int i=0; TQPtrListIterator fit = framesetsIterator(); for ( ; fit.current() ; ++fit ) { if(fit.current()->isDeleted()) continue; if(fit.current()->type()==FT_TEXT) { if(i==num) return static_cast(fit.current()); i++; } } return static_cast(m_lstFrameSet.getFirst()); } void KWDocument::newZoomAndResolution( bool updateViews, bool forPrint ) { if ( KFormula::Document* formulaDocument = m_formulaDocumentWrapper->document() ) formulaDocument->newZoomAndResolution( updateViews,forPrint ); #if 0 TQPtrListIterator fit = framesetsIterator(); for ( ; fit.current() ; ++fit ) fit.current()->zoom( forPrint ); #endif // First recalc all frames (including the kotextdocument width) updateAllFrames(); // Then relayout the text inside the frames layout(); if ( updateViews ) { emit newContentsSize(); repaintAllViews( true ); } } bool KWDocument::initDoc(InitDocFlags flags, TQWidget* parentWidget) { m_pageColumns.columns = 1; m_pageColumns.ptColumnSpacing = m_defaultColumnSpacing; m_pageHeaderFooter.header = HF_SAME; m_pageHeaderFooter.footer = HF_SAME; m_pageHeaderFooter.ptHeaderBodySpacing = 10; m_pageHeaderFooter.ptFooterBodySpacing = 10; m_pageHeaderFooter.ptFootNoteBodySpacing = 10; bool ok = FALSE; if ( isEmbedded() ) { TQString fileName( locate( "kword_template", "Normal/.source/Embedded.kwt" , KWFactory::instance() ) ); resetURL(); ok = loadNativeFormat( fileName ); if ( !ok ) showLoadingErrorDialog(); setEmpty(); setModified( FALSE ); return ok; } else if (flags==KoDocument::InitDocEmpty) { TQString fileName( locate( "kword_template", "Normal/.source/PlainText.kwt" , KWFactory::instance() ) ); resetURL(); ok = loadNativeFormat( fileName ); if ( !ok ) showLoadingErrorDialog(); setEmpty(); setModified( FALSE ); return ok; } KoTemplateChooseDia::DialogType dlgtype; if (flags != KoDocument::InitDocFileNew) dlgtype = KoTemplateChooseDia::Everything; else dlgtype = KoTemplateChooseDia::OnlyTemplates; TQString file; KoTemplateChooseDia::ReturnType ret = KoTemplateChooseDia::choose( KWFactory::instance(), file, dlgtype, "kword_template", parentWidget ); if ( ret == KoTemplateChooseDia::Template ) { resetURL(); ok = loadNativeFormat( file ); if ( !ok ) showLoadingErrorDialog(); setEmpty(); } else if ( ret == KoTemplateChooseDia::File ) { KURL url( file ); //kdDebug() << "KWDocument::initDoc opening URL " << url.prettyURL() << endl; ok = openURL( url ); } else if ( ret == KoTemplateChooseDia::Empty ) { TQString fileName( locate( "kword_template", "Normal/.source/PlainText.kwt" , KWFactory::instance() ) ); resetURL(); ok = loadNativeFormat( fileName ); if ( !ok ) showLoadingErrorDialog(); setEmpty(); } setModified( FALSE ); return ok; } void KWDocument::openExistingFile( const TQString& file ) { m_pageColumns.columns = 1; m_pageColumns.ptColumnSpacing = m_defaultColumnSpacing; m_pageHeaderFooter.header = HF_SAME; m_pageHeaderFooter.footer = HF_SAME; m_pageHeaderFooter.ptHeaderBodySpacing = 10; m_pageHeaderFooter.ptFooterBodySpacing = 10; m_pageHeaderFooter.ptFootNoteBodySpacing = 10; KoDocument::openExistingFile( file ); } void KWDocument::openTemplate( const TQString& file ) { m_pageColumns.columns = 1; m_pageColumns.ptColumnSpacing = m_defaultColumnSpacing; m_pageHeaderFooter.header = HF_SAME; m_pageHeaderFooter.footer = HF_SAME; m_pageHeaderFooter.ptHeaderBodySpacing = 10; m_pageHeaderFooter.ptFooterBodySpacing = 10; m_pageHeaderFooter.ptFootNoteBodySpacing = 10; KoDocument::openTemplate( file ); } void KWDocument::initEmpty() { m_pageColumns.columns = 1; m_pageColumns.ptColumnSpacing = m_defaultColumnSpacing; m_pageHeaderFooter.header = HF_SAME; m_pageHeaderFooter.footer = HF_SAME; m_pageHeaderFooter.ptHeaderBodySpacing = 10; m_pageHeaderFooter.ptFooterBodySpacing = 10; m_pageHeaderFooter.ptFootNoteBodySpacing = 10; TQString fileName( locate( "kword_template", "Normal/.source/PlainText.kwt" , KWFactory::instance() ) ); bool ok = loadNativeFormat( fileName ); if ( !ok ) showLoadingErrorDialog(); resetURL(); setModified( FALSE ); setEmpty(); } KoPageLayout KWDocument::pageLayout(int pageNumber /* = 0 */) const { if( pageNumber < startPage()) // impossible page.. pageNumber = startPage(); return pageManager()->pageLayout(pageNumber); } void KWDocument::setPageLayout( const KoPageLayout& layout, const KoColumns& cl, const KoKWHeaderFooter& hf, bool updateViews ) { m_pageLayout = layout; if ( m_processingType == WP ) { m_pageColumns = cl; } if ( m_processingType == DTP || isEmbedded() ) { m_pageLayout.ptLeft = 0; m_pageLayout.ptRight = 0; m_pageLayout.ptTop = 0; m_pageLayout.ptBottom = 0; } pageManager()->setDefaultPage(m_pageLayout); m_pageHeaderFooter = hf; // pages have a different size -> update framesInPage // TODO: it would be better to move stuff so that text boxes remain in the same page... // (page-number preservation instead of Y preservation) updateAllFrames( KWFrameSet::UpdateFramesInPage ); recalcFrames(); updateAllFrames(); if ( updateViews ) { // Invalidate document layout, for proper repaint this->layout(); emit pageLayoutChanged( m_pageLayout ); updateContentsSize(); } } double KWDocument::ptColumnWidth() const { KWPage *page = pageManager()->page(pageManager()->startPage()); return ( page->width() - page->leftMargin() - page->rightMargin() - ptColumnSpacing() * ( m_pageColumns.columns - 1 ) ) / m_pageColumns.columns; } class KWFootNoteFrameSetList : public TQPtrList { public: KWFootNoteFrameSetList( bool reversed ) : m_reversed( reversed ) {} protected: // Compare the order of the associated variables virtual int compareItems(TQPtrCollection::Item a, TQPtrCollection::Item b) { KWFootNoteFrameSet* fsa = ((KWFootNoteFrameSet *)a); KWFootNoteFrameSet* fsb = ((KWFootNoteFrameSet *)b); Q_ASSERT( fsa->footNoteVariable() ); Q_ASSERT( fsb->footNoteVariable() ); if ( fsa->footNoteVariable() && fsb->footNoteVariable() ) { int numa = fsa->footNoteVariable()->num(); int numb = fsb->footNoteVariable()->num(); if (numa == numb) return 0; if (numa > numb) return m_reversed ? -1 : 1; return m_reversed ? 1 : -1; } return -1; // whatever } private: bool m_reversed; }; /* append headers and footers if needed, and create enough pages for all the existing frames */ void KWDocument::recalcFrames( int fromPage, int toPage /*-1 for all*/, uint flags ) { fromPage = TQMAX(pageManager()->startPage(), fromPage); if ( m_lstFrameSet.isEmpty() ) return; //printDebug(); kdDebug(32002) << "KWDocument::recalcFrames from=" << fromPage << " to=" << toPage << endl; KWFrameSet *frameset = m_lstFrameSet.getFirst(); if ( m_processingType == WP ) { // In WP mode the pages are created automatically. In DTP not... KWTextFrameSet *firstHeader = 0L, *evenHeader = 0L, *oddHeader = 0L; KWTextFrameSet *firstFooter = 0L, *evenFooter = 0L, *oddFooter = 0L; m_bHasEndNotes = false; // will be set to true if we find any endnote // Lookup the various header / footer framesets into the variables above // [Done in all cases, in order to hide unused framesets] KWFootNoteFrameSetList footnotesList( true ); // Reversed, we want footnotes from bottom to top KWFootNoteFrameSetList endnotesList( false ); // Endnotes are in top to bottom order TQPtrListIterator fit = framesetsIterator(); for ( ; fit.current() ; ++fit ) { KWFrameSet * fs = fit.current(); switch ( fs->frameSetInfo() ) { case KWFrameSet::FI_FIRST_HEADER: if ( isHeaderVisible() ) { firstHeader = dynamic_cast( fs ); } else { fs->setVisible( false ); fs->deleteAllCopies(); } break; case KWFrameSet::FI_ODD_HEADER: if ( isHeaderVisible() ) { oddHeader = dynamic_cast( fs ); } else { fs->setVisible( false ); fs->deleteAllCopies(); } break; case KWFrameSet::FI_EVEN_HEADER: if ( isHeaderVisible() ) { evenHeader = dynamic_cast( fs ); } else { fs->setVisible( false ); fs->deleteAllCopies(); } break; case KWFrameSet::FI_FIRST_FOOTER: if ( isFooterVisible() ) { firstFooter = dynamic_cast( fs ); } else { fs->setVisible( false ); fs->deleteAllCopies(); } break; case KWFrameSet::FI_ODD_FOOTER: if ( isFooterVisible() ) { oddFooter = dynamic_cast( fs ); } else { fs->setVisible( false ); fs->deleteAllCopies(); } break; case KWFrameSet::FI_EVEN_FOOTER: if ( isFooterVisible() ) { evenFooter = dynamic_cast( fs ); } else { fs->setVisible( false ); fs->deleteAllCopies(); } break; case KWFrameSet::FI_FOOTNOTE: { KWFootNoteFrameSet* fnfs = dynamic_cast(fs); if ( fnfs && fnfs->isVisible() ) // not visible is when the footnote has been deleted { if ( fnfs->isFootNote() ) footnotesList.append( fnfs ); else if ( fnfs->isEndNote() ) { endnotesList.append( fnfs ); m_bHasEndNotes = true; } } } break; default: break; } } // This allocation each time might slow things down a bit. // TODO KWHeaderFooterFrameSet : public KWTextFrameSet, and store the HeaderFooterFrameset data into there. // ... hmm, and then KWFootNoteFrameSet needs to inherit KWHeaderFooterFrameSet TQPtrList headerFooterList; headerFooterList.setAutoDelete( true ); const int firstPageNum = startPage(); // Now hide & forget the unused header/footer framesets (e.g. 'odd pages' if we are in 'all the same' mode etc.) if ( isHeaderVisible() ) { Q_ASSERT( firstHeader ); Q_ASSERT( oddHeader ); Q_ASSERT( evenHeader ); switch ( headerType() ) { case HF_SAME: oddHeader->setVisible( true ); evenHeader->setVisible( false ); evenHeader->deleteAllCopies(); firstHeader->setVisible( false ); firstHeader->deleteAllCopies(); headerFooterList.append( new KWFrameLayout::HeaderFooterFrameset( oddHeader, firstPageNum, -1, m_pageHeaderFooter.ptHeaderBodySpacing ) ); break; case HF_FIRST_EO_DIFF: // added for koffice-1.2-beta2 firstHeader->setVisible( true ); oddHeader->setVisible( true ); evenHeader->setVisible( true ); headerFooterList.append( new KWFrameLayout::HeaderFooterFrameset( firstHeader, firstPageNum, firstPageNum, m_pageHeaderFooter.ptHeaderBodySpacing ) ); headerFooterList.append( new KWFrameLayout::HeaderFooterFrameset( oddHeader, firstPageNum + 2, -1, m_pageHeaderFooter.ptHeaderBodySpacing, KWFrameLayout::HeaderFooterFrameset::Odd ) ); headerFooterList.append( new KWFrameLayout::HeaderFooterFrameset( evenHeader, firstPageNum + 1, -1, m_pageHeaderFooter.ptHeaderBodySpacing, KWFrameLayout::HeaderFooterFrameset::Even ) ); break; case HF_FIRST_DIFF: oddHeader->setVisible( true ); evenHeader->setVisible( false ); evenHeader->deleteAllCopies(); firstHeader->setVisible( true ); headerFooterList.append( new KWFrameLayout::HeaderFooterFrameset( firstHeader, firstPageNum, firstPageNum, m_pageHeaderFooter.ptHeaderBodySpacing ) ); headerFooterList.append( new KWFrameLayout::HeaderFooterFrameset( oddHeader, firstPageNum + 1, -1, m_pageHeaderFooter.ptHeaderBodySpacing ) ); break; case HF_EO_DIFF: oddHeader->setVisible( true ); evenHeader->setVisible( true ); firstHeader->setVisible( false ); firstHeader->deleteAllCopies(); headerFooterList.append( new KWFrameLayout::HeaderFooterFrameset( oddHeader, firstPageNum, -1, m_pageHeaderFooter.ptHeaderBodySpacing, KWFrameLayout::HeaderFooterFrameset::Odd ) ); headerFooterList.append( new KWFrameLayout::HeaderFooterFrameset( evenHeader, firstPageNum + 1, -1, m_pageHeaderFooter.ptHeaderBodySpacing, KWFrameLayout::HeaderFooterFrameset::Even ) ); break; } } if ( isFooterVisible() ) { Q_ASSERT( firstFooter ); Q_ASSERT( oddFooter ); Q_ASSERT( evenFooter ); switch ( footerType() ) { case HF_SAME: oddFooter->setVisible( true ); evenFooter->setVisible( false ); evenFooter->deleteAllCopies(); firstFooter->setVisible( false ); firstFooter->deleteAllCopies(); headerFooterList.append( new KWFrameLayout::HeaderFooterFrameset( oddFooter, firstPageNum, -1, m_pageHeaderFooter.ptFooterBodySpacing ) ); break; case HF_FIRST_EO_DIFF: // added for koffice-1.2-beta2 firstFooter->setVisible( true ); oddFooter->setVisible( true ); evenFooter->setVisible( true ); headerFooterList.append( new KWFrameLayout::HeaderFooterFrameset( firstFooter, firstPageNum, firstPageNum, m_pageHeaderFooter.ptFooterBodySpacing ) ); headerFooterList.append( new KWFrameLayout::HeaderFooterFrameset( oddFooter, firstPageNum + 2, -1, m_pageHeaderFooter.ptFooterBodySpacing, KWFrameLayout::HeaderFooterFrameset::Odd ) ); headerFooterList.append( new KWFrameLayout::HeaderFooterFrameset( evenFooter, firstPageNum + 1, -1, m_pageHeaderFooter.ptFooterBodySpacing, KWFrameLayout::HeaderFooterFrameset::Even ) ); break; case HF_FIRST_DIFF: oddFooter->setVisible( true ); evenFooter->setVisible( false ); evenFooter->deleteAllCopies(); firstFooter->setVisible( true ); headerFooterList.append( new KWFrameLayout::HeaderFooterFrameset( firstFooter, firstPageNum, firstPageNum, m_pageHeaderFooter.ptFooterBodySpacing ) ); headerFooterList.append( new KWFrameLayout::HeaderFooterFrameset( oddFooter, firstPageNum + 1, -1, m_pageHeaderFooter.ptFooterBodySpacing ) ); break; case HF_EO_DIFF: oddFooter->setVisible( true ); evenFooter->setVisible( true ); firstFooter->setVisible( false ); firstFooter->deleteAllCopies(); headerFooterList.append( new KWFrameLayout::HeaderFooterFrameset( oddFooter, firstPageNum, -1, m_pageHeaderFooter.ptFooterBodySpacing, KWFrameLayout::HeaderFooterFrameset::Odd ) ); headerFooterList.append( new KWFrameLayout::HeaderFooterFrameset( evenFooter, firstPageNum + 1, -1, m_pageHeaderFooter.ptFooterBodySpacing, KWFrameLayout::HeaderFooterFrameset::Even ) ); break; } } // The frameset order _on screen_ is: // Header // Main text frame (if WP) // Footnote_s_ // Footer // In the list it will have to be from top and from bottom: // Header, Footer, Footnote from bottom to top TQPtrList footnotesHFList; footnotesHFList.setAutoDelete( true ); footnotesList.sort(); TQPtrListIterator fnfsIt( footnotesList ); // fnfs == "footnote frameset" for ( ; fnfsIt.current() ; ++fnfsIt ) { KWFootNoteFrameSet* fnfs = fnfsIt.current(); int pageNum = -42; //fnfs->footNoteVariable()->pageNumber(); // determined by KWFrameLayout KWFrameLayout::HeaderFooterFrameset* hff = new KWFrameLayout::HeaderFooterFrameset( fnfs, pageNum, pageNum, m_pageHeaderFooter.ptFootNoteBodySpacing, KWFrameLayout::HeaderFooterFrameset::All ); // With other kind of framesets, the height is simply frame->height. // But for footnotes, the height to pass to KWFrameLayout is the sum of the frame heights. hff->m_height = 0; for (TQPtrListIterator f = fnfs->frameIterator(); f.current() ; ++f ) hff->m_height += f.current()->height(); footnotesHFList.append( hff ); } // Endnotes, however are laid out from top to bottom. TQPtrList endnotesHFList; endnotesHFList.setAutoDelete( true ); endnotesList.sort(); TQPtrListIterator enfsIt( endnotesList ); // enfs == "endnote frameset" for ( ; enfsIt.current() ; ++enfsIt ) { KWFootNoteFrameSet* enfs = enfsIt.current(); KWFrameLayout::HeaderFooterFrameset* hff = new KWFrameLayout::HeaderFooterFrameset( enfs, -42, -42, // determined by KWFrameLayout m_pageHeaderFooter.ptFootNoteBodySpacing, KWFrameLayout::HeaderFooterFrameset::All ); // The height to pass to KWFrameLayout is the sum of the frame heights. hff->m_height = 0; for (TQPtrListIterator f = enfs->frameIterator(); f.current() ; ++f ) hff->m_height += f.current()->height(); endnotesHFList.append( hff ); } // append pages as needed. double maxBottom = 0; for (TQPtrListIterator fsit = framesetsIterator(); fsit.current() ; ++fsit ) { KWFrameSet *fs = fsit.current(); if ( !fs->isVisible() || fs->isAHeader() || !fs->isAFooter() || !fs->isFloating() || !fs->isFootEndNote() ) continue; for (TQPtrListIterator fit = fs->frameIterator(); fit.current() ; ++fit ) maxBottom = TQMAX(maxBottom, fit.current()->bottom()); } KWPage *last = pageManager()->page(lastPage()); double docHeight = last->offsetInDocument() + last->height(); while(docHeight <= maxBottom) { last = pageManager()->appendPage(); docHeight += last->height(); } int oldPages = pageCount(); if ( toPage == -1 ) toPage = lastPage(); if ( fromPage > toPage ) // this can happen with "endnotes only" pages :) // ### really? fromPage = toPage; // ie. start at the last real page KWFrameLayout frameLayout( this, headerFooterList, footnotesHFList, endnotesHFList ); frameLayout.layout( frameset, m_pageColumns.columns, fromPage, toPage, flags ); // If the number of pages changed, update views and variables etc. // (now that the frame layout has been done) if ( pageCount() != oldPages && !m_bGeneratingPreview ) { // Very much like the end of appendPage, but we don't want to call recalcFrames ;) emit newContentsSize(); emit numPagesChanged(); recalcVariables( VT_PGNUM ); } } else { // DTP mode: calculate the number of pages from the frames. double maxBottom=0; for (TQPtrListIterator fit = framesetsIterator(); fit.current() ; ++fit ) { if(fit.current()->isDeleted()) continue; if(fit.current()->frameSetInfo()==KWFrameSet::FI_BODY && !fit.current()->isFloating()) { KWFrameSet * fs = fit.current(); for (TQPtrListIterator f = fs->frameIterator(); f.current() ; ++f ) maxBottom=TQMAX(maxBottom, f.current()->bottom()); } } KWPage *last = pageManager()->page(lastPage()); Q_ASSERT(last); if(last) { // hack to work around bug #132338 double docHeight = last->offsetInDocument() + last->height(); while(docHeight <= maxBottom) { last = pageManager()->appendPage(); docHeight += last->height(); } } if ( toPage == -1 ) toPage = pageCount() - 1; KWFrameList::recalcFrames(this, fromPage, toPage); } kdDebug(32002) << " ~recalcFrames" << endl; } bool KWDocument::loadChildren( KoStore *store ) { //kdDebug(32001) << "KWDocument::loadChildren" << endl; TQPtrListIterator it( children() ); for( ; it.current(); ++it ) { if ( !it.current()->loadDocument( store ) ) return FALSE; } return TRUE; } void KWDocument::loadPictureMap ( TQDomElement& domElement ) { m_pictureMap.clear(); // TQDomElement picturesElem = domElement.namedItem( "PICTURES" ).toElement(); if ( !picturesElem.isNull() ) { m_pictureCollection->readXML( picturesElem, m_pictureMap ); } // TQDomElement pixmapsElem = domElement.namedItem( "PIXMAPS" ).toElement(); if ( !pixmapsElem.isNull() ) { m_pictureCollection->readXML( pixmapsElem, m_pictureMap ); } // TQDomElement clipartsElem = domElement.namedItem( "CLIPARTS" ).toElement(); if ( !clipartsElem.isNull() ) { m_pictureCollection->readXML( pixmapsElem, m_pictureMap ); } } bool KWDocument::loadOasis( const TQDomDocument& doc, KoOasisStyles& oasisStyles, const TQDomDocument& settings, KoStore* store ) { TQTime dt; dt.start(); emit sigProgress( 0 ); clear(); kdDebug(32001) << "KWDocument::loadOasis" << endl; TQDomElement content = doc.documentElement(); TQDomElement realBody ( KoDom::namedItemNS( content, KoXmlNS::office, "body" ) ); if ( realBody.isNull() ) { kdError(32001) << "No office:body found!" << endl; setErrorMessage( i18n( "Invalid OASIS OpenDocument file. No office:body tag found." ) ); return false; } TQDomElement body = KoDom::namedItemNS( realBody, KoXmlNS::office, "text" ); if ( body.isNull() ) { kdError(32001) << "No office:text found!" << endl; TQDomElement childElem; TQString localName; forEachElement( childElem, realBody ) { localName = childElem.localName(); } if ( localName.isEmpty() ) setErrorMessage( i18n( "Invalid OASIS OpenDocument file. No tag found inside office:body." ) ); else setErrorMessage( i18n( "This is not a word processing document, but %1. Please try opening it with the appropriate application." ).arg( KoDocument::tagNameToDocumentType( localName ) ) ); return false; } // TODO check versions and mimetypes etc. KoOasisContext context( this, *m_varColl, oasisStyles, store ); createLoadingInfo(); // In theory the page format is the style:master-page-name of the first paragraph... // But, hmm, in a doc with only a table there was no reference to the master page at all... // So we load the standard page layout to start with, and in KWTextParag // we might overwrite it with another one. m_loadingInfo->m_currentMasterPage = "Standard"; if ( !loadOasisPageLayout( m_loadingInfo->m_currentMasterPage, context ) ) return false; KWOasisLoader oasisLoader( this ); // oasis extension for DTP (2003-10-27 post by Daniel) m_processingType = ( !KoDom::namedItemNS( body, KoXmlNS::text, "page-sequence" ).isNull() ) ? DTP : WP; m_hasTOC = false; m_tabStop = MM_TO_POINT(15); const TQDomElement* defaultParagStyle = oasisStyles.defaultStyle( "paragraph" ); if ( defaultParagStyle ) { KoStyleStack stack; stack.push( *defaultParagStyle ); stack.setTypeProperties( "paragraph" ); TQString tabStopVal = stack.attributeNS( KoXmlNS::style, "tab-stop-distance" ); if ( !tabStopVal.isEmpty() ) m_tabStop = KoUnit::parseValue( tabStopVal ); } m_initialEditing = 0; // TODO MAILMERGE // Variable settings // By default display real variable value if ( !isReadWrite()) m_varColl->variableSetting()->setDisplayFieldCode(false); // Load all styles before the corresponding paragraphs try to use them! m_styleColl->loadOasisStyles( context ); if ( m_frameStyleColl->loadOasisStyles( context ) == 0 ) { // no styles loaded -> load default styles loadDefaultFrameStyleTemplates(); } if ( m_tableStyleColl->loadOasisStyles( context, *m_styleColl, *m_frameStyleColl ) == 0 ) { // no styles loaded -> load default styles loadDefaultTableStyleTemplates(); } static_cast( m_varColl->variableSetting() ) ->loadNoteConfiguration( oasisStyles.officeStyle() ); loadDefaultTableTemplates(); if ( m_processingType == WP ) { // Create main frameset KWTextFrameSet *fs = new KWTextFrameSet( this, i18n( "Main Text Frameset" ) ); m_lstFrameSet.append( fs ); // don't use addFrameSet here. We'll call finalize() once and for all in completeLoading fs->loadOasisContent( body, context ); KWFrame* frame = new KWFrame( fs, 29, 42, 566-29, 798-42 ); frame->setFrameBehavior( KWFrame::AutoCreateNewFrame ); frame->setNewFrameBehavior( KWFrame::Reconnect ); fs->addFrame( frame ); // load padding, background and borders for the main frame const TQDomElement* masterPage = context.oasisStyles().masterPages()[ m_loadingInfo->m_currentMasterPage ]; const TQDomElement *masterPageStyle = masterPage ? context.oasisStyles().findStyle(masterPage->attributeNS( KoXmlNS::style, "page-layout-name", TQString() ) ) : 0; if ( masterPageStyle ) { KoStyleStack styleStack; styleStack.push( *masterPageStyle ); styleStack.setTypeProperties( "page-layout" ); frame->loadBorderProperties( styleStack ); } fs->renumberFootNotes( false /*no repaint*/ ); } else { // DTP mode: the items in the body are page-sequence and then frames TQDomElement tag; forEachElement( tag, body ) { context.styleStack().save(); const TQString localName = tag.localName(); if ( localName == "page-sequence" && tag.namespaceURI() == KoXmlNS::text ) { // We don't have support for changing the page layout yet, so just take the // number of pages int pages=1; TQDomElement page; forEachElement( page, tag ) ++pages; kdDebug() << "DTP mode: found " << pages << "pages" << endl; //setPageCount ( pages ); } else if ( localName == "frame" && tag.namespaceURI() == KoXmlNS::draw ) oasisLoader.loadFrame( tag, context, KoPoint() ); else kdWarning(32001) << "Unsupported tag in DTP loading:" << tag.tagName() << endl; } } if ( !loadMasterPageStyle( m_loadingInfo->m_currentMasterPage, context ) ) return false; if ( context.cursorTextParagraph() ) { // Maybe, once 1.3-support is dropped, we can get rid of InitialEditing and fetch the // values from KoOasisContext? But well, it lives a bit longer. // At least we could store a KWFrameSet* and a KoTextParag* instead of a name and an id. m_initialEditing = new InitialEditing(); KWTextFrameSet* fs = static_cast( context.cursorTextParagraph()->textDocument() )->textFrameSet(); m_initialEditing->m_initialFrameSet = fs->name(); m_initialEditing->m_initialCursorParag = context.cursorTextParagraph()->paragId(); m_initialEditing->m_initialCursorIndex = context.cursorTextIndex(); } if ( !settings.isNull() ) { oasisLoader.loadOasisSettings( settings ); } kdDebug(32001) << "Loading took " << (float)(dt.elapsed()) / 1000 << " seconds" << endl; endOfLoading(); // This sets the columns and header/footer flags, and calls recalcFrames, // so it must be done last. setPageLayout( m_pageLayout, m_loadingInfo->columns, m_loadingInfo->hf, false ); //printDebug(); return true; } bool KWDocument::loadOasisPageLayout( const TQString& masterPageName, KoOasisContext& context ) { KoColumns& columns = m_loadingInfo->columns; const KoOasisStyles& oasisStyles = context.oasisStyles(); const TQDomElement* masterPage = oasisStyles.masterPages()[ masterPageName ]; Q_ASSERT( masterPage ); const TQDomElement *masterPageStyle = masterPage ? oasisStyles.findStyle( masterPage->attributeNS( KoXmlNS::style, "page-layout-name", TQString() ) ) : 0; Q_ASSERT( masterPageStyle ); if ( masterPageStyle ) { m_pageLayout.loadOasis( *masterPageStyle ); pageManager()->setDefaultPage(m_pageLayout); const TQDomElement properties( KoDom::namedItemNS( *masterPageStyle, KoXmlNS::style, "page-layout-properties" ) ); const TQDomElement footnoteSep = KoDom::namedItemNS( properties, KoXmlNS::style, "footnote-sep" ); if ( !footnoteSep.isNull() ) { // style:width="0.018cm" style:distance-before-sep="0.101cm" // style:distance-after-sep="0.101cm" style:adjustment="left" // style:rel-width="25%" style:color="#000000" const TQString width = footnoteSep.attributeNS( KoXmlNS::style, "width", TQString() ); if ( !width.isEmpty() ) { m_footNoteSeparatorLineWidth = KoUnit::parseValue( width ); } TQString pageWidth = footnoteSep.attributeNS( KoXmlNS::style, "rel-width", TQString() ); if ( pageWidth.endsWith( "%" ) ) { pageWidth.truncate( pageWidth.length() - 1 ); // remove '%' m_iFootNoteSeparatorLineLength = tqRound( pageWidth.toDouble() ); } // Not in KWord: color, distance before and after separator const TQString style = footnoteSep.attributeNS( KoXmlNS::style, "line-style", TQString() ); if ( style == "solid" || style.isEmpty() ) m_footNoteSeparatorLineType = SLT_SOLID; else if ( style == "dash" ) m_footNoteSeparatorLineType = SLT_DASH; else if ( style == "dotted" ) m_footNoteSeparatorLineType = SLT_DOT; else if ( style == "dot-dash" ) m_footNoteSeparatorLineType = SLT_DASH_DOT; else if ( style == "dot-dot-dash" ) m_footNoteSeparatorLineType = SLT_DASH_DOT_DOT; else kdDebug() << "Unknown value for m_footNoteSeparatorLineType: " << style << endl; const TQString pos = footnoteSep.attributeNS( KoXmlNS::style, "adjustment", TQString() ); if ( pos == "centered" ) m_footNoteSeparatorLinePos = SLP_CENTERED; else if ( pos == "right") m_footNoteSeparatorLinePos = SLP_RIGHT; else // if ( pos == "left" ) m_footNoteSeparatorLinePos = SLP_LEFT; } const TQDomElement columnsElem = KoDom::namedItemNS( properties, KoXmlNS::style, "columns" ); if ( !columnsElem.isNull() ) { columns.columns = columnsElem.attributeNS( KoXmlNS::fo, "column-count", TQString() ).toInt(); if ( columns.columns == 0 ) columns.columns = 1; // TODO OASIS OpenDocument supports columns of different sizes, using // (with fo:start-indent/fo:end-indent for per-column spacing) // But well, it also allows us to specify a single gap. if ( columnsElem.hasAttributeNS( KoXmlNS::fo, "column-gap" ) ) columns.ptColumnSpacing = KoUnit::parseValue( columnsElem.attributeNS( KoXmlNS::fo, "column-gap", TQString() ) ); // It also supports drawing a vertical line as a separator... } m_headerVisible = false; m_footerVisible = false; // TODO spHeadBody (where is this in OOo?) // TODO spFootBody (where is this in OOo?) // Answer: margins of the element } else // this doesn't happen with normal documents, but it can happen if copying something, // pasting into konq as foo.odt, then opening that... { columns.columns = 1; columns.ptColumnSpacing = 2; m_headerVisible = false; m_footerVisible = false; m_pageLayout = KoPageLayout::standardLayout(); pageManager()->setDefaultPage(m_pageLayout); } return true; } bool KWDocument::loadMasterPageStyle( const TQString& masterPageName, KoOasisContext& context ) { const KoOasisStyles& oasisStyles = context.oasisStyles(); const TQDomElement* masterPage = oasisStyles.masterPages()[ masterPageName ]; Q_ASSERT( masterPage ); const TQDomElement *masterPageStyle = masterPage ? oasisStyles.findStyle( masterPage->attributeNS( KoXmlNS::style, "page-layout-name", TQString() ) ) : 0; Q_ASSERT( masterPageStyle ); // This check is done here and not in loadOasisPageLayout in case the Standard master-page // has no page information but the first paragraph points to a master-page that does (#129585) if ( m_pageLayout.ptWidth <= 1e-13 || m_pageLayout.ptHeight <= 1e-13 ) { // Loading page layout failed, try to see why. TQDomElement properties( KoDom::namedItemNS( *masterPageStyle, KoXmlNS::style, "page-layout-properties" ) ); //if ( properties.isNull() ) // setErrorMessage( i18n( "Invalid document. No page layout properties were found. The application which produced this document isn't OASIS-compliant." ) ); //else if ( properties.hasAttributeNS( KoXmlNS::fo, "page-width" ) ) // setErrorMessage( i18n( "Invalid document. Page layout has no page width. The application which produced this document isn't OASIS-compliant." ) ); //else if ( properties.hasAttributeNS( "http://www.w3.org/1999/XSL/Format", "page-width" ) ) setErrorMessage( i18n( "Invalid document. 'fo' has the wrong namespace. The application which produced this document is not OASIS-compliant." ) ); else setErrorMessage( i18n( "Invalid document. Paper size: %1x%2" ).arg( m_pageLayout.ptWidth ).arg( m_pageLayout.ptHeight ) ); return false; } KoKWHeaderFooter& hf = m_loadingInfo->hf; bool hasEvenOddHeader = false; bool hasEvenOddFooter = false; if ( masterPageStyle ) { KWOasisLoader oasisLoader( this ); TQDomElement headerStyle = KoDom::namedItemNS( *masterPageStyle, KoXmlNS::style, "header-style" ); TQDomElement footerStyle = KoDom::namedItemNS( *masterPageStyle, KoXmlNS::style, "footer-style" ); TQDomElement headerLeftElem = KoDom::namedItemNS( *masterPage, KoXmlNS::style, "header-left" ); TQDomElement headerFirstElem = KoDom::namedItemNS( *masterPage, KoXmlNS::style, "header-first" ); // hack, not oasis compliant const bool hasFirstHeader = !headerFirstElem.isNull(); if ( !headerLeftElem.isNull() ) { hasEvenOddHeader = true; hf.header = hasFirstHeader ? HF_FIRST_EO_DIFF : HF_EO_DIFF; oasisLoader.loadOasisHeaderFooter( headerLeftElem, hasEvenOddHeader, headerStyle, context ); } else { hf.header = hasFirstHeader ? HF_FIRST_DIFF : HF_SAME; } if ( hasFirstHeader ) { oasisLoader.loadOasisHeaderFooter( headerFirstElem, hasEvenOddHeader, headerStyle, context ); } TQDomElement headerElem = KoDom::namedItemNS( *masterPage, KoXmlNS::style, "header" ); if ( !headerElem.isNull() ) { oasisLoader.loadOasisHeaderFooter( headerElem, hasEvenOddHeader, headerStyle, context ); } // -- and now footers TQDomElement footerLeftElem = KoDom::namedItemNS( *masterPage, KoXmlNS::style, "footer-left" ); TQDomElement footerFirstElem = KoDom::namedItemNS( *masterPage, KoXmlNS::style, "footer-first" ); // hack, not oasis compliant const bool hasFirstFooter = !footerFirstElem.isNull(); if ( !footerLeftElem.isNull() ) { hasEvenOddFooter = true; hf.footer = hasFirstFooter ? HF_FIRST_EO_DIFF : HF_EO_DIFF; oasisLoader.loadOasisHeaderFooter( footerLeftElem, hasEvenOddFooter, footerStyle, context ); } else { hf.footer = hasFirstFooter ? HF_FIRST_DIFF : HF_SAME; } if ( hasFirstFooter ) { oasisLoader.loadOasisHeaderFooter( footerFirstElem, hasEvenOddFooter, footerStyle, context ); } TQDomElement footerElem = KoDom::namedItemNS( *masterPage, KoXmlNS::style, "footer" ); if ( !footerElem.isNull() ) { oasisLoader.loadOasisHeaderFooter( footerElem, hasEvenOddFooter, footerStyle, context ); } // The bottom margin of headers is what we call headerBodySpacing // (TODO support the 3 other margins) if ( !headerStyle.isNull() ) { context.styleStack().push( headerStyle ); context.styleStack().setTypeProperties( "header-footer" ); hf.ptHeaderBodySpacing = KoUnit::parseValue( context.styleStack().attributeNS( KoXmlNS::fo, "margin-bottom" ) ); context.styleStack().pop(); } // The top margin of footers is what we call footerBodySpacing // (TODO support the 3 other margins) if ( !footerStyle.isNull() ) { context.styleStack().push( footerStyle ); context.styleStack().setTypeProperties( "header-footer" ); hf.ptFooterBodySpacing = KoUnit::parseValue( context.styleStack().attributeNS( KoXmlNS::fo, "margin-top" ) ); context.styleStack().pop(); } // TODO ptFootNoteBodySpacing } return true; } // Called before loading // It's important to clear out anything that might be in the document already, // for things like using DCOP to load multiple documents into the same KWDocument, // or "reload" when kword is embedded into konqueror. void KWDocument::clear() { m_pictureMap.clear(); m_textImageRequests.clear(); m_pictureRequests.clear(); m_anchorRequests.clear(); m_footnoteVarRequests.clear(); m_spellCheckIgnoreList.clear(); m_pageHeaderFooter.header = HF_SAME; m_pageHeaderFooter.footer = HF_SAME; m_pageHeaderFooter.ptHeaderBodySpacing = 10; m_pageHeaderFooter.ptFooterBodySpacing = 10; m_pageHeaderFooter.ptFootNoteBodySpacing = 10; m_pageColumns.columns = 1; m_pageColumns.ptColumnSpacing = m_defaultColumnSpacing; m_bHasEndNotes = false; m_iFootNoteSeparatorLineLength = 20; // 20%, i.e. 1/5th m_footNoteSeparatorLineWidth = 0.5; // like in OOo m_footNoteSeparatorLineType = SLT_SOLID; m_lstFrameSet.clear(); m_varColl->clear(); m_pictureCollection->clear(); m_varFormatCollection->clear(); m_styleColl->clear(); m_frameStyleColl->clear(); m_tableStyleColl->clear(); m_tableTemplateColl->clear(); // Some simple import filters don't define any style, // so let's have a Standard style at least KoParagStyle * standardStyle = new KoParagStyle( "Standard" ); // This gets translated later on //kdDebug() << "KWDocument::KWDocument creating standardStyle " << standardStyle << endl; standardStyle->format().setFont( m_defaultFont ); m_styleColl->addStyle( standardStyle ); // And let's do the same for framestyles KWFrameStyle * standardFrameStyle = new KWFrameStyle( "Plain" ); standardFrameStyle->setBackgroundColor(TQt::white); standardFrameStyle->setTopBorder(KoBorder(TQt::black,KoBorder::SOLID,0)); standardFrameStyle->setRightBorder(KoBorder(TQt::black,KoBorder::SOLID,0)); standardFrameStyle->setLeftBorder(KoBorder(TQt::black,KoBorder::SOLID,0)); standardFrameStyle->setBottomBorder(KoBorder(TQt::black,KoBorder::SOLID,0)); m_frameStyleColl->addStyle( standardFrameStyle ); // And let's do the same for tablestyles KWTableStyle *standardTableStyle = new KWTableStyle( "Plain", standardStyle, standardFrameStyle ); m_tableStyleColl->addStyle( standardTableStyle ); } bool KWDocument::loadXML( TQIODevice *, const TQDomDocument & doc ) { TQTime dt; dt.start(); emit sigProgress( 0 ); kdDebug(32001) << "KWDocument::loadXML" << endl; clear(); KoPageLayout pgLayout; KoColumns columns; columns.columns = 1; columns.ptColumnSpacing = m_defaultColumnSpacing; KoKWHeaderFooter hf; hf.header = HF_SAME; hf.footer = HF_SAME; hf.ptHeaderBodySpacing = 10.0; hf.ptFooterBodySpacing = 10.0; hf.ptFootNoteBodySpacing = 10.0; TQString value; TQDomElement word = doc.documentElement(); value = KWDocument::getAttribute( word, "mime", TQString() ); if ( value.isEmpty() ) { kdError(32001) << "No mime type specified!" << endl; setErrorMessage( i18n( "Invalid document. No mimetype specified." ) ); return false; } else if ( value != "application/x-kword" && value != "application/vnd.kde.kword" ) { kdError(32001) << "Unknown mime type " << value << endl; setErrorMessage( i18n( "Invalid document. Expected mimetype application/x-kword or application/vnd.kde.kword, got %1" ).arg( value ) ); return false; } m_syntaxVersion = KWDocument::getAttribute( word, "syntaxVersion", 0 ); if ( m_syntaxVersion > CURRENT_SYNTAX_VERSION ) { int ret = KMessageBox::warningContinueCancel( 0, i18n("This document was created with a newer version of KWord (syntax version: %1)\n" "Opening it in this version of KWord will lose some information.").arg(m_syntaxVersion), i18n("File Format Mismatch"), KStdGuiItem::cont() ); if ( ret == KMessageBox::Cancel ) { setErrorMessage( "USER_CANCELED" ); return false; } } createLoadingInfo(); // Looks like support for the old way of naming images internally, // see completeLoading. value = KWDocument::getAttribute( word, "url", TQString() ); if ( !value.isNull() ) { m_urlIntern = KURL( value ).path(); } emit sigProgress(5); // TQDomElement paper = word.namedItem( "PAPER" ).toElement(); if ( !paper.isNull() ) { pgLayout.format = static_cast( KWDocument::getAttribute( paper, "format", 0 ) ); pgLayout.orientation = static_cast( KWDocument::getAttribute( paper, "orientation", 0 ) ); pgLayout.ptWidth = getAttribute( paper, "width", 0.0 ); pgLayout.ptHeight = getAttribute( paper, "height", 0.0 ); kdDebug() << " ptWidth=" << pgLayout.ptWidth << endl; kdDebug() << " ptHeight=" << pgLayout.ptHeight << endl; if ( pgLayout.ptWidth <= 0 || pgLayout.ptHeight <= 0 ) { // Old document? pgLayout.ptWidth = getAttribute( paper, "ptWidth", 0.0 ); pgLayout.ptHeight = getAttribute( paper, "ptHeight", 0.0 ); kdDebug() << " ptWidth=" << pgLayout.ptWidth << endl; kdDebug() << " ptHeight=" << pgLayout.ptHeight << endl; // Still wrong? if ( pgLayout.ptWidth <= 0 || pgLayout.ptHeight <= 0 ) { setErrorMessage( i18n( "Invalid document. Paper size: %1x%2" ) .arg( pgLayout.ptWidth ).arg( pgLayout.ptHeight ) ); return false; } } hf.header = static_cast( KWDocument::getAttribute( paper, "hType", 0 ) ); hf.footer = static_cast( KWDocument::getAttribute( paper, "fType", 0 ) ); hf.ptHeaderBodySpacing = getAttribute( paper, "spHeadBody", 0.0 ); hf.ptFooterBodySpacing = getAttribute( paper, "spFootBody", 0.0 ); hf.ptFootNoteBodySpacing = getAttribute( paper, "spFootNoteBody", 10.0 ); m_iFootNoteSeparatorLineLength = getAttribute( paper, "slFootNoteLength", 20); if ( paper.hasAttribute( "slFootNoteWidth" ) ) m_footNoteSeparatorLineWidth = paper.attribute( "slFootNoteWidth" ).toDouble(); m_footNoteSeparatorLineType = static_cast(getAttribute( paper, "slFootNoteType",0)); if ( paper.hasAttribute("slFootNotePosition")) { TQString tmp =paper.attribute("slFootNotePosition"); if ( tmp =="centered" ) m_footNoteSeparatorLinePos = SLP_CENTERED; else if ( tmp =="right") m_footNoteSeparatorLinePos = SLP_RIGHT; else if ( tmp =="left" ) m_footNoteSeparatorLinePos = SLP_LEFT; } columns.columns = KWDocument::getAttribute( paper, "columns", 1 ); columns.ptColumnSpacing = KWDocument::getAttribute( paper, "columnspacing", 0.0 ); // Now part of the app config //m_zoom = KWDocument::getAttribute( paper, "zoom", 100 ); //if(m_zoom!=100) // setZoomAndResolution( m_zoom, KoGlobal::dpiX(), KoGlobal::dpiY(), false, false ); // Support the undocumented syntax actually used by KDE 2.0 for some of the above (:-(). // Do not add anything to this block! if ( pgLayout.ptWidth == 0.0 ) pgLayout.ptWidth = getAttribute( paper, "ptWidth", 0.0 ); if ( pgLayout.ptHeight == 0.0 ) pgLayout.ptHeight = getAttribute( paper, "ptHeight", 0.0 ); if ( hf.ptHeaderBodySpacing == 0.0 ) hf.ptHeaderBodySpacing = getAttribute( paper, "ptHeadBody", 0.0 ); if ( hf.ptFooterBodySpacing == 0.0 ) hf.ptFooterBodySpacing = getAttribute( paper, "ptFootBody", 0.0 ); if ( columns.ptColumnSpacing == 0.0 ) columns.ptColumnSpacing = getAttribute( paper, "ptColumnspc", 0.0 ); // TQDomElement paperborders = paper.namedItem( "PAPERBORDERS" ).toElement(); if ( !paperborders.isNull() ) { pgLayout.ptLeft = getAttribute( paperborders, "left", 0.0 ); pgLayout.ptTop = getAttribute( paperborders, "top", 0.0 ); pgLayout.ptRight = getAttribute( paperborders, "right", 0.0 ); pgLayout.ptBottom = getAttribute( paperborders, "bottom", 0.0 ); // Support the undocumented syntax actually used by KDE 2.0 for some of the above (:-(). if ( pgLayout.ptLeft == 0.0 ) pgLayout.ptLeft = getAttribute( paperborders, "ptLeft", 0.0 ); if ( pgLayout.ptTop == 0.0 ) pgLayout.ptTop = getAttribute( paperborders, "ptTop", 0.0 ); if ( pgLayout.ptRight == 0.0 ) pgLayout.ptRight = getAttribute( paperborders, "ptRight", 0.0 ); if ( pgLayout.ptBottom == 0.0 ) pgLayout.ptBottom = getAttribute( paperborders, "ptBottom", 0.0 ); } else kdWarning() << "No tag!" << endl; } else kdWarning() << "No tag! This is a mandatory tag! Expect weird page sizes..." << endl; // TQDomElement attributes = word.namedItem( "ATTRIBUTES" ).toElement(); if ( !attributes.isNull() ) { m_processingType = static_cast( KWDocument::getAttribute( attributes, "processing", 0 ) ); //KWDocument::getAttribute( attributes, "standardpage", TQString() ); m_headerVisible = static_cast( KWDocument::getAttribute( attributes, "hasHeader", 0 ) ); m_footerVisible = static_cast( KWDocument::getAttribute( attributes, "hasFooter", 0 ) ); if ( attributes.hasAttribute( "unit" ) ) setUnit( KoUnit::unit( attributes.attribute( "unit" ) ) ); m_hasTOC = static_cast(KWDocument::getAttribute( attributes,"hasTOC", 0 ) ); m_tabStop = KWDocument::getAttribute( attributes, "tabStopValue", MM_TO_POINT(15) ); m_initialEditing = new InitialEditing(); m_initialEditing->m_initialFrameSet = attributes.attribute( "activeFrameset" ); m_initialEditing->m_initialCursorParag = attributes.attribute( "cursorParagraph" ).toInt(); m_initialEditing->m_initialCursorIndex = attributes.attribute( "cursorIndex" ).toInt(); } else { m_processingType = WP; m_headerVisible = false; m_footerVisible = false; m_hasTOC = false; m_tabStop = MM_TO_POINT(15); delete m_initialEditing; m_initialEditing = 0L; } setPageLayout( pgLayout, columns, hf, false ); variableCollection()->variableSetting()->load(word ); //by default display real variable value if ( !isReadWrite()) variableCollection()->variableSetting()->setDisplayFieldCode(false); emit sigProgress(10); TQDomElement mailmerge = word.namedItem( "MAILMERGE" ).toElement(); if (mailmerge!=TQDomElement()) { m_slDataBase->load(mailmerge); } emit sigProgress(15); // Load all styles before the corresponding paragraphs try to use them! TQDomElement stylesElem = word.namedItem( "STYLES" ).toElement(); if ( !stylesElem.isNull() ) loadStyleTemplates( stylesElem ); emit sigProgress(17); TQDomElement frameStylesElem = word.namedItem( "FRAMESTYLES" ).toElement(); if ( !frameStylesElem.isNull() ) loadFrameStyleTemplates( frameStylesElem ); else // load default styles loadDefaultFrameStyleTemplates(); emit sigProgress(18); TQDomElement tableStylesElem = word.namedItem( "TABLESTYLES" ).toElement(); if ( !tableStylesElem.isNull() ) loadTableStyleTemplates( tableStylesElem ); else // load default styles loadDefaultTableStyleTemplates(); emit sigProgress(19); loadDefaultTableTemplates(); emit sigProgress(20); TQDomElement bookmark = word.namedItem( "BOOKMARKS" ).toElement(); if( !bookmark.isNull() ) { TQDomElement bookmarkitem = word.namedItem("BOOKMARKS").toElement(); bookmarkitem = bookmarkitem.firstChild().toElement(); while ( !bookmarkitem.isNull() ) { if ( bookmarkitem.tagName() == "BOOKMARKITEM" ) { KWLoadingInfo::BookMark bk; bk.bookname=bookmarkitem.attribute("name"); bk.cursorStartIndex=bookmarkitem.attribute("cursorIndexStart").toInt(); bk.frameSetName=bookmarkitem.attribute("frameset"); bk.paragStartIndex = bookmarkitem.attribute("startparag").toInt(); bk.paragEndIndex = bookmarkitem.attribute("endparag").toInt(); bk.cursorEndIndex = bookmarkitem.attribute("cursorIndexEnd").toInt(); Q_ASSERT( m_loadingInfo ); m_loadingInfo->bookMarkList.append( bk ); } bookmarkitem = bookmarkitem.nextSibling().toElement(); } } TQStringList lst; TQDomElement spellCheckIgnore = word.namedItem( "SPELLCHECKIGNORELIST" ).toElement(); if( !spellCheckIgnore.isNull() ) { TQDomElement spellWord=word.namedItem("SPELLCHECKIGNORELIST").toElement(); spellWord=spellWord.firstChild().toElement(); while ( !spellWord.isNull() ) { if ( spellWord.tagName()=="SPELLCHECKIGNOREWORD" ) lst.append(spellWord.attribute("word")); spellWord=spellWord.nextSibling().toElement(); } } setSpellCheckIgnoreList( lst ); emit sigProgress(25); TQDomElement framesets = word.namedItem( "FRAMESETS" ).toElement(); if ( !framesets.isNull() ) loadFrameSets( framesets ); emit sigProgress(85); loadPictureMap( word ); emit sigProgress(90); // loadEmbeddedObjects( word ); emit sigProgress(100); // the rest is only processing, not loading kdDebug(32001) << "Loading took " << (float)(dt.elapsed()) / 1000 << " seconds" << endl; endOfLoading(); return true; } void KWDocument::endOfLoading() // called by both oasis and oldxml { // insert pages double maxBottom = 0; for (TQPtrListIterator fsit = framesetsIterator(); fsit.current() ; ++fsit ) { KWFrameSet *fs = fsit.current(); for (TQPtrListIterator fit = fs->frameIterator(); fit.current() ; ++fit ) { KWFrame *frame = fit.current(); maxBottom = TQMAX(maxBottom, frame->bottom()); } } KWPage *last = pageManager()->page(lastPage()); double docHeight = last->offsetInDocument() + last->height(); while(docHeight <= maxBottom) { kdDebug(32001) << "KWDocument::loadXML appends a page\n"; last = pageManager()->appendPage(); docHeight += last->height(); } bool first_footer = false, even_footer = false, odd_footer = false; bool first_header = false, even_header = false, odd_header = false; TQPtrListIterator fit = framesetsIterator(); for ( ; fit.current() ; ++fit ) { switch( fit.current()->frameSetInfo() ) { case KWFrameSet::FI_FIRST_HEADER: first_header = true; break; case KWFrameSet::FI_ODD_HEADER: odd_header = true; break; case KWFrameSet::FI_EVEN_HEADER: even_header = true; break; case KWFrameSet::FI_FIRST_FOOTER: first_footer = true; break; case KWFrameSet::FI_ODD_FOOTER: odd_footer = true; break; case KWFrameSet::FI_EVEN_FOOTER: even_footer = true; break; case KWFrameSet::FI_FOOTNOTE: break; default: break; } } // Create defaults if they were not in the input file. // Where to insert the new frames: not at the end, since that breaks oasis-kword.sh uint newFramesetsIndex = m_lstFrameSet.isEmpty() ? 0 : 1; if ( !first_header ) { KWTextFrameSet *fs = new KWTextFrameSet( this, i18n( "First Page Header" ) ); //kdDebug(32001) << "KWDocument::loadXML KWTextFrameSet created " << fs << endl; fs->setFrameSetInfo( KWFrameSet::FI_FIRST_HEADER ); KWPage *page = pageManager()->page(startPage()); KWFrame *frame = new KWFrame(fs, page->leftMargin(), page->topMargin(), page->width() - page->leftMargin() - page->rightMargin(), 20 ); //kdDebug(32001) << "KWDocument::loadXML KWFrame created " << frame << endl; frame->setFrameBehavior( KWFrame::AutoExtendFrame ); frame->setNewFrameBehavior( KWFrame::Copy ); fs->addFrame( frame ); m_lstFrameSet.insert( newFramesetsIndex++, fs ); } if ( !odd_header ) { KWTextFrameSet *fs = new KWTextFrameSet( this, i18n( "Odd Pages Header" ) ); //kdDebug(32001) << "KWDocument::loadXML KWTextFrameSet created " << fs << endl; fs->setFrameSetInfo( KWFrameSet::FI_ODD_HEADER ); KWPage *page = pageManager()->page(TQMIN(startPage()+2, lastPage())); KWFrame *frame = new KWFrame(fs, page->leftMargin(), page->topMargin(), page->width() - page->leftMargin() - page->rightMargin(), 20 ); //kdDebug(32001) << "KWDocument::loadXML KWFrame created " << *frame << endl; frame->setFrameBehavior( KWFrame::AutoExtendFrame ); frame->setNewFrameBehavior( KWFrame::Copy ); fs->addFrame( frame ); m_lstFrameSet.insert( newFramesetsIndex++, fs ); } if ( !even_header ) { KWTextFrameSet *fs = new KWTextFrameSet( this, i18n( "Even Pages Header" ) ); //kdDebug(32001) << "KWDocument::loadXML KWTextFrameSet created " << fs << endl; fs->setFrameSetInfo( KWFrameSet::FI_EVEN_HEADER ); KWPage *page = pageManager()->page(TQMIN(startPage()+1, lastPage())); KWFrame *frame = new KWFrame(fs, page->leftMargin(), page->topMargin(), page->width() - page->leftMargin() - page->rightMargin(), 20 ); //kdDebug(32001) << "KWDocument::loadXML KWFrame created " << *frame << endl; frame->setFrameBehavior( KWFrame::AutoExtendFrame ); frame->setNewFrameBehavior( KWFrame::Copy ); fs->addFrame( frame ); m_lstFrameSet.insert( newFramesetsIndex++, fs ); } if ( !first_footer ) { KWTextFrameSet *fs = new KWTextFrameSet( this, i18n( "First Page Footer" ) ); //kdDebug(32001) << "KWDocument::loadXML KWTextFrameSet created " << fs << endl; fs->setFrameSetInfo( KWFrameSet::FI_FIRST_FOOTER ); KWPage *page = pageManager()->page(pageManager()->startPage()); KWFrame *frame = new KWFrame(fs, page->leftMargin(), page->height() - page->topMargin()- 20, page->width() - page->leftMargin() - page->rightMargin(), 20 ); //kdDebug(32001) << "KWDocument::loadXML KWFrame created " << *frame << endl; frame->setFrameBehavior( KWFrame::AutoExtendFrame ); frame->setNewFrameBehavior( KWFrame::Copy ); fs->addFrame( frame ); m_lstFrameSet.insert( newFramesetsIndex++, fs ); } if ( !odd_footer ) { KWTextFrameSet *fs = new KWTextFrameSet( this, i18n( "Odd Pages Footer" ) ); //kdDebug(32001) << "KWDocument::loadXML KWTextFrameSet created " << fs << endl; fs->setFrameSetInfo( KWFrameSet::FI_ODD_FOOTER ); KWPage *page = pageManager()->page(TQMIN(startPage()+2, lastPage())); KWFrame *frame = new KWFrame(fs, page->leftMargin(), page->height()- page->topMargin() - 20, page->width() - page->leftMargin() - page->rightMargin(), 20 ); //kdDebug(32001) << "KWDocument::loadXML KWFrame created " << *frame << endl; frame->setFrameBehavior( KWFrame::AutoExtendFrame ); frame->setNewFrameBehavior( KWFrame::Copy ); fs->addFrame( frame ); m_lstFrameSet.insert( newFramesetsIndex++, fs ); } if ( !even_footer ) { KWTextFrameSet *fs = new KWTextFrameSet( this, i18n( "Even Pages Footer" ) ); //kdDebug(32001) << "KWDocument::loadXML KWTextFrameSet created " << fs << endl; fs->setFrameSetInfo( KWFrameSet::FI_EVEN_FOOTER ); KWPage *page = pageManager()->page(TQMIN(startPage()+1, lastPage())); KWFrame *frame = new KWFrame(fs, page->leftMargin(), page->height() - page->topMargin()- 20, page->width() - page->leftMargin() - page->rightMargin(), 20 ); //kdDebug(32001) << "KWDocument::loadXML KWFrame created " << *frame << endl; frame->setFrameBehavior( KWFrame::AutoExtendFrame ); frame->setNewFrameBehavior( KWFrame::Copy ); fs->addFrame( frame ); m_lstFrameSet.insert( newFramesetsIndex++, fs ); } // do some sanity checking on document. for (int i = frameSetCount()-1; i>-1; i--) { KWFrameSet *fs = frameSet(i); if(!fs) { kdWarning() << "frameset " << i << " is NULL!!" << endl; m_lstFrameSet.remove(i); continue; } if( fs->type()==FT_TABLE) { static_cast( fs )->validate(); } else if (fs->type() == FT_TEXT) { for (int f=fs->frameCount()-1; f>=0; f--) { KWFrame *frame = fs->frame(f); if(frame->left() < 0) { kdWarning() << fs->name() << " frame " << f << " pos.x is < 0, moving frame" << endl; frame->moveBy( 0- frame->left(), 0); } if(frame->right() > m_pageLayout.ptWidth) { kdWarning() << fs->name() << " frame " << f << " rightborder outside page (" << frame->right() << ">" << m_pageLayout.ptWidth << "), shrinking" << endl; frame->setRight(m_pageLayout.ptWidth); } if(fs->isProtectSize()) continue; // don't make frames bigger of a protected frameset. if(frame->height() < s_minFrameHeight) { kdWarning() << fs->name() << " frame " << f << " height is so small no text will fit, adjusting (was: " << frame->height() << " is: " << s_minFrameHeight << ")" << endl; frame->setHeight(s_minFrameHeight); } if(frame->width() < s_minFrameWidth) { kdWarning() << fs->name() << " frame " << f << " width is so small no text will fit, adjusting (was: " << frame->width() << " is: " << s_minFrameWidth << ")" << endl; frame->setWidth(s_minFrameWidth); } } if(fs->frameCount() == 0) { KWPage *page = pageManager()->page(startPage()); KWFrame *frame = new KWFrame(fs, page->leftMargin(), page->topMargin(), page->width() - page->leftMargin() - page->rightMargin(), page->height() - page->topMargin() - page->bottomMargin()); //kdDebug(32001) << "KWDocument::loadXML main-KWFrame created " << *frame << endl; fs->addFrame( frame ); } } else if(fs->frameCount() == 0) { kdWarning () << "frameset " << i << " " << fs->name() << " has no frames" << endl; removeFrameSet(fs); if ( fs->type() == FT_PART ) delete static_cast(fs)->getChild(); delete fs; continue; } if(fs->frameCount() > 0) { KWFrame *frame = fs->frame(0); if(frame->isCopy()) { kdWarning() << "First frame in a frameset[" << fs->name() << "] was set to be a copy; resetting\n"; frame->setCopy(false); } } } // Renumber footnotes KWTextFrameSet *frameset = dynamic_cast( m_lstFrameSet.getFirst() ); if ( frameset ) frameset->renumberFootNotes( false /*no repaint*/ ); emit sigProgress(-1); //kdDebug(32001) << "KWDocument::loadXML done" << endl; // Connect to notifications from main text-frameset if ( frameset ) { connect( frameset->textObject(), TQ_SIGNAL( chapterParagraphFormatted( KoTextParag * ) ), TQ_SLOT( slotChapterParagraphFormatted( KoTextParag * ) ) ); connect( frameset, TQ_SIGNAL( mainTextHeightChanged() ), TQ_SIGNAL( mainTextHeightChanged() ) ); } // Note that more stuff will happen in completeLoading } void KWDocument::startBackgroundSpellCheck() { if ( backgroundSpellCheckEnabled() && isReadWrite() ) { m_bgSpellCheck->start(); } } void KWDocument::loadEmbeddedObjects( TQDomElement& word ) { TQDomNodeList listEmbedded = word.elementsByTagName ( "EMBEDDED" ); for (unsigned int item = 0; item < listEmbedded.count(); item++) { TQDomElement embedded = listEmbedded.item( item ).toElement(); loadEmbedded( embedded ); } } void KWDocument::loadEmbedded( const TQDomElement &embedded ) { TQDomElement object = embedded.namedItem( "OBJECT" ).toElement(); if ( !object.isNull() ) { KWDocumentChild *ch = new KWDocumentChild( this ); ch->load( object, true ); insertChild( ch ); TQDomElement settings = embedded.namedItem( "SETTINGS" ).toElement(); TQString name; if ( !settings.isNull() ) name = settings.attribute( "name" ); KWPartFrameSet *fs = new KWPartFrameSet( this, ch, name ); m_lstFrameSet.append( fs ); if ( !settings.isNull() ) { kdDebug(32001) << "KWDocument::loadXML loading embedded object" << endl; fs->load( settings ); } else kdError(32001) << "No tag in EMBEDDED" << endl; } else kdError(32001) << "No tag in EMBEDDED" << endl; } void KWDocument::loadStyleTemplates( const TQDomElement &stylesElem ) { TQValueList followingStyles; TQDomNodeList listStyles = stylesElem.elementsByTagName( "STYLE" ); if( listStyles.count() > 0) { // we are going to import at least one style. KoParagStyle *s = m_styleColl->findStyle("Standard"); //kdDebug(32001) << "KWDocument::loadStyleTemplates looking for Standard, to delete it. Found " << s << endl; if(s) // delete the standard style. m_styleColl->removeStyle(s); } for (unsigned int item = 0; item < listStyles.count(); item++) { TQDomElement styleElem = listStyles.item( item ).toElement(); KoParagStyle *sty = new KoParagStyle( TQString() ); // Load the style from the