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 trim all calls after the selected call or frame.
New trace files are created automatically and named according to the
last call number in the trimmed trace.
For example, if the original trace file is:
/path/foo.trace
and the trace is trimmed after call 1234, the name of the trimmed trace
file will be named:
/path/foo.1234.trim.trace
Upon trimming, the trimmed trace file will be loaded into qapitrace.
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.
Signed-off-by: José Fonseca <jose.r.fonseca@gmail.com>
tracedialog.cpp
traceloader.cpp
traceprocess.cpp
+ trimprocess.cpp
vertexdatainterpreter.cpp
)
#include "shaderssourcewidget.h"
#include "tracedialog.h"
#include "traceprocess.h"
+#include "trimprocess.h"
#include "thumbnail.h"
#include "ui_retracerdialog.h"
#include "vertexdatainterpreter.h"
m_ui.actionReplay->setEnabled(true);
m_ui.actionLookupState->setEnabled(true);
m_ui.actionShowThumbnails->setEnabled(true);
+ m_ui.actionTrim->setEnabled(true);
setWindowTitle(
tr("QApiTrace - %1").arg(info.fileName()));
}
}
}
+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) {
replayTrace(false, 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;
m_searchWidget->hide();
m_traceProcess = new TraceProcess(this);
+ m_trimProcess = new TrimProcess(this);
}
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.actionShowThumbnails, SIGNAL(triggered()),
this, SLOT(showThumbnails()));
connect(m_ui.actionOptions, SIGNAL(triggered()),
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)),
msg);
}
+void MainWindow::createdTrim(const QString &path)
+{
+ qDebug()<<"Done trimming "<<path;
+
+ newTraceFile(path);
+}
+
+void MainWindow::trimError(const QString &msg)
+{
+ QMessageBox::warning(
+ this,
+ tr("Trim Error"),
+ msg);
+}
+
void MainWindow::slotSearch()
{
m_jumpWidget->hide();
class SearchWidget;
class ShadersSourceWidget;
class TraceProcess;
+class TrimProcess;
class VertexDataInterpreter;
class MainWindow : public QMainWindow
void finishedLoadingTrace();
void lookupState();
void showThumbnails();
+ void trim();
void showSettings();
void openHelp(const QUrl &url);
void showSurfacesMenu(const QPoint &pos);
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);
void initConnections();
void newTraceFile(const QString &fileName);
void replayTrace(bool dumpState, bool dumpThumbnails);
+ void trimEvent();
void fillStateForFrame();
/* there's a difference between selected frame/call and
ApiTraceEvent *m_stateEvent;
+ ApiTraceEvent *m_trimEvent;
+
Retracer *m_retracer;
VertexDataInterpreter *m_vdataInterpreter;
TraceProcess *m_traceProcess;
+ TrimProcess *m_trimProcess;
+
ArgumentsEditor *m_argsEditor;
ApiTraceEvent *m_nonDefaultsLookupEvent;
--- /dev/null
+#include "trimprocess.h"
+#include "apitrace.h"
+
+#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;
+
+ updateTrimPath();
+}
+
+void TrimProcess::setTracePath(const QString &str)
+{
+ m_tracePath = str;
+
+ updateTrimPath();
+}
+
+QString TrimProcess::tracePath() const
+{
+ return m_tracePath;
+}
+
+void TrimProcess::updateTrimPath()
+{
+
+ QFileInfo fi(m_tracePath);
+ QString baseName = fi.baseName();
+ QString path = fi.path();
+
+ QString format = QString::fromLatin1("%1/%2.%3.trim.trace");
+
+ m_trimPath = format
+ .arg(path)
+ .arg(baseName)
+ .arg(m_trimIndex);
+}
+
+#include "trimprocess.moc"
--- /dev/null
+#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;
+
+private:
+ void updateTrimPath();
+
+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
<addaction name="actionStop"/>
<addaction name="actionLookupState"/>
<addaction name="actionShowThumbnails"/>
+ <addaction name="actionTrim"/>
<addaction name="separator"/>
<addaction name="actionOptions"/>
</widget>
<string>Ctrl+T</string>
</property>
</action>
+ <action name="actionTrim">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string>Tr&im</string>
+ </property>
+ <property name="shortcut">
+ <string>Ctrl+I</string>
+ </property>
+ </action>
<action name="actionOptions">
<property name="text">
<string>Options</string>