QGIS API Documentation  3.16.0-Hannover (43b64b13f3)
qgslayoutviewtooleditnodes.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgslayoutviewtooleditnodes.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 
18 #include "qgslayoutview.h"
19 #include "qgslayout.h"
20 #include "qgslayoutitemnodeitem.h"
21 #include "qgslayoutundostack.h"
22 
24  : QgsLayoutViewTool( view, tr( "Select" ) )
25 {
26  setCursor( Qt::CrossCursor );
28 }
29 
31 {
32  if ( mNodesItem && mNodesItemIndex != -1 )
33  {
34  layout()->undoStack()->beginCommand( mNodesItem, tr( "Remove Item Node" ) );
35  if ( mNodesItem->removeNode( mNodesItemIndex ) )
36  {
37  layout()->undoStack()->endCommand();
38  if ( mNodesItem->nodesSize() > 0 )
39  {
40  mNodesItemIndex = mNodesItem->selectedNode();
41  // setSelectedNode( mNodesItem, mNodesItemIndex );
42  }
43  else
44  {
45  mNodesItemIndex = -1;
46  mNodesItem = nullptr;
47  }
48  if ( mNodesItem )
49  mNodesItem->update();
50  }
51  else
52  {
54  }
55  }
56 }
57 
59 {
60  displayNodes( true );
62 }
63 
65 {
66  if ( event->button() != Qt::LeftButton )
67  {
68  event->ignore();
69  return;
70  }
71 
72  const QList<QGraphicsItem *> itemsAtCursorPos = view()->items( event->pos().x(), event->pos().y(),
73  mMoveContentSearchRadius,
74  mMoveContentSearchRadius );
75  if ( itemsAtCursorPos.isEmpty() )
76  return;
77 
78  mNodesItemIndex = -1;
79  mNodesItem = nullptr;
80  isMoving = false;
81 
82  for ( QGraphicsItem *graphicsItem : itemsAtCursorPos )
83  {
84  QgsLayoutNodesItem *item = dynamic_cast<QgsLayoutNodesItem *>( graphicsItem );
85 
86  if ( item && !item->isLocked() )
87  {
88  int index = item->nodeAtPosition( event->layoutPoint() );
89  if ( index != -1 )
90  {
91  mNodesItemIndex = index;
92  mNodesItem = item;
93  mMoveContentStartPos = event->layoutPoint();
94  }
95  }
96 
97  if ( mNodesItem && mNodesItemIndex != -1 )
98  {
99  layout()->undoStack()->beginCommand( mNodesItem, tr( "Move Item Node" ) );
100  setSelectedNode( mNodesItem, mNodesItemIndex );
101  isMoving = true;
102  break;
103  }
104  }
105 }
106 
108 {
109  if ( !isMoving )
110  {
111  event->ignore();
112  return;
113  }
114 
115  if ( mNodesItem && mNodesItemIndex != -1 && event->layoutPoint() != mMoveContentStartPos )
116  {
117  mNodesItem->moveNode( mNodesItemIndex, event->snappedPoint() );
118  }
119 }
120 
122 {
123  if ( event->button() != Qt::LeftButton || !isMoving )
124  {
125  event->ignore();
126  return;
127  }
128 
129  isMoving = false;
130  if ( mNodesItemIndex != -1 )
131  {
132  if ( event->layoutPoint() != mMoveContentStartPos )
133  {
134  layout()->undoStack()->endCommand();
135  }
136  else
137  {
139  }
140  }
141 }
142 
144 {
145  if ( event->button() != Qt::LeftButton )
146  {
147  event->ignore();
148  return;
149  }
150 
151  // erase status previously set by the mousePressEvent method
152  if ( mNodesItemIndex != -1 )
153  {
154  mNodesItem = nullptr;
155  mNodesItemIndex = -1;
156  deselectNodes();
157  }
158 
159  // search items in layout
160  const QList<QGraphicsItem *> itemsAtCursorPos = view()->items( event->pos().x(), event->pos().y(),
161  mMoveContentSearchRadius,
162  mMoveContentSearchRadius );
163 
164  if ( itemsAtCursorPos.isEmpty() )
165  return;
166 
167  bool rc = false;
168  for ( QGraphicsItem *graphicsItem : itemsAtCursorPos )
169  {
170  QgsLayoutNodesItem *item = dynamic_cast<QgsLayoutNodesItem *>( graphicsItem );
171 
172  if ( item && !item->isLocked() )
173  {
174  layout()->undoStack()->beginCommand( item, tr( "Add Item Node" ) );
175  rc = item->addNode( event->layoutPoint() );
176 
177  if ( rc )
178  {
179  layout()->undoStack()->endCommand();
180  mNodesItem = item;
181  mNodesItemIndex = mNodesItem->nodeAtPosition( event->layoutPoint() );
182  }
183  else
185  }
186 
187  if ( rc )
188  break;
189  }
190 
191  if ( rc )
192  {
193  setSelectedNode( mNodesItem, mNodesItemIndex );
194  mNodesItem->update();
195  }
196 }
197 
199 {
200  if ( mNodesItem && mNodesItemIndex != -1 && ( event->key() == Qt::Key_Left
201  || event->key() == Qt::Key_Right
202  || event->key() == Qt::Key_Up
203  || event->key() == Qt::Key_Down ) )
204  {
205  QPointF currentPos;
206 
207  if ( mNodesItem->nodePosition( mNodesItemIndex, currentPos ) )
208  {
209  QPointF delta = view()->deltaForKeyEvent( event );
210 
211  currentPos.setX( currentPos.x() + delta.x() );
212  currentPos.setY( currentPos.y() + delta.y() );
213 
214  layout()->undoStack()->beginCommand( mNodesItem, tr( "Move Item Node" ), QgsLayoutItem::UndoNodeMove );
215  mNodesItem->moveNode( mNodesItemIndex, currentPos );
216  layout()->undoStack()->endCommand();
217  layout()->update();
218  }
219  }
220  else
221  {
222  event->ignore();
223  }
224 }
225 
227 {
228  displayNodes( false );
229  deselectNodes();
231 }
232 
233 QList<QgsLayoutItem *> QgsLayoutViewToolEditNodes::ignoredSnapItems() const
234 {
235  QList< QgsLayoutItem * > items;
236  if ( mNodesItem )
237  items << mNodesItem;
238  return items;
239 }
240 
241 void QgsLayoutViewToolEditNodes::displayNodes( bool display )
242 {
243  QList<QgsLayoutNodesItem *> nodesShapes;
244  layout()->layoutItems( nodesShapes );
245 
246  for ( QgsLayoutNodesItem *item : qgis::as_const( nodesShapes ) )
247  {
248  item->setDisplayNodes( display );
249  item->update();
250  }
251 }
252 
253 void QgsLayoutViewToolEditNodes::deselectNodes()
254 {
255  QList<QgsLayoutNodesItem *> nodesShapes;
256  layout()->layoutItems( nodesShapes );
257 
258  for ( QgsLayoutNodesItem *item : qgis::as_const( nodesShapes ) )
259  {
260  item->deselectNode();
261  item->update();
262  }
263 }
264 
265 void QgsLayoutViewToolEditNodes::setSelectedNode( QgsLayoutNodesItem *shape, int index )
266 {
267  QList<QgsLayoutNodesItem *> nodesShapes;
268  layout()->layoutItems( nodesShapes );
269 
270  for ( QgsLayoutNodesItem *item : qgis::as_const( nodesShapes ) )
271  {
272  if ( item == shape )
273  {
274  item->setSelectedNode( index );
275  layout()->setSelectedItem( item );
276  item->update();
277  }
278  else
279  {
280  item->deselectNode();
281  item->update();
282  }
283  }
284 
285 }
286 
QgsLayout::undoStack
QgsLayoutUndoStack * undoStack()
Returns a pointer to the layout's undo stack, which manages undo/redo states for the layout and it's ...
Definition: qgslayout.cpp:686
qgslayoutundostack.h
QgsLayout::setSelectedItem
void setSelectedItem(QgsLayoutItem *item)
Clears any selected items and sets item as the current selection.
Definition: qgslayout.cpp:159
QgsLayout::layoutItems
void layoutItems(QList< T * > &itemList) const
Returns a list of layout items of a specific type.
Definition: qgslayout.h:121
QgsLayoutViewTool::FlagSnaps
@ FlagSnaps
Tool utilizes snapped coordinates.
Definition: qgslayoutviewtool.h:65
QgsLayoutViewToolEditNodes::layoutPressEvent
void layoutPressEvent(QgsLayoutViewMouseEvent *event) override
Mouse press event for overriding.
Definition: qgslayoutviewtooleditnodes.cpp:64
QgsLayoutViewToolEditNodes::layoutReleaseEvent
void layoutReleaseEvent(QgsLayoutViewMouseEvent *event) override
Mouse release event for overriding.
Definition: qgslayoutviewtooleditnodes.cpp:121
QgsLayoutViewToolEditNodes::QgsLayoutViewToolEditNodes
QgsLayoutViewToolEditNodes(QgsLayoutView *view)
Constructor for QgsLayoutViewToolEditNodes.
Definition: qgslayoutviewtooleditnodes.cpp:23
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
QgsLayoutView::deltaForKeyEvent
QPointF deltaForKeyEvent(QKeyEvent *event)
Returns the delta (in layout coordinates) by which to move items for the given key event.
Definition: qgslayoutview.cpp:472
QgsLayoutViewToolEditNodes::keyPressEvent
void keyPressEvent(QKeyEvent *event) override
Key press event for overriding.
Definition: qgslayoutviewtooleditnodes.cpp:198
QgsLayoutViewToolEditNodes::deactivate
void deactivate() override
Called when tool is deactivated.
Definition: qgslayoutviewtooleditnodes.cpp:226
QgsLayoutViewToolEditNodes::activate
void activate() override
Called when tool is set as the currently active layout tool.
Definition: qgslayoutviewtooleditnodes.cpp:58
QgsLayoutNodesItem::addNode
bool addNode(QPointF point, bool checkArea=true, double radius=10)
Add a node in current shape.
Definition: qgslayoutitemnodeitem.cpp:94
qgslayoutviewtooleditnodes.h
QgsLayoutViewTool::view
QgsLayoutView * view() const
Returns the view associated with the tool.
Definition: qgslayoutviewtool.cpp:38
QgsLayoutViewToolEditNodes::layoutDoubleClickEvent
void layoutDoubleClickEvent(QgsLayoutViewMouseEvent *event) override
Mouse double-click event for overriding.
Definition: qgslayoutviewtooleditnodes.cpp:143
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
QgsLayoutUndoStack::cancelCommand
void cancelCommand()
Cancels the active command, discarding it without pushing to the undo history.
Definition: qgslayoutundostack.cpp:68
qgslayout.h
QgsLayoutUndoStack::endCommand
void endCommand()
Saves final state of an object and pushes the active command to the undo history.
Definition: qgslayoutundostack.cpp:53
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
QgsLayoutViewToolEditNodes::ignoredSnapItems
QList< QgsLayoutItem * > ignoredSnapItems() const override
Returns a list of items which should be ignored while snapping events for this tool.
Definition: qgslayoutviewtooleditnodes.cpp:233
QgsLayoutUndoStack::beginCommand
void beginCommand(QgsLayoutUndoObjectInterface *object, const QString &commandText, int id=0)
Begins a new undo command for the specified object.
Definition: qgslayoutundostack.cpp:42
QgsLayoutView
A graphical widget to display and interact with QgsLayouts.
Definition: qgslayoutview.h:50
QgsLayoutViewMouseEvent::layoutPoint
QPointF layoutPoint() const
Returns the event point location in layout coordinates.
Definition: qgslayoutviewmouseevent.cpp:44
QgsLayoutViewToolEditNodes::layoutMoveEvent
void layoutMoveEvent(QgsLayoutViewMouseEvent *event) override
Mouse move event for overriding.
Definition: qgslayoutviewtooleditnodes.cpp:107
QgsLayoutNodesItem::nodeAtPosition
int nodeAtPosition(QPointF point, bool searchInRadius=true, double radius=10) const
Search for the nearest node in the shape within a maximal area.
Definition: qgslayoutitemnodeitem.cpp:209
QgsLayoutViewTool::setCursor
void setCursor(const QCursor &cursor)
Sets a user defined cursor for use when the tool is active.
Definition: qgslayoutviewtool.cpp:115
QgsLayoutViewTool::activate
virtual void activate()
Called when tool is set as the currently active layout tool.
Definition: qgslayoutviewtool.cpp:120
QgsLayoutViewMouseEvent
A QgsLayoutViewMouseEvent is the result of a user interaction with the mouse on a QgsLayoutView.
Definition: qgslayoutviewmouseevent.h:36
QgsLayoutViewToolEditNodes::deleteSelectedNode
void deleteSelectedNode()
Deletes the selected node from the item.
Definition: qgslayoutviewtooleditnodes.cpp:30
QgsLayoutItem::UndoNodeMove
@ UndoNodeMove
Node move.
Definition: qgslayoutitem.h:228
QgsLayoutItem::isLocked
bool isLocked() const
Returns true if the item is locked, and cannot be interacted with using the mouse.
Definition: qgslayoutitem.h:400