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 | |
24 | class QString; |
25 | class KSycocaDict; |
26 | class KSycocaResourceList; |
27 | template <typename T> class QList; |
28 | template <typename KT, typename VT> class QHash; |
29 | |
30 | typedef QHash<QString, KSycocaEntry::Ptr> KSycocaEntryDict; |
31 | |
32 | /** |
33 | * @internal |
34 | * Base class for sycoca factories |
35 | */ |
36 | class KDECORE_EXPORT KSycocaFactory |
37 | { |
38 | public: |
39 | virtual KSycocaFactoryId factoryId() const = 0; |
40 | |
41 | protected: // 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 | |
48 | public: |
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 (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 | |
126 | protected: |
127 | QDataStream* stream() const; |
128 | |
129 | KSycocaResourceList *m_resourceList; |
130 | KSycocaEntryDict *m_entryDict; |
131 | |
132 | private: |
133 | QDataStream *m_str; |
134 | class Private; |
135 | Private* const d; |
136 | |
137 | protected: |
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 | */ |
148 | class KDECORE_EXPORT KSycocaFactoryList : public QList<KSycocaFactory*> //krazy:exclude=dpointer (acts as a typedef) |
149 | { |
150 | public: |
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 | */ |
159 | template <typename F> class KSycocaFactoryContainer |
160 | { |
161 | public: |
162 | KSycocaFactoryContainer(F* factory) : m_factory(factory) {} |
163 | F* factory() { return m_factory; } |
164 | private: |
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 | */ |
176 | template <typename F> class KSycocaFactorySingleton |
177 | { |
178 | public: |
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 | } |
205 | private: |
206 | QThreadStorage<C*> m_factories; |
207 | }; |
208 | |
209 | #endif |
210 | |