blob: 8a23ea3ad0b112f606d7fa96a70187e4508ab5b3 [file] [log] [blame]
Zack Rusin601e8372011-03-24 22:23:21 -04001#include "mainwindow.h"
2
Zack Rusinf6667d12011-03-30 11:03:37 -04003#include "apitrace.h"
Zack Rusin96130ac2011-03-27 01:48:36 -04004#include "apitracecall.h"
Zack Rusin18eade52011-03-26 14:23:35 -04005#include "apicalldelegate.h"
Zack Rusin601e8372011-03-24 22:23:21 -04006#include "apitracemodel.h"
Zack Rusin91065372011-03-26 01:54:10 -04007#include "apitracefilter.h"
Zack Rusin601e8372011-03-24 22:23:21 -04008
Zack Rusine8685f62011-03-30 20:14:01 -04009#include <qjson/parser.h>
10
Zack Rusin601e8372011-03-24 22:23:21 -040011#include <QAction>
12#include <QDebug>
13#include <QDir>
14#include <QFileDialog>
Zack Rusin27cb2c42011-03-27 23:53:36 -040015#include <QLineEdit>
16#include <QMessageBox>
17#include <QProcess>
Zack Rusinde4ea412011-03-30 11:30:08 -040018#include <QProgressBar>
Zack Rusinea295452011-03-27 02:22:13 -040019#include <QToolBar>
Zack Rusin96130ac2011-03-27 01:48:36 -040020#include <QWebView>
Zack Rusin601e8372011-03-24 22:23:21 -040021
22
23MainWindow::MainWindow()
Zack Rusin27cb2c42011-03-27 23:53:36 -040024 : QMainWindow(),
Zack Rusin2caa06d2011-03-30 18:30:20 -040025 m_replayProcess(0),
Zack Rusin11f7e632011-03-30 22:47:51 -040026 m_currentFrame(0),
27 m_stateFrame(0),
28 m_findingState(false),
29 m_jsonParser(new QJson::Parser())
Zack Rusin601e8372011-03-24 22:23:21 -040030{
31 m_ui.setupUi(this);
32
Zack Rusinf6667d12011-03-30 11:03:37 -040033 m_trace = new ApiTrace();
Zack Rusinde4ea412011-03-30 11:30:08 -040034 connect(m_trace, SIGNAL(startedLoadingTrace()),
35 this, SLOT(startedLoadingTrace()));
36 connect(m_trace, SIGNAL(finishedLoadingTrace()),
37 this, SLOT(finishedLoadingTrace()));
Zack Rusinf6667d12011-03-30 11:03:37 -040038
Zack Rusin601e8372011-03-24 22:23:21 -040039 m_model = new ApiTraceModel();
Zack Rusinf6667d12011-03-30 11:03:37 -040040 m_model->setApiTrace(m_trace);
Zack Rusin91065372011-03-26 01:54:10 -040041 m_proxyModel = new ApiTraceFilter();
42 m_proxyModel->setSourceModel(m_model);
Zack Rusin96130ac2011-03-27 01:48:36 -040043 m_ui.callView->setModel(m_proxyModel);
Zack Rusin18eade52011-03-26 14:23:35 -040044 m_ui.callView->setItemDelegate(new ApiCallDelegate);
Zack Rusin601e8372011-03-24 22:23:21 -040045 for (int column = 0; column < m_model->columnCount(); ++column)
46 m_ui.callView->resizeColumnToContents(column);
47
Zack Rusinea295452011-03-27 02:22:13 -040048 QToolBar *toolBar = addToolBar(tr("Navigation"));
49 m_filterEdit = new QLineEdit(toolBar);
50 toolBar->addWidget(m_filterEdit);
51
Zack Rusinde4ea412011-03-30 11:30:08 -040052 m_progressBar = new QProgressBar();
53 m_progressBar->setRange(0, 0);
54 statusBar()->addPermanentWidget(m_progressBar);
55 m_progressBar->hide();
56
Zack Rusin96130ac2011-03-27 01:48:36 -040057 m_ui.detailsDock->hide();
Zack Rusin11f7e632011-03-30 22:47:51 -040058 m_ui.stateDock->hide();
Zack Rusin96130ac2011-03-27 01:48:36 -040059
Zack Rusin601e8372011-03-24 22:23:21 -040060 connect(m_ui.actionOpen, SIGNAL(triggered()),
61 this, SLOT(openTrace()));
Zack Rusin27cb2c42011-03-27 23:53:36 -040062 connect(m_ui.actionQuit, SIGNAL(triggered()),
63 this, SLOT(close()));
64
65 connect(m_ui.actionReplay, SIGNAL(triggered()),
66 this, SLOT(replayStart()));
67 connect(m_ui.actionStop, SIGNAL(triggered()),
68 this, SLOT(replayStop()));
Zack Rusin2caa06d2011-03-30 18:30:20 -040069 connect(m_ui.actionLookupState, SIGNAL(triggered()),
70 this, SLOT(lookupState()));
Zack Rusin27cb2c42011-03-27 23:53:36 -040071
Zack Rusin96130ac2011-03-27 01:48:36 -040072 connect(m_ui.callView, SIGNAL(activated(const QModelIndex &)),
73 this, SLOT(callItemSelected(const QModelIndex &)));
Zack Rusinea295452011-03-27 02:22:13 -040074 connect(m_filterEdit, SIGNAL(returnPressed()),
75 this, SLOT(filterTrace()));
Zack Rusin601e8372011-03-24 22:23:21 -040076}
77
78void MainWindow::openTrace()
79{
80 QString fileName =
81 QFileDialog::getOpenFileName(
82 this,
83 tr("Open Trace"),
84 QDir::homePath(),
85 tr("Trace Files (*.trace)"));
86
87 qDebug()<< "File name : " <<fileName;
88
Zack Rusin27cb2c42011-03-27 23:53:36 -040089 newTraceFile(fileName);
Zack Rusin601e8372011-03-24 22:23:21 -040090}
91
92void MainWindow::loadTrace(const QString &fileName)
93{
Zack Rusin27cb2c42011-03-27 23:53:36 -040094 if (!QFile::exists(fileName)) {
95 QMessageBox::warning(this, tr("File Missing"),
96 tr("File '%1' doesn't exist.").arg(fileName));
97 return;
98 }
Zack Rusin601e8372011-03-24 22:23:21 -040099 qDebug()<< "Loading : " <<fileName;
100
Zack Rusinde4ea412011-03-30 11:30:08 -0400101 m_progressBar->setValue(0);
Zack Rusin27cb2c42011-03-27 23:53:36 -0400102 newTraceFile(fileName);
Zack Rusin601e8372011-03-24 22:23:21 -0400103}
104
Zack Rusin96130ac2011-03-27 01:48:36 -0400105void MainWindow::callItemSelected(const QModelIndex &index)
106{
107 ApiTraceCall *call = index.data().value<ApiTraceCall*>();
108 if (call) {
Zack Rusin27cb2c42011-03-27 23:53:36 -0400109 m_ui.detailsWebView->setHtml(call->toHtml());
Zack Rusin96130ac2011-03-27 01:48:36 -0400110 m_ui.detailsDock->show();
Zack Rusin2caa06d2011-03-30 18:30:20 -0400111 m_currentFrame = call->parentFrame;
Zack Rusin96130ac2011-03-27 01:48:36 -0400112 } else {
Zack Rusin2caa06d2011-03-30 18:30:20 -0400113 m_currentFrame = index.data().value<ApiTraceFrame*>();
Zack Rusin96130ac2011-03-27 01:48:36 -0400114 m_ui.detailsDock->hide();
115 }
Zack Rusin11f7e632011-03-30 22:47:51 -0400116 if (m_currentFrame && !m_currentFrame->state.isEmpty()) {
117 fillStateForFrame();
118 } else
119 m_ui.stateDock->hide();
Zack Rusin96130ac2011-03-27 01:48:36 -0400120}
121
Zack Rusinea295452011-03-27 02:22:13 -0400122void MainWindow::filterTrace()
123{
124 m_proxyModel->setFilterString(m_filterEdit->text());
125}
126
Zack Rusin27cb2c42011-03-27 23:53:36 -0400127void MainWindow::replayStart()
128{
Zack Rusin2caa06d2011-03-30 18:30:20 -0400129 replayTrace(false);
Zack Rusin27cb2c42011-03-27 23:53:36 -0400130}
131
132void MainWindow::replayStop()
133{
134 if (m_replayProcess) {
135 m_replayProcess->kill();
136
137 m_ui.actionStop->setEnabled(false);
138 m_ui.actionReplay->setEnabled(true);
Zack Rusin2caa06d2011-03-30 18:30:20 -0400139 m_ui.actionLookupState->setEnabled(true);
Zack Rusin27cb2c42011-03-27 23:53:36 -0400140 }
141}
142
143void MainWindow::newTraceFile(const QString &fileName)
144{
145 m_traceFileName = fileName;
Zack Rusinf6667d12011-03-30 11:03:37 -0400146 m_trace->setFileName(fileName);
Zack Rusin27cb2c42011-03-27 23:53:36 -0400147
148 if (m_traceFileName.isEmpty()) {
149 m_ui.actionReplay->setEnabled(false);
Zack Rusin2caa06d2011-03-30 18:30:20 -0400150 m_ui.actionLookupState->setEnabled(false);
Zack Rusin27cb2c42011-03-27 23:53:36 -0400151 } else {
152 m_ui.actionReplay->setEnabled(true);
Zack Rusin2caa06d2011-03-30 18:30:20 -0400153 m_ui.actionLookupState->setEnabled(true);
Zack Rusin27cb2c42011-03-27 23:53:36 -0400154 }
155}
156
157void MainWindow::replayFinished()
158{
159 m_ui.actionStop->setEnabled(false);
160 m_ui.actionReplay->setEnabled(true);
Zack Rusin2caa06d2011-03-30 18:30:20 -0400161 m_ui.actionLookupState->setEnabled(true);
Zack Rusin27cb2c42011-03-27 23:53:36 -0400162
Zack Rusin2caa06d2011-03-30 18:30:20 -0400163 QByteArray output = m_replayProcess->readAllStandardOutput();
Zack Rusin27cb2c42011-03-27 23:53:36 -0400164
Zack Rusin11f7e632011-03-30 22:47:51 -0400165#if 0
Zack Rusin27cb2c42011-03-27 23:53:36 -0400166 qDebug()<<"Process finished = ";
167 qDebug()<<"\terr = "<<m_replayProcess->readAllStandardError();
168 qDebug()<<"\tout = "<<output;
169#endif
170
Zack Rusin2caa06d2011-03-30 18:30:20 -0400171 if (m_findingState) {
Zack Rusin11f7e632011-03-30 22:47:51 -0400172 bool ok = false;
173 QVariantMap parsedJson = m_jsonParser->parse(output, &ok).toMap();
174 parseState(parsedJson[QLatin1String("parameters")].toMap());
Zack Rusin2caa06d2011-03-30 18:30:20 -0400175 } else if (output.length() < 80) {
Zack Rusin27cb2c42011-03-27 23:53:36 -0400176 statusBar()->showMessage(output);
177 }
Zack Rusin11f7e632011-03-30 22:47:51 -0400178 m_stateFrame = 0;
179 m_findingState = false;
Zack Rusin27cb2c42011-03-27 23:53:36 -0400180}
181
182void MainWindow::replayError(QProcess::ProcessError err)
183{
184 m_ui.actionStop->setEnabled(false);
185 m_ui.actionReplay->setEnabled(true);
Zack Rusin2caa06d2011-03-30 18:30:20 -0400186 m_ui.actionLookupState->setEnabled(true);
187 m_findingState = false;
Zack Rusin11f7e632011-03-30 22:47:51 -0400188 m_stateFrame = 0;
Zack Rusin27cb2c42011-03-27 23:53:36 -0400189
190 qDebug()<<"Process error = "<<err;
191 qDebug()<<"\terr = "<<m_replayProcess->readAllStandardError();
192 qDebug()<<"\tout = "<<m_replayProcess->readAllStandardOutput();
193 QMessageBox::warning(
194 this, tr("Replay Failed"),
195 tr("Couldn't execute the replay file '%1'").arg(m_traceFileName));
196}
197
Zack Rusinde4ea412011-03-30 11:30:08 -0400198void MainWindow::startedLoadingTrace()
199{
200 Q_ASSERT(m_trace);
201 m_progressBar->show();
202 QFileInfo info(m_trace->fileName());
203 statusBar()->showMessage(
204 tr("Loading %1...").arg(info.fileName()));
205}
206
207void MainWindow::finishedLoadingTrace()
208{
209 m_progressBar->hide();
210 if (!m_trace) {
211 return;
212 }
213 QFileInfo info(m_trace->fileName());
214 statusBar()->showMessage(
215 tr("Loaded %1").arg(info.fileName()), 3000);
216}
217
Zack Rusin2caa06d2011-03-30 18:30:20 -0400218void MainWindow::replayTrace(bool dumpState)
219{
220 if (!m_replayProcess) {
221#ifdef Q_OS_WIN
222 QString format = QLatin1String("%1;");
223#else
224 QString format = QLatin1String("%1:");
225#endif
226 QString buildPath = format.arg(BUILD_DIR);
227 QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
228 env.insert("PATH", buildPath + env.value("PATH"));
229
230 qputenv("PATH", env.value("PATH").toLatin1());
231
232 m_replayProcess = new QProcess(this);
233 m_replayProcess->setProcessEnvironment(env);
234
235 connect(m_replayProcess, SIGNAL(finished(int, QProcess::ExitStatus)),
236 this, SLOT(replayFinished()));
237 connect(m_replayProcess, SIGNAL(error(QProcess::ProcessError)),
238 this, SLOT(replayError(QProcess::ProcessError)));
239 }
240
241 if (m_traceFileName.isEmpty())
242 return;
243
244 QStringList arguments;
245 if (dumpState &&
246 m_currentFrame && !m_currentFrame->calls.isEmpty()) {
247 arguments << QLatin1String("-D");
248 arguments << QString::number(m_currentFrame->calls.first()->index);
249 }
250 arguments << m_traceFileName;
251
252 m_replayProcess->start(QLatin1String("glretrace"),
253 arguments);
254
255 m_ui.actionStop->setEnabled(true);
256}
257
258void MainWindow::lookupState()
259{
260 if (!m_currentFrame) {
261 QMessageBox::warning(
262 this, tr("Unknown Frame"),
263 tr("To inspect the state select a frame in the trace."));
264 return;
265 }
Zack Rusin11f7e632011-03-30 22:47:51 -0400266 m_stateFrame = m_currentFrame;
Zack Rusin2caa06d2011-03-30 18:30:20 -0400267 m_findingState = true;
268 replayTrace(true);
269}
270
Zack Rusin11f7e632011-03-30 22:47:51 -0400271MainWindow::~MainWindow()
272{
273 delete m_jsonParser;
274}
275
276void MainWindow::parseState(const QVariantMap &params)
277{
278 QVariantMap::const_iterator itr;
279
280 m_stateFrame->state.clear();
281 m_stateFrame->state = params;
282 if (m_currentFrame == m_stateFrame) {
283 fillStateForFrame();
284 } else {
285 m_ui.stateDock->hide();
286 }
287}
288
289static void
290variantToString(const QVariant &var, QString &str)
291{
292 if (var.type() == QVariant::List) {
293 QVariantList lst = var.toList();
294 str += QLatin1String("[");
295 for (int i = 0; i < lst.count(); ++i) {
296 QVariant val = lst[i];
297 variantToString(val, str);
298 if (i < lst.count() - 1)
299 str += QLatin1String(", ");
300 }
301 str += QLatin1String("]");
302 } else if (var.type() == QVariant::Map) {
303 Q_ASSERT(!"unsupported state type");
304 } else if (var.type() == QVariant::Hash) {
305 Q_ASSERT(!"unsupported state type");
306 } else {
307 str += var.toString();
308 }
309}
310
311void MainWindow::fillStateForFrame()
312{
313 QVariantMap::const_iterator itr;
314 QVariantMap params;
315
316 if (!m_currentFrame || m_currentFrame->state.isEmpty())
317 return;
318
319 m_ui.stateTreeWidget->clear();
320 params = m_currentFrame->state;
321 QList<QTreeWidgetItem *> items;
322 for (itr = params.constBegin(); itr != params.constEnd(); ++itr) {
323 QString key = itr.key();
324 QString val;
325
326 variantToString(itr.value(), val);
327 //qDebug()<<"key = "<<key;
328 //qDebug()<<"val = "<<val;
329 QStringList lst;
330 lst += key;
331 lst += val;
332 items.append(new QTreeWidgetItem((QTreeWidget*)0, lst));
333 }
334 m_ui.stateTreeWidget->insertTopLevelItems(0, items);
335 m_ui.stateDock->show();
336}
337
Zack Rusin601e8372011-03-24 22:23:21 -0400338#include "mainwindow.moc"