blob: 18556173f64451d00f4025dac798479764e9bbb3 [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
Jose Fonseca8f0846c2015-11-10 19:53:55 +000048 connect(m_loader, SIGNAL(parseProblem(const QString&)),
49 this, SIGNAL(problemLoadingTrace(const QString&)));
Zack Rusinebf971e2011-09-06 17:44:43 -040050 connect(m_loader, SIGNAL(startedParsing()),
Zack Rusinde4ea412011-03-30 11:30:08 -040051 this, SIGNAL(startedLoadingTrace()));
Zack Rusinebf971e2011-09-06 17:44:43 -040052 connect(m_loader, SIGNAL(parsed(int)),
53 this, SIGNAL(loaded(int)));
54 connect(m_loader, SIGNAL(finishedParsing()),
Zack Rusinde4ea412011-03-30 11:30:08 -040055 this, SIGNAL(finishedLoadingTrace()));
Zack Rusind809a062011-04-17 23:30:58 -040056
Zack Rusinebf971e2011-09-06 17:44:43 -040057
Zack Rusind809a062011-04-17 23:30:58 -040058 m_saver = new SaverThread(this);
Zack Rusin9af5bff2011-04-18 01:05:50 -040059 connect(m_saver, SIGNAL(traceSaved()),
60 this, SLOT(slotSaved()));
61 connect(m_saver, SIGNAL(traceSaved()),
62 this, SIGNAL(saved()));
Zack Rusinebf971e2011-09-06 17:44:43 -040063
64 m_loaderThread = new QThread();
65 m_loader->moveToThread(m_loaderThread);
66 m_loaderThread->start();
Zack Rusinf6667d12011-03-30 11:03:37 -040067}
68
69ApiTrace::~ApiTrace()
70{
Zack Rusinebf971e2011-09-06 17:44:43 -040071 m_loaderThread->quit();
72 m_loaderThread->deleteLater();
Zack Rusinf6667d12011-03-30 11:03:37 -040073 qDeleteAll(m_frames);
74 delete m_loader;
Zack Rusind809a062011-04-17 23:30:58 -040075 delete m_saver;
Zack Rusinf6667d12011-03-30 11:03:37 -040076}
77
Zack Rusinf6667d12011-03-30 11:03:37 -040078bool ApiTrace::isEmpty() const
79{
Zack Rusinc1743432011-09-13 17:58:58 -040080 return m_frames.isEmpty();
Zack Rusinf6667d12011-03-30 11:03:37 -040081}
82
83QString ApiTrace::fileName() const
84{
Zack Rusinc5929572011-09-19 03:04:40 -040085 if (edited()) {
Zack Rusin63efea82011-04-17 17:10:45 -040086 return m_tempFileName;
Zack Rusinc5929572011-09-19 03:04:40 -040087 }
Zack Rusin63efea82011-04-17 17:10:45 -040088
Zack Rusinf6667d12011-03-30 11:03:37 -040089 return m_fileName;
90}
91
José Fonseca34500442012-03-24 07:56:45 +000092const QList<ApiTraceFrame*> & ApiTrace::frames() const
Zack Rusinf6667d12011-03-30 11:03:37 -040093{
94 return m_frames;
95}
96
97ApiTraceFrame * ApiTrace::frameAt(int idx) const
98{
99 return m_frames.value(idx);
100}
101
102int ApiTrace::numFrames() const
103{
104 return m_frames.count();
105}
106
107int ApiTrace::numCallsInFrame(int idx) const
108{
109 const ApiTraceFrame *frame = frameAt(idx);
Zack Rusinc5929572011-09-19 03:04:40 -0400110 if (frame) {
Zack Rusind9d9d222013-10-11 18:02:26 -0400111 return frame->numTotalCalls();
Zack Rusinc5929572011-09-19 03:04:40 -0400112 } else {
Zack Rusinf6667d12011-03-30 11:03:37 -0400113 return 0;
Zack Rusinc5929572011-09-19 03:04:40 -0400114 }
Zack Rusinf6667d12011-03-30 11:03:37 -0400115}
116
117void ApiTrace::setFileName(const QString &name)
118{
119 if (m_fileName != name) {
120 m_fileName = name;
Zack Rusindaf82af2011-09-24 13:42:53 -0400121 m_tempFileName = QString();
Zack Rusinf6667d12011-03-30 11:03:37 -0400122
Zack Rusinca164112011-04-11 02:23:09 -0400123 m_frames.clear();
Zack Rusin30069572011-04-20 18:21:11 -0400124 m_errors.clear();
125 m_editedCalls.clear();
Zack Rusindaf82af2011-09-24 13:42:53 -0400126 m_queuedErrors.clear();
Zack Rusin30069572011-04-20 18:21:11 -0400127 m_needsSaving = false;
Zack Rusinf6667d12011-03-30 11:03:37 -0400128 emit invalidated();
129
Zack Rusinebf971e2011-09-06 17:44:43 -0400130 emit loadTrace(m_fileName);
Zack Rusinf6667d12011-03-30 11:03:37 -0400131 }
132}
133
Zack Rusinf6667d12011-03-30 11:03:37 -0400134void ApiTrace::addFrames(const QList<ApiTraceFrame*> &frames)
135{
136 int currentFrames = m_frames.count();
137 int numNewFrames = frames.count();
Zack Rusinb56e03d2011-04-20 23:58:52 -0400138
139 emit beginAddingFrames(currentFrames, numNewFrames);
140
Zack Rusinf6667d12011-03-30 11:03:37 -0400141 m_frames += frames;
142
Zack Rusinf6667d12011-03-30 11:03:37 -0400143 foreach(ApiTraceFrame *frame, frames) {
Zack Rusinebf971e2011-09-06 17:44:43 -0400144 frame->setParentTrace(this);
Zack Rusinf6667d12011-03-30 11:03:37 -0400145 }
146
Zack Rusinb56e03d2011-04-20 23:58:52 -0400147 emit endAddingFrames();
Zack Rusinf6667d12011-03-30 11:03:37 -0400148}
149
Zack Rusinf04cf8a2011-04-12 23:21:52 -0400150ApiTraceCall * ApiTrace::callWithIndex(int idx) const
151{
Zack Rusinc1743432011-09-13 17:58:58 -0400152 for (int i = 0; i < m_frames.count(); ++i) {
153 ApiTraceCall *call = m_frames[i]->callWithIndex(idx);
Zack Rusinc5929572011-09-19 03:04:40 -0400154 if (call) {
Zack Rusinf04cf8a2011-04-12 23:21:52 -0400155 return call;
Zack Rusinc5929572011-09-19 03:04:40 -0400156 }
Zack Rusinf04cf8a2011-04-12 23:21:52 -0400157 }
158 return NULL;
159}
160
Zack Rusine2dfa2e2011-04-13 01:35:03 -0400161ApiTraceState ApiTrace::defaultState() const
162{
163 ApiTraceFrame *frame = frameAt(0);
Zack Rusinc5929572011-09-19 03:04:40 -0400164 if (!frame || !frame->isLoaded() || frame->isEmpty()) {
Zack Rusine2dfa2e2011-04-13 01:35:03 -0400165 return ApiTraceState();
Zack Rusinc5929572011-09-19 03:04:40 -0400166 }
Zack Rusine2dfa2e2011-04-13 01:35:03 -0400167
Zack Rusin851d0b02011-09-14 22:04:07 -0400168 ApiTraceCall *firstCall = frame->calls().first();
169 if (!firstCall->hasState()) {
170 return ApiTraceState();
171 }
172
173 return *firstCall->state();
Zack Rusine2dfa2e2011-04-13 01:35:03 -0400174}
175
Zack Rusin661842d2011-04-17 01:59:16 -0400176void ApiTrace::callEdited(ApiTraceCall *call)
177{
Zack Rusin63efea82011-04-17 17:10:45 -0400178 if (!m_editedCalls.contains(call)) {
José Fonseca24bc5c32014-11-10 20:13:31 +0000179 // Lets generate a temp filename
180 QFileInfo fileInfo(m_fileName);
Zack Rusin63efea82011-04-17 17:10:45 -0400181 QString tempPath = QDir::tempPath();
José Fonseca24bc5c32014-11-10 20:13:31 +0000182 m_tempFileName = QDir::tempPath();
183 m_tempFileName += QDir::separator();
184 m_tempFileName += fileInfo.fileName();
185 m_tempFileName += QString::fromLatin1(".edited");
Zack Rusin63efea82011-04-17 17:10:45 -0400186 }
Zack Rusin661842d2011-04-17 01:59:16 -0400187 m_editedCalls.insert(call);
Zack Rusin9af5bff2011-04-18 01:05:50 -0400188 m_needsSaving = true;
Zack Rusin63efea82011-04-17 17:10:45 -0400189
Zack Rusin661842d2011-04-17 01:59:16 -0400190 emit changed(call);
191}
192
193void ApiTrace::callReverted(ApiTraceCall *call)
194{
195 m_editedCalls.remove(call);
Zack Rusin63efea82011-04-17 17:10:45 -0400196
197 if (m_editedCalls.isEmpty()) {
198 m_needsSaving = false;
199 }
Zack Rusin661842d2011-04-17 01:59:16 -0400200 emit changed(call);
201}
202
Zack Rusin0ddd2502011-04-17 02:34:45 -0400203bool ApiTrace::edited() const
Zack Rusin661842d2011-04-17 01:59:16 -0400204{
205 return !m_editedCalls.isEmpty();
206}
207
Zack Rusin63efea82011-04-17 17:10:45 -0400208bool ApiTrace::needsSaving() const
209{
210 return m_needsSaving;
211}
212
213void ApiTrace::save()
214{
215 QFileInfo fi(m_tempFileName);
216 QDir dir;
Zack Rusin9af5bff2011-04-18 01:05:50 -0400217 emit startedSaving();
Zack Rusin63efea82011-04-17 17:10:45 -0400218 dir.mkpath(fi.absolutePath());
Zack Rusin9b31ffc2011-09-13 23:58:45 -0400219 m_saver->saveFile(m_tempFileName,
220 m_fileName,
221 m_editedCalls);
Zack Rusin63efea82011-04-17 17:10:45 -0400222}
223
Zack Rusin9af5bff2011-04-18 01:05:50 -0400224void ApiTrace::slotSaved()
225{
226 m_needsSaving = false;
227}
228
229bool ApiTrace::isSaving() const
230{
231 return m_saver->isRunning();
232}
233
Zack Rusincc0b4912011-04-19 01:59:20 -0400234bool ApiTrace::hasErrors() const
235{
James Benton6a319062012-08-09 16:22:50 +0100236 return !m_errors.isEmpty() || !m_queuedErrors.isEmpty();
Zack Rusincc0b4912011-04-19 01:59:20 -0400237}
238
Zack Rusin3176ebe2011-09-06 21:11:36 -0400239void ApiTrace::loadFrame(ApiTraceFrame *frame)
Zack Rusinac4dd9a2011-08-28 00:38:13 -0400240{
Zack Rusin18d094e2011-10-07 23:55:55 -0400241 if (!isFrameLoading(frame)) {
242 Q_ASSERT(!frame->isLoaded());
243 m_loadingFrames.insert(frame);
244 emit requestFrame(frame);
245 }
Zack Rusin35c27932011-08-28 21:16:22 -0400246}
247
José Fonseca67964382012-03-27 23:54:30 +0100248void ApiTrace::guessedApi(int api)
249{
250 m_api = static_cast<trace::API>(api);
251}
252
253trace::API ApiTrace::api() const
254{
255 return m_api;
256}
257
Zack Rusinf682e192011-09-07 01:36:41 -0400258void ApiTrace::finishedParsing()
259{
José Fonseca0b08bc62012-03-22 16:22:33 +0000260 if (!m_frames.isEmpty()) {
261 ApiTraceFrame *firstFrame = m_frames[0];
262 if (firstFrame && !firstFrame->isLoaded()) {
263 loadFrame(firstFrame);
264 }
Zack Rusinf682e192011-09-07 01:36:41 -0400265 }
266}
267
Zack Rusin8f98c3a2011-09-11 18:21:29 -0400268void ApiTrace::loaderFrameLoaded(ApiTraceFrame *frame,
Zack Rusind9d9d222013-10-11 18:02:26 -0400269 const QVector<ApiTraceCall*> &topLevelItems,
Zack Rusin8f98c3a2011-09-11 18:21:29 -0400270 const QVector<ApiTraceCall*> &calls,
271 quint64 binaryDataSize)
Zack Rusinf682e192011-09-07 01:36:41 -0400272{
José Fonsecacaa84282013-04-11 18:54:06 +0100273 Q_ASSERT(frame->numChildrenToLoad() >= calls.size());
Zack Rusin18d094e2011-10-07 23:55:55 -0400274
275 if (!frame->isLoaded()) {
276 emit beginLoadingFrame(frame, calls.size());
Zack Rusind9d9d222013-10-11 18:02:26 -0400277 frame->setCalls(topLevelItems, calls, binaryDataSize);
Zack Rusin18d094e2011-10-07 23:55:55 -0400278 emit endLoadingFrame(frame);
279 m_loadingFrames.remove(frame);
280 }
Zack Rusin10fd4772011-09-14 01:45:12 -0400281
282 if (!m_queuedErrors.isEmpty()) {
283 QList< QPair<ApiTraceFrame*, ApiTraceError> >::iterator itr;
Evgeny Startsev1b587ca2015-07-22 19:16:33 +0100284 itr = m_queuedErrors.begin();
285 while (itr != m_queuedErrors.end()) {
Zack Rusin10fd4772011-09-14 01:45:12 -0400286 const ApiTraceError &error = (*itr).second;
287 if ((*itr).first == frame) {
288 ApiTraceCall *call = frame->callWithIndex(error.callIndex);
289
290 if (!call) {
Evgeny Startsev1b587ca2015-07-22 19:16:33 +0100291 ++itr;
Zack Rusin10fd4772011-09-14 01:45:12 -0400292 continue;
293 }
294
295 call->setError(error.message);
Evgeny Startsev1b587ca2015-07-22 19:16:33 +0100296 itr = m_queuedErrors.erase(itr);
Zack Rusin10fd4772011-09-14 01:45:12 -0400297
298 if (call->hasError()) {
299 m_errors.insert(call);
300 } else {
301 m_errors.remove(call);
302 }
303 emit changed(call);
Evgeny Startsev1b587ca2015-07-22 19:16:33 +0100304 } else {
305 ++itr;
Zack Rusin10fd4772011-09-14 01:45:12 -0400306 }
307 }
308 }
Zack Rusinf682e192011-09-07 01:36:41 -0400309}
310
Zack Rusin8f98c3a2011-09-11 18:21:29 -0400311void ApiTrace::findNext(ApiTraceFrame *frame,
312 ApiTraceCall *from,
313 const QString &str,
314 Qt::CaseSensitivity sensitivity)
315{
316 ApiTraceCall *foundCall = 0;
317 int frameIdx = m_frames.indexOf(frame);
Zack Rusinad513b32011-09-25 14:33:41 -0400318 SearchRequest request(SearchRequest::Next,
319 frame, from, str, sensitivity);
Zack Rusin8f98c3a2011-09-11 18:21:29 -0400320
Zack Rusin1a9f7af2011-09-18 19:40:47 -0400321 if (frame->isLoaded()) {
Zack Rusin8f98c3a2011-09-11 18:21:29 -0400322 foundCall = frame->findNextCall(from, str, sensitivity);
323 if (foundCall) {
Zack Rusinad513b32011-09-25 14:33:41 -0400324 emit findResult(request, SearchResult_Found, foundCall);
Zack Rusin8f98c3a2011-09-11 18:21:29 -0400325 return;
326 }
327
328 //if the frame is loaded we already searched it above
329 // so skip it
330 frameIdx += 1;
331 }
332
Zack Rusinad513b32011-09-25 14:33:41 -0400333 //for the rest of the frames we search from beginning
334 request.from = 0;
Zack Rusin8f98c3a2011-09-11 18:21:29 -0400335 for (int i = frameIdx; i < m_frames.count(); ++i) {
336 ApiTraceFrame *frame = m_frames[i];
Zack Rusinad513b32011-09-25 14:33:41 -0400337 request.frame = frame;
Zack Rusin1a9f7af2011-09-18 19:40:47 -0400338 if (!frame->isLoaded()) {
Zack Rusinad513b32011-09-25 14:33:41 -0400339 emit loaderSearch(request);
Zack Rusin8f98c3a2011-09-11 18:21:29 -0400340 return;
341 } else {
342 ApiTraceCall *call = frame->findNextCall(0, str, sensitivity);
343 if (call) {
Zack Rusinad513b32011-09-25 14:33:41 -0400344 emit findResult(request, SearchResult_Found, call);
Zack Rusin121e3162011-09-13 01:35:12 -0400345 return;
Zack Rusin8f98c3a2011-09-11 18:21:29 -0400346 }
347 }
348 }
Zack Rusinad513b32011-09-25 14:33:41 -0400349 emit findResult(request, SearchResult_Wrapped, 0);
Zack Rusin8f98c3a2011-09-11 18:21:29 -0400350}
351
352void ApiTrace::findPrev(ApiTraceFrame *frame,
353 ApiTraceCall *from,
354 const QString &str,
355 Qt::CaseSensitivity sensitivity)
356{
357 ApiTraceCall *foundCall = 0;
358 int frameIdx = m_frames.indexOf(frame);
Zack Rusinad513b32011-09-25 14:33:41 -0400359 SearchRequest request(SearchRequest::Prev,
360 frame, from, str, sensitivity);
Zack Rusin8f98c3a2011-09-11 18:21:29 -0400361
Zack Rusin1a9f7af2011-09-18 19:40:47 -0400362 if (frame->isLoaded()) {
Zack Rusin8f98c3a2011-09-11 18:21:29 -0400363 foundCall = frame->findPrevCall(from, str, sensitivity);
364 if (foundCall) {
Zack Rusinad513b32011-09-25 14:33:41 -0400365 emit findResult(request, SearchResult_Found, foundCall);
Zack Rusin8f98c3a2011-09-11 18:21:29 -0400366 return;
367 }
368
369 //if the frame is loaded we already searched it above
370 // so skip it
371 frameIdx -= 1;
372 }
373
Zack Rusinad513b32011-09-25 14:33:41 -0400374 request.from = 0;
Zack Rusin121e3162011-09-13 01:35:12 -0400375 for (int i = frameIdx; i >= 0; --i) {
Zack Rusin8f98c3a2011-09-11 18:21:29 -0400376 ApiTraceFrame *frame = m_frames[i];
Zack Rusinad513b32011-09-25 14:33:41 -0400377 request.frame = frame;
Zack Rusin1a9f7af2011-09-18 19:40:47 -0400378 if (!frame->isLoaded()) {
Zack Rusinad513b32011-09-25 14:33:41 -0400379 emit loaderSearch(request);
Zack Rusin8f98c3a2011-09-11 18:21:29 -0400380 return;
381 } else {
382 ApiTraceCall *call = frame->findPrevCall(0, str, sensitivity);
383 if (call) {
Zack Rusinad513b32011-09-25 14:33:41 -0400384 emit findResult(request, SearchResult_Found, call);
Zack Rusin121e3162011-09-13 01:35:12 -0400385 return;
Zack Rusin8f98c3a2011-09-11 18:21:29 -0400386 }
387 }
388 }
Zack Rusinad513b32011-09-25 14:33:41 -0400389 emit findResult(request, SearchResult_Wrapped, 0);
Zack Rusin8f98c3a2011-09-11 18:21:29 -0400390}
391
Zack Rusinad513b32011-09-25 14:33:41 -0400392void ApiTrace::loaderSearchResult(const ApiTrace::SearchRequest &request,
393 ApiTrace::SearchResult result,
Zack Rusin8f98c3a2011-09-11 18:21:29 -0400394 ApiTraceCall *call)
395{
396 //qDebug()<<"Search result = "<<result
397 // <<", call is = "<<call;
Zack Rusinad513b32011-09-25 14:33:41 -0400398 emit findResult(request, result, call);
Zack Rusin8f98c3a2011-09-11 18:21:29 -0400399}
400
Zack Rusin93e4d152011-09-13 02:23:39 -0400401void ApiTrace::findFrameStart(ApiTraceFrame *frame)
402{
Alexandr Akulich05b07162012-12-07 16:58:14 +0600403 if (!frame)
404 return;
405
Zack Rusin1a9f7af2011-09-18 19:40:47 -0400406 if (frame->isLoaded()) {
Zack Rusin93e4d152011-09-13 02:23:39 -0400407 emit foundFrameStart(frame);
408 } else {
409 emit loaderFindFrameStart(frame);
410 }
411}
412
413void ApiTrace::findFrameEnd(ApiTraceFrame *frame)
414{
Alexandr Akulich05b07162012-12-07 16:58:14 +0600415 if (!frame)
416 return;
417
Zack Rusin1a9f7af2011-09-18 19:40:47 -0400418 if (frame->isLoaded()) {
Zack Rusin93e4d152011-09-13 02:23:39 -0400419 emit foundFrameEnd(frame);
420 } else {
421 emit loaderFindFrameEnd(frame);
422 }
423}
424
Zack Rusinda7579b2011-09-13 17:33:05 -0400425void ApiTrace::findCallIndex(int index)
426{
427 int frameIdx = callInFrame(index);
428 ApiTraceFrame *frame = 0;
429
430 if (frameIdx < 0) {
431 emit foundCallIndex(0);
432 return;
433 }
434
435 frame = m_frames[frameIdx];
436
437 if (frame) {
Zack Rusin1a9f7af2011-09-18 19:40:47 -0400438 if (frame->isLoaded()) {
Zack Rusinda7579b2011-09-13 17:33:05 -0400439 ApiTraceCall *call = frame->callWithIndex(index);
440 emit foundCallIndex(call);
441 } else {
442 emit loaderFindCallIndex(index);
443 }
444 }
445}
446
447int ApiTrace::callInFrame(int callIdx) const
448{
449 unsigned numCalls = 0;
450
Dan McCabe6cc6dac2012-03-22 12:18:55 +0000451 for (int frameIdx = 0; frameIdx < m_frames.size(); ++frameIdx) {
Zack Rusinda7579b2011-09-13 17:33:05 -0400452 const ApiTraceFrame *frame = m_frames[frameIdx];
Zack Rusin1a9f7af2011-09-18 19:40:47 -0400453 unsigned numCallsInFrame = frame->isLoaded()
Zack Rusind9d9d222013-10-11 18:02:26 -0400454 ? frame->numTotalCalls()
Zack Rusinda7579b2011-09-13 17:33:05 -0400455 : frame->numChildrenToLoad();
456 unsigned firstCall = numCalls;
457 unsigned endCall = numCalls + numCallsInFrame;
458 if (firstCall <= callIdx && endCall > callIdx) {
459 return frameIdx;
460 }
461 numCalls = endCall;
462 }
463
464 return -1;
465}
466
Zack Rusin10fd4772011-09-14 01:45:12 -0400467void ApiTrace::setCallError(const ApiTraceError &error)
468{
469 int frameIdx = callInFrame(error.callIndex);
Zack Rusin10fd4772011-09-14 01:45:12 -0400470 if (frameIdx < 0) {
471 return;
472 }
Zack Rusin10fd4772011-09-14 01:45:12 -0400473
Jose Fonseca05baa462015-01-25 17:21:08 +0000474 ApiTraceFrame *frame = 0;
475 frame = m_frames[frameIdx];
Zack Rusin1a9f7af2011-09-18 19:40:47 -0400476 if (frame->isLoaded()) {
Zack Rusin10fd4772011-09-14 01:45:12 -0400477 ApiTraceCall *call = frame->callWithIndex(error.callIndex);
Jose Fonseca05baa462015-01-25 17:21:08 +0000478 // call might be null if the error is in a filtered call
479 if (call) {
480 call->setError(error.message);
481 if (call->hasError()) {
482 m_errors.insert(call);
483 } else {
484 m_errors.remove(call);
485 }
486 emit changed(call);
Zack Rusin10fd4772011-09-14 01:45:12 -0400487 }
Zack Rusin10fd4772011-09-14 01:45:12 -0400488 } else {
Zack Rusin18d094e2011-10-07 23:55:55 -0400489 loadFrame(frame);
Zack Rusin10fd4772011-09-14 01:45:12 -0400490 m_queuedErrors.append(qMakePair(frame, error));
491 }
492}
493
Zack Rusin18d094e2011-10-07 23:55:55 -0400494bool ApiTrace::isFrameLoading(ApiTraceFrame *frame) const
495{
496 return m_loadingFrames.contains(frame);
497}
498
Dan McCabec6f924e2012-06-01 13:40:05 -0700499void ApiTrace::bindThumbnails(const ImageHash &thumbnails)
Dan McCabe10bd4242012-03-05 17:20:40 -0800500{
Dan McCabec6f924e2012-06-01 13:40:05 -0700501 QHashIterator<int, QImage> i(thumbnails);
Dan McCabe10bd4242012-03-05 17:20:40 -0800502
Dan McCabec6f924e2012-06-01 13:40:05 -0700503 while (i.hasNext()) {
504 i.next();
Dan McCabe10bd4242012-03-05 17:20:40 -0800505
Dan McCabec6f924e2012-06-01 13:40:05 -0700506 if (!m_thumbnails.contains(i.key())) {
507 int callIndex = i.key();
508 const QImage &thumbnail = i.value();
Dan McCabe10bd4242012-03-05 17:20:40 -0800509
Dan McCabec6f924e2012-06-01 13:40:05 -0700510 m_thumbnails.insert(callIndex, thumbnail);
Dan McCabe10bd4242012-03-05 17:20:40 -0800511
Dan McCabec6f924e2012-06-01 13:40:05 -0700512 // find the frame associated with the call index
513 int frameIndex = 0;
514 while (frameAt(frameIndex)->lastCallIndex() < callIndex) {
515 ++frameIndex;
516 }
517
518 ApiTraceFrame *frame = frameAt(frameIndex);
519
520 // if the call was actually for a frame, ...
521 if (callIndex == frame->lastCallIndex()) {
522 frame->setThumbnail(thumbnail);
523
524 emit changed(frame);
525 } else {
526 ApiTraceCall *call = frame->callWithIndex(callIndex);
527 if (call) {
528 call->setThumbnail(thumbnail);
529
530 emit changed(call);
531 }
532 }
Dan McCabe10bd4242012-03-05 17:20:40 -0800533 }
534 }
535}
536
Dan McCabed1395322012-06-01 13:40:03 -0700537void ApiTrace::missingThumbnail(ApiTraceFrame *frame)
538{
539 missingThumbnail(frame->lastCallIndex());
540}
541
542void ApiTrace::missingThumbnail(ApiTraceCall *call)
543{
544 missingThumbnail(call->index());
545}
546
547void ApiTrace::missingThumbnail(int callIdx)
548{
549 // technically, the contain() test is redundant, since this is a set;
550 // however, it enables debugging techniques to confirm correct behavior
551 if (!m_missingThumbnails.contains(callIdx)) {
552 //qDebug() << QLatin1String("debug: new missing thumbnail: ") << callIdx;
553 m_missingThumbnails.insert(callIdx);
554 }
555}
556
557bool ApiTrace::isMissingThumbnails() const
558{
559 return !m_missingThumbnails.isEmpty();
560}
561void ApiTrace::resetMissingThumbnails()
562{
563 m_missingThumbnails.clear();
564}
565
Dan McCabe88938852012-06-01 13:40:04 -0700566void ApiTrace::iterateMissingThumbnails(void *object, ThumbnailCallback cb)
567{
568 //qDebug() << QLatin1String("debug: count of missing thumbnail list") << m_missingThumbnails.count();
569 foreach (int thumbnailIndex, m_missingThumbnails) {
570 //qDebug() << QLatin1String("debug: iterate missing thumbnail list") << thumbnailIndex;
571 (*cb)(object, thumbnailIndex);
572 }
573}
574
Zack Rusinf6667d12011-03-30 11:03:37 -0400575#include "apitrace.moc"