Skip to content

Commit 43bbf68

Browse files
committed
Port labeling to properties framework
1 parent 1e0c62b commit 43bbf68

28 files changed

+833
-1394
lines changed

python/core/qgspallabeling.sip

+19-142
Original file line numberDiff line numberDiff line change
@@ -1,83 +1,3 @@
1-
// QMap<QgsPalLayerSettings::DataDefinedProperties, QgsDataDefined*> is implemented as a Python dictionary.
2-
%MappedType QMap<QgsPalLayerSettings::DataDefinedProperties, QgsDataDefined*> /DocType="dict-of-QgsPalLayerSettings.DataDefinedProperties-QgsDataDefined*"/
3-
{
4-
%TypeHeaderCode
5-
#include <qmap.h>
6-
#include <qgspallabeling.h>
7-
#include <qgsdatadefined.h>
8-
%End
9-
%ConvertFromTypeCode
10-
// Create the dictionary.
11-
PyObject *d = PyDict_New();
12-
if (!d)
13-
return NULL;
14-
// Set the dictionary elements.
15-
QMap<QgsPalLayerSettings::DataDefinedProperties, QgsDataDefined*>::const_iterator i = sipCpp->constBegin();
16-
while (i != sipCpp->constEnd())
17-
{
18-
QgsDataDefined *t = i.value();
19-
PyObject *kobj = sipConvertFromEnum(i.key(), sipType_QgsPalLayerSettings_DataDefinedProperties);
20-
PyObject *tobj = sipConvertFromType(t, sipType_QgsDataDefined, sipTransferObj);
21-
if (kobj == NULL || tobj == NULL || PyDict_SetItem(d, kobj, tobj) < 0)
22-
{
23-
Py_DECREF(d);
24-
if (kobj)
25-
{
26-
Py_DECREF(kobj);
27-
}
28-
if (tobj)
29-
{
30-
Py_DECREF(tobj);
31-
}
32-
else
33-
{
34-
delete t;
35-
}
36-
return NULL;
37-
}
38-
Py_DECREF(kobj);
39-
Py_DECREF(tobj);
40-
++i;
41-
}
42-
return d;
43-
%End
44-
%ConvertToTypeCode
45-
PyObject *kobj, *tobj;
46-
SIP_SSIZE_T i = 0;
47-
// Check the type if that is all that is required.
48-
if (sipIsErr == NULL)
49-
{
50-
if (!PyDict_Check(sipPy))
51-
return 0;
52-
while (PyDict_Next(sipPy, &i, &kobj, &tobj))
53-
if (!sipCanConvertToType(tobj, sipType_QgsDataDefined, SIP_NOT_NONE))
54-
return 0;
55-
return 1;
56-
}
57-
QMap<QgsPalLayerSettings::DataDefinedProperties, QgsDataDefined*> *qm = new QMap<QgsPalLayerSettings::DataDefinedProperties, QgsDataDefined*>;
58-
59-
while (PyDict_Next(sipPy, &i, &kobj, &tobj))
60-
{
61-
int state, k = SIPLong_AsLong(kobj);
62-
QgsDataDefined *t = reinterpret_cast<QgsDataDefined *>(sipConvertToType(tobj, sipType_QgsDataDefined, sipTransferObj, SIP_NOT_NONE, &state, sipIsErr));
63-
64-
if (*sipIsErr)
65-
{
66-
sipReleaseType(t, sipType_QgsDataDefined, state);
67-
delete qm;
68-
return 0;
69-
}
70-
qm->insert(QgsPalLayerSettings::DataDefinedProperties(k), t);
71-
sipReleaseType(t, sipType_QgsDataDefined, state);
72-
}
73-
74-
*sipCppPtr = qm;
75-
76-
return sipGetState(sipTransferObj);
77-
%End
78-
};
79-
80-
811
class QgsLabelPosition
822
{
833
%TypeHeaderCode
@@ -239,7 +159,7 @@ class QgsPalLayerSettings
239159
};
240160

241161
// update mDataDefinedNames QMap in constructor when adding/deleting enum value
242-
enum DataDefinedProperties
162+
enum Property
243163
{
244164
// text style
245165
Size,
@@ -507,67 +427,24 @@ class QgsPalLayerSettings
507427
*/
508428
QDomElement writeXml( QDomDocument& doc );
509429

510-
/** Get a data defined property pointer
511-
* @note helpful for Python access
512-
*/
513-
QgsDataDefined* dataDefinedProperty( QgsPalLayerSettings::DataDefinedProperties p );
514-
515-
/** Set a property as data defined
516-
* @note helpful for Python access
517-
*/
518-
void setDataDefinedProperty( QgsPalLayerSettings::DataDefinedProperties p,
519-
bool active, bool useExpr, const QString& expr, const QString& field );
520-
521-
/** Set a property to static instead data defined */
522-
void removeDataDefinedProperty( QgsPalLayerSettings::DataDefinedProperties p );
523-
524-
/** Clear all data-defined properties
525-
* @note added in QGIS 2.12
526-
*/
527-
void removeAllDataDefinedProperties();
528-
529-
/** Convert old property value to new one as delimited values
530-
* @note not available in python bindings; as temporary solution until refactoring of project settings
531-
*/
532-
QString updateDataDefinedString( const QString& value );
533-
534-
/** Get property value as separate values split into Qmap
535-
* @note not available in python bindings
536-
*/
537-
QMap<QString, QString> dataDefinedMap( QgsPalLayerSettings::DataDefinedProperties p ) const;
538-
539-
/** Get data defined property value from expression string or attribute field name
540-
* @returns value inside QVariant
541-
* @note not available in python bindings
542-
*/
543-
//QVariant dataDefinedValue( QgsPalLayerSettings::DataDefinedProperties p, QgsFeature& f, const QgsFields& fields,
544-
// const QgsExpressionContext* context = 0 ) const;
545-
546-
/** Get data defined property value from expression string or attribute field name
547-
* @returns true/false whether result is null or invalid
548-
* @note not available in python bindings
549-
*/
550-
//bool dataDefinedEvaluate( QgsPalLayerSettings::DataDefinedProperties p, QVariant& exprVal, const QgsExpressionContext* context = 0 ) const;
551-
552-
/** Whether data definition is active
553-
*/
554-
bool dataDefinedIsActive( QgsPalLayerSettings::DataDefinedProperties p ) const;
555-
556-
/** Whether data definition is set to use an expression
430+
/** Returns a reference to the label's property collection, used for data defined overrides.
431+
* @note added in QGIS 3.0
432+
* @see setProperties()
557433
*/
558-
bool dataDefinedUseExpression( QgsPalLayerSettings::DataDefinedProperties p ) const;
434+
QgsPropertyCollection& properties();
559435

560-
/** Map of current data defined properties
561-
*
562-
* Pointers to QgsDataDefined should never be null, the pointers are owned by this class
436+
/** Returns a reference to the label's property collection, used for data defined overrides.
437+
* @note added in QGIS 3.0
438+
* @see setProperties()
563439
*/
564-
QMap< QgsPalLayerSettings::DataDefinedProperties, QgsDataDefined* > dataDefinedProperties;
440+
//const QgsPropertyCollection& properties() const { return mProperties; }
565441

566-
/** Map of data defined enum to names and old-style indecies
567-
* The QPair contains a new string for layer property key, and a reference to old-style numeric key (< QGIS 2.0)
568-
* @note not available in python bindings;
442+
/** Sets the label's property collection, used for data defined overrides.
443+
* @param collection property collection. Existing properties will be replaced.
444+
* @note added in QGIS 3.0
445+
* @see properties()
569446
*/
570-
// QMap<QgsPalLayerSettings::DataDefinedProperties, QPair<QString, int> > dataDefinedNames() const;
447+
void setProperties( const QgsPropertyCollection& collection );
571448

572449
/** Returns the label text formatting settings, e.g., font settings, buffer settings, etc.
573450
* @see setFormat()
@@ -737,23 +614,23 @@ class QgsPalLabeling
737614
protected:
738615
// update temporary QgsPalLayerSettings with any data defined text style values
739616
void dataDefinedTextStyle( QgsPalLayerSettings& tmpLyr,
740-
const QMap< QgsPalLayerSettings::DataDefinedProperties, QVariant >& ddValues );
617+
const QMap< QgsPalLayerSettings::Property, QVariant >& ddValues );
741618

742619
// update temporary QgsPalLayerSettings with any data defined text formatting values
743620
void dataDefinedTextFormatting( QgsPalLayerSettings& tmpLyr,
744-
const QMap< QgsPalLayerSettings::DataDefinedProperties, QVariant >& ddValues );
621+
const QMap< QgsPalLayerSettings::Property, QVariant >& ddValues );
745622

746623
// update temporary QgsPalLayerSettings with any data defined text buffer values
747624
void dataDefinedTextBuffer( QgsPalLayerSettings& tmpLyr,
748-
const QMap< QgsPalLayerSettings::DataDefinedProperties, QVariant >& ddValues );
625+
const QMap< QgsPalLayerSettings::Property, QVariant >& ddValues );
749626

750627
// update temporary QgsPalLayerSettings with any data defined shape background values
751628
void dataDefinedShapeBackground( QgsPalLayerSettings& tmpLyr,
752-
const QMap< QgsPalLayerSettings::DataDefinedProperties, QVariant >& ddValues );
629+
const QMap< QgsPalLayerSettings::Property, QVariant >& ddValues );
753630

754631
// update temporary QgsPalLayerSettings with any data defined drop shadow values
755632
void dataDefinedDropShadow( QgsPalLayerSettings& tmpLyr,
756-
const QMap< QgsPalLayerSettings::DataDefinedProperties, QVariant >& ddValues );
633+
const QMap< QgsPalLayerSettings::Property, QVariant >& ddValues );
757634

758635
void deleteTemporaryData();
759636

python/core/qgsproperty.sip

+11
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,17 @@ class QgsAbstractProperty
123123
*/
124124
int valueAsInt( const QgsExpressionContext& context, int defaultValue = 0 ) const;
125125

126+
/**
127+
* Calculates the current value of the property and interprets it as an boolean.
128+
* @param context QgsExpressionContext to evaluate the property for.
129+
* @param defaultValue default boolean to return if the property cannot be calculated as an boolean
130+
* @returns value parsed to boolean
131+
* @see value()
132+
* @see valueAsDouble()
133+
* @see valueAsColor()
134+
*/
135+
bool valueAsBool( const QgsExpressionContext& context, bool defaultValue = false ) const;
136+
126137
/** Writes the current state of the property into an XML element
127138
* @param propertyElem destination element for the property's state
128139
* @param doc DOM document

python/core/qgspropertycollection.sip

+22-6
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
typedef QMap< int, QString > QgsPropertyDefinition;
2+
13
/**
24
* \ingroup core
35
* \class QgsAbstractPropertyCollection
@@ -126,6 +128,20 @@ class QgsAbstractPropertyCollection
126128
*/
127129
int valueAsInt( int key, const QgsExpressionContext& context, int defaultValue = 0 ) const;
128130

131+
/**
132+
* Calculates the current value of the property with the specified key and interprets it as an boolean.
133+
* @param key integer key for property to return. The intended use case is that a context specific enum is cast to
134+
* int and used for the key value.
135+
* @param context QgsExpressionContext to evaluate the property for.
136+
* @param defaultValue default boolean to return if the property cannot be calculated as a boolean
137+
* @returns value parsed to bool
138+
* @see value()
139+
* @see valueAsDouble()
140+
* @see valueAsColor()
141+
*/
142+
bool valueAsBool( int key, const QgsExpressionContext& context, bool defaultValue = false ) const;
143+
144+
129145
/**
130146
* Prepares the collection against a specified expression context. Calling prepare before evaluating the
131147
* collection's properties multiple times allows precalculation of expensive setup tasks such as parsing expressions.
@@ -168,7 +184,7 @@ class QgsAbstractPropertyCollection
168184
* to avoid writing the raw integer key values to XML, for readability and future-proofness.
169185
* @see readXML()
170186
*/
171-
virtual bool writeXml( QDomElement& collectionElem, QDomDocument& doc, const QMap< int, QString >& propertyNameMap ) const = 0;
187+
virtual bool writeXml( QDomElement& collectionElem, QDomDocument& doc, const QgsPropertyDefinition& propertyNameMap ) const = 0;
172188

173189
/**
174190
* Reads property collection state from an XML element.
@@ -178,7 +194,7 @@ class QgsAbstractPropertyCollection
178194
* the propertyNameMap specified when writeXML() was called.
179195
* @see writeXML()
180196
*/
181-
virtual bool readXml( const QDomElement& collectionElem, const QDomDocument& doc, const QMap<int, QString> &propertyNameMap ) = 0;
197+
virtual bool readXml( const QDomElement& collectionElem, const QDomDocument& doc, const QgsPropertyDefinition &propertyNameMap ) = 0;
182198

183199
};
184200

@@ -227,8 +243,8 @@ class QgsPropertyCollection : QgsAbstractPropertyCollection
227243
bool isActive( int key ) const;
228244
bool hasActiveProperties() const;
229245
bool hasActiveDynamicProperties() const;
230-
bool writeXml( QDomElement& collectionElem, QDomDocument& doc, const QMap< int, QString >& propertyNameMap ) const;
231-
bool readXml( const QDomElement& collectionElem, const QDomDocument& doc, const QMap<int, QString> &propertyNameMap );
246+
bool writeXml( QDomElement& collectionElem, QDomDocument& doc, const QgsPropertyDefinition& propertyNameMap ) const;
247+
bool readXml( const QDomElement& collectionElem, const QDomDocument& doc, const QgsPropertyDefinition& propertyNameMap );
232248

233249
/** Adds a property to the collection and takes ownership of it.
234250
* @param key integer key for property. Any existing property with the same key will be deleted
@@ -353,7 +369,7 @@ class QgsPropertyCollectionStack : QgsAbstractPropertyCollection
353369

354370
QSet<int> propertyKeys() const;
355371
bool hasProperty( int key ) const;
356-
bool writeXml( QDomElement& collectionElem, QDomDocument& doc, const QMap< int, QString >& propertyNameMap ) const;
357-
bool readXml( const QDomElement& collectionElem, const QDomDocument& doc, const QMap<int, QString> &propertyNameMap );
372+
bool writeXml( QDomElement& collectionElem, QDomDocument& doc, const QgsPropertyDefinition& propertyNameMap ) const;
373+
bool readXml( const QDomElement& collectionElem, const QDomDocument& doc, const QgsPropertyDefinition &propertyNameMap );
358374
};
359375

src/app/dwg/qgsdwgimportdialog.cpp

+13-15
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
#include "qgsgenericprojectionselector.h"
4343
#include "qgsmessagelog.h"
4444
#include "qgslogger.h"
45+
#include "qgsproperty.h"
4546

4647

4748
struct CursorOverride
@@ -358,14 +359,13 @@ void QgsDwgImportDialog::createGroup( QgsLayerTreeGroup *group, QString name, QS
358359
pls.drawLabels = true;
359360
pls.fieldName = "text";
360361
pls.wrapChar = "\\P";
361-
pls.setDataDefinedProperty( QgsPalLayerSettings::Size, true, false, "", "height" );
362-
pls.setDataDefinedProperty( QgsPalLayerSettings::Color, true, false, "", "color" );
363-
pls.setDataDefinedProperty( QgsPalLayerSettings::MultiLineHeight, true, true, "CASE WHEN interlin<0 THEN 1 ELSE interlin*1.5 END", "" );
364-
pls.placement = QgsPalLayerSettings::OrderedPositionsAroundPoint;
365-
pls.setDataDefinedProperty( QgsPalLayerSettings::PositionX, true, true, "$x", "" );
366-
pls.setDataDefinedProperty( QgsPalLayerSettings::PositionY, true, true, "$y", "" );
367-
pls.setDataDefinedProperty( QgsPalLayerSettings::Hali, true, true, QString(
368-
"CASE"
362+
363+
pls.properties().setProperty( QgsPalLayerSettings::Size, new QgsFieldBasedProperty( QStringLiteral( "height" ) ) );
364+
pls.properties().setProperty( QgsPalLayerSettings::Color, new QgsFieldBasedProperty( QStringLiteral( "color" ) ) );
365+
pls.properties().setProperty( QgsPalLayerSettings::MultiLineHeight, new QgsExpressionBasedProperty( QStringLiteral( "CASE WHEN interlin<0 THEN 1 ELSE interlin*1.5 END" ) ) );
366+
pls.properties().setProperty( QgsPalLayerSettings::PositionX, new QgsExpressionBasedProperty( QStringLiteral( "$x" ) ) );
367+
pls.properties().setProperty( QgsPalLayerSettings::PositionY, new QgsExpressionBasedProperty( QStringLiteral( "$y" ) ) );
368+
pls.properties().setProperty( QgsPalLayerSettings::Hali, new QgsExpressionBasedProperty( QStringLiteral( "CASE"
369369
" WHEN etype=%1 THEN"
370370
" CASE"
371371
" WHEN alignv IN (1,4,7) THEN 'Left'"
@@ -380,10 +380,8 @@ void QgsDwgImportDialog::createGroup( QgsLayerTreeGroup *group, QString name, QS
380380
" WHEN alignh=3 THEN 'Left'"
381381
" WHEN alignh=4 THEN 'Left'"
382382
" END "
383-
" END" ).arg( DRW::MTEXT ), "" );
384-
385-
pls.setDataDefinedProperty( QgsPalLayerSettings::Vali, true, true, QString(
386-
"CASE"
383+
" END" ).arg( DRW::MTEXT ) ) );
384+
pls.properties().setProperty( QgsPalLayerSettings::Vali, new QgsExpressionBasedProperty( QStringLiteral( "CASE"
387385
" WHEN etype=%1 THEN"
388386
" CASE"
389387
" WHEN alignv < 4 THEN 'Top'"
@@ -397,10 +395,10 @@ void QgsDwgImportDialog::createGroup( QgsLayerTreeGroup *group, QString name, QS
397395
" WHEN alignv=2 THEN 'Half'"
398396
" WHEN alignv=3 THEN 'Top'"
399397
" END"
400-
" END" ).arg( DRW::MTEXT ), "" );
401-
402-
pls.setDataDefinedProperty( QgsPalLayerSettings::Rotation, true, true, "angle*180.0/pi()", "" );
398+
" END" ).arg( DRW::MTEXT ) ) );
399+
pls.properties().setProperty( QgsPalLayerSettings::Rotation, new QgsExpressionBasedProperty( QStringLiteral( "angle*180.0/pi()" ) ) );
403400

401+
pls.placement = QgsPalLayerSettings::OrderedPositionsAroundPoint;
404402
pls.writeToLayer( l );
405403
}
406404

0 commit comments

Comments
 (0)