QmlProfiler: Move parts of model manager and trace file to Timeline

This way we can use the trace file loading and saving mechanism for
other profilers.

Change-Id: I98ec1cdde6f7abcea152cabf72e64d4e696dfa59
Reviewed-by: Tobias Hunger <tobias.hunger@qt.io>
This commit is contained in:
Ulf Hermann
2018-04-05 09:47:33 +02:00
parent 7099f21586
commit 1c2e0f387f
37 changed files with 1443 additions and 1001 deletions

View File

@@ -30,9 +30,9 @@
#include "qmlprofilerdetailsrewriter.h"
#include <coreplugin/progressmanager/progressmanager.h>
#include <timeline/tracestashfile.h>
#include <utils/runextensions.h>
#include <utils/qtcassert.h>
#include <utils/temporaryfile.h>
#include <QDebug>
#include <QFile>
@@ -43,7 +43,6 @@
#include <functional>
namespace QmlProfiler {
namespace Internal {
static const char *ProfileFeatureNames[] = {
QT_TRANSLATE_NOOP("MainView", "JavaScript"),
@@ -62,65 +61,44 @@ static const char *ProfileFeatureNames[] = {
Q_STATIC_ASSERT(sizeof(ProfileFeatureNames) == sizeof(char *) * MaximumProfileFeature);
} // namespace Internal
using namespace Internal;
class QmlProfilerModelManager::QmlProfilerModelManagerPrivate
{
public:
QmlProfilerModelManagerPrivate() : file("qmlprofiler-data") {}
QmlProfilerNotesModel *notesModel = nullptr;
QmlProfilerTextMarkModel *textMarkModel = nullptr;
QmlProfilerModelManager::State state = Empty;
int numFinishedFinalizers = 0;
int numLoadedEvents = 0;
quint64 availableFeatures = 0;
quint64 visibleFeatures = 0;
quint64 recordedFeatures = 0;
bool aggregateTraces = false;
QHash<ProfileFeature, QVector<EventLoader> > eventLoaders;
QVector<Finalizer> finalizers;
Internal::QmlProfilerTextMarkModel *textMarkModel = nullptr;
QVector<QmlEventType> eventTypes;
QmlProfilerDetailsRewriter *detailsRewriter = nullptr;
Internal::QmlProfilerDetailsRewriter *detailsRewriter = nullptr;
Utils::TemporaryFile file;
QDataStream eventStream;
Timeline::TraceStashFile<QmlEvent> file;
qint64 traceStart = -1;
qint64 traceEnd = -1;
qint64 restrictedTraceStart = -1;
qint64 restrictedTraceEnd = -1;
void writeToStream(const QmlEvent &event);
void addEventType(const QmlEventType &eventType);
void handleError(const QString &message);
void dispatch(const QmlEvent &event, const QmlEventType &type);
void rewriteType(int typeIndex);
int resolveStackTop();
void updateTraceTime(qint64 time);
void restrictTraceTimeToRange(qint64 start, qint64 end);
};
QmlProfilerModelManager::QmlProfilerModelManager(QObject *parent) :
QObject(parent), d(new QmlProfilerModelManagerPrivate)
Timeline::TimelineTraceManager(parent), d(new QmlProfilerModelManagerPrivate)
{
d->notesModel = new QmlProfilerNotesModel(this);
d->textMarkModel = new QmlProfilerTextMarkModel(this);
setNotesModel(new QmlProfilerNotesModel(this));
d->textMarkModel = new Internal::QmlProfilerTextMarkModel(this);
d->detailsRewriter = new QmlProfilerDetailsRewriter(this);
connect(d->detailsRewriter, &QmlProfilerDetailsRewriter::rewriteDetailsString,
this, &QmlProfilerModelManager::detailsChanged);
connect(d->detailsRewriter, &QmlProfilerDetailsRewriter::eventDetailsChanged,
d->detailsRewriter = new Internal::QmlProfilerDetailsRewriter(this);
connect(d->detailsRewriter, &Internal::QmlProfilerDetailsRewriter::rewriteDetailsString,
this, &QmlProfilerModelManager::typeDetailsChanged);
connect(d->detailsRewriter, &Internal::QmlProfilerDetailsRewriter::eventDetailsChanged,
this, &QmlProfilerModelManager::typeDetailsFinished);
if (d->file.open())
d->eventStream.setDevice(&d->file);
else
if (!d->file.open())
emit error(tr("Cannot open temporary trace file to store events."));
quint64 allFeatures = 0;
for (quint8 i = 0; i <= MaximumProfileFeature; ++i)
allFeatures |= (1ull << i);
}
QmlProfilerModelManager::~QmlProfilerModelManager()
@@ -128,123 +106,36 @@ QmlProfilerModelManager::~QmlProfilerModelManager()
delete d;
}
qint64 QmlProfilerModelManager::traceStart() const
{
return d->restrictedTraceStart != -1 ? d->restrictedTraceStart : d->traceStart;
}
qint64 QmlProfilerModelManager::traceEnd() const
{
return d->restrictedTraceEnd != -1 ? d->restrictedTraceEnd : d->traceEnd;
}
qint64 QmlProfilerModelManager::traceDuration() const
{
return traceEnd() - traceStart();
}
void QmlProfilerModelManager::decreaseTraceStart(qint64 start)
{
QTC_ASSERT(start >= 0, return);
if (d->traceStart > start || d->traceStart == -1) {
d->traceStart = start;
if (d->traceEnd == -1)
d->traceEnd = d->traceStart;
else
QTC_ASSERT(d->traceEnd >= d->traceStart, d->traceEnd = d->traceStart);
}
}
void QmlProfilerModelManager::increaseTraceEnd(qint64 end)
{
QTC_ASSERT(end >= 0, return);
if (d->traceEnd < end || d->traceEnd == -1) {
d->traceEnd = end;
if (d->traceStart == -1)
d->traceStart = d->traceEnd;
else
QTC_ASSERT(d->traceEnd >= d->traceStart, d->traceStart = d->traceEnd);
}
}
QmlProfilerNotesModel *QmlProfilerModelManager::notesModel() const
{
return d->notesModel;
}
QmlProfilerTextMarkModel *QmlProfilerModelManager::textMarkModel() const
Internal::QmlProfilerTextMarkModel *QmlProfilerModelManager::textMarkModel() const
{
return d->textMarkModel;
}
bool QmlProfilerModelManager::isEmpty() const
void QmlProfilerModelManager::registerFeatures(quint64 features, QmlEventLoader eventLoader,
Initializer initializer, Finalizer finalizer,
Clearer clearer)
{
return d->file.pos() == 0;
}
const TraceEventLoader traceEventLoader = eventLoader ? [eventLoader](
const Timeline::TraceEvent &event, const Timeline::TraceEventType &type) {
return eventLoader(static_cast<const QmlEvent &>(event),
static_cast<const QmlEventType &>(type));
} : TraceEventLoader();
int QmlProfilerModelManager::numEvents() const
{
return d->numLoadedEvents;
}
int QmlProfilerModelManager::numEventTypes() const
{
return d->eventTypes.count();
}
int QmlProfilerModelManager::numFinishedFinalizers() const
{
return d->numFinishedFinalizers;
}
int QmlProfilerModelManager::numRegisteredFinalizers() const
{
return d->finalizers.count();
Timeline::TimelineTraceManager::registerFeatures(features, traceEventLoader, initializer,
finalizer, clearer);
}
void QmlProfilerModelManager::addEvents(const QVector<QmlEvent> &events)
{
for (const QmlEvent &event : events) {
d->eventStream << event;
d->updateTraceTime(event.timestamp());
d->dispatch(event, d->eventTypes[event.typeIndex()]);
}
}
void QmlProfilerModelManager::addEvent(const QmlEvent &event)
{
d->eventStream << event;
d->updateTraceTime(event.timestamp());
QTC_ASSERT(event.typeIndex() < d->eventTypes.size(),
d->eventTypes.resize(event.typeIndex() + 1));
d->dispatch(event, d->eventTypes.at(event.typeIndex()));
for (const QmlEvent &event : events)
addEvent(event);
}
void QmlProfilerModelManager::addEventTypes(const QVector<QmlEventType> &types)
{
const int firstTypeId = d->eventTypes.length();;
d->eventTypes.append(types);
for (int typeId = firstTypeId, end = d->eventTypes.length(); typeId < end; ++typeId) {
d->rewriteType(typeId);
const QmlEventLocation &location = d->eventTypes[typeId].location();
if (location.isValid()) {
d->textMarkModel->addTextMarkId(typeId, QmlEventLocation(
findLocalFile(location.filename()), location.line(),
location.column()));
}
}
}
void QmlProfilerModelManager::addEventType(const QmlEventType &type)
{
const int typeId = d->eventTypes.count();
d->eventTypes.append(type);
d->rewriteType(typeId);
const QmlEventLocation &location = type.location();
if (location.isValid()) {
d->textMarkModel->addTextMarkId(
typeId, QmlEventLocation(findLocalFile(location.filename()),
location.line(), location.column()));
for (const QmlEventType &type : types) {
d->addEventType(type);
TimelineTraceManager::addEventType(type);
}
}
@@ -253,6 +144,15 @@ const QmlEventType &QmlProfilerModelManager::eventType(int typeId) const
return d->eventTypes.at(typeId);
}
void QmlProfilerModelManager::replayEvents(qint64 rangeStart, qint64 rangeEnd,
TraceEventLoader loader, Initializer initializer,
Finalizer finalizer, ErrorHandler errorHandler,
QFutureInterface<void> &future) const
{
replayEvents(rangeStart, rangeEnd, static_cast<QmlEventLoader>(loader), initializer, finalizer,
errorHandler, future);
}
static bool isStateful(const QmlEventType &type)
{
// Events of these types carry state that has to be taken into account when adding later events:
@@ -262,82 +162,102 @@ static bool isStateful(const QmlEventType &type)
return message == PixmapCacheEvent || message == MemoryAllocation;
}
bool QmlProfilerModelManager::replayEvents(qint64 rangeStart, qint64 rangeEnd,
EventLoader loader) const
void QmlProfilerModelManager::replayEvents(qint64 rangeStart, qint64 rangeEnd,
QmlEventLoader loader, Initializer initializer,
Finalizer finalizer, ErrorHandler errorHandler,
QFutureInterface<void> &future) const
{
QStack<QmlEvent> stack;
QmlEvent event;
QFile file(d->file.fileName());
if (!file.open(QIODevice::ReadOnly))
return false;
if (initializer)
initializer();
QDataStream stream(&file);
QStack<QmlEvent> stack;
bool crossedRangeStart = false;
while (!stream.atEnd()) {
stream >> event;
if (stream.status() == QDataStream::ReadPastEnd)
break;
const auto result = d->file.replay([&](const QmlEvent &event) {
if (future.isCanceled())
return false;
const QmlEventType &type = d->eventTypes[event.typeIndex()];
if (rangeStart != -1 && rangeEnd != -1) {
// Double-check if rangeStart has been crossed. Some versions of Qt send dirty data.
if (event.timestamp() < rangeStart && !crossedRangeStart) {
if (type.rangeType() != MaximumRangeType) {
if (event.rangeStage() == RangeStart)
stack.push(event);
else if (event.rangeStage() == RangeEnd)
stack.pop();
continue;
} else if (isStateful(type)) {
event.setTimestamp(rangeStart);
} else {
continue;
}
// No restrictions: load all events
if (rangeStart == -1 || rangeEnd == -1) {
loader(event, type);
return true;
}
// Double-check if rangeStart has been crossed. Some versions of Qt send dirty data.
qint64 adjustedTimestamp = event.timestamp();
if (event.timestamp() < rangeStart && !crossedRangeStart) {
if (type.rangeType() != MaximumRangeType) {
if (event.rangeStage() == RangeStart)
stack.push(event);
else if (event.rangeStage() == RangeEnd)
stack.pop();
return true;
} else if (isStateful(type)) {
adjustedTimestamp = rangeStart;
} else {
if (!crossedRangeStart) {
foreach (QmlEvent stashed, stack) {
stashed.setTimestamp(rangeStart);
loader(stashed, d->eventTypes[stashed.typeIndex()]);
}
stack.clear();
crossedRangeStart = true;
return true;
}
} else {
if (!crossedRangeStart) {
for (QmlEvent stashed : stack) {
stashed.setTimestamp(rangeStart);
loader(stashed, d->eventTypes[stashed.typeIndex()]);
}
if (event.timestamp() > rangeEnd) {
if (type.rangeType() != MaximumRangeType) {
if (event.rangeStage() == RangeEnd) {
if (stack.isEmpty()) {
QmlEvent endEvent(event);
endEvent.setTimestamp(rangeEnd);
loader(endEvent, d->eventTypes[event.typeIndex()]);
} else {
stack.pop();
}
} else if (event.rangeStage() == RangeStart) {
stack.push(event);
stack.clear();
crossedRangeStart = true;
}
if (event.timestamp() > rangeEnd) {
if (type.rangeType() != MaximumRangeType) {
if (event.rangeStage() == RangeEnd) {
if (stack.isEmpty()) {
QmlEvent endEvent(event);
endEvent.setTimestamp(rangeEnd);
loader(endEvent, d->eventTypes[event.typeIndex()]);
} else {
stack.pop();
}
continue;
} else if (isStateful(type)) {
event.setTimestamp(rangeEnd);
} else {
continue;
} else if (event.rangeStage() == RangeStart) {
stack.push(event);
}
return true;
} else if (isStateful(type)) {
adjustedTimestamp = rangeEnd;
} else {
return true;
}
}
}
loader(event, type);
}
return true;
}
if (adjustedTimestamp != event.timestamp()) {
QmlEvent adjusted(event);
adjusted.setTimestamp(adjustedTimestamp);
loader(adjusted, type);
} else {
loader(event, type);
}
return true;
});
void QmlProfilerModelManager::QmlProfilerModelManagerPrivate::dispatch(const QmlEvent &event,
const QmlEventType &type)
{
for (const EventLoader &loader : eventLoaders.value(
static_cast<ProfileFeature>(type.feature()))) {
loader(event, type);
switch (result) {
case Timeline::TraceStashFile<QmlEvent>::ReplaySuccess:
if (finalizer)
finalizer();
break;
case Timeline::TraceStashFile<QmlEvent>::ReplayOpenFailed:
if (errorHandler)
errorHandler(tr("Could not re-open temporary trace file"));
break;
case Timeline::TraceStashFile<QmlEvent>::ReplayLoadFailed:
if (errorHandler)
errorHandler(tr("Could not load events from temporary trace file"));
break;
case Timeline::TraceStashFile<QmlEvent>::ReplayReadPastEnd:
if (errorHandler)
errorHandler(tr("Read past end in temporary trace file"));
break;
}
++numLoadedEvents;
}
static QString getDisplayName(const QmlEventType &event)
@@ -374,6 +294,30 @@ static QString getInitialDetails(const QmlEventType &event)
return details;
}
void QmlProfilerModelManager::QmlProfilerModelManagerPrivate::writeToStream(const QmlEvent &event)
{
file.append(event);
}
void QmlProfilerModelManager::QmlProfilerModelManagerPrivate::addEventType(const QmlEventType &type)
{
const int typeId = eventTypes.count();
eventTypes.append(type);
rewriteType(typeId);
const QmlEventLocation &location = type.location();
if (location.isValid()) {
textMarkModel->addTextMarkId(typeId, QmlEventLocation(
detailsRewriter->getLocalFile(location.filename()),
location.line(), location.column()));
}
}
void QmlProfilerModelManager::QmlProfilerModelManagerPrivate::handleError(const QString &message)
{
// What to do here?
qWarning() << message;
}
void QmlProfilerModelManager::QmlProfilerModelManagerPrivate::rewriteType(int typeIndex)
{
QmlEventType &type = eventTypes[typeIndex];
@@ -390,85 +334,6 @@ void QmlProfilerModelManager::QmlProfilerModelManagerPrivate::rewriteType(int ty
detailsRewriter->requestDetailsForLocation(typeIndex, location);
}
void QmlProfilerModelManager::QmlProfilerModelManagerPrivate::updateTraceTime(qint64 time)
{
QTC_ASSERT(time >= 0, return);
if (traceStart > time || traceStart == -1)
traceStart = time;
if (traceEnd < time || traceEnd == -1)
traceEnd = time;
QTC_ASSERT(traceEnd >= traceStart, traceStart = traceEnd);
}
void QmlProfilerModelManager::QmlProfilerModelManagerPrivate::restrictTraceTimeToRange(qint64 start, qint64 end)
{
QTC_ASSERT(end == -1 || start <= end, end = start);
restrictedTraceStart = start;
restrictedTraceEnd = end;
}
void QmlProfilerModelManager::announceFeatures(quint64 features, EventLoader eventLoader,
Finalizer finalizer)
{
if ((features & d->availableFeatures) != features) {
d->availableFeatures |= features;
emit availableFeaturesChanged(d->availableFeatures);
}
if ((features & d->visibleFeatures) != features) {
d->visibleFeatures |= features;
emit visibleFeaturesChanged(d->visibleFeatures);
}
for (int feature = 0; feature != MaximumProfileFeature; ++feature) {
if (features & (1ULL << feature))
d->eventLoaders[static_cast<ProfileFeature>(feature)].append(eventLoader);
}
d->finalizers.append(finalizer);
}
quint64 QmlProfilerModelManager::availableFeatures() const
{
return d->availableFeatures;
}
quint64 QmlProfilerModelManager::visibleFeatures() const
{
return d->visibleFeatures;
}
void QmlProfilerModelManager::setVisibleFeatures(quint64 features)
{
if (d->visibleFeatures != features) {
d->visibleFeatures = features;
emit visibleFeaturesChanged(d->visibleFeatures);
}
}
quint64 QmlProfilerModelManager::recordedFeatures() const
{
return d->recordedFeatures;
}
void QmlProfilerModelManager::setRecordedFeatures(quint64 features)
{
if (d->recordedFeatures != features) {
d->recordedFeatures = features;
emit recordedFeaturesChanged(d->recordedFeatures);
}
}
bool QmlProfilerModelManager::aggregateTraces() const
{
return d->aggregateTraces;
}
void QmlProfilerModelManager::setAggregateTraces(bool aggregateTraces)
{
d->aggregateTraces = aggregateTraces;
}
const char *QmlProfilerModelManager::featureName(ProfileFeature feature)
{
return ProfileFeatureNames[feature];
@@ -477,18 +342,14 @@ const char *QmlProfilerModelManager::featureName(ProfileFeature feature)
void QmlProfilerModelManager::finalize()
{
QTC_ASSERT(state() == AcquiringData, /**/);
d->file.flush();
if (!d->file.flush())
emit error(tr("Failed to flush temporary trace file"));
d->detailsRewriter->reloadDocuments();
// Load notes after the timeline models have been initialized ...
// which happens on stateChanged(Done).
foreach (const Finalizer &finalizer, d->finalizers) {
finalizer();
++d->numFinishedFinalizers;
}
setState(Done);
TimelineTraceManager::finalize();
}
void QmlProfilerModelManager::populateFileFinder(const ProjectExplorer::Target *target)
@@ -501,146 +362,6 @@ QString QmlProfilerModelManager::findLocalFile(const QString &remoteFile)
return d->detailsRewriter->getLocalFile(remoteFile);
}
void QmlProfilerModelManager::save(const QString &filename)
{
QFile *file = new QFile(filename);
if (!file->open(QIODevice::WriteOnly)) {
emit error(tr("Could not open %1 for writing.").arg(filename));
delete file;
emit saveFinished();
return;
}
d->notesModel->stash();
QmlProfilerFileWriter *writer = new QmlProfilerFileWriter(this);
writer->setTraceTime(traceStart(), traceEnd(), traceDuration());
writer->setData(this);
writer->setNotes(d->notesModel->notes());
connect(writer, &QObject::destroyed, this, &QmlProfilerModelManager::saveFinished,
Qt::QueuedConnection);
connect(writer, &QmlProfilerFileWriter::error, this, [this, file](const QString &message) {
file->close();
file->remove();
delete file;
emit error(message);
}, Qt::QueuedConnection);
connect(writer, &QmlProfilerFileWriter::success, this, [file]() {
file->close();
delete file;
}, Qt::QueuedConnection);
connect(writer, &QmlProfilerFileWriter::canceled, this, [file]() {
file->close();
file->remove();
delete file;
}, Qt::QueuedConnection);
QFuture<void> result = Utils::runAsync([file, writer] (QFutureInterface<void> &future) {
writer->setFuture(&future);
if (file->fileName().endsWith(QLatin1String(Constants::QtdFileExtension)))
writer->saveQtd(file);
else
writer->saveQzt(file);
writer->deleteLater();
});
Core::ProgressManager::addTask(result, tr("Saving Trace Data"), Constants::TASK_SAVE,
Core::ProgressManager::ShowInApplicationIcon);
}
void QmlProfilerModelManager::load(const QString &filename)
{
bool isQtd = filename.endsWith(QLatin1String(Constants::QtdFileExtension));
QFile *file = new QFile(filename, this);
if (!file->open(isQtd ? (QIODevice::ReadOnly | QIODevice::Text) : QIODevice::ReadOnly)) {
emit error(tr("Could not open %1 for reading.").arg(filename));
delete file;
emit loadFinished();
return;
}
clear();
setState(AcquiringData);
QmlProfilerFileReader *reader = new QmlProfilerFileReader(this);
connect(reader, &QObject::destroyed, this, &QmlProfilerModelManager::loadFinished,
Qt::QueuedConnection);
connect(reader, &QmlProfilerFileReader::typesLoaded,
this, &QmlProfilerModelManager::addEventTypes);
connect(reader, &QmlProfilerFileReader::notesLoaded,
d->notesModel, &QmlProfilerNotesModel::setNotes);
connect(reader, &QmlProfilerFileReader::qmlEventsLoaded,
this, &QmlProfilerModelManager::addEvents);
connect(reader, &QmlProfilerFileReader::success, this, [this, reader]() {
if (reader->traceStart() >= 0)
decreaseTraceStart(reader->traceStart());
if (reader->traceEnd() >= 0)
increaseTraceEnd(reader->traceEnd());
setRecordedFeatures(reader->loadedFeatures());
delete reader;
finalize();
}, Qt::QueuedConnection);
connect(reader, &QmlProfilerFileReader::error, this, [this, reader](const QString &message) {
clear();
delete reader;
emit error(message);
}, Qt::QueuedConnection);
connect(reader, &QmlProfilerFileReader::canceled, this, [this, reader]() {
clear();
delete reader;
}, Qt::QueuedConnection);
QFuture<void> result = Utils::runAsync([isQtd, file, reader] (QFutureInterface<void> &future) {
reader->setFuture(&future);
if (isQtd)
reader->loadQtd(file);
else
reader->loadQzt(file);
file->close();
file->deleteLater();
});
Core::ProgressManager::addTask(result, tr("Loading Trace Data"), Constants::TASK_LOAD);
}
void QmlProfilerModelManager::setState(QmlProfilerModelManager::State state)
{
// It's not an error, we are continuously calling "AcquiringData" for example
if (d->state == state)
return;
switch (state) {
case ClearingData:
QTC_ASSERT(d->state == Done || d->state == Empty || d->state == AcquiringData, /**/);
break;
case Empty:
// if it's not empty, complain but go on
QTC_ASSERT(isEmpty(), /**/);
break;
case AcquiringData:
break;
case Done:
QTC_ASSERT(d->state == AcquiringData || d->state == Empty, return);
break;
default:
emit error(tr("Trying to set unknown state in events list."));
break;
}
d->state = state;
emit stateChanged();
}
void QmlProfilerModelManager::detailsChanged(int typeId, const QString &newString)
{
QTC_ASSERT(typeId < d->eventTypes.count(), return);
@@ -648,76 +369,40 @@ void QmlProfilerModelManager::detailsChanged(int typeId, const QString &newStrin
emit typeDetailsChanged(typeId);
}
QmlProfilerModelManager::State QmlProfilerModelManager::state() const
const Timeline::TraceEventType &QmlProfilerModelManager::lookupType(int typeIndex) const
{
return d->state;
return eventType(typeIndex);
}
void QmlProfilerModelManager::doClearEvents()
void QmlProfilerModelManager::clearEventStorage()
{
d->numLoadedEvents = 0;
d->numFinishedFinalizers = 0;
d->file.remove();
d->eventStream.unsetDevice();
if (d->file.open())
d->eventStream.setDevice(&d->file);
else
emit error(tr("Cannot open temporary trace file to store events."));
d->restrictTraceTimeToRange(-1, -1);
d->traceStart = -1;
d->traceEnd = -1;
d->notesModel->clear();
setVisibleFeatures(0);
setRecordedFeatures(0);
TimelineTraceManager::clearEventStorage();
d->file.clear();
if (!d->file.open())
emit error(tr("Failed to reset temporary trace file"));
}
void QmlProfilerModelManager::clearEvents()
void QmlProfilerModelManager::clearTypeStorage()
{
setState(ClearingData);
doClearEvents();
setState(Empty);
}
void QmlProfilerModelManager::clear()
{
setState(ClearingData);
doClearEvents();
TimelineTraceManager::clearTypeStorage();
d->eventTypes.clear();
d->detailsRewriter->clear();
setState(Empty);
}
void QmlProfilerModelManager::restrictToRange(qint64 startTime, qint64 endTime)
void QmlProfilerModelManager::addEventType(const QmlEventType &type)
{
d->notesModel->stash();
const QVector<QmlNote> notes = d->notesModel->notes();
d->notesModel->clear();
setState(ClearingData);
setVisibleFeatures(0);
startAcquiring();
if (!replayEvents(startTime, endTime,
std::bind(&QmlProfilerModelManagerPrivate::dispatch, d, std::placeholders::_1,
std::placeholders::_2))) {
emit error(tr("Could not re-read events from temporary trace file. "
"The trace data is lost."));
clear();
} else {
d->notesModel->setNotes(notes);
d->restrictTraceTimeToRange(startTime, endTime);
finalize();
}
d->addEventType(type);
TimelineTraceManager::addEventType(type);
}
bool QmlProfilerModelManager::isRestrictedToRange() const
void QmlProfilerModelManager::addEvent(const QmlEvent &event)
{
return d->restrictedTraceStart != -1 || d->restrictedTraceEnd != -1;
d->writeToStream(event);
TimelineTraceManager::addEvent(event);
}
void QmlProfilerModelManager::startAcquiring()
Timeline::TimelineTraceFile *QmlProfilerModelManager::createTraceFile()
{
setState(AcquiringData);
return new Internal::QmlProfilerTraceFile(this);
}
} // namespace QmlProfiler