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