Example #1
0
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
Example #2
0
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)
Example #3
0
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))
Example #4
0
#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)
Example #5
0
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')
Example #6
0
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