Gui: Provide ViewProviderFeaturePython selection callbacks

Adds support for Python-based selection callbacks to
`ViewProviderFeaturePython` objects.

It follows the same conventions as `SelectionObserverPython`, follows an
example:

```python
    def setPreselection(self, document, object, element):
        print("setPreselection: %s.%s.%s"%(document, object, element))

    def removePreselection(self, document, object, element):
print("removePreselection: %s.%s.%s"%(document, object,
element))

    def addSelection(self, document, object, element, position):
print("addSelection: %s.%s.%s at %s"%(document, object, element,
str(position)))

    def removeSelection(self,document, object, element):
        print("removeSelection: %s.%s.%s"%(document, object, element))

    def setSelection(self,doc):
        sel = FreeCADGui.Selection.getSelection(doc)
        print("setSelection: %s"%sel)

    def clearSelection(self,doc):
        print("clearSelection\n")
```
This commit is contained in:
tritao
2025-01-15 21:05:07 +00:00
parent 9c0b95b569
commit b1a24deac6
6 changed files with 84 additions and 8 deletions

View File

@@ -25,6 +25,7 @@
#ifndef _PreComp_
# include <array>
# include <set>
# include <boost/algorithm/string/predicate.hpp>
# include <QApplication>
#endif
@@ -52,6 +53,7 @@
#include "SelectionFilterPy.h"
#include "SelectionObserverPython.h"
#include "Tree.h"
#include "ViewProvider.h"
#include "ViewProviderDocumentObject.h"
@@ -391,6 +393,25 @@ void SelectionSingleton::enablePickedList(bool enable)
}
}
static void notifyDocumentObjectViewProvider(const SelectionChanges& changes) {
const auto* doc = App::GetApplication().getDocument(changes.pDocName);
if (!doc) {
return;
}
const auto* obj = doc->getObject(changes.pObjectName);
if (!obj) {
return;
}
auto* vp = Application::Instance->getViewProvider(obj);
if (!vp) {
return;
}
vp->onSelectionChanged(changes);
}
void SelectionSingleton::notify(SelectionChanges &&Chng)
{
if(Notifying) {
@@ -401,7 +422,7 @@ void SelectionSingleton::notify(SelectionChanges &&Chng)
NotificationQueue.push_back(std::move(Chng));
while(!NotificationQueue.empty()) {
const auto &msg = NotificationQueue.front();
bool notify;
bool notify = false;
switch(msg.Type) {
case SelectionChanges::AddSelection:
notify = isSelected(msg.pDocName, msg.pObjectName, msg.pSubName, ResolveMode::NoResolve);
@@ -420,6 +441,9 @@ void SelectionSingleton::notify(SelectionChanges &&Chng)
notify = true;
}
if(notify) {
// Notify the view provider of the object.
notifyDocumentObjectViewProvider(msg);
Notify(msg);
try {
signalSelectionChanged(msg);
@@ -1454,6 +1478,21 @@ void SelectionSingleton::clearCompleteSelection(bool clearPreSelect)
clearPreSelect?"Gui.Selection.clearSelection()"
:"Gui.Selection.clearSelection(False)");
// Send the clear selection notification to all view providers associated with the
// objects being deselected.
std::set<ViewProvider*> viewProviders;
for (_SelObj& sel : _SelList) {
if (auto vp = Application::Instance->getViewProvider(sel.pObject)) {
viewProviders.insert(vp);
}
}
for (auto& vp : viewProviders) {
SelectionChanges Chng(SelectionChanges::ClrSelection);
vp->onSelectionChanged(Chng);
}
_SelList.clear();
SelectionChanges Chng(SelectionChanges::ClrSelection);