1. Overview

The intention of QtVCP is to supply an infrastructure to support screen and VCP panel building for LinuxCNC.

By providing a diverse widget set and supporting custom coding, QtVCP hopes that development energy will be expended in one toolkit rather than continuous re-invention.

By using the same toolkit across many screens/panels, users should have an easier time customizing/creating these, and developers should find it easier to help trouble shoot with less effort.

QtVCP uses a Qt Designer built .ui file and a Python handler file

  • to load and control a screen/panel that displays Qt widgets and

  • to control LinuxCNC’s motion controller or HAL pins.

There are builtin screens and panels, easily loaded by a user, or users can build/modify one of their own.

QtVCP uses libraries and custom widgets to hide some of the complexity of interfacing to LinuxCNC. By using QtVCP’s library rather than LinuxCNC’s, we can mitigate minor LinuxCNC code changes.

2. Builtin Locations

Builtin screens and panels are stored in separate folders:

  • Screens in share/qtvcp/screens

  • Panels in share/qtvcp/panels

  • Stock images in share/qtvcp/images

Screens and panels are sorted by their folder name, which is also the name used to load them.

Inside the folder would be:

  • the .ui file,

  • the handler file, and

  • possibly the .qss theme file.

3. QtVCP Startup To Shutdown

QtVCP source is located in +src/emc/usr_intf/qtvcp+ folder of LinuxCNC source tree.

3.1. QtVCP Startup

When QtVCP first starts:

  1. It must decide if this object is a screen or a panel.

  2. It searches for and collects information about paths of required files and useful folders.

  3. It then:

    1. Builds the HAL component,

    2. Loads the window instance,

    3. Adds handler extensions,

    4. Installs an event filter.

Now the window/widgets are instantiated, the HAL pins are built. This also initiates the +_init_hal()+ function of the widgets. . The +initialized__()+ handler function is called . The STATUS library is forced to update. . HAL component is set ready at this point. . A variety of optional switch arguments are set, including calling a POSTGUI HAL file (if a screen). . Terminate signals are trapped and QtVCP now polls for events.

3.2. QtVCP Shutdown

Finally when QtVCP is asked to shutdown:

  1. It calls shutdown functions in the handler file,

  2. STATUS monitoring is shut down

  3. HAL component gets killed

4. Path Information

When QtVCP loads it collects paths information.

This is available in the handler file’s +__init__()+ function as path:


Path of builtin images


Path of builtin motion controller screens


Path of builtin accessory panels


Path of where QtVCP was launched from


Path of the launched configuration


General path, used to derive all paths


Generic name used to derive all paths


Path of QtVCP’s Python library


Path of handler file


Path of .ui file


Path of translation


Screen/panel switch

5. Idiosyncrasies

These try to cover non-obvious situations.

5.1. Error Code Collecting

LinuxCNC’s error code collecting can only be read from one place.

When read, it is consumed, i.e. no other object can read it.

In QtVCP screens, it is recommended to use the ScreenOptions widget to set up error reading.

Errors are then sent to other objects via STATUS signals.

5.2. Jog Rate

LinuxCNC has no internal record of jog rate: you must specify it at the time of jogging.

QtVCP uses the STATUS library to keep track of the latest linear and angular jog rates.

It is always specified in machine units per minute and must be converted when in non-machine units mode.
So, if your machine is imperial based but you are in metric mode, changes to jog rate sent to ACTION functions must be converted to imperial.
In the same manner, if the machine is metric based and you are in imperial mode, changes to jog rate must be sent to ACTION functions in metric units.
For angular jog rates the units don’t change in metric/imperial mode so you can send them to ACTION functions without conversion.

While you are free to ignore this jogging record while building screens, anyone modifying your screen and using the builtin jog rate widgets would not get the desired results as the ACTION library’s DO_JOG function gets it’s jog rate from the STATUS library.

5.3. Keybinding

Keybinding is always a difficult-to-get-right-in-all-cases affair.

Custom keybinding functions are to be defined in the handler file.

Most importantly widgets that require regular key input and not jogging, should be checked for in the processed_key_event__ function.

5.4. Preference File

Some QtVCP widgets use the preference file to record important information.

This requires the preference file to be set up early in the widget initialization process.
The easiest way to do this is to use the ScreenOptions widget.

5.5. Widget Special Setup Functions

QtVCP looks for and calls the +_hal_init()+ function when the widget is first loaded.

It is not called when using Qt Designer editor.

After this function is called the widget has access to some special variables:


The HAL component instance


This widget’s name as a string


This widget’s PyQt object instance


The very top level parent of the screen


The instance of QtVCP’s path library


The instance of an optional preference file


The Qsettings object

When making a custom widget, _import and sub class _the +_HalWidgetBase+ class for this behavior.

5.6. Dialogs

Dialogs (AKA "pop up windows") are best loaded with the ScreenOptions widget, but they can be placed on the screen in Qt Designer.

It doesn’t matter where on the layout but to make them hidden, cycle the state property to true then false.

By default, if there is a preference file, the dialogs will remember their last size/placement.
It is possible to override this so they open in the same location each time.

5.7. Styles (Themes)

While it is possible to set styles in Qt Designer, it is more convenient to change them later if they are all set in a separate .qss file. The file should be put in the same location as the handler file.