Proposal: Application-specific panel configurations

Problem statement

Currently ParaView-based SMTK applications have the opportunity to change the initial layout of panel positions, but not which set of panels are available. As applications are becoming more tailored to different workflows, some panels are not meaningful to some applications.

Proposed Solution

Instead of having the smtkPQComponentsPlugin instantiate a fixed set of panels, provide a method that cmb-based applications can invoke to create a configurable set of panels given XML (or eventually JSON) like the following:

  <Panels>

    <Panel Name="Projects" Border="Left" Tile="0" Tab="0">
      <View Type="pqSMTKProjectBrowser">
      </View>
    </Panel>

    <Panel Name="Toolbox" Border="Left" Tile="1" Tab="0"
       DefaultVisibility=false> <!-- Unless specified, panels are visible -->
      <View Type="qtOperationToolbox">
      </View>
    </Panel>

    <Panel Name="Operations" Border="Left" Tile="2" Tab="0">
      <View Type="qtOperationEditor">
      </View>
    </Panel>

    <Panel Name="Resources" Border="Right" Tile="0" Tab="0">
      <View Type="pqSMTKResourceBrowser">
        <PhraseModel Type="smtk::view::ResourcePhraseModel">
          <SubphraseGenerator Type="default"/>
          <Badges>
            <Badge Type="smtk::view::LockedResourceBadge"/>
            <Badge Type="smtk::extension::paraview::appcomponents::VisibilityBadge"/>
            <Badge Type="smtk::extension::qt::TypeAndColorBadge"/>
          </Badges>
        </PhraseModel>
      </View>
    </Panel>

    <!-- An attribute placeholder; users provide a resource/view to edit -->
    <Panel Name="Attributes" Border="Right" Tile="0" Tab="1">
      <View Type="pqSMTKAttributeEditor">
      </View>
    </Panel>

    <!-- A fixed attribute; users cannot change the configuration directly. -->
    <Panel Name="Attributes" Border="Right" Tile="0" Tab="1">
      <!-- Either the panel would monitor the resource manager
           for the proper resource or the Instanced attribute widget
           would be modified to do so. -->
      <Source Type="smtk::attribute::Resource" Role="app_foo"/>
      <View Type="Instanced">
        <InstancedAttributes> ... </InstancedAttributes>
      </View>
    </Panel>

  </Panels>

Note that in the example above, the View tags and their children would be exactly what is parsed by the attribute system currently. What has been added is the set of panels that contain views. Thus SMTK would only need to provide a single ParaView panel; it would hold a qtBaseView configured by on <Panel> tag above. The ViewWidgetFactory owned by the smtk::view::Manager would be used to to create the panel contents.

While JSON could also be used, the serialization for smtk::view::Configuration::Component is awkward at best. In the future, it would be preferable to eliminate this class in favor of simply passing XML or JSON snippets to the view or item directly.

Tiles and Tabs

In the XML above, each <Panel> tag has Border, Tile, and Tab attributes. The border (Left, Right, Top, Bottom) specifies the position of the panel relative to the central application view widget. Each of these areas is divided into tiles by horizontal and vertical splits. Finally, each tile can hold multiple panels (they are tabbed when more than one panel is present in a tile).

So, beyond the configuration in the XML above, it would be useful to store the splits of each border area and which tiles lie in each. The example above might have:

  <Layout>
    <Border Area="Left">
      <VSplit><Tiles>0,1,2</Tiles></VSplit>
    </Border>
    <Border Area="Right">
      <VSplit><Tiles>0,1</Tiles></VSplit>
    </Border>
  </Layout>

that splits all tiles vertically in each area. But the following would also be possible:

  <Layout>
    <Border Area="Left">
      <HSplit>
        <Tiles>0<VSplit>
          <Tiles>1,2</Tiles>
        </VSplit></Tiles>
      </HSplit>
    </Border>
    <Border Area="Right">
      <VSplit Tiles="0,1">
    </Border>
  </Layout>

This would put the project panel to the left of the operation toolbox and editor panels (which would be vertically stacked).

+1 on the concept. Certainly the apps I work with could use this.

One feature request: add an optional flag to set panel visibility

Implementation might be tricky given the nondeterministic order that plugins get loaded. Maybe the new software would create an empty panel for each view whether or not it’s currently registered, and then listen to the pqPluginManager plugin-loaded signal and check if the missing views have appeared?

@johnt Thanks, I’ve modified the top post to incorporate a DefaultVisibility XML attribute.

You are correct that plugin load order could become an issue. However, the easy solution is to create the panels but not configure their view widgets until the event loop becomes active (i.e., use a Qt::QueuedConnection to signal configuration). Having the panels created at app-initialization is important since their layout can be changed once each user’s settings are applied.

I’ve also added some comments based on the discussion in today’s meeting about how the lifecycle would be managed for panels when attribute resources might not be immediately present.