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 # define BUILD_CRASHHANDLER
39 # include <execinfo.h>
44 Quassel::BuildInfo Quassel::_buildInfo;
45 CliParser *Quassel::_cliParser = 0;
46 Quassel::RunMode Quassel::_runMode;
47 bool Quassel::_initialized = false;
48 bool Quassel::DEBUG = false;
51 // We catch SIGTERM and SIGINT (caused by Ctrl+C) to graceful shutdown Quassel.
52 signal(SIGTERM, handleSignal);
53 signal(SIGINT, handleSignal);
55 #ifdef BUILD_CRASHHANDLER
56 signal(SIGABRT, handleSignal);
57 signal(SIGBUS, handleSignal);
58 signal(SIGSEGV, handleSignal);
59 #endif // #if defined(HAVE_EXECINFO) and not defined(Q_OS_MAC)
61 _cliParser = new CliParser();
63 // put shared client&core arguments here
64 cliParser()->addSwitch("debug",'d', tr("Enable debug output"));
65 cliParser()->addSwitch("help",'h', tr("Display this help and exit"));
72 bool Quassel::init() {
73 if(_initialized) return true; // allow multiple invocations because of MonolithicApplication
75 qsrand(QTime(0,0,0).secsTo(QTime::currentTime()));
79 Global::setupVersion();
82 QCoreApplication::setApplicationName(buildInfo().applicationName);
83 QCoreApplication::setOrganizationName(buildInfo().organizationName);
84 QCoreApplication::setOrganizationDomain(buildInfo().organizationDomain);
86 Network::setDefaultCodecForServer("ISO-8859-1");
87 Network::setDefaultCodecForEncoding("UTF-8");
88 Network::setDefaultCodecForDecoding("ISO-8859-15");
90 if(!cliParser()->parse(QCoreApplication::arguments()) || isOptionSet("help")) {
94 DEBUG = isOptionSet("debug");
98 //! Register our custom types with Qt's Meta Object System.
99 /** This makes them available for QVariant and in signals/slots, among other things.
102 void Quassel::registerMetaTypes() {
104 qRegisterMetaType<QVariant>("QVariant");
105 qRegisterMetaType<Message>("Message");
106 qRegisterMetaType<BufferInfo>("BufferInfo");
107 qRegisterMetaType<NetworkInfo>("NetworkInfo");
108 qRegisterMetaType<Identity>("Identity");
109 qRegisterMetaType<Network::ConnectionState>("Network::ConnectionState");
111 qRegisterMetaTypeStreamOperators<QVariant>("QVariant");
112 qRegisterMetaTypeStreamOperators<Message>("Message");
113 qRegisterMetaTypeStreamOperators<BufferInfo>("BufferInfo");
114 qRegisterMetaTypeStreamOperators<NetworkInfo>("NetworkInfo");
115 qRegisterMetaTypeStreamOperators<Identity>("Identity");
116 qRegisterMetaTypeStreamOperators<qint8>("Network::ConnectionState");
118 qRegisterMetaType<IdentityId>("IdentityId");
119 qRegisterMetaType<BufferId>("BufferId");
120 qRegisterMetaType<NetworkId>("NetworkId");
121 qRegisterMetaType<UserId>("UserId");
122 qRegisterMetaType<AccountId>("AccountId");
123 qRegisterMetaType<MsgId>("MsgId");
125 qRegisterMetaTypeStreamOperators<IdentityId>("IdentityId");
126 qRegisterMetaTypeStreamOperators<BufferId>("BufferId");
127 qRegisterMetaTypeStreamOperators<NetworkId>("NetworkId");
128 qRegisterMetaTypeStreamOperators<UserId>("UserId");
129 qRegisterMetaTypeStreamOperators<AccountId>("AccountId");
130 qRegisterMetaTypeStreamOperators<MsgId>("MsgId");
133 void Quassel::setupTranslations() {
134 // Set up i18n support
135 QLocale locale = QLocale::system();
137 QTranslator *qtTranslator = new QTranslator(qApp);
138 qtTranslator->setObjectName("QtTr");
139 qtTranslator->load(QString(":i18n/qt_%1").arg(locale.name()));
140 qApp->installTranslator(qtTranslator);
142 QTranslator *quasselTranslator = new QTranslator(qApp);
143 quasselTranslator->setObjectName("QuasselTr");
144 quasselTranslator->load(QString(":i18n/quassel_%1").arg(locale.name()));
145 qApp->installTranslator(quasselTranslator);
148 void Quassel::setupBuildInfo() {
149 _buildInfo.applicationName = "Quassel IRC";
150 _buildInfo.coreApplicationName = "Quassel Core";
151 _buildInfo.clientApplicationName = "Quassel Client";
152 _buildInfo.organizationName = "Quassel Project";
153 _buildInfo.organizationDomain = "quassel-irc.org";
155 # include "version.inc"
156 # include "version.gen"
158 if(quasselGeneratedVersion.isEmpty()) {
159 if(quasselCommit.isEmpty())
160 quasselVersion = QString("v%1 (unknown rev)").arg(quasselBaseVersion);
162 quasselVersion = QString("v%1 (dist-%2, %3)").arg(quasselBaseVersion).arg(quasselCommit.left(7))
163 .arg(QDateTime::fromTime_t(quasselArchiveDate).toLocalTime().toString("yyyy-MM-dd"));
165 QStringList parts = quasselGeneratedVersion.split(':');
166 quasselVersion = QString("v%1").arg(parts[0]);
167 if(parts.count() >= 2) quasselVersion.append(QString(" (%1)").arg(parts[1]));
169 quasselBuildDate = __DATE__;
170 quasselBuildTime = __TIME__;
174 //! Signal handler for graceful shutdown.
175 void Quassel::handleSignal(int sig) {
179 qWarning("%s", qPrintable(QString("Caught signal %1 - exiting.").arg(sig)));
180 QCoreApplication::quit();
183 #ifdef BUILD_CRASHHANDLER
195 void Quassel::handleCrash() {
196 #ifdef BUILD_CRASHHANDLER
197 void* callstack[128];
198 int i, frames = backtrace(callstack, 128);
200 QFile dumpFile(QString("Quassel-Crash-%1").arg(QDateTime::currentDateTime().toString("yyyyMMdd-hhmm.log")));
201 dumpFile.open(QIODevice::WriteOnly);
202 QTextStream dumpStream(&dumpFile);
204 for (i = 0; i < frames; ++i) {
206 dladdr (callstack[i], &info);
210 // __const char *dli_fname; /* File name of defining object. */
211 // void *dli_fbase; /* Load address of that object. */
212 // __const char *dli_sname; /* Name of nearest symbol. */
213 // void *dli_saddr; /* Exact value of nearest symbol. */
224 char *func = abi::__cxa_demangle(info.dli_sname, 0, 0, 0);
226 funcName = QString(func);
229 funcName = QString(info.dli_sname);
232 funcName = QString("0x%1").arg((long)info.dli_saddr, addrSize, QLatin1Char('0'));
235 // prettificating the filename
236 QString fileName("???");
238 fileName = QString(info.dli_fname);
239 int slashPos = fileName.lastIndexOf('/');
241 fileName = fileName.mid(slashPos + 1);
242 if(fileName.count() < 20)
243 fileName += QString(20 - fileName.count(), ' ');
246 QString debugLine = QString("#%1 %2 0x%3 %4").arg(i, 3, 10)
248 .arg((long)(callstack[i]), addrSize, 16, QLatin1Char('0'))
251 dumpStream << debugLine << "\n";
252 qDebug() << qPrintable(debugLine);
256 #endif /* BUILD_CRASHHANDLER */
261 void Global::setupVersion() {
263 # include "version.inc"
264 # include "version.gen"
266 if(quasselGeneratedVersion.isEmpty()) {
267 if(quasselCommit.isEmpty())
268 quasselVersion = QString("v%1 (unknown rev)").arg(quasselBaseVersion);
270 quasselVersion = QString("v%1 (dist-%2, %3)").arg(quasselBaseVersion).arg(quasselCommit.left(7))
271 .arg(QDateTime::fromTime_t(quasselArchiveDate).toLocalTime().toString("yyyy-MM-dd"));
273 QStringList parts = quasselGeneratedVersion.split(':');
274 quasselVersion = QString("v%1").arg(parts[0]);
275 if(parts.count() >= 2) quasselVersion.append(QString(" (%1)").arg(parts[1]));
277 quasselBuildDate = __DATE__;
278 quasselBuildTime = __TIME__;
281 QString Global::quasselVersion;
282 QString Global::quasselBaseVersion;
283 QString Global::quasselGeneratedVersion;
284 QString Global::quasselBuildDate;
285 QString Global::quasselBuildTime;
286 QString Global::quasselCommit;
287 uint Global::quasselArchiveDate;
288 uint Global::protocolVersion;
289 uint Global::clientNeedsProtocol;
290 uint Global::coreNeedsProtocol;