27 #include <QtGui/QApplication>
28 #include <QtGui/QScrollBar>
33 using namespace KParts;
37 class PartManagerPrivate
46 m_bAllowNestedParts =
false;
47 m_bIgnoreScrollBars =
false;
48 m_activationButtonMask = Qt::LeftButton | Qt::MidButton | Qt::RightButton;
50 m_bIgnoreExplicitFocusRequest =
false;
55 void setReason(
QEvent* ev ) {
56 switch( ev->type() ) {
57 case QEvent::MouseButtonPress:
58 case QEvent::MouseButtonDblClick: {
59 QMouseEvent* mev =
static_cast<QMouseEvent *
>( ev );
60 m_reason = mev->button() == Qt::LeftButton
62 : ( mev->button() == Qt::MidButton
68 m_reason =
static_cast<QFocusEvent *
>( ev )->reason();
71 kWarning(1000) <<
"PartManagerPrivate::setReason got unexpected ev type " << ev->type();
76 bool allowExplicitFocusEvent(
QEvent* ev)
const
78 if (ev->type() == QEvent::FocusIn) {
79 QFocusEvent* fev =
static_cast<QFocusEvent*
>(ev);
80 return (!m_bIgnoreExplicitFocusRequest || fev->reason() != Qt::OtherFocusReason);
88 QList<Part *> m_parts;
95 QList<const QWidget *> m_managedTopLevelWidgets;
96 short int m_activationButtonMask;
97 bool m_bIgnoreScrollBars;
98 bool m_bAllowNestedParts;
100 bool m_bIgnoreExplicitFocusRequest;
106 :
QObject( parent ),d(new PartManagerPrivate)
109 qApp->installEventFilter(
this );
117 :
QObject( parent ),d(new PartManagerPrivate)
120 qApp->installEventFilter(
this );
129 foreach(
const QWidget* w, d->m_managedTopLevelWidgets )
131 disconnect( w, SIGNAL(destroyed()),
135 foreach(
Part* it, d->m_parts )
141 qApp->removeEventFilter(
this );
147 d->m_policy = policy;
157 d->m_bAllowNestedParts = allow;
162 return d->m_bAllowNestedParts;
167 d->m_bIgnoreScrollBars = ignore;
172 return d->m_bIgnoreScrollBars;
177 d->m_activationButtonMask = buttonMask;
182 return d->m_activationButtonMask;
188 if ( ev->type() != QEvent::MouseButtonPress &&
189 ev->type() != QEvent::MouseButtonDblClick &&
190 ev->type() != QEvent::FocusIn )
193 if ( !obj->isWidgetType() )
198 if ( ( ( w->windowFlags().testFlag(Qt::Dialog) ) && w->isModal() ) ||
199 ( w->windowFlags().testFlag(Qt::Popup) ) || ( w->windowFlags().testFlag(Qt::Tool) ) )
202 QMouseEvent* mev = 0;
203 if ( ev->type() == QEvent::MouseButtonPress || ev->type() == QEvent::MouseButtonDblClick )
205 mev =
static_cast<QMouseEvent *
>( ev );
206 #ifdef DEBUG_PARTMANAGER
207 kDebug(1000) <<
"PartManager::eventFilter button: " << mev->button() <<
" " <<
"d->m_activationButtonMask=" << d->m_activationButtonMask;
209 if ( ( mev->button() & d->m_activationButtonMask ) == 0 )
218 if ( !d->m_managedTopLevelWidgets.contains( w->topLevelWidget() ) )
221 if ( d->m_bIgnoreScrollBars && ::qobject_cast<QScrollBar *>(w) )
226 pos = mev->globalPos();
227 part = findPartFromWidget( w, pos );
229 part = findPartFromWidget( w );
231 #ifdef DEBUG_PARTMANAGER
232 const char* evType = ( ev->type() == QEvent::MouseButtonPress ) ?
"MouseButtonPress"
233 : ( ev->type() == QEvent::MouseButtonDblClick ) ?
"MouseButtonDblClick"
234 : ( ev->type() == QEvent::FocusIn ) ?
"FocusIn" :
"OTHER! ERROR!";
240 if ( ev->type() == QEvent::MouseButtonDblClick )
242 if ( part == d->m_activePart && w == d->m_activeWidget )
245 #ifdef DEBUG_PARTMANAGER
246 kDebug(1000) <<
"PartManager::eventFilter dblclick -> setActivePart" << part;
254 if ( ( d->m_selectedWidget != w || d->m_selectedPart != part ) &&
255 ( d->m_activeWidget != w || d->m_activePart != part ) )
260 #ifdef DEBUG_PARTMANAGER
261 kDebug(1000) <<
"Part " << part <<
" (non-selectable) made active because " << w->metaObject()->className() <<
" got event" <<
" " << evType;
269 else if ( d->m_selectedWidget == w && d->m_selectedPart == part )
271 #ifdef DEBUG_PARTMANAGER
272 kDebug(1000) <<
"Part " << part <<
" made active (from selected) because " << w->metaObject()->className() <<
" got event" <<
" " << evType;
279 else if ( d->m_activeWidget == w && d->m_activePart == part )
287 else if ( part != d->m_activePart && d->allowExplicitFocusEvent(ev) )
289 #ifdef DEBUG_PARTMANAGER
290 kDebug(1000) <<
"Part " << part <<
" made active because " << w->metaObject()->className() <<
" got event" <<
" " << evType;
300 w = w->parentWidget();
302 if ( w && ( ( ( w->windowFlags() & Qt::Dialog ) && w->isModal() ) ||
303 ( w->windowFlags() & Qt::Popup ) || ( w->windowFlags() & Qt::Tool ) ) )
305 #ifdef DEBUG_PARTMANAGER
306 kDebug(1000) <<
QString(
"No part made active although %1/%2 got event - loop aborted").arg(obj->objectName()).arg(obj->metaObject()->className());
313 #ifdef DEBUG_PARTMANAGER
314 kDebug(1000) <<
QString(
"No part made active although %1/%2 got event").arg(obj->objectName()).arg(obj->metaObject()->className());
321 for ( QList<Part *>::iterator it = d->m_parts.begin(),
end = d->m_parts.end() ; it !=
end ; ++it )
324 if ( part && d->m_parts.contains( part ) )
330 Part * PartManager::findPartFromWidget(
QWidget * widget )
332 for ( QList<Part *>::iterator it = d->m_parts.begin(),
end = d->m_parts.end() ; it !=
end ; ++it )
334 if ( widget == (*it)->widget() )
345 if ( d->m_parts.contains( part ) ) {
346 #ifdef DEBUG_PARTMANAGER
347 kWarning(1000) << part <<
" already added" << kBacktrace(5);
352 d->m_parts.append( part );
361 if ( w->focusPolicy() == Qt::NoFocus ) {
362 kWarning(1000) <<
"Part '" << part->objectName() <<
"' has a widget "
363 << w->objectName() <<
" with a focus policy of NoFocus. It should have at least a"
364 <<
"ClickFocus policy, for part activation to work well." << endl;
366 if ( part->
widget() && part->
widget()->focusPolicy() == Qt::TabFocus ) {
367 kWarning(1000) <<
"Part '" << part->objectName() <<
"' has a widget "
368 << w->objectName() <<
" with a focus policy of TabFocus. It should have at least a"
369 <<
"ClickFocus policy, for part activation to work well." << endl;
380 if (!d->m_parts.contains(part)) {
384 const int nb = d->m_parts.removeAll(part);
391 if ( part == d->m_activePart )
393 if ( part == d->m_selectedPart )
401 if ( !d->m_parts.contains( oldPart ) )
403 kFatal(1000) <<
QString(
"Can't remove part %1, not in KPartManager's list.").arg(oldPart->objectName());
407 d->m_parts.removeAll( oldPart );
417 if ( part && !d->m_parts.contains( part ) )
419 kWarning(1000) <<
"trying to activate a non-registered part!" << part->objectName();
425 if ( part && !d->m_bAllowNestedParts )
427 QObject *parentPart = part->parent();
436 #ifdef DEBUG_PARTMANAGER
437 kDebug(1000) <<
"PartManager::setActivePart d->m_activePart=" << d->m_activePart <<
"<->part=" << part
438 <<
" d->m_activeWidget=" << d->m_activeWidget <<
"<->widget=" << widget << endl;
442 if ( d->m_activePart && part && d->m_activePart == part &&
443 (!widget || d->m_activeWidget == widget) )
447 QWidget *oldActiveWidget = d->m_activeWidget;
451 d->m_activePart = part;
452 d->m_activeWidget = widget;
457 QWidget *savedActiveWidget = widget;
460 QApplication::sendEvent( oldActivePart, &ev );
461 if ( oldActiveWidget )
463 disconnect( oldActiveWidget, SIGNAL(destroyed()),
465 QApplication::sendEvent( oldActiveWidget, &ev );
468 d->m_activePart = savedActivePart;
469 d->m_activeWidget = savedActiveWidget;
472 if ( d->m_activePart )
475 d->m_activeWidget = part->
widget();
478 QApplication::sendEvent( d->m_activePart, &ev );
479 if ( d->m_activeWidget )
481 connect( d->m_activeWidget, SIGNAL(destroyed()),
483 QApplication::sendEvent( d->m_activeWidget, &ev );
489 #ifdef DEBUG_PARTMANAGER
490 kDebug(1000) <<
this <<
" emitting activePartChanged " << d->m_activePart;
503 return d->m_activePart;
508 return d->m_activeWidget;
513 if ( part == d->m_selectedPart && widget == d->m_selectedWidget )
516 Part *oldPart = d->m_selectedPart;
517 QWidget *oldWidget = d->m_selectedWidget;
519 d->m_selectedPart = part;
520 d->m_selectedWidget = widget;
522 if ( part && !widget )
523 d->m_selectedWidget = part->
widget();
528 QApplication::sendEvent( oldPart, &ev );
529 QApplication::sendEvent( oldWidget, &ev );
532 if ( d->m_selectedPart )
535 QApplication::sendEvent( d->m_selectedPart, &ev );
536 QApplication::sendEvent( d->m_selectedWidget, &ev );
542 return d->m_selectedPart;
547 return d->m_selectedWidget;
553 removePart( const_cast<Part *>( static_cast<const Part *>( sender() ) ) );
559 if ( static_cast<const QWidget *>( sender() ) == d->m_activeWidget )
571 if ( !topLevel->isTopLevel() )
574 if ( d->m_managedTopLevelWidgets.contains( topLevel ) )
577 d->m_managedTopLevelWidgets.append( topLevel );
578 connect( topLevel, SIGNAL(destroyed()),
584 if ( !topLevel->isTopLevel() )
587 d->m_managedTopLevelWidgets.removeAll( topLevel );
603 d->m_bIgnoreExplicitFocusRequest = ignore;
606 #include "partmanager.moc"