1 /***************************************************************************
2 * Copyright (C) 2005-08 by the Quassel IRC Team *
3 * devel@quassel-irc.org *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) version 3. *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the *
17 * Free Software Foundation, Inc., *
18 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
19 ***************************************************************************/
25 #include <QCoreApplication>
33 #include "bufferinfo.h"
35 #include "syncableobject.h"
37 #if defined(HAVE_EXECINFO) and not defined(Q_OS_MAC)
38 # include <execinfo.h>
43 Quassel::BuildInfo Quassel::_buildInfo;
44 CliParser *Quassel::_cliParser = 0;
45 Quassel::RunMode Quassel::_runMode;
46 bool Quassel::_initialized = false;
47 bool Quassel::DEBUG = false;
50 // We catch SIGTERM and SIGINT (caused by Ctrl+C) to graceful shutdown Quassel.
51 signal(SIGTERM, handleSignal);
52 signal(SIGINT, handleSignal);
54 #if defined(HAVE_EXECINFO) and not defined(Q_OS_MAC)
55 signal(SIGABRT, handleSignal);
56 signal(SIGBUS, handleSignal);
57 signal(SIGSEGV, handleSignal);
58 #endif // #if defined(HAVE_EXECINFO) and not defined(Q_OS_MAC)
60 _cliParser = new CliParser();
62 // put shared client&core arguments here
63 cliParser()->addSwitch("debug",'d', tr("Enable debug output"));
64 cliParser()->addSwitch("help",'h', tr("Display this help and exit"));
71 bool Quassel::init() {
72 if(_initialized) return true; // allow multiple invocations because of MonolithicApplication
74 qsrand(QTime(0,0,0).secsTo(QTime::currentTime()));
78 Global::setupVersion();
81 QCoreApplication::setApplicationName(buildInfo().applicationName);
82 QCoreApplication::setOrganizationName(buildInfo().organizationName);
83 QCoreApplication::setOrganizationDomain(buildInfo().organizationDomain);
85 Network::setDefaultCodecForServer("ISO-8859-1");
86 Network::setDefaultCodecForEncoding("UTF-8");
87 Network::setDefaultCodecForDecoding("ISO-8859-15");
89 if(!cliParser()->parse(QCoreApplication::arguments()) || isOptionSet("help")) {
93 DEBUG = isOptionSet("debug");
97 //! Register our custom types with Qt's Meta Object System.
98 /** This makes them available for QVariant and in signals/slots, among other things.
101 void Quassel::registerMetaTypes() {
103 qRegisterMetaType<QVariant>("QVariant");
104 qRegisterMetaType<Message>("Message");
105 qRegisterMetaType<BufferInfo>("BufferInfo");
106 qRegisterMetaType<NetworkInfo>("NetworkInfo");
107 qRegisterMetaType<Identity>("Identity");
108 qRegisterMetaType<Network::ConnectionState>("Network::ConnectionState");
110 qRegisterMetaTypeStreamOperators<QVariant>("QVariant");
111 qRegisterMetaTypeStreamOperators<Message>("Message");
112 qRegisterMetaTypeStreamOperators<BufferInfo>("BufferInfo");
113 qRegisterMetaTypeStreamOperators<NetworkInfo>("NetworkInfo");
114 qRegisterMetaTypeStreamOperators<Identity>("Identity");
115 qRegisterMetaTypeStreamOperators<qint8>("Network::ConnectionState");
117 qRegisterMetaType<IdentityId>("IdentityId");
118 qRegisterMetaType<BufferId>("BufferId");
119 qRegisterMetaType<NetworkId>("NetworkId");
120 qRegisterMetaType<UserId>("UserId");
121 qRegisterMetaType<AccountId>("AccountId");
122 qRegisterMetaType<MsgId>("MsgId");
124 qRegisterMetaTypeStreamOperators<IdentityId>("IdentityId");
125 qRegisterMetaTypeStreamOperators<BufferId>("BufferId");
126 qRegisterMetaTypeStreamOperators<NetworkId>("NetworkId");
127 qRegisterMetaTypeStreamOperators<UserId>("UserId");
128 qRegisterMetaTypeStreamOperators<AccountId>("AccountId");
129 qRegisterMetaTypeStreamOperators<MsgId>("MsgId");
132 void Quassel::setupTranslations() {
133 // Set up i18n support
134 QLocale locale = QLocale::system();
136 QTranslator *qtTranslator = new QTranslator(qApp);
137 qtTranslator->setObjectName("QtTr");
138 qtTranslator->load(QString(":i18n/qt_%1").arg(locale.name()));
139 qApp->installTranslator(qtTranslator);
141 QTranslator *quasselTranslator = new QTranslator(qApp);
142 quasselTranslator->setObjectName("QuasselTr");
143 quasselTranslator->load(QString(":i18n/quassel_%1").arg(locale.name()));
144 qApp->installTranslator(quasselTranslator);
147 void Quassel::setupBuildInfo() {
148 _buildInfo.applicationName = "Quassel IRC";
149 _buildInfo.coreApplicationName = "Quassel Core";
150 _buildInfo.clientApplicationName = "Quassel Client";
151 _buildInfo.organizationName = "Quassel Project";
152 _buildInfo.organizationDomain = "quassel-irc.org";
154 # include "version.inc"
155 # include "version.gen"
157 if(quasselGeneratedVersion.isEmpty()) {
158 if(quasselCommit.isEmpty())
159 quasselVersion = QString("v%1 (unknown rev)").arg(quasselBaseVersion);
161 quasselVersion = QString("v%1 (dist-%2, %3)").arg(quasselBaseVersion).arg(quasselCommit.left(7))
162 .arg(QDateTime::fromTime_t(quasselArchiveDate).toLocalTime().toString("yyyy-MM-dd"));
164 QStringList parts = quasselGeneratedVersion.split(':');
165 quasselVersion = QString("v%1").arg(parts[0]);
166 if(parts.count() >= 2) quasselVersion.append(QString(" (%1)").arg(parts[1]));
168 quasselBuildDate = __DATE__;
169 quasselBuildTime = __TIME__;
173 //! Signal handler for graceful shutdown.
174 void Quassel::handleSignal(int sig) {
178 qWarning("%s", qPrintable(QString("Caught signal %1 - exiting.").arg(sig)));
179 QCoreApplication::quit();
192 void Quassel::handleCrash() {
193 #if defined(HAVE_EXECINFO) and not defined(Q_OS_MAC)
194 void* callstack[128];
195 int i, frames = backtrace(callstack, 128);
197 QFile dumpFile(QString("Quassel-Crash-%1").arg(QDateTime::currentDateTime().toString("yyyyMMdd-hhmm.log")));
198 dumpFile.open(QIODevice::WriteOnly);
199 QTextStream dumpStream(&dumpFile);
201 for (i = 0; i < frames; ++i) {
203 dladdr (callstack[i], &info);
207 // __const char *dli_fname; /* File name of defining object. */
208 // void *dli_fbase; /* Load address of that object. */
209 // __const char *dli_sname; /* Name of nearest symbol. */
210 // void *dli_saddr; /* Exact value of nearest symbol. */
221 char *func = abi::__cxa_demangle(info.dli_sname, 0, 0, 0);
223 funcName = QString(func);
226 funcName = QString(info.dli_sname);
229 funcName = QString("0x%1").arg((long)info.dli_saddr, addrSize, QLatin1Char('0'));
232 // prettificating the filename
233 QString fileName("???");
235 fileName = QString(info.dli_fname);
236 int slashPos = fileName.lastIndexOf('/');
238 fileName = fileName.mid(slashPos + 1);
239 if(fileName.count() < 20)
240 fileName += QString(20 - fileName.count(), ' ');
243 QString debugLine = QString("#%1 %2 0x%3 %4").arg(i, 3, 10)
245 .arg((long)(callstack[i]), addrSize, 16, QLatin1Char('0'))
248 dumpStream << debugLine << "\n";
249 qDebug() << qPrintable(debugLine);
253 #endif // #if defined(HAVE_EXECINFO) and not defined(Q_OS_MAC)
258 void Global::setupVersion() {
260 # include "version.inc"
261 # include "version.gen"
263 if(quasselGeneratedVersion.isEmpty()) {
264 if(quasselCommit.isEmpty())
265 quasselVersion = QString("v%1 (unknown rev)").arg(quasselBaseVersion);
267 quasselVersion = QString("v%1 (dist-%2, %3)").arg(quasselBaseVersion).arg(quasselCommit.left(7))
268 .arg(QDateTime::fromTime_t(quasselArchiveDate).toLocalTime().toString("yyyy-MM-dd"));
270 QStringList parts = quasselGeneratedVersion.split(':');
271 quasselVersion = QString("v%1").arg(parts[0]);
272 if(parts.count() >= 2) quasselVersion.append(QString(" (%1)").arg(parts[1]));
274 quasselBuildDate = __DATE__;
275 quasselBuildTime = __TIME__;
278 QString Global::quasselVersion;
279 QString Global::quasselBaseVersion;
280 QString Global::quasselGeneratedVersion;
281 QString Global::quasselBuildDate;
282 QString Global::quasselBuildTime;
283 QString Global::quasselCommit;
284 uint Global::quasselArchiveDate;
285 uint Global::protocolVersion;
286 uint Global::clientNeedsProtocol;
287 uint Global::coreNeedsProtocol;