]> git.cworth.org Git - apitrace/commitdiff
Replay and parse json in a thread.
authorZack Rusin <zack@kde.org>
Sun, 10 Apr 2011 23:27:28 +0000 (19:27 -0400)
committerZack Rusin <zack@kde.org>
Sun, 10 Apr 2011 23:28:00 +0000 (19:28 -0400)
gui/apitracecall.h
gui/main.cpp
gui/mainwindow.cpp
gui/mainwindow.h
gui/retracer.cpp
gui/retracer.h

index 94bd234b5767e8052223488ffd960bed8745a2b5..dd69b0e4c9f2fbf7db7c0f37fecfb891fe890864 100644 (file)
@@ -118,6 +118,7 @@ private:
     QStringList m_shaderSources;
     QList<ApiTexture> m_textures;
 };
+Q_DECLARE_METATYPE(ApiTraceState);
 
 class ApiTraceEvent
 {
index bee35d370ce89fcb28bca3cb2be34ebab59f4227..3f8cfa6b6bcb7b884e4c47ba27da0018dc9fb1b0 100644 (file)
@@ -13,6 +13,7 @@ int main(int argc, char **argv)
     QApplication app(argc, argv);
 
     qRegisterMetaType<QList<ApiTraceFrame*> >();
+    qRegisterMetaType<ApiTraceState>();
     MainWindow window;
 
     window.show();
index b19a559fe681b882f5a16b2e0576e31cfa7fa4d5..4fc1362879d325a7c0b2166b8b48deea1ee796c2 100644 (file)
@@ -12,8 +12,6 @@
 #include "ui_retracerdialog.h"
 #include "vertexdatainterpreter.h"
 
-#include <qjson/parser.h>
-
 #include <QAction>
 #include <QDebug>
 #include <QDesktopServices>
@@ -32,8 +30,7 @@
 MainWindow::MainWindow()
     : QMainWindow(),
       m_selectedEvent(0),
-      m_stateEvent(0),
-      m_jsonParser(new QJson::Parser())
+      m_stateEvent(0)
 {
     m_ui.setupUi(this);
     initObjects();
@@ -140,7 +137,7 @@ void MainWindow::replayStart()
 
 void MainWindow::replayStop()
 {
-    m_retracer->terminate();
+    m_retracer->quit();
     m_ui.actionStop->setEnabled(false);
     m_ui.actionReplay->setEnabled(true);
     m_ui.actionLookupState->setEnabled(true);
@@ -164,20 +161,19 @@ void MainWindow::newTraceFile(const QString &fileName)
     }
 }
 
-void MainWindow::replayFinished(const QByteArray &output)
+void MainWindow::replayFinished(const QString &output)
 {
     m_ui.actionStop->setEnabled(false);
     m_ui.actionReplay->setEnabled(true);
     m_ui.actionLookupState->setEnabled(true);
 
-    if (m_retracer->captureState()) {
-        bool ok = false;
-        QVariantMap parsedJson = m_jsonParser->parse(output, &ok).toMap();
-        parseState(parsedJson);
-    } else if (output.length() < 80) {
+    m_progressBar->hide();
+    if (output.length() < 80) {
         statusBar()->showMessage(output);
     }
     m_stateEvent = 0;
+    statusBar()->showMessage(
+        tr("Replaying finished!"), 2000);
 }
 
 void MainWindow::replayError(const QString &message)
@@ -187,6 +183,9 @@ void MainWindow::replayError(const QString &message)
     m_ui.actionLookupState->setEnabled(true);
     m_stateEvent = 0;
 
+    m_progressBar->hide();
+    statusBar()->showMessage(
+        tr("Replaying unsuccessful."), 2000);
     QMessageBox::warning(
         this, tr("Replay Failed"), message);
 }
@@ -223,7 +222,8 @@ void MainWindow::replayTrace(bool dumpState)
         if (m_selectedEvent->type() == ApiTraceEvent::Call) {
             index = static_cast<ApiTraceCall*>(m_selectedEvent)->index;
         } else if (m_selectedEvent->type() == ApiTraceEvent::Frame) {
-            ApiTraceFrame *frame = static_cast<ApiTraceFrame*>(m_selectedEvent);
+            ApiTraceFrame *frame =
+                static_cast<ApiTraceFrame*>(m_selectedEvent);
             if (frame->calls.isEmpty()) {
                 //XXX i guess we could still get the current state
                 qDebug()<<"tried to get a state for an empty frame";
@@ -239,6 +239,13 @@ void MainWindow::replayTrace(bool dumpState)
     m_retracer->start();
 
     m_ui.actionStop->setEnabled(true);
+    m_progressBar->show();
+    if (dumpState)
+        statusBar()->showMessage(
+            tr("Looking up the state..."));
+    else
+        statusBar()->showMessage(
+            tr("Replaying the trace file..."));
 }
 
 void MainWindow::lookupState()
@@ -255,18 +262,6 @@ void MainWindow::lookupState()
 
 MainWindow::~MainWindow()
 {
-    delete m_jsonParser;
-}
-
-void MainWindow::parseState(const QVariantMap &parsedJson)
-{
-    m_stateEvent->setState(ApiTraceState(parsedJson));
-    m_model->stateSetOnEvent(m_stateEvent);
-    if (m_selectedEvent == m_stateEvent) {
-        fillStateForFrame();
-    } else {
-        m_ui.stateDock->hide();
-    }
 }
 
 static void
@@ -469,10 +464,12 @@ void MainWindow::initConnections()
     connect(m_trace, SIGNAL(finishedLoadingTrace()),
             this, SLOT(finishedLoadingTrace()));
 
-    connect(m_retracer, SIGNAL(finished(const QByteArray&)),
-            this, SLOT(replayFinished(const QByteArray&)));
+    connect(m_retracer, SIGNAL(finished(const QString&)),
+            this, SLOT(replayFinished(const QString&)));
     connect(m_retracer, SIGNAL(error(const QString&)),
             this, SLOT(replayError(const QString&)));
+    connect(m_retracer, SIGNAL(foundState(const ApiTraceState&)),
+            this, SLOT(replayStateFound(const ApiTraceState&)));
 
     connect(m_ui.vertexInterpretButton, SIGNAL(clicked()),
             m_vdataInterpreter, SLOT(interpretData()));
@@ -516,4 +513,15 @@ void MainWindow::initConnections()
             this, SLOT(openHelp(const QUrl&)));
 }
 
+void MainWindow::replayStateFound(const ApiTraceState &state)
+{
+    m_stateEvent->setState(state);
+    m_model->stateSetOnEvent(m_stateEvent);
+    if (m_selectedEvent == m_stateEvent) {
+        fillStateForFrame();
+    } else {
+        m_ui.stateDock->hide();
+    }
+}
+
 #include "mainwindow.moc"
index 55326bf586135c5c72d0b1b0125391eaa95eb846..313180a15086f232ab425da6788aa53551af645c 100644 (file)
@@ -11,6 +11,7 @@ class ApiTraceEvent;
 class ApiTraceFilter;
 class ApiTraceFrame;
 class ApiTraceModel;
+class ApiTraceState;
 class ImageViewer;
 class QLineEdit;
 class QModelIndex;
@@ -20,10 +21,6 @@ class Retracer;
 class ShadersSourceWidget;
 class VertexDataInterpreter;
 
-namespace QJson {
-    class Parser;
-}
-
 class MainWindow : public QMainWindow
 {
     Q_OBJECT
@@ -40,7 +37,8 @@ private slots:
     void filterTrace();
     void replayStart();
     void replayStop();
-    void replayFinished(const QByteArray &output);
+    void replayFinished(const QString &output);
+    void replayStateFound(const ApiTraceState &state);
     void replayError(const QString &msg);
     void startedLoadingTrace();
     void finishedLoadingTrace();
@@ -55,7 +53,6 @@ private:
     void initConnections();
     void newTraceFile(const QString &fileName);
     void replayTrace(bool dumpState);
-    void parseState(const QVariantMap &params);
     void fillStateForFrame();
 
 private:
@@ -75,8 +72,6 @@ private:
 
     ApiTraceEvent *m_stateEvent;
 
-    QJson::Parser *m_jsonParser;
-
     Retracer *m_retracer;
 
     VertexDataInterpreter *m_vdataInterpreter;
index b9d74b627ac429f7d5bfcfc6ba82fe0bbb9ae154..8f3508770457b6ac36fcaf6ff31de4d393904703 100644 (file)
@@ -1,15 +1,31 @@
 #include "retracer.h"
 
+#include "apitracecall.h"
+
 #include <QDebug>
+#include <QVariant>
+
+#include <qjson/parser.h>
 
 Retracer::Retracer(QObject *parent)
-    : QObject(parent),
+    : QThread(parent),
       m_benchmarking(true),
       m_doubleBuffered(true),
       m_captureState(false),
-      m_captureCall(0),
-      m_process(0)
+      m_captureCall(0)
 {
+#ifdef Q_OS_WIN
+    QString format = QLatin1String("%1;");
+#else
+    QString format = QLatin1String("%1:");
+#endif
+    QString buildPath = format.arg(BUILD_DIR);
+    m_processEnvironment = QProcessEnvironment::systemEnvironment();
+    m_processEnvironment.insert("PATH", buildPath +
+                                m_processEnvironment.value("PATH"));
+
+    qputenv("PATH",
+            m_processEnvironment.value("PATH").toLatin1());
 }
 
 QString Retracer::fileName() const
@@ -42,31 +58,65 @@ void Retracer::setDoubleBuffered(bool db)
     m_doubleBuffered = db;
 }
 
-void Retracer::start()
+void Retracer::setCaptureAtCallNumber(qlonglong num)
 {
-    if (!m_process) {
-#ifdef Q_OS_WIN
-        QString format = QLatin1String("%1;");
-#else
-        QString format = QLatin1String("%1:");
-#endif
-        QString buildPath = format.arg(BUILD_DIR);
-        QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
-        env.insert("PATH", buildPath + env.value("PATH"));
+    m_captureCall = num;
+}
+
+qlonglong Retracer::captureAtCallNumber() const
+{
+    return m_captureCall;
+}
+
+bool Retracer::captureState() const
+{
+    return m_captureState;
+}
+
+void Retracer::setCaptureState(bool enable)
+{
+    m_captureState = enable;
+}
+
 
-        qputenv("PATH", env.value("PATH").toLatin1());
+void Retracer::run()
+{
+    RetraceProcess *retrace = new RetraceProcess();
+    retrace->process()->setProcessEnvironment(m_processEnvironment);
+
+    retrace->setFileName(m_fileName);
+    retrace->setBenchmarking(m_benchmarking);
+    retrace->setDoubleBuffered(m_doubleBuffered);
+    retrace->setCaptureState(m_captureState);
+    retrace->setCaptureAtCallNumber(m_captureCall);
+
+    connect(retrace, SIGNAL(finished(const QString&)),
+            this, SLOT(cleanup()));
+    connect(retrace, SIGNAL(error(const QString&)),
+            this, SLOT(cleanup()));
+    connect(retrace, SIGNAL(finished(const QString&)),
+            this, SIGNAL(finished(const QString&)));
+    connect(retrace, SIGNAL(error(const QString&)),
+            this, SIGNAL(error(const QString&)));
+    connect(retrace, SIGNAL(foundState(const ApiTraceState&)),
+            this, SIGNAL(foundState(const ApiTraceState&)));
+
+    retrace->start();
 
-        m_process = new QProcess(this);
-        m_process->setProcessEnvironment(env);
+    exec();
 
-        connect(m_process, SIGNAL(finished(int, QProcess::ExitStatus)),
-                this, SLOT(replayFinished()));
-        connect(m_process, SIGNAL(error(QProcess::ProcessError)),
-                this, SLOT(replayError(QProcess::ProcessError)));
+    /* means we need to kill the process */
+    if (retrace->process()->state() != QProcess::NotRunning) {
+        retrace->terminate();
     }
 
-    QStringList arguments;
+    delete retrace;
+}
+
 
+void RetraceProcess::start()
+{
+    QStringList arguments;
     if (m_captureState) {
         arguments << QLatin1String("-D");
         arguments << QString::number(m_captureCall);
@@ -84,53 +134,124 @@ void Retracer::start()
     m_process->start(QLatin1String("glretrace"), arguments);
 }
 
-void Retracer::terminate()
+
+void RetraceProcess::replayFinished()
 {
-    if (m_process) {
-        m_process->terminate();
+    QByteArray output = m_process->readAllStandardOutput();
+    QString msg;
+
+#if 0
+    qDebug()<<"Process finished = ";
+    qDebug()<<"\terr = "<<m_process->readAllStandardError();
+    qDebug()<<"\tout = "<<output;
+#endif
+    if (m_captureState) {
+        bool ok = false;
+        QVariantMap parsedJson = m_jsonParser->parse(output, &ok).toMap();
+        ApiTraceState state(parsedJson);
+        emit foundState(state);
+        msg = tr("State fetched.");
+    } else {
+        msg = QString::fromUtf8(output);
     }
+
+    emit finished(msg);
 }
 
-void Retracer::setCaptureAtCallNumber(qlonglong num)
+void RetraceProcess::replayError(QProcess::ProcessError err)
+{
+    qDebug()<<"Process error = "<<err;
+    qDebug()<<"\terr = "<<m_process->readAllStandardError();
+    qDebug()<<"\tout = "<<m_process->readAllStandardOutput();
+
+    emit error(
+        tr("Couldn't execute the replay file '%1'").arg(m_fileName));
+}
+
+
+RetraceProcess::RetraceProcess(QObject *parent)
+    : QObject(parent)
+{
+    m_process = new QProcess(this);
+    m_jsonParser = new QJson::Parser();
+
+    connect(m_process, SIGNAL(finished(int, QProcess::ExitStatus)),
+            this, SLOT(replayFinished()));
+    connect(m_process, SIGNAL(error(QProcess::ProcessError)),
+            this, SLOT(replayError(QProcess::ProcessError)));
+}
+
+QProcess * RetraceProcess::process() const
+{
+    return m_process;
+}
+
+QString RetraceProcess::fileName() const
+{
+    return m_fileName;
+}
+
+void RetraceProcess::setFileName(const QString &name)
+{
+    m_fileName = name;
+}
+
+bool RetraceProcess::isBenchmarking() const
+{
+    return m_benchmarking;
+}
+
+void RetraceProcess::setBenchmarking(bool bench)
+{
+    m_benchmarking = bench;
+}
+
+bool RetraceProcess::isDoubleBuffered() const
+{
+    return m_doubleBuffered;
+}
+
+void RetraceProcess::setDoubleBuffered(bool db)
+{
+    m_doubleBuffered = db;
+}
+
+void RetraceProcess::setCaptureAtCallNumber(qlonglong num)
 {
     m_captureCall = num;
 }
 
-qlonglong Retracer::captureAtCallNumber() const
+qlonglong RetraceProcess::captureAtCallNumber() const
 {
     return m_captureCall;
 }
 
-bool Retracer::captureState() const
+bool RetraceProcess::captureState() const
 {
     return m_captureState;
 }
 
-void Retracer::setCaptureState(bool enable)
+void RetraceProcess::setCaptureState(bool enable)
 {
     m_captureState = enable;
 }
 
-void Retracer::replayFinished()
+void RetraceProcess::terminate()
 {
-    QByteArray output = m_process->readAllStandardOutput();
-
-#if 0
-    qDebug()<<"Process finished = ";
-    qDebug()<<"\terr = "<<m_process->readAllStandardError();
-    qDebug()<<"\tout = "<<output;
-#endif
-    emit finished(output);
+    if (m_process) {
+        m_process->terminate();
+        emit finished(tr("Process terminated."));
+    }
 }
 
-void Retracer::replayError(QProcess::ProcessError err)
+void Retracer::cleanup()
 {
-    qDebug()<<"Process error = "<<err;
-    qDebug()<<"\terr = "<<m_process->readAllStandardError();
-    qDebug()<<"\tout = "<<m_process->readAllStandardOutput();
+    quit();
+}
 
-    emit error(
-        tr("Couldn't execute the replay file '%1'").arg(m_fileName));
+RetraceProcess::~RetraceProcess()
+{
+    delete m_jsonParser;
 }
 
 #include "retracer.moc"
index 37502e45b79e5d580396c2eb34db1bb4df592ac5..617861e6cdc4e314c752410238f040f178aced08 100644 (file)
@@ -1,14 +1,24 @@
 #ifndef RETRACER_H
 #define RETRACER_H
 
-#include <QObject>
+#include <QThread>
 #include <QProcess>
 
-class Retracer : public QObject
+class ApiTraceState;
+namespace QJson {
+    class Parser;
+}
+
+/* internal class used by the retracer to run
+ * in the thread */
+class RetraceProcess : public QObject
 {
     Q_OBJECT
 public:
-    Retracer(QObject *parent=0);
+    RetraceProcess(QObject *parent=0);
+    ~RetraceProcess();
+
+    QProcess *process() const;
 
     QString fileName() const;
     void setFileName(const QString &name);
@@ -30,12 +40,14 @@ public slots:
     void terminate();
 
 signals:
-    void finished(const QByteArray &output);
+    void finished(const QString &output);
     void error(const QString &msg);
+    void foundState(const ApiTraceState &state);
 
 private slots:
     void replayFinished();
     void replayError(QProcess::ProcessError err);
+
 private:
     QString m_fileName;
     bool m_benchmarking;
@@ -44,6 +56,48 @@ private:
     qlonglong m_captureCall;
 
     QProcess *m_process;
+    QJson::Parser *m_jsonParser;
+};
+
+class Retracer : public QThread
+{
+    Q_OBJECT
+public:
+    Retracer(QObject *parent=0);
+
+    QString fileName() const;
+    void setFileName(const QString &name);
+
+    bool isBenchmarking() const;
+    void setBenchmarking(bool bench);
+
+    bool isDoubleBuffered() const;
+    void setDoubleBuffered(bool db);
+
+    void setCaptureAtCallNumber(qlonglong num);
+    qlonglong captureAtCallNumber() const;
+
+    bool captureState() const;
+    void setCaptureState(bool enable);
+
+signals:
+    void finished(const QString &output);
+    void foundState(const ApiTraceState &state);
+    void error(const QString &msg);
+
+protected:
+    virtual void run();
+
+private slots:
+    void cleanup();
+private:
+    QString m_fileName;
+    bool m_benchmarking;
+    bool m_doubleBuffered;
+    bool m_captureState;
+    qlonglong m_captureCall;
+
+    QProcessEnvironment m_processEnvironment;
 };
 
 #endif