Python pref page: custom rendering with default load and save

Here's the place for discussion related to coding in FreeCAD, C++ or Python. Design, interfaces and structures.
Forum rules
Be nice to others! Respect the FreeCAD code of conduct!
Post Reply
User avatar
chennes
Veteran
Posts: 3881
Joined: Fri Dec 23, 2016 3:38 pm
Location: Norman, OK, USA
Contact:

Python pref page: custom rendering with default load and save

Post by chennes »

The Addon Manager uses a simple *.ui file as its preference page, created like so:

Code: Select all

        FreeCADGui.addPreferencePage(
            os.path.join(os.path.dirname(__file__), "AddonManagerOptions.ui"),
            translate("AddonsInstaller", "Addon Manager"),
        )
This works fine. But the page has some deficiencies in its behavior, so I'd like to change it to use a Python class to handle the dialog interactions (in particular the list of external repos should be a table with a + and - button, if you're curious what I want to change). So basically the new creation code is:

Code: Select all

        FreeCADGui.addPreferencePage(
            AddonManagerOptions,
            translate("AddonsInstaller", "Addon Manager"),
        )
where AddonManagerOptions is a simple class that loads the UI file, and manages the interaction with that one widget. In an ideal world, though, I'd like all of the other widgets to continue being automatically managed by the preferences system (e.g. loading and saving their data without me doing it manually). Is there a way for me to "forward" the calls to loadSettings and saveSettings to those widgets?

Something like:

Code: Select all

class AddonManagerOptions:

    def __init__(self, parent=None):
        self.form = FreeCADGui.PySideUic.loadUi(
            os.path.join(os.path.dirname(__file__), "AddonManagerOptions.ui")
        )

    def saveSettings(self):
        self.form.guiprefcheckboxcheckupdates.saveSettings()
    
    def loadSettings(self):
        self.form.guiprefcheckboxcheckupdates.loadSettings()
(This doesn't work as I have it written, I get an error that a QCheckBox doesn't have that function).
Chris Hennes
Pioneer Library System
GitHub profile, LinkedIn profile, chrishennes.com
openBrain
Veteran
Posts: 9034
Joined: Fri Nov 09, 2018 5:38 pm
Contact:

Re: Python pref page: custom rendering with default load and save

Post by openBrain »

Just a guess, but IIRC the functions are called 'onSave()' and 'onLoad()' at widget level.
openBrain
Veteran
Posts: 9034
Joined: Fri Nov 09, 2018 5:38 pm
Contact:

Re: Python pref page: custom rendering with default load and save

Post by openBrain »

Could you try something like ?

Code: Select all

QtCore.QMetaObject.invokeMethod(self.form.guiprefcheckboxcheckupdates, "onSave", QtCore.Qt.DirectConnection)
User avatar
chennes
Veteran
Posts: 3881
Joined: Fri Dec 23, 2016 3:38 pm
Location: Norman, OK, USA
Contact:

Re: Python pref page: custom rendering with default load and save

Post by chennes »

Thanks -- that's heading me in the right direction, I think. In C++ the functions are called onSave() and onRestore(), but apparently in Python they either don't exist or are called something else. Using your idea of calling invokeMethod() now gives the error

Code: Select all

09:57:37  QMetaObject::invokeMethod: No such method Gui::PrefCheckBox::onRestore()
So it's calling the method on the right type of object, anyway, which is am improvement! (Actually, in an idea world I wouldn't do this one widget at a time, I'd just invoke the serialization on the overall preference page, so maybe I'll look into that while I'm at it).
Chris Hennes
Pioneer Library System
GitHub profile, LinkedIn profile, chrishennes.com
openBrain
Veteran
Posts: 9034
Joined: Fri Nov 09, 2018 5:38 pm
Contact:

Re: Python pref page: custom rendering with default load and save

Post by openBrain »

chennes wrote: Mon Sep 19, 2022 3:01 pm Thanks -- that's heading me in the right direction, I think. In C++ the functions are called onSave() and onRestore(), but apparently in Python they either don't exist or are called something else.
I found no Python wrapper to expose the class methods. I think they don't exist in Python.
Using your idea of calling invokeMethod() now gives the error
Yep. I just checked and indeed the methods aren't available in the metaObject. Looks like Shiboken does not run on these classes (I even don't know if FreeCAD uses it at all).
Post Reply