Index: python/CMakeLists.txt =================================================================== --- python/CMakeLists.txt (revision 14229) +++ python/CMakeLists.txt (working copy) @@ -47,6 +47,7 @@ # additional gui includes INCLUDE_DIRECTORIES( ../src/gui + ../src/gui/mapwidgets ../src/gui/symbology-ng ../src/plugins ${CMAKE_BINARY_DIR}/src/gui Index: src/app/qgsmaptoolscalebarannotation.cpp =================================================================== --- src/app/qgsmaptoolscalebarannotation.cpp (revision 14229) +++ src/app/qgsmaptoolscalebarannotation.cpp (working copy) @@ -1,9 +1,9 @@ /*************************************************************************** - qgsmaptooltextannotation.cpp + qgsmaptoolscalebarannotation.cpp ------------------------------- - begin : February 9, 2010 - copyright : (C) 2010 by Marco Hugentobler - email : marco dot hugentobler at hugis dot net + begin : September 15, 2010 + copyright : (C) 2010 by Tim Sutton + email : Tim Sutton ***************************************************************************/ /*************************************************************************** @@ -15,27 +15,27 @@ * * ***************************************************************************/ -#include "qgsmaptooltextannotation.h" -#include "qgstextannotationitem.h" +#include "qgsmaptoolscalebarannotation.h" +#include "qgsscalebarannotationitem.h" #include -QgsMapToolTextAnnotation::QgsMapToolTextAnnotation( QgsMapCanvas* canvas ): QgsMapToolAnnotation( canvas ) +QgsMapToolScaleBarAnnotation::QgsMapToolScaleBarAnnotation( QgsMapCanvas* canvas ): QgsMapToolAnnotation( canvas ) { } -QgsMapToolTextAnnotation::~QgsMapToolTextAnnotation() +QgsMapToolScaleBarAnnotation::~QgsMapToolScaleBarAnnotation() { } -QgsAnnotationItem* QgsMapToolTextAnnotation::createItem( QMouseEvent* e ) +QgsAnnotationItem* QgsMapToolScaleBarAnnotation::createItem( QMouseEvent* e ) { QgsPoint mapCoord = toMapCoordinates( e->pos() ); - QgsTextAnnotationItem* textItem = new QgsTextAnnotationItem( mCanvas ); - textItem->setMapPosition( toMapCoordinates( e->pos() ) ); - textItem->setFrameSize( QSizeF( 200, 100 ) ); - textItem->setSelected( true ); - return textItem; + QgsScaleBarAnnotationItem* scaleBarItem = new QgsScaleBarAnnotationItem( mCanvas ); + scaleBarItem->setMapPosition( toMapCoordinates( e->pos() ) ); + scaleBarItem->setFrameSize( QSizeF( 200, 100 ) ); + scaleBarItem->setSelected( true ); + return scaleBarItem; } Index: src/app/qgsmaptoolscalebarannotation.h =================================================================== --- src/app/qgsmaptoolscalebarannotation.h (revision 14229) +++ src/app/qgsmaptoolscalebarannotation.h (working copy) @@ -1,9 +1,9 @@ /*************************************************************************** - qgsmaptooltextannotation.h + qgsmaptoolscalebarannotation.h ------------------------- - begin : February 9, 2010 - copyright : (C) 2010 by Marco Hugentobler - email : marco dot hugentobler at hugis dot net + begin : September 15, 2010 + copyright : (C) 2010 by Tim Sutton + email : tim@linfiniti.com ***************************************************************************/ /*************************************************************************** @@ -15,19 +15,19 @@ * * ***************************************************************************/ -#ifndef QGSMAPTOOLTEXTANNOTATION_H -#define QGSMAPTOOLTEXTANNOTATION_H +#ifndef QGSMAPTOOLSCALEBARANNOTATION_H +#define QGSMAPTOOLSCALEBARANNOTATION_H #include "qgsmaptoolannotation.h" -class QgsMapToolTextAnnotation: public QgsMapToolAnnotation +class QgsMapToolScaleBarAnnotation: public QgsMapToolAnnotation { public: - QgsMapToolTextAnnotation( QgsMapCanvas* canvas ); - ~QgsMapToolTextAnnotation(); + QgsMapToolScaleBarAnnotation( QgsMapCanvas* canvas ); + ~QgsMapToolScaleBarAnnotation(); protected: QgsAnnotationItem* createItem( QMouseEvent* e ); }; -#endif // QGSMAPTOOLTEXTANNOTATION_H +#endif // QGSMAPTOOLSCALEBARANNOTATION_H Index: src/app/qgisapp.h =================================================================== --- src/app/qgisapp.h (revision 14229) +++ src/app/qgisapp.h (working copy) @@ -686,6 +686,7 @@ //annotations void addFormAnnotation(); void addTextAnnotation(); + void addScaleBarAnnotation(); void modifyAnnotation(); //! shows label settings dialog (for labeling-ng) @@ -925,6 +926,7 @@ QAction *mActionDraw; QAction *mActionViewSeparator5; QAction *mActionTextAnnotation; + QAction *mActionScaleBarAnnotation; QAction *mActionFormAnnotation; QAction *mActionAnnotation; QAction *mActionLabeling; @@ -1052,6 +1054,7 @@ QgsMapTool* mAnnotation; QgsMapTool* mFormAnnotation; QgsMapTool* mTextAnnotation; + QgsMapTool* mScaleBarAnnotation; } mMapTools; QgsMapTool *mNonEditMapTool; Index: src/app/CMakeLists.txt =================================================================== --- src/app/CMakeLists.txt (revision 14229) +++ src/app/CMakeLists.txt (working copy) @@ -57,6 +57,7 @@ qgsmaptoolsimplify.cpp qgsmaptoolsplitfeatures.cpp qgsmaptooltextannotation.cpp + qgsmaptoolscalebarannotation.cpp qgsmaptoolvertexedit.cpp qgsmeasuredialog.cpp qgsmeasuretool.cpp @@ -334,9 +335,16 @@ ${CMAKE_CURRENT_BINARY_DIR}/../ui ${QT_QTUITOOLS_INCLUDE_DIR} ../core - ../core/gps ../core/gps/qextserialport - ../core/composer ../core/raster ../core/renderer ../core/symbology ../core/symbology-ng - ../gui ../gui/symbology-ng + ../core/gps + ../core/gps/qextserialport + ../core/composer + ../core/raster + ../core/renderer + ../core/symbology + ../core/symbology-ng + ../gui + ../gui/symbology-ng + ../gui/mapwidgets ../plugins ../python gps Index: src/app/qgisapp.cpp =================================================================== --- src/app/qgisapp.cpp (revision 14229) +++ src/app/qgisapp.cpp (working copy) @@ -112,6 +112,7 @@ #include "qgsexception.h" #include "qgsfeature.h" #include "qgsformannotationitem.h" +#include "qgsscalebarannotationitem.h" #include "qgslabelinggui.h" #include "qgsnewvectorlayerdialog.h" #include "qgshelpviewer.h" @@ -209,6 +210,7 @@ #include "qgsmaptoolrotatepointsymbols.h" #include "qgsmaptoolsplitfeatures.h" #include "qgsmaptooltextannotation.h" +#include "qgsmaptoolscalebarannotation.h" #include "qgsmaptoolvertexedit.h" #include "qgsmaptoolzoom.h" #include "qgsmaptoolsimplify.h" @@ -553,6 +555,7 @@ delete mMapTools.mMeasureDist; delete mMapTools.mMeasureArea; delete mMapTools.mMeasureAngle; + delete mMapTools.mScaleBarAnnotation; delete mMapTools.mTextAnnotation; delete mMapTools.mFormAnnotation; delete mMapTools.mAnnotation; @@ -987,6 +990,10 @@ mActionDraw->setStatusTip( tr( "Refresh Map" ) ); connect( mActionDraw, SIGNAL( triggered() ), this, SLOT( refreshMapCanvas() ) ); + mActionScaleBarAnnotation = new QAction( getThemeIcon( "mActionScaleBarAnnotation.png" ), tr( "ScaleBar Annotation" ), this ); + mActionScaleBarAnnotation->setCheckable( true ); + connect( mActionScaleBarAnnotation, SIGNAL( triggered() ), this, SLOT( addScaleBarAnnotation() ) ); + mActionTextAnnotation = new QAction( getThemeIcon( "mActionTextAnnotation.png" ), tr( "Text Annotation" ), this ); mActionTextAnnotation->setCheckable( true ); connect( mActionTextAnnotation, SIGNAL( triggered() ), this, SLOT( addTextAnnotation() ) ); @@ -1747,6 +1754,7 @@ annotationToolButton->setCheckable( true ); annotationToolButton->addAction( mActionTextAnnotation ); annotationToolButton->addAction( mActionFormAnnotation ); + annotationToolButton->addAction( mActionScaleBarAnnotation ); annotationToolButton->addAction( mActionAnnotation ); annotationToolButton->setDefaultAction( mActionTextAnnotation ); connect( annotationToolButton, SIGNAL( triggered( QAction* ) ), @@ -2009,6 +2017,7 @@ mActionAnnotation->setIcon( getThemeIcon( "/mActionAnnotation.png" ) ); mActionFormAnnotation->setIcon( getThemeIcon( "/mActionFormAnnotation.png" ) ); mActionTextAnnotation->setIcon( getThemeIcon( "/mActionTextAnnotation.png" ) ); + mActionScaleBarAnnotation->setIcon( getThemeIcon( "/mActionTextAnnotation.png" ) ); //change themes of all composers QSet::iterator composerIt = mPrintComposers.begin(); @@ -2112,6 +2121,8 @@ mMapTools.mMeasureArea->setAction( mActionMeasureArea ); mMapTools.mMeasureAngle = new QgsMapToolMeasureAngle( mMapCanvas ); mMapTools.mMeasureAngle->setAction( mActionMeasureAngle ); + mMapTools.mScaleBarAnnotation = new QgsMapToolScaleBarAnnotation( mMapCanvas ); + mMapTools.mScaleBarAnnotation->setAction( mActionScaleBarAnnotation ); mMapTools.mTextAnnotation = new QgsMapToolTextAnnotation( mMapCanvas ); mMapTools.mTextAnnotation->setAction( mActionTextAnnotation ); mMapTools.mFormAnnotation = new QgsMapToolFormAnnotation( mMapCanvas ); @@ -3898,6 +3909,12 @@ mMapCanvas->setMapTool( mMapTools.mTextAnnotation ); } + +void QgisApp::addScaleBarAnnotation() +{ + mMapCanvas->setMapTool( mMapTools.mScaleBarAnnotation ); +} + void QgisApp::modifyAnnotation() { mMapCanvas->setMapTool( mMapTools.mAnnotation ); @@ -4262,6 +4279,13 @@ QgsFormAnnotationItem* newFormItem = new QgsFormAnnotationItem( mMapCanvas ); newFormItem->readXML( doc, formItemList.at( i ).toElement() ); } + + QDomNodeList scaleBarItemList = doc.elementsByTagName( "ScaleBarAnnotationItem" ); + for ( int i = 0; i < scaleBarItemList.size(); ++i ) + { + QgsScaleBarAnnotationItem* newScaleBarItem = new QgsScaleBarAnnotationItem( mMapCanvas ); + newScaleBarItem->readXML( doc, formItemList.at( i ).toElement() ); + } return true; } Index: src/gui/qgstextannotationitem.cpp =================================================================== --- src/gui/qgstextannotationitem.cpp (revision 14229) +++ src/gui/qgstextannotationitem.cpp (working copy) @@ -1,102 +0,0 @@ -/*************************************************************************** - qgstextannotationitem.cpp - ------------------------ - begin : February 9, 2010 - copyright : (C) 2010 by Marco Hugentobler - email : marco dot hugentobler at hugis dot net - ***************************************************************************/ - -/*************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ - -#include "qgstextannotationitem.h" -#include -#include - -QgsTextAnnotationItem::QgsTextAnnotationItem( QgsMapCanvas* canvas ): QgsAnnotationItem( canvas ), mDocument( new QTextDocument( QObject::tr( "QGIS rocks!" ) ) ) -{ - mDocument->setUseDesignMetrics( true ); -} - -QgsTextAnnotationItem::~QgsTextAnnotationItem() -{ - delete mDocument; -} - -QTextDocument* QgsTextAnnotationItem::document() const -{ - if ( !mDocument ) - { - return 0; - } - - return mDocument->clone(); -} - -void QgsTextAnnotationItem::setDocument( const QTextDocument* doc ) -{ - delete mDocument; - mDocument = doc->clone(); -} - -void QgsTextAnnotationItem::paint( QPainter * painter ) -{ - if ( !painter || !mDocument ) - { - return; - } - - drawFrame( painter ); - if ( mMapPositionFixed ) - { - drawMarkerSymbol( painter ); - } - double frameWidth = mFrameBorderWidth; - mDocument->setTextWidth( mFrameSize.width() ); - - painter->save(); - painter->translate( mOffsetFromReferencePoint.x() + frameWidth / 2.0, - mOffsetFromReferencePoint.y() + frameWidth / 2.0 ); - - //draw text document - mDocument->drawContents( painter, QRectF( 0, 0, mFrameSize.width() - frameWidth / 2.0, mFrameSize.height() - frameWidth / 2.0 ) ); - painter->restore(); - if ( isSelected() ) - { - drawSelectionBoxes( painter ); - } -} - -void QgsTextAnnotationItem::writeXML( QDomDocument& doc ) const -{ - QDomElement documentElem = doc.documentElement(); - if ( documentElem.isNull() ) - { - return; - } - QDomElement annotationElem = doc.createElement( "TextAnnotationItem" ); - if ( mDocument ) - { - annotationElem.setAttribute( "document", mDocument->toHtml() ); - } - _writeXML( doc, annotationElem ); - documentElem.appendChild( annotationElem ); -} - -void QgsTextAnnotationItem::readXML( const QDomDocument& doc, const QDomElement& itemElem ) -{ - delete mDocument; - mDocument = new QTextDocument; - mDocument->setHtml( itemElem.attribute( "document", QObject::tr( "QGIS rocks!" ) ) ); - QDomElement annotationElem = itemElem.firstChildElement( "AnnotationItem" ); - if ( !annotationElem.isNull() ) - { - _readXML( doc, annotationElem ); - } -} Index: src/gui/mapwidgets/qgstextannotationitem.h =================================================================== --- src/gui/mapwidgets/qgstextannotationitem.h (revision 0) +++ src/gui/mapwidgets/qgstextannotationitem.h (working copy) @@ -21,7 +21,8 @@ #include "qgsannotationitem.h" #include -/**An annotation item that displays formated text*/ +/** \ingroup gui + * An annotation item that displays formated text*/ class GUI_EXPORT QgsTextAnnotationItem: public QgsAnnotationItem { public: Index: src/gui/mapwidgets/qgsscalebarannotationitem.cpp =================================================================== --- src/gui/mapwidgets/qgsscalebarannotationitem.cpp (revision 0) +++ src/gui/mapwidgets/qgsscalebarannotationitem.cpp (revision 0) @@ -0,0 +1,435 @@ +/*************************************************************************** + qgsscalebarannotationitem.h + ------------------------ + begin : Sept 15, 2010 + copyright : (C) 2010 by Tim Sutton + email : tim@linfiniti.com + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#include "qgsscalebarannotationitem.h" +#include "qgslogger.h" +#include "qgsmapcanvas.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "qgsmaplayer.h" +#include "qgsmaptopixel.h" +#include "qgspoint.h" +#include "qgsproject.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//non qt includes +#include + +//the gui subclass +#include "qgslogger.h" + +QgsScaleBarAnnotationItem::QgsScaleBarAnnotationItem( QgsMapCanvas* canvas ): QgsAnnotationItem( canvas ) +{ + if ( mMapCanvas ) + { + QObject::connect( mMapCanvas, SIGNAL( renderComplete( QPainter* ) ), this, SLOT( setFeatureScaleBarapPosition() ) ); + } + setMapPositionFixed( false ); +} + +QgsScaleBarAnnotationItem::~QgsScaleBarAnnotationItem() +{ +} + +void QgsScaleBarAnnotationItem::paint( QPainter * painter ) +{ + renderScaleBar( painter ); +} + +void QgsScaleBarAnnotationItem::paint( QPainter * painter, const QStyleOptionGraphicsItem * option, QWidget * widget ) +{ + if ( !painter ) + { + return; + } + + if ( isSelected() ) + { + drawSelectionBoxes( painter ); + } + + renderScaleBar( painter ); +} + +// Actual drawing of Scale Bar +void QgsScaleBarAnnotationItem::renderScaleBar( QPainter * theQPainter ) +{ + // Get font metric info + int myFontSize = 10; //we use this later for buffering + QFont myFont( "helvetica", myFontSize ); + theQPainter->setFont( myFont ); + QFontMetrics myFontMetrics( myFont ); + double myFontHeight = myFontMetrics.height(); + double myFontWidth = myFontMetrics.width( tr("degrees" ) ); + int myBufferSize = 1; //softcode this later + + //remove the length of the longest possible map unit word (degrees) + int myCanvasWidth = mBoundingRect.width() - myFontWidth; + + //Get map units per pixel. This can be negative at times (to do with + //projections) and that just confuses the rest of the code in this + //function, so force to a positive number. + double myMapUnitsPerPixelDouble = std::abs( mMapCanvas->mapUnitsPerPixel() ); + + // Exit if the canvas width is 0 or layercount is 0 or QGIS will freeze + int myLayerCount = mMapCanvas->layerCount(); + if ( !myLayerCount || !myCanvasWidth || !myMapUnitsPerPixelDouble ) return; + + //Large if statement which determines whether to render the scale bar + // Hard coded sizes + int myMajorTickSize = 8; + int myTextOffsetX = 3; + int myMargin = 20; + + //Calculate size of scale bar for preferred number of map units + double myScaleBarWidth = myCanvasWidth; // pixels + double myActualSize = myScaleBarWidth * myMapUnitsPerPixelDouble; // map units + + // Work out the exponent for the number - e.g, 1234 will give 3, + // and .001234 will give -3 + double myPowerOf10 = floor( log10( myActualSize ) ); + + // snap to integer < 10 times power of 10 + bool mSnapping = true; //hard coded for now + if ( mSnapping ) + { + double scaler = pow( 10.0, myPowerOf10 ); + myActualSize = round( myActualSize / scaler ) * scaler; + myScaleBarWidth = myActualSize / myMapUnitsPerPixelDouble; + } + //Get type of map units and set scale bar unit label text + QGis::UnitType myMapUnits = mMapCanvas->mapUnits(); + QString myScaleBarUnitLabel; + switch ( myMapUnits ) + { + case QGis::Meters: + if ( myActualSize > 1000.0 ) + { + myScaleBarUnitLabel = tr( " km" ); + myActualSize = myActualSize / 1000; + } + else if ( myActualSize < 0.01 ) + { + myScaleBarUnitLabel = tr( " mm" ); + myActualSize = myActualSize * 1000; + } + else if ( myActualSize < 0.1 ) + { + myScaleBarUnitLabel = tr( " cm" ); + myActualSize = myActualSize * 100; + } + else + myScaleBarUnitLabel = tr( " m" ); + break; + case QGis::Feet: + if ( myActualSize > 5280.0 ) //5280 feet to the mile + { + myScaleBarUnitLabel = tr( " miles" ); + // Adjust scale bar width to get even numbers + myActualSize = myActualSize / 5000; + myScaleBarWidth = ( myScaleBarWidth * 5280 ) / 5000; + } + else if ( myActualSize == 5280.0 ) //5280 feet to the mile + { + myScaleBarUnitLabel = tr( " mile" ); + // Adjust scale bar width to get even numbers + myActualSize = myActualSize / 5000; + myScaleBarWidth = ( myScaleBarWidth * 5280 ) / 5000; + } + else if ( myActualSize < 1 ) + { + myScaleBarUnitLabel = tr( " inches" ); + myActualSize = myActualSize * 10; + myScaleBarWidth = ( myScaleBarWidth * 10 ) / 12; + } + else if ( myActualSize == 1.0 ) + { + myScaleBarUnitLabel = tr( " foot" ); + } + else + { + myScaleBarUnitLabel = tr( " feet" ); + } + break; + case QGis::Degrees: + if ( myActualSize == 1.0 ) + myScaleBarUnitLabel = tr( " degree" ); + else + myScaleBarUnitLabel = tr( " degrees" ); + break; + case QGis::UnknownUnit: + myScaleBarUnitLabel = tr( " unknown" ); + default: + QgsDebugMsg( QString( "Error: not picked up map units - actual value = %1" ).arg( myMapUnits ) ); + }; + + //Set font and calculate width of unit label + myFontWidth = myFontMetrics.width( myScaleBarUnitLabel ); + + + + //Set the maximum label + QString myScaleBarMaxLabel = QLocale::system().toString( myActualSize ); + + //Calculate total width of scale bar and label + double myTotalScaleBarWidth = myScaleBarWidth + myFontWidth; + + //determine the origin of scale bar + int myOriginX = 0; + int myOriginY = mBoundingRect.height()/2; + + //Set pen to draw with + QColor mColor(Qt::black); //hard coded for now + QPen myForegroundPen( mColor, 2 ); + QPen myBackgroundPen( Qt::white, 4 ); + + //Cast myScaleBarWidth to int for drawing + int myScaleBarWidthInt = ( int ) myScaleBarWidth; + + //Create array of vertices for scale bar depending on style + int mStyleIndex = 0; //hard coded for now + switch ( mStyleIndex ) + { + case 0: // Tick Down + { + QPolygon myTickDownArray( 4 ); + //draw a buffer first so bar shows up on dark images + theQPainter->setPen( myBackgroundPen ); + myTickDownArray.putPoints( 0, 4, + myOriginX , ( myOriginY + myMajorTickSize ) , + myOriginX , myOriginY , + ( myScaleBarWidthInt + myOriginX ), myOriginY , + ( myScaleBarWidthInt + myOriginX ), ( myOriginY + myMajorTickSize ) + ); + theQPainter->drawPolyline( myTickDownArray ); + //now draw the bar itself in user selected color + theQPainter->setPen( myForegroundPen ); + myTickDownArray.putPoints( 0, 4, + myOriginX , ( myOriginY + myMajorTickSize ) , + myOriginX , myOriginY , + ( myScaleBarWidthInt + myOriginX ), myOriginY , + ( myScaleBarWidthInt + myOriginX ), ( myOriginY + myMajorTickSize ) + ); + theQPainter->drawPolyline( myTickDownArray ); + break; + } + case 1: // tick up + { + QPolygon myTickUpArray( 4 ); + //draw a buffer first so bar shows up on dark images + theQPainter->setPen( myBackgroundPen ); + myTickUpArray.putPoints( 0, 4, + myOriginX , myOriginY , + myOriginX , myOriginY + myMajorTickSize , + ( myScaleBarWidthInt + myOriginX ), myOriginY + myMajorTickSize , + ( myScaleBarWidthInt + myOriginX ), myOriginY + ); + theQPainter->drawPolyline( myTickUpArray ); + //now draw the bar itself in user selected color + theQPainter->setPen( myForegroundPen ); + myTickUpArray.putPoints( 0, 4, + myOriginX , myOriginY , + myOriginX , myOriginY + myMajorTickSize , + ( myScaleBarWidthInt + myOriginX ), myOriginY + myMajorTickSize , + ( myScaleBarWidthInt + myOriginX ), myOriginY + ); + theQPainter->drawPolyline( myTickUpArray ); + break; + } + case 2: // Bar + { + QPolygon myBarArray( 2 ); + //draw a buffer first so bar shows up on dark images + theQPainter->setPen( myBackgroundPen ); + myBarArray.putPoints( 0, 2, + myOriginX , ( myOriginY + ( myMajorTickSize / 2 ) ), + ( myScaleBarWidthInt + myOriginX ), ( myOriginY + ( myMajorTickSize / 2 ) ) + ); + theQPainter->drawPolyline( myBarArray ); + //now draw the bar itself in user selected color + theQPainter->setPen( myForegroundPen ); + myBarArray.putPoints( 0, 2, + myOriginX , ( myOriginY + ( myMajorTickSize / 2 ) ), + ( myScaleBarWidthInt + myOriginX ), ( myOriginY + ( myMajorTickSize / 2 ) ) + ); + theQPainter->drawPolyline( myBarArray ); + break; + } + case 3: // box + { + // Want square corners for a box + myBackgroundPen.setJoinStyle( Qt::MiterJoin ); + myForegroundPen.setJoinStyle( Qt::MiterJoin ); + QPolygon myBoxArray( 5 ); + //draw a buffer first so bar shows up on dark images + theQPainter->setPen( myBackgroundPen ); + myBoxArray.putPoints( 0, 5, + myOriginX , myOriginY, + ( myScaleBarWidthInt + myOriginX ), myOriginY, + ( myScaleBarWidthInt + myOriginX ), ( myOriginY + myMajorTickSize ), + myOriginX , ( myOriginY + myMajorTickSize ), + myOriginX , myOriginY + ); + theQPainter->drawPolyline( myBoxArray ); + //now draw the bar itself in user selected color + theQPainter->setPen( myForegroundPen ); + theQPainter->setBrush( QBrush( mColor, Qt::SolidPattern ) ); + int midPointX = myScaleBarWidthInt / 2 + myOriginX; + myBoxArray.putPoints( 0, 5, + myOriginX , myOriginY, + midPointX, myOriginY, + midPointX, ( myOriginY + myMajorTickSize ), + myOriginX , ( myOriginY + myMajorTickSize ), + myOriginX , myOriginY + ); + theQPainter->drawPolygon( myBoxArray ); + + theQPainter->setBrush( Qt::NoBrush ); + myBoxArray.putPoints( 0, 5, + midPointX , myOriginY, + ( myScaleBarWidthInt + myOriginX ), myOriginY, + ( myScaleBarWidthInt + myOriginX ), ( myOriginY + myMajorTickSize ), + midPointX , ( myOriginY + myMajorTickSize ), + midPointX , myOriginY + ); + theQPainter->drawPolygon( myBoxArray ); + break; + } + default: + QgsDebugMsg( "Unknown style" ); + } + + // + //Do drawing of scale bar text + // + + QColor myBackColor = Qt::white; + QColor myForeColor = Qt::black; + + //Draw the minimum label buffer + theQPainter->setPen( myBackColor ); + myFontWidth = myFontMetrics.width( "0" ); + myFontHeight = myFontMetrics.height(); + + for ( int i = 0 - myBufferSize; i <= myBufferSize; i++ ) + { + for ( int j = 0 - myBufferSize; j <= myBufferSize; j++ ) + { + theQPainter->drawText( int( i + ( myOriginX - ( myFontWidth / 2 ) ) ), + int( j + ( myOriginY - ( myFontHeight / 4 ) ) ), + "0" ); + } + } + + //Draw minimum label + theQPainter->setPen( myForeColor ); + + theQPainter->drawText( + int( myOriginX - ( myFontWidth / 2 ) ), + int( myOriginY - ( myFontHeight / 4 ) ), + "0" + ); + + // + //Draw maximum label + // + theQPainter->setPen( myBackColor ); + myFontWidth = myFontMetrics.width( myScaleBarMaxLabel ); + myFontHeight = myFontMetrics.height(); + //first the buffer + for ( int i = 0 - myBufferSize; i <= myBufferSize; i++ ) + { + for ( int j = 0 - myBufferSize; j <= myBufferSize; j++ ) + { + theQPainter->drawText( int( i + ( myOriginX + myScaleBarWidthInt - ( myFontWidth / 2 ) ) ), + int( j + ( myOriginY - ( myFontHeight / 4 ) ) ), + myScaleBarMaxLabel ); + } + } + //then the text itself + theQPainter->setPen( myForeColor ); + theQPainter->drawText( + int( myOriginX + myScaleBarWidthInt - ( myFontWidth / 2 ) ), + int( myOriginY - ( myFontHeight / 4 ) ), + myScaleBarMaxLabel + ); + + // + //Draw unit label + // + theQPainter->setPen( myBackColor ); + myFontWidth = myFontMetrics.width( myScaleBarUnitLabel ); + myFontHeight = myFontMetrics.height(); + //first the buffer + for ( int i = 0 - myBufferSize; i <= myBufferSize; i++ ) + { + for ( int j = 0 - myBufferSize; j <= myBufferSize; j++ ) + { + theQPainter->drawText( i + ( myOriginX + myScaleBarWidthInt + myTextOffsetX ), + j + ( myOriginY + myMajorTickSize ), + myScaleBarUnitLabel ); + } + } + //then the text itself + theQPainter->setPen( myForeColor ); + theQPainter->drawText( + ( myOriginX + myScaleBarWidthInt + myTextOffsetX ), ( myOriginY + myMajorTickSize ), + myScaleBarUnitLabel + ); +} + +void QgsScaleBarAnnotationItem::writeXML( QDomDocument& doc ) const +{ + QDomElement documentElem = doc.documentElement(); + if ( documentElem.isNull() ) + { + return; + } + + QDomElement scaleBarAnnotationElem = doc.createElement( "ScaleBarAnnotationItem" ); + scaleBarAnnotationElem.setAttribute( "scalebar", "foo"); + _writeXML( doc, scaleBarAnnotationElem ); + documentElem.appendChild( scaleBarAnnotationElem ); +} + +void QgsScaleBarAnnotationItem::readXML( const QDomDocument& doc, const QDomElement& itemElem ) +{ + QObject::connect( mMapCanvas, SIGNAL( renderComplete( QPainter* ) ), this, SLOT( setFeatureScaleBarapPosition() ) ); + QDomElement annotationElem = itemElem.firstChildElement( "AnnotationItem" ); + if ( !annotationElem.isNull() ) + { + _readXML( doc, annotationElem ); + } +} Index: src/gui/mapwidgets/qgsscalebarannotationitem.h =================================================================== --- src/gui/mapwidgets/qgsscalebarannotationitem.h (revision 0) +++ src/gui/mapwidgets/qgsscalebarannotationitem.h (revision 0) @@ -0,0 +1,50 @@ +/*************************************************************************** + qgsscalebarannotationitem.h + ------------------------ + begin : September 15 2010 + copyright : (C) 2010 by Tim Sutton + email : tim@linfiniti.com + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#ifndef QGSSCALEBARANNOTATIONITEM_H +#define QGSSCALEBARANNOTATIONITEM_H + +#include "qgsannotationitem.h" +#include + +class QGraphicsProxyWidget; + +/** \ingroup gui + * An annotation item that embeds a ScaleBar */ +class GUI_EXPORT QgsScaleBarAnnotationItem: public QObject, public QgsAnnotationItem +{ + Q_OBJECT + public: + QgsScaleBarAnnotationItem( QgsMapCanvas* canvas ); + ~QgsScaleBarAnnotationItem(); + + void paint( QPainter * painter ); + + //! paint function called by map canvas + void paint( QPainter * painter, const QStyleOptionGraphicsItem * option, QWidget * widget = 0 ); + + void writeXML( QDomDocument& doc ) const; + void readXML( const QDomDocument& doc, const QDomElement& itemElem ); + + + private slots: + + private: + void renderScaleBar( QPainter * theQPainter ); +}; + +#endif // QGSSCALEBARANNOTATIONITEM_H Index: src/gui/mapwidgets/qgsannotationitem.h =================================================================== --- src/gui/mapwidgets/qgsannotationitem.h (revision 0) +++ src/gui/mapwidgets/qgsannotationitem.h (working copy) @@ -26,7 +26,8 @@ class QgsVectorLayer; class QgsMarkerSymbolV2; -/**An annotation item can be either placed either on screen corrdinates or on map coordinates. +/** \ingroup gui + * An annotation item can be either placed either on screen corrdinates or on map coordinates. It may reference a feature and displays that associatiation with a balloon like appearance*/ class GUI_EXPORT QgsAnnotationItem: public QgsMapCanvasItem { Index: src/gui/qgsformannotationitem.cpp =================================================================== --- src/gui/qgsformannotationitem.cpp (revision 14229) +++ src/gui/qgsformannotationitem.cpp (working copy) @@ -1,271 +0,0 @@ -/*************************************************************************** - qgsformannotationitem.h - ------------------------ - begin : February 26, 2010 - copyright : (C) 2010 by Marco Hugentobler - email : marco dot hugentobler at hugis dot net - ***************************************************************************/ - -/*************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ - -#include "qgsformannotationitem.h" -#include "qgsattributeeditor.h" -#include "qgsfeature.h" -#include "qgslogger.h" -#include "qgsmapcanvas.h" -#include "qgsmaplayerregistry.h" -#include "qgsvectorlayer.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include - -QgsFormAnnotationItem::QgsFormAnnotationItem( QgsMapCanvas* canvas, QgsVectorLayer* vlayer, bool hasFeature, int feature ): \ - QgsAnnotationItem( canvas ), mWidgetContainer( 0 ), mDesignerWidget( 0 ), mVectorLayer( vlayer ), \ - mHasAssociatedFeature( hasFeature ), mFeature( feature ) -{ - mWidgetContainer = new QGraphicsProxyWidget( this ); - if ( mVectorLayer && mMapCanvas ) //default to the layers edit form - { - mDesignerForm = mVectorLayer->annotationForm(); - QObject::connect( mVectorLayer, SIGNAL( layerModified( bool ) ), this, SLOT( setFeatureForMapPosition() ) ); - QObject::connect( mMapCanvas, SIGNAL( renderComplete( QPainter* ) ), this, SLOT( setFeatureForMapPosition() ) ); - QObject::connect( mMapCanvas, SIGNAL( layersChanged() ), this, SLOT( updateVisibility() ) ); - } - - setFeatureForMapPosition(); -} - -QgsFormAnnotationItem::~QgsFormAnnotationItem() -{ - delete mDesignerWidget; -} - -void QgsFormAnnotationItem::setDesignerForm( const QString& uiFile ) -{ - mDesignerForm = uiFile; - mWidgetContainer->setWidget( 0 ); - delete mDesignerWidget; - mDesignerWidget = createDesignerWidget( uiFile ); - if ( mDesignerWidget ) - { - mFrameBackgroundColor = mDesignerWidget->palette().color( QPalette::Window ); - mWidgetContainer->setWidget( mDesignerWidget ); - setFrameSize( preferredFrameSize() ); - } -} - -QWidget* QgsFormAnnotationItem::createDesignerWidget( const QString& filePath ) -{ - QFile file( filePath ); - if ( !file.open( QFile::ReadOnly ) ) - { - return 0; - } - - QUiLoader loader; - QFileInfo fi( file ); - loader.setWorkingDirectory( fi.dir() ); - QWidget* widget = loader.load( &file, 0 ); - file.close(); - - //get feature and set attribute information - if ( mVectorLayer && mHasAssociatedFeature ) - { - QgsFeature f; - if ( mVectorLayer->featureAtId( mFeature, f, false, true ) ) - { - const QgsFieldMap& fieldMap = mVectorLayer->pendingFields(); - QgsAttributeMap attMap = f.attributeMap(); - QgsAttributeMap::const_iterator attIt = attMap.constBegin(); - for ( ; attIt != attMap.constEnd(); ++attIt ) - { - QgsFieldMap::const_iterator fieldIt = fieldMap.find( attIt.key() ); - if ( fieldIt != fieldMap.constEnd() ) - { - QWidget* attWidget = widget->findChild( fieldIt->name() ); - if ( attWidget ) - { - QgsAttributeEditor::createAttributeEditor( widget, attWidget, mVectorLayer, attIt.key(), attIt.value() ); - } - } - } - } - } - return widget; -} - -void QgsFormAnnotationItem::setMapPosition( const QgsPoint& pos ) -{ - QgsAnnotationItem::setMapPosition( pos ); - setFeatureForMapPosition(); -} - -void QgsFormAnnotationItem::paint( QPainter * painter ) -{ - -} - -void QgsFormAnnotationItem::paint( QPainter * painter, const QStyleOptionGraphicsItem * option, QWidget * widget ) -{ - if ( !painter || !mWidgetContainer ) - { - return; - } - - drawFrame( painter ); - if ( mMapPositionFixed ) - { - drawMarkerSymbol( painter ); - } - - mWidgetContainer->setGeometry( QRectF( mOffsetFromReferencePoint.x() + mFrameBorderWidth / 2.0, mOffsetFromReferencePoint.y() \ - + mFrameBorderWidth / 2.0, mFrameSize.width() - mFrameBorderWidth, mFrameSize.height() \ - - mFrameBorderWidth ) ); - - if ( isSelected() ) - { - drawSelectionBoxes( painter ); - } -} - -QSizeF QgsFormAnnotationItem::minimumFrameSize() const -{ - if ( mDesignerWidget ) - { - QSizeF widgetMinSize = mDesignerWidget->minimumSize(); - return QSizeF( 2 * mFrameBorderWidth + widgetMinSize.width(), 2 * mFrameBorderWidth + widgetMinSize.height() ); - } - else - { - return QSizeF( 0, 0 ); - } -} - -QSizeF QgsFormAnnotationItem::preferredFrameSize() const -{ - if ( mDesignerWidget ) - { - return mDesignerWidget->sizeHint(); - } - else - { - return QSizeF( 0, 0 ); - } -} - -void QgsFormAnnotationItem::writeXML( QDomDocument& doc ) const -{ - QDomElement documentElem = doc.documentElement(); - if ( documentElem.isNull() ) - { - return; - } - - QDomElement formAnnotationElem = doc.createElement( "FormAnnotationItem" ); - if ( mVectorLayer ) - { - formAnnotationElem.setAttribute( "vectorLayer", mVectorLayer->getLayerID() ); - } - formAnnotationElem.setAttribute( "hasFeature", mHasAssociatedFeature ); - formAnnotationElem.setAttribute( "feature", mFeature ); - formAnnotationElem.setAttribute( "designerForm", mDesignerForm ); - _writeXML( doc, formAnnotationElem ); - documentElem.appendChild( formAnnotationElem ); -} - -void QgsFormAnnotationItem::readXML( const QDomDocument& doc, const QDomElement& itemElem ) -{ - mVectorLayer = 0; - if ( itemElem.hasAttribute( "vectorLayer" ) ) - { - mVectorLayer = dynamic_cast( QgsMapLayerRegistry::instance()->mapLayer( itemElem.attribute( "vectorLayer", "" ) ) ); - if ( mVectorLayer ) - { - QObject::connect( mVectorLayer, SIGNAL( layerModified( bool ) ), this, SLOT( setFeatureForMapPosition() ) ); - QObject::connect( mMapCanvas, SIGNAL( renderComplete( QPainter* ) ), this, SLOT( setFeatureForMapPosition() ) ); - QObject::connect( mMapCanvas, SIGNAL( layersChanged() ), this, SLOT( updateVisibility() ) ); - } - } - mHasAssociatedFeature = itemElem.attribute( "hasFeature", "0" ).toInt(); - mFeature = itemElem.attribute( "feature", "0" ).toInt(); - mDesignerForm = itemElem.attribute( "designerForm", "" ); - QDomElement annotationElem = itemElem.firstChildElement( "AnnotationItem" ); - if ( !annotationElem.isNull() ) - { - _readXML( doc, annotationElem ); - } - - mDesignerWidget = createDesignerWidget( mDesignerForm ); - if ( mDesignerWidget ) - { - mFrameBackgroundColor = mDesignerWidget->palette().color( QPalette::Window ); - mWidgetContainer->setWidget( mDesignerWidget ); - } - updateVisibility(); -} - -void QgsFormAnnotationItem::setFeatureForMapPosition() -{ - if ( !mVectorLayer || !mMapCanvas ) - { - return; - } - - QgsAttributeList noAttributes; - QSettings settings; - double identifyValue = settings.value( "/Map/identifyRadius", QGis::DEFAULT_IDENTIFY_RADIUS ).toDouble(); - double halfIdentifyWidth = mMapCanvas->extent().width() / 100 / 2 * identifyValue; - QgsRectangle searchRect( mMapPosition.x() - halfIdentifyWidth, mMapPosition.y() - halfIdentifyWidth, \ - mMapPosition.x() + halfIdentifyWidth, mMapPosition.y() + halfIdentifyWidth ); - mVectorLayer->select( noAttributes, searchRect, false, true ); - - QgsFeature currentFeature; - int currentFeatureId = 0; - bool featureFound = false; - - while ( mVectorLayer->nextFeature( currentFeature ) ) - { - currentFeatureId = currentFeature.id(); - featureFound = true; - break; - } - - mHasAssociatedFeature = featureFound; - mFeature = currentFeatureId; - - //create new embedded widget - mWidgetContainer->setWidget( 0 ); - delete mDesignerWidget; - mDesignerWidget = createDesignerWidget( mDesignerForm ); - if ( mDesignerWidget ) - { - mFrameBackgroundColor = mDesignerWidget->palette().color( QPalette::Window ); - mWidgetContainer->setWidget( mDesignerWidget ); - } -} - -void QgsFormAnnotationItem::updateVisibility() -{ - bool visible = true; - if ( mVectorLayer && mMapCanvas ) - { - visible = mMapCanvas->layers().contains( mVectorLayer ); - } - setVisible( visible ); -} - - - Index: src/gui/qgsannotationitem.cpp =================================================================== --- src/gui/qgsannotationitem.cpp (revision 14229) +++ src/gui/qgsannotationitem.cpp (working copy) @@ -1,453 +0,0 @@ -/*************************************************************************** - qgsannotationitem.cpp - ---------------------- - begin : February 9, 2010 - copyright : (C) 2010 by Marco Hugentobler - email : marco dot hugentobler at hugis dot net - ***************************************************************************/ - -/*************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ - -#include "qgsannotationitem.h" -#include "qgsmapcanvas.h" -#include "qgsrendercontext.h" -#include "qgssymbollayerv2utils.h" -#include "qgssymbolv2.h" -#include -#include - -QgsAnnotationItem::QgsAnnotationItem( QgsMapCanvas* mapCanvas ): QgsMapCanvasItem( mapCanvas ), mMapPositionFixed( true ), mOffsetFromReferencePoint( QPointF( 50, -50 ) ) -{ - setFlag( QGraphicsItem::ItemIsSelectable, true ); - mMarkerSymbol = new QgsMarkerSymbolV2(); - mFrameBorderWidth = 1.0; - mFrameColor = QColor( 0, 0, 0 ); - mFrameBackgroundColor = QColor( 255, 255, 255 ); -} - -QgsAnnotationItem::~QgsAnnotationItem() -{ - delete mMarkerSymbol; -} - -void QgsAnnotationItem::setMarkerSymbol( QgsMarkerSymbolV2* symbol ) -{ - delete mMarkerSymbol; - mMarkerSymbol = symbol; - updateBoundingRect(); -} - -void QgsAnnotationItem::setMapPosition( const QgsPoint& pos ) -{ - mMapPosition = pos; - setPos( toCanvasCoordinates( mMapPosition ) ); -} - -void QgsAnnotationItem::setOffsetFromReferencePoint( const QPointF& offset ) -{ - mOffsetFromReferencePoint = offset; - updateBoundingRect(); - updateBalloon(); -} - -void QgsAnnotationItem::setMapPositionFixed( bool fixed ) -{ - if ( mMapPositionFixed && !fixed ) - { - //set map position to the top left corner of the balloon - setMapPosition( toMapCoordinates( QPointF( pos() + mOffsetFromReferencePoint ).toPoint() ) ); - mOffsetFromReferencePoint = QPointF( 0, 0 ); - } - else if ( fixed && !mMapPositionFixed ) - { - setMapPosition( toMapCoordinates( QPointF( pos() + QPointF( -100, -100 ) ).toPoint() ) ); - mOffsetFromReferencePoint = QPointF( 100, 100 ); - } - mMapPositionFixed = fixed; - updateBoundingRect(); - updateBalloon(); - update(); -} - -void QgsAnnotationItem::updatePosition() -{ - if ( mMapPositionFixed ) - { - setPos( toCanvasCoordinates( mMapPosition ) ); - } - else - { - mMapPosition = toMapCoordinates( pos().toPoint() ); - } -} - -QRectF QgsAnnotationItem::boundingRect() const -{ - return mBoundingRect; -} - -QSizeF QgsAnnotationItem::minimumFrameSize() const -{ - return QSizeF( 0, 0 ); -} - -void QgsAnnotationItem::updateBoundingRect() -{ - prepareGeometryChange(); - double halfSymbolSize = 0.0; - if ( mMarkerSymbol ) - { - halfSymbolSize = scaledSymbolSize() / 2.0; - } - - double xMinPos = std::min( -halfSymbolSize, mOffsetFromReferencePoint.x() - mFrameBorderWidth ); - double xMaxPos = std::max( halfSymbolSize, mOffsetFromReferencePoint.x() + mFrameSize.width() + mFrameBorderWidth ); - double yMinPos = std::min( -halfSymbolSize, mOffsetFromReferencePoint.y() - mFrameBorderWidth ); - double yMaxPos = std::max( halfSymbolSize, mOffsetFromReferencePoint.y() + mFrameSize.height() + mFrameBorderWidth ); - mBoundingRect = QRectF( xMinPos, yMinPos, xMaxPos - xMinPos, yMaxPos - yMinPos ); -} - -void QgsAnnotationItem::updateBalloon() -{ - //first test if the point is in the frame. In that case we don't need a balloon. - if ( !mMapPositionFixed || - ( mOffsetFromReferencePoint.x() < 0 && ( mOffsetFromReferencePoint.x() + mFrameSize.width() ) > 0 \ - && mOffsetFromReferencePoint.y() < 0 && ( mOffsetFromReferencePoint.y() + mFrameSize.height() ) > 0 ) ) - { - mBalloonSegment = -1; - return; - } - - //edge list - QList segmentList; - segmentList << segment( 0 ); segmentList << segment( 1 ); segmentList << segment( 2 ); segmentList << segment( 3 ); - - //find closest edge / closest edge point - double minEdgeDist = DBL_MAX; - int minEdgeIndex = -1; - QLineF minEdge; - QgsPoint minEdgePoint; - QgsPoint origin( 0, 0 ); - - for ( int i = 0; i < 4; ++i ) - { - QLineF currentSegment = segmentList.at( i ); - QgsPoint currentMinDistPoint; - double currentMinDist = origin.sqrDistToSegment( currentSegment.x1(), currentSegment.y1(), currentSegment.x2(), currentSegment.y2(), currentMinDistPoint ); - if ( currentMinDist < minEdgeDist ) - { - minEdgeIndex = i; - minEdgePoint = currentMinDistPoint; - minEdgeDist = currentMinDist; - minEdge = currentSegment; - } - } - - if ( minEdgeIndex < 0 ) - { - return; - } - - //make that configurable for the item - double segmentPointWidth = 10; - - mBalloonSegment = minEdgeIndex; - QPointF minEdgeEnd = minEdge.p2(); - mBalloonSegmentPoint1 = QPointF( minEdgePoint.x(), minEdgePoint.y() ); - if ( sqrt( minEdgePoint.sqrDist( minEdgeEnd.x(), minEdgeEnd.y() ) ) < segmentPointWidth ) - { - mBalloonSegmentPoint1 = pointOnLineWithDistance( minEdge.p2(), minEdge.p1(), segmentPointWidth ); - } - - mBalloonSegmentPoint2 = pointOnLineWithDistance( mBalloonSegmentPoint1, minEdge.p2(), 10 ); -} - -void QgsAnnotationItem::drawFrame( QPainter* p ) -{ - QPen framePen( mFrameColor ); - framePen.setWidthF( mFrameBorderWidth ); - - p->setPen( framePen ); - QBrush frameBrush( mFrameBackgroundColor ); - p->setBrush( frameBrush ); - p->setRenderHint( QPainter::Antialiasing, true ); - - QPolygonF poly; - for ( int i = 0; i < 4; ++i ) - { - QLineF currentSegment = segment( i ); - poly << currentSegment.p1(); - if ( i == mBalloonSegment && mMapPositionFixed ) - { - poly << mBalloonSegmentPoint1; - poly << QPointF( 0, 0 ); - poly << mBalloonSegmentPoint2; - } - poly << currentSegment.p2(); - } - p->drawPolygon( poly ); -} - -void QgsAnnotationItem::setFrameSize( const QSizeF& size ) -{ - QSizeF frameSize = minimumFrameSize().expandedTo( size ); //don't allow frame sizes below minimum - mFrameSize = frameSize; - updateBoundingRect(); - updateBalloon(); -} - -void QgsAnnotationItem::drawMarkerSymbol( QPainter* p ) -{ - if ( !p ) - { - return; - } - - QgsRenderContext renderContext; - if ( !setRenderContextVariables( p, renderContext ) ) - { - return; - } - - QPointF canvasPoint = toCanvasCoordinates( mMapPosition ); - if ( mMarkerSymbol ) - { - mMarkerSymbol->startRender( renderContext ); - mMarkerSymbol->renderPoint( QPointF( 0, 0 ), renderContext ); - mMarkerSymbol->stopRender( renderContext ); - } -} - -void QgsAnnotationItem::drawSelectionBoxes( QPainter* p ) -{ - if ( !p ) - { - return; - } - - //no selection boxes for composer mode - if ( data( 0 ).toString() == "composer" ) - { - return; - } - - double handlerSize = 10; - p->setPen( Qt::NoPen ); - p->setBrush( QColor( 200, 200, 210, 120 ) ); - p->drawRect( QRectF( mBoundingRect.left(), mBoundingRect.top(), handlerSize, handlerSize ) ); - p->drawRect( QRectF( mBoundingRect.right() - handlerSize, mBoundingRect.top(), handlerSize, handlerSize ) ); - p->drawRect( QRectF( mBoundingRect.right() - handlerSize, mBoundingRect.bottom() - handlerSize, handlerSize, handlerSize ) ); - p->drawRect( QRectF( mBoundingRect.left(), mBoundingRect.bottom() - handlerSize, handlerSize, handlerSize ) ); -} - -QLineF QgsAnnotationItem::segment( int index ) -{ - switch ( index ) - { - case 0: - return QLineF( mOffsetFromReferencePoint.x(), mOffsetFromReferencePoint.y(), mOffsetFromReferencePoint.x() \ - + mFrameSize.width(), mOffsetFromReferencePoint.y() ); - case 1: - return QLineF( mOffsetFromReferencePoint.x() + mFrameSize.width(), mOffsetFromReferencePoint.y(), \ - mOffsetFromReferencePoint.x() + mFrameSize.width(), mOffsetFromReferencePoint.y() + mFrameSize.height() ); - case 2: - return QLineF( mOffsetFromReferencePoint.x() + mFrameSize.width(), mOffsetFromReferencePoint.y() + mFrameSize.height(), \ - mOffsetFromReferencePoint.x(), mOffsetFromReferencePoint.y() + mFrameSize.height() ); - case 3: - return QLineF( mOffsetFromReferencePoint.x(), mOffsetFromReferencePoint.y() + mFrameSize.height(), \ - mOffsetFromReferencePoint.x(), mOffsetFromReferencePoint.y() ); - default: - return QLineF(); - } -} - -QPointF QgsAnnotationItem::pointOnLineWithDistance( const QPointF& startPoint, const QPointF& directionPoint, double distance ) const -{ - double dx = directionPoint.x() - startPoint.x(); - double dy = directionPoint.y() - startPoint.y(); - double length = sqrt( dx * dx + dy * dy ); - double scaleFactor = distance / length; - return QPointF( startPoint.x() + dx * scaleFactor, startPoint.y() + dy * scaleFactor ); -} - -QgsAnnotationItem::MouseMoveAction QgsAnnotationItem::moveActionForPosition( const QPointF& pos ) const -{ - QPointF itemPos = mapFromScene( pos ); - - int cursorSensitivity = 7; - - if ( abs( itemPos.x() ) < cursorSensitivity && abs( itemPos.y() ) < cursorSensitivity ) //move map point if position is close to the origin - { - return MoveMapPosition; - } - - bool left, right, up, down; - left = abs( itemPos.x() - mOffsetFromReferencePoint.x() ) < cursorSensitivity; - right = abs( itemPos.x() - ( mOffsetFromReferencePoint.x() + mFrameSize.width() ) ) < cursorSensitivity; - up = abs( itemPos.y() - mOffsetFromReferencePoint.y() ) < cursorSensitivity; - down = abs( itemPos.y() - ( mOffsetFromReferencePoint.y() + mFrameSize.height() ) ) < cursorSensitivity; - - if ( left && up ) - { - return ResizeFrameLeftUp; - } - else if ( right && up ) - { - return ResizeFrameRightUp; - } - else if ( left && down ) - { - return ResizeFrameLeftDown; - } - else if ( right && down ) - { - return ResizeFrameRightDown; - } - if ( left ) - { - return ResizeFrameLeft; - } - if ( right ) - { - return ResizeFrameRight; - } - if ( up ) - { - return ResizeFrameUp; - } - if ( down ) - { - return ResizeFrameDown; - } - - //finally test if pos is in the frame area - if ( itemPos.x() >= mOffsetFromReferencePoint.x() && itemPos.x() <= ( mOffsetFromReferencePoint.x() + mFrameSize.width() ) \ - && itemPos.y() >= mOffsetFromReferencePoint.y() && itemPos.y() <= ( mOffsetFromReferencePoint.y() + mFrameSize.height() ) ) - { - return MoveFramePosition; - } - return NoAction; -} - -Qt::CursorShape QgsAnnotationItem::cursorShapeForAction( MouseMoveAction moveAction ) const -{ - switch ( moveAction ) - { - case NoAction: - return Qt::ArrowCursor; - case MoveMapPosition: - case MoveFramePosition: - return Qt::SizeAllCursor; - case ResizeFrameUp: - case ResizeFrameDown: - return Qt::SizeVerCursor; - case ResizeFrameLeft: - case ResizeFrameRight: - return Qt::SizeHorCursor; - case ResizeFrameLeftUp: - case ResizeFrameRightDown: - return Qt::SizeFDiagCursor; - case ResizeFrameRightUp: - case ResizeFrameLeftDown: - return Qt::SizeBDiagCursor; - default: - return Qt::ArrowCursor; - } -} - -double QgsAnnotationItem::scaledSymbolSize() const -{ - if ( !mMarkerSymbol ) - { - return 0.0; - } - - if ( !mMapCanvas ) - { - return mMarkerSymbol->size(); - } - - double dpmm = mMapCanvas->logicalDpiX() / 25.4; - return dpmm * mMarkerSymbol->size(); -} - -void QgsAnnotationItem::_writeXML( QDomDocument& doc, QDomElement& itemElem ) const -{ - if ( itemElem.isNull() ) - { - return; - } - QDomElement annotationElem = doc.createElement( "AnnotationItem" ); - annotationElem.setAttribute( "mapPositionFixed", mMapPositionFixed ); - annotationElem.setAttribute( "mapPosX", mMapPosition.x() ); - annotationElem.setAttribute( "mapPosY", mMapPosition.y() ); - annotationElem.setAttribute( "offsetX", mOffsetFromReferencePoint.x() ); - annotationElem.setAttribute( "offsetY", mOffsetFromReferencePoint.y() ); - annotationElem.setAttribute( "frameWidth", mFrameSize.width() ); - annotationElem.setAttribute( "frameHeight", mFrameSize.height() ); - QPointF canvasPos = pos(); - annotationElem.setAttribute( "canvasPosX", canvasPos.x() ); - annotationElem.setAttribute( "canvasPosY", canvasPos.y() ); - annotationElem.setAttribute( "frameBorderWidth", mFrameBorderWidth ); - annotationElem.setAttribute( "frameColor", mFrameColor.name() ); - annotationElem.setAttribute( "frameBackgroundColor", mFrameBackgroundColor.name() ); - annotationElem.setAttribute( "frameBackgroundColorAlpha", mFrameBackgroundColor.alpha() ); - annotationElem.setAttribute( "visible", isVisible() ); - if ( mMarkerSymbol ) - { - QDomElement symbolElem = QgsSymbolLayerV2Utils::saveSymbol( "marker symbol", mMarkerSymbol, doc ); - if ( !symbolElem.isNull() ) - { - annotationElem.appendChild( symbolElem ); - } - } - itemElem.appendChild( annotationElem ); -} - -void QgsAnnotationItem::_readXML( const QDomDocument& doc, const QDomElement& annotationElem ) -{ - if ( annotationElem.isNull() ) - { - return; - } - QPointF pos; - pos.setX( annotationElem.attribute( "canvasPosX", "0" ).toDouble() ); - pos.setY( annotationElem.attribute( "canvasPosY", "0" ).toDouble() ); - setPos( pos ); - QgsPoint mapPos; - mapPos.setX( annotationElem.attribute( "mapPosX", "0" ).toDouble() ); - mapPos.setY( annotationElem.attribute( "mapPosY", "0" ).toDouble() ); - mMapPosition = mapPos; - mFrameBorderWidth = annotationElem.attribute( "frameBorderWidth", "0.5" ).toDouble(); - mFrameColor.setNamedColor( annotationElem.attribute( "frameColor", "#000000" ) ); - mFrameBackgroundColor.setNamedColor( annotationElem.attribute( "frameBackgroundColor" ) ); - mFrameBackgroundColor.setAlpha( annotationElem.attribute( "frameBackgroundColorAlpha", "255" ).toInt() ); - mFrameSize.setWidth( annotationElem.attribute( "frameWidth", "50" ).toDouble() ); - mFrameSize.setHeight( annotationElem.attribute( "frameHeight", "50" ).toDouble() ); - mOffsetFromReferencePoint.setX( annotationElem.attribute( "offsetX", "0" ).toDouble() ); - mOffsetFromReferencePoint.setY( annotationElem.attribute( "offsetY", "0" ).toDouble() ); - mMapPositionFixed = annotationElem.attribute( "mapPositionFixed", "1" ).toInt(); - setVisible( annotationElem.attribute( "visible", "1" ).toInt() ); - - //marker symbol - QDomElement symbolElem = annotationElem.firstChildElement( "symbol" ); - if ( !symbolElem.isNull() ) - { - QgsMarkerSymbolV2* symbol = dynamic_cast( QgsSymbolLayerV2Utils::loadSymbol( symbolElem ) ); - if ( symbol ) - { - delete mMarkerSymbol; - mMarkerSymbol = symbol; - } - } - - updateBoundingRect(); - updateBalloon(); -} Index: src/gui/CMakeLists.txt =================================================================== --- src/gui/CMakeLists.txt (revision 14229) +++ src/gui/CMakeLists.txt (working copy) @@ -22,7 +22,6 @@ qgisgui.cpp qgisinterface.cpp -qgsannotationitem.cpp qgsattributeeditor.cpp qgslegendinterface.cpp qgscolorbutton.cpp @@ -33,7 +32,6 @@ qgsdetaileditemdata.cpp qgsencodingfiledialog.cpp qgsfiledropedit.cpp -qgsformannotationitem.cpp qgsgenericprojectionselector.cpp qgsmapcanvas.cpp qgsmapcanvasitem.cpp @@ -51,9 +49,12 @@ qgsprojectionselector.cpp qgsquickprint.cpp qgsrubberband.cpp -qgstextannotationitem.cpp qgsvertexmarker.cpp qgsludialog.cpp +mapwidgets/qgsannotationitem.cpp +mapwidgets/qgsformannotationitem.cpp +mapwidgets/qgstextannotationitem.cpp +mapwidgets/qgsscalebarannotationitem.cpp ) SET(QGIS_GUI_MOC_HDRS @@ -84,7 +85,6 @@ qgslegendinterface.h qgisinterface.h qgsencodingfiledialog.h -qgsformannotationitem.h qgsgenericprojectionselector.h qgsmapcanvas.h qgsmapoverviewcanvas.h @@ -96,6 +96,8 @@ qgsludialog.h qgsprojectbadlayerguihandler.h qgslonglongvalidator.h +mapwidgets/qgsformannotationitem.h +mapwidgets/qgsscalebarannotationitem.h ) QT4_WRAP_CPP(QGIS_GUI_MOC_SRCS ${QGIS_GUI_MOC_HDRS}) Index: src/gui/qgsformannotationitem.h =================================================================== --- src/gui/qgsformannotationitem.h (revision 14229) +++ src/gui/qgsformannotationitem.h (working copy) @@ -1,75 +0,0 @@ -/*************************************************************************** - qgsformannotationitem.h - ------------------------ - begin : February 9, 2010 - copyright : (C) 2010 by Marco Hugentobler - email : marco dot hugentobler at hugis dot net - ***************************************************************************/ - -/*************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ - -#ifndef QGSFORMANNOTATIONITEM_H -#define QGSFORMANNOTATIONITEM_H - -#include "qgsannotationitem.h" -#include - -class QGraphicsProxyWidget; - -/**An annotation item that embedds a designer form showing the feature attribute*/ -class GUI_EXPORT QgsFormAnnotationItem: public QObject, public QgsAnnotationItem -{ - Q_OBJECT - public: - QgsFormAnnotationItem( QgsMapCanvas* canvas, QgsVectorLayer* vlayer = 0, bool hasFeature = false, int feature = 0 ); - ~QgsFormAnnotationItem(); - - void paint( QPainter * painter ); - - //! paint function called by map canvas - void paint( QPainter * painter, const QStyleOptionGraphicsItem * option, QWidget * widget = 0 ); - - QSizeF minimumFrameSize() const; - /**Returns the optimal frame size*/ - QSizeF preferredFrameSize() const; - - /**Reimplemented from QgsAnnotationItem*/ - void setMapPosition( const QgsPoint& pos ); - - void setDesignerForm( const QString& uiFile ); - QString designerForm() const { return mDesignerForm; } - - void writeXML( QDomDocument& doc ) const; - void readXML( const QDomDocument& doc, const QDomElement& itemElem ); - - QgsVectorLayer* vectorLayer() const { return mVectorLayer; } - - private slots: - /**Sets a feature for the current map position and updates the dialog*/ - void setFeatureForMapPosition(); - /**Sets visibility status based on mVectorLayer visibility*/ - void updateVisibility(); - - private: - QGraphicsProxyWidget* mWidgetContainer; - QWidget* mDesignerWidget; - /**Associated vectorlayer (or 0 if attributes are not supposed to be replaced)*/ - QgsVectorLayer* mVectorLayer; - /**True if the item is related to a vector feature*/ - bool mHasAssociatedFeature; - /**Associated feature*/ - int mFeature; - /**Path to (and including) the .ui file*/ - QString mDesignerForm; - - QWidget* createDesignerWidget( const QString& filePath ); -}; - -#endif // QGSFORMANNOTATIONITEM_H Index: src/gui/qgsannotationitem.h =================================================================== --- src/gui/qgsannotationitem.h (revision 14229) +++ src/gui/qgsannotationitem.h (working copy) @@ -1,141 +0,0 @@ -/*************************************************************************** - qgsannotationitem.h - ------------------------ - begin : February 9, 2010 - copyright : (C) 2010 by Marco Hugentobler - email : marco dot hugentobler at hugis dot net - ***************************************************************************/ - -/*************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ - -#ifndef QGSANNOTATIONITEM_H -#define QGSANNOTATIONITEM_H - -#include "qgsmapcanvasitem.h" - -class QDomDocument; -class QDomElement; -class QDialog; -class QgsVectorLayer; -class QgsMarkerSymbolV2; - -/**An annotation item can be either placed either on screen corrdinates or on map coordinates. - It may reference a feature and displays that associatiation with a balloon like appearance*/ -class GUI_EXPORT QgsAnnotationItem: public QgsMapCanvasItem -{ - public: - enum MouseMoveAction - { - NoAction, - MoveMapPosition, - MoveFramePosition, - ResizeFrameUp, - ResizeFrameDown, - ResizeFrameLeft, - ResizeFrameRight, - ResizeFrameLeftUp, - ResizeFrameRightUp, - ResizeFrameLeftDown, - ResizeFrameRightDown - }; - - QgsAnnotationItem( QgsMapCanvas* mapCanvas ); - virtual ~QgsAnnotationItem(); - - void updatePosition(); - - QRectF boundingRect() const; - - virtual QSizeF minimumFrameSize() const; - - /**Returns the mouse move behaviour for a given position - @param pos the position in scene coordinates*/ - QgsAnnotationItem::MouseMoveAction moveActionForPosition( const QPointF& pos ) const; - /**Returns suitable cursor shape for mouse move action*/ - Qt::CursorShape cursorShapeForAction( MouseMoveAction moveAction ) const; - - //setters and getters - void setMapPositionFixed( bool fixed ); - bool mapPositionFixed() const { return mMapPositionFixed; } - - virtual void setMapPosition( const QgsPoint& pos ); - QgsPoint mapPosition() const { return mMapPosition; } - - void setFrameSize( const QSizeF& size ); - QSizeF frameSize() const { return mFrameSize; } - - void setOffsetFromReferencePoint( const QPointF& offset ); - QPointF offsetFromReferencePoint() const { return mOffsetFromReferencePoint; } - - /**Set symbol that is drawn on map position. Takes ownership*/ - void setMarkerSymbol( QgsMarkerSymbolV2* symbol ); - const QgsMarkerSymbolV2* markerSymbol() const {return mMarkerSymbol;} - - void setFrameBorderWidth( double w ) { mFrameBorderWidth = w; } - double frameBorderWidth() const { return mFrameBorderWidth; } - - void setFrameColor( const QColor& c ) { mFrameColor = c; } - QColor frameColor() const { return mFrameColor; } - - void setFrameBackgroundColor( const QColor& c ) { mFrameBackgroundColor = c; } - QColor frameBackgroundColor() const { return mFrameBackgroundColor; } - - virtual void writeXML( QDomDocument& doc ) const = 0; - virtual void readXML( const QDomDocument& doc, const QDomElement& itemElem ) = 0; - - void _writeXML( QDomDocument& doc, QDomElement& itemElem ) const; - void _readXML( const QDomDocument& doc, const QDomElement& annotationElem ); - - protected: - /**True: the item stays at the same map position, False: the item stays on same screen position*/ - bool mMapPositionFixed; - /**Map position (in case mMapPositionFixed is true)*/ - QgsPoint mMapPosition; - /**Describes the shift of the item content box to the reference point*/ - QPointF mOffsetFromReferencePoint; - - /**Size of the frame (without balloon)*/ - QSizeF mFrameSize; - /**Bounding rect (including item frame and balloon)*/ - QRectF mBoundingRect; - - /**Point symbol that is to be drawn at the map reference location*/ - QgsMarkerSymbolV2* mMarkerSymbol; - /**Width of the frame*/ - double mFrameBorderWidth; - /**Frame / balloon color*/ - QColor mFrameColor; - QColor mFrameBackgroundColor; - - /**Segment number where the connection to the map point is attached. -1 if no balloon needed (e.g. if point is contained in frame)*/ - int mBalloonSegment; - /**First segment point for drawing the connection (ccw direction)*/ - QPointF mBalloonSegmentPoint1; - /**Second segment point for drawing the balloon connection (ccw direction)*/ - QPointF mBalloonSegmentPoint2; - - void updateBoundingRect(); - /**Check where to attach the balloon connection between frame and map point*/ - void updateBalloon(); - - void drawFrame( QPainter* p ); - void drawMarkerSymbol( QPainter* p ); - void drawSelectionBoxes( QPainter* p ); - /**Returns frame width in painter units*/ - //double scaledFrameWidth( QPainter* p) const; - /**Gets the frame line (0 is the top line, 1 right, 2 bottom, 3 left)*/ - QLineF segment( int index ); - /**Returns a point on the line from startPoint to directionPoint that is a certain distance away from the starting point*/ - QPointF pointOnLineWithDistance( const QPointF& startPoint, const QPointF& directionPoint, double distance ) const; - /**Returns the symbol size scaled in (mapcanvas) pixels. Used for the counding rect calculation*/ - double scaledSymbolSize() const; -}; - -#endif // QGSANNOTATIONITEM_H Index: src/gui/qgstextannotationitem.h =================================================================== --- src/gui/qgstextannotationitem.h (revision 14229) +++ src/gui/qgstextannotationitem.h (working copy) @@ -1,45 +0,0 @@ -/*************************************************************************** - qgstextannotationitem.h - ------------------------ - begin : February 9, 2010 - copyright : (C) 2010 by Marco Hugentobler - email : marco dot hugentobler at hugis dot net - ***************************************************************************/ - -/*************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ - -#ifndef QGSTEXTANNOTATIONITEM_H -#define QGSTEXTANNOTATIONITEM_H - -#include "qgsannotationitem.h" -#include - -/**An annotation item that displays formated text*/ -class GUI_EXPORT QgsTextAnnotationItem: public QgsAnnotationItem -{ - public: - QgsTextAnnotationItem( QgsMapCanvas* canvas ); - ~QgsTextAnnotationItem(); - - /**Returns document (caller takes ownership)*/ - QTextDocument* document() const; - /**Sets document (does not take ownership)*/ - void setDocument( const QTextDocument* doc ); - - void writeXML( QDomDocument& doc ) const; - void readXML( const QDomDocument& doc, const QDomElement& itemElem ); - - void paint( QPainter* painter ); - - private: - QTextDocument* mDocument; -}; - -#endif // QGSTEXTANNOTATIONITEM_H