QGIS API Documentation  3.20.0-Odense (decaadbb31)
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 : [email protected]
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 #define AS_JOINFIELD QStringLiteral( "ASPK" )
31 #define AS_EXTENSION QStringLiteral( "qgd" )
32 #define AS_JOINPREFIX QStringLiteral( "auxiliary_storage_" )
33 typedef QVector<QgsPalLayerSettings::Property> PalPropertyList;
35 {
61 } ) )
62 
63 //
64 // QgsAuxiliaryLayer
65 //
66 
67 QgsAuxiliaryLayer::QgsAuxiliaryLayer( const QString &pkField, const QString &filename, const QString &table, QgsVectorLayer *vlayer )
68  : QgsVectorLayer( QStringLiteral( "%1|layername=%2" ).arg( filename, table ),
69  QStringLiteral( "%1_auxiliarystorage" ).arg( table ), QStringLiteral( "ogr" ) )
70  , mFileName( filename )
71  , mTable( table )
72  , mLayer( vlayer )
73 {
74  // init join info
75  mJoinInfo.setPrefix( AS_JOINPREFIX );
76  mJoinInfo.setJoinLayer( this );
77  mJoinInfo.setJoinFieldName( AS_JOINFIELD );
78  mJoinInfo.setTargetFieldName( pkField );
79  mJoinInfo.setEditable( true );
80  mJoinInfo.setUpsertOnEdit( true );
81  mJoinInfo.setCascadedDelete( true );
82  mJoinInfo.setJoinFieldNamesBlockList( QStringList() << QStringLiteral( "rowid" ) ); // introduced by ogr provider
83 }
84 
86 {
88  return new QgsAuxiliaryLayer( mJoinInfo.targetFieldName(), mFileName, target->id(), target );
89 }
90 
92 {
93  bool rc = deleteFeatures( allFeatureIds() );
94  commitChanges();
95  startEditing();
96  return rc;
97 }
98 
100 {
101  QgsVectorLayer *layer = QgsMemoryProviderUtils::createMemoryLayer( QStringLiteral( "auxiliary_layer" ), fields(), mLayer->wkbType(), mLayer->crs() );
102 
103  QString pkField = mJoinInfo.targetFieldName();
104  QgsFeature joinFeature;
105  QgsFeature targetFeature;
107 
108  layer->startEditing();
109  while ( it.nextFeature( joinFeature ) )
110  {
111  QString filter = QgsExpression::createFieldEqualityExpression( pkField, joinFeature.attribute( AS_JOINFIELD ) );
112 
113  QgsFeatureRequest request;
114  request.setFilterExpression( filter );
115 
116  mLayer->getFeatures( request ).nextFeature( targetFeature );
117 
118  if ( targetFeature.isValid() )
119  {
120  QgsFeature newFeature( joinFeature );
121  newFeature.setGeometry( targetFeature.geometry() );
122  layer->addFeature( newFeature );
123  }
124  }
125  layer->commitChanges();
126 
127  return layer;
128 }
129 
131 {
132  return mJoinInfo;
133 }
134 
135 bool QgsAuxiliaryLayer::exists( const QgsPropertyDefinition &definition ) const
136 {
137  return ( indexOfPropertyDefinition( definition ) >= 0 );
138 }
139 
141 {
142  if ( ( definition.name().isEmpty() && definition.comment().isEmpty() ) || exists( definition ) )
143  return false;
144 
145  const QgsField af = createAuxiliaryField( definition );
146  const bool rc = addAttribute( af );
147  updateFields();
148  mLayer->updateFields();
149 
150  if ( rc )
151  {
152  int auxIndex = indexOfPropertyDefinition( definition );
153  int index = mLayer->fields().indexOf( nameFromProperty( definition, true ) );
154 
155  if ( index >= 0 && auxIndex >= 0 )
156  {
157  if ( isHiddenProperty( auxIndex ) )
158  {
159  // update editor widget
160  QgsEditorWidgetSetup setup = QgsEditorWidgetSetup( QStringLiteral( "Hidden" ), QVariantMap() );
161  setEditorWidgetSetup( auxIndex, setup );
162 
163  // column is hidden
164  QgsAttributeTableConfig attrCfg = mLayer->attributeTableConfig();
165  attrCfg.update( mLayer->fields() );
166  QVector<QgsAttributeTableConfig::ColumnConfig> columns = attrCfg.columns();
167  QVector<QgsAttributeTableConfig::ColumnConfig>::iterator it;
168 
169  for ( it = columns.begin(); it != columns.end(); ++it )
170  {
171  if ( it->name.compare( mLayer->fields().field( index ).name() ) == 0 )
172  it->hidden = true;
173  }
174 
175  attrCfg.setColumns( columns );
176  mLayer->setAttributeTableConfig( attrCfg );
177  }
178  else if ( definition.standardTemplate() == QgsPropertyDefinition::ColorNoAlpha
180  {
181  QgsEditorWidgetSetup setup = QgsEditorWidgetSetup( QStringLiteral( "Color" ), QVariantMap() );
182  setEditorWidgetSetup( auxIndex, setup );
183  }
184 
185  mLayer->setEditorWidgetSetup( index, editorWidgetSetup( auxIndex ) );
186  }
187  }
188 
189  return rc;
190 }
191 
193 {
194  QgsFields afields;
195 
196  for ( int i = 2; i < fields().count(); i++ ) // ignore rowid and PK field
197  afields.append( createAuxiliaryField( fields().field( i ) ) );
198 
199  return afields;
200 }
201 
203 {
205  bool rc = commitChanges();
206  startEditing();
207  return rc;
208 }
209 
211 {
212  bool rc = false;
213 
214  if ( isEditable() )
215  {
216  rc = commitChanges();
217  }
218 
219  startEditing();
220 
221  return rc;
222 }
223 
225 {
226  int index = -1;
227 
228  if ( layer && layer->labeling() && layer->auxiliaryLayer() )
229  {
230  // property definition are identical whatever the provider id
231  const QgsPropertyDefinition def = layer->labeling()->settings().propertyDefinitions()[property];
232  const QString fieldName = nameFromProperty( def, true );
233 
234  layer->auxiliaryLayer()->addAuxiliaryField( def );
235 
236  if ( layer->auxiliaryLayer()->indexOfPropertyDefinition( def ) >= 0 )
237  {
238  const QgsProperty prop = QgsProperty::fromField( fieldName );
239 
240  const QStringList subProviderIds = layer->labeling()->subProviders();
241  for ( const QString &providerId : subProviderIds )
242  {
243  QgsPalLayerSettings *settings = new QgsPalLayerSettings( layer->labeling()->settings( providerId ) );
244 
246  c.setProperty( property, prop );
247  settings->setDataDefinedProperties( c );
248 
249  layer->labeling()->setSettings( settings, providerId );
250  }
251  }
252 
253  index = layer->fields().lookupField( fieldName );
254  }
255 
256  return index;
257 }
258 
260 {
261  int index = -1;
262 
263  if ( layer && layer->diagramLayerSettings() && layer->auxiliaryLayer() )
264  {
265  const QgsPropertyDefinition def = layer->diagramLayerSettings()->propertyDefinitions()[property];
266 
267  if ( layer->auxiliaryLayer()->addAuxiliaryField( def ) )
268  {
269  const QString fieldName = nameFromProperty( def, true );
270  const QgsProperty prop = QgsProperty::fromField( fieldName );
271 
272  QgsDiagramLayerSettings settings( *layer->diagramLayerSettings() );
273 
275  c.setProperty( property, prop );
276  settings.setDataDefinedProperties( c );
277 
278  layer->setDiagramLayerSettings( settings );
279  index = layer->fields().lookupField( fieldName );
280  }
281  }
282 
283  return index;
284 }
285 
287 {
288  int index = -1;
289 
290  if ( layer && layer->labeling() && layer->labeling()->settings().callout() && layer->auxiliaryLayer() )
291  {
292  // property definition are identical whatever the provider id
293  const QgsPropertyDefinition def = layer->labeling()->settings().callout()->propertyDefinitions()[property];
294  const QString fieldName = nameFromProperty( def, true );
295 
296  layer->auxiliaryLayer()->addAuxiliaryField( def );
297 
298  if ( layer->auxiliaryLayer()->indexOfPropertyDefinition( def ) >= 0 )
299  {
300  const QgsProperty prop = QgsProperty::fromField( fieldName );
301 
302  const QStringList subProviderIds = layer->labeling()->subProviders();
303  for ( const QString &providerId : subProviderIds )
304  {
305  QgsPalLayerSettings *settings = new QgsPalLayerSettings( layer->labeling()->settings( providerId ) );
306  if ( settings->callout() )
307  {
309  c.setProperty( property, prop );
310  settings->callout()->setDataDefinedProperties( c );
311  }
312  layer->labeling()->setSettings( settings, providerId );
313  }
314  }
315 
316  index = layer->fields().lookupField( fieldName );
317  }
318 
319  return index;
320 }
321 
322 bool QgsAuxiliaryLayer::isHiddenProperty( int index ) const
323 {
324  bool hidden = false;
326 
327  if ( def.origin().compare( QLatin1String( "labeling" ) ) == 0 )
328  {
329  const PalPropertyList &palProps = *palHiddenProperties();
330  for ( const QgsPalLayerSettings::Property &p : palProps )
331  {
332  const QString propName = QgsPalLayerSettings::propertyDefinitions()[ p ].name();
333  if ( propName.compare( def.name() ) == 0 )
334  {
335  hidden = true;
336  break;
337  }
338  }
339  }
340 
341  return hidden;
342 }
343 
345 {
346  int p = -1;
348 
349  if ( aDef.origin().compare( QLatin1String( "labeling" ) ) == 0 )
350  {
352  QgsPropertiesDefinition::const_iterator it = defs.constBegin();
353  for ( ; it != defs.constEnd(); ++it )
354  {
355  if ( it->name().compare( aDef.name(), Qt::CaseInsensitive ) == 0 )
356  {
357  p = it.key();
358  break;
359  }
360  }
361  }
362  else if ( aDef.origin().compare( QLatin1String( "symbol" ) ) == 0 )
363  {
365  QgsPropertiesDefinition::const_iterator it = defs.constBegin();
366  for ( ; it != defs.constEnd(); ++it )
367  {
368  if ( it->name().compare( aDef.name(), Qt::CaseInsensitive ) == 0 )
369  {
370  p = it.key();
371  break;
372  }
373  }
374  }
375  else if ( aDef.origin().compare( QLatin1String( "diagram" ) ) == 0 )
376  {
378  QgsPropertiesDefinition::const_iterator it = defs.constBegin();
379  for ( ; it != defs.constEnd(); ++it )
380  {
381  if ( it->name().compare( aDef.name(), Qt::CaseInsensitive ) == 0 )
382  {
383  p = it.key();
384  break;
385  }
386  }
387  }
388 
389  return p;
390 }
391 
393 {
394  return propertyDefinitionFromField( fields().field( index ) );
395 }
396 
398 {
399  return fields().indexOf( nameFromProperty( def ) );
400 }
401 
403 {
404  QString fieldName = def.origin();
405 
406  if ( !def.name().isEmpty() )
407  fieldName = QStringLiteral( "%1_%2" ).arg( fieldName, def.name().toLower() );
408 
409  if ( !def.comment().isEmpty() )
410  fieldName = QStringLiteral( "%1_%2" ).arg( fieldName, def.comment() );
411 
412  if ( joined )
413  fieldName = QStringLiteral( "%1%2" ).arg( AS_JOINPREFIX, fieldName );
414 
415  return fieldName;
416 }
417 
419 {
420  QgsField afield;
421 
422  if ( !def.name().isEmpty() || !def.comment().isEmpty() )
423  {
424  QVariant::Type type = QVariant::Invalid;
425  QString typeName;
426  int len( 0 ), precision( 0 );
427  switch ( def.dataType() )
428  {
430  type = QVariant::String;
431  len = 50;
432  typeName = QStringLiteral( "String" );
433  break;
435  type = QVariant::Double;
436  len = 0;
437  precision = 0;
438  typeName = QStringLiteral( "Real" );
439  break;
441  type = QVariant::Int; // sqlite does not have a bool type
442  typeName = QStringLiteral( "Integer" );
443  break;
444  }
445 
446  afield.setType( type );
447  afield.setName( nameFromProperty( def ) );
448  afield.setTypeName( typeName );
449  afield.setLength( len );
450  afield.setPrecision( precision );
451  }
452 
453  return afield;
454 }
455 
457 {
459  const QStringList parts = f.name().split( '_' );
460 
461  if ( parts.size() <= 1 )
462  return def;
463 
464  const QString origin = parts[0];
465  const QString propertyName = parts[1];
466 
467  if ( origin.compare( QLatin1String( "labeling" ), Qt::CaseInsensitive ) == 0 )
468  {
470  for ( auto it = props.constBegin(); it != props.constEnd(); ++it )
471  {
472  if ( it.value().name().compare( propertyName, Qt::CaseInsensitive ) == 0 )
473  {
474  def = it.value();
475  if ( parts.size() >= 3 )
476  def.setComment( parts.mid( 2 ).join( '_' ) );
477  break;
478  }
479  }
480  }
481  else if ( origin.compare( QLatin1String( "symbol" ), Qt::CaseInsensitive ) == 0 )
482  {
484  for ( auto it = props.constBegin(); it != props.constEnd(); ++it )
485  {
486  if ( it.value().name().compare( propertyName, Qt::CaseInsensitive ) == 0 )
487  {
488  def = it.value();
489  if ( parts.size() >= 3 )
490  def.setComment( parts.mid( 2 ).join( '_' ) );
491  break;
492  }
493  }
494  }
495  else if ( origin.compare( QLatin1String( "diagram" ), Qt::CaseInsensitive ) == 0 )
496  {
498  for ( auto it = props.constBegin(); it != props.constEnd(); ++it )
499  {
500  if ( it.value().name().compare( propertyName, Qt::CaseInsensitive ) == 0 )
501  {
502  def = it.value();
503  if ( parts.size() >= 3 )
504  def.setComment( parts.mid( 2 ).join( '_' ) );
505  break;
506  }
507  }
508  }
509  else
510  {
511  def.setOrigin( origin );
512  def.setName( propertyName );
513  switch ( f.type() )
514  {
515  case QVariant::Double:
517  break;
518 
519  case QVariant::Bool:
521  break;
522 
523  case QVariant::String:
524  default:
526  break;
527  }
528 
529  if ( parts.size() >= 3 )
530  def.setComment( parts.mid( 2 ).join( '_' ) );
531  }
532 
533  return def;
534 }
535 
537 {
539  QgsField afield;
540 
541  if ( !def.name().isEmpty() || !def.comment().isEmpty() )
542  {
543  afield = createAuxiliaryField( def );
544  afield.setTypeName( field.typeName() );
545  }
546 
547  return afield;
548 }
549 
550 //
551 // QgsAuxiliaryStorage
552 //
553 
555  : mCopy( copy )
556 {
557  initTmpFileName();
558 
559  if ( !project.absoluteFilePath().isEmpty() )
560  {
561  mFileName = filenameForProject( project );
562  }
563 
564  open( mFileName );
565 }
566 
567 QgsAuxiliaryStorage::QgsAuxiliaryStorage( const QString &filename, bool copy )
568  : mFileName( filename )
569  , mCopy( copy )
570 {
571  initTmpFileName();
572 
573  open( filename );
574 }
575 
577 {
578  QFile::remove( mTmpFileName );
579 }
580 
582 {
583  return mValid;
584 }
585 
587 {
588  return mFileName;
589 }
590 
592 {
593  if ( mFileName.isEmpty() )
594  {
595  // only a saveAs is available on a new database
596  return false;
597  }
598  else if ( mCopy )
599  {
600  if ( QFile::exists( mFileName ) )
601  QFile::remove( mFileName );
602 
603  return QFile::copy( mTmpFileName, mFileName );
604  }
605  else
606  {
607  // if the file is not empty the copy mode is not activated, then we're
608  // directly working on the database since the beginning (no savepoints
609  // /rollback for now)
610  return true;
611  }
612 }
613 
615 {
616  QgsAuxiliaryLayer *alayer = nullptr;
617 
618  if ( mValid && layer )
619  {
620  const QString table( layer->id() );
622  database = openDB( currentFileName() );
623 
624  if ( !tableExists( table, database.get() ) )
625  {
626  if ( !createTable( field.typeName(), table, database.get(), mErrorString ) )
627  {
628  return alayer;
629  }
630  }
631 
632  alayer = new QgsAuxiliaryLayer( field.name(), currentFileName(), table, layer );
633  alayer->startEditing();
634  }
635 
636  return alayer;
637 }
638 
640 {
641  bool rc = false;
642  QgsDataSourceUri uri = parseOgrUri( ogrUri );
643 
644  if ( !uri.database().isEmpty() && !uri.table().isEmpty() )
645  {
647  database = openDB( uri.database() );
648 
649  if ( database )
650  {
651  QString sql = QStringLiteral( "DROP TABLE %1" ).arg( uri.table() );
652  rc = exec( sql, database.get() );
653 
654  sql = QStringLiteral( "VACUUM" );
655  rc = exec( sql, database.get() );
656  }
657  }
658 
659  return rc;
660 }
661 
662 bool QgsAuxiliaryStorage::duplicateTable( const QgsDataSourceUri &ogrUri, const QString &newTable )
663 {
664  QgsDataSourceUri uri = parseOgrUri( ogrUri );
665  bool rc = false;
666 
667  if ( !uri.table().isEmpty() && !uri.database().isEmpty() )
668  {
670  database = openDB( uri.database() );
671 
672  if ( database )
673  {
674  QString sql = QStringLiteral( "CREATE TABLE %1 AS SELECT * FROM %2" ).arg( newTable, uri.table() );
675  rc = exec( sql, database.get() );
676  }
677  }
678 
679  return rc;
680 }
681 
683 {
684  return mErrorString;
685 }
686 
687 bool QgsAuxiliaryStorage::saveAs( const QString &filename )
688 {
689  mErrorString.clear();
690 
691  QFile dest( filename );
692  if ( dest.exists() && !dest.remove() )
693  {
694  mErrorString = dest.errorString();
695  return false;
696  }
697 
698  QFile origin( currentFileName() );
699  if ( !origin.copy( filename ) )
700  {
701  mErrorString = origin.errorString();
702  return false;
703  }
704 
705  return true;
706 }
707 
709 {
710  return saveAs( filenameForProject( project ) );
711 }
712 
714 {
715  return AS_EXTENSION;
716 }
717 
719 {
720  const QFileInfo fileinfo( filenameForProject( project ) );
721  return fileinfo.exists() && fileinfo.isFile();
722 }
723 
724 bool QgsAuxiliaryStorage::exec( const QString &sql, sqlite3 *handler )
725 {
726  bool rc = false;
727 
728  if ( handler )
729  {
730  const int err = sqlite3_exec( handler, sql.toStdString().c_str(), nullptr, nullptr, nullptr );
731 
732  if ( err == SQLITE_OK )
733  rc = true;
734  else
735  debugMsg( sql, handler );
736  }
737 
738  return rc;
739 }
740 
741 QString QgsAuxiliaryStorage::debugMsg( const QString &sql, sqlite3 *handler )
742 {
743  const QString err = QString::fromUtf8( sqlite3_errmsg( handler ) );
744  const QString msg = QObject::tr( "Unable to execute" );
745  const QString errMsg = QObject::tr( "%1 '%2': %3" ).arg( msg, sql, err );
746  QgsDebugMsg( errMsg );
747  return errMsg;
748 }
749 
750 bool QgsAuxiliaryStorage::createTable( const QString &type, const QString &table, sqlite3 *handler, QString &errorMsg )
751 {
752  const QString sql = QStringLiteral( "CREATE TABLE IF NOT EXISTS '%1' ( '%2' %3 )" ).arg( table, AS_JOINFIELD, type );
753 
754  if ( !exec( sql, handler ) )
755  {
756  errorMsg = QgsAuxiliaryStorage::debugMsg( sql, handler );
757  return false;
758  }
759 
760  return true;
761 }
762 
763 spatialite_database_unique_ptr QgsAuxiliaryStorage::createDB( const QString &filename )
764 {
766 
767  int rc;
768  rc = database.open_v2( filename, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, nullptr );
769  if ( rc )
770  {
771  debugMsg( QStringLiteral( "sqlite3_open_v2" ), database.get() );
772  }
773  else
774  // activating Foreign Key constraints
775  exec( QStringLiteral( "PRAGMA foreign_keys = 1" ), database.get() );
776 
777  return database;
778 }
779 
780 spatialite_database_unique_ptr QgsAuxiliaryStorage::openDB( const QString &filename )
781 {
783  int rc = database.open_v2( filename, SQLITE_OPEN_READWRITE, nullptr );
784 
785  if ( rc )
786  {
787  debugMsg( QStringLiteral( "sqlite3_open_v2" ), database.get() );
788  }
789 
790  return database;
791 }
792 
793 bool QgsAuxiliaryStorage::tableExists( const QString &table, sqlite3 *handler )
794 {
795  const QString sql = QStringLiteral( "SELECT 1 FROM sqlite_master WHERE type='table' AND name='%1'" ).arg( table );
796  int rows = 0;
797  int columns = 0;
798  char **results = nullptr;
799  const int rc = sqlite3_get_table( handler, sql.toStdString().c_str(), &results, &rows, &columns, nullptr );
800  if ( rc != SQLITE_OK )
801  {
802  debugMsg( sql, handler );
803  return false;
804  }
805 
806  sqlite3_free_table( results );
807  if ( rows >= 1 )
808  return true;
809 
810  return false;
811 }
812 
813 spatialite_database_unique_ptr QgsAuxiliaryStorage::open( const QString &filename )
814 {
816 
817  if ( filename.isEmpty() )
818  {
819  if ( ( database = createDB( currentFileName() ) ) )
820  mValid = true;
821  }
822  else if ( QFile::exists( filename ) )
823  {
824  if ( mCopy )
825  QFile::copy( filename, mTmpFileName );
826 
827  if ( ( database = openDB( currentFileName() ) ) )
828  mValid = true;
829  }
830  else
831  {
832  if ( ( database = createDB( currentFileName() ) ) )
833  mValid = true;
834  }
835 
836  return database;
837 }
838 
839 spatialite_database_unique_ptr QgsAuxiliaryStorage::open( const QgsProject &project )
840 {
841  return open( filenameForProject( project ) );
842 }
843 
844 QString QgsAuxiliaryStorage::filenameForProject( const QgsProject &project )
845 {
846  const QFileInfo info( project.absoluteFilePath() );
847  const QString path = info.path() + QDir::separator() + info.baseName();
848  return path + '.' + QgsAuxiliaryStorage::extension();
849 }
850 
851 void QgsAuxiliaryStorage::initTmpFileName()
852 {
853  QTemporaryFile tmpFile;
854  tmpFile.open();
855  tmpFile.close();
856  mTmpFileName = tmpFile.fileName();
857 }
858 
860 {
861  if ( mCopy || mFileName.isEmpty() )
862  return mTmpFileName;
863  else
864  return mFileName;
865 }
866 
867 QgsDataSourceUri QgsAuxiliaryStorage::parseOgrUri( const QgsDataSourceUri &uri )
868 {
869  QgsDataSourceUri newUri;
870 
871  // parsing for ogr style uri :
872  // " filePath|layername='tableName' table="" sql="
873  QStringList uriParts = uri.uri().split( '|' );
874  if ( uriParts.count() < 2 )
875  return newUri;
876 
877  const QString databasePath = uriParts[0].replace( ' ', QString() );
878 
879  const QString table = uriParts[1];
880  QStringList tableParts = table.split( ' ' );
881 
882  if ( tableParts.count() < 1 )
883  return newUri;
884 
885  const QString tableName = tableParts[0].replace( QLatin1String( "layername=" ), QString() );
886 
887  newUri.setDataSource( QString(), tableName, QString() );
888  newUri.setDatabase( databasePath );
889 
890  return newUri;
891 }
virtual QStringList subProviders() const
Gets list of sub-providers within the layer's labeling.
virtual void setSettings(QgsPalLayerSettings *settings, const QString &providerId=QString())=0
Set pal settings for a specific provider (takes ownership).
virtual QgsPalLayerSettings settings(const QString &providerId=QString()) const =0
Gets associated label settings.
This is a container for configuration of the attribute table.
QVector< QgsAttributeTableConfig::ColumnConfig > columns() const
Gets the list with all columns and their configuration.
void update(const QgsFields &fields)
Update the configuration with the given fields.
void setColumns(const QVector< QgsAttributeTableConfig::ColumnConfig > &columns)
Set the list of columns visible in the attribute table.
Class allowing to manage the auxiliary storage for a vector layer.
static QgsPropertyDefinition propertyDefinitionFromField(const QgsField &field)
Returns the property definition from an auxiliary field.
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...
bool clear()
Deletes all features from the layer.
bool addAuxiliaryField(const QgsPropertyDefinition &definition)
Adds an auxiliary field for the given property.
bool isHiddenProperty(int index) const
Returns true if the underlying field has to be hidden from editing tools like attribute table,...
QgsVectorLayer * toSpatialLayer() const
An auxiliary layer is not spatial.
bool deleteAttribute(int attr) override
Removes attribute from the layer and commits changes.
QgsFields auxiliaryFields() const
Returns a list of all auxiliary fields currently managed by the layer.
QgsAuxiliaryLayer(const QString &pkField, const QString &filename, const QString &table, QgsVectorLayer *vlayer)
Constructor.
bool save()
Commits changes and starts editing then.
int propertyFromIndex(int index) const
Returns the underlying property key for the field index.
QgsVectorLayerJoinInfo joinInfo() const
Returns information to use for joining with primary key and so on.
static QString nameFromProperty(const QgsPropertyDefinition &def, bool joined=false)
Returns the name of the auxiliary field for a property definition.
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 indexOfPropertyDefinition(const QgsPropertyDefinition &definition) const
Returns the index of the auxiliary field for a specific property definition.
static QgsField createAuxiliaryField(const QgsPropertyDefinition &definition)
Creates a new auxiliary field from a property definition.
virtual ~QgsAuxiliaryStorage()
Destructor.
static bool duplicateTable(const QgsDataSourceUri &uri, const QString &newTable)
Duplicates a table and its content.
QString errorString() const
Returns the underlying error string describing potential errors happening in saveAs().
bool save() const
Saves the current database.
static bool exists(const QgsProject &project)
Returns true if the auxiliary database yet exists for a project, false otherwise.
static bool deleteTable(const QgsDataSourceUri &uri)
Removes a table from the auxiliary storage.
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.
bool isValid() const
Returns the status of the auxiliary storage currently defined.
QString currentFileName() const
Returns the path of the current database used.
QgsAuxiliaryStorage(const QgsProject &project, bool copy=true)
Constructor.
QString fileName() const
Returns the target filename of the database.
static QString extension()
Returns the extension used for auxiliary databases.
void setDataDefinedProperties(const QgsPropertyCollection &collection)
Sets the callout's property collection, used for data defined overrides.
Definition: qgscallout.h:348
static QgsPropertiesDefinition propertyDefinitions()
Returns the definitions for data defined properties available for use in callouts.
Definition: qgscallout.cpp:192
QgsPropertyCollection & dataDefinedProperties()
Returns a reference to the callout's property collection, used for data defined overrides.
Definition: qgscallout.h:330
Property
Data definable properties.
Definition: qgscallout.h:83
Class for storing the component parts of a RDBMS data source URI (e.g.
QString table() const
Returns the table name stored in the URI.
QString uri(bool expandAuthConfig=true) const
Returns the complete URI as a string.
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.
QString database() const
Returns the database name stored in the URI.
void setDatabase(const QString &database)
Sets the URI database name.
Stores the settings for rendering of all diagrams for a layer.
Property
Data definable properties.
static const QgsPropertiesDefinition & propertyDefinitions()
Returns the diagram property definitions.
QgsPropertyCollection & dataDefinedProperties()
Returns a reference to the diagram's property collection, used for data defined overrides.
void setDataDefinedProperties(const QgsPropertyCollection &collection)
Sets the diagram's property collection, used for data defined overrides.
Holder for the widget type and its configuration for a field.
static QString createFieldEqualityExpression(const QString &fieldName, const QVariant &value)
Create an expression allowing to evaluate if a field is equal to a value.
Wrapper for iterator of features from vector data provider or vector layer.
bool nextFeature(QgsFeature &f)
This class wraps a request for features to a vector layer (or directly its vector data provider).
QgsFeatureRequest & setFilterExpression(const QString &expression)
Set the filter expression.
virtual QgsFeatureIds allFeatureIds() const
Returns a list of all feature IDs for features present in the source.
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
Definition: qgsfeature.h:56
QgsGeometry geometry
Definition: qgsfeature.h:67
bool isValid() const
Returns the validity of this feature.
Definition: qgsfeature.cpp:191
QVariant attribute(const QString &name) const
Lookup attribute value by attribute name.
Definition: qgsfeature.cpp:302
void setGeometry(const QgsGeometry &geometry)
Set the feature's geometry.
Definition: qgsfeature.cpp:145
Encapsulate a field in an attribute table or data source.
Definition: qgsfield.h:51
QString typeName() const
Gets the field type.
Definition: qgsfield.cpp:138
QString name
Definition: qgsfield.h:60
void setPrecision(int precision)
Set the field precision.
Definition: qgsfield.cpp:198
void setName(const QString &name)
Set the field name.
Definition: qgsfield.cpp:174
void setLength(int len)
Set the field length.
Definition: qgsfield.cpp:194
QVariant::Type type
Definition: qgsfield.h:58
void setType(QVariant::Type type)
Set variant type.
Definition: qgsfield.cpp:179
void setTypeName(const QString &typeName)
Set the field type.
Definition: qgsfield.cpp:189
Container of fields for a vector layer.
Definition: qgsfields.h:45
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
int indexOf(const QString &fieldName) const
Gets the field index from the field name.
Definition: qgsfields.cpp:207
int count() const
Returns number of items.
Definition: qgsfields.cpp:133
QgsField field(int fieldIdx) const
Returns the field at particular index (must be in range 0..N-1).
Definition: qgsfields.cpp:168
int lookupField(const QString &fieldName) const
Looks up field's index from the field name.
Definition: qgsfields.cpp:344
QString source() const
Returns the source for the layer.
QgsMapLayerType type
Definition: qgsmaplayer.h:77
QgsCoordinateReferenceSystem crs
Definition: qgsmaplayer.h:76
QString id() const
Returns the layer's unique ID, which is used to access this layer from QgsProject.
static QgsVectorLayer * createMemoryLayer(const QString &name, const QgsFields &fields, QgsWkbTypes::Type geometryType=QgsWkbTypes::NoGeometry, const QgsCoordinateReferenceSystem &crs=QgsCoordinateReferenceSystem()) SIP_FACTORY
Creates a new memory layer using the specified parameters.
Contains settings for how a map layer will be labeled.
QgsPropertyCollection & dataDefinedProperties()
Returns a reference to the label's property collection, used for data defined overrides.
QgsCallout * callout() const
Returns the label callout renderer, responsible for drawing label callouts.
Property
Data definable properties.
@ LabelRotation
Label rotation.
@ PositionY
Y-coordinate data defined label position.
@ Strikeout
Use strikeout.
@ FontStyle
Font style name.
@ PositionX
X-coordinate data defined label position.
@ CalloutDraw
Show callout.
@ Underline
Use underline.
@ Bold
Use bold style.
@ MaxScale
Max scale (deprecated, for old project compatibility only)
@ Hali
Horizontal alignment for data defined label position (Left, Center, Right)
@ LabelAllParts
Whether all parts of multi-part features should be labeled.
@ Italic
Use italic style.
@ MinScale
Min scale (deprecated, for old project compatibility only)
@ Family
Font family.
@ Vali
Vertical alignment for data defined label position (Bottom, Base, Half, Cap, Top)
void setDataDefinedProperties(const QgsPropertyCollection &collection)
Sets the label's property collection, used for data defined overrides.
static const QgsPropertiesDefinition & propertyDefinitions()
Returns the labeling property definitions.
Encapsulates a QGIS project, including sets of map layers and their styles, layouts,...
Definition: qgsproject.h:99
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:698
A grouped map of multiple QgsProperty objects, each referenced by a integer key value.
Definition for a property.
Definition: qgsproperty.h:48
StandardPropertyTemplate standardTemplate() const
Returns the property's standard template, if applicable.
Definition: qgsproperty.h:195
QString comment() const
Returns the comment of the property.
Definition: qgsproperty.h:169
DataType dataType() const
Returns the allowable field/value data type for the property.
Definition: qgsproperty.h:189
void setOrigin(const QString &origin)
Sets the origin of the property.
Definition: qgsproperty.h:159
@ ColorNoAlpha
Color with no alpha channel.
Definition: qgsproperty.h:66
@ ColorWithAlpha
Color with alpha channel.
Definition: qgsproperty.h:65
QString name() const
Returns the name of the property.
Definition: qgsproperty.h:140
void setDataType(DataType type)
Sets the data type.
Definition: qgsproperty.h:184
void setName(const QString &name)
Sets the name of the property.
Definition: qgsproperty.h:145
QString origin() const
Returns the origin of the property.
Definition: qgsproperty.h:152
void setComment(const QString &comment)
Sets comment of the property.
Definition: qgsproperty.h:174
@ DataTypeString
Property requires a string value.
Definition: qgsproperty.h:93
@ DataTypeBoolean
Property requires a boolean value.
Definition: qgsproperty.h:107
@ DataTypeNumeric
Property requires a numeric value.
Definition: qgsproperty.h:100
A store for object properties.
Definition: qgsproperty.h:232
static QgsProperty fromField(const QString &fieldName, bool isActive=true)
Returns a new FieldBasedProperty created from the specified field name.
static const QgsPropertiesDefinition & propertyDefinitions()
Returns the symbol layer property definitions.
Defines left outer join from our vector layer to some other vector layer.
QString targetFieldName() const
Returns name of the field of our layer that will be used for join.
Represents a vector layer which manages a vector based data sets.
Q_INVOKABLE QgsWkbTypes::Type wkbType() const FINAL
Returns the WKBType or WKBUnknown in case of error.
Q_INVOKABLE bool startEditing()
Makes the layer editable.
bool addAttribute(const QgsField &field)
Add an attribute field (but does not commit it) returns true if the field was added.
void updateFields()
Will regenerate the fields property of this layer by obtaining all fields from the dataProvider,...
QgsFeatureIterator getFeatures(const QgsFeatureRequest &request=QgsFeatureRequest()) const FINAL
Queries the layer for features specified in request.
QgsFields fields() const FINAL
Returns the list of fields of this layer.
bool deleteFeatures(const QgsFeatureIds &fids, DeleteContext *context=nullptr)
Deletes a set of features from the layer (but does not commit it)
const QgsDiagramLayerSettings * diagramLayerSettings() const
QgsAuxiliaryLayer * auxiliaryLayer()
Returns the current auxiliary layer.
virtual bool deleteAttribute(int attr)
Deletes an attribute field (but does not commit it).
bool isEditable() const FINAL
Returns true if the provider is in editing mode.
void setEditorWidgetSetup(int index, const QgsEditorWidgetSetup &setup)
The editor widget setup defines which QgsFieldFormatter and editor widget will be used for the field ...
Q_INVOKABLE bool commitChanges(bool stopEditing=true)
Attempts to commit to the underlying data provider any buffered changes made since the last to call t...
QgsEditorWidgetSetup editorWidgetSetup(int index) const
The editor widget setup defines which QgsFieldFormatter and editor widget will be used for the field ...
QgsVectorLayer * clone() const override
Returns a new instance equivalent to this one.
QgsAttributeTableConfig attributeTableConfig() const
Returns the attribute table configuration object.
bool addFeature(QgsFeature &feature, QgsFeatureSink::Flags flags=QgsFeatureSink::Flags()) FINAL
Adds a single feature to the sink.
void setAttributeTableConfig(const QgsAttributeTableConfig &attributeTableConfig)
Sets the attribute table configuration object.
void setDiagramLayerSettings(const QgsDiagramLayerSettings &s)
const QgsAbstractVectorLayerLabeling * labeling() const
Access to const labeling configuration.
Unique pointer for spatialite databases, which automatically closes the database when the pointer goe...
int open_v2(const QString &path, int flags, const char *zVfs)
Opens the database at the specified file path.
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
#define AS_JOINFIELD
Q_GLOBAL_STATIC_WITH_ARGS(PalPropertyList, palHiddenProperties,({ QgsPalLayerSettings::PositionX, QgsPalLayerSettings::PositionY, QgsPalLayerSettings::Show, QgsPalLayerSettings::LabelRotation, QgsPalLayerSettings::Family, QgsPalLayerSettings::FontStyle, QgsPalLayerSettings::Size, QgsPalLayerSettings::Bold, QgsPalLayerSettings::Italic, QgsPalLayerSettings::Underline, QgsPalLayerSettings::Color, QgsPalLayerSettings::Strikeout, QgsPalLayerSettings::MultiLineAlignment, QgsPalLayerSettings::BufferSize, QgsPalLayerSettings::BufferDraw, QgsPalLayerSettings::BufferColor, QgsPalLayerSettings::LabelDistance, QgsPalLayerSettings::Hali, QgsPalLayerSettings::Vali, QgsPalLayerSettings::ScaleVisibility, QgsPalLayerSettings::MinScale, QgsPalLayerSettings::MaxScale, QgsPalLayerSettings::AlwaysShow, QgsPalLayerSettings::CalloutDraw, QgsPalLayerSettings::LabelAllParts })) QgsAuxiliaryLayer
QVector< QgsPalLayerSettings::Property > PalPropertyList
#define AS_JOINPREFIX
#define AS_EXTENSION
struct sqlite3 sqlite3
const QgsField & field
Definition: qgsfield.h:463
#define QgsDebugMsg(str)
Definition: qgslogger.h:38
QMap< int, QgsPropertyDefinition > QgsPropertiesDefinition
Definition of available properties.
const QString & typeName
int precision