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
This commit is contained in:
wonder 2007-04-23 14:57:08 +00:00
parent 4cfcc0d1a9
commit 7e367f30b8
12 changed files with 608 additions and 489 deletions

View File

@ -1,5 +1,5 @@
class QgsMapTool
class QgsMapTool : QObject
{
%TypeHeaderCode
#include <qgsmaptool.h>
@ -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);

View File

@ -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

View File

@ -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);

View File

@ -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;

View File

@ -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 <QSettings>
#include <QLocale>
#include <iostream>
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("<p>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.</p>"
"<p>To fix this, explicitly set an appropriate map coordinate "
"system using the <tt>Settings:Project Properties</tt> 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<QgsPoint> 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();
}
}

View File

@ -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 <QSettings>
#include <QLocale>
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<QgsPoint> 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));
}
}

View File

@ -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 <QWidget>
#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<QgsPoint> 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

200
src/app/qgsmeasuretool.cpp Normal file
View File

@ -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 <QMessageBox>
#include <QSettings>
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<QgsPoint>& 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("<p>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.</p>"
"<p>To fix this, explicitly set an appropriate map coordinate "
"system using the <tt>Settings:Project Properties</tt> 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);
}

92
src/app/qgsmeasuretool.h Normal file
View File

@ -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<QgsPoint>& 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<QgsPoint> 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

View File

@ -48,7 +48,6 @@ class QgsMapLayer;
class QgsMapLayerInterface;
class QgsLegend;
class QgsLegendView;
class QgsMeasure;
class QgsRubberBand;
class QgsMapRender;

View File

@ -22,7 +22,7 @@
#include <QAction>
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;
}

View File

@ -19,6 +19,7 @@
#include <QCursor>
#include <QString>
#include <QObject>
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