QGIS API Documentation 4.1.0-Master (5bf3c20f3c9)
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
87
90
91void QgsPlotCanvas::showContextMenu( QgsPlotMouseEvent *event )
92{
93 QMenu menu;
94
95 if ( mTool )
96 {
97 mTool->populateContextMenuWithEvent( &menu, event );
98 }
99
100 emit contextMenuAboutToShow( &menu, event );
101
102 if ( !menu.isEmpty() )
103 menu.exec( event->globalPos() );
104}
105
107{
108 if ( mTool )
109 {
110 mTool->keyPressEvent( event );
111 }
112 if ( mTool && event->isAccepted() )
113 return;
114
115 if ( event->key() == Qt::Key_Space && !event->isAutoRepeat() )
116 {
117 if ( !( event->modifiers() & Qt::ControlModifier ) )
118 {
119 // Pan layout with space bar
120 setTool( mSpacePanTool );
121 }
122 else
123 {
124 //ctrl+space pressed, so switch to temporary keyboard based zoom tool
125 setTool( mSpaceZoomTool );
126 }
127 event->accept();
128 }
129}
130
132{
133 if ( mTool )
134 {
135 mTool->keyReleaseEvent( event );
136 }
137
138 if ( !mTool || !event->isAccepted() )
139 QGraphicsView::keyReleaseEvent( event );
140}
141
143{
144 if ( mTool )
145 {
146 auto me = std::make_unique<QgsPlotMouseEvent>( this, event );
147 mTool->plotDoubleClickEvent( me.get() );
148 event->setAccepted( me->isAccepted() );
149 }
150
151 if ( !mTool || !event->isAccepted() )
152 QGraphicsView::mouseDoubleClickEvent( event );
153}
154
156{
157 if ( mTool )
158 {
159 auto me = std::make_unique<QgsPlotMouseEvent>( this, event );
160 mTool->plotPressEvent( me.get() );
161 event->setAccepted( me->isAccepted() );
162 }
163
164 if ( !mTool || !event->isAccepted() )
165 {
166 if ( event->button() == Qt::MiddleButton )
167 {
168 // Pan layout with middle mouse button
169 setTool( mMidMouseButtonPanTool );
170 event->accept();
171 }
172 else if ( event->button() == Qt::RightButton && mTool && mTool->flags() & Qgis::PlotToolFlag::ShowContextMenu )
173 {
174 auto me = std::make_unique<QgsPlotMouseEvent>( this, event );
175 showContextMenu( me.get() );
176 event->accept();
177 return;
178 }
179 else
180 {
181 QGraphicsView::mousePressEvent( event );
182 }
183 }
184}
185
187{
188 if ( mTool )
189 {
190 auto me = std::make_unique<QgsPlotMouseEvent>( this, event );
191 mTool->plotReleaseEvent( me.get() );
192 event->setAccepted( me->isAccepted() );
193 }
194
195 if ( !mTool || !event->isAccepted() )
196 QGraphicsView::mouseReleaseEvent( event );
197}
198
199void QgsPlotCanvas::resizeEvent( QResizeEvent *e )
200{
201 QGraphicsView::resizeEvent( e );
202}
203
205{
206 if ( mTool )
207 {
208 mTool->wheelEvent( event );
209 }
210
211 if ( !mTool || !event->isAccepted() )
212 {
213 event->accept();
214 wheelZoom( event );
215 }
216}
217
219{
220 if ( mTool )
221 {
222 auto me = std::make_unique<QgsPlotMouseEvent>( this, event );
223 mTool->plotMoveEvent( me.get() );
224 event->setAccepted( me->isAccepted() );
225 }
226
227 if ( !mTool || !event->isAccepted() )
228 QGraphicsView::mouseMoveEvent( event );
229}
230
232{
233 if ( mTool )
234 {
235 mTool->deactivate();
236 }
237
238 if ( tool )
239 {
240 // activate new tool before setting it - gives tools a chance
241 // to respond to whatever the current tool is
242 tool->activate();
243 }
244
245 mTool = tool;
246 emit toolChanged( mTool );
247}
248
250{
251 if ( mTool && mTool == tool )
252 {
253 mTool->deactivate();
254 emit toolChanged( nullptr );
255 setCursor( Qt::ArrowCursor );
256 }
257}
258
260{
261 return mTool;
262}
263
268
270{
271 return QgsPoint();
272}
273
275{
276 return QgsPointXY();
277}
278
279void QgsPlotCanvas::panContentsBy( double, double )
280{}
281
282void QgsPlotCanvas::centerPlotOn( double, double )
283{}
284
286{}
287
288void QgsPlotCanvas::zoomToRect( const QRectF & )
289{}
290
292{
293 return QgsPointXY();
294}
295
297{
298 if ( event->type() == QEvent::ToolTip && mTool && mTool->canvasToolTipEvent( qgis::down_cast<QHelpEvent *>( event ) ) )
299 {
300 return true;
301 }
302 return QGraphicsView::viewportEvent( event );
303}
304
305void QgsPlotCanvas::wheelZoom( QWheelEvent * )
306{}
307
308bool QgsPlotCanvas::event( QEvent *e )
309{
310 if ( e->type() == QEvent::Gesture )
311 {
312 // call handler of current map tool
313 if ( mTool )
314 {
315 return mTool->gestureEvent( static_cast<QGestureEvent *>( e ) );
316 }
317 }
318
319 // pass other events to base class
320 return QGraphicsView::event( e );
321}
@ ShowContextMenu
Show a context menu when right-clicking with the tool.
Definition qgis.h:4238
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