forked from qt-creator/qt-creator
QmlProfiler: Split AbstractTimelineModel in two classes
We need a general purpose TimelineModel and a specialized QmlProfilerTimelineModel. Change-Id: I2da02d65efa11e160cab5fa9f8a21075beb0e2bf Reviewed-by: Kai Koehne <kai.koehne@theqtcompany.com>
This commit is contained in:
@@ -1,610 +0,0 @@
|
|||||||
/****************************************************************************
|
|
||||||
**
|
|
||||||
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
|
|
||||||
** Contact: http://www.qt-project.org/legal
|
|
||||||
**
|
|
||||||
** This file is part of Qt Creator.
|
|
||||||
**
|
|
||||||
** Commercial License Usage
|
|
||||||
** Licensees holding valid commercial Qt licenses may use this file in
|
|
||||||
** accordance with the commercial license agreement provided with the
|
|
||||||
** Software or, alternatively, in accordance with the terms contained in
|
|
||||||
** a written agreement between you and Digia. For licensing terms and
|
|
||||||
** conditions see http://www.qt.io/licensing. For further information
|
|
||||||
** use the contact form at http://www.qt.io/contact-us.
|
|
||||||
**
|
|
||||||
** 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 or version 3 as published by the Free
|
|
||||||
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
|
|
||||||
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
|
|
||||||
** following information to ensure the GNU Lesser General Public License
|
|
||||||
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
|
|
||||||
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
|
||||||
**
|
|
||||||
** In addition, as a special exception, Digia gives you certain additional
|
|
||||||
** rights. These rights are described in the Digia Qt LGPL Exception
|
|
||||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
|
||||||
**
|
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
#include "abstracttimelinemodel.h"
|
|
||||||
#include "abstracttimelinemodel_p.h"
|
|
||||||
|
|
||||||
#include <QLinkedList>
|
|
||||||
|
|
||||||
namespace QmlProfiler {
|
|
||||||
|
|
||||||
/*!
|
|
||||||
\class QmlProfiler::AbstractTimelineModel
|
|
||||||
\brief The AbstractTimelineModel class provides a sorted model for timeline data.
|
|
||||||
|
|
||||||
The AbstractTimelineModel lets you keep range data sorted by both start and end times, so that
|
|
||||||
visible ranges can easily be computed. The only precondition for that to work is that the ranges
|
|
||||||
must be perfectly nested. A "parent" range of a range R is defined as a range for which the
|
|
||||||
start time is smaller than R's start time and the end time is greater than R's end time. A set
|
|
||||||
of ranges is perfectly nested if all parent ranges of any given range have a common parent
|
|
||||||
range. Mind that you can always make that happen by defining a range that spans the whole
|
|
||||||
available time span. That, however, will make any code that uses firstStartTime() and
|
|
||||||
lastEndTime() for selecting subsets of the model always select all of it.
|
|
||||||
|
|
||||||
\note Indices returned from the various methods are only valid until a new range is inserted
|
|
||||||
before them. Inserting a new range before a given index moves the range pointed to by the
|
|
||||||
index by one. Incrementing the index by one will make it point to the item again.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*!
|
|
||||||
\fn qint64 AbstractTimelineModelPrivate::firstStartTime() const
|
|
||||||
Returns the begin of the first range in the model.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*!
|
|
||||||
\fn qint64 AbstractTimelineModelPrivate::lastEndTime() const
|
|
||||||
Returns the end of the last range in the model.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*!
|
|
||||||
\fn const AbstractTimelineModelPrivate::Range &AbstractTimelineModelPrivate::range(int index) const
|
|
||||||
Returns the range data at the specified index.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
/*!
|
|
||||||
\fn void AbstractTimelineModel::computeNesting()
|
|
||||||
Compute all ranges' parents.
|
|
||||||
\sa findFirstIndex
|
|
||||||
*/
|
|
||||||
void AbstractTimelineModel::computeNesting()
|
|
||||||
{
|
|
||||||
Q_D(AbstractTimelineModel);
|
|
||||||
QLinkedList<int> parents;
|
|
||||||
for (int range = 0; range != count(); ++range) {
|
|
||||||
AbstractTimelineModelPrivate::Range ¤t = d->ranges[range];
|
|
||||||
for (QLinkedList<int>::iterator parentIt = parents.begin();;) {
|
|
||||||
if (parentIt == parents.end()) {
|
|
||||||
parents.append(range);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
AbstractTimelineModelPrivate::Range &parent = d->ranges[*parentIt];
|
|
||||||
qint64 parentEnd = parent.start + parent.duration;
|
|
||||||
if (parentEnd < current.start) {
|
|
||||||
if (parent.start == current.start) {
|
|
||||||
if (parent.parent == -1) {
|
|
||||||
parent.parent = range;
|
|
||||||
} else {
|
|
||||||
AbstractTimelineModelPrivate::Range &ancestor = d->ranges[parent.parent];
|
|
||||||
if (ancestor.start == current.start &&
|
|
||||||
ancestor.duration < current.duration)
|
|
||||||
parent.parent = range;
|
|
||||||
}
|
|
||||||
// Just switch the old parent range for the new, larger one
|
|
||||||
*parentIt = range;
|
|
||||||
break;
|
|
||||||
} else {
|
|
||||||
parentIt = parents.erase(parentIt);
|
|
||||||
}
|
|
||||||
} else if (parentEnd >= current.start + current.duration) {
|
|
||||||
// no need to insert
|
|
||||||
current.parent = *parentIt;
|
|
||||||
break;
|
|
||||||
} else {
|
|
||||||
++parentIt;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int AbstractTimelineModel::collapsedRowCount() const
|
|
||||||
{
|
|
||||||
Q_D(const AbstractTimelineModel);
|
|
||||||
return d->collapsedRowCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
void AbstractTimelineModel::setCollapsedRowCount(int rows)
|
|
||||||
{
|
|
||||||
Q_D(AbstractTimelineModel);
|
|
||||||
d->collapsedRowCount = rows;
|
|
||||||
}
|
|
||||||
|
|
||||||
int AbstractTimelineModel::expandedRowCount() const
|
|
||||||
{
|
|
||||||
Q_D(const AbstractTimelineModel);
|
|
||||||
return d->expandedRowCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
void QmlProfiler::AbstractTimelineModel::setExpandedRowCount(int rows)
|
|
||||||
{
|
|
||||||
Q_D(AbstractTimelineModel);
|
|
||||||
d->expandedRowCount = rows;
|
|
||||||
}
|
|
||||||
|
|
||||||
void AbstractTimelineModel::AbstractTimelineModelPrivate::init(AbstractTimelineModel *q,
|
|
||||||
QmlProfilerModelManager *manager,
|
|
||||||
const QString &newDisplayName,
|
|
||||||
QmlDebug::Message newMessage,
|
|
||||||
QmlDebug::RangeType newRangeType)
|
|
||||||
{
|
|
||||||
q_ptr = q;
|
|
||||||
modelId = manager->registerModelProxy();
|
|
||||||
modelManager = manager;
|
|
||||||
expanded = false;
|
|
||||||
hidden = false;
|
|
||||||
displayName = newDisplayName;
|
|
||||||
message = newMessage;
|
|
||||||
rangeType = newRangeType;
|
|
||||||
expandedRowCount = 1;
|
|
||||||
collapsedRowCount = 1;
|
|
||||||
connect(modelManager->qmlModel(), SIGNAL(changed()), q, SLOT(_q_dataChanged()));
|
|
||||||
connect(q,SIGNAL(rowHeightChanged()),q,SIGNAL(heightChanged()));
|
|
||||||
connect(q,SIGNAL(expandedChanged()),q,SIGNAL(heightChanged()));
|
|
||||||
connect(q,SIGNAL(hiddenChanged()),q,SIGNAL(heightChanged()));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
AbstractTimelineModel::AbstractTimelineModel(AbstractTimelineModelPrivate *dd,
|
|
||||||
QmlProfilerModelManager *manager, const QString &displayName, QmlDebug::Message message,
|
|
||||||
QmlDebug::RangeType rangeType, QObject *parent) :
|
|
||||||
QObject(parent), d_ptr(dd)
|
|
||||||
{
|
|
||||||
d_ptr->init(this, manager, displayName, message, rangeType);
|
|
||||||
}
|
|
||||||
|
|
||||||
AbstractTimelineModel::AbstractTimelineModel(QmlProfilerModelManager *manager,
|
|
||||||
const QString &displayName, QmlDebug::Message message, QmlDebug::RangeType rangeType,
|
|
||||||
QObject *parent) :
|
|
||||||
QObject(parent), d_ptr(new AbstractTimelineModelPrivate)
|
|
||||||
{
|
|
||||||
d_ptr->init(this, manager, displayName, message, rangeType);
|
|
||||||
}
|
|
||||||
|
|
||||||
AbstractTimelineModel::~AbstractTimelineModel()
|
|
||||||
{
|
|
||||||
Q_D(AbstractTimelineModel);
|
|
||||||
delete d;
|
|
||||||
}
|
|
||||||
|
|
||||||
QmlProfilerModelManager *AbstractTimelineModel::modelManager() const
|
|
||||||
{
|
|
||||||
Q_D(const AbstractTimelineModel);
|
|
||||||
return d->modelManager;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AbstractTimelineModel::isEmpty() const
|
|
||||||
{
|
|
||||||
return count() == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int AbstractTimelineModel::modelId() const
|
|
||||||
{
|
|
||||||
Q_D(const AbstractTimelineModel);
|
|
||||||
return d->modelId;
|
|
||||||
}
|
|
||||||
|
|
||||||
int AbstractTimelineModel::rowHeight(int rowNumber) const
|
|
||||||
{
|
|
||||||
Q_D(const AbstractTimelineModel);
|
|
||||||
if (!expanded())
|
|
||||||
return AbstractTimelineModelPrivate::DefaultRowHeight;
|
|
||||||
|
|
||||||
if (d->rowOffsets.size() > rowNumber)
|
|
||||||
return d->rowOffsets[rowNumber] - (rowNumber > 0 ? d->rowOffsets[rowNumber - 1] : 0);
|
|
||||||
return AbstractTimelineModelPrivate::DefaultRowHeight;
|
|
||||||
}
|
|
||||||
|
|
||||||
int AbstractTimelineModel::rowOffset(int rowNumber) const
|
|
||||||
{
|
|
||||||
Q_D(const AbstractTimelineModel);
|
|
||||||
if (rowNumber == 0)
|
|
||||||
return 0;
|
|
||||||
if (!expanded())
|
|
||||||
return AbstractTimelineModelPrivate::DefaultRowHeight * rowNumber;
|
|
||||||
|
|
||||||
if (d->rowOffsets.size() >= rowNumber)
|
|
||||||
return d->rowOffsets[rowNumber - 1];
|
|
||||||
if (!d->rowOffsets.empty())
|
|
||||||
return d->rowOffsets.last() + (rowNumber - d->rowOffsets.size()) *
|
|
||||||
AbstractTimelineModelPrivate::DefaultRowHeight;
|
|
||||||
return rowNumber * AbstractTimelineModelPrivate::DefaultRowHeight;
|
|
||||||
}
|
|
||||||
|
|
||||||
void AbstractTimelineModel::setRowHeight(int rowNumber, int height)
|
|
||||||
{
|
|
||||||
Q_D(AbstractTimelineModel);
|
|
||||||
if (d->hidden || !d->expanded)
|
|
||||||
return;
|
|
||||||
if (height < AbstractTimelineModelPrivate::DefaultRowHeight)
|
|
||||||
height = AbstractTimelineModelPrivate::DefaultRowHeight;
|
|
||||||
|
|
||||||
int nextOffset = d->rowOffsets.empty() ? 0 : d->rowOffsets.last();
|
|
||||||
while (d->rowOffsets.size() <= rowNumber)
|
|
||||||
d->rowOffsets << (nextOffset += AbstractTimelineModelPrivate::DefaultRowHeight);
|
|
||||||
int difference = height - d->rowOffsets[rowNumber] +
|
|
||||||
(rowNumber > 0 ? d->rowOffsets[rowNumber - 1] : 0);
|
|
||||||
if (difference != 0) {
|
|
||||||
for (; rowNumber < d->rowOffsets.size(); ++rowNumber) {
|
|
||||||
d->rowOffsets[rowNumber] += difference;
|
|
||||||
}
|
|
||||||
emit rowHeightChanged();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int AbstractTimelineModel::height() const
|
|
||||||
{
|
|
||||||
Q_D(const AbstractTimelineModel);
|
|
||||||
int depth = rowCount();
|
|
||||||
if (d->hidden || !d->expanded || d->rowOffsets.empty())
|
|
||||||
return depth * AbstractTimelineModelPrivate::DefaultRowHeight;
|
|
||||||
|
|
||||||
return d->rowOffsets.last() + (depth - d->rowOffsets.size()) *
|
|
||||||
AbstractTimelineModelPrivate::DefaultRowHeight;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
\fn int AbstractTimelineModel::count() const
|
|
||||||
Returns the number of ranges in the model.
|
|
||||||
*/
|
|
||||||
int AbstractTimelineModel::count() const
|
|
||||||
{
|
|
||||||
Q_D(const AbstractTimelineModel);
|
|
||||||
return d->ranges.count();
|
|
||||||
}
|
|
||||||
|
|
||||||
qint64 AbstractTimelineModel::duration(int index) const
|
|
||||||
{
|
|
||||||
Q_D(const AbstractTimelineModel);
|
|
||||||
return d->ranges[index].duration;
|
|
||||||
}
|
|
||||||
|
|
||||||
qint64 AbstractTimelineModel::startTime(int index) const
|
|
||||||
{
|
|
||||||
Q_D(const AbstractTimelineModel);
|
|
||||||
return d->ranges[index].start;
|
|
||||||
}
|
|
||||||
|
|
||||||
qint64 AbstractTimelineModel::endTime(int index) const
|
|
||||||
{
|
|
||||||
Q_D(const AbstractTimelineModel);
|
|
||||||
return d->ranges[index].start + d->ranges[index].duration;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
Returns the type ID of the event with event ID \a index. The type ID is a globally valid ID which
|
|
||||||
can be used to communicate metainformation about events to other parts of the program. By default
|
|
||||||
it is -1, which means there is no global type information about the event.
|
|
||||||
*/
|
|
||||||
int AbstractTimelineModel::typeId(int index) const
|
|
||||||
{
|
|
||||||
Q_UNUSED(index)
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
\fn int AbstractTimelineModel::firstIndex(qint64 startTime) const
|
|
||||||
Looks up the first range with an end time greater than the given time and
|
|
||||||
returns its parent's index. If no such range is found, it returns -1. If there
|
|
||||||
is no parent, it returns the found range's index. The parent of a range is the
|
|
||||||
range with the lowest start time that completely covers the child range.
|
|
||||||
"Completely covers" means:
|
|
||||||
parent.startTime <= child.startTime && parent.endTime >= child.endTime
|
|
||||||
*/
|
|
||||||
int AbstractTimelineModel::firstIndex(qint64 startTime) const
|
|
||||||
{
|
|
||||||
Q_D(const AbstractTimelineModel);
|
|
||||||
int index = firstIndexNoParents(startTime);
|
|
||||||
if (index == -1)
|
|
||||||
return -1;
|
|
||||||
int parent = d->ranges[index].parent;
|
|
||||||
return parent == -1 ? index : parent;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
\fn int AbstractTimelineModel::firstIndexNoParents(qint64 startTime) const
|
|
||||||
Looks up the first range with an end time greater than the given time and
|
|
||||||
returns its index. If no such range is found, it returns -1.
|
|
||||||
*/
|
|
||||||
int AbstractTimelineModel::firstIndexNoParents(qint64 startTime) const
|
|
||||||
{
|
|
||||||
Q_D(const AbstractTimelineModel);
|
|
||||||
// in the "endtime" list, find the first event that ends after startTime
|
|
||||||
if (d->endTimes.isEmpty())
|
|
||||||
return -1;
|
|
||||||
if (d->endTimes.count() == 1 || d->endTimes.first().end > startTime)
|
|
||||||
return d->endTimes.first().startIndex;
|
|
||||||
if (d->endTimes.last().end <= startTime)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
return d->endTimes[d->lowerBound(d->endTimes, startTime) + 1].startIndex;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
\fn int AbstractTimelineModel::lastIndex(qint64 endTime) const
|
|
||||||
Looks up the last range with a start time smaller than the given time and
|
|
||||||
returns its index. If no such range is found, it returns -1.
|
|
||||||
*/
|
|
||||||
int AbstractTimelineModel::lastIndex(qint64 endTime) const
|
|
||||||
{
|
|
||||||
Q_D(const AbstractTimelineModel);
|
|
||||||
// in the "starttime" list, find the last event that starts before endtime
|
|
||||||
if (d->ranges.isEmpty() || d->ranges.first().start >= endTime)
|
|
||||||
return -1;
|
|
||||||
if (d->ranges.count() == 1)
|
|
||||||
return 0;
|
|
||||||
if (d->ranges.last().start < endTime)
|
|
||||||
return d->ranges.count() - 1;
|
|
||||||
|
|
||||||
return d->lowerBound(d->ranges, endTime);
|
|
||||||
}
|
|
||||||
|
|
||||||
QVariantMap AbstractTimelineModel::location(int index) const
|
|
||||||
{
|
|
||||||
Q_UNUSED(index);
|
|
||||||
QVariantMap map;
|
|
||||||
return map;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
Returns \c true if this model can contain events of global type Id \a typeIndex. Otherwise
|
|
||||||
returns \c false.
|
|
||||||
*/
|
|
||||||
bool AbstractTimelineModel::handlesTypeId(int typeIndex) const
|
|
||||||
{
|
|
||||||
if (typeIndex < 0)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
Q_D(const AbstractTimelineModel);
|
|
||||||
return accepted(d->modelManager->qmlModel()->getEventTypes().at(typeIndex));
|
|
||||||
}
|
|
||||||
|
|
||||||
int AbstractTimelineModel::selectionIdForLocation(const QString &filename, int line, int column) const
|
|
||||||
{
|
|
||||||
Q_UNUSED(filename);
|
|
||||||
Q_UNUSED(line);
|
|
||||||
Q_UNUSED(column);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int AbstractTimelineModel::bindingLoopDest(int index) const
|
|
||||||
{
|
|
||||||
Q_UNUSED(index);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
float AbstractTimelineModel::relativeHeight(int index) const
|
|
||||||
{
|
|
||||||
Q_UNUSED(index);
|
|
||||||
return 1.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
int AbstractTimelineModel::rowMinValue(int rowNumber) const
|
|
||||||
{
|
|
||||||
Q_UNUSED(rowNumber);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int AbstractTimelineModel::rowMaxValue(int rowNumber) const
|
|
||||||
{
|
|
||||||
Q_UNUSED(rowNumber);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int AbstractTimelineModel::defaultRowHeight()
|
|
||||||
{
|
|
||||||
return AbstractTimelineModelPrivate::DefaultRowHeight;
|
|
||||||
}
|
|
||||||
|
|
||||||
QmlDebug::RangeType AbstractTimelineModel::rangeType() const
|
|
||||||
{
|
|
||||||
Q_D(const AbstractTimelineModel);
|
|
||||||
return d->rangeType;
|
|
||||||
}
|
|
||||||
|
|
||||||
QmlDebug::Message AbstractTimelineModel::message() const
|
|
||||||
{
|
|
||||||
Q_D(const AbstractTimelineModel);
|
|
||||||
return d->message;
|
|
||||||
}
|
|
||||||
|
|
||||||
void AbstractTimelineModel::updateProgress(qint64 count, qint64 max) const
|
|
||||||
{
|
|
||||||
Q_D(const AbstractTimelineModel);
|
|
||||||
d->modelManager->modelProxyCountUpdated(d->modelId, count, max);
|
|
||||||
}
|
|
||||||
|
|
||||||
void AbstractTimelineModel::announceFeatures(quint64 features) const
|
|
||||||
{
|
|
||||||
Q_D(const AbstractTimelineModel);
|
|
||||||
d->modelManager->announceFeatures(d->modelId, features);
|
|
||||||
}
|
|
||||||
|
|
||||||
QColor AbstractTimelineModel::colorBySelectionId(int index) const
|
|
||||||
{
|
|
||||||
return colorByHue(selectionId(index) * AbstractTimelineModelPrivate::SelectionIdHueMultiplier);
|
|
||||||
}
|
|
||||||
|
|
||||||
QColor AbstractTimelineModel::colorByFraction(double fraction) const
|
|
||||||
{
|
|
||||||
return colorByHue(fraction * AbstractTimelineModelPrivate::FractionHueMultiplier +
|
|
||||||
AbstractTimelineModelPrivate::FractionHueMininimum);
|
|
||||||
}
|
|
||||||
|
|
||||||
QColor AbstractTimelineModel::colorByHue(int hue) const
|
|
||||||
{
|
|
||||||
return QColor::fromHsl(hue % 360, AbstractTimelineModelPrivate::Saturation,
|
|
||||||
AbstractTimelineModelPrivate::Lightness);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
Inserts an event at the time specified by \a startTime with the given \a duration and returns
|
|
||||||
its index. The \a selectionId determines the selection group the new event belongs to.
|
|
||||||
\sa selectionId()
|
|
||||||
*/
|
|
||||||
int AbstractTimelineModel::insert(qint64 startTime, qint64 duration, int selectionId)
|
|
||||||
{
|
|
||||||
Q_D(AbstractTimelineModel);
|
|
||||||
/* Doing insert-sort here is preferable as most of the time the times will actually be
|
|
||||||
* presorted in the right way. So usually this will just result in appending. */
|
|
||||||
int index = d->insertSorted(d->ranges,
|
|
||||||
AbstractTimelineModelPrivate::Range(startTime, duration, selectionId));
|
|
||||||
if (index < d->ranges.size() - 1)
|
|
||||||
d->incrementStartIndices(index);
|
|
||||||
d->insertSorted(d->endTimes,
|
|
||||||
AbstractTimelineModelPrivate::RangeEnd(index, startTime + duration));
|
|
||||||
return index;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
Inserts a range start at the time given by \a startTime and returns its index. The range end is
|
|
||||||
not set. The \a selectionId determines the selection group the new event belongs to.
|
|
||||||
\sa selectionId()
|
|
||||||
*/
|
|
||||||
int AbstractTimelineModel::insertStart(qint64 startTime, int selectionId)
|
|
||||||
{
|
|
||||||
Q_D(AbstractTimelineModel);
|
|
||||||
int index = d->insertSorted(d->ranges,
|
|
||||||
AbstractTimelineModelPrivate::Range(startTime, 0, selectionId));
|
|
||||||
if (index < d->ranges.size() - 1)
|
|
||||||
d->incrementStartIndices(index);
|
|
||||||
return index;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
\fn int AbstractTimelineModel::insertEnd(int index, qint64 duration)
|
|
||||||
Adds a range end for the given start index.
|
|
||||||
*/
|
|
||||||
void AbstractTimelineModel::insertEnd(int index, qint64 duration)
|
|
||||||
{
|
|
||||||
Q_D(AbstractTimelineModel);
|
|
||||||
d->ranges[index].duration = duration;
|
|
||||||
d->insertSorted(d->endTimes, AbstractTimelineModelPrivate::RangeEnd(index,
|
|
||||||
d->ranges[index].start + duration));
|
|
||||||
}
|
|
||||||
|
|
||||||
void AbstractTimelineModel::AbstractTimelineModelPrivate::_q_dataChanged()
|
|
||||||
{
|
|
||||||
Q_Q(AbstractTimelineModel);
|
|
||||||
bool wasEmpty = q->isEmpty();
|
|
||||||
switch (modelManager->state()) {
|
|
||||||
case QmlProfilerDataState::ProcessingData:
|
|
||||||
q->loadData();
|
|
||||||
break;
|
|
||||||
case QmlProfilerDataState::ClearingData:
|
|
||||||
q->clear();
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (wasEmpty != q->isEmpty())
|
|
||||||
emit q->emptyChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AbstractTimelineModel::accepted(const QmlProfilerDataModel::QmlEventTypeData &event) const
|
|
||||||
{
|
|
||||||
Q_D(const AbstractTimelineModel);
|
|
||||||
return (event.rangeType == d->rangeType && event.message == d->message);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AbstractTimelineModel::expanded() const
|
|
||||||
{
|
|
||||||
Q_D(const AbstractTimelineModel);
|
|
||||||
return d->expanded;
|
|
||||||
}
|
|
||||||
|
|
||||||
void AbstractTimelineModel::setExpanded(bool expanded)
|
|
||||||
{
|
|
||||||
Q_D(AbstractTimelineModel);
|
|
||||||
if (expanded != d->expanded) {
|
|
||||||
d->expanded = expanded;
|
|
||||||
emit expandedChanged();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AbstractTimelineModel::hidden() const
|
|
||||||
{
|
|
||||||
Q_D(const AbstractTimelineModel);
|
|
||||||
return d->hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
void AbstractTimelineModel::setHidden(bool hidden)
|
|
||||||
{
|
|
||||||
Q_D(AbstractTimelineModel);
|
|
||||||
if (hidden != d->hidden) {
|
|
||||||
d->hidden = hidden;
|
|
||||||
emit hiddenChanged();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
QString AbstractTimelineModel::displayName() const
|
|
||||||
{
|
|
||||||
Q_D(const AbstractTimelineModel);
|
|
||||||
return d->displayName;
|
|
||||||
}
|
|
||||||
|
|
||||||
int AbstractTimelineModel::rowCount() const
|
|
||||||
{
|
|
||||||
Q_D(const AbstractTimelineModel);
|
|
||||||
if (d->hidden)
|
|
||||||
return 0;
|
|
||||||
if (isEmpty())
|
|
||||||
return d->modelManager->isEmpty() ? 1 : 0;
|
|
||||||
return d->expanded ? d->expandedRowCount : d->collapsedRowCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
Returns the ID of the selection group the event with event Id \a index belongs to. Selection
|
|
||||||
groups are local to the model and the model can arbitrarily assign events to selection groups
|
|
||||||
when inserting them.
|
|
||||||
If one event from a selection group is selected, all visible other events from the same
|
|
||||||
selection group are highlighted. Rows are expected to correspond to selection IDs when the view
|
|
||||||
is expanded.
|
|
||||||
*/
|
|
||||||
int AbstractTimelineModel::selectionId(int index) const
|
|
||||||
{
|
|
||||||
Q_D(const AbstractTimelineModel);
|
|
||||||
return d->ranges[index].selectionId;
|
|
||||||
}
|
|
||||||
|
|
||||||
void AbstractTimelineModel::clear()
|
|
||||||
{
|
|
||||||
Q_D(AbstractTimelineModel);
|
|
||||||
d->collapsedRowCount = d->expandedRowCount = 1;
|
|
||||||
bool wasExpanded = d->expanded;
|
|
||||||
bool wasHidden = d->hidden;
|
|
||||||
bool hadRowHeights = !d->rowOffsets.empty();
|
|
||||||
d->rowOffsets.clear();
|
|
||||||
d->expanded = false;
|
|
||||||
d->hidden = false;
|
|
||||||
d->ranges.clear();
|
|
||||||
d->endTimes.clear();
|
|
||||||
if (hadRowHeights)
|
|
||||||
emit rowHeightChanged();
|
|
||||||
if (wasExpanded)
|
|
||||||
emit expandedChanged();
|
|
||||||
if (wasHidden)
|
|
||||||
emit hiddenChanged();
|
|
||||||
updateProgress(0, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#include "moc_abstracttimelinemodel.cpp"
|
|
||||||
@@ -5,7 +5,6 @@ QT += network qml quick
|
|||||||
include(../../qtcreatorplugin.pri)
|
include(../../qtcreatorplugin.pri)
|
||||||
|
|
||||||
SOURCES += \
|
SOURCES += \
|
||||||
abstracttimelinemodel.cpp \
|
|
||||||
localqmlprofilerrunner.cpp \
|
localqmlprofilerrunner.cpp \
|
||||||
qmlprofileranimationsmodel.cpp \
|
qmlprofileranimationsmodel.cpp \
|
||||||
qmlprofilerattachdialog.cpp \
|
qmlprofilerattachdialog.cpp \
|
||||||
@@ -23,6 +22,7 @@ SOURCES += \
|
|||||||
qmlprofilerruncontrolfactory.cpp \
|
qmlprofilerruncontrolfactory.cpp \
|
||||||
qmlprofilerstatemanager.cpp \
|
qmlprofilerstatemanager.cpp \
|
||||||
qmlprofilerstatewidget.cpp \
|
qmlprofilerstatewidget.cpp \
|
||||||
|
qmlprofilertimelinemodel.cpp \
|
||||||
qmlprofilertimelinemodelfactory.cpp \
|
qmlprofilertimelinemodelfactory.cpp \
|
||||||
qmlprofilertool.cpp \
|
qmlprofilertool.cpp \
|
||||||
qmlprofilertracefile.cpp \
|
qmlprofilertracefile.cpp \
|
||||||
@@ -31,14 +31,13 @@ SOURCES += \
|
|||||||
qmlprofilerviewmanager.cpp \
|
qmlprofilerviewmanager.cpp \
|
||||||
qv8profilerdatamodel.cpp \
|
qv8profilerdatamodel.cpp \
|
||||||
qv8profilereventview.cpp \
|
qv8profilereventview.cpp \
|
||||||
|
timelinemodel.cpp \
|
||||||
timelinemodelaggregator.cpp \
|
timelinemodelaggregator.cpp \
|
||||||
timelinerenderer.cpp \
|
timelinerenderer.cpp \
|
||||||
timelinezoomcontrol.cpp
|
timelinezoomcontrol.cpp
|
||||||
|
|
||||||
HEADERS += \
|
HEADERS += \
|
||||||
abstractqmlprofilerrunner.h \
|
abstractqmlprofilerrunner.h \
|
||||||
abstracttimelinemodel.h \
|
|
||||||
abstracttimelinemodel_p.h \
|
|
||||||
localqmlprofilerrunner.h \
|
localqmlprofilerrunner.h \
|
||||||
qmlprofiler_global.h \
|
qmlprofiler_global.h \
|
||||||
qmlprofileranimationsmodel.h \
|
qmlprofileranimationsmodel.h \
|
||||||
@@ -59,6 +58,7 @@ HEADERS += \
|
|||||||
qmlprofilerruncontrolfactory.h \
|
qmlprofilerruncontrolfactory.h \
|
||||||
qmlprofilerstatemanager.h \
|
qmlprofilerstatemanager.h \
|
||||||
qmlprofilerstatewidget.h \
|
qmlprofilerstatewidget.h \
|
||||||
|
qmlprofilertimelinemodel.h \
|
||||||
qmlprofilertimelinemodelfactory.h \
|
qmlprofilertimelinemodelfactory.h \
|
||||||
qmlprofilertool.h \
|
qmlprofilertool.h \
|
||||||
qmlprofilertracefile.h \
|
qmlprofilertracefile.h \
|
||||||
@@ -67,6 +67,8 @@ HEADERS += \
|
|||||||
qmlprofilerviewmanager.h \
|
qmlprofilerviewmanager.h \
|
||||||
qv8profilerdatamodel.h \
|
qv8profilerdatamodel.h \
|
||||||
qv8profilereventview.h \
|
qv8profilereventview.h \
|
||||||
|
timelinemodel.h \
|
||||||
|
timelinemodel_p.h \
|
||||||
timelinemodelaggregator.h \
|
timelinemodelaggregator.h \
|
||||||
timelinerenderer.h \
|
timelinerenderer.h \
|
||||||
timelinezoomcontrol.h
|
timelinezoomcontrol.h
|
||||||
|
|||||||
@@ -21,7 +21,6 @@ QtcPlugin {
|
|||||||
name: "General"
|
name: "General"
|
||||||
files: [
|
files: [
|
||||||
"abstractqmlprofilerrunner.h",
|
"abstractqmlprofilerrunner.h",
|
||||||
"abstracttimelinemodel.h", "abstracttimelinemodel_p.h", "abstracttimelinemodel.cpp",
|
|
||||||
"localqmlprofilerrunner.cpp", "localqmlprofilerrunner.h",
|
"localqmlprofilerrunner.cpp", "localqmlprofilerrunner.h",
|
||||||
"qmlprofiler_global.h",
|
"qmlprofiler_global.h",
|
||||||
"qmlprofileranimationsmodel.h", "qmlprofileranimationsmodel.cpp",
|
"qmlprofileranimationsmodel.h", "qmlprofileranimationsmodel.cpp",
|
||||||
@@ -41,6 +40,7 @@ QtcPlugin {
|
|||||||
"qmlprofilerstatemanager.cpp", "qmlprofilerstatemanager.h",
|
"qmlprofilerstatemanager.cpp", "qmlprofilerstatemanager.h",
|
||||||
"qmlprofilerstatewidget.cpp", "qmlprofilerstatewidget.h",
|
"qmlprofilerstatewidget.cpp", "qmlprofilerstatewidget.h",
|
||||||
"qmlprofilerrangemodel.cpp", "qmlprofilerrangemodel.h",
|
"qmlprofilerrangemodel.cpp", "qmlprofilerrangemodel.h",
|
||||||
|
"qmlprofilertimelinemodel.cpp", "qmlprofilertimelinemodel.h",
|
||||||
"qmlprofilertimelinemodelfactory.cpp", "qmlprofilertimelinemodelfactory.h",
|
"qmlprofilertimelinemodelfactory.cpp", "qmlprofilertimelinemodelfactory.h",
|
||||||
"qmlprofilertool.cpp", "qmlprofilertool.h",
|
"qmlprofilertool.cpp", "qmlprofilertool.h",
|
||||||
"qmlprofilertracefile.cpp", "qmlprofilertracefile.h",
|
"qmlprofilertracefile.cpp", "qmlprofilertracefile.h",
|
||||||
@@ -49,6 +49,7 @@ QtcPlugin {
|
|||||||
"qmlprofilerviewmanager.cpp", "qmlprofilerviewmanager.h",
|
"qmlprofilerviewmanager.cpp", "qmlprofilerviewmanager.h",
|
||||||
"qv8profilerdatamodel.cpp", "qv8profilerdatamodel.h",
|
"qv8profilerdatamodel.cpp", "qv8profilerdatamodel.h",
|
||||||
"qv8profilereventview.h", "qv8profilereventview.cpp",
|
"qv8profilereventview.h", "qv8profilereventview.cpp",
|
||||||
|
"timelinemodel.cpp", "timelinemodel.h", "timelinemodel_p.h",
|
||||||
"timelinemodelaggregator.cpp", "timelinemodelaggregator.h",
|
"timelinemodelaggregator.cpp", "timelinemodelaggregator.h",
|
||||||
"timelinerenderer.cpp", "timelinerenderer.h",
|
"timelinerenderer.cpp", "timelinerenderer.h",
|
||||||
"timelinezoomcontrol.cpp", "timelinezoomcontrol.h"
|
"timelinezoomcontrol.cpp", "timelinezoomcontrol.h"
|
||||||
|
|||||||
@@ -31,7 +31,6 @@
|
|||||||
#include "qmlprofileranimationsmodel.h"
|
#include "qmlprofileranimationsmodel.h"
|
||||||
#include "qmlprofilermodelmanager.h"
|
#include "qmlprofilermodelmanager.h"
|
||||||
#include "qmlprofilerdatamodel.h"
|
#include "qmlprofilerdatamodel.h"
|
||||||
#include "abstracttimelinemodel_p.h"
|
|
||||||
#include <utils/qtcassert.h>
|
#include <utils/qtcassert.h>
|
||||||
#include <QCoreApplication>
|
#include <QCoreApplication>
|
||||||
|
|
||||||
@@ -47,8 +46,8 @@ namespace QmlProfiler {
|
|||||||
namespace Internal {
|
namespace Internal {
|
||||||
|
|
||||||
QmlProfilerAnimationsModel::QmlProfilerAnimationsModel(QmlProfilerModelManager *manager,
|
QmlProfilerAnimationsModel::QmlProfilerAnimationsModel(QmlProfilerModelManager *manager,
|
||||||
QObject *parent)
|
QObject *parent) :
|
||||||
: AbstractTimelineModel(manager,
|
QmlProfilerTimelineModel(manager,
|
||||||
tr(QmlProfilerModelManager::featureName(QmlDebug::ProfileAnimations)),
|
tr(QmlProfilerModelManager::featureName(QmlDebug::ProfileAnimations)),
|
||||||
QmlDebug::Event, QmlDebug::MaximumRangeType, parent)
|
QmlDebug::Event, QmlDebug::MaximumRangeType, parent)
|
||||||
{
|
{
|
||||||
@@ -60,12 +59,12 @@ void QmlProfilerAnimationsModel::clear()
|
|||||||
{
|
{
|
||||||
m_maxGuiThreadAnimations = m_maxRenderThreadAnimations = 0;
|
m_maxGuiThreadAnimations = m_maxRenderThreadAnimations = 0;
|
||||||
m_data.clear();
|
m_data.clear();
|
||||||
AbstractTimelineModel::clear();
|
QmlProfilerTimelineModel::clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QmlProfilerAnimationsModel::accepted(const QmlProfilerDataModel::QmlEventTypeData &event) const
|
bool QmlProfilerAnimationsModel::accepted(const QmlProfilerDataModel::QmlEventTypeData &event) const
|
||||||
{
|
{
|
||||||
return AbstractTimelineModel::accepted(event) &&
|
return QmlProfilerTimelineModel::accepted(event) &&
|
||||||
event.detailType== QmlDebug::AnimationFrame;
|
event.detailType== QmlDebug::AnimationFrame;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -149,7 +148,7 @@ int QmlProfilerAnimationsModel::rowMaxValue(int rowNumber) const
|
|||||||
case 2:
|
case 2:
|
||||||
return m_maxRenderThreadAnimations;
|
return m_maxRenderThreadAnimations;
|
||||||
default:
|
default:
|
||||||
return AbstractTimelineModel::rowMaxValue(rowNumber);
|
return QmlProfilerTimelineModel::rowMaxValue(rowNumber);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -33,7 +33,7 @@
|
|||||||
#define QMLPROFILERANIMATIONSMODEL_H
|
#define QMLPROFILERANIMATIONSMODEL_H
|
||||||
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include "abstracttimelinemodel.h"
|
#include "qmlprofilertimelinemodel.h"
|
||||||
#include <qmldebug/qmlprofilereventtypes.h>
|
#include <qmldebug/qmlprofilereventtypes.h>
|
||||||
#include <qmldebug/qmlprofilereventlocation.h>
|
#include <qmldebug/qmlprofilereventlocation.h>
|
||||||
//#include <QHash>
|
//#include <QHash>
|
||||||
@@ -49,7 +49,7 @@ class QmlProfilerModelManager;
|
|||||||
|
|
||||||
namespace Internal {
|
namespace Internal {
|
||||||
|
|
||||||
class QmlProfilerAnimationsModel : public AbstractTimelineModel
|
class QmlProfilerAnimationsModel : public QmlProfilerTimelineModel
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
|
|||||||
@@ -47,9 +47,9 @@ void QmlProfilerNotesModel::setModelManager(QmlProfilerModelManager *modelManage
|
|||||||
m_modelManager = modelManager;
|
m_modelManager = modelManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
void QmlProfilerNotesModel::addTimelineModel(const AbstractTimelineModel *timelineModel)
|
void QmlProfilerNotesModel::addTimelineModel(const QmlProfilerTimelineModel *timelineModel)
|
||||||
{
|
{
|
||||||
connect(timelineModel, &AbstractTimelineModel::destroyed,
|
connect(timelineModel, &QmlProfilerTimelineModel::destroyed,
|
||||||
this, &QmlProfilerNotesModel::removeTimelineModel);
|
this, &QmlProfilerNotesModel::removeTimelineModel);
|
||||||
m_timelineModels.insert(timelineModel->modelId(), timelineModel);
|
m_timelineModels.insert(timelineModel->modelId(), timelineModel);
|
||||||
}
|
}
|
||||||
@@ -111,7 +111,7 @@ int QmlProfilerNotesModel::get(int timelineModel, int timelineIndex) const
|
|||||||
|
|
||||||
int QmlProfilerNotesModel::add(int timelineModel, int timelineIndex, const QString &text)
|
int QmlProfilerNotesModel::add(int timelineModel, int timelineIndex, const QString &text)
|
||||||
{
|
{
|
||||||
const AbstractTimelineModel *model = m_timelineModels[timelineModel];
|
const QmlProfilerTimelineModel *model = m_timelineModels[timelineModel];
|
||||||
int typeId = model->typeId(timelineIndex);
|
int typeId = model->typeId(timelineIndex);
|
||||||
Note note = { text, timelineModel, timelineIndex };
|
Note note = { text, timelineModel, timelineIndex };
|
||||||
m_data << note;
|
m_data << note;
|
||||||
@@ -162,7 +162,7 @@ int QmlProfilerNotesModel::add(int typeId, qint64 start, qint64 duration, const
|
|||||||
int timelineIndex = -1;
|
int timelineIndex = -1;
|
||||||
const QVector<QmlProfilerDataModel::QmlEventTypeData> &types =
|
const QVector<QmlProfilerDataModel::QmlEventTypeData> &types =
|
||||||
m_modelManager->qmlModel()->getEventTypes();
|
m_modelManager->qmlModel()->getEventTypes();
|
||||||
foreach (const AbstractTimelineModel *model, m_timelineModels) {
|
foreach (const QmlProfilerTimelineModel *model, m_timelineModels) {
|
||||||
if (model->accepted(types[typeId])) {
|
if (model->accepted(types[typeId])) {
|
||||||
for (int i = model->firstIndex(start); i <= model->lastIndex(start + duration); ++i) {
|
for (int i = model->firstIndex(start); i <= model->lastIndex(start + duration); ++i) {
|
||||||
if (i < 0)
|
if (i < 0)
|
||||||
@@ -237,7 +237,7 @@ void QmlProfilerNotesModel::saveData()
|
|||||||
if (it == m_timelineModels.end())
|
if (it == m_timelineModels.end())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
const AbstractTimelineModel *model = it.value();
|
const QmlProfilerTimelineModel *model = it.value();
|
||||||
QmlProfilerDataModel::QmlEventNoteData save = {
|
QmlProfilerDataModel::QmlEventNoteData save = {
|
||||||
model->typeId(note.timelineIndex), model->startTime(note.timelineIndex),
|
model->typeId(note.timelineIndex), model->startTime(note.timelineIndex),
|
||||||
model->duration(note.timelineIndex), note.text
|
model->duration(note.timelineIndex), note.text
|
||||||
|
|||||||
@@ -31,7 +31,7 @@
|
|||||||
#ifndef NOTESMODEL_H
|
#ifndef NOTESMODEL_H
|
||||||
#define NOTESMODEL_H
|
#define NOTESMODEL_H
|
||||||
|
|
||||||
#include "abstracttimelinemodel.h"
|
#include "qmlprofilertimelinemodel.h"
|
||||||
#include "qmlprofilermodelmanager.h"
|
#include "qmlprofilermodelmanager.h"
|
||||||
#include <QList>
|
#include <QList>
|
||||||
#include <QHash>
|
#include <QHash>
|
||||||
@@ -54,7 +54,7 @@ public:
|
|||||||
int count() const;
|
int count() const;
|
||||||
|
|
||||||
void setModelManager(QmlProfilerModelManager *modelManager);
|
void setModelManager(QmlProfilerModelManager *modelManager);
|
||||||
void addTimelineModel(const AbstractTimelineModel *timelineModel);
|
void addTimelineModel(const QmlProfilerTimelineModel *timelineModel);
|
||||||
|
|
||||||
Q_INVOKABLE int typeId(int index) const;
|
Q_INVOKABLE int typeId(int index) const;
|
||||||
Q_INVOKABLE QString text(int index) const;
|
Q_INVOKABLE QString text(int index) const;
|
||||||
@@ -86,7 +86,7 @@ private slots:
|
|||||||
protected:
|
protected:
|
||||||
QmlProfilerModelManager *m_modelManager;
|
QmlProfilerModelManager *m_modelManager;
|
||||||
QList<Note> m_data;
|
QList<Note> m_data;
|
||||||
QHash<int, const AbstractTimelineModel *> m_timelineModels;
|
QHash<int, const QmlProfilerTimelineModel *> m_timelineModels;
|
||||||
bool m_modified;
|
bool m_modified;
|
||||||
|
|
||||||
int add(int typeId, qint64 startTime, qint64 duration, const QString &text);
|
int add(int typeId, qint64 startTime, qint64 duration, const QString &text);
|
||||||
|
|||||||
@@ -32,7 +32,7 @@
|
|||||||
#include "qmlprofilerruncontrolfactory.h"
|
#include "qmlprofilerruncontrolfactory.h"
|
||||||
|
|
||||||
#include "qmlprofilertool.h"
|
#include "qmlprofilertool.h"
|
||||||
#include "abstracttimelinemodel.h"
|
#include "qmlprofilertimelinemodel.h"
|
||||||
|
|
||||||
#include <analyzerbase/analyzermanager.h>
|
#include <analyzerbase/analyzermanager.h>
|
||||||
#include <extensionsystem/pluginmanager.h>
|
#include <extensionsystem/pluginmanager.h>
|
||||||
@@ -103,7 +103,7 @@ ExtensionSystem::IPlugin::ShutdownFlag QmlProfilerPlugin::aboutToShutdown()
|
|||||||
return SynchronousShutdown;
|
return SynchronousShutdown;
|
||||||
}
|
}
|
||||||
|
|
||||||
QList<AbstractTimelineModel *> QmlProfilerPlugin::getModels(QmlProfilerModelManager *manager) const
|
QList<QmlProfilerTimelineModel *> QmlProfilerPlugin::getModels(QmlProfilerModelManager *manager) const
|
||||||
{
|
{
|
||||||
return factory->create(manager);
|
return factory->create(manager);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,7 +35,7 @@
|
|||||||
#include "qmlprofilertimelinemodelfactory.h"
|
#include "qmlprofilertimelinemodelfactory.h"
|
||||||
#include <extensionsystem/iplugin.h>
|
#include <extensionsystem/iplugin.h>
|
||||||
|
|
||||||
#include "abstracttimelinemodel.h"
|
#include "qmlprofilertimelinemodel.h"
|
||||||
|
|
||||||
namespace QmlProfiler {
|
namespace QmlProfiler {
|
||||||
namespace Internal {
|
namespace Internal {
|
||||||
@@ -55,7 +55,7 @@ public:
|
|||||||
static bool debugOutput;
|
static bool debugOutput;
|
||||||
static QmlProfilerPlugin *instance;
|
static QmlProfilerPlugin *instance;
|
||||||
|
|
||||||
QList<AbstractTimelineModel *> getModels(QmlProfilerModelManager *manager) const;
|
QList<QmlProfilerTimelineModel *> getModels(QmlProfilerModelManager *manager) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QmlProfilerTimelineModelFactory *factory;
|
QmlProfilerTimelineModelFactory *factory;
|
||||||
|
|||||||
@@ -46,8 +46,8 @@ namespace Internal {
|
|||||||
|
|
||||||
|
|
||||||
QmlProfilerRangeModel::QmlProfilerRangeModel(QmlProfilerModelManager *manager,
|
QmlProfilerRangeModel::QmlProfilerRangeModel(QmlProfilerModelManager *manager,
|
||||||
QmlDebug::RangeType range, QObject *parent)
|
QmlDebug::RangeType range, QObject *parent) :
|
||||||
: AbstractTimelineModel(manager, categoryLabel(range), QmlDebug::MaximumMessage, range, parent)
|
QmlProfilerTimelineModel(manager, categoryLabel(range), QmlDebug::MaximumMessage, range, parent)
|
||||||
{
|
{
|
||||||
m_expandedRowTypes << -1;
|
m_expandedRowTypes << -1;
|
||||||
announceFeatures(1ULL << QmlDebug::featureFromRangeType(rangeType()));
|
announceFeatures(1ULL << QmlDebug::featureFromRangeType(rangeType()));
|
||||||
@@ -58,7 +58,7 @@ void QmlProfilerRangeModel::clear()
|
|||||||
m_expandedRowTypes.clear();
|
m_expandedRowTypes.clear();
|
||||||
m_expandedRowTypes << -1;
|
m_expandedRowTypes << -1;
|
||||||
m_data.clear();
|
m_data.clear();
|
||||||
AbstractTimelineModel::clear();
|
QmlProfilerTimelineModel::clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void QmlProfilerRangeModel::loadData()
|
void QmlProfilerRangeModel::loadData()
|
||||||
|
|||||||
@@ -32,7 +32,7 @@
|
|||||||
#ifndef QMLPROFILERRANGEMODEL_H
|
#ifndef QMLPROFILERRANGEMODEL_H
|
||||||
#define QMLPROFILERRANGEMODEL_H
|
#define QMLPROFILERRANGEMODEL_H
|
||||||
|
|
||||||
#include "abstracttimelinemodel.h"
|
#include "qmlprofilertimelinemodel.h"
|
||||||
#include <qmldebug/qmlprofilereventtypes.h>
|
#include <qmldebug/qmlprofilereventtypes.h>
|
||||||
#include <qmldebug/qmlprofilereventlocation.h>
|
#include <qmldebug/qmlprofilereventlocation.h>
|
||||||
#include <QVariantList>
|
#include <QVariantList>
|
||||||
@@ -44,7 +44,7 @@ class QmlProfilerModelManager;
|
|||||||
|
|
||||||
namespace Internal {
|
namespace Internal {
|
||||||
|
|
||||||
class QmlProfilerRangeModel : public AbstractTimelineModel
|
class QmlProfilerRangeModel : public QmlProfilerTimelineModel
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
|
|||||||
112
src/plugins/qmlprofiler/qmlprofilertimelinemodel.cpp
Normal file
112
src/plugins/qmlprofiler/qmlprofilertimelinemodel.cpp
Normal file
@@ -0,0 +1,112 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
|
||||||
|
** Contact: http://www.qt-project.org/legal
|
||||||
|
**
|
||||||
|
** This file is part of Qt Creator.
|
||||||
|
**
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and Digia. For licensing terms and
|
||||||
|
** conditions see http://www.qt.io/licensing. For further information
|
||||||
|
** use the contact form at http://www.qt.io/contact-us.
|
||||||
|
**
|
||||||
|
** 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 or version 3 as published by the Free
|
||||||
|
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
|
||||||
|
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
|
||||||
|
** following information to ensure the GNU Lesser General Public License
|
||||||
|
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
|
||||||
|
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||||
|
**
|
||||||
|
** In addition, as a special exception, Digia gives you certain additional
|
||||||
|
** rights. These rights are described in the Digia Qt LGPL Exception
|
||||||
|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#include "qmlprofilertimelinemodel.h"
|
||||||
|
|
||||||
|
namespace QmlProfiler {
|
||||||
|
|
||||||
|
QmlProfilerTimelineModel::QmlProfilerTimelineModel(QmlProfilerModelManager *modelManager,
|
||||||
|
const QString &displayName,
|
||||||
|
QmlDebug::Message message,
|
||||||
|
QmlDebug::RangeType rangeType, QObject *parent) :
|
||||||
|
TimelineModel(modelManager->registerModelProxy(), displayName, parent), m_message(message),
|
||||||
|
m_rangeType(rangeType), m_modelManager(modelManager)
|
||||||
|
{
|
||||||
|
connect(modelManager->qmlModel(), &QmlProfilerDataModel::changed,
|
||||||
|
this, &QmlProfilerTimelineModel::dataChanged);
|
||||||
|
}
|
||||||
|
|
||||||
|
QmlDebug::RangeType QmlProfilerTimelineModel::rangeType() const
|
||||||
|
{
|
||||||
|
return m_rangeType;
|
||||||
|
}
|
||||||
|
|
||||||
|
QmlDebug::Message QmlProfilerTimelineModel::message() const
|
||||||
|
{
|
||||||
|
return m_message;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QmlProfilerTimelineModel::accepted(const QmlProfilerDataModel::QmlEventTypeData &event) const
|
||||||
|
{
|
||||||
|
return (event.rangeType == m_rangeType && event.message == m_message);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QmlProfilerTimelineModel::handlesTypeId(int typeIndex) const
|
||||||
|
{
|
||||||
|
if (typeIndex < 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return accepted(modelManager()->qmlModel()->getEventTypes().at(typeIndex));
|
||||||
|
}
|
||||||
|
|
||||||
|
void QmlProfilerTimelineModel::clear()
|
||||||
|
{
|
||||||
|
TimelineModel::clear();
|
||||||
|
updateProgress(0, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
QmlProfilerModelManager *QmlProfilerTimelineModel::modelManager() const
|
||||||
|
{
|
||||||
|
return m_modelManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QmlProfilerTimelineModel::updateProgress(qint64 count, qint64 max) const
|
||||||
|
{
|
||||||
|
m_modelManager->modelProxyCountUpdated(modelId(), count, max);
|
||||||
|
}
|
||||||
|
|
||||||
|
void QmlProfilerTimelineModel::announceFeatures(quint64 features) const
|
||||||
|
{
|
||||||
|
m_modelManager->announceFeatures(modelId(), features);
|
||||||
|
}
|
||||||
|
|
||||||
|
void QmlProfilerTimelineModel::dataChanged()
|
||||||
|
{
|
||||||
|
|
||||||
|
switch (m_modelManager->state()) {
|
||||||
|
case QmlProfilerDataState::ProcessingData:
|
||||||
|
loadData();
|
||||||
|
emit emptyChanged();
|
||||||
|
break;
|
||||||
|
case QmlProfilerDataState::ClearingData:
|
||||||
|
clear();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int QmlProfilerTimelineModel::bindingLoopDest(int index) const
|
||||||
|
{
|
||||||
|
Q_UNUSED(index);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
76
src/plugins/qmlprofiler/qmlprofilertimelinemodel.h
Normal file
76
src/plugins/qmlprofiler/qmlprofilertimelinemodel.h
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
|
||||||
|
** Contact: http://www.qt-project.org/legal
|
||||||
|
**
|
||||||
|
** This file is part of Qt Creator.
|
||||||
|
**
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and Digia. For licensing terms and
|
||||||
|
** conditions see http://www.qt.io/licensing. For further information
|
||||||
|
** use the contact form at http://www.qt.io/contact-us.
|
||||||
|
**
|
||||||
|
** 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 or version 3 as published by the Free
|
||||||
|
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
|
||||||
|
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
|
||||||
|
** following information to ensure the GNU Lesser General Public License
|
||||||
|
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
|
||||||
|
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||||
|
**
|
||||||
|
** In addition, as a special exception, Digia gives you certain additional
|
||||||
|
** rights. These rights are described in the Digia Qt LGPL Exception
|
||||||
|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#ifndef QMLPROFILERTIMELINEMODEL_H
|
||||||
|
#define QMLPROFILERTIMELINEMODEL_H
|
||||||
|
|
||||||
|
#include "timelinemodel.h"
|
||||||
|
|
||||||
|
namespace QmlProfiler {
|
||||||
|
|
||||||
|
class QMLPROFILER_EXPORT QmlProfilerTimelineModel : public TimelineModel {
|
||||||
|
Q_OBJECT
|
||||||
|
Q_PROPERTY(QmlDebug::RangeType rangeType READ rangeType CONSTANT)
|
||||||
|
Q_PROPERTY(QmlDebug::Message message READ message CONSTANT)
|
||||||
|
Q_PROPERTY(QmlProfilerModelManager *modelManager READ modelManager CONSTANT)
|
||||||
|
|
||||||
|
public:
|
||||||
|
QmlProfilerTimelineModel(QmlProfilerModelManager *modelManager, const QString &displayName,
|
||||||
|
QmlDebug::Message message, QmlDebug::RangeType rangeType,
|
||||||
|
QObject *parent);
|
||||||
|
|
||||||
|
QmlProfilerModelManager *modelManager() const;
|
||||||
|
|
||||||
|
QmlDebug::RangeType rangeType() const;
|
||||||
|
QmlDebug::Message message() const;
|
||||||
|
|
||||||
|
virtual bool accepted(const QmlProfilerDataModel::QmlEventTypeData &event) const;
|
||||||
|
bool handlesTypeId(int typeId) const;
|
||||||
|
Q_INVOKABLE virtual int bindingLoopDest(int index) const;
|
||||||
|
|
||||||
|
virtual void loadData() = 0;
|
||||||
|
void clear();
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void dataChanged();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void updateProgress(qint64 count, qint64 max) const;
|
||||||
|
void announceFeatures(quint64 features) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
const QmlDebug::Message m_message;
|
||||||
|
const QmlDebug::RangeType m_rangeType;
|
||||||
|
QmlProfilerModelManager *const m_modelManager;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // QMLPROFILERTIMELINEMODEL_H
|
||||||
@@ -31,7 +31,7 @@
|
|||||||
#ifndef QMLPROFILERTIMELINEMODELFACTORY_H
|
#ifndef QMLPROFILERTIMELINEMODELFACTORY_H
|
||||||
#define QMLPROFILERTIMELINEMODELFACTORY_H
|
#define QMLPROFILERTIMELINEMODELFACTORY_H
|
||||||
|
|
||||||
#include "abstracttimelinemodel.h"
|
#include "qmlprofilertimelinemodel.h"
|
||||||
#include "qmlprofilermodelmanager.h"
|
#include "qmlprofilermodelmanager.h"
|
||||||
|
|
||||||
namespace QmlProfiler {
|
namespace QmlProfiler {
|
||||||
@@ -40,7 +40,7 @@ class QMLPROFILER_EXPORT QmlProfilerTimelineModelFactory : public QObject
|
|||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
virtual QList<AbstractTimelineModel *> create(QmlProfilerModelManager *manager) = 0;
|
virtual QList<QmlProfilerTimelineModel *> create(QmlProfilerModelManager *manager) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
511
src/plugins/qmlprofiler/timelinemodel.cpp
Normal file
511
src/plugins/qmlprofiler/timelinemodel.cpp
Normal file
@@ -0,0 +1,511 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
|
||||||
|
** Contact: http://www.qt-project.org/legal
|
||||||
|
**
|
||||||
|
** This file is part of Qt Creator.
|
||||||
|
**
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and Digia. For licensing terms and
|
||||||
|
** conditions see http://www.qt.io/licensing. For further information
|
||||||
|
** use the contact form at http://www.qt.io/contact-us.
|
||||||
|
**
|
||||||
|
** 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 or version 3 as published by the Free
|
||||||
|
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
|
||||||
|
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
|
||||||
|
** following information to ensure the GNU Lesser General Public License
|
||||||
|
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
|
||||||
|
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||||
|
**
|
||||||
|
** In addition, as a special exception, Digia gives you certain additional
|
||||||
|
** rights. These rights are described in the Digia Qt LGPL Exception
|
||||||
|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#include "timelinemodel.h"
|
||||||
|
#include "timelinemodel_p.h"
|
||||||
|
|
||||||
|
#include <QLinkedList>
|
||||||
|
|
||||||
|
namespace QmlProfiler {
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\class QmlProfiler::TimelineModel
|
||||||
|
\brief The TimelineModel class provides a sorted model for timeline data.
|
||||||
|
|
||||||
|
The TimelineModel lets you keep range data sorted by both start and end times, so that
|
||||||
|
visible ranges can easily be computed. The only precondition for that to work is that the ranges
|
||||||
|
must be perfectly nested. A "parent" range of a range R is defined as a range for which the
|
||||||
|
start time is earlier than R's start time and the end time is later than R's end time. A set
|
||||||
|
of ranges is perfectly nested if all parent ranges of any given range have a common parent
|
||||||
|
range. Mind that you can always make that happen by defining a range that spans the whole
|
||||||
|
available time span. That, however, will make any code that uses firstIndex() and lastIndex()
|
||||||
|
for selecting subsets of the model always select all of it.
|
||||||
|
|
||||||
|
\note Indices returned from the various methods are only valid until a new range is inserted
|
||||||
|
before them. Inserting a new range before a given index moves the range pointed to by the
|
||||||
|
index by one. Incrementing the index by one will make it point to the item again.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Compute all ranges' parents.
|
||||||
|
\sa firstIndex()
|
||||||
|
*/
|
||||||
|
void TimelineModel::computeNesting()
|
||||||
|
{
|
||||||
|
Q_D(TimelineModel);
|
||||||
|
QLinkedList<int> parents;
|
||||||
|
for (int range = 0; range != count(); ++range) {
|
||||||
|
TimelineModelPrivate::Range ¤t = d->ranges[range];
|
||||||
|
for (QLinkedList<int>::iterator parentIt = parents.begin();;) {
|
||||||
|
if (parentIt == parents.end()) {
|
||||||
|
parents.append(range);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
TimelineModelPrivate::Range &parent = d->ranges[*parentIt];
|
||||||
|
qint64 parentEnd = parent.start + parent.duration;
|
||||||
|
if (parentEnd < current.start) {
|
||||||
|
if (parent.start == current.start) {
|
||||||
|
if (parent.parent == -1) {
|
||||||
|
parent.parent = range;
|
||||||
|
} else {
|
||||||
|
TimelineModelPrivate::Range &ancestor = d->ranges[parent.parent];
|
||||||
|
if (ancestor.start == current.start &&
|
||||||
|
ancestor.duration < current.duration)
|
||||||
|
parent.parent = range;
|
||||||
|
}
|
||||||
|
// Just switch the old parent range for the new, larger one
|
||||||
|
*parentIt = range;
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
parentIt = parents.erase(parentIt);
|
||||||
|
}
|
||||||
|
} else if (parentEnd >= current.start + current.duration) {
|
||||||
|
// no need to insert
|
||||||
|
current.parent = *parentIt;
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
++parentIt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int TimelineModel::collapsedRowCount() const
|
||||||
|
{
|
||||||
|
Q_D(const TimelineModel);
|
||||||
|
return d->collapsedRowCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TimelineModel::setCollapsedRowCount(int rows)
|
||||||
|
{
|
||||||
|
Q_D(TimelineModel);
|
||||||
|
d->collapsedRowCount = rows;
|
||||||
|
}
|
||||||
|
|
||||||
|
int TimelineModel::expandedRowCount() const
|
||||||
|
{
|
||||||
|
Q_D(const TimelineModel);
|
||||||
|
return d->expandedRowCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QmlProfiler::TimelineModel::setExpandedRowCount(int rows)
|
||||||
|
{
|
||||||
|
Q_D(TimelineModel);
|
||||||
|
d->expandedRowCount = rows;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TimelineModel::TimelineModelPrivate::TimelineModelPrivate(int modelId, const QString &displayName) :
|
||||||
|
modelId(modelId), displayName(displayName), expanded(false), hidden(false),
|
||||||
|
expandedRowCount(1), collapsedRowCount(1), q_ptr(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void TimelineModel::TimelineModelPrivate::init(TimelineModel *q)
|
||||||
|
{
|
||||||
|
q_ptr = q;
|
||||||
|
connect(q,SIGNAL(rowHeightChanged()),q,SIGNAL(heightChanged()));
|
||||||
|
connect(q,SIGNAL(expandedChanged()),q,SIGNAL(heightChanged()));
|
||||||
|
connect(q,SIGNAL(hiddenChanged()),q,SIGNAL(heightChanged()));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TimelineModel::TimelineModel(TimelineModelPrivate &dd, QObject *parent) :
|
||||||
|
QObject(parent), d_ptr(&dd)
|
||||||
|
{
|
||||||
|
d_ptr->init(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
TimelineModel::TimelineModel(int modelId, const QString &displayName, QObject *parent) :
|
||||||
|
QObject(parent), d_ptr(new TimelineModelPrivate(modelId, displayName))
|
||||||
|
{
|
||||||
|
d_ptr->init(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
TimelineModel::~TimelineModel()
|
||||||
|
{
|
||||||
|
Q_D(TimelineModel);
|
||||||
|
delete d;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TimelineModel::isEmpty() const
|
||||||
|
{
|
||||||
|
return count() == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int TimelineModel::modelId() const
|
||||||
|
{
|
||||||
|
Q_D(const TimelineModel);
|
||||||
|
return d->modelId;
|
||||||
|
}
|
||||||
|
|
||||||
|
int TimelineModel::rowHeight(int rowNumber) const
|
||||||
|
{
|
||||||
|
Q_D(const TimelineModel);
|
||||||
|
if (!expanded())
|
||||||
|
return TimelineModelPrivate::DefaultRowHeight;
|
||||||
|
|
||||||
|
if (d->rowOffsets.size() > rowNumber)
|
||||||
|
return d->rowOffsets[rowNumber] - (rowNumber > 0 ? d->rowOffsets[rowNumber - 1] : 0);
|
||||||
|
return TimelineModelPrivate::DefaultRowHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
int TimelineModel::rowOffset(int rowNumber) const
|
||||||
|
{
|
||||||
|
Q_D(const TimelineModel);
|
||||||
|
if (rowNumber == 0)
|
||||||
|
return 0;
|
||||||
|
if (!expanded())
|
||||||
|
return TimelineModelPrivate::DefaultRowHeight * rowNumber;
|
||||||
|
|
||||||
|
if (d->rowOffsets.size() >= rowNumber)
|
||||||
|
return d->rowOffsets[rowNumber - 1];
|
||||||
|
if (!d->rowOffsets.empty())
|
||||||
|
return d->rowOffsets.last() + (rowNumber - d->rowOffsets.size()) *
|
||||||
|
TimelineModelPrivate::DefaultRowHeight;
|
||||||
|
return rowNumber * TimelineModelPrivate::DefaultRowHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TimelineModel::setRowHeight(int rowNumber, int height)
|
||||||
|
{
|
||||||
|
Q_D(TimelineModel);
|
||||||
|
if (d->hidden || !d->expanded)
|
||||||
|
return;
|
||||||
|
if (height < TimelineModelPrivate::DefaultRowHeight)
|
||||||
|
height = TimelineModelPrivate::DefaultRowHeight;
|
||||||
|
|
||||||
|
int nextOffset = d->rowOffsets.empty() ? 0 : d->rowOffsets.last();
|
||||||
|
while (d->rowOffsets.size() <= rowNumber)
|
||||||
|
d->rowOffsets << (nextOffset += TimelineModelPrivate::DefaultRowHeight);
|
||||||
|
int difference = height - d->rowOffsets[rowNumber] +
|
||||||
|
(rowNumber > 0 ? d->rowOffsets[rowNumber - 1] : 0);
|
||||||
|
if (difference != 0) {
|
||||||
|
for (; rowNumber < d->rowOffsets.size(); ++rowNumber) {
|
||||||
|
d->rowOffsets[rowNumber] += difference;
|
||||||
|
}
|
||||||
|
emit rowHeightChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int TimelineModel::height() const
|
||||||
|
{
|
||||||
|
Q_D(const TimelineModel);
|
||||||
|
int depth = rowCount();
|
||||||
|
if (d->hidden || !d->expanded || d->rowOffsets.empty())
|
||||||
|
return depth * TimelineModelPrivate::DefaultRowHeight;
|
||||||
|
|
||||||
|
return d->rowOffsets.last() + (depth - d->rowOffsets.size()) *
|
||||||
|
TimelineModelPrivate::DefaultRowHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Returns the number of ranges in the model.
|
||||||
|
*/
|
||||||
|
int TimelineModel::count() const
|
||||||
|
{
|
||||||
|
Q_D(const TimelineModel);
|
||||||
|
return d->ranges.count();
|
||||||
|
}
|
||||||
|
|
||||||
|
qint64 TimelineModel::duration(int index) const
|
||||||
|
{
|
||||||
|
Q_D(const TimelineModel);
|
||||||
|
return d->ranges[index].duration;
|
||||||
|
}
|
||||||
|
|
||||||
|
qint64 TimelineModel::startTime(int index) const
|
||||||
|
{
|
||||||
|
Q_D(const TimelineModel);
|
||||||
|
return d->ranges[index].start;
|
||||||
|
}
|
||||||
|
|
||||||
|
qint64 TimelineModel::endTime(int index) const
|
||||||
|
{
|
||||||
|
Q_D(const TimelineModel);
|
||||||
|
return d->ranges[index].start + d->ranges[index].duration;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Returns the type ID of the event with event ID \a index. The type ID is a globally valid ID
|
||||||
|
which can be used to communicate meta information about events to other parts of the program. By
|
||||||
|
default it is -1, which means there is no global type information about the event.
|
||||||
|
*/
|
||||||
|
int TimelineModel::typeId(int index) const
|
||||||
|
{
|
||||||
|
Q_UNUSED(index)
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Looks up the first range with an end time later than the given time and
|
||||||
|
returns its parent's index. If no such range is found, it returns -1. If there
|
||||||
|
is no parent, it returns the found range's index. The parent of a range is the
|
||||||
|
range with the earliest start time that completely covers the child range.
|
||||||
|
"Completely covers" means:
|
||||||
|
parent.startTime <= child.startTime && parent.endTime >= child.endTime
|
||||||
|
*/
|
||||||
|
int TimelineModel::firstIndex(qint64 startTime) const
|
||||||
|
{
|
||||||
|
Q_D(const TimelineModel);
|
||||||
|
int index = firstIndexNoParents(startTime);
|
||||||
|
if (index == -1)
|
||||||
|
return -1;
|
||||||
|
int parent = d->ranges[index].parent;
|
||||||
|
return parent == -1 ? index : parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Looks up the first range with an end time later than the specified \a startTime and
|
||||||
|
returns its index. If no such range is found, it returns -1.
|
||||||
|
*/
|
||||||
|
int TimelineModel::firstIndexNoParents(qint64 startTime) const
|
||||||
|
{
|
||||||
|
Q_D(const TimelineModel);
|
||||||
|
// in the "endtime" list, find the first event that ends after startTime
|
||||||
|
if (d->endTimes.isEmpty())
|
||||||
|
return -1;
|
||||||
|
if (d->endTimes.count() == 1 || d->endTimes.first().end > startTime)
|
||||||
|
return d->endTimes.first().startIndex;
|
||||||
|
if (d->endTimes.last().end <= startTime)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return d->endTimes[d->lowerBound(d->endTimes, startTime) + 1].startIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Looks up the last range with a start time earlier than the specified \a endTime and
|
||||||
|
returns its index. If no such range is found, it returns -1.
|
||||||
|
*/
|
||||||
|
int TimelineModel::lastIndex(qint64 endTime) const
|
||||||
|
{
|
||||||
|
Q_D(const TimelineModel);
|
||||||
|
// in the "starttime" list, find the last event that starts before endtime
|
||||||
|
if (d->ranges.isEmpty() || d->ranges.first().start >= endTime)
|
||||||
|
return -1;
|
||||||
|
if (d->ranges.count() == 1)
|
||||||
|
return 0;
|
||||||
|
if (d->ranges.last().start < endTime)
|
||||||
|
return d->ranges.count() - 1;
|
||||||
|
|
||||||
|
return d->lowerBound(d->ranges, endTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariantMap TimelineModel::location(int index) const
|
||||||
|
{
|
||||||
|
Q_UNUSED(index);
|
||||||
|
QVariantMap map;
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Returns \c true if this model can contain events of global type ID \a typeIndex. Otherwise
|
||||||
|
returns \c false. The base model does not know anything about type IDs and always returns
|
||||||
|
\c false. You should override this method if you implement \l typeId().
|
||||||
|
*/
|
||||||
|
bool TimelineModel::handlesTypeId(int typeIndex) const
|
||||||
|
{
|
||||||
|
Q_UNUSED(typeIndex);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int TimelineModel::selectionIdForLocation(const QString &filename, int line, int column) const
|
||||||
|
{
|
||||||
|
Q_UNUSED(filename);
|
||||||
|
Q_UNUSED(line);
|
||||||
|
Q_UNUSED(column);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
float TimelineModel::relativeHeight(int index) const
|
||||||
|
{
|
||||||
|
Q_UNUSED(index);
|
||||||
|
return 1.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
int TimelineModel::rowMinValue(int rowNumber) const
|
||||||
|
{
|
||||||
|
Q_UNUSED(rowNumber);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int TimelineModel::rowMaxValue(int rowNumber) const
|
||||||
|
{
|
||||||
|
Q_UNUSED(rowNumber);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int TimelineModel::defaultRowHeight()
|
||||||
|
{
|
||||||
|
return TimelineModelPrivate::DefaultRowHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
QColor TimelineModel::colorBySelectionId(int index) const
|
||||||
|
{
|
||||||
|
return colorByHue(selectionId(index) * TimelineModelPrivate::SelectionIdHueMultiplier);
|
||||||
|
}
|
||||||
|
|
||||||
|
QColor TimelineModel::colorByFraction(double fraction) const
|
||||||
|
{
|
||||||
|
return colorByHue(fraction * TimelineModelPrivate::FractionHueMultiplier +
|
||||||
|
TimelineModelPrivate::FractionHueMininimum);
|
||||||
|
}
|
||||||
|
|
||||||
|
QColor TimelineModel::colorByHue(int hue) const
|
||||||
|
{
|
||||||
|
return QColor::fromHsl(hue % 360, TimelineModelPrivate::Saturation,
|
||||||
|
TimelineModelPrivate::Lightness);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Inserts the range defined by \a duration and \a selectionId at the specified \a startTime and
|
||||||
|
returns its index. The \a selectionId determines the selection group the new event belongs to.
|
||||||
|
\sa selectionId()
|
||||||
|
*/
|
||||||
|
int TimelineModel::insert(qint64 startTime, qint64 duration, int selectionId)
|
||||||
|
{
|
||||||
|
Q_D(TimelineModel);
|
||||||
|
/* Doing insert-sort here is preferable as most of the time the times will actually be
|
||||||
|
* presorted in the right way. So usually this will just result in appending. */
|
||||||
|
int index = d->insertSorted(d->ranges,
|
||||||
|
TimelineModelPrivate::Range(startTime, duration, selectionId));
|
||||||
|
if (index < d->ranges.size() - 1)
|
||||||
|
d->incrementStartIndices(index);
|
||||||
|
d->insertSorted(d->endTimes, TimelineModelPrivate::RangeEnd(index, startTime + duration));
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Inserts the specified \a selectionId as range start at the specified \a startTime and returns
|
||||||
|
its index. The range end is not set. The \a selectionId determines the selection group the new
|
||||||
|
event belongs to.
|
||||||
|
\sa selectionId()
|
||||||
|
*/
|
||||||
|
int TimelineModel::insertStart(qint64 startTime, int selectionId)
|
||||||
|
{
|
||||||
|
Q_D(TimelineModel);
|
||||||
|
int index = d->insertSorted(d->ranges, TimelineModelPrivate::Range(startTime, 0, selectionId));
|
||||||
|
if (index < d->ranges.size() - 1)
|
||||||
|
d->incrementStartIndices(index);
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Adds the range \a duration at the specified start \a index.
|
||||||
|
*/
|
||||||
|
void TimelineModel::insertEnd(int index, qint64 duration)
|
||||||
|
{
|
||||||
|
Q_D(TimelineModel);
|
||||||
|
d->ranges[index].duration = duration;
|
||||||
|
d->insertSorted(d->endTimes, TimelineModelPrivate::RangeEnd(index,
|
||||||
|
d->ranges[index].start + duration));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TimelineModel::expanded() const
|
||||||
|
{
|
||||||
|
Q_D(const TimelineModel);
|
||||||
|
return d->expanded;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TimelineModel::setExpanded(bool expanded)
|
||||||
|
{
|
||||||
|
Q_D(TimelineModel);
|
||||||
|
if (expanded != d->expanded) {
|
||||||
|
d->expanded = expanded;
|
||||||
|
emit expandedChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TimelineModel::hidden() const
|
||||||
|
{
|
||||||
|
Q_D(const TimelineModel);
|
||||||
|
return d->hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TimelineModel::setHidden(bool hidden)
|
||||||
|
{
|
||||||
|
Q_D(TimelineModel);
|
||||||
|
if (hidden != d->hidden) {
|
||||||
|
d->hidden = hidden;
|
||||||
|
emit hiddenChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QString TimelineModel::displayName() const
|
||||||
|
{
|
||||||
|
Q_D(const TimelineModel);
|
||||||
|
return d->displayName;
|
||||||
|
}
|
||||||
|
|
||||||
|
int TimelineModel::rowCount() const
|
||||||
|
{
|
||||||
|
Q_D(const TimelineModel);
|
||||||
|
if (d->hidden || isEmpty())
|
||||||
|
return 0;
|
||||||
|
return d->expanded ? d->expandedRowCount : d->collapsedRowCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Returns the ID of the selection group the event with event ID \a index belongs to. Selection
|
||||||
|
groups are local to the model and the model can arbitrarily assign events to selection groups
|
||||||
|
when inserting them.
|
||||||
|
If one event from a selection group is selected, all visible other events from the same
|
||||||
|
selection group are highlighted. Rows are expected to correspond to selection IDs when the view
|
||||||
|
is expanded.
|
||||||
|
*/
|
||||||
|
int TimelineModel::selectionId(int index) const
|
||||||
|
{
|
||||||
|
Q_D(const TimelineModel);
|
||||||
|
return d->ranges[index].selectionId;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TimelineModel::clear()
|
||||||
|
{
|
||||||
|
Q_D(TimelineModel);
|
||||||
|
d->collapsedRowCount = d->expandedRowCount = 1;
|
||||||
|
bool wasExpanded = d->expanded;
|
||||||
|
bool wasHidden = d->hidden;
|
||||||
|
bool hadRowHeights = !d->rowOffsets.empty();
|
||||||
|
d->rowOffsets.clear();
|
||||||
|
d->expanded = false;
|
||||||
|
d->hidden = false;
|
||||||
|
d->ranges.clear();
|
||||||
|
d->endTimes.clear();
|
||||||
|
if (hadRowHeights)
|
||||||
|
emit rowHeightChanged();
|
||||||
|
if (wasExpanded)
|
||||||
|
emit expandedChanged();
|
||||||
|
if (wasHidden)
|
||||||
|
emit hiddenChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#include "moc_timelinemodel.cpp"
|
||||||
@@ -28,8 +28,8 @@
|
|||||||
**
|
**
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#ifndef ABSTRACTTIMELINEMODEL_H
|
#ifndef TIMELINEMODEL_H
|
||||||
#define ABSTRACTTIMELINEMODEL_H
|
#define TIMELINEMODEL_H
|
||||||
|
|
||||||
|
|
||||||
#include "qmlprofiler_global.h"
|
#include "qmlprofiler_global.h"
|
||||||
@@ -40,30 +40,24 @@
|
|||||||
|
|
||||||
namespace QmlProfiler {
|
namespace QmlProfiler {
|
||||||
|
|
||||||
class QMLPROFILER_EXPORT AbstractTimelineModel : public QObject
|
class QMLPROFILER_EXPORT TimelineModel : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
Q_PROPERTY(int modelId READ modelId CONSTANT)
|
||||||
Q_PROPERTY(QString displayName READ displayName CONSTANT)
|
Q_PROPERTY(QString displayName READ displayName CONSTANT)
|
||||||
Q_PROPERTY(bool empty READ isEmpty NOTIFY emptyChanged)
|
Q_PROPERTY(bool empty READ isEmpty NOTIFY emptyChanged)
|
||||||
Q_PROPERTY(bool hidden READ hidden WRITE setHidden NOTIFY hiddenChanged)
|
Q_PROPERTY(bool hidden READ hidden WRITE setHidden NOTIFY hiddenChanged)
|
||||||
Q_PROPERTY(int height READ height NOTIFY heightChanged)
|
Q_PROPERTY(int height READ height NOTIFY heightChanged)
|
||||||
Q_PROPERTY(QmlProfilerModelManager *modelManager READ modelManager)
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
class AbstractTimelineModelPrivate;
|
class TimelineModelPrivate;
|
||||||
|
|
||||||
AbstractTimelineModel(QmlProfilerModelManager *manager, const QString &displayName,
|
TimelineModel(int modelId, const QString &displayName, QObject *parent);
|
||||||
QmlDebug::Message message, QmlDebug::RangeType rangeType,
|
~TimelineModel();
|
||||||
QObject *parent);
|
|
||||||
~AbstractTimelineModel();
|
|
||||||
|
|
||||||
// Trivial methods implemented by the abstract model itself
|
|
||||||
QmlProfilerModelManager *modelManager() const;
|
|
||||||
|
|
||||||
|
// Methods implemented by the abstract model itself
|
||||||
bool isEmpty() const;
|
bool isEmpty() const;
|
||||||
int modelId() const;
|
int modelId() const;
|
||||||
|
|
||||||
// Methods are directly passed on to the private model and relying on its virtual methods.
|
|
||||||
int rowHeight(int rowNumber) const;
|
int rowHeight(int rowNumber) const;
|
||||||
int rowOffset(int rowNumber) const;
|
int rowOffset(int rowNumber) const;
|
||||||
void setRowHeight(int rowNumber, int height);
|
void setRowHeight(int rowNumber, int height);
|
||||||
@@ -96,9 +90,7 @@ public:
|
|||||||
virtual QVariantMap location(int index) const;
|
virtual QVariantMap location(int index) const;
|
||||||
virtual int typeId(int index) const;
|
virtual int typeId(int index) const;
|
||||||
virtual bool handlesTypeId(int typeId) const;
|
virtual bool handlesTypeId(int typeId) const;
|
||||||
virtual bool accepted(const QmlProfilerDataModel::QmlEventTypeData &event) const;
|
|
||||||
virtual int selectionIdForLocation(const QString &filename, int line, int column) const;
|
virtual int selectionIdForLocation(const QString &filename, int line, int column) const;
|
||||||
virtual int bindingLoopDest(int index) const;
|
|
||||||
virtual float relativeHeight(int index) const;
|
virtual float relativeHeight(int index) const;
|
||||||
virtual int rowMinValue(int rowNumber) const;
|
virtual int rowMinValue(int rowNumber) const;
|
||||||
virtual int rowMaxValue(int rowNumber) const;
|
virtual int rowMaxValue(int rowNumber) const;
|
||||||
@@ -128,26 +120,15 @@ protected:
|
|||||||
int expandedRowCount() const;
|
int expandedRowCount() const;
|
||||||
void setExpandedRowCount(int rows);
|
void setExpandedRowCount(int rows);
|
||||||
|
|
||||||
QmlDebug::RangeType rangeType() const;
|
|
||||||
QmlDebug::Message message() const;
|
|
||||||
|
|
||||||
void updateProgress(qint64 count, qint64 max) const;
|
|
||||||
void announceFeatures(quint64 features) const;
|
|
||||||
|
|
||||||
explicit AbstractTimelineModel(AbstractTimelineModelPrivate *dd,
|
|
||||||
QmlProfilerModelManager *manager, const QString &displayName,
|
|
||||||
QmlDebug::Message message, QmlDebug::RangeType rangeType,
|
|
||||||
QObject *parent);
|
|
||||||
AbstractTimelineModelPrivate *d_ptr;
|
|
||||||
|
|
||||||
virtual void loadData() = 0;
|
|
||||||
virtual void clear();
|
virtual void clear();
|
||||||
|
|
||||||
|
explicit TimelineModel(TimelineModelPrivate &dd, QObject *parent);
|
||||||
|
TimelineModelPrivate *d_ptr;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Q_DECLARE_PRIVATE(AbstractTimelineModel)
|
Q_DECLARE_PRIVATE(TimelineModel)
|
||||||
Q_PRIVATE_SLOT(d_func(), void _q_dataChanged())
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // ABSTRACTTIMELINEMODEL_H
|
#endif // TIMELINEMODEL_H
|
||||||
@@ -28,14 +28,14 @@
|
|||||||
**
|
**
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#ifndef ABSTRACTTIMELINEMODEL_P_H
|
#ifndef TIMELINEMODEL_P_H
|
||||||
#define ABSTRACTTIMELINEMODEL_P_H
|
#define TIMELINEMODEL_P_H
|
||||||
|
|
||||||
#include "abstracttimelinemodel.h"
|
#include "timelinemodel.h"
|
||||||
|
|
||||||
namespace QmlProfiler {
|
namespace QmlProfiler {
|
||||||
|
|
||||||
class QMLPROFILER_EXPORT AbstractTimelineModel::AbstractTimelineModelPrivate {
|
class QMLPROFILER_EXPORT TimelineModel::TimelineModelPrivate {
|
||||||
public:
|
public:
|
||||||
static const int DefaultRowHeight = 30;
|
static const int DefaultRowHeight = 30;
|
||||||
|
|
||||||
@@ -67,11 +67,10 @@ public:
|
|||||||
inline qint64 timestamp() const {return end;}
|
inline qint64 timestamp() const {return end;}
|
||||||
};
|
};
|
||||||
|
|
||||||
void init(AbstractTimelineModel *q, QmlProfilerModelManager *manager,
|
TimelineModelPrivate(int modelId, const QString &displayName);
|
||||||
const QString &displayName, QmlDebug::Message message, QmlDebug::RangeType rangeType);
|
void init(TimelineModel *q);
|
||||||
|
|
||||||
inline qint64 lastEndTime() const { return endTimes.last().end; }
|
int firstIndexNoParents(qint64 startTime) const;
|
||||||
inline qint64 firstStartTime() const { return ranges.first().start; }
|
|
||||||
|
|
||||||
void incrementStartIndices(int index)
|
void incrementStartIndices(int index)
|
||||||
{
|
{
|
||||||
@@ -112,28 +111,24 @@ public:
|
|||||||
return fromIndex;
|
return fromIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _q_dataChanged();
|
|
||||||
|
|
||||||
QVector<Range> ranges;
|
QVector<Range> ranges;
|
||||||
QVector<RangeEnd> endTimes;
|
QVector<RangeEnd> endTimes;
|
||||||
|
|
||||||
QVector<int> rowOffsets;
|
QVector<int> rowOffsets;
|
||||||
QmlProfilerModelManager *modelManager;
|
const int modelId;
|
||||||
int modelId;
|
const QString displayName;
|
||||||
|
|
||||||
bool expanded;
|
bool expanded;
|
||||||
bool hidden;
|
bool hidden;
|
||||||
int expandedRowCount;
|
int expandedRowCount;
|
||||||
int collapsedRowCount;
|
int collapsedRowCount;
|
||||||
QString displayName;
|
|
||||||
QmlDebug::Message message;
|
|
||||||
QmlDebug::RangeType rangeType;
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
AbstractTimelineModel *q_ptr;
|
TimelineModel *q_ptr;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Q_DECLARE_PUBLIC(AbstractTimelineModel)
|
Q_DECLARE_PUBLIC(TimelineModel)
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
#endif // ABSTRACTTIMELINEMODEL_P_H
|
#endif // TIMELINEMODEL_P_H
|
||||||
@@ -52,7 +52,7 @@ public:
|
|||||||
// mapping of modelId assigned by manager to index in our list
|
// mapping of modelId assigned by manager to index in our list
|
||||||
QList <int> modelManagerIndexMapping;
|
QList <int> modelManagerIndexMapping;
|
||||||
|
|
||||||
QList <AbstractTimelineModel *> modelList;
|
QList <QmlProfilerTimelineModel *> modelList;
|
||||||
QmlProfilerModelManager *modelManager;
|
QmlProfilerModelManager *modelManager;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -80,7 +80,7 @@ void TimelineModelAggregator::setModelManager(QmlProfilerModelManager *modelMana
|
|||||||
connect(modelManager,SIGNAL(dataAvailable()),this,SIGNAL(dataAvailable()));
|
connect(modelManager,SIGNAL(dataAvailable()),this,SIGNAL(dataAvailable()));
|
||||||
|
|
||||||
// external models pushed on top
|
// external models pushed on top
|
||||||
foreach (AbstractTimelineModel *timelineModel,
|
foreach (QmlProfilerTimelineModel *timelineModel,
|
||||||
QmlProfilerPlugin::instance->getModels(modelManager)) {
|
QmlProfilerPlugin::instance->getModels(modelManager)) {
|
||||||
addModel(timelineModel);
|
addModel(timelineModel);
|
||||||
}
|
}
|
||||||
@@ -96,7 +96,7 @@ void TimelineModelAggregator::setModelManager(QmlProfilerModelManager *modelMana
|
|||||||
this, SIGNAL(notesChanged(int,int,int)));
|
this, SIGNAL(notesChanged(int,int,int)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void TimelineModelAggregator::addModel(AbstractTimelineModel *m)
|
void TimelineModelAggregator::addModel(QmlProfilerTimelineModel *m)
|
||||||
{
|
{
|
||||||
while (d->modelManagerIndexMapping.size() <= m->modelId())
|
while (d->modelManagerIndexMapping.size() <= m->modelId())
|
||||||
d->modelManagerIndexMapping.append(-1);
|
d->modelManagerIndexMapping.append(-1);
|
||||||
@@ -110,7 +110,7 @@ void TimelineModelAggregator::addModel(AbstractTimelineModel *m)
|
|||||||
emit modelsChanged(d->modelList.length(), d->modelList.length());
|
emit modelsChanged(d->modelList.length(), d->modelList.length());
|
||||||
}
|
}
|
||||||
|
|
||||||
const AbstractTimelineModel *TimelineModelAggregator::model(int modelIndex) const
|
const QmlProfilerTimelineModel *TimelineModelAggregator::model(int modelIndex) const
|
||||||
{
|
{
|
||||||
return d->modelList[modelIndex];
|
return d->modelList[modelIndex];
|
||||||
}
|
}
|
||||||
@@ -118,7 +118,7 @@ const AbstractTimelineModel *TimelineModelAggregator::model(int modelIndex) cons
|
|||||||
QVariantList TimelineModelAggregator::models() const
|
QVariantList TimelineModelAggregator::models() const
|
||||||
{
|
{
|
||||||
QVariantList ret;
|
QVariantList ret;
|
||||||
foreach (AbstractTimelineModel *model, d->modelList)
|
foreach (QmlProfilerTimelineModel *model, d->modelList)
|
||||||
ret << QVariant::fromValue(model);
|
ret << QVariant::fromValue(model);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@@ -140,7 +140,7 @@ int TimelineModelAggregator::count(int modelIndex) const
|
|||||||
|
|
||||||
bool TimelineModelAggregator::isEmpty() const
|
bool TimelineModelAggregator::isEmpty() const
|
||||||
{
|
{
|
||||||
foreach (const AbstractTimelineModel *modelProxy, d->modelList)
|
foreach (const QmlProfilerTimelineModel *modelProxy, d->modelList)
|
||||||
if (!modelProxy->isEmpty())
|
if (!modelProxy->isEmpty())
|
||||||
return false;
|
return false;
|
||||||
return true;
|
return true;
|
||||||
@@ -297,8 +297,8 @@ int TimelineModelAggregator::selectionIdForLocation(int modelIndex, const QStrin
|
|||||||
|
|
||||||
void TimelineModelAggregator::swapModels(int modelIndex1, int modelIndex2)
|
void TimelineModelAggregator::swapModels(int modelIndex1, int modelIndex2)
|
||||||
{
|
{
|
||||||
AbstractTimelineModel *&model1 = d->modelList[modelIndex1];
|
QmlProfilerTimelineModel *&model1 = d->modelList[modelIndex1];
|
||||||
AbstractTimelineModel *&model2 = d->modelList[modelIndex2];
|
QmlProfilerTimelineModel *&model2 = d->modelList[modelIndex2];
|
||||||
std::swap(d->modelManagerIndexMapping[model1->modelId()],
|
std::swap(d->modelManagerIndexMapping[model1->modelId()],
|
||||||
d->modelManagerIndexMapping[model2->modelId()]);
|
d->modelManagerIndexMapping[model2->modelId()]);
|
||||||
std::swap(model1, model2);
|
std::swap(model1, model2);
|
||||||
|
|||||||
@@ -31,7 +31,7 @@
|
|||||||
#ifndef TIMELINEMODELAGGREGATOR_H
|
#ifndef TIMELINEMODELAGGREGATOR_H
|
||||||
#define TIMELINEMODELAGGREGATOR_H
|
#define TIMELINEMODELAGGREGATOR_H
|
||||||
|
|
||||||
#include "abstracttimelinemodel.h"
|
#include "qmlprofilertimelinemodel.h"
|
||||||
#include "qmlprofilermodelmanager.h"
|
#include "qmlprofilermodelmanager.h"
|
||||||
|
|
||||||
namespace QmlProfiler {
|
namespace QmlProfiler {
|
||||||
@@ -49,8 +49,8 @@ public:
|
|||||||
|
|
||||||
int height() const;
|
int height() const;
|
||||||
void setModelManager(QmlProfilerModelManager *modelManager);
|
void setModelManager(QmlProfilerModelManager *modelManager);
|
||||||
void addModel(AbstractTimelineModel *m);
|
void addModel(QmlProfilerTimelineModel *m);
|
||||||
const AbstractTimelineModel *model(int modelIndex) const;
|
const QmlProfilerTimelineModel *model(int modelIndex) const;
|
||||||
QVariantList models() const;
|
QVariantList models() const;
|
||||||
int modelIndexFromManagerIndex(int modelManagerIndex) const;
|
int modelIndexFromManagerIndex(int modelManagerIndex) const;
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
TEMPLATE = subdirs
|
TEMPLATE = subdirs
|
||||||
|
|
||||||
SUBDIRS = \
|
SUBDIRS = \
|
||||||
abstracttimelinemodel
|
timelinemodel
|
||||||
|
|||||||
@@ -2,4 +2,4 @@ QTC_PLUGIN_DEPENDS += qmlprofiler
|
|||||||
include(../../qttest.pri)
|
include(../../qttest.pri)
|
||||||
|
|
||||||
SOURCES += \
|
SOURCES += \
|
||||||
tst_abstracttimelinemodel.cpp
|
tst_timelinemodel.cpp
|
||||||
@@ -29,8 +29,7 @@
|
|||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#include <QtTest>
|
#include <QtTest>
|
||||||
#include <qmlprofiler/abstracttimelinemodel.h>
|
#include <qmlprofiler/timelinemodel.h>
|
||||||
#include <qmlprofiler/abstracttimelinemodel_p.h>
|
|
||||||
|
|
||||||
using namespace QmlProfiler;
|
using namespace QmlProfiler;
|
||||||
|
|
||||||
@@ -40,24 +39,24 @@ static const qint64 ItemDuration = 1 << 19;
|
|||||||
static const qint64 ItemSpacing = 1 << 20;
|
static const qint64 ItemSpacing = 1 << 20;
|
||||||
|
|
||||||
class DummyModelPrivate;
|
class DummyModelPrivate;
|
||||||
class DummyModel : public AbstractTimelineModel
|
class DummyModel : public TimelineModel
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
Q_DECLARE_PRIVATE(DummyModel)
|
friend class tst_TimelineModel;
|
||||||
friend class tst_AbstractTimelineModel;
|
|
||||||
public:
|
public:
|
||||||
DummyModel(QString displayName = tr("dummy"), QObject *parent = 0);
|
DummyModel(QString displayName = tr("dummy"), QObject *parent = 0);
|
||||||
int selectionId(int index) const { return index; }
|
int typeId(int index) const { return index; }
|
||||||
QColor color(int) const { return QColor(); }
|
QColor color(int) const { return QColor(); }
|
||||||
QVariantList labels() const { return QVariantList(); }
|
QVariantList labels() const { return QVariantList(); }
|
||||||
QVariantMap details(int) const { return QVariantMap(); }
|
QVariantMap details(int) const { return QVariantMap(); }
|
||||||
int row(int) const { return 1; }
|
int row(int) const { return 1; }
|
||||||
|
quint64 features() const { return 0; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void loadData();
|
void loadData();
|
||||||
};
|
};
|
||||||
|
|
||||||
class tst_AbstractTimelineModel : public QObject
|
class tst_TimelineModel : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
@@ -66,7 +65,6 @@ private slots:
|
|||||||
void rowHeight();
|
void rowHeight();
|
||||||
void rowOffset();
|
void rowOffset();
|
||||||
void height();
|
void height();
|
||||||
void accepted();
|
|
||||||
void expand();
|
void expand();
|
||||||
void hide();
|
void hide();
|
||||||
void displayName();
|
void displayName();
|
||||||
@@ -77,20 +75,19 @@ private slots:
|
|||||||
};
|
};
|
||||||
|
|
||||||
DummyModel::DummyModel(QString displayName, QObject *parent) :
|
DummyModel::DummyModel(QString displayName, QObject *parent) :
|
||||||
AbstractTimelineModel(new QmlProfilerModelManager(0, parent), displayName,
|
TimelineModel(0, displayName, parent)
|
||||||
QmlDebug::MaximumMessage, QmlDebug::MaximumRangeType, parent)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void DummyModel::loadData()
|
void DummyModel::loadData()
|
||||||
{
|
{
|
||||||
for (int i = 0; i < NumItems; ++i)
|
for (int i = 0; i < NumItems; ++i)
|
||||||
insert(i * ItemSpacing, ItemDuration, 0);
|
insert(i * ItemSpacing, ItemDuration, 5);
|
||||||
setCollapsedRowCount(2);
|
setCollapsedRowCount(2);
|
||||||
setExpandedRowCount(2);
|
setExpandedRowCount(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
void tst_AbstractTimelineModel::isEmpty()
|
void tst_TimelineModel::isEmpty()
|
||||||
{
|
{
|
||||||
DummyModel dummy;
|
DummyModel dummy;
|
||||||
QVERIFY(dummy.isEmpty());
|
QVERIFY(dummy.isEmpty());
|
||||||
@@ -100,7 +97,7 @@ void tst_AbstractTimelineModel::isEmpty()
|
|||||||
QVERIFY(dummy.isEmpty());
|
QVERIFY(dummy.isEmpty());
|
||||||
}
|
}
|
||||||
|
|
||||||
void tst_AbstractTimelineModel::rowHeight()
|
void tst_TimelineModel::rowHeight()
|
||||||
{
|
{
|
||||||
DummyModel dummy;
|
DummyModel dummy;
|
||||||
QCOMPARE(dummy.rowHeight(0), DefaultRowHeight);
|
QCOMPARE(dummy.rowHeight(0), DefaultRowHeight);
|
||||||
@@ -135,7 +132,7 @@ void tst_AbstractTimelineModel::rowHeight()
|
|||||||
QCOMPARE(dummy.rowHeight(1), 50);
|
QCOMPARE(dummy.rowHeight(1), 50);
|
||||||
}
|
}
|
||||||
|
|
||||||
void tst_AbstractTimelineModel::rowOffset()
|
void tst_TimelineModel::rowOffset()
|
||||||
{
|
{
|
||||||
DummyModel dummy;
|
DummyModel dummy;
|
||||||
QCOMPARE(dummy.rowOffset(0), 0);
|
QCOMPARE(dummy.rowOffset(0), 0);
|
||||||
@@ -164,10 +161,10 @@ void tst_AbstractTimelineModel::rowOffset()
|
|||||||
QCOMPARE(dummy.rowOffset(1), 100);
|
QCOMPARE(dummy.rowOffset(1), 100);
|
||||||
}
|
}
|
||||||
|
|
||||||
void tst_AbstractTimelineModel::height()
|
void tst_TimelineModel::height()
|
||||||
{
|
{
|
||||||
DummyModel dummy;
|
DummyModel dummy;
|
||||||
QCOMPARE(dummy.height(), DefaultRowHeight);
|
QCOMPARE(dummy.height(), 0);
|
||||||
dummy.loadData();
|
dummy.loadData();
|
||||||
QCOMPARE(dummy.height(), 2 * DefaultRowHeight);
|
QCOMPARE(dummy.height(), 2 * DefaultRowHeight);
|
||||||
dummy.setExpanded(true);
|
dummy.setExpanded(true);
|
||||||
@@ -176,22 +173,7 @@ void tst_AbstractTimelineModel::height()
|
|||||||
QCOMPARE(dummy.height(), DefaultRowHeight + 80);
|
QCOMPARE(dummy.height(), DefaultRowHeight + 80);
|
||||||
}
|
}
|
||||||
|
|
||||||
void tst_AbstractTimelineModel::accepted()
|
void tst_TimelineModel::expand()
|
||||||
{
|
|
||||||
DummyModel dummy;
|
|
||||||
QmlProfilerDataModel::QmlEventTypeData event;
|
|
||||||
event.message = QmlDebug::MaximumMessage;
|
|
||||||
event.rangeType = QmlDebug::MaximumRangeType;
|
|
||||||
QVERIFY(dummy.accepted(event));
|
|
||||||
event.message = QmlDebug::Event;
|
|
||||||
QVERIFY(!dummy.accepted(event));
|
|
||||||
event.rangeType = QmlDebug::Painting;
|
|
||||||
QVERIFY(!dummy.accepted(event));
|
|
||||||
event.message = QmlDebug::MaximumMessage;
|
|
||||||
QVERIFY(!dummy.accepted(event));
|
|
||||||
}
|
|
||||||
|
|
||||||
void tst_AbstractTimelineModel::expand()
|
|
||||||
{
|
{
|
||||||
DummyModel dummy;
|
DummyModel dummy;
|
||||||
QSignalSpy spy(&dummy, SIGNAL(expandedChanged()));
|
QSignalSpy spy(&dummy, SIGNAL(expandedChanged()));
|
||||||
@@ -210,7 +192,7 @@ void tst_AbstractTimelineModel::expand()
|
|||||||
QCOMPARE(spy.count(), 2);
|
QCOMPARE(spy.count(), 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
void tst_AbstractTimelineModel::hide()
|
void tst_TimelineModel::hide()
|
||||||
{
|
{
|
||||||
DummyModel dummy;
|
DummyModel dummy;
|
||||||
QSignalSpy spy(&dummy, SIGNAL(hiddenChanged()));
|
QSignalSpy spy(&dummy, SIGNAL(hiddenChanged()));
|
||||||
@@ -229,45 +211,45 @@ void tst_AbstractTimelineModel::hide()
|
|||||||
QCOMPARE(spy.count(), 2);
|
QCOMPARE(spy.count(), 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
void tst_AbstractTimelineModel::displayName()
|
void tst_TimelineModel::displayName()
|
||||||
{
|
{
|
||||||
QLatin1String name("testest");
|
QLatin1String name("testest");
|
||||||
DummyModel dummy(name);
|
DummyModel dummy(name);
|
||||||
QCOMPARE(dummy.displayName(), name);
|
QCOMPARE(dummy.displayName(), name);
|
||||||
}
|
}
|
||||||
|
|
||||||
void tst_AbstractTimelineModel::defaultValues()
|
void tst_TimelineModel::defaultValues()
|
||||||
{
|
{
|
||||||
DummyModel dummy;
|
DummyModel dummy;
|
||||||
dummy.loadData();
|
dummy.loadData();
|
||||||
QCOMPARE(dummy.location(0), QVariantMap());
|
QCOMPARE(dummy.location(0), QVariantMap());
|
||||||
|
QCOMPARE(dummy.handlesTypeId(0), false);
|
||||||
QCOMPARE(dummy.selectionIdForLocation(QString(), 0, 0), -1);
|
QCOMPARE(dummy.selectionIdForLocation(QString(), 0, 0), -1);
|
||||||
QCOMPARE(dummy.bindingLoopDest(0), -1);
|
|
||||||
QCOMPARE(dummy.relativeHeight(0), 1.0);
|
QCOMPARE(dummy.relativeHeight(0), 1.0);
|
||||||
QCOMPARE(dummy.rowMinValue(0), 0);
|
QCOMPARE(dummy.rowMinValue(0), 0);
|
||||||
QCOMPARE(dummy.rowMaxValue(0), 0);
|
QCOMPARE(dummy.rowMaxValue(0), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void tst_AbstractTimelineModel::colorByHue()
|
void tst_TimelineModel::colorByHue()
|
||||||
{
|
{
|
||||||
DummyModel dummy;
|
DummyModel dummy;
|
||||||
QCOMPARE(dummy.colorByHue(10), QColor::fromHsl(10, 150, 166));
|
QCOMPARE(dummy.colorByHue(10), QColor::fromHsl(10, 150, 166));
|
||||||
QCOMPARE(dummy.colorByHue(500), QColor::fromHsl(140, 150, 166));
|
QCOMPARE(dummy.colorByHue(500), QColor::fromHsl(140, 150, 166));
|
||||||
}
|
}
|
||||||
|
|
||||||
void tst_AbstractTimelineModel::colorBySelectionId()
|
void tst_TimelineModel::colorBySelectionId()
|
||||||
{
|
{
|
||||||
DummyModel dummy;
|
DummyModel dummy;
|
||||||
dummy.loadData();
|
dummy.loadData();
|
||||||
QCOMPARE(dummy.colorBySelectionId(5), QColor::fromHsl(0, 150, 166));
|
QCOMPARE(dummy.colorBySelectionId(5), QColor::fromHsl(5 * 25, 150, 166));
|
||||||
}
|
}
|
||||||
|
|
||||||
void tst_AbstractTimelineModel::colorByFraction()
|
void tst_TimelineModel::colorByFraction()
|
||||||
{
|
{
|
||||||
DummyModel dummy;
|
DummyModel dummy;
|
||||||
QCOMPARE(dummy.colorByFraction(0.5), QColor::fromHsl(0.5 * 96 + 10, 150, 166));
|
QCOMPARE(dummy.colorByFraction(0.5), QColor::fromHsl(0.5 * 96 + 10, 150, 166));
|
||||||
}
|
}
|
||||||
|
|
||||||
QTEST_MAIN(tst_AbstractTimelineModel)
|
QTEST_MAIN(tst_TimelineModel)
|
||||||
|
|
||||||
#include "tst_abstracttimelinemodel.moc"
|
#include "tst_timelinemodel.moc"
|
||||||
Reference in New Issue
Block a user