static void buildTree(SampleNode *pRoot)
{
   SampleNode *pVisualRoot, *pFood, *pNonFood, *pStreams, *pAudio;

   pVisualRoot = createNode(pRoot, "root", "root");

   pFood = createNode(pVisualRoot, "food", "Some food");
   createNode(pFood, "parsley", "tasty herb");
   createNode(pFood, "salad", "eat a lot of it!");

   pNonFood = createNode(pVisualRoot, "non-food", "tech stuff");

   pAudio = createNode(pNonFood, "audio", "ask Lawo");
   createGain(pAudio);
   createVolume(pAudio);
   createFormat(pAudio);
   createNode(pAudio, "dangling", NULL);

   pStreams = createNode(pNonFood, "streams", "see 'em move");
   pStreams->node.pSchemaIdentifiers = stringDup("de.l-s-b.emberplus.samples.streams");
   pStreams->fields |= GlowFieldFlag_SchemaIdentifier;
   createStream1(pStreams);
   createStream2(pStreams);
   createStream3(pStreams);
   createStream4(pStreams);
}
SQLiteSyntaxHighlighter::SQLiteSyntaxHighlighter(QTextDocument *parent) :
    QSyntaxHighlighter(parent)
{
    HighlightingRule rule;

    tableFormat = createFormat("table");
    keywordFormat = createFormat("keyword");
    singleLineCommentFormat = createFormat("comment");
    identifierFormat = createFormat("identifier");
    stringFormat = createFormat("string");
    functionFormat = createFormat("function");

    // Keywords
    QStringList keywordPatterns;
    keywordPatterns
            << "ABORT" << "ACTION" << "ADD" << "AFTER" << "ALL"
            << "ALTER" << "ANALYZE" << "AND" << "AS" << "ASC"
            << "ATTACH" << "AUTOINCREMENT" << "BEFORE" << "BEGIN" << "BETWEEN"
            << "BY" << "CASCADE" << "CASE" << "CAST" << "CHECK"
            << "COLLATE" << "COLUMN" << "COMMIT" << "CONFLICT" << "CONSTRAINT"
            << "CREATE" << "CROSS" << "CURRENT_DATE" << "CURRENT_TIME" << "CURRENT_TIMESTAMP"
            << "DATABASE" << "DEFAULT" << "DEFERRABLE" << "DEFERRED" << "DELETE"
            << "DESC" << "DETACH" << "DISTINCT" << "DROP" << "EACH"
            << "ELSE" << "END" << "ESCAPE" << "EXCEPT" << "EXCLUSIVE"
            << "EXISTS" << "EXPLAIN" << "FAIL" << "FOR" << "FOREIGN"
            << "FROM" << "FULL" << "GLOB" << "GROUP" << "HAVING"
            << "IF" << "IGNORE" << "IMMEDIATE" << "IN" << "INDEX"
            << "INDEXED" << "INITIALLY" << "INNER" << "INSERT" << "INSTEAD"
            << "INTERSECT" << "INTO" << "IS" << "ISNULL" << "JOIN"
            << "KEY" << "LEFT" << "LIKE" << "LIMIT" << "MATCH"
            << "NATURAL" << "NO" << "NOT" << "NOTNULL" << "NULL"
            << "OF" << "OFFSET" << "ON" << "OR" << "ORDER"
            << "OUTER" << "PLAN" << "PRAGMA" << "PRIMARY" << "QUERY"
            << "RAISE" << "REFERENCES" << "REGEXP" << "REINDEX" << "RELEASE"
            << "RENAME" << "REPLACE" << "RESTRICT" << "RIGHT" << "ROLLBACK"
            << "ROW" << "SAVEPOINT" << "SELECT" << "SET" << "TABLE"
            << "TEMP" << "TEMPORARY" << "THEN" << "TO" << "TRANSACTION"
            << "TRIGGER" << "UNION" << "UNIQUE" << "UPDATE" << "USING"
            << "VACUUM" << "VALUES" << "VIEW" << "VIRTUAL" << "WHEN"
            << "WHERE";

    rule.format = keywordFormat;
    foreach (const QString &pattern, keywordPatterns) {
        rule.pattern = QRegExp(QString("\\b%1\\b").arg(pattern));
        rule.pattern.setCaseSensitivity(Qt::CaseInsensitive);
        highlightingRules.append(rule);
    }
SPHrender::SPHrender(QWidget *parent) :
    QGLWidget(createFormat(), parent),
    sph(this), timer(new QTimer(this)), fps(60)
{
    connect(timer, SIGNAL(timeout()), this, SLOT(updateGL()));
}