blob: 7303ae1c31e836bb2e507fe9b5fd34af657fa574 [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()));
Zack Rusin0ddd2502011-04-17 02:34:45 -0400251 connect(m_trace, SIGNAL(changed(ApiTraceCall*)),
252 this, SLOT(callChanged(ApiTraceCall*)));
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
Zack Rusin0ddd2502011-04-17 02:34:45 -0400321void ApiTraceModel::callChanged(ApiTraceCall *call)
322{
Zack Rusin63efea82011-04-17 17:10:45 -0400323 ApiTrace *trace = call->parentFrame()->parentTrace();
Zack Rusin9af5bff2011-04-18 01:05:50 -0400324
Zack Rusincc0b4912011-04-19 01:59:20 -0400325#if 0
Zack Rusin9af5bff2011-04-18 01:05:50 -0400326 qDebug()<<"Call changed = "<<call->edited();
Zack Rusin63efea82011-04-17 17:10:45 -0400327 qDebug()<<"\ttrace edited = "<<trace->edited();
328 qDebug()<<"\ttrace file = "<<trace->fileName();
329 qDebug()<<"\ttrace needs saving = "<<trace->needsSaving();
Zack Rusin9af5bff2011-04-18 01:05:50 -0400330#endif
331
Zack Rusinb53b1612011-04-19 01:33:58 -0400332 Q_ASSERT(trace);
333 if (trace->needsSaving())
334 trace->save();
335
Zack Rusin9af5bff2011-04-18 01:05:50 -0400336 ApiTraceFrame *frame = call->parentFrame();
Zack Rusin1d31b6c2011-04-26 22:30:25 -0400337 int row = frame->callIndex(call);
Zack Rusin9af5bff2011-04-18 01:05:50 -0400338 QModelIndex index = createIndex(row, 0, call);
339 emit dataChanged(index, index);
Zack Rusin0ddd2502011-04-17 02:34:45 -0400340}
341
Zack Rusinb56e03d2011-04-20 23:58:52 -0400342void ApiTraceModel::endAddingFrames()
343{
344 endInsertRows();
345}
346
Zack Rusin3176ebe2011-09-06 21:11:36 -0400347bool ApiTraceModel::canFetchMore(const QModelIndex &parent) const
348{
349 if (parent.isValid()) {
350 ApiTraceEvent *event = item(parent);
351 if (event && event->type() == ApiTraceEvent::Frame) {
352 ApiTraceFrame *frame = static_cast<ApiTraceFrame*>(event);
Zack Rusin1a9f7af2011-09-18 19:40:47 -0400353 return !frame->isLoaded() && !m_loadingFrames.contains(frame);
Zack Rusin3176ebe2011-09-06 21:11:36 -0400354 } else
355 return false;
356 } else {
357 return false;
358 }
359}
360
361void ApiTraceModel::fetchMore(const QModelIndex &parent)
362{
363 if (parent.isValid()) {
364 ApiTraceEvent *event = item(parent);
365 if (event && event->type() == ApiTraceEvent::Frame) {
366 ApiTraceFrame *frame = static_cast<ApiTraceFrame*>(event);
367 QModelIndex index = createIndex(frame->number, 0, frame);
368
Zack Rusin1a9f7af2011-09-18 19:40:47 -0400369 Q_ASSERT(!frame->isLoaded());
Zack Rusin3176ebe2011-09-06 21:11:36 -0400370 m_loadingFrames.insert(frame);
Zack Rusin3176ebe2011-09-06 21:11:36 -0400371
372 m_trace->loadFrame(frame);
373 }
374 }
375}
376
Zack Rusinf682e192011-09-07 01:36:41 -0400377void ApiTraceModel::beginLoadingFrame(ApiTraceFrame *frame, int numAdded)
378{
379 QModelIndex index = createIndex(frame->number, 0, frame);
380 beginInsertRows(index, 0, numAdded - 1);
381}
382
383void ApiTraceModel::endLoadingFrame(ApiTraceFrame *frame)
Zack Rusin3176ebe2011-09-06 21:11:36 -0400384{
385 QModelIndex index = createIndex(frame->number, 0, frame);
386#if 0
387 qDebug()<<"Frame loaded = "<<frame->loaded();
388 qDebug()<<"\tframe idx = "<<frame->number;
389 qDebug()<<"\tis empty = "<<frame->isEmpty();
390 qDebug()<<"\tnum children = "<<frame->numChildren();
391 qDebug()<<"\tindex is "<<index;
392#endif
393
Zack Rusin3176ebe2011-09-06 21:11:36 -0400394 endInsertRows();
395
396 emit dataChanged(index, index);
Zack Rusinf682e192011-09-07 01:36:41 -0400397
398 m_loadingFrames.remove(frame);
Zack Rusin3176ebe2011-09-06 21:11:36 -0400399}
400
Zack Rusin601e8372011-03-24 22:23:21 -0400401#include "apitracemodel.moc"