mirror of
https://github.com/qgis/QGIS.git
synced 2025-02-23 00:02:38 -05:00
Fix snapping on invisible geometry
This commit is contained in:
parent
5e33d7d639
commit
66b0e59fb9
@ -71,6 +71,13 @@ Get extent of the area point locator covers - if null then it caches the whole l
|
||||
Configure extent - if not null, it will index only that area
|
||||
|
||||
.. versionadded:: 2.14
|
||||
%End
|
||||
|
||||
void setRenderContext( const QgsRenderContext &context );
|
||||
%Docstring
|
||||
Configure render context - if not null, it will use to index only visible feature
|
||||
|
||||
.. versionadded:: 3.2
|
||||
%End
|
||||
|
||||
enum Type
|
||||
@ -199,7 +206,6 @@ Override of edgesInRect that construct rectangle from a center point and toleran
|
||||
find out if the point is in any polygons
|
||||
%End
|
||||
|
||||
|
||||
int cachedGeometryCount() const;
|
||||
%Docstring
|
||||
Return how many geometries are cached in the index
|
||||
|
@ -35,7 +35,7 @@ which keeps the configuration in sync with map canvas (e.g. current view, active
|
||||
%End
|
||||
public:
|
||||
|
||||
QgsSnappingUtils( QObject *parent /TransferThis/ = 0 );
|
||||
QgsSnappingUtils( QObject *parent /TransferThis/ = 0, bool enableSnappingForInvisibleFeature = true );
|
||||
%Docstring
|
||||
Constructor for QgsSnappingUtils
|
||||
%End
|
||||
@ -139,6 +139,15 @@ Get extra information about the instance
|
||||
QgsSnappingConfig config() const;
|
||||
%Docstring
|
||||
The snapping configuration controls the behavior of this object
|
||||
%End
|
||||
|
||||
void setEnableSnappingForInvisibleFeature( bool enable );
|
||||
%Docstring
|
||||
Set if invisible features must be snapped or not.
|
||||
|
||||
:param enable: Enable or not this feature
|
||||
|
||||
.. versionadded:: 3.2
|
||||
%End
|
||||
|
||||
public slots:
|
||||
|
@ -9,6 +9,7 @@
|
||||
|
||||
|
||||
|
||||
|
||||
class QgsMapCanvasSnappingUtils : QgsSnappingUtils
|
||||
{
|
||||
%Docstring
|
||||
|
@ -20,6 +20,9 @@ digitizing\default_snap_type=1
|
||||
# 2 = Project units
|
||||
digitizing\default_snapping_tolerance_unit=1
|
||||
|
||||
# Snap on invisble feature
|
||||
digitizing\snap_invisible_feature=false
|
||||
|
||||
# Default XYZ tile servers to include
|
||||
connections-xyz\OpenStreetMap\authcfg=
|
||||
connections-xyz\OpenStreetMap\password=
|
||||
|
@ -971,6 +971,7 @@ QgsOptions::QgsOptions( QWidget *parent, Qt::WindowFlags fl, const QList<QgsOpti
|
||||
|
||||
mSnappingMarkerColorButton->setColor( mSettings->value( QStringLiteral( "/qgis/digitizing/snap_color" ), QColor( Qt::magenta ) ).value<QColor>() );
|
||||
mSnappingTooltipsCheckbox->setChecked( mSettings->value( QStringLiteral( "/qgis/digitizing/snap_tooltip" ), false ).toBool() );
|
||||
mEnableSnappingOnInvisibleFeatureCheckbox->setChecked( mSettings->value( QStringLiteral( "/qgis/digitizing/snap_invisible_feature" ), false ).toBool() );
|
||||
|
||||
//vertex marker
|
||||
mMarkersOnlyForSelectedCheckBox->setChecked( mSettings->value( QStringLiteral( "/qgis/digitizing/marker_only_for_selected" ), true ).toBool() );
|
||||
@ -1483,6 +1484,7 @@ void QgsOptions::saveOptions()
|
||||
|
||||
mSettings->setValue( QStringLiteral( "/qgis/digitizing/snap_color" ), mSnappingMarkerColorButton->color() );
|
||||
mSettings->setValue( QStringLiteral( "/qgis/digitizing/snap_tooltip" ), mSnappingTooltipsCheckbox->isChecked() );
|
||||
mSettings->setValue( QStringLiteral( "/qgis/digitizing/snap_invisible_feature" ), mEnableSnappingOnInvisibleFeatureCheckbox->isChecked() );
|
||||
|
||||
mSettings->setValue( QStringLiteral( "/qgis/digitizing/marker_only_for_selected" ), mMarkersOnlyForSelectedCheckBox->isChecked() );
|
||||
|
||||
|
@ -331,6 +331,7 @@ bool QgsSymbolLegendNode::setData( const QVariant &value, int role )
|
||||
vlayer->renderer()->checkLegendSymbolItem( mItem.ruleKey(), value == Qt::Checked );
|
||||
|
||||
emit dataChanged();
|
||||
emit vlayer->styleChanged();
|
||||
|
||||
vlayer->triggerRepaint();
|
||||
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include "qgswkbptr.h"
|
||||
#include "qgis.h"
|
||||
#include "qgslogger.h"
|
||||
#include "qgsrenderer.h"
|
||||
|
||||
#include <SpatialIndex.h>
|
||||
|
||||
@ -636,6 +637,9 @@ QgsPointLocator::QgsPointLocator( QgsVectorLayer *layer, const QgsCoordinateRefe
|
||||
connect( mLayer, &QgsVectorLayer::featureDeleted, this, &QgsPointLocator::onFeatureDeleted );
|
||||
connect( mLayer, &QgsVectorLayer::geometryChanged, this, &QgsPointLocator::onGeometryChanged );
|
||||
connect( mLayer, &QgsVectorLayer::dataChanged, this, &QgsPointLocator::destroyIndex );
|
||||
connect( mLayer, &QgsVectorLayer::rendererChanged, this, &QgsPointLocator::destroyIndex );
|
||||
connect( mLayer, &QgsVectorLayer::styleChanged, this, &QgsPointLocator::destroyIndex );
|
||||
connect( mLayer, &QgsVectorLayer::layerModified, this, &QgsPointLocator::destroyIndex );
|
||||
}
|
||||
|
||||
|
||||
@ -661,6 +665,12 @@ void QgsPointLocator::setExtent( const QgsRectangle *extent )
|
||||
destroyIndex();
|
||||
}
|
||||
|
||||
void QgsPointLocator::setRenderContext( const QgsRenderContext &context )
|
||||
{
|
||||
mContext = std::unique_ptr<QgsRenderContext>( new QgsRenderContext( context ) );
|
||||
|
||||
destroyIndex();
|
||||
}
|
||||
|
||||
bool QgsPointLocator::init( int maxFeaturesToIndex )
|
||||
{
|
||||
@ -686,6 +696,7 @@ bool QgsPointLocator::rebuildIndex( int maxFeaturesToIndex )
|
||||
|
||||
QgsFeatureRequest request;
|
||||
request.setSubsetOfAttributes( QgsAttributeList() );
|
||||
|
||||
if ( mExtent )
|
||||
{
|
||||
QgsRectangle rect = *mExtent;
|
||||
@ -704,13 +715,40 @@ bool QgsPointLocator::rebuildIndex( int maxFeaturesToIndex )
|
||||
}
|
||||
request.setFilterRect( rect );
|
||||
}
|
||||
|
||||
bool filter = false;
|
||||
std::unique_ptr< QgsFeatureRenderer > renderer( mLayer->renderer() ? mLayer->renderer()->clone() : nullptr );
|
||||
QgsRenderContext *ctx = nullptr;
|
||||
if ( mContext )
|
||||
{
|
||||
mContext->expressionContext() << QgsExpressionContextUtils::layerScope( mLayer );
|
||||
ctx = mContext.get();
|
||||
if ( renderer )
|
||||
{
|
||||
// setup scale for scale dependent visibility (rule based)
|
||||
renderer->startRender( *ctx, mLayer->fields() );
|
||||
filter = renderer->capabilities() & QgsFeatureRenderer::Filter;
|
||||
request.setSubsetOfAttributes( renderer->usedAttributes( *ctx ), mLayer->fields() );
|
||||
}
|
||||
}
|
||||
|
||||
QgsFeatureIterator fi = mLayer->getFeatures( request );
|
||||
int indexedCount = 0;
|
||||
|
||||
while ( fi.nextFeature( f ) )
|
||||
{
|
||||
if ( !f.hasGeometry() )
|
||||
continue;
|
||||
|
||||
if ( ctx && renderer )
|
||||
{
|
||||
ctx->expressionContext().setFeature( f );
|
||||
if ( filter && !renderer->willRenderFeature( f, *ctx ) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if ( mTransform.isValid() )
|
||||
{
|
||||
try
|
||||
@ -761,6 +799,12 @@ bool QgsPointLocator::rebuildIndex( int maxFeaturesToIndex )
|
||||
QgsPointLocator_Stream stream( dataList );
|
||||
mRTree = RTree::createAndBulkLoadNewRTree( RTree::BLM_STR, stream, *mStorage, fillFactor, indexCapacity,
|
||||
leafCapacity, dimension, variant, indexId );
|
||||
|
||||
if ( ctx && renderer )
|
||||
{
|
||||
renderer->stopRender( *ctx );
|
||||
renderer.release();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -832,6 +876,7 @@ void QgsPointLocator::onFeatureDeleted( QgsFeatureId fid )
|
||||
mRTree->deleteData( rect2region( mGeoms[fid]->boundingBox() ), fid );
|
||||
delete mGeoms.take( fid );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void QgsPointLocator::onGeometryChanged( QgsFeatureId fid, const QgsGeometry &geom )
|
||||
|
@ -18,12 +18,15 @@
|
||||
|
||||
class QgsPointXY;
|
||||
class QgsVectorLayer;
|
||||
class QgsFeatureRenderer;
|
||||
class QgsRenderContext;
|
||||
|
||||
#include "qgis_core.h"
|
||||
#include "qgsfeature.h"
|
||||
#include "qgspointxy.h"
|
||||
#include "qgscoordinatereferencesystem.h"
|
||||
#include "qgscoordinatetransform.h"
|
||||
#include <memory>
|
||||
|
||||
class QgsPointLocator_VisitorNearestVertex;
|
||||
class QgsPointLocator_VisitorNearestEdge;
|
||||
@ -92,6 +95,12 @@ class CORE_EXPORT QgsPointLocator : public QObject
|
||||
*/
|
||||
void setExtent( const QgsRectangle *extent );
|
||||
|
||||
/**
|
||||
* Configure render context - if not null, it will use to index only visible feature
|
||||
* \since QGIS 3.2
|
||||
*/
|
||||
void setRenderContext( const QgsRenderContext &context );
|
||||
|
||||
/**
|
||||
* The type of a snap result or the filter type for a snap request.
|
||||
*/
|
||||
@ -251,8 +260,6 @@ class CORE_EXPORT QgsPointLocator : public QObject
|
||||
//! find out if the point is in any polygons
|
||||
MatchList pointInPolygon( const QgsPointXY &point );
|
||||
|
||||
//
|
||||
|
||||
/**
|
||||
* Return how many geometries are cached in the index
|
||||
* \since QGIS 2.14
|
||||
@ -278,11 +285,15 @@ class CORE_EXPORT QgsPointLocator : public QObject
|
||||
//! flag whether the layer is currently empty (i.e. mRTree is null but it is not necessary to rebuild it)
|
||||
bool mIsEmptyLayer;
|
||||
|
||||
QgsFeatureIds mFeatureIds;
|
||||
|
||||
//! R-tree containing spatial index
|
||||
QgsCoordinateTransform mTransform;
|
||||
QgsVectorLayer *mLayer = nullptr;
|
||||
QgsRectangle *mExtent = nullptr;
|
||||
|
||||
std::unique_ptr<QgsRenderContext> mContext;
|
||||
|
||||
friend class QgsPointLocator_VisitorNearestVertex;
|
||||
friend class QgsPointLocator_VisitorNearestEdge;
|
||||
friend class QgsPointLocator_VisitorArea;
|
||||
|
@ -19,10 +19,12 @@
|
||||
#include "qgsproject.h"
|
||||
#include "qgsvectorlayer.h"
|
||||
#include "qgslogger.h"
|
||||
#include "qgsrenderer.h"
|
||||
|
||||
QgsSnappingUtils::QgsSnappingUtils( QObject *parent )
|
||||
QgsSnappingUtils::QgsSnappingUtils( QObject *parent, bool enableSnappingForInvisibleFeature )
|
||||
: QObject( parent )
|
||||
, mSnappingConfig( QgsProject::instance() )
|
||||
, mEnableSnappingForInvisibleFeature( enableSnappingForInvisibleFeature )
|
||||
{
|
||||
}
|
||||
|
||||
@ -92,7 +94,6 @@ bool QgsSnappingUtils::isIndexPrepared( QgsVectorLayer *vl, const QgsRectangle &
|
||||
return ( mStrategy == IndexHybrid || mStrategy == IndexExtent ) && loc->hasIndex() && ( !loc->extent() || loc->extent()->contains( aoi ) ); // the index - even if it exists - is not suitable
|
||||
}
|
||||
|
||||
|
||||
static QgsPointLocator::Match _findClosestSegmentIntersection( const QgsPointXY &pt, const QgsPointLocator::MatchList &segments )
|
||||
{
|
||||
if ( segments.isEmpty() )
|
||||
@ -156,9 +157,9 @@ static QgsPointLocator::Match _findClosestSegmentIntersection( const QgsPointXY
|
||||
return QgsPointLocator::Match( QgsPointLocator::Vertex, nullptr, 0, std::sqrt( minSqrDist ), minP );
|
||||
}
|
||||
|
||||
|
||||
static void _replaceIfBetter( QgsPointLocator::Match &bestMatch, const QgsPointLocator::Match &candidateMatch, double maxDistance )
|
||||
{
|
||||
|
||||
// is candidate match relevant?
|
||||
if ( !candidateMatch.isValid() || candidateMatch.distance() > maxDistance )
|
||||
return;
|
||||
@ -174,7 +175,6 @@ static void _replaceIfBetter( QgsPointLocator::Match &bestMatch, const QgsPointL
|
||||
bestMatch = candidateMatch; // the other match is better!
|
||||
}
|
||||
|
||||
|
||||
static void _updateBestMatch( QgsPointLocator::Match &bestMatch, const QgsPointXY &pointMap, QgsPointLocator *loc, QgsPointLocator::Types type, double tolerance, QgsPointLocator::MatchFilter *filter )
|
||||
{
|
||||
if ( type & QgsPointLocator::Vertex )
|
||||
@ -329,7 +329,6 @@ QgsPointLocator::Match QgsSnappingUtils::snapToMap( const QgsPointXY &pointMap,
|
||||
return QgsPointLocator::Match();
|
||||
}
|
||||
|
||||
|
||||
void QgsSnappingUtils::prepareIndex( const QList<LayerAndAreaOfInterest> &layers )
|
||||
{
|
||||
if ( mIsIndexing )
|
||||
@ -341,6 +340,7 @@ void QgsSnappingUtils::prepareIndex( const QList<LayerAndAreaOfInterest> &layers
|
||||
Q_FOREACH ( const LayerAndAreaOfInterest &entry, layers )
|
||||
{
|
||||
QgsVectorLayer *vl = entry.first;
|
||||
|
||||
if ( vl->geometryType() == QgsWkbTypes::NullGeometry || mStrategy == IndexNeverFull )
|
||||
continue;
|
||||
|
||||
@ -359,7 +359,12 @@ void QgsSnappingUtils::prepareIndex( const QList<LayerAndAreaOfInterest> &layers
|
||||
QgsVectorLayer *vl = entry.first;
|
||||
QTime tt;
|
||||
tt.start();
|
||||
|
||||
QgsPointLocator *loc = locatorForLayer( vl );
|
||||
|
||||
if ( !mEnableSnappingForInvisibleFeature )
|
||||
loc->setRenderContext( QgsRenderContext::fromMapSettings( mMapSettings ) );
|
||||
|
||||
if ( mStrategy == IndexExtent )
|
||||
{
|
||||
QgsRectangle rect( mMapSettings.extent() );
|
||||
@ -428,6 +433,11 @@ QgsSnappingConfig QgsSnappingUtils::config() const
|
||||
return mSnappingConfig;
|
||||
}
|
||||
|
||||
void QgsSnappingUtils::setEnableSnappingForInvisibleFeature( bool enable )
|
||||
{
|
||||
mEnableSnappingForInvisibleFeature = enable;
|
||||
}
|
||||
|
||||
void QgsSnappingUtils::setConfig( const QgsSnappingConfig &config )
|
||||
{
|
||||
if ( mSnappingConfig == config )
|
||||
|
@ -53,7 +53,7 @@ class CORE_EXPORT QgsSnappingUtils : public QObject
|
||||
public:
|
||||
|
||||
//! Constructor for QgsSnappingUtils
|
||||
QgsSnappingUtils( QObject *parent SIP_TRANSFERTHIS = nullptr );
|
||||
QgsSnappingUtils( QObject *parent SIP_TRANSFERTHIS = nullptr, bool enableSnappingForInvisibleFeature = true );
|
||||
~QgsSnappingUtils() override;
|
||||
|
||||
// main actions
|
||||
@ -159,6 +159,15 @@ class CORE_EXPORT QgsSnappingUtils : public QObject
|
||||
*/
|
||||
QgsSnappingConfig config() const;
|
||||
|
||||
/**
|
||||
* Set if invisible features must be snapped or not.
|
||||
*
|
||||
* \param enable Enable or not this feature
|
||||
*
|
||||
* \since QGIS 3.2
|
||||
*/
|
||||
void setEnableSnappingForInvisibleFeature( bool enable );
|
||||
|
||||
public slots:
|
||||
|
||||
/**
|
||||
@ -242,6 +251,10 @@ class CORE_EXPORT QgsSnappingUtils : public QObject
|
||||
|
||||
//! internal flag that an indexing process is going on. Prevents starting two processes in parallel.
|
||||
bool mIsIndexing = false;
|
||||
|
||||
//! Disable or not the snapping on all features. By default is always true except for non visible features on map canvas.
|
||||
bool mEnableSnappingForInvisibleFeature = true;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
@ -16,12 +16,13 @@
|
||||
|
||||
#include "qgsmapcanvas.h"
|
||||
#include "qgsvectorlayer.h"
|
||||
#include "qgssettings.h"
|
||||
|
||||
#include <QApplication>
|
||||
#include <QProgressDialog>
|
||||
|
||||
QgsMapCanvasSnappingUtils::QgsMapCanvasSnappingUtils( QgsMapCanvas *canvas, QObject *parent )
|
||||
: QgsSnappingUtils( parent )
|
||||
: QgsSnappingUtils( parent, QgsSettings().value( QStringLiteral( "/qgis/digitizing/snap_invisible_feature" ), false ).toBool() )
|
||||
, mCanvas( canvas )
|
||||
|
||||
{
|
||||
@ -30,6 +31,7 @@ QgsMapCanvasSnappingUtils::QgsMapCanvasSnappingUtils( QgsMapCanvas *canvas, QObj
|
||||
connect( canvas, &QgsMapCanvas::layersChanged, this, &QgsMapCanvasSnappingUtils::canvasMapSettingsChanged );
|
||||
connect( canvas, &QgsMapCanvas::currentLayerChanged, this, &QgsMapCanvasSnappingUtils::canvasCurrentLayerChanged );
|
||||
connect( canvas, &QgsMapCanvas::transformContextChanged, this, &QgsMapCanvasSnappingUtils::canvasTransformContextChanged );
|
||||
connect( canvas, &QgsMapCanvas::mapToolSet, this, &QgsMapCanvasSnappingUtils::canvasMapToolChanged );
|
||||
canvasMapSettingsChanged();
|
||||
canvasCurrentLayerChanged();
|
||||
}
|
||||
@ -37,6 +39,7 @@ QgsMapCanvasSnappingUtils::QgsMapCanvasSnappingUtils( QgsMapCanvas *canvas, QObj
|
||||
void QgsMapCanvasSnappingUtils::canvasMapSettingsChanged()
|
||||
{
|
||||
setMapSettings( mCanvas->mapSettings() );
|
||||
setEnableSnappingForInvisibleFeature( QgsSettings().value( QStringLiteral( "/qgis/digitizing/snap_invisible_feature" ), false ).toBool() );
|
||||
}
|
||||
|
||||
void QgsMapCanvasSnappingUtils::canvasTransformContextChanged()
|
||||
@ -51,6 +54,11 @@ void QgsMapCanvasSnappingUtils::canvasCurrentLayerChanged()
|
||||
setCurrentLayer( qobject_cast<QgsVectorLayer *>( mCanvas->currentLayer() ) );
|
||||
}
|
||||
|
||||
void QgsMapCanvasSnappingUtils::canvasMapToolChanged()
|
||||
{
|
||||
setEnableSnappingForInvisibleFeature( QgsSettings().value( QStringLiteral( "/qgis/digitizing/snap_invisible_feature" ), false ).toBool() );
|
||||
}
|
||||
|
||||
void QgsMapCanvasSnappingUtils::prepareIndexStarting( int count )
|
||||
{
|
||||
QApplication::setOverrideCursor( Qt::WaitCursor );
|
||||
|
@ -18,6 +18,8 @@
|
||||
#include "qgssnappingutils.h"
|
||||
#include "qgis_gui.h"
|
||||
|
||||
#include "qgsmaptool.h"
|
||||
|
||||
class QgsMapCanvas;
|
||||
|
||||
class QProgressDialog;
|
||||
@ -42,6 +44,7 @@ class GUI_EXPORT QgsMapCanvasSnappingUtils : public QgsSnappingUtils
|
||||
void canvasMapSettingsChanged();
|
||||
void canvasTransformContextChanged();
|
||||
void canvasCurrentLayerChanged();
|
||||
void canvasMapToolChanged();
|
||||
|
||||
private:
|
||||
QgsMapCanvas *mCanvas = nullptr;
|
||||
|
@ -320,7 +320,7 @@
|
||||
<item>
|
||||
<widget class="QStackedWidget" name="mOptionsStackedWidget">
|
||||
<property name="currentIndex">
|
||||
<number>7</number>
|
||||
<number>8</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="mOptionsPageGeneral">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
@ -349,8 +349,8 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>843</width>
|
||||
<height>839</height>
|
||||
<width>411</width>
|
||||
<height>662</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_28">
|
||||
@ -654,12 +654,12 @@
|
||||
</property>
|
||||
<item row="1" column="0">
|
||||
<widget class="QCheckBox" name="mDataSourceManagerNonModal">
|
||||
<property name="text">
|
||||
<string>Modeless data source manager dialog</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>A modeless dialog allows you to interact with QGIS main window and dialogs.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Modeless data source manager dialog</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
@ -1040,8 +1040,8 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>843</width>
|
||||
<height>1110</height>
|
||||
<width>437</width>
|
||||
<height>1011</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_22">
|
||||
@ -1576,8 +1576,8 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>857</width>
|
||||
<height>826</height>
|
||||
<width>443</width>
|
||||
<height>312</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_15">
|
||||
@ -1743,8 +1743,8 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>857</width>
|
||||
<height>826</height>
|
||||
<width>393</width>
|
||||
<height>648</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_27">
|
||||
@ -2111,8 +2111,8 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>843</width>
|
||||
<height>1110</height>
|
||||
<width>541</width>
|
||||
<height>866</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_22">
|
||||
@ -2862,8 +2862,8 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>857</width>
|
||||
<height>826</height>
|
||||
<width>449</width>
|
||||
<height>195</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_25">
|
||||
@ -3119,8 +3119,8 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>857</width>
|
||||
<height>826</height>
|
||||
<width>515</width>
|
||||
<height>527</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_30">
|
||||
@ -3563,8 +3563,8 @@ The bigger the number, the faster zooming with the mouse wheel will be.</string>
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>857</width>
|
||||
<height>826</height>
|
||||
<width>124</width>
|
||||
<height>230</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_46">
|
||||
@ -3731,8 +3731,8 @@ The bigger the number, the faster zooming with the mouse wheel will be.</string>
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>572</width>
|
||||
<height>889</height>
|
||||
<width>862</width>
|
||||
<height>838</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_31">
|
||||
@ -3954,39 +3954,75 @@ The bigger the number, the faster zooming with the mouse wheel will be.</string>
|
||||
<property name="title">
|
||||
<string>Snapping</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="_10">
|
||||
<item row="6" column="5">
|
||||
<widget class="QgsColorButton" name="mSnappingMarkerColorButton"/>
|
||||
</item>
|
||||
<item row="1" column="1" colspan="6">
|
||||
<layout class="QGridLayout" name="gridLayout_3">
|
||||
<item row="0" column="0" colspan="4">
|
||||
<widget class="QCheckBox" name="mSnappingEnabledDefault">
|
||||
<property name="text">
|
||||
<string>Enable snapping by default</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<widget class="QLabel" name="label_49">
|
||||
<property name="text">
|
||||
<string>Display main dialog as (restart required)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="1">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Snapping marker color</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="mDefaultSnapModeLabel">
|
||||
<property name="text">
|
||||
<string>Default snap mode</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="6">
|
||||
<item row="1" column="1">
|
||||
<spacer>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>273</width>
|
||||
<height>19</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="1" column="2">
|
||||
<widget class="QComboBox" name="mDefaultSnapModeComboBox">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="mDefaultSnappingToleranceTextLabel">
|
||||
<property name="text">
|
||||
<string>Default snapping tolerance</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<spacer>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>241</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="2" column="2">
|
||||
<widget class="QDoubleSpinBox" name="mDefaultSnappingToleranceSpinBox">
|
||||
<property name="decimals">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>99999999.989999994635582</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="3">
|
||||
<widget class="QComboBox" name="mDefaultSnappingToleranceComboBox">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
@ -4006,7 +4042,14 @@ The bigger the number, the faster zooming with the mouse wheel will be.</string>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="4">
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="mVertexSearchRadiusVertexEditLabel">
|
||||
<property name="text">
|
||||
<string>Search radius for vertex edits</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<spacer>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
@ -4019,30 +4062,17 @@ The bigger the number, the faster zooming with the mouse wheel will be.</string>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="3" column="3" colspan="2">
|
||||
<spacer>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
<item row="3" column="2">
|
||||
<widget class="QDoubleSpinBox" name="mSearchRadiusVertexEditSpinBox">
|
||||
<property name="decimals">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>241</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="2" column="5" colspan="2">
|
||||
<widget class="QComboBox" name="mDefaultSnapModeComboBox">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
<property name="maximum">
|
||||
<double>99999999.989999994635582</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="6">
|
||||
<item row="3" column="3">
|
||||
<widget class="QComboBox" name="mSearchRadiusVertexEditComboBox">
|
||||
<item>
|
||||
<property name="text">
|
||||
@ -4056,63 +4086,40 @@ The bigger the number, the faster zooming with the mouse wheel will be.</string>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="5">
|
||||
<widget class="QDoubleSpinBox" name="mSearchRadiusVertexEditSpinBox">
|
||||
<property name="decimals">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>99999999.989999994635582</double>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="label_49">
|
||||
<property name="text">
|
||||
<string>Display main dialog as (restart required)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="5">
|
||||
<widget class="QDoubleSpinBox" name="mDefaultSnappingToleranceSpinBox">
|
||||
<property name="decimals">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>99999999.989999994635582</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="2" colspan="3">
|
||||
<spacer>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>311</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="5" column="5" colspan="2">
|
||||
<item row="4" column="2">
|
||||
<widget class="QComboBox" name="mSnappingMainDialogComboBox"/>
|
||||
</item>
|
||||
<item row="4" column="1" colspan="3">
|
||||
<widget class="QLabel" name="mVertexSearchRadiusVertexEditLabel">
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Search radius for vertex edits</string>
|
||||
<string>Snapping marker color</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1" colspan="2">
|
||||
<widget class="QLabel" name="mDefaultSnappingToleranceTextLabel">
|
||||
<property name="text">
|
||||
<string>Default snapping tolerance</string>
|
||||
</property>
|
||||
</widget>
|
||||
<item row="5" column="2">
|
||||
<widget class="QgsColorButton" name="mSnappingMarkerColorButton"/>
|
||||
</item>
|
||||
<item row="7" column="1" colspan="6">
|
||||
<item row="6" column="0" colspan="4">
|
||||
<widget class="QCheckBox" name="mSnappingTooltipsCheckbox">
|
||||
<property name="text">
|
||||
<string>Show snapping tooltips</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="0" colspan="4">
|
||||
<widget class="QCheckBox" name="mEnableSnappingOnInvisibleFeatureCheckbox">
|
||||
<property name="text">
|
||||
<string>Enable snapping on invisible features (not shown on the map canvas)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
@ -4326,8 +4333,8 @@ The bigger the number, the faster zooming with the mouse wheel will be.</string>
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>509</width>
|
||||
<height>623</height>
|
||||
<width>390</width>
|
||||
<height>539</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_39">
|
||||
@ -4595,8 +4602,8 @@ The bigger the number, the faster zooming with the mouse wheel will be.</string>
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>435</width>
|
||||
<height>402</height>
|
||||
<width>862</width>
|
||||
<height>838</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_6">
|
||||
@ -4764,8 +4771,8 @@ The bigger the number, the faster zooming with the mouse wheel will be.</string>
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>655</width>
|
||||
<height>768</height>
|
||||
<width>862</width>
|
||||
<height>838</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_33">
|
||||
@ -5533,7 +5540,6 @@ The bigger the number, the faster zooming with the mouse wheel will be.</string>
|
||||
<tabstop>mSearchRadiusVertexEditComboBox</tabstop>
|
||||
<tabstop>mSnappingMainDialogComboBox</tabstop>
|
||||
<tabstop>mSnappingMarkerColorButton</tabstop>
|
||||
<tabstop>mSnappingTooltipsCheckbox</tabstop>
|
||||
<tabstop>mMarkersOnlyForSelectedCheckBox</tabstop>
|
||||
<tabstop>mMarkerStyleComboBox</tabstop>
|
||||
<tabstop>mMarkerSizeSpinBox</tabstop>
|
||||
@ -5609,7 +5615,6 @@ The bigger the number, the faster zooming with the mouse wheel will be.</string>
|
||||
<include location="../../images/images.qrc"/>
|
||||
<include location="../../images/images.qrc"/>
|
||||
<include location="../../images/images.qrc"/>
|
||||
<include location="../../images/images.qrc"/>
|
||||
</resources>
|
||||
<connections>
|
||||
<connection>
|
||||
|
@ -24,7 +24,8 @@
|
||||
#include "qgsproject.h"
|
||||
#include "qgssnappingutils.h"
|
||||
#include "qgssnappingconfig.h"
|
||||
|
||||
#include "qgscategorizedsymbolrenderer.h"
|
||||
#include "qgssettings.h"
|
||||
|
||||
struct FilterExcludePoint : public QgsPointLocator::MatchFilter
|
||||
{
|
||||
@ -44,6 +45,7 @@ class TestQgsSnappingUtils : public QObject
|
||||
|
||||
private:
|
||||
QgsVectorLayer *mVL = nullptr;
|
||||
QgsFeature f1, f2;
|
||||
private slots:
|
||||
|
||||
void initTestCase()
|
||||
@ -60,16 +62,29 @@ class TestQgsSnappingUtils : public QObject
|
||||
// \ |
|
||||
// \|
|
||||
// + (1,0)
|
||||
mVL = new QgsVectorLayer( QStringLiteral( "Polygon" ), QStringLiteral( "x" ), QStringLiteral( "memory" ) );
|
||||
QgsFeature ff( 0 );
|
||||
mVL = new QgsVectorLayer( QStringLiteral( "Polygon?field=fld:int" ), QStringLiteral( "x" ), QStringLiteral( "memory" ) );
|
||||
int idx = mVL->fields().indexFromName( QStringLiteral( "fld" ) );
|
||||
QVERIFY( idx != -1 );
|
||||
f1.initAttributes( 1 );
|
||||
f2.initAttributes( 1 );
|
||||
|
||||
QgsPolygonXY polygon;
|
||||
QgsPolylineXY polyline;
|
||||
polyline << QgsPointXY( 0, 1 ) << QgsPointXY( 1, 0 ) << QgsPointXY( 1, 1 ) << QgsPointXY( 0, 1 );
|
||||
polygon << polyline;
|
||||
QgsGeometry polygonGeom = QgsGeometry::fromPolygonXY( polygon );
|
||||
ff.setGeometry( polygonGeom );
|
||||
f1.setGeometry( polygonGeom );
|
||||
f1.setAttribute( idx, QVariant( 2 ) );
|
||||
|
||||
polyline << QgsPointXY( 10, 11 ) << QgsPointXY( 11, 10 ) << QgsPointXY( 11, 11 ) << QgsPointXY( 10, 11 );
|
||||
polygon << polyline;
|
||||
polygonGeom = QgsGeometry::fromPolygonXY( polygon );
|
||||
f2.setGeometry( polygonGeom );
|
||||
f2.setAttribute( idx, QVariant( 20 ) );
|
||||
QgsFeatureList flist;
|
||||
flist << ff;
|
||||
flist << f1 << f2;
|
||||
|
||||
|
||||
mVL->dataProvider()->addFeatures( flist );
|
||||
|
||||
QgsProject::instance()->addMapLayer( mVL );
|
||||
@ -82,6 +97,13 @@ class TestQgsSnappingUtils : public QObject
|
||||
|
||||
void testSnapModeCurrent()
|
||||
{
|
||||
QgsSymbol *s1 = QgsSymbol::defaultSymbol( QgsWkbTypes::PolygonGeometry );
|
||||
QgsSymbol *s2 = QgsSymbol::defaultSymbol( QgsWkbTypes::PolygonGeometry );
|
||||
QgsRendererCategory c1( 2, s1, "f1", true );
|
||||
QgsRendererCategory c2( 20, s2, "f2", false );
|
||||
QgsCategoryList cl;
|
||||
cl << c1 << c2;
|
||||
|
||||
QgsMapSettings mapSettings;
|
||||
mapSettings.setOutputSize( QSize( 100, 100 ) );
|
||||
mapSettings.setExtent( QgsRectangle( 0, 0, 1, 1 ) );
|
||||
@ -89,6 +111,7 @@ class TestQgsSnappingUtils : public QObject
|
||||
|
||||
QgsSnappingUtils u;
|
||||
u.setMapSettings( mapSettings );
|
||||
u.setEnableSnappingForInvisibleFeature( false );
|
||||
u.setCurrentLayer( mVL );
|
||||
|
||||
// first try with no snapping enabled
|
||||
@ -99,7 +122,7 @@ class TestQgsSnappingUtils : public QObject
|
||||
snappingConfig.setMode( QgsSnappingConfig::ActiveLayer );
|
||||
u.setConfig( snappingConfig );
|
||||
|
||||
QgsPointLocator::Match m0 = u.snapToMap( QPoint( 100, 100 ) );
|
||||
QgsPointLocator::Match m0 = u.snapToMap( QPoint( 2, 2 ) );
|
||||
QVERIFY( !m0.isValid() );
|
||||
QVERIFY( !m0.hasVertex() );
|
||||
|
||||
@ -108,10 +131,16 @@ class TestQgsSnappingUtils : public QObject
|
||||
snappingConfig.setType( QgsSnappingConfig::Vertex );
|
||||
u.setConfig( snappingConfig );
|
||||
|
||||
QgsPointLocator::Match m = u.snapToMap( QPoint( 100, 100 ) );
|
||||
QgsPointLocator::Match m = u.snapToMap( QPoint( 11, 11 ) );
|
||||
QVERIFY( !m.isValid() );
|
||||
QVERIFY( !m.hasVertex() );
|
||||
|
||||
u.setEnableSnappingForInvisibleFeature( true );
|
||||
mVL->styleChanged();
|
||||
m = u.snapToMap( QPoint( 2, 2 ) );
|
||||
QVERIFY( m.isValid() );
|
||||
QVERIFY( m.hasVertex() );
|
||||
QCOMPARE( m.point(), QgsPointXY( 1, 0 ) );
|
||||
QCOMPARE( m.point(), QgsPointXY( 0, 1 ) );
|
||||
|
||||
QgsPointLocator::Match m2 = u.snapToMap( QPoint( 0, 100 ) );
|
||||
QVERIFY( !m2.isValid() );
|
||||
@ -127,6 +156,8 @@ class TestQgsSnappingUtils : public QObject
|
||||
FilterExcludePoint myFilter( QgsPointXY( 1, 0 ) );
|
||||
QgsPointLocator::Match m3 = u.snapToMap( QPoint( 100, 100 ), &myFilter );
|
||||
QVERIFY( !m3.isValid() );
|
||||
|
||||
|
||||
}
|
||||
|
||||
void testSnapModeAll()
|
||||
|
Loading…
x
Reference in New Issue
Block a user