QOF: Undo: Track and undo or redo entity changes

QOF 0.7.5

- Main Page
- Related Pages
- Modules
- Data Structures
- Files

Files | Macros | Functions
Undo: Track and undo or redo entity changes
Query Object Framework

## Files
file | qofundo.h
| QOF undo handling.

## Macros
#define | QOF_MOD_UNDO "qof-undo"

## Functions
void | qof_undo_set_param (QofEntity *ent, const QofParam *param, gchar *value)
| Set a value in this parameter of the entity. More...
void | qof_undo_modify (QofInstance *inst, const QofParam *param)
void | qof_undo_commit (QofInstance *inst, const QofParam *param)
void | qof_undo_create (QofInstance *inst)
void | qof_undo_delete (QofInstance *inst)
void | qof_book_clear_undo (QofBook *book)
| Free the entire undo list for this book. More...
void | qof_book_undo (QofBook *book)
| Set parameter values from before the previous event.
void | qof_book_redo (QofBook *book)
| Set parameter values from after the previous event.
gboolean | qof_book_can_undo (QofBook *book)
| event handler for undo widget More...
gboolean | qof_book_can_redo (QofBook *book)
| event handler for redo widget More...
void | qof_book_start_operation (QofBook *book, gchar *label)
| Start recording operation. More...
void | qof_book_end_operation (QofBook *book)
| End recording the current operation.
QofTime * | qof_book_undo_first_modified (QofBook *book)
| HIG compliance aid to report time of first change.
gint | qof_book_undo_count (QofBook *book)
| Number of undo operations available.

## Detailed Description

QOF Undo operates within a QofBook. In order to undo the changes to the entity, the initial state of each parameter is cached when an operation begins. If the entity changes are not successful, the lack of a qof_book_end_operation call before a qof_book_start_operation will cause the cached data to be freed. If the entity is changed successfully, qof_book_end_operation will create the undo data using the operation label and each of the entity changes that were successful.

Within each operation, entity changes can be recorded using QofEventHandler or individually.

- New entity: call qof_undo_create after creation. (QOF_EVENT_CREATE)
- Before editing a parameter of an entity, qof_undo_modify (QOF_EVENT_MODIFY)
- After editing a parameter of an entity, qof_undo_commit (QOF_EVENT_COMMIT)

- Before deleting an entity, qof_undo_delete. (QOF_EVENT_DESTROY)

  Undo data consists of a list of operations that have changed data in this book and a list of entity changes for each of those operations. Each operation can relate to more than one entity change and cover more than one entity but must only relate to one book.

1. Only QOF parameter changes can be undone or redone. Data from structs that are not QOF objects or which have no QofParam to get and set the data will not be available to the undo process.
2. Undo relates to 'user interface operations', not engine events. This is because an operation (like an import or voiding a transaction) can involve multiple, possibly conflicting, engine events - e.g. removing an entity from one reference and inserting it as another. Therefore, the UI developer alone can decide where an operation begins and ends. All changes between the two will be undone or redone in one call to qof_book_undo.
3. Undo operations cannot be nested. Be careful where you start and end an undo operation, if your application calls qof_book_start_operation() before calling qof_book_end_operation(), the undo cache will be freed and QofUndo will not notify you of this. The API is designed to silently handle user aborts during a user operation. As undo data is cached when editing begins, if the edit is never completed the cache must be cleared before the next operation. i.e. if the user starts to edit an entity but then cancels the operation, there are no changes to undo. It follows that any one book can only be the subject of one operation at a time.

Since
  0.7.0

## Function Documentation

gboolean qof_book_can_redo | ( | QofBook * | book | ) |

event handler for redo widget

Returns
  FALSE if index_position == 0 or index_position == length otherwise TRUE.

Definition at line 442 of file qofundo.c.

443 {
444 QofUndo *book_undo;
445 gint length;
446
447 book_undo = book->undo_data;
448 length = g_list_length (book_undo->undo_list);
449 if ((book_undo->index_position == length) || (length == 0))
450 return FALSE;
451 return TRUE;
452 }
QofUndo_s
Definition: qofundo-p.h:56
_QofBook::undo_data
QofUndo * undo_data
Definition: qofbook-p.h:90

gboolean qof_book_can_undo | ( | QofBook * | book | ) |

event handler for undo widget

Returns
  FALSE if length == 0 or index_position == 0, otherwise TRUE.

Definition at line 429 of file qofundo.c.

430 {
431 QofUndo *book_undo;
432 gint length;
433
434 book_undo = book->undo_data;
435 length = g_list_length (book_undo->undo_list);
436 if ((book_undo->index_position == 0) || (length == 0))
437 return FALSE;
438 return TRUE;
439 }
QofUndo_s
Definition: qofundo-p.h:56
_QofBook::undo_data
QofUndo * undo_data
Definition: qofbook-p.h:90

void qof_book_clear_undo | ( | QofBook * | book | ) |

Free the entire undo list for this book.

The application needs to decide whether to reset the undo list upon session_save, application close, user intervention etc.

Definition at line 409 of file qofundo.c.

410 {
411 QofUndoOperation *operation;
412 QofUndo *book_undo;
413
414 if (!book)
415 return;
416 book_undo = book->undo_data;
417 while (book_undo != NULL)
418 {
419 operation = (QofUndoOperation *) book_undo->undo_list->data;
420 if(operation->entity_list)
421 g_list_free (operation->entity_list);
422 book_undo->undo_list = g_list_next (book_undo->undo_list);
423 }
424 book_undo->index_position = 0;
425 g_free (book_undo->undo_label);
426 }
QofUndo_s
Definition: qofundo-p.h:56
_QofBook::undo_data
QofUndo * undo_data
Definition: qofbook-p.h:90

void qof_book_start_operation | ( | QofBook * | book,
|  | gchar * | label
| ) |  |

Start recording operation.

Definition at line 587 of file qofundo.c.

588 {
589 QofUndo *book_undo;
590
591 book_undo = book->undo_data;
592 if (book_undo->undo_operation_open && book_undo->undo_cache)
593 {
594 g_list_free (book_undo->undo_cache);
595 book_undo->undo_operation_open = FALSE;
596 if (book_undo->undo_label)
597 g_free (book_undo->undo_label);
598 }
599 book_undo->undo_label = g_strdup (label);
600 book_undo->undo_operation_open = TRUE;
601 }
QofUndo_s
Definition: qofundo-p.h:56
_QofBook::undo_data
QofUndo * undo_data
Definition: qofbook-p.h:90

void qof_undo_commit | ( | QofInstance * | inst,
|  | const QofParam * | param
| ) |  |

Mark this instance parameter after modification

Prepare undo data for this instance after committal. Record the modified state of this parameter of this instance so that if this operation is undone and then redone, the modification can be recreated.

Definition at line 571 of file qofundo.c.

572 {
573 QofUndoEntity *undo_entity;
574 QofUndo *book_undo;
575 QofBook *book;
576
577 if (!instance || !param)
578 return;
579 book = instance->book;
580 book_undo = book->undo_data;
581 undo_entity = qof_prepare_undo (&instance->entity, param);
582 book_undo->undo_cache =
583 g_list_prepend (book_undo->undo_cache, undo_entity);
584 }
QofUndo_s
Definition: qofundo-p.h:56
_QofBook::undo_data
QofUndo * undo_data
Definition: qofbook-p.h:90
_QofBook
Definition: qofbook-p.h:48

void qof_undo_create | ( | QofInstance * | inst | ) |

prepare undo data for a new instance.

Record the creation of a new (empty) instance so that undo can delete it (and recreate it on redo).

Can be used within a QofEventHandler in response to QOF_EVENT_CREATE.

Definition at line 486 of file qofundo.c.

487 {
488 QofUndoEntity *undo_entity;
489 QofBook *book;
490 QofUndo *book_undo;
491
492 if (!instance)
493 return;
494 book = instance->book;
495 book_undo = book->undo_data;
496 undo_entity = g_new0 (QofUndoEntity, 1);
497 // to undo a create, use a delete.
498 undo_entity->how = UNDO_DELETE;
499 undo_entity->guid = qof_instance_get_guid (instance);
500 undo_entity->type = instance->entity.e_type;
501 book_undo->undo_cache =
502 g_list_prepend (book_undo->undo_cache, undo_entity);
503 }
QofUndo_s
Definition: qofundo-p.h:56
_QofBook::undo_data
QofUndo * undo_data
Definition: qofbook-p.h:90
qof_instance_get_guid
const GUID * qof_instance_get_guid(QofInstance *inst)
Definition: qofinstance.c:79
_QofBook
Definition: qofbook-p.h:48

void qof_undo_delete | ( | QofInstance * | inst | ) |

prepare undo data for an instance to be deleted.

Prepare for the deletion of an entity by storing ALL data in all editable parameters so that this delete operation can be undone.

Can be used within a QofEventHandler in response to QOF_EVENT_DESTROY, before the instance itself is deleted.

Definition at line 523 of file qofundo.c.

524 {
525 QofUndoEntity *undo_entity;
526 QofIdType type;
527 QofUndo *book_undo;
528 QofBook *book;
529
530 if (!instance)
531 return;
532 book = instance->book;
533 book_undo = book->undo_data;
534 // now need to store each parameter in a second entity, MODIFY.
535 type = instance->entity.e_type;
536 qof_class_param_foreach (type, undo_get_entity, instance);
537 undo_entity = g_new0 (QofUndoEntity, 1);
538 // to undo a delete, use a create.
539 undo_entity->how = UNDO_CREATE;
540 undo_entity->guid = qof_instance_get_guid (instance);
541 undo_entity->type = type;
542 book_undo->undo_cache =
543 g_list_prepend (book_undo->undo_cache, undo_entity);
544 }
QofIdType
const gchar * QofIdType
Definition: qofid.h:81
qof_class_param_foreach
void qof_class_param_foreach(QofIdTypeConst obj_name, QofParamForeachCB cb, gpointer user_data)
Definition: qofclass.c:267
QofUndo_s
Definition: qofundo-p.h:56
_QofBook::undo_data
QofUndo * undo_data
Definition: qofbook-p.h:90
qof_instance_get_guid
const GUID * qof_instance_get_guid(QofInstance *inst)
Definition: qofinstance.c:79
_QofBook
Definition: qofbook-p.h:48

void qof_undo_modify | ( | QofInstance * | inst,
|  | const QofParam * | param
| ) |  |

Mark this instance parameter before modification.

Prepare undo data for this parameter of this instance. Record the initial state of this parameter of this instance in preparation for modification so that undo can reset the value if required.

Definition at line 547 of file qofundo.c.

548 {
549 QofBook *book;
550 QofUndo *book_undo;
551 QofUndoEntity *undo_entity;
552
553 if (!instance || !param)
554 return;
555 book = instance->book;
556 book_undo = book->undo_data;
557 // handle if record is called without a commit.
558 undo_entity = qof_prepare_undo (&instance->entity, param);
559 book_undo->undo_cache =
560 g_list_prepend (book_undo->undo_cache, undo_entity);
561 // set the initial state that undo will reinstate.
562 if (book_undo->index_position == 0)
563 {
564 book_undo->undo_list = g_list_prepend (book_undo->undo_list,
565 qof_undo_new_operation (book, "initial"));
566 book_undo->index_position++;
567 }
568 }
QofUndo_s
Definition: qofundo-p.h:56
_QofBook::undo_data
QofUndo * undo_data
Definition: qofbook-p.h:90
_QofBook
Definition: qofbook-p.h:48

void qof_undo_set_param | ( | QofEntity * | ent,
|  | const QofParam * | param,
|  | gchar * | value
| ) |  |

Set a value in this parameter of the entity.

Setting an arbitrary parameter in an entity can involve repetitive string comparisons and setter function prototypes. This function accepts a QofParam (which determines the type of value) and a string representing the value. e.g. for a boolean, pass "TRUE", for a GUID pass the result of guid_to_string_buff.

Sets the undo data for this modification at the same time, calling qof_undo_modify, sets the parameter and qof_undo_commit.

Parameters

  ent | An initialised QofEntity from an accessible QofBook.
  param | from qof_class_get_parameter
  value | A string representation of the required value - original type as specified in param->param_type.

Definition at line 207 of file qofundo.c.

209 {
210 qof_undo_modify ((QofInstance*)ent, param);
211 set_param (ent, param, value);
212 qof_undo_commit ((QofInstance*)ent, param);
213 }
QofInstance_s
Definition: qofinstance-p.h:35
qof_undo_commit
void qof_undo_commit(QofInstance *instance, const QofParam *param)
Definition: qofundo.c:571
qof_undo_modify
void qof_undo_modify(QofInstance *instance, const QofParam *param)
Definition: qofundo.c:547