kparts Library API Documentation

partmanager.cpp

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., 59 Temple Place - Suite 330, 00018 Boston, MA 02111-1307, 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 <qapplication.h> 00028 00029 //#define DEBUG_PARTMANAGER 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 // core dumps ... setActivePart( 0L ); 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; // ignore this button 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 ) // mouse press or mouse double-click event 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 ) // We found a part whose widget is w 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 ) // don't add parts more than once :) 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 // Prevent focus problems 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 //Warning. The part could be already deleted 00340 //kdDebug(1000) << QString("Part %1 removed").arg(part->name()) << endl; 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 //kdDebug(1000) << "replacePart " << oldPart->name() << "-> " << newPart->name() << " setActive=" << setActive << endl; 00355 // This methods does exactly removePart + addPart but without calling setActivePart(0) in between 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; // don't allow someone call setActivePart with a part we don't know about 00376 } 00377 00378 //check whether nested parts are disallowed and activate the top parent part then, by traversing the 00379 //tree recursively (Simon) 00380 if ( part && !d->m_bAllowNestedParts ) 00381 { 00382 QObject *parentPart = part->parent(); // ### this relies on people using KParts::Factory! 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 //kdDebug() << "PartManager::setActivePart d->m_activePart=" << d->m_activePart << "<->part=" << part 00392 // << " d->m_activeWidget=" << d->m_activeWidget << "<->widget=" << widget << endl; 00393 00394 // don't activate twice 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 // Set the new active instance in KGlobal 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 // It's a separate method to allow redefining this behavior 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 ); //do not remove the part because if the part's widget dies, then the 00512 //part will delete itself anyway, invoking removePart() in its destructor 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 { /*BASE::virtual_hook( id, data );*/ } 00552 00553 #include "partmanager.moc"
KDE Logo
This file is part of the documentation for kparts Library Version 3.2.3.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Wed Mar 16 17:22:50 2005 by doxygen 1.3.7 written by Dimitri van Heesch, © 1997-2003