add support for multiline labels (applies #1138)

git-svn-id: http://svn.osgeo.org/qgis/trunk@8775 c8812cc2-4d05-0410-92ff-de0c093fc19c
This commit is contained in:
jef 2008-07-14 20:21:57 +00:00
parent 3c13ecf648
commit b5948bde31
8 changed files with 151 additions and 53 deletions

View File

@ -30,13 +30,14 @@ public:
YOffset, YOffset,
Angle, Angle,
Alignment, Alignment,
BufferEnabled, BufferEnabled,
BufferSize, BufferSize,
BufferColor, BufferColor,
BufferBrush, BufferBrush,
BorderWidth, BorderWidth,
BorderColor, BorderColor,
BorderStyle, BorderStyle,
MultilineEnabled,
LabelFieldCount LabelFieldCount
}; };
@ -46,7 +47,7 @@ public:
void renderLabel ( QPainter* painter, QgsRect& viewExtent, void renderLabel ( QPainter* painter, QgsRect& viewExtent,
QgsCoordinateTransform* coordTransform, QgsCoordinateTransform* coordTransform,
QgsMapToPixel *transform, QgsMapToPixel *transform,
QgsFeature &feature, bool selected, QgsLabelAttributes *classAttributes=0, double sizeScale = 1); QgsFeature &feature, bool selected, QgsLabelAttributes *classAttributes=0, double sizeScale = 1);
/** Reads the renderer configuration from an XML file /** Reads the renderer configuration from an XML file
@param rnode the DOM node to read @param rnode the DOM node to read

View File

@ -101,6 +101,8 @@ public:
void setBorderStyle ( Qt::PenStyle style ); void setBorderStyle ( Qt::PenStyle style );
bool borderStyleIsSet ( ) const; bool borderStyleIsSet ( ) const;
Qt::PenStyle borderStyle ( ) const; Qt::PenStyle borderStyle ( ) const;
bool multilineEnabled() const;
void setMultilineEnabled( bool useMultiline );
}; };

View File

@ -239,6 +239,8 @@ void QgsLabelDialog::init ( )
{ {
spinBufferSize->setValue(1); spinBufferSize->setValue(1);
} }
//set the state of the multiline enabled checkbox
chkUseMultiline->setChecked(myLabelAttributes->multilineEnabled());
//set the state of the buffer enabled checkbox //set the state of the buffer enabled checkbox
chkUseBuffer->setChecked(myLabelAttributes->bufferEnabled()); chkUseBuffer->setChecked(myLabelAttributes->bufferEnabled());
@ -360,6 +362,7 @@ void QgsLabelDialog::apply()
if (radioBelow->isChecked()) myLabelAttributes->setAlignment(Qt::AlignTop | Qt::AlignHCenter); if (radioBelow->isChecked()) myLabelAttributes->setAlignment(Qt::AlignTop | Qt::AlignHCenter);
if (radioOver->isChecked()) myLabelAttributes->setAlignment(Qt::AlignCenter); if (radioOver->isChecked()) myLabelAttributes->setAlignment(Qt::AlignCenter);
myLabelAttributes->setMultilineEnabled(chkUseMultiline->isChecked());
myLabelAttributes->setBufferEnabled(chkUseBuffer->isChecked()); myLabelAttributes->setBufferEnabled(chkUseBuffer->isChecked());
myLabelAttributes->setBufferColor(mBufferColor); myLabelAttributes->setBufferColor(mBufferColor);
myTypeInt = 0; myTypeInt = 0;

View File

@ -71,7 +71,7 @@ QString QgsLabel::fieldValue ( int attr, QgsFeature &feature )
const QgsAttributeMap& attrs = feature.attributeMap(); const QgsAttributeMap& attrs = feature.attributeMap();
QgsAttributeMap::const_iterator it = attrs.find(mLabelFieldIdx[attr]); QgsAttributeMap::const_iterator it = attrs.find(mLabelFieldIdx[attr]);
if (it != attrs.end()) if (it != attrs.end())
{ {
return it->toString(); return it->toString();
@ -86,7 +86,7 @@ void QgsLabel::renderLabel( QPainter * painter, const QgsRect& viewExtent,
const QgsCoordinateTransform* coordTransform, const QgsCoordinateTransform* coordTransform,
const QgsMapToPixel *transform, const QgsMapToPixel *transform,
QgsFeature &feature, bool selected, QgsLabelAttributes *classAttributes, QgsFeature &feature, bool selected, QgsLabelAttributes *classAttributes,
double sizeScale ) double sizeScale )
{ {
QPen pen; QPen pen;
@ -137,20 +137,20 @@ void QgsLabel::renderLabel( QPainter * painter, const QgsRect& viewExtent,
int sizeType; int sizeType;
value = fieldValue ( SizeType, feature ); value = fieldValue ( SizeType, feature );
if( value.isEmpty() ) if( value.isEmpty() )
sizeType = mLabelAttributes->sizeType(); sizeType = mLabelAttributes->sizeType();
else else
{ {
value = value.toLower(); value = value.toLower();
if( value.compare("mapunits") == 0 ) if( value.compare("mapunits") == 0 )
sizeType = QgsLabelAttributes::MapUnits; sizeType = QgsLabelAttributes::MapUnits;
else else
sizeType = QgsLabelAttributes::PointUnits; sizeType = QgsLabelAttributes::PointUnits;
} }
if ( sizeType == QgsLabelAttributes::MapUnits ) if ( sizeType == QgsLabelAttributes::MapUnits )
{ {
size *= scale; size *= scale;
} else { } else {
size *= sizeScale; size *= sizeScale;
} }
if(size>0.0) if(size>0.0)
font.setPointSizeF ( size ); font.setPointSizeF ( size );
@ -214,8 +214,26 @@ void QgsLabel::renderLabel( QPainter * painter, const QgsRect& viewExtent,
/* Alignment */ /* Alignment */
int alignment; int alignment;
QFontMetrics fm ( font ); QFontMetrics fm ( font );
int width = fm.width ( text ); int width, height;
int height = fm.height();
if( mLabelAttributes->multilineEnabled() )
{
QStringList texts = text.split("\n");
width=0;
for(int i=0; i<texts.size(); i++) {
int w = fm.width(texts[i]);
if(w>width)
width=w;
}
height = fm.height()*texts.size();
}
else
{
width = fm.width ( text );
height = fm.height();
}
int dx = 0; int dx = 0;
int dy = 0; int dy = 0;
@ -226,23 +244,23 @@ void QgsLabel::renderLabel( QPainter * painter, const QgsRect& viewExtent,
} }
else else
{ {
value = value.toLower(); value = value.toLower();
alignment=0; alignment=0;
if ( value.contains("left") ) if ( value.contains("left") )
alignment |= Qt::AlignLeft; alignment |= Qt::AlignLeft;
else if( value.contains("right") ) else if( value.contains("right") )
alignment |= Qt::AlignRight; alignment |= Qt::AlignRight;
else else
alignment |= Qt::AlignHCenter; alignment |= Qt::AlignHCenter;
if( value.contains("bottom") ) if( value.contains("bottom") )
alignment |= Qt::AlignBottom; alignment |= Qt::AlignBottom;
else if( value.contains("top") ) else if( value.contains("top") )
alignment |= Qt::AlignTop; alignment |= Qt::AlignTop;
else else
alignment |= Qt::AlignVCenter; alignment |= Qt::AlignVCenter;
} }
if ( alignment & Qt::AlignLeft ) if ( alignment & Qt::AlignLeft )
@ -319,7 +337,7 @@ void QgsLabel::renderLabel( QPainter * painter, const QgsRect& viewExtent,
{ {
renderLabel(painter, overridePoint, coordTransform, renderLabel(painter, overridePoint, coordTransform,
transform, text, font, pen, dx, dy, transform, text, font, pen, dx, dy,
xoffset, yoffset, ang); xoffset, yoffset, ang, width, height, alignment);
} }
else else
{ {
@ -329,7 +347,7 @@ void QgsLabel::renderLabel( QPainter * painter, const QgsRect& viewExtent,
{ {
renderLabel(painter, points[i], coordTransform, renderLabel(painter, points[i], coordTransform,
transform, text, font, pen, dx, dy, transform, text, font, pen, dx, dy,
xoffset, yoffset, ang); xoffset, yoffset, ang, width, height, alignment);
} }
} }
} }
@ -340,7 +358,8 @@ void QgsLabel::renderLabel(QPainter* painter, QgsPoint point,
QString text, QFont font, QPen pen, QString text, QFont font, QPen pen,
int dx, int dy, int dx, int dy,
double xoffset, double yoffset, double xoffset, double yoffset,
double ang) double ang,
int width, int height, int alignment)
{ {
// Convert point to projected units // Convert point to projected units
if (coordTransform) if (coordTransform)
@ -372,31 +391,38 @@ void QgsLabel::renderLabel(QPainter* painter, QgsPoint point,
painter->setFont ( font ); painter->setFont ( font );
painter->translate ( x, y ); painter->translate ( x, y );
painter->rotate ( -ang ); painter->rotate ( -ang );
// //
// Draw a buffer behind the text if one is desired // Draw a buffer behind the text if one is desired
// //
if (mLabelAttributes->bufferSizeIsSet() && mLabelAttributes->bufferEnabled()) if (mLabelAttributes->bufferSizeIsSet() && mLabelAttributes->bufferEnabled())
{ {
int myBufferSize = static_cast<int>(mLabelAttributes->bufferSize()); int myBufferSize = static_cast<int>(mLabelAttributes->bufferSize());
if (mLabelAttributes->bufferColorIsSet()) if (mLabelAttributes->bufferColorIsSet())
{
painter->setPen( mLabelAttributes->bufferColor());
}
else //default to a white buffer
{
painter->setPen( Qt::white);
}
for (int i = dx-myBufferSize; i <= dx+myBufferSize; i++)
{
for (int j = dy-myBufferSize; j <= dy+myBufferSize; j++)
{ {
painter->setPen( mLabelAttributes->bufferColor()); if( mLabelAttributes->multilineEnabled() )
} painter->drawText( i , j-height, width, height, alignment, text);
else //default to a white buffer else
{ painter->drawText( i , j, text);
painter->setPen( Qt::white);
}
for (int i = dx-myBufferSize; i <= dx+myBufferSize; i++)
{
for (int j = dy-myBufferSize; j <= dy+myBufferSize; j++)
{
painter->drawText( i ,j, text);
}
} }
}
} }
painter->setPen ( pen ); painter->setPen ( pen );
painter->drawText ( dx, dy, text ); if( mLabelAttributes->multilineEnabled() )
painter->drawText ( dx, dy-height, width, height, alignment, text );
else
painter->drawText ( dx, dy, text );
painter->restore(); painter->restore();
} }
@ -882,6 +908,20 @@ void QgsLabel::readXML( const QDomNode& node )
setLabelField ( BufferEnabled, _elementFieldIndex(el) ); setLabelField ( BufferEnabled, _elementFieldIndex(el) );
} }
scratchNode = node.namedItem("multilineenabled");
if ( scratchNode.isNull() )
{
QgsDebugMsg("couldn't find QgsLabel ``multilineenabled'' attribute");
}
else
{
el = scratchNode.toElement();
mLabelAttributes->setMultilineEnabled ( (bool)el.attribute("on","0").toInt() );
setLabelField ( MultilineEnabled, _elementFieldIndex(el) );
}
} // QgsLabel::readXML() } // QgsLabel::readXML()
@ -1158,6 +1198,26 @@ void QgsLabel::writeXML(std::ostream& xml)
{ {
xml << "\t\t\t<bufferenabled on=\"" << "\" field=\"" << "\" />\n"; xml << "\t\t\t<bufferenabled on=\"" << "\" field=\"" << "\" />\n";
} }
// multiline enabled
if (mLabelAttributes->multilineEnabled())
{
if (mLabelFieldIdx[MultilineEnabled] != -1)
{
xml << "\t\t\t<multilineenabled on=\"" << mLabelAttributes->multilineEnabled()
<< "\" field=\"" << mLabelFieldIdx[MultilineEnabled] << "\" />\n";
}
else
{
xml << "\t\t\t<multilineenabled on=\"" << mLabelAttributes->multilineEnabled()
<< "\" field=\"\" />\n";
}
}
else
{
xml << "\t\t\t<multilineenabled on=\"" << "\" field=\"" << "\" />\n";
}
xml << "\t\t</labelattributes>\n"; xml << "\t\t</labelattributes>\n";
} }

View File

@ -73,6 +73,7 @@ public:
BorderWidth, BorderWidth,
BorderColor, BorderColor,
BorderStyle, BorderStyle,
MultilineEnabled,
LabelFieldCount LabelFieldCount
}; };
@ -127,7 +128,8 @@ private:
QString text, QFont font, QPen pen, QString text, QFont font, QPen pen,
int dx, int dy, int dx, int dy,
double xoffset, double yoffset, double xoffset, double yoffset,
double ang); double ang,
int width, int height, int alignment);
/** Get label point for simple feature in map units */ /** Get label point for simple feature in map units */
void labelPoint ( std::vector<QgsPoint>&, QgsFeature & feature ); void labelPoint ( std::vector<QgsPoint>&, QgsFeature & feature );

View File

@ -51,7 +51,8 @@ QgsLabelAttributes::QgsLabelAttributes( bool def )
mBufferStyleIsSet( false ), mBufferStyleIsSet( false ),
mBorderColorIsSet( false ), mBorderColorIsSet( false ),
mBorderWidthIsSet( false ), mBorderWidthIsSet( false ),
mBorderStyleIsSet( false ) mBorderStyleIsSet( false ),
mMultilineEnabledFlag( false )
{ {
if ( def ) { // set defaults if ( def ) { // set defaults
@ -388,13 +389,25 @@ Qt::PenStyle QgsLabelAttributes::borderStyle ( void ) const
return mBorderPen.style(); return mBorderPen.style();
} }
/* Multiline */
bool QgsLabelAttributes::multilineEnabled() const
{
return mMultilineEnabledFlag;
}
void QgsLabelAttributes::setMultilineEnabled(bool useMultilineFlag)
{
mMultilineEnabledFlag=useMultilineFlag;
}
/* units */
QString QgsLabelAttributes::unitsName ( int units ) QString QgsLabelAttributes::unitsName ( int units )
{ {
if ( units == MapUnits ){ if ( units == MapUnits )
return QString("mu"); {
} return QString("mu");
}
return QString("pt");
return QString("pt");
} }
int QgsLabelAttributes::unitsCode ( const QString &name ) int QgsLabelAttributes::unitsCode ( const QString &name )
@ -406,6 +419,7 @@ int QgsLabelAttributes::unitsCode ( const QString &name )
return PointUnits; return PointUnits;
} }
/* alignment */
QString QgsLabelAttributes::alignmentName ( int alignment ) QString QgsLabelAttributes::alignmentName ( int alignment )
{ {
std::cout << "QString QgsLabelAttributes::alignmentName (" << alignment << ")" << std::endl; std::cout << "QString QgsLabelAttributes::alignmentName (" << alignment << ")" << std::endl;

View File

@ -171,6 +171,9 @@ public:
void setBorderStyle ( Qt::PenStyle style ); void setBorderStyle ( Qt::PenStyle style );
bool borderStyleIsSet ( void ) const; bool borderStyleIsSet ( void ) const;
Qt::PenStyle borderStyle ( void ) const; Qt::PenStyle borderStyle ( void ) const;
bool multilineEnabled() const;
void setMultilineEnabled( bool useMultiline );
protected: protected:
/* Text */ /* Text */
@ -224,6 +227,9 @@ public:
bool mBorderColorIsSet; bool mBorderColorIsSet;
bool mBorderWidthIsSet; bool mBorderWidthIsSet;
bool mBorderStyleIsSet; bool mBorderStyleIsSet;
/** Multiline enablement */
bool mMultilineEnabledFlag;
}; };
#endif #endif

View File

@ -449,6 +449,16 @@
</widget> </widget>
</item> </item>
<item row="5" column="0" > <item row="5" column="0" >
<widget class="QCheckBox" name="chkUseMultiline" >
<property name="text" >
<string>Multiline labels?</string>
</property>
<property name="checked" >
<bool>true</bool>
</property>
</widget>
</item>
<item row="6" column="0" >
<spacer> <spacer>
<property name="orientation" > <property name="orientation" >
<enum>Qt::Vertical</enum> <enum>Qt::Vertical</enum>