Compile without RTTI support
[profile/ivi/qtdeclarative.git] / src / quick / designer / designersupport.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
5 **
6 ** This file is part of the QtQml module of the Qt Toolkit.
7 **
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.
16 **
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.
20 **
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.
28 **
29 ** Other Usage
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.
32 **
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/qqmlengine_p.h>
48 #include <private/qquickview_p.h>
49 #include <QtQuick/private/qquickstategroup_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 #ifndef QT_NO_DYNAMIC_CAST
203     Q_ASSERT(dynamic_cast<QQuickItemPrivate*>(QQuickItemPrivate::get(fromItem)));
204 #endif
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;
216 }
217
218 bool DesignerSupport::areChildrenAnchoredTo(QQuickItem *fromItem, QQuickItem *toItem)
219 {
220     foreach (QQuickItem *childItem, fromItem->childItems()) {
221         if (childItem) {
222             if (isAnchoredTo(childItem, toItem))
223                 return true;
224
225             if (areChildrenAnchoredTo(childItem, toItem))
226                 return true;
227         }
228     }
229
230     return false;
231 }
232
233 QQuickAnchors *anchors(QQuickItem *item)
234 {
235     QQuickItemPrivate *itemPrivate = static_cast<QQuickItemPrivate*>(QQuickItemPrivate::get(item));
236     return itemPrivate->anchors();
237 }
238
239 QQuickAnchors::Anchor anchorLineFlagForName(const QString &name)
240 {
241     if (name == QLatin1String("anchors.top"))
242         return QQuickAnchors::TopAnchor;
243
244     if (name == QLatin1String("anchors.left"))
245         return QQuickAnchors::LeftAnchor;
246
247     if (name == QLatin1String("anchors.bottom"))
248          return QQuickAnchors::BottomAnchor;
249
250     if (name == QLatin1String("anchors.right"))
251         return QQuickAnchors::RightAnchor;
252
253     if (name == QLatin1String("anchors.horizontalCenter"))
254         return QQuickAnchors::HCenterAnchor;
255
256     if (name == QLatin1String("anchors.verticalCenter"))
257          return QQuickAnchors::VCenterAnchor;
258
259     if (name == QLatin1String("anchors.baseline"))
260          return QQuickAnchors::BaselineAnchor;
261
262
263     Q_ASSERT_X(false, Q_FUNC_INFO, "wrong anchor name - this should never happen");
264     return QQuickAnchors::LeftAnchor;
265 }
266
267 bool DesignerSupport::hasAnchor(QQuickItem *item, const QString &name)
268 {
269     if (!isValidAnchorName(name))
270         return false;
271
272     if (name == QLatin1String("anchors.fill"))
273         return anchors(item)->fill() != 0;
274
275     if (name == QLatin1String("anchors.centerIn"))
276         return anchors(item)->centerIn() != 0;
277
278     if (name == QLatin1String("anchors.right"))
279         return anchors(item)->right().item != 0;
280
281     if (name == QLatin1String("anchors.top"))
282         return anchors(item)->top().item != 0;
283
284     if (name == QLatin1String("anchors.left"))
285         return anchors(item)->left().item != 0;
286
287     if (name == QLatin1String("anchors.bottom"))
288         return anchors(item)->bottom().item != 0;
289
290     if (name == QLatin1String("anchors.horizontalCenter"))
291         return anchors(item)->horizontalCenter().item != 0;
292
293     if (name == QLatin1String("anchors.verticalCenter"))
294         return anchors(item)->verticalCenter().item != 0;
295
296     if (name == QLatin1String("anchors.baseline"))
297         return anchors(item)->baseline().item != 0;
298
299     return anchors(item)->usedAnchors().testFlag(anchorLineFlagForName(name));
300 }
301
302 QQuickItem *DesignerSupport::anchorFillTargetItem(QQuickItem *item)
303 {
304     return anchors(item)->fill();
305 }
306
307 QQuickItem *DesignerSupport::anchorCenterInTargetItem(QQuickItem *item)
308 {
309     return anchors(item)->centerIn();
310 }
311
312
313
314 QPair<QString, QObject*> DesignerSupport::anchorLineTarget(QQuickItem *item, const QString &name, QQmlContext *context)
315 {
316     QObject *targetObject = 0;
317     QString targetName;
318
319     if (name == QLatin1String("anchors.fill")) {
320         targetObject = anchors(item)->fill();
321     } else if (name == QLatin1String("anchors.centerIn")) {
322         targetObject = anchors(item)->centerIn();
323     } else {
324         QQmlProperty metaProperty(item, name, context);
325         if (!metaProperty.isValid())
326             return QPair<QString, QObject*>();
327
328         QQuickAnchorLine anchorLine = metaProperty.read().value<QQuickAnchorLine>();
329         if (anchorLine.anchorLine != QQuickAnchorLine::Invalid) {
330             targetObject = anchorLine.item;
331             targetName = propertyNameForAnchorLine(anchorLine.anchorLine);
332         }
333
334     }
335
336     return QPair<QString, QObject*>(targetName, targetObject);
337 }
338
339 void DesignerSupport::resetAnchor(QQuickItem *item, const QString &name)
340 {
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();
359     }
360 }
361
362 QList<QObject*> DesignerSupport::statesForItem(QQuickItem *item)
363 {
364     QList<QObject*> objectList;
365     QList<QQuickState *> stateList = QQuickItemPrivate::get(item)->_states()->states();
366     qCopy(stateList.begin(), stateList.end(), objectList.begin());
367
368     return objectList;
369 }
370
371 bool DesignerSupport::isComponentComplete(QQuickItem *item)
372 {
373     return static_cast<QQuickItemPrivate*>(QQuickItemPrivate::get(item))->componentComplete;
374 }
375
376 int DesignerSupport::borderWidth(QQuickItem *item)
377 {
378     QQuickRectangle *rectangle = qobject_cast<QQuickRectangle*>(item);
379     if (rectangle)
380         return rectangle->border()->width();
381
382     return 0;
383 }
384
385 void DesignerSupport::refreshExpressions(QQmlContext *context)
386 {
387     QQmlContextPrivate::get(context)->data->refreshExpressions();
388 }
389
390 void DesignerSupport::setRootItem(QQuickView *view, QQuickItem *item)
391 {
392     QQuickViewPrivate::get(view)->setRootObject(item);
393 }
394
395 bool DesignerSupport::isValidWidth(QQuickItem *item)
396 {
397     return QQuickItemPrivate::get(item)->heightValid;
398 }
399
400 bool DesignerSupport::isValidHeight(QQuickItem *item)
401 {
402     return QQuickItemPrivate::get(item)->widthValid;
403 }
404
405 void DesignerSupport::updateDirtyNode(QQuickItem *item)
406 {
407     QQuickCanvasPrivate::get(item->canvas())->updateDirtyNode(item);
408 }
409
410 QT_END_NAMESPACE