QGIS API Documentation  3.18.1-Zürich (202f1bf7e5)
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
qgsquickutils.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsquickutils.cpp
3  --------------------------------------
4  Date : Nov 2017
5  Copyright : (C) 2017 by Peter Petrik
6  Email : zilolv at gmail dot com
7  ***************************************************************************
8  * *
9  * This program is free software; you can redistribute it and/or modify *
10  * it under the terms of the GNU General Public License as published by *
11  * the Free Software Foundation; either version 2 of the License, or *
12  * (at your option) any later version. *
13  * *
14  ***************************************************************************/
15 
16 #include <QGuiApplication>
17 #include <QScreen>
18 #include <QString>
19 #include <QWindow>
20 
21 #include "qgis.h"
23 #include "qgscoordinatetransform.h"
24 #include "qgsdistancearea.h"
25 #include "qgslogger.h"
26 #include "qgsvectorlayer.h"
27 #include "qgsfeature.h"
28 #include "qgsapplication.h"
31 
33 #include "qgsquickmapsettings.h"
34 #include "qgsquickutils.h"
35 #include "qgsunittypes.h"
36 
37 
38 QgsQuickUtils::QgsQuickUtils( QObject *parent )
39  : QObject( parent )
40  , mScreenDensity( calculateScreenDensity() )
41 {
42 }
43 
48 {
50 }
51 
52 QgsPointXY QgsQuickUtils::pointXY( double x, double y )
53 {
54  return QgsPointXY( x, y );
55 }
56 
57 QgsPoint QgsQuickUtils::point( double x, double y, double z, double m )
58 {
59  return QgsPoint( x, y, z, m );
60 }
61 
62 QgsPoint QgsQuickUtils::coordinateToPoint( const QGeoCoordinate &coor )
63 {
64  return QgsPoint( coor.longitude(), coor.latitude(), coor.altitude() );
65 }
66 
68  const QgsCoordinateReferenceSystem &destCrs,
69  const QgsCoordinateTransformContext &context,
70  const QgsPointXY &srcPoint )
71 {
72  try
73  {
74  QgsCoordinateTransform ct( srcCrs, destCrs, context );
75  if ( ct.isValid() )
76  {
77  const QgsPointXY pt = ct.transform( srcPoint );
78  return pt;
79  }
80  }
81  catch ( QgsCsException &cse )
82  {
83  Q_UNUSED( cse )
84  }
85  return srcPoint;
86 }
87 
88 double QgsQuickUtils::screenUnitsToMeters( QgsQuickMapSettings *mapSettings, int baseLengthPixels )
89 {
90  if ( mapSettings == nullptr ) return 0.0;
91 
92  QgsDistanceArea mDistanceArea;
93  mDistanceArea.setEllipsoid( QStringLiteral( "WGS84" ) );
94  mDistanceArea.setSourceCrs( mapSettings->destinationCrs(), mapSettings->transformContext() );
95 
96  // calculate the geographic distance from the central point of extent
97  // to the specified number of points on the right side
98  QSize s = mapSettings->outputSize();
99  QPoint pointCenter( s.width() / 2, s.height() / 2 );
100  QgsPointXY p1 = mapSettings->screenToCoordinate( pointCenter );
101  QgsPointXY p2 = mapSettings->screenToCoordinate( pointCenter + QPoint( baseLengthPixels, 0 ) );
102  return mDistanceArea.measureLine( p1, p2 );
103 }
104 
105 bool QgsQuickUtils::fileExists( const QString &path )
106 {
107  QFileInfo check_file( path );
108  // check if file exists and if yes: Is it really a file and no directory?
109  return ( check_file.exists() && check_file.isFile() );
110 }
111 
112 QString QgsQuickUtils::getRelativePath( const QString &path, const QString &prefixPath )
113 {
114  QString modPath = path;
115  QString filePrefix( "file://" );
116 
117  if ( path.startsWith( filePrefix ) )
118  {
119  modPath = modPath.replace( filePrefix, QString() );
120  }
121 
122  if ( prefixPath.isEmpty() ) return modPath;
123 
124  // Do not use a canonical path for non-existing path
125  if ( !QFileInfo( path ).exists() )
126  {
127  if ( !prefixPath.isEmpty() && modPath.startsWith( prefixPath ) )
128  {
129  return modPath.replace( prefixPath, QString() );
130  }
131  }
132  else
133  {
134  QDir absoluteDir( modPath );
135  QDir prefixDir( prefixPath );
136  QString canonicalPath = absoluteDir.canonicalPath();
137  QString prefixCanonicalPath = prefixDir.canonicalPath() + "/";
138 
139  if ( prefixCanonicalPath.length() > 1 && canonicalPath.startsWith( prefixCanonicalPath ) )
140  {
141  return canonicalPath.replace( prefixCanonicalPath, QString() );
142  }
143  }
144 
145  return QString();
146 }
147 
148 void QgsQuickUtils::logMessage( const QString &message, const QString &tag, Qgis::MessageLevel level )
149 {
150  QgsMessageLog::logMessage( message, tag, level );
151 }
152 
154 {
155  return QgsQuickFeatureLayerPair( feature, layer );
156 }
157 
158 const QUrl QgsQuickUtils::getThemeIcon( const QString &name )
159 {
160  QString path = QStringLiteral( "qrc:/%1.svg" ).arg( name );
161  QgsDebugMsg( QStringLiteral( "Using icon %1 from %2" ).arg( name, path ) );
162  return QUrl( path );
163 }
164 
165 const QUrl QgsQuickUtils::getEditorComponentSource( const QString &widgetName )
166 {
167  QString path( "qgsquick%1.qml" );
168  QStringList supportedWidgets = { QStringLiteral( "textedit" ),
169  QStringLiteral( "valuemap" ),
170  QStringLiteral( "valuerelation" ),
171  QStringLiteral( "checkbox" ),
172  QStringLiteral( "externalresource" ),
173  QStringLiteral( "datetime" ),
174  QStringLiteral( "range" )
175  };
176  if ( supportedWidgets.contains( widgetName ) )
177  {
178  return QUrl( path.arg( widgetName ) );
179  }
180  else
181  {
182  return QUrl( path.arg( QLatin1String( "textedit" ) ) );
183  }
184 }
185 
187  const QgsPoint &point,
189  int decimals,
190  QgsCoordinateFormatter::FormatFlags flags )
191 {
192  return QgsCoordinateFormatter::format( point, format, decimals, flags );
193 }
194 
195 QString QgsQuickUtils::formatDistance( double distance,
197  int decimals,
199 {
200  double destDistance;
201  QgsUnitTypes::DistanceUnit destUnits;
202 
203  humanReadableDistance( distance, units, destSystem, destDistance, destUnits );
204 
205  return QStringLiteral( "%1 %2" )
206  .arg( QString::number( destDistance, 'f', decimals ) )
207  .arg( QgsUnitTypes::toAbbreviatedString( destUnits ) );
208 }
209 
210 bool QgsQuickUtils::removeFile( const QString &filePath )
211 {
212  QFile file( filePath );
213  return file.remove( filePath );
214 }
215 
216 
219  double &destDistance, QgsUnitTypes::DistanceUnit &destUnits )
220 {
221  if ( ( destSystem == QgsUnitTypes::MetricSystem ) || ( destSystem == QgsUnitTypes::UnknownSystem ) )
222  {
223  return formatToMetricDistance( srcDistance, srcUnits, destDistance, destUnits );
224  }
225  else if ( destSystem == QgsUnitTypes::ImperialSystem )
226  {
227  return formatToImperialDistance( srcDistance, srcUnits, destDistance, destUnits );
228  }
229  else if ( destSystem == QgsUnitTypes::USCSSystem )
230  {
231  return formatToUSCSDistance( srcDistance, srcUnits, destDistance, destUnits );
232  }
233  else
234  {
235  Q_ASSERT( false ); //should never happen
236  }
237 }
238 
239 void QgsQuickUtils::formatToMetricDistance( double srcDistance,
241  double &destDistance,
242  QgsUnitTypes::DistanceUnit &destUnits )
243 {
244  double dist = srcDistance * QgsUnitTypes::fromUnitToUnitFactor( srcUnits, QgsUnitTypes::DistanceMillimeters );
245  if ( dist < 0 )
246  {
247  destDistance = 0;
249  return;
250  }
251 
253  if ( dist > mmToKm )
254  {
255  destDistance = dist / mmToKm;
257  return;
258  }
259 
261  if ( dist > mmToM )
262  {
263  destDistance = dist / mmToM;
264  destUnits = QgsUnitTypes::DistanceMeters;
265  return;
266  }
267 
269  if ( dist > mmToCm )
270  {
271  destDistance = dist / mmToCm;
273  return;
274  }
275 
276  destDistance = dist;
278 }
279 
280 void QgsQuickUtils::formatToImperialDistance( double srcDistance,
282  double &destDistance,
283  QgsUnitTypes::DistanceUnit &destUnits )
284 {
285  double dist = srcDistance * QgsUnitTypes::fromUnitToUnitFactor( srcUnits, QgsUnitTypes::DistanceFeet );
286  if ( dist < 0 )
287  {
288  destDistance = 0;
289  destUnits = QgsUnitTypes::DistanceFeet;
290  return;
291  }
292 
294  if ( dist > feetToMile )
295  {
296  destDistance = dist / feetToMile;
297  destUnits = QgsUnitTypes::DistanceMiles;
298  return;
299  }
300 
302  if ( dist > feetToYard )
303  {
304  destDistance = dist / feetToYard;
305  destUnits = QgsUnitTypes::DistanceYards;
306  return;
307  }
308 
309  destDistance = dist;
310  destUnits = QgsUnitTypes::DistanceFeet;
311  return;
312 }
313 
314 void QgsQuickUtils::formatToUSCSDistance( double srcDistance,
316  double &destDistance,
317  QgsUnitTypes::DistanceUnit &destUnits )
318 {
319  double dist = srcDistance * QgsUnitTypes::fromUnitToUnitFactor( srcUnits, QgsUnitTypes::DistanceFeet );
320  if ( dist < 0 )
321  {
322  destDistance = 0;
323  destUnits = QgsUnitTypes::DistanceFeet;
324  return;
325  }
326 
328  if ( dist > feetToMile )
329  {
330  destDistance = dist / feetToMile;
332  return;
333  }
334 
336  if ( dist > feetToYard )
337  {
338  destDistance = dist / feetToYard;
339  destUnits = QgsUnitTypes::DistanceYards;
340  return;
341  }
342 
343  destDistance = dist;
344  destUnits = QgsUnitTypes::DistanceFeet;
345  return;
346 }
347 
349 {
350  // take the first top level window
351  QScreen *screen = QGuiApplication::topLevelWindows().at( 0 )->screen();
352  double dpiX = screen->physicalDotsPerInchX();
353  double dpiY = screen->physicalDotsPerInchY();
354  int height = screen->geometry().height();
355  int width = screen->geometry().width();
356  double sizeX = static_cast<double>( width ) / dpiX * 25.4;
357  double sizeY = static_cast<double>( height ) / dpiY * 25.4;
358 
359  QString msg;
360  msg += tr( "screen resolution: %1x%2 px\n" ).arg( width ).arg( height );
361  msg += tr( "screen DPI: %1x%2\n" ).arg( dpiX ).arg( dpiY );
362  msg += tr( "screen size: %1x%2 mm\n" ).arg( QString::number( sizeX, 'f', 0 ), QString::number( sizeY, 'f', 0 ) );
363  msg += tr( "screen density: %1" ).arg( mScreenDensity );
364  return msg;
365 }
366 
367 QVariantMap QgsQuickUtils::createValueRelationCache( const QVariantMap &config, const QgsFeature &formFeature )
368 {
369  QVariantMap valueMap;
371 
372  for ( const QgsValueRelationFieldFormatter::ValueRelationItem &item : qgis::as_const( cache ) )
373  {
374  valueMap.insert( item.key.toString(), item.value );
375  }
376  return valueMap;
377 }
378 
379 QString QgsQuickUtils::evaluateExpression( const QgsQuickFeatureLayerPair &pair, QgsProject *activeProject, const QString &expression )
380 {
381  QList<QgsExpressionContextScope *> scopes;
383  scopes << QgsExpressionContextUtils::projectScope( activeProject );
384  scopes << QgsExpressionContextUtils::layerScope( pair.layer() );
385 
386  QgsExpressionContext context( scopes );
387  context.setFeature( pair.feature() );
388  QgsExpression expr( expression );
389  return expr.evaluate( &context ).toString();
390 }
391 
393 {
394  QgsFeatureIds qgsFids;
395  for ( const int &fid : fids )
396  qgsFids << fid;
397  layer->selectByIds( qgsFids, behavior );
398 }
399 
401 {
402  return QVariant( field.type() ).typeName();
403 }
404 
405 QString QgsQuickUtils::dateTimeFieldFormat( const QString &fieldFormat )
406 {
407  if ( QgsDateTimeFieldFormatter::DATE_FORMAT == fieldFormat )
408  {
409  return QString( "Date" );
410  }
411  else if ( QgsDateTimeFieldFormatter::TIME_FORMAT == fieldFormat )
412  {
413  return QString( "Time" );
414  }
415  else if ( QgsDateTimeFieldFormatter::DATETIME_FORMAT == fieldFormat )
416  {
417  return QString( "Date Time" );
418  }
419  else
420  {
421  return QString( "Date Time" );
422  }
423 }
424 
426 {
427  return QModelIndex();
428 }
429 
431 {
432  return mScreenDensity;
433 }
434 qreal QgsQuickUtils::calculateScreenDensity()
435 {
436  // calculate screen density for calculation of real pixel sizes from density-independent pixels
437  // take the first top level window
438  QScreen *screen = QGuiApplication::topLevelWindows().at( 0 )->screen();
439  double dpiX = screen->physicalDotsPerInchX();
440  double dpiY = screen->physicalDotsPerInchY();
441  double dpi = dpiX < dpiY ? dpiX : dpiY; // In case of asymmetrical DPI. Improbable
442  return dpi / 160.; // 160 DPI is baseline for density-independent pixels in Android
443 }
MessageLevel
Level for messages This will be used both for message log and message bar in application.
Definition: qgis.h:89
Format
Available formats for displaying coordinates.
static QString format(const QgsPointXY &point, Format format, int precision=12, FormatFlags flags=FlagDegreesUseStringSuffix)
Formats a point according to the specified parameters.
This class represents a coordinate reference system (CRS).
static Q_INVOKABLE QgsCoordinateReferenceSystem fromEpsgId(long epsg)
Creates a CRS from a given EPSG ID.
Contains information about the context in which a coordinate transform is executed.
Class for doing transforms between two map coordinate systems.
QgsPointXY transform(const QgsPointXY &point, TransformDirection direction=ForwardTransform) const SIP_THROW(QgsCsException)
Transform the point from the source CRS to the destination CRS.
bool isValid() const
Returns true if the coordinate transform is valid, ie both the source and destination CRS have been s...
Custom exception class for Coordinate Reference System related exceptions.
Definition: qgsexception.h:66
static const QString DATETIME_FORMAT
A general purpose distance and area calculator, capable of performing ellipsoid based calculations.
double measureLine(const QVector< QgsPointXY > &points) const
Measures the length of a line with multiple segments.
void setSourceCrs(const QgsCoordinateReferenceSystem &crs, const QgsCoordinateTransformContext &context)
Sets source spatial reference system crs.
bool setEllipsoid(const QString &ellipsoid)
Sets the ellipsoid by its acronym.
static QgsExpressionContextScope * projectScope(const QgsProject *project)
Creates a new scope which contains variables and functions relating to a QGIS project.
static QgsExpressionContextScope * layerScope(const QgsMapLayer *layer)
Creates a new scope which contains variables and functions relating to a QgsMapLayer.
static QgsExpressionContextScope * globalScope()
Creates a new scope which contains variables and functions relating to the global QGIS context.
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
void setFeature(const QgsFeature &feature)
Convenience function for setting a feature for the context.
Class for parsing and evaluation of expressions (formerly called "search strings").
QVariant evaluate()
Evaluate the feature and return the result.
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
Definition: qgsfeature.h:56
Encapsulate a field in an attribute table or data source.
Definition: qgsfield.h:51
QVariant::Type type
Definition: qgsfield.h:58
static void logMessage(const QString &message, const QString &tag=QString(), Qgis::MessageLevel level=Qgis::Warning, bool notifyUser=true)
Adds a message to the log instance (and creates it if necessary).
A class to represent a 2D point.
Definition: qgspointxy.h:44
Point geometry type, with support for z-dimension and m-values.
Definition: qgspoint.h:38
Encapsulates a QGIS project, including sets of map layers and their styles, layouts,...
Definition: qgsproject.h:99
Pair of QgsFeature and QgsVectorLayer.
QgsFeature feature
Feature that belongs to layer.
Q_GADGET QgsVectorLayer * layer
Vector layer to which the feature belongs.
The QgsQuickMapSettings class encapsulates QgsMapSettings class to offer settings of configuration of...
Q_INVOKABLE QgsCoordinateTransformContext transformContext() const
Returns the coordinate transform context, which stores various information regarding which datum tran...
Q_INVOKABLE QgsPoint screenToCoordinate(const QPointF &point) const
Convert a screen coordinate to a map coordinate.
QgsCoordinateReferenceSystem destinationCrs
CRS of destination coordinate reference system.
QSize outputSize
The size of the resulting map image.
static Q_INVOKABLE double screenUnitsToMeters(QgsQuickMapSettings *mapSettings, int baseLengthPixels)
Calculates the distance in meter representing baseLengthPixels pixels on the screen based on the curr...
static Q_INVOKABLE void selectFeaturesInLayer(QgsVectorLayer *layer, const QList< int > &fids, QgsVectorLayer::SelectBehavior behavior=QgsVectorLayer::SetSelection)
Selects features in a layer This method is required since QML cannot perform the conversion of a feat...
static Q_INVOKABLE QgsPointXY transformPoint(const QgsCoordinateReferenceSystem &srcCrs, const QgsCoordinateReferenceSystem &destCrs, const QgsCoordinateTransformContext &context, const QgsPointXY &srcPoint)
Transforms point between different crs from QML.
static Q_INVOKABLE bool removeFile(const QString &filePath)
Deletes file from a given path.
static Q_INVOKABLE QString fieldType(const QgsField &field)
Returns the QVariant typeName of a field.
static Q_INVOKABLE QString formatDistance(double distance, QgsUnitTypes::DistanceUnit units, int decimals, QgsUnitTypes::SystemOfMeasurement destSystem=QgsUnitTypes::MetricSystem)
Converts distance to human readable distance.
static void humanReadableDistance(double srcDistance, QgsUnitTypes::DistanceUnit srcUnits, QgsUnitTypes::SystemOfMeasurement destSystem, double &destDistance, QgsUnitTypes::DistanceUnit &destUnits)
Converts distance to human readable distance in destination system of measurement.
QString dumpScreenInfo() const
Returns a string with information about screen size and resolution - useful for debugging.
static Q_INVOKABLE QString evaluateExpression(const QgsQuickFeatureLayerPair &pair, QgsProject *activeProject, const QString &expression)
Evaluates expression.
static Q_INVOKABLE void logMessage(const QString &message, const QString &tag=QString("QgsQuick"), Qgis::MessageLevel level=Qgis::Warning)
Log message in QgsMessageLog.
static Q_INVOKABLE QgsCoordinateReferenceSystem coordinateReferenceSystemFromEpsgId(long epsg)
Creates crs from epsg code in QML.
static Q_INVOKABLE const QUrl getThemeIcon(const QString &name)
Returns QUrl to image from library's /images folder.
static Q_INVOKABLE bool fileExists(const QString &path)
Returns whether file on path exists.
static Q_INVOKABLE QgsPoint coordinateToPoint(const QGeoCoordinate &coor)
Converts QGeoCoordinate to QgsPoint.
static Q_INVOKABLE QgsPoint point(double x, double y, double z=std::numeric_limits< double >::quiet_NaN(), double m=std::numeric_limits< double >::quiet_NaN())
Creates QgsPoint in QML.
qreal screenDensity() const
"dp" is useful for building building components that work well with different screen densities.
static Q_INVOKABLE QString getRelativePath(const QString &path, const QString &prefixPath)
Returns relative path of the file to given prefixPath.
static Q_INVOKABLE const QUrl getEditorComponentSource(const QString &widgetName)
Returns url to field editor component for a feature form.
static Q_INVOKABLE QString formatPoint(const QgsPoint &point, QgsCoordinateFormatter::Format format=QgsCoordinateFormatter::FormatPair, int decimals=3, QgsCoordinateFormatter::FormatFlags flags=QgsCoordinateFormatter::FlagDegreesUseStringSuffix)
Formats a point according to the specified parameters.
QgsQuickUtils(QObject *parent=nullptr)
Create new utilities.
static Q_INVOKABLE QString dateTimeFieldFormat(const QString &fieldFormat)
Returns field format's name for given string representing field format defined in QgsDateTimeFieldFor...
static Q_INVOKABLE QVariantMap createValueRelationCache(const QVariantMap &config, const QgsFeature &formFeature=QgsFeature())
Creates a cache for a value relation field.
static Q_INVOKABLE QModelIndex invalidIndex()
invalidIndex returns invalid index
static Q_INVOKABLE QgsPointXY pointXY(double x, double y)
Creates QgsPointXY in QML.
static Q_INVOKABLE QgsQuickFeatureLayerPair featureFactory(const QgsFeature &feature, QgsVectorLayer *layer=nullptr)
QgsQuickFeatureLayerPair factory for tuple of QgsFeature and QgsVectorLayer used in QgsQUick library.
DistanceUnit
Units of distance.
Definition: qgsunittypes.h:68
@ DistanceMeters
Meters.
Definition: qgsunittypes.h:69
@ DistanceKilometers
Kilometers.
Definition: qgsunittypes.h:70
@ DistanceMiles
Terrestrial miles.
Definition: qgsunittypes.h:74
@ DistanceMillimeters
Millimeters.
Definition: qgsunittypes.h:77
@ DistanceYards
Imperial yards.
Definition: qgsunittypes.h:73
@ DistanceFeet
Imperial feet.
Definition: qgsunittypes.h:71
@ DistanceNauticalMiles
Nautical miles.
Definition: qgsunittypes.h:72
@ DistanceCentimeters
Centimeters.
Definition: qgsunittypes.h:76
SystemOfMeasurement
Systems of unit measurement.
Definition: qgsunittypes.h:45
@ MetricSystem
International System of Units (SI)
Definition: qgsunittypes.h:47
@ UnknownSystem
Unknown system of measurement.
Definition: qgsunittypes.h:46
@ ImperialSystem
British Imperial.
Definition: qgsunittypes.h:48
@ USCSSystem
United States customary system.
Definition: qgsunittypes.h:49
static Q_INVOKABLE double fromUnitToUnitFactor(QgsUnitTypes::DistanceUnit fromUnit, QgsUnitTypes::DistanceUnit toUnit)
Returns the conversion factor between the specified distance units.
static Q_INVOKABLE QString toAbbreviatedString(QgsUnitTypes::DistanceUnit unit)
Returns a translated abbreviation representing a distance unit.
QVariant createCache(QgsVectorLayer *layer, int fieldIndex, const QVariantMap &config) const override
Create a cache for a given field.
QVector< QgsValueRelationFieldFormatter::ValueRelationItem > ValueRelationCache
Represents a vector layer which manages a vector based data sets.
SelectBehavior
Selection behavior.
Q_INVOKABLE void selectByIds(const QgsFeatureIds &ids, QgsVectorLayer::SelectBehavior behavior=QgsVectorLayer::SetSelection)
Selects matching features using a list of feature IDs.
QSet< QgsFeatureId > QgsFeatureIds
Definition: qgsfeatureid.h:37
const QgsField & field
Definition: qgsfield.h:472
#define QgsDebugMsg(str)
Definition: qgslogger.h:38