1 | /* |
2 | This file is part of libkresources. |
3 | |
4 | Copyright (c) 2002 Tobias Koenig <tokoe@kde.org> |
5 | Copyright (c) 2002 Jan-Pascal van Best <janpascal@vanbest.org> |
6 | Copyright (c) 2003 Cornelius Schumacher <schumacher@kde.org> |
7 | |
8 | This library is free software; you can redistribute it and/or |
9 | modify it under the terms of the GNU Library General Public |
10 | License as published by the Free Software Foundation; either |
11 | version 2 of the License, or (at your option) any later version. |
12 | |
13 | This library is distributed in the hope that it will be useful, |
14 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
16 | Library General Public License for more details. |
17 | |
18 | You should have received a copy of the GNU Library General Public License |
19 | along with this library; see the file COPYING.LIB. If not, write to |
20 | the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
21 | Boston, MA 02110-1301, USA. |
22 | */ |
23 | /** |
24 | @file |
25 | This file is part of the KDE resource framework and defines the |
26 | Factory class. |
27 | |
28 | @brief |
29 | A class for loading resource plugins. |
30 | |
31 | @author Tobias Koenig |
32 | @author Jan-Pascal van Best |
33 | @author Cornelius Schumacher |
34 | */ |
35 | |
36 | #include "factory.h" |
37 | |
38 | #include <QtCore/QFile> |
39 | |
40 | #include <kdebug.h> |
41 | #include <klocalizedstring.h> |
42 | #include <kconfig.h> |
43 | #include <kconfiggroup.h> |
44 | #include <kprocess.h> |
45 | #include <kservicetypetrader.h> |
46 | #include <kpluginloader.h> |
47 | |
48 | #include "resource.h" |
49 | |
50 | using namespace KRES; |
51 | |
52 | class Factory::Private |
53 | { |
54 | public: |
55 | Resource *resourceInternal ( const QString &type, const KConfigGroup *group ); |
56 | QString mResourceFamily; |
57 | QMap<QString, KService::Ptr> mTypeMap; |
58 | }; |
59 | |
60 | class FactoryMap : public QMap<QString, Factory*> |
61 | { |
62 | public: |
63 | ~FactoryMap() { qDeleteAll( *this ); } |
64 | }; |
65 | |
66 | K_GLOBAL_STATIC( FactoryMap, mSelves ) |
67 | |
68 | Factory *Factory::self( const QString &resourceFamily ) |
69 | { |
70 | kDebug(); |
71 | |
72 | Factory *factory = 0; |
73 | |
74 | factory = mSelves->value( resourceFamily, 0 ); |
75 | |
76 | if ( !factory ) { |
77 | factory = new Factory( resourceFamily ); |
78 | mSelves->insert( resourceFamily, factory ); |
79 | |
80 | // Akonadi migration |
81 | KConfig config( QLatin1String("kres-migratorrc" ) ); |
82 | KConfigGroup migrationCfg( &config, "Migration" ); |
83 | const bool enabled = migrationCfg.readEntry( "Enabled" , false ); |
84 | const bool setupClientBrige = migrationCfg.readEntry( "SetupClientBridge" , true ); |
85 | const int currentVersion = migrationCfg.readEntry( QLatin1String("Version-" ) + resourceFamily, 0 ); |
86 | const int targetVersion = migrationCfg.readEntry( "TargetVersion" , 0 ); |
87 | if ( enabled && currentVersion < targetVersion ) { |
88 | kDebug() << "Performing Akonadi migration. Good luck!" ; |
89 | KProcess proc; |
90 | QStringList args = QStringList() << QLatin1String("--interactive-on-change" ) << QLatin1String("--type" ) << resourceFamily; |
91 | if ( !setupClientBrige ) { |
92 | args << QLatin1String("--omit-client-bridge" ); |
93 | } |
94 | proc.setProgram( QLatin1String("kres-migrator" ), args ); |
95 | proc.start(); |
96 | bool result = proc.waitForStarted(); |
97 | if ( result ) { |
98 | result = proc.waitForFinished(); |
99 | } |
100 | if ( result && proc.exitCode() == 0 ) { |
101 | kDebug() << "Akonadi migration has been successful" ; |
102 | migrationCfg.writeEntry( QLatin1String("Version-" ) + resourceFamily, targetVersion ); |
103 | migrationCfg.sync(); |
104 | } else if ( !result || proc.exitCode() != 1 ) { |
105 | // exit code 1 means it is already running, so we are probably called by a migrator instance |
106 | kError() << "Akonadi migration failed!" ; |
107 | kError() << "command was: " << proc.program(); |
108 | kError() << "exit code: " << proc.exitCode(); |
109 | kError() << "stdout: " << proc.readAllStandardOutput(); |
110 | kError() << "stderr: " << proc.readAllStandardError(); |
111 | } |
112 | } |
113 | |
114 | } |
115 | |
116 | return factory; |
117 | } |
118 | |
119 | Factory::Factory( const QString &resourceFamily ) : |
120 | d( new KRES::Factory::Private ) |
121 | { |
122 | d->mResourceFamily = resourceFamily; |
123 | reloadConfig(); |
124 | } |
125 | |
126 | void Factory::reloadConfig() |
127 | { |
128 | d->mTypeMap.clear(); |
129 | const KService::List plugins = |
130 | KServiceTypeTrader::self()->query( |
131 | QLatin1String("KResources/Plugin" ), |
132 | QString::fromLatin1( "[X-KDE-ResourceFamily] == '%1'" ).arg( d->mResourceFamily ) ); |
133 | |
134 | KService::List::ConstIterator it; |
135 | for ( it = plugins.begin(); it != plugins.end(); ++it ) { |
136 | const QVariant type = ( *it )->property( QLatin1String("X-KDE-ResourceType" ) ); |
137 | if ( !type.toString().isEmpty() ) { |
138 | d->mTypeMap.insert( type.toString(), *it ); |
139 | } |
140 | } |
141 | } |
142 | |
143 | Factory::~Factory() |
144 | { |
145 | delete d; |
146 | } |
147 | |
148 | QStringList Factory::typeNames() const |
149 | { |
150 | return d->mTypeMap.keys(); |
151 | } |
152 | |
153 | ConfigWidget *Factory::configWidget( const QString &type, QWidget *parent ) |
154 | { |
155 | if ( type.isEmpty() || !d->mTypeMap.contains( type ) ) { |
156 | return 0; |
157 | } |
158 | |
159 | KService::Ptr ptr = d->mTypeMap[ type ]; |
160 | KPluginLoader loader( ptr->library() ); |
161 | KPluginFactory *factory = loader.factory(); |
162 | if ( !factory ) { |
163 | kDebug() << "Factory creation failed: " << loader.errorString(); |
164 | return 0; |
165 | } |
166 | |
167 | PluginFactoryBase *pluginFactory = static_cast<PluginFactoryBase *>( factory ); |
168 | |
169 | if ( !pluginFactory ) { |
170 | kDebug() << "no plugin factory." ; |
171 | return 0; |
172 | } |
173 | |
174 | ConfigWidget *wdg = pluginFactory->configWidget( parent ); |
175 | if ( !wdg ) { |
176 | kDebug() << "'" << ptr->library() << "' doesn't provide a ConfigWidget" ; |
177 | return 0; |
178 | } |
179 | |
180 | return wdg; |
181 | } |
182 | |
183 | QString Factory::typeName( const QString &type ) const |
184 | { |
185 | if ( type.isEmpty() || !d->mTypeMap.contains( type ) ) { |
186 | return QString(); |
187 | } |
188 | |
189 | KService::Ptr ptr = d->mTypeMap[ type ]; |
190 | return ptr->name(); |
191 | } |
192 | |
193 | QString Factory::typeDescription( const QString &type ) const |
194 | { |
195 | if ( type.isEmpty() || !d->mTypeMap.contains( type ) ) { |
196 | return QString(); |
197 | } |
198 | |
199 | KService::Ptr ptr = d->mTypeMap[ type ]; |
200 | return ptr->comment(); |
201 | } |
202 | |
203 | Resource *Factory::Private::resourceInternal( const QString &type, const KConfigGroup *group ) |
204 | { |
205 | kDebug() << "(" << type << ", config )" ; |
206 | |
207 | if ( type.isEmpty() || !mTypeMap.contains( type ) ) { |
208 | kDebug() << "no such type" << type; |
209 | return 0; |
210 | } |
211 | |
212 | KService::Ptr ptr = mTypeMap[ type ]; |
213 | KPluginLoader loader( ptr->library() ); |
214 | KPluginFactory *factory = loader.factory(); |
215 | if ( !factory ) { |
216 | kDebug() << "Factory creation failed" << loader.errorString(); |
217 | return 0; |
218 | } |
219 | |
220 | PluginFactoryBase *pluginFactory = static_cast<PluginFactoryBase *>( factory ); |
221 | |
222 | if ( !pluginFactory ) { |
223 | kDebug() << "no plugin factory." ; |
224 | return 0; |
225 | } |
226 | |
227 | Resource *resource; |
228 | if ( group ) { |
229 | resource = pluginFactory->resource( *group ); |
230 | } else { |
231 | resource = pluginFactory->resource(); |
232 | } |
233 | |
234 | if ( !resource ) { |
235 | kDebug() << "'" << ptr->library() |
236 | << "' is not a" << mResourceFamily << "plugin." ; |
237 | return 0; |
238 | } |
239 | |
240 | resource->setType( type ); |
241 | |
242 | return resource; |
243 | } |
244 | |
245 | Resource *Factory::resource( const QString &type, const KConfigGroup &group ) |
246 | { |
247 | return d->resourceInternal( type, &group ); |
248 | } |
249 | |
250 | Resource *Factory::resource( const QString &type ) |
251 | { |
252 | return d->resourceInternal( type, 0 ); |
253 | } |
254 | |