Skip to content

Commit

Permalink
+ Add PySideUic helper module
Browse files Browse the repository at this point in the history
  • Loading branch information
wwmayer committed Jan 9, 2014
1 parent 955d1cc commit e32b747
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 0 deletions.
5 changes: 5 additions & 0 deletions src/Gui/Application.cpp
Expand Up @@ -368,6 +368,11 @@ Application::Application(bool GUIenabled)
Base::Interpreter().addType(UiLoaderPy::type_object(),
module,"UiLoader");

// PySide additions
PySideUicModule* pySide = new PySideUicModule();
Py_INCREF(pySide->module().ptr());
PyModule_AddObject(module, "PySideUic", pySide->module().ptr());

//insert Selection module
PyObject* pSelectionModule = Py_InitModule3("Selection", SelectionSingleton::Methods,
"Selection module");
Expand Down
62 changes: 62 additions & 0 deletions src/Gui/WidgetFactory.cpp
Expand Up @@ -22,6 +22,9 @@


#include "PreCompiled.h"
#ifndef _PreComp_
# include <QTextStream>
#endif

// Uncomment this block to remove PySide support and switch back to PyQt
// #undef HAVE_SHIBOKEN
Expand Down Expand Up @@ -54,6 +57,7 @@ PyTypeObject** SbkPySide_QtGuiTypes=NULL;
#include <App/Application.h>
#include <Base/Console.h>
#include <Base/Exception.h>
#include <Base/Interpreter.h>


#include "WidgetFactory.h"
Expand Down Expand Up @@ -280,6 +284,64 @@ QWidget* WidgetFactoryInst::createPrefWidget(const char* sName, QWidget* parent,

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

PySideUicModule::PySideUicModule()
: Py::ExtensionModule<PySideUicModule>("PySideUic")
{
add_varargs_method("loadUiType",&PySideUicModule::loadUiType,
"Pyside lacks the \"loadUiType\" command, so we have to convert the ui file to py code in-memory first\n"
"and then execute it in a special frame to retrieve the form_class.");
initialize("PySideUic helper module"); // register with Python
}

Py::Object PySideUicModule::loadUiType(const Py::Tuple& args)
{
Base::PyGILStateLocker lock;
PyObject* main = PyImport_AddModule("__main__");
PyObject* dict = PyModule_GetDict(main);
Py::Dict d(PyDict_Copy(dict), true);
Py::String uiFile(args.getItem(0));

QString cmd;
QTextStream str(&cmd);
// https://github.com/albop/dolo/blob/master/bin/load_ui.py
str << "import pysideuic\n"
<< "from PySide import QtCore, QtGui\n"
<< "import xml.etree.ElementTree as xml\n"
<< "from cStringIO import StringIO\n"
<< "\n"
<< "uiFile = \"" << uiFile.as_string().c_str() << "\"\n"
<< "parsed = xml.parse(uiFile)\n"
<< "widget_class = parsed.find('widget').get('class')\n"
<< "form_class = parsed.find('class').text\n"
<< "with open(uiFile, 'r') as f:\n"
<< " o = StringIO()\n"
<< " frame = {}\n"
<< " pysideuic.compileUi(f, o, indent=0)\n"
<< " pyc = compile(o.getvalue(), '<string>', 'exec')\n"
<< " exec pyc in frame\n"
<< " #Fetch the base_class and form class based on their type in the xml from designer\n"
<< " form_class = frame['Ui_%s'%form_class]\n"
<< " base_class = eval('QtGui.%s'%widget_class)\n";

PyObject* result = PyRun_String((const char*)cmd.toLatin1(), Py_file_input, d.ptr(), d.ptr());
if (result) {
Py_DECREF(result);
if (d.hasKey("form_class") && d.hasKey("base_class")) {
Py::Tuple t(2);
t.setItem(0, d.getItem("form_class"));
t.setItem(1, d.getItem("base_class"));
return t;
}
}
else {
throw Py::Exception();
}

return Py::None();
}

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

UiLoader::UiLoader(QObject* parent)
: QUiLoader(parent)
{
Expand Down
11 changes: 11 additions & 0 deletions src/Gui/WidgetFactory.h
Expand Up @@ -50,6 +50,17 @@ class GuiExport PythonWrapper
Py::Object fromQWidget(QWidget*, const char* className=0);
};

class PySideUicModule : public Py::ExtensionModule<PySideUicModule>
{

public:
PySideUicModule();
virtual ~PySideUicModule() {}

private:
Py::Object loadUiType(const Py::Tuple& args);
};

/**
* The widget factory provides methods for the dynamic creation of widgets.
* To create these widgets once they must be registered to the factory.
Expand Down

0 comments on commit e32b747

Please sign in to comment.