TDE core libraries
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

partmanager.cpp 17KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601
  1. // -*- mode: c++; c-basic-offset: 2 -*-
  2. /* This file is part of the KDE project
  3. Copyright (C) 1999 Simon Hausmann <hausmann@kde.org>
  4. (C) 1999 David Faure <faure@kde.org>
  5. This library is free software; you can redistribute it and/or
  6. modify it under the terms of the GNU Library General Public
  7. License as published by the Free Software Foundation; either
  8. version 2 of the License, or (at your option) any later version.
  9. This library is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. Library General Public License for more details.
  13. You should have received a copy of the GNU Library General Public License
  14. along with this library; see the file COPYING.LIB. If not, write to
  15. the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  16. Boston, MA 02110-1301, USA.
  17. */
  18. #include "partmanager.h"
  19. #include <tdeparts/event.h>
  20. #include <tdeparts/part.h>
  21. #include <tdeglobal.h>
  22. #include <kdebug.h>
  23. #include <tqapplication.h>
  24. //#define DEBUG_PARTMANAGER
  25. using namespace KParts;
  26. template class TQPtrList<Part>;
  27. namespace KParts {
  28. class PartManagerPrivate
  29. {
  30. public:
  31. PartManagerPrivate()
  32. {
  33. m_activeWidget = 0;
  34. m_activePart = 0;
  35. m_selectedPart = 0;
  36. m_selectedWidget = 0;
  37. m_bAllowNestedParts = false;
  38. m_bIgnoreScrollBars = false;
  39. m_activationButtonMask = Qt::LeftButton | Qt::MidButton | Qt::RightButton;
  40. m_reason = PartManager::NoReason;
  41. }
  42. ~PartManagerPrivate()
  43. {
  44. }
  45. void setReason( TQEvent* ev ) {
  46. switch( ev->type() ) {
  47. case TQEvent::MouseButtonPress:
  48. case TQEvent::MouseButtonDblClick: {
  49. TQMouseEvent* mev = TQT_TQMOUSEEVENT( ev );
  50. m_reason = mev->button() == Qt::LeftButton
  51. ? PartManager::ReasonLeftClick
  52. : ( mev->button() == Qt::MidButton
  53. ? PartManager::ReasonMidClick
  54. : PartManager::ReasonRightClick );
  55. break;
  56. }
  57. case TQEvent::FocusIn:
  58. m_reason = TQT_TQFOCUSEVENT( ev )->reason();
  59. break;
  60. default:
  61. kdWarning(1000) << "PartManagerPrivate::setReason got unexpected ev type " << ev->type() << endl;
  62. break;
  63. }
  64. }
  65. Part * m_activePart;
  66. TQWidget *m_activeWidget;
  67. TQPtrList<Part> m_parts;
  68. PartManager::SelectionPolicy m_policy;
  69. Part *m_selectedPart;
  70. TQWidget *m_selectedWidget;
  71. TQPtrList<TQWidget> m_managedTopLevelWidgets;
  72. short int m_activationButtonMask;
  73. bool m_bIgnoreScrollBars;
  74. bool m_bAllowNestedParts;
  75. int m_reason;
  76. };
  77. }
  78. PartManager::PartManager( TQWidget * parent, const char * name )
  79. : TQObject( parent, name )
  80. {
  81. d = new PartManagerPrivate;
  82. tqApp->installEventFilter( this );
  83. d->m_policy = Direct;
  84. addManagedTopLevelWidget( parent );
  85. }
  86. PartManager::PartManager( TQWidget *topLevel, TQObject *parent, const char *name )
  87. : TQObject( parent, name )
  88. {
  89. d = new PartManagerPrivate;
  90. tqApp->installEventFilter( this );
  91. d->m_policy = Direct;
  92. addManagedTopLevelWidget( topLevel );
  93. }
  94. PartManager::~PartManager()
  95. {
  96. for ( TQPtrListIterator<TQWidget> it( d->m_managedTopLevelWidgets );
  97. it.current(); ++it )
  98. disconnect( it.current(), TQT_SIGNAL( destroyed() ),
  99. this, TQT_SLOT( slotManagedTopLevelWidgetDestroyed() ) );
  100. for ( TQPtrListIterator<Part> it( d->m_parts ); it.current(); ++it )
  101. {
  102. it.current()->setManager( 0 );
  103. }
  104. // core dumps ... setActivePart( 0L );
  105. tqApp->removeEventFilter( this );
  106. delete d;
  107. }
  108. void PartManager::setSelectionPolicy( SelectionPolicy policy )
  109. {
  110. d->m_policy = policy;
  111. }
  112. PartManager::SelectionPolicy PartManager::selectionPolicy() const
  113. {
  114. return d->m_policy;
  115. }
  116. void PartManager::setAllowNestedParts( bool allow )
  117. {
  118. d->m_bAllowNestedParts = allow;
  119. }
  120. bool PartManager::allowNestedParts() const
  121. {
  122. return d->m_bAllowNestedParts;
  123. }
  124. void PartManager::setIgnoreScrollBars( bool ignore )
  125. {
  126. d->m_bIgnoreScrollBars = ignore;
  127. }
  128. bool PartManager::ignoreScrollBars() const
  129. {
  130. return d->m_bIgnoreScrollBars;
  131. }
  132. void PartManager::setActivationButtonMask( short int buttonMask )
  133. {
  134. d->m_activationButtonMask = buttonMask;
  135. }
  136. short int PartManager::activationButtonMask() const
  137. {
  138. return d->m_activationButtonMask;
  139. }
  140. bool PartManager::eventFilter( TQObject *obj, TQEvent *ev )
  141. {
  142. if ( ev->type() != TQEvent::MouseButtonPress &&
  143. ev->type() != TQEvent::MouseButtonDblClick &&
  144. ev->type() != TQEvent::FocusIn )
  145. return false;
  146. if ( !obj->isWidgetType() )
  147. return false;
  148. TQWidget *w = TQT_TQWIDGET( obj );
  149. if ( ( w->testWFlags( WType_Dialog ) && w->isModal() ) ||
  150. w->testWFlags( WType_Popup ) || w->testWFlags( WStyle_Tool ) )
  151. return false;
  152. TQMouseEvent* mev = 0L;
  153. if ( ev->type() == TQEvent::MouseButtonPress || ev->type() == TQEvent::MouseButtonDblClick )
  154. {
  155. mev = TQT_TQMOUSEEVENT( ev );
  156. #ifdef DEBUG_PARTMANAGER
  157. kdDebug(1000) << "PartManager::eventFilter button: " << mev->button() << " " << "d->m_activationButtonMask=" << d->m_activationButtonMask << endl;
  158. #endif
  159. if ( ( mev->button() & d->m_activationButtonMask ) == 0 )
  160. return false; // ignore this button
  161. }
  162. Part * part;
  163. while ( w )
  164. {
  165. TQPoint pos;
  166. if ( !d->m_managedTopLevelWidgets.containsRef( w->topLevelWidget() ) )
  167. return false;
  168. if ( d->m_bIgnoreScrollBars && w->inherits( TQSCROLLBAR_OBJECT_NAME_STRING ) )
  169. return false;
  170. if ( mev ) // mouse press or mouse double-click event
  171. {
  172. pos = mev->globalPos();
  173. part = findPartFromWidget( w, pos );
  174. } else
  175. part = findPartFromWidget( w );
  176. #ifdef DEBUG_PARTMANAGER
  177. TQCString evType = ( ev->type() == TQEvent::MouseButtonPress ) ? "MouseButtonPress"
  178. : ( ev->type() == TQEvent::MouseButtonDblClick ) ? "MouseButtonDblClick"
  179. : ( ev->type() == TQEvent::FocusIn ) ? "FocusIn" : "OTHER! ERROR!";
  180. #endif
  181. if ( part ) // We found a part whose widget is w
  182. {
  183. if ( d->m_policy == PartManager::TriState )
  184. {
  185. if ( ev->type() == TQEvent::MouseButtonDblClick )
  186. {
  187. if ( part == d->m_activePart && w == d->m_activeWidget )
  188. return false;
  189. #ifdef DEBUG_PARTMANAGER
  190. kdDebug(1000) << "PartManager::eventFilter dblclick -> setActivePart" << part << endl;
  191. #endif
  192. d->setReason( ev );
  193. setActivePart( part, w );
  194. d->m_reason = NoReason;
  195. return true;
  196. }
  197. if ( ( d->m_selectedWidget != w || d->m_selectedPart != part ) &&
  198. ( d->m_activeWidget != w || d->m_activePart != part ) )
  199. {
  200. if ( part->isSelectable() )
  201. setSelectedPart( part, w );
  202. else {
  203. #ifdef DEBUG_PARTMANAGER
  204. kdDebug(1000) << "Part " << part << " (non-selectable) made active because " << w->className() << " got event" << " " << evType << endl;
  205. #endif
  206. d->setReason( ev );
  207. setActivePart( part, w );
  208. d->m_reason = NoReason;
  209. }
  210. return true;
  211. }
  212. else if ( d->m_selectedWidget == w && d->m_selectedPart == part )
  213. {
  214. #ifdef DEBUG_PARTMANAGER
  215. kdDebug(1000) << "Part " << part << " made active (from selected) because " << w->className() << " got event" << " " << evType << endl;
  216. #endif
  217. d->setReason( ev );
  218. setActivePart( part, w );
  219. d->m_reason = NoReason;
  220. return true;
  221. }
  222. else if ( d->m_activeWidget == w && d->m_activePart == part )
  223. {
  224. setSelectedPart( 0L );
  225. return false;
  226. }
  227. return false;
  228. }
  229. else if ( part != d->m_activePart )
  230. {
  231. #ifdef DEBUG_PARTMANAGER
  232. kdDebug(1000) << "Part " << part << " made active because " << w->className() << " got event" << " " << evType << endl;
  233. #endif
  234. d->setReason( ev );
  235. setActivePart( part, w );
  236. d->m_reason = NoReason;
  237. }
  238. return false;
  239. }
  240. w = w->parentWidget();
  241. if ( w && ( ( w->testWFlags( WType_Dialog ) && w->isModal() ) ||
  242. w->testWFlags( WType_Popup ) || w->testWFlags( WStyle_Tool ) ) )
  243. {
  244. #ifdef DEBUG_PARTMANAGER
  245. kdDebug(1000) << TQString("No part made active although %1/%2 got event - loop aborted").arg(obj->name()).arg(obj->className()) << endl;
  246. #endif
  247. return false;
  248. }
  249. }
  250. #ifdef DEBUG_PARTMANAGER
  251. kdDebug(1000) << TQString("No part made active although %1/%2 got event").arg(obj->name()).arg(obj->className()) << endl;
  252. #endif
  253. return false;
  254. }
  255. Part * PartManager::findPartFromWidget( TQWidget * widget, const TQPoint &pos )
  256. {
  257. TQPtrListIterator<Part> it ( d->m_parts );
  258. for ( ; it.current() ; ++it )
  259. {
  260. Part *part = it.current()->hitTest( widget, pos );
  261. if ( part && d->m_parts.findRef( part ) != -1 )
  262. return part;
  263. }
  264. return 0L;
  265. }
  266. Part * PartManager::findPartFromWidget( TQWidget * widget )
  267. {
  268. TQPtrListIterator<Part> it ( d->m_parts );
  269. for ( ; it.current() ; ++it )
  270. {
  271. if ( widget == it.current()->widget() )
  272. return it.current();
  273. }
  274. return 0L;
  275. }
  276. void PartManager::addPart( Part *part, bool setActive )
  277. {
  278. if ( d->m_parts.findRef( part ) != -1 ) // don't add parts more than once :)
  279. {
  280. #ifdef DEBUG_PARTMANAGER
  281. kdWarning(1000) << k_funcinfo << part << " already added" << kdBacktrace(5) << endl;
  282. #endif
  283. return;
  284. }
  285. d->m_parts.append( part );
  286. part->setManager( this );
  287. if ( setActive )
  288. {
  289. setActivePart( part );
  290. if ( part->widget() )
  291. part->widget()->setFocus();
  292. }
  293. // Prevent focus problems
  294. if ( part->widget() && part->widget()->focusPolicy() == TQ_NoFocus )
  295. {
  296. 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;
  297. }
  298. if ( part->widget() && part->widget()->focusPolicy() == TQ_TabFocus )
  299. {
  300. 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;
  301. }
  302. if ( setActive && part->widget() )
  303. part->widget()->show();
  304. emit partAdded( part );
  305. }
  306. void PartManager::removePart( Part *part )
  307. {
  308. if ( d->m_parts.findRef( part ) == -1 )
  309. {
  310. kdFatal(1000) << TQString(TQString("Can't remove part %1, not in KPartManager's list.").arg(part->name())) << endl;
  311. return;
  312. }
  313. //Warning. The part could be already deleted
  314. //kdDebug(1000) << TQString("Part %1 removed").arg(part->name()) << endl;
  315. int nb = d->m_parts.count();
  316. bool ok = d->m_parts.removeRef( part );
  317. Q_ASSERT( ok );
  318. Q_ASSERT( (int)d->m_parts.count() == nb-1 );
  319. part->setManager(0);
  320. emit partRemoved( part );
  321. if ( part == d->m_activePart )
  322. setActivePart( 0 );
  323. if ( part == d->m_selectedPart )
  324. setSelectedPart( 0 );
  325. }
  326. void PartManager::replacePart( Part * oldPart, Part * newPart, bool setActive )
  327. {
  328. //kdDebug(1000) << "replacePart " << oldPart->name() << "-> " << newPart->name() << " setActive=" << setActive << endl;
  329. // This methods does exactly removePart + addPart but without calling setActivePart(0) in between
  330. if ( d->m_parts.findRef( oldPart ) == -1 )
  331. {
  332. kdFatal(1000) << TQString(TQString("Can't remove part %1, not in KPartManager's list.").arg(oldPart->name())) << endl;
  333. return;
  334. }
  335. d->m_parts.removeRef( oldPart );
  336. oldPart->setManager(0);
  337. emit partRemoved( oldPart );
  338. addPart( newPart, setActive );
  339. }
  340. void PartManager::setActivePart( Part *part, TQWidget *widget )
  341. {
  342. if ( part && d->m_parts.findRef( part ) == -1 )
  343. {
  344. kdWarning( 1000 ) << "PartManager::setActivePart : trying to activate a non-registered part! " << part->name() << endl;
  345. return; // don't allow someone call setActivePart with a part we don't know about
  346. }
  347. //check whether nested parts are disallowed and activate the top parent part then, by traversing the
  348. //tree recursively (Simon)
  349. if ( part && !d->m_bAllowNestedParts )
  350. {
  351. TQObject *parentPart = TQT_TQOBJECT(part->parent()); // ### this relies on people using KParts::Factory!
  352. if ( parentPart && parentPart->inherits( "KParts::Part" ) )
  353. {
  354. KParts::Part *parPart = static_cast<KParts::Part *>( parentPart );
  355. setActivePart( parPart, parPart->widget() );
  356. return;
  357. }
  358. }
  359. #ifdef DEBUG_PARTMANAGER
  360. kdDebug(1000) << "PartManager::setActivePart d->m_activePart=" << d->m_activePart << "<->part=" << part
  361. << " d->m_activeWidget=" << d->m_activeWidget << "<->widget=" << widget << endl;
  362. #endif
  363. // don't activate twice
  364. if ( d->m_activePart && part && d->m_activePart == part &&
  365. (!widget || d->m_activeWidget == widget) )
  366. return;
  367. KParts::Part *oldActivePart = d->m_activePart;
  368. TQWidget *oldActiveWidget = d->m_activeWidget;
  369. setSelectedPart( 0L );
  370. d->m_activePart = part;
  371. d->m_activeWidget = widget;
  372. if ( oldActivePart )
  373. {
  374. KParts::Part *savedActivePart = part;
  375. TQWidget *savedActiveWidget = widget;
  376. PartActivateEvent ev( false, oldActivePart, oldActiveWidget );
  377. TQApplication::sendEvent( oldActivePart, &ev );
  378. if ( oldActiveWidget )
  379. {
  380. disconnect( oldActiveWidget, TQT_SIGNAL( destroyed() ),
  381. this, TQT_SLOT( slotWidgetDestroyed() ) );
  382. TQApplication::sendEvent( oldActiveWidget, &ev );
  383. }
  384. d->m_activePart = savedActivePart;
  385. d->m_activeWidget = savedActiveWidget;
  386. }
  387. if ( d->m_activePart )
  388. {
  389. if ( !widget )
  390. d->m_activeWidget = part->widget();
  391. PartActivateEvent ev( true, d->m_activePart, d->m_activeWidget );
  392. TQApplication::sendEvent( d->m_activePart, &ev );
  393. if ( d->m_activeWidget )
  394. {
  395. connect( d->m_activeWidget, TQT_SIGNAL( destroyed() ),
  396. this, TQT_SLOT( slotWidgetDestroyed() ) );
  397. TQApplication::sendEvent( d->m_activeWidget, &ev );
  398. }
  399. }
  400. // Set the new active instance in TDEGlobal
  401. setActiveInstance( d->m_activePart ? d->m_activePart->instance() : 0L );
  402. kdDebug(1000) << this << " emitting activePartChanged " << d->m_activePart << endl;
  403. emit activePartChanged( d->m_activePart );
  404. }
  405. void PartManager::setActiveInstance( TDEInstance * instance )
  406. {
  407. // It's a separate method to allow redefining this behavior
  408. TDEGlobal::_activeInstance = instance;
  409. }
  410. Part *PartManager::activePart() const
  411. {
  412. return d->m_activePart;
  413. }
  414. TQWidget *PartManager::activeWidget() const
  415. {
  416. return d->m_activeWidget;
  417. }
  418. void PartManager::setSelectedPart( Part *part, TQWidget *widget )
  419. {
  420. if ( part == d->m_selectedPart && widget == d->m_selectedWidget )
  421. return;
  422. Part *oldPart = d->m_selectedPart;
  423. TQWidget *oldWidget = d->m_selectedWidget;
  424. d->m_selectedPart = part;
  425. d->m_selectedWidget = widget;
  426. if ( part && !widget )
  427. d->m_selectedWidget = part->widget();
  428. if ( oldPart )
  429. {
  430. PartSelectEvent ev( false, oldPart, oldWidget );
  431. TQApplication::sendEvent( oldPart, &ev );
  432. TQApplication::sendEvent( oldWidget, &ev );
  433. }
  434. if ( d->m_selectedPart )
  435. {
  436. PartSelectEvent ev( true, d->m_selectedPart, d->m_selectedWidget );
  437. TQApplication::sendEvent( d->m_selectedPart, &ev );
  438. TQApplication::sendEvent( d->m_selectedWidget, &ev );
  439. }
  440. }
  441. Part *PartManager::selectedPart() const
  442. {
  443. return d->m_selectedPart;
  444. }
  445. TQWidget *PartManager::selectedWidget() const
  446. {
  447. return d->m_selectedWidget;
  448. }
  449. void PartManager::slotObjectDestroyed()
  450. {
  451. kdDebug(1000) << "KPartManager::slotObjectDestroyed()" << endl;
  452. removePart( const_cast<Part *>( static_cast<const Part *>( sender() ) ) );
  453. }
  454. void PartManager::slotWidgetDestroyed()
  455. {
  456. kdDebug(1000) << "KPartsManager::slotWidgetDestroyed()" << endl;
  457. if ( static_cast<const TQWidget *>( sender() ) == d->m_activeWidget )
  458. setActivePart( 0L ); //do not remove the part because if the part's widget dies, then the
  459. //part will delete itself anyway, invoking removePart() in its destructor
  460. }
  461. const TQPtrList<Part> *PartManager::parts() const
  462. {
  463. return &d->m_parts;
  464. }
  465. void PartManager::addManagedTopLevelWidget( const TQWidget *topLevel )
  466. {
  467. if ( !topLevel->isTopLevel() )
  468. return;
  469. if ( d->m_managedTopLevelWidgets.containsRef( topLevel ) )
  470. return;
  471. d->m_managedTopLevelWidgets.append( topLevel );
  472. connect( topLevel, TQT_SIGNAL( destroyed() ),
  473. this, TQT_SLOT( slotManagedTopLevelWidgetDestroyed() ) );
  474. }
  475. void PartManager::removeManagedTopLevelWidget( const TQWidget *topLevel )
  476. {
  477. if ( !topLevel->isTopLevel() )
  478. return;
  479. if ( d->m_managedTopLevelWidgets.findRef( topLevel ) == -1 )
  480. return;
  481. d->m_managedTopLevelWidgets.remove();
  482. }
  483. void PartManager::slotManagedTopLevelWidgetDestroyed()
  484. {
  485. const TQWidget *widget = static_cast<const TQWidget *>( sender() );
  486. removeManagedTopLevelWidget( widget );
  487. }
  488. int PartManager::reason() const
  489. {
  490. return d->m_reason;
  491. }
  492. void PartManager::virtual_hook( int, void* )
  493. { /*BASE::virtual_hook( id, data );*/ }
  494. #include "partmanager.moc"