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 QtDeclarative 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/qdeclarativeengine_p.h>
48 #include <private/qquickview_p.h>
49 #include <QtQuick/private/qdeclarativestategroup_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 Q_ASSERT(dynamic_cast<QQuickItemPrivate*>(QQuickItemPrivate::get(fromItem)));
203 QQuickItemPrivate *fromItemPrivate = static_cast<QQuickItemPrivate*>(QQuickItemPrivate::get(fromItem));
204 QQuickAnchors *anchors = fromItemPrivate->anchors();
205 return anchors->fill() == toItem
206 || anchors->centerIn() == toItem
207 || anchors->bottom().item == toItem
208 || anchors->top().item == toItem
209 || anchors->left().item == toItem
210 || anchors->right().item == toItem
211 || anchors->verticalCenter().item == toItem
212 || anchors->horizontalCenter().item == toItem
213 || anchors->baseline().item == toItem;
216 bool DesignerSupport::areChildrenAnchoredTo(QQuickItem *fromItem, QQuickItem *toItem)
218 foreach (QQuickItem *childItem, fromItem->childItems()) {
220 if (isAnchoredTo(childItem, toItem))
223 if (areChildrenAnchoredTo(childItem, toItem))
231 QQuickAnchors *anchors(QQuickItem *item)
233 QQuickItemPrivate *itemPrivate = static_cast<QQuickItemPrivate*>(QQuickItemPrivate::get(item));
234 return itemPrivate->anchors();
237 QQuickAnchors::Anchor anchorLineFlagForName(const QString &name)
239 if (name == QLatin1String("anchors.top"))
240 return QQuickAnchors::TopAnchor;
242 if (name == QLatin1String("anchors.left"))
243 return QQuickAnchors::LeftAnchor;
245 if (name == QLatin1String("anchors.bottom"))
246 return QQuickAnchors::BottomAnchor;
248 if (name == QLatin1String("anchors.right"))
249 return QQuickAnchors::RightAnchor;
251 if (name == QLatin1String("anchors.horizontalCenter"))
252 return QQuickAnchors::HCenterAnchor;
254 if (name == QLatin1String("anchors.verticalCenter"))
255 return QQuickAnchors::VCenterAnchor;
257 if (name == QLatin1String("anchors.baseline"))
258 return QQuickAnchors::BaselineAnchor;
261 Q_ASSERT_X(false, Q_FUNC_INFO, "wrong anchor name - this should never happen");
262 return QQuickAnchors::LeftAnchor;
265 bool DesignerSupport::hasAnchor(QQuickItem *item, const QString &name)
267 if (!isValidAnchorName(name))
270 if (name == QLatin1String("anchors.fill"))
271 return anchors(item)->fill() != 0;
273 if (name == QLatin1String("anchors.centerIn"))
274 return anchors(item)->centerIn() != 0;
276 if (name == QLatin1String("anchors.right"))
277 return anchors(item)->right().item != 0;
279 if (name == QLatin1String("anchors.top"))
280 return anchors(item)->top().item != 0;
282 if (name == QLatin1String("anchors.left"))
283 return anchors(item)->left().item != 0;
285 if (name == QLatin1String("anchors.bottom"))
286 return anchors(item)->bottom().item != 0;
288 if (name == QLatin1String("anchors.horizontalCenter"))
289 return anchors(item)->horizontalCenter().item != 0;
291 if (name == QLatin1String("anchors.verticalCenter"))
292 return anchors(item)->verticalCenter().item != 0;
294 if (name == QLatin1String("anchors.baseline"))
295 return anchors(item)->baseline().item != 0;
297 return anchors(item)->usedAnchors().testFlag(anchorLineFlagForName(name));
300 QQuickItem *DesignerSupport::anchorFillTargetItem(QQuickItem *item)
302 return anchors(item)->fill();
305 QQuickItem *DesignerSupport::anchorCenterInTargetItem(QQuickItem *item)
307 return anchors(item)->centerIn();
312 QPair<QString, QObject*> DesignerSupport::anchorLineTarget(QQuickItem *item, const QString &name, QDeclarativeContext *context)
314 QObject *targetObject = 0;
317 if (name == QLatin1String("anchors.fill")) {
318 targetObject = anchors(item)->fill();
319 } else if (name == QLatin1String("anchors.centerIn")) {
320 targetObject = anchors(item)->centerIn();
322 QDeclarativeProperty metaProperty(item, name, context);
323 if (!metaProperty.isValid())
324 return QPair<QString, QObject*>();
326 QQuickAnchorLine anchorLine = metaProperty.read().value<QQuickAnchorLine>();
327 if (anchorLine.anchorLine != QQuickAnchorLine::Invalid) {
328 targetObject = anchorLine.item;
329 targetName = propertyNameForAnchorLine(anchorLine.anchorLine);
334 return QPair<QString, QObject*>(targetName, targetObject);
337 void DesignerSupport::resetAnchor(QQuickItem *item, const QString &name)
339 if (name == QLatin1String("anchors.fill")) {
340 anchors(item)->resetFill();
341 } else if (name == QLatin1String("anchors.centerIn")) {
342 anchors(item)->resetCenterIn();
343 } else if (name == QLatin1String("anchors.top")) {
344 anchors(item)->resetTop();
345 } else if (name == QLatin1String("anchors.left")) {
346 anchors(item)->resetLeft();
347 } else if (name == QLatin1String("anchors.right")) {
348 anchors(item)->resetRight();
349 } else if (name == QLatin1String("anchors.bottom")) {
350 anchors(item)->resetBottom();
351 } else if (name == QLatin1String("anchors.horizontalCenter")) {
352 anchors(item)->resetHorizontalCenter();
353 } else if (name == QLatin1String("anchors.verticalCenter")) {
354 anchors(item)->resetVerticalCenter();
355 } else if (name == QLatin1String("anchors.baseline")) {
356 anchors(item)->resetBaseline();
360 QList<QObject*> DesignerSupport::statesForItem(QQuickItem *item)
362 QList<QObject*> objectList;
363 QList<QDeclarativeState *> stateList = QQuickItemPrivate::get(item)->_states()->states();
364 qCopy(stateList.begin(), stateList.end(), objectList.begin());
369 bool DesignerSupport::isComponentComplete(QQuickItem *item)
371 return static_cast<QQuickItemPrivate*>(QQuickItemPrivate::get(item))->componentComplete;
374 int DesignerSupport::borderWidth(QQuickItem *item)
376 QQuickRectangle *rectangle = qobject_cast<QQuickRectangle*>(item);
378 return rectangle->border()->width();
383 void DesignerSupport::refreshExpressions(QDeclarativeContext *context)
385 QDeclarativeContextPrivate::get(context)->data->refreshExpressions();
388 void DesignerSupport::setRootItem(QQuickView *view, QQuickItem *item)
390 QQuickViewPrivate::get(view)->setRootObject(item);
393 bool DesignerSupport::isValidWidth(QQuickItem *item)
395 return QQuickItemPrivate::get(item)->heightValid;
398 bool DesignerSupport::isValidHeight(QQuickItem *item)
400 return QQuickItemPrivate::get(item)->widthValid;
403 void DesignerSupport::updateDirtyNode(QQuickItem *item)
405 QQuickCanvasPrivate::get(item->canvas())->updateDirtyNode(item);