kword

KWFrameList.cpp

00001 /* This file is part of the KOffice project
00002  * Copyright (C) 2005 Thomas Zander <zander@kde.org>
00003  *
00004  * This library is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU Library General Public
00006  * License as published by the Free Software Foundation; version 2.
00007 
00008  * This library is distributed in the hope that it will be useful,
00009  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00010  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00011  * Library General Public License for more details.
00012  *
00013  * You should have received a copy of the GNU Library General Public License
00014  * along with this library; see the file COPYING.LIB.  If not, write to
00015  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00016  * Boston, MA 02110-1301, USA.
00017  */
00018 #include <algorithm>
00019 #include "KWFrameList.h"
00020 #include "KWFrame.h"
00021 #include "KWFrameSet.h"
00022 #include "KWTextFrameSet.h"
00023 #include "KWDocument.h"
00024 #include "KWViewMode.h"
00025 #include "KWPageManager.h"
00026 
00027 //#define DEBUG_SPEED
00028 
00029 KWFrameList::KWFrameList(KWDocument *doc, KWFrame *theFrame) {
00030     m_doc = doc;
00031     m_frame = theFrame;
00032 
00033     update();
00034 }
00035 
00036 QValueList<KWFrame *> KWFrameList::framesBelow() const {
00037     QValueList<KWFrame *> frames;
00038 //kdDebug() << "framesBelow " << endl;
00039 
00040     // Copy until we find m_frame
00041     for ( QValueVector<KWFrame*>::const_iterator it = m_frames.begin(), end = m_frames.end(); it != end && *it != m_frame; ++it) {
00042         frames.append( *it );
00043     }
00044 
00045     return  frames;
00046 }
00047 
00048 QValueList<KWFrame *> KWFrameList::framesOnTop() const {
00049 //kdDebug() << "framesOnTop " << endl;
00050     QValueList<KWFrame *> frames;
00051 
00052     // Copy from m_frame to the end
00053     bool found = false;
00054     for ( QValueVector<KWFrame*>::const_iterator it = m_frames.begin(), end = m_frames.end(); it != end; ++it) {
00055         KWFrame* frame = *it;
00056         if ( found ) {
00057             Q_ASSERT( !frame->frameSet()->isFloating() );
00058             frames.append( frame );
00059         }
00060         else if ( frame == m_frame )
00061             found = true;
00062     }
00063 
00064     return frames;
00065 }
00066 
00067 void KWFrameList::setFrames(const QPtrList<KWFrame> &frames) {
00068     // kdDebug(31001) << "KWFrameList::setFrames for " << m_frame->frameSet()->name() << endl;
00069     m_frames.clear();
00070     if ( m_doc->layoutViewMode() && !m_doc->layoutViewMode()->hasFrames() )
00071         return;
00072 
00073     QPtrList<KWFrameSet> parentFramesets;
00074     KWFrameSet *fs = m_frame->frameSet();
00075     while(fs) {
00076         parentFramesets.append(fs);
00077         fs = (KWFrameSet*) fs->anchorFrameset();
00078     }
00079 
00080     // We now look at all other frames (in the same page)
00081     // to check for intersections. This is o(n^2), but with n small.
00082     QPtrListIterator<KWFrame> it( frames );
00083     for ( ; it.current() ; ++it )
00084     {
00085         KWFrame* daFrame = it.current();
00086         // kdDebug(32001) << "frame: " << daFrame->frameSet()->name() << endl;
00087         if ( m_frame == daFrame ) {
00088             m_frames.append( daFrame );
00089             continue;
00090         }
00091         // Skip 'daFrame' if it belongs to a table.
00092         // We trust that KWTableFrameSet will not make cells overlap ;)
00093         if ( m_frame->frameSet()->groupmanager() || daFrame->frameSet()->groupmanager() )
00094             continue;
00095         // Skip all frames from the parent frameset, if 'm_frame' is floating
00096         // ## might need a for loop for the case of inline-inside-inline,
00097         // or maybe calling isPaintedBy instead [depending on what should happen for tables]
00098         if ( daFrame->frameSet()->isFloating() &&
00099                 (parentFramesets.contains(daFrame->frameSet()->anchorFrameset()) ||
00100                  daFrame->frameSet()->isPaintedBy(m_frame->frameSet())) )
00101             continue;
00102         // Floating frames are not "on top", they are "inside".
00103         // They are not "below" anything either - the parent frameset is.
00104         if ( m_frame->frameSet()->isFloating() )
00105             continue;
00106         KoRect intersect = m_frame->intersect( daFrame->outerKoRect() );
00107         if ( !intersect.isEmpty() )
00108             m_frames.append( daFrame );
00109     }
00110     std::sort( m_frames.begin(), m_frames.end(), KWFrame::compareFrameZOrder );
00111 }
00112 
00113 void KWFrameList::updateAfterMove(int oldPageNum) {
00114     int pageNumber = m_doc->pageManager()->pageNumber(m_frame);
00115     updateZOrderFor(m_doc->framesInPage( pageNumber, false ));
00116 
00117     if (pageNumber != oldPageNum)
00118         updateZOrderFor(m_doc->framesInPage( oldPageNum, false ));
00119 }
00120 
00121 void KWFrameList::update() {
00122     int pageNumber = m_doc->pageManager()->pageNumber(m_frame);
00123     if(pageNumber == -1)
00124         return;
00125     updateZOrderFor(m_doc->framesInPage( pageNumber, false ));
00126 }
00127 
00128 void KWFrameList::updateZOrderFor(const QPtrList<KWFrame> &frames) {
00129 #ifdef DEBUG_SPEED
00130     kdDebug(32001) << "KWFrameList::updateZOrderFor " << frames.count() << " frames"<< endl;
00131     QTime dt;
00132     dt.start();
00133     int numberAdded = 0;
00134 #endif
00135 
00136     QPtrListIterator<KWFrame> iter(frames);
00137     while( iter.current() ) {
00138         KWFrame *frame = iter.current();
00139         Q_ASSERT( frame->frameStack() );
00140 
00141         frame->frameStack()->setFrames(frames);
00142 #ifdef DEBUG_SPEED
00143         numberAdded += frame->frameStack()->m_frames.count();
00144 #endif
00145         ++iter;
00146     }
00147 
00148 #ifdef DEBUG_SPEED
00149     kdDebug(32001) << "  updateZOrderFor took " << (float)(dt.elapsed()) / 1000 << " seconds, added " << numberAdded << " frames" << endl;
00150 #endif
00151 }
00152 
00153 // ****** statics ******
00154 KWFrameList *KWFrameList::getFirstFrameList(KWDocument *doc) {
00155     for (QPtrListIterator<KWFrameSet> fsit = doc->framesetsIterator(); fsit.current() ; ++fsit ) {
00156         KWFrame *frame = fsit.current()->frame(0);
00157         if (frame && frame->frameStack())
00158             return frame->frameStack();
00159     }
00160     return 0;
00161 }
00162 
00163 void KWFrameList::recalcFrames(KWDocument *doc, int pageFrom, int pageTo) {
00164     for(int i=pageTo; i >= pageFrom; i--) {
00165         QPtrList<KWFrame> framesOnPage = doc->framesInPage( i, false );
00166         KWFrame *f = framesOnPage.first();
00167         while(f) {
00168             Q_ASSERT(f->frameStack());
00169             f->frameStack()->setFrames(framesOnPage);
00170             f = framesOnPage.next();
00171         }
00172     }
00173 }
00174 
00175 void KWFrameList::recalcAllFrames(KWDocument *doc) {
00176     recalcFrames(doc, doc->startPage(), doc->lastPage());
00177 }
00178 
00179 void KWFrameList::createFrameList(KWFrame *f, KWDocument *doc) {
00180     Q_ASSERT(f);
00181     Q_ASSERT(doc);
00182     if(f->frameStack())
00183         return;
00184     f->setFrameStack(new KWFrameList(doc, f));
00185 }
00186 
00187 void KWFrameList::createFrameList(KWFrameSet *fs, KWDocument *doc, bool forceUpdate) {
00188     QPtrListIterator<KWFrame> iter( fs->frameIterator() );
00189     KWFrame *f = iter.current();
00190     while(f) {
00191         createFrameList(f, doc);
00192         if(forceUpdate)
00193             f->frameStack()->update();
00194         ++iter;
00195         f = iter.current();
00196     }
00197 }
KDE Home | KDE Accessibility Home | Description of Access Keys