forked from qt-creator/qt-creator
QmlDesigner: Change ImageCache to use new qml-renderer puppet
ImageCacheCollector now uses new qml-renderer puppet to generate preview images. Removed -W and -H args from qml-renderer and added --minW, --minH, --maxW and --maxH args to specify acceptable range for final scaled size of the image. If natural size of the rendered image fits within this range, then the image is not scaled. Added --libIcon arg to qml-renderer to suppress background on 3D nodes. Also changed item library icons to respect aspect ratio. Fixes: QDS-14692 Change-Id: I88f3461626f69191770c0c5e7d79c14d7e82e609 Reviewed-by: Mahmoud Badri <mahmoud.badri@qt.io> Reviewed-by: Marco Bubke <marco.bubke@qt.io>
This commit is contained in:
@@ -38,6 +38,7 @@ Item {
|
|||||||
width: ItemLibraryBackend.itemLibraryIconWidth // to be set in Qml context
|
width: ItemLibraryBackend.itemLibraryIconWidth // to be set in Qml context
|
||||||
height: ItemLibraryBackend.itemLibraryIconHeight // to be set in Qml context
|
height: ItemLibraryBackend.itemLibraryIconHeight // to be set in Qml context
|
||||||
source: itemLibraryIconPath // to be set by model
|
source: itemLibraryIconPath // to be set by model
|
||||||
|
fillMode: Image.PreserveAspectFit
|
||||||
|
|
||||||
// Icons generated for components can change if the component is edited,
|
// Icons generated for components can change if the component is edited,
|
||||||
// so don't cache them locally at Image level.
|
// so don't cache them locally at Image level.
|
||||||
|
@@ -36,8 +36,6 @@ public:
|
|||||||
const QUrl &resourceUrl,
|
const QUrl &resourceUrl,
|
||||||
const QHash<QString, QVariantMap> &edit3dToolStates,
|
const QHash<QString, QVariantMap> &edit3dToolStates,
|
||||||
const QString &language,
|
const QString &language,
|
||||||
QSize captureImageMinimumSize,
|
|
||||||
QSize captureImageMaximumSize,
|
|
||||||
qint32 stateInstanceId)
|
qint32 stateInstanceId)
|
||||||
: instances(instanceContainer)
|
: instances(instanceContainer)
|
||||||
, reparentInstances(reparentContainer)
|
, reparentInstances(reparentContainer)
|
||||||
@@ -51,8 +49,6 @@ public:
|
|||||||
, resourceUrl(resourceUrl)
|
, resourceUrl(resourceUrl)
|
||||||
, edit3dToolStates(edit3dToolStates)
|
, edit3dToolStates(edit3dToolStates)
|
||||||
, language(language)
|
, language(language)
|
||||||
, captureImageMinimumSize(captureImageMinimumSize)
|
|
||||||
, captureImageMaximumSize(captureImageMaximumSize)
|
|
||||||
, stateInstanceId{stateInstanceId}
|
, stateInstanceId{stateInstanceId}
|
||||||
{}
|
{}
|
||||||
|
|
||||||
@@ -71,8 +67,6 @@ public:
|
|||||||
out << command.edit3dToolStates;
|
out << command.edit3dToolStates;
|
||||||
out << command.language;
|
out << command.language;
|
||||||
out << command.stateInstanceId;
|
out << command.stateInstanceId;
|
||||||
out << command.captureImageMinimumSize;
|
|
||||||
out << command.captureImageMaximumSize;
|
|
||||||
|
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
@@ -92,8 +86,6 @@ public:
|
|||||||
in >> command.edit3dToolStates;
|
in >> command.edit3dToolStates;
|
||||||
in >> command.language;
|
in >> command.language;
|
||||||
in >> command.stateInstanceId;
|
in >> command.stateInstanceId;
|
||||||
in >> command.captureImageMinimumSize;
|
|
||||||
in >> command.captureImageMaximumSize;
|
|
||||||
|
|
||||||
return in;
|
return in;
|
||||||
}
|
}
|
||||||
@@ -111,8 +103,6 @@ public:
|
|||||||
QUrl resourceUrl;
|
QUrl resourceUrl;
|
||||||
QHash<QString, QVariantMap> edit3dToolStates;
|
QHash<QString, QVariantMap> edit3dToolStates;
|
||||||
QString language;
|
QString language;
|
||||||
QSize captureImageMinimumSize;
|
|
||||||
QSize captureImageMaximumSize;
|
|
||||||
qint32 stateInstanceId = 0;
|
qint32 stateInstanceId = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -517,8 +517,6 @@ extend_qtc_plugin(QmlDesigner
|
|||||||
SOURCES
|
SOURCES
|
||||||
imagecachecollector.cpp
|
imagecachecollector.cpp
|
||||||
imagecachecollector.h
|
imagecachecollector.h
|
||||||
imagecacheconnectionmanager.cpp
|
|
||||||
imagecacheconnectionmanager.h
|
|
||||||
imagecachefontcollector.cpp
|
imagecachefontcollector.cpp
|
||||||
imagecachefontcollector.h
|
imagecachefontcollector.h
|
||||||
meshimagecachecollector.cpp
|
meshimagecachecollector.cpp
|
||||||
|
@@ -13,7 +13,6 @@
|
|||||||
#include <imagecache/imagecachestorage.h>
|
#include <imagecache/imagecachestorage.h>
|
||||||
#include <imagecache/timestampprovider.h>
|
#include <imagecache/timestampprovider.h>
|
||||||
#include <imagecachecollectors/imagecachecollector.h>
|
#include <imagecachecollectors/imagecachecollector.h>
|
||||||
#include <imagecachecollectors/imagecacheconnectionmanager.h>
|
|
||||||
#include <imagecachecollectors/imagecachefontcollector.h>
|
#include <imagecachecollectors/imagecachefontcollector.h>
|
||||||
#include <modelnodeoperations.h>
|
#include <modelnodeoperations.h>
|
||||||
#include <nodelistproperty.h>
|
#include <nodelistproperty.h>
|
||||||
|
@@ -12,7 +12,6 @@
|
|||||||
#include <imagecache/imagecachestorage.h>
|
#include <imagecache/imagecachestorage.h>
|
||||||
#include <imagecache/timestampprovider.h>
|
#include <imagecache/timestampprovider.h>
|
||||||
#include <imagecachecollectors/imagecachecollector.h>
|
#include <imagecachecollectors/imagecachecollector.h>
|
||||||
#include <imagecachecollectors/imagecacheconnectionmanager.h>
|
|
||||||
|
|
||||||
#include <sqlitedatabase.h>
|
#include <sqlitedatabase.h>
|
||||||
|
|
||||||
|
@@ -2,50 +2,31 @@
|
|||||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
||||||
|
|
||||||
#include "imagecachecollector.h"
|
#include "imagecachecollector.h"
|
||||||
#include "imagecacheconnectionmanager.h"
|
|
||||||
|
|
||||||
#include <model.h>
|
#include <externaldependenciesinterface.h>
|
||||||
#include <nodeinstanceview.h>
|
#include <qmlpuppetpaths.h>
|
||||||
#include <nodemetainfo.h>
|
#include <qprocessuniqueptr.h>
|
||||||
#include <plaintexteditmodifier.h>
|
|
||||||
#include <rewriterview.h>
|
|
||||||
|
|
||||||
#include <projectexplorer/project.h>
|
#include <projectexplorer/project.h>
|
||||||
#include <projectexplorer/target.h>
|
#include <projectexplorer/target.h>
|
||||||
#include <utils/fileutils.h>
|
#include <utils/fileutils.h>
|
||||||
|
|
||||||
|
#include <QDir>
|
||||||
#include <QGuiApplication>
|
#include <QGuiApplication>
|
||||||
#include <QPlainTextEdit>
|
#include <QProcess>
|
||||||
|
#include <QTemporaryDir>
|
||||||
|
|
||||||
namespace QmlDesigner {
|
namespace QmlDesigner {
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
QByteArray fileToByteArray(const QString &filename)
|
|
||||||
{
|
|
||||||
QFile file(filename);
|
|
||||||
QFileInfo fleInfo(file);
|
|
||||||
|
|
||||||
if (fleInfo.exists() && file.open(QFile::ReadOnly))
|
|
||||||
return file.readAll();
|
|
||||||
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
QString fileToString(const QString &filename)
|
|
||||||
{
|
|
||||||
return QString::fromUtf8(fileToByteArray(filename));
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
ImageCacheCollector::ImageCacheCollector(ImageCacheConnectionManager &connectionManager,
|
ImageCacheCollector::ImageCacheCollector(QSize captureImageMinimumSize,
|
||||||
QSize captureImageMinimumSize,
|
|
||||||
QSize captureImageMaximumSize,
|
QSize captureImageMaximumSize,
|
||||||
ExternalDependenciesInterface &externalDependencies,
|
ExternalDependenciesInterface &externalDependencies,
|
||||||
ImageCacheCollectorNullImageHandling nullImageHandling)
|
ImageCacheCollectorNullImageHandling nullImageHandling)
|
||||||
: m_connectionManager{connectionManager}
|
: captureImageMinimumSize{captureImageMinimumSize}
|
||||||
, captureImageMinimumSize{captureImageMinimumSize}
|
|
||||||
, captureImageMaximumSize{captureImageMaximumSize}
|
, captureImageMaximumSize{captureImageMaximumSize}
|
||||||
, m_externalDependencies{externalDependencies}
|
, m_externalDependencies{externalDependencies}
|
||||||
, nullImageHandling{nullImageHandling}
|
, nullImageHandling{nullImageHandling}
|
||||||
@@ -65,108 +46,41 @@ QImage scaleImage(const QImage &image, QSize targetSize)
|
|||||||
QSize scaledImageSize = image.size().scaled(targetSize.boundedTo(image.size()),
|
QSize scaledImageSize = image.size().scaled(targetSize.boundedTo(image.size()),
|
||||||
Qt::KeepAspectRatio);
|
Qt::KeepAspectRatio);
|
||||||
return image.scaled(scaledImageSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
|
return image.scaled(scaledImageSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
|
||||||
|
|
||||||
}
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
void ImageCacheCollector::start(Utils::SmallStringView name,
|
void ImageCacheCollector::start(Utils::SmallStringView name,
|
||||||
Utils::SmallStringView state,
|
Utils::SmallStringView,
|
||||||
const ImageCache::AuxiliaryData &auxiliaryData,
|
const ImageCache::AuxiliaryData &auxiliaryData,
|
||||||
CaptureCallback captureCallback,
|
CaptureCallback captureCallback,
|
||||||
AbortCallback abortCallback,
|
AbortCallback abortCallback,
|
||||||
ImageCache::TraceToken traceToken)
|
ImageCache::TraceToken traceToken)
|
||||||
{
|
{
|
||||||
#ifdef QDS_USE_PROJECTSTORAGE
|
|
||||||
if (!m_projectStorage || !m_pathCache)
|
|
||||||
return;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
using namespace NanotraceHR::Literals;
|
using namespace NanotraceHR::Literals;
|
||||||
auto [collectorTraceToken, flowtoken] = traceToken.beginDurationWithFlow(
|
auto [collectorTraceToken, flowtoken] = traceToken.beginDurationWithFlow(
|
||||||
"generate image in standard collector");
|
"generate image in standard collector");
|
||||||
|
|
||||||
RewriterView rewriterView{m_externalDependencies, RewriterView::Amend};
|
QTemporaryDir outDir(QDir::tempPath() + "/qds_imagecache_XXXXXX");
|
||||||
rewriterView.setPossibleImportsEnabled(false);
|
QString outFile = outDir.filePath("capture.png");
|
||||||
NodeInstanceView nodeInstanceView{m_connectionManager, m_externalDependencies};
|
|
||||||
nodeInstanceView.setCaptureImageMinimumAndMaximumSize(captureImageMinimumSize,
|
|
||||||
captureImageMaximumSize);
|
|
||||||
|
|
||||||
const QString filePath{name};
|
QImage captureImage;
|
||||||
#ifdef QDS_USE_PROJECTSTORAGE
|
if (runProcess(createArguments(name, outFile, auxiliaryData))) {
|
||||||
auto model = QmlDesigner::Model::create({*m_projectStorage, *m_pathCache},
|
captureImage.load(outFile);
|
||||||
"Item",
|
} else {
|
||||||
{},
|
|
||||||
QUrl::fromLocalFile(filePath));
|
|
||||||
#else
|
|
||||||
auto model = QmlDesigner::Model::create("QtQuick/Item", 2, 1);
|
|
||||||
model->setFileUrl(QUrl::fromLocalFile(filePath));
|
|
||||||
#endif
|
|
||||||
|
|
||||||
auto textDocument = std::make_unique<QTextDocument>(fileToString(filePath));
|
|
||||||
|
|
||||||
auto modifier = std::make_unique<NotIndentingTextEditModifier>(textDocument.get(),
|
|
||||||
QTextCursor{textDocument.get()});
|
|
||||||
|
|
||||||
rewriterView.setTextModifier(modifier.get());
|
|
||||||
|
|
||||||
model->setRewriterView(&rewriterView);
|
|
||||||
|
|
||||||
auto rootModelNodeMetaInfo = rewriterView.rootModelNode().metaInfo();
|
|
||||||
bool is3DRoot = rewriterView.errors().isEmpty()
|
|
||||||
&& (rootModelNodeMetaInfo.isQtQuick3DNode()
|
|
||||||
|| rootModelNodeMetaInfo.isQtQuick3DMaterial());
|
|
||||||
|
|
||||||
if (!rewriterView.errors().isEmpty() || (!rewriterView.rootModelNode().metaInfo().isGraphicalItem()
|
|
||||||
&& !is3DRoot)) {
|
|
||||||
if (abortCallback)
|
if (abortCallback)
|
||||||
abortCallback(ImageCache::AbortReason::Failed, std::move(flowtoken));
|
abortCallback(ImageCache::AbortReason::Failed, std::move(flowtoken));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is3DRoot) {
|
|
||||||
if (auto libIcon = std::get_if<ImageCache::LibraryIconAuxiliaryData>(&auxiliaryData))
|
|
||||||
rewriterView.rootModelNode().setAuxiliaryData(AuxiliaryDataType::NodeInstancePropertyOverwrite,
|
|
||||||
"isLibraryIcon",
|
|
||||||
libIcon->enable);
|
|
||||||
}
|
|
||||||
|
|
||||||
ModelNode stateNode = rewriterView.modelNodeForId(QString{state});
|
|
||||||
|
|
||||||
if (stateNode.isValid())
|
|
||||||
rewriterView.setCurrentStateNode(stateNode);
|
|
||||||
|
|
||||||
QImage captureImage;
|
|
||||||
|
|
||||||
auto callback = [&](const QImage &image) { captureImage = image; };
|
|
||||||
|
|
||||||
if (!m_target)
|
|
||||||
return;
|
|
||||||
|
|
||||||
nodeInstanceView.setTarget(m_target.data());
|
|
||||||
m_connectionManager.setCallback(std::move(callback));
|
|
||||||
bool isCrashed = false;
|
|
||||||
nodeInstanceView.setCrashCallback([&] { isCrashed = true; });
|
|
||||||
model->setNodeInstanceView(&nodeInstanceView);
|
|
||||||
|
|
||||||
bool capturedDataArrived = m_connectionManager.waitForCapturedData();
|
|
||||||
|
|
||||||
m_connectionManager.setCallback({});
|
|
||||||
m_connectionManager.setCrashCallback({});
|
|
||||||
|
|
||||||
model->setNodeInstanceView({});
|
|
||||||
model->setRewriterView({});
|
|
||||||
|
|
||||||
if (isCrashed)
|
|
||||||
abortCallback(ImageCache::AbortReason::Failed, std::move(flowtoken));
|
|
||||||
|
|
||||||
if (!capturedDataArrived && abortCallback)
|
|
||||||
abortCallback(ImageCache::AbortReason::Failed, std::move(flowtoken));
|
|
||||||
|
|
||||||
if (nullImageHandling == ImageCacheCollectorNullImageHandling::CaptureNullImage
|
if (nullImageHandling == ImageCacheCollectorNullImageHandling::CaptureNullImage
|
||||||
|| !captureImage.isNull()) {
|
|| !captureImage.isNull()) {
|
||||||
QImage midSizeImage = scaleImage(captureImage, QSize{300, 300});
|
QImage midSizeImage = scaleImage(captureImage, QSize{300, 300});
|
||||||
QImage smallImage = scaleImage(midSizeImage, QSize{96, 96});
|
QImage smallImage = scaleImage(midSizeImage, QSize{96, 96});
|
||||||
captureCallback(captureImage, midSizeImage, smallImage, std::move(flowtoken));
|
captureCallback(captureImage, midSizeImage, smallImage, std::move(flowtoken));
|
||||||
|
} else {
|
||||||
|
if (abortCallback)
|
||||||
|
abortCallback(ImageCache::AbortReason::Failed, std::move(flowtoken));
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -193,4 +107,72 @@ ProjectExplorer::Target *ImageCacheCollector::target() const
|
|||||||
return m_target;
|
return m_target;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QStringList ImageCacheCollector::createArguments(Utils::SmallStringView name,
|
||||||
|
const QString &outFile,
|
||||||
|
const ImageCache::AuxiliaryData &auxiliaryData) const
|
||||||
|
{
|
||||||
|
QStringList arguments;
|
||||||
|
const QString filePath{name};
|
||||||
|
|
||||||
|
arguments.append("--qml-renderer");
|
||||||
|
arguments.append(filePath);
|
||||||
|
|
||||||
|
if (m_target && m_target->project()) {
|
||||||
|
arguments.append("-i");
|
||||||
|
arguments.append(m_target->project()->projectDirectory().toFSPathString());
|
||||||
|
}
|
||||||
|
|
||||||
|
arguments.append("-o");
|
||||||
|
arguments.append(outFile);
|
||||||
|
|
||||||
|
if (std::holds_alternative<ImageCache::LibraryIconAuxiliaryData>(auxiliaryData))
|
||||||
|
arguments.append("--libIcon");
|
||||||
|
|
||||||
|
if (captureImageMinimumSize.isValid()) {
|
||||||
|
arguments.append("--minW");
|
||||||
|
arguments.append(QString::number(captureImageMinimumSize.width()));
|
||||||
|
arguments.append("--minH");
|
||||||
|
arguments.append(QString::number(captureImageMinimumSize.height()));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (captureImageMaximumSize.isValid()) {
|
||||||
|
arguments.append("--maxW");
|
||||||
|
arguments.append(QString::number(captureImageMaximumSize.width()));
|
||||||
|
arguments.append("--maxH");
|
||||||
|
arguments.append(QString::number(captureImageMaximumSize.height()));
|
||||||
|
}
|
||||||
|
|
||||||
|
return arguments;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ImageCacheCollector::runProcess(const QStringList &arguments) const
|
||||||
|
{
|
||||||
|
if (!m_target)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
auto [workingDirectoryPath, puppetPath] = QmlDesigner::QmlPuppetPaths::qmlPuppetPaths(
|
||||||
|
target(), m_externalDependencies.designerSettings());
|
||||||
|
if (puppetPath.isEmpty())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
QProcessUniquePointer puppetProcess{new QProcess};
|
||||||
|
|
||||||
|
QObject::connect(QCoreApplication::instance(),
|
||||||
|
&QCoreApplication::aboutToQuit,
|
||||||
|
puppetProcess.get(),
|
||||||
|
&QProcess::kill);
|
||||||
|
|
||||||
|
puppetProcess->setWorkingDirectory(workingDirectoryPath.toFSPathString());
|
||||||
|
puppetProcess->setProcessChannelMode(QProcess::ForwardedChannels);
|
||||||
|
|
||||||
|
puppetProcess->start(puppetPath.toFSPathString(), arguments);
|
||||||
|
|
||||||
|
if (puppetProcess->waitForFinished(30000)) {
|
||||||
|
return puppetProcess->exitStatus() == QProcess::ExitStatus::NormalExit
|
||||||
|
&& puppetProcess->exitCode() == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace QmlDesigner
|
} // namespace QmlDesigner
|
||||||
|
@@ -5,25 +5,14 @@
|
|||||||
|
|
||||||
#include <imagecache/imagecachecollectorinterface.h>
|
#include <imagecache/imagecachecollectorinterface.h>
|
||||||
|
|
||||||
#include <modelfwd.h>
|
|
||||||
|
|
||||||
#include <QPointer>
|
#include <QPointer>
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
|
||||||
class QTextDocument;
|
|
||||||
QT_END_NAMESPACE
|
|
||||||
|
|
||||||
namespace ProjectExplorer {
|
namespace ProjectExplorer {
|
||||||
class Target;
|
class Target;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace QmlDesigner {
|
namespace QmlDesigner {
|
||||||
|
|
||||||
class Model;
|
|
||||||
class NotIndentingTextEditModifier;
|
|
||||||
class ImageCacheConnectionManager;
|
|
||||||
class RewriterView;
|
|
||||||
class NodeInstanceView;
|
|
||||||
class ExternalDependenciesInterface;
|
class ExternalDependenciesInterface;
|
||||||
|
|
||||||
enum class ImageCacheCollectorNullImageHandling { CaptureNullImage, DontCaptureNullImage };
|
enum class ImageCacheCollectorNullImageHandling { CaptureNullImage, DontCaptureNullImage };
|
||||||
@@ -31,8 +20,7 @@ enum class ImageCacheCollectorNullImageHandling { CaptureNullImage, DontCaptureN
|
|||||||
class ImageCacheCollector final : public ImageCacheCollectorInterface
|
class ImageCacheCollector final : public ImageCacheCollectorInterface
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ImageCacheCollector(ImageCacheConnectionManager &connectionManager,
|
ImageCacheCollector(QSize captureImageMinimumSize,
|
||||||
QSize captureImageMinimumSize,
|
|
||||||
QSize captureImageMaximumSize,
|
QSize captureImageMaximumSize,
|
||||||
ExternalDependenciesInterface &externalDependencies,
|
ExternalDependenciesInterface &externalDependencies,
|
||||||
ImageCacheCollectorNullImageHandling nullImageHandling = {});
|
ImageCacheCollectorNullImageHandling nullImageHandling = {});
|
||||||
@@ -58,16 +46,17 @@ public:
|
|||||||
ProjectExplorer::Target *target() const;
|
ProjectExplorer::Target *target() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ImageCacheConnectionManager &m_connectionManager;
|
bool runProcess(const QStringList &arguments) const;
|
||||||
|
QStringList createArguments(Utils::SmallStringView name,
|
||||||
|
const QString &outFile,
|
||||||
|
const ImageCache::AuxiliaryData &auxiliaryData) const;
|
||||||
|
|
||||||
|
private:
|
||||||
QPointer<ProjectExplorer::Target> m_target;
|
QPointer<ProjectExplorer::Target> m_target;
|
||||||
QSize captureImageMinimumSize;
|
QSize captureImageMinimumSize;
|
||||||
QSize captureImageMaximumSize;
|
QSize captureImageMaximumSize;
|
||||||
ExternalDependenciesInterface &m_externalDependencies;
|
ExternalDependenciesInterface &m_externalDependencies;
|
||||||
ImageCacheCollectorNullImageHandling nullImageHandling{};
|
ImageCacheCollectorNullImageHandling nullImageHandling{};
|
||||||
#ifdef QDS_USE_PROJECTSTORAGE
|
|
||||||
ProjectStorageType *m_projectStorage = nullptr;
|
|
||||||
PathCacheType *m_pathCache = nullptr;
|
|
||||||
#endif
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace QmlDesigner
|
} // namespace QmlDesigner
|
||||||
|
@@ -1,56 +0,0 @@
|
|||||||
// Copyright (C) 2022 The Qt Company Ltd.
|
|
||||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
|
||||||
|
|
||||||
#include "imagecacheconnectionmanager.h"
|
|
||||||
|
|
||||||
#include <captureddatacommand.h>
|
|
||||||
|
|
||||||
#include <QLocalSocket>
|
|
||||||
|
|
||||||
namespace QmlDesigner {
|
|
||||||
|
|
||||||
ImageCacheConnectionManager::ImageCacheConnectionManager()
|
|
||||||
{
|
|
||||||
connections().emplace_back("Capture icon", "captureiconmode");
|
|
||||||
}
|
|
||||||
|
|
||||||
void ImageCacheConnectionManager::setCallback(ImageCacheConnectionManager::Callback callback)
|
|
||||||
{
|
|
||||||
m_captureCallback = std::move(callback);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ImageCacheConnectionManager::waitForCapturedData()
|
|
||||||
{
|
|
||||||
if (connections().empty())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
disconnect(connections().front().socket.get(), &QIODevice::readyRead, nullptr, nullptr);
|
|
||||||
|
|
||||||
while (!m_capturedDataArrived) {
|
|
||||||
if (!(connections().front().socket))
|
|
||||||
return false;
|
|
||||||
bool dataArrived = connections().front().socket->waitForReadyRead(10000);
|
|
||||||
|
|
||||||
if (!dataArrived)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
readDataStream(connections().front());
|
|
||||||
}
|
|
||||||
|
|
||||||
m_capturedDataArrived = false;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ImageCacheConnectionManager::dispatchCommand(const QVariant &command,
|
|
||||||
ConnectionManagerInterface::Connection &)
|
|
||||||
{
|
|
||||||
static const int capturedDataCommandType = QMetaType::fromName("CapturedDataCommand").id();
|
|
||||||
|
|
||||||
if (command.typeId() == capturedDataCommandType) {
|
|
||||||
m_captureCallback(command.value<CapturedDataCommand>().image);
|
|
||||||
m_capturedDataArrived = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace QmlDesigner
|
|
@@ -1,31 +0,0 @@
|
|||||||
// Copyright (C) 2022 The Qt Company Ltd.
|
|
||||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <instances/connectionmanager.h>
|
|
||||||
|
|
||||||
namespace QmlDesigner {
|
|
||||||
|
|
||||||
class CapturedDataCommand;
|
|
||||||
|
|
||||||
class ImageCacheConnectionManager : public ConnectionManager
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
using Callback = std::function<void(const QImage &)>;
|
|
||||||
|
|
||||||
ImageCacheConnectionManager();
|
|
||||||
|
|
||||||
void setCallback(Callback captureCallback);
|
|
||||||
|
|
||||||
bool waitForCapturedData();
|
|
||||||
|
|
||||||
protected:
|
|
||||||
void dispatchCommand(const QVariant &command, Connection &connection) override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
Callback m_captureCallback;
|
|
||||||
bool m_capturedDataArrived = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace QmlDesigner
|
|
@@ -2,7 +2,6 @@
|
|||||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
||||||
|
|
||||||
#include "meshimagecachecollector.h"
|
#include "meshimagecachecollector.h"
|
||||||
#include "imagecacheconnectionmanager.h"
|
|
||||||
|
|
||||||
#include <projectexplorer/target.h>
|
#include <projectexplorer/target.h>
|
||||||
#include <utils/smallstring.h>
|
#include <utils/smallstring.h>
|
||||||
@@ -12,13 +11,11 @@
|
|||||||
|
|
||||||
namespace QmlDesigner {
|
namespace QmlDesigner {
|
||||||
|
|
||||||
MeshImageCacheCollector::MeshImageCacheCollector(ImageCacheConnectionManager &connectionManager,
|
MeshImageCacheCollector::MeshImageCacheCollector(QSize captureImageMinimumSize,
|
||||||
QSize captureImageMinimumSize,
|
|
||||||
QSize captureImageMaximumSize,
|
QSize captureImageMaximumSize,
|
||||||
ExternalDependenciesInterface &externalDependencies,
|
ExternalDependenciesInterface &externalDependencies,
|
||||||
ImageCacheCollectorNullImageHandling nullImageHandling)
|
ImageCacheCollectorNullImageHandling nullImageHandling)
|
||||||
: m_imageCacheCollector(connectionManager,
|
: m_imageCacheCollector(captureImageMinimumSize,
|
||||||
captureImageMinimumSize,
|
|
||||||
captureImageMaximumSize,
|
captureImageMaximumSize,
|
||||||
externalDependencies,
|
externalDependencies,
|
||||||
nullImageHandling)
|
nullImageHandling)
|
||||||
|
@@ -11,13 +11,10 @@ class Target;
|
|||||||
|
|
||||||
namespace QmlDesigner {
|
namespace QmlDesigner {
|
||||||
|
|
||||||
class ImageCacheConnectionManager;
|
|
||||||
|
|
||||||
class MeshImageCacheCollector final : public ImageCacheCollectorInterface
|
class MeshImageCacheCollector final : public ImageCacheCollectorInterface
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
MeshImageCacheCollector(ImageCacheConnectionManager &connectionManager,
|
MeshImageCacheCollector(QSize captureImageMinimumSize,
|
||||||
QSize captureImageMinimumSize,
|
|
||||||
QSize captureImageMaximumSize,
|
QSize captureImageMaximumSize,
|
||||||
ExternalDependenciesInterface &externalDependencies,
|
ExternalDependenciesInterface &externalDependencies,
|
||||||
ImageCacheCollectorNullImageHandling nullImageHandling = {});
|
ImageCacheCollectorNullImageHandling nullImageHandling = {});
|
||||||
|
@@ -1272,8 +1272,6 @@ CreateSceneCommand NodeInstanceView::createCreateSceneCommand()
|
|||||||
m_externalDependencies.currentResourcePath(),
|
m_externalDependencies.currentResourcePath(),
|
||||||
sceneStates,
|
sceneStates,
|
||||||
lastUsedLanguage,
|
lastUsedLanguage,
|
||||||
m_captureImageMinimumSize,
|
|
||||||
m_captureImageMaximumSize,
|
|
||||||
stateInstanceId);
|
stateInstanceId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -156,13 +156,6 @@ public:
|
|||||||
m_crashCallback = std::move(crashCallback);
|
m_crashCallback = std::move(crashCallback);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setCaptureImageMinimumAndMaximumSize(QSize captureImageMinimumSize,
|
|
||||||
QSize captureImageMaximumSize)
|
|
||||||
{
|
|
||||||
m_captureImageMinimumSize = captureImageMinimumSize;
|
|
||||||
m_captureImageMaximumSize = captureImageMaximumSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
void startNanotrace();
|
void startNanotrace();
|
||||||
void endNanotrace();
|
void endNanotrace();
|
||||||
|
|
||||||
@@ -313,8 +306,6 @@ private:
|
|||||||
QHash<QString, QStringList> m_qsbPathToFilterMap;
|
QHash<QString, QStringList> m_qsbPathToFilterMap;
|
||||||
int m_remainingQsbTargets = 0;
|
int m_remainingQsbTargets = 0;
|
||||||
QTimer m_rotBlockTimer;
|
QTimer m_rotBlockTimer;
|
||||||
QSize m_captureImageMinimumSize{150, 150};
|
|
||||||
QSize m_captureImageMaximumSize{1000, 1000};
|
|
||||||
bool m_qsbEnabled = false;
|
bool m_qsbEnabled = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -33,7 +33,6 @@
|
|||||||
#include <imagecache/imagecachestorage.h>
|
#include <imagecache/imagecachestorage.h>
|
||||||
#include <imagecache/timestampprovider.h>
|
#include <imagecache/timestampprovider.h>
|
||||||
#include <imagecachecollectors/imagecachecollector.h>
|
#include <imagecachecollectors/imagecachecollector.h>
|
||||||
#include <imagecachecollectors/imagecacheconnectionmanager.h>
|
|
||||||
#include <imagecachecollectors/meshimagecachecollector.h>
|
#include <imagecachecollectors/meshimagecachecollector.h>
|
||||||
#include <imagecachecollectors/textureimagecachecollector.h>
|
#include <imagecachecollectors/textureimagecachecollector.h>
|
||||||
|
|
||||||
@@ -124,8 +123,8 @@ class QmlDesignerProjectManager::ImageCacheData
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ImageCacheData(ExternalDependenciesInterface &externalDependencies)
|
ImageCacheData(ExternalDependenciesInterface &externalDependencies)
|
||||||
: meshImageCollector{connectionManager, QSize{300, 300}, QSize{600, 600}, externalDependencies}
|
: meshImageCollector{QSize{300, 300}, QSize{600, 600}, externalDependencies}
|
||||||
, nodeInstanceCollector{connectionManager, QSize{300, 300}, QSize{600, 600}, externalDependencies}
|
, nodeInstanceCollector{QSize{300, 300}, QSize{600, 600}, externalDependencies}
|
||||||
{}
|
{}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@@ -134,7 +133,6 @@ public:
|
|||||||
Sqlite::JournalMode::Wal,
|
Sqlite::JournalMode::Wal,
|
||||||
Sqlite::LockingMode::Normal};
|
Sqlite::LockingMode::Normal};
|
||||||
ImageCacheStorage<Sqlite::Database> storage{database};
|
ImageCacheStorage<Sqlite::Database> storage{database};
|
||||||
ImageCacheConnectionManager connectionManager;
|
|
||||||
MeshImageCacheCollector meshImageCollector;
|
MeshImageCacheCollector meshImageCollector;
|
||||||
TextureImageCacheCollector textureImageCollector;
|
TextureImageCacheCollector textureImageCollector;
|
||||||
ImageCacheCollector nodeInstanceCollector;
|
ImageCacheCollector nodeInstanceCollector;
|
||||||
@@ -153,8 +151,7 @@ class QmlDesignerProjectManager::PreviewImageCacheData
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
PreviewImageCacheData(ExternalDependenciesInterface &externalDependencies)
|
PreviewImageCacheData(ExternalDependenciesInterface &externalDependencies)
|
||||||
: collector{connectionManager,
|
: collector{QSize{300, 300},
|
||||||
QSize{300, 300},
|
|
||||||
QSize{1000, 1000},
|
QSize{1000, 1000},
|
||||||
externalDependencies,
|
externalDependencies,
|
||||||
ImageCacheCollectorNullImageHandling::CaptureNullImage}
|
ImageCacheCollectorNullImageHandling::CaptureNullImage}
|
||||||
@@ -168,7 +165,6 @@ public:
|
|||||||
Sqlite::JournalMode::Wal,
|
Sqlite::JournalMode::Wal,
|
||||||
Sqlite::LockingMode::Normal};
|
Sqlite::LockingMode::Normal};
|
||||||
ImageCacheStorage<Sqlite::Database> storage{database};
|
ImageCacheStorage<Sqlite::Database> storage{database};
|
||||||
ImageCacheConnectionManager connectionManager;
|
|
||||||
ImageCacheCollector collector;
|
ImageCacheCollector collector;
|
||||||
PreviewTimeStampProvider timeStampProvider;
|
PreviewTimeStampProvider timeStampProvider;
|
||||||
AsynchronousExplicitImageCache cache{storage};
|
AsynchronousExplicitImageCache cache{storage};
|
||||||
@@ -255,8 +251,7 @@ public:
|
|||||||
::ProjectExplorer::Project *project,
|
::ProjectExplorer::Project *project,
|
||||||
PathCacheType &pathCache,
|
PathCacheType &pathCache,
|
||||||
ExternalDependenciesInterface &externalDependencies)
|
ExternalDependenciesInterface &externalDependencies)
|
||||||
: collector{connectionManager,
|
: collector{QSize{300, 300},
|
||||||
QSize{300, 300},
|
|
||||||
QSize{1000, 1000},
|
QSize{1000, 1000},
|
||||||
externalDependencies,
|
externalDependencies,
|
||||||
ImageCacheCollectorNullImageHandling::CaptureNullImage}
|
ImageCacheCollectorNullImageHandling::CaptureNullImage}
|
||||||
@@ -264,7 +259,6 @@ public:
|
|||||||
, projectStorageData{createProjectStorageData(project, pathCache)}
|
, projectStorageData{createProjectStorageData(project, pathCache)}
|
||||||
{}
|
{}
|
||||||
|
|
||||||
ImageCacheConnectionManager connectionManager;
|
|
||||||
ImageCacheCollector collector;
|
ImageCacheCollector collector;
|
||||||
PreviewTimeStampProvider timeStampProvider;
|
PreviewTimeStampProvider timeStampProvider;
|
||||||
AsynchronousImageFactory factory;
|
AsynchronousImageFactory factory;
|
||||||
|
@@ -168,7 +168,6 @@ extend_qtc_executable(qmlpuppet
|
|||||||
qt5capturepreviewnodeinstanceserver.cpp qt5capturepreviewnodeinstanceserver.h
|
qt5capturepreviewnodeinstanceserver.cpp qt5capturepreviewnodeinstanceserver.h
|
||||||
nodeinstanceserverdispatcher.cpp nodeinstanceserverdispatcher.h
|
nodeinstanceserverdispatcher.cpp nodeinstanceserverdispatcher.h
|
||||||
capturenodeinstanceserverdispatcher.cpp capturenodeinstanceserverdispatcher.h
|
capturenodeinstanceserverdispatcher.cpp capturenodeinstanceserverdispatcher.h
|
||||||
qt5captureimagenodeinstanceserver.cpp qt5captureimagenodeinstanceserver.h
|
|
||||||
viewconfig.cpp viewconfig.h
|
viewconfig.cpp viewconfig.h
|
||||||
animationdriver.cpp animationdriver.h
|
animationdriver.cpp animationdriver.h
|
||||||
)
|
)
|
||||||
|
@@ -22,7 +22,6 @@ versionAtLeast(QT_VERSION, 5.15.0) {
|
|||||||
HEADERS += $$PWD/qt5nodeinstanceserver.h \
|
HEADERS += $$PWD/qt5nodeinstanceserver.h \
|
||||||
$$PWD/capturenodeinstanceserverdispatcher.h \
|
$$PWD/capturenodeinstanceserverdispatcher.h \
|
||||||
$$PWD/nodeinstanceserverdispatcher.h \
|
$$PWD/nodeinstanceserverdispatcher.h \
|
||||||
$$PWD/qt5captureimagenodeinstanceserver.h \
|
|
||||||
$$PWD/qt5capturepreviewnodeinstanceserver.h \
|
$$PWD/qt5capturepreviewnodeinstanceserver.h \
|
||||||
$$PWD/qt5testnodeinstanceserver.h \
|
$$PWD/qt5testnodeinstanceserver.h \
|
||||||
$$PWD/qt5bakelightsnodeinstanceserver.h \
|
$$PWD/qt5bakelightsnodeinstanceserver.h \
|
||||||
@@ -58,7 +57,6 @@ HEADERS += $$PWD/qt5nodeinstanceserver.h \
|
|||||||
SOURCES += $$PWD/qt5nodeinstanceserver.cpp \
|
SOURCES += $$PWD/qt5nodeinstanceserver.cpp \
|
||||||
$$PWD/capturenodeinstanceserverdispatcher.cpp \
|
$$PWD/capturenodeinstanceserverdispatcher.cpp \
|
||||||
$$PWD/nodeinstanceserverdispatcher.cpp \
|
$$PWD/nodeinstanceserverdispatcher.cpp \
|
||||||
$$PWD/qt5captureimagenodeinstanceserver.cpp \
|
|
||||||
$$PWD/qt5capturepreviewnodeinstanceserver.cpp \
|
$$PWD/qt5capturepreviewnodeinstanceserver.cpp \
|
||||||
$$PWD/qt5testnodeinstanceserver.cpp \
|
$$PWD/qt5testnodeinstanceserver.cpp \
|
||||||
$$PWD/qt5bakelightsnodeinstanceserver.cpp \
|
$$PWD/qt5bakelightsnodeinstanceserver.cpp \
|
||||||
|
@@ -4,7 +4,6 @@
|
|||||||
#include "nodeinstanceserverdispatcher.h"
|
#include "nodeinstanceserverdispatcher.h"
|
||||||
|
|
||||||
#include "qt5bakelightsnodeinstanceserver.h"
|
#include "qt5bakelightsnodeinstanceserver.h"
|
||||||
#include "qt5captureimagenodeinstanceserver.h"
|
|
||||||
#include "qt5capturepreviewnodeinstanceserver.h"
|
#include "qt5capturepreviewnodeinstanceserver.h"
|
||||||
#include "qt5import3dnodeinstanceserver.h"
|
#include "qt5import3dnodeinstanceserver.h"
|
||||||
#include "qt5informationnodeinstanceserver.h"
|
#include "qt5informationnodeinstanceserver.h"
|
||||||
@@ -164,8 +163,6 @@ std::unique_ptr<NodeInstanceServer> createNodeInstanceServer(
|
|||||||
{
|
{
|
||||||
if (serverName == "capturemode")
|
if (serverName == "capturemode")
|
||||||
return std::make_unique<Qt5CapturePreviewNodeInstanceServer>(nodeInstanceClient);
|
return std::make_unique<Qt5CapturePreviewNodeInstanceServer>(nodeInstanceClient);
|
||||||
else if (serverName == "captureiconmode")
|
|
||||||
return std::make_unique<Qt5CaptureImageNodeInstanceServer>(nodeInstanceClient);
|
|
||||||
else if (serverName == "rendermode")
|
else if (serverName == "rendermode")
|
||||||
return std::make_unique<Qt5RenderNodeInstanceServer>(nodeInstanceClient);
|
return std::make_unique<Qt5RenderNodeInstanceServer>(nodeInstanceClient);
|
||||||
else if (serverName == "editormode")
|
else if (serverName == "editormode")
|
||||||
|
@@ -1,79 +0,0 @@
|
|||||||
// Copyright (C) 2020 The Qt Company Ltd.
|
|
||||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
|
||||||
|
|
||||||
#include "qt5captureimagenodeinstanceserver.h"
|
|
||||||
#include "servernodeinstance.h"
|
|
||||||
|
|
||||||
#include <captureddatacommand.h>
|
|
||||||
#include <createscenecommand.h>
|
|
||||||
#include <nodeinstanceclientinterface.h>
|
|
||||||
|
|
||||||
#include <QImage>
|
|
||||||
#include <QQuickItem>
|
|
||||||
#include <QQuickView>
|
|
||||||
|
|
||||||
#include <private/qquickdesignersupport_p.h>
|
|
||||||
|
|
||||||
namespace QmlDesigner {
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
QImage renderImage(ServerNodeInstance rootNodeInstance, QSize minimumSize, QSize maximumSize)
|
|
||||||
{
|
|
||||||
rootNodeInstance.updateDirtyNodeRecursive();
|
|
||||||
|
|
||||||
QSize previewImageSize = rootNodeInstance.boundingRect().size().toSize();
|
|
||||||
if (previewImageSize.isEmpty()) {
|
|
||||||
previewImageSize = minimumSize;
|
|
||||||
} else if (previewImageSize.width() < minimumSize.width()
|
|
||||||
|| previewImageSize.height() < minimumSize.height()) {
|
|
||||||
previewImageSize.scale(minimumSize, Qt::KeepAspectRatio);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (previewImageSize.width() > maximumSize.width()
|
|
||||||
|| previewImageSize.height() > maximumSize.height()) {
|
|
||||||
previewImageSize.scale(maximumSize, Qt::KeepAspectRatio);
|
|
||||||
}
|
|
||||||
|
|
||||||
QImage previewImage = rootNodeInstance.renderPreviewImage(previewImageSize);
|
|
||||||
|
|
||||||
return previewImage;
|
|
||||||
}
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
void Qt5CaptureImageNodeInstanceServer::collectItemChangesAndSendChangeCommands()
|
|
||||||
{
|
|
||||||
static bool inFunction = false;
|
|
||||||
|
|
||||||
if (!rootNodeInstance().holdsGraphical()) {
|
|
||||||
nodeInstanceClient()->capturedData(CapturedDataCommand{});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!inFunction) {
|
|
||||||
inFunction = true;
|
|
||||||
|
|
||||||
auto rooNodeInstance = rootNodeInstance();
|
|
||||||
if (QQuickItem *qitem = rooNodeInstance.rootQuickItem())
|
|
||||||
qitem->setClip(true);
|
|
||||||
|
|
||||||
QQuickDesignerSupport::polishItems(quickWindow());
|
|
||||||
|
|
||||||
QImage image = renderImage(rooNodeInstance, m_minimumSize, m_maximumSize);
|
|
||||||
|
|
||||||
nodeInstanceClient()->capturedData(CapturedDataCommand{std::move(image)});
|
|
||||||
|
|
||||||
slowDownRenderTimer();
|
|
||||||
inFunction = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void QmlDesigner::Qt5CaptureImageNodeInstanceServer::createScene(const CreateSceneCommand &command)
|
|
||||||
{
|
|
||||||
m_minimumSize = command.captureImageMinimumSize;
|
|
||||||
m_maximumSize = command.captureImageMaximumSize;
|
|
||||||
|
|
||||||
Qt5PreviewNodeInstanceServer::createScene(command);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace
|
|
@@ -1,27 +0,0 @@
|
|||||||
// Copyright (C) 2020 The Qt Company Ltd.
|
|
||||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <qt5previewnodeinstanceserver.h>
|
|
||||||
|
|
||||||
namespace QmlDesigner {
|
|
||||||
|
|
||||||
class Qt5CaptureImageNodeInstanceServer : public Qt5PreviewNodeInstanceServer
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
explicit Qt5CaptureImageNodeInstanceServer(NodeInstanceClientInterface *nodeInstanceClient)
|
|
||||||
: Qt5PreviewNodeInstanceServer(nodeInstanceClient)
|
|
||||||
{}
|
|
||||||
|
|
||||||
void createScene(const CreateSceneCommand &command) override;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
void collectItemChangesAndSendChangeCommands() override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
QSize m_minimumSize;
|
|
||||||
QSize m_maximumSize;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace QmlDesigner
|
|
@@ -7,7 +7,6 @@
|
|||||||
|
|
||||||
#include "capturenodeinstanceserverdispatcher.h"
|
#include "capturenodeinstanceserverdispatcher.h"
|
||||||
#include "qt5bakelightsnodeinstanceserver.h"
|
#include "qt5bakelightsnodeinstanceserver.h"
|
||||||
#include "qt5captureimagenodeinstanceserver.h"
|
|
||||||
#include "qt5capturepreviewnodeinstanceserver.h"
|
#include "qt5capturepreviewnodeinstanceserver.h"
|
||||||
#include "qt5informationnodeinstanceserver.h"
|
#include "qt5informationnodeinstanceserver.h"
|
||||||
#include "qt5import3dnodeinstanceserver.h"
|
#include "qt5import3dnodeinstanceserver.h"
|
||||||
@@ -65,9 +64,6 @@ Qt5NodeInstanceClientProxy::Qt5NodeInstanceClientProxy(QObject *parent) :
|
|||||||
} else if (QCoreApplication::arguments().at(2) == QLatin1String("capturemode")) {
|
} else if (QCoreApplication::arguments().at(2) == QLatin1String("capturemode")) {
|
||||||
setNodeInstanceServer(std::make_unique<Qt5CapturePreviewNodeInstanceServer>(this));
|
setNodeInstanceServer(std::make_unique<Qt5CapturePreviewNodeInstanceServer>(this));
|
||||||
initializeSocket();
|
initializeSocket();
|
||||||
} else if (QCoreApplication::arguments().at(2) == QLatin1String("captureiconmode")) {
|
|
||||||
setNodeInstanceServer(std::make_unique<Qt5CaptureImageNodeInstanceServer>(this));
|
|
||||||
initializeSocket();
|
|
||||||
} else if (QCoreApplication::arguments().at(2) == QLatin1String("bakelightsmode")) {
|
} else if (QCoreApplication::arguments().at(2) == QLatin1String("bakelightsmode")) {
|
||||||
setNodeInstanceServer(std::make_unique<Qt5BakeLightsNodeInstanceServer>(this));
|
setNodeInstanceServer(std::make_unique<Qt5BakeLightsNodeInstanceServer>(this));
|
||||||
initializeSocket();
|
initializeSocket();
|
||||||
|
@@ -16,6 +16,9 @@
|
|||||||
#include <QFileInfo>
|
#include <QFileInfo>
|
||||||
#include <QQmlComponent>
|
#include <QQmlComponent>
|
||||||
|
|
||||||
|
constexpr int DEFAULT_RENDER_DIM = 300;
|
||||||
|
constexpr int DEFAULT_MAX_DIM = 1024;
|
||||||
|
|
||||||
void QmlRenderer::initCoreApp()
|
void QmlRenderer::initCoreApp()
|
||||||
{
|
{
|
||||||
#if defined QT_WIDGETS_LIB
|
#if defined QT_WIDGETS_LIB
|
||||||
@@ -36,15 +39,29 @@ void QmlRenderer::populateParser()
|
|||||||
"Output image file path.",
|
"Output image file path.",
|
||||||
"path"},
|
"path"},
|
||||||
|
|
||||||
// "h" is reserved arg for help, so use capital letters for height/width
|
// The qml component is rendered at its preferred size if available
|
||||||
{QStringList{"H", "height"},
|
// Min/max dimensions specify a range of acceptable final scaled sizes
|
||||||
"Height of the final rendered image.",
|
// If the size of rendered item is outside the min/max range, it is cropped in final scaling
|
||||||
|
{QStringList{"minW"},
|
||||||
|
"Minimum width of the final scaled rendered image.",
|
||||||
"pixels"},
|
"pixels"},
|
||||||
|
|
||||||
{QStringList{"W", "width"},
|
{QStringList{"minH"},
|
||||||
"Width of the final rendered image.",
|
"Minimum height of the final scaled rendered image.",
|
||||||
"pixels"},
|
"pixels"},
|
||||||
|
|
||||||
|
{QStringList{"maxW"},
|
||||||
|
QString("Maximum width of the final scaled rendered image."),
|
||||||
|
"pixels"},
|
||||||
|
|
||||||
|
{QStringList{"maxH"},
|
||||||
|
"Maximum height of the final scaled rendered image.",
|
||||||
|
"pixels"},
|
||||||
|
|
||||||
|
{QStringList{"libIcon"},
|
||||||
|
"Render library icon rather than regular preview."
|
||||||
|
"It zooms 3D objects bit more aggressively and suppresses the background."},
|
||||||
|
|
||||||
{QStringList{"v", "verbose"},
|
{QStringList{"v", "verbose"},
|
||||||
"Display additional output."}
|
"Display additional output."}
|
||||||
});
|
});
|
||||||
@@ -56,10 +73,14 @@ void QmlRenderer::initQmlRunner()
|
|||||||
{
|
{
|
||||||
if (m_argParser.isSet("importpath"))
|
if (m_argParser.isSet("importpath"))
|
||||||
m_importPaths = m_argParser.value("importpath").split(";");
|
m_importPaths = m_argParser.value("importpath").split(";");
|
||||||
if (m_argParser.isSet("width"))
|
if (m_argParser.isSet("minW"))
|
||||||
m_requestedSize.setWidth(m_argParser.value("width").toInt());
|
m_reqMinSize.setWidth(m_argParser.value("minW").toInt());
|
||||||
if (m_argParser.isSet("height"))
|
if (m_argParser.isSet("minH"))
|
||||||
m_requestedSize.setHeight(m_argParser.value("height").toInt());
|
m_reqMinSize.setHeight(m_argParser.value("minH").toInt());
|
||||||
|
if (m_argParser.isSet("maxW"))
|
||||||
|
m_reqMaxSize.setWidth(m_argParser.value("maxW").toInt());
|
||||||
|
if (m_argParser.isSet("maxH"))
|
||||||
|
m_reqMaxSize.setHeight(m_argParser.value("maxH").toInt());
|
||||||
if (m_argParser.isSet("verbose"))
|
if (m_argParser.isSet("verbose"))
|
||||||
m_verbose = true;
|
m_verbose = true;
|
||||||
|
|
||||||
@@ -76,17 +97,18 @@ void QmlRenderer::initQmlRunner()
|
|||||||
else
|
else
|
||||||
m_outFile = m_sourceFile + ".png";
|
m_outFile = m_sourceFile + ".png";
|
||||||
|
|
||||||
if (m_requestedSize.width() <= 0)
|
if (m_argParser.isSet("libIcon"))
|
||||||
m_requestedSize.setWidth(150);
|
m_isLibIcon = true;
|
||||||
if (m_requestedSize.height() <= 0)
|
|
||||||
m_requestedSize.setHeight(150);
|
|
||||||
|
|
||||||
if (m_verbose) {
|
if (m_verbose) {
|
||||||
info(QString("Import path = %1").arg(m_importPaths.join(";")));
|
info(QString("Import path = %1").arg(m_importPaths.join(";")));
|
||||||
info(QString("Requested size = %1 x %2").arg(m_requestedSize.width())
|
info(QString("Requested min size = %1 x %2").arg(m_reqMinSize.width())
|
||||||
.arg(m_requestedSize.height()));
|
.arg(m_reqMinSize.height()));
|
||||||
|
info(QString("Requested max size = %1 x %2").arg(m_reqMaxSize.width())
|
||||||
|
.arg(m_reqMaxSize.height()));
|
||||||
info(QString("Source file = %1").arg(m_sourceFile));
|
info(QString("Source file = %1").arg(m_sourceFile));
|
||||||
info(QString("Output file = %1").arg(m_outFile));
|
info(QString("Output file = %1").arg(m_outFile));
|
||||||
|
info(QString("Is library icon = %1").arg(m_isLibIcon ? QString("true") : QString("false")));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (setupRenderer()) {
|
if (setupRenderer()) {
|
||||||
@@ -140,6 +162,9 @@ bool QmlRenderer::setupRenderer()
|
|||||||
}
|
}
|
||||||
m_containerItem->setParentItem(m_window->contentItem());
|
m_containerItem->setParentItem(m_window->contentItem());
|
||||||
|
|
||||||
|
if (m_isLibIcon)
|
||||||
|
QMetaObject::invokeMethod(m_containerItem, "setIconMode", Q_ARG(QVariant, true));
|
||||||
|
|
||||||
contentItem3D = QQmlProperty::read(m_containerItem, "contentItem").value<QQuickItem *>();
|
contentItem3D = QQmlProperty::read(m_containerItem, "contentItem").value<QQuickItem *>();
|
||||||
if (qobject_cast<QQuick3DNode *>(renderObj)) {
|
if (qobject_cast<QQuick3DNode *>(renderObj)) {
|
||||||
QMetaObject::invokeMethod(
|
QMetaObject::invokeMethod(
|
||||||
@@ -155,28 +180,25 @@ bool QmlRenderer::setupRenderer()
|
|||||||
}
|
}
|
||||||
|
|
||||||
m_is3D = true;
|
m_is3D = true;
|
||||||
m_renderSize = m_requestedSize;
|
setRenderSize({});
|
||||||
contentItem3D->setSize(m_requestedSize);
|
contentItem3D->setSize(m_renderSize);
|
||||||
} else
|
} else
|
||||||
#endif // QUICK3D_MODULE
|
#endif // QUICK3D_MODULE
|
||||||
if (auto renderItem = qobject_cast<QQuickItem *>(renderObj)) {
|
if (auto renderItem = qobject_cast<QQuickItem *>(renderObj)) {
|
||||||
m_renderSize = renderItem->size().toSize();
|
setRenderSize(renderItem->size().toSize());
|
||||||
if (m_renderSize.width() <= 0)
|
|
||||||
m_renderSize.setWidth(m_requestedSize.width());
|
|
||||||
if (m_renderSize.height() <= 0)
|
|
||||||
m_renderSize.setHeight(m_requestedSize.height());
|
|
||||||
renderItem->setSize(m_renderSize);
|
renderItem->setSize(m_renderSize);
|
||||||
renderItem->setParentItem(m_window->contentItem());
|
renderItem->setParentItem(m_window->contentItem());
|
||||||
// When rendering 2D scenes, we just render the given QML without extra container
|
// When rendering 2D scenes, we just render the given QML without extra container
|
||||||
m_containerItem = renderItem;
|
m_containerItem = renderItem;
|
||||||
} else if (auto renderWindow = qobject_cast<QQuickWindow *>(renderObj)) {
|
} else if (auto renderWindow = qobject_cast<QQuickWindow *>(renderObj)) {
|
||||||
// Hack to render Window items: reparent window content to m_window->contentItem()
|
// Hack to render Window items: reparent window content to m_window->contentItem()
|
||||||
m_renderSize = renderWindow->size();
|
setRenderSize(renderWindow->size());
|
||||||
m_containerItem = m_window->contentItem();
|
m_containerItem = m_window->contentItem();
|
||||||
// Suppress the original window.
|
// Suppress the original window.
|
||||||
// Offscreen position ensures we don't get even brief flash of it.
|
// Offscreen position ensures we don't get even brief flash of it.
|
||||||
renderWindow->setPosition(-100000, -100000);
|
|
||||||
renderWindow->setVisible(false);
|
renderWindow->setVisible(false);
|
||||||
|
renderWindow->resize(2, 2);
|
||||||
|
renderWindow->setPosition(-10000, -10000);
|
||||||
const QList<QQuickItem *> childItems = renderWindow->contentItem()->childItems();
|
const QList<QQuickItem *> childItems = renderWindow->contentItem()->childItems();
|
||||||
for (QQuickItem *item : childItems) {
|
for (QQuickItem *item : childItems) {
|
||||||
item->setParent(m_window->contentItem());
|
item->setParent(m_window->contentItem());
|
||||||
@@ -274,12 +296,32 @@ void QmlRenderer::render()
|
|||||||
QImage wrapperImage(reinterpret_cast<const uchar *>(readResult.data.constData()),
|
QImage wrapperImage(reinterpret_cast<const uchar *>(readResult.data.constData()),
|
||||||
readResult.pixelSize.width(), readResult.pixelSize.height(),
|
readResult.pixelSize.width(), readResult.pixelSize.height(),
|
||||||
QImage::Format_RGBA8888_Premultiplied);
|
QImage::Format_RGBA8888_Premultiplied);
|
||||||
if (m_rhi->isYUpInFramebuffer())
|
|
||||||
renderImage = wrapperImage.mirrored().scaled(m_requestedSize, Qt::IgnoreAspectRatio,
|
QSize maxSize = m_reqMaxSize;
|
||||||
|
if (maxSize.width() <= 0) {
|
||||||
|
m_reqMinSize.width() > DEFAULT_MAX_DIM ? maxSize.setWidth(m_reqMinSize.width())
|
||||||
|
: maxSize.setWidth(DEFAULT_MAX_DIM);
|
||||||
|
}
|
||||||
|
if (maxSize.height() <= 0) {
|
||||||
|
m_reqMinSize.height() > DEFAULT_MAX_DIM ? maxSize.setHeight(m_reqMinSize.height())
|
||||||
|
: maxSize.setHeight(DEFAULT_MAX_DIM);
|
||||||
|
}
|
||||||
|
|
||||||
|
QSize scaledSize = m_renderSize.scaled(m_renderSize.expandedTo(m_reqMinSize).boundedTo(maxSize),
|
||||||
|
Qt::KeepAspectRatio);
|
||||||
|
|
||||||
|
info(QString("Rendered size = %1 x %2").arg(m_renderSize.width())
|
||||||
|
.arg(m_renderSize.height()));
|
||||||
|
info(QString("Scaled size = %1 x %2").arg(scaledSize.width())
|
||||||
|
.arg(scaledSize.height()));
|
||||||
|
|
||||||
|
if (m_rhi->isYUpInFramebuffer()) {
|
||||||
|
renderImage = wrapperImage.mirrored().scaled(scaledSize, Qt::IgnoreAspectRatio,
|
||||||
Qt::SmoothTransformation);
|
Qt::SmoothTransformation);
|
||||||
else
|
} else {
|
||||||
renderImage = wrapperImage.copy().scaled(m_requestedSize, Qt::IgnoreAspectRatio,
|
renderImage = wrapperImage.copy().scaled(scaledSize, Qt::IgnoreAspectRatio,
|
||||||
Qt::SmoothTransformation);
|
Qt::SmoothTransformation);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
QRhiResourceUpdateBatch *readbackBatch = m_rhi->nextResourceUpdateBatch();
|
QRhiResourceUpdateBatch *readbackBatch = m_rhi->nextResourceUpdateBatch();
|
||||||
readbackBatch->readBackTexture(m_texture.get(), &readResult);
|
readbackBatch->readBackTexture(m_texture.get(), &readResult);
|
||||||
@@ -316,3 +358,16 @@ void QmlRenderer::asyncQuit(int errorCode)
|
|||||||
exit(errorCode);
|
exit(errorCode);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void QmlRenderer::setRenderSize(QSize size)
|
||||||
|
{
|
||||||
|
m_renderSize = size;
|
||||||
|
if (m_renderSize.width() <= 0) {
|
||||||
|
m_reqMaxSize.width() > 0 ? m_renderSize.setWidth(m_reqMaxSize.width())
|
||||||
|
: m_renderSize.setWidth(DEFAULT_RENDER_DIM);
|
||||||
|
}
|
||||||
|
if (m_renderSize.height() <= 0) {
|
||||||
|
m_reqMaxSize.height() > 0 ? m_renderSize.setHeight(m_reqMaxSize.height())
|
||||||
|
: m_renderSize.setHeight(DEFAULT_RENDER_DIM);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@@ -34,14 +34,18 @@ private:
|
|||||||
void error(const QString &msg);
|
void error(const QString &msg);
|
||||||
void asyncQuit(int errorCode);
|
void asyncQuit(int errorCode);
|
||||||
|
|
||||||
|
void setRenderSize(QSize size);
|
||||||
|
|
||||||
QStringList m_importPaths;
|
QStringList m_importPaths;
|
||||||
QSize m_requestedSize;
|
QSize m_reqMinSize;
|
||||||
|
QSize m_reqMaxSize;
|
||||||
QSize m_renderSize;
|
QSize m_renderSize;
|
||||||
QString m_sourceFile;
|
QString m_sourceFile;
|
||||||
QString m_outFile;
|
QString m_outFile;
|
||||||
bool m_verbose = false;
|
bool m_verbose = false;
|
||||||
bool m_is3D = false;
|
bool m_is3D = false;
|
||||||
bool m_fit3D = false;
|
bool m_fit3D = false;
|
||||||
|
bool m_isLibIcon = false;
|
||||||
|
|
||||||
QQuickItem *m_containerItem = nullptr;
|
QQuickItem *m_containerItem = nullptr;
|
||||||
QRhi *m_rhi = nullptr;
|
QRhi *m_rhi = nullptr;
|
||||||
|
Reference in New Issue
Block a user