App/Gui: implement a lightweight weak_ptr like class to work with Document, DocumentObject and ViewProvider
This commit is contained in:
@@ -257,6 +257,7 @@ Property *DocumentObjectT::getProperty() const {
|
||||
return obj->getPropertyByName(property.c_str());
|
||||
return 0;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
SubObjectT::SubObjectT()
|
||||
@@ -387,6 +388,138 @@ std::vector<App::DocumentObject*> SubObjectT::getSubObjectList() const {
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
class DocumentWeakPtrT::Private {
|
||||
public:
|
||||
Private(App::Document* doc) : _document(doc) {
|
||||
if (doc) {
|
||||
connectApplicationDeletedDocument = App::GetApplication().signalDeleteDocument.connect(boost::bind
|
||||
(&Private::deletedDocument, this, _1));
|
||||
}
|
||||
}
|
||||
|
||||
void deletedDocument(const App::Document& doc) {
|
||||
if (_document == &doc)
|
||||
reset();
|
||||
}
|
||||
void reset() {
|
||||
connectApplicationDeletedDocument.disconnect();
|
||||
_document = nullptr;
|
||||
}
|
||||
|
||||
App::Document* _document;
|
||||
typedef boost::signals2::scoped_connection Connection;
|
||||
Connection connectApplicationDeletedDocument;
|
||||
};
|
||||
|
||||
DocumentWeakPtrT::DocumentWeakPtrT(App::Document* doc) noexcept
|
||||
: d(new Private(doc))
|
||||
{
|
||||
}
|
||||
|
||||
DocumentWeakPtrT::~DocumentWeakPtrT()
|
||||
{
|
||||
}
|
||||
|
||||
void DocumentWeakPtrT::reset() noexcept
|
||||
{
|
||||
d->reset();
|
||||
}
|
||||
|
||||
bool DocumentWeakPtrT::expired() const noexcept
|
||||
{
|
||||
return (d->_document == nullptr);
|
||||
}
|
||||
|
||||
App::Document* DocumentWeakPtrT::operator->() noexcept
|
||||
{
|
||||
return d->_document;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
class DocumentObjectWeakPtrT::Private {
|
||||
public:
|
||||
Private(App::DocumentObject* obj) : object(obj), indocument(false) {
|
||||
if (obj) {
|
||||
indocument = true;
|
||||
connectApplicationDeletedDocument = App::GetApplication().signalDeleteDocument.connect(boost::bind
|
||||
(&Private::deletedDocument, this, _1));
|
||||
App::Document* doc = obj->getDocument();
|
||||
connectDocumentCreatedObject = doc->signalNewObject.connect(boost::bind
|
||||
(&Private::createdObject, this, _1));
|
||||
connectDocumentDeletedObject = doc->signalDeletedObject.connect(boost::bind
|
||||
(&Private::deletedObject, this, _1));
|
||||
}
|
||||
}
|
||||
void deletedDocument(const App::Document& doc) {
|
||||
// When deleting document then there is no way to undo it
|
||||
if (object && object->getDocument() == &doc) {
|
||||
reset();
|
||||
}
|
||||
}
|
||||
void createdObject(const App::DocumentObject& obj) {
|
||||
// When undoing the removal
|
||||
if (object == &obj) {
|
||||
indocument = true;
|
||||
}
|
||||
}
|
||||
void deletedObject(const App::DocumentObject& obj) {
|
||||
if (object == &obj) {
|
||||
indocument = false;
|
||||
}
|
||||
}
|
||||
void reset() {
|
||||
connectApplicationDeletedDocument.disconnect();
|
||||
connectDocumentCreatedObject.disconnect();
|
||||
connectDocumentDeletedObject.disconnect();
|
||||
object = nullptr;
|
||||
indocument = false;
|
||||
}
|
||||
App::DocumentObject* get() const {
|
||||
return indocument ? object : nullptr;
|
||||
}
|
||||
|
||||
App::DocumentObject* object;
|
||||
bool indocument;
|
||||
typedef boost::signals2::scoped_connection Connection;
|
||||
Connection connectApplicationDeletedDocument;
|
||||
Connection connectDocumentCreatedObject;
|
||||
Connection connectDocumentDeletedObject;
|
||||
};
|
||||
|
||||
DocumentObjectWeakPtrT::DocumentObjectWeakPtrT(App::DocumentObject* obj) noexcept
|
||||
: d(new Private(obj))
|
||||
{
|
||||
}
|
||||
|
||||
DocumentObjectWeakPtrT::~DocumentObjectWeakPtrT()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
App::DocumentObject* DocumentObjectWeakPtrT::_get() const noexcept
|
||||
{
|
||||
return d->get();
|
||||
}
|
||||
|
||||
void DocumentObjectWeakPtrT::reset() noexcept
|
||||
{
|
||||
d->reset();
|
||||
}
|
||||
|
||||
bool DocumentObjectWeakPtrT::expired() const noexcept
|
||||
{
|
||||
return !d->indocument;
|
||||
}
|
||||
|
||||
App::DocumentObject* DocumentObjectWeakPtrT::operator->() noexcept
|
||||
{
|
||||
return d->get();
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
DocumentObserver::DocumentObserver() : _document(0)
|
||||
{
|
||||
this->connectApplicationCreatedDocument = App::GetApplication().signalNewDocument.connect(boost::bind
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#include <Base/BaseClass.h>
|
||||
#include <boost/signals2.hpp>
|
||||
#include <set>
|
||||
#include <memory>
|
||||
|
||||
namespace App
|
||||
{
|
||||
@@ -144,7 +145,7 @@ private:
|
||||
std::string property;
|
||||
};
|
||||
|
||||
class AppExport SubObjectT: public DocumentObjectT
|
||||
class AppExport SubObjectT : public DocumentObjectT
|
||||
{
|
||||
public:
|
||||
/*! Constructor */
|
||||
@@ -205,6 +206,82 @@ private:
|
||||
std::string subname;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief The DocumentWeakPtrT class
|
||||
*/
|
||||
class AppExport DocumentWeakPtrT
|
||||
{
|
||||
public:
|
||||
DocumentWeakPtrT(App::Document*) noexcept;
|
||||
~DocumentWeakPtrT();
|
||||
|
||||
/*!
|
||||
* \brief reset
|
||||
* Releases the reference to the managed object. After the call *this manages no object.
|
||||
*/
|
||||
void reset() noexcept;
|
||||
/*!
|
||||
* \brief expired
|
||||
* \return true if the managed object has already been deleted, false otherwise.
|
||||
*/
|
||||
bool expired() const noexcept;
|
||||
/*!
|
||||
* \brief operator ->
|
||||
* \return pointer to the document
|
||||
*/
|
||||
App::Document* operator->() noexcept;
|
||||
|
||||
private:
|
||||
// disable
|
||||
DocumentWeakPtrT(const DocumentWeakPtrT&);
|
||||
DocumentWeakPtrT& operator=(const DocumentWeakPtrT&);
|
||||
|
||||
class Private;
|
||||
std::unique_ptr<Private> d;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief The DocumentObjectWeakPtrT class
|
||||
*/
|
||||
class AppExport DocumentObjectWeakPtrT
|
||||
{
|
||||
public:
|
||||
DocumentObjectWeakPtrT(App::DocumentObject*) noexcept;
|
||||
~DocumentObjectWeakPtrT();
|
||||
|
||||
/*!
|
||||
* \brief reset
|
||||
* Releases the reference to the managed object. After the call *this manages no object.
|
||||
*/
|
||||
void reset() noexcept;
|
||||
/*!
|
||||
* \brief expired
|
||||
* \return true if the managed object has already been deleted, false otherwise.
|
||||
*/
|
||||
bool expired() const noexcept;
|
||||
/*!
|
||||
* \brief operator ->
|
||||
* \return pointer to the document
|
||||
*/
|
||||
App::DocumentObject* operator->() noexcept;
|
||||
/*! Get a pointer to the object or 0 if it doesn't exist any more or the type doesn't match. */
|
||||
template<typename T>
|
||||
inline T* get() const noexcept
|
||||
{
|
||||
return Base::freecad_dynamic_cast<T>(_get());
|
||||
}
|
||||
|
||||
private:
|
||||
App::DocumentObject* _get() const noexcept;
|
||||
// disable
|
||||
DocumentObjectWeakPtrT(const DocumentObjectWeakPtrT&);
|
||||
DocumentObjectWeakPtrT& operator=(const DocumentObjectWeakPtrT&);
|
||||
|
||||
private:
|
||||
class Private;
|
||||
std::unique_ptr<Private> d;
|
||||
};
|
||||
|
||||
/**
|
||||
* The DocumentObserver class simplfies the step to write classes that listen
|
||||
* to what happens inside a document.
|
||||
|
||||
@@ -199,6 +199,137 @@ std::string ViewProviderT::getObjectPython() const
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
class DocumentWeakPtrT::Private {
|
||||
public:
|
||||
Private(Gui::Document* doc) : _document(doc) {
|
||||
if (doc) {
|
||||
connectApplicationDeletedDocument = doc->signalDeleteDocument.connect(boost::bind
|
||||
(&Private::deletedDocument, this, _1));
|
||||
}
|
||||
}
|
||||
|
||||
void deletedDocument(const Gui::Document& doc) {
|
||||
if (_document == &doc)
|
||||
reset();
|
||||
}
|
||||
void reset() {
|
||||
connectApplicationDeletedDocument.disconnect();
|
||||
_document = nullptr;
|
||||
}
|
||||
|
||||
Gui::Document* _document;
|
||||
typedef boost::signals2::scoped_connection Connection;
|
||||
Connection connectApplicationDeletedDocument;
|
||||
};
|
||||
|
||||
DocumentWeakPtrT::DocumentWeakPtrT(Gui::Document* doc) noexcept
|
||||
: d(new Private(doc))
|
||||
{
|
||||
}
|
||||
|
||||
DocumentWeakPtrT::~DocumentWeakPtrT()
|
||||
{
|
||||
}
|
||||
|
||||
void DocumentWeakPtrT::reset() noexcept
|
||||
{
|
||||
d->reset();
|
||||
}
|
||||
|
||||
bool DocumentWeakPtrT::expired() const noexcept
|
||||
{
|
||||
return (d->_document == nullptr);
|
||||
}
|
||||
|
||||
Gui::Document* DocumentWeakPtrT::operator->() noexcept
|
||||
{
|
||||
return d->_document;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
class ViewProviderWeakPtrT::Private {
|
||||
public:
|
||||
Private(ViewProviderDocumentObject* obj) : object(obj), indocument(false) {
|
||||
if (obj) {
|
||||
indocument = true;
|
||||
Gui::Document* doc = obj->getDocument();
|
||||
connectApplicationDeletedDocument = doc->signalDeleteDocument.connect(boost::bind
|
||||
(&Private::deletedDocument, this, _1));
|
||||
connectDocumentCreatedObject = doc->signalNewObject.connect(boost::bind
|
||||
(&Private::createdObject, this, _1));
|
||||
connectDocumentDeletedObject = doc->signalDeletedObject.connect(boost::bind
|
||||
(&Private::deletedObject, this, _1));
|
||||
}
|
||||
}
|
||||
void deletedDocument(const Gui::Document& doc) {
|
||||
// When deleting document then there is no way to undo it
|
||||
if (object && object->getDocument() == &doc) {
|
||||
reset();
|
||||
}
|
||||
}
|
||||
void createdObject(const Gui::ViewProvider& obj) {
|
||||
// When undoing the removal
|
||||
if (object == &obj) {
|
||||
indocument = true;
|
||||
}
|
||||
}
|
||||
void deletedObject(const Gui::ViewProvider& obj) {
|
||||
if (object == &obj) {
|
||||
indocument = false;
|
||||
}
|
||||
}
|
||||
void reset() {
|
||||
connectApplicationDeletedDocument.disconnect();
|
||||
connectDocumentCreatedObject.disconnect();
|
||||
connectDocumentDeletedObject.disconnect();
|
||||
object = nullptr;
|
||||
indocument = false;
|
||||
}
|
||||
ViewProviderDocumentObject* get() const {
|
||||
return indocument ? object : nullptr;
|
||||
}
|
||||
|
||||
Gui::ViewProviderDocumentObject* object;
|
||||
bool indocument;
|
||||
typedef boost::signals2::scoped_connection Connection;
|
||||
Connection connectApplicationDeletedDocument;
|
||||
Connection connectDocumentCreatedObject;
|
||||
Connection connectDocumentDeletedObject;
|
||||
};
|
||||
|
||||
ViewProviderWeakPtrT::ViewProviderWeakPtrT(ViewProviderDocumentObject* obj) noexcept
|
||||
: d(new Private(obj))
|
||||
{
|
||||
}
|
||||
|
||||
ViewProviderWeakPtrT::~ViewProviderWeakPtrT()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
ViewProviderDocumentObject* ViewProviderWeakPtrT::_get() const noexcept
|
||||
{
|
||||
return d->get();
|
||||
}
|
||||
|
||||
void ViewProviderWeakPtrT::reset() noexcept
|
||||
{
|
||||
d->reset();
|
||||
}
|
||||
|
||||
bool ViewProviderWeakPtrT::expired() const noexcept
|
||||
{
|
||||
return !d->indocument;
|
||||
}
|
||||
|
||||
ViewProviderDocumentObject* ViewProviderWeakPtrT::operator->() noexcept
|
||||
{
|
||||
return d->get();
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
DocumentObserver::DocumentObserver()
|
||||
{
|
||||
}
|
||||
|
||||
@@ -118,6 +118,82 @@ private:
|
||||
std::string object;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief The DocumentWeakPtrT class
|
||||
*/
|
||||
class GuiExport DocumentWeakPtrT
|
||||
{
|
||||
public:
|
||||
DocumentWeakPtrT(Gui::Document*) noexcept;
|
||||
~DocumentWeakPtrT();
|
||||
|
||||
/*!
|
||||
* \brief reset
|
||||
* Releases the reference to the managed object. After the call *this manages no object.
|
||||
*/
|
||||
void reset() noexcept;
|
||||
/*!
|
||||
* \brief expired
|
||||
* \return true if the managed object has already been deleted, false otherwise.
|
||||
*/
|
||||
bool expired() const noexcept;
|
||||
/*!
|
||||
* \brief operator ->
|
||||
* \return pointer to the document
|
||||
*/
|
||||
Gui::Document* operator->() noexcept;
|
||||
|
||||
private:
|
||||
// disable
|
||||
DocumentWeakPtrT(const DocumentWeakPtrT&);
|
||||
DocumentWeakPtrT& operator=(const DocumentWeakPtrT&);
|
||||
|
||||
class Private;
|
||||
std::unique_ptr<Private> d;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief The ViewProviderWeakPtrT class
|
||||
*/
|
||||
class AppExport ViewProviderWeakPtrT
|
||||
{
|
||||
public:
|
||||
ViewProviderWeakPtrT(ViewProviderDocumentObject*) noexcept;
|
||||
~ViewProviderWeakPtrT();
|
||||
|
||||
/*!
|
||||
* \brief reset
|
||||
* Releases the reference to the managed object. After the call *this manages no object.
|
||||
*/
|
||||
void reset() noexcept;
|
||||
/*!
|
||||
* \brief expired
|
||||
* \return true if the managed object has already been deleted, false otherwise.
|
||||
*/
|
||||
bool expired() const noexcept;
|
||||
/*!
|
||||
* \brief operator ->
|
||||
* \return pointer to the document
|
||||
*/
|
||||
ViewProviderDocumentObject* operator->() noexcept;
|
||||
/*! Get a pointer to the object or 0 if it doesn't exist any more or the type doesn't match. */
|
||||
template<typename T>
|
||||
inline T* get() const noexcept
|
||||
{
|
||||
return Base::freecad_dynamic_cast<T>(_get());
|
||||
}
|
||||
|
||||
private:
|
||||
ViewProviderDocumentObject* _get() const noexcept;
|
||||
// disable
|
||||
ViewProviderWeakPtrT(const ViewProviderWeakPtrT&);
|
||||
ViewProviderWeakPtrT& operator=(const ViewProviderWeakPtrT&);
|
||||
|
||||
private:
|
||||
class Private;
|
||||
std::unique_ptr<Private> d;
|
||||
};
|
||||
|
||||
/**
|
||||
* The DocumentObserver class simplifies the step to write classes that listen
|
||||
* to what happens inside a document.
|
||||
|
||||
Reference in New Issue
Block a user