QGIS API Documentation  2.12.0-Lyon
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 "qgsauthmanager.h"
18 #include "qgscrscache.h"
20 #include "qgsexception.h"
21 #include "qgsgeometry.h"
22 #include "qgslogger.h"
23 #include "qgsmaplayerregistry.h"
25 #include "qgsproviderregistry.h"
26 #include "qgsexpression.h"
27 
28 #include <QDir>
29 #include <QFile>
30 #include <QFileInfo>
31 #include <QFileOpenEvent>
32 #include <QMessageBox>
33 #include <QPalette>
34 #include <QProcess>
35 #include <QSettings>
36 #include <QIcon>
37 #include <QPixmap>
38 #include <QThreadPool>
39 
40 #ifndef Q_OS_WIN
41 #include <netinet/in.h>
42 #else
43 #include <winsock.h>
44 #endif
45 
46 #include "qgsconfig.h"
47 
48 #include <gdal.h>
49 #include <ogr_api.h>
50 #include <cpl_conv.h> // for setting gdal options
51 #include <sqlite3.h>
52 
53 QObject * ABISYM( QgsApplication::mFileOpenEventReceiver );
54 QStringList ABISYM( QgsApplication::mFileOpenEventList );
55 QString ABISYM( QgsApplication::mPrefixPath );
56 QString ABISYM( QgsApplication::mPluginPath );
57 QString ABISYM( QgsApplication::mPkgDataPath );
58 QString ABISYM( QgsApplication::mLibraryPath );
59 QString ABISYM( QgsApplication::mLibexecPath );
60 QString ABISYM( QgsApplication::mThemeName );
61 QString ABISYM( QgsApplication::mUIThemeName );
62 QStringList ABISYM( QgsApplication::mDefaultSvgPaths );
63 QMap<QString, QString> ABISYM( QgsApplication::mSystemEnvVars );
64 QString ABISYM( QgsApplication::mConfigPath );
65 bool ABISYM( QgsApplication::mRunningFromBuildDir ) = false;
66 QString ABISYM( QgsApplication::mBuildSourcePath );
67 #ifdef _MSC_VER
68 QString ABISYM( QgsApplication::mCfgIntDir );
69 #endif
70 QString ABISYM( QgsApplication::mBuildOutputPath );
71 QStringList ABISYM( QgsApplication::mGdalSkipList );
72 int ABISYM( QgsApplication::mMaxThreads );
73 QString ABISYM( QgsApplication::mAuthDbDirPath );
74 
75 const char* QgsApplication::QGIS_ORGANIZATION_NAME = "QGIS";
76 const char* QgsApplication::QGIS_ORGANIZATION_DOMAIN = "qgis.org";
77 const char* QgsApplication::QGIS_APPLICATION_NAME = "QGIS2";
78 
92 QgsApplication::QgsApplication( int & argc, char ** argv, bool GUIenabled, const QString& customConfigPath )
93  : QApplication( argc, argv, GUIenabled )
94 {
95  init( customConfigPath ); // init can also be called directly by e.g. unit tests that don't inherit QApplication.
96 }
97 
98 void QgsApplication::init( QString customConfigPath )
99 {
100  if ( customConfigPath.isEmpty() )
101  {
102  if ( getenv( "QGIS_CUSTOM_CONFIG_PATH" ) )
103  {
104  customConfigPath = getenv( "QGIS_CUSTOM_CONFIG_PATH" );
105  }
106  else
107  {
108  customConfigPath = QString( "%1/.qgis%2/" ).arg( QDir::homePath() ).arg( QGis::QGIS_VERSION_INT / 10000 );
109  }
110  }
111 
112  qRegisterMetaType<QgsGeometry::Error>( "QgsGeometry::Error" );
113 
114  QString prefixPath( getenv( "QGIS_PREFIX_PATH" ) ? getenv( "QGIS_PREFIX_PATH" ) : applicationDirPath() );
115  // QgsDebugMsg( QString( "prefixPath(): %1" ).arg( prefixPath ) );
116 
117  // check if QGIS is run from build directory (not the install directory)
118  QFile f;
119  // "/../../.." is for Mac bundled app in build directory
120  Q_FOREACH ( const QString& path, QStringList() << "" << "/.." << "/bin" << "/../../.." )
121  {
122  f.setFileName( prefixPath + path + "/qgisbuildpath.txt" );
123  if ( f.exists() )
124  break;
125  }
126  if ( f.exists() && f.open( QIODevice::ReadOnly ) )
127  {
128  ABISYM( mRunningFromBuildDir ) = true;
129  ABISYM( mBuildSourcePath ) = f.readLine().trimmed();
130  ABISYM( mBuildOutputPath ) = f.readLine().trimmed();
131  qDebug( "Running from build directory!" );
132  qDebug( "- source directory: %s", ABISYM( mBuildSourcePath ).toUtf8().data() );
133  qDebug( "- output directory of the build: %s", ABISYM( mBuildOutputPath ).toUtf8().data() );
134 #ifdef _MSC_VER
135  ABISYM( mCfgIntDir ) = prefixPath.split( "/", QString::SkipEmptyParts ).last();
136  qDebug( "- cfg: %s", ABISYM( mCfgIntDir ).toUtf8().data() );
137 #endif
138  }
139 
140  if ( ABISYM( mRunningFromBuildDir ) )
141  {
142  // we run from source directory - not installed to destination (specified prefix)
143  ABISYM( mPrefixPath ) = QString(); // set invalid path
144 #if defined(_MSC_VER) && !defined(USING_NMAKE)
145  setPluginPath( ABISYM( mBuildOutputPath ) + "/" + QString( QGIS_PLUGIN_SUBDIR ) + "/" + ABISYM( mCfgIntDir ) );
146 #else
147  setPluginPath( ABISYM( mBuildOutputPath ) + "/" + QString( QGIS_PLUGIN_SUBDIR ) );
148 #endif
149  setPkgDataPath( ABISYM( mBuildSourcePath ) ); // directly source path - used for: doc, resources, svg
150  ABISYM( mLibraryPath ) = ABISYM( mBuildOutputPath ) + "/" + QGIS_LIB_SUBDIR + "/";
151 #if defined(_MSC_VER) && !defined(USING_NMAKE)
152  ABISYM( mLibexecPath ) = ABISYM( mBuildOutputPath ) + "/" + QGIS_LIBEXEC_SUBDIR + "/" + ABISYM( mCfgIntDir ) + "/";
153 #else
154  ABISYM( mLibexecPath ) = ABISYM( mBuildOutputPath ) + "/" + QGIS_LIBEXEC_SUBDIR + "/";
155 #endif
156  }
157  else
158  {
159  char *prefixPath = getenv( "QGIS_PREFIX_PATH" );
160  if ( !prefixPath )
161  {
162 #if defined(Q_OS_MACX) || defined(Q_OS_WIN)
164 #elif defined(ANDROID)
165  // this is "/data/data/org.qgis.qgis" in android
166  QDir myDir( QDir::homePath() );
167  myDir.cdUp();
168  QString myPrefix = myDir.absolutePath();
169  setPrefixPath( myPrefix, true );
170 #else
171  QDir myDir( applicationDirPath() );
172  myDir.cdUp();
173  QString myPrefix = myDir.absolutePath();
174  setPrefixPath( myPrefix, true );
175 #endif
176  }
177  else
178  {
179  setPrefixPath( prefixPath, true );
180  }
181  }
182 
183  if ( !customConfigPath.isEmpty() )
184  {
185  ABISYM( mConfigPath ) = customConfigPath + "/"; // make sure trailing slash is included
186  }
187 
188  ABISYM( mDefaultSvgPaths ) << qgisSettingsDirPath() + QLatin1String( "svg/" );
189 
190  ABISYM( mAuthDbDirPath ) = qgisSettingsDirPath();
191  if ( getenv( "QGIS_AUTH_DB_DIR_PATH" ) )
192  {
193  setAuthDbDirPath( getenv( "QGIS_AUTH_DB_DIR_PATH" ) );
194  }
195 
196 
197  // store system environment variables passed to application, before they are adjusted
198  QMap<QString, QString> systemEnvVarMap;
199  QString passfile( "QGIS_AUTH_PASSWORD_FILE" ); // QString, for comparison
200  Q_FOREACH ( const QString &varStr, QProcess::systemEnvironment() )
201  {
202  int pos = varStr.indexOf( QLatin1Char( '=' ) );
203  if ( pos == -1 )
204  continue;
205  QString varStrName = varStr.left( pos );
206  QString varStrValue = varStr.mid( pos + 1 );
207  if ( varStrName != passfile )
208  {
209  systemEnvVarMap.insert( varStrName, varStrValue );
210  }
211  }
212  ABISYM( mSystemEnvVars ) = systemEnvVarMap;
213 
214  // allow Qt to search for Qt plugins (e.g. sqldrivers) in our plugin directory
216 
217  // set max. thread count to -1
218  // this should be read from QSettings but we don't know where they are at this point
219  // so we read actual value in main.cpp
220  ABISYM( mMaxThreads ) = -1;
221 }
222 
224 {
225 }
226 
228 {
229  bool done = false;
230  if ( event->type() == QEvent::FileOpen )
231  {
232  // handle FileOpen event (double clicking a file icon in Mac OS X Finder)
233  if ( ABISYM( mFileOpenEventReceiver ) )
234  {
235  // Forward event to main window.
236  done = notify( ABISYM( mFileOpenEventReceiver ), event );
237  }
238  else
239  {
240  // Store filename because receiver has not registered yet.
241  // If QGIS has been launched by double clicking a file icon, FileOpen will be
242  // the first event; the main window is not yet ready to handle the event.
243  ABISYM( mFileOpenEventList ).append( static_cast<QFileOpenEvent *>( event )->file() );
244  done = true;
245  }
246  }
247  else
248  {
249  // pass other events to base class
250  done = QApplication::event( event );
251  }
252  return done;
253 }
254 
255 bool QgsApplication::notify( QObject * receiver, QEvent * event )
256 {
257  bool done = false;
258  // Crashes in customization (especially on Mac), if we're not in the main/UI thread, see #5597
259  if ( thread() == receiver->thread() )
260  emit preNotify( receiver, event, &done );
261 
262  if ( done )
263  return true;
264 
265  // Send event to receiver and catch unhandled exceptions
266  done = true;
267  try
268  {
269  done = QApplication::notify( receiver, event );
270  }
271  catch ( QgsException & e )
272  {
273  QgsDebugMsg( "Caught unhandled QgsException: " + e.what() );
274  if ( qApp->thread() == QThread::currentThread() )
275  QMessageBox::critical( activeWindow(), tr( "Exception" ), e.what() );
276  }
277  catch ( std::exception & e )
278  {
279  QgsDebugMsg( "Caught unhandled std::exception: " + QString::fromAscii( e.what() ) );
280  if ( qApp->thread() == QThread::currentThread() )
281  QMessageBox::critical( activeWindow(), tr( "Exception" ), e.what() );
282  }
283  catch ( ... )
284  {
285  QgsDebugMsg( "Caught unhandled unknown exception" );
286  if ( qApp->thread() == QThread::currentThread() )
287  QMessageBox::critical( activeWindow(), tr( "Exception" ), tr( "unknown exception" ) );
288  }
289 
290  return done;
291 }
292 
294 {
295  // Set receiver for FileOpen events
296  ABISYM( mFileOpenEventReceiver ) = receiver;
297  // Propagate any events collected before the receiver has registered.
298  if ( ABISYM( mFileOpenEventList ).count() > 0 )
299  {
300  QStringListIterator i( ABISYM( mFileOpenEventList ) );
301  while ( i.hasNext() )
302  {
303  QFileOpenEvent foe( i.next() );
304  QgsApplication::sendEvent( ABISYM( mFileOpenEventReceiver ), &foe );
305  }
306  ABISYM( mFileOpenEventList ).clear();
307  }
308 }
309 
310 void QgsApplication::setPrefixPath( const QString &thePrefixPath, bool useDefaultPaths )
311 {
312  ABISYM( mPrefixPath ) = thePrefixPath;
313 #if defined(_MSC_VER)
314  if ( ABISYM( mPrefixPath ).endsWith( "/bin" ) )
315  {
316  ABISYM( mPrefixPath ).chop( 4 );
317  }
318 #endif
319  if ( useDefaultPaths && !ABISYM( mRunningFromBuildDir ) )
320  {
321  setPluginPath( ABISYM( mPrefixPath ) + "/" + QString( QGIS_PLUGIN_SUBDIR ) );
322  setPkgDataPath( ABISYM( mPrefixPath ) + "/" + QString( QGIS_DATA_SUBDIR ) );
323  }
324  ABISYM( mLibraryPath ) = ABISYM( mPrefixPath ) + "/" + QGIS_LIB_SUBDIR + "/";
325  ABISYM( mLibexecPath ) = ABISYM( mPrefixPath ) + "/" + QGIS_LIBEXEC_SUBDIR + "/";
326 }
327 
328 void QgsApplication::setPluginPath( const QString &thePluginPath )
329 {
330  ABISYM( mPluginPath ) = thePluginPath;
331 }
332 
333 void QgsApplication::setPkgDataPath( const QString &thePkgDataPath )
334 {
335  ABISYM( mPkgDataPath ) = thePkgDataPath;
336  QString mySvgPath = thePkgDataPath + ( ABISYM( mRunningFromBuildDir ) ? "/images/svg/" : "/svg/" );
337  // avoid duplicate entries
338  if ( !ABISYM( mDefaultSvgPaths ).contains( mySvgPath ) )
339  ABISYM( mDefaultSvgPaths ) << mySvgPath;
340 }
341 
343 {
344  ABISYM( mDefaultSvgPaths ) = pathList;
345 }
346 
347 void QgsApplication::setAuthDbDirPath( const QString& theAuthDbDirPath )
348 {
349  QFileInfo fi( theAuthDbDirPath );
350  if ( fi.exists() && fi.isDir() && fi.isWritable() )
351  {
352  ABISYM( mAuthDbDirPath ) = fi.canonicalFilePath() + QDir::separator();
353  }
354 }
355 
357 {
358  if ( ABISYM( mRunningFromBuildDir ) )
359  {
360  static bool once = true;
361  if ( once )
362  qWarning( "!!! prefix path was requested, but it is not valid - we do not run from installed path !!!" );
363  once = false;
364  }
365 
366  return ABISYM( mPrefixPath );
367 }
369 {
370  return ABISYM( mPluginPath );
371 }
373 {
374  return ABISYM( mPkgDataPath );
375 }
377 {
378  return ":/images/themes/default/";
379 }
381 {
382  return userThemesFolder() + QDir::separator() + themeName() + QDir::separator() + "icons/";
383 }
384 
385 
387 {
388  // try active theme
389  QString path = activeThemePath();
390  if ( QFile::exists( path + iconFile ) )
391  return path + iconFile;
392 
393  // use default theme
394  return defaultThemePath() + iconFile;
395 }
396 
398 {
399  QString myPreferredPath = activeThemePath() + QDir::separator() + theName;
400  QString myDefaultPath = defaultThemePath() + QDir::separator() + theName;
401  if ( QFile::exists( myPreferredPath ) )
402  {
403  return QIcon( myPreferredPath );
404  }
405  else if ( QFile::exists( myDefaultPath ) )
406  {
407  //could still return an empty icon if it
408  //doesnt exist in the default theme either!
409  return QIcon( myDefaultPath );
410  }
411  else
412  {
413  return QIcon();
414  }
415 }
416 
417 // TODO: add some caching mechanism ?
419 {
420  QString myPreferredPath = activeThemePath() + QDir::separator() + theName;
421  QString myDefaultPath = defaultThemePath() + QDir::separator() + theName;
422  if ( QFile::exists( myPreferredPath ) )
423  {
424  return QPixmap( myPreferredPath );
425  }
426  else
427  {
428  //could still return an empty icon if it
429  //doesnt exist in the default theme either!
430  return QPixmap( myDefaultPath );
431  }
432 }
433 
437 void QgsApplication::setThemeName( const QString &theThemeName )
438 {
439  ABISYM( mThemeName ) = theThemeName;
440 }
445 {
446  return ABISYM( mThemeName );
447 }
448 
449 void QgsApplication::setUITheme( const QString &themeName )
450 {
451  // Loop all style sheets, find matching name, load it.
453  QString themename = themeName;
454  if ( !themes.contains( themename ) )
455  themename = "default";
456 
457  QString path = themes[themename];
458  QString stylesheetname = path + "/style.qss";
459  QString autostylesheet = stylesheetname + ".auto";
460 
461  QFile file( stylesheetname );
462  QFile variablesfile( path + "/variables.qss" );
463  QFile fileout( autostylesheet );
464 
465  QFileInfo variableInfo( variablesfile );
466 
467  if ( variableInfo.exists() && variablesfile.open( QIODevice::ReadOnly ) )
468  {
469  if ( !file.open( QIODevice::ReadOnly ) || !fileout.open( QIODevice::WriteOnly | QIODevice::Text ) )
470  {
471  return;
472  }
473 
474  QHash<QString, QString> variables;
475  QString styledata = file.readAll();
476  QTextStream in( &variablesfile );
477  while ( !in.atEnd() )
478  {
479  QString line = in.readLine();
480  // This is is a variable
481  if ( line.startsWith( "@" ) )
482  {
483  int index = line.indexOf( ":" );
484  QString name = line.mid( 0, index );
485  QString value = line.mid( index + 1, line.length() );
486  styledata.replace( name, value );
487  }
488  }
489  variablesfile.close();
490  QTextStream out( &fileout );
491  out << styledata;
492  fileout.close();
493  file.close();
494  stylesheetname = autostylesheet;
495  }
496 
497  QString styleSheet = QLatin1String( "file:///" );
498  styleSheet.append( stylesheetname );
499  qApp->setStyleSheet( styleSheet );
500  setThemeName( themename );
501 }
502 
504 {
506  QHash<QString, QString> mapping;
507  mapping.insert( "default", "" );
508  Q_FOREACH ( const QString& path, paths )
509  {
510  QDir folder( path );
511  QFileInfoList styleFiles = folder.entryInfoList( QDir::Dirs | QDir::NoDotAndDotDot );
512  Q_FOREACH ( const QFileInfo& info, styleFiles )
513  {
514  QFileInfo styleFile( info.absoluteFilePath() + "/style.qss" );
515  if ( !styleFile.exists() )
516  continue;
517 
518  QString name = info.baseName();
519  QString path = info.absoluteFilePath();
520  mapping.insert( name, path );
521  }
522  }
523  return mapping;
524 }
525 
530 {
531  return ABISYM( mPkgDataPath ) + QLatin1String( "/doc/AUTHORS" );
532 }
537 {
538  return ABISYM( mPkgDataPath ) + QLatin1String( "/doc/CONTRIBUTORS" );
539 }
541 {
542  return ABISYM( mPkgDataPath ) + QLatin1String( "/doc/developersmap.html" );
543 }
544 
549 {
550  return ABISYM( mPkgDataPath ) + QLatin1String( "/doc/SPONSORS" );
551 }
552 
557 {
558  return ABISYM( mPkgDataPath ) + QLatin1String( "/doc/DONORS" );
559 }
560 
563 {
564  return ABISYM( mPkgDataPath ) + QLatin1String( "/doc/TRANSLATORS" );
565 }
566 
569 {
570  return ABISYM( mPkgDataPath ) + QLatin1String( "/doc/LICENSE" );
571 }
572 
577 {
579 #ifdef Q_OS_MACX
580  helpAppPath = applicationDirPath() + "/bin/qgis_help.app/Contents/MacOS";
581 #else
582  helpAppPath = libexecPath();
583 #endif
584  helpAppPath += "/qgis_help";
585 #ifdef Q_OS_WIN
586  helpAppPath += ".exe";
587 #endif
588  return helpAppPath;
589 }
594 {
595  if ( ABISYM( mRunningFromBuildDir ) )
596  return ABISYM( mBuildOutputPath ) + QLatin1String( "/i18n" );
597  else
598  return ABISYM( mPkgDataPath ) + QLatin1String( "/i18n/" );
599 }
600 
605 {
606  return ABISYM( mPkgDataPath ) + QLatin1String( "/resources/qgis.db" );
607 }
608 
613 {
614  return ABISYM( mConfigPath );
615 }
616 
621 {
622  return qgisSettingsDirPath() + QLatin1String( "qgis.db" );
623 }
624 
629 {
630  return ABISYM( mAuthDbDirPath ) + QLatin1String( "qgis-auth.db" );
631 }
632 
637 {
638  return QString( ":/images/splash/" );
639 }
640 
645 {
646  return ABISYM( mPkgDataPath ) + QLatin1String( "/images/icons/" );
647 }
652 {
653  if ( ABISYM( mRunningFromBuildDir ) )
654  {
655  QString tempCopy = QDir::tempPath() + "/srs.db";
656 
657  if ( !QFile( tempCopy ).exists() )
658  {
659  QFile f( ABISYM( mPkgDataPath ) + "/resources/srs.db" );
660  if ( !f.copy( tempCopy ) )
661  {
662  qFatal( "Could not create temporary copy" );
663  }
664  }
665 
666  return tempCopy;
667  }
668  else
669  {
670  return ABISYM( mPkgDataPath ) + QLatin1String( "/resources/srs.db" );
671  }
672 }
673 
678 {
679  //local directories to search when looking for an SVG with a given basename
680  //defined by user in options dialog
681  QSettings settings;
682  QStringList myPathList;
683  QString myPaths = settings.value( "svg/searchPathsForSVG", "" ).toString();
684  if ( !myPaths.isEmpty() )
685  {
686  myPathList = myPaths.split( "|" );
687  }
688 
689  myPathList << ABISYM( mDefaultSvgPaths );
690  return myPathList;
691 }
692 
694 {
695  return qgisSettingsDirPath() + QLatin1String( "symbology-ng-style.db" );
696 }
697 
699 {
700  return qgisSettingsDirPath() + QLatin1String( "/themes" );
701 }
702 
704 {
705  return ABISYM( mPkgDataPath ) + QLatin1String( "/resources/symbology-ng-style.db" );
706 }
707 
709 {
710  return ABISYM( mPkgDataPath ) + QLatin1String( "/resources/themes" );
711 }
712 
714 {
715  return ABISYM( mLibraryPath );
716 }
717 
719 {
720  return ABISYM( mLibexecPath );
721 }
722 
724 {
725  return ( htonl( 1 ) == 1 ) ? XDR : NDR;
726 }
727 
729 {
730  // set the provider plugin path (this creates provider registry)
732 
733  // create map layer registry if doesn't exist
735 
736  // initialize authentication manager and connect to database
738 }
739 
741 {
743 
744  delete QgsAuthManager::instance();
745 
746  //Ensure that all remaining deleteLater QObjects are actually deleted before we exit.
747  //This isn't strictly necessary (since we're exiting anyway) but doing so prevents a lot of
748  //LeakSanitiser noise which hides real issues
749  QgsApplication::sendPostedEvents( 0, QEvent::DeferredDelete );
750 
751  //delete all registered functions from expression engine (see above comment)
753 }
754 
756 {
757  QString myEnvironmentVar( getenv( "QGIS_PREFIX_PATH" ) );
758  QString myState = tr( "Application state:\n"
759  "QGIS_PREFIX_PATH env var:\t\t%1\n"
760  "Prefix:\t\t%2\n"
761  "Plugin Path:\t\t%3\n"
762  "Package Data Path:\t%4\n"
763  "Active Theme Name:\t%5\n"
764  "Active Theme Path:\t%6\n"
765  "Default Theme Path:\t%7\n"
766  "SVG Search Paths:\t%8\n"
767  "User DB Path:\t%9\n"
768  "Auth DB Path:\t%10\n" )
769  .arg( myEnvironmentVar,
770  prefixPath(),
771  pluginPath(),
772  pkgDataPath(),
773  themeName(),
774  activeThemePath(),
776  svgPaths().join( tr( "\n\t\t", "match indentation of application state" ) ),
778  .arg( qgisAuthDbFilePath() );
779  return myState;
780 }
781 
783 {
784  //
785  // Make the style sheet desktop preferences aware by using qappliation
786  // palette as a basis for colors where appropriate
787  //
788 // QColor myColor1 = palette().highlight().color();
789  QColor myColor1( Qt::lightGray );
790  QColor myColor2 = myColor1;
791  myColor2 = myColor2.lighter( 110 ); //10% lighter
792  QString myStyle;
793  myStyle = "p.glossy{ background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, "
794  " stop: 0 " + myColor1.name() + ","
795  " stop: 0.1 " + myColor2.name() + ","
796  " stop: 0.5 " + myColor1.name() + ","
797  " stop: 0.9 " + myColor2.name() + ","
798  " stop: 1 " + myColor1.name() + ");"
799  " color: black;"
800  " padding-left: 4px;"
801  " padding-top: 20px;"
802  " padding-bottom: 8px;"
803  " border: 1px solid #6c6c6c;"
804  "}"
805  "p.subheaderglossy{ background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, "
806  " stop: 0 " + myColor1.name() + ","
807  " stop: 0.1 " + myColor2.name() + ","
808  " stop: 0.5 " + myColor1.name() + ","
809  " stop: 0.9 " + myColor2.name() + ","
810  " stop: 1 " + myColor1.name() + ");"
811  " font-weight: bold;"
812  " font-size: medium;"
813  " line-height: 1.1em;"
814  " width: 100%;"
815  " color: black;"
816  " padding-left: 4px;"
817  " padding-right: 4px;"
818  " padding-top: 20px;"
819  " padding-bottom: 8px;"
820  " border: 1px solid #6c6c6c;"
821  "}"
822  "th.glossy{ background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, "
823  " stop: 0 " + myColor1.name() + ","
824  " stop: 0.1 " + myColor2.name() + ","
825  " stop: 0.5 " + myColor1.name() + ","
826  " stop: 0.9 " + myColor2.name() + ","
827  " stop: 1 " + myColor1.name() + ");"
828  " color: black;"
829  " border: 1px solid #6c6c6c;"
830  "}"
831  ".overview{ font: 1.82em; font-weight: bold;}"
832  "body{ background: white;"
833  " color: black;"
834  " font-family: arial,sans-serif;"
835  "}"
836  "h1{ background-color: #F6F6F6;"
837  " color: #8FB171; "
838  " font-size: x-large; "
839  " font-weight: normal;"
840  " font-family: luxi serif, georgia, times new roman, times, serif;"
841  " background: none;"
842  " padding: 0.75em 0 0;"
843  " margin: 0;"
844  " line-height: 3em;"
845  "}"
846  "h2{ background-color: #F6F6F6;"
847  " color: #8FB171; "
848  " font-size: medium; "
849  " font-weight: normal;"
850  " font-family: luxi serif, georgia, times new roman, times, serif;"
851  " background: none;"
852  " padding: 0.75em 0 0;"
853  " margin: 0;"
854  " line-height: 1.1em;"
855  "}"
856  "h3{ background-color: #F6F6F6;"
857  " color: #729FCF;"
858  " font-family: luxi serif, georgia, times new roman, times, serif;"
859  " font-weight: bold;"
860  " font-size: large;"
861  " text-align: right;"
862  " border-bottom: 5px solid #DCEB5C;"
863  "}"
864  "h4{ background-color: #F6F6F6;"
865  " color: #729FCF;"
866  " font-family: luxi serif, georgia, times new roman, times, serif;"
867  " font-weight: bold;"
868  " font-size: medium;"
869  " text-align: right;"
870  "}"
871  "h5{ background-color: #F6F6F6;"
872  " color: #729FCF;"
873  " font-family: luxi serif, georgia, times new roman, times, serif;"
874  " font-weight: bold;"
875  " font-size: small;"
876  " text-align: right;"
877  "}"
878  "a{ color: #729FCF;"
879  " font-family: arial,sans-serif;"
880  " font-size: small;"
881  "}"
882  "label{ background-color: #FFFFCC;"
883  " border: 1px solid black;"
884  " margin: 1px;"
885  " padding: 0px 3px; "
886  " font-size: small;"
887  "}";
888  return myStyle;
889 }
890 
892 {
893  if ( 0 >= OGRGetDriverCount() )
894  {
895  OGRRegisterAll();
896  }
897 }
898 
900 {
901 #if defined( Q_OS_WIN )
902  const Qt::CaseSensitivity cs = Qt::CaseInsensitive;
903 
904  aPath.replace( "\\", "/" );
905  if ( aPath.startsWith( "//" ) )
906  {
907  // keep UNC prefix
908  aPath = "\\\\" + aPath.mid( 2 );
909  }
910 
911  targetPath.replace( "\\", "/" );
912  if ( targetPath.startsWith( "//" ) )
913  {
914  // keep UNC prefix
915  targetPath = "\\\\" + targetPath.mid( 2 );
916  }
917 #else
918  const Qt::CaseSensitivity cs = Qt::CaseSensitive;
919 #endif
920 
921  QStringList targetElems = targetPath.split( "/", QString::SkipEmptyParts );
922  QStringList aPathElems = aPath.split( "/", QString::SkipEmptyParts );
923 
924  targetElems.removeAll( "." );
925  aPathElems.removeAll( "." );
926 
927  // remove common part
928  int n = 0;
929  while ( aPathElems.size() > 0 &&
930  targetElems.size() > 0 &&
931  aPathElems[0].compare( targetElems[0], cs ) == 0 )
932  {
933  aPathElems.removeFirst();
934  targetElems.removeFirst();
935  n++;
936  }
937 
938  if ( n == 0 )
939  {
940  // no common parts; might not even be a file
941  return aPath;
942  }
943 
944  if ( targetElems.size() > 0 )
945  {
946  // go up to the common directory
947  for ( int i = 0; i < targetElems.size(); i++ )
948  {
949  aPathElems.insert( 0, ".." );
950  }
951  }
952  else
953  {
954  // let it start with . nevertheless,
955  // so relative path always start with either ./ or ../
956  aPathElems.insert( 0, "." );
957  }
958 
959  return aPathElems.join( "/" );
960 }
961 
963 {
964  // relative path should always start with ./ or ../
965  if ( !rpath.startsWith( "./" ) && !rpath.startsWith( "../" ) )
966  {
967  return rpath;
968  }
969 
970 #if defined(Q_OS_WIN)
971  rpath.replace( "\\", "/" );
972  targetPath.replace( "\\", "/" );
973 
974  bool uncPath = targetPath.startsWith( "//" );
975 #endif
976 
977  QStringList srcElems = rpath.split( "/", QString::SkipEmptyParts );
978  QStringList targetElems = targetPath.split( "/", QString::SkipEmptyParts );
979 
980 #if defined(Q_OS_WIN)
981  if ( uncPath )
982  {
983  targetElems.insert( 0, "" );
984  targetElems.insert( 0, "" );
985  }
986 #endif
987 
988  // append source path elements
989  targetElems << srcElems;
990  targetElems.removeAll( "." );
991 
992  // resolve ..
993  int pos;
994  while (( pos = targetElems.indexOf( ".." ) ) > 0 )
995  {
996  // remove preceding element and ..
997  targetElems.removeAt( pos - 1 );
998  targetElems.removeAt( pos - 1 );
999  }
1000 
1001 #if !defined(Q_OS_WIN)
1002  // make path absolute
1003  targetElems.prepend( "" );
1004 #endif
1005 
1006  return targetElems.join( "/" );
1007 }
1008 
1009 void QgsApplication::skipGdalDriver( const QString& theDriver )
1010 {
1011  if ( ABISYM( mGdalSkipList ).contains( theDriver ) || theDriver.isEmpty() )
1012  {
1013  return;
1014  }
1015  ABISYM( mGdalSkipList ) << theDriver;
1017 }
1018 
1020 {
1021  if ( !ABISYM( mGdalSkipList ).contains( theDriver ) )
1022  {
1023  return;
1024  }
1025  int myPos = ABISYM( mGdalSkipList ).indexOf( theDriver );
1026  if ( myPos >= 0 )
1027  {
1028  ABISYM( mGdalSkipList ).removeAt( myPos );
1029  }
1031 }
1032 
1034 {
1035  ABISYM( mGdalSkipList ).removeDuplicates();
1036  QString myDriverList = ABISYM( mGdalSkipList ).join( " " );
1037  QgsDebugMsg( "Gdal Skipped driver list set to:" );
1038  QgsDebugMsg( myDriverList );
1039  CPLSetConfigOption( "GDAL_SKIP", myDriverList.toUtf8() );
1040  GDALAllRegister(); //to update driver list and skip missing ones
1041 }
1042 
1044 {
1045  QString folder = userThemesFolder();
1046  QDir myDir( folder );
1047  if ( !myDir.exists() )
1048  {
1049  myDir.mkpath( folder );
1050  }
1051 
1052  copyPath( defaultThemesFolder(), userThemesFolder() );
1053  return true;
1054 }
1055 
1056 void QgsApplication::copyPath( const QString& src, const QString& dst )
1057 {
1058  QDir dir( src );
1059  if ( ! dir.exists() )
1060  return;
1061 
1062  Q_FOREACH ( const QString& d, dir.entryList( QDir::Dirs | QDir::NoDotAndDotDot ) )
1063  {
1064  QString dst_path = dst + QDir::separator() + d;
1065  dir.mkpath( dst_path );
1066  copyPath( src + QDir::separator() + d, dst_path );
1067  }
1068 
1069  Q_FOREACH ( const QString& f, dir.entryList( QDir::Files ) )
1070  {
1071  QFile::copy( src + QDir::separator() + f, dst + QDir::separator() + f );
1072  }
1073 }
1074 
1075 bool QgsApplication::createDB( QString *errorMessage )
1076 {
1077  // set a working directory up for gdal to write .aux.xml files into
1078  // for cases where the raster dir is read only to the user
1079  // if the env var is already set it will be used preferentially
1080  QString myPamPath = qgisSettingsDirPath() + QLatin1String( "gdal_pam/" );
1081  QDir myDir( myPamPath );
1082  if ( !myDir.exists() )
1083  {
1084  myDir.mkpath( myPamPath ); //fail silently
1085  }
1086 
1087 #if defined(Q_OS_WIN)
1088  CPLSetConfigOption( "GDAL_PAM_PROXY_DIR", myPamPath.toUtf8() );
1089 #else
1090  //under other OS's we use an environment var so the user can
1091  //override the path if he likes
1092  int myChangeFlag = 0; //whether we want to force the env var to change
1093  setenv( "GDAL_PAM_PROXY_DIR", myPamPath.toUtf8(), myChangeFlag );
1094 #endif
1095 
1096  // Check qgis.db and make private copy if necessary
1097  QFile qgisPrivateDbFile( QgsApplication::qgisUserDbFilePath() );
1098 
1099  // first we look for ~/.qgis/qgis.db
1100  if ( !qgisPrivateDbFile.exists() )
1101  {
1102  // if it doesnt exist we copy it in from the global resources dir
1103  QString qgisMasterDbFileName = QgsApplication::qgisMasterDbFilePath();
1104  QFile masterFile( qgisMasterDbFileName );
1105 
1106  // Must be sure there is destination directory ~/.qgis
1108 
1109  //now copy the master file into the users .qgis dir
1110  bool isDbFileCopied = masterFile.copy( qgisPrivateDbFile.fileName() );
1111 
1112  if ( !isDbFileCopied )
1113  {
1114  if ( errorMessage )
1115  {
1116  *errorMessage = tr( "[ERROR] Can not make qgis.db private copy" );
1117  }
1118  return false;
1119  }
1120  }
1121  else
1122  {
1123  // migrate if necessary
1124  sqlite3 *db;
1125  if ( sqlite3_open( QgsApplication::qgisUserDbFilePath().toUtf8().constData(), &db ) != SQLITE_OK )
1126  {
1127  if ( errorMessage )
1128  {
1129  *errorMessage = tr( "Could not open qgis.db" );
1130  }
1131  return false;
1132  }
1133 
1134  char *errmsg;
1135  int res = sqlite3_exec( db, "SELECT epsg FROM tbl_srs LIMIT 0", 0, 0, &errmsg );
1136  if ( res == SQLITE_OK )
1137  {
1138  // epsg column exists => need migration
1139  if ( sqlite3_exec( db,
1140  "ALTER TABLE tbl_srs RENAME TO tbl_srs_bak;"
1141  "CREATE TABLE tbl_srs ("
1142  "srs_id INTEGER PRIMARY KEY,"
1143  "description text NOT NULL,"
1144  "projection_acronym text NOT NULL,"
1145  "ellipsoid_acronym NOT NULL,"
1146  "parameters text NOT NULL,"
1147  "srid integer,"
1148  "auth_name varchar,"
1149  "auth_id varchar,"
1150  "is_geo integer NOT NULL,"
1151  "deprecated boolean);"
1152  "CREATE INDEX idx_srsauthid on tbl_srs(auth_name,auth_id);"
1153  "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;"
1154  "DROP TABLE tbl_srs_bak", 0, 0, &errmsg ) != SQLITE_OK
1155  )
1156  {
1157  if ( errorMessage )
1158  {
1159  *errorMessage = tr( "Migration of private qgis.db failed.\n%1" ).arg( QString::fromUtf8( errmsg ) );
1160  }
1161  sqlite3_free( errmsg );
1162  sqlite3_close( db );
1163  return false;
1164  }
1165  }
1166  else
1167  {
1168  sqlite3_free( errmsg );
1169  }
1170 
1171  if ( sqlite3_exec( db, "DROP VIEW vw_srs", 0, 0, &errmsg ) != SQLITE_OK )
1172  {
1173  QgsDebugMsg( QString( "vw_srs didn't exists in private qgis.db: %1" ).arg( errmsg ) );
1174  }
1175 
1176  if ( sqlite3_exec( db,
1177  "CREATE VIEW vw_srs AS"
1178  " SELECT"
1179  " a.description AS description"
1180  ",a.srs_id AS srs_id"
1181  ",a.is_geo AS is_geo"
1182  ",coalesce(b.name,a.projection_acronym) AS name"
1183  ",a.parameters AS parameters"
1184  ",a.auth_name AS auth_name"
1185  ",a.auth_id AS auth_id"
1186  ",a.deprecated AS deprecated"
1187  " FROM tbl_srs a"
1188  " LEFT OUTER JOIN tbl_projection b ON a.projection_acronym=b.acronym"
1189  " ORDER BY coalesce(b.name,a.projection_acronym),a.description", 0, 0, &errmsg ) != SQLITE_OK
1190  )
1191  {
1192  if ( errorMessage )
1193  {
1194  *errorMessage = tr( "Update of view in private qgis.db failed.\n%1" ).arg( QString::fromUtf8( errmsg ) );
1195  }
1196  sqlite3_free( errmsg );
1197  sqlite3_close( db );
1198  return false;
1199  }
1200 
1201  sqlite3_close( db );
1202  }
1203  return true;
1204 }
1205 
1206 void QgsApplication::setMaxThreads( int maxThreads )
1207 {
1208  QgsDebugMsg( QString( "maxThreads: %1" ).arg( maxThreads ) );
1209 
1210  // make sure value is between 1 and #cores, if not set to -1 (use #cores)
1211  // 0 could be used to disable any parallel processing
1212  if ( maxThreads < 1 || maxThreads > QThread::idealThreadCount() )
1213  maxThreads = -1;
1214 
1215  // save value
1216  ABISYM( mMaxThreads ) = maxThreads;
1217 
1218  // if -1 use #cores
1219  if ( maxThreads == -1 )
1220  maxThreads = QThread::idealThreadCount();
1221 
1222  // set max thread count in QThreadPool
1224  QgsDebugMsg( QString( "set QThreadPool max thread count to %1" ).arg( QThreadPool::globalInstance()->maxThreadCount() ) );
1225 }
1226 
static void init(QString customConfigPath=QString())
This method initialises paths etc for QGIS.
QString fromAscii(const char *str, int size)
int indexOf(QChar ch, int from, Qt::CaseSensitivity cs) const
static unsigned index
static QgsProviderRegistry * instance(const QString &pluginPath=QString::null)
Means of accessing canonical single instance.
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 void skipGdalDriver(const QString &theDriver)
Sets the GDAL_SKIP environment variable to include the specified driver and then calls GDALDriverMana...
static QgsAuthManager * instance()
Enforce singleton pattern.
QStringList systemEnvironment()
static QString authorsFilePath()
Returns the path to the authors file.
static QString qgisSettingsDirPath()
Returns the path to the settings directory in user's home dir.
static QString qgisUserDbFilePath()
Returns the path to the user qgis.db file.
static QString libraryPath()
Returns the path containing qgis_core, qgis_gui, qgispython (and other) libraries.
static QString defaultThemePath()
Returns the path to the default theme directory.
QString readLine(qint64 maxlen)
virtual bool event(QEvent *event) override
Watch for QFileOpenEvent.
QString name() const
static QString qgisAuthDbFilePath()
Returns the path to the user authentication database file: qgis-auth.db.
static QString donorsFilePath()
Returns the path to the donors file.
static void setPrefixPath(const QString &thePrefixPath, bool useDefaultPaths=false)
Alters prefix path - used by 3rd party apps.
#define QgsDebugMsg(str)
Definition: qgslogger.h:33
QStringList split(const QString &sep, SplitBehavior behavior, Qt::CaseSensitivity cs) const
static QIcon getThemeIcon(const QString &theName)
Helper to get a theme icon.
static QString themeName()
Set the active theme to the specified theme.
static QString defaultThemesFolder()
Returns the path to default themes folder from install (works as a starting point).
void removeFirst()
static QString iconPath(const QString &iconFile)
Returns path to the desired icon file.
QThreadPool * globalInstance()
void removeAt(int i)
void setFileName(const QString &name)
static void registerOgrDrivers()
Register OGR drivers ensuring this only happens once.
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()
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)
static QString developersMapFilePath()
Returns the path to the developers map file.
void addLibraryPath(const QString &path)
int size() const
static void applyGdalSkippedDrivers()
Apply the skipped drivers list to gdal.
const char * name() const
QString canonicalFilePath() const
QWidget * activeWindow()
bool exists() const
QString fromUtf8(const char *str, int size)
bool atEnd() const
void setMaxThreadCount(int maxThreadCount)
QString tempPath()
static QString pluginPath()
Returns the path to the application plugin directory.
bool isDir() const
static void setThemeName(const QString &theThemeName)
Set the active theme to the specified theme.
bool init(const QString &pluginPath=QString::null)
Initialize QCA, prioritize qca-ossl plugin and optionally set up the authentication database...
static QString helpAppPath()
Returns the path to the help application.
static bool createThemeFolder()
Create the users theme folder.
static void cleanRegisteredFunctions()
Deletes all registered functions whose ownership have been transferred to the expression engine...
QFileInfoList entryInfoList(QFlags< QDir::Filter > filters, QFlags< QDir::SortFlag > sort) const
QString absoluteFilePath() const
virtual ~QgsApplication()
bool isEmpty() const
int removeAll(const T &value)
static QString i18nPath()
Returns the path to the translation directory.
bool sendEvent(QObject *receiver, QEvent *event)
bool startsWith(const QString &s, Qt::CaseSensitivity cs) const
QByteArray readAll()
static void setPkgDataPath(const QString &thePkgDataPath)
Alters pkg data path - used by 3rd party apps.
static QString splashPath()
Returns the path to the splash screen image directory.
QStringList ABISYM(QgsApplication::mFileOpenEventList)
static const char * QGIS_ORGANIZATION_NAME
static QString qgisMasterDbFilePath()
Returns the path to the master qgis.db file.
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.
bool cdUp()
static void restoreGdalDriver(const QString &theDriver)
Sets the GDAL_SKIP environment variable to exclude the specified driver and then calls GDALDriverMana...
bool exists() const
static QString pkgDataPath()
Returns the common root path of all application data directories.
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
virtual void close()
static void setAuthDbDirPath(const QString &theAuthDbDirPath)
Alters authentication data base directory path - used by 3rd party apps.
static QString relativePathToAbsolutePath(QString rpath, QString targetPath)
Converts path relative to target to an absolute path.
static QString defaultStyleV2Path()
Returns the path to default style (works as a starting point).
static QString userStyleV2Path()
Returns the path to user's style.
QString & replace(int position, int n, QChar after)
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 QString contributorsFilePath()
Returns the path to the contributors file.
static QString activeThemePath()
Returns the path to the currently active theme directory.
QgsApplication(int &argc, char **argv, bool GUIenabled, const QString &customConfigPath=QString())
virtual bool event(QEvent *e)
QString absolutePath() const
void insert(int i, const T &value)
void sendPostedEvents()
QThread * currentThread()
StandardButton critical(QWidget *parent, const QString &title, const QString &text, QFlags< QMessageBox::StandardButton > buttons, StandardButton defaultButton)
QString styleSheet() const
bool isWritable() const
int length() const
QString left(int n) const
static void exitQgis()
deletes provider registry and map layer registry
static QStringList svgPaths()
Returns the pathes to svg directories.
static 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)
bool contains(const Key &key) const
static QString srsDbFilePath()
Returns the path to the srs.db file.
static QHash< QString, QString > uiThemes()
All themes found in ~/.qgis2/themes folder.
static QString libexecPath()
Returns the path with utility executables (help viewer, crssync, ...)
static QString prefixPath()
Returns the path to the application prefix directory.
static QString iconsPath()
Returns the path to the icons image directory.
static QString translatorsFilePath()
Returns the path to the sponsors file.
static const char * QGIS_APPLICATION_NAME
QString applicationDirPath()
virtual bool notify(QObject *receiver, QEvent *e)
QString arg(qlonglong a, int fieldWidth, int base, const QChar &fillChar) const
QString toString() const
static const int QGIS_VERSION_INT
Definition: qgis.h:44
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)
Set the current UI theme used to style the interface.
static QString licenceFilePath()
Returns the path to the licence file.
qint64 readLine(char *data, qint64 maxSize)
static QString userThemesFolder()
Returns the path to user's themes folder.
void preNotify(QObject *receiver, QEvent *event, bool *done)
QByteArray toUtf8() const