]> git.cworth.org Git - apitrace/blob - gui/apitracemodel.cpp
Add a basic gui for apitrace.
[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 <QVariant>
8
9 class VariantVisitor : public Trace::Visitor
10 {
11 public:
12     virtual void visit(Trace::Null *)
13     {
14         // Nothing
15     }
16     virtual void visit(Trace::Bool *node)
17     {
18         m_variant = QVariant(node->value);
19     }
20     virtual void visit(Trace::SInt *node)
21     {
22         m_variant = QVariant(node->value);
23     }
24     virtual void visit(Trace::UInt *node)
25     {
26         m_variant = QVariant(node->value);
27     }
28     virtual void visit(Trace::Float *node)
29     {
30         m_variant = QVariant(node->value);
31     }
32     virtual void visit(Trace::String *node)
33     {
34         m_variant = QVariant(QString::fromStdString(node->value));
35     }
36     virtual void visit(Trace::Enum *e)
37     {
38         m_variant = QVariant(QString::fromStdString(e->sig->first));
39     }
40     virtual void visit(Trace::Bitmask *bitmask)
41     {
42         //XXX we should probably convert it to QImage
43         visit(static_cast<Trace::UInt *>(bitmask));
44     }
45     virtual void visit(Trace::Struct *str)
46     {
47         //XXX: need a custom QVariant type for this one
48         QVariantList lst;
49         for (int i = 0; i < str->members.size(); ++i) {
50             VariantVisitor vst;
51             str->members[i]->visit(vst);
52             lst.append(vst.variant());
53         }
54         m_variant = QVariant(lst);
55     }
56     virtual void visit(Trace::Array *array)
57     {
58         QVariantList lst;
59         for (int i = 0; i < array->values.size(); ++i) {
60             VariantVisitor vst;
61             array->values[i]->visit(vst);
62             lst.append(vst.variant());
63         }
64         m_variant = QVariant(lst);
65     }
66     virtual void visit(Trace::Blob *blob)
67     {
68         QByteArray barray = QByteArray::fromRawData(blob->buf, blob->size);
69         m_variant = QVariant(barray);
70     }
71     virtual void visit(Trace::Pointer *ptr)
72     {
73         m_variant = QVariant(ptr->value);
74     }
75
76     QVariant variant() const
77     {
78         return m_variant;
79     }
80 private:
81     QVariant m_variant;
82 };
83
84 ApiTraceModel::ApiTraceModel(QObject *parent)
85     : QAbstractItemModel(parent)
86 {
87     m_loader = new LoaderThread();
88     connect(m_loader, SIGNAL(parsedCalls(const QList<Trace::Call*>&)),
89             SLOT(appendCalls(const QList<Trace::Call*>&)));
90 }
91
92 ApiTraceModel::~ApiTraceModel()
93 {
94     qDeleteAll(m_calls);
95     delete m_loader;
96 }
97
98 QVariant ApiTraceModel::data(const QModelIndex &index, int role) const
99 {
100     if (!index.isValid())
101         return QVariant();
102
103     if (role != Qt::DisplayRole)
104         return QVariant();
105
106     ApiTraceCall *item = m_calls.value(index.row());
107
108     if (!item)
109         return QVariant();
110
111     switch (index.column()) {
112     case 0:
113         return item->name;
114     case 1: {
115         QString str;
116         for (int i = 0; i < item->argNames.count(); ++i) {
117             str += item->argNames[i];
118             str += QString::fromLatin1(" = ");
119             str += item->argValues[i].toString();
120             if (i < item->argNames.count() - 1)
121                 str += QString::fromLatin1(", ");
122         }
123         return str;
124     }
125     case 2:
126         return item->returnValue.toString();
127     default:
128         return QVariant();
129     }
130 }
131
132 Qt::ItemFlags ApiTraceModel::flags(const QModelIndex &index) const
133 {
134     if (!index.isValid())
135         return 0;
136
137     return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
138 }
139
140 QVariant ApiTraceModel::headerData(int section, Qt::Orientation orientation,
141                                    int role ) const
142 {
143     if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
144         switch (section) {
145         case 0:
146             return tr("Function");
147         case 1:
148             return tr("Arguments");
149         case 2:
150             return tr("Return");
151         default:
152             //fall through
153             break;
154         }
155     }
156
157     return QVariant();
158 }
159
160 QModelIndex ApiTraceModel::index(int row, int column,
161                                  const QModelIndex &parent) const
162 {
163     if (parent.isValid() && parent.column() != 0)
164         return QModelIndex();
165
166     ApiTraceCall *call = m_calls.value(row);
167
168     if (call)
169         return createIndex(row, column, call);
170     else
171         return QModelIndex();
172 }
173
174 bool ApiTraceModel::hasChildren(const QModelIndex &parent) const
175 {
176     return parent.isValid() ? false : (rowCount() > 0);
177 }
178
179 QModelIndex ApiTraceModel::parent(const QModelIndex &index) const
180 {
181     if (!index.isValid())
182         return QModelIndex();
183
184     //list for now
185     return QModelIndex();
186 }
187
188 int ApiTraceModel::rowCount(const QModelIndex &parent) const
189 {
190     return m_calls.count();
191 }
192
193 int ApiTraceModel::columnCount(const QModelIndex &parent) const
194 {
195     return parent.isValid() ? 0 : 3;
196 }
197
198
199 bool ApiTraceModel::insertRows(int position, int rows,
200                                const QModelIndex &parent)
201 {
202     return false;
203 }
204
205 bool ApiTraceModel::removeRows(int position, int rows,
206                                const QModelIndex &parent)
207 {
208     bool success = true;
209
210     Q_UNUSED(parent);
211
212     if (m_calls.count() <= position)
213         return false;
214
215     beginRemoveRows(parent, position, position + rows - 1);
216     for (int i = 0; i < rows; ++i) {
217         ApiTraceCall *call = m_calls.value(i);
218         m_calls.removeAt(i);
219         delete call;
220     }
221     endRemoveRows();
222
223     return success;
224 }
225
226 void ApiTraceModel::loadTraceFile(const QString &fileName)
227 {
228     if (m_loader->isRunning()) {
229         m_loader->terminate();
230         m_loader->wait();
231     }
232     removeRows(0, m_calls.count(), QModelIndex());
233
234     m_loader->loadFile(fileName);
235 }
236
237 void ApiTraceModel::appendCalls(const QList<Trace::Call*> traceCalls)
238 {
239     beginInsertRows(QModelIndex(), m_calls.count(),
240                     m_calls.count() + traceCalls.count());
241     foreach(Trace::Call *call, traceCalls) {
242         ApiTraceCall *apiCall = new ApiTraceCall;
243         apiCall->name = QString::fromStdString(call->sig->name);
244
245         QString argumentsText;
246         for (int i = 0; i < call->sig->arg_names.size(); ++i) {
247             apiCall->argNames +=
248                 QString::fromStdString(call->sig->arg_names[i]);
249         }
250         VariantVisitor retVisitor;
251         if (call->ret) {
252             call->ret->visit(retVisitor);
253             apiCall->returnValue = retVisitor.variant();
254         }
255         for (int i = 0; i < call->args.size(); ++i) {
256             VariantVisitor argVisitor;
257             call->args[i]->visit(argVisitor);
258             apiCall->argValues += argVisitor.variant();
259         }
260         m_calls.append(apiCall);
261     }
262     endInsertRows();
263
264     qDeleteAll(traceCalls);
265 }
266
267 #include "apitracemodel.moc"