Revision control

++ // Copyright (C) 2016 The Qt Company Ltd.
++ // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
++ // Qt-Security score:significant reason:default
++
++ #include "qquickdesignersupport_p.h"
++ #include <private/qquickitem_p.h>
++
++ #if QT_CONFIG(quick_shadereffect)
++ #include <QtQuick/private/qquickshadereffectsource_p.h>
++ #endif
++ #include <QtQuick/private/qquickrectangle_p.h>
++ #include <QtQml/private/qabstractanimationjob_p.h>
++ #include <private/qqmlengine_p.h>
++ #include <private/qquickview_p.h>
++ #include <QtQuick/private/qquickstategroup_p.h>
++ #include <QtGui/QImage>
++ #include <private/qqmlvme_p.h>
++ #include <private/qqmlcomponentattached_p.h>
++ #include <private/qqmldata_p.h>
++ #include <private/qsgadaptationlayer_p.h>
++
++ QT_BEGIN_NAMESPACE
++
++ QQuickDesignerSupport::QQuickDesignerSupport()
++ {
++ }
++
++ QQuickDesignerSupport::~QQuickDesignerSupport()
++ {
++ typedef QHash<QQuickItem*, QSGLayer*>::iterator ItemTextureHashIt;
++
++ for (ItemTextureHashIt iterator = m_itemTextureHash.begin(), end = m_itemTextureHash.end(); iterator != end; ++iterator) {
++ QSGLayer *texture = iterator.value();
++ QQuickItem *item = iterator.key();
++ QQuickItemPrivate::get(item)->derefFromEffectItem(true);
++ delete texture;
++ }
++ }
++
++ void QQuickDesignerSupport::refFromEffectItem(QQuickItem *referencedItem, bool hide)
++ {
++ if (referencedItem == nullptr)
++ return;
++
++ QQuickItemPrivate::get(referencedItem)->refFromEffectItem(hide);
++ QQuickWindowPrivate::get(referencedItem->window())->updateDirtyNode(referencedItem);
++
++ Q_ASSERT(QQuickItemPrivate::get(referencedItem)->rootNode());
++
++ if (!m_itemTextureHash.contains(referencedItem)) {
++ QSGRenderContext *rc = QQuickWindowPrivate::get(referencedItem->window())->context;
++ QSGLayer *texture = rc->sceneGraphContext()->createLayer(rc);
++
++ QSizeF itemSize = referencedItem->size();
++ texture->setLive(true);
++ texture->setItem(QQuickItemPrivate::get(referencedItem)->rootNode());
++ texture->setRect(QRectF(QPointF(0, 0), itemSize));
++ texture->setSize(itemSize.toSize());
++ texture->setRecursive(true);
++ texture->setFormat(QSGLayer::RGBA8);
++ texture->setHasMipmaps(false);
++
++ m_itemTextureHash.insert(referencedItem, texture);
++ }
++ }
++
++ void QQuickDesignerSupport::derefFromEffectItem(QQuickItem *referencedItem, bool unhide)
++ {
++ if (referencedItem == nullptr)
++ return;
++
++ delete m_itemTextureHash.take(referencedItem);
++ QQuickItemPrivate::get(referencedItem)->derefFromEffectItem(unhide);
++ }
++
++ QImage QQuickDesignerSupport::renderImageForItem(QQuickItem *referencedItem, const QRectF &boundingRect, const QSize &imageSize)
++ {
++ if (referencedItem == nullptr || referencedItem->parentItem() == nullptr) {
++ qDebug() << __FILE__ << __LINE__ << "Warning: Item can be rendered.";
++ return QImage();
++ }
++
++ QSGLayer *renderTexture = m_itemTextureHash.value(referencedItem);
++
++ Q_ASSERT(renderTexture);
++ if (renderTexture == nullptr)
++ return QImage();
++ renderTexture->setRect(boundingRect);
++ renderTexture->setSize(imageSize);
++ renderTexture->setItem(QQuickItemPrivate::get(referencedItem)->rootNode());
++ renderTexture->markDirtyTexture();
++ renderTexture->updateTexture();
++
++ QImage renderImage = renderTexture->toImage();
++ renderImage.flip();
++
++ if (renderImage.size().isEmpty())
++ qDebug() << __FILE__ << __LINE__ << "Warning: Image is empty.";
++
++ return renderImage;
++ }
++
++ bool QQuickDesignerSupport::isDirty(QQuickItem *referencedItem, DirtyType dirtyType)
++ {
++ if (referencedItem == nullptr)
++ return false;
++
++ return QQuickItemPrivate::get(referencedItem)->dirtyAttributes & dirtyType;
++ }
++
++ void QQuickDesignerSupport::addDirty(QQuickItem *referencedItem, QQuickDesignerSupport::DirtyType dirtyType)
++ {
++ if (referencedItem == nullptr)
++ return;
++
++ QQuickItemPrivate::get(referencedItem)->dirtyAttributes |= dirtyType;
++ }
++
++ void QQuickDesignerSupport::resetDirty(QQuickItem *referencedItem)
++ {
++ if (referencedItem == nullptr)
++ return;
++
++ QQuickItemPrivate::get(referencedItem)->dirtyAttributes = 0x0;
++ QQuickItemPrivate::get(referencedItem)->removeFromDirtyList();
++ }
++
++ QTransform QQuickDesignerSupport::windowTransform(QQuickItem *referencedItem)
++ {
++ if (referencedItem == nullptr)
++ return QTransform();
++
++ return QQuickItemPrivate::get(referencedItem)->itemToWindowTransform();
++ }
++
++ QTransform QQuickDesignerSupport::parentTransform(QQuickItem *referencedItem)
++ {
++ if (referencedItem == nullptr)
++ return QTransform();
++
++ QTransform parentTransform;
++
++ QQuickItemPrivate::get(referencedItem)->itemToParentTransform(&parentTransform);
++
++ return parentTransform;
++ }
++
++ QString propertyNameForAnchorLine(const QQuickAnchors::Anchor &anchorLine)
++ {
++ switch (anchorLine) {
++ case QQuickAnchors::LeftAnchor: return QLatin1String("left");
++ case QQuickAnchors::RightAnchor: return QLatin1String("right");
++ case QQuickAnchors::TopAnchor: return QLatin1String("top");
++ case QQuickAnchors::BottomAnchor: return QLatin1String("bottom");
++ case QQuickAnchors::HCenterAnchor: return QLatin1String("horizontalCenter");
++ case QQuickAnchors::VCenterAnchor: return QLatin1String("verticalCenter");
++ case QQuickAnchors::BaselineAnchor: return QLatin1String("baseline");
++ case QQuickAnchors::InvalidAnchor: // fallthrough:
++ default: return QString();
++ }
++ }
++
++ bool isValidAnchorName(const QString &name)
++ {
++ static QStringList anchorNameList(QStringList() << QLatin1String("anchors.top")
++ << QLatin1String("anchors.left")
++ << QLatin1String("anchors.right")
++ << QLatin1String("anchors.bottom")
++ << QLatin1String("anchors.verticalCenter")
++ << QLatin1String("anchors.horizontalCenter")
++ << QLatin1String("anchors.fill")
++ << QLatin1String("anchors.centerIn")
++ << QLatin1String("anchors.baseline"));
++
++ return anchorNameList.contains(name);
++ }
++
++ bool QQuickDesignerSupport::isAnchoredTo(QQuickItem *fromItem, QQuickItem *toItem)
++ {
++ QQuickItemPrivate *fromItemPrivate = QQuickItemPrivate::get(fromItem);
++ QQuickAnchors *anchors = fromItemPrivate->anchors();
++ return anchors->fill() == toItem
++ || anchors->centerIn() == toItem
++ || anchors->bottom().item == toItem
++ || anchors->top().item == toItem
++ || anchors->left().item == toItem
++ || anchors->right().item == toItem
++ || anchors->verticalCenter().item == toItem
++ || anchors->horizontalCenter().item == toItem
++ || anchors->baseline().item == toItem;
++ }
++
++ bool QQuickDesignerSupport::areChildrenAnchoredTo(QQuickItem *fromItem, QQuickItem *toItem)
++ {
++ const auto childItems = fromItem->childItems();
++ for (QQuickItem *childItem : childItems) {
++ if (childItem) {
++ if (isAnchoredTo(childItem, toItem))
++ return true;
++
++ if (areChildrenAnchoredTo(childItem, toItem))
++ return true;
++ }
++ }
++
++ return false;
++ }
++
++ QQuickAnchors *anchors(QQuickItem *item)
++ {
++ QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item);
++ return itemPrivate->anchors();
++ }
++
++ QQuickAnchors::Anchor anchorLineFlagForName(const QString &name)
++ {
++ if (name == QLatin1String("anchors.top"))
++ return QQuickAnchors::TopAnchor;
++
++ if (name == QLatin1String("anchors.left"))
++ return QQuickAnchors::LeftAnchor;
++
++ if (name == QLatin1String("anchors.bottom"))
++ return QQuickAnchors::BottomAnchor;
++
++ if (name == QLatin1String("anchors.right"))
++ return QQuickAnchors::RightAnchor;
++
++ if (name == QLatin1String("anchors.horizontalCenter"))
++ return QQuickAnchors::HCenterAnchor;
++
++ if (name == QLatin1String("anchors.verticalCenter"))
++ return QQuickAnchors::VCenterAnchor;
++
++ if (name == QLatin1String("anchors.baseline"))
++ return QQuickAnchors::BaselineAnchor;
++
++
++ Q_ASSERT_X(false, Q_FUNC_INFO, "wrong anchor name - this should never happen");
++ return QQuickAnchors::LeftAnchor;
++ }
++
++ bool QQuickDesignerSupport::hasAnchor(QQuickItem *item, const QString &name)
++ {
++ if (!isValidAnchorName(name))
++ return false;
++
++ if (name == QLatin1String("anchors.fill"))
++ return anchors(item)->fill() != nullptr;
++
++ if (name == QLatin1String("anchors.centerIn"))
++ return anchors(item)->centerIn() != nullptr;
++
++ if (name == QLatin1String("anchors.right"))
++ return anchors(item)->right().item != nullptr;
++
++ if (name == QLatin1String("anchors.top"))
++ return anchors(item)->top().item != nullptr;
++
++ if (name == QLatin1String("anchors.left"))
++ return anchors(item)->left().item != nullptr;
++
++ if (name == QLatin1String("anchors.bottom"))
++ return anchors(item)->bottom().item != nullptr;
++
++ if (name == QLatin1String("anchors.horizontalCenter"))
++ return anchors(item)->horizontalCenter().item != nullptr;
++
++ if (name == QLatin1String("anchors.verticalCenter"))
++ return anchors(item)->verticalCenter().item != nullptr;
++
++ if (name == QLatin1String("anchors.baseline"))
++ return anchors(item)->baseline().item != nullptr;
++
++ return anchors(item)->usedAnchors().testFlag(anchorLineFlagForName(name));
++ }
++
++ QQuickItem *QQuickDesignerSupport::anchorFillTargetItem(QQuickItem *item)
++ {
++ return anchors(item)->fill();
++ }
++
++ QQuickItem *QQuickDesignerSupport::anchorCenterInTargetItem(QQuickItem *item)
++ {
++ return anchors(item)->centerIn();
++ }
++
++
++
++ std::pair<QString, QObject*> QQuickDesignerSupport::anchorLineTarget(QQuickItem *item, const QString &name, QQmlContext *context)
++ {
++ QObject *targetObject = nullptr;
++ QString targetName;
++
++ if (name == QLatin1String("anchors.fill")) {
++ targetObject = anchors(item)->fill();
++ } else if (name == QLatin1String("anchors.centerIn")) {
++ targetObject = anchors(item)->centerIn();
++ } else {
++ QQmlProperty metaProperty(item, name, context);
++ if (!metaProperty.isValid())
++ return std::pair<QString, QObject*>();
++
++ QQuickAnchorLine anchorLine = metaProperty.read().value<QQuickAnchorLine>();
++ if (anchorLine.anchorLine != QQuickAnchors::InvalidAnchor) {
++ targetObject = anchorLine.item;
++ targetName = propertyNameForAnchorLine(anchorLine.anchorLine);
++ }
++
++ }
++
++ return std::pair<QString, QObject*>(targetName, targetObject);
++ }
++
++ void QQuickDesignerSupport::resetAnchor(QQuickItem *item, const QString &name)
++ {
++ if (name == QLatin1String("anchors.fill")) {
++ anchors(item)->resetFill();
++ } else if (name == QLatin1String("anchors.centerIn")) {
++ anchors(item)->resetCenterIn();
++ } else if (name == QLatin1String("anchors.top")) {
++ anchors(item)->resetTop();
++ } else if (name == QLatin1String("anchors.left")) {
++ anchors(item)->resetLeft();
++ } else if (name == QLatin1String("anchors.right")) {
++ anchors(item)->resetRight();
++ } else if (name == QLatin1String("anchors.bottom")) {
++ anchors(item)->resetBottom();
++ } else if (name == QLatin1String("anchors.horizontalCenter")) {
++ anchors(item)->resetHorizontalCenter();
++ } else if (name == QLatin1String("anchors.verticalCenter")) {
++ anchors(item)->resetVerticalCenter();
++ } else if (name == QLatin1String("anchors.baseline")) {
++ anchors(item)->resetBaseline();
++ }
++ }
++
++ void QQuickDesignerSupport::emitComponentCompleteSignalForAttachedProperty(QObject *object)
++ {
++ if (!object)
++ return;
++
++ QQmlData *data = QQmlData::get(object);
++ if (data && data->context) {
++ QQmlComponentAttached *componentAttached = data->context->componentAttacheds();
++ while (componentAttached) {
++ if (componentAttached->parent())
++ if (componentAttached->parent() == object)
++ emit componentAttached->completed();
++
++ componentAttached = componentAttached->next();
++ }
++ }
++ }
++
++ QList<QObject*> QQuickDesignerSupport::statesForItem(QQuickItem *item)
++ {
++ QList<QObject*> objectList;
++ const QList<QQuickState *> stateList = QQuickItemPrivate::get(item)->_states()->states();
++
++ objectList.reserve(stateList.size());
++ for (QQuickState* state : stateList)
++ objectList.append(state);
++
++ return objectList;
++ }
++
++ bool QQuickDesignerSupport::isComponentComplete(QQuickItem *item)
++ {
++ return QQuickItemPrivate::get(item)->componentComplete;
++ }
++
++ int QQuickDesignerSupport::borderWidth(QQuickItem *item)
++ {
++ QQuickRectangle *rectangle = qobject_cast<QQuickRectangle*>(item);
++ if (rectangle)
++ return rectangle->border()->width();
++
++ return 0;
++ }
++
++ void QQuickDesignerSupport::refreshExpressions(QQmlContext *context)
++ {
++ QQmlContextData::get(context)->refreshExpressions();
++ }
++
++ void QQuickDesignerSupport::setRootItem(QQuickView *view, QQuickItem *item)
++ {
++ QQuickViewPrivate::get(view)->setRootObject(item);
++ }
++
++ bool QQuickDesignerSupport::isValidWidth(QQuickItem *item)
++ {
++ return QQuickItemPrivate::get(item)->heightValid();
++ }
++
++ bool QQuickDesignerSupport::isValidHeight(QQuickItem *item)
++ {
++ return QQuickItemPrivate::get(item)->widthValid();
++ }
++
++ void QQuickDesignerSupport::updateDirtyNode(QQuickItem *item)
++ {
++ if (item->window())
++ QQuickWindowPrivate::get(item->window())->updateDirtyNode(item);
++ }
++
++ void QQuickDesignerSupport::activateDesignerMode()
++ {
++ QQmlEnginePrivate::activateDesignerMode();
++ }
++
++ void QQuickDesignerSupport::disableComponentComplete()
++ {
++ QQmlVME::disableComponentComplete();
++ }
++
++ void QQuickDesignerSupport::enableComponentComplete()
++ {
++ QQmlVME::enableComponentComplete();
++ }
++
++ void QQuickDesignerSupport::polishItems(QQuickWindow *window)
++ {
++ QQuickWindowPrivate::get(window)->polishItems();
++ }
++
++ ComponentCompleteDisabler::ComponentCompleteDisabler()
++ {
++ QQuickDesignerSupport::disableComponentComplete();
++ }
++
++ ComponentCompleteDisabler::~ComponentCompleteDisabler()
++ {
++ QQuickDesignerSupport::enableComponentComplete();
++ }
++
++
++ QT_END_NAMESPACE