# Plans for RGG and descriptive phrases

**URL:** https://discourse.kitware.com/t/plans-for-rgg-and-descriptive-phrases/323
**Category:** Design
**Created:** [September 26, 2019, 6:22pm UTC](https://discourse.kitware.com/t/plans-for-rgg-and-descriptive-phrases/323 "2019-09-26T18:22:40Z")
**Posts on this page:** 16
**Page:** 1

<div class="post-metadata">

### Author: ![dcthomp](https://discourse.kitware.com/user_avatar/discourse.kitware.com/dcthomp/32/10_2.png) [@dcthomp](https://discourse.kitware.com/u/dcthomp)
#### Post date: [September 26, 2019, 6:22pm UTC](https://discourse.kitware.com/t/plans-for-rgg-and-descriptive-phrases/323/1 "2019-09-26T18:22:40Z")

</div>

Hi all, but esp @Haocheng_Liu and @aron.helser,

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).

---

<div class="post-metadata">

### Author: ![Haocheng\_Liu](https://discourse.kitware.com/user_avatar/discourse.kitware.com/haocheng_liu/32/36_2.png) [@Haocheng\_Liu](https://discourse.kitware.com/u/Haocheng_Liu)
#### Post date: [September 26, 2019, 7:31pm UTC](https://discourse.kitware.com/t/plans-for-rgg-and-descriptive-phrases/323/2 "2019-09-26T19:31:41Z")

</div>

Thanks for the Tips.

> [@dcthomp](#):
>
> ## 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 it 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.

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?

---

<div class="post-metadata">

### Author: ![dcthomp](https://discourse.kitware.com/user_avatar/discourse.kitware.com/dcthomp/32/10_2.png) [@dcthomp](https://discourse.kitware.com/u/dcthomp)
#### Post date: [September 26, 2019, 8:18pm UTC](https://discourse.kitware.com/t/plans-for-rgg-and-descriptive-phrases/323/3 "2019-09-26T20:18:59Z")

</div>

> [@Haocheng\_Liu](#):
>
> Do yo mean that `QueryPhraseModel` should be a generic class that can be reused by other sessions?

Yes.

> [@Haocheng\_Liu](#):
>
> 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

```xml
<View Type="DescriptivePhrase" TopLevel="true" AllowSortFilter="true">
  <PhraseModel Type="RGGPhraseModel"/>
  <SubphraseGenerator Type="QueryPhraseModel">
    <MapPhrase ParentTitle="pins">
      <Resource Type="smtk::session::rgg::Resource" 
        Filter="aux_geom[string{'rgg_type'='pin'}]"/>
   </MapPhrase>
    <MapPhrase ParentTitle="ducts">
      <Resource Type="smtk::session::rgg::Resource" 
        Filter="aux_geom[string{'rgg_type'='duct'}]"/>
   </MapPhrase>
    <MapPhrase ParentTitle="assemblies">
      <Resource Type="smtk::session::rgg::Resource" 
        Filter="group[string{'rgg_type'='assembly'}]"/>
   </MapPhrase>
    <MapPhrase ParentTitle="cores">
      <Resource Type="smtk::session::rgg::Resource" 
        Filter="group[string{'rgg_type'='core'}]"/>
   </MapPhrase>
  </SubphraseGenerator>
</View>

```

(The filter strings are discussed here: [Query filter strings for model resources](https://discourse.kitware.com/t/query-filter-strings-for-model-resources/242) .)

---

<div class="post-metadata">

### Author: ![dcthomp](https://discourse.kitware.com/user_avatar/discourse.kitware.com/dcthomp/32/10_2.png) [@dcthomp](https://discourse.kitware.com/u/dcthomp)
#### Post date: [October 22, 2019, 1:55am UTC](https://discourse.kitware.com/t/plans-for-rgg-and-descriptive-phrases/323/4 "2019-10-22T01:55:19Z")

</div>

It looks like @aron.helser’s changes are in [SMTK MR 1753](https://gitlab.kitware.com/cmb/smtk/merge_requests/1753) and @Haocheng_Liu’s changes are in [SMTK MR 1741](https://gitlab.kitware.com/cmb/smtk/merge_requests/1741). I just want to make sure the train tracks meet in Promontory, UT… have you two looked at each other’s work?

1. @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?

2. @aron.helser Are there things missing from the view configuration information that Haocheng’s work will need?

---

<div class="post-metadata">

### Author: ![Haocheng\_Liu](https://discourse.kitware.com/user_avatar/discourse.kitware.com/haocheng_liu/32/36_2.png) [@Haocheng\_Liu](https://discourse.kitware.com/u/Haocheng_Liu)
#### Post date: [October 22, 2019, 1:06pm UTC](https://discourse.kitware.com/t/plans-for-rgg-and-descriptive-phrases/323/5 "2019-10-22T13:06:18Z")

</div>

> [@dcthomp](#):
>
> @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?

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.

---

<div class="post-metadata">

### Author: ![aron.helser](https://discourse.kitware.com/user_avatar/discourse.kitware.com/aron.helser/32/149_2.png) [@aron.helser](https://discourse.kitware.com/u/aron.helser)
#### Post date: [October 22, 2019, 2:52pm UTC](https://discourse.kitware.com/t/plans-for-rgg-and-descriptive-phrases/323/6 "2019-10-22T14:52:57Z")

</div>

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.

---

<div class="post-metadata">

### Author: ![aron.helser](https://discourse.kitware.com/user_avatar/discourse.kitware.com/aron.helser/32/149_2.png) [@aron.helser](https://discourse.kitware.com/u/aron.helser)
#### Post date: [October 22, 2019, 3:23pm UTC](https://discourse.kitware.com/t/plans-for-rgg-and-descriptive-phrases/323/8 "2019-10-22T15:23:57Z")

</div>

My testing so far has been hacking the default json - I think you are the test case 😀  
Please bug me when you want to get started!

---

<div class="post-metadata">

### Author: ![aron.helser](https://discourse.kitware.com/user_avatar/discourse.kitware.com/aron.helser/32/149_2.png) [@aron.helser](https://discourse.kitware.com/u/aron.helser)
#### Post date: [October 22, 2019, 8:12pm UTC](https://discourse.kitware.com/t/plans-for-rgg-and-descriptive-phrases/323/9 "2019-10-22T20:12:13Z")

</div>

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):

```auto
    REGISTRAR rgg::Registrar
    MANAGERS smtk::view::Manager

```

- 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:

```auto
# 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:

```auto
// 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:

```auto
  nlohmann::json j = nlohmann::json::parse(ResourcePanelConfiguration_xml);
  resourcePanel->setView(j[0]);

```

I don’t actually know how you get ahold of the resourcePanel from the plugin?

---

<div class="post-metadata">

### Author: ![dcthomp](https://discourse.kitware.com/user_avatar/discourse.kitware.com/dcthomp/32/10_2.png) [@dcthomp](https://discourse.kitware.com/u/dcthomp)
#### Post date: [October 22, 2019, 8:18pm UTC](https://discourse.kitware.com/t/plans-for-rgg-and-descriptive-phrases/323/10 "2019-10-22T20:18:19Z")

</div>

> [@aron.helser](#):
>
> I don’t actually know how you get ahold of the resourcePanel from the plugin?

You would do something like this (rough sketch):

```c++
for (QWidget* w : QApplication::topLevelWidgets())
{
  auto mainWindow = dynamic_cast<QMainWindow>(w);
  if (mainWindow)
  {
    auto dock = mainWindow->findChild<pqSMTKResourcePanel*>();
    if (dock)
    {
      dock->setView(viewInfo);
    }
  }
}

```

---

<div class="post-metadata">

### Author: ![Haocheng\_Liu](https://discourse.kitware.com/user_avatar/discourse.kitware.com/haocheng_liu/32/36_2.png) [@Haocheng\_Liu](https://discourse.kitware.com/u/Haocheng_Liu)
#### Post date: [October 22, 2019, 8:20pm UTC](https://discourse.kitware.com/t/plans-for-rgg-and-descriptive-phrases/323/11 "2019-10-22T20:20:11Z")

</div>

😳 Thanks guys. I will be the daredevil to try it out once the view stuff lands in master and bug you later!

---

<div class="post-metadata">

### Author: ![Haocheng\_Liu](https://discourse.kitware.com/user_avatar/discourse.kitware.com/haocheng_liu/32/36_2.png) [@Haocheng\_Liu](https://discourse.kitware.com/u/Haocheng_Liu)
#### Post date: [November 25, 2019, 3:35pm UTC](https://discourse.kitware.com/t/plans-for-rgg-and-descriptive-phrases/323/12 "2019-11-25T15:35:32Z")

</div>

> [@dcthomp](#):
>
> You would do something like this (rough sketch):
> 
> ```auto
> for (QWidget* w : QApplication::topLevelWidgets())
> {
> auto mainWindow = dynamic_cast<QMainWindow>(w);
> if (mainWindow)
> {
> auto dock = mainWindow->findChild<pqSMTKResourcePanel*>();
> if (dock)
> {
> dock->setView(viewInfo);
> }
> }
> 
> ```

Hi David and Aron,

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.

---

<div class="post-metadata">

### Author: ![aron.helser](https://discourse.kitware.com/user_avatar/discourse.kitware.com/aron.helser/32/149_2.png) [@aron.helser](https://discourse.kitware.com/u/aron.helser)
#### Post date: [November 25, 2019, 4:14pm UTC](https://discourse.kitware.com/t/plans-for-rgg-and-descriptive-phrases/323/13 "2019-11-25T16:14:53Z")

</div>

IDK why that would have changed…

---

<div class="post-metadata">

### Author: ![Haocheng\_Liu](https://discourse.kitware.com/user_avatar/discourse.kitware.com/haocheng_liu/32/36_2.png) [@Haocheng\_Liu](https://discourse.kitware.com/u/Haocheng_Liu)
#### Post date: [November 25, 2019, 5:07pm UTC](https://discourse.kitware.com/t/plans-for-rgg-and-descriptive-phrases/323/14 "2019-11-25T17:07:21Z")

</div>

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](https://gitlab.kitware.com/cmb/plugins/rgg-session/blob/5a4267c758367bf3a4c19124518510b380b15d24/smtk/session/rgg/plugin/smtkRGGAutoStart.cxx#L79). Ideas?

---

<div class="post-metadata">

### Author: ![aron.helser](https://discourse.kitware.com/user_avatar/discourse.kitware.com/aron.helser/32/149_2.png) [@aron.helser](https://discourse.kitware.com/u/aron.helser)
#### Post date: [November 25, 2019, 6:55pm UTC](https://discourse.kitware.com/t/plans-for-rgg-and-descriptive-phrases/323/15 "2019-11-25T18:55:27Z")

</div>

@T.J. Corona Didn’t we have a method for forcing static initialization order?

---

<div class="post-metadata">

### Author: ![Haocheng\_Liu](https://discourse.kitware.com/user_avatar/discourse.kitware.com/haocheng_liu/32/36_2.png) [@Haocheng\_Liu](https://discourse.kitware.com/u/Haocheng_Liu)
#### Post date: [November 25, 2019, 8:35pm UTC](https://discourse.kitware.com/t/plans-for-rgg-and-descriptive-phrases/323/16 "2019-11-25T20:35:13Z")

</div>

I think QTimer::singleshot is the solution we are using right now.

---

<div class="post-metadata">

### Author: ![tj.corona](https://discourse.kitware.com/user_avatar/discourse.kitware.com/tj.corona/32/35_2.png) [@tj.corona](https://discourse.kitware.com/u/tj.corona)
#### Post date: [November 25, 2019, 11:42pm UTC](https://discourse.kitware.com/t/plans-for-rgg-and-descriptive-phrases/323/17 "2019-11-25T23:42:18Z")

</div>

Maybe we can do something with the ParaView registration logic? It is populated during a plugins startup.
