1
/* This file is part of the KDE project
3
Copyright (c) 1999 Matthias Elter <elter@kde.org>
4
Copyright (c) 2003 Patrick Julien <freak@codepimps.org>
5
Copyright (c) 2005 Sven Langkamp <sven.langkamp@gmail.com>
6
Copyright (c) 2007 Jan Hambrecht <jaham@gmx.net>
8
This library is free software; you can redistribute it and/or
9
modify it under the terms of the GNU Lesser 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.
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
Lesser General Public License for more details.
18
You should have received a copy of the GNU Lesser General Public
19
License along with this library; if not, write to the Free Software
20
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23
#ifndef KORESOURCESERVER_H
24
#define KORESOURCESERVER_H
26
#include <QtCore/QMutex>
27
#include <QtCore/QMutexLocker>
28
#include <QtCore/QString>
29
#include <QtCore/QStringList>
30
#include <QtCore/QList>
31
#include <QtCore/QFileInfo>
34
#include <kstandarddirs.h>
35
#include <kcomponentdata.h>
37
#include "KoResource.h"
38
#include "KoResourceServerObserver.h"
40
#include "koresource_export.h"
47
* KoResourceServerBase is the base class of all resource servers
49
class KORESOURCES_EXPORT KoResourceServerBase {
53
* Constructs a KoResourceServerBase
54
* @param resource type, has to be the same as used by KStandardDirs
55
* @param extensions the file extensions separate by ':', e.g. "*.kgr:*.svg:*.ggr"
57
KoResourceServerBase(const QString& type, const QString& extensions)
59
, m_extensions(extensions)
64
virtual ~KoResourceServerBase() {}
66
virtual void loadResources(QStringList filenames) = 0;
67
QString type() { return m_type; }
70
* File extensions for resources of the server
71
* @returns the file extensions separated by ':', e.g. "*.kgr:*.svg:*.ggr"
73
QString extensions() { return m_extensions; }
75
void cancel() { m_cancelled = true; }
89
* KoResourceServer manages the resources of one type. It stores, loads and saves the resources.
90
* To keep track of changes the server can be observed with a KoResourceServerObserver
92
template <class T> class KoResourceServer : public KoResourceServerBase {
95
KoResourceServer(const QString& type, const QString& extensions)
96
: KoResourceServerBase(type, extensions)
101
virtual ~KoResourceServer()
106
* Loads a set of resources and adds them to the resource server.
107
* If a filename appears twice the resource will only be added once. Resources that can't
108
* be loaded or and invalid aren't added to the server.
109
* @param filenames list of filenames to be loaded
111
void loadResources(QStringList filenames) {
112
kDebug(30009) << "loading resources for type " << type();
113
QStringList uniqueFiles;
115
while (!filenames.empty() && !m_cancelled)
117
QString front = filenames.first();
118
filenames.pop_front();
120
QString fname = QFileInfo(front).fileName();
122
//kDebug(30009) << "Loading " << fname << " of type " << type();
123
// XXX: Don't load resources with the same filename. Actually, we should look inside
124
// the resource to find out whether they are really the same, but for now this
125
// will prevent the same brush etc. showing up twice.
126
if (uniqueFiles.empty() || uniqueFiles.indexOf(fname) == -1) {
128
uniqueFiles.append(fname);
129
T* resource = createResource(front);
130
if (resource->load() && resource->valid())
132
m_resourcesByFilename[front] = resource;
134
if ( resource->name().isNull() ) {
135
resource->setName( fname );
137
m_resourcesByName[resource->name()] = resource;
138
m_resources.append(resource);
140
notifyResourceAdded(resource);
141
Q_CHECK_PTR(resource);
149
kDebug(30009) << "done loading resources for type " << type();
153
/// Adds an already loaded resource to the server
154
bool addResource(T* resource) {
155
if (!resource->valid()) {
156
kWarning(30009) << "Tried to add an invalid resource!";
159
if( ! resource->save() ) {
160
kWarning(30009) << "Could not save resource!";
164
Q_ASSERT( !resource->filename().isEmpty() || !resource->name().isEmpty() );
165
if ( resource->filename().isEmpty() ) {
166
resource->setFilename( resource->name() );
168
else if ( resource->name().isEmpty() ) {
169
resource->setName( resource->filename() );
172
m_resourcesByFilename[resource->filename()] = resource;
173
m_resourcesByName[resource->name()] = resource;
174
m_resources.append(resource);
176
notifyResourceAdded(resource);
181
/// Remove a resource from resourceserver and hard disk
182
bool removeResource(T* resource) {
183
if ( !m_resourcesByFilename.contains( resource->filename() ) ) {
187
bool removedFromDisk = true;
189
QFile file( resource->filename() );
190
if( ! file.remove() ) {
192
// Don't do anything, it's probably write protected. In
193
// //future, we should store in config which read-only
194
// //resources the user has removed and blacklist them on
195
// app-start. But if we cannot remove a resource from the
196
// disk, remove it from the chooser at least.
198
removedFromDisk = false;
199
kWarning(30009) << "Could not remove resource!";
202
notifyRemovingResource(resource);
204
if (removedFromDisk) {
205
m_resourcesByName.remove(resource->name());
206
m_resourcesByFilename.remove(resource->filename());
207
m_resources.removeAt(m_resources.indexOf(resource));
210
// TODO: save blacklist to config file and load it again on next start
211
m_resourceBlackList << resource;
217
QList<T*> resources() {
219
QList<T*> resourceList = m_resources;
220
foreach(T* r, m_resourceBlackList) {
221
resourceList.removeOne(r);
227
/// Returns path where to save user defined and imported resources to
228
virtual QString saveLocation() {
229
return KGlobal::mainComponent().dirs()->saveLocation(type().toAscii());
233
* Creates a new resource from a given file and adds it to the resource server
234
* @param filename file name of the resource to be imported
235
* @return the imported resource, 0 if the import failed
237
T* importResource( const QString & filename ) {
238
QFileInfo fi( filename );
239
if( fi.exists() == false )
242
T* resource = createResource( filename );
244
if(!resource->valid()){
245
kWarning(30009) << "Import failed! Resource is not valid";
250
Q_ASSERT(!resource->defaultFileExtension().isEmpty());
251
Q_ASSERT(!saveLocation().isEmpty());
253
QString newFilename = saveLocation() + fi.baseName() + resource->defaultFileExtension();
254
resource->setFilename(newFilename);
255
if(!addResource(resource)) {
264
* Addes an observer to the server
265
* @param observer the observer to be added
266
* @param notifyLoadedResources determines if the observer should be notified about the already loaded resources
268
void addObserver(KoResourceServerObserver<T>* observer, bool notifyLoadedResources = true)
271
if(observer && !m_observers.contains(observer)) {
272
m_observers.append(observer);
274
if(notifyLoadedResources) {
275
foreach(T* resource, m_resourcesByFilename) {
276
observer->resourceAdded(resource);
284
* Removes an observer from the server
285
* @param observer the observer to be removed
287
void removeObserver(KoResourceServerObserver<T>* observer)
289
int index = m_observers.indexOf( observer );
293
m_observers.removeAt( index );
296
T* getResourceByFilename( const QString& filename )
298
if ( !m_resourcesByFilename.contains( filename ) ) {
302
return m_resourcesByFilename[filename];
306
T* getResourceByName( const QString& name )
308
if ( !m_resourcesByName.contains( name ) ) {
312
return m_resourcesByName[name];
317
virtual T* createResource( const QString & filename ) { return new T(filename); }
319
void notifyResourceAdded(T* resource)
321
foreach(KoResourceServerObserver<T>* observer, m_observers) {
322
observer->resourceAdded(resource);
326
void notifyRemovingResource(T* resource)
328
foreach(KoResourceServerObserver<T>* observer, m_observers)
329
observer->removingResource(resource);
335
QHash<QString, T*> m_resourcesByName;
336
QHash<QString, T*> m_resourcesByFilename;
337
QList<T*> m_resourceBlackList;
338
QList<T*> m_resources; ///< list of resources in order of addition
339
QList<KoResourceServerObserver<T>*> m_observers;
343
#endif // KORESOURCESERVER_H