Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qqmlpreviewclient.cpp
Go to the documentation of this file.
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// Qt-Security score:significant
4
5
7#include <private/qpacket_p.h>
8
9#include <QtCore/qurl.h>
10#include <QtCore/qfile.h>
11#include <QtCore/qfileinfo.h>
12#include <QtCore/qdir.h>
13#include <QtQml/qqmlfile.h>
14
16
17QQmlPreviewClient::QQmlPreviewClient(QQmlDebugConnection *connection)
18 : QQmlDebugClient(*(new QQmlPreviewClientPrivate(connection)))
19{
20 Q_D(QQmlPreviewClient);
21 connect(&d->replayClient, &QQmlDebugClient::stateChanged, this,
22 [this](State replayClientState) {
23 if (replayClientState == Enabled)
24 configureEventReplay();
25 });
26}
27
28void QQmlPreviewClient::messageReceived(const QByteArray &message)
29{
30 QPacket packet(connection()->currentDataStreamVersion(), message);
31
32 qint8 command;
33 packet >> command;
34
35 switch (command) {
36 case Error: {
37 QString seviceError;
38 packet >> seviceError;
39 emit error(seviceError);
40 break;
41 }
42 case Request: {
43 QString fileName;
44 packet >> fileName;
45 emit request(fileName);
46 break;
47 }
48 case Fps: {
49 FpsInfo info;
50 packet >> info.numSyncs >> info.minSync >> info.maxSync >> info.totalSync
51 >> info.numRenders >> info.minRender >> info.maxRender >> info.totalRender;
52 emit fps(info);
53 break;
54 }
55 case Confirmation: {
56 Settings settings;
57 packet >> settings.enableInPlaceUpdates;
58 emit confirmation(settings);
59 break;
60 }
61 case HotReloadFailure: {
62 QString reason;
63 packet >> reason;
64 emit hotReloadFailure(reason);
65 break;
66 }
67 default:
68 emit error(QString::fromLatin1("Unknown command received: %1").arg(command));
69 break;
70 }
71}
72
73void QQmlPreviewClient::sendDirectory(const QString &path, const QStringList &entries)
74{
75 QPacket packet(connection()->currentDataStreamVersion());
76 packet << static_cast<qint8>(Directory) << path << entries;
77 sendMessage(packet.data());
78}
79
80void QQmlPreviewClient::sendFile(const QString &path, const QByteArray &contents)
81{
82 QPacket packet(connection()->currentDataStreamVersion());
83 packet << static_cast<qint8>(File) << path << contents;
84 sendMessage(packet.data());
85}
86
87void QQmlPreviewClient::sendError(const QString &path)
88{
89 QPacket packet(connection()->currentDataStreamVersion());
90 packet << static_cast<qint8>(Error) << path;
91 sendMessage(packet.data());
92}
93
95{
96 QPacket packet(connection()->currentDataStreamVersion());
97 packet << static_cast<qint8>(Configuration) << config.enableInPlaceUpdates;
98 sendMessage(packet.data());
99}
100
101void QQmlPreviewClient::triggerLoad(const QUrl &url)
102{
103 QPacket packet(connection()->currentDataStreamVersion());
104 packet << static_cast<qint8>(Load) << url;
105 sendMessage(packet.data());
106}
107
109{
110 QPacket packet(connection()->currentDataStreamVersion());
111 packet << static_cast<qint8>(Rerun);
112 sendMessage(packet.data());
113}
114
116{
117 QPacket packet(connection()->currentDataStreamVersion());
118 packet << static_cast<qint8>(Zoom) << factor;
119 sendMessage(packet.data());
120}
121
123{
124 QPacket packet(connection()->currentDataStreamVersion());
125 packet << static_cast<qint8>(AnimationSpeed) << factor;
126 sendMessage(packet.data());
127}
128
129void QQmlPreviewClient::configureEventReplay()
130{
131 Q_D(QQmlPreviewClient);
132
133 Q_ASSERT(connection());
134 Q_ASSERT(d->replayClient.state() == Enabled);
135
136 d->recordClient.setFlushInterval(1);
137 d->recordClient.setRecording(true);
138 d->replayTimer.setInterval(100);
139 connect(&d->replayTimer, &QTimer::timeout, this, [this, d]() {
140 if (d->eventReceiver.numLoadedEvents() < d->m_numExpectedEvents)
141 return;
143 d->replayTimer.stop();
144 });
145}
146
148{
149 Q_D(QQmlPreviewClient);
150
151 const auto events = d->eventReceiver.events();
152 if (events.isEmpty() || d->replayClient.state() != Enabled) {
153 d->eventReceiver.clear();
154 return;
155 }
156
157 const auto types = d->eventReceiver.eventTypes();
158
159 // The replayed events will be recorded again as they are processed. Remember
160 // how many we expect so that replayTimer can restore the animation speed
161 // once they have all arrived.
162 d->m_numExpectedEvents = events.size();
163
165 qint64 timestamp = 0;
166 for (QQmlProfilerEvent event : events) {
167 // Compress the timestamps so that the events are processed in quick succession.
168 event.setTimestamp(++timestamp);
169 d->replayClient.sendEvent(types[event.typeIndex()], std::move(event));
170 }
171
172 d->eventReceiver.clear();
173 d->replayTimer.start();
174}
175
176void QQmlPreviewClient::replayEvent(const QQmlProfilerEventType &type,
177 QQmlProfilerEvent &&event)
178{
179 Q_D(QQmlPreviewClient);
180 d->replayClient.sendEvent(type, std::move(event));
181}
182
183bool QQmlPreviewClient::saveEvents(const QString &fileName)
184{
185 Q_D(QQmlPreviewClient);
186 return d->eventReceiver.save(fileName);
187}
188
189bool QQmlPreviewClient::replayEventsFromFile(const QString &fileName)
190{
191 Q_D(QQmlPreviewClient);
192 if (d->replayClient.state() != Enabled)
193 return false;
194
196 qsizetype numEvents = 0;
197 if (d->replayClient.loadEvents(
198 fileName, [&](const QQmlProfilerEventType &type, QQmlProfilerEvent &&event) {
199 // Compress the timestamps so that the events are processed in quick succession.
200 event.setTimestamp(++numEvents);
201 d->replayClient.sendEvent(type, std::move(event));
202 })) {
203
204 d->eventReceiver.clear();
205 d->m_numExpectedEvents = numEvents;
206 d->replayTimer.start();
207 return true;
208 }
209
211 return false;
212}
213
215{
216 Q_D(const QQmlPreviewClient);
217 return d->eventReceiver.numLoadedEvents() > 0;
218}
219
221{
222 Q_D(QQmlPreviewClient);
223 d->eventReceiver.clear();
224}
225
226QT_END_NAMESPACE
227
228#include "moc_qqmlpreviewclient_p.cpp"
void messageReceived(const QByteArray &message) override
void triggerZoom(float factor)
void replayEvent(const QQmlProfilerEventType &type, QQmlProfilerEvent &&event)
bool replayEventsFromFile(const QString &fileName)
bool hasRecordedEvents() const
void triggerAnimationSpeed(float factor)
bool saveEvents(const QString &fileName)
void sendFile(const QString &path, const QByteArray &contents)
void sendError(const QString &path)
void sendDirectory(const QString &path, const QStringList &entries)
void sendConfiguration(const Settings &settings)
void triggerLoad(const QUrl &url)
Combined button and popup list for selecting options.