UniversalIndentGUI 1.2.0
|
00001 /*************************************************************************** 00002 * Copyright (C) 2006-2012 by Thomas Schweitzer * 00003 * thomas-schweitzer(at)arcor.de * 00004 * * 00005 * This program is free software; you can redistribute it and/or modify * 00006 * it under the terms of the GNU General Public License version 2.0 as * 00007 * published by the Free Software Foundation. * 00008 * * 00009 * This program is distributed in the hope that it will be useful, * 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 00012 * GNU General Public License for more details. * 00013 * * 00014 * You should have received a copy of the GNU General Public License * 00015 * along with this program in the file LICENSE.GPL; if not, write to the * 00016 * Free Software Foundation, Inc., * 00017 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * 00018 ***************************************************************************/ 00019 00020 #include "SettingsPaths.h" 00021 00022 #include <QCoreApplication> 00023 #include <QFile> 00024 #include <QDir> 00025 #include <QDirIterator> 00026 #include <QStack> 00027 #include <QtDebug> 00028 00029 #include <stdlib.h> 00030 00032 00040 bool SettingsPaths::_alreadyInitialized = false; 00041 QString SettingsPaths::_applicationBinaryPath = ""; 00042 QString SettingsPaths::_settingsPath = ""; 00043 QString SettingsPaths::_globalFilesPath = ""; 00044 QString SettingsPaths::_indenterPath = ""; 00045 QString SettingsPaths::_tempPath = ""; 00046 bool SettingsPaths::_portableMode = false; 00047 00048 00059 void SettingsPaths::init() { 00060 _alreadyInitialized = true; 00061 00062 qDebug() << __LINE__ << " " << __FUNCTION__ << ": Initializing application paths."; 00063 00064 // Get the applications binary path, with respect to MacOSXs use of the .app folder. 00065 _applicationBinaryPath = QCoreApplication::applicationDirPath(); 00066 // Remove any trailing slashes 00067 while ( _applicationBinaryPath.right(1) == "/" ) { 00068 _applicationBinaryPath.chop(1); 00069 } 00070 00071 #ifdef UNIVERSALINDENTGUI_NPP_EXPORTS 00072 _applicationBinaryPath += "/plugins/uigui"; 00073 #endif 00074 00075 #ifdef Q_OS_MAC 00076 // Because on Mac universal binaries are used, the binary path is not equal 00077 // to the applications (.app) path. So get the .apps path here. 00078 int indexOfDotApp = _applicationBinaryPath.indexOf(".app"); 00079 if ( indexOfDotApp != -1 ) { 00080 // Cut off after the dot of ".app". 00081 _applicationBinaryPath = _applicationBinaryPath.left( indexOfDotApp-1 ); 00082 // Cut off after the first slash that was in front of ".app" (normally this is the word "UniversalIndentGUI") 00083 _applicationBinaryPath = _applicationBinaryPath.left( _applicationBinaryPath.lastIndexOf("/") ); 00084 } 00085 #endif 00086 00087 // If the "config" directory is a subdir of the applications binary path, use this one (portable mode) 00088 _settingsPath = _applicationBinaryPath + "/config"; 00089 if ( QFile::exists( _settingsPath ) ) { 00090 _portableMode = true; 00091 QDir dirCreator; 00092 _globalFilesPath = _applicationBinaryPath; 00093 _indenterPath = _applicationBinaryPath + "/indenters"; 00094 dirCreator.mkpath( _settingsPath ); 00095 _tempPath = _applicationBinaryPath + "/temp"; 00096 //TODO: If the portable drive has write protection, use local temp path and clean it up on exit. 00097 dirCreator.mkpath( _tempPath ); 00098 } 00099 // ... otherwise use the system specific global application data path. 00100 else { 00101 _portableMode = false; 00102 QDir dirCreator; 00103 #ifdef Q_OS_WIN 00104 // Get the local users application settings directory. 00105 // Remove any trailing slashes. 00106 _settingsPath = QDir::fromNativeSeparators( qgetenv("APPDATA") ); 00107 while ( _settingsPath.right(1) == "/" ) { 00108 _settingsPath.chop(1); 00109 } 00110 _settingsPath = _settingsPath + "/UniversalIndentGUI"; 00111 00112 // On windows systems the directories "indenters", "translations" are subdirs of the _applicationBinaryPath. 00113 _globalFilesPath = _applicationBinaryPath; 00114 #else 00115 // Remove any trailing slashes. 00116 _settingsPath = QDir::homePath(); 00117 while ( _settingsPath.right(1) == "/" ) { 00118 _settingsPath.chop(1); 00119 } 00120 _settingsPath = _settingsPath + "/.universalindentgui"; 00121 _globalFilesPath = "/usr/share/universalindentgui"; 00122 #endif 00123 dirCreator.mkpath( _settingsPath ); 00124 // If a highlighter config file does not exist in the users home config dir 00125 // copy the default config file over there. 00126 if ( !QFile::exists(_settingsPath+"/UiGuiSyntaxHighlightConfig.ini") ) { 00127 QFile::copy( _globalFilesPath+"/config/UiGuiSyntaxHighlightConfig.ini", _settingsPath+"/UiGuiSyntaxHighlightConfig.ini" ); 00128 } 00129 _indenterPath = _globalFilesPath + "/indenters"; 00130 00131 // On different systems it may be that "QDir::tempPath()" ends with a "/" or not. So check this. 00132 // Remove any trailing slashes. 00133 _tempPath = QDir::tempPath(); 00134 while ( _tempPath.right(1) == "/" ) { 00135 _tempPath.chop(1); 00136 } 00137 _tempPath = _tempPath + "/UniversalIndentGUI"; 00138 00139 #if defined(Q_OS_WIN32) 00140 dirCreator.mkpath( _tempPath ); 00141 #else 00142 // On Unix based systems create a random temporary directory for security 00143 // reasons. Otherwise an evil human being could create a symbolic link 00144 // to an important existing file which gets overwritten when UiGUI writes 00145 // into this normally temporary but linked file. 00146 char *pathTemplate = new char[_tempPath.length()+8]; 00147 QByteArray pathTemplateQBA = QString(_tempPath + "-XXXXXX").toAscii(); 00148 delete [] pathTemplate; 00149 pathTemplate = pathTemplateQBA.data(); 00150 pathTemplate = mkdtemp( pathTemplate ); 00151 _tempPath = pathTemplate; 00152 #endif 00153 } 00154 00155 qDebug() << __LINE__ << " " << __FUNCTION__ << ": Paths are:" \ 00156 "<ul><li>_applicationBinaryPath=" << _applicationBinaryPath \ 00157 << "</li><li>_settingsPath=" << _settingsPath \ 00158 << "</li><li>_globalFilesPath=" << _globalFilesPath \ 00159 << "</li><li>_indenterPath=" << _indenterPath \ 00160 << "</li><li>_tempPath=" << _tempPath \ 00161 << "</li><li>Running in portable mode=" << _portableMode << "</li></ul>"; 00162 } 00163 00164 00168 const QString SettingsPaths::getApplicationBinaryPath() { 00169 if ( !_alreadyInitialized ) { 00170 SettingsPaths::init(); 00171 } 00172 return _applicationBinaryPath; 00173 } 00174 00175 00179 const QString SettingsPaths::getSettingsPath() { 00180 if ( !_alreadyInitialized ) { 00181 SettingsPaths::init(); 00182 } 00183 return _settingsPath; 00184 } 00185 00186 00190 const QString SettingsPaths::getGlobalFilesPath() { 00191 if ( !_alreadyInitialized ) { 00192 SettingsPaths::init(); 00193 } 00194 return _globalFilesPath; 00195 } 00196 00197 00201 const QString SettingsPaths::getIndenterPath() { 00202 if ( !_alreadyInitialized ) { 00203 SettingsPaths::init(); 00204 } 00205 return _indenterPath; 00206 } 00207 00208 00212 const QString SettingsPaths::getTempPath() { 00213 if ( !_alreadyInitialized ) { 00214 SettingsPaths::init(); 00215 } 00216 return _tempPath; 00217 } 00218 00219 00223 bool SettingsPaths::getPortableMode() { 00224 if ( !_alreadyInitialized ) { 00225 SettingsPaths::init(); 00226 } 00227 return _portableMode; 00228 } 00229 00230 00234 void SettingsPaths::cleanAndRemoveTempDir() { 00235 QDirIterator dirIterator(_tempPath, QDirIterator::Subdirectories); 00236 QStack<QString> directoryStack; 00237 bool noErrorsOccurred = true; 00238 00239 while ( dirIterator.hasNext() ) { 00240 QString currentDirOrFile = dirIterator.next(); 00241 // If this dummy call isn't done here, calling "dirIterator.fileInfo().isDir()" later somehow fails. 00242 dirIterator.fileInfo(); 00243 00244 if ( !currentDirOrFile.isEmpty() && dirIterator.fileName() != "." && dirIterator.fileName() != ".." ) { 00245 // There is a path on the stack but the current path doesn't start with that path. 00246 // So we changed into another parent directory and the one on the stack can be deleted 00247 // since it must be empty. 00248 if ( !directoryStack.isEmpty() && !currentDirOrFile.startsWith(directoryStack.top()) ) { 00249 QString dirToBeRemoved = directoryStack.pop(); 00250 bool couldRemoveDir = QDir(dirToBeRemoved).rmdir(dirToBeRemoved); 00251 noErrorsOccurred &= couldRemoveDir; 00252 if ( couldRemoveDir == false ) 00253 qWarning() << __LINE__ << " " << __FUNCTION__ << "Could not remove the directory: " << dirToBeRemoved; 00254 //qDebug() << "Removing Dir " << directoryStack.pop(); 00255 } 00256 00257 // If the iterator currently points to a directory push it onto the stack. 00258 if ( dirIterator.fileInfo().isDir() ) { 00259 directoryStack.push( currentDirOrFile ); 00260 //qDebug() << "Pushing onto Stack " << currentDirOrFile; 00261 } 00262 // otherwise it must be a file, so delete it. 00263 else { 00264 bool couldRemoveFile = QFile::remove( currentDirOrFile ); 00265 noErrorsOccurred &= couldRemoveFile; 00266 if ( couldRemoveFile == false ) 00267 qWarning() << __LINE__ << " " << __FUNCTION__ << "Could not remove the file: " << currentDirOrFile; 00268 //qDebug() << "Removing File " << currentDirOrFile; 00269 } 00270 } 00271 } 00272 noErrorsOccurred &= QDir(_tempPath).rmdir(_tempPath); 00273 if ( noErrorsOccurred == false ) 00274 qWarning() << __LINE__ << " " << __FUNCTION__ << "While cleaning up the temp dir an error occurred."; 00275 }