1// Copyright (C) 2018 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include "qqmlpreviewservice.h"
5
6#include <QtCore/qpointer.h>
7#include <QtQml/qqmlengine.h>
8#include <QtQml/qqmlcomponent.h>
9#include <QtQuick/qquickwindow.h>
10#include <QtQuick/qquickitem.h>
11#include <QtGui/qguiapplication.h>
12
13#include <private/qquickpixmap_p.h>
14#include <private/qqmldebugconnector_p.h>
15#include <private/qversionedpacket_p.h>
16
17QT_BEGIN_NAMESPACE
18
19const QString QQmlPreviewServiceImpl::s_key = QStringLiteral("QmlPreview");
20using QQmlDebugPacket = QVersionedPacket<QQmlDebugConnector>;
21
22QQmlPreviewServiceImpl::QQmlPreviewServiceImpl(QObject *parent) :
23 QQmlDebugService(s_key, 1.0f, parent)
24{
25 m_loader.reset(other: new QQmlPreviewFileLoader(this));
26 connect(sender: this, signal: &QQmlPreviewServiceImpl::load,
27 context: m_loader.data(), slot: &QQmlPreviewFileLoader::whitelist, type: Qt::DirectConnection);
28 connect(sender: this, signal: &QQmlPreviewServiceImpl::load, context: &m_handler, slot: &QQmlPreviewHandler::loadUrl);
29 connect(sender: this, signal: &QQmlPreviewServiceImpl::rerun, context: &m_handler, slot: &QQmlPreviewHandler::rerun);
30 connect(sender: this, signal: &QQmlPreviewServiceImpl::zoom, context: &m_handler, slot: &QQmlPreviewHandler::zoom);
31 connect(sender: &m_handler, signal: &QQmlPreviewHandler::error, context: this, slot: &QQmlPreviewServiceImpl::forwardError,
32 type: Qt::DirectConnection);
33 connect(sender: &m_handler, signal: &QQmlPreviewHandler::fps, context: this, slot: &QQmlPreviewServiceImpl::forwardFps,
34 type: Qt::DirectConnection);
35}
36
37QQmlPreviewServiceImpl::~QQmlPreviewServiceImpl()
38{
39}
40
41void QQmlPreviewServiceImpl::messageReceived(const QByteArray &data)
42{
43 QQmlDebugPacket packet(data);
44 qint8 command;
45
46 packet >> command;
47 switch (command) {
48 case File: {
49 QString path;
50 QByteArray contents;
51 packet >> path >> contents;
52 emit file(file: path, contents);
53
54 // Replace the whole scene with the first file successfully loaded over the debug
55 // connection. This is an OK approximation of the root component, and if the client wants
56 // something specific, it will send an explicit Load anyway.
57 if (m_currentUrl.isEmpty() && path.endsWith(s: ".qml")) {
58 if (path.startsWith(c: ':'))
59 m_currentUrl = QUrl("qrc" + path);
60 else
61 m_currentUrl = QUrl::fromLocalFile(localfile: path);
62 emit load(url: m_currentUrl);
63 }
64 break;
65 }
66 case Directory: {
67 QString path;
68 QStringList entries;
69 packet >> path >> entries;
70 emit directory(file: path, entries);
71 break;
72 }
73 case Load: {
74 QUrl url;
75 packet >> url;
76 if (url.isEmpty())
77 url = m_currentUrl;
78 else
79 m_currentUrl = url;
80 emit load(url);
81 break;
82 }
83 case Error: {
84 QString file;
85 packet >> file;
86 emit error(file);
87 break;
88 }
89 case Rerun:
90 emit rerun();
91 break;
92 case ClearCache:
93 emit clearCache();
94 break;
95 case Zoom: {
96 float factor;
97 packet >> factor;
98 emit zoom(factor: static_cast<qreal>(factor));
99 break;
100 }
101 default:
102 forwardError(error: QString::fromLatin1(ba: "Invalid command: %1").arg(a: command));
103 break;
104 }
105}
106
107void QQmlPreviewServiceImpl::engineAboutToBeAdded(QJSEngine *engine)
108{
109 if (QQmlEngine *qmlEngine = qobject_cast<QQmlEngine *>(object: engine))
110 m_handler.addEngine(engine: qmlEngine);
111 emit attachedToEngine(engine);
112}
113
114void QQmlPreviewServiceImpl::engineAboutToBeRemoved(QJSEngine *engine)
115{
116 if (QQmlEngine *qmlEngine = qobject_cast<QQmlEngine *>(object: engine))
117 m_handler.removeEngine(engine: qmlEngine);
118 emit detachedFromEngine(engine);
119}
120
121void QQmlPreviewServiceImpl::stateChanged(QQmlDebugService::State state)
122{
123 if (state == Enabled) {
124 QV4::ExecutionEngine::setPreviewing(true);
125 m_fileEngine.reset(other: new QQmlPreviewFileEngineHandler(m_loader.data()));
126 } else {
127 QV4::ExecutionEngine::setPreviewing(false);
128 m_fileEngine.reset();
129 }
130}
131
132void QQmlPreviewServiceImpl::forwardRequest(const QString &file)
133{
134 QQmlDebugPacket packet;
135 packet << static_cast<qint8>(Request) << file;
136 emit messageToClient(name: name(), message: packet.data());
137}
138
139void QQmlPreviewServiceImpl::forwardError(const QString &error)
140{
141 QQmlDebugPacket packet;
142 packet << static_cast<qint8>(Error) << error;
143 emit messageToClient(name: name(), message: packet.data());
144}
145
146void QQmlPreviewServiceImpl::forwardFps(const QQmlPreviewHandler::FpsInfo &frames)
147{
148 QQmlDebugPacket packet;
149 packet << static_cast<qint8>(Fps)
150 << frames.numSyncs << frames.minSync << frames.maxSync << frames.totalSync
151 << frames.numRenders << frames.minRender << frames.maxRender << frames.totalRender;
152 emit messageToClient(name: name(), message: packet.data());
153}
154
155QQuickItem *QQmlPreviewServiceImpl::currentRootItem()
156{
157 return m_handler.currentRootItem();
158}
159
160QT_END_NAMESPACE
161
162#include "moc_qqmlpreviewservice.cpp"
163

Provided by KDAB

Privacy Policy
Learn Advanced QML with KDAB
Find out more

source code of qtdeclarative/src/plugins/qmltooling/qmldbg_preview/qqmlpreviewservice.cpp