00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
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
00061
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
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
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
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
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
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);
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
00323
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
00338
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
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
00515 setCloseButtonEnabled( button );
00516 }
00517
00518 bool KTabWidget::hoverCloseButton() const
00519 {
00520
00521 return false;
00522 }
00523
00524 void KTabWidget::setHoverCloseButtonDelayed( bool delayed )
00525 {
00526
00527 Q_UNUSED( delayed );
00528 }
00529
00530 bool KTabWidget::hoverCloseButtonDelayed() const
00531 {
00532
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"