[PATCH] Add trim support to qapitrace GUI app

Dan McCabe zen3d.linux at gmail.com
Thu Mar 15 08:33:17 PDT 2012


This patch adds support for trimming of traces via the qapitrace GUI.
We enhance the GUI by adding a Trim entry to the Trace menu. When the
user selects either a frame or a call, the "apitrace trim" command
will be invoked to all calls after the selected call or frame. New
trace files are created automatically in numerical sequence, similar
to how new trace files are currently created in the GUI.

First, we enhance the Trace menu of the GUI app.

Next, we add a TrimProcess class. This is modelled on the TraceProcess
class, but takes into account differences and simplifications.

Next, we tie the TrimProcess class into the main window by accessing
that class and its members appropriately as well as tieing in message
communication with that class.

Finally, we add a reference to the source of TrimProcess to the make
system.
---
 gui/CMakeLists.txt   |    1 +
 gui/mainwindow.cpp   |   55 +++++++++++++++++++++++
 gui/mainwindow.h     |    9 ++++
 gui/trimprocess.cpp  |  119 ++++++++++++++++++++++++++++++++++++++++++++++++++
 gui/trimprocess.h    |   42 ++++++++++++++++++
 gui/ui/mainwindow.ui |   12 +++++
 6 files changed, 238 insertions(+), 0 deletions(-)
 create mode 100644 gui/trimprocess.cpp
 create mode 100644 gui/trimprocess.h

diff --git a/gui/CMakeLists.txt b/gui/CMakeLists.txt
index f464cb0..3c0bee3 100644
--- a/gui/CMakeLists.txt
+++ b/gui/CMakeLists.txt
@@ -22,6 +22,7 @@ set(qapitrace_SRCS
    tracedialog.cpp
    traceloader.cpp
    traceprocess.cpp
+   trimprocess.cpp
    vertexdatainterpreter.cpp
  )
 
diff --git a/gui/mainwindow.cpp b/gui/mainwindow.cpp
index 672ad64..0c50a77 100644
--- a/gui/mainwindow.cpp
+++ b/gui/mainwindow.cpp
@@ -14,6 +14,7 @@
 #include "shaderssourcewidget.h"
 #include "tracedialog.h"
 #include "traceprocess.h"
+#include "trimprocess.h"
 #include "ui_retracerdialog.h"
 #include "vertexdatainterpreter.h"
 
@@ -33,6 +34,7 @@
 #include <QWebPage>
 #include <QWebView>
 
+#include <iostream>
 
 MainWindow::MainWindow()
     : QMainWindow(),
@@ -199,6 +201,7 @@ void MainWindow::newTraceFile(const QString &fileName)
         QFileInfo info(fileName);
         m_ui.actionReplay->setEnabled(true);
         m_ui.actionLookupState->setEnabled(true);
+        m_ui.actionTrim->setEnabled(true);
         setWindowTitle(
             tr("QApiTrace - %1").arg(info.fileName()));
     }
@@ -305,6 +308,25 @@ void MainWindow::replayTrace(bool dumpState)
     }
 }
 
+void MainWindow::trimEvent()
+{
+
+    int trimIndex;
+    if (m_trimEvent->type() == ApiTraceEvent::Call) {
+        ApiTraceCall *call = static_cast<ApiTraceCall*>(m_trimEvent);
+        trimIndex = call->index();
+    } else if (m_trimEvent->type() == ApiTraceEvent::Frame) {
+        ApiTraceFrame *frame = static_cast<ApiTraceFrame*>(m_trimEvent);
+        const QList<ApiTraceFrame*> frames = m_trace->frames();
+        trimIndex = frame->lastCallIndex();
+    }
+
+    m_trimProcess->setTracePath(m_trace->fileName());
+    m_trimProcess->setTrimIndex(trimIndex);
+
+    m_trimProcess->start();
+}
+
 void MainWindow::lookupState()
 {
     if (!m_selectedEvent) {
@@ -325,6 +347,18 @@ void MainWindow::lookupState()
     replayTrace(true);
 }
 
+void MainWindow::trim()
+{
+    if (!m_selectedEvent) {
+        QMessageBox::warning(
+            this, tr("Unknown Event"),
+            tr("To trim select a frame or an event in the event list."));
+        return;
+    }
+    m_trimEvent = m_selectedEvent;
+    trimEvent();
+}
+
 MainWindow::~MainWindow()
 {
     delete m_trace;
@@ -706,6 +740,7 @@ void MainWindow::initObjects()
     m_searchWidget->hide();
 
     m_traceProcess = new TraceProcess(this);
+    m_trimProcess = new TrimProcess(this);
 }
 
 void MainWindow::initConnections()
@@ -774,6 +809,8 @@ void MainWindow::initConnections()
             this, SLOT(replayStop()));
     connect(m_ui.actionLookupState, SIGNAL(triggered()),
             this, SLOT(lookupState()));
+    connect(m_ui.actionTrim, SIGNAL(triggered()),
+            this, SLOT(trim()));
     connect(m_ui.actionOptions, SIGNAL(triggered()),
             this, SLOT(showSettings()));
 
@@ -810,6 +847,11 @@ void MainWindow::initConnections()
     connect(m_traceProcess, SIGNAL(error(const QString&)),
             SLOT(traceError(const QString&)));
 
+    connect(m_trimProcess, SIGNAL(trimmedFile(const QString&)),
+            SLOT(createdTrim(const QString&)));
+    connect(m_trimProcess, SIGNAL(error(const QString&)),
+            SLOT(trimError(const QString&)));
+
     connect(m_ui.errorsDock, SIGNAL(visibilityChanged(bool)),
             m_ui.actionShowErrorsDock, SLOT(setChecked(bool)));
     connect(m_ui.actionShowErrorsDock, SIGNAL(triggered(bool)),
@@ -857,6 +899,19 @@ void MainWindow::traceError(const QString &msg)
             msg);
 }
 
+void MainWindow::createdTrim(const QString &path)
+{
+    qDebug()<<"Done trimming "<<path;
+}
+
+void MainWindow::trimError(const QString &msg)
+{
+    QMessageBox::warning(
+            this,
+            tr("Trim Error"),
+            msg);
+}
+
 void MainWindow::slotSearch()
 {
     m_jumpWidget->hide();
diff --git a/gui/mainwindow.h b/gui/mainwindow.h
index 59c9ba7..ccbcef0 100644
--- a/gui/mainwindow.h
+++ b/gui/mainwindow.h
@@ -27,6 +27,7 @@ class Retracer;
 class SearchWidget;
 class ShadersSourceWidget;
 class TraceProcess;
+class TrimProcess;
 class VertexDataInterpreter;
 
 class MainWindow : public QMainWindow
@@ -52,6 +53,7 @@ private slots:
     void loadProgess(int percent);
     void finishedLoadingTrace();
     void lookupState();
+    void trim();
     void showSettings();
     void openHelp(const QUrl &url);
     void showSurfacesMenu(const QPoint &pos);
@@ -61,6 +63,8 @@ private slots:
     void slotJumpTo(int callNum);
     void createdTrace(const QString &path);
     void traceError(const QString &msg);
+    void createdTrim(const QString &path);
+    void trimError(const QString &msg);
     void slotSearch();
     void slotSearchNext(const QString &str, Qt::CaseSensitivity sensitivity);
     void slotSearchPrev(const QString &str, Qt::CaseSensitivity sensitivity);
@@ -86,6 +90,7 @@ private:
     void initConnections();
     void newTraceFile(const QString &fileName);
     void replayTrace(bool dumpState);
+    void trimEvent();
     void fillStateForFrame();
 
     /* there's a difference between selected frame/call and
@@ -115,6 +120,8 @@ private:
 
     ApiTraceEvent *m_stateEvent;
 
+    ApiTraceEvent *m_trimEvent;
+
     Retracer *m_retracer;
 
     VertexDataInterpreter *m_vdataInterpreter;
@@ -124,6 +131,8 @@ private:
 
     TraceProcess *m_traceProcess;
 
+    TrimProcess *m_trimProcess;
+
     ArgumentsEditor *m_argsEditor;
 
     ApiTraceEvent *m_nonDefaultsLookupEvent;
diff --git a/gui/trimprocess.cpp b/gui/trimprocess.cpp
new file mode 100644
index 0000000..5489210
--- /dev/null
+++ b/gui/trimprocess.cpp
@@ -0,0 +1,119 @@
+#include "trimprocess.h"
+#include "apitrace.h"
+
+#include <iostream>
+
+#include <QDebug>
+#include <QDir>
+#include <QFile>
+#include <QFileInfo>
+
+TrimProcess::TrimProcess(QObject *parent)
+    : QObject(parent)
+{
+    m_process = new QProcess(this);
+
+    connect(m_process, SIGNAL(finished(int, QProcess::ExitStatus)),
+            this, SLOT(trimFinished()));
+    connect(m_process, SIGNAL(error(QProcess::ProcessError)),
+            this, SLOT(trimError(QProcess::ProcessError)));
+
+#ifdef Q_OS_WIN
+    QString format = QLatin1String("%1;");
+#else
+    QString format = QLatin1String("%1:");
+#endif
+    QString buildPath = format.arg(APITRACE_BINARY_DIR);
+    QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
+    env.insert("PATH", buildPath + env.value("PATH"));
+    qputenv("PATH", env.value("PATH").toLatin1());
+}
+
+TrimProcess::~TrimProcess()
+{
+}
+
+void TrimProcess::trimFinished()
+{
+    // consume verbose output spew
+    QByteArray outputStrings = m_process->readAllStandardOutput();
+    QByteArray errorStrings = m_process->readAllStandardError();
+#if 0
+    qDebug()<<"trim finished on " << m_trimPath;
+    qDebug()<<"\terr = "<<errorStrings;
+    qDebug()<<"\tout = "<<outputStrings;
+#endif
+    emit trimmedFile(m_trimPath);
+}
+
+void TrimProcess::trimError(QProcess::ProcessError err)
+{
+    // consume verbose output spew
+    QByteArray outputStrings = m_process->readAllStandardOutput();
+    QByteArray errorStrings = m_process->readAllStandardError();
+#if 1
+    qDebug()<<"trace error = "<<m_tracePath;
+    qDebug()<<"\terr = "<<errorStrings;
+    qDebug()<<"\tout = "<<outputStrings;
+#endif
+    emit error(errorStrings);
+}
+
+
+void TrimProcess::start()
+{
+    QStringList arguments;
+
+    QString outputFormat = QLatin1String("--output=%1");
+    QString outputArgument = outputFormat
+                                .arg(m_trimPath);
+
+    QString callSetFormat = QLatin1String("--calls=0-%1");
+    QString callSetArgument = callSetFormat
+                                .arg(m_trimIndex);
+
+    arguments << QLatin1String("trim");
+    arguments << outputArgument;
+    arguments << callSetArgument;
+    arguments << m_tracePath;
+
+    m_process->start(QLatin1String("apitrace"), arguments);
+}
+
+int TrimProcess::trimIndex()
+{
+    return m_trimIndex;
+}
+
+void TrimProcess::setTrimIndex(int trimIndex)
+{
+    m_trimIndex = trimIndex;
+}
+
+void TrimProcess::setTracePath(const QString &str)
+{
+    m_tracePath = str;
+
+    QFileInfo fi(m_tracePath);
+    QString baseName = fi.baseName();
+
+    QString format = QString::fromLatin1("%1.trim.trace");
+
+    m_trimPath = format
+                  .arg(baseName);
+
+    int i = 1;
+    while (QFile::exists(m_trimPath)) {
+        format = QString::fromLatin1("%1.%2.trim.trace");
+        m_trimPath = format
+                      .arg(baseName)
+                      .arg(i++);
+    }
+}
+
+QString TrimProcess::tracePath() const
+{
+    return m_tracePath;
+}
+
+#include "trimprocess.moc"
diff --git a/gui/trimprocess.h b/gui/trimprocess.h
new file mode 100644
index 0000000..2252673
--- /dev/null
+++ b/gui/trimprocess.h
@@ -0,0 +1,42 @@
+#ifndef TRIMPROCESS_H
+#define TRIMPROCESS_H
+
+#include "apitrace.h"
+
+#include <QObject>
+#include <QProcess>
+
+class TrimProcess : public QObject
+{
+    Q_OBJECT
+public:
+    TrimProcess(QObject *parent=0);
+    ~TrimProcess();
+
+    void setTrimIndex(int trimIndex);
+    int trimIndex();
+
+    void setTracePath(const QString &str);
+    QString tracePath() const;
+
+public slots:
+    void start();
+
+signals:
+    void trimmedFile(const QString &trimPath);
+    void error(const QString &msg);
+
+private slots:
+    void trimFinished();
+    void trimError(QProcess::ProcessError err);
+
+private:
+    QStringList m_args;
+    QString m_tracePath;
+    QString m_trimPath;
+    ApiTraceEvent *m_trimEvent;
+    int m_trimIndex;
+    QProcess *m_process;
+};
+
+#endif
diff --git a/gui/ui/mainwindow.ui b/gui/ui/mainwindow.ui
index 5b48dc2..8e1f95a 100644
--- a/gui/ui/mainwindow.ui
+++ b/gui/ui/mainwindow.ui
@@ -75,6 +75,7 @@
     <addaction name="actionReplay"/>
     <addaction name="actionStop"/>
     <addaction name="actionLookupState"/>
+    <addaction name="actionTrim"/>
     <addaction name="separator"/>
     <addaction name="actionOptions"/>
    </widget>
@@ -525,6 +526,17 @@
     <string>Ctrl+L</string>
    </property>
   </action>
+  <action name="actionTrim">
+   <property name="enabled">
+    <bool>false</bool>
+   </property>
+   <property name="text">
+    <string>Trim</string>
+   </property>
+   <property name="shortcut">
+    <string>Ctrl+T</string>
+   </property>
+  </action>
   <action name="actionOptions">
    <property name="text">
     <string>Options</string>
-- 
1.7.5.4



More information about the apitrace mailing list