Skip to content
Permalink
Browse files

Merge pull request #5794 from nyalldawson/layout_next2

[layouts] Copy/paste, templates, etc
  • Loading branch information
nyalldawson committed Dec 6, 2017
2 parents ca75e8c + 8e77701 commit a12673c51bdb0feb0c890fbff45d7f464d89de64
Showing with 4,188 additions and 597 deletions.
  1. +0 −93 python/core/composer/qgscomposeritem.sip
  2. +82 −7 python/core/composer/qgslayoutmanager.sip
  3. +57 −1 python/core/layout/qgslayout.sip
  4. +0 −2 python/core/layout/qgslayoutframe.sip
  5. +177 −12 python/core/layout/qgslayoutitem.sip
  6. +0 −2 python/core/layout/qgslayoutitemattributetable.sip
  7. +6 −3 python/core/layout/qgslayoutitemgroup.sip
  8. +0 −2 python/core/layout/qgslayoutitemhtml.sip
  9. +0 −3 python/core/layout/qgslayoutitemlabel.sip
  10. +3 −2 python/core/layout/qgslayoutitemlegend.sip
  11. +3 −2 python/core/layout/qgslayoutitemmap.sip
  12. +1 −2 python/core/layout/qgslayoutitempage.sip
  13. +3 −2 python/core/layout/qgslayoutitempicture.sip
  14. +0 −2 python/core/layout/qgslayoutitempolygon.sip
  15. +0 −2 python/core/layout/qgslayoutitempolyline.sip
  16. +1 −2 python/core/layout/qgslayoutitemscalebar.sip
  17. +1 −1 python/core/layout/qgslayoutitemshape.sip
  18. +0 −2 python/core/layout/qgslayoutitemtexttable.sip
  19. +17 −9 python/core/layout/qgslayoutmultiframe.sip
  20. +10 −0 python/core/layout/qgslayoutpagecollection.sip
  21. +1 −0 python/gui/gui_auto.sip
  22. +49 −0 python/gui/layout/qgslayoutcustomdrophandler.sip
  23. +5 −0 python/gui/layout/qgslayoutdesignerinterface.sip
  24. +66 −0 python/gui/layout/qgslayoutview.sip
  25. +1 −0 python/gui/layout/qgslayoutviewtoolselect.sip
  26. +24 −0 python/gui/qgisinterface.sip
  27. +2 −2 python/gui/qgsfilewidget.sip
  28. +4 −0 src/app/CMakeLists.txt
  29. +19 −19 src/app/composer/qgscomposermanager.cpp
  30. +3 −3 src/app/composer/qgscomposermanager.h
  31. +25 −0 src/app/layout/qgslayoutappmenuprovider.cpp
  32. +2 −1 src/app/layout/qgslayoutapputils.cpp
  33. +2 −0 src/app/layout/qgslayoutapputils.h
  34. +2 −2 src/app/layout/qgslayoutattributetablewidget.h
  35. +364 −0 src/app/layout/qgslayoutdesignerdialog.cpp
  36. +33 −1 src/app/layout/qgslayoutdesignerdialog.h
  37. +2 −2 src/app/layout/qgslayouthtmlwidget.h
  38. +16 −0 src/app/layout/qgslayoutitemslistview.cpp
  39. +2 −3 src/app/layout/qgslayoutlabelwidget.h
  40. +2 −4 src/app/layout/qgslayoutlegendwidget.h
  41. +568 −0 src/app/layout/qgslayoutmanagerdialog.cpp
  42. +122 −0 src/app/layout/qgslayoutmanagerdialog.h
  43. +2 −2 src/app/layout/qgslayoutmapgridwidget.h
  44. +1 −1 src/app/layout/qgslayoutmapwidget.h
  45. +1 −1 src/app/layout/qgslayoutpicturewidget.h
  46. +1 −1 src/app/layout/qgslayoutpolygonwidget.h
  47. +1 −1 src/app/layout/qgslayoutpolylinewidget.h
  48. +63 −0 src/app/layout/qgslayoutqptdrophandler.cpp
  49. +32 −0 src/app/layout/qgslayoutqptdrophandler.h
  50. +1 −1 src/app/layout/qgslayoutscalebarwidget.h
  51. +1 −1 src/app/layout/qgslayoutshapewidget.h
  52. +134 −3 src/app/qgisapp.cpp
  53. +48 −0 src/app/qgisapp.h
  54. +15 −0 src/app/qgisappinterface.cpp
  55. +6 −3 src/app/qgisappinterface.h
  56. +1 −102 src/core/composer/qgscomposeritem.h
  57. +138 −1 src/core/composer/qgslayoutmanager.cpp
  58. +67 −6 src/core/composer/qgslayoutmanager.h
  59. +263 −5 src/core/layout/qgslayout.cpp
  60. +59 −2 src/core/layout/qgslayout.h
  61. +0 −5 src/core/layout/qgslayoutframe.cpp
  62. +0 −1 src/core/layout/qgslayoutframe.h
  63. +29 −8 src/core/layout/qgslayoutitem.cpp
  64. +177 −9 src/core/layout/qgslayoutitem.h
  65. +1 −6 src/core/layout/qgslayoutitemattributetable.cpp
  66. +0 −1 src/core/layout/qgslayoutitemattributetable.h
  67. +21 −29 src/core/layout/qgslayoutitemgroup.cpp
  68. +5 −3 src/core/layout/qgslayoutitemgroup.h
  69. +0 −5 src/core/layout/qgslayoutitemhtml.cpp
  70. +0 −1 src/core/layout/qgslayoutitemhtml.h
  71. +0 −5 src/core/layout/qgslayoutitemlabel.cpp
  72. +0 −2 src/core/layout/qgslayoutitemlabel.h
  73. +18 −11 src/core/layout/qgslayoutitemlegend.cpp
  74. +4 −1 src/core/layout/qgslayoutitemlegend.h
  75. +11 −5 src/core/layout/qgslayoutitemmap.cpp
  76. +2 −1 src/core/layout/qgslayoutitemmap.h
  77. +5 −0 src/core/layout/qgslayoutitempage.cpp
  78. +1 −3 src/core/layout/qgslayoutitempage.h
  79. +32 −27 src/core/layout/qgslayoutitempicture.cpp
  80. +5 −1 src/core/layout/qgslayoutitempicture.h
  81. +0 −5 src/core/layout/qgslayoutitempolygon.cpp
  82. +0 −1 src/core/layout/qgslayoutitempolygon.h
  83. +0 −5 src/core/layout/qgslayoutitempolyline.cpp
  84. +0 −1 src/core/layout/qgslayoutitempolyline.h
  85. +6 −0 src/core/layout/qgslayoutitemregistry.cpp
  86. +3 −2 src/core/layout/qgslayoutitemregistry.h
  87. +14 −12 src/core/layout/qgslayoutitemscalebar.cpp
  88. +3 −2 src/core/layout/qgslayoutitemscalebar.h
  89. +5 −0 src/core/layout/qgslayoutitemshape.cpp
  90. +1 −2 src/core/layout/qgslayoutitemshape.h
  91. +0 −5 src/core/layout/qgslayoutitemtexttable.cpp
  92. +0 −1 src/core/layout/qgslayoutitemtexttable.h
  93. +3 −0 src/core/layout/qgslayoutitemundocommand.cpp
  94. +6 −2 src/core/layout/qgslayoutmultiframe.cpp
  95. +17 −8 src/core/layout/qgslayoutmultiframe.h
  96. +21 −0 src/core/layout/qgslayoutpagecollection.cpp
  97. +10 −0 src/core/layout/qgslayoutpagecollection.h
  98. +2 −0 src/gui/CMakeLists.txt
  99. +27 −0 src/gui/layout/qgslayoutcustomdrophandler.cpp
  100. +54 −0 src/gui/layout/qgslayoutcustomdrophandler.h
  101. +6 −0 src/gui/layout/qgslayoutdesignerinterface.h
  102. +4 −6 src/gui/layout/qgslayoutmousehandles.cpp
  103. +156 −60 src/gui/layout/qgslayoutview.cpp
  104. +64 −0 src/gui/layout/qgslayoutview.h
  105. +7 −0 src/gui/layout/qgslayoutviewtoolselect.cpp
  106. +1 −0 src/gui/layout/qgslayoutviewtoolselect.h
  107. +21 −0 src/gui/qgisinterface.h
  108. +1 −1 src/gui/qgsfilewidget.cpp
  109. +1 −1 src/gui/qgsfilewidget.h
  110. +132 −1 src/ui/layout/qgslayoutdesignerbase.ui
  111. +203 −0 src/ui/layout/qgslayoutmanagerbase.ui
  112. +38 −0 tests/src/core/testqgslayout.cpp
  113. +16 −7 tests/src/core/testqgslayoutitem.cpp
  114. +4 −0 tests/src/core/testqgslayoutitemgroup.cpp
  115. +2 −2 tests/src/core/testqgslayoutmap.cpp
  116. +0 −5 tests/src/core/testqgslayoutmultiframe.cpp
  117. +5 −3 tests/src/core/testqgslayoutshapes.cpp
  118. +4 −4 tests/src/core/testqgslayouttable.cpp
  119. +1 −1 tests/src/core/testqgslayoututils.cpp
  120. +3 −4 tests/src/gui/testqgslayoutview.cpp
  121. +216 −0 tests/src/python/test_qgslayout.py
  122. +166 −12 tests/src/python/test_qgslayoutmanager.py
  123. +30 −0 tests/src/python/test_qgslayoutpagecollection.py
  124. +115 −2 tests/src/python/test_qgslayoutview.py
@@ -17,99 +17,6 @@ class QgsComposerItem: QgsComposerObject, QGraphicsRectItem

%TypeHeaderCode
#include "qgscomposeritem.h"
#include <qgscomposerarrow.h>
#include <qgscomposerframe.h>
#include <qgscomposeritemgroup.h>
#include <qgscomposerlabel.h>
#include <qgscomposerlegend.h>
#include <qgscomposermap.h>
#include <qgspaperitem.h>
#include <qgscomposerpicture.h>
#include <qgscomposerscalebar.h>
#include <qgscomposershape.h>
#include <qgscomposerpolygon.h>
#include <qgscomposerpolyline.h>
#include <qgscomposertexttable.h>
#include <qgslayoutitemshape.h>
#include <qgslayoutitempage.h>
%End
%ConvertToSubClassCode
// the conversions have to be static, because they're using multiple inheritance
// (seen in PyQt4 .sip files for some QGraphicsItem classes)
if ( dynamic_cast< QgsComposerItem * >( sipCpp ) )
{
switch ( sipCpp->type() )
{
case QgsComposerItem::ComposerItem:
sipType = sipType_QgsComposerItem;
*sipCppRet = static_cast<QgsComposerItem *>( sipCpp );
break;
case QgsComposerItem::ComposerArrow:
sipType = sipType_QgsComposerArrow;
*sipCppRet = static_cast<QgsComposerArrow *>( sipCpp );
break;
case QgsComposerItem::ComposerItemGroup:
sipType = sipType_QgsComposerItemGroup;
*sipCppRet = static_cast<QgsComposerItemGroup *>( sipCpp );
break;
case QgsComposerItem::ComposerLabel:
sipType = sipType_QgsComposerLabel;
*sipCppRet = static_cast<QgsComposerLabel *>( sipCpp );
break;
case QgsComposerItem::ComposerLegend:
sipType = sipType_QgsComposerLegend;
*sipCppRet = static_cast<QgsComposerLegend *>( sipCpp );
break;
case QgsComposerItem::ComposerMap:
sipType = sipType_QgsComposerMap;
*sipCppRet = static_cast<QgsComposerMap *>( sipCpp );
break;
case QgsComposerItem::ComposerPaper:
sipType = sipType_QgsPaperItem;
*sipCppRet = static_cast<QgsPaperItem *>( sipCpp );
break;
case QgsComposerItem::ComposerPicture:
sipType = sipType_QgsComposerPicture;
*sipCppRet = static_cast<QgsComposerPicture *>( sipCpp );
break;
case QgsComposerItem::ComposerScaleBar:
sipType = sipType_QgsComposerScaleBar;
*sipCppRet = static_cast<QgsComposerScaleBar *>( sipCpp );
break;
case QgsComposerItem::ComposerShape:
sipType = sipType_QgsComposerShape;
*sipCppRet = static_cast<QgsComposerShape *>( sipCpp );
break;
case QgsComposerItem::ComposerPolygon:
sipType = sipType_QgsComposerPolygon;
*sipCppRet = static_cast<QgsComposerPolygon *>( sipCpp );
break;
case QgsComposerItem::ComposerPolyline:
sipType = sipType_QgsComposerPolyline;
*sipCppRet = static_cast<QgsComposerPolyline *>( sipCpp );
break;
case QgsComposerItem::ComposerFrame:
sipType = sipType_QgsComposerFrame;
*sipCppRet = static_cast<QgsComposerFrame *>( sipCpp );
break;
default:
sipType = 0;
}
}
else
{
switch ( sipCpp->type() )
{
// really, these *should* use the constants from QgsLayoutItemRegistry, but sip doesn't like that!
case QGraphicsItem::UserType + 101:
sipType = sipType_QgsLayoutItemPage;
*sipCppRet = static_cast<QgsLayoutItemPage *>( sipCpp );
break;
default:
sipType = 0;
}
}

%End
public:

@@ -15,13 +15,13 @@ class QgsLayoutManager : QObject
%Docstring
.. versionadded:: 3.0

Manages storage of a set of compositions.
Manages storage of a set of layouts.

QgsLayoutManager handles the storage, serializing and deserializing
of QgsCompositions. Usually this class is not constructed directly, but
of QgsLayouts. Usually this class is not constructed directly, but
rather accessed through a QgsProject via QgsProject.layoutManager().

QgsLayoutManager retains ownership of all the compositions contained
QgsLayoutManager retains ownership of all the layouts contained
in the manager.
%End

@@ -48,6 +48,16 @@ class QgsLayoutManager : QObject
:rtype: bool
%End

bool addLayout( QgsLayout *layout /Transfer/ );
%Docstring
Adds a ``layout`` to the manager. Ownership of the layout is transferred to the manager.
Returns true if the addition was successful, or false if the layout could not be added (eg
as a result of a duplicate layout name).
.. seealso:: :py:func:`removeLayout()`
.. seealso:: :py:func:`layoutAdded()`
:rtype: bool
%End

bool removeComposition( QgsComposition *composition );
%Docstring
Removes a composition from the manager. The composition is deleted.
@@ -56,14 +66,26 @@ class QgsLayoutManager : QObject
.. seealso:: :py:func:`addComposition()`
.. seealso:: :py:func:`compositionRemoved()`
.. seealso:: :py:func:`compositionAboutToBeRemoved()`
.. seealso:: :py:func:`clear()`
:rtype: bool
%End

bool removeLayout( QgsLayout *layout );
%Docstring
Removes a ``layout`` from the manager. The layout is deleted.
Returns true if the removal was successful, or false if the removal failed (eg as a result
of removing a layout which is not contained in the manager).
.. seealso:: :py:func:`addLayout()`
.. seealso:: :py:func:`layoutRemoved()`
.. seealso:: :py:func:`layoutAboutToBeRemoved()`
.. seealso:: :py:func:`clear()`
:rtype: bool
%End

void clear();
%Docstring
Removes and deletes all compositions from the manager.
.. seealso:: :py:func:`removeComposition()`
Removes and deletes all layouts from the manager.
.. seealso:: :py:func:`removeLayout()`
%End

QList< QgsComposition * > compositions() const;
@@ -72,16 +94,29 @@ class QgsLayoutManager : QObject
:rtype: list of QgsComposition
%End

QList< QgsLayout * > layouts() const;
%Docstring
Returns a list of all layouts contained in the manager.
:rtype: list of QgsLayout
%End

QgsComposition *compositionByName( const QString &name ) const;
%Docstring
Returns the composition with a matching name, or None if no matching compositions
were found.
:rtype: QgsComposition
%End

QgsLayout *layoutByName( const QString &name ) const;
%Docstring
Returns the layout with a matching name, or None if no matching layouts
were found.
:rtype: QgsLayout
%End

bool readXml( const QDomElement &element, const QDomDocument &doc );
%Docstring
Reads the manager's state from a DOM element, restoring all compositions
Reads the manager's state from a DOM element, restoring all layouts
present in the XML document.
.. seealso:: :py:func:`writeXml()`
:rtype: bool
@@ -109,38 +144,78 @@ class QgsLayoutManager : QObject
:rtype: QgsComposition
%End

QString generateUniqueTitle() const;
QgsLayout *duplicateLayout( const QgsLayout *layout, const QString &newName );
%Docstring
Duplicates an existing ``layout`` from the manager. The new
layout will automatically be stored in the manager.
Returns new the layout if duplication was successful.
:rtype: QgsLayout
%End

QString generateUniqueComposerTitle() const;
%Docstring
Generates a unique title for a new composition, which does not
clash with any already contained by the manager.
:rtype: str
%End

QString generateUniqueTitle() const;
%Docstring
Generates a unique title for a new layout, which does not
clash with any already contained by the manager.
:rtype: str
%End

signals:

void compositionAboutToBeAdded( const QString &name );
%Docstring
Emitted when a composition is about to be added to the manager
%End

void layoutAboutToBeAdded( const QString &name );
%Docstring
Emitted when a layout is about to be added to the manager
%End

void compositionAdded( const QString &name );
%Docstring
Emitted when a composition has been added to the manager
%End

void layoutAdded( const QString &name );
%Docstring
Emitted when a layout has been added to the manager
%End

void compositionRemoved( const QString &name );
%Docstring
Emitted when a composition was removed from the manager
%End

void layoutRemoved( const QString &name );
%Docstring
Emitted when a layout was removed from the manager
%End

void compositionAboutToBeRemoved( const QString &name );
%Docstring
Emitted when a composition is about to be removed from the manager
%End

void layoutAboutToBeRemoved( const QString &name );
%Docstring
Emitted when a layout is about to be removed from the manager
%End

void compositionRenamed( QgsComposition *composition, const QString &newName );
%Docstring
Emitted when a composition is renamed
%End

void layoutRenamed( QgsLayout *layout, const QString &newName );
%Docstring
Emitted when a layout is renamed
%End

};
@@ -49,6 +49,13 @@ class QgsLayout : QGraphicsScene, QgsExpressionContextGenerator, QgsLayoutUndoOb
a new layout.
%End

void clear();
%Docstring
Clears the layout.

Calling this method removes all items and pages from the layout.
%End

QgsProject *project() const;
%Docstring
The project associated with the layout. Used to get access to layers, map themes,
@@ -171,10 +178,14 @@ class QgsLayout : QGraphicsScene, QgsExpressionContextGenerator, QgsLayoutUndoOb
which deferred z-order updates.
%End

QgsLayoutItem *itemByUuid( const QString &uuid );
QgsLayoutItem *itemByUuid( const QString &uuid, bool includeTemplateUuids = false );
%Docstring
Returns the layout item with matching ``uuid`` unique identifier, or a None
if a matching item could not be found.

If ``includeTemplateUuids`` is true, then item's QgsLayoutItem.templateUuid()
will also be tested when trying to match the uuid.

.. seealso:: :py:func:`multiFrameByUuid()`
:rtype: QgsLayoutItem
%End
@@ -410,6 +421,28 @@ class QgsLayout : QGraphicsScene, QgsExpressionContextGenerator, QgsLayoutUndoOb
:rtype: list of QgsLayoutMultiFrame
%End

bool saveAsTemplate( const QString &path, const QgsReadWriteContext &context ) const;
%Docstring
Saves the layout as a template at the given file ``path``.
Returns true if save was successful.
.. seealso:: :py:func:`loadFromTemplate()`
:rtype: bool
%End

QList< QgsLayoutItem * > loadFromTemplate( const QDomDocument &document, const QgsReadWriteContext &context, bool clearExisting = true, bool *ok /Out/ = 0 );
%Docstring
Load a layout template ``document``.

By default this method will clear all items from the existing layout and real all layout
settings from the template. Setting ``clearExisting`` to false will only add new items
from the template, without overwriting the existing items or layout settings.

If ``ok`` is specified, it will be set to true if the load was successful.

Returns a list of loaded items.
:rtype: list of QgsLayoutItem
%End

QDomElement writeXml( QDomDocument &document, const QgsReadWriteContext &context ) const;
%Docstring
Returns the layout's state encapsulated in a DOM element.
@@ -424,6 +457,23 @@ class QgsLayout : QGraphicsScene, QgsExpressionContextGenerator, QgsLayoutUndoOb
:rtype: bool
%End

QList< QgsLayoutItem * > addItemsFromXml( const QDomElement &parentElement, const QDomDocument &document,
const QgsReadWriteContext &context,
QPointF *position = 0, bool pasteInPlace = false );
%Docstring
Add items from an XML representation to the layout. Used for project file reading and pasting items from clipboard.

The ``position`` argument is optional, and if it is not specified the items will be restored to their
original position from the XML serialization. If specified, the items will be positioned such that the top-left
bounds of all added items is located at this ``position``.

The ``pasteInPlace`` argument determines whether the serialized position should be respected, but remapped to the
origin of the page corresponding to the page at ``position``.

A list of the newly added items is returned.
:rtype: list of QgsLayoutItem
%End

QgsLayoutUndoStack *undoStack();
%Docstring
Returns a pointer to the layout's undo stack, which manages undo/redo states for the layout
@@ -491,6 +541,12 @@ class QgsLayout : QGraphicsScene, QgsExpressionContextGenerator, QgsLayoutUndoOb
and updated.
%End

void nameChanged( const QString &name );
%Docstring
Emitted when the layout's name is changed.
.. seealso:: :py:func:`setName()`
%End

};


@@ -35,8 +35,6 @@ class QgsLayoutFrame: QgsLayoutItem

virtual int type() const;

virtual QString stringType() const;

virtual QString uuid() const;


0 comments on commit a12673c

Please sign in to comment.
You can’t perform that action at this time.