QGIS API Documentation  3.10.0-A Coruña (6c816b4204)
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 <QApplication>
17 #include <QDesktopWidget>
18 #include <QString>
19 
20 #include "qgis.h"
22 #include "qgscoordinatetransform.h"
23 #include "qgsdistancearea.h"
24 #include "qgslogger.h"
25 #include "qgsvectorlayer.h"
26 #include "qgsfeature.h"
27 #include "qgsapplication.h"
29 
31 #include "qgsquickmapsettings.h"
32 #include "qgsquickutils.h"
33 #include "qgsunittypes.h"
34 
35 
36 QgsQuickUtils::QgsQuickUtils( QObject *parent )
37  : QObject( parent )
38  , mScreenDensity( calculateScreenDensity() )
39 {
40 }
41 
46 {
48 }
49 
50 QgsPointXY QgsQuickUtils::pointXY( double x, double y )
51 {
52  return QgsPointXY( x, y );
53 }
54 
55 QgsPoint QgsQuickUtils::point( double x, double y, double z, double m )
56 {
57  return QgsPoint( x, y, z, m );
58 }
59 
60 QgsPoint QgsQuickUtils::coordinateToPoint( const QGeoCoordinate &coor )
61 {
62  return QgsPoint( coor.longitude(), coor.latitude(), coor.altitude() );
63 }
64 
66  const QgsCoordinateReferenceSystem &destCrs,
67  const QgsCoordinateTransformContext &context,
68  const QgsPointXY &srcPoint )
69 {
70  QgsCoordinateTransform mTransform( srcCrs, destCrs, context );
71  QgsPointXY pt = mTransform.transform( srcPoint );
72  return pt;
73 }
74 
75 double QgsQuickUtils::screenUnitsToMeters( QgsQuickMapSettings *mapSettings, int baseLengthPixels )
76 {
77  if ( mapSettings == nullptr ) return 0.0;
78 
79  QgsDistanceArea mDistanceArea;
80  mDistanceArea.setEllipsoid( QStringLiteral( "WGS84" ) );
81  mDistanceArea.setSourceCrs( mapSettings->destinationCrs(), mapSettings->transformContext() );
82 
83  // calculate the geographic distance from the central point of extent
84  // to the specified number of points on the right side
85  QSize s = mapSettings->outputSize();
86  QPoint pointCenter( s.width() / 2, s.height() / 2 );
87  QgsPointXY p1 = mapSettings->screenToCoordinate( pointCenter );
88  QgsPointXY p2 = mapSettings->screenToCoordinate( pointCenter + QPoint( baseLengthPixels, 0 ) );
89  return mDistanceArea.measureLine( p1, p2 );
90 }
91 
92 bool QgsQuickUtils::fileExists( const QString &path )
93 {
94  QFileInfo check_file( path );
95  // check if file exists and if yes: Is it really a file and no directory?
96  return ( check_file.exists() && check_file.isFile() );
97 }
98 
99 QString QgsQuickUtils::getRelativePath( const QString &path, const QString &prefixPath )
100 {
101  QString modPath = path;
102  QString filePrefix( "file://" );
103 
104  if ( path.startsWith( filePrefix ) )
105  {
106  modPath = modPath.replace( filePrefix, QString() );
107  }
108 
109  if ( prefixPath.isEmpty() ) return modPath;
110 
111  // Do not use a canonical path for non-existing path
112  if ( !QFileInfo( path ).exists() )
113  {
114  if ( !prefixPath.isEmpty() && modPath.startsWith( prefixPath ) )
115  {
116  return modPath.replace( prefixPath, QString() );
117  }
118  }
119  else
120  {
121  QDir absoluteDir( modPath );
122  QDir prefixDir( prefixPath );
123  QString canonicalPath = absoluteDir.canonicalPath();
124  QString prefixCanonicalPath = prefixDir.canonicalPath() + "/";
125 
126  if ( prefixCanonicalPath.length() > 1 && canonicalPath.startsWith( prefixCanonicalPath ) )
127  {
128  return canonicalPath.replace( prefixCanonicalPath, QString() );
129  }
130  }
131 
132  return QString();
133 }
134 
135 void QgsQuickUtils::logMessage( const QString &message, const QString &tag, Qgis::MessageLevel level )
136 {
137  QgsMessageLog::logMessage( message, tag, level );
138 }
139 
141 {
142  return QgsQuickFeatureLayerPair( feature, layer );
143 }
144 
145 const QUrl QgsQuickUtils::getThemeIcon( const QString &name )
146 {
147  QString path = QStringLiteral( "qrc:/%1.svg" ).arg( name );
148  QgsDebugMsg( QStringLiteral( "Using icon %1 from %2" ).arg( name, path ) );
149  return QUrl( path );
150 }
151 
152 const QUrl QgsQuickUtils::getEditorComponentSource( const QString &widgetName )
153 {
154  QString path( "qgsquick%1.qml" );
155  QStringList supportedWidgets = { QStringLiteral( "textedit" ),
156  QStringLiteral( "valuemap" ),
157  QStringLiteral( "valuerelation" ),
158  QStringLiteral( "checkbox" ),
159  QStringLiteral( "externalresource" ),
160  QStringLiteral( "datetime" ),
161  QStringLiteral( "range" )
162  };
163  if ( supportedWidgets.contains( widgetName ) )
164  {
165  return QUrl( path.arg( widgetName ) );
166  }
167  else
168  {
169  return QUrl( path.arg( QStringLiteral( "textedit" ) ) );
170  }
171 }
172 
174  const QgsPoint &point,
176  int decimals,
177  QgsCoordinateFormatter::FormatFlags flags )
178 {
179  return QgsCoordinateFormatter::format( point, format, decimals, flags );
180 }
181 
182 QString QgsQuickUtils::formatDistance( double distance,
184  int decimals,
186 {
187  double destDistance;
188  QgsUnitTypes::DistanceUnit destUnits;
189 
190  humanReadableDistance( distance, units, destSystem, destDistance, destUnits );
191 
192  return QStringLiteral( "%1 %2" )
193  .arg( QString::number( destDistance, 'f', decimals ) )
194  .arg( QgsUnitTypes::toAbbreviatedString( destUnits ) );
195 }
196 
197 bool QgsQuickUtils::removeFile( const QString &filePath )
198 {
199  QFile file( filePath );
200  return file.remove( filePath );
201 }
202 
203 
206  double &destDistance, QgsUnitTypes::DistanceUnit &destUnits )
207 {
208  if ( ( destSystem == QgsUnitTypes::MetricSystem ) || ( destSystem == QgsUnitTypes::UnknownSystem ) )
209  {
210  return formatToMetricDistance( srcDistance, srcUnits, destDistance, destUnits );
211  }
212  else if ( destSystem == QgsUnitTypes::ImperialSystem )
213  {
214  return formatToImperialDistance( srcDistance, srcUnits, destDistance, destUnits );
215  }
216  else if ( destSystem == QgsUnitTypes::USCSSystem )
217  {
218  return formatToUSCSDistance( srcDistance, srcUnits, destDistance, destUnits );
219  }
220  else
221  {
222  Q_ASSERT( false ); //should never happen
223  }
224 }
225 
226 void QgsQuickUtils::formatToMetricDistance( double srcDistance,
228  double &destDistance,
229  QgsUnitTypes::DistanceUnit &destUnits )
230 {
231  double dist = srcDistance * QgsUnitTypes::fromUnitToUnitFactor( srcUnits, QgsUnitTypes::DistanceMillimeters );
232  if ( dist < 0 )
233  {
234  destDistance = 0;
236  return;
237  }
238 
240  if ( dist > mmToKm )
241  {
242  destDistance = dist / mmToKm;
244  return;
245  }
246 
248  if ( dist > mmToM )
249  {
250  destDistance = dist / mmToM;
251  destUnits = QgsUnitTypes::DistanceMeters;
252  return;
253  }
254 
256  if ( dist > mmToCm )
257  {
258  destDistance = dist / mmToCm;
260  return;
261  }
262 
263  destDistance = dist;
265 }
266 
267 void QgsQuickUtils::formatToImperialDistance( double srcDistance,
269  double &destDistance,
270  QgsUnitTypes::DistanceUnit &destUnits )
271 {
272  double dist = srcDistance * QgsUnitTypes::fromUnitToUnitFactor( srcUnits, QgsUnitTypes::DistanceFeet );
273  if ( dist < 0 )
274  {
275  destDistance = 0;
276  destUnits = QgsUnitTypes::DistanceFeet;
277  return;
278  }
279 
281  if ( dist > feetToMile )
282  {
283  destDistance = dist / feetToMile;
284  destUnits = QgsUnitTypes::DistanceMiles;
285  return;
286  }
287 
289  if ( dist > feetToYard )
290  {
291  destDistance = dist / feetToYard;
292  destUnits = QgsUnitTypes::DistanceYards;
293  return;
294  }
295 
296  destDistance = dist;
297  destUnits = QgsUnitTypes::DistanceFeet;
298  return;
299 }
300 
301 void QgsQuickUtils::formatToUSCSDistance( double srcDistance,
303  double &destDistance,
304  QgsUnitTypes::DistanceUnit &destUnits )
305 {
306  double dist = srcDistance * QgsUnitTypes::fromUnitToUnitFactor( srcUnits, QgsUnitTypes::DistanceFeet );
307  if ( dist < 0 )
308  {
309  destDistance = 0;
310  destUnits = QgsUnitTypes::DistanceFeet;
311  return;
312  }
313 
315  if ( dist > feetToMile )
316  {
317  destDistance = dist / feetToMile;
319  return;
320  }
321 
323  if ( dist > feetToYard )
324  {
325  destDistance = dist / feetToYard;
326  destUnits = QgsUnitTypes::DistanceYards;
327  return;
328  }
329 
330  destDistance = dist;
331  destUnits = QgsUnitTypes::DistanceFeet;
332  return;
333 }
334 
336 {
337  QRect rec = QApplication::desktop()->screenGeometry();
338  int dpiX = QApplication::desktop()->physicalDpiX();
339  int dpiY = QApplication::desktop()->physicalDpiY();
340  int height = rec.height();
341  int width = rec.width();
342  double sizeX = static_cast<double>( width ) / dpiX * 25.4;
343  double sizeY = static_cast<double>( height ) / dpiY * 25.4;
344 
345  QString msg;
346  msg += tr( "screen resolution: %1x%2 px\n" ).arg( width ).arg( height );
347  msg += tr( "screen DPI: %1x%2\n" ).arg( dpiX ).arg( dpiY );
348  msg += tr( "screen size: %1x%2 mm\n" ).arg( QString::number( sizeX, 'f', 0 ), QString::number( sizeY, 'f', 0 ) );
349  msg += tr( "screen density: %1" ).arg( mScreenDensity );
350  return msg;
351 }
352 
353 QVariantMap QgsQuickUtils::createValueRelationCache( const QVariantMap &config, const QgsFeature &formFeature )
354 {
355  QVariantMap valueMap;
357 
358  for ( const QgsValueRelationFieldFormatter::ValueRelationItem &item : qgis::as_const( cache ) )
359  {
360  valueMap.insert( item.key.toString(), item.value );
361  }
362  return valueMap;
363 }
364 
365 QString QgsQuickUtils::evaluateExpression( const QgsQuickFeatureLayerPair &pair, QgsProject *activeProject, const QString &expression )
366 {
367  QList<QgsExpressionContextScope *> scopes;
369  scopes << QgsExpressionContextUtils::projectScope( activeProject );
370  scopes << QgsExpressionContextUtils::layerScope( pair.layer() );
371 
372  QgsExpressionContext context( scopes );
373  context.setFeature( pair.feature() );
374  QgsExpression expr( expression );
375  return expr.evaluate( &context ).toString();
376 }
377 
379 {
380  return mScreenDensity;
381 }
382 
383 qreal QgsQuickUtils::calculateScreenDensity()
384 {
385  // calculate screen density for calculation of real pixel sizes from density-independent pixels
386  int dpiX = QApplication::desktop()->physicalDpiX();
387  int dpiY = QApplication::desktop()->physicalDpiY();
388  int dpi = dpiX < dpiY ? dpiX : dpiY; // In case of asymmetrical DPI. Improbable
389  return dpi / 160.; // 160 DPI is baseline for density-independent pixels in Android
390 }
Class for parsing and evaluation of expressions (formerly called "search strings").
static Q_INVOKABLE const QUrl getEditorComponentSource(const QString &widgetName)
Returns url to field editor component for a feature form.
static Q_INVOKABLE QgsPoint coordinateToPoint(const QGeoCoordinate &coor)
Converts QGeoCoordinate to QgsPoint.
SystemOfMeasurement
Systems of unit measurement.
Definition: qgsunittypes.h:44
static Q_INVOKABLE QgsCoordinateReferenceSystem coordinateReferenceSystemFromEpsgId(long epsg)
Creates crs from epsg code in QML.
#define QgsDebugMsg(str)
Definition: qgslogger.h:38
QgsPointXY transform(const QgsPointXY &point, TransformDirection direction=ForwardTransform) const SIP_THROW(QgsCsException)
Transform the point from the source CRS to the destination CRS.
A class to represent a 2D point.
Definition: qgspointxy.h:43
QVariant evaluate()
Evaluate the feature and return the result.
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.
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.
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
Definition: qgsfeature.h:55
MessageLevel
Level for messages This will be used both for message log and message bar in application.
Definition: qgis.h:67
The QgsQuickMapSettings class encapsulates QgsMapSettings class to offer settings of configuration of...
static Q_INVOKABLE double screenUnitsToMeters(QgsQuickMapSettings *mapSettings, int baseLengthPixels)
Calculates the distance in meter representing baseLengthPixels pixels on the screen based on the curr...
Format
Available formats for displaying coordinates.
QVector< QgsValueRelationFieldFormatter::ValueRelationItem > ValueRelationCache
static Q_INVOKABLE QString getRelativePath(const QString &path, const QString &prefixPath)
Returns relative path of the file to given prefixPath.
British Imperial.
Definition: qgsunittypes.h:48
qreal screenDensity() const
"dp" is useful for building building components that work well with different screen densities...
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 QgsCoordinateReferenceSystem fromEpsgId(long epsg)
Creates a CRS from a given EPSG ID.
Q_INVOKABLE QgsPoint screenToCoordinate(const QPointF &point) const
Convert a screen coordinate to a map coordinate.
static Q_INVOKABLE QString toAbbreviatedString(QgsUnitTypes::DistanceUnit unit)
Returns a translated abbreviation representing a distance unit.
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...
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).
Unknown system of measurement.
Definition: qgsunittypes.h:46
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.
Encapsulates a QGIS project, including sets of map layers and their styles, layouts, annotations, canvases, etc.
Definition: qgsproject.h:89
International System of Units (SI)
Definition: qgsunittypes.h:47
Contains information about the context in which a coordinate transform is executed.
static Q_INVOKABLE const QUrl getThemeIcon(const QString &name)
Returns QUrl to image from library&#39;s /images folder.
QgsQuickUtils(QObject *parent=nullptr)
Create new utilities.
Point geometry type, with support for z-dimension and m-values.
Definition: qgspoint.h:37
QVariant createCache(QgsVectorLayer *layer, int fieldIndex, const QVariantMap &config) const override
Create a cache for a given field.
United States customary system.
Definition: qgsunittypes.h:49
DistanceUnit
Units of distance.
Definition: qgsunittypes.h:66
QgsCoordinateReferenceSystem destinationCrs
CRS of destination coordinate reference system.
QSize outputSize
The size of the resulting map image.
A general purpose distance and area calculator, capable of performing ellipsoid based calculations...
QgsFeature feature
Feature that belongs to layer.
This class represents a coordinate reference system (CRS).
static Q_INVOKABLE QString evaluateExpression(const QgsQuickFeatureLayerPair &pair, QgsProject *activeProject, const QString &expression)
Evaluates expression.
QgsVectorLayer layer
Vector layer to which the feature belongs.
Class for doing transforms between two map coordinate systems.
static Q_INVOKABLE bool removeFile(const QString &filePath)
Deletes file from a given path.
QString dumpScreenInfo() const
Returns a string with information about screen size and resolution - useful for debugging.
void setSourceCrs(const QgsCoordinateReferenceSystem &crs, const QgsCoordinateTransformContext &context)
Sets source spatial reference system crs.
static Q_INVOKABLE QString formatDistance(double distance, QgsUnitTypes::DistanceUnit units, int decimals, QgsUnitTypes::SystemOfMeasurement destSystem=QgsUnitTypes::MetricSystem)
Converts distance to human readable distance.
static Q_INVOKABLE QgsQuickFeatureLayerPair featureFactory(const QgsFeature &feature, QgsVectorLayer *layer=nullptr)
QgsQuickFeatureLayerPair factory for tuple of QgsFeature and QgsVectorLayer used in QgsQUick library...
Pair of QgsFeature and QgsVectorLayer.
static QgsExpressionContextScope * layerScope(const QgsMapLayer *layer)
Creates a new scope which contains variables and functions relating to a QgsMapLayer.
static Q_INVOKABLE QgsPointXY pointXY(double x, double y)
Creates QgsPointXY in QML.
Terrestrial miles.
Definition: qgsunittypes.h:73
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.
static Q_INVOKABLE double fromUnitToUnitFactor(QgsUnitTypes::DistanceUnit fromUnit, QgsUnitTypes::DistanceUnit toUnit)
Returns the conversion factor between the specified distance units.
Represents a vector layer which manages a vector based data sets.
Q_INVOKABLE QgsCoordinateTransformContext transformContext() const
Returns the coordinate transform context, which stores various information regarding which datum tran...
static Q_INVOKABLE bool fileExists(const QString &path)
Returns whether file on path exists.
double measureLine(const QVector< QgsPointXY > &points) const
Measures the length of a line with multiple segments.
static Q_INVOKABLE QVariantMap createValueRelationCache(const QVariantMap &config, const QgsFeature &formFeature=QgsFeature())
Creates a cache for a value relation field.
static Q_INVOKABLE void logMessage(const QString &message, const QString &tag=QString("QgsQuick"), Qgis::MessageLevel level=Qgis::Warning)
Log message in QgsMessageLog.
static QString format(const QgsPointXY &point, Format format, int precision=12, FormatFlags flags=FlagDegreesUseStringSuffix)
Formats a point according to the specified parameters.