[Evolution-hackers] Rethinking account management



As part of our transition from GConf to GSettings, which Rodrigo Moya
has graciously been helping with, I've put some thought into addressing
the XML string lists which we currently store in GConf under "accounts"
and "sources" keys.  We've known for years that this is a really bad
approach, and I don't think I have to enumerate the reasons why.

To this day many users assume they can backup or copy their Evolution
accounts by simply archiving or copying their Evolution data directory,
and no amount of repetition about the "correct" way to do it seems to
stick.  And predictably so.  Correcting people's reasonable expectation
of how something works is about as futile as getting them to say "GNU
slash Linux".  So my take on the problem is to invoke the Principle of
Least Astonishment and make account storage work the way users assume it
does.  Copying accounts from one machine to another -ought- to be as
simple as copying files in your Evolution data directory.

I propose we use key files.  Specifically a hierarchy of key file based
GSettings objects, which I'll elaborate on.  I also propose we throw out
the current EAccount and ESource classes (along with the group and list
container classes) and unify them under a common framework.  The next
release is called 3.0 so this is as good a time as any for a major API
break in libedataserver.

For lack of a better word I'm reusing the term "source" to describe the
key files, but with a slightly different definition.  A source is simply
a node in a hierarchy of sources.  A source may describe a mail account,
an address book, a calendar, a task list or memo list (or a combination
thereof), or it may simply be a stub under which other sources are
grouped.

The key files for these sources will live in two "sources" directories:
a system wide directory for built-in sources and a user directory for
custom sources.  For example:

    /usr/share/evolution-data-server-3.0/sources   # built-in sources

    $HOME/.local/share/evolution/sources           # custom sources

The user's "sources" directory will be monitored for changes, so adding
or removing a custom source will be as simple as creating or removing a
file in that directory.  Evolution will see it and respond accordingly.

In theory this should allow source creation tools such as the mail
account capplet to be written as standalone programs that don't depend
on Evolution APIs.  Such tools would just drop a properly formatted key
file in the "sources" directory, and Evolution will see the new key file
and automatically present the new source in its user interface.

I'm still designing the APIs for this, but I think I have the file
format and GSettings mappings pretty much finished so I'll just talk
about that.  More details about the API to follow.

A source's UID is the base name of its key file.  At minimum, the
content of a key file consists of a [source] group conforming to the
relocatable "org.gnome.Evolution.Source" schema, which defines the
following keys:

  org.gnome.Evolution.Source
  --------------------------
  "name"     (string,  required)  The source's UTF-8 display name.
  "parent"   (string,  optional)  The UID of the parent source, if any.
  "backend"  (string,  optional)  The backend which handles the source.

The corresponding GSettings paths would be:

  /org/gnome/evolution/sources/<<uid>>/name
  /org/gnome/evolution/sources/<<uid>>/parent
  /org/gnome/evolution/sources/<<uid>>/backend

Here's a few built-in top-level stub sources as trivial examples.  They
don't do anything other than name a backend.  They would appear as bold
group names in a source selector widget.

  1. Filename/UID: "on-this-computer"

     [source]
     name='On This Computer'
     backend='local'

  2. Filename/UID: "on-ldap-servers"

     [source]
     name='On LDAP Servers'
     backend='ldap'

  3. Filename/UID: "google"

     [source]
     name='Google'
     backend='google'

  4. Filename/UID: "caldav"

     [source]
     name='CalDAV'
     backend='caldav'

The key file format is extensible.  The file can define additional
groups, each with its own schema.  Each group is managed by a different
GSettings instance, but they share a common key file backend.

This is how a source identifies itself as a mail account, a calendar, a
task list, etc.  Plugins can even get in on the act, defining their own
group and schema for, say, per-account mail notification options (as a
hypothetical).

The built-in "system" (a.k.a. Personal) source is an interesting corner
case because it defines several different groups.  (The comments below
are just my annotations, they would not appear in the key file.)

  Filename/UID: system

  [source]                    # org.gnome.Evolution.Source
  name='Personal'
  parent='on-this-computer'
  
  [extensions/address-book]   # org.gnome.Evolution.Source.Selectable
  color='#000000'             # would not be used in the UI
  enabled=true                # would not be used in the UI

  [extensions/calendar]       # org.gnome.Evolution.Source.Selectable
  color='#becedd'
  enabled=true

  [extensions/task-list]      # org.gnome.Evolution.Source.Selectable
  color='#becedd'
  enabled=false

  [extensions/memo-list]      # org.gnome.Evolution.Source.Selectable
  color='#becedd'
  enabled=false

The corresponding GSettings paths would be:

  /org/gnome/evolution/sources/system/name
  /org/gnome/evolution/sources/system/parent
  /org/gnome/evolution/sources/system/extensions/address-book/color
  /org/gnome/evolution/sources/system/extensions/address-book/enabled
  /org/gnome/evolution/sources/system/extensions/calendar/color
  /org/gnome/evolution/sources/system/extensions/calendar/enabled
  /org/gnome/evolution/sources/system/extensions/task-list/color
  /org/gnome/evolution/sources/system/extensions/task-list/enabled
  /org/gnome/evolution/sources/system/extensions/memo-list/color
  /org/gnome/evolution/sources/system/extensions/memo-list/enabled

Hopefully now the mapping between key file groups and GSettings paths is
clear so I don't have to write that out again.  :)

So the "system" source defines a built-in address book, calendar, task
list and memo list, all named "Personal".  And notice how it doesn't
give a value for "backend".  It defers to its parent source for that
(on-this-computer -> backend='local').

For a mail account you would have a key file with a [source] group and
an [extensions/mail] group.  All the properties of our current EAccount
API would appear in the [extensions/mail] group.  In the interest of
brevity I'll skip an example of that.

Backends can also define their own groups and schemas for storing
settings that are specific to that backend.  Here's an off-the-cuff
example of what a source describing a CalDAV calendar might look like:

  [source]                    # org.gnome.Evolution.Source
  name='My Calendar'
  parent='caldav'

  [extensions/calendar]       # org.gnome.Evolution.Source.Selectable
  color='#e2f0d3'
  enabled=true

  [extensions/caldav]         # org.gnome.Evolution.Source.CalDAV
  host='my.caldav.provider'
  user='mbarnes'
  path='/dav/mbarnes/Calendar'
  ssl=true
  ...

(I'm leaning away from having URI keys, favoring instead URI components
 as separate keys from which a complete URI string can be formed.)

Here's where the hierarchy concept gets powerful.  The source structure
for a groupware account providing integrated mail, calendars, contacts
(this is Exchange, GroupWise, perhaps someday Zimbra and Kolab, etc.)
might be a top-level source with groups defining a mail account with
server info and also any calendars or address books that you get by
default on the groupware account.  Additional calendars or address books
or public mail folders for you or even other users on the server could
be implemented as child sources, such that disabling or deleting the
top-level mail account source affects the entire subtree of sources.

This is getting a little hand wavy now because I've only just figured
out the file format and groupware integration is a ways off.  But I hope
you can kinda see where I'm going with this and recognize its value over
what we have now.




[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]