From 985919c7b45fd1c221b4b0e68406019da19185d5 Mon Sep 17 00:00:00 2001 From: wmayer Date: Thu, 23 Feb 2023 08:16:34 +0100 Subject: [PATCH 1/3] Gui: expose more methods of UiLoader to Python --- src/Gui/UiLoader.cpp | 92 ++++++++++++++++++++++++++++++++++++++++++++ src/Gui/UiLoader.h | 10 +++++ 2 files changed, 102 insertions(+) diff --git a/src/Gui/UiLoader.cpp b/src/Gui/UiLoader.cpp index cb5cac8c0e..f4d257ca4a 100644 --- a/src/Gui/UiLoader.cpp +++ b/src/Gui/UiLoader.cpp @@ -528,6 +528,19 @@ void UiLoaderPy::init_type() add_varargs_method("load",&UiLoaderPy::load,"load(string, QWidget parent=None) -> QWidget\n" "load(QIODevice, QWidget parent=None) -> QWidget"); add_varargs_method("createWidget",&UiLoaderPy::createWidget,"createWidget()"); + + add_varargs_method("availableWidgets",&UiLoaderPy::availableWidgets,"availableWidgets()"); + add_varargs_method("clearPluginPaths",&UiLoaderPy::clearPluginPaths,"clearPluginPaths()"); + add_varargs_method("pluginPaths",&UiLoaderPy::pluginPaths,"pluginPaths()"); + add_varargs_method("addPluginPath",&UiLoaderPy::addPluginPath,"addPluginPath()"); + add_varargs_method("errorString",&UiLoaderPy::errorString,"errorString()"); + add_varargs_method("isLanguageChangeEnabled",&UiLoaderPy::isLanguageChangeEnabled, + "isLanguageChangeEnabled()"); + add_varargs_method("setLanguageChangeEnabled",&UiLoaderPy::setLanguageChangeEnabled, + "setLanguageChangeEnabled()"); + add_varargs_method("setWorkingDirectory",&UiLoaderPy::setWorkingDirectory, + "setWorkingDirectory()"); + add_varargs_method("workingDirectory",&UiLoaderPy::workingDirectory,"workingDirectory()"); } UiLoaderPy::UiLoaderPy() @@ -605,6 +618,85 @@ Py::Object UiLoaderPy::createWidget(const Py::Tuple& args) std::placeholders::_3)); } +Py::Object UiLoaderPy::addPluginPath(const Py::Tuple& args) +{ + Gui::PythonWrapper wrap; + if (wrap.loadCoreModule()) { + std::string fn; + if (wrap.toCString(args[0], fn)) { + loader.addPluginPath(QString::fromStdString(fn)); + } + } + return Py::None(); +} + +Py::Object UiLoaderPy::clearPluginPaths(const Py::Tuple& /*args*/) +{ + loader.clearPluginPaths(); + return Py::None(); +} + +Py::Object UiLoaderPy::pluginPaths(const Py::Tuple& /*args*/) +{ + auto list = loader.pluginPaths(); + Py::List py; + for (const auto& it : list) { + py.append(Py::String(it.toStdString())); + } + return py; +} + +Py::Object UiLoaderPy::availableWidgets(const Py::Tuple& /*args*/) +{ + auto list = loader.availableWidgets(); + Py::List py; + for (const auto& it : list) { + py.append(Py::String(it.toStdString())); + } + + auto producer = WidgetFactory().CanProduce(); + for (const auto& it : producer) { + py.append(Py::String(it)); + } + + return py; +} + +Py::Object UiLoaderPy::errorString(const Py::Tuple& /*args*/) +{ + return Py::String(loader.errorString().toStdString()); +} + +Py::Object UiLoaderPy::isLanguageChangeEnabled(const Py::Tuple& /*args*/) +{ + return Py::Boolean(loader.isLanguageChangeEnabled()); +} + +Py::Object UiLoaderPy::setLanguageChangeEnabled(const Py::Tuple& args) +{ + loader.setLanguageChangeEnabled(Py::Boolean(args[0])); + return Py::None(); +} + +Py::Object UiLoaderPy::setWorkingDirectory(const Py::Tuple& args) +{ + Gui::PythonWrapper wrap; + if (wrap.loadCoreModule()) { + std::string fn; + if (wrap.toCString(args[0], fn)) { + loader.setWorkingDirectory(QString::fromStdString(fn)); + } + } + return Py::None(); +} + +Py::Object UiLoaderPy::workingDirectory(const Py::Tuple& /*args*/) +{ + QDir dir = loader.workingDirectory(); + QString path = dir.absolutePath(); + return Py::String(path.toStdString()); +} + #if !defined (HAVE_QT_UI_TOOLS) # include "moc_UiLoader.cpp" #endif diff --git a/src/Gui/UiLoader.h b/src/Gui/UiLoader.h index 5f8ae0e6cc..112138bd57 100644 --- a/src/Gui/UiLoader.h +++ b/src/Gui/UiLoader.h @@ -135,6 +135,16 @@ public: Py::Object createWidget(const Py::Tuple&); Py::Object load(const Py::Tuple&); + Py::Object addPluginPath(const Py::Tuple&); + Py::Object clearPluginPaths(const Py::Tuple&); + Py::Object pluginPaths(const Py::Tuple&); + Py::Object availableWidgets(const Py::Tuple&); + Py::Object errorString(const Py::Tuple&); + Py::Object isLanguageChangeEnabled(const Py::Tuple&); + Py::Object setLanguageChangeEnabled(const Py::Tuple&); + Py::Object setWorkingDirectory(const Py::Tuple&); + Py::Object workingDirectory(const Py::Tuple&); + private: static PyObject *PyMake(struct _typeobject *, PyObject *, PyObject *); From d2741d298c7be6783835420476228c04ee617c81 Mon Sep 17 00:00:00 2001 From: wmayer Date: Thu, 23 Feb 2023 08:17:21 +0100 Subject: [PATCH 2/3] Gui: enable language change by default --- src/Gui/UiLoader.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Gui/UiLoader.cpp b/src/Gui/UiLoader.cpp index f4d257ca4a..002f9affbe 100644 --- a/src/Gui/UiLoader.cpp +++ b/src/Gui/UiLoader.cpp @@ -545,6 +545,7 @@ void UiLoaderPy::init_type() UiLoaderPy::UiLoaderPy() { + loader.setLanguageChangeEnabled(true); } UiLoaderPy::~UiLoaderPy() From dd23698cf2053cd9d5809b39b4efb7025394b0fc Mon Sep 17 00:00:00 2001 From: wmayer Date: Thu, 23 Feb 2023 10:40:22 +0100 Subject: [PATCH 3/3] Gui: handle language change events in task dialogs --- src/Gui/TaskView/TaskDialogPython.cpp | 24 ++++++++++++++++++++++++ src/Gui/TaskView/TaskDialogPython.h | 3 +++ 2 files changed, 27 insertions(+) diff --git a/src/Gui/TaskView/TaskDialogPython.cpp b/src/Gui/TaskView/TaskDialogPython.cpp index e79240f008..d0f15658f3 100644 --- a/src/Gui/TaskView/TaskDialogPython.cpp +++ b/src/Gui/TaskView/TaskDialogPython.cpp @@ -24,6 +24,7 @@ #ifndef _PreComp_ # include +# include # include # include #endif @@ -534,6 +535,7 @@ TaskDialogPython::TaskDialogPython(const Py::Object& o) : dlg(o) form = loader.load(&file, nullptr); file.close(); if (form) { + form->installEventFilter(this); auto taskbox = new Gui::TaskView::TaskBox( QPixmap(icon), form->windowTitle(), true, nullptr); taskbox->groupLayout()->addWidget(form); @@ -561,6 +563,7 @@ TaskDialogPython::TaskDialogPython(const Py::Object& o) : dlg(o) if (object) { QWidget* form = qobject_cast(object); if (form) { + form->installEventFilter(this); auto taskbox = new Gui::TaskView::TaskBox( form->windowIcon().pixmap(32), form->windowTitle(), true, nullptr); taskbox->groupLayout()->addWidget(form); @@ -690,6 +693,27 @@ void TaskDialogPython::helpRequested() } } +bool TaskDialogPython::eventFilter(QObject *watched, QEvent *event) +{ + if (event->type() == QEvent::LanguageChange) { + Base::PyGILStateLocker lock; + try { + if (dlg.hasAttr(std::string("changeEvent"))) { + Py::Callable method(dlg.getAttr(std::string("changeEvent"))); + Py::Tuple args{1}; + args.setItem(0, Py::Long(static_cast(event->type()))); + method.apply(args); + } + } + catch (Py::Exception&) { + Base::PyException e; // extract the Python error text + e.ReportException(); + } + } + + return TaskDialog::eventFilter(watched, event); +} + QDialogButtonBox::StandardButtons TaskDialogPython::getStandardButtons() const { Base::PyGILStateLocker lock; diff --git a/src/Gui/TaskView/TaskDialogPython.h b/src/Gui/TaskView/TaskDialogPython.h index 838a2d1e36..4d19284ac3 100644 --- a/src/Gui/TaskView/TaskDialogPython.h +++ b/src/Gui/TaskView/TaskDialogPython.h @@ -172,6 +172,9 @@ public: /// is called by the framework if the user press the help button void helpRequested() override; + /// event handling + bool eventFilter(QObject *watched, QEvent *event) override; + private: void clearForm();