Gui: move class SelectionObserverPython to its own source files

This commit is contained in:
wmayer
2022-11-22 15:44:26 +01:00
parent 6770b0ba7d
commit d038801aca
6 changed files with 308 additions and 240 deletions

View File

@@ -1,5 +1,5 @@
/***************************************************************************
* Copyright (c) 2004 Werner Mayer <wmayer[at]users.sourceforge.net> *
* Copyright (c) 2022 Werner Mayer <wmayer[at]users.sourceforge.net> *
* *
* This file is part of the FreeCAD CAx development system. *
* *

View File

@@ -1096,6 +1096,8 @@ SET(Selection_SRCS
SelectionFilter.cpp
SelectionFilter.y
SelectionFilter.l
SelectionObserverPython.cpp
SelectionObserverPython.h
)
SOURCE_GROUP("Selection" FILES ${Selection_SRCS})

View File

@@ -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*> 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<SelectionObserverPython*>::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();

View File

@@ -28,7 +28,6 @@
#include <list>
#include <string>
#include <vector>
#include <CXX/Objects.hxx>
#include <App/DocumentObject.h>
#include <App/DocumentObserver.h>
@@ -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<SelectionObserverPython*> _instances;
};
/** SelectionGate
* The selection gate allows or disallows selection of certain types.
* It has to be registered to the selection.

View File

@@ -0,0 +1,218 @@
/***************************************************************************
* Copyright (c) 2022 Werner Mayer <wmayer[at]users.sourceforge.net> *
* *
* 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 <Base/Interpreter.h>
FC_LOG_LEVEL_INIT("Selection",false,true,true)
using namespace Gui;
std::vector<SelectionObserverPython*> 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<SelectionObserverPython*>::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();
}
}

View File

@@ -0,0 +1,84 @@
/***************************************************************************
* Copyright (c) 2022 Werner Mayer <wmayer[at]users.sourceforge.net> *
* *
* 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 <CXX/Objects.hxx>
#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<SelectionObserverPython*> _instances;
};
} //namespace Gui
#endif // GUI_SELECTIONOBSERVERPYTHON_H