:lang: en
:toc:

[[cha:qtvcp-widgets]]
= QtVCP Widgets

// Custom lang highlight
// must come after the doc title, to work around a bug in asciidoc 8.6.6
:ini: {basebackend@docbook:'':ini}
:hal: {basebackend@docbook:'':hal}
:ngc: {basebackend@docbook:'':ngc}

Qtscreen uses QtVCP widgets for LinuxCNC integration.
Widget is the general name for the UI objects such as buttons and labels
in QTpy.
You are free to use any available widgets in the QTDesigner editor.
There are also special widgets made for LinuxCNC that make integration
easier.
This are split in two heading on the right side of the editor.
One is for HAL only widgets.
The other is for CNC control widgets.
You are free to mix them in any way on your panel.

[NOTE]
This description of widget properties can easily be out of date due to
further development and lack of people to write docs (a good way to give
back to the project).
The definitive descriptions are found by looking in the source code.

== HAL Only Widgets

These Widgets usually have HAL pins and don't react to the machine
controller.

=== XEmbed Widget

Allows one to embed program into the widget.
Only programs that utilize the xembed protocol will work such as:

* GladeVCP virtual control panels
* Onboard virtual keyboard
* qtvcp virtual control panels
* mplayer video player

=== Slider Widget

Allows one to adjust a HAL pins using a sliding pointer.

=== LED Widget

.LED
image::images/qtvcp_ledWidget.png["QtVCP led",scale="25%"]

An indicator that optionally follows a HAL pin's logic.

* halpin_option -selects if the LED follows an input HAL pin or program
  state.
* diameter -diameter of the LED
* color - Color of the LED when on.
* off_color - Color of the LED when off.
* alignment - Qt Alignment hint.
* state -current state of LED
* flashing -turns flashing option on and off.
* flashRate -sets the flash rate.

The LED properties can be defined in a stylesheet with the following
code added to the .qss file.
The name_of_led would be the name defined Designer's editor.

----
LED #name_0f_led{
  qproperty-color: red;
  qproperty-diameter: 20;
  qproperty-flashRate: 150;
}
----

=== Checkbox Widget

This widget allows the user to check a box to set a HAL pin true or false.

It is based on PyQt's QCheckButton

=== Radio Button Widget

This widget allows a user to set HAL pins true or false.
Only one widget of a group can be true at a time.

It is based on PyQt's QRadioButton.

=== Round Gauge

.Round Gauge
image::images/qtvcp_round_gauge.png["QtVCP round gauge",scale="25%"]

Round Gauge can be used in a LinuxCNC GUI to display an input parameter
on the dial face.
There are several properties that are user settable in order to customize
the appearance of the gauge.

There are 2 inputs that are not customizable. They can be set via HAL
pins, programmatically or via signals from other widgets.
The non customizable parameters are:

* 'Value' -
  This is the input value that will be displayed with the gauge needle
  and in the digital readout.
  It must be set to a value between 0 and the maximum value.
* 'Setpoint' -
  This is a value that determines the location of a small marker on the
  gauge face.
  It must be set to a value between 0 and the maximum value.

The following parameters can be set either programmatically or via the
designer property editor.
The custom parameters are:

* 'halpin_option' -
  Setting this True will create 2 HAL pins. One is for setting the value
  input and the other is for setting the setpoint.
  If this option is not set, then value and setpoint must be connected
  programmatically, ie., in the handler file.
* 'max_reading' -
  This value determines the highest number that will be displayed on the
  gauge face.
* 'max_value' -
  This is the maximum expected value of the value input signal. In other
  words, it is the full scale input.
* 'num_ticks' -
  This is the number of ticks, or gauge readings that will be displayed
  on the gauge face.
  It should be set to a number that ensures the text readings around the
  gauge face are readable.
  The minimum allowed value is 2.
* 'zone1_color' -
  Zone1 extends from the maximum reading to the threshold point. It can
  be set to any RGB color.
* 'zone2_color' -
  Zone2 extends from the threshold point to the minimum reading, which
  is 0. It can be set to any RGB color.
* 'bezel_color' -
  This is the color of the outer ring of the gauge.
* 'threshold' -
  The threshold is the transition point between the zones. It should be
  set to a value between 0 and the maximum value.
  The maximum allowed value is set to the gauge maximum value and minimum
  value is 0.
* 'gauge_label' -
  This is the text that appears below the value readout, near the bottom
  of the gauge.
  The function of the gauge is then easily visible.

=== HALPad

.HALPAD
image::images/qtvcp_HALPad.png["QtVCP HAL button Joypad ",scale="25%"]

This widget looks and acts like a 5 button D-pad, with an LED ring
Each button has an selectable type (Bit, S32 or Float) output HAL pin.
The LED center ring has selectable colors for off and on and is controlled
by a Bit HAL pin.

==== ENUMS

There are enumerated constants used to reference indicator positions.

----
    NONE
    LEFT
    RIGHT
    CENTER
    TOP
    BOTTOM
    LEFTRIGHT
    TOPBOTTOM
----

There are constants for HAL pin type:

----
    NONE
    BIT
    S32
    FLOAT
----

You use the widget Designer name plus the reference constant.

[source,python]
----
self.w.halpadname.set_highlight(self.w.halpadname.LEFTRIGHT)
----

==== Properties

* 'pin_name':
  Optional name to use for the HAL pins basename. If left blank, the
  designer widget name will be used.
* 'pin_type':
  Select the HAL output pin type.
  This property is only used at startup.
  Selection can be set in Designer:
+
----
NONE
BIT
S32
FlOAT
----
+
* 'left_image_path':
* 'right_image_path':
* 'center_image_path':
* 'top_image_path':
* 'bottom_image_path': +
  A file path or resource path to an image to display in the described
  button location.
  If the reset button is pressed in the Designer editor property, the
  image will not be displayed. (allowing optionally text)
* 'left_text':
* 'right_text':
* 'center_text':
* 'top_text':
* 'bottom_text': +
  A text string to be displayed in the described button location.
  If left blank an image can be designated to be displayed.
* 'true_color':
* 'false_color': +
  Color selection for the center LED ring to be displayed when the
  'BASENAME.light.center' HAL pin is True or False.
* 'text_color': +
  Color selection for the button text.
* 'text_font': +
  Font slelection for the button text.

==== StyleSheets

The above properties could be set in styles sheets.

----
HALPad{
    qproperty-on_color: #000;
    qproperty-off_color: #444;
}
----

=== Push Button Widget

This widget allows a user to set a HAL pin true or false.
as an option it can be a toggle button.
It also has other indicating options:

==== LED indicator option

.Indicated Action Button
image::images/qtvcp_actionButton.png["QtVCP led Action Button",scale="25%"]
See 'IndicatedPushButton' below for more info


It is based on PyQt's QPushButton.

=== Focus Overlay Widget

.Focus overlay example for confirm close prompt
image::images/qtvcp_focusOverlay.png["QtVCP foucus overlay",scale="25%"]

This widget places a coloured overlay over the screen usually while a
dialog is showing.
Used to create a 'focused' feel and to draw attention to critical
information.
It can also show a translucent image.
It can also display message text and buttons.
This widget can be controller with STATUS messages.

=== Grid Layout Widget

This widget controls if the widgets inside it are enabled or disabled.
disabled widgets are typically a different colour and do not respond to
actions.

It is based on PyQt's QGridLayout.

=== HAL Label Widget
This widget displays values sent to it from HAL pins, programically or a
QtSignal.
The input pin can be selected as Bit, S32, Float or no pin selected.
There is a text Template property to set the rich text and/or to format
the text.
Basic formatting might be, for bool: %r, for integer: %d, for float: %0.4f.
A rich text example might be:

[source,python]
----
self.w.my_hal_label.setProperty(textTemplate,"""
<html><head/><body><p><span style=" font-size:12pt;
font-weight:600; color:#f40c11;">%0.4f</span></p></body></html>
""")

----

The 'setDisplay' slot can be connected to a integer, float or bool signal.
If the property 'pin_name' is not set the widget name will be used.

There are function calls to display values:

* [HALLabelName].setDisplay(some_value) can be used to set the display
  if no HAL pin is selected.
* [HALLabelName].setProperty(textTemplate,"%d") - set the template of
  the display.

It is based on PyQt's QLabel

=== LCD Number Widget

This widget displays HAL float/s32/bit values in a LCD looking way.
It can display numbers in decimal, hexadecimal, binary and octal formats
by setting the property 'mode'.
When using floats you can set a formatting string.
You must set the property 'digitCount' to an appropriate setting to
display the largest number.

==== Properties

* 'pin_name':
  Option string to be used as the HAL pin name. If set to an empty string
  the widget name will be used.
* 'bit_pin_type':
  Selects the input pin as type BIT.
* 's32_pin_type':
  Selects the input pin as type S32.
* 'float_pin_type':
  Selects the input pin as type FLOAT.
* 'floatTemplate':
  A string that will be used as a Python 3 format template to tailor the
  LCD display.
  Only used when a FLOAT pin is selected.
  eg '{:.2f}' will display a float rounded to 2 numbers after the decimal.
  A blank setting will allow the decimal to move as required.

It is based on PyQt's QLCDNumber.

=== DoubleScale Widget
This widget is a spin button entry widget.
used for setting a s32 and float HAL pin.
It has an internal scale factor, set to a default of 1, that can be set
programmatically or using a QtSignal.
The scale defaults to 1
he 'setInput' slot can be connected to a integer, or float signal.

There is a function call to change the internal scaling factor:

* [HALLabelName].setInput(some_value)

The HAL pins will be set to the value of the internal scale times the
widget displayed value.

=== CamView Widget

This widget displays a image from a web camera.
It overlays an adjustable circular and cross hair target over the image.
Camview was built with precise visual positioning in mind.

=== GeneralHALInput Widget

This widget is used to connect an arbitrary Qt widget to HAL using
signals/slots.
It is used for widgets that should respond to HAL pin changes.

=== GeneralHALOutput Widget

This widget is used to connect an arbitrary Qt widget to HAL using
signals/slots.
It is used for widgets that should control HAL pins.

=== WidgetSwitcher Widget

This is used to switch the view of a multi-widget layout to  show just
one widget.
This might be used to flip between a large view of a widget or a smaller
multi widget view.
I'ts different from a stacked widget as it can pull a widget from anywhere
in the screen and
place it in it's page with a different layout then it originally had.
The original widget must be in a layout for switcher to put it back.

In Designer you will add the widgetswitcher widget on screen.
Right click the widgetswitcher and add a page,
then populate it with widgets/layouts you wish to see in a default form.
Then add as many pages as there are views to switch to.
on each page add a layout widget.
After adding the layout you must right click the widget switcher again
and set the layout option.
click on the widgetswitcher widget and then scroll to the bottom of the
property editor.
you are looking for the dynamic property 'widget_list'.
double click the to the right of the widget_list property.
A dialog will pop up allowing you to add the names of the widgets to move
to the pages you added to the widgetswitcher.

There are function calls to display specific widgets:

* [WidgetSwitcherName].show_id_widget(number)
* [WidgetSwitcherName].show_named_widget(widget_name)
* [WidgetSwitcherName].show_default()
* [WidgetSwitcherName].show_next()

By calling one of these functions, you control what widget
is currently displayed. show_default() shows the page 0
layout, and puts all other widgets back to where they were as initially
built in Designer.


It is based on the QStack widget.

== Machine Controller Widgets

These widgets interact to the Machine Controller state.

=== Action Button Widget

These buttons are used to control action of the machine controller.
They are built on top of indicator_buttons so can have LEDs overlaid.
They can change text on state, call python code and be enabled/disabled 
by linuxcnc state.

[NOTE]
If you left double click on this widget you can launch a dialog
to set any of these action. The dialogs will help to set the
right related data to the selected action.
You can also change these properties directly in the property editor.

You can select one of these actions:

* 'Estop'
* 'Machine On'
* 'Auto'
* 'mdi'
* 'manual'
* 'run'
* 'run_from_line status' (gets line number from STATUS message
  gcode-line-selected)
* 'run_from_line slot' (gets line number from designer int/str slot
  setRunFromLine)
* 'abort'
* 'pause'
* 'load dialog' (requires a dialog widget present)
* 'Camview dialog' (requires camview dialog widget present)
* 'origin offset dialog' (requires origin offset dialog widget present)
* 'macro dialog' (requires macro dialog widget present)
* 'Launch Halmeter'
* 'Launch Status'
* 'Launch Halshow'
* 'Home' (set the joint number to -1 for all-home)
* 'Unhome' (set the joint number to -1 for all-unhome)
* 'Home Selected' Homes the joint/axis selected by STATUS
* 'Unhome Selected' Unhomes the joint/axis selected by STATUS
* 'zero axis'
* 'zero G5X' zeros the current user coordinate system offsets
* 'zero G92' zeros the optional G92 offsets
* 'zero Z rotational' zeros the rotation offset
* 'jog joint positive' (set the joint number)
* 'jog joint negative' (set the joint number)
* 'jog selected positive' (selected with a different widget or STATUS)
* 'jog selected negative' (selected with a different widget or STATUS)
* 'jog increment' (set metric/imperial/angular numbers)
* 'jog rate' (set the float/alt float number)
* 'feed override' (set the float/alt float number)
* 'rapid override' (set the float/alt float number)
* 'spindle override' (set the float/alt float number)
* 'spindle fwd'
* 'spindle backward'
* 'spindle stop'
* 'spindle up'
* 'spindle down'
* 'view change' (set view_type_string)
* 'limits override'
* 'flood'
* 'mist'
* 'block delete'
* 'optional stop'
* 'mdi command' - calls a hard code MDI command (set command_string)
* 'INI mdi number' calls an INI based MDI command (set ini_mdi_number)
* 'dro absolute'
* 'dro relative'
* 'dro dtg'
* 'exit screen' Closes down LinuxCNC
* 'Override limits' Temporarily override hard limits
* 'launch dialogs' pops up dialogs if they are included in ui file.
* 'set DRO to relative'
* 'set DRO to absolute'
* 'set DRO to distance-to-go'

These set attributes of the selected action. Availability depends on the
widget.

* 'toggle float option' - allows jog rate and overrides to toggle
  between two rates
* 'joint number' - selects the joint/axis that the button controls
* 'incr imperial number' - sets the imperial jog increment (set negative
  to ignore)
* 'incr mm number' -sets the metric jog increment (set negative to
  ignore)
* 'incr angular number' -sets the angular jog increment (set negative
  to ignore)
* 'float number' - used for jograte and overrides
* 'float alternate number' -for jograte and overrides that can toggle
  between two float numbers
* 'view type string' - can be p, x, y, y2, z, z2, clear, zoom-in,
  zoom-out, pan-up, pan-down,
  pan-left, pan-right, rotate-up, rotate-down, rotate-cw, rotate-ccw
* 'command string' - MDI command string that will be invoked if the MDI
  command action is selected.
* 'ini_mdi_number' - a reference to the INI file [MDI_COMMAND_LIST]
  section.
  Set an integer of select one line under the INI's MDI_COMMAND line
  starting at 0.
  Then in the INI file, under the heading '[MDI_COMMAND_LIST]' add
  appropriate lines.
  The commands are separated by the ';'
  The label is set after the comma. The symbols '\n' adds a line break.

[source,{ini}]
----
[MDI_COMMAND_LIST]
MDI_COMMAND = G0 Z25;X0 Y0;Z0, Goto\nUser\nZero
MDI_COMMAND = G53 G0 Z0;G53 G0 X0 Y0,Goto\nMachn\nZero
----

Action buttons are subclasssed from indicated_PushButton
See 'IndicatedPushButtons' below for more details.

==== Development Info
IndicatedPushButtons and ActionButtons are based on PyQt's QPushButton +
The code is found in action_button.py and simple_widgets.py

=== ActionToolButton

Action tool  buttons are similar in concept to action buttons, but they
use QToolButtons to allow optional actions to be selected by pushing and
holding the button till the option menu pops up.

Currently there is only one option - user view.

It is based on PyQt's QToolButton.

==== User View

User view tool button allows a user to record and return to a arbitrary
graphics view.
Press and hold the button to have the menu pop up and press 'record view'.
This records the currently displayed graphics view.
click the button normally to return to the last recorded position.

The position recorded position will be remembered at shutdown if a
preference file option is set up.

[NOTE]
Do to programming limitations, the recorded position may not show exactly
the same,
Particularly if you pan zoomed out and pan again zoomed in while setting
the desired view.
Best practice is to select a main view, modify as desired, record, then
immediately click the button to 'return' to the recorded position. If it
is not as you like, modify it's existing position and re-record.

=== RoundButton

Round buttons work the same as ActionButtons other then the button is
cropped round.
They are intended only to be visually different.
They have two path properties for displaying images on true and false.

=== Axis Tool Button

This allows one to select and set an AXIS.
If the button is set checkable, it will indicate which axis is selected.
If you press and hold the button a pop up menu will show allowing one to:

* Zero the axis
* divide the axis by 2
* set the axis arbitrarily
* reset the axis to the last number recorded

You select the axis by setting the joint number
You can select a halpin option that is set true when the axis is selected

It is based on PyQt's QToolButton

=== Camview Widget

This is used to align the work piece or zero part features using a webcam.
It uses opencv vision library.

=== DRO_Label Widget

This will display the current position of an axis.

* Qjoint_number - joint number of offset to display (10 will specify
  rotational offset)
* Qreference_type - actual, relative or distance to go (0,1,2)
* metric_template - format of display ie '%10.3f'
* imperial_template - format of display ie '%9.4f'
* angular_template  - format of display ie '%Rotational: 10.1f'

The DRO_Label widget holds a property 'isHomed' that can be used with a
stylesheet
to change the color of the DRO_Label based on home state of the joint
number in LinuxCNC.

Here is a sample stylesheet entry.
It sets the font of all DRO_Label widgets.
It sets the text template (to set resolution) of the DRO
Then sets the text color based on the Qt 'isHomed' Property.

----
DROLabel {
    font: 25pt "Lato Heavy";
    qproperty-imperial_template: '%9.4f';
    qproperty-metric_template: '%10.3f';
    qproperty-angular_template: '%11.2f';
}

DROLabel[isHomed=false] {
    color: red;
}

DROLabel[isHomed=true] {
    color: green;
}
----

Here is how you specify a particular widget - by it's objectName in
designer.

----
DROLabel #dr0_x_axis [isHomed=false] {
    color: yellow;
}
----

It is based on PyQt's QLabel

=== GcodeDisplay
This displays G-code in text form. It will highlight the currently
running line.
This can also display MDI history when LinuxCNC is in MDI mode.
This can also display log entries when LinuxCNC is in MANUAL mode.
This will also display preference file entries if you enter 'PREFERENCE'
in capitals into the MDILine widget.
It has a signal percentDone(int) that that can be connected to a slot
(such as a progressBar to display percent run)


* auto_show_mdi_status +
  Set true to have the widget switch to MDI history when in MDI mode
* auto_show_manual_status +
  Set true to have the widget switch to machine log when in Manual mode

The GcodeDisplay properties can be set in a stylesheet with the following
code added to the .qss file.

----
EditorBase{
    qproperty-styleColorBackground: lightblue;
    qproperty-styleColor0: black;
    qproperty-styleColor1: #000000; /* black */
    qproperty-styleColor2: red;
    qproperty-styleColor3: black;
    qproperty-styleColor4: yellow;
    qproperty-styleColorMarginText: White;
    qproperty-styleColorMarginBackground: blue;
    qproperty-styleFont0: "Times,12,-1,0,90,0,0,0,0,0";
    qproperty-styleFont1: "Times,18,-1,0,90,1,0,0,0,0";
    qproperty-styleFont2: "Times,12,-1,0,90,0,0,0,0,0";
    qproperty-styleFont3: "Times,12,-1,0,90,0,0,0,0,0";
    qproperty-styleFont4: "Times,12,-1,0,90,0,0,0,0,0";
    qproperty-styleFontMargin: "Times,14,-1,0,90,0,0,0,0,0";
}
----

For gcodeDisplay widget's default G-code lexer:

* styleColor0 = Default = digit characters
* styleColor1 = Comments = characters inside of 'msg()'
* styleColor2 = Key = alphabetic characters
* styleColor3 = Assignment = ('%', '<', '>', '#', '=')
* styleColor4 = Value = ('[', ']')

Font definitions:
"style name, size, -1, 0, bold setting (0-99), italics (0-1), underline
(0-1),0,0,0"

It is based on PyQt's QsciScintilla

=== GcodeEditor Widget

This is an extension of the gcodeDisplay widget that adds editing
convenience.

It is based on PyQt's QWidget which incorporates GcodeDisplay widget

=== GCodeGraphics Widget

This Displays the current G-code in a graphical form.

.Graphics Display
image::images/qtvcp_gcodeGraphics.png["QtVCP G-code Graphics",scale="25%"]

Properties that can be set via stylesheets:

* '_view'
* '_dro'
* '_dtg'
* '_metric'
* '_overlay'
* '_offsets'
* '_small_origin'
* 'overlay_color'
* 'background_color'
* '_use_gradient_background'
* 'jog_color'
* 'Feed_color'
* 'Rapid_color'
* 'InhibitControls'
* 'MouseButtonMode'
* 'MouseWheelInvertZoom'

'''

*_view* Expects a string. The following shows an example of how to set this property:

----
#gcodegraphics{
    qproperty-_view:z;
}
----

Setting this property sets the default view on GUI load. Valid choices for a lathe are p, y, y2. For other screens, valid choices are p, x, y, z, z2.

'''

*_dro* Expects a boolean. The following shows an example of how to set this property:

----
#gcodegraphics{
    qproperty-_dro:False;
}
----

Setting this property will determine whether or not to show the DRO.

'''

*_dtg* Expects a boolean. The following shows an example of how to set this property:

----
#gcodegraphics{
    qproperty-_dtg:False;
}
----

Setting this property will determine whether or not to show the Distance To Go.

'''

*_metric* Expects a boolean. The following shows an example of how to set this property:

----
#gcodegraphics{
    qproperty-_metric:False;
}
----

Setting this property will determine whether or not to show the units in metric by default.

'''

*_overlay* Expects a boolean. The following shows an example of how to set this property:

----
#gcodegraphics{
    qproperty-_overlay:False;
}
----

Setting this property will determine whether or not to show the overlay by default.

'''

*_offsets* Expects a boolean. The following shows an example of how to set this property:

----
#gcodegraphics{
    qproperty-_offsets:False;
}
----

Setting this property will determine whether or not to show the offsets by default.

'''

*_small_origin* Expects a boolean. The following shows an example of how to set this property:

----
#gcodegraphics{
    qproperty-_small_origin:False;
}
----

Setting this property will determine whether or not to show the small origin by default.

'''

*overlay_color* Expects a primary, secondary, or RGBA formatted color. The following shows an example of how to set this property:

----
#gcodegraphics{
    qproperty-overlay_color:blue;
}
----

Setting this property will set the default overlay color.

'''

*background_color* Expects a primary, secondary, or RGBA formatted color. The following shows an example of how to set this property:

----
#gcodegraphics{
    qproperty-background_color:blue;
}
----

Setting this property will set the default background color.

'''

*_use_gradient_background* Expects a boolean. The following shows an example of how to set this property:

----
#gcodegraphics{
    qproperty-_use_gradient_background:False;
}
----

Setting this property will determine whether or not use a gradient background by default.

'''

*jog_color* Expects a primary, secondary, or RGBA formatted color. The following shows an example of how to set this property:

----
#gcodegraphics{
    qproperty-jog_color:red;
}
----

Setting this property will set the default jog color.

'''

*Feed_color* Expects a primary, secondary, or RGBA formatted color. The following shows an example of how to set this property:

----
#gcodegraphics{
    qproperty-Feed_color:green;
}
----

Setting this property will set the default feed color.

'''

*Rapid_color* Expects a primary, secondary, or RGBA formatted color. The following shows an example of how to set this property:

----
#gcodegraphics{
    qproperty-Rapid_color: rgba(0, 0, 255, .5);
}
----

Setting this property will set the default rapid color.

'''

*InhibitControls* Expects a boolean. The following shows an example of how to set this property:

----
#gcodegraphics{
    qproperty-InhibitControls:True;
}
----

Setting this property will determine whether or not to inhibit external controls by default.

'''

*MouseButtonMode* Expects an integer. The following shows an example of how to set this property:

----
#gcodegraphics{
    qproperty-MouseButtonMode:1;
}
----

Setting this property changes the button behavior of the mouse to rotate, move or zoom within the preview.

There are 12 valid modes:

[width="50%",cols="1,1,1,1"]
|===
|*Mode*|*Move*|*Zoom*|*Rotate*
|0|Left|Middle|Right
|1|Middle|Right|Left
|2|Middle|Left|Right
|3|Left|Right|Middle
|4|Right|Left|Middle
|5|Right|Middle|Left
|===

Modes 6-11 are intended for Machines that only require a 2D preview such as plasma or some Lathes and have no rotate button assigned.

[width="50%",cols="1,1,1"]
|===
|*Mode*|*Move*|*Zoom*
|6|Left|Middle
|7|Middle|Left
|8|Right|Left
|9|Left|Right
|10|Middle|Right
|11|Right|Middle
|===

'''

*MouseWheelInvertZoom* Expects a boolean. The following shows an example of how to set this property:

----
#gcodegraphics{
    qproperty-MouseWheelInvertZoom:True;
}
----

Setting this property to True will invert the zoom direction when zooming with the mouse wheel.

==== ACTION functions

The ACTION library can control the G-code graphics widget.

* `ACTION.RELOAD_DISPLAY()` - reload the current program which recalculates
  the origin/offsets.
* `ACTION.SET_GRAPHICS_VIEW(view)` The following commands can be sent:
+
----
clear
zoom-in
zoom-out
pan-up
pan-down
pan-right
pan-left
rotate-cw
rotate-ccw
rotate-up
rotate-down
overlay-dro-on
overlay-dro-off
overlay-offsets-on
overlay-offsets-off
alpha-mode-on
alpha-mode-off
inhibit-selection-on
inhibit-selection-off
dimensions-on
dimensions-off
grid-size
record-view
set-recorded-view
P
X
Y
Y2
Z
Z2
----
+
* `ACTION.ADJUST_PAN(X,Y)` - directly set the relative pan of view in x
  and y direction
* `ACTION.ADJUST_ROTATE(X,Y)` - directly set the relative rotation of
  view in x and y direction

It is based on PyQt's opengl widget.

== StateLabel Widget

This will display a label based on true/false states of the machine
controller.
You can select different text based on true or false.
These states are selectable via these properties:

* 'css_mode_status' +
  When true machine is in G96 Constant Surface Speed Mode
* 'diameter_mode_status' +
  When true machine is in G7 Lathe Diameter Mode
* 'fpr_mode_status' +
  When true machine is in G95 Feed per revolution Mode
* 'metric_mode_status' +
  When true machine is in G21 Metric Mode

Other Properties:

* 'true_textTemplate' +
  This will be the text set when the option is true.
  You can use Qt rich text code for different fonts/colours etc.
  Typical template for metric mode in true state, might be: 'Metric Mode'
* 'false_textTemplate' +
  This will be the text set when the option is true.
  You can use Qt rich text code for different fonts/colours etc.
  Typical template for metric mode in false state, might be: 'Imperial
  Mode'

It is based on PyQt's QLabel.

=== StatusLabel Widget

This will display a label based on variable states of the machine
controller.
You can change how the state will be display by substituting
You can use Rich text for different fonts/colors etc.
These states are selectable:

* 'actual_spindle_speed_status' +
  Used to display the actual spindle speed as reported from the HAL pin
  spindle.0.speed-i
  It's converted to RPM. Typically would use a textTemplate of %d
* 'actual surface speed_status' +
  Used to display the actual cutting surface speed on a lathe based on X
  axis and spindle speed.
  It's converted to distance per minute.
  Typically would use a textTemplate of %4.1f (feet per minute)
  and altTextTemplate of %d (meters per minute)
* 'blendcode_status' +
  Shows the current g64 setting
* 'current_feedrate_status' +
  Shows the current actual feedrate
* 'current_FPU_status' +
  Shows the current actual feed per unit
* 'fcode_status' +
  Shows the current programmed F Code setting
* 'feed_override_status' +
  Shows the current feed override setting in percent
* 'filename_status' +
  Shows the last loaded file name
* 'filepath_status' +
  Shows the last loade full file path name
* 'gcode_status' +
  Shows all active G-codes
* 'gcode selected_status' +
  Show the current selected G-code line
* 'halpin status' +
  Shows the HAL pin output of a selected HAL pin
* 'jograte_status' +
  Shows the current QtVCP based Jog Rate
* 'jograte_angular_status' +
  Shows the current QtVCP based Angular Jog Rate
* 'jogincr_status' +
  Shows the current QtVCP based Jog increment
* 'jogincr_angular_status' +
  Shows the current QtVCP based Angular Jog increment
* 'machine state_status' +
  Shows the current machine interpreter state using the text described
  from the state_list. +
  The interpreter states are: Estopped, Running, Stopped, Paused,
  Waiting, Reading
* 'max_velocity_override_status' +
  Shows the current max axis velocity override setting
* 'mcode_status' +
  Shows all active M-codes
* 'requested_spindle_speed_status' +
  Shows the requested spindle speed - actual may be different.
* 'rapid_override_status' +
  Shows the current rapid override setting in (0-100) percent
* 'spindle_override_status' +
  Shows the current spindle override setting in percent
* 'timestamp_status' +
  Shows the time based on the system settings. +
  An example of a useful textTemplate setting: '%I:%M:%S %p' see the
  Python time module for more info
* 'tool comment_status' +
  returns the comment text from the current loaded tool
* 'tool diameter_status' +
  returns the diameter from the current loaded tool
* 'tool_number_status' +
  returns the tool number of the current loaded tool
* 'tool_offset_status' +
  returns the offset of the current loaded tool, indexed by 'index_number'
  to select axis (0=x,1=y,etc)
* 'user_system_status' +
  Shows the active user coordinate system (G5x setting)

Other Properties:

* 'index_number' +
  Integer that specifies the tool status index to display.
* 'state_label_list' +
  List of labels used for different machine states.
* 'halpin_names' +
  Name of the halpin to monitor (including HAL component basename).
* 'textTemplate' +
  This uses Python formatting rules to set the text output.
  This is usually used for imperial (G20) or angular numerical settings,
  though not every option has imperial/metric conversion.
  One can use %s for no conversion, %d for integer conversion, %f for
  float conversion. etc
  You can also use Qt rich text code.
  Typical template used for formatting imperial float numbers to text
  eg. '%9.4f' or '%9.4f inch'
* 'alt_textTemplate' +
  This uses Python formatting rules to set the text output.
  This is usual used for metric (G21) numerical settings.
  Typical template used for formatting metric float to text
  eg. '%10.3f' or '%10.3f mm'

It is based on PyQt's QLabel

=== StatusImageSwicher Widget

Status image switcher will switch between images based on LinuxCNC states.

* 'watch spindle' would toggle between 3 images ( stop, fwd, revs)
* 'watch axis homed' would toggle between 2 images ( axis not homed,
  axis homed)
* 'watch all homed' would toggle between 2 images ( not all homed, all
  homed)
* 'watch hard limits' would toggle between 2 images or one per joint

Here is an example of using it to display an icon of Z axis homing state:

image::images/statusImageSwitcher.png["QtVCP Status Image Switcher",scale="25%"]

In the properties section notice that:

* 'watch axis homed' is checked
* 'axis letter' is set to Z

If you double click the 'image list' a dialog will show and allow you to
add image paths to.
If you have one image as an icon and one clear image then that will look
like it shows and hides the icon.

Selecting image paths can be done by selecting the 'pixmap' property and
selecting an image.
Note: The pixmap setting is for test display only and will be ignored
outside of Designer.
Right click the image name and you should see 'copy path'
Click 'copy path'
Now double click the 'image list' property so the dialog shows.
Click the 'New' button
Paste the image path in the entry box
Do that again for the next image - use a clear image to represent a
hidden icon.

You can test display the images from the image list by changing the
'image number'
In this case 0 is unhomed 1 would be homed
This is for test display only and will be ignored outside of Designer.

=== StatusStacked

This widget displays one of three panels based on LinuxCNC's mode.
This allows you to automatically display different widgets on Manual,
MDI and Auto modes.

.todo
It is based on PyQt's QStacked widget.

=== Jog Increments Widget

This widget allows the user to select jog increment values for jogging.
The jogging values come from the INI file under: '[DISPLAY]', 'INCREMENTS'
or '[DISPLAY]', 'ANGULAR_INCREMENTS'
This will be available to all widgets through STATUS.
You can select linear or angular increments by the property 'linear_option'
in Designer property editor.

It is based on PyQt's combobox

=== ScreenOption widget

This widget doesn't add anything visually to a screen but sets up important
options. This is the preferred way to use these options

These properties can be set in designer, in Python handler code or
(if appropriate) in stylesheets.

These include:

* 'halCompBaseName': +
  If left empty QtVCP will use the screen's name as the HAL component's
  basename.
  If set, QtVCP will use this string as the HAL component's basename.
  If the -c command line option is used when loading QtVCP,
  QtVCP will use the name specified in the command line - it overrides
  all above options.
  If you programmically set the basename in the handlerfile - it will
  override all above options.
  This option cannot be set in stylesheets.
* 'notify_option': +
  Hooking into the desktop notification bubbles for error and messages
* 'notify_max_messages': +
  Number of messages shown on screen at one time.
* 'catch_close_option': +
  Catching the close event to pop up a 'are you sure' prompt
* 'close_overlay_color': +
  Color of transparent layer shown when quitting.
* 'catch_error_option': +
  monitoring the LinuxCNC error channel. This also sends the message +
  through  STATUS to anything that registers
* 'play_sounds_option': +
  playing sounds using 'beep', 'espeak' and the system sound
* 'use_pref_file_option': +
  setting up a preference filepath.
  Using the magic word 'WORKINGFOLDER' in the preference file path will
  be replaced with
  the launched configuration path ie. WORKINFOLDER/my_preferences
* 'use_send_zmq_option': +
  Used to initiate ZMQ based outgoing messages.
* 'use_receive_zmq_messages': +
  Used to initiate ZMQ based in coming messages.
  These messages can be used to call functions in the handler file.
  Allowing external programs to intergrate tightly with qtvcp based
  screens.
* 'embedded_program_option': +
  Embed programs defined in the INI.
* 'default_emebed_tab' +
  This is the property for a default location to embed external programs.
  It would be set to the designer name of a tab page widget.
* 'focusOverlay_option': +
  Focus_overlay will put a transparent image or colored panel over the
  main screen to emphasize focus to an external event - typically a
  dialog.
* 'messageDialog_option': +
  sets up the message dialog - used for general messages
* 'message_overlay_color': +
  Color of transparent layer shown when the message dialog is shown.
* 'closeDialog_option': +
  sets up the standard close screen prompt dialog
* 'entryDialog_option': +
  sets up the numerical entry dialog
* 'entryDialogSoftKey_option': +
  sets up a floating software keyboard when entry dialog is focused.
* 'entry_overlay_color': +
  Color of transparent layer shown when the entry dialog is shown.
* 'toolDialog_option': +
  sets up the manual tool change dialog, including HAL pin.
* 'tool_overlay_color': +
  Color of transparent layer shown when the tool dialog is shown.
* 'ToolUseDesktopNotify': +
  option to use desktop notify dialogs for manual tool change dialog. +
* 'ToolFramesless': +
  Framesless dialogs can not be easily moved by users. +
* 'fileDialog_option': +
  sets up the file choosing dialog.
* 'file_overlay_color': +
  Color of transparent layer shown when the file dialog is shown.
* 'keyboardDialog_option': +
  sets up a keyboard entry widget. +
* 'keyboard_overlay_color': +
  Color of transparent layer shown when the keyboard dialog is shown.
* 'vesaProbe_option': +
  sets up the versa style probe dialog
* 'versaProbe_overlay_color': +
  Color of transparent layer shown when the versaProbe dialog is shown.
* 'macroTabeDialog_option': +
  sets up the macro selection dialog
* 'macoTab_overlay_color': +
  Color of transparent layer shown when the macroTab dialog is shown.
* 'camViewDialog_option': +
  sets up the camera alignment dialog
* 'camView_overlay_color': +
  Color of transparent layer shown when the camView dialog is shown.
* 'toolOffset_option': +
  sets up the tool offset display/editor dialog
* 'toolOffset_overlay_color': +
  Color of transparent layer shown when the toolOffset dialog is shown.
* 'originOffset_option': +
  sets up the origin display/editor dialog
* 'originOffset_overlay_color': +
  Color of transparent layer shown when the originOffset dialog is shown.
* 'calculatorDialog_option': +
  sets up the calcylatory entry dialog
* 'calculator_overlay_color': +
  Color of transparent layer shown when the calculator dialog is shown.
* 'machineLogDialog_option': +
  sets up a dialog to display logs from the machine and qtvcp
* 'machineLog_overlay_color': +
  Color of transparent layer shown when the machineLog dialog is shown.
* 'runFromLineDialog_option': +
  sets up a dialog to display starting options when starting machine
  execution from a arbitrary line. +
* 'runFromLine_overlay_color': +
  Color of transparent layer shown when the runFromLine dialog is shown.

==== Setting Properties Programically

The screen designer chooses the default settings of the screenOptions
widget.
Once chosen, most won't ever need to be changed.
but if needed some can be changed in the handler file or in stylesheets.
Some settings are only checked on startup so will not cause changes
after startup.
In these cases you would need to make the changes in Qtdesigner only.

ie. in the handler file
Here we reference the widget by the QtDesigner user defined name:

[source,python]
----
# red,green,blue,alpha 0-255
color = QtGui.QColor(0, 255, 0, 191)
self.w.screen_options.setProperty('close_overlay_color', color)
self.w.screen_options.setProperty('play_sounds_option',False)
----

ie. In style sheets
Here we can reference the widget by QtDesigner user defined name
or by widget class name.

----
/* red, green, blue 0-255, alpha 0-100% or 0.0 to 1.0 */
/* the # sign is used to refer to QtDesigner defined widget name */
/* matches/applied to only this named widget */

#screen_options {
qproperty-close_overlay_color: rgba(0, 255, 0, 0.75) }
----
----
/* red, green, blue 0-255, alpha 0-100% or 0.0 to 1.0 */
/* use widget class name - matches/applied to all widgets of this class*/

ScreenOptions {
qproperty-close_overlay_color: rgba(0, 255, 0, 0.75) }
----

==== Preference File Entries

If the preference file option is selected, screenOption widget will make
an INI based preference file.
While other QtVCP widgets will add to this list, the screenOptions widget
will add these entries:


Under the heading: 'SCREEN_OPTIONS':

* 'catch_errors =' -True or False
* 'desktop_notify =' -True or False (whether to display errors/messages
  in the system's notification mechanism)
* 'notify_max_msgs =' -Integer (number of displayed errors at one time)
* 'shutdown_check =' -True or False (whether to pop a confirmation dialog)
* 'sound_player_on =' -True or False (turns all sounds on or off)

Under the heading: 'MCH_MSG_OPTIONS'

* 'mchnMsg_play_sound =' -True or False (to play alert sound when dialog
  pops)
* 'mchnMsg_speak_errors =' -True or False (to use Espeak to speak error
  messages)
* 'mchnMsg_speak_text =' -True or False (to use Espeak to speak all other
  messages)
* 'mchnMsg_sound_type =' -sound to play when messages displayed

Under the heading: 'USER_MSG_OPTIONS'

* 'usermsg_play_sound =' -True or False (to play alert sound when dialog
  pops)
* 'userMsg_sound_type =' -sound to play when user messages displayed
* 'userMsg_use_focusOverlay =' -True or False

Under the heading: 'SHUTDOWN_OPTIONS'

* 'shutdown_play_sound =' -True or False
* 'shutdown_alert_sound_type =' -sound to play when messages displayed
* 'shutdown_exit_sound_type =' -sound to play when messages displayed
* 'shutdown_msg_title =' -Short title string to display in dialog
* 'shutdown_msg_focus_text =' -Large text string to superimpose in focus
  layer
* 'shutdown_msg_detail =' -Longer descriptive string to display in dialog

Under the heading: 'NOTIFY_OPTIONS'

* 'notify_start_greeting =' - True or False (whether to display a
  greeting dialog on start up)
* 'notify_start_title =' - Short Title string. If the speak option is
  also selected it will be spoken with Espeak.
* 'notify_start_detail =' - Longer description string.
* 'notify_start_timeout =' - time in seconds to display before closing.

[NOTE]
====
In Debian/Ubuntu/Mint based systems these sounds should be available as
sound-type entries above:
(These Sound options require python3-gst1.0 installed.)

* ERROR
* READY
* DONE
* ATTENTION
* RING
* LOGIN
* LOGOUT
* BELL

====

[NOTE]
You can also specify a file path to an arbitrary audio file.
(You can use ~ in path to substitute for the user home file path)

[NOTE]
====
If the Beep kernel module is installed and it is not disabled, these
sound-type entries are available:

* BEEP
* BEEP_RING
* BEEP_START

====

[NOTE]
====
If the Espeak module (python3-espeak) is install you can use the entry
'SPEAK' to pronounce text:

* SPEAK 'my message'

====

=== StatusSlider Widget

This widget allow the user to adjust LinuxCNC setting via a slide.

.The widget can adjust:
* Jog rate
* Angular jog rate
* Feed rate
* spindle override rate
* Rapid override rate

==== Properties

StatusSlider has properties that can be set in designer, in Python
handler code or (if appropriate) in stylesheets.

* halpin_option - sets option to make a HAL float pin that reflects
  current value.
* rapid_rate - selects a rapid override rate slider
* feed_rate - selects a feed override rate slider
* spindle_rate - selects a spindle override rate slider
* jograte_rate - selects a linear jograte slider
* jograte_angular_rate - selects a angular jograte slider
* max_velocity_rate - selects a maximum velocity rate slider
* alertState - a string to define style change. (read-only - 'under',
  'over' and 'normal')
* alertUnder - set the float value that signals the stylesheet for
  'under' warning.
* alertOver - set the float value that signals the stylesheet for 'over'
  warning.

ie. in handler file:

[source,python]
----
self.w.status_slider.setProperty('spindle_rate',True)
self.w.status_slider.setProperty('alertUnder',35)
self.w.status_slider.setProperty('alertOver',100)
----

ie. In style sheets:
----
/* warning colors for overrides if out of normal range*/
/* widget object name is slider_spindle_ovr */

    #slider_spindle_ovr[alertState='over'] {
        background: red;
    }
    #slider_spindle_ovr[alertState='under'] {
        background: yellow;
    }
----

It is based on PyQt's QSlider

=== State LED Widget

This widget gives status on the selected LinuxCNC state.

The state options are:

* is_paused_status
* is_estopped_status
* is_on_status
* is_idle_status_
* is_homed_status
* is_flood_status
* is_mist_status
* is_block_delete_status
* is_optional_stop_status
* is_joint_homed_status
* is_limits_overridden_status
* is_manual_status
* is_mdi_status
* is_auto_status
* is_spindle_stopped_status
* is_spindle_fwd_status
* is_spindle_rev_status
* is_spindle_at_speed_status

There are properties that can be changed:

* halpin_option - Adds an output pin that reflects selected state
* invert_state_status - Invert the LED state compared to the LinuxCNC
  state.
* diameter -Diameter of the LED
* color - Color of the LED when on.
* off_color - Color of the LED when off.
* alignment - Qt Aliment hint.
* state - Current state of LED (for testing in designer)
* flashing - Turns flashing option on and off.
* flashRate - Sets the flash rate.

The LED properties can be defined in a stylesheet with the following
code added to the .qss file.
The name_of_led would be the name defined Designer's editor.

----
State_LED #name_0f_led{
    qproperty-color: red;
    qproperty-diameter: 20;
    qproperty-flashRate: 150;
}
----

It is based on the LED widget

=== StatusAdjustmentBar

This widget allows setting values using buttons while displaying a bar.
It also has an optional hi/low toggle button that can be held down to
set the levels.

.The widget can adjust:
* Jog rate
* angular jog rate
* Feed rate
* Spindle override rate
* Rapid override rate

It is based on PyQt's QProgressBar

=== SystemToolButton
This widget allows you to manually select a user system by pressing and
holding.
If you don't set the button text it will automatically update to the
current system.

It is based on PyQt's QToolButton

=== MacroTab Widget

.Macrotab
image::images/qtvcp_macro.png["QtVCP led",scale="25%"]

This Widget allows a user to select and adjust special macro programs
for doing small jobs.
It uses images for visual representation of the macro and for an icon.
It searches for special macros using the INI definition:

[source,{ini}]
----
[RS274NGC]
SUBROUTINE_PATH =
----

The macros are Oword subroutine with special comments to work with the
launcher.
The first three lines must have the keywords: (The forth is optional)
Here is a sample for the first four lines in an Oword file:

----
; MACROCOMMAND=Entry1,Entry2
; MACRODEFAULTS=0,true
; MACROIMAGE=my_image.svg,Icon layer number, Macro layer number
; MACROOPTIONS=load:yes,save:yes,default:default.txt,path:~/macros
----

==== MACROCOMMAND

This is the first line in the Oword file.
It is a comma separated list of text to display above an entry.
There will be one for every variable required in the Oword function.
If the macro does not require variables, only add '; MACROCOMMAND='

==== MACRODEFAULT

This must be the second line in the Oword file.
It is a comma separated list of the default values for each variable in
the Oword function.
If you use the word 'true' or 'false' in the list, a checkbutton will be
shown.

==== MACROIMAGE

This must be the third line in the Oword file.
if using a SVG image file, the must end b .svg
The image must be added to an svg layer.
It uses layers to define different images for macro and icon.
The first entry will be the SVG image file name.
It is assumed to be in the same folder as the Oword file.
The second item will be the image layer.
the optional third entry will be the icon layer.
If the third entry is missing, the same image will be used for macro and
icon.

If using a png/jpg image file.
The first entry is the image filename.
It is assumed the image file are in the same folder an the macro.
The optional second entry will be the icon filename.
If the second entry is missing the same image will be used for macro and
image.

If the keyword is present but the entries are missing , no images will
be used.

==== MACRODEFAULT
This optional line must be the forth line in the Oword file.
It is a comma separated list of keyword and data.

 * 'LOAD:yes' - show a load button
 * 'SAVE:yes' -show a save button

=== MDILine Widget

One can enter MDI commands here. A popup keyboard is available.
There are also embedded commands available from this Widget.
Enter any of these case sensitive commands to load the respective
program or access the feature:

* `HALMETER` - Starts LinuxCNC utility
  link:../hal/tools.html#sec:halmeter[`halmeter`]
* `HALSHOW` - Starts LinuxCNC utility
  link:../hal/halshow.html#cha:halshow[`halshow`]
* `HALSCOPE` - Starts LinuxCNC utility
  link:../hal/tutorial.html#sec:tutorial-halscope[`halscope`]
* `STATUS` - Starts LinuxCNC utility
  link:../man/man1/linuxcnctop.1.html[`status`]
* `CALIBRATION` - Starts LinuxCNC utility
  link:../getting-started/updating-linuxcnc.html#_calibration_emccalib_tcl[`calibration`]
* `CLASSICLADDER` - Starts the
  link:../ladder/classic-ladder.html[ClassicLadder GUI] if the ClassicLadder realtime HAL component was loaded by the machine's config files
* `PREFERENCE` - Loads the preference file onto the gcodeEditor
* `CLEAR HISTORY` - Clears the MDI History
* `net` - See link:../man/man1/halcmd.1.html#COMMANDS[halcmd net COMMAND].
  An error will result if the command is unsuccessful.
** _Syntax_: `net <signal name> <pin name>`
** __Example__: `net plasmac:jog-inhibit motion.jog-stop`
* `setp` - Sets the value of a pin or a parameter. Valid values depend
  on the object type of the pin or parameter. An error will result if
  the data types do not match or the pin is connected to a signal.
** _Syntax_: `setp <pin/parameter-name> <value>`
** __Example__: `setp plasmac.resolution 100`
* `unlinkp` - Disconnects a pin from a signal. An error will result
  if the pin does not exist. Running LinuxCNC from terminal
  may help determine the root cause as error messages from hal_lib.c
  will be displayed there.
** _Syntax_: `unlinkp <pin name>`
** __Example__: `unlinkp motion.jog-stop`

Note that the MDILine function "spindle_inhibit" can be used by a GUI's
handler file to inhibit M3, M4, and M5 spindle commands if necessary.

It is based on PyQt's QLineEdit.

=== MDIHistory

Displays a scrollable list of past MDI command.
A edit line is embedded for MDI commands.
The same MDILine embedded commands may be accessed from this Widget.

The history is recorded in a file defined in the INI.
under the heading [DISPLAY] (this shows the default)

[source,{ini}]
----
MDI_HISTORY_FILE = '~/.axis_mdi_history'
----

=== MDITouchy

.MDI Touchy
image::images/qtvcp_mdiTouchy.png["QtVCP MDI Touchy",scale="25%"]

This widget display button and entry lines for use with entering MDI
commands.
It is based on Linuxcnc's Touchy screen's MDI entry process.
It's large buttons are most useful for touch screens.

To use MDITouchy, first press one of the 'G/XY', 'G/RO', 'M' or 'T'
button.
On the left, will show the current line that can be filled out, then
press 'Next' for the next line.
'Calc' will pop up a calculator dialog.
'Clear' clears th ecurrent entry.
'Back' allows you to change previous line entries.

The widget requires an explicied call to MDITouchu's Python code to
actually run the MDI command
For handler file code: if the widget was named mditouchy in designer,
this command would
run the displayed MDI command.

[source,python]
----
self.w.mditouchy.run_command()
----

For action button use: if the widget was named mditouchy in designer,
use the action button's 'Call Python commands' option and enter:

[source,python]
----
INSTANCE.mditouchy.run_command()
----

The macro button will cycle though macro's defined in the INI heading
[DISPLAY] add one or more 'MACRO = ' lines.  Each should be of the
format:

[source,{ini}]
----
MACRO = increment xinc yinc
----

In this example, increment is the name of the macro, and it accepts two
parameters, named xinc and yinc.

Now, place the macro in a file named 'increment.ngc', in the
'PROGRAM_PREFIX' directory or any directory in the 'SUBROUTINE_PATH'.
(specified in the INI file)

It should look like:

[source,{ngc}]
----
O<increment> sub
G91 G0 X#1 Y#2
G90
O<increment> endsub
----

Notice the name of the sub matches the file name and macro name exactly,
including case.

When you invoke the macro by pressing the Macro button
you can enter values for xinc and yinc.  These are
passed to the macro as '#1' and '#2' respectively.  Parameters you
leave empty are passed as value 0.

If there are several different macros, press the Macro button
repeatedly to cycle through them.

In this simple example, if you enter -1 for xinc and invoke the running
of the MDI cycle, a rapid 'G0' move will be invoked, moving one unit to
the left.

This macro capability is useful for edge/hole probing and other setup
tasks, as well as perhaps hole milling or other simple operations
that can be done from the panel without requiring specially-written
G-code programs.

=== OriginOffsetView Widget

.origin Offset View
image::images/qtvcp_originoffsetview.png["QtVCP Origin Offset View"]

This widget allows one to modify User System origin offsets directly
It will update LinuxCNC's Parameter file for changes made or found.
The settings can only be changed in LinuxCNC after homing and
when the motion controller is idle.
The display and entry will change between metric and imperial based
on LinuxCNC's current G20/G21 setting.
The current in-use user system will be highlighted
Extra actions can be integrated to manipulate settings.
These actions depend on extra code added either to a combined widget
like originoffsetview dialog or the screens handler code.
Typical actions might be 'Clear Current User offsets', 'Zero X'
Clicking on the columns and rows allows one to adjust the settings.
A dialog can be made to popup for data or text entry.
The comments section will be recorded in the preference file.

It is based on PyQt's QTableView, QAbstractTableModel, and
ItemEditorFactory.
Properties, functions and styles of the PyQt base objects are always
available.

==== Properties

OriginOffsetView has properties that can be set in designer, in Python
handler code or (if appropriate) in stylesheets.

* dialog_code_string - sets which dialog will pop up with numerical
  entry.
* test_dialog_code_string - sets which dialog will pop up with text
  entry.
* metric_template - metric numerical data format.
* imperial_template - imperial numerical data format.
* styleCodeHighlight - current in-use user system highlight color.

ie. in the handler file:

[source,python]
----
self.w.originoffsetview.setProperty('dialog_code','CALCULATOR')
self.w.originoffsetview.setProperty('metric_template','%10.3f')
----

ie. In style sheets:

----
OriginOffsetView{
  qproperty-styleColorHighlist: lightblue;
}
----

=== State Enable Gridlayout Widgets

This is a container that other widgets can be placed in.
It will 'grey-out' (disable) the widgets inside it depending on
LinuxCNC's current state.
It can selectably react to:

* machine on
* interpreter idle
* estop off
* all-homed

It is based on PyQt's QGridLayout

=== MachineLog

It is based on PyQt's

=== JointEnableWidget

It is based on PyQt's

=== StatusImageSwitcher

This widget will display images based on LinuxCNC status.
You can watch:

* the state of the spindle.
* the state of all homed
* the state of a certain axis homed
* the state of hard limits

It is based on PyQt's

=== FileManager

.FileManager
image::images/qtvcp_fileManager.png["QtVCP File Manager Widget",scale="25%"]

This widget is used to select files to load.
It has a the ability to scroll the names with hardware such as a MPG.

one can class patch the function 'load(self,fname):' to customize file
loading.

the function 'getCurrentSelected()' will return a Python tuple,
containing the file path and whether it's a file.

[source,python]
----
temp = FILEMANAGER.getCurrentSelected()
print('filepath={}'.format(temp[0]))
if temp[1]:
    print('Is a file')
----

It is based on PyQt's

=== RadioAxisSelector

It is based on PyQt's

=== ToolOffsetView

.Tool Offset View
image::images/qtvcp_tooloffsetview.png["QtVCP Tool Offset View"]

This widget will display and allows one to modify tool offsets
It will update LinuxCNC's tool table for changes made or found.
The tool settings can only be changed in LinuxCNC after homing and
when the motion controller is idle.
The display and entry will change between metric and imperial based
on LinuxCNC's current G20/G21 setting.
The current in-use tool will be highlighted
The current selected tool will be highlighted in a different color.
The checkbox beside each tool can be used to select a tool(s) for an
action.
This action depends on extra code added either to a combined widget like
tooloffsetview dialog or the screens handler code.
Typical actions are 'load selected tool', 'delete selected tools'
Clicking on the columns and rows allows one to adjust the settings.
A dialog can be made to popup for data or text entry.
The comments section will typically be displayed in the manual tool
change dialog.
If using a lathe configuration, there can be columns for X and Z wear.
To use these columns to adjust the tool for wear, requires a remapped
tool change routine.

It is based on PyQt's QTableView, QAbstractTableModel, and
ItemEditorFactory.
Properties, functions and styles of the PyQt base objects are always
available.

==== Properties

ToolOfsetView has properties that can be set in designer, in Python
handler code or (if appropriate) in stylesheets.

* dialog_code_string - sets which dialog will pop up with numerical entry.
* test_dialog_code_string - sets which dialog will pop up with text entry.
* metric_template - metric numerical data format.
* imperial_template - imperial numerical data format.
* styleCodeHighlight - current tool-in-use highlight color.
* styleCodeSelected - selected highlight color

ie. In handler file:

[source,python]
----
self.w.tooloffsetview.setProperty('dialog_code','CALCULATOR')
self.w.tooloffsetview.setProperty('metric_template','%10.3f')
----

ie. In style sheets:
----
ToolOffsetView{
    qproperty-styleColorHighlist: lightblue;
    qproperty-styleColorSelected: #444;
}
----

==== Functions

ToolOffsetView has some function that are useful for screen builders
to add actions.

* add_tool() - adds a blank dummy tool (99) that the user can edit to
  suit.
* delete_tools() - deletes the currently checkbox selected tools
* get_checked_list() - returns a list of tools selected by checkboxes.
* set_all_unchecked() - uncheck all selected tools.

[source,python]
----
self.w.tooloffsetview.add_tool()
self.w.tooloffsetview.delete_tools()
toolList = self.w.tooloffsetview.get_checked_list()
self.w.tooloffsetview.set_all_unchecked()
----

=== BasicProbe

.BasicProbe
image::images/qtvcp_basicProbe.png["QtVCP basicProbe widget",scale="25%"]

Widget for probing on a mill. Used by the QtDragon screen.


== Dialog Widgets

Dialogs are used to present or request immediately required information
in a focused way.
The typical used dialogs can be loaded using the screenoptions widget.
You can also add them directly to the ui - but each dialog must have a
unique launch name or you will see multiple dialogs displayed, one after
another.
You can show dialogs directly with Python code but a safer way is to use
STATUS messages to request the dialog to launch and to return the
gathered information.

To set this up first register to catch the 'general' message from STATUS:

[source,python]
----
STATUS.connect('general',self.return_value)
----

Add a function to call a dialog:
This function must build a message DICT to send to the dialog.
This message will be passed back in the general message with the addition
of the RETURN variable. It is possible to add extra user information to
the message.
The dialog will ignore these and pass them back.
'NAME' = launch code name of dialog to show.
'ID' = a unique id so we process only a dialog that we requested.
'TITLE' = the title to use on the dialog

[source,python]
----
        def show_dialog(self):
            mess = {'NAME':'ENTRY','ID':'__test1__',
                    'TITLE':'Test Entry'}
            ACTION.CALL_DIALOG, mess)
----

Add a callback function that processes the general message:
This function should check the the name and id is the same as
we sent, then it can extract the return value and any user variables.
Keep in mind this function will get all general messages so the DICT
keynames are not guaranteed to be there. Using the .get() function and
or using try/except is advisable.

[source,python]
----
    # process the STATUS return message
    def return_value(self, w, message):
        rtn = message.get('RETURN')
        code = bool(message.get('ID') == '__test1__')
        name = bool(message.get('NAME') == 'ENTRY')
        if code and name and not rtn is None:
            print('Entry return value from {} = {}'.format(code, rtn))
----


=== Lcnc_Dialog

This is a general message dialog widget.
If there is an Focus Overlay widget present, it can signal it to display.
If the sound library is set up it can play sounds.
There are options that can be set when requesting a dialog, these would
be added to the message dict.

* 'TITLE': 'Attention'      -Title of the dialog window
* 'MESSAGE': 'your text'    -Title message text in bold
* 'MORE': 'your more text' - standard text under the heading
* 'DETAILS': 'hidden text' - initial hidden text
* 'TYPE': 'OK' - type can be 'OK', 'YESNO', 'OKCANCEL'
* 'ICON': 'INFO' - icon can be 'QUESTION','INFO','CRITICAL','WARNING'
* 'PINNAME' - not implemented yet
* 'FOCUSTEXT':None - text to display if focus overlay is used. Use None for no text.
* 'FOCUSCOLOR':QColor(0, 0, 0, 150) - color to use if focus overlay is used
* 'PLAYALERT':'SPEAK alert!'- sound to play if sound is available

When using STATUS's 'request-dialog' function, the default launch name
is 'MESSAGE'.

It is based on PyQt's QMessagebox.

=== Dialog Tool Change Widget

.Manual Tool Change
image::images/qtvcp_toolChange.png["QtVCP Manual Tool Change Dialog",scale="25%"]

This is used as a manual tool change prompt.
It has HAL pins to connect to the machine controller.
The pins are named the same as the original AXIS manual tool prompt and
works the same.
the tool change dialog can only be launched by HAL pins.
If there is a Focus Overlay widget present, it will signal it to display.

It is based on PyQt's QMessagebox.

=== Dialog File Chooser Widget

.File Dialog
image::images/qtvcp_fileDialog.png["QtVCP file dialog",scale="25%"]

This is used to load G-code files.
If there is a Focus Overlay widget present, it will signal it to display.
When using STATUS's 'request-dialog' function, the default launch names
are 'LOAD' or 'SAVE'.

There are options that can be set when requesting a dialog, these would
be added to the message dict.

* EXTENSIONS
* FILENAME
* DIRECTORY

An example Python call, for a load dialog:

[source,python]
----
mess = {'NAME':'LOAD','ID':'_MY_DIALOG_',
            'TITLE':'Load Some text File',
            'FILENAME':'~/linuxcnc/nc_files/someprogram.txt',
            'EXTENSIONS':'Text Files (*.txt);;ALL Files (*.*)'
            }
ACTION.CALL_DIALOG(mess)
----

And for saving

[source,python]
----
mess = {'NAME':'SAVE','ID':'_MY_DIALOG_',
            'TITLE':'Save Some text File',
            'FILENAME':'~/linuxcnc/nc_files/someprogram.txt',
            'EXTENSIONS':'Text Files (*.txt);;ALL Files (*.*)'
            }
ACTION.CALL_DIALOG(mess)
----

It is based on PyQt's QMessagebox.

=== Dialog Origin Offset Widget

.Offsets
image::images/qtvcp_offsetpage.png["QtVCP origin Offset Page",scale="25%"]

This widget allows one to modify User System origin offsets directly.
It is in a dialog form.
If there is an Focus Overlay widget present, it will signal it to
display.
When using STATUS's 'request-dialog' function, the default launch name
is 'ORIGINOFFSET'.

It is based on PyQt's QDialog.

=== Dialog tool Offset Widget

.Tool Offsets
image::images/qtvcp_toolOffset.png["QtVCP Tool Offset Page",scale="25%"]

This widget allows one to modify Tool offsets directly.
It is in a dialog form.
If there is an Focus Overlay widget present, it will signal it to display.
When using STATUS's 'request-dialog' function, the default launch name
is 'TOOLOFFSET'.

It is based on PyQt's QDialog.

=== Dialog MacroTab

This is a dialog for displaying the macrotab widget.
Macrotab displays a choice of macro programs to run using icons.
If there is a Focus Overlay widget present, it will signal it to display.
When using STATUS's 'request-dialog' function, the default launch name
is 'MACROTAB'.

=== Dialog camview

This is a dialog to display the camview object for Webcam part alignment.
When using STATUS's 'request-dialog' function, the default launch name
is 'CAMVIEW'.
It is based on PyQt's QDialog.

=== Dialog entry

This is a dialog to display an edit line for information entry, such as
origin offset.
It returns the entry via STATUS messages using a Python dict.
The DICT contains at minimum, the name of the dialog requested and an id
code.
When using STATUS's 'request-dialog' function, the default launch name
is 'ENTRY'.

It is based on PyQt's QDialog

=== Dialog Calculator

.Calculator
image::images/qtvcp_calculator.png["QtVCP Calculator",scale="25%"]

This is a dialog to display a calculator for numeric entry, such as
origin offset.
It returns the entry via STATUS messages using a Python dict.
The DICT contains at minimum, the name of the dialog requested and an
id code.
When using STATUS's 'request-dialog' function, the default launch name
is 'CALCULATOR'.
It is based on PyQt's QDialog.

=== Dialog Run From Line

.Run-from-line Dialog
image::images/qtvcp_runFromLine.png["QtVCP Run-from-line",scale="25%"]

Dialog to preset  spindle settings before running a program from a
specific line.

=== Dialog VersaProbe

.Versa Probe Dialog
image::images/qtvcp_versaProbe.png["QtVCP Versa Probe",scale="25%"]

This is a dialog to display A probing screen based on Versa Probe.
It is based on PyQt's QDialog

=== Dialog MachineLogDialog

.Machine Log Dialog
image::images/qtvcp_machineLog.png["QtVCP MachineLog Dialog",scale="25%"]

This is a dialog to display the user machine log and qtvcp's debugging
log.
It is based on PyQt's QDialog

== Other

Other available widgets

=== Nurbs Editor

.Nurbs Editor
image::images/qtvcp_nurbsEditor.png["QtVCP nurbs editor",scale="25%"]

The Nurbs editor allows you to manipulate a nurbs based geometry on
screen and then
convert this to G-code. you can edit the G-code on screen and then send
it to LinuxCNC.

=== JoyPad

It is the base class for the HALPad widget.
This widget looks and acts like a 5 button D-pad, with an LED like
indicators in a ring.
You can put text or icons in each of the button positions.
You can connect to output signals when the buttons are pressed.
There are also input slots to change the color of the indicator(s).

==== ENUMS

There are enumerated constants used to reference indicator positions.
They are used in the Designer editor's property editor or used if using
Python code.

----
NONE
LEFT
RIGHT
CENTER
TOP
BOTTOM
LEFTRIGHT
TOPBOTTOM
----

For Python handler code, you use the widget Designer name plus the
reference constant.

[source,python]
----
self.w.joypadname.set_highlight(self.w.joypadname.LEFT)
----

==== Useful Override-able Functions

As coded they issue signals for the button pressed or released.
On signal outputs a string code for the button, one signal outputs a
bool value.

----
def _pressedOutput(self, btncode):
    self.joy_btn_pressed.emit(btncode)
    self['joy_{}_pressed'.format(btncode.lower())].emit(True)

def _releasedOutput(self, btncode):
    self.joy_btn_released.emit(btncode)
    self['joy_{}_pressed'.format(btncode.lower())].emit(False)
----

==== Callable Functions

* 'reset_highlight()': +
  Clears the highlight indicator.
* 'set_highlight(button, state=True)': +
  Set the highlight indicator in position 'button' to state 'state'
  You can use strings letters (LRCTBXA) or position ENUMS for the button
  argument.
* 'set_button_icon(button, pixmap)': +
  Sets the button's icon pixmap.
* 'set_button_text(button, text)': +
  Sets the button's icon text.
* 'set_tooltip(button, text)': +
  Sets the buttons popup tooltip descriptive text.
* 'setLight(state)':
  Sets the highlight indicator to the true color or false color.
  The set_highlight() function must be used prior to set the indicator
  to use.

==== signals

These signals will be sent when buttons are pressed.
They can be connected to in the Designer editor or Python code.
The first two output a string the indicates the button pressed.

----
joy_btn_pressed = QtCore.pyqtSignal(str)
joy_btn_released = QtCore.pyqtSignal(str)
joy_l_pressed = QtCore.pyqtSignal(bool)
joy_l_released = QtCore.pyqtSignal(bool)
joy_r_pressed = QtCore.pyqtSignal(bool)
joy_r_released = QtCore.pyqtSignal(bool)
joy_c_pressed = QtCore.pyqtSignal(bool)
joy_c_released = QtCore.pyqtSignal(bool)
joy_t_pressed = QtCore.pyqtSignal(bool)
joy_t_released = QtCore.pyqtSignal(bool)
joy_b_pressed = QtCore.pyqtSignal(bool)
joy_b_released = QtCore.pyqtSignal(bool)
----

==== slots

Slots can be connected to in the Designer editor or Python code.

----
set_colorStateTrue()
set_colorStateFalse()
set_colorState(bool)

set_true_color(str)
set_true_color(qcolor)

set_false_color(str)
set_false_color(qcolor)
----

==== Properties

These can be set in stylesheets or Python code to change it's properties.

* 'highlightPosition': +
  Set the indicator position.
* 'setColorState': +
  Select the color state of the indicator.
* 'left_image_path':
* 'right_image_path':
* 'center_image_path':
* 'top_image_path':
* 'bottom_image_path': +
  A file path or resource path to an image to display in the described
  button location.
  If the reset button is pressed in the Designer editor property, the
  image will not be displayed (allowing optionally text).
* 'left_text':
* 'right_text':
* 'center_text':
* 'top_text':
* 'bottom_text': +
  A text string to be displayed in the described button location.
  If left blank an image can be designated to be displayed.
* 'true_color':
* 'false_color': +
  Color selection for the center LED ring to be displayed when the
  'BASENAME.light.center' HAL pin is True or False.
* 'text_color': +
  Color selection for the button text.
* 'button_font': +
  Font selection for the button text.

===== StyleSheets

The above properties could be set in styles sheets.
You would usually use the designer widget name with '#' to set individual
widget properties, other wise you the class name 'JoyPad' to set all
JoyPad widgets the same.

----
#joypadname{
    qproperty-true_color: #000;
    qproperty-false_color: #444;
}
----

===== Python Code

[source,python]
----
self.w.joypadename.setProperty('true_color','green')
self.w.joypadename.setProperty('false_color','red')
----

== BaseClass/Mixin widgets
These widgets are used combine different properties and behaviours into
other widgets. You will seem them as a collapsible header in the Designer
 properties column.

=== IndicatedPushButtons
This class modifies QPushButton behaviour.

==== Indicator Option
Indicator_option puts a 'LED' on the top of the button.
It can be a triangle, circle, top bar or side bar.
The size and position can be adjusted
It will indicated the current state of the button, the state of a HAL
pin or LinuxCNC status.
Use properties to customized the indicator (not all are applicable to
every LED shape).

----
on_color
off_color
indicator_size
circle_diameter
shape_option
right_edge_offset
top_edge_offset
height_fraction
width_fraction
corner_radius
----

The LED indicator color can be defined in a stylesheet with the following
code added to the .qss file.

----
Indicated_PushButton{
    qproperty-on_color: #000;
    qproperty-off_color: #444;
}
----

or for a particular button:

----
Indicated_PushButton #button_estop{
    qproperty-on_color: black;
    qproperty-off_color: yellow;
}
----

Indicated PushButtons have exclusive options:

* indicator_HAL_pin_option
* indicator_status_option

Indicator_HAL_pin_option will add a halpin, using the button name +
'-led', that controls the button indicator state.

indicator_status_option will make the LED indicate the state of these
selectable LinuxCNC status:

----
Is Estopped
Is On
All Homed
Is Joint Homed
Idle
Paused
Flood
Mist
Block Delete
Optional Stop
Manual
MDI
Auto
Spindle Stopped
Spindle Fwd
Spindle Reverse
On Limits
----

The some indicator_status_options holds a property that can be used with
a stylesheet to change the color of the button based on the state of the
property in LinuxCNC.
Currently these status options can be used to auto style buttons:

* 'is_estopped_status' will toggle the property 'isEstop'
* 'is_on_status' will toggle the property 'isStateOn'
* 'is_manual_status,is_mdi_status,is_auto_status' will toggle the
'isManual, isMDI, isAuto'  properties.
* 'is_homed_status' will toggle the 'isAllHomed' property

Here is a sample stylesheet entry.
It sets the background of mode button widgets when LinuxCNC is in that
mode.

----
ActionButton[isManual=true] {
    background: red;
}
ActionButton[isMdi=true] {
    background: blue;
}
ActionButton[isAuto=true] {
    background: green;
}
----

Here is how you specify a particular widget - by it's objectName in
designer.

----
ActionButton #estop button [isEstopped=false] {
    color: yellow;
}
----

=== Enabled by linuxcnc state
Often having the button disabled and enabled based on the state of 
linuxcnc's motion controller is necessary.
There are several properties that can be selected to aid with this:

* 'isAllHomedSentive'
* 'isOnSensitive'
* 'isIdleSensitive'
* 'isRunSensitive'
* 'isManSensitive'
* 'isMDISensitive'
* 'isAitoSensitive'

You can select multiple properties for combined requirements.

==== Text changes on state

Choosing the checked_state_text_option allows a 'checkable' button to
change the text based on it's checked state. It uses the properties
'true_state_string' and 'false_state_string' to specify the text for
each state.

'\\n' will be converted to a newline.

You can set/change these in style sheets:

----
ActionButton #action_aux{
    qproperty-true_state_string: "Air\\nOn";
    qproperty-false_state_string: "Air\\nOff";
}
----

==== Call Python commands on state

The python_command_option allow small snippets of Python code to be run
from the push of a button, with out having to edit the handler file.
(though it can call functions in the handler file)
When using the command_string properties.

* 'true_python_cmd_string' - a python command that will be called when
  the button is toggled true
* 'false_python_cmd_string' - a python command that will be called when
  the button is toggled false

The capitalized word 'INSTANCE' will give access to the widgets instances
and handler functions. eg. 'INSTANCE.my_handler_function_call(True)'. +
The capitalized word 'ACTION' will give access to qtvcp's ACTION library.
eg. 'ACTION.TOGGLE_FLOOD()'. +
The capitalized word 'PROGRAM_LOADER' will give access to qtvcp's
PROGRAM_LOADER library. eg. 'PROGRAM_LOADER.load_halshow()'. +
The capitalized word 'HAL' will give access to HAL's python module,
e.g., 'HAL.set_p('motion.probe-input','1')'.


== Import only Widgets
These widgets are usually the base class widget for other QtVCP widgets.
They are not available directly from the Designer editor but could be
imported and manually inserted in the handler file.
They could also be subclassed to make a similar widget with new features.

=== Auto Height
Widget for measuring two heights with a probe. For setup

=== Gcode Utility
Widgets for preforming common machining processes.

=== Facing
Slab or face a definable area with different strategies

=== Hole Cicle
Drill multiple holes on a bolt hole circle

=== Qt NGCGUI
QtVcp's version of NGC subroutine selector.

=== Qt PDF
Allows adding loadable PDFs to a screen

=== Qt Vismach
Use this to build/add OpenGl simulated machines


// vim: set syntax=asciidoc:
