blob: fe676ff5cdac679079c039a6f4bd6f221460343f [file] [log] [blame]
Zack Rusinf6667d12011-03-30 11:03:37 -04001#include "apitrace.h"
2
Zack Rusinebf971e2011-09-06 17:44:43 -04003#include "traceloader.h"
Zack Rusind809a062011-04-17 23:30:58 -04004#include "saverthread.h"
Zack Rusinf6667d12011-03-30 11:03:37 -04005
Zack Rusin3176ebe2011-09-06 21:11:36 -04006#include <QDebug>
José Fonseca24bc5c32014-11-10 20:13:31 +00007#include <QFileInfo>
Zack Rusin63efea82011-04-17 17:10:45 -04008#include <QDir>
Zack Rusinebf971e2011-09-06 17:44:43 -04009#include <QThread>
Zack Rusin63efea82011-04-17 17:10:45 -040010
Zack Rusinf6667d12011-03-30 11:03:37 -040011ApiTrace::ApiTrace()
José Fonseca5cd8d992012-03-25 23:12:20 +010012 : m_needsSaving(false)
Zack Rusinf6667d12011-03-30 11:03:37 -040013{
Zack Rusinebf971e2011-09-06 17:44:43 -040014 m_loader = new TraceLoader();
Zack Rusinf682e192011-09-07 01:36:41 -040015
Zack Rusinebf971e2011-09-06 17:44:43 -040016 connect(this, SIGNAL(loadTrace(QString)),
17 m_loader, SLOT(loadTrace(QString)));
Zack Rusin3176ebe2011-09-06 21:11:36 -040018 connect(this, SIGNAL(requestFrame(ApiTraceFrame*)),
19 m_loader, SLOT(loadFrame(ApiTraceFrame*)));
Zack Rusinebf971e2011-09-06 17:44:43 -040020 connect(m_loader, SIGNAL(framesLoaded(const QList<ApiTraceFrame*>)),
Zack Rusinf6667d12011-03-30 11:03:37 -040021 this, SLOT(addFrames(const QList<ApiTraceFrame*>)));
Zack Rusin8f98c3a2011-09-11 18:21:29 -040022 connect(m_loader,
Zack Rusind9d9d222013-10-11 18:02:26 -040023 SIGNAL(frameContentsLoaded(ApiTraceFrame*,QVector<ApiTraceCall*>, QVector<ApiTraceCall*>,quint64)),
Zack Rusin8f98c3a2011-09-11 18:21:29 -040024 this,
Zack Rusind9d9d222013-10-11 18:02:26 -040025 SLOT(loaderFrameLoaded(ApiTraceFrame*,QVector<ApiTraceCall*>,QVector<ApiTraceCall*>,quint64)));
José Fonseca67964382012-03-27 23:54:30 +010026 connect(m_loader, SIGNAL(guessedApi(int)),
27 this, SLOT(guessedApi(int)));
Zack Rusinad513b32011-09-25 14:33:41 -040028 connect(this, SIGNAL(loaderSearch(ApiTrace::SearchRequest)),
29 m_loader, SLOT(search(ApiTrace::SearchRequest)));
Zack Rusin8f98c3a2011-09-11 18:21:29 -040030 connect(m_loader,
Zack Rusinad513b32011-09-25 14:33:41 -040031 SIGNAL(searchResult(ApiTrace::SearchRequest,ApiTrace::SearchResult,ApiTraceCall*)),
Zack Rusin8f98c3a2011-09-11 18:21:29 -040032 this,
Zack Rusinad513b32011-09-25 14:33:41 -040033 SLOT(loaderSearchResult(ApiTrace::SearchRequest,ApiTrace::SearchResult,ApiTraceCall*)));
Zack Rusin93e4d152011-09-13 02:23:39 -040034 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*)));
Zack Rusinda7579b2011-09-13 17:33:05 -040042 connect(this, SIGNAL(loaderFindCallIndex(int)),
43 m_loader, SLOT(findCallIndex(int)));
44 connect(m_loader, SIGNAL(foundCallIndex(ApiTraceCall*)),
45 this, SIGNAL(foundCallIndex(ApiTraceCall*)));
Zack Rusin8f98c3a2011-09-11 18:21:29 -040046
Zack Rusinebf971e2011-09-06 17:44:43 -040047
48 connect(m_loader, SIGNAL(startedParsing()),
Zack Rusinde4ea412011-03-30 11:30:08 -040049 this, SIGNAL(startedLoadingTrace()));
Zack Rusinebf971e2011-09-06 17:44:43 -040050 connect(m_loader, SIGNAL(parsed(int)),
51 this, SIGNAL(loaded(int)));
52 connect(m_loader, SIGNAL(finishedParsing()),
Zack Rusinde4ea412011-03-30 11:30:08 -040053 this, SIGNAL(finishedLoadingTrace()));
Zack Rusind809a062011-04-17 23:30:58 -040054
Zack Rusinebf971e2011-09-06 17:44:43 -040055
Zack Rusind809a062011-04-17 23:30:58 -040056 m_saver = new SaverThread(this);
Zack Rusin9af5bff2011-04-18 01:05:50 -040057 connect(m_saver, SIGNAL(traceSaved()),
58 this, SLOT(slotSaved()));
59 connect(m_saver, SIGNAL(traceSaved()),
60 this, SIGNAL(saved()));
Zack Rusinebf971e2011-09-06 17:44:43 -040061
62 m_loaderThread = new QThread();
63 m_loader->moveToThread(m_loaderThread);
64 m_loaderThread->start();
Zack Rusinf6667d12011-03-30 11:03:37 -040065}
66
67ApiTrace::~ApiTrace()
68{
Zack Rusinebf971e2011-09-06 17:44:43 -040069 m_loaderThread->quit();
70 m_loaderThread->deleteLater();
Zack Rusinf6667d12011-03-30 11:03:37 -040071 qDeleteAll(m_frames);
72 delete m_loader;
Zack Rusind809a062011-04-17 23:30:58 -040073 delete m_saver;
Zack Rusinf6667d12011-03-30 11:03:37 -040074}
75
Zack Rusinf6667d12011-03-30 11:03:37 -040076bool ApiTrace::isEmpty() const
77{
Zack Rusinc1743432011-09-13 17:58:58 -040078 return m_frames.isEmpty();
Zack Rusinf6667d12011-03-30 11:03:37 -040079}
80
81QString ApiTrace::fileName() const
82{
Zack Rusinc5929572011-09-19 03:04:40 -040083 if (edited()) {
Zack Rusin63efea82011-04-17 17:10:45 -040084 return m_tempFileName;
Zack Rusinc5929572011-09-19 03:04:40 -040085 }
Zack Rusin63efea82011-04-17 17:10:45 -040086
Zack Rusinf6667d12011-03-30 11:03:37 -040087 return m_fileName;
88}
89
José Fonseca34500442012-03-24 07:56:45 +000090const QList<ApiTraceFrame*> & ApiTrace::frames() const
Zack Rusinf6667d12011-03-30 11:03:37 -040091{
92 return m_frames;
93}
94
95ApiTraceFrame * ApiTrace::frameAt(int idx) const
96{
97 return m_frames.value(idx);
98}
99
100int ApiTrace::numFrames() const
101{
102 return m_frames.count();
103}
104
105int ApiTrace::numCallsInFrame(int idx) const
106{
107 const ApiTraceFrame *frame = frameAt(idx);
Zack Rusinc5929572011-09-19 03:04:40 -0400108 if (frame) {
Zack Rusind9d9d222013-10-11 18:02:26 -0400109 return frame->numTotalCalls();
Zack Rusinc5929572011-09-19 03:04:40 -0400110 } else {
Zack Rusinf6667d12011-03-30 11:03:37 -0400111 return 0;
Zack Rusinc5929572011-09-19 03:04:40 -0400112 }
Zack Rusinf6667d12011-03-30 11:03:37 -0400113}
114
115void ApiTrace::setFileName(const QString &name)
116{
117 if (m_fileName != name) {
118 m_fileName = name;
Zack Rusindaf82af2011-09-24 13:42:53 -0400119 m_tempFileName = QString();
Zack Rusinf6667d12011-03-30 11:03:37 -0400120
Zack Rusinca164112011-04-11 02:23:09 -0400121 m_frames.clear();
Zack Rusin30069572011-04-20 18:21:11 -0400122 m_errors.clear();
123 m_editedCalls.clear();
Zack Rusindaf82af2011-09-24 13:42:53 -0400124 m_queuedErrors.clear();
Zack Rusin30069572011-04-20 18:21:11 -0400125 m_needsSaving = false;
Zack Rusinf6667d12011-03-30 11:03:37 -0400126 emit invalidated();
127
Zack Rusinebf971e2011-09-06 17:44:43 -0400128 emit loadTrace(m_fileName);
Zack Rusinf6667d12011-03-30 11:03:37 -0400129 }
130}
131
Zack Rusinf6667d12011-03-30 11:03:37 -0400132void ApiTrace::addFrames(const QList<ApiTraceFrame*> &frames)
133{
134 int currentFrames = m_frames.count();
135 int numNewFrames = frames.count();
Zack Rusinb56e03d2011-04-20 23:58:52 -0400136
137 emit beginAddingFrames(currentFrames, numNewFrames);
138
Zack Rusinf6667d12011-03-30 11:03:37 -0400139 m_frames += frames;
140
Zack Rusinf6667d12011-03-30 11:03:37 -0400141 foreach(ApiTraceFrame *frame, frames) {
Zack Rusinebf971e2011-09-06 17:44:43 -0400142 frame->setParentTrace(this);
Zack Rusinf6667d12011-03-30 11:03:37 -0400143 }
144
Zack Rusinb56e03d2011-04-20 23:58:52 -0400145 emit endAddingFrames();
Zack Rusinf6667d12011-03-30 11:03:37 -0400146}
147
Zack Rusinf04cf8a2011-04-12 23:21:52 -0400148ApiTraceCall * ApiTrace::callWithIndex(int idx) const
149{
Zack Rusinc1743432011-09-13 17:58:58 -0400150 for (int i = 0; i < m_frames.count(); ++i) {
151 ApiTraceCall *call = m_frames[i]->callWithIndex(idx);
Zack Rusinc5929572011-09-19 03:04:40 -0400152 if (call) {
Zack Rusinf04cf8a2011-04-12 23:21:52 -0400153 return call;
Zack Rusinc5929572011-09-19 03:04:40 -0400154 }
Zack Rusinf04cf8a2011-04-12 23:21:52 -0400155 }
156 return NULL;
157}
158
Zack Rusine2dfa2e2011-04-13 01:35:03 -0400159ApiTraceState ApiTrace::defaultState() const
160{
161 ApiTraceFrame *frame = frameAt(0);
Zack Rusinc5929572011-09-19 03:04:40 -0400162 if (!frame || !frame->isLoaded() || frame->isEmpty()) {
Zack Rusine2dfa2e2011-04-13 01:35:03 -0400163 return ApiTraceState();
Zack Rusinc5929572011-09-19 03:04:40 -0400164 }
Zack Rusine2dfa2e2011-04-13 01:35:03 -0400165
Zack Rusin851d0b02011-09-14 22:04:07 -0400166 ApiTraceCall *firstCall = frame->calls().first();
167 if (!firstCall->hasState()) {
168 return ApiTraceState();
169 }
170
171 return *firstCall->state();
Zack Rusine2dfa2e2011-04-13 01:35:03 -0400172}
173
Zack Rusin661842d2011-04-17 01:59:16 -0400174void ApiTrace::callEdited(ApiTraceCall *call)
175{
Zack Rusin63efea82011-04-17 17:10:45 -0400176 if (!m_editedCalls.contains(call)) {
José Fonseca24bc5c32014-11-10 20:13:31 +0000177 // Lets generate a temp filename
178 QFileInfo fileInfo(m_fileName);
Zack Rusin63efea82011-04-17 17:10:45 -0400179 QString tempPath = QDir::tempPath();
José Fonseca24bc5c32014-11-10 20:13:31 +0000180 m_tempFileName = QDir::tempPath();
181 m_tempFileName += QDir::separator();
182 m_tempFileName += fileInfo.fileName();
183 m_tempFileName += QString::fromLatin1(".edited");
Zack Rusin63efea82011-04-17 17:10:45 -0400184 }
Zack Rusin661842d2011-04-17 01:59:16 -0400185 m_editedCalls.insert(call);
Zack Rusin9af5bff2011-04-18 01:05:50 -0400186 m_needsSaving = true;
Zack Rusin63efea82011-04-17 17:10:45 -0400187
Zack Rusin661842d2011-04-17 01:59:16 -0400188 emit changed(call);
189}
190
191void ApiTrace::callReverted(ApiTraceCall *call)
192{
193 m_editedCalls.remove(call);
Zack Rusin63efea82011-04-17 17:10:45 -0400194
195 if (m_editedCalls.isEmpty()) {
196 m_needsSaving = false;
197 }
Zack Rusin661842d2011-04-17 01:59:16 -0400198 emit changed(call);
199}
200
Zack Rusin0ddd2502011-04-17 02:34:45 -0400201bool ApiTrace::edited() const
Zack Rusin661842d2011-04-17 01:59:16 -0400202{
203 return !m_editedCalls.isEmpty();
204}
205
Zack Rusin63efea82011-04-17 17:10:45 -0400206bool ApiTrace::needsSaving() const
207{
208 return m_needsSaving;
209}
210
211void ApiTrace::save()
212{
213 QFileInfo fi(m_tempFileName);
214 QDir dir;
Zack Rusin9af5bff2011-04-18 01:05:50 -0400215 emit startedSaving();
Zack Rusin63efea82011-04-17 17:10:45 -0400216 dir.mkpath(fi.absolutePath());
Zack Rusin9b31ffc2011-09-13 23:58:45 -0400217 m_saver->saveFile(m_tempFileName,
218 m_fileName,
219 m_editedCalls);
Zack Rusin63efea82011-04-17 17:10:45 -0400220}
221
Zack Rusin9af5bff2011-04-18 01:05:50 -0400222void ApiTrace::slotSaved()
223{
224 m_needsSaving = false;
225}
226
227bool ApiTrace::isSaving() const
228{
229 return m_saver->isRunning();
230}
231
Zack Rusincc0b4912011-04-19 01:59:20 -0400232bool ApiTrace::hasErrors() const
233{
James Benton6a319062012-08-09 16:22:50 +0100234 return !m_errors.isEmpty() || !m_queuedErrors.isEmpty();
Zack Rusincc0b4912011-04-19 01:59:20 -0400235}
236
Zack Rusin3176ebe2011-09-06 21:11:36 -0400237void ApiTrace::loadFrame(ApiTraceFrame *frame)
Zack Rusinac4dd9a2011-08-28 00:38:13 -0400238{
Zack Rusin18d094e2011-10-07 23:55:55 -0400239 if (!isFrameLoading(frame)) {
240 Q_ASSERT(!frame->isLoaded());
241 m_loadingFrames.insert(frame);
242 emit requestFrame(frame);
243 }
Zack Rusin35c27932011-08-28 21:16:22 -0400244}
245
José Fonseca67964382012-03-27 23:54:30 +0100246void ApiTrace::guessedApi(int api)
247{
248 m_api = static_cast<trace::API>(api);
249}
250
251trace::API ApiTrace::api() const
252{
253 return m_api;
254}
255
Zack Rusinf682e192011-09-07 01:36:41 -0400256void ApiTrace::finishedParsing()
257{
José Fonseca0b08bc62012-03-22 16:22:33 +0000258 if (!m_frames.isEmpty()) {
259 ApiTraceFrame *firstFrame = m_frames[0];
260 if (firstFrame && !firstFrame->isLoaded()) {
261 loadFrame(firstFrame);
262 }
Zack Rusinf682e192011-09-07 01:36:41 -0400263 }
264}
265
Zack Rusin8f98c3a2011-09-11 18:21:29 -0400266void ApiTrace::loaderFrameLoaded(ApiTraceFrame *frame,
Zack Rusind9d9d222013-10-11 18:02:26 -0400267 const QVector<ApiTraceCall*> &topLevelItems,
Zack Rusin8f98c3a2011-09-11 18:21:29 -0400268 const QVector<ApiTraceCall*> &calls,
269 quint64 binaryDataSize)
Zack Rusinf682e192011-09-07 01:36:41 -0400270{
José Fonsecacaa84282013-04-11 18:54:06 +0100271 Q_ASSERT(frame->numChildrenToLoad() >= calls.size());
Zack Rusin18d094e2011-10-07 23:55:55 -0400272
273 if (!frame->isLoaded()) {
274 emit beginLoadingFrame(frame, calls.size());
Zack Rusind9d9d222013-10-11 18:02:26 -0400275 frame->setCalls(topLevelItems, calls, binaryDataSize);
Zack Rusin18d094e2011-10-07 23:55:55 -0400276 emit endLoadingFrame(frame);
277 m_loadingFrames.remove(frame);
278 }
Zack Rusin10fd4772011-09-14 01:45:12 -0400279
280 if (!m_queuedErrors.isEmpty()) {
281 QList< QPair<ApiTraceFrame*, ApiTraceError> >::iterator itr;
282 for (itr = m_queuedErrors.begin(); itr != m_queuedErrors.end();
283 ++itr) {
284 const ApiTraceError &error = (*itr).second;
285 if ((*itr).first == frame) {
286 ApiTraceCall *call = frame->callWithIndex(error.callIndex);
287
288 if (!call) {
289 continue;
290 }
291
292 call->setError(error.message);
293 m_queuedErrors.erase(itr);
294
295 if (call->hasError()) {
296 m_errors.insert(call);
297 } else {
298 m_errors.remove(call);
299 }
300 emit changed(call);
301 }
302 }
303 }
Zack Rusinf682e192011-09-07 01:36:41 -0400304}
305
Zack Rusin8f98c3a2011-09-11 18:21:29 -0400306void ApiTrace::findNext(ApiTraceFrame *frame,
307 ApiTraceCall *from,
308 const QString &str,
309 Qt::CaseSensitivity sensitivity)
310{
311 ApiTraceCall *foundCall = 0;
312 int frameIdx = m_frames.indexOf(frame);
Zack Rusinad513b32011-09-25 14:33:41 -0400313 SearchRequest request(SearchRequest::Next,
314 frame, from, str, sensitivity);
Zack Rusin8f98c3a2011-09-11 18:21:29 -0400315
Zack Rusin1a9f7af2011-09-18 19:40:47 -0400316 if (frame->isLoaded()) {
Zack Rusin8f98c3a2011-09-11 18:21:29 -0400317 foundCall = frame->findNextCall(from, str, sensitivity);
318 if (foundCall) {
Zack Rusinad513b32011-09-25 14:33:41 -0400319 emit findResult(request, SearchResult_Found, foundCall);
Zack Rusin8f98c3a2011-09-11 18:21:29 -0400320 return;
321 }
322
323 //if the frame is loaded we already searched it above
324 // so skip it
325 frameIdx += 1;
326 }
327
Zack Rusinad513b32011-09-25 14:33:41 -0400328 //for the rest of the frames we search from beginning
329 request.from = 0;
Zack Rusin8f98c3a2011-09-11 18:21:29 -0400330 for (int i = frameIdx; i < m_frames.count(); ++i) {
331 ApiTraceFrame *frame = m_frames[i];
Zack Rusinad513b32011-09-25 14:33:41 -0400332 request.frame = frame;
Zack Rusin1a9f7af2011-09-18 19:40:47 -0400333 if (!frame->isLoaded()) {
Zack Rusinad513b32011-09-25 14:33:41 -0400334 emit loaderSearch(request);
Zack Rusin8f98c3a2011-09-11 18:21:29 -0400335 return;
336 } else {
337 ApiTraceCall *call = frame->findNextCall(0, str, sensitivity);
338 if (call) {
Zack Rusinad513b32011-09-25 14:33:41 -0400339 emit findResult(request, SearchResult_Found, call);
Zack Rusin121e3162011-09-13 01:35:12 -0400340 return;
Zack Rusin8f98c3a2011-09-11 18:21:29 -0400341 }
342 }
343 }
Zack Rusinad513b32011-09-25 14:33:41 -0400344 emit findResult(request, SearchResult_Wrapped, 0);
Zack Rusin8f98c3a2011-09-11 18:21:29 -0400345}
346
347void ApiTrace::findPrev(ApiTraceFrame *frame,
348 ApiTraceCall *from,
349 const QString &str,
350 Qt::CaseSensitivity sensitivity)
351{
352 ApiTraceCall *foundCall = 0;
353 int frameIdx = m_frames.indexOf(frame);
Zack Rusinad513b32011-09-25 14:33:41 -0400354 SearchRequest request(SearchRequest::Prev,
355 frame, from, str, sensitivity);
Zack Rusin8f98c3a2011-09-11 18:21:29 -0400356
Zack Rusin1a9f7af2011-09-18 19:40:47 -0400357 if (frame->isLoaded()) {
Zack Rusin8f98c3a2011-09-11 18:21:29 -0400358 foundCall = frame->findPrevCall(from, str, sensitivity);
359 if (foundCall) {
Zack Rusinad513b32011-09-25 14:33:41 -0400360 emit findResult(request, SearchResult_Found, foundCall);
Zack Rusin8f98c3a2011-09-11 18:21:29 -0400361 return;
362 }
363
364 //if the frame is loaded we already searched it above
365 // so skip it
366 frameIdx -= 1;
367 }
368
Zack Rusinad513b32011-09-25 14:33:41 -0400369 request.from = 0;
Zack Rusin121e3162011-09-13 01:35:12 -0400370 for (int i = frameIdx; i >= 0; --i) {
Zack Rusin8f98c3a2011-09-11 18:21:29 -0400371 ApiTraceFrame *frame = m_frames[i];
Zack Rusinad513b32011-09-25 14:33:41 -0400372 request.frame = frame;
Zack Rusin1a9f7af2011-09-18 19:40:47 -0400373 if (!frame->isLoaded()) {
Zack Rusinad513b32011-09-25 14:33:41 -0400374 emit loaderSearch(request);
Zack Rusin8f98c3a2011-09-11 18:21:29 -0400375 return;
376 } else {
377 ApiTraceCall *call = frame->findPrevCall(0, str, sensitivity);
378 if (call) {
Zack Rusinad513b32011-09-25 14:33:41 -0400379 emit findResult(request, SearchResult_Found, call);
Zack Rusin121e3162011-09-13 01:35:12 -0400380 return;
Zack Rusin8f98c3a2011-09-11 18:21:29 -0400381 }
382 }
383 }
Zack Rusinad513b32011-09-25 14:33:41 -0400384 emit findResult(request, SearchResult_Wrapped, 0);
Zack Rusin8f98c3a2011-09-11 18:21:29 -0400385}
386
Zack Rusinad513b32011-09-25 14:33:41 -0400387void ApiTrace::loaderSearchResult(const ApiTrace::SearchRequest &request,
388 ApiTrace::SearchResult result,
Zack Rusin8f98c3a2011-09-11 18:21:29 -0400389 ApiTraceCall *call)
390{
391 //qDebug()<<"Search result = "<<result
392 // <<", call is = "<<call;
Zack Rusinad513b32011-09-25 14:33:41 -0400393 emit findResult(request, result, call);
Zack Rusin8f98c3a2011-09-11 18:21:29 -0400394}
395
Zack Rusin93e4d152011-09-13 02:23:39 -0400396void ApiTrace::findFrameStart(ApiTraceFrame *frame)
397{
Alexandr Akulich05b07162012-12-07 16:58:14 +0600398 if (!frame)
399 return;
400
Zack Rusin1a9f7af2011-09-18 19:40:47 -0400401 if (frame->isLoaded()) {
Zack Rusin93e4d152011-09-13 02:23:39 -0400402 emit foundFrameStart(frame);
403 } else {
404 emit loaderFindFrameStart(frame);
405 }
406}
407
408void ApiTrace::findFrameEnd(ApiTraceFrame *frame)
409{
Alexandr Akulich05b07162012-12-07 16:58:14 +0600410 if (!frame)
411 return;
412
Zack Rusin1a9f7af2011-09-18 19:40:47 -0400413 if (frame->isLoaded()) {
Zack Rusin93e4d152011-09-13 02:23:39 -0400414 emit foundFrameEnd(frame);
415 } else {
416 emit loaderFindFrameEnd(frame);
417 }
418}
419
Zack Rusinda7579b2011-09-13 17:33:05 -0400420void ApiTrace::findCallIndex(int index)
421{
422 int frameIdx = callInFrame(index);
423 ApiTraceFrame *frame = 0;
424
425 if (frameIdx < 0) {
426 emit foundCallIndex(0);
427 return;
428 }
429
430 frame = m_frames[frameIdx];
431
432 if (frame) {
Zack Rusin1a9f7af2011-09-18 19:40:47 -0400433 if (frame->isLoaded()) {
Zack Rusinda7579b2011-09-13 17:33:05 -0400434 ApiTraceCall *call = frame->callWithIndex(index);
435 emit foundCallIndex(call);
436 } else {
437 emit loaderFindCallIndex(index);
438 }
439 }
440}
441
442int ApiTrace::callInFrame(int callIdx) const
443{
444 unsigned numCalls = 0;
445
Dan McCabe6cc6dac2012-03-22 12:18:55 +0000446 for (int frameIdx = 0; frameIdx < m_frames.size(); ++frameIdx) {
Zack Rusinda7579b2011-09-13 17:33:05 -0400447 const ApiTraceFrame *frame = m_frames[frameIdx];
Zack Rusin1a9f7af2011-09-18 19:40:47 -0400448 unsigned numCallsInFrame = frame->isLoaded()
Zack Rusind9d9d222013-10-11 18:02:26 -0400449 ? frame->numTotalCalls()
Zack Rusinda7579b2011-09-13 17:33:05 -0400450 : frame->numChildrenToLoad();
451 unsigned firstCall = numCalls;
452 unsigned endCall = numCalls + numCallsInFrame;
453 if (firstCall <= callIdx && endCall > callIdx) {
454 return frameIdx;
455 }
456 numCalls = endCall;
457 }
458
459 return -1;
460}
461
Zack Rusin10fd4772011-09-14 01:45:12 -0400462void ApiTrace::setCallError(const ApiTraceError &error)
463{
464 int frameIdx = callInFrame(error.callIndex);
Zack Rusin10fd4772011-09-14 01:45:12 -0400465 if (frameIdx < 0) {
466 return;
467 }
Zack Rusin10fd4772011-09-14 01:45:12 -0400468
Jose Fonseca05baa462015-01-25 17:21:08 +0000469 ApiTraceFrame *frame = 0;
470 frame = m_frames[frameIdx];
Zack Rusin1a9f7af2011-09-18 19:40:47 -0400471 if (frame->isLoaded()) {
Zack Rusin10fd4772011-09-14 01:45:12 -0400472 ApiTraceCall *call = frame->callWithIndex(error.callIndex);
Jose Fonseca05baa462015-01-25 17:21:08 +0000473 // call might be null if the error is in a filtered call
474 if (call) {
475 call->setError(error.message);
476 if (call->hasError()) {
477 m_errors.insert(call);
478 } else {
479 m_errors.remove(call);
480 }
481 emit changed(call);
Zack Rusin10fd4772011-09-14 01:45:12 -0400482 }
Zack Rusin10fd4772011-09-14 01:45:12 -0400483 } else {
Zack Rusin18d094e2011-10-07 23:55:55 -0400484 loadFrame(frame);
Zack Rusin10fd4772011-09-14 01:45:12 -0400485 m_queuedErrors.append(qMakePair(frame, error));
486 }
487}
488
Zack Rusin18d094e2011-10-07 23:55:55 -0400489bool ApiTrace::isFrameLoading(ApiTraceFrame *frame) const
490{
491 return m_loadingFrames.contains(frame);
492}
493
Dan McCabec6f924e2012-06-01 13:40:05 -0700494void ApiTrace::bindThumbnails(const ImageHash &thumbnails)
Dan McCabe10bd4242012-03-05 17:20:40 -0800495{
Dan McCabec6f924e2012-06-01 13:40:05 -0700496 QHashIterator<int, QImage> i(thumbnails);
Dan McCabe10bd4242012-03-05 17:20:40 -0800497
Dan McCabec6f924e2012-06-01 13:40:05 -0700498 while (i.hasNext()) {
499 i.next();
Dan McCabe10bd4242012-03-05 17:20:40 -0800500
Dan McCabec6f924e2012-06-01 13:40:05 -0700501 if (!m_thumbnails.contains(i.key())) {
502 int callIndex = i.key();
503 const QImage &thumbnail = i.value();
Dan McCabe10bd4242012-03-05 17:20:40 -0800504
Dan McCabec6f924e2012-06-01 13:40:05 -0700505 m_thumbnails.insert(callIndex, thumbnail);
Dan McCabe10bd4242012-03-05 17:20:40 -0800506
Dan McCabec6f924e2012-06-01 13:40:05 -0700507 // find the frame associated with the call index
508 int frameIndex = 0;
509 while (frameAt(frameIndex)->lastCallIndex() < callIndex) {
510 ++frameIndex;
511 }
512
513 ApiTraceFrame *frame = frameAt(frameIndex);
514
515 // if the call was actually for a frame, ...
516 if (callIndex == frame->lastCallIndex()) {
517 frame->setThumbnail(thumbnail);
518
519 emit changed(frame);
520 } else {
521 ApiTraceCall *call = frame->callWithIndex(callIndex);
522 if (call) {
523 call->setThumbnail(thumbnail);
524
525 emit changed(call);
526 }
527 }
Dan McCabe10bd4242012-03-05 17:20:40 -0800528 }
529 }
530}
531
Dan McCabed1395322012-06-01 13:40:03 -0700532void ApiTrace::missingThumbnail(ApiTraceFrame *frame)
533{
534 missingThumbnail(frame->lastCallIndex());
535}
536
537void ApiTrace::missingThumbnail(ApiTraceCall *call)
538{
539 missingThumbnail(call->index());
540}
541
542void ApiTrace::missingThumbnail(int callIdx)
543{
544 // technically, the contain() test is redundant, since this is a set;
545 // however, it enables debugging techniques to confirm correct behavior
546 if (!m_missingThumbnails.contains(callIdx)) {
547 //qDebug() << QLatin1String("debug: new missing thumbnail: ") << callIdx;
548 m_missingThumbnails.insert(callIdx);
549 }
550}
551
552bool ApiTrace::isMissingThumbnails() const
553{
554 return !m_missingThumbnails.isEmpty();
555}
556void ApiTrace::resetMissingThumbnails()
557{
558 m_missingThumbnails.clear();
559}
560
Dan McCabe88938852012-06-01 13:40:04 -0700561void ApiTrace::iterateMissingThumbnails(void *object, ThumbnailCallback cb)
562{
563 //qDebug() << QLatin1String("debug: count of missing thumbnail list") << m_missingThumbnails.count();
564 foreach (int thumbnailIndex, m_missingThumbnails) {
565 //qDebug() << QLatin1String("debug: iterate missing thumbnail list") << thumbnailIndex;
566 (*cb)(object, thumbnailIndex);
567 }
568}
569
Zack Rusinf6667d12011-03-30 11:03:37 -0400570#include "apitrace.moc"