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 <QtGui/QApplication>
00028 #include <QtGui/QScrollBar>
00029 #include <kcomponentdata.h>
00030
00031
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
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;
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 )
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 )
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
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
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
00376
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
00394
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) << "trying to activate a non-registered part!" << part->objectName();
00414 return;
00415 }
00416
00417
00418
00419 if ( part && !d->m_bAllowNestedParts )
00420 {
00421 QObject *parentPart = part->parent();
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
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
00481 setActiveComponent(d->m_activePart ? d->m_activePart->componentData() : KGlobal::mainComponent());
00482
00483 #ifdef DEBUG_PARTMANAGER
00484 kDebug(1000) << this << " emitting activePartChanged " << d->m_activePart;
00485 #endif
00486 emit activePartChanged( d->m_activePart );
00487 }
00488
00489 void PartManager::setActiveComponent(const KComponentData &instance)
00490 {
00491
00492 KGlobal::setActiveComponent(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 kDebug(1000);
00547 removePart( const_cast<Part *>( static_cast<const Part *>( sender() ) ) );
00548 }
00549
00550 void PartManager::slotWidgetDestroyed()
00551 {
00552 kDebug(1000);
00553 if ( static_cast<const QWidget *>( sender() ) == d->m_activeWidget )
00554 setActivePart( 0 );
00555
00556 }
00557
00558 const QList<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.contains( 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 d->m_managedTopLevelWidgets.removeAll( topLevel );
00582 }
00583
00584 void PartManager::slotManagedTopLevelWidgetDestroyed()
00585 {
00586 const QWidget *widget = static_cast<const QWidget *>( sender() );
00587 removeManagedTopLevelWidget( widget );
00588 }
00589
00590 int PartManager::reason() const
00591 {
00592 return d->m_reason;
00593 }
00594
00595 #include "partmanager.moc"