qwt_picker.cpp
Go to the documentation of this file.
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  {
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 
119 {
120  public:
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 
137 
139 
142 
145  QFont trackerFont;
146 
147  QPolygon pickedPoints;
148  bool isActive;
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 
182  DisplayMode trackerMode, QWidget* parent ):
183  QObject( parent )
184 {
185  init( parent, rubberBand, trackerMode );
186 }
187 
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,
203 {
204  m_data = new PrivateData;
205 
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 
230 {
231  if ( m_data->stateMachine != stateMachine )
232  {
233  reset();
234 
235  delete m_data->stateMachine;
237 
238  if ( m_data->stateMachine )
240  }
241 }
242 
248 {
249  return m_data->stateMachine;
250 }
251 
257 {
258  return m_data->stateMachine;
259 }
260 
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 
290 {
292 }
293 
299 {
300  return m_data->rubberBand;
301 }
302 
320 {
321  if ( m_data->trackerMode != mode )
322  {
323  m_data->trackerMode = mode;
325  }
326 }
327 
333 {
334  return m_data->trackerMode;
335 }
336 
352 {
353  m_data->resizeMode = mode;
354 }
355 
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 
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 =
539 
540  if ( m_data->stateMachine )
541  selectionType = m_data->stateMachine->selectionType();
542 
543  switch ( selectionType )
544  {
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  }
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  }
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 =
649 
650  if ( m_data->stateMachine )
651  selectionType = m_data->stateMachine->selectionType();
652 
653  switch ( selectionType )
654  {
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  }
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  }
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 {
795 }
796 
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 
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  {
1206  {
1207  begin();
1208  break;
1209  }
1211  {
1212  append( pos );
1213  break;
1214  }
1216  {
1217  move( pos );
1218  break;
1219  }
1221  {
1222  remove();
1223  break;
1224  }
1225  case QwtPickerMachine::End:
1226  {
1227  end();
1228  break;
1229  }
1230  }
1231  }
1232 }
1233 
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 
1304 {
1305  if ( m_data->stateMachine )
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 
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 
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 
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 
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 
1582 {
1583  return m_data->rubberBandOverlay;
1584 }
1585 
1588 {
1589  return m_data->trackerOverlay;
1590 }
1591 
1592 #if QWT_MOC_INCLUDE
1593 #include "moc_qwt_picker.cpp"
1594 #endif
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:161
virtual void stretchSelection(const QSize &oldSize, const QSize &newSize)
void setRubberBand(RubberBand)
Definition: qwt_picker.cpp:289
QPen rubberBandPen() const
void setTrackerFont(const QFont &)
Definition: qwt_picker.cpp:410
virtual QList< Command > transition(const QwtEventPattern &, const QEvent *)=0
Transition.
virtual void widgetEnterEvent(QEvent *)
virtual void widgetKeyReleaseEvent(QKeyEvent *)
A crosshair ( only for QwtPickerMachine::PointSelection )
Definition: qwt_picker.h:139
lu_byte right
Definition: lparser.c:1227
static QRegion qwtMaskRegion(const QRect &r, int penWidth)
Definition: qwt_picker.cpp:23
virtual QRegion rubberBandMask() const
Definition: qwt_picker.cpp:525
static void drawLine(QPainter *, qreal x1, qreal y1, qreal x2, qreal y2)
Wrapper for QPainter::drawLine()
Definition: qwt_painter.h:154
virtual QRegion trackerMask() const
Definition: qwt_picker.cpp:514
ResizeMode resizeMode() const
The state machine not usable for any type of selection.
Display always.
Definition: qwt_picker.h:167
lu_byte left
Definition: lparser.c:1226
QWidget * parentWidget()
Return the parent widget, where the selection happens.
Definition: qwt_picker.cpp:262
void setTrackerMode(DisplayMode)
Set the display mode of the tracker.
Definition: qwt_picker.cpp:319
virtual QRegion maskHint() const
Calculate an approximation for the mask.
bool isEnabled() const
virtual QRect trackerRect(const QFont &) const
Definition: qwt_picker.cpp:812
void reset()
Set the current state to 0.
virtual void reset()
QwtWidgetOverlay(QWidget *)
Constructor.
bool isActive() const
void setMaskMode(MaskMode)
Specify how to find the mask for the overlay.
PrivateData * m_data
Definition: qwt_picker.h:334
const QwtPickerMachine * stateMachine() const
Definition: qwt_picker.cpp:256
virtual bool eventFilter(QObject *, QEvent *) QWT_OVERRIDE
Event filter.
Definition: qwt_picker.cpp:893
virtual void drawTracker(QPainter *) const
Definition: qwt_picker.cpp:732
virtual bool accept(QPolygon &) const
Validate and fix up the selection.
virtual void drawOverlay(QPainter *painter) const =0
void selected(const QPolygon &polygon)
virtual void widgetLeaveEvent(QEvent *)
void changed(const QPolygon &selection)
All points are scaled according to the new size,.
Definition: qwt_picker.h:184
const QwtWidgetOverlay * rubberBandOverlay() const
void moved(const QPoint &pos)
The state machine is for selecting a polygon (many points).
No rubberband.
Definition: qwt_picker.h:130
void setMouseTracking(bool)
void draw(QPainter *painter, const QRectF &rect) const
Definition: qwt_text.cpp:615
DisplayMode trackerMode() const
QwtPicker::ResizeMode resizeMode
Definition: qwt_picker.cpp:138
The state machine is for selecting a single point.
Definition: lz4.c:1706
RubberBand rubberBand() const
bool isEmpty() const
Definition: qwt_text.cpp:739
A polygon ( only for QwtPickerMachine::PolygonSelection )
Definition: qwt_picker.h:148
SelectionType selectionType() const
Return the selection type.
void setStateMachine(QwtPickerMachine *)
Definition: qwt_picker.cpp:229
virtual void widgetMouseMoveEvent(QMouseEvent *)
Definition: qwt_picker.cpp:996
virtual void transition(const QEvent *)
An ellipse ( only for QwtPickerMachine::RectSelection )
Definition: qwt_picker.h:145
virtual void widgetMouseDoubleClickEvent(QMouseEvent *)
QwtPicker::DisplayMode trackerMode
Definition: qwt_picker.cpp:143
A class representing a text.
Definition: qwt_text.h:51
A state machine for QwtPicker selections.
virtual void move(const QPoint &)
QSizeF textSize() const
Definition: qwt_text.cpp:570
virtual QPainterPath pickArea() const
QPoint trackerPosition() const
Definition: qwt_picker.cpp:798
QPointer< Tracker > trackerOverlay
Definition: qwt_picker.cpp:154
A horizontal line ( only for QwtPickerMachine::PointSelection )
Definition: qwt_picker.h:133
virtual void widgetWheelEvent(QWheelEvent *)
QwtPicker::RubberBand rubberBand
Definition: qwt_picker.cpp:140
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:375
Use maskHint() as mask.
void appended(const QPoint &pos)
int top(lua_State *L)
Definition: sol.hpp:11684
static void drawRect(QPainter *, qreal x, qreal y, qreal w, qreal h)
Wrapper for QPainter::drawRect()
Calculate a mask by checking the alpha values.
QPen trackerPen() const
A rectangle ( only for QwtPickerMachine::RectSelection )
Definition: qwt_picker.h:142
QPolygon selection() const
Definition: qwt_picker.cpp:792
An overlay for a widget.
QFont trackerFont() const
std::enable_if_t< all< Args... >::value, enable_t > enable
Definition: sol.hpp:2244
bool keyMatch(KeyPatternCode, const QKeyEvent *) const
Compare a key event with an event pattern.
virtual void widgetMouseReleaseEvent(QMouseEvent *)
void setResizeMode(ResizeMode)
Set the resize mode.
Definition: qwt_picker.cpp:351
virtual QPolygon adjustedPoints(const QPolygon &) const
Map the pickedPoints() into a selection()
Definition: qwt_picker.cpp:783
virtual void drawRubberBand(QPainter *) const
Definition: qwt_picker.cpp:637
A vertical line ( only for QwtPickerMachine::PointSelection )
Definition: qwt_picker.h:136
void removed(const QPoint &pos)
Display never.
Definition: qwt_picker.h:164
virtual QwtText trackerText(const QPoint &pos) const
Return the label for a position.
Definition: qwt_picker.cpp:490
QwtPicker(QWidget *parent)
Definition: qwt_picker.cpp:168
QPointer< Rubberband > rubberBandOverlay
Definition: qwt_picker.cpp:153
virtual ~QwtPicker()
Destructor.
Definition: qwt_picker.cpp:189
qreal penWidth(const QPainter *painter, const QwtScaleDraw *scaleDraw)
const QPolygon & pickedPoints() const
const QwtWidgetOverlay * trackerOverlay() const
void setRubberBandPen(const QPen &)
Definition: qwt_picker.cpp:459
virtual void begin()
int qwtCeil(qreal value)
Definition: qwt_math.h:262
virtual void widgetMousePressEvent(QMouseEvent *)
Definition: qwt_picker.cpp:982
void init(QWidget *, RubberBand rubberBand, DisplayMode trackerMode)
Initialize the picker - used by the constructors.
Definition: qwt_picker.cpp:201
void setTrackerPen(const QPen &)
Definition: qwt_picker.cpp:435
QwtPicker provides selections on a widget.
Definition: qwt_picker.h:103
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:136
virtual void append(const QPoint &)
Display only when the selection is active.
Definition: qwt_picker.h:170


plotjuggler
Author(s): Davide Faconti
autogenerated on Mon Jun 19 2023 03:01:38