|
|
|
@ -19,25 +19,11 @@ |
|
|
|
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * |
|
|
|
|
***************************************************************************/ |
|
|
|
|
|
|
|
|
|
#include <iostream> |
|
|
|
|
#include <QLibraryInfo> |
|
|
|
|
#include <QLocale> |
|
|
|
|
#include <QDir> |
|
|
|
|
#include <QtCore> |
|
|
|
|
#include <QMessageBox> |
|
|
|
|
#include <QTranslator> |
|
|
|
|
#include <QPainter> |
|
|
|
|
#include <QImage> |
|
|
|
|
#include <QStyleFactory> |
|
|
|
|
#include <QProcess> |
|
|
|
|
#include <QDesktopServices> |
|
|
|
|
#include <QUrl> |
|
|
|
|
#include <QCoreApplication> |
|
|
|
|
#include <QVarLengthArray> |
|
|
|
|
|
|
|
|
|
#include <iostream> |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
#include <QLibary> |
|
|
|
|
#include <QPluginLoader> |
|
|
|
|
#include "plugins/interfaces/IFileDialog.h" |
|
|
|
|
#include "plugins/interfaces/IKdeInit.h" |
|
|
|
|
#include "plugins/interfaces/IGnomeInit.h" |
|
|
|
@ -55,18 +41,9 @@ |
|
|
|
|
#if defined(Q_WS_X11) && defined(GLOBAL_AUTOTYPE) |
|
|
|
|
#include "Application_X11.h" |
|
|
|
|
#endif |
|
|
|
|
#ifdef Q_WS_WIN |
|
|
|
|
#include <windows.h> |
|
|
|
|
#endif |
|
|
|
|
#ifdef Q_WS_MAC |
|
|
|
|
#include <Carbon/Carbon.h> |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
using namespace std; |
|
|
|
|
|
|
|
|
|
QHash<QString,QPixmap*>PixmapCache; |
|
|
|
|
QHash<QString,QIcon*>IconCache; |
|
|
|
|
|
|
|
|
|
KpxConfig *config; |
|
|
|
|
QString AppDir; |
|
|
|
|
QString HomeDir; |
|
|
|
@ -77,42 +54,25 @@ QString DetailViewTemplate; |
|
|
|
|
|
|
|
|
|
QPixmap* EntryIcons; |
|
|
|
|
//IIconTheme* IconLoader=NULL; //TODO plugins
|
|
|
|
|
char ** argv; |
|
|
|
|
|
|
|
|
|
inline void loadImages(); |
|
|
|
|
inline void parseCmdLineArgs(int argc, char** argv,QString &ArgFile,QString& ArgCfg,QString& ArgLang,bool& ArgMin,bool& ArgLock); |
|
|
|
|
bool loadTranslation(QTranslator* tr,const QString& prefix,const QString& LocaleCode,const QStringList& SearchPaths); |
|
|
|
|
void initAppPaths(int argc, char **argv); |
|
|
|
|
|
|
|
|
|
int main(int argc, char **_argv) |
|
|
|
|
int main(int argc, char **argv) |
|
|
|
|
{ |
|
|
|
|
argv=_argv; |
|
|
|
|
QString ArgFile,ArgCfg,ArgLang,IniFilename; |
|
|
|
|
QApplication* app=NULL; |
|
|
|
|
AppDir=applicationDirPath(); |
|
|
|
|
#if defined Q_WS_WIN |
|
|
|
|
HomeDir = QString::fromLocal8Bit(qgetenv("APPDATA").constData()); |
|
|
|
|
if(!HomeDir.isEmpty() && QFile::exists(HomeDir)) |
|
|
|
|
HomeDir = QDir::fromNativeSeparators(HomeDir)+"/KeePassX"; |
|
|
|
|
else |
|
|
|
|
HomeDir = QDir::homePath()+"/KeePassX"; |
|
|
|
|
#else |
|
|
|
|
HomeDir = QDir::homePath()+"/.keepassx"; |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
#if defined Q_WS_MACX |
|
|
|
|
DataDir=AppDir+"/../Resources/keepassx"; |
|
|
|
|
#elif defined Q_WS_WIN |
|
|
|
|
DataDir=AppDir+"/share"; |
|
|
|
|
#else |
|
|
|
|
DataDir=AppDir+"/../share/keepassx"; |
|
|
|
|
#endif |
|
|
|
|
bool ArgMin = false; |
|
|
|
|
bool ArgLock = false; |
|
|
|
|
parseCmdLineArgs(argc,argv,ArgFile,ArgCfg,ArgLang,ArgMin,ArgLock); |
|
|
|
|
qDebug(CSTR(QDir::current().absolutePath())); |
|
|
|
|
|
|
|
|
|
QApplication* app=new QApplication(argc,argv); |
|
|
|
|
initAppPaths(argc,argv); |
|
|
|
|
CmdLineArgs args; |
|
|
|
|
args.parse(app->arguments()); |
|
|
|
|
delete app; |
|
|
|
|
app=NULL; |
|
|
|
|
qDebug(CSTR(AppDir)); |
|
|
|
|
qDebug(CSTR(DataDir)); |
|
|
|
|
//Load Config
|
|
|
|
|
if(ArgCfg.isEmpty()){ |
|
|
|
|
QString IniFilename; |
|
|
|
|
if(args.configLocation().isEmpty()){ |
|
|
|
|
if(!QDir(HomeDir).exists()){ |
|
|
|
|
QDir conf(QDir::homePath()); |
|
|
|
|
if(!QDir().mkpath(HomeDir)) |
|
|
|
@ -121,8 +81,7 @@ int main(int argc, char **_argv) |
|
|
|
|
IniFilename=HomeDir+"/config"; |
|
|
|
|
} |
|
|
|
|
else |
|
|
|
|
IniFilename=ArgCfg; |
|
|
|
|
|
|
|
|
|
IniFilename=args.configLocation(); |
|
|
|
|
|
|
|
|
|
config = new KpxConfig(IniFilename); |
|
|
|
|
fileDlgHistory.load(); |
|
|
|
@ -180,10 +139,10 @@ int main(int argc, char **_argv) |
|
|
|
|
|
|
|
|
|
//Internationalization
|
|
|
|
|
QLocale loc; |
|
|
|
|
if(!ArgLang.size()) |
|
|
|
|
if(!args.language().size()) |
|
|
|
|
loc=QLocale::system(); |
|
|
|
|
else |
|
|
|
|
loc=QLocale(ArgLang); |
|
|
|
|
loc=QLocale(args.language()); |
|
|
|
|
|
|
|
|
|
QTranslator* translator = NULL; |
|
|
|
|
QTranslator* qtTranslator=NULL; |
|
|
|
@ -221,7 +180,6 @@ int main(int argc, char **_argv) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
DetailViewTemplate=config->detailViewTemplate(); |
|
|
|
|
|
|
|
|
|
loadImages(); |
|
|
|
@ -230,7 +188,7 @@ int main(int argc, char **_argv) |
|
|
|
|
SecString::generateSessionKey(); |
|
|
|
|
|
|
|
|
|
QApplication::setQuitOnLastWindowClosed(false); |
|
|
|
|
KeepassMainWindow *mainWin = new KeepassMainWindow(ArgFile,ArgMin,ArgLock); |
|
|
|
|
KeepassMainWindow *mainWin = new KeepassMainWindow(args.file(), args.startMinimized(), args.startLocked()); |
|
|
|
|
int r=app->exec(); |
|
|
|
|
delete mainWin; |
|
|
|
|
|
|
|
|
@ -241,103 +199,6 @@ int main(int argc, char **_argv) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void createBanner(QPixmap* Pixmap,const QPixmap* IconAlpha,const QString& Text,int Width){ |
|
|
|
|
createBanner(Pixmap,IconAlpha,Text,Width,config->bannerColor1(),config->bannerColor2(),config->bannerTextColor()); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void createBanner(QPixmap* Pixmap,const QPixmap* IconAlpha,const QString& Text,int Width, QColor Color1, QColor Color2, QColor TextColor){ |
|
|
|
|
*Pixmap=QPixmap(Width,50); |
|
|
|
|
QPainter painter(Pixmap); |
|
|
|
|
QLinearGradient grad(0,0,Width,0); |
|
|
|
|
grad.setColorAt(0,Color1); |
|
|
|
|
grad.setColorAt(1,Color2); |
|
|
|
|
painter.setPen(Qt::NoPen); |
|
|
|
|
painter.setBrush(grad); |
|
|
|
|
painter.drawRect(0,0,Width,50); |
|
|
|
|
|
|
|
|
|
QPixmap Icon(32,32); |
|
|
|
|
if(IconAlpha){ |
|
|
|
|
Icon.fill(TextColor); |
|
|
|
|
Icon.setAlphaChannel(*IconAlpha); |
|
|
|
|
painter.drawPixmap(10,10,Icon); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
painter.setPen(QPen(TextColor)); |
|
|
|
|
painter.setFont(QFont(QApplication::font().family(),16)); |
|
|
|
|
painter.drawText(50,35,Text); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
QString decodeFileError(QFile::FileError Code){ |
|
|
|
|
switch(Code){ |
|
|
|
|
case QFile::NoError: return QApplication::translate("FileErrors","No error occurred."); |
|
|
|
|
case QFile::ReadError: return QApplication::translate("FileErrors","An error occurred while reading from the file."); |
|
|
|
|
case QFile::WriteError: return QApplication::translate("FileErrors","An error occurred while writing to the file."); |
|
|
|
|
case QFile::FatalError: return QApplication::translate("FileErrors","A fatal error occurred."); |
|
|
|
|
case QFile::ResourceError: return QApplication::translate("FileErrors","An resource error occurred."); |
|
|
|
|
case QFile::OpenError: return QApplication::translate("FileErrors","The file could not be opened."); |
|
|
|
|
case QFile::AbortError: return QApplication::translate("FileErrors","The operation was aborted."); |
|
|
|
|
case QFile::TimeOutError: return QApplication::translate("FileErrors","A timeout occurred."); |
|
|
|
|
case QFile::UnspecifiedError: return QApplication::translate("FileErrors","An unspecified error occurred."); |
|
|
|
|
case QFile::RemoveError: return QApplication::translate("FileErrors","The file could not be removed."); |
|
|
|
|
case QFile::RenameError: return QApplication::translate("FileErrors","The file could not be renamed."); |
|
|
|
|
case QFile::PositionError: return QApplication::translate("FileErrors","The position in the file could not be changed."); |
|
|
|
|
case QFile::ResizeError: return QApplication::translate("FileErrors","The file could not be resized."); |
|
|
|
|
case QFile::PermissionsError: return QApplication::translate("FileErrors","The file could not be accessed."); |
|
|
|
|
case QFile::CopyError: return QApplication::translate("FileErrors","The file could not be copied."); |
|
|
|
|
} |
|
|
|
|
return QString(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void openBrowser(IEntryHandle* entry){ |
|
|
|
|
QString url = entry->url(); |
|
|
|
|
url.replace("{TITLE}", entry->title(), Qt::CaseInsensitive); |
|
|
|
|
url.replace("{USERNAME}", entry->username(), Qt::CaseInsensitive); |
|
|
|
|
|
|
|
|
|
if (url.contains("{PASSWORD}",Qt::CaseInsensitive)){ |
|
|
|
|
SecString password=entry->password(); |
|
|
|
|
password.unlock(); |
|
|
|
|
url.replace("{PASSWORD}", password, Qt::CaseInsensitive); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
openBrowser(url); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void openBrowser(const QString& UrlString){ |
|
|
|
|
if (UrlString.startsWith("cmd://") && UrlString.length()>6){ |
|
|
|
|
QProcess::startDetached(UrlString.right(UrlString.length()-6)); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
QUrl url(UrlString); |
|
|
|
|
if(url.scheme().isEmpty()) |
|
|
|
|
url=QUrl("http://"+UrlString); |
|
|
|
|
if(config->urlCmdDef() || url.scheme()=="mailto"){ |
|
|
|
|
QDesktopServices::openUrl(url); |
|
|
|
|
} |
|
|
|
|
else{ |
|
|
|
|
QByteArray UrlEncoded = url.toEncoded(); |
|
|
|
|
QString browser = config->urlCmd(); |
|
|
|
|
if (browser.contains("%u", Qt::CaseInsensitive)) |
|
|
|
|
browser.replace("%u", UrlEncoded, Qt::CaseInsensitive); |
|
|
|
|
else if (browser.contains("%1")) |
|
|
|
|
browser.replace("%1", UrlEncoded); |
|
|
|
|
else |
|
|
|
|
browser.append(" ").append(UrlEncoded); |
|
|
|
|
QProcess::startDetached(browser); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
QString getImageFile(const QString& name){ |
|
|
|
|
if (QFile::exists(DataDir+"/icons/"+name)) |
|
|
|
|
return DataDir+"/icons/"+name; |
|
|
|
|
else{ |
|
|
|
|
QMessageBox::critical(0,QApplication::translate("Main","Error"), |
|
|
|
|
QApplication::translate("Main","File '%1' could not be found.") |
|
|
|
|
.arg(name),QApplication::translate("Main","OK"),0,0,2,1); |
|
|
|
|
exit(1); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
///TODO 0.2.3 remove
|
|
|
|
|
void loadImages(){ |
|
|
|
|
QPixmap tmpImg(getImageFile("clientic.png")); |
|
|
|
@ -347,39 +208,6 @@ void loadImages(){ |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
const QIcon& getIcon(const QString& name){ |
|
|
|
|
QIcon* CachedIcon=IconCache.value(name); |
|
|
|
|
if(CachedIcon) |
|
|
|
|
return *CachedIcon; |
|
|
|
|
QIcon* NewIcon=NULL; |
|
|
|
|
//TODO plugins
|
|
|
|
|
/*if(IconLoader){
|
|
|
|
|
NewIcon=new QIcon(IconLoader->getIcon(name)); |
|
|
|
|
if(NewIcon->isNull()){ |
|
|
|
|
delete NewIcon; |
|
|
|
|
NewIcon=NULL; |
|
|
|
|
} |
|
|
|
|
else |
|
|
|
|
IconCache.insert(name,NewIcon); |
|
|
|
|
}*/ |
|
|
|
|
if(!NewIcon) |
|
|
|
|
{ |
|
|
|
|
NewIcon=new QIcon(getImageFile(name+".png")); |
|
|
|
|
IconCache.insert(name,NewIcon); |
|
|
|
|
} |
|
|
|
|
return *NewIcon; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
const QPixmap* getPixmap(const QString& name){ |
|
|
|
|
QPixmap* CachedPixmap=PixmapCache.value(name); |
|
|
|
|
if(CachedPixmap) |
|
|
|
|
return CachedPixmap; |
|
|
|
|
QImage img(getImageFile(name+".png")); |
|
|
|
|
QPixmap* NewPixmap=new QPixmap(QPixmap::fromImage(img)); |
|
|
|
|
PixmapCache.insert(name,NewPixmap); |
|
|
|
|
return NewPixmap; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool loadTranslation(QTranslator* tr,const QString& prefix,const QString& loc,const QStringList& paths){ |
|
|
|
|
for(int i=0;i<paths.size();i++) |
|
|
|
@ -397,70 +225,77 @@ bool loadTranslation(QTranslator* tr,const QString& prefix,const QString& loc,co |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void printHelp(){ |
|
|
|
|
cout << "KeePassX" << APP_VERSION << endl; |
|
|
|
|
cout << "Usage: keepassx [Filename] [Options]" << endl; |
|
|
|
|
cout << " -help This Help" << endl; |
|
|
|
|
cout << " -cfg <CONFIG> Use specified file for loading/saving the configuration." << endl; |
|
|
|
|
cout << " -min Start minimized." << endl; |
|
|
|
|
cout << " -lock Start locked." << endl; |
|
|
|
|
cout << " -lang <LOCALE> Use specified language instead of systems default." << endl; |
|
|
|
|
cout << " <LOCALE> is the ISO-639 language code with or without ISO-3166 country code" << endl; |
|
|
|
|
cout << " Examples: de German" << endl; |
|
|
|
|
cout << " de_CH German(Switzerland)"<<endl; |
|
|
|
|
cout << " pt_BR Portuguese(Brazil)"<<endl; |
|
|
|
|
|
|
|
|
|
CmdLineArgs::CmdLineArgs(){ |
|
|
|
|
StartMinimized=false; |
|
|
|
|
StartLocked=false; |
|
|
|
|
Help=false; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void parseCmdLineArgs(int argc, char** argv,QString &ArgFile,QString& ArgCfg,QString& ArgLang,bool& ArgMin, bool& ArgLock){ |
|
|
|
|
if(argc>1){ |
|
|
|
|
int i=1; |
|
|
|
|
if(argv[i][0]!='-'){ |
|
|
|
|
ArgFile=QString::fromUtf8(argv[i]); |
|
|
|
|
i++; |
|
|
|
|
bool CmdLineArgs::parse(const QStringList& argv){ |
|
|
|
|
for(int i=1;i<argv.size();i++){ |
|
|
|
|
if(argv[i]=="-help"){ |
|
|
|
|
Help=true; |
|
|
|
|
break; // break, because other arguments will be ignored anyway
|
|
|
|
|
} |
|
|
|
|
for(; i<argc; i++){ |
|
|
|
|
if(QString(argv[i])=="-help"){ |
|
|
|
|
printHelp(); |
|
|
|
|
exit(0); |
|
|
|
|
if(argv[i]=="-cfg"){ |
|
|
|
|
if(argv.size()==i+1){ |
|
|
|
|
Error="Missing argument for '-cfg'."; |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
else if(QString(argv[i])=="-cfg"){ |
|
|
|
|
if(i-1==argc){ cout << "Missing argument for -cfg" << endl; exit(1);} |
|
|
|
|
else{ArgCfg=QString::fromUtf8(argv[i+1]); i++;} |
|
|
|
|
if(argv[i+1].left(1)=="-"){ |
|
|
|
|
Error=QString("Expected a path as argument for '-cfg' but got '%1.'").arg(argv[i+1]); |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
else if(QString(argv[i])=="-lang"){ |
|
|
|
|
if(i-1==argc) |
|
|
|
|
cout << "Missing argument for -lang" << endl; |
|
|
|
|
else |
|
|
|
|
ArgLang=QString::fromUtf8(argv[i+1]); i++; |
|
|
|
|
ConfigLocation=argv[i+1]; |
|
|
|
|
i++; |
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
|
else if(QString(argv[i])=="-min"){ |
|
|
|
|
ArgMin = true; |
|
|
|
|
if(argv[i]=="-lang"){ |
|
|
|
|
if(argv.size()==i+1){ |
|
|
|
|
Error="Missing argument for '-lang'."; |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
else if(QString(argv[i])=="-lock"){ |
|
|
|
|
ArgLock = true; |
|
|
|
|
if(argv[i+1].size() != 2 && argv[i+1].size() != 5 ){ |
|
|
|
|
Error=QString("'%1' is not a valid language code.").arg(argv[i+1]); |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
else if(QString(argv[i]).left(5)=="-psn_"){ |
|
|
|
|
// something like a pid or so, passed when starting an app bundle under MacOS X
|
|
|
|
|
// ignore
|
|
|
|
|
Language=argv[i+1]; |
|
|
|
|
i++; |
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
|
/*else if(QString(argv[i])=="-test"){
|
|
|
|
|
if (testDatabase()) exit(0); |
|
|
|
|
else exit(1); |
|
|
|
|
}*/ |
|
|
|
|
else{ |
|
|
|
|
cout << "** Unrecognized argument: " << argv[i] << endl << endl; |
|
|
|
|
printHelp(); |
|
|
|
|
exit(1); |
|
|
|
|
if(argv[i]=="-min"){ |
|
|
|
|
StartMinimized=true; |
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
|
if(argv[i]=="-lock"){ |
|
|
|
|
StartLocked=true; |
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
|
Error=QString("** Unrecognized argument: '%1'").arg(argv[i]); |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
return true;
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void showErrMsg(const QString& msg,QWidget* parent){ |
|
|
|
|
QMessageBox::critical(parent,QApplication::translate("Main","Error"),msg,QApplication::translate("Main","OK")); |
|
|
|
|
void CmdLineArgs::printHelp(){ |
|
|
|
|
cout << "KeePassX" << APP_VERSION << endl; |
|
|
|
|
cout << "Usage: keepassx [Filename] [Options]" << endl; |
|
|
|
|
cout << " -help This Help" << endl; |
|
|
|
|
cout << " -cfg <CONFIG> Use specified file for loading/saving the configuration." << endl; |
|
|
|
|
cout << " -min Start minimized." << endl; |
|
|
|
|
cout << " -lock Start locked." << endl; |
|
|
|
|
cout << " -lang <LOCALE> Use specified language instead of systems default." << endl; |
|
|
|
|
cout << " <LOCALE> is the ISO-639 language code with or without ISO-3166 country code" << endl; |
|
|
|
|
cout << " Examples: de German" << endl; |
|
|
|
|
cout << " de_CH German(Switzerland)"<<endl; |
|
|
|
|
cout << " pt_BR Portuguese(Brazil)"<<endl; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//TODO Plugins
|
|
|
|
|
/*
|
|
|
|
|
QString findPlugin(const QString& filename){ |
|
|
|
@ -474,106 +309,7 @@ QString findPlugin(const QString& filename){ |
|
|
|
|
} |
|
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
QString makePathRelative(const QString& AbsDir,const QString& CurDir){ |
|
|
|
|
QStringList abs=AbsDir.split('/'); |
|
|
|
|
QStringList cur=CurDir.split('/'); |
|
|
|
|
QString rel="./"; |
|
|
|
|
int common; |
|
|
|
|
for(common=0; common < abs.size() && common < cur.size(); common++){ |
|
|
|
|
if(abs[common]!=cur[common])break; |
|
|
|
|
} |
|
|
|
|
for(int i=0;i<cur.size()-common;i++) |
|
|
|
|
rel.append("../"); |
|
|
|
|
for(int i=common;i<abs.size();i++) |
|
|
|
|
rel.append(abs[i]+"/"); |
|
|
|
|
return rel; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
QString applicationDirPath(){ |
|
|
|
|
QString filepath=applicationFilePath(); |
|
|
|
|
filepath.truncate(filepath.lastIndexOf("/")); |
|
|
|
|
return filepath; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
QString applicationFilePath() |
|
|
|
|
{ |
|
|
|
|
#if defined( Q_WS_WIN ) |
|
|
|
|
QFileInfo filePath; |
|
|
|
|
QT_WA({ |
|
|
|
|
wchar_t module_name[256]; |
|
|
|
|
GetModuleFileNameW(0, module_name, sizeof(module_name) / sizeof(wchar_t)); |
|
|
|
|
filePath = QString::fromUtf16((ushort *)module_name); |
|
|
|
|
}, { |
|
|
|
|
char module_name[256]; |
|
|
|
|
GetModuleFileNameA(0, module_name, sizeof(module_name)); |
|
|
|
|
filePath = QString::fromLocal8Bit(module_name); |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
return filePath.filePath(); |
|
|
|
|
|
|
|
|
|
#elif defined(Q_WS_MAC) |
|
|
|
|
|
|
|
|
|
CFURLRef bundleURL(CFBundleCopyExecutableURL(CFBundleGetMainBundle())); |
|
|
|
|
//assert(bundleURL);
|
|
|
|
|
CFStringRef cfPath(CFURLCopyFileSystemPath(bundleURL, kCFURLPOSIXPathStyle)); |
|
|
|
|
//assert(cfPath);
|
|
|
|
|
CFIndex length = CFStringGetLength(cfPath); |
|
|
|
|
const UniChar *chars = CFStringGetCharactersPtr(cfPath); |
|
|
|
|
if (chars) |
|
|
|
|
return QString(reinterpret_cast<const QChar *>(chars), length); |
|
|
|
|
|
|
|
|
|
QVarLengthArray<UniChar> buffer(length); |
|
|
|
|
CFStringGetCharacters(cfPath, CFRangeMake(0, length), buffer.data()); |
|
|
|
|
return QString(reinterpret_cast<const QChar *>(buffer.constData()), length); |
|
|
|
|
|
|
|
|
|
#elif defined( Q_OS_UNIX ) |
|
|
|
|
#ifdef Q_OS_LINUX |
|
|
|
|
// Try looking for a /proc/<pid>/exe symlink first which points to
|
|
|
|
|
// the absolute path of the executable
|
|
|
|
|
QFileInfo pfi(QString::fromLatin1("/proc/%1/exe").arg(getpid())); |
|
|
|
|
if (pfi.exists() && pfi.isSymLink()) |
|
|
|
|
return pfi.canonicalFilePath(); |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
QString argv0 = QFile::decodeName(QByteArray(argv[0])); |
|
|
|
|
QString absPath; |
|
|
|
|
|
|
|
|
|
if (!argv0.isEmpty() && argv0.at(0) == QLatin1Char('/')) { |
|
|
|
|
/*
|
|
|
|
|
If argv0 starts with a slash, it is already an absolute |
|
|
|
|
file path. |
|
|
|
|
*/ |
|
|
|
|
absPath = argv0; |
|
|
|
|
} else if (argv0.contains(QLatin1Char('/'))) { |
|
|
|
|
/*
|
|
|
|
|
If argv0 contains one or more slashes, it is a file path |
|
|
|
|
relative to the current directory. |
|
|
|
|
*/ |
|
|
|
|
absPath = QDir::current().absoluteFilePath(argv0); |
|
|
|
|
} else { |
|
|
|
|
/*
|
|
|
|
|
Otherwise, the file path has to be determined using the |
|
|
|
|
PATH environment variable. |
|
|
|
|
*/ |
|
|
|
|
QByteArray pEnv = qgetenv("PATH"); |
|
|
|
|
QDir currentDir = QDir::current(); |
|
|
|
|
QStringList paths = QString::fromLocal8Bit(pEnv.constData()).split(QLatin1String(":")); |
|
|
|
|
for (QStringList::const_iterator p = paths.constBegin(); p != paths.constEnd(); ++p) { |
|
|
|
|
if ((*p).isEmpty()) |
|
|
|
|
continue; |
|
|
|
|
QString candidate = currentDir.absoluteFilePath(*p + QLatin1Char('/') + argv0); |
|
|
|
|
QFileInfo candidate_fi(candidate); |
|
|
|
|
if (candidate_fi.exists() && !candidate_fi.isDir()) { |
|
|
|
|
absPath = candidate; |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
absPath = QDir::cleanPath(absPath); |
|
|
|
|
|
|
|
|
|
QFileInfo fi(absPath); |
|
|
|
|
return fi.exists() ? fi.canonicalFilePath() : QString(); |
|
|
|
|
#endif |
|
|
|
|
} |
|
|
|
|