X-Git-Url: https://git.quassel-irc.org/?p=quassel.git;a=blobdiff_plain;f=src%2Fcommon%2Fquassel.cpp;h=bd31929afd550ef6027e887a76b2c1ed583e5f18;hp=d06aa28973b166ad5a87ffed3618957cb3ee1778;hb=cd37744f0a2cd8ffe027892ddce5c7d6f4848ab0;hpb=fe73542fbcd2129069890ffe107639eaf26b1066 diff --git a/src/common/quassel.cpp b/src/common/quassel.cpp index d06aa289..bd31929a 100644 --- a/src/common/quassel.cpp +++ b/src/common/quassel.cpp @@ -1,5 +1,5 @@ /*************************************************************************** - * Copyright (C) 2005-08 by the Quassel IRC Team * + * Copyright (C) 2005-09 by the Quassel Project * * devel@quassel-irc.org * * * * This program is free software; you can redistribute it and/or modify * @@ -34,38 +34,30 @@ #include "types.h" #include "syncableobject.h" -#if defined(HAVE_EXECINFO) && !defined(Q_OS_MAC) -# define BUILD_CRASHHANDLER -# include -# include -# include -#endif - Quassel::BuildInfo Quassel::_buildInfo; -CliParser *Quassel::_cliParser = 0; +AbstractCliParser *Quassel::_cliParser = 0; Quassel::RunMode Quassel::_runMode; +QString Quassel::_configDirPath; +QStringList Quassel::_dataDirPaths; bool Quassel::_initialized = false; bool Quassel::DEBUG = false; QString Quassel::_coreDumpFileName; Quassel::Quassel() { - Q_INIT_RESOURCE(i18n); - // We catch SIGTERM and SIGINT (caused by Ctrl+C) to graceful shutdown Quassel. signal(SIGTERM, handleSignal); signal(SIGINT, handleSignal); -#ifdef BUILD_CRASHHANDLER + // we have crashhandler for win32 and unix (based on execinfo). + // on mac os we use it's integrated backtrace generator +#if defined(Q_OS_WIN32) || (defined(HAVE_EXECINFO) && !defined(Q_OS_MAC)) signal(SIGABRT, handleSignal); - signal(SIGBUS, handleSignal); signal(SIGSEGV, handleSignal); -#endif // #if defined(HAVE_EXECINFO) && !defined(Q_OS_MAC) - - _cliParser = new CliParser(); +# ifndef Q_OS_WIN32 + signal(SIGBUS, handleSignal); +# endif +#endif - // put shared client&core arguments here - cliParser()->addSwitch("debug",'d', tr("Enable debug output")); - cliParser()->addSwitch("help",'h', tr("Display this help and exit")); } Quassel::~Quassel() { @@ -80,20 +72,16 @@ bool Quassel::init() { qsrand(QTime(0,0,0).secsTo(QTime::currentTime())); registerMetaTypes(); - setupTranslations(); - - QCoreApplication::setApplicationName(buildInfo().applicationName); - QCoreApplication::setOrganizationName(buildInfo().organizationName); - QCoreApplication::setOrganizationDomain(buildInfo().organizationDomain); Network::setDefaultCodecForServer("ISO-8859-1"); Network::setDefaultCodecForEncoding("UTF-8"); Network::setDefaultCodecForDecoding("ISO-8859-15"); - if(!cliParser()->parse(QCoreApplication::arguments()) || isOptionSet("help")) { + if(isOptionSet("help")) { cliParser()->usage(); return false; } + DEBUG = isOptionSet("debug"); return true; } @@ -108,6 +96,7 @@ void Quassel::registerMetaTypes() { qRegisterMetaType("Message"); qRegisterMetaType("BufferInfo"); qRegisterMetaType("NetworkInfo"); + qRegisterMetaType("Network::Server"); qRegisterMetaType("Identity"); qRegisterMetaType("Network::ConnectionState"); @@ -115,6 +104,7 @@ void Quassel::registerMetaTypes() { qRegisterMetaTypeStreamOperators("Message"); qRegisterMetaTypeStreamOperators("BufferInfo"); qRegisterMetaTypeStreamOperators("NetworkInfo"); + qRegisterMetaTypeStreamOperators("Network::Server"); qRegisterMetaTypeStreamOperators("Identity"); qRegisterMetaTypeStreamOperators("Network::ConnectionState"); @@ -133,21 +123,6 @@ void Quassel::registerMetaTypes() { qRegisterMetaTypeStreamOperators("MsgId"); } -void Quassel::setupTranslations() { - // Set up i18n support - QLocale locale = QLocale::system(); - - QTranslator *qtTranslator = new QTranslator(qApp); - qtTranslator->setObjectName("QtTr"); - qtTranslator->load(QString(":i18n/qt_%1").arg(locale.name())); - qApp->installTranslator(qtTranslator); - - QTranslator *quasselTranslator = new QTranslator(qApp); - quasselTranslator->setObjectName("QuasselTr"); - quasselTranslator->load(QString(":i18n/quassel_%1").arg(locale.name())); - qApp->installTranslator(quasselTranslator); -} - void Quassel::setupBuildInfo(const QString &generated) { _buildInfo.applicationName = "Quassel IRC"; _buildInfo.coreApplicationName = "Quassel Core"; @@ -207,109 +182,132 @@ void Quassel::setupBuildInfo(const QString &generated) { //! Signal handler for graceful shutdown. void Quassel::handleSignal(int sig) { switch(sig) { - case SIGTERM: - case SIGINT: - qWarning("%s", qPrintable(QString("Caught signal %1 - exiting.").arg(sig))); - QCoreApplication::quit(); - break; - -#ifdef BUILD_CRASHHANDLER - case SIGABRT: - case SIGBUS: - case SIGSEGV: - handleCrash(); + case SIGTERM: + case SIGINT: + qWarning("%s", qPrintable(QString("Caught signal %1 - exiting.").arg(sig))); + QCoreApplication::quit(); + break; + case SIGABRT: + case SIGSEGV: +#ifndef Q_OS_WIN32 + case SIGBUS: #endif - break; - default: - break; + logBacktrace(coreDumpFileName()); + exit(EXIT_FAILURE); + break; + default: + break; } } void Quassel::logFatalMessage(const char *msg) { -#ifndef Q_OS_MAC +#ifdef Q_OS_MAC + Q_UNUSED(msg) +#else QFile dumpFile(coreDumpFileName()); - dumpFile.open(QIODevice::WriteOnly); + dumpFile.open(QIODevice::Append); QTextStream dumpStream(&dumpFile); -#else - QTextStream dumpStream(stderr); -#endif - + dumpStream << "Fatal: " << msg << '\n'; dumpStream.flush(); + dumpFile.close(); +#endif +} - qInstallMsgHandler(0); - abort(); +const QString &Quassel::coreDumpFileName() { + if(_coreDumpFileName.isEmpty()) { + _coreDumpFileName = QString("Quassel-Crash-%1.log").arg(QDateTime::currentDateTime().toString("yyyyMMdd-hhmm")); + QFile dumpFile(_coreDumpFileName); + dumpFile.open(QIODevice::Append); + QTextStream dumpStream(&dumpFile); + dumpStream << "Quassel IRC: " << _buildInfo.baseVersion << ' ' << _buildInfo.commitHash << '\n'; + qDebug() << "Quassel IRC: " << _buildInfo.baseVersion << ' ' << _buildInfo.commitHash; + dumpStream.flush(); + dumpFile.close(); + } + return _coreDumpFileName; } -void Quassel::handleCrash() { -#ifdef BUILD_CRASHHANDLER - void* callstack[128]; - int i, frames = backtrace(callstack, 128); +QString Quassel::configDirPath() { + if(!_configDirPath.isEmpty()) + return _configDirPath; - QFile dumpFile(coreDumpFileName()); - dumpFile.open(QIODevice::Append); - QTextStream dumpStream(&dumpFile); + if(Quassel::isOptionSet("datadir")) { + qWarning() << "Obsolete option --datadir used!"; + _configDirPath = Quassel::optionValue("datadir"); + } else if(Quassel::isOptionSet("configdir")) { + _configDirPath = Quassel::optionValue("configdir"); + } else { - dumpStream << "Quassel IRC: " << _buildInfo.baseVersion << ' ' << _buildInfo.commitHash << '\n'; - - for (i = 0; i < frames; ++i) { - Dl_info info; - dladdr (callstack[i], &info); - // as a reference: - // typedef struct - // { - // __const char *dli_fname; /* File name of defining object. */ - // void *dli_fbase; /* Load address of that object. */ - // __const char *dli_sname; /* Name of nearest symbol. */ - // void *dli_saddr; /* Exact value of nearest symbol. */ - // } Dl_info; - - #if __LP64__ - int addrSize = 16; - #else - int addrSize = 8; - #endif - - QString funcName; - if(info.dli_sname) { - char *func = abi::__cxa_demangle(info.dli_sname, 0, 0, 0); - if(func) { - funcName = QString(func); - free(func); - } else { - funcName = QString(info.dli_sname); - } - } else { - funcName = QString("0x%1").arg((long)info.dli_saddr, addrSize, QLatin1Char('0')); - } + // FIXME use QDesktopServices? +#ifdef Q_OS_WIN32 + _configDirPath = qgetenv("APPDATA") + "/quassel/"; +#elif defined Q_WS_MAC + _configDirPath = QDir::homePath() + "/Library/Application Support/Quassel/"; +#else + _configDirPath = QDir::homePath() + "/.quassel/"; +#endif + } + + if(!_configDirPath.endsWith('/')) + _configDirPath += '/'; - // prettificating the filename - QString fileName("???"); - if(info.dli_fname) { - fileName = QString(info.dli_fname); - int slashPos = fileName.lastIndexOf('/'); - if(slashPos != -1) - fileName = fileName.mid(slashPos + 1); - if(fileName.count() < 20) - fileName += QString(20 - fileName.count(), ' '); + QDir qDir(_configDirPath); + if(!qDir.exists(_configDirPath)) { + if(!qDir.mkpath(_configDirPath)) { + qCritical() << "Unable to create Quassel config directory:" << qPrintable(qDir.absolutePath()); + return QString(); } + } - QString debugLine = QString("#%1 %2 0x%3 %4").arg(i, 3, 10) - .arg(fileName) - .arg((long)(callstack[i]), addrSize, 16, QLatin1Char('0')) - .arg(funcName); + return _configDirPath; +} - dumpStream << debugLine << "\n"; - qDebug() << qPrintable(debugLine); - } - dumpFile.close(); - exit(27); -#endif /* BUILD_CRASHHANDLER */ +QStringList Quassel::dataDirPaths() { + return _dataDirPaths; } -const QString &Quassel::coreDumpFileName() { - if(_coreDumpFileName.isEmpty()) - _coreDumpFileName = QString("Quassel-Crash-%1.log").arg(QDateTime::currentDateTime().toString("yyyyMMdd-hhmm")); +QStringList Quassel::findDataDirPaths() const { + QStringList dataDirNames = QString(qgetenv("XDG_DATA_DIRS")).split(':', QString::SkipEmptyParts); - return _coreDumpFileName; + if(!dataDirNames.isEmpty()) { + for(int i = 0; i < dataDirNames.count(); i++) + dataDirNames[i].append("/apps/quassel/"); + } else { + // Provide a fallback + // FIXME fix this for win and mac! +#ifdef Q_OS_WIN32 + dataDirNames << qgetenv("APPDATA") + "/quassel/" + << QCoreApplication::applicationDirPath(); +#elif defined Q_WS_MAC + dataDirNames << QDir::homePath() + "/Library/Application Support/Quassel/" + << QCoreApplication::applicationDirPath(); +#else + if(dataDirNames.isEmpty()) + dataDirNames.append("/usr/share/apps/quassel/"); + // on UNIX, we always check our install prefix + QString appDir = QCoreApplication::applicationDirPath(); + int binpos = appDir.lastIndexOf("/bin"); + if(binpos >= 0) { + appDir.replace(binpos, 4, "/share"); + appDir.append("/apps/quassel/"); + if(!dataDirNames.contains(appDir)) + dataDirNames.append(appDir); + } +#endif + } + + // add resource path just in case + dataDirNames << ":/data/"; + return dataDirNames; +} + +QString Quassel::findDataFilePath(const QString &fileName) { + QStringList dataDirs = dataDirPaths(); + foreach(QString dataDir, dataDirs) { + QString path = dataDir + fileName; + if(QFile::exists(path)) + return path; + } + return QString(); }