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