Skip to content

Commit

Permalink
Gui: add new API ViewProviderDocumentObject::allowOverride()
Browse files Browse the repository at this point in the history
This API is used to delcare if a view provider can be used as an
override for a give object.

Conflicts:
	src/App/DocumentObject.h
  • Loading branch information
realthunder authored and wwmayer committed Oct 6, 2019
1 parent 4775def commit 6663d62
Show file tree
Hide file tree
Showing 10 changed files with 89 additions and 103 deletions.
49 changes: 8 additions & 41 deletions src/App/Document.cpp
Expand Up @@ -3540,17 +3540,8 @@ DocumentObject * Document::addObject(const char* sType, const char* pObjectName,

pcObject->setStatus(ObjectStatus::PartialObject, isPartial);

// If an object does not allow to override its view provider then ignore any
// input of the Document.xml or from Python as this information could be wrong.
// In this case the default type from getViewProviderName() is used.
if (pcObject->allowOverrideViewProviderName()) {
if (!viewType || viewType[0] == '\0') {
viewType = pcObject->getViewProviderNameOverride();
}
}
else {
viewType = pcObject->getViewProviderName();
}
if (!viewType || viewType[0] == '\0')
viewType = pcObject->getViewProviderNameOverride();

if (viewType && viewType[0] != '\0')
pcObject->_pcViewProviderName = viewType;
Expand Down Expand Up @@ -3644,16 +3635,8 @@ std::vector<DocumentObject *> Document::addObjects(const char* sType, const std:
// mark the object as new (i.e. set status bit 2) and send the signal
pcObject->setStatus(ObjectStatus::New, true);

// If an object does not allow to override its view provider then use
// getViewProviderName() instead.
if (pcObject->allowOverrideViewProviderName()) {
const char *viewType = pcObject->getViewProviderNameOverride();
pcObject->_pcViewProviderName = viewType ? viewType : "";
}
else {
const char *viewType = pcObject->getViewProviderName();
pcObject->_pcViewProviderName = viewType ? viewType : "";
}
const char *viewType = pcObject->getViewProviderNameOverride();
pcObject->_pcViewProviderName = viewType ? viewType : "";

signalNewObject(*pcObject);

Expand Down Expand Up @@ -3711,16 +3694,8 @@ void Document::addObject(DocumentObject* pcObject, const char* pObjectName)
// mark the object as new (i.e. set status bit 2) and send the signal
pcObject->setStatus(ObjectStatus::New, true);

// If an object does not allow to override its view provider then use
// getViewProviderName() instead.
if (pcObject->allowOverrideViewProviderName()) {
const char *viewType = pcObject->getViewProviderNameOverride();
pcObject->_pcViewProviderName = viewType ? viewType : "";
}
else {
const char *viewType = pcObject->getViewProviderName();
pcObject->_pcViewProviderName = viewType ? viewType : "";
}
const char *viewType = pcObject->getViewProviderNameOverride();
pcObject->_pcViewProviderName = viewType ? viewType : "";

signalNewObject(*pcObject);

Expand Down Expand Up @@ -3751,16 +3726,8 @@ void Document::_addObject(DocumentObject* pcObject, const char* pObjectName)
d->activeUndoTransaction->addObjectDel(pcObject);
}

// If an object does not allow to override its view provider then use
// getViewProviderName() instead.
if (pcObject->allowOverrideViewProviderName()) {
const char *viewType = pcObject->getViewProviderNameOverride();
pcObject->_pcViewProviderName = viewType ? viewType : "";
}
else {
const char *viewType = pcObject->getViewProviderName();
pcObject->_pcViewProviderName = viewType ? viewType : "";
}
const char *viewType = pcObject->getViewProviderNameOverride();
pcObject->_pcViewProviderName = viewType ? viewType : "";

// send the signal
signalNewObject(*pcObject);
Expand Down
17 changes: 5 additions & 12 deletions src/App/DocumentObject.h
Expand Up @@ -114,22 +114,15 @@ class AppExport DocumentObject: public App::TransactionalObject
* This function is introduced to allow Python feature override its view provider.
* The default implementation just returns \ref getViewProviderName().
*
* If this method is reimplemented in sub-classes then also reimplement \ref
* allowOverrideViewProviderName() accordingly.
* The core will only accept the overridden view provider if it returns
* true when calling Gui::ViewProviderDocumentObject::allowOverride(obj).
* If not, the view provider will be reverted to the one returned from \ref
* getViewProviderName().
*/
virtual const char *getViewProviderNameOverride() const {
return getViewProviderName();
}
/**
* The function indicates whether the object type allows to define a view provider type
* different than the standard type. The default implementation returns false.
* The function can be overridden by Python feature to return true where the type can be
* retrieved from its proxy object.
* \sa getViewProviderNameOverride()
*/
virtual bool allowOverrideViewProviderName() const {
return false;
}

/// Constructor
DocumentObject(void);
virtual ~DocumentObject();
Expand Down
5 changes: 0 additions & 5 deletions src/App/FeaturePython.cpp
Expand Up @@ -435,11 +435,6 @@ int FeaturePythonImp::setElementVisible(const char *element, bool visible) {
}
}

bool FeaturePythonImp::allowOverrideViewProviderName() const
{
return true;
}

std::string FeaturePythonImp::getViewProviderName()
{
_FC_PY_CALL_CHECK(getViewProviderName,return(std::string()));
Expand Down
4 changes: 0 additions & 4 deletions src/App/FeaturePython.h
Expand Up @@ -57,7 +57,6 @@ class AppExport FeaturePythonImp
bool onBeforeChangeLabel(std::string &newLabel);
void onChanged(const Property* prop);
void onDocumentRestored();
bool allowOverrideViewProviderName() const;
std::string getViewProviderName();
PyObject *getPyObject(void);

Expand Down Expand Up @@ -200,9 +199,6 @@ class FeaturePythonT : public FeatureT
}
return DocumentObject::StdReturn;
}
virtual bool allowOverrideViewProviderName() const {
return imp->allowOverrideViewProviderName();
}
virtual const char* getViewProviderNameOverride(void) const override {
viewProviderName = imp->getViewProviderName();
if(viewProviderName.size())
Expand Down
72 changes: 40 additions & 32 deletions src/Gui/Document.cpp
Expand Up @@ -621,44 +621,52 @@ void Document::slotNewObject(const App::DocumentObject& Obj)
if (!pcProvider) {
//Base::Console().Log("Document::slotNewObject() called\n");
std::string cName = Obj.getViewProviderNameStored();
if (cName.empty()) {
// handle document object with no view provider specified
Base::Console().Log("%s has no view provider specified\n", Obj.getTypeId().getName());
return;
for(;;) {
if (cName.empty()) {
// handle document object with no view provider specified
FC_LOG(Obj.getFullName() << " has no view provider specified");
return;
}
Base::BaseClass* base = static_cast<Base::BaseClass*>(
Base::Type::createInstanceByName(cName.c_str(),true));
pcProvider = Base::freecad_dynamic_cast<ViewProviderDocumentObject>(base);
if (!pcProvider) {
// type not derived from ViewProviderDocumentObject!!!
FC_ERR("Invalid view provider type '" << cName << "' for " << Obj.getFullName());
delete base;
return;
} else if (cName!=Obj.getViewProviderName() && !pcProvider->allowOverride(Obj)) {
FC_WARN("View provider type '" << cName << "' does not support " << Obj.getFullName());
delete base;
pcProvider = 0;
cName = Obj.getViewProviderName();
} else
break;
}

setModified(true);
Base::BaseClass* base = static_cast<Base::BaseClass*>(Base::Type::createInstanceByName(cName.c_str(),true));
if (base) {
// type not derived from ViewProviderDocumentObject!!!
assert(base->getTypeId().isDerivedFrom(Gui::ViewProviderDocumentObject::getClassTypeId()));
pcProvider = static_cast<ViewProviderDocumentObject*>(base);
d->_ViewProviderMap[&Obj] = pcProvider;
d->_CoinMap[pcProvider->getRoot()] = pcProvider;
pcProvider->setStatus(Gui::ViewStatus::TouchDocument, d->_changeViewTouchDocument);
d->_ViewProviderMap[&Obj] = pcProvider;
d->_CoinMap[pcProvider->getRoot()] = pcProvider;
pcProvider->setStatus(Gui::ViewStatus::TouchDocument, d->_changeViewTouchDocument);

try {
// if successfully created set the right name and calculate the view
//FIXME: Consider to change argument of attach() to const pointer
pcProvider->attach(const_cast<App::DocumentObject*>(&Obj));
pcProvider->updateView();
pcProvider->setActiveMode();
}
catch(const Base::MemoryException& e){
FC_ERR("Memory exception in " << Obj.getFullName() << " thrown: " << e.what());
}
catch(Base::Exception &e){
e.ReportException();
}
#ifndef FC_DEBUG
catch(...){
FC_ERR("Unknown exception in Feature " << Obj.getFullName() << " thrown");
}
#endif
try {
// if successfully created set the right name and calculate the view
//FIXME: Consider to change argument of attach() to const pointer
pcProvider->attach(const_cast<App::DocumentObject*>(&Obj));
pcProvider->updateView();
pcProvider->setActiveMode();
}
catch(const Base::MemoryException& e){
FC_ERR("Memory exception in " << Obj.getFullName() << " thrown: " << e.what());
}
else {
FC_WARN("no view provider for the object " << cName << " found");
catch(Base::Exception &e){
e.ReportException();
}
#ifndef FC_DEBUG
catch(...){
FC_ERR("Unknown exception in Feature " << Obj.getFullName() << " thrown");
}
#endif
}else{
try {
pcProvider->reattach(const_cast<App::DocumentObject*>(&Obj));
Expand Down
8 changes: 8 additions & 0 deletions src/Gui/ViewProviderDocumentObject.h
Expand Up @@ -139,6 +139,14 @@ class GuiExport ViewProviderDocumentObject : public ViewProvider

virtual std::string getFullName() const override;

/** Allow this class to be used as an override for the original view provider of the given object
*
* @sa App::DocumentObject::getViewProviderNameOverride()
*/
virtual bool allowOverride(const App::DocumentObject &) const {
return false;
}

protected:
/*! Get the active mdi view of the document this view provider is part of.
@note The returned mdi view doesn't need to be a 3d view but can be e.g.
Expand Down
25 changes: 16 additions & 9 deletions src/Gui/ViewProviderLink.cpp
Expand Up @@ -1711,15 +1711,22 @@ QPixmap ViewProviderLink::getOverlayPixmap() const {
void ViewProviderLink::onChanged(const App::Property* prop) {
if(prop==&ChildViewProvider) {
childVp = freecad_dynamic_cast<ViewProviderDocumentObject>(ChildViewProvider.getObject().get());
if(childVp) {
childVp->setPropertyPrefix("ChildViewProvider.");
childVp->Visibility.setValue(getObject()->Visibility.getValue());
childVp->attach(getObject());
childVp->updateView();
childVp->setActiveMode();
if(pcModeSwitch->getNumChildren()>1){
childVpLink = LinkInfo::get(childVp,0);
pcModeSwitch->replaceChild(1,childVpLink->getSnapshot(LinkView::SnapshotTransform));
if(childVp && getObject()) {
if(strcmp(childVp->getTypeId().getName(),getObject()->getViewProviderName())!=0
&& !childVp->allowOverride(*getObject()))
{
FC_ERR("Child view provider type '" << childVp->getTypeId().getName()
<< "' does not support " << getObject()->getFullName());
} else {
childVp->setPropertyPrefix("ChildViewProvider.");
childVp->Visibility.setValue(getObject()->Visibility.getValue());
childVp->attach(getObject());
childVp->updateView();
childVp->setActiveMode();
if(pcModeSwitch->getNumChildren()>1){
childVpLink = LinkInfo::get(childVp,0);
pcModeSwitch->replaceChild(1,childVpLink->getSnapshot(LinkView::SnapshotTransform));
}
}
}
}else if(!isRestoring()) {
Expand Down
4 changes: 4 additions & 0 deletions src/Gui/ViewProviderLink.h
Expand Up @@ -265,6 +265,10 @@ class GuiExport ViewProviderLink : public ViewProviderDocumentObject
virtual ViewProviderDocumentObject *getLinkedViewProvider(
std::string *subname=0, bool recursive=false) const override;

virtual bool allowOverride(const App::DocumentObject &) const override {
return true;
}

protected:
bool setEdit(int ModNum) override;
void setEditViewer(View3DInventorViewer*, int ModNum) override;
Expand Down
6 changes: 6 additions & 0 deletions src/Mod/Part/Gui/ViewProviderExt.cpp
Expand Up @@ -467,6 +467,12 @@ void ViewProviderPartExt::onChanged(const App::Property* prop)
ViewProviderGeometryObject::onChanged(prop);
}

bool ViewProviderPartExt::allowOverride(const App::DocumentObject &) const {
// Many derived view providers still uses static_cast to get object
// pointer, so check for exact type here.
return getTypeId() == ViewProviderPartExt::getClassTypeId();
}

void ViewProviderPartExt::attach(App::DocumentObject *pcFeat)
{
// call parent attach method
Expand Down
2 changes: 2 additions & 0 deletions src/Mod/Part/Gui/ViewProviderExt.h
Expand Up @@ -134,6 +134,8 @@ class PartGuiExport ViewProviderPartExt : public Gui::ViewProviderGeometryObject
}
virtual void forceUpdate(bool enable = true) override;

virtual bool allowOverride(const App::DocumentObject &) const override;

/** @name Edit methods */
//@{
void setupContextMenu(QMenu*, QObject*, const char*) override;
Expand Down

0 comments on commit 6663d62

Please sign in to comment.