mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-07-20 22:41:36 +00:00
Add lazy-populating item model for SDObjects
* We also add intermediate paging nodes for large arrays to ease expansions
This commit is contained in:
+356
-61
@@ -1332,6 +1332,60 @@ void CombineUsageEvents(ICaptureContext &ctx, const rdcarray<EventUsage> &usage,
|
||||
callback(start, end, us);
|
||||
}
|
||||
|
||||
QVariant SDObject2Variant(const SDObject *obj)
|
||||
{
|
||||
QVariant param;
|
||||
|
||||
// we don't identify via the type name as many types could be serialised as a ResourceId -
|
||||
// e.g. ID3D11Resource* or ID3D11Buffer* which would be the actual typename. We want to preserve
|
||||
// that for the best raw structured data representation instead of flattening those out to just
|
||||
// "ResourceId", and we also don't want to store two types ('fake' and 'real'), so instead we
|
||||
// check the custom string.
|
||||
if(obj->type.basetype == SDBasic::Resource)
|
||||
{
|
||||
param = QVariant::fromValue(obj->data.basic.id);
|
||||
}
|
||||
else if(obj->type.flags & SDTypeFlags::NullString)
|
||||
{
|
||||
param = lit("NULL");
|
||||
}
|
||||
else if(obj->type.flags & SDTypeFlags::HasCustomString)
|
||||
{
|
||||
param = obj->data.str;
|
||||
}
|
||||
else
|
||||
{
|
||||
switch(obj->type.basetype)
|
||||
{
|
||||
case SDBasic::Chunk: param = QVariant(); break;
|
||||
case SDBasic::Struct: param = QFormatStr("%1()").arg(obj->type.name); break;
|
||||
case SDBasic::Array: param = QFormatStr("%1[]").arg(obj->type.name); break;
|
||||
case SDBasic::Null: param = lit("NULL"); break;
|
||||
case SDBasic::Buffer: param = lit("(%1 bytes)").arg(obj->type.byteSize); break;
|
||||
case SDBasic::String:
|
||||
{
|
||||
QStringList lines = QString(obj->data.str).split(QLatin1Char('\n'));
|
||||
QString trimmedStr;
|
||||
for(int i = 0; i < 3 && i < lines.count(); i++)
|
||||
trimmedStr += lines[i] + QLatin1Char('\n');
|
||||
if(lines.count() > 3)
|
||||
trimmedStr += lit("...");
|
||||
param = trimmedStr.trimmed();
|
||||
break;
|
||||
}
|
||||
case SDBasic::Resource:
|
||||
case SDBasic::Enum:
|
||||
case SDBasic::UnsignedInteger: param = Formatter::HumanFormat(obj->data.basic.u); break;
|
||||
case SDBasic::SignedInteger: param = Formatter::Format(obj->data.basic.i); break;
|
||||
case SDBasic::Float: param = Formatter::Format(obj->data.basic.d); break;
|
||||
case SDBasic::Boolean: param = (obj->data.basic.b ? lit("True") : lit("False")); break;
|
||||
case SDBasic::Character: param = QString(QLatin1Char(obj->data.basic.c)); break;
|
||||
}
|
||||
}
|
||||
|
||||
return param;
|
||||
}
|
||||
|
||||
void addStructuredChildren(RDTreeWidgetItem *parent, const SDObject &parentObj)
|
||||
{
|
||||
for(const SDObject *obj : parentObj)
|
||||
@@ -1339,73 +1393,20 @@ void addStructuredChildren(RDTreeWidgetItem *parent, const SDObject &parentObj)
|
||||
if(obj->type.flags & SDTypeFlags::Hidden)
|
||||
continue;
|
||||
|
||||
QVariant param;
|
||||
QVariant name;
|
||||
|
||||
if(parentObj.type.basetype == SDBasic::Array)
|
||||
param = QFormatStr("[%1]").arg(parent->childCount());
|
||||
name = QFormatStr("[%1]").arg(parent->childCount());
|
||||
else
|
||||
param = obj->name;
|
||||
name = obj->name;
|
||||
|
||||
RDTreeWidgetItem *item = new RDTreeWidgetItem({param, QString()});
|
||||
RDTreeWidgetItem *item = new RDTreeWidgetItem({name, QString()});
|
||||
|
||||
// we don't identify via the type name as many types could be serialised as a ResourceId -
|
||||
// e.g. ID3D11Resource* or ID3D11Buffer* which would be the actual typename. We want to preserve
|
||||
// that for the best raw structured data representation instead of flattening those out to just
|
||||
// "ResourceId", and we also don't want to store two types ('fake' and 'real'), so instead we
|
||||
// check the custom string.
|
||||
if(obj->type.basetype == SDBasic::Resource)
|
||||
{
|
||||
ResourceId id;
|
||||
static_assert(sizeof(id) == sizeof(obj->data.basic.u), "ResourceId is no longer uint64_t!");
|
||||
memcpy(&id, &obj->data.basic.u, sizeof(id));
|
||||
item->setText(1, SDObject2Variant(obj));
|
||||
|
||||
param = id;
|
||||
}
|
||||
else if(obj->type.flags & SDTypeFlags::NullString)
|
||||
{
|
||||
param = lit("NULL");
|
||||
}
|
||||
else if(obj->type.flags & SDTypeFlags::HasCustomString)
|
||||
{
|
||||
param = obj->data.str;
|
||||
}
|
||||
else
|
||||
{
|
||||
switch(obj->type.basetype)
|
||||
{
|
||||
case SDBasic::Chunk:
|
||||
case SDBasic::Struct:
|
||||
param = QFormatStr("%1()").arg(obj->type.name);
|
||||
addStructuredChildren(item, *obj);
|
||||
break;
|
||||
case SDBasic::Array:
|
||||
param = QFormatStr("%1[]").arg(obj->type.name);
|
||||
addStructuredChildren(item, *obj);
|
||||
break;
|
||||
case SDBasic::Null: param = lit("NULL"); break;
|
||||
case SDBasic::Buffer: param = lit("(%1 bytes)").arg(obj->type.byteSize); break;
|
||||
case SDBasic::String:
|
||||
{
|
||||
QStringList lines = QString(obj->data.str).split(QLatin1Char('\n'));
|
||||
QString trimmedStr;
|
||||
for(int i = 0; i < 3 && i < lines.count(); i++)
|
||||
trimmedStr += lines[i] + QLatin1Char('\n');
|
||||
if(lines.count() > 3)
|
||||
trimmedStr += lit("...");
|
||||
param = trimmedStr.trimmed();
|
||||
break;
|
||||
}
|
||||
case SDBasic::Resource:
|
||||
case SDBasic::Enum:
|
||||
case SDBasic::UnsignedInteger: param = Formatter::HumanFormat(obj->data.basic.u); break;
|
||||
case SDBasic::SignedInteger: param = Formatter::Format(obj->data.basic.i); break;
|
||||
case SDBasic::Float: param = Formatter::Format(obj->data.basic.d); break;
|
||||
case SDBasic::Boolean: param = (obj->data.basic.b ? lit("True") : lit("False")); break;
|
||||
case SDBasic::Character: param = QString(QLatin1Char(obj->data.basic.c)); break;
|
||||
}
|
||||
}
|
||||
|
||||
item->setText(1, param);
|
||||
if(obj->type.basetype == SDBasic::Chunk || obj->type.basetype == SDBasic::Struct ||
|
||||
obj->type.basetype == SDBasic::Array)
|
||||
addStructuredChildren(item, *obj);
|
||||
|
||||
parent->addChild(item);
|
||||
}
|
||||
@@ -2742,3 +2743,297 @@ void UpdateVisibleColumns(rdcstr windowTitle, int columnCount, QHeaderView *head
|
||||
header->moveSection(header->visualIndex(logicalIdx), i);
|
||||
}
|
||||
}
|
||||
|
||||
void StructuredDataItemModel::setObjects(const rdcarray<SDObject *> &objs)
|
||||
{
|
||||
emit beginResetModel();
|
||||
m_Objects = objs;
|
||||
emit endResetModel();
|
||||
}
|
||||
|
||||
// on 64-bit we've got plenty of bits so we can pack the indices into top/bottom 32-bits.
|
||||
// on 32-bit we assume there won't be any huge arrays or we'll run out of memory elsewhere probably,
|
||||
// so we pack 9/21 bits allowing for up to 512 arrays of ~2 million entries each.
|
||||
// bear in mind 2 bits are reserved for the index tag itself
|
||||
struct IndexMasks
|
||||
{
|
||||
static constexpr quintptr IndexBits() { return sizeof(void *) == 8 ? 32U : 21U; }
|
||||
static quintptr GetArrayID(quintptr packed) { return packed >> IndexBits(); }
|
||||
static quintptr GetIndexInArray(quintptr packed)
|
||||
{
|
||||
return packed & ((quintptr(1U) << IndexBits()) - 1);
|
||||
}
|
||||
static quintptr Pack(quintptr arrayId, quintptr idxInArray)
|
||||
{
|
||||
return (arrayId << IndexBits()) | idxInArray;
|
||||
}
|
||||
};
|
||||
|
||||
StructuredDataItemModel::Index StructuredDataItemModel::decodeIndex(QModelIndex idx) const
|
||||
{
|
||||
// if it's a direct pointer, the low bits will be 0 for alignment.
|
||||
Index ret;
|
||||
ret.tag = IndexTag(idx.internalId() & 0x3);
|
||||
|
||||
if(ret.tag == Direct)
|
||||
{
|
||||
ret.obj = (SDObject *)idx.internalPointer();
|
||||
}
|
||||
else
|
||||
{
|
||||
quintptr packed = idx.internalId() >> 2;
|
||||
ret.obj = (SDObject *)m_Arrays[IndexMasks::GetArrayID(packed)];
|
||||
ret.indexInArray = IndexMasks::GetIndexInArray(packed);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
quintptr StructuredDataItemModel::encodeIndex(Index idx) const
|
||||
{
|
||||
if(idx.tag == Direct)
|
||||
return (quintptr)idx.obj;
|
||||
|
||||
int arrayId = m_Arrays.indexOf(idx.obj);
|
||||
if(arrayId == -1)
|
||||
{
|
||||
m_Arrays.push_back(idx.obj);
|
||||
arrayId = m_Arrays.count() - 1;
|
||||
}
|
||||
|
||||
quintptr packed = IndexMasks::Pack(arrayId, idx.indexInArray);
|
||||
return (packed << 2U) | quintptr(idx.tag);
|
||||
}
|
||||
|
||||
// for large arrays (more than this size) paginate it with pages of this size.
|
||||
// This is primarily beneficial for lazy arrays to avoid needing to lazily evaluate a huge array.
|
||||
const int ArrayPageSize = 250;
|
||||
|
||||
bool StructuredDataItemModel::isLargeArray(SDObject *obj) const
|
||||
{
|
||||
return (int)obj->NumChildren() > ArrayPageSize;
|
||||
}
|
||||
|
||||
QModelIndex StructuredDataItemModel::index(int row, int column, const QModelIndex &parent) const
|
||||
{
|
||||
if(row < 0 || column < 0 || row >= rowCount(parent) || column >= columnCount(parent))
|
||||
return QModelIndex();
|
||||
|
||||
SDObject *par = NULL;
|
||||
|
||||
if(parent.isValid())
|
||||
{
|
||||
Index decodedParent = decodeIndex(parent);
|
||||
|
||||
// the children of page nodes are real nodes. We cache the array member's index here too for
|
||||
// parent() lookups
|
||||
if(decodedParent.tag == PageNode)
|
||||
{
|
||||
int idx = decodedParent.indexInArray + row;
|
||||
|
||||
m_ArrayMembers[decodedParent.obj->GetChild(idx)] = idx;
|
||||
|
||||
return createIndex(row, column, encodeIndex({ArrayMember, decodedParent.obj, idx}));
|
||||
}
|
||||
else if(decodedParent.tag == ArrayMember)
|
||||
{
|
||||
par = decodedParent.obj->GetChild(decodedParent.indexInArray);
|
||||
}
|
||||
else
|
||||
{
|
||||
par = decodedParent.obj;
|
||||
}
|
||||
|
||||
// if this parent node is a large array, the children are page nodes, otherwise the child is a
|
||||
// direct node
|
||||
if(isLargeArray(par))
|
||||
{
|
||||
return createIndex(row, column, encodeIndex({PageNode, par, row * ArrayPageSize}));
|
||||
}
|
||||
else
|
||||
{
|
||||
return createIndex(row, column, encodeIndex({Direct, par->GetChild(row), 0}));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return createIndex(row, column, encodeIndex({Direct, m_Objects[row], 0}));
|
||||
}
|
||||
}
|
||||
|
||||
QModelIndex StructuredDataItemModel::parent(const QModelIndex &index) const
|
||||
{
|
||||
if(index.internalPointer() == NULL)
|
||||
return QModelIndex();
|
||||
|
||||
Index decodedIndex = decodeIndex(index);
|
||||
|
||||
SDObject *obj = NULL;
|
||||
|
||||
// array members have parents that are page nodes
|
||||
if(decodedIndex.tag == ArrayMember)
|
||||
{
|
||||
int pageRow = decodedIndex.indexInArray / ArrayPageSize;
|
||||
return createIndex(decodedIndex.indexInArray / ArrayPageSize, 0,
|
||||
encodeIndex({PageNode, decodedIndex.obj, pageRow * ArrayPageSize}));
|
||||
}
|
||||
else if(decodedIndex.tag == PageNode)
|
||||
{
|
||||
obj = decodedIndex.obj;
|
||||
}
|
||||
else
|
||||
{
|
||||
obj = decodedIndex.obj->GetParent();
|
||||
}
|
||||
|
||||
// need to figure out the index for obj, it could be an array member itself in theory, or it might
|
||||
// be direct, or it could be a root object
|
||||
if(obj)
|
||||
{
|
||||
SDObject *parent = obj->GetParent();
|
||||
|
||||
if(parent == NULL)
|
||||
{
|
||||
int row = m_Objects.indexOf(obj);
|
||||
if(row >= 0)
|
||||
return createIndex(row, 0, obj);
|
||||
|
||||
qCritical() << "Encountered object with no parent that is not a root";
|
||||
|
||||
return QModelIndex();
|
||||
}
|
||||
|
||||
// if the parent is a large array
|
||||
if(isLargeArray(parent))
|
||||
{
|
||||
// we expect to have set up our member index before this lookup was ever needed
|
||||
auto it = m_ArrayMembers.find(obj);
|
||||
if(it == m_ArrayMembers.end())
|
||||
{
|
||||
qCritical() << "Expected member index to be set up, but it is not";
|
||||
|
||||
return QModelIndex();
|
||||
}
|
||||
|
||||
// return the index for this item, with the child index we looked up
|
||||
return createIndex(it.value(), 0, encodeIndex({ArrayMember, parent, it.value()}));
|
||||
}
|
||||
|
||||
// search our parent to find out our child index
|
||||
for(size_t i = 0; i < parent->NumChildren(); i++)
|
||||
if(parent->GetChild(i) == obj)
|
||||
return createIndex((int)i, 0, obj);
|
||||
|
||||
return QModelIndex();
|
||||
}
|
||||
|
||||
return QModelIndex();
|
||||
}
|
||||
|
||||
int StructuredDataItemModel::rowCount(const QModelIndex &parent) const
|
||||
{
|
||||
if(!parent.isValid())
|
||||
return m_Objects.count();
|
||||
|
||||
Index decodedIdx = decodeIndex(parent);
|
||||
|
||||
SDObject *obj = NULL;
|
||||
|
||||
// if this is a page node, it either has PageSize children if it's not the last one, or the
|
||||
// remainder
|
||||
if(decodedIdx.tag == PageNode)
|
||||
{
|
||||
size_t pageBase = decodedIdx.indexInArray;
|
||||
|
||||
return qMin(ArrayPageSize, int(decodedIdx.obj->NumChildren() - pageBase));
|
||||
}
|
||||
else if(decodedIdx.tag == ArrayMember)
|
||||
{
|
||||
obj = decodedIdx.obj->GetChild(decodedIdx.indexInArray);
|
||||
}
|
||||
else
|
||||
{
|
||||
obj = decodedIdx.obj;
|
||||
}
|
||||
|
||||
if(obj)
|
||||
{
|
||||
if(isLargeArray(obj))
|
||||
return (int(obj->NumChildren()) + ArrayPageSize - 1) / ArrayPageSize;
|
||||
else
|
||||
return (int)obj->NumChildren();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int StructuredDataItemModel::columnCount(const QModelIndex &parent) const
|
||||
{
|
||||
return m_ColumnNames.count();
|
||||
}
|
||||
|
||||
QVariant StructuredDataItemModel::headerData(int section, Qt::Orientation orientation, int role) const
|
||||
{
|
||||
if(orientation == Qt::Horizontal && role == Qt::DisplayRole)
|
||||
{
|
||||
if(section < m_ColumnNames.count())
|
||||
return m_ColumnNames[section];
|
||||
}
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
Qt::ItemFlags StructuredDataItemModel::flags(const QModelIndex &index) const
|
||||
{
|
||||
if(!index.isValid())
|
||||
return 0;
|
||||
|
||||
return QAbstractItemModel::flags(index);
|
||||
}
|
||||
|
||||
QVariant StructuredDataItemModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
if(role != Qt::DisplayRole || index.column() >= columnCount())
|
||||
return QVariant();
|
||||
|
||||
Index decodedIdx = decodeIndex(index);
|
||||
SDObject *obj = NULL;
|
||||
|
||||
if(decodedIdx.tag == PageNode)
|
||||
{
|
||||
if(m_ColumnValues[index.column()] == Name)
|
||||
{
|
||||
size_t pageBase = decodedIdx.indexInArray;
|
||||
size_t pageCount = qMin(ArrayPageSize, int(decodedIdx.obj->NumChildren() - pageBase));
|
||||
|
||||
return QFormatStr("[%1..%2]").arg(pageBase).arg(pageBase + pageCount - 1);
|
||||
}
|
||||
return QVariant();
|
||||
}
|
||||
else if(decodedIdx.tag == ArrayMember)
|
||||
{
|
||||
obj = decodedIdx.obj->GetChild(decodedIdx.indexInArray);
|
||||
}
|
||||
else
|
||||
{
|
||||
obj = decodedIdx.obj;
|
||||
}
|
||||
|
||||
if(obj)
|
||||
{
|
||||
switch(m_ColumnValues[index.column()])
|
||||
{
|
||||
case Name:
|
||||
if(decodedIdx.tag == ArrayMember)
|
||||
return QFormatStr("[%1]").arg(decodedIdx.indexInArray);
|
||||
else if(obj->GetParent() && obj->GetParent()->type.basetype == SDBasic::Array)
|
||||
return QFormatStr("[%1]").arg(index.row());
|
||||
else
|
||||
return obj->name;
|
||||
case Value: return SDObject2Variant(obj);
|
||||
case Type: return obj->type.name;
|
||||
}
|
||||
}
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
@@ -577,6 +577,67 @@ private:
|
||||
QAbstractItemView *m_widget;
|
||||
};
|
||||
|
||||
class StructuredDataItemModel : public QAbstractItemModel
|
||||
{
|
||||
public:
|
||||
enum SDColumn
|
||||
{
|
||||
Name,
|
||||
Value,
|
||||
Type,
|
||||
};
|
||||
|
||||
void setColumns(QStringList names, rdcarray<SDColumn> values)
|
||||
{
|
||||
m_ColumnNames = names;
|
||||
m_ColumnValues = values;
|
||||
}
|
||||
|
||||
void setObjects(const rdcarray<SDObject *> &objs);
|
||||
StructuredDataItemModel(QWidget *parent) : QAbstractItemModel(parent) {}
|
||||
QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override;
|
||||
QModelIndex parent(const QModelIndex &index) const override;
|
||||
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||
int columnCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||
Qt::ItemFlags flags(const QModelIndex &index) const override;
|
||||
QVariant headerData(int section, Qt::Orientation orientation, int role) const override;
|
||||
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
||||
|
||||
private:
|
||||
enum IndexTag
|
||||
{
|
||||
Direct,
|
||||
PageNode,
|
||||
ArrayMember,
|
||||
};
|
||||
|
||||
struct Index
|
||||
{
|
||||
IndexTag tag;
|
||||
SDObject *obj;
|
||||
int indexInArray;
|
||||
};
|
||||
|
||||
Index decodeIndex(QModelIndex idx) const;
|
||||
quintptr encodeIndex(Index idx) const;
|
||||
bool isLargeArray(SDObject *obj) const;
|
||||
|
||||
rdcarray<SDObject *> m_Objects;
|
||||
QStringList m_ColumnNames;
|
||||
rdcarray<SDColumn> m_ColumnValues;
|
||||
|
||||
// these below members have to be mutable since we update these caches in const functions
|
||||
|
||||
// set of large arrays, so we can refer to them by compressed index instead of needing a full
|
||||
// pointer.
|
||||
mutable rdcarray<SDObject *> m_Arrays;
|
||||
// objects that are in large arrays. This map gives us the index they are in their parent.
|
||||
// This is only used for parent() when the parent is an array member, so we only add into this
|
||||
// list when creating a child index of such an array member - which only happens when the array
|
||||
// member is expanded. That keeps to a minimum the number of entries.
|
||||
mutable QMap<SDObject *, int> m_ArrayMembers;
|
||||
};
|
||||
|
||||
// helper functions for using a double spinbox for 64-bit integers. We do this because it's
|
||||
// infeasible in Qt to actually derive and create a real 64-bit integer spinbox because critical
|
||||
// functionality depends on deriving QAbstractSpinBoxPrivate which is unavailable. So instead we use
|
||||
|
||||
@@ -128,6 +128,9 @@ ResourceInspector::ResourceInspector(ICaptureContext &ctx, QWidget *parent)
|
||||
m_ChunksModel->setColumns({tr("Parameter"), tr("Value")},
|
||||
{StructuredDataItemModel::Name, StructuredDataItemModel::Value});
|
||||
|
||||
m_delegate = new RichTextViewDelegate(ui->initChunks);
|
||||
ui->initChunks->setItemDelegate(m_delegate);
|
||||
|
||||
ui->initChunks->header()->resizeSection(0, 200);
|
||||
|
||||
ui->initChunks->setFont(Formatter::PreferredFont());
|
||||
@@ -308,27 +311,17 @@ void ResourceInspector::Inspect(ResourceId id)
|
||||
}
|
||||
ui->relatedResources->endUpdate();
|
||||
|
||||
rdcarray<SDObject *> objs;
|
||||
|
||||
for(uint32_t chunk : desc->initialisationChunks)
|
||||
{
|
||||
RDTreeWidgetItem *root = new RDTreeWidgetItem({QString(), QString()});
|
||||
|
||||
if(chunk < file.chunks.size())
|
||||
{
|
||||
SDChunk *chunkObj = file.chunks[chunk];
|
||||
|
||||
root->setText(0, chunkObj->name);
|
||||
|
||||
addStructuredChildren(root, *chunkObj);
|
||||
}
|
||||
objs.push_back(file.chunks[chunk]);
|
||||
else
|
||||
{
|
||||
root->setText(1, tr("Invalid chunk index %1").arg(chunk));
|
||||
}
|
||||
|
||||
ui->initChunks->addTopLevelItem(root);
|
||||
|
||||
ui->initChunks->setSelectedItem(root);
|
||||
qCritical() << "Invalid chunk index" << chunk;
|
||||
}
|
||||
|
||||
m_ChunksModel->setObjects(objs);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -376,7 +369,7 @@ void ResourceInspector::OnCaptureClosed()
|
||||
|
||||
m_ResourceModel->reset();
|
||||
|
||||
ui->initChunks->clear();
|
||||
m_ChunksModel->setObjects({});
|
||||
ui->initChunks->clearInternalExpansions();
|
||||
ui->relatedResources->clear();
|
||||
ui->resourceUsage->clear();
|
||||
|
||||
@@ -36,6 +36,8 @@ class QCollatorSortFilterProxyModel;
|
||||
|
||||
class RDTreeWidgetItem;
|
||||
class ResourceListItemModel;
|
||||
class StructuredDataItemModel;
|
||||
class RichTextViewDelegate;
|
||||
|
||||
class ResourceInspector : public QFrame, public IResourceInspector, public ICaptureViewer
|
||||
{
|
||||
@@ -87,4 +89,6 @@ private:
|
||||
ResourceListItemModel *m_ResourceModel;
|
||||
int m_ResourceCacheID = -1;
|
||||
QCollatorSortFilterProxyModel *m_FilterModel;
|
||||
StructuredDataItemModel *m_ChunksModel;
|
||||
RichTextViewDelegate *m_delegate;
|
||||
};
|
||||
|
||||
@@ -232,7 +232,7 @@
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="RDTreeWidget" name="initChunks">
|
||||
<widget class="RDTreeView" name="initChunks">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>60</x>
|
||||
@@ -320,6 +320,11 @@
|
||||
<extends>QLineEdit</extends>
|
||||
<header>Widgets/Extended/RDLineEdit.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>RDTreeView</class>
|
||||
<extends>QTreeView</extends>
|
||||
<header>Widgets/Extended/RDTreeView.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>RDTreeWidget</class>
|
||||
<extends>QTreeView</extends>
|
||||
|
||||
Reference in New Issue
Block a user