blob: ee43dd7fe9a76725280f3193a3443f72a9d22335 [file] [log] [blame]
Zack Rusin601e8372011-03-24 22:23:21 -04001#include "apitracemodel.h"
2
3#include "apitracecall.h"
Zack Rusinebf971e2011-09-06 17:44:43 -04004#include "traceloader.h"
Zack Rusin601e8372011-03-24 22:23:21 -04005#include "trace_parser.hpp"
6
Zack Rusin353f0532011-09-15 20:23:27 -04007#include <QBuffer>
Zack Rusin91065372011-03-26 01:54:10 -04008#include <QDebug>
Zack Rusinc1acc7f2011-04-02 01:34:04 -04009#include <QImage>
Zack Rusin601e8372011-03-24 22:23:21 -040010#include <QVariant>
11
Zack Rusin601e8372011-03-24 22:23:21 -040012
13ApiTraceModel::ApiTraceModel(QObject *parent)
Zack Rusinf6667d12011-03-30 11:03:37 -040014 : QAbstractItemModel(parent),
15 m_trace(0)
Zack Rusin601e8372011-03-24 22:23:21 -040016{
Zack Rusin601e8372011-03-24 22:23:21 -040017}
18
19ApiTraceModel::~ApiTraceModel()
20{
Zack Rusinf6667d12011-03-30 11:03:37 -040021 m_trace = 0;
Zack Rusin601e8372011-03-24 22:23:21 -040022}
23
24QVariant ApiTraceModel::data(const QModelIndex &index, int role) const
25{
26 if (!index.isValid())
27 return QVariant();
28
Zack Rusinf6667d12011-03-30 11:03:37 -040029 if (index.column() != 0)
Zack Rusin601e8372011-03-24 22:23:21 -040030 return QVariant();
31
Zack Rusinf6667d12011-03-30 11:03:37 -040032 ApiTraceEvent *itm = item(index);
Zack Rusinc1acc7f2011-04-02 01:34:04 -040033 if (!itm) {
34 return QVariant();
35 }
36
37 switch (role) {
38 case Qt::DisplayRole:
39 return itm->staticText().text();
40 case Qt::DecorationRole:
41 return QImage();
Zack Rusin1563a692011-04-02 02:07:24 -040042 case Qt::ToolTipRole: {
43 const QString stateText = tr("State info available.");
44 if (itm->type() == ApiTraceEvent::Call) {
45 ApiTraceCall *call = static_cast<ApiTraceCall*>(itm);
Zack Rusined40bc62011-08-28 17:11:02 -040046 if (!call->hasState())
Zack Rusin344923b2011-04-03 17:22:11 -040047 return QString::fromLatin1("%1)&nbsp;<b>%2</b>")
Zack Rusinead6aad2011-04-15 22:16:18 -040048 .arg(call->index())
49 .arg(call->name());
Zack Rusin1563a692011-04-02 02:07:24 -040050 else
Zack Rusin344923b2011-04-03 17:22:11 -040051 return QString::fromLatin1("%1)&nbsp;<b>%2</b><br/>%3")
Zack Rusinead6aad2011-04-15 22:16:18 -040052 .arg(call->index())
53 .arg(call->name())
Zack Rusin1563a692011-04-02 02:07:24 -040054 .arg(stateText);
55 } else {
Zack Rusin353f0532011-09-15 20:23:27 -040056 const char *htmlTempl =
57 "<div>\n"
58 "<div>\n"
59 "%1"
60 "<span style=\"font-weight:bold; font-size:large; vertical-align:center; padding-bottom: 30px \">\n"
61 "Frame %2</span>\n"
62 "</div>\n"
63 "<div >%3 calls%4</div>\n"
64 "</div>\n";
65
66
Zack Rusin1563a692011-04-02 02:07:24 -040067 ApiTraceFrame *frame = static_cast<ApiTraceFrame*>(itm);
Zack Rusin353f0532011-09-15 20:23:27 -040068 QString thumbStr, sizeStr;
69
70 if (frame->hasState()) {
71 static const char *imgTempl =
72 "<img style=\"float:left;\" "
73 "src=\"data:image/png;base64,%1\"/>\n";
74 static const char *sizeTempl =
75 ", %1kb";
76
77 ApiFramebuffer fbo = frame->state()->colorBuffer();
Martin Schulzeb44232b2016-04-16 19:06:16 +020078 QImage thumb = fbo.calculateThumbnail(false, false);
Zack Rusin353f0532011-09-15 20:23:27 -040079 if (!thumb.isNull()) {
80 QByteArray ba;
81 QBuffer buffer(&ba);
82 buffer.open(QIODevice::WriteOnly);
83 thumb.save(&buffer, "PNG");
84 thumbStr = tr(imgTempl).arg(
85 QString(buffer.data().toBase64()));
86 }
87
88 int binaryDataSize = frame->binaryDataSize() / 1024;
89 if (binaryDataSize > 0) {
90 sizeStr = tr(sizeTempl).arg(binaryDataSize);
91 }
92 }
93
Zack Rusin1a9f7af2011-09-18 19:40:47 -040094 int numCalls = frame->isLoaded()
Zack Rusind9d9d222013-10-11 18:02:26 -040095 ? frame->numTotalCalls()
Zack Rusin353f0532011-09-15 20:23:27 -040096 : frame->numChildrenToLoad();
97
98 return tr(htmlTempl)
99 .arg(thumbStr)
100 .arg(frame->number)
101 .arg(numCalls)
102 .arg(sizeStr);
Zack Rusin1563a692011-04-02 02:07:24 -0400103 }
104 }
Zack Rusinc1acc7f2011-04-02 01:34:04 -0400105 case ApiTraceModel::EventRole:
106 return QVariant::fromValue(itm);
Zack Rusin601e8372011-03-24 22:23:21 -0400107 }
Zack Rusinf6667d12011-03-30 11:03:37 -0400108
109 return QVariant();
Zack Rusin601e8372011-03-24 22:23:21 -0400110}
111
112Qt::ItemFlags ApiTraceModel::flags(const QModelIndex &index) const
113{
114 if (!index.isValid())
115 return 0;
116
117 return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
118}
119
120QVariant ApiTraceModel::headerData(int section, Qt::Orientation orientation,
121 int role ) const
122{
123 if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
124 switch (section) {
125 case 0:
Zack Rusinc1acc7f2011-04-02 01:34:04 -0400126 return tr("Events");
127 case 1:
128 return tr("Flags");
Zack Rusin601e8372011-03-24 22:23:21 -0400129 default:
130 //fall through
131 break;
132 }
133 }
134
135 return QVariant();
136}
137
138QModelIndex ApiTraceModel::index(int row, int column,
139 const QModelIndex &parent) const
140{
Zack Rusinb56e03d2011-04-20 23:58:52 -0400141 if ((parent.isValid() && parent.column() != 0) || column != 0)
Zack Rusin601e8372011-03-24 22:23:21 -0400142 return QModelIndex();
143
Zack Rusind9d9d222013-10-11 18:02:26 -0400144 //qDebug()<<"At row = "<<row<<", column = "<<column<<", parent "<<parent;
145 ApiTraceEvent *parentEvent = item(parent);
146 if (parentEvent) {
147 ApiTraceEvent *event = parentEvent->eventAtRow(row);
148 if (event) {
149 Q_ASSERT(event->type() == ApiTraceEvent::Call);
150 return createIndex(row, column, event);
151 } else {
Zack Rusinf6667d12011-03-30 11:03:37 -0400152 return QModelIndex();
153 }
Zack Rusinf6667d12011-03-30 11:03:37 -0400154 } else {
155 ApiTraceFrame *frame = m_trace->frameAt(row);
156 if (frame)
157 return createIndex(row, column, frame);
158 else
159 return QModelIndex();
160 }
161 return QModelIndex();
Zack Rusin601e8372011-03-24 22:23:21 -0400162}
163
164bool ApiTraceModel::hasChildren(const QModelIndex &parent) const
165{
Zack Rusinf6667d12011-03-30 11:03:37 -0400166 if (parent.isValid()) {
Zack Rusinc1acc7f2011-04-02 01:34:04 -0400167 ApiTraceEvent *event = item(parent);
Zack Rusind9d9d222013-10-11 18:02:26 -0400168 if (!event)
169 return false;
170 if (event->type() == ApiTraceEvent::Frame) {
Zack Rusinc1acc7f2011-04-02 01:34:04 -0400171 ApiTraceFrame *frame = static_cast<ApiTraceFrame*>(event);
Zack Rusin1d31b6c2011-04-26 22:30:25 -0400172 return !frame->isEmpty();
Zack Rusind9d9d222013-10-11 18:02:26 -0400173 } else {
174 Q_ASSERT(event->type() == ApiTraceEvent::Call);
175 ApiTraceCall *call = static_cast<ApiTraceCall*>(event);
176 return call->numChildren() != 0;
177 }
Zack Rusinf6667d12011-03-30 11:03:37 -0400178 } else {
179 return (rowCount() > 0);
180 }
Zack Rusin601e8372011-03-24 22:23:21 -0400181}
182
183QModelIndex ApiTraceModel::parent(const QModelIndex &index) const
184{
185 if (!index.isValid())
186 return QModelIndex();
187
Zack Rusinc1acc7f2011-04-02 01:34:04 -0400188 ApiTraceEvent *event = item(index);
Zack Rusind9d9d222013-10-11 18:02:26 -0400189
190 if (event->type() == ApiTraceEvent::Call) {
Zack Rusinc1acc7f2011-04-02 01:34:04 -0400191 ApiTraceCall *call = static_cast<ApiTraceCall*>(event);
Zack Rusind9d9d222013-10-11 18:02:26 -0400192
193 if (call->parentCall()) {
194 ApiTraceCall *parentCall = call->parentCall();
195 ApiTraceEvent *topEvent = parentCall->parentEvent();
196 return createIndex(topEvent->callIndex(parentCall), 0, parentCall);
197 } else {
198 Q_ASSERT(call->parentFrame());
199 return createIndex(call->parentFrame()->number,
200 0, call->parentFrame());
201 }
Zack Rusinf6667d12011-03-30 11:03:37 -0400202 }
Zack Rusin601e8372011-03-24 22:23:21 -0400203 return QModelIndex();
204}
205
206int ApiTraceModel::rowCount(const QModelIndex &parent) const
207{
Zack Rusinf6667d12011-03-30 11:03:37 -0400208 if (!parent.isValid())
209 return m_trace->numFrames();
210
Zack Rusinc1acc7f2011-04-02 01:34:04 -0400211 ApiTraceEvent *event = item(parent);
Zack Rusind9d9d222013-10-11 18:02:26 -0400212 if (!event)
Zack Rusinf6667d12011-03-30 11:03:37 -0400213 return 0;
214
Zack Rusind9d9d222013-10-11 18:02:26 -0400215 return event->numChildren();
Zack Rusin601e8372011-03-24 22:23:21 -0400216}
217
218int ApiTraceModel::columnCount(const QModelIndex &parent) const
219{
Zack Rusinf6667d12011-03-30 11:03:37 -0400220 return 1;
Zack Rusin601e8372011-03-24 22:23:21 -0400221}
222
Zack Rusin601e8372011-03-24 22:23:21 -0400223bool ApiTraceModel::insertRows(int position, int rows,
224 const QModelIndex &parent)
225{
226 return false;
227}
228
229bool ApiTraceModel::removeRows(int position, int rows,
230 const QModelIndex &parent)
231{
232 bool success = true;
233
234 Q_UNUSED(parent);
235
Zack Rusin601e8372011-03-24 22:23:21 -0400236 beginRemoveRows(parent, position, position + rows - 1);
Zack Rusinf6667d12011-03-30 11:03:37 -0400237 //XXX remove it from ApiTrace
Zack Rusin601e8372011-03-24 22:23:21 -0400238 endRemoveRows();
239
240 return success;
241}
242
Zack Rusinf6667d12011-03-30 11:03:37 -0400243void ApiTraceModel::setApiTrace(ApiTrace *trace)
Zack Rusin601e8372011-03-24 22:23:21 -0400244{
Zack Rusinf6667d12011-03-30 11:03:37 -0400245 if (m_trace == trace)
246 return;
247 if (m_trace)
248 disconnect(m_trace);
249 m_trace = trace;
Zack Rusinca164112011-04-11 02:23:09 -0400250 connect(m_trace, SIGNAL(invalidated()),
251 this, SLOT(invalidateFrames()));
Zack Rusinf6667d12011-03-30 11:03:37 -0400252 connect(m_trace, SIGNAL(framesInvalidated()),
253 this, SLOT(invalidateFrames()));
Zack Rusinb56e03d2011-04-20 23:58:52 -0400254 connect(m_trace, SIGNAL(beginAddingFrames(int, int)),
255 this, SLOT(beginAddingFrames(int, int)));
256 connect(m_trace, SIGNAL(endAddingFrames()),
257 this, SLOT(endAddingFrames()));
Dan McCabe10bd4242012-03-05 17:20:40 -0800258 connect(m_trace, SIGNAL(changed(ApiTraceEvent*)),
259 this, SLOT(changed(ApiTraceEvent*)));
Zack Rusinf682e192011-09-07 01:36:41 -0400260 connect(m_trace, SIGNAL(beginLoadingFrame(ApiTraceFrame*,int)),
261 this, SLOT(beginLoadingFrame(ApiTraceFrame*,int)));
262 connect(m_trace, SIGNAL(endLoadingFrame(ApiTraceFrame*)),
263 this, SLOT(endLoadingFrame(ApiTraceFrame*)));
264
Zack Rusin601e8372011-03-24 22:23:21 -0400265}
266
Zack Rusinf6667d12011-03-30 11:03:37 -0400267const ApiTrace * ApiTraceModel::apiTrace() const
Zack Rusin601e8372011-03-24 22:23:21 -0400268{
Zack Rusinf6667d12011-03-30 11:03:37 -0400269 return m_trace;
270}
Zack Rusin601e8372011-03-24 22:23:21 -0400271
Zack Rusinf6667d12011-03-30 11:03:37 -0400272void ApiTraceModel::invalidateFrames()
273{
274 beginResetModel();
275 endResetModel();
276}
Zack Rusin91065372011-03-26 01:54:10 -0400277
Zack Rusinb56e03d2011-04-20 23:58:52 -0400278void ApiTraceModel::beginAddingFrames(int oldCount, int numAdded)
Zack Rusinf6667d12011-03-30 11:03:37 -0400279{
280 beginInsertRows(QModelIndex(), oldCount,
Zack Rusinc1acc7f2011-04-02 01:34:04 -0400281 oldCount + numAdded - 1);
Zack Rusinf6667d12011-03-30 11:03:37 -0400282}
Zack Rusin601e8372011-03-24 22:23:21 -0400283
Zack Rusinf6667d12011-03-30 11:03:37 -0400284ApiTraceEvent * ApiTraceModel::item(const QModelIndex &index) const
285{
286 if (!index.isValid())
287 return 0;
288 return static_cast<ApiTraceEvent*>(index.internalPointer());
Zack Rusin601e8372011-03-24 22:23:21 -0400289}
290
Zack Rusinc1acc7f2011-04-02 01:34:04 -0400291void ApiTraceModel::stateSetOnEvent(ApiTraceEvent *event)
292{
293 if (!event)
294 return;
295
296 if (event->type() == ApiTraceEvent::Call) {
297 ApiTraceCall *call = static_cast<ApiTraceCall*>(event);
Zack Rusind9d9d222013-10-11 18:02:26 -0400298 QModelIndex index = indexForCall(call);
Zack Rusinc1acc7f2011-04-02 01:34:04 -0400299 emit dataChanged(index, index);
300 } else if (event->type() == ApiTraceEvent::Frame) {
301 ApiTraceFrame *frame = static_cast<ApiTraceFrame*>(event);
José Fonseca34500442012-03-24 07:56:45 +0000302 const QList<ApiTraceFrame*> & frames = m_trace->frames();
Zack Rusinc1acc7f2011-04-02 01:34:04 -0400303 int row = frames.indexOf(frame);
304 QModelIndex index = createIndex(row, 0, frame);
305 emit dataChanged(index, index);
306 }
307}
308
Zack Rusinf54c4fc2011-04-12 23:39:13 -0400309QModelIndex ApiTraceModel::indexForCall(ApiTraceCall *call) const
310{
Zack Rusinc52d18a2011-04-11 00:15:07 -0400311 if (!call) {
312 return QModelIndex();
313 }
314
Zack Rusind9d9d222013-10-11 18:02:26 -0400315 ApiTraceEvent *parentEvent = call->parentEvent();
316 Q_ASSERT(parentEvent);
Zack Rusinc52d18a2011-04-11 00:15:07 -0400317
Zack Rusind9d9d222013-10-11 18:02:26 -0400318 int row = parentEvent->callIndex(call);
Zack Rusinc52d18a2011-04-11 00:15:07 -0400319 if (row < 0) {
Zack Rusinead6aad2011-04-15 22:16:18 -0400320 qDebug() << "Couldn't find call num "<<call->index()<<" inside parent!";
Zack Rusinc52d18a2011-04-11 00:15:07 -0400321 return QModelIndex();
322 }
323 return createIndex(row, 0, call);
324}
325
Dan McCabe10bd4242012-03-05 17:20:40 -0800326void ApiTraceModel::changed(ApiTraceEvent *event)
327{
328 if (event->type() == ApiTraceEvent::Call) {
329 callChanged(static_cast<ApiTraceCall*>(event));
330 } else if (event->type() == ApiTraceEvent::Frame) {
331 frameChanged(static_cast<ApiTraceFrame*>(event));
332 }
333}
334
Zack Rusin0ddd2502011-04-17 02:34:45 -0400335void ApiTraceModel::callChanged(ApiTraceCall *call)
336{
Zack Rusin63efea82011-04-17 17:10:45 -0400337 ApiTrace *trace = call->parentFrame()->parentTrace();
Zack Rusin9af5bff2011-04-18 01:05:50 -0400338
Zack Rusincc0b4912011-04-19 01:59:20 -0400339#if 0
Zack Rusin9af5bff2011-04-18 01:05:50 -0400340 qDebug()<<"Call changed = "<<call->edited();
Zack Rusin63efea82011-04-17 17:10:45 -0400341 qDebug()<<"\ttrace edited = "<<trace->edited();
342 qDebug()<<"\ttrace file = "<<trace->fileName();
343 qDebug()<<"\ttrace needs saving = "<<trace->needsSaving();
Zack Rusin9af5bff2011-04-18 01:05:50 -0400344#endif
345
Zack Rusinb53b1612011-04-19 01:33:58 -0400346 Q_ASSERT(trace);
347 if (trace->needsSaving())
348 trace->save();
349
Zack Rusind9d9d222013-10-11 18:02:26 -0400350 QModelIndex index = indexForCall(call);
Zack Rusin9af5bff2011-04-18 01:05:50 -0400351 emit dataChanged(index, index);
Zack Rusin0ddd2502011-04-17 02:34:45 -0400352}
353
Dan McCabe10bd4242012-03-05 17:20:40 -0800354void ApiTraceModel::frameChanged(ApiTraceFrame *frame)
355{
José Fonseca34500442012-03-24 07:56:45 +0000356 const QList<ApiTraceFrame*> & frames = m_trace->frames();
Dan McCabe10bd4242012-03-05 17:20:40 -0800357 int row = frames.indexOf(frame);
358 QModelIndex index = createIndex(row, 0, frame);
359 emit dataChanged(index, index);
360}
361
Zack Rusinb56e03d2011-04-20 23:58:52 -0400362void ApiTraceModel::endAddingFrames()
363{
364 endInsertRows();
365}
366
Zack Rusin3176ebe2011-09-06 21:11:36 -0400367bool ApiTraceModel::canFetchMore(const QModelIndex &parent) const
368{
369 if (parent.isValid()) {
370 ApiTraceEvent *event = item(parent);
371 if (event && event->type() == ApiTraceEvent::Frame) {
372 ApiTraceFrame *frame = static_cast<ApiTraceFrame*>(event);
Zack Rusin1a9f7af2011-09-18 19:40:47 -0400373 return !frame->isLoaded() && !m_loadingFrames.contains(frame);
Zack Rusin3176ebe2011-09-06 21:11:36 -0400374 } else
375 return false;
376 } else {
377 return false;
378 }
379}
380
381void ApiTraceModel::fetchMore(const QModelIndex &parent)
382{
383 if (parent.isValid()) {
384 ApiTraceEvent *event = item(parent);
385 if (event && event->type() == ApiTraceEvent::Frame) {
386 ApiTraceFrame *frame = static_cast<ApiTraceFrame*>(event);
Zack Rusin3176ebe2011-09-06 21:11:36 -0400387
Zack Rusin1a9f7af2011-09-18 19:40:47 -0400388 Q_ASSERT(!frame->isLoaded());
Zack Rusin3176ebe2011-09-06 21:11:36 -0400389 m_loadingFrames.insert(frame);
Zack Rusin3176ebe2011-09-06 21:11:36 -0400390
391 m_trace->loadFrame(frame);
392 }
393 }
394}
395
Zack Rusinf682e192011-09-07 01:36:41 -0400396void ApiTraceModel::beginLoadingFrame(ApiTraceFrame *frame, int numAdded)
397{
398 QModelIndex index = createIndex(frame->number, 0, frame);
399 beginInsertRows(index, 0, numAdded - 1);
400}
401
402void ApiTraceModel::endLoadingFrame(ApiTraceFrame *frame)
Zack Rusin3176ebe2011-09-06 21:11:36 -0400403{
404 QModelIndex index = createIndex(frame->number, 0, frame);
405#if 0
406 qDebug()<<"Frame loaded = "<<frame->loaded();
407 qDebug()<<"\tframe idx = "<<frame->number;
408 qDebug()<<"\tis empty = "<<frame->isEmpty();
409 qDebug()<<"\tnum children = "<<frame->numChildren();
410 qDebug()<<"\tindex is "<<index;
411#endif
412
Zack Rusin3176ebe2011-09-06 21:11:36 -0400413 endInsertRows();
414
415 emit dataChanged(index, index);
Zack Rusinf682e192011-09-07 01:36:41 -0400416
417 m_loadingFrames.remove(frame);
Zack Rusin3176ebe2011-09-06 21:11:36 -0400418}
419
Zack Rusin601e8372011-03-24 22:23:21 -0400420#include "apitracemodel.moc"