kword

KWDocument.cpp
1/* This file is part of the KDE project
2 Copyright (C) 1998, 1999 Reginald Stadlbauer <reggie@kde.org>
3 Copyright (C) 2002-2006 David Faure <faure@kde.org>
4 Copyright (C) 2005 Thomas Zander <zander@kde.org>
5
6 This library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Library General Public
8 License as published by the Free Software Foundation; either
9 version 2 of the License, or (at your option) any later version.
10
11 This library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Library General Public License for more details.
15
16 You should have received a copy of the GNU Library General Public License
17 along with this library; see the file COPYING.LIB. If not, write to
18 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 * Boston, MA 02110-1301, USA.
20*/
21
22#include "KWDocument.h"
23
24#include "KWordDocIface.h"
25#include "KWBgSpellCheck.h"
26#include "KoTextBookmark.h"
27#include "KWCanvas.h"
28#include "KWCommand.h"
29#include "KWFormulaFrameSet.h"
30#include "KWFrameLayout.h"
31#include "KWPictureFrameSet.h"
32#include "KWPartFrameSet.h"
33#include "KWTableFrameSet.h"
34#include "KWTableStyle.h"
35#include "KWTableTemplate.h"
36#include "KWTextImage.h"
37#include "KWVariable.h"
38#include "KWView.h"
39#include "KWViewMode.h"
40#include "KWMailMergeDataBase.h"
41#include "KWLoadingInfo.h"
42#include "KWCollectFramesetsVisitor.h"
43#include "KWOasisLoader.h"
44#include "KWOasisSaver.h"
45#include "KWFrameList.h"
46#include "KWPageManager.h"
47#include "KWPage.h"
48#include "KWFrameView.h"
49#include "KWFrameViewManager.h"
50#include "KWStartupWidget.h"
51
52#include <KoPictureCollection.h>
53#include <KoTemplateChooseDia.h>
54#include <KoMainWindow.h>
55#include <KoDocumentInfo.h>
56#include <KoGlobal.h>
57#include <KoParagCounter.h>
58#include <KoTextObject.h>
59#include <KoAutoFormat.h>
60#include <KoVariable.h>
61#include <kformuladocument.h>
62#include <KoApplication.h>
63#include <KoOasisContext.h>
64#include <KoCommandHistory.h>
65#include <KoGenStyles.h>
66#include <KoStore.h>
67#include <KoStoreDrag.h>
68#include <KoStoreDevice.h>
69#include <KoXmlWriter.h>
70#include <KoOasisStore.h>
71#include <KoOasisStyles.h>
72#include <KoXmlNS.h>
73#include <KoDom.h>
74
75#include <kcursor.h>
76#include <kdebug.h>
77#include <tdeglobalsettings.h>
78#include <klibloader.h>
79#include <tdemultipledrag.h>
80#include <tdelocale.h>
81#include <tdemessagebox.h>
82#include <tdespell.h>
83#include <kstandarddirs.h>
84
85#include <tdespell2/settings.h>
86
87#include <tqfileinfo.h>
88#include <tqregexp.h>
89#include <tqtimer.h>
90#include <tqbuffer.h>
91
92#include <unistd.h>
93#include <math.h>
94
95//#define DEBUG_PAGES
96//#define DEBUG_SPEED
97
98// Make sure an appropriate DTD is available in www/koffice/DTD if changing this value
99static const char * CURRENT_DTD_VERSION = "1.2";
100
101/******************************************************************/
102/* Class: KWCommandHistory */
103/******************************************************************/
104class KWCommandHistory : public KoCommandHistory
105{
106public:
107 KWCommandHistory( KWDocument * doc ) : KoCommandHistory( doc->actionCollection(), true ), m_pDoc( doc ) {}
108public /*slots*/: // They are already slots in the parent. Running moc on the inherited class shouldn't be necessary AFAICS.
109 virtual void undo();
110 virtual void redo();
111private:
112 KWDocument * m_pDoc;
113};
114
115void KWCommandHistory::undo()
116{
117 m_pDoc->clearUndoRedoInfos();
118 KoCommandHistory::undo();
119}
120
121void KWCommandHistory::redo()
122{
123 m_pDoc->clearUndoRedoInfos();
124 KoCommandHistory::redo();
125}
126
127/******************************************************************/
128/* Class: KWDocument */
129/******************************************************************/
130void KWDocument::clearUndoRedoInfos()
131{
132 TQPtrListIterator<KWFrameSet> fit = framesetsIterator();
133 for ( ; fit.current() ; ++fit )
134 {
135 KWTextFrameSet *fs = dynamic_cast<KWTextFrameSet *>( fit.current() );
136 if ( fs )
137 fs->clearUndoRedoInfo();
138 }
139}
140
145class KWDocument::InitialEditing {
146public:
147 TQString m_initialFrameSet;
148 int m_initialCursorParag;
149 int m_initialCursorIndex;
150};
151
152const int KWDocument::CURRENT_SYNTAX_VERSION = 3;
153
154KWDocument::KWDocument(TQWidget *parentWidget, const char *widname, TQObject* parent, const char* name, bool singleViewMode )
155 : KoDocument( parentWidget, widname, parent, name, singleViewMode ),
156 m_urlIntern()
157{
158 KWStatisticVariable::setExtendedType( true );
159 dcop = 0;
160 m_framesChangedHandler = 0;
161 m_pageManager = new KWPageManager();
162 m_pageManager->appendPage();
163 m_loadingInfo = 0L;
164 m_tabStop = MM_TO_POINT( 15.0 );
165 m_processingType = WP;
166
167// varFormats.setAutoDelete(true);
168 m_lstFrameSet.setAutoDelete( true );
169 // m_textImageRequests does not create or delete the KWTextImage classes
170 m_textImageRequests.setAutoDelete(false);
171
172 m_styleColl = new KoStyleCollection();
173 m_frameStyleColl = new KWFrameStyleCollection();
174 m_tableStyleColl = new KWTableStyleCollection();
175 m_tableTemplateColl = new KWTableTemplateCollection();
176 m_pictureCollection = new KoPictureCollection();
177
178 m_personalExpressionPath = KWFactory::instance()->dirs()->resourceDirs("expression");
179
180 m_bShowGrid = false;
181 m_bSnapToGrid = false;
182
183
184 setInstance( KWFactory::instance(), false );
185 setTemplateType( "kword_template" );
186
187 m_gridX = m_gridY = MM_TO_POINT(5.0 );
188 m_indent = MM_TO_POINT( 10.0 );
189
190 m_iNbPagePerRow = 4;
191 m_maxRecentFiles = 10;
192 m_bShowRuler = true;
193
194 m_footNoteSeparatorLinePos=SLP_LEFT;
195
196 m_viewFormattingChars = false;
197
198 m_viewFormattingEndParag = true;
199 m_viewFormattingSpace = true;
200 m_viewFormattingTabs = true;
201 m_viewFormattingBreak = true;
202
203 m_viewFrameBorders = true;
204 m_repaintAllViewsPending = false;
205 m_recalcFramesPending = -1;
206 m_bShowDocStruct = true;
207 m_bShowRuler = true;
208 m_bShowStatusBar = true;
209 m_bAllowAutoFormat = true;
210 m_pgUpDownMovesCaret = true;
211 m_bShowScrollBar = true;
212 m_cursorInProtectectedArea = true;
213 m_bHasEndNotes = false;
214
215 m_bInsertDirectCursor=false;
216 m_globalLanguage = TDEGlobal::locale()->language();
217 m_bGlobalHyphenation = false;
218 m_bGeneratingPreview = false;
219 m_viewModeType="ModeNormal";
220 m_layoutViewMode = 0;
221
222 m_commandHistory = new KWCommandHistory( this );
223 connect( m_commandHistory, TQ_SIGNAL( documentRestored() ), this, TQ_SLOT( slotDocumentRestored() ) );
224 connect( m_commandHistory, TQ_SIGNAL( commandExecuted() ), this, TQ_SLOT( slotCommandExecuted() ) );
225
226 //styleMask = U_FONT_FAMILY_ALL_SIZE | U_COLOR | U_BORDER | U_INDENT |
227 // U_NUMBERING | U_ALIGN | U_TABS | U_SMART;
228 m_headerVisible = false;
229 m_footerVisible = false;
230
231 m_pasteFramesetsMap = 0L;
232 m_initialEditing = 0L;
233 m_bufPixmap = 0L;
234 m_varFormatCollection = new KoVariableFormatCollection;
235 m_varColl = new KWVariableCollection( new KWVariableSettings(), m_varFormatCollection );
236
237 m_autoFormat = new KoAutoFormat(this,m_varColl,m_varFormatCollection );
238 m_bgSpellCheck = new KWBgSpellCheck(this);
239 m_slDataBase = new KWMailMergeDataBase( this );
240 m_bookmarkList = new KoTextBookmarkList;
241 slRecordNum = -1;
242
243 m_syntaxVersion = CURRENT_SYNTAX_VERSION;
244
245 m_hasTOC=false;
246
247 // It's important to call this to have the kformula actions
248 // created. The real document is still to be created if needed.
249 m_formulaDocumentWrapper =
250 new KFormula::DocumentWrapper( instance()->config(),
251 actionCollection(),
252 m_commandHistory );
253
254 setEmpty();
255 setModified(false);
256
257 initConfig();
258
259 // Get default font from the KWord config file
260 TDEConfig *config = KWFactory::instance()->config();
261 config->setGroup("Document defaults" );
262 TQString defaultFontname=config->readEntry("DefaultFont");
263 if ( !defaultFontname.isEmpty() )
264 m_defaultFont.fromString( defaultFontname );
265 // If not found, we automatically fallback to the application font (the one from KControl's font module)
266
267 // Try to force a scalable font.
268 m_defaultFont.setStyleStrategy( TQFont::ForceOutline );
269
270 int ptSize = m_defaultFont.pointSize();
271 if ( ptSize == -1 ) // specified with a pixel size ?
272 ptSize = TQFontInfo(m_defaultFont).pointSize();
273
274 //kdDebug() << "Default font: requested family: " << m_defaultFont.family() << endl;
275 //kdDebug() << "Default font: real family: " << TQFontInfo(m_defaultFont).family() << endl;
276
277 if ( name )
278 dcopObject();
279}
280
281DCOPObject* KWDocument::dcopObject()
282{
283 if ( !dcop )
284 dcop = new KWordDocIface( this );
285 return dcop;
286}
287
288KWDocument::~KWDocument()
289{
290 //don't save config when kword is embedded into konqueror
291 if(isReadWrite())
292 saveConfig();
293 // formula frames have to be deleted before m_formulaDocumentWrapper
294 m_lstFrameSet.clear();
295 delete m_loadingInfo;
296 delete m_autoFormat;
297 delete m_formulaDocumentWrapper;
298 delete m_commandHistory;
299 delete m_varColl;
300 delete m_varFormatCollection;
301 delete m_slDataBase;
302 delete dcop;
303 delete m_bgSpellCheck;
304 delete m_styleColl;
305 delete m_frameStyleColl;
306 delete m_tableStyleColl;
307 delete m_tableTemplateColl;
308 delete m_layoutViewMode;
309 delete m_bufPixmap;
310 delete m_pictureCollection;
311 delete m_pageManager;
312 delete m_bookmarkList;
313}
314
315void KWDocument::initConfig()
316{
317 TDEConfig *config = KWFactory::instance()->config();
318 if( config->hasGroup("KSpell kword" ) )
319 {
320 config->setGroup( "KSpell kword" );
321
322 // Default is false for spellcheck, but the spell-check config dialog
323 // should write out "true" when the user configures spell checking.
324 if ( isReadWrite() )
325 m_bgSpellCheck->setEnabled(config->readBoolEntry( "SpellCheck", false ));
326 else
327 m_bgSpellCheck->setEnabled( false );
328 }
329
330 if(config->hasGroup("Interface" ) )
331 {
332 config->setGroup( "Interface" );
333 setGridY(TQMAX( config->readDoubleNumEntry("GridY",MM_TO_POINT(5.0) ), 0.1));
334 setGridX(TQMAX( config->readDoubleNumEntry("GridX",MM_TO_POINT(5.0) ), 0.1));
335 setCursorInProtectedArea( config->readBoolEntry( "cursorInProtectArea", true ));
336 // Config-file value in mm, default 10 pt
337 double indent = config->readDoubleNumEntry("Indent", MM_TO_POINT(10.0) ) ;
338 setIndentValue(indent);
339 setShowRuler(config->readBoolEntry("Rulers",true));
340 int defaultAutoSave = KoDocument::defaultAutoSave()/60; // in minutes
341 setAutoSave(config->readNumEntry("AutoSave",defaultAutoSave)*60); // read key in minutes, call setAutoSave(seconds)
342 setBackupFile( config->readBoolEntry("BackupFile", true) );
343
344 setNbPagePerRow(config->readNumEntry("nbPagePerRow",4));
345 m_maxRecentFiles = config->readNumEntry( "NbRecentFile", 10 );
346
347 m_viewFormattingChars = config->readBoolEntry( "ViewFormattingChars", false );
348 m_viewFormattingBreak = config->readBoolEntry( "ViewFormattingBreaks", true );
349 m_viewFormattingSpace = config->readBoolEntry( "ViewFormattingSpace", true );
350 m_viewFormattingEndParag = config->readBoolEntry( "ViewFormattingEndParag", true );
351 m_viewFormattingTabs = config->readBoolEntry( "ViewFormattingTabs", true );
352
353 m_viewFrameBorders = config->readBoolEntry( "ViewFrameBorders", true );
354
355 m_zoom = config->readNumEntry( "Zoom", 100 );
356 m_zoomMode = static_cast<KoZoomMode::Mode> (
357 config->readNumEntry( "ZoomMode", KoZoomMode::ZOOM_CONSTANT )
358 );
359
360 m_bShowDocStruct = config->readBoolEntry( "showDocStruct", true );
361 m_viewModeType = config->readEntry( "viewmode", "ModeNormal" );
362 setShowStatusBar( config->readBoolEntry( "ShowStatusBar" , true ) );
363 setAllowAutoFormat( config->readBoolEntry( "AllowAutoFormat" , true ) );
364 setShowScrollBar( config->readBoolEntry( "ShowScrollBar", true ) );
365 if ( isEmbedded() )
366 m_bShowDocStruct = false; // off by default for embedded docs, but still toggleable
367 m_pgUpDownMovesCaret = config->readBoolEntry( "PgUpDownMovesCaret", true );
368 m_bInsertDirectCursor= config->readBoolEntry( "InsertDirectCursor", false );
369 m_globalLanguage=config->readEntry("language", TDEGlobal::locale()->language());
370 m_bGlobalHyphenation=config->readBoolEntry("hyphenation", false);
371
372 setShowGrid( config->readBoolEntry( "ShowGrid" , false ));
373 setSnapToGrid( config->readBoolEntry( "SnapToGrid", false ));
374 setGridX( config->readDoubleNumEntry( "ResolutionX", MM_TO_POINT( 5.0 ) ));
375 setGridY( config->readDoubleNumEntry( "ResolutionY", MM_TO_POINT( 5.0 ) ));
376 }
377 else
378 {
379 m_zoom = 100;
380 m_zoomMode = KoZoomMode::ZOOM_WIDTH;
381 }
382 int undo=30;
383 if(config->hasGroup("Misc" ) )
384 {
385 config->setGroup( "Misc" );
386 undo=config->readNumEntry("UndoRedo",-1);
387
388 //load default unit setting - this is only used for new files (from templates) or empty files
389 if ( config->hasKey( "Units" ) )
390 setUnit( KoUnit::unit( config->readEntry("Units") ) );
391 m_defaultColumnSpacing = config->readDoubleNumEntry( "ColumnSpacing", 3.0 );
392 }
393
394 if(undo!=-1)
395 setUndoRedoLimit(undo);
396
397 setZoomAndResolution( m_zoom, KoGlobal::dpiX(), KoGlobal::dpiY() );
398
399 //text mode view is not a good default for a readonly document...
400 if ( !isReadWrite() && m_viewModeType =="ModeText" )
401 m_viewModeType= "ModeNormal";
402
403 m_layoutViewMode = KWViewMode::create( m_viewModeType, this, 0 /*no canvas*/);
404
405 if(config->hasGroup("Kword Path" ) )
406 {
407 config->setGroup( "Kword Path" );
408 if ( config->hasKey( "expression path" ) )
409 m_personalExpressionPath = config->readPathListEntry( "expression path" );
410 setBackupPath(config->readPathEntry( "backup path" ));
411 }
412
413 // Load personal dict
414 TDEConfigGroup group( KoGlobal::kofficeConfig(), "Spelling" );
415 m_spellCheckPersonalDict = group.readListEntry( "PersonalDict" );
416}
417
418void KWDocument::saveConfig()
419{
420 if ( !isReadWrite() )
421 return;
422 TDEConfigGroup group( KoGlobal::kofficeConfig(), "Spelling" );
423 group.writeEntry( "PersonalDict", m_spellCheckPersonalDict );
424
425 if ( !isEmbedded() )
426 {
427 // Only save the config that is manipulated by the UI directly.
428 // The config from the config dialog is saved by the dialog itself.
429 TDEConfig *config = KWFactory::instance()->config();
430 config->setGroup( "Interface" );
431 config->writeEntry( "ViewFormattingChars", m_viewFormattingChars );
432 config->writeEntry( "ViewFormattingBreaks", m_viewFormattingBreak );
433 config->writeEntry( "ViewFormattingEndParag", m_viewFormattingEndParag );
434 config->writeEntry( "ViewFormattingTabs", m_viewFormattingTabs );
435 config->writeEntry( "ViewFormattingSpace", m_viewFormattingSpace );
436 config->writeEntry( "ViewFrameBorders", m_viewFrameBorders );
437 config->writeEntry( "Zoom", m_zoom );
438 config->writeEntry( "ZoomMode", m_zoomMode );
439 config->writeEntry( "showDocStruct", m_bShowDocStruct );
440 config->writeEntry( "Rulers", m_bShowRuler );
441 config->writeEntry( "viewmode", m_viewModeType) ;
442 config->writeEntry( "AllowAutoFormat", m_bAllowAutoFormat );
443 config->writeEntry( "ShowGrid" , m_bShowGrid );
444 config->writeEntry( "SnapToGrid" , m_bSnapToGrid );
445 config->writeEntry( "ResolutionX", m_gridX );
446 config->writeEntry( "ResolutionY", m_gridY );
447 }
448}
449
450void KWDocument::setZoomAndResolution( int zoom, int dpiX, int dpiY )
451{
452 KoTextZoomHandler::setZoomAndResolution( zoom, dpiX, dpiY );
453 if ( KFormula::Document* formulaDocument = m_formulaDocumentWrapper->document() )
454 formulaDocument->setZoomAndResolution( zoom, dpiX, dpiY );
455}
456
457KWTextFrameSet * KWDocument::textFrameSet ( unsigned int num ) const
458{
459 unsigned int i=0;
460 TQPtrListIterator<KWFrameSet> fit = framesetsIterator();
461 for ( ; fit.current() ; ++fit )
462 {
463 if(fit.current()->isDeleted()) continue;
464 if(fit.current()->type()==FT_TEXT)
465 {
466 if(i==num)
467 return static_cast<KWTextFrameSet*>(fit.current());
468 i++;
469 }
470 }
471 return static_cast<KWTextFrameSet*>(m_lstFrameSet.getFirst());
472}
473
474void KWDocument::newZoomAndResolution( bool updateViews, bool forPrint )
475{
476 if ( KFormula::Document* formulaDocument = m_formulaDocumentWrapper->document() )
477 formulaDocument->newZoomAndResolution( updateViews,forPrint );
478#if 0
479 TQPtrListIterator<KWFrameSet> fit = framesetsIterator();
480 for ( ; fit.current() ; ++fit )
481 fit.current()->zoom( forPrint );
482#endif
483
484 // First recalc all frames (including the kotextdocument width)
485 updateAllFrames();
486 // Then relayout the text inside the frames
487 layout();
488 if ( updateViews )
489 {
490 emit newContentsSize();
491 repaintAllViews( true );
492 }
493}
494
495bool KWDocument::initDoc(InitDocFlags flags, TQWidget* parentWidget)
496{
497 m_pageColumns.columns = 1;
498 m_pageColumns.ptColumnSpacing = m_defaultColumnSpacing;
499
500 m_pageHeaderFooter.header = HF_SAME;
501 m_pageHeaderFooter.footer = HF_SAME;
502 m_pageHeaderFooter.ptHeaderBodySpacing = 10;
503 m_pageHeaderFooter.ptFooterBodySpacing = 10;
504 m_pageHeaderFooter.ptFootNoteBodySpacing = 10;
505
506 bool ok = false;
507
508 if ( isEmbedded() )
509 {
510 TQString fileName( locate( "kword_template", "Normal/.source/Embedded.kwt" , KWFactory::instance() ) );
511 resetURL();
512 ok = loadNativeFormat( fileName );
513 if ( !ok )
514 showLoadingErrorDialog();
515 setEmpty();
516 setModified( false );
517 return ok;
518 }
519 else if (flags==KoDocument::InitDocEmpty)
520 {
521 TQString fileName( locate( "kword_template", "Normal/.source/PlainText.kwt" , KWFactory::instance() ) );
522 resetURL();
523 ok = loadNativeFormat( fileName );
524 if ( !ok )
525 showLoadingErrorDialog();
526 setEmpty();
527 setModified( false );
528 return ok;
529 }
530
531 KoTemplateChooseDia::DialogType dlgtype;
532
533 if (flags != KoDocument::InitDocFileNew)
534 dlgtype = KoTemplateChooseDia::Everything;
535 else
536 dlgtype = KoTemplateChooseDia::OnlyTemplates;
537
538
539 TQString file;
540 KoTemplateChooseDia::ReturnType ret = KoTemplateChooseDia::choose(
541 KWFactory::instance(), file,
542 dlgtype, "kword_template", parentWidget );
543 if ( ret == KoTemplateChooseDia::Template ) {
544 resetURL();
545 ok = loadNativeFormat( file );
546 if ( !ok )
547 showLoadingErrorDialog();
548 setEmpty();
549 } else if ( ret == KoTemplateChooseDia::File ) {
550 KURL url( file );
551 //kdDebug() << "KWDocument::initDoc opening URL " << url.prettyURL() << endl;
552 ok = openURL( url );
553 } else if ( ret == KoTemplateChooseDia::Empty ) {
554 TQString fileName( locate( "kword_template", "Normal/.source/PlainText.kwt" , KWFactory::instance() ) );
555 resetURL();
556 ok = loadNativeFormat( fileName );
557 if ( !ok )
558 showLoadingErrorDialog();
559 setEmpty();
560 }
561 setModified( false );
562 return ok;
563}
564
565void KWDocument::openExistingFile( const TQString& file )
566{
567 m_pageColumns.columns = 1;
568 m_pageColumns.ptColumnSpacing = m_defaultColumnSpacing;
569
570 m_pageHeaderFooter.header = HF_SAME;
571 m_pageHeaderFooter.footer = HF_SAME;
572 m_pageHeaderFooter.ptHeaderBodySpacing = 10;
573 m_pageHeaderFooter.ptFooterBodySpacing = 10;
574 m_pageHeaderFooter.ptFootNoteBodySpacing = 10;
575
576 KoDocument::openExistingFile( file );
577}
578
579void KWDocument::openTemplate( const TQString& file )
580{
581 m_pageColumns.columns = 1;
582 m_pageColumns.ptColumnSpacing = m_defaultColumnSpacing;
583
584 m_pageHeaderFooter.header = HF_SAME;
585 m_pageHeaderFooter.footer = HF_SAME;
586 m_pageHeaderFooter.ptHeaderBodySpacing = 10;
587 m_pageHeaderFooter.ptFooterBodySpacing = 10;
588 m_pageHeaderFooter.ptFootNoteBodySpacing = 10;
589
590 KoDocument::openTemplate( file );
591}
592
593void KWDocument::initEmpty()
594{
595 m_pageColumns.columns = 1;
596 m_pageColumns.ptColumnSpacing = m_defaultColumnSpacing;
597
598 m_pageHeaderFooter.header = HF_SAME;
599 m_pageHeaderFooter.footer = HF_SAME;
600 m_pageHeaderFooter.ptHeaderBodySpacing = 10;
601 m_pageHeaderFooter.ptFooterBodySpacing = 10;
602 m_pageHeaderFooter.ptFootNoteBodySpacing = 10;
603
604 TQString fileName( locate( "kword_template", "Normal/.source/PlainText.kwt" , KWFactory::instance() ) );
605 bool ok = loadNativeFormat( fileName );
606 if ( !ok )
607 showLoadingErrorDialog();
608 resetURL();
609 setModified( false );
610 setEmpty();
611}
612
613KoPageLayout KWDocument::pageLayout(int pageNumber /* = 0 */) const
614{
615 if( pageNumber < startPage()) // impossible page..
616 pageNumber = startPage();
617 return pageManager()->pageLayout(pageNumber);
618}
619
620void KWDocument::setPageLayout( const KoPageLayout& layout, const KoColumns& cl, const KoKWHeaderFooter& hf, bool updateViews )
621{
622 m_pageLayout = layout;
623 if ( m_processingType == WP ) {
624 m_pageColumns = cl;
625 }
626 if ( m_processingType == DTP || isEmbedded() ) {
627 m_pageLayout.ptLeft = 0;
628 m_pageLayout.ptRight = 0;
629 m_pageLayout.ptTop = 0;
630 m_pageLayout.ptBottom = 0;
631 }
632 pageManager()->setDefaultPage(m_pageLayout);
633 m_pageHeaderFooter = hf;
634
635 // pages have a different size -> update framesInPage
636 // TODO: it would be better to move stuff so that text boxes remain in the same page...
637 // (page-number preservation instead of Y preservation)
638 updateAllFrames( KWFrameSet::UpdateFramesInPage );
639
640 recalcFrames();
641
642 updateAllFrames();
643
644 if ( updateViews )
645 {
646 // Invalidate document layout, for proper repaint
647 this->layout();
648 emit pageLayoutChanged( m_pageLayout );
649 updateContentsSize();
650 }
651}
652
653
654double KWDocument::ptColumnWidth() const
655{
656 KWPage *page = pageManager()->page(pageManager()->startPage());
657 return ( page->width() - page->leftMargin() - page->rightMargin() -
658 ptColumnSpacing() * ( m_pageColumns.columns - 1 ) )
659 / m_pageColumns.columns;
660}
661
662class KWFootNoteFrameSetList : public TQPtrList<KWFootNoteFrameSet>
663{
664public:
665 KWFootNoteFrameSetList( bool reversed ) : m_reversed( reversed ) {}
666protected:
667 // Compare the order of the associated variables
668 virtual int compareItems(TQPtrCollection::Item a, TQPtrCollection::Item b)
669 {
670 KWFootNoteFrameSet* fsa = ((KWFootNoteFrameSet *)a);
671 KWFootNoteFrameSet* fsb = ((KWFootNoteFrameSet *)b);
672 Q_ASSERT( fsa->footNoteVariable() );
673 Q_ASSERT( fsb->footNoteVariable() );
674 if ( fsa->footNoteVariable() && fsb->footNoteVariable() )
675 {
676 int numa = fsa->footNoteVariable()->num();
677 int numb = fsb->footNoteVariable()->num();
678 if (numa == numb) return 0;
679 if (numa > numb) return m_reversed ? -1 : 1;
680 return m_reversed ? 1 : -1;
681 }
682 return -1; // whatever
683 }
684private:
685 bool m_reversed;
686};
687
688/* append headers and footers if needed, and create enough pages for all the existing frames */
689void KWDocument::recalcFrames( int fromPage, int toPage /*-1 for all*/, uint flags )
690{
691 fromPage = TQMAX(pageManager()->startPage(), fromPage);
692 if ( m_lstFrameSet.isEmpty() )
693 return;
694 //printDebug();
695 kdDebug(32002) << "KWDocument::recalcFrames from=" << fromPage << " to=" << toPage << endl;
696
697 KWFrameSet *frameset = m_lstFrameSet.getFirst();
698
699 if ( m_processingType == WP ) { // In WP mode the pages are created automatically. In DTP not...
700
701 KWTextFrameSet *firstHeader = 0L, *evenHeader = 0L, *oddHeader = 0L;
702 KWTextFrameSet *firstFooter = 0L, *evenFooter = 0L, *oddFooter = 0L;
703 m_bHasEndNotes = false; // will be set to true if we find any endnote
704
705 // Lookup the various header / footer framesets into the variables above
706 // [Done in all cases, in order to hide unused framesets]
707
708 KWFootNoteFrameSetList footnotesList( true ); // Reversed, we want footnotes from bottom to top
709 KWFootNoteFrameSetList endnotesList( false ); // Endnotes are in top to bottom order
710 TQPtrListIterator<KWFrameSet> fit = framesetsIterator();
711 for ( ; fit.current() ; ++fit )
712 {
713 KWFrameSet * fs = fit.current();
714 switch ( fs->frameSetInfo() ) {
715 case KWFrameSet::FI_FIRST_HEADER:
716 if ( isHeaderVisible() ) {
717 firstHeader = dynamic_cast<KWTextFrameSet*>( fs );
718 } else { fs->setVisible( false ); fs->deleteAllCopies(); }
719 break;
720 case KWFrameSet::FI_ODD_HEADER:
721 if ( isHeaderVisible() ) {
722 oddHeader = dynamic_cast<KWTextFrameSet*>( fs );
723 } else { fs->setVisible( false ); fs->deleteAllCopies(); }
724 break;
725 case KWFrameSet::FI_EVEN_HEADER:
726 if ( isHeaderVisible() ) {
727 evenHeader = dynamic_cast<KWTextFrameSet*>( fs );
728 } else { fs->setVisible( false ); fs->deleteAllCopies(); }
729 break;
730 case KWFrameSet::FI_FIRST_FOOTER:
731 if ( isFooterVisible() ) {
732 firstFooter = dynamic_cast<KWTextFrameSet*>( fs );
733 } else { fs->setVisible( false ); fs->deleteAllCopies(); }
734 break;
735 case KWFrameSet::FI_ODD_FOOTER:
736 if ( isFooterVisible() ) {
737 oddFooter = dynamic_cast<KWTextFrameSet*>( fs );
738 } else { fs->setVisible( false ); fs->deleteAllCopies(); }
739 break;
740 case KWFrameSet::FI_EVEN_FOOTER:
741 if ( isFooterVisible() ) {
742 evenFooter = dynamic_cast<KWTextFrameSet*>( fs );
743 } else { fs->setVisible( false ); fs->deleteAllCopies(); }
744 break;
745 case KWFrameSet::FI_FOOTNOTE: {
746 KWFootNoteFrameSet* fnfs = dynamic_cast<KWFootNoteFrameSet *>(fs);
747 if ( fnfs && fnfs->isVisible() ) // not visible is when the footnote has been deleted
748 {
749 if ( fnfs->isFootNote() )
750 footnotesList.append( fnfs );
751 else if ( fnfs->isEndNote() ) {
752 endnotesList.append( fnfs );
753 m_bHasEndNotes = true;
754 }
755 }
756 }
757 break;
758 default: break;
759 }
760 }
761
762 // This allocation each time might slow things down a bit.
763 // TODO KWHeaderFooterFrameSet : public KWTextFrameSet, and store the HeaderFooterFrameset data into there.
764 // ... hmm, and then KWFootNoteFrameSet needs to inherit KWHeaderFooterFrameSet
765 TQPtrList<KWFrameLayout::HeaderFooterFrameset> headerFooterList;
766 headerFooterList.setAutoDelete( true );
767 const int firstPageNum = startPage();
768
769 // Now hide & forget the unused header/footer framesets (e.g. 'odd pages' if we are in 'all the same' mode etc.)
770 if ( isHeaderVisible() ) {
771 Q_ASSERT( firstHeader );
772 Q_ASSERT( oddHeader );
773 Q_ASSERT( evenHeader );
774 switch ( headerType() ) {
775 case HF_SAME:
776 oddHeader->setVisible( true );
777 evenHeader->setVisible( false );
778 evenHeader->deleteAllCopies();
779 firstHeader->setVisible( false );
780 firstHeader->deleteAllCopies();
781
782 headerFooterList.append( new KWFrameLayout::HeaderFooterFrameset(
783 oddHeader, firstPageNum, -1, m_pageHeaderFooter.ptHeaderBodySpacing ) );
784 break;
785 case HF_FIRST_EO_DIFF: // added for koffice-1.2-beta2
786 firstHeader->setVisible( true );
787 oddHeader->setVisible( true );
788 evenHeader->setVisible( true );
789
790 headerFooterList.append( new KWFrameLayout::HeaderFooterFrameset(
791 firstHeader, firstPageNum, firstPageNum, m_pageHeaderFooter.ptHeaderBodySpacing ) );
792 headerFooterList.append( new KWFrameLayout::HeaderFooterFrameset(
793 oddHeader, firstPageNum + 2, -1, m_pageHeaderFooter.ptHeaderBodySpacing,
794 KWFrameLayout::HeaderFooterFrameset::Odd ) );
795 headerFooterList.append( new KWFrameLayout::HeaderFooterFrameset(
796 evenHeader, firstPageNum + 1, -1, m_pageHeaderFooter.ptHeaderBodySpacing,
797 KWFrameLayout::HeaderFooterFrameset::Even ) );
798 break;
799 case HF_FIRST_DIFF:
800 oddHeader->setVisible( true );
801 evenHeader->setVisible( false );
802 evenHeader->deleteAllCopies();
803 firstHeader->setVisible( true );
804
805 headerFooterList.append( new KWFrameLayout::HeaderFooterFrameset(
806 firstHeader, firstPageNum, firstPageNum, m_pageHeaderFooter.ptHeaderBodySpacing ) );
807 headerFooterList.append( new KWFrameLayout::HeaderFooterFrameset(
808 oddHeader, firstPageNum + 1, -1, m_pageHeaderFooter.ptHeaderBodySpacing ) );
809 break;
810 case HF_EO_DIFF:
811 oddHeader->setVisible( true );
812 evenHeader->setVisible( true );
813 firstHeader->setVisible( false );
814 firstHeader->deleteAllCopies();
815
816 headerFooterList.append( new KWFrameLayout::HeaderFooterFrameset(
817 oddHeader, firstPageNum, -1, m_pageHeaderFooter.ptHeaderBodySpacing,
818 KWFrameLayout::HeaderFooterFrameset::Odd ) );
819 headerFooterList.append( new KWFrameLayout::HeaderFooterFrameset(
820 evenHeader, firstPageNum + 1, -1, m_pageHeaderFooter.ptHeaderBodySpacing,
821 KWFrameLayout::HeaderFooterFrameset::Even ) );
822 break;
823 }
824 }
825 if ( isFooterVisible() ) {
826 Q_ASSERT( firstFooter );
827 Q_ASSERT( oddFooter );
828 Q_ASSERT( evenFooter );
829 switch ( footerType() ) {
830 case HF_SAME:
831 oddFooter->setVisible( true );
832 evenFooter->setVisible( false );
833 evenFooter->deleteAllCopies();
834 firstFooter->setVisible( false );
835 firstFooter->deleteAllCopies();
836
837 headerFooterList.append( new KWFrameLayout::HeaderFooterFrameset(
838 oddFooter, firstPageNum, -1, m_pageHeaderFooter.ptFooterBodySpacing ) );
839 break;
840 case HF_FIRST_EO_DIFF: // added for koffice-1.2-beta2
841 firstFooter->setVisible( true );
842 oddFooter->setVisible( true );
843 evenFooter->setVisible( true );
844
845 headerFooterList.append( new KWFrameLayout::HeaderFooterFrameset(
846 firstFooter, firstPageNum, firstPageNum, m_pageHeaderFooter.ptFooterBodySpacing ) );
847 headerFooterList.append( new KWFrameLayout::HeaderFooterFrameset(
848 oddFooter, firstPageNum + 2, -1, m_pageHeaderFooter.ptFooterBodySpacing,
849 KWFrameLayout::HeaderFooterFrameset::Odd ) );
850 headerFooterList.append( new KWFrameLayout::HeaderFooterFrameset(
851 evenFooter, firstPageNum + 1, -1, m_pageHeaderFooter.ptFooterBodySpacing,
852 KWFrameLayout::HeaderFooterFrameset::Even ) );
853 break;
854 case HF_FIRST_DIFF:
855 oddFooter->setVisible( true );
856 evenFooter->setVisible( false );
857 evenFooter->deleteAllCopies();
858 firstFooter->setVisible( true );
859
860 headerFooterList.append( new KWFrameLayout::HeaderFooterFrameset(
861 firstFooter, firstPageNum, firstPageNum, m_pageHeaderFooter.ptFooterBodySpacing ) );
862 headerFooterList.append( new KWFrameLayout::HeaderFooterFrameset(
863 oddFooter, firstPageNum + 1, -1, m_pageHeaderFooter.ptFooterBodySpacing ) );
864 break;
865 case HF_EO_DIFF:
866 oddFooter->setVisible( true );
867 evenFooter->setVisible( true );
868 firstFooter->setVisible( false );
869 firstFooter->deleteAllCopies();
870
871 headerFooterList.append( new KWFrameLayout::HeaderFooterFrameset(
872 oddFooter, firstPageNum, -1, m_pageHeaderFooter.ptFooterBodySpacing,
873 KWFrameLayout::HeaderFooterFrameset::Odd ) );
874 headerFooterList.append( new KWFrameLayout::HeaderFooterFrameset(
875 evenFooter, firstPageNum + 1, -1, m_pageHeaderFooter.ptFooterBodySpacing,
876 KWFrameLayout::HeaderFooterFrameset::Even ) );
877 break;
878 }
879 }
880
881 // The frameset order _on screen_ is:
882 // Header
883 // Main text frame (if WP)
884 // Footnote_s_
885 // Footer
886 // In the list it will have to be from top and from bottom:
887 // Header, Footer, Footnote from bottom to top
888 TQPtrList<KWFrameLayout::HeaderFooterFrameset> footnotesHFList;
889 footnotesHFList.setAutoDelete( true );
890
891 footnotesList.sort();
892 TQPtrListIterator<KWFootNoteFrameSet> fnfsIt( footnotesList ); // fnfs == "footnote frameset"
893 for ( ; fnfsIt.current() ; ++fnfsIt )
894 {
895 KWFootNoteFrameSet* fnfs = fnfsIt.current();
896 int pageNum = -42; //fnfs->footNoteVariable()->pageNumber(); // determined by KWFrameLayout
897 KWFrameLayout::HeaderFooterFrameset* hff = new KWFrameLayout::HeaderFooterFrameset(
898 fnfs, pageNum, pageNum,
899 m_pageHeaderFooter.ptFootNoteBodySpacing,
900 KWFrameLayout::HeaderFooterFrameset::All );
901
902 // With other kind of framesets, the height is simply frame->height.
903 // But for footnotes, the height to pass to KWFrameLayout is the sum of the frame heights.
904 hff->m_height = 0;
905 for (TQPtrListIterator<KWFrame> f = fnfs->frameIterator(); f.current() ; ++f )
906 hff->m_height += f.current()->height();
907
908 footnotesHFList.append( hff );
909 }
910
911 // Endnotes, however are laid out from top to bottom.
912 TQPtrList<KWFrameLayout::HeaderFooterFrameset> endnotesHFList;
913 endnotesHFList.setAutoDelete( true );
914
915 endnotesList.sort();
916 TQPtrListIterator<KWFootNoteFrameSet> enfsIt( endnotesList ); // enfs == "endnote frameset"
917 for ( ; enfsIt.current() ; ++enfsIt )
918 {
919 KWFootNoteFrameSet* enfs = enfsIt.current();
920 KWFrameLayout::HeaderFooterFrameset* hff = new KWFrameLayout::HeaderFooterFrameset(
921 enfs, -42, -42, // determined by KWFrameLayout
922 m_pageHeaderFooter.ptFootNoteBodySpacing,
923 KWFrameLayout::HeaderFooterFrameset::All );
924
925 // The height to pass to KWFrameLayout is the sum of the frame heights.
926 hff->m_height = 0;
927 for (TQPtrListIterator<KWFrame> f = enfs->frameIterator(); f.current() ; ++f )
928 hff->m_height += f.current()->height();
929
930 endnotesHFList.append( hff );
931 }
932
933 // append pages as needed.
934 double maxBottom = 0;
935 for (TQPtrListIterator<KWFrameSet> fsit = framesetsIterator(); fsit.current() ; ++fsit ) {
936 KWFrameSet *fs = fsit.current();
937 if ( !fs->isVisible() || fs->isAHeader() || !fs->isAFooter() ||
938 !fs->isFloating() || !fs->isFootEndNote() )
939 continue;
940 for (TQPtrListIterator<KWFrame> fit = fs->frameIterator(); fit.current() ; ++fit )
941 maxBottom = TQMAX(maxBottom, fit.current()->bottom());
942 }
943 KWPage *last = pageManager()->page(lastPage());
944 double docHeight = last->offsetInDocument() + last->height();
945 while(docHeight <= maxBottom) {
946 last = pageManager()->appendPage();
947 docHeight += last->height();
948 }
949 int oldPages = pageCount();
950
951 if ( toPage == -1 )
952 toPage = lastPage();
953 if ( fromPage > toPage ) // this can happen with "endnotes only" pages :) // ### really?
954 fromPage = toPage; // ie. start at the last real page
955 KWFrameLayout frameLayout( this, headerFooterList, footnotesHFList, endnotesHFList );
956 frameLayout.layout( frameset, m_pageColumns.columns, fromPage, toPage, flags );
957
958 // If the number of pages changed, update views and variables etc.
959 // (now that the frame layout has been done)
960 if ( pageCount() != oldPages && !m_bGeneratingPreview )
961 {
962 // Very much like the end of appendPage, but we don't want to call recalcFrames ;)
963 emit newContentsSize();
964 emit numPagesChanged();
965 recalcVariables( VT_PGNUM );
966 }
967
968 }
969 else {
970 // DTP mode: calculate the number of pages from the frames.
971 double maxBottom=0;
972 for (TQPtrListIterator<KWFrameSet> fit = framesetsIterator(); fit.current() ; ++fit ) {
973 if(fit.current()->isDeleted()) continue;
974 if(fit.current()->frameSetInfo()==KWFrameSet::FI_BODY && !fit.current()->isFloating()) {
975 KWFrameSet * fs = fit.current();
976 for (TQPtrListIterator<KWFrame> f = fs->frameIterator(); f.current() ; ++f )
977 maxBottom=TQMAX(maxBottom, f.current()->bottom());
978 }
979 }
980 KWPage *last = pageManager()->page(lastPage());
981 Q_ASSERT(last);
982 if(last) { // hack to work around bug #132338
983 double docHeight = last->offsetInDocument() + last->height();
984 while(docHeight <= maxBottom) {
985 last = pageManager()->appendPage();
986 docHeight += last->height();
987 }
988 }
989 if ( toPage == -1 )
990 toPage = pageCount() - 1;
991 KWFrameList::recalcFrames(this, fromPage, toPage);
992 }
993 kdDebug(32002) << " ~recalcFrames" << endl;
994}
995
996bool KWDocument::loadChildren( KoStore *store )
997{
998 //kdDebug(32001) << "KWDocument::loadChildren" << endl;
999 TQPtrListIterator<KoDocumentChild> it( children() );
1000 for( ; it.current(); ++it ) {
1001 if ( !it.current()->loadDocument( store ) )
1002 return false;
1003 }
1004
1005 return true;
1006}
1007
1008void KWDocument::loadPictureMap ( TQDomElement& domElement )
1009{
1010 m_pictureMap.clear();
1011
1012 // <PICTURES>
1013 TQDomElement picturesElem = domElement.namedItem( "PICTURES" ).toElement();
1014 if ( !picturesElem.isNull() )
1015 {
1016 m_pictureCollection->readXML( picturesElem, m_pictureMap );
1017 }
1018
1019 // <PIXMAPS>
1020 TQDomElement pixmapsElem = domElement.namedItem( "PIXMAPS" ).toElement();
1021 if ( !pixmapsElem.isNull() )
1022 {
1023 m_pictureCollection->readXML( pixmapsElem, m_pictureMap );
1024 }
1025
1026 // <CLIPARTS>
1027 TQDomElement clipartsElem = domElement.namedItem( "CLIPARTS" ).toElement();
1028 if ( !clipartsElem.isNull() )
1029 {
1030 m_pictureCollection->readXML( pixmapsElem, m_pictureMap );
1031 }
1032}
1033
1034
1035bool KWDocument::loadOasis( const TQDomDocument& doc, KoOasisStyles& oasisStyles, const TQDomDocument& settings, KoStore* store )
1036{
1037 TQTime dt;
1038 dt.start();
1039 emit sigProgress( 0 );
1040 clear();
1041 kdDebug(32001) << "KWDocument::loadOasis" << endl;
1042
1043 TQDomElement content = doc.documentElement();
1044 TQDomElement realBody ( KoDom::namedItemNS( content, KoXmlNS::office, "body" ) );
1045 if ( realBody.isNull() )
1046 {
1047 kdError(32001) << "No office:body found!" << endl;
1048 setErrorMessage( i18n( "Invalid OASIS OpenDocument file. No office:body tag found." ) );
1049 return false;
1050 }
1051 TQDomElement body = KoDom::namedItemNS( realBody, KoXmlNS::office, "text" );
1052 if ( body.isNull() )
1053 {
1054 kdError(32001) << "No office:text found!" << endl;
1055 TQDomElement childElem;
1056 TQString localName;
1057 forEachElement( childElem, realBody ) {
1058 localName = childElem.localName();
1059 }
1060 if ( localName.isEmpty() )
1061 setErrorMessage( i18n( "Invalid OASIS OpenDocument file. No tag found inside office:body." ) );
1062 else
1063 setErrorMessage( i18n( "This is not a word processing document, but %1. Please try opening it with the appropriate application." ).arg( KoDocument::tagNameToDocumentType( localName ) ) );
1064 return false;
1065 }
1066
1067 // TODO check versions and mimetypes etc.
1068
1069 KoOasisContext context( this, *m_varColl, oasisStyles, store );
1070
1071 createLoadingInfo();
1072
1073 // In theory the page format is the style:master-page-name of the first paragraph...
1074 // But, hmm, in a doc with only a table there was no reference to the master page at all...
1075 // So we load the standard page layout to start with, and in KWTextParag
1076 // we might overwrite it with another one.
1077 m_loadingInfo->m_currentMasterPage = "Standard";
1078 if ( !loadOasisPageLayout( m_loadingInfo->m_currentMasterPage, context ) )
1079 return false;
1080
1081 KWOasisLoader oasisLoader( this );
1082
1083 // <text:page-sequence> oasis extension for DTP (2003-10-27 post by Daniel)
1084 m_processingType = ( !KoDom::namedItemNS( body, KoXmlNS::text, "page-sequence" ).isNull() )
1085 ? DTP : WP;
1086
1087 m_hasTOC = false;
1088 m_tabStop = MM_TO_POINT(15);
1089 const TQDomElement* defaultParagStyle = oasisStyles.defaultStyle( "paragraph" );
1090 if ( defaultParagStyle ) {
1091 KoStyleStack stack;
1092 stack.push( *defaultParagStyle );
1093 stack.setTypeProperties( "paragraph" );
1094 TQString tabStopVal = stack.attributeNS( KoXmlNS::style, "tab-stop-distance" );
1095 if ( !tabStopVal.isEmpty() )
1096 m_tabStop = KoUnit::parseValue( tabStopVal );
1097 }
1098 m_initialEditing = 0;
1099
1100 // TODO MAILMERGE
1101
1102 // Variable settings
1103 // By default display real variable value
1104 if ( !isReadWrite())
1105 m_varColl->variableSetting()->setDisplayFieldCode(false);
1106
1107 // Load all styles before the corresponding paragraphs try to use them!
1108 m_styleColl->loadOasisStyles( context );
1109 if ( m_frameStyleColl->loadOasisStyles( context ) == 0 ) {
1110 // no styles loaded -> load default styles
1111 loadDefaultFrameStyleTemplates();
1112 }
1113
1114 if ( m_tableStyleColl->loadOasisStyles( context, *m_styleColl, *m_frameStyleColl ) == 0 ) {
1115 // no styles loaded -> load default styles
1116 loadDefaultTableStyleTemplates();
1117 }
1118
1119 static_cast<KWVariableSettings *>( m_varColl->variableSetting() )
1120 ->loadNoteConfiguration( oasisStyles.officeStyle() );
1121
1122 loadDefaultTableTemplates();
1123
1124 if ( m_processingType == WP ) {
1125 // Create main frameset
1126 KWTextFrameSet *fs = new KWTextFrameSet( this, i18n( "Main Text Frameset" ) );
1127 m_lstFrameSet.append( fs ); // don't use addFrameSet here. We'll call finalize() once and for all in completeLoading
1128 fs->loadOasisContent( body, context );
1129 KWFrame* frame = new KWFrame( fs, 29, 42, 566-29, 798-42 );
1130 frame->setFrameBehavior( KWFrame::AutoCreateNewFrame );
1131 frame->setNewFrameBehavior( KWFrame::Reconnect );
1132 fs->addFrame( frame );
1133
1134 // load padding, background and borders for the main frame
1135 const TQDomElement* masterPage = context.oasisStyles().masterPages()[ m_loadingInfo->m_currentMasterPage ];
1136 const TQDomElement *masterPageStyle = masterPage ? context.oasisStyles().findStyle(masterPage->attributeNS( KoXmlNS::style, "page-layout-name", TQString() ) ) : 0;
1137 if ( masterPageStyle )
1138 {
1139 KoStyleStack styleStack;
1140 styleStack.push( *masterPageStyle );
1141 styleStack.setTypeProperties( "page-layout" );
1142 frame->loadBorderProperties( styleStack );
1143 }
1144 fs->renumberFootNotes( false /*no repaint*/ );
1145
1146 } else {
1147 // DTP mode: the items in the body are page-sequence and then frames
1148 TQDomElement tag;
1149 forEachElement( tag, body )
1150 {
1151 context.styleStack().save();
1152 const TQString localName = tag.localName();
1153 if ( localName == "page-sequence" && tag.namespaceURI() == KoXmlNS::text )
1154 {
1155 // We don't have support for changing the page layout yet, so just take the
1156 // number of pages
1157 int pages=1;
1158 TQDomElement page;
1159 forEachElement( page, tag )
1160 ++pages;
1161 kdDebug() << "DTP mode: found " << pages << "pages" << endl;
1162 //setPageCount ( pages );
1163 }
1164 else if ( localName == "frame" && tag.namespaceURI() == KoXmlNS::draw )
1165 oasisLoader.loadFrame( tag, context, KoPoint() );
1166 else
1167 kdWarning(32001) << "Unsupported tag in DTP loading:" << tag.tagName() << endl;
1168 }
1169 }
1170
1171 if ( !loadMasterPageStyle( m_loadingInfo->m_currentMasterPage, context ) )
1172 return false;
1173
1174 if ( context.cursorTextParagraph() ) {
1175 // Maybe, once 1.3-support is dropped, we can get rid of InitialEditing and fetch the
1176 // values from KoOasisContext? But well, it lives a bit longer.
1177 // At least we could store a KWFrameSet* and a KoTextParag* instead of a name and an id.
1178 m_initialEditing = new InitialEditing();
1179 KWTextFrameSet* fs = static_cast<KWTextDocument *>( context.cursorTextParagraph()->textDocument() )->textFrameSet();
1180 m_initialEditing->m_initialFrameSet = fs->name();
1181 m_initialEditing->m_initialCursorParag = context.cursorTextParagraph()->paragId();
1182 m_initialEditing->m_initialCursorIndex = context.cursorTextIndex();
1183 }
1184
1185 if ( !settings.isNull() )
1186 {
1187 oasisLoader.loadOasisSettings( settings );
1188 }
1189
1190 kdDebug(32001) << "Loading took " << (float)(dt.elapsed()) / 1000 << " seconds" << endl;
1191 endOfLoading();
1192
1193 // This sets the columns and header/footer flags, and calls recalcFrames,
1194 // so it must be done last.
1195 setPageLayout( m_pageLayout, m_loadingInfo->columns, m_loadingInfo->hf, false );
1196
1197 //printDebug();
1198 return true;
1199}
1200
1201bool KWDocument::loadOasisPageLayout( const TQString& masterPageName, KoOasisContext& context )
1202{
1203 KoColumns& columns = m_loadingInfo->columns;
1204
1205 const KoOasisStyles& oasisStyles = context.oasisStyles();
1206 const TQDomElement* masterPage = oasisStyles.masterPages()[ masterPageName ];
1207 Q_ASSERT( masterPage );
1208 const TQDomElement *masterPageStyle = masterPage ? oasisStyles.findStyle( masterPage->attributeNS( KoXmlNS::style, "page-layout-name", TQString() ) ) : 0;
1209 Q_ASSERT( masterPageStyle );
1210 if ( masterPageStyle )
1211 {
1212 m_pageLayout.loadOasis( *masterPageStyle );
1213 pageManager()->setDefaultPage(m_pageLayout);
1214
1215 const TQDomElement properties( KoDom::namedItemNS( *masterPageStyle, KoXmlNS::style, "page-layout-properties" ) );
1216 const TQDomElement footnoteSep = KoDom::namedItemNS( properties, KoXmlNS::style, "footnote-sep" );
1217 if ( !footnoteSep.isNull() ) {
1218 // style:width="0.018cm" style:distance-before-sep="0.101cm"
1219 // style:distance-after-sep="0.101cm" style:adjustment="left"
1220 // style:rel-width="25%" style:color="#000000"
1221 const TQString width = footnoteSep.attributeNS( KoXmlNS::style, "width", TQString() );
1222 if ( !width.isEmpty() ) {
1223 m_footNoteSeparatorLineWidth = KoUnit::parseValue( width );
1224 }
1225
1226 TQString pageWidth = footnoteSep.attributeNS( KoXmlNS::style, "rel-width", TQString() );
1227 if ( pageWidth.endsWith( "%" ) ) {
1228 pageWidth.truncate( pageWidth.length() - 1 ); // remove '%'
1229 m_iFootNoteSeparatorLineLength = tqRound( pageWidth.toDouble() );
1230 }
1231 // Not in KWord: color, distance before and after separator
1232
1233 const TQString style = footnoteSep.attributeNS( KoXmlNS::style, "line-style", TQString() );
1234 if ( style == "solid" || style.isEmpty() )
1235 m_footNoteSeparatorLineType = SLT_SOLID;
1236 else if ( style == "dash" )
1237 m_footNoteSeparatorLineType = SLT_DASH;
1238 else if ( style == "dotted" )
1239 m_footNoteSeparatorLineType = SLT_DOT;
1240 else if ( style == "dot-dash" )
1241 m_footNoteSeparatorLineType = SLT_DASH_DOT;
1242 else if ( style == "dot-dot-dash" )
1243 m_footNoteSeparatorLineType = SLT_DASH_DOT_DOT;
1244 else
1245 kdDebug() << "Unknown value for m_footNoteSeparatorLineType: " << style << endl;
1246
1247 const TQString pos = footnoteSep.attributeNS( KoXmlNS::style, "adjustment", TQString() );
1248 if ( pos == "centered" )
1249 m_footNoteSeparatorLinePos = SLP_CENTERED;
1250 else if ( pos == "right")
1251 m_footNoteSeparatorLinePos = SLP_RIGHT;
1252 else // if ( pos == "left" )
1253 m_footNoteSeparatorLinePos = SLP_LEFT;
1254 }
1255
1256 const TQDomElement columnsElem = KoDom::namedItemNS( properties, KoXmlNS::style, "columns" );
1257 if ( !columnsElem.isNull() )
1258 {
1259 columns.columns = columnsElem.attributeNS( KoXmlNS::fo, "column-count", TQString() ).toInt();
1260 if ( columns.columns == 0 )
1261 columns.columns = 1;
1262 // TODO OASIS OpenDocument supports columns of different sizes, using <style:column style:rel-width="...">
1263 // (with fo:start-indent/fo:end-indent for per-column spacing)
1264 // But well, it also allows us to specify a single gap.
1265 if ( columnsElem.hasAttributeNS( KoXmlNS::fo, "column-gap" ) )
1266 columns.ptColumnSpacing = KoUnit::parseValue( columnsElem.attributeNS( KoXmlNS::fo, "column-gap", TQString() ) );
1267 // It also supports drawing a vertical line as a separator...
1268 }
1269
1270 m_headerVisible = false;
1271 m_footerVisible = false;
1272
1273 // TODO spHeadBody (where is this in OOo?)
1274 // TODO spFootBody (where is this in OOo?)
1275 // Answer: margins of the <style:header-footer> element
1276 }
1277 else // this doesn't happen with normal documents, but it can happen if copying something,
1278 // pasting into konq as foo.odt, then opening that...
1279 {
1280 columns.columns = 1;
1281 columns.ptColumnSpacing = 2;
1282 m_headerVisible = false;
1283 m_footerVisible = false;
1284 m_pageLayout = KoPageLayout::standardLayout();
1285 pageManager()->setDefaultPage(m_pageLayout);
1286 }
1287 return true;
1288}
1289
1290bool KWDocument::loadMasterPageStyle( const TQString& masterPageName, KoOasisContext& context )
1291{
1292 const KoOasisStyles& oasisStyles = context.oasisStyles();
1293 const TQDomElement* masterPage = oasisStyles.masterPages()[ masterPageName ];
1294 Q_ASSERT( masterPage );
1295 const TQDomElement *masterPageStyle = masterPage ? oasisStyles.findStyle( masterPage->attributeNS( KoXmlNS::style, "page-layout-name", TQString() ) ) : 0;
1296 Q_ASSERT( masterPageStyle );
1297
1298 // This check is done here and not in loadOasisPageLayout in case the Standard master-page
1299 // has no page information but the first paragraph points to a master-page that does (#129585)
1300 if ( m_pageLayout.ptWidth <= 1e-13 || m_pageLayout.ptHeight <= 1e-13 )
1301 {
1302 // Loading page layout failed, try to see why.
1303 TQDomElement properties( KoDom::namedItemNS( *masterPageStyle, KoXmlNS::style, "page-layout-properties" ) );
1304 //if ( properties.isNull() )
1305 // setErrorMessage( i18n( "Invalid document. No page layout properties were found. The application which produced this document isn't OASIS-compliant." ) );
1306 //else if ( properties.hasAttributeNS( KoXmlNS::fo, "page-width" ) )
1307 // setErrorMessage( i18n( "Invalid document. Page layout has no page width. The application which produced this document isn't OASIS-compliant." ) );
1308 //else
1309 if ( properties.hasAttributeNS( "http://www.w3.org/1999/XSL/Format", "page-width" ) )
1310 setErrorMessage( i18n( "Invalid document. 'fo' has the wrong namespace. The application which produced this document is not OASIS-compliant." ) );
1311 else
1312 setErrorMessage( i18n( "Invalid document. Paper size: %1x%2" ).arg( m_pageLayout.ptWidth ).arg( m_pageLayout.ptHeight ) );
1313 return false;
1314 }
1315
1316
1317 KoKWHeaderFooter& hf = m_loadingInfo->hf;
1318
1319 bool hasEvenOddHeader = false;
1320 bool hasEvenOddFooter = false;
1321 if ( masterPageStyle )
1322 {
1323 KWOasisLoader oasisLoader( this );
1324
1325 TQDomElement headerStyle = KoDom::namedItemNS( *masterPageStyle, KoXmlNS::style, "header-style" );
1326 TQDomElement footerStyle = KoDom::namedItemNS( *masterPageStyle, KoXmlNS::style, "footer-style" );
1327 TQDomElement headerLeftElem = KoDom::namedItemNS( *masterPage, KoXmlNS::style, "header-left" );
1328 TQDomElement headerFirstElem = KoDom::namedItemNS( *masterPage, KoXmlNS::style, "header-first" ); // hack, not oasis compliant
1329 const bool hasFirstHeader = !headerFirstElem.isNull();
1330 if ( !headerLeftElem.isNull() )
1331 {
1332 hasEvenOddHeader = true;
1333 hf.header = hasFirstHeader ? HF_FIRST_EO_DIFF : HF_EO_DIFF;
1334 oasisLoader.loadOasisHeaderFooter( headerLeftElem, hasEvenOddHeader, headerStyle, context );
1335 }
1336 else
1337 {
1338 hf.header = hasFirstHeader ? HF_FIRST_DIFF : HF_SAME;
1339 }
1340 if ( hasFirstHeader )
1341 {
1342 oasisLoader.loadOasisHeaderFooter( headerFirstElem, hasEvenOddHeader, headerStyle, context );
1343 }
1344
1345 TQDomElement headerElem = KoDom::namedItemNS( *masterPage, KoXmlNS::style, "header" );
1346 if ( !headerElem.isNull() )
1347 {
1348 oasisLoader.loadOasisHeaderFooter( headerElem, hasEvenOddHeader, headerStyle, context );
1349 }
1350
1351 // -- and now footers
1352
1353 TQDomElement footerLeftElem = KoDom::namedItemNS( *masterPage, KoXmlNS::style, "footer-left" );
1354 TQDomElement footerFirstElem = KoDom::namedItemNS( *masterPage, KoXmlNS::style, "footer-first" ); // hack, not oasis compliant
1355 const bool hasFirstFooter = !footerFirstElem.isNull();
1356 if ( !footerLeftElem.isNull() )
1357 {
1358 hasEvenOddFooter = true;
1359 hf.footer = hasFirstFooter ? HF_FIRST_EO_DIFF : HF_EO_DIFF;
1360 oasisLoader.loadOasisHeaderFooter( footerLeftElem, hasEvenOddFooter, footerStyle, context );
1361 }
1362 else
1363 {
1364 hf.footer = hasFirstFooter ? HF_FIRST_DIFF : HF_SAME;
1365 }
1366 if ( hasFirstFooter )
1367 {
1368 oasisLoader.loadOasisHeaderFooter( footerFirstElem, hasEvenOddFooter, footerStyle, context );
1369 }
1370 TQDomElement footerElem = KoDom::namedItemNS( *masterPage, KoXmlNS::style, "footer" );
1371 if ( !footerElem.isNull() )
1372 {
1373 oasisLoader.loadOasisHeaderFooter( footerElem, hasEvenOddFooter, footerStyle, context );
1374 }
1375
1376 // The bottom margin of headers is what we call headerBodySpacing
1377 // (TODO support the 3 other margins)
1378 if ( !headerStyle.isNull() ) {
1379 context.styleStack().push( headerStyle );
1380 context.styleStack().setTypeProperties( "header-footer" );
1381 hf.ptHeaderBodySpacing = KoUnit::parseValue( context.styleStack().attributeNS( KoXmlNS::fo, "margin-bottom" ) );
1382 context.styleStack().pop();
1383 }
1384 // The top margin of footers is what we call footerBodySpacing
1385 // (TODO support the 3 other margins)
1386 if ( !footerStyle.isNull() ) {
1387 context.styleStack().push( footerStyle );
1388 context.styleStack().setTypeProperties( "header-footer" );
1389 hf.ptFooterBodySpacing = KoUnit::parseValue( context.styleStack().attributeNS( KoXmlNS::fo, "margin-top" ) );
1390 context.styleStack().pop();
1391 }
1392 // TODO ptFootNoteBodySpacing
1393 }
1394 return true;
1395}
1396
1397// Called before loading
1398// It's important to clear out anything that might be in the document already,
1399// for things like using DCOP to load multiple documents into the same KWDocument,
1400// or "reload" when kword is embedded into konqueror.
1401void KWDocument::clear()
1402{
1403 m_pictureMap.clear();
1404 m_textImageRequests.clear();
1405 m_pictureRequests.clear();
1406 m_anchorRequests.clear();
1407 m_footnoteVarRequests.clear();
1408 m_spellCheckIgnoreList.clear();
1409
1410 m_pageHeaderFooter.header = HF_SAME;
1411 m_pageHeaderFooter.footer = HF_SAME;
1412 m_pageHeaderFooter.ptHeaderBodySpacing = 10;
1413 m_pageHeaderFooter.ptFooterBodySpacing = 10;
1414 m_pageHeaderFooter.ptFootNoteBodySpacing = 10;
1415 m_pageColumns.columns = 1;
1416 m_pageColumns.ptColumnSpacing = m_defaultColumnSpacing;
1417 m_bHasEndNotes = false;
1418
1419 m_iFootNoteSeparatorLineLength = 20; // 20%, i.e. 1/5th
1420 m_footNoteSeparatorLineWidth = 0.5; // like in OOo
1421 m_footNoteSeparatorLineType = SLT_SOLID;
1422
1423 m_lstFrameSet.clear();
1424
1425 m_varColl->clear();
1426 m_pictureCollection->clear();
1427 m_varFormatCollection->clear();
1428
1429 m_styleColl->clear();
1430 m_frameStyleColl->clear();
1431 m_tableStyleColl->clear();
1432 m_tableTemplateColl->clear();
1433
1434 // Some simple import filters don't define any style,
1435 // so let's have a Standard style at least
1436 KoParagStyle * standardStyle = new KoParagStyle( "Standard" ); // This gets translated later on
1437 //kdDebug() << "KWDocument::KWDocument creating standardStyle " << standardStyle << endl;
1438 standardStyle->format().setFont( m_defaultFont );
1439 m_styleColl->addStyle( standardStyle );
1440
1441 // And let's do the same for framestyles
1442 KWFrameStyle * standardFrameStyle = new KWFrameStyle( "Plain" );
1443 standardFrameStyle->setBackgroundColor(TQt::white);
1444 standardFrameStyle->setTopBorder(KoBorder(TQt::black,KoBorder::SOLID,0));
1445 standardFrameStyle->setRightBorder(KoBorder(TQt::black,KoBorder::SOLID,0));
1446 standardFrameStyle->setLeftBorder(KoBorder(TQt::black,KoBorder::SOLID,0));
1447 standardFrameStyle->setBottomBorder(KoBorder(TQt::black,KoBorder::SOLID,0));
1448 m_frameStyleColl->addStyle( standardFrameStyle );
1449
1450 // And let's do the same for tablestyles
1451 KWTableStyle *standardTableStyle = new KWTableStyle( "Plain", standardStyle, standardFrameStyle );
1452 m_tableStyleColl->addStyle( standardTableStyle );
1453}
1454
1455bool KWDocument::loadXML( TQIODevice *, const TQDomDocument & doc )
1456{
1457 TQTime dt;
1458 dt.start();
1459 emit sigProgress( 0 );
1460 kdDebug(32001) << "KWDocument::loadXML" << endl;
1461 clear();
1462
1463 KoPageLayout pgLayout;
1464 KoColumns columns;
1465 columns.columns = 1;
1466 columns.ptColumnSpacing = m_defaultColumnSpacing;
1467 KoKWHeaderFooter hf;
1468 hf.header = HF_SAME;
1469 hf.footer = HF_SAME;
1470 hf.ptHeaderBodySpacing = 10.0;
1471 hf.ptFooterBodySpacing = 10.0;
1472 hf.ptFootNoteBodySpacing = 10.0;
1473
1474 TQString value;
1475 TQDomElement word = doc.documentElement();
1476
1477 value = KWDocument::getAttribute( word, "mime", TQString() );
1478 if ( value.isEmpty() )
1479 {
1480 kdError(32001) << "No mime type specified!" << endl;
1481 setErrorMessage( i18n( "Invalid document. No mimetype specified." ) );
1482 return false;
1483 }
1484 else if ( value != "application/x-kword" && value != "application/vnd.kde.kword" )
1485 {
1486 kdError(32001) << "Unknown mime type " << value << endl;
1487 setErrorMessage( i18n( "Invalid document. Expected mimetype application/x-kword or application/vnd.kde.kword, got %1" ).arg( value ) );
1488 return false;
1489 }
1490 m_syntaxVersion = KWDocument::getAttribute( word, "syntaxVersion", 0 );
1491 if ( m_syntaxVersion > CURRENT_SYNTAX_VERSION )
1492 {
1493 int ret = KMessageBox::warningContinueCancel(
1494 0, i18n("This document was created with a newer version of KWord (syntax version: %1)\n"
1495 "Opening it in this version of KWord will lose some information.").arg(m_syntaxVersion),
1496 i18n("File Format Mismatch"), KStdGuiItem::cont() );
1497 if ( ret == KMessageBox::Cancel )
1498 {
1499 setErrorMessage( "USER_CANCELED" );
1500 return false;
1501 }
1502 }
1503
1504 createLoadingInfo();
1505
1506 // Looks like support for the old way of naming images internally,
1507 // see completeLoading.
1508 value = KWDocument::getAttribute( word, "url", TQString() );
1509 if ( !value.isNull() )
1510 {
1511 m_urlIntern = KURL( value ).path();
1512 }
1513
1514 emit sigProgress(5);
1515
1516 // <PAPER>
1517 TQDomElement paper = word.namedItem( "PAPER" ).toElement();
1518 if ( !paper.isNull() )
1519 {
1520 pgLayout.format = static_cast<KoFormat>( KWDocument::getAttribute( paper, "format", 0 ) );
1521 pgLayout.orientation = static_cast<KoOrientation>( KWDocument::getAttribute( paper, "orientation", 0 ) );
1522 pgLayout.ptWidth = getAttribute( paper, "width", 0.0 );
1523 pgLayout.ptHeight = getAttribute( paper, "height", 0.0 );
1524 kdDebug() << " ptWidth=" << pgLayout.ptWidth << endl;
1525 kdDebug() << " ptHeight=" << pgLayout.ptHeight << endl;
1526 if ( pgLayout.ptWidth <= 0 || pgLayout.ptHeight <= 0 )
1527 {
1528 // Old document?
1529 pgLayout.ptWidth = getAttribute( paper, "ptWidth", 0.0 );
1530 pgLayout.ptHeight = getAttribute( paper, "ptHeight", 0.0 );
1531 kdDebug() << " ptWidth=" << pgLayout.ptWidth << endl;
1532 kdDebug() << " ptHeight=" << pgLayout.ptHeight << endl;
1533
1534 // Still wrong?
1535 if ( pgLayout.ptWidth <= 0 || pgLayout.ptHeight <= 0 )
1536 {
1537 setErrorMessage( i18n( "Invalid document. Paper size: %1x%2" )
1538 .arg( pgLayout.ptWidth ).arg( pgLayout.ptHeight ) );
1539 return false;
1540 }
1541 }
1542
1543 hf.header = static_cast<KoHFType>( KWDocument::getAttribute( paper, "hType", 0 ) );
1544 hf.footer = static_cast<KoHFType>( KWDocument::getAttribute( paper, "fType", 0 ) );
1545 hf.ptHeaderBodySpacing = getAttribute( paper, "spHeadBody", 0.0 );
1546 hf.ptFooterBodySpacing = getAttribute( paper, "spFootBody", 0.0 );
1547 hf.ptFootNoteBodySpacing = getAttribute( paper, "spFootNoteBody", 10.0 );
1548 m_iFootNoteSeparatorLineLength = getAttribute( paper, "slFootNoteLength", 20);
1549 if ( paper.hasAttribute( "slFootNoteWidth" ) )
1550 m_footNoteSeparatorLineWidth = paper.attribute( "slFootNoteWidth" ).toDouble();
1551 m_footNoteSeparatorLineType = static_cast<SeparatorLineLineType>(getAttribute( paper, "slFootNoteType",0));
1552
1553 if ( paper.hasAttribute("slFootNotePosition"))
1554 {
1555 TQString tmp =paper.attribute("slFootNotePosition");
1556 if ( tmp =="centered" )
1557 m_footNoteSeparatorLinePos = SLP_CENTERED;
1558 else if ( tmp =="right")
1559 m_footNoteSeparatorLinePos = SLP_RIGHT;
1560 else if ( tmp =="left" )
1561 m_footNoteSeparatorLinePos = SLP_LEFT;
1562 }
1563 columns.columns = KWDocument::getAttribute( paper, "columns", 1 );
1564 columns.ptColumnSpacing = KWDocument::getAttribute( paper, "columnspacing", 0.0 );
1565 // Now part of the app config
1566 //m_zoom = KWDocument::getAttribute( paper, "zoom", 100 );
1567 //if(m_zoom!=100)
1568 // setZoomAndResolution( m_zoom, KoGlobal::dpiX(), KoGlobal::dpiY(), false, false );
1569
1570
1571 // Support the undocumented syntax actually used by KDE 2.0 for some of the above (:-().
1572 // Do not add anything to this block!
1573 if ( pgLayout.ptWidth == 0.0 )
1574 pgLayout.ptWidth = getAttribute( paper, "ptWidth", 0.0 );
1575 if ( pgLayout.ptHeight == 0.0 )
1576 pgLayout.ptHeight = getAttribute( paper, "ptHeight", 0.0 );
1577 if ( hf.ptHeaderBodySpacing == 0.0 )
1578 hf.ptHeaderBodySpacing = getAttribute( paper, "ptHeadBody", 0.0 );
1579 if ( hf.ptFooterBodySpacing == 0.0 )
1580 hf.ptFooterBodySpacing = getAttribute( paper, "ptFootBody", 0.0 );
1581 if ( columns.ptColumnSpacing == 0.0 )
1582 columns.ptColumnSpacing = getAttribute( paper, "ptColumnspc", 0.0 );
1583
1584 // <PAPERBORDERS>
1585 TQDomElement paperborders = paper.namedItem( "PAPERBORDERS" ).toElement();
1586 if ( !paperborders.isNull() )
1587 {
1588 pgLayout.ptLeft = getAttribute( paperborders, "left", 0.0 );
1589 pgLayout.ptTop = getAttribute( paperborders, "top", 0.0 );
1590 pgLayout.ptRight = getAttribute( paperborders, "right", 0.0 );
1591 pgLayout.ptBottom = getAttribute( paperborders, "bottom", 0.0 );
1592
1593 // Support the undocumented syntax actually used by KDE 2.0 for some of the above (:-().
1594 if ( pgLayout.ptLeft == 0.0 )
1595 pgLayout.ptLeft = getAttribute( paperborders, "ptLeft", 0.0 );
1596 if ( pgLayout.ptTop == 0.0 )
1597 pgLayout.ptTop = getAttribute( paperborders, "ptTop", 0.0 );
1598 if ( pgLayout.ptRight == 0.0 )
1599 pgLayout.ptRight = getAttribute( paperborders, "ptRight", 0.0 );
1600 if ( pgLayout.ptBottom == 0.0 )
1601 pgLayout.ptBottom = getAttribute( paperborders, "ptBottom", 0.0 );
1602 }
1603 else
1604 kdWarning() << "No <PAPERBORDERS> tag!" << endl;
1605 }
1606 else
1607 kdWarning() << "No <PAPER> tag! This is a mandatory tag! Expect weird page sizes..." << endl;
1608
1609 // <ATTRIBUTES>
1610 TQDomElement attributes = word.namedItem( "ATTRIBUTES" ).toElement();
1611 if ( !attributes.isNull() )
1612 {
1613 m_processingType = static_cast<ProcessingType>( KWDocument::getAttribute( attributes, "processing", 0 ) );
1614 //KWDocument::getAttribute( attributes, "standardpage", TQString() );
1615 m_headerVisible = static_cast<bool>( KWDocument::getAttribute( attributes, "hasHeader", 0 ) );
1616 m_footerVisible = static_cast<bool>( KWDocument::getAttribute( attributes, "hasFooter", 0 ) );
1617 if ( attributes.hasAttribute( "unit" ) )
1618 setUnit( KoUnit::unit( attributes.attribute( "unit" ) ) );
1619 m_hasTOC = static_cast<bool>(KWDocument::getAttribute( attributes,"hasTOC", 0 ) );
1620 m_tabStop = KWDocument::getAttribute( attributes, "tabStopValue", MM_TO_POINT(15) );
1621 m_initialEditing = new InitialEditing();
1622 m_initialEditing->m_initialFrameSet = attributes.attribute( "activeFrameset" );
1623 m_initialEditing->m_initialCursorParag = attributes.attribute( "cursorParagraph" ).toInt();
1624 m_initialEditing->m_initialCursorIndex = attributes.attribute( "cursorIndex" ).toInt();
1625 } else {
1626 m_processingType = WP;
1627 m_headerVisible = false;
1628 m_footerVisible = false;
1629 m_hasTOC = false;
1630 m_tabStop = MM_TO_POINT(15);
1631 delete m_initialEditing;
1632 m_initialEditing = 0L;
1633 }
1634
1635 setPageLayout( pgLayout, columns, hf, false );
1636
1637 variableCollection()->variableSetting()->load(word );
1638 //by default display real variable value
1639 if ( !isReadWrite())
1640 variableCollection()->variableSetting()->setDisplayFieldCode(false);
1641
1642 emit sigProgress(10);
1643
1644 TQDomElement mailmerge = word.namedItem( "MAILMERGE" ).toElement();
1645 if (mailmerge!=TQDomElement())
1646 {
1647 m_slDataBase->load(mailmerge);
1648 }
1649
1650 emit sigProgress(15);
1651
1652 // Load all styles before the corresponding paragraphs try to use them!
1653 TQDomElement stylesElem = word.namedItem( "STYLES" ).toElement();
1654 if ( !stylesElem.isNull() )
1655 loadStyleTemplates( stylesElem );
1656
1657 emit sigProgress(17);
1658
1659 TQDomElement frameStylesElem = word.namedItem( "FRAMESTYLES" ).toElement();
1660 if ( !frameStylesElem.isNull() )
1661 loadFrameStyleTemplates( frameStylesElem );
1662 else // load default styles
1663 loadDefaultFrameStyleTemplates();
1664
1665 emit sigProgress(18);
1666
1667 TQDomElement tableStylesElem = word.namedItem( "TABLESTYLES" ).toElement();
1668 if ( !tableStylesElem.isNull() )
1669 loadTableStyleTemplates( tableStylesElem );
1670 else // load default styles
1671 loadDefaultTableStyleTemplates();
1672
1673 emit sigProgress(19);
1674
1675 loadDefaultTableTemplates();
1676
1677 emit sigProgress(20);
1678
1679 TQDomElement bookmark = word.namedItem( "BOOKMARKS" ).toElement();
1680 if( !bookmark.isNull() )
1681 {
1682 TQDomElement bookmarkitem = word.namedItem("BOOKMARKS").toElement();
1683 bookmarkitem = bookmarkitem.firstChild().toElement();
1684
1685 while ( !bookmarkitem.isNull() )
1686 {
1687 if ( bookmarkitem.tagName() == "BOOKMARKITEM" )
1688 {
1689 KWLoadingInfo::BookMark bk;
1690 bk.bookname=bookmarkitem.attribute("name");
1691 bk.cursorStartIndex=bookmarkitem.attribute("cursorIndexStart").toInt();
1692 bk.frameSetName=bookmarkitem.attribute("frameset");
1693 bk.paragStartIndex = bookmarkitem.attribute("startparag").toInt();
1694 bk.paragEndIndex = bookmarkitem.attribute("endparag").toInt();
1695 bk.cursorEndIndex = bookmarkitem.attribute("cursorIndexEnd").toInt();
1696 Q_ASSERT( m_loadingInfo );
1697 m_loadingInfo->bookMarkList.append( bk );
1698 }
1699 bookmarkitem = bookmarkitem.nextSibling().toElement();
1700 }
1701 }
1702
1703 TQStringList lst;
1704 TQDomElement spellCheckIgnore = word.namedItem( "SPELLCHECKIGNORELIST" ).toElement();
1705 if( !spellCheckIgnore.isNull() )
1706 {
1707 TQDomElement spellWord=word.namedItem("SPELLCHECKIGNORELIST").toElement();
1708 spellWord=spellWord.firstChild().toElement();
1709 while ( !spellWord.isNull() )
1710 {
1711 if ( spellWord.tagName()=="SPELLCHECKIGNOREWORD" )
1712 lst.append(spellWord.attribute("word"));
1713 spellWord=spellWord.nextSibling().toElement();
1714 }
1715 }
1716 setSpellCheckIgnoreList( lst );
1717
1718 emit sigProgress(25);
1719
1720
1721 TQDomElement framesets = word.namedItem( "FRAMESETS" ).toElement();
1722 if ( !framesets.isNull() )
1723 loadFrameSets( framesets );
1724
1725 emit sigProgress(85);
1726
1727 loadPictureMap( word );
1728
1729 emit sigProgress(90);
1730
1731 // <EMBEDDED>
1732 loadEmbeddedObjects( word );
1733
1734 emit sigProgress(100); // the rest is only processing, not loading
1735
1736 kdDebug(32001) << "Loading took " << (float)(dt.elapsed()) / 1000 << " seconds" << endl;
1737
1738 endOfLoading();
1739 return true;
1740}
1741
1742void KWDocument::endOfLoading() // called by both oasis and oldxml
1743{
1744 // insert pages
1745 double maxBottom = 0;
1746 for (TQPtrListIterator<KWFrameSet> fsit = framesetsIterator(); fsit.current() ; ++fsit ) {
1747 KWFrameSet *fs = fsit.current();
1748 for (TQPtrListIterator<KWFrame> fit = fs->frameIterator(); fit.current() ; ++fit ) {
1749 KWFrame *frame = fit.current();
1750 maxBottom = TQMAX(maxBottom, frame->bottom());
1751 }
1752 }
1753 KWPage *last = pageManager()->page(lastPage());
1754 double docHeight = last->offsetInDocument() + last->height();
1755 while(docHeight <= maxBottom) {
1756 kdDebug(32001) << "KWDocument::loadXML appends a page\n";
1757 last = pageManager()->appendPage();
1758 docHeight += last->height();
1759 }
1760
1761 bool first_footer = false, even_footer = false, odd_footer = false;
1762 bool first_header = false, even_header = false, odd_header = false;
1763
1764 TQPtrListIterator<KWFrameSet> fit = framesetsIterator();
1765 for ( ; fit.current() ; ++fit )
1766 {
1767 switch( fit.current()->frameSetInfo() ) {
1768 case KWFrameSet::FI_FIRST_HEADER: first_header = true; break;
1769 case KWFrameSet::FI_ODD_HEADER: odd_header = true; break;
1770 case KWFrameSet::FI_EVEN_HEADER: even_header = true; break;
1771 case KWFrameSet::FI_FIRST_FOOTER: first_footer = true; break;
1772 case KWFrameSet::FI_ODD_FOOTER: odd_footer = true; break;
1773 case KWFrameSet::FI_EVEN_FOOTER: even_footer = true; break;
1774 case KWFrameSet::FI_FOOTNOTE: break;
1775 default: break;
1776 }
1777 }
1778
1779 // Create defaults if they were not in the input file.
1780
1781 // Where to insert the new frames: not at the end, since that breaks oasis-kword.sh
1782 uint newFramesetsIndex = m_lstFrameSet.isEmpty() ? 0 : 1;
1783
1784 if ( !first_header ) {
1785 KWTextFrameSet *fs = new KWTextFrameSet( this, i18n( "First Page Header" ) );
1786 //kdDebug(32001) << "KWDocument::loadXML KWTextFrameSet created " << fs << endl;
1787 fs->setFrameSetInfo( KWFrameSet::FI_FIRST_HEADER );
1788 KWPage *page = pageManager()->page(startPage());
1789 KWFrame *frame = new KWFrame(fs, page->leftMargin(), page->topMargin(),
1790 page->width() - page->leftMargin() - page->rightMargin(), 20 );
1791 //kdDebug(32001) << "KWDocument::loadXML KWFrame created " << frame << endl;
1792 frame->setFrameBehavior( KWFrame::AutoExtendFrame );
1793 frame->setNewFrameBehavior( KWFrame::Copy );
1794 fs->addFrame( frame );
1795 m_lstFrameSet.insert( newFramesetsIndex++, fs );
1796 }
1797
1798 if ( !odd_header ) {
1799 KWTextFrameSet *fs = new KWTextFrameSet( this, i18n( "Odd Pages Header" ) );
1800 //kdDebug(32001) << "KWDocument::loadXML KWTextFrameSet created " << fs << endl;
1801 fs->setFrameSetInfo( KWFrameSet::FI_ODD_HEADER );
1802 KWPage *page = pageManager()->page(TQMIN(startPage()+2, lastPage()));
1803 KWFrame *frame = new KWFrame(fs, page->leftMargin(), page->topMargin(),
1804 page->width() - page->leftMargin() - page->rightMargin(), 20 );
1805 //kdDebug(32001) << "KWDocument::loadXML KWFrame created " << *frame << endl;
1806 frame->setFrameBehavior( KWFrame::AutoExtendFrame );
1807 frame->setNewFrameBehavior( KWFrame::Copy );
1808 fs->addFrame( frame );
1809 m_lstFrameSet.insert( newFramesetsIndex++, fs );
1810 }
1811
1812 if ( !even_header ) {
1813 KWTextFrameSet *fs = new KWTextFrameSet( this, i18n( "Even Pages Header" ) );
1814 //kdDebug(32001) << "KWDocument::loadXML KWTextFrameSet created " << fs << endl;
1815 fs->setFrameSetInfo( KWFrameSet::FI_EVEN_HEADER );
1816 KWPage *page = pageManager()->page(TQMIN(startPage()+1, lastPage()));
1817 KWFrame *frame = new KWFrame(fs, page->leftMargin(), page->topMargin(), page->width() -
1818 page->leftMargin() - page->rightMargin(), 20 );
1819 //kdDebug(32001) << "KWDocument::loadXML KWFrame created " << *frame << endl;
1820 frame->setFrameBehavior( KWFrame::AutoExtendFrame );
1821 frame->setNewFrameBehavior( KWFrame::Copy );
1822 fs->addFrame( frame );
1823 m_lstFrameSet.insert( newFramesetsIndex++, fs );
1824 }
1825
1826 if ( !first_footer ) {
1827 KWTextFrameSet *fs = new KWTextFrameSet( this, i18n( "First Page Footer" ) );
1828 //kdDebug(32001) << "KWDocument::loadXML KWTextFrameSet created " << fs << endl;
1829 fs->setFrameSetInfo( KWFrameSet::FI_FIRST_FOOTER );
1830 KWPage *page = pageManager()->page(pageManager()->startPage());
1831 KWFrame *frame = new KWFrame(fs, page->leftMargin(), page->height() - page->topMargin()- 20,
1832 page->width() - page->leftMargin() - page->rightMargin(), 20 );
1833 //kdDebug(32001) << "KWDocument::loadXML KWFrame created " << *frame << endl;
1834 frame->setFrameBehavior( KWFrame::AutoExtendFrame );
1835 frame->setNewFrameBehavior( KWFrame::Copy );
1836 fs->addFrame( frame );
1837 m_lstFrameSet.insert( newFramesetsIndex++, fs );
1838 }
1839
1840 if ( !odd_footer ) {
1841 KWTextFrameSet *fs = new KWTextFrameSet( this, i18n( "Odd Pages Footer" ) );
1842 //kdDebug(32001) << "KWDocument::loadXML KWTextFrameSet created " << fs << endl;
1843 fs->setFrameSetInfo( KWFrameSet::FI_ODD_FOOTER );
1844 KWPage *page = pageManager()->page(TQMIN(startPage()+2, lastPage()));
1845 KWFrame *frame = new KWFrame(fs, page->leftMargin(), page->height()- page->topMargin() - 20,
1846 page->width() - page->leftMargin() - page->rightMargin(), 20 );
1847 //kdDebug(32001) << "KWDocument::loadXML KWFrame created " << *frame << endl;
1848 frame->setFrameBehavior( KWFrame::AutoExtendFrame );
1849 frame->setNewFrameBehavior( KWFrame::Copy );
1850 fs->addFrame( frame );
1851 m_lstFrameSet.insert( newFramesetsIndex++, fs );
1852 }
1853
1854 if ( !even_footer ) {
1855 KWTextFrameSet *fs = new KWTextFrameSet( this, i18n( "Even Pages Footer" ) );
1856 //kdDebug(32001) << "KWDocument::loadXML KWTextFrameSet created " << fs << endl;
1857 fs->setFrameSetInfo( KWFrameSet::FI_EVEN_FOOTER );
1858 KWPage *page = pageManager()->page(TQMIN(startPage()+1, lastPage()));
1859 KWFrame *frame = new KWFrame(fs, page->leftMargin(), page->height() - page->topMargin()- 20,
1860 page->width() - page->leftMargin() - page->rightMargin(), 20 );
1861 //kdDebug(32001) << "KWDocument::loadXML KWFrame created " << *frame << endl;
1862 frame->setFrameBehavior( KWFrame::AutoExtendFrame );
1863 frame->setNewFrameBehavior( KWFrame::Copy );
1864 fs->addFrame( frame );
1865 m_lstFrameSet.insert( newFramesetsIndex++, fs );
1866 }
1867
1868 // do some sanity checking on document.
1869 for (int i = frameSetCount()-1; i>-1; i--) {
1870 KWFrameSet *fs = frameSet(i);
1871 if(!fs) {
1872 kdWarning() << "frameset " << i << " is NULL!!" << endl;
1873 m_lstFrameSet.remove(i);
1874 continue;
1875 }
1876 if( fs->type()==FT_TABLE) {
1877 static_cast<KWTableFrameSet *>( fs )->validate();
1878 } else if (fs->type() == FT_TEXT) {
1879 for (int f=fs->frameCount()-1; f>=0; f--) {
1880 KWFrame *frame = fs->frame(f);
1881 if(frame->left() < 0) {
1882 kdWarning() << fs->name() << " frame " << f << " pos.x is < 0, moving frame" << endl;
1883 frame->moveBy( 0- frame->left(), 0);
1884 }
1885 if(frame->right() > m_pageLayout.ptWidth) {
1886 kdWarning() << fs->name() << " frame " << f << " rightborder outside page ("
1887 << frame->right() << ">" << m_pageLayout.ptWidth << "), shrinking" << endl;
1888 frame->setRight(m_pageLayout.ptWidth);
1889 }
1890 if(fs->isProtectSize())
1891 continue; // don't make frames bigger of a protected frameset.
1892 if(frame->height() < s_minFrameHeight) {
1893 kdWarning() << fs->name() << " frame " << f << " height is so small no text will fit, adjusting (was: "
1894 << frame->height() << " is: " << s_minFrameHeight << ")" << endl;
1895 frame->setHeight(s_minFrameHeight);
1896 }
1897 if(frame->width() < s_minFrameWidth) {
1898 kdWarning() << fs->name() << " frame " << f << " width is so small no text will fit, adjusting (was: "
1899 << frame->width() << " is: " << s_minFrameWidth << ")" << endl;
1900 frame->setWidth(s_minFrameWidth);
1901 }
1902 }
1903 if(fs->frameCount() == 0) {
1904 KWPage *page = pageManager()->page(startPage());
1905 KWFrame *frame = new KWFrame(fs, page->leftMargin(), page->topMargin(),
1906 page->width() - page->leftMargin() - page->rightMargin(),
1907 page->height() - page->topMargin() - page->bottomMargin());
1908 //kdDebug(32001) << "KWDocument::loadXML main-KWFrame created " << *frame << endl;
1909 fs->addFrame( frame );
1910 }
1911 } else if(fs->frameCount() == 0) {
1912 kdWarning () << "frameset " << i << " " << fs->name() << " has no frames" << endl;
1913 removeFrameSet(fs);
1914 if ( fs->type() == FT_PART )
1915 delete static_cast<KWPartFrameSet *>(fs)->getChild();
1916 delete fs;
1917 continue;
1918 }
1919 if(fs->frameCount() > 0) {
1920 KWFrame *frame = fs->frame(0);
1921 if(frame->isCopy()) {
1922 kdWarning() << "First frame in a frameset[" << fs->name() << "] was set to be a copy; resetting\n";
1923 frame->setCopy(false);
1924 }
1925 }
1926 }
1927
1928 // Renumber footnotes
1929 KWTextFrameSet *frameset = dynamic_cast<KWTextFrameSet *>( m_lstFrameSet.getFirst() );
1930 if ( frameset )
1931 frameset->renumberFootNotes( false /*no repaint*/ );
1932
1933 emit sigProgress(-1);
1934
1935 //kdDebug(32001) << "KWDocument::loadXML done" << endl;
1936
1937 // Connect to notifications from main text-frameset
1938 if ( frameset ) {
1939 connect( frameset->textObject(), TQ_SIGNAL( chapterParagraphFormatted( KoTextParag * ) ),
1940 TQ_SLOT( slotChapterParagraphFormatted( KoTextParag * ) ) );
1941 connect( frameset, TQ_SIGNAL( mainTextHeightChanged() ),
1942 TQ_SIGNAL( mainTextHeightChanged() ) );
1943 }
1944
1945 // Note that more stuff will happen in completeLoading
1946}
1947
1948void KWDocument::startBackgroundSpellCheck()
1949{
1950 if ( backgroundSpellCheckEnabled() && isReadWrite() )
1951 {
1952 m_bgSpellCheck->start();
1953 }
1954}
1955
1956void KWDocument::loadEmbeddedObjects( TQDomElement& word )
1957{
1958 TQDomNodeList listEmbedded = word.elementsByTagName ( "EMBEDDED" );
1959 for (unsigned int item = 0; item < listEmbedded.count(); item++)
1960 {
1961 TQDomElement embedded = listEmbedded.item( item ).toElement();
1962 loadEmbedded( embedded );
1963 }
1964}
1965
1966void KWDocument::loadEmbedded( const TQDomElement &embedded )
1967{
1968 TQDomElement object = embedded.namedItem( "OBJECT" ).toElement();
1969 if ( !object.isNull() )
1970 {
1971 KWDocumentChild *ch = new KWDocumentChild( this );
1972 ch->load( object, true );
1973 insertChild( ch );
1974 TQDomElement settings = embedded.namedItem( "SETTINGS" ).toElement();
1975 TQString name;
1976 if ( !settings.isNull() )
1977 name = settings.attribute( "name" );
1978 KWPartFrameSet *fs = new KWPartFrameSet( this, ch, name );
1979 m_lstFrameSet.append( fs );
1980 if ( !settings.isNull() )
1981 {
1982 kdDebug(32001) << "KWDocument::loadXML loading embedded object" << endl;
1983 fs->load( settings );
1984 }
1985 else
1986 kdError(32001) << "No <SETTINGS> tag in EMBEDDED" << endl;
1987
1988 } else
1989 kdError(32001) << "No <OBJECT> tag in EMBEDDED" << endl;
1990}
1991
1992
1993void KWDocument::loadStyleTemplates( const TQDomElement &stylesElem )
1994{
1995 TQValueList<TQString> followingStyles;
1996 TQDomNodeList listStyles = stylesElem.elementsByTagName( "STYLE" );
1997 if( listStyles.count() > 0) { // we are going to import at least one style.
1998 KoParagStyle *s = m_styleColl->findStyle("Standard");
1999 //kdDebug(32001) << "KWDocument::loadStyleTemplates looking for Standard, to delete it. Found " << s << endl;
2000 if(s) // delete the standard style.
2001 m_styleColl->removeStyle(s);
2002 }
2003 for (unsigned int item = 0; item < listStyles.count(); item++) {
2004 TQDomElement styleElem = listStyles.item( item ).toElement();
2005
2006 KoParagStyle *sty = new KoParagStyle( TQString() );
2007 // Load the style from the <STYLE> element
2008 sty->loadStyle( styleElem, m_syntaxVersion );
2009
2010 //kdDebug(32001) << "KoParagStyle created name=" << sty->name() << endl;
2011
2012 if ( m_syntaxVersion < 3 )
2013 {
2014 // Convert old style (up to 1.2.x included)
2015 // "include in TOC if chapter numbering" to the new attribute
2016 if ( sty->paragLayout().counter && sty->paragLayout().counter->numbering() == KoParagCounter::NUM_CHAPTER )
2017 sty->setOutline( true );
2018 }
2019
2020 // the real value of followingStyle is set below after loading all styles
2021 sty->setFollowingStyle( sty );
2022
2023 TQDomElement formatElem = styleElem.namedItem( "FORMAT" ).toElement();
2024 if ( !formatElem.isNull() )
2025 sty->format() = KWTextParag::loadFormat( formatElem, 0L, defaultFont(), globalLanguage(), globalHyphenation() );
2026 else
2027 kdWarning(32001) << "No FORMAT tag in <STYLE>" << endl; // This leads to problems in applyStyle().
2028
2029 // Style created, now let's try to add it
2030 sty = m_styleColl->addStyle( sty );
2031
2032 if(m_styleColl->styleList().count() > followingStyles.count() )
2033 {
2034 TQString following = styleElem.namedItem("FOLLOWING").toElement().attribute("name");
2035 followingStyles.append( following );
2036 }
2037 else
2038 kdWarning () << "Found duplicate style declaration, overwriting former " << sty->name() << endl;
2039 }
2040
2041 Q_ASSERT( followingStyles.count() == m_styleColl->styleList().count() );
2042
2043 unsigned int i=0;
2044 for( TQValueList<TQString>::Iterator it = followingStyles.begin(); it != followingStyles.end(); ++it ) {
2045 KoParagStyle * style = m_styleColl->findStyle(*it);
2046 m_styleColl->styleAt(i++)->setFollowingStyle( style );
2047 }
2048
2049}
2050
2051void KWDocument::loadFrameStyleTemplates( const TQDomElement &stylesElem )
2052{
2053 TQDomNodeList listStyles = stylesElem.elementsByTagName( "FRAMESTYLE" );
2054 if( listStyles.count() > 0) { // we are going to import at least one style.
2055 KWFrameStyle *s = m_frameStyleColl->findStyle("Plain");
2056 if(s) // delete the standard style.
2057 m_frameStyleColl->removeStyle(s);
2058 }
2059 for (unsigned int item = 0; item < listStyles.count(); item++) {
2060 TQDomElement styleElem = listStyles.item( item ).toElement();
2061
2062 KWFrameStyle *sty = new KWFrameStyle( styleElem );
2063 m_frameStyleColl->addStyle( sty );
2064 }
2065}
2066
2067void KWDocument::loadDefaultFrameStyleTemplates()
2068{
2069 const TQString fsfileName( locate("data", "kword/framestyles.xml") );
2070
2071 kdDebug(30003) << "Data directory: " << TDEGlobal::dirs()->resourceDirs( "data" ) << endl;
2072 kdDebug(30003) << "Directory searched: " << TDEGlobal::dirs()->resourceDirs( "data" ) << endl;
2073 kdDebug(30003) << "File framestyles.xml searched at: " << fsfileName << endl;
2074
2075 m_frameStyleColl->setDefault( true );
2076
2077 if ( ! TQFile::exists( fsfileName ) )
2078 {
2079 kdWarning(30003) << "Cannot find any framestyles.xml" << endl;
2080 if (!m_frameStyleColl->findStyle("Plain")) {
2081 KWFrameStyle * standardFrameStyle = new KWFrameStyle( "Plain" );
2082 standardFrameStyle->setBackgroundColor(TQColor("white"));
2083 standardFrameStyle->setTopBorder(KoBorder(TQColor("black"),KoBorder::SOLID,0));
2084 standardFrameStyle->setRightBorder(KoBorder(TQColor("black"),KoBorder::SOLID,0));
2085 standardFrameStyle->setLeftBorder(KoBorder(TQColor("black"),KoBorder::SOLID,0));
2086 standardFrameStyle->setBottomBorder(KoBorder(TQColor("black"),KoBorder::SOLID,0));
2087 m_frameStyleColl->addStyle( standardFrameStyle );
2088 }
2089 return;
2090 }
2091
2092 kdDebug(30003) << "File framestyles.xml found!" << endl;
2093
2094 // Open file and parse it
2095 TQFile in( fsfileName );
2096 if ( !in.open( IO_ReadOnly ) )
2097 {
2098 //i18n( "Couldn't open the file for reading (check read permissions)" );
2099 kdWarning(30003) << "Couldn't open the file for reading (check read permissions)" << endl;
2100 return;
2101 }
2102 TQString errorMsg;
2103 int errorLine;
2104 int errorColumn;
2105 TQDomDocument doc;
2106 if ( ! doc.setContent( &in , &errorMsg, &errorLine, &errorColumn ) )
2107 {
2108 kdError (30003) << "Parsing Error! Aborting! (in KWDocument::loadDefaultFrameStyleTemplates())" << endl
2109 << " Line: " << errorLine << " Column: " << errorColumn << endl
2110 << " Message: " << errorMsg << endl;
2111 }
2112 in.close();
2113
2114 // Start adding framestyles
2115 TQDomElement stylesElem = doc.documentElement();
2116
2117 TQDomNodeList listStyles = stylesElem.elementsByTagName( "FRAMESTYLE" );
2118 if( listStyles.count() > 0) { // we are going to import at least one style.
2119 KWFrameStyle *s = m_frameStyleColl->findStyle("Plain");
2120 if(s) // delete the standard style.
2121 m_frameStyleColl->removeStyle(s);
2122 }
2123 for (unsigned int item = 0; item < listStyles.count(); item++) {
2124 TQDomElement styleElem = listStyles.item( item ).toElement();
2125
2126 KWFrameStyle *sty = new KWFrameStyle( styleElem );
2127 m_frameStyleColl->addStyle( sty );
2128 }
2129}
2130
2131void KWDocument::loadTableStyleTemplates( const TQDomElement& stylesElem )
2132{
2133 TQDomNodeList listStyles = stylesElem.elementsByTagName( "TABLESTYLE" );
2134 if( listStyles.count() > 0) { // we are going to import at least one style.
2135 KWTableStyle *s = m_tableStyleColl->findStyle("Plain");
2136 if(s) // delete the standard style.
2137 m_tableStyleColl->removeStyle(s);
2138 }
2139 for (unsigned int item = 0; item < listStyles.count(); item++) {
2140 TQDomElement styleElem = listStyles.item( item ).toElement();
2141
2142 KWTableStyle *sty = new KWTableStyle( styleElem, this );
2143 m_tableStyleColl->addStyle( sty );
2144 }
2145}
2146
2147void KWDocument::loadDefaultTableStyleTemplates()
2148{
2149 KURL fsfile;
2150
2151 m_tableStyleColl->setDefault( true );
2152
2153 if ( ! TQFile::exists(locate("data", "kword/tablestyles.xml")) )
2154 {
2155 if (!m_tableStyleColl->findStyle("Plain")) {
2156 m_tableStyleColl->addStyle( new KWTableStyle( "Plain", m_styleColl->styleAt(0), m_frameStyleColl->frameStyleAt(0) ) );
2157 }
2158 return;
2159 }
2160
2161 fsfile.setPath( locate("data", "kword/tablestyles.xml") );
2162
2163 // Open file and parse it
2164 TQFile in( fsfile.path() );
2165 if ( !in.open( IO_ReadOnly ) )
2166 {
2167 //i18n( "Couldn't open the file for reading (check read permissions)" );
2168 return;
2169 }
2170 in.at(0);
2171 TQString errorMsg;
2172 int errorLine;
2173 int errorColumn;
2174 TQDomDocument doc;
2175 if ( doc.setContent( &in , &errorMsg, &errorLine, &errorColumn ) ) {
2176 }
2177 else
2178 {
2179 kdError (30003) << "Parsing Error! Aborting! (in KWDocument::loadDefaultTableStyleTemplates())" << endl
2180 << " Line: " << errorLine << " Column: " << errorColumn << endl
2181 << " Message: " << errorMsg << endl;
2182 }
2183 in.close();
2184
2185 // Start adding tablestyles
2186 TQDomElement stylesElem = doc.documentElement();
2187
2188 TQDomNodeList listStyles = stylesElem.elementsByTagName( "TABLESTYLE" );
2189 if( listStyles.count() > 0) { // we are going to import at least one style.
2190 KWTableStyle *s = m_tableStyleColl->findStyle("Plain");
2191 if(s) // delete the standard style.
2192 m_tableStyleColl->removeStyle(s);
2193 }
2194 for (unsigned int item = 0; item < listStyles.count(); item++) {
2195 TQDomElement styleElem = listStyles.item( item ).toElement();
2196
2197 KWTableStyle *sty = new KWTableStyle( styleElem, this );
2198 m_tableStyleColl->addStyle( sty );
2199 }
2200}
2201
2202void KWDocument::loadDefaultTableTemplates()
2203{
2204 KURL fsfile;
2205
2206 if ( ! TQFile::exists(locate("data", "kword/tabletemplates.xml")) )
2207 {
2208 if (!m_tableTemplateColl->findTableTemplate("Plain")) {
2209 KWTableTemplate * standardTableTemplate = new KWTableTemplate( "Plain" );
2210 KWTableStyle* defaultTableStyle = tableStyleCollection()->findStyle("Plain");
2211 standardTableTemplate->setFirstRow( defaultTableStyle );
2212 standardTableTemplate->setLastRow( defaultTableStyle );
2213 standardTableTemplate->setFirstCol( defaultTableStyle );
2214 standardTableTemplate->setLastCol( defaultTableStyle );
2215 standardTableTemplate->setBodyCell( defaultTableStyle );
2216 standardTableTemplate->setTopLeftCorner( defaultTableStyle );
2217 standardTableTemplate->setTopRightCorner( defaultTableStyle );
2218 standardTableTemplate->setBottomLeftCorner( defaultTableStyle );
2219 standardTableTemplate->setBottomRightCorner( defaultTableStyle );
2220 m_tableTemplateColl->addTableTemplate( standardTableTemplate );
2221 }
2222 return;
2223 }
2224
2225 fsfile.setPath( locate("data", "kword/tabletemplates.xml") );
2226
2227 // Open file and parse it
2228 TQFile in( fsfile.path() );
2229 if ( !in.open( IO_ReadOnly ) )
2230 {
2231 //i18n( "Couldn't open the file for reading (check read permissions)" );
2232 return;
2233 }
2234 in.at(0);
2235 TQString errorMsg;
2236 int errorLine;
2237 int errorColumn;
2238 TQDomDocument doc;
2239 if ( doc.setContent( &in , &errorMsg, &errorLine, &errorColumn ) ) {
2240 }
2241 else
2242 {
2243 kdError (30003) << "Parsing Error! Aborting! (in KWDocument::readTableTemplates())" << endl
2244 << " Line: " << errorLine << " Column: " << errorColumn << endl
2245 << " Message: " << errorMsg << endl;
2246 }
2247 in.close();
2248
2249 // Start adding framestyles
2250 TQDomElement templatesElem = doc.documentElement();
2251
2252 TQDomNodeList listTemplates = templatesElem.elementsByTagName( "TABLETEMPLATE" );
2253 if( listTemplates.count() > 0) {
2254 KWTableTemplate *s = m_tableTemplateColl->findTableTemplate("Plain");
2255 if(s)
2256 m_tableTemplateColl->removeTableTemplate(s);
2257 }
2258 for (unsigned int item = 0; item < listTemplates.count(); item++) {
2259 TQDomElement templateElem = listTemplates.item( item ).toElement();
2260
2261 KWTableTemplate *temp = new KWTableTemplate( templateElem, this );
2262 m_tableTemplateColl->addTableTemplate( temp );
2263 }
2264}
2265
2266void KWDocument::progressItemLoaded()
2267{
2268 if ( !m_nrItemsToLoad ) // happens when pasting
2269 return;
2270 m_itemsLoaded++;
2271 // We progress from 20 to 85 -> 65-wide range, 20 offset.
2272 unsigned int perc = 65 * m_itemsLoaded / m_nrItemsToLoad;
2273 if ( perc != 65 * (m_itemsLoaded-1) / m_nrItemsToLoad ) // only emit if different from previous call
2274 {
2275 //kdDebug(32001) << m_itemsLoaded << " items loaded. %=" << perc + 20 << endl;
2276 emit sigProgress( perc + 20 );
2277 }
2278}
2279
2280void KWDocument::loadFrameSets( const TQDomElement &framesetsElem )
2281{
2282 // <FRAMESET>
2283 // First prepare progress info
2284 m_nrItemsToLoad = 0; // total count of items (mostly paragraph and frames)
2285 TQDomElement framesetElem = framesetsElem.firstChild().toElement();
2286 // Workaround the slowness of TQDom's elementsByTagName
2287 TQValueList<TQDomElement> framesets;
2288 for ( ; !framesetElem.isNull() ; framesetElem = framesetElem.nextSibling().toElement() )
2289 {
2290 if ( framesetElem.tagName() == "FRAMESET" )
2291 {
2292 framesets.append( framesetElem );
2293 m_nrItemsToLoad += framesetElem.childNodes().count();
2294 }
2295 }
2296
2297 m_itemsLoaded = 0;
2298
2299 TQValueList<TQDomElement>::Iterator it = framesets.begin();
2300 TQValueList<TQDomElement>::Iterator end = framesets.end();
2301 for ( ; it != end ; ++it )
2302 {
2303 (void) loadFrameSet( *it );
2304 }
2305}
2306
2307KWFrameSet * KWDocument::loadFrameSet( TQDomElement framesetElem, bool loadFrames, bool loadFootnote )
2308{
2309 FrameSetType frameSetType = static_cast<FrameSetType>( KWDocument::getAttribute( framesetElem, "frameType", FT_BASE ) );
2310 TQString fsname = KWDocument::getAttribute( framesetElem, "name", "" );
2311
2312 switch ( frameSetType ) {
2313 case FT_TEXT: {
2314 TQString tableName = KWDocument::getAttribute( framesetElem, "grpMgr", "" );
2315 if ( !tableName.isEmpty() ) {
2316 // Text frameset belongs to a table -> find table by name
2317 KWTableFrameSet *table = 0L;
2318 TQPtrListIterator<KWFrameSet> fit = framesetsIterator();
2319 for ( ; fit.current() ; ++fit ) {
2320 KWFrameSet *f = fit.current();
2321 if( f->type() == FT_TABLE &&
2322 f->isVisible() &&
2323 f->name() == tableName ) {
2324 table = static_cast<KWTableFrameSet *> (f);
2325 break;
2326 }
2327 }
2328 // No such table yet -> create
2329 if ( !table ) {
2330 table = new KWTableFrameSet( this, tableName );
2331 addFrameSet(table, false);
2332 }
2333 // Load the cell
2334 return table->loadCell( framesetElem );
2335 }
2336 else
2337 {
2338 KWFrameSet::Info info = static_cast<KWFrameSet::Info>( framesetElem.attribute("frameInfo").toInt() );
2339 if ( info == KWFrameSet::FI_FOOTNOTE )
2340 {
2341 if ( !loadFootnote )
2342 return 0L;
2343 // Footnote -> create a KWFootNoteFrameSet
2344 KWFootNoteFrameSet *fs = new KWFootNoteFrameSet( this, fsname );
2345 fs->load( framesetElem, loadFrames );
2346 addFrameSet(fs, false);
2347 return fs;
2348 }
2349 else // Normal text frame
2350 {
2351 KWTextFrameSet *fs = new KWTextFrameSet( this, fsname );
2352 fs->load( framesetElem, loadFrames );
2353 addFrameSet(fs, false);
2354
2355 // Old file format had autoCreateNewFrame as a frameset attribute
2356 if ( framesetElem.hasAttribute( "autoCreateNewFrame" ) )
2357 {
2358 KWFrame::FrameBehavior behav = static_cast<KWFrame::FrameBehavior>( framesetElem.attribute( "autoCreateNewFrame" ).toInt() );
2359 TQPtrListIterator<KWFrame> frameIt( fs->frameIterator() );
2360 for ( ; frameIt.current() ; ++frameIt ) // Apply it to all frames
2361 frameIt.current()->setFrameBehavior( behav );
2362 }
2363 return fs;
2364 }
2365 }
2366 } break;
2367 case FT_CLIPART:
2368 {
2369 kdError(32001) << "FT_CLIPART used! (in KWDocument::loadFrameSet)" << endl;
2370 // Do not break!
2371 }
2372 case FT_PICTURE:
2373 {
2374 KWPictureFrameSet *fs = new KWPictureFrameSet( this, fsname );
2375 fs->load( framesetElem, loadFrames );
2376 addFrameSet(fs, false);
2377 return fs;
2378 } break;
2379 case FT_FORMULA: {
2380 KWFormulaFrameSet *fs = new KWFormulaFrameSet( this, fsname );
2381 fs->load( framesetElem, loadFrames );
2382 addFrameSet(fs, false);
2383 return fs;
2384 } break;
2385 // Note that FT_PART cannot happen when loading from a file (part frames are saved into the SETTINGS tag)
2386 // and FT_TABLE can't happen either.
2387 case FT_PART:
2388 kdWarning(32001) << "loadFrameSet: FT_PART: impossible case" << endl;
2389 break;
2390 case FT_TABLE:
2391 kdWarning(32001) << "loadFrameSet: FT_TABLE: impossible case" << endl;
2392 break;
2393 case FT_BASE:
2394 kdWarning(32001) << "loadFrameSet: FT_BASE !?!?" << endl;
2395 break;
2396 }
2397 return 0L;
2398}
2399
2400void KWDocument::loadImagesFromStore( KoStore *store )
2401{
2402 if ( store && !m_pictureMap.isEmpty() ) {
2403 m_pictureCollection->readFromStore( store, m_pictureMap );
2404 m_pictureMap.clear(); // Release memory
2405 }
2406}
2407
2408bool KWDocument::completeLoading( KoStore *store )
2409{
2410 kdDebug() << k_funcinfo << endl;
2411 // Old-XML stuff. No-op when loading OASIS.
2412 loadImagesFromStore( store );
2413 processPictureRequests();
2414 processAnchorRequests();
2415 processFootNoteRequests();
2416
2417 // Save memory
2418 m_urlIntern = TQString();
2419
2420 // The fields and dates just got loaded -> update vars
2421 recalcVariables( VT_FIELD );
2422 recalcVariables( VT_DATE );
2423 recalcVariables( VT_STATISTIC ); // e.g. number of words etc.
2424
2425 // Finalize all the existing [non-inline] framesets
2426 TQPtrListIterator<KWFrameSet> fit = framesetsIterator();
2427 for ( ; fit.current() ; ++fit )
2428 fit.current()->finalize();
2429
2430 // This computes the number of pages (from the frames)
2431 // for the first time (and adds footers/headers/footnotes etc.)
2432 // ## Note: with OASIS the frame loading appends pages as necessary,
2433 // so maybe we don't need to calculate the pages from the frames anymore.
2434 recalcFrames();
2435
2436 // Fix z orders on older documents
2437 fixZOrders();
2438
2439 emit newContentsSize();
2440 repaintAllViews( true ); // in case any view exists already
2441 reactivateBgSpellChecking();
2442 connect( documentInfo(), TQ_SIGNAL( sigDocumentInfoModifed()),this,TQ_SLOT(slotDocumentInfoModifed() ) );
2443
2444 //desactivate bgspellchecking
2445 //attributes isReadWrite is not placed at the beginning !
2446 if ( !isReadWrite())
2447 enableBackgroundSpellCheck( false );
2448
2449 // Load bookmarks
2450 initBookmarkList();
2451
2452 deleteLoadingInfo();
2453
2454 setModified( false );
2455
2456 return true;
2457}
2458
2459KWLoadingInfo* KWDocument::createLoadingInfo()
2460{
2461 Q_ASSERT( !m_loadingInfo );
2462 m_loadingInfo = new KWLoadingInfo();
2463 m_loadingInfo->columns.ptColumnSpacing = m_defaultColumnSpacing;
2464 return m_loadingInfo;
2465}
2466
2467void KWDocument::deleteLoadingInfo()
2468{
2469 Q_ASSERT( m_loadingInfo );
2470 delete m_loadingInfo;
2471 m_loadingInfo = 0;
2472}
2473
2474void KWDocument::processPictureRequests()
2475{
2476 TQPtrListIterator<KWTextImage> it2 ( m_textImageRequests );
2477 for ( ; it2.current() ; ++it2 )
2478 {
2479 it2.current()->setImage( *m_pictureCollection );
2480 }
2481 m_textImageRequests.clear();
2482
2483 //kdDebug(32001) << m_pictureRequests.count() << " picture requests." << endl;
2484 TQPtrListIterator<KWPictureFrameSet> it3( m_pictureRequests );
2485 for ( ; it3.current() ; ++it3 )
2486 it3.current()->setPicture( m_pictureCollection->findPicture( it3.current()->key() ) );
2487 m_pictureRequests.clear();
2488}
2489
2490void KWDocument::processAnchorRequests()
2491{
2492 TQMapIterator<TQString, KWAnchorPosition> itanch = m_anchorRequests.begin();
2493 for ( ; itanch != m_anchorRequests.end(); ++itanch )
2494 {
2495 TQString fsname = itanch.key();
2496 if ( m_pasteFramesetsMap && m_pasteFramesetsMap->contains( fsname ) )
2497 fsname = (*m_pasteFramesetsMap)[ fsname ];
2498 kdDebug(32001) << "KWDocument::processAnchorRequests anchoring frameset " << fsname << endl;
2499 KWFrameSet * fs = frameSetByName( fsname );
2500 Q_ASSERT( fs );
2501 if ( fs )
2502 fs->setAnchored( itanch.data().textfs, itanch.data().paragId, itanch.data().index, true, false /*don't repaint yet*/ );
2503 }
2504 m_anchorRequests.clear();
2505}
2506
2507bool KWDocument::processFootNoteRequests()
2508{
2509 bool ret = false;
2510 TQMapIterator<TQString, KWFootNoteVariable *> itvar = m_footnoteVarRequests.begin();
2511 for ( ; itvar != m_footnoteVarRequests.end(); ++itvar )
2512 {
2513 TQString fsname = itvar.key();
2514 if ( m_pasteFramesetsMap && m_pasteFramesetsMap->contains( fsname ) )
2515 fsname = (*m_pasteFramesetsMap)[ fsname ];
2516 //kdDebug(32001) << "KWDocument::processFootNoteRequests binding footnote var " << itvar.data() << " and frameset " << fsname << endl;
2517 KWFrameSet * fs = frameSetByName( fsname );
2518 Q_ASSERT( fs );
2519 if ( !fs ) // #104431
2520 continue;
2521 Q_ASSERT( fs->type() == FT_TEXT );
2522 Q_ASSERT( fs->frameSetInfo() == KWFrameSet::FI_FOOTNOTE );
2523 KWFootNoteFrameSet* fnfs = dynamic_cast<KWFootNoteFrameSet *>(fs);
2524 if ( fnfs )
2525 {
2526 fnfs->setFootNoteVariable( itvar.data() );
2527 itvar.data()->setFrameSet( fnfs );
2528 ret = true;
2529 }
2530 }
2531 m_footnoteVarRequests.clear();
2532 // Renumber footnotes
2533 if ( ret ) {
2534 KWFrameSet *frameset = m_lstFrameSet.getFirst();
2535 if ( frameset && frameset->type() == FT_TEXT )
2536 static_cast<KWTextFrameSet *>(frameset)->renumberFootNotes( false /*no repaint*/ );
2537 }
2538 return ret;
2539}
2540
2541TQString KWDocument::uniqueFramesetName( const TQString& oldName )
2542{
2543 TQString newName = oldName;
2544 if (frameSetByName( oldName ))//rename it if name frameset exists
2545 {
2546 // make up a new name for the frameset, use Copy[digits]-[oldname] as template.
2547 // Fully translatable naturally :)
2548 TQString searchString( "^(" + i18n("Copy%1-%2").arg("\\d*").arg("){0,1}") );
2549 searchString = searchString.replace(TQRegExp("\\-"), "\\-"); // escape the '-'
2550 TQRegExp searcher(searchString);
2551 int count=0;
2552 do {
2553 newName=oldName;
2554 newName.replace(searcher,i18n("Copy%1-%2").arg(count > 0? TQString("%1").arg(count):"").arg(""));
2555 count++;
2556 } while ( frameSetByName( newName ) );
2557 }
2558 return newName;
2559}
2560
2561void KWDocument::pasteFrames( TQDomElement topElem, KMacroCommand * macroCmd, bool copyFootNote, bool loadFootNote, bool selectFrames )
2562{
2563 m_pasteFramesetsMap = new TQMap<TQString, TQString>();
2564 //TQPtrList<KWFrameSet> frameSetsToFinalize;
2565 int ref=0;
2566 int nb = 0;
2567 TQDomElement elem = topElem.firstChild().toElement();
2568 for ( ; !elem.isNull() ; elem = elem.nextSibling().toElement() )
2569 {
2570 //kdDebug() << "pasteFrames: elem=" << elem.tagName() << endl;
2571 TQDomElement frameElem;
2572 KWFrameSet * fs = 0L;
2573 if ( elem.tagName() == "FRAME" )
2574 {
2575 TQString frameSetName = frameElem.attribute( "parentFrameset" );
2576 fs = frameSetByName( frameSetName );
2577 if ( !fs )
2578 {
2579 kdWarning(32001) << "pasteFrames: Frameset '" << frameSetName << "' not found" << endl;
2580 continue;
2581 }
2582 frameElem = elem;
2583 }
2584 else if ( elem.tagName() == "FRAMESET" )
2585 {
2586 // Prepare a new name for the frameset
2587 TQString oldName = elem.attribute( "name" );
2588 TQString newName = uniqueFramesetName( oldName ); // make up a new name for the frameset
2589
2590 m_pasteFramesetsMap->insert( oldName, newName ); // remember the name transformation
2591 if(oldName != newName)
2592 kdDebug(32001) << "KWDocument::pasteFrames new frameset: " << oldName << "->" << newName << endl;
2593 FrameSetType frameSetType = static_cast<FrameSetType>( KWDocument::getAttribute( elem, "frameType", FT_BASE ) );
2594 switch ( frameSetType ) {
2595 case FT_TABLE: {
2596 KWTableFrameSet *table = new KWTableFrameSet( this, newName );
2597 table->fromXML( elem, true, false /*don't apply names*/ );
2598 table->moveBy( 20.0, 20.0 );
2599 m_lstFrameSet.append( table );
2600 table->setZOrder();
2601 if ( macroCmd )
2602 macroCmd->addCommand( new KWCreateTableCommand( TQString(), table ) );
2603 fs = table;
2604 break;
2605 }
2606 case FT_PART:
2607 {
2608 ref |= Embedded;
2609#if 0
2610 KWPartFrameSet *part = new KWPartFrameSet( this, newName );
2611 part->fromXML( elem, true, false /*don't apply names*/ );
2612 part->moveBy( 20.0, 20.0 );
2613 m_lstFrameSet.append( part );
2614 part->setZOrder();
2615 fs = part;
2616#endif
2617 break;
2618 }
2619 default:
2620 fs = loadFrameSet( elem, false, loadFootNote );
2621 if ( fs )
2622 {
2623 kdDebug() << "KWDocument::pasteFrames created frameset: '" << newName << "'\n";
2624 fs->setName( newName );
2625 frameElem = elem.namedItem( "FRAME" ).toElement();
2626 }
2627 }
2628 //when we paste a header/footer we transforme it in a body frame
2629 if(fs && (fs->isHeaderOrFooter() || ( !copyFootNote && fs->isFootEndNote())))
2630 fs->setFrameSetInfo(KWFrameSet::FI_BODY);
2631 }
2632 // Test commented out since the toplevel element can contain "PARAGRAPH" now
2633 //else
2634 //kdWarning(32001) << "Unsupported toplevel-element in KWCanvas::pasteFrames : '" << elem.tagName() << "'" << endl;
2635
2636 if ( fs )
2637 {
2638 //if ( frameSetsToFinalize.findRef( fs ) == -1 )
2639 // frameSetsToFinalize.append( fs );
2640
2641 // Load the frame
2642 if ( !frameElem.isNull() )
2643 {
2644 double offs = 20.0;
2645 KoRect rect;
2646 rect.setLeft( KWDocument::getAttribute( frameElem, "left", 0.0 ) + offs );
2647 rect.setTop( KWDocument::getAttribute( frameElem, "top", 0.0 ) + offs );
2648 rect.setRight( KWDocument::getAttribute( frameElem, "right", 0.0 ) + offs );
2649 rect.setBottom( KWDocument::getAttribute( frameElem, "bottom", 0.0 ) + offs );
2650 KWFrame * frame = new KWFrame( fs, rect.x(), rect.y(), rect.width(), rect.height() );
2651 frame->load( frameElem, fs, KWDocument::CURRENT_SYNTAX_VERSION );
2652 frame->setZOrder( maxZOrder( frame->pageNumber(this) ) + 1 +nb ); // make sure it's on top
2653 nb++;
2654 fs->addFrame( frame, false );
2655 if ( selectFrames ) {
2656 for( TQValueList<KWView *>::Iterator it = m_lstViews.begin();
2657 it != m_lstViews.end(); ++it ) {
2658 KWFrameView *fv = (*it)->frameViewManager()->view(frame);
2659 if(fv)
2660 fv->setSelected(true);
2661 }
2662 }
2663 if ( macroCmd )
2664 {
2665 KWCreateFrameCommand *cmd = new KWCreateFrameCommand( TQString(), frame );
2666 macroCmd->addCommand(cmd);
2667 }
2668 }
2669 int type=0;
2670 // Please move this to some common method somewhere (e.g. in KWDocument) (David)
2671 switch(fs->type())
2672 {
2673 case FT_TEXT:
2674 type=(int)TextFrames;
2675 break;
2676 case FT_CLIPART:
2677 {
2678 kdError(32001) << "FT_CLIPART used! (in KWDocument::loadFrameSet)" << endl;
2679 // Do not break!
2680 }
2681 case FT_PICTURE:
2682 type=(int)Pictures;
2683 break;
2684 case FT_PART:
2685 type=(int)Embedded;
2686 break;
2687 case FT_FORMULA:
2688 type=(int)FormulaFrames;
2689 break;
2690 case FT_TABLE:
2691 type=(int)Tables;
2692 break;
2693 default:
2694 type=(int)TextFrames;
2695 }
2696 ref|=type;
2697 }
2698 }
2699 refreshDocStructure(ref);
2700}
2701
2702void KWDocument::completePasting()
2703{
2704 processPictureRequests();
2705 processAnchorRequests();
2706 if ( processFootNoteRequests() )
2707 {
2708 // We pasted footnotes. Relayout frames.
2709 recalcFrames();
2710 }
2711
2712 // Finalize afterwards - especially in case of inline frames, made them inline in processAnchorRequests
2713 //for ( TQPtrListIterator<KWFrameSet> fit( frameSetsToFinalize ); fit.current(); ++fit )
2714
2715 // Do it on all of them (we'd need to store frameSetsToFinalize as member var if this is really slow)
2716 TQPtrListIterator<KWFrameSet> fit = framesetsIterator();
2717 for ( ; fit.current() ; ++fit )
2718 fit.current()->finalize();
2719 repaintAllViews();
2720 delete m_pasteFramesetsMap;
2721 m_pasteFramesetsMap = 0L;
2722}
2723
2724void KWDocument::completeOasisPasting()
2725{
2726 TQPtrListIterator<KWFrameSet> fit = framesetsIterator();
2727 for ( ; fit.current() ; ++fit )
2728 fit.current()->finalize();
2729 repaintAllViews();
2730}
2731
2732void KWDocument::insertEmbedded( KoStore *store, TQDomElement topElem, KMacroCommand * macroCmd, double offset )
2733{
2734 if ( !m_pasteFramesetsMap ) // may have been created by pasteFrames
2735 m_pasteFramesetsMap = new TQMap<TQString, TQString>();
2736
2737 TQDomElement elem = topElem.firstChild().toElement();
2738 for ( ; !elem.isNull() ; elem = elem.nextSibling().toElement() )
2739 {
2740 if ( elem.tagName() == "EMBEDDED" )
2741 {
2742 kdDebug()<<"KWDocument::insertEmbedded() Embedded object"<<endl;
2743 TQDomElement object = elem.namedItem( "OBJECT" ).toElement();
2744 TQDomElement settings = elem.namedItem( "SETTINGS" ).toElement();
2745 if ( object.isNull() || settings.isNull() )
2746 {
2747 kdError() << "No <OBJECT> or <SETTINGS> tag" << endl;
2748 }
2749 else
2750 {
2751 KWDocumentChild *ch = new KWDocumentChild( this );
2752 kdDebug()<<"KWDocument::insertEmbedded() loading document"<<endl;
2753 if ( ch->load( object, true ) )
2754 {
2755 ch->loadDocument( store );
2756 insertChild( ch );
2757 TQString oldName = settings.attribute( "name" );
2758 TQString newName = uniqueFramesetName( oldName );
2759 m_pasteFramesetsMap->insert( oldName, newName ); // remember the name transformation
2760 KWPartFrameSet *part = new KWPartFrameSet( this, ch, newName );
2761 m_lstFrameSet.append( part );
2762 kdDebug() << "KWDocument::insertEmbedded loading embedded object" << endl;
2763 part->load( settings );
2764 if ( offset != 0 ) {
2765 TQRect r = ch->geometry();
2766 r.moveBy( (int)offset, (int)offset );
2767 ch->setGeometry( r );
2768 }
2769 part->setZOrder();
2770 if ( macroCmd )
2771 {
2772 TQPtrListIterator<KWFrame> frameIt( part->frameIterator() );
2773 for ( ; frameIt.current(); ++frameIt )
2774 {
2775 macroCmd->addCommand( new KWCreateFrameCommand( TQString(), frameIt.current() ) );
2776 }
2777 }
2778 }
2779 }
2780 }
2781 }
2782 refreshDocStructure( (int)Embedded );
2783}
2784
2785bool KWDocument::saveOasis( KoStore* store, KoXmlWriter* manifestWriter )
2786{
2787 TQValueList<KWFrameView*> noFrames;
2788 return saveOasisHelper( store, manifestWriter, SaveAll, noFrames);
2789}
2790
2791// can't be const due to recalcVariables()
2792bool KWDocument::saveOasisHelper( KoStore* store, KoXmlWriter* manifestWriter, SaveFlag saveFlag, const TQValueList<KWFrameView*> &selectedFrames, TQString* plainText, KoPicture* picture, KWTextFrameSet* fs) {
2793 m_pictureCollection->assignUniqueIds();
2794 fixZOrders();
2795
2796 manifestWriter->addManifestEntry( "content.xml", "text/xml" );
2797 KoOasisStore oasisStore( store );
2798
2799 KoXmlWriter* contentWriter = oasisStore.contentWriter();
2800 if ( !contentWriter )
2801 return false;
2802
2803 TQValueList<KoPictureKey> pictureList;
2804 if ( saveFlag == SaveAll )
2805 pictureList = savePictureList();
2806
2807 m_varColl->variableSetting()->setModificationDate(TQDateTime::currentDateTime());
2808 recalcVariables( VT_DATE );
2809 recalcVariables( VT_TIME ); // for "current time"
2810 recalcVariables( VT_STATISTIC );
2811 m_syntaxVersion = CURRENT_SYNTAX_VERSION; // ### clean this up once we remove the old format
2812
2813 KoGenStyles mainStyles;
2814 KoSavingContext savingContext( mainStyles, m_varColl->variableSetting(), m_pageColumns.columns > 1, KoSavingContext::Store );
2815
2816 // Save user styles as KoGenStyle objects
2817 m_styleColl->saveOasis( mainStyles, KoGenStyle::STYLE_USER, savingContext );
2818
2819 TQByteArray headerFooterContent;
2820 if ( saveFlag == SaveAll )
2821 {
2822 // Save visual info for the first view, such as the active frameset and cursor position
2823 // It looks like a hack, but reopening a document creates only one view anyway (David)
2824 KWView * view = static_cast<KWView*>(views().getFirst());
2825 if ( view ) // no view if embedded document
2826 {
2827 KWFrameSetEdit* edit = view->getGUI()->canvasWidget()->currentFrameSetEdit();
2828 if ( edit )
2829 {
2830 KWTextFrameSetEdit* textedit = dynamic_cast<KWTextFrameSetEdit *>(edit);
2831 if ( textedit && textedit->cursor() ) {
2832 KoTextCursor* cursor = textedit->cursor();
2833 savingContext.setCursorPosition( cursor->parag(),
2834 cursor->index() );
2835 }
2836 }
2837 }
2838
2839 // Header and footers save their content into master-styles/master-page, and their
2840 // styles into the page-layout automatic-style.
2841 // However the paragraph styles used by header/footers need to be known before
2842 // hand, to promote them to styles.xml. So we collect them first, which means
2843 // storing the content into a buffer.
2844 TQBuffer buffer( headerFooterContent );
2845 buffer.open( IO_WriteOnly );
2846 KoXmlWriter headerFooterTmpWriter( &buffer ); // TODO pass indentation level
2847
2848 // The order we write out header, header-left, etc. is important. So, we go here
2849 // the dirty way to collect them first and then flush them ordered out.
2850 TQMap<KWFrameSet::Info,const KWFrameSet*> tempmap;
2851
2852 // ## This loop is duplicated in saveOasisDocumentStyles
2853 for (TQPtrListIterator<KWFrameSet> fit = framesetsIterator(); fit.current() ; ++fit ) {
2854 const KWFrameSet* fs = fit.current();
2855 if ( fs->isVisible() && // HACK to avoid saving [hidden] headers/footers framesets for now
2856 !fs->isFloating() &&
2857 !fs->isDeleted() &&
2858 fs->type() == FT_TEXT &&
2859 fs->isHeaderOrFooter() )
2860 {
2861 tempmap.insert(fs->frameSetInfo(), fs);
2862 }
2863 }
2864
2865 TQValueList<KWFrameSet::Info> order;
2866 order << KWFrameSet::FI_FIRST_HEADER << KWFrameSet::FI_ODD_HEADER << KWFrameSet::FI_EVEN_HEADER
2867 << KWFrameSet::FI_FIRST_FOOTER << KWFrameSet::FI_ODD_FOOTER << KWFrameSet::FI_EVEN_FOOTER;
2868 for (uint i=0; i<order.count(); ++i) {
2869 KWFrameSet::Info info = order[i];
2870 if (tempmap.contains(info)) {
2871 const KWFrameSet* fs = tempmap[info];
2872
2873 // Save content
2874 headerFooterTmpWriter.startElement( fs->headerFooterTag() ); // e.g. style:header
2875 static_cast<const KWTextFrameSet *>(fs)->saveOasisContent( headerFooterTmpWriter, savingContext );
2876 headerFooterTmpWriter.endElement();
2877 }
2878 }
2879
2880 // Add trailing '0'
2881 headerFooterContent.resize( headerFooterContent.size() + 1 );
2882 headerFooterContent[headerFooterContent.size()-1] = '\0';
2883
2884 // Now mark all autostyles as "for styles.xml" since headers/footers need them
2885 TQValueList<KoGenStyles::NamedStyle> autoStyles = mainStyles.styles( KoGenStyle::STYLE_AUTO );
2886 for ( TQValueList<KoGenStyles::NamedStyle>::const_iterator it = autoStyles.begin();
2887 it != autoStyles.end(); ++it ) {
2888 mainStyles.markStyleForStylesXml( (*it).name );
2889 }
2890 }
2891
2892 KoXmlWriter* bodyWriter = oasisStore.bodyWriter();
2893 bodyWriter->startElement( "office:body" );
2894 bodyWriter->startElement( "office:text" );
2895
2896 if ( saveFlag == SaveAll )
2897 {
2898 // save the body into bodyWriter
2899 saveOasisBody( *bodyWriter, savingContext );
2900 }
2901 else // SaveSelected
2902 {
2903 // In theory we should pass a view to this method, in order to
2904 // copy what is currently selected in that view only. But selection
2905 // is currently part of the KoTextParag data, so it's shared between views.
2906 if ( fs ) {
2907 *plainText = fs->textDocument()->copySelection( *bodyWriter, savingContext, KoTextDocument::Standard );
2908 // Collect inline framesets for e.g. pictures
2909 KWCollectFramesetsVisitor visitor;
2910 fs->textDocument()->visitSelection( KoTextDocument::Standard, &visitor );
2911 const TQValueList<KWFrameSet *>& frameset = visitor.frameSets();
2912 kdDebug(32001) << frameset.count() << " inline framesets" << endl;
2913 for ( TQValueList<KWFrameSet *>::ConstIterator it = frameset.begin(); it != frameset.end(); ++it )
2914 {
2915 switch ( (*it)->type() ) {
2916 case FT_PICTURE:
2917 {
2918 const KoPictureKey key = static_cast<KWPictureFrameSet *>( *it )->key();
2919 if ( !pictureList.contains( key ) )
2920 pictureList.append( key );
2921 }
2922 break;
2923 case FT_PART:
2924 // TODO
2925 default:
2926 break;
2927 }
2928 }
2929 }
2930
2931 // write selected (non-inline) frames
2932 TQString newText;
2933 saveSelectedFrames( *bodyWriter, savingContext, pictureList,
2934 selectedFrames, &newText ); // output vars
2935 *plainText += newText;
2936 // Single image -> return it
2937 if ( picture && pictureList.count() == 1 )
2938 {
2939 *picture = m_pictureCollection->findPicture( pictureList.first() );
2940 }
2941 }
2942
2943 bodyWriter->endElement(); // office:text
2944 bodyWriter->endElement(); // office:body
2945
2946 savingContext.writeFontFaces( *contentWriter );
2947 contentWriter->startElement( "office:automatic-styles" );
2948 KWOasisSaver::writeAutomaticStyles( *contentWriter, mainStyles, false );
2949 contentWriter->endElement(); // office:automatic-styles
2950
2951 oasisStore.closeContentWriter();
2952
2953 // Done with content.xml
2954
2955 if ( !store->open( "styles.xml" ) )
2956 return false;
2957 manifestWriter->addManifestEntry( "styles.xml", "text/xml" );
2958 saveOasisDocumentStyles( store, mainStyles, savingContext, saveFlag, headerFooterContent );
2959 if ( !store->close() ) // done with styles.xml
2960 return false;
2961
2962 //kdDebug(32001) << "saveOasis: " << pictureList.count() << " pictures" << endl;
2963 m_pictureCollection->saveOasisToStore( store, pictureList, manifestWriter );
2964
2965 if ( saveFlag == SaveSelected ) {
2966 // Save embedded objects - code inspired from KoDocument::saveChildrenOasis,
2967 // for the case where we're saving only some embedded objects, like with Ctrl+C.
2968
2969 // IMPORTANT: This must be done *after* we're done with writing content.xml,
2970 // not while writing it (like in saveSelectedFrames).
2971 // We can't be writing to two files at the same time.
2972
2973 TQValueList<KoDocumentChild*> embeddedObjects;
2974 TQValueListConstIterator<KWFrameView*> framesIterator = selectedFrames.begin();
2975 for(; framesIterator != selectedFrames.end(); ++framesIterator) {
2976 KWFrame *frame = (*framesIterator)->frame();
2977 KWFrameSet *fs = frame->frameSet();
2978 if ( fs->isVisible() && fs->type() == FT_PART) {
2979 embeddedObjects.append( static_cast<KWPartFrameSet *>(fs)->getChild() );
2980 }
2981 }
2982
2983 TQValueList<KoDocumentChild *>::const_iterator chl = embeddedObjects.begin();
2984 for( ; chl != embeddedObjects.end(); ++chl ) {
2985 if ( !(*chl)->saveOasis( store, manifestWriter ) )
2986 return false;
2987 }
2988 }
2989
2990 if ( saveFlag == SaveAll )
2991 {
2992
2993 if(!store->open("settings.xml"))
2994 return false;
2995
2996 KoStoreDevice contentDev( store );
2997 KoXmlWriter* settingsWriter = createOasisXmlWriter(&contentDev, "office:document-settings");
2998 saveOasisSettings( *settingsWriter );
2999 delete settingsWriter;
3000
3001 if(!store->close())
3002 return false;
3003
3004 manifestWriter->addManifestEntry("settings.xml", "text/xml");
3005 }
3006 return true;
3007}
3008
3009// can't be const due to recalcVariables()
3010TQDragObject* KWDocument::dragSelected( const TQValueList<KWFrameView*> &selectedFrames) {
3011 return dragSelectedPrivate(0, selectedFrames, 0);
3012}
3013// can't be const due to recalcVariables()
3014TQDragObject* KWDocument::dragSelected( TQWidget *parent, KWTextFrameSet* fs) {
3015 TQValueList<KWFrameView*> noFrames;
3016 return dragSelectedPrivate(parent, noFrames, fs);
3017}
3018// can't be const due to recalcVariables()
3019TQDragObject* KWDocument::dragSelectedPrivate( TQWidget *parent, const TQValueList<KWFrameView*> &selectedFrames, KWTextFrameSet* fs)
3020{
3021 // We'll create a store (ZIP format) in memory
3022 TQBuffer buffer;
3023 TQCString mimeType = KWOasisSaver::selectionMimeType();
3024 KoStore* store = KoStore::createStore( &buffer, KoStore::Write, mimeType );
3025 Q_ASSERT( store );
3026 Q_ASSERT( !store->bad() );
3027 KoOasisStore oasisStore( store );
3028
3029 KoXmlWriter* manifestWriter = oasisStore.manifestWriter( mimeType );
3030
3031 TQString plainText;
3032 KoPicture picture;
3033 if ( !saveOasisHelper( store, manifestWriter, KWDocument::SaveSelected, selectedFrames, &plainText, &picture, fs )
3034 || !oasisStore.closeManifestWriter() )
3035 {
3036 delete store;
3037 return 0;
3038 }
3039
3040 delete store;
3041
3042 KMultipleDrag* multiDrag = new KMultipleDrag( parent );
3043 if ( !plainText.isEmpty() )
3044 multiDrag->addDragObject( new TQTextDrag( plainText, 0 ) );
3045 if ( !picture.isNull() )
3046 multiDrag->addDragObject( picture.dragObject( 0 ) );
3047 KoStoreDrag* storeDrag = new KoStoreDrag( KWOasisSaver::selectionMimeType(), 0 );
3048 kdDebug() << k_funcinfo << "setting zip data: " << buffer.buffer().size() << " bytes." << endl;
3049 storeDrag->setEncodedData( buffer.buffer() );
3050 multiDrag->addDragObject( storeDrag );
3051 return multiDrag;
3052}
3053
3054void KWDocument::saveSelectedFrames( KoXmlWriter& bodyWriter, KoSavingContext& savingContext, TQValueList<KoPictureKey>& pictureList, const TQValueList<KWFrameView*> &selectedFrames, TQString* plainText ) const {
3055 TQPtrList<KoDocumentChild> embeddedObjects;
3056 TQValueListConstIterator<KWFrameView*> framesIterator = selectedFrames.begin();
3057 for(; framesIterator != selectedFrames.end(); ++framesIterator) {
3058 KWFrame *frame = (*framesIterator)->frame();
3059 KWFrameSet *fs = frame->frameSet();
3060 if ( fs->isVisible() && fs->type() == FT_PART) {
3061 embeddedObjects.append( static_cast<KWPartFrameSet *>(fs)->getChild() );
3062 }
3063 bool isTable = fs->type() == FT_TABLE;
3064
3065 // Two cases to be distinguished here
3066 // If it's the first frame of a frameset, then copy the frameset contents and the frame itself
3067 // Otherwise copy only the frame information
3068 if ( frame == fs->frame(0) || isTable ) {
3069 fs->saveOasis( bodyWriter, savingContext, false );
3070 if ( plainText )
3071 *plainText += fs->toPlainText();
3072 }
3073 else if ( !isTable ) {
3074#if 0
3075 // Save the frame information
3076 TQDomElement frameElem = parentElem.ownerDocument().createElement( "FRAME" );
3077 parentElem.appendChild( frameElem );
3078 frame->save( frameElem );
3079 if ( frame != firstFrame )
3080 {
3081 // Frame saved alone -> remember which frameset it's part of
3082 frameElem.setAttribute( "parentFrameset", fs->name() );
3083 }
3084#endif
3085 }
3086 if ( fs->type() == FT_PICTURE ) {
3087 kdDebug(32001) << "found non-inline picture framesets" << endl;
3088
3089 const KoPictureKey key = static_cast<KWPictureFrameSet *>( fs )->key();
3090 if ( !pictureList.contains( key ) )
3091 pictureList.append( key );
3092 }
3093 if ( isTable ) // Copy tables only once, even if they have many cells selected
3094 break;
3095 }
3096}
3097
3098void KWDocument::saveOasisSettings( KoXmlWriter& settingsWriter ) const
3099{
3100 settingsWriter.startElement("office:settings");
3101 settingsWriter.startElement("config:config-item-set");
3102
3103 settingsWriter.addAttribute("config:name", "view-settings");
3104
3105 KoUnit::saveOasis(&settingsWriter, unit());
3106
3107 settingsWriter.endElement(); // config:config-item-set
3108
3109 settingsWriter.startElement("config:config-item-set");
3110 settingsWriter.addAttribute("config:name", "configuration-settings");
3111 settingsWriter.addConfigItem("SpellCheckerIgnoreList", m_spellCheckIgnoreList.join( "," ) );
3112 settingsWriter.endElement(); // config:config-item-set
3113
3114 m_varColl->variableSetting()->saveOasis( settingsWriter );
3115
3116 settingsWriter.endElement(); // office:settings
3117 settingsWriter.endElement(); // Root element
3118 settingsWriter.endDocument();
3119}
3120
3121void KWDocument::saveOasisDocumentStyles( KoStore* store, KoGenStyles& mainStyles, KoSavingContext& savingContext, SaveFlag saveFlag, const TQByteArray& headerFooterContent ) const
3122{
3123 if ( saveFlag == SaveAll )
3124 {
3125 m_frameStyleColl->saveOasis( mainStyles, savingContext );
3126 m_tableStyleColl->saveOasis( mainStyles, savingContext );
3127 }
3128
3129 KoStoreDevice stylesDev( store );
3130 KoXmlWriter* stylesWriter = createOasisXmlWriter( &stylesDev, "office:document-styles" );
3131
3132 // Yeah we need to save the same font faces in both content.xml and styles.xml...
3133 savingContext.writeFontFaces( *stylesWriter );
3134
3135 stylesWriter->startElement( "office:styles" );
3136
3137 if ( saveFlag == SaveAll )
3138 {
3139 stylesWriter->startElement( "style:default-style" );
3140 stylesWriter->addAttribute( "style:family", "paragraph" );
3141 stylesWriter->startElement( "style:paragraph-properties" );
3142 stylesWriter->addAttributePt( "style:tab-stop-distance", m_tabStop );
3143 stylesWriter->endElement(); // paragraph-properties
3144 stylesWriter->endElement(); // default-style
3145 }
3146
3147 TQValueList<KoGenStyles::NamedStyle> styles = mainStyles.styles( KoGenStyle::STYLE_USER );
3148 TQValueList<KoGenStyles::NamedStyle>::const_iterator it = styles.begin();
3149 for ( ; it != styles.end() ; ++it ) {
3150 (*it).style->writeStyle( stylesWriter, mainStyles, "style:style", (*it).name, "style:paragraph-properties" );
3151 }
3152 styles = mainStyles.styles( KWDocument::STYLE_FRAME_USER );
3153 it = styles.begin();
3154 for ( ; it != styles.end() ; ++it ) {
3155 (*it).style->writeStyle( stylesWriter, mainStyles, "style:style", (*it).name , "style:graphic-properties" );
3156 }
3157 styles = mainStyles.styles( KWDocument::STYLE_TABLE_CELL_USER );
3158 it = styles.begin();
3159 for ( ; it != styles.end() ; ++it ) {
3160 (*it).style->writeStyle( stylesWriter, mainStyles, "style:style", (*it).name , "style:table-cell-properties" );
3161 }
3162 styles = mainStyles.styles( KoGenStyle::STYLE_LIST );
3163 it = styles.begin();
3164 for ( ; it != styles.end() ; ++it ) {
3165 (*it).style->writeStyle( stylesWriter, mainStyles, "text:list-style", (*it).name, 0 );
3166 }
3167 m_styleColl->saveOasisOutlineStyles( *stylesWriter );
3168 if ( saveFlag == SaveAll )
3169 static_cast<KWVariableSettings *>( m_varColl->variableSetting() )->saveNoteConfiguration( *stylesWriter );
3170 stylesWriter->endElement(); // office:styles
3171
3172 TQString pageLayoutName;
3173 if ( saveFlag == SaveAll )
3174 {
3175 stylesWriter->startElement( "office:automatic-styles" );
3176
3177 KoGenStyle pageLayout = m_pageLayout.saveOasis();
3178 pageLayout.addAttribute( "style:page-usage", "all" ); // needed?
3179 // This is for e.g. spreadsheets, not for word-processors.
3180 //pageLayout.addProperty( "style:first-page-number", m_varColl->variableSetting()->startingPage() );
3181
3182 if ( m_processingType == WP )
3183 {
3184 KWTextFrameSet *frameset = dynamic_cast<KWTextFrameSet *>( m_lstFrameSet.getFirst() );
3185 if ( frameset ) {
3186 frameset->frame(0)->saveBorderProperties( pageLayout );
3187 }
3188 }
3189
3190 TQBuffer buffer;
3191 buffer.open( IO_WriteOnly );
3192 KoXmlWriter footnoteSepTmpWriter( &buffer ); // TODO pass indentation level
3193 footnoteSepTmpWriter.startElement( "style:footnote-sep" );
3194 TQString tmp;
3195 switch( m_footNoteSeparatorLinePos )
3196 {
3197 case SLP_CENTERED:
3198 tmp = "centered";
3199 break;
3200 case SLP_RIGHT:
3201 tmp = "right";
3202 break;
3203 case SLP_LEFT:
3204 tmp = "left";
3205 break;
3206 }
3207
3208 footnoteSepTmpWriter.addAttribute( "style:adjustment", tmp );
3209 footnoteSepTmpWriter.addAttributePt( "style:width", m_footNoteSeparatorLineWidth );
3210 footnoteSepTmpWriter.addAttribute( "style:rel-width", TQString::number( footNoteSeparatorLineLength() ) + "%" );
3211 switch( m_footNoteSeparatorLineType )
3212 {
3213 case SLT_SOLID:
3214 tmp = "solid";
3215 break;
3216 case SLT_DASH:
3217 tmp = "dash";
3218 break;
3219 case SLT_DOT:
3220 tmp = "dotted";
3221 break;
3222 case SLT_DASH_DOT:
3223 tmp = "dot-dash";
3224 break;
3225 case SLT_DASH_DOT_DOT:
3226 tmp = "dot-dot-dash";
3227 break;
3228 }
3229
3230 footnoteSepTmpWriter.addAttribute( "style:line-style", tmp );
3231
3232 footnoteSepTmpWriter.endElement();
3233 const TQString elementContents = TQString::fromUtf8( buffer.buffer(), buffer.buffer().size() );
3234 pageLayout.addChildElement( "separator", elementContents );
3235 buffer.close();
3236
3237 if ( m_pageColumns.columns > 1 ) {
3238 buffer.setBuffer(TQByteArray()); // clear data
3239 buffer.open( IO_WriteOnly );
3240 KoXmlWriter columnsTmpWriter( &buffer ); // TODO pass indentation level
3241 columnsTmpWriter.startElement( "style:columns" );
3242 columnsTmpWriter.addAttribute( "fo:column-count", m_pageColumns.columns );
3243 columnsTmpWriter.addAttributePt( "fo:column-gap", m_pageColumns.ptColumnSpacing );
3244 columnsTmpWriter.endElement(); // style:columns
3245 buffer.close();
3246 const TQString elementContents = TQString::fromUtf8( buffer.buffer(), buffer.buffer().size() );
3247 pageLayout.addChildElement( "columns", elementContents );
3248 }
3249
3250 // This is a bit of a hack, which only works as long as we have only one page master
3251 // if there's more than one pagemaster we need to rethink all this
3252
3253 pageLayoutName = mainStyles.lookup( pageLayout, "pm" );
3254 pageLayout.writeStyle( stylesWriter, mainStyles, "style:page-layout", pageLayoutName,
3255 "style:page-layout-properties", false /*don't close*/ );
3256
3257 // Ouch another problem: there is only one header style in oasis
3258 // ##### can't have different borders for even/odd headers...
3259 bool headerStyleSaved = false;
3260 bool footerStyleSaved = false;
3261 // ## This loop is duplicated in saveOasis
3262 TQPtrListIterator<KWFrameSet> fit = framesetsIterator();
3263 for ( ; fit.current() ; ++fit ) {
3264 const KWFrameSet* fs = fit.current();
3265 if ( fs->isVisible() && // HACK to avoid saving [hidden] headers/footers framesets for now
3266 !fs->isFloating() &&
3267 !fs->isDeleted() &&
3268 fs->type() == FT_TEXT &&
3269 fs->isHeaderOrFooter() )
3270 {
3271 // Save header/footer style
3272 KWFrame* frame = fs->frame(0);
3273 if ( fs->isAHeader() ) {
3274 if ( headerStyleSaved )
3275 continue;
3276 headerStyleSaved = true;
3277 stylesWriter->startElement( "style:header-style" );
3278 } else {
3279 if ( footerStyleSaved )
3280 continue;
3281 footerStyleSaved = true;
3282 stylesWriter->startElement( "style:footer-style" );
3283 }
3284#if 0 // more code reuse, but harder to integrate
3285 KoGenStyle hfStyle;
3286 hfStyle.addPropertyPt( "fo:min-height", frame->minimumFrameHeight() );
3287 frame->saveBorderProperties( hfStyle );
3288 frame->saveMarginProperties( hfStyle );
3289 ...
3290#endif
3291 stylesWriter->startElement( "style:header-footer-properties" );
3292 stylesWriter->addAttributePt( "fo:min-height", frame->minimumFrameHeight() );
3293 if ( fs->isAHeader() )
3294 stylesWriter->addAttributePt( "fo:margin-bottom", m_pageHeaderFooter.ptHeaderBodySpacing );
3295 else
3296 stylesWriter->addAttributePt( "fo:margin-top", m_pageHeaderFooter.ptFooterBodySpacing );
3297 // TODO frame->saveBorderAttributes( *stylesWriter );
3298 // Interesting idea, but we can't set margins (runaround) on
3299 //frame->saveMarginAttributes( *stylesWriter );
3300 stylesWriter->endElement(); // header-footer-properties
3301 stylesWriter->endElement(); // header-style
3302 }
3303 }
3304 stylesWriter->endElement(); // style:page-layout
3305
3306 // Headers and footers might have created new automatic parag/text styles -> save those
3307 KWOasisSaver::writeAutomaticStyles( *stylesWriter, mainStyles, true );
3308
3309 stylesWriter->endElement(); // office:automatic-styles
3310 }
3311
3312
3313 stylesWriter->startElement( "office:master-styles" );
3314 stylesWriter->startElement( "style:master-page" );
3315 stylesWriter->addAttribute( "style:name", "Standard" );
3316 stylesWriter->addAttribute( "style:page-layout-name", pageLayoutName );
3317
3318 if ( isHeaderVisible() || isFooterVisible() ) { // ### TODO save them even when hidden (and not empty)?
3319 stylesWriter->addCompleteElement( headerFooterContent.data() );
3320 }
3321
3322 stylesWriter->endElement();
3323 stylesWriter->endElement(); // office:master-styles
3324
3325 stylesWriter->endElement(); // root element (office:document-styles)
3326 stylesWriter->endDocument();
3327 delete stylesWriter;
3328}
3329
3330void KWDocument::saveOasisCustomFied( KoXmlWriter &writer )const
3331{
3332 bool customVariableFound = false;
3333 TQPtrListIterator<KoVariable> it( m_varColl->getVariables() );
3334 for ( ; it.current() ; ++it )
3335 {
3336 if ( it.current()->type() == VT_CUSTOM )
3337 {
3338 if ( !customVariableFound )
3339 {
3340 writer.startElement( "text:user-field-decls" );
3341 customVariableFound = true;
3342 }
3343 //<text:user-field-decl office:value-type="string" office:string-value="dfddd" text:name="cvbcbcbx"/>
3344 writer.startElement( "text:user-field-decl" );
3345 writer.addAttribute( "office:value-type", "string" );
3346 writer.addAttribute( "office:string-value", static_cast<KoCustomVariable *>( it.current() )->value() );
3347 writer.addAttribute( "text:name", static_cast<KoCustomVariable*>( it.current() )->name() );
3348 writer.endElement();
3349 }
3350 }
3351 if ( customVariableFound )
3352 writer.endElement();
3353}
3354
3355void KWDocument::saveOasisBody( KoXmlWriter& writer, KoSavingContext& context ) const
3356{
3357 saveOasisCustomFied( writer );
3358 if ( m_processingType == WP ) {
3359
3360 // Write out the non-inline framesets first; OOo wants it that way...
3361 TQPtrListIterator<KWFrameSet> fit = framesetsIterator();
3362 ++fit; // skip main text frameset
3363 for ( ; fit.current() ; ++fit ) {
3364 KWFrameSet* fs = fit.current();
3365 if ( !fs->isFloating() &&
3366 !fs->isDeleted() &&
3367 // footnotes already saved inline, header/footers elsewhere
3368 fs->frameSetInfo() == KWFrameSet::FI_BODY )
3369 {
3370 fs->saveOasis( writer, context, true );
3371 }
3372 }
3373
3374 // Write out the main text frameset's contents
3375 KWTextFrameSet *frameset = dynamic_cast<KWTextFrameSet *>( m_lstFrameSet.getFirst() );
3376 if ( frameset ) {
3377 frameset->saveOasisContent( writer, context );
3378 }
3379
3380 } else { // DTP mode: all framesets are equal
3381 // write text:page-sequence, one item per page.
3382 writer.startElement( "text:page-sequence" );
3383 for ( int page = 0; page < pageCount(); ++page )
3384 {
3385 writer.startElement( "text:page" );
3386 // "pm" is a hack, see mainStyles.lookup( pageLayout, "pm" ) in saveOasis
3387 // [which currently happens afterwards...]
3388 writer.addAttribute( "text:master-page-name", "pm" );
3389 writer.endElement(); // text:page
3390 }
3391 writer.endElement() ; // "text:page-sequence";
3392 // Now write the framesets
3393 TQPtrListIterator<KWFrameSet> fit = framesetsIterator();
3394 for ( ; fit.current() ; ++fit ) {
3395 KWFrameSet* fs = fit.current();
3396 if ( !fs->isFloating() &&
3397 !fs->isDeleted() &&
3398 fs->frameSetInfo() == KWFrameSet::FI_BODY )
3399 {
3400 fs->saveOasis( writer, context, true );
3401 }
3402 }
3403 }
3404}
3405
3406TQDomDocument KWDocument::saveXML()
3407{
3408 m_varColl->variableSetting()->setModificationDate(TQDateTime::currentDateTime());
3409 recalcVariables( VT_DATE );
3410 recalcVariables( VT_TIME ); // for "current time"
3411 recalcVariables( VT_STATISTIC );
3412 TQDomDocument doc = createDomDocument( "DOC", CURRENT_DTD_VERSION );
3413 TQDomElement kwdoc = doc.documentElement();
3414 kwdoc.setAttribute( "editor", "KWord" );
3415 kwdoc.setAttribute( "mime", "application/x-kword" );
3416 m_syntaxVersion = CURRENT_SYNTAX_VERSION;
3417 kwdoc.setAttribute( "syntaxVersion", m_syntaxVersion );
3418
3419 TQDomElement paper = doc.createElement( "PAPER" );
3420 kwdoc.appendChild( paper );
3421 paper.setAttribute( "format", static_cast<int>( m_pageLayout.format ) );
3422 paper.setAttribute( "pages", pageCount() );
3423 paper.setAttribute( "width", m_pageLayout.ptWidth );
3424 paper.setAttribute( "height", m_pageLayout.ptHeight );
3425 paper.setAttribute( "orientation", static_cast<int>( m_pageLayout.orientation ) );
3426 paper.setAttribute( "columns", m_pageColumns.columns );
3427 paper.setAttribute( "columnspacing", m_pageColumns.ptColumnSpacing );
3428 paper.setAttribute( "hType", static_cast<int>( m_pageHeaderFooter.header ) );
3429 paper.setAttribute( "fType", static_cast<int>( m_pageHeaderFooter.footer ) );
3430 paper.setAttribute( "spHeadBody", m_pageHeaderFooter.ptHeaderBodySpacing );
3431 paper.setAttribute( "spFootBody", m_pageHeaderFooter.ptFooterBodySpacing );
3432 paper.setAttribute( "spFootNoteBody", m_pageHeaderFooter.ptFootNoteBodySpacing );
3433 if ( m_footNoteSeparatorLinePos!=SLP_LEFT )
3434 {
3435 if (m_footNoteSeparatorLinePos==SLP_CENTERED )
3436 paper.setAttribute( "slFootNotePosition", "centered" );
3437 else if ( m_footNoteSeparatorLinePos==SLP_RIGHT )
3438 paper.setAttribute( "slFootNotePosition", "right" );
3439 else if ( m_footNoteSeparatorLinePos==SLP_LEFT ) //never !
3440 paper.setAttribute( "slFootNotePosition", "left" );
3441 }
3442 if ( m_footNoteSeparatorLineType != SLT_SOLID )
3443 paper.setAttribute( "slFootNoteType", static_cast<int>(m_footNoteSeparatorLineType) );
3444
3445
3446 paper.setAttribute("slFootNoteLength", m_iFootNoteSeparatorLineLength);
3447 paper.setAttribute("slFootNoteWidth", m_footNoteSeparatorLineWidth);
3448
3449 // Now part of the app config
3450 //paper.setAttribute( "zoom",m_zoom );
3451
3452 TQDomElement borders = doc.createElement( "PAPERBORDERS" );
3453 paper.appendChild( borders );
3454 borders.setAttribute( "left", m_pageLayout.ptLeft );
3455 borders.setAttribute( "top", m_pageLayout.ptTop );
3456 borders.setAttribute( "right", m_pageLayout.ptRight );
3457 borders.setAttribute( "bottom", m_pageLayout.ptBottom );
3458
3459 TQDomElement docattrs = doc.createElement( "ATTRIBUTES" );
3460 kwdoc.appendChild( docattrs );
3461 docattrs.setAttribute( "processing", static_cast<int>( m_processingType ) );
3462 docattrs.setAttribute( "standardpage", 1 );
3463 docattrs.setAttribute( "hasHeader", static_cast<int>(isHeaderVisible()) );
3464 docattrs.setAttribute( "hasFooter", static_cast<int>(isFooterVisible()) );
3465 docattrs.setAttribute( "unit", KoUnit::unitName(unit()) );
3466 docattrs.setAttribute( "hasTOC", static_cast<int>(m_hasTOC));
3467 docattrs.setAttribute( "tabStopValue", m_tabStop );
3468
3469 // Save visual info for the first view, such as the active frameset and cursor position
3470 // It looks like a hack, but reopening a document creates only one view anyway (David)
3471 KWView * view = static_cast<KWView*>(views().getFirst());
3472 if ( view ) // no view if embedded document
3473 {
3474 KWFrameSetEdit* edit = view->getGUI()->canvasWidget()->currentFrameSetEdit();
3475 if ( edit )
3476 {
3477 docattrs.setAttribute( "activeFrameset", edit->frameSet()->name() );
3478 KWTextFrameSetEdit* textedit = dynamic_cast<KWTextFrameSetEdit *>(edit);
3479 if ( textedit && textedit->cursor() ) {
3480 KoTextCursor* cursor = textedit->cursor();
3481 docattrs.setAttribute( "cursorParagraph", cursor->parag()->paragId() );
3482 docattrs.setAttribute( "cursorIndex", cursor->index() );
3483 }
3484 }
3485 }
3486
3487 if( !m_bookmarkList->isEmpty() )
3488 {
3489 TQDomElement bookmark = doc.createElement( "BOOKMARKS" );
3490 kwdoc.appendChild( bookmark );
3491
3492 for ( KoTextBookmarkList::const_iterator it = m_bookmarkList->begin();
3493 it != m_bookmarkList->end() ; ++it )
3494 {
3495 const KoTextBookmark& book = *it;
3496 KWTextFrameSet* fs = static_cast<KWTextDocument*>(book.textDocument())->textFrameSet();
3497 if ( book.startParag() &&
3498 book.endParag() &&
3499 fs && !fs->isDeleted() )
3500 {
3501 TQDomElement bookElem = doc.createElement( "BOOKMARKITEM" );
3502 bookmark.appendChild( bookElem );
3503 bookElem.setAttribute( "name", book.bookmarkName() );
3504 bookElem.setAttribute( "frameset", fs->name() );
3505 bookElem.setAttribute( "startparag", book.startParag()->paragId() );
3506 bookElem.setAttribute( "endparag", book.endParag()->paragId() );
3507
3508 bookElem.setAttribute( "cursorIndexStart", book.bookmarkStartIndex() );
3509 bookElem.setAttribute( "cursorIndexEnd", book.bookmarkEndIndex() );
3510 }
3511 }
3512 }
3513 variableCollection()->variableSetting()->save(kwdoc );
3514
3515 TQDomElement framesets = doc.createElement( "FRAMESETS" );
3516 kwdoc.appendChild( framesets );
3517
3518 m_textImageRequests.clear(); // for KWTextImage
3519 TQValueList<KoPictureKey> savePictures;
3520
3521 TQPtrListIterator<KWFrameSet> fit = framesetsIterator();
3522 for ( ; fit.current() ; ++fit )
3523 {
3524 KWFrameSet *frameSet = fit.current();
3525 // Save non-part framesets ( part are saved further down )
3526 if ( frameSet->type() != FT_PART )
3527 frameSet->save( framesets );
3528
3529 // If picture frameset, make a note of the image it needs.
3530 if ( !frameSet->isDeleted() && ( frameSet->type() == FT_PICTURE ) )
3531 {
3532 KoPictureKey key = static_cast<KWPictureFrameSet *>( frameSet )->key();
3533 if ( !savePictures.contains( key ) )
3534 savePictures.append( key );
3535 }
3536 }
3537
3538 // Process the data of the KWTextImage classes.
3539 TQPtrListIterator<KWTextImage> textIt ( m_textImageRequests );
3540 for ( ; textIt.current() ; ++textIt )
3541 {
3542 KoPictureKey key = textIt.current()->getKey();
3543 kdDebug(32001) << "KWDocument::saveXML registering text image " << key.toString() << endl;
3544 if ( !savePictures.contains( key ) )
3545 savePictures.append( key );
3546 }
3547
3548 TQDomElement styles = doc.createElement( "STYLES" );
3549 kwdoc.appendChild( styles );
3550 TQValueList<KoUserStyle *> styleList(m_styleColl->styleList());
3551 for ( TQValueList<KoUserStyle *>::const_iterator it = styleList.begin(), end = styleList.end();
3552 it != end ; ++it )
3553 saveStyle( static_cast<KoParagStyle *>( *it ), styles );
3554
3555 TQDomElement frameStyles = doc.createElement( "FRAMESTYLES" );
3556 kwdoc.appendChild( frameStyles );
3557 TQValueList<KoUserStyle *> frameStyleList(m_frameStyleColl->styleList());
3558 for ( TQValueList<KoUserStyle *>::const_iterator it = frameStyleList.begin(), end = frameStyleList.end();
3559 it != end ; ++it )
3560 saveFrameStyle( static_cast<KWFrameStyle *>(*it), frameStyles );
3561
3562 TQDomElement tableStyles = doc.createElement( "TABLESTYLES" );
3563 kwdoc.appendChild( tableStyles );
3564 TQValueList<KoUserStyle *> tableStyleList(m_tableStyleColl->styleList());
3565 for ( TQValueList<KoUserStyle *>::const_iterator it = tableStyleList.begin(), end = tableStyleList.end();
3566 it != end ; ++it )
3567 saveTableStyle( static_cast<KWTableStyle *>(*it), tableStyles );
3568
3569 TQDomElement pictures = m_pictureCollection->saveXML( KoPictureCollection::CollectionPicture, doc, savePictures );
3570 kwdoc.appendChild( pictures );
3571
3572 // Not needed anymore
3573#if 0
3574 // Write out the list of parags (id) that form the table of contents, see KWContents::createContents
3575 if ( contents->hasContents() ) {
3576 TQDomElement cParags = doc.createElement( "CPARAGS" );
3577 kwdoc.appendChild( cParags );
3578 TQValueList<int>::Iterator it = contents->begin();
3579 for ( ; it != contents->end(); ++it )
3580 {
3581 TQDomElement paragElem = doc.createElement( "PARAG" );
3582 cParags.appendChild( paragElem );
3583 paragElem.setAttribute( "name", TQString::number( *it ) ); // write parag id
3584 }
3585 }
3586#endif
3587
3588 TQDomElement mailMerge=m_slDataBase->save(doc);
3589 kwdoc.appendChild(mailMerge);
3590
3591 if( !m_spellCheckIgnoreList.isEmpty() )
3592 {
3593 TQDomElement spellCheckIgnore = doc.createElement( "SPELLCHECKIGNORELIST" );
3594 kwdoc.appendChild( spellCheckIgnore );
3595 for ( TQStringList::ConstIterator it = m_spellCheckIgnoreList.begin(); it != m_spellCheckIgnoreList.end(); ++it )
3596 {
3597 TQDomElement spellElem = doc.createElement( "SPELLCHECKIGNOREWORD" );
3598 spellCheckIgnore.appendChild( spellElem );
3599 spellElem.setAttribute( "word", *it );
3600 }
3601 }
3602
3603 // Save embedded objects
3604 saveEmbeddedObjects( kwdoc, children() );
3605 return doc;
3606}
3607
3608// KWord-1.3 format
3609void KWDocument::saveEmbeddedObjects( TQDomElement& parentElem, const TQPtrList<KoDocumentChild>& childList )
3610{
3611 // Write "OBJECT" tag for every child, appending "EMBEDDING" tags to the main XML
3612 TQPtrListIterator<KoDocumentChild> chl( childList );
3613 TQDomDocument doc = parentElem.ownerDocument();
3614 for( ; chl.current(); ++chl ) {
3615 KWDocumentChild* curr = static_cast<KWDocumentChild*>(chl.current());
3616 if ( !curr->isDeleted() )
3617 {
3618 TQDomElement embeddedElem = doc.createElement( "EMBEDDED" );
3619 parentElem.appendChild( embeddedElem );
3620
3621 TQDomElement objectElem = curr->save( doc, true );
3622 embeddedElem.appendChild( objectElem );
3623
3624 TQDomElement settingsElem = doc.createElement( "SETTINGS" );
3625 embeddedElem.appendChild( settingsElem );
3626
3627 curr->partFrameSet()->save( settingsElem );
3628 }
3629 }
3630}
3631
3632// KWord-1.3 format
3633void KWDocument::saveStyle( KoParagStyle *sty, TQDomElement parentElem )
3634{
3635 TQDomDocument doc = parentElem.ownerDocument();
3636 TQDomElement styleElem = doc.createElement( "STYLE" );
3637 parentElem.appendChild( styleElem );
3638
3639 sty->saveStyle( styleElem );
3640
3641 TQDomElement formatElem = KWTextParag::saveFormat( doc, &sty->format(), 0L, 0, 0 );
3642 styleElem.appendChild( formatElem );
3643}
3644
3645// KWord-1.3 format
3646void KWDocument::saveFrameStyle( KWFrameStyle *sty, TQDomElement parentElem )
3647{
3648 TQDomDocument doc = parentElem.ownerDocument();
3649 TQDomElement frameStyleElem = doc.createElement( "FRAMESTYLE" );
3650 parentElem.appendChild( frameStyleElem );
3651
3652 sty->saveFrameStyle( frameStyleElem );
3653}
3654
3655// KWord-1.3 format
3656void KWDocument::saveTableStyle( KWTableStyle *sty, TQDomElement parentElem )
3657{
3658 TQDomDocument doc = parentElem.ownerDocument();
3659 TQDomElement tableStyleElem = doc.createElement( "TABLESTYLE" );
3660 parentElem.appendChild( tableStyleElem );
3661
3662 sty->saveTableStyle( tableStyleElem );
3663}
3664
3665
3666TQValueList<KoPictureKey> KWDocument::savePictureList()
3667{
3668 TQValueList<KoPictureKey> savePictures;
3669
3670 // At first, we must process the data of the KWTextImage classes.
3671 // Process the data of the KWTextImage classes.
3672 TQPtrListIterator<KWTextImage> textIt ( m_textImageRequests );
3673 for ( ; textIt.current() ; ++textIt )
3674 {
3675 KoPictureKey key = textIt.current()->getKey();
3676 kdDebug(32001) << "KWDocument::saveXML registering text image " << key.toString() << endl;
3677 if ( !savePictures.contains( key ) )
3678 savePictures.append( key );
3679 }
3680 m_textImageRequests.clear(); // Save some memory!
3681
3682 // Now do the images/cliparts in frames.
3683 TQPtrListIterator<KWFrameSet> fit = framesetsIterator();
3684 for ( ; fit.current() ; ++fit )
3685 {
3686 KWFrameSet *frameSet = fit.current();
3687 // If picture frameset, make a note of the image it needs.
3688 if ( !frameSet->isDeleted() && ( frameSet->type() == FT_PICTURE ) )
3689 {
3690 KoPictureKey key = static_cast<KWPictureFrameSet *>( frameSet )->key();
3691 if ( !savePictures.contains( key ) )
3692 savePictures.append( key );
3693 }
3694 }
3695 return savePictures;
3696}
3697
3698// KWord-1.3 format
3699bool KWDocument::completeSaving( KoStore *store )
3700{
3701 if ( !store )
3702 return true;
3703
3704 TQString u = KURL( url() ).path();
3705
3706 TQValueList<KoPictureKey> savePictures( savePictureList() );
3707
3708 return m_pictureCollection->saveToStore( KoPictureCollection::CollectionPicture, store, savePictures );
3709}
3710
3711int KWDocument::supportedSpecialFormats() const
3712{
3713 return KoDocument::supportedSpecialFormats();
3714}
3715
3716void KWDocument::addView( KoView *view )
3717{
3718 m_lstViews.append( (KWView*)view );
3719 KoDocument::addView( view );
3720 for( TQValueList<KWView *>::Iterator it = m_lstViews.begin(); it != m_lstViews.end(); ++it ) {
3721 (*it)->deselectAllFrames();
3722 }
3723}
3724
3725void KWDocument::removeView( KoView *view )
3726{
3727 m_lstViews.remove( static_cast<KWView*>(view) );
3728 KoDocument::removeView( view );
3729}
3730
3731void KWDocument::addShell( KoMainWindow *shell )
3732{
3733 connect( shell, TQ_SIGNAL( documentSaved() ), m_commandHistory, TQ_SLOT( documentSaved() ) );
3734 connect( shell, TQ_SIGNAL( saveDialogShown() ), this, TQ_SLOT( saveDialogShown() ) );
3735 KoDocument::addShell( shell );
3736}
3737
3738KoView* KWDocument::createViewInstance( TQWidget* parent, const char* name )
3739{
3740 if ( isEmbedded() )
3741 return new KWView( "ModeEmbedded", parent, name, this );
3742 else
3743 return new KWView( m_viewModeType, parent, name, this );
3744}
3745
3746// Paint this document when it's embedded
3747// This is also used to paint the preview.png that goes into the ZIP file
3748void KWDocument::paintContent( TQPainter& painter, const TQRect& rectangle, bool transparent, double zoomX, double zoomY )
3749{
3750 //kdDebug(32001) << "KWDocument::paintContent m_zoom=" << m_zoom << " zoomX=" << zoomX << " zoomY=" << zoomY << " transparent=" << transparent << " rectangle=" << rectangle << endl;
3751 Q_ASSERT( zoomX != 0 );
3752 Q_ASSERT( zoomY != 0 );
3753
3754 setZoom( 100 );
3755 m_zoomMode = KoZoomMode::ZOOM_CONSTANT;
3756
3757 // The caller doesn't care about DPI, that's our own internal zooming done on top of it:
3758 zoomX *= POINT_TO_INCH( static_cast<double>( KoGlobal::dpiX() ) );
3759 zoomY *= POINT_TO_INCH( static_cast<double>( KoGlobal::dpiY() ) );
3760
3761 if ( m_zoomedResolutionX != zoomX || m_zoomedResolutionY != zoomY )
3762 {
3763 //kdDebug(32001) << "m_zoomedResolutionX=" << m_zoomedResolutionX << " != " << zoomX << " -> calling setResolution(" << zoomX << ")" << endl;
3764 int zoomLevel = tqRound( 100 * zoomY / m_zoomedResolutionY ); // ## ignores the case where the x and y scaling differs
3765 setZoom( zoomLevel );
3766 bool forPrint = painter.device() && painter.device()->devType() == TQInternal::Printer;
3767 newZoomAndResolution( false, forPrint );
3768 if ( KFormula::Document* formulaDocument = m_formulaDocumentWrapper->document() )
3769 formulaDocument->setZoomAndResolution( zoomLevel, zoomX, zoomY, false, forPrint );
3770 // Note that this zoom and resolution are then used when activating the embedded object!
3771 }
3772
3773 TQRect rect( rectangle );
3774 painter.save();
3775 painter.translate( rect.x(), rect.y() );
3776 TQRect clipRect( 0, 0, rect.width(), rect.height() );
3777
3778 KWViewModeEmbedded * viewMode = new KWViewModeEmbedded( this, 0 /*no canvas*/ );
3779 viewMode->setDrawFrameBackground( !transparent );
3780 viewMode->setDrawSelections( false );
3781
3782 TQColorGroup cg = TQApplication::palette().active();
3783
3784 if (!transparent)
3785 {
3786 TQRegion emptyRegion( rect );
3787 createEmptyRegion( rect, emptyRegion, viewMode );
3788 eraseEmptySpace( &painter, emptyRegion, cg.brush( TQColorGroup::Base ) );
3789 }
3790
3791 TQPtrListIterator<KWFrameSet> fit = framesetsIterator();
3792 for ( ; fit.current() ; ++fit )
3793 {
3794 KWFrameSet * frameset = fit.current();
3795 if ( frameset->isVisible( viewMode ) && !frameset->isFloating() )
3796 frameset->drawContents( &painter, clipRect, cg,
3797 false /*onlyChanged*/, true /*resetChanged*/,
3798 0L, viewMode, 0 );
3799 }
3800 delete viewMode;
3801
3802 painter.restore();
3803}
3804
3805TQPixmap KWDocument::generatePreview( const TQSize& size )
3806{
3807 int oldZoom = m_zoom;
3808 double oldResolutionX = resolutionX();
3809 double oldResolutionY = resolutionY();
3810 double oldZoomX = zoomedResolutionX();
3811 double oldZoomY = zoomedResolutionY();
3812
3813 // Sometimes (due to the different resolution?) the layout creates a new page
3814 // while saving the preview. If this happens, we don't want to repaint the real views
3815 // (due to KWCanvas::slotNewContentsSize)
3816 // ##### One day when we have real doc/view separation in kotextparag, we shouldn't mess with
3817 // the real view's resolution, we should instead create a fake view for the preview itself.
3818 for( TQValueList<KWView *>::Iterator it = m_lstViews.begin(); it != m_lstViews.end(); ++it ) {
3819 (*it)->getGUI()->canvasWidget()->setUpdatesEnabled( false );
3820 }
3821 Q_ASSERT( !m_bGeneratingPreview );
3822 m_bGeneratingPreview = true;
3823 TQPixmap pix = KoDocument::generatePreview(size);
3824
3825 // Restore everything as it was before
3826 setResolution( oldResolutionX, oldResolutionY );
3827 setZoom( oldZoom );
3828
3829 for( TQValueList<KWView *>::Iterator it = m_lstViews.begin(); it != m_lstViews.end(); ++it ) {
3830 (*it)->getGUI()->canvasWidget()->setUpdatesEnabled( true );
3831 }
3832 newZoomAndResolution( true /*set contents size again*/, false );
3833 m_bGeneratingPreview = false;
3834 if ( KFormula::Document* formulaDocument = m_formulaDocumentWrapper->document() ) {
3835 formulaDocument->setZoomAndResolution( oldZoom, oldZoomX, oldZoomY );
3836 }
3837 return pix;
3838}
3839
3840void KWDocument::createEmptyRegion( const TQRect & crect, TQRegion & emptyRegion, KWViewMode * viewMode )
3841{
3842 TQPtrListIterator<KWFrameSet> fit = framesetsIterator();
3843 for ( ; fit.current() ; ++fit )
3844 {
3845 KWFrameSet *frameset = fit.current();
3846 if ( frameset->isVisible( viewMode ) )
3847 frameset->createEmptyRegion( crect, emptyRegion, viewMode );
3848 }
3849}
3850
3851void KWDocument::eraseEmptySpace( TQPainter * painter, const TQRegion & emptySpaceRegion, const TQBrush & brush )
3852{
3853 painter->save();
3854 painter->setClipRegion( emptySpaceRegion, TQPainter::CoordPainter );
3855 painter->setPen( TQt::NoPen );
3856
3857 //kdDebug(32001) << "KWDocument::eraseEmptySpace emptySpaceRegion: " << emptySpaceRegion << endl;
3858 //kdDebug(32001) << " boundingRect: " << DEBUGRECT( emptySpaceRegion.boundingRect() ) << endl;
3859 painter->fillRect( emptySpaceRegion.boundingRect(), brush );
3860 painter->restore();
3861}
3862
3863KWDocumentChild* KWDocument::createChildDoc( const KoRect& rect, KoDocument* childDoc )
3864{
3865 KWDocumentChild* ch = new KWDocumentChild( this, rect.toTQRect(), childDoc );
3866 insertChild( ch );
3867 return ch;
3868}
3869
3870KWPartFrameSet* KWDocument::insertObject( const KoRect& rect, KoDocumentEntry& e, TQWidget* parentWidget )
3871{
3872 KoDocument* doc = e.createDoc( this );
3873 if ( !doc )
3874 return 0;
3875 if ( !doc->showEmbedInitDialog( parentWidget ) )
3876 return 0;
3877
3878 KWDocumentChild* ch = createChildDoc( rect, doc );
3879 setModified( true );
3880
3881 KWPartFrameSet *frameset = new KWPartFrameSet( this, ch, TQString() );
3882 KWFrame *frame = new KWFrame(frameset, rect.x(), rect.y(), rect.width(), rect.height() );
3883 frame->setZOrder( maxZOrder( frame->pageNumber(this) ) + 1 ); // make sure it's on top
3884 frameset->addFrame( frame );
3885 addFrameSet( frameset );
3886
3887 KWCreateFrameCommand *cmd = new KWCreateFrameCommand( i18n("Create Part Frame"), frame);
3888 addCommand(cmd);
3889
3890 frameChanged( frame ); // repaint etc.
3891
3892 return frameset;
3893}
3894
3895
3896void KWDocument::delayedRepaintAllViews() {
3897 if (!m_repaintAllViewsPending) {
3898 TQTimer::singleShot( 0, this, TQ_SLOT( slotRepaintAllViews() ) );
3899 m_repaintAllViewsPending=true;
3900 }
3901}
3902
3903void KWDocument::slotRepaintAllViews() {
3904 m_repaintAllViewsPending=false;
3905 repaintAllViews( false );
3906}
3907
3908void KWDocument::delayedRecalcFrames( int fromPage ) {
3909 //kdDebug() << k_funcinfo << fromPage << endl;
3910 if ( m_recalcFramesPending == -1 || fromPage < m_recalcFramesPending )
3911 {
3912 m_recalcFramesPending = fromPage;
3913 TQTimer::singleShot( 0, this, TQ_SLOT( slotRecalcFrames() ) );
3914 }
3915}
3916
3917void KWDocument::slotRecalcFrames() {
3918 int from = m_recalcFramesPending;
3919 kdDebug() << k_funcinfo << "from=" << from << endl;
3920 m_recalcFramesPending = -1;
3921 if ( from != -1 )
3922 recalcFrames( from );
3923}
3924
3925void KWDocument::repaintAllViewsExcept( KWView *view, bool erase )
3926{
3927 //kdDebug(32001) << "KWDocument::repaintAllViewsExcept" << endl;
3928 for( TQValueList<KWView *>::Iterator it = m_lstViews.begin(); it != m_lstViews.end(); ++it ) {
3929 KWView* viewPtr = *it;
3930 if ( viewPtr != view /*&& viewPtr->getGUI() && viewPtr->getGUI()->canvasWidget()*/ ) {
3931 viewPtr->getGUI()->canvasWidget()->repaintAll( erase );
3932 }
3933 }
3934}
3935
3936void KWDocument::updateAllStyleLists()
3937{
3938 for( TQValueList<KWView *>::Iterator it = m_lstViews.begin(); it != m_lstViews.end(); ++it )
3939 (*it)->updateStyleList();
3940}
3941
3942void KWDocument::updateStyleListOrder( const TQStringList &list )
3943{
3944 styleCollection()->updateStyleListOrder( list );
3945}
3946
3947void KWDocument::applyStyleChange( KoStyleChangeDefMap changed )
3948{
3949 TQPtrList<KWTextFrameSet> textFramesets = allTextFramesets( true );
3950
3951 KWTextFrameSet *frm;
3952 for ( frm=textFramesets.first(); frm != 0; frm=textFramesets.next() ){
3953 frm->applyStyleChange( changed );
3954 }
3955}
3956
3957void KWDocument::updateAllFrameStyleLists()
3958{
3959 for( TQValueList<KWView *>::Iterator it = m_lstViews.begin(); it != m_lstViews.end(); ++it )
3960 (*it)->updateFrameStyleList();
3961}
3962
3963void KWDocument::updateAllTableStyleLists()
3964{
3965 for( TQValueList<KWView *>::Iterator it = m_lstViews.begin(); it != m_lstViews.end(); ++it )
3966 (*it)->updateTableStyleList();
3967}
3968
3969void KWDocument::repaintAllViews( bool erase )
3970{
3971 //kdDebug(32001) << "KWDocument::repaintAllViews" << endl;
3972 for( TQValueList<KWView *>::Iterator it = m_lstViews.begin(); it != m_lstViews.end(); ++it )
3973 (*it)->getGUI()->canvasWidget()->repaintAll( erase );
3974}
3975
3976TQPtrList<KWFrame> KWDocument::framesToCopyOnNewPage( int afterPageNum ) const {
3977 // afterPageNum can be -1 for 'before page 1'
3978
3979 // Look at frames on pages afterPageNum and afterPageNum-1 (for sheetside stuff)
3980 TQPtrList<KWFrame> framesToLookAt;
3981 if ( afterPageNum >= startPage() )
3982 framesToLookAt = framesInPage( afterPageNum, false );
3983
3984 if ( afterPageNum >= startPage() + 1 )
3985 {
3986 TQPtrList<KWFrame> framesToAlsoLookAt = framesInPage( afterPageNum-1, false ); // order doesn't matter
3987
3988 // Merge into single list. Other alternative, two loops, code inside moved to another method.
3989 TQPtrListIterator<KWFrame> frameAlsoIt( framesToAlsoLookAt );
3990 for ( ; frameAlsoIt.current(); ++frameAlsoIt )
3991 framesToLookAt.append( frameAlsoIt.current() );
3992 }
3993
3994 TQPtrList<KWFrame> framesToCopy; // the result
3995
3996 TQPtrListIterator<KWFrame> frameIt( framesToLookAt );
3997 for ( ; frameIt.current(); ++frameIt )
3998 {
3999 KWFrame * frame = frameIt.current();
4000 KWFrameSet* frameSet = frame->frameSet();
4001
4002 // don't add tables! A table cell ( frameset ) _must_ not have cells auto-added to them!
4003 if ( frameSet->type() == FT_TABLE ) continue;
4004
4005 // NewFrameBehavior == Copy is handled here except for headers/footers, which
4006 // are created in recalcFrames()
4007 if(frameSet->isAHeader() || frameSet->isAFooter()) continue;
4008
4009#ifdef DEBUG_PAGES
4010 kdDebug(32002) << "KWDocument::framesToCopyOnNewPage looking at frame " << frame << ", pageNum=" << frame->pageNumber() << " from " << frameSet->name() << endl;
4011 static const char * newFrameBh[] = { "Reconnect", "NoFollowup", "Copy" };
4012 kdDebug(32002) << " frame->newFrameBehavior()==" << newFrameBh[frame->newFrameBehavior()] << endl;
4013#endif
4014 const int frameIsOnPage = frame->pageNumber();
4015 if (frame->newFrameBehavior() == KWFrame::Copy &&
4016 (frameIsOnPage == afterPageNum && frame->sheetSide() == KWFrame::AnySide ||
4017 frameIsOnPage == afterPageNum -1 && frame->sheetSide() != KWFrame::AnySide))
4018 framesToCopy.append( frame );
4019 }
4020 return framesToCopy;
4021}
4022
4023KWPage* KWDocument::insertPage( int afterPageNum ) // can be -1 for 'before page 0'
4024{
4025#ifdef DEBUG_PAGES
4026 kdDebug(32002) << "insertPage: afterPageNum=" << afterPageNum << endl;
4027#endif
4028 if ( processingType() == WP )
4029 Q_ASSERT( afterPageNum == lastPage() ); // WP mode: can only append.
4030
4031 double pageHeight = pageManager()->page( afterPageNum )->height();
4032 // If not appending, move down everything after 'afterPageNum', to make room.
4033 for ( int pg = pageCount () -1 ; pg > afterPageNum ; --pg )
4034 {
4035 // pg is the 'src' page. Its contents must be moved to the page pg+1
4036 TQPtrList<KWFrame> frames = framesInPage( pg, false );
4037#ifdef DEBUG_PAGES
4038 kdDebug(32002) << "insertPage: moving " << frames.count() << " frames down, from page " << pg << endl;
4039#endif
4040 TQPtrListIterator<KWFrame> frameIt( frames );
4041 for ( ; frameIt.current(); ++frameIt )
4042 frameIt.current()->moveBy( 0, pageHeight );
4043 }
4044
4045 KWPage *page = pageManager()->insertPage(afterPageNum+1);
4046
4047 // Fill in the new page
4048 TQPtrList<KWFrame> framesToCopy = framesToCopyOnNewPage( afterPageNum );
4049 TQPtrListIterator<KWFrame> frameIt( framesToCopy );
4050 for ( ; frameIt.current(); ++frameIt )
4051 {
4052 KWFrame * frame = frameIt.current();
4053
4054 KWFrame *newFrame = frame->getCopy();
4055 newFrame->moveBy( 0, pageHeight );
4056 frame->frameSet()->addFrame( newFrame );
4057
4058 if ( frame->newFrameBehavior()==KWFrame::Copy )
4059 newFrame->setCopy( true );
4060 //kdDebug(32002) << " => created frame " << newFrame << " " << *newFrame << endl;
4061 }
4062 return page;
4063}
4064
4065KWPage* KWDocument::appendPage()
4066{
4067#ifdef DEBUG_PAGES
4068 kdDebug(32002) << "KWDocument::appendPage pageCount()=" << pageCount() << " -> insertPage(" << lastPage() << ")" << endl;
4069#endif
4070 return insertPage( lastPage() );
4071}
4072
4073void KWDocument::afterInsertPage( int pageNum )
4074{
4075#ifdef DEBUG_PAGES
4076 kdDebug(32002) << "KWDocument::afterInsertPage " << pageNum << endl;
4077#endif
4078 if ( !m_bGeneratingPreview )
4079 emit newContentsSize();
4080
4081 // Get headers and footers on the new page
4082 // This shouldn't delete the newly created page because it's still empty though
4083 recalcFrames( pageNum, -1, KWFrameLayout::DontRemovePages );
4084 // Take into account the frames on the new page, and run updateFramesOnTopOrBelow (#73819)
4085 updateAllFrames();
4086
4087 recalcVariables( VT_PGNUM );
4088 emit numPagesChanged();
4089 if ( m_viewModeType == "ModePreview" )
4090 repaintAllViews();
4091}
4092
4093bool KWDocument::canRemovePage( int num )
4094{
4095kdDebug() << "KWDocument::canRemovePage " << num<< endl;
4096 TQPtrListIterator<KWFrameSet> fit = framesetsIterator();
4097 for ( ; fit.current() ; ++fit )
4098 {
4099 KWFrameSet * frameSet = fit.current();
4100 if ( frameSet->isHeaderOrFooter() ) // don't look at headers/footers, but look at footnotes/endnotes
4101 continue;
4102 if ( frameSet->isVisible() && !frameSet->canRemovePage( num ) )
4103 return false;
4104 }
4105#ifdef DEBUG_PAGES
4106 kdDebug(32002) << "KWDocument::canRemovePage " << num << "-> true" << endl;
4107#endif
4108 return true;
4109}
4110
4111void KWDocument::removePage( int pageNum )
4112{
4113 if ( processingType() == WP )
4114 Q_ASSERT( pageNum == lastPage() ); // WP mode: can only remove last page.
4115 Q_ASSERT( pageCount() > 1 );
4116 if ( pageCount() == 1 )
4117 return;
4118
4119 // ## This assumes that framesInPage is up-to-date.
4120 TQPtrList<KWFrame> framesToDelete = framesInPage( pageNum, false );
4121#ifdef DEBUG_PAGES
4122 kdDebug(32002) << "KWDocument::removePage " << pageNum << ", " << framesToDelete.count() << " frames to delete" << endl;
4123#endif
4124 TQPtrListIterator<KWFrame> frameIt( framesToDelete );
4125 for ( ; frameIt.current(); ++frameIt )
4126 {
4127 KWFrame * frame = frameIt.current();
4128 KWFrameSet * frameSet = frame->frameSet();
4129 if ( frameSet->frameSetInfo() != KWFrameSet::FI_BODY )
4130 continue;
4131 frameSet->deleteFrame( frame, true );
4132 }
4133
4134 // If not removing the last one, move up everything after the one we removed.
4135 for ( int pg = pageNum+1 ; pg < pageCount() ; ++pg )
4136 {
4137 // pg is the 'src' page. Its contents must be moved to the page pg-1
4138 TQPtrList<KWFrame> frames = framesInPage( pg, false );
4139#ifdef DEBUG_PAGES
4140 kdDebug(32002) << "removePage: moving " << frames.count() << " frames up, from page " << pg << endl;
4141#endif
4142 TQPtrListIterator<KWFrame> frameIt( frames );
4143 for ( ; frameIt.current(); ++frameIt )
4144 frameIt.current()->moveBy( 0, pageManager()->page(0)->height() );
4145 }
4146
4147 pageManager()->removePage(pageNum);
4148#ifdef DEBUG_PAGES
4149 kdDebug(32002) << "KWDocument::removePage -- -> " << pageCount() << endl;
4150#endif
4151 // Emitting this one for each page being removed helps giving the user some feedback
4152 emit numPagesChanged();
4153}
4154
4155void KWDocument::afterRemovePages()
4156{
4157 //### IMHO recalcFrames should take care of updateAllFrames (it already does it partially).
4158 recalcFrames();
4159 // Do this before recalcVariables (which repaints). The removed frames must be removed from the frame caches.
4160 // We don't call updateAllFrames() directly, because it still calls
4161 // updateFramesOnTopOrBelow, which is useless (and slow) here.
4162 TQPtrListIterator<KWFrameSet> fit = framesetsIterator();
4163 for ( ; fit.current() ; ++fit )
4164 fit.current()->updateFrames();
4165
4166 recalcVariables( VT_PGNUM );
4167 if ( !m_bGeneratingPreview )
4168 emit newContentsSize();
4169 if ( m_viewModeType == "ModePreview" )
4170 repaintAllViews();
4171}
4172
4173bool KWDocument::tryRemovingPages()
4174{
4175 int last = lastPage();
4176 bool removed = false;
4177 // Last frame is empty -> try removing last page, and more if necessary
4178 while ( last > startPage() && canRemovePage( last ) )
4179 {
4180 removePage( last ); // this modifies pageCount
4181 if ( last <= lastPage() )
4182 {
4183 kdWarning() << "Didn't manage to remove page " << last << " (still having " << pageCount() << " pages ). Aborting" << endl;
4184 break;
4185 }
4186 removed = true;
4187 last = lastPage();
4188 }
4189 // Don't call afterRemovePages or recalcFrames from here, since this method is
4190 // itself called from KWFrameLayout (#95047)
4191 return removed;
4192}
4193
4194
4195KWFrameSet * KWDocument::frameSetByName( const TQString & name )
4196{
4197 // Note: this isn't recursive, so it won't find table cells.
4198 TQPtrListIterator<KWFrameSet> fit = framesetsIterator();
4199 for ( ; fit.current() ; ++fit )
4200 if ( fit.current()->name() == name )
4201 return fit.current();
4202 return 0L;
4203}
4204
4205//#define DEBUG_FRAMESELECT
4206
4207TQString KWDocument::generateFramesetName( const TQString & templateName )
4208{
4209 TQString name;
4210 int num = 1;
4211 bool exists;
4212 do {
4213 name = templateName.arg( num );
4214 exists = frameSetByName( name );
4215 ++num;
4216 } while ( exists );
4217 return name;
4218}
4219
4220void KWDocument::fixZOrders() {
4221 //KWFrame *frameFixed = 0;
4222 for (int pgnum = startPage() ; pgnum <= lastPage() ; pgnum++) {
4223 TQPtrList<KWFrame> frames = framesInPage(pgnum);
4224 // scan this page to see if we need to fixup:
4225 // fix up if two frames have the same zOrder,
4226 // or if a zOrder is negative (not allowed by OASIS)
4227 bool need_fixup = false;
4228 KWFrame *f = frames.last();
4229 if ( !f )
4230 continue;
4231 int lastZOrder = f->zOrder();
4232 f = frames.prev();
4233 for ( ; f ; f=frames.prev() ) {
4234 if ( !f->frameSet()->isFloating() &&
4235 ( f->zOrder() == lastZOrder || f->zOrder() < 0 ) ) {
4236 need_fixup = true;
4237 break;
4238 }
4239 lastZOrder = f->zOrder();
4240 }
4241 if ( need_fixup ) {
4242 int current_zorder=0;
4243 kdDebug() << "fixing page " << pgnum << " z-orders " << endl;
4244 for (KWFrame *fr = frames.first();fr;fr=frames.next()) {
4245 // only consider non-inline framesets.
4246 if (fr->frameSet()->isFloating())
4247 continue;
4248 current_zorder++;
4249 fr->setZOrder(current_zorder);
4250 //frameFixed = f;
4251 }
4252 }
4253
4254 if ( m_processingType == KWDocument::WP )
4255 {
4256 // In all cases, ensure the main frames are below the rest.
4257 // (This could not be the case after e.g. an import filter does it wrong)
4258 lowerMainFrames( pgnum );
4259 }
4260 }
4261 //if ( frameFixed )
4262 // frameFixed->frameStack()->recalcAllFrames();
4264}
4265
4266void KWDocument::lowerMainFrames( int pageNum )
4267{
4268 TQPtrList<KWFrame> framesInPage = this->framesInPage(pageNum);
4269 int lowestZOrder=10000;
4270 for ( TQPtrListIterator<KWFrame> frameIt( framesInPage ); frameIt.current(); ++frameIt )
4271 lowestZOrder=TQMIN(lowestZOrder, frameIt.current()->zOrder());
4272 lowerMainFrames( pageNum, lowestZOrder );
4273}
4274
4275// separated from the above one for KWView (which knows lowestZOrder already)
4276void KWDocument::lowerMainFrames( int pageNum, int lowestZOrder )
4277{
4278 // Get the main frameset and see if we have to lower its frame(s).
4279 TQPtrList<KWFrame> framesInPage = this->framesInPage(pageNum);
4280 for ( TQPtrListIterator<KWFrame> frameIt( framesInPage ); frameIt.current(); ++frameIt ) {
4281 if(frameIt.current()->frameSet()->isMainFrameset()) {
4282 if(lowestZOrder <= frameIt.current()->zOrder())
4283 frameIt.current()->setZOrder(lowestZOrder-1);
4284 // keep going, in case of multiple columns
4285 }
4286 }
4287}
4288
4289TQPtrList<KWFrame> KWDocument::framesInPage( int pageNum, bool sorted ) const {
4290
4291 ZOrderedFrameList frames;
4292 TQPtrListIterator<KWFrameSet> fit = framesetsIterator();
4293 for ( ; fit.current() ; ++fit )
4294 {
4295 KWFrameSet *frameSet = fit.current();
4296 if ( !frameSet->isVisible() )
4297 continue;
4298 // Append all frames from frameSet in page pageNum
4299 TQPtrListIterator<KWFrame> it( frameSet->framesInPage( pageNum ) );
4300 for ( ; it.current() ; ++it )
4301 frames.append( it.current() );
4302 }
4303 if (sorted) frames.sort();
4304 return frames;
4305}
4306
4307void KWDocument::updateAllFrames( int flags )
4308{
4309#ifdef DEBUG_SPEED
4310 TQTime dt;
4311 dt.start();
4312#endif
4313 TQPtrListIterator<KWFrameSet> fit = framesetsIterator();
4314 for ( ; fit.current() ; ++fit )
4315 fit.current()->updateFrames( flags );
4316
4317#ifdef DEBUG_SPEED
4318 kdDebug(32001) << "updateAllFrames(" << flags << ") took " << (float)(dt.elapsed()) / 1000 << " seconds" << endl;
4319#endif
4320
4321 // TODO: check all calls to updateAllFrames, and fix them.
4322 // E.g., if one frame moved, updateAllFrames isn't necessary,
4323 // only fs->updateFrames() and doc->updateFramesOnTopOrBelow() are necessary.
4324
4325 // Update frames ontop and below _afterwards_,
4326 // it needs the 'frames in page' array (in other framesets)
4328}
4329
4330// Tell this method when a frame is moved / resized / created / deleted
4331// and everything will be update / repainted accordingly
4332void KWDocument::frameChanged( KWFrame * frame )
4333{
4334 if(! m_framesChangedHandler) {
4335 m_framesChangedHandler = new FramesChangedHandler(this);
4336 TQTimer::singleShot( 0, this, TQ_SLOT( updateFramesChanged() ) );
4337 }
4338 m_framesChangedHandler->addFrame(frame);
4339}
4340
4341void KWDocument::framesChanged( const TQPtrList<KWFrame> & frames, KWView * view )
4342{
4343 Q_UNUSED( view ); // DF: seems my idea of excluding one view got thrown away
4344 TQPtrListIterator<KWFrame> it( frames );
4345 for ( ; it.current() ; ++it )
4346 frameChanged(it.current());
4347}
4348
4349void KWDocument::updateFramesChanged() { // slot called from frameChanged()
4350 if(!m_framesChangedHandler) return;
4351 m_framesChangedHandler->execute();
4352 delete m_framesChangedHandler;
4353 m_framesChangedHandler = 0;
4354}
4355
4356void KWDocument::framesChanged( const TQValueList<KWFrame*> &frames) {
4357 TQValueListConstIterator<KWFrame*> framesIterator = frames.begin();
4358 for(;framesIterator != frames.end(); ++framesIterator)
4359 frameChanged(*framesIterator);
4360}
4361
4362void KWDocument::setHeaderVisible( bool h )
4363{
4364 m_headerVisible = h;
4365 recalcFrames();
4366 updateAllFrames();
4367 layout();
4368 setModified(true);
4369 repaintAllViews( true );
4370}
4371
4372void KWDocument::setFooterVisible( bool f )
4373{
4374 m_footerVisible = f;
4375 recalcFrames();
4376 updateAllFrames();
4377 layout();
4378 setModified(true);
4379 repaintAllViews( true );
4380}
4381
4382bool KWDocument::hasEndNotes() const
4383{
4384 return m_bHasEndNotes;
4385}
4386
4387void KWDocument::updateHeaderButton()
4388{
4389 for( TQValueList<KWView *>::Iterator it = m_lstViews.begin(); it != m_lstViews.end(); ++it )
4390 {
4391 (*it)->updateHeaderFooterButton();
4392 (*it)->updateHeader();
4393 }
4394}
4395
4396void KWDocument::updateFooterButton()
4397{
4398 for( TQValueList<KWView *>::Iterator it = m_lstViews.begin(); it != m_lstViews.end(); ++it )
4399 {
4400 (*it)->updateHeaderFooterButton();
4401 (*it)->updateFooter();
4402 }
4403}
4404
4405void KWDocument::addTextImageRequest( KWTextImage *img )
4406{
4407 m_textImageRequests.append( img );
4408}
4409
4410void KWDocument::addPictureRequest( KWPictureFrameSet *fs )
4411{
4412 m_pictureRequests.append( fs );
4413}
4414
4415void KWDocument::addAnchorRequest( const TQString &framesetName, const KWAnchorPosition &anchorPos )
4416{
4417 m_anchorRequests.insert( framesetName, anchorPos );
4418}
4419
4420void KWDocument::addFootNoteRequest( const TQString &framesetName, KWFootNoteVariable* var )
4421{
4422 if ( var->noteType() == EndNote )
4423 m_bHasEndNotes = true;
4424 m_footnoteVarRequests.insert( framesetName, var );
4425}
4426
4427void KWDocument::refreshMenuCustomVariable()
4428{
4429 emit sig_refreshMenuCustomVariable();
4430}
4431
4432void KWDocument::recalcVariables( int type )
4433{
4434 const TQValueList<KoVariable *> modifiedVariables = m_varColl->recalcVariables(type);
4435 if ( m_bGeneratingPreview )
4436 return;
4437
4438 TQMap<KoTextDocument *, bool> modifiedTextDocuments;
4439 for ( TQValueList<KoVariable *>::const_iterator it = modifiedVariables.begin(), end = modifiedVariables.end() ; it != end ; ++it ) {
4440 KoTextDocument* textdoc = (*it)->textDocument();
4441 if ( modifiedTextDocuments.find( textdoc ) != modifiedTextDocuments.end() )
4442 {
4443 modifiedTextDocuments.insert( textdoc, true );
4444 KWTextFrameSet * textfs = static_cast<KWTextDocument *>(textdoc)->textFrameSet();
4445 slotRepaintChanged( textfs );
4446 }
4447 }
4448}
4449
4450int KWDocument::mailMergeRecord() const
4451{
4452 return slRecordNum;
4453}
4454
4455void KWDocument::setMailMergeRecord( int r )
4456{
4457 slRecordNum = r;
4458}
4459
4460void KWDocument::getPageLayout( KoPageLayout& layout, KoColumns& cl, KoKWHeaderFooter& hf )
4461{
4462 layout = m_pageLayout;
4463 cl = m_pageColumns;
4464 hf = m_pageHeaderFooter;
4465}
4466
4467void KWDocument::addFrameSet( KWFrameSet *f, bool finalize /*= true*/ )
4468{
4469 if(m_lstFrameSet.contains(f) > 0) {
4470 kdWarning(32001) << "Frameset " << f << " " << f->name() << " already in list!" << endl;
4471 return;
4472 }
4473 m_lstFrameSet.append(f);
4474
4476
4477 if ( finalize )
4478 f->finalize();
4479 setModified( true );
4480 emit sigFrameSetAdded(f);
4481}
4482
4483void KWDocument::removeFrameSet( KWFrameSet *f )
4484{
4485 emit sig_terminateEditing( f );
4486 m_lstFrameSet.take( m_lstFrameSet.find(f) );
4487 setModified( true );
4488 emit sigFrameSetRemoved(f);
4489}
4490
4491void KWDocument::addCommand( KCommand * cmd )
4492{
4493 Q_ASSERT( cmd );
4494 //kdDebug(32001) << "KWDocument::addCommand " << cmd->name() << endl;
4495 m_commandHistory->addCommand( cmd, false );
4496 setModified( true );
4497}
4498
4499void KWDocument::slotDocumentRestored()
4500{
4501 setModified( false );
4502}
4503
4504void KWDocument::slotCommandExecuted()
4505{
4506 setModified( true );
4507}
4508
4509#ifndef NDEBUG
4510void KWDocument::printStyleDebug()
4511{
4512 kdDebug() << "----------------------------------------"<<endl;
4513 m_styleColl->printDebug();
4514 kdDebug() << m_frameStyleColl->count() << " frame styles" << endl;
4515 kdDebug() << m_tableStyleColl->count() << " table-cell styles" << endl;
4516}
4517
4518void KWDocument::printDebug()
4519{
4520 kdDebug() << "----------------------------------------"<<endl;
4521 kdDebug() << " Debug info"<<endl;
4522 kdDebug() << "Document:" << this <<endl;
4523 kdDebug() << "Type of document: (0=WP, 1=DTP) " << processingType() <<endl;
4524 kdDebug() << "Header visible: " << isHeaderVisible() << endl;
4525 kdDebug() << "Footer visible: " << isFooterVisible() << endl;
4526 kdDebug() << "Units: " << unit() <<endl;
4527 kdDebug() << "# Framesets: " << frameSetCount() <<endl;
4528 TQPtrListIterator<KWFrameSet> fit = framesetsIterator();
4529 for ( unsigned int iFrameset = 0; fit.current() ; ++fit, iFrameset++ )
4530 {
4531 KWFrameSet * frameset = fit.current();
4532 kdDebug() << "Frameset " << iFrameset << ": '" <<
4533 frameset->name() << "' (" << frameset << ")" << (frameset->isDeleted()?" Deleted":"")<<endl;
4534 if ( frameset->isVisible())
4535 frameset->printDebug();
4536 else
4537 kdDebug() << " [hidden] #" << frameset->frameCount() << " frames" << endl;
4538 }
4539
4540 for ( uint pgNum = 0 ; pgNum < m_sectionTitles.size() ; ++pgNum ) {
4541 kdDebug() << "Page " << pgNum << " Section: '" << m_sectionTitles[ pgNum ] << "'"<< endl;
4542 }
4543 /*
4544 kdDebug() << "# Images: " << getImageCollection()->iterator().count() <<endl;
4545 TQDictIterator<KWImage> it( getImageCollection()->iterator() );
4546 while ( it.current() ) {
4547 kdDebug() << " + " << it.current()->getFilename() << ": "<<it.current()->refCount() <<endl;
4548 ++it;
4549 }
4550 */
4551
4552 kdDebug() << "PageManager holds "<< pageCount() << " pages in the range: " << startPage() <<
4553 "-" << lastPage() << endl;
4554 for (int pgnum = startPage() ; pgnum <= lastPage() ; pgnum++) {
4555 KWPage *page = pageManager()->page(pgnum);
4556 kdDebug() << "Page " << pgnum << " width=" << page->width() << " height=" << page->height() << endl;
4557 }
4558 kdDebug() << " The height of the doc (in pt) is: " << pageManager()->
4559 bottomOfPage(lastPage()) << endl;
4560}
4561#endif
4562
4563void KWDocument::layout()
4564{
4565 TQPtrListIterator<KWFrameSet> it = framesetsIterator();
4566 for (; it.current(); ++it )
4567 if ( it.current()->isVisible() )
4568 it.current()->layout();
4569}
4570
4571void KWDocument::invalidate(const KWFrameSet *skipThisFrameSet)
4572{
4573 TQPtrListIterator<KWFrameSet> it = framesetsIterator();
4574 for (; it.current(); ++it )
4575 if(it.current()!=skipThisFrameSet)
4576 it.current()->invalidate();
4577}
4578
4579KFormula::Document* KWDocument::formulaDocument( bool init )
4580{
4581 KFormula::Document* formulaDocument = m_formulaDocumentWrapper->document();
4582 if (!formulaDocument) {
4583 kdDebug() << k_funcinfo << endl;
4584 formulaDocument = new KFormula::Document;
4585 m_formulaDocumentWrapper->document( formulaDocument, init );
4586 if ( formulaDocument != 0 ) {
4587 // re-calculate dpiX and dpiY
4588 formulaDocument->setZoomAndResolution( m_zoom,
4589 tqRound(INCH_TO_POINT( m_resolutionX )),
4590 tqRound(INCH_TO_POINT( m_resolutionY )) );
4591 formulaDocument->newZoomAndResolution(false,false);
4592 }
4593 }
4594 return formulaDocument;
4595}
4596
4597
4598void KWDocument::slotRepaintChanged( KWFrameSet * frameset )
4599{
4600 // This has to be a loop instead of a signal, so that we can
4601 // send "true" for the last view (see KWFrameSet::drawContents)
4602 for( TQValueList<KWView *>::Iterator it = m_lstViews.begin(); it != m_lstViews.end(); ++it ) {
4603 (*it)->getGUI()->canvasWidget()->repaintChanged( frameset, it == m_lstViews.fromLast() );
4604 }
4605}
4606
4607void KWDocument::deleteTable( KWTableFrameSet *table )
4608{
4609 if ( !table )
4610 return;
4611 if ( table->isFloating() )
4612 {
4613 emit sig_terminateEditing( table ); // to unselect its cells, especially
4614 KWAnchor * anchor = table->findAnchor( 0 );
4615 addCommand( table->anchorFrameset()->deleteAnchoredFrame( anchor ) );
4616 }
4617 else
4618 {
4619 KWDeleteTableCommand *cmd = new KWDeleteTableCommand( i18n("Delete Table"), table );
4620 addCommand( cmd );
4621 cmd->execute();
4622 }
4623}
4624
4625void KWDocument::deleteFrame( KWFrame * frame )
4626{
4627 KWFrameSet * fs = frame->frameSet();
4628 kdDebug(32002) << "KWDocument::deleteFrame frame=" << frame << " fs=" << fs << endl;
4629 TQString cmdName;
4630 TypeStructDocItem docItem = (TypeStructDocItem) 0;
4631 switch (fs->type() ) {
4632 case FT_TEXT:
4633 cmdName=i18n("Delete Text Frame");
4634 docItem=TextFrames;
4635 break;
4636 case FT_FORMULA:
4637 cmdName=i18n("Delete Formula Frame");
4638 docItem=FormulaFrames;
4639 break;
4640 case FT_CLIPART:
4641 kdError(32001) << "FT_CLIPART used! (in KWDocument::deleteFrame)" << endl;
4642 break;
4643 case FT_PICTURE:
4644 cmdName=i18n("Delete Picture Frame");
4645 docItem=Pictures;
4646 break;
4647 case FT_PART:
4648 cmdName=i18n("Delete Object Frame");
4649 docItem=Embedded;
4650 break;
4651 case FT_TABLE:
4652 case FT_BASE:
4653 Q_ASSERT( 0 );
4654 break;
4655 }
4656 if ( fs->isFloating() )
4657 {
4658 KWAnchor * anchor = fs->findAnchor( 0 );
4659 addCommand( fs->anchorFrameset()->deleteAnchoredFrame( anchor ) );
4660 }
4661 else
4662 {
4663 KWDeleteFrameCommand *cmd = new KWDeleteFrameCommand( cmdName, frame );
4664 addCommand( cmd );
4665 cmd->execute();
4666 }
4667 emit docStructureChanged(docItem);
4668}
4669
4670void KWDocument::reorganizeGUI()
4671{
4672 for( TQValueList<KWView *>::Iterator it = m_lstViews.begin(); it != m_lstViews.end(); ++it )
4673 (*it)->getGUI()->reorganize();
4674}
4675
4676void KWDocument::slotDocumentInfoModifed()
4677{
4678 if (!variableCollection()->variableSetting()->displayFieldCode())
4679 recalcVariables( VT_FIELD );
4680}
4681
4682void KWDocument::refreshDocStructure(int type)
4683{
4684 emit docStructureChanged(type);
4685}
4686
4687int KWDocument::typeItemDocStructure(FrameSetType type)
4688{
4689 int typeItem;
4690 switch(type)
4691 {
4692 case FT_TEXT:
4693 typeItem=(int)TextFrames;
4694 break;
4695 case FT_PICTURE:
4696 typeItem=(int)Pictures;
4697 break;
4698 case FT_PART:
4699 typeItem=(int)Embedded;
4700 break;
4701 case FT_FORMULA:
4702 typeItem=(int)FormulaFrames;
4703 break;
4704 case FT_TABLE:
4705 typeItem=(int)Tables;
4706 break;
4707 default:
4708 typeItem=(int)TextFrames;
4709 }
4710 return typeItem;
4711}
4712
4713void KWDocument::refreshDocStructure(FrameSetType type)
4714{
4715 emit docStructureChanged(typeItemDocStructure(type));
4716}
4717
4718TQBrush KWDocument::resolveBgBrush( const TQBrush & brush, TQPainter * painter )
4719{
4720 if ( brush.color().isValid() )
4721 return brush;
4722 TQBrush ret( brush );
4723 ret.setColor( defaultBgColor( painter ) );
4724 return ret;
4725}
4726
4727TQColor KWDocument::resolveBgColor( const TQColor & col, TQPainter * painter )
4728{
4729 if (col.isValid())
4730 return col;
4731
4732 return defaultBgColor( painter );
4733}
4734
4735TQColor KWDocument::defaultBgColor( TQPainter * painter )
4736{
4737 if ( painter && painter->device()->devType() == TQInternal::Printer )
4738 return TQt::white;
4739 return TQApplication::palette().color( TQPalette::Active, TQColorGroup::Base );
4740}
4741
4742
4743void KWDocument::setTocPresent(bool hasToc)
4744{
4745 m_hasTOC=hasToc;
4746 for( TQValueList<KWView *>::Iterator it = m_lstViews.begin(); it != m_lstViews.end(); ++it )
4747 (*it)->updateTocActionText(hasToc);
4748}
4749
4750void KWDocument::refreshMenuExpression()
4751{
4752 for( TQValueList<KWView *>::Iterator it = m_lstViews.begin(); it != m_lstViews.end(); ++it )
4753 (*it)->refreshMenuExpression();
4754}
4755
4756void KWDocument::updateZoomRuler()
4757{
4758 for( TQValueList<KWView *>::Iterator it = m_lstViews.begin(); it != m_lstViews.end(); ++it ) {
4759 (*it)->getGUI()->getHorzRuler()->setZoom( zoomedResolutionX() );
4760 (*it)->getGUI()->getVertRuler()->setZoom( zoomedResolutionY() );
4761 (*it)->slotUpdateRuler();
4762 }
4763}
4764
4765void KWDocument::updateRulerFrameStartEnd()
4766{
4767 for( TQValueList<KWView *>::Iterator it = m_lstViews.begin(); it != m_lstViews.end(); ++it )
4768 (*it)->slotUpdateRuler();
4769}
4770
4771int KWDocument::undoRedoLimit() const
4772{
4773 return m_commandHistory->undoLimit();
4774}
4775
4776void KWDocument::setUndoRedoLimit(int val)
4777{
4778 m_commandHistory->setUndoLimit(val);
4779 m_commandHistory->setRedoLimit(val);
4780}
4781
4782void KWDocument::setGridX(double gridx) {
4783 m_gridX = gridx;
4784 for( TQValueList<KWView *>::Iterator it = m_lstViews.begin(); it != m_lstViews.end(); ++it )
4785 (*it)->getGUI()->getHorzRuler()->setGridSize(gridx);
4786}
4787
4788TQValueList<KoTextObject *> KWDocument::visibleTextObjects(KWViewMode *viewmode) const
4789{
4790 TQValueList<KoTextObject *> lst;
4791 TQPtrList<KWTextFrameSet> textFramesets = allTextFramesets( true );
4792
4793 KWTextFrameSet *frm;
4794 for ( frm=textFramesets.first(); frm != 0; frm=textFramesets.next() ) {
4795 if ( frm && frm->isVisible(viewmode) && !frm->textObject()->protectContent() )
4796 {
4797 lst.append( frm->textObject() );
4798 }
4799 }
4800
4801 return lst;
4802}
4803
4804void KWDocument::refreshGUIButton()
4805{
4806 for( TQValueList<KWView *>::Iterator it = m_lstViews.begin(); it != m_lstViews.end(); ++it )
4807 (*it)->initGUIButton();
4808}
4809
4810void KWDocument::enableBackgroundSpellCheck( bool b )
4811{
4812 m_bgSpellCheck->setEnabled(b);
4813 for( TQValueList<KWView *>::Iterator it = m_lstViews.begin(); it != m_lstViews.end(); ++it )
4814 (*it)->updateBgSpellCheckingState();
4815}
4816
4817bool KWDocument::backgroundSpellCheckEnabled() const
4818{
4819 return m_bgSpellCheck->enabled();
4820}
4821
4822void KWDocument::reactivateBgSpellChecking()
4823{
4824 TQPtrList<KWTextFrameSet> textFramesets = allTextFramesets( true );
4825
4826 KWTextFrameSet *frm;
4827 for ( frm=textFramesets.first(); frm != 0; frm=textFramesets.next() ){
4828 frm->textObject()->setNeedSpellCheck(true);
4829 }
4830 repaintAllViews();
4831 startBackgroundSpellCheck();
4832}
4833
4834void KWDocument::slotChapterParagraphFormatted( KoTextParag* /*parag*/ )
4835{
4836 // Attempt at invalidating from the parag's page only
4837 // But that's not good enough - if a header gets moved down,
4838 // we also need to invalidate the previous page, from where the paragraph disappeared.
4839 /*
4840 KoPoint p;
4841 KWFrame* frame = internalToDocument( parag->rect().topLeft(), p );
4842 Q_ASSERT( frame );
4843 if ( frame )
4844 // Remove any information from this page and further pages.
4845 m_sectionTitles.resize( frame->pageNumber() );
4846 */
4847
4848 m_sectionTitles.resize( 0 ); // clear up the entire cache
4849
4850 // Don't store info from parag into m_sectionTitles here.
4851 // It breaks when having two headings in the same page
4852 // (or if it keeps existing info then it can't update properly)
4853}
4854
4855TQString KWDocument::checkSectionTitleInParag( KoTextParag* parag, KWTextFrameSet* frameset, int pageNum ) const
4856{
4857 if ( parag->counter() && parag->counter()->numbering() == KoParagCounter::NUM_CHAPTER
4858 && parag->counter()->depth() == 0 )
4859 {
4860 TQString txt = parag->string()->toString();
4861 txt = txt.left( txt.length() - 1 ); // remove trailing space
4862#ifndef NDEBUG // not needed, just checking
4863 KoPoint p;
4864 KWFrame* frame = frameset->internalToDocument( parag->rect().topLeft(), p );
4865 Q_ASSERT( frame );
4866 if ( frame ) {
4867 int pgNum = frame->pageNumber();
4868 if( pgNum != pageNum )
4869 kdWarning() << "sectionTitle: was looking for pageNum " << pageNum << ", got frame " << frame << " page " << pgNum << endl;
4870 }
4871 kdDebug(32001) << "KWDocument::sectionTitle for " << pageNum << ":" << txt << endl;
4872#endif
4873 // Ensure array is big enough
4874 if ( pageNum > (int)m_sectionTitles.size()-1 )
4875 const_cast<KWDocument*>(this)->m_sectionTitles.resize( pageNum + 1 );
4876 const_cast<KWDocument*>(this)->m_sectionTitles[ pageNum ] = txt;
4877 return txt;
4878 }
4879 return TQString();
4880}
4881
4882TQString KWDocument::sectionTitle( int pageNum ) const
4883{
4884 //kdDebug(32001) << "KWDocument::sectionTitle(pageNum=" << pageNum << ") m_sectionTitles.size()=" << m_sectionTitles.size() << endl;
4885 // First look in the cache. If info is present, it's uptodate (see slotChapterParagraphFormatted)
4886 if ( (int)m_sectionTitles.size() > pageNum )
4887 {
4888 // Look whether this page has a section title, and if not, go back pages, one by one
4889 for ( int i = pageNum; i >= 0 ; --i )
4890 {
4891 const TQString& s = m_sectionTitles[i];
4892 if ( !s.isEmpty() )
4893 {
4894 // Update cache, to make this faster next time
4895 if ( pageNum > (int)m_sectionTitles.size()-1 )
4896 const_cast<KWDocument*>(this)->m_sectionTitles.resize( pageNum + 1 );
4897 const_cast<KWDocument*>(this)->m_sectionTitles[ pageNum ] = s;
4898 return s;
4899 }
4900 }
4901 }
4902
4903 // If not in the cache, determine from the paragraphs in the page.
4904
4905 if ( m_lstFrameSet.isEmpty() )
4906 return TQString();
4907 // We use the "main" frameset to determine section titles.
4908 KWTextFrameSet *frameset = dynamic_cast<KWTextFrameSet *>( m_lstFrameSet.getFirst() );
4909 if ( !frameset )
4910 return TQString();
4911
4912 int topLUpix, bottomLUpix;
4913 if ( !frameset->minMaxInternalOnPage( pageNum, topLUpix, bottomLUpix ) )
4914 return TQString();
4915
4916 KoTextParag* parag = frameset->textDocument()->firstParag();
4917 //kdDebug(32001) << "KWDocument::sectionTitle " << pageNum
4918 // << " topLUpix=" << topLUpix << " bottomLUpix=" << bottomLUpix << endl;
4919
4920 KoTextParag* lastParagOfPageAbove = parag;
4921 for ( ; parag ; parag = parag->next() )
4922 {
4923 if ( parag->rect().bottom() < topLUpix ) // too early
4924 {
4925 lastParagOfPageAbove = parag;
4926 continue;
4927 }
4928 if ( parag->rect().top() > bottomLUpix ) // done
4929 break;
4930 TQString txt = checkSectionTitleInParag( parag, frameset, pageNum );
4931 if ( !txt.isEmpty() )
4932 return txt;
4933 }
4934
4935 // No heading found in page.
4936 // Go back up until the first section parag
4937 parag = lastParagOfPageAbove;
4938 for ( ; parag ; parag = parag->prev() )
4939 {
4940 TQString txt = checkSectionTitleInParag( parag, frameset, pageNum );
4941 if ( !txt.isEmpty() )
4942 return txt;
4943 }
4944
4945 // First page, no heading found
4946 return TQString();
4947}
4948
4949
4950void KWDocument::setSpellCheckIgnoreList( const TQStringList& lst )
4951{
4952 m_spellCheckIgnoreList = lst;
4953 m_bgSpellCheck->settings()->setCurrentIgnoreList( m_spellCheckIgnoreList + m_spellCheckPersonalDict );
4954 setModified( true );
4955}
4956
4957void KWDocument::addSpellCheckIgnoreWord( const TQString & word )
4958{
4959 // ### missing: undo/redo support
4960 if( m_spellCheckIgnoreList.findIndex( word ) == -1 )
4961 m_spellCheckIgnoreList.append( word );
4962 setSpellCheckIgnoreList( m_spellCheckIgnoreList );
4963 if ( backgroundSpellCheckEnabled() )
4964 // Re-check everything to make this word normal again
4965 reactivateBgSpellChecking();
4966}
4967
4968int KWDocument::maxZOrder( int pageNum) const
4969{
4970 bool first = true;
4971 int maxZOrder = 0; //this value is only used if there's no frame on the page
4972 TQPtrList<KWFrame> frames = framesInPage( pageNum );
4973 TQPtrListIterator<KWFrame> frameIt( frames );
4974 for ( ; frameIt.current(); ++frameIt ) {
4975 if ( first || frameIt.current()->zOrder() > maxZOrder ) {
4976 maxZOrder = frameIt.current()->zOrder();
4977 first = false;
4978 }
4979 }
4980 return maxZOrder;
4981}
4982
4983TQPtrList<KWTextFrameSet> KWDocument::allTextFramesets(bool onlyReadWrite) const
4984{
4985 TQPtrList<KWTextFrameSet> textFramesets;
4986 TQPtrListIterator<KWFrameSet> fit = framesetsIterator();
4987 for ( ; fit.current() ; ++fit ) {
4988 if(fit.current()->isDeleted()) continue;
4989 fit.current()->addTextFrameSets(textFramesets, onlyReadWrite);
4990 }
4991 return textFramesets;
4992}
4993
4994TQValueList<KoTextDocument *> KWDocument::allTextDocuments() const
4995{
4996 TQValueList<KoTextDocument *> lst;
4997 const TQPtrList<KWTextFrameSet> textFramesets = allTextFramesets(false);
4998 TQPtrListIterator<KWTextFrameSet> fit( textFramesets );
4999 for ( ; fit.current() ; ++fit ) {
5000 lst.append( fit.current()->textObject()->textDocument() );
5001 }
5002 return lst;
5003}
5004
5005int KWDocument::numberOfTextFrameSet( KWFrameSet* fs, bool onlyReadWrite )
5006{
5007 TQPtrList<KWTextFrameSet> textFramesets = allTextFramesets( onlyReadWrite );
5008 return textFramesets.findRef( static_cast<KWTextFrameSet*>(fs) );
5009}
5010
5011KWFrameSet * KWDocument::textFrameSetFromIndex( unsigned int num, bool onlyReadWrite )
5012{
5013 return allTextFramesets( onlyReadWrite ).at( num );
5014}
5015
5016void KWDocument::updateTextFrameSetEdit()
5017{
5018 for( TQValueList<KWView *>::Iterator it = m_lstViews.begin(); it != m_lstViews.end(); ++it )
5019 (*it)->slotFrameSetEditChanged();
5020
5021}
5022
5023void KWDocument::displayFootNoteFieldCode()
5024{
5025 TQPtrListIterator<KoVariable> it( m_varColl->getVariables() );
5026 for ( ; it.current() ; ++it )
5027 {
5028 if ( it.current()->type() == VT_FOOTNOTE )
5029 {
5030 static_cast<KWFootNoteVariable *>(it.current())->resize();
5031 static_cast<KWFootNoteVariable *>(it.current())->frameSet()->setCounterText( static_cast<KWFootNoteVariable *>(it.current())->text() );
5032
5033 KoTextParag * parag = it.current()->paragraph();
5034 if ( parag )
5035 {
5036 parag->invalidate( 0 );
5037 parag->setChanged( true );
5038 }
5039 }
5040 }
5041}
5042
5043void KWDocument::changeFootNoteConfig()
5044{
5045 TQMap<KoTextDocument *, bool> modifiedTextDocuments;
5046 TQPtrListIterator<KoVariable> it( m_varColl->getVariables() );
5047 for ( ; it.current() ; ++it )
5048 {
5049 if ( it.current()->type() == VT_FOOTNOTE )
5050 {
5051 KWFootNoteVariable* footNoteVar = static_cast<KWFootNoteVariable *>(it.current());
5052 footNoteVar->formatedNote();
5053 if(footNoteVar->frameSet()->isDeleted())
5054 continue;
5055 footNoteVar->resize();
5056 footNoteVar->frameSet()->setCounterText( footNoteVar->text() );
5057
5058 KoTextParag * parag = footNoteVar->paragraph();
5059 if ( parag )
5060 {
5061 parag->invalidate( 0 );
5062 parag->setChanged( true );
5063 }
5064 KoTextDocument* textdoc = parag->textDocument();
5065 if ( modifiedTextDocuments.find( textdoc ) != modifiedTextDocuments.end() )
5066 modifiedTextDocuments.insert( textdoc, true );
5067 }
5068 }
5069 for( TQMap<KoTextDocument *,bool>::const_iterator it = modifiedTextDocuments.begin();
5070 it != modifiedTextDocuments.end(); ++it ) {
5071 KoTextDocument* textdoc = it.key();
5072 KWTextFrameSet * textfs = static_cast<KWTextDocument *>(textdoc)->textFrameSet();
5073 slotRepaintChanged( textfs );
5074 }
5075}
5076
5077
5078void KWDocument::setTabStopValue ( double tabStop )
5079{
5080 m_tabStop = tabStop;
5081 TQPtrList<KWTextFrameSet> textFramesets = allTextFramesets( true );
5082
5083 KWTextFrameSet *frm;
5084 for ( frm=textFramesets.first(); frm != 0; frm=textFramesets.next() ){
5085 frm->textDocument()->setTabStops( ptToLayoutUnitPixX( tabStop ));
5086 frm->layout();
5087 }
5088 repaintAllViews();
5089}
5090
5091void KWDocument::setGlobalHyphenation( bool hyphen )
5092{
5093 m_bGlobalHyphenation = hyphen;
5094 // This is only used as a default setting for the default format in new documents;
5095 // In existing documents the hyphenation comes from the existing formats.
5096}
5097
5098void KWDocument::setViewFrameBorders( bool b )
5099{
5100 m_viewFrameBorders = b;
5101 m_layoutViewMode->setDrawFrameBorders( b );
5102 for( TQValueList<KWView *>::Iterator it = m_lstViews.begin(); it != m_lstViews.end(); ++it )
5103 (*it)->getGUI()->canvasWidget()->viewMode()->setDrawFrameBorders( b );
5104}
5105
5106void KWDocument::switchViewMode( const TQString& newViewModeType )
5107{
5108 // Don't compare m_viewModeType and newViewMode here, it would break
5109 // changing the number of pages per row for the preview mode, in kwconfig.
5110 m_viewModeType = newViewModeType;
5111 delete m_layoutViewMode;
5112 m_layoutViewMode = KWViewMode::create( m_viewModeType, this, 0 /*no canvas */ );
5113
5114 //necessary to switchmode view in all canvas in first.
5115 //otherwise with more than one view kword crashes !
5116 for( TQValueList<KWView *>::Iterator it = m_lstViews.begin(); it != m_lstViews.end(); ++it )
5117 (*it)->getGUI()->canvasWidget()->switchViewMode( m_viewModeType );
5118
5119 for( TQValueList<KWView *>::Iterator it = m_lstViews.begin(); it != m_lstViews.end(); ++it )
5120 (*it)->switchModeView();
5121 emit newContentsSize();
5122
5123 // Since the text layout depends on the view mode, we need to redo it
5124 // But after telling the canvas about the new viewmode, otherwise stuff like
5125 // slotNewContentsSize will crash.
5126 updateAllFrames();
5127 layout();
5128
5129 repaintAllViews( true );
5130 for( TQValueList<KWView *>::Iterator it = m_lstViews.begin(); it != m_lstViews.end(); ++it )
5131 (*it)->getGUI()->canvasWidget()->ensureCursorVisible();
5132}
5133
5134void KWDocument::changeBgSpellCheckingState( bool b )
5135{
5136 enableBackgroundSpellCheck( b );
5137 reactivateBgSpellChecking();
5138 TDEConfig *config = KWFactory::instance()->config();
5139 config->setGroup("KSpell kword" );
5140 config->writeEntry( "SpellCheck", (int)b );
5141}
5142
5143TQString KWDocument::initialFrameSet() const
5144{
5145 return m_initialEditing ? m_initialEditing->m_initialFrameSet : TQString();
5146}
5147
5148int KWDocument::initialCursorParag() const
5149{
5150 return m_initialEditing ? m_initialEditing->m_initialCursorParag : 0;
5151}
5152
5153int KWDocument::initialCursorIndex() const
5154{
5155 return m_initialEditing ? m_initialEditing->m_initialCursorIndex : 0;
5156}
5157
5158void KWDocument::deleteInitialEditingInfo()
5159{
5160 delete m_initialEditing;
5161 m_initialEditing = 0L;
5162}
5163
5164bool KWDocument::cursorInProtectedArea()const
5165{
5166 return m_cursorInProtectectedArea;
5167}
5168
5169void KWDocument::setCursorInProtectedArea( bool b )
5170{
5171 m_cursorInProtectectedArea=b;
5172 testAndCloseAllFrameSetProtectedContent();
5173}
5174
5175
5176void KWDocument::testAndCloseAllFrameSetProtectedContent()
5177{
5178 if ( !m_cursorInProtectectedArea )
5179 {
5180 for( TQValueList<KWView *>::Iterator it = m_lstViews.begin(); it != m_lstViews.end(); ++it )
5181 (*it)->testAndCloseAllFrameSetProtectedContent();
5182 }
5183}
5184
5185void KWDocument::updateRulerInProtectContentMode()
5186{
5187 for( TQValueList<KWView *>::const_iterator it = m_lstViews.begin(); it != m_lstViews.end(); ++it )
5188 (*it)->updateRulerInProtectContentMode();
5189}
5190
5191
5192void KWDocument::insertBookmark( const TQString &name, KoTextParag *startparag, KoTextParag *endparag, int start, int end )
5193{
5194 m_bookmarkList->append( KoTextBookmark( name, startparag, endparag, start, end ) );
5195}
5196
5197void KWDocument::deleteBookmark( const TQString &name )
5198{
5199 if ( m_bookmarkList->removeByName( name ) )
5200 setModified(true);
5201}
5202
5203void KWDocument::renameBookmark( const TQString &oldName, const TQString &newName )
5204{
5205 if ( oldName == newName )
5206 return;
5207
5208 KoTextBookmarkList::iterator it = m_bookmarkList->findByName( oldName );
5209 if ( it != m_bookmarkList->end() )
5210 {
5211 (*it).setBookmarkName( newName );
5212 setModified(true);
5213 }
5214}
5215
5216const KoTextBookmark * KWDocument::bookmarkByName( const TQString & name ) const
5217{
5218 KoTextBookmarkList::const_iterator it = m_bookmarkList->findByName( name );
5219 if ( it != m_bookmarkList->end() )
5220 return &(*it);
5221 return 0;
5222}
5223
5224TQStringList KWDocument::listOfBookmarkName( KWViewMode * viewMode ) const
5225{
5226 TQStringList list;
5227 KoTextBookmarkList::const_iterator it = m_bookmarkList->begin();
5228 const KoTextBookmarkList::const_iterator end = m_bookmarkList->end();
5229 for ( ; it != end ; ++it )
5230 {
5231 const KoTextBookmark& book = *it;
5232 KWFrameSet* fs = static_cast<KWTextDocument *>(book.textDocument())->textFrameSet();
5233 if ( fs->isVisible( viewMode ) && !fs->isDeleted() )
5234 list.append( book.bookmarkName() );
5235 }
5236 return list;
5237}
5238
5239void KWDocument::paragraphModified(KoTextParag* /*parag*/, int /*KoTextParag::ParagModifyType*/ /*type*/, int /*start*/, int /*length*/)
5240{
5241 //kdDebug()<<" parag :"<<parag<<" start :"<<start<<" length :"<<length<<endl;
5242 emit docStructureChanged( Tables | TextFrames );
5243}
5244
5245
5246void KWDocument::paragraphDeleted( KoTextParag *parag, KWFrameSet *frm )
5247{
5248 KWTextFrameSet* textfs = dynamic_cast<KWTextFrameSet *>( frm );
5249 if ( textfs )
5250 {
5251 // For speed KoTextBookmarkList should probably be a per-paragraph map.
5252 // The problem is that a bookmark is associated with TWO paragraphs...
5253
5254 KoTextBookmarkList::iterator it = m_bookmarkList->begin();
5255 const KoTextBookmarkList::iterator end = m_bookmarkList->end();
5256 for ( ; it != end ; ++it )
5257 {
5258 KoTextBookmark& book = *it;
5259
5260 // Adjust bookmark to point to a valid paragraph, below or above the deleted one.
5261 // The old implementation turned the bookmark into a useless one. OOo simply deletes the bookmark...
5262 if ( book.startParag() == parag )
5263 book.setStartParag( parag->next() ? parag->next() : parag->prev() );
5264 if ( book.endParag() == parag )
5265 book.setEndParag( parag->next() ? parag->next() : parag->prev() );
5266 }
5267 }
5268}
5269
5270void KWDocument::initBookmarkList()
5271{
5272 Q_ASSERT( m_loadingInfo );
5273 if ( !m_loadingInfo )
5274 return;
5275 KWLoadingInfo::BookMarkList::Iterator it = m_loadingInfo->bookMarkList.begin();
5276 KWLoadingInfo::BookMarkList::Iterator end = m_loadingInfo->bookMarkList.end();
5277 for( ; it != end; ++it )
5278 {
5279 KWFrameSet * fs = 0L;
5280 TQString fsName = (*it).frameSetName;
5281 if ( !fsName.isEmpty() )
5282 fs = frameSetByName( fsName );
5283 if ( fs )
5284 {
5285 KWTextFrameSet *frm = dynamic_cast<KWTextFrameSet *>(fs);
5286 if ( frm )
5287 {
5288 KoTextDocument* textdoc = frm->textDocument();
5289 KoTextParag* startparag = textdoc->paragAt( (*it).paragStartIndex );
5290 KoTextParag* endparag = textdoc->paragAt( (*it).paragEndIndex );
5291 if ( startparag && endparag )
5292 {
5293 m_bookmarkList->append( KoTextBookmark( (*it).bookname,
5294 startparag, endparag,
5295 (*it).cursorStartIndex, (*it).cursorEndIndex ) );
5296 }
5297 }
5298 }
5299 }
5300}
5301
5302TQPixmap* KWDocument::doubleBufferPixmap( const TQSize& s )
5303{
5304 if ( !m_bufPixmap ) {
5305 int w = TQABS( s.width() );
5306 int h = TQABS( s.height() );
5307 m_bufPixmap = new TQPixmap( w, h );
5308 } else {
5309 if ( m_bufPixmap->width() < s.width() ||
5310 m_bufPixmap->height() < s.height() ) {
5311 m_bufPixmap->resize( TQMAX( s.width(), m_bufPixmap->width() ),
5312 TQMAX( s.height(), m_bufPixmap->height() ) );
5313 }
5314 }
5315
5316 return m_bufPixmap;
5317}
5318
5319void KWDocument::maybeDeleteDoubleBufferPixmap()
5320{
5321 if ( m_bufPixmap && m_bufPixmap->height() * m_bufPixmap->width() > 400*400 )
5322 {
5323 delete m_bufPixmap;
5324 m_bufPixmap = 0L;
5325 }
5326}
5327
5328void KWDocument::setPersonalExpressionPath( const TQStringList & lst)
5329{
5330 m_personalExpressionPath = lst;
5331 refreshMenuExpression();
5332}
5333
5334void KWDocument::updateDirectCursorButton()
5335{
5336 for( TQValueList<KWView *>::Iterator it = m_lstViews.begin(); it != m_lstViews.end(); ++it )
5337 (*it)->updateDirectCursorButton();
5338}
5339
5340void KWDocument::setInsertDirectCursor(bool b)
5341{
5342 m_bInsertDirectCursor=b;
5343 TDEConfig *config = KWFactory::instance()->config();
5344 config->setGroup( "Interface" );
5345 config->writeEntry( "InsertDirectCursor", b );
5346 updateDirectCursorButton();
5347}
5348
5349void KWDocument::saveDialogShown()
5350{
5351 if ( !textFrameSet(0) )
5352 return;
5353 // Grab first 50 chars from the main frameset's document
5354 // ### This is a somewhat slow method, if the document is huge - better iterate
5355 // over the first few parags until 50 chars have been collected.
5356 TQString first_row = textFrameSet(0)->textDocument()->plainText().left(50);
5357 bool truncate = false;
5358 TQChar ch;
5359 for (int i=0; i < (int)first_row.length(); i++)
5360 {
5361 ch = first_row.at(i);
5362 if (!truncate)
5363 if (ch.isPunct() || ch.isSpace() || ch == '.' )
5364 {
5365 first_row.remove(i,1);
5366 --i;
5367 }
5368 else
5369 truncate = true;
5370 else if ( truncate && (ch.isPunct() || ch == '.' || ch == '\n' ) )
5371 {
5372 first_row.truncate(i);
5373 break;
5374 }
5375 }
5376 first_row = first_row.stripWhiteSpace();
5377 kdDebug() << "Suggested filename:" << first_row << endl;
5378 setURL(first_row);
5379}
5380
5381void KWDocument::addWordToDictionary( const TQString& word )
5382{
5383 if ( m_bgSpellCheck )
5384 {
5385 if( m_spellCheckPersonalDict.findIndex( word ) == -1 )
5386 m_spellCheckPersonalDict.append( word );
5387 m_bgSpellCheck->settings()->setCurrentIgnoreList( m_spellCheckIgnoreList + m_spellCheckPersonalDict );
5388 if ( backgroundSpellCheckEnabled() )
5389 // Re-check everything to make this word normal again
5390 reactivateBgSpellChecking();
5391 }
5392}
5393
5394void KWDocument::setEmpty()
5395{
5396 KoDocument::setEmpty();
5397 // Whether loaded from template or from empty doc: this is a new one -> set creation date
5398 m_varColl->variableSetting()->setCreationDate(TQDateTime::currentDateTime());
5399 recalcVariables( VT_DATE ); // , VST_CREATION_DATE ...
5400 // If we then load a document, it will override that date.
5401}
5402
5403void KWDocument::updateGridButton()
5404{
5405 TQPtrListIterator<KoView> it( views() );
5406 for (; it.current(); ++it )
5407 ((KWView*)it.current())->updateGridButton();
5408
5409}
5410
5411unsigned int KWDocument::paperHeight(int pageNum) const {
5412 return static_cast<unsigned int>(zoomItY( pageManager()->pageLayout(pageNum).ptHeight ));
5413}
5414
5415unsigned int KWDocument::paperWidth(int pageNum) const {
5416 return static_cast<unsigned int>(zoomItX( pageManager()->pageLayout(pageNum).ptWidth ));
5417}
5418
5419unsigned int KWDocument::pageTop( int pgNum ) const {
5420 return zoomItY( pageManager()->topOfPage( pgNum ) );
5421}
5422
5423int KWDocument::pageCount() const {
5424 return pageManager()->pageCount();
5425}
5426
5427int KWDocument::startPage() const {
5428 return pageManager()->startPage();
5429}
5430int KWDocument::lastPage() const {
5431 return pageManager()->lastPageNumber();
5432}
5433
5434TQWidget* KWDocument::createCustomDocumentWidget(TQWidget *parent) {
5435 KoColumns columns;
5436 columns.columns = 1;
5437 columns.ptColumnSpacing = m_defaultColumnSpacing;
5438 return new KWStartupWidget(parent, this, columns);
5439}
5440
5441KWDocument::FramesChangedHandler::FramesChangedHandler(KWDocument *parent) {
5442 m_parent = parent;
5443 m_needLayout = false;
5444}
5445
5446void KWDocument::FramesChangedHandler::addFrame(KWFrame *frame) {
5447 if(frame == 0) return;
5448 if(m_frameSets.contains(frame->frameSet())) return;
5449 m_frameSets.append(frame->frameSet());
5450 if( frame->runAround() != KWFrame::RA_NO )
5451 m_needLayout = true;
5452}
5453
5454void KWDocument::FramesChangedHandler::addFrameSet(KWFrameSet *fs) {
5455 if(m_frameSets.contains(fs)) return;
5456 m_frameSets.append(fs);
5457 m_needLayout = true;
5458}
5459
5460void KWDocument::FramesChangedHandler::execute() {
5461 if(m_frameSets.count() == 0)
5462 m_parent->updateAllFrames();
5463 else {
5464 TQValueListIterator<KWFrameSet*> iter = m_frameSets.begin();
5465 for(;iter != m_frameSets.end(); ++iter) {
5466 KWFrameSet *fs = *iter;
5467 fs->updateFrames();
5468 if(!m_needLayout)
5469 fs->layout();
5470 }
5471
5473 }
5474
5475 // If frame with text flowing around it -> re-layout all frames
5476 if ( m_needLayout)
5477 m_parent->layout();
5478 //m_parent->repaintAllViewsExcept( 0 );
5479 m_parent->repaintAllViews();
5480 m_parent->updateRulerFrameStartEnd();
5481}
5482
5483#include "KWDocument.moc"
The variable showing the footnote number in superscript, in the text.
Definition KWVariable.h:106
KWFootNoteFrameSet * frameSet() const
The frameset that contains the text for this footnote.
Definition KWVariable.h:126
static void recalcAllFrames(KWDocument *doc)
Update the z-ordering for all frames of the whole document.
static void recalcFrames(KWDocument *doc, int pageFrom, int pageTo)
Update the z-ordering for all frames in the page section of the whole document.
static void createFrameList(KWFrame *f, KWDocument *doc)
Factory method to create and attach a new instance of a framelist.
Class: KWFrameSet Base type, a frameset holds content as well as frames to show that content.
Definition KWFrameSet.h:62
KWAnchor * findAnchor(int frameNum)
Return the anchor object for this frame number.
virtual void setVisible(bool v)
set the visibility of the frameset.
virtual void layout()
relayout text in frames, so that it flows correctly around other frames
Definition KWFrameSet.h:314
virtual void deleteFrame(unsigned int num, bool remove=true, bool recalc=true)
Delete a frame from the set of frames this frameSet has.
virtual FrameSetType type() const
The type of frameset.
Definition KWFrameSet.h:76
Info
The different types of textFramesets (that TEXT is important here!) FI_BODY = normal text frames.
Definition KWFrameSet.h:91
const TQPtrList< KWFrame > & frameIterator() const
Iterator over the child frames.
Definition KWFrameSet.h:159
virtual void finalize()
Called once the frameset has been completely loaded or constructed.
virtual void drawContents(TQPainter *painter, const TQRect &crect, const TQColorGroup &cg, bool onlyChanged, bool resetChanged, KWFrameSetEdit *edit, KWViewMode *viewMode, KWFrameViewManager *frameViewManager)
Paint this frameset.
void setAnchored(KWTextFrameSet *textfs, KoTextParag *parag, int index, bool placeHolderExists=false, bool repaint=true)
Make this frameset anchored, with the anchor at paragId,index in the text frameset textfs.
virtual void createEmptyRegion(const TQRect &crect, TQRegion &emptyRegion, KWViewMode *viewMode)
Let the caller know which parts of emptyRegion we do not claim, and thus the caller is free to paint ...
bool isDeleted() const
True if the frameset was deleted (but not destroyed, since it's in the undo/redo).
Definition KWFrameSet.h:166
unsigned int frameCount() const
Get number of child frames.
Definition KWFrameSet.h:163
bool isFloating() const
Return true if this frameset is floating (inline), false if it's fixed.
Definition KWFrameSet.h:372
virtual void updateFrames(int flags=0xff)
Called when our frames change, or when another frameset's frames change.
virtual void setZOrder()
set z-order for all frames
virtual void fromXML(TQDomElement &framesetElem, bool loadFrames=true, bool=true)
load from XML - when pasting from clipboard
Definition KWFrameSet.h:332
KWTextFrameSet * anchorFrameset() const
Return the frameset in which our anchor is - assuming isFloating().
Definition KWFrameSet.h:374
KWFrame * frame(unsigned int _num) const
get a frame by number
TQString name() const
get/set frameset name. For tables in particular, this must be unique
Definition KWFrameSet.h:428
Info frameSetInfo() const
Returns the type of TextFrameSet this is.
Definition KWFrameSet.h:95
virtual void saveOasis(KoXmlWriter &writer, KoSavingContext &context, bool saveFrames) const =0
Save to OASIS format.
void setFrameSetInfo(Info fi)
Set the type of TextFrameSet this is.
Definition KWFrameSet.h:97
bool isVisible(KWViewMode *viewMode=0L) const
Returns true if the frameset is visible.
Collection of frame styles.
The user-visible style for frames (borders and background).
void saveFrameStyle(TQDomElement &parentElem)
save (old xml format)
void setSelected(bool selected, MouseMeaning selectPolicy=MEANING_MOUSE_SELECT)
Set the selected state of this frameView.
This class represents a single frame.
Definition KWFrame.h:68
double minimumFrameHeight(void) const
Definition KWFrame.h:284
KWFrameSet * frameSet() const
Data stucture methods.
Definition KWFrame.h:143
FrameBehavior
what should happen when the frame is full
Definition KWFrame.h:116
void setZOrder(int z)
The z-order of the frame, relative to the other frames on the same page.
Definition KWFrame.h:155
void save(TQDomElement &frameElem)
create XML to describe yourself
Definition KWFrame.cpp:222
bool isCopy() const
Drawing property: if isCopy, this frame is a copy of the previous frame in the frameset.
Definition KWFrame.h:138
int pageNumber() const
The page on which this frame is.
Definition KWFrame.cpp:116
void load(TQDomElement &frameElem, KWFrameSet *frameSet, int syntaxVersion)
read attributes from XML.
Definition KWFrame.cpp:340
KWFrame * getCopy()
returns a copy of self
Definition KWFrame.cpp:135
Temporary information used only during loading.
static void writeAutomaticStyles(KoXmlWriter &contentWriter, KoGenStyles &mainStyles, bool stylesDotXml)
Helper function, also used by KWDocument.
The Page Manager manages all the pages a document contains and separates all the frames the document ...
This class represents a printed page of the document.
Definition KWPage.h:30
double height() const
return the height of this page (in pt)
Definition KWPage.cpp:44
double leftMargin() const
return the width of the margin at left (in pt);
Definition KWPage.cpp:97
double topMargin() const
return the height of the margin at top (in pt);
Definition KWPage.cpp:87
double bottomMargin() const
return the height of the margin at bottom (in pt);
Definition KWPage.cpp:92
double width() const
return the width of this page (in pt)
Definition KWPage.cpp:38
double rightMargin() const
return the width of the margin at left (in pt);
Definition KWPage.cpp:108
double offsetInDocument() const
All Pages are in a document-wide coordinate system that simply puts every page under the next page an...
Definition KWPage.cpp:128
A frameset that contains an embedded object (a KWDocumentChild).
virtual void load(TQDomElement &attributes, bool loadFrames=true)
load from XML - when loading
virtual TQDomElement save(TQDomElement &parentElem, bool saveFrames=true)
save to XML - when saving
This class implements tables by acting as the manager for the frame(set)s which make up the table cel...
Cell * loadCell(TQDomElement &frameElem, bool loadFrames=true, bool useNames=true)
load one cell
void moveBy(double dx, double dy)
move the whole of the table, this is mainly for anchored frames.
void setZOrder()
Sets zOrder for all cells in this table.
virtual void fromXML(TQDomElement &framesetElem, bool loadFrames=true, bool useNames=true)
load from XML - when pasting from clipboard
Collection of user-defined table styles.
Table style (can created/modified/deleted by the user) A table style is simply a paragraph style and ...
void saveTableStyle(TQDomElement &parentElem)
save (old xml format)
Class: KWTextFrameSet Contains text (KoTextObject) and frames to display that text.
KoTextObject * textObject() const
Return the contained text object.
KWFrame * internalToDocument(const KoPoint &relPoint, KoPoint &dPoint) const
Convert the in the internal qtextdoc coordinates (in layout units) into a point in the document coord...
virtual void layout()
Invalidate all paragraphs and start re-formatting.
virtual void load(TQDomElement &attributes, bool loadFrames=true)
load from XML - when loading
void loadOasisContent(const TQDomElement &bodyElem, KoOasisContext &context)
Load the contents of a frame (i.e. the text).
void saveOasisContent(KoXmlWriter &writer, KoSavingContext &context) const
Save the contents of a frame (i.e. the text).
bool minMaxInternalOnPage(int pageNum, int &topLU, int &bottomLU) const
Return the min and max LU coordinates for the text in the given page, if the frameset has any frames ...
virtual void setVisible(bool v)
set the visibility of the frameset.
void renumberFootNotes(bool repaint=true)
(Assuming this==main frameset), recalc the foot note numbers
void applyStyleChange(KoStyleChangeDefMap changed)
Update the paragraph that use the given style, after this style was changed.
This class is used by "Insert Picture", i.e.
Definition KWTextImage.h:34
static KoTextFormat loadFormat(TQDomElement &formatElem, KoTextFormat *refFormat, const TQFont &defaultFont, const TQString &defaultLanguage, bool hyphanation)
Public for loading a style (KWord-1.3 XML).
static TQDomElement saveFormat(TQDomDocument &doc, KoTextFormat *curFormat, KoTextFormat *refFormat, int pos, int len)
Public for saving a style (KWord-1.3 XML).
Abstract base class for KWCanvas's view modes.
Definition KWViewMode.h:48
Definition of an anchor's position:
Definition KWAnchorPos.h:32