a5ddc6dcc785c50b0684e9c72fed8efaa943f4a2
[profile/ivi/qtdeclarative.git] / src / quick / designer / designersupport.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: http://www.qt-project.org/
6 **
7 ** This file is part of the QtDeclarative module of the Qt Toolkit.
8 **
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** GNU Lesser General Public License Usage
11 ** This file may be used under the terms of the GNU Lesser General Public
12 ** License version 2.1 as published by the Free Software Foundation and
13 ** appearing in the file LICENSE.LGPL included in the packaging of this
14 ** file. Please review the following information to ensure the GNU Lesser
15 ** General Public License version 2.1 requirements will be met:
16 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17 **
18 ** In addition, as a special exception, Nokia gives you certain additional
19 ** rights. These rights are described in the Nokia Qt LGPL Exception
20 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21 **
22 ** GNU General Public License Usage
23 ** Alternatively, this file may be used under the terms of the GNU General
24 ** Public License version 3.0 as published by the Free Software Foundation
25 ** and appearing in the file LICENSE.GPL included in the packaging of this
26 ** file. Please review the following information to ensure the GNU General
27 ** Public License version 3.0 requirements will be met:
28 ** http://www.gnu.org/copyleft/gpl.html.
29 **
30 ** Other Usage
31 ** Alternatively, this file may be used in accordance with the terms and
32 ** conditions contained in a signed written agreement between you and Nokia.
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include "designersupport.h"
43 #include <private/qquickitem_p.h>
44
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>
51
52 QT_BEGIN_NAMESPACE
53
54 DesignerSupport::DesignerSupport()
55 {
56 }
57
58 DesignerSupport::~DesignerSupport()
59 {
60     QHash<QQuickItem*, QQuickShaderEffectTexture*>::iterator iterator;
61
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);
66         delete texture;
67     }
68 }
69
70 void DesignerSupport::refFromEffectItem(QQuickItem *referencedItem, bool hide)
71 {
72     if (referencedItem == 0)
73         return;
74
75     QQuickItemPrivate::get(referencedItem)->refFromEffectItem(hide);
76     QQuickCanvasPrivate::get(referencedItem->canvas())->updateDirtyNode(referencedItem);
77
78     Q_ASSERT(QQuickItemPrivate::get(referencedItem)->rootNode);
79
80     if (!m_itemTextureHash.contains(referencedItem)) {
81         QQuickShaderEffectTexture *texture = new QQuickShaderEffectTexture(referencedItem);
82
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);
88 #ifndef QT_OPENGL_ES
89         texture->setFormat(GL_RGBA8);
90 #else
91         texture->setFormat(GL_RGBA);
92 #endif
93         texture->setHasMipmaps(false);
94
95         m_itemTextureHash.insert(referencedItem, texture);
96     }
97 }
98
99 void DesignerSupport::derefFromEffectItem(QQuickItem *referencedItem, bool unhide)
100 {
101     if (referencedItem == 0)
102         return;
103
104     delete m_itemTextureHash.take(referencedItem);
105     QQuickItemPrivate::get(referencedItem)->derefFromEffectItem(unhide);
106 }
107
108 QImage DesignerSupport::renderImageForItem(QQuickItem *referencedItem, const QRectF &boundingRect, const QSize &imageSize)
109 {
110     if (referencedItem == 0 || referencedItem->parentItem() == 0) {
111         qDebug() << __FILE__ << __LINE__ << "Warning: Item can be rendered.";
112         return QImage();
113     }
114
115     QQuickShaderEffectTexture *renderTexture = m_itemTextureHash.value(referencedItem);
116
117     Q_ASSERT(renderTexture);
118     if (renderTexture == 0)
119          return QImage();
120     renderTexture->setRect(boundingRect);
121     renderTexture->setSize(imageSize);
122     renderTexture->updateTexture();
123
124     QImage renderImage = renderTexture->toImage();
125     renderImage = renderImage.mirrored(false, true);
126
127     if (renderImage.size().isEmpty())
128         qDebug() << __FILE__ << __LINE__ << "Warning: Image is empty.";
129
130     return renderImage;
131 }
132
133 bool DesignerSupport::isDirty(QQuickItem *referencedItem, DirtyType dirtyType)
134 {
135     if (referencedItem == 0)
136         return false;
137
138     return QQuickItemPrivate::get(referencedItem)->dirtyAttributes & dirtyType;
139 }
140
141 void DesignerSupport::resetDirty(QQuickItem *referencedItem)
142 {
143     if (referencedItem == 0)
144         return;
145
146     QQuickItemPrivate::get(referencedItem)->dirtyAttributes = 0x0;
147     QQuickItemPrivate::get(referencedItem)->removeFromDirtyList();
148 }
149
150 QTransform DesignerSupport::canvasTransform(QQuickItem *referencedItem)
151 {
152     if (referencedItem == 0)
153         return QTransform();
154
155     return QQuickItemPrivate::get(referencedItem)->itemToCanvasTransform();
156 }
157
158 QTransform DesignerSupport::parentTransform(QQuickItem *referencedItem)
159 {
160     if (referencedItem == 0)
161         return QTransform();
162
163     QTransform parentTransform;
164
165     QQuickItemPrivate::get(referencedItem)->itemToParentTransform(parentTransform);
166
167     return parentTransform;
168 }
169
170 QString propertyNameForAnchorLine(const QQuickAnchorLine::AnchorLine &anchorLine)
171 {
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();
182     }
183 }
184
185 bool isValidAnchorName(const QString &name)
186 {
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"));
196
197     return anchorNameList.contains(name);
198 }
199
200 bool DesignerSupport::isAnchoredTo(QQuickItem *fromItem, QQuickItem *toItem)
201 {
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;
214 }
215
216 bool DesignerSupport::areChildrenAnchoredTo(QQuickItem *fromItem, QQuickItem *toItem)
217 {
218     foreach (QQuickItem *childItem, fromItem->childItems()) {
219         if (childItem) {
220             if (isAnchoredTo(childItem, toItem))
221                 return true;
222
223             if (areChildrenAnchoredTo(childItem, toItem))
224                 return true;
225         }
226     }
227
228     return false;
229 }
230
231 QQuickAnchors *anchors(QQuickItem *item)
232 {
233     QQuickItemPrivate *itemPrivate = static_cast<QQuickItemPrivate*>(QQuickItemPrivate::get(item));
234     return itemPrivate->anchors();
235 }
236
237 QQuickAnchors::Anchor anchorLineFlagForName(const QString &name)
238 {
239     if (name == QLatin1String("anchors.top"))
240         return QQuickAnchors::TopAnchor;
241
242     if (name == QLatin1String("anchors.left"))
243         return QQuickAnchors::LeftAnchor;
244
245     if (name == QLatin1String("anchors.bottom"))
246          return QQuickAnchors::BottomAnchor;
247
248     if (name == QLatin1String("anchors.right"))
249         return QQuickAnchors::RightAnchor;
250
251     if (name == QLatin1String("anchors.horizontalCenter"))
252         return QQuickAnchors::HCenterAnchor;
253
254     if (name == QLatin1String("anchors.verticalCenter"))
255          return QQuickAnchors::VCenterAnchor;
256
257     if (name == QLatin1String("anchors.baseline"))
258          return QQuickAnchors::BaselineAnchor;
259
260
261     Q_ASSERT_X(false, Q_FUNC_INFO, "wrong anchor name - this should never happen");
262     return QQuickAnchors::LeftAnchor;
263 }
264
265 bool DesignerSupport::hasAnchor(QQuickItem *item, const QString &name)
266 {
267     if (!isValidAnchorName(name))
268         return false;
269
270     if (name == QLatin1String("anchors.fill"))
271         return anchors(item)->fill() != 0;
272
273     if (name == QLatin1String("anchors.centerIn"))
274         return anchors(item)->centerIn() != 0;
275
276     if (name == QLatin1String("anchors.right"))
277         return anchors(item)->right().item != 0;
278
279     if (name == QLatin1String("anchors.top"))
280         return anchors(item)->top().item != 0;
281
282     if (name == QLatin1String("anchors.left"))
283         return anchors(item)->left().item != 0;
284
285     if (name == QLatin1String("anchors.bottom"))
286         return anchors(item)->bottom().item != 0;
287
288     if (name == QLatin1String("anchors.horizontalCenter"))
289         return anchors(item)->horizontalCenter().item != 0;
290
291     if (name == QLatin1String("anchors.verticalCenter"))
292         return anchors(item)->verticalCenter().item != 0;
293
294     if (name == QLatin1String("anchors.baseline"))
295         return anchors(item)->baseline().item != 0;
296
297     return anchors(item)->usedAnchors().testFlag(anchorLineFlagForName(name));
298 }
299
300 QQuickItem *DesignerSupport::anchorFillTargetItem(QQuickItem *item)
301 {
302     return anchors(item)->fill();
303 }
304
305 QQuickItem *DesignerSupport::anchorCenterInTargetItem(QQuickItem *item)
306 {
307     return anchors(item)->centerIn();
308 }
309
310
311
312 QPair<QString, QObject*> DesignerSupport::anchorLineTarget(QQuickItem *item, const QString &name, QDeclarativeContext *context)
313 {
314     QObject *targetObject = 0;
315     QString targetName;
316
317     if (name == QLatin1String("anchors.fill")) {
318         targetObject = anchors(item)->fill();
319     } else if (name == QLatin1String("anchors.centerIn")) {
320         targetObject = anchors(item)->centerIn();
321     } else {
322         QDeclarativeProperty metaProperty(item, name, context);
323         if (!metaProperty.isValid())
324             return QPair<QString, QObject*>();
325
326         QQuickAnchorLine anchorLine = metaProperty.read().value<QQuickAnchorLine>();
327         if (anchorLine.anchorLine != QQuickAnchorLine::Invalid) {
328             targetObject = anchorLine.item;
329             targetName = propertyNameForAnchorLine(anchorLine.anchorLine);
330         }
331
332     }
333
334     return QPair<QString, QObject*>(targetName, targetObject);
335 }
336
337 void DesignerSupport::resetAnchor(QQuickItem *item, const QString &name)
338 {
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();
357     }
358 }
359
360 QList<QObject*> DesignerSupport::statesForItem(QQuickItem *item)
361 {
362     QList<QObject*> objectList;
363     QList<QDeclarativeState *> stateList = QQuickItemPrivate::get(item)->_states()->states();
364     qCopy(stateList.begin(), stateList.end(), objectList.begin());
365
366     return objectList;
367 }
368
369 bool DesignerSupport::isComponentComplete(QQuickItem *item)
370 {
371     return static_cast<QQuickItemPrivate*>(QQuickItemPrivate::get(item))->componentComplete;
372 }
373
374 int DesignerSupport::borderWidth(QQuickItem *item)
375 {
376     QQuickRectangle *rectangle = qobject_cast<QQuickRectangle*>(item);
377     if (rectangle)
378         return rectangle->border()->width();
379
380     return 0;
381 }
382
383 void DesignerSupport::refreshExpressions(QDeclarativeContext *context)
384 {
385     QDeclarativeContextPrivate::get(context)->data->refreshExpressions();
386 }
387
388 void DesignerSupport::setRootItem(QQuickView *view, QQuickItem *item)
389 {
390     QQuickViewPrivate::get(view)->setRootObject(item);
391 }
392
393 bool DesignerSupport::isValidWidth(QQuickItem *item)
394 {
395     return QQuickItemPrivate::get(item)->heightValid;
396 }
397
398 bool DesignerSupport::isValidHeight(QQuickItem *item)
399 {
400     return QQuickItemPrivate::get(item)->widthValid;
401 }
402
403 void DesignerSupport::updateDirtyNode(QQuickItem *item)
404 {
405     QQuickCanvasPrivate::get(item->canvas())->updateDirtyNode(item);
406 }
407
408 QT_END_NAMESPACE