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