26 #include "qgssettings.h" 
   34 #include <qwt_global.h> 
   35 #include <qwt_plot_canvas.h> 
   36 #include <qwt_legend.h> 
   38 #include <qwt_plot_curve.h> 
   39 #include <qwt_plot_grid.h> 
   40 #include <qwt_plot_marker.h> 
   41 #include <qwt_plot_picker.h> 
   42 #include <qwt_picker_machine.h> 
   43 #include <qwt_plot_zoomer.h> 
   44 #include <qwt_plot_layout.h> 
   45 #include <qwt_plot_renderer.h> 
   46 #include <qwt_plot_histogram.h> 
   60   connect( mSaveAsImageButton, &QToolButton::clicked, 
this, &QgsRasterHistogramWidget::mSaveAsImageButton_clicked );
 
   61   connect( cboHistoBand, 
static_cast<void ( QComboBox::* )( 
int )
>( &QComboBox::currentIndexChanged ), 
this, &QgsRasterHistogramWidget::cboHistoBand_currentIndexChanged );
 
   62   connect( btnHistoMin, &QToolButton::toggled, 
this, &QgsRasterHistogramWidget::btnHistoMin_toggled );
 
   63   connect( btnHistoMax, &QToolButton::toggled, 
this, &QgsRasterHistogramWidget::btnHistoMax_toggled );
 
   64   connect( btnHistoCompute, &QPushButton::clicked, 
this, &QgsRasterHistogramWidget::btnHistoCompute_clicked );
 
   68   mRendererWidget = 
nullptr;
 
   69   mRendererName = QStringLiteral( 
"singlebandgray" );
 
   74   mHistoPicker = 
nullptr;
 
   75   mHistoZoomer = 
nullptr;
 
   76   mHistoMarkerMin = 
nullptr;
 
   77   mHistoMarkerMax = 
nullptr;
 
   80   mHistoShowMarkers = settings.value( QStringLiteral( 
"Raster/histogram/showMarkers" ), 
false ).toBool();
 
   82   mHistoZoomToMinMax = settings.value( QStringLiteral( 
"Raster/histogram/zoomToMinMax" ), 
false ).toBool();
 
   83   mHistoUpdateStyleToMinMax = settings.value( QStringLiteral( 
"Raster/histogram/updateStyleToMinMax" ), 
true ).toBool();
 
   84   mHistoDrawLines = settings.value( QStringLiteral( 
"Raster/histogram/drawLines" ), 
true ).toBool();
 
   86   mHistoShowBands = ShowAll;
 
   92     int myBandCountInt = mRasterLayer->
bandCount();
 
   93     for ( 
int myIteratorInt = 1;
 
   94           myIteratorInt <= myBandCountInt;
 
   97       cboHistoBand->addItem( mRasterLayer->
bandName( myIteratorInt ) );
 
  113     connect( leHistoMin, &QLineEdit::editingFinished, 
this, &QgsRasterHistogramWidget::applyHistoMin );
 
  114     connect( leHistoMax, &QLineEdit::editingFinished, 
this, &QgsRasterHistogramWidget::applyHistoMax );
 
  118     QMenu *menu = 
new QMenu( 
this );
 
  119     menu->setSeparatorsCollapsible( 
false );
 
  120     btnHistoActions->setMenu( menu );
 
  121     QActionGroup *group = 
nullptr;
 
  122     QAction *action = 
nullptr;
 
  125     group = 
new QActionGroup( 
this );
 
  126     group->setExclusive( 
false );
 
  127     connect( group, &QActionGroup::triggered, 
this, &QgsRasterHistogramWidget::histoActionTriggered );
 
  128     action = 
new QAction( tr( 
"Min/Max options" ), group );
 
  129     action->setSeparator( 
true );
 
  130     menu->addAction( action );
 
  131     action = 
new QAction( tr( 
"Always show min/max markers" ), group );
 
  132     action->setData( QVariant( 
"Show markers" ) );
 
  133     action->setCheckable( 
true );
 
  134     action->setChecked( mHistoShowMarkers );
 
  135     menu->addAction( action );
 
  136     action = 
new QAction( tr( 
"Zoom to min/max" ), group );
 
  137     action->setData( QVariant( 
"Zoom min_max" ) );
 
  138     action->setCheckable( 
true );
 
  139     action->setChecked( mHistoZoomToMinMax );
 
  140     menu->addAction( action );
 
  141     action = 
new QAction( tr( 
"Update style to min/max" ), group );
 
  142     action->setData( QVariant( 
"Update min_max" ) );
 
  143     action->setCheckable( 
true );
 
  144     action->setChecked( mHistoUpdateStyleToMinMax );
 
  145     menu->addAction( action );
 
  148     group = 
new QActionGroup( 
this );
 
  149     group->setExclusive( 
false );
 
  150     connect( group, &QActionGroup::triggered, 
this, &QgsRasterHistogramWidget::histoActionTriggered );
 
  151     action = 
new QAction( tr( 
"Visibility" ), group );
 
  152     action->setSeparator( 
true );
 
  153     menu->addAction( action );
 
  154     group = 
new QActionGroup( 
this );
 
  155     group->setExclusive( 
true ); 
 
  156     connect( group, &QActionGroup::triggered, 
this, &QgsRasterHistogramWidget::histoActionTriggered );
 
  157     action = 
new QAction( tr( 
"Show all bands" ), group );
 
  158     action->setData( QVariant( 
"Show all" ) );
 
  159     action->setCheckable( 
true );
 
  160     action->setChecked( mHistoShowBands == ShowAll );
 
  161     menu->addAction( action );
 
  162     action = 
new QAction( tr( 
"Show RGB/Gray band(s)" ), group );
 
  163     action->setData( QVariant( 
"Show RGB" ) );
 
  164     action->setCheckable( 
true );
 
  165     action->setChecked( mHistoShowBands == ShowRGB );
 
  166     menu->addAction( action );
 
  167     action = 
new QAction( tr( 
"Show selected band" ), group );
 
  168     action->setData( QVariant( 
"Show selected" ) );
 
  169     action->setCheckable( 
true );
 
  170     action->setChecked( mHistoShowBands == ShowSelected );
 
  171     menu->addAction( action );
 
  174     group = 
new QActionGroup( 
this );
 
  175     group->setExclusive( 
false );
 
  176     connect( group, &QActionGroup::triggered, 
this, &QgsRasterHistogramWidget::histoActionTriggered );
 
  177     action = 
new QAction( tr( 
"Display" ), group );
 
  178     action->setSeparator( 
true );
 
  179     menu->addAction( action );
 
  181     action = 
new QAction( QString(), group );
 
  182     action->setData( QVariant( 
"Draw lines" ) );
 
  185       action->setText( tr( 
"Draw as lines" ) );
 
  186       action->setCheckable( 
true );
 
  187       action->setChecked( mHistoDrawLines );
 
  191       action->setText( tr( 
"Draw as lines (only int layers)" ) );
 
  192       action->setEnabled( 
false );
 
  194     menu->addAction( action );
 
  197     action = 
new QAction( tr( 
"Actions" ), group );
 
  198     action->setSeparator( 
true );
 
  199     menu->addAction( action );
 
  202     group = 
new QActionGroup( 
this );
 
  203     group->setExclusive( 
false );
 
  204     connect( group, &QActionGroup::triggered, 
this, &QgsRasterHistogramWidget::histoActionTriggered );
 
  205     action = 
new QAction( tr( 
"Reset" ), group );
 
  206     action->setData( QVariant( 
"Load reset" ) );
 
  207     menu->addAction( action );
 
  213     action = 
new QAction( tr( 
"Load min/max" ), group );
 
  214     action->setSeparator( 
true );
 
  215     menu->addAction( action );
 
  216     action = 
new QAction( tr( 
"Estimate (faster)" ), group );
 
  217     action->setData( QVariant( 
"Load estimate" ) );
 
  218     menu->addAction( action );
 
  219     action = 
new QAction( tr( 
"Actual (slower)" ), group );
 
  220     action->setData( QVariant( 
"Load actual" ) );
 
  221     menu->addAction( action );
 
  222     action = 
new QAction( tr( 
"Current extent" ), group );
 
  223     action->setData( QVariant( 
"Load extent" ) );
 
  224     menu->addAction( action );
 
  225     action = 
new QAction( tr( 
"Use stddev (1.0)" ), group );
 
  226     action->setData( QVariant( 
"Load 1 stddev" ) );
 
  227     menu->addAction( action );
 
  228     action = 
new QAction( tr( 
"Use stddev (custom)" ), group );
 
  229     action->setData( QVariant( 
"Load stddev" ) );
 
  230     menu->addAction( action );
 
  231     action = 
new QAction( tr( 
"Load for each band" ), group );
 
  232     action->setData( QVariant( 
"Load apply all" ) );
 
  233     action->setCheckable( 
true );
 
  234     action->setChecked( mHistoLoadApplyAll );
 
  235     menu->addAction( action );
 
  239     action = 
new QAction( tr( 
"Recompute Histogram" ), group );
 
  240     action->setData( QVariant( 
"Compute histogram" ) );
 
  241     menu->addAction( action );
 
  249   mRendererName = name;
 
  250   mRendererWidget = rendererWidget;
 
  252   cboHistoBand_currentIndexChanged( -1 );
 
  260     cboHistoBand_currentIndexChanged( -1 );
 
  264     if ( QApplication::overrideCursor() )
 
  265       QApplication::restoreOverrideCursor();
 
  266     btnHistoMin->setChecked( 
false );
 
  267     btnHistoMax->setChecked( 
false );
 
  271 void QgsRasterHistogramWidget::btnHistoCompute_clicked()
 
  300   xRes = yRes = std::sqrt( ( 
static_cast<double>( extent.width( ) ) * extent.height() ) / sampleSize );
 
  305     const double srcXRes = extent.width() / rasterInterface->
xSize();
 
  306     const double srcYRes = extent.height() / rasterInterface->
ySize();
 
  307     if ( xRes < srcXRes ) xRes = srcXRes;
 
  308     if ( yRes < srcYRes ) yRes = srcYRes;
 
  311   const int histogramWidth = 
static_cast <int>( extent.width() / xRes );
 
  312   const int histogramHeight = 
static_cast <int>( extent.height() / yRes );
 
  314   int binCount = 
static_cast<int>( std::min( 
static_cast<qint64
>( 1000 ),
 
  315                                    static_cast<qint64
>( histogramWidth ) * histogramHeight ) );
 
  320     binCount = 
static_cast<int>( std::min( 
static_cast<qint64
>( binCount ),
 
  321                                            static_cast<qint64
>( std::ceil( statsMax - statsMin + 1 ) ) ) );
 
  332   int myBandCountInt = mRasterLayer->
bandCount();
 
  335   if ( ! forceComputeFlag )
 
  337     for ( 
int myIteratorInt = 1;
 
  338           myIteratorInt <= myBandCountInt;
 
  342       const int binCount = getBinCount( mRasterLayer->
dataProvider(), myIteratorInt, sampleSize );
 
  343       if ( !mRasterLayer->
dataProvider()->
hasHistogram( myIteratorInt, binCount, std::numeric_limits<double>::quiet_NaN(), std::numeric_limits<double>::quiet_NaN(), 
QgsRectangle(), sampleSize ) )
 
  345         QgsDebugMsg( QStringLiteral( 
"band %1 does not have cached histo" ).arg( myIteratorInt ) );
 
  352   stackedWidget2->setCurrentIndex( 1 );
 
  356   QApplication::setOverrideCursor( Qt::WaitCursor );
 
  358   for ( 
int myIteratorInt = 1;
 
  359         myIteratorInt <= myBandCountInt;
 
  363     const int binCount = getBinCount( mRasterLayer->
dataProvider(), myIteratorInt, sampleSize );
 
  364     mRasterLayer->
dataProvider()->
histogram( myIteratorInt, binCount, std::numeric_limits<double>::quiet_NaN(), std::numeric_limits<double>::quiet_NaN(), 
QgsRectangle(), sampleSize, 
false, feedback.get() );
 
  368   stackedWidget2->setCurrentIndex( 0 );
 
  369   QApplication::restoreOverrideCursor();
 
  386   int myBandCountInt = mRasterLayer->
bandCount();
 
  391     QgsDebugMsg( QStringLiteral( 
"raster does not have cached histogram" ) );
 
  392     stackedWidget2->setCurrentIndex( 2 );
 
  397   mpPlot->detachItems();
 
  400   mpPlot->setAutoDelete( 
true );
 
  401   mpPlot->setTitle( QObject::tr( 
"Raster Histogram" ) );
 
  402   mpPlot->insertLegend( 
new QwtLegend(), QwtPlot::BottomLegend );
 
  404   mpPlot->setAxisTitle( QwtPlot::xBottom, QObject::tr( 
"Pixel Value" ) );
 
  405   mpPlot->setAxisTitle( QwtPlot::yLeft, QObject::tr( 
"Frequency" ) );
 
  406   mpPlot->setAxisAutoScale( QwtPlot::yLeft );
 
  410   QwtPlotGrid *myGrid = 
new QwtPlotGrid();
 
  411   myGrid->attach( mpPlot );
 
  414   mHistoColors.clear();
 
  415   mHistoColors << Qt::black; 
 
  416   QVector<QColor> myColors;
 
  417   myColors << Qt::red << Qt::green << Qt::blue << Qt::magenta << Qt::darkYellow << Qt::cyan;
 
  418   qsrand( myBandCountInt * 100 ); 
 
  419   while ( myColors.size() <= myBandCountInt )
 
  422              QColor( 1 + ( 
int )( 255.0 * qrand() / ( RAND_MAX + 1.0 ) ),
 
  423                      1 + ( 
int )( 255.0 * qrand() / ( RAND_MAX + 1.0 ) ),
 
  424                      1 + ( 
int )( 255.0 * qrand() / ( RAND_MAX + 1.0 ) ) );
 
  427   qsrand( time( 
nullptr ) );
 
  431   QList< int > mySelectedBands = rendererSelectedBands();
 
  432   if ( mRendererName == QLatin1String( 
"singlebandgray" ) )
 
  434     int myGrayBand = mySelectedBands[0];
 
  435     for ( 
int i = 1; i <= myBandCountInt; i++ )
 
  437       if ( i == myGrayBand )
 
  439         mHistoColors << Qt::darkGray;
 
  440         cboHistoBand->setItemData( i - 1, QColor( Qt::darkGray ), Qt::ForegroundRole );
 
  444         if ( ! myColors.isEmpty() )
 
  446           mHistoColors << myColors.first();
 
  447           myColors.pop_front();
 
  451           mHistoColors << Qt::black;
 
  453         cboHistoBand->setItemData( i - 1, QColor( Qt::black ), Qt::ForegroundRole );
 
  458   else if ( mRendererName == QLatin1String( 
"multibandcolor" ) )
 
  460     int myRedBand = mySelectedBands[0];
 
  461     int myGreenBand = mySelectedBands[1];
 
  462     int myBlueBand = mySelectedBands[2];
 
  465     myColors.remove( 0, 3 );
 
  466     for ( 
int i = 1; i <= myBandCountInt; i++ )
 
  469       if ( i == myRedBand )
 
  471       else if ( i == myGreenBand )
 
  473       else if ( i == myBlueBand )
 
  477         if ( ! myColors.isEmpty() )
 
  479           myColor = myColors.first();
 
  480           myColors.pop_front();
 
  486         cboHistoBand->setItemData( i - 1, QColor( Qt::black ), Qt::ForegroundRole );
 
  488       if ( i == myRedBand ||  i == myGreenBand || i == myBlueBand )
 
  490         cboHistoBand->setItemData( i - 1, myColor, Qt::ForegroundRole );
 
  492       mHistoColors << myColor;
 
  497     mHistoColors << myColors;
 
  512   bool myFirstIteration = 
true;
 
  514   mySelectedBands = histoSelectedBands();
 
  515   double myBinXStep = 1;
 
  518   for ( 
int myIteratorInt = 1;
 
  519         myIteratorInt <= myBandCountInt;
 
  523     if ( mHistoShowBands != ShowAll )
 
  525       if ( ! mySelectedBands.contains( myIteratorInt ) )
 
  534     const int binCount = getBinCount( mRasterLayer->
dataProvider(), myIteratorInt, sampleSize );
 
  537     QgsDebugMsg( QStringLiteral( 
"got raster histo for band %1 : min=%2 max=%3 count=%4" ).arg( myIteratorInt ).arg( myHistogram.
minimum ).arg( myHistogram.
maximum ).arg( myHistogram.
binCount ) );
 
  540     bool myDrawLines = 
true;
 
  541     if ( ! mHistoDrawLines &&
 
  549     QwtPlotCurve *mypCurve = 
nullptr;
 
  552       mypCurve = 
new QwtPlotCurve( tr( 
"Band %1" ).arg( myIteratorInt ) );
 
  554       mypCurve->setRenderHint( QwtPlotItem::RenderAntialiased );
 
  555       mypCurve->setPen( QPen( mHistoColors.at( myIteratorInt ) ) );
 
  558     QwtPlotHistogram *mypHisto = 
nullptr;
 
  561       mypHisto = 
new QwtPlotHistogram( tr( 
"Band %1" ).arg( myIteratorInt ) );
 
  562       mypHisto->setRenderHint( QwtPlotItem::RenderAntialiased );
 
  564       mypHisto->setPen( QPen( Qt::lightGray ) );
 
  566       mypHisto->setBrush( QBrush( mHistoColors.at( myIteratorInt ) ) );
 
  569     QVector<QPointF> data;
 
  570     QVector<QwtIntervalSample> dataHisto;
 
  576       myBinX = myHistogram.
minimum + myBinXStep / 2.0;
 
  584     for ( 
int myBin = 0; myBin < myHistogram.
binCount; myBin++ )
 
  589         data << QPointF( myBinX, myBinValue );
 
  593         dataHisto << QwtIntervalSample( myBinValue, myBinX - myBinXStep / 2.0, myBinX + myBinXStep / 2.0 );
 
  595       myBinX += myBinXStep;
 
  600       mypCurve->setSamples( data );
 
  601       mypCurve->attach( mpPlot );
 
  605       mypHisto->setSamples( dataHisto );
 
  606       mypHisto->attach( mpPlot );
 
  609     if ( myFirstIteration || mHistoMin > myHistogram.
minimum )
 
  611       mHistoMin = myHistogram.
minimum;
 
  613     if ( myFirstIteration || mHistoMax < myHistogram.
maximum )
 
  615       mHistoMax = myHistogram.
maximum;
 
  617     QgsDebugMsg( QStringLiteral( 
"computed histo min = %1 max = %2" ).arg( mHistoMin ).arg( mHistoMax ) );
 
  618     myFirstIteration = 
false;
 
  621   if ( mHistoMin < mHistoMax )
 
  627     mpPlot->setAxisScale( QwtPlot::xBottom,
 
  628                           mHistoMin - myBinXStep / 2,
 
  629                           mHistoMax + myBinXStep / 2 );
 
  630     mpPlot->setEnabled( 
true );
 
  635     mHistoMarkerMin = 
new QwtPlotMarker();
 
  636     mHistoMarkerMin->attach( mpPlot );
 
  637     mHistoMarkerMax = 
new QwtPlotMarker();
 
  638     mHistoMarkerMax->attach( mpPlot );
 
  639     updateHistoMarkers();
 
  644       mHistoPicker = 
new QwtPlotPicker( mpPlot->canvas() );
 
  646       mHistoPicker->setTrackerMode( QwtPicker::AlwaysOff );
 
  647       mHistoPicker->setRubberBand( QwtPicker::VLineRubberBand );
 
  648       mHistoPicker->setStateMachine( 
new QwtPickerDragPointMachine );
 
  649       connect( mHistoPicker, 
static_cast < void ( QwtPlotPicker::* )( 
const QPointF & ) 
> ( &QwtPlotPicker::selected ), 
this, &QgsRasterHistogramWidget::histoPickerSelected );
 
  651     mHistoPicker->setEnabled( 
false );
 
  656       mHistoZoomer = 
new QwtPlotZoomer( mpPlot->canvas() );
 
  657       mHistoZoomer->setStateMachine( 
new QwtPickerDragRectMachine );
 
  658       mHistoZoomer->setTrackerMode( QwtPicker::AlwaysOff );
 
  660     mHistoZoomer->setEnabled( 
true );
 
  664     mpPlot->setDisabled( 
true );
 
  666       mHistoPicker->setEnabled( 
false );
 
  668       mHistoZoomer->setEnabled( 
false );
 
  671   stackedWidget2->setCurrentIndex( 0 );
 
  675   QApplication::restoreOverrideCursor();
 
  678 void QgsRasterHistogramWidget::mSaveAsImageButton_clicked()
 
  684   QFileInfo myInfo( myFileNameAndFilter.first );
 
  685   if ( !myInfo.baseName().isEmpty() )
 
  692     int width, 
int height, 
int quality )
 
  695   QFileInfo myInfo( filename );
 
  696   QDir myDir( myInfo.dir() );
 
  697   if ( ! myDir.exists() )
 
  699     QgsDebugMsg( QStringLiteral( 
"Error, directory %1 non-existent (theFilename = %2)" ).arg( myDir.absolutePath(), filename ) );
 
  704   QPixmap myPixmap( width, height );
 
  705   QRect myQRect( 5, 5, width - 10, height - 10 ); 
 
  706   myPixmap.fill( Qt::white ); 
 
  708   QwtPlotRenderer myRenderer;
 
  709   myRenderer.setDiscardFlags( QwtPlotRenderer::DiscardBackground |
 
  710                               QwtPlotRenderer::DiscardCanvasBackground );
 
  711   myRenderer.setLayoutFlags( QwtPlotRenderer::FrameWithScales );
 
  714   myPainter.begin( &myPixmap );
 
  715   myRenderer.render( mpPlot, &myPainter, myQRect );
 
  719   myPixmap.save( filename, 
nullptr, quality );
 
  727   cboHistoBand->setCurrentIndex( bandNo - 1 );
 
  730 void QgsRasterHistogramWidget::cboHistoBand_currentIndexChanged( 
int index )
 
  732   if ( mHistoShowBands == ShowSelected )
 
  736   index = cboHistoBand->currentIndex();
 
  739     mHistoPicker->setEnabled( 
false );
 
  740     mHistoPicker->setRubberBandPen( QPen( mHistoColors.at( index + 1 ) ) );
 
  743     mHistoZoomer->setEnabled( 
true );
 
  744   btnHistoMin->setEnabled( 
true );
 
  745   btnHistoMax->setEnabled( 
true );
 
  747   QPair< QString, QString > myMinMax = rendererMinMax( index + 1 );
 
  748   leHistoMin->setText( myMinMax.first );
 
  749   leHistoMax->setText( myMinMax.second );
 
  755 void QgsRasterHistogramWidget::histoActionTriggered( QAction *action )
 
  759   histoAction( action->data().toString(), action->isChecked() );
 
  764   if ( actionName.isEmpty() )
 
  768   QgsDebugMsg( QStringLiteral( 
"band = %1 action = %2" ).arg( cboHistoBand->currentIndex() + 1 ).arg( actionName ) );
 
  771   if ( actionName == QLatin1String( 
"Show markers" ) )
 
  773     mHistoShowMarkers = actionFlag;
 
  774     QgsSettings settings;
 
  775     settings.setValue( QStringLiteral( 
"Raster/histogram/showMarkers" ), mHistoShowMarkers );
 
  776     updateHistoMarkers();
 
  779   else if ( actionName == QLatin1String( 
"Zoom min_max" ) )
 
  781     mHistoZoomToMinMax = actionFlag;
 
  782     QgsSettings settings;
 
  783     settings.setValue( QStringLiteral( 
"Raster/histogram/zoomToMinMax" ), mHistoZoomToMinMax );
 
  786   else if ( actionName == QLatin1String( 
"Update min_max" ) )
 
  788     mHistoUpdateStyleToMinMax = actionFlag;
 
  789     QgsSettings settings;
 
  790     settings.setValue( QStringLiteral( 
"Raster/histogram/updateStyleToMinMax" ), mHistoUpdateStyleToMinMax );
 
  793   else if ( actionName == QLatin1String( 
"Show all" ) )
 
  795     mHistoShowBands = ShowAll;
 
  800   else if ( actionName == QLatin1String( 
"Show selected" ) )
 
  802     mHistoShowBands = ShowSelected;
 
  807   else if ( actionName == QLatin1String( 
"Show RGB" ) )
 
  809     mHistoShowBands = ShowRGB;
 
  814   else if ( actionName == QLatin1String( 
"Draw lines" ) )
 
  816     mHistoDrawLines = actionFlag;
 
  817     QgsSettings settings;
 
  818     settings.setValue( QStringLiteral( 
"Raster/histogram/drawLines" ), mHistoDrawLines );
 
  819     btnHistoCompute_clicked(); 
 
  823   else if ( actionName == 
"Load apply all" )
 
  825     mHistoLoadApplyAll = actionFlag;
 
  826     settings.setValue( 
"/Raster/histogram/loadApplyAll", mHistoLoadApplyAll );
 
  832   else if ( actionName.left( 5 ) == QLatin1String( 
"Load " ) && mRendererWidget )
 
  834     QVector<int> myBands;
 
  838     double minMaxValues[2];
 
  841     if ( mHistoLoadApplyAll )
 
  843       int myBandCountInt = mRasterLayer->
bandCount();
 
  844       for ( 
int i = 1; i <= myBandCountInt; i++ )
 
  846         if ( i != cboHistoBand->currentIndex() + 1 )
 
  853     myBands << cboHistoBand->currentIndex() + 1;
 
  857     double myStdDev = 1.0;
 
  858     if ( actionName == 
"Load stddev" )
 
  860       myStdDev = mRendererWidget->
stdDev().toDouble();
 
  865     leHistoMin->blockSignals( 
true );
 
  866     leHistoMax->blockSignals( 
true );
 
  869     const auto constMyBands = myBands;
 
  870     for ( 
int bandNo : constMyBands )
 
  874       if ( actionName == 
"Load actual" )
 
  876         ok = mRendererWidget->bandMinMax( QgsRasterRendererWidget::Actual,
 
  877                                           bandNo, minMaxValues );
 
  879       else if ( actionName == 
"Load estimate" )
 
  881         ok = mRendererWidget->bandMinMax( QgsRasterRendererWidget::Estimate,
 
  882                                           bandNo, minMaxValues );
 
  884       else if ( actionName == 
"Load extent" )
 
  886         ok = mRendererWidget->bandMinMax( QgsRasterRendererWidget::CurrentExtent,
 
  887                                           bandNo, minMaxValues );
 
  889       else if ( actionName == 
"Load 1 stddev" ||
 
  890                 actionName == 
"Load stddev" )
 
  892         ok = mRendererWidget->bandMinMaxFromStdDev( myStdDev, bandNo, minMaxValues );
 
  897       cboHistoBand->setCurrentIndex( bandNo - 1 );
 
  898       if ( !ok || actionName == QLatin1String( 
"Load reset" ) )
 
  912         leHistoMin->setText( QString::number( minMaxValues[0] ) );
 
  913         leHistoMax->setText( QString::number( minMaxValues[1] ) );
 
  920     leHistoMin->blockSignals( 
false );
 
  921     leHistoMax->blockSignals( 
false );
 
  922     updateHistoMarkers();
 
  924   else if ( actionName == QLatin1String( 
"Compute histogram" ) )
 
  926     btnHistoCompute_clicked();
 
  935 void QgsRasterHistogramWidget::applyHistoMin()
 
  937   if ( ! mRendererWidget )
 
  940   int bandNo = cboHistoBand->currentIndex() + 1;
 
  941   QList< int > mySelectedBands = rendererSelectedBands();
 
  943   for ( 
int i = 0; i <= mySelectedBands.size(); i++ )
 
  947       min = leHistoMin->text();
 
  948       if ( mHistoUpdateStyleToMinMax && mRendererWidget->
min( i ) != min )
 
  950         mRendererWidget->
setMin( min, i );
 
  959   updateHistoMarkers();
 
  961   if ( ! min.isEmpty() && mHistoZoomToMinMax && mHistoZoomer )
 
  963     QRectF rect = mHistoZoomer->zoomRect();
 
  964     rect.setLeft( min.toDouble() );
 
  965     mHistoZoomer->zoom( rect );
 
  970 void QgsRasterHistogramWidget::applyHistoMax()
 
  972   if ( ! mRendererWidget )
 
  975   int bandNo = cboHistoBand->currentIndex() + 1;
 
  976   QList< int > mySelectedBands = rendererSelectedBands();
 
  978   for ( 
int i = 0; i <= mySelectedBands.size(); i++ )
 
  982       max = leHistoMax->text();
 
  983       if ( mHistoUpdateStyleToMinMax && mRendererWidget->
max( i ) != max )
 
  985         mRendererWidget->
setMax( max, i );
 
  994   updateHistoMarkers();
 
  996   if ( ! max.isEmpty() && mHistoZoomToMinMax && mHistoZoomer )
 
  998     QRectF rect = mHistoZoomer->zoomRect();
 
  999     rect.setRight( max.toDouble() );
 
 1000     mHistoZoomer->zoom( rect );
 
 1005 void QgsRasterHistogramWidget::btnHistoMin_toggled()
 
 1007   if ( mpPlot && mHistoPicker )
 
 1009     if ( QApplication::overrideCursor() )
 
 1010       QApplication::restoreOverrideCursor();
 
 1011     if ( btnHistoMin->isChecked() )
 
 1013       btnHistoMax->setChecked( 
false );
 
 1014       QApplication::setOverrideCursor( Qt::PointingHandCursor );
 
 1017       mHistoZoomer->setEnabled( ! btnHistoMin->isChecked() );
 
 1018     mHistoPicker->setEnabled( btnHistoMin->isChecked() );
 
 1020   updateHistoMarkers();
 
 1023 void QgsRasterHistogramWidget::btnHistoMax_toggled()
 
 1025   if ( mpPlot && mHistoPicker )
 
 1027     if ( QApplication::overrideCursor() )
 
 1028       QApplication::restoreOverrideCursor();
 
 1029     if ( btnHistoMax->isChecked() )
 
 1031       btnHistoMin->setChecked( 
false );
 
 1032       QApplication::setOverrideCursor( Qt::PointingHandCursor );
 
 1035       mHistoZoomer->setEnabled( ! btnHistoMax->isChecked() );
 
 1036     mHistoPicker->setEnabled( btnHistoMax->isChecked() );
 
 1038   updateHistoMarkers();
 
 1045   if ( !scale ) 
return QString();
 
 1047   QList< double > minorTicks = scale->ticks( QwtScaleDiv::MinorTick );
 
 1048   QList< double > majorTicks = scale->ticks( QwtScaleDiv::MajorTick );
 
 1049   double diff = ( minorTicks[1] - minorTicks[0] ) / div;
 
 1050   double min = majorTicks[0] - diff;
 
 1052     min -= ( majorTicks[1] - majorTicks[0] );
 
 1053   double max = scale->upperBound();
 
 1054   double closest = target;
 
 1055   double current = min;
 
 1057   while ( current < max )
 
 1060     if ( current > target )
 
 1062       closest = ( std::fabs( target - current + diff ) < std::fabs( target - current ) ) ? current - diff : current;
 
 1068   return QString::number( closest );
 
 1071 void QgsRasterHistogramWidget::histoPickerSelected( QPointF pos )
 
 1073   if ( btnHistoMin->isChecked() || btnHistoMax->isChecked() )
 
 1075     const QwtScaleDiv *scale = &mpPlot->axisScaleDiv( QwtPlot::xBottom );
 
 1077     if ( btnHistoMin->isChecked() )
 
 1081       btnHistoMin->setChecked( 
false );
 
 1087       btnHistoMax->setChecked( 
false );
 
 1090   if ( QApplication::overrideCursor() )
 
 1091     QApplication::restoreOverrideCursor();
 
 1094 void QgsRasterHistogramWidget::histoPickerSelectedQwt5( 
QwtDoublePoint pos )
 
 1096   histoPickerSelected( QPointF( pos.x(), pos.y() ) );
 
 1099 void QgsRasterHistogramWidget::updateHistoMarkers()
 
 1102   if ( leHistoMin->signalsBlocked() )
 
 1105   if ( !mpPlot || !mHistoMarkerMin || !mHistoMarkerMax )
 
 1108   int bandNo = cboHistoBand->currentIndex() + 1;
 
 1109   QList< int > mySelectedBands = histoSelectedBands();
 
 1111   if ( ( ! mHistoShowMarkers && ! btnHistoMin->isChecked() && ! btnHistoMax->isChecked() ) ||
 
 1112        ( ! mySelectedBands.isEmpty() && ! mySelectedBands.contains( bandNo ) ) )
 
 1114     mHistoMarkerMin->hide();
 
 1115     mHistoMarkerMax->hide();
 
 1120   double minVal = mHistoMin;
 
 1121   double maxVal = mHistoMax;
 
 1122   QString minStr = leHistoMin->text();
 
 1123   QString maxStr = leHistoMax->text();
 
 1124   if ( !minStr.isEmpty() )
 
 1125     minVal = minStr.toDouble();
 
 1126   if ( !maxStr.isEmpty() )
 
 1127     maxVal = maxStr.toDouble();
 
 1129   QPen linePen = QPen( mHistoColors.at( bandNo ) );
 
 1130   linePen.setStyle( Qt::DashLine );
 
 1131   mHistoMarkerMin->setLineStyle( QwtPlotMarker::VLine );
 
 1132   mHistoMarkerMin->setLinePen( linePen );
 
 1133   mHistoMarkerMin->setXValue( minVal );
 
 1134   mHistoMarkerMin->show();
 
 1135   mHistoMarkerMax->setLineStyle( QwtPlotMarker::VLine );
 
 1136   mHistoMarkerMax->setLinePen( linePen );
 
 1137   mHistoMarkerMax->setXValue( maxVal );
 
 1138   mHistoMarkerMax->show();
 
 1144 QList< int > QgsRasterHistogramWidget::histoSelectedBands()
 
 1146   QList< int > mySelectedBands;
 
 1148   if ( mHistoShowBands != ShowAll )
 
 1150     if ( mHistoShowBands == ShowSelected )
 
 1152       mySelectedBands << cboHistoBand->currentIndex() + 1;
 
 1154     else if ( mHistoShowBands == ShowRGB )
 
 1156       mySelectedBands = rendererSelectedBands();
 
 1160   return mySelectedBands;
 
 1163 QList< int > QgsRasterHistogramWidget::rendererSelectedBands()
 
 1165   QList< int > mySelectedBands;
 
 1167   if ( ! mRendererWidget )
 
 1169     mySelectedBands << -1 << -1 << -1; 
 
 1170     return mySelectedBands;
 
 1173   if ( mRendererName == QLatin1String( 
"singlebandgray" ) )
 
 1177   else if ( mRendererName == QLatin1String( 
"multibandcolor" ) )
 
 1179     for ( 
int i = 0; i <= 2; i++ )
 
 1185   return mySelectedBands;
 
 1188 QPair< QString, QString > QgsRasterHistogramWidget::rendererMinMax( 
int bandNo )
 
 1190   QPair< QString, QString > myMinMax;
 
 1192   if ( ! mRendererWidget )
 
 1195   if ( mRendererName == QLatin1String( 
"singlebandgray" ) )
 
 1199       myMinMax.first = mRendererWidget->
min();
 
 1200       myMinMax.second = mRendererWidget->
max();
 
 1203   else if ( mRendererName == QLatin1String( 
"multibandcolor" ) )
 
 1205     for ( 
int i = 0; i <= 2; i++ )
 
 1209         myMinMax.first = mRendererWidget->
min( i );
 
 1210         myMinMax.second = mRendererWidget->
max( i );
 
 1226   if ( myMinMax.first.isEmpty() )
 
 1227     myMinMax.first = QString::number( mHistoMin );
 
 1228   if ( myMinMax.second.isEmpty() )
 
 1229     myMinMax.second = QString::number( mHistoMax );
 
 1231   QgsDebugMsg( QStringLiteral( 
"bandNo %1 got min/max [%2] [%3]" ).arg( bandNo ).arg( myMinMax.first, myMinMax.second ) );
 
DataType
Raster data types.
@ Int16
Sixteen bit signed integer (qint16)
@ UInt16
Sixteen bit unsigned integer (quint16)
@ Byte
Eight bit unsigned integer (quint8)
@ Int32
Thirty two bit signed integer (qint32)
@ UInt32
Thirty two bit unsigned integer (quint32)
static QPixmap getThemePixmap(const QString &name, const QColor &foreColor=QColor(), const QColor &backColor=QColor(), int size=16)
Helper to get a theme icon as a pixmap.
static QIcon getThemeIcon(const QString &name, const QColor &fillColor=QColor(), const QColor &strokeColor=QColor())
Helper to get a theme icon.
static double maximumValuePossible(Qgis::DataType dataType)
Helper function that returns the maximum possible value for a data type.
static double minimumValuePossible(Qgis::DataType dataType)
Helper function that returns the minimum possible value for a data type.
QgsDoubleValidator is a QLineEdit Validator that combines QDoubleValidator and QRegularExpressionVali...
void progressChanged(double progress)
Emitted when the feedback object reports a progress change.
double minimumValue
The minimum cell value in the raster band.
double maximumValue
The maximum cell value in the raster band.
Feedback object tailored for raster block reading.
Qgis::DataType sourceDataType(int bandNo) const override=0
Returns source data type for the band specified by number, source data type may be shorter than dataT...
Qgis::DataType dataType(int bandNo) const override=0
Returns data type for the band specified by number.
The QgsRasterHistogram is a container for histogram of a single raster band.
double minimum
The minimum histogram value.
double maximum
The maximum histogram value.
QgsRasterHistogram::HistogramVector histogramVector
Stores the histogram for a given layer.
int binCount
Number of bins (intervals,buckets) in histogram.
Base class for processing filters like renderers, reprojector, resampler etc.
@ Size
Original data source size (and thus resolution) is known, it is not always available,...
virtual int xSize() const
Gets raster size.
virtual Qgis::DataType sourceDataType(int bandNo) const
Returns source data type for the band specified by number, source data type may be shorter than dataT...
virtual bool hasHistogram(int bandNo, int binCount, double minimum=std::numeric_limits< double >::quiet_NaN(), double maximum=std::numeric_limits< double >::quiet_NaN(), const QgsRectangle &extent=QgsRectangle(), int sampleSize=0, bool includeOutOfRange=false)
Returns true if histogram is available (cached, already calculated)
virtual QgsRasterBandStats bandStatistics(int bandNo, int stats=QgsRasterBandStats::All, const QgsRectangle &extent=QgsRectangle(), int sampleSize=0, QgsRasterBlockFeedback *feedback=nullptr)
Returns the band statistics.
virtual int capabilities() const
Returns a bitmask containing the supported capabilities.
virtual int ySize() const
virtual QgsRectangle extent() const
Gets the extent of the interface.
virtual QgsRasterHistogram histogram(int bandNo, int binCount=0, double minimum=std::numeric_limits< double >::quiet_NaN(), double maximum=std::numeric_limits< double >::quiet_NaN(), const QgsRectangle &extent=QgsRectangle(), int sampleSize=0, bool includeOutOfRange=false, QgsRasterBlockFeedback *feedback=nullptr)
Returns a band histogram.
Represents a raster layer.
int bandCount() const
Returns the number of bands in this layer.
QString bandName(int bandNoInt) const
Returns the name of a band given its number.
QgsRasterDataProvider * dataProvider() override
Returns the source data provider.
A rectangle specified with double values.
QPair< QString, QString > GUI_EXPORT getSaveAsImageName(QWidget *parent, const QString &message, const QString &defaultFilename)
A helper function to get an image name from the user.