koshell

iconsidepane.cpp
1/*
2 This file is part of KDE KOffice project.
3
4 Copyright (C) 2003 Cornelius Schumacher <schumacher@kde.org>
5 Copyright (C) 2005 Fredrik Edemar <f_edemar@linux.se>
6
7 This program is free software; you can redistribute it and/or
8 modify it under the terms of the GNU General Public
9 License as published by the Free Software Foundation; either
10 version 2 of the License, or (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; see the file COPYING. If not, write to
19 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 * Boston, MA 02110-1301, USA.
21 */
22
23#include <tqbitmap.h>
24#include <tqcursor.h>
25#include <tqdrawutil.h>
26#include <tqfontmetrics.h>
27#include <tqframe.h>
28#include <tqlabel.h>
29#include <tqobjectlist.h>
30#include <tqpainter.h>
31#include <tqptrlist.h>
32#include <tqstyle.h>
33#include <tqtooltip.h>
34#include <tqwidgetstack.h>
35
36
37#include <tdeapplication.h>
38#include <kdebug.h>
39#include <kdialog.h>
40#include <kiconloader.h>
41#include <tdelocale.h>
42#include <tdepopupmenu.h>
43#include <kpushbutton.h>
44
45#include "iconsidepane.h"
46
47EntryItem::EntryItem( Navigator *parent, int _id, const TQString &_text, const TQString & _pix )
48 : TQListBoxItem( parent ),
49 mPixmapName(_pix),
50 mId(_id),
51 mHasHover( false ),
52 mPaintActive( false )
53{
54 reloadPixmap();
55 setCustomHighlighting( true );
56 setText( _text );
57}
58
59EntryItem::~EntryItem()
60{
61}
62
63void EntryItem::setNewText(const TQString &_text)
64{
65 setText( _text );
66}
67
68void EntryItem::reloadPixmap()
69{
70 int size = (int)navigator()->viewMode();
71 if ( size != 0 )
72 mPixmap = TDEGlobal::iconLoader()->loadIcon( mPixmapName, TDEIcon::Desktop, size );
73 else
74 mPixmap = TQPixmap();
75}
76
77Navigator* EntryItem::navigator() const
78{
79 return static_cast<Navigator*>( listBox() );
80}
81
82int EntryItem::width( const TQListBox *listbox ) const
83{
84 int w = 0;
85 if( navigator()->showIcons() ) {
86 w = navigator()->viewMode();
87 if ( navigator()->viewMode() == SmallIcons )
88 w += 4;
89 }
90 if( navigator()->showText() ) {
91 if ( navigator()->viewMode() == SmallIcons )
92 w += listbox->fontMetrics().width( text() );
93 else
94 w = TQMAX( w, listbox->fontMetrics().width( text() ) );
95 }
96 return w + ( KDialog::marginHint() * 2 );
97}
98
99int EntryItem::height( const TQListBox *listbox ) const
100{
101 int h = 0;
102 if ( navigator()->showIcons() )
103 h = (int)navigator()->viewMode() + 4;
104 if ( navigator()->showText() ) {
105 if ( navigator()->viewMode() == SmallIcons || !navigator()->showIcons() )
106 h = TQMAX( h, listbox->fontMetrics().lineSpacing() ) + KDialog::spacingHint() * 2;
107 else
108 h = (int)navigator()->viewMode() + listbox->fontMetrics().lineSpacing() + 4;
109 }
110 return h;
111}
112
113void EntryItem::paint( TQPainter *p )
114{
115 reloadPixmap();
116
117 TQListBox *box = listBox();
118 bool iconAboveText = ( navigator()->viewMode() > SmallIcons )
119 && navigator()->showIcons();
120 int w = box->viewport()->width();
121 int y = 2;
122
123 // draw selected
124 if ( isCurrent() || isSelected() || mHasHover || mPaintActive ) {
125 int h = height( box );
126
127 TQBrush brush;
128 if ( isCurrent() || isSelected() || mPaintActive )
129 brush = box->colorGroup().brush( TQColorGroup::Highlight );
130 else
131 brush = TQBrush(box->colorGroup().highlight().light( 115 ));
132 p->fillRect( 1, 0, w - 2, h - 1, brush );
133 TQPen pen = p->pen();
134 TQPen oldPen = pen;
135 pen.setColor( box->colorGroup().mid() );
136 p->setPen( pen );
137
138 p->drawPoint( 1, 0 );
139 p->drawPoint( 1, h - 2 );
140 p->drawPoint( w - 2, 0 );
141 p->drawPoint( w - 2, h - 2 );
142
143 p->setPen( oldPen );
144 }
145
146 if ( !mPixmap.isNull() && navigator()->showIcons() ) {
147 int x = iconAboveText ? ( ( w - mPixmap.width() ) / 2 ) :
148 KDialog::marginHint();
149 p->drawPixmap( x, y, mPixmap );
150 }
151
152 TQColor shadowColor = listBox()->colorGroup().background().dark(115);
153 if ( isCurrent() || isSelected() ) {
154 p->setPen( box->colorGroup().highlightedText() );
155 }
156
157 if ( !text().isEmpty() && navigator()->showText() ) {
158 TQFontMetrics fm = p->fontMetrics();
159
160 int x = 0;
161 if ( iconAboveText ) {
162 x = ( w - fm.width( text() ) ) / 2;
163 y += fm.height() - fm.descent();
164 if ( navigator()->showIcons() )
165 y += mPixmap.height();
166 } else {
167 x = KDialog::marginHint() + 4;
168 if( navigator()->showIcons() ) {
169 x += mPixmap.width();
170 }
171
172 if ( !navigator()->showIcons() || mPixmap.height() < fm.height() )
173 y += fm.ascent() + fm.leading()/2;
174 else
175 y += mPixmap.height()/2 - fm.height()/2 + fm.ascent();
176 }
177
178 if ( isCurrent() || isSelected() || mHasHover ) {
179 p->setPen( box->colorGroup().highlight().dark(115) );
180 p->drawText( x + ( TQApplication::reverseLayout() ? -1 : 1),
181 y + 1, text() );
182 p->setPen( box->colorGroup().highlightedText() );
183 }
184 else
185 p->setPen( box->colorGroup().text() );
186
187 p->drawText( x, y, text() );
188 }
189
190 // ensure that we don't have a stale flag around
191 if ( isCurrent() || isSelected() ) mHasHover = false;
192}
193
194void EntryItem::setHover( bool hasHover )
195{
196 mHasHover = hasHover;
197}
198
199void EntryItem::setPaintActive( bool paintActive )
200{
201 mPaintActive = paintActive;
202}
203
204// ************************************************
205
206Navigator::Navigator(bool _selectable, TDEPopupMenu * menu, IconSidePane *_iconsidepane, TQWidget *parent, const char *name )
207 : TDEListBox( parent, name ), mSidePane( _iconsidepane ), mPopupMenu( menu )
208{
209 setSelectionMode( TDEListBox::Single );
210 viewport()->setBackgroundMode( PaletteBackground );
211 setFrameStyle( TQFrame::NoFrame );
212 setHScrollBarMode( TQScrollView::AlwaysOff );
213 //setAcceptDrops( true );
214 mMinWidth = 0;
215 mSelectable = _selectable;
216 executedItem = 0;
217 mMouseOn = 0;
218
219 setFocusPolicy( TQWidget::NoFocus );
220
221 connect( this, TQ_SIGNAL( clicked( TQListBoxItem* ) ),
222 TQ_SLOT( slotExecuted( TQListBoxItem* ) ) );
223 connect( this, TQ_SIGNAL( onItem( TQListBoxItem * ) ),
224 TQ_SLOT( slotMouseOn( TQListBoxItem * ) ) );
225 connect( this, TQ_SIGNAL( onViewport() ), TQ_SLOT( slotMouseOff() ) );
226
227 TQToolTip::remove( this );
228 if ( !mSidePane->showText() )
229 new EntryItemToolTip( this );
230}
231
232IconViewMode Navigator::viewMode()
233{
234 return mSidePane->viewMode();
235}
236
237bool Navigator::showText()
238{
239 return mSidePane->showText();
240}
241
242bool Navigator::showIcons()
243{
244 return mSidePane->showIcons();
245}
246
247void Navigator::mouseReleaseEvent(TQMouseEvent *e)
248{
249 TDEListBox::mouseReleaseEvent(e);
250 if ( e->button() != TQt::LeftButton || !mLeftMouseButtonPressed )
251 return;
252 if ( itemAt( e->pos() ) && executedItem == selectedItem() )
253 emit itemSelected( currentItem() );
254 if ( !mSelectable )
255 clearSelection();
256}
257
258void Navigator::mousePressEvent(TQMouseEvent *e)
259{
260 if ( e->button() != TQt::LeftButton || itemAt( e->pos() ) == 0 )
261 {
262 mLeftMouseButtonPressed = false;
263 if (e->button() == TQt::RightButton)
264 slotShowRMBMenu( 0,mapToGlobal( e->pos() ) );
265 return;
266 }
267 else
268 mLeftMouseButtonPressed = true;
269 TDEListBox::mousePressEvent(e);
270}
271
272void Navigator::enterEvent( TQEvent *event )
273{
274 // work around TQt behaviour: onItem is not emmitted in enterEvent()
275 TDEListBox::enterEvent( event );
276 emit onItem( itemAt( mapFromGlobal( TQCursor::pos() ) ) );
277}
278
279void Navigator::slotExecuted( TQListBoxItem *item )
280{
281 if ( !item )
282 return;
283 executedItem = item;
284}
285
286TQSize Navigator::sizeHint() const
287{
288 return TQSize( mMinWidth, 100 );
289}
290
291void Navigator::calculateMinWidth()
292{
293 mMinWidth = mSidePane->minWidth();
294
295 for (EntryItem *item = static_cast<EntryItem *>(firstItem()) ; item; item = static_cast<EntryItem *>(item->next()))
296 {
297 if (item->width( this ) > mMinWidth)
298 mMinWidth = item->width( this );
299 }
300 //kdDebug() << "minWidth:" << mMinWidth << endl;
301 parentWidget()->setFixedWidth( mMinWidth );
302 triggerUpdate(true);
303}
304
305int Navigator::insertItem(const TQString &_text, const TQString & _pix)
306{
307 EntryItem *item = new EntryItem( this, count(), _text, _pix );
308 if (item->width( this ) > mSidePane->minWidth() )
309 {
310 mMinWidth = item->width( this );
311 parentWidget()->setMinimumWidth( mMinWidth );
312 //kdDebug() << "minWidth:" << mMinWidth << endl;
313 }
314 return item->id();
315}
316
317void Navigator::setHoverItem( TQListBoxItem* item, bool hover )
318{
319 static_cast<EntryItem*>( item )->setHover( hover );
320 updateItem( item );
321}
322
323void Navigator::setPaintActiveItem( TQListBoxItem* item, bool paintActive )
324{
325 static_cast<EntryItem*>( item )->setPaintActive( paintActive );
326 updateItem( item );
327}
328
329void Navigator::slotMouseOn( TQListBoxItem* newItem )
330{
331 TQListBoxItem* oldItem = mMouseOn;
332 if ( oldItem == newItem )
333 return;
334
335 if ( oldItem && !oldItem->isCurrent() && !oldItem->isSelected() )
336 setHoverItem( oldItem, false );
337
338 if ( newItem && !newItem->isCurrent() && !newItem->isSelected() )
339 setHoverItem( newItem, true );
340 mMouseOn = newItem;
341}
342
343void Navigator::slotMouseOff()
344{
345 slotMouseOn( 0 );
346}
347
348void Navigator::resizeEvent( TQResizeEvent *event )
349{
350 TQListBox::resizeEvent( event );
351 triggerUpdate( true );
352}
353
354void Navigator::slotShowRMBMenu( TQListBoxItem *, const TQPoint &pos )
355{
356 int choice = mPopupMenu->exec( pos );
357
358 if ( choice == -1 )
359 return;
360
361 mSidePane->resetWidth();
362 if ( choice >= SmallIcons ) {
363 mSidePane->setViewMode( mSidePane->sizeIntToEnum( choice ) );
364 mPopupMenu->setItemChecked( (int)SmallIcons, false);
365 mPopupMenu->setItemChecked( (int)NormalIcons, false);
366 mPopupMenu->setItemChecked( (int)LargeIcons, false);
367 mPopupMenu->setItemChecked( mSidePane->viewMode(), true);
368 KoShellSettings::setSidePaneIconSize( choice );
369 }
370 else
371 {
372 // either icons or text were toggled
373 if ( choice == ShowIcons ) {
374 mSidePane->toogleIcons();
375 mPopupMenu->setItemChecked( (int)ShowIcons, mSidePane->showIcons() );
376 mPopupMenu->setItemEnabled( (int)ShowText, mSidePane->showIcons() );
377 mPopupMenu->setItemEnabled( (int)SmallIcons, mSidePane->showIcons());
378 mPopupMenu->setItemEnabled( (int)NormalIcons, mSidePane->showIcons());
379 mPopupMenu->setItemEnabled( (int)LargeIcons, mSidePane->showIcons());
380 KoShellSettings::setSidePaneShowIcons( mSidePane->showIcons() );
381
382 TQToolTip::remove( this );
383 } else {
384 mSidePane->toogleText();
385 mSidePane->resetWidth();
386 mPopupMenu->setItemChecked( (int)ShowText, mSidePane->showText() );
387 mPopupMenu->setItemEnabled( (int)ShowIcons, mSidePane->showText() );
388 mPopupMenu->setItemEnabled( (int)SmallIcons, true);
389 mPopupMenu->setItemEnabled( (int)NormalIcons, true);
390 mPopupMenu->setItemEnabled( (int)LargeIcons, true);
391 KoShellSettings::setSidePaneShowText( mSidePane->showText() );
392 new EntryItemToolTip( this );
393// if ( !mSidePane->showText() )
394// mSidePane->buttonGroup()->hide();
395// else
396// mSidePane->buttonGroup()->show();
397 }
398 }
399 calculateMinWidth();
400 emit updateAllWidgets();
401}
402
403// ************************************************
404
405IconSidePane::IconSidePane(TQWidget *parent, const char *name )
406 : TQVBox( parent, name )
407{
408 m_buttongroup = new TQButtonGroup(1, TQt::Horizontal, this);
409 m_buttongroup->setExclusive(true);
410 m_buttongroup->hide();
411 mWidgetstack = new TQWidgetStack(this);
412 mWidgetstack->setSizePolicy(TQSizePolicy(TQSizePolicy::Expanding, TQSizePolicy::Expanding));
413
414 // setup the popup menu
415 mShowIcons = KoShellSettings::sidePaneShowIcons();
416 mShowText = KoShellSettings::sidePaneShowText();
417 mViewMode = sizeIntToEnum( KoShellSettings::sidePaneIconSize() );
418 mPopupMenu = new TDEPopupMenu(0);
419 mPopupMenu->insertTitle( i18n( "Icon Size" ) );
420 mPopupMenu->insertItem( i18n( "Large" ), (int)LargeIcons );
421 mPopupMenu->setItemEnabled( (int)LargeIcons, mShowIcons );
422 mPopupMenu->insertItem( i18n( "Normal" ), (int)NormalIcons );
423 mPopupMenu->setItemEnabled( (int)NormalIcons, mShowIcons );
424 mPopupMenu->insertItem( i18n( "Small" ), (int)SmallIcons );
425 mPopupMenu->setItemEnabled( (int)SmallIcons, mShowIcons );
426 mPopupMenu->setItemChecked( (int)mViewMode, true );
427 mPopupMenu->insertSeparator();
428 mPopupMenu->insertItem( i18n( "Show Icons" ), (int)ShowIcons );
429 mPopupMenu->setItemChecked( (int)ShowIcons, mShowIcons );
430 mPopupMenu->setItemEnabled( (int)ShowIcons, mShowText );
431 mPopupMenu->insertItem( i18n( "Show Text" ), (int)ShowText );
432 mPopupMenu->setItemChecked( (int)ShowText, mShowText );
433 mPopupMenu->setItemEnabled( (int)ShowText, mShowIcons );
434 if ( !mShowText )
435 m_buttongroup->hide();
436}
437
438IconSidePane::~IconSidePane()
439{
440}
441
442int IconSidePane::insertItem(int _grp, const TQString & _pix, const TQString &_text)
443{
444 return static_cast<Navigator*>( mWidgetstack->widget(_grp))->insertItem( _text, _pix );
445}
446
447int IconSidePane::insertItem(const TQString & _pix, const TQString &_text)
448{
449 return mCurrentNavigator->insertItem(_text, _pix);
450}
451
452void IconSidePane::renameItem( int _grp, int _id, const TQString & _text )
453{
454 Navigator *navigator = static_cast<Navigator*>(mWidgetstack->widget(_grp));
455 if (!navigator)
456 return;
457 EntryItem *item = 0;
458 for (uint i=0; i< navigator->count(); i++)
459 {
460 item = static_cast<EntryItem *>(navigator->item(i));
461 if (_id == item->id())
462 {
463 item->setNewText(_text);
464 navigator->triggerUpdate(false);
465 break;
466 }
467 }
468}
469
470void IconSidePane::removeItem( int _grp, int _id )
471{
472 Navigator *navigator = static_cast<Navigator*>(mWidgetstack->widget(_grp));
473 if (!navigator)
474 return;
475 for (uint i=0; i< navigator->count(); i++)
476 {
477 if (_id == static_cast<EntryItem *>(navigator->item(i))->id())
478 {
479 navigator->removeItem(i);
480 break;
481 }
482 }
483}
484
485int IconSidePane::insertGroup(const TQString &_text, bool _selectable, TQObject *_obj, const char *_slot)
486{
487 mCurrentNavigator = new Navigator(_selectable, mPopupMenu, this, mWidgetstack );
488 //connect( mCurrentNavigator, TQ_SIGNAL( itemSelected( int ) ), this, TQ_SLOT( itemSelected( int ) ) );
489 if ( _obj != 0L && _slot != 0L )
490 connect( mCurrentNavigator, TQ_SIGNAL( itemSelected(int ) ), _obj, _slot );
491 connect( mCurrentNavigator, TQ_SIGNAL( updateAllWidgets() ), this, TQ_SLOT(updateAllWidgets()) );
492 int const id = mWidgetstack->addWidget(mCurrentNavigator);
493 mWidgetStackIds.append( id );
494 KPushButton *b = new KPushButton( _text, m_buttongroup );
495 m_buttongroup->insert( b, id );
496 connect( b, TQ_SIGNAL( clicked() ), this, TQ_SLOT( buttonClicked() ) );
497 b->setToggleButton( true );
498 b->setFocusPolicy( TQWidget::NoFocus );
499 if (m_buttongroup->count()==1)
500 {
501 mCurrentNavigator->calculateMinWidth();
502 m_buttongroup->setButton(m_buttongroup->id(b));
503 mWidgetstack->raiseWidget(id);
504 }
505 if ( b->width() > minimumWidth() )
506 setMinimumWidth( b->width() );
507 return id;
508}
509
510void IconSidePane::buttonClicked()
511{
512 mWidgetstack->raiseWidget( m_buttongroup->selectedId() );
513}
514
515void IconSidePane::selectGroup(int group_id)
516{
517 mWidgetstack->raiseWidget(group_id);
518}
519
520void IconSidePane::itemSelected(int item)
521{
522 kdDebug() << "Item selected:" << item << endl;
523}
524
525Navigator * IconSidePane::group(int _grp)
526{
527 return static_cast<Navigator*>(mWidgetstack->widget(_grp));
528}
529
530void IconSidePane::updateAllWidgets()
531{
532 TQValueList<int>::iterator it;
533 for ( it = mWidgetStackIds.begin(); it != mWidgetStackIds.end(); ++it )
534 static_cast<Navigator*>(mWidgetstack->widget(*it))->triggerUpdate( true );
535}
536
537int IconSidePane::minWidth()
538{
539 int width = 0;
540 TQValueList<int>::iterator it;
541 Navigator *n;
542 for ( it = mWidgetStackIds.begin(); it != mWidgetStackIds.end(); ++it )
543 {
544 n = static_cast<Navigator*>(mWidgetstack->widget(*it));
545 if ( n->minWidth() > width )
546 width = n->minWidth();
547 }
548 return width;
549}
550
551void IconSidePane::resetWidth()
552{
553 TQValueList<int>::iterator it;
554 Navigator *n;
555 for ( it = mWidgetStackIds.begin(); it != mWidgetStackIds.end(); ++it )
556 {
557 n = static_cast<Navigator*>(mWidgetstack->widget(*it));
558 n->resetWidth();
559 n->triggerUpdate(true);
560 }
561}
562
563IconViewMode IconSidePane::sizeIntToEnum(int size) const
564{
565 switch ( size ) {
566 case int(LargeIcons):
567 return LargeIcons;
568 break;
569 case int(NormalIcons):
570 return NormalIcons;
571 break;
572 case int(SmallIcons):
573 return SmallIcons;
574 break;
575 default:
576 // Stick with sane values
577 return NormalIcons;
578 kdDebug() << "View mode not implemented!" << endl;
579 break;
580 }
581}
582
583void IconSidePane::setActionCollection( TDEActionCollection *actionCollection )
584{
585 mActionCollection = actionCollection;
586}
587
588TDEActionCollection *IconSidePane::actionCollection() const
589{
590 return mActionCollection;
591}
592
593#include "iconsidepane.moc"
Tooltip that changes text depending on the item it is above.
virtual int width(const TQListBox *) const
returns the width of this item.
virtual int height(const TQListBox *) const
returns the height of this item.
Navigation pane showing all parts relevant to the user.