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 Q_INIT_RESOURCE(i18n);
53 // We catch SIGTERM and SIGINT (caused by Ctrl+C) to graceful shutdown Quassel.
54 signal(SIGTERM, handleSignal);
55 signal(SIGINT, handleSignal);
57 #ifdef BUILD_CRASHHANDLER
58 signal(SIGABRT, handleSignal);
59 signal(SIGBUS, handleSignal);
60 signal(SIGSEGV, handleSignal);
61 #endif // #if defined(HAVE_EXECINFO) and not defined(Q_OS_MAC)
63 _cliParser = new CliParser();
65 // put shared client&core arguments here
66 cliParser()->addSwitch("debug",'d', tr("Enable debug output"));
67 cliParser()->addSwitch("help",'h', tr("Display this help and exit"));
74 bool Quassel::init() {
75 if(_initialized) return true; // allow multiple invocations because of MonolithicApplication
77 qsrand(QTime(0,0,0).secsTo(QTime::currentTime()));
81 Global::setupVersion();
84 QCoreApplication::setApplicationName(buildInfo().applicationName);
85 QCoreApplication::setOrganizationName(buildInfo().organizationName);
86 QCoreApplication::setOrganizationDomain(buildInfo().organizationDomain);
88 Network::setDefaultCodecForServer("ISO-8859-1");
89 Network::setDefaultCodecForEncoding("UTF-8");
90 Network::setDefaultCodecForDecoding("ISO-8859-15");
92 if(!cliParser()->parse(QCoreApplication::arguments()) || isOptionSet("help")) {
96 DEBUG = isOptionSet("debug");
100 //! Register our custom types with Qt's Meta Object System.
101 /** This makes them available for QVariant and in signals/slots, among other things.
104 void Quassel::registerMetaTypes() {
106 qRegisterMetaType<QVariant>("QVariant");
107 qRegisterMetaType<Message>("Message");
108 qRegisterMetaType<BufferInfo>("BufferInfo");
109 qRegisterMetaType<NetworkInfo>("NetworkInfo");
110 qRegisterMetaType<Identity>("Identity");
111 qRegisterMetaType<Network::ConnectionState>("Network::ConnectionState");
113 qRegisterMetaTypeStreamOperators<QVariant>("QVariant");
114 qRegisterMetaTypeStreamOperators<Message>("Message");
115 qRegisterMetaTypeStreamOperators<BufferInfo>("BufferInfo");
116 qRegisterMetaTypeStreamOperators<NetworkInfo>("NetworkInfo");
117 qRegisterMetaTypeStreamOperators<Identity>("Identity");
118 qRegisterMetaTypeStreamOperators<qint8>("Network::ConnectionState");
120 qRegisterMetaType<IdentityId>("IdentityId");
121 qRegisterMetaType<BufferId>("BufferId");
122 qRegisterMetaType<NetworkId>("NetworkId");
123 qRegisterMetaType<UserId>("UserId");
124 qRegisterMetaType<AccountId>("AccountId");
125 qRegisterMetaType<MsgId>("MsgId");
127 qRegisterMetaTypeStreamOperators<IdentityId>("IdentityId");
128 qRegisterMetaTypeStreamOperators<BufferId>("BufferId");
129 qRegisterMetaTypeStreamOperators<NetworkId>("NetworkId");
130 qRegisterMetaTypeStreamOperators<UserId>("UserId");
131 qRegisterMetaTypeStreamOperators<AccountId>("AccountId");
132 qRegisterMetaTypeStreamOperators<MsgId>("MsgId");
135 void Quassel::setupTranslations() {
136 // Set up i18n support
137 QLocale locale = QLocale::system();
139 QTranslator *qtTranslator = new QTranslator(qApp);
140 qtTranslator->setObjectName("QtTr");
141 qtTranslator->load(QString(":i18n/qt_%1").arg(locale.name()));
142 qApp->installTranslator(qtTranslator);
144 QTranslator *quasselTranslator = new QTranslator(qApp);
145 quasselTranslator->setObjectName("QuasselTr");
146 quasselTranslator->load(QString(":i18n/quassel_%1").arg(locale.name()));
147 qApp->installTranslator(quasselTranslator);
150 void Quassel::setupBuildInfo() {
151 _buildInfo.applicationName = "Quassel IRC";
152 _buildInfo.coreApplicationName = "Quassel Core";
153 _buildInfo.clientApplicationName = "Quassel Client";
154 _buildInfo.organizationName = "Quassel Project";
155 _buildInfo.organizationDomain = "quassel-irc.org";
157 # include "version.inc"
158 # include "version.gen"
160 if(quasselGeneratedVersion.isEmpty()) {
161 if(quasselCommit.isEmpty())
162 quasselVersion = QString("v%1 (unknown rev)").arg(quasselBaseVersion);
164 quasselVersion = QString("v%1 (dist-%2, %3)").arg(quasselBaseVersion).arg(quasselCommit.left(7))
165 .arg(QDateTime::fromTime_t(quasselArchiveDate).toLocalTime().toString("yyyy-MM-dd"));
167 QStringList parts = quasselGeneratedVersion.split(':');
168 quasselVersion = QString("v%1").arg(parts[0]);
169 if(parts.count() >= 2) quasselVersion.append(QString(" (%1)").arg(parts[1]));
171 quasselBuildDate = __DATE__;
172 quasselBuildTime = __TIME__;
176 //! Signal handler for graceful shutdown.
177 void Quassel::handleSignal(int sig) {
181 qWarning("%s", qPrintable(QString("Caught signal %1 - exiting.").arg(sig)));
182 QCoreApplication::quit();
185 #ifdef BUILD_CRASHHANDLER
197 void Quassel::handleCrash() {
198 #ifdef BUILD_CRASHHANDLER
199 void* callstack[128];
200 int i, frames = backtrace(callstack, 128);
202 QFile dumpFile(QString("Quassel-Crash-%1").arg(QDateTime::currentDateTime().toString("yyyyMMdd-hhmm.log")));
203 dumpFile.open(QIODevice::WriteOnly);
204 QTextStream dumpStream(&dumpFile);
206 for (i = 0; i < frames; ++i) {
208 dladdr (callstack[i], &info);
212 // __const char *dli_fname; /* File name of defining object. */
213 // void *dli_fbase; /* Load address of that object. */
214 // __const char *dli_sname; /* Name of nearest symbol. */
215 // void *dli_saddr; /* Exact value of nearest symbol. */
226 char *func = abi::__cxa_demangle(info.dli_sname, 0, 0, 0);
228 funcName = QString(func);
231 funcName = QString(info.dli_sname);
234 funcName = QString("0x%1").arg((long)info.dli_saddr, addrSize, QLatin1Char('0'));
237 // prettificating the filename
238 QString fileName("???");
240 fileName = QString(info.dli_fname);
241 int slashPos = fileName.lastIndexOf('/');
243 fileName = fileName.mid(slashPos + 1);
244 if(fileName.count() < 20)
245 fileName += QString(20 - fileName.count(), ' ');
248 QString debugLine = QString("#%1 %2 0x%3 %4").arg(i, 3, 10)
250 .arg((long)(callstack[i]), addrSize, 16, QLatin1Char('0'))
253 dumpStream << debugLine << "\n";
254 qDebug() << qPrintable(debugLine);
258 #endif /* BUILD_CRASHHANDLER */
263 void Global::setupVersion() {
265 # include "version.inc"
266 # include "version.gen"
268 if(quasselGeneratedVersion.isEmpty()) {
269 if(quasselCommit.isEmpty())
270 quasselVersion = QString("v%1 (unknown rev)").arg(quasselBaseVersion);
272 quasselVersion = QString("v%1 (dist-%2, %3)").arg(quasselBaseVersion).arg(quasselCommit.left(7))
273 .arg(QDateTime::fromTime_t(quasselArchiveDate).toLocalTime().toString("yyyy-MM-dd"));
275 QStringList parts = quasselGeneratedVersion.split(':');
276 quasselVersion = QString("v%1").arg(parts[0]);
277 if(parts.count() >= 2) quasselVersion.append(QString(" (%1)").arg(parts[1]));
279 quasselBuildDate = __DATE__;
280 quasselBuildTime = __TIME__;
283 QString Global::quasselVersion;
284 QString Global::quasselBaseVersion;
285 QString Global::quasselGeneratedVersion;
286 QString Global::quasselBuildDate;
287 QString Global::quasselBuildTime;
288 QString Global::quasselCommit;
289 uint Global::quasselArchiveDate;
290 uint Global::protocolVersion;
291 uint Global::clientNeedsProtocol;
292 uint Global::coreNeedsProtocol;