|
|
|
/* This file is part of the KDE libraries
|
|
|
|
Copyright (C) 2003 Stephan Binner <binner@kde.org>
|
|
|
|
Copyright (C) 2003 Zack Rusin <zack@kde.org>
|
|
|
|
|
|
|
|
This library is free software; you can redistribute it and/or
|
|
|
|
modify it under the terms of the GNU Library General Public
|
|
|
|
License as published by the Free Software Foundation; either
|
|
|
|
version 2 of the License, or (at your option) any later version.
|
|
|
|
|
|
|
|
This library is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
Library General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU Library General Public License
|
|
|
|
along with this library; see the file COPYING.LIB. If not, write to
|
|
|
|
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
|
|
|
Boston, MA 02110-1301, USA.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <tqapplication.h>
|
|
|
|
#include <tqcursor.h>
|
|
|
|
#include <tqpainter.h>
|
|
|
|
#include <tqstyle.h>
|
|
|
|
#include <tqtimer.h>
|
|
|
|
#include <tqpushbutton.h>
|
|
|
|
#include <tqtooltip.h>
|
|
|
|
|
|
|
|
#include <kglobalsettings.h>
|
|
|
|
#include <kiconloader.h>
|
|
|
|
#include <klocale.h>
|
|
|
|
|
|
|
|
#include "ktabbar.h"
|
|
|
|
#include "ktabwidget.h"
|
|
|
|
|
|
|
|
KTabBar::KTabBar( TQWidget *parent, const char *name )
|
|
|
|
: TQTabBar( parent, name ), mReorderStartTab( -1 ), mReorderPreviousTab( -1 ),
|
|
|
|
mHoverCloseButtonTab( 0 ), mDragSwitchTab( 0 ), mHoverCloseButton( 0 ),
|
|
|
|
mHoverCloseButtonEnabled( false ), mHoverCloseButtonDelayed( true ),
|
|
|
|
mTabReorderingEnabled( false ), mTabCloseActivatePrevious( false )
|
|
|
|
{
|
|
|
|
setAcceptDrops( true );
|
|
|
|
setMouseTracking( true );
|
|
|
|
|
|
|
|
mEnableCloseButtonTimer = new TQTimer( this );
|
|
|
|
connect( mEnableCloseButtonTimer, TQT_SIGNAL( timeout() ), TQT_SLOT( enableCloseButton() ) );
|
|
|
|
|
|
|
|
mActivateDragSwitchTabTimer = new TQTimer( this );
|
|
|
|
connect( mActivateDragSwitchTabTimer, TQT_SIGNAL( timeout() ), TQT_SLOT( activateDragSwitchTab() ) );
|
|
|
|
|
|
|
|
connect(this, TQT_SIGNAL(layoutChanged()), TQT_SLOT(onLayoutChange()));
|
|
|
|
}
|
|
|
|
|
|
|
|
KTabBar::~KTabBar()
|
|
|
|
{
|
|
|
|
//For the future
|
|
|
|
//delete d;
|
|
|
|
}
|
|
|
|
|
|
|
|
void KTabBar::setTabEnabled( int id, bool enabled )
|
|
|
|
{
|
|
|
|
TQTab * t = tab( id );
|
|
|
|
if ( t ) {
|
|
|
|
if ( t->isEnabled() != enabled ) {
|
|
|
|
t->setEnabled( enabled );
|
|
|
|
TQRect r( t->rect() );
|
|
|
|
if ( !enabled && id == currentTab() && count()>1 ) {
|
|
|
|
TQPtrList<TQTab> *tablist = tabList();
|
|
|
|
if ( mTabCloseActivatePrevious )
|
|
|
|
t = tablist->tqat( count()-2 );
|
|
|
|
else {
|
|
|
|
int index = indexOf( id );
|
|
|
|
index += ( index+1 == count() ) ? -1 : 1;
|
|
|
|
t = tabAt( index );
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( t->isEnabled() ) {
|
|
|
|
r = r.unite( t->rect() );
|
|
|
|
tablist->append( tablist->take( tablist->findRef( t ) ) );
|
|
|
|
emit selected( t->identifier() );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
tqrepaint( r );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void KTabBar::mouseDoubleClickEvent( TQMouseEvent *e )
|
|
|
|
{
|
|
|
|
if( e->button() != Qt::LeftButton )
|
|
|
|
return;
|
|
|
|
|
|
|
|
TQTab *tab = selectTab( e->pos() );
|
|
|
|
if( tab ) {
|
|
|
|
emit( mouseDoubleClick( indexOf( tab->identifier() ) ) );
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
TQTabBar::mouseDoubleClickEvent( e );
|
|
|
|
}
|
|
|
|
|
|
|
|
void KTabBar::mousePressEvent( TQMouseEvent *e )
|
|
|
|
{
|
|
|
|
if( e->button() == Qt::LeftButton ) {
|
|
|
|
mEnableCloseButtonTimer->stop();
|
|
|
|
mDragStart = e->pos();
|
|
|
|
}
|
|
|
|
else if( e->button() == Qt::RightButton ) {
|
|
|
|
TQTab *tab = selectTab( e->pos() );
|
|
|
|
if( tab ) {
|
|
|
|
emit( contextMenu( indexOf( tab->identifier() ), mapToGlobal( e->pos() ) ) );
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
TQTabBar::mousePressEvent( e );
|
|
|
|
}
|
|
|
|
|
|
|
|
void KTabBar::mouseMoveEvent( TQMouseEvent *e )
|
|
|
|
{
|
|
|
|
if ( e->state() == Qt::LeftButton ) {
|
|
|
|
TQTab *tab = selectTab( e->pos() );
|
|
|
|
if ( mDragSwitchTab && tab != mDragSwitchTab ) {
|
|
|
|
mActivateDragSwitchTabTimer->stop();
|
|
|
|
mDragSwitchTab = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int delay = KGlobalSettings::dndEventDelay();
|
|
|
|
TQPoint newPos = e->pos();
|
|
|
|
if( newPos.x() > mDragStart.x()+delay || newPos.x() < mDragStart.x()-delay ||
|
|
|
|
newPos.y() > mDragStart.y()+delay || newPos.y() < mDragStart.y()-delay )
|
|
|
|
{
|
|
|
|
if( tab ) {
|
|
|
|
emit( initiateDrag( indexOf( tab->identifier() ) ) );
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if ( e->state() == Qt::MidButton ) {
|
|
|
|
if (mReorderStartTab==-1) {
|
|
|
|
int delay = KGlobalSettings::dndEventDelay();
|
|
|
|
TQPoint newPos = e->pos();
|
|
|
|
if( newPos.x() > mDragStart.x()+delay || newPos.x() < mDragStart.x()-delay ||
|
|
|
|
newPos.y() > mDragStart.y()+delay || newPos.y() < mDragStart.y()-delay )
|
|
|
|
{
|
|
|
|
TQTab *tab = selectTab( e->pos() );
|
|
|
|
if( tab && mTabReorderingEnabled ) {
|
|
|
|
mReorderStartTab = indexOf( tab->identifier() );
|
|
|
|
grabMouse( tqsizeAllCursor );
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
TQTab *tab = selectTab( e->pos() );
|
|
|
|
if( tab ) {
|
|
|
|
int reorderStopTab = indexOf( tab->identifier() );
|
|
|
|
if ( mReorderStartTab!=reorderStopTab && mReorderPreviousTab!=reorderStopTab ) {
|
|
|
|
emit( moveTab( mReorderStartTab, reorderStopTab ) );
|
|
|
|
mReorderPreviousTab=mReorderStartTab;
|
|
|
|
mReorderStartTab=reorderStopTab;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( mHoverCloseButtonEnabled && mReorderStartTab==-1) {
|
|
|
|
TQTab *t = selectTab( e->pos() );
|
|
|
|
if( t && t->iconSet() && t->isEnabled() ) {
|
|
|
|
TQPixmap pixmap = t->iconSet()->pixmap( TQIconSet::Small, TQIconSet::Normal );
|
|
|
|
TQRect rect( 0, 0, pixmap.width() + 4, pixmap.height() +4);
|
|
|
|
|
|
|
|
int xoff = 0, yoff = 0;
|
|
|
|
// The additional offsets were found by try and error, TODO: find the rational behind them
|
|
|
|
if ( t == tab( currentTab() ) ) {
|
|
|
|
xoff = tqstyle().tqpixelMetric( TQStyle::PM_TabBarTabShiftHorizontal, this ) + 3;
|
|
|
|
yoff = tqstyle().tqpixelMetric( TQStyle::PM_TabBarTabShiftVertical, this ) - 4;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
xoff = 7;
|
|
|
|
yoff = 0;
|
|
|
|
}
|
|
|
|
rect.moveLeft( t->rect().left() + 2 + xoff );
|
|
|
|
rect.moveTop( t->rect().center().y()-pixmap.height()/2 + yoff );
|
|
|
|
if ( rect.contains( e->pos() ) ) {
|
|
|
|
if ( mHoverCloseButton ) {
|
|
|
|
if ( mHoverCloseButtonTab == t )
|
|
|
|
return;
|
|
|
|
mEnableCloseButtonTimer->stop();
|
|
|
|
mHoverCloseButton->deleteLater();
|
|
|
|
mHoverCloseButton = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
mHoverCloseButton = new TQPushButton( this );
|
|
|
|
mHoverCloseButton->setIconSet( KGlobal::iconLoader()->loadIconSet("fileclose", KIcon::Toolbar, KIcon::SizeSmall) );
|
|
|
|
mHoverCloseButton->setGeometry( rect );
|
|
|
|
TQToolTip::add(mHoverCloseButton,i18n("Close this tab"));
|
|
|
|
mHoverCloseButton->setFlat(true);
|
|
|
|
mHoverCloseButton->show();
|
|
|
|
if ( mHoverCloseButtonDelayed ) {
|
|
|
|
mHoverCloseButton->setEnabled(false);
|
|
|
|
mEnableCloseButtonTimer->start( TQApplication::doubleClickInterval(), true );
|
|
|
|
}
|
|
|
|
mHoverCloseButtonTab = t;
|
|
|
|
connect( mHoverCloseButton, TQT_SIGNAL( clicked() ), TQT_SLOT( closeButtonClicked() ) );
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if ( mHoverCloseButton ) {
|
|
|
|
mEnableCloseButtonTimer->stop();
|
|
|
|
mHoverCloseButton->deleteLater();
|
|
|
|
mHoverCloseButton = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
TQTabBar::mouseMoveEvent( e );
|
|
|
|
}
|
|
|
|
|
|
|
|
void KTabBar::enableCloseButton()
|
|
|
|
{
|
|
|
|
mHoverCloseButton->setEnabled(true);
|
|
|
|
}
|
|
|
|
|
|
|
|
void KTabBar::activateDragSwitchTab()
|
|
|
|
{
|
|
|
|
TQTab *tab = selectTab( mapFromGlobal( TQCursor::pos() ) );
|
|
|
|
if ( tab && mDragSwitchTab == tab )
|
|
|
|
setCurrentTab( mDragSwitchTab );
|
|
|
|
mDragSwitchTab = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void KTabBar::mouseReleaseEvent( TQMouseEvent *e )
|
|
|
|
{
|
|
|
|
if( e->button() == Qt::MidButton ) {
|
|
|
|
if ( mReorderStartTab==-1 ) {
|
|
|
|
TQTab *tab = selectTab( e->pos() );
|
|
|
|
if( tab ) {
|
|
|
|
emit( mouseMiddleClick( indexOf( tab->identifier() ) ) );
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
releaseMouse();
|
|
|
|
setCursor( tqarrowCursor );
|
|
|
|
mReorderStartTab=-1;
|
|
|
|
mReorderPreviousTab=-1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
TQTabBar::mouseReleaseEvent( e );
|
|
|
|
}
|
|
|
|
|
|
|
|
void KTabBar::dragMoveEvent( TQDragMoveEvent *e )
|
|
|
|
{
|
|
|
|
TQTab *tab = selectTab( e->pos() );
|
|
|
|
if( tab ) {
|
|
|
|
bool accept = false;
|
|
|
|
// The tqreceivers of the testCanDecode() signal has to adjust
|
|
|
|
// 'accept' accordingly.
|
|
|
|
emit testCanDecode( e, accept);
|
|
|
|
if ( accept && tab != TQTabBar::tab( currentTab() ) ) {
|
|
|
|
mDragSwitchTab = tab;
|
|
|
|
mActivateDragSwitchTabTimer->start( TQApplication::doubleClickInterval()*2, true );
|
|
|
|
}
|
|
|
|
e->accept( accept );
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
e->accept( false );
|
|
|
|
TQTabBar::dragMoveEvent( e );
|
|
|
|
}
|
|
|
|
|
|
|
|
void KTabBar::dropEvent( TQDropEvent *e )
|
|
|
|
{
|
|
|
|
TQTab *tab = selectTab( e->pos() );
|
|
|
|
if( tab ) {
|
|
|
|
mActivateDragSwitchTabTimer->stop();
|
|
|
|
mDragSwitchTab = 0;
|
|
|
|
emit( receivedDropEvent( indexOf( tab->identifier() ) , e ) );
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
TQTabBar::dropEvent( e );
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifndef QT_NO_WHEELEVENT
|
|
|
|
void KTabBar::wheelEvent( TQWheelEvent *e )
|
|
|
|
{
|
|
|
|
if ( e->orientation() == Qt::Horizontal )
|
|
|
|
return;
|
|
|
|
|
|
|
|
emit( wheelDelta( e->delta() ) );
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
void KTabBar::setTabColor( int id, const TQColor& color )
|
|
|
|
{
|
|
|
|
TQTab *t = tab( id );
|
|
|
|
if ( t ) {
|
|
|
|
mTabColors.insert( id, color );
|
|
|
|
tqrepaint( t->rect(), false );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
const TQColor &KTabBar::tabColor( int id ) const
|
|
|
|
{
|
|
|
|
if ( mTabColors.contains( id ) )
|
|
|
|
return mTabColors[id];
|
|
|
|
|
|
|
|
return tqcolorGroup().foreground();
|
|
|
|
}
|
|
|
|
|
|
|
|
int KTabBar::insertTab( TQTab *t, int index )
|
|
|
|
{
|
|
|
|
int res = TQTabBar::insertTab( t, index );
|
|
|
|
|
|
|
|
if ( mTabCloseActivatePrevious && count() > 2 ) {
|
|
|
|
TQPtrList<TQTab> *tablist = tabList();
|
|
|
|
tablist->insert( count()-2, tablist->take( tablist->findRef( t ) ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
void KTabBar::removeTab( TQTab *t )
|
|
|
|
{
|
|
|
|
mTabColors.remove( t->identifier() );
|
|
|
|
TQTabBar::removeTab( t );
|
|
|
|
}
|
|
|
|
|
|
|
|
void KTabBar::paintLabel( TQPainter *p, const TQRect& br,
|
|
|
|
TQTab *t, bool has_focus ) const
|
|
|
|
{
|
|
|
|
TQRect r = br;
|
|
|
|
bool selected = currentTab() == t->identifier();
|
|
|
|
if ( t->iconSet() ) {
|
|
|
|
// the tab has an iconset, draw it in the right mode
|
|
|
|
TQIconSet::Mode mode = ( t->isEnabled() && 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 inactiveXShift = tqstyle().tqpixelMetric( TQStyle::PM_TabBarTabShiftHorizontal, this );
|
|
|
|
int inactiveYShift = tqstyle().tqpixelMetric( TQStyle::PM_TabBarTabShiftVertical, this );
|
|
|
|
|
|
|
|
int right = t->text().isEmpty() ? br.right() - pixw : br.left() + 2;
|
|
|
|
|
|
|
|
p->drawPixmap( right + (selected ? 0 : inactiveXShift),
|
|
|
|
br.center().y() - pixh / 2 + (selected ? 0 : inactiveYShift),
|
|
|
|
pixmap );
|
|
|
|
}
|
|
|
|
|
|
|
|
TQStyle::SFlags flags = TQStyle::Style_Default;
|
|
|
|
|
|
|
|
if ( isEnabled() && t->isEnabled() )
|
|
|
|
flags |= TQStyle::Style_Enabled;
|
|
|
|
if ( has_focus )
|
|
|
|
flags |= TQStyle::Style_HasFocus;
|
|
|
|
|
|
|
|
TQColorGroup cg( tqcolorGroup() );
|
|
|
|
if ( mTabColors.contains( t->identifier() ) )
|
|
|
|
cg.setColor( TQColorGroup::Foreground, mTabColors[t->identifier()] );
|
|
|
|
|
|
|
|
tqstyle().tqdrawControl( TQStyle::CE_TabBarLabel, p, this, r,
|
|
|
|
t->isEnabled() ? cg : tqpalette().disabled(),
|
|
|
|
flags, TQStyleOption(t) );
|
|
|
|
}
|
|
|
|
|
|
|
|
bool KTabBar::isTabReorderingEnabled() const
|
|
|
|
{
|
|
|
|
return mTabReorderingEnabled;
|
|
|
|
}
|
|
|
|
|
|
|
|
void KTabBar::setTabReorderingEnabled( bool on )
|
|
|
|
{
|
|
|
|
mTabReorderingEnabled = on;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool KTabBar::tabCloseActivatePrevious() const
|
|
|
|
{
|
|
|
|
return mTabCloseActivatePrevious;
|
|
|
|
}
|
|
|
|
|
|
|
|
void KTabBar::setTabCloseActivatePrevious( bool on )
|
|
|
|
{
|
|
|
|
mTabCloseActivatePrevious = on;
|
|
|
|
}
|
|
|
|
|
|
|
|
void KTabBar::closeButtonClicked()
|
|
|
|
{
|
|
|
|
emit closeRequest( indexOf( mHoverCloseButtonTab->identifier() ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
void KTabBar::setHoverCloseButton( bool button )
|
|
|
|
{
|
|
|
|
mHoverCloseButtonEnabled = button;
|
|
|
|
if ( !button )
|
|
|
|
onLayoutChange();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool KTabBar::hoverCloseButton() const
|
|
|
|
{
|
|
|
|
return mHoverCloseButtonEnabled;
|
|
|
|
}
|
|
|
|
|
|
|
|
void KTabBar::setHoverCloseButtonDelayed( bool delayed )
|
|
|
|
{
|
|
|
|
mHoverCloseButtonDelayed = delayed;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool KTabBar::hoverCloseButtonDelayed() const
|
|
|
|
{
|
|
|
|
return mHoverCloseButtonDelayed;
|
|
|
|
}
|
|
|
|
|
|
|
|
void KTabBar::onLayoutChange()
|
|
|
|
{
|
|
|
|
mEnableCloseButtonTimer->stop();
|
|
|
|
delete mHoverCloseButton;
|
|
|
|
mHoverCloseButton = 0;
|
|
|
|
mHoverCloseButtonTab = 0;
|
|
|
|
mActivateDragSwitchTabTimer->stop();
|
|
|
|
mDragSwitchTab = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
#include "ktabbar.moc"
|