Split App::AutoTransaction into its own file
This commit is contained in:
@@ -849,145 +849,6 @@ void Application::setActiveDocument(const char *Name)
|
||||
}
|
||||
}
|
||||
|
||||
AutoTransaction::AutoTransaction(const char *name, bool tmpName) {
|
||||
auto &app = GetApplication();
|
||||
if(name && app._activeTransactionGuard>=0) {
|
||||
if(!app.getActiveTransaction()
|
||||
|| (!tmpName && app._activeTransactionTmpName))
|
||||
{
|
||||
FC_LOG("auto transaction '" << name << "', " << tmpName);
|
||||
tid = app.setActiveTransaction(name);
|
||||
app._activeTransactionTmpName = tmpName;
|
||||
}
|
||||
}
|
||||
// We use negative transaction guard to disable auto transaction from here
|
||||
// and any stack below. This is to support user setting active transaction
|
||||
// before having any existing AutoTransaction on stack, or 'persist'
|
||||
// transaction that can out live AutoTransaction.
|
||||
if(app._activeTransactionGuard<0)
|
||||
--app._activeTransactionGuard;
|
||||
else if(tid || app._activeTransactionGuard>0)
|
||||
++app._activeTransactionGuard;
|
||||
else if(app.getActiveTransaction()) {
|
||||
FC_LOG("auto transaction disabled because of '" << app._activeTransactionName << "'");
|
||||
--app._activeTransactionGuard;
|
||||
} else
|
||||
++app._activeTransactionGuard;
|
||||
FC_TRACE("construct auto Transaction " << app._activeTransactionGuard);
|
||||
}
|
||||
|
||||
AutoTransaction::~AutoTransaction() {
|
||||
auto &app = GetApplication();
|
||||
FC_TRACE("before destruct auto Transaction " << app._activeTransactionGuard);
|
||||
if(app._activeTransactionGuard<0)
|
||||
++app._activeTransactionGuard;
|
||||
else if(!app._activeTransactionGuard) {
|
||||
#ifdef FC_DEBUG
|
||||
FC_ERR("Transaction guard error");
|
||||
#endif
|
||||
} else if(--app._activeTransactionGuard == 0) {
|
||||
try {
|
||||
// We don't call close() here, because close() only closes
|
||||
// transaction that we opened during construction time. However,
|
||||
// when _activeTransactionGuard reaches zero here, we are supposed
|
||||
// to close any transaction opened.
|
||||
app.closeActiveTransaction();
|
||||
} catch(Base::Exception &e) {
|
||||
e.ReportException();
|
||||
} catch(...)
|
||||
{}
|
||||
}
|
||||
FC_TRACE("destruct auto Transaction " << app._activeTransactionGuard);
|
||||
}
|
||||
|
||||
void AutoTransaction::close(bool abort) {
|
||||
if(tid || abort) {
|
||||
GetApplication().closeActiveTransaction(abort,abort?0:tid);
|
||||
tid = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void AutoTransaction::setEnable(bool enable) {
|
||||
auto &app = GetApplication();
|
||||
if(!app._activeTransactionGuard)
|
||||
return;
|
||||
if((enable && app._activeTransactionGuard>0)
|
||||
|| (!enable && app._activeTransactionGuard<0))
|
||||
return;
|
||||
app._activeTransactionGuard = -app._activeTransactionGuard;
|
||||
FC_TRACE("toggle auto Transaction " << app._activeTransactionGuard);
|
||||
if(!enable && app._activeTransactionTmpName) {
|
||||
bool close = true;
|
||||
for(auto &v : app.DocMap) {
|
||||
if(v.second->hasPendingTransaction()) {
|
||||
close = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(close)
|
||||
app.closeActiveTransaction();
|
||||
}
|
||||
}
|
||||
|
||||
int Application::setActiveTransaction(const char *name, bool persist) {
|
||||
if(!name || !name[0])
|
||||
name = "Command";
|
||||
|
||||
if(_activeTransactionGuard>0 && getActiveTransaction()) {
|
||||
if(_activeTransactionTmpName) {
|
||||
FC_LOG("transaction rename to '" << name << "'");
|
||||
for(auto &v : DocMap)
|
||||
v.second->renameTransaction(name,_activeTransactionID);
|
||||
} else {
|
||||
if(persist)
|
||||
AutoTransaction::setEnable(false);
|
||||
return 0;
|
||||
}
|
||||
}else{
|
||||
FC_LOG("set active transaction '" << name << "'");
|
||||
_activeTransactionID = 0;
|
||||
for(auto &v : DocMap)
|
||||
v.second->_commitTransaction();
|
||||
_activeTransactionID = Transaction::getNewID();
|
||||
}
|
||||
_activeTransactionTmpName = false;
|
||||
_activeTransactionName = name;
|
||||
if(persist)
|
||||
AutoTransaction::setEnable(false);
|
||||
return _activeTransactionID;
|
||||
}
|
||||
|
||||
const char *Application::getActiveTransaction(int *id) const {
|
||||
int tid = 0;
|
||||
if(Transaction::getLastID() == _activeTransactionID)
|
||||
tid = _activeTransactionID;
|
||||
if(id) *id = tid;
|
||||
return tid?_activeTransactionName.c_str():0;
|
||||
}
|
||||
|
||||
void Application::closeActiveTransaction(bool abort, int id) {
|
||||
if(!id) id = _activeTransactionID;
|
||||
if(!id) return;
|
||||
|
||||
if(_activeTransactionGuard>0 && !abort) {
|
||||
FC_LOG("ignore close transaction");
|
||||
return;
|
||||
}
|
||||
|
||||
FC_LOG("close transaction '" << _activeTransactionName << "' " << abort);
|
||||
_activeTransactionID = 0;
|
||||
|
||||
TransactionSignaller siganller(abort,false);
|
||||
for(auto &v : DocMap) {
|
||||
if(v.second->getTransactionID(true) != id)
|
||||
continue;
|
||||
if(abort)
|
||||
v.second->_abortTransaction();
|
||||
else
|
||||
v.second->_commitTransaction();
|
||||
}
|
||||
}
|
||||
|
||||
static int _TransSignalCount;
|
||||
static bool _TransSignalled;
|
||||
Application::TransactionSignaller::TransactionSignaller(bool abort, bool signal)
|
||||
|
||||
@@ -568,60 +568,6 @@ inline App::Application &GetApplication(void){
|
||||
return *App::Application::_pcSingleton;
|
||||
}
|
||||
|
||||
/// Helper class to manager transaction (i.e. undo/redo)
|
||||
class AppExport AutoTransaction {
|
||||
private:
|
||||
/// Private new operator to prevent heap allocation
|
||||
void* operator new(size_t size);
|
||||
|
||||
public:
|
||||
/** Constructor
|
||||
*
|
||||
* @param name: optional new transaction name on construction
|
||||
* @param tmpName: if true and a new transaction is setup, the name given is
|
||||
* considered as temporary, and subsequent construction of this class (or
|
||||
* calling Application::setActiveTransaction()) can override the transaction
|
||||
* name.
|
||||
*
|
||||
* The constructor increments an internal counter
|
||||
* (Application::_activeTransactionGuard). The counter prevents any new
|
||||
* active transaction being setup. It also prevents close (i.e. commits) the
|
||||
* current active transaction until it reaches zero. It does not have any
|
||||
* effect on aborting transaction, though.
|
||||
*/
|
||||
AutoTransaction(const char *name=0, bool tmpName=false);
|
||||
|
||||
/** Destructor
|
||||
*
|
||||
* This destructor decrease an internal counter
|
||||
* (Application::_activeTransactionGuard), and will commit any current
|
||||
* active transaction when the counter reaches zero.
|
||||
*/
|
||||
~AutoTransaction();
|
||||
|
||||
/** Close or abort the transaction
|
||||
*
|
||||
* This function can be used to explicitly close (i.e. commit) the
|
||||
* transaction, if the current transaction ID matches the one created inside
|
||||
* the constructor. For aborting, it will abort any current transaction
|
||||
*/
|
||||
void close(bool abort=false);
|
||||
|
||||
/** Enable/Disable any AutoTransaction instance in the current stack
|
||||
*
|
||||
* Once disabled, any empty temporary named transaction is closed. If there
|
||||
* are non-empty or non-temperary named active transaction, it will not be
|
||||
* auto closed.
|
||||
*
|
||||
* This function may be used in, for example, Gui::Document::setEdit() to
|
||||
* allow a transaction live past any command scope.
|
||||
*/
|
||||
static void setEnable(bool enable);
|
||||
|
||||
private:
|
||||
int tid = 0;
|
||||
};
|
||||
|
||||
} // namespace App
|
||||
|
||||
|
||||
|
||||
172
src/App/AutoTransaction.cpp
Normal file
172
src/App/AutoTransaction.cpp
Normal file
@@ -0,0 +1,172 @@
|
||||
/****************************************************************************
|
||||
* Copyright (c) 2019 Zheng, Lei (realthunder) <realthunder.dev@gmail.com>*
|
||||
* *
|
||||
* This file is part of the FreeCAD CAx development system. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Library General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU Library General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Library General Public *
|
||||
* License along with this library; see the file COPYING.LIB. If not, *
|
||||
* write to the Free Software Foundation, Inc., 59 Temple Place, *
|
||||
* Suite 330, Boston, MA 02111-1307, USA *
|
||||
* *
|
||||
****************************************************************************/
|
||||
|
||||
#include "PreCompiled.h"
|
||||
#include <Base/Console.h>
|
||||
#include "Application.h"
|
||||
#include "Transactions.h"
|
||||
#include "Document.h"
|
||||
#include "AutoTransaction.h"
|
||||
|
||||
FC_LOG_LEVEL_INIT("App",true,true);
|
||||
|
||||
using namespace App;
|
||||
|
||||
AutoTransaction::AutoTransaction(const char *name, bool tmpName) {
|
||||
auto &app = GetApplication();
|
||||
if(name && app._activeTransactionGuard>=0) {
|
||||
if(!app.getActiveTransaction()
|
||||
|| (!tmpName && app._activeTransactionTmpName))
|
||||
{
|
||||
FC_LOG("auto transaction '" << name << "', " << tmpName);
|
||||
tid = app.setActiveTransaction(name);
|
||||
app._activeTransactionTmpName = tmpName;
|
||||
}
|
||||
}
|
||||
// We use negative transaction guard to disable auto transaction from here
|
||||
// and any stack below. This is to support user setting active transaction
|
||||
// before having any existing AutoTransaction on stack, or 'persist'
|
||||
// transaction that can out live AutoTransaction.
|
||||
if(app._activeTransactionGuard<0)
|
||||
--app._activeTransactionGuard;
|
||||
else if(tid || app._activeTransactionGuard>0)
|
||||
++app._activeTransactionGuard;
|
||||
else if(app.getActiveTransaction()) {
|
||||
FC_LOG("auto transaction disabled because of '" << app._activeTransactionName << "'");
|
||||
--app._activeTransactionGuard;
|
||||
} else
|
||||
++app._activeTransactionGuard;
|
||||
FC_TRACE("construct auto Transaction " << app._activeTransactionGuard);
|
||||
}
|
||||
|
||||
AutoTransaction::~AutoTransaction() {
|
||||
auto &app = GetApplication();
|
||||
FC_TRACE("before destruct auto Transaction " << app._activeTransactionGuard);
|
||||
if(app._activeTransactionGuard<0)
|
||||
++app._activeTransactionGuard;
|
||||
else if(!app._activeTransactionGuard) {
|
||||
#ifdef FC_DEBUG
|
||||
FC_ERR("Transaction guard error");
|
||||
#endif
|
||||
} else if(--app._activeTransactionGuard == 0) {
|
||||
try {
|
||||
// We don't call close() here, because close() only closes
|
||||
// transaction that we opened during construction time. However,
|
||||
// when _activeTransactionGuard reaches zero here, we are supposed
|
||||
// to close any transaction opened.
|
||||
app.closeActiveTransaction();
|
||||
} catch(Base::Exception &e) {
|
||||
e.ReportException();
|
||||
} catch(...)
|
||||
{}
|
||||
}
|
||||
FC_TRACE("destruct auto Transaction " << app._activeTransactionGuard);
|
||||
}
|
||||
|
||||
void AutoTransaction::close(bool abort) {
|
||||
if(tid || abort) {
|
||||
GetApplication().closeActiveTransaction(abort,abort?0:tid);
|
||||
tid = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void AutoTransaction::setEnable(bool enable) {
|
||||
auto &app = GetApplication();
|
||||
if(!app._activeTransactionGuard)
|
||||
return;
|
||||
if((enable && app._activeTransactionGuard>0)
|
||||
|| (!enable && app._activeTransactionGuard<0))
|
||||
return;
|
||||
app._activeTransactionGuard = -app._activeTransactionGuard;
|
||||
FC_TRACE("toggle auto Transaction " << app._activeTransactionGuard);
|
||||
if(!enable && app._activeTransactionTmpName) {
|
||||
bool close = true;
|
||||
for(auto &v : app.DocMap) {
|
||||
if(v.second->hasPendingTransaction()) {
|
||||
close = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(close)
|
||||
app.closeActiveTransaction();
|
||||
}
|
||||
}
|
||||
|
||||
int Application::setActiveTransaction(const char *name, bool persist) {
|
||||
if(!name || !name[0])
|
||||
name = "Command";
|
||||
|
||||
if(_activeTransactionGuard>0 && getActiveTransaction()) {
|
||||
if(_activeTransactionTmpName) {
|
||||
FC_LOG("transaction rename to '" << name << "'");
|
||||
for(auto &v : DocMap)
|
||||
v.second->renameTransaction(name,_activeTransactionID);
|
||||
} else {
|
||||
if(persist)
|
||||
AutoTransaction::setEnable(false);
|
||||
return 0;
|
||||
}
|
||||
}else{
|
||||
FC_LOG("set active transaction '" << name << "'");
|
||||
_activeTransactionID = 0;
|
||||
for(auto &v : DocMap)
|
||||
v.second->_commitTransaction();
|
||||
_activeTransactionID = Transaction::getNewID();
|
||||
}
|
||||
_activeTransactionTmpName = false;
|
||||
_activeTransactionName = name;
|
||||
if(persist)
|
||||
AutoTransaction::setEnable(false);
|
||||
return _activeTransactionID;
|
||||
}
|
||||
|
||||
const char *Application::getActiveTransaction(int *id) const {
|
||||
int tid = 0;
|
||||
if(Transaction::getLastID() == _activeTransactionID)
|
||||
tid = _activeTransactionID;
|
||||
if(id) *id = tid;
|
||||
return tid?_activeTransactionName.c_str():0;
|
||||
}
|
||||
|
||||
void Application::closeActiveTransaction(bool abort, int id) {
|
||||
if(!id) id = _activeTransactionID;
|
||||
if(!id) return;
|
||||
|
||||
if(_activeTransactionGuard>0 && !abort) {
|
||||
FC_LOG("ignore close transaction");
|
||||
return;
|
||||
}
|
||||
|
||||
FC_LOG("close transaction '" << _activeTransactionName << "' " << abort);
|
||||
_activeTransactionID = 0;
|
||||
|
||||
TransactionSignaller siganller(abort,false);
|
||||
for(auto &v : DocMap) {
|
||||
if(v.second->getTransactionID(true) != id)
|
||||
continue;
|
||||
if(abort)
|
||||
v.second->_abortTransaction();
|
||||
else
|
||||
v.second->_commitTransaction();
|
||||
}
|
||||
}
|
||||
|
||||
84
src/App/AutoTransaction.h
Normal file
84
src/App/AutoTransaction.h
Normal file
@@ -0,0 +1,84 @@
|
||||
/****************************************************************************
|
||||
* Copyright (c) 2019 Zheng, Lei (realthunder) <realthunder.dev@gmail.com>*
|
||||
* *
|
||||
* This file is part of the FreeCAD CAx development system. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Library General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU Library General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Library General Public *
|
||||
* License along with this library; see the file COPYING.LIB. If not, *
|
||||
* write to the Free Software Foundation, Inc., 59 Temple Place, *
|
||||
* Suite 330, Boston, MA 02111-1307, USA *
|
||||
* *
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef APP_AUTOTRANSACTION_H
|
||||
#define APP_AUTOTRANSACTION_H
|
||||
|
||||
namespace App {
|
||||
|
||||
/// Helper class to manager transaction (i.e. undo/redo)
|
||||
class AppExport AutoTransaction {
|
||||
private:
|
||||
/// Private new operator to prevent heap allocation
|
||||
void* operator new(size_t size);
|
||||
|
||||
public:
|
||||
/** Constructor
|
||||
*
|
||||
* @param name: optional new transaction name on construction
|
||||
* @param tmpName: if true and a new transaction is setup, the name given is
|
||||
* considered as temporary, and subsequent construction of this class (or
|
||||
* calling Application::setActiveTransaction()) can override the transaction
|
||||
* name.
|
||||
*
|
||||
* The constructor increments an internal counter
|
||||
* (Application::_activeTransactionGuard). The counter prevents any new
|
||||
* active transaction being setup. It also prevents close (i.e. commits) the
|
||||
* current active transaction until it reaches zero. It does not have any
|
||||
* effect on aborting transaction, though.
|
||||
*/
|
||||
AutoTransaction(const char *name=0, bool tmpName=false);
|
||||
|
||||
/** Destructor
|
||||
*
|
||||
* This destructor decrease an internal counter
|
||||
* (Application::_activeTransactionGuard), and will commit any current
|
||||
* active transaction when the counter reaches zero.
|
||||
*/
|
||||
~AutoTransaction();
|
||||
|
||||
/** Close or abort the transaction
|
||||
*
|
||||
* This function can be used to explicitly close (i.e. commit) the
|
||||
* transaction, if the current transaction ID matches the one created inside
|
||||
* the constructor. For aborting, it will abort any current transaction
|
||||
*/
|
||||
void close(bool abort=false);
|
||||
|
||||
/** Enable/Disable any AutoTransaction instance in the current stack
|
||||
*
|
||||
* Once disabled, any empty temporary named transaction is closed. If there
|
||||
* are non-empty or non-temporary named active transaction, it will not be
|
||||
* auto closed.
|
||||
*
|
||||
* This function may be used in, for example, Gui::Document::setEdit() to
|
||||
* allow a transaction live past any command scope.
|
||||
*/
|
||||
static void setEnable(bool enable);
|
||||
|
||||
private:
|
||||
int tid = 0;
|
||||
};
|
||||
|
||||
} // namespace App
|
||||
|
||||
#endif // APP_AUTOTRANSACTION_H
|
||||
@@ -254,6 +254,7 @@ SET(FreeCADApp_CPP_SRCS
|
||||
${Properties_CPP_SRCS}
|
||||
Application.cpp
|
||||
ApplicationPy.cpp
|
||||
AutoTransaction.cpp
|
||||
Branding.cpp
|
||||
ColorModel.cpp
|
||||
ComplexGeoData.cpp
|
||||
@@ -267,6 +268,7 @@ SET(FreeCADApp_HPP_SRCS
|
||||
${Document_HPP_SRCS}
|
||||
${Properties_HPP_SRCS}
|
||||
Application.h
|
||||
AutoTransaction.h
|
||||
Branding.h
|
||||
ColorModel.h
|
||||
ComplexGeoData.h
|
||||
|
||||
@@ -64,6 +64,7 @@
|
||||
|
||||
#include <App/Document.h>
|
||||
#include <App/DocumentObject.h>
|
||||
#include <App/AutoTransaction.h>
|
||||
#include <Gui/ViewProviderLink.h>
|
||||
|
||||
FC_LOG_LEVEL_INIT("Command", true, true);
|
||||
|
||||
@@ -46,6 +46,7 @@
|
||||
#include <Base/Sequencer.h>
|
||||
#include <Base/Tools.h>
|
||||
#include <Base/Console.h>
|
||||
#include <App/AutoTransaction.h>
|
||||
#include <App/Document.h>
|
||||
#include <App/DocumentObjectGroup.h>
|
||||
#include <App/DocumentObject.h>
|
||||
|
||||
@@ -51,6 +51,7 @@
|
||||
#include <App/DocumentObject.h>
|
||||
#include <App/DocumentObjectGroup.h>
|
||||
#include <App/Transactions.h>
|
||||
#include <App/AutoTransaction.h>
|
||||
#include <App/GeoFeatureGroupExtension.h>
|
||||
|
||||
#include "Application.h"
|
||||
|
||||
@@ -47,6 +47,7 @@
|
||||
#include <App/Document.h>
|
||||
#include <App/DocumentObject.h>
|
||||
#include <App/DocumentObjectGroup.h>
|
||||
#include <App/AutoTransaction.h>
|
||||
#include <App/GeoFeatureGroupExtension.h>
|
||||
#include <App/Link.h>
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#define GUI_VIEWPROVIDERPYTHONFEATURE_H
|
||||
|
||||
#include <App/Application.h>
|
||||
#include <App/AutoTransaction.h>
|
||||
#include <Gui/ViewProviderGeometryObject.h>
|
||||
#include <Gui/Document.h>
|
||||
#include <App/PropertyPythonObject.h>
|
||||
|
||||
@@ -37,6 +37,7 @@
|
||||
#include <Base/Tools.h>
|
||||
#include <App/Application.h>
|
||||
#include <App/Document.h>
|
||||
#include <App/AutoTransaction.h>
|
||||
#include "MainWindow.h"
|
||||
#include "DlgAddProperty.h"
|
||||
#include "PropertyEditor.h"
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
#endif
|
||||
|
||||
#include <App/Application.h>
|
||||
#include <App/AutoTransaction.h>
|
||||
#include <App/Document.h>
|
||||
#include <Gui/Command.h>
|
||||
#include <Gui/MainWindow.h>
|
||||
|
||||
Reference in New Issue
Block a user