Skip to content

Commit

Permalink
+ Support preference pages for Python widget class
Browse files Browse the repository at this point in the history
  • Loading branch information
wwmayer committed Jul 15, 2015
1 parent 62c6a61 commit 3241b1e
Show file tree
Hide file tree
Showing 3 changed files with 169 additions and 10 deletions.
31 changes: 21 additions & 10 deletions src/Gui/ApplicationPy.cpp
Expand Up @@ -532,20 +532,31 @@ PyObject* Application::sCreateDialog(PyObject * /*self*/, PyObject *args,PyObjec
PyObject* Application::sAddPreferencePage(PyObject * /*self*/, PyObject *args,PyObject * /*kwd*/)
{
char *fn, *grp;
if (!PyArg_ParseTuple(args, "ss", &fn,&grp)) // convert args: Python->C
return NULL; // NULL triggers exception
if (PyArg_ParseTuple(args, "ss", &fn,&grp)) {
QFileInfo fi(QString::fromUtf8(fn));
if (!fi.exists()) {
PyErr_SetString(PyExc_RuntimeError, "UI file does not exist");
return 0;
}

QFileInfo fi(QString::fromUtf8(fn));
if (!fi.exists()) {
PyErr_SetString(PyExc_RuntimeError, "UI file does not exist");
return 0;
// add to the preferences dialog
new PrefPageUiProducer(fn, grp);

Py_INCREF(Py_None);
return Py_None;
}
PyErr_Clear();

// add to the preferences dialog
new PrefPageUiProducer(fn, grp);
PyObject* dlg;
if (PyArg_ParseTuple(args, "O!s", &PyClass_Type, &dlg, &grp)) {
// add to the preferences dialog
new PrefPagePyProducer(Py::Object(dlg), grp);

Py_INCREF(Py_None);
return Py_None;
Py_INCREF(Py_None);
return Py_None;
}

return 0;
}

PyObject* Application::sActivateWorkbenchHandler(PyObject * /*self*/, PyObject *args,PyObject * /*kwd*/)
Expand Down
100 changes: 100 additions & 0 deletions src/Gui/WidgetFactory.cpp
Expand Up @@ -729,6 +729,106 @@ void* PrefPageUiProducer::Produce () const

// ----------------------------------------------------

PrefPagePyProducer::PrefPagePyProducer (const Py::Object& p, const char* group)
: type(p)
{
std::string str;
Base::PyGILStateLocker lock;
if (type.hasAttr("__name__")) {
str = static_cast<std::string>(Py::String(type.getAttr("__name__")));
}

WidgetFactoryInst::instance().AddProducer(str.c_str(), this);
Gui::Dialog::DlgPreferencesImp::addPage(str, group);
}

PrefPagePyProducer::~PrefPagePyProducer ()
{
Base::PyGILStateLocker lock;
type = Py::None();
}

void* PrefPagePyProducer::Produce () const
{
Base::PyGILStateLocker lock;
Py::Callable method(type);
Py::Tuple args;
Py::Object page = method.apply(args);
return new Gui::Dialog::PreferencePagePython(page);
}

// ----------------------------------------------------

using namespace Gui::Dialog;

PreferencePagePython::PreferencePagePython(const Py::Object& p, QWidget* parent)
: PreferencePage(parent), page(p)
{
Base::PyGILStateLocker lock;
if (page.hasAttr(std::string("form"))) {
Py::Object widget(page.getAttr(std::string("form")));

Gui::PythonWrapper wrap;
if (wrap.loadCoreModule()) {
QObject* object = wrap.toQObject(widget);
if (object) {
QWidget* form = qobject_cast<QWidget*>(object);
if (form) {
this->setWindowTitle(form->windowTitle());
QVBoxLayout *layout = new QVBoxLayout;
layout->addWidget(form);
setLayout(layout);
}
}
}
}
}

PreferencePagePython::~PreferencePagePython()
{
Base::PyGILStateLocker lock;
page = Py::None();
}

void PreferencePagePython::changeEvent(QEvent *e)
{
QWidget::changeEvent(e);
}

void PreferencePagePython::loadSettings()
{
Base::PyGILStateLocker lock;
try {
if (page.hasAttr(std::string("loadSettings"))) {
Py::Callable method(page.getAttr(std::string("loadSettings")));
Py::Tuple args;
method.apply(args);
}
}
catch (Py::Exception&) {
Base::PyException e; // extract the Python error text
e.ReportException();
}
}

void PreferencePagePython::saveSettings()
{
Base::PyGILStateLocker lock;
try {
if (page.hasAttr(std::string("saveSettings"))) {
Py::Callable method(page.getAttr(std::string("saveSettings")));
Py::Tuple args;
method.apply(args);
}
}
catch (Py::Exception&) {
Base::PyException e; // extract the Python error text
e.ReportException();
}
}

// ----------------------------------------------------

/* TRANSLATOR Gui::ContainerDialog */

/**
Expand Down
48 changes: 48 additions & 0 deletions src/Gui/WidgetFactory.h
Expand Up @@ -236,6 +236,28 @@ class GuiExport PrefPageUiProducer : public Base::AbstractProducer
QString fn;
};

/**
* The PrefPagePyProducer class provides the ability to create preference pages
* dynamically from a Python class.
* @author Werner Mayer
*/
class GuiExport PrefPagePyProducer : public Base::AbstractProducer
{
public:
/**
* Register a special type of preference page to the WidgetFactoryInst.
*/
PrefPagePyProducer (const Py::Object&, const char* group);
virtual ~PrefPagePyProducer ();
/**
* Creates an instance of the specified widget.
*/
virtual void* Produce () const;

private:
Py::Object type;
};

// --------------------------------------------------------------------

/**
Expand Down Expand Up @@ -435,6 +457,32 @@ public Q_SLOTS:
QObject* mySender;
};

// ----------------------------------------------------
namespace Dialog {

/** Subclass that embeds a form from a Python class.
* \author Werner Mayer
*/
class GuiExport PreferencePagePython : public PreferencePage
{
Q_OBJECT

public:
PreferencePagePython(const Py::Object& dlg, QWidget* parent = 0);
virtual ~PreferencePagePython();

void loadSettings();
void saveSettings();

protected:
void changeEvent(QEvent *e);

private:
Py::Object page;
};

} // namespace Dialog

} // namespace Gui

#endif // GUI_WIDGETFACTORY_H

0 comments on commit 3241b1e

Please sign in to comment.