User Tools

Site Tools


Pracro - Praxis Macro system

New concepts

Upgrade from old to new database structure

Remove duplicate entries from fieldnames table:

delete from fieldnames where ctid not in (select max(dup.ctid) from fieldnames as dup group by;

Remove duplicates from fields:

delete from fields where ctid not in (select max(dup.ctid) from fields as dup group by dup.transaction,, dup.value);
ALTER TABLE transactions RENAME TO transactions_old;
CREATE TYPE session_status AS ENUM ('active', 'idle', 'committed');


See the roadmap page for details on how and when releases are made.


See the widgets page for design details on new widgets.


See the database page for database layout notes.

Random Stuff

Open/Close logic


  • Only one open macro at any point of time.
  • Not possible to close an unchanged macro by saving it.
  • Warn the user if an unsaved macro is about to be collapsed.

When clicking on the expand/collapse button (the one with the ± on it) or on the title/line on top of the macro resume, the macro will be expanded.
Initially the 'Commit' button will be disabled, and stay that way until the user changes something in the macro. The only exception to this is if the macro is loaded, prefilled with commit-able data, ie. data from Pentominos or other external sources, that simply needs to be committed to the database without further actions of the user.
When the commit button (or optionally abort button) is clicked, the macro will be collapsed, and its data either committed to the server, or thrown away.
If the expand/collapse button, or the title/line on the top of the macro is clicked, the macro will enter an 'about to collapse' mode:
If the macro contains no changes, it will simply be collapsed.
If the macro contains unsaved data, the user will be prompted to save these data and collapse, ignore the changes and collapse or stay open and do nothing.
If another macro is already open when the expansion is about to be initiated, the already open macro will enter 'about to collapse' mode. If the stay open option is selected, the new about to expand macro will stay collapsed.


There are two types in the pracro database.
A simple type, which is simply a text string, and a complex type, which is a compound string containing nested key/value pairs encapsulated in ${key|value} blocks.
The type is used when it is about to be inserted into a resume. If it is a simple type it is copied verbatim into the the resume. If it is

Resume text

If the resume text is stored with each transaction, the resume can be recreated at any point in time without consulting the XML files. Furthermore the recreated resume text can highlight all fields, thereby pointing out that they are values and not just surrounding text.

How to handle editing of prefilled macros

If a macro has already been committed t the journal and is opened for editing in the editor, is it then correct to assume that the user is about to correct a mistake made in the previous transaction? and if so, does it make sence to ask the user to fill in a reason for the editing, for later prepend at commit time?

A macro is already filled out.
A user clicks the open-for-edit button.
A pop-up box declares that “You are about to fix an error. Please specify your reason for this.”
The user fills in the lineedit, with the text “Correcting a spelling error”, and clicks OK.
he pop-up dialog closes and the macro expands for editing with all fields prefilled with the previous values.
The user corrects the error and clicks “Store”.
The new journal entry is committed with the reason-text prepended on a separate line.

Open Questions

  • What to do in journal, when committing a result that is already there (for instance an error correction).
  • What are the core functionality of Pracro??

Field database

In order to not flood the database with new fields every time a new macro is being inserted (where many of the fields are duplicates from other macroes with new names), a field table with uids, aliases and description should be created.
Every time a new field is created in a macro the existence of the field in this table must be verified.
The names (aliases) of these fields define which field values in a macro can be stored in the database, thus requiring the client to send all fields (with name attributes) and their values to the server.

Naming of the fields:
ex. henvisning.diagnose
ex. lensmeter.axis
or in some unique instances:
ex. cave
ex. cpr

Multilist format string and resume embedded language

'Raw' value from multilist (which is also the one stored in the database):

Patienten er overfølsom overfor ${cave.prep|anabolske steroider} med reaktionen ${cave.reak|udslæt}.

The journal format string:

Patienten er overfølsom overfor $[outputfield(cave.prep)] med reaktionen $[outputfield(cave.reak)].

This goes into the journal:

Patienten er overfølsom overfor anabolske steroider med reaktionen udslæt.

Block delimiter characters ''${...}'', ''$[...]''

The reason for using two different block delimiters are for the programmer to be able to distinguish the two very different types of block content. One containing a special blockname/blockvalue pair (the ${…} block), and the other containing LUA code (the $[…] block).

The reason for choosing ${} and $[] for delimiters are that they do not interfere with the XML, since neither of the constructs contain XML special characters, but still the contained values/source code must still be XML escaped. Furthermore none of the characters a used very often in what one might call natural written language, compared to for example, (), and they are also used less frequently in LUA code compared to (), thus making the job of escaping easier, and the final code easier to read, as-it-is.

The $ characters will simply render as a $ if not followed by a { or a [, and need nnever to be escaped.
The {, }, [ and ] characters can be escaped by putting two next to each other, i.e. {{ to render a single {.
If the $ is put just before a {{ or [[, the $ will be rendered as a $.

Lib docs



Initially the server receives a request from the client.
The request contains a course and a macro.
The template containing the course is loaded, and the macros in it are verified.
The requested macro are loaded.
All macro fields are looked up in the db, and prefilled.
All queries to pentominos are performed.
Maps between fields and pentominos values are performed.
The final xml are generated accordingly and sent back to the client.


The server receives a commit from the client, containing all fields and their values.
The server puts all field/value pairs in the db, all connected to a transaction id.
The corresponding macro is loaded and its resume generated according to the resume format string.
The resume is sent to the upload server.

Error handling

All server output is cached prior to sending. Upon error a special error macro window is generated and sent to the client, containing a description of the error, and a close button.
All errors should be prevented/worked around if possible.
All actions already taken, should be rolled back. In order to do this, all external transmissions must be made last, bacause they are not necessarily possible to roll back.

Connection lifespan

A connection is made to the server at first request. It is kept alive for the entire session, i.e. during commit and possible following requests (due to continue action buttons).
The connection may be terminated at any key point (after a request or a commit), since the server is stateless, but it may be saving resources to keep the connection alive, thus only creating one connection per session.



  • Make configure flag to remove pentominos support.
  • Rename luaprograms/luaprogram tags to scripts/script with a language attribute.
  • Implement use of field ttl on both pentominos queries and db lookups.
  • Rewamp configuration module.
  • Finish and test implementation of journal data injection.
  • Remove all debug code from daemon.
  • Rewrite server to use a read loop, and terminate upon socket close.
  • Make SQL escaping of special characters in insertions.
  • Make server capable of making multiple pentominos queries.
  • Make automap on pentominos queries.
  • Have the parser tell how many bytes were used, and pushing the rest back into the buffer.
  • Make QueryHandler use read loop.
  • Make server reuse pentominos connection for the entire session.
  • Make server reuse database connection for the entire session.
  • Make fieldname table, and only store field/value pairs when the fieldname is in this table.
  • Implement the ttl attribute on the querytag, instead of just the global one.
  • Clean up error (exception) handling.
  • Make header tags in course.


  • Rename luaprograms/luaprogram tags to scripts/script with a language attribute.
  • Rewrite client network code.
  • Rewrite client to reuse socket during entire session.
  • Implement a spacer tag.
  • Fix setValue bug, where enable/disable does not work.
  • Make multilist set the value of its children.
  • Centralize all common QWidget code (setWidth/setHeight/…).
  • Make help text wrap and convert \n to 2 newlines (currently only on GroupBox).
  • Make a database widget, that can make dynamic queries depending on the user input.
  • Implement 'continue without commit' button action.
  • Invalid combobox must be painted red (only visible on windows).
  • Make postgresql plugin work in windows 98 (works with libpq 8.0.14 and self compiled qt 4.4.1).
  • Make client have a nice icon.
  • Set encoding in QDomDocument stream to utf-8.
  • Remove flickering when going from expanded to collapsed state.
  • Rethink/reimplement client-side script triggering system (currently triggered onChange).
  • Make use of header tags in course.
  • Make startup criteria. Design the startpage macro, with deps as colours.
  • Automatic generation of continue button based on 'completed' and deps.


  • Document checkbox truevalue/falsevalue attributes.
  • Document dbwidget.
  • Button continue_nocommit action.
  • storechildren in metawidget
  • Header tags in course.
  • service attribute on query tags.
  • DateTime widget

Macros (local)

  • B.2.2 nethinde tykkelse skal have et 'andet' felt.
  • B.1 Præparat skal laves om til noget andet.
pracro/pracro.txt · Last modified: 2012/11/08 10:36 by deva