PIKApp/devel-docs/tagging.txt

149 lines
6.1 KiB
Plaintext

=============================================================
How does resource tagging in Pika work?
=============================================================
PikaTagged
Tagging is not limited to a concrete class hierarchy, but any class
implementing the PikaTagged interface can be tagged. In addition to
methods for adding/removing/enumerating tags it also requires
PikaTagged objects to identify themselves:
* pika_tagged_get_identifier: used to get a unique identifier of a
PikaTagged object. For objects which are stored in a file it will
usually be a filename.
* pika_tagged_get_checksum: the identifier mentioned above has the problem
that it can change during sessions (for example, user moves or renames
a resource file). Therefore, there needs to be a way to get another
identifier from the data of the tagged object, so that tags stored between
session can be remapped properly.
PikaTag
Tags are represented by a PikaTag object. There are no limitations for
tag names except that they cannot contain a selected set of terminal
punctuation characters (used to separate tags), leading or trailing
whitespace and cannot begin with a reserved prefix for internal tags
('pika:'). These conditions are enforced when creating a tag object from a
tag string. The only reason for tag creation to fail is if there are
no characters left after trying to fix a tag according to the
rules above. Tag names are displayed as the user typed them (case
sensitive), but tag comparison is done case-insensitively.
Tags are immutable, i.e. when a tag is created with one name string, it
cannot be changed, but a new tag has to be created instead.
There are methods provided for convenient use with glib, a comparison
function which can be used to sort tag lists and functions for storing
tags in a GHashTable.
PikaTagCache
Between sessions, tags assigned to objects are stored in a cache
file. The cache file is a simple XML file, which lists all resources and
tags which are added to them. Resources which have no tags assigned
are listed here too, so that when we check the cache we know that they
have no tags assigned instead of trying to find out if the resource file
has been renamed.
When the session ends, a list of all resources and their tags
is constructed. Resources which were not loaded during this session,
but had tags assigned are also added to the list (they are saved
because they could be useful in the next session, for example, when
a temporarily disconnected network directory is reconnected). The list
is then written to a tag cache file in the user's home directory.
When the session starts, the previously saved resource and tag mapping has to
be loaded and assigned to PikaTagged objects. First the tag cache is
loaded from file, and then containers are added (PikaContainer objects
which contain items implementing the PikaTagged interface). After that,
loaded resources are assigned tags:
If a resource identifier matches an identifier in the cache,
corresponding tags are assigned to the PikaTagged object.
Else, if the identifier is not found in the tag cache,
an attempt is made to check if the resource file has been
moved/renamed. In such case the checksum is used to match the
PikaTagged object with all of the records in the tag cache.
If a match is found,
the identifier is updated in the tag cache.
Otherwise,
the loaded PikaTagged object is considered to be a newly
added resource.
PikaFilteredContainer
A PikaFilteredContainer is a "view" (representation) of a
PikaContainer. It is related to tagging in that it can be used to
filter a PikaContainer to contain only PikaTagged objects which have
certain tags assigned. It is automatically updated with any changes in
the PikaContainer it wraps. However, items should not be added or removed
from this container manually as changes do not affect the original
container and would be lost when the PikaFilteredContainer is
updated. Instead, the contents should be changed by setting a tag list
which would be used to filter PikaTagged objects containing all of the
given PikaTags.
PikaFilteredContainer can use any PikaContainer as a source
container. Therefore, it is possible to use the decorator design pattern
to implement additional container views, such as a view combining items
from multiple containers.
PikaTagEntry widget
The PikaTagEntry widget extends GtkEntry and is used to either assign or
query tags depending on the selected mode. The widget support various
usability features:
* Jellybeans: When a tag is entered and confirmed by either separator,
pressing return or otherwise, it becomes a jellybean, i.e. a single
unit, not a bunch of characters. Navigating in a PikaTagEntry,
deleting tags, etc. can be performed much faster. However, while a tag
is just being entered (not yet confirmed), all actions operate on
characters as usual.
* Custom auto completion is implemented in the PikaTagEntry widget which
allows to complete tags in the middle of a tag list, doesn't offer
already completed tags, tab cycles all possible completions, etc.
* If the PikaTagEntry is empty and unused it displays a description for
the user regarding its purpose.
When operating in tag assignment mode, tags are assigned only when
the user hits the return key.
When operating in tag query mode, the given PikaFilteredContainer is
filtered as the user types. The PikaTagEntry also remembers recently used
configurations, which can be cycled using up and down arrow keys.
PikaComboTagEntry widget
The PikaComboTagEntry widget extends PikaTagEntry and adds the ability to pick
tags from a menu-like list (using the PikaTagPopup widget).
PikaTagPopup widget
The PikaTagPopup widget is used as a tag list menu from the PikaComboTagEntry
widget. It is not designed to be used with any other widget.
PikaTagPopup has many visual and behavioral similarities to GtkMenu.
In particular, it uses menu-like scrolling.
PikaTagPopup implements various usability features, some of which are:
* Tags which would result in an empty selection of resources are made
insensitive.
* Closing either with the keyboard or by clicking outside the popup area.
* Underlining of highlighted (hovered) tags.