+
+QVariant ChannelBufferItem::data(int column, int role) const
+{
+ switch (role) {
+ case NetworkModel::IrcChannelRole:
+ return QVariant::fromValue<QObject *>(_ircChannel);
+ default:
+ return BufferItem::data(column, role);
+ }
+}
+
+
+QString ChannelBufferItem::toolTip(int column) const
+{
+ Q_UNUSED(column);
+ QStringList toolTip;
+
+ toolTip.append(tr("<b>Channel %1</b>").arg(Qt::escape(bufferName())));
+ if (isActive()) {
+ //TODO: add channel modes
+ toolTip.append(tr("<b>Users:</b> %1").arg(nickCount()));
+ if (_ircChannel) {
+ QString channelMode = _ircChannel->channelModeString(); // channelModeString is compiled on the fly -> thus cache the result
+ if (!channelMode.isEmpty())
+ toolTip.append(tr("<b>Mode:</b> %1").arg(channelMode));
+ }
+
+ ItemViewSettings s;
+ bool showTopic = s.displayTopicInTooltip();
+ if (showTopic) {
+ QString _topic = topic();
+ if (_topic != "") {
+ _topic = stripFormatCodes(_topic);
+ _topic = Qt::escape(_topic);
+ toolTip.append(QString("<font size='-2'> </font>"));
+ toolTip.append(tr("<b>Topic:</b> %1").arg(_topic));
+ }
+ }
+ }
+ else {
+ toolTip.append(tr("Not active <br /> Double-click to join"));
+ }
+
+ return tr("<p> %1 </p>").arg(toolTip.join("<br />"));
+}
+
+
+void ChannelBufferItem::attachIrcChannel(IrcChannel *ircChannel)
+{
+ Q_ASSERT(!_ircChannel && ircChannel);
+
+ _ircChannel = ircChannel;
+
+ connect(ircChannel, SIGNAL(topicSet(QString)),
+ this, SLOT(setTopic(QString)));
+ connect(ircChannel, SIGNAL(encryptedSet(bool)),
+ this, SLOT(setEncrypted(bool)));
+ connect(ircChannel, SIGNAL(ircUsersJoined(QList<IrcUser *> )),
+ this, SLOT(join(QList<IrcUser *> )));
+ connect(ircChannel, SIGNAL(ircUserParted(IrcUser *)),
+ this, SLOT(part(IrcUser *)));
+ connect(ircChannel, SIGNAL(parted()),
+ this, SLOT(ircChannelParted()));
+ connect(ircChannel, SIGNAL(ircUserModesSet(IrcUser *, QString)),
+ this, SLOT(userModeChanged(IrcUser *)));
+ connect(ircChannel, SIGNAL(ircUserModeAdded(IrcUser *, QString)),
+ this, SLOT(userModeChanged(IrcUser *)));
+ connect(ircChannel, SIGNAL(ircUserModeRemoved(IrcUser *, QString)),
+ this, SLOT(userModeChanged(IrcUser *)));
+
+ if (!ircChannel->ircUsers().isEmpty())
+ join(ircChannel->ircUsers());
+
+ emit dataChanged();
+}
+
+
+void ChannelBufferItem::ircChannelParted()
+{
+ Q_CHECK_PTR(_ircChannel);
+ disconnect(_ircChannel, 0, this, 0);
+ _ircChannel = 0;
+ emit dataChanged();
+ removeAllChilds();
+}
+
+
+void ChannelBufferItem::join(const QList<IrcUser *> &ircUsers)
+{
+ addUsersToCategory(ircUsers);
+ emit dataChanged(2);
+}
+
+
+UserCategoryItem *ChannelBufferItem::findCategoryItem(int categoryId)
+{
+ UserCategoryItem *categoryItem = 0;
+
+ for (int i = 0; i < childCount(); i++) {
+ categoryItem = qobject_cast<UserCategoryItem *>(child(i));
+ if (!categoryItem)
+ continue;
+ if (categoryItem->categoryId() == categoryId)
+ return categoryItem;
+ }
+ return 0;
+}
+
+
+void ChannelBufferItem::addUserToCategory(IrcUser *ircUser)
+{
+ addUsersToCategory(QList<IrcUser *>() << ircUser);
+}
+
+
+void ChannelBufferItem::addUsersToCategory(const QList<IrcUser *> &ircUsers)
+{
+ Q_ASSERT(_ircChannel);
+
+ QHash<UserCategoryItem *, QList<IrcUser *> > categories;
+
+ int categoryId = -1;
+ UserCategoryItem *categoryItem = 0;
+
+ foreach(IrcUser *ircUser, ircUsers) {
+ categoryId = UserCategoryItem::categoryFromModes(_ircChannel->userModes(ircUser));
+ categoryItem = findCategoryItem(categoryId);
+ if (!categoryItem) {
+ categoryItem = new UserCategoryItem(categoryId, this);
+ categories[categoryItem] = QList<IrcUser *>();
+ newChild(categoryItem);
+ }
+ categories[categoryItem] << ircUser;
+ }
+
+ QHash<UserCategoryItem *, QList<IrcUser *> >::const_iterator catIter = categories.constBegin();
+ while (catIter != categories.constEnd()) {
+ catIter.key()->addUsers(catIter.value());
+ catIter++;
+ }
+}
+
+
+void ChannelBufferItem::part(IrcUser *ircUser)
+{
+ if (!ircUser) {
+ qWarning() << bufferName() << "ChannelBufferItem::part(): unknown User" << ircUser;
+ return;
+ }
+
+ disconnect(ircUser, 0, this, 0);
+ removeUserFromCategory(ircUser);
+ emit dataChanged(2);
+}
+
+
+void ChannelBufferItem::removeUserFromCategory(IrcUser *ircUser)
+{
+ if (!_ircChannel) {
+ // If we parted the channel there might still be some ircUsers connected.
+ // in that case we just ignore the call
+ Q_ASSERT(childCount() == 0);
+ return;
+ }
+
+ UserCategoryItem *categoryItem = 0;
+ for (int i = 0; i < childCount(); i++) {
+ categoryItem = qobject_cast<UserCategoryItem *>(child(i));
+ if (categoryItem->removeUser(ircUser)) {
+ if (categoryItem->childCount() == 0)
+ removeChild(i);
+ break;
+ }
+ }
+}
+
+
+void ChannelBufferItem::userModeChanged(IrcUser *ircUser)
+{
+ Q_ASSERT(_ircChannel);
+
+ int categoryId = UserCategoryItem::categoryFromModes(_ircChannel->userModes(ircUser));
+ UserCategoryItem *categoryItem = findCategoryItem(categoryId);
+
+ if (categoryItem) {
+ if (categoryItem->findIrcUser(ircUser)) {
+ return; // already in the right category;
+ }
+ }
+ else {
+ categoryItem = new UserCategoryItem(categoryId, this);
+ newChild(categoryItem);
+ }
+
+ // find the item that needs reparenting
+ IrcUserItem *ircUserItem = 0;
+ for (int i = 0; i < childCount(); i++) {
+ UserCategoryItem *oldCategoryItem = qobject_cast<UserCategoryItem *>(child(i));
+ Q_ASSERT(oldCategoryItem);
+ IrcUserItem *userItem = oldCategoryItem->findIrcUser(ircUser);
+ if (userItem) {
+ ircUserItem = userItem;
+ break;
+ }
+ }
+
+ if (!ircUserItem) {
+ qWarning() << "ChannelBufferItem::userModeChanged(IrcUser *): unable to determine old category of" << ircUser;
+ return;
+ }
+ ircUserItem->reParent(categoryItem);
+}
+
+