KOffice – TDE office suite
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.

layerlist.cpp 37KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325
  1. /*
  2. Copyright (c) 2005 Gábor Lehel <illissius@gmail.com>
  3. This library is free software; you can redistribute it and/or
  4. modify it under the terms of the GNU Library General Public
  5. License as published by the Free Software Foundation; either
  6. version 2 of the License, or (at your option) any later version.
  7. This library is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  10. Library General Public License for more details.
  11. You should have received a copy of the GNU Library General Public License
  12. along with this library; see the file COPYING.LIB. If not, write to
  13. the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  14. Boston, MA 02110-1301, USA.
  15. */
  16. #include "layerlist.h"
  17. #include <tqtooltip.h>
  18. #include <tqbitmap.h>
  19. #include <tqcursor.h>
  20. #include <tqimage.h>
  21. #include <tqheader.h>
  22. #include <tqpainter.h>
  23. #include <tqpixmap.h>
  24. #include <tqsimplerichtext.h>
  25. #include <tqtimer.h>
  26. #include <tdeapplication.h>
  27. #include <kdebug.h>
  28. #include <tdeglobal.h>
  29. #include <tdeglobalsettings.h>
  30. #include <kiconloader.h>
  31. #include <klineedit.h>
  32. #include <tdelocale.h>
  33. #include <tdepopupmenu.h>
  34. #include <kstringhandler.h>
  35. class LayerItemIterator: public TQListViewItemIterator
  36. {
  37. public:
  38. LayerItemIterator( LayerList *list ): TQListViewItemIterator( list ) { }
  39. LayerItemIterator( LayerList *list, IteratorFlag flags ): TQListViewItemIterator( list, flags ) { }
  40. LayerItemIterator( LayerItem *item ): TQListViewItemIterator( item ) { }
  41. LayerItemIterator( LayerItem *item, IteratorFlag flags ): TQListViewItemIterator( item, flags ) { }
  42. LayerItem *operator*() { return static_cast<LayerItem*>( TQListViewItemIterator::operator*() ); }
  43. };
  44. struct LayerProperty
  45. {
  46. TQString name;
  47. TQString displayName;
  48. TQPixmap enabledIcon;
  49. TQPixmap disabledIcon;
  50. bool defaultValue;
  51. bool validForFolders;
  52. LayerProperty(): defaultValue( false ), validForFolders( true ) { }
  53. LayerProperty( const TQString &pname, const TQString &pdisplayName, const TQPixmap &enabled, const TQPixmap &disabled,
  54. bool pdefaultValue, bool pvalidForFolders )
  55. : name( pname ),
  56. displayName( pdisplayName ),
  57. enabledIcon( enabled ),
  58. disabledIcon( disabled ),
  59. defaultValue( pdefaultValue ),
  60. validForFolders( pvalidForFolders )
  61. { }
  62. };
  63. class LayerToolTip;
  64. class LayerList::Private
  65. {
  66. public:
  67. LayerItem *activeLayer;
  68. bool foldersCanBeActive;
  69. bool previewsShown;
  70. int itemHeight;
  71. TQValueList<LayerProperty> properties;
  72. TDEPopupMenu contextMenu;
  73. LayerToolTip *tooltip;
  74. Private( TQWidget *parent, LayerList *list );
  75. ~Private();
  76. };
  77. class LayerItem::Private
  78. {
  79. public:
  80. bool isFolder;
  81. int id;
  82. TQValueList<bool> properties;
  83. TQImage *previewImage;
  84. bool previewChanged;
  85. TQPixmap scaledPreview;
  86. TQSize previewSize;
  87. TQPoint previewOffset;
  88. Private( int pid ): isFolder( false ), id( pid ), previewImage( 0 ), previewChanged( false )
  89. { }
  90. };
  91. static const int MAX_SIZE = 256;
  92. class LayerToolTip: public TQToolTip, public TQFrame
  93. {
  94. LayerList *m_list;
  95. LayerItem *m_item;
  96. TQPoint m_pos;
  97. TQTimer m_timer;
  98. TQImage m_img;
  99. public:
  100. LayerToolTip( TQWidget *parent, LayerList *list )
  101. : TQToolTip( parent ),
  102. TQFrame( 0, 0, WStyle_Customize | WStyle_NoBorder | WStyle_Tool | WStyle_StaysOnTop | WX11BypassWM | WNoAutoErase ),
  103. m_list( list )
  104. {
  105. TQFrame::setPalette( TQToolTip::palette() );
  106. connect( &m_timer, TQT_SIGNAL( timeout() ), m_list, TQT_SLOT( hideTip() ) );
  107. tqApp->installEventFilter( this );
  108. }
  109. virtual void maybeTip( const TQPoint &pos )
  110. {
  111. m_pos = pos;
  112. LayerItem *prev = m_item;
  113. m_item = static_cast<LayerItem*>(m_list->itemAt( m_pos ));
  114. if( TQToolTip::parentWidget() && m_list->showToolTips() && m_item )
  115. {
  116. if( m_item != prev )
  117. hideTip();
  118. showTip();
  119. }
  120. else
  121. hideTip();
  122. }
  123. void showTip()
  124. {
  125. m_img = m_item->tooltipPreview();
  126. m_timer.start( 15000, true );
  127. if( !isVisible() || sizeHint() != size() )
  128. {
  129. resize( sizeHint() );
  130. position();
  131. }
  132. if( !isVisible() )
  133. show();
  134. else
  135. update();
  136. }
  137. void hideTip()
  138. {
  139. if( !isVisible() )
  140. return;
  141. TQFrame::hide();
  142. TQToolTip::hide();
  143. m_timer.stop();
  144. m_img.reset();
  145. m_list->triggerUpdate();
  146. }
  147. virtual void drawContents( TQPainter *painter )
  148. {
  149. TQPixmap buf( width(), height() );
  150. TQPainter p( &buf );
  151. buf.fill( colorGroup().background() );
  152. p.setPen( colorGroup().foreground() );
  153. p.drawRect( buf.rect() );
  154. TQSimpleRichText text( m_item->tooltip(), TQToolTip::font() );
  155. text.setWidth( TQCOORD_MAX );
  156. p.translate( 5, 5 );
  157. if( !m_img.isNull() )
  158. {
  159. if( m_img.width() > MAX_SIZE || m_img.height() > MAX_SIZE )
  160. m_img = m_img.scale( MAX_SIZE, MAX_SIZE, TQ_ScaleMin );
  161. int y = 0;
  162. if( m_img.height() < text.height() )
  163. y = text.height()/2 - m_img.height()/2;
  164. p.drawImage( 0, y, m_img );
  165. p.drawRect( -1, y-1, m_img.width()+2, m_img.height()+2 );
  166. p.translate( m_img.width() + 10, 0 );
  167. }
  168. text.draw( &p, 0, 0, rect(), colorGroup() );
  169. painter->drawPixmap( 0, 0, buf );
  170. }
  171. virtual TQSize sizeHint() const
  172. {
  173. if( !m_item )
  174. return TQSize( 0, 0 );
  175. TQSimpleRichText text( m_item->tooltip(), TQToolTip::font() );
  176. text.setWidth( TQCOORD_MAX );
  177. int width = text.widthUsed();
  178. if( !m_img.isNull() )
  179. width += kMin( m_img.width(), MAX_SIZE ) + 10;
  180. width += 10;
  181. int height = text.height();
  182. if( !m_img.isNull() && kMin( m_img.height(), MAX_SIZE ) > height )
  183. height = kMin( m_img.height(), MAX_SIZE );
  184. height += 10;
  185. return TQSize( width, height );
  186. }
  187. void position()
  188. {
  189. const TQRect drect = TQApplication::desktop()->availableGeometry( TQToolTip::parentWidget() );
  190. const TQSize size = sizeHint();
  191. const int width = size.width(), height = size.height();
  192. const TQRect tmp = m_item->rect();
  193. const TQRect irect( m_list->viewport()->mapToGlobal( m_list->contentsToViewport(tmp.topLeft()) ), tmp.size() );
  194. int y;
  195. if( irect.bottom() + height < drect.bottom() )
  196. y = irect.bottom();
  197. else
  198. y = kMax( drect.top(), irect.top() - height );
  199. int x = kMax( drect.x(), TQToolTip::parentWidget()->mapToGlobal( m_pos ).x() - width/2 );
  200. if( x + width > drect.right() )
  201. x = drect.right() - width;
  202. move( x, y );
  203. }
  204. virtual bool eventFilter( TQObject *, TQEvent *e )
  205. {
  206. if( isVisible() )
  207. switch ( e->type() )
  208. {
  209. case TQEvent::KeyPress:
  210. case TQEvent::KeyRelease:
  211. case TQEvent::MouseButtonPress:
  212. case TQEvent::MouseButtonRelease:
  213. //case TQEvent::MouseMove:
  214. case TQEvent::FocusIn:
  215. case TQEvent::FocusOut:
  216. case TQEvent::Wheel:
  217. case TQEvent::Leave:
  218. hideTip();
  219. default: break;
  220. }
  221. return false;
  222. }
  223. };
  224. LayerList::Private::Private( TQWidget *parent, LayerList *list )
  225. : activeLayer( 0 ), foldersCanBeActive( false ), previewsShown( false ), itemHeight( 32 ),
  226. tooltip( new LayerToolTip( parent, list ) ) { }
  227. LayerList::Private::~Private()
  228. {
  229. delete tooltip;
  230. tooltip = 0;
  231. }
  232. static int getID()
  233. {
  234. static int id = -2;
  235. return id--;
  236. }
  237. static TQSize iconSize() { return TQIconSet::iconSize( TQIconSet::Small ); }
  238. ///////////////
  239. // LayerList //
  240. ///////////////
  241. LayerList::LayerList( TQWidget *parent, const char *name )
  242. : super( parent, name ), d( new Private( viewport(), this ) )
  243. {
  244. setSelectionMode( TQListView::Extended );
  245. setRootIsDecorated( true );
  246. setSorting( -1 );
  247. setSortColumn( -1 );
  248. setAllColumnsShowFocus( true );
  249. setFullWidth( true );
  250. setItemsRenameable( false );
  251. setDropHighlighter( true );
  252. setDefaultRenameAction( TQListView::Accept );
  253. setDragEnabled( true );
  254. setAcceptDrops( true );
  255. setItemsMovable( true );
  256. addColumn( TQString() );
  257. header()->hide();
  258. TQToolTip::add(this, i18n("Right-click to create folders. Click on the layername to change the layer's name. Click and drag to move layers."));
  259. setNumRows( 2 );
  260. connect( this, TQT_SIGNAL( itemRenamed( TQListViewItem*, const TQString&, int ) ),
  261. TQT_SLOT( slotItemRenamed( TQListViewItem*, const TQString&, int ) ) );
  262. connect( this, TQT_SIGNAL( moved( TQPtrList<TQListViewItem>&, TQPtrList<TQListViewItem>&, TQPtrList<TQListViewItem>& ) ),
  263. TQT_SLOT( slotItemMoved( TQPtrList<TQListViewItem>&, TQPtrList<TQListViewItem>&, TQPtrList<TQListViewItem>& ) ) );
  264. connect( this, TQT_SIGNAL( onItem( TQListViewItem* ) ), TQT_SLOT( hideTip() ) );
  265. connect( this, TQT_SIGNAL( onViewport() ), TQT_SLOT( hideTip() ) );
  266. }
  267. LayerList::~LayerList()
  268. {
  269. delete d;
  270. }
  271. void LayerList::addProperty( const TQString &name, const TQString &displayName, const TQIconSet &icon,
  272. bool defaultValue, bool validForFolders )
  273. {
  274. addProperty( name, displayName, icon.pixmap( TQIconSet::Small, TQIconSet::Normal ), icon.pixmap( TQIconSet::Small, TQIconSet::Disabled ), defaultValue, validForFolders );
  275. }
  276. void LayerList::addProperty( const TQString &name, const TQString &displayName, TQPixmap enabled, TQPixmap disabled,
  277. bool defaultValue, bool validForFolders )
  278. {
  279. d->properties.append( LayerProperty( name, displayName, enabled, disabled, defaultValue, validForFolders ) );
  280. for( LayerItemIterator it( this ); *it; ++it )
  281. (*it)->d->properties.append( defaultValue );
  282. //we do this only afterwards in case someone wants to access the other items in a connected slot...
  283. for( LayerItemIterator it( this ); *it; ++it )
  284. if( validForFolders || !(*it)->isFolder() )
  285. {
  286. emit propertyChanged( *it, name, defaultValue );
  287. emit propertyChanged( (*it)->id(), name, defaultValue );
  288. }
  289. triggerUpdate();
  290. }
  291. LayerItem *LayerList::layer( int id ) const
  292. {
  293. if( !firstChild() || id == -1 )
  294. return 0;
  295. for( LayerItemIterator it( firstChild() ); *it; ++it )
  296. if( (*it)->id() == id )
  297. return (*it);
  298. return 0;
  299. }
  300. LayerItem *LayerList::folder( int id ) const
  301. {
  302. if( !firstChild() || id == -1 )
  303. return 0;
  304. for( LayerItemIterator it( firstChild() ); *it; ++it )
  305. if( (*it)->id() == id && (*it)->isFolder() )
  306. return (*it);
  307. return 0;
  308. }
  309. LayerItem *LayerList::activeLayer() const
  310. {
  311. return d->activeLayer;
  312. }
  313. int LayerList::activeLayerID() const
  314. {
  315. if( activeLayer() )
  316. return activeLayer()->id();
  317. return -1;
  318. }
  319. TQValueList<LayerItem*> LayerList::selectedLayers() const
  320. {
  321. if( !firstChild() )
  322. return TQValueList<LayerItem*>();
  323. TQValueList<LayerItem*> layers;
  324. for( LayerItemIterator it( firstChild() ); *it; ++it )
  325. if( (*it)->isSelected() )
  326. layers.append( *it );
  327. return layers;
  328. }
  329. TQValueList<int> LayerList::selectedLayerIDs() const
  330. {
  331. const TQValueList<LayerItem*> layers = selectedLayers();
  332. TQValueList<int> ids;
  333. for( int i = 0, n = layers.count(); i < n; ++i )
  334. ids.append( layers[i]->id() );
  335. return ids;
  336. }
  337. bool LayerList::foldersCanBeActive() const
  338. {
  339. return d->foldersCanBeActive;
  340. }
  341. bool LayerList::previewsShown() const
  342. {
  343. return d->previewsShown;
  344. }
  345. int LayerList::itemHeight() const
  346. {
  347. return d->itemHeight;
  348. }
  349. int LayerList::numRows() const
  350. {
  351. if( itemHeight() < kMax( fontMetrics().height(), iconSize().height() ) )
  352. return 0;
  353. return ( itemHeight() - fontMetrics().height() ) / iconSize().height() + 1;
  354. }
  355. void LayerList::makeFolder( int id )
  356. {
  357. LayerItem* const l = layer( id );
  358. if( l )
  359. l->makeFolder();
  360. }
  361. bool LayerList::isFolder( int id ) const
  362. {
  363. LayerItem* const l = layer( id );
  364. if( !l )
  365. return false;
  366. return l->isFolder();
  367. }
  368. TQString LayerList::displayName( int id ) const
  369. {
  370. LayerItem* const l = layer( id );
  371. if( !l )
  372. return TQString(); //should be more severe...
  373. return l->displayName();
  374. }
  375. bool LayerList::property( int id, const TQString &name ) const
  376. {
  377. LayerItem* const l = layer( id );
  378. if( !l )
  379. return false; //should be more severe...
  380. return l->property( name );
  381. }
  382. TDEPopupMenu *LayerList::contextMenu() const
  383. {
  384. return &( d->contextMenu );
  385. }
  386. void LayerList::setFoldersCanBeActive( bool can ) //SLOT
  387. {
  388. d->foldersCanBeActive = can;
  389. if( !can && activeLayer() && activeLayer()->isFolder() )
  390. {
  391. d->activeLayer = 0;
  392. emit activated( static_cast<LayerItem*>( 0 ) );
  393. emit activated( -1 );
  394. }
  395. }
  396. void LayerList::setPreviewsShown( bool show ) //SLOT
  397. {
  398. d->previewsShown = show;
  399. triggerUpdate();
  400. }
  401. void LayerList::setItemHeight( int height ) //SLOT
  402. {
  403. d->itemHeight = height;
  404. for( LayerItemIterator it( this ); *it; ++it )
  405. (*it)->setup();
  406. triggerUpdate();
  407. }
  408. void LayerList::setNumRows( int rows )
  409. {
  410. if( rows < 1 )
  411. return;
  412. if( rows == 1 )
  413. setItemHeight( kMax( fontMetrics().height(), iconSize().height() ) );
  414. else
  415. setItemHeight( fontMetrics().height() + ( rows - 1 ) * iconSize().height() );
  416. }
  417. void LayerList::setActiveLayer( LayerItem *layer ) //SLOT
  418. {
  419. if( !foldersCanBeActive() && layer && layer->isFolder() )
  420. return;
  421. ensureItemVisible( layer );
  422. if( d->activeLayer == layer )
  423. return;
  424. d->activeLayer = layer;
  425. if( currentItem() != layer )
  426. setCurrentItem( layer );
  427. else
  428. {
  429. int n = 0;
  430. for( LayerItemIterator it( this, LayerItemIterator::Selected ); n < 2 && (*it); ++it ) { n++; }
  431. if( n == 1 )
  432. (*LayerItemIterator( this, LayerItemIterator::Selected ))->setSelected( false );
  433. if( layer )
  434. layer->setSelected( true );
  435. }
  436. emit activated( layer );
  437. if( layer )
  438. emit activated( layer->id() );
  439. else
  440. emit activated( -1 );
  441. }
  442. void LayerList::setActiveLayer( int id ) //SLOT
  443. {
  444. setActiveLayer( layer( id ) );
  445. }
  446. void LayerList::setLayerDisplayName( LayerItem *layer, const TQString &displayName )
  447. {
  448. if( !layer )
  449. return;
  450. layer->setDisplayName( displayName );
  451. }
  452. void LayerList::setLayerDisplayName( int id, const TQString &displayName )
  453. {
  454. setLayerDisplayName( layer( id ), displayName );
  455. }
  456. void LayerList::setLayerProperty( LayerItem *layer, const TQString &name, bool on ) //SLOT
  457. {
  458. if( !layer )
  459. return;
  460. layer->setProperty( name, on );
  461. }
  462. void LayerList::setLayerProperty( int id, const TQString &name, bool on ) //SLOT
  463. {
  464. setLayerProperty( layer( id ), name, on );
  465. }
  466. void LayerList::toggleLayerProperty( LayerItem *layer, const TQString &name ) //SLOT
  467. {
  468. if( !layer )
  469. return;
  470. layer->toggleProperty( name );
  471. }
  472. void LayerList::toggleLayerProperty( int id, const TQString &name ) //SLOT
  473. {
  474. toggleLayerProperty( layer( id ), name );
  475. }
  476. void LayerList::setLayerPreviewImage( LayerItem *layer, TQImage *image )
  477. {
  478. if( !layer )
  479. return;
  480. layer->setPreviewImage( image );
  481. }
  482. void LayerList::setLayerPreviewImage( int id, TQImage *image )
  483. {
  484. setLayerPreviewImage( layer( id ), image );
  485. }
  486. void LayerList::layerPreviewChanged( LayerItem *layer )
  487. {
  488. if( !layer )
  489. return;
  490. layer->previewChanged();
  491. }
  492. void LayerList::layerPreviewChanged( int id )
  493. {
  494. layerPreviewChanged( layer( id ) );
  495. }
  496. LayerItem *LayerList::addLayer( const TQString &displayName, LayerItem *after, int id ) //SLOT
  497. {
  498. return new LayerItem( displayName, this, after, id );
  499. }
  500. LayerItem *LayerList::addLayer( const TQString &displayName, int afterID, int id ) //SLOT
  501. {
  502. return new LayerItem( displayName, this, layer( afterID ), id );
  503. }
  504. //SLOT
  505. LayerItem *LayerList::addLayerToParent( const TQString &displayName, LayerItem *parent, LayerItem *after, int id )
  506. {
  507. if( parent && parent->isFolder() )
  508. return parent->addLayer( displayName, after, id );
  509. else
  510. return 0;
  511. }
  512. LayerItem *LayerList::addLayerToParent( const TQString &displayName, int parentID, int afterID, int id ) //SLOT
  513. {
  514. return addLayerToParent( displayName, folder( parentID ), layer( afterID ), id );
  515. }
  516. void LayerList::moveLayer( LayerItem *layer, LayerItem *parent, LayerItem *after ) //SLOT
  517. {
  518. if( !layer )
  519. return;
  520. if( parent && !parent->isFolder() )
  521. parent = 0;
  522. if( layer->parent() == parent && layer->prevSibling() == after )
  523. return;
  524. TQListViewItem *current = currentItem();
  525. moveItem( layer, parent, after );
  526. emit layerMoved( layer, parent, after );
  527. emit layerMoved( layer->id(), parent ? parent->id() : -1, after ? after->id() : -1 );
  528. setCurrentItem( current ); //HACK, sometimes TQt changes this under us
  529. }
  530. void LayerList::moveLayer( int id, int parentID, int afterID ) //SLOT
  531. {
  532. moveLayer( layer( id ), folder( parentID ), layer( afterID ) );
  533. }
  534. void LayerList::removeLayer( LayerItem *layer ) //SLOT
  535. {
  536. delete layer;
  537. }
  538. void LayerList::removeLayer( int id ) //SLOT
  539. {
  540. delete layer( id );
  541. }
  542. void LayerList::contentsMousePressEvent( TQMouseEvent *e )
  543. {
  544. LayerItem *item = static_cast<LayerItem*>( itemAt( contentsToViewport( e->pos() ) ) );
  545. if( item )
  546. {
  547. TQMouseEvent m( TQEvent::MouseButtonPress, item->mapFromListView( e->pos() ), e->button(), e->state() );
  548. if( !item->mousePressEvent( &m ) )
  549. super::contentsMousePressEvent( e );
  550. }
  551. else
  552. {
  553. super::contentsMousePressEvent( e );
  554. if( e->button() == Qt::RightButton )
  555. showContextMenu();
  556. }
  557. }
  558. void LayerList::contentsMouseDoubleClickEvent( TQMouseEvent *e )
  559. {
  560. super::contentsMouseDoubleClickEvent( e );
  561. if( LayerItem *layer = static_cast<LayerItem*>( itemAt( contentsToViewport( e->pos() ) ) ) )
  562. {
  563. if( !layer->iconsRect().contains( layer->mapFromListView( e->pos() ) ) )
  564. {
  565. emit requestLayerProperties( layer );
  566. emit requestLayerProperties( layer->id() );
  567. }
  568. }
  569. else
  570. {
  571. emit requestNewLayer( static_cast<LayerItem*>( 0 ), static_cast<LayerItem*>( 0 ) );
  572. emit requestNewLayer( -1, -1 );
  573. }
  574. }
  575. void LayerList::findDrop( const TQPoint &pos, TQListViewItem *&parent, TQListViewItem *&after )
  576. {
  577. LayerItem *item = static_cast<LayerItem*>( itemAt( contentsToViewport( pos ) ) );
  578. if( item && item->isFolder() )
  579. {
  580. parent = item;
  581. after = 0;
  582. }
  583. else
  584. super::findDrop( pos, parent, after );
  585. }
  586. void LayerList::showContextMenu()
  587. {
  588. LayerItem *layer = static_cast<LayerItem*>( itemAt( viewport()->mapFromGlobal( TQCursor::pos() ) ) );
  589. if( layer )
  590. setCurrentItem( layer );
  591. d->contextMenu.clear();
  592. constructMenu( layer );
  593. menuActivated( d->contextMenu.exec( TQCursor::pos() ), layer );
  594. }
  595. void LayerList::hideTip()
  596. {
  597. d->tooltip->hideTip();
  598. }
  599. void LayerList::maybeTip()
  600. {
  601. d->tooltip->maybeTip( d->tooltip->TQToolTip::parentWidget()->mapFromGlobal( TQCursor::pos() ) );
  602. }
  603. void LayerList::constructMenu( LayerItem *layer )
  604. {
  605. if( layer )
  606. {
  607. for( int i = 0, n = d->properties.count(); i < n; ++i )
  608. if( !layer->isFolder() || d->properties[i].validForFolders )
  609. d->contextMenu.insertItem( layer->d->properties[i] ? d->properties[i].enabledIcon : d->properties[i].disabledIcon, d->properties[i].displayName, MenuItems::COUNT + i );
  610. d->contextMenu.insertItem( SmallIconSet( "application-vnd.tde.info" ), i18n( "&Properties" ), MenuItems::LayerProperties );
  611. d->contextMenu.insertSeparator();
  612. d->contextMenu.insertItem( SmallIconSet( "edit-delete" ),
  613. selectedLayers().count() > 1 ? i18n( "Remove Layers" )
  614. : layer->isFolder() ? i18n( "&Remove Folder" )
  615. : i18n( "&Remove Layer" ), MenuItems::RemoveLayer );
  616. }
  617. d->contextMenu.insertItem( SmallIconSet( "document-new" ), i18n( "&New Layer" ), MenuItems::NewLayer );
  618. d->contextMenu.insertItem( SmallIconSet( "folder" ), i18n( "New &Folder" ), MenuItems::NewFolder );
  619. }
  620. void LayerList::menuActivated( int id, LayerItem *layer )
  621. {
  622. const TQValueList<LayerItem*> selected = selectedLayers();
  623. LayerItem *parent = ( layer && layer->isFolder() ) ? layer : 0;
  624. LayerItem *after = 0;
  625. if( layer && !parent )
  626. {
  627. parent = layer->parent();
  628. after = layer->prevSibling();
  629. }
  630. switch( id )
  631. {
  632. case MenuItems::NewLayer:
  633. emit requestNewLayer( parent, after );
  634. emit requestNewLayer( parent ? parent->id() : -1, after ? after->id() : -1 );
  635. break;
  636. case MenuItems::NewFolder:
  637. emit requestNewFolder( parent, after );
  638. emit requestNewFolder( parent ? parent->id() : -1, after ? after->id() : -1 );
  639. break;
  640. case MenuItems::RemoveLayer:
  641. {
  642. TQValueList<int> ids;
  643. for( int i = 0, n = selected.count(); i < n; ++i )
  644. {
  645. ids.append( selected[i]->id() );
  646. emit requestRemoveLayer( selected[i]->id() );
  647. }
  648. emit requestRemoveLayers( ids );
  649. }
  650. for( int i = 0, n = selected.count(); i < n; ++i )
  651. emit requestRemoveLayer( selected[i] );
  652. emit requestRemoveLayers( selected );
  653. break;
  654. case MenuItems::LayerProperties:
  655. if( layer )
  656. {
  657. emit requestLayerProperties( layer );
  658. emit requestLayerProperties( layer->id() );
  659. }
  660. break;
  661. default:
  662. if( id >= MenuItems::COUNT && layer )
  663. for( int i = 0, n = selected.count(); i < n; ++i )
  664. selected[i]->toggleProperty( d->properties[ id - MenuItems::COUNT ].name );
  665. }
  666. }
  667. void LayerList::slotItemRenamed( TQListViewItem *item, const TQString &text, int col )
  668. {
  669. if( !item || col != 0 )
  670. return;
  671. emit displayNameChanged( static_cast<LayerItem*>( item ), text );
  672. emit displayNameChanged( static_cast<LayerItem*>( item )->id(), text );
  673. }
  674. void LayerList::slotItemMoved( TQPtrList<TQListViewItem> &items, TQPtrList<TQListViewItem> &/*afterBefore*/, TQPtrList<TQListViewItem> &afterNow )
  675. {
  676. for( int i = 0, n = items.count(); i < n; ++i )
  677. {
  678. LayerItem *l = static_cast<LayerItem*>( items.at(i) ), *a = static_cast<LayerItem*>( afterNow.at(i) );
  679. if( !l )
  680. continue;
  681. if( l->parent() )
  682. l->parent()->setOpen( true );
  683. emit layerMoved( l, l->parent(), a );
  684. emit layerMoved( l->id(), l->parent() ? l->parent()->id() : -1, a ? a->id() : -1 );
  685. }
  686. }
  687. void LayerList::setCurrentItem( TQListViewItem *item )
  688. {
  689. if( !item )
  690. return;
  691. super::setCurrentItem( item );
  692. ensureItemVisible( item );
  693. int n = 0;
  694. for( LayerItemIterator it( this, LayerItemIterator::Selected ); n < 2 && (*it); ++it ) { n++; }
  695. if( n == 1 )
  696. (*LayerItemIterator( this, LayerItemIterator::Selected ))->setSelected( false );
  697. item->setSelected( true );
  698. if( activeLayer() != item )
  699. setActiveLayer( static_cast<LayerItem*>(item) );
  700. }
  701. ///////////////
  702. // LayerItem //
  703. ///////////////
  704. LayerItem::LayerItem( const TQString &displayName, LayerList *p, LayerItem *after, int id )
  705. : super( p, after ), d( new Private( id ) )
  706. {
  707. init();
  708. setDisplayName( displayName );
  709. }
  710. LayerItem::LayerItem( const TQString &displayName, LayerItem *p, LayerItem *after, int id )
  711. : super( ( p && p->isFolder() ) ? p : 0, after ), d( new Private( id ) )
  712. {
  713. init();
  714. setDisplayName( displayName );
  715. }
  716. void LayerItem::init()
  717. {
  718. if( d->id < 0 )
  719. d->id = getID();
  720. for( int i = 0, n = listView()->d->properties.count(); i < n; ++i )
  721. d->properties.append( listView()->d->properties[i].defaultValue );
  722. if( parent())
  723. parent()->setOpen( true );
  724. }
  725. LayerItem::~LayerItem()
  726. {
  727. if (listView() && (listView()->activeLayer() == this || contains(listView()->activeLayer())))
  728. listView()->setActiveLayer( static_cast<LayerItem*>( 0 ) );
  729. delete d;
  730. }
  731. void LayerItem::makeFolder()
  732. {
  733. d->isFolder = true;
  734. setPixmap( 0, SmallIcon( "folder", 16 ) );
  735. if( isActive() && !listView()->foldersCanBeActive() )
  736. listView()->setActiveLayer( static_cast<LayerItem*>( 0 ) );
  737. }
  738. bool LayerItem::isFolder() const
  739. {
  740. return d->isFolder;
  741. }
  742. bool LayerItem::contains(const LayerItem *item)
  743. {
  744. TQListViewItemIterator it(this);
  745. while (it.current()) {
  746. if (static_cast<const LayerItem *>(it.current()) == item) {
  747. return true;
  748. }
  749. ++it;
  750. }
  751. return false;
  752. }
  753. int LayerItem::id() const
  754. {
  755. return d->id;
  756. }
  757. TQString LayerItem::displayName() const
  758. {
  759. return text( 0 );
  760. }
  761. void LayerItem::setDisplayName( const TQString &s )
  762. {
  763. if( displayName() == s )
  764. return;
  765. setText( 0, s );
  766. emit listView()->displayNameChanged( this, s );
  767. emit listView()->displayNameChanged( id(), s );
  768. }
  769. bool LayerItem::isActive() const
  770. {
  771. return listView()->activeLayer() == this;
  772. }
  773. void LayerItem::setActive()
  774. {
  775. listView()->setActiveLayer( this );
  776. }
  777. bool LayerItem::property( const TQString &name ) const
  778. {
  779. int i = listView()->d->properties.count() - 1;
  780. while( i && listView()->d->properties[i].name != name )
  781. --i;
  782. if( i < 0 )
  783. return false; //should do something more severe... but what?
  784. return d->properties[i];
  785. }
  786. void LayerItem::setProperty( const TQString &name, bool on )
  787. {
  788. int i = listView()->d->properties.count() - 1;
  789. while( i && listView()->d->properties[i].name != name )
  790. --i;
  791. if( i < 0 || ( isFolder() && !listView()->d->properties[i].validForFolders ) )
  792. return;
  793. const bool notify = ( on != d->properties[i] );
  794. d->properties[i] = on;
  795. if( notify )
  796. {
  797. emit listView()->propertyChanged( this, name, on );
  798. emit listView()->propertyChanged( id(), name, on );
  799. }
  800. update();
  801. }
  802. void LayerItem::toggleProperty( const TQString &name )
  803. {
  804. int i = listView()->d->properties.count() - 1;
  805. while( i && listView()->d->properties[i].name != name )
  806. --i;
  807. if( i < 0 || ( isFolder() && !listView()->d->properties[i].validForFolders ) )
  808. return;
  809. d->properties[i] = !(d->properties[i]);
  810. emit listView()->propertyChanged( this, name, d->properties[i] );
  811. emit listView()->propertyChanged( id(), name, d->properties[i] );
  812. update();
  813. }
  814. void LayerItem::setPreviewImage( TQImage *image )
  815. {
  816. d->previewImage = image;
  817. previewChanged();
  818. }
  819. void LayerItem::previewChanged()
  820. {
  821. d->previewChanged = true;
  822. update();
  823. }
  824. LayerItem *LayerItem::addLayer( const TQString &displayName, LayerItem *after, int id )
  825. {
  826. if( !isFolder() )
  827. return 0;
  828. return new LayerItem( displayName, this, after, id );
  829. }
  830. LayerItem *LayerItem::prevSibling() const
  831. {
  832. LayerItem *item = parent() ? parent()->firstChild() : listView()->firstChild();
  833. if( !item || this == item )
  834. return 0;
  835. for(; item && this != item->nextSibling(); item = item->nextSibling() );
  836. return item;
  837. }
  838. int LayerItem::mapXFromListView( int x ) const
  839. {
  840. return x - rect().left();
  841. }
  842. int LayerItem::mapYFromListView( int y ) const
  843. {
  844. return y - rect().top();
  845. }
  846. TQPoint LayerItem::mapFromListView( const TQPoint &point ) const
  847. {
  848. return TQPoint( mapXFromListView( point.x() ), mapYFromListView( point.y() ) );
  849. }
  850. TQRect LayerItem::mapFromListView( const TQRect &rect ) const
  851. {
  852. return TQRect( mapFromListView( rect.topLeft() ), rect.size() );
  853. }
  854. int LayerItem::mapXToListView( int x ) const
  855. {
  856. return x + rect().left();
  857. }
  858. int LayerItem::mapYToListView( int y ) const
  859. {
  860. return y + rect().top();
  861. }
  862. TQPoint LayerItem::mapToListView( const TQPoint &point ) const
  863. {
  864. return TQPoint( mapXToListView( point.x() ), mapYToListView( point.y() ) );
  865. }
  866. TQRect LayerItem::mapToListView( const TQRect &rect ) const
  867. {
  868. return TQRect( mapToListView( rect.topLeft() ), rect.size() );
  869. }
  870. TQRect LayerItem::rect() const
  871. {
  872. const int indent = listView()->treeStepSize() * ( depth() + 1 );
  873. return TQRect( listView()->header()->sectionPos( 0 ) + indent, itemPos(),
  874. listView()->header()->sectionSize( 0 ) - indent, height() );
  875. }
  876. TQRect LayerItem::textRect() const
  877. {
  878. static TQFont f;
  879. static int minbearing = 1337 + 666; //can be 0 or negative, 2003 is less likely
  880. if( minbearing == 2003 || f != font() )
  881. {
  882. f = font(); //getting your bearings can be expensive, so we cache them
  883. minbearing = fontMetrics().minLeftBearing() + fontMetrics().minRightBearing();
  884. }
  885. const int margin = listView()->itemMargin();
  886. int indent = previewRect().right() + margin;
  887. if( pixmap( 0 ) )
  888. indent += pixmap( 0 )->width() + margin;
  889. const int width = ( multiline() ? rect().right() : iconsRect().left() ) - indent - margin + minbearing;
  890. return TQRect( indent, 0, width, fontMetrics().height() );
  891. }
  892. TQRect LayerItem::iconsRect() const
  893. {
  894. const TQValueList<LayerProperty> &lp = listView()->d->properties;
  895. int propscount = 0;
  896. for( int i = 0, n = lp.count(); i < n; ++i )
  897. if( !lp[i].enabledIcon.isNull() && ( !multiline() || !isFolder() || lp[i].validForFolders ) )
  898. propscount++;
  899. const int iconswidth = propscount * iconSize().width() + (propscount - 1) * listView()->itemMargin();
  900. const int x = multiline() ? previewRect().right() + listView()->itemMargin() : rect().width() - iconswidth;
  901. const int y = multiline() ? fontMetrics().height() : 0;
  902. return TQRect( x, y, iconswidth, iconSize().height() );
  903. }
  904. TQRect LayerItem::previewRect() const
  905. {
  906. return TQRect( 0, 0, listView()->previewsShown() ? height() : 0, height() );
  907. }
  908. void LayerItem::drawText( TQPainter *p, const TQColorGroup &cg, const TQRect &r )
  909. {
  910. p->translate( r.left(), r.top() );
  911. p->setPen( isSelected() ? cg.highlightedText() : cg.text() );
  912. const TQString text = KStringHandler::rPixelSqueeze( displayName(), p->fontMetrics(), r.width() );
  913. p->drawText( listView()->itemMargin(), 0, r.width(), r.height(), TQt::AlignAuto | TQt::AlignTop, text );
  914. p->translate( -r.left(), -r.top() );
  915. }
  916. void LayerItem::drawIcons( TQPainter *p, const TQColorGroup &/*cg*/, const TQRect &r )
  917. {
  918. p->translate( r.left(), r.top() );
  919. int x = 0;
  920. const TQValueList<LayerProperty> &lp = listView()->d->properties;
  921. for( int i = 0, n = lp.count(); i < n; ++i )
  922. if( !lp[i].enabledIcon.isNull() && ( !multiline() || !isFolder() || lp[i].validForFolders ) )
  923. {
  924. if( !isFolder() || lp[i].validForFolders )
  925. p->drawPixmap( x, 0, d->properties[i] ? lp[i].enabledIcon : lp[i].disabledIcon );
  926. x += iconSize().width() + listView()->itemMargin();
  927. }
  928. p->translate( -r.left(), -r.top() );
  929. }
  930. void LayerItem::drawPreview( TQPainter *p, const TQColorGroup &/*cg*/, const TQRect &r )
  931. {
  932. if( !showPreview() )
  933. return;
  934. if( d->previewChanged || r.size() != d->previewSize )
  935. { //TODO handle width() != height()
  936. const int size = kMin( r.width(), kMax( previewImage()->width(), previewImage()->height() ) );
  937. const TQImage i = previewImage()->smoothScale( size, size, TQ_ScaleMin );
  938. d->scaledPreview.convertFromImage( i );
  939. d->previewOffset.setX( r.width()/2 - i.width()/2 );
  940. d->previewOffset.setY( r.height()/2 - i.height()/2 );
  941. d->previewChanged = false;
  942. d->previewSize = r.size();
  943. }
  944. p->drawPixmap( r.topLeft() + d->previewOffset, d->scaledPreview );
  945. }
  946. bool LayerItem::showPreview() const
  947. {
  948. return listView()->previewsShown() && previewImage() && !previewImage()->isNull();
  949. }
  950. bool LayerItem::multiline() const
  951. {
  952. return height() >= fontMetrics().height() + iconSize().height();
  953. }
  954. TQFont LayerItem::font() const
  955. {
  956. if( isActive() )
  957. {
  958. TQFont f = listView()->font();
  959. f.setBold( !f.bold() );
  960. f.setItalic( !f.italic() );
  961. return f;
  962. }
  963. else
  964. return listView()->font();
  965. }
  966. TQFontMetrics LayerItem::fontMetrics() const
  967. {
  968. return TQFontMetrics( font() );
  969. }
  970. bool LayerItem::mousePressEvent( TQMouseEvent *e )
  971. {
  972. if( e->button() == Qt::RightButton )
  973. {
  974. if ( !(e->state() & TQt::ControlButton) && !(e->state() & TQt::ShiftButton) )
  975. setActive();
  976. TQTimer::singleShot( 0, listView(), TQT_SLOT( showContextMenu() ) );
  977. return false;
  978. }
  979. const TQRect ir = iconsRect(), tr = textRect();
  980. if( ir.contains( e->pos() ) )
  981. {
  982. const int iconWidth = iconSize().width();
  983. int x = e->pos().x() - ir.left();
  984. if( x % ( iconWidth + listView()->itemMargin() ) < iconWidth ) //it's on an icon, not a margin
  985. {
  986. const TQValueList<LayerProperty> &lp = listView()->d->properties;
  987. int p = -1;
  988. for( int i = 0, n = lp.count(); i < n; ++i )
  989. {
  990. if( !lp[i].enabledIcon.isNull() && ( !multiline() || !isFolder() || lp[i].validForFolders ) )
  991. x -= iconWidth + listView()->itemMargin();
  992. p += 1;
  993. if( x < 0 )
  994. break;
  995. }
  996. toggleProperty( lp[p].name );
  997. }
  998. return true;
  999. }
  1000. else if( tr.contains( e->pos() ) && isSelected() && !listView()->renameLineEdit()->isVisible() )
  1001. {
  1002. listView()->rename( this, 0 );
  1003. TQRect r( listView()->contentsToViewport( mapToListView( tr.topLeft() ) ), tr.size() );
  1004. listView()->renameLineEdit()->setGeometry( r );
  1005. return true;
  1006. }
  1007. if ( !(e->state() & TQt::ControlButton) && !(e->state() & TQt::ShiftButton) )
  1008. setActive();
  1009. return false;
  1010. }
  1011. TQString LayerItem::tooltip() const
  1012. {
  1013. TQString tip;
  1014. tip += "<table cellspacing=\"0\" cellpadding=\"0\">";
  1015. tip += TQString("<tr><td colspan=\"2\" align=\"center\"><b>%1</b></td></tr>").arg( displayName() );
  1016. TQString row = "<tr><td>%1</td><td>%2</td></tr>";
  1017. for( int i = 0, n = listView()->d->properties.count(); i < n; ++i )
  1018. if( !isFolder() || listView()->d->properties[i].validForFolders )
  1019. {
  1020. if( d->properties[i] )
  1021. tip += row.arg( i18n( "%1:" ).arg( listView()->d->properties[i].displayName ) ).arg( i18n( "Yes" ) );
  1022. else
  1023. tip += row.arg( i18n( "%1:" ).arg( listView()->d->properties[i].displayName ) ).arg( i18n( "No" ) );
  1024. }
  1025. tip += "</table>";
  1026. return tip;
  1027. }
  1028. TQImage *LayerItem::previewImage() const
  1029. {
  1030. return d->previewImage;
  1031. }
  1032. TQImage LayerItem::tooltipPreview() const
  1033. {
  1034. if( previewImage() )
  1035. return *previewImage();
  1036. return TQImage();
  1037. }
  1038. int LayerItem::width( const TQFontMetrics &fm, const TQListView *lv, int c ) const
  1039. {
  1040. if( c != 0 )
  1041. return super::width( fm, lv, c );
  1042. const TQValueList<LayerProperty> &lp = listView()->d->properties;
  1043. int propscount = 0;
  1044. for( int i = 0, n = d->properties.count(); i < n; ++i )
  1045. if( !lp[i].enabledIcon.isNull() && ( !multiline() || !isFolder() || lp[i].validForFolders ) )
  1046. propscount++;
  1047. const int iconswidth = propscount * iconSize().width() + (propscount - 1) * listView()->itemMargin();
  1048. if( multiline() )
  1049. return kMax( super::width( fm, lv, 0 ), iconswidth );
  1050. else
  1051. return super::width( fm, lv, 0 ) + iconswidth;
  1052. }
  1053. void LayerItem::paintCell( TQPainter *painter, const TQColorGroup &cg, int column, int width, int align )
  1054. {
  1055. if( column != 0 )
  1056. {
  1057. super::paintCell( painter, cg, column, width, align );
  1058. return;
  1059. }
  1060. TQPixmap buf( width, height() );
  1061. TQPainter p( &buf );
  1062. p.setFont( font() );
  1063. const TQColorGroup cg_ = isEnabled() ? listView()->palette().active() : listView()->palette().disabled();
  1064. const TQColor bg = isSelected() ? cg_.highlight()
  1065. : isAlternate() ? listView()->alternateBackground()
  1066. : listView()->viewport()->backgroundColor();
  1067. buf.fill( bg );
  1068. if( pixmap( 0 ) )
  1069. p.drawPixmap( previewRect().right() + listView()->itemMargin(), 0, *pixmap( 0 ) );
  1070. drawText( &p, cg_, textRect() );
  1071. drawIcons( &p, cg_, iconsRect() );
  1072. drawPreview( &p, cg_, previewRect() );
  1073. painter->drawPixmap( 0, 0, buf );
  1074. }
  1075. void LayerItem::setup()
  1076. {
  1077. super::setup();
  1078. setHeight( listView()->d->itemHeight );
  1079. }
  1080. void LayerItem::setSelected( bool selected )
  1081. {
  1082. if( !selected && ( isActive() || this == listView()->currentItem() ) )
  1083. return;
  1084. super::setSelected( selected );
  1085. }
  1086. /////////////////////////
  1087. // Convenience Methods //
  1088. /////////////////////////
  1089. LayerItem *LayerList::firstChild() const { return static_cast<LayerItem*>( super::firstChild() ); }
  1090. LayerItem *LayerList::lastChild() const { return static_cast<LayerItem*>( super::lastChild() ); }
  1091. LayerList *LayerItem::listView() const { return static_cast<LayerList*>( super::listView() ); }
  1092. void LayerItem::update() const { listView()->repaintItem( this ); }
  1093. LayerItem *LayerItem::firstChild() const { return static_cast<LayerItem*>( super::firstChild() ); }
  1094. LayerItem *LayerItem::nextSibling() const { return static_cast<LayerItem*>( super::nextSibling() ); }
  1095. LayerItem *LayerItem::parent() const { return static_cast<LayerItem*>( super::parent() ); }
  1096. #include "layerlist.moc"