00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include <qptrlist.h>
00023 #include <qwidgetstack.h>
00024 #include <qsignal.h>
00025 #include <qobjectlist.h>
00026 #include <qlabel.h>
00027 #include <qimage.h>
00028 #include <qpainter.h>
00029 #include <qbitmap.h>
00030 #include <qfontmetrics.h>
00031 #include <qsignalmapper.h>
00032 #include <qstyle.h>
00033 #include <qframe.h>
00034 #include <qdrawutil.h>
00035 #include <qcursor.h>
00036 #include <qtimer.h>
00037 #include <qtooltip.h>
00038
00039 #include <kpopupmenu.h>
00040 #include <kapplication.h>
00041 #include <kdialog.h>
00042 #include <klocale.h>
00043 #include <kiconloader.h>
00044 #include <sidebarextension.h>
00045
00046 #include <kdebug.h>
00047
00048 #include "mainwindow.h"
00049
00050 #include "plugin.h"
00051
00052 #include "prefs.h"
00053 #include "iconsidepane.h"
00054
00055 namespace Kontact
00056 {
00057
00058
00059
00060 class PluginProxy
00061 {
00062 public:
00063 PluginProxy()
00064 : mPlugin( 0 )
00065 { }
00066
00067 PluginProxy( Plugin *plugin )
00068 : mPlugin( plugin )
00069 { }
00070
00071 PluginProxy & operator=( Plugin *plugin )
00072 {
00073 mPlugin = plugin;
00074 return *this;
00075 }
00076
00077 bool operator<( PluginProxy &rhs ) const
00078 {
00079 return mPlugin->weight() < rhs.mPlugin->weight();
00080 }
00081
00082 Plugin *plugin() const
00083 {
00084 return mPlugin;
00085 }
00086
00087 private:
00088 Plugin *mPlugin;
00089 };
00090
00091 }
00092
00093 using namespace Kontact;
00094
00095 EntryItem::EntryItem( Navigator *parent, Kontact::Plugin *plugin )
00096 : QListBoxItem( parent ),
00097 mPlugin( plugin ),
00098 mHasHover( false ),
00099 mPaintActive( false )
00100 {
00101 reloadPixmap();
00102 setCustomHighlighting( true );
00103 setText( plugin->title() );
00104 }
00105
00106 EntryItem::~EntryItem()
00107 {
00108 }
00109
00110 void EntryItem::reloadPixmap()
00111 {
00112 int size = (int)navigator()->viewMode();
00113 if ( size != 0 )
00114 mPixmap = KGlobal::iconLoader()->loadIcon( mPlugin->icon(),
00115 KIcon::Desktop, size );
00116 else
00117 mPixmap = QPixmap();
00118 }
00119
00120 Navigator* EntryItem::navigator() const
00121 {
00122 return static_cast<Navigator*>( listBox() );
00123 }
00124
00125 int EntryItem::width( const QListBox *listbox ) const
00126 {
00127 int w = 0;
00128 if( navigator()->showIcons() ) {
00129 w = navigator()->viewMode();
00130 if ( navigator()->viewMode() == SmallIcons )
00131 w += 4;
00132 }
00133 if( navigator()->showText() ) {
00134 if ( navigator()->viewMode() == SmallIcons )
00135 w += listbox->fontMetrics().width( text() );
00136 else
00137 w = QMAX( w, listbox->fontMetrics().width( text() ) );
00138 }
00139 return w + ( KDialog::marginHint() * 2 );
00140 }
00141
00142 int EntryItem::height( const QListBox *listbox ) const
00143 {
00144 int h = 0;
00145 if ( navigator()->showIcons() )
00146 h = (int)navigator()->viewMode() + 4;
00147 if ( navigator()->showText() ) {
00148 if ( navigator()->viewMode() == SmallIcons || !navigator()->showIcons() )
00149 h = QMAX( h, listbox->fontMetrics().lineSpacing() ) + KDialog::spacingHint() * 2;
00150 else
00151 h = (int)navigator()->viewMode() + listbox->fontMetrics().lineSpacing() + 4;
00152 }
00153 return h;
00154 }
00155
00156 void EntryItem::paint( QPainter *p )
00157 {
00158 reloadPixmap();
00159
00160 QListBox *box = listBox();
00161 bool iconAboveText = ( navigator()->viewMode() > SmallIcons )
00162 && navigator()->showIcons();
00163 int w = box->viewport()->width();
00164 int y = iconAboveText ? 2 :
00165 ( ( height( box ) - mPixmap.height() ) / 2 );
00166
00167
00168 if ( isCurrent() || isSelected() || mHasHover || mPaintActive ) {
00169 int h = height( box );
00170
00171 QBrush brush;
00172 if ( isCurrent() || isSelected() || mPaintActive )
00173 brush = box->colorGroup().brush( QColorGroup::Highlight );
00174 else
00175 brush = box->colorGroup().highlight().light( 115 );
00176 p->fillRect( 1, 0, w - 2, h - 1, brush );
00177 QPen pen = p->pen();
00178 QPen oldPen = pen;
00179 pen.setColor( box->colorGroup().mid() );
00180 p->setPen( pen );
00181
00182 p->drawPoint( 1, 0 );
00183 p->drawPoint( 1, h - 2 );
00184 p->drawPoint( w - 2, 0 );
00185 p->drawPoint( w - 2, h - 2 );
00186
00187 p->setPen( oldPen );
00188 }
00189
00190 if ( !mPixmap.isNull() && navigator()->showIcons() ) {
00191 int x = iconAboveText ? ( ( w - mPixmap.width() ) / 2 ) :
00192 KDialog::marginHint();
00193 p->drawPixmap( x, y, mPixmap );
00194 }
00195
00196 QColor shadowColor = listBox()->colorGroup().background().dark(115);
00197 if ( isCurrent() || isSelected() ) {
00198 p->setPen( box->colorGroup().highlightedText() );
00199 }
00200
00201 if ( !text().isEmpty() && navigator()->showText() ) {
00202 QFontMetrics fm = p->fontMetrics();
00203
00204 int x = 0;
00205 if ( iconAboveText ) {
00206 x = ( w - fm.width( text() ) ) / 2;
00207 y += fm.height() - fm.descent();
00208 if ( navigator()->showIcons() )
00209 y += mPixmap.height();
00210 } else {
00211 x = KDialog::marginHint() + 4;
00212 if( navigator()->showIcons() ) {
00213 x += mPixmap.width();
00214 }
00215
00216 if ( !navigator()->showIcons() || mPixmap.height() < fm.height() )
00217 y = height( box )/2 - fm.height()/2 + fm.ascent();
00218 else
00219 y += mPixmap.height()/2 - fm.height()/2 + fm.ascent();
00220 }
00221
00222 if ( isCurrent() || isSelected() || mHasHover ) {
00223 p->setPen( box->colorGroup().highlight().dark(115) );
00224 p->drawText( x + ( QApplication::reverseLayout() ? -1 : 1),
00225 y + 1, text() );
00226 p->setPen( box->colorGroup().highlightedText() );
00227 }
00228 else
00229 p->setPen( box->colorGroup().text() );
00230
00231 p->drawText( x, y, text() );
00232 }
00233
00234
00235 if ( isCurrent() || isSelected() ) mHasHover = false;
00236 }
00237
00238 void EntryItem::setHover( bool hasHover )
00239 {
00240 mHasHover = hasHover;
00241 }
00242
00243 void EntryItem::setPaintActive( bool paintActive )
00244 {
00245 mPaintActive = paintActive;
00246 }
00247
00248 Navigator::Navigator( SidePaneBase *parent, const char *name )
00249 : KListBox( parent, name ), mSidePane( parent ),
00250 mShowIcons( true ), mShowText( true )
00251 {
00252 mMouseOn = 0;
00253 mHighlightItem = 0;
00254 mViewMode = sizeIntToEnum( Prefs::self()->sidePaneIconSize() );
00255 mShowIcons = Prefs::self()->sidePaneShowIcons();
00256 mShowText = Prefs::self()->sidePaneShowText();
00257 setSelectionMode( KListBox::Single );
00258 viewport()->setBackgroundMode( PaletteBackground );
00259 setFrameStyle( QFrame::NoFrame );
00260 setHScrollBarMode( QScrollView::AlwaysOff );
00261 setAcceptDrops( true );
00262
00263 setFocusPolicy( NoFocus );
00264
00265 connect( this, SIGNAL( selectionChanged( QListBoxItem* ) ),
00266 SLOT( slotExecuted( QListBoxItem* ) ) );
00267 connect( this, SIGNAL( rightButtonPressed( QListBoxItem*, const QPoint& ) ),
00268 SLOT( slotShowRMBMenu( QListBoxItem*, const QPoint& ) ) );
00269 connect( this, SIGNAL( onItem( QListBoxItem * ) ),
00270 SLOT( slotMouseOn( QListBoxItem * ) ) );
00271 connect( this, SIGNAL( onViewport() ), SLOT( slotMouseOff() ) );
00272
00273 mMapper = new QSignalMapper( this );
00274 connect( mMapper, SIGNAL( mapped( int ) ), SLOT( shortCutSelected( int ) ) );
00275
00276 QToolTip::remove( this );
00277 if ( !mShowText )
00278 new EntryItemToolTip( this );
00279
00280 }
00281
00282 QSize Navigator::sizeHint() const
00283 {
00284 return QSize( 100, 100 );
00285 }
00286
00287 void Navigator::highlightItem( EntryItem * item )
00288 {
00289 mHighlightItem = item;
00290
00291 setPaintActiveItem( mHighlightItem, true );
00292
00293 QTimer::singleShot( 2000, this, SLOT( slotStopHighlight() ) );
00294 }
00295
00296 void Navigator::slotStopHighlight()
00297 {
00298 setPaintActiveItem( mHighlightItem, false );
00299 }
00300
00301 void Navigator::setSelected( QListBoxItem *item, bool selected )
00302 {
00303
00304
00305
00306 if ( selected ) {
00307 EntryItem *entry = static_cast<EntryItem*>( item );
00308 emit pluginActivated( entry->plugin() );
00309 }
00310 }
00311
00312 void Navigator::updatePlugins( QValueList<Kontact::Plugin*> plugins_ )
00313 {
00314 QValueList<Kontact::PluginProxy> plugins;
00315 QValueList<Kontact::Plugin*>::ConstIterator end_ = plugins_.end();
00316 QValueList<Kontact::Plugin*>::ConstIterator it_ = plugins_.begin();
00317 for ( ; it_ != end_; ++it_ )
00318 plugins += PluginProxy( *it_ );
00319
00320 clear();
00321
00322 mActions.setAutoDelete( true );
00323 mActions.clear();
00324 mActions.setAutoDelete( false );
00325
00326 int counter = 0;
00327 int minWidth = 0;
00328 qBubbleSort( plugins );
00329 QValueList<Kontact::PluginProxy>::ConstIterator end = plugins.end();
00330 QValueList<Kontact::PluginProxy>::ConstIterator it = plugins.begin();
00331 for ( ; it != end; ++it ) {
00332 Kontact::Plugin *plugin = ( *it ).plugin();
00333 if ( !plugin->showInSideBar() )
00334 continue;
00335
00336 EntryItem *item = new EntryItem( this, plugin );
00337
00338 if ( item->width( this ) > minWidth )
00339 minWidth = item->width( this );
00340
00341 QString name = QString( "CTRL+%1" ).arg( counter + 1 );
00342 KAction *action = new KAction( plugin->title(), plugin->icon(), KShortcut( name ),
00343 mMapper, SLOT( map() ),
00344 mSidePane->actionCollection(), name.latin1() );
00345 mActions.append( action );
00346 mMapper->setMapping( action, counter );
00347 counter++;
00348 }
00349
00350 parentWidget()->setFixedWidth( minWidth );
00351 }
00352
00353 void Navigator::dragEnterEvent( QDragEnterEvent *event )
00354 {
00355 kdDebug(5600) << "Navigator::dragEnterEvent()" << endl;
00356
00357 dragMoveEvent( event );
00358 }
00359
00360 void Navigator::dragMoveEvent( QDragMoveEvent *event )
00361 {
00362 kdDebug(5600) << "Navigator::dragEnterEvent()" << endl;
00363
00364 kdDebug(5600) << " Format: " << event->format() << endl;
00365
00366 QListBoxItem *item = itemAt( event->pos() );
00367
00368 if ( !item ) {
00369 event->accept( false );
00370 return;
00371 }
00372
00373 EntryItem *entry = static_cast<EntryItem*>( item );
00374
00375 kdDebug(5600) << " PLUGIN: " << entry->plugin()->identifier() << endl;
00376
00377 event->accept( entry->plugin()->canDecodeDrag( event ) );
00378 }
00379
00380 void Navigator::dropEvent( QDropEvent *event )
00381 {
00382 kdDebug(5600) << "Navigator::dropEvent()" << endl;
00383
00384 QListBoxItem *item = itemAt( event->pos() );
00385
00386 if ( !item ) {
00387 return;
00388 }
00389
00390 EntryItem *entry = static_cast<EntryItem*>( item );
00391
00392 kdDebug(5600) << " PLUGIN: " << entry->plugin()->identifier() << endl;
00393
00394 entry->plugin()->processDropEvent( event );
00395 }
00396
00397 void Navigator::resizeEvent( QResizeEvent *event )
00398 {
00399 QListBox::resizeEvent( event );
00400 triggerUpdate( true );
00401 }
00402
00403 void Navigator::enterEvent( QEvent *event )
00404 {
00405
00406 KListBox::enterEvent( event );
00407 emit onItem( itemAt( mapFromGlobal( QCursor::pos() ) ) );
00408 }
00409
00410 void Navigator::leaveEvent( QEvent *event )
00411 {
00412 KListBox::leaveEvent( event );
00413 slotMouseOn( 0 );
00414 mMouseOn = 0;
00415 }
00416
00417 void Navigator::slotExecuted( QListBoxItem *item )
00418 {
00419 if ( !item )
00420 return;
00421
00422 EntryItem *entry = static_cast<EntryItem*>( item );
00423
00424 emit pluginActivated( entry->plugin() );
00425 }
00426
00427 IconViewMode Navigator::sizeIntToEnum(int size) const
00428 {
00429 switch ( size ) {
00430 case int(LargeIcons):
00431 return LargeIcons;
00432 break;
00433 case int(NormalIcons):
00434 return NormalIcons;
00435 break;
00436 case int(SmallIcons):
00437 return SmallIcons;
00438 break;
00439 default:
00440
00441 return NormalIcons;
00442 kdDebug() << "View mode not implemented!" << endl;
00443 break;
00444 }
00445 }
00446
00447 void Navigator::slotShowRMBMenu( QListBoxItem *, const QPoint &pos )
00448 {
00449 KPopupMenu menu;
00450 menu.insertTitle( i18n( "Icon Size" ) );
00451 menu.insertItem( i18n( "Large" ), (int)LargeIcons );
00452 menu.setItemEnabled( (int)LargeIcons, mShowIcons );
00453 menu.insertItem( i18n( "Normal" ), (int)NormalIcons );
00454 menu.setItemEnabled( (int)NormalIcons, mShowIcons );
00455 menu.insertItem( i18n( "Small" ), (int)SmallIcons );
00456 menu.setItemEnabled( (int)SmallIcons, mShowIcons );
00457
00458 menu.setItemChecked( (int)mViewMode, true );
00459 menu.insertSeparator();
00460
00461 menu.insertItem( i18n( "Show Icons" ), (int)ShowIcons );
00462 menu.setItemChecked( (int)ShowIcons, mShowIcons );
00463 menu.setItemEnabled( (int)ShowIcons, mShowText );
00464 menu.insertItem( i18n( "Show Text" ), (int)ShowText );
00465 menu.setItemChecked( (int)ShowText, mShowText );
00466 menu.setItemEnabled( (int)ShowText, mShowIcons );
00467 int choice = menu.exec( pos );
00468
00469 if ( choice == -1 )
00470 return;
00471
00472 if ( choice >= SmallIcons ) {
00473 mViewMode = sizeIntToEnum( choice );
00474 Prefs::self()->setSidePaneIconSize( choice );
00475 } else {
00476
00477 if ( choice == ShowIcons ) {
00478 mShowIcons = !mShowIcons;
00479 Prefs::self()->setSidePaneShowIcons( mShowIcons );
00480 QToolTip::remove( this );
00481 if ( !mShowText )
00482 new EntryItemToolTip( this );
00483 } else {
00484 mShowText = !mShowText;
00485 Prefs::self()->setSidePaneShowText( mShowText );
00486 QToolTip::remove( this );
00487 }
00488 }
00489 int maxWidth = 0;
00490 QListBoxItem* it = 0;
00491 for (int i = 0; (it = item(i)) != 0; ++i)
00492 {
00493 int width = it->width(this);
00494 if (width > maxWidth)
00495 maxWidth = width;
00496 }
00497 parentWidget()->setFixedWidth( maxWidth );
00498
00499 triggerUpdate( true );
00500 }
00501
00502 void Navigator::shortCutSelected( int pos )
00503 {
00504 setCurrentItem( pos );
00505 }
00506
00507 void Navigator::setHoverItem( QListBoxItem* item, bool hover )
00508 {
00509 static_cast<EntryItem*>( item )->setHover( hover );
00510 updateItem( item );
00511 }
00512
00513 void Navigator::setPaintActiveItem( QListBoxItem* item, bool paintActive )
00514 {
00515 static_cast<EntryItem*>( item )->setPaintActive( paintActive );
00516 updateItem( item );
00517 }
00518
00519 void Navigator::slotMouseOn( QListBoxItem* newItem )
00520 {
00521 QListBoxItem* oldItem = mMouseOn;
00522 if ( oldItem == newItem ) return;
00523
00524 if ( oldItem && !oldItem->isCurrent() && !oldItem->isSelected() )
00525 {
00526 setHoverItem( oldItem, false );
00527 }
00528
00529 if ( newItem && !newItem->isCurrent() && !newItem->isSelected() )
00530 {
00531 setHoverItem( newItem, true );
00532 }
00533 mMouseOn = newItem;
00534 }
00535
00536 void Navigator::slotMouseOff()
00537 {
00538 slotMouseOn( 0 );
00539 }
00540
00541 IconSidePane::IconSidePane( Core *core, QWidget *parent, const char *name )
00542 : SidePaneBase( core, parent, name )
00543 {
00544 mNavigator = new Navigator( this );
00545 connect( mNavigator, SIGNAL( pluginActivated( Kontact::Plugin* ) ),
00546 SIGNAL( pluginSelected( Kontact::Plugin* ) ) );
00547
00548 setAcceptDrops( true );
00549 }
00550
00551 IconSidePane::~IconSidePane()
00552 {
00553 }
00554
00555 void IconSidePane::updatePlugins()
00556 {
00557 mNavigator->updatePlugins( core()->pluginList() );
00558 }
00559
00560 void IconSidePane::selectPlugin( Kontact::Plugin *plugin )
00561 {
00562 bool blocked = signalsBlocked();
00563 blockSignals( true );
00564
00565 for ( uint i = 0; i < mNavigator->count(); ++i ) {
00566 EntryItem *item = static_cast<EntryItem*>( mNavigator->item( i ) );
00567 if ( item->plugin() == plugin ) {
00568 mNavigator->setCurrentItem( i );
00569 break;
00570 }
00571 }
00572
00573 blockSignals( blocked );
00574 }
00575
00576 void IconSidePane::selectPlugin( const QString &name )
00577 {
00578 bool blocked = signalsBlocked();
00579 blockSignals( true );
00580
00581 for ( uint i = 0; i < mNavigator->count(); ++i ) {
00582 EntryItem *item = static_cast<EntryItem*>( mNavigator->item( i ) );
00583 if ( item->plugin()->identifier() == name ) {
00584 mNavigator->setCurrentItem( i );
00585 break;
00586 }
00587 }
00588
00589 blockSignals( blocked );
00590 }
00591
00592 void IconSidePane::indicateForegrunding( Kontact::Plugin *plugin )
00593 {
00594 for ( uint i = 0; i < mNavigator->count(); ++i ) {
00595 EntryItem *item = static_cast<EntryItem*>( mNavigator->item( i ) );
00596 if ( item->plugin() == plugin ) {
00597 mNavigator->highlightItem( item );
00598 break;
00599 }
00600 }
00601
00602
00603 }
00604 #include "iconsidepane.moc"
00605
00606