[RFC] A differnt options system

Derek Atkins warlord at MIT.EDU
Wed Feb 16 18:36:48 EST 2005

Chris Shoemaker <c.shoemaker at cox.net> writes:

> Yes, it's AWFUL.  It means on page one of the dialog I have 20
> checkboxes down only the left side of the page.  The dialog is as tall
> as my screen so all the options fit.  Then on page two, I have two or
> three wide options scrunched up at the top.  Both pages look awful.
> It's an HMI disaster, and there's NO way to avoid it if you have
> different shaped widgets.  The generated gui layout is only marginally
> better than random widget placement!  How's a programmer to create a
> friendly interface with that?

The same way a programmer would have to do it with glade or any other
layout mechanism -- split the options onto separate pages..

> By pure chance, I had to take a break from coding an hour ago to do
> finances.  For my real books, I still use 1.8.9.  I was in a P&L
> report, and checking the boxes for subtotaling (which by the way are
> laid out *worse* than random, because they are misleading about which
> field go with with key) when I saw:

I think that's a labeling issue; you'd have the same issue with any
other method...

>  ** CRITICAL **: file option-util.c: line 173
> (gnc_option_set_selectable): assertion `option->odb->set_selectable !=
> NULL' failed.

Hmm, okay..  This is certainly the first I've heard of this.  And it
makes little sense to me.  The code in question is:

gnc_option_set_selectable (GNCOption *option, gboolean selectable)
  g_return_if_fail (option != NULL);
  g_return_if_fail (option->odb != NULL);
  g_return_if_fail (option->odb->set_selectable != NULL);  <--- error here

  option->odb->set_selectable (option, selectable);

> and the report behaved as if the box was checked when it wasn't.  For
> me to see strange behavior like this is not uncommon -- I do what I
> always do.  Close the options and reopen.  You'd think this would be
> an easy bug to fix.  Maybe it is, but knowing what I know, I'd guess
> it's probably not. :(  

Well, also keep in mind that there ARE a bunch of memory corruption
bugs in Gnucash.  Also note that this is a bug in _C CODE_, so it
could just as easily happen in your code as it does in the existing
code.  The devil you know vs. the devil you don't, I suppose.

> I want to help fix bugs, really.  But if people who have been hacking
> gnucash for years only understand the options system in part, what
> chance do I have after only a few months?

I know you do..  But replacing working subsystems is not necessarily a
good way to do that.  You fix bugs by fixing bugs.  Have you ever
looked at the Mozilla code base?  How do you think they would feel if
you said you wanted to wholesale replace their <insert subsystem here>

I dont know.  I rarely need to touch the code, so my knowledge of it
bitrots over time.  It's been stable; the only major issue we've had
with the code was the guile-1.6 int vs. double issue.  Between that
and adding the business options, and adding the code to save the
optiondb into the book kvp, I've not had to touch the code much at
all.  That's why I don't understand it 100% -- I haven't had to LOOK
at it in a very long time.

>> That's not quite true.  Yes, you need to define the list in the option
>> definition in scheme, but what those values mean is up to you later.
>> You could define them in one place and export to the other, or you can
>> define in two places and keep them in sync.  That's just a matter of
>> programming.  
> Exactly, so if I want to display an option with a new enumeration, I
> have to either duplicate the list or figure out how to "export" from
> one language to the other.  I hope you can see how non-trivial that is
> for people other than yourself.

Exporting from C to Scheme is absolutely trivial.
See src/engine/gw-engine-spec.scm for tons of examples.  Also see
guile-utils.c for C code to help you translate back and forth.

The code is there..  It's just not well documented.

> Well, the file you reference above contains:
> (define (gnc:account-get-type-string-plural type)
>   (assoc-ref
>    (list
>     (cons 'bank (_ "Bank"))
>     (cons 'cash (_ "Cash"))
> I suppose that's not exactly independent of xaccAccount* and
> account_type_name[] in Account.c

It mostly is, actually.  There's no order binding between them.
OTOH I'll note that even in the C code there are multiple places
where the list of accounts are enumerated in multiple forms and
need to be kept in sync, so..

> What if I don't want a notebook with a single tab?

Then fix dialog-accounts.c to hide the notebook when there's a single

> IMO, my proposal makes both adding new options and using existing
> options easier.  As for using options, look at how
> gnc-plugin-page-account-tree.c uses the options system.  Compare that
> to the equivalent functionality with the proposed api.  Conceptually,
> it's quite similar, especially w.r.t storage, but as for ease of use,
> the proposed api is much simpler.

I don't see how the new api is any simpler for a user.  Seriously, I don't.
What's so hard about using the various existing APIs:

  gnc_option_db_lookup_<foo>_option() and

You've already shown how you can create the optiondb and setup the
dialog in 6 lines of code.  If that's so much work, we can create a
helper function.

>> Why would you NOT want to store your options?  What's the point of
>> making options if you don't store them for later?
> Of course you store them.  You store them in C variables or structures
> or whatever, and eventually they may be stored in some other form.
> Maybe I wasn't clear on this point.  I'm basically referring to
> overall program preferences here.  This is perhaps where gconf could
> fit.

Except gconf doesn't seem to have a per-data-file (or even per-report)
"save" mechanism...

Also, whether you store them in C variables/structures or Scheme
variables/structures seems to be a no-op tradeoff, but not the issue
I'm referring to.

>> * shrugs * I don't really see this as a major issue, one way or the
>> other.  Whether the options are defined in scheme or C seems to be a
>> no-op tradeoff in my book.  So what if scheme is a full language and
>> guile isn't?
> Did you mean glade?  I think this is an issue only insofar as using
> scheme to do things that scheme is not well-suited for (like gui
> specification) becomes a maintenance burden and prevents the creation
> of a reasonable GUI.

Sorry, yes, I meant glade/XML.  As for "being suited", *shrugs* --
it's not like it's unsuited.  The nice thing about scheme is that we
CAN share configurations.  I see nothing inherently WRONG with using
scheme for configuration.  In fact, it would (theoretically) allow a
user to override the defaults by creating their own scheme runtime
configuration..  Overriding XML is much more problematic.

>> I think this is a BAD THING.  What's the point of making options if
>> you can't save them somewhere?
> Ok, I guess I wasn't clear about storage.  You store the option values
> by getting them from the dialog, just like things currently work on
> the C side with the existing options system.  You know,
> option_db_lookup stuff...  

I think we're talking past one another.  I honestly don't care where
the information is stored in memory; it's all about how it gets saved
and re-loaded.  Whether it's stored in a C structure or scheme
structure is irrelevant.  Storing it in a dialog isn't reasonable,
because you need to reference those options when the dialog isn't
around (c.f. reports).  Again, I think this is a no-op tradeoff, you
don't buy anything new by storing the options in C rather than Scheme.

>> The triad has the gui and storage decoupled, too.  
> You mean I can use the scheme-generated gui and have values stored with gconf?

Sure, just like you can use the scheme-generated gui and have the
values stored in a KVP_frame in the QofBook or in a scheme file.

>> This is a LOT of work for the programmer.  More so than a simple
>> scheme script to generate a bunch of options.
> Wait a sec.  Let's compare apples to apples.  I think there are
> actually two cases here.  First, there's the case where the "option
> group" has high cohesion and really should be encapsulated into a
> object so that it's behavior can live with it.  That case is analogous
> to the task of creating a new option type, which is also a lot of work
> in the current options system.

It's not really a lot of work.  It requires (at a minimum) writing one
scheme function and four C functions.  Additional functions for the C
getter/setter APIs are optional.

> Second, there's the case where the "option group" is just a loose list
> of options, like in options-utilities.scm.  In scheme this is trivial
> to specify and reuse.  WORST case with glade would be to make the
> group once and then cut-n-paste it into multiple other glade files.
> But I can think of several less-than-worst-case alternatives.  One
> such alternative is to automatically replace specially-named
> containers with other glade files, but there may be better ways.

Cut and paste == BAD BAD BAD..  If you need to make a change you now
need to make it in N places rather than just one.  See my report
options example.

> While it doesn't do everything that the options triad does (by design)
> it does do quite a bit that the option system can't do, like produce
> nicely laid-out guis, and provide a simple C api.

The triad does have a relatively simple API.  There's also a more
complicated API, too, but you can ignore that.

As for "nicely laid-out GUIs" I just don't think that's quite as
important as you're making it out to be.  We're not trying to make a
general dialog layout mechanism, here; we're making a bunch of

> But, it's important to highlight what it _doesn't_ do.  Please help me
> complete this list:
> 1) Provide scheme-side option value access 
> 2) Provide persistence for program preference option values across
> program executions

Or report option persistence.  Or the File Properties persistence.

> 3) Provide for the composition of loosely-grouped option values in a
> way that is as simple as in scheme
> what else?
> -chris


       Derek Atkins, SB '93 MIT EE, SM '95 MIT Media Laboratory
       Member, MIT Student Information Processing Board  (SIPB)
       URL: http://web.mit.edu/warlord/    PP-ASEL-IA     N1NWH
       warlord at MIT.EDU                        PGP key available

More information about the gnucash-devel mailing list