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"
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_OS_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_OS_MACX) || defined(Q_OS_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  static bool once = true;
335  if ( once )
336  qWarning( "!!! prefix path was requested, but it is not valid - we do not run from installed path !!!" );
337  once = false;
338  }
339 
340  return ABISYM( mPrefixPath );
341 }
343 {
344  return ABISYM( mPluginPath );
345 }
347 {
348  return ABISYM( mPkgDataPath );
349 }
351 {
352  return ":/images/themes/default/";
353 }
355 {
356  return ":/images/themes/" + themeName() + "/";
357 }
358 
359 
360 QString QgsApplication::iconPath( QString iconFile )
361 {
362  // try active theme
363  QString path = activeThemePath();
364  if ( QFile::exists( path + iconFile ) )
365  return path + iconFile;
366 
367  // use default theme
368  return defaultThemePath() + iconFile;
369 }
370 
371 QIcon QgsApplication::getThemeIcon( const QString &theName )
372 {
373  QString myPreferredPath = activeThemePath() + QDir::separator() + theName;
374  QString myDefaultPath = defaultThemePath() + QDir::separator() + theName;
375  if ( QFile::exists( myPreferredPath ) )
376  {
377  return QIcon( myPreferredPath );
378  }
379  else if ( QFile::exists( myDefaultPath ) )
380  {
381  //could still return an empty icon if it
382  //doesnt exist in the default theme either!
383  return QIcon( myDefaultPath );
384  }
385  else
386  {
387  return QIcon();
388  }
389 }
390 
391 // TODO: add some caching mechanism ?
392 QPixmap QgsApplication::getThemePixmap( const QString &theName )
393 {
394  QString myPreferredPath = activeThemePath() + QDir::separator() + theName;
395  QString myDefaultPath = defaultThemePath() + QDir::separator() + theName;
396  if ( QFile::exists( myPreferredPath ) )
397  {
398  return QPixmap( myPreferredPath );
399  }
400  else
401  {
402  //could still return an empty icon if it
403  //doesnt exist in the default theme either!
404  return QPixmap( myDefaultPath );
405  }
406 }
407 
411 void QgsApplication::setThemeName( const QString &theThemeName )
412 {
413  QString myPath = ":/images/themes/" + theThemeName + "/";
414  //check it exists and if not roll back to default theme
415  if ( QFile::exists( myPath ) )
416  {
417  ABISYM( mThemeName ) = theThemeName;
418  }
419  else
420  {
421  ABISYM( mThemeName ) = "default";
422  }
423 }
428 {
429  return ABISYM( mThemeName );
430 }
435 {
436  return ABISYM( mPkgDataPath ) + QString( "/doc/AUTHORS" );
437 }
442 {
443  return ABISYM( mPkgDataPath ) + QString( "/doc/CONTRIBUTORS" );
444 }
446 {
447  return ABISYM( mPkgDataPath ) + QString( "/doc/developersmap.html" );
448 }
453 {
454  return ABISYM( mPkgDataPath ) + QString( "/doc/SPONSORS" );
455 }
456 
461 {
462  return ABISYM( mPkgDataPath ) + QString( "/doc/DONORS" );
463 }
464 
467 {
468  return ABISYM( mPkgDataPath ) + QString( "/doc/TRANSLATORS" );
469 }
470 
473 {
474  return ABISYM( mPkgDataPath ) + QString( "/doc/LICENSE" );
475 }
476 
481 {
482  QString helpAppPath;
483 #ifdef Q_OS_MACX
484  helpAppPath = applicationDirPath() + "/bin/qgis_help.app/Contents/MacOS";
485 #else
486  helpAppPath = libexecPath();
487 #endif
488  helpAppPath += "/qgis_help";
489 #ifdef Q_OS_WIN
490  helpAppPath += ".exe";
491 #endif
492  return helpAppPath;
493 }
498 {
499  if ( ABISYM( mRunningFromBuildDir ) )
500  return ABISYM( mBuildOutputPath ) + QString( "/i18n" );
501  else
502  return ABISYM( mPkgDataPath ) + QString( "/i18n/" );
503 }
504 
509 {
510  return ABISYM( mPkgDataPath ) + QString( "/resources/qgis.db" );
511 }
512 
517 {
518  return ABISYM( mConfigPath );
519 }
520 
525 {
526  return qgisSettingsDirPath() + QString( "qgis.db" );
527 }
528 
533 {
534  return QString( ":/images/splash/" );
535 }
536 
541 {
542  return ABISYM( mPkgDataPath ) + QString( "/images/icons/" );
543 }
548 {
549  if ( ABISYM( mRunningFromBuildDir ) )
550  {
551  QString tempCopy = QDir::tempPath() + "/srs.db";
552 
553  if ( !QFile( tempCopy ).exists() )
554  {
555  QFile f( ABISYM( mPkgDataPath ) + "/resources/srs.db" );
556  if ( !f.copy( tempCopy ) )
557  {
558  qFatal( "Could not create temporary copy" );
559  }
560  }
561 
562  return tempCopy;
563  }
564  else
565  {
566  return ABISYM( mPkgDataPath ) + QString( "/resources/srs.db" );
567  }
568 }
569 
573 const QStringList QgsApplication::svgPaths()
574 {
575  //local directories to search when looking for an SVG with a given basename
576  //defined by user in options dialog
577  QSettings settings;
578  QStringList myPathList;
579  QString myPaths = settings.value( "svg/searchPathsForSVG", "" ).toString();
580  if ( !myPaths.isEmpty() )
581  {
582  myPathList = myPaths.split( "|" );
583  }
584 
585  myPathList << ABISYM( mDefaultSvgPaths );
586  return myPathList;
587 }
588 
590 {
591  return qgisSettingsDirPath() + QString( "symbology-ng-style.db" );
592 }
593 
595 {
596  return ABISYM( mPkgDataPath ) + QString( "/resources/symbology-ng-style.db" );
597 }
598 
600 {
601  return ABISYM( mLibraryPath );
602 }
603 
605 {
606  return ABISYM( mLibexecPath );
607 }
608 
610 {
611  return ( htonl( 1 ) == 1 ) ? XDR : NDR;
612 }
613 
615 {
616  // set the provider plugin path (this creates provider registry)
618 
619  // create map layer registry if doesn't exist
621 }
622 
624 {
625  // Cleanup known singletons
629 
630  // Cleanup providers
632 }
633 
635 {
636  QString myEnvironmentVar( getenv( "QGIS_PREFIX_PATH" ) );
637  QString myState = tr( "Application state:\n"
638  "QGIS_PREFIX_PATH env var:\t\t%1\n"
639  "Prefix:\t\t%2\n"
640  "Plugin Path:\t\t%3\n"
641  "Package Data Path:\t%4\n"
642  "Active Theme Name:\t%5\n"
643  "Active Theme Path:\t%6\n"
644  "Default Theme Path:\t%7\n"
645  "SVG Search Paths:\t%8\n"
646  "User DB Path:\t%9\n" )
647  .arg( myEnvironmentVar )
648  .arg( prefixPath() )
649  .arg( pluginPath() )
650  .arg( pkgDataPath() )
651  .arg( themeName() )
652  .arg( activeThemePath() )
653  .arg( defaultThemePath() )
654  .arg( svgPaths().join( tr( "\n\t\t", "match indentation of application state" ) ) )
655  .arg( qgisMasterDbFilePath() );
656  return myState;
657 }
658 
660 {
661  //
662  // Make the style sheet desktop preferences aware by using qappliation
663  // palette as a basis for colors where appropriate
664  //
665 // QColor myColor1 = palette().highlight().color();
666  QColor myColor1( Qt::lightGray );
667  QColor myColor2 = myColor1;
668  myColor2 = myColor2.lighter( 110 ); //10% lighter
669  QString myStyle;
670  myStyle = "p.glossy{ background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, "
671  " stop: 0 " + myColor1.name() + ","
672  " stop: 0.1 " + myColor2.name() + ","
673  " stop: 0.5 " + myColor1.name() + ","
674  " stop: 0.9 " + myColor2.name() + ","
675  " stop: 1 " + myColor1.name() + ");"
676  " color: black;"
677  " padding-left: 4px;"
678  " padding-top: 20px;"
679  " padding-bottom: 8px;"
680  " border: 1px solid #6c6c6c;"
681  "}"
682  "p.subheaderglossy{ 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  " font-weight: bold;"
689  " font-size: medium;"
690  " line-height: 1.1em;"
691  " width: 100%;"
692  " color: black;"
693  " padding-left: 4px;"
694  " padding-right: 4px;"
695  " padding-top: 20px;"
696  " padding-bottom: 8px;"
697  " border: 1px solid #6c6c6c;"
698  "}"
699  "th.glossy{ background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, "
700  " stop: 0 " + myColor1.name() + ","
701  " stop: 0.1 " + myColor2.name() + ","
702  " stop: 0.5 " + myColor1.name() + ","
703  " stop: 0.9 " + myColor2.name() + ","
704  " stop: 1 " + myColor1.name() + ");"
705  " color: black;"
706  " border: 1px solid #6c6c6c;"
707  "}"
708  ".overview{ font: 1.82em; font-weight: bold;}"
709  "body{ background: white;"
710  " color: black;"
711  " font-family: arial,sans-serif;"
712  "}"
713  "h1{ background-color: #F6F6F6;"
714  " color: #8FB171; "
715  " font-size: x-large; "
716  " font-weight: normal;"
717  " font-family: luxi serif, georgia, times new roman, times, serif;"
718  " background: none;"
719  " padding: 0.75em 0 0;"
720  " margin: 0;"
721  " line-height: 3em;"
722  "}"
723  "h2{ background-color: #F6F6F6;"
724  " color: #8FB171; "
725  " font-size: medium; "
726  " font-weight: normal;"
727  " font-family: luxi serif, georgia, times new roman, times, serif;"
728  " background: none;"
729  " padding: 0.75em 0 0;"
730  " margin: 0;"
731  " line-height: 1.1em;"
732  "}"
733  "h3{ background-color: #F6F6F6;"
734  " color: #729FCF;"
735  " font-family: luxi serif, georgia, times new roman, times, serif;"
736  " font-weight: bold;"
737  " font-size: large;"
738  " text-align: right;"
739  " border-bottom: 5px solid #DCEB5C;"
740  "}"
741  "h4{ background-color: #F6F6F6;"
742  " color: #729FCF;"
743  " font-family: luxi serif, georgia, times new roman, times, serif;"
744  " font-weight: bold;"
745  " font-size: medium;"
746  " text-align: right;"
747  "}"
748  "h5{ background-color: #F6F6F6;"
749  " color: #729FCF;"
750  " font-family: luxi serif, georgia, times new roman, times, serif;"
751  " font-weight: bold;"
752  " font-size: small;"
753  " text-align: right;"
754  "}"
755  "a{ color: #729FCF;"
756  " font-family: arial,sans-serif;"
757  " font-size: small;"
758  "}"
759  "label{ background-color: #FFFFCC;"
760  " border: 1px solid black;"
761  " margin: 1px;"
762  " padding: 0px 3px; "
763  " font-size: small;"
764  "}";
765  return myStyle;
766 }
767 
769 {
770  if ( 0 >= OGRGetDriverCount() )
771  {
772  OGRRegisterAll();
773  }
774 }
775 
776 QString QgsApplication::absolutePathToRelativePath( QString aPath, QString targetPath )
777 {
778 #if defined( Q_OS_WIN )
779  const Qt::CaseSensitivity cs = Qt::CaseInsensitive;
780 
781  aPath.replace( "\\", "/" );
782  if ( aPath.startsWith( "//" ) )
783  {
784  // keep UNC prefix
785  aPath = "\\\\" + aPath.mid( 2 );
786  }
787 
788  targetPath.replace( "\\", "/" );
789  if ( targetPath.startsWith( "//" ) )
790  {
791  // keep UNC prefix
792  targetPath = "\\\\" + targetPath.mid( 2 );
793  }
794 #else
795  const Qt::CaseSensitivity cs = Qt::CaseSensitive;
796 #endif
797 
798  QStringList targetElems = targetPath.split( "/", QString::SkipEmptyParts );
799  QStringList aPathElems = aPath.split( "/", QString::SkipEmptyParts );
800 
801  targetElems.removeAll( "." );
802  aPathElems.removeAll( "." );
803 
804  // remove common part
805  int n = 0;
806  while ( aPathElems.size() > 0 &&
807  targetElems.size() > 0 &&
808  aPathElems[0].compare( targetElems[0], cs ) == 0 )
809  {
810  aPathElems.removeFirst();
811  targetElems.removeFirst();
812  n++;
813  }
814 
815  if ( n == 0 )
816  {
817  // no common parts; might not even be a file
818  return aPath;
819  }
820 
821  if ( targetElems.size() > 0 )
822  {
823  // go up to the common directory
824  for ( int i = 0; i < targetElems.size(); i++ )
825  {
826  aPathElems.insert( 0, ".." );
827  }
828  }
829  else
830  {
831  // let it start with . nevertheless,
832  // so relative path always start with either ./ or ../
833  aPathElems.insert( 0, "." );
834  }
835 
836  return aPathElems.join( "/" );
837 }
838 
839 QString QgsApplication::relativePathToAbsolutePath( QString rpath, QString targetPath )
840 {
841  // relative path should always start with ./ or ../
842  if ( !rpath.startsWith( "./" ) && !rpath.startsWith( "../" ) )
843  {
844  return rpath;
845  }
846 
847 #if defined(Q_OS_WIN)
848  rpath.replace( "\\", "/" );
849  targetPath.replace( "\\", "/" );
850 
851  bool uncPath = targetPath.startsWith( "//" );
852 #endif
853 
854  QStringList srcElems = rpath.split( "/", QString::SkipEmptyParts );
855  QStringList targetElems = targetPath.split( "/", QString::SkipEmptyParts );
856 
857 #if defined(Q_OS_WIN)
858  if ( uncPath )
859  {
860  targetElems.insert( 0, "" );
861  targetElems.insert( 0, "" );
862  }
863 #endif
864 
865  // append source path elements
866  targetElems << srcElems;
867  targetElems.removeAll( "." );
868 
869  // resolve ..
870  int pos;
871  while (( pos = targetElems.indexOf( ".." ) ) > 0 )
872  {
873  // remove preceding element and ..
874  targetElems.removeAt( pos - 1 );
875  targetElems.removeAt( pos - 1 );
876  }
877 
878 #if !defined(Q_OS_WIN)
879  // make path absolute
880  targetElems.prepend( "" );
881 #endif
882 
883  return targetElems.join( "/" );
884 }
885 
886 void QgsApplication::skipGdalDriver( QString theDriver )
887 {
888  if ( ABISYM( mGdalSkipList ).contains( theDriver ) || theDriver.isEmpty() )
889  {
890  return;
891  }
892  ABISYM( mGdalSkipList ) << theDriver;
894 }
895 
896 void QgsApplication::restoreGdalDriver( QString theDriver )
897 {
898  if ( !ABISYM( mGdalSkipList ).contains( theDriver ) )
899  {
900  return;
901  }
902  int myPos = ABISYM( mGdalSkipList ).indexOf( theDriver );
903  if ( myPos >= 0 )
904  {
905  ABISYM( mGdalSkipList ).removeAt( myPos );
906  }
908 }
909 
911 {
912  ABISYM( mGdalSkipList ).removeDuplicates();
913  QString myDriverList = ABISYM( mGdalSkipList ).join( " " );
914  QgsDebugMsg( "Gdal Skipped driver list set to:" );
915  QgsDebugMsg( myDriverList );
916  CPLSetConfigOption( "GDAL_SKIP", myDriverList.toUtf8() );
917  GDALAllRegister(); //to update driver list and skip missing ones
918 }
919 
920 bool QgsApplication::createDB( QString *errorMessage )
921 {
922  // set a working directory up for gdal to write .aux.xml files into
923  // for cases where the raster dir is read only to the user
924  // if the env var is already set it will be used preferentially
925  QString myPamPath = qgisSettingsDirPath() + QString( "gdal_pam/" );
926  QDir myDir( myPamPath );
927  if ( !myDir.exists() )
928  {
929  myDir.mkpath( myPamPath ); //fail silently
930  }
931 
932 #if defined(Q_OS_WIN32) || defined(WIN32)
933  CPLSetConfigOption( "GDAL_PAM_PROXY_DIR", myPamPath.toUtf8() );
934 #else
935  //under other OS's we use an environment var so the user can
936  //override the path if he likes
937  int myChangeFlag = 0; //whether we want to force the env var to change
938  setenv( "GDAL_PAM_PROXY_DIR", myPamPath.toUtf8(), myChangeFlag );
939 #endif
940 
941  // Check qgis.db and make private copy if necessary
942  QFile qgisPrivateDbFile( QgsApplication::qgisUserDbFilePath() );
943 
944  // first we look for ~/.qgis/qgis.db
945  if ( !qgisPrivateDbFile.exists() )
946  {
947  // if it doesnt exist we copy it in from the global resources dir
948  QString qgisMasterDbFileName = QgsApplication::qgisMasterDbFilePath();
949  QFile masterFile( qgisMasterDbFileName );
950 
951  // Must be sure there is destination directory ~/.qgis
952  QDir().mkpath( QgsApplication::qgisSettingsDirPath() );
953 
954  //now copy the master file into the users .qgis dir
955  bool isDbFileCopied = masterFile.copy( qgisPrivateDbFile.fileName() );
956 
957  if ( !isDbFileCopied )
958  {
959  if ( errorMessage )
960  {
961  *errorMessage = tr( "[ERROR] Can not make qgis.db private copy" );
962  }
963  return false;
964  }
965  }
966  else
967  {
968  // migrate if necessary
969  sqlite3 *db;
970  if ( sqlite3_open( QgsApplication::qgisUserDbFilePath().toUtf8().constData(), &db ) != SQLITE_OK )
971  {
972  if ( errorMessage )
973  {
974  *errorMessage = tr( "Could not open qgis.db" );
975  }
976  return false;
977  }
978 
979  char *errmsg;
980  int res = sqlite3_exec( db, "SELECT epsg FROM tbl_srs LIMIT 0", 0, 0, &errmsg );
981  if ( res == SQLITE_OK )
982  {
983  // epsg column exists => need migration
984  if ( sqlite3_exec( db,
985  "ALTER TABLE tbl_srs RENAME TO tbl_srs_bak;"
986  "CREATE TABLE tbl_srs ("
987  "srs_id INTEGER PRIMARY KEY,"
988  "description text NOT NULL,"
989  "projection_acronym text NOT NULL,"
990  "ellipsoid_acronym NOT NULL,"
991  "parameters text NOT NULL,"
992  "srid integer,"
993  "auth_name varchar,"
994  "auth_id varchar,"
995  "is_geo integer NOT NULL,"
996  "deprecated boolean);"
997  "CREATE INDEX idx_srsauthid on tbl_srs(auth_name,auth_id);"
998  "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;"
999  "DROP TABLE tbl_srs_bak", 0, 0, &errmsg ) != SQLITE_OK
1000  )
1001  {
1002  if ( errorMessage )
1003  {
1004  *errorMessage = tr( "Migration of private qgis.db failed.\n%1" ).arg( QString::fromUtf8( errmsg ) );
1005  }
1006  sqlite3_free( errmsg );
1007  sqlite3_close( db );
1008  return false;
1009  }
1010  }
1011  else
1012  {
1013  sqlite3_free( errmsg );
1014  }
1015 
1016  if ( sqlite3_exec( db, "DROP VIEW vw_srs", 0, 0, &errmsg ) != SQLITE_OK )
1017  {
1018  QgsDebugMsg( QString( "vw_srs didn't exists in private qgis.db: %1" ).arg( errmsg ) );
1019  }
1020 
1021  if ( sqlite3_exec( db,
1022  "CREATE VIEW vw_srs AS"
1023  " SELECT"
1024  " a.description AS description"
1025  ",a.srs_id AS srs_id"
1026  ",a.is_geo AS is_geo"
1027  ",coalesce(b.name,a.projection_acronym) AS name"
1028  ",a.parameters AS parameters"
1029  ",a.auth_name AS auth_name"
1030  ",a.auth_id AS auth_id"
1031  ",a.deprecated AS deprecated"
1032  " FROM tbl_srs a"
1033  " LEFT OUTER JOIN tbl_projection b ON a.projection_acronym=b.acronym"
1034  " ORDER BY coalesce(b.name,a.projection_acronym),a.description", 0, 0, &errmsg ) != SQLITE_OK
1035  )
1036  {
1037  if ( errorMessage )
1038  {
1039  *errorMessage = tr( "Update of view in private qgis.db failed.\n%1" ).arg( QString::fromUtf8( errmsg ) );
1040  }
1041  sqlite3_free( errmsg );
1042  sqlite3_close( db );
1043  return false;
1044  }
1045 
1046  sqlite3_close( db );
1047  }
1048  return true;
1049 }
1050 
1051 void QgsApplication::setMaxThreads( int maxThreads )
1052 {
1053  QgsDebugMsg( QString( "maxThreads: %1" ).arg( maxThreads ) );
1054 
1055  // make sure value is between 1 and #cores, if not set to -1 (use #cores)
1056  // 0 could be used to disable any parallel processing
1057  if ( maxThreads < 1 || maxThreads > QThread::idealThreadCount() )
1058  maxThreads = -1;
1059 
1060  // save value
1061  ABISYM( mMaxThreads ) = maxThreads;
1062 
1063  // if -1 use #cores
1064  if ( maxThreads == -1 )
1065  maxThreads = QThread::idealThreadCount();
1066 
1067  // set max thread count in QThreadPool
1068  QThreadPool::globalInstance()->setMaxThreadCount( maxThreads );
1069  QgsDebugMsg( QString( "set QThreadPool max thread count to %1" ).arg( QThreadPool::globalInstance()->maxThreadCount() ) );
1070 }
1071 
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)