00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #include <cmath>
00018 #include <limits>
00019
00020 #include <QString>
00021 #include <QFont>
00022 #include <QFontMetrics>
00023
00024 #include <QPainter>
00025 #include <QDomNode>
00026 #include <QDomElement>
00027
00028 #include "qgis.h"
00029 #include "qgsfeature.h"
00030 #include "qgsgeometry.h"
00031 #include "qgsfield.h"
00032 #include "qgslogger.h"
00033 #include "qgsrectangle.h"
00034 #include "qgsmaptopixel.h"
00035 #include "qgscoordinatetransform.h"
00036 #include "qgsrendercontext.h"
00037
00038 #include "qgslabelattributes.h"
00039 #include "qgslabel.h"
00040
00041
00042 #ifdef WIN32
00043 #undef M_PI
00044 #define M_PI 4*atan(1.0)
00045 #endif
00046
00047 static const char * const ident_ =
00048 "$Id$";
00049
00050 QgsLabel::QgsLabel( const QgsFieldMap & fields )
00051 : mMinScale( 0 ),
00052 mMaxScale( 100000000 ),
00053 mScaleBasedVisibility( false )
00054 {
00055 mField = fields;
00056 mLabelFieldIdx.resize( LabelFieldCount );
00057 for ( int i = 0; i < LabelFieldCount; i++ )
00058 {
00059 mLabelFieldIdx[i] = -1;
00060 }
00061 mLabelAttributes = new QgsLabelAttributes( true );
00062 }
00063
00064 QgsLabel::~QgsLabel()
00065 {
00066 delete mLabelAttributes;
00067 }
00068
00069 QString QgsLabel::fieldValue( int attr, QgsFeature &feature )
00070 {
00071 if ( mLabelFieldIdx[attr] == -1 )
00072 {
00073 return QString();
00074 }
00075
00076 const QgsAttributeMap& attrs = feature.attributeMap();
00077 QgsAttributeMap::const_iterator it = attrs.find( mLabelFieldIdx[attr] );
00078
00079 if ( it != attrs.end() )
00080 {
00081 return it->toString();
00082 }
00083 else
00084 {
00085 return QString();
00086 }
00087 }
00088
00089 void QgsLabel::renderLabel( QgsRenderContext &renderContext,
00090 QgsFeature &feature, bool selected,
00091 QgsLabelAttributes *classAttributes )
00092 {
00093 if ( mLabelAttributes->selectedOnly() && !selected )
00094 return;
00095
00096 QPen pen;
00097 QFont font;
00098 QString value;
00099 QString text;
00100
00101
00102 QgsPoint point;
00103 point = renderContext.mapToPixel().transform( 0, 0 );
00104 double x1 = point.x();
00105 point = renderContext.mapToPixel().transform( 1000, 0 );
00106 double x2 = point.x();
00107 double scale = ( x2 - x1 ) * 0.001;
00108
00109
00110 value = fieldValue( Text, feature );
00111 if ( value.isEmpty() )
00112 {
00113 text = mLabelAttributes->text();
00114 }
00115 else
00116 {
00117 text = value;
00118 }
00119
00120
00121 value = fieldValue( Family, feature );
00122 if ( value.isEmpty() )
00123 {
00124 font.setFamily( mLabelAttributes->family() );
00125 }
00126 else
00127 {
00128 font.setFamily( value );
00129 }
00130
00131 double size;
00132 value = fieldValue( Size, feature );
00133 if ( value.isEmpty() )
00134 {
00135 size = mLabelAttributes->size();
00136 }
00137 else
00138 {
00139 size = value.toDouble();
00140 }
00141 int sizeType;
00142 value = fieldValue( SizeType, feature );
00143 if ( value.isEmpty() )
00144 sizeType = mLabelAttributes->sizeType();
00145 else
00146 {
00147 value = value.toLower();
00148 if ( value.compare( "mapunits" ) == 0 )
00149 sizeType = QgsLabelAttributes::MapUnits;
00150 else
00151 sizeType = QgsLabelAttributes::PointUnits;
00152 }
00153 if ( sizeType == QgsLabelAttributes::MapUnits )
00154 {
00155 size *= scale;
00156 }
00157 else
00158 {
00159 double sizeMM = size * 0.3527;
00160 size = sizeMM * renderContext.scaleFactor();
00161 }
00162
00163
00164
00165 size *= renderContext.rasterScaleFactor();
00166
00167 if (( int )size <= 0 )
00168
00169 return;
00170
00171 font.setPixelSize( size );
00172
00173 value = fieldValue( Color, feature );
00174 if ( value.isEmpty() )
00175 {
00176 pen.setColor( mLabelAttributes->color() );
00177 }
00178 else
00179 {
00180 pen.setColor( QColor( value ) );
00181 }
00182
00183 value = fieldValue( Bold, feature );
00184 if ( value.isEmpty() )
00185 {
00186 font.setBold( mLabelAttributes->bold() );
00187 }
00188 else
00189 {
00190 font.setBold(( bool ) value.toInt() );
00191 }
00192
00193 value = fieldValue( Italic, feature );
00194 if ( value.isEmpty() )
00195 {
00196 font.setItalic( mLabelAttributes->italic() );
00197 }
00198 else
00199 {
00200 font.setItalic(( bool ) value.toInt() );
00201 }
00202
00203 value = fieldValue( Underline, feature );
00204 if ( value.isEmpty() )
00205 {
00206 font.setUnderline( mLabelAttributes->underline() );
00207 }
00208 else
00209 {
00210 font.setUnderline(( bool ) value.toInt() );
00211 }
00212
00213 value = fieldValue( StrikeOut, feature );
00214 if ( value.isEmpty() )
00215 {
00216 font.setStrikeOut( mLabelAttributes->strikeOut() );
00217 }
00218 else
00219 {
00220 font.setStrikeOut(( bool ) value.toInt() );
00221 }
00222
00223
00224 QgsPoint overridePoint;
00225 bool useOverridePoint = false;
00226 value = fieldValue( XCoordinate, feature );
00227 if ( !value.isEmpty() )
00228 {
00229 overridePoint.setX( value.toDouble() );
00230 useOverridePoint = true;
00231 }
00232 value = fieldValue( YCoordinate, feature );
00233 if ( !value.isEmpty() )
00234 {
00235 overridePoint.setY( value.toDouble() );
00236 useOverridePoint = true;
00237 }
00238
00239
00240 int alignment;
00241 QFontMetrics fm( font );
00242 int width, height;
00243
00244 if ( mLabelAttributes->multilineEnabled() )
00245 {
00246 QStringList texts = text.split( "\n" );
00247
00248 width = 0;
00249 for ( int i = 0; i < texts.size(); i++ )
00250 {
00251 int w = fm.width( texts[i] );
00252 if ( w > width )
00253 width = w;
00254 }
00255
00256 height = fm.height() * texts.size();
00257 }
00258 else
00259 {
00260 width = fm.width( text );
00261 height = fm.height();
00262 }
00263
00264 int dx = 0;
00265 int dy = 0;
00266
00267 value = fieldValue( Alignment, feature );
00268 if ( value.isEmpty() )
00269 {
00270 alignment = mLabelAttributes->alignment();
00271 }
00272 else
00273 {
00274 value = value.toLower();
00275
00276 alignment = 0;
00277
00278 if ( value.contains( "left" ) )
00279 alignment |= Qt::AlignLeft;
00280 else if ( value.contains( "right" ) )
00281 alignment |= Qt::AlignRight;
00282 else
00283 alignment |= Qt::AlignHCenter;
00284
00285 if ( value.contains( "bottom" ) )
00286 alignment |= Qt::AlignBottom;
00287 else if ( value.contains( "top" ) )
00288 alignment |= Qt::AlignTop;
00289 else
00290 alignment |= Qt::AlignVCenter;
00291 }
00292
00293 if ( alignment & Qt::AlignLeft )
00294 {
00295 dx = 0;
00296 }
00297 else if ( alignment & Qt::AlignHCenter )
00298 {
00299 dx = -width / 2;
00300 }
00301 else if ( alignment & Qt::AlignRight )
00302 {
00303 dx = -width;
00304 }
00305
00306 if ( alignment & Qt::AlignBottom )
00307 {
00308 dy = 0;
00309 }
00310 else if ( alignment & Qt::AlignVCenter )
00311 {
00312 dy = height / 2;
00313 }
00314 else if ( alignment & Qt::AlignTop )
00315 {
00316 dy = height;
00317 }
00318
00319
00320 double xoffset, yoffset;
00321 value = fieldValue( XOffset, feature );
00322 if ( value.isEmpty() )
00323 {
00324 xoffset = mLabelAttributes->xOffset();
00325 }
00326 else
00327 {
00328 xoffset = value.toDouble();
00329 }
00330 value = fieldValue( YOffset, feature );
00331 if ( value.isEmpty() )
00332 {
00333 yoffset = mLabelAttributes->yOffset();
00334 }
00335 else
00336 {
00337 yoffset = value.toDouble();
00338 }
00339
00340
00341 if ( mLabelAttributes->offsetType() == QgsLabelAttributes::MapUnits )
00342 {
00343 xoffset *= scale;
00344 yoffset *= scale;
00345 }
00346 else
00347 {
00348 xoffset = xoffset * 0.3527 * renderContext.scaleFactor();
00349 yoffset = yoffset * 0.3527 * renderContext.scaleFactor();
00350 }
00351
00352
00353 double ang;
00354 value = fieldValue( Angle, feature );
00355 if ( value.isEmpty() )
00356 {
00357 ang = mLabelAttributes->angle();
00358 }
00359 else
00360 {
00361 ang = value.toDouble();
00362 }
00363
00364
00365
00366
00367
00368 if ( useOverridePoint )
00369 {
00370 renderLabel( renderContext, overridePoint, text, font, pen, dx, dy,
00371 xoffset, yoffset, ang, width, height, alignment );
00372 }
00373 else
00374 {
00375 std::vector<labelpoint> points;
00376 labelPoint( points, feature );
00377 for ( uint i = 0; i < points.size(); ++i )
00378 {
00379 renderLabel( renderContext, points[i].p, text, font, pen, dx, dy,
00380 xoffset, yoffset, mLabelAttributes->angleIsAuto() ? points[i].angle : ang, width, height, alignment );
00381 }
00382 }
00383 }
00384
00385 void QgsLabel::renderLabel( QgsRenderContext &renderContext,
00386 QgsPoint point,
00387 QString text, QFont font, QPen pen,
00388 int dx, int dy,
00389 double xoffset, double yoffset,
00390 double ang,
00391 int width, int height, int alignment )
00392 {
00393 QPainter *painter = renderContext.painter();
00394
00395
00396 if ( renderContext.coordinateTransform() )
00397 {
00398 try
00399 {
00400 point = renderContext.coordinateTransform()->transform( point );
00401 }
00402 catch ( QgsCsException &cse )
00403 {
00404 Q_UNUSED( cse );
00405 QgsDebugMsg( "Caught transform error. Skipping rendering this label" );
00406 return;
00407 }
00408 }
00409
00410
00411 renderContext.mapToPixel().transform( &point );
00412 double x = point.x();
00413 double y = point.y();
00414
00415 double rad = ang * M_PI / 180;
00416
00417 x = x + xoffset * cos( rad ) - yoffset * sin( rad );
00418 y = y - xoffset * sin( rad ) - yoffset * cos( rad );
00419
00420 painter->save();
00421 painter->setFont( font );
00422 painter->translate( x, y );
00423
00424 painter->scale( 1.0 / renderContext.rasterScaleFactor(), 1.0 / renderContext.rasterScaleFactor() );
00425 painter->rotate( -ang );
00426
00427
00428
00429
00430 if ( mLabelAttributes->bufferSizeIsSet() && mLabelAttributes->bufferEnabled() )
00431 {
00432 double myBufferSize = mLabelAttributes->bufferSize() * 0.3527 * renderContext.scaleFactor() * renderContext.rasterScaleFactor();
00433 QPen bufferPen;
00434 if ( mLabelAttributes->bufferColorIsSet() )
00435 {
00436 bufferPen.setColor( mLabelAttributes->bufferColor() );
00437 }
00438 else
00439 {
00440 bufferPen.setColor( Qt::white );
00441 }
00442 painter->setPen( bufferPen );
00443
00444 double bufferStepSize;
00445 if (( renderContext.scaleFactor() - 1 ) > 1.5 )
00446 {
00447 bufferStepSize = 1;
00448 }
00449 else
00450 {
00451 bufferStepSize = 1 / renderContext.rasterScaleFactor();
00452 }
00453
00454 for ( double i = dx - myBufferSize; i <= dx + myBufferSize; i += bufferStepSize )
00455 {
00456 for ( double j = dy - myBufferSize; j <= dy + myBufferSize; j += bufferStepSize )
00457 {
00458 if ( mLabelAttributes->multilineEnabled() )
00459 painter->drawText( QRectF( i, j - height, width, height ), alignment, text );
00460 else
00461 painter->drawText( QPointF( i, j ), text );
00462 }
00463 }
00464 }
00465
00466 painter->setPen( pen );
00467 if ( mLabelAttributes->multilineEnabled() )
00468 painter->drawText( dx, dy - height, width, height, alignment, text );
00469 else
00470 painter->drawText( dx, dy, text );
00471 painter->restore();
00472 }
00473
00474 void QgsLabel::addRequiredFields( QgsAttributeList& fields ) const
00475 {
00476 for ( uint i = 0; i < LabelFieldCount; i++ )
00477 {
00478 if ( mLabelFieldIdx[i] == -1 )
00479 continue;
00480 bool found = false;
00481 for ( QgsAttributeList::iterator it = fields.begin(); it != fields.end(); ++it )
00482 {
00483 if ( *it == mLabelFieldIdx[i] )
00484 {
00485 found = true;
00486 break;
00487 }
00488 }
00489 if ( !found )
00490 {
00491 fields.append( mLabelFieldIdx[i] );
00492 }
00493 }
00494 }
00495
00496 void QgsLabel::setFields( const QgsFieldMap & fields )
00497 {
00498 mField = fields;
00499 }
00500
00501 QgsFieldMap & QgsLabel::fields( void )
00502 {
00503 return mField;
00504 }
00505
00506 void QgsLabel::setLabelField( int attr, int fieldIndex )
00507 {
00508 if ( attr >= LabelFieldCount )
00509 return;
00510
00511 mLabelFieldIdx[attr] = fieldIndex;
00512 }
00513
00514 QString QgsLabel::labelField( int attr ) const
00515 {
00516 if ( attr > LabelFieldCount )
00517 return QString();
00518
00519 int fieldIndex = mLabelFieldIdx[attr];
00520 return mField[fieldIndex].name();
00521 }
00522
00523 QgsLabelAttributes *QgsLabel::labelAttributes( void )
00524 {
00525 return mLabelAttributes;
00526 }
00527
00528 QgsLabelAttributes *QgsLabel::layerAttributes( void )
00529 {
00530 return mLabelAttributes;
00531 }
00532
00533 void QgsLabel::labelPoint( std::vector<labelpoint>& points, QgsFeature & feature )
00534 {
00535 QgsGeometry *geometry = feature.geometry();
00536 unsigned char *geom = geometry->asWkb();
00537 size_t geomlen = geometry->wkbSize();
00538 QGis::WkbType wkbType = geometry->wkbType();
00539 labelpoint point;
00540
00541 switch ( wkbType )
00542 {
00543 case QGis::WKBPoint25D:
00544 case QGis::WKBPoint:
00545 case QGis::WKBLineString25D:
00546 case QGis::WKBLineString:
00547 case QGis::WKBPolygon25D:
00548 case QGis::WKBPolygon:
00549 {
00550 labelPoint( point, geom, geomlen );
00551 points.push_back( point );
00552 }
00553 break;
00554
00555 case QGis::WKBMultiPoint25D:
00556 case QGis::WKBMultiPoint:
00557 case QGis::WKBMultiLineString25D:
00558 case QGis::WKBMultiLineString:
00559 case QGis::WKBMultiPolygon25D:
00560 case QGis::WKBMultiPolygon:
00561
00562 {
00563 Q_ASSERT( 1 + sizeof( wkbType ) + sizeof( int ) <= geomlen );
00564 geom += 1 + sizeof( wkbType );
00565 int nFeatures = *( unsigned int * )geom;
00566 geom += sizeof( int );
00567
00568 unsigned char *feature = geom;
00569 for ( int i = 0; i < nFeatures && feature; ++i )
00570 {
00571 feature = labelPoint( point, feature, geom + geomlen - feature );
00572 points.push_back( point );
00573 }
00574 }
00575 break;
00576 default:
00577 QgsDebugMsg( "Unknown geometry type of " + QString::number( wkbType ) );
00578 }
00579 }
00580
00581 unsigned char* QgsLabel::labelPoint( labelpoint& point, unsigned char *geom, size_t geomlen )
00582 {
00583
00584 Q_ASSERT( sizeof( int ) == 4 );
00585 Q_ASSERT( sizeof( QGis::WkbType ) == 4 );
00586 Q_ASSERT( sizeof( double ) == 8 );
00587
00588 if ( geom == NULL )
00589 {
00590 QgsDebugMsg( "empty wkb" );
00591 return NULL;
00592 }
00593
00594 QGis::WkbType wkbType;
00595 #ifndef QT_NO_DEBUG
00596 unsigned char *geomend = geom + geomlen;
00597 #endif
00598 Q_ASSERT( geom + 1 + sizeof( wkbType ) <= geomend );
00599
00600 geom++;
00601 memcpy( &wkbType, geom, sizeof( wkbType ) );
00602 geom += sizeof( wkbType );
00603
00604 int dims = 2;
00605
00606 switch ( wkbType )
00607 {
00608 case QGis::WKBPoint25D:
00609 case QGis::WKBPoint:
00610 {
00611 Q_ASSERT( geom + 2*sizeof( double ) <= geomend );
00612 double *pts = ( double * )geom;
00613 point.p.set( pts[0], pts[1] );
00614 point.angle = 0.0;
00615 geom += 2 * sizeof( double );
00616 }
00617 break;
00618
00619 case QGis::WKBLineString25D:
00620 dims = 3;
00621 case QGis::WKBLineString:
00622 {
00623 Q_ASSERT( geom + sizeof( int ) <= geomend );
00624 int nPoints = *( unsigned int * )geom;
00625 geom += sizeof( int );
00626
00627 Q_ASSERT( geom + nPoints*sizeof( double )*dims <= geomend );
00628
00629
00630 double *pts = ( double * )geom;
00631 double tl = 0.0;
00632 for ( int i = 1; i < nPoints; i++ )
00633 {
00634 double dx = pts[dims*i] - pts[dims*( i-1 )];
00635 double dy = pts[dims*i+1] - pts[dims*( i-1 )+1];
00636 tl += sqrt( dx * dx + dy * dy );
00637 }
00638 tl /= 2.0;
00639
00640
00641 double l = 0.0;
00642 for ( int i = 1; i < nPoints; i++ )
00643 {
00644 double dx = pts[dims*i] - pts[dims*( i-1 )];
00645 double dy = pts[dims*i+1] - pts[dims*( i-1 )+1];
00646 double dl = sqrt( dx * dx + dy * dy );
00647
00648 if ( l + dl > tl )
00649 {
00650 double k = ( tl - l ) / dl;
00651
00652 point.p.set( pts[dims*( i-1 )] + k * dx,
00653 pts[dims*( i-1 )+1] + k * dy );
00654 point.angle = atan2( dy, dx ) * 180.0 * M_1_PI;
00655 break;
00656 }
00657
00658 l += dl;
00659 }
00660
00661 geom += nPoints * sizeof( double ) * dims;
00662 }
00663 break;
00664
00665 case QGis::WKBPolygon25D:
00666 dims = 3;
00667 case QGis::WKBPolygon:
00668 {
00669 Q_ASSERT( geom + sizeof( int ) <= geomend );
00670 int nRings = *( unsigned int * )geom;
00671 geom += sizeof( int );
00672
00673 for ( int i = 0; i < nRings; ++i )
00674 {
00675 Q_ASSERT( geom + sizeof( int ) <= geomend );
00676 int nPoints = *( unsigned int * )geom;
00677 geom += sizeof( int );
00678
00679 Q_ASSERT( geom + nPoints*sizeof( double )*dims <= geomend );
00680
00681 if ( i == 0 )
00682 {
00683 double sx = 0.0, sy = 0.0;
00684 double *pts = ( double* ) geom;
00685 for ( int j = 0; j < nPoints - 1; j++ )
00686 {
00687 sx += pts[dims*j];
00688 sy += pts[dims*j+1];
00689 }
00690 point.p.set( sx / ( nPoints - 1 ),
00691 sy / ( nPoints - 1 ) );
00692 point.angle = 0.0;
00693 }
00694
00695 geom += nPoints * sizeof( double ) * dims;
00696 }
00697 }
00698 break;
00699
00700 default:
00701
00702
00703 QgsDebugMsg( "unsupported wkb type" );
00704 return NULL;
00705 }
00706
00707 return geom;
00708 }
00709
00710 bool QgsLabel::readLabelField( QDomElement &el, int attr, QString prefix = "field" )
00711 {
00712 QString name = prefix + "name";
00713
00714 if ( el.hasAttribute( name ) )
00715 {
00716 name = el.attribute( name );
00717
00718 QgsFieldMap::const_iterator field_it = mField.constBegin();
00719 for ( ; field_it != mField.constEnd(); ++field_it )
00720 {
00721 if ( field_it.value().name() == name )
00722 {
00723 break;
00724 }
00725 }
00726
00727 if ( field_it != mField.constEnd() )
00728 {
00729 mLabelFieldIdx[attr] = field_it.key();
00730 return true;
00731 }
00732 }
00733 else if ( el.hasAttribute( prefix ) )
00734 {
00735 QString value = el.attribute( prefix );
00736 mLabelFieldIdx[attr] = value.isEmpty() ? -1 : value.toInt();
00737 return true;
00738 }
00739
00740 mLabelFieldIdx[attr] = -1;
00741 return false;
00742 }
00743
00744
00745 void QgsLabel::readXML( const QDomNode& node )
00746 {
00747 QgsDebugMsg( " called for layer label properties, got node " + node.nodeName() );
00748
00749 QDomNode scratchNode;
00750 QDomElement el;
00751
00752 int red, green, blue;
00753 int type;
00754
00755
00756 scratchNode = node.namedItem( "label" );
00757
00758 if ( scratchNode.isNull() )
00759 {
00760 QgsDebugMsg( "couldn't find QgsLabel ``label'' attribute" );
00761 }
00762 else
00763 {
00764 el = scratchNode.toElement();
00765 mLabelAttributes->setText( el.attribute( "text", "" ) );
00766 readLabelField( el, Text );
00767 }
00768
00769
00770 scratchNode = node.namedItem( "family" );
00771
00772 if ( scratchNode.isNull() )
00773 {
00774 QgsDebugMsg( "couldn't find QgsLabel ``family'' attribute" );
00775 }
00776 else
00777 {
00778 el = scratchNode.toElement();
00779 mLabelAttributes->setFamily( el.attribute( "name", "" ) );
00780 readLabelField( el, Family );
00781 }
00782
00783
00784 scratchNode = node.namedItem( "size" );
00785
00786 if ( scratchNode.isNull() )
00787 {
00788 QgsDebugMsg( "couldn't find QgsLabel ``size'' attribute" );
00789 }
00790 else
00791 {
00792 el = scratchNode.toElement();
00793 if ( !el.hasAttribute( "unitfield" ) && !el.hasAttribute( "unitfieldname" ) )
00794 {
00795 type = QgsLabelAttributes::unitsCode( el.attribute( "units", "" ) );
00796 mLabelAttributes->setSize( el.attribute( "value", "0.0" ).toDouble(), type );
00797 }
00798 else
00799 {
00800 readLabelField( el, SizeType, "unitfield" );
00801 }
00802 readLabelField( el, Size );
00803 }
00804
00805
00806 scratchNode = node.namedItem( "bold" );
00807
00808 if ( scratchNode.isNull() )
00809 {
00810 QgsDebugMsg( "couldn't find QgsLabel ``bold'' attribute" );
00811 }
00812 else
00813 {
00814 el = scratchNode.toElement();
00815 mLabelAttributes->setBold(( bool )el.attribute( "on", "0" ).toInt() );
00816 readLabelField( el, Bold );
00817 }
00818
00819
00820 scratchNode = node.namedItem( "italic" );
00821
00822 if ( scratchNode.isNull() )
00823 {
00824 QgsDebugMsg( "couldn't find QgsLabel ``italic'' attribute" );
00825 }
00826 else
00827 {
00828 el = scratchNode.toElement();
00829 mLabelAttributes->setItalic(( bool )el.attribute( "on", "0" ).toInt() );
00830 readLabelField( el, Italic );
00831 }
00832
00833
00834 scratchNode = node.namedItem( "underline" );
00835
00836 if ( scratchNode.isNull() )
00837 {
00838 QgsDebugMsg( "couldn't find QgsLabel ``underline'' attribute" );
00839 }
00840 else
00841 {
00842 el = scratchNode.toElement();
00843 mLabelAttributes->setUnderline(( bool )el.attribute( "on", "0" ).toInt() );
00844 readLabelField( el, Underline );
00845 }
00846
00847
00848 scratchNode = node.namedItem( "strikeout" );
00849
00850 if ( scratchNode.isNull() )
00851 {
00852 QgsDebugMsg( "couldn't find QgsLabel ``strikeout'' attribute" );
00853 }
00854 else
00855 {
00856 el = scratchNode.toElement();
00857 mLabelAttributes->setStrikeOut(( bool )el.attribute( "on", "0" ).toInt() );
00858 readLabelField( el, StrikeOut );
00859 }
00860
00861
00862 scratchNode = node.namedItem( "color" );
00863
00864 if ( scratchNode.isNull() )
00865 {
00866 QgsDebugMsg( "couldn't find QgsLabel ``color'' attribute" );
00867 }
00868 else
00869 {
00870 el = scratchNode.toElement();
00871
00872 red = el.attribute( "red", "0" ).toInt();
00873 green = el.attribute( "green", "0" ).toInt();
00874 blue = el.attribute( "blue", "0" ).toInt();
00875
00876 mLabelAttributes->setColor( QColor( red, green, blue ) );
00877
00878 readLabelField( el, Color );
00879 }
00880
00881
00882 scratchNode = node.namedItem( "x" );
00883
00884 if ( scratchNode.isNull() )
00885 {
00886 QgsDebugMsg( "couldn't find QgsLabel ``x'' attribute" );
00887 }
00888 else
00889 {
00890 el = scratchNode.toElement();
00891 readLabelField( el, XCoordinate );
00892 }
00893
00894
00895 scratchNode = node.namedItem( "y" );
00896
00897 if ( scratchNode.isNull() )
00898 {
00899 QgsDebugMsg( "couldn't find QgsLabel ``y'' attribute" );
00900 }
00901 else
00902 {
00903 el = scratchNode.toElement();
00904 readLabelField( el, YCoordinate );
00905 }
00906
00907
00908
00909 scratchNode = node.namedItem( "offset" );
00910
00911 if ( scratchNode.isNull() )
00912 {
00913 QgsDebugMsg( "couldn't find QgsLabel ``offset'' attribute" );
00914 }
00915 else
00916 {
00917 double xoffset, yoffset;
00918
00919 el = scratchNode.toElement();
00920
00921 type = QgsLabelAttributes::unitsCode( el.attribute( "units", "" ) );
00922 xoffset = el.attribute( "x", "0.0" ).toDouble();
00923 yoffset = el.attribute( "y", "0.0" ).toDouble();
00924
00925 mLabelAttributes->setOffset( xoffset, yoffset, type );
00926 readLabelField( el, XOffset, "xfield" );
00927 readLabelField( el, YOffset, "yfield" );
00928 }
00929
00930
00931 scratchNode = node.namedItem( "angle" );
00932
00933 if ( scratchNode.isNull() )
00934 {
00935 QgsDebugMsg( "couldn't find QgsLabel ``angle'' attribute" );
00936 }
00937 else
00938 {
00939 el = scratchNode.toElement();
00940 mLabelAttributes->setAngle( el.attribute( "value", "0.0" ).toDouble() );
00941 readLabelField( el, Angle );
00942 mLabelAttributes->setAutoAngle( el.attribute( "auto", "0" ) == "1" );
00943 }
00944
00945
00946 scratchNode = node.namedItem( "alignment" );
00947
00948 if ( scratchNode.isNull() )
00949 {
00950 QgsDebugMsg( "couldn't find QgsLabel ``alignment'' attribute" );
00951 }
00952 else
00953 {
00954 el = scratchNode.toElement();
00955 mLabelAttributes->setAlignment( QgsLabelAttributes::alignmentCode( el.attribute( "value", "" ) ) );
00956 readLabelField( el, Alignment );
00957 }
00958
00959
00960
00961 scratchNode = node.namedItem( "buffercolor" );
00962
00963 if ( scratchNode.isNull() )
00964 {
00965 QgsDebugMsg( "couldn't find QgsLabel ``buffercolor'' attribute" );
00966 }
00967 else
00968 {
00969 el = scratchNode.toElement();
00970
00971 red = el.attribute( "red", "0" ).toInt();
00972 green = el.attribute( "green", "0" ).toInt();
00973 blue = el.attribute( "blue", "0" ).toInt();
00974
00975 mLabelAttributes->setBufferColor( QColor( red, green, blue ) );
00976 readLabelField( el, BufferColor );
00977 }
00978
00979 scratchNode = node.namedItem( "buffersize" );
00980
00981 if ( scratchNode.isNull() )
00982 {
00983 QgsDebugMsg( "couldn't find QgsLabel ``bffersize'' attribute" );
00984 }
00985 else
00986 {
00987 el = scratchNode.toElement();
00988
00989 type = QgsLabelAttributes::unitsCode( el.attribute( "units", "" ) );
00990 mLabelAttributes->setBufferSize( el.attribute( "value", "0.0" ).toDouble(), type );
00991 readLabelField( el, BufferSize );
00992 }
00993
00994 scratchNode = node.namedItem( "bufferenabled" );
00995
00996 if ( scratchNode.isNull() )
00997 {
00998 QgsDebugMsg( "couldn't find QgsLabel ``bufferenabled'' attribute" );
00999 }
01000 else
01001 {
01002 el = scratchNode.toElement();
01003
01004 mLabelAttributes->setBufferEnabled(( bool )el.attribute( "on", "0" ).toInt() );
01005 readLabelField( el, BufferEnabled );
01006 }
01007
01008 scratchNode = node.namedItem( "multilineenabled" );
01009
01010 if ( scratchNode.isNull() )
01011 {
01012 QgsDebugMsg( "couldn't find QgsLabel ``multilineenabled'' attribute" );
01013 }
01014 else
01015 {
01016 el = scratchNode.toElement();
01017
01018 mLabelAttributes->setMultilineEnabled(( bool )el.attribute( "on", "0" ).toInt() );
01019 readLabelField( el, MultilineEnabled );
01020 }
01021
01022 scratchNode = node.namedItem( "selectedonly" );
01023
01024 if ( scratchNode.isNull() )
01025 {
01026 QgsDebugMsg( "couldn't find QgsLabel ``selectedonly'' attribute" );
01027 }
01028 else
01029 {
01030 el = scratchNode.toElement();
01031 mLabelAttributes->setSelectedOnly(( bool )el.attribute( "on", "0" ).toInt() );
01032 }
01033
01034 }
01035
01036
01037
01038 void QgsLabel::writeXML( QDomNode & layer_node, QDomDocument & document ) const
01039 {
01040 QDomElement labelattributes = document.createElement( "labelattributes" );
01041
01042
01043 QDomElement label = document.createElement( "label" );
01044 label.setAttribute( "text", mLabelAttributes->text() );
01045 if ( mLabelAttributes->textIsSet() && mLabelFieldIdx[Text] != -1 )
01046 {
01047 label.setAttribute( "fieldname", labelField( Text ) );
01048 }
01049 else
01050 {
01051 label.setAttribute( "fieldname", "" );
01052 }
01053 labelattributes.appendChild( label );
01054
01055
01056 QDomElement family = document.createElement( "family" );
01057 if ( mLabelAttributes->familyIsSet() && !mLabelAttributes->family().isNull() )
01058 {
01059 if ( mLabelFieldIdx[Family] != -1 )
01060 {
01061 family.setAttribute( "name", mLabelAttributes->family() );
01062 family.setAttribute( "fieldname", labelField( Family ) );
01063 }
01064 else
01065 {
01066 family.setAttribute( "name", mLabelAttributes->family() );
01067 family.setAttribute( "fieldname", "" );
01068 }
01069 }
01070 else
01071 {
01072 family.setAttribute( "name", "Arial" );
01073 family.setAttribute( "fieldname", "" );
01074 }
01075 labelattributes.appendChild( family );
01076
01077
01078 QDomElement size = document.createElement( "size" );
01079 size.setAttribute( "value", mLabelAttributes->size() );
01080 if ( mLabelAttributes->sizeIsSet() )
01081 {
01082 if ( mLabelFieldIdx[Size] != -1 )
01083 {
01084 if ( mLabelFieldIdx[SizeType] != -1 )
01085 {
01086 size.setAttribute( "unitfieldname", labelField( SizeType ) );
01087 }
01088 else
01089 {
01090 size.setAttribute( "units", QgsLabelAttributes::unitsName( mLabelAttributes->sizeType() ) );
01091 }
01092 size.setAttribute( "fieldname", labelField( Size ) );
01093 }
01094 else
01095 {
01096 size.setAttribute( "units", QgsLabelAttributes::unitsName( mLabelAttributes->sizeType() ) );
01097 size.setAttribute( "fieldname", "" );
01098 }
01099 }
01100 else
01101 {
01102 size.setAttribute( "value", "12" );
01103 size.setAttribute( "units", "Points" );
01104 size.setAttribute( "fieldname", "" );
01105 }
01106 labelattributes.appendChild( size );
01107
01108
01109 QDomElement bold = document.createElement( "bold" );
01110 if ( mLabelAttributes->boldIsSet() )
01111 {
01112 bold.setAttribute( "on", mLabelAttributes->bold() );
01113 if ( mLabelFieldIdx[Bold] != -1 )
01114 {
01115 bold.setAttribute( "fieldname", labelField( Bold ) );
01116 }
01117 else
01118 {
01119 bold.setAttribute( "fieldname", "" );
01120 }
01121 }
01122 else
01123 {
01124 bold.setAttribute( "on", 0 );
01125 bold.setAttribute( "fieldname", 0 );
01126 }
01127 labelattributes.appendChild( bold );
01128
01129
01130 QDomElement italic = document.createElement( "italic" );
01131 if ( mLabelAttributes->italicIsSet() )
01132 {
01133 italic.setAttribute( "on", mLabelAttributes->italic() );
01134 if ( mLabelFieldIdx[Italic] != -1 )
01135 {
01136 italic.setAttribute( "fieldname", labelField( Italic ) );
01137 }
01138 else
01139 {
01140 italic.setAttribute( "fieldname", "" );
01141 }
01142 }
01143 else
01144 {
01145 italic.setAttribute( "on", "0" );
01146 italic.setAttribute( "fieldname", "" );
01147 }
01148 labelattributes.appendChild( italic );
01149
01150
01151 QDomElement underline = document.createElement( "underline" );
01152 if ( mLabelAttributes->underlineIsSet() )
01153 {
01154 underline.setAttribute( "on", mLabelAttributes->underline() );
01155 if ( mLabelFieldIdx[Underline] != -1 )
01156 {
01157 underline.setAttribute( "fieldname", labelField( Underline ) );
01158 }
01159 else
01160 {
01161 underline.setAttribute( "fieldname", "" );
01162 }
01163 }
01164 else
01165 {
01166 underline.setAttribute( "on", 0 );
01167 underline.setAttribute( "fieldname", "" );
01168 }
01169 labelattributes.appendChild( underline );
01170
01171
01172 QDomElement strikeOut = document.createElement( "strikeout" );
01173 if ( mLabelAttributes->strikeOutIsSet() )
01174 {
01175 strikeOut.setAttribute( "on", mLabelAttributes->strikeOut() );
01176 if ( mLabelFieldIdx[StrikeOut] != -1 )
01177 {
01178 strikeOut.setAttribute( "fieldname", labelField( StrikeOut ) );
01179 }
01180 else
01181 {
01182 strikeOut.setAttribute( "fieldname", "" );
01183 }
01184 }
01185 else
01186 {
01187 strikeOut.setAttribute( "on", 0 );
01188 strikeOut.setAttribute( "fieldname", "" );
01189 }
01190 labelattributes.appendChild( strikeOut );
01191
01192
01193 QDomElement color = document.createElement( "color" );
01194 if ( mLabelAttributes->colorIsSet() )
01195 {
01196 color.setAttribute( "red", mLabelAttributes->color().red() );
01197 color.setAttribute( "green", mLabelAttributes->color().green() );
01198 color.setAttribute( "blue", mLabelAttributes->color().blue() );
01199 if ( mLabelFieldIdx[Color] != -1 )
01200 {
01201 color.setAttribute( "fieldname", labelField( Color ) );
01202 }
01203 else
01204 {
01205 color.setAttribute( "fieldname", "" );
01206 }
01207 }
01208 else
01209 {
01210 color.setAttribute( "red", 0 );
01211 color.setAttribute( "green", 0 );
01212 color.setAttribute( "blue", 0 );
01213 color.setAttribute( "fieldname", "" );
01214 }
01215 labelattributes.appendChild( color );
01216
01217
01218 QDomElement x = document.createElement( "x" );
01219 if ( mLabelFieldIdx[XCoordinate] != -1 )
01220 {
01221 x.setAttribute( "fieldname", labelField( XCoordinate ) );
01222 }
01223 else
01224 {
01225 x.setAttribute( "fieldname", "" );
01226 }
01227 labelattributes.appendChild( x );
01228
01229
01230 QDomElement y = document.createElement( "y" );
01231 if ( mLabelFieldIdx[YCoordinate] != -1 )
01232 {
01233 y.setAttribute( "fieldname", labelField( YCoordinate ) );
01234 }
01235 else
01236 {
01237 y.setAttribute( "fieldname", "" );
01238 }
01239 labelattributes.appendChild( y );
01240
01241
01242 if ( mLabelAttributes->offsetIsSet() )
01243 {
01244 QDomElement offset = document.createElement( "offset" );
01245 offset.setAttribute( "units", QgsLabelAttributes::unitsName( mLabelAttributes->offsetType() ) );
01246 offset.setAttribute( "x", mLabelAttributes->xOffset() );
01247 offset.setAttribute( "xfieldname", labelField( XOffset ) );
01248 offset.setAttribute( "y", mLabelAttributes->yOffset() );
01249 offset.setAttribute( "yfieldname", labelField( YOffset ) );
01250 labelattributes.appendChild( offset );
01251 }
01252
01253
01254 QDomElement angle = document.createElement( "angle" );
01255 if ( mLabelAttributes->angleIsSet() )
01256 {
01257 angle.setAttribute( "value", mLabelAttributes->angle() );
01258 if ( mLabelFieldIdx[Angle] != -1 )
01259 {
01260 angle.setAttribute( "fieldname", labelField( Angle ) );
01261 }
01262 else
01263 {
01264 angle.setAttribute( "fieldname", "" );
01265 }
01266 }
01267 else
01268 {
01269 angle.setAttribute( "value", "" );
01270 angle.setAttribute( "fieldname", "" );
01271 }
01272 angle.setAttribute( "auto", mLabelAttributes->angleIsAuto() ? "1" : "0" );
01273 labelattributes.appendChild( angle );
01274
01275
01276 if ( mLabelAttributes->alignmentIsSet() )
01277 {
01278 QDomElement alignment = document.createElement( "alignment" );
01279 alignment.setAttribute( "value", QgsLabelAttributes::alignmentName( mLabelAttributes->alignment() ) );
01280 alignment.setAttribute( "fieldname", labelField( Alignment ) );
01281 labelattributes.appendChild( alignment );
01282 }
01283
01284
01285 QDomElement buffercolor = document.createElement( "buffercolor" );
01286 if ( mLabelAttributes->bufferColorIsSet() )
01287 {
01288 buffercolor.setAttribute( "red", mLabelAttributes->bufferColor().red() );
01289 buffercolor.setAttribute( "green", mLabelAttributes->bufferColor().green() );
01290 buffercolor.setAttribute( "blue", mLabelAttributes->bufferColor().blue() );
01291 if ( mLabelFieldIdx[BufferColor] != -1 )
01292 {
01293 buffercolor.setAttribute( "fieldname", labelField( BufferColor ) );
01294 }
01295 else
01296 {
01297 buffercolor.setAttribute( "fieldname", "" );
01298 }
01299 }
01300 else
01301 {
01302 buffercolor.setAttribute( "red", "" );
01303 buffercolor.setAttribute( "green", "" );
01304 buffercolor.setAttribute( "blue", "" );
01305 buffercolor.setAttribute( "fieldname", "" );
01306 }
01307 labelattributes.appendChild( buffercolor );
01308
01309
01310 QDomElement buffersize = document.createElement( "buffersize" );
01311 if ( mLabelAttributes->bufferSizeIsSet() )
01312 {
01313 buffersize.setAttribute( "value", mLabelAttributes->bufferSize() );
01314 buffersize.setAttribute( "units", QgsLabelAttributes::unitsName( mLabelAttributes->bufferSizeType() ) );
01315 if ( mLabelFieldIdx[BufferSize] != -1 )
01316 {
01317 buffersize.setAttribute( "fieldname", labelField( BufferSize ) );
01318 }
01319 else
01320 {
01321 buffersize.setAttribute( "fieldname", "" );
01322 }
01323 }
01324 else
01325 {
01326 buffersize.setAttribute( "value", "" );
01327 buffersize.setAttribute( "units", "" );
01328 buffersize.setAttribute( "fieldname", "" );
01329 }
01330 labelattributes.appendChild( buffersize );
01331
01332
01333 QDomElement bufferenabled = document.createElement( "bufferenabled" );
01334 if ( mLabelAttributes->bufferEnabled() )
01335 {
01336 bufferenabled.setAttribute( "on", mLabelAttributes->bufferEnabled() );
01337 if ( mLabelFieldIdx[BufferEnabled] != -1 )
01338 {
01339 bufferenabled.setAttribute( "fieldname", labelField( BufferEnabled ) );
01340 }
01341 else
01342 {
01343 bufferenabled.setAttribute( "fieldname", "" );
01344 }
01345 }
01346 else
01347 {
01348 bufferenabled.setAttribute( "on", "" );
01349 bufferenabled.setAttribute( "fieldname", "" );
01350 }
01351 labelattributes.appendChild( bufferenabled );
01352
01353
01354 QDomElement multilineenabled = document.createElement( "multilineenabled" );
01355 if ( mLabelAttributes->multilineEnabled() )
01356 {
01357 multilineenabled.setAttribute( "on", mLabelAttributes->multilineEnabled() );
01358 if ( mLabelFieldIdx[MultilineEnabled] != -1 )
01359 {
01360 multilineenabled.setAttribute( "fieldname", labelField( MultilineEnabled ) );
01361 }
01362 else
01363 {
01364 multilineenabled.setAttribute( "fieldname", "" );
01365 }
01366 }
01367 else
01368 {
01369 multilineenabled.setAttribute( "on", "" );
01370 multilineenabled.setAttribute( "fieldname", "" );
01371 }
01372 labelattributes.appendChild( multilineenabled );
01373
01374 QDomElement selectedonly = document.createElement( "selectedonly" );
01375 if ( mLabelAttributes->selectedOnly() )
01376 {
01377 selectedonly.setAttribute( "on", mLabelAttributes->selectedOnly() );
01378 }
01379 else
01380 {
01381 selectedonly.setAttribute( "on", "" );
01382 }
01383 labelattributes.appendChild( selectedonly );
01384
01385 layer_node.appendChild( labelattributes );
01386 }
01387
01388 void QgsLabel::setScaleBasedVisibility( bool theVisibilityFlag )
01389 {
01390 mScaleBasedVisibility = theVisibilityFlag;
01391 }
01392
01393 bool QgsLabel::scaleBasedVisibility() const
01394 {
01395 return mScaleBasedVisibility;
01396 }
01397
01398 void QgsLabel::setMinScale( float theMinScale )
01399 {
01400 mMinScale = theMinScale;
01401 }
01402
01403 float QgsLabel::minScale() const
01404 {
01405 return mMinScale;
01406 }
01407
01408 void QgsLabel::setMaxScale( float theMaxScale )
01409 {
01410 mMaxScale = theMaxScale;
01411 }
01412
01413 float QgsLabel::maxScale() const
01414 {
01415 return mMaxScale;
01416 }