UniversalIndentGUI 1.2.0
SettingsPaths.cpp
Go to the documentation of this file.
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 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines