void ContactListModel::Private::removeContact(PsiContact *contact) { Q_ASSERT(monitoredContacts.contains(contact)); if (!monitoredContacts.contains(contact)) return; while (monitoredContacts.contains(contact)) { QModelIndex index = monitoredContacts.take(contact); if (!index.isValid()) { continue; } q->beginRemoveRows(index.parent(), index.row(), index.row()); ContactListItem *item = q->toItem(index); ContactListItem *group = item->parent(); delete item; q->endRemoveRows(); index = q->toModelIndex(group); // Delete empty group if (group->isGroup() && !group->childCount()) { q->beginRemoveRows(index.parent(), index.row(), index.row()); delete group; q->endRemoveRows(); } else { // Update group emit q->dataChanged(index, index); } } disconnect(contact, nullptr, this, nullptr); operationQueue.remove(contact); }
void ContactListModel::Private::clear() { q->beginResetModel(); // disconnect accounts. they have nothing to update here after clear for (const auto &child : q->root()->children()) { ContactListItem *item = static_cast<ContactListItem*>(child); if (item->isAccount()) { cleanUpAccount(item->account()); } } qDeleteAll(q->root()->children()); operationQueue.clear(); QHashIterator<PsiContact*, QPersistentModelIndex> it(monitoredContacts); while (it.hasNext()) { it.next(); disconnect(it.key(), nullptr, this, nullptr); } monitoredContacts.clear(); q->endResetModel(); }
PsiContact* ContactListModel::contactFor(const QModelIndex& index) const { ContactListItem *item = static_cast<ContactListItem*>(index.internalPointer()); if (item->type() != ContactListItem::Type::ContactType) return nullptr; return item->contact(); }
QVariant ContactListModel::data(const QModelIndex &index, int role) const { if (!index.isValid()) return QVariant(); ContactListItem* item = toItem(index); if (role == ContactListItemRole) return QVariant::fromValue(item); else return item->value(role); }
void ContactListModel::Private::updateAccount() { PsiAccount *account = qobject_cast<PsiAccount*>(sender()); if (account->enabled()) { ContactListItem *root = static_cast<ContactListItem*>(q->root());; ContactListItem *accountItem = root->findAccount(account); Q_ASSERT(accountItem); q->updateItem(accountItem); } else { cleanUpAccount(account); } }
void ContactListModel::Private::cleanUpAccount(PsiAccount *account) { disconnect(account, nullptr, this, nullptr); ContactListItem *root = static_cast<ContactListItem*>(q->root()); ContactListItem *item = root->findAccount(account); if (!item) { qCritical("BUG: account was already removed from the list"); return; } QModelIndex index = q->toModelIndex(item); q->beginRemoveRows(index.parent(), index.row(), index.row()); delete item; q->endRemoveRows(); }
/** * Returns the item flags for the given \param index in the model. */ Qt::ItemFlags ContactListModel::flags(const QModelIndex &index) const { if (!index.isValid()) return Qt::ItemIsDropEnabled; Qt::ItemFlags f = QAbstractItemModel::flags(index); f |= Qt::ItemIsSelectable | Qt::ItemIsEnabled; ContactListItem *item = toItem(index); if ((index.column() == NameColumn) && item && item->isEditable()) f |= Qt::ItemIsEditable; if (!item->isExpandable()) f |= Qt::ItemNeverHasChildren; return f; }
void ContactListModel::Private::contactUpdated() { PsiContact *contact = qobject_cast<PsiContact*>(sender()); Q_ASSERT(monitoredContacts.contains(contact)); if (!monitoredContacts.contains(contact)) return; // Check for groups changing // Maybe very difficult and should be simplified? QList<ContactListItem*> groupItems; for (const QPersistentModelIndex &index: monitoredContacts.values(contact)) { ContactListItem *item = q->toItem(index); ContactListItem *parent = item->parent(); if (parent && parent->isGroup()) { groupItems << parent; } } Operation operation = Operation::UpdateContact; ContactListItem::SpecialGroupType specialGroupType = specialGroupFor(contact); if (specialGroupType == ContactListItem::SpecialGroupType::NoneSpecialGroupType) { QStringList groups1; for (ContactListItem *item: groupItems) { groups1 << item->name(); } groups1.sort(); QStringList groups2 = contact->groups(); groups2.sort(); if (groups1 != groups2) { operation = Operation::ContactGroupsChanged; } } else if (groupItems.size() > 1 || (!groupItems.isEmpty() && groupItems.first()->specialGroupType() != specialGroupType)) { operation = Operation::ContactGroupsChanged; } addOperation(contact, operation); }
void ContactList::addContact(const QString &contactName, const QPixmap &pixmap) { ContactListItem *contact = new ContactListItem(d->mFrame); contact->setName(contactName); contact->setPixmap(pixmap); contact->setPos(0.0, d->mFrame->contentRect().height()); d->mFrame->setContentRect(QRectF(0.0, boundingRect().y(), contact->boundingRect().width(), d->mFrame->contentRect().height() + contact->boundingRect().height())); d->mContacts.append(contact); }
bool ContactListProxyModel::filterAcceptsRow(int sourceRow, const QModelIndex& sourceParent) const { QModelIndex index = sourceModel()->index(sourceRow, 0, sourceParent); if (!index.isValid()) return false; ContactListItemProxy* itemProxy = static_cast<ContactListItemProxy*>(index.internalPointer()); ContactListItem* item = itemProxy ? itemProxy->item() : 0; if (!item) { Q_ASSERT(false); return false; } if (item->editing()) { return true; } switch (ContactListModel::indexType(index)) { case ContactListModel::ContactType: { PsiContact* psiContact = dynamic_cast<PsiContact*>(item); if (psiContact->isHidden()) { return false; } if (psiContact->isSelf()) { return showSelf(); } else if (psiContact->isAgent()) { return showTransports(); } if (!showOffline()) { return psiContact->isOnline(); } else { return true; } } case ContactListModel::GroupType: { ContactListGroup::SpecialType specialGroupType = static_cast<ContactListGroup::SpecialType>(index.data(ContactListModel::SpecialGroupTypeRole).toInt()); if (specialGroupType != ContactListGroup::SpecialType_None) { if (specialGroupType == ContactListGroup::SpecialType_Transports) return showTransports(); } if (!showOffline()) { ContactListGroup* group = dynamic_cast<ContactListGroup*>(item); return group->haveOnlineContacts(); } else { return true; } } case ContactListModel::AccountType: return true; case ContactListModel::InvalidType: return true; default: Q_ASSERT(false); } return true; }
void ContactListModel::Private::realAddContact(PsiContact *contact) { ContactListItem *root = static_cast<ContactListItem*>(q->root());; if (accountsEnabled) { PsiAccount *account = contact->account(); ContactListItem *accountItem = root->findAccount(account); if (!accountItem) { accountItem = new ContactListItem(q, ContactListItem::Type::AccountType); accountItem->setAccount(account); accountItem->setExpanded(!collapsed.contains(accountItem->internalName())); connect(account, SIGNAL(accountDestroyed()), SLOT(onAccountDestroyed())); connect(account, SIGNAL(updatedAccount()), SLOT(updateAccount())); root->appendChild(accountItem); } root = accountItem; } if (!contact->isSelf() && groupsEnabled) { ContactListItem::SpecialGroupType specialGroupType = specialGroupFor(contact); QStringList groups = specialGroupType == ContactListItem::SpecialGroupType::NoneSpecialGroupType ? contact->groups() : QStringList{QString()}; for (const QString &groupName: groups) { ContactListItem *groupItem = nullptr; if (specialGroupType == ContactListItem::SpecialGroupType::NoneSpecialGroupType) groupItem = root->findGroup(groupName); else groupItem = root->findGroup(specialGroupType); // No duplicates if (groupItem && groupItem->findContact(contact)) { continue; } ContactListItem *item = new ContactListItem(q, ContactListItem::Type::ContactType); item->setContact(contact); if (!groupItem) { groupItem = new ContactListItem(q, ContactListItem::Type::GroupType, specialGroupType); if (specialGroupType == ContactListItem::SpecialGroupType::NoneSpecialGroupType) groupItem->setName(groupName); root->appendChild(groupItem); groupItem->setExpanded(!collapsed.contains(groupItem->internalName())); groupItem->setHidden(hidden.contains(groupItem->internalName())); } groupItem->appendChild(item); monitoredContacts.insertMulti(contact, q->toModelIndex(item)); } } else { ContactListItem *item = new ContactListItem(q, ContactListItem::Type::ContactType); item->setContact(contact); root->appendChild(item); monitoredContacts.insertMulti(contact, q->toModelIndex(item)); } connect(contact, SIGNAL(destroyed(PsiContact*)), SLOT(removeContact(PsiContact*))); connect(contact, SIGNAL(groupsChanged()), SLOT(contactGroupsChanged())); connect(contact, SIGNAL(updated()), SLOT(contactUpdated())); connect(contact, SIGNAL(alert()), SLOT(contactUpdated())); connect(contact, SIGNAL(anim()), SLOT(contactUpdated())); }
bool ContactListModel::setData(const QModelIndex &index, const QVariant &data, int role) { if (!index.isValid()) return false; ContactListItem *item = toItem(index); if (!item) return false; PsiContact *contact = item->isContact() ? item->contact() : nullptr; if (role == ActivateRole) { if (!contact) return false; contact->activate(); return true; } else if (role == Qt::EditRole) { QString name = data.toString(); if (contact) { item->setName(name); emit dataChanged(index, index); } else if (item->isGroup() && !name.isEmpty()) { QString oldName = item->name(); QList<PsiContact*> contacts; for (int i = 0; i < item->childCount(); ++i) { if (item->child(i)->isContact()) contacts << item->child(i)->contact(); } for (PsiContact *contact: contacts) { QStringList groups = contact->groups(); groups.removeOne(oldName); groups << name; contact->setGroups(groups); } } return true; } else if (role == ExpandedRole) { if (!item->isContact()) { item->setExpanded(data.toBool()); } } return true; }