QM  4.4.0
Working with Files

As described in section about the physical design, QM™ provides special file items that represent files to be generated on disk. The file items can only exist inside a directory item, which determines the location of the file relative to the QM Model File or the External Package File, for files nested inside External Packages.

Internal Files

Normally, the file items are just "templates" for the files to be created on disk. Such files-templates are called internal files and can be edited in the MDI windows at the center of the QM user interface, which work exactly like any other modern code editors.

You can insert any code (or text) into the file-templates, such as #include directives, declarations, definitions, comments, and anything else that you would put into hand-crafted code. All this code will then be literally copied over to the files generated on disk. But, the twist here is that you can also direct QM to generate specific parts of the code based on the model items of your choosing, with the granularity ranging from packages and classes, down to specific state machines, states, attributes, and operations.

QM Code Generation as Expansion of Code-Generation Directives

You achieve this by inserting the special Code-Generation Directives into your file-templates. For example, you can direct QM to generate a class declaration in one place of a file on disk, a class definition in another place, and so on.

The files generated from Internal Files should not be edited manually outside the QM™ tool, because the whole body of the file will be re-generated and any edits would be lost. Therefore, to prevent inadvertent change of the files generated on disk, these files are saved as read-only.

External Files

QM supports also External Files, which combine user-code with the generated-code and possibly Code-Generation Directives. This merging of a file-template with generated-code is achieved by clearly delimiting the generated-sections with special comments. Such External Files can be edited inside any editor/IDE of choice and are not editable inside QM. The following listing shows an example of an External File on disk (the comments after the listing explain the interesting lines of code):

1 //$file${.::test::test.cpp} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
2 //
3 // Model: calc_sub.qm
4 // File: ${.::test::test.cpp}
5 //
6 // This code has been generated by QM 4.4.0 (https://www.state-machine.com/qm).
7 // DO NOT EDIT SECTIONS BETWEEN THE COMMENTS "$...###".."$end...###".
8 // All your changes in these sections will be lost.
9 //
10 // This code is covered by the following QP license:
11 // License # : QPCPP-EVAL
12 // Issued to : Institution or an individual evaluating the QP/C++ framework
13 // Framework(s): qpcpp
14 // Support ends: 2019-12-31
15 // Product(s) :
16 // This license is available only for evaluation purposes and
17 // the generated code is still licensed under the terms of GPL.
18 // Please submit request for extension of the evaluaion period at:
19 // https://www.state-machine.com/licensing/#RequestForm
20 //
21 //$endhead${.::test::test.cpp} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
22 #include "qpcpp.h" // QP/C++
23 #include "bsp.h" // board support package
24 #include "calc.h" // application
25 . . .
26 $declare${SMs::Calc}
28 static Calc l_calc; // the only instance of the Calc class
30 // global-scope definitions --------------------------------------
31 QP::QMsm * const the_calc = &l_calc; // "opaque" pointer to MSM
32 . . .
34 //$skip${QP_VERSION} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
35 // Check for the minimum required QP version
36 #if (QP_VERSION < 640U) || (QP_VERSION != ((QP_RELEASE^4294967295U) % 0x3E8U))
37 #error qpcpp version 6.4.0 or higher required
38 #endif
39 //$endskip${QP_VERSION} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
40 //$define${SMs::Calc} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
41 //${SMs::Calc} ...............................................................
42 //${SMs::Calc::Calc} .........................................................
43 Calc::Calc()
44  : QMsm(Q_STATE_CAST(&Calc::initial))
45 {}
47 //${SMs::Calc::SM} ...........................................................
48 QP::QState Calc::initial(Calc * const me, QP::QEvt const * const e) {
49  . . .
50  return QM_TRAN_INIT(&tatbl_);
51 }
52 //${SMs::Calc::SM::on} .......................................................
53 QP::QMState const Calc::on_s = {
54  static_cast<QP::QMState const *>(0), // superstate (top)
55  Q_STATE_CAST(&Calc::on),
56  Q_ACTION_CAST(&Calc::on_e),
57  Q_ACTION_CAST(&Calc::on_x),
58  Q_ACTION_CAST(&Calc::on_i)
59 };
60 . . .
61 //$enddef${SMs::Calc} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  • 1-21 Top-level file comment generated by QM.
    NOTE: This code (between the $file${..} vvvvvv and $endhead${..} ^^^^^^^ should not be edited manually.
  • 22-25 user-code (editable)
  • 26 code-generation directive (editable)
  • 27-33 user-code (editable)
  • 34-61 code generated by QM by expanding the directive $define${SMs::Calc}
    NOTE: This code (between the $define${..} vvvvv and $enddef${..} ^^^^^^^^ should not be edited manually.
The files generated from External Files are saved as writable, because the user can edit parts of these files. However, the generated sections marked with the comments ##### should not be edited, because they will be re-generated and any edits in these sections would be lost.

Adding a New File

The file items can only exist inside a directory item, which determines the location of the file relative to the QM Model File. Therefore, to add a new file item, you first need to select the directory item in the Model Explorer. Then you right-click on this directory item and select the "Add File" in the popup menu, as shown below:

Adding a file item to a directory item

File Property Sheet

The following picture shows the Property Sheet of a File Item (see Property Editor):

File Item Property Sheet

File Name

The most important property of a file item is its name. QM™ automatically recognizes several file types based on the file name extension and applies a special icon for the recognized files. The following table shows the the list of recognized file types and icons:

File Name Extension File Type File Icon
.h C/C++ header file  
.hpp C++ header file  
.c C implementation file  
.cpp C++ implementation file  
.cxx C++ implementation file  
.cc C++ implementation file  
.ino Arduino sketch  
.py Python script  
.tcl Tcl/Tk script  
.mak make file  
makefile make file  
Makefile make file  
Providing one of the recognized file name extensions is necessary for QM™ to be able to apply the correct syntax highlighting for the file type. The file name extensions are case-sensitive.


The encoding drop-box property of the file item allows you to select one of the few dozens available character encodings for your file. This option might be interesting if you use special characters outside the basic ASCII character set. (NOTE: the default setting corresponds to the encoder selected in your operating system).


The "external" check box designates a file as an External File* that is **not** managed by QM, but still participates in the code generation. Such external" files can be edited with an editor/IDE of choice.

Unix End-Of-Line Convention

QM™ applies consistently the Unix end-of-line convention (single LF octet at the end of line) to all files saved on disk, regardless on the host operating system. This is done intentionally to generate identical code across diverse hosts, which might be used by various team members working on the same project.

Because the LF-only end-of-line convention is nonnative on Windows, the generated files might look incorrectly in some text editors (e.g., Notepad). However, experience shows that most programming editors designed for editing code should have no problem correctly displaying the generated code.

Next: Code-Generation Directives