Here are some broad plans on how to customize descriptive phrases for RGG. The basic idea is to make the resource panel inherit qtBaseView and use its XML configuration to control what the panel displays. Then a ParaView-aware and RGG-aware selection observer can change what is rendered and selectable.
Resource panel
The qtResourceBrowser (inherited by pqSMTKResourceBrowser) should itself inherit qtBaseView and accept configuration via the smtk::view::View class. The specific things that should be configurable:
which smtk::view::PhraseModel subclass to use for its QAbstractItemModel;
whether to use an intermediate QSortFilterProxyModel and add GUI controls (a search text entry and sort control buttons) to the panel;
which smtk::view::SubphraseGenerator subclass to use (and any configuration controls that are required);
Custom RGG PhraseModel subclass
PhraseModel subclasses determine what phrases make up the top-level items of a QAbstractItemModel in a QTreeView. RGG wants this to be a fixed set corresponding to functional groups (pins, ducts, assemblies, cores). For the purpose of this discussion, let’s say the new class is named smtk::session::rgg::PhraseModel.
Customizable subphrase generator
Rather than hardcode a subphrase generator to list pins under the smtk::session::rgg::PhraseModel's top-level “pins” item, we should create a new class (say smtk::view::QueryPhraseModel for this discussion). That class could hold a map<std::string, std::string> that uses top-level phrase title() strings as keys and returns query-strings to pass to smtk::resource::Resource::find().
Note that the subphrase generator is responsible for implementing both the subphrases() and subphrasesForCreatedObjects() methods. The former is called when the view is first created or a tree item expanded ‒ it must provide an ordered list of subphrases on demand; the latter is invoked when SMTK operations report newly-created objects (components) in their results ‒ it must provide new phrases and their locations corresponding to each new object, but only where the parent phrase already exists.
RGG selection behavior
To provide RGG users with control over what is visualized, a selection observer can identify when a pin/duct/assembly/core is selected and update component visibility in ParaView (as well as change the camera as needed).
Do yo mean that QueryPhraseModel should be a generic class that can be reused by other sessions? As a result RGGSubphraseGenerator is just a subclass user who uses the API defined in this class?
You should not need to write an RGGSubphraseGenerator class. Instead the rgg session will provide <View>...</View> configuration XML that tells the QueryPhraseModel what to do. For example, we might have
It looks like @aron.helser’s changes are in SMTK MR 1753 and @Haocheng_Liu’s changes are in SMTK MR 1741. I just want to make sure the train tracks meet in Promontory, UT… have you two looked at each other’s work?
@Haocheng_Liu
a. Do you see how to register your new PhraseModel and SubphraseGenerator subclasses?
b. And how to call pqSMTKResourcePanel::setView() inside your plugin’s autostart?
@aron.helser Are there things missing from the view configuration information that Haocheng’s work will need?
Not yet. But I’m aware of Aron’s work and try to keep my interaction with ResourceBrowser and ResourcePanel as little as possible to mitigate the transition cost as you’ve adviced.
I think we are all set to allow a custom PhraseModel and SubphraseGenerator. I see RGG will be compiled in, so this should work:
Add new subclasses to the lists in smtk::view::Registrar
Copy ResourcePanelConfiguration.json from extension/paraview/appcomponents and modify it with the new class names. Add the new .json to CMakeLists.txt so it gets converted to a header
When RGG is activated, pass the string representing the json to the json parser, which creates a smtk::view::View to pass to pqSMTKResourcePanel::setView()
Of course, I’ve only tried it with ResourcePhraseModel, and default or TwoLevel SubphraseGenerator, so we’ll probably run into some issues, but hopefully my MR can get merged today(?) so you can try it out.
OK, quick talk with David, and my three bullets aren’t sufficient when RGG is a plugin. Instead, you need to take some additional steps:
The plugin needs to create its own Registrar.[h,cxx], patterned after the one in smtk::view, which lists the PhraseModel and SubphraseGenerator subclasses it wants to register.
in CmakeLists.txt, add (or augment) two properties inside add_smtk_plugin() (with the right namespace for Registrar, look at smtk::view for an example):
Copy ResourcePanelConfiguration.json from extension/paraview/appcomponents and modify it with the new class names in the Type attributes. Add the new .json to CMakeLists.txt so it gets converted to a header. The current one looks like:
# put contents of this file in a string in a header. It's not xml, but it still works.
smtk_operation_xml("${CMAKE_CURRENT_SOURCE_DIR}/ResourcePanelConfiguration.json" smtkResourcePanelJSON)
Inside the plugin’s AutoStart file, get the json string:
// cmake puts the .json file contents into a static string, named _xml
#include "..../ResourcePanelConfiguration_xml.h"
In the setup() method, parse the json and create the view, something like this:
for (QWidget* w : QApplication::topLevelWidgets())
{
auto mainWindow = dynamic_cast<QMainWindow>(w);
if (mainWindow)
{
auto dock = mainWindow->findChild<pqSMTKResourcePanel*>();
if (dock)
{
dock->setView(viewInfo);
}
}
}
With the current smtk master + ParaView master, I can no longer find the pqSMTKResourcePanel. Any idea what’s going on here?
Edit: Now the construction of pqSMTKResourcePanel(aka smtkPQComponentsExt) is after the rgg autostart(aka loading smtkRGGSessionPlugin). Humm, let me see what I can do here.
It turns out that we are hitting the indeterministic ordering of static initialization. In my case, the smtkRGGSessionPlugin is loaded before smtkPQComponentPlugin so the pqSMTKResourcePanel has not been constructed yet. I got a not so beautiful solution to solve the problem here. Ideas?