Hi Ryan, Let me just dump my thoughts on this based on my experience with g-t. It may help with your design.
In g-t, the user names a profile and can rename it later. The name can have arbitrary Unicode characters. Logically it means that the name cannot be used directly in the conf database, so g-t cleans it up. Moreover, since profile renames are supported, the conf name for a new item may already be taken. Say: - User creates profile "Remote Server", it shows up in the database as profiles/remote-server/ - Later on, use renames "Remote Server" to "Old Server". The database key remains at profiles/remote-server/ - User creates new profile called "Remote Server", the database key profiles/remote-server/ is taken, so we use profiles/remote-server-2/ It would be immensely helpful if GSettingsList can do the cleaning up and dup-avoiding part. So, add_item() will in fact get a name *hint*, clean it [1] up, avoid dup, and return the key name. Needless to say, the key name is useless for UI use, so at least in g-t we always have to have at least one non-default key in the profile which would be its name. [1] For the actual cleaning, I suggest you transcribe it to ASCII, lower-case, replace non-alnum with dashes, remove repeated dashes. Other than that, I know you already know, but is worth stressing: please avoid magic keys and values if you can :P. behdad On 05/13/2010 06:01 PM, Ryan Lortie wrote: > Hi all, > > I've been putting off GSettingsList for a while because of a criticism > that vuntz raised during the hackfest. It's a fairly valid criticism > that I'll describe here, along with my thoughts for a solution. This is > a bit of a request for comments and a hopes that the braindumping > process itself will prove to be useful. > > If you don't know, GSettingsList is a way to have a list of like-typed > GSettings instances associated with a given parent. For example, you > could store your list of gnome-terminal profiles or Telepathy accounts > using this mechanism. > > The API is something like > > > string add_item (); > void rm_item (string name); > GSettings get_item (string name); > string[] list_items (); > > If gnome-terminal had its list of profiles and had "Default" and > "bigfont" profiles, the layout in dconf would look something like this: > > /apps/g-t/stuff... > /apps/g-t/profiles/ > /apps/g-t/profiles/Default/ > /apps/g-t/profiles/bigfont/ > > also, there is a "/apps/g-t/profiles/list" key. It is a list of > strings: ['Default', 'bigfont']. > > What vuntz didn't like (and what I don't like) is that you can remove an > item from the "list" but still have garbage settings left for it in the > database. > > Going forward it makes sense (and I would like) to tie the existence of > a item of the list to the result of calling the directory enumeration > API on dconf (ie: it's impossible to have garbage, because if you have > garbage then it's not garbage, but recognised as a valid list item). > > The main issue with this is that it goes somewhat against the dynamic > creation/removing of paths that dconf follows. Consider, for example, > that we create a new profile "white" that has all the default settings > (as per the schema) to start with. This means that no key in dconf > starts with > > /apps/g-t/profiles/white/ > > which means that "white" won't show up when we enumerate > "/apps/g-t/profiles/". > > There are two main solutions here: > > 1) change how dconf works to support explicit empty directories. > There are a lot of reasons that I don't like this, and I guess I > don't need to explain them. It's also difficult to express in the > file format (but definitely not impossible). > > 2) Store some sort of "/apps/g-t/profiles/.exists" key. This is what > my current line of thinking is (and I guess many people are > familiar with this hack from some other semi-related uses). > > The idea then is that you bring a list item into existence using > ".exists" and remove it using the "reset" call that is implemented by > the backend (which is a recursive directory removal). > > ===== > > There are three main unsolved issues here, though. This system, when > compare with the old one, suffers a major feature regression: it is no > longer possible to permute the order of the items in the list. I'm not > sure if anyone cares about this. I used to think it was important, but > I'm happy to abandon/ignore it if nobody complains too loudly. > > ===== > > The second issue is how we deal with seeding the default contents of the > list. There are a few approaches that can be taken here. > > - null approach: list initially contains zero items. > > - this is very easy, but probably insufficient. > > > - better approach: list initially contains one item where the default > values of that item are taken from the schema for items (ie: the > default values of the initially-existing item are equal to the > default values that would be applied to newly created items) > > - maybe a good compromise, but vuntz says he can imagine places > where this, also, would be insufficient. > > > - full-on approach: an arbitrary number of initial items can exist, > each one with its own set of initial values. > > - quite difficult, i recon, but probably necessary. > > Option zero is trivial and insufficient. For both reasons, I don't > discuss it here. > > The other two options have a significant requirement: the ability to > remove the initial items from the list. Keeping in mind that in the > default state the dconf database is completely empty, we need to build > the list of available items by consulting both the database and the > schema. How do we store into the database a note that says we should > ignore the information in the schema? > > My main idea here is that if we have an item in the schema called > "Default" then we could write a key "/apps/g-t/profiles/.anti-Default". > This would have the effect that listing of the "Default" item based > solely on its existence in the schema would be suppressed. If the > "Default/" item appeared explicitly in the database then I imagine it > would still appear in the list (ie: in the case that we have "Default/" > and ".anti-Default" both explicitly in the database, then we ignore the > ".anti-Default" item). This furthers the "no garbage" ideal. > > This setup of having ".anti-Default" in the profile directory itself > means that we can do a single list operation against the backend to get > all the information that we need in order to tell the user about what's > there. I dislike the idea of setting ".exists" to false for this reason > but also for the reason that it allows for lingering garbage. > > ===== > > The last issue is related to lockdown. What sorts of lockdown do we > wish to support? > > (aside) A quick summary of how lockdown works in dconf: first, > dconf keys are always given with no '/' at the end, and dconf > directories are always given with a trailing '/'. > > You specify zero or more strings that start with '/' and do not > contain '//' (ie: you give keys and directories). > > For each key specified, you may not write to that key. > > For each path specified, you may not write to any key under that > path (recursively). > > I'm not particularly interested in changing this part. > > It is clear that we can prevent all changes to the list, its contents > and the contents of the items by locking down /apps/g-t/profiles/. Can > we do finer-grained locks? > > - prevent removing some of the existing profiles > - prevent adding some new profiles > - prevent modification to a specific existing profile > > and do some of these things imply others? For example, preventing > modification to a given profile probably always implies that it can't be > removed either (otherwise you could remove it, replace it, make > modifications to the replacement). > > In the case where we want to lock the user into the schema defaults for > one item but allow them to add others, we have two main possibilities > (sysadmins could pick which they prefer): > > 1) Create /apps/g-t/profiles/Defaults/.exists and lock all > of /apps/g-t/profiles/Defaults/ (ie: any user attempt to create an > anti-Default results in that being ignored by virtue of "Defaults/" > explicitly existing) > > 2) Lock /apps/g-t/profiles/.anti-Default itself in addition to locking > /apps/g-t/profiles/Default/. ie: the first one to prevent removes > and the second to prevent changes. > > I like #2 since it allows the UI to mark the "Remove" button insensitive > based on a "is writable?" query against ".anti-Default". > > But how do we prevent adding new items without locking everything down > entirely? Maybe some ".no-new-items" key in "/apps/g-t/profiles/" that > instructs GSettings to ignore any new keys that were added? The > sysadmin could create and lock this. Seems like a bit of a hack? > > What if the sysadmin wants to add some new default items that are not in > the schema and lock those into existence and prevent the addition of any > others but still allow removals or modifications? > ".only-these-new-items" with a list of strings? Does anybody actually > care about this? > > I'm OK with ignoring the lockdown issues in the first-pass at a new > implementation as long as I can feel reasonably confident that I'm not > designing myself into a corner. > > ===== > > Ok. I lied. 4 items. > > During the GSettings hackfest, the schema format underwent some > substantial simplification. It used to support subclassed schemas > (subclasses could override default values of the parent class). This > functionality was removed, but will probably need to be brought back to > support the case of multiple initial list items with different default > values (ie: one subclass per initial item). I very much wonder how that > will work... > > > > So that's it. Those are the big GSettingsList issues. > > Cheers > > _______________________________________________ > gtk-devel-list mailing list > gtk-devel-list@gnome.org > http://mail.gnome.org/mailman/listinfo/gtk-devel-list > _______________________________________________ gtk-devel-list mailing list gtk-devel-list@gnome.org http://mail.gnome.org/mailman/listinfo/gtk-devel-list