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 | |
35 | namespace KRES { |
36 | |
37 | class 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 | */ |
47 | template<class T> |
48 | class 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 | */ |
60 | class 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 | */ |
81 | template<class T> |
82 | class 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 | |