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