qwt_picker.cpp
Go to the documentation of this file.
1 /* -*- mode: C++ ; c-file-style: "stroustrup" -*- *****************************
2  * Qwt Widget Library
3  * Copyright (C) 1997 Josef Wilgen
4  * Copyright (C) 2002 Uwe Rathmann
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the Qwt License, Version 1.0
8  *****************************************************************************/
9 
10 #include "qwt_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 QwtPickerRubberband QWT_FINAL : public QwtWidgetOverlay
68  {
69  public:
70  QwtPickerRubberband( QwtPicker *, QWidget * );
71 
72  protected:
73  virtual void drawOverlay( QPainter * ) const QWT_OVERRIDE;
74  virtual QRegion maskHint() const QWT_OVERRIDE;
75 
76  QwtPicker *d_picker;
77  };
78 
79  class QwtPickerTracker QWT_FINAL : public QwtWidgetOverlay
80  {
81  public:
82  QwtPickerTracker( QwtPicker *, QWidget * );
83 
84  protected:
85  virtual void drawOverlay( QPainter * ) const QWT_OVERRIDE;
86  virtual QRegion maskHint() const QWT_OVERRIDE;
87 
88  QwtPicker *d_picker;
89  };
90 }
91 
93 {
94 public:
96  enabled( false ),
97  stateMachine( NULL ),
98  resizeMode( QwtPicker::Stretch ),
99  rubberBand( QwtPicker::NoRubberBand ),
100  trackerMode( QwtPicker::AlwaysOff ),
101  isActive( false ),
102  trackerPosition( -1, -1 ),
103  mouseTracking( false ),
104  openGL( false )
105  {
106  }
107 
108  bool enabled;
109 
111 
113 
116 
119  QFont trackerFont;
120 
121  QPolygon pickedPoints;
122  bool isActive;
124 
125  bool mouseTracking; // used to save previous value
126 
127  QPointer< QwtPickerRubberband > rubberBandOverlay;
128  QPointer< QwtPickerTracker> trackerOverlay;
129 
130  bool openGL;
131 };
132 
133 QwtPickerRubberband::QwtPickerRubberband(
134  QwtPicker *picker, QWidget *parent ):
135  QwtWidgetOverlay( parent ),
136  d_picker( picker )
137 {
138  setMaskMode( QwtWidgetOverlay::MaskHint );
139 }
140 
141 QRegion QwtPickerRubberband::maskHint() const
142 {
143  return d_picker->rubberBandMask();
144 }
145 
146 void QwtPickerRubberband::drawOverlay( QPainter *painter ) const
147 {
148  painter->setPen( d_picker->rubberBandPen() );
149  d_picker->drawRubberBand( painter );
150 }
151 
152 QwtPickerTracker::QwtPickerTracker(
153  QwtPicker *picker, QWidget *parent ):
154  QwtWidgetOverlay( parent ),
155  d_picker( picker )
156 {
157  setMaskMode( QwtWidgetOverlay::MaskHint );
158 }
159 
160 QRegion QwtPickerTracker::maskHint() const
161 {
162  return d_picker->trackerMask();
163 }
164 
165 void QwtPickerTracker::drawOverlay( QPainter *painter ) const
166 {
167  painter->setPen( d_picker->trackerPen() );
168  d_picker->drawTracker( painter );
169 }
170 
180 QwtPicker::QwtPicker( QWidget *parent ):
181  QObject( parent )
182 {
183  init( parent, NoRubberBand, AlwaysOff );
184 }
185 
194  DisplayMode trackerMode, QWidget *parent ):
195  QObject( parent )
196 {
197  init( parent, rubberBand, trackerMode );
198 }
199 
202 {
203  setMouseTracking( false );
204 
205  delete d_data->stateMachine;
206  delete d_data->rubberBandOverlay;
207  delete d_data->trackerOverlay;
208 
209  delete d_data;
210 }
211 
213 void QwtPicker::init( QWidget *parent,
215 {
216  d_data = new PrivateData;
217 
219 
220  if ( parent )
221  {
222  if ( parent->focusPolicy() == Qt::NoFocus )
223  parent->setFocusPolicy( Qt::WheelFocus );
224 
225  d_data->openGL = parent->inherits( "QGLWidget" );
226  d_data->trackerFont = parent->font();
227  d_data->mouseTracking = parent->hasMouseTracking();
228 
229  setEnabled( true );
230  }
231 
232  setTrackerMode( trackerMode );
233 }
234 
242 {
243  if ( d_data->stateMachine != stateMachine )
244  {
245  reset();
246 
247  delete d_data->stateMachine;
249 
250  if ( d_data->stateMachine )
252  }
253 }
254 
260 {
261  return d_data->stateMachine;
262 }
263 
269 {
270  return d_data->stateMachine;
271 }
272 
275 {
276  QObject *obj = parent();
277  if ( obj && obj->isWidgetType() )
278  return static_cast<QWidget *>( obj );
279 
280  return NULL;
281 }
282 
284 const QWidget *QwtPicker::parentWidget() const
285 {
286  QObject *obj = parent();
287  if ( obj && obj->isWidgetType() )
288  return static_cast< const QWidget *>( obj );
289 
290  return NULL;
291 }
292 
302 {
304 }
305 
311 {
312  return d_data->rubberBand;
313 }
314 
332 {
333  if ( d_data->trackerMode != mode )
334  {
335  d_data->trackerMode = mode;
337  }
338 }
339 
345 {
346  return d_data->trackerMode;
347 }
348 
364 {
365  d_data->resizeMode = mode;
366 }
367 
374 {
375  return d_data->resizeMode;
376 }
377 
387 void QwtPicker::setEnabled( bool enabled )
388 {
389  if ( d_data->enabled != enabled )
390  {
391  d_data->enabled = enabled;
392 
393  QWidget *w = parentWidget();
394  if ( w )
395  {
396  if ( enabled )
397  w->installEventFilter( this );
398  else
399  w->removeEventFilter( this );
400  }
401 
402  updateDisplay();
403  }
404 }
405 
411 bool QwtPicker::isEnabled() const
412 {
413  return d_data->enabled;
414 }
415 
422 void QwtPicker::setTrackerFont( const QFont &font )
423 {
424  if ( font != d_data->trackerFont )
425  {
426  d_data->trackerFont = font;
427  updateDisplay();
428  }
429 }
430 
436 QFont QwtPicker::trackerFont() const
437 {
438  return d_data->trackerFont;
439 }
440 
447 void QwtPicker::setTrackerPen( const QPen &pen )
448 {
449  if ( pen != d_data->trackerPen )
450  {
451  d_data->trackerPen = pen;
452  updateDisplay();
453  }
454 }
455 
460 QPen QwtPicker::trackerPen() const
461 {
462  return d_data->trackerPen;
463 }
464 
471 void QwtPicker::setRubberBandPen( const QPen &pen )
472 {
473  if ( pen != d_data->rubberBandPen )
474  {
475  d_data->rubberBandPen = pen;
476  updateDisplay();
477  }
478 }
479 
484 QPen QwtPicker::rubberBandPen() const
485 {
486  return d_data->rubberBandPen;
487 }
488 
502 QwtText QwtPicker::trackerText( const QPoint &pos ) const
503 {
504  QString label;
505 
506  switch ( rubberBand() )
507  {
508  case HLineRubberBand:
509  label = QString::number( pos.y() );
510  break;
511  case VLineRubberBand:
512  label = QString::number( pos.x() );
513  break;
514  default:
515  label = QString::number( pos.x() ) + ", " + QString::number( pos.y() );
516  }
517  return label;
518 }
519 
526 QRegion QwtPicker::trackerMask() const
527 {
528  return trackerRect( d_data->trackerFont );
529 }
530 
538 {
539  QRegion mask;
540 
541  if ( !isActive() || rubberBand() == NoRubberBand ||
542  rubberBandPen().style() == Qt::NoPen )
543  {
544  return mask;
545  }
546 
547  const QPolygon pa = adjustedPoints( d_data->pickedPoints );
548 
549  QwtPickerMachine::SelectionType selectionType =
551 
552  if ( d_data->stateMachine )
553  selectionType = d_data->stateMachine->selectionType();
554 
555  switch ( selectionType )
556  {
559  {
560  if ( pa.count() < 1 )
561  return mask;
562 
563  const QPoint pos = pa[0];
564  const int pw = rubberBandPen().width();
565 
566  const QRect pRect = pickArea().boundingRect().toRect();
567  switch ( rubberBand() )
568  {
569  case VLineRubberBand:
570  {
571  mask += qwtMaskRegion( QLine( pos.x(), pRect.top(),
572  pos.x(), pRect.bottom() ), pw );
573  break;
574  }
575  case HLineRubberBand:
576  {
577  mask += qwtMaskRegion( QLine( pRect.left(), pos.y(),
578  pRect.right(), pos.y() ), pw );
579  break;
580  }
581  case CrossRubberBand:
582  {
583  mask += qwtMaskRegion( QLine( pos.x(), pRect.top(),
584  pos.x(), pRect.bottom() ), pw );
585  mask += qwtMaskRegion( QLine( pRect.left(), pos.y(),
586  pRect.right(), pos.y() ), pw );
587  break;
588  }
589  default:
590  break;
591  }
592  break;
593  }
595  {
596  if ( pa.count() < 2 )
597  return mask;
598 
599  const int pw = rubberBandPen().width();
600 
601  switch ( rubberBand() )
602  {
603  case RectRubberBand:
604  {
605  const QRect r = QRect( pa.first(), pa.last() );
606  mask = qwtMaskRegion( r.normalized(), pw );
607  break;
608  }
609  case EllipseRubberBand:
610  {
611  const QRect r = QRect( pa.first(), pa.last() );
612  mask += r.adjusted( -pw, -pw, pw, pw );
613  break;
614  }
615  default:
616  break;
617  }
618  break;
619  }
621  {
622  const int pw = rubberBandPen().width();
623  if ( pw <= 1 )
624  {
625  // because of the join style we better
626  // return a mask for a pen width <= 1 only
627 
628  const int off = 2 * pw;
629  const QRect r = pa.boundingRect();
630  mask += r.adjusted( -off, -off, off, off );
631  }
632  break;
633  }
634  default:
635  break;
636  }
637 
638  return mask;
639 }
640 
649 void QwtPicker::drawRubberBand( QPainter *painter ) const
650 {
651  if ( !isActive() || rubberBand() == NoRubberBand ||
652  rubberBandPen().style() == Qt::NoPen )
653  {
654  return;
655  }
656 
657  const QPolygon pa = adjustedPoints( d_data->pickedPoints );
658 
659  QwtPickerMachine::SelectionType selectionType =
661 
662  if ( d_data->stateMachine )
663  selectionType = d_data->stateMachine->selectionType();
664 
665  switch ( selectionType )
666  {
669  {
670  if ( pa.count() < 1 )
671  return;
672 
673  const QPoint pos = pa[0];
674 
675  const QRect pRect = pickArea().boundingRect().toRect();
676  switch ( rubberBand() )
677  {
678  case VLineRubberBand:
679  {
680  QwtPainter::drawLine( painter, pos.x(),
681  pRect.top(), pos.x(), pRect.bottom() );
682  break;
683  }
684  case HLineRubberBand:
685  {
686  QwtPainter::drawLine( painter, pRect.left(),
687  pos.y(), pRect.right(), pos.y() );
688  break;
689  }
690  case CrossRubberBand:
691  {
692  QwtPainter::drawLine( painter, pos.x(),
693  pRect.top(), pos.x(), pRect.bottom() );
694  QwtPainter::drawLine( painter, pRect.left(),
695  pos.y(), pRect.right(), pos.y() );
696  break;
697  }
698  default:
699  break;
700  }
701  break;
702  }
704  {
705  if ( pa.count() < 2 )
706  return;
707 
708  const QRect rect = QRect( pa.first(), pa.last() ).normalized();
709  switch ( rubberBand() )
710  {
711  case EllipseRubberBand:
712  {
713  QwtPainter::drawEllipse( painter, rect );
714  break;
715  }
716  case RectRubberBand:
717  {
718  QwtPainter::drawRect( painter, rect );
719  break;
720  }
721  default:
722  break;
723  }
724  break;
725  }
727  {
728  if ( rubberBand() == PolygonRubberBand )
729  painter->drawPolyline( pa );
730  break;
731  }
732  default:
733  break;
734  }
735 }
736 
744 void QwtPicker::drawTracker( QPainter *painter ) const
745 {
746  const QRect textRect = trackerRect( painter->font() );
747  if ( !textRect.isEmpty() )
748  {
749  const QwtText label = trackerText( d_data->trackerPosition );
750  if ( !label.isEmpty() )
751  label.draw( painter, textRect );
752  }
753 }
754 
796 QPolygon QwtPicker::adjustedPoints( const QPolygon &points ) const
797 {
798  return points;
799 }
800 
805 QPolygon QwtPicker::selection() const
806 {
808 }
809 
812 {
813  return d_data->trackerPosition;
814 }
815 
825 QRect QwtPicker::trackerRect( const QFont &font ) const
826 {
827  if ( trackerMode() == AlwaysOff ||
828  ( trackerMode() == ActiveOnly && !isActive() ) )
829  {
830  return QRect();
831  }
832 
833  if ( d_data->trackerPosition.x() < 0 || d_data->trackerPosition.y() < 0 )
834  return QRect();
835 
837  if ( text.isEmpty() )
838  return QRect();
839 
840  const QSizeF textSize = text.textSize( font );
841  QRect textRect( 0, 0, qwtCeil( textSize.width() ), qwtCeil( textSize.height() ) );
842 
843  const QPoint &pos = d_data->trackerPosition;
844 
845  int alignment = 0;
846  if ( isActive() && d_data->pickedPoints.count() > 1
847  && rubberBand() != NoRubberBand )
848  {
849  const QPoint last =
850  d_data->pickedPoints[ d_data->pickedPoints.count() - 2 ];
851 
852  alignment |= ( pos.x() >= last.x() ) ? Qt::AlignRight : Qt::AlignLeft;
853  alignment |= ( pos.y() > last.y() ) ? Qt::AlignBottom : Qt::AlignTop;
854  }
855  else
856  alignment = Qt::AlignTop | Qt::AlignRight;
857 
858  const int margin = 5;
859 
860  int x = pos.x();
861  if ( alignment & Qt::AlignLeft )
862  x -= textRect.width() + margin;
863  else if ( alignment & Qt::AlignRight )
864  x += margin;
865 
866  int y = pos.y();
867  if ( alignment & Qt::AlignBottom )
868  y += margin;
869  else if ( alignment & Qt::AlignTop )
870  y -= textRect.height() + margin;
871 
872  textRect.moveTopLeft( QPoint( x, y ) );
873 
874  const QRect pickRect = pickArea().boundingRect().toRect();
875 
876  int right = qMin( textRect.right(), pickRect.right() - margin );
877  int bottom = qMin( textRect.bottom(), pickRect.bottom() - margin );
878  textRect.moveBottomRight( QPoint( right, bottom ) );
879 
880  int left = qMax( textRect.left(), pickRect.left() + margin );
881  int top = qMax( textRect.top(), pickRect.top() + margin );
882  textRect.moveTopLeft( QPoint( left, top ) );
883 
884  return textRect;
885 }
886 
906 bool QwtPicker::eventFilter( QObject *object, QEvent *event )
907 {
908  if ( object && object == parentWidget() )
909  {
910  switch ( event->type() )
911  {
912  case QEvent::Resize:
913  {
914  const QResizeEvent *re = static_cast<QResizeEvent *>( event );
915 
916  /*
917  Adding/deleting additional event filters inside of an event filter
918  is not safe dues to the implementation in Qt ( changing alist while iterating ).
919  So we create the overlays in a way, that they don't install en event filter
920  ( parent set to NULL ) and do the resizing here.
921  */
922  if ( d_data->trackerOverlay )
923  d_data->trackerOverlay->resize( re->size() );
924 
925  if ( d_data->rubberBandOverlay )
926  d_data->rubberBandOverlay->resize( re->size() );
927 
928  if ( d_data->resizeMode == Stretch )
929  stretchSelection( re->oldSize(), re->size() );
930 
931  updateDisplay();
932  break;
933  }
934  case QEvent::Enter:
935  {
936  widgetEnterEvent( event );
937  break;
938  }
939  case QEvent::Leave:
940  {
941  widgetLeaveEvent( event );
942  break;
943  }
944  case QEvent::MouseButtonPress:
945  {
946  widgetMousePressEvent( static_cast<QMouseEvent *>( event ) );
947  break;
948  }
949  case QEvent::MouseButtonRelease:
950  {
951  widgetMouseReleaseEvent( static_cast<QMouseEvent *>( event ) );
952  break;
953  }
954  case QEvent::MouseButtonDblClick:
955  {
956  widgetMouseDoubleClickEvent( static_cast<QMouseEvent *>( event ) );
957  break;
958  }
959  case QEvent::MouseMove:
960  {
961  widgetMouseMoveEvent( static_cast<QMouseEvent *>( event ) );
962  break;
963  }
964  case QEvent::KeyPress:
965  {
966  widgetKeyPressEvent( static_cast<QKeyEvent *>( event ) );
967  break;
968  }
969  case QEvent::KeyRelease:
970  {
971  widgetKeyReleaseEvent( static_cast<QKeyEvent *>( event ) );
972  break;
973  }
974  case QEvent::Wheel:
975  {
976  widgetWheelEvent( static_cast<QWheelEvent *>( event ) );
977  break;
978  }
979  default:
980  break;
981  }
982  }
983  return false;
984 }
985 
995 void QwtPicker::widgetMousePressEvent( QMouseEvent *mouseEvent )
996 {
997  transition( mouseEvent );
998 }
999 
1009 void QwtPicker::widgetMouseMoveEvent( QMouseEvent *mouseEvent )
1010 {
1011  if ( pickArea().contains( mouseEvent->pos() ) )
1012  d_data->trackerPosition = mouseEvent->pos();
1013  else
1014  d_data->trackerPosition = QPoint( -1, -1 );
1015 
1016  if ( !isActive() )
1017  updateDisplay();
1018 
1019  transition( mouseEvent );
1020 }
1021 
1031 void QwtPicker::widgetEnterEvent( QEvent *event )
1032 {
1033  transition( event );
1034 }
1035 
1045 void QwtPicker::widgetLeaveEvent( QEvent *event )
1046 {
1047  transition( event );
1048 
1049  d_data->trackerPosition = QPoint( -1, -1 );
1050  if ( !isActive() )
1051  updateDisplay();
1052 }
1053 
1063 void QwtPicker::widgetMouseReleaseEvent( QMouseEvent *mouseEvent )
1064 {
1065  transition( mouseEvent );
1066 }
1067 
1077 void QwtPicker::widgetMouseDoubleClickEvent( QMouseEvent *mouseEvent )
1078 {
1079  transition( mouseEvent );
1080 }
1081 
1082 
1094 void QwtPicker::widgetWheelEvent( QWheelEvent *wheelEvent )
1095 {
1096 #if QT_VERSION < 0x050e00
1097  const QPoint wheelPos = wheelEvent->pos();
1098 #else
1099  const QPoint wheelPos = wheelEvent->position().toPoint();
1100 #endif
1101  if ( pickArea().contains( wheelPos ) )
1102  d_data->trackerPosition = wheelPos;
1103  else
1104  d_data->trackerPosition = QPoint( -1, -1 );
1105 
1106  updateDisplay();
1107 
1108  transition( wheelEvent );
1109 }
1110 
1125 void QwtPicker::widgetKeyPressEvent( QKeyEvent *keyEvent )
1126 {
1127  int dx = 0;
1128  int dy = 0;
1129 
1130  int offset = 1;
1131  if ( keyEvent->isAutoRepeat() )
1132  offset = 5;
1133 
1134  if ( keyMatch( KeyLeft, keyEvent ) )
1135  dx = -offset;
1136  else if ( keyMatch( KeyRight, keyEvent ) )
1137  dx = offset;
1138  else if ( keyMatch( KeyUp, keyEvent ) )
1139  dy = -offset;
1140  else if ( keyMatch( KeyDown, keyEvent ) )
1141  dy = offset;
1142  else if ( keyMatch( KeyAbort, keyEvent ) )
1143  {
1144  reset();
1145  }
1146  else
1147  transition( keyEvent );
1148 
1149  if ( dx != 0 || dy != 0 )
1150  {
1151  const QRect rect = pickArea().boundingRect().toRect();
1152  const QPoint pos = parentWidget()->mapFromGlobal( QCursor::pos() );
1153 
1154  int x = pos.x() + dx;
1155  x = qMax( rect.left(), x );
1156  x = qMin( rect.right(), x );
1157 
1158  int y = pos.y() + dy;
1159  y = qMax( rect.top(), y );
1160  y = qMin( rect.bottom(), y );
1161 
1162  QCursor::setPos( parentWidget()->mapToGlobal( QPoint( x, y ) ) );
1163  }
1164 }
1165 
1177 void QwtPicker::widgetKeyReleaseEvent( QKeyEvent *keyEvent )
1178 {
1179  transition( keyEvent );
1180 }
1181 
1189 void QwtPicker::transition( const QEvent *event )
1190 {
1191  if ( !d_data->stateMachine )
1192  return;
1193 
1194  const QList<QwtPickerMachine::Command> commandList =
1195  d_data->stateMachine->transition( *this, event );
1196 
1197  QPoint pos;
1198  switch ( event->type() )
1199  {
1200  case QEvent::MouseButtonDblClick:
1201  case QEvent::MouseButtonPress:
1202  case QEvent::MouseButtonRelease:
1203  case QEvent::MouseMove:
1204  {
1205  const QMouseEvent *me =
1206  static_cast< const QMouseEvent * >( event );
1207  pos = me->pos();
1208  break;
1209  }
1210  default:
1211  pos = parentWidget()->mapFromGlobal( QCursor::pos() );
1212  }
1213 
1214  for ( int i = 0; i < commandList.count(); i++ )
1215  {
1216  switch ( commandList[i] )
1217  {
1219  {
1220  begin();
1221  break;
1222  }
1224  {
1225  append( pos );
1226  break;
1227  }
1229  {
1230  move( pos );
1231  break;
1232  }
1234  {
1235  remove();
1236  break;
1237  }
1238  case QwtPickerMachine::End:
1239  {
1240  end();
1241  break;
1242  }
1243  }
1244  }
1245 }
1246 
1253 {
1254  if ( d_data->isActive )
1255  return;
1256 
1257  d_data->pickedPoints.clear();
1258  d_data->isActive = true;
1259  Q_EMIT activated( true );
1260 
1261  if ( trackerMode() != AlwaysOff )
1262  {
1263  if ( d_data->trackerPosition.x() < 0 || d_data->trackerPosition.y() < 0 )
1264  {
1265  QWidget *w = parentWidget();
1266  if ( w )
1267  d_data->trackerPosition = w->mapFromGlobal( QCursor::pos() );
1268  }
1269  }
1270 
1271  updateDisplay();
1272  setMouseTracking( true );
1273 }
1274 
1285 bool QwtPicker::end( bool ok )
1286 {
1287  if ( d_data->isActive )
1288  {
1289  setMouseTracking( false );
1290 
1291  d_data->isActive = false;
1292  Q_EMIT activated( false );
1293 
1294  if ( trackerMode() == ActiveOnly )
1295  d_data->trackerPosition = QPoint( -1, -1 );
1296 
1297  if ( ok )
1298  ok = accept( d_data->pickedPoints );
1299 
1300  if ( ok )
1301  Q_EMIT selected( d_data->pickedPoints );
1302  else
1303  d_data->pickedPoints.clear();
1304 
1305  updateDisplay();
1306  }
1307  else
1308  ok = false;
1309 
1310  return ok;
1311 }
1312 
1317 {
1318  if ( d_data->stateMachine )
1320 
1321  if ( isActive() )
1322  end( false );
1323 }
1324 
1333 void QwtPicker::append( const QPoint &pos )
1334 {
1335  if ( d_data->isActive )
1336  {
1337  d_data->pickedPoints += pos;
1338 
1339  updateDisplay();
1340  Q_EMIT appended( pos );
1341  }
1342 }
1343 
1351 void QwtPicker::move( const QPoint &pos )
1352 {
1353  if ( d_data->isActive && !d_data->pickedPoints.isEmpty() )
1354  {
1355  QPoint &point = d_data->pickedPoints.last();
1356  if ( point != pos )
1357  {
1358  point = pos;
1359 
1360  updateDisplay();
1361  Q_EMIT moved( pos );
1362  }
1363  }
1364 }
1365 
1373 {
1374  if ( d_data->isActive && !d_data->pickedPoints.isEmpty() )
1375  {
1376 #if QT_VERSION >= 0x050100
1377  const QPoint pos = d_data->pickedPoints.takeLast();
1378 #else
1379  const QPoint pos = d_data->pickedPoints.last();
1380  d_data->pickedPoints.resize( d_data->pickedPoints.count() - 1 );
1381 #endif
1382 
1383  updateDisplay();
1384  Q_EMIT removed( pos );
1385  }
1386 }
1387 
1396 bool QwtPicker::accept( QPolygon &selection ) const
1397 {
1398  Q_UNUSED( selection );
1399  return true;
1400 }
1401 
1407 {
1408  return d_data->isActive;
1409 }
1410 
1416 const QPolygon &QwtPicker::pickedPoints() const
1417 {
1418  return d_data->pickedPoints;
1419 }
1420 
1430 void QwtPicker::stretchSelection( const QSize &oldSize, const QSize &newSize )
1431 {
1432  if ( oldSize.isEmpty() )
1433  {
1434  // avoid division by zero. But scaling for small sizes also
1435  // doesn't make much sense, because of rounding losses. TODO ...
1436  return;
1437  }
1438 
1439  const double xRatio = double( newSize.width() ) / double( oldSize.width() );
1440  const double yRatio = double( newSize.height() ) / double( oldSize.height() );
1441 
1442  for ( int i = 0; i < d_data->pickedPoints.count(); i++ )
1443  {
1444  QPoint &p = d_data->pickedPoints[i];
1445  p.setX( qRound( p.x() * xRatio ) );
1446  p.setY( qRound( p.y() * yRatio ) );
1447 
1448  Q_EMIT changed( d_data->pickedPoints );
1449  }
1450 }
1451 
1466 {
1467  QWidget *widget = parentWidget();
1468  if ( !widget )
1469  return;
1470 
1471  if ( enable )
1472  {
1473  d_data->mouseTracking = widget->hasMouseTracking();
1474  widget->setMouseTracking( true );
1475  }
1476  else
1477  {
1478  widget->setMouseTracking( d_data->mouseTracking );
1479  }
1480 }
1481 
1487 QPainterPath QwtPicker::pickArea() const
1488 {
1489  QPainterPath path;
1490 
1491  const QWidget *widget = parentWidget();
1492  if ( widget )
1493  path.addRect( widget->contentsRect() );
1494 
1495  return path;
1496 }
1497 
1500 {
1501  QWidget *w = parentWidget();
1502 
1503  bool showRubberband = false;
1504  bool showTracker = false;
1505 
1506  if ( w && w->isVisible() && d_data->enabled )
1507  {
1508  if ( rubberBand() != NoRubberBand && isActive() &&
1509  rubberBandPen().style() != Qt::NoPen )
1510  {
1511  showRubberband = true;
1512  }
1513 
1514  if ( trackerMode() == AlwaysOn ||
1515  ( trackerMode() == ActiveOnly && isActive() ) )
1516  {
1517  if ( trackerPen() != Qt::NoPen
1518  && !trackerRect( QFont() ).isEmpty() )
1519  {
1520  showTracker = true;
1521  }
1522  }
1523  }
1524 
1525  QPointer< QwtPickerRubberband > &rw = d_data->rubberBandOverlay;
1526  if ( showRubberband )
1527  {
1528  if ( rw.isNull() )
1529  {
1530  rw = new QwtPickerRubberband( this, NULL ); // NULL -> no extra event filter
1531  rw->setObjectName( "PickerRubberBand" );
1532  rw->setParent( w );
1533  rw->resize( w->size() );
1534  }
1535 
1536  if ( d_data->rubberBand <= RectRubberBand )
1537  rw->setMaskMode( QwtWidgetOverlay::MaskHint );
1538  else
1539  rw->setMaskMode( QwtWidgetOverlay::AlphaMask );
1540 
1541  rw->updateOverlay();
1542  }
1543  else
1544  {
1545  if ( d_data->openGL )
1546  {
1547  // Qt 4.8 crashes for a delete
1548  if ( !rw.isNull() )
1549  {
1550  rw->hide();
1551  rw->deleteLater();
1552  rw = NULL;
1553  }
1554  }
1555  else
1556  {
1557  delete rw;
1558  }
1559  }
1560 
1561  QPointer< QwtPickerTracker > &tw = d_data->trackerOverlay;
1562  if ( showTracker )
1563  {
1564  if ( tw.isNull() )
1565  {
1566  tw = new QwtPickerTracker( this, NULL ); // NULL -> no extra event filter
1567  tw->setObjectName( "PickerTracker" );
1568  tw->setParent( w );
1569  tw->resize( w->size() );
1570  }
1571  tw->setFont( d_data->trackerFont );
1572  tw->updateOverlay();
1573  }
1574  else
1575  {
1576  if ( d_data->openGL )
1577  {
1578  // Qt 4.8 crashes for a delete
1579  if ( !tw.isNull() )
1580  {
1581  tw->hide();
1582  tw->deleteLater();
1583  tw = NULL;
1584  }
1585  }
1586  else
1587  {
1588  delete tw;
1589  }
1590  }
1591 }
1592 
1595 {
1596  return d_data->rubberBandOverlay;
1597 }
1598 
1601 {
1602  return d_data->trackerOverlay;
1603 }
1604 
1605 #if QWT_MOC_INCLUDE
1606 #include "moc_qwt_picker.cpp"
1607 #endif
virtual QRegion trackerMask() const
Definition: qwt_picker.cpp:526
virtual bool end(bool ok=true)
Close a selection setting the state to inactive.
virtual void widgetKeyPressEvent(QKeyEvent *)
virtual void remove()
DisplayMode
Display mode.
Definition: qwt_picker.h:162
virtual void stretchSelection(const QSize &oldSize, const QSize &newSize)
void setRubberBand(RubberBand)
Definition: qwt_picker.cpp:301
DisplayMode trackerMode() const
const QwtWidgetOverlay * rubberBandOverlay() const
void setTrackerFont(const QFont &)
Definition: qwt_picker.cpp:422
virtual void widgetEnterEvent(QEvent *)
virtual void widgetKeyReleaseEvent(QKeyEvent *)
A crosshair ( only for QwtPickerMachine::PointSelection )
Definition: qwt_picker.h:140
QSizeF textSize() const
Definition: qwt_text.cpp:547
lu_byte right
Definition: lparser.c:1229
static QRegion qwtMaskRegion(const QRect &r, int penWidth)
Definition: qwt_picker.cpp:23
static void drawLine(QPainter *, qreal x1, qreal y1, qreal x2, qreal y2)
Wrapper for QPainter::drawLine()
Definition: qwt_painter.h:152
The state machine not usable for any type of selection.
Display always.
Definition: qwt_picker.h:168
virtual QRegion rubberBandMask() const
Definition: qwt_picker.cpp:537
lu_byte left
Definition: lparser.c:1228
QWidget * parentWidget()
Return the parent widget, where the selection happens.
Definition: qwt_picker.cpp:274
void setTrackerMode(DisplayMode)
Set the display mode of the tracker.
Definition: qwt_picker.cpp:331
QPointer< QwtPickerRubberband > rubberBandOverlay
Definition: qwt_picker.cpp:127
void reset()
Set the current state to 0.
QPoint trackerPosition() const
Definition: qwt_picker.cpp:811
QPointer< QwtPickerTracker > trackerOverlay
Definition: qwt_picker.cpp:128
virtual void reset()
void draw(QPainter *painter, const QRectF &rect) const
Definition: qwt_text.cpp:592
virtual bool eventFilter(QObject *, QEvent *) QWT_OVERRIDE
Event filter.
Definition: qwt_picker.cpp:906
QPen rubberBandPen() const
const QPolygon & pickedPoints() const
virtual void drawOverlay(QPainter *painter) const =0
QFont trackerFont() const
QPolygon selection() const
Definition: qwt_picker.cpp:805
virtual bool accept(QPolygon &) const
Validate and fix up the selection.
void selected(const QPolygon &polygon)
virtual void widgetLeaveEvent(QEvent *)
QPen trackerPen() const
bool isActive() const
void changed(const QPolygon &selection)
All points are scaled according to the new size,.
Definition: qwt_picker.h:185
void moved(const QPoint &pos)
The state machine is for selecting a polygon (many points).
PrivateData * d_data
Definition: qwt_picker.h:335
No rubberband.
Definition: qwt_picker.h:131
void setMouseTracking(bool)
virtual QPainterPath pickArea() const
const QwtPickerMachine * stateMachine() const
Definition: qwt_picker.cpp:268
virtual void drawRubberBand(QPainter *) const
Definition: qwt_picker.cpp:649
QwtPicker::ResizeMode resizeMode
Definition: qwt_picker.cpp:112
The state machine is for selecting a single point.
A polygon ( only for QwtPickerMachine::PolygonSelection )
Definition: qwt_picker.h:149
virtual QRegion maskHint() const
Calculate an approximation for the mask.
void setStateMachine(QwtPickerMachine *)
Definition: qwt_picker.cpp:241
virtual QRect trackerRect(const QFont &) const
Definition: qwt_picker.cpp:825
virtual void widgetMouseMoveEvent(QMouseEvent *)
bool isEmpty() const
Definition: qwt_text.cpp:716
virtual void transition(const QEvent *)
An ellipse ( only for QwtPickerMachine::RectSelection )
Definition: qwt_picker.h:146
virtual void widgetMouseDoubleClickEvent(QMouseEvent *)
RubberBand rubberBand() const
QwtPicker::DisplayMode trackerMode
Definition: qwt_picker.cpp:117
A class representing a text.
Definition: qwt_text.h:51
A state machine for QwtPicker selections.
virtual void move(const QPoint &)
A horizontal line ( only for QwtPickerMachine::PointSelection )
Definition: qwt_picker.h:134
virtual void widgetWheelEvent(QWheelEvent *)
QwtPicker::RubberBand rubberBand
Definition: qwt_picker.cpp:114
virtual void updateDisplay()
Update the state of rubber band and tracker label.
static void drawEllipse(QPainter *, const QRectF &)
Wrapper for QPainter::drawEllipse()
void setEnabled(bool)
En/disable the picker.
Definition: qwt_picker.cpp:387
Use maskHint() as mask.
void appended(const QPoint &pos)
virtual QList< Command > transition(const QwtEventPattern &, const QEvent *)=0
Transition.
int top(lua_State *L)
Definition: sol.hpp:10543
static void drawRect(QPainter *, qreal x, qreal y, qreal w, qreal h)
Wrapper for QPainter::drawRect()
virtual void drawTracker(QPainter *) const
Definition: qwt_picker.cpp:744
const QwtWidgetOverlay * trackerOverlay() const
Calculate a mask by checking the alpha values.
A rectangle ( only for QwtPickerMachine::RectSelection )
Definition: qwt_picker.h:143
An overlay for a widget.
virtual QPolygon adjustedPoints(const QPolygon &) const
Map the pickedPoints() into a selection()
Definition: qwt_picker.cpp:796
std::enable_if_t< all< Args... >::value, enable_t > enable
Definition: sol.hpp:1726
bool isEnabled() const
virtual void widgetMouseReleaseEvent(QMouseEvent *)
bool keyMatch(KeyPatternCode, const QKeyEvent *) const
Compare a key event with an event pattern.
void setResizeMode(ResizeMode)
Set the resize mode.
Definition: qwt_picker.cpp:363
SelectionType selectionType() const
Return the selection type.
A vertical line ( only for QwtPickerMachine::PointSelection )
Definition: qwt_picker.h:137
void removed(const QPoint &pos)
Display never.
Definition: qwt_picker.h:165
QwtPicker(QWidget *parent)
Definition: qwt_picker.cpp:180
virtual ~QwtPicker()
Destructor.
Definition: qwt_picker.cpp:201
qreal penWidth(const QPainter *painter, const QwtScaleDraw *scaleDraw)
virtual QwtText trackerText(const QPoint &pos) const
Return the label for a position.
Definition: qwt_picker.cpp:502
void setRubberBandPen(const QPen &)
Definition: qwt_picker.cpp:471
virtual void begin()
int qwtCeil(qreal value)
Definition: qwt_math.h:262
ResizeMode resizeMode() const
virtual void widgetMousePressEvent(QMouseEvent *)
Definition: qwt_picker.cpp:995
void init(QWidget *, RubberBand rubberBand, DisplayMode trackerMode)
Initialize the picker - used by the constructors.
Definition: qwt_picker.cpp:213
void setTrackerPen(const QPen &)
Definition: qwt_picker.cpp:447
QwtPicker provides selections on a widget.
Definition: qwt_picker.h:104
The state machine is for selecting a rectangle (2 points).
#define QWT_OVERRIDE
Definition: qwt_global.h:53
void activated(bool on)
QwtPickerMachine * stateMachine
Definition: qwt_picker.cpp:110
virtual void append(const QPoint &)
Display only when the selection is active.
Definition: qwt_picker.h:171


plotjuggler
Author(s): Davide Faconti
autogenerated on Sun Dec 6 2020 03:48:10