X-Git-Url: https://git.cworth.org/git?a=blobdiff_plain;f=gui%2Fapitracecall.cpp;h=79876351a12807039e76bd5aba16c9a3dfb1d591;hb=d9d9d22837705de6a2c42ad3f9b23223a2b98fe0;hp=71e2f86a88f5531f711b39d8290bf8733b4cf629;hpb=e6bc9120fc4c954d2f8833100cca7715d91d7d9b;p=apitrace diff --git a/gui/apitracecall.cpp b/gui/apitracecall.cpp index 71e2f86..7987635 100644 --- a/gui/apitracecall.cpp +++ b/gui/apitracecall.cpp @@ -1,30 +1,116 @@ #include "apitracecall.h" +#include "apitrace.h" +#include "traceloader.h" #include "trace_model.hpp" #include +#include #include #define QT_USE_FAST_OPERATOR_PLUS #include - -ApiPointer::ApiPointer(int val) - : m_value(val) +#include + +const char * const styleSheet = + ".call {\n" + " font-weight:bold;\n" + // text shadow looks great but doesn't work well in qtwebkit 4.7 + " /*text-shadow: 0px 2px 3px #555;*/\n" + " font-size: 1.1em;\n" + "}\n" + ".arg-name {\n" + " border: 1px solid rgb(238,206,0);\n" + " border-radius: 4px;\n" + " background: yellow;\n" + " padding: 2px;\n" + " box-shadow: 0px 1px 3px dimgrey;\n" + " -webkit-transition: background 1s linear;\n" + "}\n" + ".arg-name:hover {\n" + " background: white;\n" + "}\n" + ".arg-value {\n" + " color: #0000ff;\n" + "}\n" + ".error {\n" + " border: 1px solid rgb(255,0,0);\n" + " margin: 10px;\n" + " padding: 1;\n" + " border-radius: 4px;\n" + // also looks great but qtwebkit doesn't support it + //" background: #6fb2e5;\n" + //" box-shadow: 0 1px 5px #0061aa, inset 0 10px 20px #b6f9ff;\n" + //" -o-box-shadow: 0 1px 5px #0061aa, inset 0 10px 20px #b6f9ff;\n" + //" -webkit-box-shadow: 0 1px 5px #0061aa, inset 0 10px 20px #b6f9ff;\n" + //" -moz-box-shadow: 0 1px 5px #0061aa, inset 0 10px 20px #b6f9ff;\n" + "}\n"; + + +// Qt::convertFromPlainText doesn't do precisely what we want +static QString +plainTextToHTML(const QString & plain, bool multiLine) { -} + int col = 0; + bool quote = false; + QString rich; + for (int i = 0; i < plain.length(); ++i) { + if (plain[i] == QLatin1Char('\n')){ + if (multiLine) { + rich += QLatin1String("
\n"); + } else { + rich += QLatin1String("\\n"); + } + col = 0; + quote = true; + } else { + if (plain[i] == QLatin1Char('\t')){ + if (multiLine) { + rich += QChar(0x00a0U); + ++col; + while (col % 8) { + rich += QChar(0x00a0U); + ++col; + } + } else { + rich += QLatin1String("\\t"); + } + quote = true; + } else if (plain[i].isSpace()) { + rich += QChar(0x00a0U); + quote = true; + } else if (plain[i] == QLatin1Char('<')) { + rich += QLatin1String("<"); + } else if (plain[i] == QLatin1Char('>')) { + rich += QLatin1String(">"); + } else if (plain[i] == QLatin1Char('&')) { + rich += QLatin1String("&"); + } else { + rich += plain[i]; + } + ++col; + } + } -QString ApiPointer::toString() const -{ - if (m_value) - return QString("0x%1").arg(m_value, 0, 16); - else - return QLatin1String("NULL"); + if (quote) { + return QLatin1Literal("\"") + rich + QLatin1Literal("\""); + } + + return rich; } -QString apiVariantToString(const QVariant &variant) +QString +apiVariantToString(const QVariant &variant, bool multiLine) { - if (variant.userType() == QVariant::Double) { + if (variant.isNull()) { + return QLatin1String("?"); + } + + if (variant.userType() == QMetaType::Float) { return QString::number(variant.toFloat()); } + if (variant.userType() == QVariant::Double) { + return QString::number(variant.toDouble()); + } if (variant.userType() == QVariant::ByteArray) { if (variant.toByteArray().size() < 1024) { int bytes = variant.toByteArray().size(); @@ -35,6 +121,10 @@ QString apiVariantToString(const QVariant &variant) } } + if (variant.userType() == QVariant::String) { + return plainTextToHTML(variant.toString(), multiLine); + } + if (variant.userType() < QVariant::UserType) { return variant.toString(); } @@ -46,35 +136,216 @@ QString apiVariantToString(const QVariant &variant) return variant.value().toString(); } if (variant.canConvert()) { - return variant.value().toString(); + return variant.value().toString(multiLine); } if (variant.canConvert()) { - return variant.value().toString(); + return variant.value().toString(multiLine); + } + if (variant.canConvert()) { + return variant.value().toString(); + } + + return QString(); +} + + +void VariantVisitor::visit(trace::Null *) +{ + m_variant = QVariant::fromValue(ApiPointer(0)); +} + +void VariantVisitor::visit(trace::Bool *node) +{ + m_variant = QVariant(node->value); +} + +void VariantVisitor::visit(trace::SInt *node) +{ + m_variant = QVariant(node->value); +} + +void VariantVisitor::visit(trace::UInt *node) +{ + m_variant = QVariant(node->value); +} + +void VariantVisitor::visit(trace::Float *node) +{ + m_variant = QVariant(node->value); +} + +void VariantVisitor::visit(trace::Double *node) +{ + m_variant = QVariant(node->value); +} + +void VariantVisitor::visit(trace::String *node) +{ + m_variant = QVariant(QString::fromStdString(node->value)); +} + +void VariantVisitor::visit(trace::Enum *e) +{ + ApiTraceEnumSignature *sig = 0; + + if (m_loader) { + sig = m_loader->enumSignature(e->sig->id); + } + if (!sig) { + sig = new ApiTraceEnumSignature(e->sig); + if (m_loader) { + m_loader->addEnumSignature(e->sig->id, sig); + } + } + + m_variant = QVariant::fromValue(ApiEnum(sig, e->value)); +} + +void VariantVisitor::visit(trace::Bitmask *bitmask) +{ + m_variant = QVariant::fromValue(ApiBitmask(bitmask)); +} + +void VariantVisitor::visit(trace::Struct *str) +{ + m_variant = QVariant::fromValue(ApiStruct(str)); +} + +void VariantVisitor::visit(trace::Array *array) +{ + m_variant = QVariant::fromValue(ApiArray(array)); +} + +void VariantVisitor::visit(trace::Blob *blob) +{ + QByteArray barray = QByteArray(blob->buf, blob->size); + m_variant = QVariant(barray); +} + +void VariantVisitor::visit(trace::Pointer *ptr) +{ + m_variant = QVariant::fromValue(ApiPointer(ptr->value)); +} + +void VariantVisitor::visit(trace::Repr *repr) +{ + /* TODO: Preserve both the human and machine value */ + repr->humanValue->visit(*this); +} + +ApiTraceEnumSignature::ApiTraceEnumSignature(const trace::EnumSig *sig) +{ + for (const trace::EnumValue *it = sig->values; + it != sig->values + sig->num_values; ++it) { + QPair pair; + + pair.first = QString::fromStdString(it->name); + pair.second = it->value; + + m_names.append(pair); + } +} + +QString ApiTraceEnumSignature::name(signed long long value) const +{ + for (ValueList::const_iterator it = m_names.begin(); + it != m_names.end(); ++it) { + if (value == it->second) { + return it->first; + } + } + return QString::fromLatin1("%1").arg(value); +} + +ApiEnum::ApiEnum(ApiTraceEnumSignature *sig, signed long long value) + : m_sig(sig), m_value(value) +{ +} + +QString ApiEnum::toString() const +{ + if (m_sig) { + return m_sig->name(m_value); + } + Q_ASSERT(!"should never happen"); + return QString(); +} + +QVariant ApiEnum::value() const +{ + if (m_sig) { + return QVariant::fromValue(m_value); } + Q_ASSERT(!"should never happen"); + return QVariant(); +} +QString ApiEnum::name() const +{ + if (m_sig) { + return m_sig->name(m_value); + } + Q_ASSERT(!"should never happen"); return QString(); } -ApiBitmask::ApiBitmask(const Trace::Bitmask *bitmask) +unsigned long long ApiBitmask::value() const +{ + return m_value; +} + +ApiBitmask::Signature ApiBitmask::signature() const +{ + return m_sig; +} + +ApiStruct::Signature ApiStruct::signature() const +{ + return m_sig; +} + +QList ApiStruct::values() const +{ + return m_members; +} + +ApiPointer::ApiPointer(unsigned long long val) + : m_value(val) +{ +} + + +unsigned long long ApiPointer::value() const +{ + return m_value; +} + +QString ApiPointer::toString() const +{ + if (m_value) + return QString("0x%1").arg(m_value, 0, 16); + else + return QLatin1String("NULL"); +} + +ApiBitmask::ApiBitmask(const trace::Bitmask *bitmask) : m_value(0) { init(bitmask); } - -void ApiBitmask::init(const Trace::Bitmask *bitmask) +void ApiBitmask::init(const trace::Bitmask *bitmask) { if (!bitmask) return; m_value = bitmask->value; - for (Trace::Bitmask::Signature::const_iterator it = bitmask->sig->begin(); - it != bitmask->sig->end(); ++it) { - assert(it->second); + for (const trace::BitmaskFlag *it = bitmask->sig->flags; + it != bitmask->sig->flags + bitmask->sig->num_flags; ++it) { QPair pair; - pair.first = QString::fromStdString(it->first); - pair.second = it->second; + pair.first = QString::fromStdString(it->name); + pair.second = it->value; m_sig.append(pair); } @@ -85,10 +356,10 @@ QString ApiBitmask::toString() const QString str; unsigned long long value = m_value; bool first = true; - for (Signature::const_iterator it = m_sig.begin(); - value != 0 && it != m_sig.end(); ++it) { - Q_ASSERT(it->second); - if ((value & it->second) == it->second) { + for (Signature::const_iterator it = m_sig.begin(); it != m_sig.end(); ++it) { + Q_ASSERT(it->second || first); + if ((it->second && (value & it->second) == it->second) || + (!it->second && value == 0)) { if (!first) { str += QLatin1String(" | "); } @@ -96,6 +367,9 @@ QString ApiBitmask::toString() const value &= ~it->second; first = false; } + if (value == 0) { + break; + } } if (value || first) { if (!first) { @@ -106,140 +380,548 @@ QString ApiBitmask::toString() const return str; } -ApiStruct::ApiStruct(const Trace::Struct *s) +ApiStruct::ApiStruct(const trace::Struct *s) +{ + init(s); +} + +QString ApiStruct::toString(bool multiLine) const +{ + QString str; + + str += QLatin1String("{"); + for (unsigned i = 0; i < m_members.count(); ++i) { + str += m_sig.memberNames[i] % + QLatin1Literal(" = ") % + apiVariantToString(m_members[i], multiLine); + if (i < m_members.count() - 1) + str += QLatin1String(", "); + } + str += QLatin1String("}"); + + return str; +} + +void ApiStruct::init(const trace::Struct *s) +{ + if (!s) + return; + + m_sig.name = QString::fromStdString(s->sig->name); + for (unsigned i = 0; i < s->sig->num_members; ++i) { + VariantVisitor vis(0); + m_sig.memberNames.append( + QString::fromStdString(s->sig->member_names[i])); + s->members[i]->visit(vis); + m_members.append(vis.variant()); + } +} + +ApiArray::ApiArray(const trace::Array *arr) +{ + init(arr); +} + +ApiArray::ApiArray(const QVector &vals) + : m_array(vals) +{ +} + +QVector ApiArray::values() const +{ + return m_array; +} + +QString ApiArray::toString(bool multiLine) const +{ + QString str; + str += QLatin1String("["); + for(int i = 0; i < m_array.count(); ++i) { + const QVariant &var = m_array[i]; + str += apiVariantToString(var, multiLine); + if (i < m_array.count() - 1) + str += QLatin1String(", "); + } + str += QLatin1String("]"); + + return str; +} + +void ApiArray::init(const trace::Array *arr) +{ + if (!arr) + return; + + m_array.reserve(arr->values.size()); + for (int i = 0; i < arr->values.size(); ++i) { + VariantVisitor vis(0); + arr->values[i]->visit(vis); + + m_array.append(vis.variant()); + } + m_array.squeeze(); +} + +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; + } + + m_uniforms = parsedJson[QLatin1String("uniforms")].toMap(); + + QVariantMap textures = + parsedJson[QLatin1String("textures")].toMap(); + for (itr = textures.constBegin(); itr != textures.constEnd(); ++itr) { + QVariantMap image = itr.value().toMap(); + QSize size(image[QLatin1String("__width__")].toInt(), + image[QLatin1String("__height__")].toInt()); + QString cls = image[QLatin1String("__class__")].toString(); + int depth = + image[QLatin1String("__depth__")].toInt(); + QString formatName = + image[QLatin1String("__format__")].toString(); + + QByteArray dataArray = + image[QLatin1String("__data__")].toByteArray(); + + ApiTexture tex; + tex.setSize(size); + tex.setDepth(depth); + tex.setFormatName(formatName); + tex.setLabel(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(); + int depth = buffer[QLatin1String("__depth__")].toInt(); + QString formatName = buffer[QLatin1String("__format__")].toString(); + + QByteArray dataArray = + buffer[QLatin1String("__data__")].toByteArray(); + + ApiFramebuffer fbo; + fbo.setSize(size); + fbo.setDepth(depth); + fbo.setFormatName(formatName); + fbo.setType(itr.key()); + fbo.contentsFromBase64(dataArray); + m_framebuffers.append(fbo); + } +} + +const QVariantMap & ApiTraceState::parameters() const +{ + return m_parameters; +} + +const QMap & ApiTraceState::shaderSources() const +{ + return m_shaderSources; +} + +const QVariantMap & ApiTraceState::uniforms() const +{ + return m_uniforms; +} + +bool ApiTraceState::isEmpty() const +{ + return m_parameters.isEmpty() && + m_shaderSources.isEmpty() && + m_textures.isEmpty() && + m_framebuffers.isEmpty(); +} + +const QList & ApiTraceState::textures() const +{ + return m_textures; +} + +const QList & ApiTraceState::framebuffers() const +{ + return m_framebuffers; +} + +ApiFramebuffer ApiTraceState::colorBuffer() const +{ + foreach (ApiFramebuffer fbo, m_framebuffers) { + if (fbo.type() == QLatin1String("GL_BACK")) { + return fbo; + } + } + foreach (ApiFramebuffer fbo, m_framebuffers) { + if (fbo.type() == QLatin1String("GL_FRONT")) { + return fbo; + } + } + return ApiFramebuffer(); +} + + +ApiTraceCallSignature::ApiTraceCallSignature(const QString &name, + const QStringList &argNames) + : m_name(name), + m_argNames(argNames) +{ +} + +ApiTraceCallSignature::~ApiTraceCallSignature() +{ +} + +QUrl ApiTraceCallSignature::helpUrl() const +{ + return m_helpUrl; +} + +void ApiTraceCallSignature::setHelpUrl(const QUrl &url) +{ + m_helpUrl = url; +} + +ApiTraceEvent::ApiTraceEvent() + : m_type(ApiTraceEvent::None), + m_hasBinaryData(false), + m_binaryDataIndex(0), + m_state(0), + m_staticText(0) +{ +} + +ApiTraceEvent::ApiTraceEvent(Type t) + : m_type(t), + m_hasBinaryData(false), + m_binaryDataIndex(0), + m_state(0), + m_staticText(0) +{ +} + +ApiTraceEvent::~ApiTraceEvent() +{ + delete m_state; + delete m_staticText; +} + +QVariantMap ApiTraceEvent::stateParameters() const +{ + if (m_state) { + return m_state->parameters(); + } else { + return QVariantMap(); + } +} + +ApiTraceState *ApiTraceEvent::state() const +{ + return m_state; +} + +void ApiTraceEvent::setState(ApiTraceState *state) +{ + m_state = state; +} + +ApiTraceCall::ApiTraceCall(ApiTraceFrame *parentFrame, + TraceLoader *loader, + const trace::Call *call) + : ApiTraceEvent(ApiTraceEvent::Call), + m_parentFrame(parentFrame), + m_parentCall(0) +{ + loadData(loader, call); +} + +ApiTraceCall::ApiTraceCall(ApiTraceCall *parentCall, + TraceLoader *loader, + const trace::Call *call) + : ApiTraceEvent(ApiTraceEvent::Call), + m_parentFrame(parentCall->parentFrame()), + m_parentCall(parentCall) +{ + loadData(loader, call); +} + + +ApiTraceCall::~ApiTraceCall() +{ +} + + +void +ApiTraceCall::loadData(TraceLoader *loader, + const trace::Call *call) +{ + m_index = call->no; + + m_signature = loader->signature(call->sig->id); + + if (!m_signature) { + QString name = QString::fromStdString(call->sig->name); + QStringList argNames; + argNames.reserve(call->sig->num_args); + for (int i = 0; i < call->sig->num_args; ++i) { + argNames += QString::fromStdString(call->sig->arg_names[i]); + } + m_signature = new ApiTraceCallSignature(name, argNames); + loader->addSignature(call->sig->id, m_signature); + } + if (call->ret) { + VariantVisitor retVisitor(loader); + call->ret->visit(retVisitor); + m_returnValue = retVisitor.variant(); + } + m_argValues.reserve(call->args.size()); + for (int i = 0; i < call->args.size(); ++i) { + if (call->args[i].value) { + VariantVisitor argVisitor(loader); + call->args[i].value->visit(argVisitor); + m_argValues.append(argVisitor.variant()); + if (m_argValues[i].type() == QVariant::ByteArray) { + m_hasBinaryData = true; + m_binaryDataIndex = i; + } + } else { + m_argValues.append(QVariant()); + } + } + m_argValues.squeeze(); + m_flags = call->flags; + if (call->backtrace != NULL) { + QString qbacktrace; + for (int i = 0; i < call->backtrace->size(); i++) { + const trace::StackFrame * frame = (*call->backtrace)[i]; + if (frame->module != NULL) { + qbacktrace += QString("%1 ").arg(frame->module); + } + if (frame->function != NULL) { + qbacktrace += QString("at %1() ").arg(frame->function); + } + if (frame->filename != NULL) { + qbacktrace += QString("at %1").arg(frame->filename); + if (frame->linenumber >= 0) { + qbacktrace += QString(":%1 ").arg(frame->linenumber); + } + } + else { + if (frame->offset >= 0) { + qbacktrace += QString("[0x%1]").arg(frame->offset, 0, 16); + } + } + qbacktrace += "\n"; + } + this->setBacktrace(qbacktrace); + } +} + +ApiTraceCall * +ApiTraceCall::parentCall() const +{ + return m_parentCall; +} + + +ApiTraceEvent * +ApiTraceCall::parentEvent() const +{ + if (m_parentCall) + return m_parentCall; + else + return m_parentFrame; +} + +QVector +ApiTraceCall::children() const { - init(s); + return m_children; } -QString ApiStruct::toString() const +void +ApiTraceCall::addChild(ApiTraceCall *call) { - QString str; + m_children.append(call); +} - str += QLatin1String("{"); - for (unsigned i = 0; i < m_members.count(); ++i) { - str += m_sig.memberNames[i] % - QLatin1Literal(" = ") % - apiVariantToString(m_members[i]); - if (i < m_members.count() - 1) - str += QLatin1String(", "); - } - str += QLatin1String("}"); - return str; +int +ApiTraceCall::callIndex(ApiTraceCall *call) const +{ + return m_children.indexOf(call); } -void ApiStruct::init(const Trace::Struct *s) +void +ApiTraceCall::finishedAddingChildren() { - if (!s) - return; + m_children.squeeze(); +} - m_sig.name = QString::fromStdString(s->sig->name); - for (unsigned i = 0; i < s->members.size(); ++i) { - VariantVisitor vis; - m_sig.memberNames.append( - QString::fromStdString(s->sig->member_names[i])); - s->members[i]->visit(vis); - m_members.append(vis.variant()); +bool ApiTraceCall::hasError() const +{ + return !m_error.isEmpty(); +} + +QString ApiTraceCall::error() const +{ + return m_error; +} + +void ApiTraceCall::setError(const QString &msg) +{ + if (m_error != msg) { + m_error = msg; + m_richText = QString(); } } -void VariantVisitor::visit(Trace::Null *) +ApiTrace * ApiTraceCall::parentTrace() const { - m_variant = QVariant(QLatin1String("NULL")); + if (m_parentFrame) + return m_parentFrame->parentTrace(); + return NULL; } -void VariantVisitor::visit(Trace::Bool *node) +QVector ApiTraceCall::originalValues() const { - m_variant = QVariant(node->value); + return m_argValues; } -void VariantVisitor::visit(Trace::SInt *node) +void ApiTraceCall::setEditedValues(const QVector &lst) { - m_variant = QVariant(node->value); + ApiTrace *trace = parentTrace(); + + m_editedValues = lst; + //lets regenerate data + m_richText = QString(); + m_searchText = QString(); + delete m_staticText; + m_staticText = 0; + + if (trace) { + if (!lst.isEmpty()) { + trace->callEdited(this); + } else { + trace->callReverted(this); + } + } } -void VariantVisitor::visit(Trace::UInt *node) +QVector ApiTraceCall::editedValues() const { - m_variant = QVariant(node->value); + return m_editedValues; } -void VariantVisitor::visit(Trace::Float *node) +bool ApiTraceCall::edited() const { - m_variant = QVariant(node->value); + return !m_editedValues.isEmpty(); } -void VariantVisitor::visit(Trace::String *node) +void ApiTraceCall::revert() { - m_variant = QVariant(QString::fromStdString(node->value)); + setEditedValues(QVector()); } -void VariantVisitor::visit(Trace::Enum *e) +void ApiTraceCall::setHelpUrl(const QUrl &url) { - m_variant = QVariant(QString::fromStdString(e->sig->first)); + m_signature->setHelpUrl(url); } -void VariantVisitor::visit(Trace::Bitmask *bitmask) +void ApiTraceCall::setParentFrame(ApiTraceFrame *frame) { - m_variant = QVariant::fromValue(ApiBitmask(bitmask)); + m_parentFrame = frame; } -void VariantVisitor::visit(Trace::Struct *str) +ApiTraceFrame * ApiTraceCall::parentFrame()const { - m_variant = QVariant::fromValue(ApiStruct(str)); + return m_parentFrame; } -void VariantVisitor::visit(Trace::Array *array) +int ApiTraceCall::index() const { - m_variant = QVariant::fromValue(ApiArray(array)); + return m_index; } -void VariantVisitor::visit(Trace::Blob *blob) +QString ApiTraceCall::name() const { - QByteArray barray = QByteArray::fromRawData(blob->buf, blob->size); - m_variant = QVariant(barray); + return m_signature->name(); } -void VariantVisitor::visit(Trace::Pointer *ptr) +QStringList ApiTraceCall::argNames() const { - m_variant = QVariant::fromValue(ApiPointer(ptr->value)); + return m_signature->argNames(); } -ApiArray::ApiArray(const Trace::Array *arr) +QVector ApiTraceCall::arguments() const { - init(arr); + if (m_editedValues.isEmpty()) + return m_argValues; + else + return m_editedValues; } -ApiArray::ApiArray(const QList &vals) - : m_array(vals) +ApiTraceEvent * +ApiTraceCall::eventAtRow(int row) const { + if (row < m_children.count()) + return m_children.value(row); + else + return NULL; } -QString ApiArray::toString() const +QVariant ApiTraceCall::returnValue() const { - QString str; - str += QLatin1String("["); - for(int i = 0; i < m_array.count(); ++i) { - const QVariant &var = m_array[i]; - str += apiVariantToString(var); - if (i < m_array.count() - 1) - str += QLatin1String(", "); - } - str += QLatin1String("]"); + return m_returnValue; +} - return str; +trace::CallFlags ApiTraceCall::flags() const +{ + return m_flags; } -void ApiArray::init(const Trace::Array *arr) +QUrl ApiTraceCall::helpUrl() const { - if (!arr) - return; + return m_signature->helpUrl(); +} - for (int i = 0; i < arr->values.size(); ++i) { - VariantVisitor vis; - arr->values[i]->visit(vis); +bool ApiTraceCall::hasBinaryData() const +{ + return m_hasBinaryData; +} - m_array.append(vis.variant()); - } +int ApiTraceCall::binaryDataIndex() const +{ + return m_binaryDataIndex; +} + +QString ApiTraceCall::backtrace() const +{ + return m_backtrace; +} + +void ApiTraceCall::setBacktrace(QString backtrace) +{ + m_backtrace = backtrace; } QStaticText ApiTraceCall::staticText() const @@ -247,11 +929,15 @@ QStaticText ApiTraceCall::staticText() const if (m_staticText && !m_staticText->text().isEmpty()) return *m_staticText; + QVector argValues = arguments(); + QString richText = QString::fromLatin1( - "%1(").arg(m_name); - for (int i = 0; i < m_argNames.count(); ++i) { + "%1(").arg( + m_signature->name()); + QStringList argNames = m_signature->argNames(); + for (int i = 0; i < argNames.count(); ++i) { richText += QLatin1String(""); - QString argText = apiVariantToString(m_argValues[i]); + QString argText = apiVariantToString(argValues[i]); //if arguments are really long (e.g. shader text), cut them // and elide it @@ -260,14 +946,14 @@ QStaticText ApiTraceCall::staticText() const shortened[argText.length() - 5] = '.'; shortened[argText.length() - 4] = '.'; shortened[argText.length() - 3] = '.'; - shortened[argText.length() - 2] = argText[argText.length() - 2]; - shortened[argText.length() - 1] = argText[argText.length() - 1]; + shortened[argText.length() - 2] = argText.at(argText.length() - 2); + shortened[argText.length() - 1] = argText.at(argText.length() - 1); richText += shortened; } else { richText += argText; } richText += QLatin1String(""); - if (i < m_argNames.count() - 1) + if (i < argNames.count() - 1) richText += QLatin1String(", "); } richText += QLatin1String(")"); @@ -281,6 +967,8 @@ QStaticText ApiTraceCall::staticText() const if (!m_staticText) m_staticText = new QStaticText(richText); + else + m_staticText->setText(richText); QTextOption opt; opt.setWrapMode(QTextOption::NoWrap); m_staticText->setTextOption(opt); @@ -294,26 +982,44 @@ QString ApiTraceCall::toHtml() const if (!m_richText.isEmpty()) return m_richText; - if (m_helpUrl.isEmpty()) { - m_richText = QString::fromLatin1( - "%1) %2(") - .arg(m_index) - .arg(m_name); + m_richText += QLatin1String("
"); + + + m_richText += + QString::fromLatin1("%1) ") + .arg(m_index); + QString parentTip; + if (m_parentFrame) { + parentTip = + QString::fromLatin1("Frame %1") + .arg(m_parentFrame->number); + } + QUrl helpUrl = m_signature->helpUrl(); + if (helpUrl.isEmpty()) { + m_richText += QString::fromLatin1( + "%2(") + .arg(parentTip) + .arg(m_signature->name()); } else { - m_richText = QString::fromLatin1( - "%1) %3(") - .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("") + - apiVariantToString(m_argValues[i]) + - QLatin1Literal(""); - if (i < m_argNames.count() - 1) + m_richText += QString::fromLatin1( + "%3(") + .arg(parentTip) + .arg(helpUrl.toString()) + .arg(m_signature->name()); + } + + QVector argValues = arguments(); + QStringList argNames = m_signature->argNames(); + for (int i = 0; i < argNames.count(); ++i) { + m_richText += + QLatin1String("") + + argNames[i] + + QLatin1String("") + + QLatin1Literal(" = ") + + QLatin1Literal("") + + apiVariantToString(argValues[i], true) + + QLatin1Literal(""); + if (i < argNames.count() - 1) m_richText += QLatin1String(", "); } m_richText += QLatin1String(")"); @@ -322,326 +1028,274 @@ QString ApiTraceCall::toHtml() const m_richText += QLatin1String(" = ") + QLatin1String("") + - apiVariantToString(m_returnValue) + + apiVariantToString(m_returnValue, true) + QLatin1String(""); } + m_richText += QLatin1String("
"); + + if (hasError()) { + QString errorStr = + QString::fromLatin1( + "
%1
") + .arg(m_error); + m_richText += errorStr; + } + + m_richText = + QString::fromLatin1( + "%2") + .arg(styleSheet) + .arg(m_richText); m_richText.squeeze(); + + //qDebug()< argValues = arguments(); + m_searchText = m_signature->name() + QLatin1Literal("("); + QStringList argNames = m_signature->argNames(); + for (int i = 0; i < argNames.count(); ++i) { + m_searchText += 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(", "); + apiVariantToString(argValues[i]); + if (i < argNames.count() - 1) + m_searchText += QLatin1String(", "); } - m_filterText += QLatin1String(")"); + m_searchText += QLatin1String(")"); if (m_returnValue.isValid()) { - m_filterText += QLatin1Literal(" = ") + + m_searchText += QLatin1Literal(" = ") + apiVariantToString(m_returnValue); } - m_filterText.squeeze(); - return m_filterText; -} - -QStaticText ApiTraceFrame::staticText() const -{ - if (m_staticText && !m_staticText->text().isEmpty()) - return *m_staticText; - - QString richText = - QString::fromLatin1("Frame %1").arg(number); - - if (!m_staticText) - m_staticText = new QStaticText(richText); - - QTextOption opt; - opt.setWrapMode(QTextOption::NoWrap); - m_staticText->setTextOption(opt); - m_staticText->prepare(); - - return *m_staticText; + m_searchText.squeeze(); + return m_searchText; } int ApiTraceCall::numChildren() const { - return 0; + return m_children.count(); } -int ApiTraceFrame::numChildren() const +bool ApiTraceCall::contains(const QString &str, + Qt::CaseSensitivity sensitivity) const { - return calls.count(); + QString txt = searchText(); + return txt.contains(str, sensitivity); } -ApiTraceFrame::ApiTraceFrame() - : ApiTraceEvent(ApiTraceEvent::Frame) -{ -} -ApiTraceCall::ApiTraceCall() - : ApiTraceEvent(ApiTraceEvent::Call), - m_hasBinaryData(false), - m_binaryDataIndex(0) +ApiTraceFrame::ApiTraceFrame(ApiTrace *parentTrace) + : ApiTraceEvent(ApiTraceEvent::Frame), + m_parentTrace(parentTrace), + m_binaryDataSize(0), + m_loaded(false), + m_callsToLoad(0), + m_lastCallIndex(0) { } -ApiTraceEvent::ApiTraceEvent() - : m_type(ApiTraceEvent::None), - m_staticText(0) +ApiTraceFrame::~ApiTraceFrame() { + qDeleteAll(m_calls); } -ApiTraceEvent::ApiTraceEvent(Type t) - : m_type(t), - m_staticText(0) +QStaticText ApiTraceFrame::staticText() const { -} + if (m_staticText && !m_staticText->text().isEmpty()) + return *m_staticText; -ApiTraceCall::~ApiTraceCall() -{ -} + QString richText = QObject::tr( + "Frame %1" + "   " + " " + "(%2 calls)") + .arg(number) + .arg(m_loaded ? m_calls.count() : m_callsToLoad); + + //mark the frame if it uploads more than a meg a frame + if (m_binaryDataSize > (1024*1024)) { + richText = + QObject::tr( + "%1" + "" + "    (%2MB)") + .arg(richText) + .arg(double(m_binaryDataSize / (1024.*1024.)), 0, 'g', 2); + } -QVariantMap ApiTraceEvent::stateParameters() const -{ - return m_state.parameters(); -} + if (!m_staticText) + m_staticText = new QStaticText(richText); -ApiTraceState ApiTraceEvent::state() const -{ - return m_state; + QTextOption opt; + opt.setWrapMode(QTextOption::NoWrap); + m_staticText->setTextOption(opt); + m_staticText->prepare(); + + return *m_staticText; } -void ApiTraceEvent::setState(const ApiTraceState &state) +int ApiTraceFrame::numChildren() const { - m_state = state; + return m_children.count(); } -bool ApiTraceCall::hasBinaryData() const +int ApiTraceFrame::numTotalCalls() const { - return m_hasBinaryData; + return m_calls.count(); } -int ApiTraceCall::binaryDataIndex() const +ApiTrace * ApiTraceFrame::parentTrace() const { - return m_binaryDataIndex; + return m_parentTrace; } -ApiTraceState::ApiTraceState() +QVector ApiTraceFrame::calls() const { + return m_calls; } -ApiTraceState::ApiTraceState(const QVariantMap &parsedJson) +ApiTraceEvent * ApiTraceFrame::eventAtRow(int row) const { - m_parameters = parsedJson[QLatin1String("parameters")].toMap(); - QVariantMap attachedShaders = - parsedJson[QLatin1String("shaders")].toMap(); - QVariantMap::const_iterator itr; - + if (row < m_children.count()) + return m_children.value(row); + else + return NULL; +} - 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); - } - } +ApiTraceCall * ApiTraceFrame::callWithIndex(int index) const +{ + QVector::const_iterator itr; + for (itr = m_calls.constBegin(); itr != m_calls.constEnd(); ++itr) { + if ((*itr)->index() == index) { + return *itr; } } - - 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); - } + return 0; } -QVariantMap ApiTraceState::parameters() const +int ApiTraceFrame::callIndex(ApiTraceCall *call) const { - return m_parameters; + return m_children.indexOf(call); } -QMap ApiTraceState::shaderSources() const +bool ApiTraceFrame::isEmpty() const { - return m_shaderSources; + if (m_loaded) { + return m_calls.isEmpty(); + } else { + return m_callsToLoad == 0; + } } -bool ApiTraceState::isEmpty() const +int ApiTraceFrame::binaryDataSize() const { - return m_parameters.isEmpty(); + return m_binaryDataSize; } -QList ApiTraceState::textures() const +void ApiTraceFrame::setCalls(const QVector &children, + const QVector &calls, + quint64 binaryDataSize) { - return m_textures; + m_children = children; + m_calls = calls; + m_binaryDataSize = binaryDataSize; + m_loaded = true; + delete m_staticText; + m_staticText = 0; } -QList ApiTraceState::framebuffers() const +bool ApiTraceFrame::isLoaded() const { - return m_framebuffers; + return m_loaded; } -QList ApiArray::values() const +void ApiTraceFrame::setNumChildren(int num) { - return m_array; + m_callsToLoad = num; } -int ApiTraceCall::index() const +void ApiTraceFrame::setParentTrace(ApiTrace *parent) { - return m_index; + m_parentTrace = parent; } -QString ApiTraceCall::name() const +int ApiTraceFrame::numChildrenToLoad() const { - return m_name; + return m_callsToLoad; } -QStringList ApiTraceCall::argNames() const +ApiTraceCall * +ApiTraceFrame::findNextCall(ApiTraceCall *from, + const QString &str, + Qt::CaseSensitivity sensitivity) const { - return m_argNames; -} + Q_ASSERT(m_loaded); -QVariantList ApiTraceCall::arguments() const -{ - return m_argValues; -} + int callIndex = 0; -QVariant ApiTraceCall::returnValue() const -{ - return m_returnValue; -} + if (from) { + callIndex = m_calls.indexOf(from) + 1; + } -QUrl ApiTraceCall::helpUrl() const -{ - return m_helpUrl; + for (int i = callIndex; i < m_calls.count(); ++i) { + ApiTraceCall *call = m_calls[i]; + if (call->contains(str, sensitivity)) { + return call; + } + } + return 0; } -ApiTraceCall::ApiTraceCall(const Trace::Call *call) - : ApiTraceEvent(ApiTraceEvent::Call), - m_hasBinaryData(false), - m_binaryDataIndex(0) +ApiTraceCall * +ApiTraceFrame::findPrevCall(ApiTraceCall *from, + const QString &str, + Qt::CaseSensitivity sensitivity) const { - m_name = QString::fromStdString(call->sig->name); - m_index = call->no; + Q_ASSERT(m_loaded); - 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(call->args[i]); - if (b && b->blob()) { - char *buf = (char*)b->blob(); - delete [] buf; - } + int callIndex = m_calls.count() - 1; + if (from) { + callIndex = m_calls.indexOf(from) - 1; } -} -void ApiTraceCall::setHelpUrl(const QUrl &url) -{ - m_helpUrl = url; + for (int i = callIndex; i >= 0; --i) { + ApiTraceCall *call = m_calls[i]; + if (call->contains(str, sensitivity)) { + return call; + } + } + return 0; } -void ApiTraceCall::setParentFrame(ApiTraceFrame *frame) +void ApiTraceFrame::setLastCallIndex(unsigned index) { - m_parentFrame = frame; + m_lastCallIndex = index; } -ApiTraceFrame * ApiTraceCall::parentFrame()const +unsigned ApiTraceFrame::lastCallIndex() const { - return m_parentFrame; + if (m_loaded && !m_calls.isEmpty()) { + return m_calls.last()->index(); + } else { + return m_lastCallIndex; + } } -ApiTraceEvent::~ApiTraceEvent() +void ApiTraceFrame::setThumbnail(const QImage & thumbnail) { - delete m_staticText; + m_thumbnail = thumbnail; } -void ApiTraceCall::revert() +const QImage & ApiTraceFrame::thumbnail() const { + return m_thumbnail; } -