src/gui/widgets/qtabbar.cpp
changeset 0 1918ee327afb
child 3 41300fa6a67c
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the QtGui module of the Qt Toolkit.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 #include "private/qlayoutengine_p.h"
       
    43 #include "qabstractitemdelegate.h"
       
    44 #include "qapplication.h"
       
    45 #include "qbitmap.h"
       
    46 #include "qcursor.h"
       
    47 #include "qevent.h"
       
    48 #include "qpainter.h"
       
    49 #include "qstyle.h"
       
    50 #include "qstyleoption.h"
       
    51 #include "qstylepainter.h"
       
    52 #include "qtabwidget.h"
       
    53 #include "qtooltip.h"
       
    54 #include "qwhatsthis.h"
       
    55 #include "private/qtextengine_p.h"
       
    56 #ifndef QT_NO_ACCESSIBILITY
       
    57 #include "qaccessible.h"
       
    58 #endif
       
    59 
       
    60 #include "qdebug.h"
       
    61 #include "private/qtabbar_p.h"
       
    62 
       
    63 #ifndef QT_NO_TABBAR
       
    64 
       
    65 #ifdef Q_WS_MAC
       
    66 #include <private/qt_mac_p.h>
       
    67 #include <private/qt_cocoa_helpers_mac_p.h>
       
    68 #endif
       
    69 
       
    70 QT_BEGIN_NAMESPACE
       
    71 
       
    72 inline static bool verticalTabs(QTabBar::Shape shape)
       
    73 {
       
    74     return shape == QTabBar::RoundedWest
       
    75            || shape == QTabBar::RoundedEast
       
    76            || shape == QTabBar::TriangularWest
       
    77            || shape == QTabBar::TriangularEast;
       
    78 }
       
    79 
       
    80 void QTabBarPrivate::updateMacBorderMetrics()
       
    81 {
       
    82 #if (defined Q_WS_MAC) && (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5)
       
    83     if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_5) {
       
    84         Q_Q(QTabBar);
       
    85         ::HIContentBorderMetrics metrics;
       
    86 
       
    87         // TODO: get metrics to preserve the bottom value
       
    88         // TODO: test tab bar position
       
    89 
       
    90         OSWindowRef window = qt_mac_window_for(q);
       
    91 
       
    92         // push base line separator down to the client are so we can paint over it (Carbon)
       
    93         metrics.top = (documentMode && q->isVisible()) ? 1 : 0;
       
    94         metrics.bottom = 0;
       
    95         metrics.left = 0;
       
    96         metrics.right = 0;
       
    97         qt_mac_updateContentBorderMetricts(window, metrics);
       
    98         
       
    99         // hide the base line separator if the tabs have docuemnt mode enabled (Cocoa)
       
   100         qt_mac_showBaseLineSeparator(window, !documentMode);
       
   101     }
       
   102 #endif
       
   103 }
       
   104 
       
   105 /*!
       
   106     Initialize \a option with the values from the tab at \a tabIndex. This method
       
   107     is useful for subclasses when they need a QStyleOptionTab, QStyleOptionTabV2,
       
   108     or QStyleOptionTabV3 but don't want to fill in all the information themselves.
       
   109     This function will check the version of the QStyleOptionTab and fill in the
       
   110     additional values for a QStyleOptionTabV2 and QStyleOptionTabV3.
       
   111 
       
   112     \sa QStyleOption::initFrom() QTabWidget::initStyleOption()
       
   113 */
       
   114 void QTabBar::initStyleOption(QStyleOptionTab *option, int tabIndex) const
       
   115 {
       
   116     Q_D(const QTabBar);
       
   117     int totalTabs = d->tabList.size();
       
   118 
       
   119     if (!option || (tabIndex < 0 || tabIndex >= totalTabs))
       
   120         return;
       
   121 
       
   122     const QTabBarPrivate::Tab &tab = d->tabList.at(tabIndex);
       
   123     option->initFrom(this);
       
   124     option->state &= ~(QStyle::State_HasFocus | QStyle::State_MouseOver);
       
   125     option->rect = tabRect(tabIndex);
       
   126     bool isCurrent = tabIndex == d->currentIndex;
       
   127     option->row = 0;
       
   128     if (tabIndex == d->pressedIndex)
       
   129         option->state |= QStyle::State_Sunken;
       
   130     if (isCurrent)
       
   131         option->state |= QStyle::State_Selected;
       
   132     if (isCurrent && hasFocus())
       
   133         option->state |= QStyle::State_HasFocus;
       
   134     if (!tab.enabled)
       
   135         option->state &= ~QStyle::State_Enabled;
       
   136     if (isActiveWindow())
       
   137         option->state |= QStyle::State_Active;
       
   138     if (!d->dragInProgress && option->rect == d->hoverRect)
       
   139         option->state |= QStyle::State_MouseOver;
       
   140     option->shape = d->shape;
       
   141     option->text = tab.text;
       
   142 
       
   143     if (tab.textColor.isValid())
       
   144         option->palette.setColor(foregroundRole(), tab.textColor);
       
   145 
       
   146     option->icon = tab.icon;
       
   147     if (QStyleOptionTabV2 *optionV2 = qstyleoption_cast<QStyleOptionTabV2 *>(option))
       
   148         optionV2->iconSize = iconSize();  // Will get the default value then.
       
   149 
       
   150     if (QStyleOptionTabV3 *optionV3 = qstyleoption_cast<QStyleOptionTabV3 *>(option)) {
       
   151         optionV3->leftButtonSize = tab.leftWidget ? tab.leftWidget->size() : QSize();
       
   152         optionV3->rightButtonSize = tab.rightWidget ? tab.rightWidget->size() : QSize();
       
   153         optionV3->documentMode = d->documentMode;
       
   154     }
       
   155 
       
   156     if (tabIndex > 0 && tabIndex - 1 == d->currentIndex)
       
   157         option->selectedPosition = QStyleOptionTab::PreviousIsSelected;
       
   158     else if (tabIndex < totalTabs - 1 && tabIndex + 1 == d->currentIndex)
       
   159         option->selectedPosition = QStyleOptionTab::NextIsSelected;
       
   160     else
       
   161         option->selectedPosition = QStyleOptionTab::NotAdjacent;
       
   162 
       
   163     bool paintBeginning = (tabIndex == 0) || (d->dragInProgress && tabIndex == d->pressedIndex + 1);
       
   164     bool paintEnd = (tabIndex == totalTabs - 1) || (d->dragInProgress && tabIndex == d->pressedIndex - 1);
       
   165     if (paintBeginning) {
       
   166         if (paintEnd)
       
   167             option->position = QStyleOptionTab::OnlyOneTab;
       
   168         else
       
   169             option->position = QStyleOptionTab::Beginning;
       
   170     } else if (paintEnd) {
       
   171         option->position = QStyleOptionTab::End;
       
   172     } else {
       
   173         option->position = QStyleOptionTab::Middle;
       
   174     }
       
   175 
       
   176 #ifndef QT_NO_TABWIDGET
       
   177     if (const QTabWidget *tw = qobject_cast<const QTabWidget *>(parentWidget())) {
       
   178         if (tw->cornerWidget(Qt::TopLeftCorner) || tw->cornerWidget(Qt::BottomLeftCorner))
       
   179             option->cornerWidgets |= QStyleOptionTab::LeftCornerWidget;
       
   180         if (tw->cornerWidget(Qt::TopRightCorner) || tw->cornerWidget(Qt::BottomRightCorner))
       
   181             option->cornerWidgets |= QStyleOptionTab::RightCornerWidget;
       
   182     }
       
   183 #endif
       
   184 
       
   185     QRect textRect = style()->subElementRect(QStyle::SE_TabBarTabText, option, this);
       
   186     option->text = fontMetrics().elidedText(option->text, d->elideMode, textRect.width(),
       
   187                         Qt::TextShowMnemonic);
       
   188 }
       
   189 
       
   190 /*!
       
   191     \class QTabBar
       
   192     \brief The QTabBar class provides a tab bar, e.g. for use in tabbed dialogs.
       
   193 
       
   194     \ingroup basicwidgets
       
   195 
       
   196 
       
   197     QTabBar is straightforward to use; it draws the tabs using one of
       
   198     the predefined \link QTabBar::Shape shapes\endlink, and emits a
       
   199     signal when a tab is selected. It can be subclassed to tailor the
       
   200     look and feel. Qt also provides a ready-made \l{QTabWidget}.
       
   201 
       
   202     Each tab has a tabText(), an optional tabIcon(), an optional
       
   203     tabToolTip(), optional tabWhatsThis() and optional tabData().
       
   204     The tabs's attributes can be changed with setTabText(), setTabIcon(),
       
   205     setTabToolTip(), setTabWhatsThis and setTabData(). Each tabs can be
       
   206     enabled or disabled individually with setTabEnabled().
       
   207 
       
   208     Each tab can display text in a distinct color. The current text color
       
   209     for a tab can be found with the tabTextColor() function. Set the text
       
   210     color for a particular tab with setTabTextColor().
       
   211 
       
   212     Tabs are added using addTab(), or inserted at particular positions
       
   213     using insertTab(). The total number of tabs is given by
       
   214     count(). Tabs can be removed from the tab bar with
       
   215     removeTab(). Combining removeTab() and insertTab() allows you to
       
   216     move tabs to different positions.
       
   217 
       
   218     The \l shape property defines the tabs' appearance. The choice of
       
   219     shape is a matter of taste, although tab dialogs (for preferences
       
   220     and similar) invariably use \l RoundedNorth.
       
   221     Tab controls in windows other than dialogs almost
       
   222     always use either \l RoundedSouth or \l TriangularSouth. Many
       
   223     spreadsheets and other tab controls in which all the pages are
       
   224     essentially similar use \l TriangularSouth, whereas \l
       
   225     RoundedSouth is used mostly when the pages are different (e.g. a
       
   226     multi-page tool palette). The default in QTabBar is \l
       
   227     RoundedNorth.
       
   228 
       
   229     The most important part of QTabBar's API is the currentChanged()
       
   230     signal.  This is emitted whenever the current tab changes (even at
       
   231     startup, when the current tab changes from 'none'). There is also
       
   232     a slot, setCurrentIndex(), which can be used to select a tab
       
   233     programmatically. The function currentIndex() returns the index of
       
   234     the current tab, \l count holds the number of tabs.
       
   235 
       
   236     QTabBar creates automatic mnemonic keys in the manner of QAbstractButton;
       
   237     e.g. if a tab's label is "\&Graphics", Alt+G becomes a shortcut
       
   238     key for switching to that tab.
       
   239 
       
   240     The following virtual functions may need to be reimplemented in
       
   241     order to tailor the look and feel or store extra data with each
       
   242     tab:
       
   243 
       
   244     \list
       
   245     \i tabSizeHint() calcuates the size of a tab.
       
   246     \i tabInserted() notifies that a new tab was added.
       
   247     \i tabRemoved() notifies that a tab was removed.
       
   248     \i tabLayoutChange() notifies that the tabs have been re-laid out.
       
   249     \i paintEvent() paints all tabs.
       
   250     \endlist
       
   251 
       
   252     For subclasses, you might also need the tabRect() functions which
       
   253     returns the visual geometry of a single tab.
       
   254 
       
   255     \table 100%
       
   256     \row \o \inlineimage plastique-tabbar.png Screenshot of a Plastique style tab bar
       
   257          \o A tab bar shown in the Plastique widget style.
       
   258     \row \o \inlineimage plastique-tabbar-truncated.png Screenshot of a truncated Plastique tab bar
       
   259          \o A truncated tab bar shown in the Plastique widget style.
       
   260     \endtable
       
   261 
       
   262     \sa QTabWidget
       
   263 */
       
   264 
       
   265 /*!
       
   266     \enum QTabBar::Shape
       
   267 
       
   268     This enum type lists the built-in shapes supported by QTabBar. Treat these
       
   269     as hints as some styles may not render some of the shapes. However,
       
   270     position should be honored.
       
   271 
       
   272     \value RoundedNorth  The normal rounded look above the pages
       
   273 
       
   274     \value RoundedSouth  The normal rounded look below the pages
       
   275 
       
   276     \value RoundedWest  The normal rounded look on the left side of the pages
       
   277 
       
   278     \value RoundedEast  The normal rounded look on the right side the pages
       
   279 
       
   280     \value TriangularNorth  Triangular tabs above the pages.
       
   281 
       
   282     \value TriangularSouth  Triangular tabs similar to those used in
       
   283     the Excel spreadsheet, for example
       
   284 
       
   285     \value TriangularWest  Triangular tabs on the left of the pages.
       
   286 
       
   287     \value TriangularEast  Triangular tabs on the right of the pages.
       
   288     \omitvalue RoundedAbove
       
   289     \omitvalue RoundedBelow
       
   290     \omitvalue TriangularAbove
       
   291     \omitvalue TriangularBelow
       
   292 */
       
   293 
       
   294 /*!
       
   295     \fn void QTabBar::currentChanged(int index)
       
   296 
       
   297     This signal is emitted when the tab bar's current tab changes. The
       
   298     new current has the given \a index, or -1 if there isn't a new one
       
   299     (for example, if there are no tab in the QTabBar)
       
   300 */
       
   301 
       
   302 /*!
       
   303     \fn void QTabBar::tabCloseRequested(int index)
       
   304     \since 4.5
       
   305 
       
   306     This signal is emitted when the close button on a tab is clicked.
       
   307     The \a index is the index that should be removed.
       
   308 
       
   309     \sa setTabsClosable()
       
   310 */
       
   311 
       
   312 /*!
       
   313     \fn void QTabBar::tabMoved(int from, int to)
       
   314     \since 4.5
       
   315 
       
   316     This signal is emitted when the tab has moved the tab
       
   317     at index position \a from to index position \a to.
       
   318 
       
   319     note: QTabWidget will automatically move the page when
       
   320     this signal is emitted from its tab bar.
       
   321 
       
   322     \sa moveTab()
       
   323 */
       
   324 
       
   325 int QTabBarPrivate::extraWidth() const
       
   326 {
       
   327     Q_Q(const QTabBar);
       
   328     return 2 * qMax(q->style()->pixelMetric(QStyle::PM_TabBarScrollButtonWidth, 0, q),
       
   329                     QApplication::globalStrut().width());
       
   330 }
       
   331 
       
   332 void QTabBarPrivate::init()
       
   333 {
       
   334     Q_Q(QTabBar);
       
   335     leftB = new QToolButton(q);
       
   336     leftB->setAutoRepeat(true);
       
   337     QObject::connect(leftB, SIGNAL(clicked()), q, SLOT(_q_scrollTabs()));
       
   338     leftB->hide();
       
   339     rightB = new QToolButton(q);
       
   340     rightB->setAutoRepeat(true);
       
   341     QObject::connect(rightB, SIGNAL(clicked()), q, SLOT(_q_scrollTabs()));
       
   342     rightB->hide();
       
   343 #ifdef QT_KEYPAD_NAVIGATION
       
   344     if (QApplication::keypadNavigationEnabled()) {
       
   345         leftB->setFocusPolicy(Qt::NoFocus);
       
   346         rightB->setFocusPolicy(Qt::NoFocus);
       
   347         q->setFocusPolicy(Qt::NoFocus);
       
   348     } else
       
   349 #endif
       
   350     q->setFocusPolicy(Qt::TabFocus);
       
   351     q->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
       
   352     elideMode = Qt::TextElideMode(q->style()->styleHint(QStyle::SH_TabBar_ElideMode, 0, q));
       
   353     useScrollButtons = !q->style()->styleHint(QStyle::SH_TabBar_PreferNoArrows, 0, q);
       
   354 }
       
   355 
       
   356 QTabBarPrivate::Tab *QTabBarPrivate::at(int index)
       
   357 {
       
   358     return validIndex(index)?&tabList[index]:0;
       
   359 }
       
   360 
       
   361 const QTabBarPrivate::Tab *QTabBarPrivate::at(int index) const
       
   362 {
       
   363     return validIndex(index)?&tabList[index]:0;
       
   364 }
       
   365 
       
   366 int QTabBarPrivate::indexAtPos(const QPoint &p) const
       
   367 {
       
   368     Q_Q(const QTabBar);
       
   369     if (q->tabRect(currentIndex).contains(p))
       
   370         return currentIndex;
       
   371     for (int i = 0; i < tabList.count(); ++i)
       
   372         if (tabList.at(i).enabled && q->tabRect(i).contains(p))
       
   373             return i;
       
   374     return -1;
       
   375 }
       
   376 
       
   377 void QTabBarPrivate::layoutTabs()
       
   378 {
       
   379     Q_Q(QTabBar);
       
   380     scrollOffset = 0;
       
   381     layoutDirty = false;
       
   382     QSize size = q->size();
       
   383     int last, available;
       
   384     int maxExtent;
       
   385     int i;
       
   386     bool vertTabs = verticalTabs(shape);
       
   387     int tabChainIndex = 0;
       
   388 
       
   389     Qt::Alignment tabAlignment = Qt::Alignment(q->style()->styleHint(QStyle::SH_TabBar_Alignment, 0, q));
       
   390     QVector<QLayoutStruct> tabChain(tabList.count() + 2);
       
   391 
       
   392     // We put an empty item at the front and back and set its expansive attribute
       
   393     // depending on tabAlignment.
       
   394     tabChain[tabChainIndex].init();
       
   395     tabChain[tabChainIndex].expansive = (tabAlignment != Qt::AlignLeft)
       
   396                                         && (tabAlignment != Qt::AlignJustify);
       
   397     tabChain[tabChainIndex].empty = true;
       
   398     ++tabChainIndex;
       
   399 
       
   400     // We now go through our list of tabs and set the minimum size and the size hint
       
   401     // This will allow us to elide text if necessary. Since we don't set
       
   402     // a maximum size, tabs will EXPAND to fill up the empty space.
       
   403     // Since tab widget is rather *ahem* strict about keeping the geometry of the
       
   404     // tab bar to its absolute minimum, this won't bleed through, but will show up
       
   405     // if you use tab bar on its own (a.k.a. not a bug, but a feature).
       
   406     // Update: if expanding is false, we DO set a maximum size to prevent the tabs
       
   407     // being wider than necessary.
       
   408     if (!vertTabs) {
       
   409         int minx = 0;
       
   410         int x = 0;
       
   411         int maxHeight = 0;
       
   412         for (i = 0; i < tabList.count(); ++i, ++tabChainIndex) {
       
   413             QSize sz = q->tabSizeHint(i);
       
   414             tabList[i].maxRect = QRect(x, 0, sz.width(), sz.height());
       
   415             x += sz.width();
       
   416             maxHeight = qMax(maxHeight, sz.height());
       
   417             sz = minimumTabSizeHint(i);
       
   418             tabList[i].minRect = QRect(minx, 0, sz.width(), sz.height());
       
   419             minx += sz.width();
       
   420             tabChain[tabChainIndex].init();
       
   421             tabChain[tabChainIndex].sizeHint = tabList.at(i).maxRect.width();
       
   422             tabChain[tabChainIndex].minimumSize = sz.width();
       
   423             tabChain[tabChainIndex].empty = false;
       
   424             tabChain[tabChainIndex].expansive = true;
       
   425 
       
   426             if (!expanding)
       
   427                 tabChain[tabChainIndex].maximumSize = tabChain[tabChainIndex].sizeHint;
       
   428         }
       
   429 
       
   430         last = minx;
       
   431         available = size.width();
       
   432         maxExtent = maxHeight;
       
   433     } else {
       
   434         int miny = 0;
       
   435         int y = 0;
       
   436         int maxWidth = 0;
       
   437         for (i = 0; i < tabList.count(); ++i, ++tabChainIndex) {
       
   438             QSize sz = q->tabSizeHint(i);
       
   439             tabList[i].maxRect = QRect(0, y, sz.width(), sz.height());
       
   440             y += sz.height();
       
   441             maxWidth = qMax(maxWidth, sz.width());
       
   442             sz = minimumTabSizeHint(i);
       
   443             tabList[i].minRect = QRect(0, miny, sz.width(), sz.height());
       
   444             miny += sz.height();
       
   445             tabChain[tabChainIndex].init();
       
   446             tabChain[tabChainIndex].sizeHint = tabList.at(i).maxRect.height();
       
   447             tabChain[tabChainIndex].minimumSize = sz.height();
       
   448             tabChain[tabChainIndex].empty = false;
       
   449             tabChain[tabChainIndex].expansive = true;
       
   450 
       
   451             if (!expanding)
       
   452                 tabChain[tabChainIndex].maximumSize = tabChain[tabChainIndex].sizeHint;
       
   453         }
       
   454 
       
   455         last = miny;
       
   456         available = size.height();
       
   457         maxExtent = maxWidth;
       
   458     }
       
   459 
       
   460     Q_ASSERT(tabChainIndex == tabChain.count() - 1); // add an assert just to make sure.
       
   461     // Mirror our front item.
       
   462     tabChain[tabChainIndex].init();
       
   463     tabChain[tabChainIndex].expansive = (tabAlignment != Qt::AlignRight)
       
   464                                         && (tabAlignment != Qt::AlignJustify);
       
   465     tabChain[tabChainIndex].empty = true;
       
   466 
       
   467     // Do the calculation
       
   468     qGeomCalc(tabChain, 0, tabChain.count(), 0, qMax(available, last), 0);
       
   469 
       
   470     // Use the results
       
   471     for (i = 0; i < tabList.count(); ++i) {
       
   472         const QLayoutStruct &lstruct = tabChain.at(i + 1);
       
   473         if (!vertTabs)
       
   474             tabList[i].rect.setRect(lstruct.pos, 0, lstruct.size, maxExtent);
       
   475         else
       
   476             tabList[i].rect.setRect(0, lstruct.pos, maxExtent, lstruct.size);
       
   477     }
       
   478 
       
   479     if (useScrollButtons && tabList.count() && last > available) {
       
   480         int extra = extraWidth();
       
   481         if (!vertTabs) {
       
   482             Qt::LayoutDirection ld = q->layoutDirection();
       
   483             QRect arrows = QStyle::visualRect(ld, q->rect(),
       
   484                                               QRect(available - extra, 0, extra, size.height()));
       
   485             int buttonOverlap = q->style()->pixelMetric(QStyle::PM_TabBar_ScrollButtonOverlap, 0, q);
       
   486 
       
   487             if (ld == Qt::LeftToRight) {
       
   488                 leftB->setGeometry(arrows.left(), arrows.top(), extra/2, arrows.height());
       
   489                 rightB->setGeometry(arrows.right() - extra/2 + buttonOverlap, arrows.top(),
       
   490                                     extra/2, arrows.height());
       
   491                 leftB->setArrowType(Qt::LeftArrow);
       
   492                 rightB->setArrowType(Qt::RightArrow);
       
   493             } else {
       
   494                 rightB->setGeometry(arrows.left(), arrows.top(), extra/2, arrows.height());
       
   495                 leftB->setGeometry(arrows.right() - extra/2 + buttonOverlap, arrows.top(),
       
   496                                     extra/2, arrows.height());
       
   497                 rightB->setArrowType(Qt::LeftArrow);
       
   498                 leftB->setArrowType(Qt::RightArrow);
       
   499             }
       
   500         } else {
       
   501             QRect arrows = QRect(0, available - extra, size.width(), extra );
       
   502             leftB->setGeometry(arrows.left(), arrows.top(), arrows.width(), extra/2);
       
   503             leftB->setArrowType(Qt::UpArrow);
       
   504             rightB->setGeometry(arrows.left(), arrows.bottom() - extra/2 + 1,
       
   505                                 arrows.width(), extra/2);
       
   506             rightB->setArrowType(Qt::DownArrow);
       
   507         }
       
   508         leftB->setEnabled(scrollOffset > 0);
       
   509         rightB->setEnabled(last - scrollOffset >= available - extra);
       
   510         leftB->show();
       
   511         rightB->show();
       
   512     } else {
       
   513         rightB->hide();
       
   514         leftB->hide();
       
   515     }
       
   516 
       
   517     layoutWidgets();
       
   518     q->tabLayoutChange();
       
   519 }
       
   520 
       
   521 void QTabBarPrivate::makeVisible(int index)
       
   522 {
       
   523     Q_Q(QTabBar);
       
   524     if (!validIndex(index) || leftB->isHidden())
       
   525         return;
       
   526 
       
   527     const QRect tabRect = tabList.at(index).rect;
       
   528     const int oldScrollOffset = scrollOffset;
       
   529     const bool horiz = !verticalTabs(shape);
       
   530     const int available = (horiz ? q->width() : q->height()) - extraWidth();
       
   531     const int start = horiz ? tabRect.left() : tabRect.top();
       
   532     const int end = horiz ? tabRect.right() : tabRect.bottom();
       
   533     if (start < scrollOffset) // too far left
       
   534         scrollOffset = start - (index ? 8 : 0);
       
   535     else if (end > scrollOffset + available) // too far right
       
   536         scrollOffset = end - available + 1;
       
   537 
       
   538     leftB->setEnabled(scrollOffset > 0);
       
   539     const int last = horiz ? tabList.last().rect.right() : tabList.last().rect.bottom();
       
   540     rightB->setEnabled(last - scrollOffset >= available);
       
   541     if (oldScrollOffset != scrollOffset) {
       
   542         q->update();
       
   543         layoutWidgets();
       
   544     }
       
   545 }
       
   546 
       
   547 void QTabBarPrivate::layoutTab(int index)
       
   548 {
       
   549     Q_Q(QTabBar);
       
   550     Q_ASSERT(index >= 0);
       
   551 
       
   552     Tab &tab = tabList[index];
       
   553     bool vertical = verticalTabs(shape);
       
   554     if (!(tab.leftWidget || tab.rightWidget))
       
   555         return;
       
   556 
       
   557     QStyleOptionTabV3 opt;
       
   558     q->initStyleOption(&opt, index);
       
   559     if (tab.leftWidget) {
       
   560         QRect rect = q->style()->subElementRect(QStyle::SE_TabBarTabLeftButton, &opt, q);
       
   561         QPoint p = rect.topLeft();
       
   562         if ((index == pressedIndex) || paintWithOffsets) {
       
   563             if (vertical)
       
   564                 p.setY(p.y() + tabList[index].dragOffset);
       
   565             else
       
   566                 p.setX(p.x() + tabList[index].dragOffset);
       
   567         }
       
   568         tab.leftWidget->move(p);
       
   569     }
       
   570     if (tab.rightWidget) {
       
   571         QRect rect = q->style()->subElementRect(QStyle::SE_TabBarTabRightButton, &opt, q);
       
   572         QPoint p = rect.topLeft();
       
   573         if ((index == pressedIndex) || paintWithOffsets) {
       
   574             if (vertical)
       
   575                 p.setY(p.y() + tab.dragOffset);
       
   576             else
       
   577                 p.setX(p.x() + tab.dragOffset);
       
   578         }
       
   579         tab.rightWidget->move(p);
       
   580     }
       
   581 }
       
   582 
       
   583 void QTabBarPrivate::layoutWidgets(int index)
       
   584 {
       
   585     Q_Q(QTabBar);
       
   586     int start = 0;
       
   587     int end = q->count();
       
   588     if (index != -1) {
       
   589         start = qMax(index, 0);
       
   590         end = qMin(end, start + 1);
       
   591     }
       
   592     for (int i = start; i < end; ++i) {
       
   593         layoutTab(i);
       
   594     }
       
   595 }
       
   596 
       
   597 void QTabBarPrivate::_q_closeTab()
       
   598 {
       
   599     Q_Q(QTabBar);
       
   600     QObject *object = q->sender();
       
   601     int tabToClose = -1;
       
   602     QTabBar::ButtonPosition closeSide = (QTabBar::ButtonPosition)q->style()->styleHint(QStyle::SH_TabBar_CloseButtonPosition, 0, q);
       
   603     for (int i = 0; i < tabList.count(); ++i) {
       
   604         if (closeSide == QTabBar::LeftSide) {
       
   605             if (tabList.at(i).leftWidget == object) {
       
   606                 tabToClose = i;
       
   607                 break;
       
   608             }
       
   609         } else {
       
   610             if (tabList.at(i).rightWidget == object) {
       
   611                 tabToClose = i;
       
   612                 break;
       
   613             }
       
   614         }
       
   615     }
       
   616     if (tabToClose != -1)
       
   617         emit q->tabCloseRequested(tabToClose);
       
   618 }
       
   619 
       
   620 void QTabBarPrivate::_q_scrollTabs()
       
   621 {
       
   622     Q_Q(QTabBar);
       
   623     const QObject *sender = q->sender();
       
   624     int i = -1;
       
   625     if (!verticalTabs(shape)) {
       
   626         if (sender == leftB) {
       
   627             for (i = tabList.count() - 1; i >= 0; --i) {
       
   628                 if (tabList.at(i).rect.left() - scrollOffset < 0) {
       
   629                     makeVisible(i);
       
   630                     return;
       
   631                 }
       
   632             }
       
   633         } else if (sender == rightB) {
       
   634             int availableWidth = q->width() - extraWidth();
       
   635             for (i = 0; i < tabList.count(); ++i) {
       
   636                 if (tabList.at(i).rect.right() - scrollOffset > availableWidth) {
       
   637                     makeVisible(i);
       
   638                     return;
       
   639                 }
       
   640             }
       
   641         }
       
   642     } else { // vertical
       
   643         if (sender == leftB) {
       
   644             for (i = tabList.count() - 1; i >= 0; --i) {
       
   645                 if (tabList.at(i).rect.top() - scrollOffset < 0) {
       
   646                     makeVisible(i);
       
   647                     return;
       
   648                 }
       
   649             }
       
   650         } else if (sender == rightB) {
       
   651             int available = q->height() - extraWidth();
       
   652             for (i = 0; i < tabList.count(); ++i) {
       
   653                 if (tabList.at(i).rect.bottom() - scrollOffset > available) {
       
   654                     makeVisible(i);
       
   655                     return;
       
   656                 }
       
   657             }
       
   658         }
       
   659     }
       
   660 }
       
   661 
       
   662 void QTabBarPrivate::refresh()
       
   663 {
       
   664     Q_Q(QTabBar);
       
   665 
       
   666     // be safe in case a subclass is also handling move with the tabs
       
   667     if (pressedIndex != -1
       
   668         && movable
       
   669         && QApplication::mouseButtons() == Qt::NoButton) {
       
   670         moveTabFinished(pressedIndex);
       
   671         if (!validIndex(pressedIndex))
       
   672             pressedIndex = -1;
       
   673     }
       
   674 
       
   675     if (!q->isVisible()) {
       
   676         layoutDirty = true;
       
   677     } else {
       
   678         layoutTabs();
       
   679         makeVisible(currentIndex);
       
   680         q->update();
       
   681         q->updateGeometry();
       
   682     }
       
   683 }
       
   684 
       
   685 /*!
       
   686     Creates a new tab bar with the given \a parent.
       
   687 */
       
   688 QTabBar::QTabBar(QWidget* parent)
       
   689     :QWidget(*new QTabBarPrivate, parent, 0)
       
   690 {
       
   691     Q_D(QTabBar);
       
   692     d->init();
       
   693 }
       
   694 
       
   695 
       
   696 /*!
       
   697     Destroys the tab bar.
       
   698 */
       
   699 QTabBar::~QTabBar()
       
   700 {
       
   701 }
       
   702 
       
   703 /*!
       
   704     \property QTabBar::shape
       
   705     \brief the shape of the tabs in the tab bar
       
   706 
       
   707     Possible values for this property are described by the Shape enum.
       
   708 */
       
   709 
       
   710 
       
   711 QTabBar::Shape QTabBar::shape() const
       
   712 {
       
   713     Q_D(const QTabBar);
       
   714     return d->shape;
       
   715 }
       
   716 
       
   717 void QTabBar::setShape(Shape shape)
       
   718 {
       
   719     Q_D(QTabBar);
       
   720     if (d->shape == shape)
       
   721         return;
       
   722     d->shape = shape;
       
   723     d->refresh();
       
   724 }
       
   725 
       
   726 /*!
       
   727     \property QTabBar::drawBase
       
   728     \brief defines whether or not tab bar should draw its base.
       
   729 
       
   730     If true then QTabBar draws a base in relation to the styles overlab.
       
   731     Otherwise only the tabs are drawn.
       
   732 
       
   733     \sa QStyle::pixelMetric() QStyle::PM_TabBarBaseOverlap QStyleOptionTabBarBaseV2
       
   734 */
       
   735 
       
   736 void QTabBar::setDrawBase(bool drawBase)
       
   737 {
       
   738     Q_D(QTabBar);
       
   739     if (d->drawBase == drawBase)
       
   740         return;
       
   741     d->drawBase = drawBase;
       
   742     update();
       
   743 }
       
   744 
       
   745 bool QTabBar::drawBase() const
       
   746 {
       
   747     Q_D(const QTabBar);
       
   748     return d->drawBase;
       
   749 }
       
   750 
       
   751 /*!
       
   752     Adds a new tab with text \a text. Returns the new
       
   753     tab's index.
       
   754 */
       
   755 int QTabBar::addTab(const QString &text)
       
   756 {
       
   757     return insertTab(-1, text);
       
   758 }
       
   759 
       
   760 /*!
       
   761     \overload
       
   762 
       
   763     Adds a new tab with icon \a icon and text \a
       
   764     text. Returns the new tab's index.
       
   765 */
       
   766 int QTabBar::addTab(const QIcon& icon, const QString &text)
       
   767 {
       
   768     return insertTab(-1, icon, text);
       
   769 }
       
   770 
       
   771 /*!
       
   772     Inserts a new tab with text \a text at position \a index. If \a
       
   773     index is out of range, the new tab is appened. Returns the new
       
   774     tab's index.
       
   775 */
       
   776 int QTabBar::insertTab(int index, const QString &text)
       
   777 {
       
   778     return insertTab(index, QIcon(), text);
       
   779 }
       
   780 
       
   781 /*!\overload
       
   782 
       
   783     Inserts a new tab with icon \a icon and text \a text at position
       
   784     \a index. If \a index is out of range, the new tab is
       
   785     appended. Returns the new tab's index.
       
   786 
       
   787     If the QTabBar was empty before this function is called, the inserted tab
       
   788     becomes the current tab.
       
   789 
       
   790     Inserting a new tab at an index less than or equal to the current index
       
   791     will increment the current index, but keep the current tab.
       
   792 */
       
   793 int QTabBar::insertTab(int index, const QIcon& icon, const QString &text)
       
   794 {
       
   795     Q_D(QTabBar);
       
   796     if (!d->validIndex(index)) {
       
   797         index = d->tabList.count();
       
   798         d->tabList.append(QTabBarPrivate::Tab(icon, text));
       
   799     } else {
       
   800         d->tabList.insert(index, QTabBarPrivate::Tab(icon, text));
       
   801     }
       
   802 #ifndef QT_NO_SHORTCUT
       
   803     d->tabList[index].shortcutId = grabShortcut(QKeySequence::mnemonic(text));
       
   804 #endif
       
   805     d->refresh();
       
   806     if (d->tabList.count() == 1)
       
   807         setCurrentIndex(index);
       
   808     else if (index <= d->currentIndex)
       
   809         ++d->currentIndex;
       
   810 
       
   811     if (d->closeButtonOnTabs) {
       
   812         QStyleOptionTabV3 opt;
       
   813         initStyleOption(&opt, index);
       
   814         ButtonPosition closeSide = (ButtonPosition)style()->styleHint(QStyle::SH_TabBar_CloseButtonPosition, 0, this);
       
   815         QAbstractButton *closeButton = new CloseButton(this);
       
   816         connect(closeButton, SIGNAL(clicked()), this, SLOT(_q_closeTab()));
       
   817         setTabButton(index, closeSide, closeButton);
       
   818     }
       
   819 
       
   820     for (int i = 0; i < d->tabList.count(); ++i) {
       
   821         if (d->tabList[i].lastTab >= index)
       
   822             ++d->tabList[i].lastTab;
       
   823     }
       
   824 
       
   825     tabInserted(index);
       
   826     return index;
       
   827 }
       
   828 
       
   829 
       
   830 /*!
       
   831     Removes the tab at position \a index.
       
   832 
       
   833     \sa SelectionBehavior
       
   834  */
       
   835 void QTabBar::removeTab(int index)
       
   836 {
       
   837     Q_D(QTabBar);
       
   838     if (d->validIndex(index)) {
       
   839 #ifndef QT_NO_SHORTCUT
       
   840         releaseShortcut(d->tabList.at(index).shortcutId);
       
   841 #endif
       
   842         if (d->tabList[index].leftWidget) {
       
   843             d->tabList[index].leftWidget->hide();
       
   844             d->tabList[index].leftWidget->deleteLater();
       
   845             d->tabList[index].leftWidget = 0;
       
   846         }
       
   847         if (d->tabList[index].rightWidget) {
       
   848             d->tabList[index].rightWidget->hide();
       
   849             d->tabList[index].rightWidget->deleteLater();
       
   850             d->tabList[index].rightWidget = 0;
       
   851         }
       
   852 
       
   853         int newIndex = d->tabList[index].lastTab;
       
   854         d->tabList.removeAt(index);
       
   855         for (int i = 0; i < d->tabList.count(); ++i) {
       
   856             if (d->tabList[i].lastTab == index)
       
   857                 d->tabList[i].lastTab = -1;
       
   858             if (d->tabList[i].lastTab > index)
       
   859                 --d->tabList[i].lastTab;
       
   860         }
       
   861         if (index == d->currentIndex) {
       
   862             // The current tab is going away, in order to make sure
       
   863             // we emit that "current has changed", we need to reset this
       
   864             // around.
       
   865             d->currentIndex = -1;
       
   866             if (d->tabList.size() > 0) {
       
   867                 switch(d->selectionBehaviorOnRemove) {
       
   868                 case SelectPreviousTab:
       
   869                     if (newIndex > index)
       
   870                         newIndex--;
       
   871                     if (d->validIndex(newIndex))
       
   872                         break;
       
   873                     // else fallthrough
       
   874                 case SelectRightTab:
       
   875                     newIndex = index;
       
   876                     if (newIndex >= d->tabList.size())
       
   877                         newIndex = d->tabList.size() - 1;
       
   878                     break;
       
   879                 case SelectLeftTab:
       
   880                     newIndex = index - 1;
       
   881                     if (newIndex < 0)
       
   882                         newIndex = 0;
       
   883                     break;
       
   884                 default:
       
   885                     break;
       
   886                 }
       
   887 
       
   888                 if (d->validIndex(newIndex)) {
       
   889                     // don't loose newIndex's old through setCurrentIndex
       
   890                     int bump = d->tabList[newIndex].lastTab;
       
   891                     setCurrentIndex(newIndex);
       
   892                     d->tabList[newIndex].lastTab = bump;
       
   893                 }
       
   894             } else {
       
   895                 emit currentChanged(-1);
       
   896             }
       
   897         } else if (index < d->currentIndex) {
       
   898             setCurrentIndex(d->currentIndex - 1);
       
   899         }
       
   900         d->refresh();
       
   901         tabRemoved(index);
       
   902     }
       
   903 }
       
   904 
       
   905 
       
   906 /*!
       
   907     Returns true if the tab at position \a index is enabled; otherwise
       
   908     returns false.
       
   909 */
       
   910 bool QTabBar::isTabEnabled(int index) const
       
   911 {
       
   912     Q_D(const QTabBar);
       
   913     if (const QTabBarPrivate::Tab *tab = d->at(index))
       
   914         return tab->enabled;
       
   915     return false;
       
   916 }
       
   917 
       
   918 /*!
       
   919     If \a enabled is true then the tab at position \a index is
       
   920     enabled; otherwise the item at position \a index is disabled.
       
   921 */
       
   922 void QTabBar::setTabEnabled(int index, bool enabled)
       
   923 {
       
   924     Q_D(QTabBar);
       
   925     if (QTabBarPrivate::Tab *tab = d->at(index)) {
       
   926         tab->enabled = enabled;
       
   927 #ifndef QT_NO_SHORTCUT
       
   928         setShortcutEnabled(tab->shortcutId, enabled);
       
   929 #endif
       
   930         update();
       
   931         if (!enabled && index == d->currentIndex)
       
   932             setCurrentIndex(d->validIndex(index+1)?index+1:0);
       
   933         else if (enabled && !d->validIndex(d->currentIndex))
       
   934             setCurrentIndex(index);
       
   935     }
       
   936 }
       
   937 
       
   938 
       
   939 /*!
       
   940     Returns the text of the tab at position \a index, or an empty
       
   941     string if \a index is out of range.
       
   942 */
       
   943 QString QTabBar::tabText(int index) const
       
   944 {
       
   945     Q_D(const QTabBar);
       
   946     if (const QTabBarPrivate::Tab *tab = d->at(index))
       
   947         return tab->text;
       
   948     return QString();
       
   949 }
       
   950 
       
   951 /*!
       
   952     Sets the text of the tab at position \a index to \a text.
       
   953 */
       
   954 void QTabBar::setTabText(int index, const QString &text)
       
   955 {
       
   956     Q_D(QTabBar);
       
   957     if (QTabBarPrivate::Tab *tab = d->at(index)) {
       
   958         tab->text = text;
       
   959 #ifndef QT_NO_SHORTCUT
       
   960         releaseShortcut(tab->shortcutId);
       
   961         tab->shortcutId = grabShortcut(QKeySequence::mnemonic(text));
       
   962         setShortcutEnabled(tab->shortcutId, tab->enabled);
       
   963 #endif
       
   964         d->refresh();
       
   965     }
       
   966 }
       
   967 
       
   968 /*!
       
   969     Returns the text color of the tab with the given \a index, or a invalid
       
   970     color if \a index is out of range.
       
   971 
       
   972     \sa setTabTextColor()
       
   973 */
       
   974 QColor QTabBar::tabTextColor(int index) const
       
   975 {
       
   976     Q_D(const QTabBar);
       
   977     if (const QTabBarPrivate::Tab *tab = d->at(index))
       
   978         return tab->textColor;
       
   979     return QColor();
       
   980 }
       
   981 
       
   982 /*!
       
   983     Sets the color of the text in the tab with the given \a index to the specified \a color.
       
   984 
       
   985     If an invalid color is specified, the tab will use the QTabBar foreground role instead.
       
   986 
       
   987     \sa tabTextColor()
       
   988 */
       
   989 void QTabBar::setTabTextColor(int index, const QColor &color)
       
   990 {
       
   991     Q_D(QTabBar);
       
   992     if (QTabBarPrivate::Tab *tab = d->at(index)) {
       
   993         tab->textColor = color;
       
   994         update(tabRect(index));
       
   995     }
       
   996 }
       
   997 
       
   998 /*!
       
   999     Returns the icon of the tab at position \a index, or a null icon
       
  1000     if \a index is out of range.
       
  1001 */
       
  1002 QIcon QTabBar::tabIcon(int index) const
       
  1003 {
       
  1004     Q_D(const QTabBar);
       
  1005     if (const QTabBarPrivate::Tab *tab = d->at(index))
       
  1006         return tab->icon;
       
  1007     return QIcon();
       
  1008 }
       
  1009 
       
  1010 /*!
       
  1011     Sets the icon of the tab at position \a index to \a icon.
       
  1012 */
       
  1013 void QTabBar::setTabIcon(int index, const QIcon & icon)
       
  1014 {
       
  1015     Q_D(QTabBar);
       
  1016     if (QTabBarPrivate::Tab *tab = d->at(index)) {
       
  1017         bool simpleIconChange = (!icon.isNull() && !tab->icon.isNull());
       
  1018         tab->icon = icon;
       
  1019         if (simpleIconChange)
       
  1020             update(tabRect(index));
       
  1021         else
       
  1022             d->refresh();
       
  1023     }
       
  1024 }
       
  1025 
       
  1026 #ifndef QT_NO_TOOLTIP
       
  1027 /*!
       
  1028     Sets the tool tip of the tab at position \a index to \a tip.
       
  1029 */
       
  1030 void QTabBar::setTabToolTip(int index, const QString & tip)
       
  1031 {
       
  1032     Q_D(QTabBar);
       
  1033     if (QTabBarPrivate::Tab *tab = d->at(index))
       
  1034         tab->toolTip = tip;
       
  1035 }
       
  1036 
       
  1037 /*!
       
  1038     Returns the tool tip of the tab at position \a index, or an empty
       
  1039     string if \a index is out of range.
       
  1040 */
       
  1041 QString QTabBar::tabToolTip(int index) const
       
  1042 {
       
  1043     Q_D(const QTabBar);
       
  1044     if (const QTabBarPrivate::Tab *tab = d->at(index))
       
  1045         return tab->toolTip;
       
  1046     return QString();
       
  1047 }
       
  1048 #endif // QT_NO_TOOLTIP
       
  1049 
       
  1050 #ifndef QT_NO_WHATSTHIS
       
  1051 /*!
       
  1052     \since 4.1
       
  1053 
       
  1054     Sets the What's This help text of the tab at position \a index
       
  1055     to \a text.
       
  1056 */
       
  1057 void QTabBar::setTabWhatsThis(int index, const QString &text)
       
  1058 {
       
  1059     Q_D(QTabBar);
       
  1060     if (QTabBarPrivate::Tab *tab = d->at(index))
       
  1061         tab->whatsThis = text;
       
  1062 }
       
  1063 
       
  1064 /*!
       
  1065     \since 4.1
       
  1066 
       
  1067     Returns the What's This help text of the tab at position \a index,
       
  1068     or an empty string if \a index is out of range.
       
  1069 */
       
  1070 QString QTabBar::tabWhatsThis(int index) const
       
  1071 {
       
  1072     Q_D(const QTabBar);
       
  1073     if (const QTabBarPrivate::Tab *tab = d->at(index))
       
  1074         return tab->whatsThis;
       
  1075     return QString();
       
  1076 }
       
  1077 
       
  1078 #endif // QT_NO_WHATSTHIS
       
  1079 
       
  1080 /*!
       
  1081     Sets the data of the tab at position \a index to \a data.
       
  1082 */
       
  1083 void QTabBar::setTabData(int index, const QVariant & data)
       
  1084 {
       
  1085     Q_D(QTabBar);
       
  1086     if (QTabBarPrivate::Tab *tab = d->at(index))
       
  1087         tab->data = data;
       
  1088 }
       
  1089 
       
  1090 /*!
       
  1091     Returns the data of the tab at position \a index, or a null
       
  1092     variant if \a index is out of range.
       
  1093 */
       
  1094 QVariant QTabBar::tabData(int index) const
       
  1095 {
       
  1096     Q_D(const QTabBar);
       
  1097     if (const QTabBarPrivate::Tab *tab = d->at(index))
       
  1098         return tab->data;
       
  1099     return QVariant();
       
  1100 }
       
  1101 
       
  1102 /*!
       
  1103     Returns the visual rectangle of the tab at position \a
       
  1104     index, or a null rectangle if \a index is out of range.
       
  1105 */
       
  1106 QRect QTabBar::tabRect(int index) const
       
  1107 {
       
  1108     Q_D(const QTabBar);
       
  1109     if (const QTabBarPrivate::Tab *tab = d->at(index)) {
       
  1110         if (d->layoutDirty)
       
  1111             const_cast<QTabBarPrivate*>(d)->layoutTabs();
       
  1112         QRect r = tab->rect;
       
  1113         if (verticalTabs(d->shape))
       
  1114             r.translate(0, -d->scrollOffset);
       
  1115         else
       
  1116             r.translate(-d->scrollOffset, 0);
       
  1117         if (!verticalTabs(d->shape))
       
  1118             r = QStyle::visualRect(layoutDirection(), rect(), r);
       
  1119         return r;
       
  1120     }
       
  1121     return QRect();
       
  1122 }
       
  1123 
       
  1124 /*!
       
  1125     \since 4.3
       
  1126     Returns the index of the tab that covers \a position or -1 if no
       
  1127     tab covers \a position;
       
  1128 */
       
  1129 
       
  1130 int QTabBar::tabAt(const QPoint &position) const
       
  1131 {
       
  1132     Q_D(const QTabBar);
       
  1133     if (d->validIndex(d->currentIndex)
       
  1134         && tabRect(d->currentIndex).contains(position)) {
       
  1135         return d->currentIndex;
       
  1136     }
       
  1137     const int max = d->tabList.size();
       
  1138     for (int i = 0; i < max; ++i) {
       
  1139         if (tabRect(i).contains(position)) {
       
  1140             return i;
       
  1141         }
       
  1142     }
       
  1143     return -1;
       
  1144 }
       
  1145 
       
  1146 /*!
       
  1147     \property QTabBar::currentIndex
       
  1148     \brief the index of the tab bar's visible tab
       
  1149 
       
  1150     The current index is -1 if there is no current tab.
       
  1151 */
       
  1152 
       
  1153 int QTabBar::currentIndex() const
       
  1154 {
       
  1155     Q_D(const QTabBar);
       
  1156     if (d->validIndex(d->currentIndex))
       
  1157         return d->currentIndex;
       
  1158     return -1;
       
  1159 }
       
  1160 
       
  1161 
       
  1162 void QTabBar::setCurrentIndex(int index)
       
  1163 {
       
  1164     Q_D(QTabBar);
       
  1165     if (d->dragInProgress && d->pressedIndex != -1)
       
  1166         return;
       
  1167 
       
  1168     int oldIndex = d->currentIndex;
       
  1169     if (d->validIndex(index) && d->currentIndex != index) {
       
  1170         d->currentIndex = index;
       
  1171         update();
       
  1172         d->makeVisible(index);
       
  1173         d->tabList[index].lastTab = oldIndex;
       
  1174         d->layoutWidgets(oldIndex);
       
  1175         d->layoutWidgets(index);
       
  1176 #ifdef QT3_SUPPORT
       
  1177         emit selected(index);
       
  1178 #endif
       
  1179         emit currentChanged(index);
       
  1180     }
       
  1181 }
       
  1182 
       
  1183 /*!
       
  1184     \property QTabBar::iconSize
       
  1185     \brief The size for icons in the tab bar
       
  1186     \since 4.1
       
  1187 
       
  1188     The default value is style-dependent. \c iconSize is a maximum
       
  1189     size; icons that are smaller are not scaled up.
       
  1190 
       
  1191     \sa QTabWidget::iconSize
       
  1192 */
       
  1193 QSize QTabBar::iconSize() const
       
  1194 {
       
  1195     Q_D(const QTabBar);
       
  1196     if (d->iconSize.isValid())
       
  1197         return d->iconSize;
       
  1198     int iconExtent = style()->pixelMetric(QStyle::PM_TabBarIconSize, 0, this);
       
  1199     return QSize(iconExtent, iconExtent);
       
  1200 
       
  1201 }
       
  1202 
       
  1203 void QTabBar::setIconSize(const QSize &size)
       
  1204 {
       
  1205     Q_D(QTabBar);
       
  1206     d->iconSize = size;
       
  1207     d->layoutDirty = true;
       
  1208     update();
       
  1209     updateGeometry();
       
  1210 }
       
  1211 
       
  1212 /*!
       
  1213     \property QTabBar::count
       
  1214     \brief the number of tabs in the tab bar
       
  1215 */
       
  1216 
       
  1217 int QTabBar::count() const
       
  1218 {
       
  1219     Q_D(const QTabBar);
       
  1220     return d->tabList.count();
       
  1221 }
       
  1222 
       
  1223 
       
  1224 /*!\reimp
       
  1225  */
       
  1226 QSize QTabBar::sizeHint() const
       
  1227 {
       
  1228     Q_D(const QTabBar);
       
  1229     if (d->layoutDirty)
       
  1230         const_cast<QTabBarPrivate*>(d)->layoutTabs();
       
  1231     QRect r;
       
  1232     for (int i = 0; i < d->tabList.count(); ++i)
       
  1233         r = r.united(d->tabList.at(i).maxRect);
       
  1234     QSize sz = QApplication::globalStrut();
       
  1235     return r.size().expandedTo(sz);
       
  1236 }
       
  1237 
       
  1238 /*!\reimp
       
  1239  */
       
  1240 QSize QTabBar::minimumSizeHint() const
       
  1241 {
       
  1242     Q_D(const QTabBar);
       
  1243     if (!d->useScrollButtons) {
       
  1244         QRect r;
       
  1245         for (int i = 0; i < d->tabList.count(); ++i)
       
  1246             r = r.united(d->tabList.at(i).minRect);
       
  1247         return r.size().expandedTo(QApplication::globalStrut());
       
  1248     }
       
  1249     if (verticalTabs(d->shape))
       
  1250         return QSize(sizeHint().width(), d->rightB->sizeHint().height() * 2 + 75);
       
  1251     else
       
  1252         return QSize(d->rightB->sizeHint().width() * 2 + 75, sizeHint().height());
       
  1253 }
       
  1254 
       
  1255 static QString computeElidedText(Qt::TextElideMode mode, const QString &text)
       
  1256 {
       
  1257     if (text.length() <= 7)
       
  1258         return text;
       
  1259 
       
  1260     static const QLatin1String Ellipses("...");
       
  1261     QString ret;
       
  1262     switch (mode) {
       
  1263     case Qt::ElideRight:
       
  1264         ret = text.left(4) + Ellipses;
       
  1265         break;
       
  1266     case Qt::ElideMiddle:
       
  1267         ret = text.left(2) + Ellipses + text.right(2);
       
  1268         break;
       
  1269     case Qt::ElideLeft:
       
  1270         ret = Ellipses + text.right(4);
       
  1271         break;
       
  1272     case Qt::ElideNone:
       
  1273         ret = text;
       
  1274         break;
       
  1275     }
       
  1276     return ret;
       
  1277 }
       
  1278 
       
  1279 QSize QTabBarPrivate::minimumTabSizeHint(int index)
       
  1280 {
       
  1281     Q_Q(QTabBar);
       
  1282     // ### Qt 5: make this a protected virtual function in QTabBar
       
  1283     Tab &tab = tabList[index];
       
  1284     QString oldText = tab.text;
       
  1285     tab.text = computeElidedText(elideMode, oldText);
       
  1286     QSize size = q->tabSizeHint(index);
       
  1287     tab.text = oldText;
       
  1288     return size;
       
  1289 }
       
  1290 
       
  1291 /*!
       
  1292     Returns the size hint for the tab at position \a index.
       
  1293 */
       
  1294 QSize QTabBar::tabSizeHint(int index) const
       
  1295 {
       
  1296     //Note: this must match with the computations in QCommonStylePrivate::tabLayout
       
  1297     Q_D(const QTabBar);
       
  1298     if (const QTabBarPrivate::Tab *tab = d->at(index)) {
       
  1299         QStyleOptionTabV3 opt;
       
  1300         initStyleOption(&opt, index);
       
  1301         opt.text = d->tabList.at(index).text;
       
  1302         QSize iconSize = tab->icon.isNull() ? QSize(0, 0) : opt.iconSize;
       
  1303         int hframe = style()->pixelMetric(QStyle::PM_TabBarTabHSpace, &opt, this);
       
  1304         int vframe = style()->pixelMetric(QStyle::PM_TabBarTabVSpace, &opt, this);
       
  1305         const QFontMetrics fm = fontMetrics();
       
  1306 
       
  1307         int maxWidgetHeight = qMax(opt.leftButtonSize.height(), opt.rightButtonSize.height());
       
  1308         int maxWidgetWidth = qMax(opt.leftButtonSize.width(), opt.rightButtonSize.width());
       
  1309 
       
  1310         int widgetWidth = 0;
       
  1311         int widgetHeight = 0;
       
  1312         int padding = 0;
       
  1313         if (!opt.leftButtonSize.isEmpty()) {
       
  1314             padding += 4;
       
  1315             widgetWidth += opt.leftButtonSize.width();
       
  1316             widgetHeight += opt.leftButtonSize.height();
       
  1317         }
       
  1318         if (!opt.rightButtonSize.isEmpty()) {
       
  1319             padding += 4;
       
  1320             widgetWidth += opt.rightButtonSize.width();
       
  1321             widgetHeight += opt.rightButtonSize.height();
       
  1322         }
       
  1323         if (!opt.icon.isNull())
       
  1324             padding += 4;
       
  1325 
       
  1326         QSize csz;
       
  1327         if (verticalTabs(d->shape)) {
       
  1328             csz = QSize( qMax(maxWidgetWidth, qMax(fm.height(), iconSize.height())) + vframe,
       
  1329                     fm.size(Qt::TextShowMnemonic, tab->text).width() + iconSize.width() + hframe + widgetHeight + padding);
       
  1330         } else {
       
  1331             csz = QSize(fm.size(Qt::TextShowMnemonic, tab->text).width() + iconSize.width() + hframe
       
  1332                   + widgetWidth + padding,
       
  1333                   qMax(maxWidgetHeight, qMax(fm.height(), iconSize.height())) + vframe);
       
  1334         }
       
  1335 
       
  1336         QSize retSize = style()->sizeFromContents(QStyle::CT_TabBarTab, &opt, csz, this);
       
  1337         return retSize;
       
  1338     }
       
  1339     return QSize();
       
  1340 }
       
  1341 
       
  1342 /*!
       
  1343   This virtual handler is called after a new tab was added or
       
  1344   inserted at position \a index.
       
  1345 
       
  1346   \sa tabRemoved()
       
  1347  */
       
  1348 void QTabBar::tabInserted(int index)
       
  1349 {
       
  1350     Q_UNUSED(index)
       
  1351 }
       
  1352 
       
  1353 /*!
       
  1354   This virtual handler is called after a tab was removed from
       
  1355   position \a index.
       
  1356 
       
  1357   \sa tabInserted()
       
  1358  */
       
  1359 void QTabBar::tabRemoved(int index)
       
  1360 {
       
  1361     Q_UNUSED(index)
       
  1362 }
       
  1363 
       
  1364 /*!
       
  1365   This virtual handler is called whenever the tab layout changes.
       
  1366 
       
  1367   \sa tabRect()
       
  1368  */
       
  1369 void QTabBar::tabLayoutChange()
       
  1370 {
       
  1371 }
       
  1372 
       
  1373 
       
  1374 /*!\reimp
       
  1375  */
       
  1376 void QTabBar::showEvent(QShowEvent *)
       
  1377 {
       
  1378     Q_D(QTabBar);
       
  1379     if (d->layoutDirty)
       
  1380         d->refresh();
       
  1381     if (!d->validIndex(d->currentIndex))
       
  1382         setCurrentIndex(0);
       
  1383     d->updateMacBorderMetrics();
       
  1384 }
       
  1385 
       
  1386 /*!\reimp
       
  1387  */
       
  1388 void QTabBar::hideEvent(QHideEvent *)
       
  1389 {
       
  1390     Q_D(QTabBar);
       
  1391     d->updateMacBorderMetrics();
       
  1392 }
       
  1393 
       
  1394 /*!\reimp
       
  1395  */
       
  1396 bool QTabBar::event(QEvent *event)
       
  1397 {
       
  1398     Q_D(QTabBar);
       
  1399     if (event->type() == QEvent::HoverMove
       
  1400         || event->type() == QEvent::HoverEnter) {
       
  1401         QHoverEvent *he = static_cast<QHoverEvent *>(event);
       
  1402         if (!d->hoverRect.contains(he->pos())) {
       
  1403             QRect oldHoverRect = d->hoverRect;
       
  1404             for (int i = 0; i < d->tabList.count(); ++i) {
       
  1405                 QRect area = tabRect(i);
       
  1406                 if (area.contains(he->pos())) {
       
  1407                     d->hoverRect = area;
       
  1408                     break;
       
  1409                 }
       
  1410             }
       
  1411             if (he->oldPos() != QPoint(-1, -1))
       
  1412                 update(oldHoverRect);
       
  1413             update(d->hoverRect);
       
  1414         }
       
  1415         return true;
       
  1416     } else if (event->type() == QEvent::HoverLeave ) {
       
  1417         QRect oldHoverRect = d->hoverRect;
       
  1418         d->hoverRect = QRect();
       
  1419         update(oldHoverRect);
       
  1420         return true;
       
  1421 #ifndef QT_NO_TOOLTIP
       
  1422     } else if (event->type() == QEvent::ToolTip) {
       
  1423         if (const QTabBarPrivate::Tab *tab = d->at(tabAt(static_cast<QHelpEvent*>(event)->pos()))) {
       
  1424             if (!tab->toolTip.isEmpty()) {
       
  1425                 QToolTip::showText(static_cast<QHelpEvent*>(event)->globalPos(), tab->toolTip, this);
       
  1426                 return true;
       
  1427             }
       
  1428         }
       
  1429 #endif // QT_NO_TOOLTIP
       
  1430 #ifndef QT_NO_WHATSTHIS
       
  1431     } else if (event->type() == QEvent::QueryWhatsThis) {
       
  1432         const QTabBarPrivate::Tab *tab = d->at(d->indexAtPos(static_cast<QHelpEvent*>(event)->pos()));
       
  1433         if (!tab || tab->whatsThis.isEmpty())
       
  1434             event->ignore();
       
  1435         return true;
       
  1436     } else if (event->type() == QEvent::WhatsThis) {
       
  1437         if (const QTabBarPrivate::Tab *tab = d->at(d->indexAtPos(static_cast<QHelpEvent*>(event)->pos()))) {
       
  1438             if (!tab->whatsThis.isEmpty()) {
       
  1439                 QWhatsThis::showText(static_cast<QHelpEvent*>(event)->globalPos(),
       
  1440                                      tab->whatsThis, this);
       
  1441                 return true;
       
  1442             }
       
  1443         }
       
  1444 #endif // QT_NO_WHATSTHIS
       
  1445 #ifndef QT_NO_SHORTCUT
       
  1446     } else if (event->type() == QEvent::Shortcut) {
       
  1447         QShortcutEvent *se = static_cast<QShortcutEvent *>(event);
       
  1448         for (int i = 0; i < d->tabList.count(); ++i) {
       
  1449             const QTabBarPrivate::Tab *tab = &d->tabList.at(i);
       
  1450             if (tab->shortcutId == se->shortcutId()) {
       
  1451                 setCurrentIndex(i);
       
  1452                 return true;
       
  1453             }
       
  1454         }
       
  1455 #endif
       
  1456     }
       
  1457     return QWidget::event(event);
       
  1458 }
       
  1459 
       
  1460 /*!\reimp
       
  1461  */
       
  1462 void QTabBar::resizeEvent(QResizeEvent *)
       
  1463 {
       
  1464     Q_D(QTabBar);
       
  1465     if (d->layoutDirty)
       
  1466         updateGeometry();
       
  1467     d->layoutTabs();
       
  1468 
       
  1469     d->makeVisible(d->currentIndex);
       
  1470 }
       
  1471 
       
  1472 /*!\reimp
       
  1473  */
       
  1474 void QTabBar::paintEvent(QPaintEvent *)
       
  1475 {
       
  1476     Q_D(QTabBar);
       
  1477 
       
  1478     QStyleOptionTabBarBaseV2 optTabBase;
       
  1479     QTabBarPrivate::initStyleBaseOption(&optTabBase, this, size());
       
  1480 
       
  1481     QStylePainter p(this);
       
  1482     int selected = -1;
       
  1483     int cut = -1;
       
  1484     bool rtl = optTabBase.direction == Qt::RightToLeft;
       
  1485     bool vertical = verticalTabs(d->shape);
       
  1486     QStyleOptionTab cutTab;
       
  1487     selected = d->currentIndex;
       
  1488     if (d->dragInProgress)
       
  1489         selected = d->pressedIndex;
       
  1490 
       
  1491     for (int i = 0; i < d->tabList.count(); ++i)
       
  1492          optTabBase.tabBarRect |= tabRect(i);
       
  1493 
       
  1494     optTabBase.selectedTabRect = tabRect(selected);
       
  1495 
       
  1496     if (d->drawBase)
       
  1497         p.drawPrimitive(QStyle::PE_FrameTabBarBase, optTabBase);
       
  1498 
       
  1499     for (int i = 0; i < d->tabList.count(); ++i) {
       
  1500         QStyleOptionTabV3 tab;
       
  1501         initStyleOption(&tab, i);
       
  1502         if (d->paintWithOffsets && d->tabList[i].dragOffset != 0) {
       
  1503             if (vertical) {
       
  1504                 tab.rect.moveTop(tab.rect.y() + d->tabList[i].dragOffset);
       
  1505             } else {
       
  1506                 tab.rect.moveLeft(tab.rect.x() + d->tabList[i].dragOffset);
       
  1507             }
       
  1508         }
       
  1509         if (!(tab.state & QStyle::State_Enabled)) {
       
  1510             tab.palette.setCurrentColorGroup(QPalette::Disabled);
       
  1511         }
       
  1512         // If this tab is partially obscured, make a note of it so that we can pass the information
       
  1513         // along when we draw the tear.
       
  1514         if (((!vertical && (!rtl && tab.rect.left() < 0)) || (rtl && tab.rect.right() > width()))
       
  1515             || (vertical && tab.rect.top() < 0)) {
       
  1516             cut = i;
       
  1517             cutTab = tab;
       
  1518         }
       
  1519         // Don't bother drawing a tab if the entire tab is outside of the visible tab bar.
       
  1520         if ((!vertical && (tab.rect.right() < 0 || tab.rect.left() > width()))
       
  1521             || (vertical && (tab.rect.bottom() < 0 || tab.rect.top() > height())))
       
  1522             continue;
       
  1523 
       
  1524         optTabBase.tabBarRect |= tab.rect;
       
  1525         if (i == selected)
       
  1526             continue;
       
  1527 
       
  1528         p.drawControl(QStyle::CE_TabBarTab, tab);
       
  1529     }
       
  1530 
       
  1531     // Draw the selected tab last to get it "on top"
       
  1532     if (selected >= 0) {
       
  1533         QStyleOptionTabV3 tab;
       
  1534         initStyleOption(&tab, selected);
       
  1535         if (d->paintWithOffsets && d->tabList[selected].dragOffset != 0) {
       
  1536             if (vertical)
       
  1537                 tab.rect.moveTop(tab.rect.y() + d->tabList[selected].dragOffset);
       
  1538             else
       
  1539                 tab.rect.moveLeft(tab.rect.x() + d->tabList[selected].dragOffset);
       
  1540         }
       
  1541         if (!d->dragInProgress)
       
  1542             p.drawControl(QStyle::CE_TabBarTab, tab);
       
  1543         else {
       
  1544             int taboverlap = style()->pixelMetric(QStyle::PM_TabBarTabOverlap, 0, this);
       
  1545             d->movingTab->setGeometry(tab.rect.adjusted(-taboverlap, 0, taboverlap, 0));
       
  1546         }
       
  1547     }
       
  1548 
       
  1549     // Only draw the tear indicator if necessary. Most of the time we don't need too.
       
  1550     if (d->leftB->isVisible() && cut >= 0) {
       
  1551         cutTab.rect = rect();
       
  1552         cutTab.rect = style()->subElementRect(QStyle::SE_TabBarTearIndicator, &cutTab, this);
       
  1553         p.drawPrimitive(QStyle::PE_IndicatorTabTear, cutTab);
       
  1554     }
       
  1555 }
       
  1556 
       
  1557 /*
       
  1558     Given that index at position from moved to position to where return where index goes.
       
  1559  */
       
  1560 int QTabBarPrivate::calculateNewPosition(int from, int to, int index) const
       
  1561 {
       
  1562     if (index == from)
       
  1563         return to;
       
  1564 
       
  1565     int start = qMin(from, to);
       
  1566     int end = qMax(from, to);
       
  1567     if (index >= start && index <= end)
       
  1568         index += (from < to) ? -1 : 1;
       
  1569     return index;
       
  1570 }
       
  1571 
       
  1572 /*!
       
  1573     Moves the item at index position \a from to index position \a to.
       
  1574     \since 4.5
       
  1575 
       
  1576     \sa tabMoved(), tabLayoutChange()
       
  1577  */
       
  1578 void QTabBar::moveTab(int from, int to)
       
  1579 {
       
  1580     Q_D(QTabBar);
       
  1581     if (from == to
       
  1582         || !d->validIndex(from)
       
  1583         || !d->validIndex(to))
       
  1584         return;
       
  1585 
       
  1586     bool vertical = verticalTabs(d->shape);
       
  1587     int oldPressedPosition = 0;
       
  1588     if (d->pressedIndex != -1) {
       
  1589         // Record the position of the pressed tab before reordering the tabs.
       
  1590         oldPressedPosition = vertical ? d->tabList[d->pressedIndex].rect.y()
       
  1591                              : d->tabList[d->pressedIndex].rect.x();
       
  1592     }
       
  1593 
       
  1594     // Update the locations of the tabs first
       
  1595     int start = qMin(from, to);
       
  1596     int end = qMax(from, to);
       
  1597     int width = vertical ? d->tabList[from].rect.height() : d->tabList[from].rect.width();
       
  1598     if (from < to)
       
  1599         width *= -1;
       
  1600     bool rtl = isRightToLeft();
       
  1601     for (int i = start; i <= end; ++i) {
       
  1602         if (i == from)
       
  1603             continue;
       
  1604         if (vertical)
       
  1605             d->tabList[i].rect.moveTop(d->tabList[i].rect.y() + width);
       
  1606         else
       
  1607             d->tabList[i].rect.moveLeft(d->tabList[i].rect.x() + width);
       
  1608         int direction = -1;
       
  1609         if (rtl && !vertical)
       
  1610             direction *= -1;
       
  1611         if (d->tabList[i].dragOffset != 0)
       
  1612             d->tabList[i].dragOffset += (direction * width);
       
  1613     }
       
  1614 
       
  1615     if (vertical) {
       
  1616         if (from < to)
       
  1617             d->tabList[from].rect.moveTop(d->tabList[to].rect.bottom() + 1);
       
  1618         else
       
  1619             d->tabList[from].rect.moveTop(d->tabList[to].rect.top() - width);
       
  1620     } else {
       
  1621         if (from < to)
       
  1622             d->tabList[from].rect.moveLeft(d->tabList[to].rect.right() + 1);
       
  1623         else
       
  1624             d->tabList[from].rect.moveLeft(d->tabList[to].rect.left() - width);
       
  1625     }
       
  1626 
       
  1627     // Move the actual data structures
       
  1628     d->tabList.move(from, to);
       
  1629 
       
  1630     // update lastTab locations
       
  1631     for (int i = 0; i < d->tabList.count(); ++i)
       
  1632         d->tabList[i].lastTab = d->calculateNewPosition(from, to, d->tabList[i].lastTab);
       
  1633 
       
  1634     // update external variables
       
  1635     d->currentIndex = d->calculateNewPosition(from, to, d->currentIndex);
       
  1636 
       
  1637     // If we are in the middle of a drag update the dragStartPosition
       
  1638     if (d->pressedIndex != -1) {
       
  1639         d->pressedIndex = d->calculateNewPosition(from, to, d->pressedIndex);
       
  1640         int newPressedPosition = vertical ? d->tabList[d->pressedIndex].rect.top() : d->tabList[d->pressedIndex].rect.left();
       
  1641         int diff = oldPressedPosition - newPressedPosition;
       
  1642         if (isRightToLeft() && !vertical)
       
  1643             diff *= -1;
       
  1644         if (vertical)
       
  1645             d->dragStartPosition.setY(d->dragStartPosition.y() - diff);
       
  1646         else
       
  1647             d->dragStartPosition.setX(d->dragStartPosition.x() - diff);
       
  1648     }
       
  1649 
       
  1650     d->layoutWidgets(start);
       
  1651     update();
       
  1652     emit tabMoved(from, to);
       
  1653     emit tabLayoutChange();
       
  1654 }
       
  1655 
       
  1656 void QTabBarPrivate::slide(int from, int to)
       
  1657 {
       
  1658     Q_Q(QTabBar);
       
  1659     if (from == to
       
  1660             || !validIndex(from)
       
  1661             || !validIndex(to))
       
  1662         return;
       
  1663     bool vertical = verticalTabs(shape);
       
  1664     int preLocation = vertical ? q->tabRect(from).y() : q->tabRect(from).x();
       
  1665     q->setUpdatesEnabled(false);
       
  1666     q->moveTab(from, to);
       
  1667     q->setUpdatesEnabled(true);
       
  1668     int postLocation = vertical ? q->tabRect(to).y() : q->tabRect(to).x();
       
  1669     int length = postLocation - preLocation;
       
  1670     tabList[to].dragOffset -= length;
       
  1671     tabList[to].startAnimation(this, ANIMATION_DURATION);
       
  1672 }
       
  1673 
       
  1674 void QTabBarPrivate::moveTab(int index, int offset)
       
  1675 {
       
  1676     if (!validIndex(index))
       
  1677         return;
       
  1678     tabList[index].dragOffset = offset;
       
  1679     layoutTab(index); // Make buttons follow tab
       
  1680     q_func()->update();
       
  1681 }
       
  1682 
       
  1683 /*!\reimp
       
  1684 */
       
  1685 void QTabBar::mousePressEvent(QMouseEvent *event)
       
  1686 {
       
  1687     Q_D(QTabBar);
       
  1688     if (event->button() != Qt::LeftButton) {
       
  1689         event->ignore();
       
  1690         return;
       
  1691     }
       
  1692     // Be safe!
       
  1693     if (d->pressedIndex != -1 && d->movable)
       
  1694         d->moveTabFinished(d->pressedIndex);
       
  1695 
       
  1696     d->pressedIndex = d->indexAtPos(event->pos());
       
  1697     if (d->validIndex(d->pressedIndex)) {
       
  1698         QStyleOptionTabBarBaseV2 optTabBase;
       
  1699         optTabBase.init(this);
       
  1700         optTabBase.documentMode = d->documentMode;
       
  1701         if (event->type() == style()->styleHint(QStyle::SH_TabBar_SelectMouseType, &optTabBase, this))
       
  1702             setCurrentIndex(d->pressedIndex);
       
  1703         else
       
  1704             repaint(tabRect(d->pressedIndex));
       
  1705         if (d->movable) {
       
  1706             d->dragStartPosition = event->pos();
       
  1707         }
       
  1708     }
       
  1709 }
       
  1710 
       
  1711 /*!\reimp
       
  1712  */
       
  1713 void QTabBar::mouseMoveEvent(QMouseEvent *event)
       
  1714 {
       
  1715     Q_D(QTabBar);
       
  1716     if (d->movable) {
       
  1717         // Be safe!
       
  1718         if (d->pressedIndex != -1
       
  1719             && event->buttons() == Qt::NoButton)
       
  1720             d->moveTabFinished(d->pressedIndex);
       
  1721         
       
  1722         // Start drag
       
  1723         if (!d->dragInProgress && d->pressedIndex != -1) {
       
  1724             if ((event->pos() - d->dragStartPosition).manhattanLength() > QApplication::startDragDistance()) {
       
  1725                 d->dragInProgress = true;
       
  1726                 d->setupMovableTab();
       
  1727             }
       
  1728         }
       
  1729 
       
  1730         int offset = (event->pos() - d->dragStartPosition).manhattanLength();
       
  1731         if (event->buttons() == Qt::LeftButton
       
  1732             && offset > QApplication::startDragDistance()
       
  1733             && d->validIndex(d->pressedIndex)) {
       
  1734             bool vertical = verticalTabs(d->shape);
       
  1735             int dragDistance;
       
  1736             if (vertical) {
       
  1737                 dragDistance = (event->pos().y() - d->dragStartPosition.y());
       
  1738             } else {
       
  1739                 dragDistance = (event->pos().x() - d->dragStartPosition.x());
       
  1740             }
       
  1741             d->tabList[d->pressedIndex].dragOffset = dragDistance;
       
  1742 
       
  1743             QRect startingRect = tabRect(d->pressedIndex);
       
  1744             if (vertical)
       
  1745                 startingRect.moveTop(startingRect.y() + dragDistance);
       
  1746             else
       
  1747                 startingRect.moveLeft(startingRect.x() + dragDistance);
       
  1748 
       
  1749             int overIndex;
       
  1750             if (dragDistance < 0)
       
  1751                 overIndex = tabAt(startingRect.topLeft());
       
  1752             else
       
  1753                 overIndex = tabAt(startingRect.topRight());
       
  1754 
       
  1755             if (overIndex != d->pressedIndex && overIndex != -1) {
       
  1756                 int offset = 1;
       
  1757                 if (isRightToLeft() && !vertical)
       
  1758                     offset *= -1;
       
  1759                 if (dragDistance < 0) {
       
  1760                     dragDistance *= -1;
       
  1761                     offset *= -1;
       
  1762                 }
       
  1763                 for (int i = d->pressedIndex;
       
  1764                      offset > 0 ? i < overIndex : i > overIndex;
       
  1765                      i += offset) {
       
  1766                     QRect overIndexRect = tabRect(overIndex);
       
  1767                     int needsToBeOver = (vertical ? overIndexRect.height() : overIndexRect.width()) / 2;
       
  1768                     if (dragDistance > needsToBeOver)
       
  1769                         d->slide(i + offset, d->pressedIndex);
       
  1770                 }
       
  1771             }
       
  1772             // Buttons needs to follow the dragged tab
       
  1773             d->layoutTab(d->pressedIndex);
       
  1774 
       
  1775             update();
       
  1776         }
       
  1777     }
       
  1778 
       
  1779     if (event->buttons() != Qt::LeftButton) {
       
  1780         event->ignore();
       
  1781         return;
       
  1782     }
       
  1783     QStyleOptionTabBarBaseV2 optTabBase;
       
  1784     optTabBase.init(this);
       
  1785     optTabBase.documentMode = d->documentMode;
       
  1786 }
       
  1787 
       
  1788 void QTabBarPrivate::setupMovableTab()
       
  1789 {
       
  1790     Q_Q(QTabBar);
       
  1791     if (!movingTab)
       
  1792         movingTab = new QWidget(q);
       
  1793 
       
  1794     int taboverlap = q->style()->pixelMetric(QStyle::PM_TabBarTabOverlap, 0 ,q);
       
  1795     QRect grabRect = q->tabRect(pressedIndex);
       
  1796     grabRect.adjust(-taboverlap, 0, taboverlap, 0);
       
  1797 
       
  1798     QPixmap grabImage(grabRect.size());
       
  1799     grabImage.fill(Qt::transparent);
       
  1800     QStylePainter p(&grabImage, q);
       
  1801 
       
  1802     QStyleOptionTabV3 tab;
       
  1803     q->initStyleOption(&tab, pressedIndex);
       
  1804     tab.rect.moveTopLeft(QPoint(taboverlap, 0));
       
  1805     p.drawControl(QStyle::CE_TabBarTab, tab);
       
  1806     p.end();
       
  1807 
       
  1808     QPalette pal;
       
  1809     pal.setBrush(QPalette::All, QPalette::Window, grabImage);
       
  1810     movingTab->setPalette(pal);
       
  1811     movingTab->setGeometry(grabRect);
       
  1812     movingTab->setAutoFillBackground(true);
       
  1813     movingTab->raise();
       
  1814 
       
  1815     // Re-arrange widget order to avoid overlaps
       
  1816     if (tabList[pressedIndex].leftWidget)
       
  1817         tabList[pressedIndex].leftWidget->raise();
       
  1818     if (tabList[pressedIndex].rightWidget)
       
  1819         tabList[pressedIndex].rightWidget->raise();
       
  1820     if (leftB)
       
  1821         leftB->raise();
       
  1822     if (rightB)
       
  1823         rightB->raise();
       
  1824     movingTab->setVisible(true);
       
  1825 }
       
  1826 
       
  1827 void QTabBarPrivate::moveTabFinished(int index)
       
  1828 {
       
  1829     Q_Q(QTabBar);
       
  1830     bool cleanup = (pressedIndex == index) || (pressedIndex == -1) || !validIndex(index);
       
  1831     bool allAnimationsFinished = true;
       
  1832 #ifndef QT_NO_ANIMATION
       
  1833     for(int i = 0; allAnimationsFinished && i < tabList.count(); ++i) {
       
  1834         const Tab &t = tabList.at(i);
       
  1835         if (t.animation && t.animation->state() == QAbstractAnimation::Running)
       
  1836             allAnimationsFinished = false;
       
  1837     }
       
  1838 #endif //QT_NO_ANIMATION
       
  1839     if (allAnimationsFinished && cleanup) {
       
  1840         if(movingTab)
       
  1841             movingTab->setVisible(false); // We might not get a mouse release
       
  1842         for (int i = 0; i < tabList.count(); ++i) {
       
  1843             tabList[i].dragOffset = 0;
       
  1844         }
       
  1845         if (pressedIndex != -1 && movable) {
       
  1846             pressedIndex = -1;
       
  1847             dragInProgress = false;
       
  1848             dragStartPosition = QPoint();
       
  1849         }
       
  1850         layoutWidgets();
       
  1851     } else {
       
  1852         if (!validIndex(index))
       
  1853             return;
       
  1854         tabList[index].dragOffset = 0;
       
  1855     }
       
  1856     q->update();
       
  1857 }
       
  1858 
       
  1859 /*!\reimp
       
  1860 */
       
  1861 void QTabBar::mouseReleaseEvent(QMouseEvent *event)
       
  1862 {
       
  1863     Q_D(QTabBar);
       
  1864     if (event->button() != Qt::LeftButton) {
       
  1865         event->ignore();
       
  1866         return;
       
  1867     }
       
  1868 
       
  1869     if (d->movable && d->dragInProgress && d->validIndex(d->pressedIndex)) {
       
  1870         int length = d->tabList[d->pressedIndex].dragOffset;
       
  1871         int width = verticalTabs(d->shape)
       
  1872             ? tabRect(d->pressedIndex).height()
       
  1873             : tabRect(d->pressedIndex).width();
       
  1874         int duration = qMin(ANIMATION_DURATION,
       
  1875                 (qAbs(length) * ANIMATION_DURATION) / width);
       
  1876         d->tabList[d->pressedIndex].startAnimation(d, duration);
       
  1877         d->dragInProgress = false;
       
  1878         d->movingTab->setVisible(false);
       
  1879         d->dragStartPosition = QPoint();
       
  1880     }
       
  1881 
       
  1882     int i = d->indexAtPos(event->pos()) == d->pressedIndex ? d->pressedIndex : -1;
       
  1883     d->pressedIndex = -1;
       
  1884     QStyleOptionTabBarBaseV2 optTabBase;
       
  1885     optTabBase.initFrom(this);
       
  1886     optTabBase.documentMode = d->documentMode;
       
  1887     if (style()->styleHint(QStyle::SH_TabBar_SelectMouseType, &optTabBase, this) == QEvent::MouseButtonRelease)
       
  1888         setCurrentIndex(i);
       
  1889 }
       
  1890 
       
  1891 /*!\reimp
       
  1892  */
       
  1893 void QTabBar::keyPressEvent(QKeyEvent *event)
       
  1894 {
       
  1895     Q_D(QTabBar);
       
  1896     if (event->key() != Qt::Key_Left && event->key() != Qt::Key_Right) {
       
  1897         event->ignore();
       
  1898         return;
       
  1899     }
       
  1900     int offset = event->key() == (isRightToLeft() ? Qt::Key_Right : Qt::Key_Left) ? -1 : 1;    
       
  1901     d->setCurrentNextEnabledIndex(offset);
       
  1902 }
       
  1903 
       
  1904 /*!\reimp
       
  1905  */
       
  1906 #ifndef QT_NO_WHEELEVENT
       
  1907 void QTabBar::wheelEvent(QWheelEvent *event)
       
  1908 {
       
  1909     Q_D(QTabBar);
       
  1910     int offset = event->delta() > 0 ? -1 : 1;
       
  1911     d->setCurrentNextEnabledIndex(offset);
       
  1912     QWidget::wheelEvent(event);
       
  1913 }
       
  1914 #endif //QT_NO_WHEELEVENT
       
  1915 
       
  1916 void QTabBarPrivate::setCurrentNextEnabledIndex(int offset)
       
  1917 {
       
  1918     Q_Q(QTabBar);
       
  1919     for (int index = currentIndex + offset; validIndex(index); index += offset) {
       
  1920         if (tabList.at(index).enabled) {
       
  1921             q->setCurrentIndex(index);
       
  1922             break;
       
  1923         }
       
  1924     }
       
  1925 }
       
  1926 
       
  1927 /*!\reimp
       
  1928  */
       
  1929 void QTabBar::changeEvent(QEvent *event)
       
  1930 {
       
  1931     Q_D(QTabBar);
       
  1932     if (event->type() == QEvent::StyleChange) {
       
  1933         d->elideMode = Qt::TextElideMode(style()->styleHint(QStyle::SH_TabBar_ElideMode, 0, this));
       
  1934         d->useScrollButtons = !style()->styleHint(QStyle::SH_TabBar_PreferNoArrows, 0, this);
       
  1935         d->refresh();
       
  1936     } else if (event->type() == QEvent::FontChange) {
       
  1937         d->refresh();
       
  1938     }
       
  1939     QWidget::changeEvent(event);
       
  1940 }
       
  1941 
       
  1942 /*!
       
  1943     \property QTabBar::elideMode
       
  1944     \brief how to elide text in the tab bar
       
  1945     \since 4.2
       
  1946 
       
  1947     This property controls how items are elided when there is not
       
  1948     enough space to show them for a given tab bar size.
       
  1949 
       
  1950     By default the value is style dependent.
       
  1951 
       
  1952     \sa QTabWidget::elideMode usesScrollButtons QStyle::SH_TabBar_ElideMode
       
  1953 */
       
  1954 
       
  1955 Qt::TextElideMode QTabBar::elideMode() const
       
  1956 {
       
  1957     Q_D(const QTabBar);
       
  1958     return d->elideMode;
       
  1959 }
       
  1960 
       
  1961 void QTabBar::setElideMode(Qt::TextElideMode mode)
       
  1962 {
       
  1963     Q_D(QTabBar);
       
  1964     d->elideMode = mode;
       
  1965     d->refresh();
       
  1966 }
       
  1967 
       
  1968 /*!
       
  1969     \property QTabBar::usesScrollButtons
       
  1970     \brief Whether or not a tab bar should use buttons to scroll tabs when it
       
  1971     has many tabs.
       
  1972     \since 4.2
       
  1973 
       
  1974     When there are too many tabs in a tab bar for its size, the tab bar can either choose
       
  1975     to expand its size or to add buttons that allow you to scroll through the tabs.
       
  1976 
       
  1977     By default the value is style dependant.
       
  1978 
       
  1979     \sa elideMode QTabWidget::usesScrollButtons QStyle::SH_TabBar_PreferNoArrows
       
  1980 */
       
  1981 bool QTabBar::usesScrollButtons() const
       
  1982 {
       
  1983     return d_func()->useScrollButtons;
       
  1984 }
       
  1985 
       
  1986 void QTabBar::setUsesScrollButtons(bool useButtons)
       
  1987 {
       
  1988     Q_D(QTabBar);
       
  1989     if (d->useScrollButtons == useButtons)
       
  1990         return;
       
  1991     d->useScrollButtons = useButtons;
       
  1992     d->refresh();
       
  1993 }
       
  1994 
       
  1995 /*!
       
  1996     \fn void QTabBar::setCurrentTab(int index)
       
  1997 
       
  1998     Use setCurrentIndex() instead.
       
  1999 */
       
  2000 
       
  2001 /*!
       
  2002     \fn void QTabBar::selected(int index);
       
  2003 
       
  2004     Use currentChanged() instead.
       
  2005 */
       
  2006 
       
  2007 
       
  2008 /*!
       
  2009     \property QTabBar::tabsClosable
       
  2010     \brief Whether or not a tab bar should place close buttons on each tab
       
  2011     \since 4.5
       
  2012 
       
  2013     When tabsClosable is set to true a close button will appear on the tab on
       
  2014     either the left or right hand side depending upon the style.  When the button
       
  2015     is clicked the tab the signal tabCloseRequested will be emitted.
       
  2016 
       
  2017     By default the value is false.
       
  2018 
       
  2019     \sa setTabButton(), tabRemoved()
       
  2020 */
       
  2021 
       
  2022 bool QTabBar::tabsClosable() const
       
  2023 {
       
  2024     Q_D(const QTabBar);
       
  2025     return d->closeButtonOnTabs;
       
  2026 }
       
  2027 
       
  2028 void QTabBar::setTabsClosable(bool closable)
       
  2029 {
       
  2030     Q_D(QTabBar);
       
  2031     if (d->closeButtonOnTabs == closable)
       
  2032         return;
       
  2033     d->closeButtonOnTabs = closable;
       
  2034     ButtonPosition closeSide = (ButtonPosition)style()->styleHint(QStyle::SH_TabBar_CloseButtonPosition, 0, this);
       
  2035     if (!closable) {
       
  2036         for (int i = 0; i < d->tabList.count(); ++i) {
       
  2037             if (closeSide == LeftSide && d->tabList[i].leftWidget) {
       
  2038                 d->tabList[i].leftWidget->deleteLater();
       
  2039                 d->tabList[i].leftWidget = 0;
       
  2040             }
       
  2041             if (closeSide == RightSide && d->tabList[i].rightWidget) {
       
  2042                 d->tabList[i].rightWidget->deleteLater();
       
  2043                 d->tabList[i].rightWidget = 0;
       
  2044             }
       
  2045         }
       
  2046     } else {
       
  2047         bool newButtons = false;
       
  2048         for (int i = 0; i < d->tabList.count(); ++i) {
       
  2049             if (tabButton(i, closeSide))
       
  2050                 continue;
       
  2051             newButtons = true;
       
  2052             QAbstractButton *closeButton = new CloseButton(this);
       
  2053             connect(closeButton, SIGNAL(clicked()), this, SLOT(_q_closeTab()));
       
  2054             setTabButton(i, closeSide, closeButton);
       
  2055         }
       
  2056         if (newButtons)
       
  2057             d->layoutTabs();
       
  2058     }
       
  2059     update();
       
  2060 }
       
  2061 
       
  2062 /*!
       
  2063     \enum QTabBar::ButtonPosition
       
  2064     \since 4.5
       
  2065 
       
  2066     This enum type lists the location of the widget on a tab.
       
  2067 
       
  2068     \value LeftSide Left side of the tab.
       
  2069 
       
  2070     \value RightSide Right side of the tab.
       
  2071 
       
  2072 */
       
  2073 
       
  2074 /*!
       
  2075     \enum QTabBar::SelectionBehavior
       
  2076     \since 4.5
       
  2077 
       
  2078     This enum type lists the behavior of QTabBar when a tab is removed
       
  2079     and the tab being removed is also the current tab.
       
  2080 
       
  2081     \value SelectLeftTab  Select the tab to the left of the one being removed.
       
  2082 
       
  2083     \value SelectRightTab  Select the tab to the right of the one being removed.
       
  2084 
       
  2085     \value SelectPreviousTab  Select the previously selected tab.
       
  2086 
       
  2087 */
       
  2088 
       
  2089 /*!
       
  2090     \property QTabBar::selectionBehaviorOnRemove
       
  2091     \brief What tab should be set as current when removeTab is called if
       
  2092     the removed tab is also the current tab.
       
  2093     \since 4.5
       
  2094 
       
  2095     By default the value is SelectRightTab.
       
  2096 
       
  2097     \sa removeTab()
       
  2098 */
       
  2099 
       
  2100 
       
  2101 QTabBar::SelectionBehavior QTabBar::selectionBehaviorOnRemove() const
       
  2102 {
       
  2103     Q_D(const QTabBar);
       
  2104     return d->selectionBehaviorOnRemove;
       
  2105 }
       
  2106 
       
  2107 void QTabBar::setSelectionBehaviorOnRemove(QTabBar::SelectionBehavior behavior)
       
  2108 {
       
  2109     Q_D(QTabBar);
       
  2110     d->selectionBehaviorOnRemove = behavior;
       
  2111 }
       
  2112 
       
  2113 /*!
       
  2114     \property QTabBar::expanding
       
  2115     \brief When expanding is true QTabBar will expand the tabs to use the empty space.
       
  2116     \since 4.5
       
  2117 
       
  2118     By default the value is true.
       
  2119 
       
  2120     \sa QTabWidget::documentMode
       
  2121 */
       
  2122 
       
  2123 bool QTabBar::expanding() const
       
  2124 {
       
  2125     Q_D(const QTabBar);
       
  2126     return d->expanding;
       
  2127 }
       
  2128 
       
  2129 void QTabBar::setExpanding(bool enabled)
       
  2130 {
       
  2131     Q_D(QTabBar);
       
  2132     if (d->expanding == enabled)
       
  2133         return;
       
  2134     d->expanding = enabled;
       
  2135     d->layoutTabs();
       
  2136 }
       
  2137 
       
  2138 /*!
       
  2139     \property QTabBar::movable
       
  2140     \brief This property holds whether the user can move the tabs
       
  2141     within the tabbar area.
       
  2142 
       
  2143     \since 4.5
       
  2144 
       
  2145     By default, this property is false;
       
  2146 */
       
  2147 
       
  2148 bool QTabBar::isMovable() const
       
  2149 {
       
  2150     Q_D(const QTabBar);
       
  2151     return d->movable;
       
  2152 }
       
  2153 
       
  2154 void QTabBar::setMovable(bool movable)
       
  2155 {
       
  2156     Q_D(QTabBar);
       
  2157     d->movable = movable;
       
  2158 }
       
  2159 
       
  2160 
       
  2161 /*!
       
  2162     \property QTabBar::documentMode
       
  2163     \brief Whether or not the tab bar is rendered in a mode suitable for the main window.
       
  2164     \since 4.5
       
  2165 
       
  2166     This property is used as a hint for styles to draw the tabs in a different
       
  2167     way then they would normally look in a tab widget.  On Mac OS X this will
       
  2168     look similar to the tabs in Safari or Leopard's Terminal.app.
       
  2169 
       
  2170     \sa QTabWidget::documentMode
       
  2171 */
       
  2172 bool QTabBar::documentMode() const
       
  2173 {
       
  2174     return d_func()->documentMode;
       
  2175 }
       
  2176 
       
  2177 void QTabBar::setDocumentMode(bool enabled)
       
  2178 {
       
  2179     Q_D(QTabBar);
       
  2180     d->documentMode = enabled;
       
  2181     d->updateMacBorderMetrics();
       
  2182 }
       
  2183 
       
  2184 /*!
       
  2185     Sets \a widget on the tab \a index.  The widget is placed
       
  2186     on the left or right hand side depending upon the \a position.
       
  2187     \since 4.5
       
  2188 
       
  2189     Any previously set widget in \a position is hidden.
       
  2190 
       
  2191     The tab bar will take ownership of the widget and so all widgets set here
       
  2192     will be deleted by the tab bar when it is destroyed unless you separately
       
  2193     reparent the widget after setting some other widget (or 0).
       
  2194 
       
  2195     \sa tabsClosable()
       
  2196   */
       
  2197 void QTabBar::setTabButton(int index, ButtonPosition position, QWidget *widget)
       
  2198 {
       
  2199     Q_D(QTabBar);
       
  2200     if (index < 0 || index >= d->tabList.count())
       
  2201         return;
       
  2202     if (widget) {
       
  2203         widget->setParent(this);
       
  2204         // make sure our left and right widgets stay on top
       
  2205         widget->lower();
       
  2206         widget->show();
       
  2207     }
       
  2208     if (position == LeftSide) {
       
  2209         if (d->tabList[index].leftWidget)
       
  2210             d->tabList[index].leftWidget->hide();
       
  2211         d->tabList[index].leftWidget = widget;
       
  2212     } else {
       
  2213         if (d->tabList[index].rightWidget)
       
  2214             d->tabList[index].rightWidget->hide();
       
  2215         d->tabList[index].rightWidget = widget;
       
  2216     }
       
  2217     d->layoutTabs();
       
  2218     d->refresh();
       
  2219     update();
       
  2220 }
       
  2221 
       
  2222 /*!
       
  2223     Returns the widget set a tab \a index and \a position or 0 if
       
  2224     one is not set.
       
  2225   */
       
  2226 QWidget *QTabBar::tabButton(int index, ButtonPosition position) const
       
  2227 {
       
  2228     Q_D(const QTabBar);
       
  2229     if (index < 0 || index >= d->tabList.count())
       
  2230         return 0;
       
  2231     if (position == LeftSide)
       
  2232         return d->tabList.at(index).leftWidget;
       
  2233     else
       
  2234         return d->tabList.at(index).rightWidget;
       
  2235 }
       
  2236 
       
  2237 CloseButton::CloseButton(QWidget *parent)
       
  2238     : QAbstractButton(parent)
       
  2239 {
       
  2240     setFocusPolicy(Qt::NoFocus);
       
  2241 #ifndef QT_NO_CURSOR
       
  2242     setCursor(Qt::ArrowCursor);
       
  2243 #endif
       
  2244 #ifndef QT_NO_TOOLTIP
       
  2245     setToolTip(tr("Close Tab"));
       
  2246 #endif
       
  2247     resize(sizeHint());
       
  2248 }
       
  2249 
       
  2250 QSize CloseButton::sizeHint() const
       
  2251 {
       
  2252     ensurePolished();
       
  2253     int width = style()->pixelMetric(QStyle::PM_TabCloseIndicatorWidth, 0, this);
       
  2254     int height = style()->pixelMetric(QStyle::PM_TabCloseIndicatorHeight, 0, this);
       
  2255     return QSize(width, height);
       
  2256 }
       
  2257 
       
  2258 void CloseButton::enterEvent(QEvent *event)
       
  2259 {
       
  2260     if (isEnabled())
       
  2261         update();
       
  2262     QAbstractButton::enterEvent(event);
       
  2263 }
       
  2264 
       
  2265 void CloseButton::leaveEvent(QEvent *event)
       
  2266 {
       
  2267     if (isEnabled())
       
  2268         update();
       
  2269     QAbstractButton::leaveEvent(event);
       
  2270 }
       
  2271 
       
  2272 void CloseButton::paintEvent(QPaintEvent *)
       
  2273 {
       
  2274     QPainter p(this);
       
  2275     QStyleOption opt;
       
  2276     opt.init(this);
       
  2277     opt.state |= QStyle::State_AutoRaise;
       
  2278     if (isEnabled() && underMouse() && !isChecked() && !isDown())
       
  2279         opt.state |= QStyle::State_Raised;
       
  2280     if (isChecked())
       
  2281         opt.state |= QStyle::State_On;
       
  2282     if (isDown())
       
  2283         opt.state |= QStyle::State_Sunken;
       
  2284 
       
  2285     if (const QTabBar *tb = qobject_cast<const QTabBar *>(parent())) {
       
  2286         int index = tb->currentIndex();
       
  2287         QTabBar::ButtonPosition position = (QTabBar::ButtonPosition)style()->styleHint(QStyle::SH_TabBar_CloseButtonPosition, 0, tb);
       
  2288         if (tb->tabButton(index, position) == this)
       
  2289             opt.state |= QStyle::State_Selected;
       
  2290     }
       
  2291 
       
  2292     style()->drawPrimitive(QStyle::PE_IndicatorTabClose, &opt, &p, this);
       
  2293 }
       
  2294 
       
  2295 QT_END_NAMESPACE
       
  2296 
       
  2297 #include "moc_qtabbar.cpp"
       
  2298 
       
  2299 #endif // QT_NO_TABBAR