QGIS API Documentation  3.8.0-Zanzibar (11aff65)
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:157
QgsLayoutViewToolAddItem(QgsLayoutView *view)
Constructs a QgsLayoutViewToolAddItem for the given layout view.
void setItemPosition(QgsLayoutPoint position)
Sets the item position to show in the dialog.
QgsLayoutItem * createItem(int metadataId, QgsLayout *layout) const
Creates a new instance of a layout item given the item metadata metadataId, target layout...
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:684
virtual void deactivate()
Called when tool is deactivated.
QgsUnitTypes::LayoutUnit units() const
Returns the native units for the layout.
Definition: qgslayout.h:328
QgsLayoutSize sizeWithUnits() const
Returns the item&#39;s current size, including units.
Stores GUI metadata about one layout item class.
void setLayout(QgsLayout *layout)
Sets the layout associated with the dialog.
This class provides a method of storing points, consisting of an x and y coordinate, for use in QGIS layouts.
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:84
QgsLayout * layout() const
Returns the layout associated with the tool.
QgsLayoutPoint itemPosition() const
Returns the current item position defined by the dialog.
bool isClickAndDrag(QPoint startViewPoint, QPoint endViewPoint) const
Returns true if a mouse press/release operation which started at startViewPoint and ended at endViewP...
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.
QgsLayoutItem::ReferencePoint referencePoint() const
Returns the item reference point defined by the dialog.
void deactivate() override
Called when tool is deactivated.
QgsUnitTypes::LayoutUnit units() const
Returns the units for the size.
void sizeChanged(const QString &size)
Emitted when the size of the rubber band is changed.
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:296
void createdItem()
Emitted when an item has been created using the tool.
void layoutMoveEvent(QgsLayoutViewMouseEvent *event) override
Mouse move event for overriding.
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.
QgsLayoutSize itemSize() const
Returns the item size defined by the dialog.
void addLayoutItem(QgsLayoutItem *item)
Adds an item to the layout.
Definition: qgslayout.cpp:538
QgsLayoutItemAbstractGuiMetadata * itemMetadata(int metadataId) const
Returns the metadata for the specified item metadataId.
void newItemAddedToLayout(int metadataId, QgsLayoutItem *item)
Called when a newly created item of the associated metadata metadataId has been added to a layout...
Abstract base class for all layout view tools.
QPointF snappedPoint() const
Returns the snapped event point location in layout coordinates.
void endMacro()
Ends a macro command.
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.
double height() const
Returns the height of the size.
Definition: qgslayoutsize.h:90
Tool utilizes snapped coordinates.
int page() const
Returns the page number for the new item.
int itemMetadataId() const
Returns the item metadata id for items created by the tool.
double width() const
Returns the width of the size.
Definition: qgslayoutsize.h:76