X-Git-Url: https://git.quassel-irc.org/?p=quassel.git;a=blobdiff_plain;f=src%2Fcommon%2Fircchannel.cpp;h=9a66d809d8c74ac49b1985a8822605cb6a285962;hp=e6c809f0cb43b5912ad76b5419739f2471edaa24;hb=2dc003e929312add334ccb4d48b453d942d89b7b;hpb=e733408e4759473bf38831f498f48a0f2f5e6dc7 diff --git a/src/common/ircchannel.cpp b/src/common/ircchannel.cpp index e6c809f0..9a66d809 100644 --- a/src/common/ircchannel.cpp +++ b/src/common/ircchannel.cpp @@ -21,8 +21,6 @@ #include "ircchannel.h" #include "network.h" -//#include "nicktreemodel.h" -#include "signalproxy.h" #include "ircuser.h" #include "util.h" @@ -33,20 +31,18 @@ #include -IrcChannel::IrcChannel(const QString &channelname, Network *network) +IrcChannel::IrcChannel(const QString &channelname, Network *network) : SyncableObject(network), _initialized(false), _name(channelname), _topic(QString()), - network(network) + network(network), + _codecForEncoding(0), + _codecForDecoding(0) { setObjectName(QString::number(network->networkId().toInt()) + "/" + channelname); } -IrcChannel::~IrcChannel() { - -} - // ==================== // PUBLIC: // ==================== @@ -73,18 +69,6 @@ bool IrcChannel::isValidChannelUserMode(const QString &mode) const { return isvalid; } -QString IrcChannel::name() const { - return _name; -} - -QString IrcChannel::topic() const { - return _topic; -} - -QList IrcChannel::ircUsers() const { - return _userModes.keys(); -} - QString IrcChannel::userModes(IrcUser *ircuser) const { if(_userModes.contains(ircuser)) return _userModes[ircuser]; @@ -96,10 +80,6 @@ QString IrcChannel::userModes(const QString &nick) const { return userModes(network->ircUser(nick)); } -QTextCodec *IrcChannel::codecForEncoding() const { - return _codecForEncoding; -} - void IrcChannel::setCodecForEncoding(const QString &name) { setCodecForEncoding(QTextCodec::codecForName(name.toAscii())); } @@ -108,10 +88,6 @@ void IrcChannel::setCodecForEncoding(QTextCodec *codec) { _codecForEncoding = codec; } -QTextCodec *IrcChannel::codecForDecoding() const { - return _codecForDecoding; -} - void IrcChannel::setCodecForDecoding(const QString &name) { setCodecForDecoding(QTextCodec::codecForName(name.toAscii())); } @@ -125,7 +101,7 @@ QString IrcChannel::decodeString(const QByteArray &text) const { return ::decodeString(text, _codecForDecoding); } -QByteArray IrcChannel::encodeString(const QString string) const { +QByteArray IrcChannel::encodeString(const QString &string) const { if(codecForEncoding()) { return _codecForEncoding->fromUnicode(string); } @@ -140,30 +116,77 @@ void IrcChannel::setTopic(const QString &topic) { emit topicSet(topic); } -void IrcChannel::join(IrcUser *ircuser) { - if(!_userModes.contains(ircuser) && ircuser) { - _userModes[ircuser] = QString(); - ircuser->joinChannel(name()); +void IrcChannel::setPassword(const QString &password) { + _password = password; + emit passwordSet(password); +} + +void IrcChannel::joinIrcUsers(const QList &users, const QStringList &modes) { + if(users.isEmpty()) + return; + + if(users.count() != modes.count()) { + qWarning() << "IrcChannel::addUsers(): number of nicks does not match number of modes!"; + return; + } + + QStringList newNicks; + QStringList newModes; + QList newUsers; + + IrcUser *ircuser; + for(int i = 0; i < users.count(); i++) { + ircuser = users[i]; + if(!ircuser || _userModes.contains(ircuser)) + continue; + + _userModes[ircuser] = modes[i]; + ircuser->joinChannel(this); //qDebug() << "JOIN" << name() << ircuser->nick() << ircUsers().count(); connect(ircuser, SIGNAL(nickSet(QString)), this, SLOT(ircUserNickSet(QString))); connect(ircuser, SIGNAL(destroyed()), this, SLOT(ircUserDestroyed())); // if you wonder why there is no counterpart to ircUserJoined: // the joines are propagted by the ircuser. the signal ircUserJoined is only for convenience - emit ircUserJoined(ircuser); + + newNicks << ircuser->nick(); + newModes << modes[i]; + newUsers << ircuser; } + + if(newNicks.isEmpty()) + return; + + emit ircUsersJoined(newUsers); + emit ircUsersJoined(newNicks, newModes); } -void IrcChannel::join(const QString &nick) { - join(network->ircUser(nick)); +void IrcChannel::joinIrcUsers(const QStringList &nicks, const QStringList &modes) { + QList users; + foreach(QString nick, nicks) + users << network->newIrcUser(nick); + joinIrcUsers(users, modes); +} + +void IrcChannel::joinIrcUsers(IrcUser *ircuser) { + QList users; + users << ircuser; + QStringList modes; + modes << QString(); + joinIrcUsers(users, modes); +} + +void IrcChannel::joinIrcUsers(const QString &nick) { + joinIrcUsers(network->newIrcUser(nick)); } void IrcChannel::part(IrcUser *ircuser) { if(isKnownUser(ircuser)) { _userModes.remove(ircuser); - ircuser->partChannel(name()); + ircuser->partChannel(this); //qDebug() << "PART" << name() << ircuser->nick() << ircUsers().count(); // if you wonder why there is no counterpart to ircUserParted: // the joines are propagted by the ircuser. the signal ircUserParted is only for convenience + disconnect(ircuser, 0, this, 0); emit ircUserParted(ircuser); if(network->isMe(ircuser)) deleteLater(); @@ -214,7 +237,6 @@ void IrcChannel::removeUserMode(IrcUser *ircuser, const QString &mode) { emit userModeRemoved(ircuser->nick(), mode); emit ircUserModeRemoved(ircuser, mode); } - } void IrcChannel::removeUserMode(const QString &nick, const QString &mode) { @@ -233,19 +255,90 @@ QVariantMap IrcChannel::initUserModes() const { } void IrcChannel::initSetUserModes(const QVariantMap &usermodes) { - QMapIterator iter(usermodes); - while(iter.hasNext()) { - iter.next(); - setUserModes(iter.key(), iter.value().toString()); + QList users; + QStringList modes; + QVariantMap::const_iterator iter = usermodes.constBegin(); + while(iter != usermodes.constEnd()) { + users << network->newIrcUser(iter.key()); + modes << iter.value().toString(); + iter++; + } + joinIrcUsers(users, modes); +} + +QVariantMap IrcChannel::initChanModes() const { + QVariantMap channelModes; + + QVariantMap A_modes; + QHash::const_iterator A_iter = _A_channelModes.constBegin(); + while(A_iter != _A_channelModes.constEnd()) { + A_modes[A_iter.key()] = A_iter.value(); + A_iter++; + } + channelModes["A"] = A_modes; + + QVariantMap B_modes; + QHash::const_iterator B_iter = _B_channelModes.constBegin(); + while(B_iter != _B_channelModes.constEnd()) { + B_modes[B_iter.key()] = B_iter.value(); + B_iter++; + } + channelModes["B"] = B_modes; + + QVariantMap C_modes; + QHash::const_iterator C_iter = _C_channelModes.constBegin(); + while(C_iter != _C_channelModes.constEnd()) { + C_modes[C_iter.key()] = C_iter.value(); + C_iter++; } + channelModes["C"] = C_modes; + + QString D_modes; + QSet::const_iterator D_iter = _D_channelModes.constBegin(); + while(D_iter != _D_channelModes.constEnd()) { + D_modes += *D_iter; + D_iter++; + } + channelModes["D"] = D_modes; + + return channelModes; +} + +void IrcChannel::initSetChanModes(const QVariantMap &channelModes) { + QVariantMap::const_iterator iter = channelModes["A"].toMap().constBegin(); + QVariantMap::const_iterator iterEnd = channelModes["A"].toMap().constEnd(); + while(iter != iterEnd) { + _A_channelModes[iter.key()[0]] = iter.value().toStringList(); + iter++; + } + + iter = channelModes["B"].toMap().constBegin(); + iterEnd = channelModes["B"].toMap().constEnd(); + while(iter != iterEnd) { + _B_channelModes[iter.key()[0]] = iter.value().toString(); + iter++; + } + + iter = channelModes["C"].toMap().constBegin(); + iterEnd = channelModes["C"].toMap().constEnd(); + while(iter != iterEnd) { + _C_channelModes[iter.key()[0]] = iter.value().toString(); + iter++; + } + + QString D_modes = channelModes["D"].toString(); + for(int i = 0; i < D_modes.count(); i++) { + _D_channelModes << D_modes[i]; + } + } void IrcChannel::ircUserDestroyed() { IrcUser *ircUser = static_cast(sender()); Q_ASSERT(ircUser); _userModes.remove(ircUser); - emit ircUserParted(ircUser); - //qDebug() << "DEST" << name() << ircUsers().count(); + // no further propagation. + // this leads only to fuck ups. } void IrcChannel::ircUserNickSet(QString nick) { @@ -254,3 +347,182 @@ void IrcChannel::ircUserNickSet(QString nick) { emit ircUserNickSet(ircUser, nick); } +/******************************************************************************* + * + * 3.3 CHANMODES + * + * o CHANMODES=A,B,C,D + * + * The CHANMODES token specifies the modes that may be set on a channel. + * These modes are split into four categories, as follows: + * + * o Type A: Modes that add or remove an address to or from a list. + * These modes always take a parameter when sent by the server to a + * client; when sent by a client, they may be specified without a + * parameter, which requests the server to display the current + * contents of the corresponding list on the channel to the client. + * o Type B: Modes that change a setting on the channel. These modes + * always take a parameter. + * o Type C: Modes that change a setting on the channel. These modes + * take a parameter only when set; the parameter is absent when the + * mode is removed both in the client's and server's MODE command. + * o Type D: Modes that change a setting on the channel. These modes + * never take a parameter. + * + * If the server sends any additional types after these 4, the client + * MUST ignore them; this is intended to allow future extension of this + * token. + * + * The IRC server MUST NOT list modes in CHANMODES which are also + * present in the PREFIX parameter; however, for completeness, modes + * described in PREFIX may be treated as type B modes. + * + ******************************************************************************/ + + +/******************************************************************************* + * Short Version: + * A --> add/remove from List + * B --> set value or remove + * C --> set value or remove + * D --> on/off + * + * B and C behave very similar... we store the data in different datastructes + * for future compatibility + ******************************************************************************/ + +// NOTE: the behavior of addChannelMode and removeChannelMode depends on the type of mode +// see list above for chanmode types +void IrcChannel::addChannelMode(const QChar &mode, const QString &value) { + Network::ChannelModeType modeType = network->channelModeType(mode); + + switch(modeType) { + case Network::NOT_A_CHANMODE: + return; + case Network::A_CHANMODE: + if(!_A_channelModes.contains(mode)) + _A_channelModes[mode] = QStringList(value); + else if(!_A_channelModes[mode].contains(value)) + _A_channelModes[mode] << value; + break; + + case Network::B_CHANMODE: + _B_channelModes[mode] = value; + break; + + case Network::C_CHANMODE: + _C_channelModes[mode] = value; + break; + + case Network::D_CHANMODE: + _D_channelModes << mode; + break; + } + emit channelModeAdded(mode, value); +} + +void IrcChannel::removeChannelMode(const QChar &mode, const QString &value) { + Network::ChannelModeType modeType = network->channelModeType(mode); + + switch(modeType) { + case Network::NOT_A_CHANMODE: + return; + case Network::A_CHANMODE: + if(_A_channelModes.contains(mode)) + _A_channelModes[mode].removeAll(value); + break; + + case Network::B_CHANMODE: + _B_channelModes.remove(mode); + break; + + case Network::C_CHANMODE: + _C_channelModes.remove(mode); + break; + + case Network::D_CHANMODE: + _D_channelModes.remove(mode); + break; + } + emit channelModeRemoved(mode, value); +} + +bool IrcChannel::hasMode(const QChar &mode) const { + Network::ChannelModeType modeType = network->channelModeType(mode); + + switch(modeType) { + case Network::NOT_A_CHANMODE: + return false; + case Network::A_CHANMODE: + return _A_channelModes.contains(mode); + case Network::B_CHANMODE: + return _B_channelModes.contains(mode); + case Network::C_CHANMODE: + return _C_channelModes.contains(mode); + case Network::D_CHANMODE: + return _D_channelModes.contains(mode); + default: + return false; + } +} + +QString IrcChannel::modeValue(const QChar &mode) const { + Network::ChannelModeType modeType = network->channelModeType(mode); + + switch(modeType) { + case Network::B_CHANMODE: + if(_B_channelModes.contains(mode)) + return _B_channelModes[mode]; + else + return QString(); + case Network::C_CHANMODE: + if(_C_channelModes.contains(mode)) + return _C_channelModes[mode]; + else + return QString(); + default: + return QString(); + } + +} + +QStringList IrcChannel::modeValueList(const QChar &mode) const { + Network::ChannelModeType modeType = network->channelModeType(mode); + + switch(modeType) { + case Network::A_CHANMODE: + if(_A_channelModes.contains(mode)) + return _A_channelModes[mode]; + default: + return QStringList(); + } +} + +QString IrcChannel::channelModeString() const { + QStringList params; + QString modeString; + + QSet::const_iterator D_iter = _D_channelModes.constBegin(); + while(D_iter != _D_channelModes.constEnd()) { + modeString += *D_iter; + D_iter++; + } + + QHash::const_iterator BC_iter = _C_channelModes.constBegin(); + while(BC_iter != _C_channelModes.constEnd()) { + modeString += BC_iter.key(); + params << BC_iter.value(); + BC_iter++; + } + + BC_iter = _B_channelModes.constBegin(); + while(BC_iter != _B_channelModes.constEnd()) { + modeString += BC_iter.key(); + params << BC_iter.value(); + BC_iter++; + } + if(modeString.isEmpty()) + return modeString; + else + return QString("+%1 %2").arg(modeString).arg(params.join(" ")); +}