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