Record (row) filter

Involved development of the OpenMW construction set.
Post Reply
User avatar
Zini
Posts: 5538
Joined: 06 Aug 2011, 15:16

Record (row) filter

Post by Zini »

Finally done with the filter implementation. Meant to write about it for some time, but then stuff got in the way.

There was an attempt at filtering in the previous incarnation of the OpenCS and I hoped to re-use that, but it did not worked out. The problem there was that the author had chosen to build logical filter expression via an GUI. For a casual (non-coding) user most of this interface would have been too complicated. On the other hand a power user would certainly have started to howl in pain.

It took me some hard thinking to come up with a solution that works both for a casual user and a power user and does not require two separate interfaces.

Here is a screenshot:
Screenshot.png
Our filter system is now based on a very simple, very compact filter language (you can see an example of that in the field above the table).

We now have two filter scopes: Project and Session. Project filters will be saved by the CS internally, so they can be loaded back in again, when the user is editing the same content file again (filter saving is not implemented yet, because we don't have working saving yet). Session filters are only for sessions and are not saved.
After 1.0 we will add another scope: Content. Filters with this scope will be saved in the content file.
Each of these filters is an ID with a description and a filter string in the language mentioned above.

You can select a filter for a table by entering its name into the filter field above the fable. Later we will add drag and drop (drag a filter from the filter table to said field) and also at some point an auto-complete feature.

What you are seeing in the screenshot is actually not what I described in the paragraph above. This is a so called one-shot filter, where you enter the filter string directly into the field (one-shot filters are indicated by the ! prefix). I expect these to be particular popular with power users.

Okay, so does that help the casual user? I actually do not expect that many casual users will have to learn the filter language. First, when editing a content file for the first time, the OpenCS will add a reasonable amount of filters to the project scope (not implemented yet, because again no saving and therefore no way to determine if the file was edited for the first time). These should serve most of the basic needs.

Furthermore we will implement additional drag and drop operations with the filter field as drop destination. You could for example drag a bunch of cells from the cell table to the filter field of a references tables and the filter field would automatically generate a one-short filter, that lets through only those references that are in the listed cells.
This is also not implemented yet, because we don't have working drag and drop.


And finally, the filter language syntax (semi-formally)

A filter string is an expression.

An expression is either:

- a n-ary expression
- an unary expression
- a leaf expression


N-ary expressions:

- and (<expression>, <expression>)

That's a logical and. Note that it can have more than two expressions.

- or (<expression>, <expression>)

Same as and, but logical or.


Unary expressions:

- not <expression>

Logical not.


Leaf expressions:

- true

Always evaluates to true.

- false

Always evaluates to false

- string (columnId, match)

Evaluates to true, if the content of the specified column matches match. Matching of enum type fields and boolean fields is possible with string. Matching is done via regular expressions and non-case-sensitive (damn you Morrowind).

- value (columnId, match)

Evaluates to true, if the content of the specified column is numeric and matches match. Matching of enum type fields and boolean fields is possible with numeric values (internal enum number and 0/1 respectively).

Match can either be a number or an interval. We support the following interval types:

Closed: [1, 2] (values between 1 and 2, including 1 and 2)
Open: (1, 2) (values between 1 and 2, excluding 1 and 2)
Half-Open: (1, 2] (values between 1 and 2, including 2 but not 1)
Infinity as one or both of the limits [1, ] (values of 1 and greater)


Note:
1. ColumnIds can be either given as literal text or as the internal number (this option might be interesting for power users).
2. All keywords can be abbreviated as their first letter.
3. The entire language is not case sensitive.
Post Reply