Source code for qtpyvcp.widgets.button_widgets.subcall_button

import os
import re
from qtpy.QtWidgets import qApp
from qtpy.QtCore import Property

from import Info
INFO = Info()

from qtpyvcp.widgets import VCPButton
from qtpyvcp.actions.machine_actions import issue_mdi

from qtpyvcp.utilities import logger
LOG = logger.getLogger(__name__)

# input: #<param_name> = #1 (=0.125 comment)
# result: [("param_name", "1", "0.125", "comment")]
# if a group is not present it will be an empty string
PARSE_POSITIONAL_ARGS = re.compile(r' *# *<([a-z0-9_-]+)> *= *#([0-9]+) *(?:\(= *([0-9.+-]+[0-9.]*?|) *(.*)\))?', re.I)

SUBROUTINE_SEARCH_DIRS = INFO.getSubroutineSearchDirs()

[docs]class SubCallButton(VCPButton): """Button for calling ngc subroutines. Args: parent (QWidget, optional) : The parent widget of the button, or None. filename (str, optional) : The filename of the NGCGUI style subroutine the button should call, including any extension. The subroutine must be on the subroutine path specified in the INI. The name of the subroutine must match exactly the sub/endsub name. The parameter #<parameter1> if found in the VCP the value from that widget will be used instead of the default value. If you don't have a default value you must have a widget by the same name. The widget can be a line edit, a spin box or a double spin box. :: example.ngc o<example> sub #<parameter1> = #1 #<parameter2> = #2 (=default_value) ;Body of the subroutine o<example> endsub """ def __init__(self, parent=None, filename=''): super(SubCallButton, self).__init__(parent) self._filename = filename issue_mdi.bindOk(widget=self) self.clicked.connect(self.callSub) def callSub(self): window = qApp.activeWindow() subfile = None for dir in SUBROUTINE_SEARCH_DIRS: subfile = os.path.join(dir, self._filename) if os.path.isfile(subfile): break if subfile is None: LOG.error('Subroutine file could not be found: yellow<{}>'.format(self._filename)) return False with open(subfile, 'r') as fh: lines = fh.readlines() args = [] for line in lines: line = line.strip() if not line.startswith('#'): continue result_list = PARSE_POSITIONAL_ARGS.findall(line) if len(result_list) == 0: continue pname, pnumber, default_val, comment = result_list[0] if int(pnumber) > 30: # only #1-#30 are passed to the sub continue try: # get the value from the GUI input widget val = getattr(window, pname).text() or default_val except: val = default_val LOG.warning('No input for red<{}> parameter, using default value blue<{}>'.format(pname, val)) if val == '': LOG.error('No value given for parameter red<{}>, and no default specified'.format(pname)) return False try: val = float(val) except ValueError: LOG.error('Input value "{}" given for parameter "{}" is not a valid number'.format(val, pname)) return False index = int(pnumber) - 1 while len(args) <= index: args.append("[0.0000]") args[index] = "[{}]".format(val) arg_str = ' '.join(args) sub_name = os.path.splitext(self._filename)[0] cmd_str = "o<{}> call {}".format(sub_name, arg_str) LOG.debug('Calling sub file: yellow<%s> with args blue<%s>', subfile, arg_str) issue_mdi(cmd_str) @Property(str) def filename(self): """Gets or sets the filename of the subroutine the button should call (str). The subroutine file must be on the subroutine path as specified in the INI. """ return self._filename @filename.setter def filename(self, filename): self._filename = filename
if __name__ == "__main__": import sys from qtpy.QtWidgets import QApplication app = QApplication(sys.argv) w = SubCallButton() sys.exit(app.exec_())