Skip to content

Commit 12cced5

Browse files
authored
Merge pull request FreeCAD#21978 from theo-vt/document_transaction
GSOC Multi file editing
2 parents 439c50c + ad630cb commit 12cced5

253 files changed

Lines changed: 4196 additions & 2476 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

src/App/Application.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -587,6 +587,15 @@ Document* Application::getDocument(const char *Name) const
587587

588588
return pos->second;
589589
}
590+
Document* Application::getDocumentOrActive(const char *Name) const
591+
{
592+
if (!Base::Tools::isNullOrEmpty(Name)) {
593+
return getDocument(Name);
594+
}
595+
else {
596+
return getActiveDocument();
597+
}
598+
}
590599

591600
const char * Application::getDocumentName(const Document* doc) const
592601
{

src/App/Application.h

Lines changed: 52 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,12 @@
3535
#include <set>
3636
#include <map>
3737
#include <string>
38+
#include <optional>
3839

3940
#include <Base/Observer.h>
4041
#include <Base/Parameter.h>
4142
#include <Base/ProgressIndicator.h>
43+
#include "TransactionDefs.h"
4244

4345
// forward declarations
4446
using PyObject = struct _object;
@@ -203,6 +205,8 @@ class AppExport Application
203205
*/
204206
App::Document* getDocument(const char *Name) const;
205207

208+
App::Document* getDocumentOrActive(const char *Name) const;
209+
206210
/// %Path matching modes for getDocumentByPath()
207211
enum class PathMatchMode
208212
{
@@ -289,9 +293,11 @@ class AppExport Application
289293
/**
290294
* @brief Setup a pending application-wide active transaction.
291295
*
292-
* Call this function to setup an application-wide transaction. All current
293-
* pending transactions of opening documents will be committed first.
294-
* However, no new transaction is created by this call. Any subsequent
296+
* Call this function to setup a transaction in the currently active document
297+
* if no document is active, a global transaction is created. If the current
298+
* active document already has a transaction setup it will either commit the
299+
* current transaction or rename it, depending on the tmpName flag of the
300+
* currently setup transaction. No new transaction is created by this call. Any subsequent
295301
* changes in any current opening document will auto create a transaction
296302
* with the given name and ID. If more than one document is changed, the
297303
* transactions will share the same ID, and will be undo/redo together.
@@ -303,32 +309,45 @@ class AppExport Application
303309
*
304310
* @return The new transaction ID.
305311
*/
306-
int setActiveTransaction(const char* name, bool persist = false);
307312

308-
/**
309-
* @brief Get the current active transaction name and ID.
313+
int setActiveTransaction(TransactionName name);
314+
315+
/// Return the current global transaction name and ID if such a global transaction is
316+
/// setup (uncommon)
317+
std::string getActiveTransaction(int *tid=nullptr) const;
318+
319+
int openGlobalTransaction(TransactionName name);
320+
int getGlobalTransaction() const;
321+
322+
bool transactionIsActive(int tid) const;
323+
std::string getTransactionName(int tid) const;
324+
bool transactionTmpName(int tid) const;
325+
Document* transactionInitiator(int tid) const;
326+
std::optional<TransactionDescription> transactionDescription(int tid) const;
327+
void setTransactionDescription(int tid, const TransactionDescription& desc);
328+
void setTransactionName(int tid, const TransactionName& name);
329+
330+
/** Commit/abort current active transactions
310331
*
311332
* If there is no active transaction, an empty string is returned.
312333
*
313-
* @param[out] tid If not `nullptr`, the current active transaction ID is
314-
* returned through this pointer.
315-
* @return The current active transaction name.
316-
*/
317-
const char* getActiveTransaction(int* tid = nullptr) const;
318-
319-
/**
320-
* @brief Commit/abort current active transactions.
321-
*
322334
* @param[in] abort: whether to abort or commit the transactions
323-
* @param[in] id: by default 0 meaning that the current active transaction ID is used.
324-
*
325-
* Besides calling this function directly, it will be called by
326-
* automatically if 1) any new transaction is created with a different ID,
327-
* or 2) any transaction with the current active transaction ID is either
328-
* committed or aborted.
335+
* @param[in] id: by default 0 meaning that the current global transaction ID is used.
336+
*
337+
* Bsides calling this function directly, it will be called by automatically
338+
* if 1) any new transaction is created with a different ID, or 2) any
339+
* transaction with the current active transaction ID is either committed or
340+
* aborted
341+
* returns true if it succeeded in closing the transaction
329342
*/
330-
void closeActiveTransaction(bool abort=false, int id=0);
331-
/// @}
343+
bool closeActiveTransaction(TransactionCloseMode mode = TransactionCloseMode::Commit, int id=0);
344+
345+
/// Internally call closeActiveTransaction(), but it makes the call site clearer
346+
bool commitTransaction(int tid);
347+
bool abortTransaction(int tid);
348+
349+
350+
//@}
332351

333352
// NOLINTBEGIN
334353
// clang-format off
@@ -1040,10 +1059,16 @@ class AppExport Application
10401059

10411060
friend class AutoTransaction;
10421061

1043-
std::string _activeTransactionName;
1044-
int _activeTransactionID{0};
1045-
int _activeTransactionGuard{0};
1046-
bool _activeTransactionTmpName{false};
1062+
std::map<int, TransactionDescription> _activeTransactionDescriptions; // Maps transaction ID to transaction name
1063+
1064+
int currentlyClosingID {0};
1065+
1066+
// This is the transaction ID for a global transaction
1067+
// Documents will take this ID if it is non-zero
1068+
// and generate their own otherwise
1069+
int _globalTransactionID { 0 };
1070+
bool _globalTransactionTmpName {false};
1071+
std::string _globalTransactionName;
10471072

10481073
Base::ProgressIndicator _progressIndicator;
10491074

src/App/ApplicationPy.cpp

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -242,9 +242,7 @@ PyMethodDef ApplicationPy::Methods[] = {
242242
METH_VARARGS,
243243
"setActiveTransaction(name, persist=False) -- setup active transaction with the given name\n\n"
244244
"name: the transaction name\n"
245-
"persist(False): by default, if the calling code is inside any invocation of a command, it\n"
246-
" will be auto closed once all commands within the current stack exists. To\n"
247-
" disable auto closing, set persist=True\n"
245+
"persist(False): This parameter has no effect and is kept for compatibility reasonss"
248246
"Returns the transaction ID for the active transaction. An application-wide\n"
249247
"active transaction causes any document changes to open a transaction with\n"
250248
"the given name and ID."},
@@ -1201,14 +1199,14 @@ PyObject* ApplicationPy::sGetDependentObjects(PyObject* /*self*/, PyObject* args
12011199
PyObject* ApplicationPy::sSetActiveTransaction(PyObject* /*self*/, PyObject* args)
12021200
{
12031201
char* name {};
1204-
PyObject* persist = Py_False;
1202+
PyObject* persist = Py_False; // Not used
12051203
if (!PyArg_ParseTuple(args, "s|O!", &name, &PyBool_Type, &persist)) {
12061204
return nullptr;
12071205
}
12081206

12091207
PY_TRY
12101208
{
1211-
Py::Long ret(GetApplication().setActiveTransaction(name, Base::asBoolean(persist)));
1209+
Py::Long ret(GetApplication().setActiveTransaction(TransactionName {.name=name, .temporary=false}));
12121210
return Py::new_reference_to(ret);
12131211
}
12141212
PY_CATCH;
@@ -1223,8 +1221,8 @@ PyObject* ApplicationPy::sGetActiveTransaction(PyObject* /*self*/, PyObject* arg
12231221
PY_TRY
12241222
{
12251223
int id = 0;
1226-
const char* name = GetApplication().getActiveTransaction(&id);
1227-
if (!name || id <= 0) {
1224+
std::string name = GetApplication().getActiveTransaction(&id);
1225+
if (name.empty() || id <= 0) {
12281226
Py_Return;
12291227
}
12301228
Py::Tuple ret(2);
@@ -1245,7 +1243,10 @@ PyObject* ApplicationPy::sCloseActiveTransaction(PyObject* /*self*/, PyObject* a
12451243

12461244
PY_TRY
12471245
{
1248-
GetApplication().closeActiveTransaction(Base::asBoolean(abort), id);
1246+
TransactionCloseMode mode = Base::asBoolean(abort)
1247+
? TransactionCloseMode::Abort
1248+
: TransactionCloseMode::Commit;
1249+
GetApplication().closeActiveTransaction(mode, id);
12491250
Py_Return;
12501251
}
12511252
PY_CATCH;

0 commit comments

Comments
 (0)