• Skip to content
  • Skip to link menu
KDE 4.1 API Reference
  • KDE API Reference
  • kdelibs
  • Sitemap
  • Contact Us
 

KDEUI

ktabbar.cpp

Go to the documentation of this file.
00001 /* This file is part of the KDE libraries
00002     Copyright (C) 2003 Stephan Binner <binner@kde.org>
00003     Copyright (C) 2003 Zack Rusin <zack@kde.org>
00004 
00005     This library is free software; you can redistribute it and/or
00006     modify it under the terms of the GNU Library General Public
00007     License as published by the Free Software Foundation; either
00008     version 2 of the License, or (at your option) any later version.
00009 
00010     This library is distributed in the hope that it will be useful,
00011     but WITHOUT ANY WARRANTY; without even the implied warranty of
00012     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013     Library General Public License for more details.
00014 
00015     You should have received a copy of the GNU Library General Public License
00016     along with this library; see the file COPYING.LIB.  If not, write to
00017     the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00018     Boston, MA 02110-1301, USA.
00019 */
00020 
00021 #include "ktabbar.h"
00022 #include "ktabwidget.h"
00023 
00024 #include <QtCore/QTimer>
00025 #include <QtGui/QApplication>
00026 #include <QtGui/QCursor>
00027 #include <QtGui/QMouseEvent>
00028 #include <QtGui/QPainter>
00029 #include <QtGui/QPushButton>
00030 #include <QtGui/QStyle>
00031 #include <QtGui/QStyleOption>
00032 
00033 #include <kglobalsettings.h>
00034 #include <kicon.h>
00035 #include <kiconeffect.h>
00036 #include <kiconloader.h>
00037 #include <klocale.h>
00038 #include <kstyle.h>
00039 
00040 class KTabBar::Private
00041 {
00042   public:
00043     Private()
00044       : mReorderStartTab( -1 ),
00045         mReorderPreviousTab( -1 ),
00046         mDragSwitchTab( -1 ),
00047         mHoveredCloseIconIndex( -1 ),
00048         mActivateDragSwitchTabTimer( 0 ),
00049         mHoveredCloseIcon( 0 ),
00050         mInactiveCloseIcon( 0 ),
00051         mActiveCloseIcon( 0 ),
00052         mTabReorderingEnabled( false ),
00053         mTabCloseActivatePrevious( false ),
00054         mTabCloseButtonClicked( false )
00055     {
00056     }
00057 
00058     QPoint mDragStart;
00059     int mReorderStartTab;
00060     int mReorderPreviousTab;
00061     int mDragSwitchTab;
00062     int mHoveredCloseIconIndex;
00063     //QTab *mDragSwitchTab;
00064     QTimer *mActivateDragSwitchTabTimer;
00065     QPixmap *mHoveredCloseIcon;
00066     QPixmap *mInactiveCloseIcon;
00067     QPixmap *mActiveCloseIcon;
00068 
00069     bool mTabReorderingEnabled : 1;
00070     bool mTabCloseActivatePrevious : 1;
00071     bool mTabCloseButtonClicked : 1;
00072 
00073 };
00074 
00075 KTabBar::KTabBar( QWidget *parent )
00076     : QTabBar( parent ),
00077       d( new Private )
00078 {
00079   setAcceptDrops( true );
00080   setMouseTracking( true );
00081 
00082   d->mActivateDragSwitchTabTimer = new QTimer( this );
00083   d->mActivateDragSwitchTabTimer->setSingleShot( true );
00084   connect( d->mActivateDragSwitchTabTimer, SIGNAL( timeout() ), SLOT( activateDragSwitchTab() ) );
00085 
00086   //connect( this, SIGNAL( layoutChanged() ), SLOT( onLayoutChange() ) );
00087 }
00088 
00089 KTabBar::~KTabBar()
00090 {
00091   delete d->mHoveredCloseIcon;
00092   d->mHoveredCloseIcon = 0;
00093 
00094   delete d->mInactiveCloseIcon;
00095   d->mInactiveCloseIcon = 0;
00096 
00097   delete d->mActiveCloseIcon;
00098   d->mActiveCloseIcon = 0;
00099 
00100   delete d;
00101 }
00102 
00103 void KTabBar::mouseDoubleClickEvent( QMouseEvent *event )
00104 {
00105   if ( event->button() != Qt::LeftButton )
00106     return;
00107 
00108   int tab = selectTab( event->pos() );
00109 
00110   if(tab == -1) {
00111     emit newTabRequest();
00112   } else {
00113     emit mouseDoubleClick( tab ); //deprecated
00114     emit tabDoubleClicked( tab );
00115   }
00116 }
00117 
00118 void KTabBar::mousePressEvent( QMouseEvent *event )
00119 {
00120   if ( event->button() == Qt::LeftButton ) {
00121     d->mDragStart = event->pos();
00122     if ( isCloseButtonEnabled() ) {
00123       const QPoint pos = event->pos();
00124       const int tabIndex = tabAt( pos );
00125       if (closeButtonRect( tabIndex ).contains( pos )) {
00126         // the close button is clicked - prevent that the tab gets activated
00127         d->mTabCloseButtonClicked = true;
00128         return;
00129       }
00130     }
00131   } else if( event->button() == Qt::RightButton ) {
00132     int tab = selectTab( event->pos() );
00133     if ( tab != -1 ) {
00134       emit contextMenu( tab, mapToGlobal( event->pos() ) );
00135     } else {
00136       emit emptyAreaContextMenu( mapToGlobal( event->pos() ) );
00137     }
00138     return;
00139   }
00140 
00141   QTabBar::mousePressEvent( event );
00142 }
00143 
00144 void KTabBar::mouseMoveEvent( QMouseEvent *event )
00145 {
00146   if ( isCloseButtonEnabled() ) {
00147     if ( d->mHoveredCloseIconIndex >= 0) {
00148       // reset previously hovered close button
00149       update( closeButtonRect( d->mHoveredCloseIconIndex ));
00150       d->mHoveredCloseIconIndex = -1;
00151     }
00152 
00153     const QPoint pos = event->pos();
00154     const int tabCount = count();
00155     for ( int i = 0; i < tabCount; ++i ) {
00156       const QRect rect = closeButtonRect( i );
00157       if (rect.contains( pos )) {
00158         // update currently hovered close button
00159         d->mHoveredCloseIconIndex = i;
00160         update( rect );
00161         break;
00162       }
00163     }
00164   }
00165 
00166   if ( event->buttons() == Qt::LeftButton ) {
00167     int tab = selectTab( event->pos() );
00168     if ( d->mDragSwitchTab && tab != d->mDragSwitchTab ) {
00169       d->mActivateDragSwitchTabTimer->stop();
00170       d->mDragSwitchTab = 0;
00171     }
00172 
00173     int delay = KGlobalSettings::dndEventDelay();
00174     QPoint newPos = event->pos();
00175     if ( newPos.x() > d->mDragStart.x() + delay || newPos.x() < d->mDragStart.x() - delay ||
00176          newPos.y() > d->mDragStart.y() + delay || newPos.y() < d->mDragStart.y() - delay ) {
00177       if ( tab != -1 ) {
00178         emit initiateDrag( tab );
00179         return;
00180       }
00181     }
00182   } else if ( event->buttons() == Qt::MidButton ) {
00183     if ( d->mReorderStartTab == -1 ) {
00184       int delay = KGlobalSettings::dndEventDelay();
00185       QPoint newPos = event->pos();
00186 
00187       if ( newPos.x() > d->mDragStart.x() + delay || newPos.x() < d->mDragStart.x() - delay ||
00188            newPos.y() > d->mDragStart.y() + delay || newPos.y() < d->mDragStart.y() - delay ) {
00189         int tab = selectTab( event->pos() );
00190         if ( tab != -1 && d->mTabReorderingEnabled ) {
00191           d->mReorderStartTab = tab;
00192           grabMouse( Qt::SizeAllCursor );
00193           return;
00194         }
00195       }
00196     } else {
00197       int tab = selectTab( event->pos() );
00198       if ( tab != -1 ) {
00199         int reorderStopTab = tab;
00200         if ( d->mReorderStartTab != reorderStopTab && d->mReorderPreviousTab != reorderStopTab ) {
00201           emit moveTab( d->mReorderStartTab, reorderStopTab );
00202 
00203           d->mReorderPreviousTab = d->mReorderStartTab;
00204           d->mReorderStartTab = reorderStopTab;
00205 
00206           return;
00207         }
00208       }
00209     }
00210   }
00211 
00212   QTabBar::mouseMoveEvent( event );
00213 }
00214 
00215 
00216 void KTabBar::closeButtonClicked()
00217 {
00218   // deprecated
00219 }
00220 
00221 
00222 void KTabBar::enableCloseButton()
00223 {
00224   // deprecated
00225 }
00226 
00227 
00228 void KTabBar::activateDragSwitchTab()
00229 {
00230   int tab = selectTab( mapFromGlobal( QCursor::pos() ) );
00231   if ( tab != -1 && d->mDragSwitchTab == tab )
00232     setCurrentIndex( d->mDragSwitchTab );
00233 
00234   d->mDragSwitchTab = 0;
00235 }
00236 
00237 void KTabBar::mouseReleaseEvent( QMouseEvent *event )
00238 {
00239   switch ( event->button() ) {
00240   case Qt::LeftButton:
00241     if ( isCloseButtonEnabled() ) {
00242       update(closeButtonRect( d->mHoveredCloseIconIndex ));
00243 
00244       const QPoint pos = event->pos();
00245       const int tabIndex = tabAt( pos );
00246       if (d->mTabCloseButtonClicked && closeButtonRect( tabIndex ).contains( pos )) {
00247         d->mHoveredCloseIconIndex = -1;
00248         emit closeRequest( tabIndex );
00249       }
00250     }
00251     break;
00252 
00253   case Qt::MidButton:
00254     if ( d->mReorderStartTab == -1 ) {
00255       int tab = selectTab( event->pos() );
00256       if ( tab != -1 ) {
00257         emit mouseMiddleClick( tab );
00258         return;
00259       }
00260     } else {
00261       releaseMouse();
00262       setCursor( Qt::ArrowCursor );
00263       d->mReorderStartTab = -1;
00264       d->mReorderPreviousTab = -1;
00265     }
00266     break;
00267 
00268   default:
00269     break;
00270   }
00271 
00272   d->mTabCloseButtonClicked = false;
00273   QTabBar::mouseReleaseEvent( event );
00274 }
00275 
00276 void KTabBar::dragEnterEvent( QDragEnterEvent *event )
00277 {
00278   int tab = selectTab( event->pos() );
00279   if ( tab != -1 ) {
00280     bool accept = false;
00281     // The receivers of the testCanDecode() signal has to adjust
00282     // 'accept' accordingly.
00283     emit testCanDecode( event, accept );
00284     if ( accept && tab != currentIndex() ) {
00285       d->mDragSwitchTab = tab;
00286       d->mActivateDragSwitchTabTimer->start( QApplication::doubleClickInterval() * 2 );
00287     }
00288 
00289     event->setAccepted( accept );
00290     return;
00291   }
00292 
00293   QTabBar::dragEnterEvent( event );
00294 }
00295 
00296 void KTabBar::dragMoveEvent( QDragMoveEvent *event )
00297 {
00298   int tab = selectTab( event->pos() );
00299   if ( tab != -1 ) {
00300     bool accept = false;
00301     // The receivers of the testCanDecode() signal has to adjust
00302     // 'accept' accordingly.
00303     emit testCanDecode( event, accept );
00304     if ( accept && tab != currentIndex() ) {
00305       d->mDragSwitchTab = tab;
00306       d->mActivateDragSwitchTabTimer->start( QApplication::doubleClickInterval() * 2 );
00307     }
00308 
00309     event->setAccepted( accept );
00310     return;
00311   }
00312 
00313   QTabBar::dragMoveEvent( event );
00314 }
00315 
00316 void KTabBar::dropEvent( QDropEvent *event )
00317 {
00318   int tab = selectTab( event->pos() );
00319   if ( tab != -1 ) {
00320     d->mActivateDragSwitchTabTimer->stop();
00321     d->mDragSwitchTab = 0;
00322     emit receivedDropEvent( tab , event );
00323     return;
00324   }
00325 
00326   QTabBar::dropEvent( event );
00327 }
00328 
00329 void KTabBar::paintEvent( QPaintEvent *event )
00330 {
00331   QTabBar::paintEvent( event );
00332 
00333   if ( isCloseButtonEnabled() ) {
00334     QPainter painter( this );
00335     const int tabCount = count();
00336     for ( int i = 0; i < tabCount; ++i ) {
00337       QPixmap icon;
00338       if ( i == d->mHoveredCloseIconIndex)
00339         icon = *d->mActiveCloseIcon;
00340       else if ( i == currentIndex() )
00341         icon = *d->mHoveredCloseIcon;
00342       else
00343         icon = *d->mInactiveCloseIcon;
00344 
00345       painter.drawPixmap( closeButtonPos( i ), icon );
00346     }
00347   }
00348 }
00349 
00350 void KTabBar::leaveEvent( QEvent *event )
00351 {
00352   QTabBar::leaveEvent( event );
00353   if ( d->mHoveredCloseIconIndex >= 0 ) {
00354     update( closeButtonRect( d->mHoveredCloseIconIndex ));
00355     d->mHoveredCloseIconIndex = -1;
00356   }
00357 }
00358 
00359 QSize KTabBar::tabSizeHint( int index ) const
00360 {
00361   QSize size = QTabBar::tabSizeHint( index );
00362   if ( isCloseButtonEnabled() )
00363       size.rwidth() += KIconLoader::SizeSmall * 3 / 2;
00364 
00365   return size;
00366 }
00367 
00368 #ifndef QT_NO_WHEELEVENT
00369 void KTabBar::wheelEvent( QWheelEvent *event )
00370 {
00371   if ( event->orientation() == Qt::Horizontal )
00372     return;
00373 
00374   emit( wheelDelta( event->delta() ) );
00375 }
00376 #endif
00377 
00378 bool KTabBar::isTabReorderingEnabled() const
00379 {
00380   return d->mTabReorderingEnabled;
00381 }
00382 
00383 void KTabBar::setTabReorderingEnabled( bool on )
00384 {
00385   d->mTabReorderingEnabled = on;
00386 }
00387 
00388 bool KTabBar::tabCloseActivatePrevious() const
00389 {
00390   return d->mTabCloseActivatePrevious;
00391 }
00392 
00393 void KTabBar::setTabCloseActivatePrevious( bool on )
00394 {
00395   d->mTabCloseActivatePrevious = on;
00396 }
00397 
00398 
00399 void KTabBar::setHoverCloseButton( bool button )
00400 {
00401   // deprecated
00402   setCloseButtonEnabled( button );
00403 }
00404 
00405 bool KTabBar::hoverCloseButton() const
00406 {
00407   // deprecated
00408   return isCloseButtonEnabled();
00409 }
00410 
00411 void KTabBar::setHoverCloseButtonDelayed( bool delayed )
00412 {
00413   // deprecated
00414   Q_UNUSED( delayed );
00415 }
00416 
00417 bool KTabBar::hoverCloseButtonDelayed() const
00418 {
00419   // deprecated
00420   return false;
00421 }
00422 
00423 void KTabBar::setCloseButtonEnabled( bool enable )
00424 {
00425   if ( enable == isCloseButtonEnabled() )
00426     return;
00427 
00428   d->mHoveredCloseIconIndex = -1;
00429   if ( enable ) {
00430     Q_ASSERT( d->mHoveredCloseIcon == 0 );
00431     Q_ASSERT( d->mInactiveCloseIcon == 0 );
00432     Q_ASSERT( d->mActiveCloseIcon == 0 );
00433 
00434     const QPixmap icon = KIconLoader::global()->loadIcon( "dialog-close", KIconLoader::Small );
00435 
00436     d->mHoveredCloseIcon = new QPixmap( icon );
00437     KIconEffect::semiTransparent( *d->mHoveredCloseIcon );
00438 
00439     KIconEffect iconEffect;
00440     d->mInactiveCloseIcon = new QPixmap( iconEffect.apply( icon, KIconLoader::Small, KIconLoader::DisabledState ));
00441 
00442     KIconEffect::semiTransparent( *d->mInactiveCloseIcon );
00443     d->mActiveCloseIcon = new QPixmap( icon );
00444   } else {
00445     delete d->mHoveredCloseIcon;
00446     d->mHoveredCloseIcon = 0;
00447 
00448     delete d->mInactiveCloseIcon;
00449     d->mInactiveCloseIcon = 0;
00450 
00451     delete d->mActiveCloseIcon;
00452     d->mActiveCloseIcon = 0;
00453   }
00454 }
00455 
00456 bool KTabBar::isCloseButtonEnabled() const
00457 {
00458   return d->mHoveredCloseIcon != 0;
00459 }
00460 
00461 void KTabBar::tabLayoutChange()
00462 {
00463   d->mActivateDragSwitchTabTimer->stop();
00464   d->mDragSwitchTab = 0;
00465 }
00466 
00467 int KTabBar::selectTab( const QPoint &pos ) const
00468 {
00469   const int tabCount = count();
00470   for ( int i = 0; i < tabCount; ++i )
00471     if ( tabRect( i ).contains( pos ) )
00472       return i;
00473 
00474   return -1;
00475 }
00476 
00477 QPoint KTabBar::closeButtonPos( int tabIndex ) const
00478 {
00479   QPoint buttonPos;
00480   if ( tabIndex < 0 ) {
00481     return buttonPos;
00482   }
00483 
00484   int availableHeight = height();
00485   if ( tabIndex == currentIndex() ) {
00486     QStyleOption option;
00487     option.initFrom(this);
00488     availableHeight -= style()->pixelMetric( QStyle::PM_TabBarTabShiftVertical, &option, this );
00489   }
00490 
00491   const QRect tabBounds = tabRect( tabIndex );
00492   const int xInc = (height() - KIconLoader::SizeSmall) / 2;
00493 
00494   if ( layoutDirection() == Qt::RightToLeft ) {
00495     buttonPos = tabBounds.topLeft();
00496     buttonPos.rx() += xInc;
00497   } else {
00498     buttonPos = tabBounds.topRight();
00499     buttonPos.rx() -= KIconLoader::SizeSmall + xInc;
00500   }
00501   buttonPos.ry() += (availableHeight - KIconLoader::SizeSmall) / 2;
00502 
00503   return buttonPos;
00504 }
00505 
00506 QRect KTabBar::closeButtonRect( int tabIndex ) const
00507 {
00508   QRect rect;
00509   if ( tabIndex >= 0 ) {
00510     rect.setTopLeft(closeButtonPos( tabIndex ));
00511     rect.setSize(QSize( KIconLoader::SizeSmall, KIconLoader::SizeSmall));
00512   }
00513   return rect;
00514 }
00515 
00516 #include "ktabbar.moc"

KDEUI

Skip menu "KDEUI"
  • Main Page
  • Modules
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

kdelibs

Skip menu "kdelibs"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • Kate
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • KIO
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • Kross
  • KUtils
  • Nepomuk
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.5.4
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal