forked from qt-creator/qt-creator
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:
@@ -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"
|
||||||
|
@@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -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();
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -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()
|
||||||
|
@@ -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);
|
||||||
|
@@ -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});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -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;
|
||||||
|
@@ -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())
|
||||||
|
@@ -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);
|
||||||
|
@@ -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)
|
||||||
|
@@ -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);
|
||||||
|
@@ -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));
|
||||||
}
|
}
|
||||||
|
@@ -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())
|
||||||
|
@@ -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();
|
||||||
|
Reference in New Issue
Block a user