Branch data Line data Source code
1 : : /***************************************************************************
2 : : qgis.cpp
3 : :
4 : : -------------------
5 : : begin : 2007
6 : : copyright : (C) 2007 by Gary E. Sherman
7 : : email : sherman@mrcc.com
8 : : ***************************************************************************/
9 : :
10 : : /***************************************************************************
11 : : * *
12 : : * This program is free software; you can redistribute it and/or modify *
13 : : * it under the terms of the GNU General Public License as published by *
14 : : * the Free Software Foundation; either version 2 of the License, or *
15 : : * (at your option) any later version. *
16 : : * *
17 : : ***************************************************************************/
18 : : #include "qgis.h"
19 : : #ifndef QGSVERSION
20 : : #include "qgsversion.h"
21 : : #endif
22 : : #include <QCoreApplication>
23 : : #include <QColor>
24 : : #include <QDate>
25 : : #include <QTime>
26 : : #include <QLocale>
27 : : #include <QDateTime>
28 : : #include "qgsconfig.h"
29 : : #include "qgslogger.h"
30 : : #include "qgswkbtypes.h"
31 : :
32 : : #include <gdal.h>
33 : : #include <geos_c.h>
34 : : #include <ogr_api.h>
35 : :
36 : : // Version constants
37 : : //
38 : :
39 : : // development version
40 : : const char *Qgis::QGIS_DEV_VERSION = QGSVERSION;
41 : :
42 : : const double Qgis::DEFAULT_SEARCH_RADIUS_MM = 2.;
43 : :
44 : : const float Qgis::DEFAULT_MAPTOPIXEL_THRESHOLD = 1.0f;
45 : :
46 : : const QColor Qgis::DEFAULT_HIGHLIGHT_COLOR = QColor( 255, 0, 0, 128 );
47 : :
48 : : const double Qgis::DEFAULT_HIGHLIGHT_BUFFER_MM = 0.5;
49 : :
50 : : const double Qgis::DEFAULT_HIGHLIGHT_MIN_WIDTH_MM = 1.0;
51 : :
52 : : const double Qgis::SCALE_PRECISION = 0.9999999999;
53 : :
54 : : const double Qgis::DEFAULT_Z_COORDINATE = 0.0;
55 : :
56 : : const double Qgis::DEFAULT_SNAP_TOLERANCE = 12.0;
57 : :
58 : : const QgsTolerance::UnitType Qgis::DEFAULT_SNAP_UNITS = QgsTolerance::Pixels;
59 : :
60 : : #ifdef Q_OS_WIN
61 : : const double Qgis::UI_SCALE_FACTOR = 1.5;
62 : : #else
63 : : const double Qgis::UI_SCALE_FACTOR = 1;
64 : : #endif
65 : :
66 : 0 : double qgsPermissiveToDouble( QString string, bool &ok )
67 : : {
68 : : //remove any thousands separators
69 : 0 : string.remove( QLocale().groupSeparator() );
70 : 0 : return QLocale().toDouble( string, &ok );
71 : 0 : }
72 : :
73 : 0 : int qgsPermissiveToInt( QString string, bool &ok )
74 : : {
75 : : //remove any thousands separators
76 : 0 : string.remove( QLocale().groupSeparator() );
77 : 0 : return QLocale().toInt( string, &ok );
78 : 0 : }
79 : :
80 : 0 : qlonglong qgsPermissiveToLongLong( QString string, bool &ok )
81 : : {
82 : : //remove any thousands separators
83 : 0 : string.remove( QLocale().groupSeparator() );
84 : 0 : return QLocale().toLongLong( string, &ok );
85 : 0 : }
86 : :
87 : 0 : void *qgsMalloc( size_t size )
88 : : {
89 : 0 : if ( size == 0 || long( size ) < 0 )
90 : : {
91 : 0 : QgsDebugMsg( QStringLiteral( "Negative or zero size %1." ).arg( size ) );
92 : 0 : return nullptr;
93 : : }
94 : 0 : void *p = malloc( size );
95 : 0 : if ( !p )
96 : : {
97 : 0 : QgsDebugMsg( QStringLiteral( "Allocation of %1 bytes failed." ).arg( size ) );
98 : 0 : }
99 : 0 : return p;
100 : 0 : }
101 : :
102 : 0 : void *qgsCalloc( size_t nmemb, size_t size )
103 : : {
104 : 0 : if ( nmemb == 0 || long( nmemb ) < 0 || size == 0 || long( size ) < 0 )
105 : : {
106 : 0 : QgsDebugMsg( QStringLiteral( "Negative or zero nmemb %1 or size %2." ).arg( nmemb ).arg( size ) );
107 : 0 : return nullptr;
108 : : }
109 : 0 : void *p = qgsMalloc( nmemb * size );
110 : 0 : if ( p )
111 : : {
112 : 0 : memset( p, 0, nmemb * size );
113 : 0 : }
114 : 0 : return p;
115 : 0 : }
116 : :
117 : 0 : void qgsFree( void *ptr )
118 : : {
119 : 0 : free( ptr );
120 : 0 : }
121 : :
122 : 0 : bool qgsVariantLessThan( const QVariant &lhs, const QVariant &rhs )
123 : : {
124 : : // invalid < NULL < any value
125 : 0 : if ( !lhs.isValid() )
126 : 0 : return rhs.isValid();
127 : 0 : else if ( lhs.isNull() )
128 : 0 : return rhs.isValid() && !rhs.isNull();
129 : 0 : else if ( !rhs.isValid() || rhs.isNull() )
130 : 0 : return false;
131 : :
132 : 0 : switch ( lhs.type() )
133 : : {
134 : : case QVariant::Int:
135 : 0 : return lhs.toInt() < rhs.toInt();
136 : : case QVariant::UInt:
137 : 0 : return lhs.toUInt() < rhs.toUInt();
138 : : case QVariant::LongLong:
139 : 0 : return lhs.toLongLong() < rhs.toLongLong();
140 : : case QVariant::ULongLong:
141 : 0 : return lhs.toULongLong() < rhs.toULongLong();
142 : : case QVariant::Double:
143 : 0 : return lhs.toDouble() < rhs.toDouble();
144 : : case QVariant::Char:
145 : 0 : return lhs.toChar() < rhs.toChar();
146 : : case QVariant::Date:
147 : 0 : return lhs.toDate() < rhs.toDate();
148 : : case QVariant::Time:
149 : 0 : return lhs.toTime() < rhs.toTime();
150 : : case QVariant::DateTime:
151 : 0 : return lhs.toDateTime() < rhs.toDateTime();
152 : : case QVariant::Bool:
153 : 0 : return lhs.toBool() < rhs.toBool();
154 : :
155 : : case QVariant::List:
156 : : {
157 : 0 : const QList<QVariant> &lhsl = lhs.toList();
158 : 0 : const QList<QVariant> &rhsl = rhs.toList();
159 : :
160 : 0 : int i, n = std::min( lhsl.size(), rhsl.size() );
161 : 0 : for ( i = 0; i < n && lhsl[i].type() == rhsl[i].type() && qgsVariantEqual( lhsl[i], rhsl[i] ); i++ )
162 : : ;
163 : :
164 : 0 : if ( i == n )
165 : 0 : return lhsl.size() < rhsl.size();
166 : : else
167 : 0 : return qgsVariantLessThan( lhsl[i], rhsl[i] );
168 : 0 : }
169 : :
170 : : case QVariant::StringList:
171 : : {
172 : 0 : const QStringList &lhsl = lhs.toStringList();
173 : 0 : const QStringList &rhsl = rhs.toStringList();
174 : :
175 : 0 : int i, n = std::min( lhsl.size(), rhsl.size() );
176 : 0 : for ( i = 0; i < n && lhsl[i] == rhsl[i]; i++ )
177 : : ;
178 : :
179 : 0 : if ( i == n )
180 : 0 : return lhsl.size() < rhsl.size();
181 : : else
182 : 0 : return lhsl[i] < rhsl[i];
183 : 0 : }
184 : :
185 : : default:
186 : 0 : return QString::localeAwareCompare( lhs.toString(), rhs.toString() ) < 0;
187 : : }
188 : 0 : }
189 : :
190 : 0 : bool qgsVariantGreaterThan( const QVariant &lhs, const QVariant &rhs )
191 : : {
192 : 0 : return ! qgsVariantLessThan( lhs, rhs );
193 : : }
194 : :
195 : 403 : QString qgsVsiPrefix( const QString &path )
196 : : {
197 : 403 : if ( path.startsWith( QLatin1String( "/vsizip/" ), Qt::CaseInsensitive ) )
198 : 0 : return QStringLiteral( "/vsizip/" );
199 : 403 : else if ( path.endsWith( QLatin1String( ".shp.zip" ), Qt::CaseInsensitive ) )
200 : : {
201 : : // GDAL 3.1 Shapefile driver directly handles .shp.zip files
202 : 0 : if ( GDALIdentifyDriver( path.toUtf8().constData(), nullptr ) )
203 : 0 : return QString();
204 : 0 : return QStringLiteral( "/vsizip/" );
205 : : }
206 : 403 : else if ( path.endsWith( QLatin1String( ".zip" ), Qt::CaseInsensitive ) )
207 : 0 : return QStringLiteral( "/vsizip/" );
208 : 806 : else if ( path.startsWith( QLatin1String( "/vsitar/" ), Qt::CaseInsensitive ) ||
209 : 403 : path.endsWith( QLatin1String( ".tar" ), Qt::CaseInsensitive ) ||
210 : 403 : path.endsWith( QLatin1String( ".tar.gz" ), Qt::CaseInsensitive ) ||
211 : 403 : path.endsWith( QLatin1String( ".tgz" ), Qt::CaseInsensitive ) )
212 : 0 : return QStringLiteral( "/vsitar/" );
213 : 403 : else if ( path.startsWith( QLatin1String( "/vsigzip/" ), Qt::CaseInsensitive ) ||
214 : 403 : path.endsWith( QLatin1String( ".gz" ), Qt::CaseInsensitive ) )
215 : 0 : return QStringLiteral( "/vsigzip/" );
216 : : else
217 : 403 : return QString();
218 : 403 : }
219 : :
220 : 0 : uint qHash( const QVariant &variant )
221 : : {
222 : 0 : if ( !variant.isValid() || variant.isNull() )
223 : 0 : return std::numeric_limits<uint>::max();
224 : :
225 : 0 : switch ( variant.type() )
226 : : {
227 : : case QVariant::Int:
228 : 0 : return qHash( variant.toInt() );
229 : : case QVariant::UInt:
230 : 0 : return qHash( variant.toUInt() );
231 : : case QVariant::Bool:
232 : 0 : return qHash( variant.toBool() );
233 : : case QVariant::Double:
234 : 0 : return qHash( variant.toDouble() );
235 : : case QVariant::LongLong:
236 : 0 : return qHash( variant.toLongLong() );
237 : : case QVariant::ULongLong:
238 : 0 : return qHash( variant.toULongLong() );
239 : : case QVariant::String:
240 : 0 : return qHash( variant.toString() );
241 : : case QVariant::Char:
242 : 0 : return qHash( variant.toChar() );
243 : : case QVariant::List:
244 : 0 : return qHash( variant.toList() );
245 : : case QVariant::StringList:
246 : 0 : return qHash( variant.toStringList() );
247 : : case QVariant::ByteArray:
248 : 0 : return qHash( variant.toByteArray() );
249 : : case QVariant::Date:
250 : 0 : return qHash( variant.toDate() );
251 : : case QVariant::Time:
252 : 0 : return qHash( variant.toTime() );
253 : : case QVariant::DateTime:
254 : 0 : return qHash( variant.toDateTime() );
255 : : case QVariant::Url:
256 : : case QVariant::Locale:
257 : : case QVariant::RegularExpression:
258 : : #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
259 : : case QVariant::RegExp:
260 : : #endif
261 : 0 : return qHash( variant.toString() );
262 : : default:
263 : 0 : break;
264 : : }
265 : :
266 : 0 : return std::numeric_limits<uint>::max();
267 : 0 : }
268 : :
269 : 0 : bool qgsVariantEqual( const QVariant &lhs, const QVariant &rhs )
270 : : {
271 : 0 : return ( lhs.isNull() == rhs.isNull() && lhs == rhs ) || ( lhs.isNull() && rhs.isNull() && lhs.isValid() && rhs.isValid() );
272 : : }
273 : :
274 : 0 : QString Qgis::defaultProjectScales()
275 : : {
276 : 0 : return QStringLiteral( "1:1000000,1:500000,1:250000,1:100000,1:50000,1:25000,"
277 : : "1:10000,1:5000,1:2500,1:1000,1:500" );
278 : : }
279 : :
280 : 1 : QString Qgis::version()
281 : : {
282 : 1 : return QString::fromUtf8( VERSION );
283 : : }
284 : :
285 : 8 : int Qgis::versionInt()
286 : : {
287 : : // Version number used for comparing versions using the
288 : : // "Check QGIS Version" function
289 : 8 : return VERSION_INT;
290 : : }
291 : :
292 : 1 : QString Qgis::releaseName()
293 : : {
294 : 1 : return QString::fromUtf8( RELEASE_NAME );
295 : : }
296 : :
297 : 0 : QString Qgis::devVersion()
298 : : {
299 : 0 : return QString::fromUtf8( QGIS_DEV_VERSION );
300 : : }
301 : :
302 : 0 : QString Qgis::geosVersion()
303 : : {
304 : 0 : return GEOSversion();
305 : : }
306 : :
307 : 0 : int Qgis::geosVersionInt()
308 : : {
309 : 0 : return QStringLiteral( "%1%2%3" ).arg( GEOS_VERSION_MAJOR, 2, 10, QChar( '0' ) ).arg( GEOS_VERSION_MINOR, 2, 10, QChar( '0' ) ).arg( GEOS_VERSION_PATCH, 2, 10, QChar( '0' ) ).toInt();
310 : 0 : }
311 : :
312 : 0 : int Qgis::geosVersionMajor()
313 : : {
314 : 0 : return GEOS_VERSION_MAJOR;
315 : : }
316 : :
317 : 0 : int Qgis::geosVersionMinor()
318 : : {
319 : 0 : return GEOS_VERSION_MINOR;
320 : : }
321 : :
322 : 0 : int Qgis::geosVersionPatch()
323 : : {
324 : 0 : return GEOS_VERSION_PATCH;
325 : : }
326 : :
327 : : #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
328 : : template<>
329 : 0 : bool qMapLessThanKey<QVariantList>( const QVariantList &key1, const QVariantList &key2 )
330 : : {
331 : : // qt's built in qMapLessThanKey for QVariantList is broken and does a case-insensitive operation.
332 : : // this breaks QMap< QVariantList, ... >, where key matching incorrectly becomes case-insensitive..!!?!
333 : 0 : return qgsVariantGreaterThan( key1, key2 ) && key1 != key2;
334 : 0 : }
335 : : #endif
|