kparts Library API Documentation

partmanager.cpp

00001 /* This file is part of the KDE project
00002    Copyright (C) 1999 Simon Hausmann <hausmann@kde.org>
00003              (C) 1999 David Faure <faure@kde.org>
00004 
00005    This library is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU Library General Public
00007    License as published by the Free Software Foundation; either
00008    version 2 of the License, or (at your option) any later version.
00009 
00010    This library is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013    Library General Public License for more details.
00014 
00015    You should have received a copy of the GNU Library General Public License
00016    along with this library; see the file COPYING.LIB.  If not, write to
00017    the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00018    Boston, MA 02111-1307, USA.
00019 */
00020 
00021 #include "partmanager.h"
00022 #include <kparts/event.h>
00023 #include <kparts/part.h>
00024 #include <kglobal.h>
00025 #include <kdebug.h>
00026 #include <kdebugclasses.h>
00027 
00028 #include <qapplication.h>
00029 
00030 //#define DEBUG_PARTMANAGER
00031 
00032 using namespace KParts;
00033 
00034 template class QPtrList<Part>;
00035 
00036 namespace KParts {
00037 
00038 class PartManagerPrivate
00039 {
00040 public:
00041   PartManagerPrivate()
00042   {
00043     m_activeWidget = 0;
00044     m_activePart = 0;
00045     m_selectedPart = 0;
00046     m_selectedWidget = 0;
00047     m_bAllowNestedParts = false;
00048     m_bIgnoreScrollBars = false;
00049     m_activationButtonMask = Qt::LeftButton | Qt::MidButton | Qt::RightButton;
00050   }
00051   ~PartManagerPrivate()
00052   {
00053   }
00054 
00055   Part * m_activePart;
00056   QWidget *m_activeWidget;
00057 
00058   QPtrList<Part> m_parts;
00059 
00060   PartManager::SelectionPolicy m_policy;
00061 
00062   Part *m_selectedPart;
00063   QWidget *m_selectedWidget;
00064 
00065   QPtrList<QWidget> m_managedTopLevelWidgets;
00066   short int m_activationButtonMask;
00067   bool m_bIgnoreScrollBars;
00068   bool m_bAllowNestedParts;
00069 };
00070 
00071 }
00072 
00073 PartManager::PartManager( QWidget * parent, const char * name )
00074  : QObject( parent, name )
00075 {
00076   d = new PartManagerPrivate;
00077 
00078   qApp->installEventFilter( this );
00079 
00080   d->m_policy = Direct;
00081 
00082   addManagedTopLevelWidget( parent );
00083 }
00084 
00085 PartManager::PartManager( QWidget *topLevel, QObject *parent, const char *name )
00086  : QObject( parent, name )
00087 {
00088   d = new PartManagerPrivate;
00089 
00090   qApp->installEventFilter( this );
00091 
00092   d->m_policy = Direct;
00093 
00094   addManagedTopLevelWidget( topLevel );
00095 }
00096 
00097 PartManager::~PartManager()
00098 {
00099   for ( QPtrListIterator<QWidget> it( d->m_managedTopLevelWidgets );
00100         it.current(); ++it )
00101     disconnect( it.current(), SIGNAL( destroyed() ),
00102                 this, SLOT( slotManagedTopLevelWidgetDestroyed() ) );
00103 
00104   for ( QPtrListIterator<Part> it( d->m_parts ); it.current(); ++it )
00105       it.current()->setManager( 0 );
00106 
00107   // core dumps ... setActivePart( 0L );
00108   qApp->removeEventFilter( this );
00109   delete d;
00110 }
00111 
00112 void PartManager::setSelectionPolicy( SelectionPolicy policy )
00113 {
00114   d->m_policy = policy;
00115 }
00116 
00117 PartManager::SelectionPolicy PartManager::selectionPolicy() const
00118 {
00119   return d->m_policy;
00120 }
00121 
00122 void PartManager::setAllowNestedParts( bool allow )
00123 {
00124   d->m_bAllowNestedParts = allow;
00125 }
00126 
00127 bool PartManager::allowNestedParts() const
00128 {
00129   return d->m_bAllowNestedParts;
00130 }
00131 
00132 void PartManager::setIgnoreScrollBars( bool ignore )
00133 {
00134   d->m_bIgnoreScrollBars = ignore;
00135 }
00136 
00137 bool PartManager::ignoreScrollBars() const
00138 {
00139   return d->m_bIgnoreScrollBars;
00140 }
00141 
00142 void PartManager::setActivationButtonMask( short int buttonMask )
00143 {
00144     d->m_activationButtonMask = buttonMask;
00145 }
00146 
00147 short int PartManager::activationButtonMask() const
00148 {
00149     return d->m_activationButtonMask;
00150 }
00151 
00152 bool PartManager::eventFilter( QObject *obj, QEvent *ev )
00153 {
00154 
00155   if ( ev->type() != QEvent::MouseButtonPress &&
00156        ev->type() != QEvent::MouseButtonDblClick &&
00157        ev->type() != QEvent::FocusIn )
00158     return false;
00159 
00160   if ( !obj->isWidgetType() )
00161     return false;
00162 
00163   QWidget *w = static_cast<QWidget *>( obj );
00164 
00165   if ( ( w->testWFlags( WType_Dialog ) && w->isModal() ) ||
00166        w->testWFlags( WType_Popup ) || w->testWFlags( WStyle_Tool ) )
00167     return false;
00168 
00169   QMouseEvent* mev = 0L;
00170   if ( ev->type() == QEvent::MouseButtonPress || ev->type() == QEvent::MouseButtonDblClick )
00171   {
00172       mev = static_cast<QMouseEvent *>( ev );
00173 #ifdef DEBUG_PARTMANAGER
00174       kdDebug() << "PartManager::eventFilter button: " << mev->button() << " " << "d->m_activationButtonMask=" << d->m_activationButtonMask << endl;
00175 #endif
00176       if ( ( mev->button() & d->m_activationButtonMask ) == 0 )
00177         return false; // ignore this button
00178   }
00179 
00180   Part * part;
00181   while ( w )
00182   {
00183     QPoint pos;
00184 
00185     if ( !d->m_managedTopLevelWidgets.containsRef( w->topLevelWidget() ) )
00186       return false;
00187 
00188     if ( d->m_bIgnoreScrollBars && w->inherits( "QScrollBar" ) )
00189       return false;
00190 
00191     if ( mev ) // mouse press or mouse double-click event
00192     {
00193       pos = mev->globalPos();
00194       part = findPartFromWidget( w, pos );
00195     } else
00196       part = findPartFromWidget( w );
00197 
00198 #ifdef DEBUG_PARTMANAGER
00199     QCString evType = ( ev->type() == QEvent::MouseButtonPress ) ? "MouseButtonPress"
00200                       : ( ev->type() == QEvent::MouseButtonDblClick ) ? "MouseButtonDblClick"
00201                       : ( ev->type() == QEvent::FocusIn ) ? "FocusIn" : "OTHER! ERROR!";
00202 #endif
00203     if ( part ) // We found a part whose widget is w
00204     {
00205       if ( d->m_policy == PartManager::TriState )
00206       {
00207         if ( ev->type() == QEvent::MouseButtonDblClick )
00208         {
00209           if ( part == d->m_activePart && w == d->m_activeWidget )
00210             return false;
00211 
00212 #ifdef DEBUG_PARTMANAGER
00213           kdDebug(1000) << "PartManager::eventFilter dblclick -> setActivePart" << part << endl;
00214 #endif
00215           setActivePart( part, w );
00216           return true;
00217         }
00218 
00219         if ( ( d->m_selectedWidget != w || d->m_selectedPart != part ) &&
00220              ( d->m_activeWidget != w || d->m_activePart != part ) )
00221         {
00222           if ( part->isSelectable() )
00223             setSelectedPart( part, w );
00224           else {
00225 #ifdef DEBUG_PARTMANAGER
00226               kdDebug(1000) << "Part " << part << " (non-selectable) made active because " << w->className() << " got event" << " " << evType << endl;
00227 #endif
00228               setActivePart( part, w );
00229           }
00230           return true;
00231         }
00232         else if ( d->m_selectedWidget == w && d->m_selectedPart == part )
00233         {
00234 #ifdef DEBUG_PARTMANAGER
00235           kdDebug(1000) << "Part " << part << " made active (from selected) because " << w->className() << " got event" << " " << evType << endl;
00236 #endif
00237           setActivePart( part, w );
00238           return true;
00239         }
00240         else if ( d->m_activeWidget == w && d->m_activePart == part )
00241         {
00242           setSelectedPart( 0L );
00243           return false;
00244         }
00245 
00246         return false;
00247       }
00248       else if ( part != d->m_activePart )
00249       {
00250 #ifdef DEBUG_PARTMANAGER
00251         kdDebug(1000) << "Part " << part << " made active because " << w->className() << " got event" << " " << evType << endl;
00252 #endif
00253         setActivePart( part, w );
00254       }
00255 
00256       return false;
00257     }
00258 
00259     w = w->parentWidget();
00260 
00261     if ( w && ( ( w->testWFlags( WType_Dialog ) && w->isModal() ) ||
00262                 w->testWFlags( WType_Popup ) || w->testWFlags( WStyle_Tool ) ) )
00263     {
00264 #ifdef DEBUG_PARTMANAGER
00265       kdDebug(1000) << QString("No part made active although %1/%2 got event - loop aborted").arg(obj->name()).arg(obj->className()) << endl;
00266 #endif
00267       return false;
00268     }
00269 
00270   }
00271 
00272 #ifdef DEBUG_PARTMANAGER
00273   kdDebug(1000) << QString("No part made active although %1/%2 got event").arg(obj->name()).arg(obj->className()) << endl;
00274 #endif
00275   return false;
00276 }
00277 
00278 Part * PartManager::findPartFromWidget( QWidget * widget, const QPoint &pos )
00279 {
00280   QPtrListIterator<Part> it ( d->m_parts );
00281   for ( ; it.current() ; ++it )
00282   {
00283     Part *part = it.current()->hitTest( widget, pos );
00284     if ( part && d->m_parts.findRef( part ) != -1 )
00285       return part;
00286   }
00287   return 0L;
00288 }
00289 
00290 Part * PartManager::findPartFromWidget( QWidget * widget )
00291 {
00292   QPtrListIterator<Part> it ( d->m_parts );
00293   for ( ; it.current() ; ++it )
00294   {
00295     if ( widget == it.current()->widget() )
00296       return it.current();
00297   }
00298   return 0L;
00299 }
00300 
00301 void PartManager::addPart( Part *part, bool setActive )
00302 {
00303     if ( d->m_parts.findRef( part ) != -1 ) // don't add parts more than once :)
00304       return;
00305 
00306   d->m_parts.append( part );
00307 
00308   part->setManager( this );
00309 
00310   if ( setActive )
00311   {
00312     setActivePart( part );
00313     if ( part->widget() )
00314       part->widget()->setFocus();
00315   }
00316 
00317   // Prevent focus problems
00318   if ( part->widget() && part->widget()->focusPolicy() == QWidget::NoFocus )
00319   {
00320     kdWarning(1000) << "Part '" << part->name() << "' has a widget " << part->widget()->name() << " with a focus policy of NoFocus. It should have at least a ClickFocus policy, for part activation to work well." << endl;
00321   }
00322   if ( part->widget() && part->widget()->focusPolicy() == QWidget::TabFocus )
00323   {
00324     kdWarning(1000) << "Part '" << part->name() << "' has a widget " << part->widget()->name() << " with a focus policy of TabFocus. It should have at least a ClickFocus policy, for part activation to work well." << endl;
00325   }
00326 
00327   if ( part->widget() )
00328     part->widget()->show();
00329   emit partAdded( part );
00330 }
00331 
00332 void PartManager::removePart( Part *part )
00333 {
00334   if ( d->m_parts.findRef( part ) == -1 )
00335   {
00336     kdFatal(1000) << QString("Can't remove part %1, not in KPartManager's list.").arg(part->name()) << endl;
00337     return;
00338   }
00339 
00340   //Warning. The part could be already deleted
00341   //kdDebug(1000) << QString("Part %1 removed").arg(part->name()) << endl;
00342   d->m_parts.removeRef( part );
00343   part->setManager(0);
00344 
00345   emit partRemoved( part );
00346 
00347   if ( part == d->m_activePart )
00348     setActivePart( 0 );
00349   if ( part == d->m_selectedPart )
00350     setSelectedPart( 0 );
00351 }
00352 
00353 void PartManager::replacePart( Part * oldPart, Part * newPart, bool setActive )
00354 {
00355   //kdDebug(1000) << "replacePart " << oldPart->name() << "-> " << newPart->name() << " setActive=" << setActive << endl;
00356   // This methods does exactly removePart + addPart but without calling setActivePart(0) in between
00357   if ( d->m_parts.findRef( oldPart ) == -1 )
00358   {
00359     kdFatal(1000) << QString("Can't remove part %1, not in KPartManager's list.").arg(oldPart->name()) << endl;
00360     return;
00361   }
00362 
00363   d->m_parts.removeRef( oldPart );
00364   oldPart->setManager(0);
00365 
00366   emit partRemoved( oldPart );
00367 
00368   addPart( newPart, setActive );
00369 }
00370 
00371 void PartManager::setActivePart( Part *part, QWidget *widget )
00372 {
00373   if ( part && d->m_parts.findRef( part ) == -1 )
00374   {
00375       kdWarning( 1000 ) << "PartManager::setActivePart : trying to activate a non-registered part! " << part->name() << endl;
00376       return; // don't allow someone call setActivePart with a part we don't know about
00377   }
00378 
00379   //check whether nested parts are disallowed and activate the top parent part then, by traversing the
00380   //tree recursively (Simon)
00381   if ( part && !d->m_bAllowNestedParts )
00382   {
00383     QObject *parentPart = part->parent(); // ### this relies on people using KParts::Factory!
00384     if ( parentPart && parentPart->inherits( "KParts::Part" ) )
00385     {
00386       KParts::Part *parPart = static_cast<KParts::Part *>( parentPart );
00387       setActivePart( parPart, parPart->widget() );
00388       return;
00389     }
00390   }
00391 
00392   //kdDebug() << "PartManager::setActivePart d->m_activePart=" << d->m_activePart << "<->part=" << part
00393   //          << " d->m_activeWidget=" << d->m_activeWidget << "<->widget=" << widget << endl;
00394 
00395   // don't activate twice
00396   if ( d->m_activePart && part && d->m_activePart == part &&
00397        (!widget || d->m_activeWidget == widget) )
00398     return;
00399 
00400   KParts::Part *oldActivePart = d->m_activePart;
00401   QWidget *oldActiveWidget = d->m_activeWidget;
00402 
00403   setSelectedPart( 0L );
00404 
00405   d->m_activePart = part;
00406   d->m_activeWidget = widget;
00407 
00408   if ( oldActivePart )
00409   {
00410     KParts::Part *savedActivePart = part;
00411     QWidget *savedActiveWidget = widget;
00412 
00413     PartActivateEvent ev( false, oldActivePart, oldActiveWidget );
00414     QApplication::sendEvent( oldActivePart, &ev );
00415     if ( oldActiveWidget )
00416     {
00417       disconnect( oldActiveWidget, SIGNAL( destroyed() ),
00418                   this, SLOT( slotWidgetDestroyed() ) );
00419       QApplication::sendEvent( oldActiveWidget, &ev );
00420     }
00421 
00422     d->m_activePart = savedActivePart;
00423     d->m_activeWidget = savedActiveWidget;
00424   }
00425 
00426   if ( d->m_activePart )
00427   {
00428     if ( !widget )
00429       d->m_activeWidget = part->widget();
00430 
00431     PartActivateEvent ev( true, d->m_activePart, d->m_activeWidget );
00432     QApplication::sendEvent( d->m_activePart, &ev );
00433     if ( d->m_activeWidget )
00434     {
00435       connect( d->m_activeWidget, SIGNAL( destroyed() ),
00436                this, SLOT( slotWidgetDestroyed() ) );
00437       QApplication::sendEvent( d->m_activeWidget, &ev );
00438     }
00439   }
00440   // Set the new active instance in KGlobal
00441   setActiveInstance( d->m_activePart ? d->m_activePart->instance() : 0L );
00442 
00443   kdDebug(1000) << this << " emitting activePartChanged " << d->m_activePart << endl;
00444   emit activePartChanged( d->m_activePart );
00445 }
00446 
00447 void PartManager::setActiveInstance( KInstance * instance )
00448 {
00449   // It's a separate method to allow redefining this behaviour
00450   KGlobal::_activeInstance = instance;
00451 }
00452 
00453 Part *PartManager::activePart() const
00454 {
00455   return d->m_activePart;
00456 }
00457 
00458 QWidget *PartManager::activeWidget() const
00459 {
00460   return  d->m_activeWidget;
00461 }
00462 
00463 void PartManager::setSelectedPart( Part *part, QWidget *widget )
00464 {
00465   if ( part == d->m_selectedPart && widget == d->m_selectedWidget )
00466     return;
00467 
00468   Part *oldPart = d->m_selectedPart;
00469   QWidget *oldWidget = d->m_selectedWidget;
00470 
00471   d->m_selectedPart = part;
00472   d->m_selectedWidget = widget;
00473 
00474   if ( part && !widget )
00475     d->m_selectedWidget = part->widget();
00476 
00477   if ( oldPart )
00478   {
00479     PartSelectEvent ev( false, oldPart, oldWidget );
00480     QApplication::sendEvent( oldPart, &ev );
00481     QApplication::sendEvent( oldWidget, &ev );
00482   }
00483 
00484   if ( d->m_selectedPart )
00485   {
00486     PartSelectEvent ev( true, d->m_selectedPart, d->m_selectedWidget );
00487     QApplication::sendEvent( d->m_selectedPart, &ev );
00488     QApplication::sendEvent( d->m_selectedWidget, &ev );
00489   }
00490 }
00491 
00492 Part *PartManager::selectedPart() const
00493 {
00494   return d->m_selectedPart;
00495 }
00496 
00497 QWidget *PartManager::selectedWidget() const
00498 {
00499   return d->m_selectedWidget;
00500 }
00501 
00502 void PartManager::slotObjectDestroyed()
00503 {
00504   kdDebug(1000) << "KPartManager::slotObjectDestroyed()" << endl;
00505   removePart( const_cast<Part *>( static_cast<const Part *>( sender() ) ) );
00506 }
00507 
00508 void PartManager::slotWidgetDestroyed()
00509 {
00510   kdDebug(1000) << "KPartsManager::slotWidgetDestroyed()" << endl;
00511   if ( static_cast<const QWidget *>( sender() ) == d->m_activeWidget )
00512     setActivePart( 0L ); //do not remove the part because if the part's widget dies, then the
00513                          //part will delete itself anyway, invoking removePart() in its destructor
00514 }
00515 
00516 const QPtrList<Part> *PartManager::parts() const
00517 {
00518   return &d->m_parts;
00519 }
00520 
00521 void PartManager::addManagedTopLevelWidget( const QWidget *topLevel )
00522 {
00523   if ( !topLevel->isTopLevel() )
00524     return;
00525 
00526   if ( d->m_managedTopLevelWidgets.containsRef( topLevel ) )
00527     return;
00528 
00529   d->m_managedTopLevelWidgets.append( topLevel );
00530   connect( topLevel, SIGNAL( destroyed() ),
00531            this, SLOT( slotManagedTopLevelWidgetDestroyed() ) );
00532 }
00533 
00534 void PartManager::removeManagedTopLevelWidget( const QWidget *topLevel )
00535 {
00536   if ( !topLevel->isTopLevel() )
00537     return;
00538 
00539   if ( d->m_managedTopLevelWidgets.findRef( topLevel ) == -1 )
00540     return;
00541 
00542   d->m_managedTopLevelWidgets.remove();
00543 }
00544 
00545 void PartManager::slotManagedTopLevelWidgetDestroyed()
00546 {
00547   const QWidget *widget = static_cast<const QWidget *>( sender() );
00548   removeManagedTopLevelWidget( widget );
00549 }
00550 
00551 void PartManager::virtual_hook( int, void* )
00552 { /*BASE::virtual_hook( id, data );*/ }
00553 
00554 #include "partmanager.moc"
KDE Logo
This file is part of the documentation for kdelibs Version 3.1.4.
Documentation copyright © 1996-2002 the KDE developers.
Generated on Sun Feb 27 22:15:45 2005 by doxygen 1.3.4 written by Dimitri van Heesch, © 1997-2001