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

KDEUI

ktabwidget.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 "ktabwidget.h"
00022 
00023 #include <QtGui/QApplication>
00024 #include <QtGui/QDragMoveEvent>
00025 #include <QtGui/QDropEvent>
00026 #include <QtGui/QMouseEvent>
00027 #include <QtGui/QStyle>
00028 #include <QtGui/QStyleOption>
00029 #include <QtGui/QTextDocument>
00030 #include <QtGui/QWheelEvent>
00031 
00032 #include <ksharedconfig.h>
00033 #include <kiconloader.h>
00034 #include <kstringhandler.h>
00035 
00036 #include <ktabbar.h>
00037 
00038 #include <kconfiggroup.h>
00039 
00040 class KTabWidget::Private
00041 {
00042   public:
00043     Private( KTabWidget *parent )
00044       : m_parent( parent ),
00045         m_automaticResizeTabs( false )
00046     {
00047 
00048       KConfigGroup cg(KGlobal::config(), "General");
00049       m_maxLength = cg.readEntry("MaximumTabLength", 30);
00050       m_minLength = cg.readEntry("MinimumTabLength", 3);
00051       m_currentMaxLength = m_minLength;
00052     }
00053 
00054     KTabWidget *m_parent;
00055     bool m_automaticResizeTabs;
00056     int m_maxLength;
00057     int m_minLength;
00058     int m_currentMaxLength;
00059 
00060     //holds the full names of the tab, otherwise all we
00061     //know about is the shortened name
00062     QStringList m_tabNames;
00063 
00064 
00065     bool isEmptyTabbarSpace( const QPoint & )  const;
00066     void resizeTabs( int changedTabIndex = -1 );
00067     void updateTab( int index );
00068 };
00069 
00070 bool KTabWidget::Private::isEmptyTabbarSpace( const QPoint &point ) const
00071 {
00072   QSize size( m_parent->tabBar()->sizeHint() );
00073   if ( ( m_parent->tabPosition() == QTabWidget::North && point.y() < size.height() ) ||
00074        ( m_parent->tabPosition() == QTabWidget::South && point.y() > (m_parent->height() - size.height() ) ) ) {
00075 
00076     QWidget *rightcorner = m_parent->cornerWidget( Qt::TopRightCorner );
00077     if ( rightcorner ) {
00078       if ( point.x() >= m_parent->width()-rightcorner->width() )
00079         return false;
00080     }
00081 
00082     QWidget *leftcorner = m_parent->cornerWidget( Qt::TopLeftCorner );
00083     if ( leftcorner ) {
00084       if ( point.x() <= leftcorner->width() )
00085         return false;
00086     }
00087 
00088     for ( int i = 0; i < m_parent->count(); ++i )
00089       if ( m_parent->tabBar()->tabRect( i ).contains( m_parent->tabBar()->mapFromParent( point ) ) )
00090         return false;
00091 
00092     return true;
00093   }
00094 
00095   return false;
00096 }
00097 
00098 void KTabWidget::Private::resizeTabs( int changeTabIndex )
00099 {
00100   int newMaxLength;
00101   if ( m_automaticResizeTabs ) {
00102     // Calculate new max length
00103     newMaxLength = m_maxLength;
00104     int lcw = 0, rcw = 0;
00105 
00106     int tabBarHeight = m_parent->tabBar()->sizeHint().height();
00107     if ( m_parent->cornerWidget( Qt::TopLeftCorner ) && m_parent->cornerWidget( Qt::TopLeftCorner )->isVisible() )
00108       lcw = qMax( m_parent->cornerWidget( Qt::TopLeftCorner )->width(), tabBarHeight );
00109 
00110     if ( m_parent->cornerWidget( Qt::TopRightCorner ) && m_parent->cornerWidget( Qt::TopRightCorner )->isVisible() )
00111       rcw = qMax( m_parent->cornerWidget( Qt::TopRightCorner )->width(), tabBarHeight );
00112 
00113     int maxTabBarWidth = m_parent->width() - lcw - rcw;
00114 
00115     for ( ; newMaxLength > m_minLength; newMaxLength-- ) {
00116       if ( m_parent->tabBarWidthForMaxChars( newMaxLength ) < maxTabBarWidth )
00117         break;
00118     }
00119   } else
00120     newMaxLength = 4711;
00121 
00122   // Update hinted or all tabs
00123   if ( m_currentMaxLength != newMaxLength ) {
00124     m_currentMaxLength = newMaxLength;
00125     for ( int i = 0; i < m_parent->count(); ++i )
00126       updateTab( i );
00127   } else if ( changeTabIndex != -1 )
00128     updateTab( changeTabIndex );
00129 }
00130 
00131 void KTabWidget::Private::updateTab( int index )
00132 {
00133   QString title = m_automaticResizeTabs ? m_tabNames[ index ] : m_parent->QTabWidget::tabText( index );
00134   m_parent->setTabToolTip( index, QString() );
00135 
00136   if ( title.length() > m_currentMaxLength ) {
00137     if ( Qt::mightBeRichText( title ) )
00138       m_parent->setTabToolTip( index, Qt::escape( title ) );
00139     else
00140       m_parent->setTabToolTip( index, title );
00141   }
00142 
00143   title = KStringHandler::rsqueeze( title, m_currentMaxLength ).leftJustified( m_minLength, ' ' );
00144   title.replace( '&', "&&" );
00145 
00146   if ( m_parent->QTabWidget::tabText( index ) != title )
00147     m_parent->QTabWidget::setTabText( index, title );
00148 }
00149 
00150 KTabWidget::KTabWidget( QWidget *parent, Qt::WFlags flags )
00151   : QTabWidget( parent ),
00152     d( new Private( this ) )
00153 {
00154   setWindowFlags( flags );
00155   setTabBar( new KTabBar( this ) );
00156   setObjectName( "tabbar" );
00157   setAcceptDrops( true );
00158 
00159   connect(tabBar(), SIGNAL(contextMenu( int, const QPoint & )), SLOT(contextMenu( int, const QPoint & )));
00160   connect(tabBar(), SIGNAL(tabDoubleClicked( int )), SLOT(mouseDoubleClick( int )));
00161   connect(tabBar(), SIGNAL(mouseMiddleClick( int )), SLOT(mouseMiddleClick( int )));
00162   connect(tabBar(), SIGNAL(initiateDrag( int )), SLOT(initiateDrag( int )));
00163   connect(tabBar(), SIGNAL(testCanDecode(const QDragMoveEvent *, bool & )), SIGNAL(testCanDecode(const QDragMoveEvent *, bool & )));
00164   connect(tabBar(), SIGNAL(receivedDropEvent( int, QDropEvent * )), SLOT(receivedDropEvent( int, QDropEvent * )));
00165   connect(tabBar(), SIGNAL(moveTab( int, int )), SLOT(moveTab( int, int )));
00166   connect(tabBar(), SIGNAL(closeRequest( int )), SLOT(closeRequest( int )));
00167 #ifndef QT_NO_WHEELEVENT
00168   connect(tabBar(), SIGNAL(wheelDelta( int )), SLOT(wheelDelta( int )));
00169 #endif
00170 }
00171 
00172 KTabWidget::~KTabWidget()
00173 {
00174   delete d;
00175 }
00176 
00177 /*void KTabWidget::insertTab( QWidget *child, const QString &label, int index )
00178 {
00179   QTabWidget::insertTab( child, label, index );
00180 }
00181 
00182 void KTabWidget::insertTab( QWidget *child, const QIcon& iconset, const QString &label, int index )
00183 {
00184   QTabWidget::insertTab( child, iconset, label, index );
00185 }
00186 
00187 void KTabWidget::insertTab( QWidget *child, QTab *tab, int index )
00188 {
00189   QTabWidget::insertTab( child, tab, index);
00190   if ( d->m_automaticResizeTabs ) {
00191     if ( index < 0 || index >= count() ) {
00192       d->m_tabNames.append( tab->text() );
00193       d->resizeTabs( d->m_tabNames.count()-1 );
00194     }
00195     else {
00196       d->m_tabNames.insert( d->m_tabNames.at( index ), tab->text() );
00197       d->resizeTabs( index );
00198     }
00199   }
00200 }*/
00201 
00202 void KTabWidget::setTabBarHidden( bool hide )
00203 {
00204   QWidget *rightcorner = cornerWidget( Qt::TopRightCorner );
00205   QWidget *leftcorner = cornerWidget( Qt::TopLeftCorner );
00206 
00207   if ( hide ) {
00208     if ( leftcorner ) leftcorner->hide();
00209     if ( rightcorner ) rightcorner->hide();
00210     tabBar()->hide();
00211   } else {
00212     tabBar()->show();
00213     if ( leftcorner ) leftcorner->show();
00214     if ( rightcorner ) rightcorner->show();
00215   }
00216 }
00217 
00218 bool KTabWidget::isTabBarHidden() const
00219 {
00220   return !( tabBar()->isVisible() );
00221 }
00222 
00223 void KTabWidget::setTabTextColor( int index, const QColor& color )
00224 {
00225   tabBar()->setTabTextColor( index, color );
00226 }
00227 
00228 QColor KTabWidget::tabTextColor( int index ) const
00229 {
00230   return tabBar()->tabTextColor( index );
00231 }
00232 
00233 void KTabWidget::setTabReorderingEnabled( bool on)
00234 {
00235   static_cast<KTabBar*>(tabBar())->setTabReorderingEnabled( on );
00236 }
00237 
00238 bool KTabWidget::isTabReorderingEnabled() const
00239 {
00240   return static_cast<KTabBar*>(tabBar())->isTabReorderingEnabled();
00241 }
00242 
00243 void KTabWidget::setTabCloseActivatePrevious( bool previous)
00244 {
00245   static_cast<KTabBar*>(tabBar())->setTabCloseActivatePrevious( previous );
00246 }
00247 
00248 bool KTabWidget::tabCloseActivatePrevious() const
00249 {
00250   return static_cast<KTabBar*>(tabBar())->tabCloseActivatePrevious();
00251 }
00252 
00253 int KTabWidget::tabBarWidthForMaxChars( int maxLength )
00254 {
00255   int hframe, overlap;
00256   hframe  = tabBar()->style()->pixelMetric( QStyle::PM_TabBarTabHSpace, 0L, tabBar() );
00257   overlap = tabBar()->style()->pixelMetric( QStyle::PM_TabBarTabOverlap, 0L, tabBar() );
00258 
00259   QFontMetrics fm = tabBar()->fontMetrics();
00260   int x = 0;
00261   for ( int i = 0; i < count(); ++i ) {
00262     QString newTitle = d->m_tabNames[ i ];
00263     newTitle = KStringHandler::rsqueeze( newTitle, maxLength ).leftJustified( d->m_minLength, ' ' );
00264 
00265     int lw = fm.width( newTitle );
00266     int iw = 0;
00267     if ( !tabBar()->tabIcon( i ).isNull() ) {
00268       iw = tabBar()->tabIcon( i ).pixmap( style()->pixelMetric( QStyle::PM_SmallIconSize ), QIcon::Normal ).width() + 4;
00269     }
00270     if ( isCloseButtonEnabled() ) {
00271       // FIXME: how to get the size of the close button directly from the tabBar()?
00272       iw += KIconLoader::SizeSmall * 3 / 2;
00273     }
00274     x += ( tabBar()->style()->sizeFromContents( QStyle::CT_TabBarTab, 0L,
00275          QSize( qMax( lw + hframe + iw, QApplication::globalStrut().width() ), 0 ),
00276          this ) ).width();
00277   }
00278 
00279   return x;
00280 }
00281 
00282 QString KTabWidget::tabText( int index ) const
00283 {
00284   if ( d->m_automaticResizeTabs ) {
00285     if ( index >= 0 && index < count() )
00286       return d->m_tabNames[ index ];
00287     else
00288       return QString();
00289   }
00290   else
00291     return QTabWidget::tabText( index );
00292 }
00293 
00294 void KTabWidget::setTabText( int index, const QString &text )
00295 {
00296   if (text == tabText(index))
00297     return;
00298 
00299   if ( d->m_automaticResizeTabs ) {
00300 
00301     tabBar()->setUpdatesEnabled(false); //no flicker
00302 
00303     QTabWidget::setTabText( index, text );
00304 
00305     if ( index != -1 ) {
00306       d->m_tabNames[ index ] = text;
00307       d->resizeTabs( index );
00308     }
00309 
00310     tabBar()->setUpdatesEnabled(true);
00311 
00312   } else {
00313     QTabWidget::setTabText( index, text );
00314   }
00315 }
00316 
00317 
00318 void KTabWidget::dragEnterEvent( QDragEnterEvent *event )
00319 {
00320   if ( d->isEmptyTabbarSpace( event->pos() ) ) {
00321     bool accept = false;
00322     // The receivers of the testCanDecode() signal has to adjust
00323     // 'accept' accordingly.
00324     emit testCanDecode( event, accept);
00325 
00326     event->setAccepted( accept );
00327     return;
00328   }
00329 
00330   QTabWidget::dragEnterEvent( event );
00331 }
00332 
00333 void KTabWidget::dragMoveEvent( QDragMoveEvent *event )
00334 {
00335   if ( d->isEmptyTabbarSpace( event->pos() ) ) {
00336     bool accept = false;
00337     // The receivers of the testCanDecode() signal has to adjust
00338     // 'accept' accordingly.
00339     emit testCanDecode( event, accept);
00340 
00341     event->setAccepted( accept );
00342     return;
00343   }
00344 
00345   QTabWidget::dragMoveEvent( event );
00346 }
00347 
00348 void KTabWidget::dropEvent( QDropEvent *event )
00349 {
00350   if ( d->isEmptyTabbarSpace( event->pos() ) ) {
00351     emit ( receivedDropEvent( event ) );
00352     return;
00353   }
00354 
00355   QTabWidget::dropEvent( event );
00356 }
00357 
00358 #ifndef QT_NO_WHEELEVENT
00359 void KTabWidget::wheelEvent( QWheelEvent *event )
00360 {
00361   if ( event->orientation() == Qt::Horizontal )
00362     return;
00363 
00364   if ( d->isEmptyTabbarSpace( event->pos() ) )
00365     wheelDelta( event->delta() );
00366   else
00367     event->ignore();
00368 }
00369 
00370 void KTabWidget::wheelDelta( int delta )
00371 {
00372   if ( count() < 2 )
00373     return;
00374 
00375   int page = currentIndex();
00376   if ( delta < 0 )
00377      page = (page + 1) % count();
00378   else {
00379     page--;
00380     if ( page < 0 )
00381       page = count() - 1;
00382   }
00383   setCurrentIndex( page );
00384 }
00385 #endif
00386 
00387 void KTabWidget::mouseDoubleClickEvent( QMouseEvent *event )
00388 {
00389   if ( event->button() != Qt::LeftButton )
00390     return;
00391 
00392   if ( d->isEmptyTabbarSpace( event->pos() ) ) {
00393     emit( mouseDoubleClick() );
00394     return;
00395   }
00396 
00397   QTabWidget::mouseDoubleClickEvent( event );
00398 }
00399 
00400 void KTabWidget::mousePressEvent( QMouseEvent *event )
00401 {
00402   if ( event->button() == Qt::RightButton ) {
00403     if ( d->isEmptyTabbarSpace( event->pos() ) ) {
00404       emit( contextMenu( mapToGlobal( event->pos() ) ) );
00405       return;
00406     }
00407   } else if ( event->button() == Qt::MidButton ) {
00408     if ( d->isEmptyTabbarSpace( event->pos() ) ) {
00409       emit( mouseMiddleClick() );
00410       return;
00411     }
00412   }
00413 
00414   QTabWidget::mousePressEvent( event );
00415 }
00416 
00417 void KTabWidget::receivedDropEvent( int index, QDropEvent *event )
00418 {
00419   emit( receivedDropEvent( widget( index ), event ) );
00420 }
00421 
00422 void KTabWidget::initiateDrag( int index )
00423 {
00424   emit( initiateDrag( widget( index ) ) );
00425 }
00426 
00427 void KTabWidget::contextMenu( int index, const QPoint &point )
00428 {
00429   emit( contextMenu( widget( index ), point ) );
00430 }
00431 
00432 void KTabWidget::mouseDoubleClick( int index )
00433 {
00434   emit( mouseDoubleClick( widget( index ) ) );
00435 }
00436 
00437 void KTabWidget::mouseMiddleClick( int index )
00438 {
00439   emit( mouseMiddleClick( widget( index ) ) );
00440 }
00441 
00442 void KTabWidget::moveTab( int from, int to )
00443 {
00444   setUpdatesEnabled(false);
00445 
00446   QString tablabel = tabText( from );
00447   QWidget *w = widget( from );
00448   QColor color = tabTextColor( from );
00449   QIcon tabiconset = tabIcon( from );
00450   QString tabtooltip = tabToolTip( from );
00451   bool current = ( from == currentIndex() );
00452   bool enabled = isTabEnabled( from );
00453 
00454   bool blocked = blockSignals( true );
00455   removeTab( from );
00456 
00457   // Work-around kmdi brain damage which calls showPage() in insertTab()
00458   insertTab( to, w, tablabel );
00459   if ( d->m_automaticResizeTabs ) {
00460     if ( to < 0 || to >= count() )
00461       d->m_tabNames.append( QString() );
00462     else
00463       d->m_tabNames.insert( to, QString() );
00464   }
00465 
00466   setTabIcon( to, tabiconset );
00467   setTabText( to, tablabel );
00468   setTabToolTip( to, tabtooltip );
00469   setTabTextColor( to, color );
00470   if ( current )
00471     setCurrentIndex( to );
00472   setTabEnabled( to, enabled );
00473   blockSignals( blocked );
00474 
00475   setUpdatesEnabled(true);
00476 
00477   emit ( movedTab( from, to ) );
00478 }
00479 
00480 void KTabWidget::removePage( QWidget *widget )
00481 {
00482   if ( d->m_automaticResizeTabs ) {
00483 
00484     setUpdatesEnabled(false);
00485 
00486     QTabWidget::removeTab( indexOf( widget ) );
00487     d->resizeTabs();
00488 
00489     setUpdatesEnabled(true);
00490 
00491   } else {
00492     QTabWidget::removeTab( indexOf( widget ) );
00493   }
00494 }
00495 
00496 void KTabWidget::removeTab( int index )
00497 {
00498   if ( d->m_automaticResizeTabs ) {
00499 
00500     setUpdatesEnabled(false);
00501 
00502     QTabWidget::removeTab( index );
00503     d->resizeTabs();
00504 
00505     setUpdatesEnabled(true);
00506 
00507   } else {
00508     QTabWidget::removeTab( index );
00509   }
00510 }
00511 
00512 void KTabWidget::setHoverCloseButton( bool button )
00513 {
00514   // deprecated
00515   setCloseButtonEnabled( button );
00516 }
00517 
00518 bool KTabWidget::hoverCloseButton() const
00519 {
00520   // deprecated
00521   return false;
00522 }
00523 
00524 void KTabWidget::setHoverCloseButtonDelayed( bool delayed )
00525 {
00526   // deprecated
00527   Q_UNUSED( delayed );
00528 }
00529 
00530 bool KTabWidget::hoverCloseButtonDelayed() const
00531 {
00532   // deprecated
00533   return isCloseButtonEnabled();
00534 }
00535 
00536 void KTabWidget::setCloseButtonEnabled( bool enable )
00537 {
00538   static_cast<KTabBar*>( tabBar() )->setCloseButtonEnabled( enable );
00539 }
00540 
00541 bool KTabWidget::isCloseButtonEnabled() const
00542 {
00543   return static_cast<KTabBar*>( tabBar() )->isCloseButtonEnabled();
00544 }
00545 
00546 void KTabWidget::setAutomaticResizeTabs( bool enabled )
00547 {
00548   if ( d->m_automaticResizeTabs == enabled )
00549     return;
00550 
00551   setUpdatesEnabled(false);
00552 
00553   d->m_automaticResizeTabs = enabled;
00554   if ( enabled ) {
00555     d->m_tabNames.clear();
00556     for ( int i = 0; i < count(); ++i )
00557       d->m_tabNames.append( tabBar()->tabText( i ) );
00558   } else
00559     for ( int i = 0; i < count(); ++i )
00560       tabBar()->setTabText( i, d->m_tabNames[ i ] );
00561 
00562   d->resizeTabs();
00563 
00564   setUpdatesEnabled(true);
00565 }
00566 
00567 bool KTabWidget::automaticResizeTabs() const
00568 {
00569   return d->m_automaticResizeTabs;
00570 }
00571 
00572 void KTabWidget::closeRequest( int index )
00573 {
00574   emit( closeRequest( widget( index ) ) );
00575 }
00576 
00577 void KTabWidget::resizeEvent( QResizeEvent *event )
00578 {
00579   QTabWidget::resizeEvent( event );
00580   d->resizeTabs();
00581 }
00582 
00583 void KTabWidget::tabInserted( int idx )
00584 {
00585    d->m_tabNames.insert( idx, tabBar()->tabText( idx ) );
00586 }
00587 
00588 void KTabWidget::tabRemoved( int idx )
00589 {
00590    d->m_tabNames.removeAt( idx );
00591 }
00592 
00593 #include "ktabwidget.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