newdocms - Technical information

Written by Manuel Arriaga.

This document is targeted at those who are interested in participating in the development of newdocms.

If you feel that something is missing, please let me know. (Email address at the bottom of the page.)

Overview:

newdocms works by storing a set of attributes -- as (attribute name, attribute value) pairs -- for each document in a database file. That file (~/newdocms.db) holds all the metadata. The documents themselves (the data), however, are kept in normal files outside of the database file. newdocms knows the path of the file in which each document described in the database resides, and thus is able to return the path of the documents which match a given metadata query. Similarly, when saving a document newdocms stores its attributes in the database file and then returns to the calling application the path at which the document contents should be stored.

By intercepting the usual "Open" and "Save as" dialogs which the applications pop up when they need to obtain a file path from the user newdocms allows the user to manage her documents based on the metadata stored in the database file, but when the time comes for the calling application to read/save the data itself the path to a file is always returned. newdocms acts as a "bridge" between data and metadata.

Each document is identified by its docID (a unique integer). Attributes are associated to each docID in the database, and then that docID is associated to a certain file path at which the document is actually stored.

The document attributes the system stores can be of two types:

Concept attributes take as their value a concept: eg, a document "about dogs" would be be described by the (attribute name, attribute value) pair ("about", &"dogs"), where &"dogs" represents a pointer to the concept "dogs" (it is important to understand that a concept is not merely a string!). A text attribute, on the other hand, might look like ("comment", "This document was first received on the 21st of June."), where this time the value is simply a text string.

There are quite a few functions in libnewdocms that don't deal directly with document storage and retrieval. The concept/text distinction and the organization of concepts in a "category tree" account for a good part of them.

With that out of the way, the functions which form the libnewdocms API can be divided into the following groups:

Whenever a function "does something" (other than returning a value) and has a bool return value it returns true if it was successful and false otherwise.

There are also some custom types.

The file which holds all the metadata is in SQLite format, and a text file describing the table layout is available here.


Constructor, destructor and test function:

DB(QString dbPath = QString::null, QString docDir = QString::null, QString mailDir = QString::null, QString viewDir = QString::null);

The constructor can be passed four arguments, each of them providing a path. If any of them isn't present or is an empty string then the default compile-time values will be used. If an argument is a relative path then the home dir path will be prepended to it (eg, "newdocms.db" becomes "/home/joe/newdocms.db"). dbPath is the path to the database file, docDir is the path to the document repository and viewDir is the path of the directory under which user-friendly file paths (symlinks) are created. Currently mailDir is ignored as support for email hasn't been implemented yet.

~DB(void);

bool ok(void);

This function should be called by the interface once the DB object has been instantiated and the interface is listening to the dbSorry() and dbError() signals. Only through this ugly hack is it possible for the constructor to communicate any problems, since before the constructor returns the interface can't QObject::connect() to it to listen for any signals... The object doesn't exist yet at that time! :-) Returns true if the object was constructed, false if an error occurred.


Category tree:

The category tree is the only (slightly) complicated part of libnewdocms. The idea behind it is that we allow the user to create a hierarchical structure in which concepts can be organized in a meaningful way. Each element in that hierarchy is called a "category". Four useful things to keep in mind about categories and concepts are:

  1. Categories usually point to a concept, but they don't have to. In the latter case they are called "conceptless" or "null" categories and their only purpose is to make grouping concepts by different criteria (ie, to create different "views") easier.
  2. Multiple categories can point to the same concept. (Or, to put it in another way, the same concept can be placed at multiple points of the hierarchy.) This allows the user to deal with the fact that each concept has got several "identities"/ exists in multiple dimensions. Eg, "Joe" can simultaneously be "People->Friends->Joe" as well as "People->Colleagues->Joe"; (most) newspapers not only "Organizations->Media" but also "Organizations->Corporations"; etc...
  3. Each concept must always be represented by at least one category, otherwise that concept would be inaccessible.
  4. When querying, selecting a category as the value of a concept attribute means "matching documents will have this attribute set either to the concept behind this category or to any of the concepts behind its subcategories". On the other hand, when cataloguing (saving) a document selecting a category as the value of a concept attribute specifies that the value of that attribute is precisely the concept behind that category. For that reason, when querying you can select conceptless categories (because their subcategories point to useful concepts) but while saving you can't (because they lack a concept themselves).
It would be desirable (I think) if we could define a single widget to be used in the manipulation of the category tree; you can find my attempt at that in the CategoryViewer class in newdocms-0.1/libnewdocms/libnewdocmskdegui/category_viewer.cpp. For an example of how to use these functions please take a look at that code.

QValueList<CategoryInfo> getCategoryTree(void);

This function returns a list of CategoryInfo structures describing the currently visible category tree.

QStringList getAllTerms(void);

This function returns a list of all currently visible terms stored in the database. A "term" is the name we use whenever we refer to a concept; in practical terms it is the last component of a category's name (eg, the term of the concept behind the category "Animals->Dogs" is "dogs", because that's how we refer to the concept of "dogs"). The last component of the name of a conceptless category isn't a "term", because it doesn't refer to any concept! Of course, the same term can refer to several concepts (eg, "Ford" can be someone's name as well as the car manufacturer). This function is useful for keyboard-based concept specification: when a user is asked to type a "concept" he actually types that concept's term, and it is by comparing that input against the list of terms returned by this function that we check whether we know the concept to which the user is referring.

QStringList getAllCategories(void);

This function returns a list holding the names of all currently visible categories.

QStringList getOtherCategoriesWithSameConceptAs(QString categoryName);

This function returns a list of other categories which point to the same concept as its argument. categoryName must refer to a category with a non-null concept.

QStringList getRepresentativeCategoriesWithTerm(QString term);

This function returns a list of representative categories -- ie, one category per concept -- which end in its argument. This is useful for keyboard-based concept specification: when the user provides you with a term, you need to know to which of several concepts concepts called by that term she is referring to. You do so by presenting to the user the list returned by this function and asking the user to choose the category which points to the concept she had in mind. (Another possibility being that the user wishes to define a new concept which is called by that term.)

QStringList getChildrenCategoriesOf(QString categoryName);

This function returns a list of visible children categories (at all levels: children, grandchildren, etc) given a certain category name.

bool hasNullConcept(QString categoryName);

This function returns true if categoryName is a null concept category.

bool addCategory(QStringList parentCategoryNames, QString categoryLastName, bool privateCategory, ConceptOrigin origin, QString categoryPointingToConcept, bool inheritChildren);

This function adds one or more categories to the category tree. Each of these will have as the last component of their name categoryLastName. A new category (with that name) will be created beneath each of the categories named in parentCategoriesNames. An empty string as the name of a parent category is interpreted as referring to the top of the category tree, and therefore results in the creation of a new top-level category. privateCategory specifies if the new categories will be marked as private. origin determines which kind of concept these new categories will be bound to: (i) a new concept (not previously present in the category tree), (ii) an existing concept or (iii) the null concept. If the user goes with (i) origin should be set to newConcept; if she chooses (ii) you should set origin to reuseConcept and then allow her to choose an existing category which indicates to which concept the new categories should point; finally, if she chooses (iii) origin should be set to nullConcept. In case (ii) you should then pass the relevant category name as categoryPointingToNewConcept, and indicate whether the children categories of that category (if any) should be reproduced beneath each of the new categories which "inherited" their concept from categoryPointingToNewConcept. The two last arguments are ignored if origin isn't set to reuseConcept.

QString askRemoveCategory(QStringList categoryNames);

Removing a category can have a serious impact in the user's metadata. categoryNames holds the names of the categories to be removed; the children of those categories are always removed, so you shouldn't include them in that list. If a category and/or its subcategories contain the only references to one or more concepts in the entire category tree then removing them will result in the loss of those concepts. (Otherwise the concepts would become inaccessible, and that's something we can't allow.) If a concept is removed from the system then all document attributes which refer to it are also deleted, so real metadata loss might occurr. Additionaly, and as mentioned above, whenever a category is removed all its subcategories go with it. For these two reasons, before calling removeCategory() you should call this function and -- if it returns a non-empty string -- present the question it returns to the user. That string lists the subcategories which would disappear and, most importantly, any concepts which might be removed from the database if removeCategory() is indeed called. Only if the user answers "Yes"/"Proceed" should removeCategory() be called. Note: this function will not inform the user about the removal of concepts/categories which are currently invisible.

bool removeCategory(QStringList categoryNames, bool externalUse = true);

This function effectively removes one or more categories from the category tree (together with their children), and if concepts are lost in that operation purges all document metadata from references to them. External code should leave the last argument set to true.

QString askRemoveConcept(QString categoryPointingToOldConcept);

Just as you should call askRemoveCategory() before calling removeCategory(), you should also call askRemoveConcept() before calling removeConceptAndReassociateDocs().Note: this function will not inform the user about the removal of concepts/categories which are currently invisible.

bool removeConceptAndReassociateDocs(QString categoryPointingToOldConcept, QString categoryPointingToNewConcept);

This function replaces all references to a certain concept in the collection of document metadata with references to a different concept, and removes all categories which refer to the former concept from the category tree (as always, together with any children they might have). Because other concepts might be lost in this operation (as "collateral damages" resulting from the removal of subcategories) and that would lead to the loss of document metadata, askRemoveConcept() should be called before you call this function. (Eg: After the merger of HP and Compaq, it can be argued that it no longer makes sense to have a concept called "Compaq". However, simply removing that concept from the DB would lead to metadata loss (documents catalogued as relating to "Compaq" would see that attribute disappear), and you would have to manually recatalogue all of them as "relating to HP". This function allows the user to say "Compaq no longer exists, but past references to it should from now on be interpreted as referring to HP". In addition to that, any references to the concept "Compaq" would be removed from the category tree.)

bool moveCategoryAndChildren(QString oldCategoryName, QString newCategoryName, bool externalUse = true);

This function allows you to move a category (together with all its children) from one point of the category tree to another. newCategoryName must be the concatenation of "parentCategory + categorySeparator + newLastName", where (i) parentCategory exists and (ii) currently no category with that exact name (parentCategory + categorySeparator + newLastName) exists. The operation will fail if oldCategoryName is a parent of newCategoryName: eg, you can't move "A->B" to "A->B->C" (what would be the parent of "A->B" after the operation?). If the parent of newCategoryName is flagged as private then the new category will also be marked as private; otherwise the private flag of oldCategoryName (and its children) is preserved. External code should leave the last argument set to true when calling this function.

bool bindCategoryToConcept(QStringList categoryNames, QString categoryPointingToNewConcept, bool inheritChildren, bool makeCategoryPrivate);

Because categories are simply "pointers" to concepts, they can be set to point to a concept different from the one to which they originally pointed. By calling this function you set the categories named in categoryNames to point to the concept referred to by categoryPointingToNewConcept. If the latter is an empty string then those categories are set to the null concept and thus become conceptless categories. If categoryPointingToNewConcept is non-empty and that category has got any children setting inheritChildren to true will result in the reproduction of that category's children beneath each of the rebound categories. Finally, setting makeCategoryPrivate to true will flag the categories named in the first argument as private; otherwise their private flag will remain unchanged. Note: including all categories which point to a given concept in categoryNames will result in the loss of that concept (and, therefore, metadata loss), so the interface should check whether that is the case and, in those situations, warn the user about what that implies. (XXX: This should be done by a askBindCategory() function similar to the other two askRemove...() functions. The current interface can easily check this because of the way in which the user is allowed to choose the categories that go into categoryNames, but not all interfaces will necessarily behave in a similar way.)

bool renameCategoryAndChildren(QStringList oldCategoryNames, QString newLastName, bool externalUse = true);

This function simply changes the last name of an existing category: eg, "A->B" will become "A->C". newLastName mustn't contain the categorySeparator, and external code should leave the last argument set to true.

bool copyChildrenOf(QString originalParentCategory, QStringList newParentCategories, bool externalUse = true);

This function copies the children (at all levels: children, grandchildren, etc...) of originalParentCategory to the categories named in newParentCategories. The value of their private flags is preserved, and external code should leave the last argument set to true.

bool hideCategoryAndChildren(QStringList categoryNames);

bool unhideCategoryAndChildren(QStringList categoryNames);

These two functions toggle the private flag of a list of categories and all their children.


Attribute list:

newdocms maintains a list of which attributes can be used to describe documents. As mentioned above, these can be of two types (concept or text). The functions in this section allow the user to introduce changes to that list of attributes.

bool addAttribute(QString attributeName, AttributeType type);

This function defines a new attribute of type (Concept or Text).

bool removeAttribute(QString attributeName);

This function removes an attribute from the list of available attributes. Because that attribute ceases to exist, this function leads to metadata loss: all documents for which this attribute had been defined will lose metadata

bool renameAttribute(QString oldAttributeName, QString newAttributeName);

This function changes the name of an existing attribute.

QStringList getAttributesOfType(AttributeType attributeType);

This function returns a list of all attributes of the specified type. You should use it when asking the user which concept or text attribute she wishes to set.


Visibility control:

newdocms is a single-user system, but its design tries to take into consideration the fact that that user might not always be alone... For that reason, the user can mark documents, templates and categories as private, and as a result they will only be visible through the interface if newdocms is operating in "showEverything" mode. The functions in this section allow the user to set/get the visibility level.

bool showEverything(void);

bool dontShowEverything(void);

bool everythingIsVisible(void);


Format-type map:

newdocms allows the user to define "types" of documents. Those would be generic groups of file formats such as "text documents" (*.txt, *.kwd, *.doc, etc...), "images" (*.jpg, *.png, *.gif, etc...), etc... Although this mapping is not always easy to do (eg, is a document stored in a Postscript file a "slide" or a "text document"?), it is intended to allow the user to narrow down the scope of queries run from a (future) newdocms browser, which doesn't impose any file format limitations on the queries it runs.

QStringList getAllDocTypes(void);

This function returns a list of all currently listed document types.

QString getTypeOfFormat(QString format);

This function returns a string holding the document type associated to a given file format. If no such format is found then an empty string is returned. format should be the name of a valid MIME type.

QStringList getFormatsOfType(QString type);

This function returns a list of all MIME types which are associated with a certain type.

bool setTypeOfFormat(QString format, QString type);

This function sets the document type of a file format. If it is called with an empty "type" string then any previous association of that format to a type will be undone. format should be the name of a valid MIME type.

QStringList getAllUntypedFormats(void);

This function returns a list of all currently used formats whose type newdocms ignores. This is useful so that the interface can offer to the user a list of all formats for which she might wish to define a type.


Document management:

The functions in this section handle the fundamental issues regarding the storage of documents in newdocms.

QString insertDocIntoDB(QString fileFormat, QString shortcut, QValueList<AttributeValuePair> properties, QValueList<DocCommentsTriplet> relatedDocs, QString appName, bool makePrivate);

This is the "standard" way to register a document's metadata in newdocms. fileFormat can be either a MIME type or a pattern (or a string holding several MIME types or patterns, in which case only the first one will be taken into consideration). It mustn't contain a generic ("all/all" or "*.*") filter, otherwise newdocms won't be able to determine the format in which the file will be saved (for this reason the interface should never offer the user the possibility to choose such a generic filter when saving). The shortcut (optional) is a simple text string provided by the user which acts as a key to quickly retrieve this document in the future. properties holds this document's attributes, and relatedDocs the relationships between this document and others already stored in the database. appName is the name of the calling application. This is used to keep track of the file formats in which this application has saved documents, so that if it claims to be able to open any file format we can suggest a sensible filter to the user. Finally, makePrivate signals whether this document should be marked as private.

This function returns the path to which the calling application should save the document or an empty string in case of error.

QString insertDocIntoDB(QString collectionName, QString fileFormat, QString fileName, QString appName);

This function allows you to register a document as an element of an existing collection. You must provide a fileFormat (same rules as stated above), a fileName (without an extension) and the name of the calling application.

This function returns the path to which the calling application should save the document or an empty string in case of error.

bool eraseDoc(QString docid);

This function permanently removes (unlike deleteDoc(), which simply flags a document as "deleted") all references to a document from the database and deletes the file in which the doc resides. I would suggest that the interface shouldn't provide an easy way to run it, but then I have always been afraid of permanently deleting files... :-)

bool deleteDoc(QString docID);

This function marks a doc as deleted. This document will no longer show up in query results, but neither its contents nor its database record will be erased. It will still be possible to access it through the list of deleted docs (getDeletedDocsList()). To actually delete a document and remove its record from the database eraseDoc() should be used.

bool undeleteDoc(QString docID);

This function "undeletes" a doc. The trick lies in the fact that this doc was never actually deleted, and its database record was preserved. After calling this function the document will once again show up in the results list of any query it matches. Note: this does NOT work with docs which have been really destroyed through eraseDoc(); it will only work with docs which have been "deleted" through deleteDoc().

QString makeFriendlyPath(QString docID);

This function generates a displayable, user friendly path for a given document. That path is the name of a symlink beneath viewDir which points to the real document, and it is formed by the concatenation of the last names of categories representative of the concepts to which a document is associated. If this document isn't associated to any concept then a path ending in "(uncatalogued)" is returned. In case of error an empty string is returned. Example of a "friendlyPath": "/home/jane/View/holidays-beach-2002.jpg".


Document attributes:

Document metadata is handled by the three functions in this section.

bool addAttributeToDoc(QString docID, QString attributeName, QString value, bool externalUse = true);

This function defines a new attribute of the document identified by docID. The attribute which is set is specified by the second argument, and the value to which it is set is given by the third argument. If attributeName is the name of a concept attribute then value is interpreted as the name of a category pointing to the concept to which the attribute will effectively be set. If the same attribute has already been set for that document (to some other value) then it is defined again (ie, the previous definition is not lost, a document can be "about dogs" and "about cats" at the same time). If that attribute was already set to the same value then dbSorry() is emitted and the function fails. The interface should leave the last argument set to true when calling this function.

This function returns true in case of success, false otherwise.

bool setAttributeOfDoc(QString docID, QString attributeName, QString newValue, QString oldValue);

This function redefines an attribute of a given doc, setting it to newValue where it had been previous set to oldValue.

This function returns true in case of success, false otherwise.

bool removeAttributeOfDoc(QString docID, QString attributeName, QString value = QString::null);

This function removes the definition(s) of an attribute of a given doc. If a value is specified (ie, value isn't an empty string) then only the definition of attributeName to value will be eliminated; otherwise all definitions of attributeName for this doc will we lost.

This function returns true in case of success, false otherwise.


Document relationships:

Document relationships are links between pairs of documents: they allow you to navigate your document collection in an alternative way, "jumping" from one document to another. Each link is is defined by a pair of documents together with a pair of comments (optional). The latter are meant to make the relationship between the two documents clear to the user, and which one should be shown depends on the direction in which the user is "moving": eg, if document 2 was sent as a reply to document 1, then the comment from 1 to 2 might be "This is a link to the reply I sent." while the comment from 2 to 1 would be "This is a link to the document to which I am replying.".

bool addRelationshipBetweenDocs(QString docID1, QString docID2, QString commentFrom1To2, QString commentFrom2To1, bool externalUse = true);

This function defines a relationship between the documents identified in the first two arguments. You can optionally provide two comments which will describe this relationship in both directions (From1To2 and From2To1). If you don't want to use this feature pass empty strings as comments. The interface should leave the last argument set to true.

bool modifyRelationshipBetweenDocs(QString docID1, QString docID2, QString newCommentFrom1To2, QString newCommentFrom2To1);

This function modifies the comments pertaining to a relationship between to documents. Note: if any of its two last arguments is an empty string then that comment will be cleared. If you wish to leave one of the two current comments unchanged you must pass it back to this function as you would do with a new comment.

bool deleteRelationshipBetweenDocs(QString docID1, QString docID2);

This function removes a relationship between two documents from the database.


Other document properties:

The functions in this section handle other document properties such as document shortcuts, timestamps and their private flag.

QStringList getAllShortcuts(void);

This function returns a list of all currently defined shortcuts. It might be helpful to allow the user to somehow access this list when she is trying to retrieve a document by its shortcut.

bool setShortcutOfDoc(QString docID, QString newShortcut);

This function sets the shortcut associated with a given document. newShortcut might be an empty string, in which case the shortcut for this doc will be unset.

bool updateTimeStampOfDoc(QString docID);

This function updates the access_date and access_time fields of a document.

bool hideDoc(QString docID);

bool unhideDoc(QString docID);

These functions toggle the private flag of a document. If a document is marked as private and shouldShowEverything is set to false then that document will show up neither in the query results nor in the relationships list of other documents.


Document retrieval:

This section contains the functions which can be used to query the metadata database.

QValueList<DocInfo> getMatchingDocsList(QValueList<AttributeValuePair> properties, QStringList acceptableFormatsOrTypes, bool secondArgListsTypes = false);

This function returns a list of DocInfo structures describing the documents which match the conditions defined by the arguments it takes. An empty acceptableFormatsOrTypes list is equivalent to one containing a string with a single "all/all", "*.*" or "*", all of them meaning that any format is acceptable. formats can be expressed both as MIME types as well as as extensions/patterns. If secondArgListsTypes is set to true then the second argument will be read as a list of types (as defined by setTypeOfFormat()). If an AttributeValuePair in the first argument has its AttributeValuePair.attribute member set to an empty string then that is interpreted as meaning "matching documents must have at least one concept attribute (any) set to the category named in the AttributeValuePair.value member", ie, "matching documents must somehow be related with the concept identified by the category in the AttributeValuePair.value member". (I think this can be very helpful when one wishes to increase the scope of a query: eg, "I don't simply want documents about dogs, but all documents related to dogs in any way!".)

QValueList<DocInfo> getMatchingDocsList(QString shortcut, QStringList acceptableFormatsOrTypes, bool secondArgListsTypes = false);

This function returns a list of DocInfo structures describing the documents which have a shortcut equal to its first argument. (The search is case-sensitive.) The last two arguments must obey the same rules as stated above.

QValueList<DocInfo> getUncataloguedDocsList(QStringList acceptableFormatsOrTypes, bool argListsTypes = false);

This function returns a list of DocInfo structures describing the documents for which no concept attributes are currently defined. The last two arguments must obey the same rules as stated above.

QValueList<DocInfo> getDeletedDocsList(void);

This function returns a list of DocInfo structures describing the documents which are flagged as "deleted". The user might wish to see this list for the same reasons as she would look into a normal system's trash can.


Collections:

newdocms allows users to store multiple files as a single "document" in a "collection". The two main ideas behind this are that (i) many files can share the same attributes, and grouping them together would make their characterization much less time-consuming (eg, think of digital photo albums) and (ii) some documents are really formed by several files (eg, a text and two illustrations). The functions in this section allow the user to create and manipulate collections. Note: you should think of a collection as a document, and collections are removed just like normal documents.

Collections are stored on disk as normal directories, but newdocms keeps track of the formats in which the files they hold are stored so that it knows whether to list them in the query results (given the filter which has been specified). Currently trying to insert a file into a collection when it already contains a same-named file will result in an error; furthermore, currently it isn't even possible to obtain a list of the names of the files inside a collection, so the user must keep making up new file names until no name collision occurs... :-)

bool addCollection(QString collectionName, QValueList<AttributeValuePair> properties, QValueList<DocCommentsTriplet> relatedDocs, QString shortcut, bool makePrivate);

This function creates a new collection. As in the case of insertDocIntoDB(), the arguments properties, relatedDocs and shortcut are optional.

QStringList getCollectionsList(void);

This function lists all currently visible collections. (Because they are just like "real", stand-alone documents, collections also have a private flag.)

bool insertFilesIntoCollection(QStringList paths, QString collectionName);

This function inserts a set of existing files into a collection. The original files are left untouched, but they are copied into the directory in which this collection lives.

bool removeFileFromCollection(QString collectionName, QString fileName);

This function removes a file from a collection given its filename.

bool renameFileInCollection(QString collectionName, QString oldFileName, QString newBaseName);

This function renames a file in a collection. The oldFileName must include the extension; the newBaseName mustn't.


Other functions:

QStringList getFiltersOfApp(QString appName);

This function returns a list of filters which are currently associated with the application named in its argument. It is the interface's job to -- if confronted with an empty/"all" filter -- determine the app name and invoke this function.

void stopDBAccessSlot(void);

This function (it is also a Qt slot) halts access to the SQLite database. It might be useful when the interface allows the user to see the matching documents list in "real time" (ie, the list would be continuously updated as the user gradually defines more attributes): whenever a new attribute was defined the interface would call stopDBAccessSlot() and run a new query.

void dbSorry(QString msg);

This signal is emitted when a problem generated by "wrong" user input occurs. The interface should connect this signal to a slot which displays this message to the user and continue operating normally.

void dbError(QString msg);

This signal is emitted when an internal error occurs. The interface should connect this signal to a slot which displays this message to the user and either halt its operation or try to resort to a traditional "Open"/"Save as" dialog.

void categoryTreeChanged(void);

void attributesChanged(void);

void collectionsChanged(void);

These signals are emitted when the category tree, list of attributes or list of collections change, respectively.


Types:

The newdocms header file defines some structures and one enum type. These are:

enum ConceptOrigin {newConcept=0,reuseConcept=1,nullConcept=2};

This enum is used as one of the arguments taken by addCategory().

struct AttributeValuePair { QString attribute; QString value; } ;

This structure is used to store (attribute name, attribute value) pairs. If AttributeValuePair.attribute is the name of a concept attribute, then AttributeValuePair.value is expected to be the name of a category (pointing to a non-null concept). If AttributeValuePair.attribute is the name of a text attribute, then AttributeValuePair.value is simply treated as a string.

struct TimeStamp { QDate date; QTime time; };

(This doesn't really require any explanation.)

struct DocCommentPair { QString otherDoc; QString commentToOtherDoc; } ;

This structure is used inside the DocInfo structure to describe the relationship between two documents. Given that it is only used in that context, DocCommentPair.commentToOtherDoc contains the comment from the document to which that DocInfo pertains to the document identified by the docID stored in DocCommentPair.otherDoc.

struct DocCommentsTriplet { QString otherDoc; QString commentToOtherDoc; QString commentFromOtherDoc; } ;

This structure is used when storing the metadata of a new document in the database and a link from that document to another one needs to be established. Again, the missing docID is the one pertaining to the document being inserted.

struct CategoryInfo { QString name; bool hasConcept; bool isPrivate; } ;

This structure holds the properties of an item in the category tree (a category :-)). hasConcept is false for conceptless categories, true otherwise.

struct DocInfo { QString docID; QString fileFormat; QValueList<AttributeValuePair> properties; QValueList<DocCommentPair> relatedDocs; QDate creationDate; QTime creationTime; QDate lastAccessDate; QTime lastAccessTime; bool isPrivate; QString filePath; bool isCollection; QString collectionName; } ;

This structure holds all the information recorded in newdocms about a given document. If isCollection is true this DocInfo describes a collection and fileFormat is for that reason irrelevant, while collectionName holds the collection's name; if isCollection is false then fileFormat is relevant (it is expressed as a MIME type), and you shouldn't care about the contents of collectionName.


Manuel Arriaga - Email me at marriaga followed by @ stern . nyu . edu