Skip to content

Commit

Permalink
Pass project when creating relation from Xml
Browse files Browse the repository at this point in the history
    Fix dependency inconsistency to project from QgsRelationManager
    by forcing  'QgsRelation::createFromXml' to rely on project passed
    to 'QgsRelationManager' instead of using 'QgisProject::instance()'
  • Loading branch information
dmarteau committed Dec 20, 2019
1 parent 602febc commit 5bf8d2c
Show file tree
Hide file tree
Showing 15 changed files with 1,138 additions and 11 deletions.
9 changes: 7 additions & 2 deletions python/core/auto_generated/qgsrelation.sip.in
Expand Up @@ -11,7 +11,6 @@




class QgsRelation
{

Expand All @@ -37,6 +36,11 @@ Default constructor. Creates an invalid relation.
%End
~QgsRelation();

QgsRelation( const QgsRelationContext &context );
%Docstring
Constructor with context. Creates an invalid relation.
%End

QgsRelation( const QgsRelation &other );
%Docstring
Copies a relation.
Expand All @@ -45,12 +49,13 @@ changed.
%End


static QgsRelation createFromXml( const QDomNode &node, QgsReadWriteContext &context );
static QgsRelation createFromXml( const QDomNode &node, QgsReadWriteContext &context, const QgsRelationContext &relcontext = QgsRelationContext() );
%Docstring
Creates a relation from an XML structure. Used for reading .qgs projects.

:param node: The dom node containing the relation information
:param context: to pass project translator
:param context: a relation context

:return: A relation
%End
Expand Down
56 changes: 56 additions & 0 deletions python/core/auto_generated/qgsrelationcontext.sip.in
@@ -0,0 +1,56 @@
/************************************************************************
* This file has been generated automatically from *
* *
* src/core/qgsrelationcontext.h *
* *
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
************************************************************************/





class QgsRelationContext
{
%Docstring
Context for relations. Used to resolve layers from projects.

.. versionadded:: 3.11
%End

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

QgsRelationContext( QgsProject *project = 0 );
%Docstring
Constructor for QgsRelationContext.
%End

const QgsProject *project() const;
%Docstring
Gets the associated project

If there is no associated project, then it will return the global
project instance
%End

~QgsRelationContext();

QgsRelationContext( const QgsRelationContext &other );
%Docstring
Copy constructor
%End


};


/************************************************************************
* This file has been generated automatically from *
* *
* src/core/qgsrelationcontext.h *
* *
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
************************************************************************/
5 changes: 5 additions & 0 deletions python/core/auto_generated/qgsrelationmanager.sip.in
Expand Up @@ -26,6 +26,11 @@ This class manages a set of relations between layers.
Constructor for QgsRelationManager.

:param project: associated project (used to notify project of changes)
%End

QgsRelationContext context() const;
%Docstring
Gets the relation context
%End

void setRelations( const QList<QgsRelation> &relations );
Expand Down
1 change: 1 addition & 0 deletions python/core/core_auto.sip
Expand Up @@ -163,6 +163,7 @@
%Include auto_generated/qgsreadwritecontext.sip
%Include auto_generated/qgsreadwritelocker.sip
%Include auto_generated/qgsrelation.sip
%Include auto_generated/qgsrelationcontext.sip
%Include auto_generated/qgsrelationmanager.sip
%Include auto_generated/qgsrenderchecker.sip
%Include auto_generated/qgsrendercontext.sip
Expand Down
2 changes: 2 additions & 0 deletions src/core/CMakeLists.txt
Expand Up @@ -339,6 +339,7 @@ SET(QGIS_CORE_SRCS
qgsreadwritecontext.cpp
qgsreadwritelocker.cpp
qgsrelation.cpp
qgsrelationcontext.cpp
qgsweakrelation.cpp
qgsrelationmanager.cpp
qgsrenderchecker.cpp
Expand Down Expand Up @@ -841,6 +842,7 @@ SET(QGIS_CORE_HDRS
qgsreadwritecontext.h
qgsreadwritelocker.h
qgsrelation.h
qgsrelationcontext.h
qgsweakrelation.h
qgsrelationmanager.h
qgsrenderchecker.h
Expand Down
16 changes: 12 additions & 4 deletions src/core/qgsrelation.cpp
Expand Up @@ -27,20 +27,28 @@ QgsRelation::QgsRelation()
{
}

QgsRelation::QgsRelation( const QgsRelationContext &context )
: d( new QgsRelationPrivate() )
, mContext( context )
{
}

QgsRelation::~QgsRelation() = default;

QgsRelation::QgsRelation( const QgsRelation &other )
: d( other.d )
, mContext( other.mContext )
{
}

QgsRelation &QgsRelation::operator=( const QgsRelation &other )
{
d = other.d;
mContext = other.mContext;
return *this;
}

QgsRelation QgsRelation::createFromXml( const QDomNode &node, QgsReadWriteContext &context )
QgsRelation QgsRelation::createFromXml( const QDomNode &node, QgsReadWriteContext &context, const QgsRelationContext &relationContext )
{
QDomElement elem = node.toElement();

Expand All @@ -49,15 +57,15 @@ QgsRelation QgsRelation::createFromXml( const QDomNode &node, QgsReadWriteContex
QgsLogger::warning( QApplication::translate( "QgsRelation", "Cannot create relation. Unexpected tag '%1'" ).arg( elem.tagName() ) );
}

QgsRelation relation;
QgsRelation relation( relationContext );

QString referencingLayerId = elem.attribute( QStringLiteral( "referencingLayer" ) );
QString referencedLayerId = elem.attribute( QStringLiteral( "referencedLayer" ) );
QString id = elem.attribute( QStringLiteral( "id" ) );
QString name = context.projectTranslator()->translate( QStringLiteral( "project:relations" ), elem.attribute( QStringLiteral( "name" ) ) );
QString strength = elem.attribute( QStringLiteral( "strength" ) );

const QMap<QString, QgsMapLayer *> &mapLayers = QgsProject::instance()->mapLayers();
QMap<QString, QgsMapLayer *> mapLayers = relationContext.project()->mapLayers();

QgsMapLayer *referencingLayer = mapLayers[referencingLayerId];
QgsMapLayer *referencedLayer = mapLayers[referencedLayerId];
Expand Down Expand Up @@ -355,7 +363,7 @@ QString QgsRelation::resolveReferencingField( const QString &referencedField ) c

void QgsRelation::updateRelationStatus()
{
const QMap<QString, QgsMapLayer *> &mapLayers = QgsProject::instance()->mapLayers();
const QMap<QString, QgsMapLayer *> &mapLayers = mContext.project()->mapLayers();

d->mReferencingLayer = qobject_cast<QgsVectorLayer *>( mapLayers[d->mReferencingLayerId] );
d->mReferencedLayer = qobject_cast<QgsVectorLayer *>( mapLayers[d->mReferencedLayerId] );
Expand Down
12 changes: 10 additions & 2 deletions src/core/qgsrelation.h
Expand Up @@ -23,6 +23,7 @@
#include "qgis_core.h"
#include "qgsfields.h"
#include "qgsreadwritecontext.h"
#include "qgsrelationcontext.h"

#include "qgis_sip.h"

Expand All @@ -33,7 +34,6 @@ class QgsAttributes;
class QgsVectorLayer;
class QgsRelationPrivate;


/**
* \ingroup core
* \class QgsRelation
Expand Down Expand Up @@ -96,6 +96,11 @@ class CORE_EXPORT QgsRelation
QgsRelation();
~QgsRelation();

/**
* Constructor with context. Creates an invalid relation.
*/
QgsRelation( const QgsRelationContext &context );

/**
* Copies a relation.
* This makes a shallow copy, relations are implicitly shared and only duplicated when the copy is
Expand All @@ -115,10 +120,11 @@ class CORE_EXPORT QgsRelation
*
* \param node The dom node containing the relation information
* \param context to pass project translator
* \param context a relation context
*
* \returns A relation
*/
static QgsRelation createFromXml( const QDomNode &node, QgsReadWriteContext &context );
static QgsRelation createFromXml( const QDomNode &node, QgsReadWriteContext &context, const QgsRelationContext &relcontext = QgsRelationContext() );

/**
* Writes a relation to an XML structure. Used for saving .qgs projects
Expand Down Expand Up @@ -378,6 +384,8 @@ class CORE_EXPORT QgsRelation
private:

mutable QExplicitlySharedDataPointer<QgsRelationPrivate> d;

QgsRelationContext mContext;
};

// Register QgsRelation for usage with QVariant
Expand Down
46 changes: 46 additions & 0 deletions src/core/qgsrelationcontext.cpp
@@ -0,0 +1,46 @@
/***************************************************************************
qgsrelationcontext.cpp
--------------------------------------
Date : 20.12.2019
Copyright : (C) 2019 David Marteau
Email : dmarteau at 3liz 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 "qgsproject.h"
#include "qgsrelationcontext.h"

QgsRelationContext::QgsRelationContext( QgsProject *project )
: mProject( project )
{
}

QgsRelationContext::~QgsRelationContext() = default;

QgsRelationContext::QgsRelationContext( const QgsRelationContext &other )
: mProject( other.mProject )
{
}

QgsRelationContext &QgsRelationContext::operator=( const QgsRelationContext &other )
{
mProject = other.mProject;
return *this;
}

const QgsProject *QgsRelationContext::project() const
{
if ( mProject )
{
return mProject;
}

// Fallback to qgis instance
return QgsProject::instance();
}

66 changes: 66 additions & 0 deletions src/core/qgsrelationcontext.h
@@ -0,0 +1,66 @@
/***************************************************************************
qgsrelationcontext.h
--------------------------------------
Date : 20.12.2019
Copyright : (C) 2019 David Marteau
Email : dmarteau at 3liz 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 QGSRELATIONCONTEXT_H
#define QGSRELATIONCONTEXT_H

#include "qgis_core.h"
#include "qgis_sip.h"

class QgsProject;


/**
* \ingroup core
* \class QgsRelationContext
* Context for relations. Used to resolve layers from projects.
* \since QGIS 3.11
*/
class CORE_EXPORT QgsRelationContext
{
public:

/**
* Constructor for QgsRelationContext.
*/
QgsRelationContext( QgsProject *project = nullptr );

/**
* Gets the associated project
*
* If there is no associated project, then it will return the global
* project instance
*/
const QgsProject *project() const;

~QgsRelationContext();

/**
* Copy constructor
*/
QgsRelationContext( const QgsRelationContext &other );

/**
* Assignment operator
*/
QgsRelationContext &operator=( const QgsRelationContext &other );

private:
QgsProject *mProject = nullptr;

};

#endif // QGSRELATIONCONTEXT_H

14 changes: 11 additions & 3 deletions src/core/qgsrelationmanager.cpp
Expand Up @@ -25,7 +25,7 @@ QgsRelationManager::QgsRelationManager( QgsProject *project )
: QObject( project )
, mProject( project )
{
if ( mProject )
if ( project )
{
// TODO: QGIS 4 remove: relations are now stored with the layer style
connect( project, &QgsProject::readProjectWithContext, this, &QgsRelationManager::readProject );
Expand All @@ -36,6 +36,11 @@ QgsRelationManager::QgsRelationManager( QgsProject *project )
}
}

QgsRelationContext QgsRelationManager::context() const
{
return QgsRelationContext( mProject );
}

void QgsRelationManager::setRelations( const QList<QgsRelation> &relations )
{
mRelations.clear();
Expand All @@ -59,9 +64,10 @@ void QgsRelationManager::addRelation( const QgsRelation &relation )
return;

mRelations.insert( relation.id(), relation );

if ( mProject )
{
mProject->setDirty( true );
}
emit changed();
}

Expand Down Expand Up @@ -179,12 +185,14 @@ void QgsRelationManager::readProject( const QDomDocument &doc, QgsReadWriteConte
QDomNodeList nodes = doc.elementsByTagName( QStringLiteral( "relations" ) );
if ( nodes.count() )
{
QgsRelationContext relcontext( mProject );

QDomNode node = nodes.item( 0 );
QDomNodeList relationNodes = node.childNodes();
int relCount = relationNodes.count();
for ( int i = 0; i < relCount; ++i )
{
addRelation( QgsRelation::createFromXml( relationNodes.at( i ), context ) );
addRelation( QgsRelation::createFromXml( relationNodes.at( i ), context, relcontext ) );
}
}
else
Expand Down

0 comments on commit 5bf8d2c

Please sign in to comment.