diff --git a/src/libs/tracing/timelinetracefile.cpp b/src/libs/tracing/timelinetracefile.cpp index 45fc4bbbe17..858cddbb9d8 100644 --- a/src/libs/tracing/timelinetracefile.cpp +++ b/src/libs/tracing/timelinetracefile.cpp @@ -61,6 +61,12 @@ void TimelineTraceFile::setDeviceProgress(QIODevice *device) * (MaximumProgress - MinimumProgress) / device->size()); } +void TimelineTraceFile::fail(const QString &message) +{ + emit error(message); + m_future.cancel(); +} + bool TimelineTraceFile::isCanceled() const { return m_future.isCanceled(); diff --git a/src/libs/tracing/timelinetracefile.h b/src/libs/tracing/timelinetracefile.h index 4d37cdba35b..4c1a255ba7c 100644 --- a/src/libs/tracing/timelinetracefile.h +++ b/src/libs/tracing/timelinetracefile.h @@ -64,6 +64,7 @@ public: virtual void save(QIODevice *device) = 0; virtual void load(QIODevice *device) = 0; + void fail(const QString &message); void setTraceStart(qint64 traceStart) { m_traceStart = traceStart; } qint64 traceStart() const { return m_traceStart; } @@ -79,8 +80,6 @@ public: signals: void error(const QString &error); - void success(); - void canceled(); private: qint64 m_traceStart = -1; diff --git a/src/libs/tracing/timelinetracemanager.cpp b/src/libs/tracing/timelinetracemanager.cpp index 73c686f7ca7..dcc8d322b56 100644 --- a/src/libs/tracing/timelinetracemanager.cpp +++ b/src/libs/tracing/timelinetracemanager.cpp @@ -230,100 +230,66 @@ void TimelineTraceManager::finalize() QFuture TimelineTraceManager::save(const QString &filename) { - QFile *file = new QFile(filename); - if (!file->open(QIODevice::WriteOnly)) { - delete file; - return Utils::runAsync([this, filename](QFutureInterface &future) { - future.setProgressRange(0, 1); - future.setProgressValue(1); - emit error(tr("Could not open %1 for writing.").arg(filename)); - emit saveFinished(); - }); - } - TimelineTraceFile *writer = createTraceFile(); writer->setTraceTime(traceStart(), traceEnd(), traceDuration()); writer->setTraceManager(this); writer->setNotes(d->notesModel); - connect(writer, &QObject::destroyed, this, &TimelineTraceManager::saveFinished, - Qt::QueuedConnection); + connect(writer, &QObject::destroyed, this, &TimelineTraceManager::saveFinished); + connect(writer, &TimelineTraceFile::error, this, &TimelineTraceManager::error); - connect(writer, &TimelineTraceFile::error, this, [this, file](const QString &message) { - file->close(); - file->remove(); - delete file; - if (!message.isEmpty()) - emit error(message); - }, Qt::QueuedConnection); - - connect(writer, &TimelineTraceFile::success, this, [file]() { - file->close(); - delete file; - }, Qt::QueuedConnection); - - connect(writer, &TimelineTraceFile::canceled, this, [file]() { - file->close(); - file->remove(); - delete file; - }, Qt::QueuedConnection); - - return Utils::runAsync([file, writer] (QFutureInterface &future) { + return Utils::runAsync([filename, writer] (QFutureInterface &future) { writer->setFuture(future); - writer->save(file); + QFile file(filename); + + if (file.open(QIODevice::WriteOnly)) + writer->save(&file); + else + writer->fail(tr("Could not open %1 for writing.").arg(filename)); + + if (future.isCanceled()) + file.remove(); writer->deleteLater(); }); } QFuture TimelineTraceManager::load(const QString &filename) { - QFile *file = new QFile(filename, this); - if (!file->open(QIODevice::ReadOnly)) { - delete file; - return Utils::runAsync([this, filename] (QFutureInterface &future) { - future.setProgressRange(0, 1); - future.setProgressValue(1); - emit error(tr("Could not open %1 for reading.").arg(filename)); - emit loadFinished(); - }); - } - clearAll(); initialize(); TimelineTraceFile *reader = createTraceFile(); reader->setTraceManager(this); reader->setNotes(d->notesModel); - connect(reader, &QObject::destroyed, this, &TimelineTraceManager::loadFinished, - Qt::QueuedConnection); + connect(reader, &QObject::destroyed, this, &TimelineTraceManager::loadFinished); + connect(reader, &TimelineTraceFile::error, this, &TimelineTraceManager::error); - connect(reader, &TimelineTraceFile::success, this, [this, reader]() { - if (reader->traceStart() >= 0) - decreaseTraceStart(reader->traceStart()); - if (reader->traceEnd() >= 0) - increaseTraceEnd(reader->traceEnd()); - finalize(); - delete reader; - }, Qt::QueuedConnection); - - connect(reader, &TimelineTraceFile::error, this, [this, reader](const QString &message) { - clearAll(); - delete reader; - if (!message.isEmpty()) - emit error(message); - }, Qt::QueuedConnection); - - connect(reader, &TimelineTraceFile::canceled, this, [this, reader]() { - clearAll(); - delete reader; - }, Qt::QueuedConnection); - - return Utils::runAsync([file, reader] (QFutureInterface &future) { + QFuture future = Utils::runAsync([filename, reader] (QFutureInterface &future) { reader->setFuture(future); - reader->load(file); - file->close(); - file->deleteLater(); + QFile file(filename); + + if (file.open(QIODevice::ReadOnly)) + reader->load(&file); + else + reader->fail(tr("Could not open %1 for reading.").arg(filename)); + + reader->deleteLater(); }); + + QFutureWatcher *watcher = new QFutureWatcher(reader); + watcher->setFuture(future); + connect(watcher, &QFutureWatcherBase::canceled, this, &TimelineTraceManager::clearAll); + connect(watcher, &QFutureWatcherBase::finished, this, [this, reader]() { + if (!reader->isCanceled()) { + if (reader->traceStart() >= 0) + decreaseTraceStart(reader->traceStart()); + if (reader->traceEnd() >= 0) + increaseTraceEnd(reader->traceEnd()); + finalize(); + } + }); + + return future; } qint64 TimelineTraceManager::traceStart() const diff --git a/src/plugins/qmlprofiler/qmlprofilertracefile.cpp b/src/plugins/qmlprofiler/qmlprofilertracefile.cpp index 7055cd265d0..0a69f1324c5 100644 --- a/src/plugins/qmlprofiler/qmlprofilertracefile.cpp +++ b/src/plugins/qmlprofiler/qmlprofilertracefile.cpp @@ -189,12 +189,8 @@ void QmlProfilerTraceFile::loadQtd(QIODevice *device) } } - if (isCanceled()) - emit canceled(); - else if (stream.hasError()) - emit error(tr("Error while parsing trace data file: %1").arg(stream.errorString())); - else - emit success(); + if (stream.hasError()) + fail(tr("Error while parsing trace data file: %1").arg(stream.errorString())); } void QmlProfilerTraceFile::loadQzt(QIODevice *device) @@ -205,7 +201,7 @@ void QmlProfilerTraceFile::loadQzt(QIODevice *device) QByteArray magic; stream >> magic; if (magic != QByteArray("QMLPROFILER")) { - emit error(tr("Invalid magic: %1").arg(QLatin1String(magic))); + fail(tr("Invalid magic: %1").arg(QLatin1String(magic))); return; } @@ -213,7 +209,7 @@ void QmlProfilerTraceFile::loadQzt(QIODevice *device) stream >> dataStreamVersion; if (dataStreamVersion > QDataStream::Qt_DefaultCompiledVersion) { - emit error(tr("Unknown data stream version: %1").arg(dataStreamVersion)); + fail(tr("Unknown data stream version: %1").arg(dataStreamVersion)); return; } stream.setVersion(dataStreamVersion); @@ -237,7 +233,7 @@ void QmlProfilerTraceFile::loadQzt(QIODevice *device) quint32 numEventTypes; bufferStream >> numEventTypes; if (numEventTypes > quint32(std::numeric_limits::max())) { - emit error(tr("Excessive number of event types: %1").arg(numEventTypes)); + fail(tr("Excessive number of event types: %1").arg(numEventTypes)); return; } @@ -270,7 +266,7 @@ void QmlProfilerTraceFile::loadQzt(QIODevice *device) bufferStream >> event; if (bufferStream.status() == QDataStream::Ok) { if (event.typeIndex() >= traceManager()->numEventTypes()) { - emit error(tr("Invalid type index %1").arg(event.typeIndex())); + fail(tr("Invalid type index %1").arg(event.typeIndex())); return; } addFeature(manager->eventType(event.typeIndex()).feature()); @@ -279,7 +275,7 @@ void QmlProfilerTraceFile::loadQzt(QIODevice *device) } else if (bufferStream.status() == QDataStream::ReadPastEnd) { break; // Apparently EOF is a character so we end up here after the last event. } else if (bufferStream.status() == QDataStream::ReadCorruptData) { - emit error(tr("Corrupt data before position %1.").arg(device->pos())); + fail(tr("Corrupt data before position %1.").arg(device->pos())); return; } else { Q_UNREACHABLE(); @@ -289,12 +285,6 @@ void QmlProfilerTraceFile::loadQzt(QIODevice *device) buffer.close(); setDeviceProgress(device); } - - if (isCanceled()) { - emit canceled(); - } else { - emit success(); - } } void QmlProfilerTraceFile::addEventsProgress(qint64 timestamp) @@ -694,10 +684,8 @@ void QmlProfilerTraceFile::saveQtd(QIODevice *device) addStageProgress(ProgressTypes); stream.writeEndElement(); // eventData - if (isCanceled()) { - emit canceled(); + if (isCanceled()) return; - } QStack stack; qint64 lastProgressTimestamp = traceStart(); @@ -794,15 +782,11 @@ void QmlProfilerTraceFile::saveQtd(QIODevice *device) stream.writeEndElement(); // trace stream.writeEndDocument(); - if (isCanceled()) - emit canceled(); - else if (stream.hasError()) - emit error(tr("Error writing trace file.")); - else - emit success(); + if (stream.hasError()) + fail(tr("Error writing trace file.")); }, [this](const QString &message) { - emit error(tr("Could not re-read events from temporary trace file: %s\nSaving failed.") - .arg(message)); + fail(tr("Could not re-read events from temporary trace file: %s\nSaving failed.") + .arg(message)); }, future()); } @@ -841,10 +825,8 @@ void QmlProfilerTraceFile::saveQzt(QIODevice *device) addStageProgress(ProgressNotes); } - if (isCanceled()) { - emit canceled(); + if (isCanceled()) return; - } qint64 lastProgressTimestamp = traceStart(); modelManager()->replayQmlEvents([&](const QmlEvent &event, const QmlEventType &type) { @@ -864,18 +846,15 @@ void QmlProfilerTraceFile::saveQzt(QIODevice *device) }, [&]() { buffer.open(QIODevice::WriteOnly); }, [&]() { - if (isCanceled()) { - emit canceled(); - } else { + if (!isCanceled()) { stream << qCompress(buffer.data()); buffer.close(); buffer.buffer().clear(); addEventsProgress(traceEnd() - lastProgressTimestamp); - emit success(); } }, [this](const QString &message) { - emit error(tr("Could not re-read events from temporary trace file: %s\nSaving failed.") - .arg(message)); + fail(tr("Could not re-read events from temporary trace file: %s\nSaving failed.") + .arg(message)); }, future()); }