Kaynağa Gözat

- FlatCAM can be run in HEADLESS mode now. This node can be selected by using the --headless=1 command line argument or by changing the line headless=False to True in config/configuration.txt file. In this mod the Sys Tray Icon menu will hold only the Run Scrip menu entry and Exit entry.

Marius Stanciu 6 yıl önce
ebeveyn
işleme
1d26247fc4

+ 69 - 25
FlatCAMApp.py

@@ -81,12 +81,16 @@ class App(QtCore.QObject):
     # Get Cmd Line Options
     cmd_line_shellfile = ''
     cmd_line_shellvar = ''
+    cmd_line_headless = None
 
-    cmd_line_help = "FlatCam.py --shellfile=<cmd_line_shellfile>\nFlatCam.py --shellvar=<1,'C:\\path',23>"
+    cmd_line_help = "FlatCam.py --shellfile=<cmd_line_shellfile>\n" \
+                    "FlatCam.py --shellvar=<1,'C:\\path',23>\n" \
+                    "FlatCam.py --headless=1"
     try:
         # Multiprocessing pool will spawn additional processes with 'multiprocessing-fork' flag
         cmd_line_options, args = getopt.getopt(sys.argv[1:], "h:", ["shellfile=",
                                                                     "shellvar=",
+                                                                    "headless=",
                                                                     "multiprocessing-fork="])
     except getopt.GetoptError:
         print(cmd_line_help)
@@ -99,6 +103,11 @@ class App(QtCore.QObject):
             cmd_line_shellfile = arg
         elif opt == '--shellvar':
             cmd_line_shellvar = arg
+        elif opt == '--headless':
+            try:
+                cmd_line_headless = eval(arg)
+            except NameError:
+                pass
 
     # ## Logging ###
     log = logging.getLogger('base')
@@ -251,20 +260,33 @@ class App(QtCore.QObject):
             # ####### CONFIG FILE WITH PARAMETERS REGARDING PORTABILITY ###############
             # #########################################################################
             config_file = os.path.dirname(os.path.dirname(os.path.realpath(__file__))) + '\\config\\configuration.txt'
+            try:
+                with open(config_file, 'r'):
+                    pass
+            except FileNotFoundError:
+                config_file = os.path.dirname(os.path.realpath(__file__)) + '\\config\\configuration.txt'
+
             try:
                 with open(config_file, 'r') as f:
                     try:
                         for line in f:
-                            param = str(line).rpartition('=')
+                            param = str(line).replace('\n', '').rpartition('=')
+
                             if param[0] == 'portable':
                                 try:
                                     portable = eval(param[2])
                                 except NameError:
                                     portable = False
+                            if param[0] == 'headless':
+                                if param[2].lower() == 'true':
+                                    self.cmd_line_headless = 1
+                                else:
+                                    self.cmd_line_headless = None
                     except Exception as e:
                         log.debug('App.__init__() -->%s' % str(e))
                         return
-            except FileNotFoundError:
+            except FileNotFoundError as e:
+                log.debug(str(e))
                 pass
 
             if portable is False:
@@ -365,7 +387,7 @@ class App(QtCore.QObject):
             del settings
             show_splash = 1
 
-        if show_splash:
+        if show_splash and self.cmd_line_headless != 1:
             splash_pix = QtGui.QPixmap('share/splash.png')
             self.splash = QtWidgets.QSplashScreen(splash_pix, Qt.WindowStaysOnTopHint)
             # self.splash.setMask(splash_pix.mask())
@@ -380,6 +402,8 @@ class App(QtCore.QObject):
             self.splash.showMessage(_("FlatCAM is initializing ..."),
                                alignment=Qt.AlignBottom | Qt.AlignLeft,
                                color=QtGui.QColor("gray"))
+        else:
+            show_splash = 0
 
         # #############################################################################
         # ##################### Initialize GUI ########################################
@@ -392,6 +416,7 @@ class App(QtCore.QObject):
         self.FC_dark_blue = '#0000ffbf'
 
         QtCore.QObject.__init__(self)
+
         self.ui = FlatCAMGUI(self.version, self.beta, self)
 
         self.ui.geom_update[int, int, int, int, int].connect(self.save_geometry)
@@ -1579,8 +1604,14 @@ class App(QtCore.QObject):
         # #################################################################
         if self.defaults["global_systray_icon"]:
             self.parent_w = QtWidgets.QWidget()
-            self.trayIcon = FlatCAMSystemTray(app=self, icon=QtGui.QIcon('share/flatcam_icon32_green.png'),
-                                              parent=self.parent_w)
+
+            if self.cmd_line_headless == 1:
+                self.trayIcon = FlatCAMSystemTray(app=self, icon=QtGui.QIcon('share/flatcam_icon32_green.png'),
+                                                  headless=True,
+                                                  parent=self.parent_w)
+            else:
+                self.trayIcon = FlatCAMSystemTray(app=self, icon=QtGui.QIcon('share/flatcam_icon32_green.png'),
+                                                  parent=self.parent_w)
 
         # ##############################################
         # ######### SETUP OBJECT COLLECTION ############
@@ -2454,21 +2485,25 @@ class App(QtCore.QObject):
         # ########################## SHOW GUI #################################################
         # #####################################################################################
 
-        # finish the splash
-        self.splash.finish(self.ui)
+        # if the app is not started as headless, show it
+        if self.cmd_line_headless != 1:
+            # finish the splash
+            self.splash.finish(self.ui)
 
-        settings = QSettings("Open Source", "FlatCAM")
-        if settings.contains("maximized_gui"):
-            maximized_ui = settings.value('maximized_gui', type=bool)
-            if maximized_ui is True:
-                self.ui.showMaximized()
+            settings = QSettings("Open Source", "FlatCAM")
+            if settings.contains("maximized_gui"):
+                maximized_ui = settings.value('maximized_gui', type=bool)
+                if maximized_ui is True:
+                    self.ui.showMaximized()
+                else:
+                    self.ui.show()
             else:
                 self.ui.show()
-        else:
-            self.ui.show()
 
-        if self.defaults["global_systray_icon"]:
-            self.trayIcon.show()
+            if self.defaults["global_systray_icon"]:
+                self.trayIcon.show()
+        else:
+            log.warning("*******************  RUNNING HEADLESS  *******************")
 
         # #####################################################################################
         # ########################## START-UP ARGUMENTS #######################################
@@ -8867,11 +8902,14 @@ class App(QtCore.QObject):
 
         if name:
             filename = name
-            self.splash.showMessage('%s: %ssec\n%s' % (_("Canvas initialization started.\n"
-                                                         "Canvas initialization finished in"), '%.2f' % self.used_time,
-                                                       _("Executing FlatCAMScript file.")),
-                                    alignment=Qt.AlignBottom | Qt.AlignLeft,
-                                    color=QtGui.QColor("gray"))
+            if self.cmd_line_headless != 1:
+                self.splash.showMessage('%s: %ssec\n%s' %
+                                        (_("Canvas initialization started.\n"
+                                           "Canvas initialization finished in"), '%.2f' % self.used_time,
+                                         _("Executing FlatCAMScript file.")
+                                         ),
+                                        alignment=Qt.AlignBottom | Qt.AlignLeft,
+                                        color=QtGui.QColor("gray"))
         else:
             _filter_ = "TCL script (*.FlatScript);;TCL script (*.TCL);;TCL script (*.TXT);;All Files (*.*)"
             try:
@@ -8890,12 +8928,18 @@ class App(QtCore.QObject):
                 self.inform.emit('[WARNING_NOTCL] %s' %
                                  _("Run TCL script cancelled."))
         else:
-            if self.ui.shell_dock.isHidden():
-                self.ui.shell_dock.show()
+            if self.cmd_line_headless != 1:
+                if self.ui.shell_dock.isHidden():
+                    self.ui.shell_dock.show()
+
             try:
                 with open(filename, "r") as tcl_script:
                     cmd_line_shellfile_content = tcl_script.read()
-                    self.shell._sysShell.exec_command(cmd_line_shellfile_content)
+                    if self.cmd_line_headless != 1:
+                        self.shell._sysShell.exec_command(cmd_line_shellfile_content)
+                    else:
+                        self.shell._sysShell.exec_command(cmd_line_shellfile_content, no_echo=True)
+
                 if silent is False:
                     self.inform.emit('[success] %s' %
                                      _("TCL script file opened in Code Editor and executed."))

+ 1 - 0
README.md

@@ -17,6 +17,7 @@ CAD program, and create G-Code for Isolation routing.
 - made sure that optionally, when a script is run then it is also loaded into the code editor
 - added control over the display of Sys Tray Icon in Edit -> Preferences -> General -> GUI Settings -> Sys Tray Icon checkbox
 - updated some of the default values to more reasonable ones
+- FlatCAM can be run in HEADLESS mode now. This node can be selected by using the --headless=1 command line argument or by changing the line headless=False to True in config/configuration.txt file. In this mod the Sys Tray Icon menu will hold only the Run Scrip menu entry and Exit entry.
 
 18.09.2019
 

+ 26 - 23
flatcamGUI/FlatCAMGUI.py

@@ -8212,7 +8212,7 @@ class FlatCAMInfoBar(QtWidgets.QWidget):
 
 class FlatCAMSystemTray(QtWidgets.QSystemTrayIcon):
 
-    def __init__(self, app, icon, parent=None):
+    def __init__(self, app, icon, headless=None, parent=None):
         # QtWidgets.QSystemTrayIcon.__init__(self, icon, parent)
         super().__init__(icon, parent=parent)
         self.app = app
@@ -8229,38 +8229,41 @@ class FlatCAMSystemTray(QtWidgets.QSystemTrayIcon):
 
         menu.addSeparator()
 
-        menu_open = menu.addMenu(QtGui.QIcon('share/folder32_bis.png'), _('Open'))
+        if headless is None:
+            self.menu_open = menu.addMenu(QtGui.QIcon('share/folder32_bis.png'), _('Open'))
 
-        # Open Project ...
-        menu_openproject = QtWidgets.QAction(QtGui.QIcon('share/folder16.png'), _('Open Project ...'), self)
-        menu_open.addAction(menu_openproject)
-        menu_open.addSeparator()
+            # Open Project ...
+            menu_openproject = QtWidgets.QAction(QtGui.QIcon('share/folder16.png'), _('Open Project ...'), self)
+            self.menu_open.addAction(menu_openproject)
+            self.menu_open.addSeparator()
 
-        # Open Gerber ...
-        menu_opengerber = QtWidgets.QAction(QtGui.QIcon('share/flatcam_icon24.png'),
-                                                    _('Open &Gerber ...\tCTRL+G'), self)
-        menu_open.addAction(menu_opengerber)
+            # Open Gerber ...
+            menu_opengerber = QtWidgets.QAction(QtGui.QIcon('share/flatcam_icon24.png'),
+                                                        _('Open &Gerber ...\tCTRL+G'), self)
+            self.menu_open.addAction(menu_opengerber)
 
-        # Open Excellon ...
-        menu_openexcellon = QtWidgets.QAction(QtGui.QIcon('share/open_excellon32.png'),
-                                                      _('Open &Excellon ...\tCTRL+E'), self)
-        menu_open.addAction(menu_openexcellon)
+            # Open Excellon ...
+            menu_openexcellon = QtWidgets.QAction(QtGui.QIcon('share/open_excellon32.png'),
+                                                          _('Open &Excellon ...\tCTRL+E'), self)
+            self.menu_open.addAction(menu_openexcellon)
 
-        # Open G-Code ...
-        menu_opengcode = QtWidgets.QAction(QtGui.QIcon('share/code.png'), _('Open G-&Code ...'), self)
-        menu_open.addAction(menu_opengcode)
+            # Open G-Code ...
+            menu_opengcode = QtWidgets.QAction(QtGui.QIcon('share/code.png'), _('Open G-&Code ...'), self)
+            self.menu_open.addAction(menu_opengcode)
+
+            self.menu_open.addSeparator()
 
-        menu_open.addSeparator()
+            menu_openproject.triggered.connect(self.app.on_file_openproject)
+            menu_opengerber.triggered.connect(self.app.on_fileopengerber)
+            menu_openexcellon.triggered.connect(self.app.on_fileopenexcellon)
+            menu_opengcode.triggered.connect(self.app.on_fileopengcode)
 
         exitAction = menu.addAction(_("Exit"))
         exitAction.setIcon(QtGui.QIcon('share/power16.png'))
         self.setContextMenu(menu)
 
-        menu_runscript.triggered.connect(self.app.on_filerunscript)
-        menu_openproject.triggered.connect(self.app.on_file_openproject)
-        menu_opengerber.triggered.connect(self.app.on_fileopengerber)
-        menu_openexcellon.triggered.connect(self.app.on_fileopenexcellon)
-        menu_opengcode.triggered.connect(self.app.on_fileopengcode)
+        menu_runscript.triggered.connect(lambda: self.app.on_filerunscript(
+            silent=True if self.app.cmd_line_headless == 1 else False))
 
         exitAction.triggered.connect(self.app.final_save)
 

+ 2 - 2
tclCommands/TclCommandPlotAll.py

@@ -42,5 +42,5 @@ class TclCommandPlotAll(TclCommand):
         :param unnamed_args:
         :return:
         """
-
-        self.app.plot_all()
+        if self.app.cmd_line_headless != 1:
+            self.app.plot_all()

+ 8 - 7
tclCommands/TclCommandPlotObjects.py

@@ -42,10 +42,11 @@ class TclCommandPlotObjects(TclCommand):
         :param unnamed_args:
         :return:
         """
-        names = [x.strip() for x in args['names'].split(",")]
-        objs = []
-        for name in names:
-            objs.append(self.app.collection.get_by_name(name))
-
-        for obj in objs:
-            obj.plot()
+        if self.app.cmd_line_headless != 1:
+            names = [x.strip() for x in args['names'].split(",")]
+            objs = []
+            for name in names:
+                objs.append(self.app.collection.get_by_name(name))
+
+            for obj in objs:
+                obj.plot()