kdeui Library API Documentation

ktabwidget.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 <qstyle.h>
00023 
00024 #include <kconfig.h>
00025 #include <kiconloader.h>
00026 #include <kstringhandler.h>
00027 
00028 #include "ktabwidget.h"
00029 #include "ktabbar.h"
00030 
00031 class KTabWidgetPrivate {
00032 public:
00033     bool m_automaticResizeTabs;
00034     int m_maxLength;
00035     int m_minLength;
00036     unsigned int m_CurrentMaxLength;
00037 
00038     //holds the full names of the tab, otherwise all we
00039     //know about is the shortened name
00040     QStringList m_tabNames;
00041 
00042     KTabWidgetPrivate() {
00043         m_automaticResizeTabs = false;
00044         KConfigGroupSaver groupsaver(KGlobal::config(), "General");
00045         m_maxLength = KGlobal::config()->readNumEntry("MaximumTabLength", 30);
00046         m_minLength = KGlobal::config()->readNumEntry("MinimumTabLength", 3);
00047         m_CurrentMaxLength = m_minLength;
00048     }
00049 };
00050 
00051 KTabWidget::KTabWidget( QWidget *parent, const char *name, WFlags f )
00052     : QTabWidget( parent, name, f )
00053 {
00054     d = new KTabWidgetPrivate;
00055     setTabBar( new KTabBar(this, "tabbar") );
00056     setAcceptDrops( true );
00057 
00058     connect(tabBar(), SIGNAL(contextMenu( int, const QPoint & )), SLOT(contextMenu( int, const QPoint & )));
00059     connect(tabBar(), SIGNAL(mouseDoubleClick( int )), SLOT(mouseDoubleClick( int )));
00060     connect(tabBar(), SIGNAL(mouseMiddleClick( int )), SLOT(mouseMiddleClick( int )));
00061     connect(tabBar(), SIGNAL(initiateDrag( int )), SLOT(initiateDrag( int )));
00062     connect(tabBar(), SIGNAL(testCanDecode(const QDragMoveEvent *, bool & )), SIGNAL(testCanDecode(const QDragMoveEvent *, bool & )));
00063     connect(tabBar(), SIGNAL(receivedDropEvent( int, QDropEvent * )), SLOT(receivedDropEvent( int, QDropEvent * )));
00064     connect(tabBar(), SIGNAL(moveTab( int, int )), SLOT(moveTab( int, int )));
00065     connect(tabBar(), SIGNAL(closeRequest( int )), SLOT(closeRequest( int )));
00066 #ifndef QT_NO_WHEELEVENT
00067     connect(tabBar(), SIGNAL(wheelDelta( int )), SLOT(wheelDelta( int )));
00068 #endif
00069 }
00070 
00071 KTabWidget::~KTabWidget()
00072 {
00073     delete d;
00074 }
00075 
00076 void KTabWidget::insertTab( QWidget *child, const QString &label, int index )
00077 {
00078     QTabWidget::insertTab( child, label, index );
00079 }
00080 
00081 void KTabWidget::insertTab( QWidget *child, const QIconSet& iconset, const QString &label, int index )
00082 {
00083     QTabWidget::insertTab( child, iconset, label, index );
00084 }
00085 
00086 void KTabWidget::insertTab( QWidget *child, QTab *tab, int index )
00087 {
00088     QTabWidget::insertTab( child, tab, index);
00089     if ( d->m_automaticResizeTabs ) {
00090         if ( index < 0 || index >= count() ) {
00091             d->m_tabNames.append( tab->text() );
00092             resizeTabs( d->m_tabNames.count()-1 );
00093         }
00094         else {
00095             d->m_tabNames.insert( d->m_tabNames.at( index ), tab->text() );
00096             resizeTabs( index );
00097         }
00098     }
00099 }
00100 
00101 void KTabWidget::setTabBarHidden( bool hide )
00102 {
00103     QWidget *rightcorner = this->cornerWidget( TopRight );
00104     QWidget *leftcorner = this->cornerWidget( TopLeft );
00105 
00106     if ( hide ) {
00107         if ( leftcorner ) leftcorner->hide();
00108         if ( rightcorner ) rightcorner->hide();
00109         tabBar()->hide();
00110     } else {
00111         tabBar()->show();
00112         if ( leftcorner ) leftcorner->show();
00113         if ( rightcorner ) rightcorner->show();
00114     }
00115 }
00116 
00117 bool KTabWidget::isTabBarHidden() const
00118 {
00119     return !( tabBar()->isVisible() );
00120 }
00121 
00122 void KTabWidget::setTabColor( QWidget *w, const QColor& color )
00123 {
00124     QTab *t = tabBar()->tabAt( indexOf( w ) );
00125     if (t) {
00126         static_cast<KTabBar*>(tabBar())->setTabColor( t->identifier(), color );
00127     }
00128 }
00129 
00130 QColor KTabWidget::tabColor( QWidget *w ) const
00131 {
00132     QTab *t = tabBar()->tabAt( indexOf( w ) );
00133     if (t) {
00134         return static_cast<KTabBar*>(tabBar())->tabColor( t->identifier() );
00135     } else {
00136         return QColor();
00137     }
00138 }
00139 
00140 void KTabWidget::setTabReorderingEnabled( bool on)
00141 {
00142     static_cast<KTabBar*>(tabBar())->setTabReorderingEnabled( on );
00143 }
00144 
00145 bool KTabWidget::isTabReorderingEnabled() const
00146 {
00147     return static_cast<KTabBar*>(tabBar())->isTabReorderingEnabled();
00148 }
00149 
00150 void KTabWidget::setTabCloseActivatePrevious( bool previous)
00151 {
00152     static_cast<KTabBar*>(tabBar())->setTabCloseActivatePrevious( previous );
00153 }
00154 
00155 bool KTabWidget::tabCloseActivatePrevious() const
00156 {
00157     return static_cast<KTabBar*>(tabBar())->tabCloseActivatePrevious();
00158 }
00159 
00160 unsigned int KTabWidget::tabBarWidthForMaxChars( uint maxLength )
00161 {
00162     int hframe, overlap;
00163     hframe  = tabBar()->style().pixelMetric( QStyle::PM_TabBarTabHSpace, tabBar() );
00164     overlap = tabBar()->style().pixelMetric( QStyle::PM_TabBarTabOverlap, tabBar() );
00165 
00166     QFontMetrics fm = tabBar()->fontMetrics();
00167     int x = 0;
00168     for( int i=0; i < count(); ++i ) {
00169         QString newTitle = d->m_tabNames[ i ];
00170         newTitle = KStringHandler::rsqueeze( newTitle, maxLength ).leftJustify( d->m_minLength, ' ' );
00171 
00172         QTab* tab = tabBar()->tabAt( i );
00173         int lw = fm.width( newTitle );
00174         int iw = 0;
00175         if ( tab->iconSet() )
00176           iw = tab->iconSet()->pixmap( QIconSet::Small, QIconSet::Normal ).width() + 4;
00177         x += ( tabBar()->style().sizeFromContents( QStyle::CT_TabBarTab, this,
00178                    QSize( QMAX( lw + hframe + iw, QApplication::globalStrut().width() ), 0 ),
00179                    QStyleOption( tab ) ) ).width();
00180     }
00181     return x;
00182 }
00183 
00184 void KTabWidget::changeTab( QWidget *w, const QString &label )
00185 {
00186     QTabWidget::changeTab( w, label );
00187     if ( d->m_automaticResizeTabs ) {
00188         int index = indexOf( w );
00189         if ( index != -1 ) {
00190             d->m_tabNames[ index ] = label;
00191             resizeTabs( index );
00192         }
00193     }
00194 }
00195 
00196 void KTabWidget::changeTab( QWidget *w, const QIconSet &iconset, const QString &label )
00197 {
00198     QTabWidget::changeTab( w, iconset, label );
00199     if ( d->m_automaticResizeTabs ) {
00200         int index = indexOf( w );
00201         if ( index != -1 ) {
00202             d->m_tabNames[ index ] = label;
00203             resizeTabs( index );
00204         }
00205     }
00206 }
00207 
00208 QString KTabWidget::label( int index ) const
00209 {
00210     if ( d->m_automaticResizeTabs ) {
00211         if ( index >= 0 && index < count() )
00212             return d->m_tabNames[ index ];
00213         else
00214             return QString::null;
00215     }
00216     else
00217         return QTabWidget::label( index );
00218 }
00219 
00220 QString KTabWidget::tabLabel( QWidget * w ) const
00221 {
00222     if ( d->m_automaticResizeTabs ) {
00223         int index = indexOf( w );
00224         if ( index == -1 )
00225             return QString::null;
00226         else
00227             return d->m_tabNames[ index ];
00228     }
00229     else
00230         return QTabWidget::tabLabel( w );
00231 }
00232 
00233 void KTabWidget::setTabLabel( QWidget *w, const QString &l )
00234 {
00235     QTabWidget::setTabLabel( w, l );
00236     if ( d->m_automaticResizeTabs ) {
00237         int index = indexOf( w );
00238         if ( index != -1 ) {
00239             d->m_tabNames[ index ] = l;
00240             resizeTabs( index );
00241         }
00242   }
00243 }
00244 
00245 void KTabWidget::resizeTabs( int changeTabIndex )
00246 {
00247     uint newMaxLength;
00248     if ( d->m_automaticResizeTabs ) {
00249         // Calculate new max length
00250         newMaxLength=d->m_maxLength;
00251         uint lcw=0, rcw=0;
00252 
00253         int tabBarHeight = tabBar()->sizeHint().height();
00254         if ( cornerWidget( TopLeft ) && cornerWidget( TopLeft )->isVisible() )
00255             lcw = QMAX( cornerWidget( TopLeft )->width(), tabBarHeight );
00256         if ( cornerWidget( TopRight ) && cornerWidget( TopRight )->isVisible() )
00257             rcw = QMAX( cornerWidget( TopRight )->width(), tabBarHeight );
00258 
00259         uint maxTabBarWidth = width() - lcw - rcw;
00260 
00261         for ( ; newMaxLength > (uint)d->m_minLength; newMaxLength-- ) {
00262             if ( tabBarWidthForMaxChars( newMaxLength ) < maxTabBarWidth )
00263                 break;
00264         }
00265     }
00266     else
00267         newMaxLength = 4711;
00268 
00269     // Update hinted or all tabs
00270     if ( d->m_CurrentMaxLength != newMaxLength ) {
00271         d->m_CurrentMaxLength = newMaxLength;
00272         for( int i = 0; i < count(); ++i )
00273             updateTab( i );
00274     }
00275     else if ( changeTabIndex != -1 )
00276         updateTab( changeTabIndex );
00277 }
00278 
00279 void KTabWidget::updateTab( int index )
00280 {
00281     QString title = d->m_automaticResizeTabs ? d->m_tabNames[ index ] : QTabWidget::label( index );
00282     removeTabToolTip( page( index ) );
00283     if ( title.length() > d->m_CurrentMaxLength )
00284         setTabToolTip( page( index ), title );
00285 
00286     title = KStringHandler::rsqueeze( title, d->m_CurrentMaxLength ).leftJustify( d->m_minLength, ' ' );
00287     title.replace( '&', "&&" );
00288 
00289     if ( QTabWidget::label( index ) != title )
00290         QTabWidget::setTabLabel( page( index ), title );
00291 }
00292 
00293 void KTabWidget::dragMoveEvent( QDragMoveEvent *e )
00294 {
00295     if ( isEmptyTabbarSpace( e->pos() ) ) {
00296         bool accept = false;
00297         // The receivers of the testCanDecode() signal has to adjust
00298         // 'accept' accordingly.
00299         emit testCanDecode( e, accept);
00300         e->accept( accept );
00301         return;
00302     }
00303     e->accept( false );
00304     QTabWidget::dragMoveEvent( e );
00305 }
00306 
00307 void KTabWidget::dropEvent( QDropEvent *e )
00308 {
00309     if ( isEmptyTabbarSpace( e->pos() ) ) {
00310         emit ( receivedDropEvent( e ) );
00311         return;
00312     }
00313     QTabWidget::dropEvent( e );
00314 }
00315 
00316 #ifndef QT_NO_WHEELEVENT
00317 void KTabWidget::wheelEvent( QWheelEvent *e )
00318 {
00319     if ( e->orientation() == Horizontal )
00320         return;
00321 
00322     if ( isEmptyTabbarSpace( e->pos() ) )
00323         wheelDelta( e->delta() );
00324     else
00325         e->ignore();
00326 }
00327 
00328 void KTabWidget::wheelDelta( int delta )
00329 {
00330     if ( count() < 2 )
00331         return;
00332 
00333     int page = currentPageIndex();
00334     if ( delta < 0 )
00335          page = (page + 1) % count();
00336     else {
00337         page--;
00338         if ( page < 0 )
00339             page = count() - 1;
00340     }
00341     setCurrentPage( page );
00342 }
00343 #endif
00344 
00345 void KTabWidget::mouseDoubleClickEvent( QMouseEvent *e )
00346 {
00347     if( e->button() != LeftButton )
00348         return;
00349 
00350     if ( isEmptyTabbarSpace( e->pos() ) ) {
00351         emit( mouseDoubleClick() );
00352         return;
00353     }
00354     QTabWidget::mouseDoubleClickEvent( e );
00355 }
00356 
00357 void KTabWidget::mousePressEvent( QMouseEvent *e )
00358 {
00359     if ( e->button() == RightButton ) {
00360         if ( isEmptyTabbarSpace( e->pos() ) ) {
00361             emit( contextMenu( mapToGlobal( e->pos() ) ) );
00362             return;
00363         }
00364     } else if ( e->button() == MidButton ) {
00365         if ( isEmptyTabbarSpace( e->pos() ) ) {
00366             emit( mouseMiddleClick() );
00367             return;
00368         }
00369     }
00370     QTabWidget::mousePressEvent( e );
00371 }
00372 
00373 void KTabWidget::receivedDropEvent( int index, QDropEvent *e )
00374 {
00375     emit( receivedDropEvent( page( index ), e ) );
00376 }
00377 
00378 void KTabWidget::initiateDrag( int index )
00379 {
00380     emit( initiateDrag( page( index ) ) );
00381 }
00382 
00383 void KTabWidget::contextMenu( int index, const QPoint &p )
00384 {
00385     emit( contextMenu( page( index ), p ) );
00386 }
00387 
00388 void KTabWidget::mouseDoubleClick( int index )
00389 {
00390     emit( mouseDoubleClick( page( index ) ) );
00391 }
00392 
00393 void KTabWidget::mouseMiddleClick( int index )
00394 {
00395     emit( mouseMiddleClick( page( index ) ) );
00396 }
00397 
00398 void KTabWidget::moveTab( int from, int to )
00399 {
00400     QString tablabel = label( from );
00401     QWidget *w = page( from );
00402     QColor color = tabColor( w );
00403     QIconSet tabiconset = tabIconSet( w );
00404     QString tabtooltip = tabToolTip( w );
00405     bool current = ( w == currentPage() );
00406     bool enabled = isTabEnabled( w );
00407     blockSignals(true);
00408     removePage( w );
00409 
00410     // Work-around kmdi brain damage which calls showPage() in insertTab()
00411     QTab * t = new QTab();
00412     t->setText(tablabel);
00413     QTabWidget::insertTab( w, t, to );
00414     if ( d->m_automaticResizeTabs ) {
00415         if ( to < 0 || to >= count() )
00416             d->m_tabNames.append( QString::null );
00417         else
00418             d->m_tabNames.insert( d->m_tabNames.at( to ), QString::null );
00419     }
00420 
00421     w = page( to );
00422     changeTab( w, tabiconset, tablabel );
00423     setTabToolTip( w, tabtooltip );
00424     setTabColor( w, color );
00425     if ( current )
00426         showPage( w );
00427     setTabEnabled( w, enabled );
00428     blockSignals(false);
00429 
00430     emit ( movedTab( from, to ) );
00431 }
00432 
00433 void KTabWidget::removePage( QWidget * w ) {
00434     if ( d->m_automaticResizeTabs ) {
00435         int index = indexOf( w );
00436         if ( index != -1 )
00437             d->m_tabNames.remove( d->m_tabNames.at( index ) );
00438     }
00439     QTabWidget::removePage( w );
00440     if ( d->m_automaticResizeTabs )
00441         resizeTabs();
00442 }
00443 
00444 
00445 bool KTabWidget::isEmptyTabbarSpace( const QPoint &p ) const
00446 {
00447     QPoint point( p );
00448     QSize size( tabBar()->sizeHint() );
00449     if ( ( tabPosition()==Top && point.y()< size.height() ) || ( tabPosition()==Bottom && point.y()>(height()-size.height() ) ) ) {
00450         QWidget *rightcorner = cornerWidget( TopRight );
00451         if ( rightcorner ) {
00452             if ( point.x()>=width()-rightcorner->width() )
00453                 return false;
00454         }
00455         QWidget *leftcorner = cornerWidget( TopLeft );
00456         if ( leftcorner ) {
00457             if ( point.x()<=leftcorner->width() )
00458                 return false;
00459             point.setX( point.x()-size.height() );
00460         }
00461         if ( tabPosition()==Bottom )
00462             point.setY( point.y()-( height()-size.height() ) );
00463         QTab *tab = tabBar()->selectTab( point);
00464         if( !tab )
00465             return true;
00466     }
00467     return false;
00468 }
00469 
00470 void KTabWidget::setHoverCloseButton( bool button )
00471 {
00472     static_cast<KTabBar*>(tabBar())->setHoverCloseButton( button );
00473 }
00474 
00475 bool KTabWidget::hoverCloseButton() const
00476 {
00477     return static_cast<KTabBar*>(tabBar())->hoverCloseButton();
00478 }
00479 
00480 void KTabWidget::setHoverCloseButtonDelayed( bool delayed )
00481 {
00482     static_cast<KTabBar*>(tabBar())->setHoverCloseButtonDelayed( delayed );
00483 }
00484 
00485 bool KTabWidget::hoverCloseButtonDelayed() const
00486 {
00487     return static_cast<KTabBar*>(tabBar())->hoverCloseButtonDelayed();
00488 }
00489 
00490 void KTabWidget::setAutomaticResizeTabs( bool enabled )
00491 {
00492     if ( d->m_automaticResizeTabs==enabled )
00493         return;
00494 
00495     d->m_automaticResizeTabs = enabled;
00496     if ( enabled ) {
00497         d->m_tabNames.clear();
00498         for( int i = 0; i < count(); ++i )
00499             d->m_tabNames.append( tabBar()->tabAt( i )->text() );
00500     }
00501     else
00502         for( int i = 0; i < count(); ++i )
00503             tabBar()->tabAt( i )->setText( d->m_tabNames[ i ] );
00504     resizeTabs();
00505 }
00506 
00507 bool KTabWidget::automaticResizeTabs() const
00508 {
00509     return d->m_automaticResizeTabs;
00510 }
00511 
00512 void KTabWidget::closeRequest( int index )
00513 {
00514     emit( closeRequest( page( index ) ) );
00515 }
00516 
00517 void KTabWidget::resizeEvent( QResizeEvent *e )
00518 {
00519     QTabWidget::resizeEvent( e );
00520     resizeTabs();
00521 }
00522 
00523 #include "ktabwidget.moc"
KDE Logo
This file is part of the documentation for kdeui Library Version 3.4.1.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Mon Jan 23 19:32:42 2006 by doxygen 1.4.3 written by Dimitri van Heesch, © 1997-2003