~ubuntu-branches/ubuntu/oneiric/qwt/oneiric-proposed

« back to all changes in this revision

Viewing changes to src/qwt_panner.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Fathi Boudra
  • Date: 2011-06-10 11:22:47 UTC
  • mfrom: (1.1.6 upstream) (2.1.4 sid)
  • Revision ID: james.westby@ubuntu.com-20110610112247-0i1019vvmzaq6p86
Tags: 6.0.0-1
* New upstream release (Closes: #624107):
  - drop Qt3 support. (Closes: #604379, #626868)
* Register documentation with doc-base. (Closes: #626567)
* Drop patches:
  - 01_makefiles.diff
  - 02_add_missing_warnings.diff
  - 03_qwt_branch_pull_r544.diff
* Add qwt_install_paths.patch to fix the hardcoded installation paths.
* Update debian/control:
  - drop libqt3-mt-dev build dependency.
  - bump Standards-Version to 3.9.2 (no changes).
  - drop Qt3 related packages.
  - due to bump soname (and as we dropper Qt3 support):
    - libqwt5-qt4-dev -> libqwt-dev
    - libqwt5-qt4 -> libqwt6
    - libqwt5-doc -> libqwt-doc
* Update debian/copyright file.
* Update debian/rules: drop Qt3 packages support.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* -*- mode: C++ ; c-file-style: "stroustrup" -*- *****************************
 
2
 * Qwt Widget Library
 
3
 * Copyright (C) 1997   Josef Wilgen
 
4
 * Copyright (C) 2002   Uwe Rathmann
 
5
 *
 
6
 * This library is free software; you can redistribute it and/or
 
7
 * modify it under the terms of the Qwt License, Version 1.0
 
8
 *****************************************************************************/
 
9
 
 
10
#include "qwt_panner.h"
 
11
#include "qwt_picker.h"
 
12
#include <qpainter.h>
 
13
#include <qpixmap.h>
 
14
#include <qevent.h>
 
15
#include <qcursor.h>
 
16
#include <qbitmap.h>
 
17
 
 
18
static QVector<QwtPicker *> qwtActivePickers( QWidget *w )
 
19
{
 
20
    QVector<QwtPicker *> pickers;
 
21
 
 
22
    QObjectList children = w->children();
 
23
    for ( int i = 0; i < children.size(); i++ )
 
24
    {
 
25
        QObject *obj = children[i];
 
26
        if ( obj->inherits( "QwtPicker" ) )
 
27
        {
 
28
            QwtPicker *picker = ( QwtPicker * )obj;
 
29
            if ( picker->isEnabled() )
 
30
                pickers += picker;
 
31
        }
 
32
    }
 
33
 
 
34
    return pickers;
 
35
}
 
36
 
 
37
class QwtPanner::PrivateData
 
38
{
 
39
public:
 
40
    PrivateData():
 
41
        button( Qt::LeftButton ),
 
42
        buttonState( Qt::NoButton ),
 
43
        abortKey( Qt::Key_Escape ),
 
44
        abortKeyState( Qt::NoButton ),
 
45
#ifndef QT_NO_CURSOR
 
46
        cursor( NULL ),
 
47
        restoreCursor( NULL ),
 
48
        hasCursor( false ),
 
49
#endif
 
50
        isEnabled( false )
 
51
    {
 
52
        orientations = Qt::Vertical | Qt::Horizontal;
 
53
    }
 
54
 
 
55
    ~PrivateData()
 
56
    {
 
57
#ifndef QT_NO_CURSOR
 
58
        delete cursor;
 
59
        delete restoreCursor;
 
60
#endif
 
61
    }
 
62
 
 
63
    int button;
 
64
    int buttonState;
 
65
    int abortKey;
 
66
    int abortKeyState;
 
67
 
 
68
    QPoint initialPos;
 
69
    QPoint pos;
 
70
 
 
71
    QPixmap pixmap;
 
72
    QBitmap contentsMask;
 
73
 
 
74
#ifndef QT_NO_CURSOR
 
75
    QCursor *cursor;
 
76
    QCursor *restoreCursor;
 
77
    bool hasCursor;
 
78
#endif
 
79
    bool isEnabled;
 
80
    Qt::Orientations orientations;
 
81
};
 
82
 
 
83
/*!
 
84
  Creates an panner that is enabled for the left mouse button.
 
85
 
 
86
  \param parent Parent widget to be panned
 
87
*/
 
88
QwtPanner::QwtPanner( QWidget *parent ):
 
89
    QWidget( parent )
 
90
{
 
91
    d_data = new PrivateData();
 
92
 
 
93
    setAttribute( Qt::WA_TransparentForMouseEvents );
 
94
    setAttribute( Qt::WA_NoSystemBackground );
 
95
    setFocusPolicy( Qt::NoFocus );
 
96
    hide();
 
97
 
 
98
    setEnabled( true );
 
99
}
 
100
 
 
101
//! Destructor
 
102
QwtPanner::~QwtPanner()
 
103
{
 
104
    delete d_data;
 
105
}
 
106
 
 
107
/*!
 
108
   Change the mouse button
 
109
   The defaults are Qt::LeftButton and Qt::NoButton
 
110
*/
 
111
void QwtPanner::setMouseButton( int button, int buttonState )
 
112
{
 
113
    d_data->button = button;
 
114
    d_data->buttonState = buttonState;
 
115
}
 
116
 
 
117
//! Get the mouse button
 
118
void QwtPanner::getMouseButton( int &button, int &buttonState ) const
 
119
{
 
120
    button = d_data->button;
 
121
    buttonState = d_data->buttonState;
 
122
}
 
123
 
 
124
/*!
 
125
   Change the abort key
 
126
   The defaults are Qt::Key_Escape and Qt::NoButton
 
127
 
 
128
   \param key Key ( See Qt::Keycode )
 
129
   \param state State
 
130
*/
 
131
void QwtPanner::setAbortKey( int key, int state )
 
132
{
 
133
    d_data->abortKey = key;
 
134
    d_data->abortKeyState = state;
 
135
}
 
136
 
 
137
//! Get the abort key
 
138
void QwtPanner::getAbortKey( int &key, int &state ) const
 
139
{
 
140
    key = d_data->abortKey;
 
141
    state = d_data->abortKeyState;
 
142
}
 
143
 
 
144
/*!
 
145
   Change the cursor, that is active while panning
 
146
   The default is the cursor of the parent widget.
 
147
 
 
148
   \param cursor New cursor
 
149
 
 
150
   \sa setCursor()
 
151
*/
 
152
#ifndef QT_NO_CURSOR
 
153
void QwtPanner::setCursor( const QCursor &cursor )
 
154
{
 
155
    d_data->cursor = new QCursor( cursor );
 
156
}
 
157
#endif
 
158
 
 
159
/*!
 
160
   \return Cursor that is active while panning
 
161
   \sa setCursor()
 
162
*/
 
163
#ifndef QT_NO_CURSOR
 
164
const QCursor QwtPanner::cursor() const
 
165
{
 
166
    if ( d_data->cursor )
 
167
        return *d_data->cursor;
 
168
 
 
169
    if ( parentWidget() )
 
170
        return parentWidget()->cursor();
 
171
 
 
172
    return QCursor();
 
173
}
 
174
#endif
 
175
 
 
176
/*!
 
177
  \brief En/disable the panner
 
178
 
 
179
  When enabled is true an event filter is installed for
 
180
  the observed widget, otherwise the event filter is removed.
 
181
 
 
182
  \param on true or false
 
183
  \sa isEnabled(), eventFilter()
 
184
*/
 
185
void QwtPanner::setEnabled( bool on )
 
186
{
 
187
    if ( d_data->isEnabled != on )
 
188
    {
 
189
        d_data->isEnabled = on;
 
190
 
 
191
        QWidget *w = parentWidget();
 
192
        if ( w )
 
193
        {
 
194
            if ( d_data->isEnabled )
 
195
            {
 
196
                w->installEventFilter( this );
 
197
            }
 
198
            else
 
199
            {
 
200
                w->removeEventFilter( this );
 
201
                hide();
 
202
            }
 
203
        }
 
204
    }
 
205
}
 
206
 
 
207
/*!
 
208
   Set the orientations, where panning is enabled
 
209
   The default value is in both directions: Qt::Horizontal | Qt::Vertical
 
210
 
 
211
   /param o Orientation
 
212
*/
 
213
void QwtPanner::setOrientations( Qt::Orientations o )
 
214
{
 
215
    d_data->orientations = o;
 
216
}
 
217
 
 
218
//! Return the orientation, where paning is enabled
 
219
Qt::Orientations QwtPanner::orientations() const
 
220
{
 
221
    return d_data->orientations;
 
222
}
 
223
 
 
224
/*!
 
225
   Return true if a orientatio is enabled
 
226
   \sa orientations(), setOrientations()
 
227
*/
 
228
bool QwtPanner::isOrientationEnabled( Qt::Orientation o ) const
 
229
{
 
230
    return d_data->orientations & o;
 
231
}
 
232
 
 
233
/*!
 
234
  \return true when enabled, false otherwise
 
235
  \sa setEnabled, eventFilter()
 
236
*/
 
237
bool QwtPanner::isEnabled() const
 
238
{
 
239
    return d_data->isEnabled;
 
240
}
 
241
 
 
242
/*!
 
243
   \brief Paint event
 
244
 
 
245
   Repaint the grabbed pixmap on its current position and
 
246
   fill the empty spaces by the background of the parent widget.
 
247
 
 
248
   \param pe Paint event
 
249
*/
 
250
void QwtPanner::paintEvent( QPaintEvent *pe )
 
251
{
 
252
    int dx = d_data->pos.x() - d_data->initialPos.x();
 
253
    int dy = d_data->pos.y() - d_data->initialPos.y();
 
254
 
 
255
    QRect r( 0, 0, d_data->pixmap.width(), d_data->pixmap.height() );
 
256
    r.moveCenter( QPoint( r.center().x() + dx, r.center().y() + dy ) );
 
257
 
 
258
    QPixmap pm( size() );
 
259
    pm.fill( parentWidget(), 0, 0 );
 
260
 
 
261
    QPainter painter( &pm );
 
262
 
 
263
    if ( !d_data->contentsMask.isNull() )
 
264
    {
 
265
        QPixmap masked = d_data->pixmap;
 
266
        masked.setMask( d_data->contentsMask );
 
267
        painter.drawPixmap( r, masked );
 
268
    }
 
269
    else
 
270
    {
 
271
        painter.drawPixmap( r, d_data->pixmap );
 
272
    }
 
273
 
 
274
    painter.end();
 
275
 
 
276
    if ( !d_data->contentsMask.isNull() )
 
277
        pm.setMask( d_data->contentsMask );
 
278
 
 
279
    painter.begin( this );
 
280
    painter.setClipRegion( pe->region() );
 
281
    painter.drawPixmap( 0, 0, pm );
 
282
}
 
283
 
 
284
/*!
 
285
  \brief Calculate a mask for the contents of the panned widget
 
286
 
 
287
  Sometimes only parts of the contents of a widget should be
 
288
  panned. F.e. for a widget with a styled background with rounded borders
 
289
  only the area inside of the border should be panned.
 
290
 
 
291
  \return An empty bitmap, indicating no mask
 
292
*/
 
293
QBitmap QwtPanner::contentsMask() const
 
294
{
 
295
    return QBitmap();
 
296
}
 
297
 
 
298
/*!
 
299
  Grab the widget into a pixmap.
 
300
*/
 
301
QPixmap QwtPanner::grab() const
 
302
{
 
303
    return QPixmap::grabWidget( parentWidget() );
 
304
}
 
305
 
 
306
/*!
 
307
  \brief Event filter
 
308
 
 
309
  When isEnabled() the mouse events of the observed widget are filtered.
 
310
 
 
311
  \sa widgetMousePressEvent(), widgetMouseReleaseEvent(),
 
312
      widgetMouseMoveEvent()
 
313
*/
 
314
bool QwtPanner::eventFilter( QObject *o, QEvent *e )
 
315
{
 
316
    if ( o == NULL || o != parentWidget() )
 
317
        return false;
 
318
 
 
319
    switch ( e->type() )
 
320
    {
 
321
        case QEvent::MouseButtonPress:
 
322
        {
 
323
            widgetMousePressEvent( ( QMouseEvent * )e );
 
324
            break;
 
325
        }
 
326
        case QEvent::MouseMove:
 
327
        {
 
328
            widgetMouseMoveEvent( ( QMouseEvent * )e );
 
329
            break;
 
330
        }
 
331
        case QEvent::MouseButtonRelease:
 
332
        {
 
333
            widgetMouseReleaseEvent( ( QMouseEvent * )e );
 
334
            break;
 
335
        }
 
336
        case QEvent::KeyPress:
 
337
        {
 
338
            widgetKeyPressEvent( ( QKeyEvent * )e );
 
339
            break;
 
340
        }
 
341
        case QEvent::KeyRelease:
 
342
        {
 
343
            widgetKeyReleaseEvent( ( QKeyEvent * )e );
 
344
            break;
 
345
        }
 
346
        case QEvent::Paint:
 
347
        {
 
348
            if ( isVisible() )
 
349
                return true;
 
350
            break;
 
351
        }
 
352
        default:;
 
353
    }
 
354
 
 
355
    return false;
 
356
}
 
357
 
 
358
/*!
 
359
  Handle a mouse press event for the observed widget.
 
360
 
 
361
  \param me Mouse event
 
362
  \sa eventFilter(), widgetMouseReleaseEvent(),
 
363
      widgetMouseMoveEvent(),
 
364
*/
 
365
void QwtPanner::widgetMousePressEvent( QMouseEvent *me )
 
366
{
 
367
    if ( me->button() != d_data->button )
 
368
        return;
 
369
 
 
370
    QWidget *w = parentWidget();
 
371
    if ( w == NULL )
 
372
        return;
 
373
 
 
374
    if ( ( me->modifiers() & Qt::KeyboardModifierMask ) !=
 
375
        ( int )( d_data->buttonState & Qt::KeyboardModifierMask ) )
 
376
    {
 
377
        return;
 
378
    }
 
379
 
 
380
#ifndef QT_NO_CURSOR
 
381
    showCursor( true );
 
382
#endif
 
383
 
 
384
    d_data->initialPos = d_data->pos = me->pos();
 
385
 
 
386
    setGeometry( parentWidget()->rect() );
 
387
 
 
388
    // We don't want to grab the picker !
 
389
    QVector<QwtPicker *> pickers = qwtActivePickers( parentWidget() );
 
390
    for ( int i = 0; i < ( int )pickers.size(); i++ )
 
391
        pickers[i]->setEnabled( false );
 
392
 
 
393
    d_data->pixmap = grab();
 
394
    d_data->contentsMask = contentsMask();
 
395
 
 
396
    for ( int i = 0; i < ( int )pickers.size(); i++ )
 
397
        pickers[i]->setEnabled( true );
 
398
 
 
399
    show();
 
400
}
 
401
 
 
402
/*!
 
403
  Handle a mouse move event for the observed widget.
 
404
 
 
405
  \param me Mouse event
 
406
  \sa eventFilter(), widgetMousePressEvent(), widgetMouseReleaseEvent()
 
407
*/
 
408
void QwtPanner::widgetMouseMoveEvent( QMouseEvent *me )
 
409
{
 
410
    if ( !isVisible() )
 
411
        return;
 
412
 
 
413
    QPoint pos = me->pos();
 
414
    if ( !isOrientationEnabled( Qt::Horizontal ) )
 
415
        pos.setX( d_data->initialPos.x() );
 
416
    if ( !isOrientationEnabled( Qt::Vertical ) )
 
417
        pos.setY( d_data->initialPos.y() );
 
418
 
 
419
    if ( pos != d_data->pos && rect().contains( pos ) )
 
420
    {
 
421
        d_data->pos = pos;
 
422
        update();
 
423
 
 
424
        Q_EMIT moved( d_data->pos.x() - d_data->initialPos.x(),
 
425
            d_data->pos.y() - d_data->initialPos.y() );
 
426
    }
 
427
}
 
428
 
 
429
/*!
 
430
  Handle a mouse release event for the observed widget.
 
431
 
 
432
  \param me Mouse event
 
433
  \sa eventFilter(), widgetMousePressEvent(),
 
434
      widgetMouseMoveEvent(),
 
435
*/
 
436
void QwtPanner::widgetMouseReleaseEvent( QMouseEvent *me )
 
437
{
 
438
    if ( isVisible() )
 
439
    {
 
440
        hide();
 
441
#ifndef QT_NO_CURSOR
 
442
        showCursor( false );
 
443
#endif
 
444
 
 
445
        QPoint pos = me->pos();
 
446
        if ( !isOrientationEnabled( Qt::Horizontal ) )
 
447
            pos.setX( d_data->initialPos.x() );
 
448
        if ( !isOrientationEnabled( Qt::Vertical ) )
 
449
            pos.setY( d_data->initialPos.y() );
 
450
 
 
451
        d_data->pixmap = QPixmap();
 
452
        d_data->contentsMask = QBitmap();
 
453
        d_data->pos = pos;
 
454
 
 
455
        if ( d_data->pos != d_data->initialPos )
 
456
        {
 
457
            Q_EMIT panned( d_data->pos.x() - d_data->initialPos.x(),
 
458
                d_data->pos.y() - d_data->initialPos.y() );
 
459
        }
 
460
    }
 
461
}
 
462
 
 
463
/*!
 
464
  Handle a key press event for the observed widget.
 
465
 
 
466
  \param ke Key event
 
467
  \sa eventFilter(), widgetKeyReleaseEvent()
 
468
*/
 
469
void QwtPanner::widgetKeyPressEvent( QKeyEvent *ke )
 
470
{
 
471
    if ( ke->key() == d_data->abortKey )
 
472
    {
 
473
        const bool matched =
 
474
            ( ke->modifiers() & Qt::KeyboardModifierMask ) ==
 
475
                ( int )( d_data->abortKeyState & Qt::KeyboardModifierMask );
 
476
        if ( matched )
 
477
        {
 
478
            hide();
 
479
#ifndef QT_NO_CURSOR
 
480
            showCursor( false );
 
481
#endif
 
482
            d_data->pixmap = QPixmap();
 
483
        }
 
484
    }
 
485
}
 
486
 
 
487
/*!
 
488
  Handle a key release event for the observed widget.
 
489
  \sa eventFilter(), widgetKeyReleaseEvent()
 
490
*/
 
491
void QwtPanner::widgetKeyReleaseEvent( QKeyEvent * )
 
492
{
 
493
}
 
494
 
 
495
#ifndef QT_NO_CURSOR
 
496
void QwtPanner::showCursor( bool on )
 
497
{
 
498
    if ( on == d_data->hasCursor )
 
499
        return;
 
500
 
 
501
    QWidget *w = parentWidget();
 
502
    if ( w == NULL || d_data->cursor == NULL )
 
503
        return;
 
504
 
 
505
    d_data->hasCursor = on;
 
506
 
 
507
    if ( on )
 
508
    {
 
509
        if ( w->testAttribute( Qt::WA_SetCursor ) )
 
510
        {
 
511
            delete d_data->restoreCursor;
 
512
            d_data->restoreCursor = new QCursor( w->cursor() );
 
513
        }
 
514
        w->setCursor( *d_data->cursor );
 
515
    }
 
516
    else
 
517
    {
 
518
        if ( d_data->restoreCursor )
 
519
        {
 
520
            w->setCursor( *d_data->restoreCursor );
 
521
            delete d_data->restoreCursor;
 
522
            d_data->restoreCursor = NULL;
 
523
        }
 
524
        else
 
525
            w->unsetCursor();
 
526
    }
 
527
}
 
528
#endif