27 #include <QFileOpenEvent>
28 #include <QMessageBox>
34 #include <QThreadPool>
37 #include <netinet/in.h>
42 #include "qgsconfig.h"
49 QObject *
ABISYM( QgsApplication::mFileOpenEventReceiver );
50 QStringList
ABISYM( QgsApplication::mFileOpenEventList );
51 QString
ABISYM( QgsApplication::mPrefixPath );
52 QString
ABISYM( QgsApplication::mPluginPath );
53 QString
ABISYM( QgsApplication::mPkgDataPath );
54 QString
ABISYM( QgsApplication::mLibraryPath );
55 QString
ABISYM( QgsApplication::mLibexecPath );
56 QString
ABISYM( QgsApplication::mThemeName );
57 QStringList
ABISYM( QgsApplication::mDefaultSvgPaths );
58 QMap<QString, QString>
ABISYM( QgsApplication::mSystemEnvVars );
59 QString
ABISYM( QgsApplication::mConfigPath );
60 bool ABISYM( QgsApplication::mRunningFromBuildDir ) =
false;
61 QString
ABISYM( QgsApplication::mBuildSourcePath );
63 QString
ABISYM( QgsApplication::mCfgIntDir );
65 QString
ABISYM( QgsApplication::mBuildOutputPath );
66 QStringList
ABISYM( QgsApplication::mGdalSkipList );
67 int ABISYM( QgsApplication::mMaxThreads );
87 : QApplication( argc, argv, GUIenabled )
89 init( customConfigPath );
94 if ( customConfigPath.isEmpty() )
96 if ( getenv(
"QGIS_CUSTOM_CONFIG_PATH" ) )
98 customConfigPath = getenv(
"QGIS_CUSTOM_CONFIG_PATH" );
102 customConfigPath = QString(
"%1/.qgis%2/" ).arg( QDir::homePath() ).arg(
QGis::QGIS_VERSION_INT / 10000 );
106 qRegisterMetaType<QgsGeometry::Error>(
"QgsGeometry::Error" );
108 QString
prefixPath( getenv(
"QGIS_PREFIX_PATH" ) ? getenv(
"QGIS_PREFIX_PATH" ) : applicationDirPath() );
114 foreach ( QString path, QStringList() <<
"" <<
"/.." <<
"/bin" <<
"/../../.." )
116 f.setFileName( prefixPath + path +
"/qgisbuildpath.txt" );
120 if ( f.exists() && f.open( QIODevice::ReadOnly ) )
122 ABISYM( mRunningFromBuildDir ) =
true;
123 ABISYM( mBuildSourcePath ) = f.readLine().trimmed();
124 ABISYM( mBuildOutputPath ) = f.readLine().trimmed();
125 qDebug(
"Running from build directory!" );
126 qDebug(
"- source directory: %s", ABISYM( mBuildSourcePath ).toUtf8().data() );
127 qDebug(
"- output directory of the build: %s", ABISYM( mBuildOutputPath ).toUtf8().data() );
129 ABISYM( mCfgIntDir ) = prefixPath.split(
"/", QString::SkipEmptyParts ).last();
130 qDebug(
"- cfg: %s", ABISYM( mCfgIntDir ).toUtf8().data() );
134 if ( ABISYM( mRunningFromBuildDir ) )
137 ABISYM( mPrefixPath ) = QString();
138 #if defined(_MSC_VER) && !defined(USING_NMAKE)
139 setPluginPath( ABISYM( mBuildOutputPath ) +
"/" + QString( QGIS_PLUGIN_SUBDIR ) +
"/" + ABISYM( mCfgIntDir ) );
141 setPluginPath( ABISYM( mBuildOutputPath ) +
"/" + QString( QGIS_PLUGIN_SUBDIR ) );
144 ABISYM( mLibraryPath ) = ABISYM( mBuildOutputPath ) +
"/" + QGIS_LIB_SUBDIR +
"/";
145 #if defined(_MSC_VER) && !defined(USING_NMAKE)
146 ABISYM( mLibexecPath ) = ABISYM( mBuildOutputPath ) +
"/" + QGIS_LIBEXEC_SUBDIR +
"/" + ABISYM( mCfgIntDir ) +
"/";
148 ABISYM( mLibexecPath ) = ABISYM( mBuildOutputPath ) +
"/" + QGIS_LIBEXEC_SUBDIR +
"/";
153 char *prefixPath = getenv(
"QGIS_PREFIX_PATH" );
156 #if defined(Q_OS_MACX) || defined(Q_OS_WIN32) || defined(WIN32)
158 #elif defined(ANDROID)
160 QDir myDir( QDir::homePath() );
162 QString myPrefix = myDir.absolutePath();
165 QDir myDir( applicationDirPath() );
167 QString myPrefix = myDir.absolutePath();
177 if ( !customConfigPath.isEmpty() )
179 ABISYM( mConfigPath ) = customConfigPath +
"/";
185 QMap<QString, QString> systemEnvVarMap;
186 foreach (
const QString &varStr, QProcess::systemEnvironment() )
188 int pos = varStr.indexOf( QLatin1Char(
'=' ) );
191 QString varStrName = varStr.left( pos );
192 QString varStrValue = varStr.mid( pos + 1 );
193 systemEnvVarMap.insert( varStrName, varStrValue );
195 ABISYM( mSystemEnvVars ) = systemEnvVarMap;
198 QCoreApplication::addLibraryPath(
pluginPath() );
203 ABISYM( mMaxThreads ) = -1;
213 if ( event->type() == QEvent::FileOpen )
216 if ( ABISYM( mFileOpenEventReceiver ) )
219 done =
notify( ABISYM( mFileOpenEventReceiver ), event );
226 ABISYM( mFileOpenEventList ).append( static_cast<QFileOpenEvent *>( event )->
file() );
242 if ( thread() == receiver->thread() )
243 emit
preNotify( receiver, event, &done );
257 if ( qApp->thread() == QThread::currentThread() )
258 QMessageBox::critical( activeWindow(),
tr(
"Exception" ), e.
what() );
260 catch ( std::exception & e )
262 QgsDebugMsg(
"Caught unhandled std::exception: " + QString::fromAscii( e.what() ) );
263 if ( qApp->thread() == QThread::currentThread() )
264 QMessageBox::critical( activeWindow(),
tr(
"Exception" ), e.what() );
268 QgsDebugMsg(
"Caught unhandled unknown exception" );
269 if ( qApp->thread() == QThread::currentThread() )
270 QMessageBox::critical( activeWindow(),
tr(
"Exception" ),
tr(
"unknown exception" ) );
279 ABISYM( mFileOpenEventReceiver ) = receiver;
281 if ( ABISYM( mFileOpenEventList ).count() > 0 )
283 QStringListIterator i( ABISYM( mFileOpenEventList ) );
284 while ( i.hasNext() )
286 QFileOpenEvent foe( i.next() );
287 QgsApplication::sendEvent( ABISYM( mFileOpenEventReceiver ), &foe );
289 ABISYM( mFileOpenEventList ).clear();
295 ABISYM( mPrefixPath ) = thePrefixPath;
296 #if defined(_MSC_VER)
297 if ( ABISYM( mPrefixPath ).endsWith(
"/bin" ) )
299 ABISYM( mPrefixPath ).chop( 4 );
302 if ( useDefaultPaths && !ABISYM( mRunningFromBuildDir ) )
304 setPluginPath( ABISYM( mPrefixPath ) +
"/" + QString( QGIS_PLUGIN_SUBDIR ) );
305 setPkgDataPath( ABISYM( mPrefixPath ) +
"/" + QString( QGIS_DATA_SUBDIR ) );
307 ABISYM( mLibraryPath ) = ABISYM( mPrefixPath ) +
"/" + QGIS_LIB_SUBDIR +
"/";
308 ABISYM( mLibexecPath ) = ABISYM( mPrefixPath ) +
"/" + QGIS_LIBEXEC_SUBDIR +
"/";
313 ABISYM( mPluginPath ) = thePluginPath;
318 ABISYM( mPkgDataPath ) = thePkgDataPath;
319 QString mySvgPath = thePkgDataPath + ( ABISYM( mRunningFromBuildDir ) ?
"/images/svg/" :
"/svg/" );
321 if ( !ABISYM( mDefaultSvgPaths ).contains( mySvgPath ) )
322 ABISYM( mDefaultSvgPaths ) << mySvgPath;
327 ABISYM( mDefaultSvgPaths ) = pathList;
332 if ( ABISYM( mRunningFromBuildDir ) )
334 static bool once =
true;
336 qWarning(
"!!! prefix path was requested, but it is not valid - we do not run from installed path !!!" );
340 return ABISYM( mPrefixPath );
344 return ABISYM( mPluginPath );
348 return ABISYM( mPkgDataPath );
352 return ":/images/themes/default/";
356 return ":/images/themes/" +
themeName() +
"/";
364 if ( QFile::exists( path + iconFile ) )
365 return path + iconFile;
373 QString myPreferredPath =
activeThemePath() + QDir::separator() + theName;
375 if ( QFile::exists( myPreferredPath ) )
377 return QIcon( myPreferredPath );
379 else if ( QFile::exists( myDefaultPath ) )
383 return QIcon( myDefaultPath );
394 QString myPreferredPath =
activeThemePath() + QDir::separator() + theName;
396 if ( QFile::exists( myPreferredPath ) )
398 return QPixmap( myPreferredPath );
404 return QPixmap( myDefaultPath );
413 QString myPath =
":/images/themes/" + theThemeName +
"/";
415 if ( QFile::exists( myPath ) )
417 ABISYM( mThemeName ) = theThemeName;
421 ABISYM( mThemeName ) =
"default";
429 return ABISYM( mThemeName );
436 return ABISYM( mPkgDataPath ) + QString(
"/doc/AUTHORS" );
443 return ABISYM( mPkgDataPath ) + QString(
"/doc/CONTRIBUTORS" );
447 return ABISYM( mPkgDataPath ) + QString(
"/doc/developersmap.html" );
454 return ABISYM( mPkgDataPath ) + QString(
"/doc/SPONSORS" );
462 return ABISYM( mPkgDataPath ) + QString(
"/doc/DONORS" );
468 return ABISYM( mPkgDataPath ) + QString(
"/doc/TRANSLATORS" );
474 return ABISYM( mPkgDataPath ) + QString(
"/doc/LICENSE" );
484 helpAppPath = applicationDirPath() +
"/bin/qgis_help.app/Contents/MacOS";
488 helpAppPath +=
"/qgis_help";
490 helpAppPath +=
".exe";
499 if ( ABISYM( mRunningFromBuildDir ) )
500 return ABISYM( mBuildOutputPath ) + QString(
"/i18n" );
502 return ABISYM( mPkgDataPath ) + QString(
"/i18n/" );
510 return ABISYM( mPkgDataPath ) + QString(
"/resources/qgis.db" );
518 return ABISYM( mConfigPath );
534 return QString(
":/images/splash/" );
542 return ABISYM( mPkgDataPath ) + QString(
"/images/icons/" );
549 if ( ABISYM( mRunningFromBuildDir ) )
551 QString tempCopy = QDir::tempPath() +
"/srs.db";
553 if ( !QFile( tempCopy ).exists() )
555 QFile f( ABISYM( mPkgDataPath ) +
"/resources/srs.db" );
556 if ( !f.copy( tempCopy ) )
558 qFatal(
"Could not create temporary copy" );
566 return ABISYM( mPkgDataPath ) + QString(
"/resources/srs.db" );
578 QStringList myPathList;
579 QString myPaths = settings.value(
"svg/searchPathsForSVG",
"" ).toString();
580 if ( !myPaths.isEmpty() )
582 myPathList = myPaths.split(
"|" );
585 myPathList << ABISYM( mDefaultSvgPaths );
596 return ABISYM( mPkgDataPath ) + QString(
"/resources/symbology-ng-style.db" );
601 return ABISYM( mLibraryPath );
606 return ABISYM( mLibexecPath );
611 return ( htonl( 1 ) == 1 ) ?
XDR :
NDR;
636 QString myEnvironmentVar( getenv(
"QGIS_PREFIX_PATH" ) );
637 QString myState =
tr(
"Application state:\n"
638 "QGIS_PREFIX_PATH env var:\t\t%1\n"
640 "Plugin Path:\t\t%3\n"
641 "Package Data Path:\t%4\n"
642 "Active Theme Name:\t%5\n"
643 "Active Theme Path:\t%6\n"
644 "Default Theme Path:\t%7\n"
645 "SVG Search Paths:\t%8\n"
646 "User DB Path:\t%9\n" )
647 .arg( myEnvironmentVar )
654 .arg(
svgPaths().join(
tr(
"\n\t\t",
"match indentation of application state" ) ) )
666 QColor myColor1( Qt::lightGray );
667 QColor myColor2 = myColor1;
668 myColor2 = myColor2.lighter( 110 );
670 myStyle =
"p.glossy{ background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, "
671 " stop: 0 " + myColor1.name() +
","
672 " stop: 0.1 " + myColor2.name() +
","
673 " stop: 0.5 " + myColor1.name() +
","
674 " stop: 0.9 " + myColor2.name() +
","
675 " stop: 1 " + myColor1.name() +
");"
677 " padding-left: 4px;"
678 " padding-top: 20px;"
679 " padding-bottom: 8px;"
680 " border: 1px solid #6c6c6c;"
682 "p.subheaderglossy{ background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, "
683 " stop: 0 " + myColor1.name() +
","
684 " stop: 0.1 " + myColor2.name() +
","
685 " stop: 0.5 " + myColor1.name() +
","
686 " stop: 0.9 " + myColor2.name() +
","
687 " stop: 1 " + myColor1.name() +
");"
688 " font-weight: bold;"
689 " font-size: medium;"
690 " line-height: 1.1em;"
693 " padding-left: 4px;"
694 " padding-right: 4px;"
695 " padding-top: 20px;"
696 " padding-bottom: 8px;"
697 " border: 1px solid #6c6c6c;"
699 "th.glossy{ background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, "
700 " stop: 0 " + myColor1.name() +
","
701 " stop: 0.1 " + myColor2.name() +
","
702 " stop: 0.5 " + myColor1.name() +
","
703 " stop: 0.9 " + myColor2.name() +
","
704 " stop: 1 " + myColor1.name() +
");"
706 " border: 1px solid #6c6c6c;"
708 ".overview{ font: 1.82em; font-weight: bold;}"
709 "body{ background: white;"
711 " font-family: arial,sans-serif;"
713 "h1{ background-color: #F6F6F6;"
715 " font-size: x-large; "
716 " font-weight: normal;"
717 " font-family: luxi serif, georgia, times new roman, times, serif;"
719 " padding: 0.75em 0 0;"
723 "h2{ background-color: #F6F6F6;"
725 " font-size: medium; "
726 " font-weight: normal;"
727 " font-family: luxi serif, georgia, times new roman, times, serif;"
729 " padding: 0.75em 0 0;"
731 " line-height: 1.1em;"
733 "h3{ background-color: #F6F6F6;"
735 " font-family: luxi serif, georgia, times new roman, times, serif;"
736 " font-weight: bold;"
738 " text-align: right;"
739 " border-bottom: 5px solid #DCEB5C;"
741 "h4{ background-color: #F6F6F6;"
743 " font-family: luxi serif, georgia, times new roman, times, serif;"
744 " font-weight: bold;"
745 " font-size: medium;"
746 " text-align: right;"
748 "h5{ background-color: #F6F6F6;"
750 " font-family: luxi serif, georgia, times new roman, times, serif;"
751 " font-weight: bold;"
753 " text-align: right;"
756 " font-family: arial,sans-serif;"
759 "label{ background-color: #FFFFCC;"
760 " border: 1px solid black;"
762 " padding: 0px 3px; "
770 if ( 0 >= OGRGetDriverCount() )
778 #if defined( Q_OS_WIN )
779 const Qt::CaseSensitivity cs = Qt::CaseInsensitive;
781 aPath.replace(
"\\",
"/" );
782 if ( aPath.startsWith(
"//" ) )
785 aPath =
"\\\\" + aPath.mid( 2 );
788 targetPath.replace(
"\\",
"/" );
789 if ( targetPath.startsWith(
"//" ) )
792 targetPath =
"\\\\" + targetPath.mid( 2 );
795 const Qt::CaseSensitivity cs = Qt::CaseSensitive;
798 QStringList targetElems = targetPath.split(
"/", QString::SkipEmptyParts );
799 QStringList aPathElems = aPath.split(
"/", QString::SkipEmptyParts );
801 targetElems.removeAll(
"." );
802 aPathElems.removeAll(
"." );
806 while ( aPathElems.size() > 0 &&
807 targetElems.size() > 0 &&
808 aPathElems[0].compare( targetElems[0], cs ) == 0 )
810 aPathElems.removeFirst();
811 targetElems.removeFirst();
821 if ( targetElems.size() > 0 )
824 for (
int i = 0; i < targetElems.size(); i++ )
826 aPathElems.insert( 0,
".." );
833 aPathElems.insert( 0,
"." );
836 return aPathElems.join(
"/" );
842 if ( !rpath.startsWith(
"./" ) && !rpath.startsWith(
"../" ) )
847 #if defined(Q_OS_WIN)
848 rpath.replace(
"\\",
"/" );
849 targetPath.replace(
"\\",
"/" );
851 bool uncPath = targetPath.startsWith(
"//" );
854 QStringList srcElems = rpath.split(
"/", QString::SkipEmptyParts );
855 QStringList targetElems = targetPath.split(
"/", QString::SkipEmptyParts );
857 #if defined(Q_OS_WIN)
860 targetElems.insert( 0,
"" );
861 targetElems.insert( 0,
"" );
866 targetElems << srcElems;
867 targetElems.removeAll(
"." );
871 while (( pos = targetElems.indexOf(
".." ) ) > 0 )
874 targetElems.removeAt( pos - 1 );
875 targetElems.removeAt( pos - 1 );
878 #if !defined(Q_OS_WIN)
880 targetElems.prepend(
"" );
883 return targetElems.join(
"/" );
888 if ( ABISYM( mGdalSkipList ).contains( theDriver ) || theDriver.isEmpty() )
892 ABISYM( mGdalSkipList ) << theDriver;
898 if ( !ABISYM( mGdalSkipList ).contains( theDriver ) )
902 int myPos = ABISYM( mGdalSkipList ).indexOf( theDriver );
905 ABISYM( mGdalSkipList ).removeAt( myPos );
912 ABISYM( mGdalSkipList ).removeDuplicates();
913 QString myDriverList = ABISYM( mGdalSkipList ).join(
" " );
916 CPLSetConfigOption(
"GDAL_SKIP", myDriverList.toUtf8() );
926 QDir myDir( myPamPath );
927 if ( !myDir.exists() )
929 myDir.mkpath( myPamPath );
932 #if defined(Q_OS_WIN32) || defined(WIN32)
933 CPLSetConfigOption(
"GDAL_PAM_PROXY_DIR", myPamPath.toUtf8() );
937 int myChangeFlag = 0;
938 setenv(
"GDAL_PAM_PROXY_DIR", myPamPath.toUtf8(), myChangeFlag );
945 if ( !qgisPrivateDbFile.exists() )
949 QFile masterFile( qgisMasterDbFileName );
955 bool isDbFileCopied = masterFile.copy( qgisPrivateDbFile.fileName() );
957 if ( !isDbFileCopied )
961 *errorMessage =
tr(
"[ERROR] Can not make qgis.db private copy" );
974 *errorMessage =
tr(
"Could not open qgis.db" );
980 int res = sqlite3_exec( db,
"SELECT epsg FROM tbl_srs LIMIT 0", 0, 0, &errmsg );
981 if ( res == SQLITE_OK )
984 if ( sqlite3_exec( db,
985 "ALTER TABLE tbl_srs RENAME TO tbl_srs_bak;"
986 "CREATE TABLE tbl_srs ("
987 "srs_id INTEGER PRIMARY KEY,"
988 "description text NOT NULL,"
989 "projection_acronym text NOT NULL,"
990 "ellipsoid_acronym NOT NULL,"
991 "parameters text NOT NULL,"
995 "is_geo integer NOT NULL,"
996 "deprecated boolean);"
997 "CREATE INDEX idx_srsauthid on tbl_srs(auth_name,auth_id);"
998 "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;"
999 "DROP TABLE tbl_srs_bak", 0, 0, &errmsg ) != SQLITE_OK
1004 *errorMessage =
tr(
"Migration of private qgis.db failed.\n%1" ).arg( QString::fromUtf8( errmsg ) );
1006 sqlite3_free( errmsg );
1007 sqlite3_close( db );
1013 sqlite3_free( errmsg );
1016 if ( sqlite3_exec( db,
"DROP VIEW vw_srs", 0, 0, &errmsg ) != SQLITE_OK )
1018 QgsDebugMsg( QString(
"vw_srs didn't exists in private qgis.db: %1" ).arg( errmsg ) );
1021 if ( sqlite3_exec( db,
1022 "CREATE VIEW vw_srs AS"
1024 " a.description AS description"
1025 ",a.srs_id AS srs_id"
1026 ",a.is_geo AS is_geo"
1027 ",coalesce(b.name,a.projection_acronym) AS name"
1028 ",a.parameters AS parameters"
1029 ",a.auth_name AS auth_name"
1030 ",a.auth_id AS auth_id"
1031 ",a.deprecated AS deprecated"
1033 " LEFT OUTER JOIN tbl_projection b ON a.projection_acronym=b.acronym"
1034 " ORDER BY coalesce(b.name,a.projection_acronym),a.description", 0, 0, &errmsg ) != SQLITE_OK
1039 *errorMessage =
tr(
"Update of view in private qgis.db failed.\n%1" ).arg( QString::fromUtf8( errmsg ) );
1041 sqlite3_free( errmsg );
1042 sqlite3_close( db );
1046 sqlite3_close( db );
1053 QgsDebugMsg( QString(
"maxThreads: %1" ).arg( maxThreads ) );
1057 if ( maxThreads < 1 || maxThreads > QThread::idealThreadCount() )
1064 if ( maxThreads == -1 )
1065 maxThreads = QThread::idealThreadCount();
1068 QThreadPool::globalInstance()->setMaxThreadCount( maxThreads );
1069 QgsDebugMsg( QString(
"set QThreadPool max thread count to %1" ).arg( QThreadPool::globalInstance()->maxThreadCount() ) );