9753608cb3003c7c419c88042ffefd8c2d275ced
[profile/ivi/qtdeclarative.git] / src / plugins / qmltooling / shared / abstractviewinspector.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 "abstractviewinspector.h"
43
44 #include "abstracttool.h"
45 #include "qdeclarativeinspectorprotocol.h"
46
47 #include <QtDeclarative/QDeclarativeEngine>
48 #include <QtDeclarative/QDeclarativeComponent>
49 #include <QtCore/private/qabstractanimation_p.h>
50 #include <QtDeclarative/private/qdeclarativeinspectorservice_p.h>
51
52 #include <QtGui/QMouseEvent>
53
54 namespace QmlJSDebugger {
55
56
57 AbstractViewInspector::AbstractViewInspector(QObject *parent) :
58     QObject(parent),
59     m_currentTool(0),
60     m_showAppOnTop(false),
61     m_designModeBehavior(false),
62     m_animationPaused(false),
63     m_slowDownFactor(1.0),
64     m_debugService(QDeclarativeInspectorService::instance())
65 {
66 }
67
68 void AbstractViewInspector::createQmlObject(const QString &qml, QObject *parent,
69                                             const QStringList &importList,
70                                             const QString &filename)
71 {
72     if (!parent)
73         return;
74
75     QString imports;
76     foreach (const QString &s, importList) {
77         imports += s;
78         imports += QLatin1Char('\n');
79     }
80
81     QDeclarativeContext *parentContext = declarativeEngine()->contextForObject(parent);
82     QDeclarativeComponent component(declarativeEngine());
83     QByteArray constructedQml = QString(imports + qml).toLatin1();
84
85     component.setData(constructedQml, QUrl::fromLocalFile(filename));
86     QObject *newObject = component.create(parentContext);
87     if (newObject)
88         reparentQmlObject(newObject, parent);
89 }
90
91 void AbstractViewInspector::clearComponentCache()
92 {
93     declarativeEngine()->clearComponentCache();
94 }
95
96 void AbstractViewInspector::setDesignModeBehavior(bool value)
97 {
98     if (m_designModeBehavior == value)
99         return;
100
101     m_designModeBehavior = value;
102     emit designModeBehaviorChanged(value);
103     sendDesignModeBehavior(value);
104 }
105
106 void AbstractViewInspector::setAnimationSpeed(qreal slowDownFactor)
107 {
108     Q_ASSERT(slowDownFactor > 0);
109     if (m_slowDownFactor == slowDownFactor)
110         return;
111
112     animationSpeedChangeRequested(slowDownFactor);
113     sendAnimationSpeed(slowDownFactor);
114 }
115
116 void AbstractViewInspector::setAnimationPaused(bool paused)
117 {
118     if (m_animationPaused == paused)
119         return;
120
121     animationPausedChangeRequested(paused);
122     sendAnimationPaused(paused);
123 }
124
125 void AbstractViewInspector::animationSpeedChangeRequested(qreal factor)
126 {
127     if (m_slowDownFactor != factor) {
128         m_slowDownFactor = factor;
129         emit animationSpeedChanged(factor);
130     }
131
132     const float effectiveFactor = m_animationPaused ? 0 : factor;
133     QUnifiedTimer::instance()->setSlowModeEnabled(effectiveFactor != 1.0);
134     QUnifiedTimer::instance()->setSlowdownFactor(effectiveFactor);
135 }
136
137 void AbstractViewInspector::animationPausedChangeRequested(bool paused)
138 {
139     if (m_animationPaused != paused) {
140         m_animationPaused = paused;
141         emit animationPausedChanged(paused);
142     }
143
144     const float effectiveFactor = paused ? 0 : m_slowDownFactor;
145     QUnifiedTimer::instance()->setSlowModeEnabled(effectiveFactor != 1.0);
146     QUnifiedTimer::instance()->setSlowdownFactor(effectiveFactor);
147 }
148
149 void AbstractViewInspector::setShowAppOnTop(bool appOnTop)
150 {
151     Qt::WindowFlags flags = windowFlags();
152     if (appOnTop)
153         flags |= Qt::WindowStaysOnTopHint;
154     else
155         flags &= ~Qt::WindowStaysOnTopHint;
156
157     setWindowFlags(flags);
158
159     m_showAppOnTop = appOnTop;
160     sendShowAppOnTop(appOnTop);
161
162     emit showAppOnTopChanged(appOnTop);
163 }
164
165 void AbstractViewInspector::changeToColorPickerTool()
166 {
167     changeTool(InspectorProtocol::ColorPickerTool);
168 }
169
170 void AbstractViewInspector::changeToZoomTool()
171 {
172     changeTool(InspectorProtocol::ZoomTool);
173 }
174
175 void AbstractViewInspector::changeToSingleSelectTool()
176 {
177     changeTool(InspectorProtocol::SelectTool);
178 }
179
180 void AbstractViewInspector::changeToMarqueeSelectTool()
181 {
182     changeTool(InspectorProtocol::SelectMarqueeTool);
183 }
184
185 bool AbstractViewInspector::eventFilter(QObject *obj, QEvent *event)
186 {
187     if (!designModeBehavior())
188         return QObject::eventFilter(obj, event);
189
190     switch (event->type()) {
191     case QEvent::Leave:
192         if (leaveEvent(event))
193             return true;
194         break;
195     case QEvent::MouseButtonPress:
196         if (mousePressEvent(static_cast<QMouseEvent*>(event)))
197             return true;
198         break;
199     case QEvent::MouseMove:
200         if (mouseMoveEvent(static_cast<QMouseEvent*>(event)))
201             return true;
202         break;
203     case QEvent::MouseButtonRelease:
204         if (mouseReleaseEvent(static_cast<QMouseEvent*>(event)))
205             return true;
206         break;
207     case QEvent::KeyPress:
208         if (keyPressEvent(static_cast<QKeyEvent*>(event)))
209             return true;
210         break;
211     case QEvent::KeyRelease:
212         if (keyReleaseEvent(static_cast<QKeyEvent*>(event)))
213             return true;
214         break;
215     case QEvent::MouseButtonDblClick:
216         if (mouseDoubleClickEvent(static_cast<QMouseEvent*>(event)))
217             return true;
218         break;
219     case QEvent::Wheel:
220         if (wheelEvent(static_cast<QWheelEvent*>(event)))
221             return true;
222         break;
223     default:
224         break;
225     }
226
227     return QObject::eventFilter(obj, event);
228 }
229
230 bool AbstractViewInspector::leaveEvent(QEvent *event)
231 {
232     m_currentTool->leaveEvent(event);
233     return true;
234 }
235
236 bool AbstractViewInspector::mousePressEvent(QMouseEvent *event)
237 {
238     m_currentTool->mousePressEvent(event);
239     return true;
240 }
241
242 bool AbstractViewInspector::mouseMoveEvent(QMouseEvent *event)
243 {
244     if (event->buttons()) {
245         m_currentTool->mouseMoveEvent(event);
246     } else {
247         m_currentTool->hoverMoveEvent(event);
248     }
249     return true;
250 }
251
252 bool AbstractViewInspector::mouseReleaseEvent(QMouseEvent *event)
253 {
254     m_currentTool->mouseReleaseEvent(event);
255     return true;
256 }
257
258 bool AbstractViewInspector::keyPressEvent(QKeyEvent *event)
259 {
260     m_currentTool->keyPressEvent(event);
261     return true;
262 }
263
264 bool AbstractViewInspector::keyReleaseEvent(QKeyEvent *event)
265 {
266     switch (event->key()) {
267     case Qt::Key_V:
268         changeTool(InspectorProtocol::SelectTool);
269         break;
270 // disabled because multiselection does not do anything useful without design mode
271 //    case Qt::Key_M:
272 //        changeTool(InspectorProtocol::SelectMarqueeTool);
273 //        break;
274     case Qt::Key_I:
275         changeTool(InspectorProtocol::ColorPickerTool);
276         break;
277     case Qt::Key_Z:
278         changeTool(InspectorProtocol::ZoomTool);
279         break;
280     case Qt::Key_Space:
281         setAnimationPaused(!animationPaused());
282         break;
283     default:
284         break;
285     }
286
287     m_currentTool->keyReleaseEvent(event);
288     return true;
289 }
290
291 bool AbstractViewInspector::mouseDoubleClickEvent(QMouseEvent *event)
292 {
293     m_currentTool->mouseDoubleClickEvent(event);
294     return true;
295 }
296
297 bool AbstractViewInspector::wheelEvent(QWheelEvent *event)
298 {
299     m_currentTool->wheelEvent(event);
300     return true;
301 }
302
303 void AbstractViewInspector::handleMessage(const QByteArray &message)
304 {
305     QDataStream ds(message);
306
307     InspectorProtocol::Message type;
308     ds >> type;
309
310     switch (type) {
311     case InspectorProtocol::SetCurrentObjects: {
312         int itemCount = 0;
313         ds >> itemCount;
314
315         QList<QObject*> selectedObjects;
316         for (int i = 0; i < itemCount; ++i) {
317             int debugId = -1;
318             ds >> debugId;
319             if (QObject *obj = QDeclarativeDebugService::objectForId(debugId))
320                 selectedObjects << obj;
321         }
322
323         changeCurrentObjects(selectedObjects);
324         break;
325     }
326     case InspectorProtocol::Reload: {
327         reloadView();
328         break;
329     }
330     case InspectorProtocol::SetAnimationSpeed: {
331         qreal speed;
332         ds >> speed;
333         animationSpeedChangeRequested(speed);
334         break;
335     }
336     case InspectorProtocol::SetAnimationPaused: {
337         bool paused;
338         ds >> paused;
339         animationPausedChangeRequested(paused);
340         break;
341     }
342     case InspectorProtocol::ChangeTool: {
343         InspectorProtocol::Tool tool;
344         ds >> tool;
345         changeTool(tool);
346         break;
347     }
348     case InspectorProtocol::SetDesignMode: {
349         bool inDesignMode;
350         ds >> inDesignMode;
351         setDesignModeBehavior(inDesignMode);
352         break;
353     }
354     case InspectorProtocol::ShowAppOnTop: {
355         bool showOnTop;
356         ds >> showOnTop;
357         setShowAppOnTop(showOnTop);
358         break;
359     }
360     case InspectorProtocol::CreateObject: {
361         QString qml;
362         int parentId;
363         QString filename;
364         QStringList imports;
365         ds >> qml >> parentId >> imports >> filename;
366         createQmlObject(qml, QDeclarativeDebugService::objectForId(parentId),
367                         imports, filename);
368         break;
369     }
370     case InspectorProtocol::DestroyObject: {
371         int debugId;
372         ds >> debugId;
373         if (QObject *obj = QDeclarativeDebugService::objectForId(debugId))
374             obj->deleteLater();
375         break;
376     }
377     case InspectorProtocol::MoveObject: {
378         int debugId, newParent;
379         ds >> debugId >> newParent;
380         reparentQmlObject(QDeclarativeDebugService::objectForId(debugId),
381                           QDeclarativeDebugService::objectForId(newParent));
382         break;
383     }
384     case InspectorProtocol::ObjectIdList: {
385         int itemCount;
386         ds >> itemCount;
387         m_stringIdForObjectId.clear();
388         for (int i = 0; i < itemCount; ++i) {
389             int itemDebugId;
390             QString itemIdString;
391             ds >> itemDebugId
392                >> itemIdString;
393
394             m_stringIdForObjectId.insert(itemDebugId, itemIdString);
395         }
396         break;
397     }
398     case InspectorProtocol::ClearComponentCache: {
399         clearComponentCache();
400         break;
401     }
402     default:
403         qWarning() << "Warning: Not handling message:" << type;
404     }
405 }
406
407 void AbstractViewInspector::sendDesignModeBehavior(bool inDesignMode)
408 {
409     QByteArray message;
410     QDataStream ds(&message, QIODevice::WriteOnly);
411
412     ds << InspectorProtocol::SetDesignMode
413        << inDesignMode;
414
415     m_debugService->sendMessage(message);
416 }
417
418 void AbstractViewInspector::sendCurrentObjects(const QList<QObject*> &objects)
419 {
420     QByteArray message;
421     QDataStream ds(&message, QIODevice::WriteOnly);
422
423     ds << InspectorProtocol::CurrentObjectsChanged
424        << objects.length();
425
426     foreach (QObject *object, objects) {
427         int id = QDeclarativeDebugService::idForObject(object);
428         ds << id;
429     }
430
431     m_debugService->sendMessage(message);
432 }
433
434 void AbstractViewInspector::sendCurrentTool(Constants::DesignTool toolId)
435 {
436     QByteArray message;
437     QDataStream ds(&message, QIODevice::WriteOnly);
438
439     ds << InspectorProtocol::ToolChanged
440        << toolId;
441
442     m_debugService->sendMessage(message);
443 }
444
445 void AbstractViewInspector::sendAnimationSpeed(qreal slowDownFactor)
446 {
447     QByteArray message;
448     QDataStream ds(&message, QIODevice::WriteOnly);
449
450     ds << InspectorProtocol::AnimationSpeedChanged
451        << slowDownFactor;
452
453     m_debugService->sendMessage(message);
454 }
455
456 void AbstractViewInspector::sendAnimationPaused(bool paused)
457 {
458     QByteArray message;
459     QDataStream ds(&message, QIODevice::WriteOnly);
460
461     ds << InspectorProtocol::AnimationPausedChanged
462        << paused;
463
464     m_debugService->sendMessage(message);
465 }
466
467 void AbstractViewInspector::sendReloaded()
468 {
469     QByteArray message;
470     QDataStream ds(&message, QIODevice::WriteOnly);
471
472     ds << InspectorProtocol::Reloaded;
473
474     m_debugService->sendMessage(message);
475 }
476
477 void AbstractViewInspector::sendShowAppOnTop(bool showAppOnTop)
478 {
479     QByteArray message;
480     QDataStream ds(&message, QIODevice::WriteOnly);
481
482     ds << InspectorProtocol::ShowAppOnTop << showAppOnTop;
483
484     m_debugService->sendMessage(message);
485 }
486
487 void AbstractViewInspector::sendColorChanged(const QColor &color)
488 {
489     QByteArray message;
490     QDataStream ds(&message, QIODevice::WriteOnly);
491
492     ds << InspectorProtocol::ColorChanged
493        << color;
494
495     m_debugService->sendMessage(message);
496 }
497
498 QString AbstractViewInspector::idStringForObject(QObject *obj) const
499 {
500     const int id = QDeclarativeDebugService::idForObject(obj);
501     return m_stringIdForObjectId.value(id);
502 }
503
504 } // namespace QmlJSDebugger