File indexing completed on 2025-01-05 04:47:06
0001 /* 0002 SPDX-FileCopyrightText: 2018 Daniel Vrátil <dvratil@kde.org> 0003 0004 SPDX-License-Identifier: LGPL-2.0-or-later 0005 */ 0006 0007 #include "agentconfigurationwidget.h" 0008 #include "agentconfigurationdialog.h" 0009 #include "agentconfigurationwidget_p.h" 0010 #include "akonadiwidgets_debug.h" 0011 #include "core/agentconfigurationbase.h" 0012 #include "core/agentconfigurationfactorybase.h" 0013 #include "core/agentconfigurationmanager_p.h" 0014 #include "core/agentmanager.h" 0015 #include "core/servermanager.h" 0016 0017 #include <QChildEvent> 0018 #include <QLabel> 0019 #include <QTimer> 0020 #include <QVBoxLayout> 0021 0022 #include <KLocalizedString> 0023 #include <KSharedConfig> 0024 0025 using namespace Akonadi; 0026 using namespace std::chrono_literals; 0027 AgentConfigurationWidgetPrivate::AgentConfigurationWidgetPrivate(const AgentInstance &instance) 0028 : agentInstance(instance) 0029 { 0030 } 0031 0032 AgentConfigurationWidgetPrivate::~AgentConfigurationWidgetPrivate() 0033 { 0034 } 0035 0036 void AgentConfigurationWidgetPrivate::setupErrorWidget(QWidget *parent, const QString &text) 0037 { 0038 auto layout = new QVBoxLayout(parent); 0039 layout->addStretch(2); 0040 auto label = new QLabel(text, parent); 0041 label->setAlignment(Qt::AlignCenter); 0042 layout->addWidget(label); 0043 layout->addStretch(2); 0044 } 0045 0046 bool AgentConfigurationWidgetPrivate::loadPlugin(const QString &pluginPath) 0047 { 0048 if (pluginPath.isEmpty()) { 0049 qCDebug(AKONADIWIDGETS_LOG) << "Haven't found config plugin for" << agentInstance.type().identifier(); 0050 return false; 0051 } 0052 loader = decltype(loader)(new QPluginLoader(pluginPath)); 0053 if (!loader->load()) { 0054 qCWarning(AKONADIWIDGETS_LOG) << "Failed to load config plugin" << pluginPath << ":" << loader->errorString(); 0055 loader.reset(); 0056 return false; 0057 } 0058 factory = qobject_cast<AgentConfigurationFactoryBase *>(loader->instance()); 0059 if (!factory) { 0060 // will unload the QPluginLoader and thus delete the factory as well 0061 qCWarning(AKONADIWIDGETS_LOG) << "Config plugin" << pluginPath << "does not contain AgentConfigurationFactory!"; 0062 loader.reset(); 0063 return false; 0064 } 0065 0066 qCDebug(AKONADIWIDGETS_LOG) << "Loaded agent configuration plugin" << pluginPath; 0067 return true; 0068 } 0069 0070 AgentConfigurationWidget::AgentConfigurationWidget(const AgentInstance &instance, QWidget *parent) 0071 : QWidget(parent) 0072 , d(new AgentConfigurationWidgetPrivate(instance)) 0073 { 0074 if (AgentConfigurationManager::self()->registerInstanceConfiguration(instance.identifier())) { 0075 const auto pluginPath = AgentConfigurationManager::self()->findConfigPlugin(instance.type().identifier()); 0076 if (d->loadPlugin(pluginPath)) { 0077 QString configName = instance.identifier() + QStringLiteral("rc"); 0078 configName = Akonadi::ServerManager::addNamespace(configName); 0079 KSharedConfigPtr config = KSharedConfig::openConfig(configName); 0080 auto layout = new QVBoxLayout(this); 0081 layout->setContentsMargins({}); 0082 d->plugin = d->factory->create(config, this, {instance.identifier()}); 0083 connect(d->plugin.data(), &AgentConfigurationBase::enableOkButton, this, &AgentConfigurationWidget::enableOkButton); 0084 } else { 0085 // Hide this dialog and fallback to calling the out-of-process configuration 0086 if (auto dlg = qobject_cast<AgentConfigurationDialog *>(parent)) { 0087 const_cast<AgentInstance &>(instance).configure(topLevelWidget()->parentWidget()); 0088 // If we are inside the AgentConfigurationDialog, hide the dialog 0089 QTimer::singleShot(0s, this, [dlg]() { 0090 dlg->reject(); 0091 }); 0092 } else { 0093 const_cast<AgentInstance &>(instance).configure(); 0094 // Otherwise show a message that this is opened externally 0095 d->setupErrorWidget(this, i18n("The configuration dialog has been opened in another window")); 0096 } 0097 0098 // TODO: Re-enable once we can kill the fallback code above ^^ 0099 // d->setupErrorWidget(this, i18n("Failed to load configuration plugin")); 0100 } 0101 } else if (AgentConfigurationManager::self()->isInstanceRegistered(instance.identifier())) { 0102 d->setupErrorWidget(this, i18n("Configuration for %1 is already opened elsewhere.", instance.name())); 0103 } else { 0104 d->setupErrorWidget(this, i18n("Failed to register %1 configuration dialog.", instance.name())); 0105 } 0106 0107 QTimer::singleShot(0, this, &AgentConfigurationWidget::load); 0108 } 0109 0110 AgentConfigurationWidget::~AgentConfigurationWidget() 0111 { 0112 AgentConfigurationManager::self()->unregisterInstanceConfiguration(d->agentInstance.identifier()); 0113 } 0114 0115 void AgentConfigurationWidget::load() 0116 { 0117 if (d->plugin) { 0118 d->plugin->load(); 0119 } 0120 } 0121 0122 void AgentConfigurationWidget::save() 0123 { 0124 qCDebug(AKONADIWIDGETS_LOG) << "Saving configuration for" << d->agentInstance.identifier(); 0125 if (d->plugin) { 0126 if (d->plugin->save()) { 0127 d->agentInstance.reconfigure(); 0128 } 0129 } 0130 } 0131 0132 QSize AgentConfigurationWidget::restoreDialogSize() const 0133 { 0134 if (d->plugin) { 0135 return d->plugin->restoreDialogSize(); 0136 } 0137 return {}; 0138 } 0139 0140 void AgentConfigurationWidget::saveDialogSize(QSize size) 0141 { 0142 if (d->plugin) { 0143 d->plugin->saveDialogSize(size); 0144 } 0145 } 0146 0147 QDialogButtonBox::StandardButtons AgentConfigurationWidget::standardButtons() const 0148 { 0149 if (d->plugin) { 0150 return d->plugin->standardButtons(); 0151 } 0152 return QDialogButtonBox::Ok | QDialogButtonBox::Apply | QDialogButtonBox::Cancel; 0153 } 0154 0155 void AgentConfigurationWidget::childEvent(QChildEvent *event) 0156 { 0157 if (event->added()) { 0158 if (event->child()->isWidgetType()) { 0159 layout()->addWidget(static_cast<QWidget *>(event->child())); 0160 } 0161 } 0162 0163 QWidget::childEvent(event); 0164 } 0165 0166 #include "moc_agentconfigurationwidget.cpp"