Skip to content
Permalink
Browse files

Raster MTR improvements - part one (PR #3334)

  • Loading branch information
wonder-sk committed Aug 2, 2016
2 parents f9fabb8 + a89fea1 commit 9db93046272a428629e539a915a7a459403433bd
Showing with 429 additions and 140 deletions.
  1. +1 −0 doc/api_break.dox
  2. +1 −0 python/core/core.sip
  3. +43 −0 python/core/qgsfeedback.sip
  4. +4 −0 python/core/qgsmaplayerrenderer.sip
  5. +1 −1 python/core/raster/qgsbrightnesscontrastfilter.sip
  6. +1 −1 python/core/raster/qgshillshaderenderer.sip
  7. +1 −1 python/core/raster/qgshuesaturationfilter.sip
  8. +1 −1 python/core/raster/qgsmultibandcolorrenderer.sip
  9. +1 −1 python/core/raster/qgspalettedrasterrenderer.sip
  10. +2 −2 python/core/raster/qgsrasterdataprovider.sip
  11. +2 −2 python/core/raster/qgsrasterdrawer.sip
  12. +16 −1 python/core/raster/qgsrasterinterface.sip
  13. +2 −1 python/core/raster/qgsrasteriterator.sip
  14. +1 −1 python/core/raster/qgsrasternuller.sip
  15. +1 −1 python/core/raster/qgsrasterprojector.sip
  16. +1 −1 python/core/raster/qgsrasterrenderer.sip
  17. +1 −1 python/core/raster/qgsrasterresamplefilter.sip
  18. +1 −1 python/core/raster/qgssinglebandcolordatarenderer.sip
  19. +1 −1 python/core/raster/qgssinglebandgrayrenderer.sip
  20. +1 −1 python/core/raster/qgssinglebandpseudocolorrenderer.sip
  21. +8 −0 src/app/main.cpp
  22. +1 −0 src/core/CMakeLists.txt
  23. +73 −0 src/core/qgsfeedback.h
  24. +6 −0 src/core/qgsmaplayerrenderer.h
  25. +3 −0 src/core/qgsmaprenderercustompainterjob.cpp
  26. +3 −0 src/core/qgsmaprendererparalleljob.cpp
  27. +2 −2 src/core/raster/qgsbrightnesscontrastfilter.cpp
  28. +1 −1 src/core/raster/qgsbrightnesscontrastfilter.h
  29. +3 −3 src/core/raster/qgshillshaderenderer.cpp
  30. +1 −1 src/core/raster/qgshillshaderenderer.h
  31. +2 −2 src/core/raster/qgshuesaturationfilter.cpp
  32. +1 −1 src/core/raster/qgshuesaturationfilter.h
  33. +2 −2 src/core/raster/qgsmultibandcolorrenderer.cpp
  34. +1 −1 src/core/raster/qgsmultibandcolorrenderer.h
  35. +3 −3 src/core/raster/qgspalettedrasterrenderer.cpp
  36. +1 −1 src/core/raster/qgspalettedrasterrenderer.h
  37. +3 −3 src/core/raster/qgsrasterdataprovider.cpp
  38. +3 −3 src/core/raster/qgsrasterdataprovider.h
  39. +7 −3 src/core/raster/qgsrasterdrawer.cpp
  40. +3 −2 src/core/raster/qgsrasterdrawer.h
  41. +14 −1 src/core/raster/qgsrasterinterface.h
  42. +4 −2 src/core/raster/qgsrasteriterator.cpp
  43. +4 −1 src/core/raster/qgsrasteriterator.h
  44. +9 −2 src/core/raster/qgsrasterlayerrenderer.cpp
  45. +5 −0 src/core/raster/qgsrasterlayerrenderer.h
  46. +2 −2 src/core/raster/qgsrasternuller.cpp
  47. +1 −1 src/core/raster/qgsrasternuller.h
  48. +2 −1 src/core/raster/qgsrasterpipe.h
  49. +3 −3 src/core/raster/qgsrasterprojector.cpp
  50. +1 −1 src/core/raster/qgsrasterprojector.h
  51. +1 −1 src/core/raster/qgsrasterrenderer.h
  52. +3 −3 src/core/raster/qgsrasterresamplefilter.cpp
  53. +1 −1 src/core/raster/qgsrasterresamplefilter.h
  54. +2 −2 src/core/raster/qgssinglebandcolordatarenderer.cpp
  55. +1 −1 src/core/raster/qgssinglebandcolordatarenderer.h
  56. +3 −3 src/core/raster/qgssinglebandgrayrenderer.cpp
  57. +1 −1 src/core/raster/qgssinglebandgrayrenderer.h
  58. +3 −3 src/core/raster/qgssinglebandpseudocolorrenderer.cpp
  59. +1 −1 src/core/raster/qgssinglebandpseudocolorrenderer.h
  60. +3 −1 src/providers/arcgisrest/qgsamsprovider.cpp
  61. +1 −1 src/providers/arcgisrest/qgsamsprovider.h
  62. +5 −4 src/providers/gdal/qgsgdalprovider.cpp
  63. +2 −2 src/providers/gdal/qgsgdalprovider.h
  64. +28 −1 src/providers/gdal/qgsgdalproviderbase.cpp
  65. +1 −1 src/providers/gdal/qgsgdalproviderbase.h
  66. +2 −1 src/providers/grass/qgsgrassrasterprovider.cpp
  67. +1 −1 src/providers/grass/qgsgrassrasterprovider.h
  68. +42 −26 src/providers/wcs/qgswcsprovider.cpp
  69. +4 −3 src/providers/wcs/qgswcsprovider.h
  70. +57 −18 src/providers/wms/qgswmsprovider.cpp
  71. +7 −3 src/providers/wms/qgswmsprovider.h
  72. +5 −2 tests/src/python/utilities.py
@@ -414,6 +414,7 @@ be returned instead of a null pointer if no transformation is required.</li>
<ul>
<li>srcDataType() has been renamed to sourceDataType()</li>
<li>srcInput() has been renamed to sourceInput()</li>
<li>block() has new "feedback" argument.</li>
</ul>

\subsection qgis_api_break_3_0_QgsRelation QgsRelation
@@ -54,6 +54,7 @@
%Include qgsfeaturefilterprovider.sip
%Include qgsfeatureiterator.sip
%Include qgsfeaturerequest.sip
%Include qgsfeedback.sip
%Include qgsfield.sip
%Include qgsgeometrysimplifier.sip
%Include qgsgeometryvalidator.sip
@@ -0,0 +1,43 @@

/** \ingroup core
* Base class for feedback objects to be used for cancellation of something running in a worker thread.
* The class may be used as is or it may be subclassed for extended functionality
* for a particular operation (e.g. report progress or pass some data for preview).
*
* When cancel() is called, the internal code has two options to check for cancellation state:
* - if the worker thread uses an event loop (e.g. for network communication), the code can
* make a queued connection to cancelled() signal and handle the cancellation in its slot.
* - if the worker thread does not use an event loop, it can poll isCancelled() method regularly
* to see if the operation should be cancelled.
*
* The class is meant to be created and destroyed in the main thread.
*
* For map rendering, the object may be created in constructor of a QgsMapLayerRenderer
* subclass and available with QgsMapLayerRenderer::feedback() method. When a map rendering job
* gets cancelled, the cancel() method is called on the feedback object of all layers.
*
* @note added in QGIS 3.0
*/
class QgsFeedback : QObject
{
%TypeHeaderCode
#include <qgsfeedback.h>
%End

public:
//! Construct a feedback object
QgsFeedback( QObject* parent /TransferThis/ = nullptr );

virtual ~QgsFeedback();

//! Tells the internal routines that the current operation should be cancelled. This should be run by the main thread
void cancel();

//! Tells whether the operation has been cancelled already
bool isCancelled() const;

signals:
//! Internal routines can connect to this signal if they use event loop
void cancelled();

};
@@ -12,6 +12,10 @@ class QgsMapLayerRenderer
//! Do the rendering (based on data stored in the class)
virtual bool render() = 0;

//! Access to feedback object of the layer renderer (may be null)
//! @note added in QGIS 3.0
virtual QgsFeedback* feedback() const;

//! Return list of errors (problems) that happened during the rendering
QStringList errors() const;

@@ -15,7 +15,7 @@ class QgsBrightnessContrastFilter : QgsRasterInterface

bool setInput( QgsRasterInterface* input );

QgsRasterBlock *block( int bandNo, const QgsRectangle &extent, int width, int height );
QgsRasterBlock *block( int bandNo, const QgsRectangle &extent, int width, int height, QgsRasterBlockFeedback* feedback = nullptr ) /Factory/;

void setBrightness( int brightness );
int brightness() const;
@@ -31,7 +31,7 @@ class QgsHillshadeRenderer : QgsRasterRenderer
*/
static QgsRasterRenderer* create( const QDomElement& elem, QgsRasterInterface* input ) /Factory/;

QgsRasterBlock *block( int bandNo, const QgsRectangle & extent, int width, int height ) /Factory/;
QgsRasterBlock *block( int bandNo, const QgsRectangle & extent, int width, int height, QgsRasterBlockFeedback* feedback = nullptr ) /Factory/;

void writeXml( QDomDocument& doc, QDomElement& parentElem ) const;

@@ -25,7 +25,7 @@ class QgsHueSaturationFilter : QgsRasterInterface

bool setInput( QgsRasterInterface* input );

QgsRasterBlock *block( int bandNo, const QgsRectangle &extent, int width, int height );
QgsRasterBlock *block( int bandNo, const QgsRectangle &extent, int width, int height, QgsRasterBlockFeedback* feedback = nullptr ) /Factory/;

void setSaturation( int saturation );
int saturation() const;
@@ -12,7 +12,7 @@ class QgsMultiBandColorRenderer: QgsRasterRenderer

static QgsRasterRenderer* create( const QDomElement& elem, QgsRasterDataProvider* provider ) /Factory/;

QgsRasterBlock* block( int bandNo, const QgsRectangle & extent, int width, int height ) /Factory/;
QgsRasterBlock* block( int bandNo, const QgsRectangle & extent, int width, int height, QgsRasterBlockFeedback* feedback = nullptr ) /Factory/;

int redBand() const;
void setRedBand( int band );
@@ -10,7 +10,7 @@ class QgsPalettedRasterRenderer : QgsRasterRenderer
virtual QgsPalettedRasterRenderer * clone() const /Factory/;
static QgsRasterRenderer* create( const QDomElement& elem, QgsRasterInterface* input ) /Factory/;

QgsRasterBlock *block( int bandNo, const QgsRectangle & extent, int width, int height ) /Factory/;
QgsRasterBlock *block( int bandNo, const QgsRectangle & extent, int width, int height, QgsRasterBlockFeedback* feedback = nullptr ) /Factory/;

/** Returns number of colors*/
int nColors() const;
@@ -102,7 +102,7 @@ class QgsRasterDataProvider : QgsDataProvider, QgsRasterInterface
virtual int ySize() const;

/** Read block of data using given extent and size. */
virtual QgsRasterBlock *block( int theBandNo, const QgsRectangle &theExtent, int theWidth, int theHeight ) / Factory /;
virtual QgsRasterBlock *block( int theBandNo, const QgsRectangle &theExtent, int theWidth, int theHeight, QgsRasterBlockFeedback* feedback = nullptr ) / Factory /;

/** Return true if source band has no data value */
virtual bool sourceHasNoDataValue( int bandNo ) const;
@@ -306,7 +306,7 @@ class QgsRasterDataProvider : QgsDataProvider, QgsRasterInterface
/** Read block of data using give extent and size
* @note not available in python bindings
*/
//virtual void readBlock( int bandNo, QgsRectangle const & viewExtent, int width, int height, void *data );
//virtual void readBlock( int bandNo, QgsRectangle const & viewExtent, int width, int height, void *data, QgsRasterBlockFeedback* feedback = nullptr );

/** Returns true if user no data contains value */
bool userNoDataValuesContains( int bandNo, double value ) const;
@@ -13,9 +13,9 @@ class QgsRasterDrawer
* @param p destination QPainter
* @param viewPort viewport to render
* @param theQgsMapToPixel map to pixel convertor
* @param ctx render context
* @param feedback optional raster feedback object for cancellation/preview. Added in QGIS 3.0.
*/
void draw( QPainter* p, QgsRasterViewPort* viewPort, const QgsMapToPixel* theQgsMapToPixel, const QgsRenderContext *ctx = nullptr );
void draw( QPainter* p, QgsRasterViewPort* viewPort, const QgsMapToPixel* theQgsMapToPixel, QgsRasterBlockFeedback* feedback = nullptr );

protected:
/** Draws raster part
@@ -1,4 +1,18 @@

/** \ingroup core
* Feedback object tailored for raster block reading.
*
* @note added in QGIS 3.0
*/
class QgsRasterBlockFeedback : QgsFeedback
{
%TypeHeaderCode
#include <qgsrasterinterface.h>
%End
// TODO: extend with preview functionality??
};


/** Base class for processing modules.
*
*/
@@ -129,8 +143,9 @@ class QgsRasterInterface
* @param extent extent of block
* @param width pixel width of block
* @param height pixel height of block
* @param feedback optional raster feedback object for cancellation/preview. Added in QGIS 3.0.
*/
virtual QgsRasterBlock *block( int bandNo, const QgsRectangle &extent, int width, int height ) = 0 /Factory/;
virtual QgsRasterBlock *block( int bandNo, const QgsRectangle &extent, int width, int height, QgsRasterBlockFeedback* feedback = nullptr ) = 0 /Factory/;

/** Set input.
* Returns true if set correctly, false if cannot use that input */
@@ -12,8 +12,9 @@ class QgsRasterIterator
@param nCols number of columns
@param nRows number of rows
@param extent area to read
@param feedback optional raster feedback object for cancellation/preview. Added in QGIS 3.0.
*/
void startRasterRead( int bandNumber, int nCols, int nRows, const QgsRectangle& extent );
void startRasterRead( int bandNumber, int nCols, int nRows, const QgsRectangle& extent, QgsRasterBlockFeedback* feedback = nullptr );

/** Fetches next part of raster data, caller takes ownership of the block and
caller should delete the block.
@@ -19,7 +19,7 @@ class QgsRasterNuller : QgsRasterInterface

Qgis::DataType dataType( int bandNo ) const;

QgsRasterBlock *block( int bandNo, const QgsRectangle &extent, int width, int height ) / Factory /;
QgsRasterBlock *block( int bandNo, const QgsRectangle &extent, int width, int height, QgsRasterBlockFeedback* feedback = nullptr ) / Factory /;

void setNoData( int bandNo, const QgsRasterRangeList& noData );

@@ -74,7 +74,7 @@ class QgsRasterProjector : QgsRasterInterface
// Translated precision mode, for use in ComboBox etc.
static QString precisionLabel( Precision precision );

QgsRasterBlock *block( int bandNo, const QgsRectangle & extent, int width, int height ) / Factory /;
QgsRasterBlock *block( int bandNo, const QgsRectangle & extent, int width, int height, QgsRasterBlockFeedback* feedback = nullptr ) / Factory /;

/** Calculate destination extent and size from source extent and size */
bool destExtentSize( const QgsRectangle& theSrcExtent, int theSrcXSize, int theSrcYSize,
@@ -38,7 +38,7 @@ class QgsRasterRenderer : QgsRasterInterface

virtual bool setInput( QgsRasterInterface* input );

virtual QgsRasterBlock *block( int bandNo, const QgsRectangle &extent, int width, int height ) = 0 / Factory /;
virtual QgsRasterBlock *block( int bandNo, const QgsRectangle &extent, int width, int height, QgsRasterBlockFeedback* feedback = nullptr ) = 0 / Factory /;

bool usesTransparency() const;

@@ -19,7 +19,7 @@ class QgsRasterResampleFilter : QgsRasterInterface

bool setInput( QgsRasterInterface* input );

QgsRasterBlock *block( int bandNo, const QgsRectangle &extent, int width, int height ) /Factory/;
QgsRasterBlock *block( int bandNo, const QgsRectangle &extent, int width, int height, QgsRasterBlockFeedback* feedback = nullptr ) /Factory/;

/** Set resampler for zoomed in scales. Takes ownership of the object*/
void setZoomedInResampler( QgsRasterResampler* r /Transfer/ );
@@ -12,7 +12,7 @@ class QgsSingleBandColorDataRenderer: QgsRasterRenderer

bool setInput( QgsRasterInterface* input );

QgsRasterBlock* block( int bandNo, const QgsRectangle & extent, int width, int height ) / Factory /;
QgsRasterBlock* block( int bandNo, const QgsRectangle & extent, int width, int height, QgsRasterBlockFeedback* feedback = nullptr ) / Factory /;

void writeXml( QDomDocument& doc, QDomElement& parentElem ) const;

@@ -16,7 +16,7 @@ class QgsSingleBandGrayRenderer: QgsRasterRenderer

static QgsRasterRenderer* create( const QDomElement& elem, QgsRasterDataProvider* provider ) /Factory/;

QgsRasterBlock *block( int bandNo, const QgsRectangle & extent, int width, int height ) / Factory /;
QgsRasterBlock *block( int bandNo, const QgsRectangle & extent, int width, int height, QgsRasterBlockFeedback* feedback = nullptr ) / Factory /;

int grayBand() const;
void setGrayBand( int band );
@@ -11,7 +11,7 @@ class QgsSingleBandPseudoColorRenderer: QgsRasterRenderer

static QgsRasterRenderer* create( const QDomElement& elem, QgsRasterDataProvider* provider ) /Factory/;

QgsRasterBlock* block( int bandNo, const QgsRectangle & extent, int width, int height ) / Factory /;
QgsRasterBlock* block( int bandNo, const QgsRectangle & extent, int width, int height, QgsRasterBlockFeedback* feedback = nullptr ) / Factory /;

/** Takes ownership of the shader*/
void setShader( QgsRasterShader* shader /Transfer/ );
@@ -194,6 +194,14 @@ static void dumpBacktrace( unsigned int depth )
depth = 20;

#if ((defined(linux) || defined(__linux__)) && !defined(ANDROID)) || defined(__FreeBSD__)
// Below there is a bunch of operations that are not safe in multi-threaded
// environment (dup()+close() combo, wait(), juggling with file descriptors).
// Maybe some problems could be resolved with dup2() and waitpid(), but it seems
// that if the operations on descriptors are not serialized, things will get nasty.
// That's why there's this lovely mutex here...
static QMutex mutex;
QMutexLocker locker( &mutex );

int stderr_fd = -1;
if ( access( "/usr/bin/c++filt", X_OK ) < 0 )
{
@@ -456,6 +456,7 @@ SET(QGIS_CORE_MOC_HDRS
qgsdataprovider.h
qgsdbfilterproxymodel.h
qgseditformconfig.h
qgsfeedback.h
qgsgeometryvalidator.h
qgsgml.h
qgsgmlschema.h
@@ -0,0 +1,73 @@
/***************************************************************************
qgsfeedback.h
--------------------------------------
Date : July 2016
Copyright : (C) 2016 by Martin Dobias
Email : wonder dot 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. *
* *
***************************************************************************/

#ifndef QGSFEEDBACK_H
#define QGSFEEDBACK_H

#include <QObject>

/** \ingroup core
* Base class for feedback objects to be used for cancellation of something running in a worker thread.
* The class may be used as is or it may be subclassed for extended functionality
* for a particular operation (e.g. report progress or pass some data for preview).
*
* When cancel() is called, the internal code has two options to check for cancellation state:
* - if the worker thread uses an event loop (e.g. for network communication), the code can
* make a queued connection to cancelled() signal and handle the cancellation in its slot.
* - if the worker thread does not use an event loop, it can poll isCancelled() method regularly
* to see if the operation should be cancelled.
*
* The class is meant to be created and destroyed in the main thread.
*
* For map rendering, the object may be created in constructor of a QgsMapLayerRenderer
* subclass and available with QgsMapLayerRenderer::feedback() method. When a map rendering job
* gets cancelled, the cancel() method is called on the feedback object of all layers.
*
* @note added in QGIS 3.0
*/
class CORE_EXPORT QgsFeedback : public QObject
{
Q_OBJECT
public:
//! Construct a feedback object
QgsFeedback( QObject* parent = nullptr )
: QObject( parent )
, mCancelled( false )
{}

virtual ~QgsFeedback() {}

//! Tells the internal routines that the current operation should be cancelled. This should be run by the main thread
void cancel()
{
if ( mCancelled )
return; // only emit the signal once
mCancelled = true;
emit cancelled();
}

//! Tells whether the operation has been cancelled already
bool isCancelled() const { return mCancelled; }

signals:
//! Internal routines can connect to this signal if they use event loop
void cancelled();

private:
//! Whether the operation has been cancelled already. False by default.
bool mCancelled;
};

#endif // QGSFEEDBACK_H
@@ -18,6 +18,8 @@

#include <QStringList>

class QgsFeedback;

/** \ingroup core
* Base class for utility classes that encapsulate information necessary
* for rendering of map layers. The rendering is typically done in a background
@@ -49,6 +51,10 @@ class CORE_EXPORT QgsMapLayerRenderer
//! Do the rendering (based on data stored in the class)
virtual bool render() = 0;

//! Access to feedback object of the layer renderer (may be null)
//! @note added in QGIS 3.0
virtual QgsFeedback* feedback() const { return nullptr; }

//! Return list of errors (problems) that happened during the rendering
QStringList errors() const { return mErrors; }

@@ -15,6 +15,7 @@

#include "qgsmaprenderercustompainterjob.h"

#include "qgsfeedback.h"
#include "qgslabelingenginev2.h"
#include "qgslogger.h"
#include "qgsmaplayerregistry.h"
@@ -124,6 +125,8 @@ void QgsMapRendererCustomPainterJob::cancel()
for ( LayerRenderJobs::iterator it = mLayerJobs.begin(); it != mLayerJobs.end(); ++it )
{
it->context.setRenderingStopped( true );
if ( it->renderer->feedback() )
it->renderer->feedback()->cancel();
}

QTime t;

0 comments on commit 9db9304

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