117 lines
3.8 KiB
C++
117 lines
3.8 KiB
C++
|
/*
|
||
|
SPDX-FileCopyrightText: 2020-2021 Fabian Vogt <fabian@ritter-vogt.de>
|
||
|
SPDX-License-Identifier: GPL-3.0-or-later
|
||
|
*/
|
||
|
|
||
|
#include <cstdio>
|
||
|
#include <cstdlib>
|
||
|
|
||
|
#include <dlfcn.h>
|
||
|
|
||
|
#include <QGuiApplication>
|
||
|
#include <QPluginLoader>
|
||
|
#include <QQmlExtensionPlugin>
|
||
|
#include <QDebug>
|
||
|
#include <QFileInfo>
|
||
|
#include <QQmlError>
|
||
|
|
||
|
#include <QtQml/private/qqmlmetatype_p.h>
|
||
|
#include <QtQml/private/qhashedstring_p.h>
|
||
|
|
||
|
/* Some of the overridden functions here are called before static initialization
|
||
|
* of this object is done, so use a function-local static variable instead, which
|
||
|
* is initialized on the first call. */
|
||
|
static QHash<QPair<QString,int>, int> &importDatabase()
|
||
|
{
|
||
|
static QHash<QPair<QString,int>, int> importDatabase;
|
||
|
return importDatabase;
|
||
|
}
|
||
|
|
||
|
/* Add the specific import to the database, keeping the highest minor version for
|
||
|
* each identifier + major version. */
|
||
|
static void foundImportVersion(const QString &import, int versionMajor, int versionMinor)
|
||
|
{
|
||
|
qDebug() << "Found" << import << versionMajor << versionMinor;
|
||
|
|
||
|
auto &moduleVersion = importDatabase()[{import, versionMajor}];
|
||
|
if(moduleVersion < versionMinor)
|
||
|
moduleVersion = versionMinor;
|
||
|
}
|
||
|
|
||
|
/* Catch calls to qmlRegisterModule, the information is not reachable any other way... */
|
||
|
void qmlRegisterModule(const char *uri, int versionMajor, int versionMinor)
|
||
|
{
|
||
|
// qDebug() << uri << versionMajor << versionMinor;
|
||
|
|
||
|
foundImportVersion(uri, versionMajor, versionMinor);
|
||
|
|
||
|
if(auto *a = dlsym(RTLD_NEXT, "_Z17qmlRegisterModulePKcii"))
|
||
|
{
|
||
|
auto c = (decltype(&qmlRegisterModule))a;
|
||
|
return c(uri, versionMajor, versionMinor);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
|
||
|
/* Catch calls to QQmlModuleRegistration and trigger registration immediately. */
|
||
|
void QQmlMetaType::qmlInsertModuleRegistration(const QString &uri, void (*registerFunction)())
|
||
|
{
|
||
|
registerFunction();
|
||
|
|
||
|
if(auto *a = dlsym(RTLD_NEXT, "_ZN12QQmlMetaType27qmlInsertModuleRegistrationERK7QStringPFvvE"))
|
||
|
{
|
||
|
auto c = (decltype(&QQmlMetaType::qmlInsertModuleRegistration))a;
|
||
|
return c(uri, registerFunction);
|
||
|
}
|
||
|
}
|
||
|
#else
|
||
|
/* Catch calls to QQmlModuleRegistration and trigger registration immediately. */
|
||
|
void QQmlMetaType::qmlInsertModuleRegistration(const QString &uri, int majorVersion,
|
||
|
void (*registerFunction)())
|
||
|
{
|
||
|
registerFunction();
|
||
|
|
||
|
if(auto *a = dlsym(RTLD_NEXT, "_ZN12QQmlMetaType27qmlInsertModuleRegistrationERK7QStringiPFvvE"))
|
||
|
{
|
||
|
auto c = (decltype(&QQmlMetaType::qmlInsertModuleRegistration))a;
|
||
|
return c(uri, majorVersion, registerFunction);
|
||
|
}
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
int main(int argc, char *argv[])
|
||
|
{
|
||
|
// Also used by qmlplugindump
|
||
|
setenv("QT_QPA_PLATFORM", "minimal", 0);
|
||
|
|
||
|
QGuiApplication app(argc, argv);
|
||
|
QPluginLoader loader(app.arguments().at(1));
|
||
|
auto *a = loader.instance();
|
||
|
if(!a)
|
||
|
{
|
||
|
qCritical() << loader.errorString();
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
QString typeNamespace = app.arguments().at(2);
|
||
|
QList<QQmlError> list;
|
||
|
/* Using this private call is more flexible (deals with various types of plugins)
|
||
|
* and also sets up more internal state like baseUrl, which is required by some. */
|
||
|
QQmlMetaType::registerPluginTypes(a, QFileInfo(app.arguments().at(1)).absolutePath(), app.arguments().at(2), typeNamespace, {}, &list);
|
||
|
|
||
|
// Iterate all known types and note their module identifier + version
|
||
|
for(auto type : QQmlMetaType::qmlAllTypes())
|
||
|
{
|
||
|
// qDebug() << type.module() << type.typeName() << type.majorVersion() << type.minorVersion();
|
||
|
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
|
||
|
foundImportVersion(type.module(), type.version().majorVersion(), type.version().minorVersion());
|
||
|
#else
|
||
|
foundImportVersion(type.module(), type.majorVersion(), type.minorVersion());
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
// Print the database in a parsable format
|
||
|
for(auto i = importDatabase().constBegin(); i != importDatabase().constEnd(); ++i)
|
||
|
printf("%s.%d %d\n", qPrintable(i.key().first), i.key().second, i.value());
|
||
|
}
|