forked from qt-creator/qt-creator
QmlDesigner: Show tooltip preview image for Textures with sourceItem
For non-component sourceItems, the preview shown is simply whatever image has been stored for form editor for that item. If the sourceItem is component, the preview image is the same as sourceItem's preview image, as the form editor image for components often includes unnecessary empty space. Note that currently the image stored for form editor doesn't include child items, so this is not a perfect solution. It is however in line with what form editor shows for the texture. Change-Id: I3c0c629ca5e7fa25dbcb390c53e3865e34d5e729 Fixes: QDS-2824 Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io> Reviewed-by: Mahmoud Badri <mahmoud.badri@qt.io>
This commit is contained in:
@@ -32,10 +32,13 @@ namespace QmlDesigner {
|
||||
|
||||
RequestModelNodePreviewImageCommand::RequestModelNodePreviewImageCommand() = default;
|
||||
|
||||
RequestModelNodePreviewImageCommand::RequestModelNodePreviewImageCommand(qint32 id, const QSize &size, const QString &componentPath)
|
||||
RequestModelNodePreviewImageCommand::RequestModelNodePreviewImageCommand(qint32 id, const QSize &size,
|
||||
const QString &componentPath,
|
||||
qint32 renderItemId)
|
||||
: m_instanceId(id)
|
||||
, m_size(size)
|
||||
, m_componentPath(componentPath)
|
||||
, m_renderItemId(renderItemId)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -54,11 +57,17 @@ QString RequestModelNodePreviewImageCommand::componentPath() const
|
||||
return m_componentPath;
|
||||
}
|
||||
|
||||
qint32 RequestModelNodePreviewImageCommand::renderItemId() const
|
||||
{
|
||||
return m_renderItemId;
|
||||
}
|
||||
|
||||
QDataStream &operator<<(QDataStream &out, const RequestModelNodePreviewImageCommand &command)
|
||||
{
|
||||
out << int(command.instanceId());
|
||||
out << command.size();
|
||||
out << command.componentPath();
|
||||
out << command.renderItemId();
|
||||
|
||||
return out;
|
||||
}
|
||||
@@ -68,6 +77,7 @@ QDataStream &operator>>(QDataStream &in, RequestModelNodePreviewImageCommand &co
|
||||
in >> command.m_instanceId;
|
||||
in >> command.m_size;
|
||||
in >> command.m_componentPath;
|
||||
in >> command.m_renderItemId;
|
||||
return in;
|
||||
}
|
||||
|
||||
@@ -76,7 +86,8 @@ QDebug operator <<(QDebug debug, const RequestModelNodePreviewImageCommand &comm
|
||||
return debug.nospace() << "RequestModelNodePreviewImageCommand("
|
||||
<< "instanceId: " << command.instanceId() << ", "
|
||||
<< "size: " << command.size() << ", "
|
||||
<< "componentPath: " << command.componentPath() << ")";
|
||||
<< "componentPath: " << command.componentPath() << ", "
|
||||
<< "renderItemId: " << command.renderItemId() << ")";
|
||||
}
|
||||
|
||||
} // namespace QmlDesigner
|
||||
|
@@ -40,16 +40,19 @@ class RequestModelNodePreviewImageCommand
|
||||
|
||||
public:
|
||||
RequestModelNodePreviewImageCommand();
|
||||
explicit RequestModelNodePreviewImageCommand(qint32 id, const QSize &size, const QString &componentPath);
|
||||
explicit RequestModelNodePreviewImageCommand(qint32 id, const QSize &size,
|
||||
const QString &componentPath, qint32 renderItemId);
|
||||
|
||||
qint32 instanceId() const;
|
||||
QSize size() const;
|
||||
QString componentPath() const;
|
||||
qint32 renderItemId() const;
|
||||
|
||||
private:
|
||||
qint32 m_instanceId;
|
||||
QSize m_size;
|
||||
QString m_componentPath;
|
||||
qint32 m_renderItemId;
|
||||
};
|
||||
|
||||
QDataStream &operator<<(QDataStream &out, const RequestModelNodePreviewImageCommand &command);
|
||||
|
@@ -518,7 +518,12 @@ void Qt5InformationNodeInstanceServer::renderModelNodeImageView()
|
||||
void Qt5InformationNodeInstanceServer::doRenderModelNodeImageView()
|
||||
{
|
||||
|
||||
ServerNodeInstance instance = instanceForId(m_modelNodePreviewImageCommand.instanceId());
|
||||
ServerNodeInstance instance;
|
||||
if (m_modelNodePreviewImageCommand.renderItemId() >= 0)
|
||||
instance = instanceForId(m_modelNodePreviewImageCommand.renderItemId());
|
||||
else
|
||||
instance = instanceForId(m_modelNodePreviewImageCommand.instanceId());
|
||||
|
||||
if (instance.isSubclassOf("QQuick3DObject"))
|
||||
doRenderModelNode3DImageView();
|
||||
else if (instance.isSubclassOf("QQuickItem"))
|
||||
|
@@ -1522,7 +1522,7 @@ void removeGroup(const SelectionContext &selectionContext)
|
||||
QVariant previewImageDataForGenericNode(const ModelNode &modelNode)
|
||||
{
|
||||
if (modelNode.isValid())
|
||||
return modelNode.model()->nodeInstanceView()->previewImageDataForGenericNode(modelNode);
|
||||
return modelNode.model()->nodeInstanceView()->previewImageDataForGenericNode(modelNode, {});
|
||||
return {};
|
||||
}
|
||||
|
||||
|
@@ -138,12 +138,12 @@ public:
|
||||
|
||||
void sendInputEvent(QInputEvent *e) const;
|
||||
void view3DAction(const View3DActionCommand &command);
|
||||
void requestModelNodePreviewImage(const ModelNode &node);
|
||||
void requestModelNodePreviewImage(const ModelNode &node, const ModelNode &renderNode);
|
||||
void edit3DViewResized(const QSize &size) const;
|
||||
|
||||
void handlePuppetToCreatorCommand(const PuppetToCreatorCommand &command) override;
|
||||
|
||||
QVariant previewImageDataForGenericNode(const ModelNode &modelNode);
|
||||
QVariant previewImageDataForGenericNode(const ModelNode &modelNode, const ModelNode &renderNode);
|
||||
QVariant previewImageDataForImageNode(const ModelNode &modelNode);
|
||||
|
||||
protected:
|
||||
|
@@ -79,6 +79,7 @@
|
||||
#include <modelnode.h>
|
||||
#include <nodehints.h>
|
||||
#include <rewriterview.h>
|
||||
#include <qmlitemnode.h>
|
||||
|
||||
#ifndef QMLDESIGNER_TEST
|
||||
#include <qmldesignerplugin.h>
|
||||
@@ -1522,20 +1523,28 @@ void NodeInstanceView::view3DAction(const View3DActionCommand &command)
|
||||
m_nodeInstanceServer->view3DAction(command);
|
||||
}
|
||||
|
||||
void NodeInstanceView::requestModelNodePreviewImage(const ModelNode &node)
|
||||
void NodeInstanceView::requestModelNodePreviewImage(const ModelNode &node, const ModelNode &renderNode)
|
||||
{
|
||||
if (node.isValid()) {
|
||||
auto instance = instanceForModelNode(node);
|
||||
if (instance.isValid()) {
|
||||
qint32 renderItemId = -1;
|
||||
QString componentPath;
|
||||
if (node.isComponent())
|
||||
if (renderNode.isValid()) {
|
||||
auto renderInstance = instanceForModelNode(renderNode);
|
||||
if (renderInstance.isValid())
|
||||
renderItemId = renderInstance.instanceId();
|
||||
if (renderNode.isComponent())
|
||||
componentPath = renderNode.metaInfo().componentFileName();
|
||||
} else if (node.isComponent()) {
|
||||
componentPath = node.metaInfo().componentFileName();
|
||||
}
|
||||
m_nodeInstanceServer->requestModelNodePreviewImage(
|
||||
RequestModelNodePreviewImageCommand(
|
||||
instance.instanceId(),
|
||||
QSize(Constants::MODELNODE_PREVIEW_IMAGE_DIMENSIONS,
|
||||
Constants::MODELNODE_PREVIEW_IMAGE_DIMENSIONS),
|
||||
componentPath));
|
||||
componentPath, renderItemId));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1562,15 +1571,17 @@ static QHash<QString, QHash<QString, ImageData>> imageDataMap;
|
||||
|
||||
static QVariant imageDataToVariant(const ImageData &imageData)
|
||||
{
|
||||
if (!imageData.pixmap.isNull()) {
|
||||
QVariantMap map;
|
||||
map.insert("type", imageData.type);
|
||||
static const QPixmap placeHolder(":/navigator/icon/tooltip_placeholder.png");
|
||||
|
||||
QVariantMap map;
|
||||
map.insert("type", imageData.type);
|
||||
if (imageData.pixmap.isNull())
|
||||
map.insert("pixmap", placeHolder);
|
||||
else
|
||||
map.insert("pixmap", QVariant::fromValue<QPixmap>(imageData.pixmap));
|
||||
map.insert("id", imageData.id);
|
||||
map.insert("info", imageData.info);
|
||||
return map;
|
||||
}
|
||||
return {};
|
||||
map.insert("id", imageData.id);
|
||||
map.insert("info", imageData.info);
|
||||
return map;
|
||||
}
|
||||
|
||||
QVariant NodeInstanceView::previewImageDataForImageNode(const ModelNode &modelNode)
|
||||
@@ -1583,54 +1594,79 @@ QVariant NodeInstanceView::previewImageDataForImageNode(const ModelNode &modelNo
|
||||
|
||||
VariantProperty prop = modelNode.variantProperty("source");
|
||||
QString imageSource = prop.value().toString();
|
||||
QFileInfo imageFi(imageSource);
|
||||
if (imageFi.isRelative())
|
||||
imageSource = QFileInfo(modelNode.model()->fileUrl().toLocalFile()).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;
|
||||
}
|
||||
imageData.id = modelNode.id();
|
||||
imageData.type = QString::fromLatin1(modelNode.type());
|
||||
|
||||
if (reload) {
|
||||
QPixmap originalPixmap;
|
||||
originalPixmap.load(imageSource);
|
||||
if (!originalPixmap.isNull()) {
|
||||
imageData.pixmap = originalPixmap.scaled(Constants::MODELNODE_PREVIEW_IMAGE_DIMENSIONS * 2,
|
||||
Constants::MODELNODE_PREVIEW_IMAGE_DIMENSIONS * 2,
|
||||
Qt::KeepAspectRatio);
|
||||
imageData.pixmap.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.;
|
||||
if (imageSource.isEmpty() && modelNode.isSubclassOf("QtQuick3D.Texture")) {
|
||||
// Texture node may have sourceItem instead
|
||||
BindingProperty binding = modelNode.bindingProperty("sourceItem");
|
||||
if (binding.isValid()) {
|
||||
ModelNode boundNode = binding.resolveToModelNode();
|
||||
if (boundNode.isValid()) {
|
||||
// If bound node is a component, fall back to component render mechanism, as
|
||||
// QmlItemNode::instanceRenderPixmap() often includes unnecessary empty space
|
||||
// for those
|
||||
if (boundNode.isComponent()) {
|
||||
return previewImageDataForGenericNode(modelNode, boundNode);
|
||||
} else {
|
||||
QmlItemNode itemNode(boundNode);
|
||||
imageData.pixmap = itemNode.instanceRenderPixmap().scaled(
|
||||
Constants::MODELNODE_PREVIEW_IMAGE_DIMENSIONS * 2,
|
||||
Constants::MODELNODE_PREVIEW_IMAGE_DIMENSIONS * 2,
|
||||
Qt::KeepAspectRatio);
|
||||
imageData.pixmap.setDevicePixelRatio(2.);
|
||||
}
|
||||
imageData.info = QObject::tr("Source item: %1").arg(boundNode.id());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
QFileInfo imageFi(imageSource);
|
||||
if (imageFi.isRelative())
|
||||
imageSource = QFileInfo(modelNode.model()->fileUrl().toLocalFile()).dir().absoluteFilePath(imageSource);
|
||||
|
||||
imageFi = QFileInfo(imageSource);
|
||||
QDateTime modified = imageFi.lastModified();
|
||||
|
||||
bool reload = true;
|
||||
if (localDataMap.contains(imageSource)) {
|
||||
imageData = localDataMap[imageSource];
|
||||
if (modified == imageData.time)
|
||||
reload = false;
|
||||
}
|
||||
|
||||
if (reload) {
|
||||
QPixmap originalPixmap;
|
||||
originalPixmap.load(imageSource);
|
||||
if (!originalPixmap.isNull()) {
|
||||
imageData.pixmap = originalPixmap.scaled(Constants::MODELNODE_PREVIEW_IMAGE_DIMENSIONS * 2,
|
||||
Constants::MODELNODE_PREVIEW_IMAGE_DIMENSIONS * 2,
|
||||
Qt::KeepAspectRatio);
|
||||
imageData.pixmap.setDevicePixelRatio(2.);
|
||||
|
||||
double imgSize = double(imageFi.size());
|
||||
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\n%3%4 (%5)").arg(originalPixmap.width()).arg(originalPixmap.height())
|
||||
.arg(QString::number(imgSize, 'g', 3)).arg(units[unitIndex]).arg(imageFi.suffix());
|
||||
localDataMap.insert(imageSource, imageData);
|
||||
}
|
||||
imageData.info = QStringLiteral("%1 x %2 (%3%4)").arg(originalPixmap.width()).arg(originalPixmap.height())
|
||||
.arg(QString::number(imgSize, 'g', 3)).arg(units[unitIndex]);
|
||||
localDataMap.insert(imageSource, imageData);
|
||||
}
|
||||
}
|
||||
|
||||
return imageDataToVariant(imageData);
|
||||
}
|
||||
|
||||
QVariant NodeInstanceView::previewImageDataForGenericNode(const ModelNode &modelNode)
|
||||
QVariant NodeInstanceView::previewImageDataForGenericNode(const ModelNode &modelNode, const ModelNode &renderNode)
|
||||
{
|
||||
QFileInfo docFi = QFileInfo(modelNode.model()->fileUrl().toLocalFile());
|
||||
QHash<QString, ImageData> &localDataMap = imageDataMap[docFi.absoluteFilePath()];
|
||||
ImageData imageData;
|
||||
static const QPixmap 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
|
||||
@@ -1640,10 +1676,9 @@ QVariant NodeInstanceView::previewImageDataForGenericNode(const ModelNode &model
|
||||
} else {
|
||||
imageData.type = QString::fromLatin1(modelNode.type());
|
||||
imageData.id = id;
|
||||
imageData.pixmap = placeHolder;
|
||||
localDataMap.insert(id, imageData);
|
||||
}
|
||||
requestModelNodePreviewImage(modelNode);
|
||||
requestModelNodePreviewImage(modelNode, renderNode);
|
||||
|
||||
return imageDataToVariant(imageData);
|
||||
}
|
||||
|
Reference in New Issue
Block a user