blob: debf5c5712698470c27a6ea024b96b4dd2b211ee [file] [log] [blame]
Zack Rusin601e8372011-03-24 22:23:21 -04001#include "apitracemodel.h"
2
3#include "apitracecall.h"
4#include "loaderthread.h"
5#include "trace_parser.hpp"
6
Zack Rusin91065372011-03-26 01:54:10 -04007#include <QDebug>
Zack Rusinc1acc7f2011-04-02 01:34:04 -04008#include <QImage>
Zack Rusin601e8372011-03-24 22:23:21 -04009#include <QVariant>
10
Zack Rusin601e8372011-03-24 22:23:21 -040011
12ApiTraceModel::ApiTraceModel(QObject *parent)
Zack Rusinf6667d12011-03-30 11:03:37 -040013 : QAbstractItemModel(parent),
14 m_trace(0)
Zack Rusin601e8372011-03-24 22:23:21 -040015{
Zack Rusin601e8372011-03-24 22:23:21 -040016}
17
18ApiTraceModel::~ApiTraceModel()
19{
Zack Rusinf6667d12011-03-30 11:03:37 -040020 m_trace = 0;
Zack Rusin601e8372011-03-24 22:23:21 -040021}
22
23QVariant ApiTraceModel::data(const QModelIndex &index, int role) const
24{
25 if (!index.isValid())
26 return QVariant();
27
Zack Rusinf6667d12011-03-30 11:03:37 -040028 if (index.column() != 0)
Zack Rusin601e8372011-03-24 22:23:21 -040029 return QVariant();
30
Zack Rusinf6667d12011-03-30 11:03:37 -040031 ApiTraceEvent *itm = item(index);
Zack Rusinc1acc7f2011-04-02 01:34:04 -040032 if (!itm) {
33 return QVariant();
34 }
35
36 switch (role) {
37 case Qt::DisplayRole:
38 return itm->staticText().text();
39 case Qt::DecorationRole:
40 return QImage();
Zack Rusin1563a692011-04-02 02:07:24 -040041 case Qt::ToolTipRole: {
42 const QString stateText = tr("State info available.");
43 if (itm->type() == ApiTraceEvent::Call) {
44 ApiTraceCall *call = static_cast<ApiTraceCall*>(itm);
45 if (call->state().isEmpty())
Zack Rusin344923b2011-04-03 17:22:11 -040046 return QString::fromLatin1("%1)&nbsp;<b>%2</b>")
Zack Rusinead6aad2011-04-15 22:16:18 -040047 .arg(call->index())
48 .arg(call->name());
Zack Rusin1563a692011-04-02 02:07:24 -040049 else
Zack Rusin344923b2011-04-03 17:22:11 -040050 return QString::fromLatin1("%1)&nbsp;<b>%2</b><br/>%3")
Zack Rusinead6aad2011-04-15 22:16:18 -040051 .arg(call->index())
52 .arg(call->name())
Zack Rusin1563a692011-04-02 02:07:24 -040053 .arg(stateText);
54 } else {
55 ApiTraceFrame *frame = static_cast<ApiTraceFrame*>(itm);
56 QString text = frame->staticText().text();
57 if (frame->state().isEmpty())
58 return QString::fromLatin1("<b>%1</b>").arg(text);
59 else
60 return QString::fromLatin1("<b>%1</b><br/>%2")
61 .arg(text)
62 .arg(stateText);
63 }
64 }
Zack Rusinc1acc7f2011-04-02 01:34:04 -040065 case ApiTraceModel::EventRole:
66 return QVariant::fromValue(itm);
Zack Rusin601e8372011-03-24 22:23:21 -040067 }
Zack Rusinf6667d12011-03-30 11:03:37 -040068
69 return QVariant();
Zack Rusin601e8372011-03-24 22:23:21 -040070}
71
72Qt::ItemFlags ApiTraceModel::flags(const QModelIndex &index) const
73{
74 if (!index.isValid())
75 return 0;
76
77 return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
78}
79
80QVariant ApiTraceModel::headerData(int section, Qt::Orientation orientation,
81 int role ) const
82{
83 if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
84 switch (section) {
85 case 0:
Zack Rusinc1acc7f2011-04-02 01:34:04 -040086 return tr("Events");
87 case 1:
88 return tr("Flags");
Zack Rusin601e8372011-03-24 22:23:21 -040089 default:
90 //fall through
91 break;
92 }
93 }
94
95 return QVariant();
96}
97
98QModelIndex ApiTraceModel::index(int row, int column,
99 const QModelIndex &parent) const
100{
Zack Rusinb56e03d2011-04-20 23:58:52 -0400101 if ((parent.isValid() && parent.column() != 0) || column != 0)
Zack Rusin601e8372011-03-24 22:23:21 -0400102 return QModelIndex();
103
Zack Rusinc1acc7f2011-04-02 01:34:04 -0400104 ApiTraceEvent *event = item(parent);
105 if (event) {
106 if (event->type() != ApiTraceEvent::Frame) {
107 qDebug()<<"got a valid parent but it's not a frame "<<event->type();
Zack Rusinf6667d12011-03-30 11:03:37 -0400108 return QModelIndex();
109 }
Zack Rusinc1acc7f2011-04-02 01:34:04 -0400110 ApiTraceFrame *frame = static_cast<ApiTraceFrame*>(event);
Zack Rusinf6667d12011-03-30 11:03:37 -0400111 ApiTraceCall *call = frame->calls.value(row);
112 if (call)
113 return createIndex(row, column, call);
114 else
115 return QModelIndex();
116 } else {
117 ApiTraceFrame *frame = m_trace->frameAt(row);
118 if (frame)
119 return createIndex(row, column, frame);
120 else
121 return QModelIndex();
122 }
123 return QModelIndex();
Zack Rusin601e8372011-03-24 22:23:21 -0400124}
125
126bool ApiTraceModel::hasChildren(const QModelIndex &parent) const
127{
Zack Rusinf6667d12011-03-30 11:03:37 -0400128 if (parent.isValid()) {
Zack Rusinc1acc7f2011-04-02 01:34:04 -0400129 ApiTraceEvent *event = item(parent);
130 if (event && event->type() == ApiTraceEvent::Frame) {
131 ApiTraceFrame *frame = static_cast<ApiTraceFrame*>(event);
Zack Rusinf6667d12011-03-30 11:03:37 -0400132 return !frame->calls.isEmpty();
Zack Rusinc1acc7f2011-04-02 01:34:04 -0400133 } else
Zack Rusinf6667d12011-03-30 11:03:37 -0400134 return false;
135 } else {
136 return (rowCount() > 0);
137 }
Zack Rusin601e8372011-03-24 22:23:21 -0400138}
139
140QModelIndex ApiTraceModel::parent(const QModelIndex &index) const
141{
142 if (!index.isValid())
143 return QModelIndex();
144
Zack Rusinc1acc7f2011-04-02 01:34:04 -0400145 ApiTraceEvent *event = item(index);
146 if (event && event->type() == ApiTraceEvent::Call) {
147 ApiTraceCall *call = static_cast<ApiTraceCall*>(event);
Zack Rusinead6aad2011-04-15 22:16:18 -0400148 Q_ASSERT(call->parentFrame());
149 return createIndex(call->parentFrame()->number,
150 0, call->parentFrame());
Zack Rusinf6667d12011-03-30 11:03:37 -0400151 }
Zack Rusin601e8372011-03-24 22:23:21 -0400152 return QModelIndex();
153}
154
155int ApiTraceModel::rowCount(const QModelIndex &parent) const
156{
Zack Rusinf6667d12011-03-30 11:03:37 -0400157 if (!parent.isValid())
158 return m_trace->numFrames();
159
Zack Rusinc1acc7f2011-04-02 01:34:04 -0400160 ApiTraceEvent *event = item(parent);
161 if (!event || event->type() == ApiTraceEvent::Call)
Zack Rusinf6667d12011-03-30 11:03:37 -0400162 return 0;
163
Zack Rusinc1acc7f2011-04-02 01:34:04 -0400164 ApiTraceFrame *frame = static_cast<ApiTraceFrame*>(event);
Zack Rusinf6667d12011-03-30 11:03:37 -0400165 if (frame)
166 return frame->calls.count();
167
168 return 0;
Zack Rusin601e8372011-03-24 22:23:21 -0400169}
170
171int ApiTraceModel::columnCount(const QModelIndex &parent) const
172{
Zack Rusinf6667d12011-03-30 11:03:37 -0400173 return 1;
Zack Rusin601e8372011-03-24 22:23:21 -0400174}
175
Zack Rusin601e8372011-03-24 22:23:21 -0400176bool ApiTraceModel::insertRows(int position, int rows,
177 const QModelIndex &parent)
178{
179 return false;
180}
181
182bool ApiTraceModel::removeRows(int position, int rows,
183 const QModelIndex &parent)
184{
185 bool success = true;
186
187 Q_UNUSED(parent);
188
Zack Rusin601e8372011-03-24 22:23:21 -0400189 beginRemoveRows(parent, position, position + rows - 1);
Zack Rusinf6667d12011-03-30 11:03:37 -0400190 //XXX remove it from ApiTrace
Zack Rusin601e8372011-03-24 22:23:21 -0400191 endRemoveRows();
192
193 return success;
194}
195
Zack Rusinf6667d12011-03-30 11:03:37 -0400196void ApiTraceModel::setApiTrace(ApiTrace *trace)
Zack Rusin601e8372011-03-24 22:23:21 -0400197{
Zack Rusinf6667d12011-03-30 11:03:37 -0400198 if (m_trace == trace)
199 return;
200 if (m_trace)
201 disconnect(m_trace);
202 m_trace = trace;
Zack Rusinca164112011-04-11 02:23:09 -0400203 connect(m_trace, SIGNAL(invalidated()),
204 this, SLOT(invalidateFrames()));
Zack Rusinf6667d12011-03-30 11:03:37 -0400205 connect(m_trace, SIGNAL(framesInvalidated()),
206 this, SLOT(invalidateFrames()));
Zack Rusinb56e03d2011-04-20 23:58:52 -0400207 connect(m_trace, SIGNAL(beginAddingFrames(int, int)),
208 this, SLOT(beginAddingFrames(int, int)));
209 connect(m_trace, SIGNAL(endAddingFrames()),
210 this, SLOT(endAddingFrames()));
Zack Rusin0ddd2502011-04-17 02:34:45 -0400211 connect(m_trace, SIGNAL(changed(ApiTraceCall*)),
212 this, SLOT(callChanged(ApiTraceCall*)));
Zack Rusin601e8372011-03-24 22:23:21 -0400213}
214
Zack Rusinf6667d12011-03-30 11:03:37 -0400215const ApiTrace * ApiTraceModel::apiTrace() const
Zack Rusin601e8372011-03-24 22:23:21 -0400216{
Zack Rusinf6667d12011-03-30 11:03:37 -0400217 return m_trace;
218}
Zack Rusin601e8372011-03-24 22:23:21 -0400219
Zack Rusinf6667d12011-03-30 11:03:37 -0400220void ApiTraceModel::invalidateFrames()
221{
222 beginResetModel();
223 endResetModel();
224}
Zack Rusin91065372011-03-26 01:54:10 -0400225
Zack Rusinb56e03d2011-04-20 23:58:52 -0400226void ApiTraceModel::beginAddingFrames(int oldCount, int numAdded)
Zack Rusinf6667d12011-03-30 11:03:37 -0400227{
228 beginInsertRows(QModelIndex(), oldCount,
Zack Rusinc1acc7f2011-04-02 01:34:04 -0400229 oldCount + numAdded - 1);
Zack Rusinf6667d12011-03-30 11:03:37 -0400230}
Zack Rusin601e8372011-03-24 22:23:21 -0400231
Zack Rusinf6667d12011-03-30 11:03:37 -0400232ApiTraceEvent * ApiTraceModel::item(const QModelIndex &index) const
233{
234 if (!index.isValid())
235 return 0;
236 return static_cast<ApiTraceEvent*>(index.internalPointer());
Zack Rusin601e8372011-03-24 22:23:21 -0400237}
238
Zack Rusinc1acc7f2011-04-02 01:34:04 -0400239void ApiTraceModel::stateSetOnEvent(ApiTraceEvent *event)
240{
241 if (!event)
242 return;
243
244 if (event->type() == ApiTraceEvent::Call) {
245 ApiTraceCall *call = static_cast<ApiTraceCall*>(event);
Zack Rusinead6aad2011-04-15 22:16:18 -0400246 ApiTraceFrame *frame = call->parentFrame();
Zack Rusinc1acc7f2011-04-02 01:34:04 -0400247 int row = frame->calls.indexOf(call);
248 QModelIndex index = createIndex(row, 0, call);
249 emit dataChanged(index, index);
250 } else if (event->type() == ApiTraceEvent::Frame) {
251 ApiTraceFrame *frame = static_cast<ApiTraceFrame*>(event);
252 const QList<ApiTraceFrame*> frames = m_trace->frames();
253 int row = frames.indexOf(frame);
254 QModelIndex index = createIndex(row, 0, frame);
255 emit dataChanged(index, index);
256 }
257}
258
Zack Rusinc52d18a2011-04-11 00:15:07 -0400259QModelIndex ApiTraceModel::callIndex(int callNum) const
260{
Zack Rusinf04cf8a2011-04-12 23:21:52 -0400261 ApiTraceCall *call = m_trace->callWithIndex(callNum);
Zack Rusinf54c4fc2011-04-12 23:39:13 -0400262 return indexForCall(call);
263}
Zack Rusinc52d18a2011-04-11 00:15:07 -0400264
Zack Rusinf54c4fc2011-04-12 23:39:13 -0400265QModelIndex ApiTraceModel::indexForCall(ApiTraceCall *call) const
266{
Zack Rusinc52d18a2011-04-11 00:15:07 -0400267 if (!call) {
268 return QModelIndex();
269 }
270
Zack Rusinead6aad2011-04-15 22:16:18 -0400271 ApiTraceFrame *frame = call->parentFrame();
Zack Rusinc52d18a2011-04-11 00:15:07 -0400272 Q_ASSERT(frame);
273
274 int row = frame->calls.indexOf(call);
275 if (row < 0) {
Zack Rusinead6aad2011-04-15 22:16:18 -0400276 qDebug() << "Couldn't find call num "<<call->index()<<" inside parent!";
Zack Rusinc52d18a2011-04-11 00:15:07 -0400277 return QModelIndex();
278 }
279 return createIndex(row, 0, call);
280}
281
Zack Rusin0ddd2502011-04-17 02:34:45 -0400282void ApiTraceModel::callChanged(ApiTraceCall *call)
283{
Zack Rusin63efea82011-04-17 17:10:45 -0400284 ApiTrace *trace = call->parentFrame()->parentTrace();
Zack Rusin9af5bff2011-04-18 01:05:50 -0400285
Zack Rusincc0b4912011-04-19 01:59:20 -0400286#if 0
Zack Rusin9af5bff2011-04-18 01:05:50 -0400287 qDebug()<<"Call changed = "<<call->edited();
Zack Rusin63efea82011-04-17 17:10:45 -0400288 qDebug()<<"\ttrace edited = "<<trace->edited();
289 qDebug()<<"\ttrace file = "<<trace->fileName();
290 qDebug()<<"\ttrace needs saving = "<<trace->needsSaving();
Zack Rusin9af5bff2011-04-18 01:05:50 -0400291#endif
292
Zack Rusinb53b1612011-04-19 01:33:58 -0400293 Q_ASSERT(trace);
294 if (trace->needsSaving())
295 trace->save();
296
Zack Rusin9af5bff2011-04-18 01:05:50 -0400297 ApiTraceFrame *frame = call->parentFrame();
298 int row = frame->calls.indexOf(call);
299 QModelIndex index = createIndex(row, 0, call);
300 emit dataChanged(index, index);
Zack Rusin0ddd2502011-04-17 02:34:45 -0400301}
302
Zack Rusinb56e03d2011-04-20 23:58:52 -0400303void ApiTraceModel::endAddingFrames()
304{
305 endInsertRows();
306}
307
Zack Rusin601e8372011-03-24 22:23:21 -0400308#include "apitracemodel.moc"