qmlprofilerrangemodel.cpp 9.13 KB
Newer Older
Christiaan Janssen's avatar
Christiaan Janssen committed
1
2
/****************************************************************************
**
3
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
Christiaan Janssen's avatar
Christiaan Janssen committed
4
5
6
7
8
9
10
11
12
** 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
Eike Ziller's avatar
Eike Ziller committed
13
14
** conditions see http://www.qt.io/licensing.  For further information
** use the contact form at http://www.qt.io/contact-us.
Christiaan Janssen's avatar
Christiaan Janssen committed
15
16
17
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
Eike Ziller's avatar
Eike Ziller committed
18
19
20
21
22
23
** 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.
Christiaan Janssen's avatar
Christiaan Janssen committed
24
25
26
27
28
29
30
**
** 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.
**
****************************************************************************/

31
#include "qmlprofilerrangemodel.h"
Christiaan Janssen's avatar
Christiaan Janssen committed
32
#include "qmlprofilermodelmanager.h"
33
#include "qmlprofilerdatamodel.h"
Christiaan Janssen's avatar
Christiaan Janssen committed
34
35
36
37
38
39
40
41
42
43
44
45
46
47

#include <QCoreApplication>
#include <QVector>
#include <QHash>
#include <QUrl>
#include <QString>
#include <QStack>

#include <QDebug>

namespace QmlProfiler {
namespace Internal {


48
QmlProfilerRangeModel::QmlProfilerRangeModel(QmlDebug::RangeType rangeType, QObject *parent)
49
    : AbstractTimelineModel(categoryLabel(rangeType), QmlDebug::MaximumMessage, rangeType, parent)
Christiaan Janssen's avatar
Christiaan Janssen committed
50
{
51
    m_expandedRowTypes << -1;
Christiaan Janssen's avatar
Christiaan Janssen committed
52
53
}

54
quint64 QmlProfilerRangeModel::features() const
55
{
56
    return 1ULL << QmlDebug::featureFromRangeType(rangeType());
57
58
}

59
void QmlProfilerRangeModel::clear()
Christiaan Janssen's avatar
Christiaan Janssen committed
60
{
61
62
63
    m_expandedRowTypes.clear();
    m_expandedRowTypes << -1;
    m_data.clear();
64
    AbstractTimelineModel::clear();
Christiaan Janssen's avatar
Christiaan Janssen committed
65
66
}

67
void QmlProfilerRangeModel::loadData()
Christiaan Janssen's avatar
Christiaan Janssen committed
68
69
{
    clear();
70
    QmlProfilerDataModel *simpleModel = modelManager()->qmlModel();
Christiaan Janssen's avatar
Christiaan Janssen committed
71
72
73
74
    if (simpleModel->isEmpty())
        return;

    // collect events
75
76
    const QVector<QmlProfilerDataModel::QmlEventData> &eventList = simpleModel->getEvents();
    const QVector<QmlProfilerDataModel::QmlEventTypeData> &typesList = simpleModel->getEventTypes();
77
    foreach (const QmlProfilerDataModel::QmlEventData &event, eventList) {
78
        const QmlProfilerDataModel::QmlEventTypeData &type = typesList[event.typeIndex];
79
        if (!accepted(type))
Christiaan Janssen's avatar
Christiaan Janssen committed
80
81
82
            continue;

        // store starttime-based instance
83
84
85
        m_data.insert(insert(event.startTime, event.duration, event.typeIndex),
                      QmlRangeEventStartInstance());
        updateProgress(count(), eventList.count() * 6);
Christiaan Janssen's avatar
Christiaan Janssen committed
86
87
    }

88
    updateProgress(2, 6);
Christiaan Janssen's avatar
Christiaan Janssen committed
89

90
    // compute range nesting
91
    computeNesting();
Christiaan Janssen's avatar
Christiaan Janssen committed
92
93

    // compute nestingLevel - nonexpanded
94
    computeNestingContracted();
Christiaan Janssen's avatar
Christiaan Janssen committed
95

96
    updateProgress(3, 6);
Christiaan Janssen's avatar
Christiaan Janssen committed
97
98

    // compute nestingLevel - expanded
99
    computeExpandedLevels();
Christiaan Janssen's avatar
Christiaan Janssen committed
100

101
    updateProgress(4, 6);
Christiaan Janssen's avatar
Christiaan Janssen committed
102

103
    findBindingLoops();
Christiaan Janssen's avatar
Christiaan Janssen committed
104

105
    updateProgress(5, 6);
Christiaan Janssen's avatar
Christiaan Janssen committed
106

107
    updateProgress(1, 1);
Christiaan Janssen's avatar
Christiaan Janssen committed
108
109
}

110
void QmlProfilerRangeModel::computeNestingContracted()
Christiaan Janssen's avatar
Christiaan Janssen committed
111
112
{
    int i;
113
    int eventCount = count();
Christiaan Janssen's avatar
Christiaan Janssen committed
114

115
    int nestingLevels = QmlDebug::Constants::QML_MIN_LEVEL;
116
    int collapsedRowCount = nestingLevels + 1;
117
118
    QVector<qint64> nestingEndTimes;
    nestingEndTimes.fill(0, nestingLevels + 1);
Christiaan Janssen's avatar
Christiaan Janssen committed
119
120

    for (i = 0; i < eventCount; i++) {
121
        qint64 st = startTime(i);
Christiaan Janssen's avatar
Christiaan Janssen committed
122
123

        // per type
124
        if (nestingEndTimes[nestingLevels] > st) {
125
            if (++nestingLevels == nestingEndTimes.size())
126
                nestingEndTimes << 0;
127
128
            if (nestingLevels == collapsedRowCount)
                ++collapsedRowCount;
Christiaan Janssen's avatar
Christiaan Janssen committed
129
        } else {
130
131
132
            while (nestingLevels > QmlDebug::Constants::QML_MIN_LEVEL &&
                   nestingEndTimes[nestingLevels-1] <= st)
                nestingLevels--;
Christiaan Janssen's avatar
Christiaan Janssen committed
133
        }
134
        nestingEndTimes[nestingLevels] = st + duration(i);
Christiaan Janssen's avatar
Christiaan Janssen committed
135

136
        m_data[i].displayRowCollapsed = nestingLevels;
Christiaan Janssen's avatar
Christiaan Janssen committed
137
    }
138
    setCollapsedRowCount(collapsedRowCount);
Christiaan Janssen's avatar
Christiaan Janssen committed
139
140
}

141
void QmlProfilerRangeModel::computeExpandedLevels()
Christiaan Janssen's avatar
Christiaan Janssen committed
142
143
{
    QHash<int, int> eventRow;
144
    int eventCount = count();
Christiaan Janssen's avatar
Christiaan Janssen committed
145
    for (int i = 0; i < eventCount; i++) {
146
147
148
149
        int eventTypeId = typeId(i);
        if (!eventRow.contains(eventTypeId)) {
            eventRow[eventTypeId] = m_expandedRowTypes.size();
            m_expandedRowTypes << eventTypeId;
Christiaan Janssen's avatar
Christiaan Janssen committed
150
        }
151
        m_data[i].displayRowExpanded = eventRow[eventTypeId];
Christiaan Janssen's avatar
Christiaan Janssen committed
152
    }
153
    setExpandedRowCount(m_expandedRowTypes.size());
Christiaan Janssen's avatar
Christiaan Janssen committed
154
155
}

156
void QmlProfilerRangeModel::findBindingLoops()
Christiaan Janssen's avatar
Christiaan Janssen committed
157
{
158
    if (rangeType() != QmlDebug::Binding && rangeType() != QmlDebug::HandlingSignal)
159
160
        return;

161
    typedef QPair<int, int> CallStackEntry;
Christiaan Janssen's avatar
Christiaan Janssen committed
162
163
    QStack<CallStackEntry> callStack;

164
165
    for (int i = 0; i < count(); ++i) {
        int potentialParent = callStack.isEmpty() ? -1 : callStack.top().second;
Christiaan Janssen's avatar
Christiaan Janssen committed
166

167
        while (potentialParent != -1 && !(endTime(potentialParent) > startTime(i))) {
Christiaan Janssen's avatar
Christiaan Janssen committed
168
            callStack.pop();
169
            potentialParent = callStack.isEmpty() ? -1 : callStack.top().second;
Christiaan Janssen's avatar
Christiaan Janssen committed
170
171
172
173
        }

        // check whether event is already in stack
        for (int ii = 0; ii < callStack.size(); ++ii) {
174
175
            if (callStack.at(ii).first == typeId(i)) {
                m_data[i].bindingLoopHead = callStack.at(ii).second;
Christiaan Janssen's avatar
Christiaan Janssen committed
176
177
178
179
                break;
            }
        }

180
        CallStackEntry newEntry(typeId(i), i);
Christiaan Janssen's avatar
Christiaan Janssen committed
181
182
183
184
185
186
187
        callStack.push(newEntry);
    }

}

/////////////////// QML interface

188
QString QmlProfilerRangeModel::categoryLabel(QmlDebug::RangeType rangeType)
Christiaan Janssen's avatar
Christiaan Janssen committed
189
{
190
191
    return QCoreApplication::translate("MainView",
            QmlProfilerModelManager::featureName(QmlDebug::featureFromRangeType(rangeType)));
Christiaan Janssen's avatar
Christiaan Janssen committed
192
193
}

194
int QmlProfilerRangeModel::row(int index) const
Christiaan Janssen's avatar
Christiaan Janssen committed
195
{
196
197
    if (expanded())
        return m_data[index].displayRowExpanded;
Christiaan Janssen's avatar
Christiaan Janssen committed
198
    else
199
        return m_data[index].displayRowCollapsed;
Christiaan Janssen's avatar
Christiaan Janssen committed
200
201
}

202
int QmlProfilerRangeModel::bindingLoopDest(int index) const
Christiaan Janssen's avatar
Christiaan Janssen committed
203
{
204
    return m_data[index].bindingLoopHead;
Christiaan Janssen's avatar
Christiaan Janssen committed
205
206
}

207
QColor QmlProfilerRangeModel::color(int index) const
Christiaan Janssen's avatar
Christiaan Janssen committed
208
{
209
    return colorBySelectionId(index);
Christiaan Janssen's avatar
Christiaan Janssen committed
210
211
}

212
QVariantList QmlProfilerRangeModel::labels() const
Christiaan Janssen's avatar
Christiaan Janssen committed
213
214
215
{
    QVariantList result;

216
    if (expanded() && !hidden()) {
217
        const QVector<QmlProfilerDataModel::QmlEventTypeData> &types =
218
219
                modelManager()->qmlModel()->getEventTypes();
        for (int i = 1; i < expandedRowCount(); i++) { // Ignore the -1 for the first row
220
            QVariantMap element;
221
            int typeId = m_expandedRowTypes[i];
222
223
224
            element.insert(QLatin1String("displayName"), QVariant(types[typeId].displayName));
            element.insert(QLatin1String("description"), QVariant(types[typeId].data));
            element.insert(QLatin1String("id"), QVariant(typeId));
225
            result << element;
Christiaan Janssen's avatar
Christiaan Janssen committed
226
227
228
229
230
231
        }
    }

    return result;
}

232
QVariantMap QmlProfilerRangeModel::details(int index) const
Christiaan Janssen's avatar
Christiaan Janssen committed
233
{
234
    QVariantMap result;
235
    int id = selectionId(index);
236
    const QVector<QmlProfilerDataModel::QmlEventTypeData> &types =
237
            modelManager()->qmlModel()->getEventTypes();
Christiaan Janssen's avatar
Christiaan Janssen committed
238

239
    result.insert(QStringLiteral("displayName"), categoryLabel(rangeType()));
240
    result.insert(tr("Duration"), QmlProfilerBaseModel::formatTime(duration(index)));
Christiaan Janssen's avatar
Christiaan Janssen committed
241

242
    result.insert(tr("Details"), types[id].data);
243
    result.insert(tr("Location"), types[id].displayName);
Christiaan Janssen's avatar
Christiaan Janssen committed
244
245
246
    return result;
}

247
QVariantMap QmlProfilerRangeModel::location(int index) const
Christiaan Janssen's avatar
Christiaan Janssen committed
248
249
{
    QVariantMap result;
250
    int id = selectionId(index);
Christiaan Janssen's avatar
Christiaan Janssen committed
251

252
    const QmlDebug::QmlEventLocation &location
253
            = modelManager()->qmlModel()->getEventTypes().at(id).location;
Christiaan Janssen's avatar
Christiaan Janssen committed
254

255
256
257
    result.insert(QStringLiteral("file"), location.filename);
    result.insert(QStringLiteral("line"), location.line);
    result.insert(QStringLiteral("column"), location.column);
Christiaan Janssen's avatar
Christiaan Janssen committed
258
259
260
261

    return result;
}

262
bool QmlProfilerRangeModel::isSelectionIdValid(int typeId) const
Christiaan Janssen's avatar
Christiaan Janssen committed
263
{
264
265
    if (typeId < 0)
        return false;
266
    const QmlProfilerDataModel::QmlEventTypeData &type =
267
268
            modelManager()->qmlModel()->getEventTypes().at(typeId);
    if (type.message != message() || type.rangeType != rangeType())
269
270
        return false;
    return true;
Christiaan Janssen's avatar
Christiaan Janssen committed
271
272
}

273
int QmlProfilerRangeModel::selectionIdForLocation(const QString &filename, int line, int column) const
Christiaan Janssen's avatar
Christiaan Janssen committed
274
275
{
    // if this is called from v8 view, we don't have the column number, it will be -1
276
    const QVector<QmlProfilerDataModel::QmlEventTypeData> &types =
277
278
279
            modelManager()->qmlModel()->getEventTypes();
    for (int i = 1; i < expandedRowCount(); ++i) {
        int typeId = m_expandedRowTypes[i];
280
        const QmlProfilerDataModel::QmlEventTypeData &eventData = types[typeId];
Christiaan Janssen's avatar
Christiaan Janssen committed
281
282
283
        if (eventData.location.filename == filename &&
                eventData.location.line == line &&
                (column == -1 || eventData.location.column == column))
284
            return typeId;
Christiaan Janssen's avatar
Christiaan Janssen committed
285
286
287
288
289
290
291
292
    }
    return -1;
}



}
}