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