Commit b4d3a8ba authored by Nicolas Fella's avatar Nicolas Fella
Browse files

[owncloud] Align wizard UI with new Nextcloud UI

The owncloud and nextcloud UIs are conceptually similar, with the difference that nextcloud has an additional step for web login.

This patch aligns the owncloud UI with the redesigned nextcloud UI from !8
parent e7fa6a36
......@@ -26,3 +26,10 @@ install(TARGETS owncloud_plugin_kaccounts
DESTINATION ${PLUGIN_INSTALL_DIR}/kaccounts/ui
)
kpackage_install_package(package org.kde.kaccounts.owncloud genericqml)
ecm_install_icons(
ICONS
256-apps-kaccounts-owncloud.png
DESTINATION
${ICON_INSTALL_DIR}
)
......@@ -18,6 +18,7 @@
OwnCloudWizard::OwnCloudWizard(QObject *parent)
: KAccountsUiPlugin(parent)
{
qmlRegisterUncreatableType<OwncloudController>("org.kde.kaccounts.owncloud", 1, 0, "OwncloudController", QStringLiteral("Only for enums"));
}
OwnCloudWizard::~OwnCloudWizard()
......
......@@ -18,8 +18,7 @@
OwncloudController::OwncloudController(QObject *parent)
: QObject(parent),
m_errorMessage(QString()),
m_isWorking(false),
m_noError(false)
m_isWorking(false)
{
}
......@@ -129,9 +128,6 @@ void OwncloudController::setWorking(bool start)
void OwncloudController::serverCheckResult(bool result)
{
m_noError = result;
Q_EMIT noErrorChanged();
if (!result) {
m_errorMessage = i18n("Unable to connect to ownCloud at the given server URL. Please check the server URL.");
setWorking(false);
......@@ -194,8 +190,11 @@ void OwncloudController::authCheckResult(KJob *job)
Q_EMIT errorMessageChanged();
m_noError = !kJob->isErrorPage();
Q_EMIT noErrorChanged();
if (!kJob->isErrorPage()) {
m_state = Services;
Q_EMIT stateChanged();
}
setWorking(false);
}
......@@ -204,23 +203,18 @@ bool OwncloudController::isWorking()
return m_isWorking;
}
bool OwncloudController::noError()
{
return m_noError;
}
QString OwncloudController::errorMessage() const
{
return m_errorMessage;
}
void OwncloudController::finish(bool contactsEnabled)
void OwncloudController::finish(const QStringList &disabledServices)
{
QVariantMap data;
data.insert("server", m_server);
if (!contactsEnabled) {
data.insert("__service/owncloud-contacts", false);
for (const QString &service : disabledServices) {
data.insert("__service/" + service, false);
}
QUrl carddavUrl(m_server);
......@@ -232,3 +226,11 @@ void OwncloudController::finish(bool contactsEnabled)
Q_EMIT wizardFinished(m_username, m_password, data);
}
QVariantList OwncloudController::availableServices() const
{
// TODO Find a way to not hardcode this
return {
QVariant::fromValue(Service{QStringLiteral("owncloud-storage"), i18n("Storage"), i18n("Storage integration")})
};
}
......@@ -16,28 +16,51 @@ namespace KIO
};
class KJob;
class Service
{
Q_GADGET
Q_PROPERTY(QString id MEMBER m_id)
Q_PROPERTY(QString name MEMBER m_name)
Q_PROPERTY(QString description MEMBER m_description)
public:
QString m_id;
QString m_name;
QString m_description;
};
class OwncloudController : public QObject
{
Q_OBJECT
Q_PROPERTY(State state MEMBER m_state NOTIFY stateChanged)
Q_PROPERTY(bool isWorking READ isWorking NOTIFY isWorkingChanged)
Q_PROPERTY(bool noError READ noError NOTIFY noErrorChanged)
Q_PROPERTY(QString errorMessage READ errorMessage NOTIFY errorMessageChanged)
Q_PROPERTY(QVariantList availableServices READ availableServices CONSTANT)
public:
enum State {
Server = 0,
Services
};
Q_ENUM(State)
explicit OwncloudController(QObject *parent = 0);
~OwncloudController();
Q_INVOKABLE void checkServer(const QString &username, const QString &password, const QString &server);
Q_INVOKABLE void finish(bool contactsEnabled);
Q_INVOKABLE void finish(const QStringList &disabledServices);
bool isWorking();
bool noError();
QString errorMessage() const;
State state() const;
QVariantList availableServices() const;
Q_SIGNALS:
void isWorkingChanged();
void noErrorChanged();
void errorMessageChanged();
void wizardFinished(const QString &username, const QString &password, const QVariantMap &data);
void stateChanged();
private Q_SLOTS:
void fileChecked(KJob *job);
......@@ -57,7 +80,7 @@ private:
QString m_password;
QStringList m_disabledServices;
bool m_isWorking;
bool m_noError;
State m_state = Server;
};
......
/*
* Copyright 2015 (C) Martin Klapetek <mklapetek@kde.org>
*
* SPDX-License-Identifier: LGPL-2.0-or-later
*/
import QtQuick 2.2
import QtQuick.Layouts 1.1
import QtQuick.Controls 1.2
import org.kde.plasma.core 2.0 as PlasmaCore
ColumnLayout {
id: basicInfoLayout
property bool canContinue: !helper.isWorking && helper.noError && nameText.text.length > 0 && passwordText.text.length > 0
property bool canRestartTimer: nameText.text.length > 0 && passwordText.text.length > 0 && serverText.text.length > 0
Timer {
id: checkServerTimer
interval: 1000
repeat: false
running: false
onTriggered: {
helper.checkServer(nameText.text, passwordText.text, serverText.text);
}
}
TextField {
id: nameText
Layout.fillWidth: true
// clearButtonShown: true
placeholderText: "Username"
onTextChanged: {
if (basicInfoLayout.canRestartTimer) {
checkServerTimer.restart();
}
}
}
TextField {
id: passwordText
Layout.fillWidth: true
// clearButtonShown: true
placeholderText: "Password"
echoMode: TextInput.Password
onTextChanged: {
if (basicInfoLayout.canRestartTimer) {
checkServerTimer.restart();
}
}
}
TextField {
id: serverText
Layout.fillWidth: true
// clearButtonShown: true
placeholderText: "Server"
onTextChanged: {
if (basicInfoLayout.canRestartTimer) {
checkServerTimer.restart();
}
}
}
Label {
id: errorLabel
Layout.fillWidth: true
visible: text.length > 0 && !checkServerTimer.running
text: helper.errorMessage
wrapMode: Text.WordWrap
}
Item {
Layout.fillWidth: true
Layout.fillHeight: true
BusyIndicator {
id: busy
width: parent.height > parent.width ? Math.round(parent.width/2) : Math.round(parent.height/2)
height: width
anchors.centerIn: parent
running: helper.isWorking
visible: running
}
PlasmaCore.IconItem {
width: busy.width
height: width
anchors.centerIn: parent
source: "dialog-ok"
visible: !helper.isWorking && helper.noError && !errorLabel.visible
}
}
}
/*
* SPDX-FileCopyrightText: 2020 Nicolas Fella <nicolas.fella@gmx.de>
* SPDX-FileCopyrightText: 2019 Rituka Patwal <ritukapatwal21@gmail.com>
* SPDX-FileCopyrightText: 2015 Martin Klapetek <mklapetek@kde.org>
*
* SPDX-License-Identifier: LGPL-2.0-or-later
*/
import QtQuick 2.2
import org.kde.kirigami 2.5 as Kirigami
import QtQuick.Layouts 1.12
import QtQuick.Controls 2.5
Kirigami.Page {
title: i18n("ownCloud Login")
header: Kirigami.InlineMessage {
type: Kirigami.MessageType.Error
text: helper.errorMessage
visible: text.length > 0
}
Kirigami.Icon {
source: "kaccounts-owncloud"
width: Kirigami.Units.gridUnit * 6
height: width
anchors {
horizontalCenter: form.horizontalCenter
bottom: form.top
}
}
Kirigami.FormLayout {
id: form
anchors.centerIn: parent
visible: !busy.running
TextField {
id: nameText
Kirigami.FormData.label: i18n("Username:")
}
TextField {
id: passwordText
Kirigami.FormData.label: i18n("Password:")
echoMode: TextInput.Password
}
TextField {
id: serverText
placeholderText: "https://nextcloud.provider.com"
Kirigami.FormData.label: i18n("Server address:")
}
}
BusyIndicator {
id: busy
anchors.centerIn: parent
running: helper.isWorking
}
footer: ToolBar {
RowLayout {
anchors.fill: parent
Button {
text: i18n("Next")
Layout.alignment: Qt.AlignRight
enabled: serverText.text.length > 0 && nameText.text.length > 0 && passwordText.text.length > 0 // TODO Do a more thorough validation of the URL
onClicked: {
helper.checkServer(nameText.text, passwordText.text, serverText.text);
}
}
}
}
}
/*
* Copyright 2015 (C) Martin Klapetek <mklapetek@kde.org>
* SPDX-FileCopyrightText: 2020 Nicolas Fella <nicolas.fella@gmx.de>
* SPDX-FileCopyrightText: 2019 Rituka Patwal <ritukapatwal21@gmail.com>
* SPDX-FileCopyrightText: 2015 Martin Klapetek <mklapetek@kde.org>
*
* SPDX-License-Identifier: LGPL-2.0-or-later
* SPDX-License-Identifier: LGPL-2.0-or-later
*/
import QtQuick 2.2
import QtQuick.Layouts 1.1
import QtQuick.Controls 1.2
import org.kde.kirigami 2.5 as Kirigami
import QtQuick.Layouts 1.12
import QtQuick.Controls 2.5
ColumnLayout {
id: basicInfoLayout
property bool canContinue: true
Kirigami.ScrollablePage {
id: root
title: i18n("Services")
//FIXME at some point this should become a list of disabled services
property alias contactsEnabled: contactsService.checked
property var disabledServices: []
Label {
text: i18n("Choose services to enable");
}
ListView {
model: helper.availableServices
clip: true
// Cheap copy of Kirigami.BasicListItem with CheckBox instead of Icon
delegate: Kirigami.AbstractListItem {
id: listItem
highlighted: false
onClicked: serviceCheck.toggle()
RowLayout {
CheckBox {
id: serviceCheck
Layout.alignment: Qt.AlignVCenter
checked: true
onCheckedChanged: {
if (serviceCheck.checked) {
const idx = root.disabledServices.indexOf(modelData.id);
if (idx > -1) {
root.disabledServices.splice(idx, 1);
}
} else {
root.disabledServices.push(modelData.id);
}
}
}
CheckBox {
id: contactsService
text: i18n("Contacts")
ColumnLayout {
spacing: 0
Layout.fillWidth: true
Layout.alignment: Qt.AlignVCenter
Label {
Layout.fillWidth: true
text: modelData.name
color: listItem.pressed ? listItem.activeTextColor : listItem.textColor
elide: Text.ElideRight
}
Label {
Layout.fillWidth: true
text: modelData.description
color: listItem.pressed ? listItem.activeTextColor : listItem.textColor
elide: Text.ElideRight
font: Kirigami.Theme.smallFont
opacity: 0.7
visible: text.length > 0
}
}
}
}
}
// Just an item padder
Item {
Layout.fillHeight: true
footer: ToolBar {
RowLayout {
anchors.fill: parent
Button {
text: i18n("Finish")
Layout.alignment: Qt.AlignRight
onClicked: {
helper.finish(root.disabledServices)
}
}
}
}
}
/*
* Copyright 2015 (C) Martin Klapetek <mklapetek@kde.org>
* SPDX-FileCopyrightText: 2020 Nicolas Fella <nicolas.fella@gmx.de>
* SPDX-FileCopyrightText: 2019 Rituka Patwal <ritukapatwal21@gmail.com>
* SPDX-FileCopyrightText: 2015 Martin Klapetek <mklapetek@kde.org>
*
* SPDX-License-Identifier: LGPL-2.0-or-later
* SPDX-License-Identifier: LGPL-2.0-or-later
*/
import QtQuick 2.2
import QtQuick.Layouts 1.1
import QtQuick.Controls 1.2
import QtQuick.Layouts 1.12
import QtQuick.Controls 2.5
ApplicationWindow {
id: kaccountsRoot
objectName: "_root"
import org.kde.kirigami 2.5 as Kirigami
import org.kde.kaccounts.owncloud 1.0
width: 400; height: 250
Kirigami.ApplicationWindow {
id: ocAccountRoot
ColumnLayout {
anchors.fill: parent
anchors.margins: units.largeSpacing
// Minimum size at which the web login UI looks good
minimumWidth: Kirigami.Units.gridUnit * 24
minimumHeight: Kirigami.Units.gridUnit * 35
width: minimumWidth
height: minimumHeight
Label {
text: i18n("Add new ownCloud account")
}
StackView {
id: stack
Layout.fillHeight: true
Layout.fillWidth: true
initialItem: BasicInfo {
id: basicInfoPage
objectName: "basicInfoPage"
}
}
Component {
id: servicesComponent
Services {
objectName: "servicesPage"
}
}
RowLayout {
Button {
id: backButton
Layout.fillWidth: true
text: i18n("Back");
enabled: stack.currentItem.objectName == "servicesPage"
onClicked: {
if (stack.currentItem.objectName == "servicesPage") {
stack.pop(servicesComponent);
}
}
}
Button {
id: nextButton
Layout.fillWidth: true
text: i18n("Next")
enabled: basicInfoPage.canContinue //: false
visible: stack.currentItem == basicInfoPage
onClicked: {
if (stack.currentItem == basicInfoPage) {
stack.push(servicesComponent);
}
}
}
pageStack.initialPage: Qt.resolvedUrl("Server.qml");
Button {
id: finishButton
Layout.fillWidth: true
text: i18n("Finish")
visible: stack.currentItem.objectName == "servicesPage"
Connections {
target: helper
onClicked: {
helper.finish(stack.currentItem.contactsEnabled);
}
function onStateChanged() {
if (helper.state === OwncloudController.Services) {
ocAccountRoot.pageStack.replace(Qt.resolvedUrl("Services.qml"))
}
}
}
......
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