00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
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 <qapplication.h>
00028
00029
00030
00031 using namespace KParts;
00032
00033 template class QPtrList<Part>;
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 }
00050 ~PartManagerPrivate()
00051 {
00052 }
00053
00054 Part * m_activePart;
00055 QWidget *m_activeWidget;
00056
00057 QPtrList<Part> m_parts;
00058
00059 PartManager::SelectionPolicy m_policy;
00060
00061 Part *m_selectedPart;
00062 QWidget *m_selectedWidget;
00063
00064 QPtrList<QWidget> m_managedTopLevelWidgets;
00065 short int m_activationButtonMask;
00066 bool m_bIgnoreScrollBars;
00067 bool m_bAllowNestedParts;
00068 };
00069
00070 }
00071
00072 PartManager::PartManager( QWidget * parent, const char * name )
00073 : QObject( parent, name )
00074 {
00075 d = new PartManagerPrivate;
00076
00077 qApp->installEventFilter( this );
00078
00079 d->m_policy = Direct;
00080
00081 addManagedTopLevelWidget( parent );
00082 }
00083
00084 PartManager::PartManager( QWidget *topLevel, QObject *parent, const char *name )
00085 : QObject( parent, name )
00086 {
00087 d = new PartManagerPrivate;
00088
00089 qApp->installEventFilter( this );
00090
00091 d->m_policy = Direct;
00092
00093 addManagedTopLevelWidget( topLevel );
00094 }
00095
00096 PartManager::~PartManager()
00097 {
00098 for ( QPtrListIterator<QWidget> it( d->m_managedTopLevelWidgets );
00099 it.current(); ++it )
00100 disconnect( it.current(), SIGNAL( destroyed() ),
00101 this, SLOT( slotManagedTopLevelWidgetDestroyed() ) );
00102
00103 for ( QPtrListIterator<Part> it( d->m_parts ); it.current(); ++it )
00104 it.current()->setManager( 0 );
00105
00106
00107 qApp->removeEventFilter( this );
00108 delete d;
00109 }
00110
00111 void PartManager::setSelectionPolicy( SelectionPolicy policy )
00112 {
00113 d->m_policy = policy;
00114 }
00115
00116 PartManager::SelectionPolicy PartManager::selectionPolicy() const
00117 {
00118 return d->m_policy;
00119 }
00120
00121 void PartManager::setAllowNestedParts( bool allow )
00122 {
00123 d->m_bAllowNestedParts = allow;
00124 }
00125
00126 bool PartManager::allowNestedParts() const
00127 {
00128 return d->m_bAllowNestedParts;
00129 }
00130
00131 void PartManager::setIgnoreScrollBars( bool ignore )
00132 {
00133 d->m_bIgnoreScrollBars = ignore;
00134 }
00135
00136 bool PartManager::ignoreScrollBars() const
00137 {
00138 return d->m_bIgnoreScrollBars;
00139 }
00140
00141 void PartManager::setActivationButtonMask( short int buttonMask )
00142 {
00143 d->m_activationButtonMask = buttonMask;
00144 }
00145
00146 short int PartManager::activationButtonMask() const
00147 {
00148 return d->m_activationButtonMask;
00149 }
00150
00151 bool PartManager::eventFilter( QObject *obj, QEvent *ev )
00152 {
00153
00154 if ( ev->type() != QEvent::MouseButtonPress &&
00155 ev->type() != QEvent::MouseButtonDblClick &&
00156 ev->type() != QEvent::FocusIn )
00157 return false;
00158
00159 if ( !obj->isWidgetType() )
00160 return false;
00161
00162 QWidget *w = static_cast<QWidget *>( obj );
00163
00164 if ( ( w->testWFlags( WType_Dialog ) && w->isModal() ) ||
00165 w->testWFlags( WType_Popup ) || w->testWFlags( WStyle_Tool ) )
00166 return false;
00167
00168 QMouseEvent* mev = 0L;
00169 if ( ev->type() == QEvent::MouseButtonPress || ev->type() == QEvent::MouseButtonDblClick )
00170 {
00171 mev = static_cast<QMouseEvent *>( ev );
00172 #ifdef DEBUG_PARTMANAGER
00173 kdDebug() << "PartManager::eventFilter button: " << mev->button() << " " << "d->m_activationButtonMask=" << d->m_activationButtonMask << endl;
00174 #endif
00175 if ( ( mev->button() & d->m_activationButtonMask ) == 0 )
00176 return false;
00177 }
00178
00179 Part * part;
00180 while ( w )
00181 {
00182 QPoint pos;
00183
00184 if ( !d->m_managedTopLevelWidgets.containsRef( w->topLevelWidget() ) )
00185 return false;
00186
00187 if ( d->m_bIgnoreScrollBars && w->inherits( "QScrollBar" ) )
00188 return false;
00189
00190 if ( mev )
00191 {
00192 pos = mev->globalPos();
00193 part = findPartFromWidget( w, pos );
00194 } else
00195 part = findPartFromWidget( w );
00196
00197 #ifdef DEBUG_PARTMANAGER
00198 QCString evType = ( ev->type() == QEvent::MouseButtonPress ) ? "MouseButtonPress"
00199 : ( ev->type() == QEvent::MouseButtonDblClick ) ? "MouseButtonDblClick"
00200 : ( ev->type() == QEvent::FocusIn ) ? "FocusIn" : "OTHER! ERROR!";
00201 #endif
00202 if ( part )
00203 {
00204 if ( d->m_policy == PartManager::TriState )
00205 {
00206 if ( ev->type() == QEvent::MouseButtonDblClick )
00207 {
00208 if ( part == d->m_activePart && w == d->m_activeWidget )
00209 return false;
00210
00211 #ifdef DEBUG_PARTMANAGER
00212 kdDebug(1000) << "PartManager::eventFilter dblclick -> setActivePart" << part << endl;
00213 #endif
00214 setActivePart( part, w );
00215 return true;
00216 }
00217
00218 if ( ( d->m_selectedWidget != w || d->m_selectedPart != part ) &&
00219 ( d->m_activeWidget != w || d->m_activePart != part ) )
00220 {
00221 if ( part->isSelectable() )
00222 setSelectedPart( part, w );
00223 else {
00224 #ifdef DEBUG_PARTMANAGER
00225 kdDebug(1000) << "Part " << part << " (non-selectable) made active because " << w->className() << " got event" << " " << evType << endl;
00226 #endif
00227 setActivePart( part, w );
00228 }
00229 return true;
00230 }
00231 else if ( d->m_selectedWidget == w && d->m_selectedPart == part )
00232 {
00233 #ifdef DEBUG_PARTMANAGER
00234 kdDebug(1000) << "Part " << part << " made active (from selected) because " << w->className() << " got event" << " " << evType << endl;
00235 #endif
00236 setActivePart( part, w );
00237 return true;
00238 }
00239 else if ( d->m_activeWidget == w && d->m_activePart == part )
00240 {
00241 setSelectedPart( 0L );
00242 return false;
00243 }
00244
00245 return false;
00246 }
00247 else if ( part != d->m_activePart )
00248 {
00249 #ifdef DEBUG_PARTMANAGER
00250 kdDebug(1000) << "Part " << part << " made active because " << w->className() << " got event" << " " << evType << endl;
00251 #endif
00252 setActivePart( part, w );
00253 }
00254
00255 return false;
00256 }
00257
00258 w = w->parentWidget();
00259
00260 if ( w && ( ( w->testWFlags( WType_Dialog ) && w->isModal() ) ||
00261 w->testWFlags( WType_Popup ) || w->testWFlags( WStyle_Tool ) ) )
00262 {
00263 #ifdef DEBUG_PARTMANAGER
00264 kdDebug(1000) << QString("No part made active although %1/%2 got event - loop aborted").arg(obj->name()).arg(obj->className()) << endl;
00265 #endif
00266 return false;
00267 }
00268
00269 }
00270
00271 #ifdef DEBUG_PARTMANAGER
00272 kdDebug(1000) << QString("No part made active although %1/%2 got event").arg(obj->name()).arg(obj->className()) << endl;
00273 #endif
00274 return false;
00275 }
00276
00277 Part * PartManager::findPartFromWidget( QWidget * widget, const QPoint &pos )
00278 {
00279 QPtrListIterator<Part> it ( d->m_parts );
00280 for ( ; it.current() ; ++it )
00281 {
00282 Part *part = it.current()->hitTest( widget, pos );
00283 if ( part && d->m_parts.findRef( part ) != -1 )
00284 return part;
00285 }
00286 return 0L;
00287 }
00288
00289 Part * PartManager::findPartFromWidget( QWidget * widget )
00290 {
00291 QPtrListIterator<Part> it ( d->m_parts );
00292 for ( ; it.current() ; ++it )
00293 {
00294 if ( widget == it.current()->widget() )
00295 return it.current();
00296 }
00297 return 0L;
00298 }
00299
00300 void PartManager::addPart( Part *part, bool setActive )
00301 {
00302 if ( d->m_parts.findRef( part ) != -1 )
00303 return;
00304
00305 d->m_parts.append( part );
00306
00307 part->setManager( this );
00308
00309 if ( setActive )
00310 {
00311 setActivePart( part );
00312 if ( part->widget() )
00313 part->widget()->setFocus();
00314 }
00315
00316
00317 if ( part->widget() && part->widget()->focusPolicy() == QWidget::NoFocus )
00318 {
00319 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;
00320 }
00321 if ( part->widget() && part->widget()->focusPolicy() == QWidget::TabFocus )
00322 {
00323 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;
00324 }
00325
00326 if ( part->widget() )
00327 part->widget()->show();
00328 emit partAdded( part );
00329 }
00330
00331 void PartManager::removePart( Part *part )
00332 {
00333 if ( d->m_parts.findRef( part ) == -1 )
00334 {
00335 kdFatal(1000) << QString("Can't remove part %1, not in KPartManager's list.").arg(part->name()) << endl;
00336 return;
00337 }
00338
00339
00340
00341 d->m_parts.removeRef( part );
00342 part->setManager(0);
00343
00344 emit partRemoved( part );
00345
00346 if ( part == d->m_activePart )
00347 setActivePart( 0 );
00348 if ( part == d->m_selectedPart )
00349 setSelectedPart( 0 );
00350 }
00351
00352 void PartManager::replacePart( Part * oldPart, Part * newPart, bool setActive )
00353 {
00354
00355
00356 if ( d->m_parts.findRef( oldPart ) == -1 )
00357 {
00358 kdFatal(1000) << QString("Can't remove part %1, not in KPartManager's list.").arg(oldPart->name()) << endl;
00359 return;
00360 }
00361
00362 d->m_parts.removeRef( oldPart );
00363 oldPart->setManager(0);
00364
00365 emit partRemoved( oldPart );
00366
00367 addPart( newPart, setActive );
00368 }
00369
00370 void PartManager::setActivePart( Part *part, QWidget *widget )
00371 {
00372 if ( part && d->m_parts.findRef( part ) == -1 )
00373 {
00374 kdWarning( 1000 ) << "PartManager::setActivePart : trying to activate a non-registered part! " << part->name() << endl;
00375 return;
00376 }
00377
00378
00379
00380 if ( part && !d->m_bAllowNestedParts )
00381 {
00382 QObject *parentPart = part->parent();
00383 if ( parentPart && parentPart->inherits( "KParts::Part" ) )
00384 {
00385 KParts::Part *parPart = static_cast<KParts::Part *>( parentPart );
00386 setActivePart( parPart, parPart->widget() );
00387 return;
00388 }
00389 }
00390
00391
00392
00393
00394
00395 if ( d->m_activePart && part && d->m_activePart == part &&
00396 (!widget || d->m_activeWidget == widget) )
00397 return;
00398
00399 KParts::Part *oldActivePart = d->m_activePart;
00400 QWidget *oldActiveWidget = d->m_activeWidget;
00401
00402 setSelectedPart( 0L );
00403
00404 d->m_activePart = part;
00405 d->m_activeWidget = widget;
00406
00407 if ( oldActivePart )
00408 {
00409 KParts::Part *savedActivePart = part;
00410 QWidget *savedActiveWidget = widget;
00411
00412 PartActivateEvent ev( false, oldActivePart, oldActiveWidget );
00413 QApplication::sendEvent( oldActivePart, &ev );
00414 if ( oldActiveWidget )
00415 {
00416 disconnect( oldActiveWidget, SIGNAL( destroyed() ),
00417 this, SLOT( slotWidgetDestroyed() ) );
00418 QApplication::sendEvent( oldActiveWidget, &ev );
00419 }
00420
00421 d->m_activePart = savedActivePart;
00422 d->m_activeWidget = savedActiveWidget;
00423 }
00424
00425 if ( d->m_activePart )
00426 {
00427 if ( !widget )
00428 d->m_activeWidget = part->widget();
00429
00430 PartActivateEvent ev( true, d->m_activePart, d->m_activeWidget );
00431 QApplication::sendEvent( d->m_activePart, &ev );
00432 if ( d->m_activeWidget )
00433 {
00434 connect( d->m_activeWidget, SIGNAL( destroyed() ),
00435 this, SLOT( slotWidgetDestroyed() ) );
00436 QApplication::sendEvent( d->m_activeWidget, &ev );
00437 }
00438 }
00439
00440 setActiveInstance( d->m_activePart ? d->m_activePart->instance() : 0L );
00441
00442 kdDebug(1000) << this << " emitting activePartChanged " << d->m_activePart << endl;
00443 emit activePartChanged( d->m_activePart );
00444 }
00445
00446 void PartManager::setActiveInstance( KInstance * instance )
00447 {
00448
00449 KGlobal::_activeInstance = instance;
00450 }
00451
00452 Part *PartManager::activePart() const
00453 {
00454 return d->m_activePart;
00455 }
00456
00457 QWidget *PartManager::activeWidget() const
00458 {
00459 return d->m_activeWidget;
00460 }
00461
00462 void PartManager::setSelectedPart( Part *part, QWidget *widget )
00463 {
00464 if ( part == d->m_selectedPart && widget == d->m_selectedWidget )
00465 return;
00466
00467 Part *oldPart = d->m_selectedPart;
00468 QWidget *oldWidget = d->m_selectedWidget;
00469
00470 d->m_selectedPart = part;
00471 d->m_selectedWidget = widget;
00472
00473 if ( part && !widget )
00474 d->m_selectedWidget = part->widget();
00475
00476 if ( oldPart )
00477 {
00478 PartSelectEvent ev( false, oldPart, oldWidget );
00479 QApplication::sendEvent( oldPart, &ev );
00480 QApplication::sendEvent( oldWidget, &ev );
00481 }
00482
00483 if ( d->m_selectedPart )
00484 {
00485 PartSelectEvent ev( true, d->m_selectedPart, d->m_selectedWidget );
00486 QApplication::sendEvent( d->m_selectedPart, &ev );
00487 QApplication::sendEvent( d->m_selectedWidget, &ev );
00488 }
00489 }
00490
00491 Part *PartManager::selectedPart() const
00492 {
00493 return d->m_selectedPart;
00494 }
00495
00496 QWidget *PartManager::selectedWidget() const
00497 {
00498 return d->m_selectedWidget;
00499 }
00500
00501 void PartManager::slotObjectDestroyed()
00502 {
00503 kdDebug(1000) << "KPartManager::slotObjectDestroyed()" << endl;
00504 removePart( const_cast<Part *>( static_cast<const Part *>( sender() ) ) );
00505 }
00506
00507 void PartManager::slotWidgetDestroyed()
00508 {
00509 kdDebug(1000) << "KPartsManager::slotWidgetDestroyed()" << endl;
00510 if ( static_cast<const QWidget *>( sender() ) == d->m_activeWidget )
00511 setActivePart( 0L );
00512
00513 }
00514
00515 const QPtrList<Part> *PartManager::parts() const
00516 {
00517 return &d->m_parts;
00518 }
00519
00520 void PartManager::addManagedTopLevelWidget( const QWidget *topLevel )
00521 {
00522 if ( !topLevel->isTopLevel() )
00523 return;
00524
00525 if ( d->m_managedTopLevelWidgets.containsRef( topLevel ) )
00526 return;
00527
00528 d->m_managedTopLevelWidgets.append( topLevel );
00529 connect( topLevel, SIGNAL( destroyed() ),
00530 this, SLOT( slotManagedTopLevelWidgetDestroyed() ) );
00531 }
00532
00533 void PartManager::removeManagedTopLevelWidget( const QWidget *topLevel )
00534 {
00535 if ( !topLevel->isTopLevel() )
00536 return;
00537
00538 if ( d->m_managedTopLevelWidgets.findRef( topLevel ) == -1 )
00539 return;
00540
00541 d->m_managedTopLevelWidgets.remove();
00542 }
00543
00544 void PartManager::slotManagedTopLevelWidgetDestroyed()
00545 {
00546 const QWidget *widget = static_cast<const QWidget *>( sender() );
00547 removeManagedTopLevelWidget( widget );
00548 }
00549
00550 void PartManager::virtual_hook( int, void* )
00551 { }
00552
00553 #include "partmanager.moc"