mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-08-28 09:26:52 +00:00
Add auto-completion prompts for filter function parameters
This commit is contained in:
@@ -228,6 +228,26 @@ DOCUMENT(R"(The event browser window.
|
||||
:return: An empty string if the parse succeeded, otherwise any error messages to be displayed to
|
||||
the user, such as syntax or other errors.
|
||||
:rtype: str
|
||||
|
||||
.. function:: AutoCompleteCallback(context, filter, params)
|
||||
|
||||
Not a member function - the signature for any ``AutoCompleteCallback`` callbacks.
|
||||
|
||||
Called when autocompletion is triggered inside a filter. The params passed are any previous
|
||||
text inside the filter's parameter list up to where the cursor is. The callback should return a
|
||||
list of identifiers used for auto-completion.
|
||||
|
||||
The list does not have to be pre-filtered for matches to the :paramref:`params`, that is provided
|
||||
to allow different autocompletion at different stages (e.g. if there are no parameters, you can
|
||||
autocomplete a property, if a property is already present you can autocomplete valid values for
|
||||
it)
|
||||
|
||||
:param CaptureContext context: The current capture context.
|
||||
:param str filter: The name of the filter function.
|
||||
:param str params: The previous parameter text to the filter function.
|
||||
:return: A list of strings giving identifiers to autocomplete, or an empty list of there are no
|
||||
such identifiers to prompt.
|
||||
:rtype: List[str]
|
||||
)");
|
||||
struct IEventBrowser
|
||||
{
|
||||
@@ -237,6 +257,9 @@ struct IEventBrowser
|
||||
|
||||
typedef std::function<rdcstr(ICaptureContext *, const rdcstr &, const rdcstr &)> FilterParseCallback;
|
||||
|
||||
typedef std::function<rdcarray<rdcstr>(ICaptureContext *, const rdcstr &, const rdcstr &)>
|
||||
AutoCompleteCallback;
|
||||
|
||||
DOCUMENT(R"(Retrieves the PySide2 QWidget for this :class:`EventBrowser` if PySide2 is available, or otherwise
|
||||
returns a unique opaque pointer that can be passed back to any RenderDoc functions expecting a
|
||||
QWidget.
|
||||
@@ -289,12 +312,15 @@ expression.
|
||||
:param EventFilterCallback filter: The callback to call for each candidate event to perform
|
||||
filtering.
|
||||
:param FilterParseCallback parser: The callback to call when the parsing the parameters and checking
|
||||
for any errors.
|
||||
for any errors. This can be ``None`` if no pre-parsing is required.
|
||||
:param AutoCompleteCallback completer: The callback to call when trying to provide autocomplete
|
||||
suggestions. This can be ``None`` if no completion is desired/applicable.
|
||||
:return: Whether or not the registration was successful.
|
||||
:rtype: bool
|
||||
)");
|
||||
virtual bool RegisterEventFilterFunction(const rdcstr &name, EventFilterCallback filter,
|
||||
FilterParseCallback parser) = 0;
|
||||
FilterParseCallback parser,
|
||||
AutoCompleteCallback completer) = 0;
|
||||
|
||||
DOCUMENT(R"(Unregisters an event browser filter function that was previously registered.
|
||||
|
||||
|
||||
@@ -232,7 +232,6 @@ void RDTextEdit::keyPressEvent(QKeyEvent *e)
|
||||
{
|
||||
QTextEdit::keyPressEvent(e);
|
||||
}
|
||||
emit(keyPress(e));
|
||||
|
||||
// stop completing if the character just entered is not a word-compatible character
|
||||
if(completionInProgress() && e->text().length() > 0)
|
||||
@@ -240,11 +239,20 @@ void RDTextEdit::keyPressEvent(QKeyEvent *e)
|
||||
QChar c = e->text()[0];
|
||||
if(c.isPrint() && !e->text()[0].isLetterOrNumber() && !m_WordCharacters.contains(e->text()[0]))
|
||||
{
|
||||
m_Completer->popup()->hide();
|
||||
emit(completionEnd());
|
||||
if(c.isSpace() && m_Completer->completionPrefix().trimmed() == QString())
|
||||
{
|
||||
// don't do anything if we have no prefix so far and the user enters whitespace
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Completer->popup()->hide();
|
||||
emit(completionEnd());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
emit(keyPress(e));
|
||||
|
||||
// update the completion if it's in progress, or we have our shortcut (and there's no selected
|
||||
// text)
|
||||
if((completionShortcut && !textCursor().hasSelection()) || completionInProgress())
|
||||
|
||||
@@ -1093,6 +1093,29 @@ struct EventFilter
|
||||
};
|
||||
|
||||
static QMap<QString, DrawFlags> DrawFlagsLookup;
|
||||
static QStringList DrawFlagsList;
|
||||
|
||||
void CacheDrawFlagsLookup()
|
||||
{
|
||||
if(DrawFlagsLookup.empty())
|
||||
{
|
||||
for(uint32_t i = 0; i <= 31; i++)
|
||||
{
|
||||
DrawFlags flag = DrawFlags(1U << i);
|
||||
|
||||
// bit of a hack, see if it's a valid flag by stringising and seeing if it contains
|
||||
// DrawFlags(
|
||||
QString str = ToQStr(flag);
|
||||
if(str.contains(lit("DrawFlags(")))
|
||||
continue;
|
||||
|
||||
DrawFlagsList.push_back(str);
|
||||
DrawFlagsLookup[str.toLower()] = flag;
|
||||
}
|
||||
|
||||
DrawFlagsList.sort();
|
||||
}
|
||||
}
|
||||
|
||||
bool EvaluateFilterSet(ICaptureContext &ctx, const rdcarray<EventFilter> &filters, bool all,
|
||||
uint32_t eid, const SDChunk *chunk, const DrawcallDescription *draw,
|
||||
@@ -1187,11 +1210,13 @@ struct CustomFilterCallbacks
|
||||
{
|
||||
IEventBrowser::EventFilterCallback filter;
|
||||
IEventBrowser::FilterParseCallback parser;
|
||||
IEventBrowser::AutoCompleteCallback completer;
|
||||
};
|
||||
|
||||
struct BuiltinFilterCallbacks
|
||||
{
|
||||
std::function<IEventBrowser::EventFilterCallback(QString, QString, ParseError &)> makeFilter;
|
||||
IEventBrowser::AutoCompleteCallback completer;
|
||||
};
|
||||
|
||||
struct EventFilterModel : public QSortFilterProxyModel
|
||||
@@ -1220,6 +1245,19 @@ public:
|
||||
MAKE_BUILTIN_FILTER(event);
|
||||
MAKE_BUILTIN_FILTER(draw);
|
||||
MAKE_BUILTIN_FILTER(dispatch);
|
||||
|
||||
m_BuiltinFilters[lit("event")].completer = [this](ICaptureContext *ctx, QString name,
|
||||
QString parameters) {
|
||||
return filterCompleter_event(ctx, name, parameters);
|
||||
};
|
||||
m_BuiltinFilters[lit("draw")].completer = [this](ICaptureContext *ctx, QString name,
|
||||
QString parameters) {
|
||||
return filterCompleter_draw(ctx, name, parameters);
|
||||
};
|
||||
m_BuiltinFilters[lit("dispatch")].completer = [this](ICaptureContext *ctx, QString name,
|
||||
QString parameters) {
|
||||
return filterCompleter_dispatch(ctx, name, parameters);
|
||||
};
|
||||
}
|
||||
}
|
||||
void ResetCache() { m_VisibleCache.clear(); }
|
||||
@@ -1234,12 +1272,33 @@ public:
|
||||
return ret;
|
||||
}
|
||||
|
||||
QStringList GetCompletions(QString filter, QString params)
|
||||
{
|
||||
IEventBrowser::AutoCompleteCallback cb;
|
||||
|
||||
if(m_BuiltinFilters.contains(filter))
|
||||
cb = m_BuiltinFilters[filter].completer;
|
||||
else if(m_CustomFilters.contains(filter))
|
||||
cb = m_CustomFilters[filter].completer;
|
||||
|
||||
rdcarray<rdcstr> ret;
|
||||
|
||||
if(cb)
|
||||
ret = m_BuiltinFilters[filter].completer(&m_Ctx, filter, params);
|
||||
|
||||
QStringList qret;
|
||||
for(const rdcstr &s : ret)
|
||||
qret << s;
|
||||
return qret;
|
||||
}
|
||||
|
||||
QStringList GetBuiltinFunctions() { return m_BuiltinFilters.keys(); }
|
||||
QStringList GetCustomFunctions() { return m_CustomFilters.keys(); }
|
||||
void SetEmptyRegionsVisible(bool visible) { m_EmptyRegionsVisible = visible; }
|
||||
static bool RegisterEventFilterFunction(const rdcstr &name,
|
||||
IEventBrowser::EventFilterCallback filter,
|
||||
IEventBrowser::FilterParseCallback parser)
|
||||
IEventBrowser::FilterParseCallback parser,
|
||||
IEventBrowser::AutoCompleteCallback completer)
|
||||
{
|
||||
if(m_BuiltinFilters.contains(name))
|
||||
{
|
||||
@@ -1255,7 +1314,7 @@ public:
|
||||
return false;
|
||||
}
|
||||
|
||||
m_CustomFilters[name] = {filter, parser};
|
||||
m_CustomFilters[name] = {filter, parser, completer};
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1477,6 +1536,15 @@ private:
|
||||
};
|
||||
}
|
||||
|
||||
rdcarray<rdcstr> filterCompleter_event(ICaptureContext *ctx, const rdcstr &name,
|
||||
const rdcstr ¶ms)
|
||||
{
|
||||
if(params.find_first_of(" \t") == -1)
|
||||
return {"EID"};
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
IEventBrowser::EventFilterCallback filterFunction_event(QString name, QString parameters,
|
||||
ParseError &errors)
|
||||
{
|
||||
@@ -1555,6 +1623,34 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
rdcarray<rdcstr> filterCompleter_draw(ICaptureContext *ctx, const rdcstr &name, const rdcstr ¶ms)
|
||||
{
|
||||
if(params.find_first_of(" \t") == -1)
|
||||
return {
|
||||
"EID", "parent", "drawcallId", "numIndices",
|
||||
// most aliases we don't autocomplete but this one we leave
|
||||
"numVertices", "numInstances", "baseVertex", "indexOffset", "vertexOffset",
|
||||
"instanceOffset", "dispatchX", "dispatchY", "dispatchZ", "dispatchSize", "duration",
|
||||
"flags",
|
||||
};
|
||||
|
||||
QList<Token> tokens = tokenise(params);
|
||||
|
||||
if(tokens[0].text == lit("flags") && tokens.size() >= 2)
|
||||
{
|
||||
CacheDrawFlagsLookup();
|
||||
|
||||
rdcarray<rdcstr> flags;
|
||||
|
||||
for(QString s : DrawFlagsList)
|
||||
flags.push_back(s);
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
IEventBrowser::EventFilterCallback filterFunction_draw(QString name, QString parameters,
|
||||
ParseError &errors)
|
||||
{
|
||||
@@ -1585,10 +1681,11 @@ private:
|
||||
static const NamedProp namedProps[] = {
|
||||
NAMED_PROP("eventid", draw->eventId), NAMED_PROP("eid", draw->eventId),
|
||||
NAMED_PROP("parent", draw->parent ? draw->parent->eventId : -12341234),
|
||||
NAMED_PROP("drawcallid", draw->drawcallId), NAMED_PROP("numindices", draw->numIndices),
|
||||
NAMED_PROP("numindexes", draw->numIndices), NAMED_PROP("numvertices", draw->numIndices),
|
||||
NAMED_PROP("numvertexes", draw->numIndices), NAMED_PROP("indexcount", draw->numIndices),
|
||||
NAMED_PROP("vertexcount", draw->numIndices), NAMED_PROP("numinstances", draw->numInstances),
|
||||
NAMED_PROP("drawcallid", draw->drawcallId), NAMED_PROP("drawid", draw->drawcallId),
|
||||
NAMED_PROP("numindices", draw->numIndices), NAMED_PROP("numindexes", draw->numIndices),
|
||||
NAMED_PROP("numvertices", draw->numIndices), NAMED_PROP("numvertexes", draw->numIndices),
|
||||
NAMED_PROP("indexcount", draw->numIndices), NAMED_PROP("vertexcount", draw->numIndices),
|
||||
NAMED_PROP("numinstances", draw->numInstances),
|
||||
NAMED_PROP("instancecount", draw->numInstances), NAMED_PROP("basevertex", draw->baseVertex),
|
||||
NAMED_PROP("indexoffset", draw->indexOffset), NAMED_PROP("vertexoffset", draw->vertexOffset),
|
||||
NAMED_PROP("instanceoffset", draw->instanceOffset),
|
||||
@@ -1788,7 +1885,7 @@ private:
|
||||
}
|
||||
else if(tokens[0].text.toLower() == lit("flags"))
|
||||
{
|
||||
if(tokens.size() < 3 || tokens[1].text != lit("&"))
|
||||
if(tokens.size() < 3 || (tokens[1].text != lit("&") && tokens[1].text != lit("=")))
|
||||
{
|
||||
errors.position = tokens[0].position;
|
||||
errors.length = (tokens[1].position + tokens[1].length) - errors.position + 1;
|
||||
@@ -1853,6 +1950,17 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
rdcarray<rdcstr> filterCompleter_dispatch(ICaptureContext *ctx, const rdcstr &name,
|
||||
const rdcstr ¶ms)
|
||||
{
|
||||
if(params.find_first_of(" \t") == -1)
|
||||
return {
|
||||
"EID", "eventId", "parent", "drawcallId", "drawId", "x", "y", "z", "size", "duration",
|
||||
};
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
IEventBrowser::EventFilterCallback filterFunction_dispatch(QString name, QString parameters,
|
||||
ParseError &errors)
|
||||
{
|
||||
@@ -1878,6 +1986,9 @@ private:
|
||||
};
|
||||
|
||||
static const NamedProp namedProps[] = {
|
||||
NAMED_PROP("eventid", draw->eventId), NAMED_PROP("eid", draw->eventId),
|
||||
NAMED_PROP("parent", draw->parent ? draw->parent->eventId : -12341234),
|
||||
NAMED_PROP("drawcallid", draw->drawcallId), NAMED_PROP("drawid", draw->drawcallId),
|
||||
NAMED_PROP("dispatchx", draw->dispatchDimension[0]),
|
||||
NAMED_PROP("dispatchy", draw->dispatchDimension[1]),
|
||||
NAMED_PROP("dispatchz", draw->dispatchDimension[2]),
|
||||
@@ -2712,6 +2823,15 @@ EventBrowser::EventBrowser(ICaptureContext &ctx, QWidget *parent)
|
||||
|
||||
ui->filterExpression->setCompletionStrings(completions);
|
||||
}
|
||||
else if(context.startsWith(QLatin1Char('$')) && context.contains(QLatin1Char('(')))
|
||||
{
|
||||
pos = context.indexOf(QLatin1Char('('));
|
||||
|
||||
QString filter = context.mid(1, pos - 1);
|
||||
context.remove(0, pos + 1);
|
||||
|
||||
ui->filterExpression->setCompletionStrings(m_FilterModel->GetCompletions(filter, context));
|
||||
}
|
||||
else
|
||||
{
|
||||
ui->filterExpression->setCompletionStrings({});
|
||||
@@ -3007,7 +3127,8 @@ void EventBrowser::on_filterExpression_keyPress(QKeyEvent *e)
|
||||
filter_apply();
|
||||
}
|
||||
|
||||
if(e->key() == Qt::Key_Dollar)
|
||||
if(e->key() == Qt::Key_Dollar || e->key() == Qt::Key_Ampersand || e->key() == Qt::Key_Equal ||
|
||||
e->key() == Qt::Key_Bar || e->key() == Qt::Key_ParenLeft)
|
||||
{
|
||||
// force autocompletion for filter functions, as long as we're not inside a quoted string
|
||||
|
||||
@@ -3625,9 +3746,10 @@ const DrawcallDescription *EventBrowser::GetDrawcallForEID(uint32_t eid)
|
||||
}
|
||||
|
||||
bool EventBrowser::RegisterEventFilterFunction(const rdcstr &name, EventFilterCallback filter,
|
||||
FilterParseCallback parser)
|
||||
FilterParseCallback parser,
|
||||
AutoCompleteCallback completer)
|
||||
{
|
||||
return EventFilterModel::RegisterEventFilterFunction(name, filter, parser);
|
||||
return EventFilterModel::RegisterEventFilterFunction(name, filter, parser, completer);
|
||||
}
|
||||
|
||||
bool EventBrowser::UnregisterEventFilterFunction(const rdcstr &name)
|
||||
|
||||
@@ -81,7 +81,8 @@ public:
|
||||
APIEvent GetAPIEventForEID(uint32_t eid) override;
|
||||
const DrawcallDescription *GetDrawcallForEID(uint32_t eid) override;
|
||||
bool RegisterEventFilterFunction(const rdcstr &name, EventFilterCallback filter,
|
||||
FilterParseCallback parser) override;
|
||||
FilterParseCallback parser,
|
||||
AutoCompleteCallback completer) override;
|
||||
bool UnregisterEventFilterFunction(const rdcstr &name) override;
|
||||
|
||||
void SetCurrentFilterText(const rdcstr &text) override;
|
||||
|
||||
Reference in New Issue
Block a user