Akonadi

agentconfigurationwidget.cpp
1/*
2 SPDX-FileCopyrightText: 2018 Daniel Vrátil <dvratil@kde.org>
3
4 SPDX-License-Identifier: LGPL-2.0-or-later
5*/
6
7#include "agentconfigurationwidget.h"
8#include "agentconfigurationdialog.h"
9#include "agentconfigurationwidget_p.h"
10#include "akonadiwidgets_debug.h"
11#include "controlinterface.h"
12#include "core/agentconfigurationbase.h"
13#include "core/agentconfigurationfactorybase.h"
14#include "core/agentconfigurationmanager_p.h"
15#include "core/agenttype.h"
16#include "core/servermanager.h"
17
18#include <QChildEvent>
19#include <QLabel>
20#include <QTimer>
21#include <QVBoxLayout>
22
23#include <KLocalizedString>
24#include <KSharedConfig>
25
26using namespace Akonadi;
27using namespace std::chrono_literals;
28AgentConfigurationWidgetPrivate::AgentConfigurationWidgetPrivate(const AgentInstance &instance)
29 : agentInstance(instance)
30{
31}
32
33AgentConfigurationWidgetPrivate::~AgentConfigurationWidgetPrivate()
34{
35}
36
37void AgentConfigurationWidgetPrivate::setupErrorWidget(QWidget *parent, const QString &text)
38{
39 auto layout = new QVBoxLayout(parent);
40 layout->addStretch(2);
41 auto label = new QLabel(text, parent);
42 label->setAlignment(Qt::AlignCenter);
43 layout->addWidget(label);
44 layout->addStretch(2);
45}
46
47bool AgentConfigurationWidgetPrivate::loadPlugin(const QString &pluginPath)
48{
49 if (pluginPath.isEmpty()) {
50 qCDebug(AKONADIWIDGETS_LOG) << "Haven't found config plugin for" << agentInstance.type().identifier();
51 return false;
52 }
53 loader = decltype(loader)(new QPluginLoader(pluginPath));
54 if (!loader->load()) {
55 qCWarning(AKONADIWIDGETS_LOG) << "Failed to load config plugin" << pluginPath << ":" << loader->errorString();
56 loader.reset();
57 return false;
58 }
59 factory = qobject_cast<AgentConfigurationFactoryBase *>(loader->instance());
60 if (!factory) {
61 // will unload the QPluginLoader and thus delete the factory as well
62 qCWarning(AKONADIWIDGETS_LOG) << "Config plugin" << pluginPath << "does not contain AgentConfigurationFactory!";
63 loader.reset();
64 return false;
65 }
66
67 qCDebug(AKONADIWIDGETS_LOG) << "Loaded agent configuration plugin" << pluginPath;
68 return true;
69}
70
71AgentConfigurationWidget::AgentConfigurationWidget(const AgentInstance &instance, QWidget *parent)
72 : QWidget(parent)
73 , d(new AgentConfigurationWidgetPrivate(instance))
74{
75 if (AgentConfigurationManager::self()->registerInstanceConfiguration(instance.identifier())) {
76 const auto pluginPath = AgentConfigurationManager::self()->findConfigPlugin(instance.type().identifier());
77 if (d->loadPlugin(pluginPath)) {
78 const QString configName = Akonadi::ServerManager::addNamespace(instance.identifier()) + QStringLiteral("rc");
79 KSharedConfigPtr config = KSharedConfig::openConfig(configName);
80 auto layout = new QVBoxLayout(this);
81 layout->setContentsMargins({});
82 d->plugin = d->factory->create(config, this, {instance.identifier()});
83 connect(d->plugin.data(), &AgentConfigurationBase::enableOkButton, this, &AgentConfigurationWidget::enableOkButton);
84 } else {
85 // Hide this dialog and fallback to calling the out-of-process configuration
86 if (auto dlg = qobject_cast<AgentConfigurationDialog *>(parent)) {
87 auto agentControlIface =
88 new org::freedesktop::Akonadi::Agent::Control(ServerManager::agentServiceName(ServerManager::Agent, instance.identifier()),
89 QStringLiteral("/"),
90 QDBusConnection::sessionBus(),
91 this);
92 if (!agentControlIface || !agentControlIface->isValid()) {
93 delete agentControlIface;
94 d->setupErrorWidget(this, i18n("Unable to access D-Bus interface of created agent."));
95 return;
96 }
97
98 connect(agentControlIface, &org::freedesktop::Akonadi::Agent::Control::configurationDialogAccepted, this, [agentControlIface, dlg]() {
99 agentControlIface->deleteLater();
100 dlg->accept();
101 });
102 connect(agentControlIface, &org::freedesktop::Akonadi::Agent::Control::configurationDialogRejected, this, [agentControlIface, dlg]() {
103 agentControlIface->deleteLater();
104 dlg->reject();
105 });
106
107 const auto parentWidget = topLevelWidget()->parentWidget();
108 const_cast<AgentInstance &>(instance).configure(parentWidget ? parentWidget->window()->winId() : 0);
109 // If we are inside the AgentConfigurationDialog, hide the dialog
110 QTimer::singleShot(0s, this, [dlg]() {
111 dlg->hide();
112 });
113 } else {
114 const_cast<AgentInstance &>(instance).configure();
115 // Otherwise show a message that this is opened externally
116 d->setupErrorWidget(this, i18n("The configuration dialog has been opened in another window"));
117 }
118
119 // TODO: Re-enable once we can kill the fallback code above ^^
120 // d->setupErrorWidget(this, i18n("Failed to load configuration plugin"));
121 }
122 } else if (AgentConfigurationManager::self()->isInstanceRegistered(instance.identifier())) {
123 d->setupErrorWidget(this, i18n("Configuration for %1 is already opened elsewhere.", instance.name()));
124 } else {
125 d->setupErrorWidget(this, i18n("Failed to register %1 configuration dialog.", instance.name()));
126 }
127
128 QTimer::singleShot(0, this, &AgentConfigurationWidget::load);
129}
130
131AgentConfigurationWidget::~AgentConfigurationWidget()
132{
133 AgentConfigurationManager::self()->unregisterInstanceConfiguration(d->agentInstance.identifier());
134}
135
136void AgentConfigurationWidget::load()
137{
138 if (d->plugin) {
139 d->plugin->load();
140 }
141}
142
143void AgentConfigurationWidget::save()
144{
145 qCDebug(AKONADIWIDGETS_LOG) << "Saving configuration for" << d->agentInstance.identifier();
146 if (d->plugin) {
147 if (d->plugin->save()) {
148 d->agentInstance.reconfigure();
149 }
150 }
151}
152
153QSize AgentConfigurationWidget::restoreDialogSize() const
154{
155 if (d->plugin) {
156 return d->plugin->restoreDialogSize();
157 }
158 return {};
159}
160
161void AgentConfigurationWidget::saveDialogSize(QSize size)
162{
163 if (d->plugin) {
164 d->plugin->saveDialogSize(size);
165 }
166}
167
168QDialogButtonBox::StandardButtons AgentConfigurationWidget::standardButtons() const
169{
170 if (d->plugin) {
171 auto buttons = d->plugin->standardButtons();
172 QDialogButtonBox::StandardButtons standardButtons;
173 if (buttons & AgentConfigurationBase::Ok) {
174 standardButtons |= QDialogButtonBox::Ok;
175 }
176 if (buttons & AgentConfigurationBase::Cancel) {
177 standardButtons |= QDialogButtonBox::Cancel;
178 }
179 if (buttons & AgentConfigurationBase::Apply) {
180 standardButtons |= QDialogButtonBox::Apply;
181 }
182 if (buttons & AgentConfigurationBase::Help) {
183 standardButtons |= QDialogButtonBox::Help;
184 }
185 return standardButtons;
186 }
188}
189
190void AgentConfigurationWidget::childEvent(QChildEvent *event)
191{
192 if (event->added()) {
193 if (event->child()->isWidgetType()) {
194 layout()->addWidget(static_cast<QWidget *>(event->child()));
195 }
196 }
197
199}
200
201#include "moc_agentconfigurationwidget.cpp"
Represents one agent instance and takes care of communication with it.
QString identifier() const
Set/get the unique identifier of this AgentInstance.
Helper integration between Akonadi and Qt.
QString label(StandardShortcut id)
typedef StandardButtons
void addWidget(QWidget *w)
virtual void childEvent(QChildEvent *event)
virtual bool event(QEvent *e)
bool isEmpty() const const
AlignCenter
QWidget(QWidget *parent, Qt::WindowFlags f)
QLayout * layout() const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2025 The KDE developers.
Generated on Fri Mar 28 2025 11:53:22 by doxygen 1.13.2 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.