]> git.cworth.org Git - apitrace/commitdiff
Introduce ApiTrace which encapsulates the data.
authorZack Rusin <zack@kde.org>
Wed, 30 Mar 2011 15:03:37 +0000 (11:03 -0400)
committerZack Rusin <zack@kde.org>
Thu, 31 Mar 2011 02:48:42 +0000 (22:48 -0400)
allows us to split calls into frames and do other postprocessing.

16 files changed:
gui/CMakeLists.txt
gui/apicalldelegate.cpp
gui/apicalldelegate.h
gui/apitrace.cpp [new file with mode: 0644]
gui/apitrace.h [new file with mode: 0644]
gui/apitracecall.cpp
gui/apitracecall.h
gui/apitracefilter.cpp
gui/apitracemodel.cpp
gui/apitracemodel.h
gui/loaderthread.cpp
gui/loaderthread.h
gui/main.cpp
gui/mainwindow.cpp
gui/mainwindow.h
gui/ui/mainwindow.ui

index 86f60d95521ff35e1ddbdd0a951a5065f404f128..12ed63ed232bcbf0afb6ddbdef41133bea4e6a6e 100644 (file)
@@ -1,4 +1,5 @@
 set(qapitrace_SRCS
+   apitrace.cpp
    apicalldelegate.cpp
    apitracecall.cpp
    apitracefilter.cpp
index a681c7549008b84fab16385831c7cfcdb4e8ab8e..5376c0dcdb3d266a5964ffafb230b0c252945ae0 100644 (file)
@@ -12,7 +12,8 @@ ApiCallDelegate::ApiCallDelegate(QWidget *parent)
 {
 }
 
-void ApiCallDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option,
+void ApiCallDelegate::paint(QPainter *painter,
+                            const QStyleOptionViewItem &option,
                             const QModelIndex &index) const
 {
     ApiTraceCall *call = index.data().value<ApiTraceCall*>();
@@ -21,8 +22,16 @@ void ApiCallDelegate::paint(QPainter *painter, const QStyleOptionViewItem &optio
         //text.setTextWidth(option.rect.width());
         QStyledItemDelegate::paint(painter, option, index);
         painter->drawStaticText(option.rect.topLeft(), text);
-    } else{
-        QStyledItemDelegate::paint(painter, option, index);
+    } else {
+        ApiTraceFrame *frame = index.data().value<ApiTraceFrame*>();
+        if (frame) {
+            QStaticText text = frame->staticText();
+            //text.setTextWidth(option.rect.width());
+            QStyledItemDelegate::paint(painter, option, index);
+            painter->drawStaticText(option.rect.topLeft(), text);
+        } else {
+            QStyledItemDelegate::paint(painter, option, index);
+        }
     }
 }
 
@@ -34,6 +43,13 @@ QSize ApiCallDelegate::sizeHint(const QStyleOptionViewItem &option,
         QStaticText text = call->staticText();
         //text.setTextWidth(option.rect.width());
         return text.size().toSize();
+    } else {
+        ApiTraceFrame *frame = index.data().value<ApiTraceFrame*>();
+        if (frame) {
+            QStaticText text = frame->staticText();
+            //text.setTextWidth(option.rect.width());
+            return text.size().toSize();
+        }
     }
     return QStyledItemDelegate::sizeHint(option, index);
 }
index 03298399221c7c5dd1a85e1f790b8662d910544d..a29a1784d6dc6560f751e0dae8fba7f26c4bd96e 100644 (file)
@@ -1,8 +1,6 @@
 #ifndef APICALLDELEGATE_H
 #define APICALLDELEGATE_H
 
-
-
 #include <QStyledItemDelegate>
 
 class ApiCallDelegate : public QStyledItemDelegate
diff --git a/gui/apitrace.cpp b/gui/apitrace.cpp
new file mode 100644 (file)
index 0000000..51e83b2
--- /dev/null
@@ -0,0 +1,169 @@
+#include "apitrace.h"
+
+#include "loaderthread.h"
+
+ApiTrace::ApiTrace()
+    : m_frameMarker(ApiTrace::FrameMarker_SwapBuffers)
+{
+    m_loader = new LoaderThread(this);
+    connect(m_loader, SIGNAL(parsedFrames(const QList<ApiTraceFrame*>)),
+            this, SLOT(addFrames(const QList<ApiTraceFrame*>)));
+}
+
+ApiTrace::~ApiTrace()
+{
+    qDeleteAll(m_calls);
+    qDeleteAll(m_frames);
+    delete m_loader;
+}
+
+bool ApiTrace::isCallAFrameMarker(const ApiTraceCall *call,
+                                  ApiTrace::FrameMarker marker)
+{
+    if (!call)
+        return false;
+
+    switch (marker) {
+    case FrameMarker_SwapBuffers:
+        return call->name.contains(QLatin1String("SwapBuffers"));
+    case FrameMarker_Flush:
+        return call->name == QLatin1String("glFlush");
+    case FrameMarker_Finish:
+        return call->name == QLatin1String("glFinish");
+    case FrameMarker_Clear:
+        return call->name == QLatin1String("glClear");
+    }
+
+    Q_ASSERT(!"unknown frame marker");
+
+    return false;
+}
+
+bool ApiTrace::isEmpty() const
+{
+    return m_calls.isEmpty();
+}
+
+QString ApiTrace::fileName() const
+{
+    return m_fileName;
+}
+
+ApiTrace::FrameMarker ApiTrace::frameMarker() const
+{
+    return m_frameMarker;
+}
+
+QList<ApiTraceCall*> ApiTrace::calls() const
+{
+    return m_calls;
+}
+
+ApiTraceCall * ApiTrace::callAt(int idx) const
+{
+    return m_calls.value(idx);
+}
+
+int ApiTrace::numCalls() const
+{
+    return m_calls.count();
+}
+
+QList<ApiTraceFrame*> ApiTrace::frames() const
+{
+    return m_frames;
+}
+
+ApiTraceFrame * ApiTrace::frameAt(int idx) const
+{
+    return m_frames.value(idx);
+}
+
+int ApiTrace::numFrames() const
+{
+    return m_frames.count();
+}
+
+int ApiTrace::numCallsInFrame(int idx) const
+{
+    const ApiTraceFrame *frame = frameAt(idx);
+    if (frame)
+        return frame->calls.count();
+    else
+        return 0;
+}
+
+void ApiTrace::setFileName(const QString &name)
+{
+    if (m_fileName != name) {
+        m_fileName = name;
+
+        if (m_loader->isRunning()) {
+            m_loader->terminate();
+            m_loader->wait();
+        }
+        emit invalidated();
+
+        m_loader->loadFile(m_fileName);
+    }
+}
+
+void ApiTrace::setFrameMarker(FrameMarker marker)
+{
+    if (m_frameMarker != marker) {
+        emit framesInvalidated();
+
+        qDeleteAll(m_frames);
+        m_frames.clear();
+        detectFrames();
+    }
+}
+
+void ApiTrace::addFrames(const QList<ApiTraceFrame*> &frames)
+{
+    int currentFrames = m_frames.count();
+    int numNewFrames = frames.count();
+    m_frames += frames;
+
+    int currentCalls = m_calls.count();
+    int numNewCalls = 0;
+    foreach(ApiTraceFrame *frame, frames) {
+        numNewCalls += frame->calls.count();
+        m_calls += frame->calls;
+    }
+
+    emit framesAdded(currentFrames, numNewFrames);
+    emit callsAdded(currentCalls, numNewCalls);
+}
+
+void ApiTrace::detectFrames()
+{
+    if (m_calls.isEmpty())
+        return;
+
+    ApiTraceFrame *currentFrame = 0;
+    foreach(ApiTraceCall *apiCall, m_calls) {
+        if (!currentFrame) {
+            currentFrame = new ApiTraceFrame();
+            currentFrame->number = m_frames.count();
+        }
+        apiCall->parentFrame = currentFrame;
+        apiCall->index = currentFrame->calls.count();
+        currentFrame->calls.append(apiCall);
+        if (ApiTrace::isCallAFrameMarker(apiCall,
+                                         m_frameMarker)) {
+            m_frames.append(currentFrame);
+            currentFrame = 0;
+        }
+    }
+    //last frames won't have markers
+    //  it's just a bunch of Delete calls for every object
+    //  after the last SwapBuffers
+    if (currentFrame) {
+        m_frames.append(currentFrame);
+        currentFrame = 0;
+    }
+    emit framesAdded(0, m_frames.count());
+}
+
+#include "apitrace.moc"
diff --git a/gui/apitrace.h b/gui/apitrace.h
new file mode 100644 (file)
index 0000000..c400deb
--- /dev/null
@@ -0,0 +1,67 @@
+#ifndef APITRACE_H
+#define APITRACE_H
+
+#include "apitracecall.h"
+
+#include <QObject>
+
+class LoaderThread;
+
+class ApiTrace : public QObject
+{
+    Q_OBJECT
+public:
+    enum FrameMarker {
+        FrameMarker_SwapBuffers,
+        FrameMarker_Flush,
+        FrameMarker_Finish,
+        FrameMarker_Clear
+    };
+    static bool isCallAFrameMarker(const ApiTraceCall *call,
+                                   FrameMarker marker);
+public:
+    ApiTrace();
+    ~ApiTrace();
+
+    bool isEmpty() const;
+
+    QString fileName() const;
+
+    FrameMarker frameMarker() const;
+
+    QList<ApiTraceCall*> calls() const;
+    ApiTraceCall *callAt(int idx) const;
+    int numCalls() const;
+
+    QList<ApiTraceFrame*> frames() const;
+    ApiTraceFrame *frameAt(int idx) const;
+    int numFrames() const;
+    int numCallsInFrame(int idx) const;
+
+public slots:
+    void setFileName(const QString &name);
+    void setFrameMarker(FrameMarker marker);
+
+signals:
+    void invalidated();
+    void framesInvalidated();
+
+    void framesAdded(int oldCount, int numAdded);
+    void callsAdded(int oldCount, int numAdded);
+
+private slots:
+    void addFrames(const QList<ApiTraceFrame*> &frames);
+private:
+    void detectFrames();
+private:
+    QString m_fileName;
+
+    QList<ApiTraceFrame*> m_frames;
+    QList<ApiTraceCall*> m_calls;
+
+    FrameMarker m_frameMarker;
+
+    LoaderThread *m_loader;
+};
+
+#endif
index 313d9eae0cb964aa38c4ff2b55924e4a599aa9f5..b772b66846dff89c6790d1d9ab9915da75f62310 100644 (file)
@@ -296,3 +296,54 @@ QString ApiTraceCall::filterText() const
     }
     return m_filterText;
 }
+
+QStaticText ApiTraceFrame::staticText() const
+{
+    if (!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);
+    QTextOption opt;
+    opt.setWrapMode(QTextOption::NoWrap);
+    m_staticText.setTextOption(opt);
+    m_staticText.prepare();
+
+    return m_staticText;
+}
+
+int ApiTraceCall::numChildren() const
+{
+    return 0;
+}
+
+int ApiTraceFrame::numChildren() const
+{
+    return calls.count();
+}
+
+ApiTraceFrame::ApiTraceFrame()
+    : ApiTraceEvent(ApiTraceEvent::Frame)
+{
+}
+
+ApiTraceCall::ApiTraceCall()
+    : ApiTraceEvent(ApiTraceEvent::Call)
+{
+}
+
+ApiTraceEvent::ApiTraceEvent()
+    : m_type(ApiTraceEvent::None)
+{
+}
+
+ApiTraceEvent::ApiTraceEvent(Type t)
+    : m_type(t)
+{
+}
+
+ApiTraceCall::~ApiTraceCall()
+{
+}
index 8b925e8159829818f75a1171de63630c98ba3573..8f38bdaffa2c88490cda7e9ff767733ddf9c1e8e 100644 (file)
@@ -98,23 +98,68 @@ Q_DECLARE_METATYPE(ApiArray);
 
 QString apiVariantToString(const QVariant &variant);
 
-class ApiTraceCall
+class ApiTraceFrame;
+
+class ApiTraceEvent
 {
 public:
+    enum Type {
+        None,
+        Call,
+        Frame
+    };
+public:
+    ApiTraceEvent();
+    ApiTraceEvent(Type t);
+
+    Type type() const { return m_type; }
+
+    virtual QStaticText staticText() const = 0;
+    virtual int numChildren() const = 0;
+
+protected:
+    Type m_type;
+};
+Q_DECLARE_METATYPE(ApiTraceEvent*);
+
+class ApiTraceCall : public ApiTraceEvent
+{
+public:
+    ApiTraceCall();
+    ~ApiTraceCall();
+
+    int index;
     QString name;
     QStringList argNames;
     QVariantList argValues;
     QVariant returnValue;
+    ApiTraceFrame *parentFrame;
 
     QString toHtml() const;
     QString filterText() const;
     QStaticText staticText() const;
+    int numChildren() const;
 private:
     mutable QString m_richText;
     mutable QString m_filterText;
     mutable QStaticText m_staticText;
 };
-Q_DECLARE_METATYPE(ApiTraceCall);
 Q_DECLARE_METATYPE(ApiTraceCall*);
 
+class ApiTraceFrame : public ApiTraceEvent
+{
+public:
+    ApiTraceFrame();
+    int number;
+    QList<ApiTraceCall*> calls;
+
+
+    int numChildren() const;
+    QStaticText staticText() const;
+private:
+    mutable QStaticText m_staticText;
+};
+Q_DECLARE_METATYPE(ApiTraceFrame*);
+
+
 #endif
index 5542ea9528fe1978f9445fbca87efc9dff6ec3cc..24c56bf58876591b518811a9f583988f9beb4082 100644 (file)
@@ -4,7 +4,7 @@
 
 #include <QDebug>
 
-ApiTraceFilter::ApiTraceFilter(QObject *parent )
+ApiTraceFilter::ApiTraceFilter(QObject *parent)
     : QSortFilterProxyModel()
 {
 }
@@ -16,8 +16,10 @@ bool ApiTraceFilter::filterAcceptsRow(int sourceRow,
     QVariant varientData = sourceModel()->data(index0);
     ApiTraceCall *call = varientData.value<ApiTraceCall*>();
 
-    if (!call)
-        return false;
+    if (!call) {
+        ApiTraceFrame *frame = varientData.value<ApiTraceFrame*>();
+        return frame != 0;
+    }
 
     QString function = call->name;
 
index 0a31ce8fba45c908fa2e64ced005be3e8cd53930..c135bc15fac605d12a500dab081c3e0252b3bd2f 100644 (file)
@@ -9,18 +9,14 @@
 
 
 ApiTraceModel::ApiTraceModel(QObject *parent)
-    : QAbstractItemModel(parent)
+    : QAbstractItemModel(parent),
+      m_trace(0)
 {
-    m_loader = new LoaderThread();
-
-    connect(m_loader, SIGNAL(parsedCalls(const QList<Trace::Call*>&)),
-            SLOT(appendCalls(const QList<Trace::Call*>&)));
 }
 
 ApiTraceModel::~ApiTraceModel()
 {
-    qDeleteAll(m_calls);
-    delete m_loader;
+    m_trace = 0;
 }
 
 QVariant ApiTraceModel::data(const QModelIndex &index, int role) const
@@ -31,18 +27,24 @@ QVariant ApiTraceModel::data(const QModelIndex &index, int role) const
     if (role != Qt::DisplayRole)
         return QVariant();
 
-    ApiTraceCall *item = m_calls.value(index.row());
-
-    if (!item)
+    //data only in the first column
+    if (index.column() != 0)
         return QVariant();
 
-    switch (index.column()) {
-    case 0: {
-        return QVariant::fromValue(item);
-    }
-    default:
-        return QVariant();
+    ApiTraceEvent *itm = item(index);
+    if (itm) {
+        if (itm->type() == ApiTraceEvent::Frame) {
+            ApiTraceFrame *frame =
+                static_cast<ApiTraceFrame *>(itm);
+            return QVariant::fromValue(frame);
+        } else if (itm->type() == ApiTraceEvent::Call) {
+            ApiTraceCall *call =
+                static_cast<ApiTraceCall *>(itm);
+            return QVariant::fromValue(call);
+        }
     }
+
+    return QVariant();
 }
 
 Qt::ItemFlags ApiTraceModel::flags(const QModelIndex &index) const
@@ -59,7 +61,7 @@ QVariant ApiTraceModel::headerData(int section, Qt::Orientation orientation,
     if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
         switch (section) {
         case 0:
-            return tr("Function");
+            return tr("Event");
         default:
             //fall through
             break;
@@ -75,17 +77,39 @@ QModelIndex ApiTraceModel::index(int row, int column,
     if (parent.isValid() && parent.column() != 0)
         return QModelIndex();
 
-    ApiTraceCall *call = m_calls.value(row);
-
-    if (call)
-        return createIndex(row, column, call);
-    else
-        return QModelIndex();
+    if (parent.isValid()) {
+        QVariant data = parent.data();
+        ApiTraceFrame *frame = data.value<ApiTraceFrame*>();
+        if (!frame) {
+            qDebug()<<"got a valid parent but it's not a frame "<<data;
+            return QModelIndex();
+        }
+        ApiTraceCall *call = frame->calls.value(row);
+        if (call)
+            return createIndex(row, column, call);
+        else
+            return QModelIndex();
+    } else {
+        ApiTraceFrame *frame = m_trace->frameAt(row);
+        if (frame)
+            return createIndex(row, column, frame);
+        else
+            return QModelIndex();
+    }
+    return QModelIndex();
 }
 
 bool ApiTraceModel::hasChildren(const QModelIndex &parent) const
 {
-    return parent.isValid() ? false : (rowCount() > 0);
+    if (parent.isValid()) {
+        ApiTraceFrame *frame = parent.data().value<ApiTraceFrame*>();
+        if (frame)
+            return !frame->calls.isEmpty();
+        else
+            return false;
+    } else {
+        return (rowCount() > 0);
+    }
 }
 
 QModelIndex ApiTraceModel::parent(const QModelIndex &index) const
@@ -93,18 +117,34 @@ QModelIndex ApiTraceModel::parent(const QModelIndex &index) const
     if (!index.isValid())
         return QModelIndex();
 
-    //list for now
+    ApiTraceCall *call = index.data().value<ApiTraceCall*>();
+    if (call) {
+        Q_ASSERT(call->parentFrame);
+        return createIndex(call->parentFrame->number,
+                           0, call->parentFrame);
+    }
     return QModelIndex();
 }
 
 int ApiTraceModel::rowCount(const QModelIndex &parent) const
 {
-    return m_calls.count();
+    if (!parent.isValid())
+        return m_trace->numFrames();
+
+    ApiTraceCall *call = parent.data().value<ApiTraceCall*>();
+    if (call)
+        return 0;
+
+    ApiTraceFrame *frame = parent.data().value<ApiTraceFrame*>();
+    if (frame)
+        return frame->calls.count();
+
+    return 0;
 }
 
 int ApiTraceModel::columnCount(const QModelIndex &parent) const
 {
-    return parent.isValid() ? 0 : 1;
+    return 1;
 }
 
 
@@ -121,60 +161,49 @@ bool ApiTraceModel::removeRows(int position, int rows,
 
     Q_UNUSED(parent);
 
-    if (m_calls.count() <= position)
-        return false;
-
     beginRemoveRows(parent, position, position + rows - 1);
-    for (int i = 0; i < rows; ++i) {
-        ApiTraceCall *call = m_calls.value(i);
-        m_calls.removeAt(i);
-        delete call;
-    }
+    //XXX remove it from ApiTrace
     endRemoveRows();
 
     return success;
 }
 
-void ApiTraceModel::loadTraceFile(const QString &fileName)
+void ApiTraceModel::setApiTrace(ApiTrace *trace)
 {
-    if (m_loader->isRunning()) {
-        m_loader->terminate();
-        m_loader->wait();
-    }
-    removeRows(0, m_calls.count(), QModelIndex());
-
-    m_loader->loadFile(fileName);
+    if (m_trace == trace)
+        return;
+    if (m_trace)
+        disconnect(m_trace);
+    m_trace = trace;
+    connect(m_trace, SIGNAL(framesInvalidated()),
+            this, SLOT(invalidateFrames()));
+    connect(m_trace, SIGNAL(framesAdded(int, int)),
+            this, SLOT(appendFrames(int, int)));
 }
 
-void ApiTraceModel::appendCalls(const QList<Trace::Call*> traceCalls)
+const ApiTrace * ApiTraceModel::apiTrace() const
 {
-    beginInsertRows(QModelIndex(), m_calls.count(),
-                    m_calls.count() + traceCalls.count());
-    foreach(Trace::Call *call, traceCalls) {
-        ApiTraceCall *apiCall = new ApiTraceCall;
-        apiCall->name = QString::fromStdString(call->sig->name);
+    return m_trace;
+}
 
-        QString argumentsText;
-        for (int i = 0; i < call->sig->arg_names.size(); ++i) {
-            apiCall->argNames +=
-                QString::fromStdString(call->sig->arg_names[i]);
-        }
-        if (call->ret) {
-            VariantVisitor retVisitor;
-            call->ret->visit(retVisitor);
-            apiCall->returnValue = retVisitor.variant();
-        }
-        for (int i = 0; i < call->args.size(); ++i) {
-            VariantVisitor argVisitor;
-            call->args[i]->visit(argVisitor);
-            apiCall->argValues += argVisitor.variant();
-        }
+void ApiTraceModel::invalidateFrames()
+{
+    beginResetModel();
+    endResetModel();
+}
 
-        m_calls.append(apiCall);
-    }
+void ApiTraceModel::appendFrames(int oldCount, int numAdded)
+{
+    beginInsertRows(QModelIndex(), oldCount,
+                    oldCount + numAdded);
     endInsertRows();
+}
 
-    qDeleteAll(traceCalls);
+ApiTraceEvent * ApiTraceModel::item(const QModelIndex &index) const
+{
+    if (!index.isValid())
+        return 0;
+    return static_cast<ApiTraceEvent*>(index.internalPointer());
 }
 
 #include "apitracemodel.moc"
index 422259e84405898063fb4d8ecf2cb65cbd4313fe..d9ac9dd858905f58370fa5e8879956b6a08417d4 100644 (file)
@@ -6,20 +6,22 @@
 #include <QModelIndex>
 #include <QVariant>
 
+class ApiTrace;
 class ApiTraceCall;
-class LoaderThread;
-namespace Trace {
-    class Call;
-}
+class ApiTraceEvent;
 
 class ApiTraceModel : public QAbstractItemModel
 {
     Q_OBJECT
-
 public:
     ApiTraceModel(QObject *parent = 0);
     ~ApiTraceModel();
 
+    void setApiTrace(ApiTrace *trace);
+    const ApiTrace *apiTrace() const;
+
+public:
+    /* QAbstractItemModel { */
     QVariant data(const QModelIndex &index, int role) const;
     Qt::ItemFlags flags(const QModelIndex &index) const;
     QVariant headerData(int section, Qt::Orientation orientation,
@@ -35,14 +37,17 @@ public:
                     const QModelIndex &parent = QModelIndex());
     bool removeRows(int position, int rows,
                     const QModelIndex &parent = QModelIndex());
+    /* } QAbstractItemModel; */
 
-public slots:
-    void loadTraceFile(const QString &fileName);
-    void appendCalls(const QList<Trace::Call*> traceCalls);
+private slots:
+    void invalidateFrames();
+    void appendFrames(int oldCount, int numAdded);
+
+private:
+    ApiTraceEvent *item(const QModelIndex &index) const;
 
 private:
-    QList<ApiTraceCall*> m_calls;
-    LoaderThread        *m_loader;
+    ApiTrace *m_trace;
 };
 
 #endif
index c8cbe579f3096c2faf123c8918a2f7296aa5be32..2ec06ec749f649405c14317b95c839eee516d6c9 100644 (file)
@@ -2,31 +2,81 @@
 
 #include "trace_parser.hpp"
 
+#define FRAMES_TO_CACHE 100
+
+static ApiTraceCall *
+apiCallFromTraceCall(const Trace::Call *call)
+{
+    ApiTraceCall *apiCall = new ApiTraceCall();
+    apiCall->name = QString::fromStdString(call->sig->name);
+
+    QString argumentsText;
+    for (int i = 0; i < call->sig->arg_names.size(); ++i) {
+        apiCall->argNames +=
+            QString::fromStdString(call->sig->arg_names[i]);
+    }
+    if (call->ret) {
+        VariantVisitor retVisitor;
+        call->ret->visit(retVisitor);
+        apiCall->returnValue = retVisitor.variant();
+    }
+    for (int i = 0; i < call->args.size(); ++i) {
+        VariantVisitor argVisitor;
+        call->args[i]->visit(argVisitor);
+        apiCall->argValues += argVisitor.variant();
+    }
+
+    return apiCall;
+}
+
 LoaderThread::LoaderThread(QObject *parent)
-    : QThread(parent)
+    : QThread(parent),
+      m_frameMarker(ApiTrace::FrameMarker_SwapBuffers)
 {
 }
 
 void LoaderThread::run()
 {
-    QList<Trace::Call*> traceCalls;
+    QList<ApiTraceFrame*> frames;
+    ApiTraceFrame *currentFrame = 0;
+    int frameCount = 0;
     Trace::Parser p;
     if (p.open(m_fileName.toLatin1().constData())) {
         Trace::Call *call;
         call = p.parse_call();
         while (call) {
             //std::cout << *call;
-            traceCalls.append(call);
-            if (traceCalls.count() >= 1000) {
-                emit parsedCalls(traceCalls);
-                traceCalls.clear();
+            if (!currentFrame) {
+                currentFrame = new ApiTraceFrame();
+                currentFrame->number = frameCount;
+                ++frameCount;
+            }
+            ApiTraceCall *apiCall =
+                apiCallFromTraceCall(call);
+            apiCall->parentFrame = currentFrame;
+            apiCall->index = currentFrame->calls.count();
+            currentFrame->calls.append(apiCall);
+            if (ApiTrace::isCallAFrameMarker(apiCall,
+                                             m_frameMarker)) {
+                frames.append(currentFrame);
+                currentFrame = 0;
+                if (frames.count() >= FRAMES_TO_CACHE) {
+                    emit parsedFrames(frames);
+                    frames.clear();
+                }
             }
             call = p.parse_call();
         }
     }
-    if (traceCalls.count()) {
-        emit parsedCalls(traceCalls);
-        traceCalls.clear();
+    //last frames won't have markers
+    //  it's just a bunch of Delete calls for every object
+    //  after the last SwapBuffers
+    if (currentFrame) {
+        frames.append(currentFrame);
+        currentFrame = 0;
+    }
+    if (frames.count()) {
+        emit parsedFrames(frames);
     }
 }
 
@@ -36,4 +86,15 @@ void LoaderThread::loadFile(const QString &fileName)
     start();
 }
 
+ApiTrace::FrameMarker LoaderThread::frameMarker() const
+{
+    return m_frameMarker;
+}
+
+void LoaderThread::setFrameMarker(ApiTrace::FrameMarker marker)
+{
+    Q_ASSERT(!isRunning());
+    m_frameMarker = marker;
+}
+
 #include "loaderthread.moc"
index 49148151a66564b2fb915a72836f4c9bd0559104..5073e14fff7e5e2c6802da20a358aca29bb607ac 100644 (file)
@@ -1,13 +1,12 @@
 #ifndef LOADERTHREAD_H
 #define LOADERTHREAD_H
 
+#include "apitrace.h"
 #include <QThread>
 #include <QList>
 
 class ApiTraceCall;
-namespace Trace {
-    class Call;
-}
+class ApiTraceFrame;
 
 class LoaderThread : public QThread
 {
@@ -15,17 +14,20 @@ class LoaderThread : public QThread
 public:
     LoaderThread(QObject *parent=0);
 
+    ApiTrace::FrameMarker frameMarker() const;
+    void setFrameMarker(ApiTrace::FrameMarker marker);
 public slots:
     void loadFile(const QString &fileName);
 
 signals:
-    void parsedCalls(const QList<Trace::Call*> &calls);
+    void parsedFrames(const QList<ApiTraceFrame*> &frames);
 
 protected:
     virtual void run();
 
 private:
     QString m_fileName;
+    ApiTrace::FrameMarker m_frameMarker;
 };
 
 #endif
index dcfb6c2eea721e0e781f053d89844abca32de0fb..bee35d370ce89fcb28bca3cb2be34ebab59f4227 100644 (file)
@@ -1,18 +1,18 @@
 #include "mainwindow.h"
 
-#include "trace_model.hpp"
+#include "apitracecall.h"
 
 #include <QApplication>
 #include <QMetaType>
 #include <QVariant>
 
-Q_DECLARE_METATYPE(QList<Trace::Call*>);
+Q_DECLARE_METATYPE(QList<ApiTraceFrame*>);
 
 int main(int argc, char **argv)
 {
     QApplication app(argc, argv);
 
-    qRegisterMetaType<QList<Trace::Call*> >();
+    qRegisterMetaType<QList<ApiTraceFrame*> >();
     MainWindow window;
 
     window.show();
index 74d9f94cc7742e10df6c54ff5717f47abb798cce..a46914890984e6cbbdb74705fac89a7da2ec4d28 100644 (file)
@@ -1,5 +1,6 @@
 #include "mainwindow.h"
 
+#include "apitrace.h"
 #include "apitracecall.h"
 #include "apicalldelegate.h"
 #include "apitracemodel.h"
@@ -22,7 +23,10 @@ MainWindow::MainWindow()
 {
     m_ui.setupUi(this);
 
+    m_trace = new ApiTrace();
+
     m_model = new ApiTraceModel();
+    m_model->setApiTrace(m_trace);
     m_proxyModel = new ApiTraceFilter();
     m_proxyModel->setSourceModel(m_model);
     m_ui.callView->setModel(m_proxyModel);
@@ -64,7 +68,6 @@ void MainWindow::openTrace()
     qDebug()<< "File name : " <<fileName;
 
     newTraceFile(fileName);
-    m_model->loadTraceFile(fileName);
 }
 
 void MainWindow::loadTrace(const QString &fileName)
@@ -76,7 +79,6 @@ void MainWindow::loadTrace(const QString &fileName)
     }
     qDebug()<< "Loading  : " <<fileName;
 
-    m_model->loadTraceFile(fileName);
     newTraceFile(fileName);
 }
 
@@ -145,6 +147,7 @@ void MainWindow::replayStop()
 void MainWindow::newTraceFile(const QString &fileName)
 {
     m_traceFileName = fileName;
+    m_trace->setFileName(fileName);
 
     if (m_traceFileName.isEmpty()) {
         m_ui.actionReplay->setEnabled(false);
index 56c1195790d45dad893fa377e06d0ceb88c4fc71..11290e65b186538a88e1758fef3caafa6f4ff8ab 100644 (file)
@@ -6,7 +6,7 @@
 #include <QMainWindow>
 #include <QProcess>
 
-
+class ApiTrace;
 class ApiTraceModel;
 class ApiTraceFilter;
 class QLineEdit;
@@ -36,6 +36,7 @@ private:
 
 private:
     Ui_MainWindow m_ui;
+    ApiTrace *m_trace;
     ApiTraceModel *m_model;
     ApiTraceFilter *m_proxyModel;
     QLineEdit *m_filterEdit;
index a6f17b3b8ef87c2ae985da678f3773c2ace42952..f60042cdc88d8933fd34963506ff129a290a684b 100644 (file)
      <verstretch>0</verstretch>
     </sizepolicy>
    </property>
+   <property name="minimumSize">
+    <size>
+     <width>77</width>
+     <height>100</height>
+    </size>
+   </property>
    <property name="floating">
     <bool>false</bool>
    </property>
    <widget class="QWidget" name="dockWidgetContents">
     <layout class="QHBoxLayout" name="horizontalLayout_2">
      <item>
-      <widget class="QWebView" name="detailsWebView">
+      <widget class="QWebView" name="detailsWebView" native="true">
        <property name="sizePolicy">
         <sizepolicy hsizetype="Preferred" vsizetype="Ignored">
          <horstretch>0</horstretch>
          <verstretch>0</verstretch>
         </sizepolicy>
        </property>
-       <property name="url">
+       <property name="url" stdset="0">
         <url>
          <string>about:blank</string>
         </url>
   </action>
   <action name="actionOpen">
    <property name="icon">
-    <iconset theme="document-open">
+    <iconset>
      <normaloff/>
     </iconset>
    </property>
   </action>
   <action name="actionQuit">
    <property name="icon">
-    <iconset theme="application-exit">
+    <iconset>
      <normaloff/>
     </iconset>
    </property>
     <bool>false</bool>
    </property>
    <property name="icon">
-    <iconset theme="media-playback-start">
+    <iconset>
      <normaloff/>
     </iconset>
    </property>
     <bool>false</bool>
    </property>
    <property name="icon">
-    <iconset theme="media-playback-stop">
+    <iconset>
      <normaloff/>
     </iconset>
    </property>