31#include <QActionGroup> 
   32#include <QRandomGenerator> 
   35#include <qwt_global.h> 
   36#include <qwt_plot_canvas.h> 
   37#include <qwt_legend.h> 
   39#include <qwt_plot_curve.h> 
   40#include <qwt_plot_grid.h> 
   41#include <qwt_plot_marker.h> 
   42#include <qwt_plot_picker.h> 
   43#include <qwt_picker_machine.h> 
   44#include <qwt_plot_zoomer.h> 
   45#include <qwt_plot_layout.h> 
   46#include <qwt_plot_renderer.h> 
   47#include <qwt_plot_histogram.h> 
   48#include <qwt_scale_div.h> 
   62  connect( mSaveAsImageButton, &QToolButton::clicked, 
this, &QgsRasterHistogramWidget::mSaveAsImageButton_clicked );
 
   63  connect( cboHistoBand, 
static_cast<void ( QComboBox::* )( 
int )
>( &QComboBox::currentIndexChanged ), 
this, &QgsRasterHistogramWidget::cboHistoBand_currentIndexChanged );
 
   64  connect( btnHistoMin, &QToolButton::toggled, 
this, &QgsRasterHistogramWidget::btnHistoMin_toggled );
 
   65  connect( btnHistoMax, &QToolButton::toggled, 
this, &QgsRasterHistogramWidget::btnHistoMax_toggled );
 
   66  connect( btnHistoCompute, &QPushButton::clicked, 
this, &QgsRasterHistogramWidget::btnHistoCompute_clicked );
 
   70  mRendererWidget = 
nullptr;
 
   71  mRendererName = QStringLiteral( 
"singlebandgray" );
 
   76  mHistoPicker = 
nullptr;
 
   77  mHistoZoomer = 
nullptr;
 
   78  mHistoMarkerMin = 
nullptr;
 
   79  mHistoMarkerMax = 
nullptr;
 
   82  mHistoShowMarkers = settings.
value( QStringLiteral( 
"Raster/histogram/showMarkers" ), 
false ).toBool();
 
   84  mHistoZoomToMinMax = settings.
value( QStringLiteral( 
"Raster/histogram/zoomToMinMax" ), 
false ).toBool();
 
   85  mHistoUpdateStyleToMinMax = settings.
value( QStringLiteral( 
"Raster/histogram/updateStyleToMinMax" ), 
true ).toBool();
 
   86  mHistoDrawLines = settings.
value( QStringLiteral( 
"Raster/histogram/drawLines" ), 
true ).toBool();
 
   88  mHistoShowBands = ShowAll;
 
   94    const int myBandCountInt = mRasterLayer->
bandCount();
 
   95    for ( 
int myIteratorInt = 1;
 
   96          myIteratorInt <= myBandCountInt;
 
   99      cboHistoBand->addItem( mRasterLayer->
bandName( myIteratorInt ) );
 
  116    connect( leHistoMin, &QLineEdit::editingFinished, 
this, &QgsRasterHistogramWidget::applyHistoMin );
 
  117    connect( leHistoMax, &QLineEdit::editingFinished, 
this, &QgsRasterHistogramWidget::applyHistoMax );
 
  121    QMenu *menu = 
new QMenu( 
this );
 
  122    menu->setSeparatorsCollapsible( 
false );
 
  123    btnHistoActions->setMenu( menu );
 
  124    QActionGroup *group = 
nullptr;
 
  125    QAction *action = 
nullptr;
 
  128    group = 
new QActionGroup( 
this );
 
  129    group->setExclusive( 
false );
 
  130    connect( group, &QActionGroup::triggered, 
this, &QgsRasterHistogramWidget::histoActionTriggered );
 
  131    action = 
new QAction( tr( 
"Min/Max options" ), group );
 
  132    action->setSeparator( 
true );
 
  133    menu->addAction( action );
 
  134    action = 
new QAction( tr( 
"Always show min/max markers" ), group );
 
  135    action->setData( QVariant( 
"Show markers" ) );
 
  136    action->setCheckable( 
true );
 
  137    action->setChecked( mHistoShowMarkers );
 
  138    menu->addAction( action );
 
  139    action = 
new QAction( tr( 
"Zoom to min/max" ), group );
 
  140    action->setData( QVariant( 
"Zoom min_max" ) );
 
  141    action->setCheckable( 
true );
 
  142    action->setChecked( mHistoZoomToMinMax );
 
  143    menu->addAction( action );
 
  144    action = 
new QAction( tr( 
"Update style to min/max" ), group );
 
  145    action->setData( QVariant( 
"Update min_max" ) );
 
  146    action->setCheckable( 
true );
 
  147    action->setChecked( mHistoUpdateStyleToMinMax );
 
  148    menu->addAction( action );
 
  151    group = 
new QActionGroup( 
this );
 
  152    group->setExclusive( 
false );
 
  153    connect( group, &QActionGroup::triggered, 
this, &QgsRasterHistogramWidget::histoActionTriggered );
 
  154    action = 
new QAction( tr( 
"Visibility" ), group );
 
  155    action->setSeparator( 
true );
 
  156    menu->addAction( action );
 
  157    group = 
new QActionGroup( 
this );
 
  158    group->setExclusive( 
true ); 
 
  159    connect( group, &QActionGroup::triggered, 
this, &QgsRasterHistogramWidget::histoActionTriggered );
 
  160    action = 
new QAction( tr( 
"Show all bands" ), group );
 
  161    action->setData( QVariant( 
"Show all" ) );
 
  162    action->setCheckable( 
true );
 
  163    action->setChecked( mHistoShowBands == ShowAll );
 
  164    menu->addAction( action );
 
  165    action = 
new QAction( tr( 
"Show RGB/Gray band(s)" ), group );
 
  166    action->setData( QVariant( 
"Show RGB" ) );
 
  167    action->setCheckable( 
true );
 
  168    action->setChecked( mHistoShowBands == ShowRGB );
 
  169    menu->addAction( action );
 
  170    action = 
new QAction( tr( 
"Show selected band" ), group );
 
  171    action->setData( QVariant( 
"Show selected" ) );
 
  172    action->setCheckable( 
true );
 
  173    action->setChecked( mHistoShowBands == ShowSelected );
 
  174    menu->addAction( action );
 
  177    group = 
new QActionGroup( 
this );
 
  178    group->setExclusive( 
false );
 
  179    connect( group, &QActionGroup::triggered, 
this, &QgsRasterHistogramWidget::histoActionTriggered );
 
  180    action = 
new QAction( tr( 
"Display" ), group );
 
  181    action->setSeparator( 
true );
 
  182    menu->addAction( action );
 
  184    action = 
new QAction( QString(), group );
 
  185    action->setData( QVariant( 
"Draw lines" ) );
 
  188      action->setText( tr( 
"Draw as lines" ) );
 
  189      action->setCheckable( 
true );
 
  190      action->setChecked( mHistoDrawLines );
 
  194      action->setText( tr( 
"Draw as lines (only int layers)" ) );
 
  195      action->setEnabled( 
false );
 
  197    menu->addAction( action );
 
  200    action = 
new QAction( tr( 
"Actions" ), group );
 
  201    action->setSeparator( 
true );
 
  202    menu->addAction( action );
 
  205    group = 
new QActionGroup( 
this );
 
  206    group->setExclusive( 
false );
 
  207    connect( group, &QActionGroup::triggered, 
this, &QgsRasterHistogramWidget::histoActionTriggered );
 
  208    action = 
new QAction( tr( 
"Reset" ), group );
 
  209    action->setData( QVariant( 
"Load reset" ) );
 
  210    menu->addAction( action );
 
  216    action = 
new QAction( tr( 
"Load min/max" ), group );
 
  217    action->setSeparator( 
true );
 
  218    menu->addAction( action );
 
  219    action = 
new QAction( tr( 
"Estimate (faster)" ), group );
 
  220    action->setData( QVariant( 
"Load estimate" ) );
 
  221    menu->addAction( action );
 
  222    action = 
new QAction( tr( 
"Actual (slower)" ), group );
 
  223    action->setData( QVariant( 
"Load actual" ) );
 
  224    menu->addAction( action );
 
  225    action = 
new QAction( tr( 
"Current extent" ), group );
 
  226    action->setData( QVariant( 
"Load extent" ) );
 
  227    menu->addAction( action );
 
  228    action = 
new QAction( tr( 
"Use stddev (1.0)" ), group );
 
  229    action->setData( QVariant( 
"Load 1 stddev" ) );
 
  230    menu->addAction( action );
 
  231    action = 
new QAction( tr( 
"Use stddev (custom)" ), group );
 
  232    action->setData( QVariant( 
"Load stddev" ) );
 
  233    menu->addAction( action );
 
  234    action = 
new QAction( tr( 
"Load for each band" ), group );
 
  235    action->setData( QVariant( 
"Load apply all" ) );
 
  236    action->setCheckable( 
true );
 
  237    action->setChecked( mHistoLoadApplyAll );
 
  238    menu->addAction( action );
 
  242    action = 
new QAction( tr( 
"Recompute Histogram" ), group );
 
  243    action->setData( QVariant( 
"Compute histogram" ) );
 
  244    menu->addAction( action );
 
 
  252  mRendererName = name;
 
  253  mRendererWidget = rendererWidget;
 
  255  cboHistoBand_currentIndexChanged( -1 );
 
 
  263    cboHistoBand_currentIndexChanged( -1 );
 
  267    if ( QApplication::overrideCursor() )
 
  268      QApplication::restoreOverrideCursor();
 
  269    btnHistoMin->setChecked( 
false );
 
  270    btnHistoMax->setChecked( 
false );
 
 
  274void QgsRasterHistogramWidget::btnHistoCompute_clicked()
 
  303  xRes = yRes = std::sqrt( ( 
static_cast<double>( extent.width( ) ) * extent.height() ) / sampleSize );
 
  308    const double srcXRes = extent.width() / rasterInterface->
xSize();
 
  309    const double srcYRes = extent.height() / rasterInterface->
ySize();
 
  310    if ( xRes < srcXRes ) xRes = srcXRes;
 
  311    if ( yRes < srcYRes ) yRes = srcYRes;
 
  314  const int histogramWidth = 
static_cast <int>( extent.width() / xRes );
 
  315  const int histogramHeight = 
static_cast <int>( extent.height() / yRes );
 
  317  int binCount = 
static_cast<int>( std::min( 
static_cast<qint64
>( 1000 ),
 
  318                                   static_cast<qint64
>( histogramWidth ) * histogramHeight ) );
 
  323    binCount = 
static_cast<int>( std::min( 
static_cast<qint64
>( binCount ),
 
  324                                           static_cast<qint64
>( std::ceil( statsMax - statsMin + 1 ) ) ) );
 
  335  const int myBandCountInt = mRasterLayer->
bandCount();
 
  338  if ( ! forceComputeFlag )
 
  340    for ( 
int myIteratorInt = 1;
 
  341          myIteratorInt <= myBandCountInt;
 
  345      const int binCount = getBinCount( mRasterLayer->
dataProvider(), myIteratorInt, sampleSize );
 
  346      if ( !mRasterLayer->
dataProvider()->
hasHistogram( myIteratorInt, binCount, std::numeric_limits<double>::quiet_NaN(), std::numeric_limits<double>::quiet_NaN(), 
QgsRectangle(), sampleSize ) )
 
  348        QgsDebugMsgLevel( QStringLiteral( 
"band %1 does not have cached histo" ).arg( myIteratorInt ), 2 );
 
  355  stackedWidget2->setCurrentIndex( 1 );
 
  359  QApplication::setOverrideCursor( Qt::WaitCursor );
 
  361  for ( 
int myIteratorInt = 1;
 
  362        myIteratorInt <= myBandCountInt;
 
  366    const int binCount = getBinCount( mRasterLayer->
dataProvider(), myIteratorInt, sampleSize );
 
  367    mRasterLayer->
dataProvider()->
histogram( myIteratorInt, binCount, std::numeric_limits<double>::quiet_NaN(), std::numeric_limits<double>::quiet_NaN(), 
QgsRectangle(), sampleSize, 
false, feedback.get() );
 
  371  stackedWidget2->setCurrentIndex( 0 );
 
  372  QApplication::restoreOverrideCursor();
 
 
  389  const int myBandCountInt = mRasterLayer->
bandCount();
 
  394    QgsDebugMsgLevel( QStringLiteral( 
"raster does not have cached histogram" ), 2 );
 
  395    stackedWidget2->setCurrentIndex( 2 );
 
  400  mpPlot->detachItems();
 
  403  mpPlot->setAutoDelete( 
true );
 
  404  mpPlot->setTitle( QObject::tr( 
"Raster Histogram" ) );
 
  405  mpPlot->insertLegend( 
new QwtLegend(), QwtPlot::BottomLegend );
 
  407  mpPlot->setAxisTitle( QwtPlot::xBottom, QObject::tr( 
"Pixel Value" ) );
 
  408  mpPlot->setAxisTitle( QwtPlot::yLeft, QObject::tr( 
"Frequency" ) );
 
  409  mpPlot->setAxisAutoScale( QwtPlot::yLeft );
 
  413  QwtPlotGrid *myGrid = 
new QwtPlotGrid();
 
  414  myGrid->attach( mpPlot );
 
  417  mHistoColors.clear();
 
  418  mHistoColors << Qt::black; 
 
  419  QVector<QColor> myColors;
 
  420  myColors << Qt::red << Qt::green << Qt::blue << Qt::magenta << Qt::darkYellow << Qt::cyan;
 
  423  QRandomGenerator colorGenerator( myBandCountInt * 100 );
 
  424  while ( myColors.size() <= myBandCountInt )
 
  427             QColor( colorGenerator.bounded( 1, 256 ),
 
  428                     colorGenerator.bounded( 1, 256 ),
 
  429                     colorGenerator.bounded( 1, 256 ) );
 
  434  QList< int > mySelectedBands = rendererSelectedBands();
 
  435  if ( mRendererName == QLatin1String( 
"singlebandgray" ) )
 
  437    const int myGrayBand = mySelectedBands[0];
 
  438    for ( 
int i = 1; i <= myBandCountInt; i++ )
 
  440      if ( i == myGrayBand )
 
  442        mHistoColors << Qt::darkGray;
 
  443        cboHistoBand->setItemData( i - 1, QColor( Qt::darkGray ), Qt::ForegroundRole );
 
  447        if ( ! myColors.isEmpty() )
 
  449          mHistoColors << myColors.first();
 
  450          myColors.pop_front();
 
  454          mHistoColors << Qt::black;
 
  456        cboHistoBand->setItemData( i - 1, QColor( Qt::black ), Qt::ForegroundRole );
 
  461  else if ( mRendererName == QLatin1String( 
"multibandcolor" ) )
 
  463    const int myRedBand = mySelectedBands[0];
 
  464    const int myGreenBand = mySelectedBands[1];
 
  465    const int myBlueBand = mySelectedBands[2];
 
  468    myColors.remove( 0, 3 );
 
  469    for ( 
int i = 1; i <= myBandCountInt; i++ )
 
  472      if ( i == myRedBand )
 
  474      else if ( i == myGreenBand )
 
  476      else if ( i == myBlueBand )
 
  480        if ( ! myColors.isEmpty() )
 
  482          myColor = myColors.first();
 
  483          myColors.pop_front();
 
  489        cboHistoBand->setItemData( i - 1, QColor( Qt::black ), Qt::ForegroundRole );
 
  491      if ( i == myRedBand ||  i == myGreenBand || i == myBlueBand )
 
  493        cboHistoBand->setItemData( i - 1, myColor, Qt::ForegroundRole );
 
  495      mHistoColors << myColor;
 
  500    mHistoColors << myColors;
 
  515  bool myFirstIteration = 
true;
 
  517  mySelectedBands = histoSelectedBands();
 
  518  double myBinXStep = 1;
 
  521  for ( 
int bandNumber = 1;
 
  522        bandNumber <= myBandCountInt;
 
  526    if ( mHistoShowBands != ShowAll )
 
  528      if ( ! mySelectedBands.contains( bandNumber ) )
 
  537    const int binCount = getBinCount( mRasterLayer->
dataProvider(), bandNumber, sampleSize );
 
  540    QgsDebugMsgLevel( QStringLiteral( 
"got raster histo for band %1 : min=%2 max=%3 count=%4" ).arg( bandNumber ).arg( myHistogram.
minimum ).arg( myHistogram.
maximum ).arg( myHistogram.
binCount ), 2 );
 
  543    bool myDrawLines = 
true;
 
  544    if ( ! mHistoDrawLines &&
 
  552    QwtPlotCurve *mypCurve = 
nullptr;
 
  555      mypCurve = 
new QwtPlotCurve( tr( 
"Band %1" ).arg( bandNumber ) );
 
  557      mypCurve->setRenderHint( QwtPlotItem::RenderAntialiased );
 
  558      mypCurve->setPen( QPen( mHistoColors.at( bandNumber ) ) );
 
  561    QwtPlotHistogram *mypHisto = 
nullptr;
 
  564      mypHisto = 
new QwtPlotHistogram( tr( 
"Band %1" ).arg( bandNumber ) );
 
  565      mypHisto->setRenderHint( QwtPlotItem::RenderAntialiased );
 
  567      mypHisto->setPen( QPen( Qt::lightGray ) );
 
  569      mypHisto->setBrush( QBrush( mHistoColors.at( bandNumber ) ) );
 
  572    QVector<QPointF> data;
 
  573    QVector<QwtIntervalSample> dataHisto;
 
  577    myBinX = myHistogram.
minimum + myBinXStep / 2.0;
 
  579    for ( 
int myBin = 0; myBin < myHistogram.
binCount; myBin++ )
 
  584        data << QPointF( myBinX, myBinValue );
 
  588        dataHisto << QwtIntervalSample( myBinValue, myBinX - myBinXStep / 2.0, myBinX + myBinXStep / 2.0 );
 
  590      myBinX += myBinXStep;
 
  595      mypCurve->setSamples( data );
 
  596      mypCurve->attach( mpPlot );
 
  600      mypHisto->setSamples( dataHisto );
 
  601      mypHisto->attach( mpPlot );
 
  604    if ( myFirstIteration || mHistoMin > myHistogram.
minimum )
 
  606      mHistoMin = myHistogram.
minimum;
 
  608    if ( myFirstIteration || mHistoMax < myHistogram.
maximum )
 
  610      mHistoMax = myHistogram.
maximum;
 
  612    QgsDebugMsgLevel( QStringLiteral( 
"computed histo min = %1 max = %2" ).arg( mHistoMin ).arg( mHistoMax ), 2 );
 
  613    myFirstIteration = 
false;
 
  616  if ( mHistoMin < mHistoMax )
 
  622    mpPlot->setAxisScale( QwtPlot::xBottom,
 
  623                          mHistoMin - myBinXStep / 2,
 
  624                          mHistoMax + myBinXStep / 2 );
 
  625    mpPlot->setEnabled( 
true );
 
  630    mHistoMarkerMin = 
new QwtPlotMarker();
 
  631    mHistoMarkerMin->attach( mpPlot );
 
  632    mHistoMarkerMax = 
new QwtPlotMarker();
 
  633    mHistoMarkerMax->attach( mpPlot );
 
  634    updateHistoMarkers();
 
  639      mHistoPicker = 
new QwtPlotPicker( mpPlot->canvas() );
 
  641      mHistoPicker->setTrackerMode( QwtPicker::AlwaysOff );
 
  642      mHistoPicker->setRubberBand( QwtPicker::VLineRubberBand );
 
  643      mHistoPicker->setStateMachine( 
new QwtPickerDragPointMachine );
 
  644      connect( mHistoPicker, 
static_cast < void ( QwtPlotPicker::* )( 
const QPointF & ) 
> ( &QwtPlotPicker::selected ), 
this, &QgsRasterHistogramWidget::histoPickerSelected );
 
  646    mHistoPicker->setEnabled( 
false );
 
  651      mHistoZoomer = 
new QwtPlotZoomer( mpPlot->canvas() );
 
  652      mHistoZoomer->setStateMachine( 
new QwtPickerDragRectMachine );
 
  653      mHistoZoomer->setTrackerMode( QwtPicker::AlwaysOff );
 
  655    mHistoZoomer->setEnabled( 
true );
 
  659    mpPlot->setDisabled( 
true );
 
  661      mHistoPicker->setEnabled( 
false );
 
  663      mHistoZoomer->setEnabled( 
false );
 
  666  stackedWidget2->setCurrentIndex( 0 );
 
  670  QApplication::restoreOverrideCursor();
 
 
  673void QgsRasterHistogramWidget::mSaveAsImageButton_clicked()
 
  679  const QFileInfo myInfo( myFileNameAndFilter.first );
 
  680  if ( !myInfo.baseName().isEmpty() )
 
  687    int width, 
int height, 
int quality )
 
  690  const QFileInfo myInfo( filename );
 
  691  const QDir myDir( myInfo.dir() );
 
  692  if ( ! myDir.exists() )
 
  694    QgsDebugError( QStringLiteral( 
"Error, directory %1 non-existent (theFilename = %2)" ).arg( myDir.absolutePath(), filename ) );
 
  699  QPixmap myPixmap( width, height );
 
  700  const QRect myQRect( 5, 5, width - 10, height - 10 ); 
 
  701  myPixmap.fill( Qt::white ); 
 
  703  QwtPlotRenderer myRenderer;
 
  704  myRenderer.setDiscardFlags( QwtPlotRenderer::DiscardBackground |
 
  705                              QwtPlotRenderer::DiscardCanvasBackground );
 
  706  myRenderer.setLayoutFlags( QwtPlotRenderer::FrameWithScales );
 
  709  myPainter.begin( &myPixmap );
 
  710  myRenderer.render( mpPlot, &myPainter, myQRect );
 
  714  myPixmap.save( filename, 
nullptr, quality );
 
 
  722  cboHistoBand->setCurrentIndex( bandNo - 1 );
 
 
  725void QgsRasterHistogramWidget::cboHistoBand_currentIndexChanged( 
int index )
 
  727  if ( mHistoShowBands == ShowSelected )
 
  731  index = cboHistoBand->currentIndex();
 
  734    mHistoPicker->setEnabled( 
false );
 
  735    mHistoPicker->setRubberBandPen( QPen( mHistoColors.at( index + 1 ) ) );
 
  738    mHistoZoomer->setEnabled( 
true );
 
  739  btnHistoMin->setEnabled( 
true );
 
  740  btnHistoMax->setEnabled( 
true );
 
  742  const QPair< QString, QString > myMinMax = rendererMinMax( index + 1 );
 
  743  leHistoMin->setText( myMinMax.first );
 
  744  leHistoMax->setText( myMinMax.second );
 
  750void QgsRasterHistogramWidget::histoActionTriggered( QAction *action )
 
  754  histoAction( action->data().toString(), action->isChecked() );
 
  759  if ( actionName.isEmpty() )
 
  763  QgsDebugMsgLevel( QStringLiteral( 
"band = %1 action = %2" ).arg( cboHistoBand->currentIndex() + 1 ).arg( actionName ), 2 );
 
  766  if ( actionName == QLatin1String( 
"Show markers" ) )
 
  768    mHistoShowMarkers = actionFlag;
 
  770    settings.
setValue( QStringLiteral( 
"Raster/histogram/showMarkers" ), mHistoShowMarkers );
 
  771    updateHistoMarkers();
 
  774  else if ( actionName == QLatin1String( 
"Zoom min_max" ) )
 
  776    mHistoZoomToMinMax = actionFlag;
 
  778    settings.
setValue( QStringLiteral( 
"Raster/histogram/zoomToMinMax" ), mHistoZoomToMinMax );
 
  781  else if ( actionName == QLatin1String( 
"Update min_max" ) )
 
  783    mHistoUpdateStyleToMinMax = actionFlag;
 
  785    settings.
setValue( QStringLiteral( 
"Raster/histogram/updateStyleToMinMax" ), mHistoUpdateStyleToMinMax );
 
  788  else if ( actionName == QLatin1String( 
"Show all" ) )
 
  790    mHistoShowBands = ShowAll;
 
  795  else if ( actionName == QLatin1String( 
"Show selected" ) )
 
  797    mHistoShowBands = ShowSelected;
 
  802  else if ( actionName == QLatin1String( 
"Show RGB" ) )
 
  804    mHistoShowBands = ShowRGB;
 
  809  else if ( actionName == QLatin1String( 
"Draw lines" ) )
 
  811    mHistoDrawLines = actionFlag;
 
  813    settings.
setValue( QStringLiteral( 
"Raster/histogram/drawLines" ), mHistoDrawLines );
 
  814    btnHistoCompute_clicked(); 
 
  818  else if ( actionName == 
"Load apply all" )
 
  820    mHistoLoadApplyAll = actionFlag;
 
  821    settings.setValue( 
"/Raster/histogram/loadApplyAll", mHistoLoadApplyAll );
 
  827  else if ( actionName.left( 5 ) == QLatin1String( 
"Load " ) && mRendererWidget )
 
  829    QVector<int> myBands;
 
  833    double minMaxValues[2];
 
  836    if ( mHistoLoadApplyAll )
 
  838      int myBandCountInt = mRasterLayer->
bandCount();
 
  839      for ( 
int i = 1; i <= myBandCountInt; i++ )
 
  841        if ( i != cboHistoBand->currentIndex() + 1 )
 
  848    myBands << cboHistoBand->currentIndex() + 1;
 
  852    double myStdDev = 1.0;
 
  853    if ( actionName == 
"Load stddev" )
 
  855      myStdDev = mRendererWidget->
stdDev().toDouble();
 
  860    leHistoMin->blockSignals( 
true );
 
  861    leHistoMax->blockSignals( 
true );
 
  864    const auto constMyBands = myBands;
 
  865    for ( 
const int bandNo : constMyBands )
 
  869      if ( actionName == 
"Load actual" )
 
  871        ok = mRendererWidget->bandMinMax( QgsRasterRendererWidget::Actual,
 
  872                                          bandNo, minMaxValues );
 
  874      else if ( actionName == 
"Load estimate" )
 
  876        ok = mRendererWidget->bandMinMax( QgsRasterRendererWidget::Estimate,
 
  877                                          bandNo, minMaxValues );
 
  879      else if ( actionName == 
"Load extent" )
 
  881        ok = mRendererWidget->bandMinMax( QgsRasterRendererWidget::CurrentExtent,
 
  882                                          bandNo, minMaxValues );
 
  884      else if ( actionName == 
"Load 1 stddev" ||
 
  885                actionName == 
"Load stddev" )
 
  887        ok = mRendererWidget->bandMinMaxFromStdDev( myStdDev, bandNo, minMaxValues );
 
  892      cboHistoBand->setCurrentIndex( bandNo - 1 );
 
  893      if ( !ok || actionName == QLatin1String( 
"Load reset" ) )
 
  907        leHistoMin->setText( QString::number( minMaxValues[0] ) );
 
  908        leHistoMax->setText( QString::number( minMaxValues[1] ) );
 
  915    leHistoMin->blockSignals( 
false );
 
  916    leHistoMax->blockSignals( 
false );
 
  917    updateHistoMarkers();
 
  919  else if ( actionName == QLatin1String( 
"Compute histogram" ) )
 
  921    btnHistoCompute_clicked();
 
 
  930void QgsRasterHistogramWidget::applyHistoMin()
 
  932  if ( ! mRendererWidget )
 
  935  const int bandNo = cboHistoBand->currentIndex() + 1;
 
  936  const QList< int > selectedBands = rendererSelectedBands();
 
  938  for ( 
int i = 0; i <= selectedBands.size(); i++ )
 
  942      min = leHistoMin->text();
 
  943      if ( mHistoUpdateStyleToMinMax && mRendererWidget->
min( i ) != min )
 
  945        mRendererWidget->
setMin( min, i );
 
  958  updateHistoMarkers();
 
  960  if ( ! min.isEmpty() && mHistoZoomToMinMax && mHistoZoomer )
 
  962    QRectF rect = mHistoZoomer->zoomRect();
 
  963    rect.setLeft( min.toDouble() );
 
  964    mHistoZoomer->zoom( rect );
 
  969void QgsRasterHistogramWidget::applyHistoMax()
 
  971  if ( ! mRendererWidget )
 
  974  const int bandNo = cboHistoBand->currentIndex() + 1;
 
  975  const QList< int > mySelectedBands = rendererSelectedBands();
 
  977  for ( 
int i = 0; i <= mySelectedBands.size(); i++ )
 
  981      max = leHistoMax->text();
 
  982      if ( mHistoUpdateStyleToMinMax && mRendererWidget->
max( i ) != max )
 
  984        mRendererWidget->
setMax( max, i );
 
  997  updateHistoMarkers();
 
  999  if ( ! max.isEmpty() && mHistoZoomToMinMax && mHistoZoomer )
 
 1001    QRectF rect = mHistoZoomer->zoomRect();
 
 1002    rect.setRight( max.toDouble() );
 
 1003    mHistoZoomer->zoom( rect );
 
 1008void QgsRasterHistogramWidget::btnHistoMin_toggled()
 
 1010  if ( mpPlot && mHistoPicker )
 
 1012    if ( QApplication::overrideCursor() )
 
 1013      QApplication::restoreOverrideCursor();
 
 1014    if ( btnHistoMin->isChecked() )
 
 1016      btnHistoMax->setChecked( 
false );
 
 1017      QApplication::setOverrideCursor( Qt::PointingHandCursor );
 
 1020      mHistoZoomer->setEnabled( ! btnHistoMin->isChecked() );
 
 1021    mHistoPicker->setEnabled( btnHistoMin->isChecked() );
 
 1023  updateHistoMarkers();
 
 1026void QgsRasterHistogramWidget::btnHistoMax_toggled()
 
 1028  if ( mpPlot && mHistoPicker )
 
 1030    if ( QApplication::overrideCursor() )
 
 1031      QApplication::restoreOverrideCursor();
 
 1032    if ( btnHistoMax->isChecked() )
 
 1034      btnHistoMin->setChecked( 
false );
 
 1035      QApplication::setOverrideCursor( Qt::PointingHandCursor );
 
 1038      mHistoZoomer->setEnabled( ! btnHistoMax->isChecked() );
 
 1039    mHistoPicker->setEnabled( btnHistoMax->isChecked() );
 
 1041  updateHistoMarkers();
 
 1048  if ( !scale ) 
return QString();
 
 1050  QList< double > minorTicks = scale->ticks( QwtScaleDiv::MinorTick );
 
 1051  QList< double > majorTicks = scale->ticks( QwtScaleDiv::MajorTick );
 
 1052  const double diff = ( minorTicks[1] - minorTicks[0] ) / div;
 
 1053  double min = majorTicks[0] - diff;
 
 1055    min -= ( majorTicks[1] - majorTicks[0] );
 
 1056  const double max = scale->upperBound();
 
 1057  double closest = target;
 
 1058  double current = min;
 
 1060  while ( current < max )
 
 1063    if ( current > target )
 
 1065      closest = ( std::fabs( target - current + diff ) < std::fabs( target - current ) ) ? current - diff : current;
 
 1071  return QLocale().toString( closest );
 
 
 1074void QgsRasterHistogramWidget::histoPickerSelected( QPointF pos )
 
 1076  if ( btnHistoMin->isChecked() || btnHistoMax->isChecked() )
 
 1078    const QwtScaleDiv *scale = &mpPlot->axisScaleDiv( QwtPlot::xBottom );
 
 1080    if ( btnHistoMin->isChecked() )
 
 1084      btnHistoMin->setChecked( 
false );
 
 1090      btnHistoMax->setChecked( 
false );
 
 1093  if ( QApplication::overrideCursor() )
 
 1094    QApplication::restoreOverrideCursor();
 
 1097void QgsRasterHistogramWidget::histoPickerSelectedQwt5( 
QwtDoublePoint pos )
 
 1099  histoPickerSelected( QPointF( pos.x(), pos.y() ) );
 
 1102void QgsRasterHistogramWidget::updateHistoMarkers()
 
 1105  if ( leHistoMin->signalsBlocked() )
 
 1108  if ( !mpPlot || !mHistoMarkerMin || !mHistoMarkerMax )
 
 1111  const int bandNo = cboHistoBand->currentIndex() + 1;
 
 1112  const QList< int > mySelectedBands = histoSelectedBands();
 
 1114  if ( ( ! mHistoShowMarkers && ! btnHistoMin->isChecked() && ! btnHistoMax->isChecked() ) ||
 
 1115       ( ! mySelectedBands.isEmpty() && ! mySelectedBands.contains( bandNo ) ) )
 
 1117    mHistoMarkerMin->hide();
 
 1118    mHistoMarkerMax->hide();
 
 1123  double minVal = mHistoMin;
 
 1124  double maxVal = mHistoMax;
 
 1125  const QString minStr = leHistoMin->text();
 
 1126  const QString maxStr = leHistoMax->text();
 
 1127  if ( !minStr.isEmpty() )
 
 1128    minVal = minStr.toDouble();
 
 1129  if ( !maxStr.isEmpty() )
 
 1130    maxVal = maxStr.toDouble();
 
 1132  QPen linePen = QPen( mHistoColors.at( bandNo ) );
 
 1133  linePen.setStyle( Qt::DashLine );
 
 1134  mHistoMarkerMin->setLineStyle( QwtPlotMarker::VLine );
 
 1135  mHistoMarkerMin->setLinePen( linePen );
 
 1136  mHistoMarkerMin->setXValue( minVal );
 
 1137  mHistoMarkerMin->show();
 
 1138  mHistoMarkerMax->setLineStyle( QwtPlotMarker::VLine );
 
 1139  mHistoMarkerMax->setLinePen( linePen );
 
 1140  mHistoMarkerMax->setXValue( maxVal );
 
 1141  mHistoMarkerMax->show();
 
 1147QList< int > QgsRasterHistogramWidget::histoSelectedBands()
 
 1149  QList< int > mySelectedBands;
 
 1151  if ( mHistoShowBands != ShowAll )
 
 1153    if ( mHistoShowBands == ShowSelected )
 
 1155      mySelectedBands << cboHistoBand->currentIndex() + 1;
 
 1157    else if ( mHistoShowBands == ShowRGB )
 
 1159      mySelectedBands = rendererSelectedBands();
 
 1163  return mySelectedBands;
 
 1166QList< int > QgsRasterHistogramWidget::rendererSelectedBands()
 
 1168  QList< int > mySelectedBands;
 
 1170  if ( ! mRendererWidget )
 
 1172    mySelectedBands << -1 << -1 << -1; 
 
 1173    return mySelectedBands;
 
 1176  if ( mRendererName == QLatin1String( 
"singlebandgray" ) ||
 
 1177       mRendererName == QLatin1String( 
"singlebandpseudocolor" ) )
 
 1181  else if ( mRendererName == QLatin1String( 
"multibandcolor" ) )
 
 1183    for ( 
int i = 0; i <= 2; i++ )
 
 1189  return mySelectedBands;
 
 1192QPair< QString, QString > QgsRasterHistogramWidget::rendererMinMax( 
int bandNo )
 
 1194  QPair< QString, QString > myMinMax;
 
 1196  if ( ! mRendererWidget )
 
 1199  if ( mRendererName == QLatin1String( 
"singlebandgray" ) ||
 
 1200       mRendererName == QLatin1String( 
"singlebandpseudocolor" ) )
 
 1204      myMinMax.first = mRendererWidget->
min();
 
 1205      myMinMax.second = mRendererWidget->
max();
 
 1208  else if ( mRendererName == QLatin1String( 
"multibandcolor" ) )
 
 1210    for ( 
int i = 0; i <= 2; i++ )
 
 1214        myMinMax.first = mRendererWidget->
min( i );
 
 1215        myMinMax.second = mRendererWidget->
max( i );
 
 1231  if ( myMinMax.first.isEmpty() )
 
 1232    myMinMax.first = QLocale().toString( mHistoMin );
 
 1233  if ( myMinMax.second.isEmpty() )
 
 1234    myMinMax.second = QLocale().toString( mHistoMax );
 
 1236  QgsDebugMsgLevel( QStringLiteral( 
"bandNo %1 got min/max [%2] [%3]" ).arg( bandNo ).arg( myMinMax.first, myMinMax.second ), 2 );
 
@ Size
Original data source size (and thus resolution) is known, it is not always available,...
 
DataType
Raster data types.
 
@ Int16
Sixteen bit signed integer (qint16)
 
@ Int8
Eight bit signed integer (qint8) (added in QGIS 3.30)
 
@ 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.
 
@ StretchToMinimumMaximum
Linear histogram.
 
@ NoEnhancement
Default color scaling algorithm, no scaling is applied.
 
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.
 
virtual Qgis::RasterInterfaceCapabilities capabilities() const
Returns the capabilities supported by the interface.
 
virtual int xSize() const
Gets raster size.
 
Q_DECL_DEPRECATED QgsRasterBandStats bandStatistics(int bandNo, int stats, const QgsRectangle &extent=QgsRectangle(), int sampleSize=0, QgsRasterBlockFeedback *feedback=nullptr)
Returns the band statistics.
 
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 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.
 
This class is a composition of two QSettings instances:
 
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), Section section=NoSection) const
Returns the value for setting key.
 
void setValue(const QString &key, const QVariant &value, QgsSettings::Section section=QgsSettings::NoSection)
Sets the value of setting key to value.
 
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.
 
#define QgsDebugMsgLevel(str, level)
 
#define QgsDebugError(str)