summaryrefslogtreecommitdiffstats
path: root/kword/KWFrameSet.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'kword/KWFrameSet.cpp')
-rw-r--r--kword/KWFrameSet.cpp1277
1 files changed, 1277 insertions, 0 deletions
diff --git a/kword/KWFrameSet.cpp b/kword/KWFrameSet.cpp
new file mode 100644
index 00000000..154cd22b
--- /dev/null
+++ b/kword/KWFrameSet.cpp
@@ -0,0 +1,1277 @@
+/* This file is part of the KDE project
+ Copyright (C) 1998, 1999, 2000 Reginald Stadlbauer <reggie@kde.org>
+ Copyright (C) 2005 Thomas Zander <zander@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#include "KWFrameSet.h"
+#include "KWDocument.h"
+#include "KWViewMode.h"
+#include "KWCommand.h"
+#include "KWFrame.h"
+#include "KWTextFrameSet.h"
+#include "KWTableFrameSet.h"
+#include "KWAnchor.h"
+#include "KWordFrameSetIface.h"
+#include "KWFrameList.h"
+#include "KWPageManager.h"
+#include "KWPage.h"
+#include "KWFrameViewManager.h"
+#include "KWFrameView.h"
+
+#include <KoOasisContext.h>
+#include <KoXmlNS.h>
+#include <KoXmlWriter.h>
+
+#include <qpopupmenu.h>
+#include <qapplication.h>
+
+//#define DEBUG_DRAW
+
+KWFrameSet::KWFrameSet( KWDocument *doc )
+ : m_doc( doc ), m_frames(), m_framesInPage(), m_firstPage( 0 ), m_emptyList(),
+ m_info( FI_BODY ),
+ m_groupmanager( 0L ), m_visible( true ),
+ m_protectSize( false ),
+ m_anchorTextFs( 0L ), m_dcop( 0L ), m_pageManager( 0 )
+{
+ // Send our "repaintChanged" signals to the document.
+ setName("KWFrameSet");
+ if(m_doc) {
+ connect( this, SIGNAL( repaintChanged( KWFrameSet * ) ),
+ doc, SLOT( slotRepaintChanged( KWFrameSet * ) ) );
+ m_pageManager = doc->pageManager();
+ }
+ m_frames.setAutoDelete( true );
+ m_framesInPage.setAutoDelete( true ); // autodelete the lists in the array (not the frames;)
+}
+
+KWordFrameSetIface* KWFrameSet::dcopObject()
+ {
+ if ( !m_dcop )
+ m_dcop = new KWordFrameSetIface( this );
+
+ return m_dcop;
+}
+
+
+KWFrameSet::~KWFrameSet()
+{
+ delete m_dcop;
+}
+
+void KWFrameSet::addFrame( KWFrame *frame, bool recalc )
+{
+ if ( m_frames.findRef( frame ) != -1 )
+ return;
+
+ //kdDebug(32001) << k_funcinfo << name() << " adding frame" << frame << " recalc=" << recalc << endl;
+ if(m_doc)
+ KWFrameList::createFrameList(frame, m_doc);
+ frame->setFrameSet(this);
+ m_frames.append( frame );
+ if(recalc)
+ updateFrames();
+
+ emit sigFrameAdded(frame);
+}
+
+void KWFrameSet::deleteFrame( unsigned int num, bool remove, bool recalc )
+{
+ //kdDebug(32001) << k_funcinfo << name() << " deleting frame" << num << " remove=" << remove << " recalc=" << recalc << endl; //kdBacktrace();
+ KWFrame *frm = m_frames.at( num );
+ Q_ASSERT( frm );
+ m_frames.take( num );
+ Q_ASSERT( !m_frames.contains(frm) );
+
+ unsigned int index = frm->pageNumber() - m_firstPage;
+ if(m_framesInPage.count() >= index) {
+ QPtrList<KWFrame> *lst = m_framesInPage.at(index);
+ lst->remove(frm);
+ }
+
+ KWFrameList *stack = frm->frameStack();
+ if( stack ) {
+ stack->update(); // will update the other frames on the page.
+ frm->setFrameStack(0);
+ delete stack;
+ }
+ emit sigFrameRemoved(frm);
+ if ( !remove )
+ frm->setFrameSet(0L);
+ else {
+ // ###### should something similar be done when just removing a frame from the list?
+ frameDeleted( frm, recalc ); // inform kwtableframeset if necessary
+ delete frm;
+ //kdDebug(32001) << k_funcinfo << frm << " deleted. Now I have " << m_frames.count() << " m_frames" << endl;
+ }
+
+ if ( recalc )
+ updateFrames();
+}
+
+void KWFrameSet::deleteFrame( KWFrame *frm, bool remove, bool recalc )
+{
+ //kdDebug(32001) << "KWFrameSet::deleteFrame " << frm << " remove=" << remove << endl;
+ int num = m_frames.findRef( frm );
+ Q_ASSERT( num != -1 );
+ if ( num == -1 )
+ return;
+
+ deleteFrame( num, remove, recalc );
+}
+
+void KWFrameSet::deleteAllFrames()
+{
+ if ( !m_frames.isEmpty() )
+ {
+ for ( QPtrListIterator<KWFrame> frameIt( m_frames ); frameIt.current(); ++frameIt )
+ emit sigFrameRemoved( *frameIt );
+ m_frames.clear();
+ updateFrames();
+ }
+}
+
+void KWFrameSet::deleteAllCopies()
+{
+ if ( m_frames.count() > 1 )
+ {
+ KWFrame * firstFrame = m_frames.take(0);
+ deleteAllFrames();
+ m_frames.append( firstFrame );
+ updateFrames();
+ }
+}
+
+void KWFrameSet::createEmptyRegion( const QRect & crect, QRegion & emptyRegion, KWViewMode *viewMode )
+{
+ KWPage *page = m_doc->pageManager()->page( frame(0) );
+ if( !page ) {
+ kdWarning(31001) << "The first frame of '" << name() << "' is outside all pages!!" << endl;
+ return;
+ }
+ double paperHeight = page->height();
+ //kdDebug(32001) << "KWFrameSet::createEmptyRegion " << name() << endl;
+ for (QPtrListIterator<KWFrame> frameIt = frameIterator(); frameIt.current(); ++frameIt )
+ {
+ if ( !frameIt.current()->isTransparent() )
+ {
+ QRect outerRect( viewMode->normalToView( frameIt.current()->outerRect(viewMode) ) );
+ //kdDebug(32001) << "KWFrameSet::createEmptyRegion outerRect=" << outerRect << " crect=" << crect << endl;
+ outerRect &= crect; // This is important, to avoid calling subtract with a Y difference > 65536
+ if ( !outerRect.isEmpty() )
+ {
+ emptyRegion = emptyRegion.subtract( outerRect );
+ //kdDebug(32001) << "KWFrameSet::createEmptyRegion emptyRegion now: " << endl; DEBUGREGION( emptyRegion );
+ }
+ if ( crect.bottom() + paperHeight < outerRect.top() )
+ return; // Ok, we're far below the crect, abort.
+ }
+ }
+}
+
+void KWFrameSet::drawPadding( KWFrame *frame, QPainter *p, const QRect &crect, const QColorGroup &, KWViewMode *viewMode )
+{
+ QRect outerRect( viewMode->normalToView( frame->outerRect(viewMode) ) );
+ //kdDebug(32001) << "KWFrameSet::drawPadding frame: " << frameFromPtr( frame )
+ // << " outerRect: " << outerRect
+ // << " crect: " << crect << endl;
+
+ if ( !crect.intersects( outerRect ) )
+ {
+#ifdef DEBUG_DRAW
+ kdDebug(32001) << "KWFrameSet::drawPadding no intersection with " << crect << endl;
+#endif
+ return;
+ }
+ QRect frameRect( viewMode->normalToView( m_doc->zoomRect( *frame ) ) );
+ p->save();
+ QBrush bgBrush( frame->backgroundColor() );
+ bgBrush.setColor( KWDocument::resolveBgColor( bgBrush.color(), p ) );
+ p->setBrush( bgBrush );
+ int leftMargin = m_doc->zoomItX(frame->paddingLeft());
+ int topMargin = m_doc->zoomItY(frame->paddingTop());
+ int rightMargin = m_doc->zoomItX(frame->paddingRight());
+ int bottomMargin = m_doc->zoomItY(frame->paddingBottom());
+ //kdDebug(32001) << "KWFrameSet::drawPadding leftMargin=" << leftMargin << " topMargin=" << topMargin << " rightMargin=" << rightMargin << " bottomMargin=" << bottomMargin << endl;
+
+ if ( topMargin != 0 )
+ {
+ QRect r( frameRect.left(), frameRect.top(), frameRect.width(), topMargin );
+ p->fillRect( r, bgBrush );
+ }
+ if ( leftMargin != 0 )
+ {
+ QRect r( frameRect.left(), frameRect.top(), leftMargin, frameRect.height() );
+ p->fillRect( r, bgBrush );
+ }
+ if ( rightMargin != 0 )
+ {
+ QRect r( frameRect.right()-rightMargin, frameRect.top(), rightMargin, frameRect.height() );
+ p->fillRect( r, bgBrush );
+ }
+ if ( bottomMargin != 0 )
+ {
+ QRect r( frameRect.left(), frameRect.bottom()-bottomMargin, frameRect.width(), bottomMargin );
+ p->fillRect( r, bgBrush );
+ }
+ p->restore();
+
+}
+
+
+void KWFrameSet::drawFrameBorder( QPainter *painter, KWFrame *frame, KWFrame *settingsFrame, const QRect &crect, KWViewMode *viewMode )
+{
+ QRect outerRect( viewMode->normalToView( frame->outerRect( viewMode ) ) );
+ //kdDebug(32001) << "KWFrameSet::drawFrameBorder frame: " << frameFromPtr( frame )
+ // << " outerRect: " << outerRect << endl;
+
+ if ( !crect.intersects( outerRect ) )
+ {
+ //kdDebug(32001) << "KWFrameSet::drawFrameBorder no intersection with " << crect << endl;
+ return;
+ }
+
+ QRect frameRect( viewMode->normalToView( m_doc->zoomRect( *frame ) ) );
+
+ painter->save();
+ QBrush bgBrush( settingsFrame->backgroundColor() );
+ //bool defaultColor = !bgBrush.color().isValid();
+ bgBrush.setColor( KWDocument::resolveBgColor( bgBrush.color(), painter ) );
+ painter->setBrush( bgBrush );
+
+ // Draw default borders using view settings...
+ QPen viewSetting( QApplication::palette().color( QPalette::Active, QColorGroup::Mid ) );
+ int minBorder = 1;
+ // ...except when printing, or embedded doc, or disabled.
+ if ( !viewMode || !viewMode->drawFrameBorders() )
+ {
+ viewSetting = NoPen;
+ minBorder = 0;
+ }
+
+ // Draw borders either as the user defined them, or using the view settings.
+ // Borders should be drawn _outside_ of the frame area
+ // otherwise the frames will erase the border when painting themselves.
+
+ KoBorder::drawBorders( *painter, m_doc, frameRect,
+ settingsFrame->leftBorder(), settingsFrame->rightBorder(),
+ settingsFrame->topBorder(), settingsFrame->bottomBorder(),
+ minBorder, viewSetting );
+ painter->restore();
+}
+
+void KWFrameSet::setFloating()
+{
+ // Find main text frame
+ QPtrListIterator<KWFrameSet> fit = m_doc->framesetsIterator();
+ for ( ; fit.current() ; ++fit )
+ {
+ KWTextFrameSet * frameSet = dynamic_cast<KWTextFrameSet *>( fit.current() );
+ if ( !frameSet || frameSet->frameSetInfo() != FI_BODY )
+ continue;
+
+ KoTextParag* parag = 0L;
+ int index = 0;
+ KoPoint dPoint( m_frames.first()->topLeft() );
+ kdDebug(32001) << "KWFrameSet::setFloating looking for pos at " << dPoint.x() << " " << dPoint.y() << endl;
+ frameSet->findPosition( dPoint, parag, index );
+ // Create anchor. TODO: refcount the anchors!
+ setAnchored( frameSet, parag, index );
+ frameSet->layout();
+ m_doc->frameChanged( m_frames.first() );
+ return;
+ }
+}
+
+void KWFrameSet::setProtectSize( bool b)
+{
+ m_protectSize = b;
+}
+
+void KWFrameSet::setAnchored( KWTextFrameSet* textfs, int paragId, int index, bool placeHolderExists /* = false */, bool repaint )
+{
+ KWTextParag * parag = static_cast<KWTextParag *>( textfs->textDocument()->paragAt( paragId ) );
+ Q_ASSERT( parag );
+ if ( parag )
+ setAnchored( textfs, parag, index, placeHolderExists, repaint );
+}
+
+void KWFrameSet::setAnchored( KWTextFrameSet* textfs, KoTextParag* parag, int index, bool placeHolderExists /* = false */, bool repaint )
+{
+ kdDebug(32001) << "KWFrameSet::setAnchored " << textfs << " " << parag->paragId() << " " << index << " " << placeHolderExists << endl;
+ Q_ASSERT( textfs );
+ Q_ASSERT( parag );
+ if ( isFloating() )
+ deleteAnchors();
+ m_anchorTextFs = textfs;
+ KWFrameList::createFrameList(textfs, m_doc); // remove ourselves from others list now we are inline
+ if ( parag )
+ createAnchors( parag, index, placeHolderExists, repaint );
+
+ if ( !placeHolderExists ) // i.e. not while loading
+ {
+ m_doc->updateAllFrames(); // We just became floating, so we need to be removed from "frames on top/below".
+ // TODO pass page number to updateAllFrames - hmm, we could have several frames in theory
+ }
+}
+
+void KWFrameSet::setAnchored( KWTextFrameSet* textfs )
+{
+ m_anchorTextFs = textfs;
+ m_doc->updateAllFrames(); // We just became floating, so we need to be removed from "frames on top/below".
+ // TODO pass page number - hmm, we could have several frames in theory
+}
+
+// Find where our anchor is ( if we are anchored ).
+// We can't store a pointers to anchors, because over time we might change anchors
+// (Especially, undo/redo of insert/delete can reuse an old anchor and forget a newer one etc.)
+KWAnchor * KWFrameSet::findAnchor( int frameNum )
+{
+ Q_ASSERT( m_anchorTextFs );
+ // Yes, a linear search, but only among all customitems of the correct textdoc,
+ // whose number is assumed to be quite small.
+ QPtrListIterator<KoTextCustomItem> cit( m_anchorTextFs->textDocument()->allCustomItems() );
+ for ( ; cit.current() ; ++cit )
+ {
+ KWAnchor * anchor = dynamic_cast<KWAnchor *>( cit.current() );
+ if ( anchor && !anchor->isDeleted()
+ && anchor->frameSet() == this && anchor->frameNum() == frameNum )
+ return anchor;
+ }
+ kdWarning() << "KWFrameSet::findAnchor anchor not found (frameset='" << name()
+ << "' frameNum=" << frameNum << ")" << endl;
+ return 0L;
+}
+
+void KWFrameSet::setFixed()
+{
+ kdDebug(32001) << "KWFrameSet::setFixed" << endl;
+ if ( isFloating() )
+ deleteAnchors();
+ m_anchorTextFs = 0L;
+ // make sure the frames are on top
+ // (their z-order didn't matter when they were inline)
+ QPtrListIterator<KWFrame> frameIt = frameIterator();
+ for ( ; frameIt.current(); ++frameIt )
+ frameIt.current()->setZOrder( m_doc->maxZOrder( frameIt.current()->pageNumber(m_doc) ) + 1 );
+
+ m_doc->repaintAllViews();
+ m_doc->updateRulerFrameStartEnd();
+}
+
+KWAnchor * KWFrameSet::createAnchor( KoTextDocument *txt, int frameNum )
+{
+ KWAnchor * anchor = new KWAnchor( txt, this, frameNum );
+ return anchor;
+}
+
+void KWFrameSet::createAnchors( KoTextParag * parag, int index, bool placeHolderExists /*= false */ /*only used when loading*/,
+ bool repaint )
+{
+ kdDebug(32001) << "KWFrameSet::createAnchors" << endl;
+ Q_ASSERT( m_anchorTextFs );
+ QPtrListIterator<KWFrame> frameIt = frameIterator();
+ for ( ; frameIt.current(); ++frameIt, ++index )
+ {
+ //if ( ! frameIt.current()->anchor() )
+ {
+ // Anchor this frame, after the previous one
+ KWAnchor * anchor = createAnchor( m_anchorTextFs->textDocument(), frameFromPtr( frameIt.current() ) );
+ if ( !placeHolderExists )
+ parag->insert( index, KoTextObject::customItemChar() );
+ parag->setCustomItem( index, anchor, 0 );
+ }
+ }
+ parag->setChanged( true );
+ if ( repaint )
+ emit repaintChanged( m_anchorTextFs );
+}
+
+void KWFrameSet::deleteAnchor( KWAnchor * anchor )
+{
+ // Simple deletion, no undo/redo
+ KoTextCursor c( m_anchorTextFs->textDocument() );
+ c.setParag( anchor->paragraph() );
+ c.setIndex( anchor->index() );
+ anchor->setDeleted( true ); // this sets m_anchorTextFs to 0L
+
+ static_cast<KWTextParag*>(c.parag())->removeCustomItem(c.index());
+ c.remove(); // This deletes the character where the anchor was
+ // We don't delete the anchor since it might be in a customitemmap in a text-insert command
+ // TODO: refcount the anchors
+ c.parag()->setChanged( true );
+}
+
+void KWFrameSet::deleteAnchors()
+{
+ kdDebug(32002) << "KWFrameSet::deleteAnchors" << endl;
+ KWTextFrameSet * textfs = m_anchorTextFs;
+ Q_ASSERT( textfs );
+ if ( !textfs )
+ return;
+ //QPtrListIterator<KWFrame> frameIt = frameIterator();
+ int frameNum = 0;
+ // At the moment there's only one anchor per frameset
+ // With tables the loop below will be wrong anyway...
+ //for ( ; frameIt.current(); ++frameIt, ++frameNum )
+ {
+/* if ( frameIt.current()->anchor() )
+ deleteAnchor( frameIt.current()->anchor() );
+ frameIt.current()->setAnchor( 0L );
+*/
+ KWAnchor * anchor = findAnchor( frameNum );
+ deleteAnchor( anchor );
+ }
+ emit repaintChanged( textfs );
+}
+
+void KWFrameSet::moveFloatingFrame( int frameNum, const KoPoint &position )
+{
+ KWFrame * frame = m_frames.at( frameNum );
+ Q_ASSERT( frame );
+ if ( !frame ) return;
+
+ KoPoint pos( position );
+ // position includes the border, we need to adjust accordingly
+ pos.rx() += frame->leftBorder().width();
+ pos.ry() += frame->topBorder().width();
+ if ( frame->topLeft() != pos )
+ {
+ kdDebug(32002) << "KWFrameSet::moveFloatingFrame " << pos.x() << "," << pos.y() << endl;
+ int oldPageNum = frame->pageNumber();
+ frame->moveTopLeft( pos );
+
+ updateFrames();
+ if( frame->frameStack() )
+ frame->frameStack()->updateAfterMove( oldPageNum );
+ }
+ invalidate();
+}
+
+KoRect KWFrameSet::floatingFrameRect( int frameNum )
+{
+ KWFrame * frame = m_frames.at( frameNum );
+ Q_ASSERT( frame );
+ Q_ASSERT( isFloating() );
+
+ KWAnchor* anchor = findAnchor( frameNum );
+ Q_ASSERT( anchor );
+ QRect paragRect = anchor->paragraph()->rect();
+ int x = anchor->x() + paragRect.x(); // in LU
+ int y = anchor->y() + paragRect.y(); // in LU
+
+ KoPoint topLeft( m_doc->layoutUnitToPixelX( x ), m_doc->layoutUnitToPixelY( y ) );
+ return KoRect( topLeft, frame->outerKoRect().size() );
+}
+
+KoSize KWFrameSet::floatingFrameSize( int frameNum )
+{
+ KWFrame * frame = m_frames.at( frameNum );
+ Q_ASSERT( frame );
+ return frame->outerKoRect().size();
+}
+
+KCommand * KWFrameSet::anchoredObjectCreateCommand( int frameNum )
+{
+ KWFrame * frame = m_frames.at( frameNum );
+ Q_ASSERT( frame );
+ return new KWCreateFrameCommand( QString::null, frame );
+}
+
+KCommand * KWFrameSet::anchoredObjectDeleteCommand( int frameNum )
+{
+ KWFrame * frame = m_frames.at( frameNum );
+ Q_ASSERT( frame );
+ return new KWDeleteFrameCommand( QString::null, frame );
+}
+
+KWFrame * KWFrameSet::frameAtPos( double x, double y ) const
+{
+ KoPoint docPoint( x, y );
+ QPtrListIterator<KWFrame> frameIt = frameIterator();
+ for ( ; frameIt.current(); ++frameIt )
+ if ( frameIt.current()->contains( docPoint ) )
+ return frameIt.current();
+ return 0L;
+}
+
+KWFrame *KWFrameSet::frame( unsigned int num ) const
+{
+ // QPtrList sucks
+ return const_cast<KWFrameSet*>( this )->m_frames.at( num );
+}
+
+int KWFrameSet::frameFromPtr( KWFrame *frame )
+{
+ return m_frames.findRef( frame );
+}
+
+KWFrame * KWFrameSet::settingsFrame( const KWFrame* frame )
+{
+ if ( !frame->isCopy() )
+ return const_cast<KWFrame *>( frame );
+ KWFrame* lastRealFrame=0L;
+ QPtrListIterator<KWFrame> frameIt( frame->frameSet()->frameIterator() );
+ for ( ; frameIt.current(); ++frameIt )
+ {
+ KWFrame *curFrame = frameIt.current();
+ if ( curFrame == frame )
+ return lastRealFrame ? lastRealFrame : const_cast<KWFrame *>( frame );
+ if ( !lastRealFrame || !curFrame->isCopy() )
+ lastRealFrame = curFrame;
+ }
+ return const_cast<KWFrame *>( frame ); //fallback, should never happen
+}
+
+void KWFrameSet::updateFrames( int flags )
+{
+ if ( m_frames.isEmpty() )
+ return; // No frames. This happens when the frameset is deleted (still exists for undo/redo)
+
+ // Not visible ? Don't bother then.
+ if ( !isVisible() )
+ return;
+
+ //kdDebug(32001) << "KWFrameSet::updateFrames " << this << " " << name() << endl;
+
+ if ( flags & UpdateFramesInPage ) {
+ // For each of our frames, clear old list of frames on top, and grab min/max page nums
+ m_firstPage = m_frames.first()->pageNumber(); // we know m_frames is not empty here
+ int lastPage = m_firstPage;
+ QPtrListIterator<KWFrame> fIt( frameIterator() );
+ for ( ; fIt.current(); ++fIt ) {
+ int pg = fIt.current()->pageNumber();
+ m_firstPage = KMIN( m_firstPage, pg );
+ lastPage = KMAX( lastPage, pg );
+ }
+ //kdDebug(32001) << "firstPage=" << m_firstPage << " lastPage=" << lastPage << endl;
+
+ // Prepare the m_framesInPage structure
+ int oldSize = m_framesInPage.size();
+ m_framesInPage.resize( lastPage - m_firstPage + 1 );
+ // Clear the old elements
+ int oldElements = KMIN( oldSize, (int)m_framesInPage.size() );
+ for ( int i = 0 ; i < oldElements ; ++i )
+ m_framesInPage[i]->clear();
+ // Initialize the new elements.
+ for ( int i = oldElements ; i < (int)m_framesInPage.size() ; ++i )
+ m_framesInPage.insert( i, new QPtrList<KWFrame>() );
+
+ // Iterate over m_frames again, to fill the m_framesInPage array
+ fIt.toFirst();
+ for ( ; fIt.current(); ++fIt ) {
+ int pg = fIt.current()->pageNumber();
+ Q_ASSERT( pg <= lastPage );
+ m_framesInPage[pg - m_firstPage]->append( fIt.current() );
+ }
+ }
+
+ if ( isFloating() )
+ {
+ //kdDebug(32001) << "KWFrameSet::updateFrames " << name() << " is floating" << endl;
+ QPtrListIterator<KWFrame> frameIt = frameIterator();
+ int frameNum = 0;
+ // At the moment there's only one anchor per frameset
+ //for ( ; frameIt.current(); ++frameIt, ++frameNum )
+ {
+ KWAnchor * anchor = findAnchor( frameNum );
+ //kdDebug(32001) << "KWFrameSet::updateFrames anchor=" << anchor << endl;
+ if ( anchor )
+ anchor->resize();
+ }
+ }
+}
+
+bool KWFrameSet::isPaintedBy( KWFrameSet* fs ) const
+{
+ if ( fs == this )
+ return true;
+ if ( isFloating() )
+ {
+ KWFrameSet* parentFs = anchorFrameset();
+ if ( parentFs && parentFs->isPaintedBy( fs ) )
+ return true;
+ }
+ if ( groupmanager() )
+ {
+ if ( groupmanager()->isPaintedBy( fs ) )
+ return true;
+ }
+ return false;
+}
+
+const QPtrList<KWFrame> & KWFrameSet::framesInPage( int pageNum ) const
+{
+ if ( pageNum < m_firstPage || pageNum >= (int)m_framesInPage.size() + m_firstPage )
+ {
+#ifdef DEBUG_DTI
+ kdWarning(32002) << name() << " framesInPage called for pageNum=" << pageNum << ". "
+ << " Min value: " << m_firstPage
+ << " Max value: " << m_framesInPage.size() + m_firstPage - 1 << endl;
+#endif
+ return m_emptyList; // QPtrList<KWFrame>() doesn't work, it's a temporary
+ }
+ return * m_framesInPage[pageNum - m_firstPage];
+}
+
+void KWFrameSet::drawContents( QPainter *p, const QRect & crect, const QColorGroup &cg,
+ bool onlyChanged, bool resetChanged,
+ KWFrameSetEdit *edit, KWViewMode *viewMode,
+ KWFrameViewManager *frameViewManager )
+{
+#ifdef DEBUG_DRAW
+ kdDebug(32001) << "\nKWFrameSet::drawContents " << this << " " << name()
+ << " onlyChanged=" << onlyChanged << " resetChanged=" << resetChanged
+ << " crect= " << crect
+ << endl;
+#endif
+ if ( !viewMode->isTextModeFrameset( this ) )
+ {
+ QPtrListIterator<KWFrame> frameIt( frameIterator() );
+ KWFrame * lastRealFrame = 0L;
+ //double lastRealFrameTop = 0;
+ //double totalHeight = 0; // in pt, to avoid accumulating rounding errors
+ for ( ; frameIt.current(); )
+ {
+ KWFrame *frame = frameIt.current();
+ ++frameIt; // Point to the next one, to detect "last copy"
+ // The settings come from this frame
+ KWFrame * settingsFrame = ( frame->isCopy() && lastRealFrame ) ? lastRealFrame : frame;
+ bool lastCopy = !frameIt.current() || !frameIt.current()->isCopy();
+ drawFrameAndBorders( frame, p, crect, cg, onlyChanged,
+ // Only reset the changed flag in the last copy of a given frame (#60678)
+ resetChanged && lastCopy,
+ edit,
+ viewMode, settingsFrame, true /*transparency & double-buffering*/ );
+ if(viewMode->drawSelections() && frameViewManager) {
+ KWFrameView* view = frameViewManager->view(frame);
+ if(view)
+ view->paintFrameAttributes(p, crect, viewMode, m_doc);
+ }
+
+ if ( !lastRealFrame || !frame->isCopy() )
+ {
+ lastRealFrame = frame;
+ //lastRealFrameTop = totalHeight;
+ }
+ //totalHeight += frame->innerHeight();
+ }
+ }
+ else { // Text view mode
+ QRect normalRect = viewMode->viewToNormal(crect);
+ drawFrame( 0L /*frame*/, p, normalRect, crect, QPoint(KWViewModeText::OFFSET, 0),
+ 0L /*settingsFrame*/, cg, onlyChanged, resetChanged, edit, viewMode, true );
+ }
+}
+
+void KWFrameSet::drawFrameAndBorders( KWFrame *frame,
+ QPainter *painter, const QRect &crect,
+ const QColorGroup &cg, bool onlyChanged, bool resetChanged,
+ KWFrameSetEdit *edit, KWViewMode *viewMode,
+ KWFrame *settingsFrame, bool drawUnderlyingFrames )
+{
+ if ( !frame->isValid() )
+ {
+ kdDebug(32002) << "KWFrameSet::drawFrameAndBorders " << name() << " frame " << frameFromPtr( frame ) << " " << frame << " isn't valid" << endl;
+ return;
+ }
+
+ QRect normalOuterFrameRect( frame->outerRect( viewMode ) );
+ QRect outerFrameRect( viewMode->normalToView( normalOuterFrameRect ) );
+ QRect outerCRect = crect.intersect( outerFrameRect );
+#ifdef DEBUG_DRAW
+ kdDebug(32001) << "KWFrameSet::drawFrameAndBorders " << name() << " frame " << frameFromPtr( frame ) << " " << *frame << endl;
+ kdDebug(32001) << " (outer) normalFrameRect=" << normalOuterFrameRect << " frameRect=" << outerFrameRect << endl;
+ kdDebug(32001) << " crect=" << crect << " intersec=" << outerCRect << " todraw=" << !outerCRect.isEmpty() << endl;
+#endif
+ if ( !outerCRect.isEmpty() )
+ {
+ // Determine settingsFrame if not passed (for speedup)
+ if ( !settingsFrame )
+ settingsFrame = this->settingsFrame( frame );
+
+ QRect normalInnerFrameRect( m_doc->zoomRect( frame->innerRect() ) );
+ QRect innerFrameRect( viewMode->normalToView( normalInnerFrameRect ) );
+
+ // This translates the coordinates in the document contents
+ // ( frame and r are up to here in this system )
+ // into the frame's own coordinate system.
+ int offsetX = normalInnerFrameRect.left();
+ int offsetY = normalInnerFrameRect.top() - m_doc->zoomItY( frame->internalY() );
+
+ QRect innerCRect = outerCRect.intersect( innerFrameRect );
+ if ( !innerCRect.isEmpty() )
+ {
+ QRect fcrect = viewMode->viewToNormal( innerCRect );
+#ifdef DEBUG_DRAW
+ kdDebug(32001) << " (inner) normalFrameRect=" << normalInnerFrameRect << " frameRect=" << innerFrameRect << endl;
+ //kdDebug(32001) << " crect after view-to-normal:" << fcrect << "." << " Will move by (" << -offsetX << ", -(" << normalInnerFrameRect.top() << "-" << m_doc->zoomItY(frame->internalY()) << ") == " << -offsetY << ")." << endl;
+#endif
+ fcrect.moveBy( -offsetX, -offsetY );
+ Q_ASSERT( fcrect.x() >= 0 );
+ Q_ASSERT( fcrect.y() >= 0 );
+
+ // fcrect is now the portion of the frame to be drawn,
+ // in the frame's coordinates and in pixels
+#ifdef DEBUG_DRAW
+ kdDebug(32001) << "KWFrameSet::drawFrameAndBorders in frame coords:" << fcrect << ". Will translate painter by intersec-fcrect: " << innerCRect.x()-fcrect.x() << "," << innerCRect.y()-fcrect.y() << "." << endl;
+#endif
+ QRegion reg;
+ if ( drawUnderlyingFrames )
+ reg = frameClipRegion( painter, frame, outerCRect, viewMode );
+ else // false means we are being drawn _as_ an underlying frame, so no clipping!
+ reg = painter->xForm( outerCRect );
+ if ( !reg.isEmpty() )
+ {
+ painter->save();
+ painter->setClipRegion( reg );
+
+ drawFrame( frame, painter, fcrect, outerCRect,
+ innerCRect.topLeft() - fcrect.topLeft(), // This assume that viewToNormal() is only a translation
+ settingsFrame, cg, onlyChanged, resetChanged,
+ edit, viewMode, drawUnderlyingFrames );
+
+ if( !groupmanager() ) // not for table cells
+ drawFrameBorder( painter, frame, settingsFrame, outerCRect, viewMode );
+ painter->restore();
+ }
+ }
+ }
+}
+
+void KWFrameSet::drawFrame( KWFrame *frame, QPainter *painter, const QRect &fcrect, const QRect &outerCRect,
+ const QPoint& translationOffset,
+ KWFrame *settingsFrame, const QColorGroup &cg, bool onlyChanged, bool resetChanged,
+ KWFrameSetEdit *edit, KWViewMode* viewMode, bool drawUnderlyingFrames )
+{
+ // In this method the painter is NOT translated yet. It's still in view coordinates.
+ if ( outerCRect.isEmpty() )
+ return;
+#ifdef DEBUG_DRAW
+ kdDebug(32001) << "\nKWFrameSet::drawFrame " << name() << " outerCRect=" << outerCRect << " frameCrect=" << fcrect << " drawUnderlyingFrames=" << drawUnderlyingFrames << endl;
+#endif
+ Q_ASSERT( fcrect.isValid() );
+
+ QColorGroup frameColorGroup( cg );
+ if ( settingsFrame ) // 0L in text viewmode
+ {
+ QBrush bgBrush( settingsFrame->backgroundColor() );
+ bgBrush.setColor( KWDocument::resolveBgColor( bgBrush.color(), painter ) );
+ frameColorGroup.setBrush( QColorGroup::Base, bgBrush );
+ }
+
+ if ( drawUnderlyingFrames && frame && frame->frameStack()) {
+ QValueList<KWFrame*> below = frame->frameStack()->framesBelow();
+ if ( !below.isEmpty() )
+ {
+ // Double-buffering - not when printing
+ QPainter* doubleBufPainter = painter;
+ QPixmap* pix = 0L;
+ if ( painter->device()->devType() != QInternal::Printer )
+ {
+ pix = m_doc->doubleBufferPixmap( outerCRect.size() );
+ doubleBufPainter = new QPainter;
+ doubleBufPainter->begin( pix );
+ // Initialize the pixmap to the page background color
+ // (if the frame is over the page margins, no underlying frame will paint anything there)
+ doubleBufPainter->fillRect( 0, 0, outerCRect.width(), outerCRect.height(), QApplication::palette().active().brush( QColorGroup::Base ) );
+
+ // The double-buffer pixmap has (0,0) at outerCRect.topLeft(), so we need to
+ // translate the double-buffer painter; drawFrameAndBorders will draw using view coordinates.
+ doubleBufPainter->translate( -outerCRect.x(), -outerCRect.y() );
+#ifdef DEBUG_DRAW
+ // kdDebug(32001) << " ... using double buffering. Portion covered: " << outerCRect << endl;
+#endif
+ }
+
+ // Transparency handling
+#ifdef DEBUG_DRAW
+ kdDebug(32001) << " below: " << below.count() << endl;
+#endif
+ for (QValueListIterator<KWFrame*> it = below.begin(); it != below.end(); ++it )
+ {
+ KWFrame* f = (*it);
+
+#ifdef DEBUG_DRAW
+ kdDebug(32001) << " looking at frame below us: " << f->frameSet()->name() << " frame " << frameFromPtr( frame ) << endl;
+#endif
+ QRect viewFrameCRect = outerCRect.intersect( viewMode->normalToView( f->outerRect( viewMode ) ) );
+ if ( !viewFrameCRect.isEmpty() )
+ {
+#ifdef DEBUG_DRAW
+ kdDebug(32001) << " viewFrameRect=" << viewFrameCRect << " calling drawFrameAndBorders." << endl;
+#endif
+ f->frameSet()->drawFrameAndBorders( f, doubleBufPainter, viewFrameCRect, cg,
+ false, resetChanged, edit, viewMode, 0L, false );
+ }
+ }
+
+ if ( frame->paddingLeft() || frame->paddingTop() || frame->paddingRight() || frame->paddingBottom() )
+ drawPadding( frame, doubleBufPainter, outerCRect, cg, viewMode );
+ doubleBufPainter->save();
+#ifdef DEBUG_DRAW
+ kdDebug(32001) << " translating by " << translationOffset.x() << ", " << translationOffset.y() << " before drawFrameContents" << endl;
+#endif
+ doubleBufPainter->translate( translationOffset.x(), translationOffset.y() ); // This assume that viewToNormal() is only a translation
+ // We can't "repaint changed parags only" if we just drew the underlying frames, hence the "false"
+ drawFrameContents( frame, doubleBufPainter, fcrect, frameColorGroup, false, resetChanged, edit, viewMode );
+ doubleBufPainter->restore();
+
+ if ( painter->device()->devType() != QInternal::Printer )
+ {
+ doubleBufPainter->end();
+#ifdef DEBUG_DRAW
+ kdDebug(32001) << " painting double-buf pixmap at position " << outerCRect.topLeft() << " (real painter pos:" << painter->xForm( outerCRect.topLeft() ) << ")" << endl;
+#endif
+ painter->drawPixmap( outerCRect.topLeft(), *pix );
+ delete doubleBufPainter;
+ }
+ return; // done! :)
+ }
+ else
+ {
+ // nothing below? paint a bg color then
+ frameColorGroup.setBrush( QColorGroup::Base, m_doc->defaultBgColor( painter ) );
+ }
+ }
+ if ( frame && (frame->paddingLeft() || frame->paddingTop() ||
+ frame->paddingRight() || frame->paddingBottom()) )
+ drawPadding( frame, painter, outerCRect, cg, viewMode );
+ painter->save();
+ painter->translate( translationOffset.x(), translationOffset.y() );
+
+ drawFrameContents( frame, painter, fcrect, frameColorGroup, onlyChanged, resetChanged, edit, viewMode );
+ painter->restore();
+}
+
+void KWFrameSet::drawFrameContents( KWFrame *, QPainter *, const QRect &,
+ const QColorGroup &, bool, bool, KWFrameSetEdit*, KWViewMode * )
+{
+ kdWarning() << "Default implementation of drawFrameContents called for " << className() << " " << this << " " << name() << kdBacktrace();
+}
+
+void KWFrameSet::saveCommon( QDomElement &parentElem, bool saveFrames )
+{
+ if ( m_frames.isEmpty() ) // Deleted frameset -> don't save
+ return;
+
+ // Save all the common attributes for framesets.
+ parentElem.setAttribute( "frameType", static_cast<int>( type() ) );
+ parentElem.setAttribute( "frameInfo", static_cast<int>( m_info ) );
+ parentElem.setAttribute( "name", m_name );
+ parentElem.setAttribute( "visible", static_cast<int>( m_visible ) );
+ parentElem.setAttribute( "protectSize", static_cast<int>( m_protectSize ) );
+ if ( saveFrames )
+ {
+ QPtrListIterator<KWFrame> frameIt = frameIterator();
+ for ( ; frameIt.current(); ++frameIt )
+ {
+ KWFrame *frame = frameIt.current();
+ QDomElement frameElem = parentElem.ownerDocument().createElement( "FRAME" );
+ parentElem.appendChild( frameElem );
+
+ frame->save( frameElem );
+
+ if(m_doc->processingType() == KWDocument::WP) {
+ // Assume that all header/footer frames in the same frameset are
+ // perfect copies. This might not be the case some day though.
+ if(frameSetInfo() == FI_FIRST_HEADER ||
+ frameSetInfo() == FI_EVEN_HEADER ||
+ frameSetInfo() == FI_ODD_HEADER ||
+ frameSetInfo() == FI_FIRST_FOOTER ||
+ frameSetInfo() == FI_EVEN_FOOTER ||
+ frameSetInfo() == FI_ODD_FOOTER ||
+ frameSetInfo() == FI_FOOTNOTE) break;
+ }
+ }
+ }
+}
+
+//
+// This function is intended as a helper for all the derived classes. It reads
+// in all the attributes common to all framesets and loads all frames.
+//
+void KWFrameSet::load( QDomElement &framesetElem, bool loadFrames )
+{
+ m_info = static_cast<KWFrameSet::Info>( KWDocument::getAttribute( framesetElem, "frameInfo", KWFrameSet::FI_BODY ) );
+ m_visible = static_cast<bool>( KWDocument::getAttribute( framesetElem, "visible", true ) );
+ m_protectSize=static_cast<bool>( KWDocument::getAttribute( framesetElem, "protectSize", false ) );
+ if ( loadFrames )
+ {
+ // <FRAME>
+ QDomElement frameElem = framesetElem.firstChild().toElement();
+ for ( ; !frameElem.isNull() ; frameElem = frameElem.nextSibling().toElement() )
+ {
+ if ( frameElem.tagName() == "FRAME" )
+ {
+ KoRect rect;
+ rect.setLeft( KWDocument::getAttribute( frameElem, "left", 0.0 ) );
+ rect.setTop( KWDocument::getAttribute( frameElem, "top", 0.0 ) );
+ rect.setRight( KWDocument::getAttribute( frameElem, "right", 0.0 ) );
+ rect.setBottom( KWDocument::getAttribute( frameElem, "bottom", 0.0 ) );
+ KWFrame * frame = new KWFrame(this, rect.x(), rect.y(), rect.width(), rect.height() );
+ frame->load( frameElem, this, m_doc->syntaxVersion() );
+ addFrame( frame, false );
+ m_doc->progressItemLoaded();
+ }
+ }
+ }
+}
+
+KWFrame* KWFrameSet::loadOasisFrame( const QDomElement& tag, KoOasisContext& context )
+{
+ double width = 100;
+ if ( tag.hasAttributeNS( KoXmlNS::svg, "width" ) ) { // fixed width
+ // TODO handle percentage (of enclosing table/frame/page)
+ width = KoUnit::parseValue( tag.attributeNS( KoXmlNS::svg, "width", QString::null ) );
+ } else if ( tag.hasAttributeNS( KoXmlNS::fo, "min-width" ) ) {
+ // min-width is not supported in KWord. Let's use it as a fixed width.
+ width = KoUnit::parseValue( tag.attributeNS( KoXmlNS::fo, "min-width", QString::null ) );
+ } else {
+ kdWarning(32001) << "Error in frame " << tag.tagName() << " " << tag.attributeNS( KoXmlNS::draw, "name", QString::null ) << " : neither width nor min-width specified!" << endl;
+ }
+ double height = 100;
+ if ( tag.hasAttributeNS( KoXmlNS::svg, "height" ) ) { // fixed height
+ // TODO handle percentage (of enclosing table/frame/page)
+ height = KoUnit::parseValue( tag.attributeNS( KoXmlNS::svg, "height", QString::null ) );
+ }
+ //kdDebug(32001) << k_funcinfo << "width=" << width << " height=" << height << " pt" << endl;
+
+ KWFrame * frame = new KWFrame(this,
+ KoUnit::parseValue( tag.attributeNS( KoXmlNS::svg, "x", QString::null ) ),
+ KoUnit::parseValue( tag.attributeNS( KoXmlNS::svg, "y", QString::null ) ),
+ width, height );
+
+ frame->setZOrder( tag.attributeNS( KoXmlNS::draw, "z-index", QString::null ).toInt() );
+ // Copy-frames.
+ // We currently ignore the value of the copy-of attribute. It probably needs to
+ // be handled like chain-next-name (kwtextframeset.cc) but for all types of frameset.
+ frame->setCopy( tag.hasAttributeNS( KoXmlNS::draw, "copy-of" ) );
+ frame->loadCommonOasisProperties( context, this, "graphic" );
+
+ addFrame( frame, false );
+
+ // Protect (OASIS 14.27.7, also in OO-1.1)
+ // A frame with protected contents means that the frameset is protected (makes sense)
+ // A frame with protected size means that the frameset is size-protected (hmm, kword did it that way)
+ // TODO implement position protection
+ QString protectList = context.styleStack().attributeNS( KoXmlNS::style, "protect" );
+ if ( protectList.contains( "content" ) )
+ setProtectContent( true );
+ if ( protectList.contains( "size" ) )
+ m_protectSize = true;
+
+ // TODO m_visible ? User-toggeable or internal?
+
+ return frame;
+}
+
+void KWFrameSet::setVisible( bool v )
+{
+ m_visible = v;
+ if ( m_visible )
+ // updateFrames was disabled while we were invisible
+ updateFrames();
+}
+
+bool KWFrameSet::isVisible( KWViewMode* viewMode ) const
+{
+ if ( !m_visible || m_frames.isEmpty() )
+ return false;
+ if ( isAHeader() && !m_doc->isHeaderVisible() )
+ return false;
+ if ( isAFooter() && !m_doc->isFooterVisible() )
+ return false;
+ if ( viewMode && !viewMode->isFrameSetVisible(this) )
+ return false;
+ if ( isFloating() && !anchorFrameset()->isVisible( viewMode ) )
+ return false;
+
+ KoHFType ht = m_doc != 0 ? m_doc->headerType(): HF_FIRST_DIFF;
+ KoHFType ft = m_doc != 0 ? m_doc->footerType(): HF_FIRST_DIFF;
+ switch( m_info )
+ {
+ case FI_FIRST_HEADER:
+ return ( ht == HF_FIRST_DIFF || ht == HF_FIRST_EO_DIFF );
+ case FI_ODD_HEADER:
+ return true;
+ case FI_EVEN_HEADER:
+ return ( ht == HF_EO_DIFF || ht == HF_FIRST_EO_DIFF );
+ case FI_FIRST_FOOTER:
+ return ( ft == HF_FIRST_DIFF || ft == HF_FIRST_EO_DIFF );
+ case FI_ODD_FOOTER:
+ return true;
+ case FI_EVEN_FOOTER:
+ return ( ft == HF_EO_DIFF || ft == HF_FIRST_EO_DIFF );
+ default:
+ return true;
+ }
+}
+
+bool KWFrameSet::isAHeader() const
+{
+ return ( m_info == FI_FIRST_HEADER || m_info == FI_ODD_HEADER || m_info == FI_EVEN_HEADER );
+}
+
+bool KWFrameSet::isAFooter() const
+{
+ return ( m_info == FI_FIRST_FOOTER || m_info == FI_ODD_FOOTER || m_info == FI_EVEN_FOOTER );
+}
+
+bool KWFrameSet::isFootEndNote() const
+{
+ return m_info == FI_FOOTNOTE;
+}
+
+bool KWFrameSet::isMainFrameset() const
+{
+ return ( m_doc && m_doc->processingType() == KWDocument::WP &&
+ m_doc->frameSet( 0 ) == this );
+}
+
+bool KWFrameSet::isMoveable() const
+{
+ if ( isHeaderOrFooter() )
+ return false;
+ return !isMainFrameset() && !isFloating();
+}
+
+const char* KWFrameSet::headerFooterTag() const
+{
+ switch ( m_info ) {
+ case KWFrameSet::FI_ODD_HEADER:
+ return "style:header";
+ case KWFrameSet::FI_EVEN_HEADER:
+ return "style:header-left";
+ case KWFrameSet::FI_ODD_FOOTER:
+ return "style:footer";
+ case KWFrameSet::FI_EVEN_FOOTER:
+ return "style:footer-left";
+ case KWFrameSet::FI_FIRST_HEADER:
+ return "style:header-first"; // NOT OASIS COMPLIANT
+ case KWFrameSet::FI_FIRST_FOOTER:
+ return "style:footer-first"; // NOT OASIS COMPLIANT
+ default: // shouldn't be called for body or footnote
+ return 0;
+ }
+}
+
+void KWFrameSet::finalize()
+{
+ //kdDebug(32001) << "KWFrameSet::finalize ( calls updateFrames + zoom ) " << this << endl;
+ updateFrames();
+}
+
+QRegion KWFrameSet::frameClipRegion( QPainter * painter, KWFrame *frame, const QRect & crect,
+ KWViewMode * viewMode )
+{
+// KWDocument * doc = kWordDocument();
+ QRect rc = painter->xForm( crect );
+#ifdef DEBUG_DRAW
+ //kdDebug(32002) << "KWFrameSet::frameClipRegion rc initially " << rc << endl;
+#endif
+
+ Q_ASSERT( frame );
+#if 0 // done later
+ if ( clipFrame )
+ {
+ rc &= painter->xForm( viewMode->normalToView( doc->zoomRect( (*frame) ) ) ); // intersect
+#ifdef DEBUG_DRAW
+ kdDebug(32002) << "KWFrameSet::frameClipRegion frame=" << *frame
+ << " clip region rect=" << rc
+ << " rc.isEmpty()=" << rc.isEmpty() << endl;
+#endif
+ }
+#endif
+ if ( !rc.isEmpty() )
+ {
+ QRegion reg( rc );
+ // This breaks when a frame is under another one, it still appears if !onlyChanged.
+ // cvs log says this is about frame borders... hmm.
+ /// ### if ( onlyChanged )
+
+ Q_ASSERT( frame->frameStack() );
+
+ QValueList<KWFrame *> onTop = frame->frameStack()->framesOnTop();
+ for (QValueListIterator<KWFrame*> fIt = onTop.begin(); fIt != onTop.end(); ++fIt )
+ {
+ KWFrame* frameOnTop = (*fIt);
+ Q_ASSERT( frameOnTop->frameSet() );
+ QRect r = painter->xForm( viewMode->normalToView( frameOnTop->outerRect( viewMode ) ) );
+#ifdef DEBUG_DRAW
+ //kdDebug(32002) << "frameClipRegion subtract rect "<< r << endl;
+#endif
+ reg -= r; // subtract
+ }
+#ifdef DEBUG_DRAW
+ //kdDebug(32002) << "KWFrameSet::frameClipRegion result:" << reg << endl;
+#endif
+ return reg;
+ }
+ return QRegion();
+}
+
+bool KWFrameSet::canRemovePage( int num )
+{
+ QPtrListIterator<KWFrame> frameIt( frameIterator() );
+ for ( ; frameIt.current(); ++frameIt )
+ {
+ KWFrame * frame = frameIt.current();
+ if ( frame->pageNumber() == num ) // ## TODO: use framesInPage, see KWTextFrameSet
+ {
+ // Ok, so we have a frame on that page -> we can't remove it unless it's a copied frame
+ if ( ! ( frame->isCopy() && frameIt.current() != m_frames.first() ) )
+ {
+ kdDebug(32001) << "KWFrameSet::canRemovePage " << name() << " frame on page " << num << " -> false" << endl;
+ return false;
+ }
+ }
+ }
+ return true;
+}
+
+void KWFrameSet::setFrameBehavior( KWFrame::FrameBehavior fb ) {
+ for(KWFrame *f=m_frames.first();f;f=m_frames.next())
+ f->setFrameBehavior(fb);
+}
+
+void KWFrameSet::setNewFrameBehavior( KWFrame::NewFrameBehavior nfb ) {
+ for(KWFrame *f=m_frames.first();f;f=m_frames.next())
+ f->setNewFrameBehavior(nfb);
+}
+
+// ## this should pass the viewmode as argument, probably.
+bool KWFrameSet::isFrameAtPos( const KWFrame* frame, const QPoint& point, bool borderOfFrameOnly) const {
+ QRect outerRect( frame->outerRect( m_doc->layoutViewMode() ) );
+ // Give the user a bit of margin for clicking on it :)
+ const int margin = 2;
+ outerRect.rLeft() -= margin;
+ outerRect.rTop() -= margin;
+ outerRect.rRight() += margin;
+ outerRect.rBottom() += margin;
+ if ( outerRect.contains( point ) ) {
+ if(borderOfFrameOnly) {
+ QRect innerRect( m_doc->zoomRect( *frame ) );
+ innerRect.rLeft() += margin;
+ innerRect.rTop() += margin;
+ innerRect.rRight() -= margin;
+ innerRect.rBottom() -= margin;
+ return (!innerRect.contains(point) );
+ }
+ return true;
+ }
+ return false;
+}
+
+void KWFrameSet::setZOrder()
+{
+ //kdDebug(32001) << "KWFrameSet::setZOrder (to max) " << name() << endl;
+ QPtrListIterator<KWFrame> fit = frameIterator();
+ for ( ; fit.current() ; ++fit )
+ fit.current()->setZOrder( m_doc->maxZOrder( fit.current()->pageNumber(m_doc) ) + 1 );
+}
+
+void KWFrameSet::setName( const QString &name )
+{
+ m_name = name;
+ emit sigNameChanged(this);
+}
+
+#ifndef NDEBUG
+#include "KWFrameViewManager.h"
+#include "KWFrameView.h"
+void KWFrameSet::printDebug()
+{
+ static const char * typeFrameset[] = { "base", "txt", "picture", "part", "formula", "clipart",
+ "6", "7", "8", "9", "table",
+ "ERROR" };
+ static const char * infoFrameset[] = { "body", "first header", "even headers", "odd headers",
+ "first footer", "even footers", "odd footers", "footnote", "ERROR" };
+ static const char * frameBh[] = { "AutoExtendFrame", "AutoCreateNewFrame", "Ignore", "ERROR" };
+ static const char * newFrameBh[] = { "Reconnect", "NoFollowup", "Copy" };
+ static const char * runaround[] = { "No Runaround", "Bounding Rect", "Skip", "ERROR" };
+ static const char * runaroundSide[] = { "Biggest", "Left", "Right", "ERROR" };
+
+ KWFrameViewManager *fvm = 0;
+ if ( !m_doc->getAllViews().isEmpty() ) {
+ KWView *view = m_doc->getAllViews().first();
+ if(view)
+ fvm = view->frameViewManager();
+ }
+
+ kdDebug() << " | Visible: " << isVisible() << endl;
+ kdDebug() << " | Type: " << typeFrameset[ type() ] << endl;
+ kdDebug() << " | Info: " << infoFrameset[ frameSetInfo() ] << endl;
+ kdDebug() << " | Floating: " << isFloating() << endl;
+ kdDebug() << " | Frames in page array: " << endl;
+ for ( uint i = 0 ; i < m_framesInPage.size() ; ++i )
+ {
+ QPtrListIterator<KWFrame> it( *m_framesInPage[i] );
+ int pgNum = i + m_firstPage;
+ for ( ; it.current() ; ++it )
+ kdDebug() << " | " << pgNum << ": " << it.current() << " " << *it.current()
+ << " internalY=" << it.current()->internalY() << "pt "
+ << " (in LU pix:" << m_doc->ptToLayoutUnitPixY( it.current()->internalY() ) << ")"
+ << " innerHeight=" << it.current()->innerHeight()
+ << " (in LU pix:" << m_doc->ptToLayoutUnitPixY( it.current()->innerHeight() ) << ")"
+ << endl;
+ }
+
+ QPtrListIterator<KWFrame> frameIt = frameIterator();
+ for ( unsigned int j = 0; frameIt.current(); ++frameIt, ++j ) {
+ KWFrame * frame = frameIt.current();
+ QCString copy = frame->isCopy() ? "[copy]" : "";
+ kdDebug() << " +-- Frame " << j << " of "<< frameCount() << " (" << frame << ") " << copy << endl;
+ printDebug( frame );
+ kdDebug() << " Rectangle : " << frame->x() << "," << frame->y() << " " << frame->width() << "x" << frame->height() << endl;
+ kdDebug() << " RunAround: "<< runaround[ frame->runAround() ] << " side:" << runaroundSide[ frame->runAroundSide() ]<< endl;
+ kdDebug() << " FrameBehavior: "<< frameBh[ frame->frameBehavior() ] << endl;
+ kdDebug() << " NewFrameBehavior: "<< newFrameBh[ frame->newFrameBehavior() ] << endl;
+ QColor col = frame->backgroundColor().color();
+ kdDebug() << " BackgroundColor: "<< ( col.isValid() ? col.name().latin1() : "(default)" ) << endl;
+ kdDebug() << " SheetSide "<< frame->sheetSide() << endl;
+ kdDebug() << " Z Order: " << frame->zOrder() << endl;
+
+ if( frame->frameStack() ) {
+ QValueList<KWFrame*> onTop = frame->frameStack()->framesOnTop();
+ QValueList<KWFrame*> below = frame->frameStack()->framesBelow();
+
+ kdDebug() << " Frames below: " << below.count()
+ << ", frames on top: " << onTop.count() << endl;
+ }
+ else
+ kdDebug() << " no frameStack set." << endl;
+ kdDebug() << " minFrameHeight "<< frame->minimumFrameHeight() << endl;
+ QString page = pageManager() && pageManager()->pageCount() > 0 ? QString::number(frame->pageNumber()) : " [waiting for pages to be created]";
+
+ KWFrameView *fv = 0;
+ if(fvm) fv = fvm->view(frame);
+ if(fv && fv->selected())
+ kdDebug() << " * Page "<< page << endl;
+ else
+ kdDebug() << " Page "<< page << endl;
+ }
+}
+
+void KWFrameSet::printDebug( KWFrame * )
+{
+}
+
+#endif
+
+#include "KWFrameSet.moc"