QmlDesigner: Allow adding multiple 3D nodes to the content lib

Fixes: QDS-13201
Change-Id: I5812e7fb90f9d98d3ffa15eaa049a402181b1265
Reviewed-by: Shrief Gabr <shrief.gabr@qt.io>
Reviewed-by: Miikka Heikkinen <miikka.heikkinen@qt.io>
This commit is contained in:
Mahmoud Badri
2025-03-07 13:38:27 +02:00
parent 3f0f5e0ae4
commit ba8303b86b
4 changed files with 50 additions and 31 deletions

View File

@@ -87,12 +87,17 @@ inline bool isModelOrMaterial(const SelectionContext &selectionState)
inline bool enableAddToContentLib(const SelectionContext &selectionState) inline bool enableAddToContentLib(const SelectionContext &selectionState)
{ {
ModelNode modelNode = selectionState.currentSingleSelectedNode(); const QList<ModelNode> nodes = selectionState.selectedModelNodes();
auto compUtils = QmlDesignerPlugin::instance()->documentManager().generatedComponentUtils(); if (nodes.isEmpty())
bool isInBundle = modelNode.type().startsWith(compUtils.componentBundlesTypePrefix().toLatin1()); return false;
bool isNode3D = modelNode.metaInfo().isQtQuick3DNode();
return isNode3D && !isInBundle; auto compUtils = QmlDesignerPlugin::instance()->documentManager().generatedComponentUtils();
return std::all_of(nodes.cbegin(), nodes.cend(), [&](const ModelNode &node) {
bool isInBundle = node.type().startsWith(compUtils.componentBundlesTypePrefix().toLatin1());
bool isNode3D = node.metaInfo().isQtQuick3DNode();
return isNode3D && !isInBundle;
});
} }
inline bool are3DNodes(const SelectionContext &selectionState) inline bool are3DNodes(const SelectionContext &selectionState)

View File

@@ -461,10 +461,18 @@ void ContentLibraryView::customNotification(const AbstractView *view,
addLibAssets(data.first().toStringList()); addLibAssets(data.first().toStringList());
m_widget->showTab(ContentLibraryWidget::TabIndex::UserAssetsTab); m_widget->showTab(ContentLibraryWidget::TabIndex::UserAssetsTab);
} else if (identifier == "add_3d_to_content_lib") { } else if (identifier == "add_3d_to_content_lib") {
if (nodeList.first().isComponent()) const QList<ModelNode> selected3DNodes = Utils::filtered(selectedModelNodes(),
addLib3DComponent(nodeList.first()); [](const ModelNode &node) {
else return node.metaInfo().isQtQuick3DNode();
addLibItem(nodeList.first()); });
QTC_ASSERT(!selected3DNodes.isEmpty(), return);
m_remainingIconsToSave = selected3DNodes.size();
for (const ModelNode &node : selected3DNodes) {
if (node.isComponent())
addLib3DComponent(node);
else
addLibItem(node);
}
m_widget->showTab(ContentLibraryWidget::TabIndex::UserAssetsTab); m_widget->showTab(ContentLibraryWidget::TabIndex::UserAssetsTab);
} }
} }
@@ -492,12 +500,14 @@ void ContentLibraryView::auxiliaryDataChanged(const ModelNode &,
active3DSceneChanged(data.toInt()); active3DSceneChanged(data.toInt());
} }
void ContentLibraryView::modelNodePreviewPixmapChanged(const ModelNode &, void ContentLibraryView::modelNodePreviewPixmapChanged(const ModelNode &node,
const QPixmap &pixmap, const QPixmap &pixmap,
const QByteArray &requestId) const QByteArray &requestId)
{ {
if (requestId == ADD_ITEM_REQ_ID) if (requestId == ADD_ITEM_REQ_ID) {
saveIconToBundle(pixmap); saveIconToBundle(pixmap, m_nodeIconHash.value(node));
m_nodeIconHash.remove(node);
}
} }
#ifdef QDS_USE_PROJECTSTORAGE #ifdef QDS_USE_PROJECTSTORAGE
@@ -640,8 +650,8 @@ void ContentLibraryView::addLib3DComponent(const ModelNode &node)
} }
QString iconPath = QLatin1String("icons/%1").arg(UniqueName::generateId(compBaseName) + ".png"); QString iconPath = QLatin1String("icons/%1").arg(UniqueName::generateId(compBaseName) + ".png");
m_iconSavePath = bundlePath.pathAppended(iconPath); Utils::FilePath iconSavePath = bundlePath.pathAppended(iconPath);
m_iconSavePath.parentDir().ensureWritableDir(); iconSavePath.parentDir().ensureWritableDir();
const QSet<AssetPath> compDependencies = m_bundleHelper->getComponentDependencies(compFilePath, compDir); const QSet<AssetPath> compDependencies = m_bundleHelper->getComponentDependencies(compFilePath, compDir);
@@ -683,12 +693,13 @@ void ContentLibraryView::addLib3DComponent(const ModelNode &node)
.writeFileContents(QJsonDocument(jsonRef).toJson()); .writeFileContents(QJsonDocument(jsonRef).toJson());
QTC_ASSERT_EXPECTED(result,); QTC_ASSERT_EXPECTED(result,);
m_widget->userModel()->addItem(m_bundleId, compBaseName, compFileName, m_iconSavePath.toUrl(), m_widget->userModel()->addItem(m_bundleId, compBaseName, compFileName, iconSavePath.toUrl(),
filesList); filesList);
// generate and save icon // generate and save icon
m_bundleHelper->getImageFromCache(compDir.pathAppended(compFileName).path(), [&](const QImage &image) { m_bundleHelper->getImageFromCache(compDir.pathAppended(compFileName).path(),
saveIconToBundle(image); [&, iconSavePath](const QImage &image) {
saveIconToBundle(image, iconSavePath.toFSPathString());
}); });
} }
@@ -781,10 +792,10 @@ void ContentLibraryView::addLibItem(const ModelNode &node, const QPixmap &iconPi
QTC_ASSERT_EXPECTED(result,); QTC_ASSERT_EXPECTED(result,);
} }
m_iconSavePath = bundlePath.pathAppended(iconPath); Utils::FilePath iconSavePath = bundlePath.pathAppended(iconPath);
m_iconSavePath.parentDir().ensureWritableDir(); iconSavePath.parentDir().ensureWritableDir();
m_widget->userModel()->addItem(m_bundleId, name, qml, m_iconSavePath.toUrl(), depAssetsRelativePaths); m_widget->userModel()->addItem(m_bundleId, name, qml, iconSavePath.toUrl(), depAssetsRelativePaths);
// generate and save icon // generate and save icon
QPixmap iconPixmapToSave; QPixmap iconPixmapToSave;
@@ -796,21 +807,23 @@ void ContentLibraryView::addLibItem(const ModelNode &node, const QPixmap &iconPi
iconPixmapToSave = iconPixmap; iconPixmapToSave = iconPixmap;
if (iconPixmapToSave.isNull()) { if (iconPixmapToSave.isNull()) {
m_nodeIconHash.insert(node, iconSavePath.toFSPathString());
static_cast<const NodeInstanceView *>(model()->nodeInstanceView()) static_cast<const NodeInstanceView *>(model()->nodeInstanceView())
->previewImageDataForGenericNode(node, {}, {}, ADD_ITEM_REQ_ID); ->previewImageDataForGenericNode(node, {}, {}, ADD_ITEM_REQ_ID);
} else { } else {
saveIconToBundle(iconPixmapToSave); saveIconToBundle(iconPixmapToSave, iconSavePath.toFSPathString());
} }
} }
void ContentLibraryView::saveIconToBundle(const auto &image) { // auto: QImage or QPixmap void ContentLibraryView::saveIconToBundle(const auto &image, const QString &iconPath) { // auto: QImage or QPixmap
bool iconSaved = image.save(m_iconSavePath.toFSPathString()); --m_remainingIconsToSave;
if (iconSaved) bool iconSaved = image.save(iconPath);
m_widget->userModel()->refreshSection(m_bundleId); if (iconSaved) {
else if (m_remainingIconsToSave <= 0)
m_widget->userModel()->refreshSection(m_bundleId);
} else {
qWarning() << __FUNCTION__ << ": icon save failed"; qWarning() << __FUNCTION__ << ": icon save failed";
}
m_iconSavePath.clear();
} }
void ContentLibraryView::decodeAndAddToContentLib(const QByteArray &data) void ContentLibraryView::decodeAndAddToContentLib(const QByteArray &data)

View File

@@ -67,7 +67,7 @@ private:
void addLib3DComponent(const ModelNode &node); void addLib3DComponent(const ModelNode &node);
void addLibItem(const ModelNode &node, const QPixmap &iconPixmap = {}); void addLibItem(const ModelNode &node, const QPixmap &iconPixmap = {});
void importBundleToContentLib(); void importBundleToContentLib();
void saveIconToBundle(const auto &image); void saveIconToBundle(const auto &image, const QString &iconPath);
void decodeAndAddToContentLib(const QByteArray &encodedInternalIds); void decodeAndAddToContentLib(const QByteArray &encodedInternalIds);
#ifdef QDS_USE_PROJECTSTORAGE #ifdef QDS_USE_PROJECTSTORAGE
@@ -91,9 +91,10 @@ private:
bool m_bundleMaterialAddToSelected = false; bool m_bundleMaterialAddToSelected = false;
bool m_hasQuick3DImport = false; bool m_hasQuick3DImport = false;
qint32 m_sceneId = -1; qint32 m_sceneId = -1;
Utils::FilePath m_iconSavePath;
QString m_generatedFolderName; QString m_generatedFolderName;
QString m_bundleId; QString m_bundleId;
QHash<ModelNode, QString> m_nodeIconHash;
int m_remainingIconsToSave = 0;
static constexpr char BUNDLE_VERSION[] = "1.0"; static constexpr char BUNDLE_VERSION[] = "1.0";
static constexpr char ADD_ITEM_REQ_ID[] = "AddItemReqId"; static constexpr char ADD_ITEM_REQ_ID[] = "AddItemReqId";

View File

@@ -373,7 +373,7 @@ void Edit3DWidget::createContextMenu()
contextIcon(DesignerIcons::CreateIcon), // TODO: placeholder icon contextIcon(DesignerIcons::CreateIcon), // TODO: placeholder icon
tr("Add to Content Library"), [&] { tr("Add to Content Library"), [&] {
QmlDesignerPlugin::instance()->mainWidget()->showDockWidget("ContentLibrary"); QmlDesignerPlugin::instance()->mainWidget()->showDockWidget("ContentLibrary");
view()->emitCustomNotification("add_3d_to_content_lib", {m_contextMenuTarget}); // To ContentLibrary view()->emitCustomNotification("add_3d_to_content_lib", {}); // To ContentLibrary
}); });
m_importBundleAction = m_contextMenu->addAction( m_importBundleAction = m_contextMenu->addAction(