QGIS API Documentation  3.8.0-Zanzibar (11aff65)
qgsauxiliarystorage.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsauxiliarystorage.cpp - description
3  -------------------
4  begin : Aug 28, 2017
5  copyright : (C) 2017 by Paul Blottiere
6  email : paul.blottiere@oslandia.com
7  ***************************************************************************/
8 
9 /***************************************************************************
10  * *
11  * This program is free software; you can redistribute it and/or modify *
12  * it under the terms of the GNU General Public License as published by *
13  * the Free Software Foundation; either version 2 of the License, or *
14  * (at your option) any later version. *
15  * *
16  ***************************************************************************/
17 
18 #include "qgsauxiliarystorage.h"
19 #include "qgslogger.h"
20 #include "qgsspatialiteutils.h"
21 #include "qgsproject.h"
22 #include "qgsvectorlayerlabeling.h"
23 #include "qgsdiagramrenderer.h"
24 #include "qgsmemoryproviderutils.h"
25 #include "qgssymbollayer.h"
26 
27 #include <sqlite3.h>
28 #include <QFile>
29 
30 const QString AS_JOINFIELD = "ASPK";
31 const QString AS_EXTENSION = "qgd";
32 const QString AS_JOINPREFIX = "auxiliary_storage_";
33 
34 const QVector<QgsPalLayerSettings::Property> palHiddenProperties
35 {
57 };
58 
59 //
60 // QgsAuxiliaryLayer
61 //
62 
63 QgsAuxiliaryLayer::QgsAuxiliaryLayer( const QString &pkField, const QString &filename, const QString &table, QgsVectorLayer *vlayer )
64  : QgsVectorLayer( QStringLiteral( "%1|layername=%2" ).arg( filename, table ),
65  QStringLiteral( "%1_auxiliarystorage" ).arg( table ), QStringLiteral( "ogr" ) )
66  , mFileName( filename )
67  , mTable( table )
68  , mLayer( vlayer )
69 {
70  // init join info
71  mJoinInfo.setPrefix( AS_JOINPREFIX );
72  mJoinInfo.setJoinLayer( this );
73  mJoinInfo.setJoinFieldName( AS_JOINFIELD );
74  mJoinInfo.setTargetFieldName( pkField );
75  mJoinInfo.setEditable( true );
76  mJoinInfo.setUpsertOnEdit( true );
77  mJoinInfo.setCascadedDelete( true );
78  mJoinInfo.setJoinFieldNamesBlackList( QStringList() << QStringLiteral( "rowid" ) ); // introduced by ogr provider
79 }
80 
82 {
84  return new QgsAuxiliaryLayer( mJoinInfo.targetFieldName(), mFileName, target->id(), target );
85 }
86 
88 {
89  bool rc = deleteFeatures( allFeatureIds() );
90  commitChanges();
91  startEditing();
92  return rc;
93 }
94 
96 {
97  QgsVectorLayer *layer = QgsMemoryProviderUtils::createMemoryLayer( QStringLiteral( "auxiliary_layer" ), fields(), mLayer->wkbType(), mLayer->crs() );
98 
99  QString pkField = mJoinInfo.targetFieldName();
100  QgsFeature joinFeature;
101  QgsFeature targetFeature;
103 
104  layer->startEditing();
105  while ( it.nextFeature( joinFeature ) )
106  {
107  QString filter = QgsExpression::createFieldEqualityExpression( pkField, joinFeature.attribute( AS_JOINFIELD ) );
108 
109  QgsFeatureRequest request;
110  request.setFilterExpression( filter );
111 
112  mLayer->getFeatures( request ).nextFeature( targetFeature );
113 
114  if ( targetFeature.isValid() )
115  {
116  QgsFeature newFeature( joinFeature );
117  newFeature.setGeometry( targetFeature.geometry() );
118  layer->addFeature( newFeature );
119  }
120  }
121  layer->commitChanges();
122 
123  return layer;
124 }
125 
127 {
128  return mJoinInfo;
129 }
130 
131 bool QgsAuxiliaryLayer::exists( const QgsPropertyDefinition &definition ) const
132 {
133  return ( indexOfPropertyDefinition( definition ) >= 0 );
134 }
135 
137 {
138  if ( ( definition.name().isEmpty() && definition.comment().isEmpty() ) || exists( definition ) )
139  return false;
140 
141  const QgsField af = createAuxiliaryField( definition );
142  const bool rc = addAttribute( af );
143  updateFields();
144  mLayer->updateFields();
145 
146  if ( rc )
147  {
148  int auxIndex = indexOfPropertyDefinition( definition );
149  int index = mLayer->fields().indexOf( nameFromProperty( definition, true ) );
150 
151  if ( index >= 0 && auxIndex >= 0 )
152  {
153  if ( isHiddenProperty( auxIndex ) )
154  {
155  // update editor widget
156  QgsEditorWidgetSetup setup = QgsEditorWidgetSetup( QStringLiteral( "Hidden" ), QVariantMap() );
157  setEditorWidgetSetup( auxIndex, setup );
158 
159  // column is hidden
160  QgsAttributeTableConfig attrCfg = mLayer->attributeTableConfig();
161  attrCfg.update( mLayer->fields() );
162  QVector<QgsAttributeTableConfig::ColumnConfig> columns = attrCfg.columns();
163  QVector<QgsAttributeTableConfig::ColumnConfig>::iterator it;
164 
165  for ( it = columns.begin(); it != columns.end(); ++it )
166  {
167  if ( it->name.compare( mLayer->fields().field( index ).name() ) == 0 )
168  it->hidden = true;
169  }
170 
171  attrCfg.setColumns( columns );
172  mLayer->setAttributeTableConfig( attrCfg );
173  }
174  else if ( definition.standardTemplate() == QgsPropertyDefinition::ColorNoAlpha
176  {
177  QgsEditorWidgetSetup setup = QgsEditorWidgetSetup( QStringLiteral( "Color" ), QVariantMap() );
178  setEditorWidgetSetup( auxIndex, setup );
179  }
180 
181  mLayer->setEditorWidgetSetup( index, editorWidgetSetup( auxIndex ) );
182  }
183  }
184 
185  return rc;
186 }
187 
189 {
190  QgsFields afields;
191 
192  for ( int i = 2; i < fields().count(); i++ ) // ignore rowid and PK field
193  afields.append( createAuxiliaryField( fields().field( i ) ) );
194 
195  return afields;
196 }
197 
199 {
201  bool rc = commitChanges();
202  startEditing();
203  return rc;
204 }
205 
207 {
208  bool rc = false;
209 
210  if ( isEditable() )
211  {
212  rc = commitChanges();
213  }
214 
215  startEditing();
216 
217  return rc;
218 }
219 
221 {
222  int index = -1;
223 
224  if ( layer && layer->labeling() && layer->auxiliaryLayer() )
225  {
226  // property definition are identical whatever the provider id
227  const QgsPropertyDefinition def = layer->labeling()->settings().propertyDefinitions()[property];
228  const QString fieldName = nameFromProperty( def, true );
229 
230  layer->auxiliaryLayer()->addAuxiliaryField( def );
231 
232  if ( layer->auxiliaryLayer()->indexOfPropertyDefinition( def ) >= 0 )
233  {
234  const QgsProperty prop = QgsProperty::fromField( fieldName );
235 
236  const QStringList subProviderIds = layer->labeling()->subProviders();
237  for ( const QString &providerId : subProviderIds )
238  {
239  QgsPalLayerSettings *settings = new QgsPalLayerSettings( layer->labeling()->settings( providerId ) );
240 
242  c.setProperty( property, prop );
243  settings->setDataDefinedProperties( c );
244 
245  layer->labeling()->setSettings( settings, providerId );
246  }
247 
248  emit layer->styleChanged();
249  }
250 
251  index = layer->fields().lookupField( fieldName );
252  }
253 
254  return index;
255 }
256 
258 {
259  int index = -1;
260 
261  if ( layer && layer->diagramLayerSettings() && layer->auxiliaryLayer() )
262  {
263  const QgsPropertyDefinition def = layer->diagramLayerSettings()->propertyDefinitions()[property];
264 
265  if ( layer->auxiliaryLayer()->addAuxiliaryField( def ) )
266  {
267  const QString fieldName = nameFromProperty( def, true );
268  const QgsProperty prop = QgsProperty::fromField( fieldName );
269 
270  QgsDiagramLayerSettings settings( *layer->diagramLayerSettings() );
271 
272  QgsPropertyCollection c = settings.dataDefinedProperties();
273  c.setProperty( property, prop );
274  settings.setDataDefinedProperties( c );
275 
276  layer->setDiagramLayerSettings( settings );
277  emit layer->styleChanged();
278 
279  index = layer->fields().lookupField( fieldName );
280  }
281  }
282 
283  return index;
284 }
285 
286 bool QgsAuxiliaryLayer::isHiddenProperty( int index ) const
287 {
288  bool hidden = false;
290 
291  if ( def.origin().compare( "labeling" ) == 0 )
292  {
294  {
295  const QString propName = QgsPalLayerSettings::propertyDefinitions()[ p ].name();
296  if ( propName.compare( def.name() ) == 0 )
297  {
298  hidden = true;
299  break;
300  }
301  }
302  }
303 
304  return hidden;
305 }
306 
308 {
309  int p = -1;
311 
312  if ( aDef.origin().compare( QLatin1String( "labeling" ) ) == 0 )
313  {
315  QgsPropertiesDefinition::const_iterator it = defs.constBegin();
316  for ( ; it != defs.constEnd(); ++it )
317  {
318  if ( it->name().compare( aDef.name(), Qt::CaseInsensitive ) == 0 )
319  {
320  p = it.key();
321  break;
322  }
323  }
324  }
325  else if ( aDef.origin().compare( QLatin1String( "symbol" ) ) == 0 )
326  {
328  QgsPropertiesDefinition::const_iterator it = defs.constBegin();
329  for ( ; it != defs.constEnd(); ++it )
330  {
331  if ( it->name().compare( aDef.name(), Qt::CaseInsensitive ) == 0 )
332  {
333  p = it.key();
334  break;
335  }
336  }
337  }
338  else if ( aDef.origin().compare( QLatin1String( "diagram" ) ) == 0 )
339  {
341  QgsPropertiesDefinition::const_iterator it = defs.constBegin();
342  for ( ; it != defs.constEnd(); ++it )
343  {
344  if ( it->name().compare( aDef.name(), Qt::CaseInsensitive ) == 0 )
345  {
346  p = it.key();
347  break;
348  }
349  }
350  }
351 
352  return p;
353 }
354 
356 {
357  return propertyDefinitionFromField( fields().field( index ) );
358 }
359 
361 {
362  return fields().indexOf( nameFromProperty( def ) );
363 }
364 
366 {
367  QString fieldName = def.origin();
368 
369  if ( !def.name().isEmpty() )
370  fieldName = QString( "%1_%2" ).arg( fieldName, def.name().toLower() );
371 
372  if ( !def.comment().isEmpty() )
373  fieldName = QString( "%1_%2" ).arg( fieldName, def.comment() );
374 
375  if ( joined )
376  fieldName = QString( "%1%2" ).arg( AS_JOINPREFIX, fieldName );
377 
378  return fieldName;
379 }
380 
382 {
383  QgsField afield;
384 
385  if ( !def.name().isEmpty() || !def.comment().isEmpty() )
386  {
387  QVariant::Type type = QVariant::Invalid;
388  QString typeName;
389  int len( 0 ), precision( 0 );
390  switch ( def.dataType() )
391  {
393  type = QVariant::String;
394  len = 50;
395  typeName = "String";
396  break;
398  type = QVariant::Double;
399  len = 0;
400  precision = 0;
401  typeName = "Real";
402  break;
404  type = QVariant::Int; // sqlite does not have a bool type
405  typeName = "Integer";
406  break;
407  }
408 
409  afield.setType( type );
410  afield.setName( nameFromProperty( def ) );
411  afield.setTypeName( typeName );
412  afield.setLength( len );
413  afield.setPrecision( precision );
414  }
415 
416  return afield;
417 }
418 
420 {
422  const QStringList parts = f.name().split( '_' );
423 
424  if ( parts.size() <= 1 )
425  return def;
426 
427  const QString origin = parts[0];
428  const QString propertyName = parts[1];
429 
430  if ( origin.compare( "labeling", Qt::CaseInsensitive ) == 0 )
431  {
433  for ( auto it = props.constBegin(); it != props.constEnd(); ++it )
434  {
435  if ( it.value().name().compare( propertyName, Qt::CaseInsensitive ) == 0 )
436  {
437  def = it.value();
438  if ( parts.size() == 3 )
439  def.setComment( parts[2] );
440  break;
441  }
442  }
443  }
444  else if ( origin.compare( "symbol", Qt::CaseInsensitive ) == 0 )
445  {
447  for ( auto it = props.constBegin(); it != props.constEnd(); ++it )
448  {
449  if ( it.value().name().compare( propertyName, Qt::CaseInsensitive ) == 0 )
450  {
451  def = it.value();
452  if ( parts.size() == 3 )
453  def.setComment( parts[2] );
454  break;
455  }
456  }
457  }
458  else if ( origin.compare( "diagram", Qt::CaseInsensitive ) == 0 )
459  {
461  for ( auto it = props.constBegin(); it != props.constEnd(); ++it )
462  {
463  if ( it.value().name().compare( propertyName, Qt::CaseInsensitive ) == 0 )
464  {
465  def = it.value();
466  if ( parts.size() == 3 )
467  def.setComment( parts[2] );
468  break;
469  }
470  }
471  }
472  else
473  {
474  def.setOrigin( origin );
475  def.setName( propertyName );
476 
477  if ( parts.size() == 3 )
478  def.setComment( parts[2] );
479  }
480 
481  return def;
482 }
483 
485 {
487  QgsField afield;
488 
489  if ( !def.name().isEmpty() || !def.comment().isEmpty() )
490  {
491  afield = createAuxiliaryField( def );
492  afield.setTypeName( field.typeName() );
493  }
494 
495  return afield;
496 }
497 
498 //
499 // QgsAuxiliaryStorage
500 //
501 
503  : mCopy( copy )
504 {
505  initTmpFileName();
506 
507  if ( !project.absoluteFilePath().isEmpty() )
508  {
509  mFileName = filenameForProject( project );
510  }
511 
512  open( mFileName );
513 }
514 
515 QgsAuxiliaryStorage::QgsAuxiliaryStorage( const QString &filename, bool copy )
516  : mFileName( filename )
517  , mCopy( copy )
518 {
519  initTmpFileName();
520 
521  open( filename );
522 }
523 
525 {
526  QFile::remove( mTmpFileName );
527 }
528 
530 {
531  return mValid;
532 }
533 
535 {
536  return mFileName;
537 }
538 
540 {
541  if ( mFileName.isEmpty() )
542  {
543  // only a saveAs is available on a new database
544  return false;
545  }
546  else if ( mCopy )
547  {
548  if ( QFile::exists( mFileName ) )
549  QFile::remove( mFileName );
550 
551  return QFile::copy( mTmpFileName, mFileName );
552  }
553  else
554  {
555  // if the file is not empty the copy mode is not activated, then we're
556  // directly working on the database since the beginning (no savepoints
557  // /rollback for now)
558  return true;
559  }
560 }
561 
563 {
564  QgsAuxiliaryLayer *alayer = nullptr;
565 
566  if ( mValid && layer )
567  {
568  const QString table( layer->id() );
570  database = openDB( currentFileName() );
571 
572  if ( !tableExists( table, database.get() ) )
573  {
574  if ( !createTable( field.typeName(), table, database.get() ) )
575  {
576  return alayer;
577  }
578  }
579 
580  alayer = new QgsAuxiliaryLayer( field.name(), currentFileName(), table, layer );
581  alayer->startEditing();
582  }
583 
584  return alayer;
585 }
586 
588 {
589  bool rc = false;
590  QgsDataSourceUri uri = parseOgrUri( ogrUri );
591 
592  if ( !uri.database().isEmpty() && !uri.table().isEmpty() )
593  {
595  database = openDB( uri.database() );
596 
597  if ( database )
598  {
599  QString sql = QString( "DROP TABLE %1" ).arg( uri.table() );
600  rc = exec( sql, database.get() );
601 
602  sql = QStringLiteral( "VACUUM" );
603  rc = exec( sql, database.get() );
604  }
605  }
606 
607  return rc;
608 }
609 
610 bool QgsAuxiliaryStorage::duplicateTable( const QgsDataSourceUri &ogrUri, const QString &newTable )
611 {
612  QgsDataSourceUri uri = parseOgrUri( ogrUri );
613  bool rc = false;
614 
615  if ( !uri.table().isEmpty() && !uri.database().isEmpty() )
616  {
618  database = openDB( uri.database() );
619 
620  if ( database )
621  {
622  QString sql = QStringLiteral( "CREATE TABLE %1 AS SELECT * FROM %2" ).arg( newTable, uri.table() );
623  rc = exec( sql, database.get() );
624  }
625  }
626 
627  return rc;
628 }
629 
631 {
632  return mErrorString;
633 }
634 
635 bool QgsAuxiliaryStorage::saveAs( const QString &filename )
636 {
637  mErrorString.clear();
638 
639  QFile dest( filename );
640  if ( dest.exists() && !dest.remove() )
641  {
642  mErrorString = dest.errorString();
643  return false;
644  }
645 
646  QFile origin( currentFileName() );
647  if ( !origin.copy( filename ) )
648  {
649  mErrorString = origin.errorString();
650  return false;
651  }
652 
653  return true;
654 }
655 
657 {
658  return saveAs( filenameForProject( project ) );
659 }
660 
662 {
663  return AS_EXTENSION;
664 }
665 
667 {
668  const QFileInfo fileinfo( filenameForProject( project ) );
669  return fileinfo.exists() && fileinfo.isFile();
670 }
671 
672 bool QgsAuxiliaryStorage::exec( const QString &sql, sqlite3 *handler )
673 {
674  bool rc = false;
675 
676  if ( handler )
677  {
678  const int err = sqlite3_exec( handler, sql.toStdString().c_str(), nullptr, nullptr, nullptr );
679 
680  if ( err == SQLITE_OK )
681  rc = true;
682  else
683  debugMsg( sql, handler );
684  }
685 
686  return rc;
687 }
688 
689 void QgsAuxiliaryStorage::debugMsg( const QString &sql, sqlite3 *handler )
690 {
691 #ifdef QGISDEBUG
692  const QString err = QString::fromUtf8( sqlite3_errmsg( handler ) );
693  const QString msg = QObject::tr( "Unable to execute" );
694  const QString errMsg = QObject::tr( "%1 '%2': %3" ).arg( msg, sql, err );
695  QgsDebugMsg( errMsg );
696 #else
697  Q_UNUSED( sql )
698  Q_UNUSED( handler )
699 #endif
700 }
701 
702 bool QgsAuxiliaryStorage::createTable( const QString &type, const QString &table, sqlite3 *handler )
703 {
704  const QString sql = QStringLiteral( "CREATE TABLE IF NOT EXISTS '%1' ( '%2' %3 )" ).arg( table, AS_JOINFIELD, type );
705 
706  if ( !exec( sql, handler ) )
707  return false;
708 
709  return true;
710 }
711 
712 spatialite_database_unique_ptr QgsAuxiliaryStorage::createDB( const QString &filename )
713 {
715 
716  int rc;
717  rc = database.open_v2( filename, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, nullptr );
718  if ( rc )
719  {
720  debugMsg( QStringLiteral( "sqlite3_open_v2" ), database.get() );
721  }
722  else
723  // activating Foreign Key constraints
724  exec( QStringLiteral( "PRAGMA foreign_keys = 1" ), database.get() );
725 
726  return database;
727 }
728 
729 spatialite_database_unique_ptr QgsAuxiliaryStorage::openDB( const QString &filename )
730 {
732  int rc = database.open_v2( filename, SQLITE_OPEN_READWRITE, nullptr );
733 
734  if ( rc )
735  {
736  debugMsg( "sqlite3_open_v2", database.get() );
737  }
738 
739  return database;
740 }
741 
742 bool QgsAuxiliaryStorage::tableExists( const QString &table, sqlite3 *handler )
743 {
744  const QString sql = QStringLiteral( "SELECT 1 FROM sqlite_master WHERE type='table' AND name='%1'" ).arg( table );
745  int rows = 0;
746  int columns = 0;
747  char **results = nullptr;
748  const int rc = sqlite3_get_table( handler, sql.toStdString().c_str(), &results, &rows, &columns, nullptr );
749  if ( rc != SQLITE_OK )
750  {
751  debugMsg( sql, handler );
752  return false;
753  }
754 
755  sqlite3_free_table( results );
756  if ( rows >= 1 )
757  return true;
758 
759  return false;
760 }
761 
762 spatialite_database_unique_ptr QgsAuxiliaryStorage::open( const QString &filename )
763 {
765 
766  if ( filename.isEmpty() )
767  {
768  if ( ( database = createDB( currentFileName() ) ) )
769  mValid = true;
770  }
771  else if ( QFile::exists( filename ) )
772  {
773  if ( mCopy )
774  QFile::copy( filename, mTmpFileName );
775 
776  if ( ( database = openDB( currentFileName() ) ) )
777  mValid = true;
778  }
779  else
780  {
781  if ( ( database = createDB( currentFileName() ) ) )
782  mValid = true;
783  }
784 
785  return database;
786 }
787 
788 spatialite_database_unique_ptr QgsAuxiliaryStorage::open( const QgsProject &project )
789 {
790  return open( filenameForProject( project ) );
791 }
792 
793 QString QgsAuxiliaryStorage::filenameForProject( const QgsProject &project )
794 {
795  const QFileInfo info( project.absoluteFilePath() );
796  const QString path = info.path() + QDir::separator() + info.baseName();
797  return path + '.' + QgsAuxiliaryStorage::extension();
798 }
799 
800 void QgsAuxiliaryStorage::initTmpFileName()
801 {
802  QTemporaryFile tmpFile;
803  tmpFile.open();
804  tmpFile.close();
805  mTmpFileName = tmpFile.fileName();
806 }
807 
809 {
810  if ( mCopy || mFileName.isEmpty() )
811  return mTmpFileName;
812  else
813  return mFileName;
814 }
815 
816 QgsDataSourceUri QgsAuxiliaryStorage::parseOgrUri( const QgsDataSourceUri &uri )
817 {
818  QgsDataSourceUri newUri;
819 
820  // parsing for ogr style uri :
821  // " filePath|layername='tableName' table="" sql="
822  QStringList uriParts = uri.uri().split( '|' );
823  if ( uriParts.count() < 2 )
824  return newUri;
825 
826  const QString databasePath = uriParts[0].replace( ' ', "" );
827 
828  const QString table = uriParts[1];
829  QStringList tableParts = table.split( ' ' );
830 
831  if ( tableParts.count() < 1 )
832  return newUri;
833 
834  const QString tableName = tableParts[0].replace( QStringLiteral( "layername=" ), QString() );
835 
836  newUri.setDataSource( QString(), tableName, QString() );
837  newUri.setDatabase( databasePath );
838 
839  return newUri;
840 }
void setProperty(int key, const QgsProperty &property)
Adds a property to the collection and takes ownership of it.
int lookupField(const QString &fieldName) const
Looks up field&#39;s index from the field name.
Definition: qgsfields.cpp:324
bool isValid() const
Returns the validity of this feature.
Definition: qgsfeature.cpp:183
void updateFields()
Will regenerate the fields property of this layer by obtaining all fields from the dataProvider...
void setJoinLayer(QgsVectorLayer *layer)
Sets weak reference to the joined layer.
static const QgsPropertiesDefinition & propertyDefinitions()
Returns the labeling property definitions.
Wrapper for iterator of features from vector data provider or vector layer.
static QgsField createAuxiliaryField(const QgsPropertyDefinition &definition)
Creates a new auxiliary field from a property definition.
int precision
int open_v2(const QString &path, int flags, const char *zVfs)
Opens the database at the specified file path.
QString targetFieldName() const
Returns name of the field of our layer that will be used for join.
void setDiagramLayerSettings(const QgsDiagramLayerSettings &s)
QString table() const
Returns the table name stored in the URI.
void update(const QgsFields &fields)
Update the configuration with the given fields.
Property
Data definable properties.
bool isValid() const
Returns the status of the auxiliary storage currently defined.
QgsMapLayerType type() const
Returns the type of the layer.
QString name
Definition: qgsfield.h:58
bool save()
Commits changes and starts editing then.
QgsPropertyDefinition propertyDefinitionFromIndex(int index) const
Returns the property definition for the underlying field index.
bool exists(const QgsPropertyDefinition &definition) const
Returns true if the property is stored in the layer already, false otherwise.
int propertyFromIndex(int index) const
Returns the underlying property key for the field index.
void setEditable(bool enabled)
Sets whether the form of the target layer allows editing joined fields.
QgsWkbTypes::Type wkbType() const FINAL
Returns the WKBType or WKBUnknown in case of error.
void setPrecision(int precision)
Set the field precision.
Definition: qgsfield.cpp:165
#define QgsDebugMsg(str)
Definition: qgslogger.h:38
Class allowing to manage the auxiliary storage for a vector layer.
bool commitChanges()
Attempts to commit to the underlying data provider any buffered changes made since the last to call t...
int indexOfPropertyDefinition(const QgsPropertyDefinition &definition) const
Returns the index of the auxiliary field for a specific property definition.
const QString AS_JOINFIELD
bool startEditing()
Makes the layer editable.
virtual void setSettings(QgsPalLayerSettings *settings, const QString &providerId=QString())=0
Set pal settings for a specific provider (takes ownership).
static QgsProperty fromField(const QString &fieldName, bool isActive=true)
Returns a new FieldBasedProperty created from the specified field name.
bool deleteFeatures(const QgsFeatureIds &fids)
Deletes a set of features from the layer (but does not commit it)
X-coordinate data defined label position.
void setJoinFieldName(const QString &fieldName)
Sets name of the field of joined layer that will be used for join.
Min scale (deprecated, for old project compatibility only)
Container of fields for a vector layer.
Definition: qgsfields.h:42
void setName(const QString &name)
Set the field name.
Definition: qgsfield.cpp:141
const QString AS_EXTENSION
Color with alpha channel.
Definition: qgsproperty.h:64
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
Definition: qgsfeature.h:55
QString currentFileName() const
Returns the path of the current database used.
QgsVectorLayer * toSpatialLayer() const
An auxiliary layer is not spatial.
void setName(const QString &name)
Sets the name of the property.
Definition: qgsproperty.h:143
int count() const
Returns number of items.
Definition: qgsfields.cpp:133
static QString extension()
Returns the extension used for auxiliary databases.
void styleChanged()
Signal emitted whenever a change affects the layer&#39;s style.
virtual QStringList subProviders() const
Gets list of sub-providers within the layer&#39;s labeling.
As part of the API refactoring and improvements which landed in the Processing API was substantially reworked from the x version This was done in order to allow much of the underlying Processing framework to be ported into c
static int createProperty(QgsPalLayerSettings::Property property, QgsVectorLayer *vlayer)
Creates if necessary a new auxiliary field for a PAL property and activates this property in settings...
void setLength(int len)
Set the field length.
Definition: qgsfield.cpp:161
bool isEditable() const FINAL
Returns true if the provider is in editing mode.
bool save() const
Saves the current database.
Property
Data definable properties.
void setUpsertOnEdit(bool enabled)
Sets whether a feature created on the target layer has to impact the joined layer by creating a new f...
void setEditorWidgetSetup(int index, const QgsEditorWidgetSetup &setup)
The editor widget setup defines which QgsFieldFormatter and editor widget will be used for the field ...
QgsFeatureRequest & setFilterExpression(const QString &expression)
Set the filter expression.
QString id() const
Returns the layer&#39;s unique ID, which is used to access this layer from QgsProject.
DataType dataType() const
Returns the allowable field/value data type for the property.
Definition: qgsproperty.h:187
QgsFields fields() const FINAL
Returns the list of fields of this layer.
Unique pointer for spatialite databases, which automatically closes the database when the pointer goe...
const QVector< QgsPalLayerSettings::Property > palHiddenProperties
QString fileName() const
Returns the target filename of the database.
virtual QgsPalLayerSettings settings(const QString &providerId=QString()) const =0
Gets associated label settings.
void setDataDefinedProperties(const QgsPropertyCollection &collection)
Sets the label&#39;s property collection, used for data defined overrides.
Property requires a boolean value.
Definition: qgsproperty.h:105
QString typeName() const
Gets the field type.
Definition: qgsfield.cpp:105
void setTypeName(const QString &typeName)
Set the field type.
Definition: qgsfield.cpp:156
const QString & typeName
Defines left outer join from our vector layer to some other vector layer.
virtual bool deleteAttribute(int attr)
Deletes an attribute field (but does not commit it).
const QString AS_JOINPREFIX
virtual ~QgsAuxiliaryStorage()
Destructor.
Horizontal alignment for data defined label position (Left, Center, Right)
Property requires a numeric value.
Definition: qgsproperty.h:98
This class wraps a request for features to a vector layer (or directly its vector data provider)...
QgsVectorLayerJoinInfo joinInfo() const
Returns information to use for joining with primary key and so on.
bool append(const QgsField &field, FieldOrigin origin=OriginProvider, int originIndex=-1)
Appends a field. The field must have unique name, otherwise it is rejected (returns false) ...
Definition: qgsfields.cpp:59
Reads and writes project states.
Definition: qgsproject.h:89
Encapsulate a field in an attribute table or data source.
Definition: qgsfield.h:48
bool clear()
Deletes all features from the layer.
QgsAuxiliaryLayer(const QString &pkField, const QString &filename, const QString &table, QgsVectorLayer *vlayer)
Constructor.
const QgsAbstractVectorLayerLabeling * labeling() const
Access to const labeling configuration.
A store for object properties.
Definition: qgsproperty.h:229
void setTargetFieldName(const QString &fieldName)
Sets name of the field of our layer that will be used for join.
static QString createFieldEqualityExpression(const QString &fieldName, const QVariant &value)
Create an expression allowing to evaluate if a field is equal to a value.
QgsAuxiliaryLayer * auxiliaryLayer()
Returns the current auxiliary layer.
static bool deleteTable(const QgsDataSourceUri &uri)
Removes a table from the auxiliary storage.
Definition for a property.
Definition: qgsproperty.h:46
QMap< int, QgsPropertyDefinition > QgsPropertiesDefinition
Definition of available properties.
struct sqlite3 sqlite3
QString uri(bool expandAuthConfig=true) const
Returns the complete URI as a string.
static bool exists(const QgsProject &project)
Returns true if the auxiliary database yet exists for a project, false otherwise. ...
Stores the settings for rendering of all diagrams for a layer.
QVector< QgsAttributeTableConfig::ColumnConfig > columns() const
Gets the list with all columns and their configuration.
QgsAttributeTableConfig attributeTableConfig() const
Returns the attribute table configuration object.
QString comment() const
Returns the comment of the property.
Definition: qgsproperty.h:167
void setDataSource(const QString &aSchema, const QString &aTable, const QString &aGeometryColumn, const QString &aSql=QString(), const QString &aKeyColumn=QString())
Sets all data source related members at once.
void setType(QVariant::Type type)
Set variant type.
Definition: qgsfield.cpp:146
void setPrefix(const QString &prefix)
Sets prefix of fields from the joined layer. If nullptr, joined layer&#39;s name will be used...
QgsEditorWidgetSetup editorWidgetSetup(int index) const
The editor widget setup defines which QgsFieldFormatter and editor widget will be used for the field ...
void setColumns(const QVector< QgsAttributeTableConfig::ColumnConfig > &columns)
Set the list of columns visible in the attribute table.
int indexOf(const QString &fieldName) const
Gets the field index from the field name.
Definition: qgsfields.cpp:207
Property requires a string value.
Definition: qgsproperty.h:91
QString source() const
Returns the source for the layer.
QgsAuxiliaryStorage(const QgsProject &project, bool copy=true)
Constructor.
const QgsDiagramLayerSettings * diagramLayerSettings() const
Holder for the widget type and its configuration for a field.
static const QgsPropertiesDefinition & propertyDefinitions()
Returns the diagram property definitions.
void setOrigin(const QString &origin)
Sets the origin of the property.
Definition: qgsproperty.h:157
static QString nameFromProperty(const QgsPropertyDefinition &def, bool joined=false)
Returns the name of the auxiliary field for a property definition.
void setGeometry(const QgsGeometry &geometry)
Set the feature&#39;s geometry.
Definition: qgsfeature.cpp:137
void setComment(const QString &comment)
Sets comment of the property.
Definition: qgsproperty.h:172
bool addFeature(QgsFeature &feature, QgsFeatureSink::Flags flags=nullptr) FINAL
Adds a single feature to the sink.
void setCascadedDelete(bool enabled)
Sets whether a feature deleted on the target layer has to impact the joined layer by deleting the cor...
QString errorString() const
Returns the underlying error string describing potential errors happening in saveAs().
A grouped map of multiple QgsProperty objects, each referenced by a integer key value.
QgsFeatureIterator getFeatures(const QgsFeatureRequest &request=QgsFeatureRequest()) const FINAL
Queries the layer for features specified in request.
void setJoinFieldNamesBlackList(const QStringList &blackList)
Sets a list of fields to ignore whatever happens.
bool deleteAttribute(int attr) override
Removes attribute from the layer and commits changes.
QgsGeometry geometry
Definition: qgsfeature.h:67
static bool duplicateTable(const QgsDataSourceUri &uri, const QString &newTable)
Duplicates a table and its content.
static QgsVectorLayer * createMemoryLayer(const QString &name, const QgsFields &fields, QgsWkbTypes::Type geometryType=QgsWkbTypes::NoGeometry, const QgsCoordinateReferenceSystem &crs=QgsCoordinateReferenceSystem())
Creates a new memory layer using the specified parameters.
QgsFields auxiliaryFields() const
Returns a list of all auxiliary fields currently managed by the layer.
Y-coordinate data defined label position.
bool nextFeature(QgsFeature &f)
This is a container for configuration of the attribute table.
static const QgsPropertiesDefinition & propertyDefinitions()
Returns the symbol layer property definitions.
Max scale (deprecated, for old project compatibility only)
Class for storing the component parts of a RDBMS data source URI (e.g.
bool addAuxiliaryField(const QgsPropertyDefinition &definition)
Adds an auxiliary field for the given property.
QString absoluteFilePath() const
Returns full absolute path to the project file if the project is stored in a file system - derived fr...
Definition: qgsproject.cpp:619
static QgsPropertyDefinition propertyDefinitionFromField(const QgsField &field)
Returns the property definition from an auxiliary field.
QString name() const
Returns the name of the property.
Definition: qgsproperty.h:138
Represents a vector layer which manages a vector based data sets.
bool addAttribute(const QgsField &field)
Add an attribute field (but does not commit it) returns true if the field was added.
QVariant attribute(const QString &name) const
Lookup attribute value from attribute name.
Definition: qgsfeature.cpp:262
virtual QgsFeatureIds allFeatureIds() const
Returns a list of all feature IDs for features present in the source.
Vertical alignment for data defined label position (Bottom, Base, Half, Cap, Top) ...
void setAttributeTableConfig(const QgsAttributeTableConfig &attributeTableConfig)
Sets the attribute table configuration object.
QgsField field(int fieldIdx) const
Gets field at particular index (must be in range 0..N-1)
Definition: qgsfields.cpp:168
bool isHiddenProperty(int index) const
Returns true if the underlying field has to be hidden from editing tools like attribute table...
QString database() const
Returns the database name stored in the URI.
QgsAuxiliaryLayer * createAuxiliaryLayer(const QgsField &field, QgsVectorLayer *layer) const
Creates an auxiliary layer for a vector layer.
bool saveAs(const QString &filename)
Saves the current database to a new path.
void setDatabase(const QString &database)
Sets the URI database name.
QString origin() const
Returns the origin of the property.
Definition: qgsproperty.h:150
StandardPropertyTemplate standardTemplate() const
Returns the property&#39;s standard template, if applicable.
Definition: qgsproperty.h:193
QgsCoordinateReferenceSystem crs
Definition: qgsmaplayer.h:85
QgsVectorLayer * clone() const override
Returns a new instance equivalent to this one.
QgsPropertyCollection & dataDefinedProperties()
Returns a reference to the label&#39;s property collection, used for data defined overrides.
Color with no alpha channel.
Definition: qgsproperty.h:65