QGIS API Documentation 3.41.0-Master (af5edcb665c)
Loading...
Searching...
No Matches
qgsrasterattributetablewidget.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsrasterattributetablewidget.cpp - QgsRasterAttributeTableWidget
3
4 ---------------------
5 begin : 6.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 "moc_qgsrasterattributetablewidget.cpp"
19#include "qgsrasterlayer.h"
20#include "qgsapplication.h"
21#include "qgsmessagebar.h"
24#include "qgscolorbutton.h"
26
27#include <QToolBar>
28#include <QAction>
29#include <QSortFilterProxyModel>
30#include <QMessageBox>
31#include <QFileDialog>
32
33QgsRasterAttributeTableWidget::QgsRasterAttributeTableWidget( QWidget *parent, QgsRasterLayer *rasterLayer, const int bandNumber )
34 : QgsPanelWidget( parent )
35 , mRasterLayer( rasterLayer )
36{
37 setupUi( this );
38
39 // Create the toolbar
40 QToolBar *editToolBar = new QToolBar( this );
41 editToolBar->setIconSize( QgsGuiUtils::iconSize( true ) );
42
43 mActionToggleEditing = new QAction( QgsApplication::getThemeIcon( "/mActionEditTable.svg" ), tr( "&Edit Attribute Table" ), editToolBar );
44 mActionToggleEditing->setCheckable( true );
45 connect( mActionToggleEditing, &QAction::triggered, this, [=]( bool editable ) {
46 setEditable( editable );
47 } );
48
49 editToolBar->addAction( mActionToggleEditing );
50
51 mActionAddColumn = new QAction( QgsApplication::getThemeIcon( "/mActionNewAttribute.svg" ), tr( "Add &Column…" ), editToolBar );
52 connect( mActionAddColumn, &QAction::triggered, this, &QgsRasterAttributeTableWidget::addColumn );
53 editToolBar->addAction( mActionAddColumn );
54
55 mActionAddRow = new QAction( QgsApplication::getThemeIcon( "/mActionNewTableRow.svg" ), tr( "&Add Row…" ), editToolBar );
56 connect( mActionAddRow, &QAction::triggered, this, &QgsRasterAttributeTableWidget::addRow );
57 editToolBar->addAction( mActionAddRow );
58
59 mActionRemoveRow = new QAction( QgsApplication::getThemeIcon( "/mActionRemoveSelectedFeature.svg" ), tr( "Remove Row" ), editToolBar );
60 connect( mActionRemoveRow, &QAction::triggered, this, &QgsRasterAttributeTableWidget::removeRow );
61 editToolBar->addAction( mActionRemoveRow );
62
63 mActionRemoveColumn = new QAction( QgsApplication::getThemeIcon( "/mActionDeleteAttribute.svg" ), tr( "Remove Column" ), editToolBar );
64 connect( mActionRemoveColumn, &QAction::triggered, this, &QgsRasterAttributeTableWidget::removeColumn );
65 editToolBar->addAction( mActionRemoveColumn );
66
67 mActionSaveChanges = new QAction( QgsApplication::getThemeIcon( "/mActionSaveAllEdits.svg" ), tr( "&Save Changes" ), editToolBar );
68 connect( mActionSaveChanges, &QAction::triggered, this, &QgsRasterAttributeTableWidget::saveChanges );
69 editToolBar->addAction( mActionSaveChanges );
70
71 layout()->setMenuBar( editToolBar );
72
73 connect( mClassifyButton, &QPushButton::clicked, this, &QgsRasterAttributeTableWidget::classify );
74
75 mProxyModel = new QSortFilterProxyModel( this );
76
77 mRATView->setModel( mProxyModel );
78
79 connect( mRATView->selectionModel(), &QItemSelectionModel::selectionChanged, this, &QgsRasterAttributeTableWidget::updateButtons );
80
81 if ( rasterLayer )
82 {
83 init( bandNumber );
84 }
85}
86
87void QgsRasterAttributeTableWidget::setRasterLayer( QgsRasterLayer *rasterLayer, const int bandNumber )
88{
89 mRasterLayer = rasterLayer;
90 init( bandNumber );
91}
92
93bool QgsRasterAttributeTableWidget::isDirty() const
94{
95 return mAttributeTableBuffer && mAttributeTableBuffer->isDirty();
96}
97
98void QgsRasterAttributeTableWidget::init( int bandNumber )
99{
100 disconnect( mRasterBandsComboBox, qOverload<int>( &QComboBox::currentIndexChanged ), this, &QgsRasterAttributeTableWidget::bandChanged );
101 mAttributeTableBuffer = nullptr;
102 mCurrentBand = 0;
103 mRasterBandsComboBox->clear();
104
105 QList<int> availableRats;
106
107 if ( mRasterLayer )
108 {
109 for ( int checkBandNumber = 1; checkBandNumber <= mRasterLayer->bandCount(); ++checkBandNumber )
110 {
111 // Search for RATs
112 if ( mRasterLayer->attributeTable( checkBandNumber ) )
113 {
114 mRasterBandsComboBox->addItem( mRasterLayer->bandName( checkBandNumber ), checkBandNumber );
115 availableRats.push_back( checkBandNumber );
116 }
117 }
118
119 if ( !availableRats.isEmpty() )
120 {
121 if ( availableRats.contains( bandNumber ) )
122 {
123 mCurrentBand = bandNumber;
124 }
125 else if ( !availableRats.isEmpty() )
126 {
127 mCurrentBand = availableRats.first();
128 }
129
130 mAttributeTableBuffer = std::make_unique<QgsRasterAttributeTable>( *mRasterLayer->attributeTable( mCurrentBand ) );
131 mRasterBandsComboBox->setCurrentIndex( availableRats.indexOf( mCurrentBand ) );
132 }
133 }
134
135 if ( mAttributeTableBuffer )
136 {
137 mModel.reset( new QgsRasterAttributeTableModel( mAttributeTableBuffer.get() ) );
138 mModel->setEditable( mEditable );
139
140 connect( mModel.get(), &QgsRasterAttributeTableModel::dataChanged, this, [=]( const QModelIndex &, const QModelIndex &, const QVector<int> & ) {
141 updateButtons();
142 } );
143
144 connect( mModel.get(), &QgsRasterAttributeTableModel::columnsInserted, this, [=]( const QModelIndex &, int, int ) {
145 setDelegates();
146 } );
147
148 connect( mModel.get(), &QgsRasterAttributeTableModel::columnsRemoved, this, [=]( const QModelIndex &, int, int ) {
149 setDelegates();
150 } );
151
152 static_cast<QSortFilterProxyModel *>( mRATView->model() )->setSourceModel( mModel.get() );
153 setDelegates();
154 }
155 else
156 {
157 notify( tr( "No Attribute Tables Available" ), tr( "The raster layer has no associated attribute tables, you can create a new attribute table or load one from a VAT.DBF file." ), Qgis::Warning );
158 }
159
160 connect( mRasterBandsComboBox, qOverload<int>( &QComboBox::currentIndexChanged ), this, &QgsRasterAttributeTableWidget::bandChanged );
161
162 updateButtons();
163}
164
165void QgsRasterAttributeTableWidget::updateButtons()
166{
167 const bool enableEditingButtons( static_cast<bool>( mAttributeTableBuffer ) && mEditable && mRATView->selectionModel()->currentIndex().isValid() );
168 mActionToggleEditing->setChecked( mEditable );
169 mActionToggleEditing->setEnabled( mAttributeTableBuffer && mRasterLayer );
170 mActionAddColumn->setEnabled( mEditable );
171 mActionRemoveColumn->setEnabled( enableEditingButtons );
172 mActionAddRow->setEnabled( enableEditingButtons );
173 mActionRemoveRow->setEnabled( enableEditingButtons );
174 mActionSaveChanges->setEnabled( mAttributeTableBuffer && mAttributeTableBuffer->isDirty() );
175 mClassifyButton->setEnabled( mAttributeTableBuffer && mRasterLayer );
176 mClassifyComboBox->setEnabled( mAttributeTableBuffer && mRasterLayer );
177}
178
179void QgsRasterAttributeTableWidget::setDockMode( bool dockMode )
180{
181 QgsPanelWidget::setDockMode( dockMode );
182 static_cast<QToolBar *>( layout()->menuBar() )->setIconSize( QgsGuiUtils::iconSize( dockMode ) );
183}
184
185void QgsRasterAttributeTableWidget::setMessageBar( QgsMessageBar *bar )
186{
187 mMessageBar = bar;
188}
189
190bool QgsRasterAttributeTableWidget::setEditable( bool editable, bool allowCancel )
191{
192 const bool isDirty { mAttributeTableBuffer && mAttributeTableBuffer->isDirty() && mCurrentBand > 0 && mRasterLayer->attributeTable( mCurrentBand ) };
193 bool retVal { true };
194 // Switch to read-only
195 if ( !editable && isDirty )
196 {
197 QMessageBox::StandardButtons buttons { QMessageBox::Button::Yes | QMessageBox::Button::No };
198
199 if ( allowCancel )
200 {
201 buttons |= QMessageBox::Button::Cancel;
202 }
203
204 switch ( QMessageBox::question( nullptr, tr( "Save Attribute Table" ), tr( "Attribute table contains unsaved changes, do you want to save the changes?" ), buttons ) )
205 {
206 case QMessageBox::Button::Cancel:
207 {
208 retVal = false;
209 break;
210 }
211 case QMessageBox::Button::Yes:
212 {
213 saveChanges();
214 retVal = true;
215 break;
216 }
217 case QMessageBox::Button::No:
218 default:
219 {
220 // Reset to its original state
221 mAttributeTableBuffer = std::make_unique<QgsRasterAttributeTable>( *mRasterLayer->attributeTable( mCurrentBand ) );
222 init( mCurrentBand );
223 retVal = true;
224 break;
225 }
226 }
227 }
228
229 if ( retVal )
230 {
231 mEditable = editable;
232 mModel->setEditable( editable );
233 }
234
235 updateButtons();
236
237 return retVal;
238}
239
240void QgsRasterAttributeTableWidget::saveChanges()
241{
242 if ( mRasterLayer && mAttributeTableBuffer && mAttributeTableBuffer->isDirty() && mCurrentBand > 0 )
243 {
244 QgsRasterAttributeTable *attributeTable { mRasterLayer->dataProvider()->attributeTable( mCurrentBand ) };
245 if ( !attributeTable )
246 {
247 QgsDebugError( QStringLiteral( "Error saving RAT: RAT for band %1 is unexpectedly gone!" ).arg( mCurrentBand ) );
248 }
249 else
250 {
251 *attributeTable = *mAttributeTableBuffer;
252 QString errorMessage;
253 QString newPath { attributeTable->filePath() };
254 const bool nativeRatSupported = mRasterLayer->dataProvider()->providerCapabilities().testFlag( Qgis::RasterProviderCapability::NativeRasterAttributeTable );
255 bool saveToNative { false };
256
257 if ( newPath.isEmpty() && !nativeRatSupported )
258 {
259 newPath = QFileDialog::getOpenFileName( nullptr, tr( "Save Raster Attribute Table (band %1) To File" ).arg( mCurrentBand ), QFile::exists( mRasterLayer->dataProvider()->dataSourceUri() ) ? mRasterLayer->dataProvider()->dataSourceUri() + ".vat.dbf" : QString(), QStringLiteral( "VAT DBF Files (*.vat.dbf)" ) );
260 if ( newPath.isEmpty() )
261 {
262 // Aborted by user
263 return;
264 }
265 }
266 else if ( newPath.isEmpty() )
267 {
268 saveToNative = true;
269 }
270
271 bool writeSuccess { false };
272
273 // Save to file
274 if ( !saveToNative && !newPath.isEmpty() )
275 {
276 writeSuccess = attributeTable->writeToFile( attributeTable->filePath(), &errorMessage );
277 }
278 else if ( saveToNative )
279 {
280 writeSuccess = mRasterLayer->dataProvider()->writeNativeAttributeTable( &errorMessage ); //#spellok
281 }
282
283 if ( writeSuccess )
284 {
285 mAttributeTableBuffer->setDirty( false );
286 notify( tr( "Attribute Table Write Success" ), tr( "The raster attribute table has been successfully saved." ), Qgis::MessageLevel::Success );
287 }
288 else
289 {
290 notify( tr( "Attribute Table Write Error" ), errorMessage, Qgis::MessageLevel::Critical );
291 }
292
293 // Save to native saves RATs for all bands, no need to loop further.
294 if ( saveToNative )
295 {
296 return;
297 }
298 }
299 }
300
301 updateButtons();
302}
303
304void QgsRasterAttributeTableWidget::classify()
305{
306 if ( !mAttributeTableBuffer )
307 {
308 notify( tr( "Classification Error" ), tr( "The raster attribute table is not set." ), Qgis::MessageLevel::Critical );
309 return;
310 }
311
312 if ( !mRasterLayer )
313 {
314 notify( tr( "Classification Error" ), tr( "The raster layer is not set." ), Qgis::MessageLevel::Critical );
315 return;
316 }
317
318 QString confirmMessage;
319 QString errorMessage;
320
321 if ( !mAttributeTableBuffer->isValid( &errorMessage ) )
322 {
323 confirmMessage = tr( "The attribute table does not seem to be valid and it may produce an unusable symbology, validation errors:<br>%1<br>" ).arg( errorMessage );
324 }
325
326 if ( QMessageBox::question( nullptr, tr( "Apply Style From Attribute Table" ), confirmMessage.append( tr( "The existing symbology for the raster will be replaced by a new symbology from the attribute table and any unsaved changes to the current symbology will be lost, do you want to proceed?" ) ) ) == QMessageBox::Yes )
327 {
328 if ( QgsRasterRenderer *renderer = mAttributeTableBuffer->createRenderer( mRasterLayer->dataProvider(), mCurrentBand, mClassifyComboBox->currentData().toInt() ) )
329 {
330 mRasterLayer->setRenderer( renderer );
331 mRasterLayer->triggerRepaint();
332 emit rendererChanged();
333 }
334 else
335 {
336 notify( tr( "Classification Error" ), tr( "The classification returned no classes." ), Qgis::MessageLevel::Critical );
337 }
338 }
339}
340
341void QgsRasterAttributeTableWidget::addColumn()
342{
343 if ( mAttributeTableBuffer )
344 {
345 QgsRasterAttributeTableAddColumnDialog dlg { mAttributeTableBuffer.get() };
346 if ( dlg.exec() == QDialog::Accepted )
347 {
348 QString errorMessage;
349 if ( dlg.isColor() )
350 {
351 if ( !mModel->insertColor( dlg.position(), &errorMessage ) )
352 {
353 notify( tr( "Error adding color column" ), errorMessage, Qgis::MessageLevel::Critical );
354 }
355 }
356 else if ( dlg.isRamp() )
357 {
358 if ( !mModel->insertRamp( dlg.position(), &errorMessage ) )
359 {
360 notify( tr( "Error adding color ramp column" ), errorMessage, Qgis::MessageLevel::Critical );
361 }
362 }
363 else
364 {
365 if ( !mModel->insertField( dlg.position(), dlg.name(), dlg.usage(), dlg.type(), &errorMessage ) )
366 {
367 notify( tr( "Error adding new column" ), errorMessage, Qgis::MessageLevel::Critical );
368 }
369 }
370 }
371 setDelegates();
372 }
373}
374
375void QgsRasterAttributeTableWidget::removeColumn()
376{
377 const QModelIndex currentIndex { mProxyModel->mapToSource( mRATView->selectionModel()->currentIndex() ) };
378 if ( mAttributeTableBuffer && currentIndex.isValid() && currentIndex.column() < mAttributeTableBuffer->fields().count() )
379 {
380 if ( QMessageBox::question( nullptr, tr( "Remove Column" ), tr( "Do you want to remove the selected column? This action cannot be undone." ) ) == QMessageBox::Yes )
381 {
382 QString errorMessage;
383 if ( !mModel->removeField( currentIndex.column(), &errorMessage ) )
384 {
385 notify( tr( "Error removing column" ), errorMessage, Qgis::MessageLevel::Critical );
386 }
387 }
388 }
389}
390
391void QgsRasterAttributeTableWidget::addRow()
392{
393 if ( mAttributeTableBuffer )
394 {
395 // Default to append
396 int position { mModel->rowCount( QModelIndex() ) };
397 const QModelIndex currentIndex { mProxyModel->mapToSource( mRATView->selectionModel()->currentIndex() ) };
398
399 // If there is a selected row, ask if before of after.
400 if ( currentIndex.isValid() )
401 {
402 // Ask the user where to insert the new row (before or after the currently
403 // selected row).
405 if ( dlg.exec() != QDialog::DialogCode::Accepted )
406 {
407 return;
408 }
409 else
410 {
411 position = currentIndex.row() + ( dlg.insertAfter() ? 1 : 0 );
412 }
413 }
414
415 bool result { true };
416 QString errorMessage;
417
418 QVariantList rowData;
419
420 QList<QgsRasterAttributeTable::Field> fields { mAttributeTableBuffer->fields() };
421 for ( const QgsRasterAttributeTable::Field &field : std::as_const( fields ) )
422 {
423 rowData.push_back( QgsVariantUtils::createNullVariant( field.type ) );
424 }
425
426 result = mModel->insertRow( position, rowData, &errorMessage );
427
428 if ( !result )
429 {
430 notify( tr( "Error adding row" ), errorMessage, Qgis::MessageLevel::Critical );
431 }
432 else
433 {
434 mRATView->scrollTo( mRATView->model()->index( position, 0 ) );
435 }
436 }
437}
438
439void QgsRasterAttributeTableWidget::removeRow()
440{
441 if ( mAttributeTableBuffer && mRATView->selectionModel()->currentIndex().isValid() )
442 {
443 if ( QMessageBox::question( nullptr, tr( "Remove Row" ), tr( "Do you want to remove the selected row? This action cannot be undone." ) ) == QMessageBox::Yes )
444 {
445 QString errorMessage;
446 if ( !mModel->removeRow( mProxyModel->mapToSource( mRATView->selectionModel()->currentIndex() ).row(), &errorMessage ) )
447 {
448 notify( tr( "Error removing row" ), errorMessage, Qgis::MessageLevel::Critical );
449 }
450 }
451 }
452}
453
454void QgsRasterAttributeTableWidget::bandChanged( const int index )
455{
456 const QVariant itemData = mRasterBandsComboBox->itemData( index );
457
458 if ( itemData.isValid() )
459 {
460 if ( mEditable )
461 {
462 setEditable( false );
463 }
464 init( itemData.toInt() );
465 }
466}
467
468void QgsRasterAttributeTableWidget::notify( const QString &title, const QString &message, Qgis::MessageLevel level )
469{
470 if ( mMessageBar )
471 {
472 mMessageBar->pushMessage( message, level );
473 }
474 else
475 {
476 switch ( level )
477 {
481 {
482 QMessageBox::information( nullptr, title, message );
483 break;
484 }
486 {
487 QMessageBox::warning( nullptr, title, message );
488 break;
489 }
491 {
492 QMessageBox::critical( nullptr, title, message );
493 break;
494 }
495 }
496 }
497}
498
499void QgsRasterAttributeTableWidget::setDelegates()
500{
501 mClassifyComboBox->clear();
502 if ( mAttributeTableBuffer )
503 {
504 const QList<QgsRasterAttributeTable::Field> tableFields { mAttributeTableBuffer->fields() };
505 int fieldIdx { 0 };
506 const QHash<Qgis::RasterAttributeTableFieldUsage, QgsRasterAttributeTable::UsageInformation> usageInfo { QgsRasterAttributeTable::usageInformation() };
507
508 for ( const QgsRasterAttributeTable::Field &f : std::as_const( tableFields ) )
509 {
510 // Clear all delegates.
511 mRATView->setItemDelegateForColumn( fieldIdx, nullptr );
512
513 if ( usageInfo[f.usage].maybeClass )
514 {
515 mClassifyComboBox->addItem( QgsFields::iconForFieldType( f.type ), f.name, QVariant( fieldIdx ) );
516 }
517
518 // Set delegates for doubles
519 if ( ( !f.isColor() && !f.isRamp() ) && f.type == QMetaType::Type::Double )
520 {
521 mRATView->setItemDelegateForColumn( fieldIdx, new LocalizedDoubleDelegate( mRATView ) );
522 }
523 fieldIdx++;
524 }
525
526 // Set delegates for color and ramp
527 if ( mAttributeTableBuffer->hasColor() )
528 {
529 if ( mAttributeTableBuffer->usages().contains( Qgis::RasterAttributeTableFieldUsage::Alpha ) )
530 {
531 mRATView->setItemDelegateForColumn( mAttributeTableBuffer->fields().count(), new ColorAlphaDelegate( mRATView ) );
532 }
533 else
534 {
535 mRATView->setItemDelegateForColumn( mAttributeTableBuffer->fields().count(), new ColorDelegate( mRATView ) );
536 }
537 }
538 else if ( mAttributeTableBuffer->hasRamp() )
539 {
540 if ( mAttributeTableBuffer->usages().contains( Qgis::RasterAttributeTableFieldUsage::AlphaMin ) )
541 {
542 mRATView->setItemDelegateForColumn( mAttributeTableBuffer->fields().count(), new ColorRampAlphaDelegate( mRATView ) );
543 }
544 else
545 {
546 mRATView->setItemDelegateForColumn( mAttributeTableBuffer->fields().count(), new ColorRampDelegate( mRATView ) );
547 }
548 }
549 }
550}
551
552
554
555QWidget *ColorDelegate::createEditor( QWidget *parent, const QStyleOptionViewItem &, const QModelIndex & ) const
556{
557 return new QgsColorButton( parent, tr( "Select Color" ) );
558}
559
560void ColorDelegate::setEditorData( QWidget *editor, const QModelIndex &index ) const
561{
562 const QColor color { index.data( Qt::ItemDataRole::EditRole ).value<QColor>() };
563 static_cast<QgsColorButton *>( editor )->setColor( color );
564}
565
566void ColorDelegate::setModelData( QWidget *editor, QAbstractItemModel *model, const QModelIndex &index ) const
567{
568 const QColor color { static_cast<QgsColorButton *>( editor )->color() };
569 model->setData( index, color );
570}
571
572QWidget *ColorAlphaDelegate::createEditor( QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index ) const
573{
574 QWidget *editor { ColorDelegate::createEditor( parent, option, index ) };
575 static_cast<QgsColorButton *>( editor )->setAllowOpacity( true );
576 return editor;
577}
578
579QWidget *ColorRampDelegate::createEditor( QWidget *parent, const QStyleOptionViewItem &, const QModelIndex & ) const
580{
582 return editor;
583}
584
585void ColorRampDelegate::setEditorData( QWidget *editor, const QModelIndex &index ) const
586{
587 const QgsGradientColorRamp ramp { qvariant_cast<QgsGradientColorRamp>( index.data( Qt::ItemDataRole::EditRole ) ) };
588 static_cast<QgsGradientColorRampDialog *>( editor )->setRamp( ramp );
589}
590
591void ColorRampDelegate::setModelData( QWidget *editor, QAbstractItemModel *model, const QModelIndex &index ) const
592{
593 model->setData( index, QVariant::fromValue( static_cast<QgsGradientColorRampDialog *>( editor )->ramp() ) );
594}
595
596void ColorRampDelegate::paint( QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index ) const
597{
598 const QgsGradientColorRamp ramp { qvariant_cast<QgsGradientColorRamp>( index.data( Qt::ItemDataRole::EditRole ) ) };
599 QLinearGradient gradient( QPointF( 0, 0 ), QPointF( 1, 0 ) );
600 gradient.setCoordinateMode( QGradient::CoordinateMode::ObjectBoundingMode );
601 gradient.setColorAt( 0, ramp.color1() );
602 gradient.setColorAt( 1, ramp.color2() );
603 const QRect r = option.rect.adjusted( 1, 1, -1, -1 );
604 const QgsScopedQPainterState painterState( painter );
605 painter->fillRect( r, QBrush { gradient } );
606}
607
608QWidget *ColorRampAlphaDelegate::createEditor( QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index ) const
609{
610 QWidget *editor { ColorRampDelegate::createEditor( parent, option, index ) };
611 // No opacity setting for ramps?
612 return editor;
613}
614
615
616QString LocalizedDoubleDelegate::displayText( const QVariant &value, const QLocale &locale ) const
617{
618 Q_UNUSED( locale );
619 const QString s( value.toString() );
620 const int dotPosition( s.indexOf( '.' ) );
621 int precision;
622 if ( dotPosition < 0 && s.indexOf( 'e' ) < 0 )
623 {
624 precision = 0;
625 return QLocale().toString( value.toDouble(), 'f', precision );
626 }
627 else
628 {
629 if ( dotPosition < 0 )
630 precision = 0;
631 else
632 precision = s.length() - dotPosition - 1;
633
634 if ( -1 < value.toDouble() && value.toDouble() < 1 )
635 {
636 return QLocale().toString( value.toDouble(), 'g', precision );
637 }
638 else
639 {
640 return QLocale().toString( value.toDouble(), 'f', precision );
641 }
642 }
643 return QLocale().toString( value.toDouble(), 'f' );
644}
645
@ NativeRasterAttributeTable
Indicates that the provider supports native raster attribute table.
MessageLevel
Level for messages This will be used both for message log and message bar in application.
Definition qgis.h:154
@ NoLevel
No level.
Definition qgis.h:159
@ Warning
Warning message.
Definition qgis.h:156
@ Critical
Critical/error message.
Definition qgis.h:157
@ Info
Information message.
Definition qgis.h:155
@ Success
Used for reporting a successful operation.
Definition qgis.h:158
@ AlphaMin
Field usage AlphaMin.
static QIcon getThemeIcon(const QString &name, const QColor &fillColor=QColor(), const QColor &strokeColor=QColor())
Helper to get a theme icon.
A cross platform button subclass for selecting colors.
static QIcon iconForFieldType(QMetaType::Type type, QMetaType::Type subType=QMetaType::Type::UnknownType, const QString &typeString=QString())
Returns an icon corresponding to a field type.
A dialog which allows users to modify the properties of a QgsGradientColorRamp.
Gradient color ramp, which smoothly interpolates between two colors and also supports optional extra ...
A bar for displaying non-blocking messages to the user.
Base class for any widget that can be shown as a inline panel.
virtual void setDockMode(bool dockMode)
Set the widget in dock mode which tells the widget to emit panel widgets and not open dialogs.
The QgsRasterAttributeTableAddColumnDialog class collects options to add a new column to a raster att...
The QgsRasterAttributeTableAddColumnDialog class collects options to add a new row to a raster attrib...
bool insertAfter() const
Returns true if the desired insertion position for the new row is after the currently selected row,...
The QgsRasterAttributeTableModel class manages a QgsRasterAttributeTable.
The Field class represents a Raster Attribute Table field, including its name, usage and type.
The QgsRasterAttributeTable class represents a Raster Attribute Table (RAT).
static QHash< Qgis::RasterAttributeTableFieldUsage, QgsRasterAttributeTable::UsageInformation > usageInformation()
Returns information about supported Raster Attribute Table usages.
Represents a raster layer.
Raster renderer pipe that applies colors to a raster.
Scoped object for saving and restoring a QPainter object's state.
static QVariant createNullVariant(QMetaType::Type metaType)
Helper method to properly create a null QVariant from a metaType Returns the created QVariant.
QSize iconSize(bool dockableToolbar)
Returns the user-preferred size of a window's toolbar icons.
#define QgsDebugError(str)
Definition qgslogger.h:38
int precision