+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
+ UserCategoryItem *oldCategoryItem = 0;
+ IrcUserItem *ircUserItem = 0;
+ for(int i = 0; i < childCount(); i++) {
+ UserCategoryItem *catItem = qobject_cast<UserCategoryItem *>(child(i));
+ IrcUserItem *userItem = catItem->findIrcUser(ircUser);
+ if(userItem) {
+ oldCategoryItem = catItem;
+ ircUserItem = userItem;
+ break;
+ }
+ }
+
+ if(!ircUserItem) {
+ qWarning() << "ChannelBufferItem::userModeChanged(IrcUser *): unable to determine old category of" << ircUser;
+ return;
+ }
+
+ Q_ASSERT(oldCategoryItem);
+ if(ircUserItem->reParent(categoryItem) && oldCategoryItem->childCount() == 0) {
+ removeChild(oldCategoryItem);
+ }
+}
+
+/*****************************************
+* User Category Items (like @vh etc.)
+*****************************************/
+// we hardcode this even though we have PREFIX in network... but that wouldn't help with mapping modes to
+// category strings anyway.
+const QList<QChar> UserCategoryItem::categories = QList<QChar>() << 'q' << 'a' << 'o' << 'h' << 'v';
+
+UserCategoryItem::UserCategoryItem(int category, AbstractTreeItem *parent)
+ : PropertyMapItem(QStringList() << "categoryName", parent),
+ _category(category)
+{
+ setObjectName(parent->data(0, Qt::DisplayRole).toString() + "/" + QString::number(category));
+}
+
+// caching this makes no sense, since we display the user number dynamically
+QString UserCategoryItem::categoryName() const {
+ int n = childCount();
+ switch(_category) {
+ case 0: return tr("%n Owner(s)", 0, n);
+ case 1: return tr("%n Admin(s)", 0, n);
+ case 2: return tr("%n Operator(s)", 0, n);
+ case 3: return tr("%n Half-Op(s)", 0, n);
+ case 4: return tr("%n Voiced", 0, n);
+ default: return tr("%n User(s)", 0, n);
+ }
+}
+
+IrcUserItem *UserCategoryItem::findIrcUser(IrcUser *ircUser) {
+ IrcUserItem *userItem = 0;
+
+ for(int i = 0; i < childCount(); i++) {
+ userItem = qobject_cast<IrcUserItem *>(child(i));
+ if(!userItem)
+ continue;
+ if(userItem->ircUser() == ircUser)
+ return userItem;
+ }
+ return 0;
+}
+
+void UserCategoryItem::addUsers(const QList<IrcUser *> &ircUsers) {
+ QList<AbstractTreeItem *> userItems;
+ foreach(IrcUser *ircUser, ircUsers)
+ userItems << new IrcUserItem(ircUser, this);
+ newChilds(userItems);