Skip to content

Commit

Permalink
Merge pull request #5330 from nyalldawson/layout_next
Browse files Browse the repository at this point in the history
[layouts] Port group handling
  • Loading branch information
nyalldawson committed Oct 13, 2017
2 parents f6ee7cb + 7b6156e commit 9a3b547
Show file tree
Hide file tree
Showing 44 changed files with 1,986 additions and 154 deletions.
1 change: 1 addition & 0 deletions python/core/core_auto.sip
Expand Up @@ -403,6 +403,7 @@
%Include layout/qgslayout.sip
%Include layout/qgslayoutguidecollection.sip
%Include layout/qgslayoutitem.sip
%Include layout/qgslayoutitemgroup.sip
%Include layout/qgslayoutitemmap.sip
%Include layout/qgslayoutitempage.sip
%Include layout/qgslayoutitemregistry.sip
Expand Down
19 changes: 19 additions & 0 deletions python/core/layout/qgslayout.sip
Expand Up @@ -397,6 +397,25 @@ class QgsLayout : QGraphicsScene, QgsExpressionContextGenerator, QgsLayoutUndoOb
virtual QgsAbstractLayoutUndoCommand *createCommand( const QString &text, int id = 0, QUndoCommand *parent = 0 ) /Factory/;


QgsLayoutItemGroup *groupItems( const QList<QgsLayoutItem *> &items );
%Docstring
Creates a new group from a list of layout ``items`` and adds the group to the layout.
If grouping was not possible, a None will be returned.
.. seealso:: ungroupItems()
:rtype: QgsLayoutItemGroup
%End

QList<QgsLayoutItem *> ungroupItems( QgsLayoutItemGroup *group );
%Docstring
Ungroups items by removing them from an item ``group`` and removing the group from the
layout. Child items will remain in the layout and will not be deleted.

Returns a list of the items removed from the group, or an empty list if ungrouping
was not successful.

.. seealso:: groupItems()
:rtype: list of QgsLayoutItem
%End

public slots:

Expand Down
23 changes: 23 additions & 0 deletions python/core/layout/qgslayoutitem.sip
Expand Up @@ -150,6 +150,29 @@ class QgsLayoutItem : QgsLayoutObject, QGraphicsRectItem, QgsLayoutUndoObjectInt
:rtype: bool
%End

bool isGroupMember() const;
%Docstring
Returns true if the item is part of a QgsLayoutItemGroup group.
.. seealso:: parentGroup()
.. seealso:: setParentGroup()
:rtype: bool
%End

QgsLayoutItemGroup *parentGroup() const;
%Docstring
Returns the item's parent group, if the item is part of a QgsLayoutItemGroup group.
.. seealso:: isGroupMember()
.. seealso:: setParentGroup()
:rtype: QgsLayoutItemGroup
%End

void setParentGroup( QgsLayoutItemGroup *group );
%Docstring
Sets the item's parent ``group``.
.. seealso:: isGroupMember()
.. seealso:: parentGroup()
%End

virtual void paint( QPainter *painter, const QStyleOptionGraphicsItem *itemStyle, QWidget *pWidget );

%Docstring
Expand Down
93 changes: 93 additions & 0 deletions python/core/layout/qgslayoutitemgroup.sip
@@ -0,0 +1,93 @@
/************************************************************************
* This file has been generated automatically from *
* *
* src/core/layout/qgslayoutitemgroup.h *
* *
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
************************************************************************/



class QgsLayoutItemGroup: QgsLayoutItem
{
%Docstring
A container for grouping several QgsLayoutItems.
.. versionadded:: 3.0
%End

%TypeHeaderCode
#include "qgslayoutitemgroup.h"
%End
public:

explicit QgsLayoutItemGroup( QgsLayout *layout );
%Docstring
Constructor for QgsLayoutItemGroup, belonging to the specified ``layout``.
%End
~QgsLayoutItemGroup();

virtual int type() const;

virtual QString stringType() const;

virtual QString displayName() const;


static QgsLayoutItemGroup *create( QgsLayout *layout, const QVariantMap &settings ) /Factory/;
%Docstring
Returns a new group item for the specified ``layout``.

The caller takes responsibility for deleting the returned object.
:rtype: QgsLayoutItemGroup
%End

void addItem( QgsLayoutItem *item /Transfer/ );
%Docstring
Adds an ``item`` to the group. Ownership of the item
is transferred to the group.
%End

void removeItems();
%Docstring
Removes all items from the group (but does not delete them).
Items remain in the scene but are no longer grouped together
%End

QList<QgsLayoutItem *> items() const;
%Docstring
Returns a list of items contained by the group.
:rtype: list of QgsLayoutItem
%End

virtual void setVisibility( const bool visible );


virtual void attemptMove( const QgsLayoutPoint &point );

virtual void attemptResize( const QgsLayoutSize &size );


virtual bool writeXml( QDomElement &parentElement, QDomDocument &document, const QgsReadWriteContext &context ) const;

virtual bool readXml( const QDomElement &itemElement, const QDomDocument &document, const QgsReadWriteContext &context );


virtual void paint( QPainter *painter, const QStyleOptionGraphicsItem *itemStyle, QWidget *pWidget );


protected:
virtual void draw( QgsRenderContext &context, const QStyleOptionGraphicsItem *itemStyle = 0 );


};




/************************************************************************
* This file has been generated automatically from *
* *
* src/core/layout/qgslayoutitemgroup.h *
* *
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
************************************************************************/
2 changes: 2 additions & 0 deletions python/core/layout/qgslayoutitemmap.sip
Expand Up @@ -25,8 +25,10 @@ class QgsLayoutItemMap : QgsLayoutItem
Constructor for QgsLayoutItemMap, with the specified parent ``layout``.
%End
virtual int type() const;

virtual QString stringType() const;


protected:

virtual void draw( QgsRenderContext &context, const QStyleOptionGraphicsItem *itemStyle = 0 );
Expand Down
1 change: 1 addition & 0 deletions python/core/layout/qgslayoutitemregistry.sip
Expand Up @@ -98,6 +98,7 @@ class QgsLayoutItemRegistry : QObject
enum ItemType
{
LayoutItem,
LayoutGroup,

// known
LayoutPage,
Expand Down
12 changes: 12 additions & 0 deletions python/gui/layout/qgslayoutview.sip
Expand Up @@ -314,6 +314,18 @@ class QgsLayoutView: QGraphicsView
Deletes all selected items.
%End

void groupSelectedItems();
%Docstring
Groups all selected items.
.. seealso:: ungroupSelectedItems()
%End

void ungroupSelectedItems();
%Docstring
Ungroups all selected items.
.. seealso:: groupSelectedItems()
%End

void viewChanged();
%Docstring
Updates associated rulers and other widgets after view extent or zoom has changed.
Expand Down
47 changes: 47 additions & 0 deletions src/app/layout/qgslayoutappmenuprovider.cpp
Expand Up @@ -15,6 +15,7 @@

#include "qgslayoutappmenuprovider.h"
#include "qgslayoutitempage.h"
#include "qgslayoutitemgroup.h"
#include "qgslayoutdesignerdialog.h"
#include "qgslayout.h"
#include <QMenu>
Expand All @@ -31,6 +32,52 @@ QMenu *QgsLayoutAppMenuProvider::createContextMenu( QWidget *parent, QgsLayout *
{
QMenu *menu = new QMenu( parent );

//undo/redo
menu->addAction( layout->undoStack()->stack()->createUndoAction( menu ) );
menu->addAction( layout->undoStack()->stack()->createRedoAction( menu ) );
menu->addSeparator();


const QList< QgsLayoutItem * > selectedItems = layout->selectedLayoutItems();
if ( !selectedItems.empty() )
{
bool addedGroupAction = false;
if ( selectedItems.count() > 1 )
{
QAction *groupAction = new QAction( tr( "Group" ), menu );
connect( groupAction, &QAction::triggered, this, [this]()
{
mDesigner->view()->groupSelectedItems();
} );
menu->addAction( groupAction );
addedGroupAction = true;
}
bool foundSelectedGroup = false;
QList< QgsLayoutItemGroup * > groups;
layout->layoutItems( groups );
for ( QgsLayoutItemGroup *group : qgsAsConst( groups ) )
{
if ( group->isSelected() )
{
foundSelectedGroup = true;
break;
}
}
if ( foundSelectedGroup )
{
QAction *ungroupAction = new QAction( tr( "Ungroup" ), menu );
connect( ungroupAction, &QAction::triggered, this, [this]()
{
mDesigner->view()->ungroupSelectedItems();
} );
menu->addAction( ungroupAction );
addedGroupAction = true;
}

if ( addedGroupAction )
menu->addSeparator();
}

// is a page under the mouse?
QgsLayoutItemPage *page = layout->pageCollection()->pageAtPoint( layoutPoint );
if ( page )
Expand Down
31 changes: 23 additions & 8 deletions src/app/layout/qgslayoutdesignerdialog.cpp
Expand Up @@ -372,6 +372,14 @@ QgsLayoutDesignerDialog::QgsLayoutDesignerDialog( QWidget *parent, Qt::WindowFla
{
mView->deleteSelectedItems();
} );
connect( mActionGroupItems, &QAction::triggered, this, [ = ]
{
mView->groupSelectedItems();
} );
connect( mActionUngroupItems, &QAction::triggered, this, [ = ]
{
mView->ungroupSelectedItems();
} );

//create status bar labels
mStatusCursorXLabel = new QLabel( mStatusBar );
Expand Down Expand Up @@ -518,9 +526,6 @@ QgsLayoutDesignerDialog::QgsLayoutDesignerDialog( QWidget *parent, Qt::WindowFla
mGeneralDock->show();
mItemsDock->show();

mActionUndo->setEnabled( false );
mActionRedo->setEnabled( false );

tabifyDockWidget( mGeneralDock, mUndoDock );
tabifyDockWidget( mItemDock, mUndoDock );
tabifyDockWidget( mGeneralDock, mItemDock );
Expand All @@ -547,6 +552,20 @@ void QgsLayoutDesignerDialog::setCurrentLayout( QgsLayout *layout )
mLayout = layout;
mView->setCurrentLayout( layout );

// add undo/redo actions which apply to the correct layout undo stack
delete mUndoAction;
delete mRedoAction;
mUndoAction = layout->undoStack()->stack()->createUndoAction( this );
mUndoAction->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionUndo.svg" ) ) );
mUndoAction->setShortcuts( QKeySequence::Undo );
mRedoAction = layout->undoStack()->stack()->createRedoAction( this );
mRedoAction->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionRedo.svg" ) ) );
mRedoAction->setShortcuts( QKeySequence::Redo );
menuEdit->insertAction( menuEdit->actions().at( 0 ), mRedoAction );
menuEdit->insertAction( mRedoAction, mUndoAction );
mLayoutToolbar->addAction( mUndoAction );
mLayoutToolbar->addAction( mRedoAction );

connect( mActionClearGuides, &QAction::triggered, &mLayout->guides(), [ = ]
{
mLayout->guides().clear();
Expand All @@ -560,10 +579,6 @@ void QgsLayoutDesignerDialog::setCurrentLayout( QgsLayout *layout )
mActionShowBoxes->setChecked( mLayout->context().boundingBoxesVisible() );
mActionShowPage->setChecked( mLayout->context().pagesVisible() );

connect( mLayout->undoStack()->stack(), &QUndoStack::canUndoChanged, mActionUndo, &QAction::setEnabled );
connect( mLayout->undoStack()->stack(), &QUndoStack::canRedoChanged, mActionRedo, &QAction::setEnabled );
connect( mActionUndo, &QAction::triggered, mLayout->undoStack()->stack(), &QUndoStack::undo );
connect( mActionRedo, &QAction::triggered, mLayout->undoStack()->stack(), &QUndoStack::redo );
mUndoView->setStack( mLayout->undoStack()->stack() );

mSelectTool->setLayout( layout );
Expand Down Expand Up @@ -981,7 +996,7 @@ void QgsLayoutDesignerDialog::addPages()
}

if ( dlg.numberPages() > 1 )
mLayout->undoStack()->beginMacro( tr( "Add pages" ) );
mLayout->undoStack()->beginMacro( tr( "Add Pages" ) );
for ( int i = 0; i < dlg.numberPages(); ++i )
{
QgsLayoutItemPage *page = new QgsLayoutItemPage( mLayout );
Expand Down
3 changes: 3 additions & 0 deletions src/app/layout/qgslayoutdesignerdialog.h
Expand Up @@ -283,6 +283,9 @@ class QgsLayoutDesignerDialog: public QMainWindow, private Ui::QgsLayoutDesigner
QgsDockWidget *mItemsDock = nullptr;
QTreeView *mItemsTreeView = nullptr;

QAction *mUndoAction = nullptr;
QAction *mRedoAction = nullptr;

struct PanelStatus
{
PanelStatus( bool visible = true, bool active = false )
Expand Down
6 changes: 3 additions & 3 deletions src/app/layout/qgslayoutguidewidget.cpp
Expand Up @@ -72,7 +72,7 @@ void QgsLayoutGuideWidget::addVerticalGuide()

void QgsLayoutGuideWidget::deleteHorizontalGuide()
{
mLayout->undoStack()->beginMacro( tr( "Remove horizontal guides" ) );
mLayout->undoStack()->beginMacro( tr( "Remove Horizontal Guides" ) );
Q_FOREACH ( const QModelIndex &index, mHozGuidesTableView->selectionModel()->selectedIndexes() )
{
mHozGuidesTableView->closePersistentEditor( index );
Expand All @@ -84,7 +84,7 @@ void QgsLayoutGuideWidget::deleteHorizontalGuide()

void QgsLayoutGuideWidget::deleteVerticalGuide()
{
mLayout->undoStack()->beginMacro( tr( "Remove vertical guides" ) );
mLayout->undoStack()->beginMacro( tr( "Remove Vertical Guides" ) );
Q_FOREACH ( const QModelIndex &index, mVertGuidesTableView->selectionModel()->selectedIndexes() )
{
mVertGuidesTableView->closePersistentEditor( index );
Expand Down Expand Up @@ -127,7 +127,7 @@ void QgsLayoutGuideWidget::clearAll()
mVertGuidesTableView->closePersistentEditor( index );
}

mLayout->undoStack()->beginMacro( tr( "Remove all guides" ) );
mLayout->undoStack()->beginMacro( tr( "Remove All Guides" ) );
mVertProxyModel->removeRows( 0, mVertProxyModel->rowCount() );
mHozProxyModel->removeRows( 0, mHozProxyModel->rowCount() );
mLayout->undoStack()->endMacro();
Expand Down
2 changes: 1 addition & 1 deletion src/app/layout/qgslayoutpagepropertieswidget.cpp
Expand Up @@ -128,7 +128,7 @@ void QgsLayoutPagePropertiesWidget::orientationChanged( int )

void QgsLayoutPagePropertiesWidget::updatePageSize()
{
mPage->layout()->undoStack()->beginCommand( mPage, tr( "Changed page size" ), 1 + mPage->layout()->pageCollection()->pageNumber( mPage ) );
mPage->layout()->undoStack()->beginCommand( mPage, tr( "Change Page Size" ), 1 + mPage->layout()->pageCollection()->pageNumber( mPage ) );
mPage->setPageSize( QgsLayoutSize( mWidthSpin->value(), mHeightSpin->value(), mSizeUnitsComboBox->unit() ) );
mPage->layout()->undoStack()->endCommand();
mPage->layout()->pageCollection()->reflow();
Expand Down
4 changes: 4 additions & 0 deletions src/core/CMakeLists.txt
Expand Up @@ -365,6 +365,8 @@ SET(QGIS_CORE_SRCS
layout/qgslayoutgridsettings.cpp
layout/qgslayoutguidecollection.cpp
layout/qgslayoutitem.cpp
layout/qgslayoutitemgroup.cpp
layout/qgslayoutitemgroupundocommand.cpp
layout/qgslayoutitemmap.cpp
layout/qgslayoutitempage.cpp
layout/qgslayoutitemregistry.cpp
Expand Down Expand Up @@ -714,6 +716,8 @@ SET(QGIS_CORE_MOC_HDRS
layout/qgslayout.h
layout/qgslayoutguidecollection.h
layout/qgslayoutitem.h
layout/qgslayoutitemgroup.h
layout/qgslayoutitemgroupundocommand.h
layout/qgslayoutitemmap.h
layout/qgslayoutitempage.h
layout/qgslayoutitemregistry.h
Expand Down

0 comments on commit 9a3b547

Please sign in to comment.