1/* This file is part of the KDE libraries
2 * Copyright (C) 1999 Waldo Bastian <bastian@kde.org>
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License version 2 as published by the Free Software Foundation;
7 *
8 * This library is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * Library General Public License for more details.
12 *
13 * You should have received a copy of the GNU Library General Public License
14 * along with this library; see the file COPYING.LIB. If not, write to
15 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
16 * Boston, MA 02110-1301, USA.
17 **/
18
19#ifndef KSYCOCAFACTORY_H
20#define KSYCOCAFACTORY_H
21
22#include <ksycocaentry.h>
23
24class QString;
25class KSycocaDict;
26class KSycocaResourceList;
27template <typename T> class QList;
28template <typename KT, typename VT> class QHash;
29
30typedef QHash<QString, KSycocaEntry::Ptr> KSycocaEntryDict;
31
32/**
33 * @internal
34 * Base class for sycoca factories
35 */
36class KDECORE_EXPORT KSycocaFactory
37{
38public:
39 virtual KSycocaFactoryId factoryId() const = 0;
40
41protected: // virtual class
42 /**
43 * Create a factory which can be used to lookup from/create a database
44 * (depending on KSycoca::isBuilding())
45 */
46 explicit KSycocaFactory( KSycocaFactoryId factory_id );
47
48public:
49 virtual ~KSycocaFactory();
50
51 /**
52 * @return the position of the factory in the sycoca file
53 */
54 int offset() const;
55
56 /**
57 * @return the dict, for special use by KBuildSycoca
58 */
59 KSycocaEntryDict * entryDict() { return m_entryDict; }
60
61 /**
62 * Construct an entry from a config file.
63 * To be implemented in the real factories.
64 */
65 virtual KSycocaEntry *createEntry(const QString &file, const char *resource) const = 0;
66
67 /**
68 * Add an entry
69 */
70 virtual void addEntry(const KSycocaEntry::Ptr& newEntry);
71
72 /**
73 * Remove all entries with the given name.
74 * Not very fast (O(N)), use with care.
75 */
76 void removeEntry(const QString& entryName);
77
78 /**
79 * Read an entry from the database
80 */
81 virtual KSycocaEntry *createEntry(int offset) const = 0;
82
83 /**
84 * Get a list of all entries from the database.
85 */
86 virtual KSycocaEntry::List allEntries() const;
87
88 /**
89 * Saves all entries it maintains as well as index files
90 * for these entries to the stream 'str'.
91 *
92 * Also sets mOffset to the starting position.
93 *
94 * The stream is positioned at the end of the last index.
95 *
96 * Don't forget to call the parent first when you override
97 * this function.
98 */
99 virtual void save(QDataStream &str);
100
101 /**
102 * Writes out a header to the stream 'str'.
103 * The baseclass positions the stream correctly.
104 *
105 * Don't forget to call the parent first when you override
106 * this function.
107 */
108 virtual void saveHeader(QDataStream &str);
109
110 /**
111 * @return the resources for which this factory is responsible.
112 * @internal to kbuildsycoca
113 */
114 const KSycocaResourceList * resourceList() const;
115
116 /**
117 * @return the sycoca dict, for factories to find entries by name.
118 */
119 const KSycocaDict *sycocaDict() const;
120
121 /**
122 * @return true if the factory is completely empty - no entries defined
123 */
124 bool isEmpty() const;
125
126protected:
127 QDataStream* stream() const;
128
129 KSycocaResourceList *m_resourceList;
130 KSycocaEntryDict *m_entryDict;
131
132private:
133 QDataStream *m_str;
134 class Private;
135 Private* const d;
136
137protected:
138 /** Virtual hook, used to add new "virtual" functions while maintaining
139 binary compatibility. Unused in this class.
140 */
141 virtual void virtual_hook( int id, void* data );
142};
143
144/**
145 * This, instead of a typedef, allows to declare "class ..." in header files.
146 * @internal
147 */
148class KDECORE_EXPORT KSycocaFactoryList : public QList<KSycocaFactory*> //krazy:exclude=dpointer (acts as a typedef)
149{
150public:
151 KSycocaFactoryList() { }
152};
153
154#include <QThreadStorage>
155/**
156 * Workaround for the lack of QThreadStorage::setAutoDelete(false).
157 * Container for KSycocaFactory that doesn't delete it when it is deleted.
158 */
159template <typename F> class KSycocaFactoryContainer
160{
161public:
162 KSycocaFactoryContainer(F* factory) : m_factory(factory) {}
163 F* factory() { return m_factory; }
164private:
165 F* m_factory;
166};
167
168/**
169 * Template for making it easier to define a threadsafe singleton
170 * for each factory, with support for kbuildsycoca providing a
171 * subclass of the factory.
172 *
173 * @since 4.3
174 * @internal
175 */
176template <typename F> class KSycocaFactorySingleton
177{
178public:
179 typedef KSycocaFactoryContainer<F> C;
180 KSycocaFactorySingleton() {
181 }
182 ~KSycocaFactorySingleton() {
183 // Do not delete the factory here.
184 // All factories are owned by KSycoca, and deleted by it.
185 }
186 void instanceCreated(F* newFactory) {
187 // This can also register a subclass created by kbuildsycoca
188 Q_ASSERT(!m_factories.hasLocalData());
189 Q_ASSERT(newFactory);
190 m_factories.setLocalData(new C(newFactory));
191 }
192 void instanceDestroyed(F* factory) {
193 if (m_factories.hasLocalData()) { // could be false on thread exit
194 Q_ASSERT(m_factories.localData()->factory() == factory); Q_UNUSED(factory)
195 m_factories.setLocalData(0);
196 }
197 }
198 F* self() {
199 if (!m_factories.hasLocalData()) {
200 new F; // calls instanceCreated, which calls setLocalData
201 Q_ASSERT(m_factories.hasLocalData());
202 }
203 return m_factories.localData()->factory();
204 }
205private:
206 QThreadStorage<C*> m_factories;
207};
208
209#endif
210