// Copyright (C) 2016 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0 WITH Qt-GPL-exception-1.0 #include "iconrenderer/iconrenderer.h" #include "import3d/import3d.h" #include #ifdef MULTILANGUAGE_TRANSLATIONPROVIDER #include #endif #include #include #include #include #include #include #include #include #include #ifdef ENABLE_QT_BREAKPAD #include #endif #if defined(ENABLE_CRASHPAD) && defined(Q_OS_WIN) #define NOMINMAX #include "client/crashpad_client.h" #include "client/crash_report_database.h" #include "client/settings.h" #endif #ifdef Q_OS_WIN #include #endif namespace { #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) void myMessageOutput(QtMsgType type, const QMessageLogContext &context, const QString &msg) { QByteArray localMsg = msg.toLocal8Bit(); switch (type) { case QtDebugMsg: fprintf(stderr, "Debug: %s (%s:%u, %s)\n", localMsg.constData(), context.file, context.line, context.function); break; case QtInfoMsg: fprintf(stderr, "Info: %s (%s:%u, %s)\n", localMsg.constData(), context.file, context.line, context.function); break; case QtWarningMsg: fprintf(stderr, "Warning: %s (%s:%u, %s)\n", localMsg.constData(), context.file, context.line, context.function); break; case QtCriticalMsg: fprintf(stderr, "Critical: %s (%s:%u, %s)\n", localMsg.constData(), context.file, context.line, context.function); break; case QtFatalMsg: fprintf(stderr, "Fatal: %s (%s:%u, %s)\n", localMsg.constData(), context.file, context.line, context.function); abort(); } } #endif #if defined(ENABLE_CRASHPAD) && defined(Q_OS_WIN) bool startCrashpad() { using namespace crashpad; // Cache directory that will store crashpad information and minidumps base::FilePath database(L"crashpad_reports"); base::FilePath handler(L"crashpad_handler.exe"); // URL used to submit minidumps to std::string url(CRASHPAD_BACKEND_URL); // Optional annotations passed via --annotations to the handler std::map annotations; annotations["qt-version"] = QT_VERSION_STR; // Optional arguments to pass to the handler std::vector arguments; arguments.push_back("--no-rate-limit"); CrashpadClient *client = new CrashpadClient(); bool success = client->StartHandler( handler, database, database, url, annotations, arguments, /* restartable */ true, /* asynchronous_start */ true ); // TODO: research using this method, should avoid creating a separate CrashpadClient for the // puppet (needed only on windows according to docs). // client->SetHandlerIPCPipe(L"\\\\.\\pipe\\qml2puppet"); return success; } #endif int internalMain(QGuiApplication *application) { QCoreApplication::setOrganizationName("QtProject"); QCoreApplication::setOrganizationDomain("qt-project.org"); QCoreApplication::setApplicationName("Qml2Puppet"); QCoreApplication::setApplicationVersion("1.0.0"); if (application->arguments().count() < 2 || (application->arguments().at(1) == "--readcapturedstream" && application->arguments().count() < 3) || (application->arguments().at(1) == "--rendericon" && application->arguments().count() < 5) || (application->arguments().at(1) == "--import3dAsset" && application->arguments().count() < 6)) { qDebug() << "Usage:\n"; qDebug() << "--test"; qDebug() << "--version"; qDebug() << "--readcapturedstream [control stream file]"; qDebug() << "--rendericon "; qDebug() << "--import3dAsset "; return -1; } if (application->arguments().at(1) == "--readcapturedstream" && application->arguments().count() > 2) { QFileInfo inputStreamFileInfo(application->arguments().at(2)); if (!inputStreamFileInfo.exists()) { qDebug() << "Input stream does not exist:" << inputStreamFileInfo.absoluteFilePath(); return -1; } if (application->arguments().count() > 3) { QFileInfo controlStreamFileInfo(application->arguments().at(3)); if (!controlStreamFileInfo.exists()) { qDebug() << "Output stream does not exist:" << controlStreamFileInfo.absoluteFilePath(); return -1; } } } if (application->arguments().count() == 2 && application->arguments().at(1) == "--test") { qDebug() << QCoreApplication::applicationVersion(); QQmlEngine engine; QQmlComponent component(&engine); component.setData("import QtQuick 2.0\nItem {\n}\n", QUrl::fromLocalFile("test.qml")); QObject *object = component.create(); if (object) { qDebug() << "Basic QtQuick 2.0 working..."; } else { qDebug() << "Basic QtQuick 2.0 not working..."; qDebug() << component.errorString(); } delete object; return 0; } if (application->arguments().count() == 2 && application->arguments().at(1) == "--version") { std::cout << 2; return 0; } if (application->arguments().at(1) != "--readcapturedstream" && application->arguments().count() < 4) { qDebug() << "Wrong argument count: " << application->arguments().count(); return -1; } if (application->arguments().at(1) == "--rendericon") { int size = application->arguments().at(2).toInt(); QString iconFileName = application->arguments().at(3); QString iconSource = application->arguments().at(4); IconRenderer *iconRenderer = new IconRenderer(size, iconFileName, iconSource); iconRenderer->setupRender(); return application->exec(); } if (application->arguments().at(1) == "--import3dAsset") { QString sourceAsset = application->arguments().at(2); QString outDir = application->arguments().at(3); QString options = application->arguments().at(4); Import3D::import3D(sourceAsset, outDir, options); return application->exec(); } #ifdef ENABLE_QT_BREAKPAD const QString libexecPath = QCoreApplication::applicationDirPath() + '/' + RELATIVE_LIBEXEC_PATH; QtSystemExceptionHandler systemExceptionHandler(libexecPath); #endif #if defined(ENABLE_CRASHPAD) && defined(Q_OS_WIN) /* startCrashpad(); */ #endif new QmlDesigner::Qt5NodeInstanceClientProxy(application); #if defined(Q_OS_WIN) && defined(QT_NO_DEBUG) SetErrorMode(SEM_NOGPFAULTERRORBOX); //We do not want to see any message boxes #endif if (application->arguments().at(1) == "--readcapturedstream") return 0; return application->exec(); } } // namespace int main(int argc, char *argv[]) { #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) qInstallMessageHandler(myMessageOutput); #endif // Since we always render text into an FBO, we need to globally disable // subpixel antialiasing and instead use gray. qputenv("QSG_DISTANCEFIELD_ANTIALIASING", "gray"); #ifdef Q_OS_MACOS qputenv("QT_MAC_DISABLE_FOREGROUND_APPLICATION_TRANSFORM", "true"); #endif //If a style different from Desktop is set we have to use QGuiApplication bool useGuiApplication = (!qEnvironmentVariableIsSet("QMLDESIGNER_FORCE_QAPPLICATION") || qgetenv("QMLDESIGNER_FORCE_QAPPLICATION") != "true") && qEnvironmentVariableIsSet("QT_QUICK_CONTROLS_STYLE") && qgetenv("QT_QUICK_CONTROLS_STYLE") != "Desktop"; #ifdef MULTILANGUAGE_TRANSLATIONPROVIDER Sqlite::LibraryInitializer::initialize(); #endif if (useGuiApplication) { QGuiApplication application(argc, argv); return internalMain(&application); } else { QApplication application(argc, argv); return internalMain(&application); } }