diff --git a/python/gui/qgsmaptool.sip b/python/gui/qgsmaptool.sip index ea5fd85c01e..46888d1db68 100644 --- a/python/gui/qgsmaptool.sip +++ b/python/gui/qgsmaptool.sip @@ -1,5 +1,5 @@ -class QgsMapTool +class QgsMapTool : QObject { %TypeHeaderCode #include @@ -54,7 +54,7 @@ class QgsMapTool protected: //! constructor takes map canvas as a parameter - QgsMapTool(QgsMapCanvas* canvas); + QgsMapTool(QgsMapCanvas* canvas /TransferThis/); //! transformation from screen coordinates to map coordinates QgsPoint toMapCoords(const QPoint& point); diff --git a/src/app/CMakeLists.txt b/src/app/CMakeLists.txt index c5084289daa..531225ff5b9 100644 --- a/src/app/CMakeLists.txt +++ b/src/app/CMakeLists.txt @@ -31,7 +31,8 @@ qgsmaptoolidentify.cpp qgsmaptoolselect.cpp qgsmaptoolvertexedit.cpp qgsmarkerdialog.cpp -qgsmeasure.cpp +qgsmeasuredialog.cpp +qgsmeasuretool.cpp qgsnewhttpconnection.cpp qgsnumericsortlistviewitem.cpp qgsoptions.cpp @@ -100,7 +101,7 @@ qgsludialog.h qgsmaplayerinterface.h qgsmaptoolidentify.h qgsmarkerdialog.h -qgsmeasure.h +qgsmeasuredialog.h qgsnewhttpconnection.h qgsoptions.h qgspastetransformations.h diff --git a/src/app/qgisapp.cpp b/src/app/qgisapp.cpp index d4ef7978730..8a4fe26c938 100644 --- a/src/app/qgisapp.cpp +++ b/src/app/qgisapp.cpp @@ -150,7 +150,7 @@ #include "qgsmaptoolselect.h" #include "qgsmaptoolvertexedit.h" #include "qgsmaptoolzoom.h" -#include "qgsmeasure.h" +#include "qgsmeasuretool.h" // // Conditional Includes @@ -1203,9 +1203,9 @@ void QgisApp::createCanvas() mMapTools.mPan->setAction(mActionPan); mMapTools.mIdentify = new QgsMapToolIdentify(mMapCanvas); mMapTools.mIdentify->setAction(mActionIdentify); - mMapTools.mMeasureDist = new QgsMeasure(FALSE /* area */, mMapCanvas); + mMapTools.mMeasureDist = new QgsMeasureTool(mMapCanvas, FALSE /* area */); mMapTools.mMeasureDist->setAction(mActionMeasure); - mMapTools.mMeasureArea = new QgsMeasure(TRUE /* area */, mMapCanvas); + mMapTools.mMeasureArea = new QgsMeasureTool(mMapCanvas, TRUE /* area */); mMapTools.mMeasureArea->setAction(mActionMeasureArea); mMapTools.mCapturePoint = new QgsMapToolCapture(mMapCanvas, QgsMapToolCapture::CapturePoint); mMapTools.mCapturePoint->setAction(mActionCapturePoint); diff --git a/src/app/qgsmaptoolidentify.h b/src/app/qgsmaptoolidentify.h index a6246b753fc..1dd8a02623f 100644 --- a/src/app/qgsmaptoolidentify.h +++ b/src/app/qgsmaptoolidentify.h @@ -37,7 +37,7 @@ class QgsVectorLayer; - for vector layers shows feature attributes within search radius (allows to edit values when vector layer is in editing mode) */ -class QgsMapToolIdentify : public QObject, public QgsMapTool +class QgsMapToolIdentify : public QgsMapTool { Q_OBJECT; diff --git a/src/app/qgsmeasure.cpp b/src/app/qgsmeasure.cpp deleted file mode 100644 index 003074f401b..00000000000 --- a/src/app/qgsmeasure.cpp +++ /dev/null @@ -1,406 +0,0 @@ -/*************************************************************************** - qgsmeasure.h - ------------------ - begin : March 2005 - copyright : (C) 2005 by Radim Blazek - email : blazek@itc.it - ***************************************************************************/ -/*************************************************************************** - * * - * 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. * - * * - ***************************************************************************/ -/* $Id$ */ - -#include "qgsmeasure.h" - -#include "qgscontexthelp.h" -#include "qgsdistancearea.h" -#include "qgsmapcanvas.h" -#include "qgsmaprender.h" -#include "qgsmaptopixel.h" -#include "qgsrubberband.h" -#include "qgsspatialrefsys.h" - -#include "QMessageBox" -#include -#include -#include - - -QgsMeasure::QgsMeasure(bool measureArea, QgsMapCanvas *mc, Qt::WFlags f) - : QDialog(mc->topLevelWidget(), f), QgsMapTool(mc) -{ - setupUi(this); -#ifdef Q_WS_MAC - // Mac buttons are larger than X11 and require a larger minimum width to be drawn correctly - frame4->setMinimumSize(QSize(224, 0)); -#endif - connect(mRestartButton, SIGNAL(clicked()), this, SLOT(restart())); - connect(mCloseButton, SIGNAL(clicked()), this, SLOT(close())); - - mMeasureArea = measureArea; - mMapCanvas = mc; - mTotal = 0.; - - mTable->setLeftMargin(0); // hide row labels - - // Set one cell row where to update current distance - // If measuring area, the table doesn't get shown - mTable->setNumRows(1); - mTable->setText(0, 0, QString::number(0, 'f',1)); - - //mTable->horizontalHeader()->setLabel( 0, tr("Segments (in meters)") ); - //mTable->horizontalHeader()->setLabel( 1, tr("Total") ); - //mTable->horizontalHeader()->setLabel( 2, tr("Azimuth") ); - - mTable->setColumnStretchable ( 0, true ); - //mTable->setColumnStretchable ( 1, true ); - //mTable->setColumnStretchable ( 2, true ); - - updateUi(); - - connect( mMapCanvas, SIGNAL(renderComplete(QPainter*)), this, SLOT(mapCanvasChanged()) ); - - //mCalc = new QgsDistanceArea; - - mRubberBand = new QgsRubberBand(mMapCanvas, mMeasureArea); - - mCanvas->setCursor(Qt::CrossCursor); - - mRightMouseClicked = false; -} - -void QgsMeasure::activate() -{ - restorePosition(); - QgsMapTool::activate(); - mRightMouseClicked = false; - - // ensure that we have correct settings - updateProjection(); - - // If we suspect that they have data that is projected, yet the - // map SRS is set to a geographic one, warn them. - if (mCanvas->mapRender()->distArea()->geographic() && - (mMapCanvas->extent().height() > 360 || - mMapCanvas->extent().width() > 720)) - { - QMessageBox::warning(this, tr("Incorrect measure results"), - tr("

This map is defined with a geographic coordinate system " - "(latitude/longitude) " - "but the map extents suggest that it is actually a projected " - "coordinate system (e.g., Mercator). " - "If so, the results from line or area measurements will be " - "incorrect.

" - "

To fix this, explicitly set an appropriate map coordinate " - "system using the Settings:Project Properties menu.")); - mWrongProjectProjection = true; - } -} - -void QgsMeasure::deactivate() -{ - close(); - QgsMapTool::deactivate(); -} - - -void QgsMeasure::setMeasureArea(bool measureArea) -{ - saveWindowLocation(); - mMeasureArea = measureArea; - restart(); - restorePosition(); -} - - -QgsMeasure::~QgsMeasure() -{ -// delete mCalc; - delete mRubberBand; -} - -void QgsMeasure::restart(void ) -{ - updateProjection(); - mPoints.clear(); - // Set one cell row where to update current distance - // If measuring area, the table doesn't get shown - mTable->setNumRows(1); - mTable->setText(0, 0, QString::number(0, 'f',1)); - mTotal = 0.; - - updateUi(); - - mRubberBand->reset(mMeasureArea); - - // re-read color settings - QSettings settings; - int myRed = settings.value("/qgis/default_measure_color_red", 180).toInt(); - int myGreen = settings.value("/qgis/default_measure_color_green", 180).toInt(); - int myBlue = settings.value("/qgis/default_measure_color_blue", 180).toInt(); - mRubberBand->setColor(QColor(myRed, myGreen, myBlue)); - - mRightMouseClicked = false; - mWrongProjectProjection = false; -} - -void QgsMeasure::addPoint(QgsPoint &point) -{ -#ifdef QGISDEBUG - std::cout << "QgsMeasure::addPoint" << point.x() << ", " << point.y() << std::endl; -#endif - - if (mWrongProjectProjection) - { - updateProjection(); - mWrongProjectProjection = false; - } - - // don't add points with the same coordinates - if (mPoints.size() > 0 && point == mPoints[0]) - return; - - QgsPoint pnt(point); - mPoints.append(pnt); - - if (mMeasureArea && mPoints.size() > 2) - { - double area = mCanvas->mapRender()->distArea()->measurePolygon(mPoints); - editTotal->setText(formatArea(area)); - } - else if (!mMeasureArea && mPoints.size() > 1) - { - int last = mPoints.size()-2; - - QgsPoint p1 = mPoints[last], p2 = mPoints[last+1]; - - double d = mCanvas->mapRender()->distArea()->measureLine(p1,p2); - - mTotal += d; - editTotal->setText(formatDistance(mTotal)); - - - int row = mPoints.size()-2; - mTable->setText(row, 0, QLocale::system().toString(d, 'f', 2)); - mTable->setNumRows ( mPoints.size() ); - - mTable->setText(row + 1, 0, QLocale::system().toString(0.0, 'f', 2)); - mTable->ensureCellVisible(row + 1,0); - } - - mRubberBand->addPoint(point); -} - -void QgsMeasure::mousePress(QgsPoint &point) -{ - if (mPoints.size() == 0) - { - addPoint(point); - this->show(); - } - raise(); - - mouseMove(point); -} - -void QgsMeasure::mouseMove(QgsPoint &point) -{ -#ifdef QGISDEBUG - //std::cout << "QgsMeasure::mouseMove" << point.x() << ", " << point.y() << std::endl; -#endif - - mRubberBand->movePoint(point); - - // show current distance/area while moving the point - // by creating a temporary copy of point array - // and adding moving point at the end - QList tmpPoints = mPoints; - tmpPoints.append(point); - if (mMeasureArea && tmpPoints.size() > 2) - { - double area = mCanvas->mapRender()->distArea()->measurePolygon(tmpPoints); - editTotal->setText(formatArea(area)); - } - else if (!mMeasureArea && tmpPoints.size() > 1) - { - int last = tmpPoints.size()-2; - QgsPoint p1 = tmpPoints[last], p2 = tmpPoints[last+1]; - - double d = mCanvas->mapRender()->distArea()->measureLine(p1,p2); - //mTable->setText(last, 0, QString::number(d, 'f',1)); - mTable->setText(last, 0, QLocale::system().toString(d, 'f', 2)); - editTotal->setText(formatDistance(mTotal + d)); - } -} - -void QgsMeasure::mapCanvasChanged() -{ -} - -void QgsMeasure::close(void) -{ - restart(); - saveWindowLocation(); - hide(); -} - -void QgsMeasure::closeEvent(QCloseEvent *e) -{ - saveWindowLocation(); - e->accept(); -} - -void QgsMeasure::restorePosition() -{ - QSettings settings; - int ww = settings.readNumEntry("/Windows/Measure/w", 150); - int wh; - if (mMeasureArea) - wh = settings.readNumEntry("/Windows/Measure/hNoTable", 70); - else - wh = settings.readNumEntry("/Windows/Measure/h", 200); - int wx = settings.readNumEntry("/Windows/Measure/x", 100); - int wy = settings.readNumEntry("/Windows/Measure/y", 100); -// setUpdatesEnabled(false); - adjustSize(); - resize(ww,wh); - move(wx,wy); -// setUpdatesEnabled(true); - this->show(); -} - -void QgsMeasure::saveWindowLocation() -{ - QSettings settings; - QPoint p = this->pos(); - QSize s = this->size(); - settings.writeEntry("/Windows/Measure/x", p.x()); - settings.writeEntry("/Windows/Measure/y", p.y()); - settings.writeEntry("/Windows/Measure/w", s.width()); - if (mMeasureArea) - settings.writeEntry("/Windows/Measure/hNoTable", s.height()); - else - settings.writeEntry("/Windows/Measure/h", s.height()); -} - -void QgsMeasure::on_btnHelp_clicked() -{ - QgsContextHelp::run(context_id); -} - - -QString QgsMeasure::formatDistance(double distance) -{ - QString txt; - QString unitLabel; - - QGis::units myMapUnits = mCanvas->mapUnits(); - return QgsDistanceArea::textUnit(distance, 2, myMapUnits, false); -} - -QString QgsMeasure::formatArea(double area) -{ - QGis::units myMapUnits = mCanvas->mapUnits(); - return QgsDistanceArea::textUnit(area, 2, myMapUnits, true); -} - -void QgsMeasure::updateUi() -{ - - QGis::units myMapUnits = mCanvas->mapUnits(); - switch (myMapUnits) - { - case QGis::METERS: - mTable->horizontalHeader()->setLabel( 0, tr("Segments (in meters)") ); - break; - case QGis::FEET: - mTable->horizontalHeader()->setLabel( 0, tr("Segments (in feet)") ); - break; - case QGis::DEGREES: - mTable->horizontalHeader()->setLabel( 0, tr("Segments (in degrees)") ); - break; - case QGis::UNKNOWN: - mTable->horizontalHeader()->setLabel( 0, tr("Segments") ); - }; - - if (mMeasureArea) - { - mTable->hide(); - editTotal->setText(formatArea(0)); - } - else - { - mTable->show(); - editTotal->setText(formatDistance(0)); - } - -} - -void QgsMeasure::updateProjection() -{ - // set ellipsoid - QSettings settings; - // QString ellipsoid = settings.readEntry("/qgis/measure/ellipsoid", "WGS84"); - // mCalc->setEllipsoid(ellipsoid); - - // set source SRS and projections enabled flag - // QgsMapRender* mapRender = mCanvas->mapRender(); - // mCalc->setProjectionsEnabled(mapRender->projectionsEnabled()); - // int srsid = mapRender->destinationSrs().srsid(); - // mCalc->setSourceSRS(srsid); - - int myRed = settings.value("/qgis/default_measure_color_red", 180).toInt(); - int myGreen = settings.value("/qgis/default_measure_color_green", 180).toInt(); - int myBlue = settings.value("/qgis/default_measure_color_blue", 180).toInt(); - mRubberBand->setColor(QColor(myRed, myGreen, myBlue)); - -} - -////////////////////////// - -void QgsMeasure::canvasPressEvent(QMouseEvent * e) -{ - if (e->button() == Qt::LeftButton) - { - if (mRightMouseClicked) - restart(); - - QgsPoint idPoint = mCanvas->getCoordinateTransform()->toMapCoordinates(e->x(), e->y()); - mousePress(idPoint); - } -} - - -void QgsMeasure::canvasMoveEvent(QMouseEvent * e) -{ - if (!mRightMouseClicked) - { - QgsPoint point = mCanvas->getCoordinateTransform()->toMapCoordinates(e->pos().x(), e->pos().y()); - mouseMove(point); - } -} - - -void QgsMeasure::canvasReleaseEvent(QMouseEvent * e) -{ - QgsPoint point = mCanvas->getCoordinateTransform()->toMapCoordinates(e->x(), e->y()); - - if(e->button() == Qt::RightButton && (e->state() & Qt::LeftButton) == 0) // restart - { - if (mRightMouseClicked) - restart(); - else - mRightMouseClicked = true; - } - else if (e->button() == Qt::LeftButton) - { - addPoint(point); - show(); - } - -} diff --git a/src/app/qgsmeasuredialog.cpp b/src/app/qgsmeasuredialog.cpp new file mode 100644 index 00000000000..89990ab487a --- /dev/null +++ b/src/app/qgsmeasuredialog.cpp @@ -0,0 +1,242 @@ +/*************************************************************************** + qgsmeasure.h + ------------------ + begin : March 2005 + copyright : (C) 2005 by Radim Blazek + email : blazek@itc.it + ***************************************************************************/ +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ +/* $Id$ */ + +#include "qgsmeasuredialog.h" +#include "qgsmeasuretool.h" + +#include "qgscontexthelp.h" +#include "qgsdistancearea.h" +#include "qgsmapcanvas.h" +#include "qgsmaprender.h" +#include "qgsspatialrefsys.h" + +#include +#include + + +QgsMeasureDialog::QgsMeasureDialog(QgsMeasureTool* tool, Qt::WFlags f) + : QDialog(tool->canvas()->topLevelWidget(), f), mTool(tool) +{ + setupUi(this); +#ifdef Q_WS_MAC + // Mac buttons are larger than X11 and require a larger minimum width to be drawn correctly + frame4->setMinimumSize(QSize(224, 0)); +#endif + connect(mRestartButton, SIGNAL(clicked()), this, SLOT(restart())); + connect(mCloseButton, SIGNAL(clicked()), this, SLOT(close())); + + mMeasureArea = tool->measureArea(); + mTotal = 0.; + + mTable->setLeftMargin(0); // hide row labels + + // Set one cell row where to update current distance + // If measuring area, the table doesn't get shown + mTable->setNumRows(1); + mTable->setText(0, 0, QString::number(0, 'f',1)); + + //mTable->horizontalHeader()->setLabel( 0, tr("Segments (in meters)") ); + //mTable->horizontalHeader()->setLabel( 1, tr("Total") ); + //mTable->horizontalHeader()->setLabel( 2, tr("Azimuth") ); + + mTable->setColumnStretchable ( 0, true ); + //mTable->setColumnStretchable ( 1, true ); + //mTable->setColumnStretchable ( 2, true ); + + updateUi(); +} + + +void QgsMeasureDialog::restart() +{ + mTool->restart(); + + // Set one cell row where to update current distance + // If measuring area, the table doesn't get shown + mTable->setNumRows(1); + mTable->setText(0, 0, QString::number(0, 'f',1)); + mTotal = 0.; + + updateUi(); +} + + +void QgsMeasureDialog::mousePress(QgsPoint &point) +{ + if (mTool->points().size() == 0) + { + addPoint(point); + this->show(); + } + raise(); + + mouseMove(point); +} + +void QgsMeasureDialog::mouseMove(QgsPoint &point) +{ + // show current distance/area while moving the point + // by creating a temporary copy of point array + // and adding moving point at the end + QList tmpPoints = mTool->points(); + tmpPoints.append(point); + if (mMeasureArea && tmpPoints.size() > 2) + { + double area = mTool->canvas()->mapRender()->distArea()->measurePolygon(tmpPoints); + editTotal->setText(formatArea(area)); + } + else if (!mMeasureArea && tmpPoints.size() > 1) + { + int last = tmpPoints.size()-2; + QgsPoint p1 = tmpPoints[last], p2 = tmpPoints[last+1]; + + double d = mTool->canvas()->mapRender()->distArea()->measureLine(p1,p2); + //mTable->setText(last, 0, QString::number(d, 'f',1)); + mTable->setText(last, 0, QLocale::system().toString(d, 'f', 2)); + editTotal->setText(formatDistance(mTotal + d)); + } +} + +void QgsMeasureDialog::addPoint(QgsPoint &point) +{ + int numPoints = mTool->points().size(); + if (mMeasureArea && numPoints > 2) + { + double area = mTool->canvas()->mapRender()->distArea()->measurePolygon(mTool->points()); + editTotal->setText(formatArea(area)); + } + else if (!mMeasureArea && numPoints > 1) + { + int last = numPoints-2; + + QgsPoint p1 = mTool->points()[last], p2 = mTool->points()[last+1]; + + double d = mTool->canvas()->mapRender()->distArea()->measureLine(p1,p2); + + mTotal += d; + editTotal->setText(formatDistance(mTotal)); + + + int row = numPoints-2; + mTable->setText(row, 0, QLocale::system().toString(d, 'f', 2)); + mTable->setNumRows ( numPoints ); + + mTable->setText(row + 1, 0, QLocale::system().toString(0.0, 'f', 2)); + mTable->ensureCellVisible(row + 1,0); + } +} + + +void QgsMeasureDialog::close(void) +{ + restart(); + saveWindowLocation(); + hide(); +} + +void QgsMeasureDialog::closeEvent(QCloseEvent *e) +{ + saveWindowLocation(); + e->accept(); +} + +void QgsMeasureDialog::restorePosition() +{ + QSettings settings; + int ww = settings.readNumEntry("/Windows/Measure/w", 150); + int wh; + if (mMeasureArea) + wh = settings.readNumEntry("/Windows/Measure/hNoTable", 70); + else + wh = settings.readNumEntry("/Windows/Measure/h", 200); + int wx = settings.readNumEntry("/Windows/Measure/x", 100); + int wy = settings.readNumEntry("/Windows/Measure/y", 100); +// setUpdatesEnabled(false); + adjustSize(); + resize(ww,wh); + move(wx,wy); +// setUpdatesEnabled(true); + this->show(); +} + +void QgsMeasureDialog::saveWindowLocation() +{ + QSettings settings; + QPoint p = this->pos(); + QSize s = this->size(); + settings.writeEntry("/Windows/Measure/x", p.x()); + settings.writeEntry("/Windows/Measure/y", p.y()); + settings.writeEntry("/Windows/Measure/w", s.width()); + if (mMeasureArea) + settings.writeEntry("/Windows/Measure/hNoTable", s.height()); + else + settings.writeEntry("/Windows/Measure/h", s.height()); +} + +void QgsMeasureDialog::on_btnHelp_clicked() +{ + QgsContextHelp::run(context_id); +} + + +QString QgsMeasureDialog::formatDistance(double distance) +{ + QString txt; + QString unitLabel; + + QGis::units myMapUnits = mTool->canvas()->mapUnits(); + return QgsDistanceArea::textUnit(distance, 2, myMapUnits, false); +} + +QString QgsMeasureDialog::formatArea(double area) +{ + QGis::units myMapUnits = mTool->canvas()->mapUnits(); + return QgsDistanceArea::textUnit(area, 2, myMapUnits, true); +} + +void QgsMeasureDialog::updateUi() +{ + + QGis::units myMapUnits = mTool->canvas()->mapUnits(); + switch (myMapUnits) + { + case QGis::METERS: + mTable->horizontalHeader()->setLabel( 0, tr("Segments (in meters)") ); + break; + case QGis::FEET: + mTable->horizontalHeader()->setLabel( 0, tr("Segments (in feet)") ); + break; + case QGis::DEGREES: + mTable->horizontalHeader()->setLabel( 0, tr("Segments (in degrees)") ); + break; + case QGis::UNKNOWN: + mTable->horizontalHeader()->setLabel( 0, tr("Segments") ); + }; + + if (mMeasureArea) + { + mTable->hide(); + editTotal->setText(formatArea(0)); + } + else + { + mTable->show(); + editTotal->setText(formatDistance(0)); + } + +} + diff --git a/src/app/qgsmeasure.h b/src/app/qgsmeasuredialog.h similarity index 57% rename from src/app/qgsmeasure.h rename to src/app/qgsmeasuredialog.h index 1246bd52e92..c81278fa52d 100644 --- a/src/app/qgsmeasure.h +++ b/src/app/qgsmeasuredialog.h @@ -13,30 +13,25 @@ * (at your option) any later version. * * * ***************************************************************************/ -#ifndef QGSMEASURE_H -#define QGSMEASURE_H + +#ifndef QGSMEASUREDIALOG_H +#define QGSMEASUREDIALOG_H #include "ui_qgsmeasurebase.h" -#include -#include "qgsmaptool.h" + #include "qgspoint.h" -class QgsDistanceArea; -class QgsMapCanvas; -class QgsRubberBand; - class QCloseEvent; +class QgsMeasureTool; - -class QgsMeasure:public QDialog, public QgsMapTool, private Ui::QgsMeasureBase +class QgsMeasureDialog : public QDialog, private Ui::QgsMeasureBase { Q_OBJECT; - public: + +public: //! Constructor - QgsMeasure(bool measureArea, QgsMapCanvas *mc, Qt::WFlags f = 0); - - ~QgsMeasure(); + QgsMeasureDialog(QgsMeasureTool* tool, Qt::WFlags f = 0); //! Save position void saveWindowLocation(void); @@ -53,43 +48,16 @@ class QgsMeasure:public QDialog, public QgsMapTool, private Ui::QgsMeasureBase //! Mouse press void mousePress(QgsPoint &point); - //! returns whether measuring distance or area - bool measureArea() { return mMeasureArea; } - //! sets whether we're measuring area (and restarts) - void setMeasureArea(bool measureArea); - -public: - - // Inherited from QgsMapTool - - //! Mouse move event for overriding - virtual void canvasMoveEvent(QMouseEvent * e); - - //! Mouse press event for overriding - virtual void canvasPressEvent(QMouseEvent * e); - - //! Mouse release event for overriding - virtual void canvasReleaseEvent(QMouseEvent * e); - - //! called when set as currently active map tool - virtual void activate(); - - //! called when map tool is being deactivated - virtual void deactivate(); - public slots: //! Close void close ( void); //! Reset and start new - void restart ( void); + void restart (); //! Close event void closeEvent(QCloseEvent *e); - //! Redraw lines to match current state of canvas - void mapCanvasChanged(); - //! Show the help for the dialog void on_btnHelp_clicked(); @@ -104,33 +72,16 @@ private: //! shows/hides table, shows correct units void updateUi(); - //! updates the projections we're using - void updateProjection(); - - QgsMapCanvas *mMapCanvas; - - //! distance/area calculator - //QgsDistanceArea* mCalc; - - QList mPoints; - double mTotal; - //! Rubberband widget tracking the lines being drawn - QgsRubberBand *mRubberBand; - //! Help context id static const int context_id = 687883780; //! indicates whether we're measuring distances or areas bool mMeasureArea; - //! indicates whether we've just done a right mouse click - bool mRightMouseClicked; - - //! indicates whether we've recently warned the user about having the wrong - // project projection - bool mWrongProjectProjection; + //! pointer to measure tool which owns this dialog + QgsMeasureTool* mTool; }; #endif diff --git a/src/app/qgsmeasuretool.cpp b/src/app/qgsmeasuretool.cpp new file mode 100644 index 00000000000..3da205a7d85 --- /dev/null +++ b/src/app/qgsmeasuretool.cpp @@ -0,0 +1,200 @@ +/*************************************************************************** + qgsmeasuretool.cpp - map tool for measuring distances and areas + --------------------- + begin : April 2007 + copyright : (C) 2007 by Martin Dobias + email : wonder.sk at gmail dot 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. * + * * + ***************************************************************************/ +/* $Id$ */ + +#include "qgsdistancearea.h" +#include "qgslogger.h" +#include "qgsmapcanvas.h" +#include "qgsmaprender.h" +#include "qgsmaptopixel.h" +#include "qgsrubberband.h" + +#include "qgsmeasuredialog.h" +#include "qgsmeasuretool.h" + +#include +#include + +QgsMeasureTool::QgsMeasureTool(QgsMapCanvas* canvas, bool measureArea) + : QgsMapTool(canvas) +{ + mMeasureArea = measureArea; + + mRubberBand = new QgsRubberBand(canvas, mMeasureArea); + + mCanvas->setCursor(Qt::CrossCursor); + + mRightMouseClicked = false; + + mDialog = new QgsMeasureDialog(this); +} + +QgsMeasureTool::~QgsMeasureTool() +{ + delete mRubberBand; +} + + +const QList& QgsMeasureTool::points() +{ + return mPoints; +} + + +void QgsMeasureTool::activate() +{ + mDialog->restorePosition(); + QgsMapTool::activate(); + mRightMouseClicked = false; + + // ensure that we have correct settings + updateProjection(); + + // If we suspect that they have data that is projected, yet the + // map SRS is set to a geographic one, warn them. + if (mCanvas->mapRender()->distArea()->geographic() && + (mCanvas->extent().height() > 360 || + mCanvas->extent().width() > 720)) + { + QMessageBox::warning(NULL, tr("Incorrect measure results"), + tr("

This map is defined with a geographic coordinate system " + "(latitude/longitude) " + "but the map extents suggest that it is actually a projected " + "coordinate system (e.g., Mercator). " + "If so, the results from line or area measurements will be " + "incorrect.

" + "

To fix this, explicitly set an appropriate map coordinate " + "system using the Settings:Project Properties menu.")); + mWrongProjectProjection = true; + } +} + +void QgsMeasureTool::deactivate() +{ + mDialog->close(); + QgsMapTool::deactivate(); +} + + +void QgsMeasureTool::restart() +{ + updateProjection(); + mPoints.clear(); + + mRubberBand->reset(mMeasureArea); + + // re-read color settings + QSettings settings; + int myRed = settings.value("/qgis/default_measure_color_red", 180).toInt(); + int myGreen = settings.value("/qgis/default_measure_color_green", 180).toInt(); + int myBlue = settings.value("/qgis/default_measure_color_blue", 180).toInt(); + mRubberBand->setColor(QColor(myRed, myGreen, myBlue)); + + mRightMouseClicked = false; + mWrongProjectProjection = false; + +} + + + + + +void QgsMeasureTool::updateProjection() +{ + // set ellipsoid + QSettings settings; + // QString ellipsoid = settings.readEntry("/qgis/measure/ellipsoid", "WGS84"); + // mCalc->setEllipsoid(ellipsoid); + + // set source SRS and projections enabled flag + // QgsMapRender* mapRender = mCanvas->mapRender(); + // mCalc->setProjectionsEnabled(mapRender->projectionsEnabled()); + // int srsid = mapRender->destinationSrs().srsid(); + // mCalc->setSourceSRS(srsid); + + int myRed = settings.value("/qgis/default_measure_color_red", 180).toInt(); + int myGreen = settings.value("/qgis/default_measure_color_green", 180).toInt(); + int myBlue = settings.value("/qgis/default_measure_color_blue", 180).toInt(); + mRubberBand->setColor(QColor(myRed, myGreen, myBlue)); + +} + +////////////////////////// + +void QgsMeasureTool::canvasPressEvent(QMouseEvent * e) +{ + if (e->button() == Qt::LeftButton) + { + if (mRightMouseClicked) + mDialog->restart(); + + QgsPoint idPoint = mCanvas->getCoordinateTransform()->toMapCoordinates(e->x(), e->y()); + mDialog->mousePress(idPoint); + } +} + + +void QgsMeasureTool::canvasMoveEvent(QMouseEvent * e) +{ + if (!mRightMouseClicked) + { + QgsPoint point = mCanvas->getCoordinateTransform()->toMapCoordinates(e->pos().x(), e->pos().y()); + mRubberBand->movePoint(point); + mDialog->mouseMove(point); + } +} + + +void QgsMeasureTool::canvasReleaseEvent(QMouseEvent * e) +{ + QgsPoint point = mCanvas->getCoordinateTransform()->toMapCoordinates(e->x(), e->y()); + + if(e->button() == Qt::RightButton && (e->state() & Qt::LeftButton) == 0) // restart + { + if (mRightMouseClicked) + mDialog->restart(); + else + mRightMouseClicked = true; + } + else if (e->button() == Qt::LeftButton) + { + addPoint(point); + mDialog->show(); + } + +} + + +void QgsMeasureTool::addPoint(QgsPoint &point) +{ + QgsDebugMsg( QString::number(point.x()) + ", " + QString::number(point.y())); + + if (mWrongProjectProjection) + { + updateProjection(); + mWrongProjectProjection = false; + } + + // don't add points with the same coordinates + if (mPoints.size() > 0 && point == mPoints[0]) + return; + + QgsPoint pnt(point); + mPoints.append(pnt); + + + mRubberBand->addPoint(point); + mDialog->addPoint(point); +} diff --git a/src/app/qgsmeasuretool.h b/src/app/qgsmeasuretool.h new file mode 100644 index 00000000000..6f0039866f1 --- /dev/null +++ b/src/app/qgsmeasuretool.h @@ -0,0 +1,92 @@ +/*************************************************************************** + qgsmeasuretool.h - map tool for measuring distances and areas + --------------------- + begin : April 2007 + copyright : (C) 2007 by Martin Dobias + email : wonder.sk at gmail dot 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. * + * * + ***************************************************************************/ +/* $Id$ */ + + +#ifndef QGSMEASURETOOL_H +#define QGSMEASURETOOL_H + +#include "qgsmaptool.h" + +class QgsDistanceArea; +class QgsMapCanvas; +class QgsMeasureDialog; +class QgsRubberBand; + + + +class QgsMeasureTool : public QgsMapTool +{ + +public: + + QgsMeasureTool(QgsMapCanvas* canvas, bool measureArea); + + ~QgsMeasureTool(); + + //! returns whether measuring distance or area + bool measureArea() { return mMeasureArea; } + + //! Reset and start new + void restart (); + + //! Add new point + void addPoint(QgsPoint &point); + + //! Returns reference to array of the points + const QList& points(); + + // Inherited from QgsMapTool + + //! Mouse move event for overriding + virtual void canvasMoveEvent(QMouseEvent * e); + + //! Mouse press event for overriding + virtual void canvasPressEvent(QMouseEvent * e); + + //! Mouse release event for overriding + virtual void canvasReleaseEvent(QMouseEvent * e); + + //! called when set as currently active map tool + virtual void activate(); + + //! called when map tool is being deactivated + virtual void deactivate(); + +protected: + + //! updates the projections we're using + void updateProjection(); + + QList mPoints; + + QgsMeasureDialog* mDialog; + + //! Rubberband widget tracking the lines being drawn + QgsRubberBand *mRubberBand; + + //! indicates whether we're measuring distances or areas + bool mMeasureArea; + + //! indicates whether we've just done a right mouse click + bool mRightMouseClicked; + + //! indicates whether we've recently warned the user about having the wrong + // project projection + bool mWrongProjectProjection; + +}; + +#endif diff --git a/src/gui/qgsmapcanvas.h b/src/gui/qgsmapcanvas.h index 60956976e26..8cd23e0eda1 100644 --- a/src/gui/qgsmapcanvas.h +++ b/src/gui/qgsmapcanvas.h @@ -48,7 +48,6 @@ class QgsMapLayer; class QgsMapLayerInterface; class QgsLegend; class QgsLegendView; -class QgsMeasure; class QgsRubberBand; class QgsMapRender; diff --git a/src/gui/qgsmaptool.cpp b/src/gui/qgsmaptool.cpp index 23eec1ed4e1..240cb0437aa 100644 --- a/src/gui/qgsmaptool.cpp +++ b/src/gui/qgsmaptool.cpp @@ -22,7 +22,7 @@ #include QgsMapTool::QgsMapTool(QgsMapCanvas* canvas) - : mCanvas(canvas), mCursor(Qt::CrossCursor), mAction(NULL) + : QObject(canvas), mCanvas(canvas), mCursor(Qt::CrossCursor), mAction(NULL) { } @@ -80,3 +80,39 @@ void QgsMapTool::deactivate() if (mAction) mAction->setChecked(false); } + +void QgsMapTool::setAction(QAction* action) +{ + mAction = action; +} + +QAction* QgsMapTool::action() +{ + return mAction; +} + +void QgsMapTool::canvasMoveEvent(QMouseEvent *) +{ +} + +void QgsMapTool::canvasPressEvent(QMouseEvent *) +{ +} + +void QgsMapTool::canvasReleaseEvent(QMouseEvent *) +{ +} + +void QgsMapTool::renderComplete() +{ +} + +bool QgsMapTool::isZoomTool() +{ + return false; +} + +QgsMapCanvas* QgsMapTool::canvas() +{ + return mCanvas; +} diff --git a/src/gui/qgsmaptool.h b/src/gui/qgsmaptool.h index e77442b6e32..053bd81fe3e 100644 --- a/src/gui/qgsmaptool.h +++ b/src/gui/qgsmaptool.h @@ -19,6 +19,7 @@ #include #include +#include class QgsMapLayer; class QgsMapCanvas; @@ -29,38 +30,38 @@ class QPoint; class QAction; -class GUI_EXPORT QgsMapTool +class GUI_EXPORT QgsMapTool : public QObject { public: //! virtual destructor virtual ~QgsMapTool(); - //! Mouse move event for overriding - virtual void canvasMoveEvent(QMouseEvent * e) { } + //! Mouse move event for overriding. Default implementation does nothing. + virtual void canvasMoveEvent(QMouseEvent * e); - //! Mouse press event for overriding - virtual void canvasPressEvent(QMouseEvent * e) { } + //! Mouse press event for overriding. Default implementation does nothing. + virtual void canvasPressEvent(QMouseEvent * e); - //! Mouse release event for overriding - virtual void canvasReleaseEvent(QMouseEvent * e) { } + //! Mouse release event for overriding. Default implementation does nothing. + virtual void canvasReleaseEvent(QMouseEvent * e); - //! Called when rendering has finished - virtual void renderComplete() {} + //! Called when rendering has finished. Default implementation does nothing. + virtual void renderComplete(); /** Use this to associate a button, toolbutton, menu entry etc * that inherits qaction to this maptool. Then when the setMapTool * method of mapcanvas is called the action state will be set to on. * Usually this will cause e.g. a toolbutton to appear pressed in and * the previously used toolbutton to pop out. */ - void setAction(QAction* action) { mAction = action; } + void setAction(QAction* action); - QAction* action() { return mAction; } + QAction* action(); /** Check whether this MapTool performs a zoom or pan operation. * If it does, we will be able to perform the zoom and then * resume operations with the original / previously used tool.*/ - virtual bool isZoomTool() { return false;} + virtual bool isZoomTool(); //! called when set as currently active map tool virtual void activate(); @@ -68,6 +69,9 @@ class GUI_EXPORT QgsMapTool //! called when map tool is being deactivated virtual void deactivate(); + //! returns pointer to the tool's map canvas + QgsMapCanvas* canvas(); + protected: //! constructor takes map canvas as a parameter