24#include "qgsogrprovider.h"
35using namespace Qt::StringLiterals;
38std::once_flag usageInformationLoaderFlag;
39QHash<Qgis::RasterAttributeTableFieldUsage, QgsRasterAttributeTable::UsageInformation> QgsRasterAttributeTable::sUsageInformation;
51 const QList<Qgis::RasterAttributeTableFieldUsage> fieldUsages {
usages() };
64 for (
int idx = 0; idx < mFields.count(); ++idx )
66 const Field f { mFields.at( idx ) };
97 for (
Field &f : mFields )
135 const QList<Qgis::RasterAttributeTableFieldUsage> fieldUsages {
usages() };
147 QList<Qgis::RasterAttributeTableFieldUsage>
usages;
150 usages.push_back( field.usage );
156QList<int> QgsRasterAttributeTable::intUsages()
const
161 usages.push_back(
static_cast<int>( field.usage ) );
169 QList<Qgis::RasterAttributeTableFieldUsage> fieldUsages {
usages() };
172 &&
row < mData.count()
177 const QVariantList rowData = mData.at(
row );
198 QList<Qgis::RasterAttributeTableFieldUsage> fieldUsages {
usages() };
199 const QVariantList rowData = mData.at(
row );
240 for (
const QVariantList &
row : std::as_const( mData ) )
243 for (
const auto &cell : std::as_const(
row ) )
245 attributes.append( cell );
249 features.append( feature );
266 const int realPos { std::clamp( position, 0,
static_cast<int>( mFields.count() ) ) };
268 if ( field.
name.isEmpty() )
272 *errorMessage = tr(
"Field name must not be empty." );
285 *errorMessage = tr(
"A field with name '%1' already exists." ).arg( field.
name );
291 static const QList<Qgis::RasterAttributeTableFieldUsage> uniqueUsages {
315 *errorMessage = tr(
"A field with unique usage '%1' already exists." ).arg(
usageName( field.
usage ) );
320 mFields.insert( realPos, field );
322 for (
auto it = mData.begin(); it != mData.end(); ++it )
326 switch ( field.
type )
328 case QMetaType::Type::QChar:
329 case QMetaType::Type::Int:
330 case QMetaType::Type::UInt:
331 case QMetaType::Type::LongLong:
332 case QMetaType::Type::ULongLong:
333 case QMetaType::Type::Double:
337 defaultValue = QString();
339 it->insert( realPos, defaultValue );
370 const QList<Qgis::RasterAttributeTableFieldUsage> colors {
373 int idx { position };
387 if ( fieldIndex < 0 || fieldIndex >=
fields().count() )
398 mFields[fieldIndex].
usage = usage;
410 *errorMessage = tr(
"A color ramp can only be added to an athematic attribute table." );
413 const QList<Qgis::RasterAttributeTableFieldUsage> colors {
423 int idx { position };
437 return insertField(
static_cast<int>( mFields.count() ), name, usage,
type, errorMessage );
447 return insertField(
static_cast<int>( mFields.count() ), field, errorMessage );
452 const auto toRemove { std::find_if( mFields.begin(), mFields.end(), [&name](
Field &f ) ->
bool { return f.name == name; } ) };
454 if ( toRemove != mFields.end() )
456 const int idx {
static_cast<int>( std::distance( mFields.begin(), toRemove ) ) };
457 mFields.erase( toRemove );
458 for (
auto it = mData.begin(); it != mData.end(); ++it )
469 *errorMessage = tr(
"A field with name '%1' was not found." ).arg( name );
476 const int realPos { std::clamp( position, 0,
static_cast<int>( mData.count() ) ) };
478 if ( rowData.size() != mFields.size() )
482 *errorMessage = tr(
"Row element count differs from field count (%1)." ).arg( mFields.size() );
487 QVariantList dataValid;
489 for (
int idx = 0; idx < mFields.count(); ++idx )
491 QVariant cell( rowData[idx] );
492 if ( !cell.canConvert( mFields.at( idx ).type ) || !cell.convert( mFields.at( idx ).type ) )
496 *errorMessage = tr(
"Row data at column %1 cannot be converted to field type (%2)." ).arg( idx ).arg( QVariant::typeToName( mFields.at( idx ).type ) );
502 dataValid.append( cell );
506 mData.insert( realPos, dataValid );
513 if ( position >= mData.count() || position < 0 || mData.isEmpty() )
517 *errorMessage = tr(
"Position is not valid or the table is empty." );
521 mData.removeAt( position );
528 return insertRow(
static_cast<int>( mData.count() ),
data, errorMessage );
539 std::unique_ptr<QgsVectorFileWriter> writer;
542 QString cleanedPath { path };
543 if ( path.endsWith( u
".dbf"_s, Qt::CaseSensitivity::CaseInsensitive ) )
545 cleanedPath.chop( 4 );
552 cleanedPath.append( u
".dbf"_s );
559 *errorMessage = tr(
"Error creating Raster Attribute Table table: %1." ).arg( writer->errorMessage() );
565 bool result { writer->addFeatures( features ) };
571 *errorMessage = tr(
"Error creating Raster Attribute Table table: could not add rows." );
576 result = writer->flushBuffer();
580 mFilePath = cleanedPath;
590 if ( !ratDbfSource.isValid() )
594 *errorMessage = tr(
"Error reading Raster Attribute Table table from file: invalid layer." );
599 QList<Field> oldFields = mFields;
600 QList<QVariantList> oldData = mData;
605 bool hasValueField {
false };
606 for (
const QgsField &field : ratDbfSource.fields() )
609 QMetaType::Type
type { field.type() };
611 if (
type == QMetaType::Type::LongLong
614 type = QMetaType::Type::Int;
619 hasValueField =
true;
632 if ( ! hasValueField && mFields.count() > 1 && ( mFields.at( 0 ).type == QMetaType::Type::Int || mFields.at( 0 ).type == QMetaType::Type::QChar || mFields.at( 0 ).type == QMetaType::Type::UInt || mFields.at( 0 ).type == QMetaType::Type::LongLong || mFields.at( 0 ).type == QMetaType::Type::ULongLong ) )
637 const int fieldCount {
static_cast<int>( ratDbfSource.fields().count() ) };
646 *errorMessage = tr(
"Error reading Raster Attribute Table table from file: number of fields and number of attributes do not match." );
666 if ( mFields.isEmpty() )
668 errors.push_back( tr(
"The attribute table has no fields." ) );
671 if ( mData.isEmpty() )
673 errors.push_back( tr(
"The attribute table has no rows." ) );
676 const QList<Qgis::RasterAttributeTableFieldUsage> fieldUsages {
usages() };
679 if ( !isMinMax && !isValueRamp )
681 errors.push_back( tr(
"The attribute table has no MinMax nor a pair of Min and Max fields." ) );
693 errors.push_back( tr(
"The attribute table has some but not all the fields required for color definition (Red, Green, Blue)." ) );
712 errors.push_back( tr(
"The attribute table has some but not all the fields required for color ramp definition (RedMin, GreenMin, BlueMin, RedMax, GreenMax, BlueMax)." ) );
714 else if ( !isValueRamp )
716 errors.push_back( tr(
"The attribute table has all the fields required for color ramp definition (RedMin, GreenMin, BlueMin, RedMax, GreenMax, BlueMax) but no Min and Max field." ) );
720 if ( errorMessage && !errors.isEmpty() )
722 *errorMessage = errors.join( QChar(
'\n' ) );
725 return errors.isEmpty();
735 for (
const Field &f : std::as_const( mFields ) )
737 if ( f.name == name )
755 QList<QgsRasterAttributeTable::Field> result;
756 for (
const Field &f : std::as_const( mFields ) )
758 if ( f.usage == fieldUsage )
760 result.push_back( f );
773 QVariant newVal =
value;
774 if ( column >= mFields.length() || !
value.canConvert( mFields.at( column ).type ) || !newVal.convert( mFields.at( column ).type ) )
779 const QVariant oldVal = mData[
row][column];
781 if ( newVal != oldVal )
783 mData[
row][column] = newVal;
796 return mData[
row][column];
801 const QList<Qgis::RasterAttributeTableFieldUsage> fieldUsages {
usages() };
814 double min { std::numeric_limits<double>::max() };
815 for (
int rowIdx = 0; rowIdx < mData.count(); ++rowIdx )
817 min = std::min( min,
value( rowIdx, fieldIdx ).toDouble( &ok ) );
820 return std::numeric_limits<double>::quiet_NaN();
824 if ( fieldIdx == -1 || !ok )
826 return std::numeric_limits<double>::quiet_NaN();
836 const QList<Qgis::RasterAttributeTableFieldUsage> fieldUsages {
usages() };
849 double max { std::numeric_limits<double>::lowest() };
850 for (
int rowIdx = 0; rowIdx < mData.count(); ++rowIdx )
852 max = std::max( max,
value( rowIdx, fieldIdx ).toDouble( &ok ) );
855 return std::numeric_limits<double>::quiet_NaN();
859 if ( fieldIdx == -1 || !ok )
861 return std::numeric_limits<double>::quiet_NaN();
873 return QVariantList();
876 const QList<Qgis::RasterAttributeTableFieldUsage> fieldUsages {
usages() };
881 for (
int rowIdx = 0; rowIdx < mData.count(); ++rowIdx )
884 if ( matchValue ==
value( rowIdx, colIdx ).toDouble( &ok ) && ok )
886 return mData.at( rowIdx );
894 for (
int rowIdx = 0; rowIdx < mData.count(); ++rowIdx )
897 if ( matchValue >=
value( rowIdx, minColIdx ).toDouble( &ok ) && ok )
899 if ( matchValue <
value( rowIdx, maxColIdx ).toDouble( &ok ) && ok )
901 return mData.at( rowIdx );
906 return QVariantList();
911 static const QStringList minValueNames { {
919 static const QStringList maxValueNames { {
927 const QString fieldLower { name.toLower() };
929 if (
type == QMetaType::Type::Double ||
type == QMetaType::Type::Int ||
type == QMetaType::Type::UInt ||
type == QMetaType::Type::LongLong ||
type == QMetaType::Type::ULongLong )
931 if ( minValueNames.contains( fieldLower ) )
935 else if ( maxValueNames.contains( fieldLower ) )
939 else if ( fieldLower ==
"value"_L1 )
943 else if ( fieldLower ==
"count"_L1 )
949 else if (
type != QMetaType::Type::Double )
951 if ( fieldLower.contains(
"red" ) || fieldLower ==
"r"_L1 )
953 if ( fieldLower.contains(
"min" ) )
957 else if ( fieldLower.contains(
"max" ) )
966 else if ( fieldLower.contains(
"green" ) || fieldLower ==
"g"_L1 )
968 if ( fieldLower.contains(
"min" ) )
972 else if ( fieldLower.contains(
"max" ) )
981 else if ( fieldLower.contains(
"blue" ) || fieldLower ==
"b"_L1 )
983 if ( fieldLower.contains(
"min" ) )
987 else if ( fieldLower.contains(
"max" ) )
996 else if ( fieldLower.contains(
"alpha" ) || fieldLower ==
"a"_L1 )
998 if ( fieldLower.contains(
"min" ) )
1002 else if ( fieldLower.contains(
"max" ) )
1015 if (
type == QMetaType::Type::QString )
1036 return tr(
"Green" );
1038 return tr(
"Blue" );
1040 return tr(
"Alpha" );
1042 return tr(
"Red Minimum" );
1044 return tr(
"Green Minimum" );
1046 return tr(
"Blue Minimum" );
1048 return tr(
"Alpha Minimum" );
1050 return tr(
"Red Maximum" );
1052 return tr(
"Green Maximum" );
1054 return tr(
"Blue Maximum" );
1056 return tr(
"Alpha Maximum" );
1058 return tr(
"Generic" );
1060 return tr(
"Name" );
1062 return tr(
"Pixel Count" );
1064 return tr(
"Maximum Count" );
1066 return tr(
"Value" );
1068 return tr(
"Minimum Value" );
1070 return tr(
"Maximum Value" );
1077 static const QList<Qgis::RasterAttributeTableFieldUsage> valueColorUsages { {
1094 return valueColorUsages;
1125 rat->
appendRow( QVariantList() << klass.value << klass.label << 0 << 0 << 0 << 255 );
1126 rat->
setColor(
static_cast<int>( rat->
data().length() - 1 ), klass.color );
1131 *bandNumber = palettedRenderer->inputBand();
1142 switch ( shaderFunction->colorRampType() )
1157 const QList<QgsColorRampShader::ColorRampItem> rampItems { shaderFunction->colorRampItemList() };
1158 if ( rampItems.size() > 1 )
1160 QColor color1 { rampItems.at( 0 ).color };
1161 QString label1 { rampItems.at( 0 ).label };
1162 QVariant value1( rampItems.at( 0 ).value );
1163 const int rampItemSize =
static_cast<int>( rampItems.size() );
1164 for (
int i = 1; i < rampItemSize; ++i )
1167 rat->
appendRow( QVariantList() << value1 << rampItem.
value << u
"%1 - %2"_s.arg( label1, rampItem.
label ) << 0 << 0 << 0 << 255 << 0 << 0 << 0 << 255 );
1168 rat->
setRamp(
static_cast<int>( rat->
data().length() - 1 ), color1, rampItem.
color );
1169 label1 = rampItem.
label;
1170 value1 = rampItem.
value;
1171 color1 = rampItem.
color;
1186 const QList<QgsColorRampShader::ColorRampItem> rampItems { shaderFunction->colorRampItemList() };
1187 if ( rampItems.size() > 1 )
1189 QColor color1 { rampItems.at( 0 ).color };
1190 QString label1 { rampItems.at( 0 ).label };
1191 QVariant value1( rampItems.at( 0 ).value );
1192 const int rampItemSize =
static_cast<int>( rampItems.size() );
1193 for (
int i = 1; i < rampItemSize; ++i )
1196 rat->
appendRow( QVariantList() << value1 << rampItem.
value << u
"%1 - %2"_s.arg( label1, rampItem.
label ) << 0 << 0 << 0 << 255 << 0 << 0 << 0 << 255 );
1197 rat->
setRamp(
static_cast<int>( rat->
data().length() - 1 ), color1, rampItem.
color );
1198 label1 = rampItem.
label;
1199 value1 = rampItem.
value;
1200 color1 = rampItem.
color;
1214 const QList<QgsColorRampShader::ColorRampItem> rampItems { shaderFunction->colorRampItemList() };
1217 rat->
appendRow( QVariantList() << rampItem.value << rampItem.label << 0 << 0 << 0 << 255 );
1218 rat->
setColor(
static_cast<int>( rat->
data().length() - 1 ), rampItem.color );
1226 *bandNumber = pseudoColorRenderer->inputBand();
1249 std::call_once( usageInformationLoaderFlag, [] {
1250 QgsRasterAttributeTable::sUsageInformation.insert(
1252 { tr(
"General Purpose Field" ),
false,
false,
false,
false,
true,
true, QList<QMetaType::Type>() << QMetaType::Type::QString << QMetaType::Type::Int << QMetaType::Type::LongLong << QMetaType::Type::Double }
1254 QgsRasterAttributeTable::sUsageInformation
1256 QgsRasterAttributeTable::sUsageInformation
1258 QgsRasterAttributeTable::sUsageInformation
1259 .insert(
Qgis::RasterAttributeTableFieldUsage::MinMax, { tr(
"Class Value (min=max)" ),
true,
true,
false,
false,
true,
false, QList<QMetaType::Type>() << QMetaType::Type::Int << QMetaType::Type::LongLong << QMetaType::Type::Double } );
1260 QgsRasterAttributeTable::sUsageInformation
1261 .insert(
Qgis::RasterAttributeTableFieldUsage::Min, { tr(
"Class Minimum Value" ),
true,
true,
false,
false,
true,
false, QList<QMetaType::Type>() << QMetaType::Type::Int << QMetaType::Type::LongLong << QMetaType::Type::Double } );
1262 QgsRasterAttributeTable::sUsageInformation
1263 .insert(
Qgis::RasterAttributeTableFieldUsage::Max, { tr(
"Class Maximum Value" ),
true,
true,
false,
false,
true,
false, QList<QMetaType::Type>() << QMetaType::Type::Int << QMetaType::Type::LongLong << QMetaType::Type::Double } );
1264 QgsRasterAttributeTable::sUsageInformation
1266 QgsRasterAttributeTable::sUsageInformation
1268 QgsRasterAttributeTable::sUsageInformation
1270 QgsRasterAttributeTable::sUsageInformation
1272 QgsRasterAttributeTable::sUsageInformation
1274 QgsRasterAttributeTable::sUsageInformation
1276 QgsRasterAttributeTable::sUsageInformation
1278 QgsRasterAttributeTable::sUsageInformation
1280 QgsRasterAttributeTable::sUsageInformation
1282 QgsRasterAttributeTable::sUsageInformation
1284 QgsRasterAttributeTable::sUsageInformation
1286 QgsRasterAttributeTable::sUsageInformation
1289 QgsRasterAttributeTable::sUsageInformation
1292 return QgsRasterAttributeTable::sUsageInformation;
1295void QgsRasterAttributeTable::setType()
1297 const QList<Qgis::RasterAttributeTableFieldUsage> fieldUsages {
usages() };
1303QHash<int, QgsRasterAttributeTable::UsageInformation> QgsRasterAttributeTable::usageInformationInt()
1305 QHash<int, QgsRasterAttributeTable::UsageInformation> usageInfoInt;
1307 for (
auto it = usageInfo.cbegin(); it != usageInfo.cend(); ++it )
1309 usageInfoInt.insert(
static_cast<int>( it.key() ), it.value() );
1311 return usageInfoInt;
1322 QList<QgsRasterAttributeTable::MinMaxClass> classes;
1325 QgsDebugError(
"minMaxClasses was called on an invalid RAT" );
1329 const QList<Qgis::RasterAttributeTableFieldUsage> fieldUsages {
usages() };
1333 QgsDebugError(
"minMaxClasses was called on a ramp raster" );
1339 Q_ASSERT( minMaxIndex >= 0 );
1341 int classificationIndex = classificationColumn;
1342 if ( classificationIndex >= 0 && classificationIndex < mFields.count() )
1344 const Field classificationField { mFields.at( classificationIndex ) };
1347 QgsDebugError(
"minMaxClasses was called with a classification column which is not suitable for classification" );
1351 else if ( classificationIndex == -1 )
1364 classificationIndex = minMaxIndex;
1367 else if ( classificationIndex >= mFields.count() )
1369 QgsDebugError(
"minMaxClasses was called with a classification column out of range" );
1373 if ( classificationIndex >= 0 )
1377 for (
const QVariantList &
row : std::as_const( mData ) )
1379 const QString label {
row.at( classificationIndex ).toString() };
1381 const double value {
row.at( minMaxIndex ).toDouble( &ok ) };
1385 QgsDebugError(
"minMaxClasses could not convert a MinMax value to double" );
1388 if ( labels.contains( label ) )
1390 classes[labels.indexOf( label )].minMaxValues.push_back(
value );
1394 labels.push_back( label );
1395 classes.push_back( { label, {
value },
color( rowIdx ) } );
1406 const QList<Qgis::RasterAttributeTableFieldUsage> fieldUsages {
usages() };
1409 const bool isRange { minIdx >= 0 && maxIdx >= 0 };
1411 int labelIdx { labelColumn };
1412 if ( labelColumn < 0
1413 || labelColumn >=
fields().count()
1419 if ( !mData.isEmpty() && ( minIdx >= 0 && maxIdx >= 0 ) )
1426 const double range { max - min };
1430 if ( !std::isnan( min ) && !std::isnan( max ) )
1432 const QList<QVariantList> dataCopy(
orderedRows() );
1435 for (
const Field &f : std::as_const( mFields ) )
1439 for (
const QVariantList &r : std::as_const( dataCopy ) )
1444 QColor lastColor {
ramp.color1() };
1446 if ( hasColorOrRamp )
1449 ramp.setColor2( orderedRat.
hasColor() ? orderedRat.
color(
static_cast<int>( orderedRat.
data().count() - 1 ) ) : orderedRat.
ramp(
static_cast<int>( orderedRat.
data().count() - 1 ) ).
color2() );
1453 auto labelFromField = [&](
int rowIdx ) -> QString {
1456 return u
"%L1 - %L2"_s.arg( orderedRat.
value( rowIdx, minIdx ).toDouble() ).arg( orderedRat.
value( rowIdx, maxIdx ).toDouble() );
1458 const QVariant val( orderedRat.
value( rowIdx, labelIdx ) );
1461 switch ( val.userType() )
1463 case QMetaType::Type::QChar:
1464 return QString( val.toChar() );
1465 case QMetaType::Type::Int:
1466 res = QLocale().toString( val.toInt( &ok ) );
1468 case QMetaType::Type::LongLong:
1469 res = QLocale().toString( val.toLongLong( &ok ) );
1471 case QMetaType::Type::UInt:
1472 res = QLocale().toString( val.toUInt( &ok ) );
1474 case QMetaType::Type::ULongLong:
1475 res = QLocale().toString( val.toULongLong( &ok ) );
1477 case QMetaType::Type::Double:
1478 res = QLocale().toString( val.toDouble( &ok ),
'g' );
1480 case QMetaType::Type::QString:
1482 return val.toString();
1484 return ok ? res : val.toString();
1490 if ( orderedRat.
hasColor() && isRange )
1492 labels.push_back( labelFromField( 0 ) );
1494 for (
int rowIdx = 1; rowIdx < orderedRat.
data().count(); ++rowIdx )
1496 const double offset { ( orderedRat.
value( rowIdx, minIdx ).toDouble() - min ) / range };
1497 const QColor
color { orderedRat.
color( rowIdx - 1 ) };
1499 labels.push_back( labelFromField( rowIdx ) );
1508 else if ( orderedRat.
hasRamp() && isRange )
1510 double prevOffset { 0 };
1511 labels.push_back( labelFromField( 0 ) );
1512 for (
int rowIdx = 1; rowIdx < orderedRat.
data().count(); ++rowIdx )
1514 labels.push_back( labelFromField( rowIdx ) );
1515 const int prevRowIdx { rowIdx - 1 };
1516 const double offset { ( ( orderedRat.
value( rowIdx, minIdx ).toDouble() + orderedRat.
value( prevRowIdx, maxIdx ).toDouble() ) / 2.0 - min ) / range };
1524 stops.append(
QgsGradientStop( offset + std::numeric_limits<double>::epsilon(), currentRamp.
color1() ) );
1526 prevOffset = offset;
1534 labels.push_back( labelFromField( 0 ) );
1536 for (
int rowIdx = 1; rowIdx < orderedRat.
data().count(); ++rowIdx )
1538 const int prevRowIdx { rowIdx - 1 };
1539 const double offset { ( ( orderedRat.
value( rowIdx, minIdx ).toDouble() + orderedRat.
value( prevRowIdx, maxIdx ).toDouble() ) / 2.0 - min ) / range };
1541 labels.push_back( labelFromField( rowIdx ) );
1548 ramp.setStops( stops );
1562 std::unique_ptr<QgsRasterRenderer> renderer;
1566 std::unique_ptr<QgsColorRamp>
ramp;
1569 ramp = std::make_unique<QgsRandomColorRamp>();
1572 if ( classes.isEmpty() )
1575 renderer = std::make_unique<QgsPalettedRasterRenderer>( provider, bandNumber, classes );
1579 auto pseudoColorRenderer = std::make_unique<QgsSingleBandPseudoColorRenderer>( provider, bandNumber );
1583 int labelColumn { classificationColumn };
1584 if ( labelColumn < 0 )
1586 const QList<Qgis::RasterAttributeTableFieldUsage> fieldUsages {
usages() };
1588 if ( labelColumn < 0 )
1594 pseudoColorRenderer->setClassificationMin(
minimumValue() );
1595 pseudoColorRenderer->setClassificationMax(
maximumValue() );
1597 pseudoColorRenderer->createShader(
1600 if ( pseudoColorRenderer->shader() )
1602 pseudoColorRenderer->shader()->setMaximumValue(
maximumValue() );
1603 pseudoColorRenderer->shader()->setMinimumValue(
minimumValue() );
1609 const bool labelsAreUsable {
ramp->count() > 2 && labels.count() ==
ramp->count() - 1 };
1611 if ( labelsAreUsable )
1613 QList<QgsColorRampShader::ColorRampItem> newItemList;
1616 for (
const QString &label : std::as_const( labels ) )
1618 if ( stopIdx >=
ramp->count() - 2 )
1624 newItemList.push_back( item );
1629 newItemList.push_back( item );
1630 shaderFunction->setColorRampItemList( newItemList );
1634 renderer = std::move( pseudoColorRenderer );
1637 return renderer.release();
1642 const QList<Qgis::RasterAttributeTableFieldUsage> fieldUsages {
usages() };
1645 const bool isRange { minIdx >= 0 && maxIdx >= 0 };
1646 QList<QVariantList> dataCopy( mData );
1650 std::sort( dataCopy.begin(), dataCopy.end(), [&](
const QVariantList &first,
const QVariantList &second ) ->
bool {
1651 return ( first.at( maxIdx ).toDouble() + first.at( minIdx ).toDouble() ) < ( second.at( maxIdx ).toDouble() + second.at( minIdx ).toDouble() );
1657 if ( minMaxIdx < 0 )
1663 std::sort( dataCopy.begin(), dataCopy.end(), [&](
const QVariantList &first,
const QVariantList &second ) ->
bool { return first.at( minMaxIdx ).toDouble() < second.at( minMaxIdx ).toDouble(); } );
@ Exact
Assigns the color of the exact matching value in the color ramp item list.
@ Linear
Interpolates the color between two class breaks linearly.
@ Discrete
Assigns the color of the higher class for every pixel between two class breaks.
RasterAttributeTableType
The RasterAttributeTableType enum represents the type of RAT.
@ Continuous
Uses breaks from color palette.
RasterAttributeTableFieldUsage
The RasterAttributeTableFieldUsage enum represents the usage of a Raster Attribute Table field.
@ RedMax
Field usage RedMax.
@ PixelCount
Field usage PixelCount.
@ AlphaMax
Field usage AlphaMax.
@ BlueMin
Field usage BlueMin.
@ Alpha
Field usage Alpha.
@ Generic
Field usage Generic.
@ GreenMax
Field usage GreenMax.
@ RedMin
Field usage RedMin.
@ MinMax
Field usage MinMax.
@ BlueMax
Field usage BlueMax.
@ AlphaMin
Field usage AlphaMin.
@ Green
Field usage Green.
@ MaxCount
Not used by QGIS: GDAL Maximum GFU value (equals to GFU_AlphaMax+1 currently).
@ GreenMin
Field usage GreenMin.
A ramp shader will color a raster pixel based on a list of values ranges in a ramp.
Represents a coordinate reference system (CRS).
Contains information about the context in which a coordinate transform is executed.
Wrapper for iterator of features from vector data provider or vector layer.
bool nextFeature(QgsFeature &f)
Fetch next feature and stores in f, returns true on success.
Wraps a request for features to a vector layer (or directly its vector data provider).
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
void setAttributes(const QgsAttributes &attrs)
Sets the feature's attributes.
int attributeCount() const
Returns the number of attributes attached to the feature.
Encapsulate a field in an attribute table or data source.
Container of fields for a vector layer.
bool append(const QgsField &field, Qgis::FieldOrigin origin=Qgis::FieldOrigin::Provider, int originIndex=-1)
Appends a field.
static QString ensureFileNameHasExtension(const QString &fileName, const QStringList &extensions)
Ensures that a fileName ends with an extension from the provided list of extensions.
Gradient color ramp, which smoothly interpolates between two colors and also supports optional extra ...
QColor color1() const
Returns the gradient start color.
QgsGradientColorRamp * clone() const override
Creates a clone of the color ramp.
QColor color2() const
Returns the gradient end color.
Represents a color stop within a QgsGradientColorRamp color ramp.
Renderer for paletted raster images.
static QgsPalettedRasterRenderer::MultiValueClassData rasterAttributeTableToClassData(const QgsRasterAttributeTable *attributeTable, int classificationColumn=-1, QgsColorRamp *ramp=nullptr)
Reads and returns classes from the Raster Attribute Table attributeTable, optionally classifying the ...
QList< QgsPalettedRasterRenderer::Class > ClassData
Map of value to class properties.
QList< QgsPalettedRasterRenderer::MultiValueClass > MultiValueClassData
Map of multi value to class properties.
The Field class represents a Raster Attribute Table field, including its name, usage and type.
Qgis::RasterAttributeTableFieldUsage usage
bool isRamp() const
Returns true if the field carries a color ramp component information (RedMin/RedMax,...
bool isColor() const
Returns true if the field carries a color component (Red, Green, Blue and optionally Alpha) informati...
Represents a Raster Attribute Table (RAT).
const QgsRasterAttributeTable::Field fieldByName(const QString name, bool *ok=nullptr) const
Returns a field by name or a default constructed field with empty name if the field is not found.
bool isDirty() const
Returns true if the Raster Attribute Table was modified from its last reading from the storage.
bool setColor(const int row, const QColor &color)
Sets the color for the row at rowIndex to color.
QList< QgsRasterAttributeTable::MinMaxClass > minMaxClasses(const int classificationColumn=-1) const
Returns the classes for a thematic Raster Attribute Table, classified by classificationColumn,...
QgsGradientColorRamp ramp(int row) const
Returns the gradient color ramp of the rat row or a default constructed gradient if row does not exis...
QgsRasterRenderer * createRenderer(QgsRasterDataProvider *provider, const int bandNumber, const int classificationColumn=-1)
Creates and returns a (possibly nullptr) raster renderer for the specified provider and bandNumber an...
bool readFromFile(const QString &path, QString *errorMessage=nullptr)
Reads the Raster Attribute Table from a DBF file specified by path, optionally reporting any error in...
QgsGradientColorRamp colorRamp(QStringList &labels, const int labelColumn=-1) const
Returns the color ramp for an athematic Raster Attribute Table setting the labels in labels,...
bool appendField(const QString &name, const Qgis::RasterAttributeTableFieldUsage usage, const QMetaType::Type type, QString *errorMessage=nullptr)
Creates a new field from name, usage and type and appends it to the fields, optionally reporting any ...
bool insertField(int position, const QgsRasterAttributeTable::Field &field, QString *errorMessage=nullptr)
Inserts a new field at position, optionally reporting any error in errorMessage, returns true on succ...
bool hasColor() const
Returns true if the Raster Attribute Table has color RGBA information.
bool setValue(const int row, const int column, const QVariant &value)
Sets the value for row and column.
static QList< Qgis::RasterAttributeTableFieldUsage > valueAndColorFieldUsages()
Returns the list of field usages for colors and values.
QList< QgsRasterAttributeTable::Field > fields() const
Returns the Raster Attribute Table fields.
static QgsRasterAttributeTable * createFromRaster(QgsRasterLayer *rasterLayer, int *bandNumber=nullptr)
Creates a new Raster Attribute Table from a raster layer, the renderer must be Paletted or SingleBand...
bool removeRow(int position=0, QString *errorMessage=nullptr)
Removes the row in the Raster Attribute Table at position, optionally reporting any error in errorMes...
bool appendRow(const QVariantList &data, QString *errorMessage=nullptr)
Appends a row of data to the RAT, optionally reporting any error in errorMessage, returns true on suc...
static QHash< Qgis::RasterAttributeTableFieldUsage, QgsRasterAttributeTable::UsageInformation > usageInformation()
Returns information about supported Raster Attribute Table usages.
Qgis::RasterAttributeTableType type() const
Returns the Raster Attribute Table type.
QList< Qgis::RasterAttributeTableFieldUsage > usages() const
Returns the list of field usages.
QVariantList row(const double matchValue) const
Returns a row of data for the given matchValue or and empty row if there is not match.
bool insertRow(int position, const QVariantList &rowData, QString *errorMessage=nullptr)
Inserts a row of rowData in the Raster Attribute Table at position, optionally reporting any error in...
bool writeToFile(const QString &path, QString *errorMessage=nullptr)
Writes the Raster Attribute Table to a DBF file specified by path, optionally reporting any error in ...
double minimumValue() const
Returns the minimum value of the MinMax (thematic) or Min (athematic) column, returns NaN on errors.
double maximumValue() const
Returns the maximum value of the MinMax (thematic) or Max (athematic) column, returns NaN on errors.
const QList< QgsRasterAttributeTable::Field > fieldsByUsage(const Qgis::RasterAttributeTableFieldUsage fieldUsage) const
Returns the list of fields matching fieldUsage.
void setDirty(bool isDirty)
Sets the Raster Attribute Table dirty state to isDirty;.
bool insertColor(int position, QString *errorMessage=nullptr)
Create RGBA fields and inserts them at position, optionally reporting any error in errorMessage,...
bool isValid(QString *errorMessage=nullptr) const
Returns true if the Raster Attribute Table is valid, optionally reporting validity checks results in ...
const QList< QList< QVariant > > data() const
Returns the Raster Attribute Table rows.
bool setRamp(const int row, const QColor &colorMin, const QColor &colorMax)
Sets the color ramp for the row at rowIndex to colorMin and colorMax.
PRIVATE QColor color(int row) const
Returns the color of the rat row or an invalid color if row does not exist or if there is no color de...
QList< QList< QVariant > > orderedRows() const
Returns the data rows ordered by the value column(s) in ascending order, if the attribute table type ...
static QString usageName(const Qgis::RasterAttributeTableFieldUsage fieldusage)
Returns the translated human readable name of fieldUsage.
bool hasRamp() const
Returns true if the Raster Attribute Table has ramp RGBA information.
QgsFeatureList qgisFeatures() const
Returns the Raster Attribute Table rows as a list of QgsFeature.
bool setFieldUsage(int fieldIndex, const Qgis::RasterAttributeTableFieldUsage usage)
Change the usage of the field at index fieldIndex to usage with checks for allowed types.
QString filePath() const
Returns the (possibly empty) path of the file-based RAT, the path is set when a RAT is read or writte...
bool insertRamp(int position, QString *errorMessage=nullptr)
Create RGBA minimum and maximum fields and inserts them at position, optionally reporting any error i...
QVariant value(const int row, const int column) const
Returns the value for row and column.
QgsFields qgisFields() const
Returns the Raster Attribute Table fields as QgsFields.
static Qgis::RasterAttributeTableFieldUsage guessFieldUsage(const QString &name, const QMetaType::Type type)
Try to determine the field usage from its name and type.
bool removeField(const QString &name, QString *errorMessage=nullptr)
Removes the field with name, optionally reporting any error in errorMessage, returns true on success.
Base class for raster data providers.
Represents a raster layer.
QgsRasterRenderer * renderer() const
Returns the raster's renderer.
QgsRasterDataProvider * dataProvider() override
Returns the source data provider.
Raster renderer pipe that applies colors to a raster.
Interface for all raster shaders.
Raster renderer pipe for single band pseudocolor.
static QMetaType::Type variantTypeToMetaType(QVariant::Type variantType)
Converts a QVariant::Type to a QMetaType::Type.
static QVariant createNullVariant(QMetaType::Type metaType)
Helper method to properly create a null QVariant from a metaType Returns the created QVariant.
Options to pass to QgsVectorFileWriter::writeAsVectorFormat().
QString fileEncoding
Encoding to use.
QString driverName
OGR driver to use.
QStringList layerOptions
List of OGR layer creation options.
QgsVectorFileWriter::ActionOnExistingFile actionOnExistingFile
Action on existing file.
static QgsVectorFileWriter * create(const QString &fileName, const QgsFields &fields, Qgis::WkbType geometryType, const QgsCoordinateReferenceSystem &srs, const QgsCoordinateTransformContext &transformContext, const QgsVectorFileWriter::SaveVectorOptions &options, QgsFeatureSink::SinkFlags sinkFlags=QgsFeatureSink::SinkFlags(), QString *newFilename=nullptr, QString *newLayer=nullptr)
Create a new vector file writer.
@ CreateOrOverwriteFile
Create or overwrite file.
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference).
QList< QgsGradientStop > QgsGradientStopsList
List of gradient stops.
QList< QgsFeature > QgsFeatureList
#define QgsDebugError(str)
Setting options for creating vector data providers.
Properties of a single value class.