diff --git a/share/qtcreator/qmldesigner/materialBrowserQmlSource/TextureItem.qml b/share/qtcreator/qmldesigner/materialBrowserQmlSource/TextureItem.qml index a666354b832..00bb835826e 100644 --- a/share/qtcreator/qmldesigner/materialBrowserQmlSource/TextureItem.qml +++ b/share/qtcreator/qmldesigner/materialBrowserQmlSource/TextureItem.qml @@ -40,10 +40,10 @@ Rectangle { Image { source: "image://materialBrowserTex/" + textureSource + asynchronous: true sourceSize.width: root.width - 10 sourceSize.height: root.height - 10 anchors.centerIn: parent - cache: false smooth: true } } diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/UrlChooser.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/UrlChooser.qml index b87005fe4bb..d6373f790ab 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/UrlChooser.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/UrlChooser.qml @@ -102,8 +102,8 @@ Row { Item { visible: thumbnail.status === Image.Ready - Layout.preferredWidth: 100 - Layout.preferredHeight: 100 + Layout.preferredWidth: 96 + Layout.preferredHeight: 96 Image { id: checker @@ -116,7 +116,10 @@ Row { Image { id: thumbnail asynchronous: true - anchors.fill: parent + sourceSize.height: 96 + sourceSize.width: 96 + height: 96 + width: 96 fillMode: Image.PreserveAspectFit source: { if (root.isBuiltInPrimitive(root.absoluteFilePath)) @@ -231,8 +234,8 @@ Row { Item { visible: delegateThumbnail.status === Image.Ready - Layout.preferredWidth: 100 - Layout.preferredHeight: 100 + Layout.preferredWidth: 96 + Layout.preferredHeight: 96 Image { id: delegateChecker @@ -245,7 +248,10 @@ Row { Image { id: delegateThumbnail asynchronous: true - anchors.fill: parent + sourceSize.height: 96 + sourceSize.width: 96 + height: 96 + width: 96 fillMode: Image.PreserveAspectFit source: { if (root.isBuiltInPrimitive(delegateRoot.name)) diff --git a/share/qtcreator/qmldesigner/textureEditorQmlSource/TextureEditorTopSection.qml b/share/qtcreator/qmldesigner/textureEditorQmlSource/TextureEditorTopSection.qml index 287278d9548..016049df102 100644 --- a/share/qtcreator/qmldesigner/textureEditorQmlSource/TextureEditorTopSection.qml +++ b/share/qtcreator/qmldesigner/textureEditorQmlSource/TextureEditorTopSection.qml @@ -11,7 +11,7 @@ Column { function refreshPreview() { texturePreview.source = "" - texturePreview.source = "image://textureEditor/" + backendValues.source.valueToString + texturePreview.source = "image://qmldesigner_thumbnails/" + resolveResourcePath(backendValues.source.valueToString) } anchors.left: parent.left @@ -34,12 +34,11 @@ Column { Image { id: texturePreview - + asynchronous: true sourceSize.width: 150 sourceSize.height: 150 anchors.centerIn: parent - source: "image://textureEditor/" + backendValues.source.valueToString - cache: false + source: "image://qmldesigner_thumbnails/" + resolveResourcePath(backendValues.source.valueToString) } } } diff --git a/src/plugins/qmldesigner/components/componentcore/viewmanager.cpp b/src/plugins/qmldesigner/components/componentcore/viewmanager.cpp index 08ee673ff16..7ac6d44877e 100644 --- a/src/plugins/qmldesigner/components/componentcore/viewmanager.cpp +++ b/src/plugins/qmldesigner/components/componentcore/viewmanager.cpp @@ -69,8 +69,8 @@ public: , navigatorView{externalDependencies} , propertyEditorView(imageCache, externalDependencies) , materialEditorView{externalDependencies} - , materialBrowserView{externalDependencies} - , textureEditorView{externalDependencies} + , materialBrowserView{imageCache, externalDependencies} + , textureEditorView{imageCache, externalDependencies} , statesEditorView{externalDependencies} , newStatesEditorView{externalDependencies} {} diff --git a/src/plugins/qmldesigner/components/materialbrowser/materialbrowserview.cpp b/src/plugins/qmldesigner/components/materialbrowser/materialbrowserview.cpp index 79fc5cb4b61..0445db3ba6d 100644 --- a/src/plugins/qmldesigner/components/materialbrowser/materialbrowserview.cpp +++ b/src/plugins/qmldesigner/components/materialbrowser/materialbrowserview.cpp @@ -41,8 +41,10 @@ static QString propertyEditorResourcesPath() return Core::ICore::resourcePath("qmldesigner/propertyEditorQmlSources").toString(); } -MaterialBrowserView::MaterialBrowserView(ExternalDependenciesInterface &externalDependencies) +MaterialBrowserView::MaterialBrowserView(AsynchronousImageCache &imageCache, + ExternalDependenciesInterface &externalDependencies) : AbstractView{externalDependencies} + , m_imageCache(imageCache) { m_previewTimer.setSingleShot(true); connect(&m_previewTimer, &QTimer::timeout, this, &MaterialBrowserView::requestPreviews); @@ -59,12 +61,11 @@ bool MaterialBrowserView::hasWidget() const WidgetInfo MaterialBrowserView::widgetInfo() { if (m_widget.isNull()) { - m_widget = new MaterialBrowserWidget(this); + m_widget = new MaterialBrowserWidget(m_imageCache, this); auto matEditorContext = new Internal::MaterialBrowserContext(m_widget.data()); Core::ICore::addContextObject(matEditorContext); - // custom notifications below are sent to the MaterialEditor MaterialBrowserModel *matBrowserModel = m_widget->materialBrowserModel().data(); diff --git a/src/plugins/qmldesigner/components/materialbrowser/materialbrowserview.h b/src/plugins/qmldesigner/components/materialbrowser/materialbrowserview.h index 53ee5821b99..e8f1160f2f3 100644 --- a/src/plugins/qmldesigner/components/materialbrowser/materialbrowserview.h +++ b/src/plugins/qmldesigner/components/materialbrowser/materialbrowserview.h @@ -22,7 +22,8 @@ class MaterialBrowserView : public AbstractView Q_OBJECT public: - MaterialBrowserView(ExternalDependenciesInterface &externalDependencies); + MaterialBrowserView(class AsynchronousImageCache &imageCache, + ExternalDependenciesInterface &externalDependencies); ~MaterialBrowserView() override; bool hasWidget() const override; @@ -64,6 +65,7 @@ private: void loadPropertyGroups(); void requestPreviews(); + AsynchronousImageCache &m_imageCache; QPointer m_widget; QList m_selectedModels; // selected 3D model nodes diff --git a/src/plugins/qmldesigner/components/materialbrowser/materialbrowserwidget.cpp b/src/plugins/qmldesigner/components/materialbrowser/materialbrowserwidget.cpp index 541bb385f67..d6e990761b8 100644 --- a/src/plugins/qmldesigner/components/materialbrowser/materialbrowserwidget.cpp +++ b/src/plugins/qmldesigner/components/materialbrowser/materialbrowserwidget.cpp @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -89,33 +90,6 @@ public: } }; -class TextureImageProvider : public QQuickImageProvider -{ -public: - TextureImageProvider() : QQuickImageProvider(Pixmap) {} - - QPixmap requestPixmap(const QString &id, QSize *size, const QSize &requestedSize) override - { - QPixmap pixmap; - const QString suffix = id.split('.').last().toLower(); - if (suffix == "hdr") - pixmap = HdrImage{id}.toPixmap(); - else - pixmap = Utils::StyleHelper::dpiSpecificImageFile(id); - - if (pixmap.isNull()) - pixmap = Utils::StyleHelper::dpiSpecificImageFile(":/textureeditor/images/texture_default.png"); - - if (size) - *size = pixmap.size(); - - if (requestedSize.isValid()) - return pixmap.scaled(requestedSize, Qt::KeepAspectRatio); - - return pixmap; - } -}; - bool MaterialBrowserWidget::eventFilter(QObject *obj, QEvent *event) { if (event->type() == QEvent::FocusOut) { @@ -145,9 +119,16 @@ bool MaterialBrowserWidget::eventFilter(QObject *obj, QEvent *event) QString iconPath = QLatin1String("%1/%2") .arg(DocumentManager::currentResourcePath().path(), m_textureToDrag.variantProperty("source").value().toString()); - model->startDrag(mimeData, - m_textureImageProvider->requestPixmap(iconPath, nullptr, - {128, 128})); + + QPixmap pixmap; + const QString suffix = iconPath.split('.').last().toLower(); + if (suffix == "hdr") + pixmap = HdrImage{iconPath}.toPixmap(); + else + pixmap = Utils::StyleHelper::dpiSpecificImageFile(iconPath); + if (pixmap.isNull()) + pixmap = Utils::StyleHelper::dpiSpecificImageFile(":/textureeditor/images/texture_default.png"); + model->startDrag(mimeData, pixmap.scaled({128, 128})); } m_materialToDrag = {}; m_textureToDrag = {}; @@ -161,14 +142,18 @@ bool MaterialBrowserWidget::eventFilter(QObject *obj, QEvent *event) return QObject::eventFilter(obj, event); } -MaterialBrowserWidget::MaterialBrowserWidget(MaterialBrowserView *view) +MaterialBrowserWidget::MaterialBrowserWidget(AsynchronousImageCache &imageCache, + MaterialBrowserView *view) : m_materialBrowserView(view) , m_materialBrowserModel(new MaterialBrowserModel(this)) , m_materialBrowserTexturesModel(new MaterialBrowserTexturesModel(this)) , m_quickWidget(new QQuickWidget(this)) , m_previewImageProvider(new PreviewImageProvider()) - , m_textureImageProvider(new TextureImageProvider()) { + QImage defaultImage; + defaultImage.load(Utils::StyleHelper::dpiSpecificImageFile(":/textureeditor/images/texture_default.png")); + m_textureImageProvider = new PropertyEditorImageProvider(imageCache, defaultImage); + setWindowTitle(tr("Material Browser", "Title of material browser widget")); setMinimumWidth(120); diff --git a/src/plugins/qmldesigner/components/materialbrowser/materialbrowserwidget.h b/src/plugins/qmldesigner/components/materialbrowser/materialbrowserwidget.h index 929900d52bb..a236ce14714 100644 --- a/src/plugins/qmldesigner/components/materialbrowser/materialbrowserwidget.h +++ b/src/plugins/qmldesigner/components/materialbrowser/materialbrowserwidget.h @@ -28,14 +28,14 @@ class MaterialBrowserView; class MaterialBrowserModel; class MaterialBrowserTexturesModel; class PreviewImageProvider; -class TextureImageProvider; +class PropertyEditorImageProvider; class MaterialBrowserWidget : public QFrame { Q_OBJECT public: - MaterialBrowserWidget(MaterialBrowserView *view); + MaterialBrowserWidget(class AsynchronousImageCache &imageCache, MaterialBrowserView *view); ~MaterialBrowserWidget() = default; QList createToolBarWidgets(); @@ -72,7 +72,7 @@ private: QShortcut *m_qmlSourceUpdateShortcut = nullptr; PreviewImageProvider *m_previewImageProvider = nullptr; - TextureImageProvider *m_textureImageProvider = nullptr; + PropertyEditorImageProvider *m_textureImageProvider = nullptr; Core::IContext *m_context = nullptr; QString m_filterText; diff --git a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorimageprovider.cpp b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorimageprovider.cpp index 90dd2caaebe..e7ff48450d1 100644 --- a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorimageprovider.cpp +++ b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorimageprovider.cpp @@ -25,18 +25,25 @@ QQuickImageResponse *PropertyEditorImageProvider::requestImageResponse(const QSt return m_smallImageCacheProvider.requestImageResponse("#" + id.split('.').first(), requestedSize); - QImage image; - auto response = std::make_unique(image); + auto response = std::make_unique(m_smallImageCacheProvider.defaultImage()); QMetaObject::invokeMethod( response.get(), - [response = QPointer(response.get()), image, suffix, id] { - if (AssetsLibraryModel::supportedImageSuffixes().contains(suffix)) - response->setImage(QImage(Utils::StyleHelper::dpiSpecificImageFile(id))); - else if (AssetsLibraryModel::supportedTexture3DSuffixes().contains(suffix)) - response->setImage(HdrImage{id}.image()); - else - response->abort(); + [response = QPointer(response.get()), suffix, id, requestedSize] { + if (AssetsLibraryModel::supportedImageSuffixes().contains(suffix)) { + QImage image = QImage(Utils::StyleHelper::dpiSpecificImageFile(id)); + if (!image.isNull()) { + response->setImage(image.scaled(requestedSize, Qt::KeepAspectRatio)); + return; + } + } else if (AssetsLibraryModel::supportedTexture3DSuffixes().contains(suffix)) { + HdrImage hdr{id}; + if (!hdr.image().isNull()) { + response->setImage(hdr.image().scaled(requestedSize, Qt::KeepAspectRatio)); + return; + } + } + response->setImage(response->image().scaled(requestedSize, Qt::KeepAspectRatio)); }, Qt::QueuedConnection); diff --git a/src/plugins/qmldesigner/components/textureeditor/textureeditorcontextobject.cpp b/src/plugins/qmldesigner/components/textureeditor/textureeditorcontextobject.cpp index d358425a1a3..690e78db0a5 100644 --- a/src/plugins/qmldesigner/components/textureeditor/textureeditorcontextobject.cpp +++ b/src/plugins/qmldesigner/components/textureeditor/textureeditorcontextobject.cpp @@ -12,6 +12,7 @@ #include #include +#include #include #include @@ -334,4 +335,11 @@ void TextureEditorContextObject::goIntoComponent() DocumentManager::goIntoComponent(m_selectedTexture); } +QString TextureEditorContextObject::resolveResourcePath(const QString &path) +{ + if (Utils::FilePath::fromString(path).isAbsolutePath()) + return path; + return DocumentManager::currentResourcePath().path() + '/' + path; +} + } // QmlDesigner diff --git a/src/plugins/qmldesigner/components/textureeditor/textureeditorcontextobject.h b/src/plugins/qmldesigner/components/textureeditor/textureeditorcontextobject.h index cc479e5092e..56249382724 100644 --- a/src/plugins/qmldesigner/components/textureeditor/textureeditorcontextobject.h +++ b/src/plugins/qmldesigner/components/textureeditor/textureeditorcontextobject.h @@ -73,6 +73,7 @@ public: Q_INVOKABLE bool isBlocked(const QString &propName) const; Q_INVOKABLE void goIntoComponent(); + Q_INVOKABLE QString resolveResourcePath(const QString &path); enum ToolBarAction { ApplyToSelected, diff --git a/src/plugins/qmldesigner/components/textureeditor/textureeditorqmlbackend.cpp b/src/plugins/qmldesigner/components/textureeditor/textureeditorqmlbackend.cpp index b385afe4f37..c3bcdd7d5e7 100644 --- a/src/plugins/qmldesigner/components/textureeditor/textureeditorqmlbackend.cpp +++ b/src/plugins/qmldesigner/components/textureeditor/textureeditorqmlbackend.cpp @@ -6,6 +6,7 @@ #include "bindingproperty.h" #include "documentmanager.h" #include "nodemetainfo.h" +#include "propertyeditorimageprovider.h" #include "propertyeditorvalue.h" #include "qmldesignerconstants.h" #include "qmlobjectnode.h" @@ -41,46 +42,17 @@ static QObject *variantToQObject(const QVariant &value) namespace QmlDesigner { -class TextureEditorImageProvider : public QQuickImageProvider -{ - QPixmap m_previewPixmap; - -public: - TextureEditorImageProvider() - : QQuickImageProvider(Pixmap) {} - - QPixmap requestPixmap(const QString &id, QSize *size, const QSize &requestedSize) override - { - QPixmap pixmap; - const QString suffix = id.split('.').last().toLower(); - const QString path = DocumentManager::currentResourcePath().path() + '/' + id; - if (suffix == "hdr") - pixmap = HdrImage{path}.toPixmap(); - else - pixmap = Utils::StyleHelper::dpiSpecificImageFile(path); - - if (pixmap.isNull()) - pixmap = Utils::StyleHelper::dpiSpecificImageFile(":/textureeditor/images/texture_default.png"); - - if (size) - *size = pixmap.size(); - - if (requestedSize.isValid()) - return pixmap.scaled(requestedSize, Qt::KeepAspectRatio); - - return pixmap; - } -}; - -TextureEditorQmlBackend::TextureEditorQmlBackend(TextureEditorView *textureEditor) +TextureEditorQmlBackend::TextureEditorQmlBackend(TextureEditorView *textureEditor, AsynchronousImageCache &imageCache) : m_view(new QQuickWidget) , m_textureEditorTransaction(new TextureEditorTransaction(textureEditor)) , m_contextObject(new TextureEditorContextObject(m_view->rootContext())) - , m_textureEditorImageProvider(new TextureEditorImageProvider()) { + QImage defaultImage; + defaultImage.load(Utils::StyleHelper::dpiSpecificImageFile(":/textureeditor/images/texture_default.png")); + m_textureEditorImageProvider = new PropertyEditorImageProvider(imageCache, defaultImage); m_view->setResizeMode(QQuickWidget::SizeRootObjectToView); m_view->engine()->addImportPath(propertyEditorResourcesPath() + "/imports"); - m_view->engine()->addImageProvider("textureEditor", m_textureEditorImageProvider); + m_view->engine()->addImageProvider("qmldesigner_thumbnails", m_textureEditorImageProvider); m_contextObject->setBackendValues(&m_backendValuesPropertyMap); m_contextObject->setModel(textureEditor->model()); context()->setContextObject(m_contextObject.data()); diff --git a/src/plugins/qmldesigner/components/textureeditor/textureeditorqmlbackend.h b/src/plugins/qmldesigner/components/textureeditor/textureeditorqmlbackend.h index fab25c6d586..2d0131cc9fc 100644 --- a/src/plugins/qmldesigner/components/textureeditor/textureeditorqmlbackend.h +++ b/src/plugins/qmldesigner/components/textureeditor/textureeditorqmlbackend.h @@ -17,6 +17,7 @@ QT_END_NAMESPACE namespace QmlDesigner { +class PropertyEditorImageProvider; class TextureEditorContextObject; class TextureEditorImageProvider; class TextureEditorTransaction; @@ -27,7 +28,8 @@ class TextureEditorQmlBackend Q_DISABLE_COPY(TextureEditorQmlBackend) public: - TextureEditorQmlBackend(TextureEditorView *materialEditor); + TextureEditorQmlBackend(TextureEditorView *materialEditor, + class AsynchronousImageCache &imageCache); ~TextureEditorQmlBackend(); void setup(const QmlObjectNode &selectedTextureNode, const QString &stateName, const QUrl &qmlSpecificsFile, @@ -63,7 +65,7 @@ private: DesignerPropertyMap m_backendValuesPropertyMap; QScopedPointer m_textureEditorTransaction; QScopedPointer m_contextObject; - TextureEditorImageProvider *m_textureEditorImageProvider = nullptr; + PropertyEditorImageProvider *m_textureEditorImageProvider = nullptr; }; } // namespace QmlDesigner diff --git a/src/plugins/qmldesigner/components/textureeditor/textureeditorview.cpp b/src/plugins/qmldesigner/components/textureeditor/textureeditorview.cpp index 67779743da6..b1d3c210ecb 100644 --- a/src/plugins/qmldesigner/components/textureeditor/textureeditorview.cpp +++ b/src/plugins/qmldesigner/components/textureeditor/textureeditorview.cpp @@ -49,8 +49,10 @@ namespace QmlDesigner { -TextureEditorView::TextureEditorView(ExternalDependenciesInterface &externalDependencies) +TextureEditorView::TextureEditorView(AsynchronousImageCache &imageCache, + ExternalDependenciesInterface &externalDependencies) : AbstractView{externalDependencies} + , m_imageCache(imageCache) , m_stackedWidget(new QStackedWidget) , m_dynamicPropertiesModel(new Internal::DynamicPropertiesModel(true, this)) { @@ -432,7 +434,7 @@ void TextureEditorView::setupQmlBackend() QString currentStateName = currentState().isBaseState() ? currentState().name() : "invalid state"; if (!currentQmlBackend) { - currentQmlBackend = new TextureEditorQmlBackend(this); + currentQmlBackend = new TextureEditorQmlBackend(this, m_imageCache); m_stackedWidget->addWidget(currentQmlBackend->widget()); m_qmlBackendHash.insert(qmlPaneUrl.toString(), currentQmlBackend); diff --git a/src/plugins/qmldesigner/components/textureeditor/textureeditorview.h b/src/plugins/qmldesigner/components/textureeditor/textureeditorview.h index 8e5c175e853..39586cd8425 100644 --- a/src/plugins/qmldesigner/components/textureeditor/textureeditorview.h +++ b/src/plugins/qmldesigner/components/textureeditor/textureeditorview.h @@ -31,7 +31,8 @@ class TextureEditorView : public AbstractView Q_OBJECT public: - TextureEditorView(ExternalDependenciesInterface &externalDependencies); + TextureEditorView(class AsynchronousImageCache &imageCache, + ExternalDependenciesInterface &externalDependencies); ~TextureEditorView() override; bool hasWidget() const override; @@ -105,6 +106,7 @@ private: bool noValidSelection() const; + AsynchronousImageCache &m_imageCache; ModelNode m_selectedTexture; QTimer m_ensureMatLibTimer; QShortcut *m_updateShortcut = nullptr; diff --git a/src/plugins/qmldesigner/designercore/imagecache/imagecachecollector.cpp b/src/plugins/qmldesigner/designercore/imagecache/imagecachecollector.cpp index be176760491..d762299f1cb 100644 --- a/src/plugins/qmldesigner/designercore/imagecache/imagecachecollector.cpp +++ b/src/plugins/qmldesigner/designercore/imagecache/imagecachecollector.cpp @@ -14,6 +14,7 @@ #include #include +#include #include namespace QmlDesigner { @@ -103,7 +104,11 @@ void ImageCacheCollector::start(Utils::SmallStringView name, auto callback = [=, captureCallback = std::move(captureCallback)](const QImage &image) { if (nullImageHandling == ImageCacheCollectorNullImageHandling::CaptureNullImage || !image.isNull()) { - QSize smallImageSize = image.size().scaled(QSize{96, 96}.boundedTo(image.size()), + QSize targetSize {96, 96}; + const qreal ratio = qGuiApp->devicePixelRatio(); + if (ratio > 1.0) + targetSize *= qRound(ratio); + QSize smallImageSize = image.size().scaled(targetSize.boundedTo(image.size()), Qt::KeepAspectRatio); QImage smallImage = image.isNull() ? QImage{} : image.scaled(smallImageSize, diff --git a/src/plugins/qmldesigner/designercore/imagecache/smallimagecacheprovider.h b/src/plugins/qmldesigner/designercore/imagecache/smallimagecacheprovider.h index 1a608c626c9..54b3b63f1d5 100644 --- a/src/plugins/qmldesigner/designercore/imagecache/smallimagecacheprovider.h +++ b/src/plugins/qmldesigner/designercore/imagecache/smallimagecacheprovider.h @@ -20,6 +20,7 @@ public: QQuickTextureFactory *textureFactory() const override; void setImage(const QImage &image); + QImage image() const { return m_image; } void abort(); @@ -37,6 +38,7 @@ public: QQuickImageResponse *requestImageResponse(const QString &id, const QSize &requestedSize) override; + QImage defaultImage() const { return m_defaultImage; } private: AsynchronousImageCache &m_cache;