File indexing completed on 2024-04-28 05:11:38

0001 /*
0002  * SPDX-FileCopyrightText: 2014 Sandro Knauß <knauss@kolabsys.com>
0003  *
0004  * SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
0005  *
0006  */
0007 #include "resourcemodel.h"
0008 #include "ldaputils.h"
0009 
0010 #include <KEmailAddress>
0011 #include <QDebug>
0012 
0013 using namespace IncidenceEditorNG;
0014 
0015 ResourceModel::ResourceModel(const QStringList &headers, QObject *parent)
0016     : QAbstractItemModel(parent)
0017 {
0018     this->mHeaders = headers;
0019     mRootItem = ResourceItem::Ptr(new ResourceItem(KLDAPCore::LdapDN(), headers, KLDAPWidgets::LdapClient(0)));
0020     const QStringList attrs = QStringList() << KLDAPWidgets::LdapClientSearch::defaultAttributes() << QStringLiteral("uniqueMember");
0021     mLdapSearchCollections = new KLDAPWidgets::LdapClientSearch(attrs, this);
0022     mLdapSearch = new KLDAPWidgets::LdapClientSearch(headers, this);
0023 
0024     mLdapSearchCollections->setFilter(
0025         QStringLiteral("&(ou=Resources,*)(objectClass=kolabGroupOfUniqueNames)(objectclass=groupofurls)(!(objectclass=nstombstone))(mail=*)"
0026                        "(cn=%1)"));
0027     mLdapSearch->setFilter(
0028         QStringLiteral("&(objectClass=kolabSharedFolder)(kolabFolderType=event)(mail=*)"
0029                        "(|(cn=%1)(description=%1)(kolabDescAttribute=%1))"));
0030 
0031     connect(mLdapSearchCollections,
0032             qOverload<const KLDAPWidgets::LdapResultObject::List &>(&KLDAPWidgets::LdapClientSearch ::searchData),
0033             this,
0034             &ResourceModel::slotLDAPCollectionData);
0035     connect(mLdapSearch,
0036             qOverload<const KLDAPWidgets::LdapResultObject::List &>(&KLDAPWidgets::LdapClientSearch::searchData),
0037             this,
0038             &ResourceModel::slotLDAPSearchData);
0039 
0040     mLdapSearchCollections->startSearch(QStringLiteral("*"));
0041 }
0042 
0043 ResourceModel::~ResourceModel() = default;
0044 
0045 int ResourceModel::columnCount(const QModelIndex & /* parent */) const
0046 {
0047     return mRootItem->columnCount();
0048 }
0049 
0050 QVariant ResourceModel::data(const QModelIndex &index, int role) const
0051 {
0052     if (!index.isValid()) {
0053         return {};
0054     }
0055 
0056     if (role == Qt::EditRole || role == Qt::DisplayRole) {
0057         return getItem(index)->data(index.column());
0058     } else if (role == Resource) {
0059         ResourceItem *p = getItem(parent(index));
0060         return QVariant::fromValue(p->child(index.row()));
0061     } else if (role == FullName) {
0062         ResourceItem *item = getItem(index);
0063         return KEmailAddress::normalizedAddress(item->data(QStringLiteral("cn")).toString(), item->data(QStringLiteral("mail")).toString());
0064     }
0065 
0066     return {};
0067 }
0068 
0069 Qt::ItemFlags ResourceModel::flags(const QModelIndex &index) const
0070 {
0071     if (!index.isValid()) {
0072         return Qt::NoItemFlags;
0073     }
0074 
0075     return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
0076 }
0077 
0078 ResourceItem *ResourceModel::getItem(const QModelIndex &index) const
0079 {
0080     if (index.isValid()) {
0081         auto item = static_cast<ResourceItem *>(index.internalPointer());
0082         if (item) {
0083             return item;
0084         }
0085     }
0086     return mRootItem.data();
0087 }
0088 
0089 QVariant ResourceModel::headerData(int section, Qt::Orientation orientation, int role) const
0090 {
0091     if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
0092         return translateLDAPAttributeForDisplay(mRootItem->data(section).toString());
0093     }
0094 
0095     return {};
0096 }
0097 
0098 QModelIndex ResourceModel::index(int row, int column, const QModelIndex &parent) const
0099 {
0100     ResourceItem *parentItem = getItem(parent);
0101 
0102     ResourceItem::Ptr childItem = parentItem->child(row);
0103     if (row < parentItem->childCount() && childItem) {
0104         return createIndex(row, column, childItem.data());
0105     } else {
0106         return {};
0107     }
0108 }
0109 
0110 QModelIndex ResourceModel::parent(const QModelIndex &index) const
0111 {
0112     if (!index.isValid()) {
0113         return {};
0114     }
0115     ResourceItem *childItem = getItem(index);
0116     ResourceItem::Ptr parentItem = childItem->parent();
0117 
0118     if (parentItem == mRootItem) {
0119         return {};
0120     }
0121 
0122     return createIndex(parentItem->childNumber(), index.column(), parentItem.data());
0123 }
0124 
0125 bool ResourceModel::removeRows(int position, int rows, const QModelIndex &parent)
0126 {
0127     ResourceItem *parentItem = getItem(parent);
0128 
0129     beginRemoveRows(parent, position, position + rows - 1);
0130     bool success = parentItem->removeChildren(position, rows);
0131     endRemoveRows();
0132 
0133     return success;
0134 }
0135 
0136 int ResourceModel::rowCount(const QModelIndex &parent) const
0137 {
0138     ResourceItem *parentItem = getItem(parent);
0139 
0140     return parentItem->childCount();
0141 }
0142 
0143 void ResourceModel::startSearch(const QString &query)
0144 {
0145     mSearchString = query;
0146 
0147     if (mFoundCollection) {
0148         startSearch();
0149     }
0150 }
0151 
0152 void ResourceModel::startSearch()
0153 {
0154     // Delete all resources -> only collection elements are shown
0155     for (int i = 0; i < mRootItem->childCount(); ++i) {
0156         if (mLdapCollections.contains(mRootItem->child(i))) {
0157             QModelIndex parentIndex = index(i, 0, QModelIndex());
0158             beginRemoveRows(parentIndex, 0, mRootItem->child(i)->childCount() - 1);
0159             (void)mRootItem->child(i)->removeChildren(0, mRootItem->child(i)->childCount());
0160             endRemoveRows();
0161         } else {
0162             beginRemoveRows(QModelIndex(), i, i);
0163             (void)mRootItem->removeChildren(i, 1);
0164             endRemoveRows();
0165         }
0166     }
0167 
0168     if (mSearchString.isEmpty()) {
0169         mLdapSearch->startSearch(QStringLiteral("*"));
0170     } else {
0171         mLdapSearch->startSearch(QLatin1Char('*') + mSearchString + QLatin1Char('*'));
0172     }
0173 }
0174 
0175 void ResourceModel::slotLDAPCollectionData(const KLDAPWidgets::LdapResultObject::List &results)
0176 {
0177     Q_EMIT layoutAboutToBeChanged();
0178 
0179     mFoundCollection = true;
0180     mLdapCollectionsMap.clear();
0181     mLdapCollections.clear();
0182 
0183     // qDebug() <<  "Found ldapCollections";
0184 
0185     for (const KLDAPWidgets::LdapResultObject &result : std::as_const(results)) {
0186         ResourceItem::Ptr item(new ResourceItem(result.object.dn(), mHeaders, *result.client, mRootItem));
0187         item->setLdapObject(result.object);
0188 
0189         (void)mRootItem->insertChild(mRootItem->childCount(), item);
0190         mLdapCollections.insert(item);
0191 
0192         // Resources in a collection add this link into ldapCollectionsMap
0193         const auto members = result.object.attributes()[QStringLiteral("uniqueMember")];
0194         for (const QByteArray &member : members) {
0195             mLdapCollectionsMap.insert(QString::fromLatin1(member), item);
0196         }
0197     }
0198 
0199     Q_EMIT layoutChanged();
0200 
0201     startSearch();
0202 }
0203 
0204 void ResourceModel::slotLDAPSearchData(const KLDAPWidgets::LdapResultObject::List &results)
0205 {
0206     for (const KLDAPWidgets::LdapResultObject &result : std::as_const(results)) {
0207         // Add the found items to all collections, where it is member
0208         QList<ResourceItem::Ptr> parents = mLdapCollectionsMap.values(result.object.dn().toString());
0209         if (parents.isEmpty()) {
0210             parents << mRootItem;
0211         }
0212 
0213         for (const ResourceItem::Ptr &parent : std::as_const(parents)) {
0214             ResourceItem::Ptr item(new ResourceItem(result.object.dn(), mHeaders, *result.client, parent));
0215             item->setLdapObject(result.object);
0216 
0217             QModelIndex parentIndex;
0218             if (parent != mRootItem) {
0219                 parentIndex = index(parent->childNumber(), 0, parentIndex);
0220             }
0221             beginInsertRows(parentIndex, parent->childCount(), parent->childCount());
0222             (void)parent->insertChild(parent->childCount(), item);
0223             endInsertRows();
0224         }
0225     }
0226 }
0227 
0228 #include "moc_resourcemodel.cpp"