diff options
author | Christiaan Janssen <christiaan.janssen@nokia.com> | 2011-06-29 15:05:45 +0200 |
---|---|---|
committer | Christiaan Janssen <christiaan.janssen@nokia.com> | 2011-07-04 13:20:36 +0200 |
commit | c5d6bc49e5d621cd9f5903268fee2341a269d83d (patch) | |
tree | f6988bd8705e259c1bb87bbf294f471ad098d89a /src/plugins | |
parent | c172e9ed6529615b334867bd2f3205dabadbba5e (diff) | |
download | qt-creator-c5d6bc49e5d621cd9f5903268fee2341a269d83d.tar.gz |
QmlProfiler: refactored the event views into a single class
Change-Id: I4fd193490c42894da73951afcf50e40a44abaa07
Reviewed-on: http://codereview.qt.nokia.com/1019
Reviewed-by: Christiaan Janssen <christiaan.janssen@nokia.com>
Diffstat (limited to 'src/plugins')
-rw-r--r-- | src/plugins/qmlprofiler/qmlprofiler.pro | 13 | ||||
-rw-r--r-- | src/plugins/qmlprofiler/qmlprofilercalleeview.cpp | 292 | ||||
-rw-r--r-- | src/plugins/qmlprofiler/qmlprofilercalleeview.h | 71 | ||||
-rw-r--r-- | src/plugins/qmlprofiler/qmlprofilercallerview.cpp | 288 | ||||
-rw-r--r-- | src/plugins/qmlprofiler/qmlprofilercallerview.h | 71 | ||||
-rw-r--r-- | src/plugins/qmlprofiler/qmlprofilereventtypes.h | 20 | ||||
-rw-r--r-- | src/plugins/qmlprofiler/qmlprofilereventview.cpp | 544 | ||||
-rw-r--r-- | src/plugins/qmlprofiler/qmlprofilereventview.h | 161 | ||||
-rw-r--r-- | src/plugins/qmlprofiler/qmlprofilersummaryview.cpp | 283 | ||||
-rw-r--r-- | src/plugins/qmlprofiler/qmlprofilersummaryview.h | 80 | ||||
-rw-r--r-- | src/plugins/qmlprofiler/qmlprofilertool.cpp | 60 | ||||
-rw-r--r-- | src/plugins/qmlprofiler/qmlprofilertraceclient.cpp | 12 | ||||
-rw-r--r-- | src/plugins/qmlprofiler/qmlprofilertraceclient.h | 22 |
13 files changed, 771 insertions, 1146 deletions
diff --git a/src/plugins/qmlprofiler/qmlprofiler.pro b/src/plugins/qmlprofiler/qmlprofiler.pro index 1aa41fbe83..9cf9360f73 100644 --- a/src/plugins/qmlprofiler/qmlprofiler.pro +++ b/src/plugins/qmlprofiler/qmlprofiler.pro @@ -23,14 +23,12 @@ SOURCES += \ tracewindow.cpp \ timelineview.cpp \ qmlprofilerattachdialog.cpp \ - qmlprofilersummaryview.cpp \ qmlprojectanalyzerruncontrolfactory.cpp \ localqmlprofilerrunner.cpp \ codaqmlprofilerrunner.cpp \ remotelinuxqmlprofilerrunner.cpp \ - qmlprofilercalleeview.cpp \ - qmlprofilercallerview.cpp \ - qmlprofilertraceclient.cpp + qmlprofilertraceclient.cpp \ + qmlprofilereventview.cpp HEADERS += \ qmlprofilerconstants.h \ @@ -41,15 +39,14 @@ HEADERS += \ tracewindow.h \ timelineview.h \ qmlprofilerattachdialog.h \ - qmlprofilersummaryview.h \ qmlprojectanalyzerruncontrolfactory.h \ abstractqmlprofilerrunner.h \ localqmlprofilerrunner.h \ codaqmlprofilerrunner.h \ remotelinuxqmlprofilerrunner.h \ - qmlprofilercalleeview.h \ - qmlprofilercallerview.h \ - qmlprofilertraceclient.h + qmlprofilertraceclient.h \ + qmlprofilereventview.h \ + qmlprofilereventtypes.h RESOURCES += \ qml/qml.qrc diff --git a/src/plugins/qmlprofiler/qmlprofilercalleeview.cpp b/src/plugins/qmlprofiler/qmlprofilercalleeview.cpp deleted file mode 100644 index 71fd7677b9..0000000000 --- a/src/plugins/qmlprofiler/qmlprofilercalleeview.cpp +++ /dev/null @@ -1,292 +0,0 @@ -/************************************************************************** -** -** This file is part of Qt Creator -** -** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies). -** -** Contact: Nokia Corporation (info@qt.nokia.com) -** -** No Commercial Usage -** -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at info@qt.nokia.com. -** -**************************************************************************/ - -#include "qmlprofilercalleeview.h" - -#include <QtCore/QUrl> -#include <QtCore/QHash> - -#include <QtGui/QHeaderView> -#include <QtGui/QStandardItemModel> - -using namespace QmlProfiler::Internal; - -struct BindingData -{ - BindingData() : - displayname(0), filename(0), location(0), details(0), - line(-1), rangeType(-1), level(-1), childrenHash(0), parentBinding(0) {} - - ~BindingData() { - delete displayname; - delete filename; - delete location; - delete childrenHash; - } - QString *displayname; - QString *filename; - QString *location; - QString *details; - int line; - int rangeType; - qint64 level; - QHash<QString, BindingData *> *childrenHash; - - // reference to parent binding stored in the hash - BindingData *parentBinding; -}; - -typedef QHash<QString, BindingData *> BindingHash; - -enum ItemRole { - LocationRole = Qt::UserRole+1, - FilenameRole = Qt::UserRole+2, - LineRole = Qt::UserRole+3 -}; - -class QmlProfilerCalleeView::QmlProfilerCalleeViewPrivate -{ -public: - QmlProfilerCalleeViewPrivate(QmlProfilerCalleeView *qq) : q(qq) {} - - void recursiveClearHash(BindingHash *hash); - void buildModelFromHash( BindingHash *hash, QStandardItem *parentItem ); - - QmlProfilerCalleeView *q; - - QStandardItemModel *m_model; -// ToDo: avoid unnecessary allocations by using global hash -// BindingHash m_globalHash; - BindingHash m_rootHash; - QList<BindingData *> m_bindingBuffer; -}; - -QmlProfilerCalleeView::QmlProfilerCalleeView(QWidget *parent) : - QTreeView(parent), d(new QmlProfilerCalleeViewPrivate(this)) -{ - setObjectName("QmlProfilerCalleeView"); - setRootIsDecorated(true); - header()->setResizeMode(QHeaderView::Interactive); - header()->setMinimumSectionSize(50); - setSortingEnabled(false); - setFrameStyle(QFrame::NoFrame); - - d->m_model = new QStandardItemModel(this); - - setModel(d->m_model); - - d->m_model->setColumnCount(3); - setHeaderLabels(); - - connect(this,SIGNAL(clicked(QModelIndex)), this,SLOT(jumpToItem(QModelIndex))); -} - -QmlProfilerCalleeView::~QmlProfilerCalleeView() -{ - clean(); - delete d->m_model; -} - -void QmlProfilerCalleeView::clean() -{ - d->m_model->clear(); - d->m_model->setColumnCount(3); - - // clean the hashes - d->recursiveClearHash(&d->m_rootHash); - - setHeaderLabels(); - setSortingEnabled(false); -} - -void QmlProfilerCalleeView::addRangedEvent(int type, int nestingLevel, int nestingInType, qint64 startTime, qint64 length, - const QStringList &data, const QString &fileName, int line) -{ - Q_UNUSED(startTime); - Q_UNUSED(nestingInType); - Q_UNUSED(length); - - const QChar colon = QLatin1Char(':'); - QString localName, displayName, location, details; - - if (fileName.isEmpty()) { - displayName = tr("<bytecode>"); - location = QLatin1String("--"); - - } else { - localName = QUrl(fileName).toLocalFile(); - displayName = localName.mid(localName.lastIndexOf(QChar('/')) + 1) + colon + QString::number(line); - location = fileName+colon+QString::number(line); - } - - if (data.isEmpty()) - details = tr("Source code not available"); - else - details = data.join(" ").replace('\n'," "); - - // ToDo: instead of allocating each new event, store them in the global hash - BindingData *newBinding = new BindingData; - newBinding->displayname = new QString(displayName); - newBinding->filename = new QString(fileName); - newBinding->line = line; - newBinding->level = nestingLevel; - newBinding->rangeType = type; - newBinding->location = new QString(location); - newBinding->details = new QString(details); - newBinding->childrenHash = 0; - - d->m_bindingBuffer.prepend(newBinding); - - if (nestingLevel == 1) { - // top level: insert buffered stuff - BindingHash *currentHash = &(d->m_rootHash); - BindingData *lastBinding = 0; - int lastLevel = 0; - - while (d->m_bindingBuffer.length()) { - BindingData *bindingInfo = d->m_bindingBuffer.at(0); - // find the data's place - if (bindingInfo->level > lastLevel) { - currentHash = lastBinding ? lastBinding->childrenHash : &(d->m_rootHash); - bindingInfo->parentBinding = lastBinding; - ++lastLevel; - } else if (bindingInfo->level == lastLevel) { - bindingInfo->parentBinding = lastBinding->parentBinding; - } else if (bindingInfo->level < lastLevel) { - while (bindingInfo->level < lastLevel) { - bindingInfo->parentBinding = lastBinding->parentBinding ? lastBinding->parentBinding->parentBinding : 0; - currentHash = bindingInfo->parentBinding ? bindingInfo->parentBinding->childrenHash : &(d->m_rootHash); - --lastLevel; - } - } - - BindingHash::iterator it = currentHash->find(*bindingInfo->location); - if (it == currentHash->end()) { - bindingInfo->childrenHash = new BindingHash; - currentHash->insert(*bindingInfo->location, bindingInfo); - lastBinding = bindingInfo; - } else { - lastBinding = it.value(); - delete bindingInfo; - } - - d->m_bindingBuffer.removeFirst(); - } - } -} - -void QmlProfilerCalleeView::complete() -{ - // build the model from the hashed data - d->buildModelFromHash( &d->m_rootHash, d->m_model->invisibleRootItem()); - - expandAll(); - resizeColumnToContents(0); - resizeColumnToContents(1); -} - -void QmlProfilerCalleeView::jumpToItem(const QModelIndex &index) -{ - QStandardItem *clickedItem = d->m_model->itemFromIndex(index); - QStandardItem *infoItem; - if (clickedItem->parent()) - infoItem = clickedItem->parent()->child(clickedItem->row(), 0); - else - infoItem = d->m_model->item(index.row(), 0); - - int line = infoItem->data(LineRole).toInt(); - if (line == -1) - return; - QString fileName = infoItem->data(FilenameRole).toString(); - emit gotoSourceLocation(fileName, line); -} - -void QmlProfilerCalleeView::setHeaderLabels() -{ - d->m_model->setHeaderData(0, Qt::Horizontal, QVariant(tr("Location"))); - d->m_model->setHeaderData(1, Qt::Horizontal, QVariant(tr("Type"))); - d->m_model->setHeaderData(2, Qt::Horizontal, QVariant(tr("Details"))); -} - -void QmlProfilerCalleeView::QmlProfilerCalleeViewPrivate::recursiveClearHash(BindingHash *hash) { - QHashIterator<QString, BindingData *> it(*hash); - while (it.hasNext()) { - it.next(); - if (it.value()->childrenHash) - recursiveClearHash(it.value()->childrenHash); - delete it.value(); - } - hash->clear(); -} - -inline QString nameForType(int typeNumber) -{ - switch (typeNumber) { - case 0: return QmlProfilerCalleeView::tr("Paint"); - case 1: return QmlProfilerCalleeView::tr("Compile"); - case 2: return QmlProfilerCalleeView::tr("Create"); - case 3: return QmlProfilerCalleeView::tr("Binding"); - case 4: return QmlProfilerCalleeView::tr("Signal"); - } - return QString(); -} - -void QmlProfilerCalleeView::QmlProfilerCalleeViewPrivate::buildModelFromHash( BindingHash *hash, QStandardItem *parentItem ) -{ - QHashIterator<QString, BindingData *> it(*hash); - - while (it.hasNext()) { - it.next(); - BindingData *binding = it.value(); - - QStandardItem *nameColumn = new QStandardItem(*binding->displayname); - nameColumn->setEditable(false); - - QStandardItem *typeColumn = new QStandardItem(nameForType(binding->rangeType)); - typeColumn->setEditable(false); - - QStandardItem *detailsColumn = new QStandardItem(*binding->details); - detailsColumn->setEditable(false); - - QStandardItem *firstColumn = nameColumn; - firstColumn->setData(QVariant(*binding->location),LocationRole); - firstColumn->setData(QVariant(*binding->filename),FilenameRole); - firstColumn->setData(QVariant(binding->line),LineRole); - - QList<QStandardItem *> newRow; - newRow << nameColumn << typeColumn << detailsColumn; - parentItem->appendRow(newRow); - if (!binding->childrenHash->isEmpty()) - buildModelFromHash(binding->childrenHash, nameColumn); - } -} diff --git a/src/plugins/qmlprofiler/qmlprofilercalleeview.h b/src/plugins/qmlprofiler/qmlprofilercalleeview.h deleted file mode 100644 index 715a006edd..0000000000 --- a/src/plugins/qmlprofiler/qmlprofilercalleeview.h +++ /dev/null @@ -1,71 +0,0 @@ -/************************************************************************** -** -** This file is part of Qt Creator -** -** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies). -** -** Contact: Nokia Corporation (info@qt.nokia.com) -** -** No Commercial Usage -** -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at info@qt.nokia.com. -** -**************************************************************************/ - -#ifndef QMLPROFILERCALLEEVIEW_H -#define QMLPROFILERCALLEEVIEW_H - -#include <QTreeView> - -namespace QmlProfiler { -namespace Internal { - -class QmlProfilerCalleeView : public QTreeView -{ - Q_OBJECT - -public: - explicit QmlProfilerCalleeView(QWidget *parent = 0); - ~QmlProfilerCalleeView(); - -signals: - void gotoSourceLocation(const QString &fileName, int lineNumber); - -public slots: - void clean(); - - void addRangedEvent(int type, int nestingLevel, int nestingInType, qint64 startTime, qint64 length, - const QStringList &data, const QString &fileName, int line); - void complete(); - void jumpToItem(const QModelIndex &index); - -private: - class QmlProfilerCalleeViewPrivate; - QmlProfilerCalleeViewPrivate *d; - - void setHeaderLabels(); -}; - -} // namespace Internal -} // namespace QmlProfiler - -#endif // QMLPROFILERCALLEEVIEW_H diff --git a/src/plugins/qmlprofiler/qmlprofilercallerview.cpp b/src/plugins/qmlprofiler/qmlprofilercallerview.cpp deleted file mode 100644 index 92cece6058..0000000000 --- a/src/plugins/qmlprofiler/qmlprofilercallerview.cpp +++ /dev/null @@ -1,288 +0,0 @@ -/************************************************************************** -** -** This file is part of Qt Creator -** -** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies). -** -** Contact: Nokia Corporation (info@qt.nokia.com) -** -** No Commercial Usage -** -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at info@qt.nokia.com. -** -**************************************************************************/ - -#include "qmlprofilercallerview.h" - -#include <QtCore/QUrl> -#include <QtCore/QHash> - -#include <QtGui/QHeaderView> -#include <QtGui/QStandardItemModel> - -using namespace QmlProfiler::Internal; - -struct BindingData -{ - BindingData() : displayname(0) , filename(0) , location(0) , details(0), - line(0), rangeType(0), level(-1), parentList(0) {} - ~BindingData() { - delete displayname; - delete filename; - delete location; - delete parentList; - } - QString *displayname; - QString *filename; - QString *location; - QString *details; - int line; - int rangeType; - qint64 level; - QList< BindingData *> *parentList; -}; - -typedef QHash<QString, BindingData *> BindingHash; -typedef QList<BindingData *> BindingList; - -enum ItemRole { - LocationRole = Qt::UserRole+1, - FilenameRole = Qt::UserRole+2, - LineRole = Qt::UserRole+3 -}; - -class QmlProfilerCallerView::QmlProfilerCallerViewPrivate -{ -public: - QmlProfilerCallerViewPrivate(QmlProfilerCallerView *qq) : q(qq) {} - - void recursiveClearHash(BindingHash *hash); - void buildModelFromList( BindingList *list, QStandardItem *parentItem, BindingList *listSoFar ); - - QmlProfilerCallerView *q; - - QStandardItemModel *m_model; - BindingHash m_rootHash; - QHash<int, BindingList> m_pendingChildren; - int m_lastLevel; -}; - -QmlProfilerCallerView::QmlProfilerCallerView(QWidget *parent) : - QTreeView(parent), d(new QmlProfilerCallerViewPrivate(this)) -{ - setObjectName("QmlProfilerCallerView"); - setRootIsDecorated(true); - header()->setResizeMode(QHeaderView::Interactive); - header()->setMinimumSectionSize(50); - setSortingEnabled(false); - setFrameStyle(QFrame::NoFrame); - - d->m_model = new QStandardItemModel(this); - - setModel(d->m_model); - - d->m_model->setColumnCount(3); - setHeaderLabels(); - - connect(this,SIGNAL(clicked(QModelIndex)), this,SLOT(jumpToItem(QModelIndex))); - - d->m_lastLevel = -1; -} - -QmlProfilerCallerView::~QmlProfilerCallerView() -{ - clean(); - delete d->m_model; -} - -void QmlProfilerCallerView::clean() -{ - d->m_model->clear(); - d->m_model->setColumnCount(3); - - foreach (int levelNumber, d->m_pendingChildren.keys()) - d->m_pendingChildren[levelNumber].clear(); - - d->m_lastLevel = -1; - - // clean the hashes - d->recursiveClearHash(&d->m_rootHash); - - setHeaderLabels(); - setSortingEnabled(false); -} - -void QmlProfilerCallerView::addRangedEvent(int type, int nestingLevel, int nestingInType, qint64 startTime, qint64 length, - const QStringList &data, const QString &fileName, int line) -{ - Q_UNUSED(startTime); - Q_UNUSED(nestingInType); - Q_UNUSED(length); - - const QChar colon = QLatin1Char(':'); - QString localName, displayName, location, details; - - if (fileName.isEmpty()) { - displayName = tr("<bytecode>"); - location = QLatin1String("--"); - - } else { - localName = QUrl(fileName).toLocalFile(); - displayName = localName.mid(localName.lastIndexOf(QChar('/')) + 1) + colon + QString::number(line); - location = fileName+colon+QString::number(line); - } - - if (data.isEmpty()) - details = tr("Source code not available"); - else - details = data.join(" ").replace('\n'," "); - - - // New Data: if it's not in the hash, put it there - // if it's in the hash, get the reference from the hash - BindingData *newBinding; - BindingHash::iterator it = d->m_rootHash.find(location); - if (it != d->m_rootHash.end()) { - newBinding = it.value(); - } else { - newBinding = new BindingData; - newBinding->displayname = new QString(displayName); - newBinding->filename = new QString(fileName); - newBinding->line = line; - newBinding->level = nestingLevel; - newBinding->rangeType = type; - newBinding->location = new QString(location); - newBinding->details = new QString(details); - newBinding->parentList = new BindingList(); - d->m_rootHash.insert(location, newBinding); - } - - if (nestingLevel < d->m_lastLevel) { - // I'm the parent of the former - if (d->m_pendingChildren.contains(nestingLevel+1)) { - foreach (BindingData *child, d->m_pendingChildren[nestingLevel + 1]) { - if (!child->parentList->contains(newBinding)) - child->parentList->append(newBinding); - } - d->m_pendingChildren[nestingLevel + 1].clear(); - } - - } - - if (nestingLevel > 1 && !d->m_pendingChildren[nestingLevel].contains(newBinding)) { - // I'm not root... there will come a parent later - d->m_pendingChildren[nestingLevel].append(newBinding); - } - - d->m_lastLevel = nestingLevel; -} - -void QmlProfilerCallerView::complete() -{ - // build the model from the hashed data - BindingList bindingList = d->m_rootHash.values(); - BindingList emptyList; - d->buildModelFromList(&bindingList, d->m_model->invisibleRootItem(), &emptyList); - - expandAll(); - resizeColumnToContents(0); - resizeColumnToContents(1); - collapseAll(); -} - -void QmlProfilerCallerView::jumpToItem(const QModelIndex &index) -{ - QStandardItem *clickedItem = d->m_model->itemFromIndex(index); - QStandardItem *infoItem; - if (clickedItem->parent()) - infoItem = clickedItem->parent()->child(clickedItem->row(), 0); - else - infoItem = d->m_model->item(index.row(), 0); - - int line = infoItem->data(Qt::UserRole+3).toInt(); - if (line == -1) - return; - QString fileName = infoItem->data(Qt::UserRole+2).toString(); - emit gotoSourceLocation(fileName, line); -} - -void QmlProfilerCallerView::setHeaderLabels() -{ - d->m_model->setHeaderData(0, Qt::Horizontal, QVariant(tr("Location"))); - d->m_model->setHeaderData(1, Qt::Horizontal, QVariant(tr("Type"))); - d->m_model->setHeaderData(2, Qt::Horizontal, QVariant(tr("Details"))); -} - -// ToDo: property clean the stored data -void QmlProfilerCallerView::QmlProfilerCallerViewPrivate::recursiveClearHash(BindingHash *hash) { - QHashIterator<QString, BindingData *> it(*hash); - while (it.hasNext()) { - it.next(); - delete it.value(); - } - hash->clear(); -} - -inline QString nameForType(int typeNumber) -{ - switch (typeNumber) { - case 0: return QmlProfilerCallerView::tr("Paint"); - case 1: return QmlProfilerCallerView::tr("Compile"); - case 2: return QmlProfilerCallerView::tr("Create"); - case 3: return QmlProfilerCallerView::tr("Binding"); - case 4: return QmlProfilerCallerView::tr("Signal"); - } - return QString(); -} - -void QmlProfilerCallerView::QmlProfilerCallerViewPrivate::buildModelFromList( BindingList *list, QStandardItem *parentItem, BindingList *listSoFar ) -{ - foreach (BindingData *binding, *list) { - if (listSoFar->contains(binding)) - continue; - - QStandardItem *nameColumn = new QStandardItem(*binding->displayname); - nameColumn->setEditable(false); - - QStandardItem *typeColumn = new QStandardItem(nameForType(binding->rangeType)); - typeColumn->setEditable(false); - - QStandardItem *detailsColumn = new QStandardItem(*binding->details); - detailsColumn->setEditable(false); - - QStandardItem *firstColumn = nameColumn; - firstColumn->setData(QVariant(*binding->location),LocationRole); - firstColumn->setData(QVariant(*binding->filename),FilenameRole); - firstColumn->setData(QVariant(binding->line),LineRole); - - QList<QStandardItem *> newRow; - newRow << nameColumn << typeColumn << detailsColumn; - parentItem->appendRow(newRow); - if (!binding->parentList->isEmpty()) { - // avoid infinite loops due to recursive functions - BindingList newParentList(*listSoFar); - newParentList.append(binding); - - buildModelFromList(binding->parentList, nameColumn, &newParentList); - } - } -} diff --git a/src/plugins/qmlprofiler/qmlprofilercallerview.h b/src/plugins/qmlprofiler/qmlprofilercallerview.h deleted file mode 100644 index 7f9416fea9..0000000000 --- a/src/plugins/qmlprofiler/qmlprofilercallerview.h +++ /dev/null @@ -1,71 +0,0 @@ -/************************************************************************** -** -** This file is part of Qt Creator -** -** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies). -** -** Contact: Nokia Corporation (info@qt.nokia.com) -** -** No Commercial Usage -** -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at info@qt.nokia.com. -** -**************************************************************************/ - -#ifndef QMLPROFILERCALLERVIEW_H -#define QMLPROFILERCALLERVIEW_H - -#include <QTreeView> - -namespace QmlProfiler { -namespace Internal { - -class QmlProfilerCallerView : public QTreeView -{ - Q_OBJECT - -public: - explicit QmlProfilerCallerView(QWidget *parent = 0); - ~QmlProfilerCallerView(); - -signals: - void gotoSourceLocation(const QString &fileName, int lineNumber); - -public slots: - void clean(); - - void addRangedEvent(int type, int nestingLevel, int nestingInType, qint64 startTime, qint64 length, - const QStringList &data, const QString &fileName, int line); - void complete(); - void jumpToItem(const QModelIndex &index); - -private: - class QmlProfilerCallerViewPrivate; - QmlProfilerCallerViewPrivate *d; - - void setHeaderLabels(); -}; - -} // namespace Internal -} // namespace QmlProfiler - -#endif // QMLPROFILERCALLERVIEW_H diff --git a/src/plugins/qmlprofiler/qmlprofilereventtypes.h b/src/plugins/qmlprofiler/qmlprofilereventtypes.h new file mode 100644 index 0000000000..1e324a69d8 --- /dev/null +++ b/src/plugins/qmlprofiler/qmlprofilereventtypes.h @@ -0,0 +1,20 @@ +#ifndef QMLPROFILEREVENTTYPES_H +#define QMLPROFILEREVENTTYPES_H + +namespace QmlProfiler { +namespace Internal { + +enum QmlEventType { + Painting, + Compiling, + Creating, + Binding, + HandlingSignal, + + MaximumQmlEventType +}; + +} +} + +#endif //QMLPROFILEREVENTTYPES_H diff --git a/src/plugins/qmlprofiler/qmlprofilereventview.cpp b/src/plugins/qmlprofiler/qmlprofilereventview.cpp new file mode 100644 index 0000000000..e9eee27ef0 --- /dev/null +++ b/src/plugins/qmlprofiler/qmlprofilereventview.cpp @@ -0,0 +1,544 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (info@qt.nokia.com) +** +** No Commercial Usage +** +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at info@qt.nokia.com. +** +**************************************************************************/ + +#include "qmlprofilereventview.h" + +#include <QtCore/QUrl> +#include <QtCore/QHash> + +#include <QtGui/QHeaderView> +#include <QtGui/QStandardItemModel> + +namespace QmlProfiler { +namespace Internal { + +class EventsViewItem : public QStandardItem +{ +public: + EventsViewItem(const QString &text) : QStandardItem(text) {} + + virtual bool operator<(const QStandardItem &other) const + { + if (data().type() == QVariant::String) { + // first column + return data(FilenameRole).toString() == other.data(FilenameRole).toString() ? + data(LineRole).toInt() < other.data(LineRole).toInt() : + data(FilenameRole).toString() < other.data(FilenameRole).toString(); + } + + return data().toDouble() < other.data().toDouble(); + } +}; + + +//////////////////////////////////////////////////////////////////////////////////// + +class QmlProfilerEventStatistics::QmlProfilerEventStatisticsPrivate +{ +public: + QmlProfilerEventStatisticsPrivate(QmlProfilerEventStatistics *qq) : q(qq) {} + + void postProcess(); + + QmlProfilerEventStatistics *q; + QmlEventHash m_rootHash; + QHash<int, QmlEventList> m_pendingEvents; + int m_lastLevel; +}; + + +//////////////////////////////////////////////////////////////////////////////////// + +class QmlProfilerEventsView::QmlProfilerEventsViewPrivate +{ +public: + QmlProfilerEventsViewPrivate(QmlProfilerEventsView *qq) : q(qq) {} + + void buildModelFromList(const QmlEventList &list, QStandardItem *parentItem, const QmlEventList &visitedFunctionsList = QmlEventList() ); + int getFieldCount(); + QString displayTime(double time) const; + QString nameForType(int typeNumber) const; + + + QmlProfilerEventsView *q; + + QmlProfilerEventStatistics *m_eventStatistics; + QStandardItemModel *m_model; + QList<bool> m_fieldShown; + bool m_showAnonymous; + int m_firstNumericColumn; +}; + + +//////////////////////////////////////////////////////////////////////////////////// + +QmlProfilerEventStatistics::QmlProfilerEventStatistics(QObject *parent) : + QObject(parent), d(new QmlProfilerEventStatisticsPrivate(this)) +{ + setObjectName("QmlProfilerEventStatistics"); + d->m_lastLevel = -1; +} + +QmlProfilerEventStatistics::~QmlProfilerEventStatistics() +{ + clear(); +} + +void QmlProfilerEventStatistics::clear() +{ + foreach (int levelNumber, d->m_pendingEvents.keys()) + d->m_pendingEvents[levelNumber].clear(); + + d->m_lastLevel = -1; + + foreach (QmlEventData *binding, d->m_rootHash.values()) + delete binding; + d->m_rootHash.clear(); +} + +QList <QmlEventData *> QmlProfilerEventStatistics::getEventList() +{ + return d->m_rootHash.values(); +} + +void QmlProfilerEventStatistics::addRangedEvent(int type, int nestingLevel, int nestingInType, qint64 startTime, qint64 length, + const QStringList &data, const QString &fileName, int line) +{ + Q_UNUSED(startTime); + Q_UNUSED(nestingInType); + + const QChar colon = QLatin1Char(':'); + QString localName, displayName, location, details; + + if (data.isEmpty()) + details = tr("Source code not available"); + else { + details = data.join(" ").replace('\n'," ").simplified(); + QRegExp rewrite("\\(function \\$(\\w+)\\(\\) \\{ (return |)(.+) \\}\\)"); + bool match = rewrite.exactMatch(details); + if (match) { + details = rewrite.cap(1) + ": " + rewrite.cap(3); + } + if (details.startsWith(QString("file://"))) + details = details.mid(details.lastIndexOf(QChar('/')) + 1); + } + + if (fileName.isEmpty()) { + displayName = tr("<bytecode>"); + location = QString("--:%1:%2").arg(QString::number(type), details); + } else { + localName = QUrl(fileName).toLocalFile(); + displayName = localName.mid(localName.lastIndexOf(QChar('/')) + 1) + colon + QString::number(line); + location = fileName+colon+QString::number(line); + } + + + // New Data: if it's not in the hash, put it there + // if it's in the hash, get the reference from the hash + QmlEventData *newBinding; + QmlEventHash::iterator it = d->m_rootHash.find(location); + if (it != d->m_rootHash.end()) { + newBinding = it.value(); + newBinding->duration += length; + newBinding->calls++; + if (newBinding->maxTime < length) + newBinding->maxTime = length; + if (newBinding->minTime > length) + newBinding->minTime = length; + } else { + newBinding = new QmlEventData; + newBinding->calls = 1; + newBinding->duration = length; + newBinding->displayname = new QString(displayName); + newBinding->filename = new QString(fileName); + newBinding->location = new QString(location); + newBinding->line = line; + newBinding->minTime = length; + newBinding->maxTime = length; + newBinding->level = nestingLevel; + newBinding->eventType = (QmlEventType)type; + newBinding->details = new QString(details); + newBinding->parentList = new QmlEventList(); + newBinding->childrenList = new QmlEventList(); + d->m_rootHash.insert(location, newBinding); + } + + if (nestingLevel < d->m_lastLevel) { + // I'm the parent of the former + if (d->m_pendingEvents.contains(nestingLevel+1)) { + foreach (QmlEventData *child, d->m_pendingEvents[nestingLevel + 1]) { + if (!newBinding->childrenList->contains(child)) + newBinding->childrenList->append(child); + if (!child->parentList->contains(newBinding)) + child->parentList->append(newBinding); + } + d->m_pendingEvents[nestingLevel + 1].clear(); + } + + } + + if (nestingLevel > 1 && !d->m_pendingEvents[nestingLevel].contains(newBinding)) { + // I'm not root... there will come a parent later + d->m_pendingEvents[nestingLevel].append(newBinding); + } + + d->m_lastLevel = nestingLevel; +} + +void QmlProfilerEventStatistics::complete() +{ + d->postProcess(); + emit dataReady(); +} + +void QmlProfilerEventStatistics::QmlProfilerEventStatisticsPrivate::postProcess() +{ + double totalTime = 0; + + foreach (QmlEventData *binding, m_rootHash.values()) + totalTime += binding->duration; + + foreach (QmlEventData *binding, m_rootHash.values()) { + binding->percentOfTime = binding->duration * 100.0 / totalTime; + binding->timePerCall = binding->calls > 0 ? double(binding->duration) / binding->calls : 0; + } +} + +//////////////////////////////////////////////////////////////////////////////////// + +QmlProfilerEventsView::QmlProfilerEventsView(QWidget *parent, QmlProfilerEventStatistics *model) : + QTreeView(parent), d(new QmlProfilerEventsViewPrivate(this)) +{ + setObjectName("QmlProfilerEventsView"); + header()->setResizeMode(QHeaderView::Interactive); + header()->setDefaultSectionSize(100); + header()->setMinimumSectionSize(50); + setSortingEnabled(false); + setFrameStyle(QFrame::NoFrame); + + d->m_model = new QStandardItemModel(this); + setModel(d->m_model); + connect(this,SIGNAL(clicked(QModelIndex)), this,SLOT(jumpToItem(QModelIndex))); + + d->m_eventStatistics = 0; + setEventStatisticsModel(model); + + d->m_showAnonymous = false; + d->m_firstNumericColumn = 0; + + // default view + setViewType(EventsView); +} + +QmlProfilerEventsView::~QmlProfilerEventsView() +{ + clear(); + delete d->m_model; +} + +void QmlProfilerEventsView::setEventStatisticsModel( QmlProfilerEventStatistics *model ) +{ + if (d->m_eventStatistics) + disconnect(d->m_eventStatistics,SIGNAL(dataReady()),this,SLOT(buildModel())); + d->m_eventStatistics = model; + connect(d->m_eventStatistics,SIGNAL(dataReady()),this,SLOT(buildModel())); +} + +void QmlProfilerEventsView::setFieldViewable(Fields field, bool show) +{ + if (field < MaxFields) { + int length = d->m_fieldShown.count(); + if (field >= length) { + for (int i=length; i<MaxFields; i++) + d->m_fieldShown << false; + } + d->m_fieldShown[field] = show; + } +} + +void QmlProfilerEventsView::setViewType(ViewTypes type) +{ + switch (type) { + case EventsView: { + setObjectName("QmlProfilerEventsView"); + setFieldViewable(Name, true); + setFieldViewable(Type, true); + setFieldViewable(Percent, true); + setFieldViewable(TotalDuration, true); + setFieldViewable(CallCount, true); + setFieldViewable(TimePerCall, true); + setFieldViewable(MaxTime, true); + setFieldViewable(MinTime, true); + setFieldViewable(Details, false); + setFieldViewable(Parents, false); + setFieldViewable(Children, false); + setShowAnonymousEvents(false); + break; + } + case CallersView: { + setObjectName("QmlProfilerCallersView"); + setFieldViewable(Name, true); + setFieldViewable(Type, true); + setFieldViewable(Percent, false); + setFieldViewable(TotalDuration, false); + setFieldViewable(CallCount, false); + setFieldViewable(TimePerCall, false); + setFieldViewable(MaxTime, false); + setFieldViewable(MinTime, false); + setFieldViewable(Details, true); + setFieldViewable(Parents, true); + setFieldViewable(Children, false); + setShowAnonymousEvents(true); + break; + } + case CalleesView: { + setObjectName("QmlProfilerCalleesView"); + setFieldViewable(Name, true); + setFieldViewable(Type, true); + setFieldViewable(Percent, false); + setFieldViewable(TotalDuration, false); + setFieldViewable(CallCount, false); + setFieldViewable(TimePerCall, false); + setFieldViewable(MaxTime, false); + setFieldViewable(MinTime, false); + setFieldViewable(Details, true); + setFieldViewable(Parents, false); + setFieldViewable(Children, true); + setShowAnonymousEvents(true); + break; + } + default: break; + } + + buildModel(); +} + +void QmlProfilerEventsView::setShowAnonymousEvents( bool showThem ) +{ + d->m_showAnonymous = showThem; +} + +void QmlProfilerEventsView::setHeaderLabels() +{ + int fieldIndex = 0; + d->m_firstNumericColumn = 0; + + if (d->m_fieldShown[Name]) { + d->m_model->setHeaderData(fieldIndex++, Qt::Horizontal, QVariant(tr("Location"))); + d->m_firstNumericColumn++; + } + if (d->m_fieldShown[Type]) { + d->m_model->setHeaderData(fieldIndex++, Qt::Horizontal, QVariant(tr("Type"))); + d->m_firstNumericColumn++; + } + if (d->m_fieldShown[Percent]) + d->m_model->setHeaderData(fieldIndex++, Qt::Horizontal, QVariant(tr("Time in Percent"))); + if (d->m_fieldShown[TotalDuration]) + d->m_model->setHeaderData(fieldIndex++, Qt::Horizontal, QVariant(tr("Total Time"))); + if (d->m_fieldShown[CallCount]) + d->m_model->setHeaderData(fieldIndex++, Qt::Horizontal, QVariant(tr("Calls"))); + if (d->m_fieldShown[TimePerCall]) + d->m_model->setHeaderData(fieldIndex++, Qt::Horizontal, QVariant(tr("Time per Call"))); + if (d->m_fieldShown[MaxTime]) + d->m_model->setHeaderData(fieldIndex++, Qt::Horizontal, QVariant(tr("Longest Time"))); + if (d->m_fieldShown[MinTime]) + d->m_model->setHeaderData(fieldIndex++, Qt::Horizontal, QVariant(tr("Shortest Time"))); + if (d->m_fieldShown[Details]) + d->m_model->setHeaderData(fieldIndex++, Qt::Horizontal, QVariant(tr("Details"))); +} + +void QmlProfilerEventsView::clear() +{ + d->m_model->clear(); + d->m_model->setColumnCount(d->getFieldCount()); + + setHeaderLabels(); + setSortingEnabled(false); +} + +int QmlProfilerEventsView::QmlProfilerEventsViewPrivate::getFieldCount() +{ + int count = 0; + for (int i=0; i < m_fieldShown.count(); ++i) + if (m_fieldShown[i] && i != Parents && i != Children) + count++; + return count; +} + +void QmlProfilerEventsView::buildModel() +{ + if (d->m_eventStatistics) { + clear(); + d->buildModelFromList( d->m_eventStatistics->getEventList(), d->m_model->invisibleRootItem() ); + + bool hasBranches = d->m_fieldShown[Parents] || d->m_fieldShown[Children]; + setRootIsDecorated(hasBranches); + + setSortingEnabled(!hasBranches); + + if (!hasBranches) + sortByColumn(d->m_firstNumericColumn,Qt::DescendingOrder); + + expandAll(); + if (d->m_fieldShown[Name]) + resizeColumnToContents(0); + + if (d->m_fieldShown[Type]) + resizeColumnToContents(d->m_fieldShown[Name]?1:0); + collapseAll(); + } +} + +void QmlProfilerEventsView::QmlProfilerEventsViewPrivate::buildModelFromList( const QmlEventList &list, QStandardItem *parentItem, const QmlEventList &visitedFunctionsList ) +{ + foreach (QmlEventData *binding, list) { + if (visitedFunctionsList.contains(binding)) + continue; + + if ((!m_showAnonymous) && binding->filename->isEmpty()) + continue; + + QList<QStandardItem *> newRow; + if (m_fieldShown[Name]) { + newRow << new EventsViewItem(*binding->displayname); + } + + if (m_fieldShown[Type]) { + newRow << new EventsViewItem(nameForType(binding->eventType)); + newRow.last()->setData(QVariant(binding->eventType)); + } + + if (m_fieldShown[Percent]) { + newRow << new EventsViewItem(QString::number(binding->percentOfTime,'f',2)+QLatin1String(" %")); + newRow.last()->setData(QVariant(binding->eventType)); + } + + if (m_fieldShown[TotalDuration]) { + newRow << new EventsViewItem(displayTime(binding->duration)); + newRow.last()->setData(QVariant(binding->duration)); + } + + if (m_fieldShown[CallCount]) { + newRow << new EventsViewItem(QString::number(binding->calls)); + newRow.last()->setData(QVariant(binding->calls)); + } + + if (m_fieldShown[TimePerCall]) { + newRow << new EventsViewItem(displayTime(binding->timePerCall)); + newRow.last()->setData(QVariant(binding->timePerCall)); + } + + if (m_fieldShown[MaxTime]) { + newRow << new EventsViewItem(displayTime(binding->maxTime)); + newRow.last()->setData(QVariant(binding->maxTime)); + } + + if (m_fieldShown[MinTime]) { + newRow << new EventsViewItem(displayTime(binding->minTime)); + newRow.last()->setData(QVariant(binding->minTime)); + } + + if (m_fieldShown[Details]) { + newRow << new EventsViewItem(*binding->details); + } + + if (!newRow.isEmpty()) { + // no edit + foreach (QStandardItem *item, newRow) + item->setEditable(false); + + // metadata + newRow.at(0)->setData(QVariant(*binding->location),LocationRole); + newRow.at(0)->setData(QVariant(*binding->filename),FilenameRole); + newRow.at(0)->setData(QVariant(binding->line),LineRole); + + // append + parentItem->appendRow(newRow); + + if (m_fieldShown[Parents] && !binding->parentList->isEmpty()) { + QmlEventList newParentList(visitedFunctionsList); + newParentList.append(binding); + + buildModelFromList(*binding->parentList, newRow.at(0), newParentList); + } + + if (m_fieldShown[Children] && !binding->childrenList->isEmpty()) { + QmlEventList newChildrenList(visitedFunctionsList); + newChildrenList.append(binding); + + buildModelFromList(*binding->childrenList, newRow.at(0), newChildrenList); + } + } + } +} + +QString QmlProfilerEventsView::QmlProfilerEventsViewPrivate::displayTime(double time) const +{ + if (time < 1e6) + return QString::number(time/1e3,'f',3) + QString::fromWCharArray(L" \u03BCs"); + if (time < 1e9) + return QString::number(time/1e6,'f',3) + QLatin1String(" ms"); + + return QString::number(time/1e9,'f',3) + QLatin1String(" s"); +} + +QString QmlProfilerEventsView::QmlProfilerEventsViewPrivate::nameForType(int typeNumber) const +{ + switch (typeNumber) { + case 0: return QmlProfilerEventsView::tr("Paint"); + case 1: return QmlProfilerEventsView::tr("Compile"); + case 2: return QmlProfilerEventsView::tr("Create"); + case 3: return QmlProfilerEventsView::tr("Binding"); + case 4: return QmlProfilerEventsView::tr("Signal"); + } + return QString(); +} + +void QmlProfilerEventsView::jumpToItem(const QModelIndex &index) +{ + QStandardItem *clickedItem = d->m_model->itemFromIndex(index); + QStandardItem *infoItem; + if (clickedItem->parent()) + infoItem = clickedItem->parent()->child(clickedItem->row(), 0); + else + infoItem = d->m_model->item(index.row(), 0); + + int line = infoItem->data(LineRole).toInt(); + if (line == -1) + return; + QString fileName = infoItem->data(FilenameRole).toString(); + emit gotoSourceLocation(fileName, line); +} + +} // namespace Internal +} // namespace QmlProfiler diff --git a/src/plugins/qmlprofiler/qmlprofilereventview.h b/src/plugins/qmlprofiler/qmlprofilereventview.h new file mode 100644 index 0000000000..9baba8e42b --- /dev/null +++ b/src/plugins/qmlprofiler/qmlprofilereventview.h @@ -0,0 +1,161 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (info@qt.nokia.com) +** +** No Commercial Usage +** +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at info@qt.nokia.com. +** +**************************************************************************/ + +#ifndef QMLPROFILEREVENTVIEW_H +#define QMLPROFILEREVENTVIEW_H + +#include <QTreeView> +#include "qmlprofilereventtypes.h" + +namespace QmlProfiler { +namespace Internal { + +struct QmlEventData +{ + QmlEventData() : displayname(0) , filename(0) , location(0) , details(0), + line(0), eventType(MaximumQmlEventType), level(-1), parentList(0), childrenList(0) {} + ~QmlEventData() { + delete displayname; + delete filename; + delete location; + delete parentList; + delete childrenList; + } + QString *displayname; + QString *filename; + QString *location; + QString *details; + int line; + QmlEventType eventType; + qint64 level; + QList< QmlEventData *> *parentList; + QList< QmlEventData *> *childrenList; + qint64 duration; + qint64 calls; + qint64 minTime; + qint64 maxTime; + double timePerCall; + double percentOfTime; +}; + + +typedef QHash<QString, QmlEventData *> QmlEventHash; +typedef QList<QmlEventData *> QmlEventList; + +enum ItemRole { + LocationRole = Qt::UserRole+1, + FilenameRole = Qt::UserRole+2, + LineRole = Qt::UserRole+3 +}; + +class QmlProfilerEventStatistics : public QObject +{ + Q_OBJECT +public: + + explicit QmlProfilerEventStatistics(QObject *parent = 0); + ~QmlProfilerEventStatistics(); + + QmlEventList getEventList(); + +signals: + void dataReady(); + +public slots: + void clear(); + void addRangedEvent(int type, int nestingLevel, int nestingInType, qint64 startTime, qint64 length, + const QStringList &data, const QString &fileName, int line); + void complete(); + +private: + class QmlProfilerEventStatisticsPrivate; + QmlProfilerEventStatisticsPrivate *d; +}; + +class QmlProfilerEventsView : public QTreeView +{ + Q_OBJECT +public: + enum Fields { + Name, + Type, + Percent, + TotalDuration, + CallCount, + TimePerCall, + MaxTime, + MinTime, + Details, + Parents, + Children, + + MaxFields + }; + + enum ViewTypes { + EventsView, + CallersView, + CalleesView, + + MaxViewTypes + }; + + explicit QmlProfilerEventsView(QWidget *parent, QmlProfilerEventStatistics *model); + ~QmlProfilerEventsView(); + + void setEventStatisticsModel( QmlProfilerEventStatistics *model ); + void setFieldViewable(Fields field, bool show); + void setViewType(ViewTypes type); + void setShowAnonymousEvents( bool showThem ); + +signals: + void gotoSourceLocation(const QString &fileName, int lineNumber); + +public slots: + void clear(); + void jumpToItem(const QModelIndex &index); + void buildModel(); + +private: + void setHeaderLabels(); + +private: + class QmlProfilerEventsViewPrivate; + QmlProfilerEventsViewPrivate *d; + +}; + +} // namespace Internal +} // namespace QmlProfiler + +#endif // QMLPROFILEREVENTVIEW_H diff --git a/src/plugins/qmlprofiler/qmlprofilersummaryview.cpp b/src/plugins/qmlprofiler/qmlprofilersummaryview.cpp deleted file mode 100644 index 307d920c57..0000000000 --- a/src/plugins/qmlprofiler/qmlprofilersummaryview.cpp +++ /dev/null @@ -1,283 +0,0 @@ -/************************************************************************** -** -** This file is part of Qt Creator -** -** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies). -** -** Contact: Nokia Corporation (info@qt.nokia.com) -** -** No Commercial Usage -** -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at info@qt.nokia.com. -** -**************************************************************************/ - -#include "qmlprofilersummaryview.h" - -#include <QtCore/QUrl> -#include <QtCore/QHash> - -#include <QtGui/QHeaderView> -#include <QtGui/QStandardItemModel> - -using namespace QmlProfiler::Internal; - -struct BindingData -{ - QString displayname; - QString filename; - int line; - qint64 duration; - qint64 calls; - qint64 minTime; - qint64 maxTime; - double tpc; - double percent; -}; - -class QmlProfilerSummaryView::QmlProfilerSummaryViewPrivate -{ -public: - QmlProfilerSummaryViewPrivate(QmlProfilerSummaryView *qq) : q(qq) {} - - QmlProfilerSummaryView *q; - - QStandardItemModel *m_model; - QHash<QString, BindingData *> m_bindingHash; - - enum RangeType { - Painting, - Compiling, - Creating, - Binding, - HandlingSignal, - - MaximumRangeType - }; -}; - -class ProfilerItem : public QStandardItem -{ -public: - ProfilerItem(const QString &text) : QStandardItem(text) {} - - virtual bool operator<(const QStandardItem &other) const - { - if (data().type() == QVariant::String) { - // first column - return data(Qt::UserRole+2).toString() == other.data(Qt::UserRole+2).toString() ? - data(Qt::UserRole+3).toInt() < other.data(Qt::UserRole+3).toInt() : - data(Qt::UserRole+2).toString() < other.data(Qt::UserRole+2).toString(); - } - - return data().toDouble() < other.data().toDouble(); - } -}; - -QmlProfilerSummaryView::QmlProfilerSummaryView(QWidget *parent) : - QTreeView(parent), d(new QmlProfilerSummaryViewPrivate(this)) -{ - setObjectName("QmlProfilerSummaryView"); - setRootIsDecorated(false); - header()->setResizeMode(QHeaderView::Interactive); - header()->setMinimumSectionSize(100); - setSortingEnabled(false); - setFrameStyle(QFrame::NoFrame); - - d->m_model = new QStandardItemModel(this); - - setModel(d->m_model); - - d->m_model->setColumnCount(7); - setHeaderLabels(); - - connect(this,SIGNAL(clicked(QModelIndex)), this,SLOT(jumpToItem(QModelIndex))); -} - -QmlProfilerSummaryView::~QmlProfilerSummaryView() -{ - delete d->m_model; -} - -void QmlProfilerSummaryView::clean() -{ - d->m_model->clear(); - d->m_model->setColumnCount(7); - - // clean the hash - QHashIterator<QString, BindingData *> it(d->m_bindingHash); - while (it.hasNext()) { - it.next(); - delete it.value(); - } - d->m_bindingHash.clear(); - - setHeaderLabels(); - setSortingEnabled(false); -} - -void QmlProfilerSummaryView::addRangedEvent(int type, int nestingLevel, int nestingInType, qint64 startTime, qint64 length, - const QStringList &data, const QString &fileName, int line) -{ - Q_UNUSED(startTime); - Q_UNUSED(data); - Q_UNUSED(nestingLevel); - Q_UNUSED(nestingInType); - - if (type != QmlProfilerSummaryViewPrivate::Binding && type != QmlProfilerSummaryViewPrivate::HandlingSignal) - return; - - if (fileName.isEmpty()) - return; - const QChar colon = QLatin1Char(':'); - QString localName = QUrl(fileName).toLocalFile(); - QString displayName = localName.mid(localName.lastIndexOf(QChar('/'))+1)+colon+QString::number(line); - QString location = fileName+colon+QString::number(line); - - QHash<QString, BindingData *>::iterator it = d->m_bindingHash.find(location); - if (it != d->m_bindingHash.end()) { - BindingData *bindingInfo = it.value(); - bindingInfo->duration += length; - bindingInfo->calls++; - if (bindingInfo->maxTime < length) - bindingInfo->maxTime = length; - if (bindingInfo->minTime > length) - bindingInfo->minTime = length; - } else { - BindingData *newBinding = new BindingData; - newBinding->calls = 1; - newBinding->duration = length; - newBinding->displayname = displayName; - newBinding->filename = fileName; - newBinding->line = line; - newBinding->minTime = length; - newBinding->maxTime = length; - - d->m_bindingHash.insert(location, newBinding); - } -} - -void QmlProfilerSummaryView::complete() -{ - // compute percentages - double totalTime = 0; - - QHashIterator<QString, BindingData *> it(d->m_bindingHash); - - while (it.hasNext()) { - it.next(); - totalTime += it.value()->duration; - } - - it.toFront(); - - while (it.hasNext()) { - it.next(); - BindingData *binding = it.value(); - binding->percent = binding->duration * 100.0 / totalTime; - binding->tpc = binding->calls > 0 ? double(binding->duration) / binding->calls : 0; - - appendRow(binding->displayname, - binding->filename, - binding->line, - binding->percent, - binding->duration, - binding->calls, - binding->tpc, - binding->maxTime, - binding->minTime); - - } - setSortingEnabled(true); - sortByColumn(1,Qt::DescendingOrder); - resizeColumnToContents(0); -} - -void QmlProfilerSummaryView::jumpToItem(const QModelIndex &index) -{ - int line = d->m_model->item(index.row(),0)->data(Qt::UserRole+3).toInt(); - if (line == -1) - return; - QString fileName = d->m_model->item(index.row(),0)->data(Qt::UserRole+2).toString(); - emit gotoSourceLocation(fileName, line); -} - -void QmlProfilerSummaryView::appendRow(const QString &displayName, - const QString &fileName, - int line, - double percentTime, - double totalTime, - int nCalls, - double timePerCall, - double maxTime, - double minTime) -{ - QString location = fileName + QLatin1Char(':') + QString::number(line); - ProfilerItem *locationColumn = new ProfilerItem(displayName); - locationColumn->setData(QVariant(location),Qt::UserRole+1); - locationColumn->setData(QVariant(fileName),Qt::UserRole+2); - locationColumn->setData(QVariant(line),Qt::UserRole+3); - locationColumn->setEditable(false); - ProfilerItem *percentColumn = new ProfilerItem(QString::number(percentTime,'f',2)+QLatin1String(" %")); - percentColumn->setData(QVariant(percentTime)); - percentColumn->setEditable(false); - ProfilerItem *timeColumn = new ProfilerItem(displayTime(totalTime)); - timeColumn->setData(QVariant(totalTime)); - timeColumn->setEditable(false); - ProfilerItem *callsColumn = new ProfilerItem(QString::number(nCalls)); - callsColumn->setData(QVariant(nCalls)); - callsColumn->setEditable(false); - ProfilerItem *tpcColumn = new ProfilerItem(displayTime(timePerCall)); - tpcColumn->setData(QVariant(timePerCall)); - tpcColumn->setEditable(false); - ProfilerItem *maxTimeColumn = new ProfilerItem(displayTime(maxTime)); - maxTimeColumn->setData(QVariant(maxTime)); - maxTimeColumn->setEditable(false); - ProfilerItem *minTimeColumn = new ProfilerItem(displayTime(minTime)); - minTimeColumn->setData(QVariant(minTime)); - minTimeColumn->setEditable(false); - - QList<QStandardItem *> newRow; - newRow << locationColumn << percentColumn << timeColumn << callsColumn << tpcColumn << maxTimeColumn << minTimeColumn; - d->m_model->appendRow(newRow); -} - -QString QmlProfilerSummaryView::displayTime(double time) const -{ - if (time < 1e6) - return QString::number(time/1e3,'f',3) + QString::fromWCharArray(L" \u03BCs"); - if (time < 1e9) - return QString::number(time/1e6,'f',3) + QLatin1String(" ms"); - - return QString::number(time/1e9,'f',3) + QLatin1String(" s"); -} - -void QmlProfilerSummaryView::setHeaderLabels() -{ - d->m_model->setHeaderData(0, Qt::Horizontal, QVariant(tr("Location"))); - d->m_model->setHeaderData(1, Qt::Horizontal, QVariant(tr("Time in Percent"))); - d->m_model->setHeaderData(2, Qt::Horizontal, QVariant(tr("Total Time"))); - d->m_model->setHeaderData(3, Qt::Horizontal, QVariant(tr("Calls"))); - d->m_model->setHeaderData(4, Qt::Horizontal, QVariant(tr("Time per Call"))); - d->m_model->setHeaderData(5, Qt::Horizontal, QVariant(tr("Longest Time"))); - d->m_model->setHeaderData(6, Qt::Horizontal, QVariant(tr("Shortest Time"))); -} diff --git a/src/plugins/qmlprofiler/qmlprofilersummaryview.h b/src/plugins/qmlprofiler/qmlprofilersummaryview.h deleted file mode 100644 index 8de750d806..0000000000 --- a/src/plugins/qmlprofiler/qmlprofilersummaryview.h +++ /dev/null @@ -1,80 +0,0 @@ -/************************************************************************** -** -** This file is part of Qt Creator -** -** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies). -** -** Contact: Nokia Corporation (info@qt.nokia.com) -** -** No Commercial Usage -** -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at info@qt.nokia.com. -** -**************************************************************************/ - -#ifndef QMLPROFILERSUMMARYVIEW_H -#define QMLPROFILERSUMMARYVIEW_H - -#include <QTreeView> - -namespace QmlProfiler { -namespace Internal { - -class QmlProfilerSummaryView : public QTreeView -{ - Q_OBJECT - -public: - explicit QmlProfilerSummaryView(QWidget *parent = 0); - ~QmlProfilerSummaryView(); - -signals: - void gotoSourceLocation(const QString &fileName, int lineNumber); - -public slots: - void clean(); - void addRangedEvent(int type, int nestingLevel, int nestingInType, qint64 startTime, qint64 length, - const QStringList &data, const QString &fileName, int line); - void complete(); - void jumpToItem(const QModelIndex &index); - -private: - class QmlProfilerSummaryViewPrivate; - QmlProfilerSummaryViewPrivate *d; - - void appendRow(const QString &displayname, - const QString &filename, - int line, - double percentTime, - double totalTime, - int ncalls, - double timepercall, - double maxtime, - double mintime); - void setHeaderLabels(); - QString displayTime(double time) const; -}; - -} // namespace Internal -} // namespace QmlProfiler - -#endif // QMLPROFILERSUMMARYVIEW_H diff --git a/src/plugins/qmlprofiler/qmlprofilertool.cpp b/src/plugins/qmlprofiler/qmlprofilertool.cpp index 597cd07e7c..3360dea0a2 100644 --- a/src/plugins/qmlprofiler/qmlprofilertool.cpp +++ b/src/plugins/qmlprofiler/qmlprofilertool.cpp @@ -36,9 +36,7 @@ #include "qmlprofilerplugin.h" #include "qmlprofilerconstants.h" #include "qmlprofilerattachdialog.h" -#include "qmlprofilersummaryview.h" -#include "qmlprofilercalleeview.h" -#include "qmlprofilercallerview.h" +#include "qmlprofilereventview.h" #include "tracewindow.h" #include "timelineview.h" @@ -96,9 +94,10 @@ public: QTimer m_connectionTimer; int m_connectionAttempts; TraceWindow *m_traceWindow; - QmlProfilerSummaryView *m_summary; - QmlProfilerCalleeView *m_calleetree; - QmlProfilerCallerView *m_callertree; + QmlProfilerEventStatistics *m_statistics; + QmlProfilerEventsView *m_eventsView; + QmlProfilerEventsView *m_calleeView; + QmlProfilerEventsView *m_callerView; ProjectExplorer::Project *m_project; Utils::FileInProjectFinder m_projectFinder; ProjectExplorer::RunConfiguration *m_runConfiguration; @@ -236,29 +235,25 @@ void QmlProfilerTool::initializeDockWidgets() connect(d->m_traceWindow, SIGNAL(gotoSourceLocation(QString,int)),this, SLOT(gotoSourceLocation(QString,int))); connect(d->m_traceWindow, SIGNAL(timeChanged(qreal)), this, SLOT(updateTimer(qreal))); - d->m_summary = new QmlProfilerSummaryView(mw); + d->m_statistics = new QmlProfilerEventStatistics(mw); + d->m_eventsView = new QmlProfilerEventsView(mw, d->m_statistics); + d->m_eventsView->setViewType(QmlProfilerEventsView::EventsView); connect(d->m_traceWindow, SIGNAL(range(int,int,int,qint64,qint64,QStringList,QString,int)), - d->m_summary, SLOT(addRangedEvent(int,int,int,qint64,qint64,QStringList,QString,int))); + d->m_statistics, SLOT(addRangedEvent(int,int,int,qint64,qint64,QStringList,QString,int))); connect(d->m_traceWindow, SIGNAL(viewUpdated()), - d->m_summary, SLOT(complete())); - connect(d->m_summary, SIGNAL(gotoSourceLocation(QString,int)), + d->m_statistics, SLOT(complete())); + connect(d->m_eventsView, SIGNAL(gotoSourceLocation(QString,int)), this, SLOT(gotoSourceLocation(QString,int))); - d->m_calleetree = new QmlProfilerCalleeView(mw); - connect(d->m_traceWindow, SIGNAL(range(int,int,int,qint64,qint64,QStringList,QString,int)), - d->m_calleetree, SLOT(addRangedEvent(int,int,int,qint64,qint64,QStringList,QString,int))); - connect(d->m_traceWindow, SIGNAL(viewUpdated()), - d->m_calleetree, SLOT(complete())); - connect(d->m_calleetree, SIGNAL(gotoSourceLocation(QString,int)), + d->m_calleeView = new QmlProfilerEventsView(mw, d->m_statistics); + d->m_calleeView->setViewType(QmlProfilerEventsView::CalleesView); + connect(d->m_calleeView, SIGNAL(gotoSourceLocation(QString,int)), this, SLOT(gotoSourceLocation(QString,int))); - d->m_callertree = new QmlProfilerCallerView(mw); - connect(d->m_traceWindow, SIGNAL(range(int,int,int,qint64,qint64,QStringList,QString,int)), - d->m_callertree, SLOT(addRangedEvent(int,int,int,qint64,qint64,QStringList,QString,int))); - connect(d->m_traceWindow, SIGNAL(viewUpdated()), - d->m_callertree, SLOT(complete())); - connect(d->m_callertree, SIGNAL(gotoSourceLocation(QString,int)), + d->m_callerView = new QmlProfilerEventsView(mw, d->m_statistics); + d->m_callerView->setViewType(QmlProfilerEventsView::CallersView); + connect(d->m_callerView, SIGNAL(gotoSourceLocation(QString,int)), this, SLOT(gotoSourceLocation(QString,int))); Core::ICore *core = Core::ICore::instance(); @@ -275,17 +270,17 @@ void QmlProfilerTool::initializeDockWidgets() updateAttachAction(false); - QDockWidget *summaryDock = AnalyzerManager::createDockWidget - (this, tr("Bindings"), d->m_summary, Qt::BottomDockWidgetArea); + QDockWidget *eventsDock = AnalyzerManager::createDockWidget + (this, tr("Events"), d->m_eventsView, Qt::BottomDockWidgetArea); QDockWidget *timelineDock = AnalyzerManager::createDockWidget - (this, tr("Timeline"), d->m_traceWindow, Qt::BottomDockWidgetArea); + (this, tr("Timeline"), d->m_traceWindow, Qt::BottomDockWidgetArea); QDockWidget *calleeDock = AnalyzerManager::createDockWidget - (this, tr("Callees"), d->m_calleetree, Qt::BottomDockWidgetArea); + (this, tr("Callees"), d->m_calleeView, Qt::BottomDockWidgetArea); QDockWidget *callerDock = AnalyzerManager::createDockWidget - (this, tr("Callers"), d->m_callertree, Qt::BottomDockWidgetArea); + (this, tr("Callers"), d->m_callerView, Qt::BottomDockWidgetArea); - mw->splitDockWidget(mw->toolBarDockWidget(), summaryDock, Qt::Vertical); - mw->tabifyDockWidget(summaryDock, timelineDock); + mw->splitDockWidget(mw->toolBarDockWidget(), eventsDock, Qt::Vertical); + mw->tabifyDockWidget(eventsDock, timelineDock); mw->tabifyDockWidget(timelineDock, calleeDock); mw->tabifyDockWidget(calleeDock, callerDock); } @@ -436,9 +431,10 @@ void QmlProfilerTool::updateProjectFileList() void QmlProfilerTool::clearDisplay() { d->m_traceWindow->clearDisplay(); - d->m_summary->clean(); - d->m_calleetree->clean(); - d->m_callertree->clean(); + d->m_statistics->clear(); + d->m_eventsView->clear(); + d->m_calleeView->clear(); + d->m_callerView->clear(); } void QmlProfilerTool::attach() diff --git a/src/plugins/qmlprofiler/qmlprofilertraceclient.cpp b/src/plugins/qmlprofiler/qmlprofilertraceclient.cpp index cfc69dad55..383c6f8610 100644 --- a/src/plugins/qmlprofiler/qmlprofilertraceclient.cpp +++ b/src/plugins/qmlprofiler/qmlprofilertraceclient.cpp @@ -42,14 +42,14 @@ QmlProfilerTraceClient::QmlProfilerTraceClient(QDeclarativeDebugConnection *clie : QDeclarativeDebugClient(QLatin1String("CanvasFrameRate"), client), m_inProgressRanges(0), m_maximumTime(0), m_recording(false), m_nestingLevel(0) { - ::memset(m_rangeCount, 0, MaximumRangeType * sizeof(int)); - ::memset(m_nestingInType, 0, MaximumRangeType * sizeof(int)); + ::memset(m_rangeCount, 0, MaximumQmlEventType * sizeof(int)); + ::memset(m_nestingInType, 0, MaximumQmlEventType * sizeof(int)); } void QmlProfilerTraceClient::clearView() { - ::memset(m_rangeCount, 0, MaximumRangeType * sizeof(int)); - ::memset(m_nestingInType, 0, MaximumRangeType * sizeof(int)); + ::memset(m_rangeCount, 0, MaximumQmlEventType * sizeof(int)); + ::memset(m_nestingInType, 0, MaximumQmlEventType * sizeof(int)); m_nestingLevel = 0; emit clear(); } @@ -111,7 +111,7 @@ void QmlProfilerTraceClient::messageReceived(const QByteArray &data) int range; stream >> range; - if (range >= MaximumRangeType) + if (range >= MaximumQmlEventType) return; if (messageType == RangeStart) { @@ -150,7 +150,7 @@ void QmlProfilerTraceClient::messageReceived(const QByteArray &data) Location location = m_rangeLocations[range].count() ? m_rangeLocations[range].pop() : Location(); qint64 startTime = m_rangeStartTimes[range].pop(); - emit this->range((RangeType)range, m_nestingLevel, m_nestingInType[range], startTime, + emit this->range((QmlEventType)range, m_nestingLevel, m_nestingInType[range], startTime, time - startTime, data, location.fileName, location.line); --m_nestingLevel; --m_nestingInType[range]; diff --git a/src/plugins/qmlprofiler/qmlprofilertraceclient.h b/src/plugins/qmlprofiler/qmlprofilertraceclient.h index 207f63e9d6..65f95b1068 100644 --- a/src/plugins/qmlprofiler/qmlprofilertraceclient.h +++ b/src/plugins/qmlprofiler/qmlprofilertraceclient.h @@ -38,6 +38,8 @@ #include <QtCore/QStack> #include <QtCore/QStringList> +#include "qmlprofilereventtypes.h" + namespace QmlProfiler { namespace Internal { @@ -76,16 +78,6 @@ public: MaximumMessage }; - enum RangeType { - Painting, - Compiling, - Creating, - Binding, - HandlingSignal, - - MaximumRangeType - }; - bool isRecording() const { return m_recording; } public slots: @@ -112,14 +104,14 @@ protected: private: qint64 m_inProgressRanges; - QStack<qint64> m_rangeStartTimes[MaximumRangeType]; - QStack<QStringList> m_rangeDatas[MaximumRangeType]; - QStack<Location> m_rangeLocations[MaximumRangeType]; - int m_rangeCount[MaximumRangeType]; + QStack<qint64> m_rangeStartTimes[MaximumQmlEventType]; + QStack<QStringList> m_rangeDatas[MaximumQmlEventType]; + QStack<Location> m_rangeLocations[MaximumQmlEventType]; + int m_rangeCount[MaximumQmlEventType]; qint64 m_maximumTime; bool m_recording; int m_nestingLevel; - int m_nestingInType[MaximumRangeType]; + int m_nestingInType[MaximumQmlEventType]; }; } // namespace Internal |