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