X-Git-Url: https://git.cworth.org/git?a=blobdiff_plain;f=gui%2Fmainwindow.cpp;h=f63b87e0600323632a3612cbc85da8ee628cf881;hb=52eaaa2f3749692d587a41145da900f9014e9002;hp=f3aed9f5e15bf841d5969d6e592b7d385c78ea56;hpb=1b91705727d2b9f91345b6d4a462650cb1007618;p=apitrace diff --git a/gui/mainwindow.cpp b/gui/mainwindow.cpp index f3aed9f..f63b87e 100644 --- a/gui/mainwindow.cpp +++ b/gui/mainwindow.cpp @@ -5,12 +5,17 @@ #include "apicalldelegate.h" #include "apitracemodel.h" #include "apitracefilter.h" +#include "imageviewer.h" +#include "jumpwidget.h" #include "retracer.h" +#include "searchwidget.h" #include "settingsdialog.h" +#include "shaderssourcewidget.h" +#include "tracedialog.h" +#include "traceprocess.h" +#include "ui_retracerdialog.h" #include "vertexdatainterpreter.h" -#include - #include #include #include @@ -19,8 +24,10 @@ #include #include #include +#include #include #include +#include #include #include @@ -28,95 +35,32 @@ MainWindow::MainWindow() : QMainWindow(), m_selectedEvent(0), - m_stateEvent(0), - m_jsonParser(new QJson::Parser()) + m_stateEvent(0) { m_ui.setupUi(this); - m_ui.stateTreeWidget->sortByColumn(0, Qt::AscendingOrder); - - m_trace = new ApiTrace(); - connect(m_trace, SIGNAL(startedLoadingTrace()), - this, SLOT(startedLoadingTrace())); - connect(m_trace, SIGNAL(finishedLoadingTrace()), - this, SLOT(finishedLoadingTrace())); - - m_retracer = new Retracer(this); - connect(m_retracer, SIGNAL(finished(const QByteArray&)), - this, SLOT(replayFinished(const QByteArray&))); - connect(m_retracer, SIGNAL(error(const QString&)), - this, SLOT(replayError(const QString&))); - - m_vdataInterpreter = new VertexDataInterpreter(this); - m_vdataInterpreter->setListWidget(m_ui.vertexDataListWidget); - m_vdataInterpreter->setStride( - m_ui.vertexStrideSB->value()); - m_vdataInterpreter->setComponents( - m_ui.vertexComponentsSB->value()); - m_vdataInterpreter->setStartingOffset( - m_ui.startingOffsetSB->value()); - m_vdataInterpreter->setTypeFromString( - m_ui.vertexTypeCB->currentText()); - - connect(m_ui.vertexInterpretButton, SIGNAL(clicked()), - m_vdataInterpreter, SLOT(interpretData())); - connect(m_ui.vertexTypeCB, SIGNAL(currentIndexChanged(const QString&)), - m_vdataInterpreter, SLOT(setTypeFromString(const QString&))); - connect(m_ui.vertexStrideSB, SIGNAL(valueChanged(int)), - m_vdataInterpreter, SLOT(setStride(int))); - connect(m_ui.vertexComponentsSB, SIGNAL(valueChanged(int)), - m_vdataInterpreter, SLOT(setComponents(int))); - connect(m_ui.startingOffsetSB, SIGNAL(valueChanged(int)), - m_vdataInterpreter, SLOT(setStartingOffset(int))); - - m_model = new ApiTraceModel(); - m_model->setApiTrace(m_trace); - m_proxyModel = new ApiTraceFilter(); - m_proxyModel->setSourceModel(m_model); - m_ui.callView->setModel(m_proxyModel); - m_ui.callView->setItemDelegate(new ApiCallDelegate); - m_ui.callView->resizeColumnToContents(0); - m_ui.callView->header()->swapSections(0, 1); - m_ui.callView->setColumnWidth(1, 42); - - QToolBar *toolBar = addToolBar(tr("Navigation")); - m_filterEdit = new QLineEdit(toolBar); - toolBar->addWidget(m_filterEdit); - - m_progressBar = new QProgressBar(); - m_progressBar->setRange(0, 0); - statusBar()->addPermanentWidget(m_progressBar); - m_progressBar->hide(); - - m_ui.detailsDock->hide(); - m_ui.vertexDataDock->hide(); - m_ui.stateDock->hide(); - setDockOptions(dockOptions() | QMainWindow::ForceTabbedDocks); - - tabifyDockWidget(m_ui.stateDock, m_ui.vertexDataDock); - - connect(m_ui.actionOpen, SIGNAL(triggered()), - this, SLOT(openTrace())); - connect(m_ui.actionQuit, SIGNAL(triggered()), - this, SLOT(close())); + initObjects(); + initConnections(); +} - connect(m_ui.actionReplay, SIGNAL(triggered()), - this, SLOT(replayStart())); - connect(m_ui.actionStop, SIGNAL(triggered()), - this, SLOT(replayStop())); - connect(m_ui.actionLookupState, SIGNAL(triggered()), - this, SLOT(lookupState())); - connect(m_ui.actionOptions, SIGNAL(triggered()), - this, SLOT(showSettings())); +void MainWindow::createTrace() +{ + TraceDialog dialog; - connect(m_ui.callView, SIGNAL(activated(const QModelIndex &)), - this, SLOT(callItemSelected(const QModelIndex &))); - connect(m_filterEdit, SIGNAL(returnPressed()), - this, SLOT(filterTrace())); + if (!m_traceProcess->canTrace()) { + QMessageBox::warning( + this, + tr("Unsupported"), + tr("Current configuration doesn't support tracing.")); + return; + } - m_ui.detailsWebView->page()->setLinkDelegationPolicy( - QWebPage::DelegateExternalLinks); - connect(m_ui.detailsWebView, SIGNAL(linkClicked(const QUrl&)), - this, SLOT(openHelp(const QUrl&))); + if (dialog.exec() == QDialog::Accepted) { + qDebug()<< "App : " <setExecutablePath(dialog.applicationPath()); + m_traceProcess->setArguments(dialog.arguments()); + m_traceProcess->start(); + } } void MainWindow::openTrace() @@ -192,19 +136,29 @@ void MainWindow::callItemSelected(const QModelIndex &index) m_ui.stateDock->hide(); } -void MainWindow::filterTrace() -{ - m_proxyModel->setFilterString(m_filterEdit->text()); -} - void MainWindow::replayStart() { - replayTrace(false); + QDialog dlg; + Ui_RetracerDialog dlgUi; + dlgUi.setupUi(&dlg); + + dlgUi.doubleBufferingCB->setChecked( + m_retracer->isDoubleBuffered()); + dlgUi.benchmarkCB->setChecked( + m_retracer->isBenchmarking()); + + if (dlg.exec() == QDialog::Accepted) { + m_retracer->setDoubleBuffered( + dlgUi.doubleBufferingCB->isChecked()); + m_retracer->setBenchmarking( + dlgUi.benchmarkCB->isChecked()); + replayTrace(false); + } } void MainWindow::replayStop() { - m_retracer->terminate(); + m_retracer->quit(); m_ui.actionStop->setEnabled(false); m_ui.actionReplay->setEnabled(true); m_ui.actionLookupState->setEnabled(true); @@ -228,20 +182,19 @@ void MainWindow::newTraceFile(const QString &fileName) } } -void MainWindow::replayFinished(const QByteArray &output) +void MainWindow::replayFinished(const QString &output) { m_ui.actionStop->setEnabled(false); m_ui.actionReplay->setEnabled(true); m_ui.actionLookupState->setEnabled(true); - if (m_retracer->captureState()) { - bool ok = false; - QVariantMap parsedJson = m_jsonParser->parse(output, &ok).toMap(); - parseState(parsedJson[QLatin1String("parameters")].toMap()); - } else if (output.length() < 80) { + m_progressBar->hide(); + if (output.length() < 80) { statusBar()->showMessage(output); } m_stateEvent = 0; + statusBar()->showMessage( + tr("Replaying finished!"), 2000); } void MainWindow::replayError(const QString &message) @@ -251,6 +204,9 @@ void MainWindow::replayError(const QString &message) m_ui.actionLookupState->setEnabled(true); m_stateEvent = 0; + m_progressBar->hide(); + statusBar()->showMessage( + tr("Replaying unsuccessful."), 2000); QMessageBox::warning( this, tr("Replay Failed"), message); } @@ -287,7 +243,8 @@ void MainWindow::replayTrace(bool dumpState) if (m_selectedEvent->type() == ApiTraceEvent::Call) { index = static_cast(m_selectedEvent)->index; } else if (m_selectedEvent->type() == ApiTraceEvent::Frame) { - ApiTraceFrame *frame = static_cast(m_selectedEvent); + ApiTraceFrame *frame = + static_cast(m_selectedEvent); if (frame->calls.isEmpty()) { //XXX i guess we could still get the current state qDebug()<<"tried to get a state for an empty frame"; @@ -303,6 +260,13 @@ void MainWindow::replayTrace(bool dumpState) m_retracer->start(); m_ui.actionStop->setEnabled(true); + m_progressBar->show(); + if (dumpState) + statusBar()->showMessage( + tr("Looking up the state...")); + else + statusBar()->showMessage( + tr("Replaying the trace file...")); } void MainWindow::lookupState() @@ -319,20 +283,6 @@ void MainWindow::lookupState() MainWindow::~MainWindow() { - delete m_jsonParser; -} - -void MainWindow::parseState(const QVariantMap ¶ms) -{ - QVariantMap::const_iterator itr; - - m_stateEvent->setState(params); - m_model->stateSetOnEvent(m_stateEvent); - if (m_selectedEvent == m_stateEvent) { - fillStateForFrame(); - } else { - m_ui.stateDock->hide(); - } } static void @@ -357,41 +307,205 @@ variantToString(const QVariant &var, QString &str) } } -void MainWindow::fillStateForFrame() +static QTreeWidgetItem * +variantToItem(const QString &key, const QVariant &var, const QVariant &defaultVar); + +static void +variantMapToItems(const QVariantMap &map, const QVariantMap &defaultMap, QList &items) { QVariantMap::const_iterator itr; + for (itr = map.constBegin(); itr != map.constEnd(); ++itr) { + QString key = itr.key(); + QVariant var = itr.value(); + QVariant defaultVar = defaultMap[key]; + + QTreeWidgetItem *item = variantToItem(key, var, defaultVar); + if (item) { + items.append(item); + } + } +} + +static void +variantListToItems(const QVariantList &lst, const QVariantList &defaultLst, QList &items) +{ + for (int i = 0; i < lst.count(); ++i) { + QString key = QString::number(i); + QVariant var = lst[i]; + QVariant defaultVar; + + if (i < defaultLst.count()) { + defaultVar = defaultLst[i]; + } + + QTreeWidgetItem *item = variantToItem(key, var, defaultVar); + if (item) { + items.append(item); + } + } +} + +static bool +isVariantDeep(const QVariant &var) +{ + if (var.type() == QVariant::List) { + QVariantList lst = var.toList(); + for (int i = 0; i < lst.count(); ++i) { + if (isVariantDeep(lst[i])) { + return true; + } + } + return false; + } else if (var.type() == QVariant::Map) { + return true; + } else if (var.type() == QVariant::Hash) { + return true; + } else { + return false; + } +} + +static QTreeWidgetItem * +variantToItem(const QString &key, const QVariant &var, const QVariant &defaultVar) +{ + if (var == defaultVar) { + return NULL; + } + + QString val; + + bool deep = isVariantDeep(var); + if (!deep) { + variantToString(var, val); + } + + //qDebug()<<"key = "<setExpanded(true); + + for (int i = 0; i < textures.count(); ++i) { + const ApiTexture &texture = + textures[i]; + QIcon icon(QPixmap::fromImage(texture.thumb())); + QTreeWidgetItem *item = new QTreeWidgetItem(textureItem); + item->setIcon(0, icon); + int width = texture.size().width(); + int height = texture.size().height(); + QString descr = + QString::fromLatin1("%1, %2 x %3") + .arg(texture.target()) + .arg(width) + .arg(height); + item->setText(1, descr); + + item->setData(0, Qt::UserRole, + texture.image()); + } + } + if (!fbos.isEmpty()) { + QTreeWidgetItem *fboItem = + new QTreeWidgetItem(m_ui.surfacesTreeWidget); + fboItem->setText(0, tr("Framebuffers")); + if (fbos.count() <= 6) + fboItem->setExpanded(true); + + for (int i = 0; i < fbos.count(); ++i) { + const ApiFramebuffer &fbo = + fbos[i]; + QIcon icon(QPixmap::fromImage(fbo.thumb())); + QTreeWidgetItem *item = new QTreeWidgetItem(fboItem); + item->setIcon(0, icon); + int width = fbo.size().width(); + int height = fbo.size().height(); + QString descr = + QString::fromLatin1("%1, %2 x %3") + .arg(fbo.type()) + .arg(width) + .arg(height); + item->setText(1, descr); + + item->setData(0, Qt::UserRole, + fbo.image()); + } + } + m_ui.surfacesTab->setEnabled(true); + } m_ui.stateDock->show(); } void MainWindow::showSettings() { SettingsDialog dialog; - dialog.setFilterOptions(m_proxyModel->filterOptions()); + dialog.setFilterModel(m_proxyModel); - if (dialog.exec() == QDialog::Accepted) { - m_proxyModel->setFilterOptions(dialog.filterOptions()); - } + dialog.exec(); } void MainWindow::openHelp(const QUrl &url) @@ -399,4 +513,355 @@ void MainWindow::openHelp(const QUrl &url) QDesktopServices::openUrl(url); } +void MainWindow::showSurfacesMenu(const QPoint &pos) +{ + QTreeWidget *tree = m_ui.surfacesTreeWidget; + QTreeWidgetItem *item = tree->itemAt(pos); + if (!item) + return; + + QMenu menu(tr("Surfaces"), this); + //add needed actions + QAction *act = menu.addAction(tr("View Image")); + act->setStatusTip(tr("View the currently selected surface")); + connect(act, SIGNAL(triggered()), + SLOT(showSelectedSurface())); + + menu.exec(tree->viewport()->mapToGlobal(pos)); +} + +void MainWindow::showSelectedSurface() +{ + QTreeWidgetItem *item = + m_ui.surfacesTreeWidget->currentItem(); + + if (!item) + return; + + QVariant var = item->data(0, Qt::UserRole); + m_imageViewer->setImage(var.value()); + m_imageViewer->show(); + m_imageViewer->raise(); + m_imageViewer->activateWindow(); +} + +void MainWindow::initObjects() +{ + m_ui.stateTreeWidget->sortByColumn(0, Qt::AscendingOrder); + + m_sourcesWidget = new ShadersSourceWidget(m_ui.shadersTab); + QVBoxLayout *layout = new QVBoxLayout; + layout->addWidget(m_sourcesWidget); + m_ui.shadersTab->setLayout(layout); + + m_trace = new ApiTrace(); + m_retracer = new Retracer(this); + + m_vdataInterpreter = new VertexDataInterpreter(this); + m_vdataInterpreter->setListWidget(m_ui.vertexDataListWidget); + m_vdataInterpreter->setStride( + m_ui.vertexStrideSB->value()); + m_vdataInterpreter->setComponents( + m_ui.vertexComponentsSB->value()); + m_vdataInterpreter->setStartingOffset( + m_ui.startingOffsetSB->value()); + m_vdataInterpreter->setTypeFromString( + m_ui.vertexTypeCB->currentText()); + + m_imageViewer = new ImageViewer(this); + + m_model = new ApiTraceModel(); + m_model->setApiTrace(m_trace); + m_proxyModel = new ApiTraceFilter(); + m_proxyModel->setSourceModel(m_model); + m_ui.callView->setModel(m_proxyModel); + m_ui.callView->setItemDelegate(new ApiCallDelegate); + m_ui.callView->resizeColumnToContents(0); + m_ui.callView->header()->swapSections(0, 1); + m_ui.callView->setColumnWidth(1, 42); + + m_progressBar = new QProgressBar(); + m_progressBar->setRange(0, 0); + statusBar()->addPermanentWidget(m_progressBar); + m_progressBar->hide(); + + m_ui.detailsDock->hide(); + m_ui.vertexDataDock->hide(); + m_ui.stateDock->hide(); + setDockOptions(dockOptions() | QMainWindow::ForceTabbedDocks); + + tabifyDockWidget(m_ui.stateDock, m_ui.vertexDataDock); + + m_ui.surfacesTreeWidget->setContextMenuPolicy(Qt::CustomContextMenu); + + m_ui.detailsWebView->page()->setLinkDelegationPolicy( + QWebPage::DelegateExternalLinks); + + m_jumpWidget = new JumpWidget(this); + m_ui.centralLayout->addWidget(m_jumpWidget); + m_jumpWidget->hide(); + + m_searchWidget = new SearchWidget(this); + m_ui.centralLayout->addWidget(m_searchWidget); + m_searchWidget->hide(); + + m_traceProcess = new TraceProcess(this); + + new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_G), + this, SLOT(slotGoTo())); + new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_F), + this, SLOT(slotSearch())); +} + +void MainWindow::initConnections() +{ + connect(m_trace, SIGNAL(startedLoadingTrace()), + this, SLOT(startedLoadingTrace())); + connect(m_trace, SIGNAL(finishedLoadingTrace()), + this, SLOT(finishedLoadingTrace())); + + connect(m_retracer, SIGNAL(finished(const QString&)), + this, SLOT(replayFinished(const QString&))); + connect(m_retracer, SIGNAL(error(const QString&)), + this, SLOT(replayError(const QString&))); + connect(m_retracer, SIGNAL(foundState(const ApiTraceState&)), + this, SLOT(replayStateFound(const ApiTraceState&))); + + connect(m_ui.vertexInterpretButton, SIGNAL(clicked()), + m_vdataInterpreter, SLOT(interpretData())); + connect(m_ui.vertexTypeCB, SIGNAL(currentIndexChanged(const QString&)), + m_vdataInterpreter, SLOT(setTypeFromString(const QString&))); + connect(m_ui.vertexStrideSB, SIGNAL(valueChanged(int)), + m_vdataInterpreter, SLOT(setStride(int))); + connect(m_ui.vertexComponentsSB, SIGNAL(valueChanged(int)), + m_vdataInterpreter, SLOT(setComponents(int))); + connect(m_ui.startingOffsetSB, SIGNAL(valueChanged(int)), + m_vdataInterpreter, SLOT(setStartingOffset(int))); + + + connect(m_ui.actionNew, SIGNAL(triggered()), + this, SLOT(createTrace())); + connect(m_ui.actionOpen, SIGNAL(triggered()), + this, SLOT(openTrace())); + connect(m_ui.actionQuit, SIGNAL(triggered()), + this, SLOT(close())); + + connect(m_ui.actionReplay, SIGNAL(triggered()), + this, SLOT(replayStart())); + connect(m_ui.actionStop, SIGNAL(triggered()), + this, SLOT(replayStop())); + connect(m_ui.actionLookupState, SIGNAL(triggered()), + this, SLOT(lookupState())); + connect(m_ui.actionOptions, SIGNAL(triggered()), + this, SLOT(showSettings())); + + connect(m_ui.callView, SIGNAL(activated(const QModelIndex &)), + this, SLOT(callItemSelected(const QModelIndex &))); + + connect(m_ui.surfacesTreeWidget, + SIGNAL(customContextMenuRequested(const QPoint &)), + SLOT(showSurfacesMenu(const QPoint &))); + connect(m_ui.surfacesTreeWidget, + SIGNAL(itemDoubleClicked(QTreeWidgetItem *, int)), + SLOT(showSelectedSurface())); + + connect(m_ui.detailsWebView, SIGNAL(linkClicked(const QUrl&)), + this, SLOT(openHelp(const QUrl&))); + + connect(m_ui.nonDefaultsCB, SIGNAL(toggled(bool)), + this, SLOT(fillState(bool))); + + connect(m_jumpWidget, SIGNAL(jumpTo(int)), + SLOT(slotJumpTo(int))); + + connect(m_searchWidget, + SIGNAL(searchNext(const QString&, Qt::CaseSensitivity)), + SLOT(slotSearchNext(const QString&, Qt::CaseSensitivity))); + connect(m_searchWidget, + SIGNAL(searchPrev(const QString&, Qt::CaseSensitivity)), + SLOT(slotSearchPrev(const QString&, Qt::CaseSensitivity))); + + connect(m_traceProcess, SIGNAL(tracedFile(const QString&)), + SLOT(createdTrace(const QString&))); + connect(m_traceProcess, SIGNAL(error(const QString&)), + SLOT(traceError(const QString&))); +} + +void MainWindow::replayStateFound(const ApiTraceState &state) +{ + m_stateEvent->setState(state); + m_model->stateSetOnEvent(m_stateEvent); + if (m_selectedEvent == m_stateEvent) { + fillStateForFrame(); + } else { + m_ui.stateDock->hide(); + } +} + +void MainWindow::slotGoTo() +{ + m_searchWidget->hide(); + m_jumpWidget->show(); +} + +void MainWindow::slotJumpTo(int callNum) +{ + QModelIndex index = m_proxyModel->callIndex(callNum); + if (index.isValid()) { + m_ui.callView->setCurrentIndex(index); + } +} + +void MainWindow::createdTrace(const QString &path) +{ + qDebug()<<"Done tracing "<hide(); + m_searchWidget->show(); +} + +void MainWindow::slotSearchNext(const QString &str, Qt::CaseSensitivity sensitivity) +{ + QModelIndex index = m_ui.callView->currentIndex(); + ApiTraceEvent *event = 0; + + + if (!index.isValid()) { + index = m_proxyModel->index(0, 0, QModelIndex()); + if (!index.isValid()) { + qDebug()<<"no currently valid index"; + m_searchWidget->setFound(false); + return; + } + } + + event = index.data(ApiTraceModel::EventRole).value(); + ApiTraceCall *call = 0; + + if (event->type() == ApiTraceCall::Call) + call = static_cast(event); + else { + Q_ASSERT(event->type() == ApiTraceCall::Frame); + ApiTraceFrame *frame = static_cast(event); + call = frame->calls.value(0); + } + + if (!call) { + m_searchWidget->setFound(false); + return; + } + const QList &calls = m_trace->calls(); + int callNum = calls.indexOf(call); + + for (int i = callNum + 1; i < calls.count(); ++i) { + ApiTraceCall *testCall = calls[i]; + QString txt = testCall->filterText(); + if (txt.contains(str, sensitivity)) { + QModelIndex index = m_proxyModel->indexForCall(testCall); + /* if it's not valid it means that the proxy model has already + * filtered it out */ + if (index.isValid()) { + m_ui.callView->setCurrentIndex(index); + m_searchWidget->setFound(true); + return; + } + } + } + m_searchWidget->setFound(false); +} + +void MainWindow::slotSearchPrev(const QString &str, Qt::CaseSensitivity sensitivity) +{ + QModelIndex index = m_ui.callView->currentIndex(); + ApiTraceEvent *event = 0; + + + if (!index.isValid()) { + index = m_proxyModel->index(0, 0, QModelIndex()); + if (!index.isValid()) { + qDebug()<<"no currently valid index"; + m_searchWidget->setFound(false); + return; + } + } + + event = index.data(ApiTraceModel::EventRole).value(); + ApiTraceCall *call = 0; + + if (event->type() == ApiTraceCall::Call) + call = static_cast(event); + else { + Q_ASSERT(event->type() == ApiTraceCall::Frame); + ApiTraceFrame *frame = static_cast(event); + call = frame->calls.value(0); + } + + if (!call) { + m_searchWidget->setFound(false); + return; + } + const QList &calls = m_trace->calls(); + int callNum = calls.indexOf(call); + + for (int i = callNum - 1; i >= 0; --i) { + ApiTraceCall *testCall = calls[i]; + QString txt = testCall->filterText(); + if (txt.contains(str, sensitivity)) { + QModelIndex index = m_proxyModel->indexForCall(testCall); + /* if it's not valid it means that the proxy model has already + * filtered it out */ + if (index.isValid()) { + m_ui.callView->setCurrentIndex(index); + m_searchWidget->setFound(true); + return; + } + } + } + m_searchWidget->setFound(false); +} + +void MainWindow::fillState(bool nonDefaults) +{ + if (nonDefaults) { + ApiTraceState defaultState = m_trace->defaultState(); + if (defaultState.isEmpty()) { + m_ui.nonDefaultsCB->blockSignals(true); + m_ui.nonDefaultsCB->setChecked(false); + m_ui.nonDefaultsCB->blockSignals(false); + int ret = QMessageBox::question( + this, tr("Empty Default State"), + tr("The applcation needs to figure out the " + "default state for the current trace. " + "This only has to be done once and " + "afterwards you will be able to enable " + "displaying of non default state for all calls." + "\nDo you want to lookup the default state now?"), + QMessageBox::Yes | QMessageBox::No); + if (ret != QMessageBox::Yes) + return; + ApiTraceFrame *firstFrame = + m_trace->frameAt(0); + ApiTraceEvent *oldSelected = m_selectedEvent; + if (!firstFrame) + return; + m_selectedEvent = firstFrame; + lookupState(); + m_selectedEvent = oldSelected; + } + } + fillStateForFrame(); +} + #include "mainwindow.moc"