Talk:SMObserver Abstraction
Points to consider
- QAbstractItemView uses a QAbstractItemModel.
- QAbstractItemModel interface requires a hierarchical table format.
- To display a graph, a link object can be used to form a tree.
- Having an object instance for the link is needed for the model.
- Every QAbstractItemView that displays the pipeline will need a tree model.
- Setting up the tree structure can be done in a separate model class that is reused by the various models, or it can be put in the pqServerManagerModel.
- The argument for doing the work in another class is that the main model is kept as a pure representation of the connections.
- The argument for puting the tree structure in the main model is convenience. The model can still be traversed like a graph. The link item is just an extra step when traversing the model.
- The pipeline model is a convenience for the gui. The gui will most likely be using Qt model/views in order to unify selection of gui items. Qt's selection model will be used to accomplish this, which only works with a QAbstractItemModel.
Data Structure
The Following data structure is based on the data needed for each object. The lines represent inheritence.
The base class stores the object type. This is a convenience for the model. The type can also be determined by dynamically casting the the instance. The server has a list of source objects that can be a true source or a fan-in point. The source object has a list of outputs that can be a filter or a link item to a filter. The filter object has a list of input sources. The filter inherits the output list from the source object. The link has a pointer to its input source. It also has a pointer to the filter the source is connected to.
Changes to the Redesign
The overall design will remain the same. The pqServerManagerModel will build a tree instead of a graph. More signals will be added to the pqServerManagerModel to notify the pqPipelineModel of changes. The signals will notify the model when a link is created and a filter is moved. The pqPipelineBuilder will still be used to build and modify the model. The pqServerManagerModel will still respond to events from the server manager to make changes to the data structure. A selection model tied to the pqPipeline model will be used to coordinate the gui. It will determine which proxy is displayed in the object inspector. It will also determine what operations can be performed. The selection model and related behavior should not be part of pqApplicationCore. They can be available for use in other applications, but are not required components. Prism, for instance, will define it's own behavior.
pqServerManagerModel
/// \name Server List Methods //@{ int getServerCount() const; pqPipelineServer *getServer(int index) const; int getServerIndexFor(pqPipelineServer *server) const; //@} /// \name Object Mapping Methods //@{ pqPipelineServer *getServerFor(pqServer *server) const; pqPipelineServer *getServerFor(vtkIdType connectionId) const; pqPipelineSource *getSourceFor(vtkSMProxy *proxy) const; pqPipelineDisplay *getDisplayFor(vtkSMDisplayProxy *display) const; pqRenderModule *getRenderModuleFor(vtkSMRenderModuleProxy *module) const; //@} public slots: /// \name Model Modification Methods //@{ void addServer(vtkIdType connectionId); void removeServer(vtkIdType connectionId); void addSource(QString name, vtkSMProxy *proxy); void addFilter(QString name, vtkSMProxy *proxy); void addBundle(QString name, vtkSMProxy *proxy); void removeSource(vtkSMProxy *proxy); void inputChanged(vtkSMProxy *sink); void addDisplay(QString name, vtkSMDisplayProxy* proxy); void removeDisplay(vtkSMDisplayProxy *proxy); void addRenderModule(QString name, vtkSMRenderModuleProxy *module); void removeRenderModule(vtkSMRenderModuleProxy *module); //@} signals: void serverAdded(pqPipelineServer *server); void removingServer(pqPipelineServer *server); void sourceAdded(pqPipelineSource *source); void removingSource(pqPipelineSource *source); void temporarilyRemovingSource(pqPipelineSource *source); void sourceRestored(pqPipelineSource *source); void linkAdded(pqPipelineLink *link); void removingLink(pqPipelineLink *link); void displayAdded(pqPipelineDisplay *display); void removingDisplay(pqPipelineDisplay *display); void renderModuleAdded(pqRenderModule *module); void removingRenderModule(pqRenderModule *module);
Graph vs Tree Representation
We have been having discussions about this on and off for a while now. The problem is that Qt model is designed to represent lists, tables and trees. From doc.trolltech.com:
QAbstractItemModel provides an interface to data that is flexible enough to handle views that represent data in the form of tables, lists, and trees.
However, VTK's pipeline and some other data structures (for example in the area of information visualization) that we deal with are graphs. Our current pipeline browser takes VTK's pipeline graph and simplifies it (by replacing fan-ins with links) so that it can be shown using a tree view. This is a good compromise and conveys much more information than the simple list view while still requiring a simpler implementation than a full-blown pipeline viewer. This should not, however, mean that we implement our pipeline model as a tree. Because if we do this, we are inheriting the compromise that we had to make for the tree view to work in our pipeline model and all future views will have to be aware of this. Whether we implement a flat list view or a full-blown pipeline view, the links are not necessary and should not be in the pipeline model.
Qt's model/view implementation is very nice and we should probably try to follow it as much as we make. Wherever we can't, we should still follow it's design goals and implement our own model/view classes. In this spirit, server manager model makes sense. It is not a subclass of QAbstractItemModel but it is a model nevertheless. When we write our full-blown pipeline viewer, it can be built on this.
One big improvement on the current implementation will be to abstract the graph model out so that the view is not dependent on a model that directly talks to server manager. Something like GraphModel -> ServerManagerModel. All pipeline views should then only use the GraphModel API so that they could be pulled out of ParaQ and re-used in other projects. This is not required for our immediate goals so we can put it off until we have more time in a few months. We might even be able to leverage our infovis work to implement the graph view.
Let's keep the existing design and make whatever improvements we can while we move forward with the tree-based pipeline view. Once we make the May release, we can go back and rename some of the classes for consistency.
Berk 16:46, 22 May 2006 (EDT)
- The full-blown pipeline viewer can be written as a QAbstactItemView. Not only can it be written this way, but it should be. Qt not only abstracts model/view, but also model selection. The same model and selection model can be shared between views. Having a pipeline browser and pipeline graph that share the same model and selection simplifies the gui tremendously. Otherwise, some sort of selection synchronization needs to be written. As far as reusability goes, a QAbstactItemView graph would be useful to other Qt applications.
- There will be limitations on a QAbstactItemView pipeline graph. The model will need to be abstracted to give the view knowledge of the link items. With that access, the view can jump past the link item to the real item. The view would only be able to display fan-in with the special model type.
- If all gui views of the pipeline data require a QAbstractItemModel, which requires a tree, why use a different representation? The data is solely for the gui's use. Why not have it in a form the gui accepts? I like splitting the Qt model from the data representation. The Qt model code can be a bit confusing. Having them separate can simplify things. Having them separate is required for reusing the pipeline code in Prism.
- --Mark Richardson 18:54, 22 May 2006 (EDT)