3 #include "traceloader.h"
4 #include "saverthread.h"
11 : m_frameMarker(ApiTrace::FrameMarker_SwapBuffers),
14 m_loader = new TraceLoader();
16 connect(this, SIGNAL(loadTrace(QString)),
17 m_loader, SLOT(loadTrace(QString)));
18 connect(this, SIGNAL(requestFrame(ApiTraceFrame*)),
19 m_loader, SLOT(loadFrame(ApiTraceFrame*)));
20 connect(m_loader, SIGNAL(framesLoaded(const QList<ApiTraceFrame*>)),
21 this, SLOT(addFrames(const QList<ApiTraceFrame*>)));
23 SIGNAL(frameContentsLoaded(ApiTraceFrame*,QVector<ApiTraceCall*>,quint64)),
25 SLOT(loaderFrameLoaded(ApiTraceFrame*,QVector<ApiTraceCall*>,quint64)));
26 connect(m_loader, SIGNAL(finishedParsing()),
27 this, SLOT(finishedParsing()));
28 connect(this, SIGNAL(loaderSearch(ApiTrace::SearchRequest)),
29 m_loader, SLOT(search(ApiTrace::SearchRequest)));
31 SIGNAL(searchResult(ApiTrace::SearchRequest,ApiTrace::SearchResult,ApiTraceCall*)),
33 SLOT(loaderSearchResult(ApiTrace::SearchRequest,ApiTrace::SearchResult,ApiTraceCall*)));
34 connect(this, SIGNAL(loaderFindFrameStart(ApiTraceFrame*)),
35 m_loader, SLOT(findFrameStart(ApiTraceFrame*)));
36 connect(this, SIGNAL(loaderFindFrameEnd(ApiTraceFrame*)),
37 m_loader, SLOT(findFrameEnd(ApiTraceFrame*)));
38 connect(m_loader, SIGNAL(foundFrameStart(ApiTraceFrame*)),
39 this, SIGNAL(foundFrameStart(ApiTraceFrame*)));
40 connect(m_loader, SIGNAL(foundFrameEnd(ApiTraceFrame*)),
41 this, SIGNAL(foundFrameEnd(ApiTraceFrame*)));
42 connect(this, SIGNAL(loaderFindCallIndex(int)),
43 m_loader, SLOT(findCallIndex(int)));
44 connect(m_loader, SIGNAL(foundCallIndex(ApiTraceCall*)),
45 this, SIGNAL(foundCallIndex(ApiTraceCall*)));
48 connect(m_loader, SIGNAL(startedParsing()),
49 this, SIGNAL(startedLoadingTrace()));
50 connect(m_loader, SIGNAL(parsed(int)),
51 this, SIGNAL(loaded(int)));
52 connect(m_loader, SIGNAL(finishedParsing()),
53 this, SIGNAL(finishedLoadingTrace()));
56 m_saver = new SaverThread(this);
57 connect(m_saver, SIGNAL(traceSaved()),
58 this, SLOT(slotSaved()));
59 connect(m_saver, SIGNAL(traceSaved()),
60 this, SIGNAL(saved()));
62 m_loaderThread = new QThread();
63 m_loader->moveToThread(m_loaderThread);
64 m_loaderThread->start();
69 m_loaderThread->quit();
70 m_loaderThread->deleteLater();
76 bool ApiTrace::isCallAFrameMarker(const ApiTraceCall *call,
77 ApiTrace::FrameMarker marker)
84 case FrameMarker_SwapBuffers:
85 return call->flags() & trace::CALL_FLAG_END_FRAME;
86 case FrameMarker_Flush:
87 return call->name() == QLatin1String("glFlush");
88 case FrameMarker_Finish:
89 return call->name() == QLatin1String("glFinish");
90 case FrameMarker_Clear:
91 return call->name() == QLatin1String("glClear");
94 Q_ASSERT(!"unknown frame marker");
99 bool ApiTrace::isEmpty() const
101 return m_frames.isEmpty();
104 QString ApiTrace::fileName() const
107 return m_tempFileName;
113 ApiTrace::FrameMarker ApiTrace::frameMarker() const
115 return m_frameMarker;
118 QList<ApiTraceFrame*> ApiTrace::frames() const
123 ApiTraceFrame * ApiTrace::frameAt(int idx) const
125 return m_frames.value(idx);
128 int ApiTrace::numFrames() const
130 return m_frames.count();
133 int ApiTrace::numCallsInFrame(int idx) const
135 const ApiTraceFrame *frame = frameAt(idx);
137 return frame->numChildren();
143 void ApiTrace::setFileName(const QString &name)
145 if (m_fileName != name) {
147 m_tempFileName = QString();
151 m_editedCalls.clear();
152 m_queuedErrors.clear();
153 m_needsSaving = false;
156 emit loadTrace(m_fileName);
160 void ApiTrace::addFrames(const QList<ApiTraceFrame*> &frames)
162 int currentFrames = m_frames.count();
163 int numNewFrames = frames.count();
165 emit beginAddingFrames(currentFrames, numNewFrames);
169 foreach(ApiTraceFrame *frame, frames) {
170 frame->setParentTrace(this);
173 emit endAddingFrames();
176 ApiTraceCall * ApiTrace::callWithIndex(int idx) const
178 for (int i = 0; i < m_frames.count(); ++i) {
179 ApiTraceCall *call = m_frames[i]->callWithIndex(idx);
187 ApiTraceState ApiTrace::defaultState() const
189 ApiTraceFrame *frame = frameAt(0);
190 if (!frame || !frame->isLoaded() || frame->isEmpty()) {
191 return ApiTraceState();
194 ApiTraceCall *firstCall = frame->calls().first();
195 if (!firstCall->hasState()) {
196 return ApiTraceState();
199 return *firstCall->state();
202 void ApiTrace::callEdited(ApiTraceCall *call)
204 if (!m_editedCalls.contains(call)) {
205 //lets generate a temp filename
206 QString tempPath = QDir::tempPath();
207 m_tempFileName = QString::fromLatin1("%1/%2.edited")
211 m_editedCalls.insert(call);
212 m_needsSaving = true;
217 void ApiTrace::callReverted(ApiTraceCall *call)
219 m_editedCalls.remove(call);
221 if (m_editedCalls.isEmpty()) {
222 m_needsSaving = false;
227 bool ApiTrace::edited() const
229 return !m_editedCalls.isEmpty();
232 bool ApiTrace::needsSaving() const
234 return m_needsSaving;
237 void ApiTrace::save()
239 QFileInfo fi(m_tempFileName);
241 emit startedSaving();
242 dir.mkpath(fi.absolutePath());
243 m_saver->saveFile(m_tempFileName,
248 void ApiTrace::slotSaved()
250 m_needsSaving = false;
253 bool ApiTrace::isSaving() const
255 return m_saver->isRunning();
258 bool ApiTrace::hasErrors() const
260 return !m_errors.isEmpty();
263 void ApiTrace::loadFrame(ApiTraceFrame *frame)
265 if (!isFrameLoading(frame)) {
266 Q_ASSERT(!frame->isLoaded());
267 m_loadingFrames.insert(frame);
268 emit requestFrame(frame);
272 void ApiTrace::finishedParsing()
274 if (!m_frames.isEmpty()) {
275 ApiTraceFrame *firstFrame = m_frames[0];
276 if (firstFrame && !firstFrame->isLoaded()) {
277 loadFrame(firstFrame);
282 void ApiTrace::loaderFrameLoaded(ApiTraceFrame *frame,
283 const QVector<ApiTraceCall*> &calls,
284 quint64 binaryDataSize)
286 Q_ASSERT(frame->numChildrenToLoad() == calls.size());
288 if (!frame->isLoaded()) {
289 emit beginLoadingFrame(frame, calls.size());
290 frame->setCalls(calls, binaryDataSize);
291 emit endLoadingFrame(frame);
292 m_loadingFrames.remove(frame);
295 if (!m_queuedErrors.isEmpty()) {
296 QList< QPair<ApiTraceFrame*, ApiTraceError> >::iterator itr;
297 for (itr = m_queuedErrors.begin(); itr != m_queuedErrors.end();
299 const ApiTraceError &error = (*itr).second;
300 if ((*itr).first == frame) {
301 ApiTraceCall *call = frame->callWithIndex(error.callIndex);
307 call->setError(error.message);
308 m_queuedErrors.erase(itr);
310 if (call->hasError()) {
311 m_errors.insert(call);
313 m_errors.remove(call);
321 void ApiTrace::findNext(ApiTraceFrame *frame,
324 Qt::CaseSensitivity sensitivity)
326 ApiTraceCall *foundCall = 0;
327 int frameIdx = m_frames.indexOf(frame);
328 SearchRequest request(SearchRequest::Next,
329 frame, from, str, sensitivity);
331 if (frame->isLoaded()) {
332 foundCall = frame->findNextCall(from, str, sensitivity);
334 emit findResult(request, SearchResult_Found, foundCall);
338 //if the frame is loaded we already searched it above
343 //for the rest of the frames we search from beginning
345 for (int i = frameIdx; i < m_frames.count(); ++i) {
346 ApiTraceFrame *frame = m_frames[i];
347 request.frame = frame;
348 if (!frame->isLoaded()) {
349 emit loaderSearch(request);
352 ApiTraceCall *call = frame->findNextCall(0, str, sensitivity);
354 emit findResult(request, SearchResult_Found, call);
359 emit findResult(request, SearchResult_Wrapped, 0);
362 void ApiTrace::findPrev(ApiTraceFrame *frame,
365 Qt::CaseSensitivity sensitivity)
367 ApiTraceCall *foundCall = 0;
368 int frameIdx = m_frames.indexOf(frame);
369 SearchRequest request(SearchRequest::Prev,
370 frame, from, str, sensitivity);
372 if (frame->isLoaded()) {
373 foundCall = frame->findPrevCall(from, str, sensitivity);
375 emit findResult(request, SearchResult_Found, foundCall);
379 //if the frame is loaded we already searched it above
385 for (int i = frameIdx; i >= 0; --i) {
386 ApiTraceFrame *frame = m_frames[i];
387 request.frame = frame;
388 if (!frame->isLoaded()) {
389 emit loaderSearch(request);
392 ApiTraceCall *call = frame->findPrevCall(0, str, sensitivity);
394 emit findResult(request, SearchResult_Found, call);
399 emit findResult(request, SearchResult_Wrapped, 0);
402 void ApiTrace::loaderSearchResult(const ApiTrace::SearchRequest &request,
403 ApiTrace::SearchResult result,
406 //qDebug()<<"Search result = "<<result
407 // <<", call is = "<<call;
408 emit findResult(request, result, call);
411 void ApiTrace::findFrameStart(ApiTraceFrame *frame)
413 if (frame->isLoaded()) {
414 emit foundFrameStart(frame);
416 emit loaderFindFrameStart(frame);
420 void ApiTrace::findFrameEnd(ApiTraceFrame *frame)
422 if (frame->isLoaded()) {
423 emit foundFrameEnd(frame);
425 emit loaderFindFrameEnd(frame);
429 void ApiTrace::findCallIndex(int index)
431 int frameIdx = callInFrame(index);
432 ApiTraceFrame *frame = 0;
435 emit foundCallIndex(0);
439 frame = m_frames[frameIdx];
442 if (frame->isLoaded()) {
443 ApiTraceCall *call = frame->callWithIndex(index);
444 emit foundCallIndex(call);
446 emit loaderFindCallIndex(index);
451 int ApiTrace::callInFrame(int callIdx) const
453 unsigned numCalls = 0;
455 for (int frameIdx = 0; frameIdx < m_frames.size(); ++frameIdx) {
456 const ApiTraceFrame *frame = m_frames[frameIdx];
457 unsigned numCallsInFrame = frame->isLoaded()
458 ? frame->numChildren()
459 : frame->numChildrenToLoad();
460 unsigned firstCall = numCalls;
461 unsigned endCall = numCalls + numCallsInFrame;
462 if (firstCall <= callIdx && endCall > callIdx) {
471 void ApiTrace::setCallError(const ApiTraceError &error)
473 int frameIdx = callInFrame(error.callIndex);
474 ApiTraceFrame *frame = 0;
479 frame = m_frames[frameIdx];
481 if (frame->isLoaded()) {
482 ApiTraceCall *call = frame->callWithIndex(error.callIndex);
483 call->setError(error.message);
484 if (call->hasError()) {
485 m_errors.insert(call);
487 m_errors.remove(call);
492 m_queuedErrors.append(qMakePair(frame, error));
496 bool ApiTrace::isFrameLoading(ApiTraceFrame *frame) const
498 return m_loadingFrames.contains(frame);
501 void ApiTrace::bindThumbnailsToFrames(const QList<QImage> &thumbnails)
503 QList<ApiTraceFrame *> frames = m_frames;
505 QList<QImage>::const_iterator thumbnail = thumbnails.begin();
507 foreach (ApiTraceFrame *frame, frames) {
508 if (thumbnail != thumbnails.end()) {
509 frame->setThumbnail(*thumbnail);
518 #include "apitrace.moc"