~ubuntu-branches/ubuntu/jaunty/quassel/jaunty

« back to all changes in this revision

Viewing changes to src/common/quassel.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Harald Sitter
  • Date: 2008-11-17 15:22:46 UTC
  • mfrom: (1.1.3 upstream)
  • Revision ID: james.westby@ubuntu.com-20081117152246-3lwlpnr4r08910kv
Tags: 0.3.1-0ubuntu1
* New upstream release (LP: #271403)
* Drop all patches originated from upstream (quassel_*)
* Compile with non-builtin quassel icons
  + Introduce new quassel-data package
  + quassel and quassel-client depend on quassel-data
  + Don't manually enforce icon installation for desktop files in debian/rules
  + Add quassel_01_fix_iconloader.patch
* Drop perl build dependency, I have no clue why it was added in the first
  place. Neither changelog nor Bazaar knows, and since quassel compiles just
  fine without it, removing it should be save.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/***************************************************************************
 
2
 *   Copyright (C) 2005-08 by the Quassel IRC Team                         *
 
3
 *   devel@quassel-irc.org                                                 *
 
4
 *                                                                         *
 
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.                                           *
 
9
 *                                                                         *
 
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.                          *
 
14
 *                                                                         *
 
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
 ***************************************************************************/
 
20
 
 
21
#include "quassel.h"
 
22
 
 
23
#include <signal.h>
 
24
 
 
25
#include <QCoreApplication>
 
26
#include <QDateTime>
 
27
#include <QObject>
 
28
#include <QMetaType>
 
29
 
 
30
#include "message.h"
 
31
#include "identity.h"
 
32
#include "network.h"
 
33
#include "bufferinfo.h"
 
34
#include "types.h"
 
35
#include "syncableobject.h"
 
36
 
 
37
Quassel::BuildInfo Quassel::_buildInfo;
 
38
CliParser *Quassel::_cliParser = 0;
 
39
Quassel::RunMode Quassel::_runMode;
 
40
bool Quassel::_initialized = false;
 
41
bool Quassel::DEBUG = false;
 
42
QString Quassel::_coreDumpFileName;
 
43
 
 
44
Quassel::Quassel() {
 
45
  Q_INIT_RESOURCE(i18n);
 
46
 
 
47
  // We catch SIGTERM and SIGINT (caused by Ctrl+C) to graceful shutdown Quassel.
 
48
  signal(SIGTERM, handleSignal);
 
49
  signal(SIGINT, handleSignal);
 
50
 
 
51
  // we have crashhandler for win32 and unix (based on execinfo).
 
52
  // on mac os we use it's integrated backtrace generator
 
53
#if defined(Q_OS_WIN32) || (defined(HAVE_EXECINFO) && !defined(Q_OS_MAC))
 
54
  signal(SIGABRT, handleSignal);
 
55
  signal(SIGSEGV, handleSignal);
 
56
#  ifndef Q_OS_WIN32
 
57
  signal(SIGBUS, handleSignal);
 
58
#  endif
 
59
#endif
 
60
 
 
61
  _cliParser = new CliParser();
 
62
 
 
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"));
 
66
}
 
67
 
 
68
Quassel::~Quassel() {
 
69
  delete _cliParser;
 
70
}
 
71
 
 
72
bool Quassel::init() {
 
73
  if(_initialized)
 
74
    return true;  // allow multiple invocations because of MonolithicApplication
 
75
 
 
76
  _initialized = true;
 
77
  qsrand(QTime(0,0,0).secsTo(QTime::currentTime()));
 
78
 
 
79
  registerMetaTypes();
 
80
 
 
81
  QCoreApplication::setApplicationName(buildInfo().applicationName);
 
82
  QCoreApplication::setOrganizationName(buildInfo().organizationName);
 
83
  QCoreApplication::setOrganizationDomain(buildInfo().organizationDomain);
 
84
 
 
85
  Network::setDefaultCodecForServer("ISO-8859-1");
 
86
  Network::setDefaultCodecForEncoding("UTF-8");
 
87
  Network::setDefaultCodecForDecoding("ISO-8859-15");
 
88
 
 
89
  if(!cliParser()->parse(QCoreApplication::arguments()) || isOptionSet("help")) {
 
90
    cliParser()->usage();
 
91
    return false;
 
92
  }
 
93
  DEBUG = isOptionSet("debug");
 
94
  return true;
 
95
}
 
96
 
 
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.
 
99
*
 
100
*/
 
101
void Quassel::registerMetaTypes() {
 
102
  // Complex types
 
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");
 
109
 
 
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");
 
116
 
 
117
  qRegisterMetaType<IdentityId>("IdentityId");
 
118
  qRegisterMetaType<BufferId>("BufferId");
 
119
  qRegisterMetaType<NetworkId>("NetworkId");
 
120
  qRegisterMetaType<UserId>("UserId");
 
121
  qRegisterMetaType<AccountId>("AccountId");
 
122
  qRegisterMetaType<MsgId>("MsgId");
 
123
 
 
124
  qRegisterMetaTypeStreamOperators<IdentityId>("IdentityId");
 
125
  qRegisterMetaTypeStreamOperators<BufferId>("BufferId");
 
126
  qRegisterMetaTypeStreamOperators<NetworkId>("NetworkId");
 
127
  qRegisterMetaTypeStreamOperators<UserId>("UserId");
 
128
  qRegisterMetaTypeStreamOperators<AccountId>("AccountId");
 
129
  qRegisterMetaTypeStreamOperators<MsgId>("MsgId");
 
130
}
 
131
 
 
132
void Quassel::setupBuildInfo(const QString &generated) {
 
133
  _buildInfo.applicationName = "Quassel IRC";
 
134
  _buildInfo.coreApplicationName = "Quassel Core";
 
135
  _buildInfo.clientApplicationName = "Quassel Client";
 
136
  _buildInfo.organizationName = "Quassel Project";
 
137
  _buildInfo.organizationDomain = "quassel-irc.org";
 
138
 
 
139
  QStringList gen = generated.split(',');
 
140
  Q_ASSERT(gen.count() == 10);
 
141
  _buildInfo.baseVersion = gen[0];
 
142
  _buildInfo.generatedVersion = gen[1];
 
143
  _buildInfo.isSourceDirty = !gen[2].isEmpty();
 
144
  _buildInfo.commitHash = gen[3];
 
145
  _buildInfo.commitDate = gen[4].toUInt();
 
146
  _buildInfo.protocolVersion = gen[5].toUInt();
 
147
  _buildInfo.clientNeedsProtocol = gen[6].toUInt();
 
148
  _buildInfo.coreNeedsProtocol = gen[7].toUInt();
 
149
  _buildInfo.buildDate = QString("%1 %2").arg(gen[8], gen[9]);
 
150
  // create a nice version string
 
151
  if(_buildInfo.generatedVersion.isEmpty()) {
 
152
    if(!_buildInfo.commitHash.isEmpty()) {
 
153
      // dist version
 
154
      _buildInfo.plainVersionString = QString("v%1 (dist-%2)")
 
155
                                        .arg(_buildInfo.baseVersion)
 
156
                                        .arg(_buildInfo.commitHash.left(7));
 
157
                                        _buildInfo.fancyVersionString
 
158
                                           = QString("v%1 (dist-<a href=\"http://git.quassel-irc.org/?p=quassel.git;a=commit;h=%3\">%2</a>)")
 
159
                                        .arg(_buildInfo.baseVersion)
 
160
                                        .arg(_buildInfo.commitHash.left(7))
 
161
                                        .arg(_buildInfo.commitHash);
 
162
    } else {
 
163
    // we only have a base version :(
 
164
      _buildInfo.plainVersionString = QString("v%1 (unknown rev)").arg(_buildInfo.baseVersion);
 
165
    }
 
166
  } else {
 
167
    // analyze what we got from git-describe
 
168
    QRegExp rx("(.*)-(\\d+)-g([0-9a-f]+)$");
 
169
    if(rx.exactMatch(_buildInfo.generatedVersion)) {
 
170
      QString distance = rx.cap(2) == "0" ? QString() : QString(" [+%1]").arg(rx.cap(2));
 
171
      _buildInfo.plainVersionString = QString("v%1%2 (git-%3%4)")
 
172
                                        .arg(rx.cap(1), distance, rx.cap(3))
 
173
                                        .arg(_buildInfo.isSourceDirty ? "*" : "");
 
174
      if(!_buildInfo.commitHash.isEmpty()) {
 
175
        _buildInfo.fancyVersionString = QString("v%1%2 (git-<a href=\"http://git.quassel-irc.org/?p=quassel.git;a=commit;h=%5\">%3</a>%4)")
 
176
                                          .arg(rx.cap(1), distance, rx.cap(3))
 
177
                                          .arg(_buildInfo.isSourceDirty ? "*" : "")
 
178
                                          .arg(_buildInfo.commitHash);
 
179
      }
 
180
    } else {
 
181
      _buildInfo.plainVersionString = QString("v%1 (invalid rev)").arg(_buildInfo.baseVersion);
 
182
    }
 
183
  }
 
184
  if(_buildInfo.fancyVersionString.isEmpty())
 
185
    _buildInfo.fancyVersionString = _buildInfo.plainVersionString;
 
186
}
 
187
 
 
188
//! Signal handler for graceful shutdown.
 
189
void Quassel::handleSignal(int sig) {
 
190
  switch(sig) {
 
191
  case SIGTERM:
 
192
  case SIGINT:
 
193
    qWarning("%s", qPrintable(QString("Caught signal %1 - exiting.").arg(sig)));
 
194
    QCoreApplication::quit();
 
195
    break;
 
196
  case SIGABRT:
 
197
  case SIGSEGV:
 
198
#ifndef Q_OS_WIN32
 
199
  case SIGBUS:
 
200
#endif
 
201
    logBacktrace(coreDumpFileName());
 
202
    exit(EXIT_FAILURE);
 
203
    break;
 
204
  default:
 
205
    break;
 
206
  }
 
207
}
 
208
 
 
209
void Quassel::logFatalMessage(const char *msg) {
 
210
#ifdef Q_OS_MAC
 
211
  Q_UNUSED(msg)
 
212
#else
 
213
  QFile dumpFile(coreDumpFileName());
 
214
  dumpFile.open(QIODevice::Append);
 
215
  QTextStream dumpStream(&dumpFile);
 
216
 
 
217
  dumpStream << "Fatal: " << msg << '\n';
 
218
  dumpStream.flush();
 
219
  dumpFile.close();
 
220
#endif
 
221
}
 
222
 
 
223
const QString &Quassel::coreDumpFileName() {
 
224
  if(_coreDumpFileName.isEmpty()) {
 
225
    _coreDumpFileName = QString("Quassel-Crash-%1.log").arg(QDateTime::currentDateTime().toString("yyyyMMdd-hhmm"));
 
226
    QFile dumpFile(_coreDumpFileName);
 
227
    dumpFile.open(QIODevice::Append);
 
228
    QTextStream dumpStream(&dumpFile);
 
229
    dumpStream << "Quassel IRC: " << _buildInfo.baseVersion << ' ' << _buildInfo.commitHash << '\n';
 
230
    qDebug() << "Quassel IRC: " << _buildInfo.baseVersion << ' ' << _buildInfo.commitHash;
 
231
    dumpStream.flush();
 
232
    dumpFile.close();
 
233
  }
 
234
  return _coreDumpFileName;
 
235
}