00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "qgscomposerarrow.h"
00019 #include <QPainter>
00020 #include <QSvgRenderer>
00021
00022 #ifndef Q_OS_MACX
00023 #include <cmath>
00024 #else
00025 #include <math.h>
00026 #endif
00027
00028 QgsComposerArrow::QgsComposerArrow( QgsComposition* c ): QgsComposerItem( c ), mStartPoint( 0, 0 ), mStopPoint( 0, 0 ), mMarkerMode( DefaultMarker ), mArrowColor( QColor( 0, 0, 0 ) )
00029 {
00030 initGraphicsSettings();
00031 }
00032
00033 QgsComposerArrow::QgsComposerArrow( const QPointF& startPoint, const QPointF& stopPoint, QgsComposition* c ): QgsComposerItem( c ), mStartPoint( startPoint ), \
00034 mStopPoint( stopPoint ), mMarkerMode( DefaultMarker ), mArrowColor( QColor( 0, 0, 0 ) )
00035 {
00036 initGraphicsSettings();
00037 adaptItemSceneRect();
00038 }
00039
00040 QgsComposerArrow::~QgsComposerArrow()
00041 {
00042
00043 }
00044
00045 void QgsComposerArrow::initGraphicsSettings()
00046 {
00047 setArrowHeadWidth( 4 );
00048 mPen.setColor( QColor( 0, 0, 0 ) );
00049 mPen.setWidthF( 1 );
00050
00051
00052 setPen( QPen( QColor( 255, 255, 255, 0 ) ) );
00053 setBrush( QBrush( QColor( 255, 255, 255, 0 ) ) );
00054 }
00055
00056 void QgsComposerArrow::paint( QPainter* painter, const QStyleOptionGraphicsItem* itemStyle, QWidget* pWidget )
00057 {
00058 if ( !painter )
00059 {
00060 return;
00061 }
00062
00063 drawBackground( painter );
00064
00065
00066 QPen arrowPen = mPen;
00067 arrowPen.setCapStyle( Qt::FlatCap );
00068 arrowPen.setColor( mArrowColor );
00069 painter->setPen( arrowPen );
00070 painter->setBrush( QBrush( mArrowColor ) );
00071 painter->drawLine( QPointF( mStartPoint.x() - transform().dx(), mStartPoint.y() - transform().dy() ), QPointF( mStopPoint.x() - transform().dx(), mStopPoint.y() - transform().dy() ) );
00072
00073 if ( mMarkerMode == DefaultMarker )
00074 {
00075 drawHardcodedMarker( painter, EndMarker );
00076 }
00077 else if ( mMarkerMode == SVGMarker )
00078 {
00079 drawSVGMarker( painter, StartMarker, mStartMarkerFile );
00080 drawSVGMarker( painter, EndMarker, mEndMarkerFile );
00081 }
00082
00083 drawFrame( painter );
00084 if ( isSelected() )
00085 {
00086 drawSelectionBoxes( painter );
00087 }
00088 }
00089
00090 void QgsComposerArrow::setSceneRect( const QRectF& rectangle )
00091 {
00092
00093 double startPointXPos = ( mStartPoint.x() - transform().dx() ) / rect().width();
00094 double startPointYPos = ( mStartPoint.y() - transform().dy() ) / rect().height();
00095 double stopPointXPos = ( mStopPoint.x() - transform().dx() ) / rect().width();
00096 double stopPointYPos = ( mStopPoint.y() - transform().dy() ) / rect().height();
00097
00098 mStartPoint.setX( rectangle.left() + startPointXPos * rectangle.width() );
00099 mStartPoint.setY( rectangle.top() + startPointYPos * rectangle.height() );
00100 mStopPoint.setX( rectangle.left() + stopPointXPos * rectangle.width() );
00101 mStopPoint.setY( rectangle.top() + stopPointYPos * rectangle.height() );
00102
00103 adaptItemSceneRect();
00104 }
00105
00106 void QgsComposerArrow::drawHardcodedMarker( QPainter* p, MarkerType type )
00107 {
00108 QBrush arrowBrush = p->brush();
00109 arrowBrush.setColor( mArrowColor );
00110 p->setBrush( arrowBrush );
00111 drawArrowHead( p, mStopPoint.x() - transform().dx(), mStopPoint.y() - transform().dy(), angle( mStartPoint, mStopPoint ), mArrowHeadWidth );
00112 }
00113
00114 void QgsComposerArrow::drawSVGMarker( QPainter* p, MarkerType type, const QString& markerPath )
00115 {
00116 double ang = angle( mStartPoint, mStopPoint );
00117
00118 double arrowHeadHeight;
00119 if ( type == StartMarker )
00120 {
00121 arrowHeadHeight = mStartArrowHeadHeight;
00122 }
00123 else
00124 {
00125 arrowHeadHeight = mStopArrowHeadHeight;
00126 }
00127
00128
00129 int dpi = ( p->device()->logicalDpiX() + p->device()->logicalDpiY() ) / 2;
00130 double viewScaleFactor = horizontalViewScaleFactor();
00131 int imageWidth = mArrowHeadWidth / 25.4 * dpi;
00132 int imageHeight = arrowHeadHeight / 25.4 * dpi;
00133
00134
00135 if ( mComposition && mComposition->plotStyle() == QgsComposition::Preview )
00136 {
00137 imageWidth *= std::min( viewScaleFactor, 10.0 );
00138 imageHeight *= std::min( viewScaleFactor, 10.0 );
00139 }
00140 QImage markerImage( imageWidth, imageHeight, QImage::Format_ARGB32 );
00141 QColor markerBG( 255, 255, 255, 0 );
00142 markerImage.fill( markerBG.rgba() );
00143
00144 QPointF imageFixPoint;
00145 imageFixPoint.setX( mArrowHeadWidth / 2.0 );
00146 QPointF canvasPoint;
00147 if ( type == StartMarker )
00148 {
00149 canvasPoint = QPointF( mStartPoint.x() - transform().dx(), mStartPoint.y() - transform().dy() );
00150 imageFixPoint.setY( mStartArrowHeadHeight );
00151 }
00152 else
00153 {
00154 canvasPoint = QPointF( mStopPoint.x() - transform().dx(), mStopPoint.y() - transform().dy() );
00155 imageFixPoint.setY( 0 );
00156 }
00157
00158
00159 QSvgRenderer r;
00160 if ( type == StartMarker )
00161 {
00162 if ( !r.load( mStartMarkerFile ) )
00163 {
00164 return;
00165 }
00166 }
00167 else
00168 {
00169 if ( !r.load( mEndMarkerFile ) )
00170 {
00171 return;
00172 }
00173 }
00174
00175
00176 QPointF fixPoint;
00177 if ( type == StartMarker )
00178 {
00179 fixPoint.setX( 0 ); fixPoint.setY( arrowHeadHeight / 2.0 );
00180 }
00181 else
00182 {
00183 fixPoint.setX( 0 ); fixPoint.setY( -arrowHeadHeight / 2.0 );
00184 }
00185 QPointF rotatedFixPoint;
00186 double angleRad = ang / 180 * M_PI;
00187 rotatedFixPoint.setX( fixPoint.x() * cos( angleRad ) + fixPoint.y() * -sin( angleRad ) );
00188 rotatedFixPoint.setY( fixPoint.x() * sin( angleRad ) + fixPoint.y() * cos( angleRad ) );
00189
00190
00191 QPainter imagePainter( &markerImage );
00192 r.render( &imagePainter );
00193
00194 p->save();
00195 p->translate( canvasPoint.x() - rotatedFixPoint.x() , canvasPoint.y() - rotatedFixPoint.y() );
00196 p->rotate( ang );
00197 p->translate( -mArrowHeadWidth / 2.0, -arrowHeadHeight / 2.0 );
00198
00199 p->drawImage( QRectF( 0, 0, mArrowHeadWidth, arrowHeadHeight ), markerImage, QRectF( 0, 0, imageWidth, imageHeight ) );
00200 p->restore();
00201
00202 return;
00203 }
00204
00205 void QgsComposerArrow::setStartMarker( const QString& svgPath )
00206 {
00207 QSvgRenderer r;
00208 if ( !r.load( svgPath ) )
00209 {
00210 return;
00211
00212 }
00213 mStartMarkerFile = svgPath;
00214
00215
00216 QRect viewBox = r.viewBox();
00217 mStartArrowHeadHeight = mArrowHeadWidth / viewBox.width() * viewBox.height();
00218 adaptItemSceneRect();
00219 }
00220
00221 void QgsComposerArrow::setEndMarker( const QString& svgPath )
00222 {
00223 QSvgRenderer r;
00224 if ( !r.load( svgPath ) )
00225 {
00226 return;
00227
00228 }
00229 mEndMarkerFile = svgPath;
00230
00231
00232 QRect viewBox = r.viewBox();
00233 mStopArrowHeadHeight = mArrowHeadWidth / viewBox.width() * viewBox.height();
00234 adaptItemSceneRect();
00235 }
00236
00237 void QgsComposerArrow::setOutlineWidth( double width )
00238 {
00239 mPen.setWidthF( width );
00240 adaptItemSceneRect();
00241 }
00242
00243 void QgsComposerArrow::setArrowHeadWidth( double width )
00244 {
00245 mArrowHeadWidth = width;
00246 setStartMarker( mStartMarkerFile );
00247 setEndMarker( mEndMarkerFile );
00248 adaptItemSceneRect();
00249 }
00250
00251 void QgsComposerArrow::adaptItemSceneRect()
00252 {
00253
00254 QRectF rect = QRectF( std::min( mStartPoint.x(), mStopPoint.x() ), std::min( mStartPoint.y(), mStopPoint.y() ), \
00255 fabs( mStopPoint.x() - mStartPoint.x() ), fabs( mStopPoint.y() - mStartPoint.y() ) );
00256 double enlarge = 0;
00257 if ( mMarkerMode == DefaultMarker )
00258 {
00259 enlarge = mPen.widthF() / 2.0 + mArrowHeadWidth / 2.0;
00260 }
00261 else if ( mMarkerMode == NoMarker )
00262 {
00263 enlarge = mPen.widthF() / 2.0;
00264 }
00265 else if ( mMarkerMode == SVGMarker )
00266 {
00267 double maxArrowHeight = std::max( mStartArrowHeadHeight, mStopArrowHeadHeight );
00268 enlarge = mPen.widthF() / 2 + std::max( mArrowHeadWidth / 2.0, maxArrowHeight / 2.0 );
00269 }
00270
00271 rect.adjust( -enlarge, -enlarge, enlarge, enlarge );
00272 QgsComposerItem::setSceneRect( rect );
00273 }
00274
00275 bool QgsComposerArrow::writeXML( QDomElement& elem, QDomDocument & doc ) const
00276 {
00277 QDomElement composerArrowElem = doc.createElement( "ComposerArrow" );
00278 composerArrowElem.setAttribute( "outlineWidth", outlineWidth() );
00279 composerArrowElem.setAttribute( "arrowHeadWidth", mArrowHeadWidth );
00280 composerArrowElem.setAttribute( "markerMode", mMarkerMode );
00281 composerArrowElem.setAttribute( "startMarkerFile", mStartMarkerFile );
00282 composerArrowElem.setAttribute( "endMarkerFile", mEndMarkerFile );
00283
00284
00285 QDomElement arrowColorElem = doc.createElement( "ArrowColor" );
00286 arrowColorElem.setAttribute( "red", mArrowColor.red() );
00287 arrowColorElem.setAttribute( "green", mArrowColor.green() );
00288 arrowColorElem.setAttribute( "blue", mArrowColor.blue() );
00289 arrowColorElem.setAttribute( "alpha", mArrowColor.alpha() );
00290 composerArrowElem.appendChild( arrowColorElem );
00291
00292
00293 QDomElement startPointElem = doc.createElement( "StartPoint" );
00294 startPointElem.setAttribute( "x", mStartPoint.x() );
00295 startPointElem.setAttribute( "y", mStartPoint.y() );
00296 composerArrowElem.appendChild( startPointElem );
00297
00298
00299 QDomElement stopPointElem = doc.createElement( "StopPoint" );
00300 stopPointElem.setAttribute( "x", mStopPoint.x() );
00301 stopPointElem.setAttribute( "y", mStopPoint.y() );
00302 composerArrowElem.appendChild( stopPointElem );
00303
00304 elem.appendChild( composerArrowElem );
00305 return _writeXML( composerArrowElem, doc );
00306 }
00307
00308 bool QgsComposerArrow::readXML( const QDomElement& itemElem, const QDomDocument& doc )
00309 {
00310 mArrowHeadWidth = itemElem.attribute( "arrowHeadWidth", "2.0" ).toDouble();
00311 mPen.setWidthF( itemElem.attribute( "outlineWidth", "1.0" ).toDouble() );
00312 setStartMarker( itemElem.attribute( "startMarkerFile", "" ) );
00313 setEndMarker( itemElem.attribute( "endMarkerFile", "" ) );
00314 mMarkerMode = QgsComposerArrow::MarkerMode( itemElem.attribute( "markerMode", "0" ).toInt() );
00315
00316
00317 QDomNodeList arrowColorList = itemElem.elementsByTagName( "ArrowColor" );
00318 if ( arrowColorList.size() > 0 )
00319 {
00320 QDomElement arrowColorElem = arrowColorList.at( 0 ).toElement();
00321 int red = arrowColorElem.attribute( "red", "0" ).toInt();
00322 int green = arrowColorElem.attribute( "green", "0" ).toInt();
00323 int blue = arrowColorElem.attribute( "blue", "0" ).toInt();
00324 int alpha = arrowColorElem.attribute( "alpha", "255" ).toInt();
00325 mArrowColor = QColor( red, green, blue, alpha );
00326 }
00327
00328
00329
00330 QDomNodeList composerItemList = itemElem.elementsByTagName( "ComposerItem" );
00331 if ( composerItemList.size() > 0 )
00332 {
00333 QDomElement composerItemElem = composerItemList.at( 0 ).toElement();
00334 _readXML( composerItemElem, doc );
00335 }
00336
00337
00338 QDomNodeList startPointList = itemElem.elementsByTagName( "StartPoint" );
00339 if ( startPointList.size() > 0 )
00340 {
00341 QDomElement startPointElem = startPointList.at( 0 ).toElement();
00342 mStartPoint.setX( startPointElem.attribute( "x", "0.0" ).toDouble() );
00343 mStartPoint.setY( startPointElem.attribute( "y", "0.0" ).toDouble() );
00344 }
00345
00346
00347 QDomNodeList stopPointList = itemElem.elementsByTagName( "StopPoint" );
00348 if ( stopPointList.size() > 0 )
00349 {
00350 QDomElement stopPointElem = stopPointList.at( 0 ).toElement();
00351 mStopPoint.setX( stopPointElem.attribute( "x", "0.0" ).toDouble() );
00352 mStopPoint.setY( stopPointElem.attribute( "y", "0.0" ).toDouble() );
00353 }
00354
00355 adaptItemSceneRect();
00356 return true;
00357 }