Skip to content

Commit f49bda3

Browse files
committed
qtvcp -docs: add writeup on preferred way to add custom code to screens.
earlier we promoted instance patching but handler sub classing is much better.
1 parent f7187cc commit f49bda3

1 file changed

Lines changed: 55 additions & 0 deletions

File tree

docs/src/gui/qtvcp.adoc

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,10 +232,65 @@ State_LED #name_of_led{
232232
}
233233
----
234234

235+
==== Handler Patching
236+
We can have QtVCP load a subclassed version of the standard handler file. in that file we can manipulate the original functions or add new ones. +
237+
Subclassing just means our handler file first loads the original handler file and adds our new code on top of it - so a patch of changes. +
238+
This is useful for changing/adding behaviour while still retaining standard handler updates from LinuxCNC repositories. +
239+
240+
You may still need to use the handler copy dialog to copy the original handler file to decide how to patch it.
241+
See 'custom handler file'
242+
243+
There should be a folder in the config folder; for screens: named '<CONFIG FOLDER>/qtvcp/screens/<SCREEN NAME>/' +
244+
add the handle patch file there, named like so <ORIGINAL SCREEN NAME>_handler.py +
245+
ie for Qtdragon the file would be caller 'qtdragon_handler.py' +
246+
247+
Here is a sample to add X axis jog pins to a screen like Qtdragon: +
248+
249+
[source,python]
250+
----
251+
import sys
252+
import importlib
253+
from qtvcp.core import Path, Qhal, Action
254+
PATH = Path()
255+
QHAL = Qhal()
256+
ACTION = Action()
257+
258+
# get reference to original handler file so we can subclass it
259+
sys.path.insert(0, PATH.SCREENDIR)
260+
module = "{}.{}_handler".format(PATH.BASEPATH,PATH.BASEPATH)
261+
mod = importlib.import_module(module, PATH.SCREENDIR)
262+
sys.path.remove(PATH.SCREENDIR)
263+
HandlerClass = mod.HandlerClass
264+
265+
# return our subclassed handler object to QtVCP
266+
def get_handlers(halcomp, widgets, paths):
267+
return [UserHandlerClass(halcomp, widgets, paths)]
268+
269+
# sub class HandlerClass which was imported above
270+
class UserHandlerClass(HandlerClass):
271+
# add a terminal message so we know this got loaded
272+
print('\nCustom subclassed handler patch loaded.\n')
273+
274+
def init_pins(self):
275+
# call original handler init_pins function
276+
super().init_pins()
277+
278+
# add jog pins X axis
279+
pin = QHAL.newpin("jog.axis.jog-x-plus", QHAL.HAL_BIT, QHAL.HAL_IN)
280+
pin.value_changed.connect(lambda s: self.kb_jog(s, 0, 1, fast = False, linear = True))
281+
282+
pin = QHAL.newpin("jog.axis.jog-x-minus", QHAL.HAL_BIT, QHAL.HAL_IN)
283+
pin.value_changed.connect(lambda s: self.kb_jog(s, 0, -1, fast = False, linear = True))
284+
----
285+
235286
==== Minor Python Code Changes
287+
236288
Another Python file can be used to *add commands* to the screen, after the handler file is parsed.
237289
This can be useful for minor changes while still honouring standard handler updates from LinuxCNC repositories.
238290

291+
[NOTE]
292+
Handler patching is a better way to add changes - instance patching is black magic voodoo - this is here for legacy reasons.
293+
239294
In the _INI file_ under the `[DISPLAY]` heading add *`USER_COMMAND_FILE = _PATH_`* +
240295
_PATH_ can be any valid path.
241296
It can use `~` for home directory or `WORKINGFOLDER` or `CONFIGFOLDER` to represent QtVCP's idea of those directories:

0 commit comments

Comments
 (0)