]> git.cworth.org Git - apitrace/blob - gui/apitracemodel.cpp
The trace now knows whether is has been edited.
[apitrace] / gui / apitracemodel.cpp
1 #include "apitracemodel.h"
2
3 #include "apitracecall.h"
4 #include "loaderthread.h"
5 #include "trace_parser.hpp"
6
7 #include <QDebug>
8 #include <QImage>
9 #include <QVariant>
10
11
12 ApiTraceModel::ApiTraceModel(QObject *parent)
13     : QAbstractItemModel(parent),
14       m_trace(0)
15 {
16 }
17
18 ApiTraceModel::~ApiTraceModel()
19 {
20     m_trace = 0;
21 }
22
23 QVariant ApiTraceModel::data(const QModelIndex &index, int role) const
24 {
25     if (!index.isValid())
26         return QVariant();
27
28     if (index.column() != 0)
29         return QVariant();
30
31     ApiTraceEvent *itm = item(index);
32     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();
41     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())
46                 return QString::fromLatin1("%1)&nbsp;<b>%2</b>")
47                     .arg(call->index())
48                     .arg(call->name());
49             else
50                 return QString::fromLatin1("%1)&nbsp;<b>%2</b><br/>%3")
51                     .arg(call->index())
52                     .arg(call->name())
53                     .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     }
65     case ApiTraceModel::EventRole:
66         return QVariant::fromValue(itm);
67     }
68
69     return QVariant();
70 }
71
72 Qt::ItemFlags ApiTraceModel::flags(const QModelIndex &index) const
73 {
74     if (!index.isValid())
75         return 0;
76
77     return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
78 }
79
80 QVariant 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:
86             return tr("Events");
87         case 1:
88             return tr("Flags");
89         default:
90             //fall through
91             break;
92         }
93     }
94
95     return QVariant();
96 }
97
98 QModelIndex ApiTraceModel::index(int row, int column,
99                                  const QModelIndex &parent) const
100 {
101     if (parent.isValid() && parent.column() != 0)
102         return QModelIndex();
103
104     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();
108             return QModelIndex();
109         }
110         ApiTraceFrame *frame = static_cast<ApiTraceFrame*>(event);
111         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();
124 }
125
126 bool ApiTraceModel::hasChildren(const QModelIndex &parent) const
127 {
128     if (parent.isValid()) {
129         ApiTraceEvent *event = item(parent);
130         if (event && event->type() == ApiTraceEvent::Frame) {
131             ApiTraceFrame *frame = static_cast<ApiTraceFrame*>(event);
132             return !frame->calls.isEmpty();
133         } else
134             return false;
135     } else {
136         return (rowCount() > 0);
137     }
138 }
139
140 QModelIndex ApiTraceModel::parent(const QModelIndex &index) const
141 {
142     if (!index.isValid())
143         return QModelIndex();
144
145     ApiTraceEvent *event = item(index);
146     if (event && event->type() == ApiTraceEvent::Call) {
147         ApiTraceCall *call = static_cast<ApiTraceCall*>(event);
148         Q_ASSERT(call->parentFrame());
149         return createIndex(call->parentFrame()->number,
150                            0, call->parentFrame());
151     }
152     return QModelIndex();
153 }
154
155 int ApiTraceModel::rowCount(const QModelIndex &parent) const
156 {
157     if (!parent.isValid())
158         return m_trace->numFrames();
159
160     ApiTraceEvent *event = item(parent);
161     if (!event || event->type() == ApiTraceEvent::Call)
162         return 0;
163
164     ApiTraceFrame *frame = static_cast<ApiTraceFrame*>(event);
165     if (frame)
166         return frame->calls.count();
167
168     return 0;
169 }
170
171 int ApiTraceModel::columnCount(const QModelIndex &parent) const
172 {
173     return 1;
174 }
175
176 bool ApiTraceModel::insertRows(int position, int rows,
177                                const QModelIndex &parent)
178 {
179     return false;
180 }
181
182 bool ApiTraceModel::removeRows(int position, int rows,
183                                const QModelIndex &parent)
184 {
185     bool success = true;
186
187     Q_UNUSED(parent);
188
189     beginRemoveRows(parent, position, position + rows - 1);
190     //XXX remove it from ApiTrace
191     endRemoveRows();
192
193     return success;
194 }
195
196 void ApiTraceModel::setApiTrace(ApiTrace *trace)
197 {
198     if (m_trace == trace)
199         return;
200     if (m_trace)
201         disconnect(m_trace);
202     m_trace = trace;
203     connect(m_trace, SIGNAL(invalidated()),
204             this, SLOT(invalidateFrames()));
205     connect(m_trace, SIGNAL(framesInvalidated()),
206             this, SLOT(invalidateFrames()));
207     connect(m_trace, SIGNAL(framesAdded(int, int)),
208             this, SLOT(appendFrames(int, int)));
209     connect(m_trace, SIGNAL(changed(ApiTraceCall*)),
210             this, SLOT(callChanged(ApiTraceCall*)));
211 }
212
213 const ApiTrace * ApiTraceModel::apiTrace() const
214 {
215     return m_trace;
216 }
217
218 void ApiTraceModel::invalidateFrames()
219 {
220     beginResetModel();
221     endResetModel();
222 }
223
224 void ApiTraceModel::appendFrames(int oldCount, int numAdded)
225 {
226     beginInsertRows(QModelIndex(), oldCount,
227                     oldCount + numAdded - 1);
228     endInsertRows();
229 }
230
231 ApiTraceEvent * ApiTraceModel::item(const QModelIndex &index) const
232 {
233     if (!index.isValid())
234         return 0;
235     return static_cast<ApiTraceEvent*>(index.internalPointer());
236 }
237
238 void ApiTraceModel::stateSetOnEvent(ApiTraceEvent *event)
239 {
240     if (!event)
241         return;
242
243     if (event->type() == ApiTraceEvent::Call) {
244         ApiTraceCall *call = static_cast<ApiTraceCall*>(event);
245         ApiTraceFrame *frame = call->parentFrame();
246         int row = frame->calls.indexOf(call);
247         QModelIndex index = createIndex(row, 0, call);
248         emit dataChanged(index, index);
249     } else if (event->type() == ApiTraceEvent::Frame) {
250         ApiTraceFrame *frame = static_cast<ApiTraceFrame*>(event);
251         const QList<ApiTraceFrame*> frames = m_trace->frames();
252         int row = frames.indexOf(frame);
253         QModelIndex index = createIndex(row, 0, frame);
254         emit dataChanged(index, index);
255     }
256 }
257
258 QModelIndex ApiTraceModel::callIndex(int callNum) const
259 {
260     ApiTraceCall *call = m_trace->callWithIndex(callNum);
261     return indexForCall(call);
262 }
263
264 QModelIndex ApiTraceModel::indexForCall(ApiTraceCall *call) const
265 {
266     if (!call) {
267         return QModelIndex();
268     }
269
270     ApiTraceFrame *frame = call->parentFrame();
271     Q_ASSERT(frame);
272
273     int row = frame->calls.indexOf(call);
274     if (row < 0) {
275         qDebug() << "Couldn't find call num "<<call->index()<<" inside parent!";
276         return QModelIndex();
277     }
278     return createIndex(row, 0, call);
279 }
280
281 void ApiTraceModel::callChanged(ApiTraceCall *call)
282 {
283     qDebug()<<"Call changed = "<<call->edited();
284     qDebug()<<"\ttrace edited = "<<call->parentFrame()->parentTrace()->edited();
285 }
286
287 #include "apitracemodel.moc"