From dd988bdb5ec7ae4cd082e077c0c9ff051157e1c5 Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Thu, 27 Aug 2015 17:36:46 +0200 Subject: Rename files to follow common pattern among extension plugins This way the plugin will successfully build with qbs again. Change-Id: Iac5fc64753bb225649ba9f62199d6248450e1546 Reviewed-by: Christian Kandeler --- plugins/qmlprofiler/QmlProfilerExtension.json.in | 15 + plugins/qmlprofiler/inputeventsmodel.cpp | 120 +++++ plugins/qmlprofiler/inputeventsmodel.h | 54 +++ plugins/qmlprofiler/memoryusagemodel.cpp | 273 ++++++++++++ plugins/qmlprofiler/memoryusagemodel.h | 78 ++++ plugins/qmlprofiler/pixmapcachemodel.cpp | 493 +++++++++++++++++++++ plugins/qmlprofiler/pixmapcachemodel.h | 123 +++++ plugins/qmlprofiler/qmlprofiler.pro | 26 ++ plugins/qmlprofiler/qmlprofiler.qbs | 26 ++ plugins/qmlprofiler/qmlprofiler_dependencies.pri | 5 + plugins/qmlprofiler/qmlprofilerextension_global.h | 31 ++ .../qmlprofiler/qmlprofilerextensionconstants.h | 32 ++ plugins/qmlprofiler/qmlprofilerextensionplugin.cpp | 128 ++++++ plugins/qmlprofiler/qmlprofilerextensionplugin.h | 50 +++ plugins/qmlprofiler/scenegraphtimelinemodel.cpp | 304 +++++++++++++ plugins/qmlprofiler/scenegraphtimelinemodel.h | 107 +++++ .../QmlProfilerExtension.json.in | 15 - plugins/qmlprofilerextension/inputeventsmodel.cpp | 120 ----- plugins/qmlprofilerextension/inputeventsmodel.h | 54 --- plugins/qmlprofilerextension/memoryusagemodel.cpp | 273 ------------ plugins/qmlprofilerextension/memoryusagemodel.h | 78 ---- plugins/qmlprofilerextension/pixmapcachemodel.cpp | 493 --------------------- plugins/qmlprofilerextension/pixmapcachemodel.h | 123 ----- .../qmlprofilerextension/qmlprofilerextension.pro | 27 -- .../qmlprofilerextension/qmlprofilerextension.qbs | 26 -- .../qmlprofilerextension_dependencies.pri | 5 - .../qmlprofilerextension_global.h | 31 -- .../qmlprofilerextensionconstants.h | 32 -- .../qmlprofilerextensionplugin.cpp | 128 ------ .../qmlprofilerextensionplugin.h | 50 --- .../scenegraphtimelinemodel.cpp | 304 ------------- .../qmlprofilerextension/scenegraphtimelinemodel.h | 107 ----- qmlprofiler.pro | 2 +- 33 files changed, 1866 insertions(+), 1867 deletions(-) create mode 100644 plugins/qmlprofiler/QmlProfilerExtension.json.in create mode 100644 plugins/qmlprofiler/inputeventsmodel.cpp create mode 100644 plugins/qmlprofiler/inputeventsmodel.h create mode 100644 plugins/qmlprofiler/memoryusagemodel.cpp create mode 100644 plugins/qmlprofiler/memoryusagemodel.h create mode 100644 plugins/qmlprofiler/pixmapcachemodel.cpp create mode 100644 plugins/qmlprofiler/pixmapcachemodel.h create mode 100644 plugins/qmlprofiler/qmlprofiler.pro create mode 100644 plugins/qmlprofiler/qmlprofiler.qbs create mode 100644 plugins/qmlprofiler/qmlprofiler_dependencies.pri create mode 100644 plugins/qmlprofiler/qmlprofilerextension_global.h create mode 100644 plugins/qmlprofiler/qmlprofilerextensionconstants.h create mode 100644 plugins/qmlprofiler/qmlprofilerextensionplugin.cpp create mode 100644 plugins/qmlprofiler/qmlprofilerextensionplugin.h create mode 100644 plugins/qmlprofiler/scenegraphtimelinemodel.cpp create mode 100644 plugins/qmlprofiler/scenegraphtimelinemodel.h delete mode 100644 plugins/qmlprofilerextension/QmlProfilerExtension.json.in delete mode 100644 plugins/qmlprofilerextension/inputeventsmodel.cpp delete mode 100644 plugins/qmlprofilerextension/inputeventsmodel.h delete mode 100644 plugins/qmlprofilerextension/memoryusagemodel.cpp delete mode 100644 plugins/qmlprofilerextension/memoryusagemodel.h delete mode 100644 plugins/qmlprofilerextension/pixmapcachemodel.cpp delete mode 100644 plugins/qmlprofilerextension/pixmapcachemodel.h delete mode 100644 plugins/qmlprofilerextension/qmlprofilerextension.pro delete mode 100644 plugins/qmlprofilerextension/qmlprofilerextension.qbs delete mode 100644 plugins/qmlprofilerextension/qmlprofilerextension_dependencies.pri delete mode 100644 plugins/qmlprofilerextension/qmlprofilerextension_global.h delete mode 100644 plugins/qmlprofilerextension/qmlprofilerextensionconstants.h delete mode 100644 plugins/qmlprofilerextension/qmlprofilerextensionplugin.cpp delete mode 100644 plugins/qmlprofilerextension/qmlprofilerextensionplugin.h delete mode 100644 plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp delete mode 100644 plugins/qmlprofilerextension/scenegraphtimelinemodel.h diff --git a/plugins/qmlprofiler/QmlProfilerExtension.json.in b/plugins/qmlprofiler/QmlProfilerExtension.json.in new file mode 100644 index 0000000000..e7154d2e85 --- /dev/null +++ b/plugins/qmlprofiler/QmlProfilerExtension.json.in @@ -0,0 +1,15 @@ +{ + \"Name\" : \"QmlProfilerExtension\", + \"Version\" : \"$$QTCREATOR_VERSION\", + \"CompatVersion\" : \"$$QTCREATOR_COMPAT_VERSION\", + \"Vendor\" : \"The Qt Company Ltd\", + \"Copyright\" : \"(C) 2015 The Qt Company Ltd\", + \"License\" : [ \"Commercial Usage\", + \"\", + \"Licensees holding valid Qt Commercial licenses may use this plugin in accordance with the Qt Commercial License Agreement provided with the Software or, alternatively, in accordance with the terms contained in a written agreement between you and The Qt Company.\" + ], + \"Category\" : \"Qt Quick\", + \"Description\" : \"Qml Profiler Extension Plugin.\", + \"Url\" : \"http://www.qt.io\", + $$dependencyList +} diff --git a/plugins/qmlprofiler/inputeventsmodel.cpp b/plugins/qmlprofiler/inputeventsmodel.cpp new file mode 100644 index 0000000000..0c77629321 --- /dev/null +++ b/plugins/qmlprofiler/inputeventsmodel.cpp @@ -0,0 +1,120 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd +** All rights reserved. +** For any questions to The Qt Company, please use contact form at http://www.qt.io/contact-us +** +** This file is part of the Qt Enterprise Qt Quick Profiler Add-on. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. +** +** If you have questions regarding the use of this file, please use +** contact form at http://www.qt.io/contact-us +** +****************************************************************************/ + +#include "inputeventsmodel.h" +#include "qmldebug/qmlprofilereventtypes.h" +#include "qmlprofiler/qmlprofilermodelmanager.h" + +namespace QmlProfilerExtension { +namespace Internal { + +using namespace QmlProfiler; + +InputEventsModel::InputEventsModel(QmlProfilerModelManager *manager, QObject *parent) : + QmlProfilerTimelineModel(manager, QmlDebug::Event, QmlDebug::MaximumRangeType, + QmlDebug::ProfileInputEvents, parent), + m_keyTypeId(-1), m_mouseTypeId(-1) +{ +} + +int InputEventsModel::typeId(int index) const +{ + return selectionId(index) == QmlDebug::Mouse ? m_mouseTypeId : m_keyTypeId; +} + +QColor InputEventsModel::color(int index) const +{ + return colorBySelectionId(index); +} + +QVariantList InputEventsModel::labels() const +{ + QVariantList result; + + QVariantMap element; + element.insert(QLatin1String("description"), QVariant(tr("Mouse Events"))); + element.insert(QLatin1String("id"), QVariant(QmlDebug::Mouse)); + result << element; + + element.clear(); + element.insert(QLatin1String("description"), QVariant(tr("Keyboard Events"))); + element.insert(QLatin1String("id"), QVariant(QmlDebug::Key)); + result << element; + + return result; +} + +QVariantMap InputEventsModel::details(int index) const +{ + QVariantMap result; + result.insert(QLatin1String("displayName"), + selectionId(index) == QmlDebug::Key ? tr("Keyboard Event") : tr("Mouse Event")); + result.insert(QLatin1String("Timestamp"), QmlProfilerBaseModel::formatTime(startTime(index))); + return result; +} + +int InputEventsModel::expandedRow(int index) const +{ + return selectionId(index) == QmlDebug::Mouse ? 1 : 2; +} + +int InputEventsModel::collapsedRow(int index) const +{ + Q_UNUSED(index) + return 1; +} + +void InputEventsModel::loadData() +{ + QmlProfilerDataModel *simpleModel = modelManager()->qmlModel(); + if (simpleModel->isEmpty()) + return; + + const QVector &types = simpleModel->getEventTypes(); + foreach (const QmlProfilerDataModel::QmlEventData &event, simpleModel->getEvents()) { + const QmlProfilerDataModel::QmlEventTypeData &type = types[event.typeIndex]; + if (!accepted(type)) + continue; + insert(event.startTime, 0, type.detailType); + if (type.detailType == QmlDebug::Mouse) { + if (m_mouseTypeId == -1) + m_mouseTypeId = event.typeIndex; + } else if (m_keyTypeId == -1) { + m_keyTypeId = event.typeIndex; + } + updateProgress(count(), simpleModel->getEvents().count()); + } + setCollapsedRowCount(2); + setExpandedRowCount(3); + updateProgress(1, 1); +} + +void InputEventsModel::clear() +{ + m_keyTypeId = m_mouseTypeId = -1; + QmlProfilerTimelineModel::clear(); +} + +bool InputEventsModel::accepted(const QmlProfilerDataModel::QmlEventTypeData &event) const +{ + return QmlProfilerTimelineModel::accepted(event) && + (event.detailType == QmlDebug::Mouse || event.detailType == QmlDebug::Key); +} + +} +} diff --git a/plugins/qmlprofiler/inputeventsmodel.h b/plugins/qmlprofiler/inputeventsmodel.h new file mode 100644 index 0000000000..43a9dc4498 --- /dev/null +++ b/plugins/qmlprofiler/inputeventsmodel.h @@ -0,0 +1,54 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd +** All rights reserved. +** For any questions to The Qt Company, please use contact form at http://www.qt.io/contact-us +** +** This file is part of the Qt Enterprise Qt Quick Profiler Add-on. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. +** +** If you have questions regarding the use of this file, please use +** contact form at http://www.qt.io/contact-us +** +****************************************************************************/ + +#ifndef INPUTEVENTSMODEL_H +#define INPUTEVENTSMODEL_H + +#include "qmlprofiler/qmlprofilertimelinemodel.h" + +namespace QmlProfilerExtension { +namespace Internal { + +class InputEventsModel : public QmlProfiler::QmlProfilerTimelineModel +{ + Q_OBJECT + +protected: + bool accepted(const QmlProfiler::QmlProfilerDataModel::QmlEventTypeData &event) const; + +public: + InputEventsModel(QmlProfiler::QmlProfilerModelManager *manager, QObject *parent = 0); + + int typeId(int index) const; + QColor color(int index) const; + QVariantList labels() const; + QVariantMap details(int index) const; + int expandedRow(int index) const; + int collapsedRow(int index) const; + void loadData(); + void clear(); + +private: + int m_keyTypeId; + int m_mouseTypeId; + +}; + +} +} +#endif // INPUTEVENTSMODEL_H diff --git a/plugins/qmlprofiler/memoryusagemodel.cpp b/plugins/qmlprofiler/memoryusagemodel.cpp new file mode 100644 index 0000000000..402b1e08c0 --- /dev/null +++ b/plugins/qmlprofiler/memoryusagemodel.cpp @@ -0,0 +1,273 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd +** All rights reserved. +** For any questions to The Qt Company, please use contact form at http://www.qt.io/contact-us +** +** This file is part of the Qt Enterprise Qt Quick Profiler Add-on. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. +** +** If you have questions regarding the use of this file, please use +** contact form at http://www.qt.io/contact-us +** +****************************************************************************/ + +#include "memoryusagemodel.h" +#include "qmldebug/qmlprofilereventtypes.h" +#include "qmlprofiler/qmlprofilermodelmanager.h" + +#include + +namespace QmlProfilerExtension { +namespace Internal { + +using namespace QmlProfiler; + +MemoryUsageModel::MemoryUsageModel(QmlProfilerModelManager *manager, QObject *parent) : + QmlProfilerTimelineModel(manager, QmlDebug::MemoryAllocation, QmlDebug::MaximumRangeType, + QmlDebug::ProfileMemory, parent) +{ + m_maxSize = 1; + announceFeatures((1ULL << mainFeature()) | QmlDebug::Constants::QML_JS_RANGE_FEATURES); +} + +int MemoryUsageModel::rowMaxValue(int rowNumber) const +{ + Q_UNUSED(rowNumber); + return m_maxSize; +} + +int MemoryUsageModel::expandedRow(int index) const +{ + int type = selectionId(index); + return (type == QmlDebug::HeapPage || type == QmlDebug::LargeItem) ? 1 : 2; +} + +int MemoryUsageModel::collapsedRow(int index) const +{ + return expandedRow(index); +} + +int MemoryUsageModel::typeId(int index) const +{ + return m_data[index].typeId; +} + +QColor MemoryUsageModel::color(int index) const +{ + return colorBySelectionId(index); +} + +float MemoryUsageModel::relativeHeight(int index) const +{ + return qMin(1.0f, (float)m_data[index].size / (float)m_maxSize); +} + +QVariantMap MemoryUsageModel::location(int index) const +{ + static const QLatin1String file("file"); + static const QLatin1String line("line"); + static const QLatin1String column("column"); + + QVariantMap result; + + int originType = m_data[index].originTypeIndex; + if (originType > -1) { + const QmlDebug::QmlEventLocation &location = + modelManager()->qmlModel()->getEventTypes().at(originType).location; + + result.insert(file, location.filename); + result.insert(line, location.line); + result.insert(column, location.column); + } + + return result; +} + +QVariantList MemoryUsageModel::labels() const +{ + QVariantList result; + + QVariantMap element; + element.insert(QLatin1String("description"), QVariant(tr("Memory Allocation"))); + element.insert(QLatin1String("id"), QVariant(QmlDebug::HeapPage)); + result << element; + + element.clear(); + element.insert(QLatin1String("description"), QVariant(tr("Memory Usage"))); + element.insert(QLatin1String("id"), QVariant(QmlDebug::SmallItem)); + result << element; + + return result; +} + +QVariantMap MemoryUsageModel::details(int index) const +{ + QVariantMap result; + const MemoryAllocation *ev = &m_data[index]; + + if (ev->allocated >= -ev->deallocated) + result.insert(QLatin1String("displayName"), tr("Memory Allocated")); + else + result.insert(QLatin1String("displayName"), tr("Memory Freed")); + + result.insert(tr("Total"), QString::fromLatin1("%1 bytes").arg(ev->size)); + if (ev->allocations > 0) { + result.insert(tr("Allocated"), QString::fromLatin1("%1 bytes").arg(ev->allocated)); + result.insert(tr("Allocations"), QString::number(ev->allocations)); + } + if (ev->deallocations > 0) { + result.insert(tr("Deallocated"), QString::fromLatin1("%1 bytes").arg(-ev->deallocated)); + result.insert(tr("Deallocations"), QString::number(ev->deallocations)); + } + result.insert(tr("Type"), QVariant(memoryTypeName(selectionId(index)))); + + if (ev->originTypeIndex != -1) { + result.insert(tr("Location"), + modelManager()->qmlModel()->getEventTypes().at(ev->originTypeIndex).displayName); + } + return result; +} + +struct RangeStackFrame { + RangeStackFrame() : originTypeIndex(-1), startTime(-1), endTime(-1) {} + RangeStackFrame(int originTypeIndex, qint64 startTime, qint64 endTime) : + originTypeIndex(originTypeIndex), startTime(startTime), endTime(endTime) {} + int originTypeIndex; + qint64 startTime; + qint64 endTime; +}; + +void MemoryUsageModel::loadData() +{ + QmlProfilerDataModel *simpleModel = modelManager()->qmlModel(); + if (simpleModel->isEmpty()) + return; + + qint64 currentSize = 0; + qint64 currentUsage = 0; + int currentUsageIndex = -1; + int currentJSHeapIndex = -1; + + QStack rangeStack; + + const QVector &types = simpleModel->getEventTypes(); + foreach (const QmlProfilerDataModel::QmlEventData &event, simpleModel->getEvents()) { + const QmlProfilerDataModel::QmlEventTypeData &type = types[event.typeIndex]; + while (!rangeStack.empty() && rangeStack.top().endTime < event.startTime) + rangeStack.pop(); + if (!accepted(type)) { + if (type.rangeType != QmlDebug::MaximumRangeType) { + rangeStack.push(RangeStackFrame(event.typeIndex, event.startTime, + event.startTime + event.duration)); + } + continue; + } + + if (type.detailType == QmlDebug::SmallItem || type.detailType == QmlDebug::LargeItem) { + if (!rangeStack.empty() && currentUsageIndex > -1 && + type.detailType == selectionId(currentUsageIndex) && + m_data[currentUsageIndex].originTypeIndex == rangeStack.top().originTypeIndex && + rangeStack.top().startTime < startTime(currentUsageIndex)) { + m_data[currentUsageIndex].update(event.numericData1); + currentUsage = m_data[currentUsageIndex].size; + } else { + MemoryAllocation allocation(event.typeIndex, currentUsage, + rangeStack.empty() ? -1 : rangeStack.top().originTypeIndex); + allocation.update(event.numericData1); + currentUsage = allocation.size; + + if (currentUsageIndex != -1) { + insertEnd(currentUsageIndex, + event.startTime - startTime(currentUsageIndex) - 1); + } + currentUsageIndex = insertStart(event.startTime, QmlDebug::SmallItem); + m_data.insert(currentUsageIndex, allocation); + } + } + + if (type.detailType == QmlDebug::HeapPage || type.detailType == QmlDebug::LargeItem) { + if (!rangeStack.empty() && currentJSHeapIndex > -1 && + type.detailType == selectionId(currentJSHeapIndex) && + m_data[currentJSHeapIndex].originTypeIndex == + rangeStack.top().originTypeIndex && + rangeStack.top().startTime < startTime(currentJSHeapIndex)) { + m_data[currentJSHeapIndex].update(event.numericData1); + currentSize = m_data[currentJSHeapIndex].size; + } else { + MemoryAllocation allocation(event.typeIndex, currentSize, + rangeStack.empty() ? -1 : rangeStack.top().originTypeIndex); + allocation.update(event.numericData1); + currentSize = allocation.size; + + if (currentSize > m_maxSize) + m_maxSize = currentSize; + if (currentJSHeapIndex != -1) + insertEnd(currentJSHeapIndex, + event.startTime - startTime(currentJSHeapIndex) - 1); + currentJSHeapIndex = insertStart(event.startTime, type.detailType); + m_data.insert(currentJSHeapIndex, allocation); + } + } + + updateProgress(count(), simpleModel->getEvents().count()); + } + + if (currentJSHeapIndex != -1) + insertEnd(currentJSHeapIndex, modelManager()->traceTime()->endTime() - + startTime(currentJSHeapIndex) - 1); + if (currentUsageIndex != -1) + insertEnd(currentUsageIndex, modelManager()->traceTime()->endTime() - + startTime(currentUsageIndex) - 1); + + + computeNesting(); + setExpandedRowCount(3); + setCollapsedRowCount(3); + updateProgress(1, 1); +} + +void MemoryUsageModel::clear() +{ + m_data.clear(); + m_maxSize = 1; + QmlProfilerTimelineModel::clear(); +} + +QString MemoryUsageModel::memoryTypeName(int type) +{ + switch (type) { + case QmlDebug::HeapPage: return tr("Heap Allocation"); + case QmlDebug::LargeItem: return tr("Large Item Allocation"); + case QmlDebug::SmallItem: return tr("Heap Usage"); + case QmlDebug::MaximumMemoryType: return tr("Total"); + default: return tr("Unknown"); + } +} + +MemoryUsageModel::MemoryAllocation::MemoryAllocation(int type, qint64 baseAmount, + int originTypeIndex) : + typeId(type), size(baseAmount), allocated(0), deallocated(0), allocations(0), deallocations(0), + originTypeIndex(originTypeIndex) +{ +} + +void MemoryUsageModel::MemoryAllocation::update(qint64 amount) +{ + size += amount; + if (amount < 0) { + deallocated += amount; + ++deallocations; + } else { + allocated += amount; + ++allocations; + } +} + + +} // namespace Internal +} // namespace QmlProfilerExtension diff --git a/plugins/qmlprofiler/memoryusagemodel.h b/plugins/qmlprofiler/memoryusagemodel.h new file mode 100644 index 0000000000..acd8431673 --- /dev/null +++ b/plugins/qmlprofiler/memoryusagemodel.h @@ -0,0 +1,78 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd +** All rights reserved. +** For any questions to The Qt Company, please use contact form at http://www.qt.io/contact-us +** +** This file is part of the Qt Enterprise Qt Quick Profiler Add-on. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. +** +** If you have questions regarding the use of this file, please use +** contact form at http://www.qt.io/contact-us +** +****************************************************************************/ + +#ifndef MEMORYUSAGEMODEL_H +#define MEMORYUSAGEMODEL_H + +#include "qmlprofiler/qmlprofilertimelinemodel.h" +#include "qmlprofiler/qmlprofilerdatamodel.h" + +#include +#include + +namespace QmlProfilerExtension { +namespace Internal { + +class MemoryUsageModel : public QmlProfiler::QmlProfilerTimelineModel +{ + Q_OBJECT +public: + + struct MemoryAllocation { + int typeId; + qint64 size; + qint64 allocated; + qint64 deallocated; + int allocations; + int deallocations; + int originTypeIndex; + + MemoryAllocation(int typeId = -1, qint64 baseAmount = 0, int originTypeIndex = -1); + void update(qint64 amount); + }; + + MemoryUsageModel(QmlProfiler::QmlProfilerModelManager *manager, QObject *parent = 0); + + int rowMaxValue(int rowNumber) const; + + int expandedRow(int index) const; + int collapsedRow(int index) const; + int typeId(int index) const; + QColor color(int index) const; + float relativeHeight(int index) const; + + QVariantMap location(int index) const; + + QVariantList labels() const; + QVariantMap details(int index) const; + +protected: + void loadData(); + void clear(); + +private: + static QString memoryTypeName(int type); + + QVector m_data; + qint64 m_maxSize; +}; + +} // namespace Internal +} // namespace QmlProfilerExtension + +#endif // MEMORYUSAGEMODEL_H diff --git a/plugins/qmlprofiler/pixmapcachemodel.cpp b/plugins/qmlprofiler/pixmapcachemodel.cpp new file mode 100644 index 0000000000..53b23f9f18 --- /dev/null +++ b/plugins/qmlprofiler/pixmapcachemodel.cpp @@ -0,0 +1,493 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd +** All rights reserved. +** For any questions to The Qt Company, please use contact form at http://www.qt.io/contact-us +** +** This file is part of the Qt Enterprise Qt Quick Profiler Add-on. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. +** +** If you have questions regarding the use of this file, please use +** contact form at http://www.qt.io/contact-us +** +****************************************************************************/ + +#include "pixmapcachemodel.h" +#include "qmldebug/qmlprofilereventtypes.h" +#include "qmlprofiler/qmlprofilermodelmanager.h" + +namespace QmlProfilerExtension { +namespace Internal { + +using namespace QmlProfiler; + +PixmapCacheModel::PixmapCacheModel(QmlProfilerModelManager *manager, QObject *parent) : + QmlProfilerTimelineModel(manager, QmlDebug::PixmapCacheEvent, QmlDebug::MaximumRangeType, + QmlDebug::ProfilePixmapCache, parent) +{ + m_maxCacheSize = 1; +} + +int PixmapCacheModel::rowMaxValue(int rowNumber) const +{ + if (rowNumber == 1) { + return m_maxCacheSize; + } else { + return QmlProfilerTimelineModel::rowMaxValue(rowNumber); + } +} + +int PixmapCacheModel::expandedRow(int index) const +{ + return selectionId(index) + 1; +} + +int PixmapCacheModel::collapsedRow(int index) const +{ + return m_data[index].rowNumberCollapsed; +} + +int PixmapCacheModel::typeId(int index) const +{ + return m_data[index].typeId; +} + +QColor PixmapCacheModel::color(int index) const +{ + if (m_data[index].pixmapEventType == PixmapCacheCountChanged) + return colorByHue(s_pixmapCacheCountHue); + + return colorBySelectionId(index); +} + +float PixmapCacheModel::relativeHeight(int index) const +{ + if (m_data[index].pixmapEventType == PixmapCacheCountChanged) + return (float)m_data[index].cacheSize / (float)m_maxCacheSize; + else + return 1.0f; +} + +QString getFilenameOnly(QString absUrl) +{ + int characterPos = absUrl.lastIndexOf(QLatin1Char('/'))+1; + if (characterPos < absUrl.length()) + absUrl = absUrl.mid(characterPos); + return absUrl; +} + +QVariantList PixmapCacheModel::labels() const +{ + QVariantList result; + + // Cache Size + QVariantMap element; + element.insert(QLatin1String("description"), QVariant(QLatin1String("Cache Size"))); + + element.insert(QLatin1String("id"), QVariant(0)); + result << element; + + for (int i=0; i < m_pixmaps.count(); i++) { + // Loading + QVariantMap element; + element.insert(QLatin1String("displayName"), m_pixmaps[i].url); + element.insert(QLatin1String("description"), + QVariant(getFilenameOnly(m_pixmaps[i].url))); + + element.insert(QLatin1String("id"), QVariant(i+1)); + result << element; + } + + return result; +} + +QVariantMap PixmapCacheModel::details(int index) const +{ + QVariantMap result; + const PixmapCacheEvent *ev = &m_data[index]; + + if (ev->pixmapEventType == PixmapCacheCountChanged) { + result.insert(QLatin1String("displayName"), tr("Image Cached")); + } else { + if (ev->pixmapEventType == PixmapLoadingStarted) { + result.insert(QLatin1String("displayName"), tr("Image Loaded")); + if (m_pixmaps[ev->urlIndex].sizes[ev->sizeIndex].loadState != Finished) + result.insert(tr("Result"), tr("Load Error")); + } + result.insert(tr("Duration"), QmlProfilerBaseModel::formatTime(duration(index))); + } + + result.insert(tr("Cache Size"), QString::fromLatin1("%1 px").arg(ev->cacheSize)); + result.insert(tr("File"), getFilenameOnly(m_pixmaps[ev->urlIndex].url)); + result.insert(tr("Width"), QString::fromLatin1("%1 px") + .arg(m_pixmaps[ev->urlIndex].sizes[ev->sizeIndex].size.width())); + result.insert(tr("Height"), QString::fromLatin1("%1 px") + .arg(m_pixmaps[ev->urlIndex].sizes[ev->sizeIndex].size.height())); + return result; +} + +/* Ultimately there is no way to know which cache entry a given event refers to as long as we only + * receive the pixmap URL from the application. Multiple copies of different sizes may be cached + * for each URL. However, we can apply some heuristics to make the result somewhat plausible by + * using the following assumptions: + * + * - PixmapSizeKnown will happen at most once for every cache entry. + * - PixmapSizeKnown cannot happen for entries with PixmapLoadingError and vice versa. + * - PixmapCacheCountChanged can happen for entries with PixmapLoadingError but doesn't have to. + * - Decreasing PixmapCacheCountChanged events can only happen for entries that have seen an + * increasing PixmapCacheCountChanged (but that may have happened before the trace). + * - PixmapCacheCountChanged can happen before or after PixmapSizeKnown. + * - For every PixmapLoadingFinished or PixmapLoadingError there is exactly one + * PixmapLoadingStarted event, but it may be before the trace. + * - For every PixmapLoadingStarted there is exactly one PixmapLoadingFinished or + * PixmapLoadingError, but it may be after the trace. + * - Decreasing PixmapCacheCountChanged events in the presence of corrupt cache entries are more + * likely to clear those entries than other, correctly loaded ones. + * - Increasing PixmapCacheCountChanged events are more likely to refer to correctly loaded entries + * than to ones with PixmapLoadingError. + * - PixmapLoadingFinished and PixmapLoadingError are more likely to refer to cache entries that + * have seen a PixmapLoadingStarted than to ones that haven't. + * + * For each URL we keep an ordered list of pixmaps possibly being loaded and assign new events to + * the first entry that "fits". If multiple sizes of the same pixmap are being loaded concurrently + * we generally assume that the PixmapLoadingFinished and PixmapLoadingError events occur in the + * order we learn about the existence of these sizes, subject to the above constraints. This is not + * necessarily the order the pixmaps are really loaded but it's the best we can do with the given + * information. If they're loaded sequentially the representation is correct. + */ + +void PixmapCacheModel::loadData() +{ + QmlProfilerDataModel *simpleModel = modelManager()->qmlModel(); + if (simpleModel->isEmpty()) + return; + + int lastCacheSizeEvent = -1; + int cumulatedCount = 0; + + const QVector &types = simpleModel->getEventTypes(); + foreach (const QmlProfilerDataModel::QmlEventData &event, simpleModel->getEvents()) { + const QmlProfilerDataModel::QmlEventTypeData &type = types[event.typeIndex]; + if (!accepted(type)) + continue; + + PixmapCacheEvent newEvent; + newEvent.pixmapEventType = static_cast(type.detailType); + qint64 pixmapStartTime = event.startTime; + + newEvent.urlIndex = -1; + for (QVector::const_iterator it(m_pixmaps.cend()); it != m_pixmaps.cbegin();) { + if ((--it)->url == type.location.filename) { + newEvent.urlIndex = it - m_pixmaps.cbegin(); + break; + } + } + + newEvent.sizeIndex = -1; + if (newEvent.urlIndex == -1) { + newEvent.urlIndex = m_pixmaps.count(); + m_pixmaps << Pixmap(type.location.filename); + } + + Pixmap &pixmap = m_pixmaps[newEvent.urlIndex]; + switch (newEvent.pixmapEventType) { + case PixmapSizeKnown: {// pixmap size + // Look for pixmaps for which we don't know the size, yet and which have actually been + // loaded. + for (QVector::iterator i(pixmap.sizes.begin()); + i != pixmap.sizes.end(); ++i) { + if (i->size.isValid() || i->cacheState == Uncacheable || i->cacheState == Corrupt) + continue; + + // We can't have cached it before we knew the size + Q_ASSERT(i->cacheState != Cached); + + i->size.setWidth(event.numericData1); + i->size.setHeight(event.numericData2); + newEvent.sizeIndex = i - pixmap.sizes.begin(); + break; + } + + if (newEvent.sizeIndex == -1) { + newEvent.sizeIndex = pixmap.sizes.length(); + pixmap.sizes << PixmapState(event.numericData1, event.numericData2); + } + + PixmapState &state = pixmap.sizes[newEvent.sizeIndex]; + if (state.cacheState == ToBeCached) { + lastCacheSizeEvent = updateCacheCount(lastCacheSizeEvent, pixmapStartTime, + state.size.width() * state.size.height(), newEvent, + event.typeIndex); + state.cacheState = Cached; + } + break; + } + case PixmapCacheCountChanged: {// Cache Size Changed Event + pixmapStartTime = event.startTime + 1; // delay 1 ns for proper sorting + + bool uncache = cumulatedCount > event.numericData3; + cumulatedCount = event.numericData3; + qint64 pixSize = 0; + + // First try to find a preferred pixmap, which either is Corrupt and will be uncached + // or is uncached and will be cached. + for (QVector::iterator i(pixmap.sizes.begin()); + i != pixmap.sizes.end(); ++i) { + if (uncache && i->cacheState == Corrupt) { + newEvent.sizeIndex = i - pixmap.sizes.begin(); + i->cacheState = Uncacheable; + break; + } else if (!uncache && i->cacheState == Uncached) { + newEvent.sizeIndex = i - pixmap.sizes.begin(); + if (i->size.isValid()) { + pixSize = i->size.width() * i->size.height(); + i->cacheState = Cached; + } else { + i->cacheState = ToBeCached; + } + break; + } + } + + // If none found, check for cached or ToBeCached pixmaps that shall be uncached or + // Error pixmaps that become corrupt cache entries. We also accept Initial to be + // uncached as we may have missed the matching PixmapCacheCountChanged that cached it. + if (newEvent.sizeIndex == -1) { + for (QVector::iterator i(pixmap.sizes.begin()); + i != pixmap.sizes.end(); ++i) { + if (uncache && (i->cacheState == Cached || i->cacheState == ToBeCached || + i->cacheState == Uncached)) { + newEvent.sizeIndex = i - pixmap.sizes.begin(); + if (i->size.isValid()) + pixSize = -i->size.width() * i->size.height(); + i->cacheState = Uncached; + break; + } else if (!uncache && i->cacheState == Uncacheable) { + newEvent.sizeIndex = i - pixmap.sizes.begin(); + i->cacheState = Corrupt; + break; + } + } + } + + // If that does't work, create a new entry. + if (newEvent.sizeIndex == -1) { + newEvent.sizeIndex = pixmap.sizes.length(); + pixmap.sizes << PixmapState(uncache ? Uncached : ToBeCached); + } + + lastCacheSizeEvent = updateCacheCount(lastCacheSizeEvent, pixmapStartTime, pixSize, + newEvent, event.typeIndex); + break; + } + case PixmapLoadingStarted: { // Load + // Look for a pixmap that hasn't been started, yet. There may have been a refcount + // event, which we ignore. + for (QVector::const_iterator i(pixmap.sizes.cbegin()); + i != pixmap.sizes.cend(); ++i) { + if (i->loadState == Initial) { + newEvent.sizeIndex = i - pixmap.sizes.cbegin(); + break; + } + } + if (newEvent.sizeIndex == -1) { + newEvent.sizeIndex = pixmap.sizes.length(); + pixmap.sizes << PixmapState(); + } + + PixmapState &state = pixmap.sizes[newEvent.sizeIndex]; + state.loadState = Loading; + newEvent.typeId = event.typeIndex; + state.started = insertStart(pixmapStartTime, newEvent.urlIndex + 1); + m_data.insert(state.started, newEvent); + break; + } + case PixmapLoadingFinished: + case PixmapLoadingError: { + // First try to find one that has already started + for (QVector::const_iterator i(pixmap.sizes.cbegin()); + i != pixmap.sizes.cend(); ++i) { + if (i->loadState != Loading) + continue; + // Pixmaps with known size cannot be errors and vice versa + if (newEvent.pixmapEventType == PixmapLoadingError && i->size.isValid()) + continue; + + newEvent.sizeIndex = i - pixmap.sizes.cbegin(); + break; + } + + // If none was found use any other compatible one + if (newEvent.sizeIndex == -1) { + for (QVector::const_iterator i(pixmap.sizes.cbegin()); + i != pixmap.sizes.cend(); ++i) { + if (i->loadState != Initial) + continue; + // Pixmaps with known size cannot be errors and vice versa + if (newEvent.pixmapEventType == PixmapLoadingError && i->size.isValid()) + continue; + + newEvent.sizeIndex = i - pixmap.sizes.cbegin(); + break; + } + } + + // If again none was found, create one. + if (newEvent.sizeIndex == -1) { + newEvent.sizeIndex = pixmap.sizes.length(); + pixmap.sizes << PixmapState(); + } + + PixmapState &state = pixmap.sizes[newEvent.sizeIndex]; + // If the pixmap loading wasn't started, start it at traceStartTime() + if (state.loadState == Initial) { + newEvent.pixmapEventType = PixmapLoadingStarted; + newEvent.typeId = event.typeIndex; + qint64 traceStart = modelManager()->traceTime()->startTime(); + state.started = insert(traceStart, pixmapStartTime - traceStart, + newEvent.urlIndex + 1); + m_data.insert(state.started, newEvent); + + // All other indices are wrong now as we've prepended. Fix them ... + if (lastCacheSizeEvent >= state.started) + ++lastCacheSizeEvent; + + for (int pixmapIndex = 0; pixmapIndex < m_pixmaps.count(); ++pixmapIndex) { + Pixmap &brokenPixmap = m_pixmaps[pixmapIndex]; + for (int sizeIndex = 0; sizeIndex < brokenPixmap.sizes.count(); ++sizeIndex) { + PixmapState &brokenSize = brokenPixmap.sizes[sizeIndex]; + if ((pixmapIndex != newEvent.urlIndex || sizeIndex != newEvent.sizeIndex) && + brokenSize.started >= state.started) { + ++brokenSize.started; + } + } + } + } + + insertEnd(state.started, pixmapStartTime - startTime(state.started)); + if (newEvent.pixmapEventType == PixmapLoadingError) { + state.loadState = Error; + switch (state.cacheState) { + case Uncached: + state.cacheState = Uncacheable; + break; + case ToBeCached: + state.cacheState = Corrupt; + break; + default: + // Cached cannot happen as size would have to be known and Corrupt or + // Uncacheable cannot happen as we only accept one finish or error event per + // pixmap. + Q_ASSERT(false); + } + } else { + state.loadState = Finished; + } + break; + } + default: + break; + } + + updateProgress(count(), 2 * simpleModel->getEvents().count()); + } + + if (lastCacheSizeEvent != -1) + insertEnd(lastCacheSizeEvent, modelManager()->traceTime()->endTime() - + startTime(lastCacheSizeEvent)); + + resizeUnfinishedLoads(); + + computeMaxCacheSize(); + flattenLoads(); + computeNesting(); + + updateProgress(1, 1); +} + +void PixmapCacheModel::clear() +{ + m_pixmaps.clear(); + m_maxCacheSize = 1; + m_data.clear(); + QmlProfilerTimelineModel::clear(); +} + +void PixmapCacheModel::computeMaxCacheSize() +{ + m_maxCacheSize = 1; + foreach (const PixmapCacheModel::PixmapCacheEvent &event, m_data) { + if (event.pixmapEventType == PixmapCacheModel::PixmapCacheCountChanged) { + if (event.cacheSize > m_maxCacheSize) + m_maxCacheSize = event.cacheSize; + } + } +} + +void PixmapCacheModel::resizeUnfinishedLoads() +{ + // all the "load start" events with duration 0 continue till the end of the trace + for (int i = 0; i < count(); i++) { + if (m_data[i].pixmapEventType == PixmapCacheModel::PixmapLoadingStarted && + duration(i) == 0) { + insertEnd(i, modelManager()->traceTime()->endTime() - startTime(i)); + } + } +} + +void PixmapCacheModel::flattenLoads() +{ + int collapsedRowCount = 0; + + // computes "compressed row" + QVector eventEndTimes; + for (int i = 0; i < count(); i++) { + PixmapCacheModel::PixmapCacheEvent &event = m_data[i]; + if (event.pixmapEventType == PixmapCacheModel::PixmapLoadingStarted) { + event.rowNumberCollapsed = 0; + while (eventEndTimes.count() > event.rowNumberCollapsed && + eventEndTimes[event.rowNumberCollapsed] > startTime(i)) + event.rowNumberCollapsed++; + + if (eventEndTimes.count() == event.rowNumberCollapsed) + eventEndTimes << 0; // increase stack length, proper value added below + eventEndTimes[event.rowNumberCollapsed] = endTime(i); + + // readjust to account for category empty row and bargraph + event.rowNumberCollapsed += 2; + } + if (event.rowNumberCollapsed > collapsedRowCount) + collapsedRowCount = event.rowNumberCollapsed; + } + + // Starting from 0, count is maxIndex+1 + setCollapsedRowCount(collapsedRowCount + 1); + setExpandedRowCount(m_pixmaps.count() + 2); +} + +int PixmapCacheModel::updateCacheCount(int lastCacheSizeEvent, + qint64 pixmapStartTime, qint64 pixSize, PixmapCacheEvent &newEvent, int typeId) +{ + newEvent.pixmapEventType = PixmapCacheCountChanged; + newEvent.rowNumberCollapsed = 1; + + qint64 prevSize = 0; + if (lastCacheSizeEvent != -1) { + prevSize = m_data[lastCacheSizeEvent].cacheSize; + insertEnd(lastCacheSizeEvent, pixmapStartTime - startTime(lastCacheSizeEvent)); + } + + newEvent.cacheSize = prevSize + pixSize; + newEvent.typeId = typeId; + int index = insertStart(pixmapStartTime, 0); + m_data.insert(index, newEvent); + return index; +} + + +} // namespace Internal +} // namespace QmlProfilerExtension diff --git a/plugins/qmlprofiler/pixmapcachemodel.h b/plugins/qmlprofiler/pixmapcachemodel.h new file mode 100644 index 0000000000..13dc412da1 --- /dev/null +++ b/plugins/qmlprofiler/pixmapcachemodel.h @@ -0,0 +1,123 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd +** All rights reserved. +** For any questions to The Qt Company, please use contact form at http://www.qt.io/contact-us +** +** This file is part of the Qt Enterprise Qt Quick Profiler Add-on. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. +** +** If you have questions regarding the use of this file, please use +** contact form at http://www.qt.io/contact-us +** +****************************************************************************/ + +#ifndef PIXMAPCACHEMODEL_H +#define PIXMAPCACHEMODEL_H + +#include "qmlprofiler/qmlprofilertimelinemodel.h" +#include "qmlprofiler/qmlprofilerdatamodel.h" + +#include +#include +#include + +namespace QmlProfilerExtension { +namespace Internal { + +class PixmapCacheModel : public QmlProfiler::QmlProfilerTimelineModel +{ + Q_OBJECT +public: + enum CacheState { + Uncached, // After loading started (or some other proof of existence) or after uncaching + ToBeCached, // After determining the pixmap is to be cached but before knowing its size + Cached, // After caching a pixmap or determining the size of a ToBeCached pixmap + Uncacheable, // If loading failed without ToBeCached or after a corrupt pixmap has been uncached + Corrupt // If after ToBeCached we learn that loading failed + }; + + enum LoadState { + Initial, + Loading, + Finished, + Error + }; + + struct PixmapState { + PixmapState(int width, int height, CacheState cache = Uncached) : + size(width, height), started(-1), loadState(Initial), cacheState(cache) {} + PixmapState(CacheState cache = Uncached) : started(-1), loadState(Initial), cacheState(cache) {} + QSize size; + int started; + LoadState loadState; + CacheState cacheState; + }; + + struct Pixmap { + Pixmap() {} + Pixmap(const QString &url) : url(url), sizes(1) {} + QString url; + QVector sizes; + }; + + enum PixmapEventType { + PixmapSizeKnown, + PixmapReferenceCountChanged, + PixmapCacheCountChanged, + PixmapLoadingStarted, + PixmapLoadingFinished, + PixmapLoadingError, + + MaximumPixmapEventType + }; + + struct PixmapCacheEvent { + int typeId; + PixmapEventType pixmapEventType; + int urlIndex; + int sizeIndex; + int rowNumberCollapsed; + qint64 cacheSize; + }; + + PixmapCacheModel(QmlProfiler::QmlProfilerModelManager *manager, QObject *parent = 0); + + int rowMaxValue(int rowNumber) const; + + int expandedRow(int index) const; + int collapsedRow(int index) const; + int typeId(int index) const; + QColor color(int index) const; + float relativeHeight(int index) const; + + QVariantList labels() const; + + QVariantMap details(int index) const; + +protected: + void loadData(); + void clear(); + +private: + void computeMaxCacheSize(); + void resizeUnfinishedLoads(); + void flattenLoads(); + int updateCacheCount(int lastCacheSizeEvent, qint64 startTime, qint64 pixSize, + PixmapCacheEvent &newEvent, int typeId); + + QVector m_data; + QVector m_pixmaps; + qint64 m_maxCacheSize; + + static const int s_pixmapCacheCountHue = 240; +}; + +} // namespace Internal +} // namespace QmlProfilerExtension + +#endif // PIXMAPCACHEMODEL_H diff --git a/plugins/qmlprofiler/qmlprofiler.pro b/plugins/qmlprofiler/qmlprofiler.pro new file mode 100644 index 0000000000..e892a542b7 --- /dev/null +++ b/plugins/qmlprofiler/qmlprofiler.pro @@ -0,0 +1,26 @@ +TARGET = QmlProfilerExtension +TEMPLATE = lib + +PROVIDER = Digia +include(../../qtcreatorplugin.pri) + +DEFINES += QMLPROFILEREXTENSION_LIBRARY + +# QmlProfilerExtension files + +SOURCES += qmlprofilerextensionplugin.cpp \ + scenegraphtimelinemodel.cpp \ + pixmapcachemodel.cpp \ + memoryusagemodel.cpp \ + inputeventsmodel.cpp + +HEADERS += qmlprofilerextensionplugin.h \ + qmlprofilerextension_global.h \ + qmlprofilerextensionconstants.h \ + scenegraphtimelinemodel.h \ + pixmapcachemodel.h \ + memoryusagemodel.h \ + inputeventsmodel.h + +OTHER_FILES += \ + QmlProfilerExtension.json.in diff --git a/plugins/qmlprofiler/qmlprofiler.qbs b/plugins/qmlprofiler/qmlprofiler.qbs new file mode 100644 index 0000000000..7105207e1e --- /dev/null +++ b/plugins/qmlprofiler/qmlprofiler.qbs @@ -0,0 +1,26 @@ +import qbs + +QtcCommercialPlugin { + name: "QmlProfilerExtension" + + Depends { name: "Core" } + Depends { name: "QmlProfiler" } + Depends { name: "Timeline" } + + Depends { name: "Qt.widgets" } + + files: [ + "inputeventsmodel.cpp", + "inputeventsmodel.h", + "memoryusagemodel.cpp", + "memoryusagemodel.h", + "pixmapcachemodel.cpp", + "pixmapcachemodel.h", + "qmlprofilerextensionconstants.h", + "qmlprofilerextensionplugin.cpp", + "qmlprofilerextensionplugin.h", + "qmlprofilerextension_global.h", + "scenegraphtimelinemodel.cpp", + "scenegraphtimelinemodel.h", + ] +} diff --git a/plugins/qmlprofiler/qmlprofiler_dependencies.pri b/plugins/qmlprofiler/qmlprofiler_dependencies.pri new file mode 100644 index 0000000000..7ffa4d0623 --- /dev/null +++ b/plugins/qmlprofiler/qmlprofiler_dependencies.pri @@ -0,0 +1,5 @@ +QTC_PLUGIN_NAME = QmlProfilerExtension +QTC_PLUGIN_DEPENDS += \ + qmlprofiler + +CONFIG(licensechecker): QT_PLUGIN_DEPENDS += licensechecker diff --git a/plugins/qmlprofiler/qmlprofilerextension_global.h b/plugins/qmlprofiler/qmlprofilerextension_global.h new file mode 100644 index 0000000000..0d98efe3f2 --- /dev/null +++ b/plugins/qmlprofiler/qmlprofilerextension_global.h @@ -0,0 +1,31 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd +** All rights reserved. +** For any questions to The Qt Company, please use contact form at http://www.qt.io/contact-us +** +** This file is part of the Qt Enterprise Qt Quick Profiler Add-on. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. +** +** If you have questions regarding the use of this file, please use +** contact form at http://www.qt.io/contact-us +** +****************************************************************************/ + +#ifndef QMLPROFILEREXTENSION_GLOBAL_H +#define QMLPROFILEREXTENSION_GLOBAL_H + +#include + +#if defined(QMLPROFILEREXTENSION_LIBRARY) +# define QMLPROFILEREXTENSIONSHARED_EXPORT Q_DECL_EXPORT +#else +# define QMLPROFILEREXTENSIONSHARED_EXPORT Q_DECL_IMPORT +#endif + +#endif // QMLPROFILEREXTENSION_GLOBAL_H + diff --git a/plugins/qmlprofiler/qmlprofilerextensionconstants.h b/plugins/qmlprofiler/qmlprofilerextensionconstants.h new file mode 100644 index 0000000000..4a1bedbbbb --- /dev/null +++ b/plugins/qmlprofiler/qmlprofilerextensionconstants.h @@ -0,0 +1,32 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd +** All rights reserved. +** For any questions to The Qt Company, please use contact form at http://www.qt.io/contact-us +** +** This file is part of the Qt Enterprise Qt Quick Profiler Add-on. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. +** +** If you have questions regarding the use of this file, please use +** contact form at http://www.qt.io/contact-us +** +****************************************************************************/ + +#ifndef QMLPROFILEREXTENSIONCONSTANTS_H +#define QMLPROFILEREXTENSIONCONSTANTS_H + +namespace QmlProfilerExtension { +namespace Constants { + +const char ACTION_ID[] = "QmlProfilerExtension.Action"; +const char MENU_ID[] = "QmlProfilerExtension.Menu"; + +} // namespace QmlProfilerExtension +} // namespace Constants + +#endif // QMLPROFILEREXTENSIONCONSTANTS_H + diff --git a/plugins/qmlprofiler/qmlprofilerextensionplugin.cpp b/plugins/qmlprofiler/qmlprofilerextensionplugin.cpp new file mode 100644 index 0000000000..0015b02f97 --- /dev/null +++ b/plugins/qmlprofiler/qmlprofilerextensionplugin.cpp @@ -0,0 +1,128 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd +** All rights reserved. +** For any questions to The Qt Company, please use contact form at http://www.qt.io/contact-us +** +** This file is part of the Qt Enterprise Qt Quick Profiler Add-on. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. +** +** If you have questions regarding the use of this file, please use +** contact form at http://www.qt.io/contact-us +** +****************************************************************************/ + +#include "qmlprofilerextensionplugin.h" +#include "qmlprofilerextensionconstants.h" +#include + +#ifdef LICENSECHECKER +# include +#endif + +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include + +#include + +#include "scenegraphtimelinemodel.h" +#include "pixmapcachemodel.h" +#include "memoryusagemodel.h" +#include "inputeventsmodel.h" + +using namespace QmlProfilerExtension::Internal; + +class ModelFactory : public QmlProfiler::QmlProfilerTimelineModelFactory { + Q_OBJECT +public: + QList create( + QmlProfiler::QmlProfilerModelManager *manager) + { + QList models; + models << new PixmapCacheModel(manager, this) + << new SceneGraphTimelineModel(manager, this) + << new MemoryUsageModel(manager, this) + << new InputEventsModel(manager, this); + return models; + } +}; + +QmlProfilerExtensionPlugin::QmlProfilerExtensionPlugin() +{ + // Create your members +} + +QmlProfilerExtensionPlugin::~QmlProfilerExtensionPlugin() +{ + // Unregister objects from the plugin manager's object pool + // Delete members +} + +bool QmlProfilerExtensionPlugin::initialize(const QStringList &arguments, QString *errorString) +{ + // Register objects in the plugin manager's object pool + // Load settings + // Add actions to menus + // Connect to other plugins' signals + // In the initialize method, a plugin can be sure that the plugins it + // depends on have initialized their members. + + Q_UNUSED(arguments) + Q_UNUSED(errorString) + +#ifdef LICENSECHECKER + LicenseChecker::LicenseCheckerPlugin *licenseChecker + = ExtensionSystem::PluginManager::getObject(); + + if (licenseChecker && licenseChecker->hasValidLicense()) { + if (licenseChecker->enterpriseFeatures()) + addAutoReleasedObject(new ModelFactory); + } else { + qWarning() << "Invalid license, disabling QML Profiler Enterprise features"; + } +#else // LICENSECHECKER + addAutoReleasedObject(new ModelFactory); +#endif + + return true; +} + +void QmlProfilerExtensionPlugin::extensionsInitialized() +{ + // Retrieve objects from the plugin manager's object pool + // In the extensionsInitialized method, a plugin can be sure that all + // plugins that depend on it are completely initialized. +} + +ExtensionSystem::IPlugin::ShutdownFlag QmlProfilerExtensionPlugin::aboutToShutdown() +{ + // Save settings + // Disconnect from signals that are not needed during shutdown + // Hide UI (if you add UI that is not in the main window directly) + return SynchronousShutdown; +} + +void QmlProfilerExtensionPlugin::triggerAction() +{ + QMessageBox::information(Core::ICore::mainWindow(), + tr("Action triggered"), + tr("This is an action from QmlProfilerExtension.")); +} + +#include "qmlprofilerextensionplugin.moc" diff --git a/plugins/qmlprofiler/qmlprofilerextensionplugin.h b/plugins/qmlprofiler/qmlprofilerextensionplugin.h new file mode 100644 index 0000000000..7d0ca94a80 --- /dev/null +++ b/plugins/qmlprofiler/qmlprofilerextensionplugin.h @@ -0,0 +1,50 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd +** All rights reserved. +** For any questions to The Qt Company, please use contact form at http://www.qt.io/contact-us +** +** This file is part of the Qt Enterprise Qt Quick Profiler Add-on. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. +** +** If you have questions regarding the use of this file, please use +** contact form at http://www.qt.io/contact-us +** +****************************************************************************/ + +#ifndef QMLPROFILEREXTENSION_H +#define QMLPROFILEREXTENSION_H + +#include "qmlprofilerextension_global.h" + +#include + +namespace QmlProfilerExtension { +namespace Internal { + +class QmlProfilerExtensionPlugin : public ExtensionSystem::IPlugin +{ + Q_OBJECT + Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QtCreatorPlugin" FILE "QmlProfilerExtension.json") + +public: + QmlProfilerExtensionPlugin(); + ~QmlProfilerExtensionPlugin(); + + bool initialize(const QStringList &arguments, QString *errorString); + void extensionsInitialized(); + ShutdownFlag aboutToShutdown(); + +private slots: + void triggerAction(); +}; + +} // namespace Internal +} // namespace QmlProfilerExtension + +#endif // QMLPROFILEREXTENSION_H + diff --git a/plugins/qmlprofiler/scenegraphtimelinemodel.cpp b/plugins/qmlprofiler/scenegraphtimelinemodel.cpp new file mode 100644 index 0000000000..9c7be933cc --- /dev/null +++ b/plugins/qmlprofiler/scenegraphtimelinemodel.cpp @@ -0,0 +1,304 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd +** All rights reserved. +** For any questions to The Qt Company, please use contact form at http://www.qt.io/contact-us +** +** This file is part of the Qt Enterprise Qt Quick Profiler Add-on. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. +** +** If you have questions regarding the use of this file, please use +** contact form at http://www.qt.io/contact-us +** +****************************************************************************/ + +#include "scenegraphtimelinemodel.h" +#include "qmldebug/qmlprofilereventtypes.h" +#include "qmlprofiler/qmlprofilermodelmanager.h" + +#include +#include + +namespace QmlProfilerExtension { +namespace Internal { + +using namespace QmlProfiler; + +static const char *ThreadLabels[] = { + QT_TRANSLATE_NOOP("MainView", "GUI Thread"), + QT_TRANSLATE_NOOP("MainView", "Render Thread"), + QT_TRANSLATE_NOOP("MainView", "Render Thread Details") +}; + +static const char *StageLabels[] = { + QT_TRANSLATE_NOOP("MainView", "Polish"), + QT_TRANSLATE_NOOP("MainView", "Wait"), + QT_TRANSLATE_NOOP("MainView", "GUI Thread Sync"), + QT_TRANSLATE_NOOP("MainView", "Animations"), + QT_TRANSLATE_NOOP("MainView", "Render Thread Sync"), + QT_TRANSLATE_NOOP("MainView", "Render"), + QT_TRANSLATE_NOOP("MainView", "Swap"), + QT_TRANSLATE_NOOP("MainView", "Render Preprocess"), + QT_TRANSLATE_NOOP("MainView", "Render Update"), + QT_TRANSLATE_NOOP("MainView", "Render Bind"), + QT_TRANSLATE_NOOP("MainView", "Render Render"), + QT_TRANSLATE_NOOP("MainView", "Material Compile"), + QT_TRANSLATE_NOOP("MainView", "Glyph Render"), + QT_TRANSLATE_NOOP("MainView", "Glyph Upload"), + QT_TRANSLATE_NOOP("MainView", "Texture Bind"), + QT_TRANSLATE_NOOP("MainView", "Texture Convert"), + QT_TRANSLATE_NOOP("MainView", "Texture Swizzle"), + QT_TRANSLATE_NOOP("MainView", "Texture Upload"), + QT_TRANSLATE_NOOP("MainView", "Texture Mipmap"), + QT_TRANSLATE_NOOP("MainView", "Texture Delete") +}; + +enum SceneGraphCategoryType { + SceneGraphGUIThread, + SceneGraphRenderThread, + SceneGraphRenderThreadDetails, + + MaximumSceneGraphCategoryType +}; + +Q_STATIC_ASSERT(sizeof(StageLabels) == + SceneGraphTimelineModel::MaximumSceneGraphStage * sizeof(const char *)); + +SceneGraphTimelineModel::SceneGraphTimelineModel(QmlProfilerModelManager *manager, + QObject *parent) : + QmlProfilerTimelineModel(manager, QmlDebug::SceneGraphFrame, QmlDebug::MaximumRangeType, + QmlDebug::ProfileSceneGraph, parent) +{ +} + +int SceneGraphTimelineModel::expandedRow(int index) const +{ + return selectionId(index) + 1; +} + +int SceneGraphTimelineModel::collapsedRow(int index) const +{ + return m_data[index].rowNumberCollapsed; +} + +int SceneGraphTimelineModel::typeId(int index) const +{ + return m_data[index].typeId; +} + +QColor SceneGraphTimelineModel::color(int index) const +{ + return colorBySelectionId(index); +} + +QVariantList SceneGraphTimelineModel::labels() const +{ + QVariantList result; + + for (SceneGraphStage i = MinimumSceneGraphStage; i < MaximumSceneGraphStage; + i = static_cast(i + 1)) { + QVariantMap element; + element.insert(QLatin1String("displayName"), tr(threadLabel(i))); + element.insert(QLatin1String("description"), tr(StageLabels[i])); + element.insert(QLatin1String("id"), i); + result << element; + } + + return result; +} + +QVariantMap SceneGraphTimelineModel::details(int index) const +{ + QVariantMap result; + const SceneGraphStage stage = static_cast(selectionId(index)); + + result.insert(QLatin1String("displayName"), tr(threadLabel(stage))); + result.insert(tr("Stage"), tr(StageLabels[stage])); + result.insert(tr("Duration"), QmlProfilerBaseModel::formatTime(duration(index))); + + const int glyphCount = m_data[index].glyphCount; + if (glyphCount >= 0) + result.insert(tr("Glyphs"), QString::number(glyphCount)); + + return result; +} + +void SceneGraphTimelineModel::loadData() +{ + QmlProfilerDataModel *simpleModel = modelManager()->qmlModel(); + if (simpleModel->isEmpty()) + return; + + // combine the data of several eventtypes into two rows + const QVector &types = simpleModel->getEventTypes(); + foreach (const QmlProfilerDataModel::QmlEventData &event, simpleModel->getEvents()) { + const QmlProfilerDataModel::QmlEventTypeData &type = types[event.typeIndex]; + if (!accepted(type)) + continue; + + switch ((QmlDebug::SceneGraphFrameType)type.detailType) { + case QmlDebug::SceneGraphRendererFrame: { + // Breakdown of render times. We repeat "render" here as "net" render time. It would + // look incomplete if that was left out as the printf profiler lists it, too, and people + // are apparently comparing that. Unfortunately it is somewhat redundant as the other + // parts of the breakdown are usually very short. + qint64 startTime = event.startTime - event.numericData1 - event.numericData2 - + event.numericData3 - event.numericData4; + startTime += insert(startTime, event.numericData1, event.typeIndex, RenderPreprocess); + startTime += insert(startTime, event.numericData2, event.typeIndex, RenderUpdate); + startTime += insert(startTime, event.numericData3, event.typeIndex, RenderBind); + insert(startTime, event.numericData4, event.typeIndex, RenderRender); + break; + } + case QmlDebug::SceneGraphAdaptationLayerFrame: { + qint64 startTime = event.startTime - event.numericData2 - event.numericData3; + startTime += insert(startTime, event.numericData2, event.typeIndex, GlyphRender, + event.numericData1); + insert(startTime, event.numericData3, event.typeIndex, GlyphStore, event.numericData1); + break; + } + case QmlDebug::SceneGraphContextFrame: { + insert(event.startTime - event.numericData1, event.numericData1, event.typeIndex, + Material); + break; + } + case QmlDebug::SceneGraphRenderLoopFrame: { + qint64 startTime = event.startTime - event.numericData1 - event.numericData2 - + event.numericData3; + startTime += insert(startTime, event.numericData1, event.typeIndex, + RenderThreadSync); + startTime += insert(startTime, event.numericData2, event.typeIndex, + Render); + insert(startTime, event.numericData3, event.typeIndex, Swap); + break; + } + case QmlDebug::SceneGraphTexturePrepare: { + qint64 startTime = event.startTime - event.numericData1 - event.numericData2 - + event.numericData3 - event.numericData4 - event.numericData5; + startTime += insert(startTime, event.numericData1, event.typeIndex, TextureBind); + startTime += insert(startTime, event.numericData2, event.typeIndex, TextureConvert); + startTime += insert(startTime, event.numericData3, event.typeIndex, TextureSwizzle); + startTime += insert(startTime, event.numericData4, event.typeIndex, TextureUpload); + insert(startTime, event.numericData5, event.typeIndex, TextureMipmap); + break; + } + case QmlDebug::SceneGraphTextureDeletion: { + insert(event.startTime - event.numericData1, event.numericData1, event.typeIndex, + TextureDeletion); + break; + } + case QmlDebug::SceneGraphPolishAndSync: { + qint64 startTime = event.startTime - event.numericData1 - event.numericData2 - + event.numericData3 - event.numericData4; + + startTime += insert(startTime, event.numericData1, event.typeIndex, Polish); + startTime += insert(startTime, event.numericData2, event.typeIndex, Wait); + startTime += insert(startTime, event.numericData3, event.typeIndex, GUIThreadSync); + insert(startTime, event.numericData4, event.typeIndex, Animations); + break; + } + case QmlDebug::SceneGraphWindowsAnimations: { + // GUI thread, separate animations stage + insert(event.startTime - event.numericData1, event.numericData1, event.typeIndex, + Animations); + break; + } + case QmlDebug::SceneGraphPolishFrame: { + // GUI thread, separate polish stage + insert(event.startTime - event.numericData1, event.numericData1, event.typeIndex, + Polish); + break; + } + default: break; + } + + updateProgress(count(), simpleModel->getEvents().count()); + } + + computeNesting(); + flattenLoads(); + updateProgress(1, 1); +} + +void SceneGraphTimelineModel::flattenLoads() +{ + int collapsedRowCount = 0; + + // computes "compressed row" + QVector eventEndTimes; + + for (int i = 0; i < count(); i++) { + SceneGraphEvent &event = m_data[i]; + int stage = selectionId(i); + // Don't try to put render thread events in GUI row and vice versa. + // Rows below those are free for all. + if (stage < MaximumGUIThreadStage) + event.rowNumberCollapsed = SceneGraphGUIThread; + else if (stage < MaximumRenderThreadStage) + event.rowNumberCollapsed = SceneGraphRenderThread; + else + event.rowNumberCollapsed = SceneGraphRenderThreadDetails; + + while (eventEndTimes.count() > event.rowNumberCollapsed && + eventEndTimes[event.rowNumberCollapsed] > startTime(i)) + ++event.rowNumberCollapsed; + + while (eventEndTimes.count() <= event.rowNumberCollapsed) + eventEndTimes << 0; // increase stack length, proper value added below + eventEndTimes[event.rowNumberCollapsed] = endTime(i); + + // readjust to account for category empty row + event.rowNumberCollapsed++; + if (event.rowNumberCollapsed > collapsedRowCount) + collapsedRowCount = event.rowNumberCollapsed; + } + + // Starting from 0, count is maxIndex+1 + setCollapsedRowCount(collapsedRowCount + 1); + setExpandedRowCount(MaximumSceneGraphStage + 1); +} + +/*! + * Inserts an event characterized by \a start time, \a duration, \a typeIndex, \a stage and possibly + * \a glyphCount (if it's a \c GlyphRender or \c GlyphStore event) into the scene graph model if its + * \a duration is greater than 0. Returns \a duration in that case; otherwise returns 0. + */ +qint64 SceneGraphTimelineModel::insert(qint64 start, qint64 duration, int typeIndex, + SceneGraphStage stage, int glyphCount) +{ + if (duration <= 0) + return 0; + + m_data.insert(QmlProfilerTimelineModel::insert(start, duration, stage), + SceneGraphEvent(typeIndex, glyphCount)); + return duration; +} + +const char *SceneGraphTimelineModel::threadLabel(SceneGraphStage stage) +{ + if (stage < MaximumGUIThreadStage) + return ThreadLabels[SceneGraphGUIThread]; + else if (stage < MaximumRenderThreadStage) + return ThreadLabels[SceneGraphRenderThread]; + else + return ThreadLabels[SceneGraphRenderThreadDetails]; + +} + +void SceneGraphTimelineModel::clear() +{ + m_data.clear(); + QmlProfilerTimelineModel::clear(); +} + +SceneGraphTimelineModel::SceneGraphEvent::SceneGraphEvent(int typeId, int glyphCount) : + typeId(typeId), rowNumberCollapsed(-1), glyphCount(glyphCount) +{ +} + +} // namespace Internal +} // namespace QmlProfilerExtension diff --git a/plugins/qmlprofiler/scenegraphtimelinemodel.h b/plugins/qmlprofiler/scenegraphtimelinemodel.h new file mode 100644 index 0000000000..6225963993 --- /dev/null +++ b/plugins/qmlprofiler/scenegraphtimelinemodel.h @@ -0,0 +1,107 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd +** All rights reserved. +** For any questions to The Qt Company, please use contact form at http://www.qt.io/contact-us +** +** This file is part of the Qt Enterprise Qt Quick Profiler Add-on. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. +** +** If you have questions regarding the use of this file, please use +** contact form at http://www.qt.io/contact-us +** +****************************************************************************/ + +#ifndef SCENEGRAPHTIMELINEMODEL_H +#define SCENEGRAPHTIMELINEMODEL_H + +#include "qmlprofiler/qmlprofilertimelinemodel.h" +#include "qmlprofiler/qmlprofilermodelmanager.h" +#include "qmlprofiler/qmlprofilerdatamodel.h" + +#include +#include + +namespace QmlProfilerExtension { +namespace Internal { + +class SceneGraphTimelineModel : public QmlProfiler::QmlProfilerTimelineModel +{ + Q_OBJECT +public: + enum SceneGraphStage { + MinimumSceneGraphStage = 0, + Polish = MinimumSceneGraphStage, + Wait, + GUIThreadSync, + Animations, + MaximumGUIThreadStage, + + RenderThreadSync = MaximumGUIThreadStage, + Render, + Swap, + MaximumRenderThreadStage, + + RenderPreprocess = MaximumRenderThreadStage, + RenderUpdate, + RenderBind, + RenderRender, + MaximumRenderStage, + + Material = MaximumRenderStage, + MaximumMaterialStage, + + GlyphRender = MaximumMaterialStage, + GlyphStore, + MaximumGlyphStage, + + TextureBind = MaximumGlyphStage, + TextureConvert, + TextureSwizzle, + TextureUpload, + TextureMipmap, + TextureDeletion, + MaximumTextureStage, + + MaximumSceneGraphStage = MaximumTextureStage + }; + + struct SceneGraphEvent { + SceneGraphEvent(int typeId = -1, int glyphCount = -1); + int typeId; + int rowNumberCollapsed; + int glyphCount; // only used for one event type + }; + + SceneGraphTimelineModel(QmlProfiler::QmlProfilerModelManager *manager, QObject *parent = 0); + + int expandedRow(int index) const; + int collapsedRow(int index) const; + int typeId(int index) const; + QColor color(int index) const; + + QVariantList labels() const; + + QVariantMap details(int index) const; + +protected: + void loadData(); + void clear(); + +private: + void flattenLoads(); + qint64 insert(qint64 start, qint64 duration, int typeIndex, SceneGraphStage stage, + int glyphCount = -1); + static const char *threadLabel(SceneGraphStage stage); + + QVector m_data; +}; + +} // namespace Internal +} // namespace QmlProfilerExtension + +#endif // SCENEGRAPHTIMELINEMODEL_H diff --git a/plugins/qmlprofilerextension/QmlProfilerExtension.json.in b/plugins/qmlprofilerextension/QmlProfilerExtension.json.in deleted file mode 100644 index e7154d2e85..0000000000 --- a/plugins/qmlprofilerextension/QmlProfilerExtension.json.in +++ /dev/null @@ -1,15 +0,0 @@ -{ - \"Name\" : \"QmlProfilerExtension\", - \"Version\" : \"$$QTCREATOR_VERSION\", - \"CompatVersion\" : \"$$QTCREATOR_COMPAT_VERSION\", - \"Vendor\" : \"The Qt Company Ltd\", - \"Copyright\" : \"(C) 2015 The Qt Company Ltd\", - \"License\" : [ \"Commercial Usage\", - \"\", - \"Licensees holding valid Qt Commercial licenses may use this plugin in accordance with the Qt Commercial License Agreement provided with the Software or, alternatively, in accordance with the terms contained in a written agreement between you and The Qt Company.\" - ], - \"Category\" : \"Qt Quick\", - \"Description\" : \"Qml Profiler Extension Plugin.\", - \"Url\" : \"http://www.qt.io\", - $$dependencyList -} diff --git a/plugins/qmlprofilerextension/inputeventsmodel.cpp b/plugins/qmlprofilerextension/inputeventsmodel.cpp deleted file mode 100644 index 0c77629321..0000000000 --- a/plugins/qmlprofilerextension/inputeventsmodel.cpp +++ /dev/null @@ -1,120 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 The Qt Company Ltd -** All rights reserved. -** For any questions to The Qt Company, please use contact form at http://www.qt.io/contact-us -** -** This file is part of the Qt Enterprise Qt Quick Profiler Add-on. -** -** Licensees holding valid Qt Enterprise licenses may use this file in -** accordance with the Qt Enterprise License Agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. -** -** If you have questions regarding the use of this file, please use -** contact form at http://www.qt.io/contact-us -** -****************************************************************************/ - -#include "inputeventsmodel.h" -#include "qmldebug/qmlprofilereventtypes.h" -#include "qmlprofiler/qmlprofilermodelmanager.h" - -namespace QmlProfilerExtension { -namespace Internal { - -using namespace QmlProfiler; - -InputEventsModel::InputEventsModel(QmlProfilerModelManager *manager, QObject *parent) : - QmlProfilerTimelineModel(manager, QmlDebug::Event, QmlDebug::MaximumRangeType, - QmlDebug::ProfileInputEvents, parent), - m_keyTypeId(-1), m_mouseTypeId(-1) -{ -} - -int InputEventsModel::typeId(int index) const -{ - return selectionId(index) == QmlDebug::Mouse ? m_mouseTypeId : m_keyTypeId; -} - -QColor InputEventsModel::color(int index) const -{ - return colorBySelectionId(index); -} - -QVariantList InputEventsModel::labels() const -{ - QVariantList result; - - QVariantMap element; - element.insert(QLatin1String("description"), QVariant(tr("Mouse Events"))); - element.insert(QLatin1String("id"), QVariant(QmlDebug::Mouse)); - result << element; - - element.clear(); - element.insert(QLatin1String("description"), QVariant(tr("Keyboard Events"))); - element.insert(QLatin1String("id"), QVariant(QmlDebug::Key)); - result << element; - - return result; -} - -QVariantMap InputEventsModel::details(int index) const -{ - QVariantMap result; - result.insert(QLatin1String("displayName"), - selectionId(index) == QmlDebug::Key ? tr("Keyboard Event") : tr("Mouse Event")); - result.insert(QLatin1String("Timestamp"), QmlProfilerBaseModel::formatTime(startTime(index))); - return result; -} - -int InputEventsModel::expandedRow(int index) const -{ - return selectionId(index) == QmlDebug::Mouse ? 1 : 2; -} - -int InputEventsModel::collapsedRow(int index) const -{ - Q_UNUSED(index) - return 1; -} - -void InputEventsModel::loadData() -{ - QmlProfilerDataModel *simpleModel = modelManager()->qmlModel(); - if (simpleModel->isEmpty()) - return; - - const QVector &types = simpleModel->getEventTypes(); - foreach (const QmlProfilerDataModel::QmlEventData &event, simpleModel->getEvents()) { - const QmlProfilerDataModel::QmlEventTypeData &type = types[event.typeIndex]; - if (!accepted(type)) - continue; - insert(event.startTime, 0, type.detailType); - if (type.detailType == QmlDebug::Mouse) { - if (m_mouseTypeId == -1) - m_mouseTypeId = event.typeIndex; - } else if (m_keyTypeId == -1) { - m_keyTypeId = event.typeIndex; - } - updateProgress(count(), simpleModel->getEvents().count()); - } - setCollapsedRowCount(2); - setExpandedRowCount(3); - updateProgress(1, 1); -} - -void InputEventsModel::clear() -{ - m_keyTypeId = m_mouseTypeId = -1; - QmlProfilerTimelineModel::clear(); -} - -bool InputEventsModel::accepted(const QmlProfilerDataModel::QmlEventTypeData &event) const -{ - return QmlProfilerTimelineModel::accepted(event) && - (event.detailType == QmlDebug::Mouse || event.detailType == QmlDebug::Key); -} - -} -} diff --git a/plugins/qmlprofilerextension/inputeventsmodel.h b/plugins/qmlprofilerextension/inputeventsmodel.h deleted file mode 100644 index 43a9dc4498..0000000000 --- a/plugins/qmlprofilerextension/inputeventsmodel.h +++ /dev/null @@ -1,54 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 The Qt Company Ltd -** All rights reserved. -** For any questions to The Qt Company, please use contact form at http://www.qt.io/contact-us -** -** This file is part of the Qt Enterprise Qt Quick Profiler Add-on. -** -** Licensees holding valid Qt Enterprise licenses may use this file in -** accordance with the Qt Enterprise License Agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. -** -** If you have questions regarding the use of this file, please use -** contact form at http://www.qt.io/contact-us -** -****************************************************************************/ - -#ifndef INPUTEVENTSMODEL_H -#define INPUTEVENTSMODEL_H - -#include "qmlprofiler/qmlprofilertimelinemodel.h" - -namespace QmlProfilerExtension { -namespace Internal { - -class InputEventsModel : public QmlProfiler::QmlProfilerTimelineModel -{ - Q_OBJECT - -protected: - bool accepted(const QmlProfiler::QmlProfilerDataModel::QmlEventTypeData &event) const; - -public: - InputEventsModel(QmlProfiler::QmlProfilerModelManager *manager, QObject *parent = 0); - - int typeId(int index) const; - QColor color(int index) const; - QVariantList labels() const; - QVariantMap details(int index) const; - int expandedRow(int index) const; - int collapsedRow(int index) const; - void loadData(); - void clear(); - -private: - int m_keyTypeId; - int m_mouseTypeId; - -}; - -} -} -#endif // INPUTEVENTSMODEL_H diff --git a/plugins/qmlprofilerextension/memoryusagemodel.cpp b/plugins/qmlprofilerextension/memoryusagemodel.cpp deleted file mode 100644 index 402b1e08c0..0000000000 --- a/plugins/qmlprofilerextension/memoryusagemodel.cpp +++ /dev/null @@ -1,273 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 The Qt Company Ltd -** All rights reserved. -** For any questions to The Qt Company, please use contact form at http://www.qt.io/contact-us -** -** This file is part of the Qt Enterprise Qt Quick Profiler Add-on. -** -** Licensees holding valid Qt Enterprise licenses may use this file in -** accordance with the Qt Enterprise License Agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. -** -** If you have questions regarding the use of this file, please use -** contact form at http://www.qt.io/contact-us -** -****************************************************************************/ - -#include "memoryusagemodel.h" -#include "qmldebug/qmlprofilereventtypes.h" -#include "qmlprofiler/qmlprofilermodelmanager.h" - -#include - -namespace QmlProfilerExtension { -namespace Internal { - -using namespace QmlProfiler; - -MemoryUsageModel::MemoryUsageModel(QmlProfilerModelManager *manager, QObject *parent) : - QmlProfilerTimelineModel(manager, QmlDebug::MemoryAllocation, QmlDebug::MaximumRangeType, - QmlDebug::ProfileMemory, parent) -{ - m_maxSize = 1; - announceFeatures((1ULL << mainFeature()) | QmlDebug::Constants::QML_JS_RANGE_FEATURES); -} - -int MemoryUsageModel::rowMaxValue(int rowNumber) const -{ - Q_UNUSED(rowNumber); - return m_maxSize; -} - -int MemoryUsageModel::expandedRow(int index) const -{ - int type = selectionId(index); - return (type == QmlDebug::HeapPage || type == QmlDebug::LargeItem) ? 1 : 2; -} - -int MemoryUsageModel::collapsedRow(int index) const -{ - return expandedRow(index); -} - -int MemoryUsageModel::typeId(int index) const -{ - return m_data[index].typeId; -} - -QColor MemoryUsageModel::color(int index) const -{ - return colorBySelectionId(index); -} - -float MemoryUsageModel::relativeHeight(int index) const -{ - return qMin(1.0f, (float)m_data[index].size / (float)m_maxSize); -} - -QVariantMap MemoryUsageModel::location(int index) const -{ - static const QLatin1String file("file"); - static const QLatin1String line("line"); - static const QLatin1String column("column"); - - QVariantMap result; - - int originType = m_data[index].originTypeIndex; - if (originType > -1) { - const QmlDebug::QmlEventLocation &location = - modelManager()->qmlModel()->getEventTypes().at(originType).location; - - result.insert(file, location.filename); - result.insert(line, location.line); - result.insert(column, location.column); - } - - return result; -} - -QVariantList MemoryUsageModel::labels() const -{ - QVariantList result; - - QVariantMap element; - element.insert(QLatin1String("description"), QVariant(tr("Memory Allocation"))); - element.insert(QLatin1String("id"), QVariant(QmlDebug::HeapPage)); - result << element; - - element.clear(); - element.insert(QLatin1String("description"), QVariant(tr("Memory Usage"))); - element.insert(QLatin1String("id"), QVariant(QmlDebug::SmallItem)); - result << element; - - return result; -} - -QVariantMap MemoryUsageModel::details(int index) const -{ - QVariantMap result; - const MemoryAllocation *ev = &m_data[index]; - - if (ev->allocated >= -ev->deallocated) - result.insert(QLatin1String("displayName"), tr("Memory Allocated")); - else - result.insert(QLatin1String("displayName"), tr("Memory Freed")); - - result.insert(tr("Total"), QString::fromLatin1("%1 bytes").arg(ev->size)); - if (ev->allocations > 0) { - result.insert(tr("Allocated"), QString::fromLatin1("%1 bytes").arg(ev->allocated)); - result.insert(tr("Allocations"), QString::number(ev->allocations)); - } - if (ev->deallocations > 0) { - result.insert(tr("Deallocated"), QString::fromLatin1("%1 bytes").arg(-ev->deallocated)); - result.insert(tr("Deallocations"), QString::number(ev->deallocations)); - } - result.insert(tr("Type"), QVariant(memoryTypeName(selectionId(index)))); - - if (ev->originTypeIndex != -1) { - result.insert(tr("Location"), - modelManager()->qmlModel()->getEventTypes().at(ev->originTypeIndex).displayName); - } - return result; -} - -struct RangeStackFrame { - RangeStackFrame() : originTypeIndex(-1), startTime(-1), endTime(-1) {} - RangeStackFrame(int originTypeIndex, qint64 startTime, qint64 endTime) : - originTypeIndex(originTypeIndex), startTime(startTime), endTime(endTime) {} - int originTypeIndex; - qint64 startTime; - qint64 endTime; -}; - -void MemoryUsageModel::loadData() -{ - QmlProfilerDataModel *simpleModel = modelManager()->qmlModel(); - if (simpleModel->isEmpty()) - return; - - qint64 currentSize = 0; - qint64 currentUsage = 0; - int currentUsageIndex = -1; - int currentJSHeapIndex = -1; - - QStack rangeStack; - - const QVector &types = simpleModel->getEventTypes(); - foreach (const QmlProfilerDataModel::QmlEventData &event, simpleModel->getEvents()) { - const QmlProfilerDataModel::QmlEventTypeData &type = types[event.typeIndex]; - while (!rangeStack.empty() && rangeStack.top().endTime < event.startTime) - rangeStack.pop(); - if (!accepted(type)) { - if (type.rangeType != QmlDebug::MaximumRangeType) { - rangeStack.push(RangeStackFrame(event.typeIndex, event.startTime, - event.startTime + event.duration)); - } - continue; - } - - if (type.detailType == QmlDebug::SmallItem || type.detailType == QmlDebug::LargeItem) { - if (!rangeStack.empty() && currentUsageIndex > -1 && - type.detailType == selectionId(currentUsageIndex) && - m_data[currentUsageIndex].originTypeIndex == rangeStack.top().originTypeIndex && - rangeStack.top().startTime < startTime(currentUsageIndex)) { - m_data[currentUsageIndex].update(event.numericData1); - currentUsage = m_data[currentUsageIndex].size; - } else { - MemoryAllocation allocation(event.typeIndex, currentUsage, - rangeStack.empty() ? -1 : rangeStack.top().originTypeIndex); - allocation.update(event.numericData1); - currentUsage = allocation.size; - - if (currentUsageIndex != -1) { - insertEnd(currentUsageIndex, - event.startTime - startTime(currentUsageIndex) - 1); - } - currentUsageIndex = insertStart(event.startTime, QmlDebug::SmallItem); - m_data.insert(currentUsageIndex, allocation); - } - } - - if (type.detailType == QmlDebug::HeapPage || type.detailType == QmlDebug::LargeItem) { - if (!rangeStack.empty() && currentJSHeapIndex > -1 && - type.detailType == selectionId(currentJSHeapIndex) && - m_data[currentJSHeapIndex].originTypeIndex == - rangeStack.top().originTypeIndex && - rangeStack.top().startTime < startTime(currentJSHeapIndex)) { - m_data[currentJSHeapIndex].update(event.numericData1); - currentSize = m_data[currentJSHeapIndex].size; - } else { - MemoryAllocation allocation(event.typeIndex, currentSize, - rangeStack.empty() ? -1 : rangeStack.top().originTypeIndex); - allocation.update(event.numericData1); - currentSize = allocation.size; - - if (currentSize > m_maxSize) - m_maxSize = currentSize; - if (currentJSHeapIndex != -1) - insertEnd(currentJSHeapIndex, - event.startTime - startTime(currentJSHeapIndex) - 1); - currentJSHeapIndex = insertStart(event.startTime, type.detailType); - m_data.insert(currentJSHeapIndex, allocation); - } - } - - updateProgress(count(), simpleModel->getEvents().count()); - } - - if (currentJSHeapIndex != -1) - insertEnd(currentJSHeapIndex, modelManager()->traceTime()->endTime() - - startTime(currentJSHeapIndex) - 1); - if (currentUsageIndex != -1) - insertEnd(currentUsageIndex, modelManager()->traceTime()->endTime() - - startTime(currentUsageIndex) - 1); - - - computeNesting(); - setExpandedRowCount(3); - setCollapsedRowCount(3); - updateProgress(1, 1); -} - -void MemoryUsageModel::clear() -{ - m_data.clear(); - m_maxSize = 1; - QmlProfilerTimelineModel::clear(); -} - -QString MemoryUsageModel::memoryTypeName(int type) -{ - switch (type) { - case QmlDebug::HeapPage: return tr("Heap Allocation"); - case QmlDebug::LargeItem: return tr("Large Item Allocation"); - case QmlDebug::SmallItem: return tr("Heap Usage"); - case QmlDebug::MaximumMemoryType: return tr("Total"); - default: return tr("Unknown"); - } -} - -MemoryUsageModel::MemoryAllocation::MemoryAllocation(int type, qint64 baseAmount, - int originTypeIndex) : - typeId(type), size(baseAmount), allocated(0), deallocated(0), allocations(0), deallocations(0), - originTypeIndex(originTypeIndex) -{ -} - -void MemoryUsageModel::MemoryAllocation::update(qint64 amount) -{ - size += amount; - if (amount < 0) { - deallocated += amount; - ++deallocations; - } else { - allocated += amount; - ++allocations; - } -} - - -} // namespace Internal -} // namespace QmlProfilerExtension diff --git a/plugins/qmlprofilerextension/memoryusagemodel.h b/plugins/qmlprofilerextension/memoryusagemodel.h deleted file mode 100644 index acd8431673..0000000000 --- a/plugins/qmlprofilerextension/memoryusagemodel.h +++ /dev/null @@ -1,78 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 The Qt Company Ltd -** All rights reserved. -** For any questions to The Qt Company, please use contact form at http://www.qt.io/contact-us -** -** This file is part of the Qt Enterprise Qt Quick Profiler Add-on. -** -** Licensees holding valid Qt Enterprise licenses may use this file in -** accordance with the Qt Enterprise License Agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. -** -** If you have questions regarding the use of this file, please use -** contact form at http://www.qt.io/contact-us -** -****************************************************************************/ - -#ifndef MEMORYUSAGEMODEL_H -#define MEMORYUSAGEMODEL_H - -#include "qmlprofiler/qmlprofilertimelinemodel.h" -#include "qmlprofiler/qmlprofilerdatamodel.h" - -#include -#include - -namespace QmlProfilerExtension { -namespace Internal { - -class MemoryUsageModel : public QmlProfiler::QmlProfilerTimelineModel -{ - Q_OBJECT -public: - - struct MemoryAllocation { - int typeId; - qint64 size; - qint64 allocated; - qint64 deallocated; - int allocations; - int deallocations; - int originTypeIndex; - - MemoryAllocation(int typeId = -1, qint64 baseAmount = 0, int originTypeIndex = -1); - void update(qint64 amount); - }; - - MemoryUsageModel(QmlProfiler::QmlProfilerModelManager *manager, QObject *parent = 0); - - int rowMaxValue(int rowNumber) const; - - int expandedRow(int index) const; - int collapsedRow(int index) const; - int typeId(int index) const; - QColor color(int index) const; - float relativeHeight(int index) const; - - QVariantMap location(int index) const; - - QVariantList labels() const; - QVariantMap details(int index) const; - -protected: - void loadData(); - void clear(); - -private: - static QString memoryTypeName(int type); - - QVector m_data; - qint64 m_maxSize; -}; - -} // namespace Internal -} // namespace QmlProfilerExtension - -#endif // MEMORYUSAGEMODEL_H diff --git a/plugins/qmlprofilerextension/pixmapcachemodel.cpp b/plugins/qmlprofilerextension/pixmapcachemodel.cpp deleted file mode 100644 index 53b23f9f18..0000000000 --- a/plugins/qmlprofilerextension/pixmapcachemodel.cpp +++ /dev/null @@ -1,493 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 The Qt Company Ltd -** All rights reserved. -** For any questions to The Qt Company, please use contact form at http://www.qt.io/contact-us -** -** This file is part of the Qt Enterprise Qt Quick Profiler Add-on. -** -** Licensees holding valid Qt Enterprise licenses may use this file in -** accordance with the Qt Enterprise License Agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. -** -** If you have questions regarding the use of this file, please use -** contact form at http://www.qt.io/contact-us -** -****************************************************************************/ - -#include "pixmapcachemodel.h" -#include "qmldebug/qmlprofilereventtypes.h" -#include "qmlprofiler/qmlprofilermodelmanager.h" - -namespace QmlProfilerExtension { -namespace Internal { - -using namespace QmlProfiler; - -PixmapCacheModel::PixmapCacheModel(QmlProfilerModelManager *manager, QObject *parent) : - QmlProfilerTimelineModel(manager, QmlDebug::PixmapCacheEvent, QmlDebug::MaximumRangeType, - QmlDebug::ProfilePixmapCache, parent) -{ - m_maxCacheSize = 1; -} - -int PixmapCacheModel::rowMaxValue(int rowNumber) const -{ - if (rowNumber == 1) { - return m_maxCacheSize; - } else { - return QmlProfilerTimelineModel::rowMaxValue(rowNumber); - } -} - -int PixmapCacheModel::expandedRow(int index) const -{ - return selectionId(index) + 1; -} - -int PixmapCacheModel::collapsedRow(int index) const -{ - return m_data[index].rowNumberCollapsed; -} - -int PixmapCacheModel::typeId(int index) const -{ - return m_data[index].typeId; -} - -QColor PixmapCacheModel::color(int index) const -{ - if (m_data[index].pixmapEventType == PixmapCacheCountChanged) - return colorByHue(s_pixmapCacheCountHue); - - return colorBySelectionId(index); -} - -float PixmapCacheModel::relativeHeight(int index) const -{ - if (m_data[index].pixmapEventType == PixmapCacheCountChanged) - return (float)m_data[index].cacheSize / (float)m_maxCacheSize; - else - return 1.0f; -} - -QString getFilenameOnly(QString absUrl) -{ - int characterPos = absUrl.lastIndexOf(QLatin1Char('/'))+1; - if (characterPos < absUrl.length()) - absUrl = absUrl.mid(characterPos); - return absUrl; -} - -QVariantList PixmapCacheModel::labels() const -{ - QVariantList result; - - // Cache Size - QVariantMap element; - element.insert(QLatin1String("description"), QVariant(QLatin1String("Cache Size"))); - - element.insert(QLatin1String("id"), QVariant(0)); - result << element; - - for (int i=0; i < m_pixmaps.count(); i++) { - // Loading - QVariantMap element; - element.insert(QLatin1String("displayName"), m_pixmaps[i].url); - element.insert(QLatin1String("description"), - QVariant(getFilenameOnly(m_pixmaps[i].url))); - - element.insert(QLatin1String("id"), QVariant(i+1)); - result << element; - } - - return result; -} - -QVariantMap PixmapCacheModel::details(int index) const -{ - QVariantMap result; - const PixmapCacheEvent *ev = &m_data[index]; - - if (ev->pixmapEventType == PixmapCacheCountChanged) { - result.insert(QLatin1String("displayName"), tr("Image Cached")); - } else { - if (ev->pixmapEventType == PixmapLoadingStarted) { - result.insert(QLatin1String("displayName"), tr("Image Loaded")); - if (m_pixmaps[ev->urlIndex].sizes[ev->sizeIndex].loadState != Finished) - result.insert(tr("Result"), tr("Load Error")); - } - result.insert(tr("Duration"), QmlProfilerBaseModel::formatTime(duration(index))); - } - - result.insert(tr("Cache Size"), QString::fromLatin1("%1 px").arg(ev->cacheSize)); - result.insert(tr("File"), getFilenameOnly(m_pixmaps[ev->urlIndex].url)); - result.insert(tr("Width"), QString::fromLatin1("%1 px") - .arg(m_pixmaps[ev->urlIndex].sizes[ev->sizeIndex].size.width())); - result.insert(tr("Height"), QString::fromLatin1("%1 px") - .arg(m_pixmaps[ev->urlIndex].sizes[ev->sizeIndex].size.height())); - return result; -} - -/* Ultimately there is no way to know which cache entry a given event refers to as long as we only - * receive the pixmap URL from the application. Multiple copies of different sizes may be cached - * for each URL. However, we can apply some heuristics to make the result somewhat plausible by - * using the following assumptions: - * - * - PixmapSizeKnown will happen at most once for every cache entry. - * - PixmapSizeKnown cannot happen for entries with PixmapLoadingError and vice versa. - * - PixmapCacheCountChanged can happen for entries with PixmapLoadingError but doesn't have to. - * - Decreasing PixmapCacheCountChanged events can only happen for entries that have seen an - * increasing PixmapCacheCountChanged (but that may have happened before the trace). - * - PixmapCacheCountChanged can happen before or after PixmapSizeKnown. - * - For every PixmapLoadingFinished or PixmapLoadingError there is exactly one - * PixmapLoadingStarted event, but it may be before the trace. - * - For every PixmapLoadingStarted there is exactly one PixmapLoadingFinished or - * PixmapLoadingError, but it may be after the trace. - * - Decreasing PixmapCacheCountChanged events in the presence of corrupt cache entries are more - * likely to clear those entries than other, correctly loaded ones. - * - Increasing PixmapCacheCountChanged events are more likely to refer to correctly loaded entries - * than to ones with PixmapLoadingError. - * - PixmapLoadingFinished and PixmapLoadingError are more likely to refer to cache entries that - * have seen a PixmapLoadingStarted than to ones that haven't. - * - * For each URL we keep an ordered list of pixmaps possibly being loaded and assign new events to - * the first entry that "fits". If multiple sizes of the same pixmap are being loaded concurrently - * we generally assume that the PixmapLoadingFinished and PixmapLoadingError events occur in the - * order we learn about the existence of these sizes, subject to the above constraints. This is not - * necessarily the order the pixmaps are really loaded but it's the best we can do with the given - * information. If they're loaded sequentially the representation is correct. - */ - -void PixmapCacheModel::loadData() -{ - QmlProfilerDataModel *simpleModel = modelManager()->qmlModel(); - if (simpleModel->isEmpty()) - return; - - int lastCacheSizeEvent = -1; - int cumulatedCount = 0; - - const QVector &types = simpleModel->getEventTypes(); - foreach (const QmlProfilerDataModel::QmlEventData &event, simpleModel->getEvents()) { - const QmlProfilerDataModel::QmlEventTypeData &type = types[event.typeIndex]; - if (!accepted(type)) - continue; - - PixmapCacheEvent newEvent; - newEvent.pixmapEventType = static_cast(type.detailType); - qint64 pixmapStartTime = event.startTime; - - newEvent.urlIndex = -1; - for (QVector::const_iterator it(m_pixmaps.cend()); it != m_pixmaps.cbegin();) { - if ((--it)->url == type.location.filename) { - newEvent.urlIndex = it - m_pixmaps.cbegin(); - break; - } - } - - newEvent.sizeIndex = -1; - if (newEvent.urlIndex == -1) { - newEvent.urlIndex = m_pixmaps.count(); - m_pixmaps << Pixmap(type.location.filename); - } - - Pixmap &pixmap = m_pixmaps[newEvent.urlIndex]; - switch (newEvent.pixmapEventType) { - case PixmapSizeKnown: {// pixmap size - // Look for pixmaps for which we don't know the size, yet and which have actually been - // loaded. - for (QVector::iterator i(pixmap.sizes.begin()); - i != pixmap.sizes.end(); ++i) { - if (i->size.isValid() || i->cacheState == Uncacheable || i->cacheState == Corrupt) - continue; - - // We can't have cached it before we knew the size - Q_ASSERT(i->cacheState != Cached); - - i->size.setWidth(event.numericData1); - i->size.setHeight(event.numericData2); - newEvent.sizeIndex = i - pixmap.sizes.begin(); - break; - } - - if (newEvent.sizeIndex == -1) { - newEvent.sizeIndex = pixmap.sizes.length(); - pixmap.sizes << PixmapState(event.numericData1, event.numericData2); - } - - PixmapState &state = pixmap.sizes[newEvent.sizeIndex]; - if (state.cacheState == ToBeCached) { - lastCacheSizeEvent = updateCacheCount(lastCacheSizeEvent, pixmapStartTime, - state.size.width() * state.size.height(), newEvent, - event.typeIndex); - state.cacheState = Cached; - } - break; - } - case PixmapCacheCountChanged: {// Cache Size Changed Event - pixmapStartTime = event.startTime + 1; // delay 1 ns for proper sorting - - bool uncache = cumulatedCount > event.numericData3; - cumulatedCount = event.numericData3; - qint64 pixSize = 0; - - // First try to find a preferred pixmap, which either is Corrupt and will be uncached - // or is uncached and will be cached. - for (QVector::iterator i(pixmap.sizes.begin()); - i != pixmap.sizes.end(); ++i) { - if (uncache && i->cacheState == Corrupt) { - newEvent.sizeIndex = i - pixmap.sizes.begin(); - i->cacheState = Uncacheable; - break; - } else if (!uncache && i->cacheState == Uncached) { - newEvent.sizeIndex = i - pixmap.sizes.begin(); - if (i->size.isValid()) { - pixSize = i->size.width() * i->size.height(); - i->cacheState = Cached; - } else { - i->cacheState = ToBeCached; - } - break; - } - } - - // If none found, check for cached or ToBeCached pixmaps that shall be uncached or - // Error pixmaps that become corrupt cache entries. We also accept Initial to be - // uncached as we may have missed the matching PixmapCacheCountChanged that cached it. - if (newEvent.sizeIndex == -1) { - for (QVector::iterator i(pixmap.sizes.begin()); - i != pixmap.sizes.end(); ++i) { - if (uncache && (i->cacheState == Cached || i->cacheState == ToBeCached || - i->cacheState == Uncached)) { - newEvent.sizeIndex = i - pixmap.sizes.begin(); - if (i->size.isValid()) - pixSize = -i->size.width() * i->size.height(); - i->cacheState = Uncached; - break; - } else if (!uncache && i->cacheState == Uncacheable) { - newEvent.sizeIndex = i - pixmap.sizes.begin(); - i->cacheState = Corrupt; - break; - } - } - } - - // If that does't work, create a new entry. - if (newEvent.sizeIndex == -1) { - newEvent.sizeIndex = pixmap.sizes.length(); - pixmap.sizes << PixmapState(uncache ? Uncached : ToBeCached); - } - - lastCacheSizeEvent = updateCacheCount(lastCacheSizeEvent, pixmapStartTime, pixSize, - newEvent, event.typeIndex); - break; - } - case PixmapLoadingStarted: { // Load - // Look for a pixmap that hasn't been started, yet. There may have been a refcount - // event, which we ignore. - for (QVector::const_iterator i(pixmap.sizes.cbegin()); - i != pixmap.sizes.cend(); ++i) { - if (i->loadState == Initial) { - newEvent.sizeIndex = i - pixmap.sizes.cbegin(); - break; - } - } - if (newEvent.sizeIndex == -1) { - newEvent.sizeIndex = pixmap.sizes.length(); - pixmap.sizes << PixmapState(); - } - - PixmapState &state = pixmap.sizes[newEvent.sizeIndex]; - state.loadState = Loading; - newEvent.typeId = event.typeIndex; - state.started = insertStart(pixmapStartTime, newEvent.urlIndex + 1); - m_data.insert(state.started, newEvent); - break; - } - case PixmapLoadingFinished: - case PixmapLoadingError: { - // First try to find one that has already started - for (QVector::const_iterator i(pixmap.sizes.cbegin()); - i != pixmap.sizes.cend(); ++i) { - if (i->loadState != Loading) - continue; - // Pixmaps with known size cannot be errors and vice versa - if (newEvent.pixmapEventType == PixmapLoadingError && i->size.isValid()) - continue; - - newEvent.sizeIndex = i - pixmap.sizes.cbegin(); - break; - } - - // If none was found use any other compatible one - if (newEvent.sizeIndex == -1) { - for (QVector::const_iterator i(pixmap.sizes.cbegin()); - i != pixmap.sizes.cend(); ++i) { - if (i->loadState != Initial) - continue; - // Pixmaps with known size cannot be errors and vice versa - if (newEvent.pixmapEventType == PixmapLoadingError && i->size.isValid()) - continue; - - newEvent.sizeIndex = i - pixmap.sizes.cbegin(); - break; - } - } - - // If again none was found, create one. - if (newEvent.sizeIndex == -1) { - newEvent.sizeIndex = pixmap.sizes.length(); - pixmap.sizes << PixmapState(); - } - - PixmapState &state = pixmap.sizes[newEvent.sizeIndex]; - // If the pixmap loading wasn't started, start it at traceStartTime() - if (state.loadState == Initial) { - newEvent.pixmapEventType = PixmapLoadingStarted; - newEvent.typeId = event.typeIndex; - qint64 traceStart = modelManager()->traceTime()->startTime(); - state.started = insert(traceStart, pixmapStartTime - traceStart, - newEvent.urlIndex + 1); - m_data.insert(state.started, newEvent); - - // All other indices are wrong now as we've prepended. Fix them ... - if (lastCacheSizeEvent >= state.started) - ++lastCacheSizeEvent; - - for (int pixmapIndex = 0; pixmapIndex < m_pixmaps.count(); ++pixmapIndex) { - Pixmap &brokenPixmap = m_pixmaps[pixmapIndex]; - for (int sizeIndex = 0; sizeIndex < brokenPixmap.sizes.count(); ++sizeIndex) { - PixmapState &brokenSize = brokenPixmap.sizes[sizeIndex]; - if ((pixmapIndex != newEvent.urlIndex || sizeIndex != newEvent.sizeIndex) && - brokenSize.started >= state.started) { - ++brokenSize.started; - } - } - } - } - - insertEnd(state.started, pixmapStartTime - startTime(state.started)); - if (newEvent.pixmapEventType == PixmapLoadingError) { - state.loadState = Error; - switch (state.cacheState) { - case Uncached: - state.cacheState = Uncacheable; - break; - case ToBeCached: - state.cacheState = Corrupt; - break; - default: - // Cached cannot happen as size would have to be known and Corrupt or - // Uncacheable cannot happen as we only accept one finish or error event per - // pixmap. - Q_ASSERT(false); - } - } else { - state.loadState = Finished; - } - break; - } - default: - break; - } - - updateProgress(count(), 2 * simpleModel->getEvents().count()); - } - - if (lastCacheSizeEvent != -1) - insertEnd(lastCacheSizeEvent, modelManager()->traceTime()->endTime() - - startTime(lastCacheSizeEvent)); - - resizeUnfinishedLoads(); - - computeMaxCacheSize(); - flattenLoads(); - computeNesting(); - - updateProgress(1, 1); -} - -void PixmapCacheModel::clear() -{ - m_pixmaps.clear(); - m_maxCacheSize = 1; - m_data.clear(); - QmlProfilerTimelineModel::clear(); -} - -void PixmapCacheModel::computeMaxCacheSize() -{ - m_maxCacheSize = 1; - foreach (const PixmapCacheModel::PixmapCacheEvent &event, m_data) { - if (event.pixmapEventType == PixmapCacheModel::PixmapCacheCountChanged) { - if (event.cacheSize > m_maxCacheSize) - m_maxCacheSize = event.cacheSize; - } - } -} - -void PixmapCacheModel::resizeUnfinishedLoads() -{ - // all the "load start" events with duration 0 continue till the end of the trace - for (int i = 0; i < count(); i++) { - if (m_data[i].pixmapEventType == PixmapCacheModel::PixmapLoadingStarted && - duration(i) == 0) { - insertEnd(i, modelManager()->traceTime()->endTime() - startTime(i)); - } - } -} - -void PixmapCacheModel::flattenLoads() -{ - int collapsedRowCount = 0; - - // computes "compressed row" - QVector eventEndTimes; - for (int i = 0; i < count(); i++) { - PixmapCacheModel::PixmapCacheEvent &event = m_data[i]; - if (event.pixmapEventType == PixmapCacheModel::PixmapLoadingStarted) { - event.rowNumberCollapsed = 0; - while (eventEndTimes.count() > event.rowNumberCollapsed && - eventEndTimes[event.rowNumberCollapsed] > startTime(i)) - event.rowNumberCollapsed++; - - if (eventEndTimes.count() == event.rowNumberCollapsed) - eventEndTimes << 0; // increase stack length, proper value added below - eventEndTimes[event.rowNumberCollapsed] = endTime(i); - - // readjust to account for category empty row and bargraph - event.rowNumberCollapsed += 2; - } - if (event.rowNumberCollapsed > collapsedRowCount) - collapsedRowCount = event.rowNumberCollapsed; - } - - // Starting from 0, count is maxIndex+1 - setCollapsedRowCount(collapsedRowCount + 1); - setExpandedRowCount(m_pixmaps.count() + 2); -} - -int PixmapCacheModel::updateCacheCount(int lastCacheSizeEvent, - qint64 pixmapStartTime, qint64 pixSize, PixmapCacheEvent &newEvent, int typeId) -{ - newEvent.pixmapEventType = PixmapCacheCountChanged; - newEvent.rowNumberCollapsed = 1; - - qint64 prevSize = 0; - if (lastCacheSizeEvent != -1) { - prevSize = m_data[lastCacheSizeEvent].cacheSize; - insertEnd(lastCacheSizeEvent, pixmapStartTime - startTime(lastCacheSizeEvent)); - } - - newEvent.cacheSize = prevSize + pixSize; - newEvent.typeId = typeId; - int index = insertStart(pixmapStartTime, 0); - m_data.insert(index, newEvent); - return index; -} - - -} // namespace Internal -} // namespace QmlProfilerExtension diff --git a/plugins/qmlprofilerextension/pixmapcachemodel.h b/plugins/qmlprofilerextension/pixmapcachemodel.h deleted file mode 100644 index 13dc412da1..0000000000 --- a/plugins/qmlprofilerextension/pixmapcachemodel.h +++ /dev/null @@ -1,123 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 The Qt Company Ltd -** All rights reserved. -** For any questions to The Qt Company, please use contact form at http://www.qt.io/contact-us -** -** This file is part of the Qt Enterprise Qt Quick Profiler Add-on. -** -** Licensees holding valid Qt Enterprise licenses may use this file in -** accordance with the Qt Enterprise License Agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. -** -** If you have questions regarding the use of this file, please use -** contact form at http://www.qt.io/contact-us -** -****************************************************************************/ - -#ifndef PIXMAPCACHEMODEL_H -#define PIXMAPCACHEMODEL_H - -#include "qmlprofiler/qmlprofilertimelinemodel.h" -#include "qmlprofiler/qmlprofilerdatamodel.h" - -#include -#include -#include - -namespace QmlProfilerExtension { -namespace Internal { - -class PixmapCacheModel : public QmlProfiler::QmlProfilerTimelineModel -{ - Q_OBJECT -public: - enum CacheState { - Uncached, // After loading started (or some other proof of existence) or after uncaching - ToBeCached, // After determining the pixmap is to be cached but before knowing its size - Cached, // After caching a pixmap or determining the size of a ToBeCached pixmap - Uncacheable, // If loading failed without ToBeCached or after a corrupt pixmap has been uncached - Corrupt // If after ToBeCached we learn that loading failed - }; - - enum LoadState { - Initial, - Loading, - Finished, - Error - }; - - struct PixmapState { - PixmapState(int width, int height, CacheState cache = Uncached) : - size(width, height), started(-1), loadState(Initial), cacheState(cache) {} - PixmapState(CacheState cache = Uncached) : started(-1), loadState(Initial), cacheState(cache) {} - QSize size; - int started; - LoadState loadState; - CacheState cacheState; - }; - - struct Pixmap { - Pixmap() {} - Pixmap(const QString &url) : url(url), sizes(1) {} - QString url; - QVector sizes; - }; - - enum PixmapEventType { - PixmapSizeKnown, - PixmapReferenceCountChanged, - PixmapCacheCountChanged, - PixmapLoadingStarted, - PixmapLoadingFinished, - PixmapLoadingError, - - MaximumPixmapEventType - }; - - struct PixmapCacheEvent { - int typeId; - PixmapEventType pixmapEventType; - int urlIndex; - int sizeIndex; - int rowNumberCollapsed; - qint64 cacheSize; - }; - - PixmapCacheModel(QmlProfiler::QmlProfilerModelManager *manager, QObject *parent = 0); - - int rowMaxValue(int rowNumber) const; - - int expandedRow(int index) const; - int collapsedRow(int index) const; - int typeId(int index) const; - QColor color(int index) const; - float relativeHeight(int index) const; - - QVariantList labels() const; - - QVariantMap details(int index) const; - -protected: - void loadData(); - void clear(); - -private: - void computeMaxCacheSize(); - void resizeUnfinishedLoads(); - void flattenLoads(); - int updateCacheCount(int lastCacheSizeEvent, qint64 startTime, qint64 pixSize, - PixmapCacheEvent &newEvent, int typeId); - - QVector m_data; - QVector m_pixmaps; - qint64 m_maxCacheSize; - - static const int s_pixmapCacheCountHue = 240; -}; - -} // namespace Internal -} // namespace QmlProfilerExtension - -#endif // PIXMAPCACHEMODEL_H diff --git a/plugins/qmlprofilerextension/qmlprofilerextension.pro b/plugins/qmlprofilerextension/qmlprofilerextension.pro deleted file mode 100644 index e39499280a..0000000000 --- a/plugins/qmlprofilerextension/qmlprofilerextension.pro +++ /dev/null @@ -1,27 +0,0 @@ -TARGET = QmlProfilerExtension -TEMPLATE = lib - -PROVIDER = Digia -include(../../qtcreatorplugin.pri) -include(qmlprofilerextension_dependencies.pri) - -DEFINES += QMLPROFILEREXTENSION_LIBRARY - -# QmlProfilerExtension files - -SOURCES += qmlprofilerextensionplugin.cpp \ - scenegraphtimelinemodel.cpp \ - pixmapcachemodel.cpp \ - memoryusagemodel.cpp \ - inputeventsmodel.cpp - -HEADERS += qmlprofilerextensionplugin.h \ - qmlprofilerextension_global.h \ - qmlprofilerextensionconstants.h \ - scenegraphtimelinemodel.h \ - pixmapcachemodel.h \ - memoryusagemodel.h \ - inputeventsmodel.h - -OTHER_FILES += \ - QmlProfilerExtension.json.in diff --git a/plugins/qmlprofilerextension/qmlprofilerextension.qbs b/plugins/qmlprofilerextension/qmlprofilerextension.qbs deleted file mode 100644 index 7105207e1e..0000000000 --- a/plugins/qmlprofilerextension/qmlprofilerextension.qbs +++ /dev/null @@ -1,26 +0,0 @@ -import qbs - -QtcCommercialPlugin { - name: "QmlProfilerExtension" - - Depends { name: "Core" } - Depends { name: "QmlProfiler" } - Depends { name: "Timeline" } - - Depends { name: "Qt.widgets" } - - files: [ - "inputeventsmodel.cpp", - "inputeventsmodel.h", - "memoryusagemodel.cpp", - "memoryusagemodel.h", - "pixmapcachemodel.cpp", - "pixmapcachemodel.h", - "qmlprofilerextensionconstants.h", - "qmlprofilerextensionplugin.cpp", - "qmlprofilerextensionplugin.h", - "qmlprofilerextension_global.h", - "scenegraphtimelinemodel.cpp", - "scenegraphtimelinemodel.h", - ] -} diff --git a/plugins/qmlprofilerextension/qmlprofilerextension_dependencies.pri b/plugins/qmlprofilerextension/qmlprofilerextension_dependencies.pri deleted file mode 100644 index 7ffa4d0623..0000000000 --- a/plugins/qmlprofilerextension/qmlprofilerextension_dependencies.pri +++ /dev/null @@ -1,5 +0,0 @@ -QTC_PLUGIN_NAME = QmlProfilerExtension -QTC_PLUGIN_DEPENDS += \ - qmlprofiler - -CONFIG(licensechecker): QT_PLUGIN_DEPENDS += licensechecker diff --git a/plugins/qmlprofilerextension/qmlprofilerextension_global.h b/plugins/qmlprofilerextension/qmlprofilerextension_global.h deleted file mode 100644 index 0d98efe3f2..0000000000 --- a/plugins/qmlprofilerextension/qmlprofilerextension_global.h +++ /dev/null @@ -1,31 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 The Qt Company Ltd -** All rights reserved. -** For any questions to The Qt Company, please use contact form at http://www.qt.io/contact-us -** -** This file is part of the Qt Enterprise Qt Quick Profiler Add-on. -** -** Licensees holding valid Qt Enterprise licenses may use this file in -** accordance with the Qt Enterprise License Agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. -** -** If you have questions regarding the use of this file, please use -** contact form at http://www.qt.io/contact-us -** -****************************************************************************/ - -#ifndef QMLPROFILEREXTENSION_GLOBAL_H -#define QMLPROFILEREXTENSION_GLOBAL_H - -#include - -#if defined(QMLPROFILEREXTENSION_LIBRARY) -# define QMLPROFILEREXTENSIONSHARED_EXPORT Q_DECL_EXPORT -#else -# define QMLPROFILEREXTENSIONSHARED_EXPORT Q_DECL_IMPORT -#endif - -#endif // QMLPROFILEREXTENSION_GLOBAL_H - diff --git a/plugins/qmlprofilerextension/qmlprofilerextensionconstants.h b/plugins/qmlprofilerextension/qmlprofilerextensionconstants.h deleted file mode 100644 index 4a1bedbbbb..0000000000 --- a/plugins/qmlprofilerextension/qmlprofilerextensionconstants.h +++ /dev/null @@ -1,32 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 The Qt Company Ltd -** All rights reserved. -** For any questions to The Qt Company, please use contact form at http://www.qt.io/contact-us -** -** This file is part of the Qt Enterprise Qt Quick Profiler Add-on. -** -** Licensees holding valid Qt Enterprise licenses may use this file in -** accordance with the Qt Enterprise License Agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. -** -** If you have questions regarding the use of this file, please use -** contact form at http://www.qt.io/contact-us -** -****************************************************************************/ - -#ifndef QMLPROFILEREXTENSIONCONSTANTS_H -#define QMLPROFILEREXTENSIONCONSTANTS_H - -namespace QmlProfilerExtension { -namespace Constants { - -const char ACTION_ID[] = "QmlProfilerExtension.Action"; -const char MENU_ID[] = "QmlProfilerExtension.Menu"; - -} // namespace QmlProfilerExtension -} // namespace Constants - -#endif // QMLPROFILEREXTENSIONCONSTANTS_H - diff --git a/plugins/qmlprofilerextension/qmlprofilerextensionplugin.cpp b/plugins/qmlprofilerextension/qmlprofilerextensionplugin.cpp deleted file mode 100644 index 0015b02f97..0000000000 --- a/plugins/qmlprofilerextension/qmlprofilerextensionplugin.cpp +++ /dev/null @@ -1,128 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 The Qt Company Ltd -** All rights reserved. -** For any questions to The Qt Company, please use contact form at http://www.qt.io/contact-us -** -** This file is part of the Qt Enterprise Qt Quick Profiler Add-on. -** -** Licensees holding valid Qt Enterprise licenses may use this file in -** accordance with the Qt Enterprise License Agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. -** -** If you have questions regarding the use of this file, please use -** contact form at http://www.qt.io/contact-us -** -****************************************************************************/ - -#include "qmlprofilerextensionplugin.h" -#include "qmlprofilerextensionconstants.h" -#include - -#ifdef LICENSECHECKER -# include -#endif - -#include -#include -#include -#include -#include -#include - -#include - -#include -#include -#include -#include -#include - -#include - -#include "scenegraphtimelinemodel.h" -#include "pixmapcachemodel.h" -#include "memoryusagemodel.h" -#include "inputeventsmodel.h" - -using namespace QmlProfilerExtension::Internal; - -class ModelFactory : public QmlProfiler::QmlProfilerTimelineModelFactory { - Q_OBJECT -public: - QList create( - QmlProfiler::QmlProfilerModelManager *manager) - { - QList models; - models << new PixmapCacheModel(manager, this) - << new SceneGraphTimelineModel(manager, this) - << new MemoryUsageModel(manager, this) - << new InputEventsModel(manager, this); - return models; - } -}; - -QmlProfilerExtensionPlugin::QmlProfilerExtensionPlugin() -{ - // Create your members -} - -QmlProfilerExtensionPlugin::~QmlProfilerExtensionPlugin() -{ - // Unregister objects from the plugin manager's object pool - // Delete members -} - -bool QmlProfilerExtensionPlugin::initialize(const QStringList &arguments, QString *errorString) -{ - // Register objects in the plugin manager's object pool - // Load settings - // Add actions to menus - // Connect to other plugins' signals - // In the initialize method, a plugin can be sure that the plugins it - // depends on have initialized their members. - - Q_UNUSED(arguments) - Q_UNUSED(errorString) - -#ifdef LICENSECHECKER - LicenseChecker::LicenseCheckerPlugin *licenseChecker - = ExtensionSystem::PluginManager::getObject(); - - if (licenseChecker && licenseChecker->hasValidLicense()) { - if (licenseChecker->enterpriseFeatures()) - addAutoReleasedObject(new ModelFactory); - } else { - qWarning() << "Invalid license, disabling QML Profiler Enterprise features"; - } -#else // LICENSECHECKER - addAutoReleasedObject(new ModelFactory); -#endif - - return true; -} - -void QmlProfilerExtensionPlugin::extensionsInitialized() -{ - // Retrieve objects from the plugin manager's object pool - // In the extensionsInitialized method, a plugin can be sure that all - // plugins that depend on it are completely initialized. -} - -ExtensionSystem::IPlugin::ShutdownFlag QmlProfilerExtensionPlugin::aboutToShutdown() -{ - // Save settings - // Disconnect from signals that are not needed during shutdown - // Hide UI (if you add UI that is not in the main window directly) - return SynchronousShutdown; -} - -void QmlProfilerExtensionPlugin::triggerAction() -{ - QMessageBox::information(Core::ICore::mainWindow(), - tr("Action triggered"), - tr("This is an action from QmlProfilerExtension.")); -} - -#include "qmlprofilerextensionplugin.moc" diff --git a/plugins/qmlprofilerextension/qmlprofilerextensionplugin.h b/plugins/qmlprofilerextension/qmlprofilerextensionplugin.h deleted file mode 100644 index 7d0ca94a80..0000000000 --- a/plugins/qmlprofilerextension/qmlprofilerextensionplugin.h +++ /dev/null @@ -1,50 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 The Qt Company Ltd -** All rights reserved. -** For any questions to The Qt Company, please use contact form at http://www.qt.io/contact-us -** -** This file is part of the Qt Enterprise Qt Quick Profiler Add-on. -** -** Licensees holding valid Qt Enterprise licenses may use this file in -** accordance with the Qt Enterprise License Agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. -** -** If you have questions regarding the use of this file, please use -** contact form at http://www.qt.io/contact-us -** -****************************************************************************/ - -#ifndef QMLPROFILEREXTENSION_H -#define QMLPROFILEREXTENSION_H - -#include "qmlprofilerextension_global.h" - -#include - -namespace QmlProfilerExtension { -namespace Internal { - -class QmlProfilerExtensionPlugin : public ExtensionSystem::IPlugin -{ - Q_OBJECT - Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QtCreatorPlugin" FILE "QmlProfilerExtension.json") - -public: - QmlProfilerExtensionPlugin(); - ~QmlProfilerExtensionPlugin(); - - bool initialize(const QStringList &arguments, QString *errorString); - void extensionsInitialized(); - ShutdownFlag aboutToShutdown(); - -private slots: - void triggerAction(); -}; - -} // namespace Internal -} // namespace QmlProfilerExtension - -#endif // QMLPROFILEREXTENSION_H - diff --git a/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp b/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp deleted file mode 100644 index 9c7be933cc..0000000000 --- a/plugins/qmlprofilerextension/scenegraphtimelinemodel.cpp +++ /dev/null @@ -1,304 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 The Qt Company Ltd -** All rights reserved. -** For any questions to The Qt Company, please use contact form at http://www.qt.io/contact-us -** -** This file is part of the Qt Enterprise Qt Quick Profiler Add-on. -** -** Licensees holding valid Qt Enterprise licenses may use this file in -** accordance with the Qt Enterprise License Agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. -** -** If you have questions regarding the use of this file, please use -** contact form at http://www.qt.io/contact-us -** -****************************************************************************/ - -#include "scenegraphtimelinemodel.h" -#include "qmldebug/qmlprofilereventtypes.h" -#include "qmlprofiler/qmlprofilermodelmanager.h" - -#include -#include - -namespace QmlProfilerExtension { -namespace Internal { - -using namespace QmlProfiler; - -static const char *ThreadLabels[] = { - QT_TRANSLATE_NOOP("MainView", "GUI Thread"), - QT_TRANSLATE_NOOP("MainView", "Render Thread"), - QT_TRANSLATE_NOOP("MainView", "Render Thread Details") -}; - -static const char *StageLabels[] = { - QT_TRANSLATE_NOOP("MainView", "Polish"), - QT_TRANSLATE_NOOP("MainView", "Wait"), - QT_TRANSLATE_NOOP("MainView", "GUI Thread Sync"), - QT_TRANSLATE_NOOP("MainView", "Animations"), - QT_TRANSLATE_NOOP("MainView", "Render Thread Sync"), - QT_TRANSLATE_NOOP("MainView", "Render"), - QT_TRANSLATE_NOOP("MainView", "Swap"), - QT_TRANSLATE_NOOP("MainView", "Render Preprocess"), - QT_TRANSLATE_NOOP("MainView", "Render Update"), - QT_TRANSLATE_NOOP("MainView", "Render Bind"), - QT_TRANSLATE_NOOP("MainView", "Render Render"), - QT_TRANSLATE_NOOP("MainView", "Material Compile"), - QT_TRANSLATE_NOOP("MainView", "Glyph Render"), - QT_TRANSLATE_NOOP("MainView", "Glyph Upload"), - QT_TRANSLATE_NOOP("MainView", "Texture Bind"), - QT_TRANSLATE_NOOP("MainView", "Texture Convert"), - QT_TRANSLATE_NOOP("MainView", "Texture Swizzle"), - QT_TRANSLATE_NOOP("MainView", "Texture Upload"), - QT_TRANSLATE_NOOP("MainView", "Texture Mipmap"), - QT_TRANSLATE_NOOP("MainView", "Texture Delete") -}; - -enum SceneGraphCategoryType { - SceneGraphGUIThread, - SceneGraphRenderThread, - SceneGraphRenderThreadDetails, - - MaximumSceneGraphCategoryType -}; - -Q_STATIC_ASSERT(sizeof(StageLabels) == - SceneGraphTimelineModel::MaximumSceneGraphStage * sizeof(const char *)); - -SceneGraphTimelineModel::SceneGraphTimelineModel(QmlProfilerModelManager *manager, - QObject *parent) : - QmlProfilerTimelineModel(manager, QmlDebug::SceneGraphFrame, QmlDebug::MaximumRangeType, - QmlDebug::ProfileSceneGraph, parent) -{ -} - -int SceneGraphTimelineModel::expandedRow(int index) const -{ - return selectionId(index) + 1; -} - -int SceneGraphTimelineModel::collapsedRow(int index) const -{ - return m_data[index].rowNumberCollapsed; -} - -int SceneGraphTimelineModel::typeId(int index) const -{ - return m_data[index].typeId; -} - -QColor SceneGraphTimelineModel::color(int index) const -{ - return colorBySelectionId(index); -} - -QVariantList SceneGraphTimelineModel::labels() const -{ - QVariantList result; - - for (SceneGraphStage i = MinimumSceneGraphStage; i < MaximumSceneGraphStage; - i = static_cast(i + 1)) { - QVariantMap element; - element.insert(QLatin1String("displayName"), tr(threadLabel(i))); - element.insert(QLatin1String("description"), tr(StageLabels[i])); - element.insert(QLatin1String("id"), i); - result << element; - } - - return result; -} - -QVariantMap SceneGraphTimelineModel::details(int index) const -{ - QVariantMap result; - const SceneGraphStage stage = static_cast(selectionId(index)); - - result.insert(QLatin1String("displayName"), tr(threadLabel(stage))); - result.insert(tr("Stage"), tr(StageLabels[stage])); - result.insert(tr("Duration"), QmlProfilerBaseModel::formatTime(duration(index))); - - const int glyphCount = m_data[index].glyphCount; - if (glyphCount >= 0) - result.insert(tr("Glyphs"), QString::number(glyphCount)); - - return result; -} - -void SceneGraphTimelineModel::loadData() -{ - QmlProfilerDataModel *simpleModel = modelManager()->qmlModel(); - if (simpleModel->isEmpty()) - return; - - // combine the data of several eventtypes into two rows - const QVector &types = simpleModel->getEventTypes(); - foreach (const QmlProfilerDataModel::QmlEventData &event, simpleModel->getEvents()) { - const QmlProfilerDataModel::QmlEventTypeData &type = types[event.typeIndex]; - if (!accepted(type)) - continue; - - switch ((QmlDebug::SceneGraphFrameType)type.detailType) { - case QmlDebug::SceneGraphRendererFrame: { - // Breakdown of render times. We repeat "render" here as "net" render time. It would - // look incomplete if that was left out as the printf profiler lists it, too, and people - // are apparently comparing that. Unfortunately it is somewhat redundant as the other - // parts of the breakdown are usually very short. - qint64 startTime = event.startTime - event.numericData1 - event.numericData2 - - event.numericData3 - event.numericData4; - startTime += insert(startTime, event.numericData1, event.typeIndex, RenderPreprocess); - startTime += insert(startTime, event.numericData2, event.typeIndex, RenderUpdate); - startTime += insert(startTime, event.numericData3, event.typeIndex, RenderBind); - insert(startTime, event.numericData4, event.typeIndex, RenderRender); - break; - } - case QmlDebug::SceneGraphAdaptationLayerFrame: { - qint64 startTime = event.startTime - event.numericData2 - event.numericData3; - startTime += insert(startTime, event.numericData2, event.typeIndex, GlyphRender, - event.numericData1); - insert(startTime, event.numericData3, event.typeIndex, GlyphStore, event.numericData1); - break; - } - case QmlDebug::SceneGraphContextFrame: { - insert(event.startTime - event.numericData1, event.numericData1, event.typeIndex, - Material); - break; - } - case QmlDebug::SceneGraphRenderLoopFrame: { - qint64 startTime = event.startTime - event.numericData1 - event.numericData2 - - event.numericData3; - startTime += insert(startTime, event.numericData1, event.typeIndex, - RenderThreadSync); - startTime += insert(startTime, event.numericData2, event.typeIndex, - Render); - insert(startTime, event.numericData3, event.typeIndex, Swap); - break; - } - case QmlDebug::SceneGraphTexturePrepare: { - qint64 startTime = event.startTime - event.numericData1 - event.numericData2 - - event.numericData3 - event.numericData4 - event.numericData5; - startTime += insert(startTime, event.numericData1, event.typeIndex, TextureBind); - startTime += insert(startTime, event.numericData2, event.typeIndex, TextureConvert); - startTime += insert(startTime, event.numericData3, event.typeIndex, TextureSwizzle); - startTime += insert(startTime, event.numericData4, event.typeIndex, TextureUpload); - insert(startTime, event.numericData5, event.typeIndex, TextureMipmap); - break; - } - case QmlDebug::SceneGraphTextureDeletion: { - insert(event.startTime - event.numericData1, event.numericData1, event.typeIndex, - TextureDeletion); - break; - } - case QmlDebug::SceneGraphPolishAndSync: { - qint64 startTime = event.startTime - event.numericData1 - event.numericData2 - - event.numericData3 - event.numericData4; - - startTime += insert(startTime, event.numericData1, event.typeIndex, Polish); - startTime += insert(startTime, event.numericData2, event.typeIndex, Wait); - startTime += insert(startTime, event.numericData3, event.typeIndex, GUIThreadSync); - insert(startTime, event.numericData4, event.typeIndex, Animations); - break; - } - case QmlDebug::SceneGraphWindowsAnimations: { - // GUI thread, separate animations stage - insert(event.startTime - event.numericData1, event.numericData1, event.typeIndex, - Animations); - break; - } - case QmlDebug::SceneGraphPolishFrame: { - // GUI thread, separate polish stage - insert(event.startTime - event.numericData1, event.numericData1, event.typeIndex, - Polish); - break; - } - default: break; - } - - updateProgress(count(), simpleModel->getEvents().count()); - } - - computeNesting(); - flattenLoads(); - updateProgress(1, 1); -} - -void SceneGraphTimelineModel::flattenLoads() -{ - int collapsedRowCount = 0; - - // computes "compressed row" - QVector eventEndTimes; - - for (int i = 0; i < count(); i++) { - SceneGraphEvent &event = m_data[i]; - int stage = selectionId(i); - // Don't try to put render thread events in GUI row and vice versa. - // Rows below those are free for all. - if (stage < MaximumGUIThreadStage) - event.rowNumberCollapsed = SceneGraphGUIThread; - else if (stage < MaximumRenderThreadStage) - event.rowNumberCollapsed = SceneGraphRenderThread; - else - event.rowNumberCollapsed = SceneGraphRenderThreadDetails; - - while (eventEndTimes.count() > event.rowNumberCollapsed && - eventEndTimes[event.rowNumberCollapsed] > startTime(i)) - ++event.rowNumberCollapsed; - - while (eventEndTimes.count() <= event.rowNumberCollapsed) - eventEndTimes << 0; // increase stack length, proper value added below - eventEndTimes[event.rowNumberCollapsed] = endTime(i); - - // readjust to account for category empty row - event.rowNumberCollapsed++; - if (event.rowNumberCollapsed > collapsedRowCount) - collapsedRowCount = event.rowNumberCollapsed; - } - - // Starting from 0, count is maxIndex+1 - setCollapsedRowCount(collapsedRowCount + 1); - setExpandedRowCount(MaximumSceneGraphStage + 1); -} - -/*! - * Inserts an event characterized by \a start time, \a duration, \a typeIndex, \a stage and possibly - * \a glyphCount (if it's a \c GlyphRender or \c GlyphStore event) into the scene graph model if its - * \a duration is greater than 0. Returns \a duration in that case; otherwise returns 0. - */ -qint64 SceneGraphTimelineModel::insert(qint64 start, qint64 duration, int typeIndex, - SceneGraphStage stage, int glyphCount) -{ - if (duration <= 0) - return 0; - - m_data.insert(QmlProfilerTimelineModel::insert(start, duration, stage), - SceneGraphEvent(typeIndex, glyphCount)); - return duration; -} - -const char *SceneGraphTimelineModel::threadLabel(SceneGraphStage stage) -{ - if (stage < MaximumGUIThreadStage) - return ThreadLabels[SceneGraphGUIThread]; - else if (stage < MaximumRenderThreadStage) - return ThreadLabels[SceneGraphRenderThread]; - else - return ThreadLabels[SceneGraphRenderThreadDetails]; - -} - -void SceneGraphTimelineModel::clear() -{ - m_data.clear(); - QmlProfilerTimelineModel::clear(); -} - -SceneGraphTimelineModel::SceneGraphEvent::SceneGraphEvent(int typeId, int glyphCount) : - typeId(typeId), rowNumberCollapsed(-1), glyphCount(glyphCount) -{ -} - -} // namespace Internal -} // namespace QmlProfilerExtension diff --git a/plugins/qmlprofilerextension/scenegraphtimelinemodel.h b/plugins/qmlprofilerextension/scenegraphtimelinemodel.h deleted file mode 100644 index 6225963993..0000000000 --- a/plugins/qmlprofilerextension/scenegraphtimelinemodel.h +++ /dev/null @@ -1,107 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 The Qt Company Ltd -** All rights reserved. -** For any questions to The Qt Company, please use contact form at http://www.qt.io/contact-us -** -** This file is part of the Qt Enterprise Qt Quick Profiler Add-on. -** -** Licensees holding valid Qt Enterprise licenses may use this file in -** accordance with the Qt Enterprise License Agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. -** -** If you have questions regarding the use of this file, please use -** contact form at http://www.qt.io/contact-us -** -****************************************************************************/ - -#ifndef SCENEGRAPHTIMELINEMODEL_H -#define SCENEGRAPHTIMELINEMODEL_H - -#include "qmlprofiler/qmlprofilertimelinemodel.h" -#include "qmlprofiler/qmlprofilermodelmanager.h" -#include "qmlprofiler/qmlprofilerdatamodel.h" - -#include -#include - -namespace QmlProfilerExtension { -namespace Internal { - -class SceneGraphTimelineModel : public QmlProfiler::QmlProfilerTimelineModel -{ - Q_OBJECT -public: - enum SceneGraphStage { - MinimumSceneGraphStage = 0, - Polish = MinimumSceneGraphStage, - Wait, - GUIThreadSync, - Animations, - MaximumGUIThreadStage, - - RenderThreadSync = MaximumGUIThreadStage, - Render, - Swap, - MaximumRenderThreadStage, - - RenderPreprocess = MaximumRenderThreadStage, - RenderUpdate, - RenderBind, - RenderRender, - MaximumRenderStage, - - Material = MaximumRenderStage, - MaximumMaterialStage, - - GlyphRender = MaximumMaterialStage, - GlyphStore, - MaximumGlyphStage, - - TextureBind = MaximumGlyphStage, - TextureConvert, - TextureSwizzle, - TextureUpload, - TextureMipmap, - TextureDeletion, - MaximumTextureStage, - - MaximumSceneGraphStage = MaximumTextureStage - }; - - struct SceneGraphEvent { - SceneGraphEvent(int typeId = -1, int glyphCount = -1); - int typeId; - int rowNumberCollapsed; - int glyphCount; // only used for one event type - }; - - SceneGraphTimelineModel(QmlProfiler::QmlProfilerModelManager *manager, QObject *parent = 0); - - int expandedRow(int index) const; - int collapsedRow(int index) const; - int typeId(int index) const; - QColor color(int index) const; - - QVariantList labels() const; - - QVariantMap details(int index) const; - -protected: - void loadData(); - void clear(); - -private: - void flattenLoads(); - qint64 insert(qint64 start, qint64 duration, int typeIndex, SceneGraphStage stage, - int glyphCount = -1); - static const char *threadLabel(SceneGraphStage stage); - - QVector m_data; -}; - -} // namespace Internal -} // namespace QmlProfilerExtension - -#endif // SCENEGRAPHTIMELINEMODEL_H diff --git a/qmlprofiler.pro b/qmlprofiler.pro index 337b062559..4cff3f101a 100644 --- a/qmlprofiler.pro +++ b/qmlprofiler.pro @@ -1,6 +1,6 @@ TEMPLATE = subdirs CONFIG += ordered -SUBDIRS += plugins/qmlprofilerextension +SUBDIRS += plugins/qmlprofiler QMAKE_EXTRA_TARGETS = docs install_docs # dummy targets for consistency -- cgit v1.2.3