• Skip to content
  • Skip to link menu
KDE 4.1 API Reference
  • KDE API Reference
  • kdelibs
  • Sitemap
  • 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->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->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->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->name()).arg(obj->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->name()).arg(obj->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     {
00371         kFatal(1000) << QString("Can't remove part %1, not in KPartManager's list.").arg(part->objectName());
00372         return;
00373     }
00374 
00375     //Warning. The part could be already deleted
00376     //kDebug(1000) << QString("Part %1 removed").arg(part->name());
00377     int nb = d->m_parts.count();
00378     bool ok = d->m_parts.removeAll( part );
00379     Q_ASSERT( ok );
00380     Q_ASSERT( (int)d->m_parts.count() == nb-1 );
00381     part->setManager(0);
00382 
00383     emit partRemoved( part );
00384 
00385     if ( part == d->m_activePart )
00386         setActivePart( 0 );
00387     if ( part == d->m_selectedPart )
00388         setSelectedPart( 0 );
00389 }
00390 
00391 void PartManager::replacePart( Part * oldPart, Part * newPart, bool setActive )
00392 {
00393     //kDebug(1000) << "replacePart " << oldPart->name() << "-> " << newPart->name() << " setActive=" << setActive;
00394     // This methods does exactly removePart + addPart but without calling setActivePart(0) in between
00395     if ( !d->m_parts.contains( oldPart ) )
00396     {
00397         kFatal(1000) << QString("Can't remove part %1, not in KPartManager's list.").arg(oldPart->objectName());
00398         return;
00399     }
00400 
00401     d->m_parts.removeAll( oldPart );
00402     oldPart->setManager(0);
00403 
00404     emit partRemoved( oldPart );
00405 
00406     addPart( newPart, setActive );
00407 }
00408 
00409 void PartManager::setActivePart( Part *part, QWidget *widget )
00410 {
00411     if ( part && !d->m_parts.contains( part ) )
00412     {
00413         kWarning( 1000 ) << "PartManager::setActivePart : trying to activate a non-registered part! " << part->objectName();
00414         return; // don't allow someone call setActivePart with a part we don't know about
00415     }
00416 
00417     //check whether nested parts are disallowed and activate the top parent part then, by traversing the
00418     //tree recursively (Simon)
00419     if ( part && !d->m_bAllowNestedParts )
00420     {
00421         QObject *parentPart = part->parent(); // ### this relies on people using KParts::Factory!
00422         KParts::Part *parPart = ::qobject_cast<KParts::Part *>( parentPart );
00423         if ( parPart )
00424         {
00425             setActivePart( parPart, parPart->widget() );
00426             return;
00427         }
00428     }
00429 
00430 #ifdef DEBUG_PARTMANAGER
00431     kDebug(1000) << "PartManager::setActivePart d->m_activePart=" << d->m_activePart << "<->part=" << part
00432                  << " d->m_activeWidget=" << d->m_activeWidget << "<->widget=" << widget << endl;
00433 #endif
00434 
00435     // don't activate twice
00436     if ( d->m_activePart && part && d->m_activePart == part &&
00437          (!widget || d->m_activeWidget == widget) )
00438         return;
00439 
00440     KParts::Part *oldActivePart = d->m_activePart;
00441     QWidget *oldActiveWidget = d->m_activeWidget;
00442 
00443     setSelectedPart( 0 );
00444 
00445     d->m_activePart = part;
00446     d->m_activeWidget = widget;
00447 
00448     if ( oldActivePart )
00449     {
00450         KParts::Part *savedActivePart = part;
00451         QWidget *savedActiveWidget = widget;
00452 
00453         PartActivateEvent ev( false, oldActivePart, oldActiveWidget );
00454         QApplication::sendEvent( oldActivePart, &ev );
00455         if ( oldActiveWidget )
00456         {
00457             disconnect( oldActiveWidget, SIGNAL( destroyed() ),
00458                         this, SLOT( slotWidgetDestroyed() ) );
00459             QApplication::sendEvent( oldActiveWidget, &ev );
00460         }
00461 
00462         d->m_activePart = savedActivePart;
00463         d->m_activeWidget = savedActiveWidget;
00464     }
00465 
00466     if ( d->m_activePart )
00467     {
00468         if ( !widget )
00469             d->m_activeWidget = part->widget();
00470 
00471         PartActivateEvent ev( true, d->m_activePart, d->m_activeWidget );
00472         QApplication::sendEvent( d->m_activePart, &ev );
00473         if ( d->m_activeWidget )
00474         {
00475             connect( d->m_activeWidget, SIGNAL( destroyed() ),
00476                      this, SLOT( slotWidgetDestroyed() ) );
00477             QApplication::sendEvent( d->m_activeWidget, &ev );
00478         }
00479     }
00480     // Set the new active instance in KGlobal
00481     setActiveComponent(d->m_activePart ? d->m_activePart->componentData() : KComponentData());
00482 
00483     kDebug(1000) << this << " emitting activePartChanged " << d->m_activePart;
00484     emit activePartChanged( d->m_activePart );
00485 }
00486 
00487 void PartManager::setActiveComponent(const KComponentData &instance)
00488 {
00489     // It's a separate method to allow redefining this behavior
00490     KGlobal::setActiveComponent(instance);
00491 }
00492 
00493 Part *PartManager::activePart() const
00494 {
00495     return d->m_activePart;
00496 }
00497 
00498 QWidget *PartManager::activeWidget() const
00499 {
00500     return  d->m_activeWidget;
00501 }
00502 
00503 void PartManager::setSelectedPart( Part *part, QWidget *widget )
00504 {
00505     if ( part == d->m_selectedPart && widget == d->m_selectedWidget )
00506         return;
00507 
00508     Part *oldPart = d->m_selectedPart;
00509     QWidget *oldWidget = d->m_selectedWidget;
00510 
00511     d->m_selectedPart = part;
00512     d->m_selectedWidget = widget;
00513 
00514     if ( part && !widget )
00515         d->m_selectedWidget = part->widget();
00516 
00517     if ( oldPart )
00518     {
00519         PartSelectEvent ev( false, oldPart, oldWidget );
00520         QApplication::sendEvent( oldPart, &ev );
00521         QApplication::sendEvent( oldWidget, &ev );
00522     }
00523 
00524     if ( d->m_selectedPart )
00525     {
00526         PartSelectEvent ev( true, d->m_selectedPart, d->m_selectedWidget );
00527         QApplication::sendEvent( d->m_selectedPart, &ev );
00528         QApplication::sendEvent( d->m_selectedWidget, &ev );
00529     }
00530 }
00531 
00532 Part *PartManager::selectedPart() const
00533 {
00534     return d->m_selectedPart;
00535 }
00536 
00537 QWidget *PartManager::selectedWidget() const
00538 {
00539     return d->m_selectedWidget;
00540 }
00541 
00542 void PartManager::slotObjectDestroyed()
00543 {
00544     kDebug(1000) << "KPartManager::slotObjectDestroyed()";
00545     removePart( const_cast<Part *>( static_cast<const Part *>( sender() ) ) );
00546 }
00547 
00548 void PartManager::slotWidgetDestroyed()
00549 {
00550     kDebug(1000) << "KPartsManager::slotWidgetDestroyed()";
00551     if ( static_cast<const QWidget *>( sender() ) == d->m_activeWidget )
00552         setActivePart( 0 ); //do not remove the part because if the part's widget dies, then the
00553     //part will delete itself anyway, invoking removePart() in its destructor
00554 }
00555 
00556 const QList<Part *> PartManager::parts() const
00557 {
00558     return d->m_parts;
00559 }
00560 
00561 void PartManager::addManagedTopLevelWidget( const QWidget *topLevel )
00562 {
00563     if ( !topLevel->isTopLevel() )
00564         return;
00565 
00566     if ( d->m_managedTopLevelWidgets.contains( topLevel ) )
00567         return;
00568 
00569     d->m_managedTopLevelWidgets.append( topLevel );
00570     connect( topLevel, SIGNAL( destroyed() ),
00571              this, SLOT( slotManagedTopLevelWidgetDestroyed() ) );
00572 }
00573 
00574 void PartManager::removeManagedTopLevelWidget( const QWidget *topLevel )
00575 {
00576     if ( !topLevel->isTopLevel() )
00577         return;
00578 
00579     d->m_managedTopLevelWidgets.removeAll( topLevel );
00580 }
00581 
00582 void PartManager::slotManagedTopLevelWidgetDestroyed()
00583 {
00584     const QWidget *widget = static_cast<const QWidget *>( sender() );
00585     removeManagedTopLevelWidget( widget );
00586 }
00587 
00588 int PartManager::reason() const
00589 {
00590     return d->m_reason;
00591 }
00592 
00593 #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

kdelibs

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