+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_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) {
+ VariantVisitor argVisitor(loader);
+ call->args[i]->visit(argVisitor);
+ m_argValues.append(argVisitor.variant());
+ if (m_argValues[i].type() == QVariant::ByteArray) {
+ m_hasBinaryData = true;
+ m_binaryDataIndex = i;
+ }
+ }
+ m_argValues.squeeze();
+}
+
+ApiTraceCall::~ApiTraceCall()
+{
+}
+
+
+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();
+ }
+}
+
+ApiTrace * ApiTraceCall::parentTrace() const
+{
+ if (m_parentFrame)
+ return m_parentFrame->parentTrace();
+ return NULL;
+}
+
+QVector<QVariant> ApiTraceCall::originalValues() const
+{
+ return m_argValues;
+}
+
+void ApiTraceCall::setEditedValues(const QVector<QVariant> &lst)
+{
+ 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);
+ }
+ }
+}
+
+QVector<QVariant> ApiTraceCall::editedValues() const
+{
+ return m_editedValues;
+}
+
+bool ApiTraceCall::edited() const
+{
+ return !m_editedValues.isEmpty();
+}
+
+void ApiTraceCall::revert()
+{
+ setEditedValues(QVector<QVariant>());
+}
+
+void ApiTraceCall::setHelpUrl(const QUrl &url)
+{
+ m_signature->setHelpUrl(url);
+}
+
+void ApiTraceCall::setParentFrame(ApiTraceFrame *frame)
+{
+ m_parentFrame = frame;
+}
+
+ApiTraceFrame * ApiTraceCall::parentFrame()const
+{
+ return m_parentFrame;
+}
+
+int ApiTraceCall::index() const
+{
+ return m_index;
+}
+
+QString ApiTraceCall::name() const
+{
+ return m_signature->name();
+}
+
+QStringList ApiTraceCall::argNames() const
+{
+ return m_signature->argNames();
+}
+
+QVector<QVariant> 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_signature->helpUrl();
+}
+
+bool ApiTraceCall::hasBinaryData() const
+{
+ return m_hasBinaryData;
+}
+
+int ApiTraceCall::binaryDataIndex() const
+{
+ return m_binaryDataIndex;
+}
+
+QStaticText ApiTraceCall::staticText() const
+{
+ if (m_staticText && !m_staticText->text().isEmpty())
+ return *m_staticText;
+
+ QVector<QVariant> argValues = arguments();
+
+ QString richText = QString::fromLatin1(
+ "<span style=\"font-weight:bold\">%1</span>(").arg(
+ m_signature->name());
+ QStringList argNames = m_signature->argNames();
+ for (int i = 0; i < argNames.count(); ++i) {
+ richText += QLatin1String("<span style=\"color:#0000ff\">");
+ QString argText = apiVariantToString(argValues[i]);
+
+ //if arguments are really long (e.g. shader text), cut them
+ // and elide it
+ if (argText.length() > 40) {
+ QString shortened = argText.mid(0, 40);
+ shortened[argText.length() - 5] = '.';
+ shortened[argText.length() - 4] = '.';
+ shortened[argText.length() - 3] = '.';
+ 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("</span>");
+ if (i < argNames.count() - 1)
+ richText += QLatin1String(", ");
+ }
+ richText += QLatin1String(")");
+ if (m_returnValue.isValid()) {
+ richText +=
+ QLatin1Literal(" = ") %
+ QLatin1Literal("<span style=\"color:#0000ff\">") %
+ apiVariantToString(m_returnValue) %
+ QLatin1Literal("</span>");
+ }
+
+ if (!m_staticText)
+ m_staticText = new QStaticText(richText);
+ else
+ m_staticText->setText(richText);
+ QTextOption opt;
+ opt.setWrapMode(QTextOption::NoWrap);
+ m_staticText->setTextOption(opt);
+ m_staticText->prepare();
+
+ return *m_staticText;
+}
+
+QString ApiTraceCall::toHtml() const
+{
+ if (!m_richText.isEmpty())
+ return m_richText;
+
+ m_richText = QLatin1String("<div class=\"call\">");
+
+ QUrl helpUrl = m_signature->helpUrl();
+ if (helpUrl.isEmpty()) {
+ m_richText += QString::fromLatin1(
+ "%1) <span class=\"callName\">%2</span>(")
+ .arg(m_index)
+ .arg(m_signature->name());
+ } else {
+ m_richText += QString::fromLatin1(
+ "%1) <span class=\"callName\"><a href=\"%2\">%3</a></span>(")
+ .arg(m_index)
+ .arg(helpUrl.toString())
+ .arg(m_signature->name());
+ }
+
+ QVector<QVariant> argValues = arguments();
+ QStringList argNames = m_signature->argNames();
+ for (int i = 0; i < argNames.count(); ++i) {
+ m_richText +=
+ QLatin1String("<span class=\"arg-name\">") +
+ argNames[i] +
+ QLatin1String("</span>") +
+ QLatin1Literal(" = ") +
+ QLatin1Literal("<span class=\"arg-value\">") +
+ apiVariantToString(argValues[i], true) +
+ QLatin1Literal("</span>");
+ if (i < argNames.count() - 1)
+ m_richText += QLatin1String(", ");
+ }
+ m_richText += QLatin1String(")");
+
+ if (m_returnValue.isValid()) {
+ m_richText +=
+ QLatin1String(" = ") +
+ QLatin1String("<span style=\"color:#0000ff\">") +
+ apiVariantToString(m_returnValue, true) +
+ QLatin1String("</span>");
+ }
+ m_richText += QLatin1String("</div>");
+
+ if (hasError()) {
+ QString errorStr =
+ QString::fromLatin1(
+ "<div class=\"error\">%1</div>")
+ .arg(m_error);
+ m_richText += errorStr;
+ }
+
+ m_richText =
+ QString::fromLatin1(
+ "<html><head><style type=\"text/css\" media=\"all\">"
+ "%1</style></head><body>%2</body></html>")
+ .arg(styleSheet)
+ .arg(m_richText);
+ m_richText.squeeze();
+
+ //qDebug()<<m_richText;
+ return m_richText;
+}
+
+QString ApiTraceCall::searchText() const
+{
+ if (!m_searchText.isEmpty())
+ return m_searchText;
+
+ QVector<QVariant> 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(argValues[i]);
+ if (i < argNames.count() - 1)
+ m_searchText += QLatin1String(", ");
+ }
+ m_searchText += QLatin1String(")");
+
+ if (m_returnValue.isValid()) {
+ m_searchText += QLatin1Literal(" = ") +
+ apiVariantToString(m_returnValue);
+ }
+ m_searchText.squeeze();
+ return m_searchText;
+}
+
+int ApiTraceCall::numChildren() const
+{
+ return 0;
+}
+
+bool ApiTraceCall::contains(const QString &str,
+ Qt::CaseSensitivity sensitivity) const
+{
+ QString txt = searchText();
+ return txt.contains(str, sensitivity);
+}
+
+
+ApiTraceFrame::ApiTraceFrame(ApiTrace *parentTrace)
+ : ApiTraceEvent(ApiTraceEvent::Frame),
+ m_parentTrace(parentTrace),
+ m_binaryDataSize(0),
+ m_loaded(false),
+ m_callsToLoad(0),
+ m_lastCallIndex(0)
+{
+}
+
+ApiTraceFrame::~ApiTraceFrame()
+{
+ qDeleteAll(m_calls);
+}
+
+QStaticText ApiTraceFrame::staticText() const
+{
+ if (m_staticText && !m_staticText->text().isEmpty())
+ return *m_staticText;
+
+ QString richText = QObject::tr(
+ "<span style=\"font-weight:bold\">Frame %1</span>"
+ " "
+ "<span style=\"font-style:italic;font-size:small;font-weight:lighter;\"> "
+ "(%2 calls)</span>")
+ .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"
+ "<span style=\"font-style:italic;\">"
+ " (%2MB)</span>")
+ .arg(richText)
+ .arg(double(m_binaryDataSize / (1024.*1024.)), 0, 'g', 2);
+ }
+
+ if (!m_staticText)
+ m_staticText = new QStaticText(richText);
+
+ QTextOption opt;
+ opt.setWrapMode(QTextOption::NoWrap);
+ m_staticText->setTextOption(opt);
+ m_staticText->prepare();
+
+ return *m_staticText;
+}
+
+int ApiTraceFrame::numChildren() const
+{
+ return m_calls.count();
+}
+
+ApiTrace * ApiTraceFrame::parentTrace() const
+{
+ return m_parentTrace;
+}
+
+void ApiTraceFrame::addCall(ApiTraceCall *call)
+{
+ m_calls.append(call);
+ if (call->hasBinaryData()) {
+ QByteArray data =
+ call->arguments()[call->binaryDataIndex()].toByteArray();
+ m_binaryDataSize += data.size();
+ }
+}
+
+QVector<ApiTraceCall*> ApiTraceFrame::calls() const
+{
+ return m_calls;
+}
+
+ApiTraceCall * ApiTraceFrame::call(int idx) const
+{
+ return m_calls.value(idx);
+}
+
+
+ApiTraceCall * ApiTraceFrame::callWithIndex(int index) const
+{
+ QVector<ApiTraceCall*>::const_iterator itr;
+ for (itr = m_calls.constBegin(); itr != m_calls.constEnd(); ++itr) {
+ if ((*itr)->index() == index) {
+ return *itr;
+ }
+ }
+ return 0;
+}
+
+int ApiTraceFrame::callIndex(ApiTraceCall *call) const
+{
+ return m_calls.indexOf(call);
+}
+
+bool ApiTraceFrame::isEmpty() const
+{
+ if (m_loaded) {
+ return m_calls.isEmpty();
+ } else {
+ return m_callsToLoad == 0;
+ }
+}
+
+int ApiTraceFrame::binaryDataSize() const
+{
+ return m_binaryDataSize;
+}
+
+void ApiTraceFrame::setCalls(const QVector<ApiTraceCall*> &calls,
+ quint64 binaryDataSize)
+{
+ m_calls = calls;
+ m_binaryDataSize = binaryDataSize;
+ m_loaded = true;
+ delete m_staticText;
+ m_staticText = 0;
+}
+
+bool ApiTraceFrame::isLoaded() const
+{
+ return m_loaded;
+}
+
+void ApiTraceFrame::setLoaded(bool l)
+{
+ m_loaded = l;
+}
+
+void ApiTraceFrame::setNumChildren(int num)
+{
+ m_callsToLoad = num;
+}
+
+void ApiTraceFrame::setParentTrace(ApiTrace *parent)
+{
+ m_parentTrace = parent;
+}
+
+int ApiTraceFrame::numChildrenToLoad() const
+{
+ return m_callsToLoad;
+}
+
+ApiTraceCall *
+ApiTraceFrame::findNextCall(ApiTraceCall *from,
+ const QString &str,
+ Qt::CaseSensitivity sensitivity) const
+{
+ Q_ASSERT(m_loaded);
+
+ int callIndex = 0;
+
+ if (from) {
+ callIndex = m_calls.indexOf(from) + 1;
+ }
+
+ for (int i = callIndex; i < m_calls.count(); ++i) {
+ ApiTraceCall *call = m_calls[i];
+ if (call->contains(str, sensitivity)) {
+ return call;
+ }
+ }
+ return 0;
+}
+
+ApiTraceCall *
+ApiTraceFrame::findPrevCall(ApiTraceCall *from,
+ const QString &str,
+ Qt::CaseSensitivity sensitivity) const
+{
+ Q_ASSERT(m_loaded);
+
+ int callIndex = m_calls.count() - 1;
+
+ if (from) {
+ callIndex = m_calls.indexOf(from) - 1;
+ }
+
+ for (int i = callIndex; i >= 0; --i) {
+ ApiTraceCall *call = m_calls[i];
+ if (call->contains(str, sensitivity)) {
+ return call;
+ }
+ }
+ return 0;
+}
+
+void ApiTraceFrame::setLastCallIndex(unsigned index)
+{
+ m_lastCallIndex = index;
+}
+
+unsigned ApiTraceFrame::lastCallIndex() const
+{
+ if (m_loaded && !m_calls.isEmpty()) {
+ return m_calls.last()->index();
+ } else {
+ return m_lastCallIndex;