[Inquiry]GNUCash SoC - Implementing Undo

Josh Sled jsled at asynchronous.org
Wed Mar 28 13:48:46 EDT 2007

On Wed, March 28, 2007 5:37 am, Derek Atkins wrote:
> But I ALSO think that there needs to be an application-wide UNDO
> list, for operations that don't have a locality..  E.g. imports,
> accounts/budget/business object creation, etc.
> This is clearly a VERY big problem, but how can we scope it to make it
> doable in a summer.  Perhaps each QOF Instance has an undo log and
> there's some way to merge all those logs into some serialized list
> based on the current context?  But of course you still have to worry
> about the atomicity.  For example, an import operation will create (or
> modify -- setting the cleared status) a bunch of accounts and
> transactions at one time, so if you're in an account register of one
> of those transactions you shouldn't be able to remove that WHOLE
> transaction without removing the whole import -- and gnucash should
> warn you about that somehow.

I always think of Undo in terms of the GoF Command pattern ... when app
actions (maybe literally the GtkActions implementations, maybe not) are
undertaken, they append sufficient state to an app-wide undo list.  These
objects implement a trivial interface for undo/redo.  That implementation
perhaps involves:

- detecting object freshness (the transaction is dirty, I don't want to
automatically undo)

- switching the UI view to the place the undo is about to be performed

- actually mutating the object/UI.

I think we should continue with some user-focused use-cases, rather than
thinking about the transaction log/QOF and some particular solution.

Use Case 0: The user mis-enters a credit/debit cell and wants to undo.
  - need to enter the pre/post values for the cell.

Use Case 1: The user realizes they just undid the correct value, and wants
to redo.

Use Case 2: The user realizes they just entered the last 3 transactions in
the wrong register.  For some reason, they don't want to cut/paste the
transactions, but want to undo them one by one.
  - should the change to each cell of the txns be undone separately?
  - when does the user undo a "txn entry" vs. a "xfer cell edit"?

Use Case 3: Mis-import.

Use Case 4: Invoice creation/rollback.

Use Case 5: SX frequency and start-date change.


FWIW, I think the first 2 use cases solve most users immediate needs for
undo.  I'd rather solve those two specifically than have a high-risk
change that solves some undefined general problem.

I'm pretty sure that all more complex use-cases will require UI/app
involvement to delineate the quanta of operation to be undone.  There's
probably some application support in terms of keeping a stack of this
context, so import can push IMPORT_BEGIN, import account creation can add
ACCOUNT_CREATE, transaction creation can add TXN_CREATE, ... then the
import can pop off a coherent entity.

Perhaps it's possible to leverage the transaction log for some of that so
we're not reinventing that part.  Say, the "txn_create" undo state is just
a pointer to "the txn log" (note that it's not even an object in memory,
so there's a lot of hand-waving here).  But given the txn log doesn't
cover everything, there's still call for a app-level "undo operations

http://asynchronous.org/ | a=jsled; b=asynchronous.org; echo $a@$b

More information about the gnucash-devel mailing list