Populate a StringVector from a file

Hello all,

I have a filter written in Python that presents the user a StringVector for text entry and a filechooser for selecting an optional input file (RequestData processes differently depending on which entry method the user has chosen). Is there a way I can write the contents of the file to the StringVector before Apply is pressed to allow the user to edit it?

Many thanks,

Duncan

This is usually done with either a default value or a domain, which are the same in python or xml plugins.

See here :
https://kitware.github.io/paraview-docs/latest/cxx/PluginHowto.html

Hi Mathieu,

Thanks for your reply.

I’ll check out the link you provided. The Default Value tag allows me to set the initial value of the StringVector before the user selects a file. I can’t see a way of updating this and redrawing the StringVector after a user picks a file with the chooser?

This is what I have so far:

from paraview.util.vtkAlgorithm import (
VTKPythonAlgorithmBase,
smdomain,
smhint,
smproperty,
smproxy,
)

from vtkmodules.numpy_interface import dataset_adapter as dsa
from vtkmodules.vtkCommonDataModel import (vtkDataSet, vtkCompositeDataSet, vtkMultiBlockDataSet, vtkUnstructuredGrid)

@smproxy.filter(label=“Myfilter”)
@smhint.xml(r"".format(os.path.join(PLUGINDIR,‘icons’,‘myicon.png’)))
@smhint.xml("")
@smproperty.input(name=“Input”, port_index=0)
@smdomain.datatype(dataTypes=[“vtkMultiBlockDataSet”], composite_data_supported=True)
class Myfilter(VTKPythonAlgorithmBase):
def init(self):
VTKPythonAlgorithmBase.init(self, nInputPorts=1, nOutputPorts=1, inputType=“vtkMultiBlockDataSet”, outputType=“vtkMultiBlockDataSet”)
self._text = None
self._filename = None

@smproperty.stringvector(name="Text")
@smdomain.filelist()
@smhint.filechooser(
    extensions=['txt'], file_description="Text File"
)
def SetFileName(self, filename):
    if self._filename != filename:
        self._filename = filename
        self.Modified()

@smproperty.stringvector(name="TextBox", default_values="Enter TEXT here or load a file below")
@smhint.xml(r"<Widget type='multi_line'/>")
def SetText(self, text):
    if self._text != text:
        self._text = text
        self.Modified()

def RequestData(self, request, inInfoVec, outInfoVec):

    thisMultiblock = dsa.WrapDataObject(vtkMultiBlockDataSet.GetData(inInfoVec[0]))
    output = dsa.WrapDataObject(vtkMultiBlockDataSet.GetData(outInfoVec))

    self.SetProgressText('Processing Multiblock')
    self.UpdateProgress(0.1)
    
    if self._filename is not None:
        with open(self._filename,'r') as f:
            self._text = ''.join(f.readlines())

    thisNewMultiblock = myClass.myFunction(thisMultiblock,self._text).multiblock

    output.ShallowCopy(thisNewMultiblock)
    
    self.SetProgressText('Done')
    self.UpdateProgress(1.0)
    return 1

Let me get this straight, you want the StringVectorProperty to be initialized from the content of a file, which is identified in any another property ?

I’m afraid that is not possible in a Python plugin.

Afaik, it is not (yet) possible to initialize a property using the value of a single string in a FielData. (which could have been a way to emulate what your are looking for).

This would be doable only with a C++ plugin with custom widgets.

Thanks Mathieu,

To confirm, I’d like to give the User the option of typing some data into the text box (in my case it will be a JSON string) or using the filechooser, select a JSON file which then populates the text box. The user can then edit that text before pressing Apply.

What I have so far works in that the User can either copy/ paste the contents of a file into the textbox or choose the Json file from the chooser. The contents can then be edited in notepad etc.

This is different to a Reader in that I am loading processing parameters from the JSON to apply to a multiblock on the pipeline, therefore I do not see the need to store parameters in fielddata for subsequent display in the textbox.

As you say Custom widgets is probably the way to go but the platform and version independence that Python plugins gives me massively outweighs the overhead of building ParaView and developing C++ plugins against it.

Thanks for your help and advice,

Duncan