]> git.cworth.org Git - apitrace/blobdiff - gui/mainwindow.cpp
Implement goto start of the frame and goto end of the frame.
[apitrace] / gui / mainwindow.cpp
index b5d20b1b2684e8258107e7f3e2b25dde62945259..7d4cab8f7e064b5d9d6baa4476b2cdb19a345782 100644 (file)
@@ -104,7 +104,7 @@ void MainWindow::callItemSelected(const QModelIndex &index)
             QByteArray data =
                 call->arguments()[call->binaryDataIndex()].toByteArray();
             m_vdataInterpreter->setData(data);
-            QVariantList args = call->arguments();
+            QVector<QVariant> args = call->arguments();
 
             for (int i = 0; i < call->argNames().count(); ++i) {
                 QString name = call->argNames()[i];
@@ -132,7 +132,7 @@ 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();
@@ -320,7 +320,7 @@ static void
 variantToString(const QVariant &var, QString &str)
 {
     if (var.type() == QVariant::List) {
-        QVariantList lst = var.toList();
+        QVector<QVariant> lst = var.toList().toVector();
         str += QLatin1String("[");
         for (int i = 0; i < lst.count(); ++i) {
             QVariant val = lst[i];
@@ -358,7 +358,8 @@ variantMapToItems(const QVariantMap &map, const QVariantMap &defaultMap, QList<Q
 }
 
 static void
-variantListToItems(const QVariantList &lst, const QVariantList &defaultLst, QList<QTreeWidgetItem *> &items)
+variantListToItems(const QVector<QVariant> &lst, const QVector<QVariant> &defaultLst,
+                   QList<QTreeWidgetItem *> &items)
 {
     for (int i = 0; i < lst.count(); ++i) {
         QString key = QString::number(i);
@@ -380,7 +381,7 @@ static bool
 isVariantDeep(const QVariant &var)
 {
     if (var.type() == QVariant::List) {
-        QVariantList lst = var.toList();
+        QVector<QVariant> lst = var.toList().toVector();
         for (int i = 0; i < lst.count(); ++i) {
             if (isVariantDeep(lst[i])) {
                 return true;
@@ -426,8 +427,8 @@ variantToItem(const QString &key, const QVariant &var, const QVariant &defaultVa
             variantMapToItems(map, defaultMap, children);
         }
         if (var.type() == QVariant::List) {
-            QVariantList lst = var.toList();
-            QVariantList defaultLst = defaultVar.toList();
+            QVector<QVariant> lst = var.toList().toVector();
+            QVector<QVariant> defaultLst = defaultVar.toList().toVector();
             variantListToItems(lst, defaultLst, children);
         }
         item->addChildren(children);
@@ -464,9 +465,7 @@ static void addSurfaceItem(const ApiSurface &surface,
 
 void MainWindow::fillStateForFrame()
 {
-    QVariantMap params;
-
-    if (!m_selectedEvent || m_selectedEvent->state().isEmpty())
+    if (!m_selectedEvent || !m_selectedEvent->hasState())
         return;
 
     if (m_nonDefaultsLookupEvent) {
@@ -482,11 +481,10 @@ void MainWindow::fillStateForFrame()
         defaultParams = defaultState.parameters();
     }
 
-    const ApiTraceState &state = m_selectedEvent->state();
+    const ApiTraceState &state = *m_selectedEvent->state();
     m_ui.stateTreeWidget->clear();
-    params = state.parameters();
     QList<QTreeWidgetItem *> items;
-    variantMapToItems(params, defaultParams, items);
+    variantMapToItems(state.parameters(), defaultParams, items);
     m_ui.stateTreeWidget->insertTopLevelItems(0, items);
 
     QMap<QString, QString> shaderSources = state.shaderSources();
@@ -496,6 +494,11 @@ void MainWindow::fillStateForFrame()
         m_sourcesWidget->setShaders(shaderSources);
     }
 
+    m_ui.uniformsTreeWidget->clear();
+    QList<QTreeWidgetItem *> uniformsItems;
+    variantMapToItems(state.uniforms(), QVariantMap(), uniformsItems);
+    m_ui.uniformsTreeWidget->insertTopLevelItems(0, uniformsItems);
+
     const QList<ApiTexture> &textures =
         state.textures();
     const QList<ApiFramebuffer> &fbos =
@@ -562,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));
 }
 
@@ -584,10 +592,10 @@ void MainWindow::showSelectedSurface()
     ImageViewer *viewer = new ImageViewer(this);
 
     QString title;
-    if (currentCall()) {
+    if (selectedCall()) {
         title = tr("QApiTrace - Surface at %1 (%2)")
-                .arg(currentCall()->name())
-                .arg(currentCall()->index());
+                .arg(selectedCall()->name())
+                .arg(selectedCall()->index());
     } else {
         title = tr("QApiTrace - Surface Viewer");
     }
@@ -605,6 +613,7 @@ void MainWindow::showSelectedSurface()
 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;
@@ -638,7 +647,7 @@ void MainWindow::initObjects()
     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();
 
@@ -673,6 +682,8 @@ 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()),
@@ -681,13 +692,19 @@ void MainWindow::initConnections()
             this, SLOT(slotSaved()));
     connect(m_trace, SIGNAL(changed(ApiTraceCall*)),
             this, SLOT(slotTraceChanged(ApiTraceCall*)));
+    connect(m_trace, SIGNAL(findResult(ApiTrace::SearchResult,ApiTraceCall*)),
+            this, SLOT(slotSearchResult(ApiTrace::SearchResult,ApiTraceCall*)));
+    connect(m_trace, SIGNAL(foundFrameStart(ApiTraceFrame*)),
+            this, SLOT(slotFoundFrameStart(ApiTraceFrame*)));
+    connect(m_trace, SIGNAL(foundFrameEnd(ApiTraceFrame*)),
+            this, SLOT(slotFoundFrameEnd(ApiTraceFrame*)));
 
     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<RetraceError>&)),
             this, SLOT(slotRetraceErrors(const QList<RetraceError>&)));
 
@@ -770,7 +787,7 @@ void MainWindow::initConnections()
             this, SLOT(slotErrorSelected(QTreeWidgetItem*)));
 }
 
-void MainWindow::replayStateFound(const ApiTraceState &state)
+void MainWindow::replayStateFound(ApiTraceState *state)
 {
     m_stateEvent->setState(state);
     m_model->stateSetOnEvent(m_stateEvent);
@@ -820,103 +837,31 @@ void MainWindow::slotSearch()
 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<ApiTraceEvent*>();
-    ApiTraceCall *call = 0;
+    ApiTraceCall *call = currentCall();
+    ApiTraceFrame *frame = currentFrame();
 
-    if (event->type() == ApiTraceCall::Call)
-        call = static_cast<ApiTraceCall*>(event);
-    else {
-        Q_ASSERT(event->type() == ApiTraceCall::Frame);
-        ApiTraceFrame *frame = static_cast<ApiTraceFrame*>(event);
-        call = frame->call(0);
+    Q_ASSERT(call || frame);
+    if (!frame) {
+        frame = call->parentFrame();
     }
+    Q_ASSERT(frame);
 
-    if (!call) {
-        m_searchWidget->setFound(false);
-        return;
-    }
-    const QList<ApiTraceCall*> &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->filterText();
-            if (txt.contains(str, sensitivity)) {
-                m_ui.callView->setCurrentIndex(index);
-                m_searchWidget->setFound(true);
-                return;
-            }
-        }
-    }
-    m_searchWidget->setFound(false);
+    m_trace->findNext(frame, call, str, sensitivity);
 }
 
 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<ApiTraceEvent*>();
-    ApiTraceCall *call = 0;
+    ApiTraceCall *call = currentCall();
+    ApiTraceFrame *frame = currentFrame();
 
-    if (event->type() == ApiTraceCall::Call)
-        call = static_cast<ApiTraceCall*>(event);
-    else {
-        Q_ASSERT(event->type() == ApiTraceCall::Frame);
-        ApiTraceFrame *frame = static_cast<ApiTraceFrame*>(event);
-        call = frame->call(0);
+    Q_ASSERT(call || frame);
+    if (!frame) {
+        frame = call->parentFrame();
     }
+    Q_ASSERT(frame);
 
-    if (!call) {
-        m_searchWidget->setFound(false);
-        return;
-    }
-    const QList<ApiTraceCall*> &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->filterText();
-            if (txt.contains(str, sensitivity)) {
-                m_ui.callView->setCurrentIndex(index);
-                m_searchWidget->setFound(true);
-                return;
-            }
-        }
-    }
-    m_searchWidget->setFound(false);
+    m_trace->findPrev(frame, call, str, sensitivity);
 }
 
 void MainWindow::fillState(bool nonDefaults)
@@ -927,17 +872,6 @@ void MainWindow::fillState(bool nonDefaults)
             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;
@@ -963,12 +897,14 @@ void MainWindow::customContextMenuRequested(QPoint pos)
 
     ApiTraceEvent *event =
         index.data(ApiTraceModel::EventRole).value<ApiTraceEvent*>();
-    if (!event || event->type() != ApiTraceEvent::Call)
+    if (!event)
         return;
 
     menu.addAction(QIcon(":/resources/media-record.png"),
                    tr("Lookup state"), this, SLOT(lookupState()));
-    menu.addAction(tr("Edit"), this, SLOT(editCall()));
+    if (event->type() == ApiTraceEvent::Call) {
+        menu.addAction(tr("Edit"), this, SLOT(editCall()));
+    }
 
     menu.exec(QCursor::pos());
 }
@@ -999,47 +935,28 @@ void MainWindow::slotSaved()
 void MainWindow::slotGoFrameStart()
 {
     ApiTraceFrame *frame = currentFrame();
-    if (!frame || frame->isEmpty()) {
-        return;
-    }
-
-    QList<ApiTraceCall*>::const_iterator itr;
-    QList<ApiTraceCall*> calls = frame->calls();
+    ApiTraceCall *call = currentCall();
 
-    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;
+    if (!frame && call) {
+        frame = call->parentFrame();
     }
+
+    m_trace->findFrameStart(frame);
 }
 
 void MainWindow::slotGoFrameEnd()
 {
     ApiTraceFrame *frame = currentFrame();
-    if (!frame || frame->isEmpty()) {
-        return;
+    ApiTraceCall *call = currentCall();
+
+    if (!frame && call) {
+        frame = call->parentFrame();
     }
-    QList<ApiTraceCall*>::const_iterator itr;
-    QList<ApiTraceCall*> 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());
+    m_trace->findFrameEnd(frame);
 }
 
-ApiTraceFrame * MainWindow::currentFrame() const
+ApiTraceFrame * MainWindow::selectedFrame() const
 {
     if (m_selectedEvent) {
         if (m_selectedEvent->type() == ApiTraceEvent::Frame) {
@@ -1097,7 +1014,7 @@ void MainWindow::slotErrorSelected(QTreeWidgetItem *current)
     }
 }
 
-ApiTraceCall * MainWindow::currentCall() const
+ApiTraceCall * MainWindow::selectedCall() const
 {
     if (m_selectedEvent &&
         m_selectedEvent->type() == ApiTraceEvent::Call) {
@@ -1106,4 +1023,178 @@ ApiTraceCall * MainWindow::currentCall() const
     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<QImage>();
+
+    QString imageIndex;
+    if (selectedCall()) {
+        imageIndex = tr("_call_%1")
+                     .arg(selectedCall()->index());
+    } else if (selectedFrame()) {
+        ApiTraceCall *firstCall = selectedFrame()->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 "<<fileName;
+    img.save(fileName, "PNG");
+    statusBar()->showMessage( tr("Saved '%1'").arg(fileName), 5000);
+}
+
+void MainWindow::loadProgess(int percent)
+{
+    m_progressBar->setValue(percent);
+}
+
+void MainWindow::slotSearchResult(ApiTrace::SearchResult result,
+                                  ApiTraceCall *call)
+{
+    switch (result) {
+    case ApiTrace::SearchNotFound:
+        m_searchWidget->setFound(false);
+        break;
+    case ApiTrace::SearchFound: {
+        QModelIndex index = m_proxyModel->indexForCall(call);
+        m_ui.callView->setCurrentIndex(index);
+        m_searchWidget->setFound(true);
+    }
+        break;
+    case ApiTrace::SearchWrapped:
+        m_searchWidget->setFound(false);
+        break;
+    }
+}
+
+ApiTraceFrame * MainWindow::currentFrame() const
+{
+    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";
+            return 0;
+        }
+    }
+
+    event = index.data(ApiTraceModel::EventRole).value<ApiTraceEvent*>();
+    Q_ASSERT(event);
+    if (!event) {
+        return 0;
+    }
+
+    ApiTraceFrame *frame = 0;
+    if (event->type() == ApiTraceCall::Frame) {
+        frame = static_cast<ApiTraceFrame*>(event);
+    }
+    return frame;
+}
+
+ApiTraceCall * MainWindow::currentCall() const
+{
+    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";
+            return 0;
+        }
+    }
+
+    event = index.data(ApiTraceModel::EventRole).value<ApiTraceEvent*>();
+    Q_ASSERT(event);
+    if (!event) {
+        return 0;
+    }
+
+    ApiTraceCall *call = 0;
+    if (event->type() == ApiTraceCall::Call) {
+        call = static_cast<ApiTraceCall*>(event);
+    }
+
+    return call;
+
+}
+
+void MainWindow::slotFoundFrameStart(ApiTraceFrame *frame)
+{
+    Q_ASSERT(frame->loaded());
+    if (!frame || frame->isEmpty()) {
+        return;
+    }
+
+    QVector<ApiTraceCall*>::const_iterator itr;
+    QVector<ApiTraceCall*> 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::slotFoundFrameEnd(ApiTraceFrame *frame)
+{
+    Q_ASSERT(frame->loaded());
+    if (!frame || frame->isEmpty()) {
+        return;
+    }
+    QVector<ApiTraceCall*>::const_iterator itr;
+    QVector<ApiTraceCall*> 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());
+}
+
 #include "mainwindow.moc"