1
/* -*- mode: C++ ; c-file-style: "stroustrup" -*- *****************************
3
* Copyright (C) 1997 Josef Wilgen
4
* Copyright (C) 2002 Uwe Rathmann
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
*****************************************************************************/
10
#include <qapplication.h>
17
#include "qwt_painter.h"
18
#include "qwt_picker_machine.h"
19
#include "qwt_picker.h"
20
#if QT_VERSION < 0x040000
21
#include <qguardedptr.h>
26
#if QT_VERSION >= 0x040300
28
With Qt >= 4.3 drawing of the tracker can be implemented in an
29
easier, using the textRect as mask. Because calculating
30
a QRegion from a QBitmask is expensive operation ( especially for
31
longer texts !) this implementation is much faster too.
32
Also the result looks much better.
34
#define USE_TRACKER_RECT_MASK
37
#ifndef USE_TRACKER_RECT_MASK
38
#define USE_TRACKER_BACKGROUND
41
class QwtPicker::PrivateData
44
class PickerWidget: public QWidget
52
PickerWidget(QwtPicker *, QWidget *, Type);
53
virtual void updateMask();
55
#ifdef USE_TRACKER_BACKGROUND
57
Internal flag, that is needed for tracker texts with a
58
background. This flag has been introduced in Qwt 5.0.2 to avoid
59
incompatible API changes. In Qwt 5.1 will be a cleaner solution.
61
mutable bool d_hasTrackerBackground;
64
virtual void paintEvent(QPaintEvent *);
72
QwtPickerMachine *stateMachine;
75
QwtPicker::ResizeMode resizeMode;
77
QwtPicker::RubberBand rubberBand;
80
QwtPicker::DisplayMode trackerMode;
88
bool mouseTracking; // used to save previous value
91
On X11 the widget below the picker widgets gets paint events
92
with a region that is the bounding rect of the mask, if it is complex.
93
In case of (f.e) a CrossRubberBand and a text this creates complete
94
repaints of the widget. So we better use two different widgets.
97
#if QT_VERSION < 0x040000
98
QGuardedPtr<PickerWidget> rubberBandWidget;
99
QGuardedPtr<PickerWidget> trackerWidget;
101
QPointer<PickerWidget> rubberBandWidget;
102
QPointer<PickerWidget> trackerWidget;
106
QwtPicker::PrivateData::PickerWidget::PickerWidget(
107
QwtPicker *picker, QWidget *parent, Type type):
112
#if QT_VERSION >= 0x040000
113
setAttribute(Qt::WA_TransparentForMouseEvents);
114
setAttribute(Qt::WA_NoSystemBackground);
115
setFocusPolicy(Qt::NoFocus);
117
setBackgroundMode(Qt::NoBackground);
118
setFocusPolicy(QWidget::NoFocus);
119
setMouseTracking(true);
124
void QwtPicker::PrivateData::PickerWidget::updateMask()
128
if ( d_type == RubberBand )
130
QBitmap bm(width(), height());
133
QPainter painter(&bm);
134
QPen pen = d_picker->rubberBandPen();
135
pen.setColor(Qt::color1);
138
d_picker->drawRubberBand(&painter);
142
if ( d_type == Text )
144
#ifdef USE_TRACKER_RECT_MASK
145
QBitmap bm(width(), height());
146
QPainter painter(&bm);
147
painter.setFont(font());
148
mask = d_picker->trackerRect(&painter);
150
QBitmap bm(width(), height());
153
QPainter painter(&bm);
154
painter.setFont(font());
156
QPen pen = d_picker->trackerPen();
157
pen.setColor(Qt::color1);
160
d_picker->drawTracker(&painter);
166
#if QT_VERSION < 0x040000
167
QWidget *w = parentWidget();
168
const bool doUpdate = w->isUpdatesEnabled();
169
const Qt::BackgroundMode bgMode = w->backgroundMode();
170
w->setUpdatesEnabled(false);
171
if ( bgMode != Qt::NoBackground )
172
w->setBackgroundMode(Qt::NoBackground);
177
#if QT_VERSION < 0x040000
178
if ( bgMode != Qt::NoBackground )
179
w->setBackgroundMode(bgMode);
181
w->setUpdatesEnabled(doUpdate);
184
setShown(!mask.isEmpty());
187
void QwtPicker::PrivateData::PickerWidget::paintEvent(QPaintEvent *e)
189
QPainter painter(this);
191
if ( d_type == RubberBand )
193
painter.setClipRegion(e->region());
194
painter.setPen(d_picker->rubberBandPen());
195
d_picker->drawRubberBand(&painter);
198
if ( d_type == Text )
200
painter.setClipRegion(e->region());
202
bool doDrawTracker = true;
203
#ifndef USE_TRACKER_RECT_MASK
204
#ifdef USE_TRACKER_BACKGROUND
205
doDrawTracker = d_hasTrackerBackground;
207
doDrawTracker = false;
210
#if QT_VERSION < 0x040000
211
if ( !doDrawTracker && QPainter::redirect(this) )
213
// setMask + painter redirection doesn't work
214
doDrawTracker = true;
219
painter.setPen(d_picker->trackerPen());
220
d_picker->drawTracker(&painter);
223
painter.fillRect(e->rect(), QBrush(d_picker->trackerPen().color()));
230
Creates an picker that is enabled, but where selection flag
231
is set to NoSelection, rubberband and tracker are disabled.
233
\param parent Parent widget, that will be observed
236
QwtPicker::QwtPicker(QWidget *parent):
239
init(parent, NoSelection, NoRubberBand, AlwaysOff);
245
\param selectionFlags Or'd value of SelectionType, RectSelectionType and
247
\param rubberBand Rubberband style
248
\param trackerMode Tracker mode
249
\param parent Parent widget, that will be observed
251
QwtPicker::QwtPicker(int selectionFlags, RubberBand rubberBand,
252
DisplayMode trackerMode, QWidget *parent):
255
init(parent, selectionFlags, rubberBand, trackerMode);
259
QwtPicker::~QwtPicker()
261
setMouseTracking(false);
262
delete d_data->stateMachine;
263
delete d_data->rubberBandWidget;
264
delete d_data->trackerWidget;
268
//! Init the picker, used by the constructors
269
void QwtPicker::init(QWidget *parent, int selectionFlags,
270
RubberBand rubberBand, DisplayMode trackerMode)
272
d_data = new PrivateData;
274
d_data->rubberBandWidget = NULL;
275
d_data->trackerWidget = NULL;
277
d_data->rubberBand = rubberBand;
278
d_data->enabled = false;
279
d_data->resizeMode = Stretch;
280
d_data->trackerMode = AlwaysOff;
281
d_data->isActive = false;
282
d_data->labelPosition = QPoint(-1, -1);
283
d_data->mouseTracking = false;
285
d_data->stateMachine = NULL;
286
setSelectionFlags(selectionFlags);
290
#if QT_VERSION >= 0x040000
291
if ( parent->focusPolicy() == Qt::NoFocus )
292
parent->setFocusPolicy(Qt::WheelFocus);
294
if ( parent->focusPolicy() == QWidget::NoFocus )
295
parent->setFocusPolicy(QWidget::WheelFocus);
298
d_data->trackerFont = parent->font();
299
d_data->mouseTracking = parent->hasMouseTracking();
302
setTrackerMode(trackerMode);
306
Set a state machine and delete the previous one
308
void QwtPicker::setStateMachine(QwtPickerMachine *stateMachine)
310
if ( d_data->stateMachine != stateMachine )
315
delete d_data->stateMachine;
316
d_data->stateMachine = stateMachine;
318
if ( d_data->stateMachine )
319
d_data->stateMachine->reset();
324
Create a state machine depending on the selection flags.
326
- PointSelection | ClickSelection\n
327
QwtPickerClickPointMachine()
328
- PointSelection | DragSelection\n
329
QwtPickerDragPointMachine()
330
- RectSelection | ClickSelection\n
331
QwtPickerClickRectMachine()
332
- RectSelection | DragSelection\n
333
QwtPickerDragRectMachine()
335
QwtPickerPolygonMachine()
337
\sa setSelectionFlags()
339
QwtPickerMachine *QwtPicker::stateMachine(int flags) const
341
if ( flags & PointSelection )
343
if ( flags & ClickSelection )
344
return new QwtPickerClickPointMachine;
346
return new QwtPickerDragPointMachine;
348
if ( flags & RectSelection )
350
if ( flags & ClickSelection )
351
return new QwtPickerClickRectMachine;
353
return new QwtPickerDragRectMachine;
355
if ( flags & PolygonSelection )
357
return new QwtPickerPolygonMachine();
362
//! Return the parent widget, where the selection happens
363
QWidget *QwtPicker::parentWidget()
365
QObject *obj = parent();
366
if ( obj && obj->isWidgetType() )
367
return (QWidget *)obj;
372
//! Return the parent widget, where the selection happens
373
const QWidget *QwtPicker::parentWidget() const
375
QObject *obj = parent();
376
if ( obj && obj->isWidgetType() )
377
return (QWidget *)obj;
383
Set the selection flags
385
\param flags Or'd value of SelectionType, RectSelectionType and
386
SelectionMode. The default value is NoSelection.
388
\sa selectionFlags(), SelectionType, RectSelectionType, SelectionMode
391
void QwtPicker::setSelectionFlags(int flags)
393
d_data->selectionFlags = flags;
394
setStateMachine(stateMachine(flags));
398
\return Selection flags, an Or'd value of SelectionType, RectSelectionType and
400
\sa setSelectionFlags(), SelectionType, RectSelectionType, SelectionMode
402
int QwtPicker::selectionFlags() const
404
return d_data->selectionFlags;
408
Set the rubberband style
410
\param rubberBand Rubberband style
411
The default value is NoRubberBand.
413
\sa rubberBand(), RubberBand, setRubberBandPen()
415
void QwtPicker::setRubberBand(RubberBand rubberBand)
417
d_data->rubberBand = rubberBand;
421
\return Rubberband style
422
\sa setRubberBand(), RubberBand, rubberBandPen()
424
QwtPicker::RubberBand QwtPicker::rubberBand() const
426
return d_data->rubberBand;
430
\brief Set the display mode of the tracker.
432
A tracker displays information about current position of
433
the cursor as a string. The display mode controls
434
if the tracker has to be displayed whenever the observed
435
widget has focus and cursor (AlwaysOn), never (AlwaysOff), or
436
only when the selection is active (ActiveOnly).
438
\param mode Tracker display mode
440
\warning In case of AlwaysOn, mouseTracking will be enabled
441
for the observed widget.
442
\sa trackerMode(), DisplayMode
445
void QwtPicker::setTrackerMode(DisplayMode mode)
447
if ( d_data->trackerMode != mode )
449
d_data->trackerMode = mode;
450
setMouseTracking(d_data->trackerMode == AlwaysOn);
455
\return Tracker display mode
456
\sa setTrackerMode(), DisplayMode
458
QwtPicker::DisplayMode QwtPicker::trackerMode() const
460
return d_data->trackerMode;
464
\brief Set the resize mode.
466
The resize mode controls what to do with the selected points of an active
467
selection when the observed widget is resized.
469
Stretch means the points are scaled according to the new
470
size, KeepSize means the points remain unchanged.
472
The default mode is Stretch.
474
\param mode Resize mode
475
\sa resizeMode(), ResizeMode
477
void QwtPicker::setResizeMode(ResizeMode mode)
479
d_data->resizeMode = mode;
484
\sa setResizeMode(), ResizeMode
487
QwtPicker::ResizeMode QwtPicker::resizeMode() const
489
return d_data->resizeMode;
493
\brief En/disable the picker
495
When enabled is true an event filter is installed for
496
the observed widget, otherwise the event filter is removed.
498
\param enabled true or false
499
\sa isEnabled(), eventFilter()
501
void QwtPicker::setEnabled(bool enabled)
503
if ( d_data->enabled != enabled )
505
d_data->enabled = enabled;
507
QWidget *w = parentWidget();
511
w->installEventFilter(this);
513
w->removeEventFilter(this);
521
\return true when enabled, false otherwise
522
\sa setEnabled, eventFilter()
525
bool QwtPicker::isEnabled() const
527
return d_data->enabled;
531
Set the font for the tracker
533
\param font Tracker font
534
\sa trackerFont(), setTrackerMode(), setTrackerPen()
536
void QwtPicker::setTrackerFont(const QFont &font)
538
if ( font != d_data->trackerFont )
540
d_data->trackerFont = font;
547
\sa setTrackerFont(), trackerMode(), trackerPen()
550
QFont QwtPicker::trackerFont() const
552
return d_data->trackerFont;
556
Set the pen for the tracker
558
\param pen Tracker pen
559
\sa trackerPen(), setTrackerMode(), setTrackerFont()
561
void QwtPicker::setTrackerPen(const QPen &pen)
563
if ( pen != d_data->trackerPen )
565
d_data->trackerPen = pen;
572
\sa setTrackerPen(), trackerMode(), trackerFont()
574
QPen QwtPicker::trackerPen() const
576
return d_data->trackerPen;
580
Set the pen for the rubberband
582
\param pen Rubberband pen
583
\sa rubberBandPen(), setRubberBand()
585
void QwtPicker::setRubberBandPen(const QPen &pen)
587
if ( pen != d_data->rubberBandPen )
589
d_data->rubberBandPen = pen;
595
\return Rubberband pen
596
\sa setRubberBandPen(), rubberBand()
598
QPen QwtPicker::rubberBandPen() const
600
return d_data->rubberBandPen;
604
\brief Return the label for a position
606
In case of HLineRubberBand the label is the value of the
607
y position, in case of VLineRubberBand the value of the x position.
608
Otherwise the label contains x and y position separated by a ',' .
610
The format for the string conversion is "%d".
613
\return Converted position as string
616
QwtText QwtPicker::trackerText(const QPoint &pos) const
622
case HLineRubberBand:
623
label.sprintf("%d", pos.y());
625
case VLineRubberBand:
626
label.sprintf("%d", pos.x());
629
label.sprintf("%d, %d", pos.x(), pos.y());
635
Draw a rubberband , depending on rubberBand() and selectionFlags()
637
\param painter Painter, initialized with clip rect
639
\sa rubberBand(), RubberBand, selectionFlags()
642
void QwtPicker::drawRubberBand(QPainter *painter) const
644
if ( !isActive() || rubberBand() == NoRubberBand ||
645
rubberBandPen().style() == Qt::NoPen )
650
const QRect &pRect = pickRect();
651
const QwtPolygon &pa = d_data->selection;
653
if ( selectionFlags() & PointSelection )
655
if ( pa.count() < 1 )
658
const QPoint pos = pa[0];
662
case VLineRubberBand:
663
QwtPainter::drawLine(painter, pos.x(),
664
pRect.top(), pos.x(), pRect.bottom());
667
case HLineRubberBand:
668
QwtPainter::drawLine(painter, pRect.left(),
669
pos.y(), pRect.right(), pos.y());
672
case CrossRubberBand:
673
QwtPainter::drawLine(painter, pos.x(),
674
pRect.top(), pos.x(), pRect.bottom());
675
QwtPainter::drawLine(painter, pRect.left(),
676
pos.y(), pRect.right(), pos.y());
683
else if ( selectionFlags() & RectSelection )
685
if ( pa.count() < 2 )
689
QPoint p2 = pa[int(pa.count() - 1)];
691
if ( selectionFlags() & CenterToCorner )
693
p1.setX(p1.x() - (p2.x() - p1.x()));
694
p1.setY(p1.y() - (p2.y() - p1.y()));
696
else if ( selectionFlags() & CenterToRadius )
698
const int radius = qwtMax(qwtAbs(p2.x() - p1.x()),
699
qwtAbs(p2.y() - p1.y()));
700
p2.setX(p1.x() + radius);
701
p2.setY(p1.y() + radius);
702
p1.setX(p1.x() - radius);
703
p1.setY(p1.y() - radius);
706
#if QT_VERSION < 0x040000
707
const QRect rect = QRect(p1, p2).normalize();
709
const QRect rect = QRect(p1, p2).normalized();
713
case EllipseRubberBand:
714
QwtPainter::drawEllipse(painter, rect);
717
QwtPainter::drawRect(painter, rect);
723
else if ( selectionFlags() & PolygonSelection )
725
if ( rubberBand() == PolygonRubberBand )
726
painter->drawPolyline(pa);
733
\param painter Painter
734
\sa trackerRect(), trackerText()
737
void QwtPicker::drawTracker(QPainter *painter) const
739
const QRect textRect = trackerRect(painter);
740
if ( !textRect.isEmpty() )
742
QwtText label = trackerText(d_data->labelPosition);
743
if ( !label.isEmpty() )
745
#ifdef USE_TRACKER_BACKGROUND
746
if ( label.testPaintAttribute(QwtText::PaintBackground) )
748
if ( d_data->trackerWidget )
749
d_data->trackerWidget->d_hasTrackerBackground = true;
751
if ( painter->pen() != trackerPen() &&
752
painter->pen().color() == Qt::color1 )
755
Hack time: we know, that we are painting to get the
756
region for the mask. The text is always inside the
757
textRect and on a QBitmap everything is painted in
758
Qt::color1. That's why we don't have to paint the text.
760
painter->fillRect(textRect, Qt::color1);
766
if ( d_data->trackerWidget )
767
d_data->trackerWidget->d_hasTrackerBackground = false;
771
#if defined(Q_WS_MAC)
772
#if QT_VERSION >= 0x040000 && QT_VERSION < 0x040300
773
// Antialiased fonts are broken on the Mac.
775
painter->setRenderHint(QPainter::TextAntialiasing, false);
777
QFont fnt = label.usedFont(painter->font());
778
fnt.setStyleStrategy(QFont::NoAntialias);
782
label.draw(painter, textRect);
784
#if defined(Q_WS_MAC)
785
#if QT_VERSION >= 0x040000 && QT_VERSION < 0x040300
793
QRect QwtPicker::trackerRect(QPainter *painter) const
795
if ( trackerMode() == AlwaysOff ||
796
(trackerMode() == ActiveOnly && !isActive() ) )
801
if ( d_data->labelPosition.x() < 0 || d_data->labelPosition.y() < 0 )
804
QwtText text = trackerText(d_data->labelPosition);
805
if ( text.isEmpty() )
808
QRect textRect(QPoint(0, 0), text.textSize(painter->font()));
810
const QPoint &pos = d_data->labelPosition;
813
if ( isActive() && d_data->selection.count() > 1
814
&& rubberBand() != NoRubberBand )
817
d_data->selection[int(d_data->selection.count()) - 2];
819
alignment |= (pos.x() >= last.x()) ? Qt::AlignRight : Qt::AlignLeft;
820
alignment |= (pos.y() > last.y()) ? Qt::AlignBottom : Qt::AlignTop;
823
alignment = Qt::AlignTop | Qt::AlignRight;
825
const int margin = 5;
828
if ( alignment & Qt::AlignLeft )
829
x -= textRect.width() + margin;
830
else if ( alignment & Qt::AlignRight )
834
if ( alignment & Qt::AlignBottom )
836
else if ( alignment & Qt::AlignTop )
837
y -= textRect.height() + margin;
839
textRect.moveTopLeft(QPoint(x, y));
841
int right = qwtMin(textRect.right(), pickRect().right() - margin);
842
int bottom = qwtMin(textRect.bottom(), pickRect().bottom() - margin);
843
textRect.moveBottomRight(QPoint(right, bottom));
845
int left = qwtMax(textRect.left(), pickRect().left() + margin);
846
int top = qwtMax(textRect.top(), pickRect().top() + margin);
847
textRect.moveTopLeft(QPoint(left, top));
855
When isEnabled() == true all events of the observed widget are filtered.
856
Mouse and keyboard events are translated into widgetMouse- and widgetKey-
857
and widgetWheel-events. Paint and Resize events are handled to keep
858
rubberband and tracker up to date.
860
\sa event(), widgetMousePressEvent(), widgetMouseReleaseEvent(),
861
widgetMouseDoubleClickEvent(), widgetMouseMoveEvent(),
862
widgetWheelEvent(), widgetKeyPressEvent(), widgetKeyReleaseEvent()
864
bool QwtPicker::eventFilter(QObject *o, QEvent *e)
866
if ( o && o == parentWidget() )
872
const QResizeEvent *re = (QResizeEvent *)e;
873
if ( d_data->resizeMode == Stretch )
874
stretchSelection(re->oldSize(), re->size());
876
if ( d_data->rubberBandWidget )
877
d_data->rubberBandWidget->resize(re->size());
879
if ( d_data->trackerWidget )
880
d_data->trackerWidget->resize(re->size());
886
case QEvent::MouseButtonPress:
887
widgetMousePressEvent((QMouseEvent *)e);
889
case QEvent::MouseButtonRelease:
890
widgetMouseReleaseEvent((QMouseEvent *)e);
892
case QEvent::MouseButtonDblClick:
893
widgetMouseDoubleClickEvent((QMouseEvent *)e);
895
case QEvent::MouseMove:
896
widgetMouseMoveEvent((QMouseEvent *)e);
898
case QEvent::KeyPress:
899
widgetKeyPressEvent((QKeyEvent *)e);
901
case QEvent::KeyRelease:
902
widgetKeyReleaseEvent((QKeyEvent *)e);
905
widgetWheelEvent((QWheelEvent *)e);
915
Handle a mouse press event for the observed widget.
917
Begin and/or end a selection depending on the selection flags.
919
\sa QwtPicker, selectionFlags()
920
\sa eventFilter(), widgetMouseReleaseEvent(),
921
widgetMouseDoubleClickEvent(), widgetMouseMoveEvent(),
922
widgetWheelEvent(), widgetKeyPressEvent(), widgetKeyReleaseEvent()
924
void QwtPicker::widgetMousePressEvent(QMouseEvent *e)
930
Handle a mouse move event for the observed widget.
932
Move the last point of the selection in case of isActive() == true
934
\sa eventFilter(), widgetMousePressEvent(), widgetMouseReleaseEvent(),
935
widgetMouseDoubleClickEvent(),
936
widgetWheelEvent(), widgetKeyPressEvent(), widgetKeyReleaseEvent()
938
void QwtPicker::widgetMouseMoveEvent(QMouseEvent *e)
940
if ( pickRect().contains(e->pos()) )
941
d_data->labelPosition = e->pos();
943
d_data->labelPosition = QPoint(-1, -1);
952
Handle a leave event for the observed widget.
954
\sa eventFilter(), widgetMousePressEvent(), widgetMouseReleaseEvent(),
955
widgetMouseDoubleClickEvent(),
956
widgetWheelEvent(), widgetKeyPressEvent(), widgetKeyReleaseEvent()
958
void QwtPicker::widgetLeaveEvent(QEvent *)
960
d_data->labelPosition = QPoint(-1, -1);
966
Handle a mouse relase event for the observed widget.
968
End a selection depending on the selection flags.
970
\sa QwtPicker, selectionFlags()
971
\sa eventFilter(), widgetMousePressEvent(),
972
widgetMouseDoubleClickEvent(), widgetMouseMoveEvent(),
973
widgetWheelEvent(), widgetKeyPressEvent(), widgetKeyReleaseEvent()
975
void QwtPicker::widgetMouseReleaseEvent(QMouseEvent *e)
981
Handle mouse double click event for the observed widget.
983
Empty implementation, does nothing.
985
\sa eventFilter(), widgetMousePressEvent(), widgetMouseReleaseEvent(),
986
widgetMouseMoveEvent(),
987
widgetWheelEvent(), widgetKeyPressEvent(), widgetKeyReleaseEvent()
989
void QwtPicker::widgetMouseDoubleClickEvent(QMouseEvent *me)
996
Handle a wheel event for the observed widget.
998
Move the last point of the selection in case of isActive() == true
1000
\sa eventFilter(), widgetMousePressEvent(), widgetMouseReleaseEvent(),
1001
widgetMouseDoubleClickEvent(), widgetMouseMoveEvent(),
1002
widgetKeyPressEvent(), widgetKeyReleaseEvent()
1004
void QwtPicker::widgetWheelEvent(QWheelEvent *e)
1006
if ( pickRect().contains(e->pos()) )
1007
d_data->labelPosition = e->pos();
1009
d_data->labelPosition = QPoint(-1, -1);
1017
Handle a key press event for the observed widget.
1019
Selections can be completely done by the keyboard. The arrow keys
1020
move the cursor, the abort key aborts a selection. All other keys
1021
are handled by the current state machine.
1023
\sa QwtPicker, selectionFlags()
1024
\sa eventFilter(), widgetMousePressEvent(), widgetMouseReleaseEvent(),
1025
widgetMouseDoubleClickEvent(), widgetMouseMoveEvent(),
1026
widgetWheelEvent(), widgetKeyReleaseEvent(), stateMachine(),
1027
QwtEventPattern::KeyPatternCode
1029
void QwtPicker::widgetKeyPressEvent(QKeyEvent *ke)
1035
if ( ke->isAutoRepeat() )
1038
if ( keyMatch(KeyLeft, ke) )
1040
else if ( keyMatch(KeyRight, ke) )
1042
else if ( keyMatch(KeyUp, ke) )
1044
else if ( keyMatch(KeyDown, ke) )
1046
else if ( keyMatch(KeyAbort, ke) )
1048
if ( d_data->stateMachine )
1049
d_data->stateMachine->reset();
1057
if ( dx != 0 || dy != 0 )
1059
const QRect rect = pickRect();
1060
const QPoint pos = parentWidget()->mapFromGlobal(QCursor::pos());
1062
int x = pos.x() + dx;
1063
x = qwtMax(rect.left(), x);
1064
x = qwtMin(rect.right(), x);
1066
int y = pos.y() + dy;
1067
y = qwtMax(rect.top(), y);
1068
y = qwtMin(rect.bottom(), y);
1070
QCursor::setPos(parentWidget()->mapToGlobal(QPoint(x, y)));
1075
Handle a key release event for the observed widget.
1077
Passes the event to the state machine.
1079
\sa eventFilter(), widgetMousePressEvent(), widgetMouseReleaseEvent(),
1080
widgetMouseDoubleClickEvent(), widgetMouseMoveEvent(),
1081
widgetWheelEvent(), widgetKeyPressEvent(), stateMachine()
1083
void QwtPicker::widgetKeyReleaseEvent(QKeyEvent *ke)
1089
Passes an event to the state machine and executes the resulting
1090
commands. Append and Move commands use the current position
1091
of the cursor (QCursor::pos()).
1095
void QwtPicker::transition(const QEvent *e)
1097
if ( !d_data->stateMachine )
1100
QwtPickerMachine::CommandList commandList =
1101
d_data->stateMachine->transition(*this, e);
1106
case QEvent::MouseButtonDblClick:
1107
case QEvent::MouseButtonPress:
1108
case QEvent::MouseButtonRelease:
1109
case QEvent::MouseMove:
1111
const QMouseEvent *me = (QMouseEvent *)e;
1116
pos = parentWidget()->mapFromGlobal(QCursor::pos());
1119
for ( uint i = 0; i < (uint)commandList.count(); i++ )
1121
switch(commandList[i])
1123
case QwtPickerMachine::Begin:
1128
case QwtPickerMachine::Append:
1133
case QwtPickerMachine::Move:
1138
case QwtPickerMachine::End:
1148
Open a selection setting the state to active
1150
\sa isActive, end(), append(), move()
1152
void QwtPicker::begin()
1154
if ( d_data->isActive )
1157
d_data->selection.resize(0);
1158
d_data->isActive = true;
1160
if ( trackerMode() != AlwaysOff )
1162
if ( d_data->labelPosition.x() < 0 || d_data->labelPosition.y() < 0 )
1164
QWidget *w = parentWidget();
1166
d_data->labelPosition = w->mapFromGlobal(QCursor::pos());
1171
setMouseTracking(true);
1175
\brief Close a selection setting the state to inactive.
1177
The selection is validated and maybe fixed by QwtPicker::accept().
1179
\param ok If true, complete the selection and emit a selected signal
1180
otherwise discard the selection.
1181
\return true if the selection is accepted, false otherwise
1182
\sa isActive, begin(), append(), move(), selected(), accept()
1184
bool QwtPicker::end(bool ok)
1186
if ( d_data->isActive )
1188
setMouseTracking(false);
1190
d_data->isActive = false;
1192
if ( trackerMode() == ActiveOnly )
1193
d_data->labelPosition = QPoint(-1, -1);
1196
ok = accept(d_data->selection);
1199
emit selected(d_data->selection);
1201
d_data->selection.resize(0);
1212
Append a point to the selection and update rubberband and tracker.
1213
The appended() signal is emitted.
1215
\param pos Additional point
1217
\sa isActive, begin(), end(), move(), appended()
1219
void QwtPicker::append(const QPoint &pos)
1221
if ( d_data->isActive )
1223
const int idx = d_data->selection.count();
1224
d_data->selection.resize(idx + 1);
1225
d_data->selection[idx] = pos;
1234
Move the last point of the selection
1235
The moved() signal is emitted.
1237
\param pos New position
1238
\sa isActive, begin(), end(), append()
1241
void QwtPicker::move(const QPoint &pos)
1243
if ( d_data->isActive )
1245
const int idx = d_data->selection.count() - 1;
1248
if ( d_data->selection[idx] != pos )
1250
d_data->selection[idx] = pos;
1260
bool QwtPicker::accept(QwtPolygon &) const
1266
A picker is active between begin() and end().
1267
\return true if the selection is active.
1269
bool QwtPicker::isActive() const
1271
return d_data->isActive;
1274
//! Return Selected points
1275
const QwtPolygon &QwtPicker::selection() const
1277
return d_data->selection;
1281
Scale the selection by the ratios of oldSize and newSize
1282
The changed() signal is emitted.
1284
\param oldSize Previous size
1285
\param newSize Current size
1287
\sa ResizeMode, setResizeMode(), resizeMode()
1289
void QwtPicker::stretchSelection(const QSize &oldSize, const QSize &newSize)
1291
const double xRatio =
1292
double(newSize.width()) / double(oldSize.width());
1293
const double yRatio =
1294
double(newSize.height()) / double(oldSize.height());
1296
for ( int i = 0; i < int(d_data->selection.count()); i++ )
1298
QPoint &p = d_data->selection[i];
1299
p.setX(qRound(p.x() * xRatio));
1300
p.setY(qRound(p.y() * yRatio));
1302
emit changed(d_data->selection);
1307
Set mouse tracking for the observed widget.
1309
In case of enable is true, the previous value
1310
is saved, that is restored when enable is false.
1312
\warning Even when enable is false, mouse tracking might be restored
1313
to true. When mouseTracking for the observed widget
1314
has been changed directly by QWidget::setMouseTracking
1315
while mouse tracking has been set to true, this value can't
1319
void QwtPicker::setMouseTracking(bool enable)
1321
QWidget *widget = parentWidget();
1327
d_data->mouseTracking = widget->hasMouseTracking();
1328
widget->setMouseTracking(true);
1332
widget->setMouseTracking(d_data->mouseTracking);
1337
Find the area of the observed widget, where selection might happen.
1339
\return QFrame::contentsRect() if it is a QFrame, QWidget::rect() otherwise.
1341
QRect QwtPicker::pickRect() const
1345
const QWidget *widget = parentWidget();
1349
if ( widget->inherits("QFrame") )
1350
rect = ((QFrame *)widget)->contentsRect();
1352
rect = widget->rect();
1357
void QwtPicker::updateDisplay()
1359
QWidget *w = parentWidget();
1361
bool showRubberband = false;
1362
bool showTracker = false;
1363
if ( w && w->isVisible() && d_data->enabled )
1365
if ( rubberBand() != NoRubberBand && isActive() &&
1366
rubberBandPen().style() != Qt::NoPen )
1368
showRubberband = true;
1371
if ( trackerMode() == AlwaysOn ||
1372
(trackerMode() == ActiveOnly && isActive() ) )
1374
if ( trackerPen() != Qt::NoPen )
1379
#if QT_VERSION < 0x040000
1380
QGuardedPtr<PrivateData::PickerWidget> &rw = d_data->rubberBandWidget;
1382
QPointer<PrivateData::PickerWidget> &rw = d_data->rubberBandWidget;
1384
if ( showRubberband )
1388
rw = new PrivateData::PickerWidget(
1389
this, w, PrivateData::PickerWidget::RubberBand);
1390
rw->resize(w->size());
1393
rw->update(); // Needed, when the mask doesn't change
1398
#if QT_VERSION < 0x040000
1399
QGuardedPtr<PrivateData::PickerWidget> &tw = d_data->trackerWidget;
1401
QPointer<PrivateData::PickerWidget> &tw = d_data->trackerWidget;
1407
tw = new PrivateData::PickerWidget(
1408
this, w, PrivateData::PickerWidget::Text);
1409
tw->resize(w->size());
1412
tw->update(); // Needed, when the mask doesn't change
1418
const QWidget *QwtPicker::rubberBandWidget() const
1420
return d_data->rubberBandWidget;
1423
const QWidget *QwtPicker::trackerWidget() const
1425
return d_data->trackerWidget;