Add 'important' flag on structured data

This commit is contained in:
baldurk
2019-10-11 12:58:25 +01:00
parent 5dd3c95ee3
commit ec5f570fea
6 changed files with 155 additions and 10 deletions
+102 -6
View File
@@ -1624,7 +1624,7 @@ void CombineUsageEvents(ICaptureContext &ctx, const rdcarray<EventUsage> &usage,
callback(start, end, us);
}
QVariant SDObject2Variant(const SDObject *obj)
QVariant SDObject2Variant(const SDObject *obj, bool inlineImportant)
{
QVariant param;
@@ -1649,9 +1649,100 @@ QVariant SDObject2Variant(const SDObject *obj)
{
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::Chunk:
{
if(inlineImportant)
{
QString name = obj->name;
// don't display any "ClassName::" prefix by default here
int nsSep = name.indexOf(lit("::"));
if(nsSep > 0)
name.remove(0, nsSep + 2);
name += lit("(");
bool onlyImportant(obj->type.flags & SDTypeFlags::ImportantChildren);
bool first = true;
for(const SDObject *child : *obj)
{
// never display hidden members
if(child->type.flags & SDTypeFlags::Hidden)
continue;
if(!onlyImportant || (child->type.flags & SDTypeFlags::Important))
{
if(!first)
name += lit(", ");
name += SDObject2Variant(child, true).toString();
first = false;
}
}
name += lit(")");
param = name;
}
else
{
param = QVariant();
}
break;
}
case SDBasic::Struct:
case SDBasic::Array:
{
// only inline important arrays with up to 4 elements
if(inlineImportant && (obj->type.basetype == SDBasic::Struct || obj->NumChildren() <= 4))
{
int numImportantChildren = 0;
if(obj->NumChildren() == 0)
{
param = lit("{}");
}
else
{
bool importantChildren(obj->type.flags & SDTypeFlags::ImportantChildren);
bool first = true;
QString s;
for(size_t i = 0; i < obj->NumChildren(); i++)
{
const SDObject *child = obj->GetChild(i);
if(!importantChildren || (obj->GetChild(i)->type.flags & SDTypeFlags::Important))
{
if(!first)
s += lit(", ");
first = false;
s += SDObject2Variant(child, true).toString();
numImportantChildren++;
}
}
// when a struct only has one important member, just display that as-if it were the
// struct. We rely on the underlying important flagging to not make things too
// confusing.
// This addresses case where there's a struct hierarchy but we only care about one
// member a level or two down - we don't end up with { { { { Resource } } } }
// it also helps with structs that we want to display as just a single thing - like a
// struct that references a resource with adjacent properties, which we want to elide to
// just the resource itself.
if(importantChildren && numImportantChildren == 1 && obj->type.basetype == SDBasic::Struct)
param = s;
else
param = QFormatStr("{ %1 }").arg(s);
}
}
else
{
param = obj->type.basetype == SDBasic::Array
? QFormatStr("%1[%2]").arg(obj->type.name).arg(obj->NumChildren())
: 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:
@@ -1694,7 +1785,7 @@ void addStructuredChildren(RDTreeWidgetItem *parent, const SDObject &parentObj)
RDTreeWidgetItem *item = new RDTreeWidgetItem({name, QString()});
item->setText(1, SDObject2Variant(obj));
item->setText(1, SDObject2Variant(obj, false));
if(obj->type.basetype == SDBasic::Chunk || obj->type.basetype == SDBasic::Struct ||
obj->type.basetype == SDBasic::Array)
@@ -3333,7 +3424,12 @@ QVariant StructuredDataItemModel::data(const QModelIndex &index, int role) const
return QFormatStr("[%1]").arg(index.row());
else
return obj->name;
case Value: return SDObject2Variant(obj);
case Value:
{
QVariant v = SDObject2Variant(obj, obj->GetParent() ? false : true);
RichResourceTextInitialise(v, NULL);
return v;
}
case Type: return obj->type.name;
}
}
+1 -1
View File
@@ -126,7 +126,7 @@ void CombineUsageEvents(
class RDTreeWidgetItem;
QVariant SDObject2Variant(const SDObject *obj);
QVariant SDObject2Variant(const SDObject *obj, bool inlineImportant);
void addStructuredChildren(RDTreeWidgetItem *parent, const SDObject &parentObj);
struct PointerTypeRegistry
+1 -1
View File
@@ -253,7 +253,7 @@ void APIInspector::addEvent(const APIEvent &ev, bool primary)
m_Chunks.push_back(chunk);
root->setText(1, chunk->name);
root->setText(1, SDObject2Variant(chunk, true));
addStructuredChildren(root, *chunk);
}
+3 -2
View File
@@ -1201,7 +1201,8 @@ private:
{
for(const SDObject *c : *o)
{
if(RichResourceTextFormat(*ctx, SDObject2Variant(c)).contains(paramValue, Qt::CaseInsensitive))
if(RichResourceTextFormat(*ctx, SDObject2Variant(c, false))
.contains(paramValue, Qt::CaseInsensitive))
return true;
}
@@ -1209,7 +1210,7 @@ private:
}
else
{
return RichResourceTextFormat(*ctx, SDObject2Variant(o))
return RichResourceTextFormat(*ctx, SDObject2Variant(o, false))
.contains(paramValue, Qt::CaseInsensitive);
}
+16
View File
@@ -145,6 +145,20 @@ DOCUMENT(R"(Bitfield flags that could be applied to a type.
Special flag to indicate that this is structure is stored as a union, meaning all children share
the same memory and some external flag indicates which element is valid.
.. data:: Important
Indicates that this object is important or significant, to aid in generating a summary/one-line
view of a particular chunk by only including important children.
This property can be recursive - so an important child which is a structure can have only some
members which are important.
.. data:: ImportantChildren
Indicates that only important children should be processed, as noted in :data:`Important`. This
may appear on an object which has no important children - which indicates explicitly that there
are no important children so when summarising no parameters should be shown.
)");
enum class SDTypeFlags : uint32_t
{
@@ -155,6 +169,8 @@ enum class SDTypeFlags : uint32_t
NullString = 0x8,
FixedArray = 0x10,
Union = 0x20,
Important = 0x40,
ImportantChildren = 0x80,
};
BITMASK_OPERATORS(SDTypeFlags);
+32
View File
@@ -1171,6 +1171,38 @@ public:
return *this;
}
Serialiser &Important()
{
if(ExportStructure() && !m_StructureStack.empty())
{
SDObject &current = *m_StructureStack.back();
current.type.flags |= SDTypeFlags::ImportantChildren;
if(current.NumChildren() > 0)
{
SDObject *last = current.GetChild(current.NumChildren() - 1);
last->type.flags |= SDTypeFlags::Important;
}
}
return *this;
}
Serialiser &Unimportant()
{
if(ExportStructure() && !m_StructureStack.empty())
{
SDObject &current = *m_StructureStack.back();
// similar to Important() above but we *don't* set the important flag, we just mark the
// parent has
current.type.flags |= SDTypeFlags::ImportantChildren;
}
return *this;
}
Serialiser &Named(const rdcstr &name)
{
if(ExportStructure() && !m_StructureStack.empty())