Let’s create a TreeFrog Application.
We’ll try to make a simple blog system which can list, view, and add/edit/delete text.

Generate the Application Skeleton

First we will need to make a skeleton (various settings files and a directory tree). We’ll use the name “blogapp”. Run the following command from the command line. (In Windows, please run from the TreeFrog Command Prompt).

 $ tspawn new blogapp
  created   blogapp
  created   blogapp/controllers
  created   blogapp/models
  created   blogapp/models/sqlobjects
  created   blogapp/views
  created   blogapp/views/layouts
  created   blogapp/views/mailer
  created   blogapp/views/partial

Create a Table

Now we need to create a table in the database. We’ll create the field title and content (body). Here are examples in MySQL and SQLite’

Example in MySQL:
Set the character set to UTF-8. You can also specify this when generating the database (do ensure that it is being set correctly, see FAQ). You can specify the configuration file for the database, as described below. Also, make the path through into MySQL using the command line tool.

 $ mysql -u root -p
 Enter password:

 Query OK, 1 row affected (0.01 sec)

 mysql> USE blogdb;
 Database changed

 mysql> CREATE TABLE blog (id INTEGER AUTO_INCREMENT PRIMARY KEY, title  VARCHAR(20), body VARCHAR(200), created_at DATETIME, updated_at DATETIME, lock_revision INTEGER) DEFAULT CHARSET=utf8;

 Query OK, 0 rows affected (0.02 sec)

 mysql> DESC blog;
 | Field         | Type         | Null | Key | Default | Extra          |
 | id            | int(11)      | NO   | PRI | NULL    | auto_increment |
 | title         | varchar(20)  | YES  |     | NULL    |                |
 | body          | varchar(200) | YES  |     | NULL    |                |
 | created_at    | datetime     | YES  |     | NULL    |                |
 | updated_at    | datetime     | YES  |     | NULL    |                |
 | lock_revision | int(11)      | YES  |     | NULL    |                |
 6 rows in set (0.01 sec)

 mysql> quit

Example in SQLite:
We are going to put the database files in the DB directory.

 $ cd blogapp
 $ sqlite3 db/blogdb
 SQLite version 3.6.12
 sqlite> CREATE TABLE blog (id INTEGER PRIMARY KEY AUTOINCREMENT, title VARCHAR(20), body VARCHAR(200), created_at TIMESTAMP, updated_at TIMESTAMP, lock_revision INTEGER);
 sqlite> .quit

A blog table is created with the fields: id, title, body, created_at, updated_at, and lock_revision.

With the fields updated_at and created_at, TreeFrog will automatically insert the date and time of creation and of each update. The lock_revision field, which is intended for use with optimistic locking, needs to be created as an integer type.

Optimistic Locking

The optimistic locking is used to store data while verifying that information is not locked by being updated by another user. Since there is no actual write lock, you can expect processing to be a little faster. See the section on O/R mapping for more information.

Set the Database Information

Use config/database.ini to set information about the database.
Open the file in the editor, enter the appropriate values for your environment to each item in the [dev] section, and then click Save.

Example in MySQL:


Example in SQLite:


Once you have correctly set these details, it’s time to display the table to access the DB.
If everything is setup properly, it will display a message like this:

 $ cd blogapp
 $ tspawn --show-tables
 DriverType:   QSQLITE
 DatabaseName: db\blogdb
 Database opened successfully
 Available tables:

If a required SQL driver is not included in the Qt SDK, the following error message will appear:

 QSqlDatabase: QMYSQL driver not loaded

If you receive this message, download the SQL database driver from the download page, and install it.

You can check which SQL drivers are installed with the following command;

 $ tspawn --show-drivers
 Available database drivers for Qt:

The pre-built SQL driver can be used for SQLite, although the SQLite driver can also be used with a little effort.

Specifying a Template System

In TreeFrog Framework, we can specify either Otama or ERB as a template system. We will set the TemplateSystem parameter in the development.ini file.


Automatic Generation of Code Created from the Table

From the command line, run the command generator (tspawn) which will generate the underlying code. The example below shows the production of controller, model, and view. The table name is specified as the command argument.

 $ tspawn scaffold blog
 DriverType: QSQLITE
 DatabaseName: db/blogdb
 Database open successfully
   created   controllers/blogcontroller.h
   created   controllers/blogcontroller.cpp
   updated   controllers/controllers.pro
   created   models/sqlobjects/blogobject.h
   created   models/blog.h
   created   models/blog.cpp
   updated   models/models.pro
   created   views/blog

With the tspawn options you can generate/update the model/view.

Help of the tspawn command:

 $ tspawn --help
 usage: tspawn <subcommand> [args]

 Type 'tspawn --show-drivers' to show all the available database drivers for Qt.
 Type 'tspawn --show-driver-path' to show the path of database drivers for Qt.
 Type 'tspawn --show-tables' to show all tables to user in the setting of 'dev'.
 Type 'tspawn --show-collections' to show all collections in the MongoDB.

 Available subcommands:
   new (n)         <application-name>
   scaffold (s)    <table-name> [model-name]
   controller (c)  <controller-name> action [action ...]
   model (m)       <table-name> [model-name]
   usermodel (u)   <table-name> [username password [model-name]]
   sqlobject (o)   <table-name> [model-name]
   mongoscaffold (ms) <model-name>
   mongomodel (mm) <model-name>
   validator (v)   <name>
   mailer (l)      <mailer-name> action [action ...]
   delete (d)      <table-name or validator-name>

Build the Source Code

To start the build process, run the following command only once; it will generate a Makefile.

 $ qmake -r "CONFIG+=debug"

A WARNING message will be displayed, but there is actually no problem. Next, run the make command to compile the controller, model, view, and helper.

 $ make     (On MinGW run 'mingw32-make', on MSVC run 'nmake' command instead)

If the build succeeds, four shared libraries (controller, model, view, helper) will be created in the lib directory. By default, the library is generated in debug mode; however, you can regenerate the Makefile, using the following command, to create a library in release mode.

Creating a Makefile in release mode:

 $ qmake -r "CONFIG+=release"

To Start the Application Server

Change to the root directory of the application before starting the application server (AP server). The server will start to process what it regards as the application root directory to the directory where the command is run. To stop the server, press Ctrl+c.

 $ treefrog -e dev

In Windows, start by using treefrogd.exe.

> treefrogd.exe -e dev

In Windows, start by using treefroged.exe when you build web applications in debug mode, and start by using treefrog.exe when you want to build a web application in release mode.

Release and debug modes should not be mixed, as the result will not work properly.

If you want it to run in the background, use the option -d together with any other required options.

 $ treefrog -d -e dev

The command option ‘-e’ appears in the above examples. When this is followed by a section name that you have specified in database.ini before, it can be used to change the database settings. If no section name is specified it is assumed that the command refers to a product (when the project is being made, the following three sections are predefined).

Section Description
dev For generator, development
test For test
product For official version, production version

‘-e’ comes from the initials letter of “environment”.

Stop command:

 $ treefrog -k stop

Abort command (forced termination):

 $ treefrog -k abort

Restart command:

 $ treefrog -k restart

If the firewall is in place, make sure that the correct port is open (the default is port 8800).

Browser Access

We will now use your web browser to access http://localhost:8800/Blog. A list screen, such as the following should be displayed.

Initially, there is nothing registered.

Listing Blog 1

When two items are registered the options show, edit, and remove become visible. As you can see, there is even no problem in displaying Japanese text.

Listing Blog 2

TreeFrog is equipped with a call method mechanism (Routing system) for the appropriate controller from the requested URL to the action (as well as other frameworks).
Developed source code can work on other platforms, if it is re-built.

To see a sample Web application. You can watch it here.
You can play with this and it will respond at the same speed as the average desktop application.

Source Code of Controller

Let’s take a look at the contents of the controller which is generated.
First, the header file. There are several charm codes, but these are required for sending by URL.

The purpose of public slots is to declare the actions (methods) you want to send. Actions corresponding to the CRUD are defined. Incidentally, the slots keyword is a feature of the Qt extension. Please see the Qt documentation for more details.

class T_CONTROLLER_EXPORT BlogController : public ApplicationController
    BlogController() { }
    BlogController(const BlogController &other);

public slots:
    void index();                     // Lists all entries
    void show(const QString &id);     // Shows one entry
    void create();                    // New registration
    void save(const QString &id);     // Updates (save)
    void remove(const QString &id);   // Deletes one entry

T_DECLARE_CONTROLLER(BlogController, blogcontroller)     // Charm

  Next, let’s look at the source file.
The source code is a bit long, but please bear with me.

#include "blogcontroller.h"
#include "blog.h"

BlogController::BlogController(const BlogController &)
    : ApplicationController()
{ }

void BlogController::index()
    auto blogList = Blog::getAll();  // Get a list of all Blog objects
    texport(blogList);               // Pass the value to a view
    render();                        // Render the view (template)

void BlogController::show(const QString &id)
    auto blog = Blog::get(id.toInt()) ;  // Gets Blog model by primary key

void BlogController::create()
    switch (httpRequest().method()) { // Checks the incoming httpRequest method type
    case Tf::Get:

    case Tf::Post: {
        auto blog = httpRequest().formItems("blog"); // Saves the incoming form-data in
                                                     // the 'blog' variable from type 'QVariantMap'
        auto model = Blog::create(blog);             // Creates the object from POST

        if (!model.isNull()) {
            QString notice = "Created successfully.";
            tflash(notice);                      // Sets the flash message
            redirect(urla("show", model.id()));  // Redirect to show action
        } else {
            QString error = "Failed to create."; // Object creation failure

        renderErrorResponse(Tf::NotFound);       // Shows an error page

void BlogController::save(const QString &id)
    switch (httpRequest().method()) {
    case Tf::Get: {
        auto model = Blog::get(id.toInt()); // Get a Blog object for update
        if (!model.isNull()) {
            session().insert("blog_lockRevision", model.lockRevision()); // Sets the lock revision
            auto blog = model.toVariantMap();
            texport(blog);                  // Sends the blog-data to the view

    case Tf::Post: {
        QString error;
        int rev = session().value("blog_lockRevision").toInt(); // Gets the lock revision
        auto model = Blog::get(id.toInt(), rev);                // Obtaining blog-data by its ID

        if (model.isNull()) {
            error = "Original data not found. It may have been updated/removed by another transaction.";
            redirect(urla("save", id));

        auto blog = httpRequest().formItems("blog");
        model.setProperties(blog);              // Sets the data coming from the request
        if (model.save()) {                     // Saves the object
            QString notice = "Updated successfully.";
            redirect(urla("show", model.id())); // Redirects to show action
        } else {
            error = "Failed to update.";


void BlogController::remove(const QString &pk)
    if (httpRequest().method() != Tf::Post) {

    auto blog = Blog::get(id.toInt());   // Gets a Blog object
    blog.remove();                       // Removes it

// Don't remove below this line
T_REGISTER_CONTROLLER(blogcontroller)    // Charm

Lock revision is used to realize the optimistic locking. See “model”, which comes later in this chapter, for more information.

As you can see, you can use the texport method to pass data to the view (template). The argument for this texport method is a QVariant object. QVariant can be any type, so int, QString, QList, and QHash can pass any object. For more details on QVariant, please refer to the Qt documentation.

View Mechanism

Two template systems have been incorporated into TreeFrog so far. These are the proprietary system (called Otama) and ERB. As is familiar from Rails, ERB is used for embedding into HTML.

The default view that is automatically generated by the generator is an ERB file. So, let’s take a look at the contents of index.erb. As you can see, the C++ code is surrounded by <% … %>. When the render method is called from the index action, the content of index.erb is returned as the response.

<%#include "blog.h" %>
  <meta http-equiv="content-type" content="text/html;charset=UTF-8" />
  <title><%= controller()->name() + ": " + controller()->activeAction() %></title>
<h1>Listing Blog</h1>

<%== linkTo("New entry", urla("entry")) %><br />
<br />
<table border="1" cellpadding="5" style="border: 1px #d0d0d0 solid; border-collapse: collapse;">
<% tfetch(QList<Blog>, blogList); %>
<% for (const auto &i : blogList) { %>
    <td><%= i.id() %></td>
    <td><%= i.title() %></td>
    <td><%= i.body() %></td>
      <%== linkTo("Show", urla("show", i.id())) %>
      <%== linkTo("Edit", urla("save", i.id())) %>
      <%== linkTo("Remove", urla("remove", i.id()), Tf::Post, "confirm('Are you sure?')") %>
<% } %>

Next, let’s have a look at the Otama template system.

Otama is a template system that completely separates the presentation logic from the templates. The template is written in HTML and a “mark” element is inserted as the start tag of the section to be rewritten dynamically. The presentation logic file, written in C++ code, provides the logic in relation to the “mark”.

The following example is a file, index.html, that is generated by the generator when it is specified in the Otama template system. This can include the file data, but you will see, if you open it in your browser as it is, because it uses HTML5, the design does not collapse at all without the data.

  <meta http-equiv="content-type" content="text/html;charset=UTF-8" />
  <title data-tf="@head_title"></title>
<h1>Listing Blog</h1>
<a href="#" data-tf="@link_to_entry">New entry</a><br />
<br />
<table border="1" cellpadding="5" style="border: 1px #d0d0d0 solid; border-collapse: collapse;">
  <tr data-tf="@for">               ← mark '@for'
    <td data-tf="@id"></td>
    <td data-tf="@title"></td>
    <td data-tf="@body"></td>
      <a data-tf="@linkToShow">Show</a>
      <a data-tf="@linkToEdit">Edit</a>
      <a data-tf="@linkToRemove">Remove</a>

A custom attribute called ‘data-tf’ is used to turn on the “mark”. This is a Custom Data Attribute as defined in HTML5. A string beginning with “@” is used as the value for the “mark”.

Next, let’s look at the index.otm corresponding to the presentation logic.
The mark, which links to the associated logic, is declared in the above template, and continues in effect until a blank line is encountered. The logic is contained in the C++ part of the code.

Operators (such as == ~ =) are also used. The operators control different behaviors (for more information see the following chapters).

#include "blog.h"  ← This is as it is C++ code to include the blog.h
@head_title ~= controller()->controllerName() + ": " + controller()->actionName()

@for :
tfetch(QList<Blog>, blogList);  /* Declaration to use the data passed from the controller */
for (QListIterator<Blog> it(blogList); it.hasNext(); ) {
    const Blog &i = it.next();        /* reference to Blog object */
    %%      /* usually, for loop statements, to repeat the child and elements  */

@id ~= i.id()   /* assigns the results of i.id()  to the content of the element marked with @id */

@title ~= i.title()

@body ~= i.body()

@linkToShow :== linkTo("Show", urla("show", i.id()))  /* replaces the element and child elements with the results of linkTo() */

@linkToEdit :== linkTo("Edit", urla("edit", i.id()))

@linkToRemove :== linkTo("Remove", urla("remove", i.id()), Tf::Post, "confirm('Are you sure?')")

The Otama operators, (and their combinations) are fairly simple:
~ (tilde) sets the content of marked elements to the result of the right-hand side, = output the HTML escape, therefore ~= sets the content of the element to the results of the right-hand side then HTML-escape, if you don’t want to escape HTML, you can use ~==.

: (colon) replaces the result of the right-hand child elements and the elements that are marked, therefore :== replaces the element without HTML escape.

Passing Data from the Controller to the View

If you want to use the textport data in view, the controller (object), must be declared in the tfetch (macro) method. For the argument, specify the variable name and type of the variable. Because it is the same state as immediately before the specified variable is texported, it can be used in exactly the same way as a normal variable. In the presentation logic above, it is used as the actual variable.

Here is an example in use :

Controller side :
 int hoge;
 hoge = ...

View side :
 tfetch(int, hoge);

The Otama system, generates the C++ code based on the presentation file and the template file. Internally, tmake is responsible for processing it. After that the code is compiled, with the shared library as one view, so, the operation is very fast.

HTML Glossary

An HTML element consists of three components, a start tag, the content, end an tag. For example, in the typical HTML element, “<p>Hello</p>”, <p> is the start tag, Hello is the content, and </p> is the end tag.

Model and ORM

In TreeFrog, because it is based on relationships, the model will contain an ORM object, (however, you may want to create such a model with two or more ORM objects); the relationship being has-a. In this respect TreeFrog differs from other frameworks, since it uses “ORM = Object Model” by default. You can not change this for specific cases. In TreeFrog, ORM object(s) is wrapped by Model object.

An O/R mapper named SqlObject is included by default in TreeFrog. Since C++ is a statically typed language, type declaration is required. Let’s take a look at the SqlObject file generated by blogobject.h.

There is a charm code half, but the field in the table is declared as a public member variable. It is close to the actual structure, but can only be used by CRUD or an equivalent method, (create, findFirst, update, remove). These methods are defined in the TSqlORMapper class and in the TSqlObject class.

class T_MODEL_EXPORT BlogObject : public TSqlObject, public QSharedData
    int id {0};
    QString title;
    QString body;
    QDateTime created_at;
    QDateTime updated_at;
    int lock_revision {0};

    enum PropertyIndex {
        Id = 0,

    int primaryKeyIndex() const override { return Id; }
    int autoValueIndex() const override { return Id; }
    QString tableName() const override { return QLatin1String("blog"); }

private:    /*** Don't modify below this line ***/
    Q_PROPERTY(int id READ getid WRITE setid)
    T_DEFINE_PROPERTY(int, id)
    Q_PROPERTY(QString title READ gettitle WRITE settitle)
    T_DEFINE_PROPERTY(QString, title)
    Q_PROPERTY(QString body READ getbody WRITE setbody)
    T_DEFINE_PROPERTY(QString, body)
    Q_PROPERTY(QDateTime created_at READ getcreated_at WRITE setcreated_at)
    T_DEFINE_PROPERTY(QDateTime, created_at)
    Q_PROPERTY(QDateTime updated_at READ getupdated_at WRITE setupdated_at)
    T_DEFINE_PROPERTY(QDateTime, updated_at)
    Q_PROPERTY(int lock_revision READ getlock_revision WRITE setlock_revision)
    T_DEFINE_PROPERTY(int, lock_revision)

There are methods to query and update the primary key in the TreeFrog’s O/R mapper, but the primary key SqlObject can have only one return primaryKeyIndex() method. Therefore, any table with multiple primary keys should be corrected to return one only. It is also possible to issue more complex queries by using the TCriteria class condition. Please see following chapters for details.

Next, let’s look at the model.
The setter/getter for each property and static method of generation/acquisition of the object are defined. The parent class TAbstractModel defines the methods to save and to remove, because of this, the Blog class is equipped with the CRUD methods (create, get, save, remove) .

class T_MODEL_EXPORT Blog : public TAbstractModel
    Blog(const Blog &other);
    Blog(const BlogObject &object); // constructor made from the ORM object

    int id() const;      // The following lines are the setter/getter
    QString title() const;
    void setTitle(const QString &title);
    QString body() const;
    void setBody(const QString &body);
    QDateTime createdAt() const;
    QDateTime updatedAt() const;
    int lockRevision() const;
    Blog &operator=(const Blog &other);

    bool create() { return TAbstractModel::create(); }
    bool update() { return TAbstractModel::update(); }
    bool save()   { return TAbstractModel::save(); }
    bool remove() { return TAbstractModel::remove(); }

    static Blog create(const QString &title, const QString &body); // object creation
    static Blog create(const QVariantMap &values);                 // object creation from Hash
    static Blog get(int id);                   // Gets object specified by ID
    static Blog get(int id, int lockRevision); // Gets object specified by ID and lockRevision
    static int count();                 // Returns the amount of blog data items
    static QList<Blog> getAll();        // Gets all model objects
    static QJsonArray getAllJson();     // Gets all model objects in JSON style

    QSharedDataPointer<BlogObject> d;   // Holds the pointer of the ORM object

    TModelObject *modelData();
    const TModelObject *modelData() const;


Despite the fact that the number of code steps automatically generated by the generator is not high, all the basic functions are covered.

Of course, automatically generated code is not perfect. Real life applications may need to be more complex. The code may not be sufficient as generated, thus some reworking may be necessary. Nevertheless, the generator will save a little time and effort in writing code.

In the background, the code as described above also functions to provide; CSRF measures with cookie tampering check, optimistic locking, and token authentication against SQL Injection. If you are interested, please look into the source.

Video Demo – Sample Blog Application Creation

Video Demo – Sample blog Application Creation