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 connect(sender: this, signal: &QQmlPreviewServiceImpl::load, context: &m_handler, slot: &QQmlPreviewHandler::loadUrl);
26 connect(sender: this, signal: &QQmlPreviewServiceImpl::rerun, context: &m_handler, slot: &QQmlPreviewHandler::rerun);
27 connect(sender: this, signal: &QQmlPreviewServiceImpl::zoom, context: &m_handler, slot: &QQmlPreviewHandler::zoom);
28 connect(sender: &m_handler, signal: &QQmlPreviewHandler::error, context: this, slot: &QQmlPreviewServiceImpl::forwardError,
29 type: Qt::DirectConnection);
30 connect(sender: &m_handler, signal: &QQmlPreviewHandler::fps, context: this, slot: &QQmlPreviewServiceImpl::forwardFps,
31 type: Qt::DirectConnection);
32}
33
34QQmlPreviewServiceImpl::~QQmlPreviewServiceImpl()
35{
36}
37
38void QQmlPreviewServiceImpl::messageReceived(const QByteArray &data)
39{
40 QQmlDebugPacket packet(data);
41 qint8 command;
42
43 packet >> command;
44 switch (command) {
45 case File: {
46 QString path;
47 QByteArray contents;
48 packet >> path >> contents;
49 emit file(file: path, contents);
50
51 // Replace the whole scene with the first file successfully loaded over the debug
52 // connection. This is an OK approximation of the root component, and if the client wants
53 // something specific, it will send an explicit Load anyway.
54 if (m_currentUrl.isEmpty() && path.endsWith(s: ".qml")) {
55 if (path.startsWith(c: ':'))
56 m_currentUrl = QUrl("qrc" + path);
57 else
58 m_currentUrl = QUrl::fromLocalFile(localfile: path);
59 emit load(url: m_currentUrl);
60 }
61 break;
62 }
63 case Directory: {
64 QString path;
65 QStringList entries;
66 packet >> path >> entries;
67 emit directory(file: path, entries);
68 break;
69 }
70 case Load: {
71 QUrl url;
72 packet >> url;
73 if (url.isEmpty())
74 url = m_currentUrl;
75 else
76 m_currentUrl = url;
77 emit load(url);
78 break;
79 }
80 case Error: {
81 QString file;
82 packet >> file;
83 emit error(file);
84 break;
85 }
86 case Rerun:
87 emit rerun();
88 break;
89 case ClearCache:
90 emit clearCache();
91 break;
92 case Zoom: {
93 float factor;
94 packet >> factor;
95 emit zoom(factor: static_cast<qreal>(factor));
96 break;
97 }
98 default:
99 forwardError(error: QString::fromLatin1(ba: "Invalid command: %1").arg(a: command));
100 break;
101 }
102}
103
104void QQmlPreviewServiceImpl::engineAboutToBeAdded(QJSEngine *engine)
105{
106 if (QQmlEngine *qmlEngine = qobject_cast<QQmlEngine *>(object: engine))
107 m_handler.addEngine(engine: qmlEngine);
108 emit attachedToEngine(engine);
109}
110
111void QQmlPreviewServiceImpl::engineAboutToBeRemoved(QJSEngine *engine)
112{
113 if (QQmlEngine *qmlEngine = qobject_cast<QQmlEngine *>(object: engine))
114 m_handler.removeEngine(engine: qmlEngine);
115 emit detachedFromEngine(engine);
116}
117
118void QQmlPreviewServiceImpl::stateChanged(QQmlDebugService::State state)
119{
120 if (state == Enabled) {
121 m_loader.reset(other: new QQmlPreviewFileLoader(this));
122 connect(sender: this, signal: &QQmlPreviewServiceImpl::load,
123 context: m_loader.data(), slot: &QQmlPreviewFileLoader::whitelist, type: Qt::DirectConnection);
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 m_loader.reset();
130 }
131}
132
133void QQmlPreviewServiceImpl::forwardRequest(const QString &file)
134{
135 QQmlDebugPacket packet;
136 packet << static_cast<qint8>(Request) << file;
137 emit messageToClient(name: name(), message: packet.data());
138}
139
140void QQmlPreviewServiceImpl::forwardError(const QString &error)
141{
142 QQmlDebugPacket packet;
143 packet << static_cast<qint8>(Error) << error;
144 emit messageToClient(name: name(), message: packet.data());
145}
146
147void QQmlPreviewServiceImpl::forwardFps(const QQmlPreviewHandler::FpsInfo &frames)
148{
149 QQmlDebugPacket packet;
150 packet << static_cast<qint8>(Fps)
151 << frames.numSyncs << frames.minSync << frames.maxSync << frames.totalSync
152 << frames.numRenders << frames.minRender << frames.maxRender << frames.totalRender;
153 emit messageToClient(name: name(), message: packet.data());
154}
155
156QQuickItem *QQmlPreviewServiceImpl::currentRootItem()
157{
158 return m_handler.currentRootItem();
159}
160
161QT_END_NAMESPACE
162
163#include "moc_qqmlpreviewservice.cpp"
164

Provided by KDAB

Privacy Policy
Start learning QML with our Intro Training
Find out more

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