summaryrefslogtreecommitdiffstats
path: root/experimental/tqtinterface/qt4/src/widgets/tqtabbar.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'experimental/tqtinterface/qt4/src/widgets/tqtabbar.cpp')
-rw-r--r--experimental/tqtinterface/qt4/src/widgets/tqtabbar.cpp1368
1 files changed, 1368 insertions, 0 deletions
diff --git a/experimental/tqtinterface/qt4/src/widgets/tqtabbar.cpp b/experimental/tqtinterface/qt4/src/widgets/tqtabbar.cpp
new file mode 100644
index 000000000..dd31f44c8
--- /dev/null
+++ b/experimental/tqtinterface/qt4/src/widgets/tqtabbar.cpp
@@ -0,0 +1,1368 @@
+/****************************************************************************
+**
+** Implementation of TQTab and TQTabBar classes
+**
+** Copyright (C) 2010 Timothy Pearson and (C) 1992-2008 Trolltech ASA.
+**
+** This file is part of the widgets module of the TQt GUI Toolkit.
+**
+** This file may be used under the terms of the GNU General
+** Public License versions 2.0 or 3.0 as published by the Free
+** Software Foundation and appearing in the files LICENSE.GPL2
+** and LICENSE.GPL3 included in the packaging of this file.
+** Alternatively you may (at your option) use any later version
+** of the GNU General Public License if such license has been
+** publicly approved by Trolltech ASA (or its successors, if any)
+** and the KDE Free TQt Foundation.
+**
+** Please review the following information to ensure GNU General
+** Public Licensing requirements will be met:
+** http://trolltech.com/products/qt/licenses/licensing/opensource/.
+** If you are unsure which license is appropriate for your use, please
+** review the following information:
+** http://trolltech.com/products/qt/licenses/licensing/licensingoverview
+** or contact the sales department at sales@trolltech.com.
+**
+** This file may be used under the terms of the Q Public License as
+** defined by Trolltech ASA and appearing in the file LICENSE.TQPL
+** included in the packaging of this file. Licensees holding valid TQt
+** Commercial licenses may use this file in accordance with the TQt
+** Commercial License Agreement provided with the Software.
+**
+** This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
+** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted
+** herein.
+**
+**********************************************************************/
+
+#include "tqtabbar.h"
+#ifndef TQT_NO_TABBAR
+#include "tqaccel.h"
+#include "tqbitmap.h"
+#include "tqtoolbutton.h"
+#include "tqtooltip.h"
+#include "tqapplication.h"
+#include "tqstyle.h"
+#include "tqpainter.h"
+#include "tqiconset.h"
+#include "tqcursor.h"
+#include "../kernel/tqinternal_p.h"
+#if defined(TQT_ACCESSIBILITY_SUPPORT)
+#include "tqaccessible.h"
+#endif
+
+#ifdef TQ_WS_MACX
+#include <tqmacstyle_mac.h>
+#endif
+
+
+/*!
+ \class TQTab tqtabbar.h
+ \brief The TQTab class provides the structures in a TQTabBar.
+
+ \ingroup advanced
+
+ This class is used for custom TQTabBar tab headings.
+
+ \sa TQTabBar
+*/
+
+
+/*!
+ Constructs an empty tab. All fields are set to empty.
+*/
+
+TQTab::TQTab()
+ : enabled( TRUE ),
+ id ( 0 ),
+ iconset( 0 ),
+ tb( 0 )
+{
+}
+
+/*!
+ Constructs a tab with the text \a text.
+*/
+
+TQTab::TQTab( const TQString &text )
+ : label( text ),
+ enabled( TRUE ),
+ id( 0 ),
+ iconset( 0 ),
+ tb( 0 )
+{
+}
+
+/*!
+ Constructs a tab with an \a icon and the text, \a text.
+*/
+
+TQTab::TQTab( const TQIconSet& icon, const TQString& text )
+ : label( text ),
+ enabled( TRUE ),
+ id( 0 ),
+ iconset( new TQIconSet(icon) ),
+ tb( 0 )
+{
+}
+
+/*!
+ \fn TQString TQTab::text() const
+
+ Returns the text of the TQTab label.
+*/
+
+/*!
+ \fn TQIconSet TQTab::iconSet() const
+
+ Return the TQIconSet of the TQTab.
+*/
+
+/*!
+ \fn void TQTab::setRect( const TQRect &rect )
+
+ Set the TQTab TQRect to \a rect.
+*/
+
+/*!
+ \fn TQRect TQTab::rect() const
+
+ Return the TQRect for the TQTab.
+*/
+
+/*!
+ \fn void TQTab::setEnabled( bool enable )
+
+ If \a enable is TRUE enable the TQTab, otherwise disable it.
+*/
+
+/*!
+ \fn bool TQTab::isEnabled() const
+
+ Returns TRUE if the TQTab is enabled; otherwise returns FALSE.
+*/
+
+/*!
+ \fn void TQTab::setIdentifier( int i )
+
+ Set the identifier for the TQTab to \a i. Each TQTab's identifier
+ within a TQTabBar must be unique.
+*/
+
+/*!
+ \fn int TQTab::identifier() const
+
+ Return the TQTab's identifier.
+*/
+
+
+
+/*!
+ Destroys the tab and frees up all allocated resources.
+*/
+
+TQTab::~TQTab()
+{
+ delete iconset;
+ tb = 0;
+}
+
+/*!
+ \class TQTabBar tqtabbar.h
+ \brief The TQTabBar class provides a tab bar, e.g. for use in tabbed dialogs.
+
+ \ingroup advanced
+
+ TQTabBar is straightforward to use; it draws the tabs using one of
+ the predefined \link TQTabBar::Shape tqshapes\endlink, and emits a
+ signal when a tab is selected. It can be subclassed to tailor the
+ look and feel. TQt also provides a ready-made \l{TQTabWidget} and a
+ \l{TQTabDialog}.
+
+ The choice of tab tqshape is a matter of taste, although tab dialogs
+ (for preferences and similar) invariably use \c RoundedAbove;
+ nobody uses \c TriangularAbove. Tab controls in windows other than
+ dialogs almost always use either \c RoundedBelow or \c
+ TriangularBelow. Many spreadsheets and other tab controls in which
+ all the pages are essentially similar use \c TriangularBelow,
+ whereas \c RoundedBelow is used mostly when the pages are
+ different (e.g. a multi-page tool palette).
+
+ The most important part of TQTabBar's API is the selected() signal.
+ This is emitted whenever the selected page changes (even at
+ startup, when the selected page changes from 'none'). There is
+ also a slot, setCurrentTab(), which can be used to select a page
+ programmatically.
+
+ TQTabBar creates automatic accelerator keys in the manner of
+ TQButton; e.g. if a tab's label is "\&Graphics", Alt+G becomes an
+ accelerator key for switching to that tab.
+
+ The following virtual functions may need to be reimplemented:
+ \list
+ \i paint() paints a single tab. paintEvent() calls paint() for
+ each tab so that any overlap will look right.
+ \i addTab() creates a new tab and adds it to the bar.
+ \i selectTab() decides which tab, if any, the user selects with the mouse.
+ \endlist
+
+ The index of the current tab is returned by currentTab(). The tab
+ with a particular index is returned by tabAt(), the tab with a
+ particular id is returned by tab(). The index of a tab is returned
+ by indexOf(). The current tab can be set by index or tab pointer
+ using one of the setCurrentTab() functions.
+
+ <img src=qtabbar-m.png> <img src=qtabbar-w.png>
+*/
+
+/*!
+ \enum TQTabBar::Shape
+
+ This enum type lists the built-in tqshapes supported by TQTabBar:
+
+ \value RoundedAbove the normal rounded look above the pages
+
+ \value RoundedBelow the normal rounded look below the pages
+
+ \value TriangularAbove triangular tabs above the pages (very
+ unusual; included for completeness)
+
+ \value TriangularBelow triangular tabs similar to those used in
+ the Excel spreadsheet, for example
+*/
+
+class TQTabBarToolTip;
+
+struct TQTabPrivate {
+ int id;
+ int focus;
+#ifndef TQT_NO_ACCEL
+ TQAccel * a;
+#endif
+ TQTab *pressed;
+ TQTabBar::Shape s;
+ TQToolButton* rightB;
+ TQToolButton* leftB;
+ int btnWidth;
+ bool scrolls;
+ TQTabBarToolTip * toolTips;
+};
+
+#ifndef TQT_NO_TOOLTIP
+/* \internal
+*/
+class TQTabBarToolTip : public TQToolTip
+{
+public:
+ TQTabBarToolTip( TQWidget * tqparent )
+ : TQToolTip( tqparent ) {}
+ virtual ~TQTabBarToolTip() {}
+
+ void add( TQTab * tab, const TQString & tip )
+ {
+ tabTips.tqreplace( tab, tip );
+ }
+
+ void remove( TQTab * tab )
+ {
+ tabTips.erase( tab );
+ }
+
+ TQString tipForTab( TQTab * tab ) const
+ {
+ TQMapConstIterator<TQTab *, TQString> it;
+ it = tabTips.tqfind( tab );
+ if ( it != tabTips.end() )
+ return it.data();
+ else
+ return TQString();
+ }
+
+protected:
+ void maybeTip( const TQPoint & p )
+ {
+ TQTabBar * tb = (TQTabBar *) parentWidget();
+ if ( !tb )
+ return;
+
+ // check if the scroll buttons in the tab bar are visible -
+ // don't display any tips if the pointer is over one of them
+ TQRect rectL, rectR;
+ rectL.setRect( tb->d->leftB->x(), tb->d->leftB->y(),
+ tb->d->leftB->width(), tb->d->leftB->height() );
+ rectR.setRect( tb->d->rightB->x(), tb->d->rightB->y(),
+ tb->d->rightB->width(), tb->d->rightB->height() );
+ if ( tb->d->scrolls && (rectL.tqcontains( p ) || rectR.tqcontains( p )) )
+ return;
+
+#ifndef TQT_NO_TOOLTIP
+ // tqfind and show the tool tip for the tab under the point p
+ TQMapIterator<TQTab *, TQString> it;
+ for ( it = tabTips.begin(); it != tabTips.end(); ++it ) {
+ if ( it.key()->rect().tqcontains( p ) )
+ tip( it.key()->rect(), it.data() );
+ }
+#endif
+ }
+
+private:
+ TQMap<TQTab *, TQString> tabTips;
+};
+#endif
+
+/*!
+ \fn void TQTabBar::selected( int id )
+
+ TQTabBar emits this signal whenever any tab is selected, whether by
+ the program or by the user. The argument \a id is the id of the
+ tab as returned by addTab().
+
+ show() is guaranteed to emit this signal; you can display your
+ page in a slot connected to this signal.
+*/
+
+/*!
+ \fn void TQTabBar::layoutChanged()
+
+ TQTabBar emits the signal whenever the tqlayout of the tab bar has
+ been recalculated, for example when the contents of a tab change.
+*/
+
+/*!
+ Constructs a new, empty tab bar; the \a tqparent and \a name
+ arguments are passed on to the TQWidget constructor.
+*/
+
+TQTabBar::TQTabBar( TQWidget * tqparent, const char *name )
+ : TQWidget( tqparent, name, (WFlags)(TQt::WNoAutoErase | TQt::WNoMousePropagation) )
+{
+ d = new TQTabPrivate;
+ d->pressed = 0;
+ d->id = 0;
+ d->focus = 0;
+ d->toolTips = 0;
+#ifndef TQT_NO_ACCEL
+ d->a = new TQAccel( this, "tab accelerators" );
+ connect( d->a, TQT_SIGNAL(activated(int)), this, TQT_SLOT(setCurrentTab(int)) );
+ connect( d->a, TQT_SIGNAL(activatedAmbiguously(int)), this, TQT_SLOT(setCurrentTab(int)) );
+#endif
+ d->s = RoundedAbove;
+ d->scrolls = FALSE;
+ d->leftB = new TQToolButton( TQt::LeftArrow, this, "qt_left_btn" );
+ connect( d->leftB, TQT_SIGNAL( clicked() ), this, TQT_SLOT( scrollTabs() ) );
+ d->leftB->hide();
+ d->rightB = new TQToolButton( TQt::RightArrow, this, "qt_right_btn" );
+ connect( d->rightB, TQT_SIGNAL( clicked() ), this, TQT_SLOT( scrollTabs() ) );
+ d->rightB->hide();
+ d->btnWidth = tqstyle().tqpixelMetric(TQStyle::PM_TabBarScrollButtonWidth, this);
+ l = new TQPtrList<TQTab>;
+ lstatic = new TQPtrList<TQTab>;
+ lstatic->setAutoDelete( TRUE );
+ setFocusPolicy( Qt::TabFocus );
+ tqsetSizePolicy( TQSizePolicy( TQSizePolicy::Preferred, TQSizePolicy::Fixed ) );
+}
+
+
+/*!
+ Destroys the tab control, freeing memory used.
+*/
+
+TQTabBar::~TQTabBar()
+{
+#ifndef TQT_NO_TOOLTIP
+ if ( d->toolTips )
+ delete d->toolTips;
+#endif
+ delete d;
+ d = 0;
+ delete l;
+ l = 0;
+ delete lstatic;
+ lstatic = 0;
+}
+
+
+/*!
+ Adds the tab, \a newTab, to the tab control.
+
+ Sets \a newTab's id to a new id and places the tab just to the
+ right of the existing tabs. If the tab's label tqcontains an
+ ampersand, the letter following the ampersand is used as an
+ accelerator for the tab, e.g. if the label is "Bro\&wse" then
+ Alt+W becomes an accelerator which will move the focus to this
+ tab. Returns the id.
+
+ \sa insertTab()
+*/
+
+int TQTabBar::addTab( TQTab * newTab )
+{
+ return insertTab( newTab );
+}
+
+
+/*!
+ Inserts the tab, \a newTab, into the tab control.
+
+ If \a index is not specified, the tab is simply appended.
+ Otherwise it's inserted at the specified position.
+
+ Sets \a newTab's id to a new id. If the tab's label tqcontains an
+ ampersand, the letter following the ampersand is used as an
+ accelerator for the tab, e.g. if the label is "Bro\&wse" then
+ Alt+W becomes an accelerator which will move the focus to this
+ tab. Returns the id.
+
+ \sa addTab()
+*/
+
+int TQTabBar::insertTab( TQTab * newTab, int index )
+{
+ newTab->id = d->id++;
+ if ( !tab( d->focus ) )
+ d->focus = newTab->id;
+
+ newTab->setTabBar( this );
+ l->insert( 0, newTab );
+ if ( index < 0 || index > int(lstatic->count()) )
+ lstatic->append( newTab );
+ else
+ lstatic->insert( index, newTab );
+
+ layoutTabs();
+ updateArrowButtons();
+ makeVisible( tab( currentTab() ) );
+
+#ifndef TQT_NO_ACCEL
+ int p = TQAccel::shortcutKey( newTab->label );
+ if ( p )
+ d->a->insertItem( p, newTab->id );
+#endif
+
+ return newTab->id;
+}
+
+
+/*!
+ Removes tab \a t from the tab control, and deletes the tab.
+*/
+void TQTabBar::removeTab( TQTab * t )
+{
+ //#### accelerator labels??
+#ifndef TQT_NO_TOOLTIP
+ if ( d->toolTips )
+ d->toolTips->remove( t );
+#endif
+#ifndef TQT_NO_ACCEL
+ if ( d->a )
+ d->a->removeItem( t->id );
+#endif
+ bool updateFocus = t->id == d->focus;
+ // remove the TabBar Reference
+ if(d->pressed == t)
+ d->pressed = 0;
+ t->setTabBar( 0 );
+ l->remove( t );
+ lstatic->remove( t );
+ layoutTabs();
+ updateArrowButtons();
+ makeVisible( tab( currentTab() ) );
+ if ( updateFocus )
+ d->focus = currentTab();
+ update();
+}
+
+
+/*!
+ Enables tab \a id if \a enabled is TRUE or disables it if \a
+ enabled is FALSE. If \a id is currently selected,
+ setTabEnabled(FALSE) makes another tab selected.
+
+ setTabEnabled() updates the display if this causes a change in \a
+ id's status.
+
+ \sa update(), isTabEnabled()
+*/
+
+void TQTabBar::setTabEnabled( int id, bool enabled )
+{
+ TQTab * t;
+ for( t = l->first(); t; t = l->next() ) {
+ if ( t && t->id == id ) {
+ if ( t->enabled != enabled ) {
+ t->enabled = enabled;
+#ifndef TQT_NO_ACCEL
+ d->a->setItemEnabled( t->id, enabled );
+#endif
+ TQRect r( t->r );
+ if ( !enabled && id == currentTab() ) {
+ TQPoint p1( t->r.center() ), p2;
+ int m = 2147483647;
+ int distance;
+ // look for the closest enabled tab - measure the
+ // distance between the centers of the two tabs
+ for( TQTab * n = l->first(); n; n = l->next() ) {
+ if ( n->enabled ) {
+ p2 = n->r.center();
+ distance = (p2.x() - p1.x())*(p2.x() - p1.x()) +
+ (p2.y() - p1.y())*(p2.y() - p1.y());
+ if ( distance < m ) {
+ t = n;
+ m = distance;
+ }
+ }
+ }
+ if ( t->enabled ) {
+ r = r.unite( t->r );
+ l->append( l->take( l->tqfindRef( t ) ) );
+ emit selected( t->id );
+ }
+ }
+ tqrepaint( r, FALSE );
+ }
+ return;
+ }
+ }
+}
+
+
+/*!
+ Returns TRUE if the tab with id \a id exists and is enabled;
+ otherwise returns FALSE.
+
+ \sa setTabEnabled()
+*/
+
+bool TQTabBar::isTabEnabled( int id ) const
+{
+ TQTab * t = tab( id );
+ if ( t )
+ return t->enabled;
+ return FALSE;
+}
+
+
+
+/*!
+ \reimp
+*/
+TQSize TQTabBar::tqsizeHint() const
+{
+ TQSize sz(0, 0);
+ if ( TQTab * t = l->first() ) {
+ TQRect r( t->r );
+ while ( (t = l->next()) != 0 )
+ r = r.unite( t->r );
+ sz = r.size();
+ }
+ return sz.expandedTo(TQApplication::globalStrut());
+}
+
+/*!
+ \reimp
+*/
+
+TQSize TQTabBar::tqminimumSizeHint() const
+{
+ if(tqstyle().tqstyleHint( TQStyle::SH_TabBar_PreferNoArrows, this ))
+ return tqsizeHint();
+ return TQSize( d->rightB->tqsizeHint().width() * 2 + 75, tqsizeHint().height() );
+}
+
+/*!
+ Paints the tab \a t using painter \a p. If and only if \a selected
+ is TRUE, \a t is drawn currently selected.
+
+ This virtual function may be reimplemented to change the look of
+ TQTabBar. If you decide to reimplement it, you may also need to
+ reimplement tqsizeHint().
+*/
+
+void TQTabBar::paint( TQPainter * p, TQTab * t, bool selected ) const
+{
+ TQStyle::SFlags flags = TQStyle::Style_Default;
+
+ if (isEnabled() && t->isEnabled())
+ flags |= TQStyle::Style_Enabled;
+ if (tqtopLevelWidget() == tqApp->activeWindow())
+ flags |= TQStyle::Style_Active;
+ if ( selected )
+ flags |= TQStyle::Style_Selected;
+ else if(t == d->pressed)
+ flags |= TQStyle::Style_Sunken;
+ //selection flags
+ if(t->rect().tqcontains(mapFromGlobal(TQCursor::pos())))
+ flags |= TQStyle::Style_MouseOver;
+ tqstyle().tqdrawControl( TQStyle::CE_TabBarTab, p, this, t->rect(),
+ tqcolorGroup(), flags, TQStyleOption(t) );
+
+ TQRect r( t->r );
+ p->setFont( font() );
+
+ int iw = 0;
+ int ih = 0;
+ if ( t->iconset != 0 ) {
+ iw = t->iconset->pixmap( TQIconSet::Small, TQIconSet::Normal ).width() + 4;
+ ih = t->iconset->pixmap( TQIconSet::Small, TQIconSet::Normal ).height();
+ }
+ TQFontMetrics fm = p->fontMetrics();
+ int fw = fm.width( t->label );
+ fw -= t->label.tqcontains('&') * fm.width('&');
+ fw += t->label.tqcontains("&&") * fm.width('&');
+ int w = iw + fw + 4;
+ int h = TQMAX(fm.height() + 4, ih );
+ int offset = 3;
+#ifdef TQ_WS_MAC
+ if (::tqqt_cast<TQMacStyle *>(&tqstyle()))
+ offset = 0;
+#endif
+ paintLabel( p, TQRect( r.left() + (r.width()-w)/2 - offset,
+ r.top() + (r.height()-h)/2,
+ w, h ), t, t->id == keyboardFocusTab() );
+}
+
+/*!
+ Paints the label of tab \a t centered in rectangle \a br using
+ painter \a p. A focus indication is drawn if \a has_focus is TRUE.
+*/
+
+void TQTabBar::paintLabel( TQPainter* p, const TQRect& br,
+ TQTab* t, bool has_focus ) const
+{
+ TQRect r = br;
+ bool selected = currentTab() == t->id;
+ if ( t->iconset) {
+ // the tab has an iconset, draw it in the right mode
+ TQIconSet::Mode mode = (t->enabled && isEnabled())
+ ? TQIconSet::Normal : TQIconSet::Disabled;
+ if ( mode == TQIconSet::Normal && has_focus )
+ mode = TQIconSet::Active;
+ TQPixmap pixmap = t->iconset->pixmap( TQIconSet::Small, mode );
+ int pixw = pixmap.width();
+ int pixh = pixmap.height();
+ r.setLeft( r.left() + pixw + 4 );
+ r.setRight( r.right() + 2 );
+
+ int xoff = 0, yoff = 0;
+ if(!selected) {
+ xoff = tqstyle().tqpixelMetric(TQStyle::PM_TabBarTabShiftHorizontal, this);
+ yoff = tqstyle().tqpixelMetric(TQStyle::PM_TabBarTabShiftVertical, this);
+ }
+ p->drawPixmap( br.left() + 2 + xoff, br.center().y()-pixh/2 + yoff, pixmap );
+ }
+
+ TQStyle::SFlags flags = TQStyle::Style_Default;
+
+ if (isEnabled() && t->isEnabled())
+ flags |= TQStyle::Style_Enabled;
+ if (has_focus)
+ flags |= TQStyle::Style_HasFocus;
+ if ( selected )
+ flags |= TQStyle::Style_Selected;
+ else if(t == d->pressed)
+ flags |= TQStyle::Style_Sunken;
+ if(t->rect().tqcontains(mapFromGlobal(TQCursor::pos())))
+ flags |= TQStyle::Style_MouseOver;
+ tqstyle().tqdrawControl( TQStyle::CE_TabBarLabel, p, this, r,
+ t->isEnabled() ? tqcolorGroup(): tqpalette().disabled(),
+ flags, TQStyleOption(t) );
+}
+
+
+/*!
+ Repaints the tab row. All the painting is done by paint();
+ paintEvent() only decides which tabs need painting and in what
+ order. The event is passed in \a e.
+
+ \sa paint()
+*/
+
+void TQTabBar::paintEvent( TQPaintEvent * e )
+{
+ if ( e->rect().isNull() )
+ return;
+
+ TQSharedDoubleBuffer buffer( this, e->rect() );
+
+ TQTab * t;
+ t = l->first();
+ do {
+ TQTab * n = l->next();
+ if ( t && t->r.intersects( e->rect() ) )
+ paint( buffer.painter(), t, n == 0 );
+ t = n;
+ } while ( t != 0 );
+
+ if ( d->scrolls && lstatic->first()->r.left() < 0 ) {
+ TQPointArray a;
+ int h = height();
+ if ( d->s == RoundedAbove ) {
+ buffer.painter()->fillRect( 0, 3, 4, h-5,
+ tqcolorGroup().brush( TQColorGroup::Background ) );
+ a.setPoints( 5, 0,2, 3,h/4, 0,h/2, 3,3*h/4, 0,h );
+ } else if ( d->s == RoundedBelow ) {
+ buffer.painter()->fillRect( 0, 2, 4, h-5,
+ tqcolorGroup().brush( TQColorGroup::Background ) );
+ a.setPoints( 5, 0,0, 3,h/4, 0,h/2, 3,3*h/4, 0,h-3 );
+ }
+
+ if ( !a.isEmpty() ) {
+ buffer.painter()->setPen( tqcolorGroup().light() );
+ buffer.painter()->drawPolyline( a );
+ a.translate( 1, 0 );
+ buffer.painter()->setPen( tqcolorGroup().midlight() );
+ buffer.painter()->drawPolyline( a );
+ }
+ }
+}
+
+
+/*!
+ This virtual function is called by the mouse event handlers to
+ determine which tab is pressed. The default implementation returns
+ a pointer to the tab whose bounding rectangle tqcontains \a p, if
+ exactly one tab's bounding rectangle tqcontains \a p. Otherwise it
+ returns 0.
+
+ \sa mousePressEvent() mouseReleaseEvent()
+*/
+
+TQTab * TQTabBar::selectTab( const TQPoint & p ) const
+{
+ TQTab * selected = 0;
+ bool moreThanOne = FALSE;
+
+ TQPtrListIterator<TQTab> i( *l );
+ while( i.current() ) {
+ TQTab * t = i.current();
+ ++i;
+
+ if ( t && t->r.tqcontains( p ) ) {
+ if ( selected )
+ moreThanOne = TRUE;
+ else
+ selected = t;
+ }
+ }
+
+ return moreThanOne ? 0 : selected;
+}
+
+
+/*!
+ \reimp
+*/
+void TQTabBar::mousePressEvent( TQMouseEvent * e )
+{
+ if ( e->button() != Qt::LeftButton ) {
+ e->ignore();
+ return;
+ }
+ TQTab *t = selectTab( e->pos() );
+ if ( t && t->enabled ) {
+ d->pressed = t;
+ if(e->type() == tqstyle().tqstyleHint( TQStyle::SH_TabBar_SelectMouseType, this ))
+ setCurrentTab( t );
+ else
+ tqrepaint(t->rect(), FALSE);
+ }
+}
+
+
+/*!
+ \reimp
+*/
+
+void TQTabBar::mouseMoveEvent ( TQMouseEvent *e )
+{
+ if ( e->state() != Qt::LeftButton ) {
+ e->ignore();
+ return;
+ }
+ if(tqstyle().tqstyleHint( TQStyle::SH_TabBar_SelectMouseType, this ) == TQEvent::MouseButtonRelease) {
+ TQTab *t = selectTab( e->pos() );
+ if(t != d->pressed) {
+ if(d->pressed)
+ tqrepaint(d->pressed->rect(), FALSE);
+ if((d->pressed = t))
+ tqrepaint(t->rect(), FALSE);
+ }
+ }
+}
+
+/*!
+ \reimp
+*/
+
+void TQTabBar::mouseReleaseEvent( TQMouseEvent *e )
+{
+ if ( e->button() != Qt::LeftButton )
+ e->ignore();
+ if(d->pressed) {
+ TQTab *t = selectTab( e->pos() ) == d->pressed ? d->pressed : 0;
+ d->pressed = 0;
+ if(t && t->enabled && e->type() == tqstyle().tqstyleHint( TQStyle::SH_TabBar_SelectMouseType, this ))
+ setCurrentTab( t );
+ }
+}
+
+
+/*!
+ \reimp
+*/
+void TQTabBar::show()
+{
+ // ensures that one tab is selected.
+ TQTab * t = l->last();
+ TQWidget::show();
+
+ if ( t )
+ emit selected( t->id );
+}
+
+/*!
+ \property TQTabBar::currentTab
+ \brief the id of the tab bar's visible tab
+
+ If no tab page is currently visible, the property's value is -1.
+ Even if the property's value is not -1, you cannot assume that the
+ user can see the relevant page, or that the tab is enabled. When
+ you need to display something the value of this property
+ represents the best page to display.
+
+ When this property is set to \e id, it will raise the tab with the
+ id \e id and emit the selected() signal.
+
+ \sa selected() isTabEnabled()
+*/
+
+int TQTabBar::currentTab() const
+{
+ const TQTab * t = l->getLast();
+
+ return t ? t->id : -1;
+}
+
+void TQTabBar::setCurrentTab( int id )
+{
+ setCurrentTab( tab( id ) );
+}
+
+
+/*!
+ \overload
+
+ Raises \a tab and emits the selected() signal unless the tab was
+ already current.
+
+ \sa currentTab() selected()
+*/
+
+void TQTabBar::setCurrentTab( TQTab * tab )
+{
+ if ( tab && l ) {
+ if ( l->last() == tab )
+ return;
+
+ TQRect r = l->last()->r;
+ if ( l->tqfindRef( tab ) >= 0 )
+ l->append( l->take() );
+
+ d->focus = tab->id;
+
+ setMicroFocusHint( tab->rect().x(), tab->rect().y(), tab->rect().width(), tab->rect().height(), FALSE );
+
+ if ( tab->r.intersects( r ) ) {
+ tqrepaint( r.unite( tab->r ), FALSE );
+ } else {
+#ifdef TQ_WS_MACX
+ update();
+#else
+ tqrepaint( r, FALSE );
+ tqrepaint( tab->r, FALSE );
+#endif
+ }
+ makeVisible( tab );
+ emit selected( tab->id );
+
+#ifdef TQT_ACCESSIBILITY_SUPPORT
+ TQAccessible::updateAccessibility( this, indexOf(tab->id)+1, TQAccessible::Focus );
+#endif
+ }
+}
+
+/*!
+ \property TQTabBar::keyboardFocusTab
+ \brief the id of the tab that has the keyboard focus
+
+ This property tqcontains the id of the tab that has the keyboard
+ focus or -1 if the tab bar does not have the keyboard focus.
+*/
+
+int TQTabBar::keyboardFocusTab() const
+{
+ return hasFocus() ? d->focus : -1;
+}
+
+
+/*!
+ \reimp
+*/
+void TQTabBar::keyPressEvent( TQKeyEvent * e )
+{
+ // The right and left arrow keys move a selector, the spacebar
+ // makes the tab with the selector active. All other keys are
+ // ignored.
+
+ int old = d->focus;
+
+ bool reverse = TQApplication::reverseLayout();
+ if ( ( !reverse && e->key() == Qt::Key_Left ) || ( reverse && e->key() == Qt::Key_Right ) ) {
+ // left - skip past any disabled ones
+ if ( d->focus >= 0 ) {
+ TQTab * t = lstatic->last();
+ while ( t && t->id != d->focus )
+ t = lstatic->prev();
+ do {
+ t = lstatic->prev();
+ } while ( t && !t->enabled);
+ if (t)
+ d->focus = t->id;
+ }
+ if ( d->focus < 0 )
+ d->focus = old;
+ } else if ( ( !reverse && e->key() == Qt::Key_Right ) || ( reverse && e->key() == Qt::Key_Left ) ) {
+ TQTab * t = lstatic->first();
+ while ( t && t->id != d->focus )
+ t = lstatic->next();
+ do {
+ t = lstatic->next();
+ } while ( t && !t->enabled);
+
+ if (t)
+ d->focus = t->id;
+ if ( d->focus >= d->id )
+ d->focus = old;
+ } else {
+ // other keys - ignore
+ e->ignore();
+ return;
+ }
+
+ // if the focus moved, tqrepaint and signal
+ if ( old != d->focus ) {
+ setCurrentTab( d->focus );
+ }
+}
+
+
+/*!
+ Returns the tab with id \a id or 0 if there is no such tab.
+
+ \sa count()
+*/
+
+TQTab * TQTabBar::tab( int id ) const
+{
+ TQTab * t;
+ for( t = l->first(); t; t = l->next() )
+ if ( t && t->id == id )
+ return t;
+ return 0;
+}
+
+
+/*!
+ Returns the tab at position \a index.
+
+ \sa indexOf()
+*/
+
+TQTab * TQTabBar::tabAt( int index ) const
+{
+ TQTab * t;
+ t = lstatic->at( index );
+ return t;
+}
+
+
+/*!
+ Returns the position index of the tab with id \a id or -1 if no
+ tab has this \a id.
+
+ \sa tabAt()
+*/
+int TQTabBar::indexOf( int id ) const
+{
+ TQTab * t;
+ int idx = 0;
+ for( t = lstatic->first(); t; t = lstatic->next() ) {
+ if ( t && t->id == id )
+ return idx;
+ idx++;
+ }
+ return -1;
+}
+
+
+/*!
+ \property TQTabBar::count
+ \brief the number of tabs in the tab bar
+
+ \sa tab()
+*/
+int TQTabBar::count() const
+{
+ return l->count();
+}
+
+
+/*!
+ The list of TQTab objects in the tab bar.
+
+ This list is unlikely to be in the order that the TQTab elements
+ appear visually. One way of iterating over the tabs is like this:
+ \code
+ for ( uint i = 0; i < myTabBar->count(); ++i ) {
+ nextTab = myTabBar->tabAt( i );
+ // do something with nextTab
+ }
+ \endcode
+*/
+TQPtrList<TQTab> * TQTabBar::tabList()
+{
+ return l;
+}
+
+
+/*!
+ \property TQTabBar::tqshape
+ \brief the tqshape of the tabs in the tab bar
+
+ The value of this property is one of the following: \c
+ RoundedAbove (default), \c RoundedBelow, \c TriangularAbove or \c
+ TriangularBelow.
+
+ \sa Shape
+*/
+TQTabBar::Shape TQTabBar::tqshape() const
+{
+ return d ? d->s : RoundedAbove;
+}
+
+void TQTabBar::setShape( Shape s )
+{
+ if ( !d || d->s == s )
+ return;
+ //######### must recalculate heights
+ d->s = s;
+ update();
+}
+
+/*!
+ Lays out all existing tabs according to their label and their
+ iconset.
+ */
+void TQTabBar::layoutTabs()
+{
+ if ( lstatic->isEmpty() )
+ return;
+
+ TQSize oldSh(0, 0);
+ if ( TQTab * t = l->first() ) {
+ TQRect r( t->r );
+ while ( (t = l->next()) != 0 )
+ r = r.unite( t->r );
+ oldSh = r.size();
+ }
+
+ d->btnWidth = tqstyle().tqpixelMetric(TQStyle::PM_TabBarScrollButtonWidth, this);
+ int hframe, vframe, overlap;
+ hframe = tqstyle().tqpixelMetric( TQStyle::PM_TabBarTabHSpace, this );
+ vframe = tqstyle().tqpixelMetric( TQStyle::PM_TabBarTabVSpace, this );
+ overlap = tqstyle().tqpixelMetric( TQStyle::PM_TabBarTabOverlap, this );
+
+ TQFontMetrics fm = fontMetrics();
+ TQRect r;
+ TQTab *t;
+ bool reverse = TQApplication::reverseLayout();
+ if ( reverse )
+ t = lstatic->last();
+ else
+ t = lstatic->first();
+ int x = 0;
+ int offset = (t && d->scrolls) ? t->r.x() : 0;
+ while ( t ) {
+ int lw = fm.width( t->label );
+ lw -= t->label.tqcontains('&') * fm.width('&');
+ lw += t->label.tqcontains("&&") * fm.width('&');
+ int iw = 0;
+ int ih = 0;
+ if ( t->iconset != 0 ) {
+ iw = t->iconset->pixmap( TQIconSet::Small, TQIconSet::Normal ).width() + 4;
+ ih = t->iconset->pixmap( TQIconSet::Small, TQIconSet::Normal ).height();
+ }
+ int h = TQMAX( fm.height(), ih );
+ h = TQMAX( h, TQApplication::globalStrut().height() );
+
+ h += vframe;
+ t->r = TQRect(TQPoint(x, 0), tqstyle().tqsizeFromContents(TQStyle::CT_TabBarTab, this,
+ TQSize( TQMAX( lw + hframe + iw, TQApplication::globalStrut().width() ), h ),
+ TQStyleOption(t) ));
+ x += t->r.width() - overlap;
+ r = r.unite( t->r );
+ if ( reverse )
+ t = lstatic->prev();
+ else
+ t = lstatic->next();
+ }
+ x += overlap;
+ int w = (d->scrolls) ? d->leftB->x() : width();
+ if (x + offset < w)
+ offset = w - x;
+ if (offset > 0)
+ offset = 0;
+
+ for ( t = lstatic->first(); t; t = lstatic->next() ) {
+ t->r.moveBy( offset, 0 );
+ t->r.setHeight( r.height() );
+ }
+
+ if ( tqsizeHint() != oldSh )
+ updateGeometry();
+
+ emit layoutChanged();
+}
+
+/*!
+ \reimp
+*/
+
+bool TQTabBar::event( TQEvent *e )
+{
+ if ( e->type() == TQEvent::LanguageChange ) {
+ layoutTabs();
+ updateArrowButtons();
+ makeVisible( tab( currentTab() ));
+ }
+
+ return TQWidget::event( e );
+}
+
+/*!
+ \reimp
+*/
+
+void TQTabBar::styleChange( TQStyle& old )
+{
+ layoutTabs();
+ updateArrowButtons();
+ TQWidget::styleChange( old );
+}
+
+/*!
+ \reimp
+*/
+void TQTabBar::focusInEvent( TQFocusEvent * )
+{
+ TQTab *t = tab( d->focus );
+ if ( t )
+ tqrepaint( t->r, FALSE );
+}
+
+/*!
+ \reimp
+*/
+void TQTabBar::focusOutEvent( TQFocusEvent * )
+{
+ TQTab *t = tab( d->focus );
+ if ( t )
+ tqrepaint( t->r, FALSE );
+}
+
+/*!
+ \reimp
+*/
+void TQTabBar::resizeEvent( TQResizeEvent * )
+{
+ const int arrowWidth = TQMAX( d->btnWidth, TQApplication::globalStrut().width() );;
+ d->rightB->setGeometry( width() - arrowWidth, 0, arrowWidth, height() );
+ d->leftB->setGeometry( width() - 2*arrowWidth, 0, arrowWidth, height() );
+ layoutTabs();
+ updateArrowButtons();
+ makeVisible( tab( currentTab() ));
+}
+
+void TQTabBar::scrollTabs()
+{
+ TQTab* left = 0;
+ TQTab* right = 0;
+ for ( TQTab* t = lstatic->first(); t; t = lstatic->next() ) {
+ if ( t->r.left() < 0 && t->r.right() > 0 )
+ left = t;
+ if ( t->r.left() < d->leftB->x()+2 )
+ right = t;
+ }
+
+ if ( sender() == d->leftB )
+ makeVisible( left );
+ else if ( sender() == d->rightB )
+ makeVisible( right );
+}
+
+void TQTabBar::makeVisible( TQTab* tab )
+{
+ bool tooFarLeft = ( tab && tab->r.left() < 0 );
+ bool tooFarRight = ( tab && tab->r.right() >= d->leftB->x() );
+
+ if ( !d->scrolls || ( !tooFarLeft && ! tooFarRight ) )
+ return;
+
+ bool bs = tqsignalsBlocked();
+ blockSignals(TRUE);
+ layoutTabs();
+ blockSignals(bs);
+
+ int offset = 0;
+
+ if ( tooFarLeft ) {
+ offset = tab->r.left();
+ if (tab != lstatic->first())
+ offset -= 8;
+ } else if ( tooFarRight ) {
+ offset = tab->r.right() - d->leftB->x() + 1;
+ }
+
+ for ( TQTab* t = lstatic->first(); t; t = lstatic->next() )
+ t->r.moveBy( -offset, 0 );
+
+ d->leftB->setEnabled( lstatic->first()->r.left() < 0);
+ d->rightB->setEnabled( lstatic->last()->r.right() >= d->leftB->x() );
+
+ // Make sure disabled buttons pop up again
+ if ( !d->leftB->isEnabled() && d->leftB->isDown() )
+ d->leftB->setDown( FALSE );
+ if ( !d->rightB->isEnabled() && d->rightB->isDown() )
+ d->rightB->setDown( FALSE );
+
+ update();
+ emit layoutChanged();
+}
+
+void TQTabBar::updateArrowButtons()
+{
+ if (lstatic->isEmpty()) {
+ d->scrolls = FALSE;
+ } else {
+ d->scrolls = (lstatic->last()->r.right() - lstatic->first()->r.left() > width());
+ }
+ if ( d->scrolls ) {
+ const int arrowWidth = TQMAX( d->btnWidth, TQApplication::globalStrut().width() );
+ if ( TQApplication::reverseLayout() ) {
+ d->rightB->setGeometry( arrowWidth, 0, arrowWidth, height() );
+ d->leftB->setGeometry( 0, 0, arrowWidth, height() );
+ } else {
+ d->rightB->setGeometry( width() - arrowWidth, 0, arrowWidth, height() );
+ d->leftB->setGeometry( width() - 2*arrowWidth, 0, arrowWidth, height() );
+ }
+
+ d->leftB->setEnabled( lstatic->first()->r.left() < 0);
+ d->rightB->setEnabled( lstatic->last()->r.right() >= d->leftB->x() );
+ d->leftB->show();
+ d->rightB->show();
+ } else {
+ d->leftB->hide();
+ d->rightB->hide();
+ layoutTabs();
+ }
+}
+
+/*!
+ Removes the tool tip for the tab at index position \a index.
+*/
+void TQTabBar::removeToolTip( int index )
+{
+#ifndef TQT_NO_TOOLTIP
+ TQTab * tab = tabAt( index );
+ if ( !tab || !d->toolTips )
+ return;
+ d->toolTips->remove( tab );
+#endif
+}
+
+/*!
+ Sets the tool tip for the tab at index position \a index to \a
+ tip.
+*/
+void TQTabBar::setToolTip( int index, const TQString & tip )
+{
+#ifndef TQT_NO_TOOLTIP
+ TQTab * tab = tabAt( index );
+ if ( !tab )
+ return;
+ if ( d->toolTips == 0 )
+ d->toolTips = new TQTabBarToolTip( this );
+ d->toolTips->add( tab, tip );
+#endif
+}
+
+/*!
+ Returns the tool tip for the tab at index position \a index.
+*/
+TQString TQTabBar::toolTip( int index ) const
+{
+#ifndef TQT_NO_TOOLTIP
+ if ( d->toolTips )
+ return d->toolTips->tipForTab( tabAt( index ) );
+ else
+#endif
+ return TQString();
+}
+
+/*!
+ Sets the text of the tab to \a text.
+*/
+void TQTab::setText( const TQString& text )
+{
+ label = text;
+ if ( tb ) {
+#ifndef TQT_NO_ACCEL
+ tb->d->a->removeItem( id );
+ int p = TQAccel::shortcutKey( text );
+ if ( p )
+ tb->d->a->insertItem( p, id );
+#endif
+ tb->layoutTabs();
+ tb->tqrepaint(FALSE);
+
+#if defined(TQT_ACCESSIBILITY_SUPPORT)
+ TQAccessible::updateAccessibility( tb, tb->indexOf(id)+1, TQAccessible::NameChanged );
+#endif
+ }
+}
+
+/*!
+ Sets the tab's iconset to \a icon
+*/
+void TQTab::setIconSet( const TQIconSet &icon )
+{
+ iconset = new TQIconSet( icon );
+}
+
+// this allows us to handle accelerators that are in a TQTabBar.
+void TQTab::setTabBar( TQTabBar *newTb )
+{
+ tb = newTb;
+}
+
+/*!
+ \internal
+*/
+void TQTabBar::fontChange( const TQFont & oldFont )
+{
+ layoutTabs();
+ TQWidget::fontChange( oldFont );
+}
+
+#endif