forked from qt-creator/qt-creator
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:
@@ -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);
|
||||
});
|
||||
}
|
||||
|
||||
|
@@ -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);
|
||||
};
|
||||
|
@@ -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();
|
||||
}
|
||||
|
@@ -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);
|
||||
|
||||
|
@@ -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;
|
||||
|
Reference in New Issue
Block a user