QmlDesigner: Fix asset drag to material browser

Drag now correctly accepts only assets that can be used as textures.

"selected_texture_changed" custom notification was used in two
semantically slightly different cases, both to indicate selected
texture had changed and that selection should change, which was little
confusing. Split the two cases to separate custom notifications to
clarify the situation and allow "select_texture" to be handled in
material browser even if it sent it. This fixes the issue of newly
added texture not getting selected after drag, because creation was
done by material browser view.

Similar issue was fixed with "selected_material_changed" as well.

Also fixed a couple of cases of drag not being properly ended.

Change-Id: Ie1cae01ef13b687d9e611ac1c91443688001fe49
Reviewed-by: Mahmoud Badri <mahmoud.badri@qt.io>
This commit is contained in:
Miikka Heikkinen
2023-03-06 17:27:25 +02:00
parent 632027aa14
commit c78c4817cd
14 changed files with 50 additions and 33 deletions

View File

@@ -198,7 +198,7 @@ TreeViewDelegate {
if (root.__isDirectory) if (root.__isDirectory)
return filePath return filePath
if (rootView.assetIsImage(model.filePath)) { if (rootView.assetIsImageOrTexture(model.filePath)) {
let size = rootView.imageSize(model.filePath) let size = rootView.imageSize(model.filePath)
return filePath + "\n" return filePath + "\n"

View File

@@ -716,9 +716,10 @@ Item {
dropEnabled: true dropEnabled: true
onDropEnter: (drag) => { onDropEnter: (drag) => {
drag.accepted = drag.formats[0] === "application/vnd.qtdesignstudio.bundletexture" let accepted = drag.formats[0] === "application/vnd.qtdesignstudio.bundletexture"
|| drag.formats[0] === "application/vnd.qtdesignstudio.assets" if (drag.formats[0] === "application/vnd.qtdesignstudio.assets")
accepted = rootView.hasAcceptableAssets(drag.urls)
drag.accepted = accepted
highlight = drag.accepted highlight = drag.accepted
} }

View File

@@ -169,8 +169,7 @@ bool AssetsLibraryModel::deleteFolderRecursively(const QModelIndex &folderIndex)
bool AssetsLibraryModel::allFilePathsAreTextures(const QStringList &filePaths) const bool AssetsLibraryModel::allFilePathsAreTextures(const QStringList &filePaths) const
{ {
return Utils::allOf(filePaths, [](const QString &path) { return Utils::allOf(filePaths, [](const QString &path) {
Asset asset(path); return Asset(path).isValidTextureSource();
return asset.isImage() || asset.isTexture3D();
}); });
} }

View File

@@ -245,10 +245,9 @@ QString AssetsLibraryWidget::assetFileSize(const QString &id)
return QLocale::system().formattedDataSize(fileSize, 2, QLocale::DataSizeTraditionalFormat); return QLocale::system().formattedDataSize(fileSize, 2, QLocale::DataSizeTraditionalFormat);
} }
bool AssetsLibraryWidget::assetIsImage(const QString &id) bool AssetsLibraryWidget::assetIsImageOrTexture(const QString &id)
{ {
Asset asset(id); return Asset(id).isValidTextureSource();
return asset.isImage() || asset.isTexture3D();
} }
QList<QToolButton *> AssetsLibraryWidget::createToolBarWidgets() QList<QToolButton *> AssetsLibraryWidget::createToolBarWidgets()

View File

@@ -80,7 +80,7 @@ public:
Q_INVOKABLE void invalidateThumbnail(const QString &id); Q_INVOKABLE void invalidateThumbnail(const QString &id);
Q_INVOKABLE QSize imageSize(const QString &id); Q_INVOKABLE QSize imageSize(const QString &id);
Q_INVOKABLE QString assetFileSize(const QString &id); Q_INVOKABLE QString assetFileSize(const QString &id);
Q_INVOKABLE bool assetIsImage(const QString &id); Q_INVOKABLE bool assetIsImageOrTexture(const QString &id);
Q_INVOKABLE void addTextures(const QStringList &filePaths); Q_INVOKABLE void addTextures(const QStringList &filePaths);
Q_INVOKABLE void addLightProbe(const QString &filePaths); Q_INVOKABLE void addLightProbe(const QString &filePaths);

View File

@@ -835,8 +835,8 @@ void editMaterial(const SelectionContext &selectionContext)
if (material.isValid()) { if (material.isValid()) {
QmlDesignerPlugin::instance()->mainWidget()->showDockWidget("MaterialEditor"); QmlDesignerPlugin::instance()->mainWidget()->showDockWidget("MaterialEditor");
// to MaterialEditor and MaterialBrowser... // to MaterialBrowser...
view->emitCustomNotification("selected_material_changed", {material}); view->emitCustomNotification("select_material", {material});
} }
} }

View File

@@ -4,6 +4,7 @@
#include "createtexture.h" #include "createtexture.h"
#include "abstractview.h" #include "abstractview.h"
#include "asset.h"
#include "documentmanager.h" #include "documentmanager.h"
#include "modelnodeoperations.h" #include "modelnodeoperations.h"
#include "nodelistproperty.h" #include "nodelistproperty.h"
@@ -24,7 +25,8 @@ CreateTexture::CreateTexture(AbstractView *view, bool importFile)
ModelNode CreateTexture::execute(const QString &filePath, AddTextureMode mode, int sceneId) ModelNode CreateTexture::execute(const QString &filePath, AddTextureMode mode, int sceneId)
{ {
if (m_importFile && !addFileToProject(filePath)) Asset asset(filePath);
if (!asset.isValidTextureSource() || (m_importFile && !addFileToProject(filePath)))
return {}; return {};
ModelNode texture = createTextureFromImage(filePath, mode); ModelNode texture = createTextureFromImage(filePath, mode);
@@ -36,7 +38,7 @@ ModelNode CreateTexture::execute(const QString &filePath, AddTextureMode mode, i
QTimer::singleShot(0, m_view, [this, texture]() { QTimer::singleShot(0, m_view, [this, texture]() {
if (m_view->model()) if (m_view->model())
m_view->emitCustomNotification("selected_texture_changed", {texture}, {true}); m_view->emitCustomNotification("select_texture", {texture}, {true});
}); });
return texture; return texture;

View File

@@ -503,8 +503,7 @@ void Edit3DWidget::dragEnterEvent(QDragEnterEvent *dragEnterEvent)
|| dragEnterEvent->mimeData()->hasFormat(Constants::MIME_TYPE_BUNDLE_TEXTURE)) { || dragEnterEvent->mimeData()->hasFormat(Constants::MIME_TYPE_BUNDLE_TEXTURE)) {
const auto urls = dragEnterEvent->mimeData()->urls(); const auto urls = dragEnterEvent->mimeData()->urls();
if (!urls.isEmpty()) { if (!urls.isEmpty()) {
Asset asset(urls.first().toLocalFile()); if (Asset(urls.first().toLocalFile()).isValidTextureSource())
if (asset.isTexture3D() || asset.isImage())
dragEnterEvent->acceptProposedAction(); dragEnterEvent->acceptProposedAction();
} }
} else if (actionManager.externalDragHasSupportedAssets(dragEnterEvent->mimeData()) } else if (actionManager.externalDragHasSupportedAssets(dragEnterEvent->mimeData())

View File

@@ -164,7 +164,7 @@ WidgetInfo MaterialBrowserView::widgetInfo()
MaterialBrowserTexturesModel *texturesModel = m_widget->materialBrowserTexturesModel().data(); MaterialBrowserTexturesModel *texturesModel = m_widget->materialBrowserTexturesModel().data();
connect(texturesModel, &MaterialBrowserTexturesModel::selectedIndexChanged, this, [&] (int idx) { connect(texturesModel, &MaterialBrowserTexturesModel::selectedIndexChanged, this, [&] (int idx) {
ModelNode texNode = m_widget->materialBrowserTexturesModel()->textureAt(idx); ModelNode texNode = m_widget->materialBrowserTexturesModel()->textureAt(idx);
emitCustomNotification("selected_texture_changed", {texNode}, {}); emitCustomNotification("selected_texture_changed", {texNode});
}); });
connect(texturesModel, &MaterialBrowserTexturesModel::duplicateTextureTriggered, this, connect(texturesModel, &MaterialBrowserTexturesModel::duplicateTextureTriggered, this,
[&] (const ModelNode &texture) { [&] (const ModelNode &texture) {
@@ -499,14 +499,14 @@ void MaterialBrowserView::customNotification(const AbstractView *view,
const QList<ModelNode> &nodeList, const QList<ModelNode> &nodeList,
const QList<QVariant> &data) const QList<QVariant> &data)
{ {
if (view == this) if (view == this && identifier != "select_texture")
return; return;
if (identifier == "selected_material_changed") { if (identifier == "select_material") {
int idx = m_widget->materialBrowserModel()->materialIndex(nodeList.first()); int idx = m_widget->materialBrowserModel()->materialIndex(nodeList.first());
if (idx != -1) if (idx != -1)
m_widget->materialBrowserModel()->selectMaterial(idx); m_widget->materialBrowserModel()->selectMaterial(idx);
} else if (identifier == "selected_texture_changed") { } else if (identifier == "select_texture") {
int idx = m_widget->materialBrowserTexturesModel()->textureIndex(nodeList.first()); int idx = m_widget->materialBrowserTexturesModel()->textureIndex(nodeList.first());
if (idx != -1) { if (idx != -1) {
m_widget->materialBrowserTexturesModel()->selectTexture(idx); m_widget->materialBrowserTexturesModel()->selectTexture(idx);

View File

@@ -7,19 +7,19 @@
#include "materialbrowsertexturesmodel.h" #include "materialbrowsertexturesmodel.h"
#include "materialbrowserview.h" #include "materialbrowserview.h"
#include <assetimageprovider.h> #include "asset.h"
#include <designeractionmanager.h> #include "assetimageprovider.h"
#include <designermcumanager.h> #include "designeractionmanager.h"
#include <documentmanager.h> #include "designermcumanager.h"
#include <qmldesignerconstants.h> #include "documentmanager.h"
#include <qmldesignerplugin.h> #include "hdrimage.h"
#include <variantproperty.h> #include "qmldesignerconstants.h"
#include "qmldesignerplugin.h"
#include <theme.h> #include "theme.h"
#include "variantproperty.h"
#include <utils/algorithm.h> #include <utils/algorithm.h>
#include <utils/environment.h> #include <utils/environment.h>
#include <utils/hdrimage.h>
#include <utils/qtcassert.h> #include <utils/qtcassert.h>
#include <utils/stylehelper.h> #include <utils/stylehelper.h>
@@ -273,6 +273,13 @@ void MaterialBrowserWidget::acceptBundleMaterialDrop()
m_materialBrowserView->model()->endDrag(); m_materialBrowserView->model()->endDrag();
} }
bool MaterialBrowserWidget::hasAcceptableAssets(const QList<QUrl> &urls)
{
return Utils::anyOf(urls, [](const QUrl &url) {
return Asset(url.toLocalFile()).isValidTextureSource();
});
}
void MaterialBrowserWidget::acceptBundleTextureDrop() void MaterialBrowserWidget::acceptBundleTextureDrop()
{ {
m_materialBrowserView->emitCustomNotification("drop_bundle_texture", {}, {}); // To ContentLibraryView m_materialBrowserView->emitCustomNotification("drop_bundle_texture", {}, {}); // To ContentLibraryView
@@ -284,6 +291,8 @@ void MaterialBrowserWidget::acceptAssetsDrop(const QList<QUrl> &urls)
{ {
QStringList assetPaths = Utils::transform(urls, [](const QUrl &url) { return url.toLocalFile(); }); QStringList assetPaths = Utils::transform(urls, [](const QUrl &url) { return url.toLocalFile(); });
m_materialBrowserView->createTextures(assetPaths); m_materialBrowserView->createTextures(assetPaths);
if (m_materialBrowserView->model())
m_materialBrowserView->model()->endDrag();
} }
void MaterialBrowserWidget::acceptTextureDropOnMaterial(int matIndex, const QString &texId) void MaterialBrowserWidget::acceptTextureDropOnMaterial(int matIndex, const QString &texId)
@@ -295,6 +304,9 @@ void MaterialBrowserWidget::acceptTextureDropOnMaterial(int matIndex, const QStr
m_materialBrowserModel->selectMaterial(matIndex); m_materialBrowserModel->selectMaterial(matIndex);
m_materialBrowserView->applyTextureToMaterial({mat}, tex); m_materialBrowserView->applyTextureToMaterial({mat}, tex);
} }
if (m_materialBrowserView->model())
m_materialBrowserView->model()->endDrag();
} }
void MaterialBrowserWidget::focusMaterialSection(bool focusMatSec) void MaterialBrowserWidget::focusMaterialSection(bool focusMatSec)

View File

@@ -58,6 +58,7 @@ public:
Q_INVOKABLE void startDragMaterial(int index, const QPointF &mousePos); Q_INVOKABLE void startDragMaterial(int index, const QPointF &mousePos);
Q_INVOKABLE void startDragTexture(int index, const QPointF &mousePos); Q_INVOKABLE void startDragTexture(int index, const QPointF &mousePos);
Q_INVOKABLE void acceptBundleMaterialDrop(); Q_INVOKABLE void acceptBundleMaterialDrop();
Q_INVOKABLE bool hasAcceptableAssets(const QList<QUrl> &urls);
Q_INVOKABLE void acceptBundleTextureDrop(); Q_INVOKABLE void acceptBundleTextureDrop();
Q_INVOKABLE void acceptAssetsDrop(const QList<QUrl> &urls); Q_INVOKABLE void acceptAssetsDrop(const QList<QUrl> &urls);
Q_INVOKABLE void acceptTextureDropOnMaterial(int matIndex, const QString &texId); Q_INVOKABLE void acceptTextureDropOnMaterial(int matIndex, const QString &texId);

View File

@@ -107,9 +107,7 @@ auto makeCollectorDispatcherChain(ImageCacheCollector &nodeInstanceCollector,
[](Utils::SmallStringView filePath, [](Utils::SmallStringView filePath,
[[maybe_unused]] Utils::SmallStringView state, [[maybe_unused]] Utils::SmallStringView state,
[[maybe_unused]] const QmlDesigner::ImageCache::AuxiliaryData &auxiliaryData) { [[maybe_unused]] const QmlDesigner::ImageCache::AuxiliaryData &auxiliaryData) {
Asset asset {QString(filePath)}; return Asset{QString(filePath)}.isValidTextureSource();
Asset::Type type = asset.type();
return type == Asset::Type::Image || type == Asset::Type::Texture3D;
}, },
&textureImageCollector)); &textureImageCollector));
} }

View File

@@ -180,6 +180,11 @@ bool Asset::isSupported() const
return m_type != Asset::Type::Unknown; return m_type != Asset::Type::Unknown;
} }
bool Asset::isValidTextureSource()
{
return isImage() || isTexture3D();
}
void Asset::resolveType() void Asset::resolveType()
{ {
if (m_suffix.isEmpty()) if (m_suffix.isEmpty())

View File

@@ -52,6 +52,7 @@ public:
bool isKtxFile() const; bool isKtxFile() const;
bool isEffect() const; bool isEffect() const;
bool isSupported() const; bool isSupported() const;
bool isValidTextureSource();
private: private:
void resolveType(); void resolveType();