QGIS API Documentation  2.11.0-Master
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
qgsapplication.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsapplication.cpp - Accessors for application-wide data
3  --------------------------------------
4  Date : 02-Jan-2006
5  Copyright : (C) 2006 by Tom Elwertowski
6  Email : telwertowski at users dot sourceforge dot net
7  ***************************************************************************
8  * *
9  * This program is free software; you can redistribute it and/or modify *
10  * it under the terms of the GNU General Public License as published by *
11  * the Free Software Foundation; either version 2 of the License, or *
12  * (at your option) any later version. *
13  * *
14  ***************************************************************************/
15 
16 #include "qgsapplication.h"
17 #include "qgscrscache.h"
19 #include "qgsexception.h"
20 #include "qgsgeometry.h"
21 #include "qgslogger.h"
22 #include "qgsmaplayerregistry.h"
24 #include "qgsproviderregistry.h"
25 #include "qgsexpression.h"
26 
27 #include <QDir>
28 #include <QFile>
29 #include <QFileOpenEvent>
30 #include <QMessageBox>
31 #include <QPalette>
32 #include <QProcess>
33 #include <QSettings>
34 #include <QIcon>
35 #include <QPixmap>
36 #include <QThreadPool>
37 
38 #ifndef Q_OS_WIN
39 #include <netinet/in.h>
40 #else
41 #include <winsock.h>
42 #endif
43 
44 #include "qgsconfig.h"
45 
46 #include <gdal.h>
47 #include <ogr_api.h>
48 #include <cpl_conv.h> // for setting gdal options
49 #include <sqlite3.h>
50 
51 QObject * ABISYM( QgsApplication::mFileOpenEventReceiver );
52 QStringList ABISYM( QgsApplication::mFileOpenEventList );
53 QString ABISYM( QgsApplication::mPrefixPath );
54 QString ABISYM( QgsApplication::mPluginPath );
55 QString ABISYM( QgsApplication::mPkgDataPath );
56 QString ABISYM( QgsApplication::mLibraryPath );
57 QString ABISYM( QgsApplication::mLibexecPath );
58 QString ABISYM( QgsApplication::mThemeName );
59 QString ABISYM( QgsApplication::mUIThemeName );
60 QStringList ABISYM( QgsApplication::mDefaultSvgPaths );
61 QMap<QString, QString> ABISYM( QgsApplication::mSystemEnvVars );
62 QString ABISYM( QgsApplication::mConfigPath );
63 bool ABISYM( QgsApplication::mRunningFromBuildDir ) = false;
64 QString ABISYM( QgsApplication::mBuildSourcePath );
65 #ifdef _MSC_VER
66 QString ABISYM( QgsApplication::mCfgIntDir );
67 #endif
68 QString ABISYM( QgsApplication::mBuildOutputPath );
69 QStringList ABISYM( QgsApplication::mGdalSkipList );
70 int ABISYM( QgsApplication::mMaxThreads );
71 
72 const char* QgsApplication::QGIS_ORGANIZATION_NAME = "QGIS";
73 const char* QgsApplication::QGIS_ORGANIZATION_DOMAIN = "qgis.org";
74 const char* QgsApplication::QGIS_APPLICATION_NAME = "QGIS2";
75 
89 QgsApplication::QgsApplication( int & argc, char ** argv, bool GUIenabled, QString customConfigPath )
90  : QApplication( argc, argv, GUIenabled )
91 {
92  init( customConfigPath ); // init can also be called directly by e.g. unit tests that don't inherit QApplication.
93 }
94 
95 void QgsApplication::init( QString customConfigPath )
96 {
97  if ( customConfigPath.isEmpty() )
98  {
99  if ( getenv( "QGIS_CUSTOM_CONFIG_PATH" ) )
100  {
101  customConfigPath = getenv( "QGIS_CUSTOM_CONFIG_PATH" );
102  }
103  else
104  {
105  customConfigPath = QString( "%1/.qgis%2/" ).arg( QDir::homePath() ).arg( QGis::QGIS_VERSION_INT / 10000 );
106  }
107  }
108 
109  qRegisterMetaType<QgsGeometry::Error>( "QgsGeometry::Error" );
110 
111  QString prefixPath( getenv( "QGIS_PREFIX_PATH" ) ? getenv( "QGIS_PREFIX_PATH" ) : applicationDirPath() );
112  // QgsDebugMsg( QString( "prefixPath(): %1" ).arg( prefixPath ) );
113 
114  // check if QGIS is run from build directory (not the install directory)
115  QFile f;
116  // "/../../.." is for Mac bundled app in build directory
117  foreach ( QString path, QStringList() << "" << "/.." << "/bin" << "/../../.." )
118  {
119  f.setFileName( prefixPath + path + "/qgisbuildpath.txt" );
120  if ( f.exists() )
121  break;
122  }
123  if ( f.exists() && f.open( QIODevice::ReadOnly ) )
124  {
125  ABISYM( mRunningFromBuildDir ) = true;
126  ABISYM( mBuildSourcePath ) = f.readLine().trimmed();
127  ABISYM( mBuildOutputPath ) = f.readLine().trimmed();
128  qDebug( "Running from build directory!" );
129  qDebug( "- source directory: %s", ABISYM( mBuildSourcePath ).toUtf8().data() );
130  qDebug( "- output directory of the build: %s", ABISYM( mBuildOutputPath ).toUtf8().data() );
131 #ifdef _MSC_VER
132  ABISYM( mCfgIntDir ) = prefixPath.split( "/", QString::SkipEmptyParts ).last();
133  qDebug( "- cfg: %s", ABISYM( mCfgIntDir ).toUtf8().data() );
134 #endif
135  }
136 
137  if ( ABISYM( mRunningFromBuildDir ) )
138  {
139  // we run from source directory - not installed to destination (specified prefix)
140  ABISYM( mPrefixPath ) = QString(); // set invalid path
141 #if defined(_MSC_VER) && !defined(USING_NMAKE)
142  setPluginPath( ABISYM( mBuildOutputPath ) + "/" + QString( QGIS_PLUGIN_SUBDIR ) + "/" + ABISYM( mCfgIntDir ) );
143 #else
144  setPluginPath( ABISYM( mBuildOutputPath ) + "/" + QString( QGIS_PLUGIN_SUBDIR ) );
145 #endif
146  setPkgDataPath( ABISYM( mBuildSourcePath ) ); // directly source path - used for: doc, resources, svg
147  ABISYM( mLibraryPath ) = ABISYM( mBuildOutputPath ) + "/" + QGIS_LIB_SUBDIR + "/";
148 #if defined(_MSC_VER) && !defined(USING_NMAKE)
149  ABISYM( mLibexecPath ) = ABISYM( mBuildOutputPath ) + "/" + QGIS_LIBEXEC_SUBDIR + "/" + ABISYM( mCfgIntDir ) + "/";
150 #else
151  ABISYM( mLibexecPath ) = ABISYM( mBuildOutputPath ) + "/" + QGIS_LIBEXEC_SUBDIR + "/";
152 #endif
153  }
154  else
155  {
156  char *prefixPath = getenv( "QGIS_PREFIX_PATH" );
157  if ( !prefixPath )
158  {
159 #if defined(Q_OS_MACX) || defined(Q_OS_WIN)
161 #elif defined(ANDROID)
162  // this is "/data/data/org.qgis.qgis" in android
163  QDir myDir( QDir::homePath() );
164  myDir.cdUp();
165  QString myPrefix = myDir.absolutePath();
166  setPrefixPath( myPrefix, true );
167 #else
168  QDir myDir( applicationDirPath() );
169  myDir.cdUp();
170  QString myPrefix = myDir.absolutePath();
171  setPrefixPath( myPrefix, true );
172 #endif
173  }
174  else
175  {
176  setPrefixPath( prefixPath, true );
177  }
178  }
179 
180  if ( !customConfigPath.isEmpty() )
181  {
182  ABISYM( mConfigPath ) = customConfigPath + "/"; // make sure trailing slash is included
183  }
184 
185  ABISYM( mDefaultSvgPaths ) << qgisSettingsDirPath() + QString( "svg/" );
186 
187  // store system environment variables passed to application, before they are adjusted
188  QMap<QString, QString> systemEnvVarMap;
189  foreach ( const QString &varStr, QProcess::systemEnvironment() )
190  {
191  int pos = varStr.indexOf( QLatin1Char( '=' ) );
192  if ( pos == -1 )
193  continue;
194  QString varStrName = varStr.left( pos );
195  QString varStrValue = varStr.mid( pos + 1 );
196  systemEnvVarMap.insert( varStrName, varStrValue );
197  }
198  ABISYM( mSystemEnvVars ) = systemEnvVarMap;
199 
200  // allow Qt to search for Qt plugins (e.g. sqldrivers) in our plugin directory
202 
203  // set max. thread count to -1
204  // this should be read from QSettings but we don't know where they are at this point
205  // so we read actual value in main.cpp
206  ABISYM( mMaxThreads ) = -1;
207 }
208 
210 {
211 }
212 
214 {
215  bool done = false;
216  if ( event->type() == QEvent::FileOpen )
217  {
218  // handle FileOpen event (double clicking a file icon in Mac OS X Finder)
219  if ( ABISYM( mFileOpenEventReceiver ) )
220  {
221  // Forward event to main window.
222  done = notify( ABISYM( mFileOpenEventReceiver ), event );
223  }
224  else
225  {
226  // Store filename because receiver has not registered yet.
227  // If QGIS has been launched by double clicking a file icon, FileOpen will be
228  // the first event; the main window is not yet ready to handle the event.
229  ABISYM( mFileOpenEventList ).append( static_cast<QFileOpenEvent *>( event )->file() );
230  done = true;
231  }
232  }
233  else
234  {
235  // pass other events to base class
236  done = QApplication::event( event );
237  }
238  return done;
239 }
240 
241 bool QgsApplication::notify( QObject * receiver, QEvent * event )
242 {
243  bool done = false;
244  // Crashes in customization (especially on Mac), if we're not in the main/UI thread, see #5597
245  if ( thread() == receiver->thread() )
246  emit preNotify( receiver, event, &done );
247 
248  if ( done )
249  return true;
250 
251  // Send event to receiver and catch unhandled exceptions
252  done = true;
253  try
254  {
255  done = QApplication::notify( receiver, event );
256  }
257  catch ( QgsException & e )
258  {
259  QgsDebugMsg( "Caught unhandled QgsException: " + e.what() );
260  if ( qApp->thread() == QThread::currentThread() )
261  QMessageBox::critical( activeWindow(), tr( "Exception" ), e.what() );
262  }
263  catch ( std::exception & e )
264  {
265  QgsDebugMsg( "Caught unhandled std::exception: " + QString::fromAscii( e.what() ) );
266  if ( qApp->thread() == QThread::currentThread() )
267  QMessageBox::critical( activeWindow(), tr( "Exception" ), e.what() );
268  }
269  catch ( ... )
270  {
271  QgsDebugMsg( "Caught unhandled unknown exception" );
272  if ( qApp->thread() == QThread::currentThread() )
273  QMessageBox::critical( activeWindow(), tr( "Exception" ), tr( "unknown exception" ) );
274  }
275 
276  return done;
277 }
278 
280 {
281  // Set receiver for FileOpen events
282  ABISYM( mFileOpenEventReceiver ) = receiver;
283  // Propagate any events collected before the receiver has registered.
284  if ( ABISYM( mFileOpenEventList ).count() > 0 )
285  {
286  QStringListIterator i( ABISYM( mFileOpenEventList ) );
287  while ( i.hasNext() )
288  {
289  QFileOpenEvent foe( i.next() );
290  QgsApplication::sendEvent( ABISYM( mFileOpenEventReceiver ), &foe );
291  }
292  ABISYM( mFileOpenEventList ).clear();
293  }
294 }
295 
296 void QgsApplication::setPrefixPath( const QString &thePrefixPath, bool useDefaultPaths )
297 {
298  ABISYM( mPrefixPath ) = thePrefixPath;
299 #if defined(_MSC_VER)
300  if ( ABISYM( mPrefixPath ).endsWith( "/bin" ) )
301  {
302  ABISYM( mPrefixPath ).chop( 4 );
303  }
304 #endif
305  if ( useDefaultPaths && !ABISYM( mRunningFromBuildDir ) )
306  {
307  setPluginPath( ABISYM( mPrefixPath ) + "/" + QString( QGIS_PLUGIN_SUBDIR ) );
308  setPkgDataPath( ABISYM( mPrefixPath ) + "/" + QString( QGIS_DATA_SUBDIR ) );
309  }
310  ABISYM( mLibraryPath ) = ABISYM( mPrefixPath ) + "/" + QGIS_LIB_SUBDIR + "/";
311  ABISYM( mLibexecPath ) = ABISYM( mPrefixPath ) + "/" + QGIS_LIBEXEC_SUBDIR + "/";
312 }
313 
314 void QgsApplication::setPluginPath( const QString &thePluginPath )
315 {
316  ABISYM( mPluginPath ) = thePluginPath;
317 }
318 
319 void QgsApplication::setPkgDataPath( const QString &thePkgDataPath )
320 {
321  ABISYM( mPkgDataPath ) = thePkgDataPath;
322  QString mySvgPath = thePkgDataPath + ( ABISYM( mRunningFromBuildDir ) ? "/images/svg/" : "/svg/" );
323  // avoid duplicate entries
324  if ( !ABISYM( mDefaultSvgPaths ).contains( mySvgPath ) )
325  ABISYM( mDefaultSvgPaths ) << mySvgPath;
326 }
327 
329 {
330  ABISYM( mDefaultSvgPaths ) = pathList;
331 }
332 
334 {
335  if ( ABISYM( mRunningFromBuildDir ) )
336  {
337  static bool once = true;
338  if ( once )
339  qWarning( "!!! prefix path was requested, but it is not valid - we do not run from installed path !!!" );
340  once = false;
341  }
342 
343  return ABISYM( mPrefixPath );
344 }
346 {
347  return ABISYM( mPluginPath );
348 }
350 {
351  return ABISYM( mPkgDataPath );
352 }
354 {
355  return ":/images/themes/default/";
356 }
358 {
359  return ":/images/themes/" + themeName() + "/";
360 }
361 
362 
364 {
365  // try active theme
366  QString path = activeThemePath();
367  if ( QFile::exists( path + iconFile ) )
368  return path + iconFile;
369 
370  // use default theme
371  return defaultThemePath() + iconFile;
372 }
373 
375 {
376  QString myPreferredPath = activeThemePath() + QDir::separator() + theName;
377  QString myDefaultPath = defaultThemePath() + QDir::separator() + theName;
378  if ( QFile::exists( myPreferredPath ) )
379  {
380  return QIcon( myPreferredPath );
381  }
382  else if ( QFile::exists( myDefaultPath ) )
383  {
384  //could still return an empty icon if it
385  //doesnt exist in the default theme either!
386  return QIcon( myDefaultPath );
387  }
388  else
389  {
390  return QIcon();
391  }
392 }
393 
394 // TODO: add some caching mechanism ?
396 {
397  QString myPreferredPath = activeThemePath() + QDir::separator() + theName;
398  QString myDefaultPath = defaultThemePath() + QDir::separator() + theName;
399  if ( QFile::exists( myPreferredPath ) )
400  {
401  return QPixmap( myPreferredPath );
402  }
403  else
404  {
405  //could still return an empty icon if it
406  //doesnt exist in the default theme either!
407  return QPixmap( myDefaultPath );
408  }
409 }
410 
414 void QgsApplication::setThemeName( const QString &theThemeName )
415 {
416  QString myPath = ":/images/themes/" + theThemeName + "/";
417  //check it exists and if not roll back to default theme
418  if ( QFile::exists( myPath ) )
419  {
420  ABISYM( mThemeName ) = theThemeName;
421  }
422  else
423  {
424  ABISYM( mThemeName ) = "default";
425  }
426 }
431 {
432  return ABISYM( mThemeName );
433 }
434 
435 void QgsApplication::setUITheme( const QString &themeName )
436 {
437  // Loop all style sheets, find matching name, load it.
439  QString path = themes[themeName];
440  QString styleSheet = QLatin1String( "file:///" );
441  styleSheet.append( path + "/style.qss" );
442  qApp->setStyleSheet( styleSheet );
443  QSettings settings;
444  return settings.setValue( "UI/UITheme", themeName );
445 }
446 
448 {
449  QString themepath = ABISYM( mPkgDataPath ) + QString( "/resources/themes" );
450  QString userthemes = qgisSettingsDirPath() + QString( "/themes" );
451  QStringList paths = QStringList() << themepath << userthemes;
452  QHash<QString, QString> mapping;
453  mapping.insert( "default", "" );
454  foreach( const QString path, paths )
455  {
456  QDir folder( path );
457  QFileInfoList styleFiles = folder.entryInfoList( QDir::Dirs | QDir::NoDotAndDotDot );
458  foreach ( QFileInfo info, styleFiles )
459  {
460  QFileInfo styleFile( info.absoluteFilePath() + "/style.qss" );
461  if ( !styleFile.exists() )
462  continue;
463 
464  QString name = info.baseName();
465  QString path = info.absoluteFilePath();
466  mapping.insert( name, path );
467  }
468  }
469  return mapping;
470 }
471 
473 {
474  QSettings settings;
475  return settings.value( "UI/UITheme", "default" ).toString();
476 }
477 
482 {
483  return ABISYM( mPkgDataPath ) + QString( "/doc/AUTHORS" );
484 }
489 {
490  return ABISYM( mPkgDataPath ) + QString( "/doc/CONTRIBUTORS" );
491 }
493 {
494  return ABISYM( mPkgDataPath ) + QString( "/doc/developersmap.html" );
495 }
496 
498 {
499  return ABISYM( mPkgDataPath ) + QString( "/doc/whatsnew.html" );
500 }
505 {
506  return ABISYM( mPkgDataPath ) + QString( "/doc/SPONSORS" );
507 }
508 
513 {
514  return ABISYM( mPkgDataPath ) + QString( "/doc/DONORS" );
515 }
516 
519 {
520  return ABISYM( mPkgDataPath ) + QString( "/doc/TRANSLATORS" );
521 }
522 
525 {
526  return ABISYM( mPkgDataPath ) + QString( "/doc/LICENSE" );
527 }
528 
533 {
535 #ifdef Q_OS_MACX
536  helpAppPath = applicationDirPath() + "/bin/qgis_help.app/Contents/MacOS";
537 #else
538  helpAppPath = libexecPath();
539 #endif
540  helpAppPath += "/qgis_help";
541 #ifdef Q_OS_WIN
542  helpAppPath += ".exe";
543 #endif
544  return helpAppPath;
545 }
550 {
551  if ( ABISYM( mRunningFromBuildDir ) )
552  return ABISYM( mBuildOutputPath ) + QString( "/i18n" );
553  else
554  return ABISYM( mPkgDataPath ) + QString( "/i18n/" );
555 }
556 
561 {
562  return ABISYM( mPkgDataPath ) + QString( "/resources/qgis.db" );
563 }
564 
569 {
570  return ABISYM( mConfigPath );
571 }
572 
577 {
578  return qgisSettingsDirPath() + QString( "qgis.db" );
579 }
580 
585 {
586  return QString( ":/images/splash/" );
587 }
588 
593 {
594  return ABISYM( mPkgDataPath ) + QString( "/images/icons/" );
595 }
600 {
601  if ( ABISYM( mRunningFromBuildDir ) )
602  {
603  QString tempCopy = QDir::tempPath() + "/srs.db";
604 
605  if ( !QFile( tempCopy ).exists() )
606  {
607  QFile f( ABISYM( mPkgDataPath ) + "/resources/srs.db" );
608  if ( !f.copy( tempCopy ) )
609  {
610  qFatal( "Could not create temporary copy" );
611  }
612  }
613 
614  return tempCopy;
615  }
616  else
617  {
618  return ABISYM( mPkgDataPath ) + QString( "/resources/srs.db" );
619  }
620 }
621 
626 {
627  //local directories to search when looking for an SVG with a given basename
628  //defined by user in options dialog
629  QSettings settings;
630  QStringList myPathList;
631  QString myPaths = settings.value( "svg/searchPathsForSVG", "" ).toString();
632  if ( !myPaths.isEmpty() )
633  {
634  myPathList = myPaths.split( "|" );
635  }
636 
637  myPathList << ABISYM( mDefaultSvgPaths );
638  return myPathList;
639 }
640 
642 {
643  return qgisSettingsDirPath() + QString( "symbology-ng-style.db" );
644 }
645 
647 {
648  return ABISYM( mPkgDataPath ) + QString( "/resources/symbology-ng-style.db" );
649 }
650 
652 {
653  return ABISYM( mLibraryPath );
654 }
655 
657 {
658  return ABISYM( mLibexecPath );
659 }
660 
662 {
663  return ( htonl( 1 ) == 1 ) ? XDR : NDR;
664 }
665 
667 {
668  // set the provider plugin path (this creates provider registry)
670 
671  // create map layer registry if doesn't exist
673 }
674 
676 {
678 
679  //Ensure that all remaining deleteLater QObjects are actually deleted before we exit.
680  //This isn't strictly necessary (since we're exiting anyway) but doing so prevents a lot of
681  //LeakSanitiser noise which hides real issues
682  QgsApplication::sendPostedEvents( 0, QEvent::DeferredDelete );
683 
684  //delete all registered functions from expression engine (see above comment)
686 }
687 
689 {
690  QString myEnvironmentVar( getenv( "QGIS_PREFIX_PATH" ) );
691  QString myState = tr( "Application state:\n"
692  "QGIS_PREFIX_PATH env var:\t\t%1\n"
693  "Prefix:\t\t%2\n"
694  "Plugin Path:\t\t%3\n"
695  "Package Data Path:\t%4\n"
696  "Active Theme Name:\t%5\n"
697  "Active Theme Path:\t%6\n"
698  "Default Theme Path:\t%7\n"
699  "SVG Search Paths:\t%8\n"
700  "User DB Path:\t%9\n" )
701  .arg( myEnvironmentVar )
702  .arg( prefixPath() )
703  .arg( pluginPath() )
704  .arg( pkgDataPath() )
705  .arg( themeName() )
706  .arg( activeThemePath() )
707  .arg( defaultThemePath() )
708  .arg( svgPaths().join( tr( "\n\t\t", "match indentation of application state" ) ) )
710  return myState;
711 }
712 
714 {
715  //
716  // Make the style sheet desktop preferences aware by using qappliation
717  // palette as a basis for colors where appropriate
718  //
719 // QColor myColor1 = palette().highlight().color();
720  QColor myColor1( Qt::lightGray );
721  QColor myColor2 = myColor1;
722  myColor2 = myColor2.lighter( 110 ); //10% lighter
723  QString myStyle;
724  myStyle = "p.glossy{ background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, "
725  " stop: 0 " + myColor1.name() + ","
726  " stop: 0.1 " + myColor2.name() + ","
727  " stop: 0.5 " + myColor1.name() + ","
728  " stop: 0.9 " + myColor2.name() + ","
729  " stop: 1 " + myColor1.name() + ");"
730  " color: black;"
731  " padding-left: 4px;"
732  " padding-top: 20px;"
733  " padding-bottom: 8px;"
734  " border: 1px solid #6c6c6c;"
735  "}"
736  "p.subheaderglossy{ background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, "
737  " stop: 0 " + myColor1.name() + ","
738  " stop: 0.1 " + myColor2.name() + ","
739  " stop: 0.5 " + myColor1.name() + ","
740  " stop: 0.9 " + myColor2.name() + ","
741  " stop: 1 " + myColor1.name() + ");"
742  " font-weight: bold;"
743  " font-size: medium;"
744  " line-height: 1.1em;"
745  " width: 100%;"
746  " color: black;"
747  " padding-left: 4px;"
748  " padding-right: 4px;"
749  " padding-top: 20px;"
750  " padding-bottom: 8px;"
751  " border: 1px solid #6c6c6c;"
752  "}"
753  "th.glossy{ background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, "
754  " stop: 0 " + myColor1.name() + ","
755  " stop: 0.1 " + myColor2.name() + ","
756  " stop: 0.5 " + myColor1.name() + ","
757  " stop: 0.9 " + myColor2.name() + ","
758  " stop: 1 " + myColor1.name() + ");"
759  " color: black;"
760  " border: 1px solid #6c6c6c;"
761  "}"
762  ".overview{ font: 1.82em; font-weight: bold;}"
763  "body{ background: white;"
764  " color: black;"
765  " font-family: arial,sans-serif;"
766  "}"
767  "h1{ background-color: #F6F6F6;"
768  " color: #8FB171; "
769  " font-size: x-large; "
770  " font-weight: normal;"
771  " font-family: luxi serif, georgia, times new roman, times, serif;"
772  " background: none;"
773  " padding: 0.75em 0 0;"
774  " margin: 0;"
775  " line-height: 3em;"
776  "}"
777  "h2{ background-color: #F6F6F6;"
778  " color: #8FB171; "
779  " font-size: medium; "
780  " font-weight: normal;"
781  " font-family: luxi serif, georgia, times new roman, times, serif;"
782  " background: none;"
783  " padding: 0.75em 0 0;"
784  " margin: 0;"
785  " line-height: 1.1em;"
786  "}"
787  "h3{ background-color: #F6F6F6;"
788  " color: #729FCF;"
789  " font-family: luxi serif, georgia, times new roman, times, serif;"
790  " font-weight: bold;"
791  " font-size: large;"
792  " text-align: right;"
793  " border-bottom: 5px solid #DCEB5C;"
794  "}"
795  "h4{ background-color: #F6F6F6;"
796  " color: #729FCF;"
797  " font-family: luxi serif, georgia, times new roman, times, serif;"
798  " font-weight: bold;"
799  " font-size: medium;"
800  " text-align: right;"
801  "}"
802  "h5{ background-color: #F6F6F6;"
803  " color: #729FCF;"
804  " font-family: luxi serif, georgia, times new roman, times, serif;"
805  " font-weight: bold;"
806  " font-size: small;"
807  " text-align: right;"
808  "}"
809  "a{ color: #729FCF;"
810  " font-family: arial,sans-serif;"
811  " font-size: small;"
812  "}"
813  "label{ background-color: #FFFFCC;"
814  " border: 1px solid black;"
815  " margin: 1px;"
816  " padding: 0px 3px; "
817  " font-size: small;"
818  "}";
819  return myStyle;
820 }
821 
823 {
824  if ( 0 >= OGRGetDriverCount() )
825  {
826  OGRRegisterAll();
827  }
828 }
829 
831 {
832 #if defined( Q_OS_WIN )
833  const Qt::CaseSensitivity cs = Qt::CaseInsensitive;
834 
835  aPath.replace( "\\", "/" );
836  if ( aPath.startsWith( "//" ) )
837  {
838  // keep UNC prefix
839  aPath = "\\\\" + aPath.mid( 2 );
840  }
841 
842  targetPath.replace( "\\", "/" );
843  if ( targetPath.startsWith( "//" ) )
844  {
845  // keep UNC prefix
846  targetPath = "\\\\" + targetPath.mid( 2 );
847  }
848 #else
849  const Qt::CaseSensitivity cs = Qt::CaseSensitive;
850 #endif
851 
852  QStringList targetElems = targetPath.split( "/", QString::SkipEmptyParts );
853  QStringList aPathElems = aPath.split( "/", QString::SkipEmptyParts );
854 
855  targetElems.removeAll( "." );
856  aPathElems.removeAll( "." );
857 
858  // remove common part
859  int n = 0;
860  while ( aPathElems.size() > 0 &&
861  targetElems.size() > 0 &&
862  aPathElems[0].compare( targetElems[0], cs ) == 0 )
863  {
864  aPathElems.removeFirst();
865  targetElems.removeFirst();
866  n++;
867  }
868 
869  if ( n == 0 )
870  {
871  // no common parts; might not even be a file
872  return aPath;
873  }
874 
875  if ( targetElems.size() > 0 )
876  {
877  // go up to the common directory
878  for ( int i = 0; i < targetElems.size(); i++ )
879  {
880  aPathElems.insert( 0, ".." );
881  }
882  }
883  else
884  {
885  // let it start with . nevertheless,
886  // so relative path always start with either ./ or ../
887  aPathElems.insert( 0, "." );
888  }
889 
890  return aPathElems.join( "/" );
891 }
892 
894 {
895  // relative path should always start with ./ or ../
896  if ( !rpath.startsWith( "./" ) && !rpath.startsWith( "../" ) )
897  {
898  return rpath;
899  }
900 
901 #if defined(Q_OS_WIN)
902  rpath.replace( "\\", "/" );
903  targetPath.replace( "\\", "/" );
904 
905  bool uncPath = targetPath.startsWith( "//" );
906 #endif
907 
908  QStringList srcElems = rpath.split( "/", QString::SkipEmptyParts );
909  QStringList targetElems = targetPath.split( "/", QString::SkipEmptyParts );
910 
911 #if defined(Q_OS_WIN)
912  if ( uncPath )
913  {
914  targetElems.insert( 0, "" );
915  targetElems.insert( 0, "" );
916  }
917 #endif
918 
919  // append source path elements
920  targetElems << srcElems;
921  targetElems.removeAll( "." );
922 
923  // resolve ..
924  int pos;
925  while (( pos = targetElems.indexOf( ".." ) ) > 0 )
926  {
927  // remove preceding element and ..
928  targetElems.removeAt( pos - 1 );
929  targetElems.removeAt( pos - 1 );
930  }
931 
932 #if !defined(Q_OS_WIN)
933  // make path absolute
934  targetElems.prepend( "" );
935 #endif
936 
937  return targetElems.join( "/" );
938 }
939 
941 {
942  if ( ABISYM( mGdalSkipList ).contains( theDriver ) || theDriver.isEmpty() )
943  {
944  return;
945  }
946  ABISYM( mGdalSkipList ) << theDriver;
948 }
949 
951 {
952  if ( !ABISYM( mGdalSkipList ).contains( theDriver ) )
953  {
954  return;
955  }
956  int myPos = ABISYM( mGdalSkipList ).indexOf( theDriver );
957  if ( myPos >= 0 )
958  {
959  ABISYM( mGdalSkipList ).removeAt( myPos );
960  }
962 }
963 
965 {
966  ABISYM( mGdalSkipList ).removeDuplicates();
967  QString myDriverList = ABISYM( mGdalSkipList ).join( " " );
968  QgsDebugMsg( "Gdal Skipped driver list set to:" );
969  QgsDebugMsg( myDriverList );
970  CPLSetConfigOption( "GDAL_SKIP", myDriverList.toUtf8() );
971  GDALAllRegister(); //to update driver list and skip missing ones
972 }
973 
974 bool QgsApplication::createDB( QString *errorMessage )
975 {
976  // set a working directory up for gdal to write .aux.xml files into
977  // for cases where the raster dir is read only to the user
978  // if the env var is already set it will be used preferentially
979  QString myPamPath = qgisSettingsDirPath() + QString( "gdal_pam/" );
980  QDir myDir( myPamPath );
981  if ( !myDir.exists() )
982  {
983  myDir.mkpath( myPamPath ); //fail silently
984  }
985 
986 #if defined(Q_OS_WIN)
987  CPLSetConfigOption( "GDAL_PAM_PROXY_DIR", myPamPath.toUtf8() );
988 #else
989  //under other OS's we use an environment var so the user can
990  //override the path if he likes
991  int myChangeFlag = 0; //whether we want to force the env var to change
992  setenv( "GDAL_PAM_PROXY_DIR", myPamPath.toUtf8(), myChangeFlag );
993 #endif
994 
995  // Check qgis.db and make private copy if necessary
996  QFile qgisPrivateDbFile( QgsApplication::qgisUserDbFilePath() );
997 
998  // first we look for ~/.qgis/qgis.db
999  if ( !qgisPrivateDbFile.exists() )
1000  {
1001  // if it doesnt exist we copy it in from the global resources dir
1002  QString qgisMasterDbFileName = QgsApplication::qgisMasterDbFilePath();
1003  QFile masterFile( qgisMasterDbFileName );
1004 
1005  // Must be sure there is destination directory ~/.qgis
1007 
1008  //now copy the master file into the users .qgis dir
1009  bool isDbFileCopied = masterFile.copy( qgisPrivateDbFile.fileName() );
1010 
1011  if ( !isDbFileCopied )
1012  {
1013  if ( errorMessage )
1014  {
1015  *errorMessage = tr( "[ERROR] Can not make qgis.db private copy" );
1016  }
1017  return false;
1018  }
1019  }
1020  else
1021  {
1022  // migrate if necessary
1023  sqlite3 *db;
1024  if ( sqlite3_open( QgsApplication::qgisUserDbFilePath().toUtf8().constData(), &db ) != SQLITE_OK )
1025  {
1026  if ( errorMessage )
1027  {
1028  *errorMessage = tr( "Could not open qgis.db" );
1029  }
1030  return false;
1031  }
1032 
1033  char *errmsg;
1034  int res = sqlite3_exec( db, "SELECT epsg FROM tbl_srs LIMIT 0", 0, 0, &errmsg );
1035  if ( res == SQLITE_OK )
1036  {
1037  // epsg column exists => need migration
1038  if ( sqlite3_exec( db,
1039  "ALTER TABLE tbl_srs RENAME TO tbl_srs_bak;"
1040  "CREATE TABLE tbl_srs ("
1041  "srs_id INTEGER PRIMARY KEY,"
1042  "description text NOT NULL,"
1043  "projection_acronym text NOT NULL,"
1044  "ellipsoid_acronym NOT NULL,"
1045  "parameters text NOT NULL,"
1046  "srid integer,"
1047  "auth_name varchar,"
1048  "auth_id varchar,"
1049  "is_geo integer NOT NULL,"
1050  "deprecated boolean);"
1051  "CREATE INDEX idx_srsauthid on tbl_srs(auth_name,auth_id);"
1052  "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;"
1053  "DROP TABLE tbl_srs_bak", 0, 0, &errmsg ) != SQLITE_OK
1054  )
1055  {
1056  if ( errorMessage )
1057  {
1058  *errorMessage = tr( "Migration of private qgis.db failed.\n%1" ).arg( QString::fromUtf8( errmsg ) );
1059  }
1060  sqlite3_free( errmsg );
1061  sqlite3_close( db );
1062  return false;
1063  }
1064  }
1065  else
1066  {
1067  sqlite3_free( errmsg );
1068  }
1069 
1070  if ( sqlite3_exec( db, "DROP VIEW vw_srs", 0, 0, &errmsg ) != SQLITE_OK )
1071  {
1072  QgsDebugMsg( QString( "vw_srs didn't exists in private qgis.db: %1" ).arg( errmsg ) );
1073  }
1074 
1075  if ( sqlite3_exec( db,
1076  "CREATE VIEW vw_srs AS"
1077  " SELECT"
1078  " a.description AS description"
1079  ",a.srs_id AS srs_id"
1080  ",a.is_geo AS is_geo"
1081  ",coalesce(b.name,a.projection_acronym) AS name"
1082  ",a.parameters AS parameters"
1083  ",a.auth_name AS auth_name"
1084  ",a.auth_id AS auth_id"
1085  ",a.deprecated AS deprecated"
1086  " FROM tbl_srs a"
1087  " LEFT OUTER JOIN tbl_projection b ON a.projection_acronym=b.acronym"
1088  " ORDER BY coalesce(b.name,a.projection_acronym),a.description", 0, 0, &errmsg ) != SQLITE_OK
1089  )
1090  {
1091  if ( errorMessage )
1092  {
1093  *errorMessage = tr( "Update of view in private qgis.db failed.\n%1" ).arg( QString::fromUtf8( errmsg ) );
1094  }
1095  sqlite3_free( errmsg );
1096  sqlite3_close( db );
1097  return false;
1098  }
1099 
1100  sqlite3_close( db );
1101  }
1102  return true;
1103 }
1104 
1105 void QgsApplication::setMaxThreads( int maxThreads )
1106 {
1107  QgsDebugMsg( QString( "maxThreads: %1" ).arg( maxThreads ) );
1108 
1109  // make sure value is between 1 and #cores, if not set to -1 (use #cores)
1110  // 0 could be used to disable any parallel processing
1111  if ( maxThreads < 1 || maxThreads > QThread::idealThreadCount() )
1112  maxThreads = -1;
1113 
1114  // save value
1115  ABISYM( mMaxThreads ) = maxThreads;
1116 
1117  // if -1 use #cores
1118  if ( maxThreads == -1 )
1119  maxThreads = QThread::idealThreadCount();
1120 
1121  // set max thread count in QThreadPool
1123  QgsDebugMsg( QString( "set QThreadPool max thread count to %1" ).arg( QThreadPool::globalInstance()->maxThreadCount() ) );
1124 }
1125 
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.
QString fromAscii(const char *str, int size)
static const QString i18nPath()
Returns the path to the translation directory.
static const QString contributorsFilePath()
Returns the path to the contributors file.
int indexOf(QChar ch, int from, Qt::CaseSensitivity cs) const
enum QgsApplication::ENDIAN endian_t
Constants for endian-ness.
QString & append(QChar ch)
Type type() const
iterator insert(const Key &key, const T &value)
static const QString qgisMasterDbFilePath()
Returns the path to the master qgis.db file.
static const QString uiThemeName()
Return the active UI theme set in the settings.
static const QString whatsNewFilePath()
Returns the path to the whats new html page.
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.
QStringList systemEnvironment()
QStringList ABISYM(QgsApplication::mFileOpenEventList)
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.
QString name() const
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.
QStringList split(const QString &sep, SplitBehavior behavior, Qt::CaseSensitivity cs) const
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.
void removeFirst()
QThreadPool * globalInstance()
void removeAt(int i)
void setFileName(const QString &name)
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.
QString join(const QString &separator) const
bool exists() const
static QString absolutePathToRelativePath(QString apath, QString targetPath)
Converts absolute path to path relative to target.
QThread * thread() const
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.
QString homePath()
static const QString qgisSettingsDirPath()
Returns the path to the settings directory in user's home dir.
QChar separator()
QString tr(const char *sourceText, const char *disambiguation, int n)
static QPixmap getThemePixmap(const QString &theName)
Helper to get a theme icon as a pixmap.
bool copy(const QString &newName)
void addLibraryPath(const QString &path)
int size() const
void setValue(const QString &key, const QVariant &value)
static void applyGdalSkippedDrivers()
Apply the skipped drivers list to gdal.
const char * name() const
QWidget * activeWindow()
bool exists() const
QString fromUtf8(const char *str, int size)
void setMaxThreadCount(int maxThreadCount)
QString tempPath()
static void setThemeName(const QString &theThemeName)
Set the active theme to the specified theme.
static void cleanRegisteredFunctions()
Deletes all registered functions whose ownership have been transferred to the expression engine...
static const QString iconsPath()
Returns the path to the icons image directory.
QFileInfoList entryInfoList(QFlags< QDir::Filter > filters, QFlags< QDir::SortFlag > sort) const
QString absoluteFilePath() const
virtual ~QgsApplication()
bool isEmpty() const
int removeAll(const T &value)
bool sendEvent(QObject *receiver, QEvent *event)
bool startsWith(const QString &s, Qt::CaseSensitivity cs) const
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
virtual bool open(QFlags< QIODevice::OpenModeFlag > mode)
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).
bool cdUp()
struct sqlite3 sqlite3
static void initQgis()
loads providers
static void setDefaultSvgPaths(const QStringList &pathList)
Alters default svg paths - used by 3rd party apps.
QColor lighter(int factor) const
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...
static const QString developersMapFilePath()
Returns the path to the developers map file.
QString & replace(int position, int n, QChar after)
static const QHash< QString, QString > uiThemes()
All themes found in the application resources folder and ~.qgis2 folder.
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
QVariant value(const QString &key, const QVariant &defaultValue) const
static const char * QGIS_ORGANIZATION_DOMAIN
int idealThreadCount()
static QgsMapLayerRegistry * instance()
Returns the instance pointer, creating the object on the first call.
QString mid(int position, int n) const
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.
virtual bool event(QEvent *e)
QString absolutePath() const
void insert(int i, const T &value)
void sendPostedEvents()
QThread * currentThread()
static const QString srsDbFilePath()
Returns the path to the srs.db file.
StandardButton critical(QWidget *parent, const QString &title, const QString &text, QFlags< QMessageBox::StandardButton > buttons, StandardButton defaultButton)
QString styleSheet() const
QString left(int n) const
static void exitQgis()
deletes provider registry and map layer registry
static const QString sponsorsFilePath()
Returns the path to the sponsors file.
int indexOf(const QRegExp &rx, int from) const
void prepend(const T &value)
iterator insert(const Key &key, const T &value)
QgsApplication(int &argc, char **argv, bool GUIenabled, QString customConfigPath=QString())
static const char * QGIS_APPLICATION_NAME
QString applicationDirPath()
virtual bool notify(QObject *receiver, QEvent *e)
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.
QString arg(qlonglong a, int fieldWidth, int base, const QChar &fillChar) const
QString toString() const
static const int QGIS_VERSION_INT
Definition: qgis.h:42
Defines a qgis exception class.
Definition: qgsexception.h:25
QString baseName() const
static void setMaxThreads(int maxThreads)
Set maximum concurrent thread count.
bool mkpath(const QString &dirPath) const
static void setUITheme(const QString &themeName)
qint64 readLine(char *data, qint64 maxSize)
void preNotify(QObject *receiver, QEvent *event, bool *done)
QByteArray toUtf8() const