QGIS API Documentation  2.4.0-Chugiak
 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 "qgslogger.h"
18 #include "qgsmaplayerregistry.h"
19 #include "qgsproviderregistry.h"
20 #include "qgsexception.h"
21 #include "qgsgeometry.h"
22 
23 #include <QDir>
24 #include <QFile>
25 #include <QFileOpenEvent>
26 #include <QMessageBox>
27 #include <QPalette>
28 #include <QProcess>
29 #include <QSettings>
30 #include <QIcon>
31 #include <QPixmap>
32 #include <QThreadPool>
33 
34 #ifndef Q_WS_WIN
35 #include <netinet/in.h>
36 #else
37 #include <winsock.h>
38 #endif
39 
40 #include "qgsconfig.h"
41 
42 #include <gdal.h>
43 #include <ogr_api.h>
44 #include <cpl_conv.h> // for setting gdal options
45 #include <sqlite3.h>
46 
47 QObject * ABISYM( QgsApplication::mFileOpenEventReceiver );
48 QStringList ABISYM( QgsApplication::mFileOpenEventList );
49 QString ABISYM( QgsApplication::mPrefixPath );
50 QString ABISYM( QgsApplication::mPluginPath );
51 QString ABISYM( QgsApplication::mPkgDataPath );
52 QString ABISYM( QgsApplication::mLibraryPath );
53 QString ABISYM( QgsApplication::mLibexecPath );
54 QString ABISYM( QgsApplication::mThemeName );
55 QStringList ABISYM( QgsApplication::mDefaultSvgPaths );
56 QMap<QString, QString> ABISYM( QgsApplication::mSystemEnvVars );
57 QString ABISYM( QgsApplication::mConfigPath );
58 bool ABISYM( QgsApplication::mRunningFromBuildDir ) = false;
59 QString ABISYM( QgsApplication::mBuildSourcePath );
60 #ifdef _MSC_VER
61 QString ABISYM( QgsApplication::mCfgIntDir );
62 #endif
63 QString ABISYM( QgsApplication::mBuildOutputPath );
64 QStringList ABISYM( QgsApplication::mGdalSkipList );
65 int ABISYM( QgsApplication::mMaxThreads );
66 
67 const char* QgsApplication::QGIS_ORGANIZATION_NAME = "QGIS";
68 const char* QgsApplication::QGIS_ORGANIZATION_DOMAIN = "qgis.org";
69 const char* QgsApplication::QGIS_APPLICATION_NAME = "QGIS2";
70 
84 QgsApplication::QgsApplication( int & argc, char ** argv, bool GUIenabled, QString customConfigPath )
85  : QApplication( argc, argv, GUIenabled )
86 {
87  init( customConfigPath ); // init can also be called directly by e.g. unit tests that don't inherit QApplication.
88 }
89 
90 void QgsApplication::init( QString customConfigPath )
91 {
92  if ( customConfigPath.isEmpty() )
93  {
94  customConfigPath = QString( "%1/.qgis%2/" ).arg( QDir::homePath() ).arg( QGis::QGIS_VERSION_INT / 10000 );
95  }
96 
97  qRegisterMetaType<QgsGeometry::Error>( "QgsGeometry::Error" );
98 
99  QString prefixPath( getenv( "QGIS_PREFIX_PATH" ) ? getenv( "QGIS_PREFIX_PATH" ) : applicationDirPath() );
100  // QgsDebugMsg( QString( "prefixPath(): %1" ).arg( prefixPath ) );
101 
102  // check if QGIS is run from build directory (not the install directory)
103  QFile f;
104  // "/../../.." is for Mac bundled app in build directory
105  foreach ( QString path, QStringList() << "" << "/.." << "/bin" << "/../../.." )
106  {
107  f.setFileName( prefixPath + path + "/qgisbuildpath.txt" );
108  if ( f.exists() )
109  break;
110  }
111  if ( f.exists() && f.open( QIODevice::ReadOnly ) )
112  {
113  ABISYM( mRunningFromBuildDir ) = true;
114  ABISYM( mBuildSourcePath ) = f.readLine().trimmed();
115  ABISYM( mBuildOutputPath ) = f.readLine().trimmed();
116  qDebug( "Running from build directory!" );
117  qDebug( "- source directory: %s", ABISYM( mBuildSourcePath ).toUtf8().data() );
118  qDebug( "- output directory of the build: %s", ABISYM( mBuildOutputPath ).toUtf8().data() );
119 #ifdef _MSC_VER
120  ABISYM( mCfgIntDir ) = prefixPath.split( "/", QString::SkipEmptyParts ).last();
121  qDebug( "- cfg: %s", ABISYM( mCfgIntDir ).toUtf8().data() );
122 #endif
123  }
124 
125  if ( ABISYM( mRunningFromBuildDir ) )
126  {
127  // we run from source directory - not installed to destination (specified prefix)
128  ABISYM( mPrefixPath ) = QString(); // set invalid path
129 #if defined(_MSC_VER) && !defined(USING_NMAKE)
130  setPluginPath( ABISYM( mBuildOutputPath ) + "/" + QString( QGIS_PLUGIN_SUBDIR ) + "/" + ABISYM( mCfgIntDir ) );
131 #else
132  setPluginPath( ABISYM( mBuildOutputPath ) + "/" + QString( QGIS_PLUGIN_SUBDIR ) );
133 #endif
134  setPkgDataPath( ABISYM( mBuildSourcePath ) ); // directly source path - used for: doc, resources, svg
135  ABISYM( mLibraryPath ) = ABISYM( mBuildOutputPath ) + "/" + QGIS_LIB_SUBDIR + "/";
136 #if defined(_MSC_VER) && !defined(USING_NMAKE)
137  ABISYM( mLibexecPath ) = ABISYM( mBuildOutputPath ) + "/" + QGIS_LIBEXEC_SUBDIR + "/" + ABISYM( mCfgIntDir ) + "/";
138 #else
139  ABISYM( mLibexecPath ) = ABISYM( mBuildOutputPath ) + "/" + QGIS_LIBEXEC_SUBDIR + "/";
140 #endif
141  }
142  else
143  {
144  char *prefixPath = getenv( "QGIS_PREFIX_PATH" );
145  if ( !prefixPath )
146  {
147 #if defined(Q_WS_MACX) || defined(Q_WS_WIN32) || defined(WIN32)
148  setPrefixPath( applicationDirPath(), true );
149 #elif defined(ANDROID)
150  // this is "/data/data/org.qgis.qgis" in android
151  QDir myDir( QDir::homePath() );
152  myDir.cdUp();
153  QString myPrefix = myDir.absolutePath();
154  setPrefixPath( myPrefix, true );
155 #else
156  QDir myDir( applicationDirPath() );
157  myDir.cdUp();
158  QString myPrefix = myDir.absolutePath();
159  setPrefixPath( myPrefix, true );
160 #endif
161  }
162  else
163  {
164  setPrefixPath( prefixPath, true );
165  }
166  }
167 
168  if ( !customConfigPath.isEmpty() )
169  {
170  ABISYM( mConfigPath ) = customConfigPath + "/"; // make sure trailing slash is included
171  }
172 
173  ABISYM( mDefaultSvgPaths ) << qgisSettingsDirPath() + QString( "svg/" );
174 
175  // store system environment variables passed to application, before they are adjusted
176  QMap<QString, QString> systemEnvVarMap;
177  foreach ( const QString &varStr, QProcess::systemEnvironment() )
178  {
179  int pos = varStr.indexOf( QLatin1Char( '=' ) );
180  if ( pos == -1 )
181  continue;
182  QString varStrName = varStr.left( pos );
183  QString varStrValue = varStr.mid( pos + 1 );
184  systemEnvVarMap.insert( varStrName, varStrValue );
185  }
186  ABISYM( mSystemEnvVars ) = systemEnvVarMap;
187 
188  // allow Qt to search for Qt plugins (e.g. sqldrivers) in our plugin directory
189  QCoreApplication::addLibraryPath( pluginPath() );
190 
191  // set max. thread count to -1
192  // this should be read from QSettings but we don't know where they are at this point
193  // so we read actual value in main.cpp
194  ABISYM( mMaxThreads ) = -1;
195 }
196 
198 {
199 }
200 
201 bool QgsApplication::event( QEvent * event )
202 {
203  bool done = false;
204  if ( event->type() == QEvent::FileOpen )
205  {
206  // handle FileOpen event (double clicking a file icon in Mac OS X Finder)
207  if ( ABISYM( mFileOpenEventReceiver ) )
208  {
209  // Forward event to main window.
210  done = notify( ABISYM( mFileOpenEventReceiver ), event );
211  }
212  else
213  {
214  // Store filename because receiver has not registered yet.
215  // If QGIS has been launched by double clicking a file icon, FileOpen will be
216  // the first event; the main window is not yet ready to handle the event.
217  ABISYM( mFileOpenEventList ).append( static_cast<QFileOpenEvent *>( event )->file() );
218  done = true;
219  }
220  }
221  else
222  {
223  // pass other events to base class
224  done = QApplication::event( event );
225  }
226  return done;
227 }
228 
229 bool QgsApplication::notify( QObject * receiver, QEvent * event )
230 {
231  bool done = false;
232  // Crashes in customization (especially on Mac), if we're not in the main/UI thread, see #5597
233  if ( thread() == receiver->thread() )
234  emit preNotify( receiver, event, &done );
235 
236  if ( done )
237  return true;
238 
239  // Send event to receiver and catch unhandled exceptions
240  done = true;
241  try
242  {
243  done = QApplication::notify( receiver, event );
244  }
245  catch ( QgsException & e )
246  {
247  QgsDebugMsg( "Caught unhandled QgsException: " + e.what() );
248  if ( qApp->thread() == QThread::currentThread() )
249  QMessageBox::critical( activeWindow(), tr( "Exception" ), e.what() );
250  }
251  catch ( std::exception & e )
252  {
253  QgsDebugMsg( "Caught unhandled std::exception: " + QString::fromAscii( e.what() ) );
254  if ( qApp->thread() == QThread::currentThread() )
255  QMessageBox::critical( activeWindow(), tr( "Exception" ), e.what() );
256  }
257  catch ( ... )
258  {
259  QgsDebugMsg( "Caught unhandled unknown exception" );
260  if ( qApp->thread() == QThread::currentThread() )
261  QMessageBox::critical( activeWindow(), tr( "Exception" ), tr( "unknown exception" ) );
262  }
263 
264  return done;
265 }
266 
268 {
269  // Set receiver for FileOpen events
270  ABISYM( mFileOpenEventReceiver ) = receiver;
271  // Propagate any events collected before the receiver has registered.
272  if ( ABISYM( mFileOpenEventList ).count() > 0 )
273  {
274  QStringListIterator i( ABISYM( mFileOpenEventList ) );
275  while ( i.hasNext() )
276  {
277  QFileOpenEvent foe( i.next() );
278  QgsApplication::sendEvent( ABISYM( mFileOpenEventReceiver ), &foe );
279  }
280  ABISYM( mFileOpenEventList ).clear();
281  }
282 }
283 
284 void QgsApplication::setPrefixPath( const QString &thePrefixPath, bool useDefaultPaths )
285 {
286  ABISYM( mPrefixPath ) = thePrefixPath;
287 #if defined(_MSC_VER)
288  if ( ABISYM( mPrefixPath ).endsWith( "/bin" ) )
289  {
290  ABISYM( mPrefixPath ).chop( 4 );
291  }
292 #endif
293  if ( useDefaultPaths && !ABISYM( mRunningFromBuildDir ) )
294  {
295  setPluginPath( ABISYM( mPrefixPath ) + "/" + QString( QGIS_PLUGIN_SUBDIR ) );
296  setPkgDataPath( ABISYM( mPrefixPath ) + "/" + QString( QGIS_DATA_SUBDIR ) );
297  }
298  ABISYM( mLibraryPath ) = ABISYM( mPrefixPath ) + "/" + QGIS_LIB_SUBDIR + "/";
299  ABISYM( mLibexecPath ) = ABISYM( mPrefixPath ) + "/" + QGIS_LIBEXEC_SUBDIR + "/";
300 }
301 
302 void QgsApplication::setPluginPath( const QString &thePluginPath )
303 {
304  ABISYM( mPluginPath ) = thePluginPath;
305 }
306 
307 void QgsApplication::setPkgDataPath( const QString &thePkgDataPath )
308 {
309  ABISYM( mPkgDataPath ) = thePkgDataPath;
310  QString mySvgPath = thePkgDataPath + ( ABISYM( mRunningFromBuildDir ) ? "/images/svg/" : "/svg/" );
311  // avoid duplicate entries
312  if ( !ABISYM( mDefaultSvgPaths ).contains( mySvgPath ) )
313  ABISYM( mDefaultSvgPaths ) << mySvgPath;
314 }
315 
316 void QgsApplication::setDefaultSvgPaths( const QStringList& pathList )
317 {
318  ABISYM( mDefaultSvgPaths ) = pathList;
319 }
320 
322 {
323  if ( ABISYM( mRunningFromBuildDir ) )
324  {
325  qWarning( "!!! prefix path was requested, but it is not valid - we do not run from installed path !!!" );
326  }
327 
328  return ABISYM( mPrefixPath );
329 }
331 {
332  return ABISYM( mPluginPath );
333 }
335 {
336  return ABISYM( mPkgDataPath );
337 }
339 {
340  return ":/images/themes/default/";
341 }
343 {
344  return ":/images/themes/" + themeName() + "/";
345 }
346 
347 
348 QString QgsApplication::iconPath( QString iconFile )
349 {
350  // try active theme
351  QString path = activeThemePath();
352  if ( QFile::exists( path + iconFile ) )
353  return path + iconFile;
354 
355  // use default theme
356  return defaultThemePath() + iconFile;
357 }
358 
359 QIcon QgsApplication::getThemeIcon( const QString &theName )
360 {
361  QString myPreferredPath = activeThemePath() + QDir::separator() + theName;
362  QString myDefaultPath = defaultThemePath() + QDir::separator() + theName;
363  if ( QFile::exists( myPreferredPath ) )
364  {
365  return QIcon( myPreferredPath );
366  }
367  else if ( QFile::exists( myDefaultPath ) )
368  {
369  //could still return an empty icon if it
370  //doesnt exist in the default theme either!
371  return QIcon( myDefaultPath );
372  }
373  else
374  {
375  return QIcon();
376  }
377 }
378 
379 // TODO: add some caching mechanism ?
380 QPixmap QgsApplication::getThemePixmap( const QString &theName )
381 {
382  QString myPreferredPath = activeThemePath() + QDir::separator() + theName;
383  QString myDefaultPath = defaultThemePath() + QDir::separator() + theName;
384  if ( QFile::exists( myPreferredPath ) )
385  {
386  return QPixmap( myPreferredPath );
387  }
388  else
389  {
390  //could still return an empty icon if it
391  //doesnt exist in the default theme either!
392  return QPixmap( myDefaultPath );
393  }
394 }
395 
399 void QgsApplication::setThemeName( const QString &theThemeName )
400 {
401  QString myPath = ":/images/themes/" + theThemeName + "/";
402  //check it exists and if not roll back to default theme
403  if ( QFile::exists( myPath ) )
404  {
405  ABISYM( mThemeName ) = theThemeName;
406  }
407  else
408  {
409  ABISYM( mThemeName ) = "default";
410  }
411 }
416 {
417  return ABISYM( mThemeName );
418 }
423 {
424  return ABISYM( mPkgDataPath ) + QString( "/doc/AUTHORS" );
425 }
430 {
431  return ABISYM( mPkgDataPath ) + QString( "/doc/CONTRIBUTORS" );
432 }
437 {
438  return ABISYM( mPkgDataPath ) + QString( "/doc/SPONSORS" );
439 }
440 
445 {
446  return ABISYM( mPkgDataPath ) + QString( "/doc/DONORS" );
447 }
448 
454 {
455  return ABISYM( mPkgDataPath ) + QString( "/doc/TRANSLATORS" );
456 }
457 
462 {
463  return ABISYM( mPkgDataPath ) + QString( "/doc/LICENSE" );
464 }
465 
470 {
471  QString helpAppPath;
472 #ifdef Q_OS_MACX
473  helpAppPath = applicationDirPath() + "/bin/qgis_help.app/Contents/MacOS";
474 #else
475  helpAppPath = libexecPath();
476 #endif
477  helpAppPath += "/qgis_help";
478 #ifdef Q_OS_WIN
479  helpAppPath += ".exe";
480 #endif
481  return helpAppPath;
482 }
487 {
488  if ( ABISYM( mRunningFromBuildDir ) )
489  return ABISYM( mBuildOutputPath ) + QString( "/i18n" );
490  else
491  return ABISYM( mPkgDataPath ) + QString( "/i18n/" );
492 }
493 
498 {
499  return ABISYM( mPkgDataPath ) + QString( "/resources/qgis.db" );
500 }
501 
506 {
507  return ABISYM( mConfigPath );
508 }
509 
514 {
515  return qgisSettingsDirPath() + QString( "qgis.db" );
516 }
517 
522 {
523  return QString( ":/images/splash/" );
524 }
525 
530 {
531  return ABISYM( mPkgDataPath ) + QString( "/images/icons/" );
532 }
537 {
538  if ( ABISYM( mRunningFromBuildDir ) )
539  {
540  QString tempCopy = QDir::tempPath() + "/srs.db";
541 
542  if ( !QFile( tempCopy ).exists() )
543  {
544  QFile f( ABISYM( mPkgDataPath ) + "/resources/srs.db" );
545  if ( !f.copy( tempCopy ) )
546  {
547  qFatal( "Could not create temporary copy" );
548  }
549  }
550 
551  return tempCopy;
552  }
553  else
554  {
555  return ABISYM( mPkgDataPath ) + QString( "/resources/srs.db" );
556  }
557 }
558 
562 const QStringList QgsApplication::svgPaths()
563 {
564  //local directories to search when looking for an SVG with a given basename
565  //defined by user in options dialog
566  QSettings settings;
567  QStringList myPathList;
568  QString myPaths = settings.value( "svg/searchPathsForSVG", "" ).toString();
569  if ( !myPaths.isEmpty() )
570  {
571  myPathList = myPaths.split( "|" );
572  }
573 
574  myPathList << ABISYM( mDefaultSvgPaths );
575  return myPathList;
576 }
577 
579 {
580  return qgisSettingsDirPath() + QString( "symbology-ng-style.db" );
581 }
582 
584 {
585  return ABISYM( mPkgDataPath ) + QString( "/resources/symbology-ng-style.db" );
586 }
587 
589 {
590  return ABISYM( mLibraryPath );
591 }
592 
594 {
595  return ABISYM( mLibexecPath );
596 }
597 
599 {
600  return ( htonl( 1 ) == 1 ) ? XDR : NDR ;
601 }
602 
604 {
605  // set the provider plugin path (this creates provider registry)
607 
608  // create map layer registry if doesn't exist
610 }
611 
613 {
615 
617 }
618 
620 {
621  QString myEnvironmentVar( getenv( "QGIS_PREFIX_PATH" ) );
622  QString myState = tr( "Application state:\n"
623  "QGIS_PREFIX_PATH env var:\t\t%1\n"
624  "Prefix:\t\t%2\n"
625  "Plugin Path:\t\t%3\n"
626  "Package Data Path:\t%4\n"
627  "Active Theme Name:\t%5\n"
628  "Active Theme Path:\t%6\n"
629  "Default Theme Path:\t%7\n"
630  "SVG Search Paths:\t%8\n"
631  "User DB Path:\t%9\n" )
632  .arg( myEnvironmentVar )
633  .arg( prefixPath() )
634  .arg( pluginPath() )
635  .arg( pkgDataPath() )
636  .arg( themeName() )
637  .arg( activeThemePath() )
638  .arg( defaultThemePath() )
639  .arg( svgPaths().join( tr( "\n\t\t", "match indentation of application state" ) ) )
640  .arg( qgisMasterDbFilePath() );
641  return myState;
642 }
643 
645 {
646  //
647  // Make the style sheet desktop preferences aware by using qappliation
648  // palette as a basis for colors where appropriate
649  //
650 // QColor myColor1 = palette().highlight().color();
651  QColor myColor1( Qt::lightGray );
652  QColor myColor2 = myColor1;
653  myColor2 = myColor2.lighter( 110 ); //10% lighter
654  QString myStyle;
655  myStyle = "p.glossy{ background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, "
656  " stop: 0 " + myColor1.name() + ","
657  " stop: 0.1 " + myColor2.name() + ","
658  " stop: 0.5 " + myColor1.name() + ","
659  " stop: 0.9 " + myColor2.name() + ","
660  " stop: 1 " + myColor1.name() + ");"
661  " color: black;"
662  " padding-left: 4px;"
663  " padding-top: 20px;"
664  " padding-bottom: 8px;"
665  " border: 1px solid #6c6c6c;"
666  "}"
667  "p.subheaderglossy{ background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, "
668  " stop: 0 " + myColor1.name() + ","
669  " stop: 0.1 " + myColor2.name() + ","
670  " stop: 0.5 " + myColor1.name() + ","
671  " stop: 0.9 " + myColor2.name() + ","
672  " stop: 1 " + myColor1.name() + ");"
673  " font-weight: bold;"
674  " font-size: medium;"
675  " line-height: 1.1em;"
676  " width: 100%;"
677  " color: black;"
678  " padding-left: 4px;"
679  " padding-right: 4px;"
680  " padding-top: 20px;"
681  " padding-bottom: 8px;"
682  " border: 1px solid #6c6c6c;"
683  "}"
684  "th.glossy{ background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, "
685  " stop: 0 " + myColor1.name() + ","
686  " stop: 0.1 " + myColor2.name() + ","
687  " stop: 0.5 " + myColor1.name() + ","
688  " stop: 0.9 " + myColor2.name() + ","
689  " stop: 1 " + myColor1.name() + ");"
690  " color: black;"
691  " border: 1px solid #6c6c6c;"
692  "}"
693  ".overview{ font: 1.82em; font-weight: bold;}"
694  "body{ background: white;"
695  " color: black;"
696  " font-family: arial,sans-serif;"
697  "}"
698  "h1{ background-color: #F6F6F6;"
699  " color: #8FB171; "
700  " font-size: x-large; "
701  " font-weight: normal;"
702  " font-family: luxi serif, georgia, times new roman, times, serif;"
703  " background: none;"
704  " padding: 0.75em 0 0;"
705  " margin: 0;"
706  " line-height: 3em;"
707  "}"
708  "h2{ background-color: #F6F6F6;"
709  " color: #8FB171; "
710  " font-size: medium; "
711  " font-weight: normal;"
712  " font-family: luxi serif, georgia, times new roman, times, serif;"
713  " background: none;"
714  " padding: 0.75em 0 0;"
715  " margin: 0;"
716  " line-height: 1.1em;"
717  "}"
718  "h3{ background-color: #F6F6F6;"
719  " color: #729FCF;"
720  " font-family: luxi serif, georgia, times new roman, times, serif;"
721  " font-weight: bold;"
722  " font-size: large;"
723  " text-align: right;"
724  " border-bottom: 5px solid #DCEB5C;"
725  "}"
726  "h4{ background-color: #F6F6F6;"
727  " color: #729FCF;"
728  " font-family: luxi serif, georgia, times new roman, times, serif;"
729  " font-weight: bold;"
730  " font-size: medium;"
731  " text-align: right;"
732  "}"
733  "h5{ background-color: #F6F6F6;"
734  " color: #729FCF;"
735  " font-family: luxi serif, georgia, times new roman, times, serif;"
736  " font-weight: bold;"
737  " font-size: small;"
738  " text-align: right;"
739  "}"
740  "a{ color: #729FCF;"
741  " font-family: arial,sans-serif;"
742  " font-size: small;"
743  "}"
744  "label{ background-color: #FFFFCC;"
745  " border: 1px solid black;"
746  " margin: 1px;"
747  " padding: 0px 3px; "
748  " font-size: small;"
749  "}";
750  return myStyle;
751 }
752 
754 {
755  if ( 0 >= OGRGetDriverCount() )
756  {
757  OGRRegisterAll();
758  }
759 }
760 
761 QString QgsApplication::absolutePathToRelativePath( QString aPath, QString targetPath )
762 {
763 #if defined( Q_OS_WIN )
764  const Qt::CaseSensitivity cs = Qt::CaseInsensitive;
765 
766  aPath.replace( "\\", "/" );
767  if ( aPath.startsWith( "//" ) )
768  {
769  // keep UNC prefix
770  aPath = "\\\\" + aPath.mid( 2 );
771  }
772 
773  targetPath.replace( "\\", "/" );
774  if ( targetPath.startsWith( "//" ) )
775  {
776  // keep UNC prefix
777  targetPath = "\\\\" + targetPath.mid( 2 );
778  }
779 #else
780  const Qt::CaseSensitivity cs = Qt::CaseSensitive;
781 #endif
782 
783  QStringList targetElems = targetPath.split( "/", QString::SkipEmptyParts );
784  QStringList aPathElems = aPath.split( "/", QString::SkipEmptyParts );
785 
786  targetElems.removeAll( "." );
787  aPathElems.removeAll( "." );
788 
789  // remove common part
790  int n = 0;
791  while ( aPathElems.size() > 0 &&
792  targetElems.size() > 0 &&
793  aPathElems[0].compare( targetElems[0], cs ) == 0 )
794  {
795  aPathElems.removeFirst();
796  targetElems.removeFirst();
797  n++;
798  }
799 
800  if ( n == 0 )
801  {
802  // no common parts; might not even be a file
803  return aPath;
804  }
805 
806  if ( targetElems.size() > 0 )
807  {
808  // go up to the common directory
809  for ( int i = 0; i < targetElems.size(); i++ )
810  {
811  aPathElems.insert( 0, ".." );
812  }
813  }
814  else
815  {
816  // let it start with . nevertheless,
817  // so relative path always start with either ./ or ../
818  aPathElems.insert( 0, "." );
819  }
820 
821  return aPathElems.join( "/" );
822 }
823 
824 QString QgsApplication::relativePathToAbsolutePath( QString rpath, QString targetPath )
825 {
826  // relative path should always start with ./ or ../
827  if ( !rpath.startsWith( "./" ) && !rpath.startsWith( "../" ) )
828  {
829  return rpath;
830  }
831 
832 #if defined(Q_OS_WIN)
833  rpath.replace( "\\", "/" );
834  targetPath.replace( "\\", "/" );
835 
836  bool uncPath = targetPath.startsWith( "//" );
837 #endif
838 
839  QStringList srcElems = rpath.split( "/", QString::SkipEmptyParts );
840  QStringList targetElems = targetPath.split( "/", QString::SkipEmptyParts );
841 
842 #if defined(Q_OS_WIN)
843  if ( uncPath )
844  {
845  targetElems.insert( 0, "" );
846  targetElems.insert( 0, "" );
847  }
848 #endif
849 
850  // append source path elements
851  targetElems << srcElems;
852  targetElems.removeAll( "." );
853 
854  // resolve ..
855  int pos;
856  while (( pos = targetElems.indexOf( ".." ) ) > 0 )
857  {
858  // remove preceding element and ..
859  targetElems.removeAt( pos - 1 );
860  targetElems.removeAt( pos - 1 );
861  }
862 
863 #if !defined(Q_OS_WIN)
864  // make path absolute
865  targetElems.prepend( "" );
866 #endif
867 
868  return targetElems.join( "/" );
869 }
870 
871 void QgsApplication::skipGdalDriver( QString theDriver )
872 {
873  if ( ABISYM( mGdalSkipList ).contains( theDriver ) || theDriver.isEmpty() )
874  {
875  return;
876  }
877  ABISYM( mGdalSkipList ) << theDriver;
879 }
880 
881 void QgsApplication::restoreGdalDriver( QString theDriver )
882 {
883  if ( !ABISYM( mGdalSkipList ).contains( theDriver ) )
884  {
885  return;
886  }
887  int myPos = ABISYM( mGdalSkipList ).indexOf( theDriver );
888  if ( myPos >= 0 )
889  {
890  ABISYM( mGdalSkipList ).removeAt( myPos );
891  }
893 }
894 
896 {
897  ABISYM( mGdalSkipList ).removeDuplicates();
898  QString myDriverList = ABISYM( mGdalSkipList ).join( " " );
899  QgsDebugMsg( "Gdal Skipped driver list set to:" );
900  QgsDebugMsg( myDriverList );
901  CPLSetConfigOption( "GDAL_SKIP", myDriverList.toUtf8() );
902  GDALAllRegister(); //to update driver list and skip missing ones
903 }
904 
905 bool QgsApplication::createDB( QString *errorMessage )
906 {
907  // set a working directory up for gdal to write .aux.xml files into
908  // for cases where the raster dir is read only to the user
909  // if the env var is already set it will be used preferentially
910  QString myPamPath = qgisSettingsDirPath() + QString( "gdal_pam/" );
911  QDir myDir( myPamPath );
912  if ( !myDir.exists() )
913  {
914  myDir.mkpath( myPamPath ); //fail silently
915  }
916 
917 #if defined(Q_WS_WIN32) || defined(WIN32)
918  CPLSetConfigOption( "GDAL_PAM_PROXY_DIR", myPamPath.toUtf8() );
919 #else
920  //under other OS's we use an environment var so the user can
921  //override the path if he likes
922  int myChangeFlag = 0; //whether we want to force the env var to change
923  setenv( "GDAL_PAM_PROXY_DIR", myPamPath.toUtf8(), myChangeFlag );
924 #endif
925 
926  // Check qgis.db and make private copy if necessary
927  QFile qgisPrivateDbFile( QgsApplication::qgisUserDbFilePath() );
928 
929  // first we look for ~/.qgis/qgis.db
930  if ( !qgisPrivateDbFile.exists() )
931  {
932  // if it doesnt exist we copy it in from the global resources dir
933  QString qgisMasterDbFileName = QgsApplication::qgisMasterDbFilePath();
934  QFile masterFile( qgisMasterDbFileName );
935 
936  // Must be sure there is destination directory ~/.qgis
937  QDir().mkpath( QgsApplication::qgisSettingsDirPath() );
938 
939  //now copy the master file into the users .qgis dir
940  bool isDbFileCopied = masterFile.copy( qgisPrivateDbFile.fileName() );
941 
942  if ( !isDbFileCopied )
943  {
944  if ( errorMessage )
945  {
946  *errorMessage = tr( "[ERROR] Can not make qgis.db private copy" );
947  }
948  return false;
949  }
950  }
951  else
952  {
953  // migrate if necessary
954  sqlite3 *db;
955  if ( sqlite3_open( QgsApplication::qgisUserDbFilePath().toUtf8().constData(), &db ) != SQLITE_OK )
956  {
957  if ( errorMessage )
958  {
959  *errorMessage = tr( "Could not open qgis.db" );
960  }
961  return false;
962  }
963 
964  char *errmsg;
965  int res = sqlite3_exec( db, "SELECT epsg FROM tbl_srs LIMIT 0", 0, 0, &errmsg );
966  if ( res == SQLITE_OK )
967  {
968  // epsg column exists => need migration
969  if ( sqlite3_exec( db,
970  "ALTER TABLE tbl_srs RENAME TO tbl_srs_bak;"
971  "CREATE TABLE tbl_srs ("
972  "srs_id INTEGER PRIMARY KEY,"
973  "description text NOT NULL,"
974  "projection_acronym text NOT NULL,"
975  "ellipsoid_acronym NOT NULL,"
976  "parameters text NOT NULL,"
977  "srid integer,"
978  "auth_name varchar,"
979  "auth_id varchar,"
980  "is_geo integer NOT NULL,"
981  "deprecated boolean);"
982  "CREATE INDEX idx_srsauthid on tbl_srs(auth_name,auth_id);"
983  "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;"
984  "DROP TABLE tbl_srs_bak", 0, 0, &errmsg ) != SQLITE_OK
985  )
986  {
987  if ( errorMessage )
988  {
989  *errorMessage = tr( "Migration of private qgis.db failed.\n%1" ).arg( QString::fromUtf8( errmsg ) );
990  }
991  sqlite3_free( errmsg );
992  sqlite3_close( db );
993  return false;
994  }
995  }
996  else
997  {
998  sqlite3_free( errmsg );
999  }
1000 
1001  if ( sqlite3_exec( db, "DROP VIEW vw_srs", 0, 0, &errmsg ) != SQLITE_OK )
1002  {
1003  QgsDebugMsg( QString( "vw_srs didn't exists in private qgis.db: %1" ).arg( errmsg ) );
1004  }
1005 
1006  if ( sqlite3_exec( db,
1007  "CREATE VIEW vw_srs AS"
1008  " SELECT"
1009  " a.description AS description"
1010  ",a.srs_id AS srs_id"
1011  ",a.is_geo AS is_geo"
1012  ",coalesce(b.name,a.projection_acronym) AS name"
1013  ",a.parameters AS parameters"
1014  ",a.auth_name AS auth_name"
1015  ",a.auth_id AS auth_id"
1016  ",a.deprecated AS deprecated"
1017  " FROM tbl_srs a"
1018  " LEFT OUTER JOIN tbl_projection b ON a.projection_acronym=b.acronym"
1019  " ORDER BY coalesce(b.name,a.projection_acronym),a.description", 0, 0, &errmsg ) != SQLITE_OK
1020  )
1021  {
1022  if ( errorMessage )
1023  {
1024  *errorMessage = tr( "Update of view in private qgis.db failed.\n%1" ).arg( QString::fromUtf8( errmsg ) );
1025  }
1026  sqlite3_free( errmsg );
1027  sqlite3_close( db );
1028  return false;
1029  }
1030 
1031  sqlite3_close( db );
1032  }
1033  return true;
1034 }
1035 
1036 void QgsApplication::setMaxThreads( int maxThreads )
1037 {
1038  QgsDebugMsg( QString( "maxThreads: %1" ).arg( maxThreads ) );
1039 
1040  // make sure value is between 1 and #cores, if not set to -1 (use #cores)
1041  // 0 could be used to disable any parallel processing
1042  if ( maxThreads < 1 || maxThreads > QThread::idealThreadCount() )
1043  maxThreads = -1;
1044 
1045  // save value
1046  ABISYM( mMaxThreads ) = maxThreads;
1047 
1048  // if -1 use #cores
1049  if ( maxThreads == -1 )
1050  maxThreads = QThread::idealThreadCount();
1051 
1052  // set max thread count in QThreadPool
1053  QThreadPool::globalInstance()->setMaxThreadCount( maxThreads );
1054  QgsDebugMsg( QString( "set QThreadPool max thread count to %1" ).arg( QThreadPool::globalInstance()->maxThreadCount() ) );
1055 }
1056 
static const QString pkgDataPath()
Returns the common root path of all application data directories.
static void init(QString customConfigPath=QString())
This method initialises paths etc for QGIS.
static const QString i18nPath()
Returns the path to the translation directory.
static const QString contributorsFilePath()
Returns the path to the contributors file.
enum QgsApplication::ENDIAN endian_t
constants for endian-ness
static const QString qgisMasterDbFilePath()
Returns the path to the master qgis.db file.
static const QString libexecPath()
Returns the path with utility executables (help viewer, crssync, ...)
static const QString activeThemePath()
Returns the path to the currently active theme directory.
static QObject * ABISYM(mFileOpenEventReceiver)
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.
static const QString licenceFilePath()
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:36
static QString iconPath(QString iconFile)
Returns path to the desired icon file.
static const QString libraryPath()
Returns the path containing qgis_core, qgis_gui, qgispython (and other) libraries.
static QIcon getThemeIcon(const QString &theName)
Helper to get a theme icon.
static void registerOgrDrivers()
Register OGR drivers ensuring this only happens once.
static const QString translatorsFilePath()
Returns the path to the sponsors file.
static const QString authorsFilePath()
Returns the path to the authors file.
static QString absolutePathToRelativePath(QString apath, QString targetPath)
Converts absolute path to path relative to target.
static void setFileOpenEventReceiver(QObject *receiver)
Set the FileOpen event receiver.
static QString reportStyleSheet()
get a standard css style sheet for reports.
static int maxThreads()
Get maximum concurrent thread count.
static endian_t endian()
Returns whether this machine uses big or little endian.
static const QString qgisSettingsDirPath()
Returns the path to the settings directory in user's home dir.
static QPixmap getThemePixmap(const QString &theName)
Helper to get a theme icon as a pixmap.
virtual bool notify(QObject *receiver, QEvent *event)
Catch exceptions when sending event to receiver.
static void applyGdalSkippedDrivers()
Apply the skipped drivers list to gdal.
static void setThemeName(const QString &theThemeName)
Set the active theme to the specified theme.
static const QString iconsPath()
Returns the path to the icons image directory.
virtual ~QgsApplication()
static const QString splashPath()
Returns the path to the splash screen image directory.
static const QString defaultThemePath()
Returns the path to the default theme directory.
static void setPkgDataPath(const QString &thePkgDataPath)
Alters pkg data path - used by 3rd party apps.
static void restoreGdalDriver(QString theDriver)
Sets the GDAL_SKIP environment variable to exclude the specified driver and then calls GDALDriverMana...
static const char * QGIS_ORGANIZATION_NAME
static bool createDB(QString *errorMessage=0)
initialise qgis.db
static void setPluginPath(const QString &thePluginPath)
Alters plugin path - used by 3rd party apps.
static const QString defaultStyleV2Path()
Returns the path to default style (works as a starting point). Added in QGIS 1.4. ...
struct sqlite3 sqlite3
static void initQgis()
loads providers
static void setDefaultSvgPaths(const QStringList &pathList)
Alters default svg paths - used by 3rd party apps. Added in QGIS 1.5.
static QString relativePathToAbsolutePath(QString rpath, QString targetPath)
Converts path relative to target to an absolute path.
static void skipGdalDriver(QString theDriver)
Sets the GDAL_SKIP environment variable to include the specified driver and then calls GDALDriverMana...
QString file
Definition: qgssvgcache.cpp:76
static QString showSettings()
Convenience function to get a summary of the paths used in this application instance useful for debug...
QString what() const
Definition: qgsexception.h:35
static const char * QGIS_ORGANIZATION_DOMAIN
static QgsMapLayerRegistry * instance()
Returns the instance pointer, creating the object on the first call.
static const QString donorsFilePath()
Returns the path to the donors file.
static const QString srsDbFilePath()
Returns the path to the srs.db file.
QObject * ABISYM(QgsApplication::mFileOpenEventReceiver)
static void exitQgis()
deletes provider registry and map layer registry
static const QString sponsorsFilePath()
Returns the path to the sponsors file.
QgsApplication(int &argc, char **argv, bool GUIenabled, QString customConfigPath=QString())
static const char * QGIS_APPLICATION_NAME
virtual bool event(QEvent *event)
Watch for QFileOpenEvent.
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. Added in QGIS 1.4.
static const QString themeName()
Set the active theme to the specified theme.
static const int QGIS_VERSION_INT
Definition: qgis.h:42
Defines a qgis exception class.
Definition: qgsexception.h:25
static void setMaxThreads(int maxThreads)
Set maximum concurrent thread count.
void preNotify(QObject *receiver, QEvent *event, bool *done)
#define tr(sourceText)