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>
24
#include <qpaintengine.h>
27
class QwtPicker::PickerWidget: public QWidget
36
PickerWidget(QwtPicker *, QWidget *, Type);
37
virtual void updateMask();
40
For a tracker text with a background we can use the background
41
rect as mask. Also for "regular" Qt widgets >= 4.3.0 we
42
don't need to mask the text anymore.
47
virtual void paintEvent(QPaintEvent *);
53
class QwtPicker::PrivateData
58
QwtPickerMachine *stateMachine;
61
QwtPicker::ResizeMode resizeMode;
63
QwtPicker::RubberBand rubberBand;
66
QwtPicker::DisplayMode trackerMode;
72
QPoint trackerPosition;
74
bool mouseTracking; // used to save previous value
77
On X11 the widget below the picker widgets gets paint events
78
with a region that is the bounding rect of the mask, if it is complex.
79
In case of (f.e) a CrossRubberBand and a text this creates complete
80
repaints of the widget. So we better use two different widgets.
83
#if QT_VERSION < 0x040000
84
QGuardedPtr<PickerWidget> rubberBandWidget;
85
QGuardedPtr<PickerWidget> trackerWidget;
87
QPointer<PickerWidget> rubberBandWidget;
88
QPointer<PickerWidget> trackerWidget;
92
QwtPicker::PickerWidget::PickerWidget(
93
QwtPicker *picker, QWidget *parent, Type type):
99
#if QT_VERSION >= 0x040000
100
setAttribute(Qt::WA_TransparentForMouseEvents);
101
setAttribute(Qt::WA_NoSystemBackground);
102
setFocusPolicy(Qt::NoFocus);
104
setBackgroundMode(Qt::NoBackground);
105
setFocusPolicy(QWidget::NoFocus);
106
setMouseTracking(true);
111
void QwtPicker::PickerWidget::updateMask()
115
if ( d_type == RubberBand )
117
QBitmap bm(width(), height());
120
QPainter painter(&bm);
121
QPen pen = d_picker->rubberBandPen();
122
pen.setColor(Qt::color1);
125
d_picker->drawRubberBand(&painter);
129
if ( d_type == Text )
131
d_hasTextMask = true;
132
#if QT_VERSION >= 0x040300
133
if ( !parentWidget()->testAttribute(Qt::WA_PaintOnScreen) &&
134
parentWidget()->paintEngine()->type() != QPaintEngine::OpenGL )
137
With Qt >= 4.3 drawing of the tracker can be implemented in an
138
easier way, using the textRect as mask.
141
d_hasTextMask = false;
147
const QwtText label = d_picker->trackerText(
148
d_picker->trackerPosition());
149
if ( label.testPaintAttribute(QwtText::PaintBackground)
150
&& label.backgroundBrush().style() != Qt::NoBrush )
152
#if QT_VERSION >= 0x040300
153
if ( label.backgroundBrush().color().alpha() > 0 )
155
// We don't need a text mask, when we have a background
156
d_hasTextMask = false;
162
QBitmap bm(width(), height());
165
QPainter painter(&bm);
166
painter.setFont(font());
168
QPen pen = d_picker->trackerPen();
169
pen.setColor(Qt::color1);
172
d_picker->drawTracker(&painter);
178
mask = d_picker->trackerRect(font());
182
#if QT_VERSION < 0x040000
183
QWidget *w = parentWidget();
184
const bool doUpdate = w->isUpdatesEnabled();
185
const Qt::BackgroundMode bgMode = w->backgroundMode();
186
w->setUpdatesEnabled(false);
187
if ( bgMode != Qt::NoBackground )
188
w->setBackgroundMode(Qt::NoBackground);
193
#if QT_VERSION < 0x040000
194
if ( bgMode != Qt::NoBackground )
195
w->setBackgroundMode(bgMode);
197
w->setUpdatesEnabled(doUpdate);
200
setShown(!mask.isEmpty());
203
void QwtPicker::PickerWidget::paintEvent(QPaintEvent *e)
205
QPainter painter(this);
206
painter.setClipRegion(e->region());
208
if ( d_type == RubberBand )
210
painter.setPen(d_picker->rubberBandPen());
211
d_picker->drawRubberBand(&painter);
214
if ( d_type == Text )
217
If we have a text mask we simply fill the region of
218
the mask. This gives better results for antialiased fonts.
220
bool doDrawTracker = !d_hasTextMask;
221
#if QT_VERSION < 0x040000
222
if ( !doDrawTracker && QPainter::redirect(this) )
224
// setMask + painter redirection doesn't work
225
doDrawTracker = true;
230
painter.setPen(d_picker->trackerPen());
231
d_picker->drawTracker(&painter);
234
painter.fillRect(e->rect(), QBrush(d_picker->trackerPen().color()));
241
Creates an picker that is enabled, but where selection flag
242
is set to NoSelection, rubberband and tracker are disabled.
244
\param parent Parent widget, that will be observed
247
QwtPicker::QwtPicker(QWidget *parent):
250
init(parent, NoSelection, NoRubberBand, AlwaysOff);
256
\param selectionFlags Or'd value of SelectionType, RectSelectionType and
258
\param rubberBand Rubberband style
259
\param trackerMode Tracker mode
260
\param parent Parent widget, that will be observed
262
QwtPicker::QwtPicker(int selectionFlags, RubberBand rubberBand,
263
DisplayMode trackerMode, QWidget *parent):
266
init(parent, selectionFlags, rubberBand, trackerMode);
270
QwtPicker::~QwtPicker()
272
setMouseTracking(false);
273
delete d_data->stateMachine;
274
delete d_data->rubberBandWidget;
275
delete d_data->trackerWidget;
279
//! Init the picker, used by the constructors
280
void QwtPicker::init(QWidget *parent, int selectionFlags,
281
RubberBand rubberBand, DisplayMode trackerMode)
283
d_data = new PrivateData;
285
d_data->rubberBandWidget = NULL;
286
d_data->trackerWidget = NULL;
288
d_data->rubberBand = rubberBand;
289
d_data->enabled = false;
290
d_data->resizeMode = Stretch;
291
d_data->trackerMode = AlwaysOff;
292
d_data->isActive = false;
293
d_data->trackerPosition = QPoint(-1, -1);
294
d_data->mouseTracking = false;
296
d_data->stateMachine = NULL;
297
setSelectionFlags(selectionFlags);
301
#if QT_VERSION >= 0x040000
302
if ( parent->focusPolicy() == Qt::NoFocus )
303
parent->setFocusPolicy(Qt::WheelFocus);
305
if ( parent->focusPolicy() == QWidget::NoFocus )
306
parent->setFocusPolicy(QWidget::WheelFocus);
309
d_data->trackerFont = parent->font();
310
d_data->mouseTracking = parent->hasMouseTracking();
313
setTrackerMode(trackerMode);
317
Set a state machine and delete the previous one
319
void QwtPicker::setStateMachine(QwtPickerMachine *stateMachine)
321
if ( d_data->stateMachine != stateMachine )
325
delete d_data->stateMachine;
326
d_data->stateMachine = stateMachine;
328
if ( d_data->stateMachine )
329
d_data->stateMachine->reset();
334
Create a state machine depending on the selection flags.
336
- PointSelection | ClickSelection\n
337
QwtPickerClickPointMachine()
338
- PointSelection | DragSelection\n
339
QwtPickerDragPointMachine()
340
- RectSelection | ClickSelection\n
341
QwtPickerClickRectMachine()
342
- RectSelection | DragSelection\n
343
QwtPickerDragRectMachine()
345
QwtPickerPolygonMachine()
347
\sa setSelectionFlags()
349
QwtPickerMachine *QwtPicker::stateMachine(int flags) const
351
if ( flags & PointSelection )
353
if ( flags & ClickSelection )
354
return new QwtPickerClickPointMachine;
356
return new QwtPickerDragPointMachine;
358
if ( flags & RectSelection )
360
if ( flags & ClickSelection )
361
return new QwtPickerClickRectMachine;
363
return new QwtPickerDragRectMachine;
365
if ( flags & PolygonSelection )
367
return new QwtPickerPolygonMachine();
372
//! Return the parent widget, where the selection happens
373
QWidget *QwtPicker::parentWidget()
375
QObject *obj = parent();
376
if ( obj && obj->isWidgetType() )
377
return (QWidget *)obj;
382
//! Return the parent widget, where the selection happens
383
const QWidget *QwtPicker::parentWidget() const
385
QObject *obj = parent();
386
if ( obj && obj->isWidgetType() )
387
return (QWidget *)obj;
393
Set the selection flags
395
\param flags Or'd value of SelectionType, RectSelectionType and
396
SelectionMode. The default value is NoSelection.
398
\sa selectionFlags(), SelectionType, RectSelectionType, SelectionMode
401
void QwtPicker::setSelectionFlags(int flags)
403
d_data->selectionFlags = flags;
404
setStateMachine(stateMachine(flags));
408
\return Selection flags, an Or'd value of SelectionType, RectSelectionType and
410
\sa setSelectionFlags(), SelectionType, RectSelectionType, SelectionMode
412
int QwtPicker::selectionFlags() const
414
return d_data->selectionFlags;
418
Set the rubberband style
420
\param rubberBand Rubberband style
421
The default value is NoRubberBand.
423
\sa rubberBand(), RubberBand, setRubberBandPen()
425
void QwtPicker::setRubberBand(RubberBand rubberBand)
427
d_data->rubberBand = rubberBand;
431
\return Rubberband style
432
\sa setRubberBand(), RubberBand, rubberBandPen()
434
QwtPicker::RubberBand QwtPicker::rubberBand() const
436
return d_data->rubberBand;
440
\brief Set the display mode of the tracker.
442
A tracker displays information about current position of
443
the cursor as a string. The display mode controls
444
if the tracker has to be displayed whenever the observed
445
widget has focus and cursor (AlwaysOn), never (AlwaysOff), or
446
only when the selection is active (ActiveOnly).
448
\param mode Tracker display mode
450
\warning In case of AlwaysOn, mouseTracking will be enabled
451
for the observed widget.
452
\sa trackerMode(), DisplayMode
455
void QwtPicker::setTrackerMode(DisplayMode mode)
457
if ( d_data->trackerMode != mode )
459
d_data->trackerMode = mode;
460
setMouseTracking(d_data->trackerMode == AlwaysOn);
465
\return Tracker display mode
466
\sa setTrackerMode(), DisplayMode
468
QwtPicker::DisplayMode QwtPicker::trackerMode() const
470
return d_data->trackerMode;
474
\brief Set the resize mode.
476
The resize mode controls what to do with the selected points of an active
477
selection when the observed widget is resized.
479
Stretch means the points are scaled according to the new
480
size, KeepSize means the points remain unchanged.
482
The default mode is Stretch.
484
\param mode Resize mode
485
\sa resizeMode(), ResizeMode
487
void QwtPicker::setResizeMode(ResizeMode mode)
489
d_data->resizeMode = mode;
494
\sa setResizeMode(), ResizeMode
497
QwtPicker::ResizeMode QwtPicker::resizeMode() const
499
return d_data->resizeMode;
503
\brief En/disable the picker
505
When enabled is true an event filter is installed for
506
the observed widget, otherwise the event filter is removed.
508
\param enabled true or false
509
\sa isEnabled(), eventFilter()
511
void QwtPicker::setEnabled(bool enabled)
513
if ( d_data->enabled != enabled )
515
d_data->enabled = enabled;
517
QWidget *w = parentWidget();
521
w->installEventFilter(this);
523
w->removeEventFilter(this);
531
\return true when enabled, false otherwise
532
\sa setEnabled, eventFilter()
535
bool QwtPicker::isEnabled() const
537
return d_data->enabled;
541
Set the font for the tracker
543
\param font Tracker font
544
\sa trackerFont(), setTrackerMode(), setTrackerPen()
546
void QwtPicker::setTrackerFont(const QFont &font)
548
if ( font != d_data->trackerFont )
550
d_data->trackerFont = font;
557
\sa setTrackerFont(), trackerMode(), trackerPen()
560
QFont QwtPicker::trackerFont() const
562
return d_data->trackerFont;
566
Set the pen for the tracker
568
\param pen Tracker pen
569
\sa trackerPen(), setTrackerMode(), setTrackerFont()
571
void QwtPicker::setTrackerPen(const QPen &pen)
573
if ( pen != d_data->trackerPen )
575
d_data->trackerPen = pen;
582
\sa setTrackerPen(), trackerMode(), trackerFont()
584
QPen QwtPicker::trackerPen() const
586
return d_data->trackerPen;
590
Set the pen for the rubberband
592
\param pen Rubberband pen
593
\sa rubberBandPen(), setRubberBand()
595
void QwtPicker::setRubberBandPen(const QPen &pen)
597
if ( pen != d_data->rubberBandPen )
599
d_data->rubberBandPen = pen;
605
\return Rubberband pen
606
\sa setRubberBandPen(), rubberBand()
608
QPen QwtPicker::rubberBandPen() const
610
return d_data->rubberBandPen;
614
\brief Return the label for a position
616
In case of HLineRubberBand the label is the value of the
617
y position, in case of VLineRubberBand the value of the x position.
618
Otherwise the label contains x and y position separated by a ',' .
620
The format for the string conversion is "%d".
623
\return Converted position as string
626
QwtText QwtPicker::trackerText(const QPoint &pos) const
632
case HLineRubberBand:
633
label.sprintf("%d", pos.y());
635
case VLineRubberBand:
636
label.sprintf("%d", pos.x());
639
label.sprintf("%d, %d", pos.x(), pos.y());
645
Draw a rubberband , depending on rubberBand() and selectionFlags()
647
\param painter Painter, initialized with clip rect
649
\sa rubberBand(), RubberBand, selectionFlags()
652
void QwtPicker::drawRubberBand(QPainter *painter) const
654
if ( !isActive() || rubberBand() == NoRubberBand ||
655
rubberBandPen().style() == Qt::NoPen )
660
const QRect &pRect = pickRect();
661
const QwtPolygon &pa = d_data->selection;
663
if ( selectionFlags() & PointSelection )
665
if ( pa.count() < 1 )
668
const QPoint pos = pa[0];
672
case VLineRubberBand:
673
QwtPainter::drawLine(painter, pos.x(),
674
pRect.top(), pos.x(), pRect.bottom());
677
case HLineRubberBand:
678
QwtPainter::drawLine(painter, pRect.left(),
679
pos.y(), pRect.right(), pos.y());
682
case CrossRubberBand:
683
QwtPainter::drawLine(painter, pos.x(),
684
pRect.top(), pos.x(), pRect.bottom());
685
QwtPainter::drawLine(painter, pRect.left(),
686
pos.y(), pRect.right(), pos.y());
693
else if ( selectionFlags() & RectSelection )
695
if ( pa.count() < 2 )
699
QPoint p2 = pa[int(pa.count() - 1)];
701
if ( selectionFlags() & CenterToCorner )
703
p1.setX(p1.x() - (p2.x() - p1.x()));
704
p1.setY(p1.y() - (p2.y() - p1.y()));
706
else if ( selectionFlags() & CenterToRadius )
708
const int radius = qwtMax(qwtAbs(p2.x() - p1.x()),
709
qwtAbs(p2.y() - p1.y()));
710
p2.setX(p1.x() + radius);
711
p2.setY(p1.y() + radius);
712
p1.setX(p1.x() - radius);
713
p1.setY(p1.y() - radius);
716
#if QT_VERSION < 0x040000
717
const QRect rect = QRect(p1, p2).normalize();
719
const QRect rect = QRect(p1, p2).normalized();
723
case EllipseRubberBand:
724
QwtPainter::drawEllipse(painter, rect);
727
QwtPainter::drawRect(painter, rect);
733
else if ( selectionFlags() & PolygonSelection )
735
if ( rubberBand() == PolygonRubberBand )
736
painter->drawPolyline(pa);
743
\param painter Painter
744
\sa trackerRect(), trackerText()
747
void QwtPicker::drawTracker(QPainter *painter) const
749
const QRect textRect = trackerRect(painter->font());
750
if ( !textRect.isEmpty() )
752
QwtText label = trackerText(d_data->trackerPosition);
753
if ( !label.isEmpty() )
757
#if defined(Q_WS_MAC)
758
// Antialiased fonts are broken on the Mac.
759
#if QT_VERSION >= 0x040000
760
painter->setRenderHint(QPainter::TextAntialiasing, false);
762
QFont fnt = label.usedFont(painter->font());
763
fnt.setStyleStrategy(QFont::NoAntialias);
767
label.draw(painter, textRect);
774
QPoint QwtPicker::trackerPosition() const
776
return d_data->trackerPosition;
779
QRect QwtPicker::trackerRect(const QFont &font) const
781
if ( trackerMode() == AlwaysOff ||
782
(trackerMode() == ActiveOnly && !isActive() ) )
787
if ( d_data->trackerPosition.x() < 0 || d_data->trackerPosition.y() < 0 )
790
QwtText text = trackerText(d_data->trackerPosition);
791
if ( text.isEmpty() )
794
QRect textRect(QPoint(0, 0), text.textSize(font));
796
const QPoint &pos = d_data->trackerPosition;
799
if ( isActive() && d_data->selection.count() > 1
800
&& rubberBand() != NoRubberBand )
803
d_data->selection[int(d_data->selection.count()) - 2];
805
alignment |= (pos.x() >= last.x()) ? Qt::AlignRight : Qt::AlignLeft;
806
alignment |= (pos.y() > last.y()) ? Qt::AlignBottom : Qt::AlignTop;
809
alignment = Qt::AlignTop | Qt::AlignRight;
811
const int margin = 5;
814
if ( alignment & Qt::AlignLeft )
815
x -= textRect.width() + margin;
816
else if ( alignment & Qt::AlignRight )
820
if ( alignment & Qt::AlignBottom )
822
else if ( alignment & Qt::AlignTop )
823
y -= textRect.height() + margin;
825
textRect.moveTopLeft(QPoint(x, y));
827
int right = qwtMin(textRect.right(), pickRect().right() - margin);
828
int bottom = qwtMin(textRect.bottom(), pickRect().bottom() - margin);
829
textRect.moveBottomRight(QPoint(right, bottom));
831
int left = qwtMax(textRect.left(), pickRect().left() + margin);
832
int top = qwtMax(textRect.top(), pickRect().top() + margin);
833
textRect.moveTopLeft(QPoint(left, top));
841
When isEnabled() == true all events of the observed widget are filtered.
842
Mouse and keyboard events are translated into widgetMouse- and widgetKey-
843
and widgetWheel-events. Paint and Resize events are handled to keep
844
rubberband and tracker up to date.
846
\sa event(), widgetMousePressEvent(), widgetMouseReleaseEvent(),
847
widgetMouseDoubleClickEvent(), widgetMouseMoveEvent(),
848
widgetWheelEvent(), widgetKeyPressEvent(), widgetKeyReleaseEvent()
850
bool QwtPicker::eventFilter(QObject *o, QEvent *e)
852
if ( o && o == parentWidget() )
858
const QResizeEvent *re = (QResizeEvent *)e;
859
if ( d_data->resizeMode == Stretch )
860
stretchSelection(re->oldSize(), re->size());
862
if ( d_data->rubberBandWidget )
863
d_data->rubberBandWidget->resize(re->size());
865
if ( d_data->trackerWidget )
866
d_data->trackerWidget->resize(re->size());
872
case QEvent::MouseButtonPress:
873
widgetMousePressEvent((QMouseEvent *)e);
875
case QEvent::MouseButtonRelease:
876
widgetMouseReleaseEvent((QMouseEvent *)e);
878
case QEvent::MouseButtonDblClick:
879
widgetMouseDoubleClickEvent((QMouseEvent *)e);
881
case QEvent::MouseMove:
882
widgetMouseMoveEvent((QMouseEvent *)e);
884
case QEvent::KeyPress:
885
widgetKeyPressEvent((QKeyEvent *)e);
887
case QEvent::KeyRelease:
888
widgetKeyReleaseEvent((QKeyEvent *)e);
891
widgetWheelEvent((QWheelEvent *)e);
901
Handle a mouse press event for the observed widget.
903
Begin and/or end a selection depending on the selection flags.
905
\sa QwtPicker, selectionFlags()
906
\sa eventFilter(), widgetMouseReleaseEvent(),
907
widgetMouseDoubleClickEvent(), widgetMouseMoveEvent(),
908
widgetWheelEvent(), widgetKeyPressEvent(), widgetKeyReleaseEvent()
910
void QwtPicker::widgetMousePressEvent(QMouseEvent *e)
916
Handle a mouse move event for the observed widget.
918
Move the last point of the selection in case of isActive() == true
920
\sa eventFilter(), widgetMousePressEvent(), widgetMouseReleaseEvent(),
921
widgetMouseDoubleClickEvent(),
922
widgetWheelEvent(), widgetKeyPressEvent(), widgetKeyReleaseEvent()
924
void QwtPicker::widgetMouseMoveEvent(QMouseEvent *e)
926
if ( pickRect().contains(e->pos()) )
927
d_data->trackerPosition = e->pos();
929
d_data->trackerPosition = QPoint(-1, -1);
938
Handle a leave event for the observed widget.
940
\sa eventFilter(), widgetMousePressEvent(), widgetMouseReleaseEvent(),
941
widgetMouseDoubleClickEvent(),
942
widgetWheelEvent(), widgetKeyPressEvent(), widgetKeyReleaseEvent()
944
void QwtPicker::widgetLeaveEvent(QEvent *)
946
d_data->trackerPosition = QPoint(-1, -1);
952
Handle a mouse relase event for the observed widget.
954
End a selection depending on the selection flags.
956
\sa QwtPicker, selectionFlags()
957
\sa eventFilter(), widgetMousePressEvent(),
958
widgetMouseDoubleClickEvent(), widgetMouseMoveEvent(),
959
widgetWheelEvent(), widgetKeyPressEvent(), widgetKeyReleaseEvent()
961
void QwtPicker::widgetMouseReleaseEvent(QMouseEvent *e)
967
Handle mouse double click event for the observed widget.
969
Empty implementation, does nothing.
971
\sa eventFilter(), widgetMousePressEvent(), widgetMouseReleaseEvent(),
972
widgetMouseMoveEvent(),
973
widgetWheelEvent(), widgetKeyPressEvent(), widgetKeyReleaseEvent()
975
void QwtPicker::widgetMouseDoubleClickEvent(QMouseEvent *me)
982
Handle a wheel event for the observed widget.
984
Move the last point of the selection in case of isActive() == true
986
\sa eventFilter(), widgetMousePressEvent(), widgetMouseReleaseEvent(),
987
widgetMouseDoubleClickEvent(), widgetMouseMoveEvent(),
988
widgetKeyPressEvent(), widgetKeyReleaseEvent()
990
void QwtPicker::widgetWheelEvent(QWheelEvent *e)
992
if ( pickRect().contains(e->pos()) )
993
d_data->trackerPosition = e->pos();
995
d_data->trackerPosition = QPoint(-1, -1);
1003
Handle a key press event for the observed widget.
1005
Selections can be completely done by the keyboard. The arrow keys
1006
move the cursor, the abort key aborts a selection. All other keys
1007
are handled by the current state machine.
1009
\sa QwtPicker, selectionFlags()
1010
\sa eventFilter(), widgetMousePressEvent(), widgetMouseReleaseEvent(),
1011
widgetMouseDoubleClickEvent(), widgetMouseMoveEvent(),
1012
widgetWheelEvent(), widgetKeyReleaseEvent(), stateMachine(),
1013
QwtEventPattern::KeyPatternCode
1015
void QwtPicker::widgetKeyPressEvent(QKeyEvent *ke)
1021
if ( ke->isAutoRepeat() )
1024
if ( keyMatch(KeyLeft, ke) )
1026
else if ( keyMatch(KeyRight, ke) )
1028
else if ( keyMatch(KeyUp, ke) )
1030
else if ( keyMatch(KeyDown, ke) )
1032
else if ( keyMatch(KeyAbort, ke) )
1039
if ( dx != 0 || dy != 0 )
1041
const QRect rect = pickRect();
1042
const QPoint pos = parentWidget()->mapFromGlobal(QCursor::pos());
1044
int x = pos.x() + dx;
1045
x = qwtMax(rect.left(), x);
1046
x = qwtMin(rect.right(), x);
1048
int y = pos.y() + dy;
1049
y = qwtMax(rect.top(), y);
1050
y = qwtMin(rect.bottom(), y);
1052
QCursor::setPos(parentWidget()->mapToGlobal(QPoint(x, y)));
1057
Handle a key release event for the observed widget.
1059
Passes the event to the state machine.
1061
\sa eventFilter(), widgetMousePressEvent(), widgetMouseReleaseEvent(),
1062
widgetMouseDoubleClickEvent(), widgetMouseMoveEvent(),
1063
widgetWheelEvent(), widgetKeyPressEvent(), stateMachine()
1065
void QwtPicker::widgetKeyReleaseEvent(QKeyEvent *ke)
1071
Passes an event to the state machine and executes the resulting
1072
commands. Append and Move commands use the current position
1073
of the cursor (QCursor::pos()).
1077
void QwtPicker::transition(const QEvent *e)
1079
if ( !d_data->stateMachine )
1082
QwtPickerMachine::CommandList commandList =
1083
d_data->stateMachine->transition(*this, e);
1088
case QEvent::MouseButtonDblClick:
1089
case QEvent::MouseButtonPress:
1090
case QEvent::MouseButtonRelease:
1091
case QEvent::MouseMove:
1093
const QMouseEvent *me = (QMouseEvent *)e;
1098
pos = parentWidget()->mapFromGlobal(QCursor::pos());
1101
for ( uint i = 0; i < (uint)commandList.count(); i++ )
1103
switch(commandList[i])
1105
case QwtPickerMachine::Begin:
1110
case QwtPickerMachine::Append:
1115
case QwtPickerMachine::Move:
1120
case QwtPickerMachine::End:
1130
Open a selection setting the state to active
1132
\sa isActive, end(), append(), move()
1134
void QwtPicker::begin()
1136
if ( d_data->isActive )
1139
d_data->selection.resize(0);
1140
d_data->isActive = true;
1142
if ( trackerMode() != AlwaysOff )
1144
if ( d_data->trackerPosition.x() < 0 || d_data->trackerPosition.y() < 0 )
1146
QWidget *w = parentWidget();
1148
d_data->trackerPosition = w->mapFromGlobal(QCursor::pos());
1153
setMouseTracking(true);
1157
\brief Close a selection setting the state to inactive.
1159
The selection is validated and maybe fixed by QwtPicker::accept().
1161
\param ok If true, complete the selection and emit a selected signal
1162
otherwise discard the selection.
1163
\return true if the selection is accepted, false otherwise
1164
\sa isActive, begin(), append(), move(), selected(), accept()
1166
bool QwtPicker::end(bool ok)
1168
if ( d_data->isActive )
1170
setMouseTracking(false);
1172
d_data->isActive = false;
1174
if ( trackerMode() == ActiveOnly )
1175
d_data->trackerPosition = QPoint(-1, -1);
1178
ok = accept(d_data->selection);
1181
emit selected(d_data->selection);
1183
d_data->selection.resize(0);
1194
Reset the state machine and terminate (end(false)) the selection
1196
void QwtPicker::reset()
1198
if ( d_data->stateMachine )
1199
d_data->stateMachine->reset();
1206
Append a point to the selection and update rubberband and tracker.
1207
The appended() signal is emitted.
1209
\param pos Additional point
1211
\sa isActive, begin(), end(), move(), appended()
1213
void QwtPicker::append(const QPoint &pos)
1215
if ( d_data->isActive )
1217
const int idx = d_data->selection.count();
1218
d_data->selection.resize(idx + 1);
1219
d_data->selection[idx] = pos;
1228
Move the last point of the selection
1229
The moved() signal is emitted.
1231
\param pos New position
1232
\sa isActive, begin(), end(), append()
1235
void QwtPicker::move(const QPoint &pos)
1237
if ( d_data->isActive )
1239
const int idx = d_data->selection.count() - 1;
1242
if ( d_data->selection[idx] != pos )
1244
d_data->selection[idx] = pos;
1254
bool QwtPicker::accept(QwtPolygon &) const
1260
A picker is active between begin() and end().
1261
\return true if the selection is active.
1263
bool QwtPicker::isActive() const
1265
return d_data->isActive;
1268
//! Return Selected points
1269
const QwtPolygon &QwtPicker::selection() const
1271
return d_data->selection;
1275
Scale the selection by the ratios of oldSize and newSize
1276
The changed() signal is emitted.
1278
\param oldSize Previous size
1279
\param newSize Current size
1281
\sa ResizeMode, setResizeMode(), resizeMode()
1283
void QwtPicker::stretchSelection(const QSize &oldSize, const QSize &newSize)
1285
if ( oldSize.isEmpty() )
1287
// avoid division by zero. But scaling for small sizes also
1288
// doesn't make much sense, because of rounding losses. TODO ...
1292
const double xRatio =
1293
double(newSize.width()) / double(oldSize.width());
1294
const double yRatio =
1295
double(newSize.height()) / double(oldSize.height());
1297
for ( int i = 0; i < int(d_data->selection.count()); i++ )
1299
QPoint &p = d_data->selection[i];
1300
p.setX(qRound(p.x() * xRatio));
1301
p.setY(qRound(p.y() * yRatio));
1303
emit changed(d_data->selection);
1308
Set mouse tracking for the observed widget.
1310
In case of enable is true, the previous value
1311
is saved, that is restored when enable is false.
1313
\warning Even when enable is false, mouse tracking might be restored
1314
to true. When mouseTracking for the observed widget
1315
has been changed directly by QWidget::setMouseTracking
1316
while mouse tracking has been set to true, this value can't
1320
void QwtPicker::setMouseTracking(bool enable)
1322
QWidget *widget = parentWidget();
1328
d_data->mouseTracking = widget->hasMouseTracking();
1329
widget->setMouseTracking(true);
1333
widget->setMouseTracking(d_data->mouseTracking);
1338
Find the area of the observed widget, where selection might happen.
1340
\return QFrame::contentsRect() if it is a QFrame, QWidget::rect() otherwise.
1342
QRect QwtPicker::pickRect() const
1346
const QWidget *widget = parentWidget();
1350
if ( widget->inherits("QFrame") )
1351
rect = ((QFrame *)widget)->contentsRect();
1353
rect = widget->rect();
1358
void QwtPicker::updateDisplay()
1360
QWidget *w = parentWidget();
1362
bool showRubberband = false;
1363
bool showTracker = false;
1364
if ( w && w->isVisible() && d_data->enabled )
1366
if ( rubberBand() != NoRubberBand && isActive() &&
1367
rubberBandPen().style() != Qt::NoPen )
1369
showRubberband = true;
1372
if ( trackerMode() == AlwaysOn ||
1373
(trackerMode() == ActiveOnly && isActive() ) )
1375
if ( trackerPen() != Qt::NoPen )
1380
#if QT_VERSION < 0x040000
1381
QGuardedPtr<PickerWidget> &rw = d_data->rubberBandWidget;
1383
QPointer<PickerWidget> &rw = d_data->rubberBandWidget;
1385
if ( showRubberband )
1389
rw = new PickerWidget( this, w, PickerWidget::RubberBand);
1390
rw->resize(w->size());
1393
rw->update(); // Needed, when the mask doesn't change
1398
#if QT_VERSION < 0x040000
1399
QGuardedPtr<PickerWidget> &tw = d_data->trackerWidget;
1401
QPointer<PickerWidget> &tw = d_data->trackerWidget;
1407
tw = new PickerWidget( this, w, PickerWidget::Text);
1408
tw->resize(w->size());
1411
tw->update(); // Needed, when the mask doesn't change
1417
const QWidget *QwtPicker::rubberBandWidget() const
1419
return d_data->rubberBandWidget;
1422
const QWidget *QwtPicker::trackerWidget() const
1424
return d_data->trackerWidget;