QGIS API Documentation 3.99.0-Master (2fe06baccd8)
Loading...
Searching...
No Matches
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
21#include "qgslogger.h"
22#include "qgsplotmouseevent.h"
23#include "qgsplottool.h"
25#include "qgssettings.h"
26
27#include <QGestureEvent>
28#include <QKeyEvent>
29#include <QMenu>
30
31#include "moc_qgsplotcanvas.cpp"
32
34 : QGraphicsView( parent )
35{
36 setObjectName( QStringLiteral( "PlotCanvas" ) );
37 mScene = new QGraphicsScene( this );
38 setScene( mScene );
39
40 setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
41 setVerticalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
42 setMouseTracking( true );
43 viewport()->setMouseTracking( true );
44
45 setFocusPolicy( Qt::StrongFocus );
46
47 setRenderHints( QPainter::Antialiasing );
48
49 mSpacePanTool = new QgsPlotToolTemporaryKeyPan( this );
50 mMidMouseButtonPanTool = new QgsPlotToolTemporaryMousePan( this );
51 mSpaceZoomTool = new QgsPlotToolTemporaryKeyZoom( this );
52}
53
55{
56 if ( mTool )
57 {
58 mTool->deactivate();
59 mTool = nullptr;
60 }
61 emit willBeDeleted();
62
64
65 // WARNING WARNING WARNING
66 // QgsMapCanvas deletes all items in the destructor. But for some absolutely INSANE WTF reason
67 // if we uncomment this code below then we get random crashes in QGraphicsScene EVEN IF WE NEVER EVER CREATE A QgsPlotCanvas
68 // object and this code is NEVER EVEN CALLED ONCE. Like, WTAF??!?!?!?!?!
69
70 // 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...
71#if 0
72
73 // delete canvas items prior to deleting the canvas
74 // because they might try to update canvas when it's
75 // already being destructed, ends with segfault
76 qDeleteAll( mScene->items() );
77
78 mScene->deleteLater();
79#endif
80}
81
85
89
90void QgsPlotCanvas::showContextMenu( QgsPlotMouseEvent *event )
91{
92 QMenu menu;
93
94 if ( mTool )
95 {
96 mTool->populateContextMenuWithEvent( &menu, event );
97 }
98
99 emit contextMenuAboutToShow( &menu, event );
100
101 if ( !menu.isEmpty() )
102 menu.exec( event->globalPos() );
103}
104
106{
107 if ( mTool )
108 {
109 mTool->keyPressEvent( event );
110 }
111 if ( mTool && event->isAccepted() )
112 return;
113
114 if ( event->key() == Qt::Key_Space && !event->isAutoRepeat() )
115 {
116 if ( !( event->modifiers() & Qt::ControlModifier ) )
117 {
118 // Pan layout with space bar
119 setTool( mSpacePanTool );
120 }
121 else
122 {
123 //ctrl+space pressed, so switch to temporary keyboard based zoom tool
124 setTool( mSpaceZoomTool );
125 }
126 event->accept();
127 }
128}
129
131{
132 if ( mTool )
133 {
134 mTool->keyReleaseEvent( event );
135 }
136
137 if ( !mTool || !event->isAccepted() )
138 QGraphicsView::keyReleaseEvent( event );
139}
140
142{
143 if ( mTool )
144 {
145 auto me = std::make_unique<QgsPlotMouseEvent>( this, event );
146 mTool->plotDoubleClickEvent( me.get() );
147 event->setAccepted( me->isAccepted() );
148 }
149
150 if ( !mTool || !event->isAccepted() )
151 QGraphicsView::mouseDoubleClickEvent( event );
152}
153
155{
156 if ( mTool )
157 {
158 auto me = std::make_unique<QgsPlotMouseEvent>( this, event );
159 mTool->plotPressEvent( me.get() );
160 event->setAccepted( me->isAccepted() );
161 }
162
163 if ( !mTool || !event->isAccepted() )
164 {
165 if ( event->button() == Qt::MiddleButton )
166 {
167 // Pan layout with middle mouse button
168 setTool( mMidMouseButtonPanTool );
169 event->accept();
170 }
171 else if ( event->button() == Qt::RightButton && mTool && mTool->flags() & Qgis::PlotToolFlag::ShowContextMenu )
172 {
173 auto me = std::make_unique<QgsPlotMouseEvent>( this, event );
174 showContextMenu( me.get() );
175 event->accept();
176 return;
177 }
178 else
179 {
180 QGraphicsView::mousePressEvent( event );
181 }
182 }
183}
184
186{
187 if ( mTool )
188 {
189 auto me = std::make_unique<QgsPlotMouseEvent>( this, event );
190 mTool->plotReleaseEvent( me.get() );
191 event->setAccepted( me->isAccepted() );
192 }
193
194 if ( !mTool || !event->isAccepted() )
195 QGraphicsView::mouseReleaseEvent( event );
196}
197
198void QgsPlotCanvas::resizeEvent( QResizeEvent *e )
199{
200 QGraphicsView::resizeEvent( e );
201}
202
204{
205 if ( mTool )
206 {
207 mTool->wheelEvent( event );
208 }
209
210 if ( !mTool || !event->isAccepted() )
211 {
212 event->accept();
213 wheelZoom( event );
214 }
215}
216
218{
219 if ( mTool )
220 {
221 auto me = std::make_unique<QgsPlotMouseEvent>( this, event );
222 mTool->plotMoveEvent( me.get() );
223 event->setAccepted( me->isAccepted() );
224 }
225
226 if ( !mTool || !event->isAccepted() )
227 QGraphicsView::mouseMoveEvent( event );
228}
229
231{
232 if ( mTool )
233 {
234 mTool->deactivate();
235 }
236
237 if ( tool )
238 {
239 // activate new tool before setting it - gives tools a chance
240 // to respond to whatever the current tool is
241 tool->activate();
242 }
243
244 mTool = tool;
245 emit toolChanged( mTool );
246}
247
249{
250 if ( mTool && mTool == tool )
251 {
252 mTool->deactivate();
253 emit toolChanged( nullptr );
254 setCursor( Qt::ArrowCursor );
255 }
256}
257
259{
260 return mTool;
261}
262
267
269{
270 return QgsPoint();
271}
272
274{
275 return QgsPointXY();
276}
277
278void QgsPlotCanvas::panContentsBy( double, double )
279{
280}
281
282void QgsPlotCanvas::centerPlotOn( double, double )
283{
284}
285
287{
288}
289
290void QgsPlotCanvas::zoomToRect( const QRectF & )
291{
292}
293
295{
296 return QgsPointXY();
297}
298
300{
301 if ( event->type() == QEvent::ToolTip && mTool && mTool->canvasToolTipEvent( qgis::down_cast<QHelpEvent *>( event ) ) )
302 {
303 return true;
304 }
305 return QGraphicsView::viewportEvent( event );
306}
307
308void QgsPlotCanvas::wheelZoom( QWheelEvent * )
309{
310}
311
312bool QgsPlotCanvas::event( QEvent *e )
313{
314 if ( e->type() == QEvent::Gesture )
315 {
316 // call handler of current map tool
317 if ( mTool )
318 {
319 return mTool->gestureEvent( static_cast<QGestureEvent *>( e ) );
320 }
321 }
322
323 // pass other events to base class
324 return QGraphicsView::event( e );
325}
@ ShowContextMenu
Show a context menu when right-clicking with the tool.
Definition qgis.h:4109
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 mouse event which is the result of a user interaction with 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:59
Represents a 2D point.
Definition qgspointxy.h:60
Point geometry type, with support for z-dimension and m-values.
Definition qgspoint.h:49