1 /***************************************************************************
2 * Copyright (C) 2005-08 by the Quassel Project *
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 ***************************************************************************/
24 #include <QTranslator>
31 #include "cliparser.h"
33 #if defined BUILD_CORE
38 #elif defined BUILD_QTUI
40 #include "qtuiapplication.h"
43 #elif defined BUILD_MONO
46 #include "coresession.h"
47 #include "qtuiapplication.h"
51 #error "Something is wrong - you need to #define a build mode!"
57 #if not defined(Q_OS_WIN32) && not defined(MAC_10_4_SDK)
63 //! Signal handler for graceful shutdown.
64 void handle_signal(int sig) {
65 qWarning("%s", qPrintable(QString("Caught signal %1 - exiting.").arg(sig)));
66 QCoreApplication::quit();
69 #if not defined(Q_OS_WIN32) && not defined(MAC_10_4_SDK)
70 void handle_crash(int sig) {
72 int i, frames = backtrace(callstack, 128);
74 QFile dumpFile(QString("Quassel-Crash-%1").arg(QDateTime::currentDateTime().toString("yyyyMMdd-hhmm.log")));
75 dumpFile.open(QIODevice::WriteOnly);
76 QTextStream dumpStream(&dumpFile);
78 for (i = 0; i < frames; ++i) {
80 dladdr (callstack[i], &info);
84 // __const char *dli_fname; /* File name of defining object. */
85 // void *dli_fbase; /* Load address of that object. */
86 // __const char *dli_sname; /* Name of nearest symbol. */
87 // void *dli_saddr; /* Exact value of nearest symbol. */
98 char *func = abi::__cxa_demangle(info.dli_sname, 0, 0, 0);
100 funcName = QString(func);
103 funcName = QString(info.dli_sname);
106 funcName = QString("0x%1").arg((long)info.dli_saddr, addrSize, QLatin1Char('0'));
109 // prettificating the filename
110 QString fileName("???");
112 fileName = QString(info.dli_fname);
113 int slashPos = fileName.lastIndexOf('/');
115 fileName = fileName.mid(slashPos + 1);
116 if(fileName.count() < 20)
117 fileName += QString(20 - fileName.count(), ' ');
120 QString debugLine = QString("#%1 %2 0x%3 %4").arg(i, 3, 10)
122 .arg((long)(callstack[i]), addrSize, 16, QLatin1Char('0'))
125 dumpStream << debugLine << "\n";
126 qDebug() << qPrintable(debugLine);
131 #endif // ifndef Q_OS_WIN32
134 int main(int argc, char **argv) {
135 // We catch SIGTERM and SIGINT (caused by Ctrl+C) to graceful shutdown Quassel.
136 signal(SIGTERM, handle_signal);
137 signal(SIGINT, handle_signal);
139 #if not defined(Q_OS_WIN32) && not defined(MAC_10_4_SDK)
140 signal(SIGABRT, handle_crash);
141 signal(SIGBUS, handle_crash);
142 signal(SIGSEGV, handle_crash);
143 #endif // ndef Q_OS_WIN32
145 Global::registerMetaTypes();
146 Global::setupVersion();
149 #if defined BUILD_CORE
150 Global::runMode = Global::CoreOnly;
151 QCoreApplication app(argc, argv);
152 #elif defined BUILD_QTUI
153 Global::runMode = Global::ClientOnly;
154 QApplication app(argc, argv);
156 Global::runMode = Global::Monolithic;
157 QApplication app(argc, argv);
160 #if defined BUILD_CORE
161 Global::runMode = Global::CoreOnly;
162 QCoreApplication app(argc, argv);
163 #elif defined BUILD_QTUI
164 Global::runMode = Global::ClientOnly;
165 QtUiApplication app(argc, argv);
167 Global::runMode = Global::Monolithic;
168 QtUiApplication app(argc, argv);
173 Global::parser = CliParser(QCoreApplication::arguments());
176 // put core-only arguments here
177 Global::parser.addOption("port",'p',"The port quasselcore will listen at",QString("4242"));
178 Global::parser.addSwitch("norestore", 'n', "Don't restore last core's state");
179 Global::parser.addOption("logfile",'l',"Path to logfile");
180 Global::parser.addOption("loglevel",'L',"Loglevel Debug|Info|Warning|Error","Info");
181 Global::parser.addOption("datadir", 0, "Specify the directory holding datafiles like the Sqlite DB and the SSL Cert");
184 // put client-only arguments here
185 Global::parser.addSwitch("debugbufferswitches",0,"Enables debugging for bufferswitches");
186 Global::parser.addSwitch("debugmodel",0,"Enables debugging for models");
187 #endif // BUILD_QTCORE
188 // put shared client&core arguments here
189 Global::parser.addSwitch("debug",'d',"Enable debug output");
190 Global::parser.addSwitch("help",'h', "Display this help and exit");
192 if(!Global::parser.parse() || Global::parser.isSet("help")) {
193 Global::parser.usage();
198 This is an initial check if logfile is writable since the warning would spam stdout if done
199 in current Logger implementation. Can be dropped whenever the logfile is only opened once.
201 if(Global::runMode != Global::ClientOnly) {
203 if(!Global::parser.value("logfile").isEmpty()) {
204 logFile.setFileName(Global::parser.value("logfile"));
205 if(!logFile.open(QIODevice::Append | QIODevice::Text))
206 qWarning("Warning: Couldn't open logfile '%s' - will log to stdout instead",qPrintable(logFile.fileName()));
207 else logFile.close();
211 qsrand(QTime(0,0,0).secsTo(QTime::currentTime()));
213 // Set up i18n support
214 QLocale locale = QLocale::system();
216 QTranslator qtTranslator(&app);
217 qtTranslator.setObjectName("QtTr");
218 qtTranslator.load(QString(":i18n/qt_%1").arg(locale.name()));
219 app.installTranslator(&qtTranslator);
221 QTranslator quasselTranslator(&app);
222 quasselTranslator.setObjectName("QuasselTr");
223 quasselTranslator.load(QString(":i18n/quassel_%1").arg(locale.name()));
224 app.installTranslator(&quasselTranslator);
226 Network::setDefaultCodecForServer("ISO-8859-1");
227 Network::setDefaultCodecForEncoding("UTF-8");
228 Network::setDefaultCodecForDecoding("ISO-8859-15");
230 QCoreApplication::setOrganizationDomain("quassel-irc.org");
231 QCoreApplication::setApplicationName("Quassel IRC");
232 QCoreApplication::setOrganizationName("Quassel Project");
236 Core::instance(); // create and init the core
243 QtUi *gui = new QtUi();
245 // init gui only after the event loop has started
246 QTimer::singleShot(0, gui, SLOT(init()));
251 if(!Global::parser.isSet("norestore")) {
252 Core::restoreState();
257 app.resumeSessionIfPossible();
260 int exitCode = app.exec();
267 // the mainWin has to be deleted before the Core
268 // if not Quassel will crash on exit under certain conditions since the gui
269 // still wants to access clientdata