<dirview root="" cur_user="michael" state="folder:+"> <folder name="folder1" label="My Folder"> <object class="document" object="ddriou2" label="A document in My Folder"/> </folder> <object class="document" object="3324ffq" label="My Document for Stuff"/> <object class="document" object="333333s" label="Another Document"/> </dirview>Let's talk a little about what I expect all that to mean. First, the elements "dirview", "folder", and "object" are pretty obvious. An "object" is a leaf in the directory tree, a document. (Of any type; classes in the wftk permission system are simply strings with no semantics at all, actually.) Folders and objects have names and labels; the name is the machine-readable identifier, while the label appears in the actual display. The "root" of the directory view is used to tell the constructor where to start the view; by default it is the current user, so that the directory displayed will be those objects owned/accessible by the current user. However, there are plenty of reasons to start directory views elsewhere, so that's what the root is for. The "state" of the directory view determines which of the folders is shown in an open state and which in a closed state. Open folders must of course be traversed. The convention I'm setting (tentatively) is pretty simple; if the state is blank, then nothing's open. If it's a "+", then everything's open. If a folder is named, that folder is open, and if two folders are open they're separated by commas. Finally, to open subfolders, I use semicolons, so if the folder named "f1" is open in main folder "f2", then my state is "f2:f1". If all subfolders of f2 where to be open, the state would be "f2:+". We'll see if that's adequate, but it feels right. All these incoming attributes of the dirview element are basically parameters to this construction function. So. All that explained, let's write some code.
See Scanning a user or group void dirview_create (XML * dv, XML * cur_user) { XML * elem; XML * direlem; dirview_scan (dv, cur_user, xml_attrval (dv, "state")); } |
dirview_scan
function will call itself
recursively if the state indicates that it should.
int folder_append (XML * view, XML * elem); void dirview_scan (XML * dv, XML * entity, const char *state) { XML * elem; XML * direlem; XML * group; elem = xml_firstelem (entity); while (elem) { if (!strcmp (elem->name, "object")) { direlem = xml_create ("object"); if (*xml_attrval (elem, "label")) { xml_set (direlem, "label", xml_attrval (elem, "label")); } else { xml_set (direlem, "label", xml_attrval (elem, "object")); } xml_append (dv, direlem); } else if (!strcmp (elem->name, "group") || !strcmp (elem->name, "group-include")) { direlem = xml_create ("folder"); xml_set (direlem, "name", xml_attrval (elem, "name")); if (*xml_attrval (elem, "label")) { xml_set (direlem, "label", xml_attrval (elem, "label")); } else { xml_set (direlem, "label", xml_attrval (elem, "name")); } if (folder_append (dv, direlem)) { group = group_get (xml_attrval (elem, "name")); dirview_scan (direlem, group, state); xml_free (group); } } elem = xml_nextelem (elem); } } |
folder_append
function, which simply wraps xml_append
with some
code to avoid duplicates and cycles in the directory tree (our "directory" structure is significantly more dangerous
than a real file structure in that regard.)
If the folder is indeed appended, the function returns 1; otherwise, the folder is freed and the function returns 0.
int folder_append (XML * view, XML * elem) { XML * check; const char * name = xml_attrval (elem, "name"); check = view; while (check) { if (!strcmp (xml_attrval (check, "name"), name)) { xml_free (elem); return (0); } check = check->parent; } check = xml_firstelem (view); while (check) { if (!strcmp (check->name, "folder")) { if (!strcmp (xml_attrval (check, "name"), name)) { xml_free (elem); return (0); } } check = xml_nextelem (check); } xml_append (view, elem); return (1); } |
This code and documentation are released under the terms of the GNU license. They are copyright (c) 2000, Vivtek. All rights reserved except those explicitly granted under the terms of the GNU license. |