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