partmanager.cpp Source File (kparts Library)

| # kparts Library API Documentation
Overview | Class Hierarchy | Classes | Classes (annotated) | Members | Source Files

# 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"

This file is part of the documentation for kdelibs Version 3.1.5.
Documentation copyright © 1996-2002 the KDE developers.
Generated on Wed Jan 28 13:26:51 2004 by doxygen 1.3.4 written by Dimitri van Heesch, © 1997-2001