• Skip to content
  • Skip to link menu
KDE 4.6 API Reference
  • KDE API Reference
  • kdelibs
  • KDE Home
  • Contact Us
 

KParts

partmanager.cpp

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

KParts

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

kdelibs

Skip menu "kdelibs"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • Kate
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDEWebKit
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.7.3
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