QGIS API Documentation  3.26.3-Buenos Aires (65e4edfdad)
qgsplotcanvas.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsplotcanvas.cpp
3  -----------------
4  begin : March 2022
5  copyright : (C) 2022 by Nyall Dawson
6  email : nyall dot dawson at gmail dot com
7 ***************************************************************************/
8 
9 
10 /***************************************************************************
11  * *
12  * This program is free software; you can redistribute it and/or modify *
13  * it under the terms of the GNU General Public License as published by *
14  * the Free Software Foundation; either version 2 of the License, or *
15  * (at your option) any later version. *
16  * *
17  ***************************************************************************/
18 
19 #include "qgsplotcanvas.h"
20 #include "qgsplotmouseevent.h"
21 #include "qgsplottool.h"
22 #include "qgslogger.h"
23 #include "qgsplottransienttools.h"
24 #include "qgssettings.h"
25 
26 #include <QMenu>
27 #include <QKeyEvent>
28 #include <QGestureEvent>
29 
30 QgsPlotCanvas::QgsPlotCanvas( QWidget *parent )
31  : QGraphicsView( parent )
32 {
33  setObjectName( QStringLiteral( "PlotCanvas" ) );
34  mScene = new QGraphicsScene( this );
35  setScene( mScene );
36 
37  setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
38  setVerticalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
39  setMouseTracking( true );
40  viewport()->setMouseTracking( true );
41 
42  setFocusPolicy( Qt::StrongFocus );
43 
44  setRenderHints( QPainter::Antialiasing );
45 
46  mSpacePanTool = new QgsPlotToolTemporaryKeyPan( this );
47  mMidMouseButtonPanTool = new QgsPlotToolTemporaryMousePan( this );
48  mSpaceZoomTool = new QgsPlotToolTemporaryKeyZoom( this );
49 }
50 
52 {
53  if ( mTool )
54  {
55  mTool->deactivate();
56  mTool = nullptr;
57  }
58  emit willBeDeleted();
59 
61 
62  // WARNING WARNING WARNING
63  // QgsMapCanvas deletes all items in the destructor. But for some absolutely INSANE WTF reason
64  // if we uncomment this code below then we get random crashes in QGraphicsScene EVEN IF WE NEVER EVER CREATE A QgsPlotCanvas
65  // object and this code is NEVER EVEN CALLED ONCE. Like, WTAF??!?!?!?!?!
66 
67  // change this if you want to waste days of your life only. I don't, so I just made the scene parented to this canvas, and let's see what fallout ensures...
68 #if 0
69 
70  // delete canvas items prior to deleting the canvas
71  // because they might try to update canvas when it's
72  // already being destructed, ends with segfault
73  qDeleteAll( mScene->items() );
74 
75  mScene->deleteLater();
76 #endif
77 }
78 
80 {
81 
82 }
83 
85 {
86 
87 }
88 
89 void QgsPlotCanvas::showContextMenu( QgsPlotMouseEvent *event )
90 {
91  QMenu menu;
92 
93  if ( mTool )
94  {
95  mTool->populateContextMenuWithEvent( &menu, event );
96  }
97 
98  emit contextMenuAboutToShow( &menu, event );
99 
100  if ( !menu.isEmpty() )
101  menu.exec( event->globalPos() );
102 }
103 
104 void QgsPlotCanvas::keyPressEvent( QKeyEvent *event )
105 {
106  if ( mTool )
107  {
108  mTool->keyPressEvent( event );
109  }
110  if ( mTool && event->isAccepted() )
111  return;
112 
113  if ( event->key() == Qt::Key_Space && ! event->isAutoRepeat() )
114  {
115  if ( !( event->modifiers() & Qt::ControlModifier ) )
116  {
117  // Pan layout with space bar
118  setTool( mSpacePanTool );
119  }
120  else
121  {
122  //ctrl+space pressed, so switch to temporary keyboard based zoom tool
123  setTool( mSpaceZoomTool );
124  }
125  event->accept();
126  }
127 }
128 
129 void QgsPlotCanvas::keyReleaseEvent( QKeyEvent *event )
130 {
131  if ( mTool )
132  {
133  mTool->keyReleaseEvent( event );
134  }
135 
136  if ( !mTool || !event->isAccepted() )
137  QGraphicsView::keyReleaseEvent( event );
138 }
139 
140 void QgsPlotCanvas::mouseDoubleClickEvent( QMouseEvent *event )
141 {
142  if ( mTool )
143  {
144  std::unique_ptr<QgsPlotMouseEvent> me( new QgsPlotMouseEvent( this, event ) );
145  mTool->plotDoubleClickEvent( me.get() );
146  event->setAccepted( me->isAccepted() );
147  }
148 
149  if ( !mTool || !event->isAccepted() )
150  QGraphicsView::mouseDoubleClickEvent( event );
151 }
152 
153 void QgsPlotCanvas::mousePressEvent( QMouseEvent *event )
154 {
155  if ( mTool )
156  {
157  std::unique_ptr<QgsPlotMouseEvent> me( new QgsPlotMouseEvent( this, event ) );
158  mTool->plotPressEvent( me.get() );
159  event->setAccepted( me->isAccepted() );
160  }
161 
162  if ( !mTool || !event->isAccepted() )
163  {
164  if ( event->button() == Qt::MiddleButton )
165  {
166  // Pan layout with middle mouse button
167  setTool( mMidMouseButtonPanTool );
168  event->accept();
169  }
170  else if ( event->button() == Qt::RightButton && mTool->flags() & Qgis::PlotToolFlag::ShowContextMenu )
171  {
172  std::unique_ptr<QgsPlotMouseEvent> me( new QgsPlotMouseEvent( this, event ) );
173  showContextMenu( me.get() );
174  event->accept();
175  return;
176  }
177  else
178  {
179  QGraphicsView::mousePressEvent( event );
180  }
181  }
182 }
183 
184 void QgsPlotCanvas::mouseReleaseEvent( QMouseEvent *event )
185 {
186  if ( mTool )
187  {
188  std::unique_ptr<QgsPlotMouseEvent> me( new QgsPlotMouseEvent( this, event ) );
189  mTool->plotReleaseEvent( me.get() );
190  event->setAccepted( me->isAccepted() );
191  }
192 
193  if ( !mTool || !event->isAccepted() )
194  QGraphicsView::mouseReleaseEvent( event );
195 }
196 
197 void QgsPlotCanvas::resizeEvent( QResizeEvent *e )
198 {
199  QGraphicsView::resizeEvent( e );
200 }
201 
202 void QgsPlotCanvas::wheelEvent( QWheelEvent *event )
203 {
204  if ( mTool )
205  {
206  mTool->wheelEvent( event );
207  }
208 
209  if ( !mTool || !event->isAccepted() )
210  {
211  event->accept();
212  wheelZoom( event );
213  }
214 }
215 
216 void QgsPlotCanvas::mouseMoveEvent( QMouseEvent *event )
217 {
218  if ( mTool )
219  {
220  std::unique_ptr<QgsPlotMouseEvent> me( new QgsPlotMouseEvent( this, event ) );
221  mTool->plotMoveEvent( me.get() );
222  event->setAccepted( me->isAccepted() );
223  }
224 
225  if ( !mTool || !event->isAccepted() )
226  QGraphicsView::mouseMoveEvent( event );
227 }
228 
230 {
231  if ( mTool )
232  {
233  mTool->deactivate();
234  }
235 
236  if ( tool )
237  {
238  // activate new tool before setting it - gives tools a chance
239  // to respond to whatever the current tool is
240  tool->activate();
241  }
242 
243  mTool = tool;
244  emit toolChanged( mTool );
245 }
246 
248 {
249  if ( mTool && mTool == tool )
250  {
251  mTool->deactivate();
252  emit toolChanged( nullptr );
253  setCursor( Qt::ArrowCursor );
254  }
255 }
256 
258 {
259  return mTool;
260 }
261 
263 {
265 }
266 
268 {
269  return QgsPoint();
270 }
271 
273 {
274  return QgsPointXY();
275 }
276 
277 void QgsPlotCanvas::panContentsBy( double, double )
278 {
279 
280 }
281 
282 void QgsPlotCanvas::centerPlotOn( double, double )
283 {
284 
285 }
286 
288 {
289 
290 }
291 
292 void QgsPlotCanvas::zoomToRect( const QRectF & )
293 {
294 
295 }
296 
298 {
299  return QgsPointXY();
300 }
301 
302 bool QgsPlotCanvas::viewportEvent( QEvent *event )
303 {
304  if ( event->type() == QEvent::ToolTip && mTool && mTool->canvasToolTipEvent( qgis::down_cast<QHelpEvent *>( event ) ) )
305  {
306  return true;
307  }
308  return QGraphicsView::viewportEvent( event );
309 }
310 
311 void QgsPlotCanvas::wheelZoom( QWheelEvent * )
312 {
313 
314 }
315 
316 bool QgsPlotCanvas::event( QEvent *e )
317 {
318  if ( !QTouchDevice::devices().empty() )
319  {
320  if ( e->type() == QEvent::Gesture )
321  {
322  // call handler of current map tool
323  if ( mTool )
324  {
325  return mTool->gestureEvent( static_cast<QGestureEvent *>( e ) );
326  }
327  }
328  }
329 
330  // pass other events to base class
331  return QGraphicsView::event( e );
332 }
QgsPlotCanvas::zoomToRect
virtual void zoomToRect(const QRectF &rect)
Zooms the plot to the specified rect in canvas units.
Definition: qgsplotcanvas.cpp:292
qgsplotmouseevent.h
QgsPlotCanvas::mousePressEvent
void mousePressEvent(QMouseEvent *e) override
Definition: qgsplotcanvas.cpp:153
QgsPlotCanvas::resizeEvent
void resizeEvent(QResizeEvent *e) override
Definition: qgsplotcanvas.cpp:197
QgsPlotCanvas::cancelJobs
virtual void cancelJobs()
Cancel any rendering job, in a blocking way.
Definition: qgsplotcanvas.cpp:79
QgsPlotCanvas::tool
QgsPlotTool * tool()
Returns the currently active tool.
Definition: qgsplotcanvas.cpp:257
QgsPlotCanvas::crs
virtual QgsCoordinateReferenceSystem crs() const
Returns the coordinate reference system (CRS) for map coordinates used by the canvas.
Definition: qgsplotcanvas.cpp:262
QgsPoint
Point geometry type, with support for z-dimension and m-values.
Definition: qgspoint.h:48
qgsplotcanvas.h
QgsPlotCanvas::toolChanged
void toolChanged(QgsPlotTool *newTool)
Emitted when the plot tool is changed.
QgsPlotCanvas::viewportEvent
bool viewportEvent(QEvent *event) override
Definition: qgsplotcanvas.cpp:302
QgsPlotCanvas::~QgsPlotCanvas
~QgsPlotCanvas() override
Definition: qgsplotcanvas.cpp:51
QgsPlotCanvas::toCanvasCoordinates
virtual QgsPointXY toCanvasCoordinates(const QgsPoint &point) const
Converts a point in map coordinates to the associated canvas point.
Definition: qgsplotcanvas.cpp:272
QgsPlotCanvas::willBeDeleted
void willBeDeleted()
Emitted in the destructor when the canvas is about to be deleted, but is still in a perfectly valid s...
QgsPlotCanvas::scalePlot
virtual void scalePlot(double factor)
Scales the plot by a specified scale factor.
Definition: qgsplotcanvas.cpp:287
QgsPlotToolTemporaryKeyZoom
Plot tool for temporarily zooming a plot while a key is depressed.
Definition: qgsplottransienttools.h:88
QgsPlotCanvas::centerPlotOn
virtual void centerPlotOn(double x, double y)
Centers the plot on the plot point corresponding to x, y in canvas units.
Definition: qgsplotcanvas.cpp:282
QgsPlotCanvas::refresh
virtual void refresh()
Updates and redraws the plot.
Definition: qgsplotcanvas.cpp:84
QgsPlotCanvas::mouseMoveEvent
void mouseMoveEvent(QMouseEvent *e) override
Definition: qgsplotcanvas.cpp:216
QgsPlotCanvas::mouseReleaseEvent
void mouseReleaseEvent(QMouseEvent *e) override
Definition: qgsplotcanvas.cpp:184
QgsPlotToolTemporaryKeyPan
Plot tool for temporarily panning a plot while a key is depressed.
Definition: qgsplottransienttools.h:32
QgsPlotCanvas::wheelEvent
void wheelEvent(QWheelEvent *e) override
Definition: qgsplotcanvas.cpp:202
QgsPlotTool
Abstract base class for all interactive plot tools.
Definition: qgsplottool.h:57
QgsPlotCanvas::setTool
void setTool(QgsPlotTool *tool)
Sets the interactive tool currently being used on the canvas.
Definition: qgsplotcanvas.cpp:229
Qgis::PlotToolFlag::ShowContextMenu
@ ShowContextMenu
Show a context menu when right-clicking with the tool.
qgsplottool.h
QgsCoordinateReferenceSystem
This class represents a coordinate reference system (CRS).
Definition: qgscoordinatereferencesystem.h:211
QgsPlotTool::activate
virtual void activate()
Called when the tool is set as the currently active plot tool.
Definition: qgsplottool.cpp:79
QgsPlotCanvas::event
bool event(QEvent *e) override
Definition: qgsplotcanvas.cpp:316
QgsPointXY
A class to represent a 2D point.
Definition: qgspointxy.h:58
QgsPlotCanvas::snapToPlot
virtual QgsPointXY snapToPlot(QPoint point)
Snap a canvas point to the plot.
Definition: qgsplotcanvas.cpp:297
QgsPlotCanvas::unsetTool
void unsetTool(QgsPlotTool *tool)
Unset the current tool.
Definition: qgsplotcanvas.cpp:247
qgsplottransienttools.h
QgsPlotCanvas::QgsPlotCanvas
QgsPlotCanvas(QWidget *parent=nullptr)
Constructor for QgsPlotCanvas, with the specified parent widget.
Definition: qgsplotcanvas.cpp:30
QgsPlotCanvas::keyPressEvent
void keyPressEvent(QKeyEvent *e) override
Definition: qgsplotcanvas.cpp:104
qgssettings.h
QgsPlotCanvas::panContentsBy
virtual void panContentsBy(double dx, double dy)
Pans the plot contents by dx, dy in canvas units.
Definition: qgsplotcanvas.cpp:277
QgsPlotCanvas::toMapCoordinates
virtual QgsPoint toMapCoordinates(const QgsPointXY &point) const
Converts a point on the canvas to the associated map coordinate.
Definition: qgsplotcanvas.cpp:267
QgsPlotCanvas::mouseDoubleClickEvent
void mouseDoubleClickEvent(QMouseEvent *e) override
Definition: qgsplotcanvas.cpp:140
QgsPlotMouseEvent
A QgsPlotMouseEvent is the result of a user interaction with the mouse on a QgsPlotCanvas.
Definition: qgsplotmouseevent.h:39
QgsPlotCanvas::keyReleaseEvent
void keyReleaseEvent(QKeyEvent *e) override
Definition: qgsplotcanvas.cpp:129
qgslogger.h
QgsPlotToolTemporaryMousePan
Plot tool for temporarily panning a plot while a mouse button is depressed.
Definition: qgsplottransienttools.h:60
QgsPlotCanvas::wheelZoom
virtual void wheelZoom(QWheelEvent *event)
Zoom plot from a mouse wheel event.
Definition: qgsplotcanvas.cpp:311
QgsPlotCanvas::contextMenuAboutToShow
void contextMenuAboutToShow(QMenu *menu, QgsPlotMouseEvent *event)
Emitted before the canvas context menu will be shown.