diff --git a/CHANGELOG.md b/CHANGELOG.md index 36c16983..60572af4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ CHANGELOG for FlatCAM beta - in Preferences made sure that clicking the Restore Defaults will update the values in the Preferences Tab - some changes in the Tools visibility in the Tools ToolBar - added confirmation status messages for clearing the recent files/projects lists +- moved around portions of code in the App.__init__ for optimization; added a control in Preferences for usage of Log in Tcl Shell 24.11.2020 diff --git a/appGUI/preferences/PreferencesUIManager.py b/appGUI/preferences/PreferencesUIManager.py index 13ca0126..44638cf7 100644 --- a/appGUI/preferences/PreferencesUIManager.py +++ b/appGUI/preferences/PreferencesUIManager.py @@ -53,7 +53,9 @@ class PreferencesUIManager: "units": self.ui.general_defaults_form.general_app_group.units_radio, "global_graphic_engine": self.ui.general_defaults_form.general_app_group.ge_radio, "global_app_level": self.ui.general_defaults_form.general_app_group.app_level_radio, + "global_log_verbose": self.ui.general_defaults_form.general_app_group.verbose_cb, "global_portable": self.ui.general_defaults_form.general_app_group.portability_cb, + "global_language": self.ui.general_defaults_form.general_app_group.language_cb, "global_systray_icon": self.ui.general_defaults_form.general_app_group.systray_cb, diff --git a/appGUI/preferences/general/GeneralAppPrefGroupUI.py b/appGUI/preferences/general/GeneralAppPrefGroupUI.py index eeb78728..2f6b3b72 100644 --- a/appGUI/preferences/general/GeneralAppPrefGroupUI.py +++ b/appGUI/preferences/general/GeneralAppPrefGroupUI.py @@ -57,8 +57,8 @@ class GeneralAppPrefGroupUI(OptionsGroupUI): self.precision_metric_entry.set_range(2, 16) self.precision_metric_entry.setWrapping(True) - grid0.addWidget(self.precision_metric_label, 1, 0) - grid0.addWidget(self.precision_metric_entry, 1, 1) + grid0.addWidget(self.precision_metric_label, 2, 0) + grid0.addWidget(self.precision_metric_entry, 2, 1) # Precision Inch self.precision_inch_label = FCLabel('%s:' % _('Precision Inch')) @@ -71,8 +71,8 @@ class GeneralAppPrefGroupUI(OptionsGroupUI): self.precision_inch_entry.set_range(2, 16) self.precision_inch_entry.setWrapping(True) - grid0.addWidget(self.precision_inch_label, 2, 0) - grid0.addWidget(self.precision_inch_entry, 2, 1) + grid0.addWidget(self.precision_inch_label, 4, 0) + grid0.addWidget(self.precision_inch_entry, 4, 1) # Graphic Engine for FlatCAM self.ge_label = FCLabel('%s:' % _('Graphic Engine')) @@ -86,13 +86,13 @@ class GeneralAppPrefGroupUI(OptionsGroupUI): {'label': _('OpenGL(3D)'), 'value': '3D'}], orientation='vertical') - grid0.addWidget(self.ge_label, 3, 0) - grid0.addWidget(self.ge_radio, 3, 1) + grid0.addWidget(self.ge_label, 6, 0) + grid0.addWidget(self.ge_radio, 6, 1) separator_line = QtWidgets.QFrame() separator_line.setFrameShape(QtWidgets.QFrame.HLine) separator_line.setFrameShadow(QtWidgets.QFrame.Sunken) - grid0.addWidget(separator_line, 4, 0, 1, 2) + grid0.addWidget(separator_line, 8, 0, 1, 2) # Application Level for FlatCAM self.app_level_label = FCLabel('%s:' % _('APPLICATION LEVEL')) @@ -101,51 +101,58 @@ class GeneralAppPrefGroupUI(OptionsGroupUI): "ADVANCED level -> full functionality.\n\n" "The choice here will influence the parameters in\n" "the Selected Tab for all kinds of FlatCAM objects.")) + grid0.addWidget(self.app_level_label, 10, 0, 1, 2) + self.app_level_radio = RadioSet([{'label': _('Basic'), 'value': 'b'}, {'label': _('Advanced'), 'value': 'a'}]) + grid0.addWidget(self.app_level_radio, 12, 0, 1, 2) - grid0.addWidget(self.app_level_label, 5, 0, 1, 2) - grid0.addWidget(self.app_level_radio, 6, 0, 1, 2) - - # Portability for FlatCAM + # Portability self.portability_cb = FCCheckBox('%s' % _('Portable app')) self.portability_cb.setToolTip(_("Choose if the application should run as portable.\n\n" "If Checked the application will run portable,\n" "which means that the preferences files will be saved\n" "in the application folder, in the lib\\config subfolder.")) - grid0.addWidget(self.portability_cb, 7, 0, 1, 2) + grid0.addWidget(self.portability_cb, 14, 0, 1, 2) + + # Verbose Log + self.verbose_cb = FCCheckBox('%s' % _('Verbose log')) + self.verbose_cb.setToolTip(_("Enable log messages in the Tcl Shell.\n" + "Require restart.")) + + grid0.addWidget(self.verbose_cb, 16, 0, 1, 2) separator_line = QtWidgets.QFrame() separator_line.setFrameShape(QtWidgets.QFrame.HLine) separator_line.setFrameShadow(QtWidgets.QFrame.Sunken) - grid0.addWidget(separator_line, 8, 0, 1, 2) + grid0.addWidget(separator_line, 18, 0, 1, 2) # Languages for FlatCAM self.languagelabel = FCLabel('%s' % _('Languages')) self.languagelabel.setToolTip(_("Set the language used throughout FlatCAM.")) - self.language_cb = FCComboBox() + grid0.addWidget(self.languagelabel, 20, 0, 1, 2) - grid0.addWidget(self.languagelabel, 9, 0, 1, 2) - grid0.addWidget(self.language_cb, 10, 0, 1, 2) + self.language_cb = FCComboBox() + grid0.addWidget(self.language_cb, 22, 0, 1, 2) self.language_apply_btn = FCButton(_("Apply Language")) self.language_apply_btn.setToolTip(_("Set the language used throughout FlatCAM.\n" "The app will restart after click.")) - grid0.addWidget(self.language_apply_btn, 15, 0, 1, 2) + grid0.addWidget(self.language_apply_btn, 24, 0, 1, 2) separator_line = QtWidgets.QFrame() separator_line.setFrameShape(QtWidgets.QFrame.HLine) separator_line.setFrameShadow(QtWidgets.QFrame.Sunken) - grid0.addWidget(separator_line, 16, 0, 1, 2) + grid0.addWidget(separator_line, 26, 0, 1, 2) # ----------------------------------------------------------- # ----------- APPLICATION STARTUP SETTINGS ------------------ # ----------------------------------------------------------- self.startup_label = FCLabel('%s' % _('Startup Settings')) - grid0.addWidget(self.startup_label, 17, 0, 1, 2) + grid0.addWidget(self.startup_label, 28, 0, 1, 2) # Splash Screen self.splash_cb = FCCheckBox('%s' % _('Splash Screen')) @@ -159,14 +166,14 @@ class GeneralAppPrefGroupUI(OptionsGroupUI): else: self.splash_cb.set_value(False) - grid0.addWidget(self.splash_cb, 18, 0, 1, 2) + grid0.addWidget(self.splash_cb, 30, 0, 1, 2) # Sys Tray Icon self.systray_cb = FCCheckBox('%s' % _('Sys Tray Icon')) self.systray_cb.setToolTip( _("Enable display of FlatCAM icon in Sys Tray.") ) - grid0.addWidget(self.systray_cb, 19, 0, 1, 2) + grid0.addWidget(self.systray_cb, 32, 0, 1, 2) # Shell StartUp CB self.shell_startup_cb = FCCheckBox(label='%s' % _('Show Shell')) @@ -175,7 +182,7 @@ class GeneralAppPrefGroupUI(OptionsGroupUI): "start automatically at startup.") ) - grid0.addWidget(self.shell_startup_cb, 20, 0, 1, 2) + grid0.addWidget(self.shell_startup_cb, 34, 0, 1, 2) # Project at StartUp CB self.project_startup_cb = FCCheckBox(label='%s' % _('Show Project')) @@ -183,7 +190,7 @@ class GeneralAppPrefGroupUI(OptionsGroupUI): _("Check this box if you want the project/selected/tool tab area to\n" "to be shown automatically at startup.") ) - grid0.addWidget(self.project_startup_cb, 21, 0, 1, 2) + grid0.addWidget(self.project_startup_cb, 36, 0, 1, 2) # Version Check CB self.version_check_cb = FCCheckBox(label='%s' % _('Version Check')) @@ -192,7 +199,7 @@ class GeneralAppPrefGroupUI(OptionsGroupUI): "for a new version automatically at startup.") ) - grid0.addWidget(self.version_check_cb, 22, 0, 1, 2) + grid0.addWidget(self.version_check_cb, 38, 0, 1, 2) # Send Stats CB self.send_stats_cb = FCCheckBox(label='%s' % _('Send Statistics')) @@ -201,14 +208,14 @@ class GeneralAppPrefGroupUI(OptionsGroupUI): "stats automatically at startup, to help improve FlatCAM.") ) - grid0.addWidget(self.send_stats_cb, 23, 0, 1, 2) + grid0.addWidget(self.send_stats_cb, 40, 0, 1, 2) self.ois_version_check = OptionalInputSection(self.version_check_cb, [self.send_stats_cb]) separator_line = QtWidgets.QFrame() separator_line.setFrameShape(QtWidgets.QFrame.HLine) separator_line.setFrameShadow(QtWidgets.QFrame.Sunken) - grid0.addWidget(separator_line, 24, 0, 1, 2) + grid0.addWidget(separator_line, 42, 0, 1, 2) # Worker Numbers self.worker_number_label = FCLabel('%s:' % _('Workers number')) @@ -223,8 +230,8 @@ class GeneralAppPrefGroupUI(OptionsGroupUI): self.worker_number_sb = FCSpinner() self.worker_number_sb.set_range(2, 16) - grid0.addWidget(self.worker_number_label, 25, 0) - grid0.addWidget(self.worker_number_sb, 25, 1) + grid0.addWidget(self.worker_number_label, 44, 0) + grid0.addWidget(self.worker_number_sb, 44, 1) # Geometric tolerance tol_label = FCLabel('%s:' % _("Geo Tolerance")) @@ -240,17 +247,17 @@ class GeneralAppPrefGroupUI(OptionsGroupUI): self.tol_entry.setSingleStep(0.001) self.tol_entry.set_precision(6) - grid0.addWidget(tol_label, 26, 0) - grid0.addWidget(self.tol_entry, 26, 1) + grid0.addWidget(tol_label, 46, 0) + grid0.addWidget(self.tol_entry, 46, 1) separator_line = QtWidgets.QFrame() separator_line.setFrameShape(QtWidgets.QFrame.HLine) separator_line.setFrameShadow(QtWidgets.QFrame.Sunken) - grid0.addWidget(separator_line, 27, 0, 1, 2) + grid0.addWidget(separator_line, 48, 0, 1, 2) # Save Settings self.save_label = FCLabel('%s' % _("Save Settings")) - grid0.addWidget(self.save_label, 28, 0, 1, 2) + grid0.addWidget(self.save_label, 50, 0, 1, 2) # Save compressed project CB self.save_type_cb = FCCheckBox(_('Save Compressed Project')) @@ -259,7 +266,7 @@ class GeneralAppPrefGroupUI(OptionsGroupUI): "When checked it will save a compressed FlatCAM project.") ) - grid0.addWidget(self.save_type_cb, 29, 0, 1, 2) + grid0.addWidget(self.save_type_cb, 52, 0, 1, 2) # Project LZMA Comppression Level self.compress_spinner = FCSpinner() @@ -271,8 +278,8 @@ class GeneralAppPrefGroupUI(OptionsGroupUI): "but require more RAM usage and more processing time.") ) - grid0.addWidget(self.compress_label, 30, 0) - grid0.addWidget(self.compress_spinner, 30, 1) + grid0.addWidget(self.compress_label, 54, 0) + grid0.addWidget(self.compress_spinner, 54, 1) self.proj_ois = OptionalInputSection(self.save_type_cb, [self.compress_label, self.compress_spinner], True) @@ -284,7 +291,7 @@ class GeneralAppPrefGroupUI(OptionsGroupUI): "at the set interval.") ) - grid0.addWidget(self.autosave_cb, 31, 0, 1, 2) + grid0.addWidget(self.autosave_cb, 56, 0, 1, 2) # Auto Save Timeout Interval self.autosave_entry = FCSpinner() @@ -297,21 +304,21 @@ class GeneralAppPrefGroupUI(OptionsGroupUI): "While active, some operations may block this feature.") ) - grid0.addWidget(self.autosave_label, 32, 0) - grid0.addWidget(self.autosave_entry, 32, 1) + grid0.addWidget(self.autosave_label, 58, 0) + grid0.addWidget(self.autosave_entry, 58, 1) # self.as_ois = OptionalInputSection(self.autosave_cb, [self.autosave_label, self.autosave_entry], True) separator_line = QtWidgets.QFrame() separator_line.setFrameShape(QtWidgets.QFrame.HLine) separator_line.setFrameShadow(QtWidgets.QFrame.Sunken) - grid0.addWidget(separator_line, 33, 0, 1, 2) + grid0.addWidget(separator_line, 60, 0, 1, 2) self.pdf_param_label = FCLabel('%s:' % _("Text to PDF parameters")) self.pdf_param_label.setToolTip( _("Used when saving text in Code Editor or in FlatCAM Document objects.") ) - grid0.addWidget(self.pdf_param_label, 34, 0, 1, 2) + grid0.addWidget(self.pdf_param_label, 62, 0, 1, 2) # Top Margin value self.tmargin_entry = FCDoubleSpinner() @@ -323,8 +330,8 @@ class GeneralAppPrefGroupUI(OptionsGroupUI): _("Distance between text body and the top of the PDF file.") ) - grid0.addWidget(self.tmargin_label, 35, 0) - grid0.addWidget(self.tmargin_entry, 35, 1) + grid0.addWidget(self.tmargin_label, 64, 0) + grid0.addWidget(self.tmargin_entry, 64, 1) # Bottom Margin value self.bmargin_entry = FCDoubleSpinner() @@ -336,8 +343,8 @@ class GeneralAppPrefGroupUI(OptionsGroupUI): _("Distance between text body and the bottom of the PDF file.") ) - grid0.addWidget(self.bmargin_label, 36, 0) - grid0.addWidget(self.bmargin_entry, 36, 1) + grid0.addWidget(self.bmargin_label, 66, 0) + grid0.addWidget(self.bmargin_entry, 66, 1) # Left Margin value self.lmargin_entry = FCDoubleSpinner() @@ -349,8 +356,8 @@ class GeneralAppPrefGroupUI(OptionsGroupUI): _("Distance between text body and the left of the PDF file.") ) - grid0.addWidget(self.lmargin_label, 37, 0) - grid0.addWidget(self.lmargin_entry, 37, 1) + grid0.addWidget(self.lmargin_label, 68, 0) + grid0.addWidget(self.lmargin_entry, 68, 1) # Right Margin value self.rmargin_entry = FCDoubleSpinner() @@ -362,8 +369,8 @@ class GeneralAppPrefGroupUI(OptionsGroupUI): _("Distance between text body and the right of the PDF file.") ) - grid0.addWidget(self.rmargin_label, 38, 0) - grid0.addWidget(self.rmargin_entry, 38, 1) + grid0.addWidget(self.rmargin_label, 70, 0) + grid0.addWidget(self.rmargin_entry, 70, 1) self.layout.addStretch() diff --git a/appTools/ToolShell.py b/appTools/ToolShell.py index 02e093e0..e3a6f5d2 100644 --- a/appTools/ToolShell.py +++ b/appTools/ToolShell.py @@ -7,7 +7,7 @@ # ########################################################## -from PyQt5.QtCore import Qt +from PyQt5 import QtCore, QtGui from PyQt5.QtGui import QTextCursor, QPixmap from PyQt5.QtWidgets import QVBoxLayout, QWidget, QHBoxLayout, QLabel from appGUI.GUIElements import _BrowserTextEdit, _ExpandableTextEdit, FCLabel @@ -88,8 +88,8 @@ class TermWidget(QWidget): :return: None """ - self._edit.setTextColor(Qt.white) - self._edit.setTextBackgroundColor(Qt.darkGreen) + self._edit.setTextColor(QtCore.Qt.white) + self._edit.setTextBackgroundColor(QtCore.Qt.darkGreen) if detail is None: self._edit.setPlainText(_("...processing...")) else: @@ -104,8 +104,8 @@ class TermWidget(QWidget): :return: """ - self._edit.setTextColor(Qt.black) - self._edit.setTextBackgroundColor(Qt.white) + self._edit.setTextColor(QtCore.Qt.black) + self._edit.setTextBackgroundColor(QtCore.Qt.white) self._edit.setPlainText('') self._edit.setDisabled(False) self._edit.setFocus() @@ -292,14 +292,33 @@ class FCShell(TermWidget): self.init_tcl() self._edit.set_model_data(self.app.myKeywords) - self.setWindowIcon(self.app.ui.app_icon) + + app_icon = QtGui.QIcon() + app_icon.addFile(self.app.resource_location + '/flatcam_icon16.png', QtCore.QSize(16, 16)) + app_icon.addFile(self.app.resource_location + '/flatcam_icon24.png', QtCore.QSize(24, 24)) + app_icon.addFile(self.app.resource_location + '/flatcam_icon32.png', QtCore.QSize(32, 32)) + + self.setWindowIcon(app_icon) self.setWindowTitle(_("FlatCAM Shell")) self.resize(*self.app.defaults["global_shell_shape"]) self._append_to_browser('in', "FlatCAM %s - " % version) self.append_output('%s\n\n' % _("Type >help< to get started")) self.app.ui.shell_dock.setWidget(self) - self.app.log.debug("TCL Shell has been initialized.") + + # first try to disconnect the signals since within the app the Tcl Tool can be reinitialized + try: + self.app.inform_shell[str].disconnect() + except (TypeError, AttributeError): + pass + try: + self.app.inform_shell[str, bool].disconnect() + except (TypeError, AttributeError): + pass + + # signal for displaying messages in the shell + self.app.inform_shell[str].connect(self.app.info_shell) + self.app.inform_shell[str, bool].connect(self.app.info_shell) def init_tcl(self): if hasattr(self, 'tcl') and self.tcl is not None: diff --git a/app_Main.py b/app_Main.py index 1dda6f57..d8d12471 100644 --- a/app_Main.py +++ b/app_Main.py @@ -267,9 +267,9 @@ class App(QtCore.QObject): super().__init__() - # ############################################################################################################### - # ######################################### LOGGING ############################################################# - # ############################################################################################################### + # ############################################################################################################# + # ######################################### LOGGING ########################################################### + # ############################################################################################################# self.log = logging.getLogger('base') self.log.setLevel(logging.DEBUG) # log.setLevel(logging.WARNING) @@ -304,6 +304,134 @@ class App(QtCore.QObject): self.main_thread = QtWidgets.QApplication.instance().thread() + # ########################################################################################################### + # ########################################################################################################### + # ######################################## Variables for global usage ####################################### + # ########################################################################################################### + # ########################################################################################################### + + # hold the App units + self.units = 'MM' + + # coordinates for relative position display + self.rel_point1 = (0, 0) + self.rel_point2 = (0, 0) + + # variable to store coordinates + self.pos = (0, 0) + self.pos_canvas = (0, 0) + self.pos_jump = (0, 0) + + # variable to store mouse coordinates + self.mouse = [0, 0] + + # variable to store the delta positions on cavnas + self.dx = 0 + self.dy = 0 + + # decide if we have a double click or single click + self.doubleclick = False + + # store here the is_dragging value + self.event_is_dragging = False + + # variable to store if a command is active (then the var is not None) and which one it is + self.command_active = None + # variable to store the status of moving selection action + # None value means that it's not an selection action + # True value = a selection from left to right + # False value = a selection from right to left + self.selection_type = None + + # List to store the objects that are currently loaded in FlatCAM + # This list is updated on each object creation or object delete + self.all_objects_list = [] + + self.objects_under_the_click_list = [] + + # List to store the objects that are selected + self.sel_objects_list = [] + + # holds the key modifier if pressed (CTRL, SHIFT or ALT) + self.key_modifiers = None + + # Variable to store the status of the code editor + self.toggle_codeeditor = False + + # Variable to be used for situations when we don't want the LMB click on canvas to auto open the Project Tab + self.click_noproject = False + + self.cursor = None + + # Variable to store the GCODE that was edited + self.gcode_edited = "" + + # Variable to store old state of the Tools Toolbar; used in the Editor2Object and in Object2Editor methods + self.old_state_of_tools_toolbar = False + + self.text_editor_tab = None + + # here store the color of a Tab text before it is changed so it can be restored in the future + self.old_tab_text_color = None + + # reference for the self.ui.code_editor + self.reference_code_editor = None + self.script_code = '' + + # if Tools DB are changed/edited in the Edit -> Tools Database tab the value will be set to True + self.tools_db_changed_flag = False + + self.grb_list = ['art', 'bot', 'bsm', 'cmp', 'crc', 'crs', 'dim', 'g4', 'gb0', 'gb1', 'gb2', 'gb3', 'gb5', + 'gb6', 'gb7', 'gb8', 'gb9', 'gbd', 'gbl', 'gbo', 'gbp', 'gbr', 'gbs', 'gdo', 'ger', 'gko', + 'gml', 'gm1', 'gm2', 'gm3', 'grb', 'gtl', 'gto', 'gtp', 'gts', 'ly15', 'ly2', 'mil', 'outline', + 'pho', 'plc', 'pls', 'smb', 'smt', 'sol', 'spb', 'spt', 'ssb', 'sst', 'stc', 'sts', 'top', + 'tsm'] + + self.exc_list = ['drd', 'drl', 'drill', 'exc', 'ncd', 'tap', 'txt', 'xln'] + + self.gcode_list = ['cnc', 'din', 'dnc', 'ecs', 'eia', 'fan', 'fgc', 'fnc', 'gc', 'gcd', 'gcode', 'h', 'hnc', + 'i', 'min', 'mpf', 'mpr', 'nc', 'ncc', 'ncg', 'ngc', 'ncp', 'out', 'ply', 'rol', + 'sbp', 'tap', 'xpi'] + self.svg_list = ['svg'] + self.dxf_list = ['dxf'] + self.pdf_list = ['pdf'] + self.prj_list = ['flatprj'] + self.conf_list = ['flatconfig'] + + # last used filters + self.last_op_gerber_filter = None + self.last_op_excellon_filter = None + self.last_op_gcode_filter = None + + # global variable used by NCC Tool to signal that some polygons could not be cleared, if True + # flag for polygons not cleared + self.poly_not_cleared = False + + # VisPy visuals + self.isHovering = False + self.notHovering = True + + # Window geometry + self.x_pos = None + self.y_pos = None + self.width = None + self.height = None + + # this holds a widget that is installed in the Plot Area when View Source option is used + self.source_editor_tab = None + + self.pagesize = {} + + # used in the delayed shutdown self.start_delayed_quit() method + self.save_timer = None + + # to use for tools like Distance tool who depends on the event sources who are changed inside the appEditors + # depending on from where those tools are called different actions can be done + self.call_source = 'app' + + # this is a flag to signal to other tools that the ui tooltab is locked and not accessible + self.tool_tab_locked = False + # ############################################################################################################ # ################# Setup the listening thread for another instance launching with args ###################### # ############################################################################################################ @@ -469,329 +597,9 @@ class App(QtCore.QObject): self.current_units = self.defaults['units'] - # ############################################################################################################ - # ################################### Set LOG verbosity ###################################################### - # ############################################################################################################ - if self.defaults["global_log_verbose"] is True: - self.log.handlers.pop() - self.log = AppLogging(app=self) - - # ########################################################################################################### - # #################################### SETUP OBJECT CLASSES ################################################# - # ########################################################################################################### - self.setup_obj_classes() - - # ########################################################################################################### - # ###################################### CREATE MULTIPROCESSING POOL ####################################### - # ########################################################################################################### - self.pool = Pool() - - # ########################################################################################################### - # ###################################### Clear GUI Settings - once at first start ########################### - # ########################################################################################################### - if self.defaults["first_run"] is True: - # on first run clear the previous QSettings, therefore clearing the GUI settings - qsettings = QSettings("Open Source", "FlatCAM") - for key in qsettings.allKeys(): - qsettings.remove(key) - # This will write the setting to the platform specific storage. - del qsettings - - # ########################################################################################################### - # ###################################### Setting the Splash Screen ########################################## - # ########################################################################################################### - splash_settings = QSettings("Open Source", "FlatCAM") - if splash_settings.contains("splash_screen"): - show_splash = splash_settings.value("splash_screen") - else: - splash_settings.setValue('splash_screen', 1) - - # This will write the setting to the platform specific storage. - del splash_settings - show_splash = 1 - - if show_splash and self.cmd_line_headless != 1: - splash_pix = QtGui.QPixmap(self.resource_location + '/splash.png') - self.splash = QtWidgets.QSplashScreen(splash_pix, Qt.WindowStaysOnTopHint) - # self.splash.setMask(splash_pix.mask()) - - # move splashscreen to the current monitor - desktop = QtWidgets.QApplication.desktop() - screen = desktop.screenNumber(QtGui.QCursor.pos()) - current_screen_center = desktop.availableGeometry(screen).center() - self.splash.move(current_screen_center - self.splash.rect().center()) - - self.splash.show() - self.splash.showMessage(_("The application is initializing ..."), - alignment=Qt.AlignBottom | Qt.AlignLeft, - color=QtGui.QColor("gray")) - else: - self.splash = None - show_splash = 0 - - # ########################################################################################################### - # ######################################### Initialize GUI ################################################## - # ########################################################################################################### - - # FlatCAM colors used in plotting - self.FC_light_green = '#BBF268BF' - self.FC_dark_green = '#006E20BF' - self.FC_light_blue = '#a5a5ffbf' - self.FC_dark_blue = '#0000ffbf' - - theme_settings = QtCore.QSettings("Open Source", "FlatCAM") - if theme_settings.contains("theme"): - theme = theme_settings.value('theme', type=str) - else: - theme = 'white' - - if self.defaults["global_cursor_color_enabled"]: - self.cursor_color_3D = self.defaults["global_cursor_color"] - else: - if theme == 'white': - self.cursor_color_3D = 'black' - else: - self.cursor_color_3D = 'gray' - - # update the defaults dict with the setting in QSetting - self.defaults['global_theme'] = theme - - self.ui = MainGUI(self) - - # set FlatCAM units in the Status bar - self.set_screen_units(self.defaults['units']) - - # ########################################################################################################### - # ########################################### AUTOSAVE SETUP ################################################ - # ########################################################################################################### - - self.block_autosave = False - self.autosave_timer = QtCore.QTimer(self) - self.save_project_auto_update() - self.autosave_timer.timeout.connect(self.save_project_auto) - - # ########################################################################################################### - # #################################### LOAD PREPROCESSORS ################################################### - # ########################################################################################################### - - # ----------------------------------------- WARNING -------------------------------------------------------- - # Preprocessors need to be loaded before the Preferences Manager builds the Preferences - # That's because the number of preprocessors can vary and here the combobox is populated - # ----------------------------------------------------------------------------------------------------------- - - # a dictionary that have as keys the name of the preprocessor files and the value is the class from - # the preprocessor file - self.preprocessors = load_preprocessors(self) - - # make sure that always the 'default' preprocessor is the first item in the dictionary - if 'default' in self.preprocessors.keys(): - # add the 'default' name first in the dict after removing from the preprocessor's dictionary - default_pp = self.preprocessors.pop('default') - new_ppp_dict = { - 'default': default_pp - } - - # then add the rest of the keys - for name, val_class in self.preprocessors.items(): - new_ppp_dict[name] = val_class - - # and now put back the ordered dict with 'default' key first - self.preprocessors = deepcopy(new_ppp_dict) - - # populate the Preprocessor ComboBoxes in the PREFERENCES - for name in list(self.preprocessors.keys()): - # 'Paste' preprocessors are to be used only in the Solder Paste Dispensing Tool - if name.partition('_')[0] == 'Paste': - self.ui.tools_defaults_form.tools_solderpaste_group.pp_combo.addItem(name) - continue - - self.ui.geometry_defaults_form.geometry_opt_group.pp_geometry_name_cb.addItem(name) - # HPGL preprocessor is only for Geometry objects therefore it should not be in the Excellon Preferences - if name == 'hpgl': - continue - - self.ui.tools_defaults_form.tools_drill_group.pp_excellon_name_cb.addItem(name) - - # add ToolTips for the Preprocessor ComboBoxes in Preferences - for it in range(self.ui.tools_defaults_form.tools_solderpaste_group.pp_combo.count()): - self.ui.tools_defaults_form.tools_solderpaste_group.pp_combo.setItemData( - it, self.ui.tools_defaults_form.tools_solderpaste_group.pp_combo.itemText(it), QtCore.Qt.ToolTipRole) - for it in range(self.ui.geometry_defaults_form.geometry_opt_group.pp_geometry_name_cb.count()): - self.ui.geometry_defaults_form.geometry_opt_group.pp_geometry_name_cb.setItemData( - it, self.ui.geometry_defaults_form.geometry_opt_group.pp_geometry_name_cb.itemText(it), - QtCore.Qt.ToolTipRole) - for it in range(self.ui.tools_defaults_form.tools_drill_group.pp_excellon_name_cb.count()): - self.ui.tools_defaults_form.tools_drill_group.pp_excellon_name_cb.setItemData( - it, self.ui.tools_defaults_form.tools_drill_group.pp_excellon_name_cb.itemText(it), - QtCore.Qt.ToolTipRole) - - # ########################################################################################################### - # ##################################### UPDATE PREFERENCES GUI FORMS ######################################## - # ########################################################################################################### - - self.preferencesUiManager = PreferencesUIManager(defaults=self.defaults, data_path=self.data_path, ui=self.ui, - inform=self.inform) - - self.preferencesUiManager.defaults_write_form() - - # When the self.defaults dictionary changes will update the Preferences GUI forms - self.defaults.set_change_callback(self.on_defaults_dict_change) - - # ########################################################################################################### - # ########################################## LOAD LANGUAGES ################################################ - # ########################################################################################################### - - self.languages = fcTranslate.load_languages() - for name in sorted(self.languages.values()): - self.ui.general_defaults_form.general_app_group.language_cb.addItem(name) - - # ########################################################################################################### - # ####################################### APPLY APP LANGUAGE ################################################ - # ########################################################################################################### - - ret_val = fcTranslate.apply_language('strings') - - if ret_val == "no language": - self.inform.emit('[ERROR] %s' % _("Could not find the Language files. The App strings are missing.")) - self.log.debug("Could not find the Language files. The App strings are missing.") - else: - # make the current language the current selection on the language combobox - self.ui.general_defaults_form.general_app_group.language_cb.setCurrentText(ret_val) - self.log.debug("App.__init__() --> Applied %s language." % str(ret_val).capitalize()) - - # ########################################################################################################### - # ###################################### CREATE UNIQUE SERIAL NUMBER ######################################## - # ########################################################################################################### - - chars = 'abcdefghijklmnopqrstuvwxyz0123456789' - if self.defaults['global_serial'] == 0 or len(str(self.defaults['global_serial'])) < 10: - self.defaults['global_serial'] = ''.join([random.choice(chars) for __ in range(20)]) - self.preferencesUiManager.save_defaults(silent=True, first_time=True) - - self.defaults.propagate_defaults() - - # ########################################################################################################### - # ######################################## UPDATE THE OPTIONS ############################################### - # ########################################################################################################### - - self.options = LoudDict() - # ----------------------------------------------------------------------------------------------------------- - # Update the self.options from the self.defaults - # The self.defaults holds the application defaults while the self.options holds the object defaults - # ----------------------------------------------------------------------------------------------------------- - # Copy app defaults to project options - for def_key, def_val in self.defaults.items(): - self.options[def_key] = deepcopy(def_val) - - self.preferencesUiManager.show_preferences_gui() - - # ### End of Data #### - - # ########################################################################################################### - # #################################### SETUP OBJECT COLLECTION ############################################## - # ########################################################################################################### - - self.collection = ObjectCollection(app=self) - self.ui.project_tab_layout.addWidget(self.collection.view) - - self.app_obj = AppObject(app=self) - - # ### Adjust tabs width ## ## - # self.collection.view.setMinimumWidth(self.ui.options_scroll_area.widget().sizeHint().width() + - # self.ui.options_scroll_area.verticalScrollBar().sizeHint().width()) - self.collection.view.setMinimumWidth(290) - self.log.debug("Finished creating Object Collection.") - - # ########################################################################################################### - # ######################################## SETUP Plot Area ################################################## - # ########################################################################################################### - - # determine if the Legacy Graphic Engine is to be used or the OpenGL one - if self.defaults["global_graphic_engine"] == '3D': - self.is_legacy = False - else: - self.is_legacy = True - - # Event signals disconnect id holders - self.mp = None - self.mm = None - self.mr = None - self.mdc = None - self.mp_zc = None - self.kp = None - - # Matplotlib axis - self.axes = None - - if show_splash: - self.splash.showMessage(_("The application is initializing ...\n" - "Canvas initialization started."), - alignment=Qt.AlignBottom | Qt.AlignLeft, - color=QtGui.QColor("gray")) - start_plot_time = time.time() # debug - - self.app_cursor = None - self.hover_shapes = None - - self.log.debug("Setting up canvas: %s" % str(self.defaults["global_graphic_engine"])) - - # setup the PlotCanvas - self.plotcanvas = self.on_plotcanvas_setup() - if self.plotcanvas == 'fail': - return - - end_plot_time = time.time() - self.used_time = end_plot_time - start_plot_time - self.log.debug("Finished Canvas initialization in %s seconds." % str(self.used_time)) - - if show_splash: - self.splash.showMessage('%s: %ssec' % (_("The application is initializing ...\n" - "Canvas initialization started.\n" - "Canvas initialization finished in"), '%.2f' % self.used_time), - alignment=Qt.AlignBottom | Qt.AlignLeft, - color=QtGui.QColor("gray")) - self.ui.splitter.setStretchFactor(1, 2) - - # ########################################################################################################### - # ############################################### Worker SETUP ############################################## - # ########################################################################################################### - if self.defaults["global_worker_number"]: - self.workers = WorkerStack(workers_number=int(self.defaults["global_worker_number"])) - else: - self.workers = WorkerStack(workers_number=2) - - self.worker_task.connect(self.workers.add_task) - self.log.debug("Finished creating Workers crew.") - - # ########################################################################################################### - # ############################################# Activity Monitor ############################################ - # ########################################################################################################### - # self.activity_view = FlatCAMActivityView(app=self) - # self.ui.infobar.addWidget(self.activity_view) - self.proc_container = FCVisibleProcessContainer(self.ui.activity_view) - - # ########################################################################################################### - # ########################################## Other setups ################################################### - # ########################################################################################################### - - # to use for tools like Distance tool who depends on the event sources who are changed inside the appEditors - # depending on from where those tools are called different actions can be done - self.call_source = 'app' - - # this is a flag to signal to other tools that the ui tooltab is locked and not accessible - self.tool_tab_locked = False - - # decide if to show or hide the Notebook side of the screen at startup - if self.defaults["global_project_at_startup"] is True: - self.ui.splitter.setSizes([1, 1]) - else: - self.ui.splitter.setSizes([0, 1]) - - # Sets up FlatCAMObj, FCProcess and FCProcessContainer. - self.setup_default_properties_tab() - # ########################################################################################################### # ####################################### Auto-complete KEYWORDS ############################################ + # ######################## Setup after the Defaults class was instantiated ################################## # ########################################################################################################### self.tcl_commands_list = ['add_circle', 'add_poly', 'add_polygon', 'add_polyline', 'add_rectangle', 'aligndrill', 'aligndrillgrid', 'bbox', 'clear', 'cncjob', 'cutout', @@ -1023,11 +831,344 @@ class App(QtCore.QObject): self.autocomplete_kw_list = self.defaults['util_autocomplete_keywords'].replace(' ', '').split(',') self.myKeywords = self.tcl_commands_list + self.autocomplete_kw_list + self.tcl_keywords + # ############################################################################################################ + # ################################### Set LOG verbosity ###################################################### + # ############################################################################################################ + if self.defaults["global_log_verbose"] is True: + self.log.handlers.pop() + self.log = AppLogging(app=self) + + # ########################################################################################################### + # #################################### SETUP OBJECT CLASSES ################################################# + # ########################################################################################################### + self.setup_obj_classes() + + # ########################################################################################################### + # ###################################### CREATE MULTIPROCESSING POOL ####################################### + # ########################################################################################################### + self.pool = Pool() + + # ########################################################################################################### + # ###################################### Clear GUI Settings - once at first start ########################### + # ########################################################################################################### + if self.defaults["first_run"] is True: + # on first run clear the previous QSettings, therefore clearing the GUI settings + qsettings = QSettings("Open Source", "FlatCAM") + for key in qsettings.allKeys(): + qsettings.remove(key) + # This will write the setting to the platform specific storage. + del qsettings + + # ########################################################################################################### + # ###################################### Setting the Splash Screen ########################################## + # ########################################################################################################### + splash_settings = QSettings("Open Source", "FlatCAM") + if splash_settings.contains("splash_screen"): + show_splash = splash_settings.value("splash_screen") + else: + splash_settings.setValue('splash_screen', 1) + + # This will write the setting to the platform specific storage. + del splash_settings + show_splash = 1 + + if show_splash and self.cmd_line_headless != 1: + splash_pix = QtGui.QPixmap(self.resource_location + '/splash.png') + self.splash = QtWidgets.QSplashScreen(splash_pix, Qt.WindowStaysOnTopHint) + # self.splash.setMask(splash_pix.mask()) + + # move splashscreen to the current monitor + desktop = QtWidgets.QApplication.desktop() + screen = desktop.screenNumber(QtGui.QCursor.pos()) + current_screen_center = desktop.availableGeometry(screen).center() + self.splash.move(current_screen_center - self.splash.rect().center()) + + self.splash.show() + self.splash.showMessage(_("The application is initializing ..."), + alignment=Qt.AlignBottom | Qt.AlignLeft, + color=QtGui.QColor("gray")) + else: + self.splash = None + show_splash = 0 + + # ########################################################################################################### + # ######################################### Initialize GUI ################################################## + # ########################################################################################################### + + # FlatCAM colors used in plotting + self.FC_light_green = '#BBF268BF' + self.FC_dark_green = '#006E20BF' + self.FC_light_blue = '#a5a5ffbf' + self.FC_dark_blue = '#0000ffbf' + + theme_settings = QtCore.QSettings("Open Source", "FlatCAM") + if theme_settings.contains("theme"): + theme = theme_settings.value('theme', type=str) + else: + theme = 'white' + + if self.defaults["global_cursor_color_enabled"]: + self.cursor_color_3D = self.defaults["global_cursor_color"] + else: + if theme == 'white': + self.cursor_color_3D = 'black' + else: + self.cursor_color_3D = 'gray' + + # update the defaults dict with the setting in QSetting + self.defaults['global_theme'] = theme + + self.ui = MainGUI(self) + + # set FlatCAM units in the Status bar + self.set_screen_units(self.defaults['units']) + + # decide if to show or hide the Notebook side of the screen at startup + if self.defaults["global_project_at_startup"] is True: + self.ui.splitter.setSizes([1, 1]) + else: + self.ui.splitter.setSizes([0, 1]) + + # ########################################################################################################### + # ########################################### Initialize Tcl Shell ########################################## + # ########################### always initialize it after the UI is initialized ######################### + # ########################################################################################################### + self.shell = FCShell(app=self, version=self.version) + self.log.debug("Stardate: %s" % self.date) + self.log.debug("TCL Shell has been initialized.") + + # ########################################################################################################### + # ########################################### AUTOSAVE SETUP ################################################ + # ########################################################################################################### + + self.block_autosave = False + self.autosave_timer = QtCore.QTimer(self) + self.save_project_auto_update() + self.autosave_timer.timeout.connect(self.save_project_auto) + + # ########################################################################################################### + # #################################### LOAD PREPROCESSORS ################################################### + # ########################################################################################################### + + # ----------------------------------------- WARNING -------------------------------------------------------- + # Preprocessors need to be loaded before the Preferences Manager builds the Preferences + # That's because the number of preprocessors can vary and here the combobox is populated + # ----------------------------------------------------------------------------------------------------------- + + # a dictionary that have as keys the name of the preprocessor files and the value is the class from + # the preprocessor file + self.preprocessors = load_preprocessors(self) + + # make sure that always the 'default' preprocessor is the first item in the dictionary + if 'default' in self.preprocessors.keys(): + # add the 'default' name first in the dict after removing from the preprocessor's dictionary + default_pp = self.preprocessors.pop('default') + new_ppp_dict = { + 'default': default_pp + } + + # then add the rest of the keys + for name, val_class in self.preprocessors.items(): + new_ppp_dict[name] = val_class + + # and now put back the ordered dict with 'default' key first + self.preprocessors = deepcopy(new_ppp_dict) + + # populate the Preprocessor ComboBoxes in the PREFERENCES + for name in list(self.preprocessors.keys()): + # 'Paste' preprocessors are to be used only in the Solder Paste Dispensing Tool + if name.partition('_')[0] == 'Paste': + self.ui.tools_defaults_form.tools_solderpaste_group.pp_combo.addItem(name) + continue + + self.ui.geometry_defaults_form.geometry_opt_group.pp_geometry_name_cb.addItem(name) + # HPGL preprocessor is only for Geometry objects therefore it should not be in the Excellon Preferences + if name == 'hpgl': + continue + + self.ui.tools_defaults_form.tools_drill_group.pp_excellon_name_cb.addItem(name) + + # add ToolTips for the Preprocessor ComboBoxes in Preferences + for it in range(self.ui.tools_defaults_form.tools_solderpaste_group.pp_combo.count()): + self.ui.tools_defaults_form.tools_solderpaste_group.pp_combo.setItemData( + it, self.ui.tools_defaults_form.tools_solderpaste_group.pp_combo.itemText(it), QtCore.Qt.ToolTipRole) + for it in range(self.ui.geometry_defaults_form.geometry_opt_group.pp_geometry_name_cb.count()): + self.ui.geometry_defaults_form.geometry_opt_group.pp_geometry_name_cb.setItemData( + it, self.ui.geometry_defaults_form.geometry_opt_group.pp_geometry_name_cb.itemText(it), + QtCore.Qt.ToolTipRole) + for it in range(self.ui.tools_defaults_form.tools_drill_group.pp_excellon_name_cb.count()): + self.ui.tools_defaults_form.tools_drill_group.pp_excellon_name_cb.setItemData( + it, self.ui.tools_defaults_form.tools_drill_group.pp_excellon_name_cb.itemText(it), + QtCore.Qt.ToolTipRole) + + # ########################################################################################################### + # ##################################### UPDATE PREFERENCES GUI FORMS ######################################## + # ########################################################################################################### + + self.preferencesUiManager = PreferencesUIManager(defaults=self.defaults, data_path=self.data_path, ui=self.ui, + inform=self.inform) + + self.preferencesUiManager.defaults_write_form() + + # When the self.defaults dictionary changes will update the Preferences GUI forms + self.defaults.set_change_callback(self.on_defaults_dict_change) + + # set the value used in the Windows Title + self.engine = self.ui.general_defaults_form.general_app_group.ge_radio.get_value() + + # ########################################################################################################### + # ########################################## LOAD LANGUAGES ################################################ + # ########################################################################################################### + + self.languages = fcTranslate.load_languages() + for name in sorted(self.languages.values()): + self.ui.general_defaults_form.general_app_group.language_cb.addItem(name) + + # ########################################################################################################### + # ####################################### APPLY APP LANGUAGE ################################################ + # ########################################################################################################### + + ret_val = fcTranslate.apply_language('strings') + + if ret_val == "no language": + self.inform.emit('[ERROR] %s' % _("Could not find the Language files. The App strings are missing.")) + self.log.debug("Could not find the Language files. The App strings are missing.") + else: + # make the current language the current selection on the language combobox + self.ui.general_defaults_form.general_app_group.language_cb.setCurrentText(ret_val) + self.log.debug("App.__init__() --> Applied %s language." % str(ret_val).capitalize()) + + # ########################################################################################################### + # ###################################### CREATE UNIQUE SERIAL NUMBER ######################################## + # ########################################################################################################### + + chars = 'abcdefghijklmnopqrstuvwxyz0123456789' + if self.defaults['global_serial'] == 0 or len(str(self.defaults['global_serial'])) < 10: + self.defaults['global_serial'] = ''.join([random.choice(chars) for __ in range(20)]) + self.preferencesUiManager.save_defaults(silent=True, first_time=True) + + self.defaults.propagate_defaults() + + # ########################################################################################################### + # ######################################## UPDATE THE OPTIONS ############################################### + # ########################################################################################################### + + self.options = LoudDict() + # ----------------------------------------------------------------------------------------------------------- + # Update the self.options from the self.defaults + # The self.defaults holds the application defaults while the self.options holds the object defaults + # ----------------------------------------------------------------------------------------------------------- + # Copy app defaults to project options + for def_key, def_val in self.defaults.items(): + self.options[def_key] = deepcopy(def_val) + + self.preferencesUiManager.show_preferences_gui() + + # ########################################################################################################### + # #################################### SETUP OBJECT COLLECTION ############################################## + # ########################################################################################################### + + self.collection = ObjectCollection(app=self) + self.ui.project_tab_layout.addWidget(self.collection.view) + + self.app_obj = AppObject(app=self) + + # ### Adjust tabs width ## ## + # self.collection.view.setMinimumWidth(self.ui.options_scroll_area.widget().sizeHint().width() + + # self.ui.options_scroll_area.verticalScrollBar().sizeHint().width()) + self.collection.view.setMinimumWidth(290) + self.log.debug("Finished creating Object Collection.") + + # ########################################################################################################### + # ######################################## SETUP Plot Area ################################################## + # ########################################################################################################### + + # determine if the Legacy Graphic Engine is to be used or the OpenGL one + if self.defaults["global_graphic_engine"] == '3D': + self.is_legacy = False + else: + self.is_legacy = True + + # PlotCanvas Event signals disconnect id holders + self.mp = None + self.mm = None + self.mr = None + self.mdc = None + self.mp_zc = None + self.kp = None + + # Matplotlib axis + self.axes = None + + self.app_cursor = None + self.hover_shapes = None + + if show_splash: + self.splash.showMessage(_("The application is initializing ...\n" + "Canvas initialization started."), + alignment=Qt.AlignBottom | Qt.AlignLeft, + color=QtGui.QColor("gray")) + start_plot_time = time.time() # debug + + self.log.debug("Setting up canvas: %s" % str(self.defaults["global_graphic_engine"])) + + # setup the PlotCanvas + self.plotcanvas = self.on_plotcanvas_setup() + if self.plotcanvas == 'fail': + return + + end_plot_time = time.time() + self.used_time = end_plot_time - start_plot_time + self.log.debug("Finished Canvas initialization in %s seconds." % str(self.used_time)) + + if show_splash: + self.splash.showMessage('%s: %ssec' % (_("The application is initializing ...\n" + "Canvas initialization started.\n" + "Canvas initialization finished in"), '%.2f' % self.used_time), + alignment=Qt.AlignBottom | Qt.AlignLeft, + color=QtGui.QColor("gray")) + self.ui.splitter.setStretchFactor(1, 2) + + # Storage for shapes, storage that can be used by FlatCAm tools for utility geometry + # VisPy visuals + if self.is_legacy is False: + try: + self.tool_shapes = ShapeCollection(parent=self.plotcanvas.view.scene, layers=1) + except AttributeError: + self.tool_shapes = None + else: + from appGUI.PlotCanvasLegacy import ShapeCollectionLegacy + self.tool_shapes = ShapeCollectionLegacy(obj=self, app=self, name="tool") + + # ########################################################################################################### + # ############################################### Worker SETUP ############################################## + # ########################################################################################################### + if self.defaults["global_worker_number"]: + self.workers = WorkerStack(workers_number=int(self.defaults["global_worker_number"])) + else: + self.workers = WorkerStack(workers_number=2) + + self.worker_task.connect(self.workers.add_task) + self.log.debug("Finished creating Workers crew.") + + # ########################################################################################################### + # ############################################# Activity Monitor ############################################ + # ########################################################################################################### + # self.activity_view = FlatCAMActivityView(app=self) + # self.ui.infobar.addWidget(self.activity_view) + self.proc_container = FCVisibleProcessContainer(self.ui.activity_view) + + # ########################################################################################################### + # ########################################## Other setups ################################################### + # ########################################################################################################### + + # Sets up FlatCAMObj, FCProcess and FCProcessContainer. + self.setup_default_properties_tab() + # ########################################################################################################### # ########################################## Tools and Plugins ############################################## # ########################################################################################################### - self.shell = FCShell(app=self, version=self.version) self.dblsidedtool = None self.distance_tool = None self.distance_min_tool = None @@ -1108,8 +1249,7 @@ class App(QtCore.QObject): self.log.info("Checking for updates in backgroud (this is version %s)." % str(self.version)) # self.thr2 = QtCore.QThread() - self.worker_task.emit({'fcn': self.version_check, - 'params': []}) + self.worker_task.emit({'fcn': self.version_check, 'params': []}) # self.thr2.start(QtCore.QThread.LowPriority) # ########################################################################################################### @@ -1119,139 +1259,6 @@ class App(QtCore.QObject): if sys.platform == 'win32' and self.defaults["first_run"] is True: self.on_register_files() - # ########################################################################################################### - # ######################################## Variables for global usage ####################################### - # ########################################################################################################### - - # hold the App units - self.units = 'MM' - - # coordinates for relative position display - self.rel_point1 = (0, 0) - self.rel_point2 = (0, 0) - - # variable to store coordinates - self.pos = (0, 0) - self.pos_canvas = (0, 0) - self.pos_jump = (0, 0) - - # variable to store mouse coordinates - self.mouse = [0, 0] - - # variable to store the delta positions on cavnas - self.dx = 0 - self.dy = 0 - - # decide if we have a double click or single click - self.doubleclick = False - - # store here the is_dragging value - self.event_is_dragging = False - - # variable to store if a command is active (then the var is not None) and which one it is - self.command_active = None - # variable to store the status of moving selection action - # None value means that it's not an selection action - # True value = a selection from left to right - # False value = a selection from right to left - self.selection_type = None - - # List to store the objects that are currently loaded in FlatCAM - # This list is updated on each object creation or object delete - self.all_objects_list = [] - - self.objects_under_the_click_list = [] - - # List to store the objects that are selected - self.sel_objects_list = [] - - # holds the key modifier if pressed (CTRL, SHIFT or ALT) - self.key_modifiers = None - - # Variable to store the status of the code editor - self.toggle_codeeditor = False - - # Variable to be used for situations when we don't want the LMB click on canvas to auto open the Project Tab - self.click_noproject = False - - self.cursor = None - - # Variable to store the GCODE that was edited - self.gcode_edited = "" - - # Variable to store old state of the Tools Toolbar; used in the Editor2Object and in Object2Editor methods - self.old_state_of_tools_toolbar = False - - self.text_editor_tab = None - - # here store the color of a Tab text before it is changed so it can be restored in the future - self.old_tab_text_color = None - - # reference for the self.ui.code_editor - self.reference_code_editor = None - self.script_code = '' - - # if Tools DB are changed/edited in the Edit -> Tools Database tab the value will be set to True - self.tools_db_changed_flag = False - - self.grb_list = ['art', 'bot', 'bsm', 'cmp', 'crc', 'crs', 'dim', 'g4', 'gb0', 'gb1', 'gb2', 'gb3', 'gb5', - 'gb6', 'gb7', 'gb8', 'gb9', 'gbd', 'gbl', 'gbo', 'gbp', 'gbr', 'gbs', 'gdo', 'ger', 'gko', - 'gml', 'gm1', 'gm2', 'gm3', 'grb', 'gtl', 'gto', 'gtp', 'gts', 'ly15', 'ly2', 'mil', 'outline', - 'pho', 'plc', 'pls', 'smb', 'smt', 'sol', 'spb', 'spt', 'ssb', 'sst', 'stc', 'sts', 'top', - 'tsm'] - - self.exc_list = ['drd', 'drl', 'drill', 'exc', 'ncd', 'tap', 'txt', 'xln'] - - self.gcode_list = ['cnc', 'din', 'dnc', 'ecs', 'eia', 'fan', 'fgc', 'fnc', 'gc', 'gcd', 'gcode', 'h', 'hnc', - 'i', 'min', 'mpf', 'mpr', 'nc', 'ncc', 'ncg', 'ngc', 'ncp', 'out', 'ply', 'rol', - 'sbp', 'tap', 'xpi'] - self.svg_list = ['svg'] - self.dxf_list = ['dxf'] - self.pdf_list = ['pdf'] - self.prj_list = ['flatprj'] - self.conf_list = ['flatconfig'] - - # last used filters - self.last_op_gerber_filter = None - self.last_op_excellon_filter = None - self.last_op_gcode_filter = None - - # global variable used by NCC Tool to signal that some polygons could not be cleared, if True - # flag for polygons not cleared - self.poly_not_cleared = False - - # VisPy visuals - self.isHovering = False - self.notHovering = True - - # Window geometry - self.x_pos = None - self.y_pos = None - self.width = None - self.height = None - - # set the value used in the Windows Title - self.engine = self.ui.general_defaults_form.general_app_group.ge_radio.get_value() - - # this holds a widget that is installed in the Plot Area when View Source option is used - self.source_editor_tab = None - - self.pagesize = {} - - # Storage for shapes, storage that can be used by FlatCAm tools for utility geometry - # VisPy visuals - if self.is_legacy is False: - try: - self.tool_shapes = ShapeCollection(parent=self.plotcanvas.view.scene, layers=1) - except AttributeError: - self.tool_shapes = None - else: - from appGUI.PlotCanvasLegacy import ShapeCollectionLegacy - self.tool_shapes = ShapeCollectionLegacy(obj=self, app=self, name="tool") - - # used in the delayed shutdown self.start_delayed_quit() method - self.save_timer = None - # ########################################################################################################### # ################################## ADDING FlatCAM EDITORS section ######################################### # ########################################################################################################### @@ -1364,9 +1371,7 @@ class App(QtCore.QObject): self.inform[str].connect(self.info) self.inform[str, bool].connect(self.info) - # signal for displaying messages in the shell - self.inform_shell[str].connect(self.info_shell) - self.inform_shell[str, bool].connect(self.info_shell) + # signals for displaying messages in the Tcl Shell are now connected in the ToolShell class # signal to be called when the app is quiting self.app_quit.connect(self.quit_application, type=Qt.QueuedConnection) @@ -1398,7 +1403,7 @@ class App(QtCore.QObject): # Tool Signals self.ui.menutoolshell.triggered.connect(self.ui.toggle_shell_ui) - # the rest are autoinserted + # the rest are auto-inserted # Help Signals self.connect_menuhelp_signals() @@ -1528,6 +1533,7 @@ class App(QtCore.QObject): # ##################################### Finished the CONSTRUCTOR ############################################ # ########################################################################################################### self.log.debug("END of constructor. Releasing control.") + self.log.debug("... Resistance is futile. You will be assimilated ...\n") # ########################################################################################################### # ########################################## SHOW GUI ####################################################### @@ -1803,7 +1809,7 @@ class App(QtCore.QObject): gc.collect() - def install_tools(self): + def install_tools(self, init_tcl=False): """ This installs the FlatCAM tools (plugin-like) which reside in their own classes. Instantiation of the Tools classes. @@ -1812,8 +1818,9 @@ class App(QtCore.QObject): :return: None """ - # shell tool has to be initialized always first because other tools print messages in the Shell Dock - self.shell = FCShell(app=self, version=self.version) + if init_tcl: + # shell tool has to be initialized always first because other tools print messages in the Shell Dock + self.shell = FCShell(app=self, version=self.version) self.distance_tool = Distance(self) self.distance_tool.install(icon=QtGui.QIcon(self.resource_location + '/distance16.png'), pos=self.ui.menuedit, @@ -1988,7 +1995,7 @@ class App(QtCore.QObject): # third install all of them try: - self.install_tools() + self.install_tools(init_tcl=True) except AttributeError: pass @@ -2853,17 +2860,19 @@ class App(QtCore.QObject): self.defaults.report_usage("save_to_file") self.log.debug("save_to_file()") - self.date = str(datetime.today()).rpartition('.')[0] - self.date = ''.join(c for c in self.date if c not in ':-') - self.date = self.date.replace(' ', '_') + date = str(datetime.today()).rpartition('.')[0] + date = ''.join(c for c in date if c not in ':-') + date = date.replace(' ', '_') filter__ = "HTML File .html (*.html);;TXT File .txt (*.txt);;All Files (*.*)" path_to_save = self.defaults["global_last_save_folder"] if \ self.defaults["global_last_save_folder"] is not None else self.data_path + final_path = os.path.join(path_to_save, 'file_%s' % str(date)) + try: filename, _f = FCFileSaveDialog.get_saved_filename( caption=_("Save to file"), - directory=path_to_save + '/file_' + self.date, + directory=final_path, ext_filter=filter__ ) except TypeError: diff --git a/defaults.py b/defaults.py index 3b4964c8..dff1784c 100644 --- a/defaults.py +++ b/defaults.py @@ -46,8 +46,6 @@ class FlatCAMDefaults: # 1 = show trace(show trace always), # 2 = (For the future). - "global_log_verbose": False, - "global_grid_context_menu": { 'in': [0.01, 0.02, 0.025, 0.05, 0.1], 'mm': [0.1, 0.2, 0.5, 1, 2.54] @@ -86,6 +84,7 @@ class FlatCAMDefaults: "global_graphic_engine": '3D', "global_app_level": 'b', + "global_log_verbose": False, "global_portable": False, "global_language": 'English',