QGIS API Documentation 3.28.0-Firenze (ed3ad0430f)
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"
24#include "qgssettings.h"
25
26#include <QMenu>
27#include <QKeyEvent>
28#include <QGestureEvent>
29
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
89void 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
104void 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
129void 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
140void 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
153void 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
184void 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
197void QgsPlotCanvas::resizeEvent( QResizeEvent *e )
198{
199 QGraphicsView::resizeEvent( e );
200}
201
202void 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
216void 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
277void QgsPlotCanvas::panContentsBy( double, double )
278{
279
280}
281
282void QgsPlotCanvas::centerPlotOn( double, double )
283{
284
285}
286
288{
289
290}
291
292void QgsPlotCanvas::zoomToRect( const QRectF & )
293{
294
295}
296
298{
299 return QgsPointXY();
300}
301
302bool 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
311void QgsPlotCanvas::wheelZoom( QWheelEvent * )
312{
313
314}
315
316bool QgsPlotCanvas::event( QEvent *e )
317{
318 if ( e->type() == QEvent::Gesture )
319 {
320 // call handler of current map tool
321 if ( mTool )
322 {
323 return mTool->gestureEvent( static_cast<QGestureEvent *>( e ) );
324 }
325 }
326
327 // pass other events to base class
328 return QGraphicsView::event( e );
329}
@ ShowContextMenu
Show a context menu when right-clicking with the tool.
This class represents a coordinate reference system (CRS).
bool event(QEvent *e) override
void setTool(QgsPlotTool *tool)
Sets the interactive tool currently being used on the canvas.
virtual void cancelJobs()
Cancel any rendering job, in a blocking way.
QgsPlotCanvas(QWidget *parent=nullptr)
Constructor for QgsPlotCanvas, with the specified parent widget.
virtual void refresh()
Updates and redraws the plot.
virtual void zoomToRect(const QRectF &rect)
Zooms the plot to the specified rect in canvas units.
void keyPressEvent(QKeyEvent *e) override
virtual void panContentsBy(double dx, double dy)
Pans the plot contents by dx, dy in canvas units.
void mousePressEvent(QMouseEvent *e) override
void toolChanged(QgsPlotTool *newTool)
Emitted when the plot tool is changed.
virtual QgsPointXY toCanvasCoordinates(const QgsPoint &point) const
Converts a point in map coordinates to the associated canvas point.
~QgsPlotCanvas() override
void keyReleaseEvent(QKeyEvent *e) override
QgsPlotTool * tool()
Returns the currently active tool.
void mouseDoubleClickEvent(QMouseEvent *e) override
void contextMenuAboutToShow(QMenu *menu, QgsPlotMouseEvent *event)
Emitted before the canvas context menu will be shown.
void mouseReleaseEvent(QMouseEvent *e) override
void unsetTool(QgsPlotTool *tool)
Unset the current tool.
void wheelEvent(QWheelEvent *e) override
void mouseMoveEvent(QMouseEvent *e) override
void resizeEvent(QResizeEvent *e) override
void willBeDeleted()
Emitted in the destructor when the canvas is about to be deleted, but is still in a perfectly valid s...
virtual void scalePlot(double factor)
Scales the plot by a specified scale factor.
virtual QgsCoordinateReferenceSystem crs() const
Returns the coordinate reference system (CRS) for map coordinates used by the canvas.
virtual void wheelZoom(QWheelEvent *event)
Zoom plot from a mouse wheel event.
virtual QgsPoint toMapCoordinates(const QgsPointXY &point) const
Converts a point on the canvas to the associated map coordinate.
bool viewportEvent(QEvent *event) override
virtual QgsPointXY snapToPlot(QPoint point)
Snap a canvas point to the plot.
virtual void centerPlotOn(double x, double y)
Centers the plot on the plot point corresponding to x, y in canvas units.
A QgsPlotMouseEvent is the result of a user interaction with the mouse on a QgsPlotCanvas.
Plot tool for temporarily panning a plot while a key is depressed.
Plot tool for temporarily zooming a plot while a key is depressed.
Plot tool for temporarily panning a plot while a mouse button is depressed.
Abstract base class for all interactive plot tools.
Definition: qgsplottool.h:58
virtual void activate()
Called when the tool is set as the currently active plot tool.
Definition: qgsplottool.cpp:79
A class to represent a 2D point.
Definition: qgspointxy.h:59
Point geometry type, with support for z-dimension and m-values.
Definition: qgspoint.h:49