Qwt User's Guide: qwt_picker.cpp Source File

Qwt User's Guide 6.2.0

qwt_picker.cpp
1 /******************************************************************************
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_picker.h"
11 #include "qwt_picker_machine.h"
12 #include "qwt_painter.h"
13 #include "qwt_math.h"
14 #include "qwt_widget_overlay.h"
15 #include "qwt_text.h"
16
17 #include <qevent.h>
18 #include <qpainter.h>
19 #include <qpainterpath.h>
20 #include <qcursor.h>
21 #include <qpointer.h>
22
23 static inline QRegion qwtMaskRegion( const QRect& r, int penWidth )
24 {
25 const int pw = qMax( penWidth, 1 );
26 const int pw2 = penWidth / 2;
27
28 int x1 = r.left() - pw2;
29 int x2 = r.right() + 1 + pw2 + ( pw % 2 );
30
31 int y1 = r.top() - pw2;
32 int y2 = r.bottom() + 1 + pw2 + ( pw % 2 );
33
34 QRegion region;
35
36 region += QRect( x1, y1, x2 - x1, pw );
37 region += QRect( x1, y1, pw, y2 - y1 );
38 region += QRect( x1, y2 - pw, x2 - x1, pw );
39 region += QRect( x2 - pw, y1, pw, y2 - y1 );
40
41 return region;
42 }
43
44 static inline QRegion qwtMaskRegion( const QLine& l, int penWidth )
45 {
46 const int pw = qMax( penWidth, 1 );
47 const int pw2 = penWidth / 2;
48
49 QRegion region;
50
51 if ( l.x1() == l.x2() )
52 {
53 region += QRect( l.x1() - pw2, l.y1(),
54 pw, l.y2() ).normalized();
55 }
56 else if ( l.y1() == l.y2() )
57 {
58 region += QRect( l.x1(), l.y1() - pw2,
59 l.x2(), pw ).normalized();
60 }
61
62 return region;
63 }
64
65 namespace
66 {
67 class Rubberband QWT_FINAL : public QwtWidgetOverlay
68 {
69 public:
70 Rubberband( QwtPicker* picker, QWidget* parent )
71 : QwtWidgetOverlay( parent )
72 , m_picker( picker )
73 {
74 setMaskMode( QwtWidgetOverlay::MaskHint );
75 }
76
77 protected:
78 virtual void drawOverlay( QPainter* painter ) const QWT_OVERRIDE
79 {
80 painter->setPen( m_picker->rubberBandPen() );
81 m_picker->drawRubberBand( painter );
82 }
83
84 virtual QRegion maskHint() const QWT_OVERRIDE
85 {
86 return m_picker->rubberBandMask();
87 }
88
89 QwtPicker* m_picker;
90 };
91
92 class Tracker QWT_FINAL : public QwtWidgetOverlay
93 {
94 public:
95 Tracker( QwtPicker* picker, QWidget* parent )
96 : QwtWidgetOverlay( parent )
97 , m_picker( picker )
98 {
99 setMaskMode( QwtWidgetOverlay::MaskHint );
100 }
101
102 protected:
103 virtual void drawOverlay( QPainter* painter ) const QWT_OVERRIDE
104 {
105 painter->setPen( m_picker->trackerPen() );
106 m_picker->drawTracker( painter );
107 }
108
109 virtual QRegion maskHint() const QWT_OVERRIDE
110 {
111 return m_picker->trackerMask();
112 }
113
114 QwtPicker* m_picker;
115 };
116 }
117
118 class QwtPicker::PrivateData
119 {
120 public:
121 PrivateData():
122 enabled( false ),
123 stateMachine( NULL ),
124 resizeMode( QwtPicker::Stretch ),
125 rubberBand( QwtPicker::NoRubberBand ),
126 trackerMode( QwtPicker::AlwaysOff ),
127 isActive( false ),
128 trackerPosition( -1, -1 ),
129 mouseTracking( false ),
130 openGL( false )
131 {
132 }
133
134 bool enabled;
135
136 QwtPickerMachine* stateMachine;
137
138 QwtPicker::ResizeMode resizeMode;
139
140 QwtPicker::RubberBand rubberBand;
141 QPen rubberBandPen;
142
143 QwtPicker::DisplayMode trackerMode;
144 QPen trackerPen;
145 QFont trackerFont;
146
147 QPolygon pickedPoints;
148 bool isActive;
149 QPoint trackerPosition;
150
151 bool mouseTracking; // used to save previous value
152
153 QPointer< Rubberband > rubberBandOverlay;
154 QPointer< Tracker > trackerOverlay;
155
156 bool openGL;
157 };
158
168 QwtPicker::QwtPicker( QWidget* parent ):
169 QObject( parent )
170 {
171 init( parent, NoRubberBand, AlwaysOff );
172 }
173
181 QwtPicker::QwtPicker( RubberBand rubberBand,
182 DisplayMode trackerMode, QWidget* parent ):
183 QObject( parent )
184 {
185 init( parent, rubberBand, trackerMode );
186 }
187
189 QwtPicker::~QwtPicker()
190 {
191 setMouseTracking( false );
192
193 delete m_data->stateMachine;
194 delete m_data->rubberBandOverlay;
195 delete m_data->trackerOverlay;
196
197 delete m_data;
198 }
199
201 void QwtPicker::init( QWidget* parent,
202 RubberBand rubberBand, DisplayMode trackerMode )
203 {
204 m_data = new PrivateData;
205
206 m_data->rubberBand = rubberBand;
207
208 if ( parent )
209 {
210 if ( parent->focusPolicy() == Qt::NoFocus )
211 parent->setFocusPolicy( Qt::WheelFocus );
212
213 m_data->openGL = parent->inherits( "QGLWidget" );
214 m_data->trackerFont = parent->font();
215 m_data->mouseTracking = parent->hasMouseTracking();
216
217 setEnabled( true );
218 }
219
220 setTrackerMode( trackerMode );
221 }
222
229 void QwtPicker::setStateMachine( QwtPickerMachine* stateMachine )
230 {
231 if ( m_data->stateMachine != stateMachine )
232 {
233 reset();
234
235 delete m_data->stateMachine;
236 m_data->stateMachine = stateMachine;
237
238 if ( m_data->stateMachine )
239 m_data->stateMachine->reset();
240 }
241 }
242
247 QwtPickerMachine* QwtPicker::stateMachine()
248 {
249 return m_data->stateMachine;
250 }
251
256 const QwtPickerMachine* QwtPicker::stateMachine() const
257 {
258 return m_data->stateMachine;
259 }
260
262 QWidget* QwtPicker::parentWidget()
263 {
264 QObject* obj = parent();
265 if ( obj && obj->isWidgetType() )
266 return static_cast< QWidget* >( obj );
267
268 return NULL;
269 }
270
272 const QWidget* QwtPicker::parentWidget() const
273 {
274 QObject* obj = parent();
275 if ( obj && obj->isWidgetType() )
276 return static_cast< const QWidget* >( obj );
277
278 return NULL;
279 }
280
289 void QwtPicker::setRubberBand( RubberBand rubberBand )
290 {
291 m_data->rubberBand = rubberBand;
292 }
293
298 QwtPicker::RubberBand QwtPicker::rubberBand() const
299 {
300 return m_data->rubberBand;
301 }
302
319 void QwtPicker::setTrackerMode( DisplayMode mode )
320 {
321 if ( m_data->trackerMode != mode )
322 {
323 m_data->trackerMode = mode;
324 setMouseTracking( m_data->trackerMode == AlwaysOn );
325 }
326 }
327
332 QwtPicker::DisplayMode QwtPicker::trackerMode() const
333 {
334 return m_data->trackerMode;
335 }
336
351 void QwtPicker::setResizeMode( ResizeMode mode )
352 {
353 m_data->resizeMode = mode;
354 }
355
361 QwtPicker::ResizeMode QwtPicker::resizeMode() const
362 {
363 return m_data->resizeMode;
364 }
365
375 void QwtPicker::setEnabled( bool enabled )
376 {
377 if ( m_data->enabled != enabled )
378 {
379 m_data->enabled = enabled;
380
381 QWidget* w = parentWidget();
382 if ( w )
383 {
384 if ( enabled )
385 w->installEventFilter( this );
386 else
387 w->removeEventFilter( this );
388 }
389
390 updateDisplay();
391 }
392 }
393
399 bool QwtPicker::isEnabled() const
400 {
401 return m_data->enabled;
402 }
403
410 void QwtPicker::setTrackerFont( const QFont& font )
411 {
412 if ( font != m_data->trackerFont )
413 {
414 m_data->trackerFont = font;
415 updateDisplay();
416 }
417 }
418
424 QFont QwtPicker::trackerFont() const
425 {
426 return m_data->trackerFont;
427 }
428
435 void QwtPicker::setTrackerPen( const QPen& pen )
436 {
437 if ( pen != m_data->trackerPen )
438 {
439 m_data->trackerPen = pen;
440 updateDisplay();
441 }
442 }
443
448 QPen QwtPicker::trackerPen() const
449 {
450 return m_data->trackerPen;
451 }
452
459 void QwtPicker::setRubberBandPen( const QPen& pen )
460 {
461 if ( pen != m_data->rubberBandPen )
462 {
463 m_data->rubberBandPen = pen;
464 updateDisplay();
465 }
466 }
467
472 QPen QwtPicker::rubberBandPen() const
473 {
474 return m_data->rubberBandPen;
475 }
476
490 QwtText QwtPicker::trackerText( const QPoint& pos ) const
491 {
492 QString label;
493
494 switch ( rubberBand() )
495 {
496 case HLineRubberBand:
497 label = QString::number( pos.y() );
498 break;
499 case VLineRubberBand:
500 label = QString::number( pos.x() );
501 break;
502 default:
503 label = QString::number( pos.x() ) + ", " + QString::number( pos.y() );
504 }
505 return label;
506 }
507
514 QRegion QwtPicker::trackerMask() const
515 {
516 return trackerRect( m_data->trackerFont );
517 }
518
525 QRegion QwtPicker::rubberBandMask() const
526 {
527 QRegion mask;
528
529 if ( !isActive() || rubberBand() == NoRubberBand ||
530 rubberBandPen().style() == Qt::NoPen )
531 {
532 return mask;
533 }
534
535 const QPolygon pa = adjustedPoints( m_data->pickedPoints );
536
537 QwtPickerMachine::SelectionType selectionType =
538 QwtPickerMachine::NoSelection;
539
540 if ( m_data->stateMachine )
541 selectionType = m_data->stateMachine->selectionType();
542
543 switch ( selectionType )
544 {
545 case QwtPickerMachine::NoSelection:
546 case QwtPickerMachine::PointSelection:
547 {
548 if ( pa.count() < 1 )
549 return mask;
550
551 const QPoint pos = pa[0];
552 const int pw = rubberBandPen().width();
553
554 const QRect pRect = pickArea().boundingRect().toRect();
555 switch ( rubberBand() )
556 {
557 case VLineRubberBand:
558 {
559 mask += qwtMaskRegion( QLine( pos.x(), pRect.top(),
560 pos.x(), pRect.bottom() ), pw );
561 break;
562 }
563 case HLineRubberBand:
564 {
565 mask += qwtMaskRegion( QLine( pRect.left(), pos.y(),
566 pRect.right(), pos.y() ), pw );
567 break;
568 }
569 case CrossRubberBand:
570 {
571 mask += qwtMaskRegion( QLine( pos.x(), pRect.top(),
572 pos.x(), pRect.bottom() ), pw );
573 mask += qwtMaskRegion( QLine( pRect.left(), pos.y(),
574 pRect.right(), pos.y() ), pw );
575 break;
576 }
577 default:
578 break;
579 }
580 break;
581 }
582 case QwtPickerMachine::RectSelection:
583 {
584 if ( pa.count() < 2 )
585 return mask;
586
587 const int pw = rubberBandPen().width();
588
589 switch ( rubberBand() )
590 {
591 case RectRubberBand:
592 {
593 const QRect r = QRect( pa.first(), pa.last() );
594 mask = qwtMaskRegion( r.normalized(), pw );
595 break;
596 }
597 case EllipseRubberBand:
598 {
599 const QRect r = QRect( pa.first(), pa.last() );
600 mask += r.adjusted( -pw, -pw, pw, pw );
601 break;
602 }
603 default:
604 break;
605 }
606 break;
607 }
608 case QwtPickerMachine::PolygonSelection:
609 {
610 const int pw = rubberBandPen().width();
611 if ( pw <= 1 )
612 {
613 // because of the join style we better
614 // return a mask for a pen width <= 1 only
615
616 const int off = 2 * pw;
617 const QRect r = pa.boundingRect();
618 mask += r.adjusted( -off, -off, off, off );
619 }
620 break;
621 }
622 default:
623 break;
624 }
625
626 return mask;
627 }
628
637 void QwtPicker::drawRubberBand( QPainter* painter ) const
638 {
639 if ( !isActive() || rubberBand() == NoRubberBand ||
640 rubberBandPen().style() == Qt::NoPen )
641 {
642 return;
643 }
644
645 const QPolygon pa = adjustedPoints( m_data->pickedPoints );
646
647 QwtPickerMachine::SelectionType selectionType =
648 QwtPickerMachine::NoSelection;
649
650 if ( m_data->stateMachine )
651 selectionType = m_data->stateMachine->selectionType();
652
653 switch ( selectionType )
654 {
655 case QwtPickerMachine::NoSelection:
656 case QwtPickerMachine::PointSelection:
657 {
658 if ( pa.count() < 1 )
659 return;
660
661 const QPoint pos = pa[0];
662
663 const QRect pRect = pickArea().boundingRect().toRect();
664 switch ( rubberBand() )
665 {
666 case VLineRubberBand:
667 {
668 QwtPainter::drawLine( painter, pos.x(),
669 pRect.top(), pos.x(), pRect.bottom() );
670 break;
671 }
672 case HLineRubberBand:
673 {
674 QwtPainter::drawLine( painter, pRect.left(),
675 pos.y(), pRect.right(), pos.y() );
676 break;
677 }
678 case CrossRubberBand:
679 {
680 QwtPainter::drawLine( painter, pos.x(),
681 pRect.top(), pos.x(), pRect.bottom() );
682 QwtPainter::drawLine( painter, pRect.left(),
683 pos.y(), pRect.right(), pos.y() );
684 break;
685 }
686 default:
687 break;
688 }
689 break;
690 }
691 case QwtPickerMachine::RectSelection:
692 {
693 if ( pa.count() < 2 )
694 return;
695
696 const QRect rect = QRect( pa.first(), pa.last() ).normalized();
697 switch ( rubberBand() )
698 {
699 case EllipseRubberBand:
700 {
701 QwtPainter::drawEllipse( painter, rect );
702 break;
703 }
704 case RectRubberBand:
705 {
706 QwtPainter::drawRect( painter, rect );
707 break;
708 }
709 default:
710 break;
711 }
712 break;
713 }
714 case QwtPickerMachine::PolygonSelection:
715 {
716 if ( rubberBand() == PolygonRubberBand )
717 painter->drawPolyline( pa );
718 break;
719 }
720 default:
721 break;
722 }
723 }
724
732 void QwtPicker::drawTracker( QPainter* painter ) const
733 {
734 const QRect textRect = trackerRect( painter->font() );
735 if ( !textRect.isEmpty() )
736 {
737 const QwtText label = trackerText( m_data->trackerPosition );
738 if ( !label.isEmpty() )
739 label.draw( painter, textRect );
740 }
741 }
742
783 QPolygon QwtPicker::adjustedPoints( const QPolygon& points ) const
784 {
785 return points;
786 }
787
792 QPolygon QwtPicker::selection() const
793 {
794 return adjustedPoints( m_data->pickedPoints );
795 }
796
798 QPoint QwtPicker::trackerPosition() const
799 {
800 return m_data->trackerPosition;
801 }
802
812 QRect QwtPicker::trackerRect( const QFont& font ) const
813 {
814 if ( trackerMode() == AlwaysOff ||
815 ( trackerMode() == ActiveOnly && !isActive() ) )
816 {
817 return QRect();
818 }
819
820 if ( m_data->trackerPosition.x() < 0 || m_data->trackerPosition.y() < 0 )
821 return QRect();
822
823 QwtText text = trackerText( m_data->trackerPosition );
824 if ( text.isEmpty() )
825 return QRect();
826
827 const QSizeF textSize = text.textSize( font );
828 QRect textRect( 0, 0, qwtCeil( textSize.width() ), qwtCeil( textSize.height() ) );
829
830 const QPoint& pos = m_data->trackerPosition;
831
832 int alignment = 0;
833 if ( isActive() && m_data->pickedPoints.count() > 1
834 && rubberBand() != NoRubberBand )
835 {
836 const QPoint last =
837 m_data->pickedPoints[ m_data->pickedPoints.count() - 2 ];
838
839 alignment |= ( pos.x() >= last.x() ) ? Qt::AlignRight : Qt::AlignLeft;
840 alignment |= ( pos.y() > last.y() ) ? Qt::AlignBottom : Qt::AlignTop;
841 }
842 else
843 alignment = Qt::AlignTop | Qt::AlignRight;
844
845 const int margin = 5;
846
847 int x = pos.x();
848 if ( alignment & Qt::AlignLeft )
849 x -= textRect.width() + margin;
850 else if ( alignment & Qt::AlignRight )
851 x += margin;
852
853 int y = pos.y();
854 if ( alignment & Qt::AlignBottom )
855 y += margin;
856 else if ( alignment & Qt::AlignTop )
857 y -= textRect.height() + margin;
858
859 textRect.moveTopLeft( QPoint( x, y ) );
860
861 const QRect pickRect = pickArea().boundingRect().toRect();
862
863 int right = qMin( textRect.right(), pickRect.right() - margin );
864 int bottom = qMin( textRect.bottom(), pickRect.bottom() - margin );
865 textRect.moveBottomRight( QPoint( right, bottom ) );
866
867 int left = qMax( textRect.left(), pickRect.left() + margin );
868 int top = qMax( textRect.top(), pickRect.top() + margin );
869 textRect.moveTopLeft( QPoint( left, top ) );
870
871 return textRect;
872 }
873
893 bool QwtPicker::eventFilter( QObject* object, QEvent* event )
894 {
895 if ( object && object == parentWidget() )
896 {
897 switch ( event->type() )
898 {
899 case QEvent::Resize:
900 {
901 const QResizeEvent* re = static_cast< QResizeEvent* >( event );
902
903 /*
904 Adding/deleting additional event filters inside of an event filter
905 is not safe dues to the implementation in Qt ( changing a list while iterating ).
906 So we create the overlays in a way, that they don't install en event filter
907 ( parent set to NULL ) and do the resizing here.
908 */
909 if ( m_data->trackerOverlay )
910 m_data->trackerOverlay->resize( re->size() );
911
912 if ( m_data->rubberBandOverlay )
913 m_data->rubberBandOverlay->resize( re->size() );
914
915 if ( m_data->resizeMode == Stretch )
916 stretchSelection( re->oldSize(), re->size() );
917
918 updateDisplay();
919 break;
920 }
921 case QEvent::Enter:
922 {
923 widgetEnterEvent( event );
924 break;
925 }
926 case QEvent::Leave:
927 {
928 widgetLeaveEvent( event );
929 break;
930 }
931 case QEvent::MouseButtonPress:
932 {
933 widgetMousePressEvent( static_cast< QMouseEvent* >( event ) );
934 break;
935 }
936 case QEvent::MouseButtonRelease:
937 {
938 widgetMouseReleaseEvent( static_cast< QMouseEvent* >( event ) );
939 break;
940 }
941 case QEvent::MouseButtonDblClick:
942 {
943 widgetMouseDoubleClickEvent( static_cast< QMouseEvent* >( event ) );
944 break;
945 }
946 case QEvent::MouseMove:
947 {
948 widgetMouseMoveEvent( static_cast< QMouseEvent* >( event ) );
949 break;
950 }
951 case QEvent::KeyPress:
952 {
953 widgetKeyPressEvent( static_cast< QKeyEvent* >( event ) );
954 break;
955 }
956 case QEvent::KeyRelease:
957 {
958 widgetKeyReleaseEvent( static_cast< QKeyEvent* >( event ) );
959 break;
960 }
961 case QEvent::Wheel:
962 {
963 widgetWheelEvent( static_cast< QWheelEvent* >( event ) );
964 break;
965 }
966 default:
967 break;
968 }
969 }
970 return false;
971 }
972
982 void QwtPicker::widgetMousePressEvent( QMouseEvent* mouseEvent )
983 {
984 transition( mouseEvent );
985 }
986
996 void QwtPicker::widgetMouseMoveEvent( QMouseEvent* mouseEvent )
997 {
998 if ( pickArea().contains( mouseEvent->pos() ) )
999 m_data->trackerPosition = mouseEvent->pos();
1000 else
1001 m_data->trackerPosition = QPoint( -1, -1 );
1002
1003 if ( !isActive() )
1004 updateDisplay();
1005
1006 transition( mouseEvent );
1007 }
1008
1018 void QwtPicker::widgetEnterEvent( QEvent* event )
1019 {
1020 transition( event );
1021 }
1022
1032 void QwtPicker::widgetLeaveEvent( QEvent* event )
1033 {
1034 transition( event );
1035
1036 m_data->trackerPosition = QPoint( -1, -1 );
1037 if ( !isActive() )
1038 updateDisplay();
1039 }
1040
1050 void QwtPicker::widgetMouseReleaseEvent( QMouseEvent* mouseEvent )
1051 {
1052 transition( mouseEvent );
1053 }
1054
1064 void QwtPicker::widgetMouseDoubleClickEvent( QMouseEvent* mouseEvent )
1065 {
1066 transition( mouseEvent );
1067 }
1068
1069
1081 void QwtPicker::widgetWheelEvent( QWheelEvent* wheelEvent )
1082 {
1083 #if QT_VERSION < 0x050e00
1084 const QPoint wheelPos = wheelEvent->pos();
1085 #else
1086 const QPoint wheelPos = wheelEvent->position().toPoint();
1087 #endif
1088 if ( pickArea().contains( wheelPos ) )
1089 m_data->trackerPosition = wheelPos;
1090 else
1091 m_data->trackerPosition = QPoint( -1, -1 );
1092
1093 updateDisplay();
1094
1095 transition( wheelEvent );
1096 }
1097
1112 void QwtPicker::widgetKeyPressEvent( QKeyEvent* keyEvent )
1113 {
1114 int dx = 0;
1115 int dy = 0;
1116
1117 int offset = 1;
1118 if ( keyEvent->isAutoRepeat() )
1119 offset = 5;
1120
1121 if ( keyMatch( KeyLeft, keyEvent ) )
1122 dx = -offset;
1123 else if ( keyMatch( KeyRight, keyEvent ) )
1124 dx = offset;
1125 else if ( keyMatch( KeyUp, keyEvent ) )
1126 dy = -offset;
1127 else if ( keyMatch( KeyDown, keyEvent ) )
1128 dy = offset;
1129 else if ( keyMatch( KeyAbort, keyEvent ) )
1130 {
1131 reset();
1132 }
1133 else
1134 transition( keyEvent );
1135
1136 if ( dx != 0 || dy != 0 )
1137 {
1138 const QRect rect = pickArea().boundingRect().toRect();
1139 const QPoint pos = parentWidget()->mapFromGlobal( QCursor::pos() );
1140
1141 int x = pos.x() + dx;
1142 x = qMax( rect.left(), x );
1143 x = qMin( rect.right(), x );
1144
1145 int y = pos.y() + dy;
1146 y = qMax( rect.top(), y );
1147 y = qMin( rect.bottom(), y );
1148
1149 QCursor::setPos( parentWidget()->mapToGlobal( QPoint( x, y ) ) );
1150 }
1151 }
1152
1164 void QwtPicker::widgetKeyReleaseEvent( QKeyEvent* keyEvent )
1165 {
1166 transition( keyEvent );
1167 }
1168
1176 void QwtPicker::transition( const QEvent* event )
1177 {
1178 if ( !m_data->stateMachine )
1179 return;
1180
1181 const QList< QwtPickerMachine::Command > commandList =
1182 m_data->stateMachine->transition( *this, event );
1183
1184 QPoint pos;
1185 switch ( event->type() )
1186 {
1187 case QEvent::MouseButtonDblClick:
1188 case QEvent::MouseButtonPress:
1189 case QEvent::MouseButtonRelease:
1190 case QEvent::MouseMove:
1191 {
1192 const QMouseEvent* me =
1193 static_cast< const QMouseEvent* >( event );
1194 pos = me->pos();
1195 break;
1196 }
1197 default:
1198 pos = parentWidget()->mapFromGlobal( QCursor::pos() );
1199 }
1200
1201 for ( int i = 0; i < commandList.count(); i++ )
1202 {
1203 switch ( commandList[i] )
1204 {
1205 case QwtPickerMachine::Begin:
1206 {
1207 begin();
1208 break;
1209 }
1210 case QwtPickerMachine::Append:
1211 {
1212 append( pos );
1213 break;
1214 }
1215 case QwtPickerMachine::Move:
1216 {
1217 move( pos );
1218 break;
1219 }
1220 case QwtPickerMachine::Remove:
1221 {
1222 remove();
1223 break;
1224 }
1225 case QwtPickerMachine::End:
1226 {
1227 end();
1228 break;
1229 }
1230 }
1231 }
1232 }
1233
1239 void QwtPicker::begin()
1240 {
1241 if ( m_data->isActive )
1242 return;
1243
1244 m_data->pickedPoints.clear();
1245 m_data->isActive = true;
1246 Q_EMIT activated( true );
1247
1248 if ( trackerMode() != AlwaysOff )
1249 {
1250 if ( m_data->trackerPosition.x() < 0 || m_data->trackerPosition.y() < 0 )
1251 {
1252 QWidget* w = parentWidget();
1253 if ( w )
1254 m_data->trackerPosition = w->mapFromGlobal( QCursor::pos() );
1255 }
1256 }
1257
1258 updateDisplay();
1259 setMouseTracking( true );
1260 }
1261
1272 bool QwtPicker::end( bool ok )
1273 {
1274 if ( m_data->isActive )
1275 {
1276 setMouseTracking( false );
1277
1278 m_data->isActive = false;
1279 Q_EMIT activated( false );
1280
1281 if ( trackerMode() == ActiveOnly )
1282 m_data->trackerPosition = QPoint( -1, -1 );
1283
1284 if ( ok )
1285 ok = accept( m_data->pickedPoints );
1286
1287 if ( ok )
1288 Q_EMIT selected( m_data->pickedPoints );
1289 else
1290 m_data->pickedPoints.clear();
1291
1292 updateDisplay();
1293 }
1294 else
1295 ok = false;
1296
1297 return ok;
1298 }
1299
1303 void QwtPicker::reset()
1304 {
1305 if ( m_data->stateMachine )
1306 m_data->stateMachine->reset();
1307
1308 if ( isActive() )
1309 end( false );
1310 }
1311
1320 void QwtPicker::append( const QPoint& pos )
1321 {
1322 if ( m_data->isActive )
1323 {
1324 m_data->pickedPoints += pos;
1325
1326 updateDisplay();
1327 Q_EMIT appended( pos );
1328 }
1329 }
1330
1338 void QwtPicker::move( const QPoint& pos )
1339 {
1340 if ( m_data->isActive && !m_data->pickedPoints.isEmpty() )
1341 {
1342 QPoint& point = m_data->pickedPoints.last();
1343 if ( point != pos )
1344 {
1345 point = pos;
1346
1347 updateDisplay();
1348 Q_EMIT moved( pos );
1349 }
1350 }
1351 }
1352
1359 void QwtPicker::remove()
1360 {
1361 if ( m_data->isActive && !m_data->pickedPoints.isEmpty() )
1362 {
1363 #if QT_VERSION >= 0x050100
1364 const QPoint pos = m_data->pickedPoints.takeLast();
1365 #else
1366 const QPoint pos = m_data->pickedPoints.last();
1367 m_data->pickedPoints.resize( m_data->pickedPoints.count() - 1 );
1368 #endif
1369
1370 updateDisplay();
1371 Q_EMIT removed( pos );
1372 }
1373 }
1374
1383 bool QwtPicker::accept( QPolygon& selection ) const
1384 {
1385 Q_UNUSED( selection );
1386 return true;
1387 }
1388
1393 bool QwtPicker::isActive() const
1394 {
1395 return m_data->isActive;
1396 }
1397
1403 const QPolygon& QwtPicker::pickedPoints() const
1404 {
1405 return m_data->pickedPoints;
1406 }
1407
1417 void QwtPicker::stretchSelection( const QSize& oldSize, const QSize& newSize )
1418 {
1419 if ( oldSize.isEmpty() )
1420 {
1421 // avoid division by zero. But scaling for small sizes also
1422 // doesn't make much sense, because of rounding losses. TODO ...
1423 return;
1424 }
1425
1426 const double xRatio = double( newSize.width() ) / double( oldSize.width() );
1427 const double yRatio = double( newSize.height() ) / double( oldSize.height() );
1428
1429 for ( int i = 0; i < m_data->pickedPoints.count(); i++ )
1430 {
1431 QPoint& p = m_data->pickedPoints[i];
1432 p.setX( qRound( p.x() * xRatio ) );
1433 p.setY( qRound( p.y() * yRatio ) );
1434
1435 Q_EMIT changed( m_data->pickedPoints );
1436 }
1437 }
1438
1452 void QwtPicker::setMouseTracking( bool enable )
1453 {
1454 QWidget* widget = parentWidget();
1455 if ( !widget )
1456 return;
1457
1458 if ( enable )
1459 {
1460 m_data->mouseTracking = widget->hasMouseTracking();
1461 widget->setMouseTracking( true );
1462 }
1463 else
1464 {
1465 widget->setMouseTracking( m_data->mouseTracking );
1466 }
1467 }
1468
1474 QPainterPath QwtPicker::pickArea() const
1475 {
1476 QPainterPath path;
1477
1478 const QWidget* widget = parentWidget();
1479 if ( widget )
1480 path.addRect( widget->contentsRect() );
1481
1482 return path;
1483 }
1484
1486 void QwtPicker::updateDisplay()
1487 {
1488 QWidget* w = parentWidget();
1489
1490 bool showRubberband = false;
1491 bool showTracker = false;
1492
1493 if ( w && w->isVisible() && m_data->enabled )
1494 {
1495 if ( rubberBand() != NoRubberBand && isActive() &&
1496 rubberBandPen().style() != Qt::NoPen )
1497 {
1498 showRubberband = true;
1499 }
1500
1501 if ( trackerMode() == AlwaysOn ||
1502 ( trackerMode() == ActiveOnly && isActive() ) )
1503 {
1504 if ( trackerPen() != Qt::NoPen
1505 && !trackerRect( QFont() ).isEmpty() )
1506 {
1507 showTracker = true;
1508 }
1509 }
1510 }
1511
1512 QPointer< Rubberband >& rw = m_data->rubberBandOverlay;
1513 if ( showRubberband )
1514 {
1515 if ( rw.isNull() )
1516 {
1517 rw = new Rubberband( this, NULL ); // NULL -> no extra event filter
1518 rw->setObjectName( "PickerRubberBand" );
1519 rw->setParent( w );
1520 rw->resize( w->size() );
1521 }
1522
1523 if ( m_data->rubberBand <= RectRubberBand )
1524 rw->setMaskMode( QwtWidgetOverlay::MaskHint );
1525 else
1526 rw->setMaskMode( QwtWidgetOverlay::AlphaMask );
1527
1528 rw->updateOverlay();
1529 }
1530 else
1531 {
1532 if ( m_data->openGL )
1533 {
1534 // Qt 4.8 crashes for a delete
1535 if ( !rw.isNull() )
1536 {
1537 rw->hide();
1538 rw->deleteLater();
1539 rw = NULL;
1540 }
1541 }
1542 else
1543 {
1544 delete rw;
1545 }
1546 }
1547
1548 QPointer< Tracker >& tw = m_data->trackerOverlay;
1549 if ( showTracker )
1550 {
1551 if ( tw.isNull() )
1552 {
1553 tw = new Tracker( this, NULL ); // NULL -> no extra event filter
1554 tw->setObjectName( "PickerTracker" );
1555 tw->setParent( w );
1556 tw->resize( w->size() );
1557 }
1558 tw->setFont( m_data->trackerFont );
1559 tw->updateOverlay();
1560 }
1561 else
1562 {
1563 if ( m_data->openGL )
1564 {
1565 // Qt 4.8 crashes for a delete
1566 if ( !tw.isNull() )
1567 {
1568 tw->hide();
1569 tw->deleteLater();
1570 tw = NULL;
1571 }
1572 }
1573 else
1574 {
1575 delete tw;
1576 }
1577 }
1578 }
1579
1581 const QwtWidgetOverlay* QwtPicker::rubberBandOverlay() const
1582 {
1583 return m_data->rubberBandOverlay;
1584 }
1585
1587 const QwtWidgetOverlay* QwtPicker::trackerOverlay() const
1588 {
1589 return m_data->trackerOverlay;
1590 }
1591
1592 #if QWT_MOC_INCLUDE
1593 #include "moc_qwt_picker.cpp"
1594 #endif
QList
Definition: qwt_abstract_legend.h:17
QwtEventPattern::keyMatch
bool keyMatch(KeyPatternCode, const QKeyEvent *) const
Compare a key event with an event pattern.
Definition: qwt_event_pattern.cpp:234
QwtEventPattern::KeyDown
@ KeyDown
Qt::Key_Down.
Definition: qwt_event_pattern.h:133
QwtEventPattern::KeyUp
@ KeyUp
Qt::Key_Up.
Definition: qwt_event_pattern.h:130
QwtEventPattern::KeyAbort
@ KeyAbort
Qt::Key_Escape.
Definition: qwt_event_pattern.h:121
QwtEventPattern::KeyRight
@ KeyRight
Qt::Key_Right.
Definition: qwt_event_pattern.h:127
QwtEventPattern::KeyLeft
@ KeyLeft
Qt::Key_Left.
Definition: qwt_event_pattern.h:124
QwtPainter::drawEllipse
static void drawEllipse(QPainter *, const QRectF &)
Wrapper for QPainter::drawEllipse()
Definition: qwt_painter.cpp:426
QwtPainter::drawRect
static void drawRect(QPainter *, qreal x, qreal y, qreal w, qreal h)
Wrapper for QPainter::drawRect()
Definition: qwt_painter.cpp:347
QwtPainter::drawLine
static void drawLine(QPainter *, qreal x1, qreal y1, qreal x2, qreal y2)
Wrapper for QPainter::drawLine()
Definition: qwt_painter.h:154
QwtPicker
QwtPicker provides selections on a widget.
Definition: qwt_picker.h:104
QwtPicker::DisplayMode
DisplayMode
Display mode.
Definition: qwt_picker.h:162
QwtPicker::AlwaysOn
@ AlwaysOn
Display always.
Definition: qwt_picker.h:167
QwtPicker::AlwaysOff
@ AlwaysOff
Display never.
Definition: qwt_picker.h:164
QwtPicker::ActiveOnly
@ ActiveOnly
Display only when the selection is active.
Definition: qwt_picker.h:170
QwtPicker::updateDisplay
virtual void updateDisplay()
Update the state of rubber band and tracker label.
Definition: qwt_picker.cpp:1486
QwtPicker::trackerFont
QFont trackerFont() const
Definition: qwt_picker.cpp:424
QwtPicker::resizeMode
ResizeMode resizeMode() const
Definition: qwt_picker.cpp:361
QwtPicker::reset
virtual void reset()
Definition: qwt_picker.cpp:1303
QwtPicker::drawRubberBand
virtual void drawRubberBand(QPainter *) const
Definition: qwt_picker.cpp:637
QwtPicker::rubberBand
RubberBand rubberBand() const
Definition: qwt_picker.cpp:298
QwtPicker::setRubberBandPen
void setRubberBandPen(const QPen &)
Definition: qwt_picker.cpp:459
QwtPicker::trackerMask
virtual QRegion trackerMask() const
Definition: qwt_picker.cpp:514
QwtPicker::remove
virtual void remove()
Definition: qwt_picker.cpp:1359
QwtPicker::stretchSelection
virtual void stretchSelection(const QSize &oldSize, const QSize &newSize)
Definition: qwt_picker.cpp:1417
QwtPicker::eventFilter
virtual bool eventFilter(QObject *, QEvent *) override
Event filter.
Definition: qwt_picker.cpp:893
QwtPicker::selected
void selected(const QPolygon &polygon)
QwtPicker::rubberBandPen
QPen rubberBandPen() const
Definition: qwt_picker.cpp:472
QwtPicker::rubberBandOverlay
const QwtWidgetOverlay * rubberBandOverlay() const
Definition: qwt_picker.cpp:1581
QwtPicker::begin
virtual void begin()
Definition: qwt_picker.cpp:1239
QwtPicker::widgetMousePressEvent
virtual void widgetMousePressEvent(QMouseEvent *)
Definition: qwt_picker.cpp:982
QwtPicker::move
virtual void move(const QPoint &)
Definition: qwt_picker.cpp:1338
QwtPicker::~QwtPicker
virtual ~QwtPicker()
Destructor.
Definition: qwt_picker.cpp:189
QwtPicker::append
virtual void append(const QPoint &)
Definition: qwt_picker.cpp:1320
QwtPicker::setStateMachine
void setStateMachine(QwtPickerMachine *)
Definition: qwt_picker.cpp:229
QwtPicker::drawTracker
virtual void drawTracker(QPainter *) const
Definition: qwt_picker.cpp:732
QwtPicker::trackerPen
QPen trackerPen() const
Definition: qwt_picker.cpp:448
QwtPicker::rubberBandMask
virtual QRegion rubberBandMask() const
Definition: qwt_picker.cpp:525
QwtPicker::trackerPosition
QPoint trackerPosition() const
Definition: qwt_picker.cpp:798
QwtPicker::widgetEnterEvent
virtual void widgetEnterEvent(QEvent *)
Definition: qwt_picker.cpp:1018
QwtPicker::setRubberBand
void setRubberBand(RubberBand)
Definition: qwt_picker.cpp:289
QwtPicker::trackerOverlay
const QwtWidgetOverlay * trackerOverlay() const
Definition: qwt_picker.cpp:1587
QwtPicker::widgetMouseMoveEvent
virtual void widgetMouseMoveEvent(QMouseEvent *)
Definition: qwt_picker.cpp:996
QwtPicker::activated
void activated(bool on)
QwtPicker::widgetLeaveEvent
virtual void widgetLeaveEvent(QEvent *)
Definition: qwt_picker.cpp:1032
QwtPicker::transition
virtual void transition(const QEvent *)
Definition: qwt_picker.cpp:1176
QwtPicker::accept
virtual bool accept(QPolygon &) const
Validate and fix up the selection.
Definition: qwt_picker.cpp:1383
QwtPicker::setTrackerMode
void setTrackerMode(DisplayMode)
Set the display mode of the tracker.
Definition: qwt_picker.cpp:319
QwtPicker::pickArea
virtual QPainterPath pickArea() const
Definition: qwt_picker.cpp:1474
QwtPicker::isActive
bool isActive() const
Definition: qwt_picker.cpp:1393
QwtPicker::widgetKeyReleaseEvent
virtual void widgetKeyReleaseEvent(QKeyEvent *)
Definition: qwt_picker.cpp:1164
QwtPicker::setTrackerFont
void setTrackerFont(const QFont &)
Definition: qwt_picker.cpp:410
QwtPicker::setEnabled
void setEnabled(bool)
En/disable the picker.
Definition: qwt_picker.cpp:375
QwtPicker::isEnabled
bool isEnabled() const
Definition: qwt_picker.cpp:399
QwtPicker::trackerMode
DisplayMode trackerMode() const
Definition: qwt_picker.cpp:332
QwtPicker::adjustedPoints
virtual QPolygon adjustedPoints(const QPolygon &) const
Map the pickedPoints() into a selection()
Definition: qwt_picker.cpp:783
QwtPicker::RubberBand
RubberBand
Definition: qwt_picker.h:128
QwtPicker::VLineRubberBand
@ VLineRubberBand
A vertical line ( only for QwtPickerMachine::PointSelection )
Definition: qwt_picker.h:136
QwtPicker::CrossRubberBand
@ CrossRubberBand
A crosshair ( only for QwtPickerMachine::PointSelection )
Definition: qwt_picker.h:139
QwtPicker::EllipseRubberBand
@ EllipseRubberBand
An ellipse ( only for QwtPickerMachine::RectSelection )
Definition: qwt_picker.h:145
QwtPicker::PolygonRubberBand
@ PolygonRubberBand
A polygon ( only for QwtPickerMachine::PolygonSelection )
Definition: qwt_picker.h:148
QwtPicker::HLineRubberBand
@ HLineRubberBand
A horizontal line ( only for QwtPickerMachine::PointSelection )
Definition: qwt_picker.h:133
QwtPicker::NoRubberBand
@ NoRubberBand
No rubberband.
Definition: qwt_picker.h:130
QwtPicker::RectRubberBand
@ RectRubberBand
A rectangle ( only for QwtPickerMachine::RectSelection )
Definition: qwt_picker.h:142
QwtPicker::ResizeMode
ResizeMode
Definition: qwt_picker.h:182
QwtPicker::Stretch
@ Stretch
All points are scaled according to the new size,.
Definition: qwt_picker.h:184
QwtPicker::trackerText
virtual QwtText trackerText(const QPoint &pos) const
Return the label for a position.
Definition: qwt_picker.cpp:490
QwtPicker::widgetMouseReleaseEvent
virtual void widgetMouseReleaseEvent(QMouseEvent *)
Definition: qwt_picker.cpp:1050
QwtPicker::end
virtual bool end(bool ok=true)
Close a selection setting the state to inactive.
Definition: qwt_picker.cpp:1272
QwtPicker::appended
void appended(const QPoint &pos)
QwtPicker::parentWidget
QWidget * parentWidget()
Return the parent widget, where the selection happens.
Definition: qwt_picker.cpp:262
QwtPicker::moved
void moved(const QPoint &pos)
QwtPicker::pickedPoints
const QPolygon & pickedPoints() const
Definition: qwt_picker.cpp:1403
QwtPicker::stateMachine
const QwtPickerMachine * stateMachine() const
Definition: qwt_picker.cpp:256
QwtPicker::removed
void removed(const QPoint &pos)
QwtPicker::changed
void changed(const QPolygon &selection)
QwtPicker::trackerRect
virtual QRect trackerRect(const QFont &) const
Definition: qwt_picker.cpp:812
QwtPicker::widgetMouseDoubleClickEvent
virtual void widgetMouseDoubleClickEvent(QMouseEvent *)
Definition: qwt_picker.cpp:1064
QwtPicker::widgetKeyPressEvent
virtual void widgetKeyPressEvent(QKeyEvent *)
Definition: qwt_picker.cpp:1112
QwtPicker::setTrackerPen
void setTrackerPen(const QPen &)
Definition: qwt_picker.cpp:435
QwtPicker::setResizeMode
void setResizeMode(ResizeMode)
Set the resize mode.
Definition: qwt_picker.cpp:351
QwtPicker::widgetWheelEvent
virtual void widgetWheelEvent(QWheelEvent *)
Definition: qwt_picker.cpp:1081
QwtPicker::QwtPicker
QwtPicker(QWidget *parent)
Definition: qwt_picker.cpp:168
QwtPicker::selection
QPolygon selection() const
Definition: qwt_picker.cpp:792
QwtPickerMachine
A state machine for QwtPicker selections.
Definition: qwt_picker_machine.h:29
QwtPickerMachine::SelectionType
SelectionType
Definition: qwt_picker_machine.h:36
QwtPickerMachine::NoSelection
@ NoSelection
The state machine not usable for any type of selection.
Definition: qwt_picker_machine.h:38
QwtPickerMachine::RectSelection
@ RectSelection
The state machine is for selecting a rectangle (2 points).
Definition: qwt_picker_machine.h:44
QwtPickerMachine::PolygonSelection
@ PolygonSelection
The state machine is for selecting a polygon (many points).
Definition: qwt_picker_machine.h:47
QwtPickerMachine::PointSelection
@ PointSelection
The state machine is for selecting a single point.
Definition: qwt_picker_machine.h:41
QwtText
A class representing a text.
Definition: qwt_text.h:52
QwtText::textSize
QSizeF textSize() const
Definition: qwt_text.cpp:570
QwtText::isEmpty
bool isEmpty() const
Definition: qwt_text.cpp:739
QwtText::draw
void draw(QPainter *painter, const QRectF &rect) const
Definition: qwt_text.cpp:615
QwtWidgetOverlay
An overlay for a widget.
Definition: qwt_widget_overlay.h:41
QwtWidgetOverlay::AlphaMask
@ AlphaMask
Calculate a mask by checking the alpha values.
Definition: qwt_widget_overlay.h:84
QwtWidgetOverlay::MaskHint
@ MaskHint
Use maskHint() as mask.
Definition: qwt_widget_overlay.h:72
QwtWidgetOverlay::setMaskMode
void setMaskMode(MaskMode)
Specify how to find the mask for the overlay.
Definition: qwt_widget_overlay.cpp:154
QwtWidgetOverlay::drawOverlay
virtual void drawOverlay(QPainter *painter) const =0
QwtWidgetOverlay::maskHint
virtual QRegion maskHint() const
Calculate an approximation for the mask.
Definition: qwt_widget_overlay.cpp:373