Improved node saving and loading
- Storable node can decide what is the most appropriate storage node, based on the requested file name and storable node content. This allows simplifications and removal of "special case" hacks throughlout the code base.
- Allow overriding default write file extension in storage nodes (instead of hardcoding DefaultWriteFileExtension string, it is now stored in a member variable). For example, changing default model node saving extension can be achieved by this:
msn=slicer.vtkMRMLModelStorageNode()
msn.SetDefaultWriteFileExtension('stl')
slicer.mrmlScene.AddDefaultNode(msn)
- Improved composite file extension support (.nii.gz, .seg.nrrd, ...). In "Add data dialog" the most specifically matched extension's reader is selected by default (for example, .nrrd is more specific than .*; .seg.nrrd is more specific than .nrrd). File extension matching has been more robust: instead of using heuristics, such as assuming .gz means a composite file extension and collecting all possible extension from all storage nodes; now extensions are mostly managed by the storage node, which knows exactly what extensions are possible.
In the future, composite extensions could be used for more file formats where we use the same extension for storing different node types (annotations, markups, labelmap/scalar volumes, etc) and there would be no more needs for heuristics or manual user choices for selecting the correct node type.