QGIS API Documentation  3.16.0-Hannover (43b64b13f3)
qgslayoutviewtooladdnodeitem.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgslayoutviewtooladdnodeitem.cpp
3  ----------------------------
4  Date : July 2017
5  Copyright : (C) 2017 Nyall Dawson
6  Email : nyall dot dawson at gmail dot com
7  ***************************************************************************
8  * *
9  * This program is free software; you can redistribute it and/or modify *
10  * it under the terms of the GNU General Public License as published by *
11  * the Free Software Foundation; either version 2 of the License, or *
12  * (at your option) any later version. *
13  * *
14  ***************************************************************************/
15 
17 #include "qgsapplication.h"
18 #include "qgslayoutview.h"
19 #include "qgslayout.h"
20 #include "qgslayoutitemregistry.h"
22 #include "qgslogger.h"
24 #include "qgsgui.h"
27 #include "qgssettings.h"
28 #include "qgslayoututils.h"
29 #include "qgslayoutitemnodeitem.h"
30 #include <QGraphicsRectItem>
31 #include <QPen>
32 #include <QBrush>
33 #include <QMouseEvent>
34 
36  : QgsLayoutViewTool( view, tr( "Add item" ) )
37 {
39  setCursor( Qt::CrossCursor );
40 }
41 
43 {
44  mItemMetadataId = metadataId;
45 }
46 
48 {
49  if ( event->button() == Qt::LeftButton )
50  {
51  if ( !mRubberBand )
52  {
53  mPolygon.clear();
54  mRubberBand.reset( QgsGui::layoutItemGuiRegistry()->createNodeItemRubberBand( mItemMetadataId, view() ) );
55  if ( mRubberBand )
56  layout()->addItem( mRubberBand.get() );
57  }
58 
59  if ( mRubberBand )
60  {
61  //add a new node
62  addNode( event->snappedPoint() );
63  }
64  }
65  else if ( event->button() == Qt::RightButton && mRubberBand )
66  {
67  // finish up
68 
69  // last (temporary) point is removed
70  mPolygon.remove( mPolygon.count() - 1 );
71 
72  QgsLayoutItem *item = QgsGui::layoutItemGuiRegistry()->createItem( mItemMetadataId, layout() );
73  if ( !item )
74  return;
75 
76  if ( QgsLayoutNodesItem *nodesItem = qobject_cast< QgsLayoutNodesItem * >( item ) )
77  nodesItem->setNodes( mPolygon );
78 
79  layout()->addLayoutItem( item );
80  layout()->setSelectedItem( item );
81  emit createdItem();
82  }
83  else
84  {
85  event->ignore();
86  mRubberBand.reset();
87  }
88 
89 }
90 
92 {
93  if ( mRubberBand )
94  {
95  moveTemporaryNode( event->snappedPoint(), event->modifiers() );
96  }
97  else
98  {
99  event->ignore();
100  }
101 }
102 
104 {
105  if ( !mRubberBand )
106  {
107  event->ignore();
108  return;
109  }
110 }
111 
113 {
114  if ( !mRubberBand || event->isAutoRepeat() )
115  {
116  event->ignore();
117  return;
118  }
119 
120  if ( event->key() == Qt::Key_Delete || event->key() == Qt::Key_Backspace )
121  {
122  if ( mPolygon.size() > 2 )
123  {
124  //remove last added vertex
125  mPolygon.pop_back();
126  setRubberBandNodes();
127  }
128  else
129  {
130  // all deleted, cancel
131  mRubberBand.reset();
132  }
133  }
134  else if ( event->key() == Qt::Key_Escape )
135  {
136  mRubberBand.reset();
137  }
138  else
139  {
140  event->ignore();
141  }
142 }
143 
145 {
146  if ( mRubberBand )
147  {
148  // canceled mid operation
149  mRubberBand.reset();
150  }
152 }
153 
154 void QgsLayoutViewToolAddNodeItem::addNode( QPointF scenePoint )
155 {
156  mPolygon.append( scenePoint );
157 
158  if ( mPolygon.size() == 1 )
159  mPolygon.append( scenePoint );
160 
161  setRubberBandNodes();
162 }
163 
164 void QgsLayoutViewToolAddNodeItem::moveTemporaryNode( QPointF scenePoint, Qt::KeyboardModifiers modifiers )
165 {
166  if ( mPolygon.isEmpty() )
167  return;
168 
169  if ( mPolygon.size() > 1 && ( modifiers & Qt::ShiftModifier ) )
170  {
171  QPointF start = mPolygon.at( mPolygon.size() - 2 );
172  QLineF newLine = QLineF( start, scenePoint );
173 
174  //movement is constrained to 45 degree angles
175  double angle = QgsLayoutUtils::snappedAngle( newLine.angle() );
176  newLine.setAngle( angle );
177  scenePoint = newLine.p2();
178  }
179 
180  mPolygon.replace( mPolygon.size() - 1, scenePoint );
181  setRubberBandNodes();
182 }
183 
184 void QgsLayoutViewToolAddNodeItem::setRubberBandNodes()
185 {
186  if ( QGraphicsPolygonItem *polygonItem = dynamic_cast< QGraphicsPolygonItem *>( mRubberBand.get() ) )
187  {
188  polygonItem->setPolygon( mPolygon );
189  }
190  else if ( QGraphicsPathItem *polylineItem = dynamic_cast< QGraphicsPathItem *>( mRubberBand.get() ) )
191  {
192  // rebuild a new qpainter path
193  QPainterPath path;
194  path.addPolygon( mPolygon );
195  polylineItem->setPath( path );
196  }
197 }
198 
200 {
201  return mItemMetadataId;
202 }
QgsLayout::addLayoutItem
void addLayoutItem(QgsLayoutItem *item)
Adds an item to the layout.
Definition: qgslayout.cpp:540
QgsLayout::setSelectedItem
void setSelectedItem(QgsLayoutItem *item)
Clears any selected items and sets item as the current selection.
Definition: qgslayout.cpp:159
QgsLayoutViewToolAddNodeItem::setItemMetadataId
void setItemMetadataId(int metadataId)
Sets the item metadata metadataId for items created by the tool.
Definition: qgslayoutviewtooladdnodeitem.cpp:42
QgsLayoutViewTool::FlagSnaps
@ FlagSnaps
Tool utilizes snapped coordinates.
Definition: qgslayoutviewtool.h:65
QgsLayoutUtils::snappedAngle
static double snappedAngle(double angle)
Snaps an angle (in degrees) to its closest 45 degree angle.
Definition: qgslayoututils.cpp:54
qgsgui.h
qgslayoutviewtooladdnodeitem.h
qgslayoutview.h
QgsLayoutViewTool::setFlags
void setFlags(QgsLayoutViewTool::Flags flags)
Sets the combination of flags that will be used for the tool.
Definition: qgslayoutviewtool.cpp:64
qgslayoutviewmouseevent.h
qgslayoutitemnodeitem.h
QgsLayoutViewTool::deactivate
virtual void deactivate()
Called when tool is deactivated.
Definition: qgslayoutviewtool.cpp:130
QgsLayoutViewToolAddNodeItem::layoutPressEvent
void layoutPressEvent(QgsLayoutViewMouseEvent *event) override
Mouse press event for overriding.
Definition: qgslayoutviewtooladdnodeitem.cpp:47
qgslayoutnewitempropertiesdialog.h
QgsLayoutViewToolAddNodeItem::QgsLayoutViewToolAddNodeItem
QgsLayoutViewToolAddNodeItem(QgsLayoutView *view)
Constructs a QgsLayoutViewToolAddNodeItem for the given layout view.
Definition: qgslayoutviewtooladdnodeitem.cpp:35
qgsapplication.h
qgslayoututils.h
qgslayoutviewrubberband.h
QgsLayoutViewToolAddNodeItem::layoutMoveEvent
void layoutMoveEvent(QgsLayoutViewMouseEvent *event) override
Mouse move event for overriding.
Definition: qgslayoutviewtooladdnodeitem.cpp:91
qgslayoutitemguiregistry.h
QgsLayoutViewTool::view
QgsLayoutView * view() const
Returns the view associated with the tool.
Definition: qgslayoutviewtool.cpp:38
QgsLayoutItem
Base class for graphical items within a QgsLayout.
Definition: qgslayoutitem.h:113
QgsLayoutViewTool::layout
QgsLayout * layout() const
Returns the layout associated with the tool.
Definition: qgslayoutviewtool.cpp:43
QgsLayoutViewMouseEvent::snappedPoint
QPointF snappedPoint() const
Returns the snapped event point location in layout coordinates.
Definition: qgslayoutviewmouseevent.h:78
QgsLayoutItemGuiRegistry::createItem
QgsLayoutItem * createItem(int metadataId, QgsLayout *layout) const
Creates a new instance of a layout item given the item metadata metadataId, target layout.
Definition: qgslayoutitemguiregistry.cpp:85
qgslayout.h
QgsLayoutViewToolAddNodeItem::layoutReleaseEvent
void layoutReleaseEvent(QgsLayoutViewMouseEvent *event) override
Mouse release event for overriding.
Definition: qgslayoutviewtooladdnodeitem.cpp:103
QgsLayoutNodesItem
An abstract layout item that provides generic methods for node based shapes such as polygon or polyli...
Definition: qgslayoutitemnodeitem.h:30
QgsLayoutViewTool
Abstract base class for all layout view tools.
Definition: qgslayoutviewtool.h:47
QgsLayoutViewToolAddNodeItem::itemMetadataId
int itemMetadataId() const
Returns the item metadata id for items created by the tool.
Definition: qgslayoutviewtooladdnodeitem.cpp:199
qgssettings.h
QgsLayoutView
A graphical widget to display and interact with QgsLayouts.
Definition: qgslayoutview.h:50
qgslogger.h
QgsLayoutViewToolAddNodeItem::createdItem
void createdItem()
Emitted when an item has been created using the tool.
QgsLayoutViewTool::setCursor
void setCursor(const QCursor &cursor)
Sets a user defined cursor for use when the tool is active.
Definition: qgslayoutviewtool.cpp:115
QgsLayoutViewToolAddNodeItem::keyPressEvent
void keyPressEvent(QKeyEvent *event) override
Key press event for overriding.
Definition: qgslayoutviewtooladdnodeitem.cpp:112
QgsLayoutViewMouseEvent
A QgsLayoutViewMouseEvent is the result of a user interaction with the mouse on a QgsLayoutView.
Definition: qgslayoutviewmouseevent.h:36
qgslayoutitemregistry.h
MathUtils::angle
double ANALYSIS_EXPORT angle(QgsPoint *p1, QgsPoint *p2, QgsPoint *p3, QgsPoint *p4)
Calculates the angle between two segments (in 2 dimension, z-values are ignored)
Definition: MathUtils.cpp:786
QgsGui::layoutItemGuiRegistry
static QgsLayoutItemGuiRegistry * layoutItemGuiRegistry()
Returns the global layout item GUI registry, used for registering the GUI behavior of layout items.
Definition: qgsgui.cpp:99
QgsLayoutViewToolAddNodeItem::deactivate
void deactivate() override
Called when tool is deactivated.
Definition: qgslayoutviewtooladdnodeitem.cpp:144