1 /*************************************************************************** 2 qgsquickutils.h 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 #ifndef QGSQUICKUTILS_H 17 #define QGSQUICKUTILS_H 18 19 20 #include <QObject> 21 #include <QString> 22 #include <QUrl> 23 #include <QtPositioning/QGeoCoordinate> 24 25 #include <limits> 26 27 #include "qgis.h" 28 #include "qgsexpressioncontextutils.h" 29 #include "qgsmessagelog.h" 30 #include "qgspoint.h" 31 #include "qgspointxy.h" 32 #include "qgsunittypes.h" 33 #include "qgsquickmapsettings.h" 34 #include "qgsquickfeaturelayerpair.h" 35 #include "qgis_quick.h" 36 #include "qgscoordinateformatter.h" 37 38 39 class QgsFeature; 40 class QgsVectorLayer; 41 class QgsCoordinateReferenceSystem; 42 43 /** 44 * \ingroup quick 45 * 46 * \brief Encapsulating the common utilities for QgsQuick library. 47 * 48 * \note QML Type: Utils (Singleton) 49 * 50 * \since QGIS 3.2 51 */ 52 class QUICK_EXPORT QgsQuickUtils: public QObject 53 { 54 Q_OBJECT 55 56 /** 57 * "dp" is useful for building building components that work well with different screen densities. 58 * It stands for density-independent pixels. A width of 10dp is going to be the same physical size 59 * on all screens regardless their density. In QML code, all values are specified in screen pixels, 60 * so in order to set a width of 10dp, one would use the following code: "width: 10 * QgsQuick.Utils.dp" 61 * 62 * 1dp is approximately 0.16mm. When screen has 160 DPI (baseline), the value of "dp" is 1. 63 * On high DPI screen the value will be greater, e.g. 1.5. 64 * 65 * This is a readonly property. 66 */ 67 Q_PROPERTY( qreal dp READ screenDensity CONSTANT ) 68 69 public: 70 //! Create new utilities 71 QgsQuickUtils( QObject *parent = nullptr ); 72 //! Destructor 73 ~QgsQuickUtils() = default; 74 75 //! \copydoc QgsQuickUtils::dp 76 qreal screenDensity() const; 77 78 /** 79 * Creates crs from epsg code in QML 80 * 81 * \since QGIS 3.4 82 */ 83 Q_INVOKABLE static QgsCoordinateReferenceSystem coordinateReferenceSystemFromEpsgId( long epsg ); 84 85 /** 86 * Creates QgsPointXY in QML 87 * 88 * \since QGIS 3.4 89 */ 90 Q_INVOKABLE static QgsPointXY pointXY( double x, double y ); 91 92 /** 93 * Creates QgsPoint in QML 94 * 95 * \since QGIS 3.4 96 */ 97 Q_INVOKABLE static QgsPoint point( double x, double y, double z = std::numeric_limits<double>::quiet_NaN(), double m = std::numeric_limits<double>::quiet_NaN() ); 98 99 /** 100 * Converts QGeoCoordinate to QgsPoint 101 * 102 * \since QGIS 3.4 103 */ 104 Q_INVOKABLE static QgsPoint coordinateToPoint( const QGeoCoordinate &coor ); 105 106 /** 107 * Transforms point between different crs from QML 108 * 109 * \since QGIS 3.4 110 */ 111 Q_INVOKABLE static QgsPointXY transformPoint( const QgsCoordinateReferenceSystem &srcCrs, 112 const QgsCoordinateReferenceSystem &destCrs, 113 const QgsCoordinateTransformContext &context, 114 const QgsPointXY &srcPoint ); 115 116 /** 117 * Calculates the distance in meter representing baseLengthPixels pixels on the screen based on the current map settings. 118 */ 119 Q_INVOKABLE static double screenUnitsToMeters( QgsQuickMapSettings *mapSettings, int baseLengthPixels ); 120 121 /** 122 * Returns whether file on path exists 123 * \since QGIS 3.4 124 */ 125 Q_INVOKABLE static bool fileExists( const QString &path ); 126 127 /** 128 * Returns relative path of the file to given prefixPath. If prefixPath does not match a path parameter, 129 * returns an empty string. If a path starts with "file://", this prefix is ignored. 130 * \param path Absolute path to file 131 * \param prefixPath 132 * \since QGIS 3.8 133 */ 134 Q_INVOKABLE static QString getRelativePath( const QString &path, const QString &prefixPath ); 135 136 /** 137 * Log message in QgsMessageLog 138 */ 139 Q_INVOKABLE static void logMessage( const QString &message, 140 const QString &tag = QString( "QgsQuick" ), 141 Qgis::MessageLevel level = Qgis::Warning ); 142 143 /** 144 * QgsQuickFeatureLayerPair factory for tuple of QgsFeature and QgsVectorLayer used in QgsQUick library. 145 * \param feature QgsFeature linked to new QgsQuickFeature instance. 146 * \param layer QgsVectorLayer which the feature belongs to, optional. 147 * 148 * \since QGIS 3.4 149 */ 150 Q_INVOKABLE static QgsQuickFeatureLayerPair featureFactory( const QgsFeature &feature, QgsVectorLayer *layer = nullptr ); 151 152 /** 153 * Returns QUrl to image from library's /images folder. 154 * 155 * \since QGIS 3.4 156 */ 157 Q_INVOKABLE static const QUrl getThemeIcon( const QString &name ); 158 159 /** 160 * Returns url to field editor component for a feature form. 161 * If the widgetName does not match any supported widget, text edit is returned. 162 * \param widgetName name of the attribute field widget 163 * 164 * \since QGIS 3.4 165 */ 166 Q_INVOKABLE static const QUrl getEditorComponentSource( const QString &widgetName ); 167 168 /** 169 * \copydoc QgsCoordinateFormatter::format() 170 * 171 * \since QGIS 3.4 172 */ 173 Q_INVOKABLE static QString formatPoint( 174 const QgsPoint &point, 175 QgsCoordinateFormatter::Format format = QgsCoordinateFormatter::FormatPair, 176 int decimals = 3, 177 QgsCoordinateFormatter::FormatFlags flags = QgsCoordinateFormatter::FlagDegreesUseStringSuffix ); 178 179 /** 180 * Converts distance to human readable distance 181 * 182 * This is useful for scalebar texts or output of the GPS accuracy 183 * 184 * The resulting units are determined automatically, 185 * based on requested system of measurement. 186 * e.g. 1222.234 m is converted to 1.2 km 187 * 188 * \param distance distance in units 189 * \param units units of dist 190 * \param decimals decimal to use 191 * \param destSystem system of measurement of the result 192 * \returns string represetation of dist in desired destSystem. For distance less than 0, 0 is returned. 193 * 194 * \since QGIS 3.4 195 */ 196 Q_INVOKABLE static QString formatDistance( double distance, 197 QgsUnitTypes::DistanceUnit units, 198 int decimals, 199 QgsUnitTypes::SystemOfMeasurement destSystem = QgsUnitTypes::MetricSystem ); 200 201 /** 202 * Deletes file from a given path. 203 * 204 * \param filePath Absolute path to file 205 * \returns bool TRUE, if removal was successful, otherwise FALSE. 206 * 207 * \since QGIS 3.8 208 */ 209 Q_INVOKABLE static bool removeFile( const QString &filePath ); 210 211 /** 212 * Converts distance to human readable distance in destination system of measurement 213 * 214 * \sa QgsQuickUtils::formatDistance() 215 * 216 * \param srcDistance distance in units 217 * \param srcUnits units of dist 218 * \param destSystem system of measurement of the result 219 * \param destDistance output: distance if desired system of measurement 220 * \param destUnits output: unit of destDistance 221 * 222 * \since QGIS 3.4 223 */ 224 static void humanReadableDistance( double srcDistance, 225 QgsUnitTypes::DistanceUnit srcUnits, 226 QgsUnitTypes::SystemOfMeasurement destSystem, 227 double &destDistance, 228 QgsUnitTypes::DistanceUnit &destUnits ); 229 230 //! Returns a string with information about screen size and resolution - useful for debugging 231 QString dumpScreenInfo() const; 232 233 /** 234 * Creates a cache for a value relation field. 235 * This can be used to keep the value map in the local memory 236 * if doing multiple lookups in a loop. 237 * \param config The widget configuration 238 * \param formFeature The feature currently being edited with current attribute values 239 * \return A kvp list of values for the widget 240 * 241 * \since QGIS 3.6 242 */ 243 Q_INVOKABLE static QVariantMap createValueRelationCache( const QVariantMap &config, const QgsFeature &formFeature = QgsFeature() ); 244 245 /** 246 * Evaluates expression. 247 * \param pair Used to define a context scope. 248 * \param activeProject Used to define a context scope. 249 * \param expression 250 * \return Evaluated expression 251 * 252 * \since QGIS 3.10 253 */ 254 Q_INVOKABLE static QString evaluateExpression( const QgsQuickFeatureLayerPair &pair, QgsProject *activeProject, const QString &expression ); 255 256 /** 257 * Selects features in a layer 258 * This method is required since QML cannot perform the conversion of a feature ID to a QgsFeatureId (i.e. a qint64) 259 * \param layer the vector layer 260 * \param fids the list of feature IDs 261 * \param behavior the selection behavior 262 * 263 * \since QGIS 3.12 264 */ 265 Q_INVOKABLE static void selectFeaturesInLayer( QgsVectorLayer *layer, const QList<int> &fids, QgsVectorLayer::SelectBehavior behavior = QgsVectorLayer::SetSelection ); 266 267 268 /** 269 * Returns the QVariant typeName of a \a field. 270 * This is a stable identifier (compared to the provider field name). 271 * \param field QgsField 272 */ 273 Q_INVOKABLE static QString fieldType( const QgsField &field ); 274 275 276 /** 277 * Returns field format's name for given string representing field format defined in QgsDateTimeFieldFormatter. 278 * \param fieldFormat string representing formats from QgsDateTimeFieldFormatter. 279 */ 280 Q_INVOKABLE static QString dateTimeFieldFormat( const QString &fieldFormat ); 281 282 private: 283 static void formatToMetricDistance( double srcDistance, 284 QgsUnitTypes::DistanceUnit srcUnits, 285 double &destDistance, 286 QgsUnitTypes::DistanceUnit &destUnits ); 287 288 static void formatToImperialDistance( double srcDistance, 289 QgsUnitTypes::DistanceUnit srcUnits, 290 double &destDistance, 291 QgsUnitTypes::DistanceUnit &destUnits ); 292 293 static void formatToUSCSDistance( double srcDistance, 294 QgsUnitTypes::DistanceUnit srcUnits, 295 double &destDistance, 296 QgsUnitTypes::DistanceUnit &destUnits ); 297 298 299 static qreal calculateScreenDensity(); 300 301 qreal mScreenDensity; 302 }; 303 304 #endif // QGSQUICKUTILS_H 305