Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qquickdesignersupport.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3// Qt-Security score:significant reason:default
4
6#include <private/qquickitem_p.h>
7
8#if QT_CONFIG(quick_shadereffect)
9#include <QtQuick/private/qquickshadereffectsource_p.h>
10#endif
11#include <QtQuick/private/qquickrectangle_p.h>
12#include <QtQml/private/qabstractanimationjob_p.h>
13#include <private/qqmlengine_p.h>
14#include <private/qquickview_p.h>
15#include <QtQuick/private/qquickstategroup_p.h>
16#include <QtGui/QImage>
17#include <private/qqmlvme_p.h>
18#include <private/qqmlcomponentattached_p.h>
19#include <private/qqmldata_p.h>
20#include <private/qsgadaptationlayer_p.h>
21
23
24QQuickDesignerSupport::QQuickDesignerSupport()
25{
26}
27
28QQuickDesignerSupport::~QQuickDesignerSupport()
29{
30 typedef QHash<QQuickItem*, QSGLayer*>::iterator ItemTextureHashIt;
31
32 for (ItemTextureHashIt iterator = m_itemTextureHash.begin(), end = m_itemTextureHash.end(); iterator != end; ++iterator) {
33 QSGLayer *texture = iterator.value();
34 QQuickItem *item = iterator.key();
35 QQuickItemPrivate::get(item)->derefFromEffectItem(true);
36 delete texture;
37 }
38}
39
40void QQuickDesignerSupport::refFromEffectItem(QQuickItem *referencedItem, bool hide)
41{
42 if (referencedItem == nullptr)
43 return;
44
45 QQuickItemPrivate::get(referencedItem)->refFromEffectItem(hide);
46 QQuickWindowPrivate::get(referencedItem->window())->updateDirtyNode(referencedItem);
47
48 Q_ASSERT(QQuickItemPrivate::get(referencedItem)->rootNode());
49
50 if (!m_itemTextureHash.contains(referencedItem)) {
51 QSGRenderContext *rc = QQuickWindowPrivate::get(referencedItem->window())->context;
52 QSGLayer *texture = rc->sceneGraphContext()->createLayer(rc);
53
54 QSizeF itemSize = referencedItem->size();
55 texture->setLive(true);
56 texture->setItem(QQuickItemPrivate::get(referencedItem)->rootNode());
57 texture->setRect(QRectF(QPointF(0, 0), itemSize));
58 texture->setSize(itemSize.toSize());
59 texture->setRecursive(true);
60 texture->setFormat(QSGLayer::RGBA8);
61 texture->setHasMipmaps(false);
62
63 m_itemTextureHash.insert(referencedItem, texture);
64 }
65}
66
67void QQuickDesignerSupport::derefFromEffectItem(QQuickItem *referencedItem, bool unhide)
68{
69 if (referencedItem == nullptr)
70 return;
71
72 delete m_itemTextureHash.take(referencedItem);
73 QQuickItemPrivate::get(referencedItem)->derefFromEffectItem(unhide);
74}
75
76QImage QQuickDesignerSupport::renderImageForItem(QQuickItem *referencedItem, const QRectF &boundingRect, const QSize &imageSize)
77{
78 if (referencedItem == nullptr || referencedItem->parentItem() == nullptr) {
79 qDebug() << __FILE__ << __LINE__ << "Warning: Item can be rendered.";
80 return QImage();
81 }
82
83 QSGLayer *renderTexture = m_itemTextureHash.value(referencedItem);
84
85 Q_ASSERT(renderTexture);
86 if (renderTexture == nullptr)
87 return QImage();
88 renderTexture->setRect(boundingRect);
89 renderTexture->setSize(imageSize);
90 renderTexture->setItem(QQuickItemPrivate::get(referencedItem)->rootNode());
91 renderTexture->markDirtyTexture();
92 renderTexture->updateTexture();
93
94 QImage renderImage = renderTexture->toImage();
95 renderImage.flip();
96
97 if (renderImage.size().isEmpty())
98 qDebug() << __FILE__ << __LINE__ << "Warning: Image is empty.";
99
100 return renderImage;
101}
102
103bool QQuickDesignerSupport::isDirty(QQuickItem *referencedItem, DirtyType dirtyType)
104{
105 if (referencedItem == nullptr)
106 return false;
107
108 return QQuickItemPrivate::get(referencedItem)->dirtyAttributes & dirtyType;
109}
110
111void QQuickDesignerSupport::addDirty(QQuickItem *referencedItem, QQuickDesignerSupport::DirtyType dirtyType)
112{
113 if (referencedItem == nullptr)
114 return;
115
116 QQuickItemPrivate::get(referencedItem)->dirtyAttributes |= dirtyType;
117}
118
119void QQuickDesignerSupport::resetDirty(QQuickItem *referencedItem)
120{
121 if (referencedItem == nullptr)
122 return;
123
124 QQuickItemPrivate::get(referencedItem)->dirtyAttributes = 0x0;
125 QQuickItemPrivate::get(referencedItem)->removeFromDirtyList();
126}
127
128QTransform QQuickDesignerSupport::windowTransform(QQuickItem *referencedItem)
129{
130 if (referencedItem == nullptr)
131 return QTransform();
132
133 return QQuickItemPrivate::get(referencedItem)->itemToWindowTransform();
134}
135
136QTransform QQuickDesignerSupport::parentTransform(QQuickItem *referencedItem)
137{
138 if (referencedItem == nullptr)
139 return QTransform();
140
141 QTransform parentTransform;
142
143 QQuickItemPrivate::get(referencedItem)->itemToParentTransform(&parentTransform);
144
145 return parentTransform;
146}
147
148QString propertyNameForAnchorLine(const QQuickAnchors::Anchor &anchorLine)
149{
150 switch (anchorLine) {
151 case QQuickAnchors::LeftAnchor: return QLatin1String("left");
152 case QQuickAnchors::RightAnchor: return QLatin1String("right");
153 case QQuickAnchors::TopAnchor: return QLatin1String("top");
154 case QQuickAnchors::BottomAnchor: return QLatin1String("bottom");
155 case QQuickAnchors::HCenterAnchor: return QLatin1String("horizontalCenter");
156 case QQuickAnchors::VCenterAnchor: return QLatin1String("verticalCenter");
157 case QQuickAnchors::BaselineAnchor: return QLatin1String("baseline");
158 case QQuickAnchors::InvalidAnchor: // fallthrough:
159 default: return QString();
160 }
161}
162
163bool isValidAnchorName(const QString &name)
164{
165 static QStringList anchorNameList(QStringList() << QLatin1String("anchors.top")
166 << QLatin1String("anchors.left")
167 << QLatin1String("anchors.right")
168 << QLatin1String("anchors.bottom")
169 << QLatin1String("anchors.verticalCenter")
170 << QLatin1String("anchors.horizontalCenter")
171 << QLatin1String("anchors.fill")
172 << QLatin1String("anchors.centerIn")
173 << QLatin1String("anchors.baseline"));
174
175 return anchorNameList.contains(name);
176}
177
178bool QQuickDesignerSupport::isAnchoredTo(QQuickItem *fromItem, QQuickItem *toItem)
179{
180 QQuickItemPrivate *fromItemPrivate = QQuickItemPrivate::get(fromItem);
181 QQuickAnchors *anchors = fromItemPrivate->anchors();
182 return anchors->fill() == toItem
183 || anchors->centerIn() == toItem
184 || anchors->bottom().item == toItem
185 || anchors->top().item == toItem
186 || anchors->left().item == toItem
187 || anchors->right().item == toItem
188 || anchors->verticalCenter().item == toItem
189 || anchors->horizontalCenter().item == toItem
190 || anchors->baseline().item == toItem;
191}
192
193bool QQuickDesignerSupport::areChildrenAnchoredTo(QQuickItem *fromItem, QQuickItem *toItem)
194{
195 const auto childItems = fromItem->childItems();
196 for (QQuickItem *childItem : childItems) {
197 if (childItem) {
198 if (isAnchoredTo(childItem, toItem))
199 return true;
200
201 if (areChildrenAnchoredTo(childItem, toItem))
202 return true;
203 }
204 }
205
206 return false;
207}
208
209QQuickAnchors *anchors(QQuickItem *item)
210{
211 QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item);
212 return itemPrivate->anchors();
213}
214
216{
217 if (name == QLatin1String("anchors.top"))
218 return QQuickAnchors::TopAnchor;
219
220 if (name == QLatin1String("anchors.left"))
221 return QQuickAnchors::LeftAnchor;
222
223 if (name == QLatin1String("anchors.bottom"))
224 return QQuickAnchors::BottomAnchor;
225
226 if (name == QLatin1String("anchors.right"))
227 return QQuickAnchors::RightAnchor;
228
229 if (name == QLatin1String("anchors.horizontalCenter"))
230 return QQuickAnchors::HCenterAnchor;
231
232 if (name == QLatin1String("anchors.verticalCenter"))
233 return QQuickAnchors::VCenterAnchor;
234
235 if (name == QLatin1String("anchors.baseline"))
236 return QQuickAnchors::BaselineAnchor;
237
238
239 Q_ASSERT_X(false, Q_FUNC_INFO, "wrong anchor name - this should never happen");
240 return QQuickAnchors::LeftAnchor;
241}
242
243bool QQuickDesignerSupport::hasAnchor(QQuickItem *item, const QString &name)
244{
245 if (!isValidAnchorName(name))
246 return false;
247
248 if (name == QLatin1String("anchors.fill"))
249 return anchors(item)->fill() != nullptr;
250
251 if (name == QLatin1String("anchors.centerIn"))
252 return anchors(item)->centerIn() != nullptr;
253
254 if (name == QLatin1String("anchors.right"))
255 return anchors(item)->right().item != nullptr;
256
257 if (name == QLatin1String("anchors.top"))
258 return anchors(item)->top().item != nullptr;
259
260 if (name == QLatin1String("anchors.left"))
261 return anchors(item)->left().item != nullptr;
262
263 if (name == QLatin1String("anchors.bottom"))
264 return anchors(item)->bottom().item != nullptr;
265
266 if (name == QLatin1String("anchors.horizontalCenter"))
267 return anchors(item)->horizontalCenter().item != nullptr;
268
269 if (name == QLatin1String("anchors.verticalCenter"))
270 return anchors(item)->verticalCenter().item != nullptr;
271
272 if (name == QLatin1String("anchors.baseline"))
273 return anchors(item)->baseline().item != nullptr;
274
275 return anchors(item)->usedAnchors().testFlag(anchorLineFlagForName(name));
276}
277
278QQuickItem *QQuickDesignerSupport::anchorFillTargetItem(QQuickItem *item)
279{
280 return anchors(item)->fill();
281}
282
283QQuickItem *QQuickDesignerSupport::anchorCenterInTargetItem(QQuickItem *item)
284{
285 return anchors(item)->centerIn();
286}
287
288
289
290std::pair<QString, QObject*> QQuickDesignerSupport::anchorLineTarget(QQuickItem *item, const QString &name, QQmlContext *context)
291{
292 QObject *targetObject = nullptr;
293 QString targetName;
294
295 if (name == QLatin1String("anchors.fill")) {
296 targetObject = anchors(item)->fill();
297 } else if (name == QLatin1String("anchors.centerIn")) {
298 targetObject = anchors(item)->centerIn();
299 } else {
300 QQmlProperty metaProperty(item, name, context);
301 if (!metaProperty.isValid())
302 return std::pair<QString, QObject*>();
303
304 QQuickAnchorLine anchorLine = metaProperty.read().value<QQuickAnchorLine>();
305 if (anchorLine.anchorLine != QQuickAnchors::InvalidAnchor) {
306 targetObject = anchorLine.item;
307 targetName = propertyNameForAnchorLine(anchorLine.anchorLine);
308 }
309
310 }
311
312 return std::pair<QString, QObject*>(targetName, targetObject);
313}
314
315void QQuickDesignerSupport::resetAnchor(QQuickItem *item, const QString &name)
316{
317 if (name == QLatin1String("anchors.fill")) {
318 anchors(item)->resetFill();
319 } else if (name == QLatin1String("anchors.centerIn")) {
320 anchors(item)->resetCenterIn();
321 } else if (name == QLatin1String("anchors.top")) {
322 anchors(item)->resetTop();
323 } else if (name == QLatin1String("anchors.left")) {
324 anchors(item)->resetLeft();
325 } else if (name == QLatin1String("anchors.right")) {
326 anchors(item)->resetRight();
327 } else if (name == QLatin1String("anchors.bottom")) {
328 anchors(item)->resetBottom();
329 } else if (name == QLatin1String("anchors.horizontalCenter")) {
330 anchors(item)->resetHorizontalCenter();
331 } else if (name == QLatin1String("anchors.verticalCenter")) {
332 anchors(item)->resetVerticalCenter();
333 } else if (name == QLatin1String("anchors.baseline")) {
334 anchors(item)->resetBaseline();
335 }
336}
337
338void QQuickDesignerSupport::emitComponentCompleteSignalForAttachedProperty(QObject *object)
339{
340 if (!object)
341 return;
342
343 QQmlData *data = QQmlData::get(object);
344 if (data && data->context) {
345 QQmlComponentAttached *componentAttached = data->context->componentAttacheds();
346 while (componentAttached) {
347 if (componentAttached->parent())
348 if (componentAttached->parent() == object)
349 emit componentAttached->completed();
350
351 componentAttached = componentAttached->next();
352 }
353 }
354}
355
356QList<QObject*> QQuickDesignerSupport::statesForItem(QQuickItem *item)
357{
358 QList<QObject*> objectList;
359 const QList<QQuickState *> stateList = QQuickItemPrivate::get(item)->_states()->states();
360
361 objectList.reserve(stateList.size());
362 for (QQuickState* state : stateList)
363 objectList.append(state);
364
365 return objectList;
366}
367
368bool QQuickDesignerSupport::isComponentComplete(QQuickItem *item)
369{
370 return QQuickItemPrivate::get(item)->componentComplete;
371}
372
373int QQuickDesignerSupport::borderWidth(QQuickItem *item)
374{
375 QQuickRectangle *rectangle = qobject_cast<QQuickRectangle*>(item);
376 if (rectangle)
377 return rectangle->border()->width();
378
379 return 0;
380}
381
382void QQuickDesignerSupport::refreshExpressions(QQmlContext *context)
383{
384 QQmlContextData::get(context)->refreshExpressions();
385}
386
387void QQuickDesignerSupport::setRootItem(QQuickView *view, QQuickItem *item)
388{
389 QQuickViewPrivate::get(view)->setRootObject(item);
390}
391
392bool QQuickDesignerSupport::isValidWidth(QQuickItem *item)
393{
394 return QQuickItemPrivate::get(item)->heightValid();
395}
396
397bool QQuickDesignerSupport::isValidHeight(QQuickItem *item)
398{
399 return QQuickItemPrivate::get(item)->widthValid();
400}
401
402void QQuickDesignerSupport::updateDirtyNode(QQuickItem *item)
403{
404 if (item->window())
405 QQuickWindowPrivate::get(item->window())->updateDirtyNode(item);
406}
407
408void QQuickDesignerSupport::activateDesignerMode()
409{
410 QQmlEnginePrivate::activateDesignerMode();
411}
412
413void QQuickDesignerSupport::disableComponentComplete()
414{
415 QQmlVME::disableComponentComplete();
416}
417
418void QQuickDesignerSupport::enableComponentComplete()
419{
420 QQmlVME::enableComponentComplete();
421}
422
423void QQuickDesignerSupport::polishItems(QQuickWindow *window)
424{
425 QQuickWindowPrivate::get(window)->polishItems();
426}
427
428ComponentCompleteDisabler::ComponentCompleteDisabler()
429{
430 QQuickDesignerSupport::disableComponentComplete();
431}
432
433ComponentCompleteDisabler::~ComponentCompleteDisabler()
434{
435 QQuickDesignerSupport::enableComponentComplete();
436}
437
438
439QT_END_NAMESPACE
Combined button and popup list for selecting options.
QString propertyNameForAnchorLine(const QQuickAnchors::Anchor &anchorLine)
bool isValidAnchorName(const QString &name)
QQuickAnchors * anchors(QQuickItem *item)
QQuickAnchors::Anchor anchorLineFlagForName(const QString &name)