From d038801acab8a8e31fb0eb4482e31150d443704a Mon Sep 17 00:00:00 2001 From: wmayer Date: Tue, 22 Nov 2022 15:44:26 +0100 Subject: [PATCH] Gui: move class SelectionObserverPython to its own source files --- src/Base/ProgressIndicatorPy.cpp | 2 +- src/Gui/CMakeLists.txt | 2 + src/Gui/Selection.cpp | 190 +----------------------- src/Gui/Selection.h | 52 +------ src/Gui/SelectionObserverPython.cpp | 218 ++++++++++++++++++++++++++++ src/Gui/SelectionObserverPython.h | 84 +++++++++++ 6 files changed, 308 insertions(+), 240 deletions(-) create mode 100644 src/Gui/SelectionObserverPython.cpp create mode 100644 src/Gui/SelectionObserverPython.h diff --git a/src/Base/ProgressIndicatorPy.cpp b/src/Base/ProgressIndicatorPy.cpp index fb88d7d709..a3a4a47405 100644 --- a/src/Base/ProgressIndicatorPy.cpp +++ b/src/Base/ProgressIndicatorPy.cpp @@ -1,5 +1,5 @@ /*************************************************************************** - * Copyright (c) 2004 Werner Mayer * + * Copyright (c) 2022 Werner Mayer * * * * This file is part of the FreeCAD CAx development system. * * * diff --git a/src/Gui/CMakeLists.txt b/src/Gui/CMakeLists.txt index ab81adc098..2805462bcc 100644 --- a/src/Gui/CMakeLists.txt +++ b/src/Gui/CMakeLists.txt @@ -1096,6 +1096,8 @@ SET(Selection_SRCS SelectionFilter.cpp SelectionFilter.y SelectionFilter.l + SelectionObserverPython.cpp + SelectionObserverPython.h ) SOURCE_GROUP("Selection" FILES ${Selection_SRCS}) diff --git a/src/Gui/Selection.cpp b/src/Gui/Selection.cpp index f0f96aecef..cd08beb108 100644 --- a/src/Gui/Selection.cpp +++ b/src/Gui/Selection.cpp @@ -47,6 +47,7 @@ #include "MainWindow.h" #include "MDIView.h" #include "SelectionFilter.h" +#include "SelectionObserverPython.h" #include "Tree.h" #include "ViewProviderDocumentObject.h" @@ -166,195 +167,6 @@ void SelectionObserver::detachSelection() // ------------------------------------------- -std::vector SelectionObserverPython::_instances; - -SelectionObserverPython::SelectionObserverPython(const Py::Object& obj, ResolveMode resolve) - : SelectionObserver(true, resolve), inst(obj) -{ -#undef FC_PY_ELEMENT -#define FC_PY_ELEMENT(_name) FC_PY_GetCallable(obj.ptr(),#_name,py_##_name); - FC_PY_SEL_OBSERVER -} - -SelectionObserverPython::~SelectionObserverPython() -{ -} - -void SelectionObserverPython::addObserver(const Py::Object& obj, ResolveMode resolve) -{ - _instances.push_back(new SelectionObserverPython(obj, resolve)); -} - -void SelectionObserverPython::removeObserver(const Py::Object& obj) -{ - SelectionObserverPython* obs=nullptr; - for (std::vector::iterator it = - _instances.begin(); it != _instances.end(); ++it) { - if ((*it)->inst == obj) { - obs = *it; - _instances.erase(it); - break; - } - } - - delete obs; -} - -void SelectionObserverPython::onSelectionChanged(const SelectionChanges& msg) -{ - switch (msg.Type) - { - case SelectionChanges::AddSelection: - addSelection(msg); - break; - case SelectionChanges::RmvSelection: - removeSelection(msg); - break; - case SelectionChanges::SetSelection: - setSelection(msg); - break; - case SelectionChanges::ClrSelection: - clearSelection(msg); - break; - case SelectionChanges::SetPreselect: - setPreselection(msg); - break; - case SelectionChanges::RmvPreselect: - removePreselection(msg); - break; - case SelectionChanges::PickedListChanged: - pickedListChanged(); - break; - default: - break; - } -} - -void SelectionObserverPython::pickedListChanged() -{ - if(py_pickedListChanged.isNone()) - return; - Base::PyGILStateLocker lock; - try { - Py::Callable(py_pickedListChanged).apply(Py::Tuple()); - } - catch (Py::Exception&) { - Base::PyException e; // extract the Python error text - e.ReportException(); - } -} - -void SelectionObserverPython::addSelection(const SelectionChanges& msg) -{ - if(py_addSelection.isNone()) - return; - Base::PyGILStateLocker lock; - try { - Py::Tuple args(4); - args.setItem(0, Py::String(msg.pDocName ? msg.pDocName : "")); - args.setItem(1, Py::String(msg.pObjectName ? msg.pObjectName : "")); - args.setItem(2, Py::String(msg.pSubName ? msg.pSubName : "")); - Py::Tuple tuple(3); - tuple[0] = Py::Float(msg.x); - tuple[1] = Py::Float(msg.y); - tuple[2] = Py::Float(msg.z); - args.setItem(3, tuple); - Base::pyCall(py_addSelection.ptr(),args.ptr()); - } - catch (Py::Exception&) { - Base::PyException e; // extract the Python error text - e.ReportException(); - } -} - -void SelectionObserverPython::removeSelection(const SelectionChanges& msg) -{ - if(py_removeSelection.isNone()) - return; - Base::PyGILStateLocker lock; - try { - Py::Tuple args(3); - args.setItem(0, Py::String(msg.pDocName ? msg.pDocName : "")); - args.setItem(1, Py::String(msg.pObjectName ? msg.pObjectName : "")); - args.setItem(2, Py::String(msg.pSubName ? msg.pSubName : "")); - Base::pyCall(py_removeSelection.ptr(),args.ptr()); - } - catch (Py::Exception&) { - Base::PyException e; // extract the Python error text - e.ReportException(); - } -} - -void SelectionObserverPython::setSelection(const SelectionChanges& msg) -{ - if(py_setSelection.isNone()) - return; - Base::PyGILStateLocker lock; - try { - Py::Tuple args(1); - args.setItem(0, Py::String(msg.pDocName ? msg.pDocName : "")); - Base::pyCall(py_setSelection.ptr(),args.ptr()); - } - catch (Py::Exception&) { - Base::PyException e; // extract the Python error text - e.ReportException(); - } -} - -void SelectionObserverPython::clearSelection(const SelectionChanges& msg) -{ - if(py_clearSelection.isNone()) - return; - Base::PyGILStateLocker lock; - try { - Py::Tuple args(1); - args.setItem(0, Py::String(msg.pDocName ? msg.pDocName : "")); - Base::pyCall(py_clearSelection.ptr(),args.ptr()); - } - catch (Py::Exception&) { - Base::PyException e; // extract the Python error text - e.ReportException(); - } -} - -void SelectionObserverPython::setPreselection(const SelectionChanges& msg) -{ - if(py_setPreselection.isNone()) - return; - Base::PyGILStateLocker lock; - try { - Py::Tuple args(3); - args.setItem(0, Py::String(msg.pDocName ? msg.pDocName : "")); - args.setItem(1, Py::String(msg.pObjectName ? msg.pObjectName : "")); - args.setItem(2, Py::String(msg.pSubName ? msg.pSubName : "")); - Base::pyCall(py_setPreselection.ptr(),args.ptr()); - } - catch (Py::Exception&) { - Base::PyException e; // extract the Python error text - e.ReportException(); - } -} - -void SelectionObserverPython::removePreselection(const SelectionChanges& msg) -{ - if(py_removePreselection.isNone()) - return; - Base::PyGILStateLocker lock; - try { - Py::Tuple args(3); - args.setItem(0, Py::String(msg.pDocName ? msg.pDocName : "")); - args.setItem(1, Py::String(msg.pObjectName ? msg.pObjectName : "")); - args.setItem(2, Py::String(msg.pSubName ? msg.pSubName : "")); - Base::pyCall(py_removePreselection.ptr(),args.ptr()); - } - catch (Py::Exception&) { - Base::PyException e; // extract the Python error text - e.ReportException(); - } -} - -// ------------------------------------------- - bool SelectionSingleton::hasSelection() const { return !_SelList.empty(); diff --git a/src/Gui/Selection.h b/src/Gui/Selection.h index 002b808ed7..1839435e3d 100644 --- a/src/Gui/Selection.h +++ b/src/Gui/Selection.h @@ -28,7 +28,6 @@ #include #include #include -#include #include #include @@ -37,6 +36,8 @@ #include "SelectionObject.h" +using PyObject = struct _object; + namespace App { class DocumentObject; @@ -268,55 +269,6 @@ private: bool blockedSelection; }; -/** - * The SelectionObserverPython class implements a mechanism to register - * a Python class instance implementing the required interface in order - * to be notified on selection changes. - * - * @author Werner Mayer - */ -class GuiExport SelectionObserverPython : public SelectionObserver -{ - -public: - /// Constructor - explicit SelectionObserverPython(const Py::Object& obj, ResolveMode resolve = ResolveMode::OldStyleElement); - ~SelectionObserverPython() override; - - static void addObserver(const Py::Object& obj, ResolveMode resolve = ResolveMode::OldStyleElement); - static void removeObserver(const Py::Object& obj); - -private: - void onSelectionChanged(const SelectionChanges& msg) override; - void addSelection(const SelectionChanges&); - void removeSelection(const SelectionChanges&); - void setSelection(const SelectionChanges&); - void clearSelection(const SelectionChanges&); - void setPreselection(const SelectionChanges&); - void removePreselection(const SelectionChanges&); - void pickedListChanged(); - -private: - Py::Object inst; - -#define FC_PY_SEL_OBSERVER \ - FC_PY_ELEMENT(onSelectionChanged) \ - FC_PY_ELEMENT(addSelection) \ - FC_PY_ELEMENT(removeSelection) \ - FC_PY_ELEMENT(setSelection) \ - FC_PY_ELEMENT(clearSelection) \ - FC_PY_ELEMENT(setPreselection) \ - FC_PY_ELEMENT(removePreselection) \ - FC_PY_ELEMENT(pickedListChanged) - -#undef FC_PY_ELEMENT -#define FC_PY_ELEMENT(_name) Py::Object py_##_name; - - FC_PY_SEL_OBSERVER - - static std::vector _instances; -}; - /** SelectionGate * The selection gate allows or disallows selection of certain types. * It has to be registered to the selection. diff --git a/src/Gui/SelectionObserverPython.cpp b/src/Gui/SelectionObserverPython.cpp new file mode 100644 index 0000000000..d46d36863d --- /dev/null +++ b/src/Gui/SelectionObserverPython.cpp @@ -0,0 +1,218 @@ +/*************************************************************************** + * Copyright (c) 2022 Werner Mayer * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + +#include "PreCompiled.h" + +#include "SelectionObserverPython.h" +#include + + +FC_LOG_LEVEL_INIT("Selection",false,true,true) + +using namespace Gui; + +std::vector SelectionObserverPython::_instances; + +SelectionObserverPython::SelectionObserverPython(const Py::Object& obj, ResolveMode resolve) + : SelectionObserver(true, resolve), inst(obj) +{ +#undef FC_PY_ELEMENT +#define FC_PY_ELEMENT(_name) FC_PY_GetCallable(obj.ptr(),#_name,py_##_name); + FC_PY_SEL_OBSERVER +} + +SelectionObserverPython::~SelectionObserverPython() +{ +} + +void SelectionObserverPython::addObserver(const Py::Object& obj, ResolveMode resolve) +{ + _instances.push_back(new SelectionObserverPython(obj, resolve)); +} + +void SelectionObserverPython::removeObserver(const Py::Object& obj) +{ + SelectionObserverPython* obs=nullptr; + for (std::vector::iterator it = + _instances.begin(); it != _instances.end(); ++it) { + if ((*it)->inst == obj) { + obs = *it; + _instances.erase(it); + break; + } + } + + delete obs; +} + +void SelectionObserverPython::onSelectionChanged(const SelectionChanges& msg) +{ + switch (msg.Type) + { + case SelectionChanges::AddSelection: + addSelection(msg); + break; + case SelectionChanges::RmvSelection: + removeSelection(msg); + break; + case SelectionChanges::SetSelection: + setSelection(msg); + break; + case SelectionChanges::ClrSelection: + clearSelection(msg); + break; + case SelectionChanges::SetPreselect: + setPreselection(msg); + break; + case SelectionChanges::RmvPreselect: + removePreselection(msg); + break; + case SelectionChanges::PickedListChanged: + pickedListChanged(); + break; + default: + break; + } +} + +void SelectionObserverPython::pickedListChanged() +{ + if(py_pickedListChanged.isNone()) + return; + Base::PyGILStateLocker lock; + try { + Py::Callable(py_pickedListChanged).apply(Py::Tuple()); + } + catch (Py::Exception&) { + Base::PyException e; // extract the Python error text + e.ReportException(); + } +} + +void SelectionObserverPython::addSelection(const SelectionChanges& msg) +{ + if(py_addSelection.isNone()) + return; + Base::PyGILStateLocker lock; + try { + Py::Tuple args(4); + args.setItem(0, Py::String(msg.pDocName ? msg.pDocName : "")); + args.setItem(1, Py::String(msg.pObjectName ? msg.pObjectName : "")); + args.setItem(2, Py::String(msg.pSubName ? msg.pSubName : "")); + Py::Tuple tuple(3); + tuple[0] = Py::Float(msg.x); + tuple[1] = Py::Float(msg.y); + tuple[2] = Py::Float(msg.z); + args.setItem(3, tuple); + Base::pyCall(py_addSelection.ptr(),args.ptr()); + } + catch (Py::Exception&) { + Base::PyException e; // extract the Python error text + e.ReportException(); + } +} + +void SelectionObserverPython::removeSelection(const SelectionChanges& msg) +{ + if(py_removeSelection.isNone()) + return; + Base::PyGILStateLocker lock; + try { + Py::Tuple args(3); + args.setItem(0, Py::String(msg.pDocName ? msg.pDocName : "")); + args.setItem(1, Py::String(msg.pObjectName ? msg.pObjectName : "")); + args.setItem(2, Py::String(msg.pSubName ? msg.pSubName : "")); + Base::pyCall(py_removeSelection.ptr(),args.ptr()); + } + catch (Py::Exception&) { + Base::PyException e; // extract the Python error text + e.ReportException(); + } +} + +void SelectionObserverPython::setSelection(const SelectionChanges& msg) +{ + if(py_setSelection.isNone()) + return; + Base::PyGILStateLocker lock; + try { + Py::Tuple args(1); + args.setItem(0, Py::String(msg.pDocName ? msg.pDocName : "")); + Base::pyCall(py_setSelection.ptr(),args.ptr()); + } + catch (Py::Exception&) { + Base::PyException e; // extract the Python error text + e.ReportException(); + } +} + +void SelectionObserverPython::clearSelection(const SelectionChanges& msg) +{ + if(py_clearSelection.isNone()) + return; + Base::PyGILStateLocker lock; + try { + Py::Tuple args(1); + args.setItem(0, Py::String(msg.pDocName ? msg.pDocName : "")); + Base::pyCall(py_clearSelection.ptr(),args.ptr()); + } + catch (Py::Exception&) { + Base::PyException e; // extract the Python error text + e.ReportException(); + } +} + +void SelectionObserverPython::setPreselection(const SelectionChanges& msg) +{ + if(py_setPreselection.isNone()) + return; + Base::PyGILStateLocker lock; + try { + Py::Tuple args(3); + args.setItem(0, Py::String(msg.pDocName ? msg.pDocName : "")); + args.setItem(1, Py::String(msg.pObjectName ? msg.pObjectName : "")); + args.setItem(2, Py::String(msg.pSubName ? msg.pSubName : "")); + Base::pyCall(py_setPreselection.ptr(),args.ptr()); + } + catch (Py::Exception&) { + Base::PyException e; // extract the Python error text + e.ReportException(); + } +} + +void SelectionObserverPython::removePreselection(const SelectionChanges& msg) +{ + if(py_removePreselection.isNone()) + return; + Base::PyGILStateLocker lock; + try { + Py::Tuple args(3); + args.setItem(0, Py::String(msg.pDocName ? msg.pDocName : "")); + args.setItem(1, Py::String(msg.pObjectName ? msg.pObjectName : "")); + args.setItem(2, Py::String(msg.pSubName ? msg.pSubName : "")); + Base::pyCall(py_removePreselection.ptr(),args.ptr()); + } + catch (Py::Exception&) { + Base::PyException e; // extract the Python error text + e.ReportException(); + } +} diff --git a/src/Gui/SelectionObserverPython.h b/src/Gui/SelectionObserverPython.h new file mode 100644 index 0000000000..3f5643487e --- /dev/null +++ b/src/Gui/SelectionObserverPython.h @@ -0,0 +1,84 @@ +/*************************************************************************** + * Copyright (c) 2022 Werner Mayer * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + +#ifndef GUI_SELECTIONOBSERVERPYTHON_H +#define GUI_SELECTIONOBSERVERPYTHON_H + +#include +#include "Selection.h" + + +namespace Gui +{ + +/** + * The SelectionObserverPython class implements a mechanism to register + * a Python class instance implementing the required interface in order + * to be notified on selection changes. + * + * @author Werner Mayer + */ +class GuiExport SelectionObserverPython : public SelectionObserver +{ + +public: + /// Constructor + explicit SelectionObserverPython(const Py::Object& obj, ResolveMode resolve = ResolveMode::OldStyleElement); + ~SelectionObserverPython() override; + + static void addObserver(const Py::Object& obj, ResolveMode resolve = ResolveMode::OldStyleElement); + static void removeObserver(const Py::Object& obj); + +private: + void onSelectionChanged(const SelectionChanges& msg) override; + void addSelection(const SelectionChanges&); + void removeSelection(const SelectionChanges&); + void setSelection(const SelectionChanges&); + void clearSelection(const SelectionChanges&); + void setPreselection(const SelectionChanges&); + void removePreselection(const SelectionChanges&); + void pickedListChanged(); + +private: + Py::Object inst; + +#define FC_PY_SEL_OBSERVER \ + FC_PY_ELEMENT(onSelectionChanged) \ + FC_PY_ELEMENT(addSelection) \ + FC_PY_ELEMENT(removeSelection) \ + FC_PY_ELEMENT(setSelection) \ + FC_PY_ELEMENT(clearSelection) \ + FC_PY_ELEMENT(setPreselection) \ + FC_PY_ELEMENT(removePreselection) \ + FC_PY_ELEMENT(pickedListChanged) + +#undef FC_PY_ELEMENT +#define FC_PY_ELEMENT(_name) Py::Object py_##_name; + + FC_PY_SEL_OBSERVER + + static std::vector _instances; +}; + +} //namespace Gui + +#endif // GUI_SELECTIONOBSERVERPYTHON_H