Move/rotate/hide/pin map tools are always available

This commit is contained in:
Blottiere Paul 2017-09-01 09:47:05 +01:00
parent ad1e15808f
commit 5b278d746e
20 changed files with 444 additions and 163 deletions

View File

@ -179,6 +179,32 @@ class QgsAuxiliaryLayer : QgsVectorLayer
:rtype: bool
%End
static int createProperty( QgsPalLayerSettings::Property p, const QString &providerId, QgsVectorLayer *vlayer );
%Docstring
Create if necessary a new auxiliary field for a PAL property and
activate this property in settings.
\param p The property to create
\param providerId The id of the provider to use
\param vlayer The vector layer
:return: The index of the auxiliary field or -1
:rtype: int
%End
static int createProperty( QgsDiagramLayerSettings::Property p, QgsVectorLayer *vlayer );
%Docstring
Create if necessary a new auxiliary field for a diagram's property and
activate this this property in settings.
\param p The property to create
\param providerId The id of the provider to use
\param vlayer The vector layer
:return: The index of the auxiliary field or -1
:rtype: int
%End
};

View File

@ -223,6 +223,7 @@ Try to find a rule given its unique key
:rtype: QgsRuleBasedLabeling.Rule
%End
QgsRuleBasedLabeling::Rule *clone() const /Factory/;
%Docstring
clone this rule, return new instance
@ -285,6 +286,16 @@ Create the instance from a DOM element with saved configuration
virtual QDomElement save( QDomDocument &doc, const QgsReadWriteContext &context ) const;
virtual QStringList subProviders() const;
virtual QgsPalLayerSettings settings( const QString &providerId = QString() ) const;
virtual void setSettings( QgsPalLayerSettings *settings /Transfer/, const QString &providerId = QString() );
%Docstring
Set pal settings for a specific provider (takes ownership).
\param settings Pal layer settings
\param providerId The id of the provider
.. versionadded:: 3.0
%End
virtual bool requiresAdvancedEffects() const;

View File

@ -1092,9 +1092,11 @@ Return the provider type for this layer
:rtype: int
%End
const QgsAbstractVectorLayerLabeling *labeling() const;
QgsAbstractVectorLayerLabeling *labeling();
%Docstring
Access to labeling configuration. May be null if labeling is not used.
.. versionadded:: 3.0
:rtype: QgsAbstractVectorLayerLabeling
%End

View File

@ -61,6 +61,16 @@ Get list of sub-providers within the layer's labeling.
:rtype: QgsPalLayerSettings
%End
virtual void setSettings( QgsPalLayerSettings *settings /Transfer/, const QString &providerId = QString() ) = 0;
%Docstring
Set pal settings for a specific provider (takes ownership).
\param settings Pal layer settings
\param providerId The id of the provider
.. versionadded:: 3.0
%End
virtual bool requiresAdvancedEffects() const = 0;
%Docstring
Returns true if drawing labels requires advanced effects like composition
@ -109,6 +119,17 @@ Constructs simple labeling configuration with given initial settings
virtual QgsAbstractVectorLayerLabeling *clone() const /Factory/;
virtual QDomElement save( QDomDocument &doc, const QgsReadWriteContext &context ) const;
virtual QgsPalLayerSettings settings( const QString &providerId = QString() ) const;
virtual void setSettings( QgsPalLayerSettings *settings /Transfer/, const QString &providerId = QString() );
%Docstring
Set pal settings (takes ownership).
\param settings Pal layer settings
\param providerId Unused parameter
.. versionadded:: 3.0
%End
virtual bool requiresAdvancedEffects() const;
virtual void toSld( QDomNode &parent, const QgsStringMap &props ) const;

View File

@ -10997,38 +10997,16 @@ void QgisApp::updateLabelToolButtons()
for ( QMap<QString, QgsMapLayer *>::iterator it = layers.begin(); it != layers.end(); ++it )
{
QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( it.value() );
if ( !vlayer || ( !vlayer->diagramsEnabled() && !vlayer->labelsEnabled() ) )
continue;
int colX, colY, colShow, colAng;
enablePin =
enablePin ||
( qobject_cast<QgsMapToolPinLabels *>( mMapTools.mPinLabels ) &&
( qobject_cast<QgsMapToolPinLabels *>( mMapTools.mPinLabels )->labelMoveable( vlayer, colX, colY )
|| qobject_cast<QgsMapToolPinLabels *>( mMapTools.mPinLabels )->diagramMoveable( vlayer, colX, colY ) ) );
enableShowHide =
enableShowHide ||
( qobject_cast<QgsMapToolShowHideLabels *>( mMapTools.mShowHideLabels ) &&
( qobject_cast<QgsMapToolShowHideLabels *>( mMapTools.mShowHideLabels )->labelCanShowHide( vlayer, colShow )
|| qobject_cast<QgsMapToolShowHideLabels *>( mMapTools.mShowHideLabels )->diagramCanShowHide( vlayer, colShow ) ) );
enableMove =
enableMove ||
( qobject_cast<QgsMapToolMoveLabel *>( mMapTools.mMoveLabel ) &&
( qobject_cast<QgsMapToolMoveLabel *>( mMapTools.mMoveLabel )->labelMoveable( vlayer, colX, colY )
|| qobject_cast<QgsMapToolMoveLabel *>( mMapTools.mMoveLabel )->diagramMoveable( vlayer, colX, colY ) ) );
enableRotate =
enableRotate ||
( qobject_cast<QgsMapToolRotateLabel *>( mMapTools.mRotateLabel ) &&
qobject_cast<QgsMapToolRotateLabel *>( mMapTools.mRotateLabel )->layerIsRotatable( vlayer, colAng ) );
if ( vlayer->isEditable() )
if ( vlayer && ( vlayer->diagramsEnabled() || vlayer->labelsEnabled() ) )
{
enablePin = true;
enableShowHide = true;
enableMove = true;
enableRotate = true;
enableChange = true;
if ( enablePin && enableShowHide && enableMove && enableRotate && enableChange )
break;
}
}
mActionPinLabels->setEnabled( enablePin );

View File

@ -626,7 +626,7 @@ bool QgsMapToolLabel::diagramMoveable( QgsVectorLayer *vlayer, int &xCol, int &y
bool QgsMapToolLabel::labelMoveable( QgsVectorLayer *vlayer, int &xCol, int &yCol ) const
{
if ( !vlayer || !vlayer->labeling() )
if ( !vlayer || !vlayer->isEditable() || !vlayer->labeling() )
{
return false;
}
@ -648,26 +648,7 @@ bool QgsMapToolLabel::labelMoveable( QgsVectorLayer *vlayer, const QgsPalLayerSe
//return !xColName.isEmpty() && !yColName.isEmpty();
xCol = vlayer->fields().lookupField( xColName );
yCol = vlayer->fields().lookupField( yColName );
// labels may be moveable even if layer is not editable when data defined
// columns come from auxiliary storage
if ( xCol >= 0 && yCol >= 0 )
{
bool xAuxiliaryField = vlayer->isAuxiliaryField( xCol );
bool yAuxiliaryField = vlayer->isAuxiliaryField( yCol );
if ( ! xAuxiliaryField || ! yAuxiliaryField )
{
if ( vlayer->isEditable() )
return true;
else
return false;
}
else
return true;
}
return false;
return ( xCol != -1 && yCol != -1 );
}
bool QgsMapToolLabel::layerCanPin( QgsVectorLayer *vlayer, int &xCol, int &yCol ) const
@ -679,7 +660,7 @@ bool QgsMapToolLabel::layerCanPin( QgsVectorLayer *vlayer, int &xCol, int &yCol
bool QgsMapToolLabel::labelCanShowHide( QgsVectorLayer *vlayer, int &showCol ) const
{
if ( !vlayer || !vlayer->labeling() )
if ( !vlayer || !vlayer->isEditable() || !vlayer->labeling() )
{
return false;
}
@ -689,20 +670,8 @@ bool QgsMapToolLabel::labelCanShowHide( QgsVectorLayer *vlayer, int &showCol ) c
QString fieldname = dataDefinedColumnName( QgsPalLayerSettings::Show,
vlayer->labeling()->settings( providerId ) );
showCol = vlayer->fields().lookupField( fieldname );
if ( showCol >= 0 )
{
bool auxiliaryField = vlayer->isAuxiliaryField( showCol );
if ( ! auxiliaryField )
{
if ( vlayer->isEditable() )
return true;
else
return false;
}
else
return true;
}
if ( showCol != -1 )
return true;
}
return false;
@ -773,14 +742,14 @@ QgsMapToolLabel::LabelDetails::LabelDetails( const QgsLabelPosition &p )
: pos( p )
{
layer = qobject_cast<QgsVectorLayer *>( QgsProject::instance()->mapLayer( pos.layerID ) );
if ( layer && layer->labeling() )
if ( layer && layer->labeling() && !p.isDiagram )
{
settings = layer->labeling()->settings( pos.providerID );
if ( p.isDiagram )
valid = layer->diagramsEnabled();
else
valid = true;
valid = true;
}
else if ( layer && layer->diagramsEnabled() && p.isDiagram )
{
valid = true;
}
if ( !valid )
@ -789,3 +758,69 @@ QgsMapToolLabel::LabelDetails::LabelDetails( const QgsLabelPosition &p )
settings = QgsPalLayerSettings();
}
}
bool QgsMapToolLabel::createAuxiliaryFields( QgsPalIndexes &indexes )
{
return createAuxiliaryFields( mCurrentLabel, indexes );
}
bool QgsMapToolLabel::createAuxiliaryFields( LabelDetails &details, QgsPalIndexes &indexes ) const
{
bool newAuxiliaryLayer = false;
QgsVectorLayer *vlayer = details.layer;
QString providerId = details.pos.providerID;
if ( !vlayer )
return newAuxiliaryLayer;
if ( !vlayer->auxiliaryLayer() )
{
QgsNewAuxiliaryLayerDialog dlg( vlayer );
dlg.exec();
newAuxiliaryLayer = true;
}
if ( !vlayer->auxiliaryLayer() )
return false;
Q_FOREACH ( const QgsPalLayerSettings::Property &p, mPalProperties )
{
indexes[p] = QgsAuxiliaryLayer::createProperty( p, providerId, vlayer );
}
details.settings = vlayer->labeling()->settings( providerId );
return newAuxiliaryLayer;
}
bool QgsMapToolLabel::createAuxiliaryFields( QgsDiagramIndexes &indexes )
{
return createAuxiliaryFields( mCurrentLabel, indexes );
}
bool QgsMapToolLabel::createAuxiliaryFields( LabelDetails &details, QgsDiagramIndexes &indexes )
{
bool newAuxiliaryLayer = false;
QgsVectorLayer *vlayer = details.layer;
if ( !vlayer )
return newAuxiliaryLayer;
if ( !vlayer->auxiliaryLayer() )
{
QgsNewAuxiliaryLayerDialog dlg( vlayer );
dlg.exec();
newAuxiliaryLayer = true;
}
if ( !vlayer->auxiliaryLayer() )
return false;
Q_FOREACH ( const QgsDiagramLayerSettings::Property &p, mDiagramProperties )
{
indexes[p] = QgsAuxiliaryLayer::createProperty( p, vlayer );
}
return newAuxiliaryLayer;
}

View File

@ -20,10 +20,15 @@
#include "qgsmaptool.h"
#include "qgspallabeling.h"
#include "qgsnewauxiliarylayerdialog.h"
#include "qgsauxiliarystorage.h"
#include "qgis_app.h"
class QgsRubberBand;
typedef QMap<QgsPalLayerSettings::Property, int> QgsPalIndexes;
typedef QMap<QgsDiagramLayerSettings::Property, int> QgsDiagramIndexes;
//! Base class for map tools that modify label properties
class APP_EXPORT QgsMapToolLabel: public QgsMapTool
{
@ -175,6 +180,14 @@ class APP_EXPORT QgsMapToolLabel: public QgsMapTool
\since QGIS 2.16
*/
bool isPinned();
bool createAuxiliaryFields( QgsPalIndexes &palIndexes );
bool createAuxiliaryFields( LabelDetails &details, QgsPalIndexes &palIndexes ) const;
bool createAuxiliaryFields( QgsDiagramIndexes &diagIndexes );
bool createAuxiliaryFields( LabelDetails &details, QgsDiagramIndexes &diagIndexes );
QList<QgsPalLayerSettings::Property> mPalProperties;
QList<QgsDiagramLayerSettings::Property> mDiagramProperties;
};
#endif // QGSMAPTOOLLABEL_H

View File

@ -27,6 +27,12 @@ QgsMapToolMoveLabel::QgsMapToolMoveLabel( QgsMapCanvas *canvas )
, mClickOffsetY( 0 )
{
mToolName = tr( "Move label" );
mPalProperties << QgsPalLayerSettings::PositionX;
mPalProperties << QgsPalLayerSettings::PositionY;
mDiagramProperties << QgsDiagramLayerSettings::PositionX;
mDiagramProperties << QgsDiagramLayerSettings::PositionY;
}
void QgsMapToolMoveLabel::canvasPressEvent( QgsMapMouseEvent *e )
@ -49,8 +55,29 @@ void QgsMapToolMoveLabel::canvasPressEvent( QgsMapMouseEvent *e )
}
int xCol, yCol;
if ( labelMoveable( vlayer, mCurrentLabel.settings, xCol, yCol ) ||
diagramMoveable( vlayer, xCol, yCol ) )
if ( !mCurrentLabel.pos.isDiagram && !labelMoveable( vlayer, mCurrentLabel.settings, xCol, yCol ) )
{
QgsPalIndexes indexes;
if ( createAuxiliaryFields( indexes ) )
return;
xCol = indexes[ QgsPalLayerSettings::PositionX ];
yCol = indexes[ QgsPalLayerSettings::PositionY ];
}
else if ( mCurrentLabel.pos.isDiagram && !diagramMoveable( vlayer, xCol, yCol ) )
{
QgsDiagramIndexes indexes;
if ( createAuxiliaryFields( indexes ) )
return;
xCol = indexes[ QgsDiagramLayerSettings::PositionX ];
yCol = indexes[ QgsDiagramLayerSettings::PositionY ];
}
if ( xCol >= 0 && yCol >= 0 )
{
mStartPointMapCoords = toMapCoordinates( e->pos() );
QgsPointXY referencePoint;

View File

@ -260,13 +260,6 @@ void QgsMapToolPinLabels::pinUnpinLabels( const QgsRectangle &ext, QMouseEvent *
continue;
}
QgsVectorLayer *vlayer = mCurrentLabel.layer;
if ( !vlayer->isEditable() )
{
QgsDebugMsg( QString( "Vector layer not editable, skipping label" ) );
continue;
}
// unpin label
if ( isPinned() && ( doUnpin || toggleUnpinOrPin ) )
{
@ -297,7 +290,7 @@ void QgsMapToolPinLabels::pinUnpinLabels( const QgsRectangle &ext, QMouseEvent *
if ( labelChanged )
{
mCanvas->refresh();
mCurrentLabel.layer->triggerRepaint();
if ( !mShowPinned )
{

View File

@ -33,6 +33,7 @@ QgsMapToolRotateLabel::QgsMapToolRotateLabel( QgsMapCanvas *canvas )
, mCurrentMouseAzimuth( 0.0 )
, mCtrlPressed( false )
{
mPalProperties << QgsPalLayerSettings::LabelRotation;
}
QgsMapToolRotateLabel::~QgsMapToolRotateLabel()
@ -76,6 +77,14 @@ void QgsMapToolRotateLabel::canvasPressEvent( QgsMapMouseEvent *e )
bool hasRotationValue;
int rotationCol;
if ( !labelIsRotatable( mCurrentLabel.layer, mCurrentLabel.settings, rotationCol ) )
{
QgsPalIndexes indexes;
if ( createAuxiliaryFields( indexes ) )
return;
}
if ( currentLabelDataDefinedRotation( mCurrentRotation, hasRotationValue, rotationCol, true ) )
{
if ( !hasRotationValue )

View File

@ -35,6 +35,9 @@ QgsMapToolShowHideLabels::QgsMapToolShowHideLabels( QgsMapCanvas *canvas )
{
mToolName = tr( "Show/hide labels" );
mRubberBand = nullptr;
mPalProperties << QgsPalLayerSettings::Show;
mDiagramProperties << QgsDiagramLayerSettings::Show;
}
QgsMapToolShowHideLabels::~QgsMapToolShowHideLabels()
@ -45,6 +48,24 @@ QgsMapToolShowHideLabels::~QgsMapToolShowHideLabels()
void QgsMapToolShowHideLabels::canvasPressEvent( QgsMapMouseEvent *e )
{
Q_UNUSED( e );
QgsMapLayer *layer = mCanvas->currentLayer();
QgsVectorLayer *vlayer = dynamic_cast<QgsVectorLayer *>( layer );
if ( !vlayer )
return;
int showCol;
if ( !labelCanShowHide( vlayer, showCol )
|| !diagramCanShowHide( vlayer, showCol ) )
{
if ( !vlayer->auxiliaryLayer() )
{
QgsNewAuxiliaryLayerDialog dlg( vlayer );
dlg.exec();
return;
}
}
mSelectRect.setRect( 0, 0, 0, 0 );
mSelectRect.setTopLeft( e->pos() );
mSelectRect.setBottomRight( e->pos() );
@ -107,67 +128,46 @@ void QgsMapToolShowHideLabels::canvasReleaseEvent( QgsMapMouseEvent *e )
void QgsMapToolShowHideLabels::showHideLabels( QMouseEvent *e )
{
QgsMapLayer *layer = mCanvas->currentLayer();
QgsVectorLayer *vlayer = dynamic_cast<QgsVectorLayer *>( layer );
if ( !vlayer )
{
QgsDebugMsg( "Failed to cast label layer to vector layer" );
return;
}
bool doHide = e->modifiers() & Qt::ShiftModifier;
bool labelChanged = false;
QString editTxt = doHide ? tr( "Hid labels" ) : tr( "Showed labels" );
vlayer->beginEditCommand( editTxt );
if ( !doHide )
bool labelChanged = false;
if ( doHide )
{
QgsDebugMsg( "Showing labels operation" );
QgsFeatureIds selectedFeatIds;
if ( !selectedFeatures( vlayer, selectedFeatIds ) )
{
vlayer->destroyEditCommand();
return;
}
QgsDebugMsg( "Number of selected labels or features: " + QString::number( selectedFeatIds.size() ) );
if ( selectedFeatIds.isEmpty() )
{
vlayer->destroyEditCommand();
return;
}
Q_FOREACH ( QgsFeatureId fid, selectedFeatIds )
{
mCurrentLabel.pos.featureId = fid;
mCurrentLabel.pos.isDiagram = false;
bool labChanged = showHide( vlayer, true );
mCurrentLabel.pos.isDiagram = true;
bool diagChanged = showHide( vlayer, true );
if ( labChanged || diagChanged )
{
// TODO: highlight features (maybe with QTimer?)
labelChanged = true;
}
}
}
else
{
QgsDebugMsg( "Hiding labels operation" );
QList<QgsLabelPosition> positions;
if ( selectedLabelFeatures( vlayer, positions ) )
{
Q_FOREACH ( const QgsLabelPosition &pos, positions )
{
mCurrentLabel.pos = pos;
if ( showHide( pos, false ) )
labelChanged = true;
}
}
}
else
{
QgsFeatureIds fids;
if ( selectedFeatures( vlayer, fids ) )
{
Q_FOREACH ( QgsFeatureId fid, fids )
{
QgsLabelPosition pos;
pos.featureId = fid;
pos.layerID = vlayer->id();
if ( showHide( vlayer, false ) )
// we want to show labels...
pos.isDiagram = false;
if ( showHide( pos, true ) )
labelChanged = true;
// ... and diagrams
pos.isDiagram = true;
if ( showHide( pos, true ) )
labelChanged = true;
}
}
@ -269,42 +269,45 @@ bool QgsMapToolShowHideLabels::selectedLabelFeatures( QgsVectorLayer *vlayer,
return true;
}
bool QgsMapToolShowHideLabels::showHide( QgsVectorLayer *vl, const bool show )
bool QgsMapToolShowHideLabels::showHide( const QgsLabelPosition &pos, bool show )
{
// verify attribute table has proper field setup
bool showSuccess;
int showCol;
int showVal;
LabelDetails details = LabelDetails( pos );
if ( !dataDefinedShowHide( vl, mCurrentLabel.pos.featureId, showVal,
showSuccess, showCol ) )
{
if ( !details.valid )
return false;
QgsVectorLayer *vlayer = details.layer;
if ( !vlayer )
return false;
int showCol = -1;
if ( pos.isDiagram )
{
if ( !diagramCanShowHide( vlayer, showCol ) )
{
QgsDiagramIndexes indexes;
createAuxiliaryFields( details, indexes );
showCol = indexes[ QgsDiagramLayerSettings::Show ];
}
}
else
{
if ( !labelCanShowHide( vlayer, showCol ) )
{
QgsPalIndexes indexes;
createAuxiliaryFields( details, indexes );
showCol = indexes[ QgsPalLayerSettings::Show ];
}
}
// we need to pass int value to the provider
// (committing bool value would fail on int field)
int curVal = show ? 1 : 0;
// check if attribute value is already the same
if ( showSuccess && showVal == curVal )
if ( showCol >= 0 )
{
return false;
int showVal = show ? 1 : 0;
vlayer->changeAttributeValue( pos.featureId, showCol, showVal );
return true;
}
// allow NULL (maybe default) value to stand for show label (i.e. 1)
// skip NULL attributes if trying to show label
if ( !showSuccess && curVal == 1 )
{
return false;
}
// different attribute value, edit table
if ( ! vl->changeAttributeValue( mCurrentLabel.pos.featureId, showCol, curVal ) )
{
QgsDebugMsg( "Failed write to attribute table" );
return false;
}
return true;
return false;
}

View File

@ -64,8 +64,7 @@ class APP_EXPORT QgsMapToolShowHideLabels : public QgsMapToolLabel
bool selectedLabelFeatures( QgsVectorLayer *vlayer,
QList<QgsLabelPosition> &listPos );
//! Show label or diagram with feature ID
bool showHide( QgsVectorLayer *vl, const bool show );
bool showHide( const QgsLabelPosition &pos, bool show );
};
#endif // QGSMAPTOOLSHOWHIDELABELS_H

View File

@ -19,7 +19,7 @@
#include "qgslogger.h"
#include "qgsslconnect.h"
#include "qgsproject.h"
#include "qgspallabeling.h"
#include "qgsvectorlayerlabeling.h"
#include "qgsdiagramrenderer.h"
#include "qgsmemoryproviderutils.h"
@ -241,6 +241,62 @@ bool QgsAuxiliaryLayer::save()
return rc;
}
int QgsAuxiliaryLayer::createProperty( QgsPalLayerSettings::Property p, const QString &providerId, QgsVectorLayer *layer )
{
int index = -1;
if ( layer && layer->labeling() && layer->auxiliaryLayer() )
{
const QgsPropertyDefinition def = layer->labeling()->settings( providerId ).propertyDefinitions()[p];
const QString fieldName = QgsAuxiliaryField::nameFromProperty( def, true );
if ( layer->auxiliaryLayer()->addAuxiliaryField( def ) )
{
const QgsProperty prop = QgsProperty::fromField( fieldName );
QgsPalLayerSettings *settings = new QgsPalLayerSettings( layer->labeling()->settings( providerId ) );
QgsPropertyCollection c = settings->dataDefinedProperties();
c.setProperty( p, prop );
settings->setDataDefinedProperties( c );
layer->labeling()->setSettings( settings, providerId );
}
index = layer->fields().lookupField( fieldName );
}
return index;
}
int QgsAuxiliaryLayer::createProperty( QgsDiagramLayerSettings::Property p, QgsVectorLayer *layer )
{
int index = -1;
if ( layer && layer->diagramLayerSettings() && layer->auxiliaryLayer() )
{
const QgsPropertyDefinition def = layer->diagramLayerSettings()->propertyDefinitions()[p];
if ( layer->auxiliaryLayer()->addAuxiliaryField( def ) )
{
const QString fieldName = QgsAuxiliaryField::nameFromProperty( def, true );
const QgsProperty prop = QgsProperty::fromField( fieldName );
QgsDiagramLayerSettings settings( *layer->diagramLayerSettings() );
QgsPropertyCollection c = settings.dataDefinedProperties();
c.setProperty( p, prop );
settings.setDataDefinedProperties( c );
layer->setDiagramLayerSettings( settings );
index = layer->fields().lookupField( fieldName );
}
}
return index;
}
//
// QgsAuxiliaryStorage
//

View File

@ -20,6 +20,8 @@
#include "qgis_core.h"
#include "qgsdatasourceuri.h"
#include "qgspallabeling.h"
#include "qgsdiagramrenderer.h"
#include "qgsvectorlayerjoininfo.h"
#include "qgsproperty.h"
@ -197,6 +199,30 @@ class CORE_EXPORT QgsAuxiliaryLayer : public QgsVectorLayer
*/
virtual bool deleteAttribute( int attr ) override;
/**
* Create if necessary a new auxiliary field for a PAL property and
* activate this property in settings.
*
* \param p The property to create
* \param providerId The id of the provider to use
* \param vlayer The vector layer
*
* \returns The index of the auxiliary field or -1
*/
static int createProperty( QgsPalLayerSettings::Property p, const QString &providerId, QgsVectorLayer *vlayer );
/**
* Create if necessary a new auxiliary field for a diagram's property and
* activate this this property in settings.
*
* \param p The property to create
* \param providerId The id of the provider to use
* \param vlayer The vector layer
*
* \returns The index of the auxiliary field or -1
*/
static int createProperty( QgsDiagramLayerSettings::Property p, QgsVectorLayer *vlayer );
private:
QgsVectorLayerJoinInfo mJoinInfo;
const QgsVectorLayer *mLayer = nullptr;

View File

@ -177,6 +177,20 @@ const QgsRuleBasedLabeling::Rule *QgsRuleBasedLabeling::Rule::findRuleByKey( con
return nullptr;
}
QgsRuleBasedLabeling::Rule *QgsRuleBasedLabeling::Rule::findRuleByKey( const QString &key )
{
if ( key == mRuleKey )
return this;
Q_FOREACH ( Rule *rule, mChildren )
{
Rule *r = rule->findRuleByKey( key );
if ( r )
return r;
}
return nullptr;
}
QgsRuleBasedLabeling::Rule *QgsRuleBasedLabeling::Rule::clone() const
{
QgsPalLayerSettings *s = mSettings ? new QgsPalLayerSettings( *mSettings ) : nullptr;
@ -451,3 +465,13 @@ bool QgsRuleBasedLabeling::requiresAdvancedEffects() const
{
return mRootRule->requiresAdvancedEffects();
}
void QgsRuleBasedLabeling::setSettings( QgsPalLayerSettings *settings, const QString &providerId )
{
if ( settings )
{
Rule *rule = mRootRule->findRuleByKey( providerId );
if ( rule && rule->settings() )
return rule->setSettings( settings );
}
}

View File

@ -231,6 +231,17 @@ class CORE_EXPORT QgsRuleBasedLabeling : public QgsAbstractVectorLayerLabeling
//! Try to find a rule given its unique key
const QgsRuleBasedLabeling::Rule *findRuleByKey( const QString &key ) const;
/**
* Find a labeling rule thanks to its key.
*
* \param key The key of the rule to find
*
* \returns The rule or a nullptr if not found
*
* \since QGIS 3.0
*/
QgsRuleBasedLabeling::Rule *findRuleByKey( const QString &key ) SIP_SKIP;
//! clone this rule, return new instance
QgsRuleBasedLabeling::Rule *clone() const SIP_FACTORY;
@ -350,6 +361,16 @@ class CORE_EXPORT QgsRuleBasedLabeling : public QgsAbstractVectorLayerLabeling
virtual QgsVectorLayerLabelProvider *provider( QgsVectorLayer *layer ) const override SIP_SKIP;
virtual QStringList subProviders() const override;
virtual QgsPalLayerSettings settings( const QString &providerId = QString() ) const override;
/**
* Set pal settings for a specific provider (takes ownership).
*
* \param settings Pal layer settings
* \param providerId The id of the provider
*
* \since QGIS 3.0
*/
virtual void setSettings( QgsPalLayerSettings *settings SIP_TRANSFER, const QString &providerId = QString() ) override;
bool requiresAdvancedEffects() const override;
protected:

View File

@ -1133,11 +1133,17 @@ class CORE_EXPORT QgsVectorLayer : public QgsMapLayer, public QgsExpressionConte
*/
int addTopologicalPoints( const QgsPointXY &p );
/**
* Access to const labeling configuration. May be null if labeling is not used.
* \since QGIS 3.0
*/
const QgsAbstractVectorLayerLabeling *labeling() const SIP_SKIP { return mLabeling; }
/**
* Access to labeling configuration. May be null if labeling is not used.
* \since QGIS 3.0
*/
const QgsAbstractVectorLayerLabeling *labeling() const { return mLabeling; }
QgsAbstractVectorLayerLabeling *labeling() { return mLabeling; }
/**
* Set labeling configuration. Takes ownership of the object.

View File

@ -192,7 +192,7 @@ QgsLabelFeature *QgsVectorLayerDiagramProvider::registerDiagram( QgsFeature &fea
}
// data defined show diagram? check this before doing any other processing
if ( !mSettings.dataDefinedProperties().valueAsBool( QgsDiagramLayerSettings::Show, context.expressionContext(), true ) )
if ( !mSettings.dataDefinedProperties().valueAsBool( QgsDiagramLayerSettings::Show, context.expressionContext(), true ) || !context.expressionContext().feature().isValid() )
return nullptr;
// data defined obstacle?

View File

@ -546,3 +546,13 @@ void QgsVectorLayerSimpleLabeling::toSld( QDomNode &parent, const QgsStringMap &
}
void QgsVectorLayerSimpleLabeling::setSettings( QgsPalLayerSettings *settings, const QString &providerId )
{
Q_UNUSED( providerId );
if ( mSettings.get() == settings )
return;
mSettings.reset( settings );
}

View File

@ -68,6 +68,16 @@ class CORE_EXPORT QgsAbstractVectorLayerLabeling
*/
virtual QgsPalLayerSettings settings( const QString &providerId = QString() ) const = 0;
/**
* Set pal settings for a specific provider (takes ownership).
*
* \param settings Pal layer settings
* \param providerId The id of the provider
*
* \since QGIS 3.0
*/
virtual void setSettings( QgsPalLayerSettings *settings SIP_TRANSFER, const QString &providerId = QString() ) = 0;
/**
* Returns true if drawing labels requires advanced effects like composition
* modes, which could prevent it being used as an isolated cached image
@ -121,6 +131,17 @@ class CORE_EXPORT QgsVectorLayerSimpleLabeling : public QgsAbstractVectorLayerLa
virtual QgsVectorLayerLabelProvider *provider( QgsVectorLayer *layer ) const override SIP_SKIP;
virtual QDomElement save( QDomDocument &doc, const QgsReadWriteContext &context ) const override;
virtual QgsPalLayerSettings settings( const QString &providerId = QString() ) const override;
/**
* Set pal settings (takes ownership).
*
* \param settings Pal layer settings
* \param providerId Unused parameter
*
* \since QGIS 3.0
*/
virtual void setSettings( QgsPalLayerSettings *settings SIP_TRANSFER, const QString &providerId = QString() ) override;
bool requiresAdvancedEffects() const override;
virtual void toSld( QDomNode &parent, const QgsStringMap &props ) const override;