QGIS API Documentation  3.4.15-Madeira (e83d02e274)
qgslayoutviewtooladditem.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgslayoutviewtooladditem.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 "qgslayoutundostack.h"
29 #include <QGraphicsRectItem>
30 #include <QPen>
31 #include <QBrush>
32 #include <QMouseEvent>
33 
35  : QgsLayoutViewTool( view, tr( "Add item" ) )
36 {
38  setCursor( Qt::CrossCursor );
39 }
40 
42 {
43  mItemMetadataId = metadataId;
44 }
45 
47 {
48  if ( event->button() != Qt::LeftButton )
49  {
50  event->ignore();
51  return;
52  }
53 
54  mDrawing = true;
55  mMousePressStartPos = event->pos();
56  mRubberBand.reset( QgsGui::layoutItemGuiRegistry()->createItemRubberBand( mItemMetadataId, view() ) );
57  if ( mRubberBand )
58  {
59  connect( mRubberBand.get(), &QgsLayoutViewRubberBand::sizeChanged, this, [ = ]( const QString & size )
60  {
61  view()->pushStatusMessage( size );
62  } );
63  mRubberBand->start( event->snappedPoint(), event->modifiers() );
64  }
65 }
66 
68 {
69  if ( mDrawing && mRubberBand )
70  {
71  mRubberBand->update( event->snappedPoint(), event->modifiers() );
72  }
73  else
74  {
75  event->ignore();
76  }
77 }
78 
80 {
81  if ( event->button() != Qt::LeftButton || !mDrawing )
82  {
83  event->ignore();
84  return;
85  }
86  mDrawing = false;
87 
88  QRectF rect = mRubberBand->finish( event->snappedPoint(), event->modifiers() );
89 
90  QString undoText;
91  if ( QgsLayoutItemAbstractGuiMetadata *metadata = QgsGui::layoutItemGuiRegistry()->itemMetadata( mItemMetadataId ) )
92  {
93  undoText = tr( "Create %1" ).arg( metadata->visibleName() );
94  }
95  else
96  {
97  undoText = tr( "Create Item" );
98  }
99  layout()->undoStack()->beginMacro( undoText );
100 
101  QgsLayoutItem *item = QgsGui::layoutItemGuiRegistry()->createItem( mItemMetadataId, layout() );
102  if ( !item )
103  {
104  layout()->undoStack()->endMacro();
105  return;
106  }
107 
108  // click? or click-and-drag?
109  bool clickOnly = !isClickAndDrag( mMousePressStartPos, event->pos() );
110  if ( clickOnly )
111  {
113  dlg.setLayout( layout() );
114  dlg.setItemPosition( QgsLayoutPoint( event->snappedPoint(), layout()->units() ) );
115  if ( dlg.exec() )
116  {
117  item->setReferencePoint( dlg.referencePoint() );
118  item->attemptResize( dlg.itemSize() );
119  item->attemptMove( dlg.itemPosition(), true, false, dlg.page() );
120  }
121  else
122  {
123  delete item;
124  layout()->undoStack()->endMacro();
125  return;
126  }
127  }
128  else
129  {
130  item->attemptResize( QgsLayoutSize( rect.width(), rect.height(), QgsUnitTypes::LayoutMillimeters ) );
131  item->attemptMove( QgsLayoutPoint( rect.left(), rect.top(), QgsUnitTypes::LayoutMillimeters ) );
132  }
133 
134  // record last created item size
135  QgsSettings settings;
136  settings.setValue( QStringLiteral( "LayoutDesigner/lastItemWidth" ), item->sizeWithUnits().width() );
137  settings.setValue( QStringLiteral( "LayoutDesigner/lastItemHeight" ), item->sizeWithUnits().height() );
138  settings.setEnumValue( QStringLiteral( "LayoutDesigner/lastSizeUnit" ), item->sizeWithUnits().units() );
139 
140  QgsGui::layoutItemGuiRegistry()->newItemAddedToLayout( mItemMetadataId, item );
141 
142  // it's possible (in certain circumstances, e.g. when adding frame items) that this item
143  // has already been added to the layout
144  if ( item->scene() != layout() )
145  layout()->addLayoutItem( item );
146  layout()->setSelectedItem( item );
147 
148  layout()->undoStack()->endMacro();
149  emit createdItem();
150 }
151 
153 {
154  if ( mDrawing )
155  {
156  // canceled mid operation
157  mRubberBand->finish();
158  mDrawing = false;
159  }
161 }
162 
164 {
165  return mItemMetadataId;
166 }
void pushStatusMessage(const QString &message)
Pushes a new status bar message to the view.
void setCursor(const QCursor &cursor)
Sets a user defined cursor for use when the tool is active.
void setFlags(QgsLayoutViewTool::Flags flags)
Sets the combination of flags that will be used for the tool.
void setSelectedItem(QgsLayoutItem *item)
Clears any selected items and sets item as the current selection.
Definition: qgslayout.cpp:156
QgsLayoutViewToolAddItem(QgsLayoutView *view)
Constructs a QgsLayoutViewToolAddItem for the given layout view.
void setItemPosition(QgsLayoutPoint position)
Sets the item position to show in the dialog.
Base class for graphical items within a QgsLayout.
A graphical widget to display and interact with QgsLayouts.
Definition: qgslayoutview.h:49
This class is a composition of two QSettings instances:
Definition: qgssettings.h:58
QgsLayoutUndoStack * undoStack()
Returns a pointer to the layout&#39;s undo stack, which manages undo/redo states for the layout and it&#39;s ...
Definition: qgslayout.cpp:682
QgsUnitTypes::LayoutUnit units() const
Returns the units for the size.
virtual void deactivate()
Called when tool is deactivated.
Stores GUI metadata about one layout item class.
void setLayout(QgsLayout *layout)
Sets the layout associated with the dialog.
double height() const
Returns the height of the size.
Definition: qgslayoutsize.h:90
QgsLayoutSize sizeWithUnits() const
Returns the item&#39;s current size, including units.
This class provides a method of storing points, consisting of an x and y coordinate, for use in QGIS layouts.
QgsLayout * layout() const
Returns the layout associated with the tool.
double width() const
Returns the width of the size.
Definition: qgslayoutsize.h:76
QgsLayoutView * view() const
Returns the view associated with the tool.
static QgsLayoutItemGuiRegistry * layoutItemGuiRegistry()
Returns the global layout item GUI registry, used for registering the GUI behavior of layout items...
Definition: qgsgui.cpp:83
int page() const
Returns the page number for the new item.
A dialog for configuring properties like the size and position of layout items.
virtual void attemptResize(const QgsLayoutSize &size, bool includesFrame=false)
Attempts to resize the item to a specified target size.
void deactivate() override
Called when tool is deactivated.
void sizeChanged(const QString &size)
Emitted when the size of the rubber band is changed.
int itemMetadataId() const
Returns the item metadata id for items created by the tool.
void layoutPressEvent(QgsLayoutViewMouseEvent *event) override
Mouse press event for overriding.
void beginMacro(const QString &commandText)
Starts a macro command, with the given descriptive commandText.
void setItemMetadataId(int metadataId)
Sets the item metadata metadataId for items created by the tool.
A QgsLayoutViewMouseEvent is the result of a user interaction with the mouse on a QgsLayoutView...
void setEnumValue(const QString &key, const T &value, const Section section=NoSection)
Set the value of a setting based on an enum.
Definition: qgssettings.h:287
void createdItem()
Emitted when an item has been created using the tool.
QgsLayoutSize itemSize() const
Returns the item size defined by the dialog.
QgsLayoutItemAbstractGuiMetadata * itemMetadata(int metadataId) const
Returns the metadata for the specified item metadataId.
void layoutMoveEvent(QgsLayoutViewMouseEvent *event) override
Mouse move event for overriding.
bool isClickAndDrag(QPoint startViewPoint, QPoint endViewPoint) const
Returns true if a mouse press/release operation which started at startViewPoint and ended at endViewP...
void setValue(const QString &key, const QVariant &value, QgsSettings::Section section=QgsSettings::NoSection)
Sets the value of setting key to value.
virtual void attemptMove(const QgsLayoutPoint &point, bool useReferencePoint=true, bool includesFrame=false, int page=-1)
Attempts to move the item to a specified point.
void setReferencePoint(ReferencePoint point)
Sets the reference point for positioning of the layout item.
void addLayoutItem(QgsLayoutItem *item)
Adds an item to the layout.
Definition: qgslayout.cpp:536
void newItemAddedToLayout(int metadataId, QgsLayoutItem *item)
Called when a newly created item of the associated metadata metadataId has been added to a layout...
QgsUnitTypes::LayoutUnit units() const
Returns the native units for the layout.
Definition: qgslayout.h:328
QgsLayoutItem::ReferencePoint referencePoint() const
Returns the item reference point defined by the dialog.
Abstract base class for all layout view tools.
void endMacro()
Ends a macro command.
QgsLayoutPoint itemPosition() const
Returns the current item position defined by the dialog.
This class provides a method of storing sizes, consisting of a width and height, for use in QGIS layo...
Definition: qgslayoutsize.h:40
void layoutReleaseEvent(QgsLayoutViewMouseEvent *event) override
Mouse release event for overriding.
QgsLayoutItem * createItem(int metadataId, QgsLayout *layout) const
Creates a new instance of a layout item given the item metadata metadataId, target layout...
Tool utilizes snapped coordinates.
QPointF snappedPoint() const
Returns the snapped event point location in layout coordinates.