3 #include "traceloader.h"
4 #include "saverthread.h"
11 : m_needsSaving(false)
13 m_loader = new TraceLoader();
15 connect(this, SIGNAL(loadTrace(QString)),
16 m_loader, SLOT(loadTrace(QString)));
17 connect(this, SIGNAL(requestFrame(ApiTraceFrame*)),
18 m_loader, SLOT(loadFrame(ApiTraceFrame*)));
19 connect(m_loader, SIGNAL(framesLoaded(const QList<ApiTraceFrame*>)),
20 this, SLOT(addFrames(const QList<ApiTraceFrame*>)));
22 SIGNAL(frameContentsLoaded(ApiTraceFrame*,QVector<ApiTraceCall*>, QVector<ApiTraceCall*>,quint64)),
24 SLOT(loaderFrameLoaded(ApiTraceFrame*,QVector<ApiTraceCall*>,QVector<ApiTraceCall*>,quint64)));
25 connect(m_loader, SIGNAL(guessedApi(int)),
26 this, SLOT(guessedApi(int)));
27 connect(m_loader, SIGNAL(finishedParsing()),
28 this, SLOT(finishedParsing()));
29 connect(this, SIGNAL(loaderSearch(ApiTrace::SearchRequest)),
30 m_loader, SLOT(search(ApiTrace::SearchRequest)));
32 SIGNAL(searchResult(ApiTrace::SearchRequest,ApiTrace::SearchResult,ApiTraceCall*)),
34 SLOT(loaderSearchResult(ApiTrace::SearchRequest,ApiTrace::SearchResult,ApiTraceCall*)));
35 connect(this, SIGNAL(loaderFindFrameStart(ApiTraceFrame*)),
36 m_loader, SLOT(findFrameStart(ApiTraceFrame*)));
37 connect(this, SIGNAL(loaderFindFrameEnd(ApiTraceFrame*)),
38 m_loader, SLOT(findFrameEnd(ApiTraceFrame*)));
39 connect(m_loader, SIGNAL(foundFrameStart(ApiTraceFrame*)),
40 this, SIGNAL(foundFrameStart(ApiTraceFrame*)));
41 connect(m_loader, SIGNAL(foundFrameEnd(ApiTraceFrame*)),
42 this, SIGNAL(foundFrameEnd(ApiTraceFrame*)));
43 connect(this, SIGNAL(loaderFindCallIndex(int)),
44 m_loader, SLOT(findCallIndex(int)));
45 connect(m_loader, SIGNAL(foundCallIndex(ApiTraceCall*)),
46 this, SIGNAL(foundCallIndex(ApiTraceCall*)));
49 connect(m_loader, SIGNAL(startedParsing()),
50 this, SIGNAL(startedLoadingTrace()));
51 connect(m_loader, SIGNAL(parsed(int)),
52 this, SIGNAL(loaded(int)));
53 connect(m_loader, SIGNAL(finishedParsing()),
54 this, SIGNAL(finishedLoadingTrace()));
57 m_saver = new SaverThread(this);
58 connect(m_saver, SIGNAL(traceSaved()),
59 this, SLOT(slotSaved()));
60 connect(m_saver, SIGNAL(traceSaved()),
61 this, SIGNAL(saved()));
63 m_loaderThread = new QThread();
64 m_loader->moveToThread(m_loaderThread);
65 m_loaderThread->start();
70 m_loaderThread->quit();
71 m_loaderThread->deleteLater();
77 bool ApiTrace::isEmpty() const
79 return m_frames.isEmpty();
82 QString ApiTrace::fileName() const
85 return m_tempFileName;
91 const QList<ApiTraceFrame*> & ApiTrace::frames() const
96 ApiTraceFrame * ApiTrace::frameAt(int idx) const
98 return m_frames.value(idx);
101 int ApiTrace::numFrames() const
103 return m_frames.count();
106 int ApiTrace::numCallsInFrame(int idx) const
108 const ApiTraceFrame *frame = frameAt(idx);
110 return frame->numTotalCalls();
116 void ApiTrace::setFileName(const QString &name)
118 if (m_fileName != name) {
120 m_tempFileName = QString();
124 m_editedCalls.clear();
125 m_queuedErrors.clear();
126 m_needsSaving = false;
129 emit loadTrace(m_fileName);
133 void ApiTrace::addFrames(const QList<ApiTraceFrame*> &frames)
135 int currentFrames = m_frames.count();
136 int numNewFrames = frames.count();
138 emit beginAddingFrames(currentFrames, numNewFrames);
142 foreach(ApiTraceFrame *frame, frames) {
143 frame->setParentTrace(this);
146 emit endAddingFrames();
149 ApiTraceCall * ApiTrace::callWithIndex(int idx) const
151 for (int i = 0; i < m_frames.count(); ++i) {
152 ApiTraceCall *call = m_frames[i]->callWithIndex(idx);
160 ApiTraceState ApiTrace::defaultState() const
162 ApiTraceFrame *frame = frameAt(0);
163 if (!frame || !frame->isLoaded() || frame->isEmpty()) {
164 return ApiTraceState();
167 ApiTraceCall *firstCall = frame->calls().first();
168 if (!firstCall->hasState()) {
169 return ApiTraceState();
172 return *firstCall->state();
175 void ApiTrace::callEdited(ApiTraceCall *call)
177 if (!m_editedCalls.contains(call)) {
178 //lets generate a temp filename
179 QString tempPath = QDir::tempPath();
180 m_tempFileName = QString::fromLatin1("%1/%2.edited")
184 m_editedCalls.insert(call);
185 m_needsSaving = true;
190 void ApiTrace::callReverted(ApiTraceCall *call)
192 m_editedCalls.remove(call);
194 if (m_editedCalls.isEmpty()) {
195 m_needsSaving = false;
200 bool ApiTrace::edited() const
202 return !m_editedCalls.isEmpty();
205 bool ApiTrace::needsSaving() const
207 return m_needsSaving;
210 void ApiTrace::save()
212 QFileInfo fi(m_tempFileName);
214 emit startedSaving();
215 dir.mkpath(fi.absolutePath());
216 m_saver->saveFile(m_tempFileName,
221 void ApiTrace::slotSaved()
223 m_needsSaving = false;
226 bool ApiTrace::isSaving() const
228 return m_saver->isRunning();
231 bool ApiTrace::hasErrors() const
233 return !m_errors.isEmpty() || !m_queuedErrors.isEmpty();
236 void ApiTrace::loadFrame(ApiTraceFrame *frame)
238 if (!isFrameLoading(frame)) {
239 Q_ASSERT(!frame->isLoaded());
240 m_loadingFrames.insert(frame);
241 emit requestFrame(frame);
245 void ApiTrace::guessedApi(int api)
247 m_api = static_cast<trace::API>(api);
250 trace::API ApiTrace::api() const
255 void ApiTrace::finishedParsing()
257 if (!m_frames.isEmpty()) {
258 ApiTraceFrame *firstFrame = m_frames[0];
259 if (firstFrame && !firstFrame->isLoaded()) {
260 loadFrame(firstFrame);
265 void ApiTrace::loaderFrameLoaded(ApiTraceFrame *frame,
266 const QVector<ApiTraceCall*> &topLevelItems,
267 const QVector<ApiTraceCall*> &calls,
268 quint64 binaryDataSize)
270 Q_ASSERT(frame->numChildrenToLoad() >= calls.size());
272 if (!frame->isLoaded()) {
273 emit beginLoadingFrame(frame, calls.size());
274 frame->setCalls(topLevelItems, calls, binaryDataSize);
275 emit endLoadingFrame(frame);
276 m_loadingFrames.remove(frame);
279 if (!m_queuedErrors.isEmpty()) {
280 QList< QPair<ApiTraceFrame*, ApiTraceError> >::iterator itr;
281 for (itr = m_queuedErrors.begin(); itr != m_queuedErrors.end();
283 const ApiTraceError &error = (*itr).second;
284 if ((*itr).first == frame) {
285 ApiTraceCall *call = frame->callWithIndex(error.callIndex);
291 call->setError(error.message);
292 m_queuedErrors.erase(itr);
294 if (call->hasError()) {
295 m_errors.insert(call);
297 m_errors.remove(call);
305 void ApiTrace::findNext(ApiTraceFrame *frame,
308 Qt::CaseSensitivity sensitivity)
310 ApiTraceCall *foundCall = 0;
311 int frameIdx = m_frames.indexOf(frame);
312 SearchRequest request(SearchRequest::Next,
313 frame, from, str, sensitivity);
315 if (frame->isLoaded()) {
316 foundCall = frame->findNextCall(from, str, sensitivity);
318 emit findResult(request, SearchResult_Found, foundCall);
322 //if the frame is loaded we already searched it above
327 //for the rest of the frames we search from beginning
329 for (int i = frameIdx; i < m_frames.count(); ++i) {
330 ApiTraceFrame *frame = m_frames[i];
331 request.frame = frame;
332 if (!frame->isLoaded()) {
333 emit loaderSearch(request);
336 ApiTraceCall *call = frame->findNextCall(0, str, sensitivity);
338 emit findResult(request, SearchResult_Found, call);
343 emit findResult(request, SearchResult_Wrapped, 0);
346 void ApiTrace::findPrev(ApiTraceFrame *frame,
349 Qt::CaseSensitivity sensitivity)
351 ApiTraceCall *foundCall = 0;
352 int frameIdx = m_frames.indexOf(frame);
353 SearchRequest request(SearchRequest::Prev,
354 frame, from, str, sensitivity);
356 if (frame->isLoaded()) {
357 foundCall = frame->findPrevCall(from, str, sensitivity);
359 emit findResult(request, SearchResult_Found, foundCall);
363 //if the frame is loaded we already searched it above
369 for (int i = frameIdx; i >= 0; --i) {
370 ApiTraceFrame *frame = m_frames[i];
371 request.frame = frame;
372 if (!frame->isLoaded()) {
373 emit loaderSearch(request);
376 ApiTraceCall *call = frame->findPrevCall(0, str, sensitivity);
378 emit findResult(request, SearchResult_Found, call);
383 emit findResult(request, SearchResult_Wrapped, 0);
386 void ApiTrace::loaderSearchResult(const ApiTrace::SearchRequest &request,
387 ApiTrace::SearchResult result,
390 //qDebug()<<"Search result = "<<result
391 // <<", call is = "<<call;
392 emit findResult(request, result, call);
395 void ApiTrace::findFrameStart(ApiTraceFrame *frame)
400 if (frame->isLoaded()) {
401 emit foundFrameStart(frame);
403 emit loaderFindFrameStart(frame);
407 void ApiTrace::findFrameEnd(ApiTraceFrame *frame)
412 if (frame->isLoaded()) {
413 emit foundFrameEnd(frame);
415 emit loaderFindFrameEnd(frame);
419 void ApiTrace::findCallIndex(int index)
421 int frameIdx = callInFrame(index);
422 ApiTraceFrame *frame = 0;
425 emit foundCallIndex(0);
429 frame = m_frames[frameIdx];
432 if (frame->isLoaded()) {
433 ApiTraceCall *call = frame->callWithIndex(index);
434 emit foundCallIndex(call);
436 emit loaderFindCallIndex(index);
441 int ApiTrace::callInFrame(int callIdx) const
443 unsigned numCalls = 0;
445 for (int frameIdx = 0; frameIdx < m_frames.size(); ++frameIdx) {
446 const ApiTraceFrame *frame = m_frames[frameIdx];
447 unsigned numCallsInFrame = frame->isLoaded()
448 ? frame->numTotalCalls()
449 : frame->numChildrenToLoad();
450 unsigned firstCall = numCalls;
451 unsigned endCall = numCalls + numCallsInFrame;
452 if (firstCall <= callIdx && endCall > callIdx) {
461 void ApiTrace::setCallError(const ApiTraceError &error)
463 int frameIdx = callInFrame(error.callIndex);
464 ApiTraceFrame *frame = 0;
469 frame = m_frames[frameIdx];
471 if (frame->isLoaded()) {
472 ApiTraceCall *call = frame->callWithIndex(error.callIndex);
473 call->setError(error.message);
474 if (call->hasError()) {
475 m_errors.insert(call);
477 m_errors.remove(call);
482 m_queuedErrors.append(qMakePair(frame, error));
486 bool ApiTrace::isFrameLoading(ApiTraceFrame *frame) const
488 return m_loadingFrames.contains(frame);
491 void ApiTrace::bindThumbnailsToFrames(const QList<QImage> &thumbnails)
493 QList<ApiTraceFrame *> frames = m_frames;
495 QList<QImage>::const_iterator thumbnail = thumbnails.begin();
497 foreach (ApiTraceFrame *frame, frames) {
498 if (thumbnail != thumbnails.end()) {
499 frame->setThumbnail(*thumbnail);
508 #include "apitrace.moc"