~ubuntu-branches/ubuntu/precise/koffice/precise

« back to all changes in this revision

Viewing changes to libs/resources/KoResourceServer.h

  • Committer: Bazaar Package Importer
  • Author(s): Jonathan Riddell
  • Date: 2010-09-21 15:36:35 UTC
  • mfrom: (1.4.1 upstream) (60.2.11 maverick)
  • Revision ID: james.westby@ubuntu.com-20100921153635-6tejqkiro2u21ydi
Tags: 1:2.2.2-0ubuntu3
Add kubuntu_03_fix-crash-on-closing-sqlite-connection-2.2.2.diff and
kubuntu_04_support-large-memo-values-for-msaccess-2.2.2.diff as
recommended by upstream http://kexi-
project.org/wiki/wikiview/index.php@Kexi2.2_Patches.html#sqlite_stab
ility

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*  This file is part of the KDE project
2
 
 
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>
7
 
 
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.
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
 
    Lesser General Public License for more details.
17
 
 
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
21
 
 */
22
 
 
23
 
#ifndef KORESOURCESERVER_H
24
 
#define KORESOURCESERVER_H
25
 
 
26
 
#include <QtCore/QMutex>
27
 
#include <QtCore/QMutexLocker>
28
 
#include <QtCore/QString>
29
 
#include <QtCore/QStringList>
30
 
#include <QtCore/QList>
31
 
#include <QtCore/QFileInfo>
32
 
 
33
 
#include <kglobal.h>
34
 
#include <kstandarddirs.h>
35
 
#include <kcomponentdata.h>
36
 
 
37
 
#include "KoResource.h"
38
 
#include "KoResourceServerObserver.h"
39
 
 
40
 
#include "koresource_export.h"
41
 
 
42
 
#include <KDebug>
43
 
 
44
 
class KoResource;
45
 
 
46
 
/**
47
 
 * KoResourceServerBase is the base class of all resource servers
48
 
 */
49
 
class KORESOURCES_EXPORT KoResourceServerBase {
50
 
 
51
 
public:
52
 
    /**
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"
56
 
    */
57
 
    KoResourceServerBase(const QString& type, const QString& extensions)
58
 
        : m_type(type)
59
 
        , m_extensions(extensions)
60
 
        , m_cancelled(false)
61
 
    {
62
 
    }
63
 
 
64
 
    virtual ~KoResourceServerBase() {}
65
 
 
66
 
    virtual void loadResources(QStringList filenames) = 0;
67
 
    QString type() { return m_type; }
68
 
 
69
 
    /**
70
 
    * File extensions for resources of the server
71
 
    * @returns the file extensions separated by ':', e.g. "*.kgr:*.svg:*.ggr"
72
 
    */
73
 
    QString extensions() { return m_extensions; }
74
 
 
75
 
    void cancel() { m_cancelled = true; }
76
 
 
77
 
private:
78
 
    QString m_type;
79
 
    QString m_extensions;
80
 
 
81
 
protected:
82
 
 
83
 
    bool   m_cancelled;
84
 
    QMutex m_loadLock;
85
 
 
86
 
};
87
 
 
88
 
/**
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
91
 
 */
92
 
template <class T> class KoResourceServer : public KoResourceServerBase {
93
 
 
94
 
public:
95
 
    KoResourceServer(const QString& type, const QString& extensions)
96
 
        : KoResourceServerBase(type, extensions)
97
 
 
98
 
        {
99
 
        }
100
 
 
101
 
    virtual ~KoResourceServer()
102
 
        {
103
 
        }
104
 
 
105
 
   /**
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
110
 
     */
111
 
    void loadResources(QStringList filenames) {
112
 
        kDebug(30009) << "loading  resources for type " << type();
113
 
        QStringList uniqueFiles;
114
 
 
115
 
        while (!filenames.empty() && !m_cancelled)
116
 
        {
117
 
            QString front = filenames.first();
118
 
            filenames.pop_front();
119
 
 
120
 
            QString fname = QFileInfo(front).fileName();
121
 
 
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) {
127
 
                m_loadLock.lock();
128
 
                uniqueFiles.append(fname);
129
 
                T* resource = createResource(front);
130
 
                if (resource->load() && resource->valid())
131
 
                {
132
 
                    m_resourcesByFilename[front] = resource;
133
 
 
134
 
                    if ( resource->name().isNull() ) {
135
 
                        resource->setName( fname );
136
 
                    }
137
 
                    m_resourcesByName[resource->name()] = resource;
138
 
                    m_resources.append(resource);
139
 
 
140
 
                    notifyResourceAdded(resource);
141
 
                    Q_CHECK_PTR(resource);
142
 
                }
143
 
                else {
144
 
                    delete resource;
145
 
                }
146
 
                m_loadLock.unlock();
147
 
            }
148
 
        }
149
 
        kDebug(30009) << "done loading  resources for type " << type();
150
 
    }
151
 
 
152
 
 
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!";
157
 
            return false;
158
 
        }
159
 
        if( ! resource->save() ) {
160
 
            kWarning(30009) << "Could not save resource!";
161
 
            return false;
162
 
        }
163
 
 
164
 
        Q_ASSERT( !resource->filename().isEmpty() || !resource->name().isEmpty() );
165
 
        if ( resource->filename().isEmpty() ) {
166
 
            resource->setFilename( resource->name() );
167
 
        }
168
 
        else if ( resource->name().isEmpty() ) {
169
 
            resource->setName( resource->filename() );
170
 
        }
171
 
 
172
 
        m_resourcesByFilename[resource->filename()] = resource;
173
 
        m_resourcesByName[resource->name()] = resource;
174
 
        m_resources.append(resource);
175
 
 
176
 
        notifyResourceAdded(resource);
177
 
 
178
 
        return true;
179
 
    }
180
 
 
181
 
    /// Remove a resource from resourceserver and hard disk
182
 
    bool removeResource(T* resource) {
183
 
        if ( !m_resourcesByFilename.contains( resource->filename() ) ) {
184
 
            return false;
185
 
        }
186
 
 
187
 
        bool removedFromDisk = true;
188
 
 
189
 
        QFile file( resource->filename() );
190
 
        if( ! file.remove() ) {
191
 
 
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.
197
 
 
198
 
            removedFromDisk = false;
199
 
            kWarning(30009) << "Could not remove resource!";
200
 
        }
201
 
 
202
 
        notifyRemovingResource(resource);
203
 
 
204
 
        if (removedFromDisk) {
205
 
            m_resourcesByName.remove(resource->name());
206
 
            m_resourcesByFilename.remove(resource->filename());
207
 
            m_resources.removeAt(m_resources.indexOf(resource));
208
 
            delete resource;
209
 
        } else {
210
 
            // TODO: save blacklist to config file and load it again on next start
211
 
            m_resourceBlackList << resource;
212
 
        }
213
 
 
214
 
        return true;
215
 
    }
216
 
 
217
 
    QList<T*> resources() {
218
 
        m_loadLock.lock();
219
 
        QList<T*> resourceList = m_resources;
220
 
        foreach(T* r, m_resourceBlackList) {
221
 
            resourceList.removeOne(r);
222
 
        }
223
 
        m_loadLock.unlock();
224
 
        return resourceList;
225
 
    }
226
 
 
227
 
    /// Returns path where to save user defined and imported resources to
228
 
    virtual QString saveLocation() {
229
 
        return KGlobal::mainComponent().dirs()->saveLocation(type().toAscii());
230
 
    }
231
 
 
232
 
    /**
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
236
 
     */
237
 
    T* importResource( const QString & filename ) {
238
 
        QFileInfo fi( filename );
239
 
        if( fi.exists() == false )
240
 
            return 0;
241
 
 
242
 
        T* resource = createResource( filename );
243
 
        resource->load();
244
 
        if(!resource->valid()){
245
 
            kWarning(30009) << "Import failed! Resource is not valid";
246
 
            delete resource;
247
 
            return 0;
248
 
         }
249
 
 
250
 
         Q_ASSERT(!resource->defaultFileExtension().isEmpty());
251
 
         Q_ASSERT(!saveLocation().isEmpty());
252
 
 
253
 
        QString newFilename = saveLocation() + fi.baseName() + resource->defaultFileExtension();
254
 
        resource->setFilename(newFilename);
255
 
        if(!addResource(resource)) {
256
 
            delete resource;
257
 
            return 0;
258
 
        }
259
 
 
260
 
        return resource;
261
 
    }
262
 
 
263
 
    /**
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
267
 
     */
268
 
    void addObserver(KoResourceServerObserver<T>* observer, bool notifyLoadedResources = true)
269
 
    {
270
 
        m_loadLock.lock();
271
 
        if(observer && !m_observers.contains(observer)) {
272
 
            m_observers.append(observer);
273
 
 
274
 
            if(notifyLoadedResources) {
275
 
                foreach(T* resource, m_resourcesByFilename) {
276
 
                    observer->resourceAdded(resource);
277
 
                }
278
 
            }
279
 
        }
280
 
        m_loadLock.unlock();
281
 
    }
282
 
 
283
 
    /**
284
 
     * Removes an observer from the server
285
 
     * @param observer the observer to be removed
286
 
     */
287
 
    void removeObserver(KoResourceServerObserver<T>* observer)
288
 
    {
289
 
        int index = m_observers.indexOf( observer );
290
 
        if( index < 0 )
291
 
            return;
292
 
 
293
 
        m_observers.removeAt( index );
294
 
    }
295
 
 
296
 
    T* getResourceByFilename( const QString& filename )
297
 
    {
298
 
        if ( !m_resourcesByFilename.contains( filename ) ) {
299
 
            return 0;
300
 
        }
301
 
 
302
 
        return m_resourcesByFilename[filename];
303
 
    }
304
 
 
305
 
 
306
 
    T* getResourceByName( const QString& name )
307
 
    {
308
 
        if ( !m_resourcesByName.contains( name ) ) {
309
 
            return 0;
310
 
        }
311
 
 
312
 
        return m_resourcesByName[name];
313
 
    }
314
 
 
315
 
protected:
316
 
 
317
 
    virtual T* createResource( const QString & filename ) { return new T(filename); }
318
 
 
319
 
    void notifyResourceAdded(T* resource)
320
 
    {
321
 
        foreach(KoResourceServerObserver<T>* observer, m_observers) {
322
 
            observer->resourceAdded(resource);
323
 
        }
324
 
    }
325
 
 
326
 
    void notifyRemovingResource(T* resource)
327
 
    {
328
 
        foreach(KoResourceServerObserver<T>* observer, m_observers)
329
 
            observer->removingResource(resource);
330
 
    }
331
 
 
332
 
 
333
 
private:
334
 
 
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;
340
 
 
341
 
};
342
 
 
343
 
#endif // KORESOURCESERVER_H