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 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
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
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
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
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
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
00291
00292
00293
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);
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
00334
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
00349
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
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
00526 setCloseButtonEnabled( button );
00527 }
00528
00529 bool KTabWidget::hoverCloseButton() const
00530 {
00531
00532 return false;
00533 }
00534
00535 void KTabWidget::setHoverCloseButtonDelayed( bool delayed )
00536 {
00537
00538 Q_UNUSED( delayed );
00539 }
00540
00541 bool KTabWidget::hoverCloseButtonDelayed() const
00542 {
00543
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"