QmlDesigner: Add assets to navigator in 1 transaction

...so only 1 undo step is created when dragging multiple assets to
navigator.

Change-Id: Ifa812eada5ce56a51e164d80864c3826f9875caf
Reviewed-by: Miikka Heikkinen <miikka.heikkinen@qt.io>
This commit is contained in:
Mahmoud Badri
2021-06-18 15:52:28 +03:00
parent 1c44dab5af
commit 95a3ce7e25
2 changed files with 119 additions and 125 deletions

View File

@@ -535,7 +535,7 @@ bool NavigatorTreeModel::dropMimeData(const QMimeData *mimeData,
if (mimeData->hasFormat("application/vnd.bauhaus.itemlibraryinfo")) { if (mimeData->hasFormat("application/vnd.bauhaus.itemlibraryinfo")) {
handleItemLibraryItemDrop(mimeData, rowNumber, dropModelIndex); handleItemLibraryItemDrop(mimeData, rowNumber, dropModelIndex);
} else if (mimeData->hasFormat("application/vnd.bauhaus.libraryresource")) { } else if (mimeData->hasFormat("application/vnd.bauhaus.libraryresource")) {
QStringList assetsPaths = QString::fromUtf8(mimeData->data("application/vnd.bauhaus.libraryresource")).split(","); const QStringList assetsPaths = QString::fromUtf8(mimeData->data("application/vnd.bauhaus.libraryresource")).split(",");
NodeAbstractProperty targetProperty; NodeAbstractProperty targetProperty;
const QModelIndex rowModelIndex = dropModelIndex.sibling(dropModelIndex.row(), 0); const QModelIndex rowModelIndex = dropModelIndex.sibling(dropModelIndex.row(), 0);
@@ -544,7 +544,24 @@ bool NavigatorTreeModel::dropMimeData(const QMimeData *mimeData,
if (foundTarget) { if (foundTarget) {
QList<ModelNode> addedNodes; QList<ModelNode> addedNodes;
ModelNode currNode; ModelNode currNode;
for (const QString &assetPath : std::as_const(assetsPaths)) {
QSet<QString> neededImports;
for (const QString &assetPath : assetsPaths) {
QString assetType = ItemLibraryWidget::getAssetTypeAndData(assetPath).first;
if (assetType == "application/vnd.bauhaus.libraryresource.shader")
neededImports.insert("QtQuick3D");
else if (assetType == "application/vnd.bauhaus.libraryresource.sound")
neededImports.insert("QtMultimedia");
if (neededImports.size() == 2)
break;
};
for (const QString &import : std::as_const(neededImports))
addImport(import);
m_view->executeInTransaction("NavigatorTreeModel::dropMimeData", [&] {
for (const QString &assetPath : assetsPaths) {
auto assetTypeAndData = ItemLibraryWidget::getAssetTypeAndData(assetPath); auto assetTypeAndData = ItemLibraryWidget::getAssetTypeAndData(assetPath);
QString assetType = assetTypeAndData.first; QString assetType = assetTypeAndData.first;
QString assetData = QString::fromUtf8(assetTypeAndData.second); QString assetData = QString::fromUtf8(assetTypeAndData.second);
@@ -562,6 +579,8 @@ bool NavigatorTreeModel::dropMimeData(const QMimeData *mimeData,
if (currNode.isValid()) if (currNode.isValid())
addedNodes.append(currNode); addedNodes.append(currNode);
} }
});
if (!addedNodes.isEmpty()) { if (!addedNodes.isEmpty()) {
moveNodesInteractive(targetProperty, addedNodes, rowNumber); moveNodesInteractive(targetProperty, addedNodes, rowNumber);
m_view->setSelectedModelNodes(addedNodes); m_view->setSelectedModelNodes(addedNodes);
@@ -757,14 +776,12 @@ ModelNode NavigatorTreeModel::handleItemLibraryImageDrop(const QString &imagePat
// if dropping an image on an existing image, set the source // if dropping an image on an existing image, set the source
targetNode.variantProperty("source").setValue(imagePathRelative); targetNode.variantProperty("source").setValue(imagePathRelative);
} else { } else {
m_view->executeInTransaction("NavigatorTreeModel::handleItemLibraryImageDrop", [&] {
// create an image // create an image
QmlItemNode newItemNode = QmlItemNode::createQmlItemNodeFromImage(m_view, imagePath, QPointF(), targetProperty, false); QmlItemNode newItemNode = QmlItemNode::createQmlItemNodeFromImage(m_view, imagePath, QPointF(), targetProperty, false);
if (NodeHints::fromModelNode(targetProperty.parentModelNode()).canBeContainerFor(newItemNode.modelNode())) if (NodeHints::fromModelNode(targetProperty.parentModelNode()).canBeContainerFor(newItemNode.modelNode()))
newModelNode = newItemNode.modelNode(); newModelNode = newItemNode.modelNode();
else else
newItemNode.destroy(); newItemNode.destroy();
});
} }
} }
@@ -781,7 +798,6 @@ ModelNode NavigatorTreeModel::handleItemLibraryFontDrop(const QString &fontFamil
ModelNode newModelNode; ModelNode newModelNode;
m_view->executeInTransaction("NavigatorTreeModel::handleItemLibraryFontDrop", [&] {
if (targetNode.isSubclassOf("QtQuick.Text")) { if (targetNode.isSubclassOf("QtQuick.Text")) {
// if dropping into an existing Text, update font // if dropping into an existing Text, update font
targetNode.variantProperty("font.family").setValue(fontFamily); targetNode.variantProperty("font.family").setValue(fontFamily);
@@ -794,37 +810,37 @@ ModelNode NavigatorTreeModel::handleItemLibraryFontDrop(const QString &fontFamil
else else
newItemNode.destroy(); newItemNode.destroy();
} }
});
return newModelNode; return newModelNode;
} }
void NavigatorTreeModel::addImport(const QString &importName)
{
Import import = Import::createLibraryImport(importName);
if (!m_view->model()->hasImport(import, true, true)) {
const QList<Import> possImports = m_view->model()->possibleImports();
for (const auto &possImport : possImports) {
if (possImport.url() == import.url()) {
import = possImport;
m_view->model()->changeImports({import}, {});
QmlDesignerPlugin::instance()->currentDesignDocument()->updateSubcomponentManagerImport(import);
break;
}
}
}
}
ModelNode NavigatorTreeModel::handleItemLibraryShaderDrop(const QString &shaderPath, bool isFragShader, ModelNode NavigatorTreeModel::handleItemLibraryShaderDrop(const QString &shaderPath, bool isFragShader,
NodeAbstractProperty targetProperty, NodeAbstractProperty targetProperty,
const QModelIndex &rowModelIndex) const QModelIndex &rowModelIndex)
{ {
QTC_ASSERT(m_view, return {}); QTC_ASSERT(m_view, return {});
Import import = Import::createLibraryImport(QStringLiteral("QtQuick3D"));
bool addImport = false;
if (!m_view->model()->hasImport(import, true, true)) {
const QList<Import> possImports = m_view->model()->possibleImports();
for (const auto &possImport : possImports) {
if (possImport.url() == import.url()) {
import = possImport;
addImport = true;
m_view->model()->changeImports({import}, {});
break;
}
}
}
ModelNode targetNode(modelNodeForIndex(rowModelIndex)); ModelNode targetNode(modelNodeForIndex(rowModelIndex));
ModelNode newModelNode; ModelNode newModelNode;
const QString relPath = DocumentManager::currentFilePath().toFileInfo().dir().relativeFilePath(shaderPath); const QString relPath = DocumentManager::currentFilePath().toFileInfo().dir().relativeFilePath(shaderPath);
m_view->executeInTransaction("NavigatorTreeModel::handleItemLibraryShaderDrop", [&] {
if (targetNode.isSubclassOf("QtQuick3D.Shader")) { if (targetNode.isSubclassOf("QtQuick3D.Shader")) {
// if dropping into an existing Shader, update // if dropping into an existing Shader, update
targetNode.variantProperty("stage").setEnumeration(isFragShader ? "Shader.Fragment" targetNode.variantProperty("stage").setEnumeration(isFragShader ? "Shader.Fragment"
@@ -855,10 +871,6 @@ ModelNode NavigatorTreeModel::handleItemLibraryShaderDrop(const QString &shaderP
newModelNode.setIdWithoutRefactoring(m_view->generateNewId(fi.baseName(), newModelNode.setIdWithoutRefactoring(m_view->generateNewId(fi.baseName(),
"shader")); "shader"));
} }
});
if (addImport)
QmlDesignerPlugin::instance()->currentDesignDocument()->updateSubcomponentManager();
return newModelNode; return newModelNode;
} }
@@ -869,26 +881,11 @@ ModelNode NavigatorTreeModel::handleItemLibrarySoundDrop(const QString &soundPat
{ {
QTC_ASSERT(m_view, return {}); QTC_ASSERT(m_view, return {});
Import import = Import::createLibraryImport(QStringLiteral("QtMultimedia"));
bool addImport = false;
if (!m_view->model()->hasImport(import, true, true)) {
const QList<Import> possImports = m_view->model()->possibleImports();
for (const auto &possImport : possImports) {
if (possImport.url() == import.url()) {
import = possImport;
addImport = true;
m_view->model()->changeImports({import}, {});
break;
}
}
}
ModelNode targetNode(modelNodeForIndex(rowModelIndex)); ModelNode targetNode(modelNodeForIndex(rowModelIndex));
ModelNode newModelNode; ModelNode newModelNode;
const QString relPath = DocumentManager::currentFilePath().toFileInfo().dir().relativeFilePath(soundPath); const QString relPath = DocumentManager::currentFilePath().toFileInfo().dir().relativeFilePath(soundPath);
m_view->executeInTransaction("NavigatorTreeModel::handleItemLibrarySoundDrop", [&] {
if (targetNode.isSubclassOf("QtMultimedia.SoundEffect")) { if (targetNode.isSubclassOf("QtMultimedia.SoundEffect")) {
// if dropping into on an existing SoundEffect, update // if dropping into on an existing SoundEffect, update
targetNode.variantProperty("source").setValue(relPath); targetNode.variantProperty("source").setValue(relPath);
@@ -913,10 +910,6 @@ ModelNode NavigatorTreeModel::handleItemLibrarySoundDrop(const QString &soundPat
newModelNode.setIdWithoutRefactoring(m_view->generateNewId(fi.baseName(), newModelNode.setIdWithoutRefactoring(m_view->generateNewId(fi.baseName(),
"soundEffect")); "soundEffect"));
} }
});
if (addImport)
QmlDesignerPlugin::instance()->currentDesignDocument()->updateSubcomponentManager();
return newModelNode; return newModelNode;
} }

View File

@@ -128,6 +128,7 @@ private:
const QString &imagePath, ModelNode &newNode); const QString &imagePath, ModelNode &newNode);
ModelNode createTextureNode(const NodeAbstractProperty &targetProp, const QString &imagePath); ModelNode createTextureNode(const NodeAbstractProperty &targetProp, const QString &imagePath);
QList<QPersistentModelIndex> nodesToPersistentIndex(const QList<ModelNode> &modelNodes); QList<QPersistentModelIndex> nodesToPersistentIndex(const QList<ModelNode> &modelNodes);
void addImport(const QString &importName);
QPointer<NavigatorView> m_view; QPointer<NavigatorView> m_view;
mutable QHash<ModelNode, QModelIndex> m_nodeIndexHash; mutable QHash<ModelNode, QModelIndex> m_nodeIndexHash;