+
+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);
+ QString strTooltip;
+ QTextStream tooltip( &strTooltip, QIODevice::WriteOnly );
+ tooltip << "<qt><style>.bold { font-weight: bold; }</style>"
+ << "<qt><style>.italic { font-style: italic; }</style>";
+
+ // Function to add a row to the tooltip table
+ auto addRow = [&](const QString& key, const QString& value, bool condition) {
+ if (condition) {
+ tooltip << "<tr><td class='bold' align='right'>" << key << "</td><td>" << value << "</td></tr>";
+ }
+ };
+
+ tooltip << "<p class='bold' align='center'>";
+ tooltip << NetworkItem::escapeHTML(tr("Channel %1").arg(bufferName()), true) << "</p>";
+
+ if (isActive()) {
+ tooltip << "<table cellspacing='5' cellpadding='0'>";
+ addRow(tr("Users"), QString::number(nickCount()), true);
+
+ if (_ircChannel) {
+ QString channelMode = _ircChannel->channelModeString(); // channelModeString is compiled on the fly -> thus cache the result
+ if (!channelMode.isEmpty())
+ addRow(tr("Mode"), channelMode, true);
+ }
+
+ ItemViewSettings s;
+ bool showTopic = s.displayTopicInTooltip();
+ if (showTopic) {
+ QString _topic = topic();
+ if (_topic != "") {
+ _topic = stripFormatCodes(_topic);
+ _topic = NetworkItem::escapeHTML(_topic);
+ addRow(tr("Topic"), _topic, true);
+ }
+ }
+
+ tooltip << "</table>";
+ } else {
+ tooltip << "<p class='italic'>" << tr("Not active, double-click to join") << "</p>";
+ }
+
+ tooltip << "</qt>";
+ return strTooltip;
+}
+
+
+void ChannelBufferItem::attachIrcChannel(IrcChannel *ircChannel)
+{
+ if (_ircChannel) {
+ qWarning() << Q_FUNC_INFO << "IrcChannel already set; cleanup failed!?";
+ disconnect(_ircChannel, 0, this, 0);
+ }
+
+ _ircChannel = ircChannel;
+
+ connect(ircChannel, SIGNAL(destroyed(QObject*)),
+ this, SLOT(ircChannelDestroyed()));
+ 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();
+}
+
+QString ChannelBufferItem::nickChannelModes(const QString &nick) const
+{
+ if (!_ircChannel) {
+ qDebug() << Q_FUNC_INFO << "IrcChannel not set, can't get user modes";
+ return QString();
+ }
+
+ return _ircChannel->userModes(nick);
+}
+
+
+void ChannelBufferItem::ircChannelParted()
+{
+ Q_CHECK_PTR(_ircChannel);
+ disconnect(_ircChannel, 0, this, 0);
+ _ircChannel = 0;
+ emit dataChanged();
+ removeAllChilds();
+}
+
+
+void ChannelBufferItem::ircChannelDestroyed()
+{
+ if (_ircChannel) {
+ _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);
+}
+
+