blob: 54e480d3ff980156c7954f4ed4e56b1e35255d74 [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 Rusin91065372011-03-26 01:54:10 -040047
José Fonsecae8a1aa92011-04-21 09:13:23 +010048// Qt::convertFromPlainText doesn't do precisely what we want
49static QString
50plainTextToHTML(const QString & plain, bool multiLine)
51{
52 int col = 0;
53 bool quote = false;
54 QString rich;
55 for (int i = 0; i < plain.length(); ++i) {
56 if (plain[i] == QLatin1Char('\n')){
57 if (multiLine) {
58 rich += QLatin1String("<br>\n");
59 } else {
60 rich += QLatin1String("\\n");
61 }
62 col = 0;
63 quote = true;
64 } else {
65 if (plain[i] == QLatin1Char('\t')){
66 if (multiLine) {
67 rich += QChar(0x00a0U);
68 ++col;
69 while (col % 8) {
70 rich += QChar(0x00a0U);
71 ++col;
72 }
73 } else {
74 rich += QLatin1String("\\t");
75 }
76 quote = true;
77 } else if (plain[i].isSpace()) {
78 rich += QChar(0x00a0U);
79 quote = true;
80 } else if (plain[i] == QLatin1Char('<')) {
81 rich += QLatin1String("&lt;");
82 } else if (plain[i] == QLatin1Char('>')) {
83 rich += QLatin1String("&gt;");
84 } else if (plain[i] == QLatin1Char('&')) {
85 rich += QLatin1String("&amp;");
86 } else {
87 rich += plain[i];
88 }
89 ++col;
90 }
91 }
92
93 if (quote) {
94 return QLatin1Literal("\"") + rich + QLatin1Literal("\"");
95 }
96
97 return rich;
98}
99
Zack Rusina1a3ad52011-08-27 19:19:18 -0400100QString
101apiVariantToString(const QVariant &variant, bool multiLine)
Zack Rusin91065372011-03-26 01:54:10 -0400102{
103 if (variant.userType() == QVariant::Double) {
104 return QString::number(variant.toFloat());
105 }
Zack Rusin35451522011-04-02 23:44:53 -0400106 if (variant.userType() == QVariant::ByteArray) {
Zack Rusin8e7a4ff2011-04-07 01:15:48 -0400107 if (variant.toByteArray().size() < 1024) {
108 int bytes = variant.toByteArray().size();
109 return QObject::tr("[binary data, size = %1 bytes]").arg(bytes);
110 } else {
111 float kb = variant.toByteArray().size()/1024.;
112 return QObject::tr("[binary data, size = %1 kb]").arg(kb);
113 }
Zack Rusin35451522011-04-02 23:44:53 -0400114 }
Zack Rusin91065372011-03-26 01:54:10 -0400115
José Fonsecae8a1aa92011-04-21 09:13:23 +0100116 if (variant.userType() == QVariant::String) {
117 return plainTextToHTML(variant.toString(), multiLine);
118 }
119
Zack Rusin91065372011-03-26 01:54:10 -0400120 if (variant.userType() < QVariant::UserType) {
121 return variant.toString();
122 }
123
124 if (variant.canConvert<ApiPointer>()) {
125 return variant.value<ApiPointer>().toString();
126 }
127 if (variant.canConvert<ApiBitmask>()) {
128 return variant.value<ApiBitmask>().toString();
129 }
130 if (variant.canConvert<ApiStruct>()) {
131 return variant.value<ApiStruct>().toString();
132 }
133 if (variant.canConvert<ApiArray>()) {
134 return variant.value<ApiArray>().toString();
135 }
Zack Rusind54055e2011-04-17 18:27:28 -0400136 if (variant.canConvert<ApiEnum>()) {
137 return variant.value<ApiEnum>().toString();
138 }
Zack Rusin91065372011-03-26 01:54:10 -0400139
140 return QString();
141}
142
Zack Rusina1a3ad52011-08-27 19:19:18 -0400143
144void VariantVisitor::visit(Trace::Null *)
145{
146 m_variant = QVariant::fromValue(ApiPointer(0));
147}
148
149void VariantVisitor::visit(Trace::Bool *node)
150{
151 m_variant = QVariant(node->value);
152}
153
154void VariantVisitor::visit(Trace::SInt *node)
155{
156 m_variant = QVariant(node->value);
157}
158
159void VariantVisitor::visit(Trace::UInt *node)
160{
161 m_variant = QVariant(node->value);
162}
163
164void VariantVisitor::visit(Trace::Float *node)
165{
166 m_variant = QVariant(node->value);
167}
168
169void VariantVisitor::visit(Trace::String *node)
170{
171 m_variant = QVariant(QString::fromStdString(node->value));
172}
173
174void VariantVisitor::visit(Trace::Enum *e)
175{
176 QVariant val = QVariant(e->sig->value);
177
178 m_variant = QVariant::fromValue(
179 ApiEnum(QString::fromStdString(e->sig->name), val));
180}
181
182void VariantVisitor::visit(Trace::Bitmask *bitmask)
183{
184 m_variant = QVariant::fromValue(ApiBitmask(bitmask));
185}
186
187void VariantVisitor::visit(Trace::Struct *str)
188{
189 m_variant = QVariant::fromValue(ApiStruct(str));
190}
191
192void VariantVisitor::visit(Trace::Array *array)
193{
194 m_variant = QVariant::fromValue(ApiArray(array));
195}
196
197void VariantVisitor::visit(Trace::Blob *blob)
198{
199 //XXX
200 //FIXME: this is a nasty hack. Trace::Blob's can't
201 // delete the contents in the destructor because
202 // the data is being used by other calls. We piggy back
203 // on that assumption and don't deep copy the data. If
204 // Blob's will start deleting the data we will need to
205 // start deep copying it or switch to using something like
206 // Boost's shared_ptr or Qt's QSharedPointer to handle it
207 QByteArray barray = QByteArray::fromRawData(blob->buf, blob->size);
208 m_variant = QVariant(barray);
209}
210
211void VariantVisitor::visit(Trace::Pointer *ptr)
212{
213 m_variant = QVariant::fromValue(ApiPointer(ptr->value));
214}
215
216
217ApiEnum::ApiEnum(const QString &name, const QVariant &val)
218 : m_name(name),
219 m_value(val)
220{
221}
222
223QString ApiEnum::toString() const
224{
225 return m_name;
226}
227
228QVariant ApiEnum::value() const
229{
230 return m_value;
231}
232
233QString ApiEnum::name() const
234{
235 return m_name;
236}
237
238unsigned long long ApiBitmask::value() const
239{
240 return m_value;
241}
242
243ApiBitmask::Signature ApiBitmask::signature() const
244{
245 return m_sig;
246}
247
248ApiStruct::Signature ApiStruct::signature() const
249{
250 return m_sig;
251}
252
253QList<QVariant> ApiStruct::values() const
254{
255 return m_members;
256}
257
258ApiPointer::ApiPointer(unsigned long long val)
259 : m_value(val)
260{
261}
262
263
264unsigned long long ApiPointer::value() const
265{
266 return m_value;
267}
268
269QString ApiPointer::toString() const
270{
271 if (m_value)
272 return QString("0x%1").arg(m_value, 0, 16);
273 else
274 return QLatin1String("NULL");
275}
276
Zack Rusin91065372011-03-26 01:54:10 -0400277ApiBitmask::ApiBitmask(const Trace::Bitmask *bitmask)
278 : m_value(0)
279{
280 init(bitmask);
281}
282
Zack Rusin91065372011-03-26 01:54:10 -0400283void ApiBitmask::init(const Trace::Bitmask *bitmask)
284{
285 if (!bitmask)
286 return;
287
288 m_value = bitmask->value;
José Fonsecafcfbf172011-05-28 13:20:01 +0100289 for (const Trace::BitmaskFlag *it = bitmask->sig->flags;
290 it != bitmask->sig->flags + bitmask->sig->num_flags; ++it) {
José Fonseca31b183a2011-05-28 12:21:15 +0100291 assert(it->value);
Zack Rusin91065372011-03-26 01:54:10 -0400292 QPair<QString, unsigned long long> pair;
293
José Fonseca31b183a2011-05-28 12:21:15 +0100294 pair.first = QString::fromStdString(it->name);
295 pair.second = it->value;
Zack Rusin91065372011-03-26 01:54:10 -0400296
297 m_sig.append(pair);
298 }
299}
300
301QString ApiBitmask::toString() const
302{
303 QString str;
304 unsigned long long value = m_value;
305 bool first = true;
306 for (Signature::const_iterator it = m_sig.begin();
307 value != 0 && it != m_sig.end(); ++it) {
308 Q_ASSERT(it->second);
309 if ((value & it->second) == it->second) {
310 if (!first) {
311 str += QLatin1String(" | ");
312 }
313 str += it->first;
314 value &= ~it->second;
315 first = false;
316 }
317 }
318 if (value || first) {
319 if (!first) {
320 str += QLatin1String(" | ");
321 }
322 str += QString::fromLatin1("0x%1").arg(value, 0, 16);
323 }
324 return str;
325}
326
327ApiStruct::ApiStruct(const Trace::Struct *s)
328{
329 init(s);
330}
331
332QString ApiStruct::toString() const
333{
334 QString str;
335
336 str += QLatin1String("{");
337 for (unsigned i = 0; i < m_members.count(); ++i) {
Zack Rusin5e277b02011-04-16 21:52:26 -0400338 str += m_sig.memberNames[i] %
339 QLatin1Literal(" = ") %
340 apiVariantToString(m_members[i]);
Zack Rusin91065372011-03-26 01:54:10 -0400341 if (i < m_members.count() - 1)
342 str += QLatin1String(", ");
343 }
344 str += QLatin1String("}");
345
346 return str;
347}
348
349void ApiStruct::init(const Trace::Struct *s)
350{
351 if (!s)
352 return;
353
354 m_sig.name = QString::fromStdString(s->sig->name);
José Fonseca1b23ed22011-05-28 13:01:16 +0100355 for (unsigned i = 0; i < s->sig->num_members; ++i) {
Zack Rusin91065372011-03-26 01:54:10 -0400356 VariantVisitor vis;
357 m_sig.memberNames.append(
358 QString::fromStdString(s->sig->member_names[i]));
359 s->members[i]->visit(vis);
360 m_members.append(vis.variant());
361 }
362}
363
Zack Rusin91065372011-03-26 01:54:10 -0400364ApiArray::ApiArray(const Trace::Array *arr)
365{
366 init(arr);
367}
368
Zack Rusinabb3fde2011-04-16 02:16:49 -0400369ApiArray::ApiArray(const QList<QVariant> &vals)
370 : m_array(vals)
371{
372}
373
Zack Rusina1a3ad52011-08-27 19:19:18 -0400374QList<QVariant> ApiArray::values() const
375{
376 return m_array;
377}
378
Zack Rusin91065372011-03-26 01:54:10 -0400379QString ApiArray::toString() const
380{
381 QString str;
382 str += QLatin1String("[");
383 for(int i = 0; i < m_array.count(); ++i) {
384 const QVariant &var = m_array[i];
385 str += apiVariantToString(var);
386 if (i < m_array.count() - 1)
387 str += QLatin1String(", ");
388 }
389 str += QLatin1String("]");
390
391 return str;
392}
393
394void ApiArray::init(const Trace::Array *arr)
395{
396 if (!arr)
397 return;
398
Zack Rusin3c70dbf2011-08-28 03:10:01 -0400399 m_array.reserve(arr->values.size());
Zack Rusin91065372011-03-26 01:54:10 -0400400 for (int i = 0; i < arr->values.size(); ++i) {
401 VariantVisitor vis;
402 arr->values[i]->visit(vis);
403
404 m_array.append(vis.variant());
405 }
406}
Zack Rusin18eade52011-03-26 14:23:35 -0400407
Zack Rusina1a3ad52011-08-27 19:19:18 -0400408ApiTraceState::ApiTraceState()
409{
410}
411
412ApiTraceState::ApiTraceState(const QVariantMap &parsedJson)
413{
414 m_parameters = parsedJson[QLatin1String("parameters")].toMap();
415 QVariantMap attachedShaders =
416 parsedJson[QLatin1String("shaders")].toMap();
417 QVariantMap::const_iterator itr;
418
419
420 for (itr = attachedShaders.constBegin(); itr != attachedShaders.constEnd();
421 ++itr) {
422 QString type = itr.key();
423 QString source = itr.value().toString();
424 m_shaderSources[type] = source;
425 }
426
427 m_uniforms = parsedJson[QLatin1String("uniforms")].toMap();
428
429 QVariantMap textures =
430 parsedJson[QLatin1String("textures")].toMap();
431 for (itr = textures.constBegin(); itr != textures.constEnd(); ++itr) {
432 QVariantMap image = itr.value().toMap();
433 QSize size(image[QLatin1String("__width__")].toInt(),
434 image[QLatin1String("__height__")].toInt());
435 QString cls = image[QLatin1String("__class__")].toString();
436 QString type = image[QLatin1String("__type__")].toString();
437 bool normalized =
438 image[QLatin1String("__normalized__")].toBool();
439 int numChannels =
440 image[QLatin1String("__channels__")].toInt();
441
442 Q_ASSERT(type == QLatin1String("uint8"));
443 Q_ASSERT(normalized == true);
Zack Rusindf95ce02011-08-27 19:46:16 -0400444 Q_UNUSED(normalized);
Zack Rusina1a3ad52011-08-27 19:19:18 -0400445
446 QByteArray dataArray =
447 image[QLatin1String("__data__")].toByteArray();
448
449 ApiTexture tex;
450 tex.setSize(size);
451 tex.setNumChannels(numChannels);
452 tex.setLabel(itr.key());
453 tex.contentsFromBase64(dataArray);
454
455 m_textures.append(tex);
456 }
457
458 QVariantMap fbos =
459 parsedJson[QLatin1String("framebuffer")].toMap();
460 for (itr = fbos.constBegin(); itr != fbos.constEnd(); ++itr) {
461 QVariantMap buffer = itr.value().toMap();
462 QSize size(buffer[QLatin1String("__width__")].toInt(),
463 buffer[QLatin1String("__height__")].toInt());
464 QString cls = buffer[QLatin1String("__class__")].toString();
465 QString type = buffer[QLatin1String("__type__")].toString();
466 bool normalized = buffer[QLatin1String("__normalized__")].toBool();
467 int numChannels = buffer[QLatin1String("__channels__")].toInt();
468
469 Q_ASSERT(type == QLatin1String("uint8"));
470 Q_ASSERT(normalized == true);
Zack Rusindf95ce02011-08-27 19:46:16 -0400471 Q_UNUSED(normalized);
Zack Rusina1a3ad52011-08-27 19:19:18 -0400472
473 QByteArray dataArray =
474 buffer[QLatin1String("__data__")].toByteArray();
475
476 ApiFramebuffer fbo;
477 fbo.setSize(size);
478 fbo.setNumChannels(numChannels);
479 fbo.setType(itr.key());
480 fbo.contentsFromBase64(dataArray);
481 m_framebuffers.append(fbo);
482 }
483}
484
485const QVariantMap & ApiTraceState::parameters() const
486{
487 return m_parameters;
488}
489
490const QMap<QString, QString> & ApiTraceState::shaderSources() const
491{
492 return m_shaderSources;
493}
494
495const QVariantMap & ApiTraceState::uniforms() const
496{
497 return m_uniforms;
498}
499
500bool ApiTraceState::isEmpty() const
501{
502 return m_parameters.isEmpty();
503}
504
505const QList<ApiTexture> & ApiTraceState::textures() const
506{
507 return m_textures;
508}
509
510const QList<ApiFramebuffer> & ApiTraceState::framebuffers() const
511{
512 return m_framebuffers;
513}
514
Zack Rusinac4dd9a2011-08-28 00:38:13 -0400515ApiTraceCallSignature::ApiTraceCallSignature(const QString &name,
516 const QStringList &argNames)
517 : m_name(name),
518 m_argNames(argNames)
519{
520}
521
522ApiTraceCallSignature::~ApiTraceCallSignature()
523{
524}
525
526QUrl ApiTraceCallSignature::helpUrl() const
527{
528 return m_helpUrl;
529}
530
531void ApiTraceCallSignature::setHelpUrl(const QUrl &url)
532{
533 m_helpUrl = url;
534}
535
Zack Rusina1a3ad52011-08-27 19:19:18 -0400536ApiTraceEvent::ApiTraceEvent()
537 : m_type(ApiTraceEvent::None),
Zack Rusined40bc62011-08-28 17:11:02 -0400538 m_hasBinaryData(false),
539 m_binaryDataIndex(0),
540 m_state(0),
Zack Rusina1a3ad52011-08-27 19:19:18 -0400541 m_staticText(0)
542{
543}
544
545ApiTraceEvent::ApiTraceEvent(Type t)
546 : m_type(t),
Zack Rusined40bc62011-08-28 17:11:02 -0400547 m_hasBinaryData(false),
548 m_binaryDataIndex(0),
549 m_state(0),
Zack Rusina1a3ad52011-08-27 19:19:18 -0400550 m_staticText(0)
551{
552}
553
554ApiTraceEvent::~ApiTraceEvent()
555{
Zack Rusined40bc62011-08-28 17:11:02 -0400556 delete m_state;
Zack Rusina1a3ad52011-08-27 19:19:18 -0400557 delete m_staticText;
558}
559
560QVariantMap ApiTraceEvent::stateParameters() const
561{
Zack Rusined40bc62011-08-28 17:11:02 -0400562 if (m_state) {
563 return m_state->parameters();
564 } else {
565 return QVariantMap();
566 }
Zack Rusina1a3ad52011-08-27 19:19:18 -0400567}
568
Zack Rusined40bc62011-08-28 17:11:02 -0400569ApiTraceState *ApiTraceEvent::state() const
Zack Rusina1a3ad52011-08-27 19:19:18 -0400570{
571 return m_state;
572}
573
Zack Rusined40bc62011-08-28 17:11:02 -0400574void ApiTraceEvent::setState(ApiTraceState *state)
Zack Rusina1a3ad52011-08-27 19:19:18 -0400575{
576 m_state = state;
577}
578
Zack Rusinac4dd9a2011-08-28 00:38:13 -0400579ApiTraceCall::ApiTraceCall(ApiTraceFrame *parentFrame, const Trace::Call *call)
Zack Rusina1a3ad52011-08-27 19:19:18 -0400580 : ApiTraceEvent(ApiTraceEvent::Call),
Zack Rusined40bc62011-08-28 17:11:02 -0400581 m_parentFrame(parentFrame)
Zack Rusina1a3ad52011-08-27 19:19:18 -0400582{
Zack Rusinac4dd9a2011-08-28 00:38:13 -0400583 ApiTrace *trace = parentTrace();
Zack Rusina1a3ad52011-08-27 19:19:18 -0400584
Zack Rusinac4dd9a2011-08-28 00:38:13 -0400585 Q_ASSERT(trace);
Zack Rusina1a3ad52011-08-27 19:19:18 -0400586
Zack Rusina1a3ad52011-08-27 19:19:18 -0400587 m_index = call->no;
588
Zack Rusinac4dd9a2011-08-28 00:38:13 -0400589 QString name = QString::fromStdString(call->sig->name);
590 m_signature = trace->signature(name);
591
592 if (!m_signature) {
593 QStringList argNames;
Zack Rusinf22d7992011-08-28 02:23:47 -0400594 argNames.reserve(call->sig->num_args);
Zack Rusinac4dd9a2011-08-28 00:38:13 -0400595 for (int i = 0; i < call->sig->num_args; ++i) {
Zack Rusinf22d7992011-08-28 02:23:47 -0400596 argNames += QString::fromStdString(call->sig->arg_names[i]);
Zack Rusinac4dd9a2011-08-28 00:38:13 -0400597 }
598 m_signature = new ApiTraceCallSignature(name, argNames);
599 trace->addSignature(m_signature);
Zack Rusina1a3ad52011-08-27 19:19:18 -0400600 }
601 if (call->ret) {
602 VariantVisitor retVisitor;
603 call->ret->visit(retVisitor);
604 m_returnValue = retVisitor.variant();
605 }
Zack Rusinf22d7992011-08-28 02:23:47 -0400606 m_argValues.reserve(call->args.size());
Zack Rusina1a3ad52011-08-27 19:19:18 -0400607 for (int i = 0; i < call->args.size(); ++i) {
608 VariantVisitor argVisitor;
609 call->args[i]->visit(argVisitor);
Zack Rusinf22d7992011-08-28 02:23:47 -0400610 m_argValues.append(argVisitor.variant());
Zack Rusina1a3ad52011-08-27 19:19:18 -0400611 if (m_argValues[i].type() == QVariant::ByteArray) {
612 m_hasBinaryData = true;
613 m_binaryDataIndex = i;
614 }
615 }
616}
617
618ApiTraceCall::~ApiTraceCall()
619{
620}
621
622
623bool ApiTraceCall::hasError() const
624{
625 return !m_error.isEmpty();
626}
627
628QString ApiTraceCall::error() const
629{
630 return m_error;
631}
632
633void ApiTraceCall::setError(const QString &msg)
634{
635 if (m_error != msg) {
636 ApiTrace *trace = parentTrace();
637 m_error = msg;
638 m_richText = QString();
639 if (trace)
640 trace->callError(this);
641 }
642}
643
644ApiTrace * ApiTraceCall::parentTrace() const
645{
646 if (m_parentFrame)
647 return m_parentFrame->parentTrace();
648 return NULL;
649}
650
651QVariantList ApiTraceCall::originalValues() const
652{
653 return m_argValues;
654}
655
656void ApiTraceCall::setEditedValues(const QVariantList &lst)
657{
658 ApiTrace *trace = parentTrace();
659
660 m_editedValues = lst;
661 //lets regenerate data
662 m_richText = QString();
Zack Rusindc792082011-08-27 23:29:19 -0400663 m_searchText = QString();
Zack Rusina1a3ad52011-08-27 19:19:18 -0400664 delete m_staticText;
665 m_staticText = 0;
666
667 if (trace) {
668 if (!lst.isEmpty()) {
669 trace->callEdited(this);
670 } else {
671 trace->callReverted(this);
672 }
673 }
674}
675
676QVariantList ApiTraceCall::editedValues() const
677{
678 return m_editedValues;
679}
680
681bool ApiTraceCall::edited() const
682{
683 return !m_editedValues.isEmpty();
684}
685
686void ApiTraceCall::revert()
687{
688 setEditedValues(QVariantList());
689}
690
691void ApiTraceCall::setHelpUrl(const QUrl &url)
692{
Zack Rusinac4dd9a2011-08-28 00:38:13 -0400693 m_signature->setHelpUrl(url);
Zack Rusina1a3ad52011-08-27 19:19:18 -0400694}
695
696void ApiTraceCall::setParentFrame(ApiTraceFrame *frame)
697{
698 m_parentFrame = frame;
699}
700
701ApiTraceFrame * ApiTraceCall::parentFrame()const
702{
703 return m_parentFrame;
704}
705
706int ApiTraceCall::index() const
707{
708 return m_index;
709}
710
711QString ApiTraceCall::name() const
712{
Zack Rusinac4dd9a2011-08-28 00:38:13 -0400713 return m_signature->name();
Zack Rusina1a3ad52011-08-27 19:19:18 -0400714}
715
716QStringList ApiTraceCall::argNames() const
717{
Zack Rusinac4dd9a2011-08-28 00:38:13 -0400718 return m_signature->argNames();
Zack Rusina1a3ad52011-08-27 19:19:18 -0400719}
720
721QVariantList ApiTraceCall::arguments() const
722{
723 if (m_editedValues.isEmpty())
724 return m_argValues;
725 else
726 return m_editedValues;
727}
728
729QVariant ApiTraceCall::returnValue() const
730{
731 return m_returnValue;
732}
733
734QUrl ApiTraceCall::helpUrl() const
735{
Zack Rusinac4dd9a2011-08-28 00:38:13 -0400736 return m_signature->helpUrl();
Zack Rusina1a3ad52011-08-27 19:19:18 -0400737}
738
739bool ApiTraceCall::hasBinaryData() const
740{
741 return m_hasBinaryData;
742}
743
744int ApiTraceCall::binaryDataIndex() const
745{
746 return m_binaryDataIndex;
747}
748
Zack Rusin18eade52011-03-26 14:23:35 -0400749QStaticText ApiTraceCall::staticText() const
750{
Zack Rusin53484b22011-04-16 11:56:19 -0400751 if (m_staticText && !m_staticText->text().isEmpty())
752 return *m_staticText;
Zack Rusin18eade52011-03-26 14:23:35 -0400753
Zack Rusin9af5bff2011-04-18 01:05:50 -0400754 QVariantList argValues = arguments();
755
Zack Rusin53484b22011-04-16 11:56:19 -0400756 QString richText = QString::fromLatin1(
Zack Rusinac4dd9a2011-08-28 00:38:13 -0400757 "<span style=\"font-weight:bold\">%1</span>(").arg(
758 m_signature->name());
759 QStringList argNames = m_signature->argNames();
760 for (int i = 0; i < argNames.count(); ++i) {
Zack Rusin27cb2c42011-03-27 23:53:36 -0400761 richText += QLatin1String("<span style=\"color:#0000ff\">");
Zack Rusin9af5bff2011-04-18 01:05:50 -0400762 QString argText = apiVariantToString(argValues[i]);
Zack Rusindd7f2302011-03-31 22:55:57 -0400763
764 //if arguments are really long (e.g. shader text), cut them
765 // and elide it
766 if (argText.length() > 40) {
767 QString shortened = argText.mid(0, 40);
768 shortened[argText.length() - 5] = '.';
769 shortened[argText.length() - 4] = '.';
770 shortened[argText.length() - 3] = '.';
Zack Rusindf95ce02011-08-27 19:46:16 -0400771 shortened[argText.length() - 2] = argText.at(argText.length() - 2);
772 shortened[argText.length() - 1] = argText.at(argText.length() - 1);
Zack Rusindd7f2302011-03-31 22:55:57 -0400773 richText += shortened;
774 } else {
775 richText += argText;
776 }
Zack Rusin27cb2c42011-03-27 23:53:36 -0400777 richText += QLatin1String("</span>");
Zack Rusinac4dd9a2011-08-28 00:38:13 -0400778 if (i < argNames.count() - 1)
Zack Rusin5e277b02011-04-16 21:52:26 -0400779 richText += QLatin1String(", ");
Zack Rusin27cb2c42011-03-27 23:53:36 -0400780 }
781 richText += QLatin1String(")");
Zack Rusinead6aad2011-04-15 22:16:18 -0400782 if (m_returnValue.isValid()) {
Zack Rusin5e277b02011-04-16 21:52:26 -0400783 richText +=
784 QLatin1Literal(" = ") %
785 QLatin1Literal("<span style=\"color:#0000ff\">") %
786 apiVariantToString(m_returnValue) %
787 QLatin1Literal("</span>");
José Fonseca908f38d2011-03-31 10:09:14 +0100788 }
Zack Rusin27cb2c42011-03-27 23:53:36 -0400789
Zack Rusin53484b22011-04-16 11:56:19 -0400790 if (!m_staticText)
791 m_staticText = new QStaticText(richText);
Zack Rusin9af5bff2011-04-18 01:05:50 -0400792 else
793 m_staticText->setText(richText);
Zack Rusin27cb2c42011-03-27 23:53:36 -0400794 QTextOption opt;
795 opt.setWrapMode(QTextOption::NoWrap);
Zack Rusin53484b22011-04-16 11:56:19 -0400796 m_staticText->setTextOption(opt);
797 m_staticText->prepare();
Zack Rusin27cb2c42011-03-27 23:53:36 -0400798
Zack Rusin53484b22011-04-16 11:56:19 -0400799 return *m_staticText;
Zack Rusin27cb2c42011-03-27 23:53:36 -0400800}
801
802QString ApiTraceCall::toHtml() const
803{
804 if (!m_richText.isEmpty())
805 return m_richText;
806
Zack Rusinb53b1612011-04-19 01:33:58 -0400807 m_richText = QLatin1String("<div class=\"call\">");
808
Zack Rusinac4dd9a2011-08-28 00:38:13 -0400809 QUrl helpUrl = m_signature->helpUrl();
810 if (helpUrl.isEmpty()) {
Zack Rusinb53b1612011-04-19 01:33:58 -0400811 m_richText += QString::fromLatin1(
812 "%1) <span class=\"callName\">%2</span>(")
813 .arg(m_index)
Zack Rusinac4dd9a2011-08-28 00:38:13 -0400814 .arg(m_signature->name());
Zack Rusinc97fadc2011-04-07 15:16:59 -0400815 } else {
Zack Rusinb53b1612011-04-19 01:33:58 -0400816 m_richText += QString::fromLatin1(
817 "%1) <span class=\"callName\"><a href=\"%2\">%3</a></span>(")
Zack Rusinead6aad2011-04-15 22:16:18 -0400818 .arg(m_index)
Zack Rusinac4dd9a2011-08-28 00:38:13 -0400819 .arg(helpUrl.toString())
820 .arg(m_signature->name());
Zack Rusinc97fadc2011-04-07 15:16:59 -0400821 }
822
Zack Rusin9af5bff2011-04-18 01:05:50 -0400823 QVariantList argValues = arguments();
Zack Rusinac4dd9a2011-08-28 00:38:13 -0400824 QStringList argNames = m_signature->argNames();
825 for (int i = 0; i < argNames.count(); ++i) {
Zack Rusinb53b1612011-04-19 01:33:58 -0400826 m_richText +=
827 QLatin1String("<span class=\"arg-name\">") +
Zack Rusinac4dd9a2011-08-28 00:38:13 -0400828 argNames[i] +
Zack Rusinb53b1612011-04-19 01:33:58 -0400829 QLatin1String("</span>") +
830 QLatin1Literal(" = ") +
831 QLatin1Literal("<span class=\"arg-value\">") +
José Fonsecae8a1aa92011-04-21 09:13:23 +0100832 apiVariantToString(argValues[i], true) +
Zack Rusinb53b1612011-04-19 01:33:58 -0400833 QLatin1Literal("</span>");
Zack Rusinac4dd9a2011-08-28 00:38:13 -0400834 if (i < argNames.count() - 1)
Zack Rusin5e277b02011-04-16 21:52:26 -0400835 m_richText += QLatin1String(", ");
Zack Rusin18eade52011-03-26 14:23:35 -0400836 }
837 m_richText += QLatin1String(")");
838
Zack Rusinead6aad2011-04-15 22:16:18 -0400839 if (m_returnValue.isValid()) {
Zack Rusin5e277b02011-04-16 21:52:26 -0400840 m_richText +=
841 QLatin1String(" = ") +
842 QLatin1String("<span style=\"color:#0000ff\">") +
José Fonsecae8a1aa92011-04-21 09:13:23 +0100843 apiVariantToString(m_returnValue, true) +
Zack Rusin5e277b02011-04-16 21:52:26 -0400844 QLatin1String("</span>");
Zack Rusin18eade52011-03-26 14:23:35 -0400845 }
Zack Rusinb53b1612011-04-19 01:33:58 -0400846 m_richText += QLatin1String("</div>");
847
Zack Rusincc0b4912011-04-19 01:59:20 -0400848 if (hasError()) {
849 QString errorStr =
850 QString::fromLatin1(
851 "<div class=\"error\">%1</div>")
852 .arg(m_error);
853 m_richText += errorStr;
854 }
855
Zack Rusinb53b1612011-04-19 01:33:58 -0400856 m_richText =
857 QString::fromLatin1(
858 "<html><head><style type=\"text/css\" media=\"all\">"
859 "%1</style></head><body>%2</body></html>")
860 .arg(styleSheet)
861 .arg(m_richText);
Zack Rusin5e277b02011-04-16 21:52:26 -0400862 m_richText.squeeze();
Zack Rusinb53b1612011-04-19 01:33:58 -0400863
864 //qDebug()<<m_richText;
Zack Rusin18eade52011-03-26 14:23:35 -0400865 return m_richText;
866}
Zack Rusinba3c1bf2011-03-27 17:12:06 -0400867
Zack Rusindc792082011-08-27 23:29:19 -0400868QString ApiTraceCall::searchText() const
Zack Rusinba3c1bf2011-03-27 17:12:06 -0400869{
Zack Rusindc792082011-08-27 23:29:19 -0400870 if (!m_searchText.isEmpty())
871 return m_searchText;
Zack Rusinba3c1bf2011-03-27 17:12:06 -0400872
Zack Rusin9af5bff2011-04-18 01:05:50 -0400873 QVariantList argValues = arguments();
Zack Rusinac4dd9a2011-08-28 00:38:13 -0400874 m_searchText = m_signature->name() + QLatin1Literal("(");
875 QStringList argNames = m_signature->argNames();
876 for (int i = 0; i < argNames.count(); ++i) {
877 m_searchText += argNames[i] +
Zack Rusin5e277b02011-04-16 21:52:26 -0400878 QLatin1Literal(" = ") +
Zack Rusin9af5bff2011-04-18 01:05:50 -0400879 apiVariantToString(argValues[i]);
Zack Rusinac4dd9a2011-08-28 00:38:13 -0400880 if (i < argNames.count() - 1)
Zack Rusindc792082011-08-27 23:29:19 -0400881 m_searchText += QLatin1String(", ");
Zack Rusinba3c1bf2011-03-27 17:12:06 -0400882 }
Zack Rusindc792082011-08-27 23:29:19 -0400883 m_searchText += QLatin1String(")");
Zack Rusinba3c1bf2011-03-27 17:12:06 -0400884
Zack Rusinead6aad2011-04-15 22:16:18 -0400885 if (m_returnValue.isValid()) {
Zack Rusindc792082011-08-27 23:29:19 -0400886 m_searchText += QLatin1Literal(" = ") +
Zack Rusin5e277b02011-04-16 21:52:26 -0400887 apiVariantToString(m_returnValue);
Zack Rusinba3c1bf2011-03-27 17:12:06 -0400888 }
Zack Rusindc792082011-08-27 23:29:19 -0400889 m_searchText.squeeze();
890 return m_searchText;
Zack Rusinba3c1bf2011-03-27 17:12:06 -0400891}
Zack Rusinf6667d12011-03-30 11:03:37 -0400892
Zack Rusina1a3ad52011-08-27 19:19:18 -0400893int ApiTraceCall::numChildren() const
894{
895 return 0;
896}
897
Zack Rusinac4dd9a2011-08-28 00:38:13 -0400898ApiTraceFrame::ApiTraceFrame(ApiTrace *parentTrace)
Zack Rusina1a3ad52011-08-27 19:19:18 -0400899 : ApiTraceEvent(ApiTraceEvent::Frame),
Zack Rusinac4dd9a2011-08-28 00:38:13 -0400900 m_parentTrace(parentTrace),
Zack Rusina1a3ad52011-08-27 19:19:18 -0400901 m_binaryDataSize(0)
902{
903}
904
Zack Rusinf6667d12011-03-30 11:03:37 -0400905QStaticText ApiTraceFrame::staticText() const
906{
Zack Rusin53484b22011-04-16 11:56:19 -0400907 if (m_staticText && !m_staticText->text().isEmpty())
908 return *m_staticText;
Zack Rusinf6667d12011-03-30 11:03:37 -0400909
Zack Rusin9e292fc2011-04-26 23:03:42 -0400910 QString richText;
911
912 //mark the frame if it uploads more than a meg a frame
913 if (m_binaryDataSize > (1024*1024)) {
914 richText =
915 QObject::tr(
916 "<span style=\"font-weight:bold;\">"
917 "Frame&nbsp;%1</span>"
918 "<span style=\"font-style:italic;\">"
919 "&nbsp;&nbsp;&nbsp;&nbsp;(%2MB)</span>")
920 .arg(number)
921 .arg(double(m_binaryDataSize / (1024.*1024.)), 0, 'g', 2);
922 } else {
923 richText =
924 QObject::tr(
925 "<span style=\"font-weight:bold\">Frame %1</span>")
926 .arg(number);
927 }
Zack Rusinf6667d12011-03-30 11:03:37 -0400928
Zack Rusin53484b22011-04-16 11:56:19 -0400929 if (!m_staticText)
930 m_staticText = new QStaticText(richText);
931
Zack Rusinf6667d12011-03-30 11:03:37 -0400932 QTextOption opt;
933 opt.setWrapMode(QTextOption::NoWrap);
Zack Rusin53484b22011-04-16 11:56:19 -0400934 m_staticText->setTextOption(opt);
935 m_staticText->prepare();
Zack Rusinf6667d12011-03-30 11:03:37 -0400936
Zack Rusin53484b22011-04-16 11:56:19 -0400937 return *m_staticText;
Zack Rusinf6667d12011-03-30 11:03:37 -0400938}
939
Zack Rusinf6667d12011-03-30 11:03:37 -0400940int ApiTraceFrame::numChildren() const
941{
Zack Rusin1d31b6c2011-04-26 22:30:25 -0400942 return m_calls.count();
Zack Rusinf6667d12011-03-30 11:03:37 -0400943}
944
Zack Rusin7c1793e2011-04-16 23:14:25 -0400945ApiTrace * ApiTraceFrame::parentTrace() const
946{
947 return m_parentTrace;
948}
949
Zack Rusin1d31b6c2011-04-26 22:30:25 -0400950void ApiTraceFrame::addCall(ApiTraceCall *call)
951{
952 m_calls.append(call);
Zack Rusin9e292fc2011-04-26 23:03:42 -0400953 if (call->hasBinaryData()) {
954 QByteArray data =
955 call->arguments()[call->binaryDataIndex()].toByteArray();
956 m_binaryDataSize += data.size();
957 }
Zack Rusin1d31b6c2011-04-26 22:30:25 -0400958}
959
960QList<ApiTraceCall*> ApiTraceFrame::calls() const
961{
962 return m_calls;
963}
964
965ApiTraceCall * ApiTraceFrame::call(int idx) const
966{
967 return m_calls.value(idx);
968}
969
970int ApiTraceFrame::callIndex(ApiTraceCall *call) const
971{
972 return m_calls.indexOf(call);
973}
974
975bool ApiTraceFrame::isEmpty() const
976{
977 return m_calls.isEmpty();
978}
979
Zack Rusin9e292fc2011-04-26 23:03:42 -0400980int ApiTraceFrame::binaryDataSize() const
981{
982 return m_binaryDataSize;
983}