Newer
Older
/* -*- mode: C++ ; c-file-style: "stroustrup" -*- *****************************
* Qwt Widget Library
* Copyright (C) 1997 Josef Wilgen
* Copyright (C) 2002 Uwe Rathmann
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the Qwt License, Version 1.0
*****************************************************************************/
// vim: expandtab
#include <qpainter.h>
#include <qpixmap.h>
#include <qevent.h>
#include <qframe.h>
#include <qcursor.h>
#if QT_VERSION < 0x040000
#include <qobjectlist.h>
#endif
#include "qwt_picker.h"
#include "qwt_array.h"
#include "qwt_panner.h"
static QwtArray<QwtPicker *> activePickers(QWidget *w)
{
QwtArray<QwtPicker *> pickers;
#if QT_VERSION >= 0x040000
QObjectList children = w->children();
for ( int i = 0; i < children.size(); i++ ) {
if ( obj->inherits("QwtPicker") ) {
QwtPicker *picker = (QwtPicker *)obj;
if ( picker->isEnabled() )
pickers += picker;
}
}
#else
QObjectList *children = (QObjectList *)w->children();
if ( children ) {
for ( QObjectListIterator it(*children); it.current(); ++it ) {
if ( obj->inherits("QwtPicker") ) {
pickers.resize(pickers.size() + 1);
pickers[int(pickers.size()) - 1] = picker;
}
}
}
}
#endif
return pickers;
}
class QwtPanner::PrivateData
{
public:
PrivateData():
button(Qt::LeftButton),
buttonState(Qt::NoButton),
abortKey(Qt::Key_Escape),
abortKeyState(Qt::NoButton),
#ifndef QT_NO_CURSOR
cursor(NULL),
restoreCursor(NULL),
hasCursor(false),
#endif
#if QT_VERSION >= 0x040000
orientations = Qt::Vertical | Qt::Horizontal;
#else
orientations[Qt::Vertical] = true;
orientations[Qt::Horizontal] = true;
#endif
}
#ifndef QT_NO_CURSOR
delete cursor;
delete restoreCursor;
#endif
}
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
int button;
int buttonState;
int abortKey;
int abortKeyState;
QPoint initialPos;
QPoint pos;
QPixmap pixmap;
#ifndef QT_NO_CURSOR
QCursor *cursor;
QCursor *restoreCursor;
bool hasCursor;
#endif
bool isEnabled;
#if QT_VERSION >= 0x040000
Qt::Orientations orientations;
#else
bool orientations[2];
#endif
};
/*!
Creates an panner that is enabled for the left mouse button.
\param parent Parent widget to be panned
*/
QwtPanner::QwtPanner(QWidget *parent):
QWidget(parent)
{
d_data = new PrivateData();
#if QT_VERSION >= 0x040000
setAttribute(Qt::WA_TransparentForMouseEvents);
setAttribute(Qt::WA_NoSystemBackground);
setFocusPolicy(Qt::NoFocus);
#else
setBackgroundMode(Qt::NoBackground);
setFocusPolicy(QWidget::NoFocus);
#endif
hide();
setEnabled(true);
}
//! Destructor
QwtPanner::~QwtPanner()
{
delete d_data;
}
/*!
Change the mouse button
The defaults are Qt::LeftButton and Qt::NoButton
*/
void QwtPanner::setMouseButton(int button, int buttonState)
{
d_data->button = button;
d_data->buttonState = buttonState;
}
//! Get the mouse button
void QwtPanner::getMouseButton(int &button, int &buttonState) const
{
button = d_data->button;
buttonState = d_data->buttonState;
}
/*!
Change the abort key
The defaults are Qt::Key_Escape and Qt::NoButton
*/
void QwtPanner::setAbortKey(int key, int state)
{
d_data->abortKey = key;
d_data->abortKeyState = state;
}
//! Get the abort key
void QwtPanner::getAbortKey(int &key, int &state) const
{
key = d_data->abortKey;
state = d_data->abortKeyState;
}
/*!
Change the cursor, that is active while panning
The default is the cursor of the parent widget.
\param cursor New cursor
\sa setCursor()
*/
#ifndef QT_NO_CURSOR
void QwtPanner::setCursor(const QCursor &cursor)
{
d_data->cursor = new QCursor(cursor);
}
#endif
/*!
\return Cursor that is active while panning
\sa setCursor()
*/
#ifndef QT_NO_CURSOR
const QCursor QwtPanner::cursor() const
{
if ( d_data->cursor )
return *d_data->cursor;
if ( parentWidget() )
return parentWidget()->cursor();
return QCursor();
}
#endif
When enabled is true an event filter is installed for
the observed widget, otherwise the event filter is removed.
\param on true or false
\sa isEnabled(), eventFilter()
*/
void QwtPanner::setEnabled(bool on)
{
if ( w ) {
if ( d_data->isEnabled ) {
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
w->removeEventFilter(this);
hide();
}
}
}
}
#if QT_VERSION >= 0x040000
/*!
Set the orientations, where panning is enabled
The default value is in both directions: Qt::Horizontal | Qt::Vertical
/param o Orientation
*/
void QwtPanner::setOrientations(Qt::Orientations o)
{
d_data->orientations = o;
}
//! Return the orientation, where paning is enabled
Qt::Orientations QwtPanner::orientations() const
{
return d_data->orientations;
}
#else
void QwtPanner::enableOrientation(Qt::Orientation o, bool enable)
{
if ( o == Qt::Vertical || o == Qt::Horizontal )
d_data->orientations[o] = enable;
}
#endif
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
Return true if a orientatio is enabled
\sa orientations(), setOrientations()
*/
bool QwtPanner::isOrientationEnabled(Qt::Orientation o) const
{
#if QT_VERSION >= 0x040000
return d_data->orientations & o;
#else
if ( o == Qt::Vertical || o == Qt::Horizontal )
return d_data->orientations[o];
return false;
#endif
}
/*!
\return true when enabled, false otherwise
\sa setEnabled, eventFilter()
*/
bool QwtPanner::isEnabled() const
{
return d_data->isEnabled;
}
/*!
\brief Paint event
Repaint the grabbed pixmap on its current position and
fill the empty spaces by the background of the parent widget.
\param pe Paint event
*/
void QwtPanner::paintEvent(QPaintEvent *pe)
{
QPixmap pm(size());
QPainter painter(&pm);
const QColor bg =
#if QT_VERSION < 0x040000
parentWidget()->palette().color(
QPalette::Normal, QColorGroup::Background);
#else
parentWidget()->palette().color(
QPalette::Normal, QPalette::Background);
#endif
painter.setPen(Qt::NoPen);
painter.setBrush(QBrush(bg));
painter.drawRect(0, 0, pm.width(), pm.height());
int dx = d_data->pos.x() - d_data->initialPos.x();
int dy = d_data->pos.y() - d_data->initialPos.y();
QRect r(0, 0, d_data->pixmap.width(), d_data->pixmap.height());
r.moveCenter(QPoint(r.center().x() + dx, r.center().y() + dy));
painter.drawPixmap(r, d_data->pixmap);
painter.end();
painter.begin(this);
painter.setClipRegion(pe->region());
painter.drawPixmap(0, 0, pm);
}
\brief Event filter
When isEnabled() the mouse events of the observed widget are filtered.
\sa widgetMousePressEvent(), widgetMouseReleaseEvent(),
widgetMouseMoveEvent()
*/
bool QwtPanner::eventFilter(QObject *o, QEvent *e)
{
if ( o == NULL || o != parentWidget() )
return false;
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
switch(e->type()) {
case QEvent::MouseButtonPress: {
widgetMousePressEvent((QMouseEvent *)e);
break;
}
case QEvent::MouseMove: {
widgetMouseMoveEvent((QMouseEvent *)e);
break;
}
case QEvent::MouseButtonRelease: {
widgetMouseReleaseEvent((QMouseEvent *)e);
break;
}
case QEvent::KeyPress: {
widgetKeyPressEvent((QKeyEvent *)e);
break;
}
case QEvent::KeyRelease: {
widgetKeyReleaseEvent((QKeyEvent *)e);
break;
}
case QEvent::Paint: {
if ( isVisible() )
return true;
break;
}
default:
;
}
return false;
}
/*!
Handle a mouse press event for the observed widget.
\param me Mouse event
\sa eventFilter(), widgetMouseReleaseEvent(),
widgetMouseMoveEvent(),
*/
void QwtPanner::widgetMousePressEvent(QMouseEvent *me)
{
if ( me->button() != d_data->button )
return;
QWidget *w = parentWidget();
if ( w == NULL )
return;
#if QT_VERSION < 0x040000
if ( (me->state() & Qt::KeyButtonMask) !=
(d_data->buttonState & Qt::KeyButtonMask) )
(int)(d_data->buttonState & Qt::KeyboardModifierMask) )
#endif
{
return;
}
#ifndef QT_NO_CURSOR
showCursor(true);
#endif
d_data->initialPos = d_data->pos = me->pos();
QRect cr = parentWidget()->rect();
if ( parentWidget()->inherits("QFrame") ) {
const QFrame* frame = (QFrame*)parentWidget();
cr = frame->contentsRect();
}
setGeometry(cr);
// We don't want to grab the picker !
QwtArray<QwtPicker *> pickers = activePickers(parentWidget());
for ( int i = 0; i < (int)pickers.size(); i++ )
pickers[i]->setEnabled(false);
d_data->pixmap = QPixmap::grabWidget(parentWidget(),
cr.x(), cr.y(), cr.width(), cr.height());
for ( int i = 0; i < (int)pickers.size(); i++ )
pickers[i]->setEnabled(true);
show();
}
/*!
Handle a mouse move event for the observed widget.
\param me Mouse event
\sa eventFilter(), widgetMousePressEvent(), widgetMouseReleaseEvent()
*/
void QwtPanner::widgetMouseMoveEvent(QMouseEvent *me)
{
if ( !isVisible() )
return;
QPoint pos = me->pos();
if ( !isOrientationEnabled(Qt::Horizontal) )
pos.setX(d_data->initialPos.x());
if ( !isOrientationEnabled(Qt::Vertical) )
pos.setY(d_data->initialPos.y());
if ( pos != d_data->pos && rect().contains(pos) ) {
emit moved(d_data->pos.x() - d_data->initialPos.x(),
d_data->pos.y() - d_data->initialPos.y());
}
}
/*!
Handle a mouse release event for the observed widget.
\param me Mouse event
\sa eventFilter(), widgetMousePressEvent(),
widgetMouseMoveEvent(),
*/
void QwtPanner::widgetMouseReleaseEvent(QMouseEvent *me)
{
hide();
#ifndef QT_NO_CURSOR
showCursor(false);
#endif
QPoint pos = me->pos();
if ( !isOrientationEnabled(Qt::Horizontal) )
pos.setX(d_data->initialPos.x());
if ( !isOrientationEnabled(Qt::Vertical) )
pos.setY(d_data->initialPos.y());
d_data->pixmap = QPixmap();
d_data->pos = pos;
if ( d_data->pos != d_data->initialPos ) {
emit panned(d_data->pos.x() - d_data->initialPos.x(),
d_data->pos.y() - d_data->initialPos.y());
}
}
}
/*!
Handle a key press event for the observed widget.
\param ke Key event
\sa eventFilter(), widgetKeyReleaseEvent()
*/
void QwtPanner::widgetKeyPressEvent(QKeyEvent *ke)
{
if ( ke->key() == d_data->abortKey ) {
const bool matched =
#if QT_VERSION < 0x040000
(ke->state() & Qt::KeyButtonMask) ==
(d_data->abortKeyState & Qt::KeyButtonMask);
(int)(d_data->abortKeyState & Qt::KeyboardModifierMask);
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
hide();
#ifndef QT_NO_CURSOR
showCursor(false);
#endif
d_data->pixmap = QPixmap();
}
}
}
/*!
Handle a key release event for the observed widget.
\param ke Key event
\sa eventFilter(), widgetKeyReleaseEvent()
*/
void QwtPanner::widgetKeyReleaseEvent(QKeyEvent *)
{
}
#ifndef QT_NO_CURSOR
void QwtPanner::showCursor(bool on)
{
if ( on == d_data->hasCursor )
return;
QWidget *w = parentWidget();
if ( w == NULL || d_data->cursor == NULL )
return;
d_data->hasCursor = on;
#if QT_VERSION < 0x040000
if ( w->testWState(WState_OwnCursor) )
#else
if ( w->testAttribute(Qt::WA_SetCursor) )
#endif
{
delete d_data->restoreCursor;
d_data->restoreCursor = new QCursor(w->cursor());
}
w->setCursor(*d_data->cursor);
} else {
if ( d_data->restoreCursor ) {
w->setCursor(*d_data->restoreCursor);
delete d_data->restoreCursor;
d_data->restoreCursor = NULL;