[PATCH] Add trim support to qapitrace GUI app

José Fonseca jose.r.fonseca at gmail.com
Thu Mar 15 12:02:17 PDT 2012


Usually I'd say that trim is one of those transformations that would
be better easily done inside the GUI process, without forking a
separate apitrace command.

But honestly I don't know any more. There's simply not enough people
working on the GUI for me to be picky about these things. And having
the GUI to be a layer on top of the the CLI might actually be a good
way to ensure the GUI keeps receiving more new features, without too
much code duplication.  At the end of the day, the GUI user doesn't
care how we implement stuff as long as it works..

What are your thoughts on this, Zack?

Jose

On Thu, Mar 15, 2012 at 3:33 PM, Dan McCabe <zen3d.linux at gmail.com> wrote:
> 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
>
> _______________________________________________
> apitrace mailing list
> apitrace at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/apitrace


More information about the apitrace mailing list