From 9106537b9d36c50e97375fda7788e6128a1adda0 Mon Sep 17 00:00:00 2001 From: Zack Rusin Date: Sat, 26 Mar 2011 01:54:10 -0400 Subject: [PATCH] A lot better data conversions. --- gui/CMakeLists.txt | 2 + gui/apitracecall.cpp | 226 +++++++++++++++++++++++++++++++++++++++++ gui/apitracecall.h | 93 +++++++++++++++++ gui/apitracefilter.cpp | 33 ++++++ gui/apitracefilter.h | 18 ++++ gui/apitracemodel.cpp | 103 ++++--------------- gui/mainwindow.cpp | 3 + gui/mainwindow.h | 2 + 8 files changed, 394 insertions(+), 86 deletions(-) create mode 100644 gui/apitracecall.cpp create mode 100644 gui/apitracefilter.cpp create mode 100644 gui/apitracefilter.h diff --git a/gui/CMakeLists.txt b/gui/CMakeLists.txt index 466847c..3a6ef75 100644 --- a/gui/CMakeLists.txt +++ b/gui/CMakeLists.txt @@ -1,4 +1,6 @@ set(qapitrace_SRCS + apitracecall.cpp + apitracefilter.cpp apitracemodel.cpp loaderthread.cpp mainwindow.cpp diff --git a/gui/apitracecall.cpp b/gui/apitracecall.cpp new file mode 100644 index 0000000..679ee5c --- /dev/null +++ b/gui/apitracecall.cpp @@ -0,0 +1,226 @@ +#include "apitracecall.h" + +#include "trace_model.hpp" + +#include + +ApiPointer::ApiPointer(int val) + : m_value(val) +{ +} + +QString ApiPointer::toString() const +{ + if (m_value) + return QString("0x%1").arg(m_value, 0, 16); + else + return QLatin1String("NULL"); +} + +QString apiVariantToString(const QVariant &variant) +{ + if (variant.userType() == QVariant::Double) { + return QString::number(variant.toFloat()); + } + + if (variant.userType() < QVariant::UserType) { + return variant.toString(); + } + + if (variant.canConvert()) { + return variant.value().toString(); + } + if (variant.canConvert()) { + return variant.value().toString(); + } + if (variant.canConvert()) { + return variant.value().toString(); + } + if (variant.canConvert()) { + return variant.value().toString(); + } + + return QString(); +} + +ApiBitmask::ApiBitmask(const Trace::Bitmask *bitmask) + : m_value(0) +{ + init(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); + QPair pair; + + pair.first = QString::fromStdString(it->first); + pair.second = it->second; + + m_sig.append(pair); + } +} + +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) { + if (!first) { + str += QLatin1String(" | "); + } + str += it->first; + value &= ~it->second; + first = false; + } + } + if (value || first) { + if (!first) { + str += QLatin1String(" | "); + } + str += QString::fromLatin1("0x%1").arg(value, 0, 16); + } + return str; +} + +ApiStruct::ApiStruct(const Trace::Struct *s) +{ + init(s); +} + +QString ApiStruct::toString() const +{ + QString str; + + str += QLatin1String("{"); + for (unsigned i = 0; i < m_members.count(); ++i) { + str += m_sig.memberNames[i]; + str += QLatin1String(" = "); + str += apiVariantToString(m_members[i]); + 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->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()); + } +} + +void VariantVisitor::visit(Trace::Null *) +{ + m_variant = QVariant(QLatin1String("NULL")); +} + +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::String *node) +{ + m_variant = QVariant(QString::fromStdString(node->value)); +} + +void VariantVisitor::visit(Trace::Enum *e) +{ + m_variant = QVariant(QString::fromStdString(e->sig->first)); +} + +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::fromRawData(blob->buf, blob->size); + m_variant = QVariant(barray); +} + +void VariantVisitor::visit(Trace::Pointer *ptr) +{ + m_variant = QVariant::fromValue(ApiPointer(ptr->value)); +} + +ApiArray::ApiArray(const Trace::Array *arr) +{ + init(arr); +} + +QString ApiArray::toString() 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 str; +} + +void ApiArray::init(const Trace::Array *arr) +{ + if (!arr) + return; + + for (int i = 0; i < arr->values.size(); ++i) { + VariantVisitor vis; + arr->values[i]->visit(vis); + + m_array.append(vis.variant()); + } +} diff --git a/gui/apitracecall.h b/gui/apitracecall.h index 6474663..8dffb27 100644 --- a/gui/apitracecall.h +++ b/gui/apitracecall.h @@ -4,6 +4,99 @@ #include #include +#include "trace_model.hpp" + + +class VariantVisitor : public Trace::Visitor +{ +public: + virtual void visit(Trace::Null *); + virtual void visit(Trace::Bool *node); + virtual void visit(Trace::SInt *node); + virtual void visit(Trace::UInt *node); + virtual void visit(Trace::Float *node); + virtual void visit(Trace::String *node); + virtual void visit(Trace::Enum *e); + virtual void visit(Trace::Bitmask *bitmask); + virtual void visit(Trace::Struct *str); + virtual void visit(Trace::Array *array); + virtual void visit(Trace::Blob *blob); + virtual void visit(Trace::Pointer *ptr); + + QVariant variant() const + { + return m_variant; + } +private: + QVariant m_variant; +}; + + +class ApiPointer +{ +public: + ApiPointer(int val=0); + + QString toString() const; +private: + int m_value; +}; +Q_DECLARE_METATYPE(ApiPointer); + +class ApiBitmask +{ +public: + typedef QList > Signature; + + ApiBitmask(const Trace::Bitmask *bitmask = 0); + + QString toString() const; + +private: + void init(const Trace::Bitmask *bitmask); +private: + Signature m_sig; + unsigned long long m_value; +}; +Q_DECLARE_METATYPE(ApiBitmask); + +class ApiStruct +{ +public: + struct Signature { + QString name; + QStringList memberNames; + }; + + ApiStruct(const Trace::Struct *s = 0); + + QString toString() const; + +private: + void init(const Trace::Struct *bitmask); +private: + Signature m_sig; + QList m_members; +}; +Q_DECLARE_METATYPE(ApiStruct); + +class ApiArray +{ +public: + ApiArray(const Trace::Array *arr = 0); + + QString toString() const; + +private: + void init(const Trace::Array *arr); +private: + QList m_array; +}; +Q_DECLARE_METATYPE(ApiArray); + + +QString apiVariantToString(const QVariant &variant); + class ApiTraceCall { public: diff --git a/gui/apitracefilter.cpp b/gui/apitracefilter.cpp new file mode 100644 index 0000000..3aa5ef8 --- /dev/null +++ b/gui/apitracefilter.cpp @@ -0,0 +1,33 @@ +#include "apitracefilter.h" + +#include "apitracecall.h" + +ApiTraceFilter::ApiTraceFilter(QObject *parent ) + : QSortFilterProxyModel() +{ +} + +bool ApiTraceFilter::filterAcceptsRow(int sourceRow, + const QModelIndex &sourceParent) const +{ + QModelIndex index0 = sourceModel()->index(sourceRow, 0, sourceParent); + QModelIndex index1 = sourceModel()->index(sourceRow, 1, sourceParent); + QModelIndex index2 = sourceModel()->index(sourceRow, 2, sourceParent); + QString function = sourceModel()->data(index0).toString(); + QString arguments = sourceModel()->data(index1).toString(); + + //XXX make it configurable + if (function.contains(QLatin1String("glXGetProcAddress"))) + return false; + if (function.contains(QLatin1String("wglGetProcAddress"))) + return false; + + if (function.contains(QLatin1String("glGetString")) && + arguments.contains(QLatin1String("GL_EXTENSIONS"))) + return false; + + return true; +} + + +#include "apitracefilter.moc" diff --git a/gui/apitracefilter.h b/gui/apitracefilter.h new file mode 100644 index 0000000..c19a5e2 --- /dev/null +++ b/gui/apitracefilter.h @@ -0,0 +1,18 @@ +#ifndef APITRACEFILTER_H +#define APITRACEFILTER_H + +#include + +//! [0] +class ApiTraceFilter : public QSortFilterProxyModel +{ + Q_OBJECT + +public: + ApiTraceFilter(QObject *parent = 0); + +protected: + bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const; +}; + +#endif diff --git a/gui/apitracemodel.cpp b/gui/apitracemodel.cpp index 826a35b..f635294 100644 --- a/gui/apitracemodel.cpp +++ b/gui/apitracemodel.cpp @@ -4,87 +4,15 @@ #include "loaderthread.h" #include "trace_parser.hpp" +#include #include -class VariantVisitor : public Trace::Visitor -{ -public: - virtual void visit(Trace::Null *) - { - // Nothing - } - virtual void visit(Trace::Bool *node) - { - m_variant = QVariant(node->value); - } - virtual void visit(Trace::SInt *node) - { - m_variant = QVariant(node->value); - } - virtual void visit(Trace::UInt *node) - { - m_variant = QVariant(node->value); - } - virtual void visit(Trace::Float *node) - { - m_variant = QVariant(node->value); - } - virtual void visit(Trace::String *node) - { - m_variant = QVariant(QString::fromStdString(node->value)); - } - virtual void visit(Trace::Enum *e) - { - m_variant = QVariant(QString::fromStdString(e->sig->first)); - } - virtual void visit(Trace::Bitmask *bitmask) - { - //XXX we should probably convert it to QImage - visit(static_cast(bitmask)); - } - virtual void visit(Trace::Struct *str) - { - //XXX: need a custom QVariant type for this one - QVariantList lst; - for (int i = 0; i < str->members.size(); ++i) { - VariantVisitor vst; - str->members[i]->visit(vst); - lst.append(vst.variant()); - } - m_variant = QVariant(lst); - } - virtual void visit(Trace::Array *array) - { - QVariantList lst; - for (int i = 0; i < array->values.size(); ++i) { - VariantVisitor vst; - array->values[i]->visit(vst); - lst.append(vst.variant()); - } - m_variant = QVariant(lst); - } - virtual void visit(Trace::Blob *blob) - { - QByteArray barray = QByteArray::fromRawData(blob->buf, blob->size); - m_variant = QVariant(barray); - } - virtual void visit(Trace::Pointer *ptr) - { - m_variant = QVariant(ptr->value); - } - - QVariant variant() const - { - return m_variant; - } -private: - QVariant m_variant; -}; ApiTraceModel::ApiTraceModel(QObject *parent) : QAbstractItemModel(parent) { m_loader = new LoaderThread(); + connect(m_loader, SIGNAL(parsedCalls(const QList&)), SLOT(appendCalls(const QList&))); } @@ -109,21 +37,27 @@ QVariant ApiTraceModel::data(const QModelIndex &index, int role) const return QVariant(); switch (index.column()) { - case 0: - return item->name; - case 1: { + case 0: { QString str; + str += QString::number(index.row()); + str += QLatin1String(") "); + str += item->name; + str += QLatin1String("("); for (int i = 0; i < item->argNames.count(); ++i) { str += item->argNames[i]; str += QString::fromLatin1(" = "); - str += item->argValues[i].toString(); + str += apiVariantToString(item->argValues[i]); if (i < item->argNames.count() - 1) str += QString::fromLatin1(", "); } + str += QLatin1String(")"); + + if (item->returnValue.isValid()) { + str += QLatin1String(" = "); + str += apiVariantToString(item->returnValue); + } return str; } - case 2: - return item->returnValue.toString(); default: return QVariant(); } @@ -144,10 +78,6 @@ QVariant ApiTraceModel::headerData(int section, Qt::Orientation orientation, switch (section) { case 0: return tr("Function"); - case 1: - return tr("Arguments"); - case 2: - return tr("Return"); default: //fall through break; @@ -192,7 +122,7 @@ int ApiTraceModel::rowCount(const QModelIndex &parent) const int ApiTraceModel::columnCount(const QModelIndex &parent) const { - return parent.isValid() ? 0 : 3; + return parent.isValid() ? 0 : 1; } @@ -247,8 +177,8 @@ void ApiTraceModel::appendCalls(const QList traceCalls) apiCall->argNames += QString::fromStdString(call->sig->arg_names[i]); } - VariantVisitor retVisitor; if (call->ret) { + VariantVisitor retVisitor; call->ret->visit(retVisitor); apiCall->returnValue = retVisitor.variant(); } @@ -257,6 +187,7 @@ void ApiTraceModel::appendCalls(const QList traceCalls) call->args[i]->visit(argVisitor); apiCall->argValues += argVisitor.variant(); } + m_calls.append(apiCall); } endInsertRows(); diff --git a/gui/mainwindow.cpp b/gui/mainwindow.cpp index d04b61d..05dbb63 100644 --- a/gui/mainwindow.cpp +++ b/gui/mainwindow.cpp @@ -1,6 +1,7 @@ #include "mainwindow.h" #include "apitracemodel.h" +#include "apitracefilter.h" #include #include @@ -14,6 +15,8 @@ MainWindow::MainWindow() m_ui.setupUi(this); m_model = new ApiTraceModel(); + m_proxyModel = new ApiTraceFilter(); + m_proxyModel->setSourceModel(m_model); m_ui.callView->setModel(m_model); for (int column = 0; column < m_model->columnCount(); ++column) m_ui.callView->resizeColumnToContents(column); diff --git a/gui/mainwindow.h b/gui/mainwindow.h index e7107f5..a7c942b 100644 --- a/gui/mainwindow.h +++ b/gui/mainwindow.h @@ -6,6 +6,7 @@ #include class ApiTraceModel; +class ApiTraceFilter; class MainWindow : public QMainWindow { @@ -22,6 +23,7 @@ private slots: private: Ui_MainWindow m_ui; ApiTraceModel *m_model; + ApiTraceFilter *m_proxyModel; }; -- 2.43.0