fixed a bug in IrcChannel. Upgrade is strongly advised! Distclean as usual.
[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) 
37   : SyncableObject(network),
38     _initialized(false),
39     _name(channelname),
40     _topic(QString()),
41     network(network)
42 {
43   setObjectName(QString::number(network->networkId().toInt()) + "/" +  channelname);
44 }
45
46 IrcChannel::~IrcChannel() {
47
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::name() const {
77   return _name;
78 }
79
80 QString IrcChannel::topic() const {
81   return _topic;
82 }
83
84 QList<IrcUser *> IrcChannel::ircUsers() const {
85   return _userModes.keys();
86 }
87
88 QString IrcChannel::userModes(IrcUser *ircuser) const {
89   if(_userModes.contains(ircuser))
90     return _userModes[ircuser];
91   else
92     return QString();
93 }
94
95 QString IrcChannel::userModes(const QString &nick) const {
96   return userModes(network->ircUser(nick));
97 }
98
99 QTextCodec *IrcChannel::codecForEncoding() const {
100   return _codecForEncoding;
101 }
102
103 void IrcChannel::setCodecForEncoding(const QString &name) {
104   setCodecForEncoding(QTextCodec::codecForName(name.toAscii()));
105 }
106
107 void IrcChannel::setCodecForEncoding(QTextCodec *codec) {
108   _codecForEncoding = codec;
109 }
110
111 QTextCodec *IrcChannel::codecForDecoding() const {
112   return _codecForDecoding;
113 }
114
115 void IrcChannel::setCodecForDecoding(const QString &name) {
116   setCodecForDecoding(QTextCodec::codecForName(name.toAscii()));
117 }
118
119 void IrcChannel::setCodecForDecoding(QTextCodec *codec) {
120   _codecForDecoding = codec;
121 }
122
123 QString IrcChannel::decodeString(const QByteArray &text) const {
124   if(!codecForDecoding()) return network->decodeString(text);
125   return ::decodeString(text, _codecForDecoding);
126 }
127
128 QByteArray IrcChannel::encodeString(const QString string) const {
129   if(codecForEncoding()) {
130     return _codecForEncoding->fromUnicode(string);
131   }
132   return network->encodeString(string);
133 }
134
135 // ====================
136 //  PUBLIC SLOTS:
137 // ====================
138 void IrcChannel::setTopic(const QString &topic) {
139   _topic = topic;
140   emit topicSet(topic);
141 }
142
143 void IrcChannel::join(IrcUser *ircuser) {
144   if(!_userModes.contains(ircuser) && ircuser) {
145     _userModes[ircuser] = QString();
146     ircuser->joinChannel(name());
147     //qDebug() << "JOIN" << name() << ircuser->nick() << ircUsers().count();
148     connect(ircuser, SIGNAL(nickSet(QString)), this, SLOT(ircUserNickSet(QString)));
149     connect(ircuser, SIGNAL(destroyed()), this, SLOT(ircUserDestroyed()));
150     // if you wonder why there is no counterpart to ircUserJoined:
151     // the joines are propagted by the ircuser. the signal ircUserJoined is only for convenience
152     emit ircUserJoined(ircuser);
153   }
154 }
155
156 void IrcChannel::join(const QString &nick) {
157   join(network->ircUser(nick));
158 }
159
160 void IrcChannel::part(IrcUser *ircuser) {
161   if(isKnownUser(ircuser)) {
162     _userModes.remove(ircuser);
163     ircuser->partChannel(name());
164     //qDebug() << "PART" << name() << ircuser->nick() << ircUsers().count();
165     // if you wonder why there is no counterpart to ircUserParted:
166     // the joines are propagted by the ircuser. the signal ircUserParted is only for convenience
167     disconnect(ircuser, 0, this, 0);
168     emit ircUserParted(ircuser);
169     if(network->isMe(ircuser))
170        deleteLater();
171   }
172 }
173
174 void IrcChannel::part(const QString &nick) {
175   part(network->ircUser(nick));
176 }
177
178 // SET USER MODE
179 void IrcChannel::setUserModes(IrcUser *ircuser, const QString &modes) {
180   if(isKnownUser(ircuser)) {
181     _userModes[ircuser] = modes;
182     emit userModesSet(ircuser->nick(), modes);
183     emit ircUserModesSet(ircuser, modes);
184   }
185 }
186
187 void IrcChannel::setUserModes(const QString &nick, const QString &modes) {
188   setUserModes(network->ircUser(nick), modes);
189 }
190
191 // ADD USER MODE
192 void IrcChannel::addUserMode(IrcUser *ircuser, const QString &mode) {
193   if(!isKnownUser(ircuser) || !isValidChannelUserMode(mode))
194     return;
195
196   if(!_userModes[ircuser].contains(mode)) {
197     _userModes[ircuser] += mode;
198     emit userModeAdded(ircuser->nick(), mode);
199     emit ircUserModeAdded(ircuser, mode);
200   }
201
202 }
203
204 void IrcChannel::addUserMode(const QString &nick, const QString &mode) {
205   addUserMode(network->ircUser(nick), mode);
206 }
207
208 // REMOVE USER MODE
209 void IrcChannel::removeUserMode(IrcUser *ircuser, const QString &mode) {
210   if(!isKnownUser(ircuser) || !isValidChannelUserMode(mode))
211     return;
212
213   if(_userModes[ircuser].contains(mode)) {
214     _userModes[ircuser].remove(mode);
215     emit userModeRemoved(ircuser->nick(), mode);
216     emit ircUserModeRemoved(ircuser, mode);
217   }
218
219 }
220
221 void IrcChannel::removeUserMode(const QString &nick, const QString &mode) {
222   removeUserMode(network->ircUser(nick), mode);
223 }
224
225 // INIT SET USER MODES
226 QVariantMap IrcChannel::initUserModes() const {
227   QVariantMap usermodes;
228   QHash<IrcUser *, QString>::const_iterator iter = _userModes.constBegin();
229   while(iter != _userModes.constEnd()) {
230     usermodes[iter.key()->nick()] = iter.value();
231     iter++;
232   }
233   return usermodes;
234 }
235
236 void IrcChannel::initSetUserModes(const QVariantMap &usermodes) {
237   QMapIterator<QString, QVariant> iter(usermodes);
238   while(iter.hasNext()) {
239     iter.next();
240     setUserModes(iter.key(), iter.value().toString());
241   }
242 }
243
244 void IrcChannel::ircUserDestroyed() {
245   qDebug() << "IrcChannel::ircUserDestroyed()";
246   IrcUser *ircUser = static_cast<IrcUser *>(sender());
247   Q_ASSERT(ircUser);
248   _userModes.remove(ircUser);
249   emit ircUserParted(ircUser);
250   //qDebug() << "DEST" << name() << ircUsers().count();
251 }
252
253 void IrcChannel::ircUserNickSet(QString nick) {
254   IrcUser *ircUser = qobject_cast<IrcUser *>(sender());
255   Q_ASSERT(ircUser);
256   emit ircUserNickSet(ircUser, nick);
257 }
258