mirror of
https://github.com/qgis/QGIS.git
synced 2025-02-26 00:02:08 -05:00
Port item alignment to layouts
This commit is contained in:
parent
c6da276783
commit
0939333273
@ -157,6 +157,7 @@
|
||||
%Include composer/qgscomposermultiframecommand.sip
|
||||
%Include composer/qgscomposertexttable.sip
|
||||
%Include composer/qgspaperitem.sip
|
||||
%Include layout/qgslayoutaligner.sip
|
||||
%Include layout/qgslayoutcontext.sip
|
||||
%Include layout/qgslayoutgridsettings.sip
|
||||
%Include layout/qgslayoutmeasurement.sip
|
||||
|
52
python/core/layout/qgslayoutaligner.sip
Normal file
52
python/core/layout/qgslayoutaligner.sip
Normal file
@ -0,0 +1,52 @@
|
||||
/************************************************************************
|
||||
* This file has been generated automatically from *
|
||||
* *
|
||||
* src/core/layout/qgslayoutaligner.h *
|
||||
* *
|
||||
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
|
||||
************************************************************************/
|
||||
|
||||
|
||||
|
||||
class QgsLayoutAligner
|
||||
{
|
||||
%Docstring
|
||||
Handles aligning and distributing sets of layout items.
|
||||
|
||||
QgsLayoutAligner contains methods for automatically aligning and distributing
|
||||
sets of layout items, e.g. aligning a group of items to top or left sides.
|
||||
|
||||
.. versionadded:: 3.0
|
||||
%End
|
||||
|
||||
%TypeHeaderCode
|
||||
#include "qgslayoutaligner.h"
|
||||
%End
|
||||
public:
|
||||
|
||||
enum Alignment
|
||||
{
|
||||
Left,
|
||||
HCenter,
|
||||
Right,
|
||||
Top,
|
||||
VCenter,
|
||||
Bottom,
|
||||
};
|
||||
|
||||
static void alignItems( QgsLayout *layout, const QList< QgsLayoutItem * > &items, Alignment alignment );
|
||||
%Docstring
|
||||
Aligns a set of ``items`` from a ``layout`` in place.
|
||||
|
||||
The ``alignment`` argument specifies the method to use when aligning the items.
|
||||
%End
|
||||
|
||||
};
|
||||
|
||||
/************************************************************************
|
||||
* This file has been generated automatically from *
|
||||
* *
|
||||
* src/core/layout/qgslayoutaligner.h *
|
||||
* *
|
||||
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
|
||||
************************************************************************/
|
@ -127,6 +127,11 @@ class QgsLayoutView: QGraphicsView
|
||||
:rtype: list of int
|
||||
%End
|
||||
|
||||
void alignSelectedItems( QgsLayoutAligner::Alignment alignment );
|
||||
%Docstring
|
||||
Aligns all selected items using the specified ``alignment``.
|
||||
%End
|
||||
|
||||
public slots:
|
||||
|
||||
void zoomFull();
|
||||
|
@ -179,6 +179,20 @@ QgsLayoutDesignerDialog::QgsLayoutDesignerDialog( QWidget *parent, Qt::WindowFla
|
||||
orderingToolButton->setDefaultAction( mActionRaiseItems );
|
||||
mActionsToolbar->addWidget( orderingToolButton );
|
||||
|
||||
QToolButton *alignToolButton = new QToolButton( this );
|
||||
alignToolButton->setPopupMode( QToolButton::InstantPopup );
|
||||
alignToolButton->setAutoRaise( true );
|
||||
alignToolButton->setToolButtonStyle( Qt::ToolButtonIconOnly );
|
||||
|
||||
alignToolButton->addAction( mActionAlignLeft );
|
||||
alignToolButton->addAction( mActionAlignHCenter );
|
||||
alignToolButton->addAction( mActionAlignRight );
|
||||
alignToolButton->addAction( mActionAlignTop );
|
||||
alignToolButton->addAction( mActionAlignVCenter );
|
||||
alignToolButton->addAction( mActionAlignBottom );
|
||||
alignToolButton->setDefaultAction( mActionAlignLeft );
|
||||
mActionsToolbar->addWidget( alignToolButton );
|
||||
|
||||
mAddItemTool = new QgsLayoutViewToolAddItem( mView );
|
||||
mPanTool = new QgsLayoutViewToolPan( mView );
|
||||
mPanTool->setAction( mActionPan );
|
||||
@ -213,6 +227,30 @@ QgsLayoutDesignerDialog::QgsLayoutDesignerDialog( QWidget *parent, Qt::WindowFla
|
||||
connect( mActionLowerItems, &QAction::triggered, this, &QgsLayoutDesignerDialog::lowerSelectedItems );
|
||||
connect( mActionMoveItemsToTop, &QAction::triggered, this, &QgsLayoutDesignerDialog::moveSelectedItemsToTop );
|
||||
connect( mActionMoveItemsToBottom, &QAction::triggered, this, &QgsLayoutDesignerDialog::moveSelectedItemsToBottom );
|
||||
connect( mActionAlignLeft, &QAction::triggered, this, [ = ]
|
||||
{
|
||||
mView->alignSelectedItems( QgsLayoutAligner::Left );
|
||||
} );
|
||||
connect( mActionAlignHCenter, &QAction::triggered, this, [ = ]
|
||||
{
|
||||
mView->alignSelectedItems( QgsLayoutAligner::HCenter );
|
||||
} );
|
||||
connect( mActionAlignRight, &QAction::triggered, this, [ = ]
|
||||
{
|
||||
mView->alignSelectedItems( QgsLayoutAligner::Right );
|
||||
} );
|
||||
connect( mActionAlignTop, &QAction::triggered, this, [ = ]
|
||||
{
|
||||
mView->alignSelectedItems( QgsLayoutAligner::Top );
|
||||
} );
|
||||
connect( mActionAlignVCenter, &QAction::triggered, this, [ = ]
|
||||
{
|
||||
mView->alignSelectedItems( QgsLayoutAligner::VCenter );
|
||||
} );
|
||||
connect( mActionAlignBottom, &QAction::triggered, this, [ = ]
|
||||
{
|
||||
mView->alignSelectedItems( QgsLayoutAligner::Bottom );
|
||||
} );
|
||||
|
||||
connect( mActionAddPages, &QAction::triggered, this, &QgsLayoutDesignerDialog::addPages );
|
||||
|
||||
|
@ -359,6 +359,7 @@ SET(QGIS_CORE_SRCS
|
||||
dxf/qgsdxfpallabeling.cpp
|
||||
|
||||
layout/qgslayout.cpp
|
||||
layout/qgslayoutaligner.cpp
|
||||
layout/qgslayoutcontext.cpp
|
||||
layout/qgslayoutgridsettings.cpp
|
||||
layout/qgslayoutguidecollection.cpp
|
||||
@ -965,6 +966,7 @@ SET(QGIS_CORE_HDRS
|
||||
composer/qgscomposertexttable.h
|
||||
composer/qgspaperitem.h
|
||||
|
||||
layout/qgslayoutaligner.h
|
||||
layout/qgslayoutcontext.h
|
||||
layout/qgslayoutgridsettings.h
|
||||
layout/qgslayoutitemundocommand.h
|
||||
|
131
src/core/layout/qgslayoutaligner.cpp
Normal file
131
src/core/layout/qgslayoutaligner.cpp
Normal file
@ -0,0 +1,131 @@
|
||||
/***************************************************************************
|
||||
qgslayoutaligner.cpp
|
||||
--------------------
|
||||
begin : October 2017
|
||||
copyright : (C) 2017 by Nyall Dawson
|
||||
email : nyall dot dawson at gmail dot com
|
||||
***************************************************************************/
|
||||
/***************************************************************************
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#include "qgslayoutaligner.h"
|
||||
#include "qgslayoutitem.h"
|
||||
#include "qgslayout.h"
|
||||
|
||||
void QgsLayoutAligner::alignItems( QgsLayout *layout, const QList<QgsLayoutItem *> &items, QgsLayoutAligner::Alignment alignment )
|
||||
{
|
||||
if ( !layout || items.size() < 2 )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
QRectF itemBBox = boundingRectOfItems( items );
|
||||
if ( !itemBBox.isValid() )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
double refCoord = 0;
|
||||
switch ( alignment )
|
||||
{
|
||||
case Left:
|
||||
refCoord = itemBBox.left();
|
||||
break;
|
||||
case HCenter:
|
||||
refCoord = itemBBox.center().x();
|
||||
break;
|
||||
case Right:
|
||||
refCoord = itemBBox.right();
|
||||
break;
|
||||
case Top:
|
||||
refCoord = itemBBox.top();
|
||||
break;
|
||||
case VCenter:
|
||||
refCoord = itemBBox.center().y();
|
||||
break;
|
||||
case Bottom:
|
||||
refCoord = itemBBox.bottom();
|
||||
break;
|
||||
}
|
||||
|
||||
layout->undoStack()->beginMacro( QObject::tr( "Aligned items bottom" ) );
|
||||
for ( QgsLayoutItem *item : items )
|
||||
{
|
||||
layout->undoStack()->beginCommand( item, QString() );
|
||||
|
||||
QPointF shifted = item->pos();
|
||||
switch ( alignment )
|
||||
{
|
||||
case Left:
|
||||
shifted.setX( refCoord );
|
||||
break;
|
||||
case HCenter:
|
||||
shifted.setX( refCoord - item->rect().width() / 2.0 );
|
||||
break;
|
||||
case Right:
|
||||
shifted.setX( refCoord - item->rect().width() );
|
||||
break;
|
||||
case Top:
|
||||
shifted.setY( refCoord );
|
||||
break;
|
||||
case VCenter:
|
||||
shifted.setY( refCoord - item->rect().height() / 2.0 );
|
||||
break;
|
||||
case Bottom:
|
||||
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()->endCommand();
|
||||
}
|
||||
layout->undoStack()->endMacro();
|
||||
}
|
||||
|
||||
QRectF QgsLayoutAligner::boundingRectOfItems( const QList<QgsLayoutItem *> &items )
|
||||
{
|
||||
if ( items.empty() )
|
||||
{
|
||||
return QRectF();
|
||||
}
|
||||
|
||||
auto it = items.constBegin();
|
||||
//set the box to the first item
|
||||
QgsLayoutItem *currentItem = *it;
|
||||
it++;
|
||||
double minX = currentItem->pos().x();
|
||||
double minY = currentItem->pos().y();
|
||||
double maxX = minX + currentItem->rect().width();
|
||||
double maxY = minY + currentItem->rect().height();
|
||||
|
||||
double currentMinX, currentMinY, currentMaxX, currentMaxY;
|
||||
|
||||
for ( ; it != items.constEnd(); ++it )
|
||||
{
|
||||
currentItem = *it;
|
||||
currentMinX = currentItem->pos().x();
|
||||
currentMinY = currentItem->pos().y();
|
||||
currentMaxX = currentMinX + currentItem->rect().width();
|
||||
currentMaxY = currentMinY + currentItem->rect().height();
|
||||
|
||||
if ( currentMinX < minX )
|
||||
minX = currentMinX;
|
||||
if ( currentMaxX > maxX )
|
||||
maxX = currentMaxX;
|
||||
if ( currentMinY < minY )
|
||||
minY = currentMinY;
|
||||
if ( currentMaxY > maxY )
|
||||
maxY = currentMaxY;
|
||||
}
|
||||
|
||||
return QRectF( QPointF( minX, minY ), QPointF( maxX, maxY ) );
|
||||
}
|
71
src/core/layout/qgslayoutaligner.h
Normal file
71
src/core/layout/qgslayoutaligner.h
Normal file
@ -0,0 +1,71 @@
|
||||
/***************************************************************************
|
||||
qgslayoutaligner.h
|
||||
------------------
|
||||
begin : October 2017
|
||||
copyright : (C) 2017 by Nyall Dawson
|
||||
email : nyall dot dawson at gmail dot com
|
||||
***************************************************************************/
|
||||
/***************************************************************************
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
#ifndef QGSLAYOUTALIGNER_H
|
||||
#define QGSLAYOUTALIGNER_H
|
||||
|
||||
#include "qgis_core.h"
|
||||
#include <QList>
|
||||
#include <QRectF>
|
||||
|
||||
class QgsLayoutItem;
|
||||
class QgsLayout;
|
||||
|
||||
/**
|
||||
* \ingroup core
|
||||
* \class QgsLayoutAligner
|
||||
* \brief Handles aligning and distributing sets of layout items.
|
||||
*
|
||||
* QgsLayoutAligner contains methods for automatically aligning and distributing
|
||||
* sets of layout items, e.g. aligning a group of items to top or left sides.
|
||||
*
|
||||
* \since QGIS 3.0
|
||||
*/
|
||||
class CORE_EXPORT QgsLayoutAligner
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
//! 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
|
||||
};
|
||||
|
||||
/**
|
||||
* Aligns a set of \a items from a \a layout in place.
|
||||
*
|
||||
* The \a alignment argument specifies the method to use when aligning the items.
|
||||
*/
|
||||
static void alignItems( QgsLayout *layout, const QList< QgsLayoutItem * > &items, Alignment alignment );
|
||||
|
||||
private:
|
||||
|
||||
/**
|
||||
* Returns the bounding rectangle of the selected items in
|
||||
* scene coordinates.
|
||||
*/
|
||||
static QRectF boundingRectOfItems( const QList< QgsLayoutItem * > &items );
|
||||
|
||||
|
||||
|
||||
};
|
||||
|
||||
#endif //QGSLAYOUTALIGNER_H
|
@ -230,6 +230,12 @@ QList<int> QgsLayoutView::visiblePageNumbers() const
|
||||
return currentLayout()->pageCollection()->visiblePageNumbers( visibleRect );
|
||||
}
|
||||
|
||||
void QgsLayoutView::alignSelectedItems( QgsLayoutAligner::Alignment alignment )
|
||||
{
|
||||
const QList<QgsLayoutItem *> selectedItems = currentLayout()->selectedLayoutItems();
|
||||
QgsLayoutAligner::alignItems( currentLayout(), selectedItems, alignment );
|
||||
}
|
||||
|
||||
void QgsLayoutView::zoomFull()
|
||||
{
|
||||
fitInView( scene()->sceneRect(), Qt::KeepAspectRatio );
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include "qgsprevieweffect.h" // for QgsPreviewEffect::PreviewMode
|
||||
#include "qgis_gui.h"
|
||||
#include "qgslayoutitempage.h"
|
||||
#include "qgslayoutaligner.h"
|
||||
#include <QPointer>
|
||||
#include <QGraphicsView>
|
||||
#include <QGraphicsRectItem>
|
||||
@ -157,6 +158,11 @@ class GUI_EXPORT QgsLayoutView: public QGraphicsView
|
||||
*/
|
||||
QList< int > visiblePageNumbers() const;
|
||||
|
||||
/**
|
||||
* Aligns all selected items using the specified \a alignment.
|
||||
*/
|
||||
void alignSelectedItems( QgsLayoutAligner::Alignment alignment );
|
||||
|
||||
public slots:
|
||||
|
||||
/**
|
||||
|
@ -85,7 +85,7 @@
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>1083</width>
|
||||
<height>25</height>
|
||||
<height>42</height>
|
||||
</rect>
|
||||
</property>
|
||||
<widget class="QMenu" name="mLayoutMenu">
|
||||
@ -160,8 +160,16 @@
|
||||
<addaction name="mActionLowerItems"/>
|
||||
<addaction name="mActionMoveItemsToTop"/>
|
||||
<addaction name="mActionMoveItemsToBottom"/>
|
||||
<addaction name="separator"/>
|
||||
<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"/>
|
||||
</widget>
|
||||
<addaction name="mLayoutMenu"/>
|
||||
<addaction name="menuEdit"/>
|
||||
@ -663,6 +671,78 @@
|
||||
<string>Ctrl+Shift+[</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="mActionAlignLeft">
|
||||
<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>Align Left</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Align selected items left</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="mActionAlignHCenter">
|
||||
<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>Align Center</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Align center horizontal</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="mActionAlignRight">
|
||||
<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>Align Right</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Align selected items right</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="mActionAlignTop">
|
||||
<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>Align Top</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Align selected items to top</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="mActionAlignVCenter">
|
||||
<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>Align Center Vertical</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Align center vertical</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="mActionAlignBottom">
|
||||
<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>Align Bottom</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Align selected items bottom</string>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
<resources>
|
||||
<include location="../../../images/images.qrc"/>
|
||||
@ -691,7 +771,6 @@
|
||||
<include location="../../../images/images.qrc"/>
|
||||
<include location="../../../images/images.qrc"/>
|
||||
<include location="../../../images/images.qrc"/>
|
||||
<include location="../../../images/images.qrc"/>
|
||||
</resources>
|
||||
<connections/>
|
||||
</ui>
|
||||
|
Loading…
x
Reference in New Issue
Block a user