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#ifndef KRESOURCES_MANAGER_H
25#define KRESOURCES_MANAGER_H
26
27#include "managerimpl.h"
28#include "factory.h"
29
30#include <kdebug.h>
31
32#include <QtCore/QList>
33#include <QtCore/QStringList>
34
35namespace KRES {
36
37class Resource;
38
39/**
40 Observer class for Manager class. For getting notified about changes of
41 Resources managed by a Manager object implement this Observer interface and
42 add an object of this implementation to the Manager using addObserver(). The
43 resourceAdded(), resourceModified() and resourceDeleted() functions of your
44 implementation will be called whenever resources managed by the Manager object
45 are added, modified or deleted.
46*/
47template<class T>
48class ManagerObserver
49{
50 public:
51 virtual ~ManagerObserver(){}
52 virtual void resourceAdded( T *resource ) = 0;
53 virtual void resourceModified( T *resource ) = 0;
54 virtual void resourceDeleted( T *resource ) = 0;
55};
56
57/**
58 @internal
59*/
60class ManagerNotifier
61{
62 public:
63 virtual ~ManagerNotifier(){}
64 virtual void notifyResourceAdded( Resource *resource ) = 0;
65 virtual void notifyResourceModified( Resource *resource ) = 0;
66 virtual void notifyResourceDeleted( Resource *resource ) = 0;
67};
68
69/**
70 This class provides a manager for resources of a specified family. It takes
71 care of loading and saving resource configurations and provides access to the
72 resources and their attributes. External changes in the resource configuration
73 are notified by the ManagerObserver interface. If your application needs to be
74 notified about resource configuration changes, you have to subclass
75 ManagerObserver and add it to the Manager by addObserver().
76
77 Since KDE 3.4 it's required to supply your application with a *.desktop
78 file for each resource family you introduce. The ServiceType should be of
79 KResources/Manager.
80*/
81template<class T>
82class Manager : private ManagerNotifier
83{
84 public:
85 /**
86 Iterator for iterations over all resources managed by a manager.
87 */
88 class Iterator
89 {
90 friend class Manager;
91 public:
92 Iterator() {}
93 Iterator( const Iterator &it ) { mIt = it.mIt; }
94
95 T *operator*() { return static_cast<T *>( *mIt ); }
96 Iterator &operator++()
97 {
98 mIt++;
99 return *this;
100 }
101 Iterator &operator++( int )
102 {
103 mIt++;
104 return *this;
105 }
106 Iterator &operator--()
107 {
108 mIt--;
109 return *this;
110 }
111 Iterator &operator--( int )
112 {
113 mIt--;
114 return *this;
115 }
116 bool operator==( const Iterator &it ) const
117 {
118 return mIt == it.mIt;
119 }
120 bool operator!=( const Iterator &it ) const
121 {
122 return mIt != it.mIt;
123 }
124
125 private:
126 Resource::List::Iterator mIt;
127 };
128
129 /**
130 Typedef for STL style iterator
131 */
132 typedef Iterator iterator;
133
134 /**
135 Return Iterator on first resource. If there is no resource returns end().
136 */
137 Iterator begin()
138 {
139 Iterator it;
140 it.mIt = mImpl->resourceList()->begin();
141 return it;
142 }
143
144 /**
145 Return Iterator indicating end of resource list.
146 */
147 Iterator end()
148 {
149 Iterator it;
150 it.mIt = mImpl->resourceList()->end();
151 return it;
152 }
153
154 /**
155 Iterator for iterations over only active resources managed by a manager.
156 */
157 class ActiveIterator
158 {
159 friend class Manager;
160 public:
161 ActiveIterator() : mList( 0 ) {}
162 ActiveIterator( const ActiveIterator &it )
163 {
164 mIt = it.mIt;
165 mList = it.mList;
166 }
167
168 T *operator*() { return static_cast<T *>( *mIt ); }
169 ActiveIterator &operator++()
170 {
171 do { mIt++; } while ( checkActive() );
172 return *this;
173 }
174 ActiveIterator &operator++( int )
175 {
176 do { mIt++; } while ( checkActive() );
177 return *this;
178 }
179 ActiveIterator &operator--()
180 {
181 do { mIt--; } while ( checkActive() );
182 return *this;
183 }
184 ActiveIterator &operator--( int )
185 {
186 do { mIt--; } while ( checkActive() );
187 return *this;
188 }
189 bool operator==( const ActiveIterator &it ) const { return mIt == it.mIt; }
190 bool operator!=( const ActiveIterator &it ) const { return mIt != it.mIt; }
191
192 private:
193 /**
194 Check if iterator needs to be advanced once more.
195 */
196 bool checkActive()
197 {
198 if ( !mList || mIt == mList->end() ) {
199 return false;
200 }
201 return !( *mIt )->isActive();
202 }
203
204 Resource::List::Iterator mIt;
205 Resource::List *mList;
206 };
207
208 /**
209 Return Iterator on first active resource. If there is no active resource
210 returns end().
211 */
212 ActiveIterator activeBegin()
213 {
214 ActiveIterator it;
215 it.mIt = mImpl->resourceList()->begin();
216 it.mList = mImpl->resourceList();
217 if ( it.mIt != mImpl->resourceList()->end() ) {
218 if ( !( *it )->isActive() ) {
219 it++;
220 }
221 }
222 return it;
223 }
224
225 /**
226 Return Iterator indicating end of active resource list.
227 */
228 ActiveIterator activeEnd()
229 {
230 ActiveIterator it;
231 it.mIt = mImpl->resourceList()->end();
232 it.mList = mImpl->resourceList();
233 return it;
234 }
235
236 /**
237 Return true, if manager doesn't hold any resources. If there are resources
238 return false.
239 */
240 bool isEmpty() const { return mImpl->resourceList()->isEmpty(); }
241
242 /**
243 Create manager for given resource family. The family argument is used as
244 identifier for loading and saving resource configurations.
245 */
246 Manager( const QString &family )
247 {
248 mFactory = Factory::self( family );
249 // The managerimpl will use the same Factory object as the manager
250 // because of the Factory::self() pattern
251 mImpl = new ManagerImpl( this, family );
252 }
253
254 virtual ~Manager()
255 {
256 delete mImpl;
257 }
258
259 /**
260 Recreate Resource objects from configuration file. If cfg is 0, read
261 standard configuration file determined by family name.
262 */
263 void readConfig( KConfig *cfg = 0 )
264 {
265 mImpl->readConfig( cfg );
266 }
267
268 /**
269 Write configuration of Resource objects to configuration file. If cfg is
270 0, write to standard configuration file determined by family name.
271 */
272 void writeConfig( KConfig *cfg = 0 )
273 {
274 mImpl->writeConfig( cfg );
275 }
276
277 /**
278 Add resource to manager. This passes ownership of the Resource object
279 to the manager.
280 */
281 void add( Resource *resource )
282 {
283 if ( resource ) {
284 mImpl->add( resource );
285 }
286 }
287
288 /**
289 Remove resource from manager. This deletes the Resource object.
290 */
291 void remove( Resource *resource )
292 {
293 if ( resource ) {
294 mImpl->remove( resource );
295 }
296 }
297
298 /**
299 Call this to notify manager about changes of the configuration of the
300 given resource.
301 */
302 void change( T *resource )
303 {
304 mImpl->change( resource );
305 }
306
307 /**
308 Return standard resource.
309 */
310 T *standardResource()
311 {
312 return static_cast<T *>( mImpl->standardResource() );
313 }
314
315 /**
316 Set standard resource.
317 */
318 void setStandardResource( T *resource )
319 {
320 if ( resource ) {
321 mImpl->setStandardResource( resource );
322 }
323 }
324
325 /**
326 Set active state of resource.
327 */
328 void setActive( Resource *resource, bool active )
329 {
330 if ( resource ) {
331 mImpl->setActive( resource, active );
332 }
333 }
334
335 /**
336 Returns a list of the names of the resources managed by the
337 Manager for this family.
338 */
339 QStringList resourceNames() const
340 {
341 return mImpl->resourceNames();
342 }
343
344 /**
345 Creates a new resource of type @p type with default
346 settings. The resource is
347 not added to the manager, the application has to do that.
348 Returns a pointer to a resource object or a null pointer
349 if resource type doesn't exist.
350
351 @param type The type of the resource, one of those returned
352 by resourceTypeNames()
353 */
354 T *createResource( const QString &type )
355 {
356 return dynamic_cast<T *>( mFactory->resource( type ) );
357 }
358
359 /**
360 Returns a list of the names of all available resource types.
361 */
362 QStringList resourceTypeNames() const
363 {
364 return mFactory->typeNames();
365 }
366
367 /**
368 Return list of descriptions of all available resource types.
369 */
370 QStringList resourceTypeDescriptions() const
371 {
372 QStringList typeDescs;
373 const QStringList types = mFactory->typeNames();
374
375 for ( QStringList::ConstIterator it = types.constBegin(); it != types.constEnd(); ++it ) {
376 QString desc = mFactory->typeName( *it );
377 if ( !mFactory->typeDescription( *it ).isEmpty() ) {
378 desc += QLatin1String( " (" ) + mFactory->typeDescription( *it ) + QLatin1Char( ')' );
379 }
380
381 typeDescs.append( desc );
382 }
383
384 return typeDescs;
385 }
386
387 /**
388 Add observer for resource changes to manager. See ManagerObserver. The
389 Manager does not take ownership of the Observer object.
390 */
391 void addObserver( ManagerObserver<T> *observer )
392 {
393 mObservers.append( observer );
394 }
395
396 /**
397 Remove Observer for resource changes from manager. See ManagerObserver.
398 The Observer is not deleted by the Manager after being removed.
399 */
400 void removeObserver( ManagerObserver<T> *observer )
401 {
402 mObservers.removeAll( observer );
403 }
404
405 private:
406 /**
407 Implementation of the ManagerNotifier interface.
408 */
409 void notifyResourceAdded( Resource *res )
410 {
411 kDebug() << res->resourceName();
412 T *resource = dynamic_cast<T *>( res );
413 if ( resource ) {
414 for ( int i = 0; i < mObservers.size(); ++i ) {
415 mObservers.at( i )->resourceAdded( resource );
416 }
417 }
418 }
419
420 /**
421 Implementation of the ManagerNotifier interface.
422 */
423 void notifyResourceModified( Resource *res )
424 {
425 kDebug() << res->resourceName();
426 T *resource = dynamic_cast<T *>( res );
427 if ( resource ) {
428 for ( int i = 0; i < mObservers.size(); ++i ) {
429 mObservers.at( i )->resourceAdded( resource );
430 }
431 }
432 }
433
434 /**
435 Implementation of the ManagerNotifier interface.
436 */
437 void notifyResourceDeleted( Resource *res )
438 {
439 kDebug() << res->resourceName();
440 T *resource = dynamic_cast<T *>( res );
441 if ( resource ) {
442 for ( int i = 0; i < mObservers.size(); ++i ) {
443 mObservers.at( i )->resourceDeleted( resource );
444 }
445 }
446 }
447
448 private:
449 ManagerImpl *mImpl;
450 Factory *mFactory;
451 QList<ManagerObserver<T> *> mObservers;
452};
453
454}
455
456#endif
457