• Skip to content
  • Skip to link menu
KDE 3.5 API Reference
  • KDE API Reference
  • API Reference
  • Sitemap
  • Contact Us
 

KParts

partmanager.cpp

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

KParts

Skip menu "KParts"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

API Reference

Skip menu "API Reference"
  • dcop
  • DNSSD
  • interfaces
  • Kate
  • kconf_update
  • KDECore
  • KDED
  • kdefx
  • KDEsu
  • kdeui
  • KDocTools
  • KHTML
  • KImgIO
  • KInit
  • kio
  • kioslave
  • KJS
  • KNewStuff
  • KParts
  • KUtils
Generated for API Reference by doxygen 1.5.9
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal