File indexing completed on 2024-04-21 12:27:52

0001 /*
0002  *  SPDX-FileCopyrightText: 2012 Alejandro Fiestas Olivares <afiestas@kde.org>
0003  *  SPDX-FileCopyrightText: 2020 Dan Leinir Turthra Jensen <admin@leinir.dk>
0004  *
0005  *  SPDX-License-Identifier: GPL-2.0-or-later
0006  */
0007 
0008 #include "accountsmodel.h"
0009 
0010 #include "core.h"
0011 #include "servicesmodel.h"
0012 
0013 #include <QDebug>
0014 
0015 #include <QIcon>
0016 #include <klocalizedstring.h>
0017 
0018 #include <SignOn/Identity>
0019 
0020 #include <Accounts/Account>
0021 #include <Accounts/Manager>
0022 
0023 namespace KAccounts
0024 {
0025 
0026 class AccountsModel::Private : public QObject
0027 {
0028 public:
0029     Private(AccountsModel *model)
0030         : accountsManager(KAccounts::accountsManager())
0031         , q(model)
0032     {
0033         accountIDs = accountsManager->accountList();
0034 
0035         connect(accountsManager, &Accounts::Manager::accountCreated, q, [this](Accounts::AccountId accountId) {
0036             int row = accountIDs.count();
0037             q->beginInsertRows(QModelIndex(), row, row);
0038             accountIDs.insert(row, accountId);
0039             q->endInsertRows();
0040         });
0041         connect(accountsManager, &Accounts::Manager::accountRemoved, q, [this](Accounts::AccountId accountId) {
0042             q->beginRemoveRows(QModelIndex(), accountIDs.indexOf(accountId), accountIDs.indexOf(accountId));
0043             removeAccount(accountId);
0044             q->endRemoveRows();
0045         });
0046     };
0047     virtual ~Private()
0048     {
0049         qDeleteAll(accounts);
0050     };
0051 
0052     Accounts::Manager *accountsManager;
0053     Accounts::AccountIdList accountIDs;
0054     QHash<int, Accounts::Account *> accounts;
0055     QHash<Accounts::Account *, ServicesModel *> servicesModels;
0056 
0057     Accounts::Account *accountById(int id);
0058     void removeAccount(Accounts::AccountId accountId);
0059 
0060 private:
0061     AccountsModel *q;
0062 };
0063 
0064 Accounts::Account *AccountsModel::Private::accountById(int id)
0065 {
0066     if (accounts.contains(id)) {
0067         return accounts.value(id);
0068     }
0069 
0070     // If we don't yet have this account cached, get it and connect it up to the model
0071     Accounts::Account *account = accountsManager->account(id);
0072     if (!account) {
0073         qDebug() << "\t Failed to get the account from manager";
0074         return nullptr;
0075     }
0076 
0077     connect(account, &Accounts::Account::displayNameChanged, q, [this, account]() {
0078         QModelIndex accountIndex = q->index(accountIDs.indexOf(account->id()));
0079         Q_EMIT q->dataChanged(accountIndex, accountIndex, QVector<int>() << AccountsModel::DisplayNameRole);
0080     });
0081 
0082     accounts[id] = account;
0083     return account;
0084 }
0085 
0086 void AccountsModel::Private::removeAccount(Accounts::AccountId accountId)
0087 {
0088     accountIDs.removeOne(accountId);
0089     delete accounts.take(accountId);
0090 }
0091 
0092 AccountsModel::AccountsModel(QObject *parent)
0093     : QAbstractListModel(parent)
0094     , d(new AccountsModel::Private(this))
0095 {
0096 }
0097 
0098 AccountsModel::~AccountsModel()
0099 {
0100     delete d;
0101 }
0102 
0103 QHash<int, QByteArray> AccountsModel::roleNames() const
0104 {
0105     static QHash<int, QByteArray> roles{
0106         {IdRole, "id"},
0107         {ServicesRole, "services"},
0108         {EnabledRole, "enabled"},
0109         {CredentialsIdRole, "credentialsId"},
0110         {DisplayNameRole, "displayName"},
0111         {ProviderNameRole, "providerName"},
0112         {IconNameRole, "iconName"},
0113         {DataObjectRole, "dataObject"},
0114         {ProviderDisplayNameRole, "providerDisplayName"},
0115     };
0116     return roles;
0117 }
0118 
0119 int AccountsModel::rowCount(const QModelIndex &parent) const
0120 {
0121     if (parent.isValid()) {
0122         return 0;
0123     }
0124 
0125     return d->accountIDs.count();
0126 }
0127 
0128 QVariant AccountsModel::data(const QModelIndex &index, int role) const
0129 {
0130     QVariant data;
0131     if (checkIndex(index)) {
0132         Accounts::AccountId accountId = d->accountIDs.value(index.row());
0133         Accounts::Account *account = d->accountById(accountId);
0134         if (account) {
0135             switch (role) {
0136             case IdRole:
0137                 data.setValue(account->id());
0138                 break;
0139             case ServicesRole: {
0140                 ServicesModel *servicesModel{nullptr};
0141                 if (d->servicesModels.contains(account)) {
0142                     servicesModel = d->servicesModels.value(account);
0143                 } else {
0144                     // Not parenting to the account itself, so we can avoid it suddenly
0145                     // disappearing. Just to be on the safe side
0146                     servicesModel = new ServicesModel(d->accountsManager);
0147                     servicesModel->setAccount(account);
0148                     d->servicesModels[account] = servicesModel;
0149                 }
0150                 data.setValue(servicesModel);
0151                 break;
0152             }
0153             case EnabledRole:
0154                 data.setValue(account->enabled());
0155                 break;
0156             case CredentialsIdRole:
0157                 data.setValue(account->credentialsId());
0158                 break;
0159             case DisplayNameRole:
0160                 data.setValue(account->displayName());
0161                 break;
0162             case ProviderNameRole:
0163                 data.setValue(account->providerName());
0164                 break;
0165             case ProviderDisplayNameRole:
0166                 data.setValue(account->provider().displayName());
0167                 break;
0168             case IconNameRole: {
0169                 QString iconName = QStringLiteral("user-identity");
0170                 if (account->provider().isValid() && !account->provider().iconName().isEmpty()) {
0171                     iconName = account->provider().iconName();
0172                 }
0173                 data.setValue(iconName);
0174                 break;
0175             }
0176             case DataObjectRole:
0177                 data.setValue<QObject *>(account);
0178                 break;
0179             }
0180         }
0181     }
0182 
0183     return data;
0184 }
0185 
0186 };