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) if raw_args.get('--info'): printSystemInfo() sys.exit() # convert raw argument dict keys to valid python attribute names opts = DotDict({arg.strip('-<>').replace('-', '_') : convType(value) for arg, value in raw_args.items()}) return opts
def main(): raw_args = docopt(__doc__) # convert raw argument keys to valid python names opts = DotDict({arg.strip('-<>').replace('-', '_'): value for arg, value in raw_args.items()}) app = QApplication(sys.argv) launch_designer(opts)
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) else: fname = opts.vcp or opts.ui_file if not '.' in fname or not '/' in fname: entry_points = {} for entry_point in iter_entry_points(group='qtpyvcp.example_vcp'): entry_points[entry_point.name] = entry_point for entry_point in iter_entry_points(group='qtpyvcp.vcp'): entry_points[entry_point.name] = entry_point try: vcp = entry_points[fname.lower()].load() fname = vcp.VCP_CONFIG_FILE except KeyError: pass if 'lib/python2.7/site-packages' in fname: print INSTALLED_ERROR_MSG sys.exit(1) cmd = ['designer'] ext = os.path.splitext(fname)[1] if ext in ['.yml', '.yaml']: print "Loading YAML config file:", fname from qtpyvcp import CONFIG, DEFAULT_CONFIG_FILE from qtpyvcp.utilities.config_loader import load_config_files try: CONFIG.update(load_config_files(fname, DEFAULT_CONFIG_FILE)) data = CONFIG.get('qtdesigner') except: print "Error loading YAML config file:" raise from qtpyvcp.utilities.settings import addSetting for k, v in CONFIG['settings'].items(): addSetting(k, **v) # add to path so that QtDesginer can load it when it starts os.environ['VCP_CONFIG_FILES'] = fname + ':' + os.getenv( 'VCP_CONFIG_FILES', '') if data is not None: yml_dir = os.path.realpath(os.path.dirname(fname)) # prefer command line ui file ui_file = opts.ui_file or data.get('ui_file') if ui_file is not None: ui_file = os.path.join(yml_dir, ui_file) cmd.append(ui_file) print "Loading UI file:", ui_file else: print "No UI file specified." # prefer command line qss file qss_file = opts.qss_file or data.get('qss_file') if qss_file is not None: qss_file = os.path.join(yml_dir, qss_file) os.environ['QSS_STYLESHEET'] = qss_file print "Loading QSS file:", qss_file else: print "No QSS file specified." elif ext == '.ui': cmd.append(fname) print "Loading UI file:", fname else: print "No valid file type selected.\n " \ "File must be a .yaml config file or a .ui file." sys.exit() base = os.path.dirname(__file__) sys.path.insert(0, base) os.environ['QTPYVCP_LOG_FILE'] = opts.log_file os.environ['QTPYVCP_LOG_LEVEL'] = opts.log_level os.environ['QT_SELECT'] = 'qt5' os.environ['PYQTDESIGNERPATH'] = os.path.join(base, '../widgets') print "\nStarting QtDesigner ..." sys.exit(subprocess.call(cmd))
#import sys;sys.path.append(r'/root/.p2/pool/plugins/org.python.pydev.core_7.5.0.202001101138/pysrc') #import pydevd;pydevd.settrace() import os from qtpyvcp.lib.types import DotDict from ._version import get_versions __version__ = get_versions()['version'] del get_versions QTPYVCP_DIR = os.path.abspath(os.path.dirname(__file__)) TOP_DIR = os.path.dirname(QTPYVCP_DIR) DEFAULT_CONFIG_FILE = os.path.join(QTPYVCP_DIR, 'yaml_lib/default_config.yml') # globals CONFIG = {} OPTIONS = DotDict() DIALOGS = {} WINDOWS = {} SETTINGS = {} # for backward compatibility from qtpyvcp.app import run def run_vcp(*args, **kwargs): run(*args, **kwargs)
def launch_designer(opts=DotDict()) -> None: 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) else: fname = opts.vcp or opts.ui_file if '.' not in fname or '/' not in fname: entry_points = {} for entry_point in iter_entry_points(group='qtpyvcp.example_vcp'): entry_points[entry_point.name] = entry_point for entry_point in iter_entry_points(group='qtpyvcp.vcp'): entry_points[entry_point.name] = entry_point try: vcp = entry_points[fname.lower()].load() fname = vcp.VCP_CONFIG_FILE except KeyError: pass if 'lib/python2.7/site-packages' in fname: LOG.error(INSTALLED_ERROR_MSG) sys.exit(1) cmd = ['designer'] ext = os.path.splitext(fname)[1] if ext in ['.yml', '.yaml']: LOG.info(f"Loading YAML config file: {fname}") from qtpyvcp import CONFIG, DEFAULT_CONFIG_FILE from qtpyvcp.utilities.config_loader import load_config_files try: CONFIG.update(load_config_files(fname, DEFAULT_CONFIG_FILE)) data = CONFIG.get('qtdesigner') except Exception as e: LOG.error("Error loading YAML config file:") LOG.error(e) raise from qtpyvcp.utilities.settings import addSetting for k, v in list(CONFIG['settings'].items()): addSetting(k, **v) # add to path so that QtDesginer can load it when it starts config_file = f"{fname}:{os.getenv('VCP_CONFIG_FILES', '')}" os.environ['VCP_CONFIG_FILES'] = config_file if data is not None: yml_dir = os.path.realpath(os.path.dirname(fname)) # prefer command line ui file ui_file = opts.ui_file or data.get('ui_file') if ui_file is not None: ui_file = os.path.join(yml_dir, ui_file) cmd.append(ui_file) LOG.info(f"Loading UI file: {ui_file}") else: LOG.info("No UI file specified.") # prefer command line qss file qss_file = opts.qss_file or data.get('qss_file') if qss_file is not None: qss_file = os.path.join(yml_dir, qss_file) os.environ['QSS_STYLESHEET'] = qss_file LOG.info(f"Loading QSS file: {qss_file}") else: LOG.info("No QSS file specified.") elif ext == '.ui': cmd.append(fname) LOG.info(f"Loading UI file: {fname}") else: LOG.error("""No valid file type selected.\n File must be a .yaml config file or a .ui file.""") sys.exit() base = os.path.dirname(__file__) sys.path.insert(0, base) os.environ['QTPYVCP_LOG_FILE'] = opts.log_file os.environ['QTPYVCP_LOG_LEVEL'] = opts.log_level os.environ['QT_SELECT'] = 'qt5' os.environ['PYQTDESIGNERPATH'] = os.path.join(base, '../widgets') LOG.info("Starting QtDesigner ...") try: process = Popen(cmd, stdout=PIPE, stderr=STDOUT) with process.stdout: log_subprocess_output(process.stdout) exitcode = process.wait() # 0 means success except OSError as exception: LOG.error("""Designer not found, Install with\n sudo apt install qttools5-dev qttools5-dev-tools""") LOG.error(f'Exception occured: {exception}') LOG.error('Subprocess failed') return False else: # no exception was raised LOG.info('EditVCP finished')
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