#include "apitracemodel.h"
#include "apitracecall.h"
-#include "loaderthread.h"
+#include "traceloader.h"
#include "trace_parser.hpp"
+#include <QBuffer>
#include <QDebug>
#include <QImage>
#include <QVariant>
const QString stateText = tr("State info available.");
if (itm->type() == ApiTraceEvent::Call) {
ApiTraceCall *call = static_cast<ApiTraceCall*>(itm);
- if (call->state().isEmpty())
+ if (!call->hasState())
return QString::fromLatin1("%1) <b>%2</b>")
- .arg(call->index)
- .arg(call->name);
+ .arg(call->index())
+ .arg(call->name());
else
return QString::fromLatin1("%1) <b>%2</b><br/>%3")
- .arg(call->index)
- .arg(call->name)
+ .arg(call->index())
+ .arg(call->name())
.arg(stateText);
} else {
+ const char *htmlTempl =
+ "<div>\n"
+ "<div>\n"
+ "%1"
+ "<span style=\"font-weight:bold; font-size:large; vertical-align:center; padding-bottom: 30px \">\n"
+ "Frame %2</span>\n"
+ "</div>\n"
+ "<div >%3 calls%4</div>\n"
+ "</div>\n";
+
+
ApiTraceFrame *frame = static_cast<ApiTraceFrame*>(itm);
- QString text = frame->staticText().text();
- if (frame->state().isEmpty())
- return QString::fromLatin1("<b>%1</b>").arg(text);
- else
- return QString::fromLatin1("<b>%1</b><br/>%2")
- .arg(text)
- .arg(stateText);
+ QString thumbStr, sizeStr;
+
+ if (frame->hasState()) {
+ static const char *imgTempl =
+ "<img style=\"float:left;\" "
+ "src=\"data:image/png;base64,%1\"/>\n";
+ static const char *sizeTempl =
+ ", %1kb";
+
+ ApiFramebuffer fbo = frame->state()->colorBuffer();
+ QImage thumb = fbo.thumb();
+ if (!thumb.isNull()) {
+ QByteArray ba;
+ QBuffer buffer(&ba);
+ buffer.open(QIODevice::WriteOnly);
+ thumb.save(&buffer, "PNG");
+ thumbStr = tr(imgTempl).arg(
+ QString(buffer.data().toBase64()));
+ }
+
+ int binaryDataSize = frame->binaryDataSize() / 1024;
+ if (binaryDataSize > 0) {
+ sizeStr = tr(sizeTempl).arg(binaryDataSize);
+ }
+ }
+
+ int numCalls = frame->isLoaded()
+ ? frame->numChildren()
+ : frame->numChildrenToLoad();
+
+ return tr(htmlTempl)
+ .arg(thumbStr)
+ .arg(frame->number)
+ .arg(numCalls)
+ .arg(sizeStr);
}
}
case ApiTraceModel::EventRole:
QModelIndex ApiTraceModel::index(int row, int column,
const QModelIndex &parent) const
{
- if (parent.isValid() && parent.column() != 0)
+ if ((parent.isValid() && parent.column() != 0) || column != 0)
return QModelIndex();
ApiTraceEvent *event = item(parent);
return QModelIndex();
}
ApiTraceFrame *frame = static_cast<ApiTraceFrame*>(event);
- ApiTraceCall *call = frame->calls.value(row);
+ ApiTraceCall *call = frame->call(row);
if (call)
return createIndex(row, column, call);
else
ApiTraceEvent *event = item(parent);
if (event && event->type() == ApiTraceEvent::Frame) {
ApiTraceFrame *frame = static_cast<ApiTraceFrame*>(event);
- return !frame->calls.isEmpty();
+ return !frame->isEmpty();
} else
return false;
} else {
ApiTraceEvent *event = item(index);
if (event && event->type() == ApiTraceEvent::Call) {
ApiTraceCall *call = static_cast<ApiTraceCall*>(event);
- Q_ASSERT(call->parentFrame);
- return createIndex(call->parentFrame->number,
- 0, call->parentFrame);
+ Q_ASSERT(call->parentFrame());
+ return createIndex(call->parentFrame()->number,
+ 0, call->parentFrame());
}
return QModelIndex();
}
ApiTraceFrame *frame = static_cast<ApiTraceFrame*>(event);
if (frame)
- return frame->calls.count();
+ return frame->numChildren();
return 0;
}
if (m_trace)
disconnect(m_trace);
m_trace = trace;
+ connect(m_trace, SIGNAL(invalidated()),
+ this, SLOT(invalidateFrames()));
connect(m_trace, SIGNAL(framesInvalidated()),
this, SLOT(invalidateFrames()));
- connect(m_trace, SIGNAL(framesAdded(int, int)),
- this, SLOT(appendFrames(int, int)));
+ connect(m_trace, SIGNAL(beginAddingFrames(int, int)),
+ this, SLOT(beginAddingFrames(int, int)));
+ connect(m_trace, SIGNAL(endAddingFrames()),
+ this, SLOT(endAddingFrames()));
+ connect(m_trace, SIGNAL(changed(ApiTraceEvent*)),
+ this, SLOT(changed(ApiTraceEvent*)));
+ connect(m_trace, SIGNAL(beginLoadingFrame(ApiTraceFrame*,int)),
+ this, SLOT(beginLoadingFrame(ApiTraceFrame*,int)));
+ connect(m_trace, SIGNAL(endLoadingFrame(ApiTraceFrame*)),
+ this, SLOT(endLoadingFrame(ApiTraceFrame*)));
+
}
const ApiTrace * ApiTraceModel::apiTrace() const
endResetModel();
}
-void ApiTraceModel::appendFrames(int oldCount, int numAdded)
+void ApiTraceModel::beginAddingFrames(int oldCount, int numAdded)
{
beginInsertRows(QModelIndex(), oldCount,
oldCount + numAdded - 1);
- endInsertRows();
}
ApiTraceEvent * ApiTraceModel::item(const QModelIndex &index) const
if (event->type() == ApiTraceEvent::Call) {
ApiTraceCall *call = static_cast<ApiTraceCall*>(event);
- ApiTraceFrame *frame = call->parentFrame;
- int row = frame->calls.indexOf(call);
+ ApiTraceFrame *frame = call->parentFrame();
+ int row = frame->callIndex(call);
QModelIndex index = createIndex(row, 0, call);
emit dataChanged(index, index);
} else if (event->type() == ApiTraceEvent::Frame) {
ApiTraceFrame *frame = static_cast<ApiTraceFrame*>(event);
- const QList<ApiTraceFrame*> frames = m_trace->frames();
+ const QList<ApiTraceFrame*> & frames = m_trace->frames();
int row = frames.indexOf(frame);
QModelIndex index = createIndex(row, 0, frame);
emit dataChanged(index, index);
}
}
-QModelIndex ApiTraceModel::callIndex(int callNum) const
+QModelIndex ApiTraceModel::indexForCall(ApiTraceCall *call) const
{
- ApiTraceCall *call = m_trace->callAt(callNum);
-
if (!call) {
return QModelIndex();
}
- ApiTraceFrame *frame = call->parentFrame;
+ ApiTraceFrame *frame = call->parentFrame();
Q_ASSERT(frame);
- int row = frame->calls.indexOf(call);
+ int row = frame->callIndex(call);
if (row < 0) {
- qDebug() << "Couldn't find call num "<<callNum<<" inside parent!";
+ qDebug() << "Couldn't find call num "<<call->index()<<" inside parent!";
return QModelIndex();
}
return createIndex(row, 0, call);
}
+void ApiTraceModel::changed(ApiTraceEvent *event)
+{
+ if (event->type() == ApiTraceEvent::Call) {
+ callChanged(static_cast<ApiTraceCall*>(event));
+ } else if (event->type() == ApiTraceEvent::Frame) {
+ frameChanged(static_cast<ApiTraceFrame*>(event));
+ }
+}
+
+void ApiTraceModel::callChanged(ApiTraceCall *call)
+{
+ ApiTrace *trace = call->parentFrame()->parentTrace();
+
+#if 0
+ qDebug()<<"Call changed = "<<call->edited();
+ qDebug()<<"\ttrace edited = "<<trace->edited();
+ qDebug()<<"\ttrace file = "<<trace->fileName();
+ qDebug()<<"\ttrace needs saving = "<<trace->needsSaving();
+#endif
+
+ Q_ASSERT(trace);
+ if (trace->needsSaving())
+ trace->save();
+
+ ApiTraceFrame *frame = call->parentFrame();
+ int row = frame->callIndex(call);
+ QModelIndex index = createIndex(row, 0, call);
+ emit dataChanged(index, index);
+}
+
+void ApiTraceModel::frameChanged(ApiTraceFrame *frame)
+{
+ const QList<ApiTraceFrame*> & frames = m_trace->frames();
+ int row = frames.indexOf(frame);
+ QModelIndex index = createIndex(row, 0, frame);
+ emit dataChanged(index, index);
+}
+
+void ApiTraceModel::endAddingFrames()
+{
+ endInsertRows();
+}
+
+bool ApiTraceModel::canFetchMore(const QModelIndex &parent) const
+{
+ if (parent.isValid()) {
+ ApiTraceEvent *event = item(parent);
+ if (event && event->type() == ApiTraceEvent::Frame) {
+ ApiTraceFrame *frame = static_cast<ApiTraceFrame*>(event);
+ return !frame->isLoaded() && !m_loadingFrames.contains(frame);
+ } else
+ return false;
+ } else {
+ return false;
+ }
+}
+
+void ApiTraceModel::fetchMore(const QModelIndex &parent)
+{
+ if (parent.isValid()) {
+ ApiTraceEvent *event = item(parent);
+ if (event && event->type() == ApiTraceEvent::Frame) {
+ ApiTraceFrame *frame = static_cast<ApiTraceFrame*>(event);
+ QModelIndex index = createIndex(frame->number, 0, frame);
+
+ Q_ASSERT(!frame->isLoaded());
+ m_loadingFrames.insert(frame);
+
+ m_trace->loadFrame(frame);
+ }
+ }
+}
+
+void ApiTraceModel::beginLoadingFrame(ApiTraceFrame *frame, int numAdded)
+{
+ QModelIndex index = createIndex(frame->number, 0, frame);
+ beginInsertRows(index, 0, numAdded - 1);
+}
+
+void ApiTraceModel::endLoadingFrame(ApiTraceFrame *frame)
+{
+ QModelIndex index = createIndex(frame->number, 0, frame);
+#if 0
+ qDebug()<<"Frame loaded = "<<frame->loaded();
+ qDebug()<<"\tframe idx = "<<frame->number;
+ qDebug()<<"\tis empty = "<<frame->isEmpty();
+ qDebug()<<"\tnum children = "<<frame->numChildren();
+ qDebug()<<"\tindex is "<<index;
+#endif
+
+ endInsertRows();
+
+ emit dataChanged(index, index);
+
+ m_loadingFrames.remove(frame);
+}
+
#include "apitracemodel.moc"