X-Git-Url: https://git.cworth.org/git?a=blobdiff_plain;f=gui%2Fmainwindow.cpp;h=e5f6d9b2a4b7852a71d375fac33055940e6cbf8c;hb=ebf971eec6c3a5f98885cc418e04690ba213b645;hp=e2d58b6cb55bf0f6d967dbadc2e79f6b83b134e9;hpb=3438a524eb988749c39d849cb0127996d6656471;p=apitrace diff --git a/gui/mainwindow.cpp b/gui/mainwindow.cpp index e2d58b6..e5f6d9b 100644 --- a/gui/mainwindow.cpp +++ b/gui/mainwindow.cpp @@ -5,17 +5,23 @@ #include "apicalldelegate.h" #include "apitracemodel.h" #include "apitracefilter.h" +#include "argumentseditor.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 +#include #include #include #include @@ -31,7 +37,8 @@ MainWindow::MainWindow() : QMainWindow(), m_selectedEvent(0), - m_stateEvent(0) + m_stateEvent(0), + m_nonDefaultsLookupEvent(0) { m_ui.setupUi(this); initObjects(); @@ -42,9 +49,20 @@ void MainWindow::createTrace() { TraceDialog dialog; + if (!m_traceProcess->canTrace()) { + QMessageBox::warning( + this, + tr("Unsupported"), + tr("Current configuration doesn't support tracing.")); + return; + } + if (dialog.exec() == QDialog::Accepted) { qDebug()<< "App : " <setExecutablePath(dialog.applicationPath()); + m_traceProcess->setArguments(dialog.arguments()); + m_traceProcess->start(); } } @@ -57,9 +75,9 @@ void MainWindow::openTrace() QDir::homePath(), tr("Trace Files (*.trace)")); - qDebug()<< "File name : " <setValue(0); newTraceFile(fileName); } @@ -86,19 +102,20 @@ void MainWindow::callItemSelected(const QModelIndex &index) m_ui.detailsDock->show(); if (call->hasBinaryData()) { QByteArray data = - call->argValues[call->binaryDataIndex()].toByteArray(); + call->arguments()[call->binaryDataIndex()].toByteArray(); m_vdataInterpreter->setData(data); + QVector args = call->arguments(); - for (int i = 0; i < call->argNames.count(); ++i) { - QString name = call->argNames[i]; + for (int i = 0; i < call->argNames().count(); ++i) { + QString name = call->argNames()[i]; if (name == QLatin1String("stride")) { - int stride = call->argValues[i].toInt(); + int stride = args[i].toInt(); m_ui.vertexStrideSB->setValue(stride); } else if (name == QLatin1String("size")) { - int components = call->argValues[i].toInt(); + int components = args[i].toInt(); m_ui.vertexComponentsSB->setValue(components); } else if (name == QLatin1String("type")) { - QString val = call->argValues[i].toString(); + QString val = args[i].toString(); int textIndex = m_ui.vertexTypeCB->findText(val); if (textIndex >= 0) m_ui.vertexTypeCB->setCurrentIndex(textIndex); @@ -115,33 +132,36 @@ void MainWindow::callItemSelected(const QModelIndex &index) m_ui.detailsDock->hide(); m_ui.vertexDataDock->hide(); } - if (m_selectedEvent && !m_selectedEvent->state().isEmpty()) { + if (m_selectedEvent && m_selectedEvent->hasState()) { fillStateForFrame(); } else m_ui.stateDock->hide(); } -void MainWindow::filterTrace() -{ - m_proxyModel->setFilterString(m_filterEdit->text()); -} - void MainWindow::replayStart() { + if (m_trace->isSaving()) { + QMessageBox::warning( + this, + tr("Trace Saving"), + tr("QApiTrace is currently saving the edited trace file. " + "Please wait until it finishes and try again.")); + return; + } QDialog dlg; Ui_RetracerDialog dlgUi; dlgUi.setupUi(&dlg); dlgUi.doubleBufferingCB->setChecked( m_retracer->isDoubleBuffered()); - dlgUi.benchmarkCB->setChecked( - m_retracer->isBenchmarking()); + dlgUi.errorCheckCB->setChecked( + !m_retracer->isBenchmarking()); if (dlg.exec() == QDialog::Accepted) { m_retracer->setDoubleBuffered( dlgUi.doubleBufferingCB->isChecked()); m_retracer->setBenchmarking( - dlgUi.benchmarkCB->isChecked()); + !dlgUi.errorCheckCB->isChecked()); replayTrace(false); } } @@ -156,10 +176,12 @@ void MainWindow::replayStop() void MainWindow::newTraceFile(const QString &fileName) { - m_traceFileName = fileName; + qDebug()<< "Loading : " <setValue(0); m_trace->setFileName(fileName); - if (m_traceFileName.isEmpty()) { + if (fileName.isEmpty()) { m_ui.actionReplay->setEnabled(false); m_ui.actionLookupState->setEnabled(false); setWindowTitle(tr("QApiTrace")); @@ -183,6 +205,11 @@ void MainWindow::replayFinished(const QString &output) statusBar()->showMessage(output); } m_stateEvent = 0; + m_ui.actionShowErrorsDock->setEnabled(m_trace->hasErrors()); + m_ui.errorsDock->setVisible(m_trace->hasErrors()); + if (!m_trace->hasErrors()) + m_ui.errorsTreeWidget->clear(); + statusBar()->showMessage( tr("Replaying finished!"), 2000); } @@ -193,6 +220,7 @@ void MainWindow::replayError(const QString &message) m_ui.actionReplay->setEnabled(true); m_ui.actionLookupState->setEnabled(true); m_stateEvent = 0; + m_nonDefaultsLookupEvent = 0; m_progressBar->hide(); statusBar()->showMessage( @@ -223,24 +251,24 @@ void MainWindow::finishedLoadingTrace() void MainWindow::replayTrace(bool dumpState) { - if (m_traceFileName.isEmpty()) + if (m_trace->fileName().isEmpty()) return; - m_retracer->setFileName(m_traceFileName); + m_retracer->setFileName(m_trace->fileName()); m_retracer->setCaptureState(dumpState); if (m_retracer->captureState() && m_selectedEvent) { int index = 0; if (m_selectedEvent->type() == ApiTraceEvent::Call) { - index = static_cast(m_selectedEvent)->index; + index = static_cast(m_selectedEvent)->index(); } else if (m_selectedEvent->type() == ApiTraceEvent::Frame) { ApiTraceFrame *frame = static_cast(m_selectedEvent); - if (frame->calls.isEmpty()) { + if (frame->isEmpty()) { //XXX i guess we could still get the current state qDebug()<<"tried to get a state for an empty frame"; return; } - index = frame->calls.first()->index; + index = frame->calls().first()->index(); } else { qDebug()<<"Unknown event type"; return; @@ -267,19 +295,32 @@ void MainWindow::lookupState() tr("To inspect the state select an event in the event list.")); return; } + if (m_trace->isSaving()) { + QMessageBox::warning( + this, + tr("Trace Saving"), + tr("QApiTrace is currently saving the edited trace file. " + "Please wait until it finishes and try again.")); + return; + } m_stateEvent = m_selectedEvent; replayTrace(true); } MainWindow::~MainWindow() { + delete m_trace; + m_trace = 0; + + delete m_proxyModel; + delete m_model; } static void variantToString(const QVariant &var, QString &str) { if (var.type() == QVariant::List) { - QVariantList lst = var.toList(); + QVector lst = var.toList().toVector(); str += QLatin1String("["); for (int i = 0; i < lst.count(); ++i) { QVariant val = lst[i]; @@ -297,39 +338,167 @@ 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; - QVariantMap params; + for (itr = map.constBegin(); itr != map.constEnd(); ++itr) { + QString key = itr.key(); + QVariant var = itr.value(); + QVariant defaultVar = defaultMap[key]; - if (!m_selectedEvent || m_selectedEvent->state().isEmpty()) + QTreeWidgetItem *item = variantToItem(key, var, defaultVar); + if (item) { + items.append(item); + } + } +} + +static void +variantListToItems(const QVector &lst, const QVector &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) { + QVector lst = var.toList().toVector(); + 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 = "<setText(1, descr); + QLabel *l = new QLabel(descr, tree); + l->setWordWrap(true); + tree->setItemWidget(item, 1, l); + + item->setData(0, Qt::UserRole, surface.image()); +} + +void MainWindow::fillStateForFrame() +{ + if (!m_selectedEvent || !m_selectedEvent->hasState()) return; - const ApiTraceState &state = m_selectedEvent->state(); - m_ui.stateTreeWidget->clear(); - params = state.parameters(); - QList items; - for (itr = params.constBegin(); itr != params.constEnd(); ++itr) { - QString key = itr.key(); - QString val; + if (m_nonDefaultsLookupEvent) { + m_ui.nonDefaultsCB->blockSignals(true); + m_ui.nonDefaultsCB->setChecked(true); + m_ui.nonDefaultsCB->blockSignals(false); + } - variantToString(itr.value(), 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()); + addSurfaceItem(texture, texture.label(), + textureItem, + m_ui.surfacesTreeWidget); } } 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()); + addSurfaceItem(fbo, fbo.type(), + fboItem, + m_ui.surfacesTreeWidget); } } m_ui.surfacesTab->setEnabled(true); @@ -394,11 +547,9 @@ void MainWindow::fillStateForFrame() 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) @@ -414,12 +565,17 @@ void MainWindow::showSurfacesMenu(const QPoint &pos) 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())); + act = menu.addAction(tr("Save Image")); + act->setStatusTip(tr("Save the currently selected surface")); + connect(act, SIGNAL(triggered()), + SLOT(saveSelectedSurface())); + menu.exec(tree->viewport()->mapToGlobal(pos)); } @@ -432,15 +588,32 @@ void MainWindow::showSelectedSurface() return; QVariant var = item->data(0, Qt::UserRole); - m_imageViewer->setImage(var.value()); - m_imageViewer->show(); - m_imageViewer->raise(); - m_imageViewer->activateWindow(); + QImage img = var.value(); + ImageViewer *viewer = new ImageViewer(this); + + QString title; + if (currentCall()) { + title = tr("QApiTrace - Surface at %1 (%2)") + .arg(currentCall()->name()) + .arg(currentCall()->index()); + } else { + title = tr("QApiTrace - Surface Viewer"); + } + viewer->setWindowTitle(title); + viewer->setAttribute(Qt::WA_DeleteOnClose, true); + viewer->setImage(img); + QRect screenRect = QApplication::desktop()->availableGeometry(); + viewer->resize(qMin(int(0.75 * screenRect.width()), img.width()) + 40, + qMin(int(0.75 * screenRect.height()), img.height()) + 40); + viewer->show(); + viewer->raise(); + viewer->activateWindow(); } void MainWindow::initObjects() { m_ui.stateTreeWidget->sortByColumn(0, Qt::AscendingOrder); + m_ui.uniformsTreeWidget->sortByColumn(0, Qt::AscendingOrder); m_sourcesWidget = new ShadersSourceWidget(m_ui.shadersTab); QVBoxLayout *layout = new QVBoxLayout; @@ -461,53 +634,73 @@ void MainWindow::initObjects() 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->setItemDelegate( + new ApiCallDelegate(m_ui.callView)); 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_ui.callView->setContextMenuPolicy(Qt::CustomContextMenu); m_progressBar = new QProgressBar(); - m_progressBar->setRange(0, 0); + m_progressBar->setRange(0, 100); statusBar()->addPermanentWidget(m_progressBar); m_progressBar->hide(); + m_argsEditor = new ArgumentsEditor(this); + m_ui.detailsDock->hide(); + m_ui.errorsDock->hide(); m_ui.vertexDataDock->hide(); m_ui.stateDock->hide(); setDockOptions(dockOptions() | QMainWindow::ForceTabbedDocks); tabifyDockWidget(m_ui.stateDock, m_ui.vertexDataDock); + tabifyDockWidget(m_ui.detailsDock, m_ui.errorsDock); 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); } void MainWindow::initConnections() { connect(m_trace, SIGNAL(startedLoadingTrace()), this, SLOT(startedLoadingTrace())); + connect(m_trace, SIGNAL(loaded(int)), + this, SLOT(loadProgess(int))); connect(m_trace, SIGNAL(finishedLoadingTrace()), this, SLOT(finishedLoadingTrace())); + connect(m_trace, SIGNAL(startedSaving()), + this, SLOT(slotStartedSaving())); + connect(m_trace, SIGNAL(saved()), + this, SLOT(slotSaved())); + connect(m_trace, SIGNAL(changed(ApiTraceCall*)), + this, SLOT(slotTraceChanged(ApiTraceCall*))); 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_retracer, SIGNAL(foundState(ApiTraceState*)), + this, SLOT(replayStateFound(ApiTraceState*))); + connect(m_retracer, SIGNAL(retraceErrors(const QList&)), + this, SLOT(slotRetraceErrors(const QList&))); connect(m_ui.vertexInterpretButton, SIGNAL(clicked()), m_vdataInterpreter, SLOT(interpretData())); @@ -528,6 +721,15 @@ void MainWindow::initConnections() connect(m_ui.actionQuit, SIGNAL(triggered()), this, SLOT(close())); + connect(m_ui.actionFind, SIGNAL(triggered()), + this, SLOT(slotSearch())); + connect(m_ui.actionGo, SIGNAL(triggered()), + this, SLOT(slotGoTo())); + connect(m_ui.actionGoFrameStart, SIGNAL(triggered()), + this, SLOT(slotGoFrameStart())); + connect(m_ui.actionGoFrameEnd, SIGNAL(triggered()), + this, SLOT(slotGoFrameEnd())); + connect(m_ui.actionReplay, SIGNAL(triggered()), this, SLOT(replayStart())); connect(m_ui.actionStop, SIGNAL(triggered()), @@ -539,8 +741,8 @@ void MainWindow::initConnections() connect(m_ui.callView, SIGNAL(activated(const QModelIndex &)), this, SLOT(callItemSelected(const QModelIndex &))); - connect(m_filterEdit, SIGNAL(returnPressed()), - this, SLOT(filterTrace())); + connect(m_ui.callView, SIGNAL(customContextMenuRequested(QPoint)), + this, SLOT(customContextMenuRequested(QPoint))); connect(m_ui.surfacesTreeWidget, SIGNAL(customContextMenuRequested(const QPoint &)), @@ -551,17 +753,417 @@ void MainWindow::initConnections() 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&))); + + connect(m_ui.errorsDock, SIGNAL(visibilityChanged(bool)), + m_ui.actionShowErrorsDock, SLOT(setChecked(bool))); + connect(m_ui.actionShowErrorsDock, SIGNAL(triggered(bool)), + m_ui.errorsDock, SLOT(setVisible(bool))); + connect(m_ui.errorsTreeWidget, + SIGNAL(currentItemChanged(QTreeWidgetItem*, QTreeWidgetItem*)), + this, SLOT(slotErrorSelected(QTreeWidgetItem*))); } -void MainWindow::replayStateFound(const ApiTraceState &state) +void MainWindow::replayStateFound(ApiTraceState *state) { m_stateEvent->setState(state); m_model->stateSetOnEvent(m_stateEvent); - if (m_selectedEvent == m_stateEvent) { + if (m_selectedEvent == m_stateEvent || + m_nonDefaultsLookupEvent == m_selectedEvent) { fillStateForFrame(); } else { m_ui.stateDock->hide(); } + m_nonDefaultsLookupEvent = 0; +} + +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->call(0); + } + + if (!call) { + m_searchWidget->setFound(false); + return; + } + const QVector &calls = m_trace->calls(); + int callNum = calls.indexOf(call); + + for (int i = callNum + 1; i < calls.count(); ++i) { + ApiTraceCall *testCall = calls[i]; + 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()) { + QString txt = testCall->searchText(); + if (txt.contains(str, sensitivity)) { + 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->call(0); + } + + if (!call) { + m_searchWidget->setFound(false); + return; + } + const QVector &calls = m_trace->calls(); + int callNum = calls.indexOf(call); + + for (int i = callNum - 1; i >= 0; --i) { + ApiTraceCall *testCall = calls[i]; + 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()) { + QString txt = testCall->searchText(); + if (txt.contains(str, sensitivity)) { + 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); + ApiTraceFrame *firstFrame = + m_trace->frameAt(0); + ApiTraceEvent *oldSelected = m_selectedEvent; + if (!firstFrame) + return; + m_nonDefaultsLookupEvent = m_selectedEvent; + m_selectedEvent = firstFrame; + lookupState(); + m_selectedEvent = oldSelected; + } + } + fillStateForFrame(); +} + +void MainWindow::customContextMenuRequested(QPoint pos) +{ + QMenu menu; + QModelIndex index = m_ui.callView->indexAt(pos); + + callItemSelected(index); + if (!index.isValid()) + return; + + ApiTraceEvent *event = + index.data(ApiTraceModel::EventRole).value(); + if (!event) + return; + + menu.addAction(QIcon(":/resources/media-record.png"), + tr("Lookup state"), this, SLOT(lookupState())); + if (event->type() == ApiTraceEvent::Call) { + menu.addAction(tr("Edit"), this, SLOT(editCall())); + } + + menu.exec(QCursor::pos()); +} + +void MainWindow::editCall() +{ + if (m_selectedEvent && m_selectedEvent->type() == ApiTraceEvent::Call) { + ApiTraceCall *call = static_cast(m_selectedEvent); + m_argsEditor->setCall(call); + m_argsEditor->show(); + } +} + +void MainWindow::slotStartedSaving() +{ + m_progressBar->show(); + statusBar()->showMessage( + tr("Saving to %1").arg(m_trace->fileName())); +} + +void MainWindow::slotSaved() +{ + statusBar()->showMessage( + tr("Saved to %1").arg(m_trace->fileName()), 2000); + m_progressBar->hide(); +} + +void MainWindow::slotGoFrameStart() +{ + ApiTraceFrame *frame = currentFrame(); + if (!frame || frame->isEmpty()) { + return; + } + + QVector::const_iterator itr; + QVector calls = frame->calls(); + + itr = calls.constBegin(); + while (itr != calls.constEnd()) { + ApiTraceCall *call = *itr; + QModelIndex idx = m_proxyModel->indexForCall(call); + if (idx.isValid()) { + m_ui.callView->setCurrentIndex(idx); + break; + } + ++itr; + } +} + +void MainWindow::slotGoFrameEnd() +{ + ApiTraceFrame *frame = currentFrame(); + if (!frame || frame->isEmpty()) { + return; + } + QVector::const_iterator itr; + QVector calls = frame->calls(); + + itr = calls.constEnd(); + do { + --itr; + ApiTraceCall *call = *itr; + QModelIndex idx = m_proxyModel->indexForCall(call); + if (idx.isValid()) { + m_ui.callView->setCurrentIndex(idx); + break; + } + } while (itr != calls.constBegin()); +} + +ApiTraceFrame * MainWindow::currentFrame() const +{ + if (m_selectedEvent) { + if (m_selectedEvent->type() == ApiTraceEvent::Frame) { + return static_cast(m_selectedEvent); + } else { + Q_ASSERT(m_selectedEvent->type() == ApiTraceEvent::Call); + ApiTraceCall *call = static_cast(m_selectedEvent); + return call->parentFrame(); + } + } + return NULL; +} + +void MainWindow::slotTraceChanged(ApiTraceCall *call) +{ + Q_ASSERT(call); + if (call == m_selectedEvent) { + m_ui.detailsWebView->setHtml(call->toHtml()); + } +} + +void MainWindow::slotRetraceErrors(const QList &errors) +{ + m_ui.errorsTreeWidget->clear(); + + foreach(RetraceError error, errors) { + ApiTraceCall *call = m_trace->callWithIndex(error.callIndex); + if (!call) + continue; + call->setError(error.message); + + QTreeWidgetItem *item = + new QTreeWidgetItem(m_ui.errorsTreeWidget); + item->setData(0, Qt::DisplayRole, error.callIndex); + item->setData(0, Qt::UserRole, QVariant::fromValue(call)); + QString type = error.type; + type[0] = type[0].toUpper(); + item->setData(1, Qt::DisplayRole, type); + item->setData(2, Qt::DisplayRole, error.message); + } +} + +void MainWindow::slotErrorSelected(QTreeWidgetItem *current) +{ + if (current) { + ApiTraceCall *call = + current->data(0, Qt::UserRole).value(); + Q_ASSERT(call); + QModelIndex index = m_proxyModel->indexForCall(call); + if (index.isValid()) { + m_ui.callView->setCurrentIndex(index); + } else { + statusBar()->showMessage(tr("Call has been filtered out.")); + } + } +} + +ApiTraceCall * MainWindow::currentCall() const +{ + if (m_selectedEvent && + m_selectedEvent->type() == ApiTraceEvent::Call) { + return static_cast(m_selectedEvent); + } + return NULL; +} + +void MainWindow::saveSelectedSurface() +{ + QTreeWidgetItem *item = + m_ui.surfacesTreeWidget->currentItem(); + + if (!item || !m_trace) + return; + + QVariant var = item->data(0, Qt::UserRole); + QImage img = var.value(); + + QString imageIndex; + if (currentCall()) { + imageIndex = tr("_call_%1") + .arg(currentCall()->index()); + } else if (currentFrame()) { + ApiTraceCall *firstCall = currentFrame()->call(0); + if (firstCall) { + imageIndex = tr("_frame_%1") + .arg(firstCall->index()); + } else { + qDebug()<<"unknown frame number"; + imageIndex = tr("_frame_%1") + .arg(firstCall->index()); + } + } + + //which of the surfaces are we saving + QTreeWidgetItem *parent = item->parent(); + int parentIndex = + m_ui.surfacesTreeWidget->indexOfTopLevelItem(parent); + if (parentIndex < 0) { + parentIndex = 0; + } + int childIndex = 0; + if (parent) { + childIndex = parent->indexOfChild(item); + } else { + childIndex = m_ui.surfacesTreeWidget->indexOfTopLevelItem(item); + } + + + QString fileName = + tr("%1%2-%3_%4.png") + .arg(m_trace->fileName()) + .arg(imageIndex) + .arg(parentIndex) + .arg(childIndex); + //qDebug()<<"save "<showMessage( tr("Saved '%1'").arg(fileName), 5000); +} + +void MainWindow::loadProgess(int percent) +{ + m_progressBar->setValue(percent); } #include "mainwindow.moc"