diff --git a/src/declarative/kaccountsdeclarativeplugin.cpp b/src/declarative/kaccountsdeclarativeplugin.cpp --- a/src/declarative/kaccountsdeclarativeplugin.cpp +++ b/src/declarative/kaccountsdeclarativeplugin.cpp @@ -1,5 +1,6 @@ /************************************************************************************* * Copyright (C) 2015 by Aleix Pol * + * Copyright (C) 2020 by Dan Leinir Turthra Jensen * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License * @@ -19,10 +20,18 @@ #include "kaccountsdeclarativeplugin.h" #include "createaccountjob.h" #include "accountservicetogglejob.h" +#include "removeaccountjob.h" +#include "accountsmodel.h" +#include "servicesmodel.h" #include void KAccountsDeclarativePlugin::registerTypes(const char* uri) { + qmlRegisterType(uri, 1, 0, "CreateAccount"); + qmlRegisterType(uri, 1, 1, "AccountServiceToggle"); + qmlRegisterType(uri, 1, 2, "RemoveAccount"); + qmlRegisterType(uri, 1, 2, "AccountsModel"); + qmlRegisterType(uri, 1, 2, "ServicesModel"); qmlRegisterType(uri, 1, 0, "CreateAccountJob"); qmlRegisterType(uri, 1, 1, "AccountServiceToggleJob"); } diff --git a/src/kcm/accounts.cpp b/src/kcm/accounts.cpp --- a/src/kcm/accounts.cpp +++ b/src/kcm/accounts.cpp @@ -32,6 +32,7 @@ KAboutData* about = new KAboutData(QStringLiteral("kcm_kaccounts"), i18n("Accounts"), QStringLiteral("1.0"), QString(), KAboutLicense::LGPL); about->addAuthor(i18n("Sebastian Kügler"), QString(), QStringLiteral("sebas@kde.org")); + about->addAuthor(i18n("Dan Leinir Turthra Jensen"), QString(), QStringLiteral("admin@leinir.dk"), QString(), QStringLiteral("leinir")); setAboutData(about); } diff --git a/src/kcm/package/contents/ui/Accounts.qml b/src/kcm/package/contents/ui/Accounts.qml --- a/src/kcm/package/contents/ui/Accounts.qml +++ b/src/kcm/package/contents/ui/Accounts.qml @@ -26,73 +26,80 @@ import org.kde.kirigami 2.7 as Kirigami -import org.kde.kaccounts 1.0 +import org.kde.kaccounts 1.2 as KAccounts import org.kde.kcm 1.2 -import Ubuntu.OnlineAccounts 0.1 as OA - ScrollViewKCM { id: kaccountsRoot // Existing accounts view: ListView { - model: OA.AccountServiceModel { - id: accountsModel - service: "global" - includeDisabled: true - } + model: KAccounts.AccountsModel { } delegate: Kirigami.SwipeListItem { id: accountDelegate width: ListView.view.width - contentItem: Controls.Label { - text: { - if (model.displayName.length > 0 && model.providerName.length > 0) { - return i18n("%1 (%2)", model.displayName, model.providerName) - } else if (model.displayName.length > 0) { - return model.displayName - } else { - return i18n("%1 account", model.providerName) - } + contentItem: RowLayout { + implicitWidth: accountDelegate.ListView.view.width + implicitHeight: Kirigami.Units.iconSizes.large + Kirigami.Units.smallSpacing * 2 + spacing: Kirigami.Units.smallSpacing + Kirigami.Icon { + source: model.iconName + Layout.preferredWidth: Kirigami.Units.iconSizes.large + Layout.preferredHeight: Kirigami.Units.iconSizes.large } - - OA.Account { - id: account - objectHandle: model.accountHandle + Controls.Label { + Layout.fillWidth: true + text: { + if (model.displayName.length > 0 && model.providerName.length > 0) { + return i18n("%1 (%2)", model.displayName, model.providerName) + } else if (model.displayName.length > 0) { + return model.displayName + } else { + return i18n("%1 account", model.providerName) + } + } } } actions: [ Kirigami.Action { text: i18nc("Tooltip for an action which will offer the user to remove the mentioned account", "Remove %1", accountDelegate.contentItem.text) iconName: "edit-delete-remove" onTriggered: { - accountRemovalDlg.account = account; + accountRemovalDlg.accountId = model.id; accountRemovalDlg.displayName = model.displayName; accountRemovalDlg.providerName = model.providerName; accountRemovalDlg.open(); } } ] - onClicked: kcm.push("AvailableServices.qml", {accountId: model.accountId}) + onClicked: kcm.push("AvailableServices.qml", {model: model.services}) } - Controls.Label { - anchors { - fill: parent - margins: Kirigami.Units.largeSpacing + Kirigami.AbstractCard { + visible: view.count === 0 + anchors.centerIn: parent + width: kaccountsRoot.width * 2/ 3 + height: kaccountsRoot.height * 2 / 3 + header: Kirigami.Heading { + Layout.fillWidth: true; + text: i18n("No accounts yet") + } + contentItem: Controls.Label { + clip: true + horizontalAlignment: Text.AlignHCenter + wrapMode: Text.Wrap + textFormat: Text.RichText + text: i18nc("A text shown when a user has not yet added any accounts", "You have not added any accounts yet.

Click on \"Add New Account\" to do so.") + onLinkActivated: kcm.push("AvailableAccounts.qml") } - verticalAlignment: Text.AlignVCenter - horizontalAlignment: Text.AlignHCenter - wrapMode: Text.Wrap - visible: parent.count === 0 - opacity: 0.5 - text: i18nc("A text shown when a user has not yet added any accounts", "You have not added any accounts yet.\nClick the \"Add new Account\" button below to do so.") } } + MessageBoxSheet { id: accountRemovalDlg parent: kaccountsRoot - property QtObject account + property int accountId property string displayName property string providerName title: i18nc("The title for a dialog which lets you remove an account", "Remove Account?") @@ -108,11 +115,19 @@ actions: [ Kirigami.Action { text: i18nc("The label for a button which will cause the removal of a specified account", "Remove Account") - onTriggered: { accountRemovalDlg.account.remove(); } + onTriggered: { + var job = accountRemovalJob.createObject(kaccountsRoot, { "accountId": accountRemovalDlg.accountId }); + job.start(); + } } ] } + Component { + id: accountRemovalJob + KAccounts.RemoveAccount { } + } + footer: RowLayout { Controls.Button { Layout.alignment: Qt.AlignRight diff --git a/src/kcm/package/contents/ui/AvailableAccounts.qml b/src/kcm/package/contents/ui/AvailableAccounts.qml --- a/src/kcm/package/contents/ui/AvailableAccounts.qml +++ b/src/kcm/package/contents/ui/AvailableAccounts.qml @@ -21,7 +21,7 @@ import QtQuick.Layouts 1.11 import QtQuick.Controls 2.0 as Controls import org.kde.kirigami 2.4 as Kirigami -import org.kde.kaccounts 1.0 +import org.kde.kaccounts 1.0 as KAccounts import org.kde.kcm 1.2 import Ubuntu.OnlineAccounts 0.1 as OA @@ -36,6 +36,7 @@ icon: model.iconName label: model.displayName width: parent.width + height: Kirigami.Units.iconSizes.large + Kirigami.Units.smallSpacing * 2 onClicked: { var job = jobComponent.createObject(root, { "providerName": providerId }) @@ -46,7 +47,7 @@ Component { id: jobComponent - CreateAccountJob { + KAccounts.CreateAccount { onFinished: kcm.pop() } } diff --git a/src/kcm/package/contents/ui/AvailableServices.qml b/src/kcm/package/contents/ui/AvailableServices.qml --- a/src/kcm/package/contents/ui/AvailableServices.qml +++ b/src/kcm/package/contents/ui/AvailableServices.qml @@ -22,58 +22,130 @@ import QtQuick.Layouts 1.11 import QtQuick.Controls 2.0 as Controls import org.kde.kirigami 2.4 as Kirigami -import org.kde.kaccounts 1.1 as KAccounts +import org.kde.kaccounts 1.2 as KAccounts import org.kde.kcm 1.2 -import Ubuntu.OnlineAccounts 0.1 as OA -ScrollViewKCM { +SimpleKCM { id: component; title: i18n("Available Services") - property alias accountId: servicesModel.accountId + property alias model: servicesList.model - view: ListView { - model: OA.AccountServiceModel { - id: servicesModel - includeDisabled: true - function refreshData() { - // Because AccountServiceModel seems to not pick this up itself, we'll reset the model... like so, because there's no reset - var oldId = component.accountId; - component.accountId = ""; - component.accountId = oldId; + MessageBoxSheet { + id: accountRemovalDlg + parent: component + property int accountId + property string displayName + property string providerName + title: i18nc("The title for a dialog which lets you remove an account", "Remove Account?") + text: { + if (accountRemovalDlg.displayName.length > 0 && accountRemovalDlg.providerName.length > 0) { + return i18nc("The text for a dialog which lets you remove an account when both provider name and account name are available", "Are you sure you wish to remove the \"%1\" account \"%2\"?", accountRemovalDlg.providerName, accountRemovalDlg.displayName) + } else if (accountRemovalDlg.displayName.length > 0) { + return i18nc("The text for a dialog which lets you remove an account when only the account name is available", "Are you sure you wish to remove the account \"%1\"?", accountRemovalDlg.displayName) + } else { + return i18nc("The text for a dialog which lets you remove an account when only the provider name is available", "Are you sure you wish to remove this \"%1\" account?", accountRemovalDlg.providerName) } } - delegate: Kirigami.AbstractListItem { - width: parent.width - Controls.CheckBox { + actions: [ + Kirigami.Action { + text: i18nc("The label for a button which will cause the removal of a specified account", "Remove Account") + onTriggered: { + var job = accountRemovalJob.createObject(kaccountsRoot, { "accountId": accountRemovalDlg.accountId }); + job.start(); + } + } + ] + } + + Component { + id: jobComponent + KAccounts.AccountServiceToggle { } + } + + Component { + id: accountRemovalJob + KAccounts.RemoveAccount { + onFinished: { + kcm.pop(); + } + } + } + + header: RowLayout { + Layout.fillWidth: true + Layout.margins: Kirigami.Units.smallSpacing + spacing: Kirigami.Units.smallSpacing + Kirigami.Icon { + source: model.accountIconName + Layout.preferredWidth: Kirigami.Units.iconSizes.large + Layout.preferredHeight: Kirigami.Units.iconSizes.large + } + Controls.Label { + Layout.fillWidth: true + text: { + if (model.accountDisplayName.length > 0 && model.accountProviderName.length > 0) { + return i18n("%1 (%2)", model.accountDisplayName, model.accountProviderName) + } else if (model.accountDisplayName.length > 0) { + return model.accountDisplayName + } else { + return i18n("%1 account", model.accountProviderName) + } + } + } + } + + footer: RowLayout { + Controls.Button { + Layout.alignment: Qt.AlignRight + text: i18n("Remove This Account") + icon.name: "edit-delete-remove" + onClicked: { + accountRemovalDlg.accountId = servicesList.model.accountId; + accountRemovalDlg.displayName = servicesList.model.accountDisplayName; + accountRemovalDlg.providerName = servicesList.model.accountProviderName; + accountRemovalDlg.open(); + } + } + } + + Kirigami.FormLayout { + Layout.fillWidth: true + Item { + visible: servicesList.count === 0 + Layout.fillWidth: true + height: Kirigami.Units.largeSpacing + } + Kirigami.AbstractCard { + Layout.fillWidth: true + visible: servicesList.count === 0 + header: Kirigami.Heading { + text: i18nc("Heading for a box informing the user there are no configuration points in this account", "No Services") + } + contentItem: Controls.Label { + verticalAlignment: Text.AlignVCenter + horizontalAlignment: Text.AlignHCenter + wrapMode: Text.Wrap + text: i18nc("A text shown when an account has no configurable services", "This account has no services available for configuration") + } + } + Repeater { + id: servicesList + delegate: Controls.CheckBox { id: serviceCheck - text: model.serviceName + Kirigami.FormData.label: model.displayName + "\n" + model.description checked: model.enabled Binding { target: serviceCheck property: "checked" value: model.enabled } onClicked: { - var job = jobComponent.createObject(component, { "accountId": component.accountId, "serviceId": model.serviceName, "serviceEnabled": !model.enabled }) - job.result.connect(servicesModel.refreshData); + var job = jobComponent.createObject(component, { "accountId": servicesList.model.accountId, "serviceId": model.name, "serviceEnabled": !model.enabled }) job.start() } } } - Controls.Label { - anchors.fill: parent - verticalAlignment: Text.AlignVCenter - horizontalAlignment: Text.AlignHCenter - wrapMode: Text.Wrap - visible: parent.count === 0 - opacity: 0.5 - text: i18nc("A text shown when an account has no configurable services", "(No services for this account)") - } - } - Component { - id: jobComponent - KAccounts.AccountServiceToggleJob { } } } diff --git a/src/lib/CMakeLists.txt b/src/lib/CMakeLists.txt --- a/src/lib/CMakeLists.txt +++ b/src/lib/CMakeLists.txt @@ -6,24 +6,32 @@ PACKAGE_VERSION_FILE "${CMAKE_CURRENT_BINARY_DIR}/KAccountsConfigVersion.cmake" SOVERSION ${KACCOUNTS_SOVERSION}) -set(kaccountslib_SRCS +set (kaccountslib_SRCS + accountsmodel.cpp + core.cpp + kaccountsdplugin.cpp + kaccountsuiplugin.cpp + servicesmodel.cpp + uipluginsmanager.cpp + accountservicetogglejob.cpp createaccountjob.cpp - kaccountsuiplugin.cpp - kaccountsdplugin.cpp getcredentialsjob.cpp - core.cpp - uipluginsmanager.cpp + removeaccountjob.cpp ) ecm_generate_headers(kaccountslib_HEADERS HEADER_NAMES + AccountsModel Core - GetCredentialsJob KAccountsUiPlugin KAccountsDPlugin + ServicesModel + AccountServiceToggleJob + GetCredentialsJob CreateAccountJob + RemoveAccountJob REQUIRED_HEADERS kaccountslib_HEADERS ) diff --git a/src/lib/accountservicetogglejob.h b/src/lib/accountservicetogglejob.h --- a/src/lib/accountservicetogglejob.h +++ b/src/lib/accountservicetogglejob.h @@ -21,6 +21,8 @@ #include "kaccounts_export.h" +#include "kaccounts_export.h" + #include #include diff --git a/src/lib/accountservicetogglejob.h b/src/lib/accountsmodel.h copy from src/lib/accountservicetogglejob.h copy to src/lib/accountsmodel.h --- a/src/lib/accountservicetogglejob.h +++ b/src/lib/accountsmodel.h @@ -1,4 +1,5 @@ /************************************************************************************* + * Copyright (C) 2012 by Alejandro Fiestas Olivares * * Copyright (C) 2020 by Dan Leinir Turthra Jensen * * * * This program is free software; you can redistribute it and/or * @@ -16,40 +17,45 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA * *************************************************************************************/ -#ifndef ACCOUNTSERVICETOGGLE_H -#define ACCOUNTSERVICETOGGLE_H +#ifndef ACCOUNTS_MODEL_H +#define ACCOUNTS_MODEL_H #include "kaccounts_export.h" -#include +#include -#include +#include -class KACCOUNTS_EXPORT AccountServiceToggleJob : public KJob +class KACCOUNTS_EXPORT AccountsModel : public QAbstractListModel { Q_OBJECT - Q_PROPERTY(QString accountId READ accountId WRITE setAccountId NOTIFY accountIdChanged) - Q_PROPERTY(QString serviceId READ serviceId WRITE setServiceId NOTIFY serviceIdChanged) - Q_PROPERTY(bool serviceEnabled READ serviceEnabled WRITE setServiceEnabled NOTIFY serviceEnabledChanged) -public: - explicit AccountServiceToggleJob(QObject* parent = nullptr); - virtual ~AccountServiceToggleJob(); - - void start() override; - - QString accountId() const; - void setAccountId(const QString& accountId); - Q_SIGNAL void accountIdChanged(); - - QString serviceId() const; - void setServiceId(const QString& serviceId); - Q_SIGNAL void serviceIdChanged(); - - bool serviceEnabled() const; - void setServiceEnabled(bool serviceEnabled); - Q_SIGNAL void serviceEnabledChanged(); -private: - class Private; - Private* d; + + public: + enum Roles { + IdRole = Qt::UserRole + 1, + ServicesRole, + EnabledRole, + CredentialsIdRole, + DisplayNameRole, + ProviderNameRole, + IconNameRole, + DataObjectRole + }; + explicit AccountsModel(QObject* parent = nullptr); + virtual ~AccountsModel(); + + QHash< int, QByteArray > roleNames() const override; + virtual int rowCount(const QModelIndex& parent = QModelIndex()) const override; + virtual QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; + + public Q_SLOTS: + void accountCreated(Accounts::AccountId accountId); + void accountRemoved(Accounts::AccountId accountId); + void accountUpdated(); + + private: + class Private; + Private *d; }; -#endif//ACCOUNTSERVICETOGGLE_H + +#endif //ACCOUNTS_MODEL_H diff --git a/src/lib/accountsmodel.cpp b/src/lib/accountsmodel.cpp new file mode 100644 --- /dev/null +++ b/src/lib/accountsmodel.cpp @@ -0,0 +1,207 @@ +/************************************************************************************* + * Copyright (C) 2012 by Alejandro Fiestas Olivares * + * Copyright (C) 2020 by Dan Leinir Turthra Jensen * + * * + * This program is free software; you can redistribute it and/or * + * modify it under the terms of the GNU General Public License * + * as published by the Free Software Foundation; either version 2 * + * of the License, or (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA * + *************************************************************************************/ + +#include "accountsmodel.h" + +#include "core.h" +#include "servicesmodel.h" + +#include + +#include +#include + +#include + +#include +#include + +class AccountsModel::Private : public QObject +{ +public: + Private(AccountsModel *model) + : accountsManager(KAccounts::accountsManager()) + , q(model) + { + accountIDs = accountsManager->accountList(); + + connect(accountsManager, SIGNAL(accountCreated(Accounts::AccountId)), + q, SLOT(accountCreated(Accounts::AccountId))); + connect(accountsManager, SIGNAL(accountRemoved(Accounts::AccountId)), + q, SLOT(accountRemoved(Accounts::AccountId))); + }; + virtual ~Private() + { + qDeleteAll(accounts); + }; + + Accounts::Manager *accountsManager; + Accounts::AccountIdList accountIDs; + QHash accounts; + QHash servicesModels; + + Accounts::Account* accountById(int id); + void removeAccount(Accounts::AccountId accountId); + +private: + AccountsModel* q; +}; + +Accounts::Account* AccountsModel::Private::accountById(int id) +{ + if (accounts.contains(id)) { + return accounts.value(id); + } + + Accounts::Account* account = accountsManager->account(id); + if (!account) { + qDebug() << "\t Failed to get the account from manager"; + return nullptr; + } + + connect(account, SIGNAL(displayNameChanged(QString)), q, SLOT(accountUpdated())); + + accounts[id] = account; + return account; +} + +void AccountsModel::Private::removeAccount(Accounts::AccountId accountId) +{ + accountIDs.removeOne(accountId); + delete accounts.take(accountId); +} + +AccountsModel::AccountsModel(QObject* parent) + : QAbstractListModel(parent) + , d(new AccountsModel::Private(this)) +{ +} + +AccountsModel::~AccountsModel() +{ + delete d; +} + +QHash AccountsModel::roleNames() const +{ + static QHash roles{ + {IdRole, "id"}, + {ServicesRole, "services"}, + {EnabledRole, "enabled"}, + {CredentialsIdRole, "credentialsId"}, + {DisplayNameRole, "displayName"}, + {ProviderNameRole, "providerName"}, + {IconNameRole, "iconName"}, + {DataObjectRole, "dataObject"} + }; + return roles; +} + +int AccountsModel::rowCount(const QModelIndex& parent) const +{ + if (parent.isValid()) { + return 0; + } + + return d->accountIDs.count(); +} + +QVariant AccountsModel::data(const QModelIndex& index, int role) const +{ + QVariant data; + if(checkIndex(index)) { + Accounts::AccountId accountId = d->accountIDs.value(index.row()); + Accounts::Account *account = d->accountById(accountId); + if (account) { + switch (role) { + case IdRole: + data.setValue(account->id()); + break; + case ServicesRole: + { + ServicesModel* servicesModel{nullptr}; + if (d->servicesModels.contains(account)) { + servicesModel = d->servicesModels.value(account); + } else { + // Not parenting to the account itself, so we can avoid it suddenly + // disappearing. Just to be on the safe side + servicesModel = new ServicesModel(d->accountsManager); + servicesModel->setAccount(account); + d->servicesModels[account] = servicesModel; + } + data.setValue(servicesModel); + break; + } + case EnabledRole: + data.setValue(account->enabled()); + break; + case CredentialsIdRole: + data.setValue(account->credentialsId()); + break; + case DisplayNameRole: + data.setValue(account->displayName()); + break; + case ProviderNameRole: + data.setValue(account->providerName()); + break; + case IconNameRole: + { + QString iconName = QString::fromLatin1("unknown"); + if (account->provider().isValid() && !account->provider().iconName().isEmpty()) { + iconName = account->provider().iconName(); + } + data.setValue(iconName); + break; + } + case DataObjectRole: + data.setValue(account); + break; + } + } + } + + return data; +} + +void AccountsModel::accountCreated(Accounts::AccountId accountId) +{ + qDebug() << "AccountsModel::accountCreated: " << accountId; + int row = d->accountIDs.count(); + beginInsertRows(QModelIndex(), row, row); + d->accountIDs.insert(row, accountId); + endInsertRows(); +} + +void AccountsModel::accountRemoved(Accounts::AccountId accountId) +{ + qDebug() << "AccountsModel::accountRemoved: " << accountId; + beginRemoveRows(QModelIndex(), d->accountIDs.indexOf(accountId), d->accountIDs.indexOf(accountId)); + d->removeAccount(accountId); + endRemoveRows(); +} + +void AccountsModel::accountUpdated() +{ + Accounts::Account *acc = qobject_cast(sender()); + Accounts::AccountId accountId = acc->id(); + qDebug() << "Account updated: " << accountId; + + QModelIndex accountIndex = index(d->accountIDs.indexOf(accountId), 0); + Q_EMIT dataChanged(accountIndex, accountIndex); +} diff --git a/src/lib/createaccountjob.cpp b/src/lib/createaccountjob.cpp --- a/src/lib/createaccountjob.cpp +++ b/src/lib/createaccountjob.cpp @@ -17,6 +17,7 @@ *************************************************************************************/ #include "createaccountjob.h" + #include "kaccountsuiplugin.h" #include "core.h" #include "uipluginsmanager.h" diff --git a/src/lib/accountservicetogglejob.h b/src/lib/removeaccountjob.h copy from src/lib/accountservicetogglejob.h copy to src/lib/removeaccountjob.h --- a/src/lib/accountservicetogglejob.h +++ b/src/lib/removeaccountjob.h @@ -16,40 +16,30 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA * *************************************************************************************/ -#ifndef ACCOUNTSERVICETOGGLE_H -#define ACCOUNTSERVICETOGGLE_H +#ifndef REMOVEACCOUNT_H +#define REMOVEACCOUNT_H #include "kaccounts_export.h" #include -#include +#include -class KACCOUNTS_EXPORT AccountServiceToggleJob : public KJob +class KACCOUNTS_EXPORT RemoveAccountJob : public KJob { Q_OBJECT Q_PROPERTY(QString accountId READ accountId WRITE setAccountId NOTIFY accountIdChanged) - Q_PROPERTY(QString serviceId READ serviceId WRITE setServiceId NOTIFY serviceIdChanged) - Q_PROPERTY(bool serviceEnabled READ serviceEnabled WRITE setServiceEnabled NOTIFY serviceEnabledChanged) public: - explicit AccountServiceToggleJob(QObject* parent = nullptr); - virtual ~AccountServiceToggleJob(); + explicit RemoveAccountJob(QObject* parent = nullptr); + virtual ~RemoveAccountJob(); void start() override; QString accountId() const; void setAccountId(const QString& accountId); Q_SIGNAL void accountIdChanged(); - - QString serviceId() const; - void setServiceId(const QString& serviceId); - Q_SIGNAL void serviceIdChanged(); - - bool serviceEnabled() const; - void setServiceEnabled(bool serviceEnabled); - Q_SIGNAL void serviceEnabledChanged(); private: class Private; Private* d; }; -#endif//ACCOUNTSERVICETOGGLE_H +#endif//REMOVEACCOUNT_H diff --git a/src/lib/accountservicetogglejob.h b/src/lib/removeaccountjob.cpp copy from src/lib/accountservicetogglejob.h copy to src/lib/removeaccountjob.cpp --- a/src/lib/accountservicetogglejob.h +++ b/src/lib/removeaccountjob.cpp @@ -16,40 +16,60 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA * *************************************************************************************/ -#ifndef ACCOUNTSERVICETOGGLE_H -#define ACCOUNTSERVICETOGGLE_H +#include "removeaccountjob.h" -#include "kaccounts_export.h" +#include +#include "core.h" +#include +#include -#include +class RemoveAccountJob::Private { +public: + Private() {} + QString accountId; +}; -#include +RemoveAccountJob::RemoveAccountJob(QObject* parent) + : KJob(parent) + , d(new Private) +{ } -class KACCOUNTS_EXPORT AccountServiceToggleJob : public KJob +RemoveAccountJob::~RemoveAccountJob() { - Q_OBJECT - Q_PROPERTY(QString accountId READ accountId WRITE setAccountId NOTIFY accountIdChanged) - Q_PROPERTY(QString serviceId READ serviceId WRITE setServiceId NOTIFY serviceIdChanged) - Q_PROPERTY(bool serviceEnabled READ serviceEnabled WRITE setServiceEnabled NOTIFY serviceEnabledChanged) -public: - explicit AccountServiceToggleJob(QObject* parent = nullptr); - virtual ~AccountServiceToggleJob(); - - void start() override; + delete d; +} - QString accountId() const; - void setAccountId(const QString& accountId); - Q_SIGNAL void accountIdChanged(); +QString RemoveAccountJob::accountId() const +{ + return d->accountId; +} - QString serviceId() const; - void setServiceId(const QString& serviceId); - Q_SIGNAL void serviceIdChanged(); +void RemoveAccountJob::setAccountId(const QString& accountId) +{ + d->accountId = accountId; + Q_EMIT accountIdChanged(); +} - bool serviceEnabled() const; - void setServiceEnabled(bool serviceEnabled); - Q_SIGNAL void serviceEnabledChanged(); -private: - class Private; - Private* d; -}; -#endif//ACCOUNTSERVICETOGGLE_H +void RemoveAccountJob::start() +{ + Accounts::Manager* accountsManager = KAccounts::accountsManager(); + if (accountsManager) { + Accounts::Account *account = accountsManager->account(d->accountId.toInt()); + if (account) { + connect(account, &Accounts::Account::synced, this, [this](){ emitResult(); }); + SignOn::Identity *identity = SignOn::Identity::existingIdentity(account->credentialsId(), this); + if (identity) { + identity->remove(); + identity->deleteLater(); + } + account->remove(); + account->sync(); + } else { + qWarning() << "No account found with the ID" << d->accountId; + emitResult(); + } + } else { + qWarning() << "No accounts manager, this is not awesome."; + emitResult(); + } +} diff --git a/src/lib/servicesmodel.h b/src/lib/servicesmodel.h new file mode 100644 --- /dev/null +++ b/src/lib/servicesmodel.h @@ -0,0 +1,68 @@ +/************************************************************************************* + * Copyright (C) 2012 by Alejandro Fiestas Olivares * + * Copyright (C) 2020 by Dan Leinir Turthra Jensen * + * * + * This program is free software; you can redistribute it and/or * + * modify it under the terms of the GNU General Public License * + * as published by the Free Software Foundation; either version 2 * + * of the License, or (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA * + *************************************************************************************/ + +#ifndef SERVICES_MODEL_H +#define SERVICES_MODEL_H + +#include "kaccounts_export.h" + +#include + +#include + +class KACCOUNTS_EXPORT ServicesModel : public QAbstractListModel +{ + Q_OBJECT + Q_PROPERTY(QObject* account READ account WRITE setAccount NOTIFY accountChanged) + Q_PROPERTY(quint32 accountId READ accountId NOTIFY accountChanged) + Q_PROPERTY(QString accountDisplayName READ accountDisplayName NOTIFY accountChanged) + Q_PROPERTY(QString accountProviderName READ accountProviderName NOTIFY accountChanged) + Q_PROPERTY(QString accountIconName READ accountIconName NOTIFY accountChanged) + public: + enum Roles { + NameRole = Qt::UserRole + 1, + DescriptionRole, + DisplayNameRole, + ServiceTypeRole, + ProviderNameRole, + IconNameRole, + TagsRole, + EnabledRole + }; + explicit ServicesModel(QObject* parent = nullptr); + virtual ~ServicesModel(); + + QHash< int, QByteArray > roleNames() const override; + virtual int rowCount(const QModelIndex& parent = QModelIndex()) const override; + virtual QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; + + void setAccount(QObject* account); + QObject* account() const; + quint32 accountId() const; + QString accountDisplayName() const; + QString accountProviderName() const; + QString accountIconName() const; + Q_SIGNAL void accountChanged(); + + private: + class Private; + Private *d; +}; + +#endif //ACCOUNTS_MODEL_H diff --git a/src/lib/servicesmodel.cpp b/src/lib/servicesmodel.cpp new file mode 100644 --- /dev/null +++ b/src/lib/servicesmodel.cpp @@ -0,0 +1,190 @@ +/************************************************************************************* + * Copyright (C) 2012 by Alejandro Fiestas Olivares * + * Copyright (C) 2020 by Dan Leinir Turthra Jensen * + * * + * This program is free software; you can redistribute it and/or * + * modify it under the terms of the GNU General Public License * + * as published by the Free Software Foundation; either version 2 * + * of the License, or (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA * + *************************************************************************************/ + +#include "servicesmodel.h" + +#include "core.h" + +#include + +#include + +#include + +#include +#include + +class ServicesModel::Private : public QObject +{ +public: + Private(ServicesModel *model) + : q(model) + { }; + virtual ~Private() + { }; + + Accounts::ServiceList services; + Accounts::Account* account{nullptr}; + +private: + ServicesModel* q; +}; + +ServicesModel::ServicesModel(QObject* parent) + : QAbstractListModel(parent) + , d(new ServicesModel::Private(this)) +{ +} + +ServicesModel::~ServicesModel() +{ + delete d; +} + +QHash ServicesModel::roleNames() const +{ + static QHash roles{ + {NameRole, "name"}, + {DescriptionRole, "description"}, + {DisplayNameRole, "displayName"}, + {ServiceTypeRole, "servieType"}, + {ProviderNameRole, "providerName"}, + {IconNameRole, "iconName"}, + {TagsRole, "tags"}, + {EnabledRole, "enabled"} + }; + return roles; +} + +int ServicesModel::rowCount(const QModelIndex& parent) const +{ + if (parent.isValid()) { + return 0; + } + + return d->services.count(); +} + +QVariant ServicesModel::data(const QModelIndex& index, int role) const +{ + QVariant data; + if(checkIndex(index)) { + const Accounts::Service& service = d->services.value(index.row()); + if (service.isValid()) { + switch (role) { + case NameRole: + data.setValue(service.name()); + break; + case DescriptionRole: + data.setValue(service.description()); + break; + case DisplayNameRole: + data.setValue(service.displayName()); + break; + case ServiceTypeRole: + data.setValue(service.serviceType()); + break; + case ProviderNameRole: + data.setValue(service.provider()); + break; + case IconNameRole: + data.setValue(service.iconName()); + break; + case TagsRole: + data.setValue(service.tags().values()); + break; + case EnabledRole: + data.setValue(d->account->enabledServices().contains(service)); + break; + } + } + } + return data; +} + +void ServicesModel::setAccount(QObject* account) +{ + if (d->account != account) { + beginResetModel(); + d->services.clear(); + if (d->account) { + disconnect(d->account, nullptr, this, nullptr); + } + d->account = qobject_cast(account); + if (d->account) { + connect(d->account, &Accounts::Account::enabledChanged, this, [this](const QString& serviceName, bool /*enabled*/){ + int i{0}; + for (const Accounts::Service& service : d->services) { + if (service.name() == serviceName) { + break; + } + ++i; + } + dataChanged(index(i), index(i)); + }); + connect(d->account, &QObject::destroyed, this, [this](){ + beginResetModel(); + d->account = nullptr; + Q_EMIT accountChanged(); + d->services.clear(); + endResetModel(); + }); + d->services = d->account->services(); + } + endResetModel(); + Q_EMIT accountChanged(); + } +} + +QObject * ServicesModel::account() const +{ + return d->account; +} + +quint32 ServicesModel::accountId() const +{ + if (d->account) { + return d->account->id(); + } + return -1; +} + +QString ServicesModel::accountDisplayName() const +{ + if (d->account) { + return d->account->displayName(); + } + return QString{}; +} + +QString ServicesModel::accountProviderName() const +{ + if (d->account) { + return d->account->providerName(); + } + return QString{}; +} + +QString ServicesModel::accountIconName() const +{ + if (d->account && d->account->provider().isValid() && !d->account->provider().iconName().isEmpty()) { + return d->account->provider().iconName(); + } + return QString::fromLatin1("unknown"); +}