1 | /* This file is part of the KDE project |
2 | Copyright 2008 Stefan Nikolaus <stefan.nikolaus@kdemail.net> |
3 | |
4 | This library is free software; you can redistribute it and/or |
5 | modify it under the terms of the GNU Library General Public |
6 | License as published by the Free Software Foundation; either |
7 | version 2 of the License, or (at your option) any later version. |
8 | |
9 | This library is distributed in the hope that it will be useful, |
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
12 | Library General Public License for more details. |
13 | |
14 | You should have received a copy of the GNU Library General Public License |
15 | along with this library; see the file COPYING.LIB. If not, write to |
16 | the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
17 | Boston, MA 02110-1301, USA. |
18 | */ |
19 | |
20 | #include "FunctionModuleRegistry.h" |
21 | |
22 | #include "Function.h" |
23 | #include "FunctionRepository.h" |
24 | |
25 | #include <kdebug.h> |
26 | #include <kglobal.h> |
27 | #include <kstandarddirs.h> |
28 | |
29 | #ifndef SHEETS_NO_PLUGINMODULES |
30 | #include <kplugininfo.h> |
31 | #include <kservicetypetrader.h> |
32 | #else |
33 | #include "functions/BitOpsModule.h" |
34 | #include "functions/ConversionModule.h" |
35 | #include "functions/DatabaseModule.h" |
36 | #include "functions/DateTimeModule.h" |
37 | #include "functions/EngineeringModule.h" |
38 | #include "functions/FinancialModule.h" |
39 | #include "functions/InformationModule.h" |
40 | #include "functions/LogicModule.h" |
41 | #include "functions/MathModule.h" |
42 | #include "functions/ReferenceModule.h" |
43 | #include "functions/StatisticalModule.h" |
44 | #include "functions/TextModule.h" |
45 | #include "functions/TrigonometryModule.h" |
46 | #endif |
47 | |
48 | using namespace Calligra::Sheets; |
49 | |
50 | class FunctionModuleRegistry::Private |
51 | { |
52 | public: |
53 | void registerFunctionModule(FunctionModule* module); |
54 | void removeFunctionModule(FunctionModule* module); |
55 | |
56 | public: |
57 | bool repositoryInitialized; |
58 | }; |
59 | |
60 | void FunctionModuleRegistry::Private::registerFunctionModule(FunctionModule* module) |
61 | { |
62 | const QList<QSharedPointer<Function> > functions = module->functions(); |
63 | for (int i = 0; i < functions.count(); ++i) { |
64 | FunctionRepository::self()->add(functions[i]); |
65 | } |
66 | Q_ASSERT(!module->descriptionFileName().isEmpty()); |
67 | const KStandardDirs* dirs = KGlobal::activeComponent().dirs(); |
68 | const QString fileName = dirs->findResource("functions" , module->descriptionFileName()); |
69 | if (fileName.isEmpty()) { |
70 | kDebug(36002) << module->descriptionFileName() << "not found." ; |
71 | return; |
72 | } |
73 | FunctionRepository::self()->loadFunctionDescriptions(fileName); |
74 | } |
75 | |
76 | void FunctionModuleRegistry::Private::removeFunctionModule(FunctionModule* module) |
77 | { |
78 | const QList<QSharedPointer<Function> > functions = module->functions(); |
79 | for (int i = 0; i < functions.count(); ++i) { |
80 | FunctionRepository::self()->remove(functions[i]); |
81 | } |
82 | } |
83 | |
84 | |
85 | FunctionModuleRegistry::FunctionModuleRegistry() |
86 | : d(new Private) |
87 | { |
88 | d->repositoryInitialized = false; |
89 | } |
90 | |
91 | FunctionModuleRegistry::~FunctionModuleRegistry() |
92 | { |
93 | foreach(const QString &id, keys()) { |
94 | get(id)->deleteLater(); |
95 | } |
96 | qDeleteAll(doubleEntries()); |
97 | delete d; |
98 | } |
99 | |
100 | FunctionModuleRegistry* FunctionModuleRegistry::instance() |
101 | { |
102 | K_GLOBAL_STATIC(FunctionModuleRegistry, s_instance) |
103 | return s_instance; |
104 | } |
105 | |
106 | void FunctionModuleRegistry::loadFunctionModules() |
107 | { |
108 | #ifndef SHEETS_NO_PLUGINMODULES |
109 | const quint32 minKSpreadVersion = CALLIGRA_MAKE_VERSION(2, 1, 0); |
110 | const QString serviceType = QLatin1String("CalligraSheets/Plugin" ); |
111 | const QString query = QLatin1String("([X-CalligraSheets-InterfaceVersion] == 0) and " |
112 | "([X-KDE-PluginInfo-Category] == 'FunctionModule')" ); |
113 | const KService::List offers = KServiceTypeTrader::self()->query(serviceType, query); |
114 | const KConfigGroup moduleGroup = KGlobal::config()->group("Plugins" ); |
115 | const KPluginInfo::List pluginInfos = KPluginInfo::fromServices(offers, moduleGroup); |
116 | kDebug(36002) << pluginInfos.count() << "function modules found." ; |
117 | foreach(KPluginInfo pluginInfo, pluginInfos) { |
118 | pluginInfo.load(); // load activation state |
119 | KPluginLoader loader(*pluginInfo.service()); |
120 | // Let's be paranoid: do not believe the service type. |
121 | if (loader.pluginVersion() < minKSpreadVersion) { |
122 | kDebug(36002) << pluginInfo.name() |
123 | << "was built against Caligra Sheets" << loader.pluginVersion() |
124 | << "; required version >=" << minKSpreadVersion; |
125 | continue; |
126 | } |
127 | if (pluginInfo.isPluginEnabled() && !contains(pluginInfo.pluginName())) { |
128 | // Plugin enabled, but not registered. Add it. |
129 | KPluginFactory* const factory = loader.factory(); |
130 | if (!factory) { |
131 | kDebug(36002) << "Unable to create plugin factory for" << pluginInfo.name(); |
132 | continue; |
133 | } |
134 | FunctionModule* const module = factory->create<FunctionModule>(); |
135 | if (!module) { |
136 | kDebug(36002) << "Unable to create function module for" << pluginInfo.name(); |
137 | continue; |
138 | } |
139 | add(pluginInfo.pluginName(), module); |
140 | |
141 | // Delays the function registration until the user needs one. |
142 | if (d->repositoryInitialized) { |
143 | d->registerFunctionModule(module); |
144 | } |
145 | } else if (!pluginInfo.isPluginEnabled() && contains(pluginInfo.pluginName())) { |
146 | // Plugin disabled, but registered. Remove it. |
147 | FunctionModule* const module = get(pluginInfo.pluginName()); |
148 | // Delay the function registration until the user needs one. |
149 | if (d->repositoryInitialized) { |
150 | d->removeFunctionModule(module); |
151 | } |
152 | remove(pluginInfo.pluginName()); |
153 | if (module->isRemovable()) { |
154 | delete module; |
155 | delete loader.factory(); |
156 | loader.unload(); |
157 | } else { |
158 | // Put it back in. |
159 | add(pluginInfo.pluginName(), module); |
160 | // Delay the function registration until the user needs one. |
161 | if (d->repositoryInitialized) { |
162 | d->registerFunctionModule(module); |
163 | } |
164 | } |
165 | } |
166 | } |
167 | #else |
168 | QList<FunctionModule*> modules; |
169 | QObject *parent = 0; |
170 | |
171 | modules << new BitOpsModule(parent); |
172 | modules << new ConversionModule(parent); |
173 | modules << new DatabaseModule(parent); |
174 | modules << new DateTimeModule(parent); |
175 | modules << new EngineeringModule(parent); |
176 | modules << new FinancialModule(parent); |
177 | modules << new InformationModule(parent); |
178 | modules << new LogicModule(parent); |
179 | modules << new MathModule(parent); |
180 | modules << new ReferenceModule(parent); |
181 | modules << new StatisticalModule(parent); |
182 | modules << new TextModule(parent); |
183 | modules << new TrigonometryModule(parent); |
184 | |
185 | Q_FOREACH(FunctionModule* module, modules) { |
186 | add(module->id(), module); |
187 | d->registerFunctionModule(module); |
188 | } |
189 | #endif |
190 | } |
191 | |
192 | void FunctionModuleRegistry::registerFunctions() |
193 | { |
194 | d->repositoryInitialized = true; |
195 | const QList<FunctionModule*> modules = values(); |
196 | for (int i = 0; i < modules.count(); ++i) { |
197 | d->registerFunctionModule(modules[i]); |
198 | } |
199 | } |
200 | |