Skip to content
Permalink
Browse files

[tracer] improved reporting of warnings

  • Loading branch information
wonder-sk committed Jan 11, 2016
1 parent 2c414ce commit e7d277fd868d62de4f72106c44019cb73243e588
@@ -1974,10 +1974,8 @@ void QgisApp::createToolBars()
// Cad toolbar
mAdvancedDigitizeToolBar->insertAction( mActionUndo, mAdvancedDigitizingDockWidget->enableAction() );

mTracer = new QgsMapCanvasTracer( mMapCanvas );
mTracer = new QgsMapCanvasTracer( mMapCanvas, messageBar() );
mAdvancedDigitizeToolBar->insertAction( mActionUndo, mTracer->actionEnableTracing() );
connect( mTracer, SIGNAL( messageEmitted( QString, QgsMessageBar::MessageLevel ) ),
this, SLOT( displayMapToolMessage( QString, QgsMessageBar::MessageLevel ) ) );
}

void QgisApp::createStatusBar()
@@ -486,14 +486,14 @@ bool QgsTracer::initGraph()
}

extract_linework( f.geometry(), mpl );

++featuresCounted;
if ( mMaxFeatureCount != 0 && featuresCounted >= mMaxFeatureCount )
return false;
}
}
int timeExtract = t1.elapsed();

if ( mMaxFeatureCount != 0 && featuresCounted >= mMaxFeatureCount )
return false;

// resolve intersections

t2.start();
@@ -611,18 +611,32 @@ void QgsTracer::onGeometryChanged( QgsFeatureId fid, QgsGeometry& geom )
invalidateGraph();
}

QVector<QgsPoint> QgsTracer::findShortestPath( const QgsPoint& p1, const QgsPoint& p2 )
QVector<QgsPoint> QgsTracer::findShortestPath(const QgsPoint& p1, const QgsPoint& p2, PathError* error )
{
init(); // does nothing if the graph exists already
if ( !mGraph )
{
if ( error ) *error = ErrTooManyFeatures;
return QVector<QgsPoint>();
}

QTime t;
t.start();
int v1 = point_in_graph( *mGraph, p1 );
int v2 = point_in_graph( *mGraph, p2 );
int tPrep = t.elapsed();

if ( v1 == -1 )
{
if ( error ) *error = ErrPoint1;
return QVector<QgsPoint>();
}
if ( v2 == -1 )
{
if ( error ) *error = ErrPoint2;
return QVector<QgsPoint>();
}

QTime t2;
t2.start();
QgsPolyline points = shortest_path( *mGraph, v1, v2 );
@@ -632,6 +646,9 @@ QVector<QgsPoint> QgsTracer::findShortestPath( const QgsPoint& p1, const QgsPoin

reset_graph( *mGraph );

if ( error )
*error = points.isEmpty() ? ErrNoPath : ErrNone;

return points;
}

@@ -68,11 +68,20 @@ class CORE_EXPORT QgsTracer : public QObject
//! if necessary.
virtual bool init();

enum PathError
{
ErrNone,
ErrTooManyFeatures,
ErrPoint1,
ErrPoint2,
ErrNoPath,
};

//! Given two points, find the shortest path and return points on the way.
//! If the points are not located on existing vertices or edges,
//! search will fail and return empty array. The search will also fail
//! if the two points are not connected.
QVector<QgsPoint> findShortestPath( const QgsPoint& p1, const QgsPoint& p2 );
QVector<QgsPoint> findShortestPath( const QgsPoint& p1, const QgsPoint& p2, PathError* error = 0 );

//! Find out whether the point is snapped to a vertex or edge (i.e. it can be used for tracing start/stop)
bool isPointSnapped( const QgsPoint& pt );
@@ -4,6 +4,7 @@
#include "qgsmapcanvas.h"
#include "qgsmaplayerregistry.h"
#include "qgsmessagebar.h"
#include "qgsmessagebaritem.h"
#include "qgssnappingutils.h"
#include "qgsvectorlayer.h"

@@ -12,8 +13,10 @@
QHash<QgsMapCanvas*, QgsMapCanvasTracer*> QgsMapCanvasTracer::sTracers;


QgsMapCanvasTracer::QgsMapCanvasTracer( QgsMapCanvas* canvas )
QgsMapCanvasTracer::QgsMapCanvasTracer( QgsMapCanvas* canvas, QgsMessageBar* messageBar )
: mCanvas( canvas )
, mMessageBar( messageBar )
, mLastMessage( nullptr )
{
sTracers.insert( canvas, this );

@@ -29,7 +32,7 @@ QgsMapCanvasTracer::QgsMapCanvasTracer( QgsMapCanvas* canvas )

// arbitrarily chosen limit that should allow for fairly fast initialization
// of the underlying graph structure
setMaxFeatureCount( 10000 );
setMaxFeatureCount( QSettings().value( "/qgis/digitizing/tracing_max_feature_count", 10000 ).toInt() );

updateSettings(); // initialize
updateLayerSettings();
@@ -43,10 +46,6 @@ QgsMapCanvasTracer::~QgsMapCanvasTracer()
bool QgsMapCanvasTracer::init()
{
bool res = QgsTracer::init();

if ( !res )
emit messageEmitted( tr( "Tracing disabled because there are too many features displayed. Try zooming in or disable some layers." ) );

return res;
}

@@ -55,6 +54,45 @@ QgsMapCanvasTracer* QgsMapCanvasTracer::tracerForCanvas( QgsMapCanvas* canvas )
return sTracers.value( canvas, 0 );
}

void QgsMapCanvasTracer::reportError( QgsTracer::PathError err, bool addingVertex )
{
if ( !mMessageBar )
return;

// remove previous message (if any)
mMessageBar->popWidget( mLastMessage );
mLastMessage = nullptr;

QString message;
switch ( err )
{
case ErrTooManyFeatures:
message = tr( "Disabled - there are too many features displayed. Try zooming in or disable some layers." );
break;
case ErrPoint1:
message = tr( "The start point needs to be snapped and in the visible map view" );
break;
case ErrPoint2:
if ( addingVertex )
message = tr( "The end point needs to be snapped" );
break;
case ErrNoPath:
if ( addingVertex )
message = tr( "Endpoints are not connected" );
break;
case ErrNone:
default:
break;
}

if ( message.isEmpty() )
return;

mLastMessage = new QgsMessageBarItem( tr( "Tracing" ), message, QgsMessageBar::WARNING,
QSettings().value( "/qgis/messageTimeout", 5 ).toInt() );
mMessageBar->pushItem( mLastMessage );
}

void QgsMapCanvasTracer::updateSettings()
{
setDestinationCrs( mCanvas->mapSettings().destinationCrs() );
@@ -1,18 +1,19 @@
#ifndef QGSMAPCANVASTRACER_H
#define QGSMAPCANVASTRACER_H

#include "qgsmessagebar.h"
#include "qgstracer.h"

class QAction;
class QgsMapCanvas;
class QgsMessageBar;
class QgsMessageBarItem;

class GUI_EXPORT QgsMapCanvasTracer : public QgsTracer
{
Q_OBJECT

public:
explicit QgsMapCanvasTracer( QgsMapCanvas* canvas );
explicit QgsMapCanvasTracer( QgsMapCanvas* canvas, QgsMessageBar* messageBar = 0 );
~QgsMapCanvasTracer();

QAction* actionEnableTracing() { return mActionEnableTracing; }
@@ -24,12 +25,8 @@ class GUI_EXPORT QgsMapCanvasTracer : public QgsTracer
//! instances for easier access to the common tracer by various map tools
static QgsMapCanvasTracer* tracerForCanvas( QgsMapCanvas* canvas );

signals:
//! emit a message
void messageEmitted( const QString& message, QgsMessageBar::MessageLevel = QgsMessageBar::INFO );

//! emit signal to clear previous message
//void messageDiscarded();
//! Report a path finding error to the user
void reportError( PathError err, bool addingVertex );

private slots:
void updateSettings();
@@ -38,6 +35,8 @@ class GUI_EXPORT QgsMapCanvasTracer : public QgsTracer

private:
QgsMapCanvas* mCanvas;
QgsMessageBar* mMessageBar;
QgsMessageBarItem* mLastMessage;

QAction* mActionEnableTracing;

@@ -174,14 +174,15 @@ void QgsMapToolCapture::tracingMouseMove( QgsMapMouseEvent* e )
if ( !tracer )
return; // this should not happen!

if ( !tracer->init() ) // normally no-op if the graph is built already
return; // graph would be too big

mTempRubberBand->reset( mCaptureMode == CapturePolygon ? QGis::Polygon : QGis::Line );

QVector<QgsPoint> points = tracer->findShortestPath( pt0, e->mapPoint() );
QgsTracer::PathError err;
QVector<QgsPoint> points = tracer->findShortestPath( pt0, e->mapPoint(), &err );
if ( points.isEmpty() )
{
tracer->reportError( err, false );
return;
}

if ( mCaptureMode == CapturePolygon )
mTempRubberBand->addPoint( *mRubberBand->getPoint( 0, 0 ), false );
@@ -192,19 +193,20 @@ void QgsMapToolCapture::tracingMouseMove( QgsMapMouseEvent* e )
}


bool QgsMapToolCapture::tracingAddVertex( const QgsPoint& point, bool& pathNotFound )
bool QgsMapToolCapture::tracingAddVertex( const QgsPoint& point )
{
pathNotFound = false;

QgsMapCanvasTracer* tracer = QgsMapCanvasTracer::tracerForCanvas( mCanvas );
if ( !tracer )
return false; // this should not happen!

if ( !tracer->init() ) // normally no-op if the graph is built already
return false; // graph would be too big

if ( mCaptureCurve.numPoints() == 0 )
{
if ( !tracer->init() )
{
tracer->reportError( QgsTracer::ErrTooManyFeatures, true );
return false;
}

// only accept first point if it is snapped to the graph (to vertex or edge)
bool res = tracer->isPointSnapped( point );
if ( res )
@@ -222,10 +224,11 @@ bool QgsMapToolCapture::tracingAddVertex( const QgsPoint& point, bool& pathNotFo
if ( pt0 == QgsPoint() )
return false;

QVector<QgsPoint> points = tracer->findShortestPath( pt0, point );
QgsTracer::PathError err;
QVector<QgsPoint> points = tracer->findShortestPath( pt0, point, &err );
if ( points.isEmpty() )
{
pathNotFound = true;
tracer->reportError( err, true );
return false; // ignore the vertex - can't find path to the end point!
}

@@ -369,14 +372,9 @@ int QgsMapToolCapture::addVertex( const QgsPoint& point )

if ( tracingEnabled() )
{
bool pathNotFound;
bool res = tracingAddVertex( point, pathNotFound );
bool res = tracingAddVertex( point );
if ( !res )
{
if ( pathNotFound )
emit messageEmitted( tr( "Tracing: The point needs to be snapped to a geometry" ), QgsMessageBar::WARNING );
return 1; // early exit if the point cannot be accepted
}
}
else
{
@@ -148,7 +148,7 @@ class GUI_EXPORT QgsMapToolCapture : public QgsMapToolAdvancedDigitizing
//! handle of mouse movement when tracing enabled and capturing has started
void tracingMouseMove( QgsMapMouseEvent* e );
//! handle of addition of clicked point (with the rest of the trace) when tracing enabled
bool tracingAddVertex( const QgsPoint& point, bool& pathNotFound );
bool tracingAddVertex( const QgsPoint& point );

private:
/** Flag to indicate a map canvas capture operation is taking place */

0 comments on commit e7d277f

Please sign in to comment.
You can’t perform that action at this time.