]> git.cworth.org Git - apitrace/blob - gui/apitracemodel.cpp
Tooltips in the event list
[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("<b>%1</b>").arg(call->name);
47             else
48                 return QString::fromLatin1("<b>%1</b><br/>%2")
49                     .arg(call->name)
50                     .arg(stateText);
51         } else {
52             ApiTraceFrame *frame = static_cast<ApiTraceFrame*>(itm);
53             QString text = frame->staticText().text();
54             if (frame->state().isEmpty())
55                 return QString::fromLatin1("<b>%1</b>").arg(text);
56             else
57                 return QString::fromLatin1("<b>%1</b><br/>%2")
58                     .arg(text)
59                     .arg(stateText);
60         }
61     }
62     case ApiTraceModel::EventRole:
63         return QVariant::fromValue(itm);
64     }
65
66     return QVariant();
67 }
68
69 Qt::ItemFlags ApiTraceModel::flags(const QModelIndex &index) const
70 {
71     if (!index.isValid())
72         return 0;
73
74     return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
75 }
76
77 QVariant ApiTraceModel::headerData(int section, Qt::Orientation orientation,
78                                    int role ) const
79 {
80     if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
81         switch (section) {
82         case 0:
83             return tr("Events");
84         case 1:
85             return tr("Flags");
86         default:
87             //fall through
88             break;
89         }
90     }
91
92     return QVariant();
93 }
94
95 QModelIndex ApiTraceModel::index(int row, int column,
96                                  const QModelIndex &parent) const
97 {
98     if (parent.isValid() && parent.column() != 0)
99         return QModelIndex();
100
101     ApiTraceEvent *event = item(parent);
102     if (event) {
103         if (event->type() != ApiTraceEvent::Frame) {
104             qDebug()<<"got a valid parent but it's not a frame "<<event->type();
105             return QModelIndex();
106         }
107         ApiTraceFrame *frame = static_cast<ApiTraceFrame*>(event);
108         ApiTraceCall *call = frame->calls.value(row);
109         if (call)
110             return createIndex(row, column, call);
111         else
112             return QModelIndex();
113     } else {
114         ApiTraceFrame *frame = m_trace->frameAt(row);
115         if (frame)
116             return createIndex(row, column, frame);
117         else
118             return QModelIndex();
119     }
120     return QModelIndex();
121 }
122
123 bool ApiTraceModel::hasChildren(const QModelIndex &parent) const
124 {
125     if (parent.isValid()) {
126         ApiTraceEvent *event = item(parent);
127         if (event && event->type() == ApiTraceEvent::Frame) {
128             ApiTraceFrame *frame = static_cast<ApiTraceFrame*>(event);
129             return !frame->calls.isEmpty();
130         } else
131             return false;
132     } else {
133         return (rowCount() > 0);
134     }
135 }
136
137 QModelIndex ApiTraceModel::parent(const QModelIndex &index) const
138 {
139     if (!index.isValid())
140         return QModelIndex();
141
142     ApiTraceEvent *event = item(index);
143     if (event && event->type() == ApiTraceEvent::Call) {
144         ApiTraceCall *call = static_cast<ApiTraceCall*>(event);
145         Q_ASSERT(call->parentFrame);
146         return createIndex(call->parentFrame->number,
147                            0, call->parentFrame);
148     }
149     return QModelIndex();
150 }
151
152 int ApiTraceModel::rowCount(const QModelIndex &parent) const
153 {
154     if (!parent.isValid())
155         return m_trace->numFrames();
156
157     ApiTraceEvent *event = item(parent);
158     if (!event || event->type() == ApiTraceEvent::Call)
159         return 0;
160
161     ApiTraceFrame *frame = static_cast<ApiTraceFrame*>(event);
162     if (frame)
163         return frame->calls.count();
164
165     return 0;
166 }
167
168 int ApiTraceModel::columnCount(const QModelIndex &parent) const
169 {
170     return 1;
171 }
172
173 bool ApiTraceModel::insertRows(int position, int rows,
174                                const QModelIndex &parent)
175 {
176     return false;
177 }
178
179 bool ApiTraceModel::removeRows(int position, int rows,
180                                const QModelIndex &parent)
181 {
182     bool success = true;
183
184     Q_UNUSED(parent);
185
186     beginRemoveRows(parent, position, position + rows - 1);
187     //XXX remove it from ApiTrace
188     endRemoveRows();
189
190     return success;
191 }
192
193 void ApiTraceModel::setApiTrace(ApiTrace *trace)
194 {
195     if (m_trace == trace)
196         return;
197     if (m_trace)
198         disconnect(m_trace);
199     m_trace = trace;
200     connect(m_trace, SIGNAL(framesInvalidated()),
201             this, SLOT(invalidateFrames()));
202     connect(m_trace, SIGNAL(framesAdded(int, int)),
203             this, SLOT(appendFrames(int, int)));
204 }
205
206 const ApiTrace * ApiTraceModel::apiTrace() const
207 {
208     return m_trace;
209 }
210
211 void ApiTraceModel::invalidateFrames()
212 {
213     beginResetModel();
214     endResetModel();
215 }
216
217 void ApiTraceModel::appendFrames(int oldCount, int numAdded)
218 {
219     beginInsertRows(QModelIndex(), oldCount,
220                     oldCount + numAdded - 1);
221     endInsertRows();
222 }
223
224 ApiTraceEvent * ApiTraceModel::item(const QModelIndex &index) const
225 {
226     if (!index.isValid())
227         return 0;
228     return static_cast<ApiTraceEvent*>(index.internalPointer());
229 }
230
231 void ApiTraceModel::stateSetOnEvent(ApiTraceEvent *event)
232 {
233     if (!event)
234         return;
235
236     if (event->type() == ApiTraceEvent::Call) {
237         ApiTraceCall *call = static_cast<ApiTraceCall*>(event);
238         ApiTraceFrame *frame = call->parentFrame;
239         int row = frame->calls.indexOf(call);
240         QModelIndex index = createIndex(row, 0, call);
241         emit dataChanged(index, index);
242     } else if (event->type() == ApiTraceEvent::Frame) {
243         ApiTraceFrame *frame = static_cast<ApiTraceFrame*>(event);
244         const QList<ApiTraceFrame*> frames = m_trace->frames();
245         int row = frames.indexOf(frame);
246         QModelIndex index = createIndex(row, 0, frame);
247         emit dataChanged(index, index);
248     }
249 }
250
251 #include "apitracemodel.moc"