1 /****************************************************************************
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
6 ** This file is part of the QtQml module of the Qt Toolkit.
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
42 #include "designersupport.h"
43 #include <private/qquickitem_p.h>
45 #include <QtQuick/private/qquickshadereffectsource_p.h>
46 #include <QtQuick/private/qquickrectangle_p.h>
47 #include <private/qqmlengine_p.h>
48 #include <private/qquickview_p.h>
49 #include <QtQuick/private/qquickstategroup_p.h>
50 #include <QtGui/QImage>
54 DesignerSupport::DesignerSupport()
58 DesignerSupport::~DesignerSupport()
60 QHash<QQuickItem*, QQuickShaderEffectTexture*>::iterator iterator;
62 for (iterator = m_itemTextureHash.begin(); iterator != m_itemTextureHash.end(); ++iterator) {
63 QQuickShaderEffectTexture *texture = iterator.value();
64 QQuickItem *item = iterator.key();
65 QQuickItemPrivate::get(item)->derefFromEffectItem(true);
70 void DesignerSupport::refFromEffectItem(QQuickItem *referencedItem, bool hide)
72 if (referencedItem == 0)
75 QQuickItemPrivate::get(referencedItem)->refFromEffectItem(hide);
76 QQuickCanvasPrivate::get(referencedItem->canvas())->updateDirtyNode(referencedItem);
78 Q_ASSERT(QQuickItemPrivate::get(referencedItem)->rootNode());
80 if (!m_itemTextureHash.contains(referencedItem)) {
81 QQuickShaderEffectTexture *texture = new QQuickShaderEffectTexture(referencedItem);
83 texture->setLive(true);
84 texture->setItem(QQuickItemPrivate::get(referencedItem)->rootNode());
85 texture->setRect(referencedItem->boundingRect());
86 texture->setSize(referencedItem->boundingRect().size().toSize());
87 texture->setRecursive(true);
89 texture->setFormat(GL_RGBA8);
91 texture->setFormat(GL_RGBA);
93 texture->setHasMipmaps(false);
95 m_itemTextureHash.insert(referencedItem, texture);
99 void DesignerSupport::derefFromEffectItem(QQuickItem *referencedItem, bool unhide)
101 if (referencedItem == 0)
104 delete m_itemTextureHash.take(referencedItem);
105 QQuickItemPrivate::get(referencedItem)->derefFromEffectItem(unhide);
108 QImage DesignerSupport::renderImageForItem(QQuickItem *referencedItem, const QRectF &boundingRect, const QSize &imageSize)
110 if (referencedItem == 0 || referencedItem->parentItem() == 0) {
111 qDebug() << __FILE__ << __LINE__ << "Warning: Item can be rendered.";
115 QQuickShaderEffectTexture *renderTexture = m_itemTextureHash.value(referencedItem);
117 Q_ASSERT(renderTexture);
118 if (renderTexture == 0)
120 renderTexture->setRect(boundingRect);
121 renderTexture->setSize(imageSize);
122 renderTexture->updateTexture();
124 QImage renderImage = renderTexture->toImage();
125 renderImage = renderImage.mirrored(false, true);
127 if (renderImage.size().isEmpty())
128 qDebug() << __FILE__ << __LINE__ << "Warning: Image is empty.";
133 bool DesignerSupport::isDirty(QQuickItem *referencedItem, DirtyType dirtyType)
135 if (referencedItem == 0)
138 return QQuickItemPrivate::get(referencedItem)->dirtyAttributes & dirtyType;
141 void DesignerSupport::resetDirty(QQuickItem *referencedItem)
143 if (referencedItem == 0)
146 QQuickItemPrivate::get(referencedItem)->dirtyAttributes = 0x0;
147 QQuickItemPrivate::get(referencedItem)->removeFromDirtyList();
150 QTransform DesignerSupport::canvasTransform(QQuickItem *referencedItem)
152 if (referencedItem == 0)
155 return QQuickItemPrivate::get(referencedItem)->itemToCanvasTransform();
158 QTransform DesignerSupport::parentTransform(QQuickItem *referencedItem)
160 if (referencedItem == 0)
163 QTransform parentTransform;
165 QQuickItemPrivate::get(referencedItem)->itemToParentTransform(parentTransform);
167 return parentTransform;
170 QString propertyNameForAnchorLine(const QQuickAnchorLine::AnchorLine &anchorLine)
172 switch (anchorLine) {
173 case QQuickAnchorLine::Left: return QLatin1String("left");
174 case QQuickAnchorLine::Right: return QLatin1String("right");
175 case QQuickAnchorLine::Top: return QLatin1String("top");
176 case QQuickAnchorLine::Bottom: return QLatin1String("bottom");
177 case QQuickAnchorLine::HCenter: return QLatin1String("horizontalCenter");
178 case QQuickAnchorLine::VCenter: return QLatin1String("verticalCenter");
179 case QQuickAnchorLine::Baseline: return QLatin1String("baseline");
180 case QQuickAnchorLine::Invalid:
181 default: return QString();
185 bool isValidAnchorName(const QString &name)
187 static QStringList anchorNameList(QStringList() << QLatin1String("anchors.top")
188 << QLatin1String("anchors.left")
189 << QLatin1String("anchors.right")
190 << QLatin1String("anchors.bottom")
191 << QLatin1String("anchors.verticalCenter")
192 << QLatin1String("anchors.horizontalCenter")
193 << QLatin1String("anchors.fill")
194 << QLatin1String("anchors.centerIn")
195 << QLatin1String("anchors.baseline"));
197 return anchorNameList.contains(name);
200 bool DesignerSupport::isAnchoredTo(QQuickItem *fromItem, QQuickItem *toItem)
202 #ifndef QT_NO_DYNAMIC_CAST
203 Q_ASSERT(dynamic_cast<QQuickItemPrivate*>(QQuickItemPrivate::get(fromItem)));
205 QQuickItemPrivate *fromItemPrivate = static_cast<QQuickItemPrivate*>(QQuickItemPrivate::get(fromItem));
206 QQuickAnchors *anchors = fromItemPrivate->anchors();
207 return anchors->fill() == toItem
208 || anchors->centerIn() == toItem
209 || anchors->bottom().item == toItem
210 || anchors->top().item == toItem
211 || anchors->left().item == toItem
212 || anchors->right().item == toItem
213 || anchors->verticalCenter().item == toItem
214 || anchors->horizontalCenter().item == toItem
215 || anchors->baseline().item == toItem;
218 bool DesignerSupport::areChildrenAnchoredTo(QQuickItem *fromItem, QQuickItem *toItem)
220 foreach (QQuickItem *childItem, fromItem->childItems()) {
222 if (isAnchoredTo(childItem, toItem))
225 if (areChildrenAnchoredTo(childItem, toItem))
233 QQuickAnchors *anchors(QQuickItem *item)
235 QQuickItemPrivate *itemPrivate = static_cast<QQuickItemPrivate*>(QQuickItemPrivate::get(item));
236 return itemPrivate->anchors();
239 QQuickAnchors::Anchor anchorLineFlagForName(const QString &name)
241 if (name == QLatin1String("anchors.top"))
242 return QQuickAnchors::TopAnchor;
244 if (name == QLatin1String("anchors.left"))
245 return QQuickAnchors::LeftAnchor;
247 if (name == QLatin1String("anchors.bottom"))
248 return QQuickAnchors::BottomAnchor;
250 if (name == QLatin1String("anchors.right"))
251 return QQuickAnchors::RightAnchor;
253 if (name == QLatin1String("anchors.horizontalCenter"))
254 return QQuickAnchors::HCenterAnchor;
256 if (name == QLatin1String("anchors.verticalCenter"))
257 return QQuickAnchors::VCenterAnchor;
259 if (name == QLatin1String("anchors.baseline"))
260 return QQuickAnchors::BaselineAnchor;
263 Q_ASSERT_X(false, Q_FUNC_INFO, "wrong anchor name - this should never happen");
264 return QQuickAnchors::LeftAnchor;
267 bool DesignerSupport::hasAnchor(QQuickItem *item, const QString &name)
269 if (!isValidAnchorName(name))
272 if (name == QLatin1String("anchors.fill"))
273 return anchors(item)->fill() != 0;
275 if (name == QLatin1String("anchors.centerIn"))
276 return anchors(item)->centerIn() != 0;
278 if (name == QLatin1String("anchors.right"))
279 return anchors(item)->right().item != 0;
281 if (name == QLatin1String("anchors.top"))
282 return anchors(item)->top().item != 0;
284 if (name == QLatin1String("anchors.left"))
285 return anchors(item)->left().item != 0;
287 if (name == QLatin1String("anchors.bottom"))
288 return anchors(item)->bottom().item != 0;
290 if (name == QLatin1String("anchors.horizontalCenter"))
291 return anchors(item)->horizontalCenter().item != 0;
293 if (name == QLatin1String("anchors.verticalCenter"))
294 return anchors(item)->verticalCenter().item != 0;
296 if (name == QLatin1String("anchors.baseline"))
297 return anchors(item)->baseline().item != 0;
299 return anchors(item)->usedAnchors().testFlag(anchorLineFlagForName(name));
302 QQuickItem *DesignerSupport::anchorFillTargetItem(QQuickItem *item)
304 return anchors(item)->fill();
307 QQuickItem *DesignerSupport::anchorCenterInTargetItem(QQuickItem *item)
309 return anchors(item)->centerIn();
314 QPair<QString, QObject*> DesignerSupport::anchorLineTarget(QQuickItem *item, const QString &name, QQmlContext *context)
316 QObject *targetObject = 0;
319 if (name == QLatin1String("anchors.fill")) {
320 targetObject = anchors(item)->fill();
321 } else if (name == QLatin1String("anchors.centerIn")) {
322 targetObject = anchors(item)->centerIn();
324 QQmlProperty metaProperty(item, name, context);
325 if (!metaProperty.isValid())
326 return QPair<QString, QObject*>();
328 QQuickAnchorLine anchorLine = metaProperty.read().value<QQuickAnchorLine>();
329 if (anchorLine.anchorLine != QQuickAnchorLine::Invalid) {
330 targetObject = anchorLine.item;
331 targetName = propertyNameForAnchorLine(anchorLine.anchorLine);
336 return QPair<QString, QObject*>(targetName, targetObject);
339 void DesignerSupport::resetAnchor(QQuickItem *item, const QString &name)
341 if (name == QLatin1String("anchors.fill")) {
342 anchors(item)->resetFill();
343 } else if (name == QLatin1String("anchors.centerIn")) {
344 anchors(item)->resetCenterIn();
345 } else if (name == QLatin1String("anchors.top")) {
346 anchors(item)->resetTop();
347 } else if (name == QLatin1String("anchors.left")) {
348 anchors(item)->resetLeft();
349 } else if (name == QLatin1String("anchors.right")) {
350 anchors(item)->resetRight();
351 } else if (name == QLatin1String("anchors.bottom")) {
352 anchors(item)->resetBottom();
353 } else if (name == QLatin1String("anchors.horizontalCenter")) {
354 anchors(item)->resetHorizontalCenter();
355 } else if (name == QLatin1String("anchors.verticalCenter")) {
356 anchors(item)->resetVerticalCenter();
357 } else if (name == QLatin1String("anchors.baseline")) {
358 anchors(item)->resetBaseline();
362 QList<QObject*> DesignerSupport::statesForItem(QQuickItem *item)
364 QList<QObject*> objectList;
365 QList<QQuickState *> stateList = QQuickItemPrivate::get(item)->_states()->states();
366 qCopy(stateList.begin(), stateList.end(), objectList.begin());
371 bool DesignerSupport::isComponentComplete(QQuickItem *item)
373 return static_cast<QQuickItemPrivate*>(QQuickItemPrivate::get(item))->componentComplete;
376 int DesignerSupport::borderWidth(QQuickItem *item)
378 QQuickRectangle *rectangle = qobject_cast<QQuickRectangle*>(item);
380 return rectangle->border()->width();
385 void DesignerSupport::refreshExpressions(QQmlContext *context)
387 QQmlContextPrivate::get(context)->data->refreshExpressions();
390 void DesignerSupport::setRootItem(QQuickView *view, QQuickItem *item)
392 QQuickViewPrivate::get(view)->setRootObject(item);
395 bool DesignerSupport::isValidWidth(QQuickItem *item)
397 return QQuickItemPrivate::get(item)->heightValid;
400 bool DesignerSupport::isValidHeight(QQuickItem *item)
402 return QQuickItemPrivate::get(item)->widthValid;
405 void DesignerSupport::updateDirtyNode(QQuickItem *item)
407 QQuickCanvasPrivate::get(item->canvas())->updateDirtyNode(item);