QmlDesigner: Show error message on import log for failed 3D import

The import is done on puppet side, so we use a log file to pass the
error message.

Also changed how import process is matched to the import, so that
exit code is no longer needed for this purpose. Crashes are also
now reported as import errors.

Task-number: QDS-6402
Change-Id: Ie14cd1df0bbba965d8e5f2aa7302a955e944379b
Reviewed-by: Samuel Ghinet <samuel.ghinet@qt.io>
Reviewed-by: Mahmoud Badri <mahmoud.badri@qt.io>
Reviewed-by: <github-actions-qt-creator@cristianadam.eu>
This commit is contained in:
Miikka Heikkinen
2022-03-10 15:11:33 +02:00
parent 38cdbd2bcd
commit 8b27281354
5 changed files with 61 additions and 33 deletions

View File

@@ -29,18 +29,21 @@
#include <QtQuick3DAssetImport/private/qssgassetimportmanager_p.h>
#endif
#include <QCoreApplication>
#include <QDebug>
#include <QFile>
#include <QJsonDocument>
#include <QJsonObject>
#include <QCoreApplication>
#include <QTimer>
#include <QScopedPointer>
#include <QDebug>
#include <QTextStream>
#include <QTimer>
namespace Import3D
{
void import3D(const QString &sourceAsset, const QString &outDir, int exitId, const QString &options)
void import3D(const QString &sourceAsset, const QString &outDir, const QString &options)
{
QString errorStr;
#ifdef IMPORT_QUICK3D_ASSETS
QScopedPointer importer {new QSSGAssetImportManager};
@@ -48,32 +51,35 @@ void import3D(const QString &sourceAsset, const QString &outDir, int exitId, con
QJsonDocument optDoc = QJsonDocument::fromJson(options.toUtf8(), &error);
if (!optDoc.isNull() && optDoc.isObject()) {
QString errorStr;
QJsonObject optObj = optDoc.object();
if (importer->importFile(sourceAsset, outDir, optObj.toVariantMap(), &errorStr)
!= QSSGAssetImportManager::ImportState::Success) {
qWarning() << __FUNCTION__ << "Failed to import 3D asset"
<< sourceAsset << "with error:" << errorStr;
} else {
// Allow little time for file operations to finish
QTimer::singleShot(2000, nullptr, [exitId]() {
qApp->exit(exitId);
});
return;
}
} else {
qWarning() << __FUNCTION__ << "Failed to parse import options:" << error.errorString();
errorStr = QObject::tr("Failed to parse import options: %1").arg(error.errorString());
}
#else
errorStr = QObject::tr("QtQuick3D is not available.");
Q_UNUSED(sourceAsset)
Q_UNUSED(outDir)
Q_UNUSED(exitId)
Q_UNUSED(options)
qWarning() << __FUNCTION__ << "Failed to parse import options, Quick3DAssetImport not available";
#endif
QTimer::singleShot(0, nullptr, [exitId]() {
// Negative exitId means import failure
qApp->exit(-exitId);
if (!errorStr.isEmpty()) {
qWarning() << __FUNCTION__ << "Failed to import asset:" << errorStr << outDir;
// Write the error into a file in outDir to pass it to creator side
QString errorFileName = outDir + "/__error.log";
QFile file(errorFileName);
if (file.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
QTextStream out(&file);
out << errorStr;
file.close();
}
}
// Allow little time for file operations to finish
QTimer::singleShot(2000, nullptr, []() {
qApp->exit(0);
});
}

View File

@@ -29,5 +29,5 @@
namespace Import3D
{
void import3D(const QString &sourceAsset, const QString &outDir, int id, const QString &options);
void import3D(const QString &sourceAsset, const QString &outDir, const QString &options);
};

View File

@@ -228,10 +228,9 @@ int internalMain(QGuiApplication *application)
if (application->arguments().at(1) == "--import3dAsset") {
QString sourceAsset = application->arguments().at(2);
QString outDir = application->arguments().at(3);
int exitId = application->arguments().at(4).toInt();
QString options = application->arguments().at(5);
QString options = application->arguments().at(4);
Import3D::import3D(sourceAsset, outDir, exitId, options);
Import3D::import3D(sourceAsset, outDir, options);
return application->exec();
}

View File

@@ -142,9 +142,10 @@ void ItemLibraryAssetImporter::addInfo(const QString &infoMsg, const QString &sr
emit infoReported(infoMsg, srcPath);
}
void ItemLibraryAssetImporter::importProcessFinished(int exitCode, QProcess::ExitStatus exitStatus)
void ItemLibraryAssetImporter::importProcessFinished(int exitCode, QProcess::ExitStatus exitStatus,
int importId)
{
Q_UNUSED(exitStatus)
Q_UNUSED(exitCode)
++m_qmlImportFinishedCount;
@@ -154,9 +155,32 @@ void ItemLibraryAssetImporter::importProcessFinished(int exitCode, QProcess::Exi
return !entry || entry->state() == QProcess::NotRunning;
}));
if (m_parseData.contains(-exitCode)) {
const ParseData pd = m_parseData.take(-exitCode);
addError(tr("Asset import process failed for: \"%1\".").arg(pd.sourceInfo.absoluteFilePath()));
if (m_parseData.contains(importId)) {
const ParseData &pd = m_parseData[importId];
QString errStr;
if (exitStatus == QProcess::ExitStatus::CrashExit) {
errStr = tr("Import process crashed.");
} else {
bool unknownFail = !pd.outDir.exists() || pd.outDir.isEmpty();
if (!unknownFail) {
QFile errorLog(pd.outDir.filePath("__error.log"));
if (errorLog.exists()) {
if (errorLog.open(QIODevice::ReadOnly))
errStr = QString::fromUtf8(errorLog.readAll());
else
unknownFail = true;
}
}
if (unknownFail)
errStr = tr("Import failed for unknown reason.");
}
if (!errStr.isEmpty()) {
addError(tr("Asset import process failed: \"%1\".")
.arg(pd.sourceInfo.absoluteFilePath()));
addError(errStr);
m_parseData.remove(importId);
}
}
if (m_qmlImportFinishedCount == m_qmlPuppetCount) {
@@ -565,15 +589,14 @@ bool ItemLibraryAssetImporter::startImportProcess(const ParseData &pd)
QJsonDocument optDoc(pd.options);
puppetArgs << "--import3dAsset" << pd.sourceInfo.absoluteFilePath()
<< pd.outDir.absolutePath() << QString::number(pd.importId)
<< QString::fromUtf8(optDoc.toJson());
<< pd.outDir.absolutePath() << QString::fromUtf8(optDoc.toJson());
QProcessUniquePointer process = puppetCreator.createPuppetProcess(
"custom",
{},
[&] {},
[&](int exitCode, QProcess::ExitStatus exitStatus) {
importProcessFinished(exitCode, exitStatus);
importProcessFinished(exitCode, exitStatus, pd.importId);
},
puppetArgs);

View File

@@ -74,7 +74,7 @@ signals:
void importFinished();
private slots:
void importProcessFinished(int exitCode, QProcess::ExitStatus exitStatus);
void importProcessFinished(int exitCode, QProcess::ExitStatus exitStatus, int importId);
void iconProcessFinished(int exitCode, QProcess::ExitStatus exitStatus);
private:
@@ -125,7 +125,7 @@ private:
std::vector<QProcessUniquePointer> m_qmlPuppetProcesses;
int m_qmlPuppetCount = 0;
int m_qmlImportFinishedCount = 0;
int m_importIdCounter = 1000000; // Use ids in range unlikely to clash with any normal process exit codes
int m_importIdCounter = 0;
QHash<int, ParseData> m_parseData;
QString m_progressTitle;
QList<Import> m_requiredImports;