~ubuntu-branches/ubuntu/karmic/psi/karmic

« back to all changes in this revision

Viewing changes to libpsi/psiwidgets/psitabbar.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Jan Niehusmann
  • Date: 2008-04-14 18:57:30 UTC
  • mfrom: (2.1.9 hardy)
  • Revision ID: james.westby@ubuntu.com-20080414185730-528re3zp0m2hdlhi
Tags: 0.11-8
* added CONFIG -= link_prl to .pro files and removed dependencies
  which are made unnecessary by this change
* Fix segfault when closing last chat tab with qt4.4
  (This is from upstream svn, rev. 1101) (Closes: Bug#476122)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* Copyright (C) 2005 Kevin Smith
2
 
                notice goes here
3
 
         */
4
 
 
5
 
 
6
 
/* This file is heavily based on part of the KDE libraries
7
 
    Copyright (C) 2003 Stephan Binner <binner@kde.org>
8
 
    Copyright (C) 2003 Zack Rusin <zack@kde.org>
9
 
*/
10
 
 
11
 
#include <qapplication.h>
12
 
#include <qcursor.h>
13
 
#include <qpainter.h>
14
 
#include <qstyle.h>
15
 
#include <qtimer.h>
16
 
#include <qpushbutton.h>
17
 
#include <qtooltip.h>
18
 
 
19
 
#include "psitabbar.h"
20
 
#include "psitabwidget.h"
21
 
 
22
 
KTabBar::KTabBar( QWidget *parent, const char *name )
23
 
    : QTabBar( parent, name ), mReorderStartTab( -1 ), mReorderPreviousTab( -1 ),
24
 
      mHoverCloseButtonTab( 0 ), mDragSwitchTab( 0 ), mHoverCloseButton( 0 ),
25
 
      mHoverCloseButtonEnabled( false ), mHoverCloseButtonDelayed( true ),
26
 
      mTabReorderingEnabled( false ), mTabCloseActivatePrevious( false )
27
 
{
28
 
    setAcceptDrops( true );
29
 
    setMouseTracking( true );
30
 
 
31
 
    mEnableCloseButtonTimer = new QTimer( this );
32
 
    connect( mEnableCloseButtonTimer, SIGNAL( timeout() ), SLOT( enableCloseButton() ) );
33
 
 
34
 
    mActivateDragSwitchTabTimer = new QTimer( this );
35
 
    connect( mActivateDragSwitchTabTimer, SIGNAL( timeout() ), SLOT( activateDragSwitchTab() ) );
36
 
 
37
 
    connect(this, SIGNAL(layoutChanged()), SLOT(onLayoutChange()));
38
 
                dndEventDelay=5;
39
 
}
40
 
 
41
 
KTabBar::~KTabBar()
42
 
{
43
 
    //For the future
44
 
    //delete d;
45
 
}
46
 
 
47
 
void KTabBar::setCloseIcon(const QIconSet& icon)
48
 
{
49
 
        closeIcon=icon;
50
 
}
51
 
 
52
 
void KTabBar::setTabEnabled( int id, bool enabled )
53
 
{
54
 
    QTab * t = tab( id );
55
 
    if ( t ) {
56
 
        if ( t->isEnabled() != enabled ) {
57
 
            t->setEnabled( enabled );
58
 
            QRect r( t->rect() );
59
 
            if ( !enabled && id == currentTab() && count()>1 ) {
60
 
                QPtrList<QTab> *tablist = tabList();
61
 
                if ( mTabCloseActivatePrevious )
62
 
                    t = tablist->at( count()-2 );
63
 
                else {
64
 
                int index = indexOf( id );
65
 
                index += ( index+1 == count() ) ? -1 : 1;
66
 
                t = tabAt( index );
67
 
                }
68
 
 
69
 
                if ( t->isEnabled() ) {
70
 
                    r = r.unite( t->rect() );
71
 
                    tablist->append( tablist->take( tablist->findRef( t ) ) );
72
 
                    emit selected( t->identifier() );
73
 
                }
74
 
            }
75
 
            repaint( r );
76
 
        }
77
 
    }
78
 
}
79
 
 
80
 
void KTabBar::mouseDoubleClickEvent( QMouseEvent *e )
81
 
{
82
 
    if( e->button() != LeftButton )
83
 
        return;
84
 
 
85
 
    QTab *tab = selectTab( e->pos() );
86
 
    if( tab ) {
87
 
        emit( mouseDoubleClick( indexOf( tab->identifier() ) ) );
88
 
        return;
89
 
    }
90
 
    QTabBar::mouseDoubleClickEvent( e );
91
 
}
92
 
 
93
 
void KTabBar::mousePressEvent( QMouseEvent *e )
94
 
{
95
 
    if( e->button() == LeftButton ) {
96
 
        mEnableCloseButtonTimer->stop();
97
 
        mDragStart = e->pos();
98
 
    }
99
 
    else if( e->button() == RightButton ) {
100
 
        QTab *tab = selectTab( e->pos() );
101
 
        if( tab ) {
102
 
            emit( contextMenu( indexOf( tab->identifier() ), mapToGlobal( e->pos() ) ) );
103
 
            return;
104
 
        }
105
 
    }
106
 
    QTabBar::mousePressEvent( e );
107
 
}
108
 
 
109
 
void KTabBar::mouseMoveEvent( QMouseEvent *e )
110
 
{
111
 
    if ( e->state() == LeftButton ) {
112
 
        QTab *tab = selectTab( e->pos() );
113
 
        if ( mDragSwitchTab && tab != mDragSwitchTab ) {
114
 
          mActivateDragSwitchTabTimer->stop();
115
 
          mDragSwitchTab = 0;
116
 
        }
117
 
 
118
 
        QPoint newPos = e->pos();
119
 
        if( newPos.x() > mDragStart.x()+dndEventDelay || newPos.x() < mDragStart.x()-dndEventDelay ||
120
 
            newPos.y() > mDragStart.y()+dndEventDelay || newPos.y() < mDragStart.y()-dndEventDelay )
121
 
         {
122
 
            if( tab ) {
123
 
                emit( initiateDrag( indexOf( tab->identifier() ) ) );
124
 
                return;
125
 
           }
126
 
       }
127
 
    }
128
 
    else if ( e->state() == MidButton ) {
129
 
        if (mReorderStartTab==-1) {
130
 
            QPoint newPos = e->pos();
131
 
            if( newPos.x() > mDragStart.x()+dndEventDelay || newPos.x() < mDragStart.x()-dndEventDelay ||
132
 
                newPos.y() > mDragStart.y()+dndEventDelay || newPos.y() < mDragStart.y()-dndEventDelay )
133
 
            {
134
 
                QTab *tab = selectTab( e->pos() );
135
 
                if( tab && mTabReorderingEnabled ) {
136
 
                    mReorderStartTab = indexOf( tab->identifier() );
137
 
                    grabMouse( sizeAllCursor );
138
 
                    return;
139
 
                }
140
 
            }
141
 
        }
142
 
        else {
143
 
            QTab *tab = selectTab( e->pos() );
144
 
            if( tab ) {
145
 
                int reorderStopTab = indexOf( tab->identifier() );
146
 
                if ( mReorderStartTab!=reorderStopTab && mReorderPreviousTab!=reorderStopTab ) {
147
 
                    emit( moveTab( mReorderStartTab, reorderStopTab ) );
148
 
                    mReorderPreviousTab=mReorderStartTab;
149
 
                    mReorderStartTab=reorderStopTab;
150
 
                    return;
151
 
                }
152
 
            }
153
 
        }
154
 
    }
155
 
 
156
 
    if ( mHoverCloseButtonEnabled && mReorderStartTab==-1) {
157
 
        QTab *t = selectTab( e->pos() );
158
 
        if( t && t->iconSet() && t->isEnabled() ) {
159
 
            QPixmap pixmap = t->iconSet()->pixmap( QIconSet::Small, QIconSet::Normal );
160
 
#ifndef Q_WS_MAC
161
 
            QRect rect( 0, 0, pixmap.width() + 4, pixmap.height() +4);
162
 
#else
163
 
                        QRect rect( 0, 0, pixmap.width(), pixmap.height());
164
 
#endif
165
 
                        int xoff = 0, yoff = 0;
166
 
            // The additional offsets were found by try and error, TODO: find the rational behind them
167
 
            if ( t == tab( currentTab() ) ) {
168
 
                xoff = style().pixelMetric( QStyle::PM_TabBarTabShiftHorizontal, this ) + 3;
169
 
                yoff = style().pixelMetric( QStyle::PM_TabBarTabShiftVertical, this ) - 4;
170
 
            }
171
 
            else {
172
 
                xoff = 7;
173
 
                yoff = 0;
174
 
            }
175
 
#ifdef Q_WS_MAC
176
 
                        yoff=0; //kev hacks for OSX
177
 
                        xoff=7; //also kev
178
 
#endif
179
 
            rect.moveLeft( t->rect().left() + 2 + xoff );
180
 
            rect.moveTop( t->rect().center().y()-pixmap.height()/2 + yoff );
181
 
            if ( rect.contains( e->pos() ) ) {
182
 
                if ( mHoverCloseButton ) {
183
 
                    if ( mHoverCloseButtonTab == t )
184
 
                        return;
185
 
                    mEnableCloseButtonTimer->stop();
186
 
                    delete mHoverCloseButton;
187
 
                }
188
 
 
189
 
                //This is the code that shows the close button.
190
 
                                // The problems with MAC, 'fix'ed above appear here
191
 
                                mHoverCloseButton = new QPushButton( this );
192
 
                mHoverCloseButton->setIconSet( closeIcon);
193
 
                mHoverCloseButton->setGeometry( rect );
194
 
                QToolTip::add(mHoverCloseButton,tr("Close this tab"));
195
 
                mHoverCloseButton->setFlat(true);
196
 
                mHoverCloseButton->show();
197
 
                if ( mHoverCloseButtonDelayed ) {
198
 
                  mHoverCloseButton->setEnabled(false);
199
 
                  mEnableCloseButtonTimer->start( QApplication::doubleClickInterval(), true );
200
 
                }
201
 
                mHoverCloseButtonTab = t;
202
 
                connect( mHoverCloseButton, SIGNAL( clicked() ), SLOT( closeButtonClicked() ) );
203
 
                return;
204
 
            }
205
 
        }
206
 
        if ( mHoverCloseButton ) {
207
 
            mEnableCloseButtonTimer->stop();
208
 
            delete mHoverCloseButton;
209
 
            mHoverCloseButton = 0;
210
 
        }
211
 
    }
212
 
 
213
 
    QTabBar::mouseMoveEvent( e );
214
 
}
215
 
 
216
 
void KTabBar::enableCloseButton()
217
 
{
218
 
    mHoverCloseButton->setEnabled(true);
219
 
}
220
 
 
221
 
void KTabBar::activateDragSwitchTab()
222
 
{
223
 
    QTab *tab = selectTab( mapFromGlobal( QCursor::pos() ) );
224
 
    if ( tab && mDragSwitchTab == tab )
225
 
    setCurrentTab( mDragSwitchTab );
226
 
    mDragSwitchTab = 0;
227
 
}
228
 
 
229
 
void KTabBar::mouseReleaseEvent( QMouseEvent *e )
230
 
{
231
 
    if( e->button() == MidButton ) {
232
 
        if ( mReorderStartTab==-1 ) {
233
 
            QTab *tab = selectTab( e->pos() );
234
 
            if( tab ) {
235
 
                emit( mouseMiddleClick( indexOf( tab->identifier() ) ) );
236
 
                return;
237
 
            }
238
 
        }
239
 
        else {
240
 
            releaseMouse();
241
 
            setCursor( arrowCursor );
242
 
            mReorderStartTab=-1;
243
 
            mReorderPreviousTab=-1;
244
 
        }
245
 
    }
246
 
    QTabBar::mouseReleaseEvent( e );
247
 
}
248
 
 
249
 
void KTabBar::dragMoveEvent( QDragMoveEvent *e )
250
 
{
251
 
    QTab *tab = selectTab( e->pos() );
252
 
    if( tab ) {
253
 
        bool accept = false;
254
 
        // The receivers of the testCanDecode() signal has to adjust
255
 
        // 'accept' accordingly.
256
 
        emit testCanDecode( e, accept);
257
 
        if ( accept && tab != QTabBar::tab( currentTab() ) ) {
258
 
          mDragSwitchTab = tab;
259
 
          mActivateDragSwitchTabTimer->start( QApplication::doubleClickInterval()*2, true );
260
 
        }
261
 
        e->accept( accept );
262
 
        return;
263
 
    }
264
 
    e->accept( false );
265
 
    QTabBar::dragMoveEvent( e );
266
 
}
267
 
 
268
 
void KTabBar::dropEvent( QDropEvent *e )
269
 
{
270
 
    QTab *tab = selectTab( e->pos() );
271
 
    if( tab ) {
272
 
        mActivateDragSwitchTabTimer->stop();
273
 
        mDragSwitchTab = 0;
274
 
        emit( receivedDropEvent( indexOf( tab->identifier() ) , e ) );
275
 
        return;
276
 
    }
277
 
    QTabBar::dropEvent( e );
278
 
}
279
 
 
280
 
#ifndef QT_NO_WHEELEVENT
281
 
void KTabBar::wheelEvent( QWheelEvent *e )
282
 
{
283
 
    if ( e->orientation() == Horizontal )
284
 
        return;
285
 
 
286
 
    emit( wheelDelta( e->delta() ) );
287
 
}
288
 
#endif
289
 
 
290
 
void KTabBar::setTabColor( int id, const QColor& color )
291
 
{
292
 
    QTab *t = tab( id );
293
 
    if ( t ) {
294
 
        mTabColors.insert( id, color );
295
 
        repaint( t->rect(), false );
296
 
    }
297
 
}
298
 
 
299
 
const QColor &KTabBar::tabColor( int id  ) const
300
 
{
301
 
    if ( mTabColors.contains( id ) )
302
 
        return mTabColors[id];
303
 
 
304
 
    return colorGroup().foreground();
305
 
}
306
 
 
307
 
int KTabBar::insertTab( QTab *t, int index )
308
 
{
309
 
    int res = QTabBar::insertTab( t, index );
310
 
 
311
 
    if ( mTabCloseActivatePrevious && count() > 2 ) {
312
 
        QPtrList<QTab> *tablist = tabList();
313
 
        tablist->insert( count()-2, tablist->take( tablist->findRef( t ) ) );
314
 
    }
315
 
 
316
 
    return res;
317
 
}
318
 
 
319
 
void KTabBar::removeTab( QTab *t )
320
 
{
321
 
    mTabColors.remove( t->identifier() );
322
 
    QTabBar::removeTab( t );
323
 
}
324
 
 
325
 
void KTabBar::paintLabel( QPainter *p, const QRect& br,
326
 
                          QTab *t, bool has_focus ) const
327
 
{
328
 
    QRect r = br;
329
 
    bool selected = currentTab() == t->identifier();
330
 
    if ( t->iconSet() ) {
331
 
        // the tab has an iconset, draw it in the right mode
332
 
        QIconSet::Mode mode = ( t->isEnabled() && isEnabled() )
333
 
                                 ? QIconSet::Normal : QIconSet::Disabled;
334
 
        if ( mode == QIconSet::Normal && has_focus )
335
 
            mode = QIconSet::Active;
336
 
        QPixmap pixmap = t->iconSet()->pixmap( QIconSet::Small, mode );
337
 
        int pixw = pixmap.width();
338
 
        int pixh = pixmap.height();
339
 
        r.setLeft( r.left() + pixw + 4 );
340
 
        r.setRight( r.right() + 2 );
341
 
 
342
 
        int inactiveXShift = style().pixelMetric( QStyle::PM_TabBarTabShiftHorizontal, this );
343
 
        int inactiveYShift = style().pixelMetric( QStyle::PM_TabBarTabShiftVertical, this );
344
 
 
345
 
        int right = t->text().isEmpty() ? br.right() - pixw : br.left() + 2;
346
 
 
347
 
        p->drawPixmap( right + (selected ? 0 : inactiveXShift),
348
 
                       br.center().y() - pixh / 2 + (selected ? 0 : inactiveYShift),
349
 
                       pixmap );
350
 
    }
351
 
 
352
 
    QStyle::SFlags flags = QStyle::Style_Default;
353
 
 
354
 
    if ( isEnabled() && t->isEnabled() )
355
 
        flags |= QStyle::Style_Enabled;
356
 
    if ( has_focus )
357
 
        {
358
 
        flags |= QStyle::Style_HasFocus;
359
 
        }
360
 
 
361
 
    QColorGroup cg( colorGroup() );
362
 
    if ( mTabColors.contains( t->identifier() ) )
363
 
        cg.setColor( QColorGroup::Foreground, mTabColors[t->identifier()] );
364
 
 
365
 
    style().drawControl( QStyle::CE_TabBarLabel, p, this, r,
366
 
                             t->isEnabled() ? cg : palette().disabled(),
367
 
                             flags, QStyleOption(t) );
368
 
}
369
 
 
370
 
bool KTabBar::isTabReorderingEnabled() const
371
 
{
372
 
    return mTabReorderingEnabled;
373
 
}
374
 
 
375
 
void KTabBar::setTabReorderingEnabled( bool on )
376
 
{
377
 
    mTabReorderingEnabled = on;
378
 
}
379
 
 
380
 
bool KTabBar::tabCloseActivatePrevious() const
381
 
{
382
 
    return mTabCloseActivatePrevious;
383
 
}
384
 
 
385
 
void KTabBar::setTabCloseActivatePrevious( bool on )
386
 
{
387
 
    mTabCloseActivatePrevious = on;
388
 
}
389
 
 
390
 
void KTabBar::closeButtonClicked()
391
 
{
392
 
    emit closeRequest( indexOf( mHoverCloseButtonTab->identifier() ) );
393
 
}
394
 
 
395
 
void KTabBar::setHoverCloseButton( bool button )
396
 
{
397
 
    mHoverCloseButtonEnabled = button;
398
 
    if ( !button )
399
 
        onLayoutChange();
400
 
}
401
 
 
402
 
bool KTabBar::hoverCloseButton() const
403
 
{
404
 
    return mHoverCloseButtonEnabled;
405
 
}
406
 
 
407
 
void KTabBar::setHoverCloseButtonDelayed( bool delayed )
408
 
{
409
 
    mHoverCloseButtonDelayed = delayed;
410
 
}
411
 
 
412
 
bool KTabBar::hoverCloseButtonDelayed() const
413
 
{
414
 
    return mHoverCloseButtonDelayed;
415
 
}
416
 
 
417
 
void KTabBar::onLayoutChange()
418
 
{
419
 
    mEnableCloseButtonTimer->stop();
420
 
    delete mHoverCloseButton;
421
 
    mHoverCloseButton = 0;
422
 
    mHoverCloseButtonTab = 0;
423
 
    mActivateDragSwitchTabTimer->stop();
424
 
    mDragSwitchTab = 0;
425
 
}
426