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 | #include "managerimpl.h" |
24 | |
25 | #include <kaboutdata.h> |
26 | #include <krandom.h> |
27 | #include <kdebug.h> |
28 | #include <kconfig.h> |
29 | #include <kstandarddirs.h> |
30 | #include <kconfiggroup.h> |
31 | |
32 | #include <QtDBus/QtDBus> |
33 | |
34 | #include "resource.h" |
35 | #include "factory.h" |
36 | #include "manager.h" |
37 | #include "kresourcesmanageradaptor.h" |
38 | |
39 | using namespace KRES; |
40 | |
41 | class ManagerImpl::ManagerImplPrivate |
42 | { |
43 | public: |
44 | ManagerNotifier *mNotifier; |
45 | QString mFamily; |
46 | KConfig *mConfig; |
47 | KConfig *mStdConfig; |
48 | Resource *mStandard; |
49 | Factory *mFactory; |
50 | Resource::List mResources; |
51 | QString mId; |
52 | bool mConfigRead; |
53 | |
54 | }; |
55 | |
56 | ManagerImpl::ManagerImpl( ManagerNotifier *notifier, const QString &family ) |
57 | : d( new ManagerImplPrivate ) |
58 | { |
59 | d->mNotifier = notifier; |
60 | d->mFamily = family; |
61 | d->mConfig = 0; |
62 | d->mStdConfig = 0; |
63 | d->mStandard = 0; |
64 | d->mFactory = 0; |
65 | d->mConfigRead = false; |
66 | |
67 | new KResourcesManagerAdaptor( this ); |
68 | const QString dBusPath = QLatin1String( "/ManagerIface_" ) + family; |
69 | QDBusConnection::sessionBus().registerObject( dBusPath, this ); |
70 | kDebug(); |
71 | |
72 | d->mId = KRandom::randomString( 8 ); |
73 | |
74 | // Register with D-Bus |
75 | QDBusConnection::sessionBus().registerService( QLatin1String("org.kde.KResourcesManager" ) ); |
76 | |
77 | QDBusConnection::sessionBus().connect( QString(), dBusPath, |
78 | QLatin1String("org.kde.KResourcesManager" ), QLatin1String("signalKResourceAdded" ), |
79 | this, SLOT(dbusKResourceAdded(QString,QString))); |
80 | QDBusConnection::sessionBus().connect( QString(), dBusPath, |
81 | QLatin1String("org.kde.KResourcesManager" ), QLatin1String("signalKResourceModified" ), |
82 | this, SLOT(dbusKResourceModified(QString,QString))); |
83 | QDBusConnection::sessionBus().connect( QString(), dBusPath, |
84 | QLatin1String("org.kde.KResourcesManager" ), QLatin1String("signalKResourceDeleted" ), |
85 | this, SLOT(dbusKResourceDeleted(QString,QString))); |
86 | } |
87 | |
88 | ManagerImpl::~ManagerImpl() |
89 | { |
90 | kDebug(); |
91 | |
92 | qDeleteAll( d->mResources ); |
93 | delete d->mStdConfig; |
94 | delete d; |
95 | } |
96 | |
97 | void ManagerImpl::createStandardConfig() |
98 | { |
99 | if ( !d->mStdConfig ) { |
100 | QString file = defaultConfigFile( d->mFamily ); |
101 | d->mStdConfig = new KConfig( file ); |
102 | } |
103 | |
104 | d->mConfig = d->mStdConfig; |
105 | } |
106 | |
107 | void ManagerImpl::readConfig( KConfig *cfg ) |
108 | { |
109 | kDebug(); |
110 | |
111 | if ( d->mFactory ) { |
112 | d->mFactory->reloadConfig(); |
113 | } else { |
114 | d->mFactory = Factory::self( d->mFamily ); |
115 | } |
116 | |
117 | if ( !cfg ) { |
118 | createStandardConfig(); |
119 | } else { |
120 | d->mConfig = cfg; |
121 | } |
122 | |
123 | d->mStandard = 0; |
124 | KConfigGroup group = d->mConfig->group( "General" ); |
125 | |
126 | QStringList keys = group.readEntry( "ResourceKeys" , QStringList() ); |
127 | keys += group.readEntry( "PassiveResourceKeys" , QStringList() ); |
128 | |
129 | const QString standardKey = group.readEntry( "Standard" ); |
130 | |
131 | for ( QStringList::const_iterator it = keys.constBegin(); it != keys.constEnd(); ++it ) { |
132 | readResourceConfig( *it, false ); |
133 | } |
134 | |
135 | d->mConfigRead = true; |
136 | } |
137 | |
138 | void ManagerImpl::writeConfig( KConfig *cfg ) |
139 | { |
140 | kDebug(); |
141 | |
142 | if ( !cfg ) { |
143 | createStandardConfig(); |
144 | } else { |
145 | d->mConfig = cfg; |
146 | } |
147 | |
148 | QStringList activeKeys; |
149 | QStringList passiveKeys; |
150 | |
151 | // First write all keys, collect active and passive keys on the way |
152 | Resource::List::Iterator it; |
153 | for ( it = d->mResources.begin(); it != d->mResources.end(); ++it ) { |
154 | writeResourceConfig( *it, false ); |
155 | |
156 | QString key = ( *it )->identifier(); |
157 | if ( ( *it )->isActive() ) { |
158 | activeKeys.append( key ); |
159 | } else { |
160 | passiveKeys.append( key ); |
161 | } |
162 | } |
163 | |
164 | // And then the general group |
165 | |
166 | kDebug() << "Saving general info" ; |
167 | KConfigGroup group = d->mConfig->group( "General" ); |
168 | group.writeEntry( "ResourceKeys" , activeKeys ); |
169 | group.writeEntry( "PassiveResourceKeys" , passiveKeys ); |
170 | if ( d->mStandard ) { |
171 | group.writeEntry( "Standard" , d->mStandard->identifier() ); |
172 | } else { |
173 | group.writeEntry( "Standard" , QString() ); |
174 | } |
175 | |
176 | group.sync(); |
177 | kDebug() << "finished" ; |
178 | } |
179 | |
180 | void ManagerImpl::add( Resource *resource ) |
181 | { |
182 | resource->setActive( true ); |
183 | |
184 | if ( d->mResources.isEmpty() ) { |
185 | d->mStandard = resource; |
186 | } |
187 | |
188 | d->mResources.append( resource ); |
189 | |
190 | if ( d->mConfigRead ) { |
191 | writeResourceConfig( resource, true ); |
192 | } |
193 | |
194 | signalKResourceAdded( d->mId, resource->identifier() ); |
195 | } |
196 | |
197 | void ManagerImpl::remove( Resource *resource ) |
198 | { |
199 | if ( d->mStandard == resource ) { |
200 | d->mStandard = 0; |
201 | } |
202 | removeResource( resource ); |
203 | |
204 | d->mResources.removeAll( resource ); |
205 | |
206 | signalKResourceDeleted( d->mId, resource->identifier() ); |
207 | |
208 | delete resource; |
209 | |
210 | kDebug() << "Finished" ; |
211 | } |
212 | |
213 | void ManagerImpl::change( Resource *resource ) |
214 | { |
215 | writeResourceConfig( resource, true ); |
216 | |
217 | signalKResourceModified( d->mId, resource->identifier() ); |
218 | } |
219 | |
220 | void ManagerImpl::setActive( Resource *resource, bool active ) |
221 | { |
222 | if ( resource && resource->isActive() != active ) { |
223 | resource->setActive( active ); |
224 | } |
225 | } |
226 | |
227 | Resource *ManagerImpl::standardResource() |
228 | { |
229 | return d->mStandard; |
230 | } |
231 | |
232 | void ManagerImpl::setStandardResource( Resource *resource ) |
233 | { |
234 | d->mStandard = resource; |
235 | } |
236 | |
237 | // DBUS asynchronous functions |
238 | |
239 | void ManagerImpl::dbusKResourceAdded( const QString &managerId, |
240 | const QString &resourceId ) |
241 | { |
242 | if ( managerId == d->mId ) { |
243 | kDebug() << "Ignore D-Bus notification to myself" ; |
244 | return; |
245 | } |
246 | kDebug() << "Receive D-Bus call: added resource" << resourceId; |
247 | |
248 | if ( getResource( resourceId ) ) { |
249 | kDebug() << "This resource is already known to me." ; |
250 | } |
251 | |
252 | if ( !d->mConfig ) { |
253 | createStandardConfig(); |
254 | } |
255 | |
256 | d->mConfig->reparseConfiguration(); |
257 | Resource *resource = readResourceConfig( resourceId, true ); |
258 | |
259 | if ( resource ) { |
260 | d->mNotifier->notifyResourceAdded( resource ); |
261 | } else { |
262 | kError() << "Received D-Bus: resource added for unknown resource" |
263 | << resourceId; |
264 | } |
265 | } |
266 | |
267 | void ManagerImpl::dbusKResourceModified( const QString &managerId, |
268 | const QString &resourceId ) |
269 | { |
270 | if ( managerId == d->mId ) { |
271 | kDebug() << "Ignore D-Bus notification to myself" ; |
272 | return; |
273 | } |
274 | kDebug() << "Receive D-Bus call: modified resource" << resourceId; |
275 | |
276 | Resource *resource = getResource( resourceId ); |
277 | if ( resource ) { |
278 | d->mNotifier->notifyResourceModified( resource ); |
279 | } else { |
280 | kError() << "Received D-Bus: resource modified for unknown resource" |
281 | << resourceId; |
282 | } |
283 | } |
284 | |
285 | void ManagerImpl::dbusKResourceDeleted( const QString &managerId, |
286 | const QString &resourceId ) |
287 | { |
288 | if ( managerId == d->mId ) { |
289 | kDebug() << "Ignore D-Bus notification to myself" ; |
290 | return; |
291 | } |
292 | kDebug() << "Receive D-Bus call: deleted resource" << resourceId; |
293 | |
294 | Resource *resource = getResource( resourceId ); |
295 | if ( resource ) { |
296 | d->mNotifier->notifyResourceDeleted( resource ); |
297 | |
298 | kDebug() << "Removing item from mResources" ; |
299 | // Now delete item |
300 | if ( d->mStandard == resource ) { |
301 | d->mStandard = 0; |
302 | } |
303 | d->mResources.removeAll( resource ); |
304 | } else { |
305 | kError() << "Received D-Bus: resource deleted for unknown resource" |
306 | << resourceId; |
307 | } |
308 | } |
309 | |
310 | QStringList ManagerImpl::resourceNames() |
311 | { |
312 | QStringList result; |
313 | |
314 | Resource::List::ConstIterator it; |
315 | Resource::List::ConstIterator end(d->mResources.constEnd()); |
316 | for ( it = d->mResources.constBegin(); it != end; ++it ) { |
317 | result.append( ( *it )->resourceName() ); |
318 | } |
319 | return result; |
320 | } |
321 | |
322 | Resource::List *ManagerImpl::resourceList() |
323 | { |
324 | return &d->mResources; |
325 | } |
326 | |
327 | QList<Resource *> ManagerImpl::resources() |
328 | { |
329 | return QList<Resource *>( d->mResources ); |
330 | } |
331 | |
332 | QList<Resource *> ManagerImpl::resources( bool active ) |
333 | { |
334 | QList<Resource *> result; |
335 | |
336 | for ( int i = 0; i < d->mResources.size(); ++i ) { |
337 | if ( d->mResources.at( i )->isActive() == active ) { |
338 | result.append( d->mResources.at( i ) ); |
339 | } |
340 | } |
341 | return result; |
342 | } |
343 | |
344 | Resource *ManagerImpl::readResourceConfig( const QString &identifier, |
345 | bool checkActive ) |
346 | { |
347 | kDebug() << identifier; |
348 | |
349 | if ( !d->mFactory ) { |
350 | kError() << "mFactory is 0. Did the app forget to call readConfig?" ; |
351 | return 0; |
352 | } |
353 | |
354 | KConfigGroup group = d->mConfig->group( QLatin1String("Resource_" ) + identifier ); |
355 | |
356 | QString type = group.readEntry( "ResourceType" ); |
357 | QString name = group.readEntry( "ResourceName" ); |
358 | Resource *resource = d->mFactory->resource( type, group ); |
359 | if ( !resource ) { |
360 | kDebug() << "Failed to create resource with id" << identifier; |
361 | return 0; |
362 | } |
363 | |
364 | if ( resource->identifier().isEmpty() ) { |
365 | resource->setIdentifier( identifier ); |
366 | } |
367 | |
368 | group = d->mConfig->group( "General" ); |
369 | |
370 | QString standardKey = group.readEntry( "Standard" ); |
371 | if ( standardKey == identifier ) { |
372 | d->mStandard = resource; |
373 | } |
374 | |
375 | if ( checkActive ) { |
376 | QStringList activeKeys = group.readEntry( "ResourceKeys" , QStringList() ); |
377 | resource->setActive( activeKeys.contains( identifier ) ); |
378 | } |
379 | d->mResources.append( resource ); |
380 | |
381 | return resource; |
382 | } |
383 | |
384 | void ManagerImpl::writeResourceConfig( Resource *resource, bool checkActive ) |
385 | { |
386 | QString key = resource->identifier(); |
387 | |
388 | kDebug() << "Saving resource" << key; |
389 | |
390 | if ( !d->mConfig ) { |
391 | createStandardConfig(); |
392 | } |
393 | |
394 | KConfigGroup group( d->mConfig, QLatin1String("Resource_" ) + key ); |
395 | resource->writeConfig( group ); |
396 | |
397 | group = d->mConfig->group( "General" ); |
398 | QString standardKey = group.readEntry( "Standard" ); |
399 | |
400 | if ( resource == d->mStandard && standardKey != key ) { |
401 | group.writeEntry( "Standard" , resource->identifier() ); |
402 | } else if ( resource != d->mStandard && standardKey == key ) { |
403 | group.writeEntry( "Standard" , "" ); |
404 | } |
405 | |
406 | if ( checkActive ) { |
407 | QStringList activeKeys = group.readEntry( "ResourceKeys" , QStringList() ); |
408 | QStringList passiveKeys = group.readEntry( "PassiveResourceKeys" , QStringList() ); |
409 | if ( resource->isActive() ) { |
410 | if ( passiveKeys.contains( key ) ) { // remove it from passive list |
411 | passiveKeys.removeAll( key ); |
412 | group.writeEntry( "PassiveResourceKeys" , passiveKeys ); |
413 | } |
414 | if ( !activeKeys.contains( key ) ) { // add it to active list |
415 | activeKeys.append( key ); |
416 | group.writeEntry( "ResourceKeys" , activeKeys ); |
417 | } |
418 | } else if ( !resource->isActive() ) { |
419 | if ( activeKeys.contains( key ) ) { // remove it from active list |
420 | activeKeys.removeAll( key ); |
421 | group.writeEntry( "ResourceKeys" , activeKeys ); |
422 | } |
423 | if ( !passiveKeys.contains( key ) ) { // add it to passive list |
424 | passiveKeys.append( key ); |
425 | group.writeEntry( "PassiveResourceKeys" , passiveKeys ); |
426 | } |
427 | } |
428 | } |
429 | |
430 | d->mConfig->sync(); |
431 | } |
432 | |
433 | void ManagerImpl::removeResource( Resource *resource ) |
434 | { |
435 | QString key = resource->identifier(); |
436 | |
437 | if ( !d->mConfig ) { |
438 | createStandardConfig(); |
439 | } |
440 | |
441 | KConfigGroup group = d->mConfig->group( "General" ); |
442 | QStringList activeKeys = group.readEntry( "ResourceKeys" , QStringList() ); |
443 | if ( activeKeys.contains( key ) ) { |
444 | activeKeys.removeAll( key ); |
445 | group.writeEntry( "ResourceKeys" , activeKeys ); |
446 | } else { |
447 | QStringList passiveKeys= group.readEntry( "PassiveResourceKeys" , QStringList() ); |
448 | passiveKeys.removeAll( key ); |
449 | group.writeEntry( "PassiveResourceKeys" , passiveKeys ); |
450 | } |
451 | |
452 | QString standardKey = group.readEntry( "Standard" ); |
453 | if ( standardKey == key ) { |
454 | group.writeEntry( "Standard" , "" ); |
455 | } |
456 | |
457 | d->mConfig->deleteGroup( QLatin1String("Resource_" ) + resource->identifier() ); |
458 | group.sync(); |
459 | } |
460 | |
461 | Resource *ManagerImpl::getResource( const QString &identifier ) |
462 | { |
463 | Resource::List::ConstIterator it; |
464 | for ( it = d->mResources.constBegin(); it != d->mResources.constEnd(); ++it ) { |
465 | if ( ( *it )->identifier() == identifier ) { |
466 | return *it; |
467 | } |
468 | } |
469 | return 0; |
470 | } |
471 | |
472 | QString ManagerImpl::defaultConfigFile( const QString &family ) |
473 | { |
474 | return KStandardDirs::locateLocal( "config" , |
475 | QString::fromLatin1( "kresources/%1/stdrc" ).arg( family ) ); |
476 | } |
477 | |
478 | |