]> git.cworth.org Git - apitrace/blob - gui/apitrace.cpp
Merge branch 'trace-editing'
[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         emit invalidated();
126
127         m_loader->loadFile(m_fileName);
128     }
129 }
130
131 void ApiTrace::setFrameMarker(FrameMarker marker)
132 {
133     if (m_frameMarker != marker) {
134         emit framesInvalidated();
135
136         qDeleteAll(m_frames);
137         m_frames.clear();
138         detectFrames();
139     }
140 }
141
142 void ApiTrace::addFrames(const QList<ApiTraceFrame*> &frames)
143 {
144     int currentFrames = m_frames.count();
145     int numNewFrames = frames.count();
146     m_frames += frames;
147
148     int currentCalls = m_calls.count();
149     int numNewCalls = 0;
150     foreach(ApiTraceFrame *frame, frames) {
151         frame->setParentTrace(this);
152         numNewCalls += frame->calls.count();
153         m_calls += frame->calls;
154     }
155
156     emit framesAdded(currentFrames, numNewFrames);
157     emit callsAdded(currentCalls, numNewCalls);
158 }
159
160 void ApiTrace::detectFrames()
161 {
162     if (m_calls.isEmpty())
163         return;
164
165     ApiTraceFrame *currentFrame = 0;
166     foreach(ApiTraceCall *apiCall, m_calls) {
167         if (!currentFrame) {
168             currentFrame = new ApiTraceFrame();
169             currentFrame->setParentTrace(this);
170             currentFrame->number = m_frames.count();
171         }
172         apiCall->setParentFrame(currentFrame);
173         currentFrame->calls.append(apiCall);
174         if (ApiTrace::isCallAFrameMarker(apiCall,
175                                          m_frameMarker)) {
176             m_frames.append(currentFrame);
177             currentFrame = 0;
178         }
179     }
180     //last frames won't have markers
181     //  it's just a bunch of Delete calls for every object
182     //  after the last SwapBuffers
183     if (currentFrame) {
184         m_frames.append(currentFrame);
185         currentFrame = 0;
186     }
187     emit framesAdded(0, m_frames.count());
188 }
189
190 ApiTraceCall * ApiTrace::callWithIndex(int idx) const
191 {
192     for (int i = 0; i < m_calls.count(); ++i) {
193         ApiTraceCall *call = m_calls[i];
194         if (call->index() == idx)
195             return call;
196     }
197     return NULL;
198 }
199
200 ApiTraceState ApiTrace::defaultState() const
201 {
202     ApiTraceFrame *frame = frameAt(0);
203     if (!frame)
204         return ApiTraceState();
205
206     return frame->state();
207 }
208
209 void ApiTrace::callEdited(ApiTraceCall *call)
210 {
211     if (!m_editedCalls.contains(call)) {
212         //lets generate a temp filename
213         QString tempPath = QDir::tempPath();
214         m_tempFileName = QString::fromLatin1("%1/%2.edited")
215                          .arg(tempPath)
216                          .arg(m_fileName);
217     }
218     m_editedCalls.insert(call);
219     m_needsSaving = true;
220
221     emit changed(call);
222 }
223
224 void ApiTrace::callReverted(ApiTraceCall *call)
225 {
226     m_editedCalls.remove(call);
227
228     if (m_editedCalls.isEmpty()) {
229         m_needsSaving = false;
230     }
231     emit changed(call);
232 }
233
234 bool ApiTrace::edited() const
235 {
236     return !m_editedCalls.isEmpty();
237 }
238
239 bool ApiTrace::needsSaving() const
240 {
241     return m_needsSaving;
242 }
243
244 void ApiTrace::save()
245 {
246     QFileInfo fi(m_tempFileName);
247     QDir dir;
248     emit startedSaving();
249     dir.mkpath(fi.absolutePath());
250     m_saver->saveFile(m_tempFileName, m_calls);
251 }
252
253 void ApiTrace::slotSaved()
254 {
255     m_needsSaving = false;
256 }
257
258 bool ApiTrace::isSaving() const
259 {
260     return m_saver->isRunning();
261 }
262
263 #include "apitrace.moc"