blob: 1fc8b35621639605217939cb435995aa9417952a [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 Rusin963102f2011-04-15 01:45:05 -04008#include "argumentseditor.h"
Zack Rusin09ec4842011-04-10 01:57:17 -04009#include "imageviewer.h"
Zack Rusinc52d18a2011-04-11 00:15:07 -040010#include "jumpwidget.h"
James Bentonfc4f55a2012-08-08 17:09:07 +010011#include "profiledialog.h"
Zack Rusin3acde362011-04-06 01:11:55 -040012#include "retracer.h"
Zack Rusinf04cf8a2011-04-12 23:21:52 -040013#include "searchwidget.h"
Zack Rusine1745572011-04-03 14:30:19 -040014#include "settingsdialog.h"
Zack Rusin7c814f12011-04-09 19:20:58 -040015#include "shaderssourcewidget.h"
Zack Rusin3438a522011-04-10 22:56:31 -040016#include "tracedialog.h"
Zack Rusinca164112011-04-11 02:23:09 -040017#include "traceprocess.h"
Dan McCabe1c3ddde2012-03-21 09:53:45 -070018#include "trimprocess.h"
José Fonseca3f456402012-03-25 20:59:24 +010019#include "thumbnail.h"
Zack Rusin3165c832011-04-07 20:32:46 -040020#include "ui_retracerdialog.h"
James Bentonfc4f55a2012-08-08 17:09:07 +010021#include "ui_profilereplaydialog.h"
Zack Rusin8e7a4ff2011-04-07 01:15:48 -040022#include "vertexdatainterpreter.h"
James Bentonfc4f55a2012-08-08 17:09:07 +010023#include "trace_profiler.hpp"
Jose Fonsecabceafec2016-05-05 11:09:52 +010024#include "image.hpp"
Jose Fonsecaa20a7952016-01-19 14:16:24 +000025#include "leaktracethread.h"
Zack Rusin601e8372011-03-24 22:23:21 -040026
27#include <QAction>
Zack Rusin96a83492011-04-23 02:30:29 -040028#include <QApplication>
Zack Rusin601e8372011-03-24 22:23:21 -040029#include <QDebug>
Zack Rusinc97fadc2011-04-07 15:16:59 -040030#include <QDesktopServices>
Zack Rusin96a83492011-04-23 02:30:29 -040031#include <QDesktopWidget>
Zack Rusin601e8372011-03-24 22:23:21 -040032#include <QDir>
33#include <QFileDialog>
Zack Rusin27cb2c42011-03-27 23:53:36 -040034#include <QLineEdit>
35#include <QMessageBox>
Zack Rusinde4ea412011-03-30 11:30:08 -040036#include <QProgressBar>
Zack Rusinea295452011-03-27 02:22:13 -040037#include <QToolBar>
Zack Rusinc97fadc2011-04-07 15:16:59 -040038#include <QUrl>
Zack Rusin7c814f12011-04-09 19:20:58 -040039#include <QVBoxLayout>
Jose Fonseca3b7e9c02016-03-21 14:20:55 +000040#include <QTextBrowser>
Zack Rusin601e8372011-03-24 22:23:21 -040041
42
43MainWindow::MainWindow()
Zack Rusin27cb2c42011-03-27 23:53:36 -040044 : QMainWindow(),
Jose Fonseca65d26052017-07-30 13:48:40 +010045 m_api(trace::API_GL),
José Fonsecab7eb1522011-11-27 15:15:33 +000046 m_initalCallNum(-1),
Zack Rusin581e3ff2011-03-31 23:58:07 -040047 m_selectedEvent(0),
Zack Rusin3b7fbd72011-04-27 23:48:16 -040048 m_stateEvent(0),
49 m_nonDefaultsLookupEvent(0)
Zack Rusin601e8372011-03-24 22:23:21 -040050{
51 m_ui.setupUi(this);
Alexandr Akulich1af94092012-12-07 16:59:52 +060052 updateActionsState(false);
Zack Rusin46678422011-04-10 12:15:46 -040053 initObjects();
54 initConnections();
Zack Rusin601e8372011-03-24 22:23:21 -040055}
56
James Bentonfc4f55a2012-08-08 17:09:07 +010057MainWindow::~MainWindow()
58{
59 delete m_trace;
60 m_trace = 0;
61
62 delete m_proxyModel;
63 delete m_model;
64}
65
Zack Rusin3438a522011-04-10 22:56:31 -040066void MainWindow::createTrace()
67{
Zack Rusinca164112011-04-11 02:23:09 -040068 if (!m_traceProcess->canTrace()) {
69 QMessageBox::warning(
70 this,
71 tr("Unsupported"),
72 tr("Current configuration doesn't support tracing."));
73 return;
74 }
75
Zack Rusinc5929572011-09-19 03:04:40 -040076 TraceDialog dialog;
Zack Rusin3438a522011-04-10 22:56:31 -040077 if (dialog.exec() == QDialog::Accepted) {
78 qDebug()<< "App : " <<dialog.applicationPath();
79 qDebug()<< " Arguments: "<<dialog.arguments();
José Fonseca2cdc9402012-02-28 17:12:24 +000080 m_traceProcess->setApi(dialog.api());
Zack Rusinca164112011-04-11 02:23:09 -040081 m_traceProcess->setExecutablePath(dialog.applicationPath());
82 m_traceProcess->setArguments(dialog.arguments());
83 m_traceProcess->start();
Zack Rusin3438a522011-04-10 22:56:31 -040084 }
85}
86
Zack Rusin601e8372011-03-24 22:23:21 -040087void MainWindow::openTrace()
88{
89 QString fileName =
Zack Rusinc5929572011-09-19 03:04:40 -040090 QFileDialog::getOpenFileName(
91 this,
92 tr("Open Trace"),
93 QDir::homePath(),
94 tr("Trace Files (*.trace)"));
Zack Rusin601e8372011-03-24 22:23:21 -040095
Zack Rusinb108d682011-04-27 21:33:57 -040096 if (!fileName.isEmpty() && QFile::exists(fileName)) {
97 newTraceFile(fileName);
98 }
Zack Rusin601e8372011-03-24 22:23:21 -040099}
100
Alexander Trukhind99ab922015-03-27 23:38:01 +0300101void MainWindow::saveTrace()
102{
103 QString localFile = m_trace->fileName();
104
105 QString fileName =
106 QFileDialog::getSaveFileName(
107 this,
108 tr("Save Trace As"),
109 QFileInfo(localFile).fileName(),
110 tr("Trace Files (*.trace);;All Files (*)"));
111
112 if (!fileName.isEmpty()) {
Martin Schulze3b6cfd12016-03-29 16:48:07 +0200113 // copy won't overwrite existing files!
114 if (QFile::exists(fileName)) {
115 if (!QFile::remove(fileName)) {
116 QMessageBox::warning(
117 this, tr("Could not overwrite file"),
118 tr("The existing file %0 could not be replaced!")
119 .arg(fileName));
120 }
121 }
Alexander Trukhind99ab922015-03-27 23:38:01 +0300122 QFile::copy(localFile, fileName);
123 }
124}
125
José Fonsecab7eb1522011-11-27 15:15:33 +0000126void MainWindow::loadTrace(const QString &fileName, int callNum)
Zack Rusin601e8372011-03-24 22:23:21 -0400127{
Zack Rusin27cb2c42011-03-27 23:53:36 -0400128 if (!QFile::exists(fileName)) {
129 QMessageBox::warning(this, tr("File Missing"),
130 tr("File '%1' doesn't exist.").arg(fileName));
131 return;
132 }
Zack Rusin601e8372011-03-24 22:23:21 -0400133
José Fonsecab7eb1522011-11-27 15:15:33 +0000134 m_initalCallNum = callNum;
Zack Rusin27cb2c42011-03-27 23:53:36 -0400135 newTraceFile(fileName);
Zack Rusin601e8372011-03-24 22:23:21 -0400136}
137
Carl Worth7257dfc2012-08-09 08:21:42 -0700138void MainWindow::setRemoteTarget(const QString &host)
139{
140 m_retracer->setRemoteTarget(host);
141}
142
Zack Rusin96130ac2011-03-27 01:48:36 -0400143void MainWindow::callItemSelected(const QModelIndex &index)
144{
Zack Rusinc1acc7f2011-04-02 01:34:04 -0400145 ApiTraceEvent *event =
146 index.data(ApiTraceModel::EventRole).value<ApiTraceEvent*>();
147
148 if (event && event->type() == ApiTraceEvent::Call) {
149 ApiTraceCall *call = static_cast<ApiTraceCall*>(event);
Zack Rusin5a74d3c2011-11-16 23:52:15 -0500150 m_ui.detailsDock->setWindowTitle(
151 tr("Details View. Frame %1, Call %2")
152 .arg(call->parentFrame() ? call->parentFrame()->number : 0)
153 .arg(call->index()));
Zack Rusin27cb2c42011-03-27 23:53:36 -0400154 m_ui.detailsWebView->setHtml(call->toHtml());
Zack Rusin96130ac2011-03-27 01:48:36 -0400155 m_ui.detailsDock->show();
Lawrence L Love158f4092014-03-13 09:24:05 -0700156 m_ui.callView->scrollTo(index);
Zack Rusin8e7a4ff2011-04-07 01:15:48 -0400157 if (call->hasBinaryData()) {
158 QByteArray data =
Zack Rusinead6aad2011-04-15 22:16:18 -0400159 call->arguments()[call->binaryDataIndex()].toByteArray();
Zack Rusin8e7a4ff2011-04-07 01:15:48 -0400160 m_vdataInterpreter->setData(data);
161
Zack Rusinc5929572011-09-19 03:04:40 -0400162 QVector<QVariant> args = call->arguments();
Zack Rusinead6aad2011-04-15 22:16:18 -0400163 for (int i = 0; i < call->argNames().count(); ++i) {
164 QString name = call->argNames()[i];
Zack Rusin8e7a4ff2011-04-07 01:15:48 -0400165 if (name == QLatin1String("stride")) {
Zack Rusinead6aad2011-04-15 22:16:18 -0400166 int stride = args[i].toInt();
Zack Rusin8e7a4ff2011-04-07 01:15:48 -0400167 m_ui.vertexStrideSB->setValue(stride);
168 } else if (name == QLatin1String("size")) {
Zack Rusinead6aad2011-04-15 22:16:18 -0400169 int components = args[i].toInt();
Zack Rusin8e7a4ff2011-04-07 01:15:48 -0400170 m_ui.vertexComponentsSB->setValue(components);
171 } else if (name == QLatin1String("type")) {
Zack Rusinead6aad2011-04-15 22:16:18 -0400172 QString val = args[i].toString();
Zack Rusin8e7a4ff2011-04-07 01:15:48 -0400173 int textIndex = m_ui.vertexTypeCB->findText(val);
Zack Rusinc5929572011-09-19 03:04:40 -0400174 if (textIndex >= 0) {
Zack Rusin8e7a4ff2011-04-07 01:15:48 -0400175 m_ui.vertexTypeCB->setCurrentIndex(textIndex);
Zack Rusinc5929572011-09-19 03:04:40 -0400176 }
Zack Rusin8e7a4ff2011-04-07 01:15:48 -0400177 }
178 }
179 }
Alexander Monakov9d1b1c52013-05-13 15:33:54 +0100180 m_ui.backtraceBrowser->setText(call->backtrace());
181 m_ui.backtraceDock->setVisible(!call->backtrace().isNull());
Zack Rusin8e7a4ff2011-04-07 01:15:48 -0400182 m_ui.vertexDataDock->setVisible(call->hasBinaryData());
Zack Rusin581e3ff2011-03-31 23:58:07 -0400183 m_selectedEvent = call;
Zack Rusin96130ac2011-03-27 01:48:36 -0400184 } else {
Zack Rusinc1acc7f2011-04-02 01:34:04 -0400185 if (event && event->type() == ApiTraceEvent::Frame) {
186 m_selectedEvent = static_cast<ApiTraceFrame*>(event);
Zack Rusinc5929572011-09-19 03:04:40 -0400187 } else {
Zack Rusinc1acc7f2011-04-02 01:34:04 -0400188 m_selectedEvent = 0;
Zack Rusinc5929572011-09-19 03:04:40 -0400189 }
Zack Rusin96130ac2011-03-27 01:48:36 -0400190 m_ui.detailsDock->hide();
Eugene Velesevichaa1b2132013-04-23 17:56:14 +0400191 m_ui.backtraceDock->hide();
Zack Rusin8e7a4ff2011-04-07 01:15:48 -0400192 m_ui.vertexDataDock->hide();
Zack Rusin96130ac2011-03-27 01:48:36 -0400193 }
Zack Rusined40bc62011-08-28 17:11:02 -0400194 if (m_selectedEvent && m_selectedEvent->hasState()) {
Zack Rusin11f7e632011-03-30 22:47:51 -0400195 fillStateForFrame();
Zack Rusinc5929572011-09-19 03:04:40 -0400196 } else {
Zack Rusin11f7e632011-03-30 22:47:51 -0400197 m_ui.stateDock->hide();
Zack Rusinc5929572011-09-19 03:04:40 -0400198 }
Zack Rusin96130ac2011-03-27 01:48:36 -0400199}
200
José Fonseca63d59402011-10-30 10:56:04 +0000201void MainWindow::callItemActivated(const QModelIndex &index) {
202 lookupState();
203}
204
Zack Rusin27cb2c42011-03-27 23:53:36 -0400205void MainWindow::replayStart()
206{
Zack Rusin9af5bff2011-04-18 01:05:50 -0400207 if (m_trace->isSaving()) {
208 QMessageBox::warning(
209 this,
210 tr("Trace Saving"),
211 tr("QApiTrace is currently saving the edited trace file. "
212 "Please wait until it finishes and try again."));
213 return;
214 }
James Bentonfc4f55a2012-08-08 17:09:07 +0100215
Zack Rusin3165c832011-04-07 20:32:46 -0400216 QDialog dlg;
217 Ui_RetracerDialog dlgUi;
218 dlgUi.setupUi(&dlg);
219
220 dlgUi.doubleBufferingCB->setChecked(
221 m_retracer->isDoubleBuffered());
James Bentonfc4f55a2012-08-08 17:09:07 +0100222
Zack Rusin404a1ef2011-04-19 23:49:56 -0400223 dlgUi.errorCheckCB->setChecked(
224 !m_retracer->isBenchmarking());
Zack Rusin3165c832011-04-07 20:32:46 -0400225
Peter Lohrmannb34c6752013-07-10 11:08:14 -0400226 dlgUi.singlethreadCB->setChecked(
227 m_retracer->isSinglethread());
228
Corey Richardsonf3006462014-01-26 17:15:42 -0500229 dlgUi.coreProfileCB->setChecked(
230 m_retracer->isCoreProfile());
231
Zack Rusin3165c832011-04-07 20:32:46 -0400232 if (dlg.exec() == QDialog::Accepted) {
233 m_retracer->setDoubleBuffered(
234 dlgUi.doubleBufferingCB->isChecked());
James Bentonfc4f55a2012-08-08 17:09:07 +0100235
Zack Rusin3165c832011-04-07 20:32:46 -0400236 m_retracer->setBenchmarking(
Zack Rusin404a1ef2011-04-19 23:49:56 -0400237 !dlgUi.errorCheckCB->isChecked());
James Bentonfc4f55a2012-08-08 17:09:07 +0100238
Peter Lohrmannb34c6752013-07-10 11:08:14 -0400239 m_retracer->setSinglethread(
240 dlgUi.singlethreadCB->isChecked());
241
Corey Richardsonf3006462014-01-26 17:15:42 -0500242 m_retracer->setCoreProfile(
243 dlgUi.coreProfileCB->isChecked());
244
Jose Fonseca65d26052017-07-30 13:48:40 +0100245 m_retracer->setProfiling(false, false, false);
James Bentonfc4f55a2012-08-08 17:09:07 +0100246
247 replayTrace(false, false);
248 }
249}
250
251void MainWindow::replayProfile()
252{
253 if (m_trace->isSaving()) {
254 QMessageBox::warning(
255 this,
256 tr("Trace Saving"),
257 tr("QApiTrace is currently saving the edited trace file. "
258 "Please wait until it finishes and try again."));
259 return;
260 }
261
262 QDialog dlg;
263 Ui_ProfileReplayDialog dlgUi;
264 dlgUi.setupUi(&dlg);
265
266 if (dlg.exec() == QDialog::Accepted) {
267 m_retracer->setProfiling(
268 dlgUi.gpuTimesCB->isChecked(),
269 dlgUi.cpuTimesCB->isChecked(),
Jose Fonseca65d26052017-07-30 13:48:40 +0100270 dlgUi.pixelsDrawnCB->isChecked());
James Bentonfc4f55a2012-08-08 17:09:07 +0100271
272 replayTrace(false, false);
Zack Rusin3165c832011-04-07 20:32:46 -0400273 }
Zack Rusin27cb2c42011-03-27 23:53:36 -0400274}
275
276void MainWindow::replayStop()
277{
Zack Rusinf389ae82011-04-10 19:27:28 -0400278 m_retracer->quit();
Alexandr Akulich1af94092012-12-07 16:59:52 +0600279 updateActionsState(true, true);
Zack Rusin27cb2c42011-03-27 23:53:36 -0400280}
281
282void MainWindow::newTraceFile(const QString &fileName)
283{
José Fonseca11ad0ea2014-11-15 09:58:44 +0000284 qDebug()<< "Loading:" << fileName;
Zack Rusinb108d682011-04-27 21:33:57 -0400285
286 m_progressBar->setValue(0);
Zack Rusinf6667d12011-03-30 11:03:37 -0400287 m_trace->setFileName(fileName);
Zack Rusin27cb2c42011-03-27 23:53:36 -0400288
Zack Rusin0d041ac2011-04-17 02:42:07 -0400289 if (fileName.isEmpty()) {
Alexandr Akulich1af94092012-12-07 16:59:52 +0600290 updateActionsState(false);
Zack Rusina228d692011-04-06 17:29:39 -0400291 setWindowTitle(tr("QApiTrace"));
Zack Rusin27cb2c42011-03-27 23:53:36 -0400292 } else {
Alexandr Akulich1af94092012-12-07 16:59:52 +0600293 updateActionsState(true);
Zack Rusina228d692011-04-06 17:29:39 -0400294 QFileInfo info(fileName);
Zack Rusina228d692011-04-06 17:29:39 -0400295 setWindowTitle(
296 tr("QApiTrace - %1").arg(info.fileName()));
Zack Rusin27cb2c42011-03-27 23:53:36 -0400297 }
298}
299
José Fonseca126f64b2012-03-28 00:13:55 +0100300void MainWindow::replayFinished(const QString &message)
Zack Rusin27cb2c42011-03-27 23:53:36 -0400301{
Alexandr Akulich1af94092012-12-07 16:59:52 +0600302 updateActionsState(true);
Zack Rusinf389ae82011-04-10 19:27:28 -0400303 m_progressBar->hide();
José Fonseca126f64b2012-03-28 00:13:55 +0100304 statusBar()->showMessage(message, 2000);
Zack Rusin581e3ff2011-03-31 23:58:07 -0400305 m_stateEvent = 0;
Zack Rusina263fc52011-04-19 23:35:25 -0400306 m_ui.actionShowErrorsDock->setEnabled(m_trace->hasErrors());
307 m_ui.errorsDock->setVisible(m_trace->hasErrors());
Zack Rusinc5929572011-09-19 03:04:40 -0400308 if (!m_trace->hasErrors()) {
Zack Rusin30069572011-04-20 18:21:11 -0400309 m_ui.errorsTreeWidget->clear();
Zack Rusinc5929572011-09-19 03:04:40 -0400310 }
Zack Rusin27cb2c42011-03-27 23:53:36 -0400311}
312
Zack Rusin3acde362011-04-06 01:11:55 -0400313void MainWindow::replayError(const QString &message)
Zack Rusin27cb2c42011-03-27 23:53:36 -0400314{
Alexandr Akulich1af94092012-12-07 16:59:52 +0600315 updateActionsState(true);
Zack Rusin581e3ff2011-03-31 23:58:07 -0400316 m_stateEvent = 0;
Zack Rusin3b7fbd72011-04-27 23:48:16 -0400317 m_nonDefaultsLookupEvent = 0;
Zack Rusin27cb2c42011-03-27 23:53:36 -0400318
Zack Rusinf389ae82011-04-10 19:27:28 -0400319 m_progressBar->hide();
320 statusBar()->showMessage(
321 tr("Replaying unsuccessful."), 2000);
Zack Rusin27cb2c42011-03-27 23:53:36 -0400322 QMessageBox::warning(
Zack Rusin3acde362011-04-06 01:11:55 -0400323 this, tr("Replay Failed"), message);
Zack Rusin27cb2c42011-03-27 23:53:36 -0400324}
325
Jose Fonseca8f0846c2015-11-10 19:53:55 +0000326void MainWindow::loadError(const QString &message)
327{
328 m_progressBar->hide();
329 statusBar()->showMessage(
330 tr("Load unsuccessful."), 2000);
331 QMessageBox::warning(
332 this, tr("Load Failed"), message);
333}
334
Zack Rusinde4ea412011-03-30 11:30:08 -0400335void MainWindow::startedLoadingTrace()
336{
337 Q_ASSERT(m_trace);
338 m_progressBar->show();
339 QFileInfo info(m_trace->fileName());
340 statusBar()->showMessage(
341 tr("Loading %1...").arg(info.fileName()));
342}
343
344void MainWindow::finishedLoadingTrace()
345{
346 m_progressBar->hide();
347 if (!m_trace) {
348 return;
349 }
José Fonseca67964382012-03-27 23:54:30 +0100350 m_api = m_trace->api();
Zack Rusinde4ea412011-03-30 11:30:08 -0400351 QFileInfo info(m_trace->fileName());
352 statusBar()->showMessage(
353 tr("Loaded %1").arg(info.fileName()), 3000);
José Fonsecab7eb1522011-11-27 15:15:33 +0000354 if (m_initalCallNum >= 0) {
355 m_trace->findCallIndex(m_initalCallNum);
356 m_initalCallNum = -1;
Lawrence L Love55d98e62014-02-21 16:46:30 -0800357 } else {
358 m_trace->finishedParsing();
José Fonsecab7eb1522011-11-27 15:15:33 +0000359 }
Zack Rusinde4ea412011-03-30 11:30:08 -0400360}
361
Dan McCabe66dfdda2012-03-05 17:20:39 -0800362void MainWindow::replayTrace(bool dumpState, bool dumpThumbnails)
Zack Rusin2caa06d2011-03-30 18:30:20 -0400363{
Zack Rusinc5929572011-09-19 03:04:40 -0400364 if (m_trace->fileName().isEmpty()) {
Zack Rusin2caa06d2011-03-30 18:30:20 -0400365 return;
Zack Rusinc5929572011-09-19 03:04:40 -0400366 }
Zack Rusin2caa06d2011-03-30 18:30:20 -0400367
Zack Rusin0d041ac2011-04-17 02:42:07 -0400368 m_retracer->setFileName(m_trace->fileName());
José Fonseca62997b42011-11-27 15:16:34 +0000369 m_retracer->setAPI(m_api);
Zack Rusin3acde362011-04-06 01:11:55 -0400370 m_retracer->setCaptureState(dumpState);
Gabe Dagani9ff44052017-11-28 09:30:15 -0600371 m_retracer->setMsaaResolve(m_ui.surfacesResolveMSAA->isChecked());
Dan McCabe66dfdda2012-03-05 17:20:39 -0800372 m_retracer->setCaptureThumbnails(dumpThumbnails);
Zack Rusin3acde362011-04-06 01:11:55 -0400373 if (m_retracer->captureState() && m_selectedEvent) {
Zack Rusin581e3ff2011-03-31 23:58:07 -0400374 int index = 0;
375 if (m_selectedEvent->type() == ApiTraceEvent::Call) {
Zack Rusinead6aad2011-04-15 22:16:18 -0400376 index = static_cast<ApiTraceCall*>(m_selectedEvent)->index();
Zack Rusin581e3ff2011-03-31 23:58:07 -0400377 } else if (m_selectedEvent->type() == ApiTraceEvent::Frame) {
Zack Rusinf389ae82011-04-10 19:27:28 -0400378 ApiTraceFrame *frame =
379 static_cast<ApiTraceFrame*>(m_selectedEvent);
Zack Rusin1d31b6c2011-04-26 22:30:25 -0400380 if (frame->isEmpty()) {
Zack Rusin581e3ff2011-03-31 23:58:07 -0400381 //XXX i guess we could still get the current state
382 qDebug()<<"tried to get a state for an empty frame";
383 return;
384 }
Zack Rusin851d0b02011-09-14 22:04:07 -0400385 index = frame->lastCallIndex();
Zack Rusin581e3ff2011-03-31 23:58:07 -0400386 } else {
387 qDebug()<<"Unknown event type";
388 return;
389 }
Zack Rusin3acde362011-04-06 01:11:55 -0400390 m_retracer->setCaptureAtCallNumber(index);
Zack Rusin2caa06d2011-03-30 18:30:20 -0400391 }
Dan McCabe88938852012-06-01 13:40:04 -0700392 if (m_trace->isMissingThumbnails()) {
393 m_retracer->resetThumbnailsToCapture();
394 m_trace->iterateMissingThumbnails(this, this->thumbnailCallback);
395 m_trace->resetMissingThumbnails();
396 }
Zack Rusin3acde362011-04-06 01:11:55 -0400397 m_retracer->start();
Zack Rusin2caa06d2011-03-30 18:30:20 -0400398
399 m_ui.actionStop->setEnabled(true);
Zack Rusinf389ae82011-04-10 19:27:28 -0400400 m_progressBar->show();
Dan McCabe66dfdda2012-03-05 17:20:39 -0800401 if (dumpState || dumpThumbnails) {
402 if (dumpState && dumpThumbnails) {
403 statusBar()->showMessage(
404 tr("Looking up the state and capturing thumbnails..."));
405 } else if (dumpState) {
406 statusBar()->showMessage(
407 tr("Looking up the state..."));
408 } else if (dumpThumbnails) {
409 statusBar()->showMessage(
410 tr("Capturing thumbnails..."));
411 }
James Bentonfc4f55a2012-08-08 17:09:07 +0100412 } else if (m_retracer->isProfiling()) {
413 statusBar()->showMessage(
414 tr("Profiling draw calls in trace file..."));
Zack Rusinc5929572011-09-19 03:04:40 -0400415 } else {
Zack Rusinf389ae82011-04-10 19:27:28 -0400416 statusBar()->showMessage(
417 tr("Replaying the trace file..."));
Zack Rusinc5929572011-09-19 03:04:40 -0400418 }
Zack Rusin2caa06d2011-03-30 18:30:20 -0400419}
420
Dan McCabe1c3ddde2012-03-21 09:53:45 -0700421void MainWindow::trimEvent()
422{
Zack Rusin66ce10a2013-09-10 20:30:59 -0400423 int trimIndex = 0;
Dan McCabe1c3ddde2012-03-21 09:53:45 -0700424
Zack Rusin66ce10a2013-09-10 20:30:59 -0400425 Q_ASSERT(m_trimEvent->type() == ApiTraceEvent::Call ||
426 m_trimEvent->type() == ApiTraceEvent::Frame);
427
Dan McCabe1c3ddde2012-03-21 09:53:45 -0700428 if (m_trimEvent->type() == ApiTraceEvent::Call) {
429 ApiTraceCall *call = static_cast<ApiTraceCall*>(m_trimEvent);
430 trimIndex = call->index();
431 } else if (m_trimEvent->type() == ApiTraceEvent::Frame) {
432 ApiTraceFrame *frame = static_cast<ApiTraceFrame*>(m_trimEvent);
433 const QList<ApiTraceFrame*> frames = m_trace->frames();
434 trimIndex = frame->lastCallIndex();
435 }
436
437 m_trimProcess->setTracePath(m_trace->fileName());
438 m_trimProcess->setTrimIndex(trimIndex);
439
440 m_trimProcess->start();
441}
442
Zack Rusin2caa06d2011-03-30 18:30:20 -0400443void MainWindow::lookupState()
444{
Zack Rusin581e3ff2011-03-31 23:58:07 -0400445 if (!m_selectedEvent) {
Zack Rusin2caa06d2011-03-30 18:30:20 -0400446 QMessageBox::warning(
Zack Rusin581e3ff2011-03-31 23:58:07 -0400447 this, tr("Unknown Event"),
448 tr("To inspect the state select an event in the event list."));
Zack Rusin2caa06d2011-03-30 18:30:20 -0400449 return;
450 }
Zack Rusin9af5bff2011-04-18 01:05:50 -0400451 if (m_trace->isSaving()) {
452 QMessageBox::warning(
453 this,
454 tr("Trace Saving"),
455 tr("QApiTrace is currently saving the edited trace file. "
456 "Please wait until it finishes and try again."));
457 return;
458 }
Zack Rusin581e3ff2011-03-31 23:58:07 -0400459 m_stateEvent = m_selectedEvent;
Dan McCabe66dfdda2012-03-05 17:20:39 -0800460 replayTrace(true, false);
Zack Rusin2caa06d2011-03-30 18:30:20 -0400461}
462
José Fonsecae5fa5412012-03-24 09:27:27 +0000463void MainWindow::showThumbnails()
464{
465 replayTrace(false, true);
Zack Rusin601e8372011-03-24 22:23:21 -0400466}
467
Dan McCabe1c3ddde2012-03-21 09:53:45 -0700468void MainWindow::trim()
469{
470 if (!m_selectedEvent) {
471 QMessageBox::warning(
472 this, tr("Unknown Event"),
473 tr("To trim select a frame or an event in the event list."));
474 return;
475 }
476 m_trimEvent = m_selectedEvent;
477 trimEvent();
478}
479
Zack Rusin11f7e632011-03-30 22:47:51 -0400480static void
481variantToString(const QVariant &var, QString &str)
482{
483 if (var.type() == QVariant::List) {
Zack Rusinf736a622011-08-28 22:19:46 -0400484 QVector<QVariant> lst = var.toList().toVector();
Zack Rusin11f7e632011-03-30 22:47:51 -0400485 str += QLatin1String("[");
486 for (int i = 0; i < lst.count(); ++i) {
487 QVariant val = lst[i];
488 variantToString(val, str);
489 if (i < lst.count() - 1)
490 str += QLatin1String(", ");
491 }
492 str += QLatin1String("]");
493 } else if (var.type() == QVariant::Map) {
494 Q_ASSERT(!"unsupported state type");
495 } else if (var.type() == QVariant::Hash) {
496 Q_ASSERT(!"unsupported state type");
497 } else {
498 str += var.toString();
499 }
500}
501
José Fonseca333adcf2011-04-14 09:12:40 +0100502static QTreeWidgetItem *
Zack Rusinc5929572011-09-19 03:04:40 -0400503variantToItem(const QString &key, const QVariant &var,
504 const QVariant &defaultVar);
José Fonseca333adcf2011-04-14 09:12:40 +0100505
506static void
Zack Rusinc5929572011-09-19 03:04:40 -0400507variantMapToItems(const QVariantMap &map, const QVariantMap &defaultMap,
508 QList<QTreeWidgetItem *> &items)
Zack Rusin11f7e632011-03-30 22:47:51 -0400509{
510 QVariantMap::const_iterator itr;
José Fonseca333adcf2011-04-14 09:12:40 +0100511 for (itr = map.constBegin(); itr != map.constEnd(); ++itr) {
512 QString key = itr.key();
513 QVariant var = itr.value();
514 QVariant defaultVar = defaultMap[key];
515
516 QTreeWidgetItem *item = variantToItem(key, var, defaultVar);
517 if (item) {
518 items.append(item);
519 }
520 }
521}
522
523static void
Zack Rusinc5929572011-09-19 03:04:40 -0400524variantListToItems(const QVector<QVariant> &lst,
525 const QVector<QVariant> &defaultLst,
Zack Rusinf736a622011-08-28 22:19:46 -0400526 QList<QTreeWidgetItem *> &items)
José Fonseca333adcf2011-04-14 09:12:40 +0100527{
José Fonsecaba1b4782014-10-22 23:33:07 +0100528 int width = QString::number(lst.count()).length();
José Fonseca333adcf2011-04-14 09:12:40 +0100529 for (int i = 0; i < lst.count(); ++i) {
José Fonsecaba1b4782014-10-22 23:33:07 +0100530 QString key = QString::number(i).rightJustified(width, ' ');
José Fonseca333adcf2011-04-14 09:12:40 +0100531 QVariant var = lst[i];
532 QVariant defaultVar;
Corey Richardsonf3006462014-01-26 17:15:42 -0500533
José Fonseca333adcf2011-04-14 09:12:40 +0100534 if (i < defaultLst.count()) {
535 defaultVar = defaultLst[i];
536 }
537
538 QTreeWidgetItem *item = variantToItem(key, var, defaultVar);
539 if (item) {
540 items.append(item);
541 }
542 }
543}
544
José Fonseca17999c92014-10-23 13:49:35 +0100545// Get the depth (dimensionality) of the variant:
546//
547// It will return:
548// 0: scalar
549// 1: vector (up to 4 elems)
550// 2: matrix (up to 4x4 elements)
551// 3: array
552// 4: map, etc.
553static unsigned
554getVariantDepth(const QVariant &var)
José Fonseca333adcf2011-04-14 09:12:40 +0100555{
556 if (var.type() == QVariant::List) {
Zack Rusinf736a622011-08-28 22:19:46 -0400557 QVector<QVariant> lst = var.toList().toVector();
José Fonseca17999c92014-10-23 13:49:35 +0100558 unsigned maxDepth = 0;
José Fonseca333adcf2011-04-14 09:12:40 +0100559 for (int i = 0; i < lst.count(); ++i) {
José Fonseca17999c92014-10-23 13:49:35 +0100560 unsigned elemDepth = getVariantDepth(lst[i]);
561 if (elemDepth > maxDepth) {
562 if (elemDepth >= 4) {
563 return elemDepth;
564 }
565 maxDepth = elemDepth;
José Fonseca333adcf2011-04-14 09:12:40 +0100566 }
567 }
José Fonseca17999c92014-10-23 13:49:35 +0100568 if (lst.count() > 1) {
569 if (lst.count() > 4) {
570 return 3;
571 }
572 maxDepth += 1;
573 }
574 return maxDepth;
José Fonseca333adcf2011-04-14 09:12:40 +0100575 } else if (var.type() == QVariant::Map) {
José Fonseca17999c92014-10-23 13:49:35 +0100576 return 4;
José Fonseca333adcf2011-04-14 09:12:40 +0100577 } else if (var.type() == QVariant::Hash) {
José Fonseca17999c92014-10-23 13:49:35 +0100578 return 4;
José Fonseca333adcf2011-04-14 09:12:40 +0100579 } else {
José Fonseca17999c92014-10-23 13:49:35 +0100580 return 0;
José Fonseca333adcf2011-04-14 09:12:40 +0100581 }
582}
583
584static QTreeWidgetItem *
Zack Rusinc5929572011-09-19 03:04:40 -0400585variantToItem(const QString &key, const QVariant &var,
586 const QVariant &defaultVar)
José Fonseca333adcf2011-04-14 09:12:40 +0100587{
588 if (var == defaultVar) {
589 return NULL;
590 }
591
592 QString val;
593
José Fonseca17999c92014-10-23 13:49:35 +0100594 bool deep = getVariantDepth(var) >= 3;
José Fonseca333adcf2011-04-14 09:12:40 +0100595 if (!deep) {
596 variantToString(var, val);
597 }
598
599 //qDebug()<<"key = "<<key;
600 //qDebug()<<"val = "<<val;
601 QStringList lst;
602 lst += key;
603 lst += val;
604
605 QTreeWidgetItem *item = new QTreeWidgetItem((QTreeWidgetItem *)0, lst);
606
607 if (deep) {
608 QList<QTreeWidgetItem *> children;
609 if (var.type() == QVariant::Map) {
610 QVariantMap map = var.toMap();
611 QVariantMap defaultMap = defaultVar.toMap();
612 variantMapToItems(map, defaultMap, children);
613 }
614 if (var.type() == QVariant::List) {
Zack Rusinf736a622011-08-28 22:19:46 -0400615 QVector<QVariant> lst = var.toList().toVector();
616 QVector<QVariant> defaultLst = defaultVar.toList().toVector();
José Fonseca333adcf2011-04-14 09:12:40 +0100617 variantListToItems(lst, defaultLst, children);
618 }
619 item->addChildren(children);
620 }
621
622 return item;
623}
624
Zack Rusin9977b372011-05-06 20:26:54 -0400625static void addSurfaceItem(const ApiSurface &surface,
626 const QString &label,
627 QTreeWidgetItem *parent,
Martin Schulzeb44232b2016-04-16 19:06:16 +0200628 QTreeWidget *tree,
629 bool opaque, bool alpha)
Zack Rusin9977b372011-05-06 20:26:54 -0400630{
Martin Schulzeb44232b2016-04-16 19:06:16 +0200631 QIcon icon(QPixmap::fromImage(surface.calculateThumbnail(opaque, alpha)));
Zack Rusin9977b372011-05-06 20:26:54 -0400632 QTreeWidgetItem *item = new QTreeWidgetItem(parent);
Zack Rusin9977b372011-05-06 20:26:54 -0400633 item->setIcon(0, icon);
634
Zack Rusinc5929572011-09-19 03:04:40 -0400635 int width = surface.size().width();
636 int height = surface.size().height();
Zack Rusin9977b372011-05-06 20:26:54 -0400637 QString descr =
Zack Rusine181b992011-11-17 16:00:41 -0500638 QString::fromLatin1("%1, %2, %3 x %4")
Zack Rusin9977b372011-05-06 20:26:54 -0400639 .arg(label)
Zack Rusine181b992011-11-17 16:00:41 -0500640 .arg(surface.formatName())
Zack Rusin9977b372011-05-06 20:26:54 -0400641 .arg(width)
642 .arg(height);
643
Jose Fonseca6203b5a2015-02-06 15:39:54 +0000644 QString toolTip;
645 toolTip += QString::fromLatin1("label = %1\n").arg(label);
646 toolTip += QString::fromLatin1("format = %1\n").arg(surface.formatName());
647 toolTip += QString::fromLatin1("width = %1\n").arg(width);
648 toolTip += QString::fromLatin1("height = %1\n").arg(height);
649 item->setToolTip(0, toolTip);
650 item->setToolTip(1, toolTip);
651
Zack Rusin9977b372011-05-06 20:26:54 -0400652 //item->setText(1, descr);
653 QLabel *l = new QLabel(descr, tree);
654 l->setWordWrap(true);
655 tree->setItemWidget(item, 1, l);
656
Jose Fonseca93a7c0c2015-05-27 20:52:51 +0100657 item->setData(0, Qt::UserRole, surface.data());
Zack Rusin9977b372011-05-06 20:26:54 -0400658}
659
Martin Schulze638ec442015-10-11 12:37:42 +0200660void MainWindow::addSurface(const ApiTexture &image, QTreeWidgetItem *parent) {
Martin Schulzeb44232b2016-04-16 19:06:16 +0200661 addSurface(image, image.label(), parent);
Martin Schulze638ec442015-10-11 12:37:42 +0200662}
663
664void MainWindow::addSurface(const ApiFramebuffer &fbo, QTreeWidgetItem *parent) {
Martin Schulzeb44232b2016-04-16 19:06:16 +0200665 addSurface(fbo, fbo.type(), parent);
666}
667
668void MainWindow::addSurface(const ApiSurface &surface, const QString &label,
669 QTreeWidgetItem *parent)
670{
671 addSurfaceItem(surface, label, parent,
672 m_ui.surfacesTreeWidget, m_ui.surfacesOpaqueCB->isChecked(),
673 m_ui.surfacesAlphaCB->isChecked());
Martin Schulze638ec442015-10-11 12:37:42 +0200674}
675
676template <typename Surface>
677void MainWindow::addSurfaces(const QList<Surface> &surfaces, const char *label) {
678 if (!surfaces.isEmpty()) {
679 QTreeWidgetItem *imageItem = new QTreeWidgetItem(m_ui.surfacesTreeWidget);
680 imageItem->setText(0, tr(label));
681 if (surfaces.count() <= 6) {
682 imageItem->setExpanded(true);
683 }
684 for (int i = 0; i < surfaces.count(); ++i) {
685 addSurface(surfaces[i], imageItem);
686 }
687 }
688}
689
Martin Schulzefbfe7a62016-05-01 08:02:20 +0100690QStringList shortenReferencingShaderNames(QStringList referencingShaders)
691{
692 static QMap<QString, QString> map = {
693 {"GL_REFERENCED_BY_VERTEX_SHADER", "VS"},
694 {"GL_REFERENCED_BY_TESS_CONTROL_SHADER", "TCS"},
695 {"GL_REFERENCED_BY_TESS_EVALUATION_SHADER", "TES"},
696 {"GL_REFERENCED_BY_GEOMETRY_SHADER", "GS"},
697 {"GL_REFERENCED_BY_FRAGMENT_SHADER", "FS"},
698 {"GL_REFERENCED_BY_COMPUTE_SHADER", "CS"}};
699 for (auto &referencingShader : referencingShaders) {
700 assert(map.count(referencingShader));
701 referencingShader = map[referencingShader];
702 }
703 return referencingShaders;
704}
705
706QStringList getReferencingShaders(QTreeWidgetItem *bufferItem)
707{
708 QStringList referencingShaders;
709 for (int i = 0; i < bufferItem->childCount(); ++i) {
710 const auto &text = bufferItem->child(i)->text(0);
711 if (text.startsWith("GL_REFERENCED_BY_") && text.endsWith("_SHADER")) {
712 referencingShaders.append(text);
713 }
714 }
715 return referencingShaders;
716}
717
718void setValueOfSSBBItem(const ApiTraceState &state, QTreeWidgetItem *bufferItem)
Martin Schulzee9e85782016-03-23 17:03:16 +0100719{
720 assert(bufferItem);
721 const auto &bufferBindingItem = bufferItem->child(0);
722 assert(bufferBindingItem->text(0) == "GL_BUFFER_BINDING");
723 const int bufferBindingIndex = bufferBindingItem->text(1).toInt();
724 qDebug() << bufferBindingIndex;
725 assert(state.parameters().count("GL_SHADER_STORAGE_BUFFER"));
726 assert(state.parameters()["GL_SHADER_STORAGE_BUFFER"].toMap().count("i"));
727 assert(bufferBindingIndex < state.parameters()["GL_SHADER_STORAGE_BUFFER"]
728 .toMap()["i"]
729 .toList()
730 .size());
731 const auto &SSB = state.parameters()["GL_SHADER_STORAGE_BUFFER"]
732 .toMap()["i"]
733 .toList()[bufferBindingIndex]
734 .toMap();
735
736 assert(SSB.count("GL_SHADER_STORAGE_BUFFER_START"));
737 auto start = SSB["GL_SHADER_STORAGE_BUFFER_START"].toInt();
738
739 assert(SSB.count("GL_SHADER_STORAGE_BUFFER_SIZE"));
740 auto size = SSB["GL_SHADER_STORAGE_BUFFER_SIZE"].toInt();
741
742 assert(SSB.count("GL_SHADER_STORAGE_BUFFER_BINDING"));
743 auto bufferName = SSB["GL_SHADER_STORAGE_BUFFER_BINDING"].toInt();
744
Martin Schulzefbfe7a62016-05-01 08:02:20 +0100745 // Build overview text like:
746 // "Binding 1 in VS, FS; Buffer 16 (6 Bytes starting at 2)"
Martin Schulzee9e85782016-03-23 17:03:16 +0100747 QString bindingText = QString("Binding %0").arg(bufferBindingIndex);
Martin Schulzee9e85782016-03-23 17:03:16 +0100748
Martin Schulzefbfe7a62016-05-01 08:02:20 +0100749 QStringList referencingShaders =
750 shortenReferencingShaderNames(getReferencingShaders(bufferItem));
Martin Schulzee9e85782016-03-23 17:03:16 +0100751 if (!referencingShaders.empty()) {
752 bindingText += " in ";
753 bindingText += referencingShaders.join(", ");
754 }
755
756 QString bufferText;
757 if (bufferName != 0) {
758 bufferText = QString("Buffer %0").arg(bufferName);
759 if (size != 0) {
760 if (start != 0) {
761 bufferText +=
762 QString(" (%0 Bytes starting at %1)").arg(size).arg(start);
763 } else {
764 bufferText += QString(" (first %0 Bytes)").arg(size);
765 }
766 } else {
767 if (start != 0) {
768 bufferText += QString(" (starting at offset %0)").arg(start);
769 }
770 }
771 }
772 if (bufferText.isEmpty()) {
773 bufferItem->setText(1, bindingText);
774 } else {
775 bufferItem->setText(1, bindingText + "; " + bufferText);
776 }
777}
778
Martin Schulzeb44232b2016-04-16 19:06:16 +0200779void MainWindow::updateSurfacesView()
780{
781 updateSurfacesView(*m_selectedEvent->state());
782}
783
784void MainWindow::updateSurfacesView(const ApiTraceState &state)
785{
786 const QList<ApiTexture> &textures =
787 state.textures();
788 const QList<ApiFramebuffer> &fbos =
789 state.framebuffers();
790
791 m_ui.surfacesTreeWidget->clear();
792 if (textures.isEmpty() && fbos.isEmpty()) {
793 m_ui.surfacesTab->setDisabled(false);
794 } else {
795 m_ui.surfacesTreeWidget->setIconSize(QSize(THUMBNAIL_SIZE, THUMBNAIL_SIZE));
796 addSurfaces(textures, "Textures");
797 addSurfaces(fbos, "Framebuffers");
798 m_ui.surfacesTab->setEnabled(true);
799 }
800}
801
José Fonseca333adcf2011-04-14 09:12:40 +0100802void MainWindow::fillStateForFrame()
803{
Zack Rusinc5929572011-09-19 03:04:40 -0400804 if (!m_selectedEvent || !m_selectedEvent->hasState()) {
Zack Rusin11f7e632011-03-30 22:47:51 -0400805 return;
Zack Rusinc5929572011-09-19 03:04:40 -0400806 }
Zack Rusin11f7e632011-03-30 22:47:51 -0400807
Zack Rusin3b7fbd72011-04-27 23:48:16 -0400808 if (m_nonDefaultsLookupEvent) {
809 m_ui.nonDefaultsCB->blockSignals(true);
810 m_ui.nonDefaultsCB->setChecked(true);
811 m_ui.nonDefaultsCB->blockSignals(false);
812 }
813
Zack Rusine2dfa2e2011-04-13 01:35:03 -0400814 bool nonDefaults = m_ui.nonDefaultsCB->isChecked();
José Fonseca333adcf2011-04-14 09:12:40 +0100815 QVariantMap defaultParams;
816 if (nonDefaults) {
817 ApiTraceState defaultState = m_trace->defaultState();
818 defaultParams = defaultState.parameters();
819 }
Zack Rusine2dfa2e2011-04-13 01:35:03 -0400820
Zack Rusined40bc62011-08-28 17:11:02 -0400821 const ApiTraceState &state = *m_selectedEvent->state();
Zack Rusin11f7e632011-03-30 22:47:51 -0400822 m_ui.stateTreeWidget->clear();
Zack Rusin11f7e632011-03-30 22:47:51 -0400823 QList<QTreeWidgetItem *> items;
José Fonseca6b9d1332011-08-01 00:08:40 +0100824 variantMapToItems(state.parameters(), defaultParams, items);
Zack Rusin11f7e632011-03-30 22:47:51 -0400825 m_ui.stateTreeWidget->insertTopLevelItems(0, items);
Zack Rusin7c814f12011-04-09 19:20:58 -0400826
José Fonsecaf7a6b622011-04-13 10:37:13 +0100827 QMap<QString, QString> shaderSources = state.shaderSources();
Zack Rusin7c814f12011-04-09 19:20:58 -0400828 if (shaderSources.isEmpty()) {
829 m_sourcesWidget->setShaders(shaderSources);
830 } else {
831 m_sourcesWidget->setShaders(shaderSources);
832 }
833
José Fonseca6b9d1332011-08-01 00:08:40 +0100834 m_ui.uniformsTreeWidget->clear();
835 QList<QTreeWidgetItem *> uniformsItems;
José Fonseca26b34172011-08-01 00:16:35 +0100836 variantMapToItems(state.uniforms(), QVariantMap(), uniformsItems);
José Fonseca6b9d1332011-08-01 00:08:40 +0100837 m_ui.uniformsTreeWidget->insertTopLevelItems(0, uniformsItems);
838
José Fonsecad1d1ecf2014-10-22 23:55:16 +0100839 m_ui.buffersTreeWidget->clear();
840 QList<QTreeWidgetItem *> buffersItems;
841 variantMapToItems(state.buffers(), QVariantMap(), buffersItems);
842 m_ui.buffersTreeWidget->insertTopLevelItems(0, buffersItems);
843
Martin Schulzeb44232b2016-04-16 19:06:16 +0200844 updateSurfacesView(state);
Zack Rusin11f7e632011-03-30 22:47:51 -0400845 m_ui.stateDock->show();
Martin Schulzee9e85782016-03-23 17:03:16 +0100846
847 {
848 m_ui.ssbsTreeWidget->clear();
849 QList<QTreeWidgetItem *> buffersItems;
850 variantMapToItems(state.shaderStorageBufferBlocks(), QVariantMap(),
851 buffersItems);
852 const bool hasSSBs = buffersItems.size() > 0;
853 for (auto const &bufferItem : buffersItems) {
854 setValueOfSSBBItem(state, bufferItem);
855 }
856 m_ui.ssbsTreeWidget->insertTopLevelItems(0, buffersItems);
857 m_ui.ssbTab->setEnabled(hasSSBs);
858 }
Zack Rusin11f7e632011-03-30 22:47:51 -0400859}
860
Zack Rusine1745572011-04-03 14:30:19 -0400861void MainWindow::showSettings()
862{
863 SettingsDialog dialog;
Zack Rusin20e6a8c2011-04-13 00:41:32 -0400864 dialog.setFilterModel(m_proxyModel);
Zack Rusine1745572011-04-03 14:30:19 -0400865
Zack Rusin20e6a8c2011-04-13 00:41:32 -0400866 dialog.exec();
Zack Rusine1745572011-04-03 14:30:19 -0400867}
868
Jose Fonsecaa20a7952016-01-19 14:16:24 +0000869void MainWindow::leakTrace()
870{
871 LeakTraceThread *t=new LeakTraceThread(m_trace->fileName());
872
873 connect (t,SIGNAL(finished()),this,SLOT(leakTraceFinished()));
874
875 connect (t,SIGNAL(leakTraceErrors(const QList<ApiTraceError> &)),
876 this,SLOT(slotRetraceErrors(const QList<ApiTraceError>&)));
877
878 t->start();
879}
880
881void MainWindow::leakTraceFinished(){
882
883 LeakTraceThread *t = qobject_cast<LeakTraceThread*>(sender());
884
885 m_ui.errorsDock->setVisible(t->hasError());
886
887 delete t;
888}
889
Zack Rusin09ec4842011-04-10 01:57:17 -0400890void MainWindow::showSurfacesMenu(const QPoint &pos)
891{
892 QTreeWidget *tree = m_ui.surfacesTreeWidget;
893 QTreeWidgetItem *item = tree->itemAt(pos);
Zack Rusinc5929572011-09-19 03:04:40 -0400894 if (!item) {
Zack Rusin09ec4842011-04-10 01:57:17 -0400895 return;
Zack Rusinc5929572011-09-19 03:04:40 -0400896 }
Zack Rusin09ec4842011-04-10 01:57:17 -0400897
898 QMenu menu(tr("Surfaces"), this);
Zack Rusinfd638e52011-06-20 19:46:17 -0400899
Zack Rusin09ec4842011-04-10 01:57:17 -0400900 QAction *act = menu.addAction(tr("View Image"));
901 act->setStatusTip(tr("View the currently selected surface"));
902 connect(act, SIGNAL(triggered()),
903 SLOT(showSelectedSurface()));
904
Zack Rusinfd638e52011-06-20 19:46:17 -0400905 act = menu.addAction(tr("Save Image"));
906 act->setStatusTip(tr("Save the currently selected surface"));
907 connect(act, SIGNAL(triggered()),
908 SLOT(saveSelectedSurface()));
909
Zack Rusin09ec4842011-04-10 01:57:17 -0400910 menu.exec(tree->viewport()->mapToGlobal(pos));
911}
912
913void MainWindow::showSelectedSurface()
914{
915 QTreeWidgetItem *item =
916 m_ui.surfacesTreeWidget->currentItem();
Zack Rusinc5929572011-09-19 03:04:40 -0400917 if (!item) {
Zack Rusin09ec4842011-04-10 01:57:17 -0400918 return;
Zack Rusinc5929572011-09-19 03:04:40 -0400919 }
Zack Rusin09ec4842011-04-10 01:57:17 -0400920
José Fonseca41e7db92014-05-30 14:09:35 +0100921 QVariant var = item->data(0, Qt::UserRole);
922 if (!var.isValid()) {
923 return;
924 }
925
Martin Schulzeb44232b2016-04-16 19:06:16 +0200926 ImageViewer *viewer =
927 new ImageViewer(this, m_ui.surfacesOpaqueCB->isChecked(),
Gabe Dagani9ff44052017-11-28 09:30:15 -0600928 m_ui.surfacesAlphaCB->isChecked());
Zack Rusinbe547732011-04-23 17:16:34 -0400929
930 QString title;
Zack Rusin8f98c3a2011-09-11 18:21:29 -0400931 if (selectedCall()) {
Zack Rusinbe547732011-04-23 17:16:34 -0400932 title = tr("QApiTrace - Surface at %1 (%2)")
Zack Rusin8f98c3a2011-09-11 18:21:29 -0400933 .arg(selectedCall()->name())
934 .arg(selectedCall()->index());
Zack Rusinbe547732011-04-23 17:16:34 -0400935 } else {
936 title = tr("QApiTrace - Surface Viewer");
937 }
938 viewer->setWindowTitle(title);
Zack Rusinc5929572011-09-19 03:04:40 -0400939
Zack Rusin60d2b652011-04-23 01:41:13 -0400940 viewer->setAttribute(Qt::WA_DeleteOnClose, true);
Zack Rusinc5929572011-09-19 03:04:40 -0400941
Jose Fonseca93a7c0c2015-05-27 20:52:51 +0100942 QByteArray data = var.value<QByteArray>();
943 viewer->setData(data);
Zack Rusinc5929572011-09-19 03:04:40 -0400944
Zack Rusin60d2b652011-04-23 01:41:13 -0400945 viewer->show();
946 viewer->raise();
947 viewer->activateWindow();
Zack Rusin09ec4842011-04-10 01:57:17 -0400948}
949
Zack Rusin46678422011-04-10 12:15:46 -0400950void MainWindow::initObjects()
951{
952 m_ui.stateTreeWidget->sortByColumn(0, Qt::AscendingOrder);
José Fonseca426347a2011-08-01 00:33:14 +0100953 m_ui.uniformsTreeWidget->sortByColumn(0, Qt::AscendingOrder);
Zack Rusin46678422011-04-10 12:15:46 -0400954
955 m_sourcesWidget = new ShadersSourceWidget(m_ui.shadersTab);
956 QVBoxLayout *layout = new QVBoxLayout;
957 layout->addWidget(m_sourcesWidget);
958 m_ui.shadersTab->setLayout(layout);
959
960 m_trace = new ApiTrace();
961 m_retracer = new Retracer(this);
962
963 m_vdataInterpreter = new VertexDataInterpreter(this);
964 m_vdataInterpreter->setListWidget(m_ui.vertexDataListWidget);
965 m_vdataInterpreter->setStride(
966 m_ui.vertexStrideSB->value());
967 m_vdataInterpreter->setComponents(
968 m_ui.vertexComponentsSB->value());
969 m_vdataInterpreter->setStartingOffset(
970 m_ui.startingOffsetSB->value());
971 m_vdataInterpreter->setTypeFromString(
972 m_ui.vertexTypeCB->currentText());
973
Zack Rusin46678422011-04-10 12:15:46 -0400974 m_model = new ApiTraceModel();
975 m_model->setApiTrace(m_trace);
976 m_proxyModel = new ApiTraceFilter();
977 m_proxyModel->setSourceModel(m_model);
978 m_ui.callView->setModel(m_proxyModel);
Zack Rusin5492af52011-04-24 18:05:27 -0400979 m_ui.callView->setItemDelegate(
980 new ApiCallDelegate(m_ui.callView));
Zack Rusin46678422011-04-10 12:15:46 -0400981 m_ui.callView->resizeColumnToContents(0);
982 m_ui.callView->header()->swapSections(0, 1);
983 m_ui.callView->setColumnWidth(1, 42);
Zack Rusinfb23ba12011-04-15 19:29:45 -0400984 m_ui.callView->setContextMenuPolicy(Qt::CustomContextMenu);
Zack Rusin46678422011-04-10 12:15:46 -0400985
Zack Rusin46678422011-04-10 12:15:46 -0400986 m_progressBar = new QProgressBar();
Zack Rusinebf971e2011-09-06 17:44:43 -0400987 m_progressBar->setRange(0, 100);
Zack Rusin46678422011-04-10 12:15:46 -0400988 statusBar()->addPermanentWidget(m_progressBar);
989 m_progressBar->hide();
990
Zack Rusin963102f2011-04-15 01:45:05 -0400991 m_argsEditor = new ArgumentsEditor(this);
Zack Rusin963102f2011-04-15 01:45:05 -0400992
Zack Rusin46678422011-04-10 12:15:46 -0400993 m_ui.detailsDock->hide();
Eugene Velesevichaa1b2132013-04-23 17:56:14 +0400994 m_ui.backtraceDock->hide();
Zack Rusinb53b1612011-04-19 01:33:58 -0400995 m_ui.errorsDock->hide();
Zack Rusin46678422011-04-10 12:15:46 -0400996 m_ui.vertexDataDock->hide();
997 m_ui.stateDock->hide();
998 setDockOptions(dockOptions() | QMainWindow::ForceTabbedDocks);
999
1000 tabifyDockWidget(m_ui.stateDock, m_ui.vertexDataDock);
Zack Rusinb53b1612011-04-19 01:33:58 -04001001 tabifyDockWidget(m_ui.detailsDock, m_ui.errorsDock);
Eugene Velesevichaa1b2132013-04-23 17:56:14 +04001002 tabifyDockWidget(m_ui.detailsDock, m_ui.backtraceDock);
Zack Rusin46678422011-04-10 12:15:46 -04001003
1004 m_ui.surfacesTreeWidget->setContextMenuPolicy(Qt::CustomContextMenu);
1005
Zack Rusinc52d18a2011-04-11 00:15:07 -04001006 m_jumpWidget = new JumpWidget(this);
1007 m_ui.centralLayout->addWidget(m_jumpWidget);
1008 m_jumpWidget->hide();
1009
Zack Rusinf04cf8a2011-04-12 23:21:52 -04001010 m_searchWidget = new SearchWidget(this);
1011 m_ui.centralLayout->addWidget(m_searchWidget);
1012 m_searchWidget->hide();
1013
Zack Rusinca164112011-04-11 02:23:09 -04001014 m_traceProcess = new TraceProcess(this);
Dan McCabe1c3ddde2012-03-21 09:53:45 -07001015 m_trimProcess = new TrimProcess(this);
James Bentonfc4f55a2012-08-08 17:09:07 +01001016
1017 m_profileDialog = new ProfileDialog();
Zack Rusin46678422011-04-10 12:15:46 -04001018}
1019
1020void MainWindow::initConnections()
1021{
Jose Fonseca8f0846c2015-11-10 19:53:55 +00001022 connect(m_trace, SIGNAL(problemLoadingTrace(const QString&)),
1023 this, SLOT(loadError(const QString&)));
Zack Rusin46678422011-04-10 12:15:46 -04001024 connect(m_trace, SIGNAL(startedLoadingTrace()),
1025 this, SLOT(startedLoadingTrace()));
Zack Rusinebf971e2011-09-06 17:44:43 -04001026 connect(m_trace, SIGNAL(loaded(int)),
1027 this, SLOT(loadProgess(int)));
Zack Rusin46678422011-04-10 12:15:46 -04001028 connect(m_trace, SIGNAL(finishedLoadingTrace()),
1029 this, SLOT(finishedLoadingTrace()));
Zack Rusin9af5bff2011-04-18 01:05:50 -04001030 connect(m_trace, SIGNAL(startedSaving()),
1031 this, SLOT(slotStartedSaving()));
1032 connect(m_trace, SIGNAL(saved()),
1033 this, SLOT(slotSaved()));
Dan McCabe10bd4242012-03-05 17:20:40 -08001034 connect(m_trace, SIGNAL(changed(ApiTraceEvent*)),
1035 this, SLOT(slotTraceChanged(ApiTraceEvent*)));
Zack Rusinad513b32011-09-25 14:33:41 -04001036 connect(m_trace, SIGNAL(findResult(ApiTrace::SearchRequest,ApiTrace::SearchResult,ApiTraceCall*)),
1037 this, SLOT(slotSearchResult(ApiTrace::SearchRequest,ApiTrace::SearchResult,ApiTraceCall*)));
Zack Rusin93e4d152011-09-13 02:23:39 -04001038 connect(m_trace, SIGNAL(foundFrameStart(ApiTraceFrame*)),
1039 this, SLOT(slotFoundFrameStart(ApiTraceFrame*)));
1040 connect(m_trace, SIGNAL(foundFrameEnd(ApiTraceFrame*)),
1041 this, SLOT(slotFoundFrameEnd(ApiTraceFrame*)));
Zack Rusinda7579b2011-09-13 17:33:05 -04001042 connect(m_trace, SIGNAL(foundCallIndex(ApiTraceCall*)),
1043 this, SLOT(slotJumpToResult(ApiTraceCall*)));
Zack Rusin46678422011-04-10 12:15:46 -04001044
Jose Fonseca65d26052017-07-30 13:48:40 +01001045 connect(m_retracer, SIGNAL(finished(const QString&)),
1046 this, SLOT(replayFinished(const QString&)));
1047 connect(m_retracer, SIGNAL(error(const QString&)),
1048 this, SLOT(replayError(const QString&)));
1049 connect(m_retracer, SIGNAL(foundState(ApiTraceState*)),
1050 this, SLOT(replayStateFound(ApiTraceState*)));
1051 connect(m_retracer, SIGNAL(foundProfile(trace::Profile*)),
1052 this, SLOT(replayProfileFound(trace::Profile*)));
1053 connect(m_retracer, SIGNAL(foundThumbnails(const ImageHash&)),
1054 this, SLOT(replayThumbnailsFound(const ImageHash&)));
1055 connect(m_retracer, SIGNAL(retraceErrors(const QList<ApiTraceError>&)),
1056 this, SLOT(slotRetraceErrors(const QList<ApiTraceError>&)));
Zack Rusin46678422011-04-10 12:15:46 -04001057
1058 connect(m_ui.vertexInterpretButton, SIGNAL(clicked()),
1059 m_vdataInterpreter, SLOT(interpretData()));
Edward Rudd14158b92014-07-07 17:46:05 -04001060 connect(m_ui.bufferExportButton, SIGNAL(clicked()),
1061 this, SLOT(exportBufferData()));
Zack Rusin46678422011-04-10 12:15:46 -04001062 connect(m_ui.vertexTypeCB, SIGNAL(currentIndexChanged(const QString&)),
1063 m_vdataInterpreter, SLOT(setTypeFromString(const QString&)));
1064 connect(m_ui.vertexStrideSB, SIGNAL(valueChanged(int)),
1065 m_vdataInterpreter, SLOT(setStride(int)));
1066 connect(m_ui.vertexComponentsSB, SIGNAL(valueChanged(int)),
1067 m_vdataInterpreter, SLOT(setComponents(int)));
1068 connect(m_ui.startingOffsetSB, SIGNAL(valueChanged(int)),
1069 m_vdataInterpreter, SLOT(setStartingOffset(int)));
1070
1071
Zack Rusin3438a522011-04-10 22:56:31 -04001072 connect(m_ui.actionNew, SIGNAL(triggered()),
1073 this, SLOT(createTrace()));
Zack Rusin46678422011-04-10 12:15:46 -04001074 connect(m_ui.actionOpen, SIGNAL(triggered()),
1075 this, SLOT(openTrace()));
Alexander Trukhind99ab922015-03-27 23:38:01 +03001076 connect(m_ui.actionSave, SIGNAL(triggered()),
1077 this, SLOT(saveTrace()));
Zack Rusin46678422011-04-10 12:15:46 -04001078 connect(m_ui.actionQuit, SIGNAL(triggered()),
1079 this, SLOT(close()));
1080
Zack Rusin9623daf2011-04-18 18:03:34 -04001081 connect(m_ui.actionFind, SIGNAL(triggered()),
1082 this, SLOT(slotSearch()));
1083 connect(m_ui.actionGo, SIGNAL(triggered()),
1084 this, SLOT(slotGoTo()));
1085 connect(m_ui.actionGoFrameStart, SIGNAL(triggered()),
1086 this, SLOT(slotGoFrameStart()));
1087 connect(m_ui.actionGoFrameEnd, SIGNAL(triggered()),
1088 this, SLOT(slotGoFrameEnd()));
1089
Zack Rusin46678422011-04-10 12:15:46 -04001090 connect(m_ui.actionReplay, SIGNAL(triggered()),
1091 this, SLOT(replayStart()));
James Bentonfc4f55a2012-08-08 17:09:07 +01001092 connect(m_ui.actionProfile, SIGNAL(triggered()),
1093 this, SLOT(replayProfile()));
Zack Rusin46678422011-04-10 12:15:46 -04001094 connect(m_ui.actionStop, SIGNAL(triggered()),
1095 this, SLOT(replayStop()));
1096 connect(m_ui.actionLookupState, SIGNAL(triggered()),
1097 this, SLOT(lookupState()));
Dan McCabe1c3ddde2012-03-21 09:53:45 -07001098 connect(m_ui.actionTrim, SIGNAL(triggered()),
1099 this, SLOT(trim()));
José Fonsecae5fa5412012-03-24 09:27:27 +00001100 connect(m_ui.actionShowThumbnails, SIGNAL(triggered()),
1101 this, SLOT(showThumbnails()));
Zack Rusin46678422011-04-10 12:15:46 -04001102 connect(m_ui.actionOptions, SIGNAL(triggered()),
1103 this, SLOT(showSettings()));
Jose Fonsecaa20a7952016-01-19 14:16:24 +00001104 connect(m_ui.actionLeakTrace,SIGNAL(triggered()),
1105 this, SLOT(leakTrace()));
Zack Rusin46678422011-04-10 12:15:46 -04001106
José Fonseca6068f672011-10-30 10:51:53 +00001107 connect(m_ui.callView->selectionModel(), SIGNAL(currentChanged(const QModelIndex &, const QModelIndex &)),
Zack Rusin46678422011-04-10 12:15:46 -04001108 this, SLOT(callItemSelected(const QModelIndex &)));
José Fonseca63d59402011-10-30 10:56:04 +00001109 connect(m_ui.callView, SIGNAL(doubleClicked(const QModelIndex &)),
1110 this, SLOT(callItemActivated(const QModelIndex &)));
Zack Rusinfb23ba12011-04-15 19:29:45 -04001111 connect(m_ui.callView, SIGNAL(customContextMenuRequested(QPoint)),
1112 this, SLOT(customContextMenuRequested(QPoint)));
Zack Rusin46678422011-04-10 12:15:46 -04001113
1114 connect(m_ui.surfacesTreeWidget,
1115 SIGNAL(customContextMenuRequested(const QPoint &)),
1116 SLOT(showSurfacesMenu(const QPoint &)));
1117 connect(m_ui.surfacesTreeWidget,
1118 SIGNAL(itemDoubleClicked(QTreeWidgetItem *, int)),
1119 SLOT(showSelectedSurface()));
1120
Zack Rusine2dfa2e2011-04-13 01:35:03 -04001121 connect(m_ui.nonDefaultsCB, SIGNAL(toggled(bool)),
1122 this, SLOT(fillState(bool)));
1123
Zack Rusinc52d18a2011-04-11 00:15:07 -04001124 connect(m_jumpWidget, SIGNAL(jumpTo(int)),
1125 SLOT(slotJumpTo(int)));
Zack Rusinca164112011-04-11 02:23:09 -04001126
Zack Rusine2dfa2e2011-04-13 01:35:03 -04001127 connect(m_searchWidget,
1128 SIGNAL(searchNext(const QString&, Qt::CaseSensitivity)),
Zack Rusinf04cf8a2011-04-12 23:21:52 -04001129 SLOT(slotSearchNext(const QString&, Qt::CaseSensitivity)));
Zack Rusine2dfa2e2011-04-13 01:35:03 -04001130 connect(m_searchWidget,
1131 SIGNAL(searchPrev(const QString&, Qt::CaseSensitivity)),
Zack Rusinf04cf8a2011-04-12 23:21:52 -04001132 SLOT(slotSearchPrev(const QString&, Qt::CaseSensitivity)));
1133
Zack Rusinca164112011-04-11 02:23:09 -04001134 connect(m_traceProcess, SIGNAL(tracedFile(const QString&)),
1135 SLOT(createdTrace(const QString&)));
1136 connect(m_traceProcess, SIGNAL(error(const QString&)),
1137 SLOT(traceError(const QString&)));
Zack Rusina263fc52011-04-19 23:35:25 -04001138
Dan McCabe1c3ddde2012-03-21 09:53:45 -07001139 connect(m_trimProcess, SIGNAL(trimmedFile(const QString&)),
1140 SLOT(createdTrim(const QString&)));
1141 connect(m_trimProcess, SIGNAL(error(const QString&)),
1142 SLOT(trimError(const QString&)));
1143
Zack Rusina263fc52011-04-19 23:35:25 -04001144 connect(m_ui.errorsDock, SIGNAL(visibilityChanged(bool)),
1145 m_ui.actionShowErrorsDock, SLOT(setChecked(bool)));
1146 connect(m_ui.actionShowErrorsDock, SIGNAL(triggered(bool)),
1147 m_ui.errorsDock, SLOT(setVisible(bool)));
Zack Rusin3b7fbd72011-04-27 23:48:16 -04001148 connect(m_ui.errorsTreeWidget,
José Fonseca18919892011-10-30 10:49:19 +00001149 SIGNAL(itemActivated(QTreeWidgetItem*, int)),
Zack Rusind9239342011-04-19 23:43:06 -04001150 this, SLOT(slotErrorSelected(QTreeWidgetItem*)));
James Bentonfc4f55a2012-08-08 17:09:07 +01001151
1152 connect(m_ui.actionShowProfileDialog, SIGNAL(triggered(bool)),
1153 m_profileDialog, SLOT(show()));
1154 connect(m_profileDialog, SIGNAL(jumpToCall(int)),
1155 this, SLOT(slotJumpTo(int)));
Martin Schulzeb44232b2016-04-16 19:06:16 +02001156
1157 connect(m_ui.surfacesOpaqueCB, SIGNAL(stateChanged(int)), this,
1158 SLOT(updateSurfacesView()));
1159 connect(m_ui.surfacesAlphaCB, SIGNAL(stateChanged(int)), this,
1160 SLOT(updateSurfacesView()));
Gabe Dagani9ff44052017-11-28 09:30:15 -06001161 connect(m_ui.surfacesResolveMSAA, SIGNAL(stateChanged(int)), this,
1162 SLOT(updateSurfacesView()));
James Bentonfc4f55a2012-08-08 17:09:07 +01001163}
1164
Alexandr Akulich1af94092012-12-07 16:59:52 +06001165void MainWindow::updateActionsState(bool traceLoaded, bool stopped)
1166{
1167 if (traceLoaded) {
Alexander Trukhind99ab922015-03-27 23:38:01 +03001168 /* File */
1169 m_ui.actionSave ->setEnabled(true);
1170
Alexandr Akulich1af94092012-12-07 16:59:52 +06001171 /* Edit */
1172 m_ui.actionFind ->setEnabled(true);
1173 m_ui.actionGo ->setEnabled(true);
1174 m_ui.actionGoFrameStart ->setEnabled(true);
1175 m_ui.actionGoFrameEnd ->setEnabled(true);
1176
1177 /* Trace */
1178 if (stopped) {
1179 m_ui.actionStop->setEnabled(false);
1180 m_ui.actionReplay->setEnabled(true);
1181 }
1182 else {
1183 m_ui.actionStop->setEnabled(true);
1184 m_ui.actionReplay->setEnabled(false);
1185 }
1186
1187 m_ui.actionProfile ->setEnabled(true);
1188 m_ui.actionLookupState ->setEnabled(true);
1189 m_ui.actionShowThumbnails->setEnabled(true);
1190 m_ui.actionTrim ->setEnabled(true);
1191 }
1192 else {
Alexander Trukhind99ab922015-03-27 23:38:01 +03001193 /* File */
1194 m_ui.actionSave ->setEnabled(false);
1195
Alexandr Akulich1af94092012-12-07 16:59:52 +06001196 /* Edit */
1197 m_ui.actionFind ->setEnabled(false);
1198 m_ui.actionGo ->setEnabled(false);
1199 m_ui.actionGoFrameStart ->setEnabled(false);
1200 m_ui.actionGoFrameEnd ->setEnabled(false);
1201
1202 /* Trace */
1203 m_ui.actionReplay ->setEnabled(false);
1204 m_ui.actionProfile ->setEnabled(false);
1205 m_ui.actionStop ->setEnabled(false);
1206 m_ui.actionLookupState ->setEnabled(false);
1207 m_ui.actionShowThumbnails->setEnabled(false);
1208 m_ui.actionTrim ->setEnabled(false);
1209 }
1210}
1211
James Bentonfc4f55a2012-08-08 17:09:07 +01001212void MainWindow::closeEvent(QCloseEvent * event)
1213{
1214 m_profileDialog->close();
1215 QMainWindow::closeEvent(event);
1216}
1217
1218void MainWindow::replayProfileFound(trace::Profile *profile)
1219{
1220 m_ui.actionShowProfileDialog->setEnabled(true);
1221 m_profileDialog->setProfile(profile);
1222 m_profileDialog->show();
1223 m_profileDialog->activateWindow();
1224 m_profileDialog->setFocus();
Zack Rusin46678422011-04-10 12:15:46 -04001225}
1226
Zack Rusined40bc62011-08-28 17:11:02 -04001227void MainWindow::replayStateFound(ApiTraceState *state)
Zack Rusinf389ae82011-04-10 19:27:28 -04001228{
1229 m_stateEvent->setState(state);
1230 m_model->stateSetOnEvent(m_stateEvent);
Zack Rusin3b7fbd72011-04-27 23:48:16 -04001231 if (m_selectedEvent == m_stateEvent ||
1232 m_nonDefaultsLookupEvent == m_selectedEvent) {
Zack Rusinf389ae82011-04-10 19:27:28 -04001233 fillStateForFrame();
1234 } else {
1235 m_ui.stateDock->hide();
1236 }
Zack Rusin3b7fbd72011-04-27 23:48:16 -04001237 m_nonDefaultsLookupEvent = 0;
Zack Rusinf389ae82011-04-10 19:27:28 -04001238}
1239
Dan McCabec6f924e2012-06-01 13:40:05 -07001240void MainWindow::replayThumbnailsFound(const ImageHash &thumbnails)
Dan McCabe66dfdda2012-03-05 17:20:39 -08001241{
José Fonseca3f456402012-03-25 20:59:24 +01001242 m_ui.callView->setUniformRowHeights(false);
Dan McCabec6f924e2012-06-01 13:40:05 -07001243 m_trace->bindThumbnails(thumbnails);
Dan McCabe66dfdda2012-03-05 17:20:39 -08001244}
1245
Zack Rusinc52d18a2011-04-11 00:15:07 -04001246void MainWindow::slotGoTo()
1247{
Zack Rusinf04cf8a2011-04-12 23:21:52 -04001248 m_searchWidget->hide();
Zack Rusinc52d18a2011-04-11 00:15:07 -04001249 m_jumpWidget->show();
1250}
1251
1252void MainWindow::slotJumpTo(int callNum)
1253{
Zack Rusinda7579b2011-09-13 17:33:05 -04001254 m_trace->findCallIndex(callNum);
Zack Rusinc52d18a2011-04-11 00:15:07 -04001255}
1256
Zack Rusinca164112011-04-11 02:23:09 -04001257void MainWindow::createdTrace(const QString &path)
1258{
1259 qDebug()<<"Done tracing "<<path;
1260 newTraceFile(path);
1261}
1262
1263void MainWindow::traceError(const QString &msg)
1264{
1265 QMessageBox::warning(
1266 this,
1267 tr("Tracing Error"),
1268 msg);
1269}
1270
Dan McCabe1c3ddde2012-03-21 09:53:45 -07001271void MainWindow::createdTrim(const QString &path)
1272{
1273 qDebug()<<"Done trimming "<<path;
1274
1275 newTraceFile(path);
1276}
1277
1278void MainWindow::trimError(const QString &msg)
1279{
1280 QMessageBox::warning(
1281 this,
1282 tr("Trim Error"),
1283 msg);
1284}
1285
Zack Rusinf04cf8a2011-04-12 23:21:52 -04001286void MainWindow::slotSearch()
1287{
1288 m_jumpWidget->hide();
1289 m_searchWidget->show();
1290}
1291
Zack Rusine37bf9f2011-04-24 15:54:33 -04001292void MainWindow::slotSearchNext(const QString &str,
1293 Qt::CaseSensitivity sensitivity)
Zack Rusinf04cf8a2011-04-12 23:21:52 -04001294{
Zack Rusin8f98c3a2011-09-11 18:21:29 -04001295 ApiTraceCall *call = currentCall();
1296 ApiTraceFrame *frame = currentFrame();
Zack Rusinf54c4fc2011-04-12 23:39:13 -04001297
Zack Rusin8f98c3a2011-09-11 18:21:29 -04001298 if (!frame) {
Tapani Pällia3bcd6d2015-02-12 11:25:53 +02001299 // Trace is still loading.
1300 if (!call) {
1301 return;
1302 }
Zack Rusin8f98c3a2011-09-11 18:21:29 -04001303 frame = call->parentFrame();
Zack Rusinf54c4fc2011-04-12 23:39:13 -04001304 }
Zack Rusin8f98c3a2011-09-11 18:21:29 -04001305 Q_ASSERT(frame);
Zack Rusinf54c4fc2011-04-12 23:39:13 -04001306
Zack Rusin8f98c3a2011-09-11 18:21:29 -04001307 m_trace->findNext(frame, call, str, sensitivity);
Zack Rusinf04cf8a2011-04-12 23:21:52 -04001308}
1309
Zack Rusine37bf9f2011-04-24 15:54:33 -04001310void MainWindow::slotSearchPrev(const QString &str,
1311 Qt::CaseSensitivity sensitivity)
Zack Rusinf04cf8a2011-04-12 23:21:52 -04001312{
Zack Rusin8f98c3a2011-09-11 18:21:29 -04001313 ApiTraceCall *call = currentCall();
1314 ApiTraceFrame *frame = currentFrame();
Zack Rusinf54c4fc2011-04-12 23:39:13 -04001315
Zack Rusin8f98c3a2011-09-11 18:21:29 -04001316 if (!frame) {
Tapani Pällia3bcd6d2015-02-12 11:25:53 +02001317 // Trace is still loading.
1318 if (!call) {
1319 return;
1320 }
Zack Rusin8f98c3a2011-09-11 18:21:29 -04001321 frame = call->parentFrame();
Zack Rusinf54c4fc2011-04-12 23:39:13 -04001322 }
Zack Rusin8f98c3a2011-09-11 18:21:29 -04001323 Q_ASSERT(frame);
Zack Rusinf54c4fc2011-04-12 23:39:13 -04001324
Zack Rusin8f98c3a2011-09-11 18:21:29 -04001325 m_trace->findPrev(frame, call, str, sensitivity);
Zack Rusinf04cf8a2011-04-12 23:21:52 -04001326}
1327
Zack Rusine2dfa2e2011-04-13 01:35:03 -04001328void MainWindow::fillState(bool nonDefaults)
1329{
1330 if (nonDefaults) {
1331 ApiTraceState defaultState = m_trace->defaultState();
1332 if (defaultState.isEmpty()) {
1333 m_ui.nonDefaultsCB->blockSignals(true);
1334 m_ui.nonDefaultsCB->setChecked(false);
1335 m_ui.nonDefaultsCB->blockSignals(false);
Zack Rusine2dfa2e2011-04-13 01:35:03 -04001336 ApiTraceFrame *firstFrame =
1337 m_trace->frameAt(0);
Zack Rusinc5929572011-09-19 03:04:40 -04001338 if (!firstFrame) {
Zack Rusine2dfa2e2011-04-13 01:35:03 -04001339 return;
Zack Rusinc5929572011-09-19 03:04:40 -04001340 }
Zack Rusin1a9f7af2011-09-18 19:40:47 -04001341 if (!firstFrame->isLoaded()) {
Zack Rusin851d0b02011-09-14 22:04:07 -04001342 m_trace->loadFrame(firstFrame);
1343 return;
1344 }
1345 ApiTraceCall *firstCall = firstFrame->calls().first();
1346 ApiTraceEvent *oldSelected = m_selectedEvent;
Zack Rusin3b7fbd72011-04-27 23:48:16 -04001347 m_nonDefaultsLookupEvent = m_selectedEvent;
Zack Rusin851d0b02011-09-14 22:04:07 -04001348 m_selectedEvent = firstCall;
Zack Rusine2dfa2e2011-04-13 01:35:03 -04001349 lookupState();
1350 m_selectedEvent = oldSelected;
1351 }
1352 }
1353 fillStateForFrame();
1354}
1355
Zack Rusinfb23ba12011-04-15 19:29:45 -04001356void MainWindow::customContextMenuRequested(QPoint pos)
1357{
Zack Rusinfb23ba12011-04-15 19:29:45 -04001358 QModelIndex index = m_ui.callView->indexAt(pos);
1359
1360 callItemSelected(index);
Zack Rusinc5929572011-09-19 03:04:40 -04001361 if (!index.isValid()) {
Zack Rusinfb23ba12011-04-15 19:29:45 -04001362 return;
Zack Rusinc5929572011-09-19 03:04:40 -04001363 }
Zack Rusinfb23ba12011-04-15 19:29:45 -04001364
1365 ApiTraceEvent *event =
1366 index.data(ApiTraceModel::EventRole).value<ApiTraceEvent*>();
Zack Rusinc5929572011-09-19 03:04:40 -04001367 if (!event) {
Zack Rusinfb23ba12011-04-15 19:29:45 -04001368 return;
Zack Rusinc5929572011-09-19 03:04:40 -04001369 }
Zack Rusinfb23ba12011-04-15 19:29:45 -04001370
Zack Rusinc5929572011-09-19 03:04:40 -04001371 QMenu menu;
Zack Rusinfb23ba12011-04-15 19:29:45 -04001372 menu.addAction(QIcon(":/resources/media-record.png"),
1373 tr("Lookup state"), this, SLOT(lookupState()));
Zack Rusin218015c2011-05-07 01:41:33 -04001374 if (event->type() == ApiTraceEvent::Call) {
1375 menu.addAction(tr("Edit"), this, SLOT(editCall()));
1376 }
Zack Rusinfb23ba12011-04-15 19:29:45 -04001377
1378 menu.exec(QCursor::pos());
1379}
1380
1381void MainWindow::editCall()
1382{
1383 if (m_selectedEvent && m_selectedEvent->type() == ApiTraceEvent::Call) {
1384 ApiTraceCall *call = static_cast<ApiTraceCall*>(m_selectedEvent);
1385 m_argsEditor->setCall(call);
1386 m_argsEditor->show();
1387 }
1388}
1389
Zack Rusin9af5bff2011-04-18 01:05:50 -04001390void MainWindow::slotStartedSaving()
1391{
Zack Rusin1d0d2292011-04-18 01:52:13 -04001392 m_progressBar->show();
Zack Rusin9af5bff2011-04-18 01:05:50 -04001393 statusBar()->showMessage(
1394 tr("Saving to %1").arg(m_trace->fileName()));
1395}
1396
1397void MainWindow::slotSaved()
1398{
1399 statusBar()->showMessage(
1400 tr("Saved to %1").arg(m_trace->fileName()), 2000);
1401 m_progressBar->hide();
1402}
1403
Zack Rusin9623daf2011-04-18 18:03:34 -04001404void MainWindow::slotGoFrameStart()
1405{
Zack Rusin93e4d152011-09-13 02:23:39 -04001406 ApiTraceFrame *frame = currentFrame();
1407 ApiTraceCall *call = currentCall();
1408
1409 if (!frame && call) {
1410 frame = call->parentFrame();
Zack Rusin9623daf2011-04-18 18:03:34 -04001411 }
1412
Zack Rusin93e4d152011-09-13 02:23:39 -04001413 m_trace->findFrameStart(frame);
Zack Rusin9623daf2011-04-18 18:03:34 -04001414}
1415
1416void MainWindow::slotGoFrameEnd()
1417{
Zack Rusin93e4d152011-09-13 02:23:39 -04001418 ApiTraceFrame *frame = currentFrame();
1419 ApiTraceCall *call = currentCall();
Zack Rusin9623daf2011-04-18 18:03:34 -04001420
Zack Rusin93e4d152011-09-13 02:23:39 -04001421 if (!frame && call) {
1422 frame = call->parentFrame();
1423 }
1424
1425 m_trace->findFrameEnd(frame);
Zack Rusin9623daf2011-04-18 18:03:34 -04001426}
1427
Zack Rusin8f98c3a2011-09-11 18:21:29 -04001428ApiTraceFrame * MainWindow::selectedFrame() const
Zack Rusin9623daf2011-04-18 18:03:34 -04001429{
1430 if (m_selectedEvent) {
1431 if (m_selectedEvent->type() == ApiTraceEvent::Frame) {
1432 return static_cast<ApiTraceFrame*>(m_selectedEvent);
1433 } else {
1434 Q_ASSERT(m_selectedEvent->type() == ApiTraceEvent::Call);
1435 ApiTraceCall *call = static_cast<ApiTraceCall*>(m_selectedEvent);
1436 return call->parentFrame();
1437 }
1438 }
1439 return NULL;
1440}
1441
Dan McCabe10bd4242012-03-05 17:20:40 -08001442void MainWindow::slotTraceChanged(ApiTraceEvent *event)
Zack Rusincc0b4912011-04-19 01:59:20 -04001443{
Dan McCabe10bd4242012-03-05 17:20:40 -08001444 Q_ASSERT(event);
1445 if (event == m_selectedEvent) {
1446 if (event->type() == ApiTraceEvent::Call) {
1447 ApiTraceCall *call = static_cast<ApiTraceCall*>(event);
1448 m_ui.detailsWebView->setHtml(call->toHtml());
1449 }
Zack Rusincc0b4912011-04-19 01:59:20 -04001450 }
1451}
1452
Zack Rusin10fd4772011-09-14 01:45:12 -04001453void MainWindow::slotRetraceErrors(const QList<ApiTraceError> &errors)
Zack Rusinb39e1c62011-04-19 23:09:26 -04001454{
1455 m_ui.errorsTreeWidget->clear();
1456
Zack Rusin10fd4772011-09-14 01:45:12 -04001457 foreach(ApiTraceError error, errors) {
1458 m_trace->setCallError(error);
Zack Rusinb39e1c62011-04-19 23:09:26 -04001459
1460 QTreeWidgetItem *item =
1461 new QTreeWidgetItem(m_ui.errorsTreeWidget);
1462 item->setData(0, Qt::DisplayRole, error.callIndex);
Zack Rusin10fd4772011-09-14 01:45:12 -04001463 item->setData(0, Qt::UserRole, error.callIndex);
Zack Rusinb39e1c62011-04-19 23:09:26 -04001464 QString type = error.type;
1465 type[0] = type[0].toUpper();
1466 item->setData(1, Qt::DisplayRole, type);
1467 item->setData(2, Qt::DisplayRole, error.message);
1468 }
Zack Rusinb39e1c62011-04-19 23:09:26 -04001469}
1470
Zack Rusind9239342011-04-19 23:43:06 -04001471void MainWindow::slotErrorSelected(QTreeWidgetItem *current)
1472{
1473 if (current) {
Zack Rusin10fd4772011-09-14 01:45:12 -04001474 int callIndex =
1475 current->data(0, Qt::UserRole).toInt();
1476 m_trace->findCallIndex(callIndex);
Zack Rusind9239342011-04-19 23:43:06 -04001477 }
1478}
1479
Zack Rusin8f98c3a2011-09-11 18:21:29 -04001480ApiTraceCall * MainWindow::selectedCall() const
Zack Rusinbe547732011-04-23 17:16:34 -04001481{
1482 if (m_selectedEvent &&
1483 m_selectedEvent->type() == ApiTraceEvent::Call) {
1484 return static_cast<ApiTraceCall*>(m_selectedEvent);
1485 }
1486 return NULL;
1487}
1488
Zack Rusinfd638e52011-06-20 19:46:17 -04001489void MainWindow::saveSelectedSurface()
1490{
1491 QTreeWidgetItem *item =
1492 m_ui.surfacesTreeWidget->currentItem();
1493
Zack Rusinc5929572011-09-19 03:04:40 -04001494 if (!item || !m_trace) {
Zack Rusinfd638e52011-06-20 19:46:17 -04001495 return;
Zack Rusinc5929572011-09-19 03:04:40 -04001496 }
Zack Rusinfd638e52011-06-20 19:46:17 -04001497
1498 QVariant var = item->data(0, Qt::UserRole);
Edward Ruddb86e9932014-07-07 17:23:45 -04001499 if (!var.isValid()) {
1500 return;
1501 }
1502
Zack Rusinfd638e52011-06-20 19:46:17 -04001503 QImage img = var.value<QImage>();
Edward Ruddb86e9932014-07-07 17:23:45 -04001504 if (img.isNull()) {
Jose Fonseca93a7c0c2015-05-27 20:52:51 +01001505 image::Image *traceImage = ApiSurface::imageFromData(var.value<QByteArray>());
Edward Ruddb86e9932014-07-07 17:23:45 -04001506 img = ApiSurface::qimageFromRawImage(traceImage);
1507 delete traceImage;
1508 }
1509 if (img.isNull()) {
1510 statusBar()->showMessage( "Failed to save image", 5000);
1511 return;
1512 }
Zack Rusinfd638e52011-06-20 19:46:17 -04001513
1514 QString imageIndex;
Jose Fonsecad75bd302015-05-19 14:36:01 +01001515 ApiTraceCall *call = selectedCall();
1516 if (call) {
Zack Rusinfd638e52011-06-20 19:46:17 -04001517 imageIndex = tr("_call_%1")
Jose Fonsecad75bd302015-05-19 14:36:01 +01001518 .arg(call->index());
1519 } else {
1520 ApiTraceFrame *frame = selectedFrame();
1521 if (frame) {
Zack Rusinfd638e52011-06-20 19:46:17 -04001522 imageIndex = tr("_frame_%1")
Jose Fonsecad75bd302015-05-19 14:36:01 +01001523 .arg(frame->number);
Zack Rusinfd638e52011-06-20 19:46:17 -04001524 }
1525 }
1526
1527 //which of the surfaces are we saving
1528 QTreeWidgetItem *parent = item->parent();
1529 int parentIndex =
1530 m_ui.surfacesTreeWidget->indexOfTopLevelItem(parent);
1531 if (parentIndex < 0) {
1532 parentIndex = 0;
1533 }
1534 int childIndex = 0;
1535 if (parent) {
1536 childIndex = parent->indexOfChild(item);
1537 } else {
1538 childIndex = m_ui.surfacesTreeWidget->indexOfTopLevelItem(item);
1539 }
1540
1541
1542 QString fileName =
1543 tr("%1%2-%3_%4.png")
1544 .arg(m_trace->fileName())
1545 .arg(imageIndex)
1546 .arg(parentIndex)
1547 .arg(childIndex);
1548 //qDebug()<<"save "<<fileName;
Edward Ruddb86e9932014-07-07 17:23:45 -04001549 if (img.save(fileName, "PNG")) {
1550 statusBar()->showMessage( tr("Saved '%1'").arg(fileName), 5000);
1551 } else {
1552 statusBar()->showMessage( tr("Failed to save '%1'").arg(fileName), 5000);
1553 }
Zack Rusinfd638e52011-06-20 19:46:17 -04001554}
1555
Edward Rudd14158b92014-07-07 17:46:05 -04001556void MainWindow::exportBufferData()
1557{
1558 QByteArray data = m_vdataInterpreter->data();
1559 if (data.isEmpty())
1560 return;
1561
1562 QString bufferIndex;
Jose Fonsecad75bd302015-05-19 14:36:01 +01001563 ApiTraceCall *call = selectedCall();
1564 if (call) {
1565 bufferIndex = tr("_call_%1").arg(call->index());
1566 } else {
1567 ApiTraceFrame *frame = selectedFrame();
1568 if (frame) {
Edward Rudd14158b92014-07-07 17:46:05 -04001569 bufferIndex = tr("_frame_%1")
Jose Fonsecad75bd302015-05-19 14:36:01 +01001570 .arg(frame->number);
Edward Rudd14158b92014-07-07 17:46:05 -04001571 }
1572 }
1573
1574 QString filename =
1575 tr("%1%2_buffer.raw")
1576 .arg(m_trace->fileName())
1577 .arg(bufferIndex);
1578
1579 QFile file(filename);
1580 if (!file.open(QIODevice::WriteOnly)) {
1581 statusBar()->showMessage("Failed to save buffer data", 5000);
1582 return;
1583 }
1584
1585 if (file.write(data) == -1) {
1586 statusBar()->showMessage("Failed to save buffer data", 5000);
1587 return;
1588 }
1589
1590 file.close();
1591
1592 statusBar()->showMessage( tr("Saved buffer to '%1'").arg(filename), 5000);
1593}
1594
Zack Rusinebf971e2011-09-06 17:44:43 -04001595void MainWindow::loadProgess(int percent)
1596{
1597 m_progressBar->setValue(percent);
1598}
1599
Zack Rusinad513b32011-09-25 14:33:41 -04001600void MainWindow::slotSearchResult(const ApiTrace::SearchRequest &request,
1601 ApiTrace::SearchResult result,
Zack Rusin8f98c3a2011-09-11 18:21:29 -04001602 ApiTraceCall *call)
1603{
1604 switch (result) {
Zack Rusin1a9f7af2011-09-18 19:40:47 -04001605 case ApiTrace::SearchResult_NotFound:
Zack Rusin8f98c3a2011-09-11 18:21:29 -04001606 m_searchWidget->setFound(false);
1607 break;
Zack Rusin1a9f7af2011-09-18 19:40:47 -04001608 case ApiTrace::SearchResult_Found: {
Zack Rusin8f98c3a2011-09-11 18:21:29 -04001609 QModelIndex index = m_proxyModel->indexForCall(call);
Zack Rusinad513b32011-09-25 14:33:41 -04001610
1611 if (index.isValid()) {
1612 m_ui.callView->setCurrentIndex(index);
1613 m_searchWidget->setFound(true);
1614 } else {
1615 //call is filtered out, so continue searching but from the
1616 // filtered call
1617 if (!call) {
1618 qDebug()<<"Error: search success with no call";
1619 return;
1620 }
1621// qDebug()<<"filtered! search from "<<call->searchText()
1622// <<", call idx = "<<call->index();
1623
1624 if (request.direction == ApiTrace::SearchRequest::Next) {
1625 m_trace->findNext(call->parentFrame(), call,
1626 request.text, request.cs);
1627 } else {
1628 m_trace->findNext(call->parentFrame(), call,
1629 request.text, request.cs);
1630 }
1631 }
Zack Rusin8f98c3a2011-09-11 18:21:29 -04001632 }
1633 break;
Zack Rusin1a9f7af2011-09-18 19:40:47 -04001634 case ApiTrace::SearchResult_Wrapped:
Zack Rusin8f98c3a2011-09-11 18:21:29 -04001635 m_searchWidget->setFound(false);
1636 break;
1637 }
1638}
1639
1640ApiTraceFrame * MainWindow::currentFrame() const
1641{
1642 QModelIndex index = m_ui.callView->currentIndex();
1643 ApiTraceEvent *event = 0;
1644
1645 if (!index.isValid()) {
1646 index = m_proxyModel->index(0, 0, QModelIndex());
1647 if (!index.isValid()) {
1648 qDebug()<<"no currently valid index";
1649 return 0;
1650 }
1651 }
1652
1653 event = index.data(ApiTraceModel::EventRole).value<ApiTraceEvent*>();
1654 Q_ASSERT(event);
1655 if (!event) {
1656 return 0;
1657 }
1658
1659 ApiTraceFrame *frame = 0;
1660 if (event->type() == ApiTraceCall::Frame) {
1661 frame = static_cast<ApiTraceFrame*>(event);
1662 }
1663 return frame;
1664}
1665
1666ApiTraceCall * MainWindow::currentCall() const
1667{
1668 QModelIndex index = m_ui.callView->currentIndex();
1669 ApiTraceEvent *event = 0;
1670
1671 if (!index.isValid()) {
1672 index = m_proxyModel->index(0, 0, QModelIndex());
1673 if (!index.isValid()) {
1674 qDebug()<<"no currently valid index";
1675 return 0;
1676 }
1677 }
1678
1679 event = index.data(ApiTraceModel::EventRole).value<ApiTraceEvent*>();
1680 Q_ASSERT(event);
1681 if (!event) {
1682 return 0;
1683 }
1684
1685 ApiTraceCall *call = 0;
1686 if (event->type() == ApiTraceCall::Call) {
1687 call = static_cast<ApiTraceCall*>(event);
1688 }
1689
1690 return call;
1691
1692}
1693
Zack Rusin93e4d152011-09-13 02:23:39 -04001694void MainWindow::slotFoundFrameStart(ApiTraceFrame *frame)
1695{
Zack Rusin1a9f7af2011-09-18 19:40:47 -04001696 Q_ASSERT(frame->isLoaded());
Zack Rusin93e4d152011-09-13 02:23:39 -04001697 if (!frame || frame->isEmpty()) {
1698 return;
1699 }
1700
1701 QVector<ApiTraceCall*>::const_iterator itr;
1702 QVector<ApiTraceCall*> calls = frame->calls();
1703
1704 itr = calls.constBegin();
1705 while (itr != calls.constEnd()) {
1706 ApiTraceCall *call = *itr;
1707 QModelIndex idx = m_proxyModel->indexForCall(call);
1708 if (idx.isValid()) {
1709 m_ui.callView->setCurrentIndex(idx);
James Bentonfc4f55a2012-08-08 17:09:07 +01001710 m_ui.callView->scrollTo(idx, QAbstractItemView::PositionAtTop);
Zack Rusin93e4d152011-09-13 02:23:39 -04001711 break;
1712 }
1713 ++itr;
1714 }
1715}
1716
1717void MainWindow::slotFoundFrameEnd(ApiTraceFrame *frame)
1718{
Zack Rusin1a9f7af2011-09-18 19:40:47 -04001719 Q_ASSERT(frame->isLoaded());
Zack Rusin93e4d152011-09-13 02:23:39 -04001720 if (!frame || frame->isEmpty()) {
1721 return;
1722 }
1723 QVector<ApiTraceCall*>::const_iterator itr;
1724 QVector<ApiTraceCall*> calls = frame->calls();
1725
1726 itr = calls.constEnd();
1727 do {
1728 --itr;
1729 ApiTraceCall *call = *itr;
1730 QModelIndex idx = m_proxyModel->indexForCall(call);
1731 if (idx.isValid()) {
1732 m_ui.callView->setCurrentIndex(idx);
James Bentonfc4f55a2012-08-08 17:09:07 +01001733 m_ui.callView->scrollTo(idx, QAbstractItemView::PositionAtBottom);
Zack Rusin93e4d152011-09-13 02:23:39 -04001734 break;
1735 }
1736 } while (itr != calls.constBegin());
1737}
1738
Zack Rusinda7579b2011-09-13 17:33:05 -04001739void MainWindow::slotJumpToResult(ApiTraceCall *call)
1740{
James Bentonfc4f55a2012-08-08 17:09:07 +01001741 QModelIndex idx = m_proxyModel->indexForCall(call);
1742 if (idx.isValid()) {
1743 activateWindow();
1744 m_ui.callView->setFocus();
1745 m_ui.callView->setCurrentIndex(idx);
1746 m_ui.callView->scrollTo(idx, QAbstractItemView::PositionAtCenter);
Zack Rusin10fd4772011-09-14 01:45:12 -04001747 } else {
1748 statusBar()->showMessage(tr("Call has been filtered out."));
Zack Rusinda7579b2011-09-13 17:33:05 -04001749 }
1750}
1751
Dan McCabe88938852012-06-01 13:40:04 -07001752void MainWindow::thumbnailCallback(void *object, int thumbnailIdx)
1753{
1754 //qDebug() << QLatin1String("debug: transfer from trace to retracer thumbnail index: ") << thumbnailIdx;
1755 MainWindow *mySelf = (MainWindow *) object;
1756 mySelf->m_retracer->addThumbnailToCapture(thumbnailIdx);
1757}
1758
Zack Rusin601e8372011-03-24 22:23:21 -04001759#include "mainwindow.moc"