From 7e367f30b893b3adf8a8323d4f7d1db8c549367e Mon Sep 17 00:00:00 2001 From: wonder Date: Mon, 23 Apr 2007 14:57:08 +0000 Subject: [PATCH] Solved problems with destruction of map tools - canvas mustn't be deleted before map tool, however in Python the destruction had to be done explicitly to acheive right order. New solution is that QgsMapTool is derived from QObject and on construction, QgsMapCanvas is set as its parent. This way canvas is always deleted after deletion of map tools. Also, because of this, I've divided QgsMeasure to QgsMeasureTool and QgsMeasureDialog (problem with 2 parents with QObject as a base). git-svn-id: http://svn.osgeo.org/qgis/trunk@6908 c8812cc2-4d05-0410-92ff-de0c093fc19c --- python/gui/qgsmaptool.sip | 4 +- src/app/CMakeLists.txt | 5 +- src/app/qgisapp.cpp | 6 +- src/app/qgsmaptoolidentify.h | 2 +- src/app/qgsmeasure.cpp | 406 ------------------- src/app/qgsmeasuredialog.cpp | 242 +++++++++++ src/app/{qgsmeasure.h => qgsmeasuredialog.h} | 73 +--- src/app/qgsmeasuretool.cpp | 200 +++++++++ src/app/qgsmeasuretool.h | 92 +++++ src/gui/qgsmapcanvas.h | 1 - src/gui/qgsmaptool.cpp | 38 +- src/gui/qgsmaptool.h | 28 +- 12 files changed, 608 insertions(+), 489 deletions(-) delete mode 100644 src/app/qgsmeasure.cpp create mode 100644 src/app/qgsmeasuredialog.cpp rename src/app/{qgsmeasure.h => qgsmeasuredialog.h} (57%) create mode 100644 src/app/qgsmeasuretool.cpp create mode 100644 src/app/qgsmeasuretool.h 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