25 if ( !layout || items.size() < 2 )
30 const QRectF itemBBox = boundingRectOfItems( items );
31 if ( !itemBBox.isValid() )
40 refCoord = itemBBox.left();
43 refCoord = itemBBox.center().x();
46 refCoord = itemBBox.right();
49 refCoord = itemBBox.top();
52 refCoord = itemBBox.center().y();
55 refCoord = itemBBox.bottom();
64 QPointF shifted = item->pos();
68 shifted.setX( refCoord );
71 shifted.setX( refCoord - item->rect().width() / 2.0 );
74 shifted.setX( refCoord - item->rect().width() );
77 shifted.setY( refCoord );
80 shifted.setY( refCoord - item->rect().height() / 2.0 );
83 shifted.setY( refCoord - item->rect().height() );
89 item->attemptMove( newPos,
false );
98 if ( items.size() < 2 )
104 distributeEquispacedItems( layout, items, distribution );
108 auto collectReferenceCoord = [distribution](
QgsLayoutItem *item ) ->
double {
109 const QRectF itemBBox = item->sceneBoundingRect();
110 switch ( distribution )
113 return itemBBox.left();
115 return itemBBox.center().x();
117 return itemBBox.right();
119 return itemBBox.top();
121 return itemBBox.center().y();
123 return itemBBox.bottom();
127 return std::numeric_limits<double>::quiet_NaN();
130 return itemBBox.left();
134 double minCoord = std::numeric_limits<double>::max();
135 double maxCoord = std::numeric_limits<double>::lowest();
136 QMap< double, QgsLayoutItem * > itemCoords;
139 const double refCoord = collectReferenceCoord( item );
140 minCoord = std::min( minCoord, refCoord );
141 maxCoord = std::max( maxCoord, refCoord );
142 itemCoords.insert( refCoord, item );
145 const double step = ( maxCoord - minCoord ) / ( items.size() - 1 );
147 auto distributeItemToCoord = [layout, distribution](
QgsLayoutItem *item,
double refCoord ) {
148 QPointF shifted = item->pos();
149 switch ( distribution )
152 shifted.setX( refCoord );
155 shifted.setX( refCoord - item->rect().width() / 2.0 );
158 shifted.setX( refCoord - item->rect().width() );
161 shifted.setY( refCoord );
164 shifted.setY( refCoord - item->rect().height() / 2.0 );
167 shifted.setY( refCoord - item->rect().height() );
177 item->attemptMove( newPos,
false );
182 double currentVal = minCoord;
183 for (
auto itemIt = itemCoords.constBegin(); itemIt != itemCoords.constEnd(); ++itemIt )
186 distributeItemToCoord( itemIt.value(), currentVal );
196 if ( !( items.size() >= 2 || ( items.size() == 1 && resize ==
ResizeToSquare ) ) )
199 auto collectSize = [resize](
QgsLayoutItem *item ) ->
double {
200 const QRectF itemBBox = item->sceneBoundingRect();
206 return itemBBox.width();
209 return itemBBox.height();
212 return itemBBox.width();
215 double newSize = collectSize( items.at( 0 ) );
218 const double size = collectSize( item );
223 newSize = std::min( size, newSize );
227 newSize = std::max( size, newSize );
234 auto resizeItemToSize = [layout, resize](
QgsLayoutItem *item,
double size ) {
235 QSizeF newSize = item->rect().size();
240 newSize.setWidth( size );
244 newSize.setHeight( size );
248 if ( newSize.width() > newSize.height() )
249 newSize.setHeight( newSize.width() );
251 newSize.setWidth( newSize.height() );
258 item->attemptResize( newSizeWithUnits );
265 resizeItemToSize( item, newSize );
271QRectF QgsLayoutAligner::boundingRectOfItems(
const QList<QgsLayoutItem *> &items )
278 auto it = items.constBegin();
280 QgsLayoutItem *currentItem = *it;
282 double minX = currentItem->pos().x();
283 double minY = currentItem->pos().y();
284 double maxX = minX + currentItem->rect().width();
285 double maxY = minY + currentItem->rect().height();
287 double currentMinX, currentMinY, currentMaxX, currentMaxY;
289 for ( ; it != items.constEnd(); ++it )
292 currentMinX = currentItem->pos().x();
293 currentMinY = currentItem->pos().y();
294 currentMaxX = currentMinX + currentItem->rect().width();
295 currentMaxY = currentMinY + currentItem->rect().height();
297 if ( currentMinX < minX )
299 if ( currentMaxX > maxX )
301 if ( currentMinY < minY )
303 if ( currentMaxY > maxY )
307 return QRectF( QPointF( minX, minY ), QPointF( maxX, maxY ) );
310QString QgsLayoutAligner::undoText( Distribution distribution )
312 switch ( distribution )
315 return QObject::tr(
"Distribute Items by Left" );
317 return QObject::tr(
"Distribute Items by Horizontal Center" );
319 return QObject::tr(
"Distribute Horizontal Spacing Equally" );
321 return QObject::tr(
"Distribute Items by Right" );
323 return QObject::tr(
"Distribute Items by Top" );
325 return QObject::tr(
"Distribute Items by Vertical Center" );
327 return QObject::tr(
"Distribute Vertical Spacing Equally" );
329 return QObject::tr(
"Distribute Items by Bottom" );
339 return QObject::tr(
"Resize Items to Narrowest" );
341 return QObject::tr(
"Resize Items to Widest" );
343 return QObject::tr(
"Resize Items to Shortest" );
345 return QObject::tr(
"Resize Items to Tallest" );
347 return QObject::tr(
"Resize Items to Square" );
352QString QgsLayoutAligner::undoText( Alignment alignment )
357 return QObject::tr(
"Align Items to Left" );
359 return QObject::tr(
"Align Items to Center" );
361 return QObject::tr(
"Align Items to Right" );
363 return QObject::tr(
"Align Items to Top" );
365 return QObject::tr(
"Align Items to Vertical Center" );
367 return QObject::tr(
"Align Items to Bottom" );
375 double minCoord = std::numeric_limits<double>::max();
376 double maxCoord = std::numeric_limits<double>::lowest();
377 QMap< double, QgsLayoutItem * > itemCoords;
379 for ( QgsLayoutItem *item : items )
381 const QRectF itemBBox = item->sceneBoundingRect();
383 const double item_min = ( distribution ==
DistributeHSpace ? itemBBox.left() : itemBBox.top() );
384 const double item_max = ( distribution ==
DistributeHSpace ? itemBBox.right() : itemBBox.bottom() );
386 minCoord = std::min( minCoord, item_min );
387 maxCoord = std::max( maxCoord, item_max );
388 length += ( item_max - item_min );
389 itemCoords.insert( item_min, item );
391 const double step = ( maxCoord - minCoord - length ) / ( items.size() - 1 );
393 double currentVal = minCoord;
395 for (
auto itemIt = itemCoords.constBegin(); itemIt != itemCoords.constEnd(); ++itemIt )
397 QgsLayoutItem *item = itemIt.value();
398 QPointF shifted = item->pos();
404 shifted.setX( currentVal );
408 shifted.setY( currentVal );
416 currentVal += ( distribution ==
DistributeHSpace ? item->rect().width() : item->rect().height() ) + step;
Alignment
Alignment options.
@ AlignVCenter
Align vertical centers.
@ AlignLeft
Align left edges.
@ AlignBottom
Align bottom edges.
@ AlignRight
Align right edges.
@ AlignTop
Align top edges.
@ AlignHCenter
Align horizontal centers.
@ ResizeNarrowest
Resize width to match narrowest width.
@ ResizeShortest
Resize height to match shortest height.
@ ResizeTallest
Resize height to match tallest height.
@ ResizeToSquare
Resize items to square.
@ ResizeWidest
Resize width to match widest width.
static void alignItems(QgsLayout *layout, const QList< QgsLayoutItem * > &items, Alignment alignment)
Aligns a set of items from a layout in place.
static void distributeItems(QgsLayout *layout, const QList< QgsLayoutItem * > &items, Distribution distribution)
Distributes a set of items from a layout in place.
static void resizeItems(QgsLayout *layout, const QList< QgsLayoutItem * > &items, Resize resize)
Resizes a set of items from a layout in place.
Distribution
Distribution options.
@ DistributeHSpace
Distribute horizontal equispaced.
@ DistributeVCenter
Distribute vertical centers.
@ DistributeBottom
Distribute bottom edges.
@ DistributeLeft
Distribute left edges.
@ DistributeHCenter
Distribute horizontal centers.
@ DistributeRight
Distribute right edges.
@ DistributeVSpace
Distribute vertical equispaced.
@ DistributeTop
Distribute top edges.
Base class for graphical items within a QgsLayout.
QgsLayoutPoint positionWithUnits() const
Returns the item's current position, including units.
virtual void attemptMove(const QgsLayoutPoint &point, bool useReferencePoint=true, bool includesFrame=false, int page=-1)
Attempts to move the item to a specified point.
Provides a method of storing points, consisting of an x and y coordinate, for use in QGIS layouts.
Qgis::LayoutUnit units() const
Returns the units for the point.
Provides a method of storing sizes, consisting of a width and height, for use in QGIS layouts.
void endCommand()
Saves final state of an object and pushes the active command to the undo history.
void beginMacro(const QString &commandText)
Starts a macro command, with the given descriptive commandText.
void beginCommand(QgsLayoutUndoObjectInterface *object, const QString &commandText, int id=0)
Begins a new undo command for the specified object.
void endMacro()
Ends a macro command.
Base class for layouts, which can contain items such as maps, labels, scalebars, etc.
QgsLayoutMeasurement convertFromLayoutUnits(double length, Qgis::LayoutUnit unit) const
Converts a length measurement from the layout's native units to a specified target unit.
QgsLayoutUndoStack * undoStack()
Returns a pointer to the layout's undo stack, which manages undo/redo states for the layout and it's ...