Commit b06d5126 authored by Carl Schwan's avatar Carl Schwan 🚴
Browse files

Update look of account configuration



Signed-off-by: Carl Schwan's avatarCarl Schwan <carl@carlschwan.eu>
parent 5478d97e
Pipeline #234236 passed with stage
in 2 minutes and 3 seconds
......@@ -14,8 +14,6 @@ set(kalendar_SRCS
about.h
models/actionsmodel.cpp
models/actionsmodel.h
agentconfiguration.cpp
agentconfiguration.h
models/attachmentsmodel.cpp
models/attachmentsmodel.h
models/attendeesmodel.cpp
......
......@@ -21,16 +21,9 @@ Kirigami.CategorizedSettings {
page: Qt.resolvedUrl("ViewSettingsPage.qml")
},
Kirigami.SettingAction {
text: i18n("Calendar Sources")
text: i18n("Accounts")
icon.name: "preferences-system-users"
page: Qt.resolvedUrl("SourceSettingsPage.qml")
onTriggered: AgentConfiguration.mode = KalendarApplication.Event
},
Kirigami.SettingAction {
text: i18n("Address Book Sources")
icon.name: "preferences-system-users"
page: Qt.resolvedUrl("SourceSettingsPage.qml")
onTriggered: AgentConfiguration.mode = KalendarApplication.Contact
},
Kirigami.SettingAction {
text: i18n("Calendars")
......
// SPDX-FileCopyrightText: 2021 Carl Schwan <carlschwan@kde.org>
// SPDX-License-Identifier: LGPL-2.0-or-later
// SPDX-FileCopyrightText: 2022 Devin Lin <devin@kde.org>
// SPDX-License-Identifier: GPL-2.0-or-later
import QtQuick 2.15
import org.kde.kirigami 2.14 as Kirigami
import QtQuick.Controls 2.15 as Controls
import org.kde.kirigami 2.19 as Kirigami
import QtQuick.Layouts 1.15
import org.kde.kalendar 1.0
import org.kde.akonadi 1.0
import org.kde.kirigamiaddons.labs.mobileform 0.1 as MobileForm
Kirigami.Page {
Kirigami.ScrollablePage {
id: sourcesSettingsPage
title: switch (mode) {
case KalendarApplication.Contact:
return i18n("Address Book Sources");
case KalendarApplication.Event:
return i18n("Calendar Sources");
}
property int mode: AgentConfiguration.mode
title: i18n("Accounts")
ColumnLayout {
anchors.fill: parent
Controls.ScrollView {
Component.onCompleted: background.visible = true
AgentConfigurationForm {
mimetypes: [MimeTypes.calendar, MimeTypes.todo]
title: i18n("Calendars")
addPageTitle: i18n("Add New Calendar Source…")
Layout.fillWidth: true
Layout.fillHeight: true
ListView {
Layout.fillWidth: true
Layout.fillHeight: true
clip: true
model: AgentConfiguration.runningAgents
delegate: Kirigami.BasicListItem {
id: listItem
leftPadding: Kirigami.Units.largeSpacing * 2
topPadding: Kirigami.Units.largeSpacing
bottomPadding: Kirigami.Units.largeSpacing
contentItem: Item {
implicitWidth: delegateLayout.implicitWidth
implicitHeight: delegateLayout.implicitHeight
GridLayout {
id: delegateLayout
anchors {
left: parent.left
top: parent.top
right: parent.right
}
rowSpacing: Kirigami.Units.smallSpacing
columnSpacing: Kirigami.Units.smallSpacing
columns: 4
rows: 3
Kirigami.Icon {
source: model.decoration
Layout.row: 0
Layout.column: 0
Layout.rowSpan: 2
Layout.preferredWidth: Kirigami.Units.gridUnit * 3
Layout.preferredHeight: Kirigami.Units.gridUnit * 3
color: (listItem.highlighted || listItem.checked || (listItem.pressed && listItem.supportsMouseEvents)) ? listItem.activeTextColor : listItem.textColor
}
Layout.topMargin: Kirigami.Units.largeSpacing
}
Controls.Label {
Layout.row: 0
Layout.column: 1
font.weight: Font.Light
font.pointSize: Math.round(Kirigami.Theme.defaultFont.pointSize * 1.25)
text: model.display
Layout.fillWidth: true
elide: Text.ElideRight
maximumLineCount: 2
wrapMode: Text.WordWrap
color: (listItem.highlighted || listItem.checked || (listItem.pressed && listItem.supportsMouseEvents)) ? listItem.activeTextColor : listItem.textColor
}
Controls.Label {
id: alarmName
Layout.row: 1
Layout.column: 1
visible: text !== ""
font.weight: Font.Bold
color: {
// TODO this is weird
if (model.status === /* running */0) {
return (listItem.highlighted || listItem.checked || (listItem.pressed && listItem.supportsMouseEvents)) ? Kirigami.ColorUtils.linearInterpolation(Kirigami.Theme.positiveTextColor, listItem.activeTextColor, 0.5) : Kirigami.Theme.positiveTextColor;
} else if (model.status === /* idle */1) {
return (listItem.highlighted || listItem.checked || (listItem.pressed && listItem.supportsMouseEvents)) ? Kirigami.ColorUtils.linearInterpolation(Kirigami.Theme.disabledTextColor, listItem.activeTextColor, 0.5) : Kirigami.Theme.disabledTextColor;
} else if (model.status === /* broken */2) {
return (listItem.highlighted || listItem.checked || (listItem.pressed && listItem.supportsMouseEvents)) ? Kirigami.ColorUtils.linearInterpolation(Kirigami.Theme.negativeTextColor, listItem.activeTextColor, 0.5) : Kirigami.Theme.negativeTextColor;;
} else {
return (listItem.highlighted || listItem.checked || (listItem.pressed && listItem.supportsMouseEvents)) ? listItem.activeTextColor : listItem.textColor
}
}
text: model.statusMessage
}
RowLayout {
readonly property bool smallScreen: sourcesSettingsPage.width < Kirigami.Units.gridUnit * 30
Layout.row: smallScreen ? 3 : 0
Layout.column: smallScreen ? 4 : 2
Layout.columnSpan : 2
Layout.alignment: Qt.AlignRight
Controls.Button {
icon.name: "view-refresh"
text: i18n("Restart")
onClicked: {
AgentConfiguration.restart(index);
}
}
Controls.Button {
icon.name: "entry-edit"
text: i18n("Edit")
onClicked: {
AgentConfiguration.edit(index);
}
}
Controls.Button {
icon.name: "delete"
text: i18n("Remove")
onClicked: {
// TODO add confirmation dialog
AgentConfiguration.remove(index);
}
}
}
}
}
}
}
}
Component {
id: addCalendarPage
Kirigami.ScrollablePage {
id: overlay
title: sourcesSettingsPage.mode === KalendarApplication.Contact ? i18n("Add New Address Book Source…") : i18n("Add New Calendar Source")
footer: Controls.DialogButtonBox {
Kirigami.Theme.inherit: false
Kirigami.Theme.colorSet: Kirigami.Theme.Window
standardButtons: Controls.DialogButtonBox.Close
onRejected: closeDialog()
background: Rectangle {
color: Kirigami.Theme.backgroundColor
}
}
ListView {
implicitWidth: Kirigami.Units.gridUnit * 20
model: AgentConfiguration.availableAgents
delegate: Kirigami.BasicListItem {
label: model.display
icon: model.decoration
subtitle: model.description
subtitleItem.wrapMode: Text.Wrap
enabled: AgentConfiguration.availableAgents.flags(AgentConfiguration.availableAgents.index(index, 0)) & Qt.ItemIsEnabled
onClicked: {
AgentConfiguration.createNew(index);
overlay.close();
overlay.destroy();
}
}
}
}
}
RowLayout {
AgentConfigurationForm {
mimetypes: [MimeTypes.contactGroup, MimeTypes.address]
title: i18n("Contact Books")
addPageTitle: i18n("Add New Address Book Source…")
Layout.fillWidth: true
Controls.Button {
Layout.alignment: Qt.AlignRight
text: mode === KalendarApplication.Contact ? i18n("Add New Address Book Source…") : i18n("Add New Calendar Source")
icon.name: "list-add"
onClicked: pageStack.pushDialogLayer(addCalendarPage)
}
}
Layout.topMargin: Kirigami.Units.largeSpacing
}
// TODO actually we should show identity instead as an identity contains a receiving and sending account
AgentConfigurationForm {
visible: Config.enableMailIntegration
mimetypes: [MimeTypes.mail]
title: i18n("Mail Accounts")
addPageTitle: i18n("Add New mail account…")
Layout.fillWidth: true
Layout.topMargin: Kirigami.Units.largeSpacing
}
}
}
// SPDX-FileCopyrightText: 2021 Carl Schwan <carlschwan@kde.org>
// SPDX-License-Identifier: LGPL-2.1-or-later
#include "about.h"
#include "agentconfiguration.h"
#include "akonadi/collectionfilterproxymodel.h"
#include "calendarmanager.h"
#include "config-kalendar.h"
......@@ -100,7 +99,6 @@ int main(int argc, char *argv[])
aboutData.processCommandLine(&parser);
auto config = KalendarConfig::self();
AgentConfiguration agentConfiguration;
auto kalendarApplication = new KalendarApplication;
kalendarApplication->setCalendar(CalendarManager::instance()->calendar());
......@@ -122,7 +120,6 @@ int main(int argc, char *argv[])
auto tagManager = new TagManager(&engine);
qmlRegisterSingletonInstance("org.kde.kalendar", 1, 0, "Config", config);
qmlRegisterSingletonInstance("org.kde.kalendar", 1, 0, "CalendarManager", CalendarManager::instance());
qmlRegisterSingletonInstance("org.kde.kalendar", 1, 0, "AgentConfiguration", &agentConfiguration);
qmlRegisterSingletonInstance("org.kde.kalendar", 1, 0, "TagManager", tagManager);
qmlRegisterSingletonInstance("org.kde.kalendar", 1, 0, "AboutType", new AboutType());
qmlRegisterSingletonInstance("org.kde.kalendar", 1, 0, "KalendarApplication", kalendarApplication);
......
......@@ -15,10 +15,13 @@ target_sources(akonadi_quick_plugin PRIVATE
mimetypes.h
akonadiquickplugin.cpp
akonadiquickplugin.h
agentconfiguration.cpp
agentconfiguration.h
)
ecm_target_qml_sources(akonadi_quick_plugin SOURCES
qml/CollectionComboBox.qml
qml/AgentConfigurationForm.qml
)
ecm_qt_declare_logging_category(akonadi_quick_plugin
......@@ -29,7 +32,7 @@ ecm_qt_declare_logging_category(akonadi_quick_plugin
EXPORT KALENDAR
)
target_link_libraries(akonadi_quick_plugin PRIVATE kalendar_lib)
target_link_libraries(akonadi_quick_plugin PRIVATE kalendar_lib KF5::WindowSystem)
ecm_qt_install_logging_categories(
EXPORT KALENDAR
......
......@@ -13,13 +13,11 @@
#include <KWindowSystem>
#include <QPointer>
#include <qobjectdefs.h>
using namespace Akonadi;
AgentConfiguration::AgentConfiguration(QObject *parent)
: QObject(parent)
, m_mode(KalendarApplication::Event)
{
connect(Akonadi::AgentManager::self(), &Akonadi::AgentManager::instanceProgressChanged, this, &AgentConfiguration::processInstanceProgressChanged);
connect(Akonadi::AgentManager::self(), &Akonadi::AgentManager::instanceStatusChanged, this, &AgentConfiguration::processInstanceProgressChanged);
......@@ -35,11 +33,8 @@ Akonadi::AgentFilterProxyModel *AgentConfiguration::availableAgents()
auto agentInstanceModel = new AgentTypeModel(this);
m_availableAgents = new AgentFilterProxyModel(this);
if (m_mode == KalendarApplication::Contact) {
m_availableAgents->addMimeTypeFilter(KContacts::Addressee::mimeType());
m_availableAgents->addMimeTypeFilter(KContacts::ContactGroup::mimeType());
} else {
m_availableAgents->addMimeTypeFilter(QStringLiteral("text/calendar"));
for (const auto &mimetype : m_mimetypes) {
m_availableAgents->addMimeTypeFilter(mimetype);
}
m_availableAgents->setSourceModel(agentInstanceModel);
m_availableAgents->addCapabilityFilter(QStringLiteral("Resource")); // show only resources, no agents
......@@ -54,11 +49,8 @@ Akonadi::AgentFilterProxyModel *AgentConfiguration::runningAgents()
auto agentInstanceModel = new AgentInstanceModel(this);
m_runningAgents = new AgentFilterProxyModel(this);
if (m_mode == KalendarApplication::Contact) {
m_runningAgents->addMimeTypeFilter(KContacts::Addressee::mimeType());
m_runningAgents->addMimeTypeFilter(KContacts::ContactGroup::mimeType());
} else {
m_runningAgents->addMimeTypeFilter(QStringLiteral("text/calendar"));
for (const auto &mimetype : m_mimetypes) {
m_runningAgents->addMimeTypeFilter(mimetype);
}
m_runningAgents->setSourceModel(agentInstanceModel);
m_runningAgents->addCapabilityFilter(QStringLiteral("Resource")); // show only resources, no agents
......@@ -155,18 +147,18 @@ void AgentConfiguration::processInstanceProgressChanged(const Akonadi::AgentInst
Q_EMIT agentProgressChanged(instanceData);
}
KalendarApplication::Mode AgentConfiguration::mode() const
QStringList AgentConfiguration::mimetypes() const
{
return m_mode;
return m_mimetypes;
}
void AgentConfiguration::setMode(KalendarApplication::Mode mode)
void AgentConfiguration::setMimetypes(QStringList mimetypes)
{
if (mode == m_mode) {
if (mimetypes == m_mimetypes) {
return;
}
m_mode = mode;
Q_EMIT modeChanged();
m_mimetypes = mimetypes;
Q_EMIT mimetypesChanged();
if (m_runningAgents) {
delete m_runningAgents;
......
......@@ -3,17 +3,15 @@
#pragma once
#include "kalendarapplication.h"
#include <Akonadi/AgentFilterProxyModel>
#include <Akonadi/AgentInstance>
#include <QObject>
class AgentConfiguration : public QObject
{
Q_OBJECT
Q_PROPERTY(Akonadi::AgentFilterProxyModel *availableAgents READ availableAgents NOTIFY availableAgentsChanged)
Q_PROPERTY(Akonadi::AgentFilterProxyModel *runningAgents READ runningAgents NOTIFY runningAgentsChanged)
Q_PROPERTY(KalendarApplication::Mode mode READ mode WRITE setMode NOTIFY modeChanged)
Q_PROPERTY(QStringList mimetypes READ mimetypes WRITE setMimetypes NOTIFY mimetypesChanged)
public:
enum AgentStatuses {
Idle = Akonadi::AgentInstance::Idle,
......@@ -28,8 +26,8 @@ public:
Akonadi::AgentFilterProxyModel *availableAgents();
Akonadi::AgentFilterProxyModel *runningAgents();
KalendarApplication::Mode mode() const;
void setMode(KalendarApplication::Mode mode);
QStringList mimetypes() const;
void setMimetypes(QStringList mimetypes);
Q_INVOKABLE void createNew(int index);
Q_INVOKABLE void edit(int index);
......@@ -44,7 +42,7 @@ public Q_SLOTS:
Q_SIGNALS:
void agentProgressChanged(const QVariantMap agentData);
void modeChanged();
void mimetypesChanged();
void runningAgentsChanged();
void availableAgentsChanged();
......@@ -55,5 +53,5 @@ private:
Akonadi::AgentFilterProxyModel *m_runningAgents = nullptr;
Akonadi::AgentFilterProxyModel *m_availableAgents = nullptr;
KalendarApplication::Mode m_mode;
QStringList m_mimetypes;
};
......@@ -3,10 +3,11 @@
#include "akonadiquickplugin.h"
#include "mimetypes.h"
#include "agentconfiguration.h"
#include "collection.h"
#include "collectioncomboboxmodel.h"
#include "collectionpickermodel.h"
#include "mimetypes.h"
#include <akonadi_version.h>
#include <Akonadi/Collection>
......@@ -22,6 +23,7 @@ void AkonadiQuickPlugin::registerTypes(const char *uri)
return new Akonadi::Quick::MimeTypes;
});
qmlRegisterType<AgentConfiguration>("org.kde.akonadi", 1, 0, "AgentConfiguration");
qmlRegisterType<Akonadi::Quick::CollectionComboBoxModel>("org.kde.akonadi", 1, 0, "CollectionComboBoxModel");
qmlRegisterType<Akonadi::Quick::CollectionPickerModel>("org.kde.akonadi", 1, 0, "CollectionPickerModel");
......
......@@ -34,3 +34,7 @@ QString MimeTypes::contactGroup() const
return KContacts::ContactGroup::mimeType();
}
QString MimeTypes::mail() const
{
return QStringLiteral("message/rfc822");
}
......@@ -14,6 +14,7 @@ class MimeTypes : public QObject
Q_PROPERTY(QString todo READ todo CONSTANT)
Q_PROPERTY(QString address READ address CONSTANT)
Q_PROPERTY(QString contactGroup READ contactGroup CONSTANT)
Q_PROPERTY(QString mail READ mail CONSTANT)
public:
MimeTypes(QObject *parent = nullptr);
......@@ -21,6 +22,7 @@ public:
QString todo() const;
QString address() const;
QString contactGroup() const;
QString mail() const;
};
}
}
\ No newline at end of file
}
// SPDX-FileCopyrightText: 2022 Devin Lin <devin@kde.org>
// SPDX-License-Identifier: GPL-2.0-or-later
import QtQuick 2.15
import QtQuick.Layouts 1.15
import QtQuick.Controls 2.15 as QQC2
import org.kde.kirigami 2.19 as Kirigami
import org.kde.kirigamiaddons.labs.mobileform 0.1 as MobileForm
import org.kde.akonadi 1.0
MobileForm.FormCard {
id: root
required property var mimetypes
required property string title
required property string addPageTitle
readonly property AgentConfiguration _configuration: AgentConfiguration {
mimetypes: root.mimetypes
}
contentItem: ColumnLayout {
spacing: 0
MobileForm.FormCardHeader {
title: root.title
}
Repeater {
model: root._configuration.runningAgents
delegate: MobileForm.FormButtonDelegate {
Loader {
id: dialogLoader
sourceComponent: Kirigami.PromptDialog {
id: dialog
title: i18n("Configure %1", model.display)
subtitle: i18n("Modify or delete this account agent.")
standardButtons: Kirigami.Dialog.NoButton
customFooterActions: [
Kirigami.Action {
text: i18n("Modify")
iconName: "edit-entry"
onTriggered: {
root._configuration.edit(model.index);
dialog.close();
}
},
Kirigami.Action {
text: i18n("Delete")
iconName: "delete"
onTriggered: {
root._configuration.remove(model.index);
dialog.close();
}
}
]
}
}
onClicked: {
dialogLoader.active = true;
dialogLoader.item.open();
}
contentItem: RowLayout {
Kirigami.Icon {
source: model.decoration
Layout.rightMargin: Kirigami.Units.largeSpacing
implicitWidth: Kirigami.Units.iconSizes.medium
implicitHeight: Kirigami.Units.iconSizes.medium
}
ColumnLayout {
Layout.fillWidth: true
spacing: Kirigami.Units.smallSpacing
QQC2.Label {
Layout.fillWidth: true
text: model.display
elide: Text.ElideRight
wrapMode: Text.Wrap
maximumLineCount: 2
color: Kirigami.Theme.textColor
}
QQC2.Label {
Layout.fillWidth: true
text: model.statusMessage
color: Kirigami.Theme.disabledTextColor
font: Kirigami.Theme.smallFont
elide: Text.ElideRight
}
}
MobileForm.FormArrow {
Layout.alignment: Qt.AlignRight | Qt.AlignVCenter
direction: MobileForm.FormArrow.Right
}
}
}
}
MobileForm.FormDelegateSeparator { below: addAccountDelegate }
MobileForm.FormButtonDelegate {
id: addAccountDelegate
text: i18n("Add Account")
icon.name: "list-add"
onClicked: pageStack.pushDialogLayer(addAccountPage)
}
}
Component {
id: addAccountPage
Kirigami.ScrollablePage {
id: overlay
title: root.addPageTitle
footer: QQC2.DialogButtonBox {
Kirigami.Theme.inherit: false
Kirigami.Theme.colorSet: Kirigami.Theme.Window
standardButtons: QQC2.DialogButtonBox.Close
onRejected: closeDialog()
background: Rectangle {
color: Kirigami.Theme.backgroundColor
}
}
ListView {
implicitWidth: Kirigami.Units.gridUnit * 20
model: root._configuration.availableAgents
delegate: Kirigami.BasicListItem {
label: model.display
icon: model.decoration
subtitle: model.description
subtitleItem.wrapMode: Text.Wrap
enabled: root._configuration.availableAgents.flags(root._configuration.availableAgents.index(index, 0)) & Qt.ItemIsEnabled
onClicked: {
root._configuration.createNew(index);
overlay.close();
overlay.destroy();
}
}
}
}
}
}