summaryrefslogtreecommitdiffstats
path: root/src/corelib/plugin
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@nokia.com>2009-03-23 10:18:55 +0100
committerSimon Hausmann <simon.hausmann@nokia.com>2009-03-23 10:18:55 +0100
commite5fcad302d86d316390c6b0f62759a067313e8a9 (patch)
treec2afbf6f1066b6ce261f14341cf6d310e5595bc1 /src/corelib/plugin
Long live Qt 4.5!
Diffstat (limited to 'src/corelib/plugin')
-rw-r--r--src/corelib/plugin/plugin.pri24
-rw-r--r--src/corelib/plugin/qfactoryinterface.h67
-rw-r--r--src/corelib/plugin/qfactoryloader.cpp256
-rw-r--r--src/corelib/plugin/qfactoryloader_p.h89
-rw-r--r--src/corelib/plugin/qlibrary.cpp1130
-rw-r--r--src/corelib/plugin/qlibrary.h120
-rw-r--r--src/corelib/plugin/qlibrary_p.h122
-rw-r--r--src/corelib/plugin/qlibrary_unix.cpp266
-rw-r--r--src/corelib/plugin/qlibrary_win.cpp147
-rw-r--r--src/corelib/plugin/qplugin.h141
-rw-r--r--src/corelib/plugin/qpluginloader.cpp371
-rw-r--r--src/corelib/plugin/qpluginloader.h100
-rw-r--r--src/corelib/plugin/quuid.cpp624
-rw-r--r--src/corelib/plugin/quuid.h190
14 files changed, 3647 insertions, 0 deletions
diff --git a/src/corelib/plugin/plugin.pri b/src/corelib/plugin/plugin.pri
new file mode 100644
index 0000000000..aaecec9de6
--- /dev/null
+++ b/src/corelib/plugin/plugin.pri
@@ -0,0 +1,24 @@
+# Qt core library plugin module
+
+HEADERS += \
+ plugin/qfactoryinterface.h \
+ plugin/qpluginloader.h \
+ plugin/qlibrary.h \
+ plugin/qlibrary_p.h \
+ plugin/qplugin.h \
+ plugin/quuid.h \
+ plugin/qfactoryloader_p.h
+
+SOURCES += \
+ plugin/qpluginloader.cpp \
+ plugin/qfactoryloader.cpp \
+ plugin/quuid.cpp \
+ plugin/qlibrary.cpp
+
+win32 {
+ SOURCES += plugin/qlibrary_win.cpp
+}
+
+unix {
+ SOURCES += plugin/qlibrary_unix.cpp
+}
diff --git a/src/corelib/plugin/qfactoryinterface.h b/src/corelib/plugin/qfactoryinterface.h
new file mode 100644
index 0000000000..ee00d8f061
--- /dev/null
+++ b/src/corelib/plugin/qfactoryinterface.h
@@ -0,0 +1,67 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFACTORYINTERFACE_H
+#define QFACTORYINTERFACE_H
+
+#include <QtCore/qobject.h>
+#include <QtCore/qstringlist.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+struct Q_CORE_EXPORT QFactoryInterface
+{
+ virtual ~QFactoryInterface() {}
+ virtual QStringList keys() const = 0;
+};
+
+
+Q_DECLARE_INTERFACE(QFactoryInterface, "com.trolltech.Qt.QFactoryInterface")
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QFACTORYINTERFACE_H
diff --git a/src/corelib/plugin/qfactoryloader.cpp b/src/corelib/plugin/qfactoryloader.cpp
new file mode 100644
index 0000000000..516302778c
--- /dev/null
+++ b/src/corelib/plugin/qfactoryloader.cpp
@@ -0,0 +1,256 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qfactoryloader_p.h"
+
+#if !defined (QT_NO_LIBRARY) && !defined(QT_NO_SETTINGS)
+#include "qfactoryinterface.h"
+#include "qmap.h"
+#include <qdir.h>
+#include <qsettings.h>
+#include <qdebug.h>
+#include "qmutex.h"
+#include "qplugin.h"
+#include "qpluginloader.h"
+#include "private/qobject_p.h"
+#include "private/qcoreapplication_p.h"
+
+QT_BEGIN_NAMESPACE
+
+Q_GLOBAL_STATIC(QList<QFactoryLoader *>, qt_factory_loaders);
+
+Q_GLOBAL_STATIC_WITH_ARGS(QMutex, qt_factoryloader_mutex, (QMutex::Recursive))
+
+class QFactoryLoaderPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QFactoryLoader)
+public:
+ QFactoryLoaderPrivate(){}
+ mutable QMutex mutex;
+ QByteArray iid;
+ QList<QLibraryPrivate*> libraryList;
+ QMap<QString,QLibraryPrivate*> keyMap;
+ QStringList keyList;
+ QString suffix;
+ Qt::CaseSensitivity cs;
+ QStringList loadedPaths;
+
+ void unloadPath(const QString &path);
+};
+
+QFactoryLoader::QFactoryLoader(const char *iid,
+ const QString &suffix,
+ Qt::CaseSensitivity cs)
+ : QObject(*new QFactoryLoaderPrivate)
+{
+ moveToThread(QCoreApplicationPrivate::mainThread());
+ Q_D(QFactoryLoader);
+ d->iid = iid;
+ d->cs = cs;
+ d->suffix = suffix;
+
+
+ QMutexLocker locker(qt_factoryloader_mutex());
+ qt_factory_loaders()->append(this);
+ update();
+}
+
+
+
+void QFactoryLoader::update()
+{
+#ifdef QT_SHARED
+ Q_D(QFactoryLoader);
+ QStringList paths = QCoreApplication::libraryPaths();
+ QSettings settings(QSettings::UserScope, QLatin1String("Trolltech"));
+ for (int i = 0; i < paths.count(); ++i) {
+ const QString &pluginDir = paths.at(i);
+ // Already loaded, skip it...
+ if (d->loadedPaths.contains(pluginDir))
+ continue;
+ d->loadedPaths << pluginDir;
+
+ QString path = pluginDir + d->suffix;
+ if (!QDir(path).exists(QLatin1String(".")))
+ continue;
+
+ QStringList plugins = QDir(path).entryList(QDir::Files);
+ QLibraryPrivate *library = 0;
+ for (int j = 0; j < plugins.count(); ++j) {
+ QString fileName = QDir::cleanPath(path + QLatin1Char('/') + plugins.at(j));
+ if (qt_debug_component()) {
+ qDebug() << "QFactoryLoader::QFactoryLoader() looking at" << fileName;
+ }
+ library = QLibraryPrivate::findOrCreate(QFileInfo(fileName).canonicalFilePath());
+ if (!library->isPlugin(&settings)) {
+ if (qt_debug_component()) {
+ qDebug() << library->errorString;
+ qDebug() << " not a plugin";
+ }
+ library->release();
+ continue;
+ }
+ QString regkey = QString::fromLatin1("Qt Factory Cache %1.%2/%3:/%4")
+ .arg((QT_VERSION & 0xff0000) >> 16)
+ .arg((QT_VERSION & 0xff00) >> 8)
+ .arg(QLatin1String(d->iid))
+ .arg(fileName);
+ QStringList reg, keys;
+ reg = settings.value(regkey).toStringList();
+ if (reg.count() && library->lastModified == reg[0]) {
+ keys = reg;
+ keys.removeFirst();
+ } else {
+ if (!library->loadPlugin()) {
+ if (qt_debug_component()) {
+ qDebug() << library->errorString;
+ qDebug() << " could not load";
+ }
+ library->release();
+ continue;
+ }
+ QObject *instance = library->instance();
+ if (!instance)
+ // ignore plugins that have a valid signature but cannot be loaded.
+ continue;
+ QFactoryInterface *factory = qobject_cast<QFactoryInterface*>(instance);
+ if (instance && factory && instance->qt_metacast(d->iid))
+ keys = factory->keys();
+ if (keys.isEmpty())
+ library->unload();
+ reg.clear();
+ reg << library->lastModified;
+ reg += keys;
+ settings.setValue(regkey, reg);
+ }
+ if (qt_debug_component()) {
+ qDebug() << "keys" << keys;
+ }
+
+ if (keys.isEmpty()) {
+ library->release();
+ continue;
+ }
+ d->libraryList += library;
+ for (int k = 0; k < keys.count(); ++k) {
+ // first come first serve, unless the first
+ // library was built with a future Qt version,
+ // whereas the new one has a Qt version that fits
+ // better
+ QString key = keys.at(k);
+ if (!d->cs)
+ key = key.toLower();
+ QLibraryPrivate *previous = d->keyMap.value(key);
+ if (!previous || (previous->qt_version > QT_VERSION && library->qt_version <= QT_VERSION)) {
+ d->keyMap[key] = library;
+ d->keyList += keys.at(k);
+ }
+ }
+ }
+ }
+#else
+ Q_D(QFactoryLoader);
+ if (qt_debug_component()) {
+ qDebug() << "QFactoryLoader::QFactoryLoader() ignoring" << d->iid
+ << "since plugins are disabled in static builds";
+ }
+#endif
+}
+
+QFactoryLoader::~QFactoryLoader()
+{
+ Q_D(QFactoryLoader);
+ for (int i = 0; i < d->libraryList.count(); ++i)
+ d->libraryList.at(i)->release();
+
+ QMutexLocker locker(qt_factoryloader_mutex());
+ qt_factory_loaders()->removeAll(this);
+}
+
+QStringList QFactoryLoader::keys() const
+{
+ Q_D(const QFactoryLoader);
+ QMutexLocker locker(&d->mutex);
+ QStringList keys = d->keyList;
+ QObjectList instances = QPluginLoader::staticInstances();
+ for (int i = 0; i < instances.count(); ++i)
+ if (QFactoryInterface *factory = qobject_cast<QFactoryInterface*>(instances.at(i)))
+ if (instances.at(i)->qt_metacast(d->iid))
+ keys += factory->keys();
+ return keys;
+}
+
+QObject *QFactoryLoader::instance(const QString &key) const
+{
+ Q_D(const QFactoryLoader);
+ QMutexLocker locker(&d->mutex);
+ QObjectList instances = QPluginLoader::staticInstances();
+ for (int i = 0; i < instances.count(); ++i)
+ if (QFactoryInterface *factory = qobject_cast<QFactoryInterface*>(instances.at(i)))
+ if (instances.at(i)->qt_metacast(d->iid) && factory->keys().contains(key, Qt::CaseInsensitive))
+ return instances.at(i);
+
+ QString lowered = d->cs ? key : key.toLower();
+ if (QLibraryPrivate* library = d->keyMap.value(lowered)) {
+ if (library->instance || library->loadPlugin()) {
+ if (QObject *obj = library->instance()) {
+ if (obj && !obj->parent())
+ obj->moveToThread(QCoreApplicationPrivate::mainThread());
+ return obj;
+ }
+ }
+ }
+ return 0;
+}
+
+void QFactoryLoader::refreshAll()
+{
+ QMutexLocker locker(qt_factoryloader_mutex());
+ QList<QFactoryLoader *> *loaders = qt_factory_loaders();
+ for (QList<QFactoryLoader *>::const_iterator it = loaders->constBegin();
+ it != loaders->constEnd(); ++it) {
+ (*it)->update();
+ }
+}
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_LIBRARY
diff --git a/src/corelib/plugin/qfactoryloader_p.h b/src/corelib/plugin/qfactoryloader_p.h
new file mode 100644
index 0000000000..8110a60cfe
--- /dev/null
+++ b/src/corelib/plugin/qfactoryloader_p.h
@@ -0,0 +1,89 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFACTORYLOADER_P_H
+#define QFACTORYLOADER_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "QtCore/qobject.h"
+#include "QtCore/qstringlist.h"
+#include "private/qlibrary_p.h"
+
+#if !defined (QT_NO_LIBRARY) && !defined(QT_NO_SETTINGS)
+
+QT_BEGIN_NAMESPACE
+
+class QFactoryLoaderPrivate;
+
+class Q_CORE_EXPORT QFactoryLoader : public QObject
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QFactoryLoader)
+
+public:
+ QFactoryLoader(const char *iid,
+ const QString &suffix = QString(),
+ Qt::CaseSensitivity = Qt::CaseSensitive);
+ ~QFactoryLoader();
+
+ QStringList keys() const;
+ QObject *instance(const QString &key) const;
+
+ void update();
+
+ static void refreshAll();
+};
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_LIBRARY
+
+#endif // QFACTORYLOADER_P_H
diff --git a/src/corelib/plugin/qlibrary.cpp b/src/corelib/plugin/qlibrary.cpp
new file mode 100644
index 0000000000..79400a8396
--- /dev/null
+++ b/src/corelib/plugin/qlibrary.cpp
@@ -0,0 +1,1130 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qplatformdefs.h"
+#include "qlibrary.h"
+
+#ifndef QT_NO_LIBRARY
+
+#include "qlibrary_p.h"
+#include <qstringlist.h>
+#include <qfile.h>
+#include <qfileinfo.h>
+#include <qmutex.h>
+#include <qmap.h>
+#include <qsettings.h>
+#include <qdatetime.h>
+#ifdef Q_OS_MAC
+# include <private/qcore_mac_p.h>
+#endif
+#ifndef NO_ERRNO_H
+#include <errno.h>
+#endif // NO_ERROR_H
+#include <qdebug.h>
+#include <qvector.h>
+#include <qdir.h>
+
+QT_BEGIN_NAMESPACE
+
+//#define QT_DEBUG_COMPONENT
+
+#ifdef QT_NO_DEBUG
+# define QLIBRARY_AS_DEBUG false
+#else
+# define QLIBRARY_AS_DEBUG true
+#endif
+
+#if defined(Q_OS_UNIX) && !defined(Q_OS_MAC)
+// We don't use separate debug and release libs on UNIX, so we want
+// to allow loading plugins, regardless of how they were built.
+# define QT_NO_DEBUG_PLUGIN_CHECK
+#endif
+
+Q_GLOBAL_STATIC(QMutex, qt_library_mutex)
+
+/*!
+ \class QLibrary
+ \reentrant
+ \brief The QLibrary class loads shared libraries at runtime.
+
+ \mainclass
+ \ingroup plugins
+
+ An instance of a QLibrary object operates on a single shared
+ object file (which we call a "library", but is also known as a
+ "DLL"). A QLibrary provides access to the functionality in the
+ library in a platform independent way. You can either pass a file
+ name in the constructor, or set it explicitly with setFileName().
+ When loading the library, QLibrary searches in all the
+ system-specific library locations (e.g. \c LD_LIBRARY_PATH on
+ Unix), unless the file name has an absolute path. If the file
+ cannot be found, QLibrary tries the name with different
+ platform-specific file suffixes, like ".so" on Unix, ".dylib" on
+ the Mac, or ".dll" on Windows. This makes it possible to specify
+ shared libraries that are only identified by their basename (i.e.
+ without their suffix), so the same code will work on different
+ operating systems.
+
+ The most important functions are load() to dynamically load the
+ library file, isLoaded() to check whether loading was successful,
+ and resolve() to resolve a symbol in the library. The resolve()
+ function implicitly tries to load the library if it has not been
+ loaded yet. Multiple instances of QLibrary can be used to access
+ the same physical library. Once loaded, libraries remain in memory
+ until the application terminates. You can attempt to unload a
+ library using unload(), but if other instances of QLibrary are
+ using the same library, the call will fail, and unloading will
+ only happen when every instance has called unload().
+
+ A typical use of QLibrary is to resolve an exported symbol in a
+ library, and to call the C function that this symbol represents.
+ This is called "explicit linking" in contrast to "implicit
+ linking", which is done by the link step in the build process when
+ linking an executable against a library.
+
+ The following code snippet loads a library, resolves the symbol
+ "mysymbol", and calls the function if everything succeeded. If
+ something goes wrong, e.g. the library file does not exist or the
+ symbol is not defined, the function pointer will be 0 and won't be
+ called.
+
+ \snippet doc/src/snippets/code/src_corelib_plugin_qlibrary.cpp 0
+
+ The symbol must be exported as a C function from the library for
+ resolve() to work. This means that the function must be wrapped in
+ an \c{extern "C"} block if the library is compiled with a C++
+ compiler. On Windows, this also requires the use of a \c dllexport
+ macro; see resolve() for the details of how this is done. For
+ convenience, there is a static resolve() function which you can
+ use if you just want to call a function in a library without
+ explicitly loading the library first:
+
+ \snippet doc/src/snippets/code/src_corelib_plugin_qlibrary.cpp 1
+
+ \sa QPluginLoader
+*/
+
+/*!
+ \enum QLibrary::LoadHint
+
+ This enum describes the possible hints that can be used to change the way
+ libraries are handled when they are loaded. These values indicate how
+ symbols are resolved when libraries are loaded, and are specified using
+ the setLoadHints() function.
+
+ \value ResolveAllSymbolsHint
+ Causes all symbols in a library to be resolved when it is loaded, not
+ simply when resolve() is called.
+ \value ExportExternalSymbolsHint
+ Exports unresolved and external symbols in the library so that they can be
+ resolved in other dynamically-loaded libraries loaded later.
+ \value LoadArchiveMemberHint
+ Allows the file name of the library to specify a particular object file
+ within an archive file.
+ If this hint is given, the filename of the library consists of
+ a path, which is a reference to an archive file, followed by
+ a reference to the archive member.
+
+ \sa loadHints
+*/
+
+
+#ifndef QT_NO_PLUGIN_CHECK
+struct qt_token_info
+{
+ qt_token_info(const char *f, const ulong fc)
+ : fields(f), field_count(fc), results(fc), lengths(fc)
+ {
+ results.fill(0);
+ lengths.fill(0);
+ }
+
+ const char *fields;
+ const ulong field_count;
+
+ QVector<const char *> results;
+ QVector<ulong> lengths;
+};
+
+/*
+ return values:
+ 1 parse ok
+ 0 eos
+ -1 parse error
+*/
+static int qt_tokenize(const char *s, ulong s_len, ulong *advance,
+ qt_token_info &token_info)
+{
+ ulong pos = 0, field = 0, fieldlen = 0;
+ char current;
+ int ret = -1;
+ *advance = 0;
+ for (;;) {
+ current = s[pos];
+
+ // next char
+ ++pos;
+ ++fieldlen;
+ ++*advance;
+
+ if (! current || pos == s_len + 1) {
+ // save result
+ token_info.results[(int)field] = s;
+ token_info.lengths[(int)field] = fieldlen - 1;
+
+ // end of string
+ ret = 0;
+ break;
+ }
+
+ if (current == token_info.fields[field]) {
+ // save result
+ token_info.results[(int)field] = s;
+ token_info.lengths[(int)field] = fieldlen - 1;
+
+ // end of field
+ fieldlen = 0;
+ ++field;
+ if (field == token_info.field_count - 1) {
+ // parse ok
+ ret = 1;
+ }
+ if (field == token_info.field_count) {
+ // done parsing
+ break;
+ }
+
+ // reset string and its length
+ s = s + pos;
+ s_len -= pos;
+ pos = 0;
+ }
+ }
+
+ return ret;
+}
+
+/*
+ returns true if the string s was correctly parsed, false otherwise.
+*/
+static bool qt_parse_pattern(const char *s, uint *version, bool *debug, QByteArray *key)
+{
+ bool ret = true;
+
+ qt_token_info pinfo("=\n", 2);
+ int parse;
+ ulong at = 0, advance, parselen = qstrlen(s);
+ do {
+ parse = qt_tokenize(s + at, parselen, &advance, pinfo);
+ if (parse == -1) {
+ ret = false;
+ break;
+ }
+
+ at += advance;
+ parselen -= advance;
+
+ if (qstrncmp("version", pinfo.results[0], pinfo.lengths[0]) == 0) {
+ // parse version string
+ qt_token_info pinfo2("..-", 3);
+ if (qt_tokenize(pinfo.results[1], pinfo.lengths[1],
+ &advance, pinfo2) != -1) {
+ QByteArray m(pinfo2.results[0], pinfo2.lengths[0]);
+ QByteArray n(pinfo2.results[1], pinfo2.lengths[1]);
+ QByteArray p(pinfo2.results[2], pinfo2.lengths[2]);
+ *version = (m.toUInt() << 16) | (n.toUInt() << 8) | p.toUInt();
+ } else {
+ ret = false;
+ break;
+ }
+ } else if (qstrncmp("debug", pinfo.results[0], pinfo.lengths[0]) == 0) {
+ *debug = qstrncmp("true", pinfo.results[1], pinfo.lengths[1]) == 0;
+ } else if (qstrncmp("buildkey", pinfo.results[0],
+ pinfo.lengths[0]) == 0){
+ // save buildkey
+ *key = QByteArray(pinfo.results[1], pinfo.lengths[1]);
+ }
+ } while (parse == 1 && parselen > 0);
+
+ return ret;
+}
+#endif // QT_NO_PLUGIN_CHECK
+
+#if defined(Q_OS_UNIX) && !defined(Q_OS_MAC) && !defined(QT_NO_PLUGIN_CHECK)
+
+#if defined(Q_OS_FREEBSD) || defined(Q_OS_LINUX)
+# define USE_MMAP
+QT_BEGIN_INCLUDE_NAMESPACE
+# include <sys/types.h>
+# include <sys/mman.h>
+QT_END_INCLUDE_NAMESPACE
+#endif // Q_OS_FREEBSD || Q_OS_LINUX
+
+static long qt_find_pattern(const char *s, ulong s_len,
+ const char *pattern, ulong p_len)
+{
+ /*
+ we search from the end of the file because on the supported
+ systems, the read-only data/text segments are placed at the end
+ of the file. HOWEVER, when building with debugging enabled, all
+ the debug symbols are placed AFTER the data/text segments.
+
+ what does this mean? when building in release mode, the search
+ is fast because the data we are looking for is at the end of the
+ file... when building in debug mode, the search is slower
+ because we have to skip over all the debugging symbols first
+ */
+
+ if (! s || ! pattern || p_len > s_len) return -1;
+ ulong i, hs = 0, hp = 0, delta = s_len - p_len;
+
+ for (i = 0; i < p_len; ++i) {
+ hs += s[delta + i];
+ hp += pattern[i];
+ }
+ i = delta;
+ for (;;) {
+ if (hs == hp && qstrncmp(s + i, pattern, p_len) == 0)
+ return i;
+ if (i == 0)
+ break;
+ --i;
+ hs -= s[i + p_len];
+ hs += s[i];
+ }
+
+ return -1;
+}
+
+/*
+ This opens the specified library, mmaps it into memory, and searches
+ for the QT_PLUGIN_VERIFICATION_DATA. The advantage of this approach is that
+ we can get the verification data without have to actually load the library.
+ This lets us detect mismatches more safely.
+
+ Returns false if version/key information is not present, or if the
+ information could not be read.
+ Returns true if version/key information is present and successfully read.
+*/
+static bool qt_unix_query(const QString &library, uint *version, bool *debug, QByteArray *key, QLibraryPrivate *lib = 0)
+{
+ QFile file(library);
+ if (!file.open(QIODevice::ReadOnly)) {
+ if (lib)
+ lib->errorString = file.errorString();
+ if (qt_debug_component()) {
+ qWarning("%s: %s", (const char*) QFile::encodeName(library),
+ qPrintable(qt_error_string(errno)));
+ }
+ return false;
+ }
+
+ QByteArray data;
+ char *filedata = 0;
+ ulong fdlen = 0;
+
+#ifdef USE_MMAP
+ char *mapaddr = 0;
+ size_t maplen = file.size();
+ mapaddr = (char *) mmap(mapaddr, maplen, PROT_READ, MAP_PRIVATE, file.handle(), 0);
+ if (mapaddr != MAP_FAILED) {
+ // mmap succeeded
+ filedata = mapaddr;
+ fdlen = maplen;
+ } else {
+ // mmap failed
+ if (qt_debug_component()) {
+ qWarning("mmap: %s", qPrintable(qt_error_string(errno)));
+ }
+ if (lib)
+ lib->errorString = QLibrary::tr("Could not mmap '%1': %2")
+ .arg(library)
+ .arg(qt_error_string());
+#endif // USE_MMAP
+ // try reading the data into memory instead
+ data = file.readAll();
+ filedata = data.data();
+ fdlen = data.size();
+#ifdef USE_MMAP
+ }
+#endif // USE_MMAP
+
+ // verify that the pattern is present in the plugin
+ const char pattern[] = "pattern=QT_PLUGIN_VERIFICATION_DATA";
+ const ulong plen = qstrlen(pattern);
+ long pos = qt_find_pattern(filedata, fdlen, pattern, plen);
+
+ bool ret = false;
+ if (pos >= 0)
+ ret = qt_parse_pattern(filedata + pos, version, debug, key);
+
+ if (!ret && lib)
+ lib->errorString = QLibrary::tr("Plugin verification data mismatch in '%1'").arg(library);
+#ifdef USE_MMAP
+ if (mapaddr != MAP_FAILED && munmap(mapaddr, maplen) != 0) {
+ if (qt_debug_component())
+ qWarning("munmap: %s", qPrintable(qt_error_string(errno)));
+ if (lib)
+ lib->errorString = QLibrary::tr("Could not unmap '%1': %2")
+ .arg(library)
+ .arg( qt_error_string() );
+ }
+#endif // USE_MMAP
+
+ file.close();
+ return ret;
+}
+
+#endif // Q_OS_UNIX && !Q_OS_MAC && !defined(QT_NO_PLUGIN_CHECK)
+
+typedef QMap<QString, QLibraryPrivate*> LibraryMap;
+Q_GLOBAL_STATIC(LibraryMap, libraryMap)
+
+QLibraryPrivate::QLibraryPrivate(const QString &canonicalFileName, const QString &version)
+ :pHnd(0), fileName(canonicalFileName), fullVersion(version), instance(0), qt_version(0),
+ libraryRefCount(1), libraryUnloadCount(0), pluginState(MightBeAPlugin)
+{ libraryMap()->insert(canonicalFileName, this); }
+
+QLibraryPrivate *QLibraryPrivate::findOrCreate(const QString &fileName, const QString &version)
+{
+ QMutexLocker locker(qt_library_mutex());
+ if (QLibraryPrivate *lib = libraryMap()->value(fileName)) {
+ lib->libraryRefCount.ref();
+ return lib;
+ }
+
+ return new QLibraryPrivate(fileName, version);
+}
+
+QLibraryPrivate::~QLibraryPrivate()
+{
+ LibraryMap * const map = libraryMap();
+ if (map) {
+ QLibraryPrivate *that = map->take(fileName);
+ Q_ASSERT(this == that);
+ Q_UNUSED(that);
+ }
+}
+
+void *QLibraryPrivate::resolve(const char *symbol)
+{
+ if (!pHnd)
+ return 0;
+ return resolve_sys(symbol);
+}
+
+
+bool QLibraryPrivate::load()
+{
+ libraryUnloadCount.ref();
+ if (pHnd)
+ return true;
+ if (fileName.isEmpty())
+ return false;
+ return load_sys();
+}
+
+bool QLibraryPrivate::unload()
+{
+ if (!pHnd)
+ return false;
+ if (!libraryUnloadCount.deref()) { // only unload if ALL QLibrary instance wanted to
+ if (instance)
+ delete instance();
+ if (unload_sys()) {
+ instance = 0;
+ pHnd = 0;
+ }
+ }
+
+ return (pHnd == 0);
+}
+
+void QLibraryPrivate::release()
+{
+ QMutexLocker locker(qt_library_mutex());
+ if (!libraryRefCount.deref())
+ delete this;
+}
+
+bool QLibraryPrivate::loadPlugin()
+{
+ if (instance) {
+ libraryUnloadCount.ref();
+ return true;
+ }
+ if (load()) {
+ instance = (QtPluginInstanceFunction)resolve("qt_plugin_instance");
+ return instance;
+ }
+ return false;
+}
+
+/*!
+ Returns true if \a fileName has a valid suffix for a loadable
+ library; otherwise returns false.
+
+ \table
+ \header \i Platform \i Valid suffixes
+ \row \i Windows \i \c .dll
+ \row \i Unix/Linux \i \c .so
+ \row \i AIX \i \c .a
+ \row \i HP-UX \i \c .sl, \c .so (HP-UXi)
+ \row \i Mac OS X \i \c .dylib, \c .bundle, \c .so
+ \endtable
+
+ Trailing versioning numbers on Unix are ignored.
+ */
+bool QLibrary::isLibrary(const QString &fileName)
+{
+#if defined(Q_OS_WIN32) || defined(Q_OS_WINCE)
+ return fileName.endsWith(QLatin1String(".dll"));
+#else
+ QString completeSuffix = QFileInfo(fileName).completeSuffix();
+ if (completeSuffix.isEmpty())
+ return false;
+ QStringList suffixes = completeSuffix.split(QLatin1Char('.'));
+# if defined(Q_OS_DARWIN)
+
+ // On Mac, libs look like libmylib.1.0.0.dylib
+ const QString lastSuffix = suffixes.at(suffixes.count() - 1);
+ const QString firstSuffix = suffixes.at(0);
+
+ bool valid = (lastSuffix == QLatin1String("dylib")
+ || firstSuffix == QLatin1String("so")
+ || firstSuffix == QLatin1String("bundle"));
+
+ return valid;
+# else // Generic Unix
+ QStringList validSuffixList;
+
+# if defined(Q_OS_HPUX)
+/*
+ See "HP-UX Linker and Libraries User's Guide", section "Link-time Differences between PA-RISC and IPF":
+ "In PA-RISC (PA-32 and PA-64) shared libraries are suffixed with .sl. In IPF (32-bit and 64-bit),
+ the shared libraries are suffixed with .so. For compatibility, the IPF linker also supports the .sl suffix."
+ */
+ validSuffixList << QLatin1String("sl");
+# if defined __ia64
+ validSuffixList << QLatin1String("so");
+# endif
+# elif defined(Q_OS_AIX)
+ validSuffixList << QLatin1String("a") << QLatin1String("so");
+# elif defined(Q_OS_UNIX)
+ validSuffixList << QLatin1String("so");
+# endif
+
+ // Examples of valid library names:
+ // libfoo.so
+ // libfoo.so.0
+ // libfoo.so.0.3
+ // libfoo-0.3.so
+ // libfoo-0.3.so.0.3.0
+
+ int suffix;
+ int suffixPos = -1;
+ for (suffix = 0; suffix < validSuffixList.count() && suffixPos == -1; ++suffix)
+ suffixPos = suffixes.indexOf(validSuffixList.at(suffix));
+
+ bool valid = suffixPos != -1;
+ for (int i = suffixPos + 1; i < suffixes.count() && valid; ++i)
+ if (i != suffixPos)
+ suffixes.at(i).toInt(&valid);
+ return valid;
+# endif
+#endif
+
+}
+
+bool QLibraryPrivate::isPlugin(QSettings *settings)
+{
+ errorString.clear();
+ if (pluginState != MightBeAPlugin)
+ return pluginState == IsAPlugin;
+
+#ifndef QT_NO_PLUGIN_CHECK
+ bool debug = !QLIBRARY_AS_DEBUG;
+ QByteArray key;
+ bool success = false;
+
+ QFileInfo fileinfo(fileName);
+
+#ifndef QT_NO_DATESTRING
+ lastModified = fileinfo.lastModified().toString(Qt::ISODate);
+#endif
+ QString regkey = QString::fromLatin1("Qt Plugin Cache %1.%2.%3/%4")
+ .arg((QT_VERSION & 0xff0000) >> 16)
+ .arg((QT_VERSION & 0xff00) >> 8)
+ .arg(QLIBRARY_AS_DEBUG ? QLatin1String("debug") : QLatin1String("false"))
+ .arg(fileName);
+ QStringList reg;
+#ifndef QT_NO_SETTINGS
+ bool madeSettings = false;
+ if (!settings) {
+ settings = new QSettings(QSettings::UserScope, QLatin1String("Trolltech"));
+ madeSettings = true;
+ }
+ reg = settings->value(regkey).toStringList();
+#endif
+ if (reg.count() == 4 && lastModified == reg.at(3)) {
+ qt_version = reg.at(0).toUInt(0, 16);
+ debug = bool(reg.at(1).toInt());
+ key = reg.at(2).toLatin1();
+ success = qt_version != 0;
+ } else {
+#if defined(Q_OS_UNIX) && !defined(Q_OS_MAC)
+ if (!pHnd) {
+ // use unix shortcut to avoid loading the library
+ success = qt_unix_query(fileName, &qt_version, &debug, &key, this);
+ } else
+#endif
+ {
+ bool temporary_load = false;
+#ifdef Q_OS_WIN
+ HMODULE hTempModule = 0;
+#endif
+ if (!pHnd) {
+#ifdef Q_OS_WIN
+ QT_WA({
+ hTempModule = ::LoadLibraryExW((wchar_t*)QDir::toNativeSeparators(fileName).utf16(), 0, DONT_RESOLVE_DLL_REFERENCES);
+ } , {
+ temporary_load = load_sys();
+ });
+#else
+ temporary_load = load_sys();
+#endif
+ }
+# ifdef Q_CC_BOR
+ typedef const char * __stdcall (*QtPluginQueryVerificationDataFunction)();
+# else
+ typedef const char * (*QtPluginQueryVerificationDataFunction)();
+# endif
+#ifdef Q_OS_WIN
+ QtPluginQueryVerificationDataFunction qtPluginQueryVerificationDataFunction = hTempModule
+ ? (QtPluginQueryVerificationDataFunction)
+#ifdef Q_OS_WINCE
+ ::GetProcAddressW(hTempModule, L"qt_plugin_query_verification_data")
+#else
+ ::GetProcAddress(hTempModule, "qt_plugin_query_verification_data")
+#endif
+ : (QtPluginQueryVerificationDataFunction) resolve("qt_plugin_query_verification_data");
+#else
+ QtPluginQueryVerificationDataFunction qtPluginQueryVerificationDataFunction =
+ (QtPluginQueryVerificationDataFunction) resolve("qt_plugin_query_verification_data");
+#endif
+
+ if (!qtPluginQueryVerificationDataFunction
+ || !qt_parse_pattern(qtPluginQueryVerificationDataFunction(), &qt_version, &debug, &key)) {
+ qt_version = 0;
+ key = "unknown";
+ if (temporary_load)
+ unload_sys();
+ } else {
+ success = true;
+ }
+#ifdef Q_OS_WIN
+ if (hTempModule) {
+ BOOL ok = ::FreeLibrary(hTempModule);
+ if (ok) {
+ hTempModule = 0;
+ }
+
+ }
+#endif
+ }
+
+ QStringList queried;
+ queried << QString::number(qt_version,16)
+ << QString::number((int)debug)
+ << QLatin1String(key)
+ << lastModified;
+#ifndef QT_NO_SETTINGS
+ settings->setValue(regkey, queried);
+#endif
+ }
+#ifndef QT_NO_SETTINGS
+ if (madeSettings)
+ delete settings;
+#endif
+
+ if (!success) {
+ if (errorString.isEmpty()){
+ if (fileName.isEmpty())
+ errorString = QLibrary::tr("The shared library was not found.");
+ else
+ errorString = QLibrary::tr("The file '%1' is not a valid Qt plugin.").arg(fileName);
+ }
+ return false;
+ }
+
+ pluginState = IsNotAPlugin; // be pessimistic
+
+ if ((qt_version > QT_VERSION) || ((QT_VERSION & 0xff0000) > (qt_version & 0xff0000))) {
+ if (qt_debug_component()) {
+ qWarning("In %s:\n"
+ " Plugin uses incompatible Qt library (%d.%d.%d) [%s]",
+ (const char*) QFile::encodeName(fileName),
+ (qt_version&0xff0000) >> 16, (qt_version&0xff00) >> 8, qt_version&0xff,
+ debug ? "debug" : "release");
+ }
+ errorString = QLibrary::tr("The plugin '%1' uses incompatible Qt library. (%2.%3.%4) [%5]")
+ .arg(fileName)
+ .arg((qt_version&0xff0000) >> 16)
+ .arg((qt_version&0xff00) >> 8)
+ .arg(qt_version&0xff)
+ .arg(debug ? QLatin1String("debug") : QLatin1String("release"));
+ } else if (key != QT_BUILD_KEY
+#ifdef QT_BUILD_KEY_COMPAT
+ // be sure to load plugins using an older but compatible build key
+ && key != QT_BUILD_KEY_COMPAT
+#endif
+ ) {
+ if (qt_debug_component()) {
+ qWarning("In %s:\n"
+ " Plugin uses incompatible Qt library\n"
+ " expected build key \"%s\", got \"%s\"",
+ (const char*) QFile::encodeName(fileName),
+ QT_BUILD_KEY,
+ key.isEmpty() ? "<null>" : (const char *) key);
+ }
+ errorString = QLibrary::tr("The plugin '%1' uses incompatible Qt library."
+ " Expected build key \"%2\", got \"%3\"")
+ .arg(fileName)
+ .arg(QLatin1String(QT_BUILD_KEY))
+ .arg(key.isEmpty() ? QLatin1String("<null>") : QLatin1String((const char *) key));
+#ifndef QT_NO_DEBUG_PLUGIN_CHECK
+ } else if(debug != QLIBRARY_AS_DEBUG) {
+ //don't issue a qWarning since we will hopefully find a non-debug? --Sam
+ errorString = QLibrary::tr("The plugin '%1' uses incompatible Qt library."
+ " (Cannot mix debug and release libraries.)").arg(fileName);
+#endif
+ } else {
+ pluginState = IsAPlugin;
+ }
+
+ return pluginState == IsAPlugin;
+#else
+ Q_UNUSED(settings);
+ return pluginState == MightBeAPlugin;
+#endif
+}
+
+/*!
+ Loads the library and returns true if the library was loaded
+ successfully; otherwise returns false. Since resolve() always
+ calls this function before resolving any symbols it is not
+ necessary to call it explicitly. In some situations you might want
+ the library loaded in advance, in which case you would use this
+ function.
+
+ \sa unload()
+*/
+bool QLibrary::load()
+{
+ if (!d)
+ return false;
+ if (did_load)
+ return d->pHnd;
+ did_load = true;
+ return d->load();
+}
+
+/*!
+ Unloads the library and returns true if the library could be
+ unloaded; otherwise returns false.
+
+ This happens automatically on application termination, so you
+ shouldn't normally need to call this function.
+
+ If other instances of QLibrary are using the same library, the
+ call will fail, and unloading will only happen when every instance
+ has called unload().
+
+ Note that on Mac OS X 10.3 (Panther), dynamic libraries cannot be unloaded.
+
+ \sa resolve(), load()
+*/
+bool QLibrary::unload()
+{
+ if (did_load) {
+ did_load = false;
+ return d->unload();
+ }
+ return false;
+}
+
+/*!
+ Returns true if the library is loaded; otherwise returns false.
+
+ \sa load()
+ */
+bool QLibrary::isLoaded() const
+{
+ return d && d->pHnd;
+}
+
+
+/*!
+ Constructs a library with the given \a parent.
+ */
+QLibrary::QLibrary(QObject *parent)
+ :QObject(parent), d(0), did_load(false)
+{
+}
+
+
+/*!
+ Constructs a library object with the given \a parent that will
+ load the library specified by \a fileName.
+
+ We recommend omitting the file's suffix in \a fileName, since
+ QLibrary will automatically look for the file with the appropriate
+ suffix in accordance with the platform, e.g. ".so" on Unix,
+ ".dylib" on Mac OS X, and ".dll" on Windows. (See \l{fileName}.)
+ */
+QLibrary::QLibrary(const QString& fileName, QObject *parent)
+ :QObject(parent), d(0), did_load(false)
+{
+ setFileName(fileName);
+}
+
+
+/*!
+ Constructs a library object with the given \a parent that will
+ load the library specified by \a fileName and major version number \a verNum.
+ Currently, the version number is ignored on Windows.
+
+ We recommend omitting the file's suffix in \a fileName, since
+ QLibrary will automatically look for the file with the appropriate
+ suffix in accordance with the platform, e.g. ".so" on Unix,
+ ".dylib" on Mac OS X, and ".dll" on Windows. (See \l{fileName}.)
+ */
+QLibrary::QLibrary(const QString& fileName, int verNum, QObject *parent)
+ :QObject(parent), d(0), did_load(false)
+{
+ setFileNameAndVersion(fileName, verNum);
+}
+
+/*!
+ Constructs a library object with the given \a parent that will
+ load the library specified by \a fileName and full version number \a version.
+ Currently, the version number is ignored on Windows.
+
+ We recommend omitting the file's suffix in \a fileName, since
+ QLibrary will automatically look for the file with the appropriate
+ suffix in accordance with the platform, e.g. ".so" on Unix,
+ ".dylib" on Mac OS X, and ".dll" on Windows. (See \l{fileName}.)
+ */
+QLibrary::QLibrary(const QString& fileName, const QString &version, QObject *parent)
+ :QObject(parent), d(0), did_load(false)
+{
+ setFileNameAndVersion(fileName, version);
+}
+
+/*!
+ Destroys the QLibrary object.
+
+ Unless unload() was called explicitly, the library stays in memory
+ until the application terminates.
+
+ \sa isLoaded(), unload()
+*/
+QLibrary::~QLibrary()
+{
+ if (d)
+ d->release();
+}
+
+
+/*!
+ \property QLibrary::fileName
+ \brief the file name of the library
+
+ We recommend omitting the file's suffix in the file name, since
+ QLibrary will automatically look for the file with the appropriate
+ suffix (see isLibrary()).
+
+ When loading the library, QLibrary searches in all system-specific
+ library locations (e.g. \c LD_LIBRARY_PATH on Unix), unless the
+ file name has an absolute path. After loading the library
+ successfully, fileName() returns the fully-qualified file name of
+ the library, including the full path to the library if one was given
+ in the constructor or passed to setFileName().
+
+ For example, after successfully loading the "GL" library on Unix
+ platforms, fileName() will return "libGL.so". If the file name was
+ originally passed as "/usr/lib/libGL", fileName() will return
+ "/usr/lib/libGL.so".
+*/
+
+void QLibrary::setFileName(const QString &fileName)
+{
+ QLibrary::LoadHints lh;
+ if (d) {
+ lh = d->loadHints;
+ d->release();
+ d = 0;
+ did_load = false;
+ }
+ d = QLibraryPrivate::findOrCreate(fileName);
+ d->loadHints = lh;
+}
+
+QString QLibrary::fileName() const
+{
+ if (d)
+ return d->qualifiedFileName.isEmpty() ? d->fileName : d->qualifiedFileName;
+ return QString();
+}
+
+/*!
+ \fn void QLibrary::setFileNameAndVersion(const QString &fileName, int versionNumber)
+
+ Sets the fileName property and major version number to \a fileName
+ and \a versionNumber respectively.
+ The \a versionNumber is ignored on Windows.
+ \sa setFileName()
+*/
+void QLibrary::setFileNameAndVersion(const QString &fileName, int verNum)
+{
+ QLibrary::LoadHints lh;
+ if (d) {
+ lh = d->loadHints;
+ d->release();
+ d = 0;
+ did_load = false;
+ }
+ d = QLibraryPrivate::findOrCreate(fileName, verNum >= 0 ? QString::number(verNum) : QString());
+ d->loadHints = lh;
+}
+
+/*!
+ \since 4.4
+
+ Sets the fileName property and full version number to \a fileName
+ and \a version respectively.
+ The \a version parameter is ignored on Windows.
+ \sa setFileName()
+*/
+void QLibrary::setFileNameAndVersion(const QString &fileName, const QString &version)
+{
+ QLibrary::LoadHints lh;
+ if (d) {
+ lh = d->loadHints;
+ d->release();
+ d = 0;
+ did_load = false;
+ }
+ d = QLibraryPrivate::findOrCreate(fileName, version);
+ d->loadHints = lh;
+}
+
+/*!
+ Returns the address of the exported symbol \a symbol. The library is
+ loaded if necessary. The function returns 0 if the symbol could
+ not be resolved or if the library could not be loaded.
+
+ Example:
+ \snippet doc/src/snippets/code/src_corelib_plugin_qlibrary.cpp 2
+
+ The symbol must be exported as a C function from the library. This
+ means that the function must be wrapped in an \c{extern "C"} if
+ the library is compiled with a C++ compiler. On Windows you must
+ also explicitly export the function from the DLL using the
+ \c{__declspec(dllexport)} compiler directive, for example:
+
+ \snippet doc/src/snippets/code/src_corelib_plugin_qlibrary.cpp 3
+
+ with \c MY_EXPORT defined as
+
+ \snippet doc/src/snippets/code/src_corelib_plugin_qlibrary.cpp 4
+
+*/
+void *QLibrary::resolve(const char *symbol)
+{
+ if (!load())
+ return 0;
+ return d->resolve(symbol);
+}
+
+/*!
+ \overload
+
+ Loads the library \a fileName and returns the address of the
+ exported symbol \a symbol. Note that \a fileName should not
+ include the platform-specific file suffix; (see \l{fileName}). The
+ library remains loaded until the application exits.
+
+ The function returns 0 if the symbol could not be resolved or if
+ the library could not be loaded.
+
+ \sa resolve()
+*/
+void *QLibrary::resolve(const QString &fileName, const char *symbol)
+{
+ QLibrary library(fileName);
+ return library.resolve(symbol);
+}
+
+/*!
+ \overload
+
+ Loads the library \a fileName with major version number \a verNum and
+ returns the address of the exported symbol \a symbol.
+ Note that \a fileName should not include the platform-specific file suffix;
+ (see \l{fileName}). The library remains loaded until the application exits.
+ \a verNum is ignored on Windows.
+
+ The function returns 0 if the symbol could not be resolved or if
+ the library could not be loaded.
+
+ \sa resolve()
+*/
+void *QLibrary::resolve(const QString &fileName, int verNum, const char *symbol)
+{
+ QLibrary library(fileName, verNum);
+ return library.resolve(symbol);
+}
+
+/*!
+ \overload
+ \since 4.4
+
+ Loads the library \a fileName with full version number \a version and
+ returns the address of the exported symbol \a symbol.
+ Note that \a fileName should not include the platform-specific file suffix;
+ (see \l{fileName}). The library remains loaded until the application exits.
+ \a version is ignored on Windows.
+
+ The function returns 0 if the symbol could not be resolved or if
+ the library could not be loaded.
+
+ \sa resolve()
+*/
+void *QLibrary::resolve(const QString &fileName, const QString &version, const char *symbol)
+{
+ QLibrary library(fileName, version);
+ return library.resolve(symbol);
+}
+
+/*!
+ \fn QString QLibrary::library() const
+
+ Use fileName() instead.
+*/
+
+/*!
+ \fn void QLibrary::setAutoUnload( bool b )
+
+ Use load(), isLoaded(), and unload() as necessary instead.
+*/
+
+/*!
+ \since 4.2
+
+ Returns a text string with the description of the last error that occurred.
+ Currently, errorString will only be set if load(), unload() or resolve() for some reason fails.
+*/
+QString QLibrary::errorString() const
+{
+ return (!d || d->errorString.isEmpty()) ? tr("Unknown error") : d->errorString;
+}
+
+/*!
+ \property QLibrary::loadHints
+ \brief Give the load() function some hints on how it should behave.
+
+ You can give some hints on how the symbols are resolved. Usually,
+ the symbols are not resolved at load time, but resolved lazily,
+ (that is, when resolve() is called). If you set the loadHint to
+ ResolveAllSymbolsHint, then all symbols will be resolved at load time
+ if the platform supports it.
+
+ Setting ExportExternalSymbolsHint will make the external symbols in the
+ library available for resolution in subsequent loaded libraries.
+
+ If LoadArchiveMemberHint is set, the file name
+ is composed of two components: A path which is a reference to an
+ archive file followed by the second component which is the reference to
+ the archive member. For instance, the fileName \c libGL.a(shr_64.o) will refer
+ to the library \c shr_64.o in the archive file named \c libGL.a. This
+ is only supported on the AIX platform.
+
+ The interpretation of the load hints is platform dependent, and if
+ you use it you are probably making some assumptions on which platform
+ you are compiling for, so use them only if you understand the consequences
+ of them.
+
+ By default, none of these flags are set, so libraries will be loaded with
+ lazy symbol resolution, and will not export external symbols for resolution
+ in other dynamically-loaded libraries.
+*/
+void QLibrary::setLoadHints(LoadHints hints)
+{
+ if (!d) {
+ d = QLibraryPrivate::findOrCreate(QString()); // ugly, but we need a d-ptr
+ d->errorString.clear();
+ }
+ d->loadHints = hints;
+}
+
+QLibrary::LoadHints QLibrary::loadHints() const
+{
+ return d ? d->loadHints : (QLibrary::LoadHints)0;
+}
+
+/* Internal, for debugging */
+bool qt_debug_component()
+{
+#if defined(QT_DEBUG_COMPONENT)
+ return true; //compatibility?
+#else
+ static int debug_env = -1;
+ if (debug_env == -1)
+ debug_env = QT_PREPEND_NAMESPACE(qgetenv)("QT_DEBUG_PLUGINS").toInt();
+
+ return debug_env != 0;
+#endif
+}
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_LIBRARY
diff --git a/src/corelib/plugin/qlibrary.h b/src/corelib/plugin/qlibrary.h
new file mode 100644
index 0000000000..7e551e58bf
--- /dev/null
+++ b/src/corelib/plugin/qlibrary.h
@@ -0,0 +1,120 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QLIBRARY_H
+#define QLIBRARY_H
+
+#include <QtCore/qobject.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+#if defined(QT_NO_LIBRARY) && defined(Q_OS_WIN)
+#undef QT_NO_LIBRARY
+#pragma message("QT_NO_LIBRARY is not supported on Windows")
+#endif
+
+#ifndef QT_NO_LIBRARY
+
+class QLibraryPrivate;
+
+class Q_CORE_EXPORT QLibrary : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(QString fileName READ fileName WRITE setFileName)
+ Q_PROPERTY(LoadHints loadHints READ loadHints WRITE setLoadHints)
+ Q_FLAGS(LoadHint LoadHints)
+public:
+ enum LoadHint {
+ ResolveAllSymbolsHint = 0x01,
+ ExportExternalSymbolsHint = 0x02,
+ LoadArchiveMemberHint = 0x04
+ };
+ Q_DECLARE_FLAGS(LoadHints, LoadHint)
+
+ explicit QLibrary(QObject *parent = 0);
+ explicit QLibrary(const QString& fileName, QObject *parent = 0);
+ explicit QLibrary(const QString& fileName, int verNum, QObject *parent = 0);
+ explicit QLibrary(const QString& fileName, const QString &version, QObject *parent = 0);
+ ~QLibrary();
+
+ void *resolve(const char *symbol);
+ static void *resolve(const QString &fileName, const char *symbol);
+ static void *resolve(const QString &fileName, int verNum, const char *symbol);
+ static void *resolve(const QString &fileName, const QString &version, const char *symbol);
+
+ bool load();
+ bool unload();
+ bool isLoaded() const;
+
+ static bool isLibrary(const QString &fileName);
+
+ void setFileName(const QString &fileName);
+ QString fileName() const;
+
+ void setFileNameAndVersion(const QString &fileName, int verNum);
+ void setFileNameAndVersion(const QString &fileName, const QString &version);
+ QString errorString() const;
+
+ void setLoadHints(LoadHints hints);
+ LoadHints loadHints() const;
+#ifdef QT3_SUPPORT
+ inline QT3_SUPPORT QString library() const { return fileName(); }
+ inline QT3_SUPPORT void setAutoUnload( bool ) {}
+#endif
+private:
+ QLibraryPrivate *d;
+ bool did_load;
+ Q_DISABLE_COPY(QLibrary)
+};
+
+Q_DECLARE_OPERATORS_FOR_FLAGS(QLibrary::LoadHints)
+
+#endif //QT_NO_LIBRARY
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif //QLIBRARY_H
diff --git a/src/corelib/plugin/qlibrary_p.h b/src/corelib/plugin/qlibrary_p.h
new file mode 100644
index 0000000000..36bde95f5d
--- /dev/null
+++ b/src/corelib/plugin/qlibrary_p.h
@@ -0,0 +1,122 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QLIBRARY_P_H
+#define QLIBRARY_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of the QLibrary class. This header file may change from
+// version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#ifdef Q_WS_WIN
+# include "QtCore/qt_windows.h"
+#endif
+#include "QtCore/qlibrary.h"
+#include "QtCore/qpointer.h"
+#include "QtCore/qstringlist.h"
+#include "QtCore/qplugin.h"
+
+#ifndef QT_NO_LIBRARY
+
+QT_BEGIN_NAMESPACE
+
+bool qt_debug_component();
+
+class QSettings;
+class QLibraryPrivate
+{
+public:
+
+#ifdef Q_WS_WIN
+ HINSTANCE
+#else
+ void *
+#endif
+ pHnd;
+
+ QString fileName, qualifiedFileName;
+ QString fullVersion;
+
+ bool load();
+ bool loadPlugin(); // loads and resolves instance
+ bool unload();
+ void release();
+ void *resolve(const char *);
+
+ static QLibraryPrivate *findOrCreate(const QString &fileName, const QString &version = QString());
+
+ QtPluginInstanceFunction instance;
+ uint qt_version;
+ QString lastModified;
+
+ QString errorString;
+ QLibrary::LoadHints loadHints;
+
+ bool isPlugin(QSettings *settings = 0);
+
+
+private:
+ explicit QLibraryPrivate(const QString &canonicalFileName, const QString &version);
+ ~QLibraryPrivate();
+
+ bool load_sys();
+ bool unload_sys();
+ void *resolve_sys(const char *);
+
+ QAtomicInt libraryRefCount;
+ QAtomicInt libraryUnloadCount;
+
+ enum {IsAPlugin, IsNotAPlugin, MightBeAPlugin } pluginState;
+ friend class QLibraryPrivateHasFriends;
+};
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_LIBRARY
+
+#endif // QLIBRARY_P_H
diff --git a/src/corelib/plugin/qlibrary_unix.cpp b/src/corelib/plugin/qlibrary_unix.cpp
new file mode 100644
index 0000000000..08bd2d0843
--- /dev/null
+++ b/src/corelib/plugin/qlibrary_unix.cpp
@@ -0,0 +1,266 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qplatformdefs.h"
+
+#include <qfile.h>
+#include "qlibrary_p.h"
+#include <qfileinfo.h>
+#include <qcoreapplication.h>
+
+#ifndef QT_NO_LIBRARY
+
+#ifdef Q_OS_MAC
+# include <private/qcore_mac_p.h>
+#endif
+
+#if defined(QT_AOUT_UNDERSCORE)
+#include <string.h>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+#if !defined(QT_HPUX_LD)
+QT_BEGIN_INCLUDE_NAMESPACE
+#include <dlfcn.h>
+QT_END_INCLUDE_NAMESPACE
+#endif
+
+static QString qdlerror()
+{
+#if !defined(QT_HPUX_LD)
+ const char *err = dlerror();
+#else
+ const char *err = strerror(errno);
+#endif
+ return err ? QLatin1String("(")+QString::fromLocal8Bit(err) + QLatin1String(")"): QString();
+}
+
+bool QLibraryPrivate::load_sys()
+{
+ QFileInfo fi(fileName);
+ QString path = fi.path();
+ QString name = fi.fileName();
+ if (path == QLatin1String(".") && !fileName.startsWith(path))
+ path.clear();
+ else
+ path += QLatin1Char('/');
+
+ // The first filename we want to attempt to load is the filename as the callee specified.
+ // Thus, the first attempt we do must be with an empty prefix and empty suffix.
+ QStringList suffixes(QLatin1String("")), prefixes(QLatin1String(""));
+ if (pluginState != IsAPlugin) {
+ prefixes << QLatin1String("lib");
+#if defined(Q_OS_HPUX)
+ // according to
+ // http://docs.hp.com/en/B2355-90968/linkerdifferencesiapa.htm
+
+ // In PA-RISC (PA-32 and PA-64) shared libraries are suffixed
+ // with .sl. In IPF (32-bit and 64-bit), the shared libraries
+ // are suffixed with .so. For compatibility, the IPF linker
+ // also supports the .sl suffix.
+
+ // But since we don't know if we are built on HPUX or HPUXi,
+ // we support both .sl (and .<version>) and .so suffixes but
+ // .so is preferred.
+# if defined(__ia64)
+ if (!fullVersion.isEmpty()) {
+ suffixes << QString::fromLatin1(".so.%1").arg(fullVersion);
+ } else {
+ suffixes << QLatin1String(".so");
+ }
+# endif
+ if (!fullVersion.isEmpty()) {
+ suffixes << QString::fromLatin1(".sl.%1").arg(fullVersion);
+ suffixes << QString::fromLatin1(".%1").arg(fullVersion);
+ } else {
+ suffixes << QLatin1String(".sl");
+ }
+#elif defined(Q_OS_AIX)
+ suffixes << ".a";
+#else
+ if (!fullVersion.isEmpty()) {
+ suffixes << QString::fromLatin1(".so.%1").arg(fullVersion);
+ } else {
+ suffixes << QLatin1String(".so");
+ }
+#endif
+# ifdef Q_OS_MAC
+ if (!fullVersion.isEmpty()) {
+ suffixes << QString::fromLatin1(".%1.bundle").arg(fullVersion);
+ suffixes << QString::fromLatin1(".%1.dylib").arg(fullVersion);
+ } else {
+ suffixes << QLatin1String(".bundle") << QLatin1String(".dylib");
+ }
+#endif
+ }
+ int dlFlags = 0;
+#if defined(QT_HPUX_LD)
+ dlFlags = DYNAMIC_PATH | BIND_NONFATAL;
+ if (loadHints & QLibrary::ResolveAllSymbolsHint) {
+ dlFlags |= BIND_IMMEDIATE;
+ } else {
+ dlFlags |= BIND_DEFERRED;
+ }
+#else
+ if (loadHints & QLibrary::ResolveAllSymbolsHint) {
+ dlFlags |= RTLD_NOW;
+ } else {
+ dlFlags |= RTLD_LAZY;
+ }
+ if (loadHints & QLibrary::ExportExternalSymbolsHint) {
+ dlFlags |= RTLD_GLOBAL;
+ }
+#if !defined(Q_OS_CYGWIN)
+ else {
+#if defined(Q_OS_MAC)
+ if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4)
+#endif
+ dlFlags |= RTLD_LOCAL;
+ }
+#endif
+#if defined(Q_OS_AIX) // Not sure if any other platform actually support this thing.
+ if (loadHints & QLibrary::LoadArchiveMemberHint) {
+ dlFlags |= RTLD_MEMBER;
+ }
+#endif
+#endif // QT_HPUX_LD
+ QString attempt;
+ bool retry = true;
+ for(int prefix = 0; retry && !pHnd && prefix < prefixes.size(); prefix++) {
+ for(int suffix = 0; retry && !pHnd && suffix < suffixes.size(); suffix++) {
+ if (!prefixes.at(prefix).isEmpty() && name.startsWith(prefixes.at(prefix)))
+ continue;
+ if (!suffixes.at(suffix).isEmpty() && name.endsWith(suffixes.at(suffix)))
+ continue;
+ if (loadHints & QLibrary::LoadArchiveMemberHint) {
+ attempt = name;
+ int lparen = attempt.indexOf(QLatin1Char('('));
+ if (lparen == -1)
+ lparen = attempt.count();
+ attempt = path + prefixes.at(prefix) + attempt.insert(lparen, suffixes.at(suffix));
+ } else {
+ attempt = path + prefixes.at(prefix) + name + suffixes.at(suffix);
+ }
+#if defined(QT_HPUX_LD)
+ pHnd = (void*)shl_load(QFile::encodeName(attempt), dlFlags, 0);
+#else
+ pHnd = dlopen(QFile::encodeName(attempt), dlFlags);
+#endif
+ if (!pHnd && fileName.startsWith(QLatin1Char('/')) && QFile::exists(attempt)) {
+ // We only want to continue if dlopen failed due to that the shared library did not exist.
+ // However, we are only able to apply this check for absolute filenames (since they are
+ // not influenced by the content of LD_LIBRARY_PATH, /etc/ld.so.cache, DT_RPATH etc...)
+ // This is all because dlerror is flawed and cannot tell us the reason why it failed.
+ retry = false;
+ }
+ }
+ }
+
+#ifdef Q_OS_MAC
+ if (!pHnd) {
+ if (CFBundleRef bundle = CFBundleGetBundleWithIdentifier(QCFString(fileName))) {
+ QCFType<CFURLRef> url = CFBundleCopyExecutableURL(bundle);
+ QCFString str = CFURLCopyFileSystemPath(url, kCFURLPOSIXPathStyle);
+ pHnd = dlopen(QFile::encodeName(str), dlFlags);
+ attempt = str;
+ }
+ }
+# endif
+ if (!pHnd) {
+ errorString = QLibrary::tr("Cannot load library %1: %2").arg(fileName).arg(qdlerror());
+ }
+ if (pHnd) {
+ qualifiedFileName = attempt;
+ errorString.clear();
+ }
+ return (pHnd != 0);
+}
+
+bool QLibraryPrivate::unload_sys()
+{
+#if defined(QT_HPUX_LD)
+ if (shl_unload((shl_t)pHnd)) {
+#else
+ if (dlclose(pHnd)) {
+#endif
+ errorString = QLibrary::tr("Cannot unload library %1: %2").arg(fileName).arg(qdlerror());
+ return false;
+ }
+ errorString.clear();
+ return true;
+}
+
+#ifdef Q_OS_MAC
+Q_CORE_EXPORT void *qt_mac_resolve_sys(void *handle, const char *symbol)
+{
+ return dlsym(handle, symbol);
+}
+#endif
+
+void* QLibraryPrivate::resolve_sys(const char* symbol)
+{
+#if defined(QT_AOUT_UNDERSCORE)
+ // older a.out systems add an underscore in front of symbols
+ char* undrscr_symbol = new char[strlen(symbol)+2];
+ undrscr_symbol[0] = '_';
+ strcpy(undrscr_symbol+1, symbol);
+ void* address = dlsym(pHnd, undrscr_symbol);
+ delete [] undrscr_symbol;
+#elif defined(QT_HPUX_LD)
+ void* address = 0;
+ if (shl_findsym((shl_t*)&pHnd, symbol, TYPE_UNDEFINED, &address) < 0)
+ address = 0;
+#else
+ void* address = dlsym(pHnd, symbol);
+#endif
+ if (!address) {
+ errorString = QLibrary::tr("Cannot resolve symbol \"%1\" in %2: %3").arg(
+ QString::fromAscii(symbol)).arg(fileName).arg(qdlerror());
+ } else {
+ errorString.clear();
+ }
+ return address;
+}
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_LIBRARY
diff --git a/src/corelib/plugin/qlibrary_win.cpp b/src/corelib/plugin/qlibrary_win.cpp
new file mode 100644
index 0000000000..bbd698db78
--- /dev/null
+++ b/src/corelib/plugin/qlibrary_win.cpp
@@ -0,0 +1,147 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qplatformdefs.h"
+#include "qlibrary_p.h"
+#include "qfile.h"
+#include "qdir.h"
+#include "qfileinfo.h"
+#include "qdir.h"
+
+#if defined(QT_NO_LIBRARY) && defined(Q_OS_WIN)
+#undef QT_NO_LIBRARY
+#pragma message("QT_NO_LIBRARY is not supported on Windows")
+#endif
+
+#include "qt_windows.h"
+
+QT_BEGIN_NAMESPACE
+
+extern QString qt_error_string(int code);
+
+bool QLibraryPrivate::load_sys()
+{
+#ifdef Q_OS_WINCE
+ QString attempt = QFileInfo(fileName).absoluteFilePath();
+#else
+ QString attempt = fileName;
+#endif
+
+ //avoid 'Bad Image' message box
+ UINT oldmode = SetErrorMode(SEM_FAILCRITICALERRORS|SEM_NOOPENFILEERRORBOX);
+ QT_WA({
+ pHnd = LoadLibraryW((TCHAR*)QDir::toNativeSeparators(attempt).utf16());
+ } , {
+ pHnd = LoadLibraryA(QFile::encodeName(QDir::toNativeSeparators(attempt)).data());
+ });
+
+ if (pluginState != IsAPlugin) {
+#if defined(Q_OS_WINCE)
+ if (!pHnd && ::GetLastError() == ERROR_MOD_NOT_FOUND) {
+ QString secondAttempt = fileName;
+ QT_WA({
+ pHnd = LoadLibraryW((TCHAR*)QDir::toNativeSeparators(secondAttempt).utf16());
+ } , {
+ pHnd = LoadLibraryA(QFile::encodeName(QDir::toNativeSeparators(secondAttempt)).data());
+ });
+ }
+#endif
+ if (!pHnd && ::GetLastError() == ERROR_MOD_NOT_FOUND) {
+ attempt += QLatin1String(".dll");
+ QT_WA({
+ pHnd = LoadLibraryW((TCHAR*)QDir::toNativeSeparators(attempt).utf16());
+ } , {
+ pHnd = LoadLibraryA(QFile::encodeName(QDir::toNativeSeparators(attempt)).data());
+ });
+ }
+ }
+
+ SetErrorMode(oldmode);
+ if (!pHnd) {
+ errorString = QLibrary::tr("Cannot load library %1: %2").arg(fileName).arg(qt_error_string());
+ }
+ if (pHnd) {
+ errorString.clear();
+ QT_WA({
+ TCHAR buffer[MAX_PATH + 1];
+ ::GetModuleFileNameW(pHnd, buffer, MAX_PATH);
+ attempt = QString::fromUtf16(reinterpret_cast<const ushort *>(&buffer));
+ }, {
+ char buffer[MAX_PATH + 1];
+ ::GetModuleFileNameA(pHnd, buffer, MAX_PATH);
+ attempt = QString::fromLocal8Bit(buffer);
+ });
+ const QDir dir = QFileInfo(fileName).dir();
+ const QString realfilename = attempt.mid(attempt.lastIndexOf(QLatin1Char('\\')) + 1);
+ if (dir.path() == QLatin1String("."))
+ qualifiedFileName = realfilename;
+ else
+ qualifiedFileName = dir.filePath(realfilename);
+ }
+ return (pHnd != 0);
+}
+
+bool QLibraryPrivate::unload_sys()
+{
+ if (!FreeLibrary(pHnd)) {
+ errorString = QLibrary::tr("Cannot unload library %1: %2").arg(fileName).arg(qt_error_string());
+ return false;
+ }
+ errorString.clear();
+ return true;
+}
+
+void* QLibraryPrivate::resolve_sys(const char* symbol)
+{
+#ifdef Q_OS_WINCE
+ void* address = (void*)GetProcAddress(pHnd, (const wchar_t*)QString::fromLatin1(symbol).utf16());
+#else
+ void* address = (void*)GetProcAddress(pHnd, symbol);
+#endif
+ if (!address) {
+ errorString = QLibrary::tr("Cannot resolve symbol \"%1\" in %2: %3").arg(
+ QString::fromAscii(symbol)).arg(fileName).arg(qt_error_string());
+ } else {
+ errorString.clear();
+ }
+ return address;
+}
+QT_END_NAMESPACE
diff --git a/src/corelib/plugin/qplugin.h b/src/corelib/plugin/qplugin.h
new file mode 100644
index 0000000000..4d0e53c2b0
--- /dev/null
+++ b/src/corelib/plugin/qplugin.h
@@ -0,0 +1,141 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QPLUGIN_H
+#define QPLUGIN_H
+
+#include <QtCore/qobject.h>
+#include <QtCore/qpointer.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+#ifndef Q_EXTERN_C
+# ifdef __cplusplus
+# define Q_EXTERN_C extern "C"
+# else
+# define Q_EXTERN_C extern
+# endif
+#endif
+
+typedef QObject *(*QtPluginInstanceFunction)();
+
+void Q_CORE_EXPORT qRegisterStaticPluginInstanceFunction(QtPluginInstanceFunction function);
+
+#define Q_IMPORT_PLUGIN(PLUGIN) \
+ extern QT_PREPEND_NAMESPACE(QObject) *qt_plugin_instance_##PLUGIN(); \
+ class Static##PLUGIN##PluginInstance{ \
+ public: \
+ Static##PLUGIN##PluginInstance() { \
+ qRegisterStaticPluginInstanceFunction(qt_plugin_instance_##PLUGIN); \
+ } \
+ }; \
+ static Static##PLUGIN##PluginInstance static##PLUGIN##Instance;
+
+#define Q_PLUGIN_INSTANCE(IMPLEMENTATION) \
+ { \
+ static QT_PREPEND_NAMESPACE(QPointer)<QT_PREPEND_NAMESPACE(QObject)> _instance; \
+ if (!_instance) \
+ _instance = new IMPLEMENTATION; \
+ return _instance; \
+ }
+
+# define Q_EXPORT_PLUGIN(PLUGIN) \
+ Q_EXPORT_PLUGIN2(PLUGIN, PLUGIN)
+
+# define Q_EXPORT_STATIC_PLUGIN(PLUGIN) \
+ Q_EXPORT_STATIC_PLUGIN2(PLUGIN, PLUGIN)
+
+#if defined(QT_STATICPLUGIN)
+
+# define Q_EXPORT_PLUGIN2(PLUGIN, PLUGINCLASS) \
+ QT_PREPEND_NAMESPACE(QObject) \
+ *qt_plugin_instance_##PLUGIN() \
+ Q_PLUGIN_INSTANCE(PLUGINCLASS)
+
+# define Q_EXPORT_STATIC_PLUGIN2(PLUGIN, PLUGINCLASS) \
+ Q_EXPORT_PLUGIN2(PLUGIN, PLUGINCLASS)
+
+#else
+// NOTE: if you change pattern, you MUST change the pattern in
+// qlibrary.cpp as well. changing the pattern will break all
+// backwards compatibility as well (no old plugins will be loaded).
+# ifdef QPLUGIN_DEBUG_STR
+# undef QPLUGIN_DEBUG_STR
+# endif
+# ifdef QT_NO_DEBUG
+# define QPLUGIN_DEBUG_STR "false"
+# else
+# define QPLUGIN_DEBUG_STR "true"
+# endif
+# define Q_PLUGIN_VERIFICATION_DATA \
+ static const char *qt_plugin_verification_data = \
+ "pattern=""QT_PLUGIN_VERIFICATION_DATA""\n" \
+ "version="QT_VERSION_STR"\n" \
+ "debug="QPLUGIN_DEBUG_STR"\n" \
+ "buildkey="QT_BUILD_KEY"\0";
+
+# if defined (Q_OS_WIN32) && defined(Q_CC_BOR)
+# define Q_STANDARD_CALL __stdcall
+# else
+# define Q_STANDARD_CALL
+# endif
+
+# define Q_EXPORT_PLUGIN2(PLUGIN, PLUGINCLASS) \
+ Q_PLUGIN_VERIFICATION_DATA \
+ Q_EXTERN_C Q_DECL_EXPORT \
+ const char * Q_STANDARD_CALL qt_plugin_query_verification_data() \
+ { return qt_plugin_verification_data; } \
+ Q_EXTERN_C Q_DECL_EXPORT QT_PREPEND_NAMESPACE(QObject) * Q_STANDARD_CALL qt_plugin_instance() \
+ Q_PLUGIN_INSTANCE(PLUGINCLASS)
+
+# define Q_EXPORT_STATIC_PLUGIN2(PLUGIN, PLUGINCLASS)
+
+#endif
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // Q_PLUGIN_H
diff --git a/src/corelib/plugin/qpluginloader.cpp b/src/corelib/plugin/qpluginloader.cpp
new file mode 100644
index 0000000000..15ebe3d792
--- /dev/null
+++ b/src/corelib/plugin/qpluginloader.cpp
@@ -0,0 +1,371 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qplatformdefs.h"
+
+#include "qplugin.h"
+#include "qpluginloader.h"
+#include <qfileinfo.h>
+#include "qlibrary_p.h"
+#include "qdebug.h"
+
+#ifndef QT_NO_LIBRARY
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QPluginLoader
+ \reentrant
+ \brief The QPluginLoader class loads a plugin at run-time.
+
+ \mainclass
+ \ingroup plugins
+
+ QPluginLoader provides access to a \l{How to Create Qt
+ Plugins}{Qt plugin}. A Qt plugin is stored in a shared library (a
+ DLL) and offers these benefits over shared libraries accessed
+ using QLibrary:
+
+ \list
+ \o QPluginLoader checks that a plugin is linked against the same
+ version of Qt as the application.
+ \o QPluginLoader provides direct access to a root component object
+ (instance()), instead of forcing you to resolve a C function manually.
+ \endlist
+
+ An instance of a QPluginLoader object operates on a single shared
+ library file, which we call a plugin. It provides access to the
+ functionality in the plugin in a platform-independent way. To
+ specify which plugin to load, either pass a file name in
+ the constructor or set it with setFileName().
+
+ The most important functions are load() to dynamically load the
+ plugin file, isLoaded() to check whether loading was successful,
+ and instance() to access the root component in the plugin. The
+ instance() function implicitly tries to load the plugin if it has
+ not been loaded yet. Multiple instances of QPluginLoader can be
+ used to access the same physical plugin.
+
+ Once loaded, plugins remain in memory until all instances of
+ QPluginLoader has been unloaded, or until the application
+ terminates. You can attempt to unload a plugin using unload(),
+ but if other instances of QPluginLoader are using the same
+ library, the call will fail, and unloading will only happen when
+ every instance has called unload(). Right before the unloading
+ happen, the root component will also be deleted.
+
+ In order to speed up loading and validation of plugins, some of
+ the information that is collected during loading is cached in
+ persistent memory (through QSettings). For instance, the result
+ of a load operation (e.g. succeeded or failed) is stored in the
+ cache, so that subsequent load operations don't try to load an
+ invalid plugin. However, if the "last modified" timestamp of
+ a plugin has changed, the plugin's cache entry is invalidated
+ and the plugin is reloaded regardless of the values in the cache
+ entry. The cache entry is then updated with the new result of the
+ load operation.
+
+ This also means that the timestamp must be updated each time the
+ plugin or any dependent resources (such as a shared library) is
+ updated, since the dependent resources might influence the result
+ of loading a plugin.
+
+ See \l{How to Create Qt Plugins} for more information about
+ how to make your application extensible through plugins.
+
+ Note that the QPluginLoader cannot be used if your application is
+ statically linked against Qt. In this case, you will also have to
+ link to plugins statically. You can use QLibrary if you need to
+ load dynamic libraries in a statically linked application.
+
+ \sa QLibrary, {Plug & Paint Example}
+*/
+
+/*!
+ Constructs a plugin loader with the given \a parent.
+*/
+QPluginLoader::QPluginLoader(QObject *parent)
+ : QObject(parent), d(0), did_load(false)
+{
+}
+
+/*!
+ Constructs a plugin loader with the given \a parent that will
+ load the plugin specified by \a fileName.
+
+ To be loadable, the file's suffix must be a valid suffix for a
+ loadable library in accordance with the platform, e.g. \c .so on
+ Unix, - \c .dylib on Mac OS X, and \c .dll on Windows. The suffix
+ can be verified with QLibrary::isLibrary().
+
+ \sa setFileName()
+*/
+QPluginLoader::QPluginLoader(const QString &fileName, QObject *parent)
+ : QObject(parent), d(0), did_load(false)
+{
+ setFileName(fileName);
+}
+
+/*!
+ Destroys the QPluginLoader object.
+
+ Unless unload() was called explicitly, the plugin stays in memory
+ until the application terminates.
+
+ \sa isLoaded(), unload()
+*/
+QPluginLoader::~QPluginLoader()
+{
+ if (d)
+ d->release();
+}
+
+/*!
+ Returns the root component object of the plugin. The plugin is
+ loaded if necessary. The function returns 0 if the plugin could
+ not be loaded or if the root component object could not be
+ instantiated.
+
+ If the root component object was destroyed, calling this function
+ creates a new instance.
+
+ The root component, returned by this function, is not deleted when
+ the QPluginLoader is destroyed. If you want to ensure that the root
+ component is deleted, you should call unload() as soon you don't
+ need to access the core component anymore. When the library is
+ finally unloaded, the root component will automatically be deleted.
+
+ The component object is a QObject. Use qobject_cast() to access
+ interfaces you are interested in.
+
+ \sa load()
+*/
+QObject *QPluginLoader::instance()
+{
+ if (!load())
+ return 0;
+ if (d->instance)
+ return d->instance();
+ return 0;
+}
+
+/*!
+ Loads the plugin and returns true if the plugin was loaded
+ successfully; otherwise returns false. Since instance() always
+ calls this function before resolving any symbols it is not
+ necessary to call it explicitly. In some situations you might want
+ the plugin loaded in advance, in which case you would use this
+ function.
+
+ \sa unload()
+*/
+bool QPluginLoader::load()
+{
+ if (!d || d->fileName.isEmpty())
+ return false;
+ if (did_load)
+ return d->pHnd && d->instance;
+ if (!d->isPlugin())
+ return false;
+ did_load = true;
+ return d->loadPlugin();
+}
+
+
+/*!
+ Unloads the plugin and returns true if the plugin could be
+ unloaded; otherwise returns false.
+
+ This happens automatically on application termination, so you
+ shouldn't normally need to call this function.
+
+ If other instances of QPluginLoader are using the same plugin, the
+ call will fail, and unloading will only happen when every instance
+ has called unload().
+
+ Don't try to delete the root component. Instead rely on
+ that unload() will automatically delete it when needed.
+
+ \sa instance(), load()
+*/
+bool QPluginLoader::unload()
+{
+ if (did_load) {
+ did_load = false;
+ return d->unload();
+ }
+ if (d) // Ouch
+ d->errorString = tr("The plugin was not loaded.");
+ return false;
+}
+
+/*!
+ Returns true if the plugin is loaded; otherwise returns false.
+
+ \sa load()
+ */
+bool QPluginLoader::isLoaded() const
+{
+ return d && d->pHnd && d->instance;
+}
+
+/*!
+ \property QPluginLoader::fileName
+ \brief the file name of the plugin
+
+ To be loadable, the file's suffix must be a valid suffix for a
+ loadable library in accordance with the platform, e.g. \c .so on
+ Unix, \c .dylib on Mac OS X, and \c .dll on Windows. The suffix
+ can be verified with QLibrary::isLibrary().
+
+ If the file name does not exist, it will not be set. This property
+ will then contain an empty string.
+
+ By default, this property contains an empty string.
+
+ \sa load()
+*/
+void QPluginLoader::setFileName(const QString &fileName)
+{
+#if defined(QT_SHARED)
+ QLibrary::LoadHints lh;
+ if (d) {
+ lh = d->loadHints;
+ d->release();
+ d = 0;
+ did_load = false;
+ }
+ QString fn = QFileInfo(fileName).canonicalFilePath();
+ d = QLibraryPrivate::findOrCreate(fn);
+ d->loadHints = lh;
+ if (fn.isEmpty())
+ d->errorString = QLibrary::tr("The shared library was not found.");
+#else
+ if (qt_debug_component()) {
+ qWarning("Cannot load %s into a statically linked Qt library.",
+ (const char*)QFile::encodeName(fileName));
+ }
+ Q_UNUSED(fileName);
+#endif
+}
+
+QString QPluginLoader::fileName() const
+{
+ if (d)
+ return d->fileName;
+ return QString();
+}
+
+/*!
+ \since 4.2
+
+ Returns a text string with the description of the last error that occurred.
+*/
+QString QPluginLoader::errorString() const
+{
+ return (!d || d->errorString.isEmpty()) ? tr("Unknown error") : d->errorString;
+}
+
+typedef QList<QtPluginInstanceFunction> StaticInstanceFunctionList;
+Q_GLOBAL_STATIC(StaticInstanceFunctionList, staticInstanceFunctionList)
+
+/*! \since 4.4
+
+ \property QPluginLoader::loadHints
+ \brief Give the load() function some hints on how it should behave.
+
+ You can give hints on how the symbols in the plugin are
+ resolved. By default, none of the hints are set.
+
+ See the documentation of QLibrary::loadHints for a complete
+ description of how this property works.
+
+ \sa QLibrary::loadHints
+*/
+
+void QPluginLoader::setLoadHints(QLibrary::LoadHints loadHints)
+{
+ if (!d) {
+ d = QLibraryPrivate::findOrCreate(QString()); // ugly, but we need a d-ptr
+ d->errorString.clear();
+ }
+ d->loadHints = loadHints;
+}
+
+QLibrary::LoadHints QPluginLoader::loadHints() const
+{
+ if (!d) {
+ QPluginLoader *that = const_cast<QPluginLoader *>(this);
+ that->d = QLibraryPrivate::findOrCreate(QString()); // ugly, but we need a d-ptr
+ that->d->errorString.clear();
+ }
+ return d->loadHints;
+}
+
+/*!
+ \relates QPluginLoader
+ \since 4.4
+
+ Registers the given \a function with the plugin loader.
+*/
+void Q_CORE_EXPORT qRegisterStaticPluginInstanceFunction(QtPluginInstanceFunction function)
+{
+ staticInstanceFunctionList()->append(function);
+}
+
+/*!
+ Returns a list of static plugin instances (root components) held
+ by the plugin loader.
+*/
+QObjectList QPluginLoader::staticInstances()
+{
+ QObjectList instances;
+ StaticInstanceFunctionList *functions = staticInstanceFunctionList();
+ if (functions) {
+ for (int i = 0; i < functions->count(); ++i)
+ instances.append((*functions)[i]());
+ }
+ return instances;
+}
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_LIBRARY
diff --git a/src/corelib/plugin/qpluginloader.h b/src/corelib/plugin/qpluginloader.h
new file mode 100644
index 0000000000..7b8b9ed6e0
--- /dev/null
+++ b/src/corelib/plugin/qpluginloader.h
@@ -0,0 +1,100 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QPLUGINLOADER_H
+#define QPLUGINLOADER_H
+
+#include <QtCore/qlibrary.h>
+
+#if defined(QT_NO_LIBRARY) && defined(Q_OS_WIN)
+#undef QT_NO_LIBRARY
+#pragma message("QT_NO_LIBRARY is not supported on Windows")
+#endif
+
+#ifndef QT_NO_LIBRARY
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+class QLibraryPrivate;
+
+class Q_CORE_EXPORT QPluginLoader : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(QString fileName READ fileName WRITE setFileName)
+ Q_PROPERTY(QLibrary::LoadHints loadHints READ loadHints WRITE setLoadHints)
+public:
+ explicit QPluginLoader(QObject *parent = 0);
+ explicit QPluginLoader(const QString &fileName, QObject *parent = 0);
+ ~QPluginLoader();
+
+ QObject *instance();
+
+ static QObjectList staticInstances();
+
+ bool load();
+ bool unload();
+ bool isLoaded() const;
+
+ void setFileName(const QString &fileName);
+ QString fileName() const;
+
+ QString errorString() const;
+
+ void setLoadHints(QLibrary::LoadHints loadHints);
+ QLibrary::LoadHints loadHints() const;
+
+private:
+ QLibraryPrivate *d;
+ bool did_load;
+ Q_DISABLE_COPY(QPluginLoader)
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QT_NO_LIBRARY
+
+#endif //QPLUGINLOADER_H
diff --git a/src/corelib/plugin/quuid.cpp b/src/corelib/plugin/quuid.cpp
new file mode 100644
index 0000000000..3e05d28834
--- /dev/null
+++ b/src/corelib/plugin/quuid.cpp
@@ -0,0 +1,624 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "quuid.h"
+
+#include "qdatastream.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QUuid
+ \brief The QUuid class stores a Universally Unique Identifier (UUID).
+
+ \reentrant
+ \ingroup misc
+
+ Using \e{U}niversally \e{U}nique \e{ID}entifiers (UUID) is a
+ standard way to uniquely identify entities in a distributed
+ computing environment. A UUID is a 16-byte (128-bit) number
+ generated by some algorithm that is meant to guarantee that the
+ UUID will be unique in the distributed computing environment where
+ it is used. The acronym GUID is often used instead, \e{G}lobally
+ \e{U}nique \e{ID}entifiers, but it refers to the same thing.
+
+ \target Variant field
+ Actually, the GUID is one \e{variant} of UUID. Multiple variants
+ are in use. Each UUID contains a bit field that specifies which
+ type (variant) of UUID it is. Call variant() to discover which
+ type of UUID an instance of QUuid contains. It extracts the three
+ most signifcant bits of byte 8 of the 16 bytes. In QUuid, byte 8
+ is \c{QUuid::data4[0]}. If you create instances of QUuid using the
+ constructor that accepts all the numeric values as parameters, use
+ the following table to set the three most significant bits of
+ parameter \c{b1}, which becomes \c{QUuid::data4[0]} and contains
+ the variant field in its three most significant bits. In the
+ table, 'x' means \e {don't care}.
+
+ \table
+ \header
+ \o msb0
+ \o msb1
+ \o msb2
+ \o Variant
+
+ \row
+ \o 0
+ \o x
+ \o x
+ \o NCS (Network Computing System)
+
+ \row
+ \o 1
+ \o 0
+ \o x
+ \o DCE (Distributed Computing Environment)
+
+ \row
+ \o 1
+ \o 1
+ \o 0
+ \o Microsoft (GUID)
+
+ \row
+ \o 1
+ \o 1
+ \o 1
+ \o Reserved for future expansion
+
+ \endtable
+
+ \target Version field
+ If variant() returns QUuid::DCE, the UUID also contains a
+ \e{version} field in the four most significant bits of
+ \c{QUuid::data3}, and you can call version() to discover which
+ version your QUuid contains. If you create instances of QUuid
+ using the constructor that accepts all the numeric values as
+ parameters, use the following table to set the four most
+ significant bits of parameter \c{w2}, which becomes
+ \c{QUuid::data3} and contains the version field in its four most
+ significant bits.
+
+ \table
+ \header
+ \o msb0
+ \o msb1
+ \o msb2
+ \o msb3
+ \o Version
+
+ \row
+ \o 0
+ \o 0
+ \o 0
+ \o 1
+ \o Time
+
+ \row
+ \o 0
+ \o 0
+ \o 1
+ \o 0
+ \o Embedded POSIX
+
+ \row
+ \o 0
+ \o 0
+ \o 1
+ \o 1
+ \o Name
+
+ \row
+ \o 0
+ \o 1
+ \o 0
+ \o 0
+ \o Random
+
+ \endtable
+
+ The field layouts for the DCE versions listed in the table above
+ are specified in the \l{http://www.ietf.org/rfc/rfc4122.txt}
+ {Network Working Group UUID Specification}.
+
+ Most platforms provide a tool for generating new UUIDs, e.g. \c
+ uuidgen and \c guidgen. You can also use createUuid(). UUIDs
+ generated by createUuid() are of the random type. Their
+ QUuid::Version bits are set to QUuid::Random, and their
+ QUuid::Variant bits are set to QUuid::DCE. The rest of the UUID is
+ composed of random numbers. Theoretically, this means there is a
+ small chance that a UUID generated by createUuid() will not be
+ unique. But it is
+ \l{http://en.wikipedia.org/wiki/Universally_Unique_Identifier#Random_UUID_probability_of_duplicates}
+ {a \e{very} small chance}.
+
+ UUIDs can be constructed from numeric values or from strings, or
+ using the static createUuid() function. They can be converted to a
+ string with toString(). UUIDs have a variant() and a version(),
+ and null UUIDs return true from isNull().
+*/
+
+/*!
+ \fn QUuid::QUuid(const GUID &guid)
+
+ Casts a Windows \a guid to a Qt QUuid.
+
+ \warning This function is only for Windows platforms.
+*/
+
+/*!
+ \fn QUuid &QUuid::operator=(const GUID &guid)
+
+ Assigns a Windows \a guid to a Qt QUuid.
+
+ \warning This function is only for Windows platforms.
+*/
+
+/*!
+ \fn QUuid::operator GUID() const
+
+ Returns a Windows GUID from a QUuid.
+
+ \warning This function is only for Windows platforms.
+*/
+
+/*!
+ \fn QUuid::QUuid()
+
+ Creates the null UUID. toString() will output the null UUID
+ as "{00000000-0000-0000-0000-000000000000}".
+*/
+
+/*!
+ \fn QUuid::QUuid(uint l, ushort w1, ushort w2, uchar b1, uchar b2, uchar b3, uchar b4, uchar b5, uchar b6, uchar b7, uchar b8)
+
+ Creates a UUID with the value specified by the parameters, \a l,
+ \a w1, \a w2, \a b1, \a b2, \a b3, \a b4, \a b5, \a b6, \a b7, \a
+ b8.
+
+ Example:
+ \snippet doc/src/snippets/code/src_corelib_plugin_quuid.cpp 0
+*/
+
+#ifndef QT_NO_QUUID_STRING
+/*!
+ Creates a QUuid object from the string \a text, which must be
+ formatted as five hex fields separated by '-', e.g.,
+ "{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}" where 'x' is a hex
+ digit. The curly braces shown here are optional, but it is normal to
+ include them. If the conversion fails, a null UUID is created. See
+ toString() for an explanation of how the five hex fields map to the
+ public data members in QUuid.
+
+ \sa toString(), QUuid()
+*/
+QUuid::QUuid(const QString &text)
+{
+ bool ok;
+ if (text.isEmpty()) {
+ *this = QUuid();
+ return;
+ }
+ QString temp = text.toUpper();
+ if (temp[0] != QLatin1Char('{'))
+ temp = QLatin1Char('{') + text;
+ if (text[(int)text.length()-1] != QLatin1Char('}'))
+ temp += QLatin1Char('}');
+
+ data1 = temp.mid(1, 8).toULongLong(&ok, 16);
+ if (!ok) {
+ *this = QUuid();
+ return;
+ }
+
+ data2 = temp.mid(10, 4).toUInt(&ok, 16);
+ if (!ok) {
+ *this = QUuid();
+ return;
+ }
+ data3 = temp.mid(15, 4).toUInt(&ok, 16);
+ if (!ok) {
+ *this = QUuid();
+ return;
+ }
+ data4[0] = temp.mid(20, 2).toUInt(&ok, 16);
+ if (!ok) {
+ *this = QUuid();
+ return;
+ }
+ data4[1] = temp.mid(22, 2).toUInt(&ok, 16);
+ if (!ok) {
+ *this = QUuid();
+ return;
+ }
+ for (int i = 2; i<8; i++) {
+ data4[i] = temp.mid(25 + (i-2)*2, 2).toUShort(&ok, 16);
+ if (!ok) {
+ *this = QUuid();
+ return;
+ }
+ }
+}
+
+/*!
+ \internal
+*/
+QUuid::QUuid(const char *text)
+{
+ *this = QUuid(QString::fromLatin1(text));
+}
+#endif
+
+/*!
+ \fn bool QUuid::operator==(const QUuid &other) const
+
+ Returns true if this QUuid and the \a other QUuid are identical;
+ otherwise returns false.
+*/
+
+/*!
+ \fn bool QUuid::operator!=(const QUuid &other) const
+
+ Returns true if this QUuid and the \a other QUuid are different;
+ otherwise returns false.
+*/
+#ifndef QT_NO_QUUID_STRING
+/*!
+ \fn QUuid::operator QString() const
+
+ Returns the string representation of the uuid.
+
+ \sa toString()
+*/
+
+static QString uuidhex(uint data, int digits)
+{
+ return QString::number(data, 16).rightJustified(digits, QLatin1Char('0'));
+}
+
+/*!
+ Returns the string representation of this QUuid. The string is
+ formatted as five hex fields separated by '-' and enclosed in
+ curly braces, i.e., "{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}" where
+ 'x' is a hex digit. From left to right, the five hex fields are
+ obtained from the four public data members in QUuid as follows:
+
+ \table
+ \header
+ \o Field #
+ \o Source
+
+ \row
+ \o 1
+ \o data1
+
+ \row
+ \o 2
+ \o data2
+
+ \row
+ \o 3
+ \o data3
+
+ \row
+ \o 4
+ \o data4[0] .. data4[1]
+
+ \row
+ \o 5
+ \o data4[2] .. data4[7]
+
+ \endtable
+*/
+QString QUuid::toString() const
+{
+ QString result;
+
+ QChar dash = QLatin1Char('-');
+ result = QLatin1Char('{') + uuidhex(data1,8);
+ result += dash;
+ result += uuidhex(data2,4);
+ result += dash;
+ result += uuidhex(data3,4);
+ result += dash;
+ result += uuidhex(data4[0],2);
+ result += uuidhex(data4[1],2);
+ result += dash;
+ for (int i = 2; i < 8; i++)
+ result += uuidhex(data4[i],2);
+
+ return result + QLatin1Char('}');
+}
+#endif
+
+#ifndef QT_NO_DATASTREAM
+/*!
+ \relates QUuid
+ Writes the UUID \a id to the data stream \a s.
+*/
+QDataStream &operator<<(QDataStream &s, const QUuid &id)
+{
+ s << (quint32)id.data1;
+ s << (quint16)id.data2;
+ s << (quint16)id.data3;
+ for (int i = 0; i < 8; i++)
+ s << (quint8)id.data4[i];
+ return s;
+}
+
+/*!
+ \relates QUuid
+ Reads a UUID from the stream \a s into \a id.
+*/
+QDataStream &operator>>(QDataStream &s, QUuid &id)
+{
+ quint32 u32;
+ quint16 u16;
+ quint8 u8;
+ s >> u32;
+ id.data1 = u32;
+ s >> u16;
+ id.data2 = u16;
+ s >> u16;
+ id.data3 = u16;
+ for (int i = 0; i < 8; i++) {
+ s >> u8;
+ id.data4[i] = u8;
+ }
+ return s;
+}
+#endif
+
+/*!
+ Returns true if this is the null UUID
+ {00000000-0000-0000-0000-000000000000}; otherwise returns false.
+*/
+bool QUuid::isNull() const
+{
+ return data4[0] == 0 && data4[1] == 0 && data4[2] == 0 && data4[3] == 0 &&
+ data4[4] == 0 && data4[5] == 0 && data4[6] == 0 && data4[7] == 0 &&
+ data1 == 0 && data2 == 0 && data3 == 0;
+}
+
+/*!
+ \enum QUuid::Variant
+
+ This enum defines the values used in the \l{Variant field}
+ {variant field} of the UUID. The value in the variant field
+ determines the layout of the 128-bit value.
+
+ \value VarUnknown Variant is unknown
+ \value NCS Reserved for NCS (Network Computing System) backward compatibility
+ \value DCE Distributed Computing Environment, the scheme used by QUuid
+ \value Microsoft Reserved for Microsoft backward compatibility (GUID)
+ \value Reserved Reserved for future definition
+*/
+
+/*!
+ \enum QUuid::Version
+
+ This enum defines the values used in the \l{Version field}
+ {version field} of the UUID. The version field is meaningful
+ only if the value in the \l{Variant field} {variant field}
+ is QUuid::DCE.
+
+ \value VerUnknown Version is unknown
+ \value Time Time-based, by using timestamp, clock sequence, and
+ MAC network card address (if available) for the node sections
+ \value EmbeddedPOSIX DCE Security version, with embedded POSIX UUIDs
+ \value Name Name-based, by using values from a name for all sections
+ \value Random Random-based, by using random numbers for all sections
+*/
+
+/*!
+ \fn QUuid::Variant QUuid::variant() const
+
+ Returns the value in the \l{Variant field} {variant field} of the
+ UUID. If the return value is QUuid::DCE, call version() to see
+ which layout it uses. The null UUID is considered to be of an
+ unknown variant.
+
+ \sa version()
+*/
+QUuid::Variant QUuid::variant() const
+{
+ if (isNull())
+ return VarUnknown;
+ // Check the 3 MSB of data4[0]
+ if ((data4[0] & 0x80) == 0x00) return NCS;
+ else if ((data4[0] & 0xC0) == 0x80) return DCE;
+ else if ((data4[0] & 0xE0) == 0xC0) return Microsoft;
+ else if ((data4[0] & 0xE0) == 0xE0) return Reserved;
+ return VarUnknown;
+}
+
+/*!
+ \fn QUuid::Version QUuid::version() const
+
+ Returns the \l{Version field} {version field} of the UUID, if the
+ UUID's \l{Variant field} {variant field} is QUuid::DCE. Otherwise
+ it returns QUuid::VerUnknown.
+
+ \sa variant()
+*/
+QUuid::Version QUuid::version() const
+{
+ // Check the 4 MSB of data3
+ Version ver = (Version)(data3>>12);
+ if (isNull()
+ || (variant() != DCE)
+ || ver < Time
+ || ver > Random)
+ return VerUnknown;
+ return ver;
+}
+
+/*!
+ \fn bool QUuid::operator<(const QUuid &other) const
+
+ Returns true if this QUuid has the same \l{Variant field}
+ {variant field} as the \a other QUuid and is lexicographically
+ \e{before} the \a other QUuid. If the \a other QUuid has a
+ different variant field, the return value is determined by
+ comparing the two \l{QUuid::Variant} {variants}.
+
+ \sa variant()
+*/
+#define ISLESS(f1, f2) if (f1!=f2) return (f1<f2);
+bool QUuid::operator<(const QUuid &other) const
+{
+ if (variant() != other.variant())
+ return variant() < other.variant();
+
+ ISLESS(data1, other.data1);
+ ISLESS(data2, other.data2);
+ ISLESS(data3, other.data3);
+ for (int n = 0; n < 8; n++) {
+ ISLESS(data4[n], other.data4[n]);
+ }
+ return false;
+}
+
+/*!
+ \fn bool QUuid::operator>(const QUuid &other) const
+
+ Returns true if this QUuid has the same \l{Variant field}
+ {variant field} as the \a other QUuid and is lexicographically
+ \e{after} the \a other QUuid. If the \a other QUuid has a
+ different variant field, the return value is determined by
+ comparing the two \l{QUuid::Variant} {variants}.
+
+ \sa variant()
+*/
+#define ISMORE(f1, f2) if (f1!=f2) return (f1>f2);
+bool QUuid::operator>(const QUuid &other) const
+{
+ if (variant() != other.variant())
+ return variant() > other.variant();
+
+ ISMORE(data1, other.data1);
+ ISMORE(data2, other.data2);
+ ISMORE(data3, other.data3);
+ for (int n = 0; n < 8; n++) {
+ ISMORE(data4[n], other.data4[n]);
+ }
+ return false;
+}
+
+/*!
+ \fn QUuid QUuid::createUuid()
+
+ On any platform other than Windows, this function returns a new
+ UUID with variant QUuid::DCE and version QUuid::Random. The random
+ numbers used to construct the UUID are obtained from the local
+ pseudo-random generator, which is usually not a cryptographic
+ quality random number generator. Therefore, a UUID generated by
+ this function can't be guaranteed to be unique.
+
+ On a Windows platform, a GUID is generated, which almost certainly
+ \e{will} be unique, on this or any other system, networked or not.
+
+ \sa variant(), version()
+*/
+#if defined(Q_OS_WIN32)
+
+QT_BEGIN_INCLUDE_NAMESPACE
+#include <objbase.h> // For CoCreateGuid
+QT_END_INCLUDE_NAMESPACE
+
+QUuid QUuid::createUuid()
+{
+ GUID guid;
+ CoCreateGuid(&guid);
+ QUuid result = guid;
+ return result;
+}
+
+#else // !Q_OS_WIN32
+
+QT_BEGIN_INCLUDE_NAMESPACE
+#include "qdatetime.h"
+#include "stdlib.h" // For srand/rand
+QT_END_INCLUDE_NAMESPACE
+
+QUuid QUuid::createUuid()
+{
+ static const int intbits = sizeof(int)*8;
+ static int randbits = 0;
+ if (!randbits) {
+ int max = RAND_MAX;
+ do { ++randbits; } while ((max=max>>1));
+ qsrand((uint)QDateTime::currentDateTime().toTime_t());
+ qrand(); // Skip first
+ }
+
+ QUuid result;
+ uint *data = &(result.data1);
+ int chunks = 16 / sizeof(uint);
+ while (chunks--) {
+ uint randNumber = 0;
+ for (int filled = 0; filled < intbits; filled += randbits)
+ randNumber |= qrand()<<filled;
+ *(data+chunks) = randNumber;
+ }
+
+ result.data4[0] = (result.data4[0] & 0x3F) | 0x80; // UV_DCE
+ result.data3 = (result.data3 & 0x0FFF) | 0x4000; // UV_Random
+
+ return result;
+}
+#endif // !Q_OS_WIN32
+
+/*!
+ \fn bool QUuid::operator==(const GUID &guid) const
+
+ Returns true if this UUID is equal to the Windows GUID \a guid;
+ otherwise returns false.
+*/
+
+/*!
+ \fn bool QUuid::operator!=(const GUID &guid) const
+
+ Returns true if this UUID is not equal to the Windows GUID \a
+ guid; otherwise returns false.
+*/
+
+QT_END_NAMESPACE
diff --git a/src/corelib/plugin/quuid.h b/src/corelib/plugin/quuid.h
new file mode 100644
index 0000000000..95716d46a8
--- /dev/null
+++ b/src/corelib/plugin/quuid.h
@@ -0,0 +1,190 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QUUID_H
+#define QUUID_H
+
+#include <QtCore/qstring.h>
+
+QT_BEGIN_HEADER
+
+#if defined(Q_OS_WIN)
+#ifndef GUID_DEFINED
+#define GUID_DEFINED
+typedef struct _GUID
+{
+ ulong Data1;
+ ushort Data2;
+ ushort Data3;
+ uchar Data4[8];
+} GUID, *REFGUID, *LPGUID;
+#endif
+#endif
+
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+struct Q_CORE_EXPORT QUuid
+{
+ enum Variant {
+ VarUnknown =-1,
+ NCS = 0, // 0 - -
+ DCE = 2, // 1 0 -
+ Microsoft = 6, // 1 1 0
+ Reserved = 7 // 1 1 1
+ };
+
+ enum Version {
+ VerUnknown =-1,
+ Time = 1, // 0 0 0 1
+ EmbeddedPOSIX = 2, // 0 0 1 0
+ Name = 3, // 0 0 1 1
+ Random = 4 // 0 1 0 0
+ };
+
+ QUuid()
+ {
+ data1 = 0;
+ data2 = 0;
+ data3 = 0;
+ for(int i = 0; i < 8; i++)
+ data4[i] = 0;
+ }
+ QUuid(uint l, ushort w1, ushort w2, uchar b1, uchar b2, uchar b3, uchar b4, uchar b5, uchar b6, uchar b7, uchar b8)
+ {
+ data1 = l;
+ data2 = w1;
+ data3 = w2;
+ data4[0] = b1;
+ data4[1] = b2;
+ data4[2] = b3;
+ data4[3] = b4;
+ data4[4] = b5;
+ data4[5] = b6;
+ data4[6] = b7;
+ data4[7] = b8;
+ }
+#ifndef QT_NO_QUUID_STRING
+ QUuid(const QString &);
+ QUuid(const char *);
+ QString toString() const;
+ operator QString() const { return toString(); }
+#endif
+ bool isNull() const;
+
+ bool operator==(const QUuid &orig) const
+ {
+ uint i;
+ if (data1 != orig.data1 || data2 != orig.data2 ||
+ data3 != orig.data3)
+ return false;
+
+ for(i = 0; i < 8; i++)
+ if (data4[i] != orig.data4[i])
+ return false;
+
+ return true;
+ }
+
+ bool operator!=(const QUuid &orig) const
+ {
+ return !(*this == orig);
+ }
+
+ bool operator<(const QUuid &other) const;
+ bool operator>(const QUuid &other) const;
+
+#if defined(Q_OS_WIN)
+ // On Windows we have a type GUID that is used by the platform API, so we
+ // provide convenience operators to cast from and to this type.
+ QUuid(const GUID &guid)
+ {
+ data1 = guid.Data1;
+ data2 = guid.Data2;
+ data3 = guid.Data3;
+ for(int i = 0; i < 8; i++)
+ data4[i] = guid.Data4[i];
+ }
+
+ QUuid &operator=(const GUID &guid)
+ {
+ *this = QUuid(guid);
+ return *this;
+ }
+
+ operator GUID() const
+ {
+ GUID guid = { data1, data2, data3, { data4[0], data4[1], data4[2], data4[3], data4[4], data4[5], data4[6], data4[7] } };
+ return guid;
+ }
+
+ bool operator==(const GUID &guid) const
+ {
+ return *this == QUuid(guid);
+ }
+
+ bool operator!=(const GUID &guid) const
+ {
+ return !(*this == guid);
+ }
+#endif
+ static QUuid createUuid();
+ QUuid::Variant variant() const;
+ QUuid::Version version() const;
+
+ uint data1;
+ ushort data2;
+ ushort data3;
+ uchar data4[8];
+};
+
+#ifndef QT_NO_DATASTREAM
+Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, const QUuid &);
+Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QUuid &);
+#endif
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QUUID_H