Fixed those nasty "Client::updateLastSeen(): Unknown buffer $bufferId" messages.
[quassel.git] / src / common / ircchannel.cpp
1 /***************************************************************************
2  *   Copyright (C) 2005-08 by the Quassel Project                          *
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 "ircchannel.h"
22
23 #include "network.h"
24 //#include "nicktreemodel.h"
25 #include "signalproxy.h"
26 #include "ircuser.h"
27 #include "util.h"
28
29 #include <QMapIterator>
30 #include <QHashIterator>
31 #include <QTextCodec>
32
33 #include <QDebug>
34
35
36 IrcChannel::IrcChannel(const QString &channelname, Network *network) : SyncableObject(network),
37     _initialized(false),
38     _name(channelname),
39     _topic(QString()),
40     network(network),
41     _codecForEncoding(0),
42     _codecForDecoding(0)
43 {
44   setObjectName(QString::number(network->networkId().toInt()) + "/" +  channelname);
45 }
46
47 IrcChannel::~IrcChannel() {
48 }
49
50 // ====================
51 //  PUBLIC:
52 // ====================
53 bool IrcChannel::isKnownUser(IrcUser *ircuser) const {
54   if(ircuser == 0) {
55     qWarning() << "Channel" << name() << "received IrcUser Nullpointer!";
56     return false;
57   }
58   
59   if(!_userModes.contains(ircuser)) {
60     qWarning() << "Channel" << name() << "received data for unknown User" << ircuser->nick();
61     return false;
62   }
63
64   return true;
65 }
66
67 bool IrcChannel::isValidChannelUserMode(const QString &mode) const {
68   bool isvalid = true;
69   if(mode.size() > 1) {
70     qWarning() << "Channel" << name() << "received Channel User Mode which is longer then 1 Char:" << mode;
71     isvalid = false;
72   }
73   return isvalid;
74 }
75
76 QString IrcChannel::userModes(IrcUser *ircuser) const {
77   if(_userModes.contains(ircuser))
78     return _userModes[ircuser];
79   else
80     return QString();
81 }
82
83 QString IrcChannel::userModes(const QString &nick) const {
84   return userModes(network->ircUser(nick));
85 }
86
87 void IrcChannel::setCodecForEncoding(const QString &name) {
88   setCodecForEncoding(QTextCodec::codecForName(name.toAscii()));
89 }
90
91 void IrcChannel::setCodecForEncoding(QTextCodec *codec) {
92   _codecForEncoding = codec;
93 }
94
95 void IrcChannel::setCodecForDecoding(const QString &name) {
96   setCodecForDecoding(QTextCodec::codecForName(name.toAscii()));
97 }
98
99 void IrcChannel::setCodecForDecoding(QTextCodec *codec) {
100   _codecForDecoding = codec;
101 }
102
103 QString IrcChannel::decodeString(const QByteArray &text) const {
104   if(!codecForDecoding()) return network->decodeString(text);
105   return ::decodeString(text, _codecForDecoding);
106 }
107
108 QByteArray IrcChannel::encodeString(const QString &string) const {
109   if(codecForEncoding()) {
110     return _codecForEncoding->fromUnicode(string);
111   }
112   return network->encodeString(string);
113 }
114
115 // ====================
116 //  PUBLIC SLOTS:
117 // ====================
118 void IrcChannel::setTopic(const QString &topic) {
119   _topic = topic;
120   emit topicSet(topic);
121 }
122
123 void IrcChannel::setPassword(const QString &password) {
124   _password = password;
125   emit passwordSet(password);
126 }
127
128 void IrcChannel::join(IrcUser *ircuser) {
129   if(!_userModes.contains(ircuser) && ircuser) {
130     _userModes[ircuser] = QString();
131     ircuser->joinChannel(this);
132     //qDebug() << "JOIN" << name() << ircuser->nick() << ircUsers().count();
133     connect(ircuser, SIGNAL(nickSet(QString)), this, SLOT(ircUserNickSet(QString)));
134     connect(ircuser, SIGNAL(destroyed()), this, SLOT(ircUserDestroyed()));
135     // if you wonder why there is no counterpart to ircUserJoined:
136     // the joines are propagted by the ircuser. the signal ircUserJoined is only for convenience
137     emit ircUserJoined(ircuser);
138   }
139 }
140
141 void IrcChannel::join(const QString &nick) {
142   join(network->ircUser(nick));
143 }
144
145 void IrcChannel::part(IrcUser *ircuser) {
146   if(isKnownUser(ircuser)) {
147     _userModes.remove(ircuser);
148     ircuser->partChannel(this);
149     //qDebug() << "PART" << name() << ircuser->nick() << ircUsers().count();
150     // if you wonder why there is no counterpart to ircUserParted:
151     // the joines are propagted by the ircuser. the signal ircUserParted is only for convenience
152     disconnect(ircuser, 0, this, 0);
153     emit ircUserParted(ircuser);
154     if(network->isMe(ircuser))
155        deleteLater();
156   }
157 }
158
159 void IrcChannel::part(const QString &nick) {
160   part(network->ircUser(nick));
161 }
162
163 // SET USER MODE
164 void IrcChannel::setUserModes(IrcUser *ircuser, const QString &modes) {
165   if(isKnownUser(ircuser)) {
166     _userModes[ircuser] = modes;
167     emit userModesSet(ircuser->nick(), modes);
168     emit ircUserModesSet(ircuser, modes);
169   }
170 }
171
172 void IrcChannel::setUserModes(const QString &nick, const QString &modes) {
173   setUserModes(network->ircUser(nick), modes);
174 }
175
176 // ADD USER MODE
177 void IrcChannel::addUserMode(IrcUser *ircuser, const QString &mode) {
178   if(!isKnownUser(ircuser) || !isValidChannelUserMode(mode))
179     return;
180
181   if(!_userModes[ircuser].contains(mode)) {
182     _userModes[ircuser] += mode;
183     emit userModeAdded(ircuser->nick(), mode);
184     emit ircUserModeAdded(ircuser, mode);
185   }
186
187 }
188
189 void IrcChannel::addUserMode(const QString &nick, const QString &mode) {
190   addUserMode(network->ircUser(nick), mode);
191 }
192
193 // REMOVE USER MODE
194 void IrcChannel::removeUserMode(IrcUser *ircuser, const QString &mode) {
195   if(!isKnownUser(ircuser) || !isValidChannelUserMode(mode))
196     return;
197
198   if(_userModes[ircuser].contains(mode)) {
199     _userModes[ircuser].remove(mode);
200     emit userModeRemoved(ircuser->nick(), mode);
201     emit ircUserModeRemoved(ircuser, mode);
202   }
203
204 }
205
206 void IrcChannel::removeUserMode(const QString &nick, const QString &mode) {
207   removeUserMode(network->ircUser(nick), mode);
208 }
209
210 // INIT SET USER MODES
211 QVariantMap IrcChannel::initUserModes() const {
212   QVariantMap usermodes;
213   QHash<IrcUser *, QString>::const_iterator iter = _userModes.constBegin();
214   while(iter != _userModes.constEnd()) {
215     usermodes[iter.key()->nick()] = iter.value();
216     iter++;
217   }
218   return usermodes;
219 }
220
221 void IrcChannel::initSetUserModes(const QVariantMap &usermodes) {
222   QMapIterator<QString, QVariant> iter(usermodes);
223   while(iter.hasNext()) {
224     iter.next();
225     setUserModes(iter.key(), iter.value().toString());
226   }
227 }
228
229 void IrcChannel::ircUserDestroyed() {
230   IrcUser *ircUser = static_cast<IrcUser *>(sender());
231   Q_ASSERT(ircUser);
232   _userModes.remove(ircUser);
233   // no further propagation.
234   // this leads only to fuck ups.
235 }
236
237 void IrcChannel::ircUserNickSet(QString nick) {
238   IrcUser *ircUser = qobject_cast<IrcUser *>(sender());
239   Q_ASSERT(ircUser);
240   emit ircUserNickSet(ircUser, nick);
241 }
242