kdeui Library API Documentation

ktabbar.cpp

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., 59 Temple Place - Suite 330, 00018 Boston, MA 02111-1307, USA. 00019 */ 00020 00021 #include <qapplication.h> 00022 #include <qpainter.h> 00023 #include <qstyle.h> 00024 #include <qtimer.h> 00025 #include <qpushbutton.h> 00026 #include <qtooltip.h> 00027 00028 #include <kglobalsettings.h> 00029 #include <kiconloader.h> 00030 #include <klocale.h> 00031 00032 #include "ktabbar.h" 00033 #include "ktabwidget.h" 00034 00035 KTabBar::KTabBar( QWidget *parent, const char *name ) 00036 : QTabBar( parent, name ), mReorderStartTab( -1 ), mReorderPreviousTab( -1 ), 00037 mHoverCloseButtonTab( 0 ), mDragSwitchTab( 0 ), mHoverCloseButton( 0 ), 00038 mHoverCloseButtonEnabled( false ), mHoverCloseButtonDelayed( true ), 00039 mTabReorderingEnabled( false ), mTabCloseActivatePrevious( false ) 00040 { 00041 setAcceptDrops( true ); 00042 setMouseTracking( true ); 00043 00044 mEnableCloseButtonTimer = new QTimer( this ); 00045 connect( mEnableCloseButtonTimer, SIGNAL( timeout() ), SLOT( enableCloseButton() ) ); 00046 00047 mActivateDragSwitchTabTimer = new QTimer( this ); 00048 connect( mActivateDragSwitchTabTimer, SIGNAL( timeout() ), SLOT( activateDragSwitchTab() ) ); 00049 00050 connect(this, SIGNAL(layoutChanged()), SLOT(onLayoutChange())); 00051 } 00052 00053 KTabBar::~KTabBar() 00054 { 00055 //For the future 00056 //delete d; 00057 } 00058 00059 void KTabBar::setTabEnabled( int id, bool enabled ) 00060 { 00061 QTab * t = tab( id ); 00062 if ( t ) { 00063 if ( t->isEnabled() != enabled ) { 00064 t->setEnabled( enabled ); 00065 QRect r( t->rect() ); 00066 if ( !enabled && id == currentTab() && count()>1 ) { 00067 QPtrList<QTab> *tablist = tabList(); 00068 if ( mTabCloseActivatePrevious ) 00069 t = tablist->at( count()-2 ); 00070 else { 00071 int index = indexOf( id ); 00072 index += ( index+1 == count() ) ? -1 : 1; 00073 t = tabAt( index ); 00074 } 00075 00076 if ( t->isEnabled() ) { 00077 r = r.unite( t->rect() ); 00078 tablist->append( tablist->take( tablist->findRef( t ) ) ); 00079 emit selected( t->identifier() ); 00080 } 00081 } 00082 repaint( r ); 00083 } 00084 } 00085 } 00086 00087 void KTabBar::mouseDoubleClickEvent( QMouseEvent *e ) 00088 { 00089 if( e->button() != LeftButton ) 00090 return; 00091 00092 QTab *tab = selectTab( e->pos() ); 00093 if( tab!= 0L ) { 00094 emit( mouseDoubleClick( indexOf( tab->identifier() ) ) ); 00095 return; 00096 } 00097 QTabBar::mouseDoubleClickEvent( e ); 00098 } 00099 00100 void KTabBar::mousePressEvent( QMouseEvent *e ) 00101 { 00102 if( e->button() == LeftButton ) { 00103 mEnableCloseButtonTimer->stop(); 00104 mDragStart = e->pos(); 00105 } 00106 else if( e->button() == RightButton ) { 00107 QTab *tab = selectTab( e->pos() ); 00108 if( tab!= 0L ) { 00109 emit( contextMenu( indexOf( tab->identifier() ), mapToGlobal( e->pos() ) ) ); 00110 return; 00111 } 00112 } 00113 QTabBar::mousePressEvent( e ); 00114 } 00115 00116 void KTabBar::mouseMoveEvent( QMouseEvent *e ) 00117 { 00118 if ( e->state() == LeftButton ) { 00119 QTab *tab = selectTab( e->pos() ); 00120 if ( mDragSwitchTab && tab != mDragSwitchTab ) { 00121 mActivateDragSwitchTabTimer->stop(); 00122 mDragSwitchTab = 0; 00123 } 00124 00125 int delay = KGlobalSettings::dndEventDelay(); 00126 QPoint newPos = e->pos(); 00127 if( newPos.x() > mDragStart.x()+delay || newPos.x() < mDragStart.x()-delay || 00128 newPos.y() > mDragStart.y()+delay || newPos.y() < mDragStart.y()-delay ) 00129 { 00130 if( tab!= 0L ) { 00131 emit( initiateDrag( indexOf( tab->identifier() ) ) ); 00132 return; 00133 } 00134 } 00135 } 00136 else if ( e->state() == MidButton ) { 00137 if (mReorderStartTab==-1) { 00138 int delay = KGlobalSettings::dndEventDelay(); 00139 QPoint newPos = e->pos(); 00140 if( newPos.x() > mDragStart.x()+delay || newPos.x() < mDragStart.x()-delay || 00141 newPos.y() > mDragStart.y()+delay || newPos.y() < mDragStart.y()-delay ) 00142 { 00143 QTab *tab = selectTab( e->pos() ); 00144 if( tab!= 0L && mTabReorderingEnabled ) { 00145 mReorderStartTab = indexOf( tab->identifier() ); 00146 grabMouse( sizeAllCursor ); 00147 return; 00148 } 00149 } 00150 } 00151 else { 00152 QTab *tab = selectTab( e->pos() ); 00153 if( tab!= 0L ) { 00154 int reorderStopTab = indexOf( tab->identifier() ); 00155 if ( mReorderStartTab!=reorderStopTab && mReorderPreviousTab!=reorderStopTab ) { 00156 emit( moveTab( mReorderStartTab, reorderStopTab ) ); 00157 mReorderPreviousTab=mReorderStartTab; 00158 mReorderStartTab=reorderStopTab; 00159 return; 00160 } 00161 } 00162 } 00163 } 00164 00165 if ( mHoverCloseButtonEnabled && mReorderStartTab==-1) { 00166 QTab *t = selectTab( e->pos() ); 00167 if( t && t->iconSet() && t->isEnabled() ) { 00168 QPixmap pixmap = t->iconSet()->pixmap( QIconSet::Small, QIconSet::Normal ); 00169 QRect rect( 0, 0, pixmap.width() + 4, pixmap.height() +4); 00170 00171 int xoff = 0, yoff = 0; 00172 // The additional offsets were found by try and error, TODO: find the rational behind them 00173 if ( t == tab( currentTab() ) ) { 00174 xoff = style().pixelMetric( QStyle::PM_TabBarTabShiftHorizontal, this ) + 3; 00175 yoff = style().pixelMetric( QStyle::PM_TabBarTabShiftVertical, this ) - 4; 00176 } 00177 else { 00178 xoff = 7; 00179 yoff = 0; 00180 } 00181 rect.moveLeft( t->rect().left() + 2 + xoff ); 00182 rect.moveTop( t->rect().center().y()-pixmap.height()/2 + yoff ); 00183 if ( rect.contains( e->pos() ) ) { 00184 if ( mHoverCloseButton ) { 00185 if ( mHoverCloseButtonTab == t ) 00186 return; 00187 mEnableCloseButtonTimer->stop(); 00188 delete mHoverCloseButton; 00189 } 00190 00191 mHoverCloseButton = new QPushButton( this ); 00192 mHoverCloseButton->setIconSet( KGlobal::iconLoader()->loadIcon("fileclose", KIcon::Toolbar, KIcon::SizeSmall, KIcon::ActiveState) ); 00193 mHoverCloseButton->setGeometry( rect ); 00194 QToolTip::add(mHoverCloseButton,i18n("Close this tab")); 00195 mHoverCloseButton->setFlat(true); 00196 mHoverCloseButton->show(); 00197 if ( mHoverCloseButtonDelayed ) { 00198 mHoverCloseButton->setEnabled(false); 00199 mEnableCloseButtonTimer->start( QApplication::doubleClickInterval(), true ); 00200 } 00201 mHoverCloseButtonTab = t; 00202 connect( mHoverCloseButton, SIGNAL( clicked() ), SLOT( closeButtonClicked() ) ); 00203 return; 00204 } 00205 } 00206 if ( mHoverCloseButton ) { 00207 mEnableCloseButtonTimer->stop(); 00208 delete mHoverCloseButton; 00209 mHoverCloseButton = 0; 00210 } 00211 } 00212 00213 QTabBar::mouseMoveEvent( e ); 00214 } 00215 00216 void KTabBar::enableCloseButton() 00217 { 00218 mHoverCloseButton->setEnabled(true); 00219 } 00220 00221 void KTabBar::activateDragSwitchTab() 00222 { 00223 setCurrentTab( mDragSwitchTab ); 00224 mDragSwitchTab = 0; 00225 } 00226 00227 void KTabBar::mouseReleaseEvent( QMouseEvent *e ) 00228 { 00229 if( e->button() == MidButton ) { 00230 if ( mReorderStartTab==-1 ) { 00231 QTab *tab = selectTab( e->pos() ); 00232 if( tab!= 0L ) { 00233 emit( mouseMiddleClick( indexOf( tab->identifier() ) ) ); 00234 return; 00235 } 00236 } 00237 else { 00238 releaseMouse(); 00239 setCursor( arrowCursor ); 00240 mReorderStartTab=-1; 00241 mReorderPreviousTab=-1; 00242 } 00243 } 00244 QTabBar::mouseReleaseEvent( e ); 00245 } 00246 00247 void KTabBar::dragMoveEvent( QDragMoveEvent *e ) 00248 { 00249 QTab *tab = selectTab( e->pos() ); 00250 if( tab!= 0L ) { 00251 bool accept = false; 00252 // The receivers of the testCanDecode() signal has to adjust 00253 // 'accept' accordingly. 00254 emit testCanDecode( e, accept); 00255 if ( accept && tab != QTabBar::tab( currentTab() ) ) { 00256 mDragSwitchTab = tab; 00257 mActivateDragSwitchTabTimer->start( QApplication::doubleClickInterval()*2, true ); 00258 } 00259 e->accept( accept ); 00260 return; 00261 } 00262 e->accept( false ); 00263 QTabBar::dragMoveEvent( e ); 00264 } 00265 00266 void KTabBar::dropEvent( QDropEvent *e ) 00267 { 00268 QTab *tab = selectTab( e->pos() ); 00269 if( tab!= 0L ) { 00270 mActivateDragSwitchTabTimer->stop(); 00271 mDragSwitchTab = 0; 00272 emit( receivedDropEvent( indexOf( tab->identifier() ) , e ) ); 00273 return; 00274 } 00275 QTabBar::dropEvent( e ); 00276 } 00277 00278 #ifndef QT_NO_WHEELEVENT 00279 void KTabBar::wheelEvent( QWheelEvent *e ) 00280 { 00281 if ( e->orientation() == Horizontal ) 00282 return; 00283 00284 emit( wheelDelta( e->delta() ) ); 00285 } 00286 #endif 00287 00288 void KTabBar::setTabColor( int id, const QColor& color ) 00289 { 00290 QTab *t = tab( id ); 00291 if ( t ) { 00292 mTabColors.insert( id, color ); 00293 repaint( t->rect(), false ); 00294 } 00295 } 00296 00297 const QColor &KTabBar::tabColor( int id ) const 00298 { 00299 if ( mTabColors.contains( id ) ) 00300 return mTabColors[id]; 00301 00302 return colorGroup().foreground(); 00303 } 00304 00305 int KTabBar::insertTab( QTab *t, int index ) 00306 { 00307 int res = QTabBar::insertTab( t, index ); 00308 00309 if ( mTabCloseActivatePrevious && count() > 2 ) { 00310 QPtrList<QTab> *tablist = tabList(); 00311 tablist->insert( count()-2, tablist->take( tablist->findRef( t ) ) ); 00312 } 00313 00314 return res; 00315 } 00316 00317 void KTabBar::removeTab( QTab *t ) 00318 { 00319 mTabColors.remove( t->identifier() ); 00320 QTabBar::removeTab( t ); 00321 } 00322 00323 void KTabBar::paintLabel( QPainter *p, const QRect& br, 00324 QTab *t, bool has_focus ) const 00325 { 00326 QRect r = br; 00327 bool selected = currentTab() == t->identifier(); 00328 if ( t->iconSet() ) { 00329 // the tab has an iconset, draw it in the right mode 00330 QIconSet::Mode mode = ( t->isEnabled() && isEnabled() ) 00331 ? QIconSet::Normal : QIconSet::Disabled; 00332 if ( mode == QIconSet::Normal && has_focus ) 00333 mode = QIconSet::Active; 00334 QPixmap pixmap = t->iconSet()->pixmap( QIconSet::Small, mode ); 00335 int pixw = pixmap.width(); 00336 int pixh = pixmap.height(); 00337 r.setLeft( r.left() + pixw + 4 ); 00338 r.setRight( r.right() + 2 ); 00339 00340 int inactiveXShift = style().pixelMetric( QStyle::PM_TabBarTabShiftHorizontal, this ); 00341 int inactiveYShift = style().pixelMetric( QStyle::PM_TabBarTabShiftVertical, this ); 00342 00343 int right = t->text().isEmpty() ? br.right() - pixw : br.left() + 2; 00344 00345 p->drawPixmap( right + ((selected == true) ? 0 : inactiveXShift), 00346 br.center().y() - pixh / 2 + ((selected == true) ? 0 : inactiveYShift), 00347 pixmap ); 00348 } 00349 00350 QStyle::SFlags flags = QStyle::Style_Default; 00351 00352 if ( isEnabled() && t->isEnabled() ) 00353 flags |= QStyle::Style_Enabled; 00354 if ( has_focus ) 00355 flags |= QStyle::Style_HasFocus; 00356 00357 QColorGroup cg( colorGroup() ); 00358 if ( mTabColors.contains( t->identifier() ) ) 00359 cg.setColor( QColorGroup::Foreground, mTabColors[t->identifier()] ); 00360 00361 style().drawControl( QStyle::CE_TabBarLabel, p, this, r, 00362 t->isEnabled() ? cg : palette().disabled(), 00363 flags, QStyleOption(t) ); 00364 } 00365 00366 bool KTabBar::isTabReorderingEnabled() const 00367 { 00368 return mTabReorderingEnabled; 00369 } 00370 00371 void KTabBar::setTabReorderingEnabled( bool on ) 00372 { 00373 mTabReorderingEnabled = on; 00374 } 00375 00376 bool KTabBar::tabCloseActivatePrevious() const 00377 { 00378 return mTabCloseActivatePrevious; 00379 } 00380 00381 void KTabBar::setTabCloseActivatePrevious( bool on ) 00382 { 00383 mTabCloseActivatePrevious = on; 00384 } 00385 00386 void KTabBar::closeButtonClicked() 00387 { 00388 emit closeRequest( indexOf( mHoverCloseButtonTab->identifier() ) ); 00389 } 00390 00391 void KTabBar::setHoverCloseButton( bool button ) 00392 { 00393 mHoverCloseButtonEnabled = button; 00394 if ( !button ) 00395 onLayoutChange(); 00396 } 00397 00398 bool KTabBar::hoverCloseButton() const 00399 { 00400 return mHoverCloseButtonEnabled; 00401 } 00402 00403 void KTabBar::setHoverCloseButtonDelayed( bool delayed ) 00404 { 00405 mHoverCloseButtonDelayed = delayed; 00406 } 00407 00408 bool KTabBar::hoverCloseButtonDelayed() const 00409 { 00410 return mHoverCloseButtonDelayed; 00411 } 00412 00413 void KTabBar::onLayoutChange() 00414 { 00415 mEnableCloseButtonTimer->stop(); 00416 delete mHoverCloseButton; 00417 mHoverCloseButton = 0; 00418 mHoverCloseButtonTab = 0; 00419 mActivateDragSwitchTabTimer->stop(); 00420 mDragSwitchTab = 0; 00421 } 00422 00423 #include "ktabbar.moc"
KDE Logo
This file is part of the documentation for kdeui Library Version 3.3.1.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Sun Oct 17 11:27:32 2004 by doxygen 1.3.8 written by Dimitri van Heesch, © 1997-2003