From 56607f81246f04db3a0e71c9a8757d7f75d6cfcf Mon Sep 17 00:00:00 2001 From: Marcus Eggenberger Date: Sat, 1 Mar 2008 22:08:48 +0000 Subject: [PATCH 1/1] Yet another protocol break (I warned you...). Major speed improvement when joining channels. Please let me know if you notice any weird issues. --- src/client/networkmodel.cpp | 61 +++++++++++++++++++---------------- src/client/networkmodel.h | 5 +-- src/client/treemodel.cpp | 29 +++++++++++++++++ src/client/treemodel.h | 1 + src/common/ircchannel.cpp | 53 ++++++++++++++++++++++++++---- src/common/ircchannel.h | 9 ++++-- src/common/ircuser.cpp | 7 ++-- src/common/ircuser.h | 2 +- src/common/network.cpp | 1 + src/common/network.h | 1 + src/core/ircserverhandler.cpp | 18 ++++++++--- version.inc | 2 +- 12 files changed, 141 insertions(+), 48 deletions(-) diff --git a/src/client/networkmodel.cpp b/src/client/networkmodel.cpp index 94d90b8d..0582d44c 100644 --- a/src/client/networkmodel.cpp +++ b/src/client/networkmodel.cpp @@ -131,8 +131,8 @@ void BufferItem::attachIrcChannel(IrcChannel *ircChannel) { connect(ircChannel, SIGNAL(topicSet(QString)), this, SLOT(setTopic(QString))); - connect(ircChannel, SIGNAL(ircUserJoined(IrcUser *)), - this, SLOT(join(IrcUser *))); + connect(ircChannel, SIGNAL(ircUsersJoined(QList)), + this, SLOT(join(QList))); connect(ircChannel, SIGNAL(ircUserParted(IrcUser *)), this, SLOT(part(IrcUser *))); connect(ircChannel, SIGNAL(destroyed()), @@ -146,9 +146,7 @@ void BufferItem::attachIrcChannel(IrcChannel *ircChannel) { if(!ircChannel->ircUsers().isEmpty()) { qWarning() << "Channel" << ircChannel->name() << "has already users which is quite surprising :)"; - foreach(IrcUser *ircUser, ircChannel->ircUsers()) { - join(ircUser); - } + join(ircChannel->ircUsers()); } emit dataChanged(); @@ -200,30 +198,41 @@ void BufferItem::setTopic(const QString &topic) { emit dataChanged(1); } -void BufferItem::join(IrcUser *ircUser) { - if(!ircUser) - return; +void BufferItem::join(const QList &ircUsers) { + addUsersToCategory(ircUsers); - addUserToCategory(ircUser); - connect(ircUser, SIGNAL(destroyed()), - this, SLOT(ircUserDestroyed())); + foreach(IrcUser *ircUser, ircUsers) { + if(!ircUser) + continue; + connect(ircUser, SIGNAL(destroyed()), this, SLOT(ircUserDestroyed())); + } + emit dataChanged(2); } void BufferItem::addUserToCategory(IrcUser *ircUser) { + addUsersToCategory(QList() << ircUser); +} + +void BufferItem::addUsersToCategory(const QList &ircUsers) { Q_ASSERT(_ircChannel); - UserCategoryItem *categoryItem; - int categoryId = UserCategoryItem::categoryFromModes(_ircChannel->userModes(ircUser)); - if(!(categoryItem = qobject_cast(childById(qHash(categoryId))))) { - categoryItem = new UserCategoryItem(categoryId, this); - newChild(categoryItem); + QHash > categories; + foreach(IrcUser *ircUser, ircUsers) { + UserCategoryItem *categoryItem; + int categoryId = UserCategoryItem::categoryFromModes(_ircChannel->userModes(ircUser)); + if(!(categoryItem = qobject_cast(childById(qHash(categoryId))))) { + categoryItem = new UserCategoryItem(categoryId, this); + categories[categoryItem] = QList(); + newChild(categoryItem); + } + categories[categoryItem] << ircUser; } - categoryItem->addUser(ircUser); - int totalusers = 0; - for(int i = 0; i < childCount(); i++) { - totalusers += child(i)->childCount(); + QHash >::const_iterator catIter = categories.constBegin(); + while(catIter != categories.constEnd()) { + catIter.key()->addUsers(catIter.value()); + catIter++; } } @@ -267,11 +276,6 @@ void BufferItem::removeUserFromCategory(IrcUser *ircUser) { qDebug() << "==== End Of Childlist for Item:" << this << id() << bufferName() << "===="; } Q_ASSERT(success); - - int totalusers = 0; - for(int i = 0; i < childCount(); i++) { - totalusers += child(i)->childCount(); - } } void BufferItem::userModeChanged(IrcUser *ircUser) { @@ -496,8 +500,11 @@ quint64 UserCategoryItem::id() const { return qHash(_category); } -void UserCategoryItem::addUser(IrcUser *ircUser) { - newChild(new IrcUserItem(ircUser, this)); +void UserCategoryItem::addUsers(const QList &ircUsers) { + QList userItems; + foreach(IrcUser *ircUser, ircUsers) + userItems << new IrcUserItem(ircUser, this); + newChilds(userItems); } bool UserCategoryItem::removeUser(IrcUser *ircUser) { diff --git a/src/client/networkmodel.h b/src/client/networkmodel.h index 208503c8..d9598c94 100644 --- a/src/client/networkmodel.h +++ b/src/client/networkmodel.h @@ -81,10 +81,11 @@ public: public slots: void setTopic(const QString &topic); - void join(IrcUser *ircUser); + void join(const QList &ircUsers); void part(IrcUser *ircUser); void addUserToCategory(IrcUser *ircUser); + void addUsersToCategory(const QList &ircUser); void removeUserFromCategory(IrcUser *ircUser); void userModeChanged(IrcUser *ircUser); @@ -152,7 +153,7 @@ public: virtual quint64 id() const; virtual QVariant data(int column, int role) const; - void addUser(IrcUser *ircUser); + void addUsers(const QList &ircUser); bool removeUser(IrcUser *ircUser); static int categoryFromModes(const QString &modes); diff --git a/src/client/treemodel.cpp b/src/client/treemodel.cpp index 9a01abf4..d66cc3a9 100644 --- a/src/client/treemodel.cpp +++ b/src/client/treemodel.cpp @@ -51,6 +51,35 @@ bool AbstractTreeItem::newChild(AbstractTreeItem *item) { return true; } +bool AbstractTreeItem::newChilds(const QList &items) { + if(items.isEmpty()) + return false; + + QList::const_iterator itemIter = items.constBegin(); + AbstractTreeItem *item; + while(itemIter != items.constEnd()) { + item = *itemIter; + if(childById(item->id()) != 0) { + qWarning() << "AbstractTreeItem::newChilds(): received child that is already attached" << item << item->id(); + return false; + } + itemIter++; + } + + int nextRow = childCount(); + int lastRow = nextRow + items.count() - 1; + + emit beginAppendChilds(nextRow, lastRow); + itemIter = items.constBegin(); + while(itemIter != items.constEnd()) { + _childItems.append(*itemIter); + itemIter++; + } + emit endAppendChilds(); + + return true; +} + bool AbstractTreeItem::removeChild(int row) { if(childCount() <= row) return false; diff --git a/src/client/treemodel.h b/src/client/treemodel.h index 6eef89f1..3a1c144e 100644 --- a/src/client/treemodel.h +++ b/src/client/treemodel.h @@ -41,6 +41,7 @@ public: virtual ~AbstractTreeItem(); bool newChild(AbstractTreeItem *child); + bool newChilds(const QList &items); bool removeChild(int row); bool removeChildById(const quint64 &id); diff --git a/src/common/ircchannel.cpp b/src/common/ircchannel.cpp index 832a5a99..eb63dd57 100644 --- a/src/common/ircchannel.cpp +++ b/src/common/ircchannel.cpp @@ -125,21 +125,62 @@ void IrcChannel::setPassword(const QString &password) { emit passwordSet(password); } -void IrcChannel::join(IrcUser *ircuser) { - if(!_userModes.contains(ircuser) && ircuser) { - _userModes[ircuser] = QString(); +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::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::join(const QString &nick) { - join(network->ircUser(nick)); +void IrcChannel::joinIrcUsers(const QString &nick) { + joinIrcUsers(network->newIrcUser(nick)); } void IrcChannel::part(IrcUser *ircuser) { diff --git a/src/common/ircchannel.h b/src/common/ircchannel.h index dfc8de05..26340ce6 100644 --- a/src/common/ircchannel.h +++ b/src/common/ircchannel.h @@ -69,8 +69,10 @@ public slots: void setTopic(const QString &topic); void setPassword(const QString &password); - void join(IrcUser *ircuser); - void join(const QString &nick); + void joinIrcUsers(const QList &users, const QStringList &modes); + void joinIrcUsers(const QStringList &nicks, const QStringList &modes); + void joinIrcUsers(IrcUser *ircuser); + void joinIrcUsers(const QString &nick); void part(IrcUser *ircuser); void part(const QString &nick); @@ -100,7 +102,8 @@ signals: void userModeRemoved(QString nick, QString mode); //void userModeRemoved(IrcUser *ircuser, QString mode); - void ircUserJoined(IrcUser *ircuser); + void ircUsersJoined(QList ircusers); + void ircUsersJoined(QStringList nicks, QStringList modes); void ircUserParted(IrcUser *ircuser); void ircUserNickSet(IrcUser *ircuser, QString nick); void ircUserModeAdded(IrcUser *ircuser, QString mode); diff --git a/src/common/ircuser.cpp b/src/common/ircuser.cpp index efa75415..4c12580d 100644 --- a/src/common/ircuser.cpp +++ b/src/common/ircuser.cpp @@ -243,9 +243,8 @@ void IrcUser::joinChannel(IrcChannel *channel) { Q_ASSERT(channel); if(!_channels.contains(channel)) { _channels.insert(channel); - channel->join(this); + channel->joinIrcUsers(this); connect(channel, SIGNAL(destroyed()), this, SLOT(channelDestroyed())); - emit channelJoined(channel->name()); } } @@ -259,7 +258,7 @@ void IrcUser::partChannel(IrcChannel *channel) { disconnect(channel, 0, this, 0); channel->part(this); emit channelParted(channel->name()); - if(_channels.isEmpty()) + if(_channels.isEmpty() && network()->isMe(this)) deleteLater(); } } @@ -278,6 +277,8 @@ void IrcUser::channelDestroyed() { IrcChannel *channel = static_cast(sender()); if(_channels.contains(channel)) { _channels.remove(channel); + if(_channels.isEmpty()) + deleteLater(); } } diff --git a/src/common/ircuser.h b/src/common/ircuser.h index 3235158d..176e36ee 100644 --- a/src/common/ircuser.h +++ b/src/common/ircuser.h @@ -123,7 +123,7 @@ signals: void userModesSet(QString modes); - void channelJoined(QString channel); + // void channelJoined(QString channel); void channelParted(QString channel); void userModeAdded(QString mode); diff --git a/src/common/network.cpp b/src/common/network.cpp index c7343ca3..2fbde1e3 100644 --- a/src/common/network.cpp +++ b/src/common/network.cpp @@ -290,6 +290,7 @@ IrcUser *Network::newIrcUser(const QString &hostmask) { connect(ircuser, SIGNAL(nickSet(QString)), this, SLOT(ircUserNickChanged(QString))); connect(ircuser, SIGNAL(initDone()), this, SLOT(ircUserInitDone())); + connect(ircuser, SIGNAL(destroyed()), this, SLOT(ircUserDestroyed())); _ircUsers[nick] = ircuser; emit ircUserAdded(hostmask); emit ircUserAdded(ircuser); diff --git a/src/common/network.h b/src/common/network.h index 2bdda21c..d065306b 100644 --- a/src/common/network.h +++ b/src/common/network.h @@ -181,6 +181,7 @@ public slots: void removeSupport(const QString ¶m); inline void addIrcUser(const QString &hostmask) { newIrcUser(hostmask); } + inline void addIrcChannel(const QString &channel) { newIrcChannel(channel); } void removeIrcUser(const QString &nick); void removeIrcChannel(const QString &channel); diff --git a/src/core/ircserverhandler.cpp b/src/core/ircserverhandler.cpp index e46bb737..ae92b093 100644 --- a/src/core/ircserverhandler.cpp +++ b/src/core/ircserverhandler.cpp @@ -558,6 +558,15 @@ void IrcServerHandler::handle353(const QString &prefix, const QList // we don't use this information at the time beeing QString channelname = serverDecode(params[1]); + IrcChannel *channel = network()->ircChannel(channelname); + if(!channel) { + qWarning() << "IrcServerHandler::handle353(): received unknown target channel:" << channelname; + return; + } + + QStringList nicks; + QStringList modes; + foreach(QString nick, serverDecode(params[2]).split(' ')) { QString mode = QString(); @@ -566,12 +575,11 @@ void IrcServerHandler::handle353(const QString &prefix, const QList nick = nick.mid(1); } - IrcUser *ircuser = network()->newIrcUser(nick); - ircuser->joinChannel(channelname); - - if(!mode.isNull()) - network()->ircChannel(channelname)->addUserMode(ircuser, mode); + nicks << nick; + modes << mode; } + + channel->joinIrcUsers(nicks, modes); } /* RPL_ENDOFWHOWAS - " :End of WHOWAS" */ diff --git a/version.inc b/version.inc index 7f0c1464..116c53b6 100644 --- a/version.inc +++ b/version.inc @@ -5,7 +5,7 @@ quasselVersion = "0.2.0-alpha3-pre"; quasselDate = "2008-03-01"; - quasselBuild = 606; + quasselBuild = 608; //! Minimum client build number the core needs clientBuildNeeded = 605; -- 2.20.1