]> git.notmuchmail.org Git - apitrace/blobdiff - gui/apitracecall.cpp
Various part now propagate the values.
[apitrace] / gui / apitracecall.cpp
index 26d310255501513aab9a34807c4b431c67bc6791..a43c699a2d3b029ae5f5a39824549efd40e62f89 100644 (file)
@@ -1,9 +1,12 @@
 #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)
@@ -24,8 +27,13 @@ QString apiVariantToString(const QVariant &variant)
         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) {
@@ -110,9 +118,9 @@ QString ApiStruct::toString() const
 
     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(", ");
     }
@@ -202,6 +210,11 @@ ApiArray::ApiArray(const Trace::Array *arr)
     init(arr);
 }
 
+ApiArray::ApiArray(const QList<QVariant> &vals)
+    : m_array(vals)
+{
+}
+
 QString ApiArray::toString() const
 {
     QString str;
@@ -232,13 +245,14 @@ void ApiArray::init(const Trace::Array *arr)
 
 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
@@ -254,24 +268,26 @@ QStaticText ApiTraceCall::staticText() const
             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
@@ -279,24 +295,38 @@ 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;
 }
 
@@ -305,38 +335,45 @@ QString ApiTraceCall::filterText() const
     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
@@ -350,22 +387,27 @@ int ApiTraceFrame::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)
 {
 }
 
@@ -373,12 +415,279 @@ ApiTraceCall::~ApiTraceCall()
 {
 }
 
-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();
+}
+