diff --git a/src/plugins/qmldesigner/components/contentlibrary/contentlibraryview.cpp b/src/plugins/qmldesigner/components/contentlibrary/contentlibraryview.cpp index feb648665ef..600fa181f5b 100644 --- a/src/plugins/qmldesigner/components/contentlibrary/contentlibraryview.cpp +++ b/src/plugins/qmldesigner/components/contentlibrary/contentlibraryview.cpp @@ -27,6 +27,8 @@ #include #include #include + +#include #include #include @@ -386,6 +388,8 @@ void ContentLibraryView::customNotification(const AbstractView *view, exportLib3DItem(nodeList.first()); } else if (identifier == "export_material_as_bundle") { exportLib3DItem(nodeList.first(), data.first().value()); + } else if (identifier == "import_bundle_to_3d_scene") { + importBundle(); } } @@ -798,6 +802,9 @@ void ContentLibraryView::exportLib3DComponent(const ModelNode &node) jsonObj["items"] = itemsArr; + auto compUtils = QmlDesignerPlugin::instance()->documentManager().generatedComponentUtils(); + jsonObj["id"] = compUtils.user3DBundleId(); + Utils::FilePath jsonFilePath = targetPath.pathAppended(Constants::BUNDLE_JSON_FILENAME); m_zipWriter->addFile(jsonFilePath.fileName(), QJsonDocument(jsonObj).toJson()); @@ -875,7 +882,7 @@ void ContentLibraryView::addLib3DItem(const ModelNode &node) m_widget->userModel()->add3DItem(name, qml, m_iconSavePath.toUrl(), depAssetsList); } -QString ContentLibraryView::getExportPath(const ModelNode &node) +QString ContentLibraryView::getExportPath(const ModelNode &node) const { QString defaultExportFileName = QLatin1String("%1.%2").arg(node.id(), Constants::BUNDLE_SUFFIX); Utils::FilePath projectFP = DocumentManager::currentProjectDirPath(); @@ -891,6 +898,18 @@ QString ContentLibraryView::getExportPath(const ModelNode &node) tr("Qt Design Studio Bundle Files (*.%1)").arg(Constants::BUNDLE_SUFFIX)); } +QString ContentLibraryView::getImportPath() const +{ + Utils::FilePath projectFP = DocumentManager::currentProjectDirPath(); + if (projectFP.isEmpty()) { + projectFP = QmlDesignerPlugin::instance()->documentManager() + .currentDesignDocument()->fileName().parentDir(); + } + + return QFileDialog::getOpenFileName(m_widget, tr("Import Component"), projectFP.toFSPathString(), + tr("Qt Design Studio Bundle Files (*.%1)").arg(Constants::BUNDLE_SUFFIX)); +} + void ContentLibraryView::exportLib3DItem(const ModelNode &node, const QPixmap &iconPixmap) { QString exportPath = getExportPath(node); @@ -934,6 +953,10 @@ void ContentLibraryView::exportLib3DItem(const ModelNode &node, const QPixmap &i jsonObj["items"] = itemsArr; + auto compUtils = QmlDesignerPlugin::instance()->documentManager().generatedComponentUtils(); + jsonObj["id"] = node.metaInfo().isQtQuick3DMaterial() ? compUtils.userMaterialsBundleId() + : compUtils.user3DBundleId(); + Utils::FilePath jsonFilePath = targetPath.pathAppended(Constants::BUNDLE_JSON_FILENAME); m_zipWriter->addFile(jsonFilePath.fileName(), QJsonDocument(jsonObj).toJson()); @@ -961,6 +984,60 @@ void ContentLibraryView::exportLib3DItem(const ModelNode &node, const QPixmap &i addIconAndCloseZip(iconPixmap); } +void ContentLibraryView::importBundle() +{ + // TODO: support importing materials + + QString importPath = getImportPath(); + if (importPath.isEmpty()) + return; + + auto bundlePath = Utils::FilePath::fromString(Paths::bundlesPathSetting() + "/User/3d/"); + ZipReader zipReader(importPath); + + QByteArray bundleJsonContent = zipReader.fileData(Constants::BUNDLE_JSON_FILENAME); + QTC_ASSERT(!bundleJsonContent.isEmpty(), return); + + const QJsonObject importedJsonObj = QJsonDocument::fromJson(bundleJsonContent).object(); + const QJsonArray importedItemsArr = importedJsonObj.value("items").toArray(); + QTC_ASSERT(!importedItemsArr.isEmpty(), return); + + // copy files to bundle folder + const QList fiList = zipReader.fileInfoList(); + for (const ZipReader::FileInfo &fi : fiList) { + if (fi.filePath == Constants::BUNDLE_JSON_FILENAME) + continue; + + Utils::FilePath fp = bundlePath.pathAppended(fi.filePath); + fp.parentDir().ensureWritableDir(); + fp.writeFileContents(zipReader.fileData(fi.filePath)); + } + zipReader.close(); + + // update bundle json file and user model + QJsonObject &jsonRef = m_widget->userModel()->bundleJson3DObjectRef(); + QJsonArray itemsArr = jsonRef.value("items").toArray(); + for (const QJsonValueConstRef &itemRef : importedItemsArr) { + // add entry to json + itemsArr.append(itemRef); + + // add entry to model + const QJsonObject itemObj = itemRef.toObject(); + QString name = itemObj.value("name").toString(); + QString qml = itemObj.value("qml").toString(); + QStringList files = itemObj.value("files").toVariant().toStringList(); + QUrl iconUrl = bundlePath.pathAppended(itemObj.value("icon").toString()).toUrl(); + m_widget->userModel()->add3DItem(name, qml, iconUrl, files); + } + jsonRef["items"] = itemsArr; + + auto result = bundlePath.pathAppended(Constants::BUNDLE_JSON_FILENAME) + .writeFileContents(QJsonDocument(jsonRef).toJson()); + QTC_ASSERT_EXPECTED(result,); + + m_widget->userModel()->refresh3DSection(); +} + /** * @brief Generates an icon image from a qml component * @param qmlPath path to the qml component file to be rendered diff --git a/src/plugins/qmldesigner/components/contentlibrary/contentlibraryview.h b/src/plugins/qmldesigner/components/contentlibrary/contentlibraryview.h index c109aace134..404a270d705 100644 --- a/src/plugins/qmldesigner/components/contentlibrary/contentlibraryview.h +++ b/src/plugins/qmldesigner/components/contentlibrary/contentlibraryview.h @@ -65,9 +65,11 @@ private: void exportLib3DComponent(const ModelNode &node); void addLib3DItem(const ModelNode &node); void exportLib3DItem(const ModelNode &node, const QPixmap &iconPixmap = {}); + void importBundle(); void getImageFromCache(const QString &qmlPath, std::function successCallback); - QString getExportPath(const ModelNode &node); + QString getExportPath(const ModelNode &node) const; + QString getImportPath() const; QPair> modelNodeToQmlString(const ModelNode &node, int depth = 0); #ifdef QDS_USE_PROJECTSTORAGE diff --git a/src/plugins/qmldesigner/components/edit3d/edit3dwidget.cpp b/src/plugins/qmldesigner/components/edit3d/edit3dwidget.cpp index e013862f9ca..34733d3f0e8 100644 --- a/src/plugins/qmldesigner/components/edit3d/edit3dwidget.cpp +++ b/src/plugins/qmldesigner/components/edit3d/edit3dwidget.cpp @@ -373,7 +373,7 @@ void Edit3DWidget::createContextMenu() m_importBundleAction = m_contextMenu->addAction( contextIcon(DesignerIcons::CreateIcon), // TODO: placeholder icon tr("Import Components"), [&] { - // TODO: implement importing components + view()->emitCustomNotification("import_bundle_to_3d_scene", {m_contextMenuTarget}); // To ContentLibrary }); m_exportBundleAction = m_contextMenu->addAction( @@ -662,7 +662,6 @@ void Edit3DWidget::showContextMenu(const QPoint &pos, const ModelNode &modelNode m_bakeLightsAction->setVisible(view()->bakeLightsAction()->action()->isVisible()); m_bakeLightsAction->setEnabled(view()->bakeLightsAction()->action()->isEnabled()); m_addToContentLibAction->setEnabled(isNode && !isInBundle); - m_importBundleAction->setEnabled(isNode); m_exportBundleAction->setEnabled(isNode); if (m_view) {