QmlDesigner: Add navigator preview tooltip for materials

Request 3D preview image for material instances from puppet
to show on tooltip.

Support for effect previews is also done, but handler for it is not
registered, as effects cannot be shared between windows due to
issue QTBUG-86616.

Also refactored the preview image support out of navigator
to make it more accessible by other components.

Change-Id: Ie08ba218f929660c2e43d39578997a5a1a883efd
Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io>
This commit is contained in:
Miikka Heikkinen
2020-09-10 16:02:31 +03:00
parent f849bd1105
commit 90d9cb36f3
47 changed files with 848 additions and 103 deletions

View File

@@ -34,7 +34,8 @@ HEADERS += $$PWD/synchronizecommand.h \ \
$$PWD/update3dviewstatecommand.h \ $$PWD/update3dviewstatecommand.h \
$$PWD/puppettocreatorcommand.h \ $$PWD/puppettocreatorcommand.h \
$$PWD/inputeventcommand.h \ $$PWD/inputeventcommand.h \
$$PWD/view3dactioncommand.h $$PWD/view3dactioncommand.h \
$$PWD/requestmodelnodepreviewimagecommand.h
SOURCES += $$PWD/synchronizecommand.cpp \ SOURCES += $$PWD/synchronizecommand.cpp \
$$PWD/changepreviewimagesizecommand.cpp \ $$PWD/changepreviewimagesizecommand.cpp \
@@ -68,4 +69,5 @@ SOURCES += $$PWD/synchronizecommand.cpp \
$$PWD/update3dviewstatecommand.cpp \ $$PWD/update3dviewstatecommand.cpp \
$$PWD/puppettocreatorcommand.cpp \ $$PWD/puppettocreatorcommand.cpp \
$$PWD/inputeventcommand.cpp \ $$PWD/inputeventcommand.cpp \
$$PWD/view3dactioncommand.cpp $$PWD/view3dactioncommand.cpp \
$$PWD/requestmodelnodepreviewimagecommand.cpp

View File

@@ -34,7 +34,7 @@ namespace QmlDesigner {
class PuppetToCreatorCommand class PuppetToCreatorCommand
{ {
public: public:
enum Type { Edit3DToolState, Render3DView, ActiveSceneChanged, None }; enum Type { Edit3DToolState, Render3DView, ActiveSceneChanged, RenderModelNodePreviewImage, None };
PuppetToCreatorCommand(Type type, const QVariant &data); PuppetToCreatorCommand(Type type, const QVariant &data);
PuppetToCreatorCommand() = default; PuppetToCreatorCommand() = default;

View File

@@ -0,0 +1,73 @@
/****************************************************************************
**
** Copyright (C) 2020 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#include "requestmodelnodepreviewimagecommand.h"
#include <QDataStream>
#include <QDebug>
namespace QmlDesigner {
RequestModelNodePreviewImageCommand::RequestModelNodePreviewImageCommand() = default;
RequestModelNodePreviewImageCommand::RequestModelNodePreviewImageCommand(qint32 id, const QSize &size)
: m_instanceId(id)
, m_size(size)
{
}
qint32 RequestModelNodePreviewImageCommand::instanceId() const
{
return m_instanceId;
}
QSize QmlDesigner::RequestModelNodePreviewImageCommand::size() const
{
return m_size;
}
QDataStream &operator<<(QDataStream &out, const RequestModelNodePreviewImageCommand &command)
{
out << int(command.instanceId());
out << command.size();
return out;
}
QDataStream &operator>>(QDataStream &in, RequestModelNodePreviewImageCommand &command)
{
in >> command.m_instanceId;
in >> command.m_size;
return in;
}
QDebug operator <<(QDebug debug, const RequestModelNodePreviewImageCommand &command)
{
return debug.nospace() << "RequestModelNodePreviewImageCommand("
<< "instanceId: " << command.instanceId() << ", "
<< "size: " << command.size() << ")";
}
} // namespace QmlDesigner

View File

@@ -0,0 +1,60 @@
/****************************************************************************
**
** Copyright (C) 2020 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#pragma once
#include <QtCore/qmetatype.h>
#include <QtCore/qdatastream.h>
#include <QtGui/qevent.h>
#include "instancecontainer.h"
namespace QmlDesigner {
class RequestModelNodePreviewImageCommand
{
friend QDataStream &operator>>(QDataStream &in, RequestModelNodePreviewImageCommand &command);
friend QDebug operator <<(QDebug debug, const RequestModelNodePreviewImageCommand &command);
public:
RequestModelNodePreviewImageCommand();
explicit RequestModelNodePreviewImageCommand(qint32 id, const QSize &size);
qint32 instanceId() const;
QSize size() const;
private:
qint32 m_instanceId;
QSize m_size;
};
QDataStream &operator<<(QDataStream &out, const RequestModelNodePreviewImageCommand &command);
QDataStream &operator>>(QDataStream &in, RequestModelNodePreviewImageCommand &command);
QDebug operator <<(QDebug debug, const RequestModelNodePreviewImageCommand &command);
} // namespace QmlDesigner
Q_DECLARE_METATYPE(QmlDesigner::RequestModelNodePreviewImageCommand)

View File

@@ -75,6 +75,7 @@
#include "update3dviewstatecommand.h" #include "update3dviewstatecommand.h"
#include "valueschangedcommand.h" #include "valueschangedcommand.h"
#include "view3dactioncommand.h" #include "view3dactioncommand.h"
#include "requestmodelnodepreviewimagecommand.h"
namespace QmlDesigner { namespace QmlDesigner {
@@ -339,6 +340,11 @@ void NodeInstanceClientProxy::view3DAction(const View3DActionCommand &command)
nodeInstanceServer()->view3DAction(command); nodeInstanceServer()->view3DAction(command);
} }
void NodeInstanceClientProxy::requestModelNodePreviewImage(const RequestModelNodePreviewImageCommand &command)
{
nodeInstanceServer()->requestModelNodePreviewImage(command);
}
void NodeInstanceClientProxy::changeLanguage(const ChangeLanguageCommand &command) void NodeInstanceClientProxy::changeLanguage(const ChangeLanguageCommand &command)
{ {
nodeInstanceServer()->changeLanguage(command); nodeInstanceServer()->changeLanguage(command);
@@ -516,6 +522,7 @@ void NodeInstanceClientProxy::dispatchCommand(const QVariant &command)
static const int changeSelectionCommandType = QMetaType::type("ChangeSelectionCommand"); static const int changeSelectionCommandType = QMetaType::type("ChangeSelectionCommand");
static const int inputEventCommandType = QMetaType::type("InputEventCommand"); static const int inputEventCommandType = QMetaType::type("InputEventCommand");
static const int view3DActionCommandType = QMetaType::type("View3DActionCommand"); static const int view3DActionCommandType = QMetaType::type("View3DActionCommand");
static const int requestModelNodePreviewImageCommandType = QMetaType::type("RequestModelNodePreviewImageCommand");
static const int changeLanguageCommand = QMetaType::type("ChangeLanguageCommand"); static const int changeLanguageCommand = QMetaType::type("ChangeLanguageCommand");
static const int changePreviewImageSizeCommand = QMetaType::type( static const int changePreviewImageSizeCommand = QMetaType::type(
"ChangePreviewImageSizeCommand"); "ChangePreviewImageSizeCommand");
@@ -562,6 +569,8 @@ void NodeInstanceClientProxy::dispatchCommand(const QVariant &command)
redirectToken(command.value<EndPuppetCommand>()); redirectToken(command.value<EndPuppetCommand>());
else if (commandType == view3DActionCommandType) else if (commandType == view3DActionCommandType)
view3DAction(command.value<View3DActionCommand>()); view3DAction(command.value<View3DActionCommand>());
else if (commandType == requestModelNodePreviewImageCommandType)
requestModelNodePreviewImage(command.value<RequestModelNodePreviewImageCommand>());
else if (commandType == synchronizeCommandType) { else if (commandType == synchronizeCommandType) {
SynchronizeCommand synchronizeCommand = command.value<SynchronizeCommand>(); SynchronizeCommand synchronizeCommand = command.value<SynchronizeCommand>();
m_synchronizeId = synchronizeCommand.synchronizeId(); m_synchronizeId = synchronizeCommand.synchronizeId();

View File

@@ -63,6 +63,7 @@ class ChangeSelectionCommand;
class PuppetToCreatorCommand; class PuppetToCreatorCommand;
class InputEventCommand; class InputEventCommand;
class View3DActionCommand; class View3DActionCommand;
class RequestModelNodePreviewImageCommand;
class ChangeLanguageCommand; class ChangeLanguageCommand;
class ChangePreviewImageSizeCommand; class ChangePreviewImageSizeCommand;
@@ -123,6 +124,7 @@ protected:
static QVariant readCommandFromIOStream(QIODevice *ioDevice, quint32 *readCommandCounter, quint32 *blockSize); static QVariant readCommandFromIOStream(QIODevice *ioDevice, quint32 *readCommandCounter, quint32 *blockSize);
void inputEvent(const InputEventCommand &command); void inputEvent(const InputEventCommand &command);
void view3DAction(const View3DActionCommand &command); void view3DAction(const View3DActionCommand &command);
void requestModelNodePreviewImage(const RequestModelNodePreviewImageCommand &command);
void changeLanguage(const ChangeLanguageCommand &command); void changeLanguage(const ChangeLanguageCommand &command);
void changePreviewImageSize(const ChangePreviewImageSizeCommand &command); void changePreviewImageSize(const ChangePreviewImageSizeCommand &command);

View File

@@ -67,6 +67,7 @@
#include "update3dviewstatecommand.h" #include "update3dviewstatecommand.h"
#include "valueschangedcommand.h" #include "valueschangedcommand.h"
#include "view3dactioncommand.h" #include "view3dactioncommand.h"
#include "requestmodelnodepreviewimagecommand.h"
#include <enumeration.h> #include <enumeration.h>
@@ -213,6 +214,9 @@ void NodeInstanceServerInterface::registerCommands()
qRegisterMetaType<View3DActionCommand>("View3DActionCommand"); qRegisterMetaType<View3DActionCommand>("View3DActionCommand");
qRegisterMetaTypeStreamOperators<View3DActionCommand>("View3DActionCommand"); qRegisterMetaTypeStreamOperators<View3DActionCommand>("View3DActionCommand");
qRegisterMetaType<RequestModelNodePreviewImageCommand>("RequestModelNodePreviewImageCommand");
qRegisterMetaTypeStreamOperators<RequestModelNodePreviewImageCommand>("RequestModelNodePreviewImageCommand");
qRegisterMetaType<QPair<int, int>>("QPairIntInt"); qRegisterMetaType<QPair<int, int>>("QPairIntInt");
qRegisterMetaTypeStreamOperators<QPair<int, int>>("QPairIntInt"); qRegisterMetaTypeStreamOperators<QPair<int, int>>("QPairIntInt");

View File

@@ -53,6 +53,7 @@ class RemoveSharedMemoryCommand;
class ChangeSelectionCommand; class ChangeSelectionCommand;
class InputEventCommand; class InputEventCommand;
class View3DActionCommand; class View3DActionCommand;
class RequestModelNodePreviewImageCommand;
class ChangeLanguageCommand; class ChangeLanguageCommand;
class ChangePreviewImageSizeCommand; class ChangePreviewImageSizeCommand;
@@ -82,6 +83,7 @@ public:
virtual void changeSelection(const ChangeSelectionCommand &command) = 0; virtual void changeSelection(const ChangeSelectionCommand &command) = 0;
virtual void inputEvent(const InputEventCommand &command) = 0; virtual void inputEvent(const InputEventCommand &command) = 0;
virtual void view3DAction(const View3DActionCommand &command) = 0; virtual void view3DAction(const View3DActionCommand &command) = 0;
virtual void requestModelNodePreviewImage(const RequestModelNodePreviewImageCommand &command) = 0;
virtual void changeLanguage(const ChangeLanguageCommand &command) = 0; virtual void changeLanguage(const ChangeLanguageCommand &command) = 0;
virtual void changePreviewImageSize(const ChangePreviewImageSizeCommand &command) = 0; virtual void changePreviewImageSize(const ChangePreviewImageSizeCommand &command) = 0;

View File

@@ -0,0 +1,65 @@
/****************************************************************************
**
** Copyright (C) 2020 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
import QtQuick3D 1.15
import QtQuick3D.Effects 1.15
View3D {
id: root
anchors.fill: parent
environment: sceneEnv
property Effect previewEffect
SceneEnvironment {
id: sceneEnv
antialiasingMode: SceneEnvironment.MSAA
antialiasingQuality: SceneEnvironment.High
effects: previewEffect
}
Node {
DirectionalLight {
eulerRotation.x: -30
eulerRotation.y: -30
}
PerspectiveCamera {
z: 120
clipFar: 1000
clipNear: 1
}
Model {
id: model
source: "#Sphere"
materials: [
DefaultMaterial {
diffuseColor: "green"
}
]
}
}
}

View File

@@ -0,0 +1,59 @@
/****************************************************************************
**
** Copyright (C) 2020 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
import QtQuick3D 1.15
View3D {
id: root
anchors.fill: parent
environment: sceneEnv
property Material previewMaterial
SceneEnvironment {
id: sceneEnv
antialiasingMode: SceneEnvironment.MSAA
antialiasingQuality: SceneEnvironment.High
}
Node {
DirectionalLight {
eulerRotation.x: -30
eulerRotation.y: -30
}
PerspectiveCamera {
z: 120
clipFar: 1000
clipNear: 1
}
Model {
id: model
source: "#Sphere"
materials: previewMaterial
}
}
}

View File

@@ -0,0 +1,96 @@
/****************************************************************************
**
** Copyright (C) 2020 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
import QtQuick 2.15
import QtQuick3D 1.15
import QtQuick3D.Effects 1.15
Item {
id: root
width: 150
height: 150
visible: true
property View3D view: null
property alias contentItem: contentItem
property var materialViewComponent
property var effectViewComponent
function destroyView()
{
if (view) {
// Destroy is async, so make sure we don't get any more updates for the old view
_generalHelper.enableItemUpdate(view, false);
view.destroy();
}
}
function createViewForObject(obj, w, h)
{
width = w;
height = h;
if (obj instanceof Material)
createViewForMaterial(obj);
else if (obj instanceof Effect)
createViewForEffect(obj);
}
function createViewForMaterial(material)
{
if (!materialViewComponent)
materialViewComponent = Qt.createComponent("MaterialNodeView.qml");
// Always recreate the view to ensure material is up to date
if (materialViewComponent.status === Component.Ready)
view = materialViewComponent.createObject(viewRect, {"previewMaterial": material});
}
function createViewForEffect(effect)
{
if (!effectViewComponent)
effectViewComponent = Qt.createComponent("EffectNodeView.qml");
// Always recreate the view to ensure effect is up to date
if (effectViewComponent.status === Component.Ready)
view = effectViewComponent.createObject(viewRect, {"previewEffect": effect});
}
Item {
id: contentItem
anchors.fill: parent
Rectangle {
id: viewRect
anchors.fill: parent
gradient: Gradient {
GradientStop { position: 1.0; color: "#222222" }
GradientStop { position: 0.0; color: "#999999" }
}
}
}
}

View File

@@ -69,6 +69,7 @@
#include <changeselectioncommand.h> #include <changeselectioncommand.h>
#include <inputeventcommand.h> #include <inputeventcommand.h>
#include <view3dactioncommand.h> #include <view3dactioncommand.h>
#include <requestmodelnodepreviewimagecommand.h>
#include <changelanguagecommand.h> #include <changelanguagecommand.h>
#include <QDebug> #include <QDebug>
@@ -1417,6 +1418,11 @@ void NodeInstanceServer::view3DAction(const View3DActionCommand &command)
Q_UNUSED(command) Q_UNUSED(command)
} }
void NodeInstanceServer::requestModelNodePreviewImage(const RequestModelNodePreviewImageCommand &command)
{
Q_UNUSED(command)
}
void NodeInstanceServer::changeLanguage(const ChangeLanguageCommand &command) void NodeInstanceServer::changeLanguage(const ChangeLanguageCommand &command)
{ {
setTranslationLanguage(command.language); setTranslationLanguage(command.language);

View File

@@ -152,6 +152,7 @@ public:
void changeSelection(const ChangeSelectionCommand &command) override; void changeSelection(const ChangeSelectionCommand &command) override;
void inputEvent(const InputEventCommand &command) override; void inputEvent(const InputEventCommand &command) override;
void view3DAction(const View3DActionCommand &command) override; void view3DAction(const View3DActionCommand &command) override;
void requestModelNodePreviewImage(const RequestModelNodePreviewImageCommand &command) override;
void changeLanguage(const ChangeLanguageCommand &command) override; void changeLanguage(const ChangeLanguageCommand &command) override;
void changePreviewImageSize(const ChangePreviewImageSizeCommand &command) override; void changePreviewImageSize(const ChangePreviewImageSizeCommand &command) override;

View File

@@ -158,6 +158,12 @@ void NodeInstanceServerDispatcher::view3DAction(const View3DActionCommand &comma
server->view3DAction(command); server->view3DAction(command);
} }
void NodeInstanceServerDispatcher::requestModelNodePreviewImage(const RequestModelNodePreviewImageCommand &command)
{
for (std::unique_ptr<NodeInstanceServer> &server : m_servers)
server->requestModelNodePreviewImage(command);
}
void NodeInstanceServerDispatcher::changeLanguage(const ChangeLanguageCommand &command) void NodeInstanceServerDispatcher::changeLanguage(const ChangeLanguageCommand &command)
{ {
for (std::unique_ptr<NodeInstanceServer> &server : m_servers) for (std::unique_ptr<NodeInstanceServer> &server : m_servers)

View File

@@ -58,6 +58,7 @@ public:
void changeSelection(const ChangeSelectionCommand &command); void changeSelection(const ChangeSelectionCommand &command);
void inputEvent(const InputEventCommand &command); void inputEvent(const InputEventCommand &command);
void view3DAction(const View3DActionCommand &command); void view3DAction(const View3DActionCommand &command);
void requestModelNodePreviewImage(const RequestModelNodePreviewImageCommand &command);
void changeLanguage(const ChangeLanguageCommand &command); void changeLanguage(const ChangeLanguageCommand &command);
void changePreviewImageSize(const ChangePreviewImageSizeCommand &command); void changePreviewImageSize(const ChangePreviewImageSizeCommand &command);

View File

@@ -62,6 +62,7 @@
#include "puppettocreatorcommand.h" #include "puppettocreatorcommand.h"
#include "inputeventcommand.h" #include "inputeventcommand.h"
#include "view3dactioncommand.h" #include "view3dactioncommand.h"
#include "requestmodelnodepreviewimagecommand.h"
#include "dummycontextobject.h" #include "dummycontextobject.h"
#include "../editor3d/generalhelper.h" #include "../editor3d/generalhelper.h"
@@ -145,13 +146,35 @@ void Qt5InformationNodeInstanceServer::createEditView3D()
this, &Qt5InformationNodeInstanceServer::handleObjectPropertyChangeTimeout); this, &Qt5InformationNodeInstanceServer::handleObjectPropertyChangeTimeout);
QObject::connect(&m_selectionChangeTimer, &QTimer::timeout, QObject::connect(&m_selectionChangeTimer, &QTimer::timeout,
this, &Qt5InformationNodeInstanceServer::handleSelectionChangeTimeout); this, &Qt5InformationNodeInstanceServer::handleSelectionChangeTimeout);
QObject::connect(&m_renderTimer, &QTimer::timeout, QObject::connect(&m_render3DEditViewTimer, &QTimer::timeout,
this, &Qt5InformationNodeInstanceServer::doRender3DEditView); this, &Qt5InformationNodeInstanceServer::doRender3DEditView);
QObject::connect(&m_renderModelNode3DImageViewTimer, &QTimer::timeout,
this, &Qt5InformationNodeInstanceServer::doRenderModelNode3DImageView);
helper->setParent(m_editView3DRootItem); helper->setParent(m_editView3DRootItem);
#endif #endif
} }
void Qt5InformationNodeInstanceServer::create3DPreviewView()
{
#ifdef QUICK3D_MODULE
// This function assumes createEditView3D() has been called previously
m_ModelNode3DImageView = new QQuickView(quickView()->engine(), quickView());
m_ModelNode3DImageView->setFormat(quickView()->format());
DesignerSupport::createOpenGLContext(m_ModelNode3DImageView.data());
QQmlComponent component(engine());
component.loadUrl(QUrl("qrc:/qtquickplugin/mockfiles/ModelNode3DImageView.qml"));
m_ModelNode3DImageViewRootItem = qobject_cast<QQuickItem *>(component.create());
if (!m_ModelNode3DImageViewRootItem) {
qWarning() << "Could not create ModelNode preview image 3D view: " << component.errors();
return;
}
DesignerSupport::setRootItem(m_ModelNode3DImageView, m_ModelNode3DImageViewRootItem);
#endif
}
// The selection has changed in the edit view 3D. Empty list indicates selection is cleared. // The selection has changed in the edit view 3D. Empty list indicates selection is cleared.
void Qt5InformationNodeInstanceServer::handleSelectionChanged(const QVariant &objs) void Qt5InformationNodeInstanceServer::handleSelectionChanged(const QVariant &objs)
{ {
@@ -440,31 +463,37 @@ ServerNodeInstance Qt5InformationNodeInstanceServer::active3DSceneInstance() con
return sceneInstance; return sceneInstance;
} }
void Qt5InformationNodeInstanceServer::updateNodesRecursive(QQuickItem *item)
{
for (QQuickItem *childItem : item->childItems())
updateNodesRecursive(childItem);
DesignerSupport::updateDirtyNode(item);
}
QQuickItem *Qt5InformationNodeInstanceServer::getContentItemForRendering(QQuickItem *rootItem)
{
QQuickItem *contentItem = QQmlProperty::read(rootItem, "contentItem").value<QQuickItem *>();
if (contentItem) {
designerSupport()->refFromEffectItem(contentItem, false);
QmlDesigner::Internal::QmlPrivateGate::disableNativeTextRendering(contentItem);
}
return contentItem;
}
void Qt5InformationNodeInstanceServer::render3DEditView(int count) void Qt5InformationNodeInstanceServer::render3DEditView(int count)
{ {
m_needRender = qMax(count, m_needRender); m_need3DEditViewRender = qMax(count, m_need3DEditViewRender);
if (!m_renderTimer.isActive()) if (!m_render3DEditViewTimer.isActive())
m_renderTimer.start(0); m_render3DEditViewTimer.start(0);
} }
// render the 3D edit view and send the result to creator process // render the 3D edit view and send the result to creator process
void Qt5InformationNodeInstanceServer::doRender3DEditView() void Qt5InformationNodeInstanceServer::doRender3DEditView()
{ {
if (m_editView3DRootItem) { if (m_editView3DRootItem) {
if (!m_editView3DContentItem) { if (!m_editView3DContentItem)
m_editView3DContentItem = QQmlProperty::read(m_editView3DRootItem, "contentItem").value<QQuickItem *>(); m_editView3DContentItem = getContentItemForRendering(m_editView3DRootItem);
if (m_editView3DContentItem) {
designerSupport()->refFromEffectItem(m_editView3DContentItem, false);
QmlDesigner::Internal::QmlPrivateGate::disableNativeTextRendering(m_editView3DContentItem);
}
}
std::function<void (QQuickItem *)> updateNodesRecursive;
updateNodesRecursive = [&updateNodesRecursive](QQuickItem *item) {
for (QQuickItem *childItem : item->childItems())
updateNodesRecursive(childItem);
DesignerSupport::updateDirtyNode(item);
};
updateNodesRecursive(m_editView3DContentItem); updateNodesRecursive(m_editView3DContentItem);
// Fake render loop signaling to update things like QML items as 3D textures // Fake render loop signaling to update things like QML items as 3D textures
@@ -480,26 +509,69 @@ void Qt5InformationNodeInstanceServer::doRender3DEditView()
// There's no instance related to image, so instance id is -1. // There's no instance related to image, so instance id is -1.
// Key number is selected so that it is unlikely to conflict other ImageContainer use. // Key number is selected so that it is unlikely to conflict other ImageContainer use.
const qint32 edit3DKey = 2100000000; auto imgContainer = ImageContainer(-1, renderImage, 2100000000);
auto imgContainer = ImageContainer(-1, renderImage, edit3DKey);
// send the rendered image to creator process // send the rendered image to creator process
nodeInstanceClient()->handlePuppetToCreatorCommand({PuppetToCreatorCommand::Render3DView, nodeInstanceClient()->handlePuppetToCreatorCommand({PuppetToCreatorCommand::Render3DView,
QVariant::fromValue(imgContainer)}); QVariant::fromValue(imgContainer)});
if (m_needRender > 0) { if (m_need3DEditViewRender > 0) {
m_renderTimer.start(0); m_render3DEditViewTimer.start(0);
--m_needRender; --m_need3DEditViewRender;
} }
} }
} }
void Qt5InformationNodeInstanceServer::renderModelNode3DImageView()
{
if (!m_renderModelNode3DImageViewTimer.isActive())
m_renderModelNode3DImageViewTimer.start(0);
}
void Qt5InformationNodeInstanceServer::doRenderModelNode3DImageView()
{
if (m_ModelNode3DImageViewRootItem) {
if (!m_ModelNode3DImageViewContentItem)
m_ModelNode3DImageViewContentItem = getContentItemForRendering(m_ModelNode3DImageViewRootItem);
ServerNodeInstance instance = instanceForId(m_modelNodelPreviewImageCommand.instanceId());
QObject *instanceObj = instance.internalObject();
QSize renderSize = m_modelNodelPreviewImageCommand.size() * 2;
QMetaObject::invokeMethod(m_ModelNode3DImageViewRootItem, "createViewForObject",
Q_ARG(QVariant, objectToVariant(instanceObj)),
Q_ARG(QVariant, QVariant::fromValue(renderSize.width())),
Q_ARG(QVariant, QVariant::fromValue(renderSize.height())));
updateNodesRecursive(m_ModelNode3DImageViewContentItem);
// Fake render loop signaling to update things like QML items as 3D textures
m_editView3D->beforeSynchronizing();
m_editView3D->beforeRendering();
QSizeF size = qobject_cast<QQuickItem *>(m_ModelNode3DImageViewContentItem)->size();
QRectF renderRect(QPointF(0., 0.), size);
QImage renderImage = designerSupport()->renderImageForItem(m_ModelNode3DImageViewContentItem,
renderRect, size.toSize());
m_editView3D->afterRendering();
QMetaObject::invokeMethod(m_ModelNode3DImageViewRootItem, "destroyView");
// Key number is selected so that it is unlikely to conflict other ImageContainer use.
auto imgContainer = ImageContainer(m_modelNodelPreviewImageCommand.instanceId(), renderImage, 2100000001);
// send the rendered image to creator process
nodeInstanceClient()->handlePuppetToCreatorCommand({PuppetToCreatorCommand::RenderModelNodePreviewImage,
QVariant::fromValue(imgContainer)});
}
}
Qt5InformationNodeInstanceServer::Qt5InformationNodeInstanceServer(NodeInstanceClientInterface *nodeInstanceClient) : Qt5InformationNodeInstanceServer::Qt5InformationNodeInstanceServer(NodeInstanceClientInterface *nodeInstanceClient) :
Qt5NodeInstanceServer(nodeInstanceClient) Qt5NodeInstanceServer(nodeInstanceClient)
{ {
m_propertyChangeTimer.setInterval(100); m_propertyChangeTimer.setInterval(100);
m_propertyChangeTimer.setSingleShot(true); m_propertyChangeTimer.setSingleShot(true);
m_selectionChangeTimer.setSingleShot(true); m_selectionChangeTimer.setSingleShot(true);
m_renderTimer.setSingleShot(true); m_render3DEditViewTimer.setSingleShot(true);
m_renderModelNode3DImageViewTimer.setSingleShot(true);
} }
void Qt5InformationNodeInstanceServer::sendTokenBack() void Qt5InformationNodeInstanceServer::sendTokenBack()
@@ -815,6 +887,7 @@ void Qt5InformationNodeInstanceServer::setup3DEditView(const QList<ServerNodeIns
add3DScenes(instanceList); add3DScenes(instanceList);
createEditView3D(); createEditView3D();
create3DPreviewView();
QString lastSceneId; QString lastSceneId;
auto helper = qobject_cast<QmlDesigner::Internal::GeneralHelper *>(m_3dHelper); auto helper = qobject_cast<QmlDesigner::Internal::GeneralHelper *>(m_3dHelper);
@@ -1237,6 +1310,15 @@ void Qt5InformationNodeInstanceServer::view3DAction(const View3DActionCommand &c
render3DEditView(renderCount); render3DEditView(renderCount);
} }
void Qt5InformationNodeInstanceServer::requestModelNodePreviewImage(const RequestModelNodePreviewImageCommand &command)
{
m_modelNodelPreviewImageCommand = command;
ServerNodeInstance instance = instanceForId(m_modelNodelPreviewImageCommand.instanceId());
if (instance.isSubclassOf("QQuick3DObject"))
renderModelNode3DImageView();
}
void Qt5InformationNodeInstanceServer::changeAuxiliaryValues(const ChangeAuxiliaryCommand &command) void Qt5InformationNodeInstanceServer::changeAuxiliaryValues(const ChangeAuxiliaryCommand &command)
{ {
Qt5NodeInstanceServer::changeAuxiliaryValues(command); Qt5NodeInstanceServer::changeAuxiliaryValues(command);

View File

@@ -29,6 +29,7 @@
#include "tokencommand.h" #include "tokencommand.h"
#include "valueschangedcommand.h" #include "valueschangedcommand.h"
#include "changeselectioncommand.h" #include "changeselectioncommand.h"
#include "requestmodelnodepreviewimagecommand.h"
#include <QTimer> #include <QTimer>
#include <QVariant> #include <QVariant>
@@ -59,6 +60,7 @@ public:
void removeInstances(const RemoveInstancesCommand &command) override; void removeInstances(const RemoveInstancesCommand &command) override;
void inputEvent(const InputEventCommand &command) override; void inputEvent(const InputEventCommand &command) override;
void view3DAction(const View3DActionCommand &command) override; void view3DAction(const View3DActionCommand &command) override;
void requestModelNodePreviewImage(const RequestModelNodePreviewImageCommand &command) override;
void changeAuxiliaryValues(const ChangeAuxiliaryCommand &command) override; void changeAuxiliaryValues(const ChangeAuxiliaryCommand &command) override;
void changePropertyBindings(const ChangeBindingsCommand &command) override; void changePropertyBindings(const ChangeBindingsCommand &command) override;
void changeIds(const ChangeIdsCommand &command) override; void changeIds(const ChangeIdsCommand &command) override;
@@ -89,6 +91,7 @@ private:
void handleObjectPropertyChangeTimeout(); void handleObjectPropertyChangeTimeout();
void handleSelectionChangeTimeout(); void handleSelectionChangeTimeout();
void createEditView3D(); void createEditView3D();
void create3DPreviewView();
void setup3DEditView(const QList<ServerNodeInstance> &instanceList, void setup3DEditView(const QList<ServerNodeInstance> &instanceList,
const QHash<QString, QVariantMap> &toolStates); const QHash<QString, QVariantMap> &toolStates);
void createCameraAndLightGizmos(const QList<ServerNodeInstance> &instanceList) const; void createCameraAndLightGizmos(const QList<ServerNodeInstance> &instanceList) const;
@@ -110,12 +113,20 @@ private:
void removeNode3D(QObject *node); void removeNode3D(QObject *node);
void resolveSceneRoots(); void resolveSceneRoots();
ServerNodeInstance active3DSceneInstance() const; ServerNodeInstance active3DSceneInstance() const;
void updateNodesRecursive(QQuickItem *item);
QQuickItem *getContentItemForRendering(QQuickItem *rootItem);
void render3DEditView(int count = 1); void render3DEditView(int count = 1);
void doRender3DEditView(); void doRender3DEditView();
void renderModelNode3DImageView();
void doRenderModelNode3DImageView();
QPointer<QQuickView> m_editView3D; QPointer<QQuickView> m_editView3D;
QQuickItem *m_editView3DRootItem = nullptr; QQuickItem *m_editView3DRootItem = nullptr;
QQuickItem *m_editView3DContentItem = nullptr; QQuickItem *m_editView3DContentItem = nullptr;
QPointer<QQuickView> m_ModelNode3DImageView;
QQuickItem *m_ModelNode3DImageViewRootItem = nullptr;
QQuickItem *m_ModelNode3DImageViewContentItem = nullptr;
RequestModelNodePreviewImageCommand m_modelNodelPreviewImageCommand;
QSet<QObject *> m_view3Ds; QSet<QObject *> m_view3Ds;
QMultiHash<QObject *, QObject *> m_3DSceneMap; // key: scene root, value: node QMultiHash<QObject *, QObject *> m_3DSceneMap; // key: scene root, value: node
QObject *m_active3DView = nullptr; QObject *m_active3DView = nullptr;
@@ -126,12 +137,13 @@ private:
QList<TokenCommand> m_tokenList; QList<TokenCommand> m_tokenList;
QTimer m_propertyChangeTimer; QTimer m_propertyChangeTimer;
QTimer m_selectionChangeTimer; QTimer m_selectionChangeTimer;
QTimer m_renderTimer; QTimer m_render3DEditViewTimer;
QTimer m_renderModelNode3DImageViewTimer;
QVariant m_changedNode; QVariant m_changedNode;
PropertyName m_changedProperty; PropertyName m_changedProperty;
ChangeSelectionCommand m_lastSelectionChangeCommand; ChangeSelectionCommand m_lastSelectionChangeCommand;
QObject *m_3dHelper = nullptr; QObject *m_3dHelper = nullptr;
int m_needRender = 0; int m_need3DEditViewRender = 0;
}; };
} // namespace QmlDesigner } // namespace QmlDesigner

View File

@@ -40,6 +40,9 @@
<file>mockfiles/AxisHelper.qml</file> <file>mockfiles/AxisHelper.qml</file>
<file>mockfiles/AxisHelperArm.qml</file> <file>mockfiles/AxisHelperArm.qml</file>
<file>mockfiles/Line3D.qml</file> <file>mockfiles/Line3D.qml</file>
<file>mockfiles/ModelNode3DImageView.qml</file>
<file>mockfiles/MaterialNodeView.qml</file>
<file>mockfiles/EffectNodeView.qml</file>
<file>mockfiles/meshes/arrow.mesh</file> <file>mockfiles/meshes/arrow.mesh</file>
<file>mockfiles/meshes/scalerod.mesh</file> <file>mockfiles/meshes/scalerod.mesh</file>
<file>mockfiles/meshes/ring.mesh</file> <file>mockfiles/meshes/ring.mesh</file>

View File

@@ -166,6 +166,7 @@ extend_qtc_plugin(QmlDesigner
puppettocreatorcommand.cpp puppettocreatorcommand.h puppettocreatorcommand.cpp puppettocreatorcommand.h
inputeventcommand.cpp inputeventcommand.h inputeventcommand.cpp inputeventcommand.h
view3dactioncommand.cpp view3dactioncommand.h view3dactioncommand.cpp view3dactioncommand.h
requestmodelnodepreviewimagecommand.cpp requestmodelnodepreviewimagecommand.h
) )
extend_qtc_plugin(QmlDesigner extend_qtc_plugin(QmlDesigner

View File

@@ -194,6 +194,54 @@ void DesignerActionManager::registerAddResourceHandler(const AddResourceHandler
m_addResourceHandler.append(handler); m_addResourceHandler.append(handler);
} }
QHash<TypeName, ModelNodePreviewImageHandler> DesignerActionManager::modelNodePreviewHandlers() const
{
return m_modelNodePreviewImageHandlers;
}
void DesignerActionManager::registerModelNodePreviewHandler(const ModelNodePreviewImageHandler &handler)
{
m_modelNodePreviewImageHandlers.insert(handler.type, handler);
// Registering a new handler potentially invalidates no-handler set
m_noModelNodePreviewImageHandlers.clear();
}
bool DesignerActionManager::hasModelNodePreviewHandler(const ModelNode &node) const
{
if (m_modelNodePreviewImageHandlers.contains(node.type()))
return true;
if (m_noModelNodePreviewImageHandlers.contains(node.type()))
return false;
// Node may be a subclass of a registered type
for (const auto &handler : qAsConst(m_modelNodePreviewImageHandlers)) {
if (node.isSubclassOf(handler.type)) {
ModelNodePreviewImageHandler subClassHandler = handler;
return true;
}
}
m_noModelNodePreviewImageHandlers.insert(node.type());
return false;
}
ModelNodePreviewImageOperation DesignerActionManager::modelNodePreviewOperation(const ModelNode &node) const
{
ModelNodePreviewImageOperation op = nullptr;
if (!m_noModelNodePreviewImageHandlers.contains(node.type())) {
int prio = -1;
for (const auto &handler : qAsConst(m_modelNodePreviewImageHandlers)) {
if (node.isSubclassOf(handler.type) && handler.priority > prio)
op = handler.operation;
}
if (!op)
m_noModelNodePreviewImageHandlers.insert(node.type());
}
return op;
}
class VisiblityModelNodeAction : public ModelNodeContextMenuAction class VisiblityModelNodeAction : public ModelNodeContextMenuAction
{ {
public: public:
@@ -1309,6 +1357,24 @@ void DesignerActionManager::createDefaultAddResourceHandler()
ModelNodeOperations::addFontToProject)); ModelNodeOperations::addFontToProject));
} }
void DesignerActionManager::createDefaultModelNodePreviewImageHandlers()
{
registerModelNodePreviewHandler(
ModelNodePreviewImageHandler("QtQuick.Image",
ModelNodeOperations::previewImageDataForImageNode));
registerModelNodePreviewHandler(
ModelNodePreviewImageHandler("QtQuick3D.Texture",
ModelNodeOperations::previewImageDataForImageNode));
registerModelNodePreviewHandler(
ModelNodePreviewImageHandler("QtQuick3D.Material",
ModelNodeOperations::previewImageDataFor3DNode));
// TODO - Disabled until QTBUG-86616 is fixed
// registerModelNodePreviewHandler(
// ModelNodePreviewImageHandler("QtQuick3D.Effect",
// ModelNodeOperations::previewImageDataFor3DNode));
}
void DesignerActionManager::addDesignerAction(ActionInterface *newAction) void DesignerActionManager::addDesignerAction(ActionInterface *newAction)
{ {
m_designerActions.append(QSharedPointer<ActionInterface>(newAction)); m_designerActions.append(QSharedPointer<ActionInterface>(newAction));

View File

@@ -27,11 +27,13 @@
#include <qmldesignercorelib_global.h> #include <qmldesignercorelib_global.h>
#include "actioninterface.h" #include "actioninterface.h"
#include "modelnode.h"
#include <coreplugin/actionmanager/command.h> #include <coreplugin/actionmanager/command.h>
#include <utils/styledbar.h> #include <utils/styledbar.h>
#include <QToolBar> #include <QToolBar>
#include <QImage>
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
class QGraphicsItem; class QGraphicsItem;
@@ -43,6 +45,7 @@ namespace QmlDesigner {
class DesignerActionManagerView; class DesignerActionManagerView;
using AddResourceOperation = std::function<bool (const QStringList &, const QString &)>; using AddResourceOperation = std::function<bool (const QStringList &, const QString &)>;
using ModelNodePreviewImageOperation = std::function<QVariant (const ModelNode &)>;
struct AddResourceHandler struct AddResourceHandler
{ {
@@ -64,6 +67,23 @@ public:
int piority; int piority;
}; };
struct ModelNodePreviewImageHandler
{
public:
ModelNodePreviewImageHandler(const TypeName &t,
ModelNodePreviewImageOperation op,
int prio = 0)
: type(t)
, operation(op)
, priority(prio)
{
}
TypeName type;
ModelNodePreviewImageOperation operation = nullptr;
int priority = 0;
};
class DesignerActionToolBar : public Utils::StyledBar class DesignerActionToolBar : public Utils::StyledBar
{ {
public: public:
@@ -87,6 +107,8 @@ public:
void createDefaultDesignerActions(); void createDefaultDesignerActions();
void createDefaultAddResourceHandler(); void createDefaultAddResourceHandler();
void createDefaultModelNodePreviewImageHandlers();
DesignerActionManagerView *view(); DesignerActionManagerView *view();
DesignerActionToolBar *createToolBar(QWidget *parent = nullptr) const; DesignerActionToolBar *createToolBar(QWidget *parent = nullptr) const;
@@ -102,6 +124,11 @@ public:
QList<AddResourceHandler> addResourceHandler() const; QList<AddResourceHandler> addResourceHandler() const;
void registerAddResourceHandler(const AddResourceHandler &handler); void registerAddResourceHandler(const AddResourceHandler &handler);
QHash<TypeName, ModelNodePreviewImageHandler> modelNodePreviewHandlers() const;
void registerModelNodePreviewHandler(const ModelNodePreviewImageHandler &handler);
bool hasModelNodePreviewHandler(const ModelNode &node) const;
ModelNodePreviewImageOperation modelNodePreviewOperation(const ModelNode &node) const;
private: private:
void addTransitionEffectAction(const TypeName &typeName); void addTransitionEffectAction(const TypeName &typeName);
void addCustomTransitionEffectAction(); void addCustomTransitionEffectAction();
@@ -109,6 +136,8 @@ private:
QList<QSharedPointer<ActionInterface> > m_designerActions; QList<QSharedPointer<ActionInterface> > m_designerActions;
DesignerActionManagerView *m_designerActionManagerView; DesignerActionManagerView *m_designerActionManagerView;
QList<AddResourceHandler> m_addResourceHandler; QList<AddResourceHandler> m_addResourceHandler;
QMultiHash<TypeName, ModelNodePreviewImageHandler> m_modelNodePreviewImageHandlers;
mutable QSet<TypeName> m_noModelNodePreviewImageHandlers;
}; };
} //QmlDesigner } //QmlDesigner

View File

@@ -46,6 +46,8 @@
#include <nodelistproperty.h> #include <nodelistproperty.h>
#include <nodeproperty.h> #include <nodeproperty.h>
#include <signalhandlerproperty.h> #include <signalhandlerproperty.h>
#include <qmldesignerconstants.h>
#include <nodeinstanceview.h>
#include <componentcore_constants.h> #include <componentcore_constants.h>
#include <stylesheetmerger.h> #include <stylesheetmerger.h>
@@ -78,6 +80,7 @@
#include <QFileDialog> #include <QFileDialog>
#include <QPushButton> #include <QPushButton>
#include <QGridLayout> #include <QGridLayout>
#include <QImage>
#include <algorithm> #include <algorithm>
#include <functional> #include <functional>
@@ -1518,6 +1521,110 @@ void removeGroup(const SelectionContext &selectionContext)
}); });
} }
struct ImageData {
QDateTime time;
QImage image;
QString type;
QString id;
QString info;
};
static QHash<QString, QHash<QString, ImageData>> imageDataMap;
static QVariant imageDataToVariant(const ImageData &imageData)
{
if (!imageData.image.isNull()) {
QVariantMap map;
map.insert("type", imageData.type);
map.insert("image", QVariant::fromValue<QImage>(imageData.image));
map.insert("id", imageData.id);
map.insert("info", imageData.info);
return map;
}
return {};
}
QVariant previewImageDataForImageNode(const ModelNode &modelNode)
{
// Images on file system can be cached globally as they are found by absolute paths
QHash<QString, ImageData> &localDataMap = imageDataMap[{}];
VariantProperty prop = modelNode.variantProperty("source");
QString imageSource = prop.value().toString();
QFileInfo imageFi(imageSource);
if (imageFi.isRelative())
imageSource = QmlDesignerPlugin::instance()->documentManager().currentFilePath().toFileInfo().dir().absoluteFilePath(imageSource);
imageFi = QFileInfo(imageSource);
QDateTime modified = imageFi.lastModified();
ImageData imageData;
bool reload = true;
if (localDataMap.contains(imageSource)) {
imageData = localDataMap[imageSource];
if (modified == imageData.time)
reload = false;
}
if (reload) {
QImage originalImage;
originalImage.load(imageSource);
if (!originalImage.isNull()) {
imageData.image = originalImage.scaled(Constants::MODELNODE_PREVIEW_IMAGE_DIMENSIONS * 2,
Constants::MODELNODE_PREVIEW_IMAGE_DIMENSIONS * 2,
Qt::KeepAspectRatio);
imageData.image.setDevicePixelRatio(2.);
double imgSize = double(imageFi.size());
imageData.type = QStringLiteral("%1 (%2)").arg(QString::fromLatin1(modelNode.type())).arg(imageFi.suffix());
imageData.id = modelNode.id();
static QStringList units({QObject::tr("B"), QObject::tr("KB"), QObject::tr("MB"), QObject::tr("GB")});
int unitIndex = 0;
while (imgSize > 1024. && unitIndex < units.size() - 1) {
++unitIndex;
imgSize /= 1024.;
}
imageData.info = QStringLiteral("%1 x %2 (%3%4)").arg(originalImage.width()).arg(originalImage.height())
.arg(QString::number(imgSize, 'g', 3)).arg(units[unitIndex]);
localDataMap.insert(imageSource, imageData);
}
}
return imageDataToVariant(imageData);
}
QVariant previewImageDataFor3DNode(const ModelNode &modelNode)
{
QFileInfo docFi = QmlDesignerPlugin::instance()->documentManager().currentFilePath().toFileInfo();
QHash<QString, ImageData> &localDataMap = imageDataMap[docFi.absoluteFilePath()];
ImageData imageData;
static const QImage placeHolder(":/navigator/icon/tooltip_placeholder.png");
// We need puppet to generate the image, which needs to be asynchronous.
// Until the image is ready, we show a placeholder
const QString id = modelNode.id();
if (localDataMap.contains(id)) {
imageData = localDataMap[id];
} else {
imageData.type = QString::fromLatin1(modelNode.type());
imageData.id = id;
imageData.image = placeHolder;
localDataMap.insert(id, imageData);
}
modelNode.model()->nodeInstanceView()->requestModelNodePreviewImage(modelNode);
return imageDataToVariant(imageData);
}
void updatePreviewImageForNode(const ModelNode &modelNode, const QImage &image)
{
QFileInfo docFi = QmlDesignerPlugin::instance()->documentManager().currentFilePath().toFileInfo();
QString docPath = docFi.absoluteFilePath();
if (imageDataMap.contains(docPath)) {
QHash<QString, ImageData> &localDataMap = imageDataMap[docPath];
if (localDataMap.contains(modelNode.id()))
localDataMap[modelNode.id()].image = image;
}
}
} // namespace ModelNodeOperations } // namespace ModelNodeOperations
} //QmlDesigner } //QmlDesigner

View File

@@ -27,6 +27,8 @@
#include "selectioncontext.h" #include "selectioncontext.h"
QT_FORWARD_DECLARE_CLASS(QImage)
namespace QmlDesigner { namespace QmlDesigner {
namespace ModelNodeOperations { namespace ModelNodeOperations {
@@ -84,5 +86,10 @@ void selectFlowEffect(const SelectionContext &selectionContext);
void mergeWithTemplate(const SelectionContext &selectionContext); void mergeWithTemplate(const SelectionContext &selectionContext);
void removeGroup(const SelectionContext &selectionContext); void removeGroup(const SelectionContext &selectionContext);
// ModelNodePreviewImageOperations
QVariant previewImageDataFor3DNode(const ModelNode &modelNode);
QVariant previewImageDataForImageNode(const ModelNode &modelNode);
void updatePreviewImageForNode(const ModelNode &modelNode, const QImage &image);
} // namespace ModelNodeOperationso } // namespace ModelNodeOperationso
} //QmlDesigner } //QmlDesigner

View File

@@ -12,5 +12,6 @@
<file>export_checked@2x.png</file> <file>export_checked@2x.png</file>
<file>export_unchecked.png</file> <file>export_unchecked.png</file>
<file>export_unchecked@2x.png</file> <file>export_unchecked@2x.png</file>
<file>tooltip_placeholder.png</file>
</qresource> </qresource>
</RCC> </RCC>

View File

@@ -40,6 +40,7 @@
#include <invalididexception.h> #include <invalididexception.h>
#include <rewritingexception.h> #include <rewritingexception.h>
#include <qmlitemnode.h> #include <qmlitemnode.h>
#include <designeractionmanager.h>
#include <coreplugin/icore.h> #include <coreplugin/icore.h>
@@ -53,7 +54,6 @@
#include <QPointF> #include <QPointF>
#include <QDir> #include <QDir>
#include <QFileInfo> #include <QFileInfo>
#include <QDateTime>
#include <coreplugin/messagebox.h> #include <coreplugin/messagebox.h>
@@ -181,6 +181,7 @@ static void reparentModelNodeToNodeProperty(NodeAbstractProperty &parentProperty
NavigatorTreeModel::NavigatorTreeModel(QObject *parent) : QAbstractItemModel(parent) NavigatorTreeModel::NavigatorTreeModel(QObject *parent) : QAbstractItemModel(parent)
{ {
m_actionManager = &QmlDesignerPlugin::instance()->viewManager().designerActionManager();
} }
NavigatorTreeModel::~NavigatorTreeModel() = default; NavigatorTreeModel::~NavigatorTreeModel() = default;
@@ -201,13 +202,6 @@ QVariant NavigatorTreeModel::data(const QModelIndex &index, int role) const
if (role == ItemIsVisibleRole) //independent of column if (role == ItemIsVisibleRole) //independent of column
return m_view->isNodeInvisible(modelNode) ? Qt::Unchecked : Qt::Checked; return m_view->isNodeInvisible(modelNode) ? Qt::Unchecked : Qt::Checked;
auto hasImageToolTip = [modelNode]() -> bool {
if (modelNode.isValid() && modelNode.metaInfo().isValid())
return modelNode.type() == "QtQuick.Image" || modelNode.type() == "QtQuick3D.Texture";
else
return false;
};
if (index.column() == 0) { if (index.column() == 0) {
if (role == Qt::DisplayRole) { if (role == Qt::DisplayRole) {
return modelNode.displayName(); return modelNode.displayName();
@@ -229,7 +223,7 @@ QVariant NavigatorTreeModel::data(const QModelIndex &index, int role) const
} }
if (modelNode.metaInfo().isValid()) { if (modelNode.metaInfo().isValid()) {
if (hasImageToolTip()) if (m_actionManager->hasModelNodePreviewHandler(modelNode))
return {}; // Images have special tooltip popup, so suppress regular one return {}; // Images have special tooltip popup, so suppress regular one
else else
return modelNode.type(); return modelNode.type();
@@ -239,62 +233,9 @@ QVariant NavigatorTreeModel::data(const QModelIndex &index, int role) const
} else if (role == ToolTipImageRole) { } else if (role == ToolTipImageRole) {
if (currentQmlObjectNode.hasError()) // Error already shown on regular tooltip if (currentQmlObjectNode.hasError()) // Error already shown on regular tooltip
return {}; return {};
auto op = m_actionManager->modelNodePreviewOperation(modelNode);
if (hasImageToolTip()) { if (op)
VariantProperty prop = modelNode.variantProperty("source"); return op(modelNode);
QString imageSource = prop.value().toString();
QFileInfo fi(imageSource);
if (fi.isRelative())
imageSource = QmlDesignerPlugin::instance()->documentManager().currentFilePath().toFileInfo().dir().absoluteFilePath(imageSource);
fi = QFileInfo(imageSource);
QDateTime modified = fi.lastModified();
struct ImageData {
QDateTime time;
QImage image;
QString type;
QString id;
QString info;
};
static QHash<QString, ImageData> toolTipImageMap;
ImageData imageData;
bool reload = true;
if (toolTipImageMap.contains(imageSource)) {
imageData = toolTipImageMap[imageSource];
if (modified == imageData.time)
reload = false;
}
if (reload) {
QImage originalImage;
originalImage.load(imageSource);
if (!originalImage.isNull()) {
imageData.image = originalImage.scaled(150, 150, Qt::KeepAspectRatio);
double imgSize = double(fi.size());
imageData.type = QStringLiteral("%1 (%2)").arg(QString::fromLatin1(modelNode.type())).arg(fi.suffix());
imageData.id = modelNode.id();
static QStringList units({tr("B"), tr("KB"), tr("MB"), tr("GB")});
int unitIndex = 0;
while (imgSize > 1024. && unitIndex < units.size() - 1) {
++unitIndex;
imgSize /= 1024.;
}
imageData.info = QStringLiteral("%1 x %2 (%3%4)").arg(originalImage.width()).arg(originalImage.height())
.arg(QString::number(imgSize, 'g', 3)).arg(units[unitIndex]);
toolTipImageMap.insert(imageSource, imageData);
}
}
if (!imageData.image.isNull()) {
QVariantMap map;
map.insert("type", imageData.type);
map.insert("image", QVariant::fromValue<QImage>(imageData.image));
map.insert("id", imageData.id);
map.insert("info", imageData.info);
return map;
}
}
} else if (role == ModelNodeRole) { } else if (role == ModelNodeRole) {
return QVariant::fromValue<ModelNode>(modelNode); return QVariant::fromValue<ModelNode>(modelNode);
} }
@@ -898,4 +839,9 @@ void NavigatorTreeModel::resetModel()
endResetModel(); endResetModel();
} }
void NavigatorTreeModel::updateToolTipImage(const ModelNode &node, const QImage &image)
{
emit toolTipImageUpdated(node.id(), image);
}
} // QmlDesigner } // QmlDesigner

View File

@@ -32,12 +32,14 @@
#include <QAbstractItemModel> #include <QAbstractItemModel>
#include <QPointer> #include <QPointer>
#include <QDateTime>
namespace QmlDesigner { namespace QmlDesigner {
class Model; class Model;
class NavigatorView; class NavigatorView;
class ModelNode; class ModelNode;
class DesignerActionManager;
class NavigatorTreeModel : public QAbstractItemModel, public NavigatorModelInterface class NavigatorTreeModel : public QAbstractItemModel, public NavigatorModelInterface
{ {
@@ -91,6 +93,11 @@ public:
void setFilter(bool showOnlyVisibleItems) override; void setFilter(bool showOnlyVisibleItems) override;
void resetModel() override; void resetModel() override;
void updateToolTipImage(const ModelNode &node, const QImage &image);
signals:
void toolTipImageUpdated(const QString &id, const QImage &image) const;
private: private:
void moveNodesInteractive(NodeAbstractProperty &parentProperty, const QList<ModelNode> &modelNodes, void moveNodesInteractive(NodeAbstractProperty &parentProperty, const QList<ModelNode> &modelNodes,
int targetIndex, bool executeInTransaction = true); int targetIndex, bool executeInTransaction = true);
@@ -102,6 +109,7 @@ private:
QPointer<NavigatorView> m_view; QPointer<NavigatorView> m_view;
mutable QHash<ModelNode, QModelIndex> m_nodeIndexHash; mutable QHash<ModelNode, QModelIndex> m_nodeIndexHash;
bool m_showOnlyVisibleItems = true; bool m_showOnlyVisibleItems = true;
DesignerActionManager *m_actionManager = nullptr;
}; };
} // namespace QmlDesigner } // namespace QmlDesigner

View File

@@ -168,6 +168,12 @@ NavigatorTreeView::NavigatorTreeView(QWidget *parent)
setMinimumWidth(240); setMinimumWidth(240);
setRootIsDecorated(false); setRootIsDecorated(false);
setIndentation(indentation() * 0.5); setIndentation(indentation() * 0.5);
m_toolTipHideTimer.setSingleShot(true);
connect(&m_toolTipHideTimer, &QTimer::timeout, [this]() {
if (m_previewToolTip && m_previewToolTip->isVisible())
m_previewToolTip->hide();
});
} }
void NavigatorTreeView::drawSelectionBackground(QPainter *painter, const QStyleOption &option) void NavigatorTreeView::drawSelectionBackground(QPainter *painter, const QStyleOption &option)
@@ -187,22 +193,30 @@ bool NavigatorTreeView::viewportEvent(QEvent *event)
QVariantMap imgMap = navModel->data(index, ToolTipImageRole).toMap(); QVariantMap imgMap = navModel->data(index, ToolTipImageRole).toMap();
if (!imgMap.isEmpty()) { if (!imgMap.isEmpty()) {
if (!m_previewToolTip) m_toolTipHideTimer.stop();
if (!m_previewToolTip) {
m_previewToolTip = new PreviewToolTip(QApplication::activeWindow()); m_previewToolTip = new PreviewToolTip(QApplication::activeWindow());
connect(navModel, &NavigatorTreeModel::toolTipImageUpdated,
[this](const QString &id, const QImage &image) {
if (m_previewToolTip && m_previewToolTip->id() == id)
m_previewToolTip->setImage(image);
});
}
m_previewToolTip->setId(imgMap["id"].toString()); m_previewToolTip->setId(imgMap["id"].toString());
m_previewToolTip->setType(imgMap["type"].toString()); m_previewToolTip->setType(imgMap["type"].toString());
m_previewToolTip->setInfo(imgMap["info"].toString()); m_previewToolTip->setInfo(imgMap["info"].toString());
m_previewToolTip->setImage(imgMap["image"].value<QImage>()); m_previewToolTip->setImage(imgMap["image"].value<QImage>());
m_previewToolTip->move(helpEvent->pos()); m_previewToolTip->move(m_previewToolTip->parentWidget()->mapFromGlobal(helpEvent->globalPos())
+ QPoint(15, 15));
if (!m_previewToolTip->isVisible()) if (!m_previewToolTip->isVisible())
m_previewToolTip->show(); m_previewToolTip->show();
} else if (m_previewToolTip) { } else if (m_previewToolTip) {
m_previewToolTip->hide(); m_toolTipHideTimer.start(0);
} }
} }
} else if (event->type() == QEvent::Leave) { } else if (event->type() == QEvent::Leave) {
if (m_previewToolTip) if (m_previewToolTip)
m_previewToolTip->hide(); m_toolTipHideTimer.start(500);
} }
return QTreeView::viewportEvent(event); return QTreeView::viewportEvent(event);

View File

@@ -26,6 +26,7 @@
#pragma once #pragma once
#include <QTreeView> #include <QTreeView>
#include <QTimer>
namespace QmlDesigner { namespace QmlDesigner {
@@ -42,5 +43,6 @@ public:
private: private:
PreviewToolTip *m_previewToolTip = nullptr; PreviewToolTip *m_previewToolTip = nullptr;
QTimer m_toolTipHideTimer;
}; };
} }

View File

@@ -40,6 +40,7 @@
#include <variantproperty.h> #include <variantproperty.h>
#include <qmlitemnode.h> #include <qmlitemnode.h>
#include <rewritingexception.h> #include <rewritingexception.h>
#include <nodeinstanceview.h>
#include <coreplugin/editormanager/editormanager.h> #include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/icore.h> #include <coreplugin/icore.h>
@@ -229,6 +230,11 @@ void NavigatorView::enableWidget()
m_widget->enableNavigator(); m_widget->enableNavigator();
} }
void NavigatorView::modelNodePreviewImageChanged(const ModelNode &node, const QImage &image)
{
m_treeModel->updateToolTipImage(node, image);
}
ModelNode NavigatorView::modelNodeForIndex(const QModelIndex &modelIndex) const ModelNode NavigatorView::modelNodeForIndex(const QModelIndex &modelIndex) const
{ {
return modelIndex.model()->data(modelIndex, ModelNodeRole).value<ModelNode>(); return modelIndex.model()->data(modelIndex, ModelNodeRole).value<ModelNode>();

View File

@@ -38,6 +38,7 @@ class QTreeView;
class QItemSelection; class QItemSelection;
class QModelIndex; class QModelIndex;
class QAbstractItemModel; class QAbstractItemModel;
class QImage;
QT_END_NAMESPACE QT_END_NAMESPACE
namespace QmlDesigner { namespace QmlDesigner {
@@ -95,6 +96,8 @@ public:
void disableWidget() override; void disableWidget() override;
void enableWidget() override; void enableWidget() override;
void modelNodePreviewImageChanged(const ModelNode &node, const QImage &image) override;
private: private:
ModelNode modelNodeForIndex(const QModelIndex &modelIndex) const; ModelNode modelNodeForIndex(const QModelIndex &modelIndex) const;
void changeSelection(const QItemSelection &selected, const QItemSelection &deselected); void changeSelection(const QItemSelection &selected, const QItemSelection &deselected);

View File

@@ -67,4 +67,9 @@ void PreviewToolTip::setImage(const QImage &image)
m_ui->imageLabel->setPixmap(QPixmap::fromImage(image)); m_ui->imageLabel->setPixmap(QPixmap::fromImage(image));
} }
QString PreviewToolTip::id() const
{
return m_ui->idLabel->text();
}
} }

View File

@@ -46,6 +46,8 @@ public:
void setInfo(const QString &info); void setInfo(const QString &info);
void setImage(const QImage &image); void setImage(const QImage &image);
QString id() const;
private: private:
Ui::PreviewToolTip *m_ui; Ui::PreviewToolTip *m_ui;
}; };

View File

@@ -7,7 +7,7 @@
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>400</width> <width>400</width>
<height>160</height> <height>166</height>
</rect> </rect>
</property> </property>
<property name="sizePolicy"> <property name="sizePolicy">
@@ -18,8 +18,8 @@
</property> </property>
<property name="minimumSize"> <property name="minimumSize">
<size> <size>
<width>200</width> <width>300</width>
<height>150</height> <height>140</height>
</size> </size>
</property> </property>
<property name="maximumSize"> <property name="maximumSize">
@@ -90,8 +90,8 @@
</property> </property>
<property name="minimumSize"> <property name="minimumSize">
<size> <size>
<width>140</width> <width>150</width>
<height>140</height> <height>150</height>
</size> </size>
</property> </property>
<property name="frameShape"> <property name="frameShape">

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

View File

@@ -186,6 +186,7 @@ public:
void emitInstanceToken(const QString &token, int number, const QVector<ModelNode> &nodeVector); void emitInstanceToken(const QString &token, int number, const QVector<ModelNode> &nodeVector);
void emitRenderImage3DChanged(const QImage &image); void emitRenderImage3DChanged(const QImage &image);
void emitUpdateActiveScene3D(const QVariantMap &sceneState); void emitUpdateActiveScene3D(const QVariantMap &sceneState);
void emitModelNodelPreviewImageChanged(const ModelNode &node, const QImage &image);
void sendTokenToInstances(const QString &token, int number, const QVector<ModelNode> &nodeVector); void sendTokenToInstances(const QString &token, int number, const QVector<ModelNode> &nodeVector);
@@ -245,6 +246,7 @@ public:
virtual void renderImage3DChanged(const QImage &image); virtual void renderImage3DChanged(const QImage &image);
virtual void updateActiveScene3D(const QVariantMap &sceneState); virtual void updateActiveScene3D(const QVariantMap &sceneState);
virtual void modelNodePreviewImageChanged(const ModelNode &node, const QImage &image);
void changeRootNodeType(const TypeName &type, int majorVersion, int minorVersion); void changeRootNodeType(const TypeName &type, int majorVersion, int minorVersion);

View File

@@ -138,6 +138,7 @@ public:
void sendInputEvent(QInputEvent *e) const; void sendInputEvent(QInputEvent *e) const;
void view3DAction(const View3DActionCommand &command); void view3DAction(const View3DActionCommand &command);
void requestModelNodePreviewImage(const ModelNode &node);
void edit3DViewResized(const QSize &size) const; void edit3DViewResized(const QSize &size) const;
void handlePuppetToCreatorCommand(const PuppetToCreatorCommand &command) override; void handlePuppetToCreatorCommand(const PuppetToCreatorCommand &command) override;

View File

@@ -60,6 +60,7 @@
#include <update3dviewstatecommand.h> #include <update3dviewstatecommand.h>
#include <valueschangedcommand.h> #include <valueschangedcommand.h>
#include <view3dactioncommand.h> #include <view3dactioncommand.h>
#include <requestmodelnodepreviewimagecommand.h>
#include <import.h> #include <import.h>
#include <nodeinstanceview.h> #include <nodeinstanceview.h>
@@ -293,6 +294,11 @@ void NodeInstanceServerProxy::view3DAction(const View3DActionCommand &command)
writeCommand(QVariant::fromValue(command)); writeCommand(QVariant::fromValue(command));
} }
void NodeInstanceServerProxy::requestModelNodePreviewImage(const RequestModelNodePreviewImageCommand &command)
{
writeCommand(QVariant::fromValue(command));
}
void NodeInstanceServerProxy::changeLanguage(const ChangeLanguageCommand &command) void NodeInstanceServerProxy::changeLanguage(const ChangeLanguageCommand &command)
{ {
writeCommand(QVariant::fromValue(command)); writeCommand(QVariant::fromValue(command));

View File

@@ -81,6 +81,7 @@ public:
void benchmark(const QString &message) override; void benchmark(const QString &message) override;
void inputEvent(const InputEventCommand &command) override; void inputEvent(const InputEventCommand &command) override;
void view3DAction(const View3DActionCommand &command) override; void view3DAction(const View3DActionCommand &command) override;
void requestModelNodePreviewImage(const RequestModelNodePreviewImageCommand &command) override;
void changeLanguage(const ChangeLanguageCommand &command) override; void changeLanguage(const ChangeLanguageCommand &command) override;
void changePreviewImageSize(const ChangePreviewImageSizeCommand &command) override; void changePreviewImageSize(const ChangePreviewImageSizeCommand &command) override;

View File

@@ -71,6 +71,7 @@
#include "valueschangedcommand.h" #include "valueschangedcommand.h"
#include "variantproperty.h" #include "variantproperty.h"
#include "view3dactioncommand.h" #include "view3dactioncommand.h"
#include "requestmodelnodepreviewimagecommand.h"
#include <designersettings.h> #include <designersettings.h>
#include <metainfo.h> #include <metainfo.h>
@@ -1487,6 +1488,16 @@ void NodeInstanceView::handlePuppetToCreatorCommand(const PuppetToCreatorCommand
} else if (command.type() == PuppetToCreatorCommand::ActiveSceneChanged) { } else if (command.type() == PuppetToCreatorCommand::ActiveSceneChanged) {
const auto sceneState = qvariant_cast<QVariantMap>(command.data()); const auto sceneState = qvariant_cast<QVariantMap>(command.data());
emitUpdateActiveScene3D(sceneState); emitUpdateActiveScene3D(sceneState);
} else if (command.type() == PuppetToCreatorCommand::RenderModelNodePreviewImage) {
ImageContainer container = qvariant_cast<ImageContainer>(command.data());
QImage image = container.image();
if (hasModelNodeForInternalId(container.instanceId()) && !image.isNull()) {
auto node = modelNodeForInternalId(container.instanceId());
if (node.isValid()) {
image.setDevicePixelRatio(2.);
emitModelNodelPreviewImageChanged(node, image);
}
}
} }
} }
@@ -1511,6 +1522,20 @@ void NodeInstanceView::view3DAction(const View3DActionCommand &command)
m_nodeInstanceServer->view3DAction(command); m_nodeInstanceServer->view3DAction(command);
} }
void NodeInstanceView::requestModelNodePreviewImage(const ModelNode &node)
{
if (node.isValid()) {
auto instance = instanceForModelNode(node);
if (instance.isValid()) {
m_nodeInstanceServer->requestModelNodePreviewImage(
RequestModelNodePreviewImageCommand(
instance.instanceId(),
QSize(Constants::MODELNODE_PREVIEW_IMAGE_DIMENSIONS,
Constants::MODELNODE_PREVIEW_IMAGE_DIMENSIONS)));
}
}
}
void NodeInstanceView::edit3DViewResized(const QSize &size) const void NodeInstanceView::edit3DViewResized(const QSize &size) const
{ {
m_nodeInstanceServer->update3DViewState(Update3dViewStateCommand(size)); m_nodeInstanceServer->update3DViewState(Update3dViewStateCommand(size));

View File

@@ -382,6 +382,10 @@ void AbstractView::updateActiveScene3D(const QVariantMap & /*sceneState*/)
{ {
} }
void AbstractView::modelNodePreviewImageChanged(const ModelNode & /*node*/, const QImage & /*image*/)
{
}
QList<ModelNode> AbstractView::toModelNodeList(const QList<Internal::InternalNode::Pointer> &nodeList) const QList<ModelNode> AbstractView::toModelNodeList(const QList<Internal::InternalNode::Pointer> &nodeList) const
{ {
return QmlDesigner::toModelNodeList(nodeList, const_cast<AbstractView*>(this)); return QmlDesigner::toModelNodeList(nodeList, const_cast<AbstractView*>(this));
@@ -766,6 +770,12 @@ void AbstractView::emitUpdateActiveScene3D(const QVariantMap &sceneState)
model()->d->notifyUpdateActiveScene3D(sceneState); model()->d->notifyUpdateActiveScene3D(sceneState);
} }
void AbstractView::emitModelNodelPreviewImageChanged(const ModelNode &node, const QImage &image)
{
if (model())
model()->d->notifyModelNodePreviewImageChanged(node, image);
}
void AbstractView::emitRewriterEndTransaction() void AbstractView::emitRewriterEndTransaction()
{ {
if (model()) if (model())

View File

@@ -26,6 +26,7 @@
#include "model.h" #include "model.h"
#include "model_p.h" #include "model_p.h"
#include <modelnode.h> #include <modelnode.h>
#include <modelnodeoperations.h>
#include "internalnode_p.h" #include "internalnode_p.h"
#include "invalidpropertyexception.h" #include "invalidpropertyexception.h"
#include "invalidargumentexception.h" #include "invalidargumentexception.h"
@@ -700,6 +701,16 @@ void ModelPrivate::notifyUpdateActiveScene3D(const QVariantMap &sceneState)
} }
} }
void ModelPrivate::notifyModelNodePreviewImageChanged(const ModelNode &node, const QImage &image)
{
ModelNodeOperations::updatePreviewImageForNode(node, image);
for (const QPointer<AbstractView> &view : qAsConst(m_viewList)) {
Q_ASSERT(view != nullptr);
view->modelNodePreviewImageChanged(node, image);
}
}
void ModelPrivate::notifyRewriterBeginTransaction() void ModelPrivate::notifyRewriterBeginTransaction()
{ {
bool resetModel = false; bool resetModel = false;

View File

@@ -160,6 +160,7 @@ public:
void notifyRenderImage3DChanged(const QImage &image); void notifyRenderImage3DChanged(const QImage &image);
void notifyUpdateActiveScene3D(const QVariantMap &sceneState); void notifyUpdateActiveScene3D(const QVariantMap &sceneState);
void notifyModelNodePreviewImageChanged(const ModelNode &node, const QImage &image);
void setDocumentMessages(const QList<DocumentMessage> &errors, const QList<DocumentMessage> &warnings); void setDocumentMessages(const QList<DocumentMessage> &errors, const QList<DocumentMessage> &warnings);

View File

@@ -224,6 +224,7 @@ void DesignModeWidget::setup()
auto &actionManager = viewManager().designerActionManager(); auto &actionManager = viewManager().designerActionManager();
actionManager.createDefaultDesignerActions(); actionManager.createDefaultDesignerActions();
actionManager.createDefaultAddResourceHandler(); actionManager.createDefaultAddResourceHandler();
actionManager.createDefaultModelNodePreviewImageHandlers();
actionManager.polishActions(); actionManager.polishActions();
auto settings = Core::ICore::settings(QSettings::UserScope); auto settings = Core::ICore::settings(QSettings::UserScope);

View File

@@ -75,6 +75,8 @@ const char QT_QUICK_3D_MODULE_NAME[] = "QtQuick3D";
// Menus // Menus
const char M_WINDOW_WORKSPACES[] = "QmlDesigner.Menu.Window.Workspaces"; const char M_WINDOW_WORKSPACES[] = "QmlDesigner.Menu.Window.Workspaces";
const int MODELNODE_PREVIEW_IMAGE_DIMENSIONS = 150;
namespace Internal { namespace Internal {
enum { debug = 0 }; enum { debug = 0 };
} }

View File

@@ -188,6 +188,8 @@ Project {
"commands/inputeventcommand.h", "commands/inputeventcommand.h",
"commands/view3dactioncommand.cpp", "commands/view3dactioncommand.cpp",
"commands/view3dactioncommand.h", "commands/view3dactioncommand.h",
"commands/requestmodelnodepreviewimagecommand.cpp",
"commands/requestmodelnodepreviewimagecommand.h",
"container/addimportcontainer.cpp", "container/addimportcontainer.cpp",
"container/addimportcontainer.h", "container/addimportcontainer.h",
"container/idcontainer.cpp", "container/idcontainer.cpp",

View File

@@ -51,6 +51,7 @@ extend_qtc_executable(qml2puppet
puppettocreatorcommand.cpp puppettocreatorcommand.h puppettocreatorcommand.cpp puppettocreatorcommand.h
inputeventcommand.cpp inputeventcommand.h inputeventcommand.cpp inputeventcommand.h
view3dactioncommand.cpp view3dactioncommand.h view3dactioncommand.cpp view3dactioncommand.h
requestmodelnodepreviewimagecommand.cpp requestmodelnodepreviewimagecommand.h
valueschangedcommand.cpp valueschangedcommand.cpp
captureddatacommand.h captureddatacommand.h
scenecreatedcommand.h scenecreatedcommand.h

View File

@@ -116,6 +116,8 @@ QtcTool {
"commands/inputeventcommand.h", "commands/inputeventcommand.h",
"commands/view3dactioncommand.cpp", "commands/view3dactioncommand.cpp",
"commands/view3dactioncommand.h", "commands/view3dactioncommand.h",
"commands/requestmodelnodepreviewimagecommand.cpp",
"commands/requestmodelnodepreviewimagecommand.h",
"commands/captureddatacommand.h", "commands/captureddatacommand.h",
"commands/scenecreatedcommand.h", "commands/scenecreatedcommand.h",
"container/addimportcontainer.cpp", "container/addimportcontainer.cpp",