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 :rtype: bool
%End %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 :rtype: QgsRuleBasedLabeling.Rule
%End %End
QgsRuleBasedLabeling::Rule *clone() const /Factory/; QgsRuleBasedLabeling::Rule *clone() const /Factory/;
%Docstring %Docstring
clone this rule, return new instance 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 QDomElement save( QDomDocument &doc, const QgsReadWriteContext &context ) const;
virtual QStringList subProviders() const; virtual QStringList subProviders() const;
virtual QgsPalLayerSettings settings( const QString &providerId = QString() ) 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; virtual bool requiresAdvancedEffects() const;

View File

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

View File

@ -61,6 +61,16 @@ Get list of sub-providers within the layer's labeling.
:rtype: QgsPalLayerSettings :rtype: QgsPalLayerSettings
%End %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; virtual bool requiresAdvancedEffects() const = 0;
%Docstring %Docstring
Returns true if drawing labels requires advanced effects like composition 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 QgsAbstractVectorLayerLabeling *clone() const /Factory/;
virtual QDomElement save( QDomDocument &doc, const QgsReadWriteContext &context ) const; virtual QDomElement save( QDomDocument &doc, const QgsReadWriteContext &context ) const;
virtual QgsPalLayerSettings settings( const QString &providerId = QString() ) 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 bool requiresAdvancedEffects() const;
virtual void toSld( QDomNode &parent, const QgsStringMap &props ) 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 ) for ( QMap<QString, QgsMapLayer *>::iterator it = layers.begin(); it != layers.end(); ++it )
{ {
QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( it.value() ); QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( it.value() );
if ( !vlayer || ( !vlayer->diagramsEnabled() && !vlayer->labelsEnabled() ) ) if ( vlayer && ( vlayer->diagramsEnabled() || vlayer->labelsEnabled() ) )
continue; {
enablePin = true;
int colX, colY, colShow, colAng; enableShowHide = true;
enablePin = enableMove = true;
enablePin || enableRotate = true;
( 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() )
enableChange = true; enableChange = true;
if ( enablePin && enableShowHide && enableMove && enableRotate && enableChange )
break; break;
}
} }
mActionPinLabels->setEnabled( enablePin ); 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 bool QgsMapToolLabel::labelMoveable( QgsVectorLayer *vlayer, int &xCol, int &yCol ) const
{ {
if ( !vlayer || !vlayer->labeling() ) if ( !vlayer || !vlayer->isEditable() || !vlayer->labeling() )
{ {
return false; return false;
} }
@ -648,26 +648,7 @@ bool QgsMapToolLabel::labelMoveable( QgsVectorLayer *vlayer, const QgsPalLayerSe
//return !xColName.isEmpty() && !yColName.isEmpty(); //return !xColName.isEmpty() && !yColName.isEmpty();
xCol = vlayer->fields().lookupField( xColName ); xCol = vlayer->fields().lookupField( xColName );
yCol = vlayer->fields().lookupField( yColName ); yCol = vlayer->fields().lookupField( yColName );
return ( xCol != -1 && yCol != -1 );
// 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;
} }
bool QgsMapToolLabel::layerCanPin( QgsVectorLayer *vlayer, int &xCol, int &yCol ) const 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 bool QgsMapToolLabel::labelCanShowHide( QgsVectorLayer *vlayer, int &showCol ) const
{ {
if ( !vlayer || !vlayer->labeling() ) if ( !vlayer || !vlayer->isEditable() || !vlayer->labeling() )
{ {
return false; return false;
} }
@ -689,20 +670,8 @@ bool QgsMapToolLabel::labelCanShowHide( QgsVectorLayer *vlayer, int &showCol ) c
QString fieldname = dataDefinedColumnName( QgsPalLayerSettings::Show, QString fieldname = dataDefinedColumnName( QgsPalLayerSettings::Show,
vlayer->labeling()->settings( providerId ) ); vlayer->labeling()->settings( providerId ) );
showCol = vlayer->fields().lookupField( fieldname ); showCol = vlayer->fields().lookupField( fieldname );
if ( showCol >= 0 ) if ( showCol != -1 )
{ return true;
bool auxiliaryField = vlayer->isAuxiliaryField( showCol );
if ( ! auxiliaryField )
{
if ( vlayer->isEditable() )
return true;
else
return false;
}
else
return true;
}
} }
return false; return false;
@ -773,14 +742,14 @@ QgsMapToolLabel::LabelDetails::LabelDetails( const QgsLabelPosition &p )
: pos( p ) : pos( p )
{ {
layer = qobject_cast<QgsVectorLayer *>( QgsProject::instance()->mapLayer( pos.layerID ) ); 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 ); settings = layer->labeling()->settings( pos.providerID );
valid = true;
if ( p.isDiagram ) }
valid = layer->diagramsEnabled(); else if ( layer && layer->diagramsEnabled() && p.isDiagram )
else {
valid = true; valid = true;
} }
if ( !valid ) if ( !valid )
@ -789,3 +758,69 @@ QgsMapToolLabel::LabelDetails::LabelDetails( const QgsLabelPosition &p )
settings = QgsPalLayerSettings(); 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 "qgsmaptool.h"
#include "qgspallabeling.h" #include "qgspallabeling.h"
#include "qgsnewauxiliarylayerdialog.h"
#include "qgsauxiliarystorage.h"
#include "qgis_app.h" #include "qgis_app.h"
class QgsRubberBand; class QgsRubberBand;
typedef QMap<QgsPalLayerSettings::Property, int> QgsPalIndexes;
typedef QMap<QgsDiagramLayerSettings::Property, int> QgsDiagramIndexes;
//! Base class for map tools that modify label properties //! Base class for map tools that modify label properties
class APP_EXPORT QgsMapToolLabel: public QgsMapTool class APP_EXPORT QgsMapToolLabel: public QgsMapTool
{ {
@ -175,6 +180,14 @@ class APP_EXPORT QgsMapToolLabel: public QgsMapTool
\since QGIS 2.16 \since QGIS 2.16
*/ */
bool isPinned(); 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 #endif // QGSMAPTOOLLABEL_H

View File

@ -27,6 +27,12 @@ QgsMapToolMoveLabel::QgsMapToolMoveLabel( QgsMapCanvas *canvas )
, mClickOffsetY( 0 ) , mClickOffsetY( 0 )
{ {
mToolName = tr( "Move label" ); mToolName = tr( "Move label" );
mPalProperties << QgsPalLayerSettings::PositionX;
mPalProperties << QgsPalLayerSettings::PositionY;
mDiagramProperties << QgsDiagramLayerSettings::PositionX;
mDiagramProperties << QgsDiagramLayerSettings::PositionY;
} }
void QgsMapToolMoveLabel::canvasPressEvent( QgsMapMouseEvent *e ) void QgsMapToolMoveLabel::canvasPressEvent( QgsMapMouseEvent *e )
@ -49,8 +55,29 @@ void QgsMapToolMoveLabel::canvasPressEvent( QgsMapMouseEvent *e )
} }
int xCol, yCol; 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() ); mStartPointMapCoords = toMapCoordinates( e->pos() );
QgsPointXY referencePoint; QgsPointXY referencePoint;

View File

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

View File

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

View File

@ -35,6 +35,9 @@ QgsMapToolShowHideLabels::QgsMapToolShowHideLabels( QgsMapCanvas *canvas )
{ {
mToolName = tr( "Show/hide labels" ); mToolName = tr( "Show/hide labels" );
mRubberBand = nullptr; mRubberBand = nullptr;
mPalProperties << QgsPalLayerSettings::Show;
mDiagramProperties << QgsDiagramLayerSettings::Show;
} }
QgsMapToolShowHideLabels::~QgsMapToolShowHideLabels() QgsMapToolShowHideLabels::~QgsMapToolShowHideLabels()
@ -45,6 +48,24 @@ QgsMapToolShowHideLabels::~QgsMapToolShowHideLabels()
void QgsMapToolShowHideLabels::canvasPressEvent( QgsMapMouseEvent *e ) void QgsMapToolShowHideLabels::canvasPressEvent( QgsMapMouseEvent *e )
{ {
Q_UNUSED( 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.setRect( 0, 0, 0, 0 );
mSelectRect.setTopLeft( e->pos() ); mSelectRect.setTopLeft( e->pos() );
mSelectRect.setBottomRight( e->pos() ); mSelectRect.setBottomRight( e->pos() );
@ -107,67 +128,46 @@ void QgsMapToolShowHideLabels::canvasReleaseEvent( QgsMapMouseEvent *e )
void QgsMapToolShowHideLabels::showHideLabels( QMouseEvent *e ) void QgsMapToolShowHideLabels::showHideLabels( QMouseEvent *e )
{ {
QgsMapLayer *layer = mCanvas->currentLayer(); QgsMapLayer *layer = mCanvas->currentLayer();
QgsVectorLayer *vlayer = dynamic_cast<QgsVectorLayer *>( layer ); QgsVectorLayer *vlayer = dynamic_cast<QgsVectorLayer *>( layer );
if ( !vlayer ) if ( !vlayer )
{
QgsDebugMsg( "Failed to cast label layer to vector layer" );
return; return;
}
bool doHide = e->modifiers() & Qt::ShiftModifier; bool doHide = e->modifiers() & Qt::ShiftModifier;
bool labelChanged = false;
QString editTxt = doHide ? tr( "Hid labels" ) : tr( "Showed labels" ); QString editTxt = doHide ? tr( "Hid labels" ) : tr( "Showed labels" );
vlayer->beginEditCommand( editTxt ); 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; QList<QgsLabelPosition> positions;
if ( selectedLabelFeatures( vlayer, positions ) ) if ( selectedLabelFeatures( vlayer, positions ) )
{ {
Q_FOREACH ( const QgsLabelPosition &pos, 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; labelChanged = true;
} }
} }
@ -269,42 +269,45 @@ bool QgsMapToolShowHideLabels::selectedLabelFeatures( QgsVectorLayer *vlayer,
return true; 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 LabelDetails details = LabelDetails( pos );
bool showSuccess;
int showCol;
int showVal;
if ( !dataDefinedShowHide( vl, mCurrentLabel.pos.featureId, showVal, if ( !details.valid )
showSuccess, showCol ) )
{
return false; 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 if ( showCol >= 0 )
// (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 )
{ {
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) return false;
// 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;
} }

View File

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

View File

@ -19,7 +19,7 @@
#include "qgslogger.h" #include "qgslogger.h"
#include "qgsslconnect.h" #include "qgsslconnect.h"
#include "qgsproject.h" #include "qgsproject.h"
#include "qgspallabeling.h" #include "qgsvectorlayerlabeling.h"
#include "qgsdiagramrenderer.h" #include "qgsdiagramrenderer.h"
#include "qgsmemoryproviderutils.h" #include "qgsmemoryproviderutils.h"
@ -241,6 +241,62 @@ bool QgsAuxiliaryLayer::save()
return rc; 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 // QgsAuxiliaryStorage
// //

View File

@ -20,6 +20,8 @@
#include "qgis_core.h" #include "qgis_core.h"
#include "qgsdatasourceuri.h" #include "qgsdatasourceuri.h"
#include "qgspallabeling.h"
#include "qgsdiagramrenderer.h"
#include "qgsvectorlayerjoininfo.h" #include "qgsvectorlayerjoininfo.h"
#include "qgsproperty.h" #include "qgsproperty.h"
@ -197,6 +199,30 @@ class CORE_EXPORT QgsAuxiliaryLayer : public QgsVectorLayer
*/ */
virtual bool deleteAttribute( int attr ) override; 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: private:
QgsVectorLayerJoinInfo mJoinInfo; QgsVectorLayerJoinInfo mJoinInfo;
const QgsVectorLayer *mLayer = nullptr; const QgsVectorLayer *mLayer = nullptr;

View File

@ -177,6 +177,20 @@ const QgsRuleBasedLabeling::Rule *QgsRuleBasedLabeling::Rule::findRuleByKey( con
return nullptr; 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 QgsRuleBasedLabeling::Rule *QgsRuleBasedLabeling::Rule::clone() const
{ {
QgsPalLayerSettings *s = mSettings ? new QgsPalLayerSettings( *mSettings ) : nullptr; QgsPalLayerSettings *s = mSettings ? new QgsPalLayerSettings( *mSettings ) : nullptr;
@ -451,3 +465,13 @@ bool QgsRuleBasedLabeling::requiresAdvancedEffects() const
{ {
return mRootRule->requiresAdvancedEffects(); 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 //! Try to find a rule given its unique key
const QgsRuleBasedLabeling::Rule *findRuleByKey( const QString &key ) const; 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 //! clone this rule, return new instance
QgsRuleBasedLabeling::Rule *clone() const SIP_FACTORY; 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 QgsVectorLayerLabelProvider *provider( QgsVectorLayer *layer ) const override SIP_SKIP;
virtual QStringList subProviders() const override; virtual QStringList subProviders() const override;
virtual QgsPalLayerSettings settings( const QString &providerId = QString() ) 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; bool requiresAdvancedEffects() const override;
protected: protected:

View File

@ -1133,11 +1133,17 @@ class CORE_EXPORT QgsVectorLayer : public QgsMapLayer, public QgsExpressionConte
*/ */
int addTopologicalPoints( const QgsPointXY &p ); 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. * Access to labeling configuration. May be null if labeling is not used.
* \since QGIS 3.0 * \since QGIS 3.0
*/ */
const QgsAbstractVectorLayerLabeling *labeling() const { return mLabeling; } QgsAbstractVectorLayerLabeling *labeling() { return mLabeling; }
/** /**
* Set labeling configuration. Takes ownership of the object. * 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 // 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; return nullptr;
// data defined obstacle? // 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; 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 * Returns true if drawing labels requires advanced effects like composition
* modes, which could prevent it being used as an isolated cached image * 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 QgsVectorLayerLabelProvider *provider( QgsVectorLayer *layer ) const override SIP_SKIP;
virtual QDomElement save( QDomDocument &doc, const QgsReadWriteContext &context ) const override; virtual QDomElement save( QDomDocument &doc, const QgsReadWriteContext &context ) const override;
virtual QgsPalLayerSettings settings( const QString &providerId = QString() ) 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; bool requiresAdvancedEffects() const override;
virtual void toSld( QDomNode &parent, const QgsStringMap &props ) const override; virtual void toSld( QDomNode &parent, const QgsStringMap &props ) const override;