kword

KWFrameSet.cpp
1/* This file is part of the KDE project
2 Copyright (C) 1998, 1999, 2000 Reginald Stadlbauer <reggie@kde.org>
3 Copyright (C) 2005 Thomas Zander <zander@kde.org>
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public
7 License as published by the Free Software Foundation; either
8 version 2 of the License, or (at your option) any later version.
9
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Library General Public License for more details.
14
15 You should have received a copy of the GNU Library General Public License
16 along with this library; see the file COPYING.LIB. If not, write to
17 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 * Boston, MA 02110-1301, USA.
19*/
20
21#include "KWFrameSet.h"
22#include "KWDocument.h"
23#include "KWViewMode.h"
24#include "KWCommand.h"
25#include "KWFrame.h"
26#include "KWTextFrameSet.h"
27#include "KWTableFrameSet.h"
28#include "KWAnchor.h"
29#include "KWordFrameSetIface.h"
30#include "KWFrameList.h"
31#include "KWPageManager.h"
32#include "KWPage.h"
33#include "KWFrameViewManager.h"
34#include "KWFrameView.h"
35
36#include <KoOasisContext.h>
37#include <KoXmlNS.h>
38#include <KoXmlWriter.h>
39
40#include <tqpopupmenu.h>
41#include <tqapplication.h>
42
43//#define DEBUG_DRAW
44
45KWFrameSet::KWFrameSet( KWDocument *doc )
46 : m_doc( doc ), m_frames(), m_framesInPage(), m_firstPage( 0 ), m_emptyList(),
47 m_info( FI_BODY ),
48 m_groupmanager( 0L ), m_visible( true ),
49 m_protectSize( false ),
50 m_anchorTextFs( 0L ), m_dcop( 0L ), m_pageManager( 0 )
51{
52 // Send our "repaintChanged" signals to the document.
53 setName("KWFrameSet");
54 if(m_doc) {
55 connect( this, TQ_SIGNAL( repaintChanged( KWFrameSet * ) ),
56 doc, TQ_SLOT( slotRepaintChanged( KWFrameSet * ) ) );
57 m_pageManager = doc->pageManager();
58 }
59 m_frames.setAutoDelete( true );
60 m_framesInPage.setAutoDelete( true ); // autodelete the lists in the array (not the frames;)
61}
62
63KWordFrameSetIface* KWFrameSet::dcopObject()
64 {
65 if ( !m_dcop )
66 m_dcop = new KWordFrameSetIface( this );
67
68 return m_dcop;
69}
70
71
73{
74 delete m_dcop;
75}
76
77void KWFrameSet::addFrame( KWFrame *frame, bool recalc )
78{
79 if ( m_frames.findRef( frame ) != -1 )
80 return;
81
82 //kdDebug(32001) << k_funcinfo << name() << " adding frame" << frame << " recalc=" << recalc << endl;
83 if(m_doc)
85 frame->setFrameSet(this);
86 m_frames.append( frame );
87 if(recalc)
89
90 emit sigFrameAdded(frame);
91}
92
93void KWFrameSet::deleteFrame( unsigned int num, bool remove, bool recalc )
94{
95 //kdDebug(32001) << k_funcinfo << name() << " deleting frame" << num << " remove=" << remove << " recalc=" << recalc << endl; //kdBacktrace();
96 KWFrame *frm = m_frames.at( num );
97 Q_ASSERT( frm );
98 m_frames.take( num );
99 Q_ASSERT( !m_frames.contains(frm) );
100
101 unsigned int index = frm->pageNumber() - m_firstPage;
102 if(m_framesInPage.count() >= index) {
103 TQPtrList<KWFrame> *lst = m_framesInPage.at(index);
104 lst->remove(frm);
105 }
106
107 KWFrameList *stack = frm->frameStack();
108 if( stack ) {
109 stack->update(); // will update the other frames on the page.
110 frm->setFrameStack(0);
111 delete stack;
112 }
113 emit sigFrameRemoved(frm);
114 if ( !remove )
115 frm->setFrameSet(0L);
116 else {
117 // ###### should something similar be done when just removing a frame from the list?
118 frameDeleted( frm, recalc ); // inform kwtableframeset if necessary
119 delete frm;
120 //kdDebug(32001) << k_funcinfo << frm << " deleted. Now I have " << m_frames.count() << " m_frames" << endl;
121 }
122
123 if ( recalc )
124 updateFrames();
125}
126
127void KWFrameSet::deleteFrame( KWFrame *frm, bool remove, bool recalc )
128{
129 //kdDebug(32001) << "KWFrameSet::deleteFrame " << frm << " remove=" << remove << endl;
130 int num = m_frames.findRef( frm );
131 Q_ASSERT( num != -1 );
132 if ( num == -1 )
133 return;
134
135 deleteFrame( num, remove, recalc );
136}
137
138void KWFrameSet::deleteAllFrames()
139{
140 if ( !m_frames.isEmpty() )
141 {
142 for ( TQPtrListIterator<KWFrame> frameIt( m_frames ); frameIt.current(); ++frameIt )
143 emit sigFrameRemoved( *frameIt );
144 m_frames.clear();
145 updateFrames();
146 }
147}
148
149void KWFrameSet::deleteAllCopies()
150{
151 if ( m_frames.count() > 1 )
152 {
153 KWFrame * firstFrame = m_frames.take(0);
154 deleteAllFrames();
155 m_frames.append( firstFrame );
156 updateFrames();
157 }
158}
159
160void KWFrameSet::createEmptyRegion( const TQRect & crect, TQRegion & emptyRegion, KWViewMode *viewMode )
161{
162 KWPage *page = m_doc->pageManager()->page( frame(0) );
163 if( !page ) {
164 kdWarning(31001) << "The first frame of '" << name() << "' is outside all pages!!" << endl;
165 return;
166 }
167 double paperHeight = page->height();
168 //kdDebug(32001) << "KWFrameSet::createEmptyRegion " << name() << endl;
169 for (TQPtrListIterator<KWFrame> frameIt = frameIterator(); frameIt.current(); ++frameIt )
170 {
171 if ( !frameIt.current()->isTransparent() )
172 {
173 TQRect outerRect( viewMode->normalToView( frameIt.current()->outerRect(viewMode) ) );
174 //kdDebug(32001) << "KWFrameSet::createEmptyRegion outerRect=" << outerRect << " crect=" << crect << endl;
175 outerRect &= crect; // This is important, to avoid calling subtract with a Y difference > 65536
176 if ( !outerRect.isEmpty() )
177 {
178 emptyRegion = emptyRegion.subtract( outerRect );
179 //kdDebug(32001) << "KWFrameSet::createEmptyRegion emptyRegion now: " << endl; DEBUGREGION( emptyRegion );
180 }
181 if ( crect.bottom() + paperHeight < outerRect.top() )
182 return; // Ok, we're far below the crect, abort.
183 }
184 }
185}
186
187void KWFrameSet::drawPadding( KWFrame *frame, TQPainter *p, const TQRect &crect, const TQColorGroup &, KWViewMode *viewMode )
188{
189 TQRect outerRect( viewMode->normalToView( frame->outerRect(viewMode) ) );
190 //kdDebug(32001) << "KWFrameSet::drawPadding frame: " << frameFromPtr( frame )
191 // << " outerRect: " << outerRect
192 // << " crect: " << crect << endl;
193
194 if ( !crect.intersects( outerRect ) )
195 {
196#ifdef DEBUG_DRAW
197 kdDebug(32001) << "KWFrameSet::drawPadding no intersection with " << crect << endl;
198#endif
199 return;
200 }
201 TQRect frameRect( viewMode->normalToView( m_doc->zoomRect( *frame ) ) );
202 p->save();
203 TQBrush bgBrush( frame->backgroundColor() );
204 bgBrush.setColor( KWDocument::resolveBgColor( bgBrush.color(), p ) );
205 p->setBrush( bgBrush );
206 int leftMargin = m_doc->zoomItX(frame->paddingLeft());
207 int topMargin = m_doc->zoomItY(frame->paddingTop());
208 int rightMargin = m_doc->zoomItX(frame->paddingRight());
209 int bottomMargin = m_doc->zoomItY(frame->paddingBottom());
210 //kdDebug(32001) << "KWFrameSet::drawPadding leftMargin=" << leftMargin << " topMargin=" << topMargin << " rightMargin=" << rightMargin << " bottomMargin=" << bottomMargin << endl;
211
212 if ( topMargin != 0 )
213 {
214 TQRect r( frameRect.left(), frameRect.top(), frameRect.width(), topMargin );
215 p->fillRect( r, bgBrush );
216 }
217 if ( leftMargin != 0 )
218 {
219 TQRect r( frameRect.left(), frameRect.top(), leftMargin, frameRect.height() );
220 p->fillRect( r, bgBrush );
221 }
222 if ( rightMargin != 0 )
223 {
224 TQRect r( frameRect.right()-rightMargin, frameRect.top(), rightMargin, frameRect.height() );
225 p->fillRect( r, bgBrush );
226 }
227 if ( bottomMargin != 0 )
228 {
229 TQRect r( frameRect.left(), frameRect.bottom()-bottomMargin, frameRect.width(), bottomMargin );
230 p->fillRect( r, bgBrush );
231 }
232 p->restore();
233
234}
235
236
237void KWFrameSet::drawFrameBorder( TQPainter *painter, KWFrame *frame, KWFrame *settingsFrame, const TQRect &crect, KWViewMode *viewMode )
238{
239 TQRect outerRect( viewMode->normalToView( frame->outerRect( viewMode ) ) );
240 //kdDebug(32001) << "KWFrameSet::drawFrameBorder frame: " << frameFromPtr( frame )
241 // << " outerRect: " << outerRect << endl;
242
243 if ( !crect.intersects( outerRect ) )
244 {
245 //kdDebug(32001) << "KWFrameSet::drawFrameBorder no intersection with " << crect << endl;
246 return;
247 }
248
249 TQRect frameRect( viewMode->normalToView( m_doc->zoomRect( *frame ) ) );
250
251 painter->save();
252 TQBrush bgBrush( settingsFrame->backgroundColor() );
253 //bool defaultColor = !bgBrush.color().isValid();
254 bgBrush.setColor( KWDocument::resolveBgColor( bgBrush.color(), painter ) );
255 painter->setBrush( bgBrush );
256
257 // Draw default borders using view settings...
258 TQPen viewSetting( TQApplication::palette().color( TQPalette::Active, TQColorGroup::Mid ) );
259 int minBorder = 1;
260 // ...except when printing, or embedded doc, or disabled.
261 if ( !viewMode || !viewMode->drawFrameBorders() )
262 {
263 viewSetting = TQPen(TQt::NoPen);
264 minBorder = 0;
265 }
266
267 // Draw borders either as the user defined them, or using the view settings.
268 // Borders should be drawn _outside_ of the frame area
269 // otherwise the frames will erase the border when painting themselves.
270
271 KoBorder::drawBorders( *painter, m_doc, frameRect,
272 settingsFrame->leftBorder(), settingsFrame->rightBorder(),
273 settingsFrame->topBorder(), settingsFrame->bottomBorder(),
274 minBorder, viewSetting );
275 painter->restore();
276}
277
279{
280 // Find main text frame
281 TQPtrListIterator<KWFrameSet> fit = m_doc->framesetsIterator();
282 for ( ; fit.current() ; ++fit )
283 {
284 KWTextFrameSet * frameSet = dynamic_cast<KWTextFrameSet *>( fit.current() );
285 if ( !frameSet || frameSet->frameSetInfo() != FI_BODY )
286 continue;
287
288 KoTextParag* parag = 0L;
289 int index = 0;
290 KoPoint dPoint( m_frames.first()->topLeft() );
291 kdDebug(32001) << "KWFrameSet::setFloating looking for pos at " << dPoint.x() << " " << dPoint.y() << endl;
292 frameSet->findPosition( dPoint, parag, index );
293 // Create anchor. TODO: refcount the anchors!
294 setAnchored( frameSet, parag, index );
295 frameSet->layout();
296 m_doc->frameChanged( m_frames.first() );
297 return;
298 }
299}
300
301void KWFrameSet::setProtectSize( bool b)
302{
303 m_protectSize = b;
304}
305
306void KWFrameSet::setAnchored( KWTextFrameSet* textfs, int paragId, int index, bool placeHolderExists /* = false */, bool repaint )
307{
308 KWTextParag * parag = static_cast<KWTextParag *>( textfs->textDocument()->paragAt( paragId ) );
309 Q_ASSERT( parag );
310 if ( parag )
311 setAnchored( textfs, parag, index, placeHolderExists, repaint );
312}
313
314void KWFrameSet::setAnchored( KWTextFrameSet* textfs, KoTextParag* parag, int index, bool placeHolderExists /* = false */, bool repaint )
315{
316 kdDebug(32001) << "KWFrameSet::setAnchored " << textfs << " " << parag->paragId() << " " << index << " " << placeHolderExists << endl;
317 Q_ASSERT( textfs );
318 Q_ASSERT( parag );
319 if ( isFloating() )
320 deleteAnchors();
321 m_anchorTextFs = textfs;
322 KWFrameList::createFrameList(textfs, m_doc); // remove ourselves from others list now we are inline
323 if ( parag )
324 createAnchors( parag, index, placeHolderExists, repaint );
325
326 if ( !placeHolderExists ) // i.e. not while loading
327 {
328 m_doc->updateAllFrames(); // We just became floating, so we need to be removed from "frames on top/below".
329 // TODO pass page number to updateAllFrames - hmm, we could have several frames in theory
330 }
331}
332
334{
335 m_anchorTextFs = textfs;
336 m_doc->updateAllFrames(); // We just became floating, so we need to be removed from "frames on top/below".
337 // TODO pass page number - hmm, we could have several frames in theory
338}
339
340// Find where our anchor is ( if we are anchored ).
341// We can't store a pointers to anchors, because over time we might change anchors
342// (Especially, undo/redo of insert/delete can reuse an old anchor and forget a newer one etc.)
344{
345 Q_ASSERT( m_anchorTextFs );
346 // Yes, a linear search, but only among all customitems of the correct textdoc,
347 // whose number is assumed to be quite small.
348 TQPtrListIterator<KoTextCustomItem> cit( m_anchorTextFs->textDocument()->allCustomItems() );
349 for ( ; cit.current() ; ++cit )
350 {
351 KWAnchor * anchor = dynamic_cast<KWAnchor *>( cit.current() );
352 if ( anchor && !anchor->isDeleted()
353 && anchor->frameSet() == this && anchor->frameNum() == frameNum )
354 return anchor;
355 }
356 kdWarning() << "KWFrameSet::findAnchor anchor not found (frameset='" << name()
357 << "' frameNum=" << frameNum << ")" << endl;
358 return 0L;
359}
360
362{
363 kdDebug(32001) << "KWFrameSet::setFixed" << endl;
364 if ( isFloating() )
365 deleteAnchors();
366 m_anchorTextFs = 0L;
367 // make sure the frames are on top
368 // (their z-order didn't matter when they were inline)
369 TQPtrListIterator<KWFrame> frameIt = frameIterator();
370 for ( ; frameIt.current(); ++frameIt )
371 frameIt.current()->setZOrder( m_doc->maxZOrder( frameIt.current()->pageNumber(m_doc) ) + 1 );
372
373 m_doc->repaintAllViews();
374 m_doc->updateRulerFrameStartEnd();
375}
376
377KWAnchor * KWFrameSet::createAnchor( KoTextDocument *txt, int frameNum )
378{
379 KWAnchor * anchor = new KWAnchor( txt, this, frameNum );
380 return anchor;
381}
382
383void KWFrameSet::createAnchors( KoTextParag * parag, int index, bool placeHolderExists /*= false */ /*only used when loading*/,
384 bool repaint )
385{
386 kdDebug(32001) << "KWFrameSet::createAnchors" << endl;
387 Q_ASSERT( m_anchorTextFs );
388 TQPtrListIterator<KWFrame> frameIt = frameIterator();
389 for ( ; frameIt.current(); ++frameIt, ++index )
390 {
391 //if ( ! frameIt.current()->anchor() )
392 {
393 // Anchor this frame, after the previous one
394 KWAnchor * anchor = createAnchor( m_anchorTextFs->textDocument(), frameFromPtr( frameIt.current() ) );
395 if ( !placeHolderExists )
396 parag->insert( index, KoTextObject::customItemChar() );
397 parag->setCustomItem( index, anchor, 0 );
398 }
399 }
400 parag->setChanged( true );
401 if ( repaint )
402 emit repaintChanged( m_anchorTextFs );
403}
404
405void KWFrameSet::deleteAnchor( KWAnchor * anchor )
406{
407 // Simple deletion, no undo/redo
408 KoTextCursor c( m_anchorTextFs->textDocument() );
409 c.setParag( anchor->paragraph() );
410 c.setIndex( anchor->index() );
411 anchor->setDeleted( true ); // this sets m_anchorTextFs to 0L
412
413 static_cast<KWTextParag*>(c.parag())->removeCustomItem(c.index());
414 c.remove(); // This deletes the character where the anchor was
415 // We don't delete the anchor since it might be in a customitemmap in a text-insert command
416 // TODO: refcount the anchors
417 c.parag()->setChanged( true );
418}
419
420void KWFrameSet::deleteAnchors()
421{
422 kdDebug(32002) << "KWFrameSet::deleteAnchors" << endl;
423 KWTextFrameSet * textfs = m_anchorTextFs;
424 Q_ASSERT( textfs );
425 if ( !textfs )
426 return;
427 //TQPtrListIterator<KWFrame> frameIt = frameIterator();
428 int frameNum = 0;
429 // At the moment there's only one anchor per frameset
430 // With tables the loop below will be wrong anyway...
431 //for ( ; frameIt.current(); ++frameIt, ++frameNum )
432 {
433/* if ( frameIt.current()->anchor() )
434 deleteAnchor( frameIt.current()->anchor() );
435 frameIt.current()->setAnchor( 0L );
436*/
437 KWAnchor * anchor = findAnchor( frameNum );
438 deleteAnchor( anchor );
439 }
440 emit repaintChanged( textfs );
441}
442
443void KWFrameSet::moveFloatingFrame( int frameNum, const KoPoint &position )
444{
445 KWFrame * frame = m_frames.at( frameNum );
446 Q_ASSERT( frame );
447 if ( !frame ) return;
448
449 KoPoint pos( position );
450 // position includes the border, we need to adjust accordingly
451 pos.rx() += frame->leftBorder().width();
452 pos.ry() += frame->topBorder().width();
453 if ( frame->topLeft() != pos )
454 {
455 kdDebug(32002) << "KWFrameSet::moveFloatingFrame " << pos.x() << "," << pos.y() << endl;
456 int oldPageNum = frame->pageNumber();
457 frame->moveTopLeft( pos );
458
459 updateFrames();
460 if( frame->frameStack() )
461 frame->frameStack()->updateAfterMove( oldPageNum );
462 }
463 invalidate();
464}
465
466KoRect KWFrameSet::floatingFrameRect( int frameNum )
467{
468 KWFrame * frame = m_frames.at( frameNum );
469 Q_ASSERT( frame );
470 Q_ASSERT( isFloating() );
471
472 KWAnchor* anchor = findAnchor( frameNum );
473 Q_ASSERT( anchor );
474 TQRect paragRect = anchor->paragraph()->rect();
475 int x = anchor->x() + paragRect.x(); // in LU
476 int y = anchor->y() + paragRect.y(); // in LU
477
478 KoPoint topLeft( m_doc->layoutUnitToPixelX( x ), m_doc->layoutUnitToPixelY( y ) );
479 return KoRect( topLeft, frame->outerKoRect().size() );
480}
481
482KoSize KWFrameSet::floatingFrameSize( int frameNum )
483{
484 KWFrame * frame = m_frames.at( frameNum );
485 Q_ASSERT( frame );
486 return frame->outerKoRect().size();
487}
488
490{
491 KWFrame * frame = m_frames.at( frameNum );
492 Q_ASSERT( frame );
493 return new KWCreateFrameCommand( TQString(), frame );
494}
495
497{
498 KWFrame * frame = m_frames.at( frameNum );
499 Q_ASSERT( frame );
500 return new KWDeleteFrameCommand( TQString(), frame );
501}
502
503KWFrame * KWFrameSet::frameAtPos( double x, double y ) const
504{
505 KoPoint docPoint( x, y );
506 TQPtrListIterator<KWFrame> frameIt = frameIterator();
507 for ( ; frameIt.current(); ++frameIt )
508 if ( frameIt.current()->contains( docPoint ) )
509 return frameIt.current();
510 return 0L;
511}
512
513KWFrame *KWFrameSet::frame( unsigned int num ) const
514{
515 // TQPtrList sucks
516 return const_cast<KWFrameSet*>( this )->m_frames.at( num );
517}
518
520{
521 return m_frames.findRef( frame );
522}
523
525{
526 if ( !frame->isCopy() )
527 return const_cast<KWFrame *>( frame );
528 KWFrame* lastRealFrame=0L;
529 TQPtrListIterator<KWFrame> frameIt( frame->frameSet()->frameIterator() );
530 for ( ; frameIt.current(); ++frameIt )
531 {
532 KWFrame *curFrame = frameIt.current();
533 if ( curFrame == frame )
534 return lastRealFrame ? lastRealFrame : const_cast<KWFrame *>( frame );
535 if ( !lastRealFrame || !curFrame->isCopy() )
536 lastRealFrame = curFrame;
537 }
538 return const_cast<KWFrame *>( frame ); //fallback, should never happen
539}
540
542{
543 if ( m_frames.isEmpty() )
544 return; // No frames. This happens when the frameset is deleted (still exists for undo/redo)
545
546 // Not visible ? Don't bother then.
547 if ( !isVisible() )
548 return;
549
550 //kdDebug(32001) << "KWFrameSet::updateFrames " << this << " " << name() << endl;
551
552 if ( flags & UpdateFramesInPage ) {
553 // For each of our frames, clear old list of frames on top, and grab min/max page nums
554 m_firstPage = m_frames.first()->pageNumber(); // we know m_frames is not empty here
555 int lastPage = m_firstPage;
556 TQPtrListIterator<KWFrame> fIt( frameIterator() );
557 for ( ; fIt.current(); ++fIt ) {
558 int pg = fIt.current()->pageNumber();
559 m_firstPage = KMIN( m_firstPage, pg );
560 lastPage = KMAX( lastPage, pg );
561 }
562 //kdDebug(32001) << "firstPage=" << m_firstPage << " lastPage=" << lastPage << endl;
563
564 // Prepare the m_framesInPage structure
565 int oldSize = m_framesInPage.size();
566 m_framesInPage.resize( lastPage - m_firstPage + 1 );
567 // Clear the old elements
568 int oldElements = KMIN( oldSize, (int)m_framesInPage.size() );
569 for ( int i = 0 ; i < oldElements ; ++i )
570 m_framesInPage[i]->clear();
571 // Initialize the new elements.
572 for ( int i = oldElements ; i < (int)m_framesInPage.size() ; ++i )
573 m_framesInPage.insert( i, new TQPtrList<KWFrame>() );
574
575 // Iterate over m_frames again, to fill the m_framesInPage array
576 fIt.toFirst();
577 for ( ; fIt.current(); ++fIt ) {
578 int pg = fIt.current()->pageNumber();
579 Q_ASSERT( pg <= lastPage );
580 m_framesInPage[pg - m_firstPage]->append( fIt.current() );
581 }
582 }
583
584 if ( isFloating() )
585 {
586 //kdDebug(32001) << "KWFrameSet::updateFrames " << name() << " is floating" << endl;
587 TQPtrListIterator<KWFrame> frameIt = frameIterator();
588 int frameNum = 0;
589 // At the moment there's only one anchor per frameset
590 //for ( ; frameIt.current(); ++frameIt, ++frameNum )
591 {
592 KWAnchor * anchor = findAnchor( frameNum );
593 //kdDebug(32001) << "KWFrameSet::updateFrames anchor=" << anchor << endl;
594 if ( anchor )
595 anchor->resize();
596 }
597 }
598}
599
600bool KWFrameSet::isPaintedBy( KWFrameSet* fs ) const
601{
602 if ( fs == this )
603 return true;
604 if ( isFloating() )
605 {
606 KWFrameSet* parentFs = anchorFrameset();
607 if ( parentFs && parentFs->isPaintedBy( fs ) )
608 return true;
609 }
610 if ( groupmanager() )
611 {
612 if ( groupmanager()->isPaintedBy( fs ) )
613 return true;
614 }
615 return false;
616}
617
618const TQPtrList<KWFrame> & KWFrameSet::framesInPage( int pageNum ) const
619{
620 if ( pageNum < m_firstPage || pageNum >= (int)m_framesInPage.size() + m_firstPage )
621 {
622#ifdef DEBUG_DTI
623 kdWarning(32002) << name() << " framesInPage called for pageNum=" << pageNum << ". "
624 << " Min value: " << m_firstPage
625 << " Max value: " << m_framesInPage.size() + m_firstPage - 1 << endl;
626#endif
627 return m_emptyList; // TQPtrList<KWFrame>() doesn't work, it's a temporary
628 }
629 return * m_framesInPage[pageNum - m_firstPage];
630}
631
632void KWFrameSet::drawContents( TQPainter *p, const TQRect & crect, const TQColorGroup &cg,
633 bool onlyChanged, bool resetChanged,
634 KWFrameSetEdit *edit, KWViewMode *viewMode,
635 KWFrameViewManager *frameViewManager )
636{
637#ifdef DEBUG_DRAW
638 kdDebug(32001) << "\nKWFrameSet::drawContents " << this << " " << name()
639 << " onlyChanged=" << onlyChanged << " resetChanged=" << resetChanged
640 << " crect= " << crect
641 << endl;
642#endif
643 if ( !viewMode->isTextModeFrameset( this ) )
644 {
645 TQPtrListIterator<KWFrame> frameIt( frameIterator() );
646 KWFrame * lastRealFrame = 0L;
647 //double lastRealFrameTop = 0;
648 //double totalHeight = 0; // in pt, to avoid accumulating rounding errors
649 for ( ; frameIt.current(); )
650 {
651 KWFrame *frame = frameIt.current();
652 ++frameIt; // Point to the next one, to detect "last copy"
653 // The settings come from this frame
654 KWFrame * settingsFrame = ( frame->isCopy() && lastRealFrame ) ? lastRealFrame : frame;
655 bool lastCopy = !frameIt.current() || !frameIt.current()->isCopy();
656 drawFrameAndBorders( frame, p, crect, cg, onlyChanged,
657 // Only reset the changed flag in the last copy of a given frame (#60678)
658 resetChanged && lastCopy,
659 edit,
660 viewMode, settingsFrame, true /*transparency & double-buffering*/ );
661 if(viewMode->drawSelections() && frameViewManager) {
662 KWFrameView* view = frameViewManager->view(frame);
663 if(view)
664 view->paintFrameAttributes(p, crect, viewMode, m_doc);
665 }
666
667 if ( !lastRealFrame || !frame->isCopy() )
668 {
669 lastRealFrame = frame;
670 //lastRealFrameTop = totalHeight;
671 }
672 //totalHeight += frame->innerHeight();
673 }
674 }
675 else { // Text view mode
676 TQRect normalRect = viewMode->viewToNormal(crect);
677 drawFrame( 0L /*frame*/, p, normalRect, crect, TQPoint(KWViewModeText::OFFSET, 0),
678 0L /*settingsFrame*/, cg, onlyChanged, resetChanged, edit, viewMode, true );
679 }
680}
681
683 TQPainter *painter, const TQRect &crect,
684 const TQColorGroup &cg, bool onlyChanged, bool resetChanged,
685 KWFrameSetEdit *edit, KWViewMode *viewMode,
686 KWFrame *settingsFrame, bool drawUnderlyingFrames )
687{
688 if ( !frame->isValid() )
689 {
690 kdDebug(32002) << "KWFrameSet::drawFrameAndBorders " << name() << " frame " << frameFromPtr( frame ) << " " << frame << " isn't valid" << endl;
691 return;
692 }
693
694 TQRect normalOuterFrameRect( frame->outerRect( viewMode ) );
695 TQRect outerFrameRect( viewMode->normalToView( normalOuterFrameRect ) );
696 TQRect outerCRect = crect.intersect( outerFrameRect );
697#ifdef DEBUG_DRAW
698 kdDebug(32001) << "KWFrameSet::drawFrameAndBorders " << name() << " frame " << frameFromPtr( frame ) << " " << *frame << endl;
699 kdDebug(32001) << " (outer) normalFrameRect=" << normalOuterFrameRect << " frameRect=" << outerFrameRect << endl;
700 kdDebug(32001) << " crect=" << crect << " intersec=" << outerCRect << " todraw=" << !outerCRect.isEmpty() << endl;
701#endif
702 if ( !outerCRect.isEmpty() )
703 {
704 // Determine settingsFrame if not passed (for speedup)
705 if ( !settingsFrame )
706 settingsFrame = this->settingsFrame( frame );
707
708 TQRect normalInnerFrameRect( m_doc->zoomRect( frame->innerRect() ) );
709 TQRect innerFrameRect( viewMode->normalToView( normalInnerFrameRect ) );
710
711 // This translates the coordinates in the document contents
712 // ( frame and r are up to here in this system )
713 // into the frame's own coordinate system.
714 int offsetX = normalInnerFrameRect.left();
715 int offsetY = normalInnerFrameRect.top() - m_doc->zoomItY( frame->internalY() );
716
717 TQRect innerCRect = outerCRect.intersect( innerFrameRect );
718 if ( !innerCRect.isEmpty() )
719 {
720 TQRect fcrect = viewMode->viewToNormal( innerCRect );
721#ifdef DEBUG_DRAW
722 kdDebug(32001) << " (inner) normalFrameRect=" << normalInnerFrameRect << " frameRect=" << innerFrameRect << endl;
723 //kdDebug(32001) << " crect after view-to-normal:" << fcrect << "." << " Will move by (" << -offsetX << ", -(" << normalInnerFrameRect.top() << "-" << m_doc->zoomItY(frame->internalY()) << ") == " << -offsetY << ")." << endl;
724#endif
725 fcrect.moveBy( -offsetX, -offsetY );
726 Q_ASSERT( fcrect.x() >= 0 );
727 Q_ASSERT( fcrect.y() >= 0 );
728
729 // fcrect is now the portion of the frame to be drawn,
730 // in the frame's coordinates and in pixels
731#ifdef DEBUG_DRAW
732 kdDebug(32001) << "KWFrameSet::drawFrameAndBorders in frame coords:" << fcrect << ". Will translate painter by intersec-fcrect: " << innerCRect.x()-fcrect.x() << "," << innerCRect.y()-fcrect.y() << "." << endl;
733#endif
734 TQRegion reg;
735 if ( drawUnderlyingFrames )
736 reg = frameClipRegion( painter, frame, outerCRect, viewMode );
737 else // false means we are being drawn _as_ an underlying frame, so no clipping!
738 reg = painter->xForm( outerCRect );
739 if ( !reg.isEmpty() )
740 {
741 painter->save();
742 painter->setClipRegion( reg );
743
744 drawFrame( frame, painter, fcrect, outerCRect,
745 innerCRect.topLeft() - fcrect.topLeft(), // This assume that viewToNormal() is only a translation
746 settingsFrame, cg, onlyChanged, resetChanged,
747 edit, viewMode, drawUnderlyingFrames );
748
749 if( !groupmanager() ) // not for table cells
750 drawFrameBorder( painter, frame, settingsFrame, outerCRect, viewMode );
751 painter->restore();
752 }
753 }
754 }
755}
756
757void KWFrameSet::drawFrame( KWFrame *frame, TQPainter *painter, const TQRect &fcrect, const TQRect &outerCRect,
758 const TQPoint& translationOffset,
759 KWFrame *settingsFrame, const TQColorGroup &cg, bool onlyChanged, bool resetChanged,
760 KWFrameSetEdit *edit, KWViewMode* viewMode, bool drawUnderlyingFrames )
761{
762 // In this method the painter is NOT translated yet. It's still in view coordinates.
763 if ( outerCRect.isEmpty() )
764 return;
765#ifdef DEBUG_DRAW
766 kdDebug(32001) << "\nKWFrameSet::drawFrame " << name() << " outerCRect=" << outerCRect << " frameCrect=" << fcrect << " drawUnderlyingFrames=" << drawUnderlyingFrames << endl;
767#endif
768 Q_ASSERT( fcrect.isValid() );
769
770 TQColorGroup frameColorGroup( cg );
771 if ( settingsFrame ) // 0L in text viewmode
772 {
773 TQBrush bgBrush( settingsFrame->backgroundColor() );
774 bgBrush.setColor( KWDocument::resolveBgColor( bgBrush.color(), painter ) );
775 frameColorGroup.setBrush( TQColorGroup::Base, bgBrush );
776 }
777
778 if ( drawUnderlyingFrames && frame && frame->frameStack()) {
779 TQValueList<KWFrame*> below = frame->frameStack()->framesBelow();
780 if ( !below.isEmpty() )
781 {
782 // Double-buffering - not when printing
783 TQPainter* doubleBufPainter = painter;
784 TQPixmap* pix = 0L;
785 if ( painter->device()->devType() != TQInternal::Printer )
786 {
787 pix = m_doc->doubleBufferPixmap( outerCRect.size() );
788 doubleBufPainter = new TQPainter;
789 doubleBufPainter->begin( pix );
790 // Initialize the pixmap to the page background color
791 // (if the frame is over the page margins, no underlying frame will paint anything there)
792 doubleBufPainter->fillRect( 0, 0, outerCRect.width(), outerCRect.height(), TQApplication::palette().active().brush( TQColorGroup::Base ) );
793
794 // The double-buffer pixmap has (0,0) at outerCRect.topLeft(), so we need to
795 // translate the double-buffer painter; drawFrameAndBorders will draw using view coordinates.
796 doubleBufPainter->translate( -outerCRect.x(), -outerCRect.y() );
797#ifdef DEBUG_DRAW
798 // kdDebug(32001) << " ... using double buffering. Portion covered: " << outerCRect << endl;
799#endif
800 }
801
802 // Transparency handling
803#ifdef DEBUG_DRAW
804 kdDebug(32001) << " below: " << below.count() << endl;
805#endif
806 for (TQValueListIterator<KWFrame*> it = below.begin(); it != below.end(); ++it )
807 {
808 KWFrame* f = (*it);
809
810#ifdef DEBUG_DRAW
811 kdDebug(32001) << " looking at frame below us: " << f->frameSet()->name() << " frame " << frameFromPtr( frame ) << endl;
812#endif
813 TQRect viewFrameCRect = outerCRect.intersect( viewMode->normalToView( f->outerRect( viewMode ) ) );
814 if ( !viewFrameCRect.isEmpty() )
815 {
816#ifdef DEBUG_DRAW
817 kdDebug(32001) << " viewFrameRect=" << viewFrameCRect << " calling drawFrameAndBorders." << endl;
818#endif
819 f->frameSet()->drawFrameAndBorders( f, doubleBufPainter, viewFrameCRect, cg,
820 false, resetChanged, edit, viewMode, 0L, false );
821 }
822 }
823
824 if ( frame->paddingLeft() || frame->paddingTop() || frame->paddingRight() || frame->paddingBottom() )
825 drawPadding( frame, doubleBufPainter, outerCRect, cg, viewMode );
826 doubleBufPainter->save();
827#ifdef DEBUG_DRAW
828 kdDebug(32001) << " translating by " << translationOffset.x() << ", " << translationOffset.y() << " before drawFrameContents" << endl;
829#endif
830 doubleBufPainter->translate( translationOffset.x(), translationOffset.y() ); // This assume that viewToNormal() is only a translation
831 // We can't "repaint changed parags only" if we just drew the underlying frames, hence the "false"
832 drawFrameContents( frame, doubleBufPainter, fcrect, frameColorGroup, false, resetChanged, edit, viewMode );
833 doubleBufPainter->restore();
834
835 if ( painter->device()->devType() != TQInternal::Printer )
836 {
837 doubleBufPainter->end();
838#ifdef DEBUG_DRAW
839 kdDebug(32001) << " painting double-buf pixmap at position " << outerCRect.topLeft() << " (real painter pos:" << painter->xForm( outerCRect.topLeft() ) << ")" << endl;
840#endif
841 painter->drawPixmap( outerCRect.topLeft(), *pix );
842 delete doubleBufPainter;
843 }
844 return; // done! :)
845 }
846 else
847 {
848 // nothing below? paint a bg color then
849 frameColorGroup.setBrush( TQColorGroup::Base, m_doc->defaultBgColor( painter ) );
850 }
851 }
852 if ( frame && (frame->paddingLeft() || frame->paddingTop() ||
853 frame->paddingRight() || frame->paddingBottom()) )
854 drawPadding( frame, painter, outerCRect, cg, viewMode );
855 painter->save();
856 painter->translate( translationOffset.x(), translationOffset.y() );
857
858 drawFrameContents( frame, painter, fcrect, frameColorGroup, onlyChanged, resetChanged, edit, viewMode );
859 painter->restore();
860}
861
862void KWFrameSet::drawFrameContents( KWFrame *, TQPainter *, const TQRect &,
863 const TQColorGroup &, bool, bool, KWFrameSetEdit*, KWViewMode * )
864{
865 kdWarning() << "Default implementation of drawFrameContents called for " << className() << " " << this << " " << name() << kdBacktrace();
866}
867
868void KWFrameSet::saveCommon( TQDomElement &parentElem, bool saveFrames )
869{
870 if ( m_frames.isEmpty() ) // Deleted frameset -> don't save
871 return;
872
873 // Save all the common attributes for framesets.
874 parentElem.setAttribute( "frameType", static_cast<int>( type() ) );
875 parentElem.setAttribute( "frameInfo", static_cast<int>( m_info ) );
876 parentElem.setAttribute( "name", m_name );
877 parentElem.setAttribute( "visible", static_cast<int>( m_visible ) );
878 parentElem.setAttribute( "protectSize", static_cast<int>( m_protectSize ) );
879 if ( saveFrames )
880 {
881 TQPtrListIterator<KWFrame> frameIt = frameIterator();
882 for ( ; frameIt.current(); ++frameIt )
883 {
884 KWFrame *frame = frameIt.current();
885 TQDomElement frameElem = parentElem.ownerDocument().createElement( "FRAME" );
886 parentElem.appendChild( frameElem );
887
888 frame->save( frameElem );
889
890 if(m_doc->processingType() == KWDocument::WP) {
891 // Assume that all header/footer frames in the same frameset are
892 // perfect copies. This might not be the case some day though.
893 if(frameSetInfo() == FI_FIRST_HEADER ||
894 frameSetInfo() == FI_EVEN_HEADER ||
895 frameSetInfo() == FI_ODD_HEADER ||
896 frameSetInfo() == FI_FIRST_FOOTER ||
897 frameSetInfo() == FI_EVEN_FOOTER ||
898 frameSetInfo() == FI_ODD_FOOTER ||
899 frameSetInfo() == FI_FOOTNOTE) break;
900 }
901 }
902 }
903}
904
905//
906// This function is intended as a helper for all the derived classes. It reads
907// in all the attributes common to all framesets and loads all frames.
908//
909void KWFrameSet::load( TQDomElement &framesetElem, bool loadFrames )
910{
911 m_info = static_cast<KWFrameSet::Info>( KWDocument::getAttribute( framesetElem, "frameInfo", KWFrameSet::FI_BODY ) );
912 m_visible = static_cast<bool>( KWDocument::getAttribute( framesetElem, "visible", true ) );
913 m_protectSize=static_cast<bool>( KWDocument::getAttribute( framesetElem, "protectSize", false ) );
914 if ( loadFrames )
915 {
916 // <FRAME>
917 TQDomElement frameElem = framesetElem.firstChild().toElement();
918 for ( ; !frameElem.isNull() ; frameElem = frameElem.nextSibling().toElement() )
919 {
920 if ( frameElem.tagName() == "FRAME" )
921 {
922 KoRect rect;
923 rect.setLeft( KWDocument::getAttribute( frameElem, "left", 0.0 ) );
924 rect.setTop( KWDocument::getAttribute( frameElem, "top", 0.0 ) );
925 rect.setRight( KWDocument::getAttribute( frameElem, "right", 0.0 ) );
926 rect.setBottom( KWDocument::getAttribute( frameElem, "bottom", 0.0 ) );
927 KWFrame * frame = new KWFrame(this, rect.x(), rect.y(), rect.width(), rect.height() );
928 frame->load( frameElem, this, m_doc->syntaxVersion() );
929 addFrame( frame, false );
930 m_doc->progressItemLoaded();
931 }
932 }
933 }
934}
935
936KWFrame* KWFrameSet::loadOasisFrame( const TQDomElement& tag, KoOasisContext& context )
937{
938 double width = 100;
939 if ( tag.hasAttributeNS( KoXmlNS::svg, "width" ) ) { // fixed width
940 // TODO handle percentage (of enclosing table/frame/page)
941 width = KoUnit::parseValue( tag.attributeNS( KoXmlNS::svg, "width", TQString() ) );
942 } else if ( tag.hasAttributeNS( KoXmlNS::fo, "min-width" ) ) {
943 // min-width is not supported in KWord. Let's use it as a fixed width.
944 width = KoUnit::parseValue( tag.attributeNS( KoXmlNS::fo, "min-width", TQString() ) );
945 } else {
946 kdWarning(32001) << "Error in frame " << tag.tagName() << " " << tag.attributeNS( KoXmlNS::draw, "name", TQString() ) << " : neither width nor min-width specified!" << endl;
947 }
948 double height = 100;
949 if ( tag.hasAttributeNS( KoXmlNS::svg, "height" ) ) { // fixed height
950 // TODO handle percentage (of enclosing table/frame/page)
951 height = KoUnit::parseValue( tag.attributeNS( KoXmlNS::svg, "height", TQString() ) );
952 }
953 //kdDebug(32001) << k_funcinfo << "width=" << width << " height=" << height << " pt" << endl;
954
955 KWFrame * frame = new KWFrame(this,
956 KoUnit::parseValue( tag.attributeNS( KoXmlNS::svg, "x", TQString() ) ),
957 KoUnit::parseValue( tag.attributeNS( KoXmlNS::svg, "y", TQString() ) ),
958 width, height );
959
960 frame->setZOrder( tag.attributeNS( KoXmlNS::draw, "z-index", TQString() ).toInt() );
961 // Copy-frames.
962 // We currently ignore the value of the copy-of attribute. It probably needs to
963 // be handled like chain-next-name (kwtextframeset.cpp) but for all types of frameset.
964 frame->setCopy( tag.hasAttributeNS( KoXmlNS::draw, "copy-of" ) );
965 frame->loadCommonOasisProperties( context, this, "graphic" );
966
967 addFrame( frame, false );
968
969 // Protect (OASIS 14.27.7, also in OO-1.1)
970 // A frame with protected contents means that the frameset is protected (makes sense)
971 // A frame with protected size means that the frameset is size-protected (hmm, kword did it that way)
972 // TODO implement position protection
973 TQString protectList = context.styleStack().attributeNS( KoXmlNS::style, "protect" );
974 if ( protectList.contains( "content" ) )
975 setProtectContent( true );
976 if ( protectList.contains( "size" ) )
977 m_protectSize = true;
978
979 // TODO m_visible ? User-toggeable or internal?
980
981 return frame;
982}
983
985{
986 m_visible = v;
987 if ( m_visible )
988 // updateFrames was disabled while we were invisible
989 updateFrames();
990}
991
992bool KWFrameSet::isVisible( KWViewMode* viewMode ) const
993{
994 if ( !m_visible || m_frames.isEmpty() )
995 return false;
996 if ( isAHeader() && !m_doc->isHeaderVisible() )
997 return false;
998 if ( isAFooter() && !m_doc->isFooterVisible() )
999 return false;
1000 if ( viewMode && !viewMode->isFrameSetVisible(this) )
1001 return false;
1002 if ( isFloating() && !anchorFrameset()->isVisible( viewMode ) )
1003 return false;
1004
1005 KoHFType ht = m_doc != 0 ? m_doc->headerType(): HF_FIRST_DIFF;
1006 KoHFType ft = m_doc != 0 ? m_doc->footerType(): HF_FIRST_DIFF;
1007 switch( m_info )
1008 {
1009 case FI_FIRST_HEADER:
1010 return ( ht == HF_FIRST_DIFF || ht == HF_FIRST_EO_DIFF );
1011 case FI_ODD_HEADER:
1012 return true;
1013 case FI_EVEN_HEADER:
1014 return ( ht == HF_EO_DIFF || ht == HF_FIRST_EO_DIFF );
1015 case FI_FIRST_FOOTER:
1016 return ( ft == HF_FIRST_DIFF || ft == HF_FIRST_EO_DIFF );
1017 case FI_ODD_FOOTER:
1018 return true;
1019 case FI_EVEN_FOOTER:
1020 return ( ft == HF_EO_DIFF || ft == HF_FIRST_EO_DIFF );
1021 default:
1022 return true;
1023 }
1024}
1025
1026bool KWFrameSet::isAHeader() const
1027{
1028 return ( m_info == FI_FIRST_HEADER || m_info == FI_ODD_HEADER || m_info == FI_EVEN_HEADER );
1029}
1030
1031bool KWFrameSet::isAFooter() const
1032{
1033 return ( m_info == FI_FIRST_FOOTER || m_info == FI_ODD_FOOTER || m_info == FI_EVEN_FOOTER );
1034}
1035
1036bool KWFrameSet::isFootEndNote() const
1037{
1038 return m_info == FI_FOOTNOTE;
1039}
1040
1041bool KWFrameSet::isMainFrameset() const
1042{
1043 return ( m_doc && m_doc->processingType() == KWDocument::WP &&
1044 m_doc->frameSet( 0 ) == this );
1045}
1046
1047bool KWFrameSet::isMoveable() const
1048{
1049 if ( isHeaderOrFooter() )
1050 return false;
1051 return !isMainFrameset() && !isFloating();
1052}
1053
1054const char* KWFrameSet::headerFooterTag() const
1055{
1056 switch ( m_info ) {
1057 case KWFrameSet::FI_ODD_HEADER:
1058 return "style:header";
1059 case KWFrameSet::FI_EVEN_HEADER:
1060 return "style:header-left";
1061 case KWFrameSet::FI_ODD_FOOTER:
1062 return "style:footer";
1063 case KWFrameSet::FI_EVEN_FOOTER:
1064 return "style:footer-left";
1065 case KWFrameSet::FI_FIRST_HEADER:
1066 return "style:header-first"; // NOT OASIS COMPLIANT
1067 case KWFrameSet::FI_FIRST_FOOTER:
1068 return "style:footer-first"; // NOT OASIS COMPLIANT
1069 default: // shouldn't be called for body or footnote
1070 return 0;
1071 }
1072}
1073
1075{
1076 //kdDebug(32001) << "KWFrameSet::finalize ( calls updateFrames + zoom ) " << this << endl;
1077 updateFrames();
1078}
1079
1080TQRegion KWFrameSet::frameClipRegion( TQPainter * painter, KWFrame *frame, const TQRect & crect,
1081 KWViewMode * viewMode )
1082{
1083// KWDocument * doc = kWordDocument();
1084 TQRect rc = painter->xForm( crect );
1085#ifdef DEBUG_DRAW
1086 //kdDebug(32002) << "KWFrameSet::frameClipRegion rc initially " << rc << endl;
1087#endif
1088
1089 Q_ASSERT( frame );
1090#if 0 // done later
1091 if ( clipFrame )
1092 {
1093 rc &= painter->xForm( viewMode->normalToView( doc->zoomRect( (*frame) ) ) ); // intersect
1094#ifdef DEBUG_DRAW
1095 kdDebug(32002) << "KWFrameSet::frameClipRegion frame=" << *frame
1096 << " clip region rect=" << rc
1097 << " rc.isEmpty()=" << rc.isEmpty() << endl;
1098#endif
1099 }
1100#endif
1101 if ( !rc.isEmpty() )
1102 {
1103 TQRegion reg( rc );
1104 // This breaks when a frame is under another one, it still appears if !onlyChanged.
1105 // cvs log says this is about frame borders... hmm.
1107
1108 Q_ASSERT( frame->frameStack() );
1109
1110 TQValueList<KWFrame *> onTop = frame->frameStack()->framesOnTop();
1111 for (TQValueListIterator<KWFrame*> fIt = onTop.begin(); fIt != onTop.end(); ++fIt )
1112 {
1113 KWFrame* frameOnTop = (*fIt);
1114 Q_ASSERT( frameOnTop->frameSet() );
1115 TQRect r = painter->xForm( viewMode->normalToView( frameOnTop->outerRect( viewMode ) ) );
1116#ifdef DEBUG_DRAW
1117 //kdDebug(32002) << "frameClipRegion subtract rect "<< r << endl;
1118#endif
1119 reg -= r; // subtract
1120 }
1121#ifdef DEBUG_DRAW
1122 //kdDebug(32002) << "KWFrameSet::frameClipRegion result:" << reg << endl;
1123#endif
1124 return reg;
1125 }
1126 return TQRegion();
1127}
1128
1130{
1131 TQPtrListIterator<KWFrame> frameIt( frameIterator() );
1132 for ( ; frameIt.current(); ++frameIt )
1133 {
1134 KWFrame * frame = frameIt.current();
1135 if ( frame->pageNumber() == num ) // ## TODO: use framesInPage, see KWTextFrameSet
1136 {
1137 // Ok, so we have a frame on that page -> we can't remove it unless it's a copied frame
1138 if ( ! ( frame->isCopy() && frameIt.current() != m_frames.first() ) )
1139 {
1140 kdDebug(32001) << "KWFrameSet::canRemovePage " << name() << " frame on page " << num << " -> false" << endl;
1141 return false;
1142 }
1143 }
1144 }
1145 return true;
1146}
1147
1149 for(KWFrame *f=m_frames.first();f;f=m_frames.next())
1150 f->setFrameBehavior(fb);
1151}
1152
1154 for(KWFrame *f=m_frames.first();f;f=m_frames.next())
1155 f->setNewFrameBehavior(nfb);
1156}
1157
1158// ## this should pass the viewmode as argument, probably.
1159bool KWFrameSet::isFrameAtPos( const KWFrame* frame, const TQPoint& point, bool borderOfFrameOnly) const {
1160 TQRect outerRect( frame->outerRect( m_doc->layoutViewMode() ) );
1161 // Give the user a bit of margin for clicking on it :)
1162 const int margin = 2;
1163 outerRect.rLeft() -= margin;
1164 outerRect.rTop() -= margin;
1165 outerRect.rRight() += margin;
1166 outerRect.rBottom() += margin;
1167 if ( outerRect.contains( point ) ) {
1168 if(borderOfFrameOnly) {
1169 TQRect innerRect( m_doc->zoomRect( *frame ) );
1170 innerRect.rLeft() += margin;
1171 innerRect.rTop() += margin;
1172 innerRect.rRight() -= margin;
1173 innerRect.rBottom() -= margin;
1174 return (!innerRect.contains(point) );
1175 }
1176 return true;
1177 }
1178 return false;
1179}
1180
1182{
1183 //kdDebug(32001) << "KWFrameSet::setZOrder (to max) " << name() << endl;
1184 TQPtrListIterator<KWFrame> fit = frameIterator();
1185 for ( ; fit.current() ; ++fit )
1186 fit.current()->setZOrder( m_doc->maxZOrder( fit.current()->pageNumber(m_doc) ) + 1 );
1187}
1188
1189void KWFrameSet::setName( const TQString &name )
1190{
1191 m_name = name;
1192 emit sigNameChanged(this);
1193}
1194
1195#ifndef NDEBUG
1196#include "KWFrameViewManager.h"
1197#include "KWFrameView.h"
1198void KWFrameSet::printDebug()
1199{
1200 static const char * typeFrameset[] = { "base", "txt", "picture", "part", "formula", "clipart",
1201 "6", "7", "8", "9", "table",
1202 "ERROR" };
1203 static const char * infoFrameset[] = { "body", "first header", "even headers", "odd headers",
1204 "first footer", "even footers", "odd footers", "footnote", "ERROR" };
1205 static const char * frameBh[] = { "AutoExtendFrame", "AutoCreateNewFrame", "Ignore", "ERROR" };
1206 static const char * newFrameBh[] = { "Reconnect", "NoFollowup", "Copy" };
1207 static const char * runaround[] = { "No Runaround", "Bounding Rect", "Skip", "ERROR" };
1208 static const char * runaroundSide[] = { "Biggest", "Left", "Right", "ERROR" };
1209
1210 KWFrameViewManager *fvm = 0;
1211 if ( !m_doc->getAllViews().isEmpty() ) {
1212 KWView *view = m_doc->getAllViews().first();
1213 if(view)
1214 fvm = view->frameViewManager();
1215 }
1216
1217 kdDebug() << " | Visible: " << isVisible() << endl;
1218 kdDebug() << " | Type: " << typeFrameset[ type() ] << endl;
1219 kdDebug() << " | Info: " << infoFrameset[ frameSetInfo() ] << endl;
1220 kdDebug() << " | Floating: " << isFloating() << endl;
1221 kdDebug() << " | Frames in page array: " << endl;
1222 for ( uint i = 0 ; i < m_framesInPage.size() ; ++i )
1223 {
1224 TQPtrListIterator<KWFrame> it( *m_framesInPage[i] );
1225 int pgNum = i + m_firstPage;
1226 for ( ; it.current() ; ++it )
1227 kdDebug() << " | " << pgNum << ": " << it.current() << " " << *it.current()
1228 << " internalY=" << it.current()->internalY() << "pt "
1229 << " (in LU pix:" << m_doc->ptToLayoutUnitPixY( it.current()->internalY() ) << ")"
1230 << " innerHeight=" << it.current()->innerHeight()
1231 << " (in LU pix:" << m_doc->ptToLayoutUnitPixY( it.current()->innerHeight() ) << ")"
1232 << endl;
1233 }
1234
1235 TQPtrListIterator<KWFrame> frameIt = frameIterator();
1236 for ( unsigned int j = 0; frameIt.current(); ++frameIt, ++j ) {
1237 KWFrame * frame = frameIt.current();
1238 TQCString copy = frame->isCopy() ? "[copy]" : "";
1239 kdDebug() << " +-- Frame " << j << " of "<< frameCount() << " (" << frame << ") " << copy << endl;
1240 printDebug( frame );
1241 kdDebug() << " Rectangle : " << frame->x() << "," << frame->y() << " " << frame->width() << "x" << frame->height() << endl;
1242 kdDebug() << " RunAround: "<< runaround[ frame->runAround() ] << " side:" << runaroundSide[ frame->runAroundSide() ]<< endl;
1243 kdDebug() << " FrameBehavior: "<< frameBh[ frame->frameBehavior() ] << endl;
1244 kdDebug() << " NewFrameBehavior: "<< newFrameBh[ frame->newFrameBehavior() ] << endl;
1245 TQColor col = frame->backgroundColor().color();
1246 kdDebug() << " BackgroundColor: "<< ( col.isValid() ? col.name().latin1() : "(default)" ) << endl;
1247 kdDebug() << " SheetSide "<< frame->sheetSide() << endl;
1248 kdDebug() << " Z Order: " << frame->zOrder() << endl;
1249
1250 if( frame->frameStack() ) {
1251 TQValueList<KWFrame*> onTop = frame->frameStack()->framesOnTop();
1252 TQValueList<KWFrame*> below = frame->frameStack()->framesBelow();
1253
1254 kdDebug() << " Frames below: " << below.count()
1255 << ", frames on top: " << onTop.count() << endl;
1256 }
1257 else
1258 kdDebug() << " no frameStack set." << endl;
1259 kdDebug() << " minFrameHeight "<< frame->minimumFrameHeight() << endl;
1260 TQString page = pageManager() && pageManager()->pageCount() > 0 ? TQString::number(frame->pageNumber()) : " [waiting for pages to be created]";
1261
1262 KWFrameView *fv = 0;
1263 if(fvm) fv = fvm->view(frame);
1264 if(fv && fv->selected())
1265 kdDebug() << " * Page "<< page << endl;
1266 else
1267 kdDebug() << " Page "<< page << endl;
1268 }
1269}
1270
1271void KWFrameSet::printDebug( KWFrame * )
1272{
1273}
1274
1275#endif
1276
1277#include "KWFrameSet.moc"
An anchor is a special character, or 'custom item'.
Definition KWAnchor.h:35
int frameNum() const
The index the frameset needs to access which content is displayed in the anchor object.
Definition KWAnchor.h:52
KWFrameSet * frameSet() const
The frameset that will provide the content to display in this anchor object.
Definition KWAnchor.h:50
Command created when creating a frame.
Definition KWCommand.h:436
Command created when deleting a frame.
Definition KWCommand.h:415
This class calculates and caches a list of frames that are on top or below the KWFrame instance this ...
Definition KWFrameList.h:32
void update()
Update the z-ordering around the frame we host the framelist for.
static void createFrameList(KWFrame *f, KWDocument *doc)
Factory method to create and attach a new instance of a framelist.
This object is created to edit a particular frameset in a particular view The view's canvas creates i...
Class: KWFrameSet Base type, a frameset holds content as well as frames to show that content.
Definition KWFrameSet.h:62
void drawFrameAndBorders(KWFrame *frame, TQPainter *painter, const TQRect &crect, const TQColorGroup &cg, bool, bool, KWFrameSetEdit *edit, KWViewMode *viewMode, KWFrame *settingsFrame, bool drawUnderlyingFrames)
This one is called by drawContents for each frame.
void repaintChanged(KWFrameSet *frameset)
Emitted when something has changed in this frameset, so that all views repaint it.
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 moveFloatingFrame(int frameNum, const KoPoint &position)
Move the frame frameNum to the given position - this is called when the frame is anchored and the anc...
void drawFrameBorder(TQPainter *painter, KWFrame *frame, KWFrame *settingsFrame, const TQRect &crect, KWViewMode *viewMode)
Paint the borders for one frame of this frameset.
virtual void deleteFrame(unsigned int num, bool remove=true, bool recalc=true)
Delete a frame from the set of frames this frameSet has.
static KWFrame * settingsFrame(const KWFrame *frame)
Returns the original frame that the param frame is a copy off, or the frame itself.
void setNewFrameBehavior(KWFrame::NewFrameBehavior nfb)
set newFrameBehavior on all frames, see KWFrame for specifics
virtual FrameSetType type() const
The type of frameset.
Definition KWFrameSet.h:76
virtual void drawPadding(KWFrame *frame, TQPainter *p, const TQRect &fcrect, const TQColorGroup &cg, KWViewMode *viewMode)
Draw the padding area inside of a specific frame of this frameSet.
int m_firstPage
always equal to m_framesInPage[0].first()->pageNumber() :)
Definition KWFrameSet.h:491
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 ...
TQPtrVector< TQPtrList< KWFrame > > m_framesInPage
This array provides a direct access to the frames on page N.
Definition KWFrameSet.h:489
virtual void drawFrame(KWFrame *frame, TQPainter *painter, const TQRect &fcrect, const TQRect &crect, const TQPoint &translationOffset, KWFrame *settingsFrame, const TQColorGroup &cg, bool onlyChanged, bool resetChanged, KWFrameSetEdit *edit, KWViewMode *viewMode, bool drawUnderlyingFrames)
Draw a particular frame of this frameset.
virtual ~KWFrameSet()
destructor
virtual KWAnchor * createAnchor(KoTextDocument *txt, int frameNum)
Create an anchor for the floating frame identified by frameNum.
int frameFromPtr(KWFrame *frame)
Get frame number.
virtual bool canRemovePage(int num)
Return true if page num can be removed, as far as this frameset is concerned.
unsigned int frameCount() const
Get number of child frames.
Definition KWFrameSet.h:163
virtual void load(TQDomElement &framesetElem, bool loadFrames=true)
load from XML - when loading
bool isFloating() const
Return true if this frameset is floating (inline), false if it's fixed.
Definition KWFrameSet.h:372
virtual void frameDeleted(KWFrame *, bool)
Called by deleteFrame when it really deletes a frame (remove=true), to remove it from the table too.
Definition KWFrameSet.h:129
virtual void updateFrames(int flags=0xff)
Called when our frames change, or when another frameset's frames change.
void saveCommon(TQDomElement &parentElem, bool saveFrames)
save the common attributes for the frameset
virtual void setZOrder()
set z-order for all frames
TQPtrList< KWFrame > m_emptyList
always empty, for convenience in framesInPage
Definition KWFrameSet.h:493
KWTableFrameSet * groupmanager() const
returns the groupManager this frameset belongs to.
Definition KWFrameSet.h:408
virtual KoSize floatingFrameSize(int frameNum=0)
Get the size of the "floating frame" identified by frameNum.
KWTextFrameSet * anchorFrameset() const
Return the frameset in which our anchor is - assuming isFloating().
Definition KWFrameSet.h:374
void setFrameBehavior(KWFrame::FrameBehavior fb)
set frameBehavior on all frames, see KWFrame for specifics
void setFixed()
Make this frameset fixed, i.e. not anchored.
KWFrame * frame(unsigned int _num) const
get a frame by number
void setFloating()
Make this frameset floating (anchored), as close to its current position as possible.
TQString name() const
get/set frameset name. For tables in particular, this must be unique
Definition KWFrameSet.h:428
KWFrameSet(KWDocument *doc)
constructor
TQRegion frameClipRegion(TQPainter *painter, KWFrame *frame, const TQRect &crect, KWViewMode *viewMode)
Determine the clipping rectangle for drawing the contents of frame with painter in the rectangle deli...
const TQPtrList< KWFrame > & framesInPage(int pageNum) const
Return list of frames in page pageNum.
Info frameSetInfo() const
Returns the type of TextFrameSet this is.
Definition KWFrameSet.h:95
virtual KCommand * anchoredObjectCreateCommand(int frameNum)
Store command for creating an anchored object.
virtual void drawFrameContents(KWFrame *frame, TQPainter *painter, const TQRect &fcrect, const TQColorGroup &cg, bool onlyChanged, bool resetChanged, KWFrameSetEdit *edit, KWViewMode *viewMode)
Implement this one instead of drawFrame to benefit from double-buffering AND transparency handling (p...
bool isVisible(KWViewMode *viewMode=0L) const
Returns true if the frameset is visible.
bool isFrameAtPos(const KWFrame *frame, const TQPoint &nPoint, bool borderOfFrameOnly=false) const
Return if the point is on the frame.
KoRect floatingFrameRect(int frameNum=0)
Get the rect of the "floating frame" identified by frameNum, in coordinates RELATIVE TO THE PARENT FR...
KWFrame * frameAtPos(double _x, double _y) const
retrieve frame from x and y coords (unzoomed coords)
virtual KCommand * anchoredObjectDeleteCommand(int frameNum)
Store command for deleting an anchored object.
Class that knows about all the (visible) frames in the document and will act as a manager between the...
KWFrameView * view(const KoPoint &point, SelectionType select, bool borderOnly=false) const
Returns a frameView representing a frame positioned at point, or 0 when no match found.
an instance of a KWFrameView represents the view in the MVC model of a frame; there can be multiple K...
Definition KWFrameView.h:82
bool selected() const
returns if this frameView is selected. A selected frame is shown differently on screen.
Definition KWFrameView.h:93
void paintFrameAttributes(TQPainter *painter, const TQRect &crect, KWViewMode *vm, KoZoomHandler *zh)
Paint view based items of the frameView, like selected state.
This class represents a single frame.
Definition KWFrame.h:68
NewFrameBehavior
What happens on new page (create a new frame and reconnect, no followup, make copy).
Definition KWFrame.h:132
TQRect outerRect(KWViewMode *viewMode) const
Return the zoomed rectangle for this frame, including the border - for drawing.
Definition KWFrame.cpp:185
KWFrameSet * frameSet() const
Data stucture methods.
Definition KWFrame.h:143
FrameBehavior
what should happen when the frame is full
Definition KWFrame.h:116
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
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
Class: KWTextFrameSet Contains text (KoTextObject) and frames to display that text.
virtual void layout()
Invalidate all paragraphs and start re-formatting.
This class extends KoTextParag for KWord-specific formatting stuff, custom items, loading and saving.
Definition KWTextParag.h:41
static const int OFFSET
hardcoded distance from the left side this viewmode starts its rendering
Definition KWViewMode.h:290
Abstract base class for KWCanvas's view modes.
Definition KWViewMode.h:48
virtual bool isTextModeFrameset(KWFrameSet *) const
Answers the question if argument frameset has to be drawn as a text-mode text area if true,...
Definition KWViewMode.h:129
virtual TQPoint normalToView(const TQPoint &nPoint)=0
Normal coord -> view coord.
virtual bool drawSelections()
Should selected text be drawn as such?
Definition KWViewMode.h:99
bool drawFrameBorders() const
Should we see frame borders?
Definition KWViewMode.h:105
virtual TQPoint viewToNormal(const TQPoint &vPoint)=0
View coord -> normal coord.
virtual bool isFrameSetVisible(const KWFrameSet *)
Should this frameset be visible in this viewmode?
Definition KWViewMode.h:109