From 4081bea801909ef98c4dbcf64dcdb3d8191c2c90 Mon Sep 17 00:00:00 2001 From: Julien Cabieces Date: Tue, 3 Sep 2019 14:45:42 +0200 Subject: [PATCH] Use TaskManager to build index --- .../auto_generated/qgspointlocator.sip.in | 12 ++---- .../auto_generated/qgssnappingutils.sip.in | 10 +++-- .../qgsmapcanvassnappingutils.sip.in | 6 --- src/core/CMakeLists.txt | 2 + src/core/qgspointlocator.cpp | 43 ++++++++++--------- src/core/qgspointlocator.h | 18 +++----- src/core/qgssnappingutils.cpp | 9 ---- src/core/qgssnappingutils.h | 21 ++++----- src/gui/qgsmapcanvassnappingutils.cpp | 16 ------- src/gui/qgsmapcanvassnappingutils.h | 5 --- .../app/testqgsmaptooltrimextendfeature.cpp | 1 + 11 files changed, 52 insertions(+), 91 deletions(-) diff --git a/python/core/auto_generated/qgspointlocator.sip.in b/python/core/auto_generated/qgspointlocator.sip.in index d209e7043f0..dfc858f0ca5 100644 --- a/python/core/auto_generated/qgspointlocator.sip.in +++ b/python/core/auto_generated/qgspointlocator.sip.in @@ -42,10 +42,9 @@ do the searches on data reprojected to the given CRS. For accurate reprojection to set the correct ``transformContext`` if a ``destinationCrs`` is specified. This is usually taken from the current :py:func:`QgsProject.transformContext()` -:param asynchronous: if ``False``, point locator init() method will block until index is completely - finished. if ``True``, index building will be done in another thread and init() method returns - immediatly. initStarted() and initFinished() signals can be used to control current state of - the point locator. +:param asynchronous: if ``False``, point locator init() method will block until point locator index + is completely built. if ``True``, index building will be done in another thread and init() method returns + immediately. initFinished() signal will be emitted once the initialization is over. If ``extent`` is not ``None``, the locator will index only a subset of the layer which falls within that extent. %End @@ -246,11 +245,6 @@ Emitted whenever index has been built and initialization is finished features, otherwise ``True`` %End - void initStarted(); -%Docstring -Emitted whenever index initialization has started -%End - protected: bool rebuildIndex( int maxFeaturesToIndex = -1 ); protected slots: diff --git a/python/core/auto_generated/qgssnappingutils.sip.in b/python/core/auto_generated/qgssnappingutils.sip.in index d9006ec5696..c1fa1f4136b 100644 --- a/python/core/auto_generated/qgssnappingutils.sip.in +++ b/python/core/auto_generated/qgssnappingutils.sip.in @@ -177,13 +177,15 @@ Emitted when the snapping settings object changes. %End protected: - virtual void prepareIndexStarting(); + + virtual void prepareIndexStarting( int count ); %Docstring -Called when starting to index +This methods is now deprecated and never called %End - virtual void prepareIndexFinished(); + + virtual void prepareIndexProgress( int index ); %Docstring -Called when finished indexing a layer +This methods is now deprecated and never called %End void clearAllLocators(); diff --git a/python/gui/auto_generated/qgsmapcanvassnappingutils.sip.in b/python/gui/auto_generated/qgsmapcanvassnappingutils.sip.in index a4f95ef5015..e6824a3f007 100644 --- a/python/gui/auto_generated/qgsmapcanvassnappingutils.sip.in +++ b/python/gui/auto_generated/qgsmapcanvassnappingutils.sip.in @@ -25,12 +25,6 @@ Snapping utils instance that is connected to a canvas and updates the configurat public: QgsMapCanvasSnappingUtils( QgsMapCanvas *canvas, QObject *parent = 0 ); - protected: - virtual void prepareIndexStarting(); - - virtual void prepareIndexFinished(); - - }; diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 828bdb6faf3..c1386d01f9d 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -317,6 +317,7 @@ SET(QGIS_CORE_SRCS qgspluginlayerregistry.cpp qgspointxy.cpp qgspointlocator.cpp + qgspointlocatorinittask.cpp qgsproject.cpp qgsprojectbadlayerhandler.cpp qgsprojectfiletransform.cpp @@ -708,6 +709,7 @@ SET(QGIS_CORE_MOC_HDRS qgspluginlayer.h qgspointxy.h qgspointlocator.h + qgspointlocatorinittask.h qgsproject.h qgsproxyprogresstask.h qgsrelationmanager.h diff --git a/src/core/qgspointlocator.cpp b/src/core/qgspointlocator.cpp index 195d0ee3202..8acc2a922dc 100644 --- a/src/core/qgspointlocator.cpp +++ b/src/core/qgspointlocator.cpp @@ -22,9 +22,11 @@ #include "qgis.h" #include "qgslogger.h" #include "qgsrenderer.h" +#include "qgsapplication.h" #include "qgsvectorlayerfeatureiterator.h" #include "qgsexpressioncontextutils.h" #include "qgslinestring.h" +#include "qgspointlocatorinittask.h" #include #include @@ -543,8 +545,6 @@ QgsPointLocator::QgsPointLocator( QgsVectorLayer *layer, const QgsCoordinateRefe connect( mLayer, &QgsVectorLayer::geometryChanged, this, &QgsPointLocator::onGeometryChanged ); connect( mLayer, &QgsVectorLayer::attributeValueChanged, this, &QgsPointLocator::onAttributeValueChanged ); connect( mLayer, &QgsVectorLayer::dataChanged, this, &QgsPointLocator::destroyIndex ); - - connect( &mFutureWatcher, &QFutureWatcher::finished, this, &QgsPointLocator::onRebuildIndexFinished ); } @@ -560,8 +560,8 @@ QgsCoordinateReferenceSystem QgsPointLocator::destinationCrs() const void QgsPointLocator::setExtent( const QgsRectangle *extent ) { - if ( mFuture.isRunning() ) - // already running, return! + if ( mIsIndexing ) + // already indexing, return! return; mExtent.reset( extent ? new QgsRectangle( *extent ) : nullptr ); @@ -571,8 +571,8 @@ void QgsPointLocator::setExtent( const QgsRectangle *extent ) void QgsPointLocator::setRenderContext( const QgsRenderContext *context ) { - if ( mFuture.isRunning() ) - // already running, return! + if ( mIsIndexing ) + // already indexing, return! return; disconnect( mLayer, &QgsVectorLayer::styleChanged, this, &QgsPointLocator::destroyIndex ); @@ -588,10 +588,10 @@ void QgsPointLocator::setRenderContext( const QgsRenderContext *context ) } - -void QgsPointLocator::onRebuildIndexFinished() +void QgsPointLocator::onRebuildIndexFinished( bool ok ) { - emit initFinished( mFuture.result() ); + mIsIndexing = false; + emit initFinished( ok ); } void QgsPointLocator::init( int maxFeaturesToIndex ) @@ -599,7 +599,7 @@ void QgsPointLocator::init( int maxFeaturesToIndex ) const QgsWkbTypes::GeometryType geomType = mLayer->geometryType(); if ( geomType == QgsWkbTypes::NullGeometry // nothing to index || hasIndex() - || mFuture.isRunning() ) // already running, return! + || mIsIndexing ) // already indexing, return! return; mRenderer.reset( mLayer->renderer() ? mLayer->renderer()->clone() : nullptr ); @@ -609,23 +609,26 @@ void QgsPointLocator::init( int maxFeaturesToIndex ) mContext->expressionContext() << QgsExpressionContextUtils::layerScope( mLayer ); } - emit initStarted(); + mIsIndexing = true; if ( mAsynchronous ) { - mFuture = QtConcurrent::run( this, &QgsPointLocator::rebuildIndex, maxFeaturesToIndex ); - mFutureWatcher.setFuture( mFuture ); + QgsPointLocatorInitTask *task = new QgsPointLocatorInitTask( this ); + connect( task, &QgsPointLocatorInitTask::rebuildIndexFinished, this, &QgsPointLocator::onRebuildIndexFinished ); + connect( task, &QgsPointLocatorInitTask::taskTerminated, this, [ = ] { mIsIndexing = false; } ); + QgsApplication::taskManager()->addTask( task ); } else { const bool ok = rebuildIndex( maxFeaturesToIndex ); + mIsIndexing = false; emit initFinished( ok ); } } bool QgsPointLocator::hasIndex() const { - return mFuture.isRunning() || mRTree || mIsEmptyLayer; + return mIsIndexing || mRTree || mIsEmptyLayer; } @@ -876,7 +879,7 @@ void QgsPointLocator::onAttributeValueChanged( QgsFeatureId fid, int idx, const QgsPointLocator::Match QgsPointLocator::nearestVertex( const QgsPointXY &point, double tolerance, MatchFilter *filter ) { - if ( mFuture.isRunning() ) + if ( mIsIndexing ) return Match(); if ( !mRTree ) @@ -897,7 +900,7 @@ QgsPointLocator::Match QgsPointLocator::nearestVertex( const QgsPointXY &point, QgsPointLocator::Match QgsPointLocator::nearestEdge( const QgsPointXY &point, double tolerance, MatchFilter *filter ) { - if ( mFuture.isRunning() ) + if ( mIsIndexing ) return Match(); if ( !mRTree ) @@ -922,7 +925,7 @@ QgsPointLocator::Match QgsPointLocator::nearestEdge( const QgsPointXY &point, do QgsPointLocator::Match QgsPointLocator::nearestArea( const QgsPointXY &point, double tolerance, MatchFilter *filter ) { - if ( mFuture.isRunning() ) + if ( mIsIndexing ) return Match(); if ( !mRTree ) @@ -959,7 +962,7 @@ QgsPointLocator::Match QgsPointLocator::nearestArea( const QgsPointXY &point, do QgsPointLocator::MatchList QgsPointLocator::edgesInRect( const QgsRectangle &rect, QgsPointLocator::MatchFilter *filter ) { - if ( mFuture.isRunning() ) + if ( mIsIndexing ) return MatchList(); if ( !mRTree ) @@ -988,7 +991,7 @@ QgsPointLocator::MatchList QgsPointLocator::edgesInRect( const QgsPointXY &point QgsPointLocator::MatchList QgsPointLocator::verticesInRect( const QgsRectangle &rect, QgsPointLocator::MatchFilter *filter ) { - if ( mFuture.isRunning() ) + if ( mIsIndexing ) return MatchList(); if ( !mRTree ) @@ -1014,7 +1017,7 @@ QgsPointLocator::MatchList QgsPointLocator::verticesInRect( const QgsPointXY &po QgsPointLocator::MatchList QgsPointLocator::pointInPolygon( const QgsPointXY &point ) { - if ( mFuture.isRunning() ) + if ( mIsIndexing ) return MatchList(); if ( !mRTree ) diff --git a/src/core/qgspointlocator.h b/src/core/qgspointlocator.h index 0ea5736ceb8..308be8ff313 100644 --- a/src/core/qgspointlocator.h +++ b/src/core/qgspointlocator.h @@ -68,10 +68,9 @@ class CORE_EXPORT QgsPointLocator : public QObject * to set the correct \a transformContext if a \a destinationCrs is specified. This is usually taken * from the current QgsProject::transformContext(). * - * \param asynchronous if FALSE, point locator init() method will block until index is completely - * finished. if TRUE, index building will be done in another thread and init() method returns - * immediatly. initStarted() and initFinished() signals can be used to control current state of - * the point locator. + * \param asynchronous if FALSE, point locator init() method will block until point locator index + * is completely built. if TRUE, index building will be done in another thread and init() method returns + * immediately. initFinished() signal will be emitted once the initialization is over. * * If \a extent is not NULLPTR, the locator will index only a subset of the layer which falls within that extent. */ @@ -301,17 +300,12 @@ class CORE_EXPORT QgsPointLocator : public QObject */ void initFinished( bool ok ); - /** - * Emitted whenever index initialization has started - */ - void initStarted(); - protected: bool rebuildIndex( int maxFeaturesToIndex = -1 ); protected slots: void destroyIndex(); private slots: - void onRebuildIndexFinished(); + void onRebuildIndexFinished( bool ok ); void onFeatureAdded( QgsFeatureId fid ); void onFeatureDeleted( QgsFeatureId fid ); void onGeometryChanged( QgsFeatureId fid, const QgsGeometry &geom ); @@ -335,16 +329,16 @@ class CORE_EXPORT QgsPointLocator : public QObject std::unique_ptr mContext; std::unique_ptr mRenderer; - QFuture mFuture; - QFutureWatcher mFutureWatcher; int mMaxFeaturesToIndex = -1; bool mAsynchronous = false; + bool mIsIndexing = false; friend class QgsPointLocator_VisitorNearestVertex; friend class QgsPointLocator_VisitorNearestEdge; friend class QgsPointLocator_VisitorArea; friend class QgsPointLocator_VisitorEdgesInRect; friend class QgsPointLocator_VisitorVerticesInRect; + friend class QgsPointLocatorInitTask; }; diff --git a/src/core/qgssnappingutils.cpp b/src/core/qgssnappingutils.cpp index 7f15fa4476a..1497e5ecca5 100644 --- a/src/core/qgssnappingutils.cpp +++ b/src/core/qgssnappingutils.cpp @@ -45,7 +45,6 @@ QgsPointLocator *QgsSnappingUtils::locatorForLayer( QgsVectorLayer *vl ) { QgsPointLocator *vlpl = new QgsPointLocator( vl, destinationCrs(), mMapSettings.transformContext(), nullptr, mAsynchronous ); connect( vlpl, &QgsPointLocator::initFinished, this, &QgsSnappingUtils::onInitFinished ); - connect( vlpl, &QgsPointLocator::initStarted, this, &QgsSnappingUtils::onInitStarted ); mLocators.insert( vl, vlpl ); } return mLocators.value( vl ); @@ -80,7 +79,6 @@ QgsPointLocator *QgsSnappingUtils::temporaryLocatorForLayer( QgsVectorLayer *vl, pointMap.x() + tolerance, pointMap.y() + tolerance ); QgsPointLocator *vlpl = new QgsPointLocator( vl, destinationCrs(), mMapSettings.transformContext(), &rect, mAsynchronous ); connect( vlpl, &QgsPointLocator::initFinished, this, &QgsSnappingUtils::onInitFinished ); - connect( vlpl, &QgsPointLocator::initStarted, this, &QgsSnappingUtils::onInitStarted ); mTemporaryLocators.insert( vl, vlpl ); return mTemporaryLocators.value( vl ); @@ -355,13 +353,6 @@ void QgsSnappingUtils::onInitFinished( bool ok ) { mHybridMaxAreaPerLayer[loc->layer()->id()] /= 4; } - - prepareIndexFinished(); -} - -void QgsSnappingUtils::onInitStarted() -{ - prepareIndexStarting(); } void QgsSnappingUtils::prepareIndex( const QList &layers ) diff --git a/src/core/qgssnappingutils.h b/src/core/qgssnappingutils.h index f251a5a303f..1384e70f912 100644 --- a/src/core/qgssnappingutils.h +++ b/src/core/qgssnappingutils.h @@ -196,10 +196,16 @@ class CORE_EXPORT QgsSnappingUtils : public QObject void configChanged( const QgsSnappingConfig &snappingConfig ); protected: - //! Called when starting to index - virtual void prepareIndexStarting() {} - //! Called when finished indexing a layer - virtual void prepareIndexFinished() {} + + /** + * This methods is now deprecated and never called + */ + Q_DECL_DEPRECATED virtual void prepareIndexStarting( int count ) { Q_UNUSED( count ); } + + /** + * This methods is now deprecated and never called + */ + Q_DECL_DEPRECATED virtual void prepareIndexProgress( int index ) { Q_UNUSED( index ); } //! Deletes all existing locators (e.g. when destination CRS has changed and we need to reindex) void clearAllLocators(); @@ -209,9 +215,6 @@ class CORE_EXPORT QgsSnappingUtils : public QObject //! called whenever a point locator has finished void onInitFinished( bool ok ); - //! called whenever a point locator has started - void onInitStarted(); - private: void onIndividualLayerSettingsChanged( const QHash &layerSettings ); //! Gets destination CRS from map settings, or an invalid CRS if projections are disabled @@ -266,13 +269,11 @@ class CORE_EXPORT QgsSnappingUtils : public QObject //! Disable or not the snapping on all features. By default is always TRUE except for non visible features on map canvas. bool mEnableSnappingForInvisibleFeature = true; - //! Number of index currently being prepared - int mPreparingIndexCount = 0; - //! true if we have to build point locator asynchronously bool mAsynchronous = false; friend class TestQgsVertexTool; + friend class TestQgsMapToolTrimExtendFeature; }; diff --git a/src/gui/qgsmapcanvassnappingutils.cpp b/src/gui/qgsmapcanvassnappingutils.cpp index 2d026bc8126..560d3842858 100644 --- a/src/gui/qgsmapcanvassnappingutils.cpp +++ b/src/gui/qgsmapcanvassnappingutils.cpp @@ -58,19 +58,3 @@ void QgsMapCanvasSnappingUtils::canvasMapToolChanged() { setEnableSnappingForInvisibleFeature( QgsSettings().value( QStringLiteral( "/qgis/digitizing/snap_invisible_feature" ), false ).toBool() ); } - -void QgsMapCanvasSnappingUtils::prepareIndexStarting() -{ - if ( !mPreparingIndexCount ) - QApplication::setOverrideCursor( Qt::BusyCursor ); - - mPreparingIndexCount++; -} - -void QgsMapCanvasSnappingUtils::prepareIndexFinished() -{ - mPreparingIndexCount--; - - if ( !mPreparingIndexCount ) - QApplication::restoreOverrideCursor(); -} diff --git a/src/gui/qgsmapcanvassnappingutils.h b/src/gui/qgsmapcanvassnappingutils.h index d00c4e71996..306aa9fdb91 100644 --- a/src/gui/qgsmapcanvassnappingutils.h +++ b/src/gui/qgsmapcanvassnappingutils.h @@ -36,10 +36,6 @@ class GUI_EXPORT QgsMapCanvasSnappingUtils : public QgsSnappingUtils public: QgsMapCanvasSnappingUtils( QgsMapCanvas *canvas, QObject *parent = nullptr ); - protected: - void prepareIndexStarting() override; - void prepareIndexFinished() override; - private slots: void canvasMapSettingsChanged(); void canvasTransformContextChanged(); @@ -49,7 +45,6 @@ class GUI_EXPORT QgsMapCanvasSnappingUtils : public QgsSnappingUtils private: QgsMapCanvas *mCanvas = nullptr; QProgressDialog *mProgress = nullptr; - int mPreparingIndexCount = 0; }; diff --git a/tests/src/app/testqgsmaptooltrimextendfeature.cpp b/tests/src/app/testqgsmaptooltrimextendfeature.cpp index b48a878eebf..a35baa4fee6 100644 --- a/tests/src/app/testqgsmaptooltrimextendfeature.cpp +++ b/tests/src/app/testqgsmaptooltrimextendfeature.cpp @@ -164,6 +164,7 @@ class TestQgsMapToolTrimExtendFeature : public QObject mapSettings.setLayers( QList() << vlPolygon.get() << vlMultiLine.get() << vlLineZ.get() << vlTopoEdit.get() << vlTopoLimit.get() ); QgsSnappingUtils *mSnappingUtils = new QgsMapCanvasSnappingUtils( mCanvas, this ); + mSnappingUtils->mAsynchronous = false; QgsSnappingConfig snappingConfig = mSnappingUtils->config(); mSnappingUtils->setMapSettings( mapSettings ); snappingConfig.setEnabled( true );