diff options
-rw-r--r-- | gui/apitrace.cpp | 101 | ||||
-rw-r--r-- | gui/apitrace.h | 32 | ||||
-rw-r--r-- | gui/apitracecall.cpp | 52 | ||||
-rw-r--r-- | gui/apitracecall.h | 11 | ||||
-rw-r--r-- | gui/main.cpp | 8 | ||||
-rw-r--r-- | gui/mainwindow.cpp | 197 | ||||
-rw-r--r-- | gui/mainwindow.h | 12 | ||||
-rw-r--r-- | gui/traceloader.cpp | 167 | ||||
-rw-r--r-- | gui/traceloader.h | 18 |
9 files changed, 452 insertions, 146 deletions
diff --git a/gui/apitrace.cpp b/gui/apitrace.cpp index 958009b7..bff1686a 100644 --- a/gui/apitrace.cpp +++ b/gui/apitrace.cpp @@ -19,10 +19,21 @@ ApiTrace::ApiTrace() m_loader, SLOT(loadFrame(ApiTraceFrame*))); connect(m_loader, SIGNAL(framesLoaded(const QList<ApiTraceFrame*>)), this, SLOT(addFrames(const QList<ApiTraceFrame*>))); - connect(m_loader, SIGNAL(frameLoaded(ApiTraceFrame*)), - this, SLOT(frameLoadFinished(ApiTraceFrame*))); + connect(m_loader, + SIGNAL(frameContentsLoaded(ApiTraceFrame*,QVector<ApiTraceCall*>,quint64)), + this, + SLOT(loaderFrameLoaded(ApiTraceFrame*,QVector<ApiTraceCall*>,quint64))); connect(m_loader, SIGNAL(finishedParsing()), this, SLOT(finishedParsing())); + connect(this, SIGNAL(loaderSearchNext(int,QString,Qt::CaseSensitivity)), + m_loader, SLOT(searchNext(int,QString,Qt::CaseSensitivity))); + connect(this, SIGNAL(loaderSearchPrev(int,QString,Qt::CaseSensitivity)), + m_loader, SLOT(searchPrev(int,QString,Qt::CaseSensitivity))); + connect(m_loader, + SIGNAL(searchResult(ApiTrace::SearchResult,ApiTraceCall*)), + this, + SLOT(loaderSearchResult(ApiTrace::SearchResult,ApiTraceCall*))); + connect(m_loader, SIGNAL(startedParsing()), this, SIGNAL(startedLoadingTrace())); @@ -306,7 +317,6 @@ bool ApiTrace::hasErrors() const void ApiTrace::loadFrame(ApiTraceFrame *frame) { Q_ASSERT(!frame->loaded()); - emit beginLoadingFrame(frame, frame->numChildrenToLoad()); emit requestFrame(frame); } @@ -318,9 +328,92 @@ void ApiTrace::finishedParsing() } } -void ApiTrace::frameLoadFinished(ApiTraceFrame *frame) +void ApiTrace::loaderFrameLoaded(ApiTraceFrame *frame, + const QVector<ApiTraceCall*> &calls, + quint64 binaryDataSize) { + Q_ASSERT(frame->numChildrenToLoad() == calls.size()); + emit beginLoadingFrame(frame, calls.size()); + frame->setCalls(calls, binaryDataSize); emit endLoadingFrame(frame); } +void ApiTrace::findNext(ApiTraceFrame *frame, + ApiTraceCall *from, + const QString &str, + Qt::CaseSensitivity sensitivity) +{ + ApiTraceCall *foundCall = 0; + int frameIdx = m_frames.indexOf(frame); + + if (frame->loaded()) { + foundCall = frame->findNextCall(from, str, sensitivity); + if (foundCall) { + emit findResult(SearchFound, foundCall); + return; + } + + //if the frame is loaded we already searched it above + // so skip it + frameIdx += 1; + } + + for (int i = frameIdx; i < m_frames.count(); ++i) { + ApiTraceFrame *frame = m_frames[i]; + if (!frame->loaded()) { + emit loaderSearchNext(i, str, sensitivity); + return; + } else { + ApiTraceCall *call = frame->findNextCall(0, str, sensitivity); + if (call) { + emit findResult(SearchFound, call); + } + } + } + emit findResult(SearchWrapped, 0); +} + +void ApiTrace::findPrev(ApiTraceFrame *frame, + ApiTraceCall *from, + const QString &str, + Qt::CaseSensitivity sensitivity) +{ + ApiTraceCall *foundCall = 0; + int frameIdx = m_frames.indexOf(frame); + + if (frame->loaded()) { + foundCall = frame->findPrevCall(from, str, sensitivity); + if (foundCall) { + emit findResult(SearchFound, foundCall); + return; + } + + //if the frame is loaded we already searched it above + // so skip it + frameIdx -= 1; + } + + for (int i = frameIdx; i <= 0; --i) { + ApiTraceFrame *frame = m_frames[i]; + if (!frame->loaded()) { + emit loaderSearchPrev(i, str, sensitivity); + return; + } else { + ApiTraceCall *call = frame->findPrevCall(0, str, sensitivity); + if (call) { + emit findResult(SearchFound, call); + } + } + } + emit findResult(SearchWrapped, 0); +} + +void ApiTrace::loaderSearchResult(ApiTrace::SearchResult result, + ApiTraceCall *call) +{ + //qDebug()<<"Search result = "<<result + // <<", call is = "<<call; + emit findResult(result, call); +} + #include "apitrace.moc" diff --git a/gui/apitrace.h b/gui/apitrace.h index d01e7a0c..3edffef7 100644 --- a/gui/apitrace.h +++ b/gui/apitrace.h @@ -20,6 +20,12 @@ public: FrameMarker_Finish, FrameMarker_Clear }; + enum SearchResult { + SearchNotFound, + SearchFound, + SearchWrapped + }; + static bool isCallAFrameMarker(const ApiTraceCall *call, FrameMarker marker); public: @@ -59,6 +65,15 @@ public slots: void setFrameMarker(FrameMarker marker); void save(); void loadFrame(ApiTraceFrame *frame); + void findNext(ApiTraceFrame *frame, + ApiTraceCall *call, + const QString &str, + Qt::CaseSensitivity sensitivity); + void findPrev(ApiTraceFrame *frame, + ApiTraceCall *call, + const QString &str, + Qt::CaseSensitivity sensitivity); + signals: void loadTrace(const QString &name); @@ -71,6 +86,8 @@ signals: void changed(ApiTraceCall *call); void startedSaving(); void saved(); + void findResult(ApiTrace::SearchResult result, + ApiTraceCall *call); void beginAddingFrames(int oldCount, int numAdded); void endAddingFrames(); @@ -78,11 +95,24 @@ signals: void beginLoadingFrame(ApiTraceFrame *frame, int numAdded); void endLoadingFrame(ApiTraceFrame *frame); + +signals: + void loaderSearchNext(int startFrame, + const QString &str, + Qt::CaseSensitivity sensitivity); + void loaderSearchPrev(int startFrame, + const QString &str, + Qt::CaseSensitivity sensitivity); + private slots: void addFrames(const QList<ApiTraceFrame*> &frames); void slotSaved(); void finishedParsing(); - void frameLoadFinished(ApiTraceFrame *frame); + void loaderFrameLoaded(ApiTraceFrame *frame, + const QVector<ApiTraceCall*> &calls, + quint64 binaryDataSize); + void loaderSearchResult(ApiTrace::SearchResult result, + ApiTraceCall *call); private: void detectFrames(); diff --git a/gui/apitracecall.cpp b/gui/apitracecall.cpp index 59250452..b26514dd 100644 --- a/gui/apitracecall.cpp +++ b/gui/apitracecall.cpp @@ -919,6 +919,14 @@ int ApiTraceCall::numChildren() const return 0; } +bool ApiTraceCall::contains(const QString &str, + Qt::CaseSensitivity sensitivity) const +{ + QString txt = searchText(); + return txt.contains(str, sensitivity); +} + + ApiTraceFrame::ApiTraceFrame(ApiTrace *parentTrace) : ApiTraceEvent(ApiTraceEvent::Frame), m_parentTrace(parentTrace), @@ -1044,3 +1052,47 @@ int ApiTraceFrame::numChildrenToLoad() const { return m_callsToLoad; } + +ApiTraceCall * +ApiTraceFrame::findNextCall(ApiTraceCall *from, + const QString &str, + Qt::CaseSensitivity sensitivity) const +{ + Q_ASSERT(m_loaded); + + int callIndex = 0; + + if (from) { + callIndex = m_calls.indexOf(from) + 1; + } + + for (int i = callIndex; i < m_calls.count(); ++i) { + ApiTraceCall *call = m_calls[i]; + if (call->contains(str, sensitivity)) { + return call; + } + } + return 0; +} + +ApiTraceCall * +ApiTraceFrame::findPrevCall(ApiTraceCall *from, + const QString &str, + Qt::CaseSensitivity sensitivity) const +{ + Q_ASSERT(m_loaded); + + int callIndex = m_calls.count() - 1; + + if (from) { + callIndex = m_calls.indexOf(from) - 1; + } + + for (int i = callIndex; i >= 0; --i) { + ApiTraceCall *call = m_calls[i]; + if (call->contains(str, sensitivity)) { + return call; + } + } + return 0; +} diff --git a/gui/apitracecall.h b/gui/apitracecall.h index ca4c3543..adfa1b05 100644 --- a/gui/apitracecall.h +++ b/gui/apitracecall.h @@ -259,6 +259,9 @@ public: QVector<QVariant> editedValues() const; void revert(); + bool contains(const QString &str, + Qt::CaseSensitivity sensitivity) const; + ApiTrace *parentTrace() const; QString toHtml() const; @@ -306,6 +309,14 @@ public: void setCalls(const QVector<ApiTraceCall*> &calls, quint64 binaryDataSize); + ApiTraceCall *findNextCall(ApiTraceCall *from, + const QString &str, + Qt::CaseSensitivity sensitivity) const; + + ApiTraceCall *findPrevCall(ApiTraceCall *from, + const QString &str, + Qt::CaseSensitivity sensitivity) const; + int binaryDataSize() const; bool loaded() const; diff --git a/gui/main.cpp b/gui/main.cpp index 3f8cfa6b..6043b750 100644 --- a/gui/main.cpp +++ b/gui/main.cpp @@ -1,5 +1,6 @@ #include "mainwindow.h" +#include "apitrace.h" #include "apitracecall.h" #include <QApplication> @@ -7,13 +8,20 @@ #include <QVariant> Q_DECLARE_METATYPE(QList<ApiTraceFrame*>); +Q_DECLARE_METATYPE(QVector<ApiTraceCall*>); +Q_DECLARE_METATYPE(Qt::CaseSensitivity); +Q_DECLARE_METATYPE(ApiTrace::SearchResult); + int main(int argc, char **argv) { QApplication app(argc, argv); qRegisterMetaType<QList<ApiTraceFrame*> >(); + qRegisterMetaType<QVector<ApiTraceCall*> >(); qRegisterMetaType<ApiTraceState>(); + qRegisterMetaType<Qt::CaseSensitivity>(); + qRegisterMetaType<ApiTrace::SearchResult>(); MainWindow window; window.show(); diff --git a/gui/mainwindow.cpp b/gui/mainwindow.cpp index e5f6d9b2..9dc530db 100644 --- a/gui/mainwindow.cpp +++ b/gui/mainwindow.cpp @@ -592,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"); } @@ -692,6 +692,8 @@ 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_retracer, SIGNAL(finished(const QString&)), this, SLOT(replayFinished(const QString&))); @@ -831,103 +833,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 QVector<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->searchText(); - 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; - + ApiTraceCall *call = currentCall(); + ApiTraceFrame *frame = currentFrame(); - if (!index.isValid()) { - index = m_proxyModel->index(0, 0, QModelIndex()); - if (!index.isValid()) { - qDebug()<<"no currently valid index"; - m_searchWidget->setFound(false); - return; - } + Q_ASSERT(call || frame); + if (!frame) { + frame = call->parentFrame(); } + Q_ASSERT(frame); - event = index.data(ApiTraceModel::EventRole).value<ApiTraceEvent*>(); - ApiTraceCall *call = 0; - - 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); - } - - if (!call) { - m_searchWidget->setFound(false); - return; - } - const QVector<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->searchText(); - 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) @@ -1000,7 +930,7 @@ void MainWindow::slotSaved() void MainWindow::slotGoFrameStart() { - ApiTraceFrame *frame = currentFrame(); + ApiTraceFrame *frame = selectedFrame(); if (!frame || frame->isEmpty()) { return; } @@ -1022,7 +952,7 @@ void MainWindow::slotGoFrameStart() void MainWindow::slotGoFrameEnd() { - ApiTraceFrame *frame = currentFrame(); + ApiTraceFrame *frame = selectedFrame(); if (!frame || frame->isEmpty()) { return; } @@ -1041,7 +971,7 @@ void MainWindow::slotGoFrameEnd() } while (itr != calls.constBegin()); } -ApiTraceFrame * MainWindow::currentFrame() const +ApiTraceFrame * MainWindow::selectedFrame() const { if (m_selectedEvent) { if (m_selectedEvent->type() == ApiTraceEvent::Frame) { @@ -1099,7 +1029,7 @@ void MainWindow::slotErrorSelected(QTreeWidgetItem *current) } } -ApiTraceCall * MainWindow::currentCall() const +ApiTraceCall * MainWindow::selectedCall() const { if (m_selectedEvent && m_selectedEvent->type() == ApiTraceEvent::Call) { @@ -1120,11 +1050,11 @@ void MainWindow::saveSelectedSurface() QImage img = var.value<QImage>(); QString imageIndex; - if (currentCall()) { + if (selectedCall()) { imageIndex = tr("_call_%1") - .arg(currentCall()->index()); - } else if (currentFrame()) { - ApiTraceCall *firstCall = currentFrame()->call(0); + .arg(selectedCall()->index()); + } else if (selectedFrame()) { + ApiTraceCall *firstCall = selectedFrame()->call(0); if (firstCall) { imageIndex = tr("_frame_%1") .arg(firstCall->index()); @@ -1166,4 +1096,77 @@ 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; + +} + #include "mainwindow.moc" diff --git a/gui/mainwindow.h b/gui/mainwindow.h index 00fe04b2..e5b19b44 100644 --- a/gui/mainwindow.h +++ b/gui/mainwindow.h @@ -3,6 +3,8 @@ #include "ui_mainwindow.h" +#include "apitrace.h" + #include <QMainWindow> #include <QProcess> @@ -71,6 +73,8 @@ private slots: void slotTraceChanged(ApiTraceCall *call); void slotRetraceErrors(const QList<RetraceError> &errors); void slotErrorSelected(QTreeWidgetItem *current); + void slotSearchResult(ApiTrace::SearchResult result, + ApiTraceCall *call); private: void initObjects(); @@ -78,9 +82,17 @@ private: void newTraceFile(const QString &fileName); void replayTrace(bool dumpState); void fillStateForFrame(); + + /* there's a difference between selected frame/call and + * current call/frame. the former implies actual selection + * the latter might be just a highlight, e.g. during searching + */ + ApiTraceFrame *selectedFrame() const; + ApiTraceCall *selectedCall() const; ApiTraceFrame *currentFrame() const; ApiTraceCall *currentCall() const; + private: Ui_MainWindow m_ui; ShadersSourceWidget *m_sourcesWidget; diff --git a/gui/traceloader.cpp b/gui/traceloader.cpp index a6ffd297..11847fff 100644 --- a/gui/traceloader.cpp +++ b/gui/traceloader.cpp @@ -56,49 +56,7 @@ void TraceLoader::loadTrace(const QString &filename) void TraceLoader::loadFrame(ApiTraceFrame *currentFrame) { - if (m_parser.supportsOffsets()) { - unsigned frameIdx = currentFrame->number; - int numOfCalls = numberOfCallsInFrame(frameIdx); - - if (numOfCalls) { - quint64 binaryDataSize = 0; - QVector<ApiTraceCall*> calls(numOfCalls); - const FrameBookmark &frameBookmark = m_frameBookmarks[frameIdx]; - - m_parser.setBookmark(frameBookmark.start); - - Trace::Call *call; - int parsedCalls = 0; - while ((call = m_parser.parse_call())) { - ApiTraceCall *apiCall = - apiCallFromTraceCall(call, m_helpHash, - currentFrame, this); - calls[parsedCalls] = apiCall; - Q_ASSERT(calls[parsedCalls]); - if (apiCall->hasBinaryData()) { - QByteArray data = - apiCall->arguments()[ - apiCall->binaryDataIndex()].toByteArray(); - binaryDataSize += data.size(); - } - - ++parsedCalls; - - delete call; - - if (ApiTrace::isCallAFrameMarker(apiCall, m_frameMarker)) { - break; - } - - } - assert(parsedCalls == numOfCalls); - Q_ASSERT(parsedCalls == calls.size()); - Q_ASSERT(parsedCalls == currentFrame->numChildrenToLoad()); - calls.squeeze(); - currentFrame->setCalls(calls, binaryDataSize); - emit frameLoaded(currentFrame); - } - } + fetchFrameContents(currentFrame); } void TraceLoader::setFrameMarker(ApiTrace::FrameMarker marker) @@ -188,6 +146,7 @@ void TraceLoader::scanTrace() currentFrame->setNumChildren(numOfCalls); frames.append(currentFrame); + m_createdFrames.append(currentFrame); m_frameBookmarks[numOfFrames] = frameBookmark; ++numOfFrames; @@ -211,6 +170,7 @@ void TraceLoader::scanTrace() currentFrame->setNumChildren(numOfCalls); frames.append(currentFrame); + m_createdFrames.append(currentFrame); m_frameBookmarks[numOfFrames] = frameBookmark; ++numOfFrames; } @@ -312,4 +272,125 @@ void TraceLoader::addEnumSignature(unsigned id, ApiTraceEnumSignature *signature m_enumSignatures[id] = signature; } +void TraceLoader::searchNext(int startFrame, + const QString &str, + Qt::CaseSensitivity sensitivity) +{ + Q_ASSERT(m_parser.supportsOffsets()); + if (m_parser.supportsOffsets()) { + const FrameBookmark &frameBookmark = m_frameBookmarks[startFrame]; + m_parser.setBookmark(frameBookmark.start); + Trace::Call *call = 0; + while ((call = m_parser.parse_call())) { + + if (callContains(call, str, sensitivity)) { + unsigned frameIdx = callInFrame(call->no); + ApiTraceFrame *frame = m_createdFrames[frameIdx]; + const QVector<ApiTraceCall*> calls = + fetchFrameContents(frame); + for (int i = 0; i < calls.count(); ++i) { + if (calls[i]->index() == call->no) { + emit searchResult(ApiTrace::SearchFound, calls[i]); + break; + } + } + delete call; + return; + } + + delete call; + } + } + emit searchResult(ApiTrace::SearchNotFound, 0); +} + +void TraceLoader::searchPrev(int startFrame, + const QString &str, + Qt::CaseSensitivity sensitivity) +{ +} + +int TraceLoader::callInFrame(int callIdx) const +{ + unsigned numCalls = 0; + + for (int frameIdx = 0; frameIdx <= m_frameBookmarks.size(); ++frameIdx) { + const FrameBookmark &frameBookmark = m_frameBookmarks[frameIdx]; + unsigned firstCall = numCalls; + unsigned endCall = numCalls + frameBookmark.numberOfCalls; + if (firstCall <= callIdx && endCall > callIdx) { + return frameIdx; + } + numCalls = endCall; + } + Q_ASSERT(!"call not in the trace"); + return 0; +} + +bool TraceLoader::callContains(Trace::Call *call, + const QString &str, + Qt::CaseSensitivity sensitivity) +{ + /* + * FIXME: do string comparison directly on Trace::Call + */ + ApiTraceCall *apiCall = apiCallFromTraceCall(call, m_helpHash, + 0, this); + bool result = apiCall->contains(str, sensitivity); + delete apiCall; + return result; +} + +QVector<ApiTraceCall*> +TraceLoader::fetchFrameContents(ApiTraceFrame *currentFrame) +{ + Q_ASSERT(currentFrame); + if (m_parser.supportsOffsets()) { + unsigned frameIdx = currentFrame->number; + int numOfCalls = numberOfCallsInFrame(frameIdx); + + if (numOfCalls) { + quint64 binaryDataSize = 0; + QVector<ApiTraceCall*> calls(numOfCalls); + const FrameBookmark &frameBookmark = m_frameBookmarks[frameIdx]; + + m_parser.setBookmark(frameBookmark.start); + + Trace::Call *call; + int parsedCalls = 0; + while ((call = m_parser.parse_call())) { + ApiTraceCall *apiCall = + apiCallFromTraceCall(call, m_helpHash, + currentFrame, this); + calls[parsedCalls] = apiCall; + Q_ASSERT(calls[parsedCalls]); + if (apiCall->hasBinaryData()) { + QByteArray data = + apiCall->arguments()[ + apiCall->binaryDataIndex()].toByteArray(); + binaryDataSize += data.size(); + } + + ++parsedCalls; + + delete call; + + if (ApiTrace::isCallAFrameMarker(apiCall, m_frameMarker)) { + break; + } + + } + assert(parsedCalls == numOfCalls); + Q_ASSERT(parsedCalls == calls.size()); + calls.squeeze(); + + Q_ASSERT(parsedCalls == currentFrame->numChildrenToLoad()); + emit frameContentsLoaded(currentFrame, + calls, binaryDataSize); + return calls; + } + } + return QVector<ApiTraceCall*>(); +} + #include "traceloader.moc" diff --git a/gui/traceloader.h b/gui/traceloader.h index 86b75263..c83cf47b 100644 --- a/gui/traceloader.h +++ b/gui/traceloader.h @@ -28,6 +28,12 @@ public slots: void loadTrace(const QString &filename); void loadFrame(ApiTraceFrame *frame); void setFrameMarker(ApiTrace::FrameMarker marker); + void searchNext(int startFrame, + const QString &str, + Qt::CaseSensitivity sensitivity); + void searchPrev(int startFrame, + const QString &str, + Qt::CaseSensitivity sensitivity); signals: void startedParsing(); @@ -35,8 +41,11 @@ signals: void finishedParsing(); void framesLoaded(const QList<ApiTraceFrame*> &frames); - void frameLoaded(ApiTraceFrame *frame); + void frameContentsLoaded(ApiTraceFrame *frame, + const QVector<ApiTraceCall*> &calls, + quint64 binaryDataSize); + void searchResult(ApiTrace::SearchResult result, ApiTraceCall *call); private: struct FrameBookmark { FrameBookmark() @@ -58,6 +67,12 @@ private: void scanTrace(); void parseTrace(); + int callInFrame(int callIdx) const; + bool callContains(Trace::Call *call, + const QString &str, + Qt::CaseSensitivity sensitivity); + QVector<ApiTraceCall*> fetchFrameContents(ApiTraceFrame *frame); + private: Trace::Parser m_parser; QString m_fileName; @@ -65,6 +80,7 @@ private: typedef QMap<int, FrameBookmark> FrameBookmarks; FrameBookmarks m_frameBookmarks; + QList<ApiTraceFrame*> m_createdFrames; QHash<QString, QUrl> m_helpHash; |