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