]> git.cworth.org Git - apitrace/blob - gui/apitrace.cpp
Various cleanups.
[apitrace] / gui / apitrace.cpp
1 #include "apitrace.h"
2
3 #include "loaderthread.h"
4 #include "saverthread.h"
5
6 #include <QDir>
7
8 ApiTrace::ApiTrace()
9     : m_frameMarker(ApiTrace::FrameMarker_SwapBuffers),
10       m_needsSaving(false)
11 {
12     m_loader = new LoaderThread(this);
13     connect(m_loader, SIGNAL(parsedFrames(const QList<ApiTraceFrame*>)),
14             this, SLOT(addFrames(const QList<ApiTraceFrame*>)));
15     connect(m_loader, SIGNAL(started()),
16             this, SIGNAL(startedLoadingTrace()));
17     connect(m_loader, SIGNAL(finished()),
18             this, SIGNAL(finishedLoadingTrace()));
19
20     m_saver = new SaverThread(this);
21     connect(m_saver, SIGNAL(traceSaved()),
22             this, SLOT(slotSaved()));
23     connect(m_saver, SIGNAL(traceSaved()),
24             this, SIGNAL(saved()));
25 }
26
27 ApiTrace::~ApiTrace()
28 {
29     qDeleteAll(m_calls);
30     qDeleteAll(m_frames);
31     delete m_loader;
32     delete m_saver;
33 }
34
35 bool ApiTrace::isCallAFrameMarker(const ApiTraceCall *call,
36                                   ApiTrace::FrameMarker marker)
37 {
38     if (!call)
39         return false;
40
41     switch (marker) {
42     case FrameMarker_SwapBuffers:
43         return call->name().contains(QLatin1String("SwapBuffers"));
44     case FrameMarker_Flush:
45         return call->name() == QLatin1String("glFlush");
46     case FrameMarker_Finish:
47         return call->name() == QLatin1String("glFinish");
48     case FrameMarker_Clear:
49         return call->name() == QLatin1String("glClear");
50     }
51
52     Q_ASSERT(!"unknown frame marker");
53
54     return false;
55 }
56
57 bool ApiTrace::isEmpty() const
58 {
59     return m_calls.isEmpty();
60 }
61
62 QString ApiTrace::fileName() const
63 {
64     if (edited())
65         return m_tempFileName;
66
67     return m_fileName;
68 }
69
70 ApiTrace::FrameMarker ApiTrace::frameMarker() const
71 {
72     return m_frameMarker;
73 }
74
75 QList<ApiTraceCall*> ApiTrace::calls() const
76 {
77     return m_calls;
78 }
79
80 ApiTraceCall * ApiTrace::callAt(int idx) const
81 {
82     return m_calls.value(idx);
83 }
84
85 int ApiTrace::numCalls() const
86 {
87     return m_calls.count();
88 }
89
90 QList<ApiTraceFrame*> ApiTrace::frames() const
91 {
92     return m_frames;
93 }
94
95 ApiTraceFrame * ApiTrace::frameAt(int idx) const
96 {
97     return m_frames.value(idx);
98 }
99
100 int ApiTrace::numFrames() const
101 {
102     return m_frames.count();
103 }
104
105 int ApiTrace::numCallsInFrame(int idx) const
106 {
107     const ApiTraceFrame *frame = frameAt(idx);
108     if (frame)
109         return frame->calls.count();
110     else
111         return 0;
112 }
113
114 void ApiTrace::setFileName(const QString &name)
115 {
116     if (m_fileName != name) {
117         m_fileName = name;
118
119         if (m_loader->isRunning()) {
120             m_loader->terminate();
121             m_loader->wait();
122         }
123         m_frames.clear();
124         m_calls.clear();
125         m_errors.clear();
126         m_editedCalls.clear();
127         m_needsSaving = false;
128         emit invalidated();
129
130         m_loader->loadFile(m_fileName);
131     }
132 }
133
134 void ApiTrace::setFrameMarker(FrameMarker marker)
135 {
136     if (m_frameMarker != marker) {
137         emit framesInvalidated();
138
139         qDeleteAll(m_frames);
140         m_frames.clear();
141         detectFrames();
142     }
143 }
144
145 void ApiTrace::addFrames(const QList<ApiTraceFrame*> &frames)
146 {
147     int currentFrames = m_frames.count();
148     int numNewFrames = frames.count();
149     m_frames += frames;
150
151     int currentCalls = m_calls.count();
152     int numNewCalls = 0;
153     foreach(ApiTraceFrame *frame, frames) {
154         frame->setParentTrace(this);
155         numNewCalls += frame->calls.count();
156         m_calls += frame->calls;
157     }
158
159     emit framesAdded(currentFrames, numNewFrames);
160     emit callsAdded(currentCalls, numNewCalls);
161 }
162
163 void ApiTrace::detectFrames()
164 {
165     if (m_calls.isEmpty())
166         return;
167
168     ApiTraceFrame *currentFrame = 0;
169     foreach(ApiTraceCall *apiCall, m_calls) {
170         if (!currentFrame) {
171             currentFrame = new ApiTraceFrame();
172             currentFrame->setParentTrace(this);
173             currentFrame->number = m_frames.count();
174         }
175         apiCall->setParentFrame(currentFrame);
176         currentFrame->calls.append(apiCall);
177         if (ApiTrace::isCallAFrameMarker(apiCall,
178                                          m_frameMarker)) {
179             m_frames.append(currentFrame);
180             currentFrame = 0;
181         }
182     }
183     //last frames won't have markers
184     //  it's just a bunch of Delete calls for every object
185     //  after the last SwapBuffers
186     if (currentFrame) {
187         m_frames.append(currentFrame);
188         currentFrame = 0;
189     }
190     emit framesAdded(0, m_frames.count());
191 }
192
193 ApiTraceCall * ApiTrace::callWithIndex(int idx) const
194 {
195     for (int i = 0; i < m_calls.count(); ++i) {
196         ApiTraceCall *call = m_calls[i];
197         if (call->index() == idx)
198             return call;
199     }
200     return NULL;
201 }
202
203 ApiTraceState ApiTrace::defaultState() const
204 {
205     ApiTraceFrame *frame = frameAt(0);
206     if (!frame)
207         return ApiTraceState();
208
209     return frame->state();
210 }
211
212 void ApiTrace::callEdited(ApiTraceCall *call)
213 {
214     if (!m_editedCalls.contains(call)) {
215         //lets generate a temp filename
216         QString tempPath = QDir::tempPath();
217         m_tempFileName = QString::fromLatin1("%1/%2.edited")
218                          .arg(tempPath)
219                          .arg(m_fileName);
220     }
221     m_editedCalls.insert(call);
222     m_needsSaving = true;
223
224     emit changed(call);
225 }
226
227 void ApiTrace::callReverted(ApiTraceCall *call)
228 {
229     m_editedCalls.remove(call);
230
231     if (m_editedCalls.isEmpty()) {
232         m_needsSaving = false;
233     }
234     emit changed(call);
235 }
236
237 bool ApiTrace::edited() const
238 {
239     return !m_editedCalls.isEmpty();
240 }
241
242 bool ApiTrace::needsSaving() const
243 {
244     return m_needsSaving;
245 }
246
247 void ApiTrace::save()
248 {
249     QFileInfo fi(m_tempFileName);
250     QDir dir;
251     emit startedSaving();
252     dir.mkpath(fi.absolutePath());
253     m_saver->saveFile(m_tempFileName, m_calls);
254 }
255
256 void ApiTrace::slotSaved()
257 {
258     m_needsSaving = false;
259 }
260
261 bool ApiTrace::isSaving() const
262 {
263     return m_saver->isRunning();
264 }
265
266 void ApiTrace::callError(ApiTraceCall *call)
267 {
268     Q_ASSERT(call);
269
270     if (call->hasError())
271         m_errors.insert(call);
272     else
273         m_errors.remove(call);
274
275     emit changed(call);
276 }
277
278 bool ApiTrace::hasErrors() const
279 {
280     return !m_errors.isEmpty();
281 }
282
283 #include "apitrace.moc"