author | kergoth <kergoth> | 2002-11-01 00:10:42 (UTC) |
---|---|---|
committer | kergoth <kergoth> | 2002-11-01 00:10:42 (UTC) |
commit | 5042e3cf0d3514552769e441f5aad590c8eaf967 (patch) (unidiff) | |
tree | 4a5ea45f3519d981a172ab5275bf38c6fa778dec /qmake/tools/qcomponentfactory.cpp | |
parent | 108c1c753e74e989cc13923086996791428c9af4 (diff) | |
download | opie-5042e3cf0d3514552769e441f5aad590c8eaf967.zip opie-5042e3cf0d3514552769e441f5aad590c8eaf967.tar.gz opie-5042e3cf0d3514552769e441f5aad590c8eaf967.tar.bz2 |
Adding qmake in preperation for new build system
Diffstat (limited to 'qmake/tools/qcomponentfactory.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r-- | qmake/tools/qcomponentfactory.cpp | 352 |
1 files changed, 352 insertions, 0 deletions
diff --git a/qmake/tools/qcomponentfactory.cpp b/qmake/tools/qcomponentfactory.cpp new file mode 100644 index 0000000..8ea81a8 --- a/dev/null +++ b/qmake/tools/qcomponentfactory.cpp | |||
@@ -0,0 +1,352 @@ | |||
1 | /**************************************************************************** | ||
2 | ** $Id$ | ||
3 | ** | ||
4 | ** Implementation of the QComponentFactory class | ||
5 | ** | ||
6 | ** Created : 990101 | ||
7 | ** | ||
8 | ** Copyright (C) 1992-2002 Trolltech AS. All rights reserved. | ||
9 | ** | ||
10 | ** This file is part of the tools module of the Qt GUI Toolkit. | ||
11 | ** | ||
12 | ** This file may be distributed under the terms of the Q Public License | ||
13 | ** as defined by Trolltech AS of Norway and appearing in the file | ||
14 | ** LICENSE.QPL included in the packaging of this file. | ||
15 | ** | ||
16 | ** This file may be distributed and/or modified under the terms of the | ||
17 | ** GNU General Public License version 2 as published by the Free Software | ||
18 | ** Foundation and appearing in the file LICENSE.GPL included in the | ||
19 | ** packaging of this file. | ||
20 | ** | ||
21 | ** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition | ||
22 | ** licenses may use this file in accordance with the Qt Commercial License | ||
23 | ** Agreement provided with the Software. | ||
24 | ** | ||
25 | ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE | ||
26 | ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. | ||
27 | ** | ||
28 | ** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for | ||
29 | ** information about Qt Commercial License Agreements. | ||
30 | ** See http://www.trolltech.com/qpl/ for QPL licensing information. | ||
31 | ** See http://www.trolltech.com/gpl/ for GPL licensing information. | ||
32 | ** | ||
33 | ** Contact info@trolltech.com if any conditions of this licensing are | ||
34 | ** not clear to you. | ||
35 | ** | ||
36 | **********************************************************************/ | ||
37 | |||
38 | #include "qcomponentfactory_p.h" | ||
39 | |||
40 | #ifndef QT_NO_COMPONENT | ||
41 | #include "qsettings.h" | ||
42 | #include <private/qcomlibrary_p.h> | ||
43 | #include "qdir.h" | ||
44 | #include "qapplication.h" | ||
45 | |||
46 | /*! | ||
47 | \class QComponentFactory qcomponentfactory.h | ||
48 | \brief The QComponentFactory class provides static functions to create and register components. | ||
49 | |||
50 | \internal | ||
51 | |||
52 | The static convenience functions can be used both by applications to instantiate components, | ||
53 | and by component servers to register components. | ||
54 | |||
55 | The createInstance() function provides a pointer to an interface implemented in a specific | ||
56 | component if the component requested has been installed properly and implements the interface. | ||
57 | |||
58 | Use registerServer() to load a component server and register its components, and unregisterServer() | ||
59 | to unregister the components. The component exported by the component server has to implement the | ||
60 | QComponentRegistrationInterface. | ||
61 | |||
62 | The static functions registerComponent() and unregisterComponent() register and unregister a single | ||
63 | component in the system component registry, and should be used when implementing the | ||
64 | \link QComponentRegistrationInterface::registerComponents() registerCompontents() \endlink and | ||
65 | \link QComponentRegistrationInterface::unregisterComponents() unregisterCompontents() \endlink functions | ||
66 | in the QComponentRegistrationInterface. | ||
67 | |||
68 | A component is registered using a UUID, but can additionally be registered with a name, version and | ||
69 | description. A component registered with a name and a version can be instantiated by client applications | ||
70 | using the name and specific version number, or the highest available version number for that component by | ||
71 | just using the name. A component that is registered calling | ||
72 | |||
73 | \code | ||
74 | QComponentFactory::registerComponent( QUuid(...), filename, "MyProgram.Component", 1 ); | ||
75 | \endcode | ||
76 | |||
77 | can be instantiated calling either: | ||
78 | |||
79 | \code | ||
80 | QComponentFactory::createInstance( QUuid(...), IID_XYZ, (QUnknownInterface**)&iface ); | ||
81 | \endcode | ||
82 | or | ||
83 | \code | ||
84 | QComponentFactory::createInstance( "MyProgram.Component", IID_XYZ, (QUnknownInterface**)&iface ); | ||
85 | \endcode | ||
86 | or | ||
87 | \code | ||
88 | QComponentFactory::createInstance( "MyProgram.Component.1", IID_XYZ, (QUnknownInterface**)&iface ); | ||
89 | \endcode | ||
90 | |||
91 | The first and the last way will always instantiate exactly the component registered above, while | ||
92 | the second call might also return a later version of the same component. This allows smoother upgrading | ||
93 | of components, and is easier to use in application source code, but should only be used when new versions | ||
94 | of the component are guaranteed to work with the application. | ||
95 | |||
96 | The component name can be anything, but should be unique on the system the component is being | ||
97 | installed on. A common naming convention for components is \e application.component. | ||
98 | |||
99 | \sa QComponentRegistrationInterface QComponentFactoryInterface | ||
100 | */ | ||
101 | |||
102 | |||
103 | static QPtrList<QComLibrary> *libraries = 0; | ||
104 | |||
105 | static void cleanup() | ||
106 | { | ||
107 | delete libraries; | ||
108 | libraries = 0; | ||
109 | } | ||
110 | |||
111 | static QPtrList<QComLibrary> *liblist() | ||
112 | { | ||
113 | if ( !libraries ) { | ||
114 | libraries = new QPtrList<QComLibrary>(); | ||
115 | libraries->setAutoDelete( TRUE ); | ||
116 | qAddPostRoutine( cleanup ); | ||
117 | } | ||
118 | return libraries; | ||
119 | } | ||
120 | |||
121 | /*! | ||
122 | Searches for the component identifier \a cid in the system component registry, | ||
123 | loads the corresponding component server and queries for the interface \a iid. | ||
124 | \a iface is set to the resulting interface pointer. \a cid can either be the | ||
125 | UUID or the name of the component. | ||
126 | |||
127 | The parameter \a outer is a pointer to the outer interface used | ||
128 | for containment and aggregation and is propagated to the \link | ||
129 | QComponentFactoryInterface::createInstance() createInstance() \endlink | ||
130 | implementation of the QComponentFactoryInterface in the component server if | ||
131 | provided. | ||
132 | |||
133 | The function returns QS_OK if the interface was successfully instantiated, QE_NOINTERFACE if | ||
134 | the component does not provide an interface \a iid, or QE_NOCOMPONENT if there was | ||
135 | an error loading the component. | ||
136 | |||
137 | Example: | ||
138 | \code | ||
139 | QInterfacePtr<MyInterface> iface; | ||
140 | if ( QComponentFactory::createInstance( IID_MyInterface, CID_MyComponent, (QUnknownInterface**)&iface ) == QS_OK ) | ||
141 | iface->doSomething(); | ||
142 | ... | ||
143 | } | ||
144 | \endcode | ||
145 | */ | ||
146 | QRESULT QComponentFactory::createInstance( const QString &cid, const QUuid &iid, QUnknownInterface** iface, QUnknownInterface *outer ) | ||
147 | { | ||
148 | QSettings settings; | ||
149 | settings.insertSearchPath( QSettings::Windows, "/Classes" ); | ||
150 | bool ok = FALSE; | ||
151 | QString cidStr = cid; | ||
152 | QRESULT res = QE_NOCOMPONENT; | ||
153 | |||
154 | QUuid uuid( cidStr ); // try to parse, and resolve CLSID if necessary | ||
155 | if ( uuid.isNull() ) { | ||
156 | uuid = settings.readEntry( "/" + cid + "/CLSID/Default", QString::null, &ok ); | ||
157 | cidStr = uuid.toString().upper(); | ||
158 | } | ||
159 | |||
160 | if ( cidStr.isEmpty() ) | ||
161 | return res; | ||
162 | |||
163 | QString file = settings.readEntry( "/CLSID/" + cidStr + "/InprocServer32/Default", QString::null, &ok ); | ||
164 | if ( !ok ) | ||
165 | return res; | ||
166 | |||
167 | QComLibrary *library = new QComLibrary( file ); | ||
168 | library->setAutoUnload( FALSE ); | ||
169 | |||
170 | QComponentFactoryInterface *cfIface =0; | ||
171 | library->queryInterface( IID_QComponentFactory, (QUnknownInterface**)&cfIface ); | ||
172 | |||
173 | if ( cfIface ) { | ||
174 | res = cfIface->createInstance( uuid, iid, iface, outer ); | ||
175 | cfIface->release(); | ||
176 | } else { | ||
177 | res = library->queryInterface( iid, iface ); | ||
178 | } | ||
179 | QLibraryInterface *libiface = 0; | ||
180 | if ( library->queryInterface( IID_QLibrary, (QUnknownInterface**)&libiface ) != QS_OK || !qApp ) { | ||
181 | delete library; // only deletes the object, thanks to QLibrary::Manual | ||
182 | } else { | ||
183 | libiface->release(); | ||
184 | library->setAutoUnload( TRUE ); | ||
185 | liblist()->prepend( library ); | ||
186 | } | ||
187 | return res; | ||
188 | } | ||
189 | |||
190 | /*! | ||
191 | Loads the shared library \a filename and queries for a | ||
192 | QComponentRegistrationInterface. If the library implements this interface, | ||
193 | the \link QComponentRegistrationInterface::registerComponents() | ||
194 | registerComponents() \endlink function is called. | ||
195 | |||
196 | Returns TRUE if the interface is found and successfully called, | ||
197 | otherwise returns FALSE. | ||
198 | */ | ||
199 | QRESULT QComponentFactory::registerServer( const QString &filename ) | ||
200 | { | ||
201 | QComLibrary lib( filename ); | ||
202 | lib.load(); | ||
203 | QComponentRegistrationInterface *iface = 0; | ||
204 | QRESULT res = lib.queryInterface( IID_QComponentRegistration, (QUnknownInterface**)&iface ); | ||
205 | if ( res != QS_OK ) | ||
206 | return res; | ||
207 | QDir dir( filename ); | ||
208 | bool ok = iface->registerComponents( dir.absPath() ); | ||
209 | iface->release(); | ||
210 | return ok ? QS_OK : QS_FALSE; | ||
211 | } | ||
212 | |||
213 | /*! | ||
214 | Loads the shared library \a filename and queries for a | ||
215 | QComponentRegistrationInterface. If the library implements this interface, | ||
216 | the \link QComponentRegistrationInterface::unregisterComponents() | ||
217 | unregisterComponents() \endlink function is called. | ||
218 | |||
219 | Returns TRUE if the interface is found and successfully unregistered, | ||
220 | otherwise returns FALSE. | ||
221 | */ | ||
222 | QRESULT QComponentFactory::unregisterServer( const QString &filename ) | ||
223 | { | ||
224 | QComLibrary lib( filename ); | ||
225 | lib.load(); | ||
226 | QComponentRegistrationInterface *iface = 0; | ||
227 | QRESULT res = lib.queryInterface( IID_QComponentRegistration, (QUnknownInterface**)&iface ); | ||
228 | if ( res != QS_OK ) | ||
229 | return res; | ||
230 | bool ok = iface->unregisterComponents(); | ||
231 | iface->release(); | ||
232 | return ok ? QS_OK : QS_FALSE; | ||
233 | } | ||
234 | |||
235 | /*! | ||
236 | Registers the component with id \a cid in the system component registry and | ||
237 | returns TRUE if the component was registerd successfully, otherwise returns | ||
238 | FALSE. The component is provided by the component server at \a filepath and | ||
239 | registered with an optional \a name, \a version and \a description. | ||
240 | |||
241 | This function does nothing and returns FALSE if a component with an identical | ||
242 | \a cid does already exist on the system. | ||
243 | |||
244 | A component that has been registered with a \a name can be created using both the | ||
245 | \a cid and the \a name value using createInstance(). | ||
246 | |||
247 | Call this function for each component in an implementation of | ||
248 | \link QComponentRegistrationInterface::registerComponents() registerComponents() \endlink. | ||
249 | |||
250 | \sa unregisterComponent(), registerServer(), createInstance() | ||
251 | */ | ||
252 | bool QComponentFactory::registerComponent( const QUuid &cid, const QString &filepath, const QString &name, int version, const QString &description ) | ||
253 | { | ||
254 | bool ok = FALSE; | ||
255 | QSettings settings; | ||
256 | settings.insertSearchPath( QSettings::Windows, "/Classes" ); | ||
257 | |||
258 | QString cidStr = cid.toString().upper(); | ||
259 | settings.readEntry( "/CLSID/" + cidStr + "/InprocServer32/Default", QString::null, &ok ); | ||
260 | if ( ok ) // don't overwrite existing component | ||
261 | return FALSE; | ||
262 | |||
263 | ok = settings.writeEntry( "/CLSID/" + cidStr + "/InprocServer32/Default", filepath ); | ||
264 | if ( ok && !!description ) | ||
265 | settings.writeEntry( "/CLSID/" + cidStr + "/Default", description ); | ||
266 | |||
267 | // register the human readable part | ||
268 | if ( ok && !!name ) { | ||
269 | QString vName = version ? name + "." + QString::number( version ) : name; | ||
270 | settings.writeEntry( "/CLSID/" + cidStr + "/ProgID/Default", vName ); | ||
271 | ok = settings.writeEntry( "/" + vName + "/CLSID/Default", cidStr ); | ||
272 | if ( ok && !!description ) | ||
273 | settings.writeEntry( "/" + vName + "/Default", description ); | ||
274 | |||
275 | if ( ok && version ) { | ||
276 | settings.writeEntry( "/CLSID/" + cidStr + "/VersionIndependentProgID/Default", name ); | ||
277 | QString curVer = settings.readEntry( "/" + name + "/CurVer/Default" ); | ||
278 | if ( !curVer || curVer < vName ) { // no previous, or a lesser version installed | ||
279 | settings.writeEntry( "/" + name + "/CurVer/Default", vName ); | ||
280 | ok = settings.writeEntry( "/" + name + "/CLSID/Default", cidStr ); | ||
281 | if ( ok && !!description ) | ||
282 | settings.writeEntry( "/" + name + "/Default", description ); | ||
283 | } | ||
284 | } | ||
285 | } | ||
286 | |||
287 | return ok; | ||
288 | } | ||
289 | |||
290 | /*! | ||
291 | Unregisters the component with id \a cid from the system component registry and returns | ||
292 | TRUE if the component was unregistered successfully, otherwise returns FALSE. | ||
293 | |||
294 | Call this function for each component in an implementation of | ||
295 | \link QComponentRegistrationInterface::unregisterComponents() unregisterComponents() \endlink. | ||
296 | |||
297 | \sa registerComponent(), unregisterServer() | ||
298 | */ | ||
299 | bool QComponentFactory::unregisterComponent( const QUuid &cid ) | ||
300 | { | ||
301 | QSettings settings; | ||
302 | bool ok = FALSE; | ||
303 | settings.insertSearchPath( QSettings::Windows, "/Classes" ); | ||
304 | |||
305 | QString cidStr = cid.toString().upper(); | ||
306 | if ( cidStr.isEmpty() ) | ||
307 | return FALSE; | ||
308 | |||
309 | // unregister the human readable part | ||
310 | QString vName = settings.readEntry( "/CLSID/" + cidStr + "/ProgID/Default", QString::null, &ok ); | ||
311 | if ( ok ) { | ||
312 | QString name = settings.readEntry( "/CLSID/" + cidStr + "/VersionIndependentProgID/Default", QString::null ); | ||
313 | if ( !!name && settings.readEntry( "/" + name + "/CurVer/Default" ) == vName ) { | ||
314 | // unregistering the current version -> change CurVer to previous version | ||
315 | QString version = vName.right( vName.length() - name.length() - 1 ); | ||
316 | QString newVerName; | ||
317 | QString newCidStr; | ||
318 | if ( version.find( '.' ) == -1 ) { | ||
319 | int ver = version.toInt(); | ||
320 | // see if a lesser version is installed, and make that the CurVer | ||
321 | while ( ver-- ) { | ||
322 | newVerName = name + "." + QString::number( ver ); | ||
323 | newCidStr = settings.readEntry( "/" + newVerName + "/CLSID/Default" ); | ||
324 | if ( !!newCidStr ) | ||
325 | break; | ||
326 | } | ||
327 | } else { | ||
328 | // oh well... | ||
329 | } | ||
330 | if ( !!newCidStr ) { | ||
331 | settings.writeEntry( "/" + name + "/CurVer/Default", newVerName ); | ||
332 | settings.writeEntry( "/" + name + "/CLSID/Default", newCidStr ); | ||
333 | } else { | ||
334 | settings.removeEntry( "/" + name + "/CurVer/Default" ); | ||
335 | settings.removeEntry( "/" + name + "/CLSID/Default" ); | ||
336 | settings.removeEntry( "/" + name + "/Default" ); | ||
337 | } | ||
338 | } | ||
339 | |||
340 | settings.removeEntry( "/" + vName + "/CLSID/Default" ); | ||
341 | settings.removeEntry( "/" + vName + "/Default" ); | ||
342 | } | ||
343 | |||
344 | settings.removeEntry( "/CLSID/" + cidStr + "/VersionIndependentProgID/Default" ); | ||
345 | settings.removeEntry( "/CLSID/" + cidStr + "/ProgID/Default" ); | ||
346 | settings.removeEntry( "/CLSID/" + cidStr + "/InprocServer32/Default" ); | ||
347 | ok = settings.removeEntry( "/CLSID/" + cidStr + "/Default" ); | ||
348 | |||
349 | return ok; | ||
350 | } | ||
351 | |||
352 | #endif // QT_NO_COMPONENT | ||