Skip to content
Permalink
Browse files

prepare view provider for undo/redo

  • Loading branch information...
wwmayer committed Jun 20, 2016
1 parent f0e0031 commit 9ec06b47c61896e3305cfbc9b716893c39c7bc3d
@@ -1937,6 +1937,12 @@ DocumentObject * Document::addObject(const char* sType, const char* pObjectName,
// mark the object as new (i.e. set status bit 2) and send the signal
pcObject->StatusBits.set(2);
signalNewObject(*pcObject);

// do no transactions if we do a rollback!
if (!d->rollback && d->activeUndoTransaction) {
signalTransactionAppend(*pcObject, d->activeUndoTransaction);
}

signalActivatedObject(*pcObject);

// return the Object
@@ -1979,6 +1985,12 @@ void Document::addObject(DocumentObject* pcObject, const char* pObjectName)
// mark the object as new (i.e. set status bit 2) and send the signal
pcObject->StatusBits.set(2);
signalNewObject(*pcObject);

// do no transactions if we do a rollback!
if (!d->rollback && d->activeUndoTransaction) {
signalTransactionAppend(*pcObject, d->activeUndoTransaction);
}

signalActivatedObject(*pcObject);
}

@@ -1991,14 +2003,20 @@ void Document::_addObject(DocumentObject* pcObject, const char* pObjectName)
pcObject->pcNameInDocument = &(d->objectMap.find(ObjectName)->first);

// do no transactions if we do a rollback!
if(!d->rollback){
if (!d->rollback) {
// Undo stuff
if (d->activeUndoTransaction)
d->activeUndoTransaction->addObjectDel(pcObject);
}

// send the signal
signalNewObject(*pcObject);

// do no transactions if we do a rollback!
if (!d->rollback && d->activeUndoTransaction) {
signalTransactionAppend(*pcObject, d->activeUndoTransaction);
}

d->activeObject = pcObject;
signalActivatedObject(*pcObject);
}
@@ -2022,9 +2040,20 @@ void Document::remObject(const char* sName)
if (!d->undoing && !d->rollback) {
pos->second->unsetupObject();
}

signalDeletedObject(*(pos->second));
pos->second->StatusBits.reset (ObjectStatus::Delete); // Unset the bit to be on the safe side

// do no transactions if we do a rollback!
if (!d->rollback && d->activeUndoTransaction) {
// in this case transaction delete or save the object
signalTransactionRemove(*pos->second, d->activeUndoTransaction);
}
else {
// if not saved in undo -> delete object
signalTransactionRemove(*pos->second, 0);
}

if (!d->vertexMap.empty()) {
// recompute of document is running
for (std::map<Vertex,DocumentObject*>::iterator it = d->vertexMap.begin(); it != d->vertexMap.end(); ++it) {
@@ -2051,9 +2080,10 @@ void Document::remObject(const char* sName)
// in this case transaction delete or save the object
d->activeUndoTransaction->addObjectNew(pos->second);
}
else
else {
// if not saved in undo -> delete object
delete pos->second;
}
}

for (std::vector<DocumentObject*>::iterator obj = d->objectArray.begin(); obj != d->objectArray.end(); ++obj) {
@@ -2098,9 +2128,12 @@ void Document::_remObject(DocumentObject* pcObject)
// do no transactions if we do a rollback!
if (!d->rollback) {
// Undo stuff
if (d->activeUndoTransaction)
if (d->activeUndoTransaction) {
signalTransactionRemove(*pcObject, d->activeUndoTransaction);
d->activeUndoTransaction->addObjectNew(pcObject);
}
}

// remove from map
d->objectMap.erase(pos);

@@ -116,6 +116,10 @@ class AppExport Document : public App::PropertyContainer
boost::signal<void (const App::DocumentObject&)> signalRelabelObject;
/// signal on activated Object
boost::signal<void (const App::DocumentObject&)> signalActivatedObject;
/// signal on created object
boost::signal<void (const App::DocumentObject&, Transaction*)> signalTransactionAppend;
/// signal on removed object
boost::signal<void (const App::DocumentObject&, Transaction*)> signalTransactionRemove;
/// signal on undo
boost::signal<void (const App::Document&)> signalUndo;
/// signal on redo
@@ -44,6 +44,16 @@ TransactionalObject::~TransactionalObject(void)
{
}

bool TransactionalObject::isAttachedToDocument() const
{
return false;
}

const char* TransactionalObject::detachFromDocument()
{
return "";
}

void TransactionalObject::onBeforeChangeProperty(Document *doc, const Property *prop)
{
doc->onBeforeChangeProperty(this, prop);
@@ -42,8 +42,8 @@ class AppExport TransactionalObject : public App::PropertyContainer
/// Constructor
TransactionalObject(void);
virtual ~TransactionalObject();
virtual bool isAttachedToDocument() const = 0;
virtual const char* detachFromDocument() = 0;
virtual bool isAttachedToDocument() const;
virtual const char* detachFromDocument();

protected:
void onBeforeChangeProperty(Document *doc, const Property *prop);
@@ -67,9 +67,6 @@ class AppExport Transaction : public Base::Persistence
/// check if this object is used in a transaction
bool hasObject(const TransactionalObject *Obj) const;

friend class Document;

protected:
void addObjectNew(TransactionalObject *Obj);
void addObjectDel(const TransactionalObject *Obj);
void addObjectChange(const TransactionalObject *Obj, const Property *Prop);
@@ -45,6 +45,7 @@
#include <App/Document.h>
#include <App/DocumentObject.h>
#include <App/DocumentObjectGroup.h>
#include <App/Transactions.h>

#include "Application.h"
#include "MainWindow.h"
@@ -99,6 +100,8 @@ struct DocumentP
Connection connectImportObjects;
Connection connectUndoDocument;
Connection connectRedoDocument;
Connection connectTransactionAppend;
Connection connectTransactionRemove;
};

} // namespace Gui
@@ -149,8 +152,12 @@ Document::Document(App::Document* pcDocument,Application * app)
d->connectUndoDocument = pcDocument->signalUndo.connect
(boost::bind(&Gui::Document::slotUndoDocument, this, _1));
d->connectRedoDocument = pcDocument->signalRedo.connect
(boost::bind(&Gui::Document::slotRedoDocument, this, _1));
(boost::bind(&Gui::Document::slotRedoDocument, this, _1));

d->connectTransactionAppend = pcDocument->signalTransactionAppend.connect
(boost::bind(&Gui::Document::slotTransactionAppend, this, _1, _2));
d->connectTransactionRemove = pcDocument->signalTransactionRemove.connect
(boost::bind(&Gui::Document::slotTransactionRemove, this, _1, _2));
// pointer to the python class
// NOTE: As this Python object doesn't get returned to the interpreter we
// mustn't increment it (Werner Jan-12-2006)
@@ -181,6 +188,8 @@ Document::~Document()
d->connectImportObjects.disconnect();
d->connectUndoDocument.disconnect();
d->connectRedoDocument.disconnect();
d->connectTransactionAppend.disconnect();
d->connectTransactionRemove.disconnect();

// e.g. if document gets closed from within a Python command
d->_isClosing = true;
@@ -390,41 +399,49 @@ void Document::setPos(const char* name, const Base::Matrix4D& rclMtrx)
//*****************************************************************************************************
void Document::slotNewObject(const App::DocumentObject& Obj)
{
//Base::Console().Log("Document::slotNewObject() called\n");
std::string cName = Obj.getViewProviderName();
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;
}

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()));
ViewProviderDocumentObject *pcProvider = static_cast<ViewProviderDocumentObject*>(base);
d->_ViewProviderMap[&Obj] = pcProvider;

try {
// if succesfully 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){
Base::Console().Error("Memory exception in '%s' thrown: %s\n",Obj.getNameInDocument(),e.what());
}
catch(Base::Exception &e){
e.ReportException();
ViewProviderDocumentObject* pcProvider = static_cast<ViewProviderDocumentObject*>(getViewProvider(&Obj));
if (!pcProvider) {
//Base::Console().Log("Document::slotNewObject() called\n");
std::string cName = Obj.getViewProviderName();
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;
}

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;

try {
// if succesfully 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){
Base::Console().Error("Memory exception in '%s' thrown: %s\n",Obj.getNameInDocument(),e.what());
}
catch(Base::Exception &e){
e.ReportException();
}
#ifndef FC_DEBUG
catch(...){
Base::Console().Error("App::Document::_RecomputeFeature(): Unknown exception in Feature \"%s\" thrown\n",Obj.getNameInDocument());
}
catch(...){
Base::Console().Error("App::Document::_RecomputeFeature(): Unknown exception in Feature \"%s\" thrown\n",Obj.getNameInDocument());
}
#endif
}
else {
Base::Console().Warning("Gui::Document::slotNewObject() no view provider for the object %s found\n",cName.c_str());
}
}

if (pcProvider) {
std::list<Gui::BaseView*>::iterator vIt;
// cycling to all views of the document
for (vIt = d->baseViews.begin();vIt != d->baseViews.end();++vIt) {
@@ -436,12 +453,9 @@ void Document::slotNewObject(const App::DocumentObject& Obj)
// adding to the tree
signalNewObject(*pcProvider);

// it is possible that a new viewprovider aready claims children
// it is possible that a new viewprovider already claims children
handleChildren3D(pcProvider);
}
else {
Base::Console().Warning("Gui::Document::slotNewObject() no view provider for the object %s found\n",cName.c_str());
}
}

void Document::slotDeletedObject(const App::DocumentObject& Obj)
@@ -469,9 +483,6 @@ void Document::slotDeletedObject(const App::DocumentObject& Obj)

// removing from tree
signalDeletedObject(*(static_cast<ViewProviderDocumentObject*>(viewProvider)));

delete viewProvider;
d->_ViewProviderMap.erase(&Obj);
}
}

@@ -514,6 +525,30 @@ void Document::slotRelabelObject(const App::DocumentObject& Obj)
}
}

void Document::slotTransactionAppend(const App::DocumentObject& obj, App::Transaction* transaction)
{
ViewProvider* viewProvider = getViewProvider(&obj);
if (viewProvider && viewProvider->isDerivedFrom(ViewProviderDocumentObject::getClassTypeId())) {
transaction->addObjectDel(viewProvider);
}
}

void Document::slotTransactionRemove(const App::DocumentObject& obj, App::Transaction* transaction)
{
std::map<const App::DocumentObject*,ViewProviderDocumentObject*>::const_iterator
it = d->_ViewProviderMap.find(&obj);
if (it != d->_ViewProviderMap.end()) {
ViewProvider* viewProvider = it->second;
d->_ViewProviderMap.erase(&obj);
// transaction being a nullptr indicates that undo/redo is off and the object
// can be safely deleted
if (transaction)
transaction->addObjectNew(viewProvider);
else
delete viewProvider;
}
}

void Document::slotActivatedObject(const App::DocumentObject& Obj)
{
ViewProvider* viewProvider = getViewProvider(&Obj);
@@ -538,6 +573,18 @@ void Document::slotRedoDocument(const App::Document& doc)
signalRedoDocument(*this);
}

void Document::addViewProvider(Gui::ViewProviderDocumentObject* vp)
{
vp->setStatus(Detach, false);
d->_ViewProviderMap[vp->getObject()] = vp;
}

void Document::removeViewProvider(Gui::ViewProviderDocumentObject* vp)
{
vp->setStatus(Detach, true);
d->_ViewProviderMap.erase(vp->getObject());
}

void Document::setModified(bool b)
{
d->_isModified = b;
@@ -51,6 +51,7 @@ class ViewProvider;
class ViewProviderDocumentObject;
class Application;
class DocumentPy;
class TransactionViewProvider;
enum HighlightMode;

/** The Gui Document
@@ -75,13 +76,18 @@ class GuiExport Document : public Base::Persistence
void slotDeletedObject(const App::DocumentObject&);
void slotChangedObject(const App::DocumentObject&, const App::Property&);
void slotRelabelObject(const App::DocumentObject&);
void slotTransactionAppend(const App::DocumentObject&, App::Transaction*);
void slotTransactionRemove(const App::DocumentObject&, App::Transaction*);
void slotActivatedObject(const App::DocumentObject&);
void slotStartRestoreDocument(const App::Document&);
void slotFinishRestoreDocument(const App::Document&);
void slotUndoDocument(const App::Document&);
void slotRedoDocument(const App::Document&);
//@}

void addViewProvider(Gui::ViewProviderDocumentObject*);
void removeViewProvider(Gui::ViewProviderDocumentObject*);

public:
/** @name Signals of the document */
//@{
@@ -254,6 +260,8 @@ class GuiExport Document : public Base::Persistence
/// redo names list
std::list<std::string> listRedoNames;
//@}

friend class TransactionViewProvider;
};

} // namespace Gui
Oops, something went wrong.

0 comments on commit 9ec06b4

Please sign in to comment.
You can’t perform that action at this time.