X-Git-Url: https://git.quassel-irc.org/?p=quassel.git;a=blobdiff_plain;f=src%2Fcommon%2Fquassel.cpp;h=eb854b30e01da5c41b6a171622ac251fb25bbafe;hp=33b6cbd4c9bc2267df6441ac44a3aca8a16841a6;hb=8a0b44b52a6a0a855a832fa7b46f3631a8684a3f;hpb=0a1c1ff4f99a7eb53ff6cdd95ce5d7ac263e77d2 diff --git a/src/common/quassel.cpp b/src/common/quassel.cpp index 33b6cbd4..eb854b30 100644 --- a/src/common/quassel.cpp +++ b/src/common/quassel.cpp @@ -32,6 +32,7 @@ #include #include #include +#include #include "message.h" #include "identity.h" @@ -49,35 +50,26 @@ QStringList Quassel::_dataDirPaths; bool Quassel::_initialized = false; bool Quassel::DEBUG = false; QString Quassel::_coreDumpFileName; +Quassel *Quassel::_instance = 0; +bool Quassel::_handleCrashes = true; +Quassel::LogLevel Quassel::_logLevel = InfoLevel; +QFile *Quassel::_logFile = 0; +bool Quassel::_logToSyslog = false; Quassel::Quassel() { + Q_ASSERT(!_instance); + _instance = this; + // We catch SIGTERM and SIGINT (caused by Ctrl+C) to graceful shutdown Quassel. signal(SIGTERM, handleSignal); signal(SIGINT, handleSignal); - - // 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)) - -# ifndef Q_OS_WIN32 - // we only handle crashes ourselves if coredumps are disabled - struct rlimit *limit = (rlimit *) malloc(sizeof(struct rlimit)); - int rc = getrlimit(RLIMIT_CORE, limit); - - if(rc == -1 || !((long)limit->rlim_cur > 0 || limit->rlim_cur == RLIM_INFINITY)) { -# endif - signal(SIGABRT, handleSignal); - signal(SIGSEGV, handleSignal); -# ifndef Q_OS_WIN32 - signal(SIGBUS, handleSignal); - } - free(limit); -# endif - -#endif } Quassel::~Quassel() { + if(logFile()) { + logFile()->close(); + logFile()->deleteLater(); + } delete _cliParser; } @@ -85,6 +77,26 @@ bool Quassel::init() { if(_initialized) return true; // allow multiple invocations because of MonolithicApplication + if (_handleCrashes) { + // we have crashhandler for win32 and unix (based on execinfo). +#if defined(Q_OS_WIN32) || defined(HAVE_EXECINFO) +# ifndef Q_OS_WIN32 + // we only handle crashes ourselves if coredumps are disabled + struct rlimit *limit = (rlimit *) malloc(sizeof(struct rlimit)); + int rc = getrlimit(RLIMIT_CORE, limit); + + if(rc == -1 || !((long)limit->rlim_cur > 0 || limit->rlim_cur == RLIM_INFINITY)) { +# endif /* Q_OS_WIN32 */ + signal(SIGABRT, handleSignal); + signal(SIGSEGV, handleSignal); +# ifndef Q_OS_WIN32 + signal(SIGBUS, handleSignal); + } + free(limit); +# endif /* Q_OS_WIN32 */ +#endif /* Q_OS_WIN32 || HAVE_EXECINFO */ + } + _initialized = true; qsrand(QTime(0,0,0).secsTo(QTime::currentTime())); @@ -105,30 +117,56 @@ bool Quassel::init() { } DEBUG = isOptionSet("debug"); + + // set up logging + if(Quassel::runMode() != Quassel::ClientOnly) { + if(isOptionSet("loglevel")) { + QString level = optionValue("loglevel"); + + if(level == "Debug") _logLevel = DebugLevel; + else if(level == "Info") _logLevel = InfoLevel; + else if(level == "Warning") _logLevel= WarningLevel; + else if(level == "Error") _logLevel = ErrorLevel; + } + + QString logfilename = optionValue("logfile"); + if(!logfilename.isEmpty()) { + _logFile = new QFile(logfilename); + if(!_logFile->open(QIODevice::Append | QIODevice::Text)) { + qWarning() << "Could not open log file" << logfilename << ":" << _logFile->errorString(); + _logFile->deleteLater(); + _logFile = 0; + } + } +#ifdef HAVE_SYSLOG + _logToSyslog = isOptionSet("syslog"); +#endif + } + return true; } +void Quassel::quit() { + QCoreApplication::quit(); +} + //! Register our custom types with Qt's Meta Object System. /** This makes them available for QVariant and in signals/slots, among other things. * */ void Quassel::registerMetaTypes() { // Complex types - qRegisterMetaType("QVariant"); qRegisterMetaType("Message"); qRegisterMetaType("BufferInfo"); qRegisterMetaType("NetworkInfo"); qRegisterMetaType("Network::Server"); qRegisterMetaType("Identity"); - qRegisterMetaType("Network::ConnectionState"); - qRegisterMetaTypeStreamOperators("QVariant"); qRegisterMetaTypeStreamOperators("Message"); qRegisterMetaTypeStreamOperators("BufferInfo"); qRegisterMetaTypeStreamOperators("NetworkInfo"); qRegisterMetaTypeStreamOperators("Network::Server"); qRegisterMetaTypeStreamOperators("Identity"); - qRegisterMetaTypeStreamOperators("Network::ConnectionState"); qRegisterMetaType("IdentityId"); qRegisterMetaType("BufferId"); @@ -137,12 +175,20 @@ void Quassel::registerMetaTypes() { qRegisterMetaType("AccountId"); qRegisterMetaType("MsgId"); + qRegisterMetaType("QHostAddress"); + qRegisterMetaTypeStreamOperators("IdentityId"); qRegisterMetaTypeStreamOperators("BufferId"); qRegisterMetaTypeStreamOperators("NetworkId"); qRegisterMetaTypeStreamOperators("UserId"); qRegisterMetaTypeStreamOperators("AccountId"); qRegisterMetaTypeStreamOperators("MsgId"); + + // Versions of Qt prior to 4.7 didn't define QVariant as a meta type + if(!QMetaType::type("QVariant")) { + qRegisterMetaType("QVariant"); + qRegisterMetaTypeStreamOperators("QVariant"); + } } void Quassel::setupBuildInfo(const QString &generated) { @@ -170,8 +216,7 @@ void Quassel::setupBuildInfo(const QString &generated) { _buildInfo.plainVersionString = QString("v%1 (dist-%2)") .arg(_buildInfo.baseVersion) .arg(_buildInfo.commitHash.left(7)); - _buildInfo.fancyVersionString - = QString("v%1 (dist-%2)") + _buildInfo.fancyVersionString = QString("v%1 (dist-%2)") .arg(_buildInfo.baseVersion) .arg(_buildInfo.commitHash.left(7)) .arg(_buildInfo.commitHash); @@ -183,13 +228,13 @@ void Quassel::setupBuildInfo(const QString &generated) { // analyze what we got from git-describe QRegExp rx("(.*)-(\\d+)-g([0-9a-f]+)$"); if(rx.exactMatch(_buildInfo.generatedVersion)) { - QString distance = rx.cap(2) == "0" ? QString() : QString(" [+%1]").arg(rx.cap(2)); - _buildInfo.plainVersionString = QString("v%1%2 (git-%3%4)") - .arg(rx.cap(1), distance, rx.cap(3)) + QString distance = rx.cap(2) == "0" ? QString() : QString("%1+%2 ").arg(rx.cap(1), rx.cap(2)); + _buildInfo.plainVersionString = QString("v%1 (%2git-%3%4)") + .arg(_buildInfo.baseVersion, distance, rx.cap(3)) .arg(_buildInfo.isSourceDirty ? "*" : ""); if(!_buildInfo.commitHash.isEmpty()) { - _buildInfo.fancyVersionString = QString("v%1%2 (git-%3%4)") - .arg(rx.cap(1), distance, rx.cap(3)) + _buildInfo.fancyVersionString = QString("v%1 (%2git-%3%4)") + .arg(_buildInfo.baseVersion, distance, rx.cap(3)) .arg(_buildInfo.isSourceDirty ? "*" : "") .arg(_buildInfo.commitHash); } @@ -207,7 +252,10 @@ void Quassel::handleSignal(int sig) { case SIGTERM: case SIGINT: qWarning("%s", qPrintable(QString("Caught signal %1 - exiting.").arg(sig))); - QCoreApplication::quit(); + if(_instance) + _instance->quit(); + else + QCoreApplication::quit(); break; case SIGABRT: case SIGSEGV: @@ -236,6 +284,14 @@ void Quassel::logFatalMessage(const char *msg) { #endif } +Quassel::Features Quassel::features() { + Features feats = 0; + for(int i = 1; i <= NumFeatures; i<<=1) + feats |= (Feature) i; + + return feats; +} + const QString &Quassel::coreDumpFileName() { if(_coreDumpFileName.isEmpty()) { QDir configDir(configDirPath()); @@ -383,24 +439,27 @@ void Quassel::loadTranslation(const QLocale &locale) { QTranslator *qtTranslator = QCoreApplication::instance()->findChild("QtTr"); QTranslator *quasselTranslator = QCoreApplication::instance()->findChild("QuasselTr"); - if(!qtTranslator) { - qtTranslator = new QTranslator(qApp); - qtTranslator->setObjectName("QtTr"); - qApp->installTranslator(qtTranslator); - } - if(!quasselTranslator) { - quasselTranslator = new QTranslator(qApp); - quasselTranslator->setObjectName("QuasselTr"); - qApp->installTranslator(quasselTranslator); - } - - QLocale::setDefault(locale); + if(qtTranslator) + qApp->removeTranslator(qtTranslator); + if(quasselTranslator) + qApp->removeTranslator(quasselTranslator); + // We use QLocale::C to indicate that we don't want a translation if(locale.language() == QLocale::C) return; + qtTranslator = new QTranslator(qApp); + qtTranslator->setObjectName("QtTr"); + qApp->installTranslator(qtTranslator); + + quasselTranslator = new QTranslator(qApp); + quasselTranslator->setObjectName("QuasselTr"); + qApp->installTranslator(quasselTranslator); + + QLocale::setDefault(locale); + bool success = qtTranslator->load(QString("qt_%1").arg(locale.name()), translationDirPath()); if(!success) qtTranslator->load(QString("qt_%1").arg(locale.name()), QLibraryInfo::location(QLibraryInfo::TranslationsPath)); - quasselTranslator->load(QString("quassel_%1").arg(locale.name()), translationDirPath()); + quasselTranslator->load(QString("%1").arg(locale.name()), translationDirPath()); }