diff options
author | Mahmoud Badri <mahmoud.badri@qt.io> | 2018-08-15 14:18:54 +0300 |
---|---|---|
committer | Tomi Korpipää <tomi.korpipaa@qt.io> | 2018-08-17 03:39:04 +0000 |
commit | be23d3d7e307bc91de323bab9d6489c9291a7f71 (patch) | |
tree | d51902906d33450f811003b3a550b2b515488ac7 /src/Authoring/Studio/Palettes | |
parent | 9080e19cabeae385fd5b9a762d19a8c5a7a7aa74 (diff) |
Import Qml streams
Allow importing visual Qml files (Qml streams) to the Studio. visual Qmls
are detected and put in the 'qml streams' folder. the qml file is
parsed recursively and any node with a valid 'source' attribute is
imported as well. Imported Qmls are added to the project file for use as
a sub-presentation.
Task-number: QT3DS-2061
Change-Id: Ic0ac0178adb4bac06972a9e553c1dc0bb6c5286d
Reviewed-by: Miikka Heikkinen <miikka.heikkinen@qt.io>
Reviewed-by: Janne Kangas <janne.kangas@qt.io>
Reviewed-by: Tomi Korpipää <tomi.korpipaa@qt.io>
Diffstat (limited to 'src/Authoring/Studio/Palettes')
4 files changed, 85 insertions, 5 deletions
diff --git a/src/Authoring/Studio/Palettes/Project/ProjectFileSystemModel.cpp b/src/Authoring/Studio/Palettes/Project/ProjectFileSystemModel.cpp index b0ab81f2..39587036 100644 --- a/src/Authoring/Studio/Palettes/Project/ProjectFileSystemModel.cpp +++ b/src/Authoring/Studio/Palettes/Project/ProjectFileSystemModel.cpp @@ -44,6 +44,7 @@ #include "Qt3DSMessageBox.h" #include "IDocumentEditor.h" #include "IDragable.h" +#include <QtQml/qqmlapplicationengine.h> ProjectFileSystemModel::ProjectFileSystemModel(QObject *parent) : QAbstractListModel(parent) , m_model(new QFileSystemModel(this)) @@ -128,7 +129,7 @@ bool ProjectFileSystemModel::isRefreshable(int row) const const QString path = filePath(row); // Import needs to be refreshable even if it is not referenced, as user may drag just individual // meshes into the scene, and not the whole import. - return path.endsWith(QStringLiteral(".import")); + return path.endsWith(QLatin1String(".import")); } void ProjectFileSystemModel::updateReferences(bool emitDataChanged) @@ -220,6 +221,8 @@ Q3DStudio::DocumentEditorFileType::Enum ProjectFileSystemModel::assetTypeForRow( return Q3DStudio::DocumentEditorFileType::Behavior; else if (path == QLatin1String("presentations")) return Q3DStudio::DocumentEditorFileType::Presentation; + else if (path == QLatin1String("qml streams")) + return Q3DStudio::DocumentEditorFileType::QmlStream; return Q3DStudio::DocumentEditorFileType::Unknown; } @@ -362,6 +365,7 @@ void ProjectFileSystemModel::importUrls(const QList<QUrl> &urls, int row, bool a const TreeItem &item = m_items.at(row); QString targetPath = item.index.data(QFileSystemModel::FilePathRole).toString(); + QFileInfo fi(targetPath); if (!fi.isDir()) targetPath = fi.absolutePath(); @@ -383,8 +387,8 @@ void ProjectFileSystemModel::importUrls(const QList<QUrl> &urls, int row, bool a } if (sortedDir.exists()) { - expandPaths << sortedPath; - importUrl(sortedPath, url); + importUrl(sortedDir, url); + expandPaths << sortedDir.path(); } } @@ -395,7 +399,7 @@ void ProjectFileSystemModel::importUrls(const QList<QUrl> &urls, int row, bool a } } -void ProjectFileSystemModel::importUrl(const QDir &targetDir, const QUrl &url) const +void ProjectFileSystemModel::importUrl(QDir &targetDir, const QUrl &url) { using namespace Q3DStudio; using namespace qt3dsimp; @@ -444,6 +448,25 @@ void ProjectFileSystemModel::importUrl(const QDir &targetDir, const QUrl &url) c translator.m_TranslationLog, forceError); #endif } else { + QQmlApplicationEngine qmlEngine; + QObject *qmlRoot = nullptr; + if (extension == QLatin1String("qml")) { + qmlEngine.load(sourceFile); + const char *rootClassName = qmlEngine.rootObjects().at(0) + ->metaObject()->superClass()->className(); + + // the assumption here is that any qml that is not a behavior is a qml stream + if (strcmp(rootClassName, "Q3DStudio::Q3DSQmlBehavior") != 0) { // not a behavior + qmlRoot = qmlEngine.rootObjects().at(0); + + // put the qml in the correct folder + if (targetDir.path().endsWith(QLatin1String("/scripts"))) { + const QString path(QStringLiteral("../qml streams")); + targetDir.mkpath(path); // create the folder if doesn't exist (i.e. old project) + targetDir.cd(path); + } + } + } // Copy the file to target directory // FindAndCopyDestFile will make sure the file name is unique and make sure it is // not read only. @@ -455,6 +478,10 @@ void ProjectFileSystemModel::importUrl(const QDir &targetDir, const QUrl &url) c // add presentation node to the project file g_StudioApp.GetCore()->getProjectFile().addPresentationNode(destPath); importPresentationAssets(fileInfo, QFileInfo(destPath)); + } else if (qmlRoot) { // importing a qml stream + g_StudioApp.GetCore()->getProjectFile().addPresentationNode(destPath); + m_importQmlOverrideChoice = QMessageBox::NoButton; + importQmlAssets(qmlRoot, fileInfo.dir(), targetDir); } // For effect and custom material files, automatically copy related resources @@ -543,6 +570,52 @@ void ProjectFileSystemModel::importPresentationAssets(const QFileInfo &uipSrc, } } +void ProjectFileSystemModel::importQmlAssets(const QObject *qmlNode, const QDir &srcDir, + const QDir &targetDir) +{ + QString assetSrc = qmlNode->property("source").toString(); // absolute file path + + if (!assetSrc.isEmpty()) { + // remove file:/// + if (assetSrc.startsWith(QLatin1String("file:///"))) + assetSrc = assetSrc.mid(8); + else if (assetSrc.startsWith(QLatin1String("file://"))) + assetSrc = assetSrc.mid(7); + + if (srcDir.exists(assetSrc)) { // there is an asset to import + QString assetTarget = targetDir.absoluteFilePath(srcDir.relativeFilePath(assetSrc)); + + QFileInfo fi(assetTarget); + if (!fi.dir().exists()) + fi.dir().mkpath("."); + + if (fi.exists()) { // imported asset exists, show override / skip box + if (m_importQmlOverrideChoice == QMessageBox::YesToAll) { + QFile::remove(assetTarget); + } else if (m_importQmlOverrideChoice == QMessageBox::NoToAll) { + // QFile::copy() does not override files + } else { + // get path relative to project root (for neat displaying) + QString pathFromRoot = QDir(g_StudioApp.GetCore()->getProjectFile() + .getProjectPath()).relativeFilePath(assetTarget); + + m_importQmlOverrideChoice = g_StudioApp.GetDialogs() + ->displayOverrideAssetBox(pathFromRoot); + if (m_importQmlOverrideChoice & (QMessageBox::Yes | QMessageBox::YesToAll)) + QFile::remove(assetTarget); + } + } + + QFile::copy(assetSrc, assetTarget); + } + } + + // recursively load child nodes + const QObjectList qmlNodeChildren = qmlNode->children(); + for (int i = 0; i < qmlNodeChildren.count(); ++i) + importQmlAssets(qmlNodeChildren.at(i), srcDir, targetDir); +} + int ProjectFileSystemModel::rowForPath(const QString &path) const { for (int i = m_items.size() - 1; i >= 0 ; --i) { @@ -782,6 +855,7 @@ void ProjectFileSystemModel::updateDefaultDirMap() m_defaultDirToAbsPathMap.insert(QStringLiteral("models"), QString()); m_defaultDirToAbsPathMap.insert(QStringLiteral("scripts"), QString()); m_defaultDirToAbsPathMap.insert(QStringLiteral("presentations"), QString()); + m_defaultDirToAbsPathMap.insert(QStringLiteral("qml streams"), QString()); } const QString rootPath = m_items[0].index.data(QFileSystemModel::FilePathRole).toString(); diff --git a/src/Authoring/Studio/Palettes/Project/ProjectFileSystemModel.h b/src/Authoring/Studio/Palettes/Project/ProjectFileSystemModel.h index 60bc1f40..75f9e985 100644 --- a/src/Authoring/Studio/Palettes/Project/ProjectFileSystemModel.h +++ b/src/Authoring/Studio/Palettes/Project/ProjectFileSystemModel.h @@ -88,7 +88,7 @@ private: EStudioObjectType getIconType(const QString &path) const; bool isVisible(const QModelIndex& modelIndex) const; bool hasVisibleChildren(const QModelIndex &modelIndex) const; - void importUrl(const QDir &targetDir, const QUrl &url) const; + void importUrl(QDir &targetDir, const QUrl &url); void importPresentationAssets(const QFileInfo &uipSrc, const QFileInfo &uipTarget, const int overrideChoice = QMessageBox::NoButton) const; @@ -96,6 +96,7 @@ private: void modelRowsRemoved(const QModelIndex &parent, int start, int end); void modelRowsMoved(const QModelIndex &parent, int start, int end); void modelLayoutChanged(); + void importQmlAssets(const QObject *qmlNode, const QDir &srcDir, const QDir &targetDir); void updateDefaultDirMap(); @@ -112,6 +113,7 @@ private: QList<TreeItem> m_items; QStringList m_references; QHash<QString, QString> m_defaultDirToAbsPathMap; + int m_importQmlOverrideChoice = QMessageBox::NoButton; }; #endif // TREEVIEWADAPTOR_H diff --git a/src/Authoring/Studio/Palettes/Project/ProjectView.cpp b/src/Authoring/Studio/Palettes/Project/ProjectView.cpp index 670aab30..f97c7c1a 100644 --- a/src/Authoring/Studio/Palettes/Project/ProjectView.cpp +++ b/src/Authoring/Studio/Palettes/Project/ProjectView.cpp @@ -65,6 +65,7 @@ ProjectView::ProjectView(const QSize &preferredSize, QWidget *parent) : QQuickWi m_defaultMaterialDir = theApplicationPath + QStringLiteral("/Content/Material Library"); m_defaultModelDir = theApplicationPath + QStringLiteral("/Content/Models Library"); m_defaultPresentationDir = theApplicationPath + QStringLiteral("/Content/Presentations"); + m_defaultQmlStreamDir = theApplicationPath + QStringLiteral("/Content/Qml Streams"); m_BehaviorDir = m_defaultBehaviorDir; m_EffectDir = m_defaultEffectDir; @@ -73,6 +74,7 @@ ProjectView::ProjectView(const QSize &preferredSize, QWidget *parent) : QQuickWi m_MaterialDir = m_defaultMaterialDir; m_ModelDir = m_defaultModelDir; m_presentationDir = m_defaultPresentationDir; + m_qmlStreamDir = m_defaultQmlStreamDir; m_assetImportDir = theApplicationPath + QStringLiteral("/Content"); diff --git a/src/Authoring/Studio/Palettes/Project/ProjectView.h b/src/Authoring/Studio/Palettes/Project/ProjectView.h index 3c24c57f..eedd562e 100644 --- a/src/Authoring/Studio/Palettes/Project/ProjectView.h +++ b/src/Authoring/Studio/Palettes/Project/ProjectView.h @@ -112,6 +112,7 @@ private: QString m_defaultMaterialDir; QString m_defaultModelDir; QString m_defaultPresentationDir; + QString m_defaultQmlStreamDir; QString m_BehaviorDir; QString m_EffectDir; QString m_FontDir; @@ -119,6 +120,7 @@ private: QString m_MaterialDir; QString m_ModelDir; QString m_presentationDir; + QString m_qmlStreamDir; QString m_assetImportDir; QSize m_preferredSize; }; |