Python bindings for custom PV widgets

Dear PV devs,

I hope you could assist with the following challenge:

We have conjured a small xml/C++ plugin with custom QT widgets and not all of them are represented in the XML file. Now we would like to manipulate the widget values via a python script, similar to how “trace” and “paraview.simple” would do it.

Could you give some directions on how such PV-friendly python bindings could be implemented?

My sincere gratitude,
Art

We have figured it out! The answer was right in front of us, i.e. Q_PROPERTY.

Many thanks,
Art

Dear all,

Our success with Q_PROPERTY was somewhat limited, hence I ask for assistance once again.

To recap, we have a C++ plugin with internal variables A, B, where A is a float and B is a string. We would like to set these variables within ParaView’s python console as

plugin.A = 2.5
plugin.B = "string"

Currently, the connection to python is done via this construct

Q_PROPERTY(QList<QVariant> Values READ GetValues WRITE SetValues)

which enables the above python calls. However, the Q_PROPERTY approach turned out to have a notable flaw, namely QList<QVariance> in C++ translates into python as list of floats only, although QVariance can contain numbers, strings and more.

Is there any other approach to connect C++ plugin to a python console in ParaView? Is the Q_PROPERTY approach not meant to be used this way in the first place?

Any expertise on the matter is appreciated. Many thanks,
Art

Q_PROPERTY is definitely meant to be used in a custom property widget.

See Plugins/LagrangianParticleTracker/pqIntegrationModelSeedHelperWidget.h for an example.

Hello Mathieu,

Thank you for a prompt reply.

Our implementation is very similiar to your example. Specifically, here is our C++ part:

(plugin.h) 
Q_PROPERTY(QList<QVariant> Values READ GetValues WRITE SetValues)

and

(plugin.cpp)
void plugin::SetValues(const QList<QVariant>& values)
{
    if(values.count() == 0)
        return;

    std::cout << "values[0] = " << values[0].toString().toStdString() << std::endl;
    std::cout << "values[1] = " << values[1].toString().toStdString() << std::endl;
}

When updated from a python console as plugin.values = [1, 3.5], the (correct) output is

values[0] = 1
values[1] = 3.5

But this update plugin.values = [1, 'a'] (with a char/string) raises an error:

../paraview/servermanager.py", line 820, in SetData
    self.SMProperty.SetElement(idx, val)
TypeError: SetElement argument 2:

which, if I understand correctly is an index error. Yet, the number of elements in the array is the same. I can’t figure out what I’m doing wrong here.

Thanks a lot,
Art

Are you using a StringVectorProperty in your XML file ?

That is it!

It was a <DoubleVectorProperty>, changing to <StringVectorProperty> removed the error.

Two more questions:
(1) Is there a way to have a mixture of doubles and strings?
(2) Can I have nested structures like lists inside lists?

  1. StringVectorProperty allows you to specify the element types, int double or string. Search for element_types

  2. No, but you can have sort of two dimensional vectors by using number_elements_per_command

I will look into element_types, thanks a lot.

I also saw in your example that you emulate nested structures by splitting strings via a separator ;, we might try that as well.

Thanks a lot for all the help.

Best,
Art