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