blob: 9103da58e9847a07ec8aaedbba0c567c173d6ae9 [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();
78 QImage thumb = fbo.thumb();
79 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 Rusin353f0532011-09-15 20:23:27 -040095 ? frame->numChildren()
96 : 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 Rusinc1acc7f2011-04-02 01:34:04 -0400144 ApiTraceEvent *event = item(parent);
145 if (event) {
146 if (event->type() != ApiTraceEvent::Frame) {
147 qDebug()<<"got a valid parent but it's not a frame "<<event->type();
Zack Rusinf6667d12011-03-30 11:03:37 -0400148 return QModelIndex();
149 }
Zack Rusinc1acc7f2011-04-02 01:34:04 -0400150 ApiTraceFrame *frame = static_cast<ApiTraceFrame*>(event);
Zack Rusin1d31b6c2011-04-26 22:30:25 -0400151 ApiTraceCall *call = frame->call(row);
Zack Rusinf6667d12011-03-30 11:03:37 -0400152 if (call)
153 return createIndex(row, column, call);
154 else
155 return QModelIndex();
156 } else {
157 ApiTraceFrame *frame = m_trace->frameAt(row);
158 if (frame)
159 return createIndex(row, column, frame);
160 else
161 return QModelIndex();
162 }
163 return QModelIndex();
Zack Rusin601e8372011-03-24 22:23:21 -0400164}
165
166bool ApiTraceModel::hasChildren(const QModelIndex &parent) const
167{
Zack Rusinf6667d12011-03-30 11:03:37 -0400168 if (parent.isValid()) {
Zack Rusinc1acc7f2011-04-02 01:34:04 -0400169 ApiTraceEvent *event = item(parent);
170 if (event && event->type() == ApiTraceEvent::Frame) {
171 ApiTraceFrame *frame = static_cast<ApiTraceFrame*>(event);
Zack Rusin1d31b6c2011-04-26 22:30:25 -0400172 return !frame->isEmpty();
Zack Rusinc1acc7f2011-04-02 01:34:04 -0400173 } else
Zack Rusinf6667d12011-03-30 11:03:37 -0400174 return false;
175 } else {
176 return (rowCount() > 0);
177 }
Zack Rusin601e8372011-03-24 22:23:21 -0400178}
179
180QModelIndex ApiTraceModel::parent(const QModelIndex &index) const
181{
182 if (!index.isValid())
183 return QModelIndex();
184
Zack Rusinc1acc7f2011-04-02 01:34:04 -0400185 ApiTraceEvent *event = item(index);
186 if (event && event->type() == ApiTraceEvent::Call) {
187 ApiTraceCall *call = static_cast<ApiTraceCall*>(event);
Zack Rusinead6aad2011-04-15 22:16:18 -0400188 Q_ASSERT(call->parentFrame());
189 return createIndex(call->parentFrame()->number,
190 0, call->parentFrame());
Zack Rusinf6667d12011-03-30 11:03:37 -0400191 }
Zack Rusin601e8372011-03-24 22:23:21 -0400192 return QModelIndex();
193}
194
195int ApiTraceModel::rowCount(const QModelIndex &parent) const
196{
Zack Rusinf6667d12011-03-30 11:03:37 -0400197 if (!parent.isValid())
198 return m_trace->numFrames();
199
Zack Rusinc1acc7f2011-04-02 01:34:04 -0400200 ApiTraceEvent *event = item(parent);
201 if (!event || event->type() == ApiTraceEvent::Call)
Zack Rusinf6667d12011-03-30 11:03:37 -0400202 return 0;
203
Zack Rusinc1acc7f2011-04-02 01:34:04 -0400204 ApiTraceFrame *frame = static_cast<ApiTraceFrame*>(event);
Zack Rusinf6667d12011-03-30 11:03:37 -0400205 if (frame)
Zack Rusin1d31b6c2011-04-26 22:30:25 -0400206 return frame->numChildren();
Zack Rusinf6667d12011-03-30 11:03:37 -0400207
208 return 0;
Zack Rusin601e8372011-03-24 22:23:21 -0400209}
210
211int ApiTraceModel::columnCount(const QModelIndex &parent) const
212{
Zack Rusinf6667d12011-03-30 11:03:37 -0400213 return 1;
Zack Rusin601e8372011-03-24 22:23:21 -0400214}
215
Zack Rusin601e8372011-03-24 22:23:21 -0400216bool ApiTraceModel::insertRows(int position, int rows,
217 const QModelIndex &parent)
218{
219 return false;
220}
221
222bool ApiTraceModel::removeRows(int position, int rows,
223 const QModelIndex &parent)
224{
225 bool success = true;
226
227 Q_UNUSED(parent);
228
Zack Rusin601e8372011-03-24 22:23:21 -0400229 beginRemoveRows(parent, position, position + rows - 1);
Zack Rusinf6667d12011-03-30 11:03:37 -0400230 //XXX remove it from ApiTrace
Zack Rusin601e8372011-03-24 22:23:21 -0400231 endRemoveRows();
232
233 return success;
234}
235
Zack Rusinf6667d12011-03-30 11:03:37 -0400236void ApiTraceModel::setApiTrace(ApiTrace *trace)
Zack Rusin601e8372011-03-24 22:23:21 -0400237{
Zack Rusinf6667d12011-03-30 11:03:37 -0400238 if (m_trace == trace)
239 return;
240 if (m_trace)
241 disconnect(m_trace);
242 m_trace = trace;
Zack Rusinca164112011-04-11 02:23:09 -0400243 connect(m_trace, SIGNAL(invalidated()),
244 this, SLOT(invalidateFrames()));
Zack Rusinf6667d12011-03-30 11:03:37 -0400245 connect(m_trace, SIGNAL(framesInvalidated()),
246 this, SLOT(invalidateFrames()));
Zack Rusinb56e03d2011-04-20 23:58:52 -0400247 connect(m_trace, SIGNAL(beginAddingFrames(int, int)),
248 this, SLOT(beginAddingFrames(int, int)));
249 connect(m_trace, SIGNAL(endAddingFrames()),
250 this, SLOT(endAddingFrames()));
Dan McCabe10bd4242012-03-05 17:20:40 -0800251 connect(m_trace, SIGNAL(changed(ApiTraceEvent*)),
252 this, SLOT(changed(ApiTraceEvent*)));
Zack Rusinf682e192011-09-07 01:36:41 -0400253 connect(m_trace, SIGNAL(beginLoadingFrame(ApiTraceFrame*,int)),
254 this, SLOT(beginLoadingFrame(ApiTraceFrame*,int)));
255 connect(m_trace, SIGNAL(endLoadingFrame(ApiTraceFrame*)),
256 this, SLOT(endLoadingFrame(ApiTraceFrame*)));
257
Zack Rusin601e8372011-03-24 22:23:21 -0400258}
259
Zack Rusinf6667d12011-03-30 11:03:37 -0400260const ApiTrace * ApiTraceModel::apiTrace() const
Zack Rusin601e8372011-03-24 22:23:21 -0400261{
Zack Rusinf6667d12011-03-30 11:03:37 -0400262 return m_trace;
263}
Zack Rusin601e8372011-03-24 22:23:21 -0400264
Zack Rusinf6667d12011-03-30 11:03:37 -0400265void ApiTraceModel::invalidateFrames()
266{
267 beginResetModel();
268 endResetModel();
269}
Zack Rusin91065372011-03-26 01:54:10 -0400270
Zack Rusinb56e03d2011-04-20 23:58:52 -0400271void ApiTraceModel::beginAddingFrames(int oldCount, int numAdded)
Zack Rusinf6667d12011-03-30 11:03:37 -0400272{
273 beginInsertRows(QModelIndex(), oldCount,
Zack Rusinc1acc7f2011-04-02 01:34:04 -0400274 oldCount + numAdded - 1);
Zack Rusinf6667d12011-03-30 11:03:37 -0400275}
Zack Rusin601e8372011-03-24 22:23:21 -0400276
Zack Rusinf6667d12011-03-30 11:03:37 -0400277ApiTraceEvent * ApiTraceModel::item(const QModelIndex &index) const
278{
279 if (!index.isValid())
280 return 0;
281 return static_cast<ApiTraceEvent*>(index.internalPointer());
Zack Rusin601e8372011-03-24 22:23:21 -0400282}
283
Zack Rusinc1acc7f2011-04-02 01:34:04 -0400284void ApiTraceModel::stateSetOnEvent(ApiTraceEvent *event)
285{
286 if (!event)
287 return;
288
289 if (event->type() == ApiTraceEvent::Call) {
290 ApiTraceCall *call = static_cast<ApiTraceCall*>(event);
Zack Rusinead6aad2011-04-15 22:16:18 -0400291 ApiTraceFrame *frame = call->parentFrame();
Zack Rusin1d31b6c2011-04-26 22:30:25 -0400292 int row = frame->callIndex(call);
Zack Rusinc1acc7f2011-04-02 01:34:04 -0400293 QModelIndex index = createIndex(row, 0, call);
294 emit dataChanged(index, index);
295 } else if (event->type() == ApiTraceEvent::Frame) {
296 ApiTraceFrame *frame = static_cast<ApiTraceFrame*>(event);
297 const QList<ApiTraceFrame*> frames = m_trace->frames();
298 int row = frames.indexOf(frame);
299 QModelIndex index = createIndex(row, 0, frame);
300 emit dataChanged(index, index);
301 }
302}
303
Zack Rusinf54c4fc2011-04-12 23:39:13 -0400304QModelIndex ApiTraceModel::indexForCall(ApiTraceCall *call) const
305{
Zack Rusinc52d18a2011-04-11 00:15:07 -0400306 if (!call) {
307 return QModelIndex();
308 }
309
Zack Rusinead6aad2011-04-15 22:16:18 -0400310 ApiTraceFrame *frame = call->parentFrame();
Zack Rusinc52d18a2011-04-11 00:15:07 -0400311 Q_ASSERT(frame);
312
Zack Rusin1d31b6c2011-04-26 22:30:25 -0400313 int row = frame->callIndex(call);
Zack Rusinc52d18a2011-04-11 00:15:07 -0400314 if (row < 0) {
Zack Rusinead6aad2011-04-15 22:16:18 -0400315 qDebug() << "Couldn't find call num "<<call->index()<<" inside parent!";
Zack Rusinc52d18a2011-04-11 00:15:07 -0400316 return QModelIndex();
317 }
318 return createIndex(row, 0, call);
319}
320
Dan McCabe10bd4242012-03-05 17:20:40 -0800321void ApiTraceModel::changed(ApiTraceEvent *event)
322{
323 if (event->type() == ApiTraceEvent::Call) {
324 callChanged(static_cast<ApiTraceCall*>(event));
325 } else if (event->type() == ApiTraceEvent::Frame) {
326 frameChanged(static_cast<ApiTraceFrame*>(event));
327 }
328}
329
Zack Rusin0ddd2502011-04-17 02:34:45 -0400330void ApiTraceModel::callChanged(ApiTraceCall *call)
331{
Zack Rusin63efea82011-04-17 17:10:45 -0400332 ApiTrace *trace = call->parentFrame()->parentTrace();
Zack Rusin9af5bff2011-04-18 01:05:50 -0400333
Zack Rusincc0b4912011-04-19 01:59:20 -0400334#if 0
Zack Rusin9af5bff2011-04-18 01:05:50 -0400335 qDebug()<<"Call changed = "<<call->edited();
Zack Rusin63efea82011-04-17 17:10:45 -0400336 qDebug()<<"\ttrace edited = "<<trace->edited();
337 qDebug()<<"\ttrace file = "<<trace->fileName();
338 qDebug()<<"\ttrace needs saving = "<<trace->needsSaving();
Zack Rusin9af5bff2011-04-18 01:05:50 -0400339#endif
340
Zack Rusinb53b1612011-04-19 01:33:58 -0400341 Q_ASSERT(trace);
342 if (trace->needsSaving())
343 trace->save();
344
Zack Rusin9af5bff2011-04-18 01:05:50 -0400345 ApiTraceFrame *frame = call->parentFrame();
Zack Rusin1d31b6c2011-04-26 22:30:25 -0400346 int row = frame->callIndex(call);
Zack Rusin9af5bff2011-04-18 01:05:50 -0400347 QModelIndex index = createIndex(row, 0, call);
348 emit dataChanged(index, index);
Zack Rusin0ddd2502011-04-17 02:34:45 -0400349}
350
Dan McCabe10bd4242012-03-05 17:20:40 -0800351void ApiTraceModel::frameChanged(ApiTraceFrame *frame)
352{
353 const QList<ApiTraceFrame*> frames = m_trace->frames();
354 int row = frames.indexOf(frame);
355 QModelIndex index = createIndex(row, 0, frame);
356 emit dataChanged(index, index);
357}
358
Zack Rusinb56e03d2011-04-20 23:58:52 -0400359void ApiTraceModel::endAddingFrames()
360{
361 endInsertRows();
362}
363
Zack Rusin3176ebe2011-09-06 21:11:36 -0400364bool ApiTraceModel::canFetchMore(const QModelIndex &parent) const
365{
366 if (parent.isValid()) {
367 ApiTraceEvent *event = item(parent);
368 if (event && event->type() == ApiTraceEvent::Frame) {
369 ApiTraceFrame *frame = static_cast<ApiTraceFrame*>(event);
Zack Rusin1a9f7af2011-09-18 19:40:47 -0400370 return !frame->isLoaded() && !m_loadingFrames.contains(frame);
Zack Rusin3176ebe2011-09-06 21:11:36 -0400371 } else
372 return false;
373 } else {
374 return false;
375 }
376}
377
378void ApiTraceModel::fetchMore(const QModelIndex &parent)
379{
380 if (parent.isValid()) {
381 ApiTraceEvent *event = item(parent);
382 if (event && event->type() == ApiTraceEvent::Frame) {
383 ApiTraceFrame *frame = static_cast<ApiTraceFrame*>(event);
384 QModelIndex index = createIndex(frame->number, 0, frame);
385
Zack Rusin1a9f7af2011-09-18 19:40:47 -0400386 Q_ASSERT(!frame->isLoaded());
Zack Rusin3176ebe2011-09-06 21:11:36 -0400387 m_loadingFrames.insert(frame);
Zack Rusin3176ebe2011-09-06 21:11:36 -0400388
389 m_trace->loadFrame(frame);
390 }
391 }
392}
393
Zack Rusinf682e192011-09-07 01:36:41 -0400394void ApiTraceModel::beginLoadingFrame(ApiTraceFrame *frame, int numAdded)
395{
396 QModelIndex index = createIndex(frame->number, 0, frame);
397 beginInsertRows(index, 0, numAdded - 1);
398}
399
400void ApiTraceModel::endLoadingFrame(ApiTraceFrame *frame)
Zack Rusin3176ebe2011-09-06 21:11:36 -0400401{
402 QModelIndex index = createIndex(frame->number, 0, frame);
403#if 0
404 qDebug()<<"Frame loaded = "<<frame->loaded();
405 qDebug()<<"\tframe idx = "<<frame->number;
406 qDebug()<<"\tis empty = "<<frame->isEmpty();
407 qDebug()<<"\tnum children = "<<frame->numChildren();
408 qDebug()<<"\tindex is "<<index;
409#endif
410
Zack Rusin3176ebe2011-09-06 21:11:36 -0400411 endInsertRows();
412
413 emit dataChanged(index, index);
Zack Rusinf682e192011-09-07 01:36:41 -0400414
415 m_loadingFrames.remove(frame);
Zack Rusin3176ebe2011-09-06 21:11:36 -0400416}
417
Zack Rusin601e8372011-03-24 22:23:21 -0400418#include "apitracemodel.moc"