Index: python/core/qgsmaprenderer.sip =================================================================== --- python/core/qgsmaprenderer.sip (Revision 13948) +++ python/core/qgsmaprenderer.sip (Arbeitskopie) @@ -18,6 +18,9 @@ virtual bool willUseLayer( QgsVectorLayer* layer ) = 0; //! called when starting rendering of a layer virtual int prepareLayer(QgsVectorLayer* layer, int& attrIndex, QgsRenderContext& ctx ) = 0; + //! called when starting rendering of a layer + //! @note: this method was added in version 1.6 + virtual int prepareLayer( QgsVectorLayer* layer, QSet& attrIndices, QgsRenderContext& ctx ) = 0; //! called for every feature virtual void registerFeature( QgsVectorLayer* layer, QgsFeature& feat, const QgsRenderContext& context = QgsRenderContext() ) = 0; //! called when the map is drawn and labels should be placed Index: src/app/qgslabelinggui.h =================================================================== --- src/app/qgslabelinggui.h (Revision 13948) +++ src/app/qgslabelinggui.h (Arbeitskopie) @@ -48,6 +48,10 @@ protected: void populatePlacementMethods(); void populateFieldNames(); + void populateDataDefinedCombos( QgsPalLayerSettings& s ); + /**Sets data defined property attribute to map (if selected in combo box)*/ + void setDataDefinedProperty( const QComboBox* c, QgsPalLayerSettings::DataDefinedProperties p, QgsPalLayerSettings& lyr ); + void setCurrentComboValue( QComboBox* c, const QgsPalLayerSettings& s, QgsPalLayerSettings::DataDefinedProperties p ); void updateFont( QFont font ); private: Index: src/app/qgslabelinggui.cpp =================================================================== --- src/app/qgslabelinggui.cpp (Revision 13948) +++ src/app/qgslabelinggui.cpp (Arbeitskopie) @@ -70,6 +70,8 @@ QgsPalLayerSettings lyr; lyr.readFromLayer( layer ); + populateDataDefinedCombos( lyr ); + // placement switch ( lyr.placement ) { @@ -237,6 +239,18 @@ lyr.bufferSize = 0; } lyr.minFeatureSize = mMinSizeSpinBox->value(); + + //data defined labeling + setDataDefinedProperty( mSizeAttributeComboBox, QgsPalLayerSettings::Size, lyr ); + setDataDefinedProperty( mColorAttributeComboBox, QgsPalLayerSettings::Color, lyr ); + setDataDefinedProperty( mBoldAttributeComboBox, QgsPalLayerSettings::Bold, lyr ); + setDataDefinedProperty( mItalicAttributeComboBox, QgsPalLayerSettings::Italic, lyr ); + setDataDefinedProperty( mUnderlineAttributeComboBox, QgsPalLayerSettings::Underline, lyr ); + setDataDefinedProperty( mStrikeoutAttributeComboBox, QgsPalLayerSettings::Strikeout, lyr ); + setDataDefinedProperty( mFontFamilyAttributeComboBox, QgsPalLayerSettings::Family, lyr ); + setDataDefinedProperty( mBufferSizeAttributeComboBox, QgsPalLayerSettings:: BufferSize, lyr ); + setDataDefinedProperty( mBufferColorAttributeComboBox, QgsPalLayerSettings::BufferColor, lyr ); + return lyr; } @@ -250,6 +264,79 @@ } } +void QgsLabelingGui::setDataDefinedProperty( const QComboBox* c, QgsPalLayerSettings::DataDefinedProperties p, QgsPalLayerSettings& lyr ) +{ + if ( !c ) + { + return; + } + + QVariant propertyField = c->itemData( c->currentIndex() ); + if ( propertyField.isValid() ) + { + lyr.setDataDefinedProperty( p, propertyField.toInt() ); + } +} + +void QgsLabelingGui::setCurrentComboValue( QComboBox* c, const QgsPalLayerSettings& s, QgsPalLayerSettings::DataDefinedProperties p ) +{ + if ( !c ) + { + return; + } + + QMap< QgsPalLayerSettings::DataDefinedProperties, int >::const_iterator it = s.dataDefinedProperties.find( p ); + if ( it == s.dataDefinedProperties.constEnd() ) + { + c->setCurrentIndex( 0 ); + } + else + { + c->setCurrentIndex( c->findData( it.value() ) ); + } +} + +void QgsLabelingGui::populateDataDefinedCombos( QgsPalLayerSettings& s ) +{ + QList comboList; + comboList << mSizeAttributeComboBox; + comboList << mColorAttributeComboBox; + comboList << mBoldAttributeComboBox; + comboList << mItalicAttributeComboBox; + comboList << mUnderlineAttributeComboBox; + comboList << mStrikeoutAttributeComboBox; + comboList << mFontFamilyAttributeComboBox; + comboList << mBufferSizeAttributeComboBox; + comboList << mBufferColorAttributeComboBox; + + QList::iterator comboIt = comboList.begin(); + for ( ; comboIt != comboList.end(); ++comboIt ) + { + ( *comboIt )->addItem( "", QVariant() ); + } + + const QgsFieldMap& fields = mLayer->dataProvider()->fields(); + for ( QgsFieldMap::const_iterator it = fields.constBegin(); it != fields.constEnd(); it++ ) + { + for ( comboIt = comboList.begin(); comboIt != comboList.end(); ++comboIt ) + { + ( *comboIt )->addItem( it.value().name(), it.key() ); + } + + } + + //set current combo boxes to already existing indices + setCurrentComboValue( mSizeAttributeComboBox, s, QgsPalLayerSettings::Size ); + setCurrentComboValue( mColorAttributeComboBox, s, QgsPalLayerSettings::Color ); + setCurrentComboValue( mBoldAttributeComboBox, s, QgsPalLayerSettings::Bold ); + setCurrentComboValue( mItalicAttributeComboBox, s, QgsPalLayerSettings::Italic ); + setCurrentComboValue( mUnderlineAttributeComboBox, s, QgsPalLayerSettings::Underline ); + setCurrentComboValue( mStrikeoutAttributeComboBox, s, QgsPalLayerSettings::Strikeout ); + setCurrentComboValue( mFontFamilyAttributeComboBox, s, QgsPalLayerSettings::Family ); + setCurrentComboValue( mBufferSizeAttributeComboBox, s , QgsPalLayerSettings::BufferSize ); + setCurrentComboValue( mBufferColorAttributeComboBox, s, QgsPalLayerSettings::BufferColor ); +} + void QgsLabelingGui::changeTextColor() { QColor color = QColorDialog::getColor( btnTextColor->color(), this ); Index: src/core/qgsvectorlayer.cpp =================================================================== --- src/core/qgsvectorlayer.cpp (Revision 13948) +++ src/core/qgsvectorlayer.cpp (Arbeitskopie) @@ -922,11 +922,17 @@ bool labeling = false; if ( rendererContext.labelingEngine() ) { - int attrIndex; + QSet attrIndex; if ( rendererContext.labelingEngine()->prepareLayer( this, attrIndex, rendererContext ) ) { - if ( !attributes.contains( attrIndex ) ) - attributes << attrIndex; + QSet::const_iterator attIt = attrIndex.constBegin(); + for ( ; attIt != attrIndex.constEnd(); ++attIt ) + { + if ( !attributes.contains( *attIt ) ) + { + attributes << *attIt; + } + } labeling = true; } } @@ -978,11 +984,17 @@ bool labeling = false; if ( rendererContext.labelingEngine() ) { - int attrIndex; + QSet attrIndex; if ( rendererContext.labelingEngine()->prepareLayer( this, attrIndex, rendererContext ) ) { - if ( !attributes.contains( attrIndex ) ) - attributes << attrIndex; + QSet::const_iterator attIt = attrIndex.constBegin(); + for ( ; attIt != attrIndex.constEnd(); ++attIt ) + { + if ( !attributes.contains( *attIt ) ) + { + attributes << *attIt; + } + } labeling = true; } } Index: src/core/qgsmaprenderer.h =================================================================== --- src/core/qgsmaprenderer.h (Revision 13948) +++ src/core/qgsmaprenderer.h (Arbeitskopie) @@ -50,8 +50,11 @@ virtual void init( QgsMapRenderer* mp ) = 0; //! called to find out whether the layer is used for labeling virtual bool willUseLayer( QgsVectorLayer* layer ) = 0; + //! legacy method. Use prepareLayer with QSet for new code + virtual int prepareLayer( QgsVectorLayer* layer, int& attributeIndex, QgsRenderContext& ctx ) = 0; //! called when starting rendering of a layer - virtual int prepareLayer( QgsVectorLayer* layer, int& attrIndex, QgsRenderContext& ctx ) = 0; + //! @note: this method was added in version 1.6 + virtual int prepareLayer( QgsVectorLayer* layer, QSet& attrIndices, QgsRenderContext& ctx ) = 0; //! called for every feature virtual void registerFeature( QgsVectorLayer* layer, QgsFeature& feat, const QgsRenderContext& context = QgsRenderContext() ) = 0; //! called when the map is drawn and labels should be placed Index: src/core/qgspallabeling.cpp =================================================================== --- src/core/qgspallabeling.cpp (Revision 13948) +++ src/core/qgspallabeling.cpp (Arbeitskopie) @@ -95,12 +95,17 @@ return mInfo; } + const QMap< QgsPalLayerSettings::DataDefinedProperties, QVariant >& dataDefinedValues() const { return mDataDefinedValues; } + void addDataDefinedValue( QgsPalLayerSettings::DataDefinedProperties p, QVariant v ) { mDataDefinedValues.insert( p, v ); } + protected: GEOSGeometry* mG; QString mText; QByteArray mStrId; int mId; LabelInfo* mInfo; + /**Stores attribute values for data defined properties*/ + QMap< QgsPalLayerSettings::DataDefinedProperties, QVariant > mDataDefinedValues; }; // ------------- @@ -151,6 +156,7 @@ vectorScaleFactor = s.vectorScaleFactor; rasterCompressFactor = s.rasterCompressFactor; + dataDefinedProperties = s.dataDefinedProperties; fontMetrics = NULL; ct = NULL; } @@ -179,6 +185,64 @@ layer->setCustomProperty( property + "B", color.blue() ); } +static void _writeDataDefinedPropertyMap( QgsVectorLayer* layer, const QMap< QgsPalLayerSettings::DataDefinedProperties, int >& propertyMap ) +{ + if ( !layer ) + { + return; + } + + for ( int i = 0; i < 9; ++i ) + { + QMap< QgsPalLayerSettings::DataDefinedProperties, int >::const_iterator it = propertyMap.find(( QgsPalLayerSettings::DataDefinedProperties )i ); + QVariant propertyValue; + if ( it == propertyMap.constEnd() ) + { + propertyValue = QVariant(); //we cannot delete properties, so we just insert an invalid variant + } + else + { + propertyValue = *it; + } + layer->setCustomProperty( "labeling/dataDefinedProperty" + QString::number( i ), propertyValue ); + } +} + +static void _readDataDefinedProperty( QgsVectorLayer* layer, QgsPalLayerSettings::DataDefinedProperties p, \ + QMap< QgsPalLayerSettings::DataDefinedProperties, int >& propertyMap ) +{ + QVariant propertyField = layer->customProperty( "labeling/dataDefinedProperty" + QString::number( p ) ); + bool conversionOk; + int fieldIndex; + + if ( propertyField.isValid() ) + { + fieldIndex = propertyField.toInt( &conversionOk ); + if( conversionOk ) + { + propertyMap.insert( p, fieldIndex ); + } + } +} + +static void _readDataDefinedPropertyMap( QgsVectorLayer* layer, QMap< QgsPalLayerSettings::DataDefinedProperties, int >& propertyMap ) +{ + if ( !layer ) + { + return; + } + + _readDataDefinedProperty( layer, QgsPalLayerSettings::Size, propertyMap ); + _readDataDefinedProperty( layer, QgsPalLayerSettings::Color, propertyMap ); + _readDataDefinedProperty( layer, QgsPalLayerSettings::Bold, propertyMap ); + _readDataDefinedProperty( layer, QgsPalLayerSettings::Italic, propertyMap ); + _readDataDefinedProperty( layer, QgsPalLayerSettings::Underline, propertyMap ); + _readDataDefinedProperty( layer, QgsPalLayerSettings::Strikeout, propertyMap ); + _readDataDefinedProperty( layer, QgsPalLayerSettings::Family, propertyMap ); + _readDataDefinedProperty( layer, QgsPalLayerSettings::BufferSize, propertyMap ); + _readDataDefinedProperty( layer, QgsPalLayerSettings::BufferColor, propertyMap ); +} + void QgsPalLayerSettings::readFromLayer( QgsVectorLayer* layer ) { if ( layer->customProperty( "labeling" ).toString() != QString( "pal" ) ) @@ -205,6 +269,7 @@ mergeLines = layer->customProperty( "labeling/mergeLines" ).toBool(); multiLineLabels = layer->customProperty( "labeling/multiLineLabels" ).toBool(); minFeatureSize = layer->customProperty( "labeling/minFeatureSize" ).toDouble(); + _readDataDefinedPropertyMap( layer, dataDefinedProperties ); } void QgsPalLayerSettings::writeToLayer( QgsVectorLayer* layer ) @@ -234,8 +299,19 @@ layer->setCustomProperty( "labeling/mergeLines", mergeLines ); layer->setCustomProperty( "labeling/multiLineLabels", multiLineLabels ); layer->setCustomProperty( "labeling/minFeatureSize", minFeatureSize ); + _writeDataDefinedPropertyMap( layer, dataDefinedProperties ); } +void QgsPalLayerSettings::setDataDefinedProperty( DataDefinedProperties p, int attributeIndex ) +{ + dataDefinedProperties.insert( p, attributeIndex ); +} + +void QgsPalLayerSettings::removeDataDefinedProperty( DataDefinedProperties p ) +{ + dataDefinedProperties.remove( p ); +} + bool QgsPalLayerSettings::checkMinimumSizeMM( const QgsRenderContext& ct, QgsGeometry* geom, double minSize ) const { if ( minSize <= 0 ) @@ -274,9 +350,14 @@ return true; //should never be reached. Return true in this case to label such geometries anyway. } -void QgsPalLayerSettings::calculateLabelSize( QString text, double& labelX, double& labelY ) +void QgsPalLayerSettings::calculateLabelSize( const QFontMetrics* fm, QString text, double& labelX, double& labelY ) { - QRectF labelRect = fontMetrics->boundingRect( text ); + if ( !fm ) + { + return; + } + + QRectF labelRect = fm->boundingRect( text ); double w, h; if ( !multiLineLabels ) { @@ -286,11 +367,11 @@ else { QStringList multiLineSplit = text.split( "\n" ); - h = fontMetrics->height() * multiLineSplit.size() / rasterCompressFactor; + h = fm->height() * multiLineSplit.size() / rasterCompressFactor; w = 0; for ( int i = 0; i < multiLineSplit.size(); ++i ) { - double width = fontMetrics->width( multiLineSplit.at( i ) ); + double width = fm->width( multiLineSplit.at( i ) ); if ( width > w ) { w = width; @@ -309,8 +390,31 @@ { QString labelText = f.attributeMap()[fieldIndex].toString(); double labelX, labelY; // will receive label size - calculateLabelSize( labelText, labelX, labelY ); + //data defined label size? + QMap< DataDefinedProperties, int >::const_iterator it = dataDefinedProperties.find( QgsPalLayerSettings::Size ); + if( it != dataDefinedProperties.constEnd() ) + { + QFont labelFont = textFont; + //find out size + QVariant size = f.attributeMap().value( *it ); + if ( size.isValid() ) + { + double sizeDouble = size.toDouble(); + if ( sizeDouble <= 0 ) + { + return; + } + labelFont.setPointSize( sizeToPixel( sizeDouble, context ) ); + } + QFontMetrics labelFontMetrics( labelFont ); + calculateLabelSize( &labelFontMetrics, labelText, labelX, labelY ); + } + else + { + calculateLabelSize( fontMetrics, labelText, labelX, labelY ); + } + QgsGeometry* geom = f.geometry(); if ( ct != NULL ) // reproject the geometry if necessary geom->transform( *ct ); @@ -344,9 +448,23 @@ // TODO: allow layer-wide feature dist in PAL...? if ( dist != 0 ) feat->setDistLabel( fabs( ptOne.x() - ptZero.x() )* dist * vectorScaleFactor ); + + //add parameters for data defined labeling to QgsPalGeometry + QMap< DataDefinedProperties, int >::const_iterator dIt = dataDefinedProperties.constBegin(); + for ( ; dIt != dataDefinedProperties.constEnd(); ++dIt ) + { + lbl->addDataDefinedValue( dIt.key(), f.attributeMap()[dIt.value()] ); + } } +int QgsPalLayerSettings::sizeToPixel( double size, const QgsRenderContext& c ) const +{ + // set font size from points to output size + double pixelSize = 0.3527 * size * c.scaleFactor() * c.rasterScaleFactor() + 0.5; + return ( int )pixelSize; +} + // ------------- QgsPalLabeling::QgsPalLabeling() @@ -387,8 +505,20 @@ return lyrTmp.enabled; } +int QgsPalLabeling::prepareLayer( QgsVectorLayer* layer, int& attributeIndex, QgsRenderContext& ctx ) +{ + //for backward compatibility + QSet attributeSet; + prepareLayer( layer, attributeSet, ctx ); + if ( attributeSet.size() > 0 ) + { + attributeIndex = *attributeSet.constBegin(); + } + return 1; +} -int QgsPalLabeling::prepareLayer( QgsVectorLayer* layer, int& attrIndex, QgsRenderContext& ctx ) + +int QgsPalLabeling::prepareLayer( QgsVectorLayer* layer, QSet& attrIndices, QgsRenderContext& ctx ) { Q_ASSERT( mMapRenderer != NULL ); @@ -403,8 +533,15 @@ int fldIndex = layer->fieldNameIndex( lyrTmp.fieldName ); if ( fldIndex == -1 ) return 0; - attrIndex = fldIndex; + attrIndices.insert( fldIndex ); + //add indices of data defined fields + QMap< QgsPalLayerSettings::DataDefinedProperties, int >::const_iterator dIt = lyrTmp.dataDefinedProperties.constBegin(); + for ( ; dIt != lyrTmp.dataDefinedProperties.constEnd(); ++dIt ) + { + attrIndices.insert( dIt.value() ); + } + // add layer settings to the pallabeling hashtable: mActiveLayers.insert( layer, lyrTmp ); // start using the reference to the layer in hashtable instead of local instance @@ -445,10 +582,7 @@ // set whether adjacent lines should be merged l->setMergeConnectedLines( lyr.mergeLines ); - // set font size from points to output size - double size = 0.3527 * lyr.textFont.pointSizeF() * ctx.scaleFactor(); - // request larger font and then scale down painter (to avoid Qt font scale bug) - lyr.textFont.setPixelSize(( int )( size*ctx.rasterScaleFactor() + 0.5 ) ); + lyr.textFont.setPixelSize( lyr.sizeToPixel( lyr.textFont.pointSizeF(), ctx ) ); //raster and vector scale factors lyr.vectorScaleFactor = ctx.scaleFactor(); @@ -587,11 +721,86 @@ for ( ; it != labels->end(); ++it ) { const QgsPalLayerSettings& lyr = layer(( *it )->getLayerName() ); + QFont fontForLabel = lyr.textFont; + QColor fontColor = lyr.textColor; + double bufferSize = lyr.bufferSize; + QColor bufferColor = lyr.bufferColor; + QgsPalGeometry* palGeometry = dynamic_cast< QgsPalGeometry* >(( *it )->getFeaturePart()->getUserGeometry() ); + if ( !palGeometry ) + { + continue; + } + + //apply data defined settings for the label + //font size + QVariant dataDefinedSize = palGeometry->dataDefinedValues().value( QgsPalLayerSettings::Size ); + if ( dataDefinedSize.isValid() ) + { + fontForLabel.setPointSize( lyr.sizeToPixel( dataDefinedSize.toDouble(), context ) ); + } + //font color + QVariant dataDefinedColor = palGeometry->dataDefinedValues().value( QgsPalLayerSettings::Color ); + if ( dataDefinedColor.isValid() ) + { + fontColor.setNamedColor( dataDefinedColor.toString() ); + if ( !fontColor.isValid() ) + { + fontColor = lyr.textColor; + } + } + //font bold + QVariant dataDefinedBold = palGeometry->dataDefinedValues().value( QgsPalLayerSettings::Bold ); + if ( dataDefinedBold.isValid() ) + { + fontForLabel.setBold(( bool )dataDefinedBold.toInt() ); + } + //font italic + QVariant dataDefinedItalic = palGeometry->dataDefinedValues().value( QgsPalLayerSettings::Italic ); + if ( dataDefinedItalic.isValid() ) + { + fontForLabel.setItalic(( bool ) dataDefinedItalic.toInt() ); + } + //font underline + QVariant dataDefinedUnderline = palGeometry->dataDefinedValues().value( QgsPalLayerSettings::Underline ); + if ( dataDefinedUnderline.isValid() ) + { + fontForLabel.setUnderline(( bool ) dataDefinedUnderline.toInt() ); + } + //font strikeout + QVariant dataDefinedStrikeout = palGeometry->dataDefinedValues().value( QgsPalLayerSettings::Strikeout ); + if ( dataDefinedStrikeout.isValid() ) + { + fontForLabel.setStrikeOut(( bool ) dataDefinedStrikeout.toInt() ); + } + //font family + QVariant dataDefinedFontFamily = palGeometry->dataDefinedValues().value( QgsPalLayerSettings::Family ); + if ( dataDefinedFontFamily.isValid() ) + { + fontForLabel.setFamily( dataDefinedFontFamily.toString() ); + } + //buffer size + QVariant dataDefinedBufferSize = palGeometry->dataDefinedValues().value( QgsPalLayerSettings::BufferSize ); + if ( dataDefinedBufferSize.isValid() ) + { + bufferSize = dataDefinedBufferSize.toDouble(); + } + + //buffer color + QVariant dataDefinedBufferColor = palGeometry->dataDefinedValues().value( QgsPalLayerSettings::BufferColor ); + if ( dataDefinedBufferColor.isValid() ) + { + bufferColor.setNamedColor( dataDefinedBufferColor.toString() ); + if ( !bufferColor.isValid() ) + { + bufferColor = lyr.bufferColor; + } + } + if ( lyr.bufferSize != 0 ) - drawLabel( *it, painter, xform, true ); + drawLabel( *it, painter, fontForLabel, fontColor, xform, bufferSize, bufferColor, true ); - drawLabel( *it, painter, xform ); + drawLabel( *it, painter, fontForLabel, fontColor, xform ); } QgsDebugMsg( QString( "LABELING draw: %1 ms" ).arg( t.elapsed() ) ); @@ -660,7 +869,8 @@ #include "qgslogger.h" -void QgsPalLabeling::drawLabel( pal::LabelPosition* label, QPainter* painter, const QgsMapToPixel* xform, bool drawBuffer ) +void QgsPalLabeling::drawLabel( pal::LabelPosition* label, QPainter* painter, const QFont& f, const QColor& c, const QgsMapToPixel* xform, double bufferSize, \ + const QColor& bufferColor, bool drawBuffer ) { QgsPoint outPt = xform->transform( label->getX(), label->getY() ); @@ -698,21 +908,21 @@ if ( drawBuffer ) { // we're drawing buffer - drawLabelBuffer( painter, multiLineList.at( i ), lyr.textFont, lyr.bufferSize * lyr.vectorScaleFactor * lyr.rasterCompressFactor , lyr.bufferColor ); + drawLabelBuffer( painter, multiLineList.at( i ), f, bufferSize * lyr.vectorScaleFactor * lyr.rasterCompressFactor , bufferColor ); } else { // we're drawing real label QPainterPath path; - path.addText( 0, 0, lyr.textFont, multiLineList.at( i ) ); + path.addText( 0, 0, f, multiLineList.at( i ) ); painter->setPen( Qt::NoPen ); - painter->setBrush( lyr.textColor ); + painter->setBrush( c ); painter->drawPath( path ); } painter->restore(); if ( label->getNextPart() ) - drawLabel( label->getNextPart(), painter, xform, drawBuffer ); + drawLabel( label->getNextPart(), painter, f, c, xform, drawBuffer ); } } Index: src/core/qgspallabeling.h =================================================================== --- src/core/qgspallabeling.h (Revision 13948) +++ src/core/qgspallabeling.h (Arbeitskopie) @@ -72,6 +72,19 @@ MapOrientation = 8 }; + enum DataDefinedProperties + { + Size = 0, + Bold, + Italic, + Underline, + Color, + Strikeout, + Family, + BufferSize, + BufferColor, + }; + QString fieldName; Placement placement; unsigned int placementFlags; @@ -92,7 +105,7 @@ double minFeatureSize; // minimum feature size to be labelled (in mm) // called from register feature hook - void calculateLabelSize( QString text, double& labelX, double& labelY ); + void calculateLabelSize( const QFontMetrics* fm, QString text, double& labelX, double& labelY ); // implementation of register feature hook void registerFeature( QgsFeature& f, const QgsRenderContext& context ); @@ -100,6 +113,11 @@ void readFromLayer( QgsVectorLayer* layer ); void writeToLayer( QgsVectorLayer* layer ); + /**Set a property as data defined*/ + void setDataDefinedProperty( DataDefinedProperties p, int attributeIndex ); + /**Set a property to static instead data defined*/ + void removeDataDefinedProperty( DataDefinedProperties p ); + // temporary stuff: set when layer gets prepared pal::Layer* palLayer; int fieldIndex; @@ -109,6 +127,15 @@ QgsPoint ptZero, ptOne; QList geometries; + /**Stores field indices for data defined layer properties*/ + QMap< DataDefinedProperties, int > dataDefinedProperties; + + /**Calculates pixel size (considering scale factors and oversampling) + @param label size (pixels, possibily map units in future) + @param c rendercontext + @return font pixel size*/ + int sizeToPixel( double size, const QgsRenderContext& c ) const; + private: /**Checks if a feature is larger than a minimum size (in mm) @return true if above size, false if below*/ @@ -153,8 +180,10 @@ virtual void init( QgsMapRenderer* mr ); //! called to find out whether the layer is used for labeling virtual bool willUseLayer( QgsVectorLayer* layer ); + //! legacy method. Use prepareLayer with QSet for new code + virtual int prepareLayer( QgsVectorLayer* layer, int& attributeIndex, QgsRenderContext& ctx ); //! hook called when drawing layer before issuing select() - virtual int prepareLayer( QgsVectorLayer* layer, int& attrIndex, QgsRenderContext& ctx ); + virtual int prepareLayer( QgsVectorLayer* layer, QSet& attrIndices, QgsRenderContext& ctx ); //! hook called when drawing for every feature in a layer virtual void registerFeature( QgsVectorLayer* layer, QgsFeature& feat, const QgsRenderContext& context = QgsRenderContext() ); //! called when the map is drawn and labels should be placed @@ -166,14 +195,15 @@ virtual QgsLabelingEngineInterface* clone(); void drawLabelCandidateRect( pal::LabelPosition* lp, QPainter* painter, const QgsMapToPixel* xform ); - void drawLabel( pal::LabelPosition* label, QPainter* painter, const QgsMapToPixel* xform, bool drawBuffer = false ); + //!drawLabel + void drawLabel( pal::LabelPosition* label, QPainter* painter, const QFont& f, const QColor& c, const QgsMapToPixel* xform, double bufferSize = -1, \ + const QColor& bufferColor = QColor( 255, 255, 255 ), bool drawBuffer = false ); static void drawLabelBuffer( QPainter* p, QString text, const QFont& font, double size, QColor color ); protected: void initPal(); - protected: // temporary hashtable of layer settings, being filled during labeling, cleared once labeling's done QHash mActiveLayers; Index: src/ui/qgslabelingguibase.ui =================================================================== --- src/ui/qgslabelingguibase.ui (Revision 13948) +++ src/ui/qgslabelingguibase.ui (Arbeitskopie) @@ -6,8 +6,8 @@ 0 0 - 482 - 610 + 496 + 659 @@ -17,719 +17,869 @@ ../../../../.designer/backup../../../../.designer/backup - + - - - Label this layer + + + 0 - - - - - - - - Field with labels - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - Placement - - - - 0 - - - 0 - - - 0 - - - 4 - - - - - 0 - - - - - - - around point - - - true - - - - - - - over point - - - - + + + Label settings + + + + + + Label this layer + - - + + + + + + + Field with labels + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + Placement + + + + 0 + + + 0 + + + 0 + + + 4 + - - - parallel + + + 2 - - true - + + + + + + around point + + + true + + + + + + + over point + + + + + + + + + + + parallel + + + true + + + + + + + curved + + + + + + + horizontal + + + + + + + + + + + over centroid + + + true + + + + + + + around centroid + + + + + + + horizontal (slow) + + + + + + + free (slow) + + + + + + + using perimeter + + + + + - - - curved + + + Qt::Vertical - - - horizontal + + + 1 + + + + + + Label distance + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + 2 + + + + + + + mm + + + + + + + Rotation + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + false + + + + + + + degrees + + + + + + + + + + + above line + + + true + + + + + + + on line + + + + + + + below line + + + + + + + + + Orientation + + + + + + + map + + + true + + + + + + + line + + + + + + + + + + + Label distance + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + 2 + + + + + + + mm + + + + + + + + - - - - - - over centroid - - - true - - - - - - - around centroid - - - - - - - horizontal (slow) - - - - - - - free (slow) - - - - - - - using perimeter - - - - - - - - - - - Qt::Vertical - - - - - - - 0 - - - - - - - Label distance - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - 2 - - - - - - - mm - - - - - - - Rotation - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - false - - - - - - - degrees - - - - - - - - - - - above line - - - true - - - - - - - on line - - - - - - - below line - - - - - - - + + + + + + + Text style + + + + + + + 0 + 0 + + - Orientation + Font + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 1 + 0 + + + + TextLabel + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + ... + + + + + + + + + + 0 + 0 + + + + Color + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + + + 0 + 0 + + + + + + + + + + + Qt::Horizontal + + + QSizePolicy::Preferred + + + + 142 + 20 + + + + + + + + + + Buffer + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + + + 0 + 0 + + + + + + + + + + + Size + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + mm + + + + + + + Color + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 0 + 0 + + + + ... + + + + + + + + + + 0 + 0 + + + + Sample + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 30 + 30 + + + + Lorem Ipsum + + + Qt::AlignCenter + + + + + + + Qt::Horizontal + + + + + + + + + + Priority + + - + - map + Low - - true + + + + + + 10 + + 5 + + + Qt::Horizontal + + + QSlider::TicksBelow + + + 1 + - + - line + High - - - - - + + + + + + Scale-based visibility + + + + - Label distance + Enabled + + + + + + Minimum + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - 2 + + + + 1 + + 10000000 + - - + + - mm + Maximum + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + 1 + + + 10000000 + + + 10000000 + + + + + + + + + + + label every part of multi-part features + + + + + + + merge connected lines to avoid duplicate labels + + + + + + + multiline labels + + + + + + + + + Suppress labeling of features smaller than + + + + + + + mm + + + + + + + + + + + true + + + features don't act as obstacles for labels + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + true + + + Engine settings + + + + + + + + + + Data defined settings + + + + + + + 0 + 0 + + + + Font properties + + + + + + + + Size + + + + + + + + + + Bold + + + + + + + + + + + + + Color + + + + + + + + + + Italic + + + + + + + + + + Underline + + + + + + + + + + Font family + + + + + + + + + + Strikeout + + + + - - - - - - - - - - - - Text style - - - - - - - 0 - 0 - - - - Font - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - - - 1 - 0 - - - - TextLabel - - + + + + + Buffer properties + + + + + + + + Buffer size + + + + + + + + + + Buffer color + + + + + + + - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - ... - - - - - - - - - 0 - 0 - - - - Color - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - - - 0 - 0 - - - - - - - - - - - Qt::Horizontal - - - QSizePolicy::Preferred - - - - 142 - 20 - - - - - - - - - - Buffer - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - - - 0 - 0 - - - - - - - - - - - Size - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - mm - - - - - - - Color - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - 0 - 0 - - - - ... - - - - - - - - - - 0 - 0 - - - - Sample - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - 30 - 30 - - - - Lorem Ipsum - - - Qt::AlignCenter - - - - - - - Qt::Horizontal - - - - - - - - - - Priority - - - - - - Low - - - - - - - 10 - - - 5 - - - Qt::Horizontal - - - QSlider::TicksBelow - - - 1 - - - - - - - High - - - - - - - - - - Scale-based visibility - - - - - - Enabled - - - - - - - Minimum - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - 1 - - - 10000000 - - - - - - - Maximum - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - 1 - - - 10000000 - - - 10000000 - - - - - - - - - - - - label every part of multi-part features - + + + + + + Qt::Vertical + + + + 20 + 521 + + + + + + - - - - merge connected lines to avoid duplicate labels - - - - - - - - - Suppress labeling of features smaller than - - - - - - - mm - - - - - - - - - - - true - - - features don't act as obstacles for labels - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - true - - - Engine settings - - - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - + Qt::Horizontal @@ -739,13 +889,6 @@ - - - - multiline labels - - - @@ -762,28 +905,6 @@ - chkEnableLabeling - cboFieldName - radAroundPoint - radOverPoint - radLineParallel - radLineHorizontal - radAroundCentroid - radPolygonHorizontal - radPolygonFree - spinDistPoint - spinAngle - spinDistLine - btnChangeFont - btnTextColor - chkBuffer - btnBufferColor - sliderPriority - chkScaleBasedVisibility - spinScaleMin - spinScaleMax - chkNoObstacle - btnEngineSettings buttonBox