QGIS API Documentation 3.29.0-Master (694ebda27c)
qgscreaterasterattributetabledialog.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgscreaterasterattributetabledialog.cpp - QgsCreateRasterAttributeTableDialog
3
4 ---------------------
5 begin : 13.10.2022
6 copyright : (C) 2022 by Alessandro Pasotti
7 email : elpaso at itopen dot it
8 ***************************************************************************
9 * *
10 * This program is free software; you can redistribute it and/or modify *
11 * it under the terms of the GNU General Public License as published by *
12 * the Free Software Foundation; either version 2 of the License, or *
13 * (at your option) any later version. *
14 * *
15 ***************************************************************************/
17#include "qgsrasterlayer.h"
18#include "qgsmessagebar.h"
19#include "qgsgui.h"
20#include <QMessageBox>
21
23 : QDialog( parent )
24 , mRasterLayer( rasterLayer )
25{
26 Q_ASSERT( mRasterLayer );
27 Q_ASSERT( mRasterLayer->canCreateRasterAttributeTable() );
28
29 setupUi( this );
30
31 // Apparently, some drivers (HFA) ignore Min/Max fields and set them to generic,
32 // for this reason we disable the native support for thematic RATs (later in the loop)
33 bool nativeRatSupported { mRasterLayer->dataProvider()->providerCapabilities().testFlag( QgsRasterDataProvider::ProviderCapability::NativeRasterAttributeTable ) };
34
35 connect( mNativeRadioButton, &QRadioButton::toggled, this, &QgsCreateRasterAttributeTableDialog::updateButtons );
36 connect( mDbfRadioButton, &QRadioButton::toggled, this, &QgsCreateRasterAttributeTableDialog::updateButtons );
37
38
39 // Check for existing RATs
40 QStringList existingRatsInfo;
41 if ( mRasterLayer->attributeTableCount() > 0 )
42 {
43 for ( int bandNo = 1; bandNo <= mRasterLayer->bandCount(); ++bandNo )
44 {
45 if ( QgsRasterAttributeTable *rat = mRasterLayer->attributeTable( bandNo ) )
46 {
47 // disable the native support for thematic RATs
48 if ( nativeRatSupported && rat->type() != Qgis::RasterAttributeTableType::Athematic )
49 {
50 nativeRatSupported = false;
51 existingRatsInfo.push_back( tr( "The data provider supports attribute table storage but some drivers do not support 'thematic' types, for this reason the option is disabled." ) );
52 }
53 if ( ! rat->filePath().isEmpty() )
54 {
55 existingRatsInfo.push_back( tr( "Raster band %1 already has an associated attribute table at %2." ).arg( QString::number( bandNo ), rat->filePath() ) );
56 }
57 else
58 {
59 existingRatsInfo.push_back( tr( "Raster band %1 already has an associated attribute table." ).arg( bandNo ) );
60 }
61 }
62 }
63 }
64
65 if ( ! existingRatsInfo.isEmpty() )
66 {
67 mCreateInfoLabel->setText( mCreateInfoLabel->text().append( QStringLiteral( "<br><ul><li>" ) + existingRatsInfo.join( QLatin1String( "</li><li>" ) ) ).append( QStringLiteral( "</ul>" ) ) );
68 mCreateInfoLabel->adjustSize();
69 mCreateInfoLabel->show();
70 }
71
72 if ( ! nativeRatSupported )
73 {
74 mNativeRadioButton->setEnabled( false );
75 mDbfRadioButton->setChecked( true );
76 }
77 else
78 {
79 mDbfPathWidget->setFilter( QStringLiteral( "VAT DBF Files (*.vat.dbf)" ) );
80 if ( QFile::exists( mRasterLayer->dataProvider()->dataSourceUri( ) ) )
81 {
82 mDbfPathWidget->setFilePath( mRasterLayer->dataProvider()->dataSourceUri( ) + ".vat.dbf" );
83 }
84 }
85
86 connect( mButtonBox, &QDialogButtonBox::accepted, this, &QDialog::accept );
87 connect( mButtonBox, &QDialogButtonBox::rejected, this, &QDialog::reject );
88
89 updateButtons();
90
92}
93
95{
96 return mDbfPathWidget->filePath();
97}
98
100{
101 return mDbfRadioButton->isChecked();
102}
103
105{
106 return mOpenRat->isChecked();
107}
108
110{
111 mMessageBar = bar;
112}
113
115{
116 if ( ! visible )
117 {
118 mOpenRat->setChecked( false );
119 }
120
121 mOpenRat->setVisible( visible );
122}
123
125{
126 QString errorMessage;
127 int bandNumber { 0 };
128 QgsRasterAttributeTable *rat { QgsRasterAttributeTable::createFromRaster( mRasterLayer, &bandNumber ) };
129 bool success { false };
130
131 if ( ! rat )
132 {
133 notify( tr( "Error Creating Raster Attribute Table" ),
134 tr( "The raster attribute table could not be created." ),
135 Qgis::MessageLevel::Critical );
136 }
137 else
138 {
139 mRasterLayer->dataProvider()->setAttributeTable( bandNumber, rat );
140
141 // Save it
142 const bool storageIsFile { saveToFile() };
143 if ( storageIsFile )
144 {
145 const QString destinationPath { filePath() };
146 if ( QFile::exists( destinationPath ) && QMessageBox::warning( nullptr, tr( "Confirm Overwrite" ), tr( "Are you sure you want to overwrite the existing attribute table at '%1'?" ).arg( destinationPath ), QMessageBox::Yes | QMessageBox::No, QMessageBox::No ) == QMessageBox::Yes )
147 {
148 success = rat->writeToFile( destinationPath, &errorMessage );
149 if ( ! success )
150 {
151 notify( tr( "Error Saving Raster Attribute Table" ),
152 errorMessage,
153 Qgis::MessageLevel::Critical );
154 mRasterLayer->dataProvider()->setAttributeTable( bandNumber, nullptr );
155 }
156 }
157 }
158 else
159 {
160 success = mRasterLayer->dataProvider()->writeNativeAttributeTable( &errorMessage ); //#spellok
161 if ( ! success )
162 {
163 notify( tr( "Error Saving Raster Attribute Table" ),
164 errorMessage,
165 Qgis::MessageLevel::Critical );
166 mRasterLayer->dataProvider()->setAttributeTable( bandNumber, nullptr );
167
168 }
169 }
170 }
171
172 if ( success )
173 {
174 notify( tr( "Raster Attribute Table Saved" ),
175 tr( "The new Raster Attribute Table was successfully created." ),
176 Qgis::MessageLevel::Success );
177 }
178
179 QDialog::accept();
180}
181
182void QgsCreateRasterAttributeTableDialog::notify( const QString &title, const QString &message, Qgis::MessageLevel level )
183{
184 if ( mMessageBar )
185 {
186 mMessageBar->pushMessage( message, level );
187 }
188 else
189 {
190 switch ( level )
191 {
192 case Qgis::MessageLevel::Info:
193 case Qgis::MessageLevel::Success:
194 case Qgis::MessageLevel::NoLevel:
195 {
196 QMessageBox::information( nullptr, title, message );
197 break;
198 }
199 case Qgis::MessageLevel::Warning:
200 {
201 QMessageBox::warning( nullptr, title, message );
202 break;
203 }
204 case Qgis::MessageLevel::Critical:
205 {
206 QMessageBox::critical( nullptr, title, message );
207 break;
208 }
209 }
210 }
211}
212
213void QgsCreateRasterAttributeTableDialog::updateButtons()
214{
215 mDbfPathWidget->setEnabled( mDbfRadioButton->isChecked() );
216}
MessageLevel
Level for messages This will be used both for message log and message bar in application.
Definition: qgis.h:115
QgsCreateRasterAttributeTableDialog(QgsRasterLayer *rasterLayer, QWidget *parent=nullptr)
Creates a new QgsCreateRasterAttributeTableDialog.
void setOpenWhenDoneVisible(bool visible)
Sets the visibility of the "Open newly created raster attribute table" option to visible,...
QString filePath() const
Returns the file path in case of VAT.DBF save option.
void setMessageBar(QgsMessageBar *bar)
Sets the message bar associated with the widget.
bool openWhenDone() const
Returns true if the option to open the newly created attribute table is checked.
bool saveToFile() const
Returns true if the option to save to a file is selected.
virtual QString dataSourceUri(bool expandAuthConfig=false) const
Gets the data source specification.
static void enableAutoGeometryRestore(QWidget *widget, const QString &key=QString())
Register the widget to allow its position to be automatically saved and restored when open and closed...
Definition: qgsgui.cpp:178
A bar for displaying non-blocking messages to the user.
Definition: qgsmessagebar.h:61
void pushMessage(const QString &text, Qgis::MessageLevel level=Qgis::MessageLevel::Info, int duration=-1)
A convenience method for pushing a message with the specified text to the bar.
The QgsRasterAttributeTable class represents a Raster Attribute Table (RAT).
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...
virtual bool writeNativeAttributeTable(QString *errorMessage=nullptr)
Writes the native attribute table, optionally reporting any error in errorMessage,...
void setAttributeTable(int bandNumber, QgsRasterAttributeTable *attributeTable)
Set the attribute table to attributeTable for the specified bandNumber, if the attributeTable is NULL...
virtual QgsRasterDataProvider::ProviderCapabilities providerCapabilities() const
Returns flags containing the supported capabilities of the data provider.
Represents a raster layer.
bool canCreateRasterAttributeTable()
Returns true if the raster renderer is suitable for creation of a raster attribute table.
QgsRasterAttributeTable * attributeTable(int bandNumber) const
Returns the (possibly NULL) raster attribute table for the given band bandNumber.
int attributeTableCount() const
Returns the number of attribute tables for the raster by counting the number of bands that have an as...
int bandCount() const
Returns the number of bands in this layer.
QgsRasterDataProvider * dataProvider() override
Returns the source data provider.