blob: 93add0ee97d47864b0d437aa56c259efd0af7eb2 [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 Rusin581e3ff2011-03-31 23:58:07 -040026 m_selectedEvent(0),
27 m_stateEvent(0),
Zack Rusin11f7e632011-03-30 22:47:51 -040028 m_findingState(false),
29 m_jsonParser(new QJson::Parser())
Zack Rusin601e8372011-03-24 22:23:21 -040030{
31 m_ui.setupUi(this);
José Fonsecaf2c40fb2011-04-01 10:05:53 +010032 m_ui.stateTreeWidget->sortByColumn(0, Qt::AscendingOrder);
Zack Rusin601e8372011-03-24 22:23:21 -040033
Zack Rusinf6667d12011-03-30 11:03:37 -040034 m_trace = new ApiTrace();
Zack Rusinde4ea412011-03-30 11:30:08 -040035 connect(m_trace, SIGNAL(startedLoadingTrace()),
36 this, SLOT(startedLoadingTrace()));
37 connect(m_trace, SIGNAL(finishedLoadingTrace()),
38 this, SLOT(finishedLoadingTrace()));
Zack Rusinf6667d12011-03-30 11:03:37 -040039
Zack Rusin601e8372011-03-24 22:23:21 -040040 m_model = new ApiTraceModel();
Zack Rusinf6667d12011-03-30 11:03:37 -040041 m_model->setApiTrace(m_trace);
Zack Rusin91065372011-03-26 01:54:10 -040042 m_proxyModel = new ApiTraceFilter();
43 m_proxyModel->setSourceModel(m_model);
Zack Rusin96130ac2011-03-27 01:48:36 -040044 m_ui.callView->setModel(m_proxyModel);
Zack Rusin18eade52011-03-26 14:23:35 -040045 m_ui.callView->setItemDelegate(new ApiCallDelegate);
Zack Rusinc1acc7f2011-04-02 01:34:04 -040046 m_ui.callView->resizeColumnToContents(0);
47 m_ui.callView->header()->swapSections(0, 1);
48 m_ui.callView->setColumnWidth(1, 42);
Zack Rusin601e8372011-03-24 22:23:21 -040049
Zack Rusinea295452011-03-27 02:22:13 -040050 QToolBar *toolBar = addToolBar(tr("Navigation"));
51 m_filterEdit = new QLineEdit(toolBar);
52 toolBar->addWidget(m_filterEdit);
53
Zack Rusinde4ea412011-03-30 11:30:08 -040054 m_progressBar = new QProgressBar();
55 m_progressBar->setRange(0, 0);
56 statusBar()->addPermanentWidget(m_progressBar);
57 m_progressBar->hide();
58
Zack Rusin96130ac2011-03-27 01:48:36 -040059 m_ui.detailsDock->hide();
Zack Rusin11f7e632011-03-30 22:47:51 -040060 m_ui.stateDock->hide();
Zack Rusin96130ac2011-03-27 01:48:36 -040061
Zack Rusin601e8372011-03-24 22:23:21 -040062 connect(m_ui.actionOpen, SIGNAL(triggered()),
63 this, SLOT(openTrace()));
Zack Rusin27cb2c42011-03-27 23:53:36 -040064 connect(m_ui.actionQuit, SIGNAL(triggered()),
65 this, SLOT(close()));
66
67 connect(m_ui.actionReplay, SIGNAL(triggered()),
68 this, SLOT(replayStart()));
69 connect(m_ui.actionStop, SIGNAL(triggered()),
70 this, SLOT(replayStop()));
Zack Rusin2caa06d2011-03-30 18:30:20 -040071 connect(m_ui.actionLookupState, SIGNAL(triggered()),
72 this, SLOT(lookupState()));
Zack Rusin27cb2c42011-03-27 23:53:36 -040073
Zack Rusin96130ac2011-03-27 01:48:36 -040074 connect(m_ui.callView, SIGNAL(activated(const QModelIndex &)),
75 this, SLOT(callItemSelected(const QModelIndex &)));
Zack Rusinea295452011-03-27 02:22:13 -040076 connect(m_filterEdit, SIGNAL(returnPressed()),
77 this, SLOT(filterTrace()));
Zack Rusin601e8372011-03-24 22:23:21 -040078}
79
80void MainWindow::openTrace()
81{
82 QString fileName =
83 QFileDialog::getOpenFileName(
84 this,
85 tr("Open Trace"),
86 QDir::homePath(),
87 tr("Trace Files (*.trace)"));
88
89 qDebug()<< "File name : " <<fileName;
90
Zack Rusin27cb2c42011-03-27 23:53:36 -040091 newTraceFile(fileName);
Zack Rusin601e8372011-03-24 22:23:21 -040092}
93
94void MainWindow::loadTrace(const QString &fileName)
95{
Zack Rusin27cb2c42011-03-27 23:53:36 -040096 if (!QFile::exists(fileName)) {
97 QMessageBox::warning(this, tr("File Missing"),
98 tr("File '%1' doesn't exist.").arg(fileName));
99 return;
100 }
Zack Rusin601e8372011-03-24 22:23:21 -0400101 qDebug()<< "Loading : " <<fileName;
102
Zack Rusinde4ea412011-03-30 11:30:08 -0400103 m_progressBar->setValue(0);
Zack Rusin27cb2c42011-03-27 23:53:36 -0400104 newTraceFile(fileName);
Zack Rusin601e8372011-03-24 22:23:21 -0400105}
106
Zack Rusin96130ac2011-03-27 01:48:36 -0400107void MainWindow::callItemSelected(const QModelIndex &index)
108{
Zack Rusinc1acc7f2011-04-02 01:34:04 -0400109 ApiTraceEvent *event =
110 index.data(ApiTraceModel::EventRole).value<ApiTraceEvent*>();
111
112 if (event && event->type() == ApiTraceEvent::Call) {
113 ApiTraceCall *call = static_cast<ApiTraceCall*>(event);
Zack Rusin27cb2c42011-03-27 23:53:36 -0400114 m_ui.detailsWebView->setHtml(call->toHtml());
Zack Rusin96130ac2011-03-27 01:48:36 -0400115 m_ui.detailsDock->show();
Zack Rusin581e3ff2011-03-31 23:58:07 -0400116 m_selectedEvent = call;
Zack Rusin96130ac2011-03-27 01:48:36 -0400117 } else {
Zack Rusinc1acc7f2011-04-02 01:34:04 -0400118 if (event && event->type() == ApiTraceEvent::Frame) {
119 m_selectedEvent = static_cast<ApiTraceFrame*>(event);
120 } else
121 m_selectedEvent = 0;
Zack Rusin96130ac2011-03-27 01:48:36 -0400122 m_ui.detailsDock->hide();
123 }
Zack Rusin581e3ff2011-03-31 23:58:07 -0400124 if (m_selectedEvent && !m_selectedEvent->state().isEmpty()) {
Zack Rusin11f7e632011-03-30 22:47:51 -0400125 fillStateForFrame();
126 } else
127 m_ui.stateDock->hide();
Zack Rusin96130ac2011-03-27 01:48:36 -0400128}
129
Zack Rusinea295452011-03-27 02:22:13 -0400130void MainWindow::filterTrace()
131{
132 m_proxyModel->setFilterString(m_filterEdit->text());
133}
134
Zack Rusin27cb2c42011-03-27 23:53:36 -0400135void MainWindow::replayStart()
136{
Zack Rusin2caa06d2011-03-30 18:30:20 -0400137 replayTrace(false);
Zack Rusin27cb2c42011-03-27 23:53:36 -0400138}
139
140void MainWindow::replayStop()
141{
142 if (m_replayProcess) {
143 m_replayProcess->kill();
144
145 m_ui.actionStop->setEnabled(false);
146 m_ui.actionReplay->setEnabled(true);
Zack Rusin2caa06d2011-03-30 18:30:20 -0400147 m_ui.actionLookupState->setEnabled(true);
Zack Rusin27cb2c42011-03-27 23:53:36 -0400148 }
149}
150
151void MainWindow::newTraceFile(const QString &fileName)
152{
153 m_traceFileName = fileName;
Zack Rusinf6667d12011-03-30 11:03:37 -0400154 m_trace->setFileName(fileName);
Zack Rusin27cb2c42011-03-27 23:53:36 -0400155
156 if (m_traceFileName.isEmpty()) {
157 m_ui.actionReplay->setEnabled(false);
Zack Rusin2caa06d2011-03-30 18:30:20 -0400158 m_ui.actionLookupState->setEnabled(false);
Zack Rusin27cb2c42011-03-27 23:53:36 -0400159 } else {
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 }
163}
164
165void MainWindow::replayFinished()
166{
167 m_ui.actionStop->setEnabled(false);
168 m_ui.actionReplay->setEnabled(true);
Zack Rusin2caa06d2011-03-30 18:30:20 -0400169 m_ui.actionLookupState->setEnabled(true);
Zack Rusin27cb2c42011-03-27 23:53:36 -0400170
Zack Rusin2caa06d2011-03-30 18:30:20 -0400171 QByteArray output = m_replayProcess->readAllStandardOutput();
Zack Rusin27cb2c42011-03-27 23:53:36 -0400172
Zack Rusin11f7e632011-03-30 22:47:51 -0400173#if 0
Zack Rusin27cb2c42011-03-27 23:53:36 -0400174 qDebug()<<"Process finished = ";
175 qDebug()<<"\terr = "<<m_replayProcess->readAllStandardError();
176 qDebug()<<"\tout = "<<output;
177#endif
178
Zack Rusin2caa06d2011-03-30 18:30:20 -0400179 if (m_findingState) {
Zack Rusin11f7e632011-03-30 22:47:51 -0400180 bool ok = false;
181 QVariantMap parsedJson = m_jsonParser->parse(output, &ok).toMap();
182 parseState(parsedJson[QLatin1String("parameters")].toMap());
Zack Rusin2caa06d2011-03-30 18:30:20 -0400183 } else if (output.length() < 80) {
Zack Rusin27cb2c42011-03-27 23:53:36 -0400184 statusBar()->showMessage(output);
185 }
Zack Rusin581e3ff2011-03-31 23:58:07 -0400186 m_stateEvent = 0;
Zack Rusin11f7e632011-03-30 22:47:51 -0400187 m_findingState = false;
Zack Rusin27cb2c42011-03-27 23:53:36 -0400188}
189
190void MainWindow::replayError(QProcess::ProcessError err)
191{
192 m_ui.actionStop->setEnabled(false);
193 m_ui.actionReplay->setEnabled(true);
Zack Rusin2caa06d2011-03-30 18:30:20 -0400194 m_ui.actionLookupState->setEnabled(true);
195 m_findingState = false;
Zack Rusin581e3ff2011-03-31 23:58:07 -0400196 m_stateEvent = 0;
Zack Rusin27cb2c42011-03-27 23:53:36 -0400197
198 qDebug()<<"Process error = "<<err;
199 qDebug()<<"\terr = "<<m_replayProcess->readAllStandardError();
200 qDebug()<<"\tout = "<<m_replayProcess->readAllStandardOutput();
201 QMessageBox::warning(
202 this, tr("Replay Failed"),
203 tr("Couldn't execute the replay file '%1'").arg(m_traceFileName));
204}
205
Zack Rusinde4ea412011-03-30 11:30:08 -0400206void MainWindow::startedLoadingTrace()
207{
208 Q_ASSERT(m_trace);
209 m_progressBar->show();
210 QFileInfo info(m_trace->fileName());
211 statusBar()->showMessage(
212 tr("Loading %1...").arg(info.fileName()));
213}
214
215void MainWindow::finishedLoadingTrace()
216{
217 m_progressBar->hide();
218 if (!m_trace) {
219 return;
220 }
221 QFileInfo info(m_trace->fileName());
222 statusBar()->showMessage(
223 tr("Loaded %1").arg(info.fileName()), 3000);
224}
225
Zack Rusin2caa06d2011-03-30 18:30:20 -0400226void MainWindow::replayTrace(bool dumpState)
227{
228 if (!m_replayProcess) {
229#ifdef Q_OS_WIN
230 QString format = QLatin1String("%1;");
231#else
232 QString format = QLatin1String("%1:");
233#endif
234 QString buildPath = format.arg(BUILD_DIR);
235 QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
236 env.insert("PATH", buildPath + env.value("PATH"));
237
238 qputenv("PATH", env.value("PATH").toLatin1());
239
240 m_replayProcess = new QProcess(this);
241 m_replayProcess->setProcessEnvironment(env);
242
243 connect(m_replayProcess, SIGNAL(finished(int, QProcess::ExitStatus)),
244 this, SLOT(replayFinished()));
245 connect(m_replayProcess, SIGNAL(error(QProcess::ProcessError)),
246 this, SLOT(replayError(QProcess::ProcessError)));
247 }
248
249 if (m_traceFileName.isEmpty())
250 return;
251
252 QStringList arguments;
253 if (dumpState &&
Zack Rusin581e3ff2011-03-31 23:58:07 -0400254 m_selectedEvent) {
255 int index = 0;
256 if (m_selectedEvent->type() == ApiTraceEvent::Call) {
257 index = static_cast<ApiTraceCall*>(m_selectedEvent)->index;
258 } else if (m_selectedEvent->type() == ApiTraceEvent::Frame) {
259 ApiTraceFrame *frame = static_cast<ApiTraceFrame*>(m_selectedEvent);
260 if (frame->calls.isEmpty()) {
261 //XXX i guess we could still get the current state
262 qDebug()<<"tried to get a state for an empty frame";
263 return;
264 }
265 index = frame->calls.first()->index;
266 } else {
267 qDebug()<<"Unknown event type";
268 return;
269 }
Zack Rusin2caa06d2011-03-30 18:30:20 -0400270 arguments << QLatin1String("-D");
Zack Rusin581e3ff2011-03-31 23:58:07 -0400271 arguments << QString::number(index);
Zack Rusin2caa06d2011-03-30 18:30:20 -0400272 }
273 arguments << m_traceFileName;
274
275 m_replayProcess->start(QLatin1String("glretrace"),
276 arguments);
277
278 m_ui.actionStop->setEnabled(true);
279}
280
281void MainWindow::lookupState()
282{
Zack Rusin581e3ff2011-03-31 23:58:07 -0400283 if (!m_selectedEvent) {
Zack Rusin2caa06d2011-03-30 18:30:20 -0400284 QMessageBox::warning(
Zack Rusin581e3ff2011-03-31 23:58:07 -0400285 this, tr("Unknown Event"),
286 tr("To inspect the state select an event in the event list."));
Zack Rusin2caa06d2011-03-30 18:30:20 -0400287 return;
288 }
Zack Rusin581e3ff2011-03-31 23:58:07 -0400289 m_stateEvent = m_selectedEvent;
Zack Rusin2caa06d2011-03-30 18:30:20 -0400290 m_findingState = true;
291 replayTrace(true);
292}
293
Zack Rusin11f7e632011-03-30 22:47:51 -0400294MainWindow::~MainWindow()
295{
296 delete m_jsonParser;
297}
298
299void MainWindow::parseState(const QVariantMap &params)
300{
301 QVariantMap::const_iterator itr;
302
Zack Rusin581e3ff2011-03-31 23:58:07 -0400303 m_stateEvent->setState(params);
Zack Rusinc1acc7f2011-04-02 01:34:04 -0400304 m_model->stateSetOnEvent(m_stateEvent);
Zack Rusin581e3ff2011-03-31 23:58:07 -0400305 if (m_selectedEvent == m_stateEvent) {
Zack Rusin11f7e632011-03-30 22:47:51 -0400306 fillStateForFrame();
307 } else {
308 m_ui.stateDock->hide();
309 }
310}
311
312static void
313variantToString(const QVariant &var, QString &str)
314{
315 if (var.type() == QVariant::List) {
316 QVariantList lst = var.toList();
317 str += QLatin1String("[");
318 for (int i = 0; i < lst.count(); ++i) {
319 QVariant val = lst[i];
320 variantToString(val, str);
321 if (i < lst.count() - 1)
322 str += QLatin1String(", ");
323 }
324 str += QLatin1String("]");
325 } else if (var.type() == QVariant::Map) {
326 Q_ASSERT(!"unsupported state type");
327 } else if (var.type() == QVariant::Hash) {
328 Q_ASSERT(!"unsupported state type");
329 } else {
330 str += var.toString();
331 }
332}
333
334void MainWindow::fillStateForFrame()
335{
336 QVariantMap::const_iterator itr;
337 QVariantMap params;
338
Zack Rusin581e3ff2011-03-31 23:58:07 -0400339 if (!m_selectedEvent || m_selectedEvent->state().isEmpty())
Zack Rusin11f7e632011-03-30 22:47:51 -0400340 return;
341
342 m_ui.stateTreeWidget->clear();
Zack Rusin581e3ff2011-03-31 23:58:07 -0400343 params = m_selectedEvent->state();
Zack Rusin11f7e632011-03-30 22:47:51 -0400344 QList<QTreeWidgetItem *> items;
345 for (itr = params.constBegin(); itr != params.constEnd(); ++itr) {
346 QString key = itr.key();
347 QString val;
348
349 variantToString(itr.value(), val);
350 //qDebug()<<"key = "<<key;
351 //qDebug()<<"val = "<<val;
352 QStringList lst;
353 lst += key;
354 lst += val;
355 items.append(new QTreeWidgetItem((QTreeWidget*)0, lst));
356 }
357 m_ui.stateTreeWidget->insertTopLevelItems(0, items);
358 m_ui.stateDock->show();
359}
360
Zack Rusin601e8372011-03-24 22:23:21 -0400361#include "mainwindow.moc"