QGIS API Documentation  2.11.0-Master
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
qgsapplication.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsapplication.cpp - Accessors for application-wide data
3  --------------------------------------
4  Date : 02-Jan-2006
5  Copyright : (C) 2006 by Tom Elwertowski
6  Email : telwertowski at users dot sourceforge dot net
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 "qgsapplication.h"
17 #include "qgscrscache.h"
19 #include "qgsexception.h"
20 #include "qgsgeometry.h"
21 #include "qgslogger.h"
22 #include "qgsmaplayerregistry.h"
24 #include "qgsproviderregistry.h"
25 
26 #include <QDir>
27 #include <QFile>
28 #include <QFileOpenEvent>
29 #include <QMessageBox>
30 #include <QPalette>
31 #include <QProcess>
32 #include <QSettings>
33 #include <QIcon>
34 #include <QPixmap>
35 #include <QThreadPool>
36 
37 #ifndef Q_OS_WIN
38 #include <netinet/in.h>
39 #else
40 #include <winsock.h>
41 #endif
42 
43 #include "qgsconfig.h"
44 
45 #include <gdal.h>
46 #include <ogr_api.h>
47 #include <cpl_conv.h> // for setting gdal options
48 #include <sqlite3.h>
49 
50 QObject * ABISYM( QgsApplication::mFileOpenEventReceiver );
51 QStringList ABISYM( QgsApplication::mFileOpenEventList );
52 QString ABISYM( QgsApplication::mPrefixPath );
53 QString ABISYM( QgsApplication::mPluginPath );
54 QString ABISYM( QgsApplication::mPkgDataPath );
55 QString ABISYM( QgsApplication::mLibraryPath );
56 QString ABISYM( QgsApplication::mLibexecPath );
57 QString ABISYM( QgsApplication::mThemeName );
58 QStringList ABISYM( QgsApplication::mDefaultSvgPaths );
59 QMap<QString, QString> ABISYM( QgsApplication::mSystemEnvVars );
60 QString ABISYM( QgsApplication::mConfigPath );
61 bool ABISYM( QgsApplication::mRunningFromBuildDir ) = false;
62 QString ABISYM( QgsApplication::mBuildSourcePath );
63 #ifdef _MSC_VER
64 QString ABISYM( QgsApplication::mCfgIntDir );
65 #endif
66 QString ABISYM( QgsApplication::mBuildOutputPath );
67 QStringList ABISYM( QgsApplication::mGdalSkipList );
68 int ABISYM( QgsApplication::mMaxThreads );
69 
70 const char* QgsApplication::QGIS_ORGANIZATION_NAME = "QGIS";
71 const char* QgsApplication::QGIS_ORGANIZATION_DOMAIN = "qgis.org";
72 const char* QgsApplication::QGIS_APPLICATION_NAME = "QGIS2";
73 
87 QgsApplication::QgsApplication( int & argc, char ** argv, bool GUIenabled, QString customConfigPath )
88  : QApplication( argc, argv, GUIenabled )
89 {
90  init( customConfigPath ); // init can also be called directly by e.g. unit tests that don't inherit QApplication.
91 }
92 
93 void QgsApplication::init( QString customConfigPath )
94 {
95  if ( customConfigPath.isEmpty() )
96  {
97  if ( getenv( "QGIS_CUSTOM_CONFIG_PATH" ) )
98  {
99  customConfigPath = getenv( "QGIS_CUSTOM_CONFIG_PATH" );
100  }
101  else
102  {
103  customConfigPath = QString( "%1/.qgis%2/" ).arg( QDir::homePath() ).arg( QGis::QGIS_VERSION_INT / 10000 );
104  }
105  }
106 
107  qRegisterMetaType<QgsGeometry::Error>( "QgsGeometry::Error" );
108 
109  QString prefixPath( getenv( "QGIS_PREFIX_PATH" ) ? getenv( "QGIS_PREFIX_PATH" ) : applicationDirPath() );
110  // QgsDebugMsg( QString( "prefixPath(): %1" ).arg( prefixPath ) );
111 
112  // check if QGIS is run from build directory (not the install directory)
113  QFile f;
114  // "/../../.." is for Mac bundled app in build directory
115  foreach ( QString path, QStringList() << "" << "/.." << "/bin" << "/../../.." )
116  {
117  f.setFileName( prefixPath + path + "/qgisbuildpath.txt" );
118  if ( f.exists() )
119  break;
120  }
121  if ( f.exists() && f.open( QIODevice::ReadOnly ) )
122  {
123  ABISYM( mRunningFromBuildDir ) = true;
124  ABISYM( mBuildSourcePath ) = f.readLine().trimmed();
125  ABISYM( mBuildOutputPath ) = f.readLine().trimmed();
126  qDebug( "Running from build directory!" );
127  qDebug( "- source directory: %s", ABISYM( mBuildSourcePath ).toUtf8().data() );
128  qDebug( "- output directory of the build: %s", ABISYM( mBuildOutputPath ).toUtf8().data() );
129 #ifdef _MSC_VER
130  ABISYM( mCfgIntDir ) = prefixPath.split( "/", QString::SkipEmptyParts ).last();
131  qDebug( "- cfg: %s", ABISYM( mCfgIntDir ).toUtf8().data() );
132 #endif
133  }
134 
135  if ( ABISYM( mRunningFromBuildDir ) )
136  {
137  // we run from source directory - not installed to destination (specified prefix)
138  ABISYM( mPrefixPath ) = QString(); // set invalid path
139 #if defined(_MSC_VER) && !defined(USING_NMAKE)
140  setPluginPath( ABISYM( mBuildOutputPath ) + "/" + QString( QGIS_PLUGIN_SUBDIR ) + "/" + ABISYM( mCfgIntDir ) );
141 #else
142  setPluginPath( ABISYM( mBuildOutputPath ) + "/" + QString( QGIS_PLUGIN_SUBDIR ) );
143 #endif
144  setPkgDataPath( ABISYM( mBuildSourcePath ) ); // directly source path - used for: doc, resources, svg
145  ABISYM( mLibraryPath ) = ABISYM( mBuildOutputPath ) + "/" + QGIS_LIB_SUBDIR + "/";
146 #if defined(_MSC_VER) && !defined(USING_NMAKE)
147  ABISYM( mLibexecPath ) = ABISYM( mBuildOutputPath ) + "/" + QGIS_LIBEXEC_SUBDIR + "/" + ABISYM( mCfgIntDir ) + "/";
148 #else
149  ABISYM( mLibexecPath ) = ABISYM( mBuildOutputPath ) + "/" + QGIS_LIBEXEC_SUBDIR + "/";
150 #endif
151  }
152  else
153  {
154  char *prefixPath = getenv( "QGIS_PREFIX_PATH" );
155  if ( !prefixPath )
156  {
157 #if defined(Q_OS_MACX) || defined(Q_OS_WIN32) || defined(WIN32)
159 #elif defined(ANDROID)
160  // this is "/data/data/org.qgis.qgis" in android
161  QDir myDir( QDir::homePath() );
162  myDir.cdUp();
163  QString myPrefix = myDir.absolutePath();
164  setPrefixPath( myPrefix, true );
165 #else
166  QDir myDir( applicationDirPath() );
167  myDir.cdUp();
168  QString myPrefix = myDir.absolutePath();
169  setPrefixPath( myPrefix, true );
170 #endif
171  }
172  else
173  {
174  setPrefixPath( prefixPath, true );
175  }
176  }
177 
178  if ( !customConfigPath.isEmpty() )
179  {
180  ABISYM( mConfigPath ) = customConfigPath + "/"; // make sure trailing slash is included
181  }
182 
183  ABISYM( mDefaultSvgPaths ) << qgisSettingsDirPath() + QString( "svg/" );
184 
185  // store system environment variables passed to application, before they are adjusted
186  QMap<QString, QString> systemEnvVarMap;
187  foreach ( const QString &varStr, QProcess::systemEnvironment() )
188  {
189  int pos = varStr.indexOf( QLatin1Char( '=' ) );
190  if ( pos == -1 )
191  continue;
192  QString varStrName = varStr.left( pos );
193  QString varStrValue = varStr.mid( pos + 1 );
194  systemEnvVarMap.insert( varStrName, varStrValue );
195  }
196  ABISYM( mSystemEnvVars ) = systemEnvVarMap;
197 
198  // allow Qt to search for Qt plugins (e.g. sqldrivers) in our plugin directory
200 
201  // set max. thread count to -1
202  // this should be read from QSettings but we don't know where they are at this point
203  // so we read actual value in main.cpp
204  ABISYM( mMaxThreads ) = -1;
205 }
206 
208 {
209 }
210 
212 {
213  bool done = false;
214  if ( event->type() == QEvent::FileOpen )
215  {
216  // handle FileOpen event (double clicking a file icon in Mac OS X Finder)
217  if ( ABISYM( mFileOpenEventReceiver ) )
218  {
219  // Forward event to main window.
220  done = notify( ABISYM( mFileOpenEventReceiver ), event );
221  }
222  else
223  {
224  // Store filename because receiver has not registered yet.
225  // If QGIS has been launched by double clicking a file icon, FileOpen will be
226  // the first event; the main window is not yet ready to handle the event.
227  ABISYM( mFileOpenEventList ).append( static_cast<QFileOpenEvent *>( event )->file() );
228  done = true;
229  }
230  }
231  else
232  {
233  // pass other events to base class
234  done = QApplication::event( event );
235  }
236  return done;
237 }
238 
239 bool QgsApplication::notify( QObject * receiver, QEvent * event )
240 {
241  bool done = false;
242  // Crashes in customization (especially on Mac), if we're not in the main/UI thread, see #5597
243  if ( thread() == receiver->thread() )
244  emit preNotify( receiver, event, &done );
245 
246  if ( done )
247  return true;
248 
249  // Send event to receiver and catch unhandled exceptions
250  done = true;
251  try
252  {
253  done = QApplication::notify( receiver, event );
254  }
255  catch ( QgsException & e )
256  {
257  QgsDebugMsg( "Caught unhandled QgsException: " + e.what() );
258  if ( qApp->thread() == QThread::currentThread() )
259  QMessageBox::critical( activeWindow(), tr( "Exception" ), e.what() );
260  }
261  catch ( std::exception & e )
262  {
263  QgsDebugMsg( "Caught unhandled std::exception: " + QString::fromAscii( e.what() ) );
264  if ( qApp->thread() == QThread::currentThread() )
265  QMessageBox::critical( activeWindow(), tr( "Exception" ), e.what() );
266  }
267  catch ( ... )
268  {
269  QgsDebugMsg( "Caught unhandled unknown exception" );
270  if ( qApp->thread() == QThread::currentThread() )
271  QMessageBox::critical( activeWindow(), tr( "Exception" ), tr( "unknown exception" ) );
272  }
273 
274  return done;
275 }
276 
278 {
279  // Set receiver for FileOpen events
280  ABISYM( mFileOpenEventReceiver ) = receiver;
281  // Propagate any events collected before the receiver has registered.
282  if ( ABISYM( mFileOpenEventList ).count() > 0 )
283  {
284  QStringListIterator i( ABISYM( mFileOpenEventList ) );
285  while ( i.hasNext() )
286  {
287  QFileOpenEvent foe( i.next() );
288  QgsApplication::sendEvent( ABISYM( mFileOpenEventReceiver ), &foe );
289  }
290  ABISYM( mFileOpenEventList ).clear();
291  }
292 }
293 
294 void QgsApplication::setPrefixPath( const QString &thePrefixPath, bool useDefaultPaths )
295 {
296  ABISYM( mPrefixPath ) = thePrefixPath;
297 #if defined(_MSC_VER)
298  if ( ABISYM( mPrefixPath ).endsWith( "/bin" ) )
299  {
300  ABISYM( mPrefixPath ).chop( 4 );
301  }
302 #endif
303  if ( useDefaultPaths && !ABISYM( mRunningFromBuildDir ) )
304  {
305  setPluginPath( ABISYM( mPrefixPath ) + "/" + QString( QGIS_PLUGIN_SUBDIR ) );
306  setPkgDataPath( ABISYM( mPrefixPath ) + "/" + QString( QGIS_DATA_SUBDIR ) );
307  }
308  ABISYM( mLibraryPath ) = ABISYM( mPrefixPath ) + "/" + QGIS_LIB_SUBDIR + "/";
309  ABISYM( mLibexecPath ) = ABISYM( mPrefixPath ) + "/" + QGIS_LIBEXEC_SUBDIR + "/";
310 }
311 
312 void QgsApplication::setPluginPath( const QString &thePluginPath )
313 {
314  ABISYM( mPluginPath ) = thePluginPath;
315 }
316 
317 void QgsApplication::setPkgDataPath( const QString &thePkgDataPath )
318 {
319  ABISYM( mPkgDataPath ) = thePkgDataPath;
320  QString mySvgPath = thePkgDataPath + ( ABISYM( mRunningFromBuildDir ) ? "/images/svg/" : "/svg/" );
321  // avoid duplicate entries
322  if ( !ABISYM( mDefaultSvgPaths ).contains( mySvgPath ) )
323  ABISYM( mDefaultSvgPaths ) << mySvgPath;
324 }
325 
327 {
328  ABISYM( mDefaultSvgPaths ) = pathList;
329 }
330 
332 {
333  if ( ABISYM( mRunningFromBuildDir ) )
334  {
335  static bool once = true;
336  if ( once )
337  qWarning( "!!! prefix path was requested, but it is not valid - we do not run from installed path !!!" );
338  once = false;
339  }
340 
341  return ABISYM( mPrefixPath );
342 }
344 {
345  return ABISYM( mPluginPath );
346 }
348 {
349  return ABISYM( mPkgDataPath );
350 }
352 {
353  return ":/images/themes/default/";
354 }
356 {
357  return ":/images/themes/" + themeName() + "/";
358 }
359 
360 
362 {
363  // try active theme
364  QString path = activeThemePath();
365  if ( QFile::exists( path + iconFile ) )
366  return path + iconFile;
367 
368  // use default theme
369  return defaultThemePath() + iconFile;
370 }
371 
373 {
374  QString myPreferredPath = activeThemePath() + QDir::separator() + theName;
375  QString myDefaultPath = defaultThemePath() + QDir::separator() + theName;
376  if ( QFile::exists( myPreferredPath ) )
377  {
378  return QIcon( myPreferredPath );
379  }
380  else if ( QFile::exists( myDefaultPath ) )
381  {
382  //could still return an empty icon if it
383  //doesnt exist in the default theme either!
384  return QIcon( myDefaultPath );
385  }
386  else
387  {
388  return QIcon();
389  }
390 }
391 
392 // TODO: add some caching mechanism ?
394 {
395  QString myPreferredPath = activeThemePath() + QDir::separator() + theName;
396  QString myDefaultPath = defaultThemePath() + QDir::separator() + theName;
397  if ( QFile::exists( myPreferredPath ) )
398  {
399  return QPixmap( myPreferredPath );
400  }
401  else
402  {
403  //could still return an empty icon if it
404  //doesnt exist in the default theme either!
405  return QPixmap( myDefaultPath );
406  }
407 }
408 
412 void QgsApplication::setThemeName( const QString &theThemeName )
413 {
414  QString myPath = ":/images/themes/" + theThemeName + "/";
415  //check it exists and if not roll back to default theme
416  if ( QFile::exists( myPath ) )
417  {
418  ABISYM( mThemeName ) = theThemeName;
419  }
420  else
421  {
422  ABISYM( mThemeName ) = "default";
423  }
424 }
429 {
430  return ABISYM( mThemeName );
431 }
436 {
437  return ABISYM( mPkgDataPath ) + QString( "/doc/AUTHORS" );
438 }
443 {
444  return ABISYM( mPkgDataPath ) + QString( "/doc/CONTRIBUTORS" );
445 }
447 {
448  return ABISYM( mPkgDataPath ) + QString( "/doc/developersmap.html" );
449 }
454 {
455  return ABISYM( mPkgDataPath ) + QString( "/doc/SPONSORS" );
456 }
457 
462 {
463  return ABISYM( mPkgDataPath ) + QString( "/doc/DONORS" );
464 }
465 
468 {
469  return ABISYM( mPkgDataPath ) + QString( "/doc/TRANSLATORS" );
470 }
471 
474 {
475  return ABISYM( mPkgDataPath ) + QString( "/doc/LICENSE" );
476 }
477 
482 {
484 #ifdef Q_OS_MACX
485  helpAppPath = applicationDirPath() + "/bin/qgis_help.app/Contents/MacOS";
486 #else
487  helpAppPath = libexecPath();
488 #endif
489  helpAppPath += "/qgis_help";
490 #ifdef Q_OS_WIN
491  helpAppPath += ".exe";
492 #endif
493  return helpAppPath;
494 }
499 {
500  if ( ABISYM( mRunningFromBuildDir ) )
501  return ABISYM( mBuildOutputPath ) + QString( "/i18n" );
502  else
503  return ABISYM( mPkgDataPath ) + QString( "/i18n/" );
504 }
505 
510 {
511  return ABISYM( mPkgDataPath ) + QString( "/resources/qgis.db" );
512 }
513 
518 {
519  return ABISYM( mConfigPath );
520 }
521 
526 {
527  return qgisSettingsDirPath() + QString( "qgis.db" );
528 }
529 
534 {
535  return QString( ":/images/splash/" );
536 }
537 
542 {
543  return ABISYM( mPkgDataPath ) + QString( "/images/icons/" );
544 }
549 {
550  if ( ABISYM( mRunningFromBuildDir ) )
551  {
552  QString tempCopy = QDir::tempPath() + "/srs.db";
553 
554  if ( !QFile( tempCopy ).exists() )
555  {
556  QFile f( ABISYM( mPkgDataPath ) + "/resources/srs.db" );
557  if ( !f.copy( tempCopy ) )
558  {
559  qFatal( "Could not create temporary copy" );
560  }
561  }
562 
563  return tempCopy;
564  }
565  else
566  {
567  return ABISYM( mPkgDataPath ) + QString( "/resources/srs.db" );
568  }
569 }
570 
575 {
576  //local directories to search when looking for an SVG with a given basename
577  //defined by user in options dialog
578  QSettings settings;
579  QStringList myPathList;
580  QString myPaths = settings.value( "svg/searchPathsForSVG", "" ).toString();
581  if ( !myPaths.isEmpty() )
582  {
583  myPathList = myPaths.split( "|" );
584  }
585 
586  myPathList << ABISYM( mDefaultSvgPaths );
587  return myPathList;
588 }
589 
591 {
592  return qgisSettingsDirPath() + QString( "symbology-ng-style.db" );
593 }
594 
596 {
597  return ABISYM( mPkgDataPath ) + QString( "/resources/symbology-ng-style.db" );
598 }
599 
601 {
602  return ABISYM( mLibraryPath );
603 }
604 
606 {
607  return ABISYM( mLibexecPath );
608 }
609 
611 {
612  return ( htonl( 1 ) == 1 ) ? XDR : NDR;
613 }
614 
616 {
617  // set the provider plugin path (this creates provider registry)
619 
620  // create map layer registry if doesn't exist
622 }
623 
625 {
627 }
628 
630 {
631  QString myEnvironmentVar( getenv( "QGIS_PREFIX_PATH" ) );
632  QString myState = tr( "Application state:\n"
633  "QGIS_PREFIX_PATH env var:\t\t%1\n"
634  "Prefix:\t\t%2\n"
635  "Plugin Path:\t\t%3\n"
636  "Package Data Path:\t%4\n"
637  "Active Theme Name:\t%5\n"
638  "Active Theme Path:\t%6\n"
639  "Default Theme Path:\t%7\n"
640  "SVG Search Paths:\t%8\n"
641  "User DB Path:\t%9\n" )
642  .arg( myEnvironmentVar )
643  .arg( prefixPath() )
644  .arg( pluginPath() )
645  .arg( pkgDataPath() )
646  .arg( themeName() )
647  .arg( activeThemePath() )
648  .arg( defaultThemePath() )
649  .arg( svgPaths().join( tr( "\n\t\t", "match indentation of application state" ) ) )
651  return myState;
652 }
653 
655 {
656  //
657  // Make the style sheet desktop preferences aware by using qappliation
658  // palette as a basis for colors where appropriate
659  //
660 // QColor myColor1 = palette().highlight().color();
661  QColor myColor1( Qt::lightGray );
662  QColor myColor2 = myColor1;
663  myColor2 = myColor2.lighter( 110 ); //10% lighter
664  QString myStyle;
665  myStyle = "p.glossy{ background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, "
666  " stop: 0 " + myColor1.name() + ","
667  " stop: 0.1 " + myColor2.name() + ","
668  " stop: 0.5 " + myColor1.name() + ","
669  " stop: 0.9 " + myColor2.name() + ","
670  " stop: 1 " + myColor1.name() + ");"
671  " color: black;"
672  " padding-left: 4px;"
673  " padding-top: 20px;"
674  " padding-bottom: 8px;"
675  " border: 1px solid #6c6c6c;"
676  "}"
677  "p.subheaderglossy{ background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, "
678  " stop: 0 " + myColor1.name() + ","
679  " stop: 0.1 " + myColor2.name() + ","
680  " stop: 0.5 " + myColor1.name() + ","
681  " stop: 0.9 " + myColor2.name() + ","
682  " stop: 1 " + myColor1.name() + ");"
683  " font-weight: bold;"
684  " font-size: medium;"
685  " line-height: 1.1em;"
686  " width: 100%;"
687  " color: black;"
688  " padding-left: 4px;"
689  " padding-right: 4px;"
690  " padding-top: 20px;"
691  " padding-bottom: 8px;"
692  " border: 1px solid #6c6c6c;"
693  "}"
694  "th.glossy{ background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, "
695  " stop: 0 " + myColor1.name() + ","
696  " stop: 0.1 " + myColor2.name() + ","
697  " stop: 0.5 " + myColor1.name() + ","
698  " stop: 0.9 " + myColor2.name() + ","
699  " stop: 1 " + myColor1.name() + ");"
700  " color: black;"
701  " border: 1px solid #6c6c6c;"
702  "}"
703  ".overview{ font: 1.82em; font-weight: bold;}"
704  "body{ background: white;"
705  " color: black;"
706  " font-family: arial,sans-serif;"
707  "}"
708  "h1{ background-color: #F6F6F6;"
709  " color: #8FB171; "
710  " font-size: x-large; "
711  " font-weight: normal;"
712  " font-family: luxi serif, georgia, times new roman, times, serif;"
713  " background: none;"
714  " padding: 0.75em 0 0;"
715  " margin: 0;"
716  " line-height: 3em;"
717  "}"
718  "h2{ background-color: #F6F6F6;"
719  " color: #8FB171; "
720  " font-size: medium; "
721  " font-weight: normal;"
722  " font-family: luxi serif, georgia, times new roman, times, serif;"
723  " background: none;"
724  " padding: 0.75em 0 0;"
725  " margin: 0;"
726  " line-height: 1.1em;"
727  "}"
728  "h3{ background-color: #F6F6F6;"
729  " color: #729FCF;"
730  " font-family: luxi serif, georgia, times new roman, times, serif;"
731  " font-weight: bold;"
732  " font-size: large;"
733  " text-align: right;"
734  " border-bottom: 5px solid #DCEB5C;"
735  "}"
736  "h4{ background-color: #F6F6F6;"
737  " color: #729FCF;"
738  " font-family: luxi serif, georgia, times new roman, times, serif;"
739  " font-weight: bold;"
740  " font-size: medium;"
741  " text-align: right;"
742  "}"
743  "h5{ background-color: #F6F6F6;"
744  " color: #729FCF;"
745  " font-family: luxi serif, georgia, times new roman, times, serif;"
746  " font-weight: bold;"
747  " font-size: small;"
748  " text-align: right;"
749  "}"
750  "a{ color: #729FCF;"
751  " font-family: arial,sans-serif;"
752  " font-size: small;"
753  "}"
754  "label{ background-color: #FFFFCC;"
755  " border: 1px solid black;"
756  " margin: 1px;"
757  " padding: 0px 3px; "
758  " font-size: small;"
759  "}";
760  return myStyle;
761 }
762 
764 {
765  if ( 0 >= OGRGetDriverCount() )
766  {
767  OGRRegisterAll();
768  }
769 }
770 
772 {
773 #if defined( Q_OS_WIN )
774  const Qt::CaseSensitivity cs = Qt::CaseInsensitive;
775 
776  aPath.replace( "\\", "/" );
777  if ( aPath.startsWith( "//" ) )
778  {
779  // keep UNC prefix
780  aPath = "\\\\" + aPath.mid( 2 );
781  }
782 
783  targetPath.replace( "\\", "/" );
784  if ( targetPath.startsWith( "//" ) )
785  {
786  // keep UNC prefix
787  targetPath = "\\\\" + targetPath.mid( 2 );
788  }
789 #else
790  const Qt::CaseSensitivity cs = Qt::CaseSensitive;
791 #endif
792 
793  QStringList targetElems = targetPath.split( "/", QString::SkipEmptyParts );
794  QStringList aPathElems = aPath.split( "/", QString::SkipEmptyParts );
795 
796  targetElems.removeAll( "." );
797  aPathElems.removeAll( "." );
798 
799  // remove common part
800  int n = 0;
801  while ( aPathElems.size() > 0 &&
802  targetElems.size() > 0 &&
803  aPathElems[0].compare( targetElems[0], cs ) == 0 )
804  {
805  aPathElems.removeFirst();
806  targetElems.removeFirst();
807  n++;
808  }
809 
810  if ( n == 0 )
811  {
812  // no common parts; might not even be a file
813  return aPath;
814  }
815 
816  if ( targetElems.size() > 0 )
817  {
818  // go up to the common directory
819  for ( int i = 0; i < targetElems.size(); i++ )
820  {
821  aPathElems.insert( 0, ".." );
822  }
823  }
824  else
825  {
826  // let it start with . nevertheless,
827  // so relative path always start with either ./ or ../
828  aPathElems.insert( 0, "." );
829  }
830 
831  return aPathElems.join( "/" );
832 }
833 
835 {
836  // relative path should always start with ./ or ../
837  if ( !rpath.startsWith( "./" ) && !rpath.startsWith( "../" ) )
838  {
839  return rpath;
840  }
841 
842 #if defined(Q_OS_WIN)
843  rpath.replace( "\\", "/" );
844  targetPath.replace( "\\", "/" );
845 
846  bool uncPath = targetPath.startsWith( "//" );
847 #endif
848 
849  QStringList srcElems = rpath.split( "/", QString::SkipEmptyParts );
850  QStringList targetElems = targetPath.split( "/", QString::SkipEmptyParts );
851 
852 #if defined(Q_OS_WIN)
853  if ( uncPath )
854  {
855  targetElems.insert( 0, "" );
856  targetElems.insert( 0, "" );
857  }
858 #endif
859 
860  // append source path elements
861  targetElems << srcElems;
862  targetElems.removeAll( "." );
863 
864  // resolve ..
865  int pos;
866  while (( pos = targetElems.indexOf( ".." ) ) > 0 )
867  {
868  // remove preceding element and ..
869  targetElems.removeAt( pos - 1 );
870  targetElems.removeAt( pos - 1 );
871  }
872 
873 #if !defined(Q_OS_WIN)
874  // make path absolute
875  targetElems.prepend( "" );
876 #endif
877 
878  return targetElems.join( "/" );
879 }
880 
882 {
883  if ( ABISYM( mGdalSkipList ).contains( theDriver ) || theDriver.isEmpty() )
884  {
885  return;
886  }
887  ABISYM( mGdalSkipList ) << theDriver;
889 }
890 
892 {
893  if ( !ABISYM( mGdalSkipList ).contains( theDriver ) )
894  {
895  return;
896  }
897  int myPos = ABISYM( mGdalSkipList ).indexOf( theDriver );
898  if ( myPos >= 0 )
899  {
900  ABISYM( mGdalSkipList ).removeAt( myPos );
901  }
903 }
904 
906 {
907  ABISYM( mGdalSkipList ).removeDuplicates();
908  QString myDriverList = ABISYM( mGdalSkipList ).join( " " );
909  QgsDebugMsg( "Gdal Skipped driver list set to:" );
910  QgsDebugMsg( myDriverList );
911  CPLSetConfigOption( "GDAL_SKIP", myDriverList.toUtf8() );
912  GDALAllRegister(); //to update driver list and skip missing ones
913 }
914 
915 bool QgsApplication::createDB( QString *errorMessage )
916 {
917  // set a working directory up for gdal to write .aux.xml files into
918  // for cases where the raster dir is read only to the user
919  // if the env var is already set it will be used preferentially
920  QString myPamPath = qgisSettingsDirPath() + QString( "gdal_pam/" );
921  QDir myDir( myPamPath );
922  if ( !myDir.exists() )
923  {
924  myDir.mkpath( myPamPath ); //fail silently
925  }
926 
927 #if defined(Q_OS_WIN32) || defined(WIN32)
928  CPLSetConfigOption( "GDAL_PAM_PROXY_DIR", myPamPath.toUtf8() );
929 #else
930  //under other OS's we use an environment var so the user can
931  //override the path if he likes
932  int myChangeFlag = 0; //whether we want to force the env var to change
933  setenv( "GDAL_PAM_PROXY_DIR", myPamPath.toUtf8(), myChangeFlag );
934 #endif
935 
936  // Check qgis.db and make private copy if necessary
937  QFile qgisPrivateDbFile( QgsApplication::qgisUserDbFilePath() );
938 
939  // first we look for ~/.qgis/qgis.db
940  if ( !qgisPrivateDbFile.exists() )
941  {
942  // if it doesnt exist we copy it in from the global resources dir
943  QString qgisMasterDbFileName = QgsApplication::qgisMasterDbFilePath();
944  QFile masterFile( qgisMasterDbFileName );
945 
946  // Must be sure there is destination directory ~/.qgis
948 
949  //now copy the master file into the users .qgis dir
950  bool isDbFileCopied = masterFile.copy( qgisPrivateDbFile.fileName() );
951 
952  if ( !isDbFileCopied )
953  {
954  if ( errorMessage )
955  {
956  *errorMessage = tr( "[ERROR] Can not make qgis.db private copy" );
957  }
958  return false;
959  }
960  }
961  else
962  {
963  // migrate if necessary
964  sqlite3 *db;
965  if ( sqlite3_open( QgsApplication::qgisUserDbFilePath().toUtf8().constData(), &db ) != SQLITE_OK )
966  {
967  if ( errorMessage )
968  {
969  *errorMessage = tr( "Could not open qgis.db" );
970  }
971  return false;
972  }
973 
974  char *errmsg;
975  int res = sqlite3_exec( db, "SELECT epsg FROM tbl_srs LIMIT 0", 0, 0, &errmsg );
976  if ( res == SQLITE_OK )
977  {
978  // epsg column exists => need migration
979  if ( sqlite3_exec( db,
980  "ALTER TABLE tbl_srs RENAME TO tbl_srs_bak;"
981  "CREATE TABLE tbl_srs ("
982  "srs_id INTEGER PRIMARY KEY,"
983  "description text NOT NULL,"
984  "projection_acronym text NOT NULL,"
985  "ellipsoid_acronym NOT NULL,"
986  "parameters text NOT NULL,"
987  "srid integer,"
988  "auth_name varchar,"
989  "auth_id varchar,"
990  "is_geo integer NOT NULL,"
991  "deprecated boolean);"
992  "CREATE INDEX idx_srsauthid on tbl_srs(auth_name,auth_id);"
993  "INSERT INTO tbl_srs(srs_id,description,projection_acronym,ellipsoid_acronym,parameters,srid,auth_name,auth_id,is_geo,deprecated) SELECT srs_id,description,projection_acronym,ellipsoid_acronym,parameters,srid,'','',is_geo,0 FROM tbl_srs_bak;"
994  "DROP TABLE tbl_srs_bak", 0, 0, &errmsg ) != SQLITE_OK
995  )
996  {
997  if ( errorMessage )
998  {
999  *errorMessage = tr( "Migration of private qgis.db failed.\n%1" ).arg( QString::fromUtf8( errmsg ) );
1000  }
1001  sqlite3_free( errmsg );
1002  sqlite3_close( db );
1003  return false;
1004  }
1005  }
1006  else
1007  {
1008  sqlite3_free( errmsg );
1009  }
1010 
1011  if ( sqlite3_exec( db, "DROP VIEW vw_srs", 0, 0, &errmsg ) != SQLITE_OK )
1012  {
1013  QgsDebugMsg( QString( "vw_srs didn't exists in private qgis.db: %1" ).arg( errmsg ) );
1014  }
1015 
1016  if ( sqlite3_exec( db,
1017  "CREATE VIEW vw_srs AS"
1018  " SELECT"
1019  " a.description AS description"
1020  ",a.srs_id AS srs_id"
1021  ",a.is_geo AS is_geo"
1022  ",coalesce(b.name,a.projection_acronym) AS name"
1023  ",a.parameters AS parameters"
1024  ",a.auth_name AS auth_name"
1025  ",a.auth_id AS auth_id"
1026  ",a.deprecated AS deprecated"
1027  " FROM tbl_srs a"
1028  " LEFT OUTER JOIN tbl_projection b ON a.projection_acronym=b.acronym"
1029  " ORDER BY coalesce(b.name,a.projection_acronym),a.description", 0, 0, &errmsg ) != SQLITE_OK
1030  )
1031  {
1032  if ( errorMessage )
1033  {
1034  *errorMessage = tr( "Update of view in private qgis.db failed.\n%1" ).arg( QString::fromUtf8( errmsg ) );
1035  }
1036  sqlite3_free( errmsg );
1037  sqlite3_close( db );
1038  return false;
1039  }
1040 
1041  sqlite3_close( db );
1042  }
1043  return true;
1044 }
1045 
1046 void QgsApplication::setMaxThreads( int maxThreads )
1047 {
1048  QgsDebugMsg( QString( "maxThreads: %1" ).arg( maxThreads ) );
1049 
1050  // make sure value is between 1 and #cores, if not set to -1 (use #cores)
1051  // 0 could be used to disable any parallel processing
1052  if ( maxThreads < 1 || maxThreads > QThread::idealThreadCount() )
1053  maxThreads = -1;
1054 
1055  // save value
1056  ABISYM( mMaxThreads ) = maxThreads;
1057 
1058  // if -1 use #cores
1059  if ( maxThreads == -1 )
1060  maxThreads = QThread::idealThreadCount();
1061 
1062  // set max thread count in QThreadPool
1064  QgsDebugMsg( QString( "set QThreadPool max thread count to %1" ).arg( QThreadPool::globalInstance()->maxThreadCount() ) );
1065 }
1066 
static const QString pkgDataPath()
Returns the common root path of all application data directories.
static void init(QString customConfigPath=QString())
This method initialises paths etc for QGIS.
QString fromAscii(const char *str, int size)
static const QString i18nPath()
Returns the path to the translation directory.
static const QString contributorsFilePath()
Returns the path to the contributors file.
int indexOf(QChar ch, int from, Qt::CaseSensitivity cs) const
enum QgsApplication::ENDIAN endian_t
constants for endian-ness
Type type() const
static const QString qgisMasterDbFilePath()
Returns the path to the master qgis.db file.
static const QString libexecPath()
Returns the path with utility executables (help viewer, crssync, ...)
static const QString activeThemePath()
Returns the path to the currently active theme directory.
QStringList systemEnvironment()
QStringList ABISYM(QgsApplication::mFileOpenEventList)
static const QString prefixPath()
Returns the path to the application prefix directory.
static const QString helpAppPath()
Returns the path to the help application.
static const QStringList svgPaths()
Returns the pathes to svg directories.
virtual bool event(QEvent *event) override
Watch for QFileOpenEvent.
QString name() const
static const QString licenceFilePath()
Returns the path to the licence file.
static QgsProviderRegistry * instance(QString pluginPath=QString::null)
means of accessing canonical single instance
static void setPrefixPath(const QString &thePrefixPath, bool useDefaultPaths=false)
Alters prefix path - used by 3rd party apps.
#define QgsDebugMsg(str)
Definition: qgslogger.h:33
static QString iconPath(QString iconFile)
Returns path to the desired icon file.
QStringList split(const QString &sep, SplitBehavior behavior, Qt::CaseSensitivity cs) const
static const QString libraryPath()
Returns the path containing qgis_core, qgis_gui, qgispython (and other) libraries.
static QIcon getThemeIcon(const QString &theName)
Helper to get a theme icon.
void removeFirst()
QThreadPool * globalInstance()
void removeAt(int i)
void setFileName(const QString &name)
static void registerOgrDrivers()
Register OGR drivers ensuring this only happens once.
static const QString translatorsFilePath()
Returns the path to the sponsors file.
static const QString authorsFilePath()
Returns the path to the authors file.
QString join(const QString &separator) const
bool exists() const
static QString absolutePathToRelativePath(QString apath, QString targetPath)
Converts absolute path to path relative to target.
QThread * thread() const
static void setFileOpenEventReceiver(QObject *receiver)
Set the FileOpen event receiver.
static QString reportStyleSheet()
get a standard css style sheet for reports.
static int maxThreads()
Get maximum concurrent thread count.
static endian_t endian()
Returns whether this machine uses big or little endian.
QString homePath()
static const QString qgisSettingsDirPath()
Returns the path to the settings directory in user's home dir.
QChar separator()
QString tr(const char *sourceText, const char *disambiguation, int n)
static QPixmap getThemePixmap(const QString &theName)
Helper to get a theme icon as a pixmap.
bool copy(const QString &newName)
void addLibraryPath(const QString &path)
int size() const
static void applyGdalSkippedDrivers()
Apply the skipped drivers list to gdal.
QWidget * activeWindow()
bool exists() const
QString fromUtf8(const char *str, int size)
void setMaxThreadCount(int maxThreadCount)
QString tempPath()
static void setThemeName(const QString &theThemeName)
Set the active theme to the specified theme.
static const QString iconsPath()
Returns the path to the icons image directory.
virtual ~QgsApplication()
bool isEmpty() const
int removeAll(const T &value)
bool sendEvent(QObject *receiver, QEvent *event)
bool startsWith(const QString &s, Qt::CaseSensitivity cs) const
static const QString splashPath()
Returns the path to the splash screen image directory.
static const QString defaultThemePath()
Returns the path to the default theme directory.
static void setPkgDataPath(const QString &thePkgDataPath)
Alters pkg data path - used by 3rd party apps.
static void restoreGdalDriver(QString theDriver)
Sets the GDAL_SKIP environment variable to exclude the specified driver and then calls GDALDriverMana...
static const char * QGIS_ORGANIZATION_NAME
virtual bool open(QFlags< QIODevice::OpenModeFlag > mode)
static bool createDB(QString *errorMessage=0)
initialise qgis.db
static void setPluginPath(const QString &thePluginPath)
Alters plugin path - used by 3rd party apps.
static const QString defaultStyleV2Path()
Returns the path to default style (works as a starting point).
bool cdUp()
struct sqlite3 sqlite3
static void initQgis()
loads providers
static void setDefaultSvgPaths(const QStringList &pathList)
Alters default svg paths - used by 3rd party apps.
QColor lighter(int factor) const
static QString relativePathToAbsolutePath(QString rpath, QString targetPath)
Converts path relative to target to an absolute path.
static void skipGdalDriver(QString theDriver)
Sets the GDAL_SKIP environment variable to include the specified driver and then calls GDALDriverMana...
static const QString developersMapFilePath()
Returns the path to the developers map file.
QString & replace(int position, int n, QChar after)
static QString showSettings()
Convenience function to get a summary of the paths used in this application instance useful for debug...
QString what() const
Definition: qgsexception.h:35
QVariant value(const QString &key, const QVariant &defaultValue) const
static const char * QGIS_ORGANIZATION_DOMAIN
int idealThreadCount()
static QgsMapLayerRegistry * instance()
Returns the instance pointer, creating the object on the first call.
QString mid(int position, int n) const
virtual bool notify(QObject *receiver, QEvent *event) override
Catch exceptions when sending event to receiver.
static const QString donorsFilePath()
Returns the path to the donors file.
virtual bool event(QEvent *e)
QString absolutePath() const
void insert(int i, const T &value)
QThread * currentThread()
static const QString srsDbFilePath()
Returns the path to the srs.db file.
StandardButton critical(QWidget *parent, const QString &title, const QString &text, QFlags< QMessageBox::StandardButton > buttons, StandardButton defaultButton)
QString left(int n) const
static void exitQgis()
deletes provider registry and map layer registry
static const QString sponsorsFilePath()
Returns the path to the sponsors file.
int indexOf(const QRegExp &rx, int from) const
void prepend(const T &value)
iterator insert(const Key &key, const T &value)
QgsApplication(int &argc, char **argv, bool GUIenabled, QString customConfigPath=QString())
static const char * QGIS_APPLICATION_NAME
QString applicationDirPath()
virtual bool notify(QObject *receiver, QEvent *e)
static const QString qgisUserDbFilePath()
Returns the path to the user qgis.db file.
static const QString pluginPath()
Returns the path to the application plugin directory.
static const QString userStyleV2Path()
Returns the path to user's style.
static const QString themeName()
Set the active theme to the specified theme.
QString arg(qlonglong a, int fieldWidth, int base, const QChar &fillChar) const
QString toString() const
static const int QGIS_VERSION_INT
Definition: qgis.h:42
Defines a qgis exception class.
Definition: qgsexception.h:25
static void setMaxThreads(int maxThreads)
Set maximum concurrent thread count.
bool mkpath(const QString &dirPath) const
qint64 readLine(char *data, qint64 maxSize)
void preNotify(QObject *receiver, QEvent *event, bool *done)
QByteArray toUtf8() const