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