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