QGIS API Documentation  2.11.0-Master
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups 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 ( const 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 userThemesFolder() + QDir::separator() + themeName() + QDir::separator() + "icons/";
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  ABISYM( mThemeName ) = theThemeName;
417 }
422 {
423  return ABISYM( mThemeName );
424 }
425 
426 void QgsApplication::setUITheme( const QString &themeName )
427 {
428  // Loop all style sheets, find matching name, load it.
430  QString themename = themeName;
431  if (!themes.contains(themename))
432  themename = "default";
433 
434  QString path = themes[themename];
435  QString stylesheetname = path + "/style.qss";
436  QString autostylesheet = stylesheetname + ".auto";
437 
438  QFile file( stylesheetname );
439  QFile variablesfile( path + "/variables.qss" );
440  QFile fileout( autostylesheet );
441 
442  QFileInfo variableInfo( variablesfile );
443 
444  if ( variableInfo.exists() && variablesfile.open( QIODevice::ReadOnly ) )
445  {
446  if ( !file.open( QIODevice::ReadOnly ) || !fileout.open( QIODevice::WriteOnly | QIODevice::Text ) )
447  {
448  return;
449  }
450 
451  QHash<QString, QString> variables;
452  QString styledata = file.readAll();
453  QTextStream in( &variablesfile );
454  while ( !in.atEnd() )
455  {
456  QString line = in.readLine();
457  // This is is a variable
458  if ( line.startsWith( "@" ) )
459  {
460  int index = line.indexOf( ":" );
461  QString name = line.mid( 0, index );
462  QString value = line.mid( index + 1, line.length() );
463  styledata.replace( name, value );
464  }
465  }
466  variablesfile.close();
467  QTextStream out( &fileout );
468  out << styledata;
469  fileout.close();
470  file.close();
471  stylesheetname = autostylesheet;
472  }
473 
474  QString styleSheet = QLatin1String( "file:///" );
475  styleSheet.append( stylesheetname );
476  qApp->setStyleSheet( styleSheet );
477  setThemeName( themename );
478 }
479 
481 {
483  QHash<QString, QString> mapping;
484  mapping.insert( "default", "" );
485  foreach ( const QString& path, paths )
486  {
487  QDir folder( path );
488  QFileInfoList styleFiles = folder.entryInfoList( QDir::Dirs | QDir::NoDotAndDotDot );
489  foreach ( const QFileInfo& info, styleFiles )
490  {
491  QFileInfo styleFile( info.absoluteFilePath() + "/style.qss" );
492  if ( !styleFile.exists() )
493  continue;
494 
495  QString name = info.baseName();
496  QString path = info.absoluteFilePath();
497  mapping.insert( name, path );
498  }
499  }
500  return mapping;
501 }
502 
507 {
508  return ABISYM( mPkgDataPath ) + QString( "/doc/AUTHORS" );
509 }
514 {
515  return ABISYM( mPkgDataPath ) + QString( "/doc/CONTRIBUTORS" );
516 }
518 {
519  return ABISYM( mPkgDataPath ) + QString( "/doc/developersmap.html" );
520 }
521 
523 {
524  return ABISYM( mPkgDataPath ) + QString( "/doc/whatsnew.html" );
525 }
530 {
531  return ABISYM( mPkgDataPath ) + QString( "/doc/SPONSORS" );
532 }
533 
538 {
539  return ABISYM( mPkgDataPath ) + QString( "/doc/DONORS" );
540 }
541 
544 {
545  return ABISYM( mPkgDataPath ) + QString( "/doc/TRANSLATORS" );
546 }
547 
550 {
551  return ABISYM( mPkgDataPath ) + QString( "/doc/LICENSE" );
552 }
553 
558 {
560 #ifdef Q_OS_MACX
561  helpAppPath = applicationDirPath() + "/bin/qgis_help.app/Contents/MacOS";
562 #else
563  helpAppPath = libexecPath();
564 #endif
565  helpAppPath += "/qgis_help";
566 #ifdef Q_OS_WIN
567  helpAppPath += ".exe";
568 #endif
569  return helpAppPath;
570 }
575 {
576  if ( ABISYM( mRunningFromBuildDir ) )
577  return ABISYM( mBuildOutputPath ) + QString( "/i18n" );
578  else
579  return ABISYM( mPkgDataPath ) + QString( "/i18n/" );
580 }
581 
586 {
587  return ABISYM( mPkgDataPath ) + QString( "/resources/qgis.db" );
588 }
589 
594 {
595  return ABISYM( mConfigPath );
596 }
597 
602 {
603  return qgisSettingsDirPath() + QString( "qgis.db" );
604 }
605 
610 {
611  return QString( ":/images/splash/" );
612 }
613 
618 {
619  return ABISYM( mPkgDataPath ) + QString( "/images/icons/" );
620 }
625 {
626  if ( ABISYM( mRunningFromBuildDir ) )
627  {
628  QString tempCopy = QDir::tempPath() + "/srs.db";
629 
630  if ( !QFile( tempCopy ).exists() )
631  {
632  QFile f( ABISYM( mPkgDataPath ) + "/resources/srs.db" );
633  if ( !f.copy( tempCopy ) )
634  {
635  qFatal( "Could not create temporary copy" );
636  }
637  }
638 
639  return tempCopy;
640  }
641  else
642  {
643  return ABISYM( mPkgDataPath ) + QString( "/resources/srs.db" );
644  }
645 }
646 
651 {
652  //local directories to search when looking for an SVG with a given basename
653  //defined by user in options dialog
654  QSettings settings;
655  QStringList myPathList;
656  QString myPaths = settings.value( "svg/searchPathsForSVG", "" ).toString();
657  if ( !myPaths.isEmpty() )
658  {
659  myPathList = myPaths.split( "|" );
660  }
661 
662  myPathList << ABISYM( mDefaultSvgPaths );
663  return myPathList;
664 }
665 
667 {
668  return qgisSettingsDirPath() + QString( "symbology-ng-style.db" );
669 }
670 
672 {
673  return qgisSettingsDirPath() + QString( "/themes" );
674 }
675 
677 {
678  return ABISYM( mPkgDataPath ) + QString( "/resources/symbology-ng-style.db" );
679 }
680 
682 {
683  return ABISYM( mPkgDataPath ) + QString( "/resources/themes" );
684 }
685 
687 {
688  return ABISYM( mLibraryPath );
689 }
690 
692 {
693  return ABISYM( mLibexecPath );
694 }
695 
697 {
698  return ( htonl( 1 ) == 1 ) ? XDR : NDR;
699 }
700 
702 {
703  // set the provider plugin path (this creates provider registry)
705 
706  // create map layer registry if doesn't exist
708 }
709 
711 {
713 
714  //Ensure that all remaining deleteLater QObjects are actually deleted before we exit.
715  //This isn't strictly necessary (since we're exiting anyway) but doing so prevents a lot of
716  //LeakSanitiser noise which hides real issues
717  QgsApplication::sendPostedEvents( 0, QEvent::DeferredDelete );
718 
719  //delete all registered functions from expression engine (see above comment)
721 }
722 
724 {
725  QString myEnvironmentVar( getenv( "QGIS_PREFIX_PATH" ) );
726  QString myState = tr( "Application state:\n"
727  "QGIS_PREFIX_PATH env var:\t\t%1\n"
728  "Prefix:\t\t%2\n"
729  "Plugin Path:\t\t%3\n"
730  "Package Data Path:\t%4\n"
731  "Active Theme Name:\t%5\n"
732  "Active Theme Path:\t%6\n"
733  "Default Theme Path:\t%7\n"
734  "SVG Search Paths:\t%8\n"
735  "User DB Path:\t%9\n" )
736  .arg( myEnvironmentVar )
737  .arg( prefixPath() )
738  .arg( pluginPath() )
739  .arg( pkgDataPath() )
740  .arg( themeName() )
741  .arg( activeThemePath() )
742  .arg( defaultThemePath() )
743  .arg( svgPaths().join( tr( "\n\t\t", "match indentation of application state" ) ) )
745  return myState;
746 }
747 
749 {
750  //
751  // Make the style sheet desktop preferences aware by using qappliation
752  // palette as a basis for colors where appropriate
753  //
754 // QColor myColor1 = palette().highlight().color();
755  QColor myColor1( Qt::lightGray );
756  QColor myColor2 = myColor1;
757  myColor2 = myColor2.lighter( 110 ); //10% lighter
758  QString myStyle;
759  myStyle = "p.glossy{ background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, "
760  " stop: 0 " + myColor1.name() + ","
761  " stop: 0.1 " + myColor2.name() + ","
762  " stop: 0.5 " + myColor1.name() + ","
763  " stop: 0.9 " + myColor2.name() + ","
764  " stop: 1 " + myColor1.name() + ");"
765  " color: black;"
766  " padding-left: 4px;"
767  " padding-top: 20px;"
768  " padding-bottom: 8px;"
769  " border: 1px solid #6c6c6c;"
770  "}"
771  "p.subheaderglossy{ background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, "
772  " stop: 0 " + myColor1.name() + ","
773  " stop: 0.1 " + myColor2.name() + ","
774  " stop: 0.5 " + myColor1.name() + ","
775  " stop: 0.9 " + myColor2.name() + ","
776  " stop: 1 " + myColor1.name() + ");"
777  " font-weight: bold;"
778  " font-size: medium;"
779  " line-height: 1.1em;"
780  " width: 100%;"
781  " color: black;"
782  " padding-left: 4px;"
783  " padding-right: 4px;"
784  " padding-top: 20px;"
785  " padding-bottom: 8px;"
786  " border: 1px solid #6c6c6c;"
787  "}"
788  "th.glossy{ background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, "
789  " stop: 0 " + myColor1.name() + ","
790  " stop: 0.1 " + myColor2.name() + ","
791  " stop: 0.5 " + myColor1.name() + ","
792  " stop: 0.9 " + myColor2.name() + ","
793  " stop: 1 " + myColor1.name() + ");"
794  " color: black;"
795  " border: 1px solid #6c6c6c;"
796  "}"
797  ".overview{ font: 1.82em; font-weight: bold;}"
798  "body{ background: white;"
799  " color: black;"
800  " font-family: arial,sans-serif;"
801  "}"
802  "h1{ background-color: #F6F6F6;"
803  " color: #8FB171; "
804  " font-size: x-large; "
805  " font-weight: normal;"
806  " font-family: luxi serif, georgia, times new roman, times, serif;"
807  " background: none;"
808  " padding: 0.75em 0 0;"
809  " margin: 0;"
810  " line-height: 3em;"
811  "}"
812  "h2{ background-color: #F6F6F6;"
813  " color: #8FB171; "
814  " font-size: medium; "
815  " font-weight: normal;"
816  " font-family: luxi serif, georgia, times new roman, times, serif;"
817  " background: none;"
818  " padding: 0.75em 0 0;"
819  " margin: 0;"
820  " line-height: 1.1em;"
821  "}"
822  "h3{ background-color: #F6F6F6;"
823  " color: #729FCF;"
824  " font-family: luxi serif, georgia, times new roman, times, serif;"
825  " font-weight: bold;"
826  " font-size: large;"
827  " text-align: right;"
828  " border-bottom: 5px solid #DCEB5C;"
829  "}"
830  "h4{ background-color: #F6F6F6;"
831  " color: #729FCF;"
832  " font-family: luxi serif, georgia, times new roman, times, serif;"
833  " font-weight: bold;"
834  " font-size: medium;"
835  " text-align: right;"
836  "}"
837  "h5{ background-color: #F6F6F6;"
838  " color: #729FCF;"
839  " font-family: luxi serif, georgia, times new roman, times, serif;"
840  " font-weight: bold;"
841  " font-size: small;"
842  " text-align: right;"
843  "}"
844  "a{ color: #729FCF;"
845  " font-family: arial,sans-serif;"
846  " font-size: small;"
847  "}"
848  "label{ background-color: #FFFFCC;"
849  " border: 1px solid black;"
850  " margin: 1px;"
851  " padding: 0px 3px; "
852  " font-size: small;"
853  "}";
854  return myStyle;
855 }
856 
858 {
859  if ( 0 >= OGRGetDriverCount() )
860  {
861  OGRRegisterAll();
862  }
863 }
864 
866 {
867 #if defined( Q_OS_WIN )
868  const Qt::CaseSensitivity cs = Qt::CaseInsensitive;
869 
870  aPath.replace( "\\", "/" );
871  if ( aPath.startsWith( "//" ) )
872  {
873  // keep UNC prefix
874  aPath = "\\\\" + aPath.mid( 2 );
875  }
876 
877  targetPath.replace( "\\", "/" );
878  if ( targetPath.startsWith( "//" ) )
879  {
880  // keep UNC prefix
881  targetPath = "\\\\" + targetPath.mid( 2 );
882  }
883 #else
884  const Qt::CaseSensitivity cs = Qt::CaseSensitive;
885 #endif
886 
887  QStringList targetElems = targetPath.split( "/", QString::SkipEmptyParts );
888  QStringList aPathElems = aPath.split( "/", QString::SkipEmptyParts );
889 
890  targetElems.removeAll( "." );
891  aPathElems.removeAll( "." );
892 
893  // remove common part
894  int n = 0;
895  while ( aPathElems.size() > 0 &&
896  targetElems.size() > 0 &&
897  aPathElems[0].compare( targetElems[0], cs ) == 0 )
898  {
899  aPathElems.removeFirst();
900  targetElems.removeFirst();
901  n++;
902  }
903 
904  if ( n == 0 )
905  {
906  // no common parts; might not even be a file
907  return aPath;
908  }
909 
910  if ( targetElems.size() > 0 )
911  {
912  // go up to the common directory
913  for ( int i = 0; i < targetElems.size(); i++ )
914  {
915  aPathElems.insert( 0, ".." );
916  }
917  }
918  else
919  {
920  // let it start with . nevertheless,
921  // so relative path always start with either ./ or ../
922  aPathElems.insert( 0, "." );
923  }
924 
925  return aPathElems.join( "/" );
926 }
927 
929 {
930  // relative path should always start with ./ or ../
931  if ( !rpath.startsWith( "./" ) && !rpath.startsWith( "../" ) )
932  {
933  return rpath;
934  }
935 
936 #if defined(Q_OS_WIN)
937  rpath.replace( "\\", "/" );
938  targetPath.replace( "\\", "/" );
939 
940  bool uncPath = targetPath.startsWith( "//" );
941 #endif
942 
943  QStringList srcElems = rpath.split( "/", QString::SkipEmptyParts );
944  QStringList targetElems = targetPath.split( "/", QString::SkipEmptyParts );
945 
946 #if defined(Q_OS_WIN)
947  if ( uncPath )
948  {
949  targetElems.insert( 0, "" );
950  targetElems.insert( 0, "" );
951  }
952 #endif
953 
954  // append source path elements
955  targetElems << srcElems;
956  targetElems.removeAll( "." );
957 
958  // resolve ..
959  int pos;
960  while (( pos = targetElems.indexOf( ".." ) ) > 0 )
961  {
962  // remove preceding element and ..
963  targetElems.removeAt( pos - 1 );
964  targetElems.removeAt( pos - 1 );
965  }
966 
967 #if !defined(Q_OS_WIN)
968  // make path absolute
969  targetElems.prepend( "" );
970 #endif
971 
972  return targetElems.join( "/" );
973 }
974 
976 {
977  if ( ABISYM( mGdalSkipList ).contains( theDriver ) || theDriver.isEmpty() )
978  {
979  return;
980  }
981  ABISYM( mGdalSkipList ) << theDriver;
983 }
984 
986 {
987  if ( !ABISYM( mGdalSkipList ).contains( theDriver ) )
988  {
989  return;
990  }
991  int myPos = ABISYM( mGdalSkipList ).indexOf( theDriver );
992  if ( myPos >= 0 )
993  {
994  ABISYM( mGdalSkipList ).removeAt( myPos );
995  }
997 }
998 
1000 {
1001  ABISYM( mGdalSkipList ).removeDuplicates();
1002  QString myDriverList = ABISYM( mGdalSkipList ).join( " " );
1003  QgsDebugMsg( "Gdal Skipped driver list set to:" );
1004  QgsDebugMsg( myDriverList );
1005  CPLSetConfigOption( "GDAL_SKIP", myDriverList.toUtf8() );
1006  GDALAllRegister(); //to update driver list and skip missing ones
1007 }
1008 
1010 {
1011  QString folder = userThemesFolder();
1012  QDir myDir( folder );
1013  if ( !myDir.exists() )
1014  {
1015  myDir.mkpath( folder );
1016  }
1017 
1018  copyPath( defaultThemesFolder(), userThemesFolder() );
1019  return true;
1020 }
1021 
1022 void QgsApplication::copyPath( QString src, QString dst )
1023 {
1024  QDir dir( src );
1025  if ( ! dir.exists() )
1026  return;
1027 
1028  foreach ( QString d, dir.entryList( QDir::Dirs | QDir::NoDotAndDotDot ) )
1029  {
1030  QString dst_path = dst + QDir::separator() + d;
1031  dir.mkpath( dst_path );
1032  copyPath( src + QDir::separator() + d, dst_path );
1033  }
1034 
1035  foreach ( QString f, dir.entryList( QDir::Files ) )
1036  {
1037  QFile::copy( src + QDir::separator() + f, dst + QDir::separator() + f );
1038  }
1039 }
1040 
1041 bool QgsApplication::createDB( QString *errorMessage )
1042 {
1043  // set a working directory up for gdal to write .aux.xml files into
1044  // for cases where the raster dir is read only to the user
1045  // if the env var is already set it will be used preferentially
1046  QString myPamPath = qgisSettingsDirPath() + QString( "gdal_pam/" );
1047  QDir myDir( myPamPath );
1048  if ( !myDir.exists() )
1049  {
1050  myDir.mkpath( myPamPath ); //fail silently
1051  }
1052 
1053 #if defined(Q_OS_WIN)
1054  CPLSetConfigOption( "GDAL_PAM_PROXY_DIR", myPamPath.toUtf8() );
1055 #else
1056  //under other OS's we use an environment var so the user can
1057  //override the path if he likes
1058  int myChangeFlag = 0; //whether we want to force the env var to change
1059  setenv( "GDAL_PAM_PROXY_DIR", myPamPath.toUtf8(), myChangeFlag );
1060 #endif
1061 
1062  // Check qgis.db and make private copy if necessary
1063  QFile qgisPrivateDbFile( QgsApplication::qgisUserDbFilePath() );
1064 
1065  // first we look for ~/.qgis/qgis.db
1066  if ( !qgisPrivateDbFile.exists() )
1067  {
1068  // if it doesnt exist we copy it in from the global resources dir
1069  QString qgisMasterDbFileName = QgsApplication::qgisMasterDbFilePath();
1070  QFile masterFile( qgisMasterDbFileName );
1071 
1072  // Must be sure there is destination directory ~/.qgis
1074 
1075  //now copy the master file into the users .qgis dir
1076  bool isDbFileCopied = masterFile.copy( qgisPrivateDbFile.fileName() );
1077 
1078  if ( !isDbFileCopied )
1079  {
1080  if ( errorMessage )
1081  {
1082  *errorMessage = tr( "[ERROR] Can not make qgis.db private copy" );
1083  }
1084  return false;
1085  }
1086  }
1087  else
1088  {
1089  // migrate if necessary
1090  sqlite3 *db;
1091  if ( sqlite3_open( QgsApplication::qgisUserDbFilePath().toUtf8().constData(), &db ) != SQLITE_OK )
1092  {
1093  if ( errorMessage )
1094  {
1095  *errorMessage = tr( "Could not open qgis.db" );
1096  }
1097  return false;
1098  }
1099 
1100  char *errmsg;
1101  int res = sqlite3_exec( db, "SELECT epsg FROM tbl_srs LIMIT 0", 0, 0, &errmsg );
1102  if ( res == SQLITE_OK )
1103  {
1104  // epsg column exists => need migration
1105  if ( sqlite3_exec( db,
1106  "ALTER TABLE tbl_srs RENAME TO tbl_srs_bak;"
1107  "CREATE TABLE tbl_srs ("
1108  "srs_id INTEGER PRIMARY KEY,"
1109  "description text NOT NULL,"
1110  "projection_acronym text NOT NULL,"
1111  "ellipsoid_acronym NOT NULL,"
1112  "parameters text NOT NULL,"
1113  "srid integer,"
1114  "auth_name varchar,"
1115  "auth_id varchar,"
1116  "is_geo integer NOT NULL,"
1117  "deprecated boolean);"
1118  "CREATE INDEX idx_srsauthid on tbl_srs(auth_name,auth_id);"
1119  "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;"
1120  "DROP TABLE tbl_srs_bak", 0, 0, &errmsg ) != SQLITE_OK
1121  )
1122  {
1123  if ( errorMessage )
1124  {
1125  *errorMessage = tr( "Migration of private qgis.db failed.\n%1" ).arg( QString::fromUtf8( errmsg ) );
1126  }
1127  sqlite3_free( errmsg );
1128  sqlite3_close( db );
1129  return false;
1130  }
1131  }
1132  else
1133  {
1134  sqlite3_free( errmsg );
1135  }
1136 
1137  if ( sqlite3_exec( db, "DROP VIEW vw_srs", 0, 0, &errmsg ) != SQLITE_OK )
1138  {
1139  QgsDebugMsg( QString( "vw_srs didn't exists in private qgis.db: %1" ).arg( errmsg ) );
1140  }
1141 
1142  if ( sqlite3_exec( db,
1143  "CREATE VIEW vw_srs AS"
1144  " SELECT"
1145  " a.description AS description"
1146  ",a.srs_id AS srs_id"
1147  ",a.is_geo AS is_geo"
1148  ",coalesce(b.name,a.projection_acronym) AS name"
1149  ",a.parameters AS parameters"
1150  ",a.auth_name AS auth_name"
1151  ",a.auth_id AS auth_id"
1152  ",a.deprecated AS deprecated"
1153  " FROM tbl_srs a"
1154  " LEFT OUTER JOIN tbl_projection b ON a.projection_acronym=b.acronym"
1155  " ORDER BY coalesce(b.name,a.projection_acronym),a.description", 0, 0, &errmsg ) != SQLITE_OK
1156  )
1157  {
1158  if ( errorMessage )
1159  {
1160  *errorMessage = tr( "Update of view in private qgis.db failed.\n%1" ).arg( QString::fromUtf8( errmsg ) );
1161  }
1162  sqlite3_free( errmsg );
1163  sqlite3_close( db );
1164  return false;
1165  }
1166 
1167  sqlite3_close( db );
1168  }
1169  return true;
1170 }
1171 
1172 void QgsApplication::setMaxThreads( int maxThreads )
1173 {
1174  QgsDebugMsg( QString( "maxThreads: %1" ).arg( maxThreads ) );
1175 
1176  // make sure value is between 1 and #cores, if not set to -1 (use #cores)
1177  // 0 could be used to disable any parallel processing
1178  if ( maxThreads < 1 || maxThreads > QThread::idealThreadCount() )
1179  maxThreads = -1;
1180 
1181  // save value
1182  ABISYM( mMaxThreads ) = maxThreads;
1183 
1184  // if -1 use #cores
1185  if ( maxThreads == -1 )
1186  maxThreads = QThread::idealThreadCount();
1187 
1188  // set max thread count in QThreadPool
1190  QgsDebugMsg( QString( "set QThreadPool max thread count to %1" ).arg( QThreadPool::globalInstance()->maxThreadCount() ) );
1191 }
1192 
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
enum QgsApplication::ENDIAN endian_t
Constants for endian-ness.
QString & append(QChar ch)
Type type() const
iterator insert(const Key &key, const T &value)
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.
QStringList ABISYM(QgsApplication::mFileOpenEventList)
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 donorsFilePath()
Returns the path to the donors 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 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()
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
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.
static void setThemeName(const QString &theThemeName)
Set the active theme to the specified theme.
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.
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 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 QString whatsNewFilePath()
Returns the path to the whats new html page.
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 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 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.
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
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.
QgsApplication(int &argc, char **argv, bool GUIenabled, QString customConfigPath=QString())
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: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)
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