File indexing completed on 2024-04-28 16:21:23
0001 /* This file is part of the KDE project 0002 Copyright 2008 Stefan Nikolaus <stefan.nikolaus@kdemail.net> 0003 0004 This library is free software; you can redistribute it and/or 0005 modify it under the terms of the GNU Library General Public 0006 License as published by the Free Software Foundation; either 0007 version 2 of the License, or (at your option) any later version. 0008 0009 This library is distributed in the hope that it will be useful, 0010 but WITHOUT ANY WARRANTY; without even the implied warranty of 0011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0012 Library General Public License for more details. 0013 0014 You should have received a copy of the GNU Library General Public License 0015 along with this library; see the file COPYING.LIB. If not, write to 0016 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0017 Boston, MA 02110-1301, USA. 0018 */ 0019 0020 #include "FunctionModuleRegistry.h" 0021 0022 #include "SheetsDebug.h" 0023 #include "Function.h" 0024 #include "FunctionRepository.h" 0025 0026 #include <QGlobalStatic> 0027 #include <KSharedConfig> 0028 0029 #ifndef SHEETS_NO_PLUGINMODULES 0030 #include <kplugininfo.h> 0031 #include <KPluginFactory> 0032 #include <KoPluginLoader.h> 0033 #else 0034 #include "functions/BitOpsModule.h" 0035 #include "functions/ConversionModule.h" 0036 #include "functions/DatabaseModule.h" 0037 #include "functions/DateTimeModule.h" 0038 #include "functions/EngineeringModule.h" 0039 #include "functions/FinancialModule.h" 0040 #include "functions/InformationModule.h" 0041 #include "functions/LogicModule.h" 0042 #include "functions/MathModule.h" 0043 #include "functions/ReferenceModule.h" 0044 #include "functions/StatisticalModule.h" 0045 #include "functions/TextModule.h" 0046 #include "functions/TrigonometryModule.h" 0047 #endif 0048 0049 Q_GLOBAL_STATIC(Calligra::Sheets::FunctionModuleRegistry, s_instance) 0050 0051 using namespace Calligra::Sheets; 0052 0053 class Q_DECL_HIDDEN FunctionModuleRegistry::Private 0054 { 0055 public: 0056 void registerFunctionModule(FunctionModule* module); 0057 void removeFunctionModule(FunctionModule* module); 0058 0059 public: 0060 bool repositoryInitialized; 0061 }; 0062 0063 void FunctionModuleRegistry::Private::registerFunctionModule(FunctionModule* module) 0064 { 0065 const QList<QSharedPointer<Function> > functions = module->functions(); 0066 for (int i = 0; i < functions.count(); ++i) { 0067 FunctionRepository::self()->add(functions[i]); 0068 } 0069 Q_ASSERT(!module->descriptionFileName().isEmpty()); 0070 const QString fileName = QStandardPaths::locate(QStandardPaths::GenericDataLocation, 0071 QStringLiteral("calligrasheets/functions/")+module->descriptionFileName()); 0072 if (fileName.isEmpty()) { 0073 debugSheetsFormula << module->descriptionFileName() << "not found."; 0074 return; 0075 } 0076 FunctionRepository::self()->loadFunctionDescriptions(fileName); 0077 } 0078 0079 void FunctionModuleRegistry::Private::removeFunctionModule(FunctionModule* module) 0080 { 0081 const QList<QSharedPointer<Function> > functions = module->functions(); 0082 for (int i = 0; i < functions.count(); ++i) { 0083 FunctionRepository::self()->remove(functions[i]); 0084 } 0085 } 0086 0087 0088 FunctionModuleRegistry::FunctionModuleRegistry() 0089 : d(new Private) 0090 { 0091 d->repositoryInitialized = false; 0092 } 0093 0094 FunctionModuleRegistry::~FunctionModuleRegistry() 0095 { 0096 foreach(const QString &id, keys()) { 0097 get(id)->deleteLater(); 0098 } 0099 qDeleteAll(doubleEntries()); 0100 delete d; 0101 } 0102 0103 FunctionModuleRegistry* FunctionModuleRegistry::instance() 0104 { 0105 return s_instance; 0106 } 0107 0108 void FunctionModuleRegistry::loadFunctionModules() 0109 { 0110 #ifndef SHEETS_NO_PLUGINMODULES 0111 const QList<QPluginLoader *> offers = KoPluginLoader::pluginLoaders(QStringLiteral("calligrasheets/functions")); 0112 debugSheetsFormula << offers.count() << "function modules found."; 0113 0114 const KConfigGroup pluginsConfigGroup = KSharedConfig::openConfig()->group("Plugins"); 0115 foreach (QPluginLoader *loader, offers) { 0116 0117 QJsonObject metaData = loader->metaData().value("MetaData").toObject(); 0118 int version = metaData.value("X-CalligraSheets-InterfaceVersion").toInt(); 0119 if (version != 0) { 0120 debugSheetsFormula << "Skipping" << loader->fileName() << ", because interface version is" << version; 0121 continue; 0122 } 0123 QJsonObject pluginData = metaData.value("KPlugin").toObject(); 0124 QString category = pluginData.value("Category").toString(); 0125 if (category != "FunctionModule") { 0126 debugSheetsFormula << "Skipping" << loader->fileName() << ", because category is " << category; 0127 continue; 0128 } 0129 0130 const QString pluginId = pluginData.value("Id").toString(); 0131 const QString pluginConfigEnableKey = pluginId + QLatin1String("Enabled"); 0132 const bool isPluginEnabled = pluginsConfigGroup.hasKey(pluginConfigEnableKey) ? 0133 pluginsConfigGroup.readEntry(pluginConfigEnableKey, true) : 0134 pluginData.value("EnabledByDefault").toBool(true); 0135 0136 if (isPluginEnabled) { 0137 if(contains(pluginId)) { 0138 continue; 0139 } 0140 // Plugin enabled, but not registered. Add it. 0141 KPluginFactory* const factory = qobject_cast<KPluginFactory *>(loader->instance()); 0142 if (!factory) { 0143 debugSheetsFormula << "Unable to create plugin factory for" << loader->fileName(); 0144 continue; 0145 } 0146 FunctionModule* const module = qobject_cast<FunctionModule *>(factory->create()); 0147 if (!module) { 0148 debugSheetsFormula << "Unable to create function module for" << loader->fileName(); 0149 continue; 0150 } 0151 0152 add(pluginId, module); 0153 debugSheetsFormula << "Loaded" << pluginId; 0154 0155 // Delays the function registration until the user needs one. 0156 if (d->repositoryInitialized) { 0157 d->registerFunctionModule(module); 0158 } 0159 } else { 0160 if (!contains(pluginId)) { 0161 continue; 0162 } 0163 // Plugin disabled, but registered. Remove it. 0164 FunctionModule* const module = get(pluginId); 0165 // Delay the function registration until the user needs one. 0166 if (d->repositoryInitialized) { 0167 d->removeFunctionModule(module); 0168 } 0169 remove(pluginId); 0170 if (module->isRemovable()) { 0171 delete module; 0172 KPluginFactory* factory = qobject_cast<KPluginFactory *>(loader->instance()); 0173 delete factory; 0174 loader->unload(); 0175 } else { 0176 // Put it back in. 0177 add(pluginId, module); 0178 // Delay the function registration until the user needs one. 0179 if (d->repositoryInitialized) { 0180 d->registerFunctionModule(module); 0181 } 0182 } 0183 } 0184 } 0185 qDeleteAll(offers); 0186 #else 0187 QList<FunctionModule*> modules; 0188 QObject *parent = 0; 0189 0190 modules << new BitOpsModule(parent); 0191 modules << new ConversionModule(parent); 0192 modules << new DatabaseModule(parent); 0193 modules << new DateTimeModule(parent); 0194 modules << new EngineeringModule(parent); 0195 modules << new FinancialModule(parent); 0196 modules << new InformationModule(parent); 0197 modules << new LogicModule(parent); 0198 modules << new MathModule(parent); 0199 modules << new ReferenceModule(parent); 0200 modules << new StatisticalModule(parent); 0201 modules << new TextModule(parent); 0202 modules << new TrigonometryModule(parent); 0203 0204 Q_FOREACH(FunctionModule* module, modules) { 0205 add(module->id(), module); 0206 d->registerFunctionModule(module); 0207 } 0208 #endif 0209 } 0210 0211 void FunctionModuleRegistry::registerFunctions() 0212 { 0213 d->repositoryInitialized = true; 0214 const QList<FunctionModule*> modules = values(); 0215 for (int i = 0; i < modules.count(); ++i) { 0216 d->registerFunctionModule(modules[i]); 0217 } 0218 }