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
- text attributes
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:
- Constructor, destructor and test function.
- Category tree: these functions are used to
manipulate and access the category tree.
- Attribute list: these functions are used to manage the
list of concept and text attributes which the user can define when
cataloguing a document.
- Visibility control: these functions control whether
documents, categories and templates which are marked as private should be visible.
- Format-type map: these functions allow you to control/access
the format-type map.
- Document management: these functions are
used to insert, mark as deleted and remove documents.
- Document attributes: these functions are
used to add, remove or modify document attributes.
- Document relationships: these functions are
used to add, remove or modify links between documents.
- Other document properties: these functions are
used to set/get other document properties such as their shortcuts, timestamp
and private flag.
- Document retrieval: these functions are
used to query the database and obtain lists of matching documents.
- Collections: these functions are
used to create/list collections and to manipulate files already stored inside
them.
- Other functions.
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.
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.
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:
- 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.
- 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...
- Each concept must always be represented by at least one category,
otherwise that concept would be inaccessible.
- 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.
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.
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);
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.
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 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 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.
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.
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.
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.
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.
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