Skip to content

Commit

Permalink
[layouts] Fix some linked map items not correctly restored when
Browse files Browse the repository at this point in the history
loading projects.

Also remove some outdated TODOs

Fixes #17892, #17891
  • Loading branch information
nyalldawson committed Jan 22, 2018
1 parent f69c1cf commit 20f50fb
Show file tree
Hide file tree
Showing 21 changed files with 142 additions and 107 deletions.
1 change: 0 additions & 1 deletion python/core/layout/qgslayoutframe.sip.in
Expand Up @@ -62,7 +62,6 @@ Returns the parent multiframe for the frame.
virtual QgsLayoutSize fixedSize() const;



QRectF extent() const;
%Docstring
Returns the visible portion of the multi frame's content which
Expand Down
2 changes: 2 additions & 0 deletions python/core/layout/qgslayoutitemattributetable.sip.in
Expand Up @@ -292,6 +292,8 @@ be replaced by a line break.

virtual QgsExpressionContext createExpressionContext() const;

virtual void finalizeRestoreFromXml();


protected:

Expand Down
22 changes: 22 additions & 0 deletions python/core/layout/qgslayoutitemmapitem.sip.in
Expand Up @@ -48,6 +48,17 @@ Sets the map item state from a DOM document, where ``element`` is the DOM
node corresponding to a 'LayoutMapGrid' tag.

.. seealso:: :py:func:`writeXml`
%End

virtual void finalizeRestoreFromXml();
%Docstring
Called after all pending items have been restored from XML. Map items can use
this method to run steps which must take place after all items have been restored to the layout,
such as connecting to signals emitted by other items, which may not have existed in the layout
at the time readXml() was called. E.g. an overview can use this to connect to its linked
map item after restoration from XML.

.. seealso:: :py:func:`readXml`
%End

void setMap( QgsLayoutItemMap *map );
Expand Down Expand Up @@ -156,6 +167,17 @@ Sets the item stack's state from a DOM document, where ``element`` is a DOM node
Returns true if read was successful.

.. seealso:: :py:func:`writeXml`
%End

virtual void finalizeRestoreFromXml();
%Docstring
Called after all pending items have been restored from XML. Map item stacks can use
this method to run steps which must take place after all items have been restored to the layout,
such as connecting to signals emitted by other items, which may not have existed in the layout
at the time readXml() was called. E.g. an overview can use this to connect to its linked
map item after restoration from XML.

.. seealso:: :py:func:`readXml`
%End

void drawItems( QPainter *painter );
Expand Down
2 changes: 2 additions & 0 deletions python/core/layout/qgslayoutitemmapoverview.sip.in
Expand Up @@ -138,6 +138,8 @@ Constructor for QgsLayoutItemMapOverview.

virtual bool readXml( const QDomElement &itemElem, const QDomDocument &doc, const QgsReadWriteContext &context );

virtual void finalizeRestoreFromXml();

virtual bool usesAdvancedEffects() const;


Expand Down
18 changes: 0 additions & 18 deletions src/core/layout/qgslayoutframe.cpp
Expand Up @@ -209,21 +209,3 @@ bool QgsLayoutFrame::readPropertiesFromElement( const QDomElement &itemElem, con
mMultiFrame = mLayout->multiFrameByUuid( mMultiFrameUuid );
return true;
}

#if 0 //TODO
void QgsLayoutFrame::beginItemCommand( const QString &text )
{
if ( mComposition )
{
mComposition->beginMultiFrameCommand( multiFrame(), text );
}
}

void QgsLayoutFrame::endItemCommand()
{
if ( mComposition )
{
mComposition->endMultiFrameCommand();
}
}
#endif
5 changes: 0 additions & 5 deletions src/core/layout/qgslayoutframe.h
Expand Up @@ -68,11 +68,6 @@ class CORE_EXPORT QgsLayoutFrame: public QgsLayoutItem
QgsLayoutSize minimumSize() const override;
QgsLayoutSize fixedSize() const override;

#if 0 //TODO
void beginItemCommand( const QString &text ) override;
void endItemCommand() override;
#endif

/**
* Returns the visible portion of the multi frame's content which
* is shown in this frame, in layout units.
Expand Down
4 changes: 0 additions & 4 deletions src/core/layout/qgslayoutitem.cpp
Expand Up @@ -699,10 +699,6 @@ bool QgsLayoutItem::readXml( const QDomElement &element, const QDomDocument &doc
bool alphaOk = false;
int penRed, penGreen, penBlue, penAlpha;

#if 0 // TODO, old style
double penWidth;
penWidth = element.attribute( QStringLiteral( "outlineWidth" ) ).toDouble( &widthOk );
#endif
penRed = frameColorElem.attribute( QStringLiteral( "red" ) ).toDouble( &redOk );
penGreen = frameColorElem.attribute( QStringLiteral( "green" ) ).toDouble( &greenOk );
penBlue = frameColorElem.attribute( QStringLiteral( "blue" ) ).toDouble( &blueOk );
Expand Down
29 changes: 17 additions & 12 deletions src/core/layout/qgslayoutitemattributetable.cpp
Expand Up @@ -538,6 +538,19 @@ QgsExpressionContext QgsLayoutItemAttributeTable::createExpressionContext() cons
return context;
}

void QgsLayoutItemAttributeTable::finalizeRestoreFromXml()
{
if ( !mMap && !mMapUuid.isEmpty() && mLayout )
{
mMap = qobject_cast< QgsLayoutItemMap *>( mLayout->itemByUuid( mMapUuid, true ) );
if ( mMap )
{
//if we have found a valid map item, listen out to extent changes on it and refresh the table
connect( mMap, &QgsLayoutItemMap::extentChanged, this, &QgsLayoutTable::refreshAttributes );
}
}
}

QVariant QgsLayoutItemAttributeTable::replaceWrapChar( const QVariant &variant ) const
{
//avoid converting variants to string if not required (try to maintain original type for sorting)
Expand Down Expand Up @@ -683,21 +696,13 @@ bool QgsLayoutItemAttributeTable::readPropertiesFromElement( const QDomElement &
mWrapString = itemElem.attribute( QStringLiteral( "wrapString" ) );

//map
QString mapUuid = itemElem.attribute( QStringLiteral( "mapUuid" ) );
if ( !mLayout || mapUuid.isEmpty() )
{
mMap = nullptr;
}
else
{
mMap = qobject_cast< QgsLayoutItemMap *>( mLayout->itemByUuid( mapUuid, true ) );
}

mMapUuid = itemElem.attribute( QStringLiteral( "mapUuid" ) );
if ( mMap )
{
//if we have found a valid map item, listen out to extent changes on it and refresh the table
connect( mMap, &QgsLayoutItemMap::extentChanged, this, &QgsLayoutTable::refreshAttributes );
disconnect( mMap, &QgsLayoutItemMap::extentChanged, this, &QgsLayoutTable::refreshAttributes );
mMap = nullptr;
}
// setting new mMap occurs in finalizeRestoreFromXml

//vector layer
QString layerId = itemElem.attribute( QStringLiteral( "vectorLayer" ) );
Expand Down
2 changes: 2 additions & 0 deletions src/core/layout/qgslayoutitemattributetable.h
Expand Up @@ -290,6 +290,7 @@ class CORE_EXPORT QgsLayoutItemAttributeTable: public QgsLayoutTable
bool getTableContents( QgsLayoutTableContents &contents ) override SIP_SKIP;

QgsExpressionContext createExpressionContext() const override;
void finalizeRestoreFromXml() override;

protected:

Expand All @@ -310,6 +311,7 @@ class CORE_EXPORT QgsLayoutItemAttributeTable: public QgsLayoutTable

//! Associated map (used to display the visible features)
QgsLayoutItemMap *mMap = nullptr;
QString mMapUuid;

//! Maximum number of features that is displayed
int mMaximumNumberOfFeatures = 30;
Expand Down
49 changes: 28 additions & 21 deletions src/core/layout/qgslayoutitemlegend.cpp
Expand Up @@ -126,12 +126,6 @@ void QgsLayoutItemLegend::paint( QPainter *painter, const QStyleOptionGraphicsIt

void QgsLayoutItemLegend::finalizeRestoreFromXml()
{
#if 0 //TODO
if ( mMapId != -1 && mMapUuid.isEmpty() )
{
setMap( mComposition->getComposerMapById( itemElem.attribute( QStringLiteral( "map" ) ).toInt() ) );
}
#endif
if ( !mMapUuid.isEmpty() )
{
setLinkedMap( qobject_cast< QgsLayoutItemMap * >( mLayout->itemByUuid( mMapUuid, true ) ) );
Expand Down Expand Up @@ -211,7 +205,6 @@ void QgsLayoutItemLegend::setCustomLayerTree( QgsLayerTree *rootGroup )
mCustomLayerTree.reset( rootGroup );
}


void QgsLayoutItemLegend::setAutoUpdateModel( bool autoUpdate )
{
if ( autoUpdate == autoUpdateModel() )
Expand Down Expand Up @@ -584,16 +577,14 @@ bool QgsLayoutItemLegend::readPropertiesFromElement( const QDomElement &itemElem
//composer map
mLegendFilterByMap = itemElem.attribute( QStringLiteral( "legendFilterByMap" ), QStringLiteral( "0" ) ).toInt();

mMapId = -1;
mMapUuid.clear();
if ( !itemElem.attribute( QStringLiteral( "map" ) ).isEmpty() )
{
mMapId = itemElem.attribute( QStringLiteral( "map" ) ).toInt();
}
if ( !itemElem.attribute( QStringLiteral( "map_uuid" ) ).isEmpty() )
{
mMapUuid = itemElem.attribute( QStringLiteral( "map_uuid" ) );
}
// disconnect current map
setupMapConnections( mMap, false );
mMap = nullptr;

mFilterOutAtlas = itemElem.attribute( QStringLiteral( "legendFilterByAtlas" ), QStringLiteral( "0" ) ).toInt();

Expand Down Expand Up @@ -638,24 +629,40 @@ QString QgsLayoutItemLegend::displayName() const
}
}


void QgsLayoutItemLegend::setupMapConnections( QgsLayoutItemMap *map, bool connectSlots )
{
if ( !map )
return;

if ( !connectSlots )
{
disconnect( map, &QObject::destroyed, this, &QgsLayoutItemLegend::invalidateCurrentMap );
disconnect( map, &QgsLayoutObject::changed, this, &QgsLayoutItemLegend::updateFilterByMapAndRedraw );
disconnect( map, &QgsLayoutItemMap::extentChanged, this, &QgsLayoutItemLegend::updateFilterByMapAndRedraw );
disconnect( map, &QgsLayoutItemMap::layerStyleOverridesChanged, this, &QgsLayoutItemLegend::mapLayerStyleOverridesChanged );
}
else
{
connect( map, &QObject::destroyed, this, &QgsLayoutItemLegend::invalidateCurrentMap );
connect( map, &QgsLayoutObject::changed, this, &QgsLayoutItemLegend::updateFilterByMapAndRedraw );
connect( map, &QgsLayoutItemMap::extentChanged, this, &QgsLayoutItemLegend::updateFilterByMapAndRedraw );
connect( map, &QgsLayoutItemMap::layerStyleOverridesChanged, this, &QgsLayoutItemLegend::mapLayerStyleOverridesChanged );
}
}

void QgsLayoutItemLegend::setLinkedMap( QgsLayoutItemMap *map )
{
if ( mMap )
{
disconnect( mMap, &QObject::destroyed, this, &QgsLayoutItemLegend::invalidateCurrentMap );
disconnect( mMap, &QgsLayoutObject::changed, this, &QgsLayoutItemLegend::updateFilterByMapAndRedraw );
disconnect( mMap, &QgsLayoutItemMap::extentChanged, this, &QgsLayoutItemLegend::updateFilterByMapAndRedraw );
disconnect( mMap, &QgsLayoutItemMap::layerStyleOverridesChanged, this, &QgsLayoutItemLegend::mapLayerStyleOverridesChanged );
setupMapConnections( mMap, false );
}

mMap = map;

if ( map )
if ( mMap )
{
connect( map, &QObject::destroyed, this, &QgsLayoutItemLegend::invalidateCurrentMap );
connect( map, &QgsLayoutObject::changed, this, &QgsLayoutItemLegend::updateFilterByMapAndRedraw );
connect( map, &QgsLayoutItemMap::extentChanged, this, &QgsLayoutItemLegend::updateFilterByMapAndRedraw );
connect( map, &QgsLayoutItemMap::layerStyleOverridesChanged, this, &QgsLayoutItemLegend::mapLayerStyleOverridesChanged );
setupMapConnections( mMap, true );
}

updateFilterByMap();
Expand Down
3 changes: 2 additions & 1 deletion src/core/layout/qgslayoutitemlegend.h
Expand Up @@ -472,6 +472,8 @@ class CORE_EXPORT QgsLayoutItemLegend : public QgsLayoutItem
//! use new custom layer tree and update model. if new root is null pointer, will use project's tree
void setCustomLayerTree( QgsLayerTree *rootGroup );

void setupMapConnections( QgsLayoutItemMap *map, bool connect = true );

std::unique_ptr< QgsLegendModel > mLegendModel;
std::unique_ptr< QgsLayerTreeGroup > mCustomLayerTree;

Expand All @@ -481,7 +483,6 @@ class CORE_EXPORT QgsLayoutItemLegend : public QgsLayoutItem
int mColumnCount = 1;

QString mMapUuid;
int mMapId = -1;
QgsLayoutItemMap *mMap = nullptr;

bool mLegendFilterByMap = false;
Expand Down
7 changes: 2 additions & 5 deletions src/core/layout/qgslayoutitemmap.cpp
Expand Up @@ -1110,11 +1110,8 @@ void QgsLayoutItemMap::finalizeRestoreFromXml()
{
assignFreeId();

const QList<QgsLayoutItemMapOverview * > allOverviews = overviews()->asList();
for ( QgsLayoutItemMapOverview *overview : allOverviews )
{
overview->connectSignals();
}
mOverviewStack->finalizeRestoreFromXml();
mGridStack->finalizeRestoreFromXml();
}

void QgsLayoutItemMap::setMoveContentPreviewOffset( double xOffset, double yOffset )
Expand Down
12 changes: 12 additions & 0 deletions src/core/layout/qgslayoutitemmapitem.cpp
Expand Up @@ -47,6 +47,10 @@ bool QgsLayoutItemMapItem::readXml( const QDomElement &itemElem, const QDomDocum
return true;
}

void QgsLayoutItemMapItem::finalizeRestoreFromXml()
{
}

void QgsLayoutItemMapItem::setMap( QgsLayoutItemMap *map )
{
mMap = map;
Expand Down Expand Up @@ -195,6 +199,14 @@ bool QgsLayoutItemMapItemStack::writeXml( QDomElement &elem, QDomDocument &doc,
return true;
}

void QgsLayoutItemMapItemStack::finalizeRestoreFromXml()
{
for ( QgsLayoutItemMapItem *item : mItems )
{
item->finalizeRestoreFromXml();
}
}

void QgsLayoutItemMapItemStack::drawItems( QPainter *painter )
{
if ( !painter )
Expand Down
20 changes: 20 additions & 0 deletions src/core/layout/qgslayoutitemmapitem.h
Expand Up @@ -61,6 +61,16 @@ class CORE_EXPORT QgsLayoutItemMapItem : public QgsLayoutObject
*/
virtual bool readXml( const QDomElement &element, const QDomDocument &doc, const QgsReadWriteContext &context );

/**
* Called after all pending items have been restored from XML. Map items can use
* this method to run steps which must take place after all items have been restored to the layout,
* such as connecting to signals emitted by other items, which may not have existed in the layout
* at the time readXml() was called. E.g. an overview can use this to connect to its linked
* map item after restoration from XML.
* \see readXml()
*/
virtual void finalizeRestoreFromXml();

/**
* Sets the corresponding layout \a map for the item.
* \see map()
Expand Down Expand Up @@ -165,6 +175,16 @@ class CORE_EXPORT QgsLayoutItemMapItemStack
*/
virtual bool readXml( const QDomElement &element, const QDomDocument &doc, const QgsReadWriteContext &context ) = 0;

/**
* Called after all pending items have been restored from XML. Map item stacks can use
* this method to run steps which must take place after all items have been restored to the layout,
* such as connecting to signals emitted by other items, which may not have existed in the layout
* at the time readXml() was called. E.g. an overview can use this to connect to its linked
* map item after restoration from XML.
* \see readXml()
*/
virtual void finalizeRestoreFromXml();

/**
* Draws the items from the stack on a specified \a painter.
*/
Expand Down
14 changes: 11 additions & 3 deletions src/core/layout/qgslayoutitemmapoverview.cpp
Expand Up @@ -178,9 +178,9 @@ bool QgsLayoutItemMapOverview::readXml( const QDomElement &itemElem, const QDomD

bool ok = QgsLayoutItemMapItem::readXml( itemElem, doc, context );

#if 0 //TODO
setFrameMapUuid( itemElem.attribute( QStringLiteral( "frameMap" ), QStringLiteral( "-1" ) ).toInt() );
#endif
mFrameMapUuid = itemElem.attribute( QStringLiteral( "frameMap" ) );
setLinkedMap( nullptr );

mBlendMode = QgsPainting::getCompositionMode( static_cast< QgsPainting::BlendMode >( itemElem.attribute( QStringLiteral( "blendMode" ), QStringLiteral( "0" ) ).toUInt() ) );
mInverted = ( itemElem.attribute( QStringLiteral( "inverted" ), QStringLiteral( "0" ) ) != QLatin1String( "0" ) );
mCentered = ( itemElem.attribute( QStringLiteral( "centered" ), QStringLiteral( "0" ) ) != QLatin1String( "0" ) );
Expand All @@ -193,6 +193,14 @@ bool QgsLayoutItemMapOverview::readXml( const QDomElement &itemElem, const QDomD
return ok;
}

void QgsLayoutItemMapOverview::finalizeRestoreFromXml()
{
if ( !mFrameMapUuid.isEmpty() )
{
setLinkedMap( qobject_cast< QgsLayoutItemMap * >( mLayout->itemByUuid( mFrameMapUuid, true ) ) );
}
}

bool QgsLayoutItemMapOverview::usesAdvancedEffects() const
{
return mBlendMode != QPainter::CompositionMode_SourceOver;
Expand Down
2 changes: 2 additions & 0 deletions src/core/layout/qgslayoutitemmapoverview.h
Expand Up @@ -135,6 +135,7 @@ class CORE_EXPORT QgsLayoutItemMapOverview : public QgsLayoutItemMapItem
void draw( QPainter *painter ) override;
bool writeXml( QDomElement &elem, QDomDocument &doc, const QgsReadWriteContext &context ) const override;
bool readXml( const QDomElement &itemElem, const QDomDocument &doc, const QgsReadWriteContext &context ) override;
void finalizeRestoreFromXml() override;
bool usesAdvancedEffects() const override;

/**
Expand Down Expand Up @@ -224,6 +225,7 @@ class CORE_EXPORT QgsLayoutItemMapOverview : public QgsLayoutItemMapItem

QgsLayoutItemMapOverview() = delete;

QString mFrameMapUuid;
QPointer< QgsLayoutItemMap > mFrameMap;

//! Drawing style for overview farme
Expand Down

0 comments on commit 20f50fb

Please sign in to comment.