[FEATURE][layout] Add item distribution actions

Adds actions for distributing selections of items by their
left/center/right/top/bottom edges.

Useful for quickly evenly distributing items in the layout

Needs new icons
This commit is contained in:
Nyall Dawson 2017-10-04 07:49:53 +10:00
parent c5fcc9da69
commit 5141c05ba7
10 changed files with 543 additions and 57 deletions

View File

@ -26,12 +26,22 @@ class QgsLayoutAligner
enum Alignment
{
Left,
HCenter,
Right,
Top,
VCenter,
Bottom,
AlignLeft,
AlignHCenter,
AlignRight,
AlignTop,
AlignVCenter,
AlignBottom,
};
enum Distribution
{
DistributeLeft,
DistributeHCenter,
DistributeRight,
DistributeTop,
DistributeVCenter,
DistributeBottom,
};
static void alignItems( QgsLayout *layout, const QList< QgsLayoutItem * > &items, Alignment alignment );
@ -41,6 +51,13 @@ class QgsLayoutAligner
The ``alignment`` argument specifies the method to use when aligning the items.
%End
static void distributeItems( QgsLayout *layout, const QList< QgsLayoutItem * > &items, Distribution distribution );
%Docstring
Distributes a set of ``items`` from a ``layout`` in place.
The ``distribution`` argument specifies the method to use when distributing the items.
%End
};
/************************************************************************

View File

@ -130,6 +130,13 @@ class QgsLayoutView: QGraphicsView
void alignSelectedItems( QgsLayoutAligner::Alignment alignment );
%Docstring
Aligns all selected items using the specified ``alignment``.
.. seealso:: distributeSelectedItems()
%End
void distributeSelectedItems( QgsLayoutAligner::Distribution distribution );
%Docstring
Distributes all selected items using the specified ``distribution``.
see alignSelectedItems()
%End
public slots:

View File

@ -183,7 +183,6 @@ QgsLayoutDesignerDialog::QgsLayoutDesignerDialog( QWidget *parent, Qt::WindowFla
alignToolButton->setPopupMode( QToolButton::InstantPopup );
alignToolButton->setAutoRaise( true );
alignToolButton->setToolButtonStyle( Qt::ToolButtonIconOnly );
alignToolButton->addAction( mActionAlignLeft );
alignToolButton->addAction( mActionAlignHCenter );
alignToolButton->addAction( mActionAlignRight );
@ -193,6 +192,19 @@ QgsLayoutDesignerDialog::QgsLayoutDesignerDialog( QWidget *parent, Qt::WindowFla
alignToolButton->setDefaultAction( mActionAlignLeft );
mActionsToolbar->addWidget( alignToolButton );
QToolButton *distributeToolButton = new QToolButton( this );
distributeToolButton->setPopupMode( QToolButton::InstantPopup );
distributeToolButton->setAutoRaise( true );
distributeToolButton->setToolButtonStyle( Qt::ToolButtonIconOnly );
distributeToolButton->addAction( mActionDistributeLeft );
distributeToolButton->addAction( mActionDistributeHCenter );
distributeToolButton->addAction( mActionDistributeRight );
distributeToolButton->addAction( mActionDistributeTop );
distributeToolButton->addAction( mActionDistributeVCenter );
distributeToolButton->addAction( mActionDistributeBottom );
distributeToolButton->setDefaultAction( mActionDistributeLeft );
mActionsToolbar->addWidget( distributeToolButton );
mAddItemTool = new QgsLayoutViewToolAddItem( mView );
mPanTool = new QgsLayoutViewToolPan( mView );
mPanTool->setAction( mActionPan );
@ -229,27 +241,51 @@ QgsLayoutDesignerDialog::QgsLayoutDesignerDialog( QWidget *parent, Qt::WindowFla
connect( mActionMoveItemsToBottom, &QAction::triggered, this, &QgsLayoutDesignerDialog::moveSelectedItemsToBottom );
connect( mActionAlignLeft, &QAction::triggered, this, [ = ]
{
mView->alignSelectedItems( QgsLayoutAligner::Left );
mView->alignSelectedItems( QgsLayoutAligner::AlignLeft );
} );
connect( mActionAlignHCenter, &QAction::triggered, this, [ = ]
{
mView->alignSelectedItems( QgsLayoutAligner::HCenter );
mView->alignSelectedItems( QgsLayoutAligner::AlignHCenter );
} );
connect( mActionAlignRight, &QAction::triggered, this, [ = ]
{
mView->alignSelectedItems( QgsLayoutAligner::Right );
mView->alignSelectedItems( QgsLayoutAligner::AlignRight );
} );
connect( mActionAlignTop, &QAction::triggered, this, [ = ]
{
mView->alignSelectedItems( QgsLayoutAligner::Top );
mView->alignSelectedItems( QgsLayoutAligner::AlignTop );
} );
connect( mActionAlignVCenter, &QAction::triggered, this, [ = ]
{
mView->alignSelectedItems( QgsLayoutAligner::VCenter );
mView->alignSelectedItems( QgsLayoutAligner::AlignVCenter );
} );
connect( mActionAlignBottom, &QAction::triggered, this, [ = ]
{
mView->alignSelectedItems( QgsLayoutAligner::Bottom );
mView->alignSelectedItems( QgsLayoutAligner::AlignBottom );
} );
connect( mActionDistributeLeft, &QAction::triggered, this, [ = ]
{
mView->distributeSelectedItems( QgsLayoutAligner::DistributeLeft );
} );
connect( mActionDistributeHCenter, &QAction::triggered, this, [ = ]
{
mView->distributeSelectedItems( QgsLayoutAligner::DistributeHCenter );
} );
connect( mActionDistributeRight, &QAction::triggered, this, [ = ]
{
mView->distributeSelectedItems( QgsLayoutAligner::DistributeRight );
} );
connect( mActionDistributeTop, &QAction::triggered, this, [ = ]
{
mView->distributeSelectedItems( QgsLayoutAligner::DistributeTop );
} );
connect( mActionDistributeVCenter, &QAction::triggered, this, [ = ]
{
mView->distributeSelectedItems( QgsLayoutAligner::DistributeVCenter );
} );
connect( mActionDistributeBottom, &QAction::triggered, this, [ = ]
{
mView->distributeSelectedItems( QgsLayoutAligner::DistributeBottom );
} );
connect( mActionAddPages, &QAction::triggered, this, &QgsLayoutDesignerDialog::addPages );

View File

@ -34,27 +34,27 @@ void QgsLayoutAligner::alignItems( QgsLayout *layout, const QList<QgsLayoutItem
double refCoord = 0;
switch ( alignment )
{
case Left:
case AlignLeft:
refCoord = itemBBox.left();
break;
case HCenter:
case AlignHCenter:
refCoord = itemBBox.center().x();
break;
case Right:
case AlignRight:
refCoord = itemBBox.right();
break;
case Top:
case AlignTop:
refCoord = itemBBox.top();
break;
case VCenter:
case AlignVCenter:
refCoord = itemBBox.center().y();
break;
case Bottom:
case AlignBottom:
refCoord = itemBBox.bottom();
break;
}
layout->undoStack()->beginMacro( QObject::tr( "Aligned items bottom" ) );
layout->undoStack()->beginMacro( undoText( alignment ) );
for ( QgsLayoutItem *item : items )
{
layout->undoStack()->beginCommand( item, QString() );
@ -62,22 +62,22 @@ void QgsLayoutAligner::alignItems( QgsLayout *layout, const QList<QgsLayoutItem
QPointF shifted = item->pos();
switch ( alignment )
{
case Left:
case AlignLeft:
shifted.setX( refCoord );
break;
case HCenter:
case AlignHCenter:
shifted.setX( refCoord - item->rect().width() / 2.0 );
break;
case Right:
case AlignRight:
shifted.setX( refCoord - item->rect().width() );
break;
case Top:
case AlignTop:
shifted.setY( refCoord );
break;
case VCenter:
case AlignVCenter:
shifted.setY( refCoord - item->rect().height() / 2.0 );
break;
case Bottom:
case AlignBottom:
shifted.setY( refCoord - item->rect().height() );
break;
}
@ -91,6 +91,91 @@ void QgsLayoutAligner::alignItems( QgsLayout *layout, const QList<QgsLayoutItem
layout->undoStack()->endMacro();
}
void QgsLayoutAligner::distributeItems( QgsLayout *layout, const QList<QgsLayoutItem *> &items, QgsLayoutAligner::Distribution distribution )
{
if ( items.size() < 2 )
return;
auto collectReferenceCoord = [distribution]( QgsLayoutItem * item )->double
{
QRectF itemBBox = item->sceneBoundingRect();
switch ( distribution )
{
case AlignLeft:
return itemBBox.left();
case AlignHCenter:
return itemBBox.center().x();
case AlignRight:
return itemBBox.right();
case AlignTop:
return itemBBox.top();
case AlignVCenter:
return itemBBox.center().y();
case AlignBottom:
return itemBBox.bottom();
}
// no warnings
return itemBBox.left();
};
double minCoord = DBL_MAX;
double maxCoord = -DBL_MAX;
QMap< double, QgsLayoutItem * > itemCoords;
for ( QgsLayoutItem *item : items )
{
double refCoord = collectReferenceCoord( item );
minCoord = std::min( minCoord, refCoord );
maxCoord = std::max( maxCoord, refCoord );
itemCoords.insert( refCoord, item );
}
double step = ( maxCoord - minCoord ) / ( items.size() - 1 );
auto distributeItemToCoord = [layout, distribution]( QgsLayoutItem * item, double refCoord )
{
QPointF shifted = item->pos();
switch ( distribution )
{
case DistributeLeft:
shifted.setX( refCoord );
break;
case DistributeHCenter:
shifted.setX( refCoord - item->rect().width() / 2.0 );
break;
case DistributeRight:
shifted.setX( refCoord - item->rect().width() );
break;
case DistributeTop:
shifted.setY( refCoord );
break;
case DistributeVCenter:
shifted.setY( refCoord - item->rect().height() / 2.0 );
break;
case DistributeBottom:
shifted.setY( refCoord - item->rect().height() );
break;
}
// need to keep item units
QgsLayoutPoint newPos = layout->convertFromLayoutUnits( shifted, item->positionWithUnits().units() );
item->attemptMove( newPos );
};
layout->undoStack()->beginMacro( undoText( distribution ) );
double currentVal = minCoord;
for ( auto itemIt = itemCoords.constBegin(); itemIt != itemCoords.constEnd(); ++itemIt )
{
layout->undoStack()->beginCommand( itemIt.value(), QString() );
distributeItemToCoord( itemIt.value(), currentVal );
layout->undoStack()->endCommand();
currentVal += step;
}
layout->undoStack()->endMacro();
}
QRectF QgsLayoutAligner::boundingRectOfItems( const QList<QgsLayoutItem *> &items )
{
if ( items.empty() )
@ -129,3 +214,43 @@ QRectF QgsLayoutAligner::boundingRectOfItems( const QList<QgsLayoutItem *> &item
return QRectF( QPointF( minX, minY ), QPointF( maxX, maxY ) );
}
QString QgsLayoutAligner::undoText( Distribution distribution )
{
switch ( distribution )
{
case DistributeLeft:
return QObject::tr( "Distributed items by left" );
case DistributeHCenter:
return QObject::tr( "Distributed items by center" );
case DistributeRight:
return QObject::tr( "Distributed items by right" );
case DistributeTop:
return QObject::tr( "Distributed items by top" );
case DistributeVCenter:
return QObject::tr( "Distributed items by vertical center" );
case DistributeBottom:
return QObject::tr( "Distributed items by bottom" );
}
return QString(); //no warnings
}
QString QgsLayoutAligner::undoText( Alignment alignment )
{
switch ( alignment )
{
case AlignLeft:
return QObject::tr( "Aligned items to left" );
case AlignHCenter:
return QObject::tr( "Aligned items to center" );
case AlignRight:
return QObject::tr( "Aligned items to right" );
case AlignTop:
return QObject::tr( "Aligned items to top" );
case AlignVCenter:
return QObject::tr( "Aligned items to vertical center" );
case AlignBottom:
return QObject::tr( "Aligned items to bottom" );
}
return QString(); //no warnings
}

View File

@ -41,12 +41,23 @@ class CORE_EXPORT QgsLayoutAligner
//! Alignment options
enum Alignment
{
Left, //!< Align left edges
HCenter, //!< Align horizontal centers
Right, //!< Align right edges
Top, //!< Align top edges
VCenter, //!< Align vertical centers
Bottom, //!< Align bottom edges
AlignLeft, //!< Align left edges
AlignHCenter, //!< Align horizontal centers
AlignRight, //!< Align right edges
AlignTop, //!< Align top edges
AlignVCenter, //!< Align vertical centers
AlignBottom, //!< Align bottom edges
};
//! Distribution options
enum Distribution
{
DistributeLeft, //!< Distribute left edges
DistributeHCenter, //!< Distribute horizontal centers
DistributeRight, //!< Distribute right edges
DistributeTop, //!< Distribute top edges
DistributeVCenter, //!< Distribute vertical centers
DistributeBottom, //!< Distribute bottom edges
};
/**
@ -56,6 +67,13 @@ class CORE_EXPORT QgsLayoutAligner
*/
static void alignItems( QgsLayout *layout, const QList< QgsLayoutItem * > &items, Alignment alignment );
/**
* Distributes a set of \a items from a \a layout in place.
*
* The \a distribution argument specifies the method to use when distributing the items.
*/
static void distributeItems( QgsLayout *layout, const QList< QgsLayoutItem * > &items, Distribution distribution );
private:
/**
@ -64,6 +82,9 @@ class CORE_EXPORT QgsLayoutAligner
*/
static QRectF boundingRectOfItems( const QList< QgsLayoutItem * > &items );
static QString undoText( Alignment alignment );
static QString undoText( Distribution distribution );
};

View File

@ -236,6 +236,12 @@ void QgsLayoutView::alignSelectedItems( QgsLayoutAligner::Alignment alignment )
QgsLayoutAligner::alignItems( currentLayout(), selectedItems, alignment );
}
void QgsLayoutView::distributeSelectedItems( QgsLayoutAligner::Distribution distribution )
{
const QList<QgsLayoutItem *> selectedItems = currentLayout()->selectedLayoutItems();
QgsLayoutAligner::distributeItems( currentLayout(), selectedItems, distribution );
}
void QgsLayoutView::zoomFull()
{
fitInView( scene()->sceneRect(), Qt::KeepAspectRatio );

View File

@ -160,9 +160,16 @@ class GUI_EXPORT QgsLayoutView: public QGraphicsView
/**
* Aligns all selected items using the specified \a alignment.
* \see distributeSelectedItems()
*/
void alignSelectedItems( QgsLayoutAligner::Alignment alignment );
/**
* Distributes all selected items using the specified \a distribution.
* see alignSelectedItems()
*/
void distributeSelectedItems( QgsLayoutAligner::Distribution distribution );
public slots:
/**

View File

@ -156,6 +156,30 @@
<property name="title">
<string>Layout</string>
</property>
<widget class="QMenu" name="menuAlign_Items">
<property name="title">
<string>&amp;Align Items</string>
</property>
<addaction name="mActionAlignLeft"/>
<addaction name="mActionAlignHCenter"/>
<addaction name="mActionAlignRight"/>
<addaction name="separator"/>
<addaction name="mActionAlignBottom"/>
<addaction name="mActionAlignVCenter"/>
<addaction name="mActionAlignTop"/>
</widget>
<widget class="QMenu" name="menu_Distribute_Items">
<property name="title">
<string>&amp;Distribute Items</string>
</property>
<addaction name="mActionDistributeLeft"/>
<addaction name="mActionDistributeHCenter"/>
<addaction name="mActionDistributeRight"/>
<addaction name="separator"/>
<addaction name="mActionDistributeTop"/>
<addaction name="mActionDistributeVCenter"/>
<addaction name="mActionDistributeBottom"/>
</widget>
<addaction name="mActionRaiseItems"/>
<addaction name="mActionLowerItems"/>
<addaction name="mActionMoveItemsToTop"/>
@ -164,12 +188,8 @@
<addaction name="mActionLockItems"/>
<addaction name="mActionUnlockAll"/>
<addaction name="separator"/>
<addaction name="mActionAlignLeft"/>
<addaction name="mActionAlignHCenter"/>
<addaction name="mActionAlignRight"/>
<addaction name="mActionAlignTop"/>
<addaction name="mActionAlignVCenter"/>
<addaction name="mActionAlignBottom"/>
<addaction name="menuAlign_Items"/>
<addaction name="menu_Distribute_Items"/>
</widget>
<addaction name="mLayoutMenu"/>
<addaction name="menuEdit"/>
@ -677,7 +697,7 @@
<normaloff>:/images/themes/default/mActionAlignLeft.svg</normaloff>:/images/themes/default/mActionAlignLeft.svg</iconset>
</property>
<property name="text">
<string>Align Left</string>
<string>Align &amp;Left</string>
</property>
<property name="toolTip">
<string>Align selected items left</string>
@ -689,7 +709,7 @@
<normaloff>:/images/themes/default/mActionAlignHCenter.svg</normaloff>:/images/themes/default/mActionAlignHCenter.svg</iconset>
</property>
<property name="text">
<string>Align Center</string>
<string>Align &amp;Center</string>
</property>
<property name="toolTip">
<string>Align center horizontal</string>
@ -701,7 +721,7 @@
<normaloff>:/images/themes/default/mActionAlignRight.svg</normaloff>:/images/themes/default/mActionAlignRight.svg</iconset>
</property>
<property name="text">
<string>Align Right</string>
<string>Align &amp;Right</string>
</property>
<property name="toolTip">
<string>Align selected items right</string>
@ -713,7 +733,7 @@
<normaloff>:/images/themes/default/mActionAlignTop.svg</normaloff>:/images/themes/default/mActionAlignTop.svg</iconset>
</property>
<property name="text">
<string>Align Top</string>
<string>Align &amp;Top</string>
</property>
<property name="toolTip">
<string>Align selected items to top</string>
@ -725,7 +745,7 @@
<normaloff>:/images/themes/default/mActionAlignVCenter.svg</normaloff>:/images/themes/default/mActionAlignVCenter.svg</iconset>
</property>
<property name="text">
<string>Align Center Vertical</string>
<string>Align Center &amp;Vertical</string>
</property>
<property name="toolTip">
<string>Align center vertical</string>
@ -737,12 +757,84 @@
<normaloff>:/images/themes/default/mActionAlignBottom.svg</normaloff>:/images/themes/default/mActionAlignBottom.svg</iconset>
</property>
<property name="text">
<string>Align Bottom</string>
<string>Align &amp;Bottom</string>
</property>
<property name="toolTip">
<string>Align selected items bottom</string>
</property>
</action>
<action name="mActionDistributeLeft">
<property name="icon">
<iconset resource="../../../images/images.qrc">
<normaloff>:/images/themes/default/mActionAlignLeft.svg</normaloff>:/images/themes/default/mActionAlignLeft.svg</iconset>
</property>
<property name="text">
<string>Distribute &amp;Left Edges</string>
</property>
<property name="toolTip">
<string>Distributes left edges of items equidistantly</string>
</property>
</action>
<action name="mActionDistributeHCenter">
<property name="icon">
<iconset resource="../../../images/images.qrc">
<normaloff>:/images/themes/default/mActionAlignHCenter.svg</normaloff>:/images/themes/default/mActionAlignHCenter.svg</iconset>
</property>
<property name="text">
<string>Distribute &amp;Centers</string>
</property>
<property name="toolTip">
<string>Distributes horizontal centers of items equidistantly</string>
</property>
</action>
<action name="mActionDistributeRight">
<property name="icon">
<iconset resource="../../../images/images.qrc">
<normaloff>:/images/themes/default/mActionAlignRight.svg</normaloff>:/images/themes/default/mActionAlignRight.svg</iconset>
</property>
<property name="text">
<string>Distribute &amp;Right Edges</string>
</property>
<property name="toolTip">
<string>Distributes right edges of items equidistantly</string>
</property>
</action>
<action name="mActionDistributeTop">
<property name="icon">
<iconset resource="../../../images/images.qrc">
<normaloff>:/images/themes/default/mActionAlignTop.svg</normaloff>:/images/themes/default/mActionAlignTop.svg</iconset>
</property>
<property name="text">
<string>Distribute &amp;Top Edges</string>
</property>
<property name="toolTip">
<string>Distributes top edges of items equidistantly</string>
</property>
</action>
<action name="mActionDistributeVCenter">
<property name="icon">
<iconset resource="../../../images/images.qrc">
<normaloff>:/images/themes/default/mActionAlignVCenter.svg</normaloff>:/images/themes/default/mActionAlignVCenter.svg</iconset>
</property>
<property name="text">
<string>Distribute &amp;Vertical Centers</string>
</property>
<property name="toolTip">
<string>Distributes vertical centers of items equidistantly</string>
</property>
</action>
<action name="mActionDistributeBottom">
<property name="icon">
<iconset resource="../../../images/images.qrc">
<normaloff>:/images/themes/default/mActionAlignBottom.svg</normaloff>:/images/themes/default/mActionAlignBottom.svg</iconset>
</property>
<property name="text">
<string>Distribute &amp;Bottom Edges</string>
</property>
<property name="toolTip">
<string>Distributes bottom edges of items equidistantly</string>
</property>
</action>
</widget>
<resources>
<include location="../../../images/images.qrc"/>

View File

@ -57,7 +57,7 @@ class TestQgsLayoutAligner(unittest.TestCase):
item3.attemptResize(QgsLayoutSize(1.8, 1.6, QgsUnitTypes.LayoutCentimeters))
l.addItem(item3)
QgsLayoutAligner.alignItems(l, [item1, item2, item3], QgsLayoutAligner.Left)
QgsLayoutAligner.alignItems(l, [item1, item2, item3], QgsLayoutAligner.AlignLeft)
self.assertEqual(item1.positionWithUnits(), QgsLayoutPoint(4, 8, QgsUnitTypes.LayoutMillimeters))
self.assertEqual(item1.sizeWithUnits(), QgsLayoutSize(18, 12, QgsUnitTypes.LayoutMillimeters))
self.assertEqual(item2.positionWithUnits(), QgsLayoutPoint(4, 10, QgsUnitTypes.LayoutMillimeters))
@ -65,7 +65,7 @@ class TestQgsLayoutAligner(unittest.TestCase):
self.assertEqual(item3.positionWithUnits(), QgsLayoutPoint(0.4, 1.2, QgsUnitTypes.LayoutCentimeters))
self.assertEqual(item3.sizeWithUnits(), QgsLayoutSize(1.8, 1.6, QgsUnitTypes.LayoutCentimeters))
QgsLayoutAligner.alignItems(l, [item1, item2, item3], QgsLayoutAligner.HCenter)
QgsLayoutAligner.alignItems(l, [item1, item2, item3], QgsLayoutAligner.AlignHCenter)
self.assertEqual(item1.positionWithUnits(), QgsLayoutPoint(4, 8, QgsUnitTypes.LayoutMillimeters))
self.assertEqual(item1.sizeWithUnits(), QgsLayoutSize(18, 12, QgsUnitTypes.LayoutMillimeters))
self.assertEqual(item2.positionWithUnits(), QgsLayoutPoint(8, 10, QgsUnitTypes.LayoutMillimeters))
@ -73,7 +73,7 @@ class TestQgsLayoutAligner(unittest.TestCase):
self.assertEqual(item3.positionWithUnits(), QgsLayoutPoint(0.4, 1.2, QgsUnitTypes.LayoutCentimeters))
self.assertEqual(item3.sizeWithUnits(), QgsLayoutSize(1.8, 1.6, QgsUnitTypes.LayoutCentimeters))
QgsLayoutAligner.alignItems(l, [item1, item2, item3], QgsLayoutAligner.Right)
QgsLayoutAligner.alignItems(l, [item1, item2, item3], QgsLayoutAligner.AlignRight)
self.assertEqual(item1.positionWithUnits(), QgsLayoutPoint(4, 8, QgsUnitTypes.LayoutMillimeters))
self.assertEqual(item1.sizeWithUnits(), QgsLayoutSize(18, 12, QgsUnitTypes.LayoutMillimeters))
self.assertEqual(item2.positionWithUnits(), QgsLayoutPoint(12, 10, QgsUnitTypes.LayoutMillimeters))
@ -81,7 +81,7 @@ class TestQgsLayoutAligner(unittest.TestCase):
self.assertEqual(item3.positionWithUnits(), QgsLayoutPoint(0.4, 1.2, QgsUnitTypes.LayoutCentimeters))
self.assertEqual(item3.sizeWithUnits(), QgsLayoutSize(1.8, 1.6, QgsUnitTypes.LayoutCentimeters))
QgsLayoutAligner.alignItems(l, [item1, item2, item3], QgsLayoutAligner.Top)
QgsLayoutAligner.alignItems(l, [item1, item2, item3], QgsLayoutAligner.AlignTop)
self.assertEqual(item1.positionWithUnits(), QgsLayoutPoint(4, 8, QgsUnitTypes.LayoutMillimeters))
self.assertEqual(item1.sizeWithUnits(), QgsLayoutSize(18, 12, QgsUnitTypes.LayoutMillimeters))
self.assertEqual(item2.positionWithUnits(), QgsLayoutPoint(12, 8, QgsUnitTypes.LayoutMillimeters))
@ -89,7 +89,7 @@ class TestQgsLayoutAligner(unittest.TestCase):
self.assertEqual(item3.positionWithUnits(), QgsLayoutPoint(0.4, 0.8, QgsUnitTypes.LayoutCentimeters))
self.assertEqual(item3.sizeWithUnits(), QgsLayoutSize(1.8, 1.6, QgsUnitTypes.LayoutCentimeters))
QgsLayoutAligner.alignItems(l, [item1, item2, item3], QgsLayoutAligner.VCenter)
QgsLayoutAligner.alignItems(l, [item1, item2, item3], QgsLayoutAligner.AlignVCenter)
self.assertEqual(item1.positionWithUnits(), QgsLayoutPoint(4, 10, QgsUnitTypes.LayoutMillimeters))
self.assertEqual(item1.sizeWithUnits(), QgsLayoutSize(18, 12, QgsUnitTypes.LayoutMillimeters))
self.assertEqual(item2.positionWithUnits(), QgsLayoutPoint(12, 11.5, QgsUnitTypes.LayoutMillimeters))
@ -97,7 +97,7 @@ class TestQgsLayoutAligner(unittest.TestCase):
self.assertEqual(item3.positionWithUnits(), QgsLayoutPoint(0.4, 0.8, QgsUnitTypes.LayoutCentimeters))
self.assertEqual(item3.sizeWithUnits(), QgsLayoutSize(1.8, 1.6, QgsUnitTypes.LayoutCentimeters))
QgsLayoutAligner.alignItems(l, [item1, item2, item3], QgsLayoutAligner.Bottom)
QgsLayoutAligner.alignItems(l, [item1, item2, item3], QgsLayoutAligner.AlignBottom)
self.assertEqual(item1.positionWithUnits(), QgsLayoutPoint(4, 12, QgsUnitTypes.LayoutMillimeters))
self.assertEqual(item1.sizeWithUnits(), QgsLayoutSize(18, 12, QgsUnitTypes.LayoutMillimeters))
self.assertEqual(item2.positionWithUnits(), QgsLayoutPoint(12, 15, QgsUnitTypes.LayoutMillimeters))
@ -105,6 +105,89 @@ class TestQgsLayoutAligner(unittest.TestCase):
self.assertEqual(item3.positionWithUnits(), QgsLayoutPoint(0.4, 0.8, QgsUnitTypes.LayoutCentimeters))
self.assertEqual(item3.sizeWithUnits(), QgsLayoutSize(1.8, 1.6, QgsUnitTypes.LayoutCentimeters))
def testDistribute(self):
p = QgsProject()
l = QgsLayout(p)
# add some items
item1 = QgsLayoutItemMap(l)
item1.attemptMove(QgsLayoutPoint(4, 8, QgsUnitTypes.LayoutMillimeters))
item1.attemptResize(QgsLayoutSize(18, 12, QgsUnitTypes.LayoutMillimeters))
l.addItem(item1)
item2 = QgsLayoutItemMap(l)
item2.attemptMove(QgsLayoutPoint(7, 10, QgsUnitTypes.LayoutMillimeters))
item2.attemptResize(QgsLayoutSize(10, 9, QgsUnitTypes.LayoutMillimeters))
l.addItem(item2)
item3 = QgsLayoutItemMap(l)
item3.attemptMove(QgsLayoutPoint(0.8, 1.2, QgsUnitTypes.LayoutCentimeters))
item3.attemptResize(QgsLayoutSize(1.8, 1.6, QgsUnitTypes.LayoutCentimeters))
l.addItem(item3)
QgsLayoutAligner.distributeItems(l, [item1, item2, item3], QgsLayoutAligner.DistributeLeft)
self.assertEqual(item1.positionWithUnits(), QgsLayoutPoint(4, 8, QgsUnitTypes.LayoutMillimeters))
self.assertEqual(item1.sizeWithUnits(), QgsLayoutSize(18, 12, QgsUnitTypes.LayoutMillimeters))
self.assertAlmostEqual(item2.positionWithUnits().x(), 6.0, 3)
self.assertEqual(item2.positionWithUnits().units(), QgsUnitTypes.LayoutMillimeters)
self.assertEqual(item2.sizeWithUnits(), QgsLayoutSize(10, 9, QgsUnitTypes.LayoutMillimeters))
self.assertAlmostEqual(item3.positionWithUnits().x(), 0.8, 3)
self.assertEqual(item3.positionWithUnits().units(), QgsUnitTypes.LayoutCentimeters)
self.assertEqual(item3.sizeWithUnits(), QgsLayoutSize(1.8, 1.6, QgsUnitTypes.LayoutCentimeters))
QgsLayoutAligner.distributeItems(l, [item1, item2, item3], QgsLayoutAligner.DistributeHCenter)
self.assertAlmostEqual(item1.positionWithUnits().x(), 5.0, 3)
self.assertEqual(item1.positionWithUnits().units(), QgsUnitTypes.LayoutMillimeters)
self.assertEqual(item1.sizeWithUnits(), QgsLayoutSize(18, 12, QgsUnitTypes.LayoutMillimeters))
self.assertAlmostEqual(item2.positionWithUnits().x(), 6.0, 3)
self.assertEqual(item2.positionWithUnits().units(), QgsUnitTypes.LayoutMillimeters)
self.assertEqual(item2.sizeWithUnits(), QgsLayoutSize(10, 9, QgsUnitTypes.LayoutMillimeters))
self.assertAlmostEqual(item3.positionWithUnits().x(), 0.8, 3)
self.assertEqual(item3.positionWithUnits().units(), QgsUnitTypes.LayoutCentimeters)
self.assertEqual(item3.sizeWithUnits(), QgsLayoutSize(1.8, 1.6, QgsUnitTypes.LayoutCentimeters))
QgsLayoutAligner.distributeItems(l, [item1, item2, item3], QgsLayoutAligner.DistributeRight)
self.assertAlmostEqual(item1.positionWithUnits().x(), 3.0, 3)
self.assertEqual(item1.positionWithUnits().units(), QgsUnitTypes.LayoutMillimeters)
self.assertEqual(item1.sizeWithUnits(), QgsLayoutSize(18, 12, QgsUnitTypes.LayoutMillimeters))
self.assertAlmostEqual(item2.positionWithUnits().x(), 6.0, 3)
self.assertEqual(item2.positionWithUnits().units(), QgsUnitTypes.LayoutMillimeters)
self.assertEqual(item2.sizeWithUnits(), QgsLayoutSize(10, 9, QgsUnitTypes.LayoutMillimeters))
self.assertAlmostEqual(item3.positionWithUnits().x(), 0.8, 3)
self.assertEqual(item3.positionWithUnits().units(), QgsUnitTypes.LayoutCentimeters)
self.assertEqual(item3.sizeWithUnits(), QgsLayoutSize(1.8, 1.6, QgsUnitTypes.LayoutCentimeters))
QgsLayoutAligner.distributeItems(l, [item1, item2, item3], QgsLayoutAligner.DistributeTop)
self.assertAlmostEqual(item1.positionWithUnits().y(), 8.0, 3)
self.assertEqual(item1.positionWithUnits().units(), QgsUnitTypes.LayoutMillimeters)
self.assertEqual(item1.sizeWithUnits(), QgsLayoutSize(18, 12, QgsUnitTypes.LayoutMillimeters))
self.assertAlmostEqual(item2.positionWithUnits().y(), 10.0, 3)
self.assertEqual(item2.positionWithUnits().units(), QgsUnitTypes.LayoutMillimeters)
self.assertEqual(item2.sizeWithUnits(), QgsLayoutSize(10, 9, QgsUnitTypes.LayoutMillimeters))
self.assertAlmostEqual(item3.positionWithUnits().y(), 1.2, 3)
self.assertEqual(item3.positionWithUnits().units(), QgsUnitTypes.LayoutCentimeters)
self.assertEqual(item3.sizeWithUnits(), QgsLayoutSize(1.8, 1.6, QgsUnitTypes.LayoutCentimeters))
QgsLayoutAligner.distributeItems(l, [item1, item2, item3], QgsLayoutAligner.DistributeVCenter)
self.assertAlmostEqual(item1.positionWithUnits().y(), 8.0, 3)
self.assertEqual(item1.positionWithUnits().units(), QgsUnitTypes.LayoutMillimeters)
self.assertEqual(item1.sizeWithUnits(), QgsLayoutSize(18, 12, QgsUnitTypes.LayoutMillimeters))
self.assertAlmostEqual(item2.positionWithUnits().y(), 12.5, 3)
self.assertEqual(item2.positionWithUnits().units(), QgsUnitTypes.LayoutMillimeters)
self.assertEqual(item2.sizeWithUnits(), QgsLayoutSize(10, 9, QgsUnitTypes.LayoutMillimeters))
self.assertAlmostEqual(item3.positionWithUnits().y(), 1.2, 3)
self.assertEqual(item3.positionWithUnits().units(), QgsUnitTypes.LayoutCentimeters)
self.assertEqual(item3.sizeWithUnits(), QgsLayoutSize(1.8, 1.6, QgsUnitTypes.LayoutCentimeters))
QgsLayoutAligner.distributeItems(l, [item1, item2, item3], QgsLayoutAligner.DistributeBottom)
self.assertAlmostEqual(item1.positionWithUnits().y(), 8.0, 3)
self.assertEqual(item1.positionWithUnits().units(), QgsUnitTypes.LayoutMillimeters)
self.assertEqual(item1.sizeWithUnits(), QgsLayoutSize(18, 12, QgsUnitTypes.LayoutMillimeters))
self.assertAlmostEqual(item2.positionWithUnits().y(), 15.0, 3)
self.assertEqual(item2.positionWithUnits().units(), QgsUnitTypes.LayoutMillimeters)
self.assertEqual(item2.sizeWithUnits(), QgsLayoutSize(10, 9, QgsUnitTypes.LayoutMillimeters))
self.assertAlmostEqual(item3.positionWithUnits().y(), 1.2, 3)
self.assertEqual(item3.positionWithUnits().units(), QgsUnitTypes.LayoutCentimeters)
self.assertEqual(item3.sizeWithUnits(), QgsLayoutSize(1.8, 1.6, QgsUnitTypes.LayoutCentimeters))
if __name__ == '__main__':
unittest.main()

View File

@ -431,13 +431,13 @@ class TestQgsLayoutView(unittest.TestCase):
view = QgsLayoutView()
view.setCurrentLayout(l)
view.alignSelectedItems(QgsLayoutAligner.Left)
view.alignSelectedItems(QgsLayoutAligner.AlignLeft)
item1.setSelected(True)
item2.setSelected(True)
item3.setSelected(True)
view.alignSelectedItems(QgsLayoutAligner.Left)
view.alignSelectedItems(QgsLayoutAligner.AlignLeft)
self.assertEqual(item1.positionWithUnits(), QgsLayoutPoint(4, 8, QgsUnitTypes.LayoutMillimeters))
self.assertEqual(item1.sizeWithUnits(), QgsLayoutSize(18, 12, QgsUnitTypes.LayoutMillimeters))
self.assertEqual(item2.positionWithUnits(), QgsLayoutPoint(4, 10, QgsUnitTypes.LayoutMillimeters))
@ -445,7 +445,7 @@ class TestQgsLayoutView(unittest.TestCase):
self.assertEqual(item3.positionWithUnits(), QgsLayoutPoint(0.4, 1.2, QgsUnitTypes.LayoutCentimeters))
self.assertEqual(item3.sizeWithUnits(), QgsLayoutSize(1.8, 1.6, QgsUnitTypes.LayoutCentimeters))
view.alignSelectedItems(QgsLayoutAligner.HCenter)
view.alignSelectedItems(QgsLayoutAligner.AlignHCenter)
self.assertEqual(item1.positionWithUnits(), QgsLayoutPoint(4, 8, QgsUnitTypes.LayoutMillimeters))
self.assertEqual(item1.sizeWithUnits(), QgsLayoutSize(18, 12, QgsUnitTypes.LayoutMillimeters))
self.assertEqual(item2.positionWithUnits(), QgsLayoutPoint(8, 10, QgsUnitTypes.LayoutMillimeters))
@ -453,7 +453,7 @@ class TestQgsLayoutView(unittest.TestCase):
self.assertEqual(item3.positionWithUnits(), QgsLayoutPoint(0.4, 1.2, QgsUnitTypes.LayoutCentimeters))
self.assertEqual(item3.sizeWithUnits(), QgsLayoutSize(1.8, 1.6, QgsUnitTypes.LayoutCentimeters))
view.alignSelectedItems(QgsLayoutAligner.Right)
view.alignSelectedItems(QgsLayoutAligner.AlignRight)
self.assertEqual(item1.positionWithUnits(), QgsLayoutPoint(4, 8, QgsUnitTypes.LayoutMillimeters))
self.assertEqual(item1.sizeWithUnits(), QgsLayoutSize(18, 12, QgsUnitTypes.LayoutMillimeters))
self.assertEqual(item2.positionWithUnits(), QgsLayoutPoint(12, 10, QgsUnitTypes.LayoutMillimeters))
@ -461,7 +461,7 @@ class TestQgsLayoutView(unittest.TestCase):
self.assertEqual(item3.positionWithUnits(), QgsLayoutPoint(0.4, 1.2, QgsUnitTypes.LayoutCentimeters))
self.assertEqual(item3.sizeWithUnits(), QgsLayoutSize(1.8, 1.6, QgsUnitTypes.LayoutCentimeters))
view.alignSelectedItems(QgsLayoutAligner.Top)
view.alignSelectedItems(QgsLayoutAligner.AlignTop)
self.assertEqual(item1.positionWithUnits(), QgsLayoutPoint(4, 8, QgsUnitTypes.LayoutMillimeters))
self.assertEqual(item1.sizeWithUnits(), QgsLayoutSize(18, 12, QgsUnitTypes.LayoutMillimeters))
self.assertEqual(item2.positionWithUnits(), QgsLayoutPoint(12, 8, QgsUnitTypes.LayoutMillimeters))
@ -469,7 +469,7 @@ class TestQgsLayoutView(unittest.TestCase):
self.assertEqual(item3.positionWithUnits(), QgsLayoutPoint(0.4, 0.8, QgsUnitTypes.LayoutCentimeters))
self.assertEqual(item3.sizeWithUnits(), QgsLayoutSize(1.8, 1.6, QgsUnitTypes.LayoutCentimeters))
view.alignSelectedItems(QgsLayoutAligner.VCenter)
view.alignSelectedItems(QgsLayoutAligner.AlignVCenter)
self.assertEqual(item1.positionWithUnits(), QgsLayoutPoint(4, 10, QgsUnitTypes.LayoutMillimeters))
self.assertEqual(item1.sizeWithUnits(), QgsLayoutSize(18, 12, QgsUnitTypes.LayoutMillimeters))
self.assertEqual(item2.positionWithUnits(), QgsLayoutPoint(12, 11.5, QgsUnitTypes.LayoutMillimeters))
@ -477,7 +477,7 @@ class TestQgsLayoutView(unittest.TestCase):
self.assertEqual(item3.positionWithUnits(), QgsLayoutPoint(0.4, 0.8, QgsUnitTypes.LayoutCentimeters))
self.assertEqual(item3.sizeWithUnits(), QgsLayoutSize(1.8, 1.6, QgsUnitTypes.LayoutCentimeters))
view.alignSelectedItems(QgsLayoutAligner.Bottom)
view.alignSelectedItems(QgsLayoutAligner.AlignBottom)
self.assertEqual(item1.positionWithUnits(), QgsLayoutPoint(4, 12, QgsUnitTypes.LayoutMillimeters))
self.assertEqual(item1.sizeWithUnits(), QgsLayoutSize(18, 12, QgsUnitTypes.LayoutMillimeters))
self.assertEqual(item2.positionWithUnits(), QgsLayoutPoint(12, 15, QgsUnitTypes.LayoutMillimeters))
@ -485,6 +485,98 @@ class TestQgsLayoutView(unittest.TestCase):
self.assertEqual(item3.positionWithUnits(), QgsLayoutPoint(0.4, 0.8, QgsUnitTypes.LayoutCentimeters))
self.assertEqual(item3.sizeWithUnits(), QgsLayoutSize(1.8, 1.6, QgsUnitTypes.LayoutCentimeters))
def testDistribute(self):
p = QgsProject()
l = QgsLayout(p)
# add some items
item1 = QgsLayoutItemMap(l)
item1.attemptMove(QgsLayoutPoint(4, 8, QgsUnitTypes.LayoutMillimeters))
item1.attemptResize(QgsLayoutSize(18, 12, QgsUnitTypes.LayoutMillimeters))
l.addItem(item1)
item2 = QgsLayoutItemMap(l)
item2.attemptMove(QgsLayoutPoint(7, 10, QgsUnitTypes.LayoutMillimeters))
item2.attemptResize(QgsLayoutSize(10, 9, QgsUnitTypes.LayoutMillimeters))
l.addItem(item2)
item3 = QgsLayoutItemMap(l)
item3.attemptMove(QgsLayoutPoint(0.8, 1.2, QgsUnitTypes.LayoutCentimeters))
item3.attemptResize(QgsLayoutSize(1.8, 1.6, QgsUnitTypes.LayoutCentimeters))
l.addItem(item3)
view = QgsLayoutView()
view.setCurrentLayout(l)
view.distributeSelectedItems(QgsLayoutAligner.DistributeLeft)
item1.setSelected(True)
item2.setSelected(True)
item3.setSelected(True)
view.distributeSelectedItems(QgsLayoutAligner.DistributeLeft)
self.assertEqual(item1.positionWithUnits(), QgsLayoutPoint(4, 8, QgsUnitTypes.LayoutMillimeters))
self.assertEqual(item1.sizeWithUnits(), QgsLayoutSize(18, 12, QgsUnitTypes.LayoutMillimeters))
self.assertAlmostEqual(item2.positionWithUnits().x(), 6.0, 3)
self.assertEqual(item2.positionWithUnits().units(), QgsUnitTypes.LayoutMillimeters)
self.assertEqual(item2.sizeWithUnits(), QgsLayoutSize(10, 9, QgsUnitTypes.LayoutMillimeters))
self.assertAlmostEqual(item3.positionWithUnits().x(), 0.8, 3)
self.assertEqual(item3.positionWithUnits().units(), QgsUnitTypes.LayoutCentimeters)
self.assertEqual(item3.sizeWithUnits(), QgsLayoutSize(1.8, 1.6, QgsUnitTypes.LayoutCentimeters))
view.distributeSelectedItems(QgsLayoutAligner.DistributeHCenter)
self.assertAlmostEqual(item1.positionWithUnits().x(), 5.0, 3)
self.assertEqual(item1.positionWithUnits().units(), QgsUnitTypes.LayoutMillimeters)
self.assertEqual(item1.sizeWithUnits(), QgsLayoutSize(18, 12, QgsUnitTypes.LayoutMillimeters))
self.assertAlmostEqual(item2.positionWithUnits().x(), 6.0, 3)
self.assertEqual(item2.positionWithUnits().units(), QgsUnitTypes.LayoutMillimeters)
self.assertEqual(item2.sizeWithUnits(), QgsLayoutSize(10, 9, QgsUnitTypes.LayoutMillimeters))
self.assertAlmostEqual(item3.positionWithUnits().x(), 0.8, 3)
self.assertEqual(item3.positionWithUnits().units(), QgsUnitTypes.LayoutCentimeters)
self.assertEqual(item3.sizeWithUnits(), QgsLayoutSize(1.8, 1.6, QgsUnitTypes.LayoutCentimeters))
view.distributeSelectedItems(QgsLayoutAligner.DistributeRight)
self.assertAlmostEqual(item1.positionWithUnits().x(), 3.0, 3)
self.assertEqual(item1.positionWithUnits().units(), QgsUnitTypes.LayoutMillimeters)
self.assertEqual(item1.sizeWithUnits(), QgsLayoutSize(18, 12, QgsUnitTypes.LayoutMillimeters))
self.assertAlmostEqual(item2.positionWithUnits().x(), 6.0, 3)
self.assertEqual(item2.positionWithUnits().units(), QgsUnitTypes.LayoutMillimeters)
self.assertEqual(item2.sizeWithUnits(), QgsLayoutSize(10, 9, QgsUnitTypes.LayoutMillimeters))
self.assertAlmostEqual(item3.positionWithUnits().x(), 0.8, 3)
self.assertEqual(item3.positionWithUnits().units(), QgsUnitTypes.LayoutCentimeters)
self.assertEqual(item3.sizeWithUnits(), QgsLayoutSize(1.8, 1.6, QgsUnitTypes.LayoutCentimeters))
view.distributeSelectedItems(QgsLayoutAligner.DistributeTop)
self.assertAlmostEqual(item1.positionWithUnits().y(), 8.0, 3)
self.assertEqual(item1.positionWithUnits().units(), QgsUnitTypes.LayoutMillimeters)
self.assertEqual(item1.sizeWithUnits(), QgsLayoutSize(18, 12, QgsUnitTypes.LayoutMillimeters))
self.assertAlmostEqual(item2.positionWithUnits().y(), 10.0, 3)
self.assertEqual(item2.positionWithUnits().units(), QgsUnitTypes.LayoutMillimeters)
self.assertEqual(item2.sizeWithUnits(), QgsLayoutSize(10, 9, QgsUnitTypes.LayoutMillimeters))
self.assertAlmostEqual(item3.positionWithUnits().y(), 1.2, 3)
self.assertEqual(item3.positionWithUnits().units(), QgsUnitTypes.LayoutCentimeters)
self.assertEqual(item3.sizeWithUnits(), QgsLayoutSize(1.8, 1.6, QgsUnitTypes.LayoutCentimeters))
view.distributeSelectedItems(QgsLayoutAligner.DistributeVCenter)
self.assertAlmostEqual(item1.positionWithUnits().y(), 8.0, 3)
self.assertEqual(item1.positionWithUnits().units(), QgsUnitTypes.LayoutMillimeters)
self.assertEqual(item1.sizeWithUnits(), QgsLayoutSize(18, 12, QgsUnitTypes.LayoutMillimeters))
self.assertAlmostEqual(item2.positionWithUnits().y(), 12.5, 3)
self.assertEqual(item2.positionWithUnits().units(), QgsUnitTypes.LayoutMillimeters)
self.assertEqual(item2.sizeWithUnits(), QgsLayoutSize(10, 9, QgsUnitTypes.LayoutMillimeters))
self.assertAlmostEqual(item3.positionWithUnits().y(), 1.2, 3)
self.assertEqual(item3.positionWithUnits().units(), QgsUnitTypes.LayoutCentimeters)
self.assertEqual(item3.sizeWithUnits(), QgsLayoutSize(1.8, 1.6, QgsUnitTypes.LayoutCentimeters))
view.distributeSelectedItems(QgsLayoutAligner.DistributeBottom)
self.assertAlmostEqual(item1.positionWithUnits().y(), 8.0, 3)
self.assertEqual(item1.positionWithUnits().units(), QgsUnitTypes.LayoutMillimeters)
self.assertEqual(item1.sizeWithUnits(), QgsLayoutSize(18, 12, QgsUnitTypes.LayoutMillimeters))
self.assertAlmostEqual(item2.positionWithUnits().y(), 15.0, 3)
self.assertEqual(item2.positionWithUnits().units(), QgsUnitTypes.LayoutMillimeters)
self.assertEqual(item2.sizeWithUnits(), QgsLayoutSize(10, 9, QgsUnitTypes.LayoutMillimeters))
self.assertAlmostEqual(item3.positionWithUnits().y(), 1.2, 3)
self.assertEqual(item3.positionWithUnits().units(), QgsUnitTypes.LayoutCentimeters)
self.assertEqual(item3.sizeWithUnits(), QgsLayoutSize(1.8, 1.6, QgsUnitTypes.LayoutCentimeters))
if __name__ == '__main__':
unittest.main()