Akonadi

agentconfigurationwidget.cpp
1 /*
2  SPDX-FileCopyrightText: 2018 Daniel Vr├ítil <[email protected]>
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 "core/agentconfigurationbase.h"
12 #include "core/agentconfigurationfactorybase.h"
13 #include "core/agentconfigurationmanager_p.h"
14 #include "core/agentmanager.h"
15 #include "core/servermanager.h"
16 
17 #include <QChildEvent>
18 #include <QLabel>
19 #include <QTimer>
20 #include <QVBoxLayout>
21 
22 #include <KLocalizedString>
23 #include <KSharedConfig>
24 
25 
26 using namespace Akonadi;
27 using namespace std::chrono_literals;
28 AgentConfigurationWidgetPrivate::AgentConfigurationWidgetPrivate(const AgentInstance &instance)
29  : agentInstance(instance)
30 {
31 }
32 
33 AgentConfigurationWidgetPrivate::~AgentConfigurationWidgetPrivate()
34 {
35 }
36 
37 void 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 
47 bool 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 
71 AgentConfigurationWidget::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  QString configName = instance.identifier() + QStringLiteral("rc");
79  configName = Akonadi::ServerManager::addNamespace(configName);
80  KSharedConfigPtr config = KSharedConfig::openConfig(configName);
81  auto layout = new QVBoxLayout(this);
82  layout->setContentsMargins({});
83  d->plugin = d->factory->create(config, this, {instance.identifier()});
84  connect(d->plugin.data(), &AgentConfigurationBase::enableOkButton, this, &AgentConfigurationWidget::enableOkButton);
85  } else {
86  // Hide this dialog and fallback to calling the out-of-process configuration
87  if (auto dlg = qobject_cast<AgentConfigurationDialog *>(parent)) {
88  const_cast<AgentInstance &>(instance).configure(topLevelWidget()->parentWidget());
89  // If we are inside the AgentConfigurationDialog, hide the dialog
90  QTimer::singleShot(0s, this, [dlg]() {
91  dlg->reject();
92  });
93  } else {
94  const_cast<AgentInstance &>(instance).configure();
95  // Otherwise show a message that this is opened externally
96  d->setupErrorWidget(this, i18n("The configuration dialog has been opened in another window"));
97  }
98 
99  // TODO: Re-enable once we can kill the fallback code above ^^
100  // d->setupErrorWidget(this, i18n("Failed to load configuration plugin"));
101  }
102  } else if (AgentConfigurationManager::self()->isInstanceRegistered(instance.identifier())) {
103  d->setupErrorWidget(this, i18n("Configuration for %1 is already opened elsewhere.", instance.name()));
104  } else {
105  d->setupErrorWidget(this, i18n("Failed to register %1 configuration dialog.", instance.name()));
106  }
107 
108  QTimer::singleShot(0, this, &AgentConfigurationWidget::load);
109 }
110 
111 AgentConfigurationWidget::~AgentConfigurationWidget()
112 {
113  AgentConfigurationManager::self()->unregisterInstanceConfiguration(d->agentInstance.identifier());
114 }
115 
116 void AgentConfigurationWidget::load()
117 {
118  if (d->plugin) {
119  d->plugin->load();
120  }
121 }
122 
123 void AgentConfigurationWidget::save()
124 {
125  qCDebug(AKONADIWIDGETS_LOG) << "Saving configuration for" << d->agentInstance.identifier();
126  if (d->plugin) {
127  if (d->plugin->save()) {
128  d->agentInstance.reconfigure();
129  }
130  }
131 }
132 
133 QSize AgentConfigurationWidget::restoreDialogSize() const
134 {
135  if (d->plugin) {
136  return d->plugin->restoreDialogSize();
137  }
138  return {};
139 }
140 
141 void AgentConfigurationWidget::saveDialogSize(QSize size)
142 {
143  if (d->plugin) {
144  d->plugin->saveDialogSize(size);
145  }
146 }
147 
148 QDialogButtonBox::StandardButtons AgentConfigurationWidget::standardButtons() const
149 {
150  if (d->plugin) {
151  return d->plugin->standardButtons();
152  }
154 }
155 
156 void AgentConfigurationWidget::childEvent(QChildEvent *event)
157 {
158  if (event->added()) {
159  if (event->child()->isWidgetType()) {
160  layout()->addWidget(static_cast<QWidget *>(event->child()));
161  }
162  }
163 
165 }
QString identifier() const
Returns the unique identifier of the agent instance.
AlignCenter
AgentType type() const
Returns the agent type of this instance.
KGuiItem configure()
QLayout * layout() const const
virtual bool event(QEvent *event) override
QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
static KSharedConfig::Ptr openConfig(const QString &fileName=QString(), OpenFlags mode=FullConfig, QStandardPaths::StandardLocation type=QStandardPaths::GenericConfigLocation)
KSharedConfigPtr config() const
Returns KConfig object belonging to the current Akonadi agent instance.
QString i18n(const char *text, const TYPE &arg...)
bool isEmpty() const const
static QString addNamespace(const QString &string)
Adds the multi-instance namespace to string if required (with '_' as separator).
typedef StandardButtons
QString name() const
Returns the user visible name of the agent instance.
QString label(StandardShortcut id)
QString identifier() const
Returns the unique identifier of the agent type.
virtual void childEvent(QChildEvent *event)
void addWidget(QWidget *w)
A representation of an agent instance.
QObject * parent() const const
Helper integration between Akonadi and Qt.
This file is part of the KDE documentation.
Documentation copyright © 1996-2022 The KDE developers.
Generated on Sat Jun 25 2022 06:00:31 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.