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 #include <kdebugclasses.h>
00027
00028 #include <qapplication.h>
00029
00030
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
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;
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 )
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 )
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 )
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
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
00341
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
00356
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;
00377 }
00378
00379
00380
00381 if ( part && !d->m_bAllowNestedParts )
00382 {
00383 QObject *parentPart = part->parent();
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
00393
00394
00395
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
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
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 );
00513
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 { }
00553
00554 #include "partmanager.moc"