kword

KWFrameViewManager.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 "KWDocument.h"
00019 #include "KWFrameViewManager.h"
00020 #include <KWFrameView.h>
00021 #include <KWFrame.h>
00022 #include <KWFrameSet.h>
00023 
00024 #include <kdebug.h>
00025 #include <kcursor.h>
00026 #include <qcursor.h>
00027 #include <qtimer.h>
00028 #include "qpopupmenu.h"
00029 #include <algorithm>
00030 
00031 KWFrameViewManager::KWFrameViewManager() : QObject() {
00032     setName("KWFrameViewManager");
00033     m_queueRequested = false;
00034     m_blockEvents = false;
00035 }
00036 
00037 KWFrameViewManager::KWFrameViewManager(KWDocument *doc) {
00038     m_queueRequested = false;
00039     m_blockEvents = true;
00040     QPtrListIterator<KWFrameSet> frameSets = doc->framesetsIterator();
00041     while(frameSets.current()) {
00042         slotFrameSetAdded(*frameSets);
00043         ++frameSets;
00044     }
00045     m_blockEvents = false;
00046     connect(doc, SIGNAL( sigFrameSetAdded(KWFrameSet*)), SLOT( slotFrameSetAdded(KWFrameSet*)));
00047     connect(doc, SIGNAL( sigFrameSetRemoved(KWFrameSet*)), SLOT( slotFrameSetRemoved(KWFrameSet*)));
00048     recalculateFrameCache();
00049 }
00050 
00051 KWFrameViewManager::~KWFrameViewManager() {
00052     QValueListIterator<FrameEvent *> events = m_frameEvents.begin();
00053     while(events != m_frameEvents.end()) {
00054         delete (*events);
00055         ++events;
00056     }
00057 }
00058 
00059 void KWFrameViewManager::addKWFramesListener(KWFramesListener *listener) {
00060     m_framesListener.append(listener);
00061 }
00062 void KWFrameViewManager::removeKWFramesListener(KWFramesListener *listener) {
00063     m_framesListener.remove(listener);
00064 }
00065 
00066 void KWFrameViewManager::slotFrameSetAdded(KWFrameSet *fs) {
00067     if(! m_blockEvents)
00068         m_frameEvents.append(new FrameEvent(FrameEvent::FrameSetAdded, fs));
00069     connect(fs, SIGNAL( sigFrameAdded(KWFrame*)), SLOT( slotFrameAdded(KWFrame *)));
00070     connect(fs, SIGNAL( sigFrameRemoved(KWFrame*)), SLOT( slotFrameRemoved(KWFrame *)));
00071     connect(fs, SIGNAL( sigNameChanged(KWFrameSet*)), SLOT( slotFrameSetRenamed(KWFrameSet *)));
00072     QPtrListIterator<KWFrame> frames = fs->frameIterator();
00073     while(frames.current()) {
00074         KWFrame *f = frames.current();
00075         slotFrameAdded(f);
00076         ++frames;
00077     }
00078     requestFireEvents();
00079 }
00080 void KWFrameViewManager::slotFrameSetRemoved(KWFrameSet *fs) {
00081     if(! m_blockEvents)
00082         m_frameEvents.append(new FrameEvent(FrameEvent::FrameSetRemoved, fs));
00083     disconnect(fs, SIGNAL( sigFrameAdded(KWFrame*)), this, SLOT( slotFrameAdded(KWFrame *)));
00084     disconnect(fs, SIGNAL( sigFrameRemoved(KWFrame*)), this, SLOT( slotFrameRemoved(KWFrame *)));
00085     disconnect(fs, SIGNAL( sigNameChanged(KWFrameSet*)), this, SLOT( slotFrameSetRenamed(KWFrameSet *)));
00086     QPtrListIterator<KWFrame> frames = fs->frameIterator();
00087     while(frames.current()) {
00088         KWFrame *f = frames.current();
00089         slotFrameRemoved(f);
00090         ++frames;
00091     }
00092     requestFireEvents();
00093 }
00094 void KWFrameViewManager::slotFrameAdded(KWFrame *f) {
00095     if(! m_blockEvents)
00096         m_frameEvents.append(new FrameEvent(FrameEvent::FrameAdded, f));
00097     m_frames.append(new KWFrameView(this, f));
00098     requestFireEvents();
00099 }
00100 void KWFrameViewManager::slotFrameRemoved(KWFrame *f) {
00101     if(! m_blockEvents)
00102         m_frameEvents.append(new FrameEvent(FrameEvent::FrameRemoved, f));
00103     QValueListIterator<KWFrameView *> frames = m_frames.begin();
00104     while(frames != m_frames.end()) {
00105         KWFrameView *fv = *frames;
00106         if(fv->frame() == f) {
00107             if(fv->selected())
00108                 m_frameEvents.append(new FrameEvent(FrameEvent::FrameSelectionChanged));
00109             m_frames.remove(frames);
00110             delete fv;
00111             break;
00112         }
00113         ++frames;
00114     }
00115     requestFireEvents();
00116 }
00117 void KWFrameViewManager::slotFrameMoved(KWFrame *f, double previousYPosition) {
00118     Q_UNUSED(previousYPosition); // to be used for the page caches to mark them dirty
00119     if(! m_blockEvents)
00120         m_frameEvents.append(new FrameEvent(FrameEvent::FrameMoved, f));
00121     // TODO; KWFrameList update??
00122     // update our caches..
00123     requestFireEvents();
00124 }
00125 void KWFrameViewManager::slotFrameResized(KWFrame *f) {
00126     if(! m_blockEvents)
00127         m_frameEvents.append(new FrameEvent(FrameEvent::FrameResized, f));
00128     // update our caches..
00129     requestFireEvents();
00130 }
00131 void KWFrameViewManager::slotFrameSelectionChanged() {
00132     if(! m_blockEvents)
00133         m_frameEvents.append(new FrameEvent(FrameEvent::FrameSelectionChanged));
00134     // update our caches..
00135     requestFireEvents();
00136 }
00137 
00138 void KWFrameViewManager::slotFrameSetRenamed(KWFrameSet *fs) {
00139     if(! m_blockEvents)
00140         m_frameEvents.append(new FrameEvent(FrameEvent::FrameSetRenamed, fs));
00141     requestFireEvents();
00142 }
00143 
00144 void KWFrameViewManager::requestFireEvents() {
00145     if(m_queueRequested && !m_blockEvents)
00146         return;
00147     m_queueRequested = true;
00148     QTimer::singleShot ( 0, this, SLOT(fireEvents()) );
00149 }
00150 
00151 void KWFrameViewManager::fireEvents() {
00152     m_queueRequested = false;
00153     if(m_frameEvents.isEmpty())
00154         return;
00155     recalculateFrameCache();
00156 
00157     QValueList<FrameEvent *> copy(m_frameEvents);
00158     m_frameEvents.clear();
00159 
00160     QValueList<KWFrame*> resizedFrames;
00161     QValueList<KWFrame*> movedFrames;
00162     QValueList<KWFramesListener *> listenersCopy(m_framesListener);
00163     bool selectionChangedFired=false;
00164 
00165     QValueListIterator<FrameEvent *> events = copy.begin();
00166     while(events != copy.end()) {
00167         FrameEvent *event = *events;
00168 
00169         // emit based.
00170         if(!selectionChangedFired && event->m_action == FrameEvent::FrameSelectionChanged) {
00171             emit sigFrameSelectionChanged();
00172             selectionChangedFired = true;  // only fire ones.
00173         } else if(event->m_action == FrameEvent::FrameSetRenamed) {
00174             QPtrListIterator<KWFrame> frames = event->m_frameSet->frameIterator();
00175             for(;frames.current();++frames) {
00176                 if(view(frames.current())->selected()) {
00177                     emit sigFrameSetRenamed();
00178                     break;
00179                 }
00180             }
00181         } else if(event->m_action == FrameEvent::FrameResized) {
00182             resizedFrames.append(event->m_frame);
00183         } else if(event->m_action == FrameEvent::FrameMoved) {
00184             movedFrames.append(event->m_frame);
00185         }
00186 
00187         // listener based
00188         QValueListIterator<KWFramesListener *> listeners = listenersCopy.begin();
00189         while(listeners != listenersCopy.end()) {
00190             if(event->m_action == FrameEvent::FrameRemoved)
00191                 (*listeners)->frameRemoved(event->m_frame);
00192             else if(event->m_action == FrameEvent::FrameAdded)
00193                 (*listeners)->frameAdded(event->m_frame);
00194             else if(event->m_action == FrameEvent::FrameSetRemoved)
00195                 (*listeners)->frameSetRemoved(event->m_frameSet);
00196             else if(event->m_action == FrameEvent::FrameSetAdded)
00197                 (*listeners)->frameSetAdded(event->m_frameSet);
00198             ++listeners;
00199         }
00200 
00201         delete event;
00202         events = copy.remove(events);
00203     }
00204     if(resizedFrames.count() > 0)
00205         emit sigFrameResized(resizedFrames);
00206     if(movedFrames.count() > 0)
00207         emit sigFrameMoved(movedFrames);
00208 }
00209 
00210 void KWFrameViewManager::recalculateFrameCache() {
00211     // TODO :) design and implement a cache...
00212     // list of frames sorted on y-coord, with an additional list containing a jump-index
00213     kdDebug(31001) << "recalculateFrameCache " << m_frames.count() << " frames are currently registred" << endl;
00214 }
00215 
00216 KWFrameView *KWFrameViewManager::view(const KoPoint &point, SelectionType selected, bool borderOnly) const {
00217     QValueVector<KWFrameView*> framesThatAreHit = framesAt(point, borderOnly);
00218     bool foundCycleFrame = false;
00219     QValueVector<KWFrameView*>::iterator sortedFrames = framesThatAreHit.begin();
00220     while(sortedFrames != framesThatAreHit.end()) {
00221         if(selected == nextUnselected) {
00222             if((*sortedFrames)->selected() )
00223                 foundCycleFrame = true;
00224             else if(foundCycleFrame && !(*sortedFrames)->selected() )
00225                 return *sortedFrames;
00226         }
00227         else if(selected == frameOnTop)
00228             return *sortedFrames;
00229         else { // not cycle, so simply a selected check.
00230             if((*sortedFrames)->selected() == (selected == KWFrameViewManager::selected ))
00231                 return *sortedFrames;
00232         }
00233         ++sortedFrames;
00234     }
00235     if(selected == nextUnselected && framesThatAreHit.count() > 0)
00236         return framesThatAreHit[0];
00237     return 0;
00238 }
00239 
00240 QValueVector<KWFrameView*> KWFrameViewManager::framesAt(const KoPoint &point, bool borderOnly) const {
00241     QValueVector<KWFrameView*> framesThatAreHit;
00242     // This is probably the slowest and worst way to do it, mark this for optimalisation!
00243     for(QValueListConstIterator<KWFrameView*> frames = m_frames.begin();
00244             frames != m_frames.end(); ++frames) {
00245         if(! (*frames)->frame()->frameSet()->isVisible())
00246             continue;
00247         if(borderOnly && (*frames)->isBorderHit(point) ||
00248                 !borderOnly && (*frames)->contains(point))
00249             framesThatAreHit.append(*frames);
00250     }
00251     // sort on z-ordering; top on first
00252     std::sort(framesThatAreHit.begin(), framesThatAreHit.end(), compareFrameViewZOrder);
00253     return framesThatAreHit;
00254 }
00255 
00256 KWFrameView *KWFrameViewManager::view(const KWFrame *frame) const {
00257     // This is probably the slowest and worst way to do it, mark this for optimalisation!
00258     QValueListConstIterator<KWFrameView*> frames = m_frames.begin();
00259     while(frames != m_frames.end()) {
00260         if((*frames)->frame() == frame)
00261             return *frames;
00262         ++frames;
00263     }
00264     return 0;
00265 }
00266 
00267 bool KWFrameViewManager::compareFrameViewZOrder(KWFrameView *f1, KWFrameView *f2) {
00268     return f1->frame()->zOrder() >= f2->frame()->zOrder();
00269 }
00270 
00271 QCursor KWFrameViewManager::mouseCursor( const KoPoint &point, int keyState ) const {
00272     KWFrameView *view = 0;
00273     QValueVector<KWFrameView*> framesThatAreHit = framesAt(point);
00274     QValueVector<KWFrameView*>::iterator sortedFrames = framesThatAreHit.begin();
00275     MouseMeaning meaning;
00276     while(sortedFrames != framesThatAreHit.end()) {
00277         meaning = (*sortedFrames)->mouseMeaning(point, keyState);
00278         if(meaning != MEANING_NONE) {
00279             view = (*sortedFrames);
00280             break;
00281         }
00282         ++sortedFrames;
00283     }
00284 
00285     if(view == 0)
00286         return QCursor(); // default arrow shape
00287 
00288     KWFrameSet*frameSet = view->frame()->frameSet();
00289     switch ( meaning ) {
00290         case MEANING_NONE:
00291             return Qt::ibeamCursor; // default cursor in margins
00292         case MEANING_MOUSE_INSIDE:
00293             return QCursor(); // default arrow shape
00294         case MEANING_MOUSE_INSIDE_TEXT:
00295             return Qt::ibeamCursor;
00296         case MEANING_MOUSE_OVER_LINK:
00297             return Qt::PointingHandCursor;
00298         case MEANING_MOUSE_OVER_FOOTNOTE:
00299             return Qt::PointingHandCursor;
00300         case MEANING_MOUSE_MOVE:
00301             return Qt::sizeAllCursor;
00302         case MEANING_MOUSE_SELECT:
00303             return KCursor::handCursor();
00304         case MEANING_ACTIVATE_PART:
00305             return KCursor::handCursor();
00306         case MEANING_TOPLEFT:
00307         case MEANING_BOTTOMRIGHT:
00308             return Qt::sizeFDiagCursor;
00309         case MEANING_LEFT:
00310         case MEANING_RIGHT:
00311             return Qt::sizeHorCursor;
00312         case MEANING_BOTTOMLEFT:
00313         case MEANING_TOPRIGHT:
00314             return Qt::sizeBDiagCursor;
00315         case MEANING_TOP:
00316         case MEANING_BOTTOM:
00317             if ( frameSet->isProtectSize() || frameSet->isMainFrameset())
00318                 return Qt::forbiddenCursor;
00319             return Qt::sizeVerCursor;
00320         case MEANING_RESIZE_COLUMN:
00321             // Bug in Qt up to Qt-3.1.1 : Qt::splitVCursor and Qt::splitHCursor are swapped!
00322 #if QT_VERSION <= 0x030101
00323             return Qt::splitVCursor;
00324 #else
00325             return Qt::splitHCursor;
00326 #endif
00327         case MEANING_RESIZE_ROW:
00328 #if QT_VERSION <= 0x030101
00329             return Qt::splitHCursor;
00330 #else
00331             return Qt::splitVCursor;
00332 #endif
00333         case MEANING_SELECT_RANGE:
00334         case MEANING_SELECT_COLUMN:
00335         case MEANING_SELECT_ROW:
00336         case MEANING_FORBIDDEN:
00337             return KCursor::handCursor();
00338     }
00339     return QCursor(); // default arrow shape
00340 }
00341 
00342 MouseMeaning KWFrameViewManager::mouseMeaning( const KoPoint &point, int keyState) const {
00343     QValueVector<KWFrameView*> framesThatAreHit = framesAt(point);
00344     QValueVector<KWFrameView*>::iterator sortedFrames = framesThatAreHit.begin();
00345     while(sortedFrames != framesThatAreHit.end()) {
00346         MouseMeaning answer = (*sortedFrames)->mouseMeaning(point, keyState);
00347         if(answer != MEANING_NONE) {
00348             //kdDebug() << "mouseMeaning at " << point << " is " << answer << endl;
00349             return answer;
00350         }
00351         ++sortedFrames;
00352     }
00353     return MEANING_NONE;
00354 }
00355 
00356 QValueList<KWFrameView*> KWFrameViewManager::selectedFrames() const {
00357     QValueList<KWFrameView*> selectedFrames;
00358 
00359     QValueList<KWFrameView*>::const_iterator frames = m_frames.begin();
00360     for(; frames != m_frames.end(); ++frames )
00361         if( (*frames)->selected() )
00362             selectedFrames.append( *frames );
00363     return selectedFrames;
00364 }
00365 
00366 KWFrameView* KWFrameViewManager::selectedFrame() const {
00367     QValueList<KWFrameView*>::const_iterator frames = m_frames.begin();
00368     for(; frames != m_frames.end(); ++frames )
00369         if( (*frames)->selected() )
00370             return *frames;
00371     return 0;
00372 }
00373 
00374 void KWFrameViewManager::showPopup( const KoPoint &point, KWView *view, int keyState, const QPoint &popupPoint) const {
00375     QValueVector<KWFrameView*> framesThatAreHit = framesAt(point);
00376     if(framesThatAreHit.count() == 0) {
00377         view->popupMenu("action_popup")->popup(popupPoint);
00378         return;
00379     }
00380     if(keyState == Qt::ControlButton) {
00381         // show the border popup of the top most frame.
00382         framesThatAreHit[0]->showPopup(framesThatAreHit[0]->frame()->topLeft(), view, popupPoint);
00383         return;
00384     }
00385     QValueVector<KWFrameView*>::iterator iter = framesThatAreHit.begin();
00386     while(iter != framesThatAreHit.end()) {
00387         if( (*iter)->selected() && keyState == Qt::ControlButton ) {
00388             (*iter)->showPopup(point, view, popupPoint);
00389             return;
00390         }
00391         ++iter;
00392     }
00393     framesThatAreHit[0]->showPopup(point, view, popupPoint);
00394 }
00395 
00396 void KWFrameViewManager::selectFrames(const KoPoint &point, int keyState, bool leftClick) {
00397     MouseMeaning mm = mouseMeaning(point, keyState);
00398     bool multiSelect = mm == MEANING_MOUSE_SELECT || ( keyState & Qt::ControlButton );
00399     SelectionType se = frameOnTop;
00400     if(leftClick && multiSelect)
00401         se = nextUnselected;
00402     KWFrameView *toBeSelected = view(point, se, !multiSelect);
00403     //kdDebug() << "KWFrameViewManager::selectFrames" << point << " got: " << toBeSelected << endl;
00404     if(toBeSelected == 0 || (keyState & Qt::ControlButton) == 0 || ( keyState & Qt::ShiftButton ) &&
00405         !(leftClick && (mm == MEANING_TOPLEFT || mm == MEANING_TOPRIGHT || mm == MEANING_TOP ||
00406         mm == MEANING_LEFT || mm == MEANING_RIGHT || mm == MEANING_MOUSE_MOVE ||
00407         mm == MEANING_BOTTOMLEFT || mm == MEANING_BOTTOM || mm == MEANING_BOTTOMRIGHT))) {
00408         // unselect all
00409         for(QValueListConstIterator<KWFrameView*> frames = m_frames.begin();
00410                 frames != m_frames.end(); ++frames) {
00411             (*frames)->setSelected(false);
00412         }
00413     }
00414     if(toBeSelected == 0)
00415         return;
00416     toBeSelected->setSelected(true, mm);
00417     slotFrameSelectionChanged();
00418 }
00419 
00420 // ********** FrameEvent **** */
00421 KWFrameViewManager::FrameEvent::FrameEvent (ActionType action) {
00422     m_action = action;
00423 }
00424 KWFrameViewManager::FrameEvent::FrameEvent (ActionType action, KWFrame *frame) {
00425     m_action = action;
00426     m_frame = frame;
00427 }
00428 KWFrameViewManager::FrameEvent::FrameEvent (ActionType action, KWFrameSet *frameSet) {
00429     m_action = action;
00430     m_frameSet = frameSet;
00431 }
00432 
00433 
00434 #include "KWFrameViewManager.moc"
KDE Home | KDE Accessibility Home | Description of Access Keys