prepare view provider for undo/redo

This commit is contained in:
wmayer
2016-06-20 12:50:21 +02:00
parent 3d16ae0f04
commit e471ebe1fb
12 changed files with 181 additions and 70 deletions

View File

@@ -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;
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;
}
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();
}
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;