Proposed changes to Qt view & item registration

Purpose

There are a few places where registration happens in SMTK that do not use the new Schwarz counter and plugin management stuff that TJ put in:

  • Qt view & item constructors are handled in qtSMTKUtilities; and
  • smtk::common::Extension classes also use old-style static registration

We would like to refactor these so that the API is consistent and takes advantage of the new mechanism.

Proposal

Qt item and view constructors

With SMTK MR 1753, there is now an smtk::view::Manager object that is more of a factory than anything else (it creates PhraseModel and SubphraseGenerator instances). We should expand its role to the creation of new views in a GUI-independent way.

Note that unlike the resource Manager (which manages resources but does not require resources to be managed to be useful), the view Manager will be necessary for most views to function properly.

This work will involve the following changes:

  1. In smtk::view, rename the View class to Configuration to avoid name collision/confusion below.
  2. Create a derived class smtk:::extension::qtConfiguration, and have it hold a weak pointer to the view Manager that created it.
  3. Create a new smtk::view::View class and make qtBaseView inherit it.
  4. Add a method to smtk::view::Manager named create(const view::Configuration&) that will construct a new smtk::view::View subclass, passing its constructor the view configuration.
  5. Create a new smtk::extension::qtConfiguration class that inherits smtk::view::Configuration; its purpose is to take the place of smtk::extension::ViewInfo (Qt-specific view configuration).
    a. Since this object inherits view::Configuration, it need not own an instance of it. By using emplacement and move semantics, it will be possible for a Qt view containers (i.e., ParaView panels or other application components) to efficiently convert a hierarchy of smtk::view::Configuration objects into smtk::extension::qtConfiguration instances as needed.
    b. This class will own a QLayout dictionary and hold a pointer to a QWidget.
  6. Add methods to the view::Manager to register and unregister View constructors.
  7. Create a subclass of smtk::view::Manager that is specific to Qt - smtk::extension::qtManager. Beyond the basic view manager, this class will
    a. have register and unregister methods for qtItem constructors
    b. have register and unregister methods for qtModelView constructors (QTreeView, QListView, etc.)
    c. provide methods currently housed in qtUIManager that deal with application-wide configuration information such as colors and settings. Since every view holds a weak pointer to the manager which created it, it is accessible everywhere qtUIManager is currently used.
  8. Remove the qtSMTKUtilities class (the view manager holds custom view constructors and the Qt-specific view manager holds custom item and modelview-widget constructors).
  9. Remove the qtUIManager class (the Qt-specific view manager, smtk::extension::qtManager, should replace it).

Extension registration

We have two alternatives:

  • a minimal change to the extensions to use the Registrar pattern while maintaining the existing pattern or
  • adapting the smtk::common::Generator pattern to deal with extension-like behavior.

@tj.corona probably has strong opinions here; this page is a wiki so he can edit this section to provide more details of what he wants to see.

I have used all three patterns for registration (Extension, Generator and Registrar). I think the Extension and Generator are pretty similar, and are good for situations where feature extension is intended to be at global scope (such as registering a reader for a file type). They can probably be merged into one pattern. The Registrar pattern is more for augmenting the main features of SMTK; we should probably keep the number of manager types to a maintainable level.

Since the current view::View class (which will be named something like view::Configuration (or Spec, Specification, etc…) ) represents the serializable aspects of the View (XML or JSON) - I would hate to have it “contaminated” with none serializable information like pointers to view managers or QWidgets. That is the current role of the ViewInfo class(es). So I would propose we keep ViewInfo (maybe rename it) - and create a non-qt base class for it. Maybe call it view::Construction and a derived extension::qtViewConstruction (or qt::ViewConstruction if we decide to move all qt named classes into a qt:: namespace). The view::Construction class would simple hold onto a view::Configuration instance while the qt version would hold onto things like the View’s parent Widget).

Then all factory methods would take in a view::Construction instance.

@Bob_Obara I’ve changed the ViewConfiguration class name in a few more places above. The other thing we discussed offline was namespaces. I used smtk::qt::Configuration and smtk::qt::Manager, but to be consistent with what’s currently in SMTK we would use smtk::extension::qtConfiguration and smtk::extension::qtManager. I think putting Qt-specific stuff inside smtk::view could be problematic unless we do something like smtk::view::qt.

I am fine keeping the configuration (you also mentioned specification as an alternative) separate from the other “construction state” and will update the plan above some time soon.

Backtracking a bit:

  • +1 for keeping smtk::view::View a “final” class in order to preserve its current serialization. As for potentially renaming it, I would add smtk::view::Definition to the list of candidate names, analogous to attribute and item definition.
  • As for a common base class (that would contain the renamed smtk::view::Definition) I think we could repurpose the current smtk::view::View.

Bob and I discussed, and we think reusing an existing name for this will be very confusing, and impossible to document accurately. I think we settled on smtk::view::BaseView, as opposed to Base or BaseImplementation.

We’re also unsure of how the conversion from view::configuration to extension::qtConfiguration would work - would it seem like you are re-constructing the objects just to use them? Also, for consistency, the name might need to be extension::qtViewConfiguration - if the extension namespace is a grab-bag of stuff.

Gonna try to meet about it tomorrow.

After some discussion and reflection, here is another attempt to outline the new design, the reasons for it, and then the way we might work towards it in small steps instead of a cliff dive.

Proposed Design

The diagram above shows several new and renamed classes in the smtk::view namespace:

  • view::Manager ‒ Maintain a list of views, a list of view configurations (as read from project resources), and act as a factory for views and the items they contain.
  • view::Configuration ‒ Hold specifications for a view independent of any UI that is read from project resource files.
  • view::Confguration::Component (or view::Configuration::Item) ‒ Same as above but for components of a view rather than the view itself.
  • view::View ‒ A base class for all views (Qt-specific or not; attribute-specific or model-specific). Note that currently, all of SMTK’s views end up being ParaView panels. While it is possible that ParaView’s 2-D and 3-D visualization views might also become SMTK views, that would complicate saving server-manager state. The basic capabilities of a view are to:
    • report their parent view (if any);
    • contain items (optional);
    • accept new view::Configurations as the workflow requests changes; and
    • respond to operations and other changes to SMTK objects.
  • view::Component (or view::Item) ‒ A base class for all visual components of views. The basic capabilities of an item are to:
    • report their parent view and (if any) parent item;
    • contain items (optional);
    • accept new view::Configuration::Components as the workflow requests changes; and
    • respond to operations and other changes to SMTK objects.
  • view::Panel — (not shown) a base class for application panels that contain views. This allows projects or plugins to specify a set of windows/panels each of which may be configured to show a view.

Qt-specific subclasses of view::View and view::Item would dual-inherit both the SMTK class and QWidget.

Benefits

The design above would

  • allow the view::Manager class to maintain a list of views that applications could manage, rather than just act as a factory for views and items;
  • refactor more of the UI code that need not be dependent on Qt into the smtk::view namespace (inside smtkCore);
  • reduce the number of classes we maintain (by removing Qt-specific item and view “Info” classes)
  • adopt a more Qt-like pattern for the widgets (where attribute, item, and view classes inherit QWidget instead of managing QWidgets).
  • adopt a more SMTK-like manager-observer pattern for views.
  • allow SMTK applications to manage GUIs built with other toolkits. An example would be a web environment where SMTK running through Python served a client web browser with HTML “renderings” of an attribute system that would update attributes on the server. This use case would let SMTK provide interactive renderings of large 3D models from the server while sending attribute panel components to the client.

Incremental Implementation

These changes could be made in several steps (largely outlined in the top post of this topic).

  • Implement view::View and view::Item as core classes, then change qtItem and qtBaseView to inherit them.
  • Make attribute reader store view::Configuration in the view::Manager rather than attribute resources.
  • Refactor away qtSMTKUtilities into view::Manager.
  • Remove the factory API from qtUIManager in favor of view::Manager.
  • Change the inheritance of qtItem and qtBaseView to QWidget.This step would also need to refactor away Qt helper classes like qtAttributeItemInfo.

There was talk a while ago about smtk::view moving out of core. Is now a good time to revisit that possibility?

The only real barrier is smtk::attribute, whose resource currently deserializes view::Configuration.