blob: b7694f46f79f5753d1c19d34f287093238e37341 [file] [log] [blame]
Zack Rusin91065372011-03-26 01:54:10 -04001#include "apitracecall.h"
2
Zack Rusin661842d2011-04-17 01:59:16 -04003#include "apitrace.h"
Zack Rusin91065372011-03-26 01:54:10 -04004#include "trace_model.hpp"
5
6#include <QDebug>
Zack Rusin9e292fc2011-04-26 23:03:42 -04007#include <QLocale>
Zack Rusin35451522011-04-02 23:44:53 -04008#include <QObject>
Zack Rusin5e277b02011-04-16 21:52:26 -04009#define QT_USE_FAST_OPERATOR_PLUS
10#include <QStringBuilder>
José Fonsecae8a1aa92011-04-21 09:13:23 +010011#include <QTextDocument>
Zack Rusin91065372011-03-26 01:54:10 -040012
Zack Rusinb53b1612011-04-19 01:33:58 -040013const char * const styleSheet =
14 ".call {\n"
15 " font-weight:bold;\n"
16 // text shadow looks great but doesn't work well in qtwebkit 4.7
17 " /*text-shadow: 0px 2px 3px #555;*/\n"
18 " font-size: 1.2em;\n"
19 "}\n"
20 ".arg-name {\n"
21 " border: 1px solid rgb(238,206,0);\n"
22 " border-radius: 4px;\n"
23 " background: yellow;\n"
24 " padding: 2px;\n"
25 " box-shadow: 0px 1px 3px dimgrey;\n"
26 " -webkit-transition: background 1s linear;\n"
27 "}\n"
28 ".arg-name:hover {\n"
29 " background: white;\n"
30 "}\n"
31 ".arg-value {\n"
32 " color: #0000ff;\n"
33 "}\n"
34 ".error {\n"
Zack Rusincc0b4912011-04-19 01:59:20 -040035 " border: 1px solid rgb(255,0,0);\n"
Zack Rusinb53b1612011-04-19 01:33:58 -040036 " margin: 10px;\n"
Zack Rusincc0b4912011-04-19 01:59:20 -040037 " padding: 1;\n"
38 " border-radius: 4px;\n"
39 // also looks great but qtwebkit doesn't support it
40 //" background: #6fb2e5;\n"
41 //" box-shadow: 0 1px 5px #0061aa, inset 0 10px 20px #b6f9ff;\n"
42 //" -o-box-shadow: 0 1px 5px #0061aa, inset 0 10px 20px #b6f9ff;\n"
43 //" -webkit-box-shadow: 0 1px 5px #0061aa, inset 0 10px 20px #b6f9ff;\n"
44 //" -moz-box-shadow: 0 1px 5px #0061aa, inset 0 10px 20px #b6f9ff;\n"
Zack Rusinb53b1612011-04-19 01:33:58 -040045 "}\n";
46
Zack Rusinc6247dd2011-04-17 22:56:58 -040047ApiPointer::ApiPointer(unsigned long long val)
Zack Rusin91065372011-03-26 01:54:10 -040048 : m_value(val)
49{
50}
51
52QString ApiPointer::toString() const
53{
54 if (m_value)
55 return QString("0x%1").arg(m_value, 0, 16);
56 else
57 return QLatin1String("NULL");
58}
59
José Fonsecae8a1aa92011-04-21 09:13:23 +010060// Qt::convertFromPlainText doesn't do precisely what we want
61static QString
62plainTextToHTML(const QString & plain, bool multiLine)
63{
64 int col = 0;
65 bool quote = false;
66 QString rich;
67 for (int i = 0; i < plain.length(); ++i) {
68 if (plain[i] == QLatin1Char('\n')){
69 if (multiLine) {
70 rich += QLatin1String("<br>\n");
71 } else {
72 rich += QLatin1String("\\n");
73 }
74 col = 0;
75 quote = true;
76 } else {
77 if (plain[i] == QLatin1Char('\t')){
78 if (multiLine) {
79 rich += QChar(0x00a0U);
80 ++col;
81 while (col % 8) {
82 rich += QChar(0x00a0U);
83 ++col;
84 }
85 } else {
86 rich += QLatin1String("\\t");
87 }
88 quote = true;
89 } else if (plain[i].isSpace()) {
90 rich += QChar(0x00a0U);
91 quote = true;
92 } else if (plain[i] == QLatin1Char('<')) {
93 rich += QLatin1String("&lt;");
94 } else if (plain[i] == QLatin1Char('>')) {
95 rich += QLatin1String("&gt;");
96 } else if (plain[i] == QLatin1Char('&')) {
97 rich += QLatin1String("&amp;");
98 } else {
99 rich += plain[i];
100 }
101 ++col;
102 }
103 }
104
105 if (quote) {
106 return QLatin1Literal("\"") + rich + QLatin1Literal("\"");
107 }
108
109 return rich;
110}
111
112QString apiVariantToString(const QVariant &variant, bool multiLine)
Zack Rusin91065372011-03-26 01:54:10 -0400113{
114 if (variant.userType() == QVariant::Double) {
115 return QString::number(variant.toFloat());
116 }
Zack Rusin35451522011-04-02 23:44:53 -0400117 if (variant.userType() == QVariant::ByteArray) {
Zack Rusin8e7a4ff2011-04-07 01:15:48 -0400118 if (variant.toByteArray().size() < 1024) {
119 int bytes = variant.toByteArray().size();
120 return QObject::tr("[binary data, size = %1 bytes]").arg(bytes);
121 } else {
122 float kb = variant.toByteArray().size()/1024.;
123 return QObject::tr("[binary data, size = %1 kb]").arg(kb);
124 }
Zack Rusin35451522011-04-02 23:44:53 -0400125 }
Zack Rusin91065372011-03-26 01:54:10 -0400126
José Fonsecae8a1aa92011-04-21 09:13:23 +0100127 if (variant.userType() == QVariant::String) {
128 return plainTextToHTML(variant.toString(), multiLine);
129 }
130
Zack Rusin91065372011-03-26 01:54:10 -0400131 if (variant.userType() < QVariant::UserType) {
132 return variant.toString();
133 }
134
135 if (variant.canConvert<ApiPointer>()) {
136 return variant.value<ApiPointer>().toString();
137 }
138 if (variant.canConvert<ApiBitmask>()) {
139 return variant.value<ApiBitmask>().toString();
140 }
141 if (variant.canConvert<ApiStruct>()) {
142 return variant.value<ApiStruct>().toString();
143 }
144 if (variant.canConvert<ApiArray>()) {
145 return variant.value<ApiArray>().toString();
146 }
Zack Rusind54055e2011-04-17 18:27:28 -0400147 if (variant.canConvert<ApiEnum>()) {
148 return variant.value<ApiEnum>().toString();
149 }
Zack Rusin91065372011-03-26 01:54:10 -0400150
151 return QString();
152}
153
154ApiBitmask::ApiBitmask(const Trace::Bitmask *bitmask)
155 : m_value(0)
156{
157 init(bitmask);
158}
159
160
161void ApiBitmask::init(const Trace::Bitmask *bitmask)
162{
163 if (!bitmask)
164 return;
165
166 m_value = bitmask->value;
167 for (Trace::Bitmask::Signature::const_iterator it = bitmask->sig->begin();
168 it != bitmask->sig->end(); ++it) {
José Fonseca31b183a2011-05-28 12:21:15 +0100169 assert(it->value);
Zack Rusin91065372011-03-26 01:54:10 -0400170 QPair<QString, unsigned long long> pair;
171
José Fonseca31b183a2011-05-28 12:21:15 +0100172 pair.first = QString::fromStdString(it->name);
173 pair.second = it->value;
Zack Rusin91065372011-03-26 01:54:10 -0400174
175 m_sig.append(pair);
176 }
177}
178
179QString ApiBitmask::toString() const
180{
181 QString str;
182 unsigned long long value = m_value;
183 bool first = true;
184 for (Signature::const_iterator it = m_sig.begin();
185 value != 0 && it != m_sig.end(); ++it) {
186 Q_ASSERT(it->second);
187 if ((value & it->second) == it->second) {
188 if (!first) {
189 str += QLatin1String(" | ");
190 }
191 str += it->first;
192 value &= ~it->second;
193 first = false;
194 }
195 }
196 if (value || first) {
197 if (!first) {
198 str += QLatin1String(" | ");
199 }
200 str += QString::fromLatin1("0x%1").arg(value, 0, 16);
201 }
202 return str;
203}
204
205ApiStruct::ApiStruct(const Trace::Struct *s)
206{
207 init(s);
208}
209
210QString ApiStruct::toString() const
211{
212 QString str;
213
214 str += QLatin1String("{");
215 for (unsigned i = 0; i < m_members.count(); ++i) {
Zack Rusin5e277b02011-04-16 21:52:26 -0400216 str += m_sig.memberNames[i] %
217 QLatin1Literal(" = ") %
218 apiVariantToString(m_members[i]);
Zack Rusin91065372011-03-26 01:54:10 -0400219 if (i < m_members.count() - 1)
220 str += QLatin1String(", ");
221 }
222 str += QLatin1String("}");
223
224 return str;
225}
226
227void ApiStruct::init(const Trace::Struct *s)
228{
229 if (!s)
230 return;
231
232 m_sig.name = QString::fromStdString(s->sig->name);
233 for (unsigned i = 0; i < s->members.size(); ++i) {
234 VariantVisitor vis;
235 m_sig.memberNames.append(
236 QString::fromStdString(s->sig->member_names[i]));
237 s->members[i]->visit(vis);
238 m_members.append(vis.variant());
239 }
240}
241
242void VariantVisitor::visit(Trace::Null *)
243{
Zack Rusin1d0d2292011-04-18 01:52:13 -0400244 m_variant = QVariant::fromValue(ApiPointer(0));
Zack Rusin91065372011-03-26 01:54:10 -0400245}
246
247void VariantVisitor::visit(Trace::Bool *node)
248{
249 m_variant = QVariant(node->value);
250}
251
252void VariantVisitor::visit(Trace::SInt *node)
253{
254 m_variant = QVariant(node->value);
255}
256
257void VariantVisitor::visit(Trace::UInt *node)
258{
259 m_variant = QVariant(node->value);
260}
261
262void VariantVisitor::visit(Trace::Float *node)
263{
264 m_variant = QVariant(node->value);
265}
266
267void VariantVisitor::visit(Trace::String *node)
268{
269 m_variant = QVariant(QString::fromStdString(node->value));
270}
271
272void VariantVisitor::visit(Trace::Enum *e)
273{
Zack Rusind54055e2011-04-17 18:27:28 -0400274 VariantVisitor vis;
275 e->sig->second->visit(vis);
276
277 QVariant val = vis.variant();
278
279 m_variant = QVariant::fromValue(
280 ApiEnum(QString::fromStdString(e->sig->first), val));
Zack Rusin91065372011-03-26 01:54:10 -0400281}
282
283void VariantVisitor::visit(Trace::Bitmask *bitmask)
284{
285 m_variant = QVariant::fromValue(ApiBitmask(bitmask));
286}
287
288void VariantVisitor::visit(Trace::Struct *str)
289{
290 m_variant = QVariant::fromValue(ApiStruct(str));
291}
292
293void VariantVisitor::visit(Trace::Array *array)
294{
295 m_variant = QVariant::fromValue(ApiArray(array));
296}
297
298void VariantVisitor::visit(Trace::Blob *blob)
299{
Zack Rusin2f8bb0b2011-04-18 00:22:50 -0400300 //XXX
301 //FIXME: this is a nasty hack. Trace::Blob's can't
302 // delete the contents in the destructor because
303 // the data is being used by other calls. We piggy back
304 // on that assumption and don't deep copy the data. If
305 // Blob's will start deleting the data we will need to
306 // start deep copying it or switch to using something like
307 // Boost's shared_ptr or Qt's QSharedPointer to handle it
Zack Rusin91065372011-03-26 01:54:10 -0400308 QByteArray barray = QByteArray::fromRawData(blob->buf, blob->size);
309 m_variant = QVariant(barray);
310}
311
312void VariantVisitor::visit(Trace::Pointer *ptr)
313{
314 m_variant = QVariant::fromValue(ApiPointer(ptr->value));
315}
316
317ApiArray::ApiArray(const Trace::Array *arr)
318{
319 init(arr);
320}
321
Zack Rusinabb3fde2011-04-16 02:16:49 -0400322ApiArray::ApiArray(const QList<QVariant> &vals)
323 : m_array(vals)
324{
325}
326
Zack Rusin91065372011-03-26 01:54:10 -0400327QString ApiArray::toString() const
328{
329 QString str;
330 str += QLatin1String("[");
331 for(int i = 0; i < m_array.count(); ++i) {
332 const QVariant &var = m_array[i];
333 str += apiVariantToString(var);
334 if (i < m_array.count() - 1)
335 str += QLatin1String(", ");
336 }
337 str += QLatin1String("]");
338
339 return str;
340}
341
342void ApiArray::init(const Trace::Array *arr)
343{
344 if (!arr)
345 return;
346
347 for (int i = 0; i < arr->values.size(); ++i) {
348 VariantVisitor vis;
349 arr->values[i]->visit(vis);
350
351 m_array.append(vis.variant());
352 }
353}
Zack Rusin18eade52011-03-26 14:23:35 -0400354
355QStaticText ApiTraceCall::staticText() const
356{
Zack Rusin53484b22011-04-16 11:56:19 -0400357 if (m_staticText && !m_staticText->text().isEmpty())
358 return *m_staticText;
Zack Rusin18eade52011-03-26 14:23:35 -0400359
Zack Rusin9af5bff2011-04-18 01:05:50 -0400360 QVariantList argValues = arguments();
361
Zack Rusin53484b22011-04-16 11:56:19 -0400362 QString richText = QString::fromLatin1(
363 "<span style=\"font-weight:bold\">%1</span>(").arg(m_name);
Zack Rusinead6aad2011-04-15 22:16:18 -0400364 for (int i = 0; i < m_argNames.count(); ++i) {
Zack Rusin27cb2c42011-03-27 23:53:36 -0400365 richText += QLatin1String("<span style=\"color:#0000ff\">");
Zack Rusin9af5bff2011-04-18 01:05:50 -0400366 QString argText = apiVariantToString(argValues[i]);
Zack Rusindd7f2302011-03-31 22:55:57 -0400367
368 //if arguments are really long (e.g. shader text), cut them
369 // and elide it
370 if (argText.length() > 40) {
371 QString shortened = argText.mid(0, 40);
372 shortened[argText.length() - 5] = '.';
373 shortened[argText.length() - 4] = '.';
374 shortened[argText.length() - 3] = '.';
375 shortened[argText.length() - 2] = argText[argText.length() - 2];
376 shortened[argText.length() - 1] = argText[argText.length() - 1];
377 richText += shortened;
378 } else {
379 richText += argText;
380 }
Zack Rusin27cb2c42011-03-27 23:53:36 -0400381 richText += QLatin1String("</span>");
Zack Rusinead6aad2011-04-15 22:16:18 -0400382 if (i < m_argNames.count() - 1)
Zack Rusin5e277b02011-04-16 21:52:26 -0400383 richText += QLatin1String(", ");
Zack Rusin27cb2c42011-03-27 23:53:36 -0400384 }
385 richText += QLatin1String(")");
Zack Rusinead6aad2011-04-15 22:16:18 -0400386 if (m_returnValue.isValid()) {
Zack Rusin5e277b02011-04-16 21:52:26 -0400387 richText +=
388 QLatin1Literal(" = ") %
389 QLatin1Literal("<span style=\"color:#0000ff\">") %
390 apiVariantToString(m_returnValue) %
391 QLatin1Literal("</span>");
José Fonseca908f38d2011-03-31 10:09:14 +0100392 }
Zack Rusin27cb2c42011-03-27 23:53:36 -0400393
Zack Rusin53484b22011-04-16 11:56:19 -0400394 if (!m_staticText)
395 m_staticText = new QStaticText(richText);
Zack Rusin9af5bff2011-04-18 01:05:50 -0400396 else
397 m_staticText->setText(richText);
Zack Rusin27cb2c42011-03-27 23:53:36 -0400398 QTextOption opt;
399 opt.setWrapMode(QTextOption::NoWrap);
Zack Rusin53484b22011-04-16 11:56:19 -0400400 m_staticText->setTextOption(opt);
401 m_staticText->prepare();
Zack Rusin27cb2c42011-03-27 23:53:36 -0400402
Zack Rusin53484b22011-04-16 11:56:19 -0400403 return *m_staticText;
Zack Rusin27cb2c42011-03-27 23:53:36 -0400404}
405
406QString ApiTraceCall::toHtml() const
407{
408 if (!m_richText.isEmpty())
409 return m_richText;
410
Zack Rusinb53b1612011-04-19 01:33:58 -0400411 m_richText = QLatin1String("<div class=\"call\">");
412
Zack Rusinead6aad2011-04-15 22:16:18 -0400413 if (m_helpUrl.isEmpty()) {
Zack Rusinb53b1612011-04-19 01:33:58 -0400414 m_richText += QString::fromLatin1(
415 "%1) <span class=\"callName\">%2</span>(")
416 .arg(m_index)
417 .arg(m_name);
Zack Rusinc97fadc2011-04-07 15:16:59 -0400418 } else {
Zack Rusinb53b1612011-04-19 01:33:58 -0400419 m_richText += QString::fromLatin1(
420 "%1) <span class=\"callName\"><a href=\"%2\">%3</a></span>(")
Zack Rusinead6aad2011-04-15 22:16:18 -0400421 .arg(m_index)
422 .arg(m_helpUrl.toString())
423 .arg(m_name);
Zack Rusinc97fadc2011-04-07 15:16:59 -0400424 }
425
Zack Rusin9af5bff2011-04-18 01:05:50 -0400426 QVariantList argValues = arguments();
Zack Rusinead6aad2011-04-15 22:16:18 -0400427 for (int i = 0; i < m_argNames.count(); ++i) {
Zack Rusinb53b1612011-04-19 01:33:58 -0400428 m_richText +=
429 QLatin1String("<span class=\"arg-name\">") +
430 m_argNames[i] +
431 QLatin1String("</span>") +
432 QLatin1Literal(" = ") +
433 QLatin1Literal("<span class=\"arg-value\">") +
José Fonsecae8a1aa92011-04-21 09:13:23 +0100434 apiVariantToString(argValues[i], true) +
Zack Rusinb53b1612011-04-19 01:33:58 -0400435 QLatin1Literal("</span>");
Zack Rusinead6aad2011-04-15 22:16:18 -0400436 if (i < m_argNames.count() - 1)
Zack Rusin5e277b02011-04-16 21:52:26 -0400437 m_richText += QLatin1String(", ");
Zack Rusin18eade52011-03-26 14:23:35 -0400438 }
439 m_richText += QLatin1String(")");
440
Zack Rusinead6aad2011-04-15 22:16:18 -0400441 if (m_returnValue.isValid()) {
Zack Rusin5e277b02011-04-16 21:52:26 -0400442 m_richText +=
443 QLatin1String(" = ") +
444 QLatin1String("<span style=\"color:#0000ff\">") +
José Fonsecae8a1aa92011-04-21 09:13:23 +0100445 apiVariantToString(m_returnValue, true) +
Zack Rusin5e277b02011-04-16 21:52:26 -0400446 QLatin1String("</span>");
Zack Rusin18eade52011-03-26 14:23:35 -0400447 }
Zack Rusinb53b1612011-04-19 01:33:58 -0400448 m_richText += QLatin1String("</div>");
449
Zack Rusincc0b4912011-04-19 01:59:20 -0400450 if (hasError()) {
451 QString errorStr =
452 QString::fromLatin1(
453 "<div class=\"error\">%1</div>")
454 .arg(m_error);
455 m_richText += errorStr;
456 }
457
Zack Rusinb53b1612011-04-19 01:33:58 -0400458 m_richText =
459 QString::fromLatin1(
460 "<html><head><style type=\"text/css\" media=\"all\">"
461 "%1</style></head><body>%2</body></html>")
462 .arg(styleSheet)
463 .arg(m_richText);
Zack Rusin5e277b02011-04-16 21:52:26 -0400464 m_richText.squeeze();
Zack Rusinb53b1612011-04-19 01:33:58 -0400465
466 //qDebug()<<m_richText;
Zack Rusin18eade52011-03-26 14:23:35 -0400467 return m_richText;
468}
Zack Rusinba3c1bf2011-03-27 17:12:06 -0400469
470QString ApiTraceCall::filterText() const
471{
472 if (!m_filterText.isEmpty())
473 return m_filterText;
474
Zack Rusin9af5bff2011-04-18 01:05:50 -0400475 QVariantList argValues = arguments();
Zack Rusin5e277b02011-04-16 21:52:26 -0400476 m_filterText = m_name + QLatin1Literal("(");
Zack Rusinead6aad2011-04-15 22:16:18 -0400477 for (int i = 0; i < m_argNames.count(); ++i) {
Zack Rusin5e277b02011-04-16 21:52:26 -0400478 m_filterText += m_argNames[i] +
479 QLatin1Literal(" = ") +
Zack Rusin9af5bff2011-04-18 01:05:50 -0400480 apiVariantToString(argValues[i]);
Zack Rusinead6aad2011-04-15 22:16:18 -0400481 if (i < m_argNames.count() - 1)
Zack Rusin5e277b02011-04-16 21:52:26 -0400482 m_filterText += QLatin1String(", ");
Zack Rusinba3c1bf2011-03-27 17:12:06 -0400483 }
484 m_filterText += QLatin1String(")");
485
Zack Rusinead6aad2011-04-15 22:16:18 -0400486 if (m_returnValue.isValid()) {
Zack Rusin5e277b02011-04-16 21:52:26 -0400487 m_filterText += QLatin1Literal(" = ") +
488 apiVariantToString(m_returnValue);
Zack Rusinba3c1bf2011-03-27 17:12:06 -0400489 }
Zack Rusin5e277b02011-04-16 21:52:26 -0400490 m_filterText.squeeze();
Zack Rusinba3c1bf2011-03-27 17:12:06 -0400491 return m_filterText;
492}
Zack Rusinf6667d12011-03-30 11:03:37 -0400493
494QStaticText ApiTraceFrame::staticText() const
495{
Zack Rusin53484b22011-04-16 11:56:19 -0400496 if (m_staticText && !m_staticText->text().isEmpty())
497 return *m_staticText;
Zack Rusinf6667d12011-03-30 11:03:37 -0400498
Zack Rusin9e292fc2011-04-26 23:03:42 -0400499 QString richText;
500
501 //mark the frame if it uploads more than a meg a frame
502 if (m_binaryDataSize > (1024*1024)) {
503 richText =
504 QObject::tr(
505 "<span style=\"font-weight:bold;\">"
506 "Frame&nbsp;%1</span>"
507 "<span style=\"font-style:italic;\">"
508 "&nbsp;&nbsp;&nbsp;&nbsp;(%2MB)</span>")
509 .arg(number)
510 .arg(double(m_binaryDataSize / (1024.*1024.)), 0, 'g', 2);
511 } else {
512 richText =
513 QObject::tr(
514 "<span style=\"font-weight:bold\">Frame %1</span>")
515 .arg(number);
516 }
Zack Rusinf6667d12011-03-30 11:03:37 -0400517
Zack Rusin53484b22011-04-16 11:56:19 -0400518 if (!m_staticText)
519 m_staticText = new QStaticText(richText);
520
Zack Rusinf6667d12011-03-30 11:03:37 -0400521 QTextOption opt;
522 opt.setWrapMode(QTextOption::NoWrap);
Zack Rusin53484b22011-04-16 11:56:19 -0400523 m_staticText->setTextOption(opt);
524 m_staticText->prepare();
Zack Rusinf6667d12011-03-30 11:03:37 -0400525
Zack Rusin53484b22011-04-16 11:56:19 -0400526 return *m_staticText;
Zack Rusinf6667d12011-03-30 11:03:37 -0400527}
528
529int ApiTraceCall::numChildren() const
530{
531 return 0;
532}
533
534int ApiTraceFrame::numChildren() const
535{
Zack Rusin1d31b6c2011-04-26 22:30:25 -0400536 return m_calls.count();
Zack Rusinf6667d12011-03-30 11:03:37 -0400537}
538
539ApiTraceFrame::ApiTraceFrame()
Zack Rusin7c1793e2011-04-16 23:14:25 -0400540 : ApiTraceEvent(ApiTraceEvent::Frame),
Zack Rusin1d31b6c2011-04-26 22:30:25 -0400541 m_parentTrace(0),
542 m_binaryDataSize(0)
Zack Rusinf6667d12011-03-30 11:03:37 -0400543{
544}
545
546ApiTraceCall::ApiTraceCall()
Zack Rusin8e7a4ff2011-04-07 01:15:48 -0400547 : ApiTraceEvent(ApiTraceEvent::Call),
548 m_hasBinaryData(false),
549 m_binaryDataIndex(0)
Zack Rusinf6667d12011-03-30 11:03:37 -0400550{
551}
552
553ApiTraceEvent::ApiTraceEvent()
Zack Rusin53484b22011-04-16 11:56:19 -0400554 : m_type(ApiTraceEvent::None),
555 m_staticText(0)
Zack Rusinf6667d12011-03-30 11:03:37 -0400556{
557}
558
559ApiTraceEvent::ApiTraceEvent(Type t)
Zack Rusin53484b22011-04-16 11:56:19 -0400560 : m_type(t),
561 m_staticText(0)
Zack Rusinf6667d12011-03-30 11:03:37 -0400562{
563}
564
565ApiTraceCall::~ApiTraceCall()
566{
567}
Zack Rusin581e3ff2011-03-31 23:58:07 -0400568
Zack Rusin7c814f12011-04-09 19:20:58 -0400569QVariantMap ApiTraceEvent::stateParameters() const
570{
571 return m_state.parameters();
572}
573
574ApiTraceState ApiTraceEvent::state() const
Zack Rusin581e3ff2011-03-31 23:58:07 -0400575{
576 return m_state;
577}
578
Zack Rusin7c814f12011-04-09 19:20:58 -0400579void ApiTraceEvent::setState(const ApiTraceState &state)
Zack Rusin581e3ff2011-03-31 23:58:07 -0400580{
581 m_state = state;
582}
Zack Rusin8e7a4ff2011-04-07 01:15:48 -0400583
584bool ApiTraceCall::hasBinaryData() const
585{
586 return m_hasBinaryData;
587}
588
589int ApiTraceCall::binaryDataIndex() const
590{
591 return m_binaryDataIndex;
592}
Zack Rusin7c814f12011-04-09 19:20:58 -0400593
594ApiTraceState::ApiTraceState()
595{
596}
597
598ApiTraceState::ApiTraceState(const QVariantMap &parsedJson)
599{
600 m_parameters = parsedJson[QLatin1String("parameters")].toMap();
José Fonsecaf7a6b622011-04-13 10:37:13 +0100601 QVariantMap attachedShaders =
José Fonseca3773dd62011-04-13 10:54:19 +0100602 parsedJson[QLatin1String("shaders")].toMap();
José Fonsecaf7a6b622011-04-13 10:37:13 +0100603 QVariantMap::const_iterator itr;
Zack Rusin7c814f12011-04-09 19:20:58 -0400604
605
Zack Rusin5e277b02011-04-16 21:52:26 -0400606 for (itr = attachedShaders.constBegin(); itr != attachedShaders.constEnd();
607 ++itr) {
José Fonsecaf7a6b622011-04-13 10:37:13 +0100608 QString type = itr.key();
609 QString source = itr.value().toString();
610 m_shaderSources[type] = source;
Zack Rusin7c814f12011-04-09 19:20:58 -0400611 }
Zack Rusin952e9d42011-04-09 23:37:21 -0400612
José Fonseca18081d52011-05-07 00:10:25 +0100613 QVariantMap textures =
614 parsedJson[QLatin1String("textures")].toMap();
615 for (itr = textures.constBegin(); itr != textures.constEnd(); ++itr) {
616 QVariantMap image = itr.value().toMap();
617 QSize size(image[QLatin1String("__width__")].toInt(),
618 image[QLatin1String("__height__")].toInt());
619 QString cls = image[QLatin1String("__class__")].toString();
620 QString type = image[QLatin1String("__type__")].toString();
621 bool normalized =
622 image[QLatin1String("__normalized__")].toBool();
623 int numChannels =
624 image[QLatin1String("__channels__")].toInt();
Zack Rusin952e9d42011-04-09 23:37:21 -0400625
José Fonseca18081d52011-05-07 00:10:25 +0100626 Q_ASSERT(type == QLatin1String("uint8"));
627 Q_ASSERT(normalized == true);
Zack Rusin952e9d42011-04-09 23:37:21 -0400628
José Fonseca18081d52011-05-07 00:10:25 +0100629 QByteArray dataArray =
630 image[QLatin1String("__data__")].toByteArray();
Zack Rusin952e9d42011-04-09 23:37:21 -0400631
José Fonseca18081d52011-05-07 00:10:25 +0100632 ApiTexture tex;
633 tex.setSize(size);
634 tex.setNumChannels(numChannels);
635 tex.setLabel(itr.key());
636 tex.contentsFromBase64(dataArray);
Zack Rusin952e9d42011-04-09 23:37:21 -0400637
José Fonseca18081d52011-05-07 00:10:25 +0100638 m_textures.append(tex);
Zack Rusin952e9d42011-04-09 23:37:21 -0400639 }
Zack Rusina6846412011-04-10 19:51:44 -0400640
641 QVariantMap fbos =
642 parsedJson[QLatin1String("framebuffer")].toMap();
Zack Rusina6846412011-04-10 19:51:44 -0400643 for (itr = fbos.constBegin(); itr != fbos.constEnd(); ++itr) {
644 QVariantMap buffer = itr.value().toMap();
645 QSize size(buffer[QLatin1String("__width__")].toInt(),
646 buffer[QLatin1String("__height__")].toInt());
647 QString cls = buffer[QLatin1String("__class__")].toString();
648 QString type = buffer[QLatin1String("__type__")].toString();
649 bool normalized = buffer[QLatin1String("__normalized__")].toBool();
650 int numChannels = buffer[QLatin1String("__channels__")].toInt();
651
Zack Rusina6846412011-04-10 19:51:44 -0400652 Q_ASSERT(type == QLatin1String("uint8"));
653 Q_ASSERT(normalized == true);
654
655 QByteArray dataArray =
656 buffer[QLatin1String("__data__")].toByteArray();
657
658 ApiFramebuffer fbo;
659 fbo.setSize(size);
José Fonsecab794df12011-04-12 08:28:45 +0100660 fbo.setNumChannels(numChannels);
Zack Rusina6846412011-04-10 19:51:44 -0400661 fbo.setType(itr.key());
662 fbo.contentsFromBase64(dataArray);
663 m_framebuffers.append(fbo);
664 }
Zack Rusin7c814f12011-04-09 19:20:58 -0400665}
666
667QVariantMap ApiTraceState::parameters() const
668{
669 return m_parameters;
670}
671
José Fonsecaf7a6b622011-04-13 10:37:13 +0100672QMap<QString, QString> ApiTraceState::shaderSources() const
Zack Rusin7c814f12011-04-09 19:20:58 -0400673{
674 return m_shaderSources;
675}
676
677bool ApiTraceState::isEmpty() const
678{
679 return m_parameters.isEmpty();
680}
681
Zack Rusin952e9d42011-04-09 23:37:21 -0400682QList<ApiTexture> ApiTraceState::textures() const
683{
684 return m_textures;
685}
686
Zack Rusina6846412011-04-10 19:51:44 -0400687QList<ApiFramebuffer> ApiTraceState::framebuffers() const
688{
689 return m_framebuffers;
690}
691
Zack Rusin963102f2011-04-15 01:45:05 -0400692QList<QVariant> ApiArray::values() const
693{
694 return m_array;
695}
Zack Rusinead6aad2011-04-15 22:16:18 -0400696
697int ApiTraceCall::index() const
698{
699 return m_index;
700}
701
702QString ApiTraceCall::name() const
703{
704 return m_name;
705}
706
707QStringList ApiTraceCall::argNames() const
708{
709 return m_argNames;
710}
711
712QVariantList ApiTraceCall::arguments() const
713{
Zack Rusin661842d2011-04-17 01:59:16 -0400714 if (m_editedValues.isEmpty())
715 return m_argValues;
716 else
717 return m_editedValues;
Zack Rusinead6aad2011-04-15 22:16:18 -0400718}
719
720QVariant ApiTraceCall::returnValue() const
721{
722 return m_returnValue;
723}
724
725QUrl ApiTraceCall::helpUrl() const
726{
727 return m_helpUrl;
728}
729
730ApiTraceCall::ApiTraceCall(const Trace::Call *call)
731 : ApiTraceEvent(ApiTraceEvent::Call),
732 m_hasBinaryData(false),
733 m_binaryDataIndex(0)
734{
735 m_name = QString::fromStdString(call->sig->name);
736 m_index = call->no;
737
738 QString argumentsText;
739 for (int i = 0; i < call->sig->arg_names.size(); ++i) {
740 m_argNames +=
741 QString::fromStdString(call->sig->arg_names[i]);
742 }
743 if (call->ret) {
744 VariantVisitor retVisitor;
745 call->ret->visit(retVisitor);
746 m_returnValue = retVisitor.variant();
747 }
748 for (int i = 0; i < call->args.size(); ++i) {
749 VariantVisitor argVisitor;
750 call->args[i]->visit(argVisitor);
751 m_argValues += argVisitor.variant();
Zack Rusin6224f242011-04-25 16:47:21 -0400752 if (m_argValues[i].type() == QVariant::ByteArray) {
753 m_hasBinaryData = true;
754 m_binaryDataIndex = i;
755 }
Zack Rusinead6aad2011-04-15 22:16:18 -0400756 }
757}
758
759void ApiTraceCall::setHelpUrl(const QUrl &url)
760{
761 m_helpUrl = url;
762}
763
764void ApiTraceCall::setParentFrame(ApiTraceFrame *frame)
765{
766 m_parentFrame = frame;
767}
768
769ApiTraceFrame * ApiTraceCall::parentFrame()const
770{
771 return m_parentFrame;
772}
Zack Rusinabb3fde2011-04-16 02:16:49 -0400773
Zack Rusin53484b22011-04-16 11:56:19 -0400774ApiTraceEvent::~ApiTraceEvent()
775{
776 delete m_staticText;
777}
778
Zack Rusine6bc9122011-04-16 23:07:05 -0400779void ApiTraceCall::revert()
780{
Zack Rusin0ddd2502011-04-17 02:34:45 -0400781 setEditedValues(QVariantList());
Zack Rusine6bc9122011-04-16 23:07:05 -0400782}
783
Zack Rusin7c1793e2011-04-16 23:14:25 -0400784ApiTrace * ApiTraceFrame::parentTrace() const
785{
786 return m_parentTrace;
787}
788
789void ApiTraceFrame::setParentTrace(ApiTrace *trace)
790{
791 m_parentTrace = trace;
792}
793
Zack Rusin661842d2011-04-17 01:59:16 -0400794QVariantList ApiTraceCall::originalValues() const
795{
796 return m_argValues;
797}
798
799void ApiTraceCall::setEditedValues(const QVariantList &lst)
800{
Zack Rusinb53b1612011-04-19 01:33:58 -0400801 ApiTrace *trace = parentTrace();
Zack Rusin9af5bff2011-04-18 01:05:50 -0400802
Zack Rusin661842d2011-04-17 01:59:16 -0400803 m_editedValues = lst;
Zack Rusin9af5bff2011-04-18 01:05:50 -0400804 //lets regenerate data
805 m_richText = QString();
806 m_filterText = QString();
807 delete m_staticText;
808 m_staticText = 0;
Zack Rusin661842d2011-04-17 01:59:16 -0400809
810 if (trace) {
811 if (!lst.isEmpty()) {
812 trace->callEdited(this);
813 } else {
814 trace->callReverted(this);
815 }
816 }
817}
818
819QVariantList ApiTraceCall::editedValues() const
820{
821 return m_editedValues;
822}
823
824bool ApiTraceCall::edited() const
825{
826 return !m_editedValues.isEmpty();
827}
828
Zack Rusind54055e2011-04-17 18:27:28 -0400829ApiEnum::ApiEnum(const QString &name, const QVariant &val)
830 : m_name(name),
831 m_value(val)
832{
833}
834
835QString ApiEnum::toString() const
836{
837 return m_name;
838}
839
840QVariant ApiEnum::value() const
841{
842 return m_value;
843}
844
845QString ApiEnum::name() const
846{
847 return m_name;
848}
849
Zack Rusinc6247dd2011-04-17 22:56:58 -0400850unsigned long long ApiBitmask::value() const
851{
852 return m_value;
853}
854
855ApiBitmask::Signature ApiBitmask::signature() const
856{
857 return m_sig;
858}
859
860ApiStruct::Signature ApiStruct::signature() const
861{
862 return m_sig;
863}
864
865QList<QVariant> ApiStruct::values() const
866{
867 return m_members;
868}
869
870unsigned long long ApiPointer::value() const
871{
872 return m_value;
873}
874
Zack Rusinb53b1612011-04-19 01:33:58 -0400875bool ApiTraceCall::hasError() const
876{
877 return !m_error.isEmpty();
878}
879
880QString ApiTraceCall::error() const
881{
882 return m_error;
883}
884
885void ApiTraceCall::setError(const QString &msg)
886{
887 if (m_error != msg) {
888 ApiTrace *trace = parentTrace();
889 m_error = msg;
Zack Rusincc0b4912011-04-19 01:59:20 -0400890 m_richText = QString();
Zack Rusinb53b1612011-04-19 01:33:58 -0400891 if (trace)
892 trace->callError(this);
893 }
894}
895
896ApiTrace * ApiTraceCall::parentTrace() const
897{
898 if (m_parentFrame)
899 return m_parentFrame->parentTrace();
900 return NULL;
901}
902
Zack Rusin1d31b6c2011-04-26 22:30:25 -0400903void ApiTraceFrame::addCall(ApiTraceCall *call)
904{
905 m_calls.append(call);
Zack Rusin9e292fc2011-04-26 23:03:42 -0400906 if (call->hasBinaryData()) {
907 QByteArray data =
908 call->arguments()[call->binaryDataIndex()].toByteArray();
909 m_binaryDataSize += data.size();
910 }
Zack Rusin1d31b6c2011-04-26 22:30:25 -0400911}
912
913QList<ApiTraceCall*> ApiTraceFrame::calls() const
914{
915 return m_calls;
916}
917
918ApiTraceCall * ApiTraceFrame::call(int idx) const
919{
920 return m_calls.value(idx);
921}
922
923int ApiTraceFrame::callIndex(ApiTraceCall *call) const
924{
925 return m_calls.indexOf(call);
926}
927
928bool ApiTraceFrame::isEmpty() const
929{
930 return m_calls.isEmpty();
931}
932
Zack Rusin9e292fc2011-04-26 23:03:42 -0400933int ApiTraceFrame::binaryDataSize() const
934{
935 return m_binaryDataSize;
936}
937