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