File indexing completed on 2024-12-22 05:16:05

0001 /*
0002     SPDX-FileCopyrightText: 2019 Nicolas Fella <nicolas.fella@gmx.de>
0003     SPDX-FileCopyrightText: 2020 Carson Black <uhhadd@gmail.com>
0004 
0005     SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
0006 */
0007 
0008 #include "usermodel.h"
0009 
0010 #include <KLocalizedString>
0011 #include <QDBusInterface>
0012 #include <QDBusPendingReply>
0013 #include <algorithm>
0014 
0015 #include "accounts_interface.h"
0016 #include "kcmusers_debug.h"
0017 
0018 UserModel::UserModel(QObject *parent)
0019     : QAbstractListModel(parent)
0020     , m_dbusInterface(new OrgFreedesktopAccountsInterface(QStringLiteral("org.freedesktop.Accounts"),
0021                                                           QStringLiteral("/org/freedesktop/Accounts"),
0022                                                           QDBusConnection::systemBus(),
0023                                                           this))
0024 {
0025     connect(m_dbusInterface, &OrgFreedesktopAccountsInterface::UserAdded, this, [this](const QDBusObjectPath &path) {
0026         User *user = new User(this);
0027         user->setPath(path);
0028         beginInsertRows(QModelIndex(), m_userList.size(), m_userList.size());
0029         m_userList.append(user);
0030         endInsertRows();
0031     });
0032 
0033     connect(m_dbusInterface, &OrgFreedesktopAccountsInterface::UserDeleted, this, [this](const QDBusObjectPath &path) {
0034         QList<User *> toRemove;
0035         for (int i = 0; i < m_userList.length(); i++) {
0036             if (m_userList[i]->path().path() == path.path()) {
0037                 toRemove << m_userList[i];
0038             }
0039         }
0040         for (auto user : toRemove) {
0041             auto index = m_userList.indexOf(user);
0042             beginRemoveRows(QModelIndex(), index, index);
0043             m_userList.removeOne(user);
0044             endRemoveRows();
0045         }
0046     });
0047 
0048     auto reply = m_dbusInterface->ListCachedUsers();
0049     reply.waitForFinished();
0050 
0051     if (reply.isError()) {
0052         qCWarning(KCMUSERS) << reply.error().message();
0053         return;
0054     }
0055 
0056     const QList<QDBusObjectPath> users = reply.value();
0057     for (const QDBusObjectPath &path : users) {
0058         User *user = new User(this);
0059         user->setPath(path);
0060 
0061         const std::list<QPair<void (User::*const)(), int>> set = {
0062             {&User::uidChanged, UidRole},
0063             {&User::nameChanged, NameRole},
0064             {&User::displayNamesChanged, DisplayPrimaryNameRole},
0065             {&User::displayNamesChanged, DisplaySecondaryNameRole},
0066             {&User::faceValidChanged, FaceValidRole},
0067             {&User::realNameChanged, RealNameRole},
0068             {&User::emailChanged, EmailRole},
0069             {&User::administratorChanged, AdministratorRole},
0070         };
0071 
0072         for (const auto &item : set) {
0073             const auto role = item.second;
0074             connect(user, item.first, this, [this, user, role] {
0075                 auto idx = index(m_userList.lastIndexOf(user));
0076                 Q_EMIT dataChanged(idx, idx, {role});
0077             });
0078         }
0079 
0080         m_userList.append(user);
0081     }
0082     std::sort(m_userList.begin(), m_userList.end(), [](User *lhs, User *) {
0083         return lhs->loggedIn();
0084     });
0085 }
0086 
0087 QHash<int, QByteArray> UserModel::roleNames() const
0088 {
0089     QHash<int, QByteArray> names = QAbstractItemModel::roleNames();
0090     names.insert(UidRole, "uid");
0091     names.insert(NameRole, "name");
0092     names.insert(DisplayPrimaryNameRole, "displayPrimaryName");
0093     names.insert(DisplaySecondaryNameRole, "displaySecondaryName");
0094     names.insert(EmailRole, "email");
0095     names.insert(AdministratorRole, "administrator");
0096     names.insert(UserRole, "userObject");
0097     names.insert(FaceValidRole, "faceValid");
0098     names.insert(LoggedInRole, "loggedIn");
0099     names.insert(SectionHeaderRole, "sectionHeader");
0100     return names;
0101 }
0102 
0103 UserModel::~UserModel()
0104 {
0105 }
0106 
0107 User *UserModel::getLoggedInUser() const
0108 {
0109     for (const auto user : std::as_const(m_userList)) {
0110         if (user->loggedIn()) {
0111             return user;
0112         }
0113     }
0114     return nullptr;
0115 }
0116 
0117 QVariant UserModel::data(const QModelIndex &index, int role) const
0118 {
0119     if (!checkIndex(index)) {
0120         return QVariant();
0121     }
0122 
0123     User *user = m_userList.at(index.row());
0124 
0125     switch (role) {
0126     case NameRole:
0127         return user->name();
0128     case FaceRole:
0129         return user->face().toString();
0130     case RealNameRole:
0131         return user->realName();
0132     case DisplayPrimaryNameRole:
0133         return user->displayPrimaryName();
0134     case DisplaySecondaryNameRole:
0135         return user->displaySecondaryName();
0136     case EmailRole:
0137         return user->email();
0138     case AdministratorRole:
0139         return user->administrator();
0140     case FaceValidRole:
0141         return QFile::exists(user->face().toString());
0142     case UserRole:
0143         return QVariant::fromValue(user);
0144     case LoggedInRole:
0145         return user->loggedIn();
0146     case SectionHeaderRole:
0147         return user->loggedIn() ? i18n("Your Account") : i18n("Other Accounts");
0148     }
0149 
0150     return QVariant();
0151 }
0152 
0153 int UserModel::rowCount(const QModelIndex &parent) const
0154 {
0155     if (parent.isValid()) {
0156         // Return size 0 if we are a child because this is not a tree
0157         return 0;
0158     }
0159 
0160     return m_userList.count();
0161 }