#include "trace_parser.hpp"
#include <QDebug>
+#include <QImage>
#include <QVariant>
ApiTraceModel::ApiTraceModel(QObject *parent)
- : QAbstractItemModel(parent)
+ : QAbstractItemModel(parent),
+ m_trace(0)
{
- m_loader = new LoaderThread();
-
- connect(m_loader, SIGNAL(parsedCalls(const QList<Trace::Call*>&)),
- SLOT(appendCalls(const QList<Trace::Call*>&)));
}
ApiTraceModel::~ApiTraceModel()
{
- qDeleteAll(m_calls);
- delete m_loader;
+ m_trace = 0;
}
QVariant ApiTraceModel::data(const QModelIndex &index, int role) const
if (!index.isValid())
return QVariant();
- if (role != Qt::DisplayRole)
+ if (index.column() != 0)
return QVariant();
- ApiTraceCall *item = m_calls.value(index.row());
-
- if (!item)
+ ApiTraceEvent *itm = item(index);
+ if (!itm) {
return QVariant();
+ }
- switch (index.column()) {
- case 0: {
- QString str;
- str += QString::number(index.row());
- str += QLatin1String(") ");
- str += item->name;
- str += QLatin1String("(");
- for (int i = 0; i < item->argNames.count(); ++i) {
- str += item->argNames[i];
- str += QString::fromLatin1(" = ");
- str += apiVariantToString(item->argValues[i]);
- if (i < item->argNames.count() - 1)
- str += QString::fromLatin1(", ");
- }
- str += QLatin1String(")");
-
- if (item->returnValue.isValid()) {
- str += QLatin1String(" = ");
- str += apiVariantToString(item->returnValue);
+ switch (role) {
+ case Qt::DisplayRole:
+ return itm->staticText().text();
+ case Qt::DecorationRole:
+ return QImage();
+ case Qt::ToolTipRole: {
+ const QString stateText = tr("State info available.");
+ if (itm->type() == ApiTraceEvent::Call) {
+ ApiTraceCall *call = static_cast<ApiTraceCall*>(itm);
+ if (call->state().isEmpty())
+ return QString::fromLatin1("%1) <b>%2</b>")
+ .arg(call->index)
+ .arg(call->name);
+ else
+ return QString::fromLatin1("%1) <b>%2</b><br/>%3")
+ .arg(call->index)
+ .arg(call->name)
+ .arg(stateText);
+ } else {
+ 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);
}
- return str;
}
- default:
- return QVariant();
+ case ApiTraceModel::EventRole:
+ return QVariant::fromValue(itm);
}
+
+ return QVariant();
}
Qt::ItemFlags ApiTraceModel::flags(const QModelIndex &index) const
if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
switch (section) {
case 0:
- return tr("Function");
+ return tr("Events");
+ case 1:
+ return tr("Flags");
default:
//fall through
break;
if (parent.isValid() && parent.column() != 0)
return QModelIndex();
- ApiTraceCall *call = m_calls.value(row);
-
- if (call)
- return createIndex(row, column, call);
- else
- return QModelIndex();
+ ApiTraceEvent *event = item(parent);
+ if (event) {
+ if (event->type() != ApiTraceEvent::Frame) {
+ qDebug()<<"got a valid parent but it's not a frame "<<event->type();
+ return QModelIndex();
+ }
+ ApiTraceFrame *frame = static_cast<ApiTraceFrame*>(event);
+ ApiTraceCall *call = frame->calls.value(row);
+ if (call)
+ return createIndex(row, column, call);
+ else
+ return QModelIndex();
+ } else {
+ ApiTraceFrame *frame = m_trace->frameAt(row);
+ if (frame)
+ return createIndex(row, column, frame);
+ else
+ return QModelIndex();
+ }
+ return QModelIndex();
}
bool ApiTraceModel::hasChildren(const QModelIndex &parent) const
{
- return parent.isValid() ? false : (rowCount() > 0);
+ if (parent.isValid()) {
+ ApiTraceEvent *event = item(parent);
+ if (event && event->type() == ApiTraceEvent::Frame) {
+ ApiTraceFrame *frame = static_cast<ApiTraceFrame*>(event);
+ return !frame->calls.isEmpty();
+ } else
+ return false;
+ } else {
+ return (rowCount() > 0);
+ }
}
QModelIndex ApiTraceModel::parent(const QModelIndex &index) const
if (!index.isValid())
return QModelIndex();
- //list for now
+ 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);
+ }
return QModelIndex();
}
int ApiTraceModel::rowCount(const QModelIndex &parent) const
{
- return m_calls.count();
+ if (!parent.isValid())
+ return m_trace->numFrames();
+
+ ApiTraceEvent *event = item(parent);
+ if (!event || event->type() == ApiTraceEvent::Call)
+ return 0;
+
+ ApiTraceFrame *frame = static_cast<ApiTraceFrame*>(event);
+ if (frame)
+ return frame->calls.count();
+
+ return 0;
}
int ApiTraceModel::columnCount(const QModelIndex &parent) const
{
- return parent.isValid() ? 0 : 1;
+ return 1;
}
-
bool ApiTraceModel::insertRows(int position, int rows,
const QModelIndex &parent)
{
Q_UNUSED(parent);
- if (m_calls.count() <= position)
- return false;
-
beginRemoveRows(parent, position, position + rows - 1);
- for (int i = 0; i < rows; ++i) {
- ApiTraceCall *call = m_calls.value(i);
- m_calls.removeAt(i);
- delete call;
- }
+ //XXX remove it from ApiTrace
endRemoveRows();
return success;
}
-void ApiTraceModel::loadTraceFile(const QString &fileName)
+void ApiTraceModel::setApiTrace(ApiTrace *trace)
{
- if (m_loader->isRunning()) {
- m_loader->terminate();
- m_loader->wait();
- }
- removeRows(0, m_calls.count(), QModelIndex());
-
- m_loader->loadFile(fileName);
+ if (m_trace == trace)
+ return;
+ if (m_trace)
+ disconnect(m_trace);
+ m_trace = trace;
+ connect(m_trace, SIGNAL(framesInvalidated()),
+ this, SLOT(invalidateFrames()));
+ connect(m_trace, SIGNAL(framesAdded(int, int)),
+ this, SLOT(appendFrames(int, int)));
}
-void ApiTraceModel::appendCalls(const QList<Trace::Call*> traceCalls)
+const ApiTrace * ApiTraceModel::apiTrace() const
{
- beginInsertRows(QModelIndex(), m_calls.count(),
- m_calls.count() + traceCalls.count());
- foreach(Trace::Call *call, traceCalls) {
- ApiTraceCall *apiCall = new ApiTraceCall;
- apiCall->name = QString::fromStdString(call->sig->name);
+ return m_trace;
+}
- QString argumentsText;
- for (int i = 0; i < call->sig->arg_names.size(); ++i) {
- apiCall->argNames +=
- QString::fromStdString(call->sig->arg_names[i]);
- }
- if (call->ret) {
- VariantVisitor retVisitor;
- call->ret->visit(retVisitor);
- apiCall->returnValue = retVisitor.variant();
- }
- for (int i = 0; i < call->args.size(); ++i) {
- VariantVisitor argVisitor;
- call->args[i]->visit(argVisitor);
- apiCall->argValues += argVisitor.variant();
- }
+void ApiTraceModel::invalidateFrames()
+{
+ beginResetModel();
+ endResetModel();
+}
- m_calls.append(apiCall);
- }
+void ApiTraceModel::appendFrames(int oldCount, int numAdded)
+{
+ beginInsertRows(QModelIndex(), oldCount,
+ oldCount + numAdded - 1);
endInsertRows();
+}
+
+ApiTraceEvent * ApiTraceModel::item(const QModelIndex &index) const
+{
+ if (!index.isValid())
+ return 0;
+ return static_cast<ApiTraceEvent*>(index.internalPointer());
+}
- qDeleteAll(traceCalls);
+void ApiTraceModel::stateSetOnEvent(ApiTraceEvent *event)
+{
+ if (!event)
+ return;
+
+ if (event->type() == ApiTraceEvent::Call) {
+ ApiTraceCall *call = static_cast<ApiTraceCall*>(event);
+ ApiTraceFrame *frame = call->parentFrame;
+ int row = frame->calls.indexOf(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();
+ int row = frames.indexOf(frame);
+ QModelIndex index = createIndex(row, 0, frame);
+ emit dataChanged(index, index);
+ }
}
#include "apitracemodel.moc"