Otherwise you will need to install LinuxCNC 2.8, info on how to do that can be found here: https://gnipsel.com/linuxcnc/uspace/ """.strip() INSTALLED_ERROR_MSG = """ \033[31mERROR:\033[0m Can not edit an installed VCP The specified VCP appears to be installed in the `python2.7/site-packages` directory. Please set up a development install to edit the VCP. """.strip() if linuxcnc.version.startswith('2.7'): print LCNC_VERSION_ERROR_MSG.format(linuxcnc.version) sys.exit(1) LOG = initBaseLogger('qtpyvcp', log_file=os.devnull, log_level='WARNING') def launch_designer(opts=DotDict()): if not opts.vcp and not opts.ui_file: fname, _ = QFileDialog.getOpenFileName( parent=None, caption="Choose VCP to Edit in QtDesigner", filter= "VCP Config Files (*.yml *.yaml);;VCP UI Files (*.ui);;All Files (*)", options=QFileDialog.Options() | QFileDialog.DontUseNativeDialog) if not fname: sys.exit(1)
sys.exit() import qtpy if qtpy.API != 'pyqt5': print( "ERROR: You must use the PyQt5 bindings in order to use the custom \n" "widgets in QtDesigner.") sys.exit() os.environ['DESIGNER'] = 'true' from qtpyvcp.utilities.logger import initBaseLogger LOG = initBaseLogger("qtpyvcp-designer", log_level=os.getenv('QTPYVCP_LOG_LEVEL', 'ERROR'), log_file=os.getenv( 'QTPYVCP_LOG_FILE', os.path.expanduser('~/qtpyvcp-designer.log'))) from qtpyvcp import CONFIG, DEFAULT_CONFIG_FILE os.environ['VCP_CONFIG_FILES'] = os.getenv('VCP_CONFIG_FILES', '') + \ ':' + DEFAULT_CONFIG_FILE from qtpyvcp.utilities.config_loader import load_config_files_from_env CONFIG.update(load_config_files_from_env()) from qtpyvcp.app.launcher import loadPlugins loadPlugins(CONFIG['data_plugins'])
from qtpy import API from qtpy.QtCore import QTimer, Slot, Qt from qtpy.QtWidgets import QApplication, QStyleFactory import qtpyvcp from qtpyvcp.utilities.logger import initBaseLogger from qtpyvcp.plugins import getPlugin from qtpyvcp.widgets.base_widgets.base_widget import QtPyVCPBaseWidget from qtpyvcp.widgets.form_widgets.main_window import VCPMainWindow # initialize logging. If a base logger was already initialized in a startup # script (e.g. vcp_launcher.py), then that logger will be returned, otherwise # this will initialise a base logger with default log level of DEBUG LOG = initBaseLogger('qtpyvcp') # Needed to silence this PySide2 warning: # Qt WebEngine seems to be initialized from a plugin. Please set # Qt::AA_ShareOpenGLContexts using QCoreApplication::setAttribute # before constructing QGuiApplication. if API == 'pyside2': from qtpy.QtCore import Qt QApplication.setAttribute(Qt.AA_ShareOpenGLContexts) class VCPApplication(QApplication): def __init__(self, theme=None, stylesheet=None): app_args = (qtpyvcp.OPTIONS.command_line_args or "").split() super(VCPApplication, self).__init__(app_args)
# pydevd.settrace() from io import TextIOWrapper from subprocess import Popen, PIPE, STDOUT from pkg_resources import iter_entry_points from docopt import docopt from qtpy.QtWidgets import QApplication, QFileDialog from qtpyvcp.lib.types import DotDict from qtpyvcp.utilities.logger import initBaseLogger from linuxcnc import version as lcnc_version LOG = initBaseLogger('EditVCP', log_file=None, log_level='DEBUG') DESIGNER_LOG = initBaseLogger('Designer', log_file=None, log_level='DEBUG') LCNC_VERSION_ERROR_MSG = """ \033[31mERROR:\033[0m Unsupported LinuxCNC version QtPyVCP only supports LinuxCNC 2.8, current version is {}. If you have LinuxCNC installed as a RIP make sure you have activated the run-in-place environment by running:\n" $ . <linuxcnc-rip-dir>/scripts/rip-environment Otherwise you will need to install LinuxCNC 2.8, info on how to do that can be found here: https://gnipsel.com/linuxcnc/uspace/ """.strip()
def parse_opts(doc=__doc__, vcp_name='NotSpecified', vcp_cmd='notspecified', vcp_version=None): # LinuxCNC passes the INI file as `-ini=inifile` which docopt sees as a # short argument which does not support an equals sign, so we loop thru # and add another dash to the ini argument if needed. for index, item in enumerate(sys.argv): if item.startswith('-ini'): sys.argv[index] = '-' + item break version_str = 'QtPyVCP {}'.format(QTPYVCP_VERSION) if vcp_version is not None: version_str += ', {} v{}'.format(vcp_name, vcp_version) doc = doc.format(vcp_name=vcp_name, vcp_cmd=vcp_cmd) raw_args = docopt(doc, version=version_str) def convType(val): if isinstance(val, basestring): if val.lower() in ['true', 'on', 'yes', 'false', 'off', 'no']: return val.lower() in ['true', 'on', 'yes'] try: return int(val) except ValueError: pass try: return float(val) except ValueError: pass return val # convert raw argument dict keys to valid python attribute names opts = DotDict({ arg.strip('-<>').replace('-', '_'): convType(value) for arg, value in raw_args.items() }) # read options from INI file and merge with cmd line options ini_file = ini( normalizePath(opts.ini, os.path.expanduser('~/linuxcnc/configs'))) for k, v in opts.iteritems(): ini_val = ini_file.find('DISPLAY', k.upper().replace('-', '_')) if ini_val is None: continue # convert str values to bool if type(v) == bool: # TODO: Find a way to prefer cmd line values over INI values ini_val = ini_val.lower() in ['true', 'on', 'yes', '1'] # if its a non bool value and it was specified on the cmd line # then prefer the cmd line value elif v is not None: continue opts[k] = convType(ini_val) # Check if LinuxCNC is running if not os.path.isfile('/tmp/linuxcnc.lock'): # LinuxCNC is not running. # TODO: maybe launch LinuxCNC using subprocess? print 'LinuxCNC must be running to launch a VCP' sys.exit() # setup the environment variables ini_file = os.environ.get('INI_FILE_NAME') or opts.ini if ini_file is None: print 'LinuxCNC is running, but you must specify the INI file' sys.exit() if not os.getenv('INI_FILE_NAME'): base_path = os.path.expanduser('~/linuxcnc/configs') ini_file = os.path.realpath(normalizePath(ini_file, base_path)) if not os.path.isfile(ini_file): print 'Specified INI file does not exist: {}'.format(ini_file) sys.exit() os.environ['INI_FILE_NAME'] = ini_file os.environ['CONFIG_DIR'] = os.path.dirname(ini_file) if opts.qt_api: os.environ['QT_API'] = opts.qt_api if opts.config_file is not None: # cmd line config file should be relative to INI file config_dir = os.getenv('CONFIG_DIR', '') config_file_path = normalizePath(opts.config_file, config_dir) if not os.path.isfile(config_file_path): print 'Specified YAML file does not exist: {}'.format( config_file_path) sys.exit() opts.config_file = config_file_path # show the chooser if the --chooser flag was specified if opts.chooser or not opts.get('vcp', True): from qtpyvcp.vcp_chooser import VCPChooser from qtpy.QtWidgets import QApplication, qApp app = QApplication([]) result = VCPChooser(opts).exec_() if result == VCPChooser.Rejected: sys.exit() # destroy the evidence qApp.deleteLater() del app # normalize log file path log_file = normalizePath(opts.log_file, os.getenv('CONFIG_DIR') or os.getenv('HOME')) if log_file is None or os.path.isdir(log_file): log_file = os.path.expanduser('~/qtpyvcp.log') opts.log_file = log_file # init the logger from qtpyvcp.utilities import logger LOG = logger.initBaseLogger('qtpyvcp', log_file=opts.log_file, log_level=opts.log_level or "INFO") LOG.info("QtPyVCP Version: %s", QTPYVCP_VERSION) if LOG.getEffectiveLevel() == logger.LOG_LEVEL_MAPPING['DEBUG']: import qtpy LOG.debug("Qt Version: %s", qtpy.QT_VERSION) LOG.debug("Qt API: %s", qtpy.QT_API) LOG.debug("QtPy Version: %s", qtpy.__version__) LOG.debug("Command line options:\n%s", json.dumps(opts, sort_keys=True, indent=4)) return opts
def apply_opts(opts): # read options from INI file and merge with cmd line options ini_file = normalizePath(opts.ini, os.path.expanduser('~/linuxcnc/configs')) ini_obj = ini(ini_file) for k, v in opts.iteritems(): ini_val = ini_obj.find('DISPLAY', k.upper().replace('-', '_')) if ini_val is None: continue # convert str values to bool if type(v) == bool: # TODO: Find a way to prefer cmd line values over INI values ini_val = ini_val.lower() in ['true', 'on', 'yes', '1'] # if its a non bool value and it was specified on the cmd line # then prefer the cmd line value elif v is not None: continue # If a VCP is specified in the INI as a .ui or .yaml file the path # should be relative to the config dir rather then the $PWD. if k.lower() == 'vcp' and ini_val.lower().split('.')[-1] in ['ui', 'yml', 'yaml']: ini_val = normalizePath(ini_val, os.path.dirname(ini_file)) opts[k] = convType(ini_val) # Check if LinuxCNC is running if not os.path.isfile('/tmp/linuxcnc.lock'): # LinuxCNC is not running. # TODO: maybe launch LinuxCNC using subprocess? print 'LinuxCNC must be running to launch a VCP' sys.exit() # setup the environment variables ini_file = os.environ.get('INI_FILE_NAME') or opts.ini if ini_file is None: print 'LinuxCNC is running, but you must specify the INI file' sys.exit() if not os.getenv('INI_FILE_NAME'): base_path = os.path.expanduser('~/linuxcnc/configs') ini_file = os.path.realpath(normalizePath(ini_file, base_path)) if not os.path.isfile(ini_file): print 'Specified INI file does not exist: {}'.format(ini_file) sys.exit() os.environ['INI_FILE_NAME'] = ini_file os.environ['CONFIG_DIR'] = os.path.dirname(ini_file) if opts.qt_api: os.environ['QT_API'] = opts.qt_api if opts.config_file is not None: # cmd line config file should be relative to INI file config_dir = os.getenv('CONFIG_DIR', '') config_file_path = normalizePath(opts.config_file, config_dir) if not os.path.isfile(config_file_path): print 'Specified YAML file does not exist: {}'.format(config_file_path) sys.exit() opts.config_file = config_file_path # show the chooser if the --chooser flag was specified if opts.chooser or not opts.get('vcp', True): from qtpyvcp.vcp_chooser import VCPChooser from qtpy.QtWidgets import QApplication, qApp app = QApplication([]) result = VCPChooser(opts).exec_() if result == VCPChooser.Rejected: sys.exit() # destroy the evidence qApp.deleteLater() del app # normalize log file path log_file = normalizePath(opts.log_file, os.getenv('CONFIG_DIR') or os.getenv('HOME')) if log_file is None or os.path.isdir(log_file): log_file = os.path.expanduser('~/qtpyvcp.log') opts.log_file = log_file # init the logger from qtpyvcp.utilities import logger LOG = logger.initBaseLogger('qtpyvcp', log_file=opts.log_file, log_level=opts.log_level or "INFO") LOG.info("QtPyVCP Version: %s", QTPYVCP_VERSION) if LOG.getEffectiveLevel() == logger.logLevelFromName("DEBUG"): import qtpy LOG.debug("Qt Version: %s", qtpy.QT_VERSION) LOG.debug("Qt API: %s", qtpy.QT_API) LOG.debug("QtPy Version: %s", qtpy.__version__) LOG.debug("Command line options:\n%s", json.dumps(opts, sort_keys=True, indent=4)) return opts