QGIS API Documentation  2.9.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 "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)
158  setPrefixPath( applicationDirPath(), true );
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
199  QCoreApplication::addLibraryPath( pluginPath() );
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 
211 bool QgsApplication::event( QEvent * event )
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 
326 void QgsApplication::setDefaultSvgPaths( const QStringList& pathList )
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 
361 QString QgsApplication::iconPath( QString iconFile )
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 
372 QIcon QgsApplication::getThemeIcon( const QString &theName )
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 ?
393 QPixmap QgsApplication::getThemePixmap( const QString &theName )
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 {
483  QString helpAppPath;
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 
574 const QStringList QgsApplication::svgPaths()
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 {
626  // Cleanup known singletons
631 
632  // Cleanup providers
634 }
635 
637 {
638  QString myEnvironmentVar( getenv( "QGIS_PREFIX_PATH" ) );
639  QString myState = tr( "Application state:\n"
640  "QGIS_PREFIX_PATH env var:\t\t%1\n"
641  "Prefix:\t\t%2\n"
642  "Plugin Path:\t\t%3\n"
643  "Package Data Path:\t%4\n"
644  "Active Theme Name:\t%5\n"
645  "Active Theme Path:\t%6\n"
646  "Default Theme Path:\t%7\n"
647  "SVG Search Paths:\t%8\n"
648  "User DB Path:\t%9\n" )
649  .arg( myEnvironmentVar )
650  .arg( prefixPath() )
651  .arg( pluginPath() )
652  .arg( pkgDataPath() )
653  .arg( themeName() )
654  .arg( activeThemePath() )
655  .arg( defaultThemePath() )
656  .arg( svgPaths().join( tr( "\n\t\t", "match indentation of application state" ) ) )
657  .arg( qgisMasterDbFilePath() );
658  return myState;
659 }
660 
662 {
663  //
664  // Make the style sheet desktop preferences aware by using qappliation
665  // palette as a basis for colors where appropriate
666  //
667 // QColor myColor1 = palette().highlight().color();
668  QColor myColor1( Qt::lightGray );
669  QColor myColor2 = myColor1;
670  myColor2 = myColor2.lighter( 110 ); //10% lighter
671  QString myStyle;
672  myStyle = "p.glossy{ background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, "
673  " stop: 0 " + myColor1.name() + ","
674  " stop: 0.1 " + myColor2.name() + ","
675  " stop: 0.5 " + myColor1.name() + ","
676  " stop: 0.9 " + myColor2.name() + ","
677  " stop: 1 " + myColor1.name() + ");"
678  " color: black;"
679  " padding-left: 4px;"
680  " padding-top: 20px;"
681  " padding-bottom: 8px;"
682  " border: 1px solid #6c6c6c;"
683  "}"
684  "p.subheaderglossy{ background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, "
685  " stop: 0 " + myColor1.name() + ","
686  " stop: 0.1 " + myColor2.name() + ","
687  " stop: 0.5 " + myColor1.name() + ","
688  " stop: 0.9 " + myColor2.name() + ","
689  " stop: 1 " + myColor1.name() + ");"
690  " font-weight: bold;"
691  " font-size: medium;"
692  " line-height: 1.1em;"
693  " width: 100%;"
694  " color: black;"
695  " padding-left: 4px;"
696  " padding-right: 4px;"
697  " padding-top: 20px;"
698  " padding-bottom: 8px;"
699  " border: 1px solid #6c6c6c;"
700  "}"
701  "th.glossy{ background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, "
702  " stop: 0 " + myColor1.name() + ","
703  " stop: 0.1 " + myColor2.name() + ","
704  " stop: 0.5 " + myColor1.name() + ","
705  " stop: 0.9 " + myColor2.name() + ","
706  " stop: 1 " + myColor1.name() + ");"
707  " color: black;"
708  " border: 1px solid #6c6c6c;"
709  "}"
710  ".overview{ font: 1.82em; font-weight: bold;}"
711  "body{ background: white;"
712  " color: black;"
713  " font-family: arial,sans-serif;"
714  "}"
715  "h1{ background-color: #F6F6F6;"
716  " color: #8FB171; "
717  " font-size: x-large; "
718  " font-weight: normal;"
719  " font-family: luxi serif, georgia, times new roman, times, serif;"
720  " background: none;"
721  " padding: 0.75em 0 0;"
722  " margin: 0;"
723  " line-height: 3em;"
724  "}"
725  "h2{ background-color: #F6F6F6;"
726  " color: #8FB171; "
727  " font-size: medium; "
728  " font-weight: normal;"
729  " font-family: luxi serif, georgia, times new roman, times, serif;"
730  " background: none;"
731  " padding: 0.75em 0 0;"
732  " margin: 0;"
733  " line-height: 1.1em;"
734  "}"
735  "h3{ background-color: #F6F6F6;"
736  " color: #729FCF;"
737  " font-family: luxi serif, georgia, times new roman, times, serif;"
738  " font-weight: bold;"
739  " font-size: large;"
740  " text-align: right;"
741  " border-bottom: 5px solid #DCEB5C;"
742  "}"
743  "h4{ background-color: #F6F6F6;"
744  " color: #729FCF;"
745  " font-family: luxi serif, georgia, times new roman, times, serif;"
746  " font-weight: bold;"
747  " font-size: medium;"
748  " text-align: right;"
749  "}"
750  "h5{ background-color: #F6F6F6;"
751  " color: #729FCF;"
752  " font-family: luxi serif, georgia, times new roman, times, serif;"
753  " font-weight: bold;"
754  " font-size: small;"
755  " text-align: right;"
756  "}"
757  "a{ color: #729FCF;"
758  " font-family: arial,sans-serif;"
759  " font-size: small;"
760  "}"
761  "label{ background-color: #FFFFCC;"
762  " border: 1px solid black;"
763  " margin: 1px;"
764  " padding: 0px 3px; "
765  " font-size: small;"
766  "}";
767  return myStyle;
768 }
769 
771 {
772  if ( 0 >= OGRGetDriverCount() )
773  {
774  OGRRegisterAll();
775  }
776 }
777 
778 QString QgsApplication::absolutePathToRelativePath( QString aPath, QString targetPath )
779 {
780 #if defined( Q_OS_WIN )
781  const Qt::CaseSensitivity cs = Qt::CaseInsensitive;
782 
783  aPath.replace( "\\", "/" );
784  if ( aPath.startsWith( "//" ) )
785  {
786  // keep UNC prefix
787  aPath = "\\\\" + aPath.mid( 2 );
788  }
789 
790  targetPath.replace( "\\", "/" );
791  if ( targetPath.startsWith( "//" ) )
792  {
793  // keep UNC prefix
794  targetPath = "\\\\" + targetPath.mid( 2 );
795  }
796 #else
797  const Qt::CaseSensitivity cs = Qt::CaseSensitive;
798 #endif
799 
800  QStringList targetElems = targetPath.split( "/", QString::SkipEmptyParts );
801  QStringList aPathElems = aPath.split( "/", QString::SkipEmptyParts );
802 
803  targetElems.removeAll( "." );
804  aPathElems.removeAll( "." );
805 
806  // remove common part
807  int n = 0;
808  while ( aPathElems.size() > 0 &&
809  targetElems.size() > 0 &&
810  aPathElems[0].compare( targetElems[0], cs ) == 0 )
811  {
812  aPathElems.removeFirst();
813  targetElems.removeFirst();
814  n++;
815  }
816 
817  if ( n == 0 )
818  {
819  // no common parts; might not even be a file
820  return aPath;
821  }
822 
823  if ( targetElems.size() > 0 )
824  {
825  // go up to the common directory
826  for ( int i = 0; i < targetElems.size(); i++ )
827  {
828  aPathElems.insert( 0, ".." );
829  }
830  }
831  else
832  {
833  // let it start with . nevertheless,
834  // so relative path always start with either ./ or ../
835  aPathElems.insert( 0, "." );
836  }
837 
838  return aPathElems.join( "/" );
839 }
840 
841 QString QgsApplication::relativePathToAbsolutePath( QString rpath, QString targetPath )
842 {
843  // relative path should always start with ./ or ../
844  if ( !rpath.startsWith( "./" ) && !rpath.startsWith( "../" ) )
845  {
846  return rpath;
847  }
848 
849 #if defined(Q_OS_WIN)
850  rpath.replace( "\\", "/" );
851  targetPath.replace( "\\", "/" );
852 
853  bool uncPath = targetPath.startsWith( "//" );
854 #endif
855 
856  QStringList srcElems = rpath.split( "/", QString::SkipEmptyParts );
857  QStringList targetElems = targetPath.split( "/", QString::SkipEmptyParts );
858 
859 #if defined(Q_OS_WIN)
860  if ( uncPath )
861  {
862  targetElems.insert( 0, "" );
863  targetElems.insert( 0, "" );
864  }
865 #endif
866 
867  // append source path elements
868  targetElems << srcElems;
869  targetElems.removeAll( "." );
870 
871  // resolve ..
872  int pos;
873  while (( pos = targetElems.indexOf( ".." ) ) > 0 )
874  {
875  // remove preceding element and ..
876  targetElems.removeAt( pos - 1 );
877  targetElems.removeAt( pos - 1 );
878  }
879 
880 #if !defined(Q_OS_WIN)
881  // make path absolute
882  targetElems.prepend( "" );
883 #endif
884 
885  return targetElems.join( "/" );
886 }
887 
888 void QgsApplication::skipGdalDriver( QString theDriver )
889 {
890  if ( ABISYM( mGdalSkipList ).contains( theDriver ) || theDriver.isEmpty() )
891  {
892  return;
893  }
894  ABISYM( mGdalSkipList ) << theDriver;
896 }
897 
898 void QgsApplication::restoreGdalDriver( QString theDriver )
899 {
900  if ( !ABISYM( mGdalSkipList ).contains( theDriver ) )
901  {
902  return;
903  }
904  int myPos = ABISYM( mGdalSkipList ).indexOf( theDriver );
905  if ( myPos >= 0 )
906  {
907  ABISYM( mGdalSkipList ).removeAt( myPos );
908  }
910 }
911 
913 {
914  ABISYM( mGdalSkipList ).removeDuplicates();
915  QString myDriverList = ABISYM( mGdalSkipList ).join( " " );
916  QgsDebugMsg( "Gdal Skipped driver list set to:" );
917  QgsDebugMsg( myDriverList );
918  CPLSetConfigOption( "GDAL_SKIP", myDriverList.toUtf8() );
919  GDALAllRegister(); //to update driver list and skip missing ones
920 }
921 
922 bool QgsApplication::createDB( QString *errorMessage )
923 {
924  // set a working directory up for gdal to write .aux.xml files into
925  // for cases where the raster dir is read only to the user
926  // if the env var is already set it will be used preferentially
927  QString myPamPath = qgisSettingsDirPath() + QString( "gdal_pam/" );
928  QDir myDir( myPamPath );
929  if ( !myDir.exists() )
930  {
931  myDir.mkpath( myPamPath ); //fail silently
932  }
933 
934 #if defined(Q_OS_WIN32) || defined(WIN32)
935  CPLSetConfigOption( "GDAL_PAM_PROXY_DIR", myPamPath.toUtf8() );
936 #else
937  //under other OS's we use an environment var so the user can
938  //override the path if he likes
939  int myChangeFlag = 0; //whether we want to force the env var to change
940  setenv( "GDAL_PAM_PROXY_DIR", myPamPath.toUtf8(), myChangeFlag );
941 #endif
942 
943  // Check qgis.db and make private copy if necessary
944  QFile qgisPrivateDbFile( QgsApplication::qgisUserDbFilePath() );
945 
946  // first we look for ~/.qgis/qgis.db
947  if ( !qgisPrivateDbFile.exists() )
948  {
949  // if it doesnt exist we copy it in from the global resources dir
950  QString qgisMasterDbFileName = QgsApplication::qgisMasterDbFilePath();
951  QFile masterFile( qgisMasterDbFileName );
952 
953  // Must be sure there is destination directory ~/.qgis
954  QDir().mkpath( QgsApplication::qgisSettingsDirPath() );
955 
956  //now copy the master file into the users .qgis dir
957  bool isDbFileCopied = masterFile.copy( qgisPrivateDbFile.fileName() );
958 
959  if ( !isDbFileCopied )
960  {
961  if ( errorMessage )
962  {
963  *errorMessage = tr( "[ERROR] Can not make qgis.db private copy" );
964  }
965  return false;
966  }
967  }
968  else
969  {
970  // migrate if necessary
971  sqlite3 *db;
972  if ( sqlite3_open( QgsApplication::qgisUserDbFilePath().toUtf8().constData(), &db ) != SQLITE_OK )
973  {
974  if ( errorMessage )
975  {
976  *errorMessage = tr( "Could not open qgis.db" );
977  }
978  return false;
979  }
980 
981  char *errmsg;
982  int res = sqlite3_exec( db, "SELECT epsg FROM tbl_srs LIMIT 0", 0, 0, &errmsg );
983  if ( res == SQLITE_OK )
984  {
985  // epsg column exists => need migration
986  if ( sqlite3_exec( db,
987  "ALTER TABLE tbl_srs RENAME TO tbl_srs_bak;"
988  "CREATE TABLE tbl_srs ("
989  "srs_id INTEGER PRIMARY KEY,"
990  "description text NOT NULL,"
991  "projection_acronym text NOT NULL,"
992  "ellipsoid_acronym NOT NULL,"
993  "parameters text NOT NULL,"
994  "srid integer,"
995  "auth_name varchar,"
996  "auth_id varchar,"
997  "is_geo integer NOT NULL,"
998  "deprecated boolean);"
999  "CREATE INDEX idx_srsauthid on tbl_srs(auth_name,auth_id);"
1000  "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;"
1001  "DROP TABLE tbl_srs_bak", 0, 0, &errmsg ) != SQLITE_OK
1002  )
1003  {
1004  if ( errorMessage )
1005  {
1006  *errorMessage = tr( "Migration of private qgis.db failed.\n%1" ).arg( QString::fromUtf8( errmsg ) );
1007  }
1008  sqlite3_free( errmsg );
1009  sqlite3_close( db );
1010  return false;
1011  }
1012  }
1013  else
1014  {
1015  sqlite3_free( errmsg );
1016  }
1017 
1018  if ( sqlite3_exec( db, "DROP VIEW vw_srs", 0, 0, &errmsg ) != SQLITE_OK )
1019  {
1020  QgsDebugMsg( QString( "vw_srs didn't exists in private qgis.db: %1" ).arg( errmsg ) );
1021  }
1022 
1023  if ( sqlite3_exec( db,
1024  "CREATE VIEW vw_srs AS"
1025  " SELECT"
1026  " a.description AS description"
1027  ",a.srs_id AS srs_id"
1028  ",a.is_geo AS is_geo"
1029  ",coalesce(b.name,a.projection_acronym) AS name"
1030  ",a.parameters AS parameters"
1031  ",a.auth_name AS auth_name"
1032  ",a.auth_id AS auth_id"
1033  ",a.deprecated AS deprecated"
1034  " FROM tbl_srs a"
1035  " LEFT OUTER JOIN tbl_projection b ON a.projection_acronym=b.acronym"
1036  " ORDER BY coalesce(b.name,a.projection_acronym),a.description", 0, 0, &errmsg ) != SQLITE_OK
1037  )
1038  {
1039  if ( errorMessage )
1040  {
1041  *errorMessage = tr( "Update of view in private qgis.db failed.\n%1" ).arg( QString::fromUtf8( errmsg ) );
1042  }
1043  sqlite3_free( errmsg );
1044  sqlite3_close( db );
1045  return false;
1046  }
1047 
1048  sqlite3_close( db );
1049  }
1050  return true;
1051 }
1052 
1053 void QgsApplication::setMaxThreads( int maxThreads )
1054 {
1055  QgsDebugMsg( QString( "maxThreads: %1" ).arg( maxThreads ) );
1056 
1057  // make sure value is between 1 and #cores, if not set to -1 (use #cores)
1058  // 0 could be used to disable any parallel processing
1059  if ( maxThreads < 1 || maxThreads > QThread::idealThreadCount() )
1060  maxThreads = -1;
1061 
1062  // save value
1063  ABISYM( mMaxThreads ) = maxThreads;
1064 
1065  // if -1 use #cores
1066  if ( maxThreads == -1 )
1067  maxThreads = QThread::idealThreadCount();
1068 
1069  // set max thread count in QThreadPool
1070  QThreadPool::globalInstance()->setMaxThreadCount( maxThreads );
1071  QgsDebugMsg( QString( "set QThreadPool max thread count to %1" ).arg( QThreadPool::globalInstance()->maxThreadCount() ) );
1072 }
1073 
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.
virtual bool event(QEvent *event) override
Watch for QFileOpenEvent.
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 QgsMapLayerRegistry * instance()
Definition: qgssingleton.h:23
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.
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 const QString developersMapFilePath()
Returns the path to the developers map file.
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
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.
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
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)