Commit 748b8519 authored by Dan Leinir Turthra Jensen's avatar Dan Leinir Turthra Jensen 🌈
Browse files

Polish up the KAccounts KCM

Summary:
Since changing to the QtQuick based KAccounts KCM, it seems that
we managed to lose a few features that really want to be in there.
This is work toward ensuring that we get those features back, and
further end up with something which is more pleasant in use in
general than what we had before.

* Add a job for toggling an account service's enabled status and use it to allow this (and then force the model to update, because apparently it doesn't do that automatically)
* Add a dialog when deleting accounts (to ensure less accidental data loss when just clicking around the UI)
* Add self to copyright
* Various little bits of polish (like swapping out icons, ensuring wording is more pleasant in a few places, and adding tooltips)

Accounts list with a few accounts (hovering over one):
{F8112625}

Clicked the remove account action for an account:
{F8112366}

Reviewers: #plasma, bshah, nicolasfella

Reviewed By: nicolasfella

Subscribers: nicolasfella, ahiemstra, apol, mart, bshah, jbbgameich

Differential Revision: https://phabricator.kde.org/D27479
parent 2625460a
......@@ -2,6 +2,7 @@ include_directories(${CMAKE_CURRENT_BINARY_DIR}/.. ${CMAKE_CURRENT_SOURCE_DIR}/.
add_library(kaccountsdeclarativeplugin SHARED kaccountsdeclarativeplugin.cpp
../jobs/createaccount.cpp
../jobs/accountservicetoggle.cpp
../lib/uipluginsmanager.cpp)
target_link_libraries(kaccountsdeclarativeplugin Qt5::Qml
......
......@@ -18,9 +18,11 @@
#include "kaccountsdeclarativeplugin.h"
#include "../jobs/createaccount.h"
#include "../jobs/accountservicetoggle.h"
#include <qqml.h>
void KAccountsDeclarativePlugin::registerTypes(const char* uri)
{
qmlRegisterType<CreateAccount>(uri, 1, 0, "CreateAccount");
qmlRegisterType<AccountServiceToggle>(uri, 1, 1, "AccountServiceToggle");
}
/*************************************************************************************
* Copyright (C) 2020 by Dan Leinir Turthra Jensen <admin@leinir.dk> *
* *
* 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 "accountservicetoggle.h"
#include <QDebug>
#include <KAccounts/Core>
#include <Accounts/Manager>
class AccountServiceToggle::Private {
public:
Private() {}
QString accountId;
QString serviceId;
bool serviceEnabled{false};
};
AccountServiceToggle::AccountServiceToggle(QObject* parent)
: KJob(parent)
, d(new Private)
{ }
AccountServiceToggle::~AccountServiceToggle()
{
delete d;
}
QString AccountServiceToggle::accountId() const
{
return d->accountId;
}
void AccountServiceToggle::setAccountId(const QString& accountId)
{
d->accountId = accountId;
Q_EMIT accountIdChanged();
}
QString AccountServiceToggle::serviceId() const
{
return d->serviceId;
}
void AccountServiceToggle::setServiceId(const QString& serviceId)
{
d->serviceId = serviceId;
Q_EMIT serviceIdChanged();
}
bool AccountServiceToggle::serviceEnabled() const
{
return d->serviceEnabled;
}
void AccountServiceToggle::setServiceEnabled(bool serviceEnabled)
{
d->serviceEnabled = serviceEnabled;
Q_EMIT serviceEnabledChanged();
}
void AccountServiceToggle::start()
{
Accounts::Manager* accountsManager = KAccounts::accountsManager();
if (accountsManager) {
Accounts::Account *account = accountsManager->account(d->accountId.toInt());
if (account) {
Accounts::Service service = accountsManager->service(d->serviceId);
if (!service.isValid()) {
// qWarning() << "Looks like we might have been given a name instead of an ID for the service, which will be expected when using the Ubuntu AccountServiceModel, which only gives you the name";
for (const Accounts::Service& aService : account->services()) {
if (aService.displayName() == d->serviceId) {
service = aService;
break;
}
}
}
if (service.isValid()) {
account->selectService(service);
account->setEnabled(d->serviceEnabled);
if (d->serviceEnabled) {
account->selectService();
account->setEnabled(true);
} else {
bool shouldStayEnabled = false;
for (const Accounts::Service &accountService : account->services()) {
// Skip the current service, that is not synced to the account yet
// so it would return the state before the user clicked the checkbox
if (accountService == service) {
continue;
}
account->selectService(accountService);
if (account->isEnabled()) {
// At least one service is enabled, leave the account enabled
shouldStayEnabled = true;
break;
}
}
// Make sure we're operating on the global account
account->selectService();
account->setEnabled(shouldStayEnabled);
}
connect(account, &Accounts::Account::synced, this, [this](){ emitResult(); });
account->sync();
} else {
qWarning() << "No service found with the ID" << d->serviceId << "on account" << account->displayName();
emitResult();
}
} else {
qWarning() << "No account found with the ID" << d->accountId;
emitResult();
}
} else {
qWarning() << "No accounts manager, this is not awesome.";
emitResult();
}
}
/*************************************************************************************
* Copyright (C) 2020 by Dan Leinir Turthra Jensen <admin@leinir.dk> *
* *
* 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 ACCOUNTSERVICETOGGLE_H
#define ACCOUNTSERVICETOGGLE_H
#include <kjob.h>
#include <QStringList>
class AccountServiceToggle : 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 AccountServiceToggle(QObject* parent = nullptr);
virtual ~AccountServiceToggle();
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
/*
* Copyright 2015 Martin Klapetek <mklapetek@kde.org>
* Copyright 2020 Dan Leinir Turthra Jensen <admin@leinir.dk>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Library General Public License as
......@@ -23,7 +24,7 @@ import QtQuick 2.7
import QtQuick.Layouts 1.11
import QtQuick.Controls 2.0 as Controls
import org.kde.kirigami 2.4 as Kirigami
import org.kde.kirigami 2.7 as Kirigami
import org.kde.kaccounts 1.0
import org.kde.kcm 1.2
......@@ -42,10 +43,19 @@ ScrollViewKCM {
}
delegate: Kirigami.SwipeListItem {
id: accountDelegate
width: ListView.view.width
contentItem: Controls.Label {
text: i18n("%1 (%2)", model.displayName, model.providerName)
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)
}
}
OA.Account {
id: account
......@@ -54,14 +64,53 @@ ScrollViewKCM {
}
actions: [
Kirigami.Action {
iconName: "bookmark-remove"
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: {
account.remove()
accountRemovalDlg.account = account;
accountRemovalDlg.displayName = model.displayName;
accountRemovalDlg.providerName = model.providerName;
accountRemovalDlg.open();
}
}
]
onClicked: kcm.push("AvailableServices.qml", {accountId: model.accountId})
}
Controls.Label {
anchors {
fill: parent
margins: Kirigami.Units.largeSpacing
}
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 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)
}
}
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(); }
}
]
}
footer: RowLayout {
......
/*
* Copyright 2019 Nicolas Fella <nicolas.fella@gmx.de>
* Copyright 2020 Dan Leinir Turthra Jensen <admin@leinir.dk>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Library General Public License as
......@@ -21,11 +22,12 @@ import QtQuick 2.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.1 as KAccounts
import org.kde.kcm 1.2
import Ubuntu.OnlineAccounts 0.1 as OA
ScrollViewKCM {
id: component;
title: i18n("Available Services")
......@@ -34,13 +36,44 @@ ScrollViewKCM {
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;
}
}
delegate: Kirigami.AbstractListItem {
width: parent.width
Controls.CheckBox {
id: serviceCheck
text: model.serviceName
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);
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.AccountServiceToggle { }
}
}
/*
* Copyright 2020 Dan Leinir Turthra Jensen <admin@leinir.dk>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Library General Public License as
* published by the Free Software Foundation; either version 2 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 Library General Public License for more details
*
* You should have received a copy of the GNU Library 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.
*/
import QtQuick 2.7
import QtQuick.Controls 2.11 as QtControls
import QtQuick.Layouts 1.11 as QtLayouts
import org.kde.kirigami 2.7 as Kirigami
Kirigami.OverlaySheet {
id: component
property alias title: headerLabel.text
property alias text: messageLabel.text
property list<QtObject> actions
showCloseButton: true
header: Kirigami.Heading {
id: headerLabel
QtLayouts.Layout.fillWidth: true
elide: Text.ElideRight
}
contentItem: QtControls.Label {
id: messageLabel
QtLayouts.Layout.preferredWidth: Kirigami.Units.gridUnit * 10
QtLayouts.Layout.margins: Kirigami.Units.largeSpacing
wrapMode: Text.Wrap
}
footer: QtLayouts.RowLayout {
Item { QtLayouts.Layout.fillWidth: true }
Repeater {
model: component.actions;
QtControls.Button {
action: modelData
Connections {
target: action
onTriggered: component.close()
}
}
}
}
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment