#include "apitracecall.h"
+#include "apitrace.h"
#include "trace_model.hpp"
#include <QDebug>
#include <QObject>
+#define QT_USE_FAST_OPERATOR_PLUS
+#include <QStringBuilder>
ApiPointer::ApiPointer(int val)
: m_value(val)
return QString::number(variant.toFloat());
}
if (variant.userType() == QVariant::ByteArray) {
- float kb = variant.toByteArray().size()/1024.;
- return QObject::tr("[binary data, size = %1kb]").arg(kb);
+ if (variant.toByteArray().size() < 1024) {
+ int bytes = variant.toByteArray().size();
+ return QObject::tr("[binary data, size = %1 bytes]").arg(bytes);
+ } else {
+ float kb = variant.toByteArray().size()/1024.;
+ return QObject::tr("[binary data, size = %1 kb]").arg(kb);
+ }
}
if (variant.userType() < QVariant::UserType) {
str += QLatin1String("{");
for (unsigned i = 0; i < m_members.count(); ++i) {
- str += m_sig.memberNames[i];
- str += QLatin1String(" = ");
- str += apiVariantToString(m_members[i]);
+ str += m_sig.memberNames[i] %
+ QLatin1Literal(" = ") %
+ apiVariantToString(m_members[i]);
if (i < m_members.count() - 1)
str += QLatin1String(", ");
}
init(arr);
}
+ApiArray::ApiArray(const QList<QVariant> &vals)
+ : m_array(vals)
+{
+}
+
QString ApiArray::toString() const
{
QString str;
QStaticText ApiTraceCall::staticText() const
{
- if (!m_staticText.text().isEmpty())
- return m_staticText;
+ if (m_staticText && !m_staticText->text().isEmpty())
+ return *m_staticText;
- QString richText = QString::fromLatin1("<span style=\"font-weight:bold\">%1</span>(").arg(name);
- for (int i = 0; i < argNames.count(); ++i) {
+ QString richText = QString::fromLatin1(
+ "<span style=\"font-weight:bold\">%1</span>(").arg(m_name);
+ for (int i = 0; i < m_argNames.count(); ++i) {
richText += QLatin1String("<span style=\"color:#0000ff\">");
- QString argText = apiVariantToString(argValues[i]);
+ QString argText = apiVariantToString(m_argValues[i]);
//if arguments are really long (e.g. shader text), cut them
// and elide it
richText += argText;
}
richText += QLatin1String("</span>");
- if (i < argNames.count() - 1)
- richText += QString::fromLatin1(", ");
+ if (i < m_argNames.count() - 1)
+ richText += QLatin1String(", ");
}
richText += QLatin1String(")");
- if (returnValue.isValid()) {
- richText += QLatin1String(" = ");
- richText += QLatin1String("<span style=\"color:#0000ff\">");
- richText += apiVariantToString(returnValue);
- richText += QLatin1String("</span>");
+ if (m_returnValue.isValid()) {
+ richText +=
+ QLatin1Literal(" = ") %
+ QLatin1Literal("<span style=\"color:#0000ff\">") %
+ apiVariantToString(m_returnValue) %
+ QLatin1Literal("</span>");
}
- m_staticText.setText(richText);
+ if (!m_staticText)
+ m_staticText = new QStaticText(richText);
QTextOption opt;
opt.setWrapMode(QTextOption::NoWrap);
- m_staticText.setTextOption(opt);
- m_staticText.prepare();
+ m_staticText->setTextOption(opt);
+ m_staticText->prepare();
- return m_staticText;
+ return *m_staticText;
}
QString ApiTraceCall::toHtml() const
if (!m_richText.isEmpty())
return m_richText;
- m_richText = QString::fromLatin1("<span style=\"font-weight:bold\">%1</span>(").arg(name);
- for (int i = 0; i < argNames.count(); ++i) {
- m_richText += argNames[i];
- m_richText += QString::fromLatin1(" = ");
- m_richText += QLatin1String("<span style=\"color:#0000ff\">");
- m_richText += apiVariantToString(argValues[i]);
- m_richText += QLatin1String("</span>");
- if (i < argNames.count() - 1)
- m_richText += QString::fromLatin1(", ");
+ if (m_helpUrl.isEmpty()) {
+ m_richText = QString::fromLatin1(
+ "%1) <span style=\"font-weight:bold\">%2</span>(")
+ .arg(m_index)
+ .arg(m_name);
+ } else {
+ m_richText = QString::fromLatin1(
+ "%1) <span style=\"font-weight:bold\"><a href=\"%2\">%3</a></span>(")
+ .arg(m_index)
+ .arg(m_helpUrl.toString())
+ .arg(m_name);
+ }
+
+ for (int i = 0; i < m_argNames.count(); ++i) {
+ m_richText += m_argNames[i] +
+ QLatin1Literal(" = ") +
+ QLatin1Literal("<span style=\"color:#0000ff\">") +
+ apiVariantToString(m_argValues[i]) +
+ QLatin1Literal("</span>");
+ if (i < m_argNames.count() - 1)
+ m_richText += QLatin1String(", ");
}
m_richText += QLatin1String(")");
- if (returnValue.isValid()) {
- m_richText += QLatin1String(" = ");
- m_richText += QLatin1String("<span style=\"color:#0000ff\">");
- m_richText += apiVariantToString(returnValue);
- m_richText += QLatin1String("</span>");
+ if (m_returnValue.isValid()) {
+ m_richText +=
+ QLatin1String(" = ") +
+ QLatin1String("<span style=\"color:#0000ff\">") +
+ apiVariantToString(m_returnValue) +
+ QLatin1String("</span>");
}
+ m_richText.squeeze();
return m_richText;
}
if (!m_filterText.isEmpty())
return m_filterText;
- m_filterText = name;
- for (int i = 0; i < argNames.count(); ++i) {
- m_filterText += argNames[i];
- m_filterText += QString::fromLatin1(" = ");
- m_filterText += apiVariantToString(argValues[i]);
- if (i < argNames.count() - 1)
- m_filterText += QString::fromLatin1(", ");
+ m_filterText = m_name + QLatin1Literal("(");
+ for (int i = 0; i < m_argNames.count(); ++i) {
+ m_filterText += m_argNames[i] +
+ QLatin1Literal(" = ") +
+ apiVariantToString(m_argValues[i]);
+ if (m_argValues[i].type() == QVariant::ByteArray) {
+ m_hasBinaryData = true;
+ m_binaryDataIndex = i;
+ }
+ if (i < m_argNames.count() - 1)
+ m_filterText += QLatin1String(", ");
}
m_filterText += QLatin1String(")");
- if (returnValue.isValid()) {
- m_filterText += QLatin1String(" = ");
- m_filterText += apiVariantToString(returnValue);
+ if (m_returnValue.isValid()) {
+ m_filterText += QLatin1Literal(" = ") +
+ apiVariantToString(m_returnValue);
}
+ m_filterText.squeeze();
return m_filterText;
}
QStaticText ApiTraceFrame::staticText() const
{
- if (!m_staticText.text().isEmpty())
- return m_staticText;
+ if (m_staticText && !m_staticText->text().isEmpty())
+ return *m_staticText;
QString richText =
QString::fromLatin1("<span style=\"font-weight:bold\">Frame %1</span>").arg(number);
- m_staticText.setText(richText);
+ if (!m_staticText)
+ m_staticText = new QStaticText(richText);
+
QTextOption opt;
opt.setWrapMode(QTextOption::NoWrap);
- m_staticText.setTextOption(opt);
- m_staticText.prepare();
+ m_staticText->setTextOption(opt);
+ m_staticText->prepare();
- return m_staticText;
+ return *m_staticText;
}
int ApiTraceCall::numChildren() const
}
ApiTraceFrame::ApiTraceFrame()
- : ApiTraceEvent(ApiTraceEvent::Frame)
+ : ApiTraceEvent(ApiTraceEvent::Frame),
+ m_parentTrace(0)
{
}
ApiTraceCall::ApiTraceCall()
- : ApiTraceEvent(ApiTraceEvent::Call)
+ : ApiTraceEvent(ApiTraceEvent::Call),
+ m_hasBinaryData(false),
+ m_binaryDataIndex(0)
{
}
ApiTraceEvent::ApiTraceEvent()
- : m_type(ApiTraceEvent::None)
+ : m_type(ApiTraceEvent::None),
+ m_staticText(0)
{
}
ApiTraceEvent::ApiTraceEvent(Type t)
- : m_type(t)
+ : m_type(t),
+ m_staticText(0)
{
}
{
}
-QVariantMap ApiTraceEvent::state() const
+QVariantMap ApiTraceEvent::stateParameters() const
+{
+ return m_state.parameters();
+}
+
+ApiTraceState ApiTraceEvent::state() const
{
return m_state;
}
-void ApiTraceEvent::setState(const QVariantMap &state)
+void ApiTraceEvent::setState(const ApiTraceState &state)
{
m_state = state;
}
+
+bool ApiTraceCall::hasBinaryData() const
+{
+ return m_hasBinaryData;
+}
+
+int ApiTraceCall::binaryDataIndex() const
+{
+ return m_binaryDataIndex;
+}
+
+ApiTraceState::ApiTraceState()
+{
+}
+
+ApiTraceState::ApiTraceState(const QVariantMap &parsedJson)
+{
+ m_parameters = parsedJson[QLatin1String("parameters")].toMap();
+ QVariantMap attachedShaders =
+ parsedJson[QLatin1String("shaders")].toMap();
+ QVariantMap::const_iterator itr;
+
+
+ for (itr = attachedShaders.constBegin(); itr != attachedShaders.constEnd();
+ ++itr) {
+ QString type = itr.key();
+ QString source = itr.value().toString();
+ m_shaderSources[type] = source;
+ }
+
+ QVariantList textureUnits =
+ parsedJson[QLatin1String("textures")].toList();
+ for (int i = 0; i < textureUnits.count(); ++i) {
+ QVariantMap unit = textureUnits[i].toMap();
+ for (itr = unit.constBegin(); itr != unit.constEnd(); ++itr) {
+ QVariantMap target = itr.value().toMap();
+ if (target.count()) {
+ QVariantList levels = target[QLatin1String("levels")].toList();
+ for (int j = 0; j < levels.count(); ++j) {
+ QVariantMap level = levels[j].toMap();
+ QVariantMap image = level[QLatin1String("image")].toMap();
+ QSize size(image[QLatin1String("__width__")].toInt(),
+ image[QLatin1String("__height__")].toInt());
+ QString cls = image[QLatin1String("__class__")].toString();
+ QString type = image[QLatin1String("__type__")].toString();
+ bool normalized =
+ image[QLatin1String("__normalized__")].toBool();
+ int numChannels =
+ image[QLatin1String("__channels__")].toInt();
+
+ Q_ASSERT(type == QLatin1String("uint8"));
+ Q_ASSERT(normalized == true);
+
+ QByteArray dataArray =
+ image[QLatin1String("__data__")].toByteArray();
+
+ ApiTexture tex;
+ tex.setSize(size);
+ tex.setNumChannels(numChannels);
+ tex.setLevel(j);
+ tex.setUnit(i);
+ tex.setTarget(itr.key());
+ tex.contentsFromBase64(dataArray);
+
+ m_textures.append(tex);
+ }
+ }
+ }
+ }
+
+ QVariantMap fbos =
+ parsedJson[QLatin1String("framebuffer")].toMap();
+ for (itr = fbos.constBegin(); itr != fbos.constEnd(); ++itr) {
+ QVariantMap buffer = itr.value().toMap();
+ QSize size(buffer[QLatin1String("__width__")].toInt(),
+ buffer[QLatin1String("__height__")].toInt());
+ QString cls = buffer[QLatin1String("__class__")].toString();
+ QString type = buffer[QLatin1String("__type__")].toString();
+ bool normalized = buffer[QLatin1String("__normalized__")].toBool();
+ int numChannels = buffer[QLatin1String("__channels__")].toInt();
+
+ Q_ASSERT(type == QLatin1String("uint8"));
+ Q_ASSERT(normalized == true);
+
+ QByteArray dataArray =
+ buffer[QLatin1String("__data__")].toByteArray();
+
+ ApiFramebuffer fbo;
+ fbo.setSize(size);
+ fbo.setNumChannels(numChannels);
+ fbo.setType(itr.key());
+ fbo.contentsFromBase64(dataArray);
+ m_framebuffers.append(fbo);
+ }
+}
+
+QVariantMap ApiTraceState::parameters() const
+{
+ return m_parameters;
+}
+
+QMap<QString, QString> ApiTraceState::shaderSources() const
+{
+ return m_shaderSources;
+}
+
+bool ApiTraceState::isEmpty() const
+{
+ return m_parameters.isEmpty();
+}
+
+QList<ApiTexture> ApiTraceState::textures() const
+{
+ return m_textures;
+}
+
+QList<ApiFramebuffer> ApiTraceState::framebuffers() const
+{
+ return m_framebuffers;
+}
+
+QList<QVariant> ApiArray::values() const
+{
+ return m_array;
+}
+
+int ApiTraceCall::index() const
+{
+ return m_index;
+}
+
+QString ApiTraceCall::name() const
+{
+ return m_name;
+}
+
+QStringList ApiTraceCall::argNames() const
+{
+ return m_argNames;
+}
+
+QVariantList ApiTraceCall::arguments() const
+{
+ if (m_editedValues.isEmpty())
+ return m_argValues;
+ else
+ return m_editedValues;
+}
+
+QVariant ApiTraceCall::returnValue() const
+{
+ return m_returnValue;
+}
+
+QUrl ApiTraceCall::helpUrl() const
+{
+ return m_helpUrl;
+}
+
+ApiTraceCall::ApiTraceCall(const Trace::Call *call)
+ : ApiTraceEvent(ApiTraceEvent::Call),
+ m_hasBinaryData(false),
+ m_binaryDataIndex(0)
+{
+ m_name = QString::fromStdString(call->sig->name);
+ m_index = call->no;
+
+ QString argumentsText;
+ for (int i = 0; i < call->sig->arg_names.size(); ++i) {
+ m_argNames +=
+ QString::fromStdString(call->sig->arg_names[i]);
+ }
+ if (call->ret) {
+ VariantVisitor retVisitor;
+ call->ret->visit(retVisitor);
+ m_returnValue = retVisitor.variant();
+ }
+ for (int i = 0; i < call->args.size(); ++i) {
+ VariantVisitor argVisitor;
+ call->args[i]->visit(argVisitor);
+ m_argValues += argVisitor.variant();
+
+ //XXX
+ //FIXME: this is a nasty hack. Trace::Blob's can't
+ // delete the contents in the destructor because
+ // the data is being used by other calls. we should
+ // use something like Boost's shared_ptr or
+ // Qt's QSharedPointer to handle it.
+ Trace::Blob *b = dynamic_cast<Trace::Blob*>(call->args[i]);
+ if (b && b->blob()) {
+ char *buf = (char*)b->blob();
+ delete [] buf;
+ }
+
+ }
+}
+
+void ApiTraceCall::setHelpUrl(const QUrl &url)
+{
+ m_helpUrl = url;
+}
+
+void ApiTraceCall::setParentFrame(ApiTraceFrame *frame)
+{
+ m_parentFrame = frame;
+}
+
+ApiTraceFrame * ApiTraceCall::parentFrame()const
+{
+ return m_parentFrame;
+}
+
+ApiTraceEvent::~ApiTraceEvent()
+{
+ delete m_staticText;
+}
+
+void ApiTraceCall::revert()
+{
+}
+
+ApiTrace * ApiTraceFrame::parentTrace() const
+{
+ return m_parentTrace;
+}
+
+void ApiTraceFrame::setParentTrace(ApiTrace *trace)
+{
+ m_parentTrace = trace;
+}
+
+QVariantList ApiTraceCall::originalValues() const
+{
+ return m_argValues;
+}
+
+void ApiTraceCall::setEditedValues(const QVariantList &lst)
+{
+ ApiTrace *trace = 0;
+ if (m_parentFrame)
+ trace = m_parentFrame->parentTrace();
+ m_editedValues = lst;
+
+ if (trace) {
+ if (!lst.isEmpty()) {
+ trace->callEdited(this);
+ } else {
+ trace->callReverted(this);
+ }
+ }
+}
+
+QVariantList ApiTraceCall::editedValues() const
+{
+ return m_editedValues;
+}
+
+bool ApiTraceCall::edited() const
+{
+ return !m_editedValues.isEmpty();
+}
+