def __init__(self): sys.excepthook = self.excepthook INIPATH = None INITITLE = INFO.TITLE INIICON = INFO.ICON usage = "usage: %prog [options] myfile.ui" parser = OptionParser(usage=usage) parser.disable_interspersed_args() parser.add_options(options) # remove [-ini filepath] that linuxcnc adds if being launched as a screen # keep a reference of that path for i in range(len(sys.argv)): if sys.argv[i] =='-ini': # delete -ini del sys.argv[i] # pop out the ini path INIPATH = sys.argv.pop(i) break (opts, args) = parser.parse_args() # so web engine can load local images sys.argv.append("--disable-web-security") # initialize QApp so we can pop up dialogs now. self.app = MyApplication(sys.argv) # we import here so that the QApp is initialized before # the Notify library is loaded because it uses DBusQtMainLoop # DBusQtMainLoop must be initialized after to work properly from qtvcp import qt_makepins, qt_makegui # ToDo: pass specific log levels as an argument, or use an INI setting if opts.debug: # Log level defaults to INFO, so set lower if in debug mode logger.setGlobalLevel(logger.DEBUG) if opts.verbose: # Log level defaults to INFO, so set lowest if in verbose mode logger.setGlobalLevel(logger.VERBOSE) LOG.verbose('VERBOSE DEBUGGING ON') # a specific path has been set to load from or... # no path set but -ini is present: default qtvcp screen...or # oops error if args: basepath=args[0] elif INIPATH: basepath = "qt_cnc" else: print(parser.print_help()) sys.exit(0) # set paths using basename error = PATH.set_paths(basepath, bool(INIPATH)) if error: sys.exit(0) # keep track of python version during this transition ver = 'Python 3' ################# # Screen specific ################# if INIPATH: LOG.info('green<Building A Linuxcnc Main Screen with {}>'.format(ver)) import linuxcnc # pull info from the INI file self.inifile = linuxcnc.ini(INIPATH) self.inipath = INIPATH # if no handler file specified, use stock test one if not opts.usermod: LOG.info('No handler file specified on command line') target = os.path.join(PATH.CONFIGPATH, '%s_handler.py' % PATH.BASENAME) source = os.path.join(PATH.SCREENDIR, 'tester/tester_handler.py') if PATH.HANDLER is None: message = (""" Qtvcp encountered an error; No handler file was found. Would you like to copy a basic handler file into your config folder? This handler file will allow display of your screen and basic keyboard jogging. The new handlerfile's path will be: %s Pressing cancel will close linuxcnc.""" % target) rtn = QtWidgets.QMessageBox.critical(None, "QTVCP Error", message,QtWidgets.QMessageBox.Ok | QtWidgets.QMessageBox.Cancel) if rtn == QtWidgets.QMessageBox.Ok: try: shutil.copy(source, target) except IOError as e: LOG.critical("Unable to copy handler file. %s" % e) sys.exit(0) except: LOG.critical("Unexpected error copying handler file:", sys.exc_info()) sys.exit(0) opts.usermod = PATH.HANDLER = target else: LOG.critical('No handler file found or specified. User requested stopping') else: opts.usermod = PATH.HANDLER # specify the HAL component name if missing if opts.component is None: LOG.info('No HAL component base name specified on command line using: {}'.format(PATH.BASENAME)) opts.component = PATH.BASENAME ################# # VCP specific ################# else: LOG.info('green<Building A VCP Panel with {}>'.format(ver)) # if no handler file specified, use stock test one if not opts.usermod: LOG.info('No handler file specified - using {}'.format(PATH.HANDLER)) opts.usermod = PATH.HANDLER # specify the HAL component name if missing if opts.component is None: LOG.info('No HAL component base name specified - using: {}'.format(PATH.BASENAME)) opts.component = PATH.BASENAME ############################ # International translation ############################ if PATH.LOCALEDIR is not None: translator = QtCore.QTranslator() translator.load(PATH.LOCALEDIR) self.app.installTranslator(translator) #QtCore.QCoreApplication.installTranslator(translator) #print(self.app.translate("MainWindow", 'Machine Log')) ############## # Build ui ############## #if there was no component name specified use the xml file name if opts.component is None: opts.component = PATH.BASENAME # initialize HAL try: self.halcomp = hal.component(opts.component) self.hal = Qhal(self.halcomp, hal) except: LOG.critical("Asking for a HAL component using a name that already exists?") raise Exception('"Asking for a HAL component using a name that already exists?') # initialize the window window = qt_makegui.VCPWindow(self.hal, PATH) # give reference to user command line options if opts.useropts: window.USEROPTIONS_ = opts.useropts else: window.USEROPTIONS_ = None # load optional user handler file if opts.usermod: LOG.debug('Loading the handler file') window.load_extension(opts.usermod) try: window.web_view = QWebView() except: window.web_view = None # do any class patching now if "class_patch__" in dir(window.handler_instance): window.handler_instance.class_patch__() # add filter to catch keyboard events LOG.debug('Adding the key events filter') myFilter = qt_makegui.MyEventFilter(window) self.app.installEventFilter(myFilter) # actually build the widgets window.instance() # title if INIPATH: if (INITITLE == ""): INITITLE='QTvcp-Screen-%s'% opts.component title = INITITLE else: title = 'QTvcp-Panel-%s'% opts.component window.setWindowTitle(title) # make QT widget HAL pins self.panel = qt_makepins.QTPanel(self.hal, PATH, window, opts.debug) # call handler file's initialized function if opts.usermod: if "initialized__" in dir(window.handler_instance): LOG.debug('''Calling the handler file's initialized__ function''') window.handler_instance.initialized__() # add any external handler override user commands if INFO.USER_COMMAND_FILE is None: INFO.USER_COMMAND_FILE = os.path.join(PATH.CONFIGPATH,'.{}rc'.format(PATH.BASEPATH)) INFO.USER_COMMAND_FILE = INFO.USER_COMMAND_FILE.replace('CONFIGFOLDER',PATH.CONFIGPATH) INFO.USER_COMMAND_FILE = INFO.USER_COMMAND_FILE.replace('WORKINGFOLDER',PATH.WORKINGDIR) window.handler_instance.call_user_command_(window.handler_instance, INFO.USER_COMMAND_FILE) # All Widgets should be added now - synch them to linuxcnc STATUS.forced_update() # call a HAL file after widgets built if opts.halfile: if opts.halfile[-4:] == ".tcl": cmd = ["haltcl", opts.halfile] else: cmd = ["halcmd", "-f", opts.halfile] res = subprocess.call(cmd, stdout=sys.stdout, stderr=sys.stderr) if res: print("'%s' exited with %d" %(' '.join(cmd), res), file=sys.stderr) self.shutdown() # User components are set up so report that we are ready LOG.debug('Set HAL ready') self.halcomp.ready() # embed us into an X11 window (such as AXIS) if opts.parent: try: from qtvcp.lib import xembed window = xembed.reparent_qt_to_x11(window, opts.parent) forward = os.environ.get('AXIS_FORWARD_EVENTS_TO', None) LOG.critical('Forwarding events to AXIS is not well tested yet') if forward: xembed.XEmbedForwarding(window, forward) except Exception as e: LOG.critical('Embedding error:{}'.format(e)) # push the window id for embedment into an external program if opts.push_XID: wid = int(window.winId()) print(wid, file=sys.stdout) sys.stdout.flush() # for window resize and or position options if "+" in opts.geometry: LOG.debug('-g option: moving window') try: j = opts.geometry.partition("+") pos = j[2].partition("+") window.move( int(pos[0]), int(pos[2]) ) except Exception as e: LOG.critical("With -g window position data:\n {}".format(e)) parser.print_help() self.shutdown() if "x" in opts.geometry: LOG.debug('-g option: resizing') try: if "+" in opts.geometry: j = opts.geometry.partition("+") t = j[0].partition("x") else: t = opts.geometry.partition("x") window.resize( int(t[0]), int(t[2]) ) except Exception as e: LOG.critical("With -g window resize data:\n {}".format(e)) parser.print_help() self.shutdown() # always on top if opts.always_top: window.setWindowFlags(QtCore.Qt.WindowStaysOnTopHint) # theme (styles in QT speak) specify a qss file if opts.theme: window.apply_styles(opts.theme) # apply qss file or default theme else: window.apply_styles() LOG.debug('Show window') # maximize if opts.maximum: window.showMaximized() # fullscreen elif opts.fullscreen: window.showFullScreen() else: self.panel.set_preference_geometry() window.show() if INIPATH: self.postgui() self.postgui_cmd() if (INIICON == ""): window.setWindowIcon(QtGui.QIcon(os.path.join(PATH.IMAGEDIR, 'linuxcncicon.png'))) else: window.setWindowIcon(QtGui.QIcon(os.path.join(PATH.CONFIGPATH, INIICON))) else: window.setWindowIcon(QtGui.QIcon(os.path.join(PATH.IMAGEDIR, 'linuxcnc-wizard.gif'))) # catch control c and terminate signals signal.signal(signal.SIGTERM, self.shutdown) signal.signal(signal.SIGINT, self.shutdown) if opts.usermod and "before_loop__" in dir(window.handler_instance): LOG.debug('''Calling the handler file's before_loop__ function''') window.handler_instance.before_loop__() LOG.info('Preference path: {}'.format(PATH.PREFS_FILENAME)) # start loop self.app.exec_() # now shut it all down self.shutdown()
LOG = logger.getLogger(__name__) # Set the log level for this module #LOG.setLevel(logger.INFO) # One of DEBUG, INFO, WARNING, ERROR, CRITICAL ########################################### # **** instantiate libraries section **** # ########################################### KEYBIND = Keylookup() STATUS = Status() ACTION = Action() INFO = Info() TOOLBAR = ToolBarActions() STYLEEDITOR = SSE() QHAL = Qhal() ################################### # **** HANDLER CLASS SECTION **** # ################################### class HandlerClass: ######################## # **** INITIALIZE **** # ######################## # widgets allows access to widgets from the qtvcp files # at this point the widgets and hal pins are not instantiated def __init__(self, halcomp, widgets, paths): self.hal = halcomp self.w = widgets