forked from qt-creator/qt-creator
Merge remote-tracking branch 'origin/qds/dev'
Change-Id: I907e067abba640d27313ce03bc41326d3ed750f0
This commit is contained in:
@@ -29,6 +29,7 @@ endif()
|
||||
add_subdirectory(processlauncher)
|
||||
if (WITH_QMLDESIGNER)
|
||||
add_subdirectory(qml2puppet)
|
||||
add_subdirectory(sqlitetester)
|
||||
endif()
|
||||
add_subdirectory(qtcdebugger) ## windows only
|
||||
# add_subdirectory(qtcrashhandler)
|
||||
|
||||
@@ -498,7 +498,6 @@ View3D {
|
||||
targetNode: viewRoot.selectedNode
|
||||
globalOrientation: viewRoot.globalOrientation
|
||||
visible: viewRoot.selectedNode && viewRoot.transformMode === EditView3D.TransformMode.Move
|
||||
&& overlayView.isActive
|
||||
view3D: overlayView
|
||||
dragHelper: gizmoDragHelper
|
||||
property var propertyNames: ["position"]
|
||||
@@ -523,7 +522,6 @@ View3D {
|
||||
highlightOnHover: true
|
||||
targetNode: viewRoot.selectedNode
|
||||
visible: viewRoot.selectedNode && viewRoot.transformMode === EditView3D.TransformMode.Scale
|
||||
&& overlayView.isActive
|
||||
view3D: overlayView
|
||||
dragHelper: gizmoDragHelper
|
||||
property var propertyNames: ["scale"]
|
||||
@@ -550,7 +548,6 @@ View3D {
|
||||
targetNode: viewRoot.selectedNode
|
||||
globalOrientation: viewRoot.globalOrientation
|
||||
visible: viewRoot.selectedNode && viewRoot.transformMode === EditView3D.TransformMode.Rotate
|
||||
&& overlayView.isActive
|
||||
view3D: overlayView
|
||||
dragHelper: gizmoDragHelper
|
||||
property var propertyNames: ["eulerRotation"]
|
||||
@@ -588,7 +585,6 @@ View3D {
|
||||
Line3D {
|
||||
id: pivotLine
|
||||
visible: viewRoot.selectedNode && viewRoot.selectedNode !== viewRoot.multiSelectionNode
|
||||
&& overlayView.isActive
|
||||
name: "3D Edit View Pivot Line"
|
||||
color: "#ddd600"
|
||||
|
||||
|
||||
@@ -989,6 +989,12 @@ bool MouseArea3D::eventFilter(QObject *, QEvent *event)
|
||||
|
||||
break;
|
||||
}
|
||||
case QEvent::HoverLeave: {
|
||||
setHovering(false);
|
||||
if (s_mouseGrab == this && !dragging())
|
||||
s_mouseGrab = nullptr;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -382,18 +382,20 @@ void NodeInstanceServer::reparentInstances(const QVector<ReparentContainer> &con
|
||||
ServerNodeInstance instance = instanceForId(container.instanceId());
|
||||
if (instance.isValid()) {
|
||||
ServerNodeInstance newParent = instanceForId(container.newParentInstanceId());
|
||||
PropertyName newParentProperty = container.newParentProperty();
|
||||
if (!isInformationServer()) {
|
||||
// Children of the component wraps are left out of the node tree to avoid
|
||||
// incorrectly rendering them
|
||||
if (newParent.isComponentWrap()) {
|
||||
newParent = {};
|
||||
newParentProperty.clear();
|
||||
if (newParent.isValid()) {
|
||||
PropertyName newParentProperty = container.newParentProperty();
|
||||
if (!isInformationServer()) {
|
||||
// Children of the component wraps are left out of the node tree to avoid
|
||||
// incorrectly rendering them
|
||||
if (newParent.isComponentWrap()) {
|
||||
newParent = {};
|
||||
newParentProperty.clear();
|
||||
}
|
||||
}
|
||||
instance.reparent(instanceForId(container.oldParentInstanceId()),
|
||||
container.oldParentProperty(),
|
||||
newParent, newParentProperty);
|
||||
}
|
||||
instance.reparent(instanceForId(container.oldParentInstanceId()),
|
||||
container.oldParentProperty(),
|
||||
newParent, newParentProperty);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -173,6 +173,11 @@ bool ObjectNodeInstance::isPropertyChange() const
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ObjectNodeInstance::isComposedEffect() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ObjectNodeInstance::equalGraphicsItem(QGraphicsItem * /*item*/) const
|
||||
{
|
||||
return false;
|
||||
|
||||
@@ -83,6 +83,7 @@ public:
|
||||
virtual bool isLayoutable() const;
|
||||
virtual bool isRenderable() const;
|
||||
virtual bool isPropertyChange() const;
|
||||
virtual bool isComposedEffect() const;
|
||||
|
||||
virtual bool equalGraphicsItem(QGraphicsItem *item) const;
|
||||
|
||||
|
||||
@@ -17,11 +17,13 @@
|
||||
|
||||
#include <QQmlProperty>
|
||||
|
||||
#include <private/qquickdesignersupport_p.h>
|
||||
|
||||
#ifdef QUICK3D_MODULE
|
||||
#include <private/qquick3dnode_p.h>
|
||||
#include <private/qquick3dviewport_p.h>
|
||||
#include <private/qquick3dcamera_p.h>
|
||||
#include <private/qquickdesignersupport_p.h>
|
||||
#include <private/qquick3dperspectivecamera_p.h>
|
||||
#endif
|
||||
|
||||
namespace QmlDesigner {
|
||||
@@ -35,7 +37,7 @@ Qt5Import3dNodeInstanceServer::Qt5Import3dNodeInstanceServer(NodeInstanceClientI
|
||||
#ifdef QUICK3D_MODULE
|
||||
m_generalHelper = new Internal::GeneralHelper();
|
||||
QObject::connect(m_generalHelper, &Internal::GeneralHelper::requestRender, this, [this]() {
|
||||
startRenderTimer();
|
||||
addCurrentNodeToRenderQueue();
|
||||
});
|
||||
#endif
|
||||
}
|
||||
@@ -51,7 +53,25 @@ void Qt5Import3dNodeInstanceServer::createScene(const CreateSceneCommand &comman
|
||||
registerFonts(command.resourceUrl);
|
||||
setTranslationLanguage(command.language);
|
||||
setupScene(command);
|
||||
startRenderTimer();
|
||||
|
||||
#ifdef QUICK3D_MODULE
|
||||
QObject *obj = rootItem();
|
||||
auto initView = [&obj, this](const QString &viewId, QQuick3DViewport *&view3D) {
|
||||
QQmlProperty viewProp(obj, viewId, context());
|
||||
QObject *viewObj = viewProp.read().value<QObject *>();
|
||||
view3D = qobject_cast<QQuick3DViewport *>(viewObj);
|
||||
};
|
||||
initView("view3d", m_view3D);
|
||||
initView("iconView3d", m_iconView3D);
|
||||
|
||||
if (m_view3D) {
|
||||
QQmlProperty sceneNodeProp(obj, "sceneNode", context());
|
||||
m_sceneNode = sceneNodeProp.read().value<QQuick3DNode *>();
|
||||
m_defaultCameraRotation = m_view3D->camera()->rotation();
|
||||
m_defaultCameraPosition = m_view3D->camera()->position();
|
||||
addInitToRenderQueue();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void Qt5Import3dNodeInstanceServer::view3DAction([[maybe_unused]] const View3DActionCommand &command)
|
||||
@@ -66,9 +86,14 @@ void Qt5Import3dNodeInstanceServer::view3DAction([[maybe_unused]] const View3DAc
|
||||
QQmlProperty hProp(obj, "height", context());
|
||||
wProp.write(size.width());
|
||||
hProp.write(size.height());
|
||||
if (auto camera = qobject_cast<QQuick3DPerspectiveCamera *>(m_view3D->camera())) {
|
||||
if (size.width() >= size.height())
|
||||
camera->setFieldOfViewOrientation(QQuick3DPerspectiveCamera::Vertical);
|
||||
else
|
||||
camera->setFieldOfViewOrientation(QQuick3DPerspectiveCamera::Horizontal);
|
||||
}
|
||||
resizeCanvasToRootItem();
|
||||
|
||||
startRenderTimer();
|
||||
addCurrentNodeToRenderQueue();
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -76,15 +101,80 @@ void Qt5Import3dNodeInstanceServer::view3DAction([[maybe_unused]] const View3DAc
|
||||
QObject *obj = rootItem();
|
||||
QQmlProperty sceneNodeProp(obj, "sceneNode", context());
|
||||
auto sceneNode = sceneNodeProp.read().value<QQuick3DNode *>();
|
||||
if (sceneNode) {
|
||||
if (sceneNode && m_previewData.contains(m_currentNode)) {
|
||||
PreviewData &data = m_previewData[m_currentNode];
|
||||
QPointF delta = command.value().toPointF();
|
||||
m_generalHelper->orbitCamera(m_view3D->camera(), m_view3D->camera()->eulerRotation(),
|
||||
m_lookAt, {}, {float(delta.x()), float(delta.y()), 0.f});
|
||||
m_keepRendering = true;
|
||||
startRenderTimer();
|
||||
data.lookAt, {}, {float(delta.x()), float(delta.y()), 0.f});
|
||||
// Add 2 renders to keep render timer alive for smooth rotation
|
||||
addCurrentNodeToRenderQueue(2);
|
||||
data.cameraRotation = m_view3D->camera()->rotation();
|
||||
data.cameraPosition = m_view3D->camera()->position();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case View3DActionType::Import3dAddPreviewModel: {
|
||||
const QVariantHash cmd = command.value().toHash();
|
||||
const QString name = cmd["name"].toString();
|
||||
const QString qmlName = cmd["qmlName"].toString();
|
||||
const QString folder = cmd["folder"].toString();
|
||||
|
||||
bool isUpdate = m_previewData.contains(name);
|
||||
if (isUpdate) {
|
||||
QQuick3DNode *node = m_previewData[name].node;
|
||||
if (node) {
|
||||
node->setParentItem({});
|
||||
node->setParent({});
|
||||
node->deleteLater();
|
||||
}
|
||||
}
|
||||
|
||||
PreviewData &data = m_previewData[name];
|
||||
data.name = name;
|
||||
data.lookAt = {};
|
||||
if (!isUpdate) {
|
||||
data.cameraRotation = m_defaultCameraRotation;
|
||||
data.cameraPosition = m_defaultCameraPosition;
|
||||
}
|
||||
|
||||
QFileInfo fi(fileUrl().toLocalFile());
|
||||
QString compPath = fi.absolutePath() + '/' + folder + '/' + qmlName + ".qml";
|
||||
QQmlComponent comp(engine(), compPath, QQmlComponent::PreferSynchronous);
|
||||
data.node = qobject_cast<QQuick3DNode *>(comp.create(context()));
|
||||
if (data.node) {
|
||||
engine()->setObjectOwnership(data.node, QJSEngine::CppOwnership);
|
||||
data.node->setParentItem(m_sceneNode);
|
||||
data.node->setParent(m_sceneNode);
|
||||
|
||||
addInitToRenderQueue();
|
||||
|
||||
if (m_currentNode == name)
|
||||
addCurrentNodeToRenderQueue();
|
||||
|
||||
addIconToRenderQueue(name);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case View3DActionType::Import3dSetCurrentPreviewModel: {
|
||||
QString newName = command.value().toString();
|
||||
if (m_previewData.contains(newName) && m_currentNode != newName) {
|
||||
QQuick3DCamera *camera = m_view3D->camera();
|
||||
if (m_previewData.contains(m_currentNode)) {
|
||||
PreviewData &oldData = m_previewData[m_currentNode];
|
||||
oldData.cameraPosition = camera->position();
|
||||
oldData.cameraRotation = camera->rotation();
|
||||
}
|
||||
m_currentNode = newName;
|
||||
const PreviewData &newData = m_previewData[m_currentNode];
|
||||
camera->setPosition(newData.cameraPosition);
|
||||
camera->setRotation(newData.cameraRotation);
|
||||
addInitToRenderQueue();
|
||||
addCurrentNodeToRenderQueue();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -93,8 +183,10 @@ void Qt5Import3dNodeInstanceServer::view3DAction([[maybe_unused]] const View3DAc
|
||||
|
||||
void Qt5Import3dNodeInstanceServer::startRenderTimer()
|
||||
{
|
||||
if (m_keepRendering && timerMode() == TimerMode::NormalTimer)
|
||||
#ifdef QUICK3D_MODULE
|
||||
if (!m_renderQueue.isEmpty() && timerMode() == TimerMode::NormalTimer)
|
||||
return;
|
||||
#endif
|
||||
|
||||
NodeInstanceServer::startRenderTimer();
|
||||
}
|
||||
@@ -102,16 +194,52 @@ void Qt5Import3dNodeInstanceServer::startRenderTimer()
|
||||
void Qt5Import3dNodeInstanceServer::cleanup()
|
||||
{
|
||||
#ifdef QUICK3D_MODULE
|
||||
delete m_previewNode;
|
||||
for (const PreviewData &data : std::as_const(m_previewData))
|
||||
delete data.node;
|
||||
m_previewData.clear();
|
||||
delete m_generalHelper;
|
||||
#endif
|
||||
}
|
||||
|
||||
void Qt5Import3dNodeInstanceServer::finish()
|
||||
#ifdef QUICK3D_MODULE
|
||||
void Qt5Import3dNodeInstanceServer::addInitToRenderQueue()
|
||||
{
|
||||
cleanup();
|
||||
startRenderTimer();
|
||||
|
||||
// "Init" render is simply a rendering of the entire scene without producing any images.
|
||||
// This is done to make sure everything is initialized properly for subsequent renders.
|
||||
|
||||
if (m_renderQueue.isEmpty() || m_renderQueue[0] != RenderType::Init)
|
||||
m_renderQueue.prepend(RenderType::Init);
|
||||
}
|
||||
|
||||
void Qt5Import3dNodeInstanceServer::addCurrentNodeToRenderQueue(int count)
|
||||
{
|
||||
startRenderTimer();
|
||||
|
||||
int remaining = count;
|
||||
for (const RenderType &type : std::as_const(m_renderQueue)) {
|
||||
if (type == RenderType::CurrentNode && --remaining <= 0)
|
||||
return;
|
||||
}
|
||||
|
||||
int index = !m_renderQueue.isEmpty() && m_renderQueue[0] == RenderType::Init ? 1 : 0;
|
||||
|
||||
while (remaining > 0) {
|
||||
m_renderQueue.insert(index, RenderType::CurrentNode);
|
||||
--remaining;
|
||||
}
|
||||
}
|
||||
|
||||
void Qt5Import3dNodeInstanceServer::addIconToRenderQueue(const QString &assetName)
|
||||
{
|
||||
startRenderTimer();
|
||||
|
||||
m_generateIconQueue.append(assetName);
|
||||
m_renderQueue.append(RenderType::NextIcon);
|
||||
}
|
||||
#endif
|
||||
|
||||
void Qt5Import3dNodeInstanceServer::collectItemChangesAndSendChangeCommands()
|
||||
{
|
||||
static bool inFunction = false;
|
||||
@@ -133,75 +261,113 @@ void Qt5Import3dNodeInstanceServer::collectItemChangesAndSendChangeCommands()
|
||||
void Qt5Import3dNodeInstanceServer::render()
|
||||
{
|
||||
#ifdef QUICK3D_MODULE
|
||||
++m_renderCount;
|
||||
if (m_renderQueue.isEmpty() || !m_view3D || !m_iconView3D)
|
||||
return;
|
||||
|
||||
if (m_renderCount == 1) {
|
||||
QObject *obj = rootItem();
|
||||
QQmlProperty viewProp(obj, "view3d", context());
|
||||
QObject *viewObj = viewProp.read().value<QObject *>();
|
||||
m_view3D = qobject_cast<QQuick3DViewport *>(viewObj);
|
||||
if (m_view3D) {
|
||||
QQmlProperty sceneModelNameProp(obj, "sceneModelName", context());
|
||||
QQmlProperty sceneNodeProp(obj, "sceneNode", context());
|
||||
auto sceneNode = sceneNodeProp.read().value<QQuick3DNode *>();
|
||||
if (sceneNode) {
|
||||
QString sceneModelName = sceneModelNameProp.read().toString();
|
||||
QFileInfo fi(fileUrl().toLocalFile());
|
||||
QString compPath = fi.absolutePath() + '/' + sceneModelName + ".qml";
|
||||
QQmlComponent comp(engine(), compPath, QQmlComponent::PreferSynchronous);
|
||||
m_previewNode = qobject_cast<QQuick3DNode *>(comp.create(context()));
|
||||
if (m_previewNode) {
|
||||
engine()->setObjectOwnership(m_previewNode, QJSEngine::CppOwnership);
|
||||
m_previewNode->setParentItem(sceneNode);
|
||||
m_previewNode->setParent(sceneNode);
|
||||
RenderType currentType = m_renderQueue.takeFirst();
|
||||
PreviewData data;
|
||||
QQuick3DViewport *currentView = m_view3D;
|
||||
QVector3D cameraPosition = m_view3D->camera()->position();
|
||||
QQuaternion cameraRotation = m_view3D->camera()->rotation();
|
||||
|
||||
if (currentType == RenderType::Init) {
|
||||
m_view3D->setVisible(true);
|
||||
m_iconView3D->setVisible(true);
|
||||
} else {
|
||||
auto showNode = [this](const QString &name) {
|
||||
for (const PreviewData &data : std::as_const(m_previewData))
|
||||
data.node->setVisible(data.name == name);
|
||||
};
|
||||
|
||||
if (currentType == RenderType::CurrentNode) {
|
||||
if (m_previewData.contains(m_currentNode)) {
|
||||
showNode(m_currentNode);
|
||||
data = m_previewData[m_currentNode];
|
||||
m_view3D->setVisible(true);
|
||||
m_iconView3D->setVisible(false);
|
||||
}
|
||||
} else if (currentType == RenderType::NextIcon) {
|
||||
if (!m_generateIconQueue.isEmpty()) {
|
||||
const QString assetName = m_generateIconQueue.takeFirst();
|
||||
if (m_previewData.contains(assetName)) {
|
||||
m_view3D->setVisible(false);
|
||||
m_iconView3D->setVisible(true);
|
||||
showNode(assetName);
|
||||
data = m_previewData[assetName];
|
||||
m_refocus = true;
|
||||
currentView = m_iconView3D;
|
||||
currentView->camera()->setRotation(m_defaultCameraRotation);
|
||||
currentView->camera()->setPosition(m_defaultCameraPosition);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (m_refocus && data.node) {
|
||||
m_generalHelper->calculateBoundsAndFocusCamera(currentView->camera(), data.node,
|
||||
currentView, 1050, false, data.lookAt,
|
||||
data.extents);
|
||||
if (currentType == RenderType::CurrentNode) {
|
||||
auto getExtentStr = [&data](int idx) -> QString {
|
||||
int prec = 0;
|
||||
float val = data.extents[idx];
|
||||
|
||||
if (val == 0.f) {
|
||||
prec = 1;
|
||||
} else {
|
||||
while (val < 100.f) {
|
||||
++prec;
|
||||
val *= 10.f;
|
||||
}
|
||||
}
|
||||
// Strip unnecessary zeroes after decimal separator
|
||||
if (prec > 0) {
|
||||
QString checkStr = QString::number(data.extents[idx], 'f', prec);
|
||||
while (prec > 0 && (checkStr.last(1) == "0" || checkStr.last(1) == ".")) {
|
||||
--prec;
|
||||
checkStr.chop(1);
|
||||
}
|
||||
}
|
||||
QString retval = QLocale().toString(data.extents[idx], 'f', prec);
|
||||
return retval;
|
||||
};
|
||||
|
||||
QQmlProperty extentsProp(rootItem(), "extents", context());
|
||||
extentsProp.write(tr("Dimensions: %1 x %2 x %3").arg(getExtentStr(0))
|
||||
.arg(getExtentStr(1))
|
||||
.arg(getExtentStr(2)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Render scene once to ensure geometries are intialized so bounds calculations work correctly
|
||||
if (m_renderCount == 2 && m_view3D) {
|
||||
QVector3D extents;
|
||||
m_generalHelper->calculateBoundsAndFocusCamera(m_view3D->camera(), m_previewNode,
|
||||
m_view3D, 1050, false, m_lookAt, extents);
|
||||
auto getExtentStr = [&extents](int idx) -> QString {
|
||||
int prec = 0;
|
||||
float val = extents[idx];
|
||||
while (val < 100.f) {
|
||||
++prec;
|
||||
val *= 10.f;
|
||||
}
|
||||
// Strip unnecessary zeroes after decimal separator
|
||||
if (prec > 0) {
|
||||
QString checkStr = QString::number(extents[idx], 'f', prec);
|
||||
while (prec > 0 && (checkStr.last(1) == "0" || checkStr.last(1) == ".")) {
|
||||
--prec;
|
||||
checkStr.chop(1);
|
||||
}
|
||||
}
|
||||
QString retval = QLocale().toString(extents[idx], 'f', prec);
|
||||
return retval;
|
||||
};
|
||||
QQmlProperty extentsProp(rootItem(), "extents", context());
|
||||
extentsProp.write(tr("Dimensions: %1 x %2 x %3").arg(getExtentStr(0))
|
||||
.arg(getExtentStr(1))
|
||||
.arg(getExtentStr(2)));
|
||||
}
|
||||
|
||||
rootNodeInstance().updateDirtyNodeRecursive();
|
||||
currentView->update();
|
||||
QImage renderImage = grabWindow();
|
||||
|
||||
if (m_renderCount >= 2) {
|
||||
ImageContainer imgContainer(0, renderImage, m_renderCount);
|
||||
nodeInstanceClient()->handlePuppetToCreatorCommand(
|
||||
{PuppetToCreatorCommand::Import3DPreviewImage,
|
||||
QVariant::fromValue(imgContainer)});
|
||||
|
||||
if (!m_keepRendering)
|
||||
slowDownRenderTimer();
|
||||
|
||||
m_keepRendering = false;
|
||||
if (currentType == RenderType::Init) {
|
||||
m_refocus = true;
|
||||
} else if (currentType == RenderType::CurrentNode) {
|
||||
if (m_previewData.contains(m_currentNode)) {
|
||||
ImageContainer imgContainer(0, renderImage, 1000000);
|
||||
nodeInstanceClient()->handlePuppetToCreatorCommand(
|
||||
{PuppetToCreatorCommand::Import3DPreviewImage, QVariant::fromValue(imgContainer)});
|
||||
}
|
||||
} else if (currentType == RenderType::NextIcon) {
|
||||
if (!data.name.isEmpty()) {
|
||||
QSizeF iconSize = m_iconView3D->size();
|
||||
QImage iconImage = renderImage.copy(0, 0, iconSize.width(), iconSize.height());
|
||||
static qint32 renderId = 1000001;
|
||||
ImageContainer imgContainer(0, iconImage, ++renderId);
|
||||
QVariantList cmdData;
|
||||
cmdData.append(data.name);
|
||||
cmdData.append(QVariant::fromValue(imgContainer));
|
||||
nodeInstanceClient()->handlePuppetToCreatorCommand(
|
||||
{PuppetToCreatorCommand::Import3DPreviewIcon, cmdData});
|
||||
}
|
||||
m_refocus = true;
|
||||
currentView->camera()->setRotation(cameraRotation);
|
||||
currentView->camera()->setPosition(cameraPosition);
|
||||
}
|
||||
if (m_renderQueue.isEmpty())
|
||||
slowDownRenderTimer();
|
||||
#else
|
||||
slowDownRenderTimer();
|
||||
#endif
|
||||
|
||||
@@ -8,9 +8,12 @@
|
||||
#endif
|
||||
#include "qt5nodeinstanceserver.h"
|
||||
|
||||
#ifdef QUICK3D_MODULE
|
||||
#include "generalhelper.h"
|
||||
QT_BEGIN_NAMESPACE
|
||||
class QQuick3DNode;
|
||||
QT_END_NAMESPACE
|
||||
#endif
|
||||
|
||||
namespace QmlDesigner {
|
||||
|
||||
@@ -33,17 +36,42 @@ protected:
|
||||
void startRenderTimer() override;
|
||||
|
||||
private:
|
||||
void finish();
|
||||
void cleanup();
|
||||
|
||||
int m_renderCount = 0;
|
||||
bool m_keepRendering = false;
|
||||
|
||||
#ifdef QUICK3D_MODULE
|
||||
void addInitToRenderQueue();
|
||||
void addCurrentNodeToRenderQueue(int count = 1);
|
||||
void addIconToRenderQueue(const QString &assetName);
|
||||
|
||||
QQuick3DViewport *m_view3D = nullptr;
|
||||
QQuick3DViewport *m_iconView3D = nullptr;
|
||||
Internal::GeneralHelper *m_generalHelper = nullptr;
|
||||
QQuick3DNode *m_previewNode = nullptr;
|
||||
QVector3D m_lookAt;
|
||||
|
||||
struct PreviewData
|
||||
{
|
||||
QString name;
|
||||
QVector3D lookAt;
|
||||
QVector3D extents;
|
||||
QQuick3DNode *node = {};
|
||||
QQuaternion cameraRotation;
|
||||
QVector3D cameraPosition;
|
||||
};
|
||||
QHash<QString, PreviewData> m_previewData;
|
||||
|
||||
enum class RenderType
|
||||
{
|
||||
Init,
|
||||
CurrentNode,
|
||||
NextIcon
|
||||
};
|
||||
QList<RenderType> m_renderQueue;
|
||||
|
||||
bool m_refocus = false;
|
||||
QString m_currentNode;
|
||||
QQuick3DNode *m_sceneNode = {};
|
||||
QStringList m_generateIconQueue;
|
||||
QQuaternion m_defaultCameraRotation;
|
||||
QVector3D m_defaultCameraPosition;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
@@ -1377,6 +1377,7 @@ void Qt5InformationNodeInstanceServer::doRenderModelNode3DImageView(
|
||||
// Key number is selected so that it is unlikely to conflict other ImageContainer use.
|
||||
ImageContainer imgContainer(cmd.instanceId(), {}, 2100000001 + cmd.instanceId());
|
||||
imgContainer.setImage(renderImage);
|
||||
imgContainer.setRequestId(cmd.requestId());
|
||||
|
||||
// send the rendered image to creator process
|
||||
nodeInstanceClient()->handlePuppetToCreatorCommand(
|
||||
@@ -1472,6 +1473,7 @@ void Qt5InformationNodeInstanceServer::doRenderModelNode2DImageView(const Reques
|
||||
|
||||
if (!renderImage.isNull()) {
|
||||
imgContainer.setImage(renderImage);
|
||||
imgContainer.setRequestId(cmd.requestId());
|
||||
|
||||
// send the rendered image to creator process
|
||||
nodeInstanceClient()->handlePuppetToCreatorCommand({PuppetToCreatorCommand::RenderModelNodePreviewImage,
|
||||
|
||||
@@ -89,6 +89,7 @@ void Qt5NodeInstanceServer::initializeView()
|
||||
|
||||
m_viewData.renderControl = new QQuickRenderControl;
|
||||
m_viewData.window = new QQuickWindow(m_viewData.renderControl);
|
||||
m_viewData.window->setColor(Qt::transparent);
|
||||
setPipelineCacheConfig(m_viewData.window);
|
||||
m_viewData.renderControl->initialize();
|
||||
m_qmlEngine = new QQmlEngine;
|
||||
@@ -379,9 +380,11 @@ QImage Qt5NodeInstanceServer::grabRenderControl([[maybe_unused]] RenderViewData
|
||||
QRhiReadbackResult readResult;
|
||||
readResult.completed = [&] {
|
||||
readCompleted = true;
|
||||
QImage wrapperImage(reinterpret_cast<const uchar *>(readResult.data.constData()),
|
||||
readResult.pixelSize.width(), readResult.pixelSize.height(),
|
||||
QImage::Format_RGBA8888_Premultiplied);
|
||||
QImage wrapperImage(
|
||||
reinterpret_cast<const uchar *>(readResult.data.constData()),
|
||||
readResult.pixelSize.width(),
|
||||
readResult.pixelSize.height(),
|
||||
QImage::Format_RGBA8888_Premultiplied);
|
||||
if (viewData.rhi->isYUpInFramebuffer())
|
||||
renderImage = wrapperImage.mirrored();
|
||||
else
|
||||
|
||||
@@ -239,7 +239,7 @@ void Qt5RenderNodeInstanceServer::changePropertyValues(const ChangeValuesCommand
|
||||
instance = instanceForObject(targetObject);
|
||||
}
|
||||
|
||||
if (instance.hasParent() && instance.propertyNames().contains("_isEffectItem"))
|
||||
if (instance.hasParent() && instance.isComposedEffect())
|
||||
makeDirtyRecursive(instance.parent());
|
||||
} else if (container.isDynamic() && hasInstanceForId(container.instanceId())) {
|
||||
// Changes to dynamic properties are not always noticed by normal signal spy mechanism
|
||||
@@ -263,13 +263,68 @@ void Qt5RenderNodeInstanceServer::changePropertyBindings(const ChangeBindingsCom
|
||||
}
|
||||
}
|
||||
|
||||
void Qt5RenderNodeInstanceServer::makeDirtyRecursive(const ServerNodeInstance &instance)
|
||||
void Qt5RenderNodeInstanceServer::reparentInstances(const ReparentInstancesCommand &command)
|
||||
{
|
||||
const QList<ServerNodeInstance> children = instance.childItems();
|
||||
for (const auto &child : children) {
|
||||
m_dirtyInstanceSet.insert(child);
|
||||
makeDirtyRecursive(child);
|
||||
ServerNodeInstance effectNode;
|
||||
ServerNodeInstance oldParent;
|
||||
const QVector<ReparentContainer> containers = command.reparentInstances();
|
||||
for (const ReparentContainer &container : containers) {
|
||||
if (hasInstanceForId(container.instanceId())) {
|
||||
ServerNodeInstance instance = instanceForId(container.instanceId());
|
||||
if (instance.isComposedEffect()) {
|
||||
oldParent = instance.parent();
|
||||
effectNode = instance;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Qt5NodeInstanceServer::reparentInstances(command);
|
||||
|
||||
if (oldParent.isValid())
|
||||
makeDirtyRecursive(oldParent);
|
||||
if (effectNode.isValid()) {
|
||||
ServerNodeInstance newParent = effectNode.parent();
|
||||
if (newParent.isValid()) {
|
||||
// This is a hack to work around Image elements sometimes losing their textures when
|
||||
// used as children of an effect. Toggling the visibility of the affected node seems
|
||||
// to be the only way to fix this issue.
|
||||
// Note that just marking the children's visibility dirty doesn't fix this issue.
|
||||
QQuickItem *parentItem = newParent.rootQuickItem();
|
||||
if (parentItem && parentItem->isVisible()) {
|
||||
parentItem->setVisible(false);
|
||||
parentItem->setVisible(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Qt5RenderNodeInstanceServer::removeInstances(const RemoveInstancesCommand &command)
|
||||
{
|
||||
ServerNodeInstance oldParent;
|
||||
const QVector<qint32> ids = command.instanceIds();
|
||||
for (qint32 id : ids) {
|
||||
if (hasInstanceForId(id)) {
|
||||
ServerNodeInstance instance = instanceForId(id);
|
||||
if (instance.isComposedEffect()) {
|
||||
oldParent = instance.parent();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Qt5NodeInstanceServer::removeInstances(command);
|
||||
|
||||
if (oldParent.isValid())
|
||||
makeDirtyRecursive(oldParent);
|
||||
}
|
||||
|
||||
void Qt5RenderNodeInstanceServer::makeDirtyRecursive(const ServerNodeInstance &instance)
|
||||
{
|
||||
m_dirtyInstanceSet.insert(instance);
|
||||
const QList<ServerNodeInstance> children = instance.childItems();
|
||||
for (const auto &child : children)
|
||||
makeDirtyRecursive(child);
|
||||
}
|
||||
|
||||
} // namespace QmlDesigner
|
||||
|
||||
@@ -19,6 +19,8 @@ public:
|
||||
void removeSharedMemory(const RemoveSharedMemoryCommand &command) override;
|
||||
void changePropertyValues(const ChangeValuesCommand &command) override;
|
||||
void changePropertyBindings(const ChangeBindingsCommand &command) override;
|
||||
void reparentInstances(const ReparentInstancesCommand &command) override;
|
||||
void removeInstances(const RemoveInstancesCommand &command) override;
|
||||
|
||||
protected:
|
||||
void collectItemChangesAndSendChangeCommands() override;
|
||||
|
||||
@@ -150,8 +150,6 @@ void QuickItemNodeInstance::initialize(const ObjectNodeInstance::Pointer &object
|
||||
|
||||
if (instanceId() == 0)
|
||||
nodeInstanceServer()->setRootItem(quickItem());
|
||||
else
|
||||
quickItem()->setParentItem(nodeInstanceServer()->rootItem());
|
||||
|
||||
ObjectNodeInstance::initialize(objectNodeInstance, flags);
|
||||
}
|
||||
@@ -181,6 +179,10 @@ void QuickItemNodeInstance::doComponentComplete()
|
||||
if (contentItemProperty.isValid())
|
||||
m_contentItem = contentItemProperty.read().value<QQuickItem*>();
|
||||
|
||||
QQmlProperty composedEffectProperty(quickItem(), "_isEffectItem", engine());
|
||||
if (composedEffectProperty.isValid())
|
||||
m_isComposedEffect = true;
|
||||
|
||||
quickItem()->update();
|
||||
}
|
||||
|
||||
@@ -490,6 +492,11 @@ bool QuickItemNodeInstance::isRenderable() const
|
||||
return quickItem() && (!s_unifiedRenderPath || isRootNodeInstance());
|
||||
}
|
||||
|
||||
bool QuickItemNodeInstance::isComposedEffect() const
|
||||
{
|
||||
return m_isComposedEffect;
|
||||
}
|
||||
|
||||
QList<ServerNodeInstance> QuickItemNodeInstance::stateInstances() const
|
||||
{
|
||||
QList<ServerNodeInstance> instanceList;
|
||||
|
||||
@@ -75,6 +75,7 @@ public:
|
||||
bool isMovable() const override;
|
||||
bool isQuickItem() const override;
|
||||
bool isRenderable() const override;
|
||||
bool isComposedEffect() const override;
|
||||
|
||||
QList<ServerNodeInstance> stateInstances() const override;
|
||||
|
||||
@@ -123,6 +124,7 @@ private: //variables
|
||||
double m_width;
|
||||
double m_height;
|
||||
bool m_hidden = false;
|
||||
bool m_isComposedEffect = false;
|
||||
static bool s_createEffectItem;
|
||||
static bool s_unifiedRenderPath;
|
||||
};
|
||||
|
||||
@@ -158,6 +158,11 @@ bool ServerNodeInstance::isComponentWrap() const
|
||||
return m_nodeInstance->isComponentWrap();
|
||||
}
|
||||
|
||||
bool ServerNodeInstance::isComposedEffect() const
|
||||
{
|
||||
return m_nodeInstance->isComposedEffect();
|
||||
}
|
||||
|
||||
QQuickItem *ServerNodeInstance::contentItem() const
|
||||
{
|
||||
return m_nodeInstance->contentItem();
|
||||
|
||||
@@ -54,6 +54,7 @@ public:
|
||||
friend class Qt5BakeLightsNodeInstanceServer;
|
||||
friend class Qt5PreviewNodeInstanceServer;
|
||||
friend class Qt5CapturePreviewNodeInstanceServer;
|
||||
friend class Qt5RenderNodeInstanceServer;
|
||||
friend class Qt5TestNodeInstanceServer;
|
||||
friend class QHash<qint32, ServerNodeInstance>;
|
||||
friend QHashValueType qHash(const ServerNodeInstance &instance);
|
||||
@@ -160,6 +161,7 @@ public:
|
||||
bool holdsGraphical() const;
|
||||
|
||||
bool isComponentWrap() const;
|
||||
bool isComposedEffect() const;
|
||||
|
||||
QQuickItem *contentItem() const;
|
||||
|
||||
|
||||
@@ -124,13 +124,13 @@ void QmlPuppet::initQmlRunner()
|
||||
QString options = m_coreApp->arguments().at(4);
|
||||
|
||||
Import3D::import3D(sourceAsset, outDir, options);
|
||||
} else {
|
||||
startCrashpad(QCoreApplication::applicationDirPath()
|
||||
+ '/' + RELATIVE_LIBEXEC_PATH, crashReportsPath());
|
||||
|
||||
new QmlDesigner::Qt5NodeInstanceClientProxy(m_coreApp.get());
|
||||
}
|
||||
|
||||
startCrashpad(QCoreApplication::applicationDirPath()
|
||||
+ '/' + RELATIVE_LIBEXEC_PATH, crashReportsPath());
|
||||
|
||||
new QmlDesigner::Qt5NodeInstanceClientProxy(m_coreApp.get());
|
||||
|
||||
#if defined(Q_OS_WIN) && defined(QT_NO_DEBUG)
|
||||
SetErrorMode(SEM_NOGPFAULTERRORBOX); //We do not want to see any message boxes
|
||||
#endif
|
||||
|
||||
@@ -90,19 +90,7 @@ static QQuickDesignerSupport::PropertyNameList propertyNameListForWritableProper
|
||||
QMetaType jsType = QMetaType::fromType<QJSValue>();
|
||||
int userType = value.userType();
|
||||
|
||||
//qDebug() << jsType << jsType.id();
|
||||
//qDebug() << "tp" << value.typeName();
|
||||
//qDebug() << "ut" << userType;
|
||||
|
||||
if (userType == jsType.id()) {
|
||||
qDebug() << "js value found";
|
||||
//QJSValue jsValue = value.value<QJSValue>(); //crashes
|
||||
//qDebug() << jsValue.isObject();
|
||||
//qDebug() << jsValue.isQObject();
|
||||
} else {
|
||||
|
||||
|
||||
|
||||
if (userType != jsType.id()) {
|
||||
valueType->setValue(value);
|
||||
propertyNameList.append(propertyNameListForWritablePropertiesInternal(valueType,
|
||||
baseName + QQuickDesignerSupport::PropertyName(metaProperty.name())
|
||||
@@ -175,36 +163,12 @@ static QQuickDesignerSupport::PropertyNameList allPropertyNamesFork(QObject *obj
|
||||
propertyNameList.append(baseName + QQuickDesignerSupport::PropertyName(metaProperty.name()));
|
||||
const QJsonValue jsonValue = value.toJsonValue();
|
||||
|
||||
if (!jsonValue.isNull()) {
|
||||
qDebug() << "llokhere";
|
||||
qDebug() << "name" << metaProperty.name();
|
||||
qDebug() << "value" << value;
|
||||
qDebug() << jsonValue;
|
||||
}
|
||||
|
||||
if (value.isValid() && jsonValue.isNull()) {
|
||||
//qDebug() << "llokhere crash";
|
||||
//qDebug() << "name" << metaProperty.name();
|
||||
//qDebug() << "value" << value;
|
||||
//qDebug() << jsonValue;
|
||||
|
||||
|
||||
QMetaType jsType = QMetaType::fromType<QJSValue>();
|
||||
|
||||
int userType = value.userType();
|
||||
|
||||
//qDebug() << jsType << jsType.id();
|
||||
//qDebug() << "tp" << value.typeName();
|
||||
//qDebug() << "ut" << userType;
|
||||
|
||||
if (userType == jsType.id()) {
|
||||
qDebug() << "js value found";
|
||||
//QJSValue jsValue = value.value<QJSValue>(); //crashes
|
||||
//qDebug() << jsValue.isObject();
|
||||
//qDebug() << jsValue.isQObject();
|
||||
} else {
|
||||
|
||||
|
||||
if (userType != jsType.id()) {
|
||||
valueType->setValue(value);
|
||||
propertyNameList.append(allPropertyNamesFork(valueType,
|
||||
baseName
|
||||
|
||||
37
src/tools/sqlitetester/CMakeLists.txt
Normal file
37
src/tools/sqlitetester/CMakeLists.txt
Normal file
@@ -0,0 +1,37 @@
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
|
||||
# standalone build
|
||||
if (NOT QT_CREATOR_API_DEFINED)
|
||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/../../../cmake")
|
||||
|
||||
project(sqlitetester)
|
||||
|
||||
set(CMAKE_AUTOMOC ON)
|
||||
set(CMAKE_AUTORCC ON)
|
||||
set(CMAKE_AUTOUIC ON)
|
||||
set(CMAKE_CXX_STANDARD 20)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
set(CMAKE_CXX_EXTENSIONS OFF)
|
||||
|
||||
set(DESTINATION DESTINATION .)
|
||||
include(QtCreatorIDEBranding)
|
||||
include(QtCreatorAPI)
|
||||
qtc_handle_compiler_cache_support()
|
||||
|
||||
find_package(Qt6
|
||||
COMPONENTS Core Gui Widgets
|
||||
REQUIRED
|
||||
)
|
||||
endif()
|
||||
|
||||
add_qtc_executable(sqlitetester
|
||||
${DESTINATION}
|
||||
CONDITION WINDOWS AND BUILD_DESIGNSTUDIO
|
||||
DEPENDS
|
||||
Sqlite
|
||||
Qt::Core Qt::Widgets
|
||||
INCLUDES
|
||||
${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
SOURCES
|
||||
main.cpp
|
||||
)
|
||||
137
src/tools/sqlitetester/main.cpp
Normal file
137
src/tools/sqlitetester/main.cpp
Normal file
@@ -0,0 +1,137 @@
|
||||
// Copyright (C) 2024 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
||||
|
||||
#include <sqlitedatabase.h>
|
||||
#include <sqlitelibraryinitializer.h>
|
||||
|
||||
#include <QApplication>
|
||||
#include <QWidget>
|
||||
#include <QVBoxLayout>
|
||||
#include <QLineEdit>
|
||||
#include <QPushButton>
|
||||
#include <QTextBrowser>
|
||||
#include <QTemporaryFile>
|
||||
#include <QDir>
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
class DatabaseApp : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
DatabaseApp(QWidget *parent = nullptr);
|
||||
|
||||
private slots:
|
||||
void onSetDirectoryClicked();
|
||||
void createDatabase(const QString &dirPath);
|
||||
|
||||
private:
|
||||
void deleteFileIfExist(const QString &filePath);
|
||||
void logMessage(const QString &message);
|
||||
void logDetailedWindowsError();
|
||||
|
||||
QLineEdit *directoryLineEdit;
|
||||
QTextBrowser *logBrowser;
|
||||
QString databaseDirectory;
|
||||
};
|
||||
|
||||
DatabaseApp::DatabaseApp(QWidget *parent) : QWidget(parent) {
|
||||
QVBoxLayout *layout = new QVBoxLayout(this);
|
||||
|
||||
directoryLineEdit = new QLineEdit(this);
|
||||
directoryLineEdit->setPlaceholderText("Enter database directory path");
|
||||
layout->addWidget(directoryLineEdit);
|
||||
|
||||
QPushButton *setDirectoryButton = new QPushButton("Set Directory and Create Database", this);
|
||||
layout->addWidget(setDirectoryButton);
|
||||
|
||||
logBrowser = new QTextBrowser(this);
|
||||
layout->addWidget(logBrowser);
|
||||
|
||||
connect(setDirectoryButton, &QPushButton::clicked, this, &DatabaseApp::onSetDirectoryClicked);
|
||||
}
|
||||
|
||||
void DatabaseApp::onSetDirectoryClicked() {
|
||||
QString dirPath = directoryLineEdit->text();
|
||||
if (dirPath.isEmpty()) {
|
||||
logMessage("Directory path is empty.");
|
||||
return;
|
||||
}
|
||||
|
||||
QDir dir(dirPath);
|
||||
if (!dir.exists()) {
|
||||
logMessage("Directory does not exist.");
|
||||
return;
|
||||
}
|
||||
|
||||
QTemporaryFile tempFile(dirPath + "/tempfileXXXXXX");
|
||||
if (!tempFile.open()) {
|
||||
logMessage("Cannot create temporary file in the directory: " + tempFile.errorString());
|
||||
logDetailedWindowsError();
|
||||
return;
|
||||
}
|
||||
tempFile.close();
|
||||
|
||||
createDatabase(dirPath);
|
||||
}
|
||||
|
||||
void DatabaseApp::deleteFileIfExist(const QString &filePath) {
|
||||
if (QFile::exists(filePath)) {
|
||||
if (!QFile::remove(filePath)) {
|
||||
logMessage(QString("Failed to delete existing file %1 before creating database").arg(filePath));
|
||||
logDetailedWindowsError();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DatabaseApp::createDatabase(const QString &dirPath) {
|
||||
databaseDirectory = dirPath;
|
||||
QString dbPath = dirPath + "/mysqlitetester.db";
|
||||
dbPath.replace("\\", "/");
|
||||
deleteFileIfExist(dbPath);
|
||||
|
||||
try {
|
||||
Sqlite::Database database{Utils::PathString{dbPath}};
|
||||
} catch (const Sqlite::Exception &e) {
|
||||
logMessage(QString("Cannot create %1: %2").arg(dbPath, QString::fromUtf8(e.what())));
|
||||
logDetailedWindowsError();
|
||||
}
|
||||
deleteFileIfExist(dbPath);
|
||||
logMessage(QString("Test with %1 was successful.").arg(dbPath));
|
||||
}
|
||||
|
||||
void DatabaseApp::logMessage(const QString &message) {
|
||||
logBrowser->append(message);
|
||||
}
|
||||
|
||||
void DatabaseApp::logDetailedWindowsError() {
|
||||
DWORD errorCode = GetLastError();
|
||||
if (errorCode != 0) {
|
||||
LPVOID errorMsg;
|
||||
DWORD size = FormatMessage(
|
||||
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||
NULL, errorCode, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
||||
(LPWSTR)&errorMsg, 0, NULL);
|
||||
|
||||
if (size) {
|
||||
QString detailedMessage = QString::fromWCharArray((LPWSTR)errorMsg, size);
|
||||
logMessage("Windows error: " + detailedMessage);
|
||||
LocalFree(errorMsg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
Sqlite::LibraryInitializer::initialize();
|
||||
|
||||
|
||||
QApplication app(argc, argv);
|
||||
DatabaseApp window;
|
||||
window.setWindowTitle("SQLite Write Database Tester");
|
||||
window.resize(400, 300);
|
||||
window.show();
|
||||
return app.exec();
|
||||
}
|
||||
|
||||
#include "main.moc"
|
||||
Reference in New Issue
Block a user