From 9ec6b3afb2157d995e1506da1fb7c42077ca5cae Mon Sep 17 00:00:00 2001 From: David Robertson Date: Fri, 1 May 2020 01:27:05 +0100 Subject: [PATCH 01/41] Deduplicate code in PreferencesUIManager.show_preferences_gui() --- .../preferences/PreferencesUIManager.py | 109 +++++++----------- 1 file changed, 43 insertions(+), 66 deletions(-) diff --git a/flatcamGUI/preferences/PreferencesUIManager.py b/flatcamGUI/preferences/PreferencesUIManager.py index 7934cdc6..1cb17c12 100644 --- a/flatcamGUI/preferences/PreferencesUIManager.py +++ b/flatcamGUI/preferences/PreferencesUIManager.py @@ -1,4 +1,6 @@ import os +from typing import Any, Dict + from PyQt5 import QtGui, QtCore, QtWidgets from PyQt5.QtCore import QSettings from defaults import FlatCAMDefaults @@ -583,15 +585,44 @@ class PreferencesUIManager: } + self.child_forms = { + "general": ui.general_defaults_form, + "gerber": ui.gerber_defaults_form, + "excellon": ui.excellon_defaults_form, + "geometry": ui.geometry_defaults_form, + "cncjob": ui.cncjob_defaults_form, + "tools": ui.tools_defaults_form, + "tools2": ui.tools2_defaults_form, + "util": ui.util_defaults_form + } + self.child_scroll_areas = { + "general": ui.general_scroll_area, + "gerber": ui.gerber_scroll_area, + "excellon": ui.excellon_scroll_area, + "geometry": ui.geometry_scroll_area, + "cncjob": ui.cncjob_scroll_area, + "tools": ui.tools_scroll_area, + "tools2": ui.tools2_scroll_area, + "util": ui.fa_scroll_area + } + + def get_form_fields(self) -> Dict[str, Any]: + return self.defaults_form_fields + + def get_form_field(self, option: str) -> Any: + return self.get_form_fields()[option] + + + def defaults_read_form(self): """ Will read all the values in the Preferences GUI and update the defaults dictionary. :return: None """ - for option in self.defaults_form_fields: + for option in self.get_form_fields(): try: - self.defaults[option] = self.defaults_form_fields[option].get_value() + self.defaults[option] = self.get_form_field(option=option).get_value() except Exception as e: log.debug("App.defaults_read_form() --> %s" % str(e)) @@ -633,7 +664,7 @@ class PreferencesUIManager: if factor is not None: value *= factor - form_field = self.defaults_form_fields[field] + form_field = self.get_form_field(option=field) if units is None: form_field.set_value(value) elif (units == 'IN' or units == 'MM') and (field == 'global_gridx' or field == 'global_gridy'): @@ -651,69 +682,15 @@ class PreferencesUIManager: :return: None """ - gen_form = self.ui.general_defaults_form - try: - self.ui.general_scroll_area.takeWidget() - except Exception: - log.debug("Nothing to remove") - self.ui.general_scroll_area.setWidget(gen_form) - gen_form.show() - - ger_form = self.ui.gerber_defaults_form - try: - self.ui.gerber_scroll_area.takeWidget() - except Exception: - log.debug("Nothing to remove") - self.ui.gerber_scroll_area.setWidget(ger_form) - ger_form.show() - - exc_form = self.ui.excellon_defaults_form - try: - self.ui.excellon_scroll_area.takeWidget() - except Exception: - log.debug("Nothing to remove") - self.ui.excellon_scroll_area.setWidget(exc_form) - exc_form.show() - - geo_form = self.ui.geometry_defaults_form - try: - self.ui.geometry_scroll_area.takeWidget() - except Exception: - log.debug("Nothing to remove") - self.ui.geometry_scroll_area.setWidget(geo_form) - geo_form.show() - - cnc_form = self.ui.cncjob_defaults_form - try: - self.ui.cncjob_scroll_area.takeWidget() - except Exception: - log.debug("Nothing to remove") - self.ui.cncjob_scroll_area.setWidget(cnc_form) - cnc_form.show() - - tools_form = self.ui.tools_defaults_form - try: - self.ui.tools_scroll_area.takeWidget() - except Exception: - log.debug("Nothing to remove") - self.ui.tools_scroll_area.setWidget(tools_form) - tools_form.show() - - tools2_form = self.ui.tools2_defaults_form - try: - self.ui.tools2_scroll_area.takeWidget() - except Exception: - log.debug("Nothing to remove") - self.ui.tools2_scroll_area.setWidget(tools2_form) - tools2_form.show() - - fa_form = self.ui.util_defaults_form - try: - self.ui.fa_scroll_area.takeWidget() - except Exception: - log.debug("Nothing to remove") - self.ui.fa_scroll_area.setWidget(fa_form) - fa_form.show() + for section in self.child_scroll_areas: + scroll_area = self.child_scroll_areas[section] + form = self.child_forms[section] + try: + scroll_area.takeWidget() + except Exception: + log.debug("Nothing to remove for section "+section) + scroll_area.setWidget(form) + form.show() # Initialize the color box's color in Preferences -> Global -> Colo self.__init_color_pickers() From 86ef9d903867172fb38b23d7cf8e39e9ca1ad980 Mon Sep 17 00:00:00 2001 From: David Robertson Date: Fri, 1 May 2020 02:21:59 +0100 Subject: [PATCH 02/41] Introduce a PreferencesSectionUI widget --- .../preferences/PreferencesSectionUI.py | 22 ++++++++++++ .../preferences/PreferencesUIManager.py | 1 - .../general/GeneralPreferencesUI.py | 34 +++++++++---------- 3 files changed, 38 insertions(+), 19 deletions(-) create mode 100644 flatcamGUI/preferences/PreferencesSectionUI.py diff --git a/flatcamGUI/preferences/PreferencesSectionUI.py b/flatcamGUI/preferences/PreferencesSectionUI.py new file mode 100644 index 00000000..ad70a9ff --- /dev/null +++ b/flatcamGUI/preferences/PreferencesSectionUI.py @@ -0,0 +1,22 @@ +from PyQt5 import QtWidgets + +from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI + + +class PreferencesSectionUI(QtWidgets.QWidget): + + def __init__(self, **kwargs): + super().__init__(**kwargs) + + self.layout = QtWidgets.QHBoxLayout() + self.setLayout(self.layout) + + self.groups = self.build_groups() + for group in self.groups: + group.setMinimumWidth(250) + self.layout.addWidget(group) + + self.layout.addStretch() + + def build_groups(self) -> [OptionsGroupUI]: + return [] diff --git a/flatcamGUI/preferences/PreferencesUIManager.py b/flatcamGUI/preferences/PreferencesUIManager.py index 1cb17c12..35733b99 100644 --- a/flatcamGUI/preferences/PreferencesUIManager.py +++ b/flatcamGUI/preferences/PreferencesUIManager.py @@ -22,7 +22,6 @@ else: log = logging.getLogger('PreferencesUIManager') - class PreferencesUIManager: def __init__(self, defaults: FlatCAMDefaults, data_path: str, ui, inform): diff --git a/flatcamGUI/preferences/general/GeneralPreferencesUI.py b/flatcamGUI/preferences/general/GeneralPreferencesUI.py index 46636438..59e99174 100644 --- a/flatcamGUI/preferences/general/GeneralPreferencesUI.py +++ b/flatcamGUI/preferences/general/GeneralPreferencesUI.py @@ -1,9 +1,10 @@ -from PyQt5 import QtWidgets from PyQt5.QtCore import QSettings +from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI +from flatcamGUI.preferences.PreferencesSectionUI import PreferencesSectionUI from flatcamGUI.preferences.general.GeneralAppPrefGroupUI import GeneralAppPrefGroupUI from flatcamGUI.preferences.general.GeneralAPPSetGroupUI import GeneralAPPSetGroupUI -from flatcamGUI.preferences.general.GeneralGUIPrefGroupUI import GeneralGUIPrefGroupUI +from flatcamGUI.preferences.general.GeneralGUIPrefGroupUI import GeneralGUIPrefGroupUI, GeneralGUIPrefGroupUI2 import gettext import FlatCAMTranslation as fcTranslate @@ -20,24 +21,21 @@ else: machinist_setting = 0 -class GeneralPreferencesUI(QtWidgets.QWidget): - def __init__(self, decimals, parent=None): - QtWidgets.QWidget.__init__(self, parent=parent) - self.layout = QtWidgets.QHBoxLayout() - self.setLayout(self.layout) +class GeneralPreferencesUI(PreferencesSectionUI): + + def __init__(self, decimals, **kwargs): self.decimals = decimals - - self.general_app_group = GeneralAppPrefGroupUI(decimals=self.decimals) - self.general_app_group.setMinimumWidth(250) - self.general_gui_group = GeneralGUIPrefGroupUI(decimals=self.decimals) - self.general_gui_group.setMinimumWidth(250) - + #self.general_gui_group2 = GeneralGUIPrefGroupUI2(decimals=self.decimals) + self.general_app_group = GeneralAppPrefGroupUI(decimals=self.decimals) self.general_app_set_group = GeneralAPPSetGroupUI(decimals=self.decimals) - self.general_app_set_group.setMinimumWidth(250) + super().__init__(**kwargs) - self.layout.addWidget(self.general_app_group) - self.layout.addWidget(self.general_gui_group) - self.layout.addWidget(self.general_app_set_group) + def build_groups(self) -> [OptionsGroupUI]: + return [ + self.general_app_group, + self.general_gui_group, + self.general_gui_group2, + self.general_app_set_group + ] - self.layout.addStretch() From a00cdd6de7016b1f9039412b0d6c283b0d7a18ab Mon Sep 17 00:00:00 2001 From: David Robertson Date: Sat, 2 May 2020 01:11:31 +0100 Subject: [PATCH 03/41] Work in progress on prefs overhaul --- flatcamGUI/GUIElements.py | 55 ++++++ flatcamGUI/preferences/OptionUI.py | 161 ++++++++++++++++++ flatcamGUI/preferences/OptionsGroupUI.py | 64 ++++++- .../preferences/PreferencesSectionUI.py | 10 ++ .../preferences/PreferencesUIManager.py | 98 +++-------- .../general/GeneralAPPSetGroupUI.py | 4 +- .../general/GeneralAppPrefGroupUI.py | 4 +- .../general/GeneralGUIPrefGroupUI.py | 156 ++++++++++++++++- .../general/GeneralPreferencesUI.py | 2 +- .../geometry/GeometryAdvOptPrefGroupUI.py | 1 - 10 files changed, 463 insertions(+), 92 deletions(-) create mode 100644 flatcamGUI/preferences/OptionUI.py diff --git a/flatcamGUI/GUIElements.py b/flatcamGUI/GUIElements.py index 4771c5e6..360165b5 100644 --- a/flatcamGUI/GUIElements.py +++ b/flatcamGUI/GUIElements.py @@ -655,6 +655,61 @@ class EvalEntry2(QtWidgets.QLineEdit): return QtCore.QSize(EDIT_SIZE_HINT, default_hint_size.height()) +class FCColorEntry(QtWidgets.QWidget): + + def __init__(self, **kwargs): + super().__init__(**kwargs) + + self.entry = FCEntry() + + self.button = QtWidgets.QPushButton() + self.button.setFixedSize(15, 15) + self.button.setStyleSheet("border-color: dimgray;") + + self.layout = QtWidgets.QHBoxLayout() + self.layout.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter) + self.layout.addWidget(self.entry) + self.layout.addWidget(self.button) + self.setLayout(self.layout) + + self.entry.editingFinished.connect(self._sync_button_color) + self.button.clicked.connect(self._on_button_clicked) + + def get_value(self) -> str: + return self.entry.get_value() + + def set_value(self, value: str): + self.entry.set_value(value) + self._sync_button_color() + + def _sync_button_color(self): + value = self.get_value() + self.button.setStyleSheet("background-color:%s;" % self._extract_color(value)) + + def _on_button_clicked(self): + value = self.entry.get_value() + current_color = QtGui.QColor(self._extract_color(value)) + + color_dialog = QtWidgets.QColorDialog() + selected_color = color_dialog.getColor(initial=current_color, options=QtWidgets.QColorDialog.ShowAlphaChannel) + + if selected_color.isValid() is False: + return + + new_value = str(selected_color.name()) + self._extract_alpha(value) + self.set_value(new_value) + + def _extract_color(self, value: str) -> str: + return value[:7] + + def _extract_alpha(self, value: str) -> str: + return value[7:9] + + + + + + class FCSpinner(QtWidgets.QSpinBox): returnPressed = QtCore.pyqtSignal() diff --git a/flatcamGUI/preferences/OptionUI.py b/flatcamGUI/preferences/OptionUI.py new file mode 100644 index 00000000..90a72358 --- /dev/null +++ b/flatcamGUI/preferences/OptionUI.py @@ -0,0 +1,161 @@ +from PyQt5 import QtWidgets +from flatcamGUI.GUIElements import RadioSet, FCCheckBox, FCButton, FCComboBox, FCEntry, FCSpinner, FCColorEntry + +import gettext +import FlatCAMTranslation as fcTranslate +import builtins +fcTranslate.apply_language('strings') +if '_' not in builtins.__dict__: + _ = gettext.gettext + + +class OptionUI: + + def __init__(self, option: str): + self.option = option + + def add_to_grid(self, grid: QtWidgets.QGridLayout, row: int) -> int: + """ + Adds the necessary widget to the grid, starting at the supplied row. + Returns the number of rows used (normally 1) + """ + raise NotImplementedError() + + def get_field(self): + raise NotImplementedError() + + +class BasicOptionUI(OptionUI): + """Abstract OptionUI that has a label on the left then some other widget on the right""" + def __init__(self, option: str, label_text: str, label_tooltip: str): + super().__init__(option=option) + self.label_text = label_text + self.label_tooltip = label_tooltip + self.label_widget = self.build_label_widget() + self.entry_widget = self.build_entry_widget() + + def build_label_widget(self) -> QtWidgets.QLabel: + label_widget = QtWidgets.QLabel('%s:' % _(self.label_text)) + if self.label_tooltip is not None: + label_widget.setToolTip(_(self.label_tooltip)) + return label_widget + + def build_entry_widget(self) -> QtWidgets.QWidget: + raise NotImplementedError() + + def add_to_grid(self, grid: QtWidgets.QGridLayout, row: int) -> int: + grid.addWidget(self.label_widget, row, 0) + grid.addWidget(self.entry_widget, row, 1) + return 1 + + def get_field(self): + return self.entry_widget + + +class RadioSetOptionUI(BasicOptionUI): + + def __init__(self, option: str, label_text: str, label_tooltip: str, choices: list, orientation='horizontal'): + self.choices = choices + self.orientation = orientation + super().__init__(option=option, label_text=label_text, label_tooltip=label_tooltip) + + def build_entry_widget(self) -> QtWidgets.QWidget: + return RadioSet(choices=self.choices, orientation=self.orientation) + + +class CheckboxOptionUI(OptionUI): + + def __init__(self, option: str, label_text: str, label_tooltip: str): + super().__init__(option=option) + self.label_text = label_text + self.label_tooltip = label_tooltip + self.checkbox_widget = self.build_checkbox_widget() + + def build_checkbox_widget(self): + checkbox = FCCheckBox('%s' % _(self.label_text)) + checkbox.setToolTip(_(self.label_tooltip)) + return checkbox + + def add_to_grid(self, grid: QtWidgets.QGridLayout, row: int) -> int: + grid.addWidget(self.checkbox_widget, row, 0, 1, 3) + return 1 + + def get_field(self): + return self.checkbox_widget + + +class ComboboxOptionUI(BasicOptionUI): + + def __init__(self, option: str, label_text: str, label_tooltip: str, choices: list): + self.choices = choices + super().__init__(option=option, label_text=label_text, label_tooltip=label_tooltip) + + def build_entry_widget(self): + combo = FCComboBox() + for choice in self.choices: + # don't translate the QCombo items as they are used in QSettings and identified by name + combo.addItem(choice) + return combo + + +class ColorOptionUI(BasicOptionUI): + def build_entry_widget(self) -> QtWidgets.QWidget: + return FCColorEntry() + + +class HeadingOptionUI(OptionUI): + def __init__(self, label_text: str, label_tooltip: str): + super().__init__(option="__heading") + self.label_text = label_text + self.label_tooltip = label_tooltip + + def build_heading_widget(self): + heading = QtWidgets.QLabel('%s' % _(self.label_text)) + heading.setToolTip(_(self.label_tooltip)) + return heading + + def add_to_grid(self, grid: QtWidgets.QGridLayout, row: int) -> int: + grid.addWidget(self.build_heading_widget(), row, 0, 1, 2) + return 1 + + def get_field(self): + return None + + +class SeparatorOptionUI(OptionUI): + + def __init__(self): + super().__init__(option="__separator") + + def build_separator_widget(self): + separator = QtWidgets.QFrame() + separator.setFrameShape(QtWidgets.QFrame.HLine) + separator.setFrameShadow(QtWidgets.QFrame.Sunken) + return separator + + def add_to_grid(self, grid: QtWidgets.QGridLayout, row: int) -> int: + grid.addWidget(self.build_separator_widget(), row, 0, 1, 2) + return 1 + + def get_field(self): + return None + + +class FullWidthButtonOptionUI(OptionUI): + def __init__(self, option: str, label_text: str, label_tooltip: str): + super().__init__(option=option) + self.label_text = label_text + self.label_tooltip = label_tooltip + self.button_widget = self.build_button_widget() + + def build_button_widget(self): + button = FCButton(_(self.label_text)) + button.setToolTip(_(self.label_tooltip)) + return button + + def add_to_grid(self, grid: QtWidgets.QGridLayout, row: int) -> int: + grid.addWidget(self.button_widget, row, 0, 1, 3) + return 1 + + def get_field(self): + return self.button_widget \ No newline at end of file diff --git a/flatcamGUI/preferences/OptionsGroupUI.py b/flatcamGUI/preferences/OptionsGroupUI.py index 98780004..1167a8d4 100644 --- a/flatcamGUI/preferences/OptionsGroupUI.py +++ b/flatcamGUI/preferences/OptionsGroupUI.py @@ -1,12 +1,34 @@ +from typing import Dict + from PyQt5 import QtWidgets + +from PyQt5.QtCore import QSettings + +import gettext +import FlatCAMTranslation as fcTranslate +import builtins + +from flatcamGUI.preferences.OptionUI import OptionUI + +fcTranslate.apply_language('strings') +if '_' not in builtins.__dict__: + _ = gettext.gettext + +settings = QSettings("Open Source", "FlatCAM") +if settings.contains("machinist"): + machinist_setting = settings.value('machinist', type=int) +else: + machinist_setting = 0 + + class OptionsGroupUI(QtWidgets.QGroupBox): app = None - def __init__(self, title, parent=None): - # QtGui.QGroupBox.__init__(self, title, parent=parent) - super(OptionsGroupUI, self).__init__() + def __init__(self, fixme_get_rid_of_this=None, **kwargs): + super().__init__(**kwargs) + self.setStyleSheet(""" QGroupBox { @@ -16,4 +38,38 @@ class OptionsGroupUI(QtWidgets.QGroupBox): """) self.layout = QtWidgets.QVBoxLayout() - self.setLayout(self.layout) \ No newline at end of file + self.setLayout(self.layout) + + def option_dict(self) -> Dict[str, OptionUI]: + # FIXME! + return {} + + +class OptionsGroupUI2(OptionsGroupUI): + + def __init__(self, **kwargs): + super().__init__(**kwargs) + + self.grid = QtWidgets.QGridLayout() + self.layout.addLayout(self.grid) + self.grid.setColumnStretch(0, 0) + self.grid.setColumnStretch(1, 1) + + self.options = self.build_options() + + row = 0 + for option in self.options: + row += option.add_to_grid(grid=self.grid, row=row) + + self.layout.addStretch() + + def build_options(self) -> [OptionUI]: + return [] + + def option_dict(self) -> Dict[str, OptionUI]: + result = {} + for optionui in self.options: + result[optionui.option] = optionui + return result + + diff --git a/flatcamGUI/preferences/PreferencesSectionUI.py b/flatcamGUI/preferences/PreferencesSectionUI.py index ad70a9ff..858bf3d8 100644 --- a/flatcamGUI/preferences/PreferencesSectionUI.py +++ b/flatcamGUI/preferences/PreferencesSectionUI.py @@ -1,5 +1,8 @@ +from typing import Dict + from PyQt5 import QtWidgets +from flatcamGUI.preferences.OptionUI import OptionUI from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI @@ -20,3 +23,10 @@ class PreferencesSectionUI(QtWidgets.QWidget): def build_groups(self) -> [OptionsGroupUI]: return [] + + def option_dict(self) -> Dict[str, OptionUI]: + result = {} + for group in self.groups: + groupoptions = group.option_dict() + result.update(groupoptions) + return result \ No newline at end of file diff --git a/flatcamGUI/preferences/PreferencesUIManager.py b/flatcamGUI/preferences/PreferencesUIManager.py index 35733b99..f7022613 100644 --- a/flatcamGUI/preferences/PreferencesUIManager.py +++ b/flatcamGUI/preferences/PreferencesUIManager.py @@ -10,6 +10,8 @@ import gettext import FlatCAMTranslation as fcTranslate import builtins +from flatcamGUI.preferences.OptionUI import OptionUI + fcTranslate.apply_language('strings') if '_' not in builtins.__dict__: _ = gettext.gettext @@ -74,24 +76,6 @@ class PreferencesUIManager: "global_tpdf_lmargin": self.ui.general_defaults_form.general_app_group.lmargin_entry, "global_tpdf_rmargin": self.ui.general_defaults_form.general_app_group.rmargin_entry, - # General GUI Preferences - "global_theme": self.ui.general_defaults_form.general_gui_group.theme_radio, - "global_gray_icons": self.ui.general_defaults_form.general_gui_group.gray_icons_cb, - "global_layout": self.ui.general_defaults_form.general_gui_group.layout_combo, - "global_hover": self.ui.general_defaults_form.general_gui_group.hover_cb, - "global_selection_shape": self.ui.general_defaults_form.general_gui_group.selection_cb, - - "global_sel_fill": self.ui.general_defaults_form.general_gui_group.sf_color_entry, - "global_sel_line": self.ui.general_defaults_form.general_gui_group.sl_color_entry, - "global_alt_sel_fill": self.ui.general_defaults_form.general_gui_group.alt_sf_color_entry, - "global_alt_sel_line": self.ui.general_defaults_form.general_gui_group.alt_sl_color_entry, - "global_draw_color": self.ui.general_defaults_form.general_gui_group.draw_color_entry, - "global_sel_draw_color": self.ui.general_defaults_form.general_gui_group.sel_draw_color_entry, - - "global_proj_item_color": self.ui.general_defaults_form.general_gui_group.proj_color_entry, - "global_proj_item_dis_color": self.ui.general_defaults_form.general_gui_group.proj_color_dis_entry, - "global_project_autohide": self.ui.general_defaults_form.general_gui_group.project_autohide_cb, - # General GUI Settings "global_gridx": self.ui.general_defaults_form.general_app_set_group.gridx_entry, "global_gridy": self.ui.general_defaults_form.general_app_set_group.gridy_entry, @@ -605,13 +589,30 @@ class PreferencesUIManager: "util": ui.fa_scroll_area } + self.sections = [ + # FIXME! + ui.general_defaults_form + ] + def get_form_fields(self) -> Dict[str, Any]: - return self.defaults_form_fields + result = {} + result.update(self.defaults_form_fields) + result.update(self._option_field_dict()) + return result def get_form_field(self, option: str) -> Any: return self.get_form_fields()[option] + def option_dict(self) -> Dict[str, OptionUI]: + result = {} + for section in self.sections: + sectionoptions = section.option_dict() + result.update(sectionoptions) + return result + def _option_field_dict(self): + result = {k: v.get_field() for k, v in self.option_dict().items()} + return result def defaults_read_form(self): """ @@ -772,65 +773,6 @@ class PreferencesUIManager: "background-color:%s;" "border-color: dimgray" % str(self.defaults['cncjob_plot_line'])[:7]) - # Init Left-Right Selection colors - self.ui.general_defaults_form.general_gui_group.sf_color_entry.set_value(self.defaults['global_sel_fill']) - self.ui.general_defaults_form.general_gui_group.sf_color_button.setStyleSheet( - "background-color:%s;" - "border-color: dimgray" % str(self.defaults['global_sel_fill'])[:7]) - self.ui.general_defaults_form.general_gui_group.sf_color_alpha_spinner.set_value( - int(self.defaults['global_sel_fill'][7:9], 16)) - self.ui.general_defaults_form.general_gui_group.sf_color_alpha_slider.setValue( - int(self.defaults['global_sel_fill'][7:9], 16)) - - self.ui.general_defaults_form.general_gui_group.sl_color_entry.set_value(self.defaults['global_sel_line']) - self.ui.general_defaults_form.general_gui_group.sl_color_button.setStyleSheet( - "background-color:%s;" - "border-color: dimgray" % str(self.defaults['global_sel_line'])[:7]) - - # Init Right-Left Selection colors - self.ui.general_defaults_form.general_gui_group.alt_sf_color_entry.set_value( - self.defaults['global_alt_sel_fill']) - self.ui.general_defaults_form.general_gui_group.alt_sf_color_button.setStyleSheet( - "background-color:%s;" - "border-color: dimgray" % str(self.defaults['global_alt_sel_fill'])[:7]) - self.ui.general_defaults_form.general_gui_group.alt_sf_color_alpha_spinner.set_value( - int(self.defaults['global_sel_fill'][7:9], 16)) - self.ui.general_defaults_form.general_gui_group.alt_sf_color_alpha_slider.setValue( - int(self.defaults['global_sel_fill'][7:9], 16)) - - self.ui.general_defaults_form.general_gui_group.alt_sl_color_entry.set_value( - self.defaults['global_alt_sel_line']) - self.ui.general_defaults_form.general_gui_group.alt_sl_color_button.setStyleSheet( - "background-color:%s;" - "border-color: dimgray" % str(self.defaults['global_alt_sel_line'])[:7]) - - # Init Draw color and Selection Draw Color - self.ui.general_defaults_form.general_gui_group.draw_color_entry.set_value( - self.defaults['global_draw_color']) - self.ui.general_defaults_form.general_gui_group.draw_color_button.setStyleSheet( - "background-color:%s;" - "border-color: dimgray" % str(self.defaults['global_draw_color'])[:7]) - - self.ui.general_defaults_form.general_gui_group.sel_draw_color_entry.set_value( - self.defaults['global_sel_draw_color']) - self.ui.general_defaults_form.general_gui_group.sel_draw_color_button.setStyleSheet( - "background-color:%s;" - "border-color: dimgray" % str(self.defaults['global_sel_draw_color'])[:7]) - - # Init Project Items color - self.ui.general_defaults_form.general_gui_group.proj_color_entry.set_value( - self.defaults['global_proj_item_color']) - self.ui.general_defaults_form.general_gui_group.proj_color_button.setStyleSheet( - "background-color:%s;" - "border-color: dimgray" % str(self.defaults['global_proj_item_color'])[:7]) - - # Init Project Disabled Items color - self.ui.general_defaults_form.general_gui_group.proj_color_dis_entry.set_value( - self.defaults['global_proj_item_dis_color']) - self.ui.general_defaults_form.general_gui_group.proj_color_dis_button.setStyleSheet( - "background-color:%s;" - "border-color: dimgray" % str(self.defaults['global_proj_item_dis_color'])[:7]) - # Init Project Disabled Items color self.ui.general_defaults_form.general_app_set_group.mouse_cursor_entry.set_value( self.defaults['global_cursor_color']) diff --git a/flatcamGUI/preferences/general/GeneralAPPSetGroupUI.py b/flatcamGUI/preferences/general/GeneralAPPSetGroupUI.py index 3daff809..11c7a784 100644 --- a/flatcamGUI/preferences/general/GeneralAPPSetGroupUI.py +++ b/flatcamGUI/preferences/general/GeneralAPPSetGroupUI.py @@ -22,8 +22,8 @@ else: class GeneralAPPSetGroupUI(OptionsGroupUI): - def __init__(self, decimals=4, parent=None): - super(GeneralAPPSetGroupUI, self).__init__(self, parent=parent) + def __init__(self, decimals=4, **kwargs): + super().__init__(**kwargs) self.setTitle(str(_("App Settings"))) self.decimals = decimals diff --git a/flatcamGUI/preferences/general/GeneralAppPrefGroupUI.py b/flatcamGUI/preferences/general/GeneralAppPrefGroupUI.py index ab563f67..15d96474 100644 --- a/flatcamGUI/preferences/general/GeneralAppPrefGroupUI.py +++ b/flatcamGUI/preferences/general/GeneralAppPrefGroupUI.py @@ -23,8 +23,8 @@ else: class GeneralAppPrefGroupUI(OptionsGroupUI): - def __init__(self, decimals=4, parent=None): - super(GeneralAppPrefGroupUI, self).__init__(self, parent=parent) + def __init__(self, decimals=4, **kwargs): + super().__init__(**kwargs) self.setTitle(_("App Preferences")) self.decimals = decimals diff --git a/flatcamGUI/preferences/general/GeneralGUIPrefGroupUI.py b/flatcamGUI/preferences/general/GeneralGUIPrefGroupUI.py index a074c75b..4b115a2f 100644 --- a/flatcamGUI/preferences/general/GeneralGUIPrefGroupUI.py +++ b/flatcamGUI/preferences/general/GeneralGUIPrefGroupUI.py @@ -2,12 +2,15 @@ from PyQt5 import QtWidgets, QtCore, QtGui from PyQt5.QtCore import QSettings, Qt from flatcamGUI.GUIElements import RadioSet, FCCheckBox, FCButton, FCComboBox, FCEntry, FCSpinner -from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI +from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI, OptionsGroupUI2 import gettext import FlatCAMTranslation as fcTranslate import builtins +from flatcamGUI.preferences.OptionUI import OptionUI, BasicOptionUI, CheckboxOptionUI, RadioSetOptionUI, \ + SeparatorOptionUI, HeadingOptionUI, ComboboxOptionUI, ColorOptionUI, FullWidthButtonOptionUI + fcTranslate.apply_language('strings') if '_' not in builtins.__dict__: _ = gettext.gettext @@ -19,9 +22,150 @@ else: machinist_setting = 0 +class GeneralGUIPrefGroupUI2(OptionsGroupUI2): + + def __init__(self, decimals=4, **kwargs): + super().__init__(**kwargs) + self.decimals = decimals + self.setTitle(str(_("GUI Preferences 2"))) + + def build_options(self) -> [OptionUI]: + return [ + RadioSetOptionUI( + option="global_theme", + label_text="Theme", + label_tooltip="Select a theme for FlatCAM.\nIt will theme the plot area.", + choices=[ + {"label": _("Light"), "value": "white"}, + {"label": _("Dark"), "value": "black"} + ], + orientation='vertical' + ), + CheckboxOptionUI( + option="global_gray_icons", + label_text="Use Gray Icons", + label_tooltip="Check this box to use a set of icons with\na lighter (gray) color. To be used when a\nfull dark theme is applied." + ), + FullWidthButtonOptionUI( + option="__button_apply_theme", + label_text="Apply Theme", + label_tooltip="Select a theme for FlatCAM.\n" + "It will theme the plot area.\n" + "The application will restart after change." + ), + SeparatorOptionUI(), + + + ComboboxOptionUI( + # FIXME! + option="layout", + label_text="Layout", + label_tooltip="Select an layout for FlatCAM.\nIt is applied immediately.", + choices=[ + "standard", + "compact", + "minimal" + ] + ), + ComboboxOptionUI( + #FIXME! + option="style", + label_text="Style", + label_tooltip="Select an style for FlatCAM.\nIt will be applied at the next app start.", + choices=QtWidgets.QStyleFactory.keys() + ), + CheckboxOptionUI( + # FIXME + option="hdpi", + label_text='Activate HDPI Support', + label_tooltip="Enable High DPI support for FlatCAM.\nIt will be applied at the next app start.", + ), + CheckboxOptionUI( + option="global_hover", + label_text='Display Hover Shape', + label_tooltip="Enable display of a hover shape for FlatCAM objects.\nIt is displayed whenever the mouse cursor is hovering\nover any kind of not-selected object.", + ), + CheckboxOptionUI( + option="global_selection_shape", + label_text='Display Selection Shape', + label_tooltip="Enable the display of a selection shape for FlatCAM objects.\n" + "It is displayed whenever the mouse selects an object\n" + "either by clicking or dragging mouse from left to right or\n" + "right to left." + ), + SeparatorOptionUI(), + + HeadingOptionUI(label_text="Left-Right Selection Color", label_tooltip=None), + ColorOptionUI( + option="global_sel_line", + label_text="Outline", + label_tooltip="Set the line color for the 'left to right' selection box." + ), + ColorOptionUI( + option="global_sel_fill", + label_text="Fill", + label_tooltip="Set the fill color for the selection box\n" + "in case that the selection is done from left to right.\n" + "First 6 digits are the color and the last 2\n" + "digits are for alpha (transparency) level." + ), + + HeadingOptionUI(label_text="Right-Left Selection Color", label_tooltip=None), + ColorOptionUI( + option="global_alt_sel_line", + label_text="Outline", + label_tooltip="Set the line color for the 'right to left' selection box." + ), + ColorOptionUI( + option="global_alt_sel_fill", + label_text="Fill", + label_tooltip="Set the fill color for the selection box\n" + "in case that the selection is done from right to left.\n" + "First 6 digits are the color and the last 2\n" + "digits are for alpha (transparency) level." + ), + # FIXME: opacity slider? + SeparatorOptionUI(), + + HeadingOptionUI(label_text='Editor Color', label_tooltip=None), + ColorOptionUI( + option="global_draw_color", + label_text="Drawing", + label_tooltip="Set the color for the shape." + ), + ColorOptionUI( + option="global_sel_draw_color", + label_text="Selection", + label_tooltip="Set the color of the shape when selected." + ), + SeparatorOptionUI(), + + HeadingOptionUI(label_text='Project Items Color', label_tooltip=None), + ColorOptionUI( + option="global_proj_item_color", + label_text="Enabled", + label_tooltip="Set the color of the items in Project Tab Tree." + ), + ColorOptionUI( + option="global_proj_item_dis_color", + label_text="Disabled", + label_tooltip="Set the color of the items in Project Tab Tree,\n" + "for the case when the items are disabled." + ), + CheckboxOptionUI( + option="global_project_autohide", + label_text="Project AutoHide", + label_tooltip="Check this box if you want the project/selected/tool tab area to\n" + "hide automatically when there are no objects loaded and\n" + "to show whenever a new object is created." + ), + ] + + class GeneralGUIPrefGroupUI(OptionsGroupUI): - def __init__(self, decimals=4, parent=None): - super(GeneralGUIPrefGroupUI, self).__init__(self, parent=parent) + def __init__(self, decimals=4, **kwargs): + # region Description + super().__init__(**kwargs) self.setTitle(str(_("GUI Preferences"))) self.decimals = decimals @@ -151,10 +295,12 @@ class GeneralGUIPrefGroupUI(OptionsGroupUI): self.sel_lr_label = QtWidgets.QLabel('%s' % _('Left-Right Selection Color')) grid0.addWidget(self.sel_lr_label, 15, 0, 1, 2) + self.sl_color_label = QtWidgets.QLabel('%s:' % _('Outline')) self.sl_color_label.setToolTip( _("Set the line color for the 'left to right' selection box.") ) + self.sl_color_entry = FCEntry() self.sl_color_button = QtWidgets.QPushButton() self.sl_color_button.setFixedSize(15, 15) @@ -212,6 +358,7 @@ class GeneralGUIPrefGroupUI(OptionsGroupUI): separator_line.setFrameShadow(QtWidgets.QFrame.Sunken) grid0.addWidget(separator_line, 19, 0, 1, 2) + # Plot Selection (left - right) Color self.sel_rl_label = QtWidgets.QLabel('%s' % _('Right-Left Selection Color')) grid0.addWidget(self.sel_rl_label, 20, 0, 1, 2) @@ -279,6 +426,7 @@ class GeneralGUIPrefGroupUI(OptionsGroupUI): separator_line.setFrameShadow(QtWidgets.QFrame.Sunken) grid0.addWidget(separator_line, 24, 0, 1, 2) + # ------------------------------------------------------------------ # ----------------------- Editor Color ----------------------------- # ------------------------------------------------------------------ @@ -324,7 +472,7 @@ class GeneralGUIPrefGroupUI(OptionsGroupUI): separator_line.setFrameShape(QtWidgets.QFrame.HLine) separator_line.setFrameShadow(QtWidgets.QFrame.Sunken) grid0.addWidget(separator_line, 28, 0, 1, 2) - + # endregion # ------------------------------------------------------------------ # ----------------------- Project Settings ----------------------------- # ------------------------------------------------------------------ diff --git a/flatcamGUI/preferences/general/GeneralPreferencesUI.py b/flatcamGUI/preferences/general/GeneralPreferencesUI.py index 59e99174..259eb1fc 100644 --- a/flatcamGUI/preferences/general/GeneralPreferencesUI.py +++ b/flatcamGUI/preferences/general/GeneralPreferencesUI.py @@ -26,7 +26,7 @@ class GeneralPreferencesUI(PreferencesSectionUI): def __init__(self, decimals, **kwargs): self.decimals = decimals self.general_gui_group = GeneralGUIPrefGroupUI(decimals=self.decimals) - #self.general_gui_group2 = GeneralGUIPrefGroupUI2(decimals=self.decimals) + self.general_gui_group2 = GeneralGUIPrefGroupUI2(decimals=self.decimals) self.general_app_group = GeneralAppPrefGroupUI(decimals=self.decimals) self.general_app_set_group = GeneralAPPSetGroupUI(decimals=self.decimals) super().__init__(**kwargs) diff --git a/flatcamGUI/preferences/geometry/GeometryAdvOptPrefGroupUI.py b/flatcamGUI/preferences/geometry/GeometryAdvOptPrefGroupUI.py index 53c344d3..66354015 100644 --- a/flatcamGUI/preferences/geometry/GeometryAdvOptPrefGroupUI.py +++ b/flatcamGUI/preferences/geometry/GeometryAdvOptPrefGroupUI.py @@ -21,7 +21,6 @@ else: class GeometryAdvOptPrefGroupUI(OptionsGroupUI): def __init__(self, decimals=4, parent=None): - # OptionsGroupUI.__init__(self, "Geometry Advanced Options Preferences", parent=parent) super(GeometryAdvOptPrefGroupUI, self).__init__(self, parent=parent) self.setTitle(str(_("Geometry Adv. Options"))) From b24474be65dfab4c5dc41585f29037376d5b5557 Mon Sep 17 00:00:00 2001 From: David Robertson Date: Sat, 2 May 2020 02:12:09 +0100 Subject: [PATCH 04/41] wip --- FlatCAMApp.py | 4 +- flatcamGUI/preferences/OptionUI.py | 4 +- .../preferences/PreferencesUIManager.py | 9 +- .../general/GeneralGUIPrefGroupUI.py | 682 ++---------------- .../general/GeneralPreferencesUI.py | 22 +- 5 files changed, 62 insertions(+), 659 deletions(-) diff --git a/FlatCAMApp.py b/FlatCAMApp.py index 898300ee..75cf400c 100644 --- a/FlatCAMApp.py +++ b/FlatCAMApp.py @@ -563,8 +563,8 @@ class App(QtCore.QObject): self.ui.general_defaults_form.general_gui_group.on_layout(lay=initial_lay) # Set the combobox in Preferences to the current layout - idx = self.ui.general_defaults_form.general_gui_group.layout_combo.findText(initial_lay) - self.ui.general_defaults_form.general_gui_group.layout_combo.setCurrentIndex(idx) + idx = self.ui.general_defaults_form.general_gui_group.layout_field.findText(initial_lay) + self.ui.general_defaults_form.general_gui_group.layout_field.setCurrentIndex(idx) # after the first run, this object should be False self.defaults["first_run"] = False diff --git a/flatcamGUI/preferences/OptionUI.py b/flatcamGUI/preferences/OptionUI.py index 90a72358..067e1aaf 100644 --- a/flatcamGUI/preferences/OptionUI.py +++ b/flatcamGUI/preferences/OptionUI.py @@ -1,3 +1,5 @@ +from typing import Union + from PyQt5 import QtWidgets from flatcamGUI.GUIElements import RadioSet, FCCheckBox, FCButton, FCComboBox, FCEntry, FCSpinner, FCColorEntry @@ -104,7 +106,7 @@ class ColorOptionUI(BasicOptionUI): class HeadingOptionUI(OptionUI): - def __init__(self, label_text: str, label_tooltip: str): + def __init__(self, label_text: str, label_tooltip: Union[str, None]): super().__init__(option="__heading") self.label_text = label_text self.label_tooltip = label_tooltip diff --git a/flatcamGUI/preferences/PreferencesUIManager.py b/flatcamGUI/preferences/PreferencesUIManager.py index f7022613..eaeb7922 100644 --- a/flatcamGUI/preferences/PreferencesUIManager.py +++ b/flatcamGUI/preferences/PreferencesUIManager.py @@ -621,10 +621,11 @@ class PreferencesUIManager: :return: None """ for option in self.get_form_fields(): - try: - self.defaults[option] = self.get_form_field(option=option).get_value() - except Exception as e: - log.debug("App.defaults_read_form() --> %s" % str(e)) + if option in self.defaults: + try: + self.defaults[option] = self.get_form_field(option=option).get_value() + except Exception as e: + log.debug("App.defaults_read_form() --> %s" % str(e)) def defaults_write_form(self, factor=None, fl_units=None, source_dict=None): """ diff --git a/flatcamGUI/preferences/general/GeneralGUIPrefGroupUI.py b/flatcamGUI/preferences/general/GeneralGUIPrefGroupUI.py index 4b115a2f..9914f087 100644 --- a/flatcamGUI/preferences/general/GeneralGUIPrefGroupUI.py +++ b/flatcamGUI/preferences/general/GeneralGUIPrefGroupUI.py @@ -1,25 +1,16 @@ -from PyQt5 import QtWidgets, QtCore, QtGui +from PyQt5 import QtWidgets, QtCore from PyQt5.QtCore import QSettings, Qt - -from flatcamGUI.GUIElements import RadioSet, FCCheckBox, FCButton, FCComboBox, FCEntry, FCSpinner -from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI, OptionsGroupUI2 +from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI2 import gettext import FlatCAMTranslation as fcTranslate import builtins - -from flatcamGUI.preferences.OptionUI import OptionUI, BasicOptionUI, CheckboxOptionUI, RadioSetOptionUI, \ - SeparatorOptionUI, HeadingOptionUI, ComboboxOptionUI, ColorOptionUI, FullWidthButtonOptionUI - fcTranslate.apply_language('strings') if '_' not in builtins.__dict__: _ = gettext.gettext -settings = QSettings("Open Source", "FlatCAM") -if settings.contains("machinist"): - machinist_setting = settings.value('machinist', type=int) -else: - machinist_setting = 0 +from flatcamGUI.preferences.OptionUI import OptionUI, CheckboxOptionUI, RadioSetOptionUI, \ + SeparatorOptionUI, HeadingOptionUI, ComboboxOptionUI, ColorOptionUI, FullWidthButtonOptionUI class GeneralGUIPrefGroupUI2(OptionsGroupUI2): @@ -29,6 +20,27 @@ class GeneralGUIPrefGroupUI2(OptionsGroupUI2): self.decimals = decimals self.setTitle(str(_("GUI Preferences 2"))) + self.layout_field = self.option_dict()["layout"].get_field() + self.layout_field.activated.connect(self.on_layout) + + self.theme_field = self.option_dict()["global_theme"].get_field() + self.theme_apply_button = self.option_dict()["__button_apply_theme"].get_field() + self.theme_apply_button.clicked.connect(self.on_theme_change) + + self.style_field = self.option_dict()["style"].get_field() + current_style_index = self.style_field.findText(QtWidgets.qApp.style().objectName(), QtCore.Qt.MatchFixedString) + self.style_field.setCurrentIndex(current_style_index) + self.style_field.activated[str].connect(self.handle_style) + + self.hdpi_field = self.option_dict()["hdpi"].get_field() + qsettings = QSettings("Open Source", "FlatCAM") + if qsettings.contains("hdpi"): + self.hdpi_field.set_value(qsettings.value('hdpi', type=int)) + else: + self.hdpi_field.set_value(False) + self.hdpi_field.stateChanged.connect(self.handle_hdpi) + + def build_options(self) -> [OptionUI]: return [ RadioSetOptionUI( @@ -55,9 +67,7 @@ class GeneralGUIPrefGroupUI2(OptionsGroupUI2): ), SeparatorOptionUI(), - ComboboxOptionUI( - # FIXME! option="layout", label_text="Layout", label_tooltip="Select an layout for FlatCAM.\nIt is applied immediately.", @@ -68,14 +78,12 @@ class GeneralGUIPrefGroupUI2(OptionsGroupUI2): ] ), ComboboxOptionUI( - #FIXME! option="style", label_text="Style", label_tooltip="Select an style for FlatCAM.\nIt will be applied at the next app start.", choices=QtWidgets.QStyleFactory.keys() ), CheckboxOptionUI( - # FIXME option="hdpi", label_text='Activate HDPI Support', label_tooltip="Enable High DPI support for FlatCAM.\nIt will be applied at the next app start.", @@ -161,629 +169,19 @@ class GeneralGUIPrefGroupUI2(OptionsGroupUI2): ), ] - -class GeneralGUIPrefGroupUI(OptionsGroupUI): - def __init__(self, decimals=4, **kwargs): - # region Description - super().__init__(**kwargs) - - self.setTitle(str(_("GUI Preferences"))) - self.decimals = decimals - - # Create a grid layout for the Application general settings - grid0 = QtWidgets.QGridLayout() - self.layout.addLayout(grid0) - grid0.setColumnStretch(0, 0) - grid0.setColumnStretch(1, 1) - - # Theme selection - self.theme_label = QtWidgets.QLabel('%s:' % _('Theme')) - self.theme_label.setToolTip( - _("Select a theme for FlatCAM.\n" - "It will theme the plot area.") - ) - - self.theme_radio = RadioSet([ - {"label": _("Light"), "value": "white"}, - {"label": _("Dark"), "value": "black"} - ], orientation='vertical') - - grid0.addWidget(self.theme_label, 0, 0) - grid0.addWidget(self.theme_radio, 0, 1) - - # Enable Gray Icons - self.gray_icons_cb = FCCheckBox('%s' % _('Use Gray Icons')) - self.gray_icons_cb.setToolTip( - _("Check this box to use a set of icons with\n" - "a lighter (gray) color. To be used when a\n" - "full dark theme is applied.") - ) - grid0.addWidget(self.gray_icons_cb, 1, 0, 1, 3) - - self.theme_button = FCButton(_("Apply Theme")) - self.theme_button.setToolTip( - _("Select a theme for FlatCAM.\n" - "It will theme the plot area.\n" - "The application will restart after change.") - ) - grid0.addWidget(self.theme_button, 2, 0, 1, 3) - - separator_line = QtWidgets.QFrame() - separator_line.setFrameShape(QtWidgets.QFrame.HLine) - separator_line.setFrameShadow(QtWidgets.QFrame.Sunken) - grid0.addWidget(separator_line, 3, 0, 1, 2) - - # Layout selection - self.layout_label = QtWidgets.QLabel('%s:' % _('Layout')) - self.layout_label.setToolTip( - _("Select an layout for FlatCAM.\n" - "It is applied immediately.") - ) - self.layout_combo = FCComboBox() - # don't translate the QCombo items as they are used in QSettings and identified by name - self.layout_combo.addItem("standard") - self.layout_combo.addItem("compact") - self.layout_combo.addItem("minimal") - - grid0.addWidget(self.layout_label, 4, 0) - grid0.addWidget(self.layout_combo, 4, 1) - - # Set the current index for layout_combo - qsettings = QSettings("Open Source", "FlatCAM") - if qsettings.contains("layout"): - layout = qsettings.value('layout', type=str) - idx = self.layout_combo.findText(layout.capitalize()) - self.layout_combo.setCurrentIndex(idx) - - # Style selection - self.style_label = QtWidgets.QLabel('%s:' % _('Style')) - self.style_label.setToolTip( - _("Select an style for FlatCAM.\n" - "It will be applied at the next app start.") - ) - self.style_combo = FCComboBox() - self.style_combo.addItems(QtWidgets.QStyleFactory.keys()) - # find current style - index = self.style_combo.findText(QtWidgets.qApp.style().objectName(), QtCore.Qt.MatchFixedString) - self.style_combo.setCurrentIndex(index) - self.style_combo.activated[str].connect(self.handle_style) - - grid0.addWidget(self.style_label, 5, 0) - grid0.addWidget(self.style_combo, 5, 1) - - # Enable High DPI Support - self.hdpi_cb = FCCheckBox('%s' % _('Activate HDPI Support')) - self.hdpi_cb.setToolTip( - _("Enable High DPI support for FlatCAM.\n" - "It will be applied at the next app start.") - ) - - qsettings = QSettings("Open Source", "FlatCAM") - if qsettings.contains("hdpi"): - self.hdpi_cb.set_value(qsettings.value('hdpi', type=int)) - else: - self.hdpi_cb.set_value(False) - self.hdpi_cb.stateChanged.connect(self.handle_hdpi) - - grid0.addWidget(self.hdpi_cb, 6, 0, 1, 3) - - # Enable Hover box - self.hover_cb = FCCheckBox('%s' % _('Display Hover Shape')) - self.hover_cb.setToolTip( - _("Enable display of a hover shape for FlatCAM objects.\n" - "It is displayed whenever the mouse cursor is hovering\n" - "over any kind of not-selected object.") - ) - grid0.addWidget(self.hover_cb, 8, 0, 1, 3) - - # Enable Selection box - self.selection_cb = FCCheckBox('%s' % _('Display Selection Shape')) - self.selection_cb.setToolTip( - _("Enable the display of a selection shape for FlatCAM objects.\n" - "It is displayed whenever the mouse selects an object\n" - "either by clicking or dragging mouse from left to right or\n" - "right to left.") - ) - grid0.addWidget(self.selection_cb, 9, 0, 1, 3) - - separator_line = QtWidgets.QFrame() - separator_line.setFrameShape(QtWidgets.QFrame.HLine) - separator_line.setFrameShadow(QtWidgets.QFrame.Sunken) - grid0.addWidget(separator_line, 14, 0, 1, 2) - - # Plot Selection (left - right) Color - self.sel_lr_label = QtWidgets.QLabel('%s' % _('Left-Right Selection Color')) - grid0.addWidget(self.sel_lr_label, 15, 0, 1, 2) - - - self.sl_color_label = QtWidgets.QLabel('%s:' % _('Outline')) - self.sl_color_label.setToolTip( - _("Set the line color for the 'left to right' selection box.") - ) - - self.sl_color_entry = FCEntry() - self.sl_color_button = QtWidgets.QPushButton() - self.sl_color_button.setFixedSize(15, 15) - - self.form_box_child_4 = QtWidgets.QHBoxLayout() - self.form_box_child_4.addWidget(self.sl_color_entry) - self.form_box_child_4.addWidget(self.sl_color_button) - self.form_box_child_4.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter) - - grid0.addWidget(self.sl_color_label, 16, 0) - grid0.addLayout(self.form_box_child_4, 16, 1) - - self.sf_color_label = QtWidgets.QLabel('%s:' % _('Fill')) - self.sf_color_label.setToolTip( - _("Set the fill color for the selection box\n" - "in case that the selection is done from left to right.\n" - "First 6 digits are the color and the last 2\n" - "digits are for alpha (transparency) level.") - ) - self.sf_color_entry = FCEntry() - self.sf_color_button = QtWidgets.QPushButton() - self.sf_color_button.setFixedSize(15, 15) - - self.form_box_child_5 = QtWidgets.QHBoxLayout() - self.form_box_child_5.addWidget(self.sf_color_entry) - self.form_box_child_5.addWidget(self.sf_color_button) - self.form_box_child_5.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter) - - grid0.addWidget(self.sf_color_label, 17, 0) - grid0.addLayout(self.form_box_child_5, 17, 1) - - # Plot Selection (left - right) Fill Transparency Level - self.sf_alpha_label = QtWidgets.QLabel('%s:' % _('Alpha')) - self.sf_alpha_label.setToolTip( - _("Set the fill transparency for the 'left to right' selection box.") - ) - self.sf_color_alpha_slider = QtWidgets.QSlider(QtCore.Qt.Horizontal) - self.sf_color_alpha_slider.setMinimum(0) - self.sf_color_alpha_slider.setMaximum(255) - self.sf_color_alpha_slider.setSingleStep(1) - - self.sf_color_alpha_spinner = FCSpinner() - self.sf_color_alpha_spinner.setMinimumWidth(70) - self.sf_color_alpha_spinner.set_range(0, 255) - - self.form_box_child_6 = QtWidgets.QHBoxLayout() - self.form_box_child_6.addWidget(self.sf_color_alpha_slider) - self.form_box_child_6.addWidget(self.sf_color_alpha_spinner) - - grid0.addWidget(self.sf_alpha_label, 18, 0) - grid0.addLayout(self.form_box_child_6, 18, 1) - - separator_line = QtWidgets.QFrame() - separator_line.setFrameShape(QtWidgets.QFrame.HLine) - separator_line.setFrameShadow(QtWidgets.QFrame.Sunken) - grid0.addWidget(separator_line, 19, 0, 1, 2) - - - # Plot Selection (left - right) Color - self.sel_rl_label = QtWidgets.QLabel('%s' % _('Right-Left Selection Color')) - grid0.addWidget(self.sel_rl_label, 20, 0, 1, 2) - - # Plot Selection (right - left) Line Color - self.alt_sl_color_label = QtWidgets.QLabel('%s:' % _('Outline')) - self.alt_sl_color_label.setToolTip( - _("Set the line color for the 'right to left' selection box.") - ) - self.alt_sl_color_entry = FCEntry() - self.alt_sl_color_button = QtWidgets.QPushButton() - self.alt_sl_color_button.setFixedSize(15, 15) - - self.form_box_child_7 = QtWidgets.QHBoxLayout() - self.form_box_child_7.addWidget(self.alt_sl_color_entry) - self.form_box_child_7.addWidget(self.alt_sl_color_button) - self.form_box_child_7.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter) - - grid0.addWidget(self.alt_sl_color_label, 21, 0) - grid0.addLayout(self.form_box_child_7, 21, 1) - - # Plot Selection (right - left) Fill Color - self.alt_sf_color_label = QtWidgets.QLabel('%s:' % _('Fill')) - self.alt_sf_color_label.setToolTip( - _("Set the fill color for the selection box\n" - "in case that the selection is done from right to left.\n" - "First 6 digits are the color and the last 2\n" - "digits are for alpha (transparency) level.") - ) - self.alt_sf_color_entry = FCEntry() - self.alt_sf_color_button = QtWidgets.QPushButton() - self.alt_sf_color_button.setFixedSize(15, 15) - - self.form_box_child_8 = QtWidgets.QHBoxLayout() - self.form_box_child_8.addWidget(self.alt_sf_color_entry) - self.form_box_child_8.addWidget(self.alt_sf_color_button) - self.form_box_child_8.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter) - - grid0.addWidget(self.alt_sf_color_label, 22, 0) - grid0.addLayout(self.form_box_child_8, 22, 1) - - # Plot Selection (right - left) Fill Transparency Level - self.alt_sf_alpha_label = QtWidgets.QLabel('%s:' % _('Alpha')) - self.alt_sf_alpha_label.setToolTip( - _("Set the fill transparency for selection 'right to left' box.") - ) - self.alt_sf_color_alpha_slider = QtWidgets.QSlider(QtCore.Qt.Horizontal) - self.alt_sf_color_alpha_slider.setMinimum(0) - self.alt_sf_color_alpha_slider.setMaximum(255) - self.alt_sf_color_alpha_slider.setSingleStep(1) - - self.alt_sf_color_alpha_spinner = FCSpinner() - self.alt_sf_color_alpha_spinner.setMinimumWidth(70) - self.alt_sf_color_alpha_spinner.set_range(0, 255) - - self.form_box_child_9 = QtWidgets.QHBoxLayout() - self.form_box_child_9.addWidget(self.alt_sf_color_alpha_slider) - self.form_box_child_9.addWidget(self.alt_sf_color_alpha_spinner) - - grid0.addWidget(self.alt_sf_alpha_label, 23, 0) - grid0.addLayout(self.form_box_child_9, 23, 1) - - separator_line = QtWidgets.QFrame() - separator_line.setFrameShape(QtWidgets.QFrame.HLine) - separator_line.setFrameShadow(QtWidgets.QFrame.Sunken) - grid0.addWidget(separator_line, 24, 0, 1, 2) - - - # ------------------------------------------------------------------ - # ----------------------- Editor Color ----------------------------- - # ------------------------------------------------------------------ - - self.editor_color_label = QtWidgets.QLabel('%s' % _('Editor Color')) - grid0.addWidget(self.editor_color_label, 25, 0, 1, 2) - - # Editor Draw Color - self.draw_color_label = QtWidgets.QLabel('%s:' % _('Drawing')) - self.alt_sf_color_label.setToolTip( - _("Set the color for the shape.") - ) - self.draw_color_entry = FCEntry() - self.draw_color_button = QtWidgets.QPushButton() - self.draw_color_button.setFixedSize(15, 15) - - self.form_box_child_10 = QtWidgets.QHBoxLayout() - self.form_box_child_10.addWidget(self.draw_color_entry) - self.form_box_child_10.addWidget(self.draw_color_button) - self.form_box_child_10.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter) - - grid0.addWidget(self.draw_color_label, 26, 0) - grid0.addLayout(self.form_box_child_10, 26, 1) - - # Editor Draw Selection Color - self.sel_draw_color_label = QtWidgets.QLabel('%s:' % _('Selection')) - self.sel_draw_color_label.setToolTip( - _("Set the color of the shape when selected.") - ) - self.sel_draw_color_entry = FCEntry() - self.sel_draw_color_button = QtWidgets.QPushButton() - self.sel_draw_color_button.setFixedSize(15, 15) - - self.form_box_child_11 = QtWidgets.QHBoxLayout() - self.form_box_child_11.addWidget(self.sel_draw_color_entry) - self.form_box_child_11.addWidget(self.sel_draw_color_button) - self.form_box_child_11.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter) - - grid0.addWidget(self.sel_draw_color_label, 27, 0) - grid0.addLayout(self.form_box_child_11, 27, 1) - - separator_line = QtWidgets.QFrame() - separator_line.setFrameShape(QtWidgets.QFrame.HLine) - separator_line.setFrameShadow(QtWidgets.QFrame.Sunken) - grid0.addWidget(separator_line, 28, 0, 1, 2) - # endregion - # ------------------------------------------------------------------ - # ----------------------- Project Settings ----------------------------- - # ------------------------------------------------------------------ - - self.proj_settings_label = QtWidgets.QLabel('%s' % _('Project Items Color')) - grid0.addWidget(self.proj_settings_label, 29, 0, 1, 2) - - # Project Tab items color - self.proj_color_label = QtWidgets.QLabel('%s:' % _('Enabled')) - self.proj_color_label.setToolTip( - _("Set the color of the items in Project Tab Tree.") - ) - self.proj_color_entry = FCEntry() - self.proj_color_button = QtWidgets.QPushButton() - self.proj_color_button.setFixedSize(15, 15) - - self.form_box_child_12 = QtWidgets.QHBoxLayout() - self.form_box_child_12.addWidget(self.proj_color_entry) - self.form_box_child_12.addWidget(self.proj_color_button) - self.form_box_child_12.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter) - - grid0.addWidget(self.proj_color_label, 30, 0) - grid0.addLayout(self.form_box_child_12, 30, 1) - - self.proj_color_dis_label = QtWidgets.QLabel('%s:' % _('Disabled')) - self.proj_color_dis_label.setToolTip( - _("Set the color of the items in Project Tab Tree,\n" - "for the case when the items are disabled.") - ) - self.proj_color_dis_entry = FCEntry() - self.proj_color_dis_button = QtWidgets.QPushButton() - self.proj_color_dis_button.setFixedSize(15, 15) - - self.form_box_child_13 = QtWidgets.QHBoxLayout() - self.form_box_child_13.addWidget(self.proj_color_dis_entry) - self.form_box_child_13.addWidget(self.proj_color_dis_button) - self.form_box_child_13.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter) - - grid0.addWidget(self.proj_color_dis_label, 31, 0) - grid0.addLayout(self.form_box_child_13, 31, 1) - - # Project autohide CB - self.project_autohide_cb = FCCheckBox(label=_('Project AutoHide')) - self.project_autohide_cb.setToolTip( - _("Check this box if you want the project/selected/tool tab area to\n" - "hide automatically when there are no objects loaded and\n" - "to show whenever a new object is created.") - ) - - grid0.addWidget(self.project_autohide_cb, 32, 0, 1, 2) - - # Just to add empty rows - grid0.addWidget(QtWidgets.QLabel(''), 33, 0, 1, 2) - - self.layout.addStretch() - - self.theme_button.clicked.connect(self.on_theme_change) - - # ############################################################################# - # ############################# GUI COLORS SIGNALS ############################ - # ############################################################################# - - # Setting selection (left - right) colors signals - self.sf_color_entry.editingFinished.connect(self.on_sf_color_entry) - self.sf_color_button.clicked.connect(self.on_sf_color_button) - self.sf_color_alpha_spinner.valueChanged.connect(self.on_sf_color_spinner) - self.sf_color_alpha_slider.valueChanged.connect(self.on_sf_color_slider) - self.sl_color_entry.editingFinished.connect(self.on_sl_color_entry) - self.sl_color_button.clicked.connect(self.on_sl_color_button) - - # Setting selection (right - left) colors signals - self.alt_sf_color_entry.editingFinished.connect(self.on_alt_sf_color_entry) - self.alt_sf_color_button.clicked.connect(self.on_alt_sf_color_button) - self.alt_sf_color_alpha_spinner.valueChanged.connect(self.on_alt_sf_color_spinner) - self.alt_sf_color_alpha_slider.valueChanged.connect(self.on_alt_sf_color_slider) - self.alt_sl_color_entry.editingFinished.connect(self.on_alt_sl_color_entry) - self.alt_sl_color_button.clicked.connect(self.on_alt_sl_color_button) - - # Setting Editor Draw colors signals - self.draw_color_entry.editingFinished.connect(self.on_draw_color_entry) - self.draw_color_button.clicked.connect(self.on_draw_color_button) - - self.sel_draw_color_entry.editingFinished.connect(self.on_sel_draw_color_entry) - self.sel_draw_color_button.clicked.connect(self.on_sel_draw_color_button) - - self.proj_color_entry.editingFinished.connect(self.on_proj_color_entry) - self.proj_color_button.clicked.connect(self.on_proj_color_button) - - self.proj_color_dis_entry.editingFinished.connect(self.on_proj_color_dis_entry) - self.proj_color_dis_button.clicked.connect(self.on_proj_color_dis_button) - - self.layout_combo.activated.connect(self.on_layout) - def on_theme_change(self): - val = self.theme_radio.get_value() + # FIXME: this should be moved out to a view model + val = self.theme_field.get_value() qsettings = QSettings("Open Source", "FlatCAM") - qsettings.setValue('theme', val) + qsettings.setValue("theme", val) # This will write the setting to the platform specific storage. del qsettings self.app.on_app_restart() - @staticmethod - def handle_style(style): - # set current style - qsettings = QSettings("Open Source", "FlatCAM") - qsettings.setValue('style', style) - - # This will write the setting to the platform specific storage. - del qsettings - - @staticmethod - def handle_hdpi(state): - # set current HDPI - qsettings = QSettings("Open Source", "FlatCAM") - qsettings.setValue('hdpi', state) - - # This will write the setting to the platform specific storage. - del qsettings - - # Setting selection colors (left - right) handlers - def on_sf_color_entry(self): - self.app.defaults['global_sel_fill'] = self.app.defaults['global_sel_fill'][7:9] - self.sf_color_button.setStyleSheet("background-color:%s" % str(self.app.defaults['global_sel_fill'])[:7]) - - def on_sf_color_button(self): - current_color = QtGui.QColor(self.app.defaults['global_sel_fill'][:7]) - - c_dialog = QtWidgets.QColorDialog() - plot_fill_color = c_dialog.getColor(initial=current_color) - - if plot_fill_color.isValid() is False: - return - - self.sf_color_button.setStyleSheet("background-color:%s" % str(plot_fill_color.name())) - - new_val = str(plot_fill_color.name()) + str(self.app.defaults['global_sel_fill'][7:9]) - self.sf_color_entry.set_value(new_val) - self.app.defaults['global_sel_fill'] = new_val - - def on_sf_color_spinner(self): - spinner_value = self.sf_color_alpha_spinner.value() - self.sf_color_alpha_slider.setValue(spinner_value) - self.app.defaults['global_sel_fill'] = self.app.defaults['global_sel_fill'][:7] + \ - (hex(spinner_value)[2:] if int(hex(spinner_value)[2:], 16) > 0 else '00') - self.app.defaults['global_sel_line'] = self.app.defaults['global_sel_line'][:7] + \ - (hex(spinner_value)[2:] if int(hex(spinner_value)[2:], 16) > 0 else '00') - - def on_sf_color_slider(self): - slider_value = self.sf_color_alpha_slider.value() - self.sf_color_alpha_spinner.setValue(slider_value) - - def on_sl_color_entry(self): - self.app.defaults['global_sel_line'] = self.sl_color_entry.get_value()[:7] + \ - self.app.defaults['global_sel_line'][7:9] - self.sl_color_button.setStyleSheet("background-color:%s" % str(self.app.defaults['global_sel_line'])[:7]) - - def on_sl_color_button(self): - current_color = QtGui.QColor(self.app.defaults['global_sel_line'][:7]) - - c_dialog = QtWidgets.QColorDialog() - plot_line_color = c_dialog.getColor(initial=current_color) - - if plot_line_color.isValid() is False: - return - - self.sl_color_button.setStyleSheet("background-color:%s" % str(plot_line_color.name())) - - new_val_line = str(plot_line_color.name()) + str(self.app.defaults['global_sel_line'][7:9]) - self.sl_color_entry.set_value(new_val_line) - self.app.defaults['global_sel_line'] = new_val_line - - # Setting selection colors (right - left) handlers - def on_alt_sf_color_entry(self): - self.app.defaults['global_alt_sel_fill'] = self.alt_sf_color_entry.get_value()[:7] + \ - self.app.defaults['global_alt_sel_fill'][7:9] - self.alt_sf_color_button.setStyleSheet( - "background-color:%s" % str(self.app.defaults['global_alt_sel_fill'])[:7] - ) - - def on_alt_sf_color_button(self): - current_color = QtGui.QColor(self.app.defaults['global_alt_sel_fill'][:7]) - - c_dialog = QtWidgets.QColorDialog() - plot_fill_color = c_dialog.getColor(initial=current_color) - - if plot_fill_color.isValid() is False: - return - - self.alt_sf_color_button.setStyleSheet("background-color:%s" % str(plot_fill_color.name())) - - new_val = str(plot_fill_color.name()) + str(self.app.defaults['global_alt_sel_fill'][7:9]) - self.alt_sf_color_entry.set_value(new_val) - self.app.defaults['global_alt_sel_fill'] = new_val - - def on_alt_sf_color_spinner(self): - spinner_value = self.alt_sf_color_alpha_spinner.value() - self.alt_sf_color_alpha_slider.setValue(spinner_value) - self.app.defaults['global_alt_sel_fill'] = self.app.defaults['global_alt_sel_fill'][:7] + \ - (hex(spinner_value)[2:] if int(hex(spinner_value)[2:], 16) > 0 else '00') - self.app.defaults['global_alt_sel_line'] = self.app.defaults['global_alt_sel_line'][:7] + \ - (hex(spinner_value)[2:] if int(hex(spinner_value)[2:], 16) > 0 else '00') - - def on_alt_sf_color_slider(self): - slider_value = self.alt_sf_color_alpha_slider.value() - self.alt_sf_color_alpha_spinner.setValue(slider_value) - - def on_alt_sl_color_entry(self): - self.app.defaults['global_alt_sel_line'] = self.alt_sl_color_entry.get_value()[:7] + \ - self.app.defaults['global_alt_sel_line'][7:9] - self.alt_sl_color_button.setStyleSheet( - "background-color:%s" % str(self.app.defaults['global_alt_sel_line'])[:7] - ) - - def on_alt_sl_color_button(self): - current_color = QtGui.QColor(self.app.defaults['global_alt_sel_line'][:7]) - - c_dialog = QtWidgets.QColorDialog() - plot_line_color = c_dialog.getColor(initial=current_color) - - if plot_line_color.isValid() is False: - return - - self.alt_sl_color_button.setStyleSheet("background-color:%s" % str(plot_line_color.name())) - - new_val_line = str(plot_line_color.name()) + str(self.app.defaults['global_alt_sel_line'][7:9]) - self.alt_sl_color_entry.set_value(new_val_line) - self.app.defaults['global_alt_sel_line'] = new_val_line - - # Setting Editor colors - def on_draw_color_entry(self): - self.app.defaults['global_draw_color'] = self.draw_color_entry.get_value() - self.draw_color_button.setStyleSheet("background-color:%s" % str(self.app.defaults['global_draw_color'])) - - def on_draw_color_button(self): - current_color = QtGui.QColor(self.app.defaults['global_draw_color']) - - c_dialog = QtWidgets.QColorDialog() - draw_color = c_dialog.getColor(initial=current_color) - - if draw_color.isValid() is False: - return - - self.draw_color_button.setStyleSheet("background-color:%s" % str(draw_color.name())) - - new_val = str(draw_color.name()) - self.draw_color_entry.set_value(new_val) - self.app.defaults['global_draw_color'] = new_val - - def on_sel_draw_color_entry(self): - self.app.defaults['global_sel_draw_color'] = self.sel_draw_color_entry.get_value() - self.sel_draw_color_button.setStyleSheet( - "background-color:%s" % str(self.app.defaults['global_sel_draw_color'])) - - def on_sel_draw_color_button(self): - current_color = QtGui.QColor(self.app.defaults['global_sel_draw_color']) - - c_dialog = QtWidgets.QColorDialog() - sel_draw_color = c_dialog.getColor(initial=current_color) - - if sel_draw_color.isValid() is False: - return - - self.sel_draw_color_button.setStyleSheet("background-color:%s" % str(sel_draw_color.name())) - - new_val_sel = str(sel_draw_color.name()) - self.sel_draw_color_entry.set_value(new_val_sel) - self.app.defaults['global_sel_draw_color'] = new_val_sel - - def on_proj_color_entry(self): - self.app.defaults['global_proj_item_color'] = self.proj_color_entry.get_value() - self.proj_color_button.setStyleSheet( - "background-color:%s" % str(self.app.defaults['global_proj_item_color'])) - - def on_proj_color_button(self): - current_color = QtGui.QColor(self.app.defaults['global_proj_item_color']) - - c_dialog = QtWidgets.QColorDialog() - proj_color = c_dialog.getColor(initial=current_color) - - if proj_color.isValid() is False: - return - - self.proj_color_button.setStyleSheet("background-color:%s" % str(proj_color.name())) - - new_val_sel = str(proj_color.name()) - self.proj_color_entry.set_value(new_val_sel) - self.app.defaults['global_proj_item_color'] = new_val_sel - - def on_proj_color_dis_entry(self): - self.app.defaults['global_proj_item_dis_color'] = self.proj_color_dis_entry.get_value() - self.proj_color_dis_button.setStyleSheet( - "background-color:%s" % str(self.app.defaults['global_proj_item_dis_color'])) - - def on_proj_color_dis_button(self): - current_color = QtGui.QColor(self.app.defaults['global_proj_item_dis_color']) - - c_dialog = QtWidgets.QColorDialog() - proj_color = c_dialog.getColor(initial=current_color) - - if proj_color.isValid() is False: - return - - self.proj_color_dis_button.setStyleSheet("background-color:%s" % str(proj_color.name())) - - new_val_sel = str(proj_color.name()) - self.proj_color_dis_entry.set_value(new_val_sel) - self.app.defaults['global_proj_item_dis_color'] = new_val_sel - def on_layout(self, index=None, lay=None): + # FIXME: this should be moved out somewhere else """ Set the toolbars layout (location) @@ -796,7 +194,7 @@ class GeneralGUIPrefGroupUI(OptionsGroupUI): if lay: current_layout = lay else: - current_layout = self.layout_combo.get_value() + current_layout = self.layout_field.get_value() lay_settings = QSettings("Open Source", "FlatCAM") lay_settings.setValue('layout', current_layout) @@ -933,3 +331,23 @@ class GeneralGUIPrefGroupUI(OptionsGroupUI): self.app.ui.grid_gap_y_entry.setText(str(self.app.defaults["global_gridy"])) self.app.ui.snap_max_dist_entry.setText(str(self.app.defaults["global_snap_max"])) self.app.ui.grid_gap_link_cb.setChecked(True) + + @staticmethod + def handle_style(style): + # FIXME: this should be moved out to a view model + # set current style + qsettings = QSettings("Open Source", "FlatCAM") + qsettings.setValue('style', style) + + # This will write the setting to the platform specific storage. + del qsettings + + @staticmethod + def handle_hdpi(state): + # FIXME: this should be moved out to a view model + # set current HDPI + qsettings = QSettings("Open Source", "FlatCAM") + qsettings.setValue('hdpi', state) + + # This will write the setting to the platform specific storage. + del qsettings \ No newline at end of file diff --git a/flatcamGUI/preferences/general/GeneralPreferencesUI.py b/flatcamGUI/preferences/general/GeneralPreferencesUI.py index 259eb1fc..744e01ec 100644 --- a/flatcamGUI/preferences/general/GeneralPreferencesUI.py +++ b/flatcamGUI/preferences/general/GeneralPreferencesUI.py @@ -1,32 +1,15 @@ -from PyQt5.QtCore import QSettings - from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI from flatcamGUI.preferences.PreferencesSectionUI import PreferencesSectionUI from flatcamGUI.preferences.general.GeneralAppPrefGroupUI import GeneralAppPrefGroupUI from flatcamGUI.preferences.general.GeneralAPPSetGroupUI import GeneralAPPSetGroupUI -from flatcamGUI.preferences.general.GeneralGUIPrefGroupUI import GeneralGUIPrefGroupUI, GeneralGUIPrefGroupUI2 - -import gettext -import FlatCAMTranslation as fcTranslate -import builtins - -fcTranslate.apply_language('strings') -if '_' not in builtins.__dict__: - _ = gettext.gettext - -settings = QSettings("Open Source", "FlatCAM") -if settings.contains("machinist"): - machinist_setting = settings.value('machinist', type=int) -else: - machinist_setting = 0 +from flatcamGUI.preferences.general.GeneralGUIPrefGroupUI import GeneralGUIPrefGroupUI2 class GeneralPreferencesUI(PreferencesSectionUI): def __init__(self, decimals, **kwargs): self.decimals = decimals - self.general_gui_group = GeneralGUIPrefGroupUI(decimals=self.decimals) - self.general_gui_group2 = GeneralGUIPrefGroupUI2(decimals=self.decimals) + self.general_gui_group = GeneralGUIPrefGroupUI2(decimals=self.decimals) self.general_app_group = GeneralAppPrefGroupUI(decimals=self.decimals) self.general_app_set_group = GeneralAPPSetGroupUI(decimals=self.decimals) super().__init__(**kwargs) @@ -35,7 +18,6 @@ class GeneralPreferencesUI(PreferencesSectionUI): return [ self.general_app_group, self.general_gui_group, - self.general_gui_group2, self.general_app_set_group ] From b6593b41e26c83005bc3f63cc37bb6f1c25a9a6b Mon Sep 17 00:00:00 2001 From: David Robertson Date: Sat, 2 May 2020 03:08:42 +0100 Subject: [PATCH 05/41] translated the gui prefs group --- flatcamGUI/GUIElements.py | 3 ++- flatcamGUI/preferences/OptionUI.py | 3 ++- flatcamGUI/preferences/general/GeneralGUIPrefGroupUI.py | 6 ++++-- flatcamGUI/preferences/general/GeneralPreferencesUI.py | 4 ++-- 4 files changed, 10 insertions(+), 6 deletions(-) diff --git a/flatcamGUI/GUIElements.py b/flatcamGUI/GUIElements.py index 360165b5..9a6229c1 100644 --- a/flatcamGUI/GUIElements.py +++ b/flatcamGUI/GUIElements.py @@ -655,7 +655,7 @@ class EvalEntry2(QtWidgets.QLineEdit): return QtCore.QSize(EDIT_SIZE_HINT, default_hint_size.height()) -class FCColorEntry(QtWidgets.QWidget): +class FCColorEntry(QtWidgets.QFrame): def __init__(self, **kwargs): super().__init__(**kwargs) @@ -668,6 +668,7 @@ class FCColorEntry(QtWidgets.QWidget): self.layout = QtWidgets.QHBoxLayout() self.layout.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter) + self.layout.setContentsMargins(0, 0, 0, 0) self.layout.addWidget(self.entry) self.layout.addWidget(self.button) self.setLayout(self.layout) diff --git a/flatcamGUI/preferences/OptionUI.py b/flatcamGUI/preferences/OptionUI.py index 067e1aaf..0d52037a 100644 --- a/flatcamGUI/preferences/OptionUI.py +++ b/flatcamGUI/preferences/OptionUI.py @@ -102,7 +102,8 @@ class ComboboxOptionUI(BasicOptionUI): class ColorOptionUI(BasicOptionUI): def build_entry_widget(self) -> QtWidgets.QWidget: - return FCColorEntry() + entry = FCColorEntry() + return entry class HeadingOptionUI(OptionUI): diff --git a/flatcamGUI/preferences/general/GeneralGUIPrefGroupUI.py b/flatcamGUI/preferences/general/GeneralGUIPrefGroupUI.py index 9914f087..49529713 100644 --- a/flatcamGUI/preferences/general/GeneralGUIPrefGroupUI.py +++ b/flatcamGUI/preferences/general/GeneralGUIPrefGroupUI.py @@ -13,12 +13,12 @@ from flatcamGUI.preferences.OptionUI import OptionUI, CheckboxOptionUI, RadioSet SeparatorOptionUI, HeadingOptionUI, ComboboxOptionUI, ColorOptionUI, FullWidthButtonOptionUI -class GeneralGUIPrefGroupUI2(OptionsGroupUI2): +class GeneralGUIPrefGroupUI(OptionsGroupUI2): def __init__(self, decimals=4, **kwargs): super().__init__(**kwargs) self.decimals = decimals - self.setTitle(str(_("GUI Preferences 2"))) + self.setTitle(str(_("GUI Preferences"))) self.layout_field = self.option_dict()["layout"].get_field() self.layout_field.activated.connect(self.on_layout) @@ -117,6 +117,8 @@ class GeneralGUIPrefGroupUI2(OptionsGroupUI2): "First 6 digits are the color and the last 2\n" "digits are for alpha (transparency) level." ), + # FIXME: opacity slider? + SeparatorOptionUI(), HeadingOptionUI(label_text="Right-Left Selection Color", label_tooltip=None), ColorOptionUI( diff --git a/flatcamGUI/preferences/general/GeneralPreferencesUI.py b/flatcamGUI/preferences/general/GeneralPreferencesUI.py index 744e01ec..4e44a473 100644 --- a/flatcamGUI/preferences/general/GeneralPreferencesUI.py +++ b/flatcamGUI/preferences/general/GeneralPreferencesUI.py @@ -2,14 +2,14 @@ from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI from flatcamGUI.preferences.PreferencesSectionUI import PreferencesSectionUI from flatcamGUI.preferences.general.GeneralAppPrefGroupUI import GeneralAppPrefGroupUI from flatcamGUI.preferences.general.GeneralAPPSetGroupUI import GeneralAPPSetGroupUI -from flatcamGUI.preferences.general.GeneralGUIPrefGroupUI import GeneralGUIPrefGroupUI2 +from flatcamGUI.preferences.general.GeneralGUIPrefGroupUI import GeneralGUIPrefGroupUI class GeneralPreferencesUI(PreferencesSectionUI): def __init__(self, decimals, **kwargs): self.decimals = decimals - self.general_gui_group = GeneralGUIPrefGroupUI2(decimals=self.decimals) + self.general_gui_group = GeneralGUIPrefGroupUI(decimals=self.decimals) self.general_app_group = GeneralAppPrefGroupUI(decimals=self.decimals) self.general_app_set_group = GeneralAPPSetGroupUI(decimals=self.decimals) super().__init__(**kwargs) From 84566301ce04ab42f0cb6e24c6a74b650aa0f706 Mon Sep 17 00:00:00 2001 From: David Robertson Date: Sat, 2 May 2020 04:09:07 +0100 Subject: [PATCH 06/41] reimplement alpha slider --- flatcamGUI/GUIElements.py | 39 +++++++++++++ flatcamGUI/preferences/OptionUI.py | 15 ++++- .../general/GeneralGUIPrefGroupUI.py | 56 ++++++++++++++++++- 3 files changed, 106 insertions(+), 4 deletions(-) diff --git a/flatcamGUI/GUIElements.py b/flatcamGUI/GUIElements.py index 9a6229c1..7319457a 100644 --- a/flatcamGUI/GUIElements.py +++ b/flatcamGUI/GUIElements.py @@ -707,6 +707,45 @@ class FCColorEntry(QtWidgets.QFrame): return value[7:9] +class FCSliderWithSpinner(QtWidgets.QFrame): + + def __init__(self, min=0, max=100, step=1, **kwargs): + super().__init__(**kwargs) + + self.slider = QtWidgets.QSlider(QtCore.Qt.Horizontal) + self.slider.setMinimum(min) + self.slider.setMaximum(max) + self.slider.setSingleStep(step) + + self.spinner = FCSpinner() + self.spinner.set_range(min, max) + self.spinner.set_step(step) + self.spinner.setMinimumWidth(70) + + self.layout = QtWidgets.QHBoxLayout() + self.layout.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter) + self.layout.setContentsMargins(0, 0, 0, 0) + self.layout.addWidget(self.slider) + self.layout.addWidget(self.spinner) + self.setLayout(self.layout) + + self.slider.valueChanged.connect(self._on_slider) + self.spinner.valueChanged.connect(self._on_spinner) + + def get_value(self) -> int: + return self.spinner.get_value() + + def set_value(self, value: int): + self.spinner.set_value(value) + + def _on_spinner(self): + spinner_value = self.spinner.value() + self.slider.setValue(spinner_value) + + def _on_slider(self): + slider_value = self.slider.value() + self.spinner.set_value(slider_value) + diff --git a/flatcamGUI/preferences/OptionUI.py b/flatcamGUI/preferences/OptionUI.py index 0d52037a..8915237f 100644 --- a/flatcamGUI/preferences/OptionUI.py +++ b/flatcamGUI/preferences/OptionUI.py @@ -1,7 +1,8 @@ from typing import Union from PyQt5 import QtWidgets -from flatcamGUI.GUIElements import RadioSet, FCCheckBox, FCButton, FCComboBox, FCEntry, FCSpinner, FCColorEntry +from flatcamGUI.GUIElements import RadioSet, FCCheckBox, FCButton, FCComboBox, FCEntry, FCSpinner, FCColorEntry, \ + FCSliderWithSpinner import gettext import FlatCAMTranslation as fcTranslate @@ -106,6 +107,18 @@ class ColorOptionUI(BasicOptionUI): return entry +class SliderWithSpinnerOptionUI(BasicOptionUI): + def __init__(self, option: str, label_text: str, label_tooltip: str, min=0, max=100, step=1): + self.min = min + self.max = max + self.step = step + super().__init__(option=option, label_text=label_text, label_tooltip=label_tooltip) + + def build_entry_widget(self) -> QtWidgets.QWidget: + entry = FCSliderWithSpinner(min=self.min, max=self.max, step=self.step) + return entry + + class HeadingOptionUI(OptionUI): def __init__(self, label_text: str, label_tooltip: Union[str, None]): super().__init__(option="__heading") diff --git a/flatcamGUI/preferences/general/GeneralGUIPrefGroupUI.py b/flatcamGUI/preferences/general/GeneralGUIPrefGroupUI.py index 49529713..ae56c3e6 100644 --- a/flatcamGUI/preferences/general/GeneralGUIPrefGroupUI.py +++ b/flatcamGUI/preferences/general/GeneralGUIPrefGroupUI.py @@ -10,7 +10,8 @@ if '_' not in builtins.__dict__: _ = gettext.gettext from flatcamGUI.preferences.OptionUI import OptionUI, CheckboxOptionUI, RadioSetOptionUI, \ - SeparatorOptionUI, HeadingOptionUI, ComboboxOptionUI, ColorOptionUI, FullWidthButtonOptionUI + SeparatorOptionUI, HeadingOptionUI, ComboboxOptionUI, ColorOptionUI, FullWidthButtonOptionUI, \ + SliderWithSpinnerOptionUI class GeneralGUIPrefGroupUI(OptionsGroupUI2): @@ -40,6 +41,16 @@ class GeneralGUIPrefGroupUI(OptionsGroupUI2): self.hdpi_field.set_value(False) self.hdpi_field.stateChanged.connect(self.handle_hdpi) + self.sel_line_field = self.option_dict()["global_sel_line"].get_field() + self.sel_fill_field = self.option_dict()["global_sel_fill"].get_field() + self.sel_alpha_field = self.option_dict()["_global_sel_alpha"].get_field() + self.sel_alpha_field.spinner.valueChanged.connect(self.on_sel_alpha_change) + + self.alt_sel_line_field = self.option_dict()["global_alt_sel_line"].get_field() + self.alt_sel_fill_field = self.option_dict()["global_alt_sel_fill"].get_field() + self.alt_sel_alpha_field = self.option_dict()["_global_alt_sel_alpha"].get_field() + self.alt_sel_alpha_field.spinner.valueChanged.connect(self.on_alt_sel_alpha_change) + def build_options(self) -> [OptionUI]: return [ @@ -117,7 +128,12 @@ class GeneralGUIPrefGroupUI(OptionsGroupUI2): "First 6 digits are the color and the last 2\n" "digits are for alpha (transparency) level." ), - # FIXME: opacity slider? + SliderWithSpinnerOptionUI( + option="_global_sel_alpha", + label_text="Alpha", + label_tooltip="Set the fill transparency for the 'left to right' selection box.", + min=0, max=255, step=1 + ), SeparatorOptionUI(), HeadingOptionUI(label_text="Right-Left Selection Color", label_tooltip=None), @@ -134,7 +150,12 @@ class GeneralGUIPrefGroupUI(OptionsGroupUI2): "First 6 digits are the color and the last 2\n" "digits are for alpha (transparency) level." ), - # FIXME: opacity slider? + SliderWithSpinnerOptionUI( + option="_global_alt_sel_alpha", + label_text="Alpha", + label_tooltip="Set the fill transparency for the 'right to left' selection box.", + min=0, max=255, step=1 + ), SeparatorOptionUI(), HeadingOptionUI(label_text='Editor Color', label_tooltip=None), @@ -171,6 +192,35 @@ class GeneralGUIPrefGroupUI(OptionsGroupUI2): ), ] + def on_sel_alpha_change(self): + alpha = self.sel_alpha_field.get_value() + fill = self._modify_color_alpha(color=self.sel_fill_field.get_value(), alpha=alpha) + self.sel_fill_field.set_value(fill) + line = self._modify_color_alpha(color=self.sel_line_field.get_value(), alpha=alpha) + self.sel_line_field.set_value(line) + + def on_alt_sel_alpha_change(self): + alpha = self.alt_sel_alpha_field.get_value() + fill = self._modify_color_alpha(color=self.alt_sel_fill_field.get_value(), alpha=alpha) + self.alt_sel_fill_field.set_value(fill) + line = self._modify_color_alpha(color=self.alt_sel_line_field.get_value(), alpha=alpha) + self.alt_sel_line_field.set_value(line) + + + + def _modify_color_alpha(self, color: str, alpha: int): + color_without_alpha = color[:7] + if alpha > 255: + return color_without_alpha + "FF" + elif alpha < 0: + return color_without_alpha + "00" + else: + hexalpha = hex(alpha)[2:] + if len(hexalpha) == 1: + hexalpha = "0" + hexalpha + return color_without_alpha + hexalpha + + def on_theme_change(self): # FIXME: this should be moved out to a view model val = self.theme_field.get_value() From f3bdaf802338fd860a3b8f3eb43191328850c0fc Mon Sep 17 00:00:00 2001 From: David Robertson Date: Sun, 3 May 2020 02:27:17 +0100 Subject: [PATCH 07/41] Added DoubleSpinnerOptionUI --- flatcamGUI/preferences/OptionUI.py | 33 +++++++++++++++++++++++++----- 1 file changed, 28 insertions(+), 5 deletions(-) diff --git a/flatcamGUI/preferences/OptionUI.py b/flatcamGUI/preferences/OptionUI.py index 8915237f..c7e829b2 100644 --- a/flatcamGUI/preferences/OptionUI.py +++ b/flatcamGUI/preferences/OptionUI.py @@ -2,7 +2,7 @@ from typing import Union from PyQt5 import QtWidgets from flatcamGUI.GUIElements import RadioSet, FCCheckBox, FCButton, FCComboBox, FCEntry, FCSpinner, FCColorEntry, \ - FCSliderWithSpinner + FCSliderWithSpinner, FCDoubleSpinner import gettext import FlatCAMTranslation as fcTranslate @@ -108,14 +108,37 @@ class ColorOptionUI(BasicOptionUI): class SliderWithSpinnerOptionUI(BasicOptionUI): - def __init__(self, option: str, label_text: str, label_tooltip: str, min=0, max=100, step=1): - self.min = min - self.max = max + def __init__(self, option: str, label_text: str, label_tooltip: str, min_value=0, max_value=100, step=1): + self.min_value = min_value + self.max_value = max_value self.step = step super().__init__(option=option, label_text=label_text, label_tooltip=label_tooltip) def build_entry_widget(self) -> QtWidgets.QWidget: - entry = FCSliderWithSpinner(min=self.min, max=self.max, step=self.step) + entry = FCSliderWithSpinner(min=self.min_value, max=self.max_value, step=self.step) + return entry + + +class DoubleSpinnerOptionUI(BasicOptionUI): + def __init__(self, option: str, label_text: str, label_tooltip: str, step: float, decimals: int, min_value=None, max_value=None): + self.min_value = min_value + self.max_value = max_value + self.step = step + self.decimals = decimals + super().__init__(option=option, label_text=label_text, label_tooltip=label_tooltip) + + def build_entry_widget(self) -> QtWidgets.QWidget: + entry = FCDoubleSpinner() + entry.set_precision(self.decimals) + entry.setSingleStep(self.step) + if self.min_value is None: + self.min_value = entry.minimum() + else: + entry.setMinimum(self.min_value) + if self.max_value is None: + self.max_value = entry.maximum() + else: + entry.setMaximum(self.max_value) return entry From 7062afc1afa7f42fb9ac840e6268ad3989ea645e Mon Sep 17 00:00:00 2001 From: David Robertson Date: Sun, 3 May 2020 04:18:10 +0100 Subject: [PATCH 08/41] Rework app settings group --- FlatCAMApp.py | 37 +- flatcamGUI/preferences/OptionUI.py | 19 +- .../preferences/PreferencesUIManager.py | 38 +- .../general/GeneralAPPSetGroupUI.py | 483 ------------------ .../general/GeneralAppSettingsGroupUI.py | 301 +++++++++++ .../general/GeneralGUIPrefGroupUI.py | 5 +- .../general/GeneralPreferencesUI.py | 6 +- 7 files changed, 348 insertions(+), 541 deletions(-) delete mode 100644 flatcamGUI/preferences/general/GeneralAPPSetGroupUI.py create mode 100644 flatcamGUI/preferences/general/GeneralAppSettingsGroupUI.py diff --git a/FlatCAMApp.py b/FlatCAMApp.py index eeac19f7..f960f2e7 100644 --- a/FlatCAMApp.py +++ b/FlatCAMApp.py @@ -963,19 +963,22 @@ class App(QtCore.QObject): lambda: self.on_toggle_units(no_pref=False)) # ##################################### Workspace Setting Signals ########################################### - self.ui.general_defaults_form.general_app_set_group.wk_cb.currentIndexChanged.connect( + + + self.preferencesUiManager.option_dict()["global_workspaceT"].get_field().currentIndexChanged.connect( self.on_workspace_modified) - self.ui.general_defaults_form.general_app_set_group.wk_orientation_radio.activated_custom.connect( + self.preferencesUiManager.option_dict()["global_workspace_orientation"].get_field().activated_custom.connect( self.on_workspace_modified ) + self.preferencesUiManager.option_dict()["global_workspace"].get_field().stateChanged.connect(self.on_workspace) - self.ui.general_defaults_form.general_app_set_group.workspace_cb.stateChanged.connect(self.on_workspace) # ########################################################################################################### # ######################################## GUI SETTINGS SIGNALS ############################################# # ########################################################################################################### self.ui.general_defaults_form.general_app_group.ge_radio.activated_custom.connect(self.on_app_restart) - self.ui.general_defaults_form.general_app_set_group.cursor_radio.activated_custom.connect(self.on_cursor_type) + + self.preferencesUiManager.get_form_field("global_cursor_type").activated_custom.connect(self.on_cursor_type) # ######################################## Tools related signals ############################################ # Film Tool @@ -3563,20 +3566,20 @@ class App(QtCore.QObject): ) stgs.setValue( 'notebook_font_size', - self.ui.general_defaults_form.general_app_set_group.notebook_font_size_spinner.get_value() + self.preferencesUiManager.get_form_field("notebook_font_size").get_value() ) stgs.setValue( 'axis_font_size', - self.ui.general_defaults_form.general_app_set_group.axis_font_size_spinner.get_value() + self.preferencesUiManager.get_form_field("axis_font_size").get_value() ) stgs.setValue( 'textbox_font_size', - self.ui.general_defaults_form.general_app_set_group.textbox_font_size_spinner.get_value() + self.preferencesUiManager.get_form_field("textbox_font_size").get_value() ) stgs.setValue('toolbar_lock', self.ui.lock_action.isChecked()) stgs.setValue( 'machinist', - 1 if self.ui.general_defaults_form.general_app_set_group.machinist_cb.get_value() else 0 + 1 if self.preferencesUiManager.get_form_field("global_machinist_setting").get_value() else 0 ) # This will write the setting to the platform specific storage. @@ -4951,7 +4954,7 @@ class App(QtCore.QObject): self.plotcanvas.draw_workspace(workspace_size=self.defaults['global_workspaceT']) def on_workspace(self): - if self.ui.general_defaults_form.general_app_set_group.workspace_cb.get_value(): + if self.preferencesUiManager.option_dict()["global_workspace"].get_field().get_value(): self.plotcanvas.draw_workspace(workspace_size=self.defaults['global_workspaceT']) else: self.plotcanvas.delete_workspace() @@ -4959,13 +4962,13 @@ class App(QtCore.QObject): # self.save_defaults(silent=True) def on_workspace_toggle(self): - state = False if self.ui.general_defaults_form.general_app_set_group.workspace_cb.get_value() else True + state = False if self.preferencesUiManager.option_dict()["global_workspace"].get_field().get_value() else True try: - self.ui.general_defaults_form.general_app_set_group.workspace_cb.stateChanged.disconnect(self.on_workspace) + self.preferencesUiManager.option_dict()["global_workspace"].get_field().stateChanged.disconnect(self.on_workspace) except TypeError: pass - self.ui.general_defaults_form.general_app_set_group.workspace_cb.set_value(state) - self.ui.general_defaults_form.general_app_set_group.workspace_cb.stateChanged.connect(self.on_workspace) + self.preferencesUiManager.option_dict()["global_workspace"].get_field().set_value(state) + self.preferencesUiManager.option_dict()["global_workspace"].get_field().stateChanged.connect(self.on_workspace) self.on_workspace() def on_cursor_type(self, val): @@ -4977,12 +4980,12 @@ class App(QtCore.QObject): self.app_cursor.enabled = False if val == 'small': - self.ui.general_defaults_form.general_app_set_group.cursor_size_entry.setDisabled(False) - self.ui.general_defaults_form.general_app_set_group.cursor_size_lbl.setDisabled(False) + self.preferencesUiManager.get_form_field("global_cursor_size").setDisabled(False) + #self.ui.general_defaults_form.general_app_set_group.cursor_size_lbl.setDisabled(False) self.app_cursor = self.plotcanvas.new_cursor() else: - self.ui.general_defaults_form.general_app_set_group.cursor_size_entry.setDisabled(True) - self.ui.general_defaults_form.general_app_set_group.cursor_size_lbl.setDisabled(True) + self.preferencesUiManager.get_form_field("global_cursor_size").setDisabled(False) + #self.ui.general_defaults_form.general_app_set_group.cursor_size_lbl.setDisabled(True) self.app_cursor = self.plotcanvas.new_cursor(big=True) if self.ui.grid_snap_btn.isChecked(): diff --git a/flatcamGUI/preferences/OptionUI.py b/flatcamGUI/preferences/OptionUI.py index c7e829b2..bec4247c 100644 --- a/flatcamGUI/preferences/OptionUI.py +++ b/flatcamGUI/preferences/OptionUI.py @@ -1,4 +1,4 @@ -from typing import Union +from typing import Union, Sequence from PyQt5 import QtWidgets from flatcamGUI.GUIElements import RadioSet, FCCheckBox, FCButton, FCComboBox, FCEntry, FCSpinner, FCColorEntry, \ @@ -89,7 +89,7 @@ class CheckboxOptionUI(OptionUI): class ComboboxOptionUI(BasicOptionUI): - def __init__(self, option: str, label_text: str, label_tooltip: str, choices: list): + def __init__(self, option: str, label_text: str, label_tooltip: str, choices: Sequence): self.choices = choices super().__init__(option=option, label_text=label_text, label_tooltip=label_tooltip) @@ -119,6 +119,21 @@ class SliderWithSpinnerOptionUI(BasicOptionUI): return entry +class SpinnerOptionUI(BasicOptionUI): + def __init__(self, option: str, label_text: str, label_tooltip: str, min_value: int, max_value: int, step: int = 1): + self.min_value = min_value + self.max_value = max_value + self.step = step + super().__init__(option=option, label_text=label_text, label_tooltip=label_tooltip) + + def build_entry_widget(self) -> QtWidgets.QWidget: + entry = FCSpinner() + entry.set_range(self.min_value, self.max_value) + entry.set_step(self.step) + entry.setWrapping(True) + return entry + + class DoubleSpinnerOptionUI(BasicOptionUI): def __init__(self, option: str, label_text: str, label_tooltip: str, step: float, decimals: int, min_value=None, max_value=None): self.min_value = min_value diff --git a/flatcamGUI/preferences/PreferencesUIManager.py b/flatcamGUI/preferences/PreferencesUIManager.py index 86fc57fb..3234e251 100644 --- a/flatcamGUI/preferences/PreferencesUIManager.py +++ b/flatcamGUI/preferences/PreferencesUIManager.py @@ -76,29 +76,6 @@ class PreferencesUIManager: "global_tpdf_lmargin": self.ui.general_defaults_form.general_app_group.lmargin_entry, "global_tpdf_rmargin": self.ui.general_defaults_form.general_app_group.rmargin_entry, - # General GUI Settings - "global_gridx": self.ui.general_defaults_form.general_app_set_group.gridx_entry, - "global_gridy": self.ui.general_defaults_form.general_app_set_group.gridy_entry, - "global_snap_max": self.ui.general_defaults_form.general_app_set_group.snap_max_dist_entry, - "global_workspace": self.ui.general_defaults_form.general_app_set_group.workspace_cb, - "global_workspaceT": self.ui.general_defaults_form.general_app_set_group.wk_cb, - "global_workspace_orientation": self.ui.general_defaults_form.general_app_set_group.wk_orientation_radio, - - "global_cursor_type": self.ui.general_defaults_form.general_app_set_group.cursor_radio, - "global_cursor_size": self.ui.general_defaults_form.general_app_set_group.cursor_size_entry, - "global_cursor_width": self.ui.general_defaults_form.general_app_set_group.cursor_width_entry, - "global_cursor_color_enabled": self.ui.general_defaults_form.general_app_set_group.mouse_cursor_color_cb, - "global_cursor_color": self.ui.general_defaults_form.general_app_set_group.mouse_cursor_entry, - "global_pan_button": self.ui.general_defaults_form.general_app_set_group.pan_button_radio, - "global_mselect_key": self.ui.general_defaults_form.general_app_set_group.mselect_radio, - "global_delete_confirmation": self.ui.general_defaults_form.general_app_set_group.delete_conf_cb, - "global_open_style": self.ui.general_defaults_form.general_app_set_group.open_style_cb, - "global_toggle_tooltips": self.ui.general_defaults_form.general_app_set_group.toggle_tooltips_cb, - "global_machinist_setting": self.ui.general_defaults_form.general_app_set_group.machinist_cb, - - "global_bookmarks_limit": self.ui.general_defaults_form.general_app_set_group.bm_limit_spinner, - "global_activity_icon": self.ui.general_defaults_form.general_app_set_group.activity_combo, - # Gerber General "gerber_plot": self.ui.gerber_defaults_form.gerber_gen_group.plot_cb, "gerber_solid": self.ui.gerber_defaults_form.gerber_gen_group.solid_cb, @@ -774,12 +751,7 @@ class PreferencesUIManager: "background-color:%s;" "border-color: dimgray" % str(self.defaults['cncjob_plot_line'])[:7]) - # Init Project Disabled Items color - self.ui.general_defaults_form.general_app_set_group.mouse_cursor_entry.set_value( - self.defaults['global_cursor_color']) - self.ui.general_defaults_form.general_app_set_group.mouse_cursor_button.setStyleSheet( - "background-color:%s;" - "border-color: dimgray" % str(self.defaults['global_cursor_color'])[:7]) + # Init the Annotation CNC Job color self.ui.cncjob_defaults_form.cncjob_adv_opt_group.annotation_fontcolor_entry.set_value( @@ -839,20 +811,20 @@ class PreferencesUIManager: settgs = QSettings("Open Source", "FlatCAM") # save the notebook font size - fsize = self.ui.general_defaults_form.general_app_set_group.notebook_font_size_spinner.get_value() + fsize = self.get_form_field("notebook_font_size").get_value() settgs.setValue('notebook_font_size', fsize) # save the axis font size - g_fsize = self.ui.general_defaults_form.general_app_set_group.axis_font_size_spinner.get_value() + g_fsize = self.get_form_field("axis_font_size").get_value() settgs.setValue('axis_font_size', g_fsize) # save the textbox font size - tb_fsize = self.ui.general_defaults_form.general_app_set_group.textbox_font_size_spinner.get_value() + tb_fsize = self.get_form_field("textbox_font_size").get_value() settgs.setValue('textbox_font_size', tb_fsize) settgs.setValue( 'machinist', - 1 if self.ui.general_defaults_form.general_app_set_group.machinist_cb.get_value() else 0 + 1 if self.get_form_field("global_machinist_setting").get_value() else 0 ) # This will write the setting to the platform specific storage. diff --git a/flatcamGUI/preferences/general/GeneralAPPSetGroupUI.py b/flatcamGUI/preferences/general/GeneralAPPSetGroupUI.py deleted file mode 100644 index 11c7a784..00000000 --- a/flatcamGUI/preferences/general/GeneralAPPSetGroupUI.py +++ /dev/null @@ -1,483 +0,0 @@ -from PyQt5 import QtCore, QtWidgets, QtGui -from PyQt5.QtCore import QSettings - -from flatcamGUI.GUIElements import FCDoubleSpinner, FCCheckBox, FCComboBox, RadioSet, OptionalInputSection, FCSpinner, \ - FCEntry -from flatcamGUI.preferences import settings -from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI - -import gettext -import FlatCAMTranslation as fcTranslate -import builtins - -fcTranslate.apply_language('strings') -if '_' not in builtins.__dict__: - _ = gettext.gettext - -settings = QSettings("Open Source", "FlatCAM") -if settings.contains("machinist"): - machinist_setting = settings.value('machinist', type=int) -else: - machinist_setting = 0 - - -class GeneralAPPSetGroupUI(OptionsGroupUI): - def __init__(self, decimals=4, **kwargs): - super().__init__(**kwargs) - - self.setTitle(str(_("App Settings"))) - self.decimals = decimals - - theme_settings = QtCore.QSettings("Open Source", "FlatCAM") - if theme_settings.contains("theme"): - theme = theme_settings.value('theme', type=str) - else: - theme = 'white' - - if theme == 'white': - self.resource_loc = 'assets/resources' - else: - self.resource_loc = 'assets/resources' - - # Create a grid layout for the Application general settings - grid0 = QtWidgets.QGridLayout() - self.layout.addLayout(grid0) - grid0.setColumnStretch(0, 0) - grid0.setColumnStretch(1, 1) - - # GRID Settings - self.grid_label = QtWidgets.QLabel('%s' % _('Grid Settings')) - grid0.addWidget(self.grid_label, 0, 0, 1, 2) - - # Grid X Entry - self.gridx_label = QtWidgets.QLabel('%s:' % _('X value')) - self.gridx_label.setToolTip( - _("This is the Grid snap value on X axis.") - ) - self.gridx_entry = FCDoubleSpinner() - self.gridx_entry.set_precision(self.decimals) - self.gridx_entry.setSingleStep(0.1) - - grid0.addWidget(self.gridx_label, 1, 0) - grid0.addWidget(self.gridx_entry, 1, 1) - - # Grid Y Entry - self.gridy_label = QtWidgets.QLabel('%s:' % _('Y value')) - self.gridy_label.setToolTip( - _("This is the Grid snap value on Y axis.") - ) - self.gridy_entry = FCDoubleSpinner() - self.gridy_entry.set_precision(self.decimals) - self.gridy_entry.setSingleStep(0.1) - - grid0.addWidget(self.gridy_label, 2, 0) - grid0.addWidget(self.gridy_entry, 2, 1) - - # Snap Max Entry - self.snap_max_label = QtWidgets.QLabel('%s:' % _('Snap Max')) - self.snap_max_label.setToolTip(_("Max. magnet distance")) - self.snap_max_dist_entry = FCDoubleSpinner() - self.snap_max_dist_entry.set_precision(self.decimals) - self.snap_max_dist_entry.setSingleStep(0.1) - - grid0.addWidget(self.snap_max_label, 3, 0) - grid0.addWidget(self.snap_max_dist_entry, 3, 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) - - # Workspace - self.workspace_label = QtWidgets.QLabel('%s' % _('Workspace Settings')) - grid0.addWidget(self.workspace_label, 5, 0, 1, 2) - - self.workspace_cb = FCCheckBox('%s' % _('Active')) - self.workspace_cb.setToolTip( - _("Draw a delimiting rectangle on canvas.\n" - "The purpose is to illustrate the limits for our work.") - ) - - grid0.addWidget(self.workspace_cb, 6, 0, 1, 2) - - self.workspace_type_lbl = QtWidgets.QLabel('%s:' % _('Size')) - self.workspace_type_lbl.setToolTip( - _("Select the type of rectangle to be used on canvas,\n" - "as valid workspace.") - ) - self.wk_cb = FCComboBox() - - grid0.addWidget(self.workspace_type_lbl, 7, 0) - grid0.addWidget(self.wk_cb, 7, 1) - - self.pagesize = {} - self.pagesize.update( - { - 'A0': (841, 1189), - 'A1': (594, 841), - 'A2': (420, 594), - 'A3': (297, 420), - 'A4': (210, 297), - 'A5': (148, 210), - 'A6': (105, 148), - 'A7': (74, 105), - 'A8': (52, 74), - 'A9': (37, 52), - 'A10': (26, 37), - - 'B0': (1000, 1414), - 'B1': (707, 1000), - 'B2': (500, 707), - 'B3': (353, 500), - 'B4': (250, 353), - 'B5': (176, 250), - 'B6': (125, 176), - 'B7': (88, 125), - 'B8': (62, 88), - 'B9': (44, 62), - 'B10': (31, 44), - - 'C0': (917, 1297), - 'C1': (648, 917), - 'C2': (458, 648), - 'C3': (324, 458), - 'C4': (229, 324), - 'C5': (162, 229), - 'C6': (114, 162), - 'C7': (81, 114), - 'C8': (57, 81), - 'C9': (40, 57), - 'C10': (28, 40), - - # American paper sizes - 'LETTER': (8.5, 11), - 'LEGAL': (8.5, 14), - 'ELEVENSEVENTEEN': (11, 17), - - # From https://en.wikipedia.org/wiki/Paper_size - 'JUNIOR_LEGAL': (5, 8), - 'HALF_LETTER': (5.5, 8), - 'GOV_LETTER': (8, 10.5), - 'GOV_LEGAL': (8.5, 13), - 'LEDGER': (17, 11), - } - ) - - page_size_list = list(self.pagesize.keys()) - - self.wk_cb.addItems(page_size_list) - - # Page orientation - self.wk_orientation_label = QtWidgets.QLabel('%s:' % _("Orientation")) - self.wk_orientation_label.setToolTip(_("Can be:\n" - "- Portrait\n" - "- Landscape")) - - self.wk_orientation_radio = RadioSet([{'label': _('Portrait'), 'value': 'p'}, - {'label': _('Landscape'), 'value': 'l'}, - ], stretch=False) - - self.wks = OptionalInputSection(self.workspace_cb, - [ - self.workspace_type_lbl, - self.wk_cb, - self.wk_orientation_label, - self.wk_orientation_radio - ]) - - grid0.addWidget(self.wk_orientation_label, 8, 0) - grid0.addWidget(self.wk_orientation_radio, 8, 1) - - separator_line = QtWidgets.QFrame() - separator_line.setFrameShape(QtWidgets.QFrame.HLine) - separator_line.setFrameShadow(QtWidgets.QFrame.Sunken) - grid0.addWidget(separator_line, 9, 0, 1, 2) - - # Font Size - self.font_size_label = QtWidgets.QLabel('%s' % _('Font Size')) - grid0.addWidget(self.font_size_label, 10, 0, 1, 2) - - # Notebook Font Size - self.notebook_font_size_label = QtWidgets.QLabel('%s:' % _('Notebook')) - self.notebook_font_size_label.setToolTip( - _("This sets the font size for the elements found in the Notebook.\n" - "The notebook is the collapsible area in the left side of the GUI,\n" - "and include the Project, Selected and Tool tabs.") - ) - - self.notebook_font_size_spinner = FCSpinner() - self.notebook_font_size_spinner.set_range(8, 40) - self.notebook_font_size_spinner.setWrapping(True) - - qsettings = QSettings("Open Source", "FlatCAM") - if qsettings.contains("notebook_font_size"): - self.notebook_font_size_spinner.set_value(qsettings.value('notebook_font_size', type=int)) - else: - self.notebook_font_size_spinner.set_value(12) - - grid0.addWidget(self.notebook_font_size_label, 11, 0) - grid0.addWidget(self.notebook_font_size_spinner, 11, 1) - - # Axis Font Size - self.axis_font_size_label = QtWidgets.QLabel('%s:' % _('Axis')) - self.axis_font_size_label.setToolTip( - _("This sets the font size for canvas axis.") - ) - - self.axis_font_size_spinner = FCSpinner() - self.axis_font_size_spinner.set_range(0, 40) - self.axis_font_size_spinner.setWrapping(True) - - qsettings = QSettings("Open Source", "FlatCAM") - if qsettings.contains("axis_font_size"): - self.axis_font_size_spinner.set_value(qsettings.value('axis_font_size', type=int)) - else: - self.axis_font_size_spinner.set_value(8) - - grid0.addWidget(self.axis_font_size_label, 12, 0) - grid0.addWidget(self.axis_font_size_spinner, 12, 1) - - # TextBox Font Size - self.textbox_font_size_label = QtWidgets.QLabel('%s:' % _('Textbox')) - self.textbox_font_size_label.setToolTip( - _("This sets the font size for the Textbox GUI\n" - "elements that are used in FlatCAM.") - ) - - self.textbox_font_size_spinner = FCSpinner() - self.textbox_font_size_spinner.set_range(8, 40) - self.textbox_font_size_spinner.setWrapping(True) - - qsettings = QSettings("Open Source", "FlatCAM") - if qsettings.contains("textbox_font_size"): - self.textbox_font_size_spinner.set_value(settings.value('textbox_font_size', type=int)) - else: - self.textbox_font_size_spinner.set_value(10) - - grid0.addWidget(self.textbox_font_size_label, 13, 0) - grid0.addWidget(self.textbox_font_size_spinner, 13, 1) - - separator_line = QtWidgets.QFrame() - separator_line.setFrameShape(QtWidgets.QFrame.HLine) - separator_line.setFrameShadow(QtWidgets.QFrame.Sunken) - grid0.addWidget(separator_line, 14, 0, 1, 2) - - # ----------------------------------------------------------- - # -------------- MOUSE SETTINGS ----------------------------- - # ----------------------------------------------------------- - - self.mouse_lbl = QtWidgets.QLabel('%s' % _('Mouse Settings')) - grid0.addWidget(self.mouse_lbl, 21, 0, 1, 2) - - # Mouse Cursor Shape - self.cursor_lbl = QtWidgets.QLabel('%s:' % _('Cursor Shape')) - self.cursor_lbl.setToolTip( - _("Choose a mouse cursor shape.\n" - "- Small -> with a customizable size.\n" - "- Big -> Infinite lines") - ) - - self.cursor_radio = RadioSet([ - {"label": _("Small"), "value": "small"}, - {"label": _("Big"), "value": "big"} - ], orientation='horizontal', stretch=False) - - grid0.addWidget(self.cursor_lbl, 22, 0) - grid0.addWidget(self.cursor_radio, 22, 1) - - # Mouse Cursor Size - self.cursor_size_lbl = QtWidgets.QLabel('%s:' % _('Cursor Size')) - self.cursor_size_lbl.setToolTip( - _("Set the size of the mouse cursor, in pixels.") - ) - - self.cursor_size_entry = FCSpinner() - self.cursor_size_entry.set_range(10, 70) - self.cursor_size_entry.setWrapping(True) - - grid0.addWidget(self.cursor_size_lbl, 23, 0) - grid0.addWidget(self.cursor_size_entry, 23, 1) - - # Cursor Width - self.cursor_width_lbl = QtWidgets.QLabel('%s:' % _('Cursor Width')) - self.cursor_width_lbl.setToolTip( - _("Set the line width of the mouse cursor, in pixels.") - ) - - self.cursor_width_entry = FCSpinner() - self.cursor_width_entry.set_range(1, 10) - self.cursor_width_entry.setWrapping(True) - - grid0.addWidget(self.cursor_width_lbl, 24, 0) - grid0.addWidget(self.cursor_width_entry, 24, 1) - - # Cursor Color Enable - self.mouse_cursor_color_cb = FCCheckBox(label='%s' % _('Cursor Color')) - self.mouse_cursor_color_cb.setToolTip( - _("Check this box to color mouse cursor.") - ) - grid0.addWidget(self.mouse_cursor_color_cb, 25, 0, 1, 2) - - # Cursor Color - self.mouse_color_label = QtWidgets.QLabel('%s:' % _('Cursor Color')) - self.mouse_color_label.setToolTip( - _("Set the color of the mouse cursor.") - ) - self.mouse_cursor_entry = FCEntry() - self.mouse_cursor_button = QtWidgets.QPushButton() - self.mouse_cursor_button.setFixedSize(15, 15) - - self.form_box_child_1 = QtWidgets.QHBoxLayout() - self.form_box_child_1.addWidget(self.mouse_cursor_entry) - self.form_box_child_1.addWidget(self.mouse_cursor_button) - self.form_box_child_1.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter) - - grid0.addWidget(self.mouse_color_label, 26, 0) - grid0.addLayout(self.form_box_child_1, 26, 1) - - self.mois = OptionalInputSection( - self.mouse_cursor_color_cb, - [ - self.mouse_color_label, - self.mouse_cursor_entry, - self.mouse_cursor_button - ] - ) - # Select mouse pan button - self.panbuttonlabel = QtWidgets.QLabel('%s:' % _('Pan Button')) - self.panbuttonlabel.setToolTip( - _("Select the mouse button to use for panning:\n" - "- MMB --> Middle Mouse Button\n" - "- RMB --> Right Mouse Button") - ) - self.pan_button_radio = RadioSet([{'label': _('MMB'), 'value': '3'}, - {'label': _('RMB'), 'value': '2'}]) - - grid0.addWidget(self.panbuttonlabel, 27, 0) - grid0.addWidget(self.pan_button_radio, 27, 1) - - # Multiple Selection Modifier Key - self.mselectlabel = QtWidgets.QLabel('%s:' % _('Multiple Selection')) - self.mselectlabel.setToolTip( - _("Select the key used for multiple selection.") - ) - self.mselect_radio = RadioSet([{'label': _('CTRL'), 'value': 'Control'}, - {'label': _('SHIFT'), 'value': 'Shift'}]) - - grid0.addWidget(self.mselectlabel, 28, 0) - grid0.addWidget(self.mselect_radio, 28, 1) - - separator_line = QtWidgets.QFrame() - separator_line.setFrameShape(QtWidgets.QFrame.HLine) - separator_line.setFrameShadow(QtWidgets.QFrame.Sunken) - grid0.addWidget(separator_line, 29, 0, 1, 2) - - # Delete confirmation - self.delete_conf_cb = FCCheckBox(_('Delete object confirmation')) - self.delete_conf_cb.setToolTip( - _("When checked the application will ask for user confirmation\n" - "whenever the Delete object(s) event is triggered, either by\n" - "menu shortcut or key shortcut.") - ) - grid0.addWidget(self.delete_conf_cb, 30, 0, 1, 2) - - # Open behavior - self.open_style_cb = FCCheckBox('%s' % _('"Open" behavior')) - self.open_style_cb.setToolTip( - _("When checked the path for the last saved file is used when saving files,\n" - "and the path for the last opened file is used when opening files.\n\n" - "When unchecked the path for opening files is the one used last: either the\n" - "path for saving files or the path for opening files.") - ) - - grid0.addWidget(self.open_style_cb, 31, 0, 1, 2) - - # Enable/Disable ToolTips globally - self.toggle_tooltips_cb = FCCheckBox(label=_('Enable ToolTips')) - self.toggle_tooltips_cb.setToolTip( - _("Check this box if you want to have toolTips displayed\n" - "when hovering with mouse over items throughout the App.") - ) - - grid0.addWidget(self.toggle_tooltips_cb, 32, 0, 1, 2) - - # Machinist settings that allow unsafe settings - self.machinist_cb = FCCheckBox(_("Allow Machinist Unsafe Settings")) - self.machinist_cb.setToolTip( - _("If checked, some of the application settings will be allowed\n" - "to have values that are usually unsafe to use.\n" - "Like Z travel negative values or Z Cut positive values.\n" - "It will applied at the next application start.\n" - "<>: Don't change this unless you know what you are doing !!!") - ) - - grid0.addWidget(self.machinist_cb, 33, 0, 1, 2) - - # Bookmarks Limit in the Help Menu - self.bm_limit_spinner = FCSpinner() - self.bm_limit_spinner.set_range(0, 9999) - self.bm_limit_label = QtWidgets.QLabel('%s:' % _('Bookmarks limit')) - self.bm_limit_label.setToolTip( - _("The maximum number of bookmarks that may be installed in the menu.\n" - "The number of bookmarks in the bookmark manager may be greater\n" - "but the menu will hold only so much.") - ) - - grid0.addWidget(self.bm_limit_label, 34, 0) - grid0.addWidget(self.bm_limit_spinner, 34, 1) - - # Activity monitor icon - self.activity_label = QtWidgets.QLabel('%s:' % _("Activity Icon")) - self.activity_label.setToolTip( - _("Select the GIF that show activity when FlatCAM is active.") - ) - self.activity_combo = FCComboBox() - self.activity_combo.addItems(['Ball black', 'Ball green', 'Arrow green', 'Eclipse green']) - - grid0.addWidget(self.activity_label, 35, 0) - grid0.addWidget(self.activity_combo, 35, 1) - - self.layout.addStretch() - - self.mouse_cursor_color_cb.stateChanged.connect(self.on_mouse_cursor_color_enable) - - self.mouse_cursor_entry.editingFinished.connect(self.on_mouse_cursor_entry) - self.mouse_cursor_button.clicked.connect(self.on_mouse_cursor_button) - - def on_mouse_cursor_color_enable(self, val): - if val: - self.app.cursor_color_3D = self.app.defaults["global_cursor_color"] - else: - theme_settings = QtCore.QSettings("Open Source", "FlatCAM") - if theme_settings.contains("theme"): - theme = theme_settings.value('theme', type=str) - else: - theme = 'white' - - if theme == 'white': - self.app.cursor_color_3D = 'black' - else: - self.app.cursor_color_3D = 'gray' - - def on_mouse_cursor_entry(self): - self.app.defaults['global_cursor_color'] = self.mouse_cursor_entry.get_value() - self.mouse_cursor_button.setStyleSheet("background-color:%s" % str(self.app.defaults['global_cursor_color'])) - - self.app.cursor_color_3D = self.app.defaults["global_cursor_color"] - - def on_mouse_cursor_button(self): - current_color = QtGui.QColor(self.app.defaults['global_cursor_color']) - - c_dialog = QtWidgets.QColorDialog() - proj_color = c_dialog.getColor(initial=current_color) - - if proj_color.isValid() is False: - return - - self.mouse_cursor_button.setStyleSheet("background-color:%s" % str(proj_color.name())) - - new_val_sel = str(proj_color.name()) - self.mouse_cursor_entry.set_value(new_val_sel) - self.app.defaults['global_cursor_color'] = new_val_sel - - self.app.cursor_color_3D = self.app.defaults["global_cursor_color"] diff --git a/flatcamGUI/preferences/general/GeneralAppSettingsGroupUI.py b/flatcamGUI/preferences/general/GeneralAppSettingsGroupUI.py new file mode 100644 index 00000000..a3cd4f20 --- /dev/null +++ b/flatcamGUI/preferences/general/GeneralAppSettingsGroupUI.py @@ -0,0 +1,301 @@ +from PyQt5 import QtCore, QtGui +from PyQt5.QtCore import QSettings +from flatcamGUI.GUIElements import OptionalInputSection +from flatcamGUI.preferences import settings +from flatcamGUI.preferences.OptionUI import * +from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI, OptionsGroupUI2 + +import gettext +import FlatCAMTranslation as fcTranslate +import builtins +fcTranslate.apply_language('strings') +if '_' not in builtins.__dict__: + _ = gettext.gettext + + +class GeneralAppSettingsGroupUI(OptionsGroupUI2): + def __init__(self, decimals=4, **kwargs): + self.decimals = decimals + self.pagesize = {} + self.pagesize.update( + { + 'A0': (841, 1189), + 'A1': (594, 841), + 'A2': (420, 594), + 'A3': (297, 420), + 'A4': (210, 297), + 'A5': (148, 210), + 'A6': (105, 148), + 'A7': (74, 105), + 'A8': (52, 74), + 'A9': (37, 52), + 'A10': (26, 37), + + 'B0': (1000, 1414), + 'B1': (707, 1000), + 'B2': (500, 707), + 'B3': (353, 500), + 'B4': (250, 353), + 'B5': (176, 250), + 'B6': (125, 176), + 'B7': (88, 125), + 'B8': (62, 88), + 'B9': (44, 62), + 'B10': (31, 44), + + 'C0': (917, 1297), + 'C1': (648, 917), + 'C2': (458, 648), + 'C3': (324, 458), + 'C4': (229, 324), + 'C5': (162, 229), + 'C6': (114, 162), + 'C7': (81, 114), + 'C8': (57, 81), + 'C9': (40, 57), + 'C10': (28, 40), + + # American paper sizes + 'LETTER': (8.5, 11), + 'LEGAL': (8.5, 14), + 'ELEVENSEVENTEEN': (11, 17), + + # From https://en.wikipedia.org/wiki/Paper_size + 'JUNIOR_LEGAL': (5, 8), + 'HALF_LETTER': (5.5, 8), + 'GOV_LETTER': (8, 10.5), + 'GOV_LEGAL': (8.5, 13), + 'LEDGER': (17, 11), + } + ) + super().__init__(**kwargs) + + self.setTitle(str(_("App Settings"))) + + qsettings = QSettings("Open Source", "FlatCAM") + + self.notebook_font_size_field = self.option_dict()["notebook_font_size"].get_field() + if qsettings.contains("notebook_font_size"): + self.notebook_font_size_field.set_value(qsettings.value('notebook_font_size', type=int)) + else: + self.notebook_font_size_field.set_value(12) + + self.axis_font_size_field = self.option_dict()["axis_font_size"].get_field() + if qsettings.contains("axis_font_size"): + self.axis_font_size_field.set_value(qsettings.value('axis_font_size', type=int)) + else: + self.axis_font_size_field.set_value(8) + + self.textbox_font_size_field = self.option_dict()["textbox_font_size"].get_field() + if qsettings.contains("textbox_font_size"): + self.textbox_font_size_field.set_value(settings.value('textbox_font_size', type=int)) + else: + self.textbox_font_size_field.set_value(10) + + self.workspace_enabled_field = self.option_dict()["global_workspace"].get_field() + self.workspace_type_field = self.option_dict()["global_workspaceT"].get_field() + self.workspace_type_label = self.option_dict()["global_workspaceT"].label_widget + self.workspace_orientation_field = self.option_dict()["global_workspace_orientation"].get_field() + self.workspace_orientation_label = self.option_dict()["global_workspace_orientation"].label_widget + self.wks = OptionalInputSection(self.workspace_enabled_field, [self.workspace_type_label, self.workspace_type_field, self.workspace_orientation_label, self.workspace_orientation_field]) + + self.mouse_cursor_color_enabled_field = self.option_dict()["global_cursor_color_enabled"].get_field() + self.mouse_cursor_color_field = self.option_dict()["global_cursor_color"].get_field() + self.mouse_cursor_color_label = self.option_dict()["global_cursor_color"].label_widget + self.mois = OptionalInputSection(self.mouse_cursor_color_enabled_field, [self.mouse_cursor_color_label, self.mouse_cursor_color_field]) + self.mouse_cursor_color_enabled_field.stateChanged.connect(self.on_mouse_cursor_color_enable) + self.mouse_cursor_color_field.entry.editingFinished.connect(self.on_mouse_cursor_entry) + + def build_options(self) -> [OptionUI]: + return [ + HeadingOptionUI(label_text="Grid Settings", label_tooltip=None), + DoubleSpinnerOptionUI( + option="global_gridx", + label_text="X value", + label_tooltip="This is the Grid snap value on X axis.", + step=0.1, + decimals=self.decimals + ), + DoubleSpinnerOptionUI( + option="global_gridy", + label_text='Y value', + label_tooltip="This is the Grid snap value on Y axis.", + step=0.1, + decimals=self.decimals + ), + DoubleSpinnerOptionUI( + option="global_snap_max", + label_text="Snap Max", + label_tooltip="Max. magnet distance", + step=0.1, + decimals=self.decimals + ), + SeparatorOptionUI(), + + HeadingOptionUI(label_text="Workspace Settings", label_tooltip=None), + CheckboxOptionUI( + option="global_workspace", + label_text="Active", + label_tooltip="Draw a delimiting rectangle on canvas.\n" + "The purpose is to illustrate the limits for our work." + ), + ComboboxOptionUI( + option="global_workspaceT", + label_text="Size", + label_tooltip="Select the type of rectangle to be used on canvas,\nas valid workspace.", + choices=list(self.pagesize.keys()) + ), + RadioSetOptionUI( + option="global_workspace_orientation", + label_text="Orientation", + label_tooltip="Can be:\n- Portrait\n- Landscape", + choices=[ + {'label': _('Portrait'), 'value': 'p'}, + {'label': _('Landscape'), 'value': 'l'}, + ] + ), + # FIXME enabling OptionalInputSection ?? + SeparatorOptionUI(), + + HeadingOptionUI(label_text="Font Size", label_tooltip=None), + SpinnerOptionUI( + option="notebook_font_size", #FIXME qsettings + label_text="Notebook", + label_tooltip="This sets the font size for the elements found in the Notebook.\n" + "The notebook is the collapsible area in the left side of the GUI,\n" + "and include the Project, Selected and Tool tabs.", + min_value=8, max_value=40, step=1 + ), + SpinnerOptionUI( + option="axis_font_size", #FIXME qsettings + label_text="Axis", + label_tooltip="This sets the font size for canvas axis.", + min_value=8, max_value=40, step=1 + ), + SpinnerOptionUI( + option="textbox_font_size", #FIXME qsettings, + label_text="Textbox", + label_tooltip="This sets the font size for the Textbox GUI\n" + "elements that are used in FlatCAM.", + min_value=8, max_value=40, step=1 + ), + SeparatorOptionUI(), + + HeadingOptionUI(label_text="Mouse Settings", label_tooltip=None), + RadioSetOptionUI( + option="global_cursor_type", + label_text="Cursor Shape", + label_tooltip="Choose a mouse cursor shape.\n" + "- Small -> with a customizable size.\n" + "- Big -> Infinite lines", + choices=[ + {"label": _("Small"), "value": "small"}, + {"label": _("Big"), "value": "big"} + ] + ), + SpinnerOptionUI( + option="global_cursor_size", + label_text="Cursor Size", + label_tooltip="Set the size of the mouse cursor, in pixels.", + min_value=10, max_value=70, step=1 + ), + SpinnerOptionUI( + option="global_cursor_width", + label_text="Cursor Width", + label_tooltip="Set the line width of the mouse cursor, in pixels.", + min_value=1, max_value=10, step=1 + ), + CheckboxOptionUI( + option="global_cursor_color_enabled", + label_text="Cursor Color", + label_tooltip="Check this box to color mouse cursor." + ), + ColorOptionUI( + option="global_cursor_color", + label_text="Cursor Color", + label_tooltip="Set the color of the mouse cursor." + ), + # FIXME enabling of cursor color + RadioSetOptionUI( + option="global_pan_button", + label_text="Pan Button", + label_tooltip="Select the mouse button to use for panning:\n" + "- MMB --> Middle Mouse Button\n" + "- RMB --> Right Mouse Button", + choices=[{'label': _('MMB'), 'value': '3'}, + {'label': _('RMB'), 'value': '2'}] + ), + RadioSetOptionUI( + option="global_mselect_key", + label_text="Multiple Selection", + label_tooltip="Select the key used for multiple selection.", + choices=[{'label': _('CTRL'), 'value': 'Control'}, + {'label': _('SHIFT'), 'value': 'Shift'}] + ), + SeparatorOptionUI(), + + CheckboxOptionUI( + option="global_delete_confirmation", + label_text="Delete object confirmation", + label_tooltip="When checked the application will ask for user confirmation\n" + "whenever the Delete object(s) event is triggered, either by\n" + "menu shortcut or key shortcut." + ), + CheckboxOptionUI( + option="global_open_style", + label_text='"Open" behavior', + label_tooltip="When checked the path for the last saved file is used when saving files,\n" + "and the path for the last opened file is used when opening files.\n\n" + "When unchecked the path for opening files is the one used last: either the\n" + "path for saving files or the path for opening files." + ), + CheckboxOptionUI( + option="global_toggle_tooltips", + label_text="Enable ToolTips", + label_tooltip="Check this box if you want to have toolTips displayed\n" + "when hovering with mouse over items throughout the App." + ), + CheckboxOptionUI( + option="global_machinist_setting", + label_text="Allow Machinist Unsafe Settings", + label_tooltip="If checked, some of the application settings will be allowed\n" + "to have values that are usually unsafe to use.\n" + "Like Z travel negative values or Z Cut positive values.\n" + "It will applied at the next application start.\n" + "<>: Don't change this unless you know what you are doing !!!" + ), + SpinnerOptionUI( + option="global_bookmarks_limit", + label_text="Bookmarks limit", + label_tooltip="The maximum number of bookmarks that may be installed in the menu.\n" + "The number of bookmarks in the bookmark manager may be greater\n" + "but the menu will hold only so much.", + min_value=0, max_value=9999, step=1 + ), + ComboboxOptionUI( + option="global_activity_icon", + label_text="Activity Icon", + label_tooltip="Select the GIF that show activity when FlatCAM is active.", + choices=['Ball black', 'Ball green', 'Arrow green', 'Eclipse green'] + ) + + ] + + def on_mouse_cursor_color_enable(self, val): + if val: + self.app.cursor_color_3D = self.app.defaults["global_cursor_color"] + else: + theme_settings = QtCore.QSettings("Open Source", "FlatCAM") + if theme_settings.contains("theme"): + theme = theme_settings.value('theme', type=str) + else: + theme = 'white' + + if theme == 'white': + self.app.cursor_color_3D = 'black' + else: + self.app.cursor_color_3D = 'gray' + + def on_mouse_cursor_entry(self): + self.app.defaults['global_cursor_color'] = self.mouse_cursor_color_field.get_value() + self.app.cursor_color_3D = self.app.defaults["global_cursor_color"] diff --git a/flatcamGUI/preferences/general/GeneralGUIPrefGroupUI.py b/flatcamGUI/preferences/general/GeneralGUIPrefGroupUI.py index 668c8780..8b77cce6 100644 --- a/flatcamGUI/preferences/general/GeneralGUIPrefGroupUI.py +++ b/flatcamGUI/preferences/general/GeneralGUIPrefGroupUI.py @@ -51,7 +51,6 @@ class GeneralGUIPrefGroupUI(OptionsGroupUI2): self.alt_sel_alpha_field = self.option_dict()["_global_alt_sel_alpha"].get_field() self.alt_sel_alpha_field.spinner.valueChanged.connect(self.on_alt_sel_alpha_change) - def build_options(self) -> [OptionUI]: return [ RadioSetOptionUI( @@ -132,7 +131,7 @@ class GeneralGUIPrefGroupUI(OptionsGroupUI2): option="_global_sel_alpha", label_text="Alpha", label_tooltip="Set the fill transparency for the 'left to right' selection box.", - min=0, max=255, step=1 + min_value=0, max_value=255, step=1 ), SeparatorOptionUI(), @@ -154,7 +153,7 @@ class GeneralGUIPrefGroupUI(OptionsGroupUI2): option="_global_alt_sel_alpha", label_text="Alpha", label_tooltip="Set the fill transparency for the 'right to left' selection box.", - min=0, max=255, step=1 + min_value=0, max_value=255, step=1 ), SeparatorOptionUI(), diff --git a/flatcamGUI/preferences/general/GeneralPreferencesUI.py b/flatcamGUI/preferences/general/GeneralPreferencesUI.py index 4e44a473..f504fcf8 100644 --- a/flatcamGUI/preferences/general/GeneralPreferencesUI.py +++ b/flatcamGUI/preferences/general/GeneralPreferencesUI.py @@ -1,7 +1,7 @@ from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI from flatcamGUI.preferences.PreferencesSectionUI import PreferencesSectionUI from flatcamGUI.preferences.general.GeneralAppPrefGroupUI import GeneralAppPrefGroupUI -from flatcamGUI.preferences.general.GeneralAPPSetGroupUI import GeneralAPPSetGroupUI +from flatcamGUI.preferences.general.GeneralAppSettingsGroupUI import GeneralAppSettingsGroupUI from flatcamGUI.preferences.general.GeneralGUIPrefGroupUI import GeneralGUIPrefGroupUI @@ -11,13 +11,13 @@ class GeneralPreferencesUI(PreferencesSectionUI): self.decimals = decimals self.general_gui_group = GeneralGUIPrefGroupUI(decimals=self.decimals) self.general_app_group = GeneralAppPrefGroupUI(decimals=self.decimals) - self.general_app_set_group = GeneralAPPSetGroupUI(decimals=self.decimals) + self.general_app_settings_group = GeneralAppSettingsGroupUI(decimals=self.decimals) super().__init__(**kwargs) def build_groups(self) -> [OptionsGroupUI]: return [ self.general_app_group, self.general_gui_group, - self.general_app_set_group + self.general_app_settings_group ] From 406faa36c37784e900ef590f49fbfc8e186f3f82 Mon Sep 17 00:00:00 2001 From: David Robertson Date: Sun, 3 May 2020 04:18:40 +0100 Subject: [PATCH 09/41] Fix crash on startupo when cursor set to "big" --- flatcamEditors/FlatCAMExcEditor.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flatcamEditors/FlatCAMExcEditor.py b/flatcamEditors/FlatCAMExcEditor.py index 49dc5eb5..820e5eb8 100644 --- a/flatcamEditors/FlatCAMExcEditor.py +++ b/flatcamEditors/FlatCAMExcEditor.py @@ -2119,7 +2119,7 @@ class FlatCAMExcEditor(QtCore.QObject): if self.app.is_legacy is False: self.shapes = self.app.plotcanvas.new_shape_collection(layers=1) if self.app.plotcanvas.big_cursor is True: - self.tool_shape = self.app.plotcanvas.new_shape_collection(layers=1, line_width=2) + self.tool_shape = self.app.plotcanvas.new_shape_collection(layers=1) else: self.tool_shape = self.app.plotcanvas.new_shape_collection(layers=1) else: From df9ebaf2c9d6ff6c4d4c41ec15ef3c1e7e9c2705 Mon Sep 17 00:00:00 2001 From: David Robertson Date: Sun, 3 May 2020 14:07:22 +0100 Subject: [PATCH 10/41] minor cleanup --- .../preferences/general/GeneralAppSettingsGroupUI.py | 8 ++++---- flatcamGUI/preferences/general/GeneralPreferencesUI.py | 7 +++---- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/flatcamGUI/preferences/general/GeneralAppSettingsGroupUI.py b/flatcamGUI/preferences/general/GeneralAppSettingsGroupUI.py index a3cd4f20..5c37c527 100644 --- a/flatcamGUI/preferences/general/GeneralAppSettingsGroupUI.py +++ b/flatcamGUI/preferences/general/GeneralAppSettingsGroupUI.py @@ -3,7 +3,7 @@ from PyQt5.QtCore import QSettings from flatcamGUI.GUIElements import OptionalInputSection from flatcamGUI.preferences import settings from flatcamGUI.preferences.OptionUI import * -from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI, OptionsGroupUI2 +from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI2 import gettext import FlatCAMTranslation as fcTranslate @@ -159,7 +159,7 @@ class GeneralAppSettingsGroupUI(OptionsGroupUI2): HeadingOptionUI(label_text="Font Size", label_tooltip=None), SpinnerOptionUI( - option="notebook_font_size", #FIXME qsettings + option="notebook_font_size", label_text="Notebook", label_tooltip="This sets the font size for the elements found in the Notebook.\n" "The notebook is the collapsible area in the left side of the GUI,\n" @@ -167,13 +167,13 @@ class GeneralAppSettingsGroupUI(OptionsGroupUI2): min_value=8, max_value=40, step=1 ), SpinnerOptionUI( - option="axis_font_size", #FIXME qsettings + option="axis_font_size", label_text="Axis", label_tooltip="This sets the font size for canvas axis.", min_value=8, max_value=40, step=1 ), SpinnerOptionUI( - option="textbox_font_size", #FIXME qsettings, + option="textbox_font_size", label_text="Textbox", label_tooltip="This sets the font size for the Textbox GUI\n" "elements that are used in FlatCAM.", diff --git a/flatcamGUI/preferences/general/GeneralPreferencesUI.py b/flatcamGUI/preferences/general/GeneralPreferencesUI.py index f504fcf8..6b3bea67 100644 --- a/flatcamGUI/preferences/general/GeneralPreferencesUI.py +++ b/flatcamGUI/preferences/general/GeneralPreferencesUI.py @@ -8,10 +8,9 @@ from flatcamGUI.preferences.general.GeneralGUIPrefGroupUI import GeneralGUIPrefG class GeneralPreferencesUI(PreferencesSectionUI): def __init__(self, decimals, **kwargs): - self.decimals = decimals - self.general_gui_group = GeneralGUIPrefGroupUI(decimals=self.decimals) - self.general_app_group = GeneralAppPrefGroupUI(decimals=self.decimals) - self.general_app_settings_group = GeneralAppSettingsGroupUI(decimals=self.decimals) + self.general_app_group = GeneralAppPrefGroupUI(decimals=decimals) + self.general_gui_group = GeneralGUIPrefGroupUI(decimals=decimals) + self.general_app_settings_group = GeneralAppSettingsGroupUI(decimals=decimals) super().__init__(**kwargs) def build_groups(self) -> [OptionsGroupUI]: From a2d48d1c663d0a3a596a8ee2d319cc1f9fcce888 Mon Sep 17 00:00:00 2001 From: David Robertson Date: Sun, 3 May 2020 15:38:26 +0100 Subject: [PATCH 11/41] Refactor the app prefs group --- FlatCAMApp.py | 40 +- FlatCAMTranslation.py | 2 +- flatcamGUI/FlatCAMGUI.py | 2 +- flatcamGUI/preferences/OptionUI.py | 33 +- .../preferences/PreferencesUIManager.py | 32 +- .../general/GeneralAppPrefGroupUI.py | 571 +++++++----------- .../general/GeneralGUIPrefGroupUI.py | 2 +- 7 files changed, 266 insertions(+), 416 deletions(-) diff --git a/FlatCAMApp.py b/FlatCAMApp.py index f960f2e7..93043ed7 100644 --- a/FlatCAMApp.py +++ b/FlatCAMApp.py @@ -625,8 +625,9 @@ class App(QtCore.QObject): # ########################################################################################################### self.languages = fcTranslate.load_languages() + language_field = self.preferencesUiManager.get_form_field("global_language") for name in sorted(self.languages.values()): - self.ui.general_defaults_form.general_app_group.language_cb.addItem(name) + language_field.addItem(name) # ########################################################################################################### # ####################################### APPLY APP LANGUAGE ################################################ @@ -639,7 +640,7 @@ class App(QtCore.QObject): 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.preferencesUiManager.get_form_field("global_language").setCurrentText(ret_val) log.debug("App.__init__() --> Applied %s language." % str(ret_val).capitalize()) # ########################################################################################################### @@ -959,25 +960,24 @@ class App(QtCore.QObject): # #################################### GUI PREFERENCES SIGNALS ############################################## # ########################################################################################################### - self.ui.general_defaults_form.general_app_group.units_radio.activated_custom.connect( + self.preferencesUiManager.get_form_field("units").activated_custom.connect( lambda: self.on_toggle_units(no_pref=False)) # ##################################### Workspace Setting Signals ########################################### - self.preferencesUiManager.option_dict()["global_workspaceT"].get_field().currentIndexChanged.connect( + self.preferencesUiManager.get_form_field("global_workspaceT").currentIndexChanged.connect( self.on_workspace_modified) - self.preferencesUiManager.option_dict()["global_workspace_orientation"].get_field().activated_custom.connect( + self.preferencesUiManager.get_form_field("global_workspace_orientation").activated_custom.connect( self.on_workspace_modified ) - self.preferencesUiManager.option_dict()["global_workspace"].get_field().stateChanged.connect(self.on_workspace) + self.preferencesUiManager.get_form_field("global_workspace").stateChanged.connect(self.on_workspace) # ########################################################################################################### # ######################################## GUI SETTINGS SIGNALS ############################################# # ########################################################################################################### - self.ui.general_defaults_form.general_app_group.ge_radio.activated_custom.connect(self.on_app_restart) - + self.preferencesUiManager.get_form_field("global_graphic_engine").activated_custom.connect(self.on_app_restart) self.preferencesUiManager.get_form_field("global_cursor_type").activated_custom.connect(self.on_cursor_type) # ######################################## Tools related signals ############################################ @@ -998,7 +998,7 @@ class App(QtCore.QObject): self.on_qrcode_back_color_button) # portability changed signal - self.ui.general_defaults_form.general_app_group.portability_cb.stateChanged.connect(self.on_portable_checked) + self.preferencesUiManager.get_form_field("global_portable").stateChanged.connect(self.on_portable_checked) # Object list self.collection.view.activated.connect(self.on_row_activated) @@ -1421,8 +1421,8 @@ class App(QtCore.QObject): # Separate thread (Not worker) # Check for updates on startup but only if the user consent and the app is not in Beta version if (self.beta is False or self.beta is None) and \ - self.ui.general_defaults_form.general_app_group.version_check_cb.get_value() is True: - App.log.info("Checking for updates in backgroud (this is version %s)." % str(self.version)) + self.preferencesUiManager.get_form_field("global_version_check").get_value() is True: + App.log.info("Checking for updates in background (this is version %s)." % str(self.version)) # self.thr2 = QtCore.QThread() self.worker_task.emit({'fcn': self.version_check, @@ -1549,7 +1549,7 @@ class App(QtCore.QObject): self.abort_flag = False # set the value used in the Windows Title - self.engine = self.ui.general_defaults_form.general_app_group.ge_radio.get_value() + self.engine = self.preferencesUiManager.get_form_field("global_graphic_engine").get_value() # this holds a widget that is installed in the Plot Area when View Source option is used self.source_editor_tab = None @@ -3562,7 +3562,7 @@ class App(QtCore.QObject): stgs.setValue('maximized_gui', self.ui.isMaximized()) stgs.setValue( 'language', - self.ui.general_defaults_form.general_app_group.language_cb.get_value() + self.preferencesUiManager.get_form_field("global_language").get_value() ) stgs.setValue( 'notebook_font_size', @@ -4204,18 +4204,18 @@ class App(QtCore.QObject): def on_toggle_units_click(self): try: - self.ui.general_defaults_form.general_app_group.units_radio.activated_custom.disconnect() + self.preferencesUiManager.get_form_field("units").activated_custom.disconnect() except (TypeError, AttributeError): pass if self.defaults["units"] == 'MM': - self.ui.general_defaults_form.general_app_group.units_radio.set_value("IN") + self.preferencesUiManager.get_form_field("units").set_value("IN") else: - self.ui.general_defaults_form.general_app_group.units_radio.set_value("MM") + self.preferencesUiManager.get_form_field("units").set_value("MM") self.on_toggle_units(no_pref=True) - self.ui.general_defaults_form.general_app_group.units_radio.activated_custom.connect( + self.preferencesUiManager.get_form_field("units").activated_custom.connect( lambda: self.on_toggle_units(no_pref=False)) def on_toggle_units(self, no_pref=False): @@ -4233,7 +4233,7 @@ class App(QtCore.QObject): if self.toggle_units_ignore: return - new_units = self.ui.general_defaults_form.general_app_group.units_radio.get_value().upper() + new_units = self.preferencesUiManager.get_form_field("units").get_value().upper() # If option is the same, then ignore if new_units == self.defaults["units"].upper(): @@ -4530,9 +4530,9 @@ class App(QtCore.QObject): # Undo toggling self.toggle_units_ignore = True if self.defaults['units'].upper() == 'MM': - self.ui.general_defaults_form.general_app_group.units_radio.set_value('IN') + self.preferencesUiManager.get_form_field("units").set_value('IN') else: - self.ui.general_defaults_form.general_app_group.units_radio.set_value('MM') + self.preferencesUiManager.get_form_field("units").set_value('MM') self.toggle_units_ignore = False # store the grid values so they are not changed in the next step diff --git a/FlatCAMTranslation.py b/FlatCAMTranslation.py index a4ab8f51..49c58b3e 100644 --- a/FlatCAMTranslation.py +++ b/FlatCAMTranslation.py @@ -79,7 +79,7 @@ def on_language_apply_click(app, restart=False): :return: """ - name = app.ui.general_defaults_form.general_app_group.language_cb.currentText() + name = app.preferencesUiManager.get_form_field("global_language").currentText() theme_settings = QSettings("Open Source", "FlatCAM") if theme_settings.contains("theme"): diff --git a/flatcamGUI/FlatCAMGUI.py b/flatcamGUI/FlatCAMGUI.py index c1b368b4..b029b324 100644 --- a/flatcamGUI/FlatCAMGUI.py +++ b/flatcamGUI/FlatCAMGUI.py @@ -4057,7 +4057,7 @@ class FlatCAMGUI(QtWidgets.QMainWindow): if key == QtCore.Qt.Key_T or key == 'T': self.app.exc_editor.launched_from_shortcuts = True # ## Current application units in Upper Case - self.units = self.general_defaults_form.general_app_group.units_radio.get_value().upper() + self.units = self.general_defaults_form.option_dict()["units"].get_field().get_value().upper() tool_add_popup = FCInputDialog(title=_("New Tool ..."), text='%s:' % _('Enter a Tool Diameter'), min=0.0000, max=99.9999, decimals=4) diff --git a/flatcamGUI/preferences/OptionUI.py b/flatcamGUI/preferences/OptionUI.py index bec4247c..bef0b5c5 100644 --- a/flatcamGUI/preferences/OptionUI.py +++ b/flatcamGUI/preferences/OptionUI.py @@ -30,15 +30,22 @@ class OptionUI: class BasicOptionUI(OptionUI): """Abstract OptionUI that has a label on the left then some other widget on the right""" - def __init__(self, option: str, label_text: str, label_tooltip: str): + def __init__(self, option: str, label_text: str, label_tooltip: Union[str, None] = None, label_bold: bool = False, label_red: bool = False): super().__init__(option=option) self.label_text = label_text self.label_tooltip = label_tooltip + self.label_bold = label_bold + self.label_red = label_red self.label_widget = self.build_label_widget() self.entry_widget = self.build_entry_widget() def build_label_widget(self) -> QtWidgets.QLabel: - label_widget = QtWidgets.QLabel('%s:' % _(self.label_text)) + fmt = "%s:" + if self.label_bold: + fmt = "%s" % fmt + if self.label_red: + fmt = "%s" % fmt + label_widget = QtWidgets.QLabel(fmt % _(self.label_text)) if self.label_tooltip is not None: label_widget.setToolTip(_(self.label_tooltip)) return label_widget @@ -57,10 +64,10 @@ class BasicOptionUI(OptionUI): class RadioSetOptionUI(BasicOptionUI): - def __init__(self, option: str, label_text: str, label_tooltip: str, choices: list, orientation='horizontal'): + def __init__(self, option: str, label_text: str, choices: list, orientation='horizontal', **kwargs): self.choices = choices self.orientation = orientation - super().__init__(option=option, label_text=label_text, label_tooltip=label_tooltip) + super().__init__(option=option, label_text=label_text, **kwargs) def build_entry_widget(self) -> QtWidgets.QWidget: return RadioSet(choices=self.choices, orientation=self.orientation) @@ -89,9 +96,9 @@ class CheckboxOptionUI(OptionUI): class ComboboxOptionUI(BasicOptionUI): - def __init__(self, option: str, label_text: str, label_tooltip: str, choices: Sequence): + def __init__(self, option: str, label_text: str, choices: Sequence, **kwargs): self.choices = choices - super().__init__(option=option, label_text=label_text, label_tooltip=label_tooltip) + super().__init__(option=option, label_text=label_text, **kwargs) def build_entry_widget(self): combo = FCComboBox() @@ -108,11 +115,11 @@ class ColorOptionUI(BasicOptionUI): class SliderWithSpinnerOptionUI(BasicOptionUI): - def __init__(self, option: str, label_text: str, label_tooltip: str, min_value=0, max_value=100, step=1): + def __init__(self, option: str, label_text: str, min_value=0, max_value=100, step=1, **kwargs): self.min_value = min_value self.max_value = max_value self.step = step - super().__init__(option=option, label_text=label_text, label_tooltip=label_tooltip) + super().__init__(option=option, label_text=label_text, **kwargs) def build_entry_widget(self) -> QtWidgets.QWidget: entry = FCSliderWithSpinner(min=self.min_value, max=self.max_value, step=self.step) @@ -120,11 +127,11 @@ class SliderWithSpinnerOptionUI(BasicOptionUI): class SpinnerOptionUI(BasicOptionUI): - def __init__(self, option: str, label_text: str, label_tooltip: str, min_value: int, max_value: int, step: int = 1): + def __init__(self, option: str, label_text: str, min_value: int, max_value: int, step: int = 1, **kwargs): self.min_value = min_value self.max_value = max_value self.step = step - super().__init__(option=option, label_text=label_text, label_tooltip=label_tooltip) + super().__init__(option=option, label_text=label_text, **kwargs) def build_entry_widget(self) -> QtWidgets.QWidget: entry = FCSpinner() @@ -135,12 +142,12 @@ class SpinnerOptionUI(BasicOptionUI): class DoubleSpinnerOptionUI(BasicOptionUI): - def __init__(self, option: str, label_text: str, label_tooltip: str, step: float, decimals: int, min_value=None, max_value=None): + def __init__(self, option: str, label_text: str, step: float, decimals: int, min_value=None, max_value=None, **kwargs): self.min_value = min_value self.max_value = max_value self.step = step self.decimals = decimals - super().__init__(option=option, label_text=label_text, label_tooltip=label_tooltip) + super().__init__(option=option, label_text=label_text, **kwargs) def build_entry_widget(self) -> QtWidgets.QWidget: entry = FCDoubleSpinner() @@ -158,7 +165,7 @@ class DoubleSpinnerOptionUI(BasicOptionUI): class HeadingOptionUI(OptionUI): - def __init__(self, label_text: str, label_tooltip: Union[str, None]): + def __init__(self, label_text: str, label_tooltip: Union[str, None] = None): super().__init__(option="__heading") self.label_text = label_text self.label_tooltip = label_tooltip diff --git a/flatcamGUI/preferences/PreferencesUIManager.py b/flatcamGUI/preferences/PreferencesUIManager.py index 3234e251..f898e9fd 100644 --- a/flatcamGUI/preferences/PreferencesUIManager.py +++ b/flatcamGUI/preferences/PreferencesUIManager.py @@ -48,34 +48,6 @@ class PreferencesUIManager: # when adding entries here read the comments in the method found below named: # def new_object(self, kind, name, initialize, active=True, fit=True, plot=True) self.defaults_form_fields = { - # General App - "decimals_inch": self.ui.general_defaults_form.general_app_group.precision_inch_entry, - "decimals_metric": self.ui.general_defaults_form.general_app_group.precision_metric_entry, - "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_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, - "global_shell_at_startup": self.ui.general_defaults_form.general_app_group.shell_startup_cb, - "global_project_at_startup": self.ui.general_defaults_form.general_app_group.project_startup_cb, - "global_version_check": self.ui.general_defaults_form.general_app_group.version_check_cb, - "global_send_stats": self.ui.general_defaults_form.general_app_group.send_stats_cb, - - "global_worker_number": self.ui.general_defaults_form.general_app_group.worker_number_sb, - "global_tolerance": self.ui.general_defaults_form.general_app_group.tol_entry, - - "global_compression_level": self.ui.general_defaults_form.general_app_group.compress_spinner, - "global_save_compressed": self.ui.general_defaults_form.general_app_group.save_type_cb, - "global_autosave": self.ui.general_defaults_form.general_app_group.autosave_cb, - "global_autosave_timeout": self.ui.general_defaults_form.general_app_group.autosave_entry, - - "global_tpdf_tmargin": self.ui.general_defaults_form.general_app_group.tmargin_entry, - "global_tpdf_bmargin": self.ui.general_defaults_form.general_app_group.bmargin_entry, - "global_tpdf_lmargin": self.ui.general_defaults_form.general_app_group.lmargin_entry, - "global_tpdf_rmargin": self.ui.general_defaults_form.general_app_group.rmargin_entry, - # Gerber General "gerber_plot": self.ui.gerber_defaults_form.gerber_gen_group.plot_cb, "gerber_solid": self.ui.gerber_defaults_form.gerber_gen_group.solid_cb, @@ -844,11 +816,11 @@ class PreferencesUIManager: self.ignore_tab_close_event = True try: - self.ui.general_defaults_form.general_app_group.units_radio.activated_custom.disconnect() + self.get_form_field("units").activated_custom.disconnect() except (TypeError, AttributeError): pass self.defaults_write_form(source_dict=self.defaults.current_defaults) - self.ui.general_defaults_form.general_app_group.units_radio.activated_custom.connect( + self.get_form_field("units").activated_custom.connect( lambda: self.ui.app.on_toggle_units(no_pref=False)) self.defaults.update(self.defaults.current_defaults) diff --git a/flatcamGUI/preferences/general/GeneralAppPrefGroupUI.py b/flatcamGUI/preferences/general/GeneralAppPrefGroupUI.py index 4410f43d..9edb2bd5 100644 --- a/flatcamGUI/preferences/general/GeneralAppPrefGroupUI.py +++ b/flatcamGUI/preferences/general/GeneralAppPrefGroupUI.py @@ -1,382 +1,253 @@ import sys -from PyQt5 import QtWidgets from PyQt5.QtCore import QSettings -from flatcamGUI.GUIElements import RadioSet, FCSpinner, FCCheckBox, FCComboBox, FCButton, OptionalInputSection, \ - FCDoubleSpinner -from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI +from flatcamGUI.GUIElements import OptionalInputSection +from flatcamGUI.preferences.OptionUI import * +from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI2 import gettext import FlatCAMTranslation as fcTranslate import builtins - fcTranslate.apply_language('strings') if '_' not in builtins.__dict__: _ = gettext.gettext -settings = QSettings("Open Source", "FlatCAM") -if settings.contains("machinist"): - machinist_setting = settings.value('machinist', type=int) -else: - machinist_setting = 0 - -class GeneralAppPrefGroupUI(OptionsGroupUI): +class GeneralAppPrefGroupUI(OptionsGroupUI2): def __init__(self, decimals=4, **kwargs): - super().__init__(**kwargs) - - self.setTitle(_("App Preferences")) self.decimals = decimals + super().__init__(**kwargs) + self.setTitle(str(_("App Preferences"))) - # Create a form layout for the Application general settings - grid0 = QtWidgets.QGridLayout() - self.layout.addLayout(grid0) - grid0.setColumnStretch(0, 0) - grid0.setColumnStretch(1, 1) - - # Units for FlatCAM - self.unitslabel = QtWidgets.QLabel('%s:' % _('Units')) - self.unitslabel.setToolTip(_("The default value for FlatCAM units.\n" - "Whatever is selected here is set every time\n" - "FlatCAM is started.")) - self.units_radio = RadioSet([{'label': _('MM'), 'value': 'MM'}, - {'label': _('IN'), 'value': 'IN'}]) - - grid0.addWidget(self.unitslabel, 0, 0) - grid0.addWidget(self.units_radio, 0, 1) - - # Precision Metric - self.precision_metric_label = QtWidgets.QLabel('%s:' % _('Precision MM')) - self.precision_metric_label.setToolTip( - _("The number of decimals used throughout the application\n" - "when the set units are in METRIC system.\n" - "Any change here require an application restart.") - ) - self.precision_metric_entry = FCSpinner() - 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) - - # Precision Inch - self.precision_inch_label = QtWidgets.QLabel('%s:' % _('Precision INCH')) - self.precision_inch_label.setToolTip( - _("The number of decimals used throughout the application\n" - "when the set units are in INCH system.\n" - "Any change here require an application restart.") - ) - self.precision_inch_entry = FCSpinner() - 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) - - # Graphic Engine for FlatCAM - self.ge_label = QtWidgets.QLabel('%s:' % _('Graphic Engine')) - self.ge_label.setToolTip(_("Choose what graphic engine to use in FlatCAM.\n" - "Legacy(2D) -> reduced functionality, slow performance but enhanced compatibility.\n" - "OpenGL(3D) -> full functionality, high performance\n" - "Some graphic cards are too old and do not work in OpenGL(3D) mode, like:\n" - "Intel HD3000 or older. In this case the plot area will be black therefore\n" - "use the Legacy(2D) mode.")) - self.ge_radio = RadioSet([{'label': _('Legacy(2D)'), 'value': '2D'}, - {'label': _('OpenGL(3D)'), 'value': '3D'}], - orientation='vertical') - - grid0.addWidget(self.ge_label, 3, 0) - grid0.addWidget(self.ge_radio, 3, 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) - - # Application Level for FlatCAM - self.app_level_label = QtWidgets.QLabel('%s:' % _('APP. LEVEL')) - self.app_level_label.setToolTip(_("Choose the default level of usage for FlatCAM.\n" - "BASIC level -> reduced functionality, best for beginner's.\n" - "ADVANCED level -> full functionality.\n\n" - "The choice here will influence the parameters in\n" - "the Selected Tab for all kinds of FlatCAM objects.")) - self.app_level_radio = RadioSet([{'label': _('Basic'), 'value': 'b'}, - {'label': _('Advanced'), 'value': 'a'}]) - - grid0.addWidget(self.app_level_label, 5, 0) - grid0.addWidget(self.app_level_radio, 5, 1) - - # Portability for FlatCAM - 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, 6, 0, 1, 2) - - separator_line = QtWidgets.QFrame() - separator_line.setFrameShape(QtWidgets.QFrame.HLine) - separator_line.setFrameShadow(QtWidgets.QFrame.Sunken) - grid0.addWidget(separator_line, 7, 0, 1, 2) - - # Languages for FlatCAM - self.languagelabel = QtWidgets.QLabel('%s' % _('Languages')) - self.languagelabel.setToolTip(_("Set the language used throughout FlatCAM.")) - self.language_cb = FCComboBox() - - grid0.addWidget(self.languagelabel, 8, 0, 1, 2) - grid0.addWidget(self.language_cb, 9, 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) - - separator_line = QtWidgets.QFrame() - separator_line.setFrameShape(QtWidgets.QFrame.HLine) - separator_line.setFrameShadow(QtWidgets.QFrame.Sunken) - grid0.addWidget(separator_line, 16, 0, 1, 2) - - # ----------------------------------------------------------- - # ----------- APPLICATION STARTUP SETTINGS ------------------ - # ----------------------------------------------------------- - - self.startup_label = QtWidgets.QLabel('%s' % _('Startup Settings')) - grid0.addWidget(self.startup_label, 17, 0, 1, 2) - - # Splash Screen - self.splash_cb = FCCheckBox('%s' % _('Splash Screen')) - self.splash_cb.setToolTip( - _("Enable display of the splash screen at application startup.") - ) + if sys.platform != 'win32': + self.option_dict()["global_portable"].get_field().hide() + self.option_dict()["splash_screen"].get_field().stateChanged.connect(self.on_splash_changed) + self.option_dict()["global_shell_at_startup"].get_field().clicked.connect(self.on_toggle_shell_from_settings) + self.option_dict()["__apply_language_button"].get_field().clicked.connect(lambda: fcTranslate.on_language_apply_click(app=self.app, restart=True)) qsettings = QSettings("Open Source", "FlatCAM") if qsettings.value("splash_screen"): - self.splash_cb.set_value(True) + self.option_dict()["splash_screen"].get_field().set_value(True) else: - self.splash_cb.set_value(False) + self.option_dict()["splash_screen"].get_field().set_value(False) - grid0.addWidget(self.splash_cb, 18, 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) - - # Shell StartUp CB - self.shell_startup_cb = FCCheckBox(label='%s' % _('Show Shell')) - self.shell_startup_cb.setToolTip( - _("Check this box if you want the shell to\n" - "start automatically at startup.") - ) - - grid0.addWidget(self.shell_startup_cb, 20, 0, 1, 2) - - # Project at StartUp CB - self.project_startup_cb = FCCheckBox(label='%s' % _('Show Project')) - self.project_startup_cb.setToolTip( - _("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) - - # Version Check CB - self.version_check_cb = FCCheckBox(label='%s' % _('Version Check')) - self.version_check_cb.setToolTip( - _("Check this box if you want to check\n" - "for a new version automatically at startup.") - ) - - grid0.addWidget(self.version_check_cb, 22, 0, 1, 2) - - # Send Stats CB - self.send_stats_cb = FCCheckBox(label='%s' % _('Send Statistics')) - self.send_stats_cb.setToolTip( - _("Check this box if you agree to send anonymous\n" - "stats automatically at startup, to help improve FlatCAM.") - ) - - grid0.addWidget(self.send_stats_cb, 23, 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) - - # Worker Numbers - self.worker_number_label = QtWidgets.QLabel('%s:' % _('Workers number')) - self.worker_number_label.setToolTip( - _("The number of Qthreads made available to the App.\n" - "A bigger number may finish the jobs more quickly but\n" - "depending on your computer speed, may make the App\n" - "unresponsive. Can have a value between 2 and 16.\n" - "Default value is 2.\n" - "After change, it will be applied at next App start.") - ) - 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) - - # Geometric tolerance - tol_label = QtWidgets.QLabel('%s:' % _("Geo Tolerance")) - tol_label.setToolTip(_( - "This value can counter the effect of the Circle Steps\n" - "parameter. Default value is 0.005.\n" - "A lower value will increase the detail both in image\n" - "and in Gcode for the circles, with a higher cost in\n" - "performance. Higher value will provide more\n" - "performance at the expense of level of detail." - )) - self.tol_entry = FCDoubleSpinner() - 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) - - separator_line = QtWidgets.QFrame() - separator_line.setFrameShape(QtWidgets.QFrame.HLine) - separator_line.setFrameShadow(QtWidgets.QFrame.Sunken) - grid0.addWidget(separator_line, 27, 0, 1, 2) - - # Save Settings - self.save_label = QtWidgets.QLabel('%s' % _("Save Settings")) - grid0.addWidget(self.save_label, 28, 0, 1, 2) - - # Save compressed project CB - self.save_type_cb = FCCheckBox(_('Save Compressed Project')) - self.save_type_cb.setToolTip( - _("Whether to save a compressed or uncompressed project.\n" - "When checked it will save a compressed FlatCAM project.") - ) - - grid0.addWidget(self.save_type_cb, 29, 0, 1, 2) - - # Project LZMA Comppression Level - self.compress_spinner = FCSpinner() - self.compress_spinner.set_range(0, 9) - self.compress_label = QtWidgets.QLabel('%s:' % _('Compression')) - self.compress_label.setToolTip( - _("The level of compression used when saving\n" - "a FlatCAM project. Higher value means better compression\n" - "but require more RAM usage and more processing time.") - ) - - grid0.addWidget(self.compress_label, 30, 0) - grid0.addWidget(self.compress_spinner, 30, 1) - - self.proj_ois = OptionalInputSection(self.save_type_cb, [self.compress_label, self.compress_spinner], True) - - # Auto save CB - self.autosave_cb = FCCheckBox(_('Enable Auto Save')) - self.autosave_cb.setToolTip( - _("Check to enable the autosave feature.\n" - "When enabled, the application will try to save a project\n" - "at the set interval.") - ) - - grid0.addWidget(self.autosave_cb, 31, 0, 1, 2) - - # Auto Save Timeout Interval - self.autosave_entry = FCSpinner() - self.autosave_entry.set_range(0, 9999999) - self.autosave_label = QtWidgets.QLabel('%s:' % _('Interval')) - self.autosave_label.setToolTip( - _("Time interval for autosaving. In milliseconds.\n" - "The application will try to save periodically but only\n" - "if the project was saved manually at least once.\n" - "While active, some operations may block this feature.") - ) - - grid0.addWidget(self.autosave_label, 32, 0) - grid0.addWidget(self.autosave_entry, 32, 1) + self.version_check_field = self.option_dict()["global_version_check"].get_field() + self.send_stats_field = self.option_dict()["global_send_stats"].get_field() + self.ois_version_check = OptionalInputSection(self.version_check_field, [self.send_stats_field]) + self.save_compressed_field = self.option_dict()["global_save_compressed"].get_field() + self.compression_label = self.option_dict()["global_compression_level"].label_widget + self.compression_field = self.option_dict()["global_compression_level"].get_field() + self.proj_ois = OptionalInputSection(self.save_compressed_field, [self.compression_label, self.compression_field], True) # 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) + def build_options(self) -> [OptionUI]: + return [ + RadioSetOptionUI( + option="units", + label_text="Units", + label_tooltip="The default value for FlatCAM units.\n" + "Whatever is selected here is set every time\n" + "FlatCAM is started.", + label_bold=True, + label_red=True, + choices=[{'label': _('MM'), 'value': 'MM'}, + {'label': _('IN'), 'value': 'IN'}] + ), + SpinnerOptionUI( + option="decimals_metric", + label_text="Precision MM", + label_tooltip="The number of decimals used throughout the application\n" + "when the set units are in METRIC system.\n" + "Any change here require an application restart.", + min_value=2, max_value=16, step=1 + ), + SpinnerOptionUI( + option="decimals_metric", + label_text="Precision INCH", + label_tooltip="The number of decimals used throughout the application\n" + "when the set units are in INCH system.\n" + "Any change here require an application restart.", + min_value=2, max_value=16, step=1 + ), + RadioSetOptionUI( + option="global_graphic_engine", + label_text='Graphic Engine', + label_tooltip="Choose what graphic engine to use in FlatCAM.\n" + "Legacy(2D) -> reduced functionality, slow performance but enhanced compatibility.\n" + "OpenGL(3D) -> full functionality, high performance\n" + "Some graphic cards are too old and do not work in OpenGL(3D) mode, like:\n" + "Intel HD3000 or older. In this case the plot area will be black therefore\n" + "use the Legacy(2D) mode.", + label_bold=True, + choices=[{'label': _('Legacy(2D)'), 'value': '2D'}, + {'label': _('OpenGL(3D)'), 'value': '3D'}], + orientation="vertical" + ), + SeparatorOptionUI(), - self.pdf_param_label = QtWidgets.QLabel('%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) + RadioSetOptionUI( + option="global_app_level", + label_text="APP. LEVEL", + label_tooltip="Choose the default level of usage for FlatCAM.\n" + "BASIC level -> reduced functionality, best for beginner's.\n" + "ADVANCED level -> full functionality.\n\n" + "The choice here will influence the parameters in\n" + "the Selected Tab for all kinds of FlatCAM objects.", + label_bold=True, + label_red=True, + choices=[{'label': _('Basic'), 'value': 'b'}, + {'label': _('Advanced'), 'value': 'a'}] + ), + CheckboxOptionUI( + option="global_portable", + label_text="Portable app", + label_tooltip="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." + ), + SeparatorOptionUI(), - # Top Margin value - self.tmargin_entry = FCDoubleSpinner() - self.tmargin_entry.set_precision(self.decimals) - self.tmargin_entry.set_range(0.0000, 9999.9999) + HeadingOptionUI(label_text="Languages", label_tooltip="Set the language used throughout FlatCAM."), + ComboboxOptionUI( + option="global_language", + label_text="Language", + label_tooltip="Set the language used throughout FlatCAM.", + choices=[] # FIXME: choices should be added here instead of in App + ), + FullWidthButtonOptionUI( + option="__apply_language_button", + label_text="Apply Language", + label_tooltip="Set the language used throughout FlatCAM.\n" + "The app will restart after click." + ), + SeparatorOptionUI(), - self.tmargin_label = QtWidgets.QLabel('%s:' % _("Top Margin")) - self.tmargin_label.setToolTip( - _("Distance between text body and the top of the PDF file.") - ) + HeadingOptionUI("Startup Settings", label_tooltip=None), + CheckboxOptionUI( + option="splash_screen", + label_text="Splash Screen", + label_tooltip="Enable display of the splash screen at application startup." + ), + CheckboxOptionUI( + option="global_systray_icon", + label_text="Sys Tray Icon", + label_tooltip="Enable display of FlatCAM icon in Sys Tray." + ), + CheckboxOptionUI( + option="global_shell_at_startup", + label_text="Show Shell", + label_tooltip="Check this box if you want the shell to\n" + "start automatically at startup." + ), + CheckboxOptionUI( + option="global_project_at_startup", + label_text="Show Project", + label_tooltip="Check this box if you want the project/selected/tool tab area to\n" + "to be shown automatically at startup." + ), + CheckboxOptionUI( + option="global_version_check", + label_text="Version Check", + label_tooltip="Check this box if you want to check\n" + "for a new version automatically at startup." + ), + CheckboxOptionUI( + option="global_send_stats", + label_text="Send Statistics", + label_tooltip="Check this box if you agree to send anonymous\n" + "stats automatically at startup, to help improve FlatCAM." + ), + SeparatorOptionUI(), - grid0.addWidget(self.tmargin_label, 35, 0) - grid0.addWidget(self.tmargin_entry, 35, 1) + SpinnerOptionUI( + option="global_worker_number", + label_text="Workers number", + label_tooltip="The number of Qthreads made available to the App.\n" + "A bigger number may finish the jobs more quickly but\n" + "depending on your computer speed, may make the App\n" + "unresponsive. Can have a value between 2 and 16.\n" + "Default value is 2.\n" + "After change, it will be applied at next App start.", + min_value=2, max_value=16, step=1 + ), + DoubleSpinnerOptionUI( + option="global_tolerance", + label_text="Geo Tolerance", + label_tooltip="This value can counter the effect of the Circle Steps\n" + "parameter. Default value is 0.005.\n" + "A lower value will increase the detail both in image\n" + "and in Gcode for the circles, with a higher cost in\n" + "performance. Higher value will provide more\n" + "performance at the expense of level of detail.", + min_value=0.0, max_value=100.0, step=0.001, decimals=6 + ), + SeparatorOptionUI(), - # Bottom Margin value - self.bmargin_entry = FCDoubleSpinner() - self.bmargin_entry.set_precision(self.decimals) - self.bmargin_entry.set_range(0.0000, 9999.9999) + HeadingOptionUI(label_text="Save Settings"), + CheckboxOptionUI( + option="global_save_compressed", + label_text="Save Compressed Project", + label_tooltip="Whether to save a compressed or uncompressed project.\n" + "When checked it will save a compressed FlatCAM project." + ), + SpinnerOptionUI( + option="global_compression_level", + label_text="Compression", + label_tooltip="The level of compression used when saving\n" + "a FlatCAM project. Higher value means better compression\n" + "but require more RAM usage and more processing time.", + min_value=0, max_value=9, step=1 + ), + CheckboxOptionUI( + option="global_autosave", + label_text="Enable Auto Save", + label_tooltip="Check to enable the autosave feature.\n" + "When enabled, the application will try to save a project\n" + "at the set interval." + ), + SpinnerOptionUI( + option="global_autosave_timeout", + label_text="Interval", + label_tooltip="Time interval for autosaving. In milliseconds.\n" + "The application will try to save periodically but only\n" + "if the project was saved manually at least once.\n" + "While active, some operations may block this feature.", + min_value=500, max_value=9999999, step=60000 + ), + SeparatorOptionUI(), - self.bmargin_label = QtWidgets.QLabel('%s:' % _("Bottom Margin")) - self.bmargin_label.setToolTip( - _("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) - - # Left Margin value - self.lmargin_entry = FCDoubleSpinner() - self.lmargin_entry.set_precision(self.decimals) - self.lmargin_entry.set_range(0.0000, 9999.9999) - - self.lmargin_label = QtWidgets.QLabel('%s:' % _("Left Margin")) - self.lmargin_label.setToolTip( - _("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) - - # Right Margin value - self.rmargin_entry = FCDoubleSpinner() - self.rmargin_entry.set_precision(self.decimals) - self.rmargin_entry.set_range(0.0000, 9999.9999) - - self.rmargin_label = QtWidgets.QLabel('%s:' % _("Right Margin")) - self.rmargin_label.setToolTip( - _("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) - - self.layout.addStretch() - - if sys.platform != 'win32': - self.portability_cb.hide() - - # splash screen button signal - self.splash_cb.stateChanged.connect(self.on_splash_changed) - - # Monitor the checkbox from the Application Defaults Tab and show the TCL shell or not depending on it's value - self.shell_startup_cb.clicked.connect(self.on_toggle_shell_from_settings) - - self.language_apply_btn.clicked.connect(lambda: fcTranslate.on_language_apply_click(app=self.app, restart=True)) + HeadingOptionUI( + label_text="Text to PDF parameters", + label_tooltip="Used when saving text in Code Editor or in FlatCAM Document objects." + ), + DoubleSpinnerOptionUI( + option="global_tpdf_tmargin", + label_text="Top Margin", + label_tooltip="Distance between text body and the top of the PDF file.", + min_value=0.0, max_value=9999.9999, step=1, decimals=2 + ), + DoubleSpinnerOptionUI( + option="global_tpdf_bmargin", + label_text="Bottom Margin", + label_tooltip="Distance between text body and the bottom of the PDF file.", + min_value=0.0, max_value=9999.9999, step=1, decimals=2 + ), + DoubleSpinnerOptionUI( + option="global_tpdf_lmargin", + label_text="Left Margin", + label_tooltip="Distance between text body and the left of the PDF file.", + min_value=0.0, max_value=9999.9999, step=1, decimals=2 + ), + DoubleSpinnerOptionUI( + option="global_tpdf_rmargin", + label_text="Right Margin", + label_tooltip="Distance between text body and the right of the PDF file.", + min_value=0.0, max_value=9999.9999, step=1, decimals=2 + ) + ] def on_toggle_shell_from_settings(self, state): """ @@ -399,4 +270,4 @@ class GeneralAppPrefGroupUI(OptionsGroupUI): qsettings.setValue('splash_screen', 1) if state else qsettings.setValue('splash_screen', 0) # This will write the setting to the platform specific storage. - del qsettings + del qsettings \ No newline at end of file diff --git a/flatcamGUI/preferences/general/GeneralGUIPrefGroupUI.py b/flatcamGUI/preferences/general/GeneralGUIPrefGroupUI.py index 8b77cce6..d1ce729a 100644 --- a/flatcamGUI/preferences/general/GeneralGUIPrefGroupUI.py +++ b/flatcamGUI/preferences/general/GeneralGUIPrefGroupUI.py @@ -17,8 +17,8 @@ from flatcamGUI.preferences.OptionUI import OptionUI, CheckboxOptionUI, RadioSet class GeneralGUIPrefGroupUI(OptionsGroupUI2): def __init__(self, decimals=4, **kwargs): - super().__init__(**kwargs) self.decimals = decimals + super().__init__(**kwargs) self.setTitle(str(_("GUI Preferences"))) self.layout_field = self.option_dict()["layout"].get_field() From c2c437589348f230ac4e63cbad6466d24b135ae9 Mon Sep 17 00:00:00 2001 From: David Robertson Date: Sun, 3 May 2020 15:57:12 +0100 Subject: [PATCH 12/41] Move the code for setting layout out from GeneralGUIPrefGroupUI into FlatCAMGUI --- FlatCAMApp.py | 13 +- flatcamGUI/FlatCAMGUI.py | 147 +++++++++++++++++ .../general/GeneralAppPrefGroupUI.py | 2 +- .../general/GeneralGUIPrefGroupUI.py | 148 +----------------- .../general/GeneralPreferencesUI.py | 9 +- 5 files changed, 159 insertions(+), 160 deletions(-) diff --git a/FlatCAMApp.py b/FlatCAMApp.py index 93043ed7..9c21e2a0 100644 --- a/FlatCAMApp.py +++ b/FlatCAMApp.py @@ -560,13 +560,11 @@ class App(QtCore.QObject): if self.defaults["first_run"] is True: - # ONLY AT FIRST STARTUP INIT THE GUI LAYOUT TO 'COMPACT' + # ONLY AT FIRST STARTUP INIT THE GUI LAYOUT TO 'minimal' initial_lay = 'minimal' - self.ui.general_defaults_form.general_gui_group.on_layout(lay=initial_lay) - - # Set the combobox in Preferences to the current layout - idx = self.ui.general_defaults_form.general_gui_group.layout_field.findText(initial_lay) - self.ui.general_defaults_form.general_gui_group.layout_field.setCurrentIndex(idx) + layout_field = self.preferencesUiManager.get_form_field("layout") + layout_field.setCurrentIndex(layout_field.findText(initial_lay)) + self.ui.set_layout(initial_lay) # after the first run, this object should be False self.defaults["first_run"] = False @@ -10206,7 +10204,8 @@ class App(QtCore.QObject): self.log.debug("version_check()") - if self.ui.general_defaults_form.general_app_group.send_stats_cb.get_value() is True: + + if self.defaults["global_send_stats"] is True: full_url = "%s?s=%s&v=%s&os=%s&%s" % ( App.version_url, str(self.defaults['global_serial']), diff --git a/flatcamGUI/FlatCAMGUI.py b/flatcamGUI/FlatCAMGUI.py index b029b324..b4b0363f 100644 --- a/flatcamGUI/FlatCAMGUI.py +++ b/flatcamGUI/FlatCAMGUI.py @@ -4252,6 +4252,153 @@ class FlatCAMGUI(QtWidgets.QMainWindow): self.final_save.emit() event.ignore() + def set_layout(self, layout: str): + """ + Set the toolbars layout (location) + + :param index: + :param lay: Type of layout to be set on the toolbard + :return: None + """ + + self.app.defaults.report_usage("on_layout()") + + lay_settings = QSettings("Open Source", "FlatCAM") + lay_settings.setValue('layout', layout) + # This will write the setting to the platform specific storage. + del lay_settings + + # first remove the toolbars: + try: + self.removeToolBar(self.app.ui.toolbarfile) + self.removeToolBar(self.app.ui.toolbargeo) + self.removeToolBar(self.app.ui.toolbarview) + self.removeToolBar(self.app.ui.toolbarshell) + self.removeToolBar(self.app.ui.toolbartools) + self.removeToolBar(self.app.ui.exc_edit_toolbar) + self.removeToolBar(self.app.ui.geo_edit_toolbar) + self.removeToolBar(self.app.ui.grb_edit_toolbar) + self.removeToolBar(self.app.ui.snap_toolbar) + self.removeToolBar(self.app.ui.toolbarshell) + except Exception: + pass + + if layout == 'compact': + # ## TOOLBAR INSTALLATION # ## + self.toolbarfile = QtWidgets.QToolBar('File Toolbar') + self.toolbarfile.setObjectName('File_TB') + self.addToolBar(Qt.LeftToolBarArea, self.app.ui.toolbarfile) + + self.toolbargeo = QtWidgets.QToolBar('Edit Toolbar') + self.toolbargeo.setObjectName('Edit_TB') + self.addToolBar(Qt.LeftToolBarArea, self.app.ui.toolbargeo) + + self.toolbarshell = QtWidgets.QToolBar('Shell Toolbar') + self.toolbarshell.setObjectName('Shell_TB') + self.addToolBar(Qt.LeftToolBarArea, self.app.ui.toolbarshell) + + self.toolbartools = QtWidgets.QToolBar('Tools Toolbar') + self.toolbartools.setObjectName('Tools_TB') + self.addToolBar(Qt.LeftToolBarArea, self.app.ui.toolbartools) + + self.geo_edit_toolbar = QtWidgets.QToolBar('Geometry Editor Toolbar') + # self.geo_edit_toolbar.setVisible(False) + self.geo_edit_toolbar.setObjectName('GeoEditor_TB') + self.addToolBar(Qt.RightToolBarArea, self.app.ui.geo_edit_toolbar) + + self.toolbarview = QtWidgets.QToolBar('View Toolbar') + self.toolbarview.setObjectName('View_TB') + self.addToolBar(Qt.RightToolBarArea, self.app.ui.toolbarview) + + self.addToolBarBreak(area=Qt.RightToolBarArea) + + self.grb_edit_toolbar = QtWidgets.QToolBar('Gerber Editor Toolbar') + # self.grb_edit_toolbar.setVisible(False) + self.grb_edit_toolbar.setObjectName('GrbEditor_TB') + self.addToolBar(Qt.RightToolBarArea, self.app.ui.grb_edit_toolbar) + + self.exc_edit_toolbar = QtWidgets.QToolBar('Excellon Editor Toolbar') + self.exc_edit_toolbar.setObjectName('ExcEditor_TB') + self.addToolBar(Qt.RightToolBarArea, self.app.ui.exc_edit_toolbar) + + self.snap_toolbar = QtWidgets.QToolBar('Grid Toolbar') + self.snap_toolbar.setObjectName('Snap_TB') + self.snap_toolbar.setMaximumHeight(30) + self.splitter_left.addWidget(self.app.ui.snap_toolbar) + + self.corner_snap_btn.setVisible(True) + self.snap_magnet.setVisible(True) + else: + # ## TOOLBAR INSTALLATION # ## + self.toolbarfile = QtWidgets.QToolBar('File Toolbar') + self.toolbarfile.setObjectName('File_TB') + self.addToolBar(self.app.ui.toolbarfile) + + self.toolbargeo = QtWidgets.QToolBar('Edit Toolbar') + self.toolbargeo.setObjectName('Edit_TB') + self.addToolBar(self.app.ui.toolbargeo) + + self.toolbarview = QtWidgets.QToolBar('View Toolbar') + self.toolbarview.setObjectName('View_TB') + self.addToolBar(self.app.ui.toolbarview) + + self.toolbarshell = QtWidgets.QToolBar('Shell Toolbar') + self.toolbarshell.setObjectName('Shell_TB') + self.addToolBar(self.app.ui.toolbarshell) + + self.toolbartools = QtWidgets.QToolBar('Tools Toolbar') + self.toolbartools.setObjectName('Tools_TB') + self.addToolBar(self.app.ui.toolbartools) + + self.exc_edit_toolbar = QtWidgets.QToolBar('Excellon Editor Toolbar') + # self.exc_edit_toolbar.setVisible(False) + self.exc_edit_toolbar.setObjectName('ExcEditor_TB') + self.addToolBar(self.app.ui.exc_edit_toolbar) + + self.addToolBarBreak() + + self.geo_edit_toolbar = QtWidgets.QToolBar('Geometry Editor Toolbar') + # self.geo_edit_toolbar.setVisible(False) + self.geo_edit_toolbar.setObjectName('GeoEditor_TB') + self.addToolBar(self.app.ui.geo_edit_toolbar) + + self.grb_edit_toolbar = QtWidgets.QToolBar('Gerber Editor Toolbar') + # self.grb_edit_toolbar.setVisible(False) + self.grb_edit_toolbar.setObjectName('GrbEditor_TB') + self.addToolBar(self.app.ui.grb_edit_toolbar) + + self.snap_toolbar = QtWidgets.QToolBar('Grid Toolbar') + self.snap_toolbar.setObjectName('Snap_TB') + # self.snap_toolbar.setMaximumHeight(30) + self.addToolBar(self.app.ui.snap_toolbar) + + self.corner_snap_btn.setVisible(False) + self.snap_magnet.setVisible(False) + + if layout == 'minimal': + self.toolbarview.setVisible(False) + self.toolbarshell.setVisible(False) + self.snap_toolbar.setVisible(False) + self.geo_edit_toolbar.setVisible(False) + self.grb_edit_toolbar.setVisible(False) + self.exc_edit_toolbar.setVisible(False) + self.lock_toolbar(lock=True) + + # add all the actions to the toolbars + self.populate_toolbars() + + # reconnect all the signals to the toolbar actions + self.app.connect_toolbar_signals() + + self.grid_snap_btn.setChecked(True) + self.on_grid_snap_triggered(state=True) + + self.grid_gap_x_entry.setText(str(self.app.defaults["global_gridx"])) + self.grid_gap_y_entry.setText(str(self.app.defaults["global_gridy"])) + self.snap_max_dist_entry.setText(str(self.app.defaults["global_snap_max"])) + self.grid_gap_link_cb.setChecked(True) + + class FlatCAMActivityView(QtWidgets.QWidget): """ diff --git a/flatcamGUI/preferences/general/GeneralAppPrefGroupUI.py b/flatcamGUI/preferences/general/GeneralAppPrefGroupUI.py index 9edb2bd5..68bcd5d7 100644 --- a/flatcamGUI/preferences/general/GeneralAppPrefGroupUI.py +++ b/flatcamGUI/preferences/general/GeneralAppPrefGroupUI.py @@ -115,7 +115,7 @@ class GeneralAppPrefGroupUI(OptionsGroupUI2): option="global_language", label_text="Language", label_tooltip="Set the language used throughout FlatCAM.", - choices=[] # FIXME: choices should be added here instead of in App + choices=[] # FIXME: choices should be added here instead of in App ), FullWidthButtonOptionUI( option="__apply_language_button", diff --git a/flatcamGUI/preferences/general/GeneralGUIPrefGroupUI.py b/flatcamGUI/preferences/general/GeneralGUIPrefGroupUI.py index d1ce729a..c16cec4a 100644 --- a/flatcamGUI/preferences/general/GeneralGUIPrefGroupUI.py +++ b/flatcamGUI/preferences/general/GeneralGUIPrefGroupUI.py @@ -205,8 +205,6 @@ class GeneralGUIPrefGroupUI(OptionsGroupUI2): line = self._modify_color_alpha(color=self.alt_sel_line_field.get_value(), alpha=alpha) self.alt_sel_line_field.set_value(line) - - def _modify_color_alpha(self, color: str, alpha: int): color_without_alpha = color[:7] if alpha > 255: @@ -219,7 +217,6 @@ class GeneralGUIPrefGroupUI(OptionsGroupUI2): hexalpha = "0" + hexalpha return color_without_alpha + hexalpha - def on_theme_change(self): # FIXME: this should be moved out to a view model val = self.theme_field.get_value() @@ -232,156 +229,13 @@ class GeneralGUIPrefGroupUI(OptionsGroupUI2): self.app.on_app_restart() def on_layout(self, index=None, lay=None): - # FIXME: this should be moved out somewhere else - """ - Set the toolbars layout (location) - - :param index: - :param lay: Type of layout to be set on the toolbard - :return: None - """ - - self.app.defaults.report_usage("on_layout()") if lay: current_layout = lay else: current_layout = self.layout_field.get_value() + self.app.ui.set_layout(current_layout) - lay_settings = QSettings("Open Source", "FlatCAM") - lay_settings.setValue('layout', current_layout) - # This will write the setting to the platform specific storage. - del lay_settings - - # first remove the toolbars: - try: - self.app.ui.removeToolBar(self.app.ui.toolbarfile) - self.app.ui.removeToolBar(self.app.ui.toolbargeo) - self.app.ui.removeToolBar(self.app.ui.toolbarview) - self.app.ui.removeToolBar(self.app.ui.toolbarshell) - self.app.ui.removeToolBar(self.app.ui.toolbartools) - self.app.ui.removeToolBar(self.app.ui.exc_edit_toolbar) - self.app.ui.removeToolBar(self.app.ui.geo_edit_toolbar) - self.app.ui.removeToolBar(self.app.ui.grb_edit_toolbar) - self.app.ui.removeToolBar(self.app.ui.snap_toolbar) - self.app.ui.removeToolBar(self.app.ui.toolbarshell) - except Exception: - pass - - if current_layout == 'compact': - # ## TOOLBAR INSTALLATION # ## - self.app.ui.toolbarfile = QtWidgets.QToolBar('File Toolbar') - self.app.ui.toolbarfile.setObjectName('File_TB') - self.app.ui.addToolBar(Qt.LeftToolBarArea, self.app.ui.toolbarfile) - - self.app.ui.toolbargeo = QtWidgets.QToolBar('Edit Toolbar') - self.app.ui.toolbargeo.setObjectName('Edit_TB') - self.app.ui.addToolBar(Qt.LeftToolBarArea, self.app.ui.toolbargeo) - - self.app.ui.toolbarshell = QtWidgets.QToolBar('Shell Toolbar') - self.app.ui.toolbarshell.setObjectName('Shell_TB') - self.app.ui.addToolBar(Qt.LeftToolBarArea, self.app.ui.toolbarshell) - - self.app.ui.toolbartools = QtWidgets.QToolBar('Tools Toolbar') - self.app.ui.toolbartools.setObjectName('Tools_TB') - self.app.ui.addToolBar(Qt.LeftToolBarArea, self.app.ui.toolbartools) - - self.app.ui.geo_edit_toolbar = QtWidgets.QToolBar('Geometry Editor Toolbar') - # self.app.ui.geo_edit_toolbar.setVisible(False) - self.app.ui.geo_edit_toolbar.setObjectName('GeoEditor_TB') - self.app.ui.addToolBar(Qt.RightToolBarArea, self.app.ui.geo_edit_toolbar) - - self.app.ui.toolbarview = QtWidgets.QToolBar('View Toolbar') - self.app.ui.toolbarview.setObjectName('View_TB') - self.app.ui.addToolBar(Qt.RightToolBarArea, self.app.ui.toolbarview) - - self.app.ui.addToolBarBreak(area=Qt.RightToolBarArea) - - self.app.ui.grb_edit_toolbar = QtWidgets.QToolBar('Gerber Editor Toolbar') - # self.app.ui.grb_edit_toolbar.setVisible(False) - self.app.ui.grb_edit_toolbar.setObjectName('GrbEditor_TB') - self.app.ui.addToolBar(Qt.RightToolBarArea, self.app.ui.grb_edit_toolbar) - - self.app.ui.exc_edit_toolbar = QtWidgets.QToolBar('Excellon Editor Toolbar') - self.app.ui.exc_edit_toolbar.setObjectName('ExcEditor_TB') - self.app.ui.addToolBar(Qt.RightToolBarArea, self.app.ui.exc_edit_toolbar) - - self.app.ui.snap_toolbar = QtWidgets.QToolBar('Grid Toolbar') - self.app.ui.snap_toolbar.setObjectName('Snap_TB') - self.app.ui.snap_toolbar.setMaximumHeight(30) - self.app.ui.splitter_left.addWidget(self.app.ui.snap_toolbar) - - self.app.ui.corner_snap_btn.setVisible(True) - self.app.ui.snap_magnet.setVisible(True) - else: - # ## TOOLBAR INSTALLATION # ## - self.app.ui.toolbarfile = QtWidgets.QToolBar('File Toolbar') - self.app.ui.toolbarfile.setObjectName('File_TB') - self.app.ui.addToolBar(self.app.ui.toolbarfile) - - self.app.ui.toolbargeo = QtWidgets.QToolBar('Edit Toolbar') - self.app.ui.toolbargeo.setObjectName('Edit_TB') - self.app.ui.addToolBar(self.app.ui.toolbargeo) - - self.app.ui.toolbarview = QtWidgets.QToolBar('View Toolbar') - self.app.ui.toolbarview.setObjectName('View_TB') - self.app.ui.addToolBar(self.app.ui.toolbarview) - - self.app.ui.toolbarshell = QtWidgets.QToolBar('Shell Toolbar') - self.app.ui.toolbarshell.setObjectName('Shell_TB') - self.app.ui.addToolBar(self.app.ui.toolbarshell) - - self.app.ui.toolbartools = QtWidgets.QToolBar('Tools Toolbar') - self.app.ui.toolbartools.setObjectName('Tools_TB') - self.app.ui.addToolBar(self.app.ui.toolbartools) - - self.app.ui.exc_edit_toolbar = QtWidgets.QToolBar('Excellon Editor Toolbar') - # self.app.ui.exc_edit_toolbar.setVisible(False) - self.app.ui.exc_edit_toolbar.setObjectName('ExcEditor_TB') - self.app.ui.addToolBar(self.app.ui.exc_edit_toolbar) - - self.app.ui.addToolBarBreak() - - self.app.ui.geo_edit_toolbar = QtWidgets.QToolBar('Geometry Editor Toolbar') - # self.app.ui.geo_edit_toolbar.setVisible(False) - self.app.ui.geo_edit_toolbar.setObjectName('GeoEditor_TB') - self.app.ui.addToolBar(self.app.ui.geo_edit_toolbar) - - self.app.ui.grb_edit_toolbar = QtWidgets.QToolBar('Gerber Editor Toolbar') - # self.app.ui.grb_edit_toolbar.setVisible(False) - self.app.ui.grb_edit_toolbar.setObjectName('GrbEditor_TB') - self.app.ui.addToolBar(self.app.ui.grb_edit_toolbar) - - self.app.ui.snap_toolbar = QtWidgets.QToolBar('Grid Toolbar') - self.app.ui.snap_toolbar.setObjectName('Snap_TB') - # self.app.ui.snap_toolbar.setMaximumHeight(30) - self.app.ui.addToolBar(self.app.ui.snap_toolbar) - - self.app.ui.corner_snap_btn.setVisible(False) - self.app.ui.snap_magnet.setVisible(False) - - if current_layout == 'minimal': - self.app.ui.toolbarview.setVisible(False) - self.app.ui.toolbarshell.setVisible(False) - self.app.ui.snap_toolbar.setVisible(False) - self.app.ui.geo_edit_toolbar.setVisible(False) - self.app.ui.grb_edit_toolbar.setVisible(False) - self.app.ui.exc_edit_toolbar.setVisible(False) - self.app.ui.lock_toolbar(lock=True) - - # add all the actions to the toolbars - self.app.ui.populate_toolbars() - - # reconnect all the signals to the toolbar actions - self.app.connect_toolbar_signals() - - self.app.ui.grid_snap_btn.setChecked(True) - self.app.ui.on_grid_snap_triggered(state=True) - - self.app.ui.grid_gap_x_entry.setText(str(self.app.defaults["global_gridx"])) - self.app.ui.grid_gap_y_entry.setText(str(self.app.defaults["global_gridy"])) - self.app.ui.snap_max_dist_entry.setText(str(self.app.defaults["global_snap_max"])) - self.app.ui.grid_gap_link_cb.setChecked(True) @staticmethod def handle_style(style): diff --git a/flatcamGUI/preferences/general/GeneralPreferencesUI.py b/flatcamGUI/preferences/general/GeneralPreferencesUI.py index 6b3bea67..34151506 100644 --- a/flatcamGUI/preferences/general/GeneralPreferencesUI.py +++ b/flatcamGUI/preferences/general/GeneralPreferencesUI.py @@ -8,15 +8,14 @@ from flatcamGUI.preferences.general.GeneralGUIPrefGroupUI import GeneralGUIPrefG class GeneralPreferencesUI(PreferencesSectionUI): def __init__(self, decimals, **kwargs): - self.general_app_group = GeneralAppPrefGroupUI(decimals=decimals) - self.general_gui_group = GeneralGUIPrefGroupUI(decimals=decimals) - self.general_app_settings_group = GeneralAppSettingsGroupUI(decimals=decimals) + self.decimals = decimals + self.general_gui_group = GeneralGUIPrefGroupUI(decimals=self.decimals) super().__init__(**kwargs) def build_groups(self) -> [OptionsGroupUI]: return [ - self.general_app_group, + GeneralAppPrefGroupUI(decimals=self.decimals), self.general_gui_group, - self.general_app_settings_group + GeneralAppSettingsGroupUI(decimals=self.decimals) ] From 100f3e5394de5950c3016f951e2f29404e2030d4 Mon Sep 17 00:00:00 2001 From: David Robertson Date: Sun, 3 May 2020 16:01:06 +0100 Subject: [PATCH 13/41] clean up --- flatcamGUI/preferences/general/GeneralAppPrefGroupUI.py | 2 -- flatcamGUI/preferences/general/GeneralAppSettingsGroupUI.py | 2 +- flatcamGUI/preferences/general/GeneralGUIPrefGroupUI.py | 4 +--- flatcamGUI/preferences/general/GeneralPreferencesUI.py | 3 +-- 4 files changed, 3 insertions(+), 8 deletions(-) diff --git a/flatcamGUI/preferences/general/GeneralAppPrefGroupUI.py b/flatcamGUI/preferences/general/GeneralAppPrefGroupUI.py index 68bcd5d7..96ac84b7 100644 --- a/flatcamGUI/preferences/general/GeneralAppPrefGroupUI.py +++ b/flatcamGUI/preferences/general/GeneralAppPrefGroupUI.py @@ -1,7 +1,5 @@ import sys - from PyQt5.QtCore import QSettings - from flatcamGUI.GUIElements import OptionalInputSection from flatcamGUI.preferences.OptionUI import * from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI2 diff --git a/flatcamGUI/preferences/general/GeneralAppSettingsGroupUI.py b/flatcamGUI/preferences/general/GeneralAppSettingsGroupUI.py index 5c37c527..1978bd6d 100644 --- a/flatcamGUI/preferences/general/GeneralAppSettingsGroupUI.py +++ b/flatcamGUI/preferences/general/GeneralAppSettingsGroupUI.py @@ -1,4 +1,4 @@ -from PyQt5 import QtCore, QtGui +from PyQt5 import QtCore from PyQt5.QtCore import QSettings from flatcamGUI.GUIElements import OptionalInputSection from flatcamGUI.preferences import settings diff --git a/flatcamGUI/preferences/general/GeneralGUIPrefGroupUI.py b/flatcamGUI/preferences/general/GeneralGUIPrefGroupUI.py index c16cec4a..6ee4a6fa 100644 --- a/flatcamGUI/preferences/general/GeneralGUIPrefGroupUI.py +++ b/flatcamGUI/preferences/general/GeneralGUIPrefGroupUI.py @@ -1,5 +1,5 @@ from PyQt5 import QtWidgets, QtCore -from PyQt5.QtCore import QSettings, Qt +from PyQt5.QtCore import QSettings from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI2 import gettext @@ -235,8 +235,6 @@ class GeneralGUIPrefGroupUI(OptionsGroupUI2): current_layout = self.layout_field.get_value() self.app.ui.set_layout(current_layout) - - @staticmethod def handle_style(style): # FIXME: this should be moved out to a view model diff --git a/flatcamGUI/preferences/general/GeneralPreferencesUI.py b/flatcamGUI/preferences/general/GeneralPreferencesUI.py index 34151506..c582ccd6 100644 --- a/flatcamGUI/preferences/general/GeneralPreferencesUI.py +++ b/flatcamGUI/preferences/general/GeneralPreferencesUI.py @@ -9,13 +9,12 @@ class GeneralPreferencesUI(PreferencesSectionUI): def __init__(self, decimals, **kwargs): self.decimals = decimals - self.general_gui_group = GeneralGUIPrefGroupUI(decimals=self.decimals) super().__init__(**kwargs) def build_groups(self) -> [OptionsGroupUI]: return [ GeneralAppPrefGroupUI(decimals=self.decimals), - self.general_gui_group, + GeneralGUIPrefGroupUI(decimals=self.decimals), GeneralAppSettingsGroupUI(decimals=self.decimals) ] From 81018b886f4c3f3e06b3af2575356960b3ba53c2 Mon Sep 17 00:00:00 2001 From: David Robertson Date: Sun, 3 May 2020 22:51:53 +0100 Subject: [PATCH 14/41] use get_form_field instead of option_dict in FlatCAMApp --- FlatCAMApp.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/FlatCAMApp.py b/FlatCAMApp.py index 9c21e2a0..ea1b5b65 100644 --- a/FlatCAMApp.py +++ b/FlatCAMApp.py @@ -4952,7 +4952,7 @@ class App(QtCore.QObject): self.plotcanvas.draw_workspace(workspace_size=self.defaults['global_workspaceT']) def on_workspace(self): - if self.preferencesUiManager.option_dict()["global_workspace"].get_field().get_value(): + if self.preferencesUiManager.get_form_field("global_workspace").get_value(): self.plotcanvas.draw_workspace(workspace_size=self.defaults['global_workspaceT']) else: self.plotcanvas.delete_workspace() @@ -4960,13 +4960,13 @@ class App(QtCore.QObject): # self.save_defaults(silent=True) def on_workspace_toggle(self): - state = False if self.preferencesUiManager.option_dict()["global_workspace"].get_field().get_value() else True + state = False if self.preferencesUiManager.get_form_field("global_workspace").get_value() else True try: - self.preferencesUiManager.option_dict()["global_workspace"].get_field().stateChanged.disconnect(self.on_workspace) + self.preferencesUiManager.get_form_field("global_workspace").stateChanged.disconnect(self.on_workspace) except TypeError: pass - self.preferencesUiManager.option_dict()["global_workspace"].get_field().set_value(state) - self.preferencesUiManager.option_dict()["global_workspace"].get_field().stateChanged.connect(self.on_workspace) + self.preferencesUiManager.get_form_field("global_workspace").set_value(state) + self.preferencesUiManager.get_form_field("global_workspace").stateChanged.connect(self.on_workspace) self.on_workspace() def on_cursor_type(self, val): From 1fc076b158231be9891dff1dd0989390306f52ec Mon Sep 17 00:00:00 2001 From: David Robertson Date: Wed, 6 May 2020 02:15:41 +0100 Subject: [PATCH 15/41] Make all of the prefs sections into subclasses of PreferencesSectionUI --- .../preferences/PreferencesUIManager.py | 11 ++- .../preferences/cncjob/CNCJobPreferencesUI.py | 25 +++--- .../excellon/ExcellonPreferencesUI.py | 50 +++-------- .../geometry/GeometryPreferencesUI.py | 45 +++------- .../preferences/gerber/GerberPreferencesUI.py | 51 +++-------- .../preferences/tools/Tools2PreferencesUI.py | 84 +++++------------- .../preferences/tools/ToolsPreferencesUI.py | 87 +++++-------------- .../utilities/UtilPreferencesUI.py | 36 +++----- 8 files changed, 115 insertions(+), 274 deletions(-) diff --git a/flatcamGUI/preferences/PreferencesUIManager.py b/flatcamGUI/preferences/PreferencesUIManager.py index eec62277..90d2cbf2 100644 --- a/flatcamGUI/preferences/PreferencesUIManager.py +++ b/flatcamGUI/preferences/PreferencesUIManager.py @@ -543,8 +543,15 @@ class PreferencesUIManager: } self.sections = [ - # FIXME! - ui.general_defaults_form + # FIXME + ui.general_defaults_form, + ui.gerber_defaults_form, + ui.excellon_defaults_form, + ui.geometry_defaults_form, + ui.cncjob_defaults_form, + ui.tools_defaults_form, + ui.tools2_defaults_form, + ui.util_defaults_form ] def get_form_fields(self) -> Dict[str, Any]: diff --git a/flatcamGUI/preferences/cncjob/CNCJobPreferencesUI.py b/flatcamGUI/preferences/cncjob/CNCJobPreferencesUI.py index cc9a7e32..5262a691 100644 --- a/flatcamGUI/preferences/cncjob/CNCJobPreferencesUI.py +++ b/flatcamGUI/preferences/cncjob/CNCJobPreferencesUI.py @@ -1,27 +1,24 @@ from PyQt5 import QtWidgets +from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI +from flatcamGUI.preferences.PreferencesSectionUI import PreferencesSectionUI from flatcamGUI.preferences.cncjob.CNCJobAdvOptPrefGroupUI import CNCJobAdvOptPrefGroupUI from flatcamGUI.preferences.cncjob.CNCJobOptPrefGroupUI import CNCJobOptPrefGroupUI from flatcamGUI.preferences.cncjob.CNCJobGenPrefGroupUI import CNCJobGenPrefGroupUI -class CNCJobPreferencesUI(QtWidgets.QWidget): +class CNCJobPreferencesUI(PreferencesSectionUI): - def __init__(self, decimals, parent=None): - QtWidgets.QWidget.__init__(self, parent=parent) - self.layout = QtWidgets.QHBoxLayout() - self.setLayout(self.layout) + def __init__(self, decimals, **kwargs): self.decimals = decimals - self.cncjob_gen_group = CNCJobGenPrefGroupUI(decimals=self.decimals) - self.cncjob_gen_group.setMinimumWidth(260) self.cncjob_opt_group = CNCJobOptPrefGroupUI(decimals=self.decimals) - self.cncjob_opt_group.setMinimumWidth(260) self.cncjob_adv_opt_group = CNCJobAdvOptPrefGroupUI(decimals=self.decimals) - self.cncjob_adv_opt_group.setMinimumWidth(260) + super().__init__(**kwargs) - self.layout.addWidget(self.cncjob_gen_group) - self.layout.addWidget(self.cncjob_opt_group) - self.layout.addWidget(self.cncjob_adv_opt_group) - - self.layout.addStretch() + def build_groups(self) -> [OptionsGroupUI]: + return [ + self.cncjob_gen_group, + self.cncjob_opt_group, + self.cncjob_adv_opt_group + ] diff --git a/flatcamGUI/preferences/excellon/ExcellonPreferencesUI.py b/flatcamGUI/preferences/excellon/ExcellonPreferencesUI.py index b3d6d165..3ba51eb1 100644 --- a/flatcamGUI/preferences/excellon/ExcellonPreferencesUI.py +++ b/flatcamGUI/preferences/excellon/ExcellonPreferencesUI.py @@ -1,53 +1,29 @@ -from PyQt5 import QtWidgets -from PyQt5.QtCore import QSettings - +from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI +from flatcamGUI.preferences.PreferencesSectionUI import PreferencesSectionUI from flatcamGUI.preferences.excellon.ExcellonEditorPrefGroupUI import ExcellonEditorPrefGroupUI from flatcamGUI.preferences.excellon.ExcellonExpPrefGroupUI import ExcellonExpPrefGroupUI from flatcamGUI.preferences.excellon.ExcellonAdvOptPrefGroupUI import ExcellonAdvOptPrefGroupUI from flatcamGUI.preferences.excellon.ExcellonOptPrefGroupUI import ExcellonOptPrefGroupUI from flatcamGUI.preferences.excellon.ExcellonGenPrefGroupUI import ExcellonGenPrefGroupUI -import gettext -import FlatCAMTranslation as fcTranslate -import builtins -fcTranslate.apply_language('strings') -if '_' not in builtins.__dict__: - _ = gettext.gettext +class ExcellonPreferencesUI(PreferencesSectionUI): -settings = QSettings("Open Source", "FlatCAM") -if settings.contains("machinist"): - machinist_setting = settings.value('machinist', type=int) -else: - machinist_setting = 0 - - -class ExcellonPreferencesUI(QtWidgets.QWidget): - - def __init__(self, decimals, parent=None): - QtWidgets.QWidget.__init__(self, parent=parent) - self.layout = QtWidgets.QHBoxLayout() - self.setLayout(self.layout) + def __init__(self, decimals, **kwargs): self.decimals = decimals - self.excellon_gen_group = ExcellonGenPrefGroupUI(decimals=self.decimals) - self.excellon_gen_group.setMinimumWidth(220) self.excellon_opt_group = ExcellonOptPrefGroupUI(decimals=self.decimals) - self.excellon_opt_group.setMinimumWidth(290) self.excellon_exp_group = ExcellonExpPrefGroupUI(decimals=self.decimals) - self.excellon_exp_group.setMinimumWidth(250) self.excellon_adv_opt_group = ExcellonAdvOptPrefGroupUI(decimals=self.decimals) - self.excellon_adv_opt_group.setMinimumWidth(250) self.excellon_editor_group = ExcellonEditorPrefGroupUI(decimals=self.decimals) - self.excellon_editor_group.setMinimumWidth(260) + super().__init__(**kwargs) - self.vlay = QtWidgets.QVBoxLayout() - self.vlay.addWidget(self.excellon_opt_group) - self.vlay.addWidget(self.excellon_exp_group) + def build_groups(self) -> [OptionsGroupUI]: + return [ + self.excellon_gen_group, + self.excellon_opt_group, + self.excellon_exp_group, + self.excellon_adv_opt_group, + self.excellon_editor_group + ] - self.layout.addWidget(self.excellon_gen_group) - self.layout.addLayout(self.vlay) - self.layout.addWidget(self.excellon_adv_opt_group) - self.layout.addWidget(self.excellon_editor_group) - - self.layout.addStretch() diff --git a/flatcamGUI/preferences/geometry/GeometryPreferencesUI.py b/flatcamGUI/preferences/geometry/GeometryPreferencesUI.py index cf906d61..621cf294 100644 --- a/flatcamGUI/preferences/geometry/GeometryPreferencesUI.py +++ b/flatcamGUI/preferences/geometry/GeometryPreferencesUI.py @@ -1,46 +1,25 @@ -from PyQt5 import QtWidgets -from PyQt5.QtCore import QSettings - +from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI +from flatcamGUI.preferences.PreferencesSectionUI import PreferencesSectionUI from flatcamGUI.preferences.geometry.GeometryEditorPrefGroupUI import GeometryEditorPrefGroupUI from flatcamGUI.preferences.geometry.GeometryAdvOptPrefGroupUI import GeometryAdvOptPrefGroupUI from flatcamGUI.preferences.geometry.GeometryOptPrefGroupUI import GeometryOptPrefGroupUI from flatcamGUI.preferences.geometry.GeometryGenPrefGroupUI import GeometryGenPrefGroupUI -import gettext -import FlatCAMTranslation as fcTranslate -import builtins -fcTranslate.apply_language('strings') -if '_' not in builtins.__dict__: - _ = gettext.gettext +class GeometryPreferencesUI(PreferencesSectionUI): -settings = QSettings("Open Source", "FlatCAM") -if settings.contains("machinist"): - machinist_setting = settings.value('machinist', type=int) -else: - machinist_setting = 0 - - -class GeometryPreferencesUI(QtWidgets.QWidget): - - def __init__(self, decimals, parent=None): - QtWidgets.QWidget.__init__(self, parent=parent) - self.layout = QtWidgets.QHBoxLayout() - self.setLayout(self.layout) + def __init__(self, decimals, **kwargs): self.decimals = decimals - self.geometry_gen_group = GeometryGenPrefGroupUI(decimals=self.decimals) - self.geometry_gen_group.setMinimumWidth(220) self.geometry_opt_group = GeometryOptPrefGroupUI(decimals=self.decimals) - self.geometry_opt_group.setMinimumWidth(300) self.geometry_adv_opt_group = GeometryAdvOptPrefGroupUI(decimals=self.decimals) - self.geometry_adv_opt_group.setMinimumWidth(270) self.geometry_editor_group = GeometryEditorPrefGroupUI(decimals=self.decimals) - self.geometry_editor_group.setMinimumWidth(250) + super().__init__(**kwargs) - self.layout.addWidget(self.geometry_gen_group) - self.layout.addWidget(self.geometry_opt_group) - self.layout.addWidget(self.geometry_adv_opt_group) - self.layout.addWidget(self.geometry_editor_group) - - self.layout.addStretch() + def build_groups(self) -> [OptionsGroupUI]: + return [ + self.geometry_gen_group, + self.geometry_opt_group, + self.geometry_adv_opt_group, + self.geometry_editor_group + ] diff --git a/flatcamGUI/preferences/gerber/GerberPreferencesUI.py b/flatcamGUI/preferences/gerber/GerberPreferencesUI.py index f9d9f8aa..f7306b21 100644 --- a/flatcamGUI/preferences/gerber/GerberPreferencesUI.py +++ b/flatcamGUI/preferences/gerber/GerberPreferencesUI.py @@ -1,53 +1,28 @@ -from PyQt5 import QtWidgets -from PyQt5.QtCore import QSettings - +from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI +from flatcamGUI.preferences.PreferencesSectionUI import PreferencesSectionUI from flatcamGUI.preferences.gerber.GerberEditorPrefGroupUI import GerberEditorPrefGroupUI from flatcamGUI.preferences.gerber.GerberExpPrefGroupUI import GerberExpPrefGroupUI from flatcamGUI.preferences.gerber.GerberAdvOptPrefGroupUI import GerberAdvOptPrefGroupUI from flatcamGUI.preferences.gerber.GerberOptPrefGroupUI import GerberOptPrefGroupUI from flatcamGUI.preferences.gerber.GerberGenPrefGroupUI import GerberGenPrefGroupUI -import gettext -import FlatCAMTranslation as fcTranslate -import builtins -fcTranslate.apply_language('strings') -if '_' not in builtins.__dict__: - _ = gettext.gettext +class GerberPreferencesUI(PreferencesSectionUI): -settings = QSettings("Open Source", "FlatCAM") -if settings.contains("machinist"): - machinist_setting = settings.value('machinist', type=int) -else: - machinist_setting = 0 - - -class GerberPreferencesUI(QtWidgets.QWidget): - - def __init__(self, decimals, parent=None): - QtWidgets.QWidget.__init__(self, parent=parent) - self.layout = QtWidgets.QHBoxLayout() - self.setLayout(self.layout) + def __init__(self, decimals, **kwargs): self.decimals = decimals - self.gerber_gen_group = GerberGenPrefGroupUI(decimals=self.decimals) - self.gerber_gen_group.setMinimumWidth(250) self.gerber_opt_group = GerberOptPrefGroupUI(decimals=self.decimals) - self.gerber_opt_group.setMinimumWidth(250) self.gerber_exp_group = GerberExpPrefGroupUI(decimals=self.decimals) - self.gerber_exp_group.setMinimumWidth(230) self.gerber_adv_opt_group = GerberAdvOptPrefGroupUI(decimals=self.decimals) - self.gerber_adv_opt_group.setMinimumWidth(200) self.gerber_editor_group = GerberEditorPrefGroupUI(decimals=self.decimals) - self.gerber_editor_group.setMinimumWidth(200) + super().__init__(**kwargs) - self.vlay = QtWidgets.QVBoxLayout() - self.vlay.addWidget(self.gerber_opt_group) - self.vlay.addWidget(self.gerber_exp_group) - - self.layout.addWidget(self.gerber_gen_group) - self.layout.addLayout(self.vlay) - self.layout.addWidget(self.gerber_adv_opt_group) - self.layout.addWidget(self.gerber_editor_group) - - self.layout.addStretch() + def build_groups(self) -> [OptionsGroupUI]: + return [ + self.gerber_gen_group, + self.gerber_opt_group, # FIXME vertical layout with opt and ext + self.gerber_exp_group, + self.gerber_adv_opt_group, + self.gerber_editor_group + ] \ No newline at end of file diff --git a/flatcamGUI/preferences/tools/Tools2PreferencesUI.py b/flatcamGUI/preferences/tools/Tools2PreferencesUI.py index 01ed4def..8cf6a95b 100644 --- a/flatcamGUI/preferences/tools/Tools2PreferencesUI.py +++ b/flatcamGUI/preferences/tools/Tools2PreferencesUI.py @@ -1,6 +1,5 @@ -from PyQt5 import QtWidgets -from PyQt5.QtCore import QSettings - +from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI +from flatcamGUI.preferences.PreferencesSectionUI import PreferencesSectionUI from flatcamGUI.preferences.tools.Tools2InvertPrefGroupUI import Tools2InvertPrefGroupUI from flatcamGUI.preferences.tools.Tools2PunchGerberPrefGroupUI import Tools2PunchGerberPrefGroupUI from flatcamGUI.preferences.tools.Tools2EDrillsPrefGroupUI import Tools2EDrillsPrefGroupUI @@ -11,79 +10,40 @@ from flatcamGUI.preferences.tools.Tools2QRCodePrefGroupUI import Tools2QRCodePre from flatcamGUI.preferences.tools.Tools2OptimalPrefGroupUI import Tools2OptimalPrefGroupUI from flatcamGUI.preferences.tools.Tools2RulesCheckPrefGroupUI import Tools2RulesCheckPrefGroupUI -import gettext -import FlatCAMTranslation as fcTranslate -import builtins -fcTranslate.apply_language('strings') -if '_' not in builtins.__dict__: - _ = gettext.gettext +class Tools2PreferencesUI(PreferencesSectionUI): -settings = QSettings("Open Source", "FlatCAM") -if settings.contains("machinist"): - machinist_setting = settings.value('machinist', type=int) -else: - machinist_setting = 0 - - -class Tools2PreferencesUI(QtWidgets.QWidget): - - def __init__(self, decimals, parent=None): - QtWidgets.QWidget.__init__(self, parent=parent) - self.layout = QtWidgets.QHBoxLayout() - self.setLayout(self.layout) + def __init__(self, decimals, **kwargs): self.decimals = decimals - self.tools2_checkrules_group = Tools2RulesCheckPrefGroupUI(decimals=self.decimals) - self.tools2_checkrules_group.setMinimumWidth(220) - self.tools2_optimal_group = Tools2OptimalPrefGroupUI(decimals=self.decimals) - self.tools2_optimal_group.setMinimumWidth(220) - self.tools2_qrcode_group = Tools2QRCodePrefGroupUI(decimals=self.decimals) - self.tools2_qrcode_group.setMinimumWidth(220) - self.tools2_cfill_group = Tools2CThievingPrefGroupUI(decimals=self.decimals) - self.tools2_cfill_group.setMinimumWidth(220) - self.tools2_fiducials_group = Tools2FiducialsPrefGroupUI(decimals=self.decimals) - self.tools2_fiducials_group.setMinimumWidth(220) - self.tools2_cal_group = Tools2CalPrefGroupUI(decimals=self.decimals) - self.tools2_cal_group.setMinimumWidth(220) - self.tools2_edrills_group = Tools2EDrillsPrefGroupUI(decimals=self.decimals) - self.tools2_edrills_group.setMinimumWidth(220) - self.tools2_punch_group = Tools2PunchGerberPrefGroupUI(decimals=self.decimals) - self.tools2_punch_group.setMinimumWidth(220) - self.tools2_invert_group = Tools2InvertPrefGroupUI(decimals=self.decimals) - self.tools2_invert_group.setMinimumWidth(220) + super().__init__(**kwargs) - self.vlay = QtWidgets.QVBoxLayout() - self.vlay.addWidget(self.tools2_checkrules_group) - self.vlay.addWidget(self.tools2_optimal_group) + def build_groups(self) -> [OptionsGroupUI]: + return [ + # fixme column 1 + self.tools2_checkrules_group, + self.tools2_optimal_group, - self.vlay1 = QtWidgets.QVBoxLayout() - self.vlay1.addWidget(self.tools2_qrcode_group) - self.vlay1.addWidget(self.tools2_fiducials_group) + # fixme column 2 + self.tools2_qrcode_group, + self.tools2_fiducials_group, - self.vlay2 = QtWidgets.QVBoxLayout() - self.vlay2.addWidget(self.tools2_cfill_group) + # fixme column 3 + self.tools2_cfill_group, - self.vlay3 = QtWidgets.QVBoxLayout() - self.vlay3.addWidget(self.tools2_cal_group) - self.vlay3.addWidget(self.tools2_edrills_group) + # fixme column 4 + self.tools2_cal_group, + self.tools2_edrills_group, - self.vlay4 = QtWidgets.QVBoxLayout() - self.vlay4.addWidget(self.tools2_punch_group) - self.vlay4.addWidget(self.tools2_invert_group) - - self.layout.addLayout(self.vlay) - self.layout.addLayout(self.vlay1) - self.layout.addLayout(self.vlay2) - self.layout.addLayout(self.vlay3) - self.layout.addLayout(self.vlay4) - - self.layout.addStretch() + # fixme column 5 + self.tools2_punch_group, + self.tools2_invert_group, + ] \ No newline at end of file diff --git a/flatcamGUI/preferences/tools/ToolsPreferencesUI.py b/flatcamGUI/preferences/tools/ToolsPreferencesUI.py index dc3061a8..2b9000cd 100644 --- a/flatcamGUI/preferences/tools/ToolsPreferencesUI.py +++ b/flatcamGUI/preferences/tools/ToolsPreferencesUI.py @@ -1,6 +1,5 @@ -from PyQt5 import QtWidgets -from PyQt5.QtCore import QSettings - +from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI +from flatcamGUI.preferences.PreferencesSectionUI import PreferencesSectionUI from flatcamGUI.preferences.tools.ToolsSubPrefGroupUI import ToolsSubPrefGroupUI from flatcamGUI.preferences.tools.ToolsSolderpastePrefGroupUI import ToolsSolderpastePrefGroupUI from flatcamGUI.preferences.tools.ToolsTransformPrefGroupUI import ToolsTransformPrefGroupUI @@ -12,83 +11,43 @@ from flatcamGUI.preferences.tools.Tools2sidedPrefGroupUI import Tools2sidedPrefG from flatcamGUI.preferences.tools.ToolsCutoutPrefGroupUI import ToolsCutoutPrefGroupUI from flatcamGUI.preferences.tools.ToolsNCCPrefGroupUI import ToolsNCCPrefGroupUI -import gettext -import FlatCAMTranslation as fcTranslate -import builtins -fcTranslate.apply_language('strings') -if '_' not in builtins.__dict__: - _ = gettext.gettext +class ToolsPreferencesUI(PreferencesSectionUI): -settings = QSettings("Open Source", "FlatCAM") -if settings.contains("machinist"): - machinist_setting = settings.value('machinist', type=int) -else: - machinist_setting = 0 - - -class ToolsPreferencesUI(QtWidgets.QWidget): - - def __init__(self, decimals, parent=None): - QtWidgets.QWidget.__init__(self, parent=parent) - self.layout = QtWidgets.QHBoxLayout() - self.setLayout(self.layout) + def __init__(self, decimals, **kwargs): self.decimals = decimals - self.tools_ncc_group = ToolsNCCPrefGroupUI(decimals=self.decimals) - self.tools_ncc_group.setMinimumWidth(220) - self.tools_paint_group = ToolsPaintPrefGroupUI(decimals=self.decimals) - self.tools_paint_group.setMinimumWidth(220) - self.tools_cutout_group = ToolsCutoutPrefGroupUI(decimals=self.decimals) - self.tools_cutout_group.setMinimumWidth(220) - self.tools_2sided_group = Tools2sidedPrefGroupUI(decimals=self.decimals) - self.tools_2sided_group.setMinimumWidth(220) - self.tools_film_group = ToolsFilmPrefGroupUI(decimals=self.decimals) - self.tools_film_group.setMinimumWidth(220) - self.tools_panelize_group = ToolsPanelizePrefGroupUI(decimals=self.decimals) - self.tools_panelize_group.setMinimumWidth(220) - self.tools_calculators_group = ToolsCalculatorsPrefGroupUI(decimals=self.decimals) - self.tools_calculators_group.setMinimumWidth(220) - self.tools_transform_group = ToolsTransformPrefGroupUI(decimals=self.decimals) - self.tools_transform_group.setMinimumWidth(200) - self.tools_solderpaste_group = ToolsSolderpastePrefGroupUI(decimals=self.decimals) - self.tools_solderpaste_group.setMinimumWidth(200) - self.tools_sub_group = ToolsSubPrefGroupUI(decimals=self.decimals) - self.tools_sub_group.setMinimumWidth(200) + super().__init__(**kwargs) - self.vlay = QtWidgets.QVBoxLayout() - self.vlay.addWidget(self.tools_ncc_group) - self.vlay.addWidget(self.tools_cutout_group) + def build_groups(self) -> [OptionsGroupUI]: + return [ + # fixme column 1 + self.tools_ncc_group, + self.tools_cutout_group, - self.vlay1 = QtWidgets.QVBoxLayout() - self.vlay1.addWidget(self.tools_paint_group) - self.vlay1.addWidget(self.tools_panelize_group) + # fixme column 2 + self.tools_paint_group, + self.tools_panelize_group, - self.vlay2 = QtWidgets.QVBoxLayout() - self.vlay2.addWidget(self.tools_transform_group) - self.vlay2.addWidget(self.tools_2sided_group) - self.vlay2.addWidget(self.tools_sub_group) + # fixme column 3 + self.tools_transform_group, + self.tools_2sided_group, + self.tools_sub_group, - self.vlay3 = QtWidgets.QVBoxLayout() - self.vlay3.addWidget(self.tools_film_group) - self.vlay3.addWidget(self.tools_calculators_group) + # fixme column 4 + self.tools_film_group, + self.tools_calculators_group, - self.vlay4 = QtWidgets.QVBoxLayout() - self.vlay4.addWidget(self.tools_solderpaste_group) + # fixme column 5 + self.tools_solderpaste_group, + ] - self.layout.addLayout(self.vlay) - self.layout.addLayout(self.vlay1) - self.layout.addLayout(self.vlay2) - self.layout.addLayout(self.vlay3) - self.layout.addLayout(self.vlay4) - - self.layout.addStretch() diff --git a/flatcamGUI/preferences/utilities/UtilPreferencesUI.py b/flatcamGUI/preferences/utilities/UtilPreferencesUI.py index ae9e2110..2ce2047a 100644 --- a/flatcamGUI/preferences/utilities/UtilPreferencesUI.py +++ b/flatcamGUI/preferences/utilities/UtilPreferencesUI.py @@ -1,37 +1,25 @@ -from PyQt5 import QtWidgets - +from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI +from flatcamGUI.preferences.PreferencesSectionUI import PreferencesSectionUI from flatcamGUI.preferences.utilities.AutoCompletePrefGroupUI import AutoCompletePrefGroupUI from flatcamGUI.preferences.utilities.FAGrbPrefGroupUI import FAGrbPrefGroupUI from flatcamGUI.preferences.utilities.FAGcoPrefGroupUI import FAGcoPrefGroupUI from flatcamGUI.preferences.utilities.FAExcPrefGroupUI import FAExcPrefGroupUI -class UtilPreferencesUI(QtWidgets.QWidget): +class UtilPreferencesUI(PreferencesSectionUI): - def __init__(self, decimals, parent=None): - QtWidgets.QWidget.__init__(self, parent=parent) - self.layout = QtWidgets.QHBoxLayout() - self.setLayout(self.layout) + def __init__(self, decimals, **kwargs): self.decimals = decimals - - self.vlay = QtWidgets.QVBoxLayout() self.fa_excellon_group = FAExcPrefGroupUI(decimals=self.decimals) - self.fa_excellon_group.setMinimumWidth(260) - self.fa_gcode_group = FAGcoPrefGroupUI(decimals=self.decimals) - self.fa_gcode_group.setMinimumWidth(260) - - self.vlay.addWidget(self.fa_excellon_group) - self.vlay.addWidget(self.fa_gcode_group) - self.fa_gerber_group = FAGrbPrefGroupUI(decimals=self.decimals) - self.fa_gerber_group.setMinimumWidth(260) - self.kw_group = AutoCompletePrefGroupUI(decimals=self.decimals) - self.kw_group.setMinimumWidth(260) + super().__init__(**kwargs) - self.layout.addLayout(self.vlay) - self.layout.addWidget(self.fa_gerber_group) - self.layout.addWidget(self.kw_group) - - self.layout.addStretch() + def build_groups(self) -> [OptionsGroupUI]: + return [ + self.fa_excellon_group, # fixme column with fa_excellon and fa_gcode + self.fa_gcode_group, + self.fa_gerber_group, + self.kw_group, + ] From f05540a5873f945b80c41c0f52a4a8961507a00f Mon Sep 17 00:00:00 2001 From: David Robertson Date: Wed, 6 May 2020 03:02:23 +0100 Subject: [PATCH 16/41] Deduplicate code creating widgets for prefs tabs --- flatcamGUI/FlatCAMGUI.py | 83 ------------------- .../preferences/PreferencesSectionUI.py | 27 +++++- .../preferences/PreferencesUIManager.py | 36 ++------ .../preferences/cncjob/CNCJobPreferencesUI.py | 7 ++ .../excellon/ExcellonPreferencesUI.py | 6 ++ .../general/GeneralPreferencesUI.py | 5 ++ .../geometry/GeometryPreferencesUI.py | 7 ++ .../preferences/gerber/GerberPreferencesUI.py | 8 +- .../preferences/tools/Tools2PreferencesUI.py | 8 +- .../preferences/tools/ToolsPreferencesUI.py | 5 ++ .../utilities/UtilPreferencesUI.py | 6 ++ 11 files changed, 81 insertions(+), 117 deletions(-) diff --git a/flatcamGUI/FlatCAMGUI.py b/flatcamGUI/FlatCAMGUI.py index 11b90242..f8faad02 100644 --- a/flatcamGUI/FlatCAMGUI.py +++ b/flatcamGUI/FlatCAMGUI.py @@ -1207,89 +1207,6 @@ class FlatCAMGUI(QtWidgets.QMainWindow): self.pref_tab_area_tabBar.setExpanding(True) self.pref_tab_layout.addWidget(self.pref_tab_area) - self.general_tab = QtWidgets.QWidget() - self.general_tab.setObjectName("general_tab") - self.pref_tab_area.addTab(self.general_tab, _("General")) - self.general_tab_lay = QtWidgets.QVBoxLayout() - self.general_tab_lay.setContentsMargins(2, 2, 2, 2) - self.general_tab.setLayout(self.general_tab_lay) - - self.hlay1 = QtWidgets.QHBoxLayout() - self.general_tab_lay.addLayout(self.hlay1) - - self.hlay1.addStretch() - - self.general_scroll_area = QtWidgets.QScrollArea() - self.general_tab_lay.addWidget(self.general_scroll_area) - - self.gerber_tab = QtWidgets.QWidget() - self.gerber_tab.setObjectName("gerber_tab") - self.pref_tab_area.addTab(self.gerber_tab, _("GERBER")) - self.gerber_tab_lay = QtWidgets.QVBoxLayout() - self.gerber_tab_lay.setContentsMargins(2, 2, 2, 2) - self.gerber_tab.setLayout(self.gerber_tab_lay) - - self.gerber_scroll_area = QtWidgets.QScrollArea() - self.gerber_tab_lay.addWidget(self.gerber_scroll_area) - - self.excellon_tab = QtWidgets.QWidget() - self.excellon_tab.setObjectName("excellon_tab") - self.pref_tab_area.addTab(self.excellon_tab, _("EXCELLON")) - self.excellon_tab_lay = QtWidgets.QVBoxLayout() - self.excellon_tab_lay.setContentsMargins(2, 2, 2, 2) - self.excellon_tab.setLayout(self.excellon_tab_lay) - - self.excellon_scroll_area = QtWidgets.QScrollArea() - self.excellon_tab_lay.addWidget(self.excellon_scroll_area) - - self.geometry_tab = QtWidgets.QWidget() - self.geometry_tab.setObjectName("geometry_tab") - self.pref_tab_area.addTab(self.geometry_tab, _("GEOMETRY")) - self.geometry_tab_lay = QtWidgets.QVBoxLayout() - self.geometry_tab_lay.setContentsMargins(2, 2, 2, 2) - self.geometry_tab.setLayout(self.geometry_tab_lay) - - self.geometry_scroll_area = QtWidgets.QScrollArea() - self.geometry_tab_lay.addWidget(self.geometry_scroll_area) - - self.text_editor_tab = QtWidgets.QWidget() - self.text_editor_tab.setObjectName("text_editor_tab") - self.pref_tab_area.addTab(self.text_editor_tab, _("CNC-JOB")) - self.cncjob_tab_lay = QtWidgets.QVBoxLayout() - self.cncjob_tab_lay.setContentsMargins(2, 2, 2, 2) - self.text_editor_tab.setLayout(self.cncjob_tab_lay) - - self.cncjob_scroll_area = QtWidgets.QScrollArea() - self.cncjob_tab_lay.addWidget(self.cncjob_scroll_area) - - self.tools_tab = QtWidgets.QWidget() - self.pref_tab_area.addTab(self.tools_tab, _("TOOLS")) - self.tools_tab_lay = QtWidgets.QVBoxLayout() - self.tools_tab_lay.setContentsMargins(2, 2, 2, 2) - self.tools_tab.setLayout(self.tools_tab_lay) - - self.tools_scroll_area = QtWidgets.QScrollArea() - self.tools_tab_lay.addWidget(self.tools_scroll_area) - - self.tools2_tab = QtWidgets.QWidget() - self.pref_tab_area.addTab(self.tools2_tab, _("TOOLS 2")) - self.tools2_tab_lay = QtWidgets.QVBoxLayout() - self.tools2_tab_lay.setContentsMargins(2, 2, 2, 2) - self.tools2_tab.setLayout(self.tools2_tab_lay) - - self.tools2_scroll_area = QtWidgets.QScrollArea() - self.tools2_tab_lay.addWidget(self.tools2_scroll_area) - - self.fa_tab = QtWidgets.QWidget() - self.fa_tab.setObjectName("fa_tab") - self.pref_tab_area.addTab(self.fa_tab, _("UTILITIES")) - self.fa_tab_lay = QtWidgets.QVBoxLayout() - self.fa_tab_lay.setContentsMargins(2, 2, 2, 2) - self.fa_tab.setLayout(self.fa_tab_lay) - - self.fa_scroll_area = QtWidgets.QScrollArea() - self.fa_tab_lay.addWidget(self.fa_scroll_area) - self.pref_tab_bottom_layout = QtWidgets.QHBoxLayout() self.pref_tab_bottom_layout.setAlignment(QtCore.Qt.AlignVCenter) self.pref_tab_layout.addLayout(self.pref_tab_bottom_layout) diff --git a/flatcamGUI/preferences/PreferencesSectionUI.py b/flatcamGUI/preferences/PreferencesSectionUI.py index 858bf3d8..e0c1d3b5 100644 --- a/flatcamGUI/preferences/PreferencesSectionUI.py +++ b/flatcamGUI/preferences/PreferencesSectionUI.py @@ -29,4 +29,29 @@ class PreferencesSectionUI(QtWidgets.QWidget): for group in self.groups: groupoptions = group.option_dict() result.update(groupoptions) - return result \ No newline at end of file + return result + + def build_tab(self): + tab = QtWidgets.QWidget() + + tab_lay = QtWidgets.QVBoxLayout() + tab_lay.setContentsMargins(2, 2, 2, 2) + tab.setLayout(tab_lay) + + # Not sure what the point of this is ??? + hlay1 = QtWidgets.QHBoxLayout() + hlay1.addStretch() + tab_lay.addLayout(hlay1) + + scroll_area = QtWidgets.QScrollArea() + scroll_area.setWidget(self) + self.show() + tab_lay.addWidget(scroll_area) + + return tab + + def get_tab_id(self) -> str: + raise NotImplementedError + + def get_tab_label(self) -> str: + raise NotImplementedError diff --git a/flatcamGUI/preferences/PreferencesUIManager.py b/flatcamGUI/preferences/PreferencesUIManager.py index 90d2cbf2..76f00eba 100644 --- a/flatcamGUI/preferences/PreferencesUIManager.py +++ b/flatcamGUI/preferences/PreferencesUIManager.py @@ -521,29 +521,7 @@ class PreferencesUIManager: } - self.child_forms = { - "general": ui.general_defaults_form, - "gerber": ui.gerber_defaults_form, - "excellon": ui.excellon_defaults_form, - "geometry": ui.geometry_defaults_form, - "cncjob": ui.cncjob_defaults_form, - "tools": ui.tools_defaults_form, - "tools2": ui.tools2_defaults_form, - "util": ui.util_defaults_form - } - self.child_scroll_areas = { - "general": ui.general_scroll_area, - "gerber": ui.gerber_scroll_area, - "excellon": ui.excellon_scroll_area, - "geometry": ui.geometry_scroll_area, - "cncjob": ui.cncjob_scroll_area, - "tools": ui.tools_scroll_area, - "tools2": ui.tools2_scroll_area, - "util": ui.fa_scroll_area - } - self.sections = [ - # FIXME ui.general_defaults_form, ui.gerber_defaults_form, ui.excellon_defaults_form, @@ -642,16 +620,12 @@ class PreferencesUIManager: :return: None """ + # FIXME this should be done in __init__ - for section in self.child_scroll_areas: - scroll_area = self.child_scroll_areas[section] - form = self.child_forms[section] - try: - scroll_area.takeWidget() - except Exception: - log.debug("Nothing to remove for section "+section) - scroll_area.setWidget(form) - form.show() + for section in self.sections: + tab = section.build_tab() + tab.setObjectName(section.get_tab_id()) + self.ui.pref_tab_area.addTab(tab, section.get_tab_label()) # Initialize the color box's color in Preferences -> Global -> Colo self.__init_color_pickers() diff --git a/flatcamGUI/preferences/cncjob/CNCJobPreferencesUI.py b/flatcamGUI/preferences/cncjob/CNCJobPreferencesUI.py index 5262a691..f9e617ad 100644 --- a/flatcamGUI/preferences/cncjob/CNCJobPreferencesUI.py +++ b/flatcamGUI/preferences/cncjob/CNCJobPreferencesUI.py @@ -22,3 +22,10 @@ class CNCJobPreferencesUI(PreferencesSectionUI): self.cncjob_opt_group, self.cncjob_adv_opt_group ] + + def get_tab_id(self): + # FIXME this doesn't seem right + return "text_editor_tab" + + def get_tab_label(self): + return _("CNC-JOB") \ No newline at end of file diff --git a/flatcamGUI/preferences/excellon/ExcellonPreferencesUI.py b/flatcamGUI/preferences/excellon/ExcellonPreferencesUI.py index 3ba51eb1..01616d37 100644 --- a/flatcamGUI/preferences/excellon/ExcellonPreferencesUI.py +++ b/flatcamGUI/preferences/excellon/ExcellonPreferencesUI.py @@ -27,3 +27,9 @@ class ExcellonPreferencesUI(PreferencesSectionUI): self.excellon_editor_group ] + def get_tab_id(self): + return "excellon_tab" + + def get_tab_label(self): + return _("EXCELLON") + diff --git a/flatcamGUI/preferences/general/GeneralPreferencesUI.py b/flatcamGUI/preferences/general/GeneralPreferencesUI.py index c582ccd6..c88d7362 100644 --- a/flatcamGUI/preferences/general/GeneralPreferencesUI.py +++ b/flatcamGUI/preferences/general/GeneralPreferencesUI.py @@ -18,3 +18,8 @@ class GeneralPreferencesUI(PreferencesSectionUI): GeneralAppSettingsGroupUI(decimals=self.decimals) ] + def get_tab_id(self): + return "general_tab" + + def get_tab_label(self): + return _("General") diff --git a/flatcamGUI/preferences/geometry/GeometryPreferencesUI.py b/flatcamGUI/preferences/geometry/GeometryPreferencesUI.py index 621cf294..c0e5a10f 100644 --- a/flatcamGUI/preferences/geometry/GeometryPreferencesUI.py +++ b/flatcamGUI/preferences/geometry/GeometryPreferencesUI.py @@ -23,3 +23,10 @@ class GeometryPreferencesUI(PreferencesSectionUI): self.geometry_adv_opt_group, self.geometry_editor_group ] + + def get_tab_id(self): + return "geometry_tab" + + def get_tab_label(self): + return _("GEOMETRY") + diff --git a/flatcamGUI/preferences/gerber/GerberPreferencesUI.py b/flatcamGUI/preferences/gerber/GerberPreferencesUI.py index f7306b21..2e564831 100644 --- a/flatcamGUI/preferences/gerber/GerberPreferencesUI.py +++ b/flatcamGUI/preferences/gerber/GerberPreferencesUI.py @@ -25,4 +25,10 @@ class GerberPreferencesUI(PreferencesSectionUI): self.gerber_exp_group, self.gerber_adv_opt_group, self.gerber_editor_group - ] \ No newline at end of file + ] + + def get_tab_id(self): + return "gerber_tab" + + def get_tab_label(self): + return _("GERBER") diff --git a/flatcamGUI/preferences/tools/Tools2PreferencesUI.py b/flatcamGUI/preferences/tools/Tools2PreferencesUI.py index 8cf6a95b..168940a0 100644 --- a/flatcamGUI/preferences/tools/Tools2PreferencesUI.py +++ b/flatcamGUI/preferences/tools/Tools2PreferencesUI.py @@ -46,4 +46,10 @@ class Tools2PreferencesUI(PreferencesSectionUI): # fixme column 5 self.tools2_punch_group, self.tools2_invert_group, - ] \ No newline at end of file + ] + + def get_tab_id(self): + return "tools2_tab" + + def get_tab_label(self): + return _("TOOLS 2") \ No newline at end of file diff --git a/flatcamGUI/preferences/tools/ToolsPreferencesUI.py b/flatcamGUI/preferences/tools/ToolsPreferencesUI.py index 2b9000cd..0c4ffd70 100644 --- a/flatcamGUI/preferences/tools/ToolsPreferencesUI.py +++ b/flatcamGUI/preferences/tools/ToolsPreferencesUI.py @@ -51,3 +51,8 @@ class ToolsPreferencesUI(PreferencesSectionUI): self.tools_solderpaste_group, ] + def get_tab_id(self): + return "tools_tab" + + def get_tab_label(self): + return _("TOOLS") diff --git a/flatcamGUI/preferences/utilities/UtilPreferencesUI.py b/flatcamGUI/preferences/utilities/UtilPreferencesUI.py index 2ce2047a..9e2f40b1 100644 --- a/flatcamGUI/preferences/utilities/UtilPreferencesUI.py +++ b/flatcamGUI/preferences/utilities/UtilPreferencesUI.py @@ -23,3 +23,9 @@ class UtilPreferencesUI(PreferencesSectionUI): self.fa_gerber_group, self.kw_group, ] + + def get_tab_id(self): + return "fa_tab" + + def get_tab_label(self): + return _("UTILITIES") \ No newline at end of file From 1c0dc433a79e06453c1837eade033a2767763f51 Mon Sep 17 00:00:00 2001 From: David Robertson Date: Wed, 6 May 2020 03:10:40 +0100 Subject: [PATCH 17/41] Simplify build_tab() --- flatcamGUI/preferences/PreferencesSectionUI.py | 16 +--------------- flatcamGUI/preferences/PreferencesUIManager.py | 2 +- 2 files changed, 2 insertions(+), 16 deletions(-) diff --git a/flatcamGUI/preferences/PreferencesSectionUI.py b/flatcamGUI/preferences/PreferencesSectionUI.py index e0c1d3b5..fa55ec31 100644 --- a/flatcamGUI/preferences/PreferencesSectionUI.py +++ b/flatcamGUI/preferences/PreferencesSectionUI.py @@ -32,23 +32,9 @@ class PreferencesSectionUI(QtWidgets.QWidget): return result def build_tab(self): - tab = QtWidgets.QWidget() - - tab_lay = QtWidgets.QVBoxLayout() - tab_lay.setContentsMargins(2, 2, 2, 2) - tab.setLayout(tab_lay) - - # Not sure what the point of this is ??? - hlay1 = QtWidgets.QHBoxLayout() - hlay1.addStretch() - tab_lay.addLayout(hlay1) - scroll_area = QtWidgets.QScrollArea() scroll_area.setWidget(self) - self.show() - tab_lay.addWidget(scroll_area) - - return tab + return scroll_area def get_tab_id(self) -> str: raise NotImplementedError diff --git a/flatcamGUI/preferences/PreferencesUIManager.py b/flatcamGUI/preferences/PreferencesUIManager.py index 76f00eba..93bb8e44 100644 --- a/flatcamGUI/preferences/PreferencesUIManager.py +++ b/flatcamGUI/preferences/PreferencesUIManager.py @@ -33,7 +33,7 @@ class PreferencesUIManager: :param defaults: a dictionary storage where all the application settings are stored :param data_path: a path to the file where all the preferences are stored for persistence :param ui: reference to the FlatCAMGUI class which constructs the UI - :param inform: a pyqtSignal used to display information's in the StatusBar of the GUI + :param inform: a pyqtSignal used to display information in the StatusBar of the GUI """ self.defaults = defaults From 44fb91633a9092219135bd6e7e7943c734fdfeae Mon Sep 17 00:00:00 2001 From: David Robertson Date: Wed, 6 May 2020 04:03:27 +0100 Subject: [PATCH 18/41] Some work on gerber prefs --- FlatCAMApp.py | 2 +- .../preferences/PreferencesUIManager.py | 31 -- .../gerber/GerberExpPrefGroupUI.py | 149 +++---- .../gerber/GerberGenPrefGroupUI.py | 374 ++++++------------ 4 files changed, 166 insertions(+), 390 deletions(-) diff --git a/FlatCAMApp.py b/FlatCAMApp.py index 348984f1..11ccf1fd 100644 --- a/FlatCAMApp.py +++ b/FlatCAMApp.py @@ -10552,7 +10552,7 @@ class App(QtCore.QObject): alpha_level = str(hex( self.ui.excellon_defaults_form.excellon_gen_group.color_alpha_slider.value())[2:]) elif sel_obj.kind == 'gerber': - alpha_level = str(hex(self.ui.gerber_defaults_form.gerber_gen_group.pf_color_alpha_slider.value())[2:]) + alpha_level = self.defaults["gerber_plot_fill"][7:] elif sel_obj.kind == 'geometry': alpha_level = 'FF' else: diff --git a/flatcamGUI/preferences/PreferencesUIManager.py b/flatcamGUI/preferences/PreferencesUIManager.py index 93bb8e44..db154cbf 100644 --- a/flatcamGUI/preferences/PreferencesUIManager.py +++ b/flatcamGUI/preferences/PreferencesUIManager.py @@ -48,17 +48,6 @@ class PreferencesUIManager: # when adding entries here read the comments in the method found below named: # def new_object(self, kind, name, initialize, active=True, fit=True, plot=True) self.defaults_form_fields = { - # Gerber General - "gerber_plot": self.ui.gerber_defaults_form.gerber_gen_group.plot_cb, - "gerber_solid": self.ui.gerber_defaults_form.gerber_gen_group.solid_cb, - "gerber_multicolored": self.ui.gerber_defaults_form.gerber_gen_group.multicolored_cb, - "gerber_circle_steps": self.ui.gerber_defaults_form.gerber_gen_group.circle_steps_entry, - "gerber_def_units": self.ui.gerber_defaults_form.gerber_gen_group.gerber_units_radio, - "gerber_def_zeros": self.ui.gerber_defaults_form.gerber_gen_group.gerber_zeros_radio, - "gerber_clean_apertures": self.ui.gerber_defaults_form.gerber_gen_group.gerber_clean_cb, - "gerber_extra_buffering": self.ui.gerber_defaults_form.gerber_gen_group.gerber_extra_buffering, - "gerber_plot_fill": self.ui.gerber_defaults_form.gerber_gen_group.pf_color_entry, - "gerber_plot_line": self.ui.gerber_defaults_form.gerber_gen_group.pl_color_entry, # Gerber Options "gerber_isotooldia": self.ui.gerber_defaults_form.gerber_opt_group.iso_tool_dia_entry, @@ -87,11 +76,6 @@ class PreferencesUIManager: "gerber_simplification": self.ui.gerber_defaults_form.gerber_adv_opt_group.simplify_cb, "gerber_simp_tolerance": self.ui.gerber_defaults_form.gerber_adv_opt_group.simplification_tol_spinner, - # Gerber Export - "gerber_exp_units": self.ui.gerber_defaults_form.gerber_exp_group.gerber_units_radio, - "gerber_exp_integer": self.ui.gerber_defaults_form.gerber_exp_group.format_whole_entry, - "gerber_exp_decimals": self.ui.gerber_defaults_form.gerber_exp_group.format_dec_entry, - "gerber_exp_zeros": self.ui.gerber_defaults_form.gerber_exp_group.zeros_radio, # Gerber Editor "gerber_editor_sel_limit": self.ui.gerber_defaults_form.gerber_editor_group.sel_limit_entry, @@ -639,21 +623,6 @@ class PreferencesUIManager: log.debug("Finished Preferences GUI form initialization.") def __init_color_pickers(self): - # Init Gerber Plot Colors - self.ui.gerber_defaults_form.gerber_gen_group.pf_color_entry.set_value(self.defaults['gerber_plot_fill']) - self.ui.gerber_defaults_form.gerber_gen_group.pf_color_button.setStyleSheet( - "background-color:%s;" - "border-color: dimgray" % str(self.defaults['gerber_plot_fill'])[:7]) - self.ui.gerber_defaults_form.gerber_gen_group.pf_color_alpha_spinner.set_value( - int(self.defaults['gerber_plot_fill'][7:9], 16)) - self.ui.gerber_defaults_form.gerber_gen_group.pf_color_alpha_slider.setValue( - int(self.defaults['gerber_plot_fill'][7:9], 16)) - - self.ui.gerber_defaults_form.gerber_gen_group.pl_color_entry.set_value(self.defaults['gerber_plot_line']) - self.ui.gerber_defaults_form.gerber_gen_group.pl_color_button.setStyleSheet( - "background-color:%s;" - "border-color: dimgray" % str(self.defaults['gerber_plot_line'])[:7]) - # Init Excellon Plot Colors self.ui.excellon_defaults_form.excellon_gen_group.fill_color_entry.set_value( self.defaults['excellon_plot_fill']) diff --git a/flatcamGUI/preferences/gerber/GerberExpPrefGroupUI.py b/flatcamGUI/preferences/gerber/GerberExpPrefGroupUI.py index 01729dc5..e6e85fb6 100644 --- a/flatcamGUI/preferences/gerber/GerberExpPrefGroupUI.py +++ b/flatcamGUI/preferences/gerber/GerberExpPrefGroupUI.py @@ -1,8 +1,5 @@ -from PyQt5 import QtWidgets, QtCore -from PyQt5.QtCore import QSettings - -from flatcamGUI.GUIElements import RadioSet, FCSpinner -from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI +from flatcamGUI.preferences.OptionUI import * +from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI2 import gettext import FlatCAMTranslation as fcTranslate @@ -12,107 +9,49 @@ fcTranslate.apply_language('strings') if '_' not in builtins.__dict__: _ = gettext.gettext -settings = QSettings("Open Source", "FlatCAM") -if settings.contains("machinist"): - machinist_setting = settings.value('machinist', type=int) -else: - machinist_setting = 0 +class GerberExpPrefGroupUI(OptionsGroupUI2): -class GerberExpPrefGroupUI(OptionsGroupUI): - - def __init__(self, decimals=4, parent=None): - super(GerberExpPrefGroupUI, self).__init__(self, parent=parent) - - self.setTitle(str(_("Gerber Export"))) + def __init__(self, decimals=4, **kwargs): self.decimals = decimals + super().__init__(**kwargs) + self.setTitle(str(_("Gerber Export"))) - # Plot options - self.export_options_label = QtWidgets.QLabel("%s:" % _("Export Options")) - self.export_options_label.setToolTip( - _("The parameters set here are used in the file exported\n" - "when using the File -> Export -> Export Gerber menu entry.") - ) - self.layout.addWidget(self.export_options_label) - - form = QtWidgets.QFormLayout() - self.layout.addLayout(form) - - # Gerber Units - self.gerber_units_label = QtWidgets.QLabel('%s:' % _('Units')) - self.gerber_units_label.setToolTip( - _("The units used in the Gerber file.") - ) - - self.gerber_units_radio = RadioSet([{'label': _('INCH'), 'value': 'IN'}, - {'label': _('MM'), 'value': 'MM'}]) - self.gerber_units_radio.setToolTip( - _("The units used in the Gerber file.") - ) - - form.addRow(self.gerber_units_label, self.gerber_units_radio) - - # Gerber format - self.digits_label = QtWidgets.QLabel("%s:" % _("Int/Decimals")) - self.digits_label.setToolTip( - _("The number of digits in the whole part of the number\n" - "and in the fractional part of the number.") - ) - - hlay1 = QtWidgets.QHBoxLayout() - - self.format_whole_entry = FCSpinner() - self.format_whole_entry.set_range(0, 9) - self.format_whole_entry.set_step(1) - self.format_whole_entry.setWrapping(True) - - self.format_whole_entry.setMinimumWidth(30) - self.format_whole_entry.setToolTip( - _("This numbers signify the number of digits in\n" - "the whole part of Gerber coordinates.") - ) - hlay1.addWidget(self.format_whole_entry, QtCore.Qt.AlignLeft) - - gerber_separator_label = QtWidgets.QLabel(':') - gerber_separator_label.setFixedWidth(5) - hlay1.addWidget(gerber_separator_label, QtCore.Qt.AlignLeft) - - self.format_dec_entry = FCSpinner() - self.format_dec_entry.set_range(0, 9) - self.format_dec_entry.set_step(1) - self.format_dec_entry.setWrapping(True) - - self.format_dec_entry.setMinimumWidth(30) - self.format_dec_entry.setToolTip( - _("This numbers signify the number of digits in\n" - "the decimal part of Gerber coordinates.") - ) - hlay1.addWidget(self.format_dec_entry, QtCore.Qt.AlignLeft) - hlay1.addStretch() - - form.addRow(self.digits_label, hlay1) - - # Gerber Zeros - self.zeros_label = QtWidgets.QLabel('%s:' % _('Zeros')) - self.zeros_label.setAlignment(QtCore.Qt.AlignLeft) - self.zeros_label.setToolTip( - _("This sets the type of Gerber zeros.\n" - "If LZ then Leading Zeros are removed and\n" - "Trailing Zeros are kept.\n" - "If TZ is checked then Trailing Zeros are removed\n" - "and Leading Zeros are kept.") - ) - - self.zeros_radio = RadioSet([{'label': _('LZ'), 'value': 'L'}, - {'label': _('TZ'), 'value': 'T'}]) - self.zeros_radio.setToolTip( - _("This sets the type of Gerber zeros.\n" - "If LZ then Leading Zeros are removed and\n" - "Trailing Zeros are kept.\n" - "If TZ is checked then Trailing Zeros are removed\n" - "and Leading Zeros are kept.") - ) - - form.addRow(self.zeros_label, self.zeros_radio) - - self.layout.addStretch() + def build_options(self) -> [OptionUI]: + return [ + HeadingOptionUI( + label_text="Export Options", + label_tooltip="The parameters set here are used in the file exported\n" + "when using the File -> Export -> Export Gerber menu entry." + ), + RadioSetOptionUI( + option="gerber_exp_units", + label_text="Units", + label_tooltip="The units used in the Gerber file.", + choices=[{'label': _('INCH'), 'value': 'IN'}, + {'label': _('MM'), 'value': 'MM'}] + ), + SpinnerOptionUI( + option="gerber_exp_integer", + label_text="Int", + label_tooltip="The number of digits in the whole part of Gerber coordinates", + min_value=0, max_value=9, step=1 + ), + SpinnerOptionUI( + option="gerber_exp_decimals", + label_text="Decimals", + label_tooltip="The number of digits in the decimal part of Gerber coordinates", + min_value=0, max_value=9, step=1 + ), + RadioSetOptionUI( + option="gerber_exp_zeros", + label_text="Zeros", + label_tooltip="This sets the type of Gerber zeros.\n" + "If LZ then Leading Zeros are removed and\n" + "Trailing Zeros are kept.\n" + "If TZ is checked then Trailing Zeros are removed\n" + "and Leading Zeros are kept.", + choices=[{'label': _('LZ'), 'value': 'L'}, + {'label': _('TZ'), 'value': 'T'}] + ) + ] \ No newline at end of file diff --git a/flatcamGUI/preferences/gerber/GerberGenPrefGroupUI.py b/flatcamGUI/preferences/gerber/GerberGenPrefGroupUI.py index 6f52fe45..4c938ebf 100644 --- a/flatcamGUI/preferences/gerber/GerberGenPrefGroupUI.py +++ b/flatcamGUI/preferences/gerber/GerberGenPrefGroupUI.py @@ -1,273 +1,141 @@ -from PyQt5 import QtWidgets, QtCore, QtGui -from PyQt5.QtCore import QSettings - -from flatcamGUI.GUIElements import FCCheckBox, FCSpinner, RadioSet, FCEntry -from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI +from PyQt5 import QtCore, QtGui +from flatcamGUI.preferences.OptionUI import * +from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI2 import gettext import FlatCAMTranslation as fcTranslate import builtins - fcTranslate.apply_language('strings') if '_' not in builtins.__dict__: _ = gettext.gettext -settings = QSettings("Open Source", "FlatCAM") -if settings.contains("machinist"): - machinist_setting = settings.value('machinist', type=int) -else: - machinist_setting = 0 - -class GerberGenPrefGroupUI(OptionsGroupUI): - def __init__(self, decimals=4, parent=None): - # OptionsGroupUI.__init__(self, "Gerber General Preferences", parent=parent) - super(GerberGenPrefGroupUI, self).__init__(self, parent=parent) - - self.setTitle(str(_("Gerber General"))) +class GerberGenPrefGroupUI(OptionsGroupUI2): + def __init__(self, decimals=4, **kwargs): self.decimals = decimals + super().__init__(**kwargs) + self.setTitle(str(_("Gerber General"))) - # ## Plot options - self.plot_options_label = QtWidgets.QLabel("%s:" % _("Plot Options")) - self.layout.addWidget(self.plot_options_label) + self.plot_line_field = self.option_dict()["gerber_plot_line"].get_field() + self.plot_fill_field = self.option_dict()["gerber_plot_fill"].get_field() + self.plot_alpha_field = self.option_dict()["_gerber_plot_alpha"].get_field() + self.plot_alpha_field.spinner.valueChanged.connect(self.on_plot_alpha_change) - grid0 = QtWidgets.QGridLayout() - self.layout.addLayout(grid0) + def build_options(self) -> [OptionUI]: + return [ + HeadingOptionUI(label_text="Plot Options"), + CheckboxOptionUI( + option="gerber_solid", + label_text="Solid", + label_tooltip="Solid color polygons." + ), + CheckboxOptionUI( + option="gerber_multicolored", + label_text="M-Color", + label_tooltip="Draw polygons in different colors." + ), + CheckboxOptionUI( + option="gerber_plot", + label_text="Plot", + label_tooltip="Plot (show) this object." + ), + SpinnerOptionUI( + option="gerber_circle_steps", + label_text="Circle Steps", + label_tooltip="The number of circle steps for Gerber \n" + "circular aperture linear approximation.", + min_value=0, max_value=9999, step=1 + ), + SeparatorOptionUI(), - # Solid CB - self.solid_cb = FCCheckBox(label='%s' % _('Solid')) - self.solid_cb.setToolTip( - _("Solid color polygons.") - ) - grid0.addWidget(self.solid_cb, 0, 0) + HeadingOptionUI( + label_text="Default Values", + label_tooltip="Those values will be used as fallback values\n" + "in case that they are not found in the Gerber file." + ), + RadioSetOptionUI( + option="gerber_def_units", + label_text="Units", + label_tooltip="The units used in the Gerber file.", + choices=[{'label': _('INCH'), 'value': 'IN'}, + {'label': _('MM'), 'value': 'MM'}] + ), + RadioSetOptionUI( + option="gerber_def_zeros", + label_text="Zeros", + label_tooltip="This sets the type of Gerber zeros.\n" + "If LZ then Leading Zeros are removed and\n" + "Trailing Zeros are kept.\n" + "If TZ is checked then Trailing Zeros are removed\n" + "and Leading Zeros are kept.", + choices=[{'label': _('LZ'), 'value': 'L'}, + {'label': _('TZ'), 'value': 'T'}] + ), + SeparatorOptionUI(), - # Multicolored CB - self.multicolored_cb = FCCheckBox(label='%s' % _('M-Color')) - self.multicolored_cb.setToolTip( - _("Draw polygons in different colors.") - ) - grid0.addWidget(self.multicolored_cb, 0, 1) + CheckboxOptionUI( + option="gerber_clean_apertures", + label_text="Clean Apertures", + label_tooltip="Will remove apertures that do not have geometry\n" + "thus lowering the number of apertures in the Gerber object." + ), + CheckboxOptionUI( + option="gerber_extra_buffering", + label_text="Polarity change buffer", + label_tooltip="Will apply extra buffering for the\n" + "solid geometry when we have polarity changes.\n" + "May help loading Gerber files that otherwise\n" + "do not load correctly." + ), + SeparatorOptionUI(), - # Plot CB - self.plot_cb = FCCheckBox(label='%s' % _('Plot')) - self.plot_options_label.setToolTip( - _("Plot (show) this object.") - ) - grid0.addWidget(self.plot_cb, 0, 2) + HeadingOptionUI(label_text="Gerber Object Color"), + ColorOptionUI( + option="gerber_plot_line", + label_text="Outline", + label_tooltip="Set the line color for plotted objects.", + ), + ColorOptionUI( + option="gerber_plot_fill", + label_text="Fill", + label_tooltip="Set the fill color for plotted objects.\n" + "First 6 digits are the color and the last 2\n" + "digits are for alpha (transparency) level." + ), + SliderWithSpinnerOptionUI( + option="_gerber_plot_alpha", + label_text="Alpha", + label_tooltip="Set the transparency for plotted objects.", + min_value=0, max_value=255, step=1 + ) + ] - # Number of circle steps for circular aperture linear approximation - self.circle_steps_label = QtWidgets.QLabel('%s:' % _("Circle Steps")) - self.circle_steps_label.setToolTip( - _("The number of circle steps for Gerber \n" - "circular aperture linear approximation.") - ) - self.circle_steps_entry = FCSpinner() - self.circle_steps_entry.set_range(0, 9999) + def on_plot_alpha_change(self): + alpha = self.plot_alpha_field.get_value() + fill = self._modify_color_alpha(color=self.plot_fill_field.get_value(), alpha=alpha) + self.plot_fill_field.set_value(fill) + line = self._modify_color_alpha(color=self.plot_line_field.get_value(), alpha=alpha) + self.plot_line_field.set_value(line) - grid0.addWidget(self.circle_steps_label, 1, 0) - grid0.addWidget(self.circle_steps_entry, 1, 1, 1, 2) + def _modify_color_alpha(self, color: str, alpha: int): + color_without_alpha = color[:7] + if alpha > 255: + return color_without_alpha + "FF" + elif alpha < 0: + return color_without_alpha + "00" + else: + hexalpha = hex(alpha)[2:] + if len(hexalpha) == 1: + hexalpha = "0" + hexalpha + return color_without_alpha + hexalpha - grid0.addWidget(QtWidgets.QLabel(''), 2, 0, 1, 3) - # Default format for Gerber - self.gerber_default_label = QtWidgets.QLabel('%s:' % _('Default Values')) - self.gerber_default_label.setToolTip( - _("Those values will be used as fallback values\n" - "in case that they are not found in the Gerber file.") - ) + # def on_pf_color_alpha_spinner(self): + # self.pf_color_alpha_slider.setValue(spinner_value) + # self.app.defaults['gerber_plot_fill'] = \ + # self.app.defaults['gerber_plot_fill'][:7] + \ + # (hex(spinner_value)[2:] if int(hex(spinner_value)[2:], 16) > 0 else '00') + # self.app.defaults['gerber_plot_line'] = \ + # self.app.defaults['gerber_plot_line'][:7] + \ + # (hex(spinner_value)[2:] if int(hex(spinner_value)[2:], 16) > 0 else '00') - grid0.addWidget(self.gerber_default_label, 3, 0, 1, 3) - - # Gerber Units - self.gerber_units_label = QtWidgets.QLabel('%s:' % _('Units')) - self.gerber_units_label.setToolTip( - _("The units used in the Gerber file.") - ) - - self.gerber_units_radio = RadioSet([{'label': _('INCH'), 'value': 'IN'}, - {'label': _('MM'), 'value': 'MM'}]) - self.gerber_units_radio.setToolTip( - _("The units used in the Gerber file.") - ) - - grid0.addWidget(self.gerber_units_label, 4, 0) - grid0.addWidget(self.gerber_units_radio, 4, 1, 1, 2) - - # Gerber Zeros - self.gerber_zeros_label = QtWidgets.QLabel('%s:' % _('Zeros')) - self.gerber_zeros_label.setAlignment(QtCore.Qt.AlignLeft) - self.gerber_zeros_label.setToolTip( - _("This sets the type of Gerber zeros.\n" - "If LZ then Leading Zeros are removed and\n" - "Trailing Zeros are kept.\n" - "If TZ is checked then Trailing Zeros are removed\n" - "and Leading Zeros are kept.") - ) - - self.gerber_zeros_radio = RadioSet([{'label': _('LZ'), 'value': 'L'}, - {'label': _('TZ'), 'value': 'T'}]) - self.gerber_zeros_radio.setToolTip( - _("This sets the type of Gerber zeros.\n" - "If LZ then Leading Zeros are removed and\n" - "Trailing Zeros are kept.\n" - "If TZ is checked then Trailing Zeros are removed\n" - "and Leading Zeros are kept.") - ) - - grid0.addWidget(self.gerber_zeros_label, 5, 0) - grid0.addWidget(self.gerber_zeros_radio, 5, 1, 1, 2) - - separator_line = QtWidgets.QFrame() - separator_line.setFrameShape(QtWidgets.QFrame.HLine) - separator_line.setFrameShadow(QtWidgets.QFrame.Sunken) - grid0.addWidget(separator_line, 6, 0, 1, 3) - - # Apertures Cleaning - self.gerber_clean_cb = FCCheckBox(label='%s' % _('Clean Apertures')) - self.gerber_clean_cb.setToolTip( - _("Will remove apertures that do not have geometry\n" - "thus lowering the number of apertures in the Gerber object.") - ) - grid0.addWidget(self.gerber_clean_cb, 7, 0, 1, 3) - - # Apply Extra Buffering - self.gerber_extra_buffering = FCCheckBox(label='%s' % _('Polarity change buffer')) - self.gerber_extra_buffering.setToolTip( - _("Will apply extra buffering for the\n" - "solid geometry when we have polarity changes.\n" - "May help loading Gerber files that otherwise\n" - "do not load correctly.") - ) - grid0.addWidget(self.gerber_extra_buffering, 8, 0, 1, 3) - - separator_line = QtWidgets.QFrame() - separator_line.setFrameShape(QtWidgets.QFrame.HLine) - separator_line.setFrameShadow(QtWidgets.QFrame.Sunken) - grid0.addWidget(separator_line, 9, 0, 1, 3) - - # Gerber Object Color - self.gerber_color_label = QtWidgets.QLabel('%s' % _('Gerber Object Color')) - grid0.addWidget(self.gerber_color_label, 10, 0, 1, 3) - - # Plot Line Color - self.pl_color_label = QtWidgets.QLabel('%s:' % _('Outline')) - self.pl_color_label.setToolTip( - _("Set the line color for plotted objects.") - ) - self.pl_color_entry = FCEntry() - self.pl_color_button = QtWidgets.QPushButton() - self.pl_color_button.setFixedSize(15, 15) - - self.form_box_child_2 = QtWidgets.QHBoxLayout() - self.form_box_child_2.addWidget(self.pl_color_entry) - self.form_box_child_2.addWidget(self.pl_color_button) - self.form_box_child_2.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter) - - grid0.addWidget(self.pl_color_label, 11, 0) - grid0.addLayout(self.form_box_child_2, 11, 1, 1, 2) - - # Plot Fill Color - self.pf_color_label = QtWidgets.QLabel('%s:' % _('Fill')) - self.pf_color_label.setToolTip( - _("Set the fill color for plotted objects.\n" - "First 6 digits are the color and the last 2\n" - "digits are for alpha (transparency) level.") - ) - self.pf_color_entry = FCEntry() - self.pf_color_button = QtWidgets.QPushButton() - self.pf_color_button.setFixedSize(15, 15) - - self.form_box_child_1 = QtWidgets.QHBoxLayout() - self.form_box_child_1.addWidget(self.pf_color_entry) - self.form_box_child_1.addWidget(self.pf_color_button) - self.form_box_child_1.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter) - - grid0.addWidget(self.pf_color_label, 12, 0) - grid0.addLayout(self.form_box_child_1, 12, 1, 1, 2) - - # Plot Fill Transparency Level - self.pf_alpha_label = QtWidgets.QLabel('%s:' % _('Alpha')) - self.pf_alpha_label.setToolTip( - _("Set the fill transparency for plotted objects.") - ) - self.pf_color_alpha_slider = QtWidgets.QSlider(QtCore.Qt.Horizontal) - self.pf_color_alpha_slider.setMinimum(0) - self.pf_color_alpha_slider.setMaximum(255) - self.pf_color_alpha_slider.setSingleStep(1) - - self.pf_color_alpha_spinner = FCSpinner() - self.pf_color_alpha_spinner.setMinimumWidth(70) - self.pf_color_alpha_spinner.set_range(0, 255) - - self.form_box_child_3 = QtWidgets.QHBoxLayout() - self.form_box_child_3.addWidget(self.pf_color_alpha_slider) - self.form_box_child_3.addWidget(self.pf_color_alpha_spinner) - - grid0.addWidget(self.pf_alpha_label, 13, 0) - grid0.addLayout(self.form_box_child_3, 13, 1, 1, 2) - - self.layout.addStretch() - - # Setting plot colors signals - self.pl_color_entry.editingFinished.connect(self.on_pl_color_entry) - self.pl_color_button.clicked.connect(self.on_pl_color_button) - self.pf_color_entry.editingFinished.connect(self.on_pf_color_entry) - self.pf_color_button.clicked.connect(self.on_pf_color_button) - self.pf_color_alpha_spinner.valueChanged.connect(self.on_pf_color_spinner) - self.pf_color_alpha_slider.valueChanged.connect(self.on_pf_color_slider) - - # Setting plot colors handlers - def on_pf_color_entry(self): - self.app.defaults['gerber_plot_fill'] = self.pf_color_entry.get_value()[:7] + \ - self.app.defaults['gerber_plot_fill'][7:9] - self.pf_color_button.setStyleSheet("background-color:%s" % str(self.app.defaults['gerber_plot_fill'])[:7]) - - def on_pf_color_button(self): - current_color = QtGui.QColor(self.app.defaults['gerber_plot_fill'][:7]) - - c_dialog = QtWidgets.QColorDialog() - plot_fill_color = c_dialog.getColor(initial=current_color) - - if plot_fill_color.isValid() is False: - return - - self.pf_color_button.setStyleSheet("background-color:%s" % str(plot_fill_color.name())) - - new_val = str(plot_fill_color.name()) + str(self.app.defaults['gerber_plot_fill'][7:9]) - self.pf_color_entry.set_value(new_val) - self.app.defaults['gerber_plot_fill'] = new_val - - def on_pf_color_spinner(self): - spinner_value = self.pf_color_alpha_spinner.value() - self.pf_color_alpha_slider.setValue(spinner_value) - self.app.defaults['gerber_plot_fill'] = \ - self.app.defaults['gerber_plot_fill'][:7] + \ - (hex(spinner_value)[2:] if int(hex(spinner_value)[2:], 16) > 0 else '00') - self.app.defaults['gerber_plot_line'] = \ - self.app.defaults['gerber_plot_line'][:7] + \ - (hex(spinner_value)[2:] if int(hex(spinner_value)[2:], 16) > 0 else '00') - - def on_pf_color_slider(self): - slider_value = self.pf_color_alpha_slider.value() - self.pf_color_alpha_spinner.setValue(slider_value) - - def on_pl_color_entry(self): - self.app.defaults['gerber_plot_line'] = self.pl_color_entry.get_value()[:7] + \ - self.app.defaults['gerber_plot_line'][7:9] - self.pl_color_button.setStyleSheet("background-color:%s" % str(self.app.defaults['gerber_plot_line'])[:7]) - - def on_pl_color_button(self): - current_color = QtGui.QColor(self.app.defaults['gerber_plot_line'][:7]) - # print(current_color) - - c_dialog = QtWidgets.QColorDialog() - plot_line_color = c_dialog.getColor(initial=current_color) - - if plot_line_color.isValid() is False: - return - - self.pl_color_button.setStyleSheet("background-color:%s" % str(plot_line_color.name())) - - new_val_line = str(plot_line_color.name()) + str(self.app.defaults['gerber_plot_line'][7:9]) - self.pl_color_entry.set_value(new_val_line) - self.app.defaults['gerber_plot_line'] = new_val_line From be93f78f7c8081cd170920a5dc88177e946502b7 Mon Sep 17 00:00:00 2001 From: David Robertson Date: Wed, 6 May 2020 04:56:56 +0100 Subject: [PATCH 19/41] Fix the alpha sliders not taking the correct value on startup and not syncing bidirectionally. --- flatcamGUI/GUIElements.py | 3 ++ flatcamGUI/preferences/OptionUI.py | 48 ++++++++++++++++- flatcamGUI/preferences/OptionsGroupUI.py | 2 - .../general/GeneralGUIPrefGroupUI.py | 54 ++++--------------- .../gerber/GerberGenPrefGroupUI.py | 43 ++------------- 5 files changed, 63 insertions(+), 87 deletions(-) diff --git a/flatcamGUI/GUIElements.py b/flatcamGUI/GUIElements.py index 20cc3a1d..eaf67be9 100644 --- a/flatcamGUI/GUIElements.py +++ b/flatcamGUI/GUIElements.py @@ -677,6 +677,7 @@ class FCColorEntry(QtWidgets.QFrame): self.entry.editingFinished.connect(self._sync_button_color) self.button.clicked.connect(self._on_button_clicked) + def get_value(self) -> str: return self.entry.get_value() @@ -733,6 +734,8 @@ class FCSliderWithSpinner(QtWidgets.QFrame): self.slider.valueChanged.connect(self._on_slider) self.spinner.valueChanged.connect(self._on_spinner) + self.valueChanged = self.spinner.valueChanged + def get_value(self) -> int: return self.spinner.get_value() diff --git a/flatcamGUI/preferences/OptionUI.py b/flatcamGUI/preferences/OptionUI.py index bef0b5c5..ce27dffd 100644 --- a/flatcamGUI/preferences/OptionUI.py +++ b/flatcamGUI/preferences/OptionUI.py @@ -1,4 +1,4 @@ -from typing import Union, Sequence +from typing import Union, Sequence, List from PyQt5 import QtWidgets from flatcamGUI.GUIElements import RadioSet, FCCheckBox, FCButton, FCComboBox, FCEntry, FCSpinner, FCColorEntry, \ @@ -7,6 +7,7 @@ from flatcamGUI.GUIElements import RadioSet, FCCheckBox, FCButton, FCComboBox, F import gettext import FlatCAMTranslation as fcTranslate import builtins + fcTranslate.apply_language('strings') if '_' not in builtins.__dict__: _ = gettext.gettext @@ -125,6 +126,51 @@ class SliderWithSpinnerOptionUI(BasicOptionUI): entry = FCSliderWithSpinner(min=self.min_value, max=self.max_value, step=self.step) return entry +class ColorAlphaSliderOptionUI(SliderWithSpinnerOptionUI): + def __init__(self, applies_to: List[str], group, label_text: str, **kwargs): + self.applies_to = applies_to + self.group = group + super().__init__(option="__color_alpha_slider", label_text=label_text, min_value=0, max_value=255, step=1, **kwargs) + self.get_field().valueChanged.connect(self._on_alpha_change) + + def add_to_grid(self, grid: QtWidgets.QGridLayout, row: int) -> int: + for index, field in enumerate(self._get_target_fields()): + field.entry.textChanged.connect(lambda value, i=index: self._on_target_change(target_index=i)) + return super().add_to_grid(grid, row) + + def _get_target_fields(self): + return list(map(lambda n: self.group.option_dict()[n].get_field(), self.applies_to)) + + def _on_target_change(self, target_index: int): + field = self._get_target_fields()[target_index] + color = field.get_value() + alpha_part = color[7:] + if len(alpha_part) != 2: + return + alpha = int(alpha_part, 16) + if alpha < 0 or alpha > 255 or self.get_field().get_value() == alpha: + return + self.get_field().set_value(alpha) + + def _on_alpha_change(self): + alpha = self.get_field().get_value() + for field in self._get_target_fields(): + old_value = field.get_value() + new_value = self._modify_color_alpha(old_value, alpha=alpha) + field.set_value(new_value) + + def _modify_color_alpha(self, color: str, alpha: int): + color_without_alpha = color[:7] + if alpha > 255: + return color_without_alpha + "FF" + elif alpha < 0: + return color_without_alpha + "00" + else: + hexalpha = hex(alpha)[2:] + if len(hexalpha) == 1: + hexalpha = "0" + hexalpha + return color_without_alpha + hexalpha + class SpinnerOptionUI(BasicOptionUI): def __init__(self, option: str, label_text: str, min_value: int, max_value: int, step: int = 1, **kwargs): diff --git a/flatcamGUI/preferences/OptionsGroupUI.py b/flatcamGUI/preferences/OptionsGroupUI.py index 1167a8d4..2f519ea9 100644 --- a/flatcamGUI/preferences/OptionsGroupUI.py +++ b/flatcamGUI/preferences/OptionsGroupUI.py @@ -2,8 +2,6 @@ from typing import Dict from PyQt5 import QtWidgets - - from PyQt5.QtCore import QSettings import gettext diff --git a/flatcamGUI/preferences/general/GeneralGUIPrefGroupUI.py b/flatcamGUI/preferences/general/GeneralGUIPrefGroupUI.py index 6ee4a6fa..5021e26e 100644 --- a/flatcamGUI/preferences/general/GeneralGUIPrefGroupUI.py +++ b/flatcamGUI/preferences/general/GeneralGUIPrefGroupUI.py @@ -11,7 +11,7 @@ if '_' not in builtins.__dict__: from flatcamGUI.preferences.OptionUI import OptionUI, CheckboxOptionUI, RadioSetOptionUI, \ SeparatorOptionUI, HeadingOptionUI, ComboboxOptionUI, ColorOptionUI, FullWidthButtonOptionUI, \ - SliderWithSpinnerOptionUI + SliderWithSpinnerOptionUI, ColorAlphaSliderOptionUI class GeneralGUIPrefGroupUI(OptionsGroupUI2): @@ -41,16 +41,6 @@ class GeneralGUIPrefGroupUI(OptionsGroupUI2): self.hdpi_field.set_value(False) self.hdpi_field.stateChanged.connect(self.handle_hdpi) - self.sel_line_field = self.option_dict()["global_sel_line"].get_field() - self.sel_fill_field = self.option_dict()["global_sel_fill"].get_field() - self.sel_alpha_field = self.option_dict()["_global_sel_alpha"].get_field() - self.sel_alpha_field.spinner.valueChanged.connect(self.on_sel_alpha_change) - - self.alt_sel_line_field = self.option_dict()["global_alt_sel_line"].get_field() - self.alt_sel_fill_field = self.option_dict()["global_alt_sel_fill"].get_field() - self.alt_sel_alpha_field = self.option_dict()["_global_alt_sel_alpha"].get_field() - self.alt_sel_alpha_field.spinner.valueChanged.connect(self.on_alt_sel_alpha_change) - def build_options(self) -> [OptionUI]: return [ RadioSetOptionUI( @@ -127,11 +117,11 @@ class GeneralGUIPrefGroupUI(OptionsGroupUI2): "First 6 digits are the color and the last 2\n" "digits are for alpha (transparency) level." ), - SliderWithSpinnerOptionUI( - option="_global_sel_alpha", + ColorAlphaSliderOptionUI( + applies_to=["global_sel_line", "global_sel_fill"], + group=self, label_text="Alpha", - label_tooltip="Set the fill transparency for the 'left to right' selection box.", - min_value=0, max_value=255, step=1 + label_tooltip="Set the fill transparency for the 'left to right' selection box." ), SeparatorOptionUI(), @@ -149,11 +139,11 @@ class GeneralGUIPrefGroupUI(OptionsGroupUI2): "First 6 digits are the color and the last 2\n" "digits are for alpha (transparency) level." ), - SliderWithSpinnerOptionUI( - option="_global_alt_sel_alpha", + ColorAlphaSliderOptionUI( + applies_to=["global_alt_sel_line", "global_alt_sel_fill"], + group=self, label_text="Alpha", - label_tooltip="Set the fill transparency for the 'right to left' selection box.", - min_value=0, max_value=255, step=1 + label_tooltip="Set the fill transparency for the 'right to left' selection box." ), SeparatorOptionUI(), @@ -191,32 +181,6 @@ class GeneralGUIPrefGroupUI(OptionsGroupUI2): ), ] - def on_sel_alpha_change(self): - alpha = self.sel_alpha_field.get_value() - fill = self._modify_color_alpha(color=self.sel_fill_field.get_value(), alpha=alpha) - self.sel_fill_field.set_value(fill) - line = self._modify_color_alpha(color=self.sel_line_field.get_value(), alpha=alpha) - self.sel_line_field.set_value(line) - - def on_alt_sel_alpha_change(self): - alpha = self.alt_sel_alpha_field.get_value() - fill = self._modify_color_alpha(color=self.alt_sel_fill_field.get_value(), alpha=alpha) - self.alt_sel_fill_field.set_value(fill) - line = self._modify_color_alpha(color=self.alt_sel_line_field.get_value(), alpha=alpha) - self.alt_sel_line_field.set_value(line) - - def _modify_color_alpha(self, color: str, alpha: int): - color_without_alpha = color[:7] - if alpha > 255: - return color_without_alpha + "FF" - elif alpha < 0: - return color_without_alpha + "00" - else: - hexalpha = hex(alpha)[2:] - if len(hexalpha) == 1: - hexalpha = "0" + hexalpha - return color_without_alpha + hexalpha - def on_theme_change(self): # FIXME: this should be moved out to a view model val = self.theme_field.get_value() diff --git a/flatcamGUI/preferences/gerber/GerberGenPrefGroupUI.py b/flatcamGUI/preferences/gerber/GerberGenPrefGroupUI.py index 4c938ebf..33acdfcc 100644 --- a/flatcamGUI/preferences/gerber/GerberGenPrefGroupUI.py +++ b/flatcamGUI/preferences/gerber/GerberGenPrefGroupUI.py @@ -1,4 +1,3 @@ -from PyQt5 import QtCore, QtGui from flatcamGUI.preferences.OptionUI import * from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI2 @@ -16,11 +15,6 @@ class GerberGenPrefGroupUI(OptionsGroupUI2): super().__init__(**kwargs) self.setTitle(str(_("Gerber General"))) - self.plot_line_field = self.option_dict()["gerber_plot_line"].get_field() - self.plot_fill_field = self.option_dict()["gerber_plot_fill"].get_field() - self.plot_alpha_field = self.option_dict()["_gerber_plot_alpha"].get_field() - self.plot_alpha_field.spinner.valueChanged.connect(self.on_plot_alpha_change) - def build_options(self) -> [OptionUI]: return [ HeadingOptionUI(label_text="Plot Options"), @@ -102,40 +96,11 @@ class GerberGenPrefGroupUI(OptionsGroupUI2): "First 6 digits are the color and the last 2\n" "digits are for alpha (transparency) level." ), - SliderWithSpinnerOptionUI( - option="_gerber_plot_alpha", + ColorAlphaSliderOptionUI( + applies_to=["gerber_plot_line", "gerber_plot_fill"], + group=self, label_text="Alpha", - label_tooltip="Set the transparency for plotted objects.", - min_value=0, max_value=255, step=1 + label_tooltip="Set the transparency for plotted objects." ) ] - def on_plot_alpha_change(self): - alpha = self.plot_alpha_field.get_value() - fill = self._modify_color_alpha(color=self.plot_fill_field.get_value(), alpha=alpha) - self.plot_fill_field.set_value(fill) - line = self._modify_color_alpha(color=self.plot_line_field.get_value(), alpha=alpha) - self.plot_line_field.set_value(line) - - def _modify_color_alpha(self, color: str, alpha: int): - color_without_alpha = color[:7] - if alpha > 255: - return color_without_alpha + "FF" - elif alpha < 0: - return color_without_alpha + "00" - else: - hexalpha = hex(alpha)[2:] - if len(hexalpha) == 1: - hexalpha = "0" + hexalpha - return color_without_alpha + hexalpha - - - # def on_pf_color_alpha_spinner(self): - # self.pf_color_alpha_slider.setValue(spinner_value) - # self.app.defaults['gerber_plot_fill'] = \ - # self.app.defaults['gerber_plot_fill'][:7] + \ - # (hex(spinner_value)[2:] if int(hex(spinner_value)[2:], 16) > 0 else '00') - # self.app.defaults['gerber_plot_line'] = \ - # self.app.defaults['gerber_plot_line'][:7] + \ - # (hex(spinner_value)[2:] if int(hex(spinner_value)[2:], 16) > 0 else '00') - From 21756bea9ca4b512fd3137558f6a19c13c30e36a Mon Sep 17 00:00:00 2001 From: David Robertson Date: Thu, 7 May 2020 02:56:22 +0100 Subject: [PATCH 20/41] Gerber opt pref group --- flatcamGUI/preferences/OptionUI.py | 5 +- .../preferences/PreferencesUIManager.py | 12 - .../gerber/GerberOptPrefGroupUI.py | 266 +++++++----------- 3 files changed, 98 insertions(+), 185 deletions(-) diff --git a/flatcamGUI/preferences/OptionUI.py b/flatcamGUI/preferences/OptionUI.py index ce27dffd..c866c89e 100644 --- a/flatcamGUI/preferences/OptionUI.py +++ b/flatcamGUI/preferences/OptionUI.py @@ -188,15 +188,16 @@ class SpinnerOptionUI(BasicOptionUI): class DoubleSpinnerOptionUI(BasicOptionUI): - def __init__(self, option: str, label_text: str, step: float, decimals: int, min_value=None, max_value=None, **kwargs): + def __init__(self, option: str, label_text: str, step: float, decimals: int, min_value=None, max_value=None, suffix=None, **kwargs): self.min_value = min_value self.max_value = max_value self.step = step + self.suffix = suffix self.decimals = decimals super().__init__(option=option, label_text=label_text, **kwargs) def build_entry_widget(self) -> QtWidgets.QWidget: - entry = FCDoubleSpinner() + entry = FCDoubleSpinner(suffix=self.suffix) entry.set_precision(self.decimals) entry.setSingleStep(self.step) if self.min_value is None: diff --git a/flatcamGUI/preferences/PreferencesUIManager.py b/flatcamGUI/preferences/PreferencesUIManager.py index db154cbf..a295925e 100644 --- a/flatcamGUI/preferences/PreferencesUIManager.py +++ b/flatcamGUI/preferences/PreferencesUIManager.py @@ -49,18 +49,6 @@ class PreferencesUIManager: # def new_object(self, kind, name, initialize, active=True, fit=True, plot=True) self.defaults_form_fields = { - # Gerber Options - "gerber_isotooldia": self.ui.gerber_defaults_form.gerber_opt_group.iso_tool_dia_entry, - "gerber_isopasses": self.ui.gerber_defaults_form.gerber_opt_group.iso_width_entry, - "gerber_isooverlap": self.ui.gerber_defaults_form.gerber_opt_group.iso_overlap_entry, - "gerber_combine_passes": self.ui.gerber_defaults_form.gerber_opt_group.combine_passes_cb, - "gerber_iso_scope": self.ui.gerber_defaults_form.gerber_opt_group.iso_scope_radio, - "gerber_milling_type": self.ui.gerber_defaults_form.gerber_opt_group.milling_type_radio, - "gerber_noncoppermargin": self.ui.gerber_defaults_form.gerber_opt_group.noncopper_margin_entry, - "gerber_noncopperrounded": self.ui.gerber_defaults_form.gerber_opt_group.noncopper_rounded_cb, - "gerber_bboxmargin": self.ui.gerber_defaults_form.gerber_opt_group.bbmargin_entry, - "gerber_bboxrounded": self.ui.gerber_defaults_form.gerber_opt_group.bbrounded_cb, - # Gerber Advanced Options "gerber_aperture_display": self.ui.gerber_defaults_form.gerber_adv_opt_group.aperture_table_visibility_cb, # "gerber_aperture_scale_factor": self.ui.gerber_defaults_form.gerber_adv_opt_group.scale_aperture_entry, diff --git a/flatcamGUI/preferences/gerber/GerberOptPrefGroupUI.py b/flatcamGUI/preferences/gerber/GerberOptPrefGroupUI.py index 404f17ba..231c6528 100644 --- a/flatcamGUI/preferences/gerber/GerberOptPrefGroupUI.py +++ b/flatcamGUI/preferences/gerber/GerberOptPrefGroupUI.py @@ -1,8 +1,5 @@ -from PyQt5 import QtWidgets -from PyQt5.QtCore import QSettings - -from flatcamGUI.GUIElements import FCDoubleSpinner, FCSpinner, RadioSet, FCCheckBox -from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI +from flatcamGUI.preferences.OptionUI import * +from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI2 import gettext import FlatCAMTranslation as fcTranslate @@ -12,176 +9,103 @@ fcTranslate.apply_language('strings') if '_' not in builtins.__dict__: _ = gettext.gettext -settings = QSettings("Open Source", "FlatCAM") -if settings.contains("machinist"): - machinist_setting = settings.value('machinist', type=int) -else: - machinist_setting = 0 +class GerberOptPrefGroupUI(OptionsGroupUI2): -class GerberOptPrefGroupUI(OptionsGroupUI): - def __init__(self, decimals=4, parent=None): - # OptionsGroupUI.__init__(self, "Gerber Options Preferences", parent=parent) - super(GerberOptPrefGroupUI, self).__init__(self, parent=parent) - + def __init__(self, decimals=4, **kwargs): self.decimals = decimals - + super().__init__(**kwargs) self.setTitle(str(_("Gerber Options"))) - # ## Isolation Routing - self.isolation_routing_label = QtWidgets.QLabel("%s:" % _("Isolation Routing")) - self.isolation_routing_label.setToolTip( - _("Create a Geometry object with\n" - "toolpaths to cut outside polygons.") - ) - self.layout.addWidget(self.isolation_routing_label) + def build_options(self) -> [OptionUI]: + return [ + HeadingOptionUI( + label_text="Isolation Routing", + label_tooltip="Create a Geometry object with\n" + "toolpaths to cut outside polygons." + ), + DoubleSpinnerOptionUI( + option="gerber_isotooldia", + label_text="Tool dia", + label_tooltip="Diameter of the cutting tool.", + min_value=0.0, max_value=9999.9, step=0.1, decimals=self.decimals + ), + SpinnerOptionUI( + option="gerber_isopasses", + label_text="# Passes", + label_tooltip="Width of the isolation gap in\n" + "number (integer) of tool widths.", + min_value=1, max_value=999, step=1 + ), + DoubleSpinnerOptionUI( + option="gerber_isooverlap", + label_text="Pass overlap", + label_tooltip="How much (percentage) of the tool width to overlap each tool pass.", + min_value=0.0, max_value=99.9999, step=0.1, decimals=self.decimals, suffix="%" + ), + RadioSetOptionUI( + option="gerber_iso_scope", + label_text="Scope", + label_tooltip="Isolation scope. Choose what to isolate:\n" + "- 'All' -> Isolate all the polygons in the object\n" + "- 'Selection' -> Isolate a selection of polygons.", + choices=[{'label': _('All'), 'value': 'all'}, + {'label': _('Selection'), 'value': 'single'}] + ), + RadioSetOptionUI( + option="gerber_milling_type", + label_text="Milling Type", + label_tooltip="Milling type:\n" + "- climb / best for precision milling and to reduce tool usage\n" + "- conventional / useful when there is no backlash compensation", + choices=[{'label': _('Climb'), 'value': 'cl'}, + {'label': _('Conventional'), 'value': 'cv'}] + ), + CheckboxOptionUI( + option="gerber_combine_passes", + label_text="Combine Passes", + label_tooltip="Combine all passes into one object" + ), + SeparatorOptionUI(), - # Cutting Tool Diameter - grid0 = QtWidgets.QGridLayout() - self.layout.addLayout(grid0) + HeadingOptionUI( + label_text="Non-copper regions", + label_tooltip="Create polygons covering the\n" + "areas without copper on the PCB.\n" + "Equivalent to the inverse of this\n" + "object. Can be used to remove all\n" + "copper from a specified region." + ), + DoubleSpinnerOptionUI( + option="gerber_noncoppermargin", + label_text="Boundary Margin", + label_tooltip="Specify the edge of the PCB\n" + "by drawing a box around all\n" + "objects with this minimum\n" + "distance.", + min_value=-9999, max_value=9999, step=0.1, decimals=self.decimals + ), + CheckboxOptionUI( + option="gerber_noncopperrounded", + label_text="Rounded Geo", + label_tooltip="Resulting geometry will have rounded corners." + ), + SeparatorOptionUI(), - tdlabel = QtWidgets.QLabel('%s:' % _('Tool dia')) - tdlabel.setToolTip( - _("Diameter of the cutting tool.") - ) - grid0.addWidget(tdlabel, 0, 0) - self.iso_tool_dia_entry = FCDoubleSpinner() - self.iso_tool_dia_entry.set_precision(self.decimals) - self.iso_tool_dia_entry.setSingleStep(0.1) - self.iso_tool_dia_entry.set_range(-9999, 9999) - - grid0.addWidget(self.iso_tool_dia_entry, 0, 1) - - # Nr of passes - passlabel = QtWidgets.QLabel('%s:' % _('# Passes')) - passlabel.setToolTip( - _("Width of the isolation gap in\n" - "number (integer) of tool widths.") - ) - self.iso_width_entry = FCSpinner() - self.iso_width_entry.set_range(1, 999) - - grid0.addWidget(passlabel, 1, 0) - grid0.addWidget(self.iso_width_entry, 1, 1) - - # Pass overlap - overlabel = QtWidgets.QLabel('%s:' % _('Pass overlap')) - overlabel.setToolTip( - _("How much (percentage) of the tool width to overlap each tool pass.") - ) - self.iso_overlap_entry = FCDoubleSpinner(suffix='%') - self.iso_overlap_entry.set_precision(self.decimals) - self.iso_overlap_entry.setWrapping(True) - self.iso_overlap_entry.setRange(0.0000, 99.9999) - self.iso_overlap_entry.setSingleStep(0.1) - - grid0.addWidget(overlabel, 2, 0) - grid0.addWidget(self.iso_overlap_entry, 2, 1) - - # Isolation Scope - self.iso_scope_label = QtWidgets.QLabel('%s:' % _('Scope')) - self.iso_scope_label.setToolTip( - _("Isolation scope. Choose what to isolate:\n" - "- 'All' -> Isolate all the polygons in the object\n" - "- 'Selection' -> Isolate a selection of polygons.") - ) - self.iso_scope_radio = RadioSet([{'label': _('All'), 'value': 'all'}, - {'label': _('Selection'), 'value': 'single'}]) - - grid0.addWidget(self.iso_scope_label, 3, 0) - grid0.addWidget(self.iso_scope_radio, 3, 1, 1, 2) - - # Milling Type - milling_type_label = QtWidgets.QLabel('%s:' % _('Milling Type')) - milling_type_label.setToolTip( - _("Milling type:\n" - "- climb / best for precision milling and to reduce tool usage\n" - "- conventional / useful when there is no backlash compensation") - ) - grid0.addWidget(milling_type_label, 4, 0) - self.milling_type_radio = RadioSet([{'label': _('Climb'), 'value': 'cl'}, - {'label': _('Conventional'), 'value': 'cv'}]) - grid0.addWidget(self.milling_type_radio, 4, 1) - - # Combine passes - self.combine_passes_cb = FCCheckBox(label=_('Combine Passes')) - self.combine_passes_cb.setToolTip( - _("Combine all passes into one object") - ) - grid0.addWidget(self.combine_passes_cb, 5, 0, 1, 2) - - separator_line = QtWidgets.QFrame() - separator_line.setFrameShape(QtWidgets.QFrame.HLine) - separator_line.setFrameShadow(QtWidgets.QFrame.Sunken) - grid0.addWidget(separator_line, 6, 0, 1, 2) - - # ## Clear non-copper regions - self.clearcopper_label = QtWidgets.QLabel("%s:" % _("Non-copper regions")) - self.clearcopper_label.setToolTip( - _("Create polygons covering the\n" - "areas without copper on the PCB.\n" - "Equivalent to the inverse of this\n" - "object. Can be used to remove all\n" - "copper from a specified region.") - ) - self.layout.addWidget(self.clearcopper_label) - - grid1 = QtWidgets.QGridLayout() - self.layout.addLayout(grid1) - - # Margin - bmlabel = QtWidgets.QLabel('%s:' % _('Boundary Margin')) - bmlabel.setToolTip( - _("Specify the edge of the PCB\n" - "by drawing a box around all\n" - "objects with this minimum\n" - "distance.") - ) - grid1.addWidget(bmlabel, 0, 0) - self.noncopper_margin_entry = FCDoubleSpinner() - self.noncopper_margin_entry.set_precision(self.decimals) - self.noncopper_margin_entry.setSingleStep(0.1) - self.noncopper_margin_entry.set_range(-9999, 9999) - grid1.addWidget(self.noncopper_margin_entry, 0, 1) - - # Rounded corners - self.noncopper_rounded_cb = FCCheckBox(label=_("Rounded Geo")) - self.noncopper_rounded_cb.setToolTip( - _("Resulting geometry will have rounded corners.") - ) - grid1.addWidget(self.noncopper_rounded_cb, 1, 0, 1, 2) - - separator_line = QtWidgets.QFrame() - separator_line.setFrameShape(QtWidgets.QFrame.HLine) - separator_line.setFrameShadow(QtWidgets.QFrame.Sunken) - grid1.addWidget(separator_line, 2, 0, 1, 2) - - # ## Bounding box - self.boundingbox_label = QtWidgets.QLabel('%s:' % _('Bounding Box')) - self.layout.addWidget(self.boundingbox_label) - - grid2 = QtWidgets.QGridLayout() - self.layout.addLayout(grid2) - - bbmargin = QtWidgets.QLabel('%s:' % _('Boundary Margin')) - bbmargin.setToolTip( - _("Distance of the edges of the box\n" - "to the nearest polygon.") - ) - self.bbmargin_entry = FCDoubleSpinner() - self.bbmargin_entry.set_precision(self.decimals) - self.bbmargin_entry.setSingleStep(0.1) - self.bbmargin_entry.set_range(-9999, 9999) - - grid2.addWidget(bbmargin, 0, 0) - grid2.addWidget(self.bbmargin_entry, 0, 1) - - self.bbrounded_cb = FCCheckBox(label='%s' % _("Rounded Geo")) - self.bbrounded_cb.setToolTip( - _("If the bounding box is \n" - "to have rounded corners\n" - "their radius is equal to\n" - "the margin.") - ) - grid2.addWidget(self.bbrounded_cb, 1, 0, 1, 2) - self.layout.addStretch() + HeadingOptionUI(label_text="Bounding Box"), + DoubleSpinnerOptionUI( + option="gerber_bboxmargin", + label_text="Boundary Margin", + label_tooltip="Distance of the edges of the box\n" + "to the nearest polygon.", + min_value=-9999, max_value=9999, step=0.1, decimals=self.decimals + ), + CheckboxOptionUI( + option="gerber_bboxrounded", + label_text="Rounded Geo", + label_tooltip="If the bounding box is \n" + "to have rounded corners\n" + "their radius is equal to\n" + "the margin." + ), + ] \ No newline at end of file From c5b2bac591836baf976ce388d27a5e8bb41336bc Mon Sep 17 00:00:00 2001 From: David Robertson Date: Sat, 9 May 2020 14:57:55 +0100 Subject: [PATCH 21/41] cleanup --- flatcamGUI/preferences/gerber/GerberAdvOptPrefGroupUI.py | 8 -------- 1 file changed, 8 deletions(-) diff --git a/flatcamGUI/preferences/gerber/GerberAdvOptPrefGroupUI.py b/flatcamGUI/preferences/gerber/GerberAdvOptPrefGroupUI.py index 20376bfd..baecfd84 100644 --- a/flatcamGUI/preferences/gerber/GerberAdvOptPrefGroupUI.py +++ b/flatcamGUI/preferences/gerber/GerberAdvOptPrefGroupUI.py @@ -1,5 +1,4 @@ from PyQt5 import QtWidgets -from PyQt5.QtCore import QSettings from flatcamGUI.GUIElements import FCCheckBox, RadioSet, FCDoubleSpinner, FCSpinner, OptionalInputSection from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI @@ -12,16 +11,9 @@ fcTranslate.apply_language('strings') if '_' not in builtins.__dict__: _ = gettext.gettext -settings = QSettings("Open Source", "FlatCAM") -if settings.contains("machinist"): - machinist_setting = settings.value('machinist', type=int) -else: - machinist_setting = 0 - class GerberAdvOptPrefGroupUI(OptionsGroupUI): def __init__(self, decimals=4, parent=None): - # OptionsGroupUI.__init__(self, "Gerber Adv. Options Preferences", parent=parent) super(GerberAdvOptPrefGroupUI, self).__init__(self, parent=parent) self.setTitle(str(_("Gerber Adv. Options"))) From 126ed47783424353dc303aff813a6e50716c9446 Mon Sep 17 00:00:00 2001 From: David Robertson Date: Sat, 9 May 2020 15:28:48 +0100 Subject: [PATCH 22/41] gerber advanced options --- .../preferences/PreferencesUIManager.py | 11 - .../gerber/GerberAdvOptPrefGroupUI.py | 266 +++++++----------- 2 files changed, 105 insertions(+), 172 deletions(-) diff --git a/flatcamGUI/preferences/PreferencesUIManager.py b/flatcamGUI/preferences/PreferencesUIManager.py index c520c156..efedea99 100644 --- a/flatcamGUI/preferences/PreferencesUIManager.py +++ b/flatcamGUI/preferences/PreferencesUIManager.py @@ -50,19 +50,8 @@ class PreferencesUIManager: self.defaults_form_fields = { # Gerber Advanced Options - "gerber_aperture_display": self.ui.gerber_defaults_form.gerber_adv_opt_group.aperture_table_visibility_cb, # "gerber_aperture_scale_factor": self.ui.gerber_defaults_form.gerber_adv_opt_group.scale_aperture_entry, # "gerber_aperture_buffer_factor": self.ui.gerber_defaults_form.gerber_adv_opt_group.buffer_aperture_entry, - "gerber_follow": self.ui.gerber_defaults_form.gerber_adv_opt_group.follow_cb, - "gerber_tool_type": self.ui.gerber_defaults_form.gerber_adv_opt_group.tool_type_radio, - "gerber_vtipdia": self.ui.gerber_defaults_form.gerber_adv_opt_group.tipdia_spinner, - "gerber_vtipangle": self.ui.gerber_defaults_form.gerber_adv_opt_group.tipangle_spinner, - "gerber_vcutz": self.ui.gerber_defaults_form.gerber_adv_opt_group.cutz_spinner, - "gerber_iso_type": self.ui.gerber_defaults_form.gerber_adv_opt_group.iso_type_radio, - - "gerber_buffering": self.ui.gerber_defaults_form.gerber_adv_opt_group.buffering_radio, - "gerber_simplification": self.ui.gerber_defaults_form.gerber_adv_opt_group.simplify_cb, - "gerber_simp_tolerance": self.ui.gerber_defaults_form.gerber_adv_opt_group.simplification_tol_spinner, # Gerber Editor diff --git a/flatcamGUI/preferences/gerber/GerberAdvOptPrefGroupUI.py b/flatcamGUI/preferences/gerber/GerberAdvOptPrefGroupUI.py index baecfd84..af9f28c8 100644 --- a/flatcamGUI/preferences/gerber/GerberAdvOptPrefGroupUI.py +++ b/flatcamGUI/preferences/gerber/GerberAdvOptPrefGroupUI.py @@ -1,7 +1,6 @@ -from PyQt5 import QtWidgets - -from flatcamGUI.GUIElements import FCCheckBox, RadioSet, FCDoubleSpinner, FCSpinner, OptionalInputSection -from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI +from flatcamGUI.GUIElements import OptionalInputSection +from flatcamGUI.preferences.OptionUI import * +from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI2 import gettext import FlatCAMTranslation as fcTranslate @@ -12,167 +11,112 @@ if '_' not in builtins.__dict__: _ = gettext.gettext -class GerberAdvOptPrefGroupUI(OptionsGroupUI): - def __init__(self, decimals=4, parent=None): - super(GerberAdvOptPrefGroupUI, self).__init__(self, parent=parent) +class GerberAdvOptPrefGroupUI(OptionsGroupUI2): - self.setTitle(str(_("Gerber Adv. Options"))) + def __init__(self, decimals=4, **kwargs): self.decimals = decimals + super().__init__(**kwargs) + self.setTitle(str(_("Gerber Adv. Options"))) - # ## Advanced Gerber Parameters - self.adv_param_label = QtWidgets.QLabel('%s:' % _('Advanced Options')) - self.adv_param_label.setToolTip( - _("A list of Gerber advanced parameters.\n" - "Those parameters are available only for\n" - "Advanced App. Level.") - ) - self.layout.addWidget(self.adv_param_label) + self.simplify_cb = self.option_dict()["gerber_simplification"].get_field() + self.simplification_tol_label = self.option_dict()["gerber_simp_tolerance"].label_widget + self.simplification_tol_spinner = self.option_dict()["gerber_simp_tolerance"].get_field() + self.ois_simplif = OptionalInputSection(self.simplify_cb, [self.simplification_tol_label, self.simplification_tol_spinner], logic=True) - grid0 = QtWidgets.QGridLayout() - self.layout.addLayout(grid0) + def build_options(self) -> [OptionUI]: + return [ + HeadingOptionUI( + label_text="Advanced Options", + label_tooltip="A list of Gerber advanced parameters.\n" + "Those parameters are available only for\n" + "Advanced App. Level." + ), + CheckboxOptionUI( + option="gerber_follow", + label_text='"Follow"', + label_tooltip="Generate a 'Follow' geometry.\n" + "This means that it will cut through\n" + "the middle of the trace." + ), + CheckboxOptionUI( + option="gerber_aperture_display", + label_text="Table Show/Hide", + label_tooltip="Toggle the display of the Gerber Apertures Table.\n" + "Also, on hide, it will delete all mark shapes\n" + "that are drawn on canvas." + ), + SeparatorOptionUI(), - # Follow Attribute - self.follow_cb = FCCheckBox(label=_('"Follow"')) - self.follow_cb.setToolTip( - _("Generate a 'Follow' geometry.\n" - "This means that it will cut through\n" - "the middle of the trace.") - ) - grid0.addWidget(self.follow_cb, 0, 0, 1, 2) + RadioSetOptionUI( + option="gerber_tool_type", + label_text="Tool Type", + label_bold=True, + label_tooltip="Choose which tool to use for Gerber isolation:\n" + "'Circular' or 'V-shape'.\n" + "When the 'V-shape' is selected then the tool\n" + "diameter will depend on the chosen cut depth.", + choices=[{'label': 'Circular', 'value': 'circular'}, + {'label': 'V-Shape', 'value': 'v'}] + ), + DoubleSpinnerOptionUI( + option="gerber_vtipdia", + label_text="V-Tip Dia", + label_tooltip="The tip diameter for V-Shape Tool", + min_value=-99.9999, max_value=99.9999, step=0.1, decimals=self.decimals + ), + SpinnerOptionUI( + option="gerber_vtipangle", + label_text="V-Tip Angle", + label_tooltip="The tip angle for V-Shape Tool.\n" + "In degrees.", + min_value=1, max_value=180, step=5 + ), + DoubleSpinnerOptionUI( + option="gerber_vcutz", + label_text="Cut Z", + label_tooltip="Cutting depth (negative)\n" + "below the copper surface.", + min_value=-99.9999, max_value=0.0000, step=0.1, decimals=self.decimals + ), - # Aperture Table Visibility CB - self.aperture_table_visibility_cb = FCCheckBox(label=_('Table Show/Hide')) - self.aperture_table_visibility_cb.setToolTip( - _("Toggle the display of the Gerber Apertures Table.\n" - "Also, on hide, it will delete all mark shapes\n" - "that are drawn on canvas.") + RadioSetOptionUI( + option="gerber_iso_type", + label_text="Isolation Type", + label_tooltip="Choose how the isolation will be executed:\n" + "- 'Full' -> complete isolation of polygons\n" + "- 'Ext' -> will isolate only on the outside\n" + "- 'Int' -> will isolate only on the inside\n" + "'Exterior' isolation is almost always possible\n" + "(with the right tool) but 'Interior'\n" + "isolation can be done only when there is an opening\n" + "inside of the polygon (e.g polygon is a 'doughnut' shape).", + choices=[{'label': _('Full'), 'value': 'full'}, + {'label': _('Exterior'), 'value': 'ext'}, + {'label': _('Interior'), 'value': 'int'}] + ), + SeparatorOptionUI(), - ) - grid0.addWidget(self.aperture_table_visibility_cb, 1, 0, 1, 2) - - separator_line = QtWidgets.QFrame() - separator_line.setFrameShape(QtWidgets.QFrame.HLine) - separator_line.setFrameShadow(QtWidgets.QFrame.Sunken) - grid0.addWidget(separator_line, 2, 0, 1, 2) - - # Tool Type - self.tool_type_label = QtWidgets.QLabel('%s' % _('Tool Type')) - self.tool_type_label.setToolTip( - _("Choose which tool to use for Gerber isolation:\n" - "'Circular' or 'V-shape'.\n" - "When the 'V-shape' is selected then the tool\n" - "diameter will depend on the chosen cut depth.") - ) - self.tool_type_radio = RadioSet([{'label': 'Circular', 'value': 'circular'}, - {'label': 'V-Shape', 'value': 'v'}]) - - grid0.addWidget(self.tool_type_label, 3, 0) - grid0.addWidget(self.tool_type_radio, 3, 1, 1, 2) - - # Tip Dia - self.tipdialabel = QtWidgets.QLabel('%s:' % _('V-Tip Dia')) - self.tipdialabel.setToolTip( - _("The tip diameter for V-Shape Tool") - ) - self.tipdia_spinner = FCDoubleSpinner() - self.tipdia_spinner.set_precision(self.decimals) - self.tipdia_spinner.set_range(-99.9999, 99.9999) - self.tipdia_spinner.setSingleStep(0.1) - self.tipdia_spinner.setWrapping(True) - grid0.addWidget(self.tipdialabel, 4, 0) - grid0.addWidget(self.tipdia_spinner, 4, 1, 1, 2) - - # Tip Angle - self.tipanglelabel = QtWidgets.QLabel('%s:' % _('V-Tip Angle')) - self.tipanglelabel.setToolTip( - _("The tip angle for V-Shape Tool.\n" - "In degree.") - ) - self.tipangle_spinner = FCSpinner() - self.tipangle_spinner.set_range(1, 180) - self.tipangle_spinner.set_step(5) - self.tipangle_spinner.setWrapping(True) - grid0.addWidget(self.tipanglelabel, 5, 0) - grid0.addWidget(self.tipangle_spinner, 5, 1, 1, 2) - - # Cut Z - self.cutzlabel = QtWidgets.QLabel('%s:' % _('Cut Z')) - self.cutzlabel.setToolTip( - _("Cutting depth (negative)\n" - "below the copper surface.") - ) - self.cutz_spinner = FCDoubleSpinner() - self.cutz_spinner.set_precision(self.decimals) - self.cutz_spinner.set_range(-99.9999, 0.0000) - self.cutz_spinner.setSingleStep(0.1) - self.cutz_spinner.setWrapping(True) - - grid0.addWidget(self.cutzlabel, 6, 0) - grid0.addWidget(self.cutz_spinner, 6, 1, 1, 2) - - # Isolation Type - self.iso_type_label = QtWidgets.QLabel('%s:' % _('Isolation Type')) - self.iso_type_label.setToolTip( - _("Choose how the isolation will be executed:\n" - "- 'Full' -> complete isolation of polygons\n" - "- 'Ext' -> will isolate only on the outside\n" - "- 'Int' -> will isolate only on the inside\n" - "'Exterior' isolation is almost always possible\n" - "(with the right tool) but 'Interior'\n" - "isolation can be done only when there is an opening\n" - "inside of the polygon (e.g polygon is a 'doughnut' shape).") - ) - self.iso_type_radio = RadioSet([{'label': _('Full'), 'value': 'full'}, - {'label': _('Exterior'), 'value': 'ext'}, - {'label': _('Interior'), 'value': 'int'}]) - - grid0.addWidget(self.iso_type_label, 7, 0,) - grid0.addWidget(self.iso_type_radio, 7, 1, 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) - - # Buffering Type - buffering_label = QtWidgets.QLabel('%s:' % _('Buffering')) - buffering_label.setToolTip( - _("Buffering type:\n" - "- None --> best performance, fast file loading but no so good display\n" - "- Full --> slow file loading but good visuals. This is the default.\n" - "<>: Don't change this unless you know what you are doing !!!") - ) - self.buffering_radio = RadioSet([{'label': _('None'), 'value': 'no'}, - {'label': _('Full'), 'value': 'full'}]) - grid0.addWidget(buffering_label, 9, 0) - grid0.addWidget(self.buffering_radio, 9, 1) - - # Simplification - self.simplify_cb = FCCheckBox(label=_('Simplify')) - self.simplify_cb.setToolTip( - _("When checked all the Gerber polygons will be\n" - "loaded with simplification having a set tolerance.\n" - "<>: Don't change this unless you know what you are doing !!!") - ) - grid0.addWidget(self.simplify_cb, 10, 0, 1, 2) - - # Simplification tolerance - self.simplification_tol_label = QtWidgets.QLabel(_('Tolerance')) - self.simplification_tol_label.setToolTip(_("Tolerance for polygon simplification.")) - - self.simplification_tol_spinner = FCDoubleSpinner() - self.simplification_tol_spinner.set_precision(self.decimals + 1) - self.simplification_tol_spinner.setWrapping(True) - self.simplification_tol_spinner.setRange(0.00000, 0.01000) - self.simplification_tol_spinner.setSingleStep(0.0001) - - grid0.addWidget(self.simplification_tol_label, 11, 0) - grid0.addWidget(self.simplification_tol_spinner, 11, 1) - self.ois_simplif = OptionalInputSection( - self.simplify_cb, - [ - self.simplification_tol_label, self.simplification_tol_spinner - ], - logic=True) - - self.layout.addStretch() + RadioSetOptionUI( + option="gerber_buffering", + label_text="Buffering", + label_tooltip="Buffering type:\n" + "- None --> best performance, fast file loading but no so good display\n" + "- Full --> slow file loading but good visuals. This is the default.\n" + "<>: Don't change this unless you know what you are doing !!!", + choices=[{'label': _('None'), 'value': 'no'}, + {'label': _('Full'), 'value': 'full'}] + ), + CheckboxOptionUI( + option="gerber_simplification", + label_text="Simplify", + label_tooltip="When checked all the Gerber polygons will be\n" + "loaded with simplification having a set tolerance.\n" + "<>: Don't change this unless you know what you are doing !!!" + ), + DoubleSpinnerOptionUI( + option="gerber_simp_tolerance", + label_text="Tolerance", + label_tooltip="Tolerance for polygon simplification.", + min_value=0.0, max_value=0.01, step=0.0001, decimals=self.decimals+1 + ) + ] \ No newline at end of file From 3db52093f07ac84b6c5e94cb8b28c350a9281e55 Mon Sep 17 00:00:00 2001 From: David Robertson Date: Sat, 9 May 2020 15:59:21 +0100 Subject: [PATCH 23/41] gerber editor prefs --- flatcamGUI/preferences/OptionUI.py | 9 + .../preferences/PreferencesUIManager.py | 23 -- .../gerber/GerberEditorPrefGroupUI.py | 351 ++++++------------ 3 files changed, 130 insertions(+), 253 deletions(-) diff --git a/flatcamGUI/preferences/OptionUI.py b/flatcamGUI/preferences/OptionUI.py index c866c89e..33d05386 100644 --- a/flatcamGUI/preferences/OptionUI.py +++ b/flatcamGUI/preferences/OptionUI.py @@ -63,6 +63,14 @@ class BasicOptionUI(OptionUI): return self.entry_widget +class LineEntryOptionUI(BasicOptionUI): + def __init__(self, option: str, label_text: str, **kwargs): + super().__init__(option=option, label_text=label_text, **kwargs) + + def build_entry_widget(self) -> QtWidgets.QWidget: + return FCEntry() + + class RadioSetOptionUI(BasicOptionUI): def __init__(self, option: str, label_text: str, choices: list, orientation='horizontal', **kwargs): @@ -126,6 +134,7 @@ class SliderWithSpinnerOptionUI(BasicOptionUI): entry = FCSliderWithSpinner(min=self.min_value, max=self.max_value, step=self.step) return entry + class ColorAlphaSliderOptionUI(SliderWithSpinnerOptionUI): def __init__(self, applies_to: List[str], group, label_text: str, **kwargs): self.applies_to = applies_to diff --git a/flatcamGUI/preferences/PreferencesUIManager.py b/flatcamGUI/preferences/PreferencesUIManager.py index efedea99..9172dfc7 100644 --- a/flatcamGUI/preferences/PreferencesUIManager.py +++ b/flatcamGUI/preferences/PreferencesUIManager.py @@ -49,29 +49,6 @@ class PreferencesUIManager: # def new_object(self, kind, name, initialize, active=True, fit=True, plot=True) self.defaults_form_fields = { - # Gerber Advanced Options - # "gerber_aperture_scale_factor": self.ui.gerber_defaults_form.gerber_adv_opt_group.scale_aperture_entry, - # "gerber_aperture_buffer_factor": self.ui.gerber_defaults_form.gerber_adv_opt_group.buffer_aperture_entry, - - - # Gerber Editor - "gerber_editor_sel_limit": self.ui.gerber_defaults_form.gerber_editor_group.sel_limit_entry, - "gerber_editor_newcode": self.ui.gerber_defaults_form.gerber_editor_group.addcode_entry, - "gerber_editor_newsize": self.ui.gerber_defaults_form.gerber_editor_group.addsize_entry, - "gerber_editor_newtype": self.ui.gerber_defaults_form.gerber_editor_group.addtype_combo, - "gerber_editor_newdim": self.ui.gerber_defaults_form.gerber_editor_group.adddim_entry, - "gerber_editor_array_size": self.ui.gerber_defaults_form.gerber_editor_group.grb_array_size_entry, - "gerber_editor_lin_axis": self.ui.gerber_defaults_form.gerber_editor_group.grb_axis_radio, - "gerber_editor_lin_pitch": self.ui.gerber_defaults_form.gerber_editor_group.grb_pitch_entry, - "gerber_editor_lin_angle": self.ui.gerber_defaults_form.gerber_editor_group.grb_angle_entry, - "gerber_editor_circ_dir": self.ui.gerber_defaults_form.gerber_editor_group.grb_circular_dir_radio, - "gerber_editor_circ_angle": - self.ui.gerber_defaults_form.gerber_editor_group.grb_circular_angle_entry, - "gerber_editor_scale_f": self.ui.gerber_defaults_form.gerber_editor_group.grb_scale_entry, - "gerber_editor_buff_f": self.ui.gerber_defaults_form.gerber_editor_group.grb_buff_entry, - "gerber_editor_ma_low": self.ui.gerber_defaults_form.gerber_editor_group.grb_ma_low_entry, - "gerber_editor_ma_high": self.ui.gerber_defaults_form.gerber_editor_group.grb_ma_high_entry, - # Excellon General "excellon_plot": self.ui.excellon_defaults_form.excellon_gen_group.plot_cb, "excellon_solid": self.ui.excellon_defaults_form.excellon_gen_group.solid_cb, diff --git a/flatcamGUI/preferences/gerber/GerberEditorPrefGroupUI.py b/flatcamGUI/preferences/gerber/GerberEditorPrefGroupUI.py index 3ba0da99..2b9bd49e 100644 --- a/flatcamGUI/preferences/gerber/GerberEditorPrefGroupUI.py +++ b/flatcamGUI/preferences/gerber/GerberEditorPrefGroupUI.py @@ -1,247 +1,138 @@ -from PyQt5 import QtWidgets -from PyQt5.QtCore import QSettings - -from flatcamGUI.GUIElements import FCSpinner, FCDoubleSpinner, FCComboBox, FCEntry, RadioSet -from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI +from flatcamGUI.preferences.OptionUI import * +from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI2 import gettext import FlatCAMTranslation as fcTranslate import builtins - fcTranslate.apply_language('strings') if '_' not in builtins.__dict__: _ = gettext.gettext -settings = QSettings("Open Source", "FlatCAM") -if settings.contains("machinist"): - machinist_setting = settings.value('machinist', type=int) -else: - machinist_setting = 0 +class GerberEditorPrefGroupUI(OptionsGroupUI2): -class GerberEditorPrefGroupUI(OptionsGroupUI): - def __init__(self, decimals=4, parent=None): - # OptionsGroupUI.__init__(self, "Gerber Adv. Options Preferences", parent=parent) - super(GerberEditorPrefGroupUI, self).__init__(self, parent=parent) - - self.setTitle(str(_("Gerber Editor"))) + def __init__(self, decimals=4, **kwargs): self.decimals = decimals + super().__init__(**kwargs) + self.setTitle(str(_("Gerber Editor"))) - # Advanced Gerber Parameters - self.param_label = QtWidgets.QLabel("%s:" % _("Parameters")) - self.param_label.setToolTip( - _("A list of Gerber Editor parameters.") - ) - self.layout.addWidget(self.param_label) + def build_options(self) -> [OptionUI]: + return [ + HeadingOptionUI( + label_text="Parameters", + label_tooltip="A list of Gerber Editor parameters." + ), + SpinnerOptionUI( + option="gerber_editor_sel_limit", + label_text="Selection limit", + label_tooltip="Set the number of selected Gerber geometry\n" + "items above which the utility geometry\n" + "becomes just a selection rectangle.\n" + "Increases the performance when moving a\n" + "large number of geometric elements.", + min_value=0, max_value=9999, step=1 + ), + SpinnerOptionUI( + option="gerber_editor_newcode", + label_text="New Aperture code", + label_tooltip="Code for the new aperture", + min_value=10, max_value=99, step=1 + ), + DoubleSpinnerOptionUI( + option="gerber_editor_newsize", + label_text="New Aperture size", + label_tooltip="Size for the new aperture", + min_value=0.0, max_value=100.0, step=0.1, decimals=self.decimals + ), + ComboboxOptionUI( + option="gerber_editor_newtype", + label_text="New Aperture type", + label_tooltip="Type for the new aperture.\n" + "Can be 'C', 'R' or 'O'.", + choices=['C', 'R', 'O'] + ), + SpinnerOptionUI( + option="gerber_editor_array_size", + label_text="Nr of pads", + label_tooltip="Specify how many pads to be in the array.", + min_value=0, max_value=9999, step=1 + ), + LineEntryOptionUI( + option="gerber_editor_newdim", + label_text="Aperture Dimensions", + label_tooltip="Diameters of the tools, separated by comma.\n" + "The value of the diameter has to use the dot decimals separator.\n" + "Valid values: 0.3, 1.0" + ), - grid0 = QtWidgets.QGridLayout() - self.layout.addLayout(grid0) + HeadingOptionUI(label_text="Linear Pad Array"), + RadioSetOptionUI( + option="gerber_editor_lin_axis", + label_text="Linear Direction", + label_tooltip="Direction on which the linear array is oriented:\n" + "- 'X' - horizontal axis \n" + "- 'Y' - vertical axis or \n" + "- 'Angle' - a custom angle for the array inclination", + choices=[{'label': _('X'), 'value': 'X'}, + {'label': _('Y'), 'value': 'Y'}, + {'label': _('Angle'), 'value': 'A'}] + ), + DoubleSpinnerOptionUI( + option="gerber_editor_lin_pitch", + label_text="Pitch", + label_tooltip="Pitch = Distance between elements of the array.", + min_value=-9999.99, max_value=9999.99, step=0.1, decimals=self.decimals + ), + DoubleSpinnerOptionUI( + option="gerber_editor_lin_angle", + label_text="Angle", + label_tooltip="Angle at which each element in circular array is placed.", # FIXME: this seems wrong + min_value=-360, max_value=360, step=5, decimals=self.decimals + ), - # Selection Limit - self.sel_limit_label = QtWidgets.QLabel('%s:' % _("Selection limit")) - self.sel_limit_label.setToolTip( - _("Set the number of selected Gerber geometry\n" - "items above which the utility geometry\n" - "becomes just a selection rectangle.\n" - "Increases the performance when moving a\n" - "large number of geometric elements.") - ) - self.sel_limit_entry = FCSpinner() - self.sel_limit_entry.set_range(0, 9999) + HeadingOptionUI(label_text="Circular Pad Array"), + RadioSetOptionUI( + option="gerber_editor_circ_dir", + label_text="Circular Direction", + label_tooltip="Direction for circular array.\n" + "Can be CW = clockwise or CCW = counter clockwise.", + choices=[{'label': _('CW'), 'value': 'CW'}, + {'label': _('CCW'), 'value': 'CCW'}] + ), + DoubleSpinnerOptionUI( + option="gerber_editor_circ_angle", + label_text="Circular Angle", + label_tooltip="Angle at which each element in circular array is placed.", + min_value=-360, max_value=360, step=5, decimals=self.decimals + ), - grid0.addWidget(self.sel_limit_label, 0, 0) - grid0.addWidget(self.sel_limit_entry, 0, 1) + HeadingOptionUI(label_text="Buffer Tool"), + DoubleSpinnerOptionUI( + option="gerber_editor_buff_f", + label_text="Buffer distance", + label_tooltip="Distance at which to buffer the Gerber element.", + min_value=-9999, max_value=9999, step=0.1, decimals=self.decimals + ), - # New aperture code - self.addcode_entry_lbl = QtWidgets.QLabel('%s:' % _('New Aperture code')) - self.addcode_entry_lbl.setToolTip( - _("Code for the new aperture") - ) + HeadingOptionUI(label_text="Scale Tool"), + DoubleSpinnerOptionUI( + option="gerber_editor_scale_f", + label_text="Scale factor", + label_tooltip="Factor to scale the Gerber element.", + min_value=0, max_value=9999, step=0.1, decimals=self.decimals + ), - self.addcode_entry = FCSpinner() - self.addcode_entry.set_range(10, 99) - self.addcode_entry.setWrapping(True) - - grid0.addWidget(self.addcode_entry_lbl, 1, 0) - grid0.addWidget(self.addcode_entry, 1, 1) - - # New aperture size - self.addsize_entry_lbl = QtWidgets.QLabel('%s:' % _('New Aperture size')) - self.addsize_entry_lbl.setToolTip( - _("Size for the new aperture") - ) - - self.addsize_entry = FCDoubleSpinner() - self.addsize_entry.set_range(0, 100) - self.addsize_entry.set_precision(self.decimals) - - grid0.addWidget(self.addsize_entry_lbl, 2, 0) - grid0.addWidget(self.addsize_entry, 2, 1) - - # New aperture type - self.addtype_combo_lbl = QtWidgets.QLabel('%s:' % _('New Aperture type')) - self.addtype_combo_lbl.setToolTip( - _("Type for the new aperture.\n" - "Can be 'C', 'R' or 'O'.") - ) - - self.addtype_combo = FCComboBox() - self.addtype_combo.addItems(['C', 'R', 'O']) - - grid0.addWidget(self.addtype_combo_lbl, 3, 0) - grid0.addWidget(self.addtype_combo, 3, 1) - - # Number of pads in a pad array - self.grb_array_size_label = QtWidgets.QLabel('%s:' % _('Nr of pads')) - self.grb_array_size_label.setToolTip( - _("Specify how many pads to be in the array.") - ) - - self.grb_array_size_entry = FCSpinner() - self.grb_array_size_entry.set_range(0, 9999) - - grid0.addWidget(self.grb_array_size_label, 4, 0) - grid0.addWidget(self.grb_array_size_entry, 4, 1) - - self.adddim_label = QtWidgets.QLabel('%s:' % _('Aperture Dimensions')) - self.adddim_label.setToolTip( - _("Diameters of the tools, separated by comma.\n" - "The value of the diameter has to use the dot decimals separator.\n" - "Valid values: 0.3, 1.0") - ) - grid0.addWidget(self.adddim_label, 5, 0) - self.adddim_entry = FCEntry() - grid0.addWidget(self.adddim_entry, 5, 1) - - self.grb_array_linear_label = QtWidgets.QLabel('%s:' % _('Linear Pad Array')) - grid0.addWidget(self.grb_array_linear_label, 6, 0, 1, 2) - - # Linear Pad Array direction - self.grb_axis_label = QtWidgets.QLabel('%s:' % _('Linear Direction')) - self.grb_axis_label.setToolTip( - _("Direction on which the linear array is oriented:\n" - "- 'X' - horizontal axis \n" - "- 'Y' - vertical axis or \n" - "- 'Angle' - a custom angle for the array inclination") - ) - - self.grb_axis_radio = RadioSet([{'label': _('X'), 'value': 'X'}, - {'label': _('Y'), 'value': 'Y'}, - {'label': _('Angle'), 'value': 'A'}]) - - grid0.addWidget(self.grb_axis_label, 7, 0) - grid0.addWidget(self.grb_axis_radio, 7, 1) - - # Linear Pad Array pitch distance - self.grb_pitch_label = QtWidgets.QLabel('%s:' % _('Pitch')) - self.grb_pitch_label.setToolTip( - _("Pitch = Distance between elements of the array.") - ) - # self.drill_pitch_label.setMinimumWidth(100) - self.grb_pitch_entry = FCDoubleSpinner() - self.grb_pitch_entry.set_precision(self.decimals) - - grid0.addWidget(self.grb_pitch_label, 8, 0) - grid0.addWidget(self.grb_pitch_entry, 8, 1) - - # Linear Pad Array custom angle - self.grb_angle_label = QtWidgets.QLabel('%s:' % _('Angle')) - self.grb_angle_label.setToolTip( - _("Angle at which each element in circular array is placed.") - ) - self.grb_angle_entry = FCDoubleSpinner() - self.grb_angle_entry.set_precision(self.decimals) - self.grb_angle_entry.set_range(-360, 360) - self.grb_angle_entry.setSingleStep(5) - - grid0.addWidget(self.grb_angle_label, 9, 0) - grid0.addWidget(self.grb_angle_entry, 9, 1) - - self.grb_array_circ_label = QtWidgets.QLabel('%s:' % _('Circular Pad Array')) - grid0.addWidget(self.grb_array_circ_label, 10, 0, 1, 2) - - # Circular Pad Array direction - self.grb_circular_direction_label = QtWidgets.QLabel('%s:' % _('Circular Direction')) - self.grb_circular_direction_label.setToolTip( - _("Direction for circular array.\n" - "Can be CW = clockwise or CCW = counter clockwise.") - ) - - self.grb_circular_dir_radio = RadioSet([{'label': _('CW'), 'value': 'CW'}, - {'label': _('CCW'), 'value': 'CCW'}]) - - grid0.addWidget(self.grb_circular_direction_label, 11, 0) - grid0.addWidget(self.grb_circular_dir_radio, 11, 1) - - # Circular Pad Array Angle - self.grb_circular_angle_label = QtWidgets.QLabel('%s:' % _('Circular Angle')) - self.grb_circular_angle_label.setToolTip( - _("Angle at which each element in circular array is placed.") - ) - self.grb_circular_angle_entry = FCDoubleSpinner() - self.grb_circular_angle_entry.set_precision(self.decimals) - self.grb_circular_angle_entry.set_range(-360, 360) - - self.grb_circular_angle_entry.setSingleStep(5) - - grid0.addWidget(self.grb_circular_angle_label, 12, 0) - grid0.addWidget(self.grb_circular_angle_entry, 12, 1) - - self.grb_array_tools_b_label = QtWidgets.QLabel('%s:' % _('Buffer Tool')) - grid0.addWidget(self.grb_array_tools_b_label, 13, 0, 1, 2) - - # Buffer Distance - self.grb_buff_label = QtWidgets.QLabel('%s:' % _('Buffer distance')) - self.grb_buff_label.setToolTip( - _("Distance at which to buffer the Gerber element.") - ) - self.grb_buff_entry = FCDoubleSpinner() - self.grb_buff_entry.set_precision(self.decimals) - self.grb_buff_entry.set_range(-9999, 9999) - - grid0.addWidget(self.grb_buff_label, 14, 0) - grid0.addWidget(self.grb_buff_entry, 14, 1) - - self.grb_array_tools_s_label = QtWidgets.QLabel('%s:' % _('Scale Tool')) - grid0.addWidget(self.grb_array_tools_s_label, 15, 0, 1, 2) - - # Scale Factor - self.grb_scale_label = QtWidgets.QLabel('%s:' % _('Scale factor')) - self.grb_scale_label.setToolTip( - _("Factor to scale the Gerber element.") - ) - self.grb_scale_entry = FCDoubleSpinner() - self.grb_scale_entry.set_precision(self.decimals) - self.grb_scale_entry.set_range(0, 9999) - - grid0.addWidget(self.grb_scale_label, 16, 0) - grid0.addWidget(self.grb_scale_entry, 16, 1) - - self.grb_array_tools_ma_label = QtWidgets.QLabel('%s:' % _('Mark Area Tool')) - grid0.addWidget(self.grb_array_tools_ma_label, 17, 0, 1, 2) - - # Mark area Tool low threshold - self.grb_ma_low_label = QtWidgets.QLabel('%s:' % _('Threshold low')) - self.grb_ma_low_label.setToolTip( - _("Threshold value under which the apertures are not marked.") - ) - self.grb_ma_low_entry = FCDoubleSpinner() - self.grb_ma_low_entry.set_precision(self.decimals) - self.grb_ma_low_entry.set_range(0, 9999) - - grid0.addWidget(self.grb_ma_low_label, 18, 0) - grid0.addWidget(self.grb_ma_low_entry, 18, 1) - - # Mark area Tool high threshold - self.grb_ma_high_label = QtWidgets.QLabel('%s:' % _('Threshold high')) - self.grb_ma_high_label.setToolTip( - _("Threshold value over which the apertures are not marked.") - ) - self.grb_ma_high_entry = FCDoubleSpinner() - self.grb_ma_high_entry.set_precision(self.decimals) - self.grb_ma_high_entry.set_range(0, 9999) - - grid0.addWidget(self.grb_ma_high_label, 19, 0) - grid0.addWidget(self.grb_ma_high_entry, 19, 1) - - self.layout.addStretch() + HeadingOptionUI(label_text="Mark Area Tool"), + DoubleSpinnerOptionUI( + option="gerber_editor_ma_low", + label_text="Threshold low", + label_tooltip="Threshold value under which the apertures are not marked.", + min_value=0, max_value=9999, step=0.1, decimals=self.decimals + ), + DoubleSpinnerOptionUI( + option="gerber_editor_ma_high", + label_text="Threshold high", + label_tooltip="Threshold value over which the apertures are not marked.", + min_value=0, max_value=9999, step=0.1, decimals=self.decimals + ) + ] From 31d0cfbdd714a39fe479fa6aa3941866dc6e1c30 Mon Sep 17 00:00:00 2001 From: David Robertson Date: Sat, 9 May 2020 16:01:06 +0100 Subject: [PATCH 24/41] GerberPreferencesUI cleanup --- .../preferences/gerber/GerberPreferencesUI.py | 24 +++++++++++-------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/flatcamGUI/preferences/gerber/GerberPreferencesUI.py b/flatcamGUI/preferences/gerber/GerberPreferencesUI.py index 2e564831..8d3b3e90 100644 --- a/flatcamGUI/preferences/gerber/GerberPreferencesUI.py +++ b/flatcamGUI/preferences/gerber/GerberPreferencesUI.py @@ -6,25 +6,29 @@ from flatcamGUI.preferences.gerber.GerberAdvOptPrefGroupUI import GerberAdvOptPr from flatcamGUI.preferences.gerber.GerberOptPrefGroupUI import GerberOptPrefGroupUI from flatcamGUI.preferences.gerber.GerberGenPrefGroupUI import GerberGenPrefGroupUI +import gettext +import FlatCAMTranslation as fcTranslate +import builtins +fcTranslate.apply_language('strings') +if '_' not in builtins.__dict__: + _ = gettext.gettext + class GerberPreferencesUI(PreferencesSectionUI): def __init__(self, decimals, **kwargs): self.decimals = decimals - self.gerber_gen_group = GerberGenPrefGroupUI(decimals=self.decimals) - self.gerber_opt_group = GerberOptPrefGroupUI(decimals=self.decimals) - self.gerber_exp_group = GerberExpPrefGroupUI(decimals=self.decimals) - self.gerber_adv_opt_group = GerberAdvOptPrefGroupUI(decimals=self.decimals) - self.gerber_editor_group = GerberEditorPrefGroupUI(decimals=self.decimals) super().__init__(**kwargs) def build_groups(self) -> [OptionsGroupUI]: return [ - self.gerber_gen_group, - self.gerber_opt_group, # FIXME vertical layout with opt and ext - self.gerber_exp_group, - self.gerber_adv_opt_group, - self.gerber_editor_group + GerberGenPrefGroupUI(decimals=self.decimals), + + GerberOptPrefGroupUI(decimals=self.decimals), # FIXME vertical layout with opt and exp + GerberExpPrefGroupUI(decimals=self.decimals), + + GerberAdvOptPrefGroupUI(decimals=self.decimals), + GerberEditorPrefGroupUI(decimals=self.decimals) ] def get_tab_id(self): From 9f2991c003f91b38288ebe60a531163fc7869c7f Mon Sep 17 00:00:00 2001 From: David Robertson Date: Sat, 9 May 2020 16:21:21 +0100 Subject: [PATCH 25/41] Geometry general prefs --- flatcamGUI/preferences/OptionUI.py | 8 +- .../preferences/PreferencesUIManager.py | 12 -- .../general/GeneralAppPrefGroupUI.py | 4 +- .../geometry/GeometryGenPrefGroupUI.py | 147 +++++------------- .../geometry/GeometryPreferencesUI.py | 7 + 5 files changed, 52 insertions(+), 126 deletions(-) diff --git a/flatcamGUI/preferences/OptionUI.py b/flatcamGUI/preferences/OptionUI.py index 33d05386..1fb34b72 100644 --- a/flatcamGUI/preferences/OptionUI.py +++ b/flatcamGUI/preferences/OptionUI.py @@ -31,12 +31,12 @@ class OptionUI: class BasicOptionUI(OptionUI): """Abstract OptionUI that has a label on the left then some other widget on the right""" - def __init__(self, option: str, label_text: str, label_tooltip: Union[str, None] = None, label_bold: bool = False, label_red: bool = False): + def __init__(self, option: str, label_text: str, label_tooltip: Union[str, None] = None, label_bold: bool = False, label_color: Union[str, None] = None): super().__init__(option=option) self.label_text = label_text self.label_tooltip = label_tooltip self.label_bold = label_bold - self.label_red = label_red + self.label_color = label_color self.label_widget = self.build_label_widget() self.entry_widget = self.build_entry_widget() @@ -44,8 +44,8 @@ class BasicOptionUI(OptionUI): fmt = "%s:" if self.label_bold: fmt = "%s" % fmt - if self.label_red: - fmt = "%s" % fmt + if self.label_color: + fmt = "%s" % (self.label_color, fmt) label_widget = QtWidgets.QLabel(fmt % _(self.label_text)) if self.label_tooltip is not None: label_widget.setToolTip(_(self.label_tooltip)) diff --git a/flatcamGUI/preferences/PreferencesUIManager.py b/flatcamGUI/preferences/PreferencesUIManager.py index 9172dfc7..7b5eaec6 100644 --- a/flatcamGUI/preferences/PreferencesUIManager.py +++ b/flatcamGUI/preferences/PreferencesUIManager.py @@ -141,11 +141,6 @@ class PreferencesUIManager: "excellon_editor_slot_circ_angle": self.ui.excellon_defaults_form.excellon_editor_group.slot_array_circular_angle_entry, - # Geometry General - "geometry_plot": self.ui.geometry_defaults_form.geometry_gen_group.plot_cb, - "geometry_circle_steps": self.ui.geometry_defaults_form.geometry_gen_group.circle_steps_entry, - "geometry_cnctooldia": self.ui.geometry_defaults_form.geometry_gen_group.cnctooldia_entry, - "geometry_plot_line": self.ui.geometry_defaults_form.geometry_gen_group.line_color_entry, # Geometry Options "geometry_cutz": self.ui.geometry_defaults_form.geometry_opt_group.cutz_entry, @@ -594,13 +589,6 @@ class PreferencesUIManager: "background-color:%s;" "border-color: dimgray" % str(self.defaults['excellon_plot_line'])[:7]) - # Init Geometry Plot Colors - self.ui.geometry_defaults_form.geometry_gen_group.line_color_entry.set_value( - self.defaults['geometry_plot_line']) - self.ui.geometry_defaults_form.geometry_gen_group.line_color_button.setStyleSheet( - "background-color:%s;" - "border-color: dimgray" % str(self.defaults['geometry_plot_line'])[:7]) - # Init CNCJob Travel Line Colors self.ui.cncjob_defaults_form.cncjob_gen_group.tfill_color_entry.set_value( self.defaults['cncjob_travel_fill']) diff --git a/flatcamGUI/preferences/general/GeneralAppPrefGroupUI.py b/flatcamGUI/preferences/general/GeneralAppPrefGroupUI.py index 96ac84b7..4ab4f105 100644 --- a/flatcamGUI/preferences/general/GeneralAppPrefGroupUI.py +++ b/flatcamGUI/preferences/general/GeneralAppPrefGroupUI.py @@ -49,7 +49,7 @@ class GeneralAppPrefGroupUI(OptionsGroupUI2): "Whatever is selected here is set every time\n" "FlatCAM is started.", label_bold=True, - label_red=True, + label_color="red", choices=[{'label': _('MM'), 'value': 'MM'}, {'label': _('IN'), 'value': 'IN'}] ), @@ -94,7 +94,7 @@ class GeneralAppPrefGroupUI(OptionsGroupUI2): "The choice here will influence the parameters in\n" "the Selected Tab for all kinds of FlatCAM objects.", label_bold=True, - label_red=True, + label_color="red", choices=[{'label': _('Basic'), 'value': 'b'}, {'label': _('Advanced'), 'value': 'a'}] ), diff --git a/flatcamGUI/preferences/geometry/GeometryGenPrefGroupUI.py b/flatcamGUI/preferences/geometry/GeometryGenPrefGroupUI.py index 60479236..1e800702 100644 --- a/flatcamGUI/preferences/geometry/GeometryGenPrefGroupUI.py +++ b/flatcamGUI/preferences/geometry/GeometryGenPrefGroupUI.py @@ -1,8 +1,5 @@ -from PyQt5 import QtWidgets, QtCore, QtGui -from PyQt5.QtCore import QSettings - -from flatcamGUI.GUIElements import FCCheckBox, FCSpinner, FCEntry -from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI +from flatcamGUI.preferences.OptionUI import * +from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI2 import gettext import FlatCAMTranslation as fcTranslate @@ -12,112 +9,46 @@ fcTranslate.apply_language('strings') if '_' not in builtins.__dict__: _ = gettext.gettext -settings = QSettings("Open Source", "FlatCAM") -if settings.contains("machinist"): - machinist_setting = settings.value('machinist', type=int) -else: - machinist_setting = 0 +class GeometryGenPrefGroupUI(OptionsGroupUI2): -class GeometryGenPrefGroupUI(OptionsGroupUI): - def __init__(self, decimals=4, parent=None): - # OptionsGroupUI.__init__(self, "Geometry General Preferences", parent=parent) - super(GeometryGenPrefGroupUI, self).__init__(self, parent=parent) - - self.setTitle(str(_("Geometry General"))) + def __init__(self, decimals=4, **kwargs): self.decimals = decimals + super().__init__(**kwargs) + self.setTitle(str(_("Geometry General"))) - # ## Plot options - self.plot_options_label = QtWidgets.QLabel("%s:" % _("Plot Options")) - self.layout.addWidget(self.plot_options_label) + def build_options(self) -> [OptionUI]: + return [ + HeadingOptionUI(label_text="Plot Options"), + CheckboxOptionUI( + option="geometry_plot", + label_text="Plot", + label_tooltip="Plot (show) this object." + ), + SpinnerOptionUI( + option="geometry_circle_steps", + label_text="Circle Steps", + label_tooltip="The number of circle steps for Geometry \n" + "circle and arc shapes linear approximation.", + min_value=0, max_value=9999, step=1 + ), + HeadingOptionUI(label_text="Tools"), + LineEntryOptionUI( + option="geometry_cnctooldia", + label_text="Tools Dia", + label_color="green", + label_bold=True, + label_tooltip="Diameters of the tools, separated by comma.\n" + "The value of the diameter has to use the dot decimals separator.\n" + "Valid values: 0.3, 1.0" + ), + SeparatorOptionUI(), - # Plot CB - self.plot_cb = FCCheckBox(label=_('Plot')) - self.plot_cb.setToolTip( - _("Plot (show) this object.") - ) - self.layout.addWidget(self.plot_cb) + HeadingOptionUI(label_text="Geometry Object Color"), + ColorOptionUI( + option="geometry_plot_line", + label_text="Outline", - grid0 = QtWidgets.QGridLayout() - self.layout.addLayout(grid0) - grid0.setColumnStretch(0, 0) - grid0.setColumnStretch(1, 1) - - # Number of circle steps for circular aperture linear approximation - self.circle_steps_label = QtWidgets.QLabel('%s:' % _("Circle Steps")) - self.circle_steps_label.setToolTip( - _("The number of circle steps for Geometry \n" - "circle and arc shapes linear approximation.") - ) - self.circle_steps_entry = FCSpinner() - self.circle_steps_entry.set_range(0, 999) - - grid0.addWidget(self.circle_steps_label, 1, 0) - grid0.addWidget(self.circle_steps_entry, 1, 1) - - # Tools - self.tools_label = QtWidgets.QLabel("%s:" % _("Tools")) - grid0.addWidget(self.tools_label, 2, 0, 1, 2) - - # Tooldia - tdlabel = QtWidgets.QLabel('%s:' % _('Tools Dia')) - tdlabel.setToolTip( - _("Diameters of the tools, separated by comma.\n" - "The value of the diameter has to use the dot decimals separator.\n" - "Valid values: 0.3, 1.0") - ) - self.cnctooldia_entry = FCEntry() - - grid0.addWidget(tdlabel, 3, 0) - grid0.addWidget(self.cnctooldia_entry, 3, 1) - - separator_line = QtWidgets.QFrame() - separator_line.setFrameShape(QtWidgets.QFrame.HLine) - separator_line.setFrameShadow(QtWidgets.QFrame.Sunken) - grid0.addWidget(separator_line, 9, 0, 1, 2) - - # Geometry Object Color - self.gerber_color_label = QtWidgets.QLabel('%s' % _('Geometry Object Color')) - grid0.addWidget(self.gerber_color_label, 10, 0, 1, 2) - - # Plot Line Color - self.line_color_label = QtWidgets.QLabel('%s:' % _('Outline')) - self.line_color_label.setToolTip( - _("Set the line color for plotted objects.") - ) - self.line_color_entry = FCEntry() - self.line_color_button = QtWidgets.QPushButton() - self.line_color_button.setFixedSize(15, 15) - - self.form_box_child_2 = QtWidgets.QHBoxLayout() - self.form_box_child_2.addWidget(self.line_color_entry) - self.form_box_child_2.addWidget(self.line_color_button) - self.form_box_child_2.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter) - - grid0.addWidget(self.line_color_label, 11, 0) - grid0.addLayout(self.form_box_child_2, 11, 1) - - self.layout.addStretch() - - # Setting plot colors signals - self.line_color_entry.editingFinished.connect(self.on_line_color_entry) - self.line_color_button.clicked.connect(self.on_line_color_button) - - def on_line_color_entry(self): - self.app.defaults['geometry_plot_line'] = self.line_color_entry.get_value()[:7] + 'FF' - self.line_color_button.setStyleSheet("background-color:%s" % str(self.app.defaults['geometry_plot_line'])[:7]) - - def on_line_color_button(self): - current_color = QtGui.QColor(self.app.defaults['geometry_plot_line'][:7]) - # print(current_color) - - c_dialog = QtWidgets.QColorDialog() - plot_line_color = c_dialog.getColor(initial=current_color) - - if plot_line_color.isValid() is False: - return - - self.line_color_button.setStyleSheet("background-color:%s" % str(plot_line_color.name())) - - new_val_line = str(plot_line_color.name()) + str(self.app.defaults['geometry_plot_line'][7:9]) - self.line_color_entry.set_value(new_val_line) + label_tooltip="Set the line color for plotted objects.", + ), + ] diff --git a/flatcamGUI/preferences/geometry/GeometryPreferencesUI.py b/flatcamGUI/preferences/geometry/GeometryPreferencesUI.py index c0e5a10f..c15ff152 100644 --- a/flatcamGUI/preferences/geometry/GeometryPreferencesUI.py +++ b/flatcamGUI/preferences/geometry/GeometryPreferencesUI.py @@ -5,6 +5,13 @@ from flatcamGUI.preferences.geometry.GeometryAdvOptPrefGroupUI import GeometryAd from flatcamGUI.preferences.geometry.GeometryOptPrefGroupUI import GeometryOptPrefGroupUI from flatcamGUI.preferences.geometry.GeometryGenPrefGroupUI import GeometryGenPrefGroupUI +import gettext +import FlatCAMTranslation as fcTranslate +import builtins +fcTranslate.apply_language('strings') +if '_' not in builtins.__dict__: + _ = gettext.gettext + class GeometryPreferencesUI(PreferencesSectionUI): From 805a1567d8f1e28a8212d7bc25794ddcfc87a9fd Mon Sep 17 00:00:00 2001 From: David Robertson Date: Sat, 9 May 2020 16:26:54 +0100 Subject: [PATCH 26/41] Geometry editor prefs --- .../preferences/PreferencesUIManager.py | 4 - .../geometry/GeometryEditorPrefGroupUI.py | 84 +++++++------------ 2 files changed, 29 insertions(+), 59 deletions(-) diff --git a/flatcamGUI/preferences/PreferencesUIManager.py b/flatcamGUI/preferences/PreferencesUIManager.py index 7b5eaec6..5d89e7b7 100644 --- a/flatcamGUI/preferences/PreferencesUIManager.py +++ b/flatcamGUI/preferences/PreferencesUIManager.py @@ -175,10 +175,6 @@ class PreferencesUIManager: "geometry_area_strategy": self.ui.geometry_defaults_form.geometry_adv_opt_group.strategy_radio, "geometry_area_overz": self.ui.geometry_defaults_form.geometry_adv_opt_group.over_z_entry, - # Geometry Editor - "geometry_editor_sel_limit": self.ui.geometry_defaults_form.geometry_editor_group.sel_limit_entry, - "geometry_editor_milling_type": self.ui.geometry_defaults_form.geometry_editor_group.milling_type_radio, - # CNCJob General "cncjob_plot": self.ui.cncjob_defaults_form.cncjob_gen_group.plot_cb, "cncjob_plot_kind": self.ui.cncjob_defaults_form.cncjob_gen_group.cncplot_method_radio, diff --git a/flatcamGUI/preferences/geometry/GeometryEditorPrefGroupUI.py b/flatcamGUI/preferences/geometry/GeometryEditorPrefGroupUI.py index 9c5204ab..fe861c34 100644 --- a/flatcamGUI/preferences/geometry/GeometryEditorPrefGroupUI.py +++ b/flatcamGUI/preferences/geometry/GeometryEditorPrefGroupUI.py @@ -1,67 +1,41 @@ -from PyQt5 import QtWidgets -from PyQt5.QtCore import QSettings - -from flatcamGUI.GUIElements import FCSpinner, RadioSet -from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI +from flatcamGUI.preferences.OptionUI import * +from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI2 import gettext import FlatCAMTranslation as fcTranslate import builtins - fcTranslate.apply_language('strings') if '_' not in builtins.__dict__: _ = gettext.gettext -settings = QSettings("Open Source", "FlatCAM") -if settings.contains("machinist"): - machinist_setting = settings.value('machinist', type=int) -else: - machinist_setting = 0 +class GeometryEditorPrefGroupUI(OptionsGroupUI2): -class GeometryEditorPrefGroupUI(OptionsGroupUI): - def __init__(self, decimals=4, parent=None): - # OptionsGroupUI.__init__(self, "Gerber Adv. Options Preferences", parent=parent) - super(GeometryEditorPrefGroupUI, self).__init__(self, parent=parent) - - self.setTitle(str(_("Geometry Editor"))) + def __init__(self, decimals=4, **kwargs): self.decimals = decimals + super().__init__(**kwargs) + self.setTitle(str(_("Geometry Editor"))) - # Advanced Geometry Parameters - self.param_label = QtWidgets.QLabel("%s:" % _("Parameters")) - self.param_label.setToolTip( - _("A list of Geometry Editor parameters.") - ) - self.layout.addWidget(self.param_label) - - grid0 = QtWidgets.QGridLayout() - self.layout.addLayout(grid0) - - # Selection Limit - self.sel_limit_label = QtWidgets.QLabel('%s:' % _("Selection limit")) - self.sel_limit_label.setToolTip( - _("Set the number of selected geometry\n" - "items above which the utility geometry\n" - "becomes just a selection rectangle.\n" - "Increases the performance when moving a\n" - "large number of geometric elements.") - ) - self.sel_limit_entry = FCSpinner() - self.sel_limit_entry.set_range(0, 9999) - - grid0.addWidget(self.sel_limit_label, 0, 0) - grid0.addWidget(self.sel_limit_entry, 0, 1) - - # Milling Type - milling_type_label = QtWidgets.QLabel('%s:' % _('Milling Type')) - milling_type_label.setToolTip( - _("Milling type:\n" - "- climb / best for precision milling and to reduce tool usage\n" - "- conventional / useful when there is no backlash compensation") - ) - self.milling_type_radio = RadioSet([{'label': _('Climb'), 'value': 'cl'}, - {'label': _('Conventional'), 'value': 'cv'}]) - grid0.addWidget(milling_type_label, 1, 0) - grid0.addWidget(self.milling_type_radio, 1, 1) - - self.layout.addStretch() + def build_options(self) -> [OptionUI]: + return [ + HeadingOptionUI(label_text="Parameters"), + SpinnerOptionUI( + option="geometry_editor_sel_limit", + label_text="Selection limit", + label_tooltip="Set the number of selected geometry\n" + "items above which the utility geometry\n" + "becomes just a selection rectangle.\n" + "Increases the performance when moving a\n" + "large number of geometric elements.", + min_value=0, max_value=9999, step=1 + ), + RadioSetOptionUI( + option="geometry_editor_milling_type", + label_text="Milling Type", + label_tooltip="Milling type:\n" + "- climb / best for precision milling and to reduce tool usage\n" + "- conventional / useful when there is no backlash compensation", + choices=[{'label': _('Climb'), 'value': 'cl'}, + {'label': _('Conventional'), 'value': 'cv'}] + ) + ] \ No newline at end of file From 6a6674c368a79ae728168433b131c339872cbfdf Mon Sep 17 00:00:00 2001 From: David Robertson Date: Sat, 9 May 2020 17:43:53 +0100 Subject: [PATCH 27/41] Geometry options --- .../preferences/PreferencesUIManager.py | 15 - .../geometry/GeometryOptPrefGroupUI.py | 364 ++++++------------ 2 files changed, 126 insertions(+), 253 deletions(-) diff --git a/flatcamGUI/preferences/PreferencesUIManager.py b/flatcamGUI/preferences/PreferencesUIManager.py index 5d89e7b7..c46f374c 100644 --- a/flatcamGUI/preferences/PreferencesUIManager.py +++ b/flatcamGUI/preferences/PreferencesUIManager.py @@ -142,21 +142,6 @@ class PreferencesUIManager: self.ui.excellon_defaults_form.excellon_editor_group.slot_array_circular_angle_entry, - # Geometry Options - "geometry_cutz": self.ui.geometry_defaults_form.geometry_opt_group.cutz_entry, - "geometry_travelz": self.ui.geometry_defaults_form.geometry_opt_group.travelz_entry, - "geometry_feedrate": self.ui.geometry_defaults_form.geometry_opt_group.cncfeedrate_entry, - "geometry_feedrate_z": self.ui.geometry_defaults_form.geometry_opt_group.feedrate_z_entry, - "geometry_spindlespeed": self.ui.geometry_defaults_form.geometry_opt_group.cncspindlespeed_entry, - "geometry_dwell": self.ui.geometry_defaults_form.geometry_opt_group.dwell_cb, - "geometry_dwelltime": self.ui.geometry_defaults_form.geometry_opt_group.dwelltime_entry, - "geometry_ppname_g": self.ui.geometry_defaults_form.geometry_opt_group.pp_geometry_name_cb, - "geometry_toolchange": self.ui.geometry_defaults_form.geometry_opt_group.toolchange_cb, - "geometry_toolchangez": self.ui.geometry_defaults_form.geometry_opt_group.toolchangez_entry, - "geometry_endz": self.ui.geometry_defaults_form.geometry_opt_group.endz_entry, - "geometry_endxy": self.ui.geometry_defaults_form.geometry_opt_group.endxy_entry, - "geometry_depthperpass": self.ui.geometry_defaults_form.geometry_opt_group.depthperpass_entry, - "geometry_multidepth": self.ui.geometry_defaults_form.geometry_opt_group.multidepth_cb, # Geometry Advanced Options "geometry_toolchangexy": self.ui.geometry_defaults_form.geometry_adv_opt_group.toolchangexy_entry, diff --git a/flatcamGUI/preferences/geometry/GeometryOptPrefGroupUI.py b/flatcamGUI/preferences/geometry/GeometryOptPrefGroupUI.py index c2e0f6e2..5a60d21c 100644 --- a/flatcamGUI/preferences/geometry/GeometryOptPrefGroupUI.py +++ b/flatcamGUI/preferences/geometry/GeometryOptPrefGroupUI.py @@ -1,14 +1,13 @@ -from PyQt5 import QtWidgets from PyQt5.QtCore import Qt, QSettings -from flatcamGUI.GUIElements import FCDoubleSpinner, FCCheckBox, OptionalInputSection, FCEntry, FCSpinner, FCComboBox +from flatcamGUI.GUIElements import OptionalInputSection from flatcamGUI.preferences import machinist_setting -from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI +from flatcamGUI.preferences.OptionUI import * +from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI2 import gettext import FlatCAMTranslation as fcTranslate import builtins - fcTranslate.apply_language('strings') if '_' not in builtins.__dict__: _ = gettext.gettext @@ -20,246 +19,135 @@ else: machinist_setting = 0 -class GeometryOptPrefGroupUI(OptionsGroupUI): - def __init__(self, decimals=4, parent=None): - # OptionsGroupUI.__init__(self, "Geometry Options Preferences", parent=parent) - super(GeometryOptPrefGroupUI, self).__init__(self, parent=parent) +class GeometryOptPrefGroupUI(OptionsGroupUI2): - self.setTitle(str(_("Geometry Options"))) + def __init__(self, decimals=4, **kwargs): self.decimals = decimals + super().__init__(**kwargs) + self.setTitle(str(_("Geometry Options"))) + self.pp_geometry_name_cb = self.option_dict()["geometry_ppname_g"].get_field() - # ------------------------------ - # ## Create CNC Job - # ------------------------------ - self.cncjob_label = QtWidgets.QLabel('%s:' % _('Create CNC Job')) - self.cncjob_label.setToolTip( - _("Create a CNC Job object\n" - "tracing the contours of this\n" - "Geometry object.") - ) - self.layout.addWidget(self.cncjob_label) - - grid1 = QtWidgets.QGridLayout() - self.layout.addLayout(grid1) - grid1.setColumnStretch(0, 0) - grid1.setColumnStretch(1, 1) - - # Cut Z - cutzlabel = QtWidgets.QLabel('%s:' % _('Cut Z')) - cutzlabel.setToolTip( - _("Cutting depth (negative)\n" - "below the copper surface.") - ) - self.cutz_entry = FCDoubleSpinner() - - if machinist_setting == 0: - self.cutz_entry.set_range(-9999.9999, 0.0000) - else: - self.cutz_entry.set_range(-9999.9999, 9999.9999) - - self.cutz_entry.set_precision(self.decimals) - self.cutz_entry.setSingleStep(0.1) - self.cutz_entry.setWrapping(True) - - grid1.addWidget(cutzlabel, 0, 0) - grid1.addWidget(self.cutz_entry, 0, 1) - - # Multidepth CheckBox - self.multidepth_cb = FCCheckBox(label=_('Multi-Depth')) - self.multidepth_cb.setToolTip( - _( - "Use multiple passes to limit\n" - "the cut depth in each pass. Will\n" - "cut multiple times until Cut Z is\n" - "reached." - ) - ) - grid1.addWidget(self.multidepth_cb, 1, 0) - - # Depth/pass - dplabel = QtWidgets.QLabel('%s:' % _('Depth/Pass')) - dplabel.setToolTip( - _("The depth to cut on each pass,\n" - "when multidepth is enabled.\n" - "It has positive value although\n" - "it is a fraction from the depth\n" - "which has negative value.") - ) - - self.depthperpass_entry = FCDoubleSpinner() - self.depthperpass_entry.set_range(0, 99999) - self.depthperpass_entry.set_precision(self.decimals) - self.depthperpass_entry.setSingleStep(0.1) - self.depthperpass_entry.setWrapping(True) - - grid1.addWidget(dplabel, 2, 0) - grid1.addWidget(self.depthperpass_entry, 2, 1) - + self.multidepth_cb = self.option_dict()["geometry_multidepth"].get_field() + self.depthperpass_entry = self.option_dict()["geometry_depthperpass"].get_field() self.ois_multidepth = OptionalInputSection(self.multidepth_cb, [self.depthperpass_entry]) - # Travel Z - travelzlabel = QtWidgets.QLabel('%s:' % _('Travel Z')) - travelzlabel.setToolTip( - _("Height of the tool when\n" - "moving without cutting.") - ) - self.travelz_entry = FCDoubleSpinner() - - if machinist_setting == 0: - self.travelz_entry.set_range(0.0001, 9999.9999) - else: - self.travelz_entry.set_range(-9999.9999, 9999.9999) - - self.travelz_entry.set_precision(self.decimals) - self.travelz_entry.setSingleStep(0.1) - self.travelz_entry.setWrapping(True) - - grid1.addWidget(travelzlabel, 3, 0) - grid1.addWidget(self.travelz_entry, 3, 1) - - # Tool change: - self.toolchange_cb = FCCheckBox('%s' % _("Tool change")) - self.toolchange_cb.setToolTip( - _( - "Include tool-change sequence\n" - "in the Machine Code (Pause for tool change)." - ) - ) - grid1.addWidget(self.toolchange_cb, 4, 0, 1, 2) - - # Toolchange Z - toolchangezlabel = QtWidgets.QLabel('%s:' % _('Toolchange Z')) - toolchangezlabel.setToolTip( - _( - "Z-axis position (height) for\n" - "tool change." - ) - ) - self.toolchangez_entry = FCDoubleSpinner() - - if machinist_setting == 0: - self.toolchangez_entry.set_range(0.000, 9999.9999) - else: - self.toolchangez_entry.set_range(-9999.9999, 9999.9999) - - self.toolchangez_entry.set_precision(self.decimals) - self.toolchangez_entry.setSingleStep(0.1) - self.toolchangez_entry.setWrapping(True) - - grid1.addWidget(toolchangezlabel, 5, 0) - grid1.addWidget(self.toolchangez_entry, 5, 1) - - # End move Z - endz_label = QtWidgets.QLabel('%s:' % _('End move Z')) - endz_label.setToolTip( - _("Height of the tool after\n" - "the last move at the end of the job.") - ) - self.endz_entry = FCDoubleSpinner() - - if machinist_setting == 0: - self.endz_entry.set_range(0.000, 9999.9999) - else: - self.endz_entry.set_range(-9999.9999, 9999.9999) - - self.endz_entry.set_precision(self.decimals) - self.endz_entry.setSingleStep(0.1) - self.endz_entry.setWrapping(True) - - grid1.addWidget(endz_label, 6, 0) - grid1.addWidget(self.endz_entry, 6, 1) - - # End Move X,Y - endmove_xy_label = QtWidgets.QLabel('%s:' % _('End move X,Y')) - endmove_xy_label.setToolTip( - _("End move X,Y position. In format (x,y).\n" - "If no value is entered then there is no move\n" - "on X,Y plane at the end of the job.") - ) - self.endxy_entry = FCEntry() - - grid1.addWidget(endmove_xy_label, 7, 0) - grid1.addWidget(self.endxy_entry, 7, 1) - - # Feedrate X-Y - frlabel = QtWidgets.QLabel('%s:' % _('Feedrate X-Y')) - frlabel.setToolTip( - _("Cutting speed in the XY\n" - "plane in units per minute") - ) - self.cncfeedrate_entry = FCDoubleSpinner() - self.cncfeedrate_entry.set_range(0, 99999.9999) - self.cncfeedrate_entry.set_precision(self.decimals) - self.cncfeedrate_entry.setSingleStep(0.1) - self.cncfeedrate_entry.setWrapping(True) - - grid1.addWidget(frlabel, 8, 0) - grid1.addWidget(self.cncfeedrate_entry, 8, 1) - - # Feedrate Z (Plunge) - frz_label = QtWidgets.QLabel('%s:' % _('Feedrate Z')) - frz_label.setToolTip( - _("Cutting speed in the XY\n" - "plane in units per minute.\n" - "It is called also Plunge.") - ) - self.feedrate_z_entry = FCDoubleSpinner() - self.feedrate_z_entry.set_range(0, 99999.9999) - self.feedrate_z_entry.set_precision(self.decimals) - self.feedrate_z_entry.setSingleStep(0.1) - self.feedrate_z_entry.setWrapping(True) - - grid1.addWidget(frz_label, 9, 0) - grid1.addWidget(self.feedrate_z_entry, 9, 1) - - # Spindle Speed - spdlabel = QtWidgets.QLabel('%s:' % _('Spindle speed')) - spdlabel.setToolTip( - _( - "Speed of the spindle in RPM (optional).\n" - "If LASER preprocessor is used,\n" - "this value is the power of laser." - ) - ) - self.cncspindlespeed_entry = FCSpinner() - self.cncspindlespeed_entry.set_range(0, 1000000) - self.cncspindlespeed_entry.set_step(100) - - grid1.addWidget(spdlabel, 10, 0) - grid1.addWidget(self.cncspindlespeed_entry, 10, 1) - - # Dwell - self.dwell_cb = FCCheckBox(label='%s' % _('Enable Dwell')) - self.dwell_cb.setToolTip( - _("Pause to allow the spindle to reach its\n" - "speed before cutting.") - ) - dwelltime = QtWidgets.QLabel('%s:' % _('Duration')) - dwelltime.setToolTip( - _("Number of time units for spindle to dwell.") - ) - self.dwelltime_entry = FCDoubleSpinner() - self.dwelltime_entry.set_range(0, 99999) - self.dwelltime_entry.set_precision(self.decimals) - self.dwelltime_entry.setSingleStep(0.1) - self.dwelltime_entry.setWrapping(True) - - grid1.addWidget(self.dwell_cb, 11, 0) - grid1.addWidget(dwelltime, 12, 0) - grid1.addWidget(self.dwelltime_entry, 12, 1) - + self.dwell_cb = self.option_dict()["geometry_dwell"].get_field() + self.dwelltime_entry = self.option_dict()["geometry_dwelltime"].get_field() self.ois_dwell = OptionalInputSection(self.dwell_cb, [self.dwelltime_entry]) - # preprocessor selection - pp_label = QtWidgets.QLabel('%s:' % _("Preprocessor")) - pp_label.setToolTip( - _("The Preprocessor file that dictates\n" - "the Machine Code (like GCode, RML, HPGL) output.") - ) - self.pp_geometry_name_cb = FCComboBox() - self.pp_geometry_name_cb.setFocusPolicy(Qt.StrongFocus) + def build_options(self) -> [OptionUI]: + return [ + HeadingOptionUI( + label_text="Create CNC Job", + label_tooltip="Create a CNC Job object\n" + "tracing the contours of this\n" + "Geometry object." + ), + DoubleSpinnerOptionUI( + option="geometry_cutz", + label_text="Cut Z", + label_tooltip="Cutting depth (negative)\n" + "below the copper surface.", + min_value=-9999.9999, max_value=(9999.999 if machinist_setting else 0.0), + decimals=self.decimals, step=0.1 + ), + CheckboxOptionUI( + option="geometry_multidepth", + label_text="Multi-Depth", + label_tooltip="Use multiple passes to limit\n" + "the cut depth in each pass. Will\n" + "cut multiple times until Cut Z is\n" + "reached." + ), + DoubleSpinnerOptionUI( + option="geometry_depthperpass", + label_text="Depth/Pass", + label_tooltip="The depth to cut on each pass,\n" + "when multidepth is enabled.\n" + "It has positive value although\n" + "it is a fraction from the depth\n" + "which has negative value.", + min_value=0, max_value=99999, step=0.1, decimals=self.decimals - grid1.addWidget(pp_label, 13, 0) - grid1.addWidget(self.pp_geometry_name_cb, 13, 1) + ), + DoubleSpinnerOptionUI( + option="geometry_travelz", + label_text="Travel Z", + label_tooltip="Height of the tool when\n" + "moving without cutting.", + min_value=(-9999.9999 if machinist_setting else 0.0001), max_value=9999.9999, + step=0.1, decimals=self.decimals + ), + CheckboxOptionUI( + option="geometry_toolchange", + label_text="Tool change", + label_tooltip="Include tool-change sequence\n" + "in the Machine Code (Pause for tool change)." + ), + DoubleSpinnerOptionUI( + option="geometry_toolchangez", + label_text="Toolchange Z", + label_tooltip="Z-axis position (height) for\n" + "tool change.", + min_value=(-9999.9999 if machinist_setting else 0.0), max_value=9999.9999, + step=0.1, decimals=self.decimals + ), + DoubleSpinnerOptionUI( + option="geometry_endz", + label_text="End move Z", + label_tooltip="Height of the tool after\n" + "the last move at the end of the job.", + min_value=(-9999.9999 if machinist_setting else 0.0), max_value=9999.9999, + step=0.1, decimals=self.decimals + ), + LineEntryOptionUI( + option="geometry_endxy", + label_text="End move X,Y", + label_tooltip="End move X,Y position. In format (x,y).\n" + "If no value is entered then there is no move\n" + "on X,Y plane at the end of the job." + ), + DoubleSpinnerOptionUI( + option="geometry_feedrate", + label_text="Feedrate X-Y", + label_tooltip="Cutting speed in the XY\n" + "plane in units per minute", + min_value=0, max_value=99999.9999, step=0.1, decimals=self.decimals + ), + DoubleSpinnerOptionUI( + option="geometry_feedrate_z", + label_text="Feedrate Z", + label_tooltip="Cutting speed in the XY\n" + "plane in units per minute.\n" + "It is called also Plunge.", + min_value=0, max_value=99999.9999, step=0.1, decimals=self.decimals + ), + SpinnerOptionUI( + option="geometry_spindlespeed", + label_text="Spindle speed", + label_tooltip="Speed of the spindle in RPM (optional).\n" + "If LASER preprocessor is used,\n" + "this value is the power of laser.", + min_value=0, max_value=1000000, step=100 + ), + CheckboxOptionUI( + option="geometry_dwell", + label_text="Enable Dwell", + label_tooltip="Pause to allow the spindle to reach its\n" + "speed before cutting." + ), + DoubleSpinnerOptionUI( + option="geometry_dwelltime", + label_text="Duration", + label_tooltip="Number of time units for spindle to dwell.", + min_value=0, max_value=999999, step=0.5, decimals=self.decimals + ), + ComboboxOptionUI( + option="geometry_ppname_g", + label_text="Preprocessor", + label_tooltip="The Preprocessor file that dictates\n" + "the Machine Code (like GCode, RML, HPGL) output.", + choices=[] # Populated in App (FIXME) + ) + ] - self.layout.addStretch() From 2e54dc6920e165a9924addde61f16e326634de0d Mon Sep 17 00:00:00 2001 From: David Robertson Date: Sat, 9 May 2020 18:21:50 +0100 Subject: [PATCH 28/41] Geometry advanced options --- flatcamGUI/preferences/OptionUI.py | 11 +- .../preferences/PreferencesUIManager.py | 18 - .../geometry/GeometryAdvOptPrefGroupUI.py | 367 +++++++----------- .../geometry/GeometryOptPrefGroupUI.py | 2 +- 4 files changed, 144 insertions(+), 254 deletions(-) diff --git a/flatcamGUI/preferences/OptionUI.py b/flatcamGUI/preferences/OptionUI.py index 1fb34b72..90512c04 100644 --- a/flatcamGUI/preferences/OptionUI.py +++ b/flatcamGUI/preferences/OptionUI.py @@ -2,7 +2,7 @@ from typing import Union, Sequence, List from PyQt5 import QtWidgets from flatcamGUI.GUIElements import RadioSet, FCCheckBox, FCButton, FCComboBox, FCEntry, FCSpinner, FCColorEntry, \ - FCSliderWithSpinner, FCDoubleSpinner + FCSliderWithSpinner, FCDoubleSpinner, FloatEntry import gettext import FlatCAMTranslation as fcTranslate @@ -64,12 +64,15 @@ class BasicOptionUI(OptionUI): class LineEntryOptionUI(BasicOptionUI): - def __init__(self, option: str, label_text: str, **kwargs): - super().__init__(option=option, label_text=label_text, **kwargs) - def build_entry_widget(self) -> QtWidgets.QWidget: return FCEntry() +# Not sure why this is needed over DoubleSpinnerOptionUI +class FloatEntryOptionUI(BasicOptionUI): + def build_entry_widget(self) -> QtWidgets.QWidget: + return FloatEntry() + + class RadioSetOptionUI(BasicOptionUI): diff --git a/flatcamGUI/preferences/PreferencesUIManager.py b/flatcamGUI/preferences/PreferencesUIManager.py index c46f374c..b21a0c71 100644 --- a/flatcamGUI/preferences/PreferencesUIManager.py +++ b/flatcamGUI/preferences/PreferencesUIManager.py @@ -142,24 +142,6 @@ class PreferencesUIManager: self.ui.excellon_defaults_form.excellon_editor_group.slot_array_circular_angle_entry, - - # Geometry Advanced Options - "geometry_toolchangexy": self.ui.geometry_defaults_form.geometry_adv_opt_group.toolchangexy_entry, - "geometry_startz": self.ui.geometry_defaults_form.geometry_adv_opt_group.gstartz_entry, - "geometry_feedrate_rapid": self.ui.geometry_defaults_form.geometry_adv_opt_group.feedrate_rapid_entry, - "geometry_extracut": self.ui.geometry_defaults_form.geometry_adv_opt_group.extracut_cb, - "geometry_extracut_length": self.ui.geometry_defaults_form.geometry_adv_opt_group.e_cut_entry, - "geometry_z_pdepth": self.ui.geometry_defaults_form.geometry_adv_opt_group.pdepth_entry, - "geometry_feedrate_probe": self.ui.geometry_defaults_form.geometry_adv_opt_group.feedrate_probe_entry, - "geometry_spindledir": self.ui.geometry_defaults_form.geometry_adv_opt_group.spindledir_radio, - "geometry_f_plunge": self.ui.geometry_defaults_form.geometry_adv_opt_group.fplunge_cb, - "geometry_segx": self.ui.geometry_defaults_form.geometry_adv_opt_group.segx_entry, - "geometry_segy": self.ui.geometry_defaults_form.geometry_adv_opt_group.segy_entry, - "geometry_area_exclusion": self.ui.geometry_defaults_form.geometry_adv_opt_group.exclusion_cb, - "geometry_area_shape": self.ui.geometry_defaults_form.geometry_adv_opt_group.area_shape_radio, - "geometry_area_strategy": self.ui.geometry_defaults_form.geometry_adv_opt_group.strategy_radio, - "geometry_area_overz": self.ui.geometry_defaults_form.geometry_adv_opt_group.over_z_entry, - # CNCJob General "cncjob_plot": self.ui.cncjob_defaults_form.cncjob_gen_group.plot_cb, "cncjob_plot_kind": self.ui.cncjob_defaults_form.cncjob_gen_group.cncplot_method_radio, diff --git a/flatcamGUI/preferences/geometry/GeometryAdvOptPrefGroupUI.py b/flatcamGUI/preferences/geometry/GeometryAdvOptPrefGroupUI.py index 1496fb96..57993400 100644 --- a/flatcamGUI/preferences/geometry/GeometryAdvOptPrefGroupUI.py +++ b/flatcamGUI/preferences/geometry/GeometryAdvOptPrefGroupUI.py @@ -1,245 +1,150 @@ -from PyQt5 import QtWidgets -from PyQt5.QtCore import QSettings - -from flatcamGUI.GUIElements import FCEntry, FloatEntry, FCDoubleSpinner, FCCheckBox, RadioSet, FCLabel -from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI +from flatcamGUI.preferences.OptionUI import * +from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI2 import gettext import FlatCAMTranslation as fcTranslate import builtins - fcTranslate.apply_language('strings') if '_' not in builtins.__dict__: _ = gettext.gettext -settings = QSettings("Open Source", "FlatCAM") -if settings.contains("machinist"): - machinist_setting = settings.value('machinist', type=int) -else: - machinist_setting = 0 +class GeometryAdvOptPrefGroupUI(OptionsGroupUI2): -class GeometryAdvOptPrefGroupUI(OptionsGroupUI): - def __init__(self, decimals=4, parent=None): - super(GeometryAdvOptPrefGroupUI, self).__init__(self, parent=parent) - - self.setTitle(str(_("Geometry Adv. Options"))) + def __init__(self, decimals=4, **kwargs): self.decimals = decimals + super().__init__(**kwargs) + self.setTitle(str(_("Geometry Adv. Options"))) - # ------------------------------ - # ## Advanced Options - # ------------------------------ - self.geo_label = QtWidgets.QLabel('%s:' % _('Advanced Options')) - self.geo_label.setToolTip( - _("A list of Geometry advanced parameters.\n" - "Those parameters are available only for\n" - "Advanced App. Level.") - ) - self.layout.addWidget(self.geo_label) + def build_options(self) -> [OptionUI]: + return [ + HeadingOptionUI( + label_text="Advanced Options", + label_tooltip="A list of Geometry advanced parameters.\n" + "Those parameters are available only for\n" + "Advanced App. Level." + ), + LineEntryOptionUI( + option="geometry_toolchangexy", + label_text="Toolchange X-Y", + label_tooltip="Toolchange X,Y position." + ), + FloatEntryOptionUI( + option="geometry_startz", + label_text="Start Z", + label_tooltip="Height of the tool just after starting the work.\n" + "Delete the value if you don't need this feature." + ), + DoubleSpinnerOptionUI( + option="geometry_feedrate_rapid", + label_text="Feedrate Rapids", + label_tooltip="Cutting speed in the XY plane\n" + "(in units per minute).\n" + "This is for the rapid move G00.\n" + "It is useful only for Marlin,\n" + "ignore for any other cases.", + min_value=0, max_value=99999.9999, step=10, decimals=self.decimals + ), + CheckboxOptionUI( + option="geometry_extracut", + label_text="Re-cut", + label_tooltip="In order to remove possible\n" + "copper leftovers where first cut\n" + "meet with last cut, we generate an\n" + "extended cut over the first cut section." + ), + DoubleSpinnerOptionUI( + option="geometry_extracut_length", + label_text="Re-cut length", + label_tooltip="In order to remove possible\n" + "copper leftovers where first cut\n" + "meet with last cut, we generate an\n" + "extended cut over the first cut section.", + min_value=0, max_value=99999, step=0.1, decimals=self.decimals + ), + DoubleSpinnerOptionUI( + option="geometry_z_pdepth", + label_text="Probe Z depth", + label_tooltip="The maximum depth that the probe is allowed\n" + "to probe. Negative value, in current units.", + min_value=-99999, max_value=0.0, step=0.1, decimals=self.decimals + ), + DoubleSpinnerOptionUI( + option="geometry_feedrate_probe", + label_text="Feedrate Probe", + label_tooltip="The feedrate used while the probe is probing.", + min_value=0, max_value=99999.9999, step=0.1, decimals=self.decimals + ), + RadioSetOptionUI( + option="geometry_spindledir", + label_text="Spindle direction", + label_tooltip="This sets the direction that the spindle is rotating.\n" + "It can be either:\n" + "- CW = clockwise or\n" + "- CCW = counter clockwise", + choices=[{'label': _('CW'), 'value': 'CW'}, + {'label': _('CCW'), 'value': 'CCW'}] + ), + CheckboxOptionUI( + option="geometry_f_plunge", + label_text="Fast Plunge", + label_tooltip="By checking this, the vertical move from\n" + "Z_Toolchange to Z_move is done with G0,\n" + "meaning the fastest speed available.\n" + "WARNING: the move is done at Toolchange X,Y coords." + ), + DoubleSpinnerOptionUI( + option="geometry_segx", + label_text="Segment X size", + label_tooltip="The size of the trace segment on the X axis.\n" + "Useful for auto-leveling.\n" + "A value of 0 means no segmentation on the X axis.", + min_value=0, max_value=99999, step=0.1, decimals=self.decimals + ), + DoubleSpinnerOptionUI( + option="geometry_segy", + label_text="Segment Y size", + label_tooltip="The size of the trace segment on the Y axis.\n" + "Useful for auto-leveling.\n" + "A value of 0 means no segmentation on the Y axis.", + min_value=0, max_value=99999, step=0.1, decimals=self.decimals + ), - grid1 = QtWidgets.QGridLayout() - self.layout.addLayout(grid1) - - # Toolchange X,Y - toolchange_xy_label = QtWidgets.QLabel('%s:' % _('Toolchange X-Y')) - toolchange_xy_label.setToolTip( - _("Toolchange X,Y position.") - ) - grid1.addWidget(toolchange_xy_label, 1, 0) - self.toolchangexy_entry = FCEntry() - grid1.addWidget(self.toolchangexy_entry, 1, 1) - - # Start move Z - startzlabel = QtWidgets.QLabel('%s:' % _('Start Z')) - startzlabel.setToolTip( - _("Height of the tool just after starting the work.\n" - "Delete the value if you don't need this feature.") - ) - grid1.addWidget(startzlabel, 2, 0) - self.gstartz_entry = FloatEntry() - grid1.addWidget(self.gstartz_entry, 2, 1) - - # Feedrate rapids - fr_rapid_label = QtWidgets.QLabel('%s:' % _('Feedrate Rapids')) - fr_rapid_label.setToolTip( - _("Cutting speed in the XY plane\n" - "(in units per minute).\n" - "This is for the rapid move G00.\n" - "It is useful only for Marlin,\n" - "ignore for any other cases.") - ) - self.feedrate_rapid_entry = FCDoubleSpinner() - self.feedrate_rapid_entry.set_range(0, 99999.9999) - self.feedrate_rapid_entry.set_precision(self.decimals) - self.feedrate_rapid_entry.setSingleStep(0.1) - self.feedrate_rapid_entry.setWrapping(True) - - grid1.addWidget(fr_rapid_label, 4, 0) - grid1.addWidget(self.feedrate_rapid_entry, 4, 1) - - # End move extra cut - self.extracut_cb = FCCheckBox('%s' % _('Re-cut')) - self.extracut_cb.setToolTip( - _("In order to remove possible\n" - "copper leftovers where first cut\n" - "meet with last cut, we generate an\n" - "extended cut over the first cut section.") - ) - - self.e_cut_entry = FCDoubleSpinner() - self.e_cut_entry.set_range(0, 99999) - self.e_cut_entry.set_precision(self.decimals) - self.e_cut_entry.setSingleStep(0.1) - self.e_cut_entry.setWrapping(True) - self.e_cut_entry.setToolTip( - _("In order to remove possible\n" - "copper leftovers where first cut\n" - "meet with last cut, we generate an\n" - "extended cut over the first cut section.") - ) - grid1.addWidget(self.extracut_cb, 5, 0) - grid1.addWidget(self.e_cut_entry, 5, 1) - - # Probe depth - self.pdepth_label = QtWidgets.QLabel('%s:' % _("Probe Z depth")) - self.pdepth_label.setToolTip( - _("The maximum depth that the probe is allowed\n" - "to probe. Negative value, in current units.") - ) - self.pdepth_entry = FCDoubleSpinner() - self.pdepth_entry.set_range(-99999, 0.0000) - self.pdepth_entry.set_precision(self.decimals) - self.pdepth_entry.setSingleStep(0.1) - self.pdepth_entry.setWrapping(True) - - grid1.addWidget(self.pdepth_label, 6, 0) - grid1.addWidget(self.pdepth_entry, 6, 1) - - # Probe feedrate - self.feedrate_probe_label = QtWidgets.QLabel('%s:' % _("Feedrate Probe")) - self.feedrate_probe_label.setToolTip( - _("The feedrate used while the probe is probing.") - ) - self.feedrate_probe_entry = FCDoubleSpinner() - self.feedrate_probe_entry.set_range(0, 99999.9999) - self.feedrate_probe_entry.set_precision(self.decimals) - self.feedrate_probe_entry.setSingleStep(0.1) - self.feedrate_probe_entry.setWrapping(True) - - grid1.addWidget(self.feedrate_probe_label, 7, 0) - grid1.addWidget(self.feedrate_probe_entry, 7, 1) - - # Spindle direction - spindle_dir_label = QtWidgets.QLabel('%s:' % _('Spindle direction')) - spindle_dir_label.setToolTip( - _("This sets the direction that the spindle is rotating.\n" - "It can be either:\n" - "- CW = clockwise or\n" - "- CCW = counter clockwise") - ) - - self.spindledir_radio = RadioSet([{'label': _('CW'), 'value': 'CW'}, - {'label': _('CCW'), 'value': 'CCW'}]) - grid1.addWidget(spindle_dir_label, 8, 0) - grid1.addWidget(self.spindledir_radio, 8, 1) - - # Fast Move from Z Toolchange - self.fplunge_cb = FCCheckBox('%s' % _('Fast Plunge')) - self.fplunge_cb.setToolTip( - _("By checking this, the vertical move from\n" - "Z_Toolchange to Z_move is done with G0,\n" - "meaning the fastest speed available.\n" - "WARNING: the move is done at Toolchange X,Y coords.") - ) - grid1.addWidget(self.fplunge_cb, 9, 0, 1, 2) - - # Size of trace segment on X axis - segx_label = QtWidgets.QLabel('%s:' % _("Segment X size")) - segx_label.setToolTip( - _("The size of the trace segment on the X axis.\n" - "Useful for auto-leveling.\n" - "A value of 0 means no segmentation on the X axis.") - ) - self.segx_entry = FCDoubleSpinner() - self.segx_entry.set_range(0, 99999) - self.segx_entry.set_precision(self.decimals) - self.segx_entry.setSingleStep(0.1) - self.segx_entry.setWrapping(True) - - grid1.addWidget(segx_label, 10, 0) - grid1.addWidget(self.segx_entry, 10, 1) - - # Size of trace segment on Y axis - segy_label = QtWidgets.QLabel('%s:' % _("Segment Y size")) - segy_label.setToolTip( - _("The size of the trace segment on the Y axis.\n" - "Useful for auto-leveling.\n" - "A value of 0 means no segmentation on the Y axis.") - ) - self.segy_entry = FCDoubleSpinner() - self.segy_entry.set_range(0, 99999) - self.segy_entry.set_precision(self.decimals) - self.segy_entry.setSingleStep(0.1) - self.segy_entry.setWrapping(True) - - grid1.addWidget(segy_label, 11, 0) - grid1.addWidget(self.segy_entry, 11, 1) - - # ----------------------------- - # --- Area Exclusion ---------- - # ----------------------------- - self.adv_label = QtWidgets.QLabel('%s:' % _('Area Exclusion')) - self.adv_label.setToolTip( - _("Area exclusion parameters.\n" - "Those parameters are available only for\n" - "Advanced App. Level.") - ) - grid1.addWidget(self.adv_label, 12, 0, 1, 2) - - # Exclusion Area CB - self.exclusion_cb = FCCheckBox('%s:' % _("Exclusion areas")) - self.exclusion_cb.setToolTip( - _( - "Include exclusion areas.\n" - "In those areas the travel of the tools\n" - "is forbidden." + HeadingOptionUI( + label_text="Area Exclusion", + label_tooltip="Area exclusion parameters.\n" + "Those parameters are available only for\n" + "Advanced App. Level." + ), + CheckboxOptionUI( + option="geometry_area_exclusion", + label_text="Exclusion areas", + label_tooltip="Include exclusion areas.\n" + "In those areas the travel of the tools\n" + "is forbidden." + ), + RadioSetOptionUI( + option="geometry_area_shape", + label_text="Shape", + label_tooltip="The kind of selection shape used for area selection.", + choices=[{'label': _("Square"), 'value': 'square'}, + {'label': _("Polygon"), 'value': 'polygon'}] + ), + RadioSetOptionUI( + option="geometry_area_strategy", + label_text="Strategy", + label_tooltip="The strategy followed when encountering an exclusion area.\n" + "Can be:\n" + "- Over -> when encountering the area, the tool will go to a set height\n" + "- Around -> will avoid the exclusion area by going around the area", + choices=[{'label': _('Over'), 'value': 'over'}, + {'label': _('Around'), 'value': 'around'}] + ), + DoubleSpinnerOptionUI( + option="geometry_area_overz", + label_text="Over Z", + label_tooltip="The height Z to which the tool will rise in order to avoid\n" + "an interdiction area.", + min_value=0.0, max_value=9999.9999, step=0.5, decimals=self.decimals ) - ) - grid1.addWidget(self.exclusion_cb, 13, 0, 1, 2) - - # Area Selection shape - self.area_shape_label = QtWidgets.QLabel('%s:' % _("Shape")) - self.area_shape_label.setToolTip( - _("The kind of selection shape used for area selection.") - ) - - self.area_shape_radio = RadioSet([{'label': _("Square"), 'value': 'square'}, - {'label': _("Polygon"), 'value': 'polygon'}]) - - grid1.addWidget(self.area_shape_label, 14, 0) - grid1.addWidget(self.area_shape_radio, 14, 1) - - # Chose Strategy - self.strategy_label = FCLabel('%s:' % _("Strategy")) - self.strategy_label.setToolTip(_("The strategy followed when encountering an exclusion area.\n" - "Can be:\n" - "- Over -> when encountering the area, the tool will go to a set height\n" - "- Around -> will avoid the exclusion area by going around the area")) - self.strategy_radio = RadioSet([{'label': _('Over'), 'value': 'over'}, - {'label': _('Around'), 'value': 'around'}]) - - grid1.addWidget(self.strategy_label, 15, 0) - grid1.addWidget(self.strategy_radio, 15, 1) - - # Over Z - self.over_z_label = FCLabel('%s:' % _("Over Z")) - self.over_z_label.setToolTip(_("The height Z to which the tool will rise in order to avoid\n" - "an interdiction area.")) - self.over_z_entry = FCDoubleSpinner() - self.over_z_entry.set_range(0.000, 9999.9999) - self.over_z_entry.set_precision(self.decimals) - - grid1.addWidget(self.over_z_label, 18, 0) - grid1.addWidget(self.over_z_entry, 18, 1) - - self.layout.addStretch() + ] diff --git a/flatcamGUI/preferences/geometry/GeometryOptPrefGroupUI.py b/flatcamGUI/preferences/geometry/GeometryOptPrefGroupUI.py index 5a60d21c..102a9273 100644 --- a/flatcamGUI/preferences/geometry/GeometryOptPrefGroupUI.py +++ b/flatcamGUI/preferences/geometry/GeometryOptPrefGroupUI.py @@ -1,4 +1,4 @@ -from PyQt5.QtCore import Qt, QSettings +from PyQt5.QtCore import QSettings from flatcamGUI.GUIElements import OptionalInputSection from flatcamGUI.preferences import machinist_setting From cac97f585a71fdb6c777ccf233738be82fb9348d Mon Sep 17 00:00:00 2001 From: David Robertson Date: Sat, 9 May 2020 18:25:02 +0100 Subject: [PATCH 29/41] cleanup --- .../preferences/geometry/GeometryPreferencesUI.py | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/flatcamGUI/preferences/geometry/GeometryPreferencesUI.py b/flatcamGUI/preferences/geometry/GeometryPreferencesUI.py index c15ff152..643b606d 100644 --- a/flatcamGUI/preferences/geometry/GeometryPreferencesUI.py +++ b/flatcamGUI/preferences/geometry/GeometryPreferencesUI.py @@ -17,18 +17,16 @@ class GeometryPreferencesUI(PreferencesSectionUI): def __init__(self, decimals, **kwargs): self.decimals = decimals - self.geometry_gen_group = GeometryGenPrefGroupUI(decimals=self.decimals) + # FIXME: remove the need for external access to geometry_opt_group self.geometry_opt_group = GeometryOptPrefGroupUI(decimals=self.decimals) - self.geometry_adv_opt_group = GeometryAdvOptPrefGroupUI(decimals=self.decimals) - self.geometry_editor_group = GeometryEditorPrefGroupUI(decimals=self.decimals) super().__init__(**kwargs) def build_groups(self) -> [OptionsGroupUI]: return [ - self.geometry_gen_group, + GeometryGenPrefGroupUI(decimals=self.decimals), self.geometry_opt_group, - self.geometry_adv_opt_group, - self.geometry_editor_group + GeometryAdvOptPrefGroupUI(decimals=self.decimals), + GeometryEditorPrefGroupUI(decimals=self.decimals) ] def get_tab_id(self): From 17eaa6e8ad5d1dff8774f23daddf84595fb62a0c Mon Sep 17 00:00:00 2001 From: David Robertson Date: Sat, 9 May 2020 18:53:42 +0100 Subject: [PATCH 30/41] CNC job general prefs --- .../preferences/PreferencesUIManager.py | 43 -- .../cncjob/CNCJobGenPrefGroupUI.py | 497 +++++------------- .../preferences/cncjob/CNCJobPreferencesUI.py | 10 +- 3 files changed, 133 insertions(+), 417 deletions(-) diff --git a/flatcamGUI/preferences/PreferencesUIManager.py b/flatcamGUI/preferences/PreferencesUIManager.py index b21a0c71..be279f62 100644 --- a/flatcamGUI/preferences/PreferencesUIManager.py +++ b/flatcamGUI/preferences/PreferencesUIManager.py @@ -142,21 +142,6 @@ class PreferencesUIManager: self.ui.excellon_defaults_form.excellon_editor_group.slot_array_circular_angle_entry, - # CNCJob General - "cncjob_plot": self.ui.cncjob_defaults_form.cncjob_gen_group.plot_cb, - "cncjob_plot_kind": self.ui.cncjob_defaults_form.cncjob_gen_group.cncplot_method_radio, - "cncjob_annotation": self.ui.cncjob_defaults_form.cncjob_gen_group.annotation_cb, - - "cncjob_tooldia": self.ui.cncjob_defaults_form.cncjob_gen_group.tooldia_entry, - "cncjob_coords_type": self.ui.cncjob_defaults_form.cncjob_gen_group.coords_type_radio, - "cncjob_coords_decimals": self.ui.cncjob_defaults_form.cncjob_gen_group.coords_dec_entry, - "cncjob_fr_decimals": self.ui.cncjob_defaults_form.cncjob_gen_group.fr_dec_entry, - "cncjob_steps_per_circle": self.ui.cncjob_defaults_form.cncjob_gen_group.steps_per_circle_entry, - "cncjob_line_ending": self.ui.cncjob_defaults_form.cncjob_gen_group.line_ending_cb, - "cncjob_plot_line": self.ui.cncjob_defaults_form.cncjob_gen_group.line_color_entry, - "cncjob_plot_fill": self.ui.cncjob_defaults_form.cncjob_gen_group.fill_color_entry, - "cncjob_travel_line": self.ui.cncjob_defaults_form.cncjob_gen_group.tline_color_entry, - "cncjob_travel_fill": self.ui.cncjob_defaults_form.cncjob_gen_group.tfill_color_entry, # CNC Job Options "cncjob_prepend": self.ui.cncjob_defaults_form.cncjob_opt_group.prepend_text, @@ -552,35 +537,7 @@ class PreferencesUIManager: "background-color:%s;" "border-color: dimgray" % str(self.defaults['excellon_plot_line'])[:7]) - # Init CNCJob Travel Line Colors - self.ui.cncjob_defaults_form.cncjob_gen_group.tfill_color_entry.set_value( - self.defaults['cncjob_travel_fill']) - self.ui.cncjob_defaults_form.cncjob_gen_group.tfill_color_button.setStyleSheet( - "background-color:%s;" - "border-color: dimgray" % str(self.defaults['cncjob_travel_fill'])[:7]) - self.ui.cncjob_defaults_form.cncjob_gen_group.tcolor_alpha_spinner.set_value( - int(self.defaults['cncjob_travel_fill'][7:9], 16)) - self.ui.cncjob_defaults_form.cncjob_gen_group.tcolor_alpha_slider.setValue( - int(self.defaults['cncjob_travel_fill'][7:9], 16)) - self.ui.cncjob_defaults_form.cncjob_gen_group.tline_color_entry.set_value( - self.defaults['cncjob_travel_line']) - self.ui.cncjob_defaults_form.cncjob_gen_group.tline_color_button.setStyleSheet( - "background-color:%s;" - "border-color: dimgray" % str(self.defaults['cncjob_travel_line'])[:7]) - - # Init CNCJob Plot Colors - self.ui.cncjob_defaults_form.cncjob_gen_group.fill_color_entry.set_value( - self.defaults['cncjob_plot_fill']) - self.ui.cncjob_defaults_form.cncjob_gen_group.fill_color_button.setStyleSheet( - "background-color:%s;" - "border-color: dimgray" % str(self.defaults['cncjob_plot_fill'])[:7]) - - self.ui.cncjob_defaults_form.cncjob_gen_group.line_color_entry.set_value( - self.defaults['cncjob_plot_line']) - self.ui.cncjob_defaults_form.cncjob_gen_group.line_color_button.setStyleSheet( - "background-color:%s;" - "border-color: dimgray" % str(self.defaults['cncjob_plot_line'])[:7]) diff --git a/flatcamGUI/preferences/cncjob/CNCJobGenPrefGroupUI.py b/flatcamGUI/preferences/cncjob/CNCJobGenPrefGroupUI.py index 66276e23..e999fb6e 100644 --- a/flatcamGUI/preferences/cncjob/CNCJobGenPrefGroupUI.py +++ b/flatcamGUI/preferences/cncjob/CNCJobGenPrefGroupUI.py @@ -1,389 +1,142 @@ -from PyQt5 import QtWidgets, QtCore, QtGui -from PyQt5.QtCore import QSettings +from flatcamGUI.preferences.OptionUI import * +from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI2 -from flatcamGUI.GUIElements import FCCheckBox, RadioSet, FCSpinner, FCDoubleSpinner, FCEntry -from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI import gettext import FlatCAMTranslation as fcTranslate import builtins - fcTranslate.apply_language('strings') if '_' not in builtins.__dict__: _ = gettext.gettext -settings = QSettings("Open Source", "FlatCAM") -if settings.contains("machinist"): - machinist_setting = settings.value('machinist', type=int) -else: - machinist_setting = 0 +class CNCJobGenPrefGroupUI(OptionsGroupUI2): -class CNCJobGenPrefGroupUI(OptionsGroupUI): - def __init__(self, decimals=4, parent=None): - # OptionsGroupUI.__init__(self, "CNC Job General Preferences", parent=None) - super(CNCJobGenPrefGroupUI, self).__init__(self, parent=parent) - - self.setTitle(str(_("CNC Job General"))) + def __init__(self, decimals=4, **kwargs): self.decimals = decimals - - # ## Plot options - self.plot_options_label = QtWidgets.QLabel("%s:" % _("Plot Options")) - self.layout.addWidget(self.plot_options_label) - - grid0 = QtWidgets.QGridLayout() - self.layout.addLayout(grid0) - grid0.setColumnStretch(0, 0) - grid0.setColumnStretch(1, 1) - - # Plot CB - # self.plot_cb = QtWidgets.QCheckBox('Plot') - self.plot_cb = FCCheckBox(_('Plot Object')) - self.plot_cb.setToolTip(_("Plot (show) this object.")) - grid0.addWidget(self.plot_cb, 0, 0, 1, 2) - - # Plot Kind - self.cncplot_method_label = QtWidgets.QLabel('%s:' % _("Plot kind")) - self.cncplot_method_label.setToolTip( - _("This selects the kind of geometries on the canvas to plot.\n" - "Those can be either of type 'Travel' which means the moves\n" - "above the work piece or it can be of type 'Cut',\n" - "which means the moves that cut into the material.") - ) - - self.cncplot_method_radio = RadioSet([ - {"label": _("All"), "value": "all"}, - {"label": _("Travel"), "value": "travel"}, - {"label": _("Cut"), "value": "cut"} - ], orientation='vertical') - - grid0.addWidget(self.cncplot_method_label, 1, 0) - grid0.addWidget(self.cncplot_method_radio, 1, 1) - grid0.addWidget(QtWidgets.QLabel(''), 1, 2) - - # Display Annotation - self.annotation_cb = FCCheckBox(_("Display Annotation")) - self.annotation_cb.setToolTip( - _("This selects if to display text annotation on the plot.\n" - "When checked it will display numbers in order for each end\n" - "of a travel line." - ) - ) - - grid0.addWidget(self.annotation_cb, 2, 0, 1, 3) - - # ################################################################### - # Number of circle steps for circular aperture linear approximation # - # ################################################################### - self.steps_per_circle_label = QtWidgets.QLabel('%s:' % _("Circle Steps")) - self.steps_per_circle_label.setToolTip( - _("The number of circle steps for GCode \n" - "circle and arc shapes linear approximation.") - ) - grid0.addWidget(self.steps_per_circle_label, 3, 0) - self.steps_per_circle_entry = FCSpinner() - self.steps_per_circle_entry.set_range(0, 99999) - grid0.addWidget(self.steps_per_circle_entry, 3, 1) - - # Tool dia for plot - tdlabel = QtWidgets.QLabel('%s:' % _('Travel dia')) - tdlabel.setToolTip( - _("The width of the travel lines to be\n" - "rendered in the plot.") - ) - self.tooldia_entry = FCDoubleSpinner() - self.tooldia_entry.set_range(0, 99999) - self.tooldia_entry.set_precision(self.decimals) - self.tooldia_entry.setSingleStep(0.1) - self.tooldia_entry.setWrapping(True) - - grid0.addWidget(tdlabel, 4, 0) - grid0.addWidget(self.tooldia_entry, 4, 1) - - # add a space - grid0.addWidget(QtWidgets.QLabel('%s:' % _("G-code Decimals")), 5, 0, 1, 2) - - # Number of decimals to use in GCODE coordinates - cdeclabel = QtWidgets.QLabel('%s:' % _('Coordinates')) - cdeclabel.setToolTip( - _("The number of decimals to be used for \n" - "the X, Y, Z coordinates in CNC code (GCODE, etc.)") - ) - self.coords_dec_entry = FCSpinner() - self.coords_dec_entry.set_range(0, 9) - self.coords_dec_entry.setWrapping(True) - - grid0.addWidget(cdeclabel, 6, 0) - grid0.addWidget(self.coords_dec_entry, 6, 1) - - # Number of decimals to use in GCODE feedrate - frdeclabel = QtWidgets.QLabel('%s:' % _('Feedrate')) - frdeclabel.setToolTip( - _("The number of decimals to be used for \n" - "the Feedrate parameter in CNC code (GCODE, etc.)") - ) - self.fr_dec_entry = FCSpinner() - self.fr_dec_entry.set_range(0, 9) - self.fr_dec_entry.setWrapping(True) - - grid0.addWidget(frdeclabel, 7, 0) - grid0.addWidget(self.fr_dec_entry, 7, 1) - - # The type of coordinates used in the Gcode: Absolute or Incremental - coords_type_label = QtWidgets.QLabel('%s:' % _('Coordinates type')) - coords_type_label.setToolTip( - _("The type of coordinates to be used in Gcode.\n" - "Can be:\n" - "- Absolute G90 -> the reference is the origin x=0, y=0\n" - "- Incremental G91 -> the reference is the previous position") - ) - self.coords_type_radio = RadioSet([ - {"label": _("Absolute G90"), "value": "G90"}, - {"label": _("Incremental G91"), "value": "G91"} - ], orientation='vertical', stretch=False) - grid0.addWidget(coords_type_label, 8, 0) - grid0.addWidget(self.coords_type_radio, 8, 1) + super().__init__(**kwargs) + self.setTitle(str(_("CNC Job General"))) # hidden for the time being, until implemented - coords_type_label.hide() - self.coords_type_radio.hide() + self.option_dict()["cncjob_coords_type"].label_widget.hide() + self.option_dict()["cncjob_coords_type"].get_field().hide() - # Line Endings - self.line_ending_cb = FCCheckBox(_("Force Windows style line-ending")) - self.line_ending_cb.setToolTip( - _("When checked will force a Windows style line-ending\n" - "(\\r\\n) on non-Windows OS's.") - ) + def build_options(self) -> [OptionUI]: + return [ + HeadingOptionUI(label_text="Plot Options"), + CheckboxOptionUI( + option="cncjob_plot", + label_text="Plot Object", + label_tooltip="Plot (show) this object." + ), + RadioSetOptionUI( + option="cncjob_plot_kind", + label_text="Plot kind", + label_tooltip="This selects the kind of geometries on the canvas to plot.\n" + "Those can be either of type 'Travel' which means the moves\n" + "above the work piece or it can be of type 'Cut',\n" + "which means the moves that cut into the material.", + choices=[ + {"label": _("All"), "value": "all"}, + {"label": _("Travel"), "value": "travel"}, + {"label": _("Cut"), "value": "cut"} + ], + orientation="vertical" + ), + CheckboxOptionUI( + option="cncjob_annotation", + label_text="Display Annotation", + label_tooltip="This selects if to display text annotation on the plot.\n" + "When checked it will display numbers in order for each end\n" + "of a travel line." + ), + SpinnerOptionUI( + option="cncjob_steps_per_circle", + label_text="Circle Steps", + label_tooltip="The number of circle steps for GCode \n" + "circle and arc shapes linear approximation.", + min_value=3, max_value=99999, step=1 + ), + DoubleSpinnerOptionUI( + option="cncjob_tooldia", + label_text="Travel dia", + label_tooltip="The width of the travel lines to be\n" + "rendered in the plot.", + min_value=0, max_value=99999, step=0.1, decimals=self.decimals + ), - grid0.addWidget(self.line_ending_cb, 9, 0, 1, 3) + HeadingOptionUI(label_text="G-code Decimals"), + SpinnerOptionUI( + option="cncjob_coords_decimals", + label_text="Coordinates", + label_tooltip="The number of decimals to be used for \n" + "the X, Y, Z coordinates in CNC code (GCODE, etc.)", + min_value=0, max_value=9, step=1 + ), + SpinnerOptionUI( + option="cncjob_fr_decimals", + label_text="Feedrate", + label_tooltip="The number of decimals to be used for \n" + "the Feedrate parameter in CNC code (GCODE, etc.)", + min_value=0, max_value=9, step=1 + ), + RadioSetOptionUI( + option="cncjob_coords_type", + label_text="Coordinates type", + label_tooltip="The type of coordinates to be used in Gcode.\n" + "Can be:\n" + "- Absolute G90 -> the reference is the origin x=0, y=0\n" + "- Incremental G91 -> the reference is the previous position", + choices=[ + {"label": _("Absolute G90"), "value": "G90"}, + {"label": _("Incremental G91"), "value": "G91"} + ], + orientation="vertical" + ), + CheckboxOptionUI( + option="cncjob_line_ending", + label_text="Force Windows style line-ending", + label_tooltip="When checked will force a Windows style line-ending\n" + "(\\r\\n) on non-Windows OS's." + ), + SeparatorOptionUI(), - separator_line = QtWidgets.QFrame() - separator_line.setFrameShape(QtWidgets.QFrame.HLine) - separator_line.setFrameShadow(QtWidgets.QFrame.Sunken) - grid0.addWidget(separator_line, 12, 0, 1, 2) + HeadingOptionUI(label_text="Travel Line Color"), + ColorOptionUI( + option="cncjob_travel_line", + label_text="Outline", + label_tooltip="Set the line color for plotted objects.", + ), + ColorOptionUI( + option="cncjob_travel_fill", + label_text="Fill", + label_tooltip="Set the fill color for plotted objects.\n" + "First 6 digits are the color and the last 2\n" + "digits are for alpha (transparency) level." + ), + ColorAlphaSliderOptionUI( + applies_to=["cncjob_travel_line", "cncjob_travel_fill"], + group=self, + label_text="Alpha", + label_tooltip="Set the transparency for plotted objects." + ), - # Travel Line Color - self.travel_color_label = QtWidgets.QLabel('%s' % _('Travel Line Color')) - grid0.addWidget(self.travel_color_label, 13, 0, 1, 2) - - # Plot Line Color - self.tline_color_label = QtWidgets.QLabel('%s:' % _('Outline')) - self.tline_color_label.setToolTip( - _("Set the travel line color for plotted objects.") - ) - self.tline_color_entry = FCEntry() - self.tline_color_button = QtWidgets.QPushButton() - self.tline_color_button.setFixedSize(15, 15) - - self.form_box_child_2 = QtWidgets.QHBoxLayout() - self.form_box_child_2.addWidget(self.tline_color_entry) - self.form_box_child_2.addWidget(self.tline_color_button) - self.form_box_child_2.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter) - - grid0.addWidget(self.tline_color_label, 14, 0) - grid0.addLayout(self.form_box_child_2, 14, 1) - - # Plot Fill Color - self.tfill_color_label = QtWidgets.QLabel('%s:' % _('Fill')) - self.tfill_color_label.setToolTip( - _("Set the fill color for plotted objects.\n" - "First 6 digits are the color and the last 2\n" - "digits are for alpha (transparency) level.") - ) - self.tfill_color_entry = FCEntry() - self.tfill_color_button = QtWidgets.QPushButton() - self.tfill_color_button.setFixedSize(15, 15) - - self.form_box_child_1 = QtWidgets.QHBoxLayout() - self.form_box_child_1.addWidget(self.tfill_color_entry) - self.form_box_child_1.addWidget(self.tfill_color_button) - self.form_box_child_1.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter) - - grid0.addWidget(self.tfill_color_label, 15, 0) - grid0.addLayout(self.form_box_child_1, 15, 1) - - # Plot Fill Transparency Level - self.alpha_label = QtWidgets.QLabel('%s:' % _('Alpha')) - self.alpha_label.setToolTip( - _("Set the fill transparency for plotted objects.") - ) - self.tcolor_alpha_slider = QtWidgets.QSlider(QtCore.Qt.Horizontal) - self.tcolor_alpha_slider.setMinimum(0) - self.tcolor_alpha_slider.setMaximum(255) - self.tcolor_alpha_slider.setSingleStep(1) - - self.tcolor_alpha_spinner = FCSpinner() - self.tcolor_alpha_spinner.setMinimumWidth(70) - self.tcolor_alpha_spinner.set_range(0, 255) - - self.form_box_child_3 = QtWidgets.QHBoxLayout() - self.form_box_child_3.addWidget(self.tcolor_alpha_slider) - self.form_box_child_3.addWidget(self.tcolor_alpha_spinner) - - grid0.addWidget(self.alpha_label, 16, 0) - grid0.addLayout(self.form_box_child_3, 16, 1) - - separator_line = QtWidgets.QFrame() - separator_line.setFrameShape(QtWidgets.QFrame.HLine) - separator_line.setFrameShadow(QtWidgets.QFrame.Sunken) - grid0.addWidget(separator_line, 17, 0, 1, 2) - - # CNCJob Object Color - self.cnc_color_label = QtWidgets.QLabel('%s' % _('CNCJob Object Color')) - grid0.addWidget(self.cnc_color_label, 18, 0, 1, 2) - - # Plot Line Color - self.line_color_label = QtWidgets.QLabel('%s:' % _('Outline')) - self.line_color_label.setToolTip( - _("Set the color for plotted objects.") - ) - self.line_color_entry = FCEntry() - self.line_color_button = QtWidgets.QPushButton() - self.line_color_button.setFixedSize(15, 15) - - self.form_box_child_2 = QtWidgets.QHBoxLayout() - self.form_box_child_2.addWidget(self.line_color_entry) - self.form_box_child_2.addWidget(self.line_color_button) - self.form_box_child_2.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter) - - grid0.addWidget(self.line_color_label, 19, 0) - grid0.addLayout(self.form_box_child_2, 19, 1) - - # Plot Fill Color - self.fill_color_label = QtWidgets.QLabel('%s:' % _('Fill')) - self.fill_color_label.setToolTip( - _("Set the fill color for plotted objects.\n" - "First 6 digits are the color and the last 2\n" - "digits are for alpha (transparency) level.") - ) - self.fill_color_entry = FCEntry() - self.fill_color_button = QtWidgets.QPushButton() - self.fill_color_button.setFixedSize(15, 15) - - self.form_box_child_1 = QtWidgets.QHBoxLayout() - self.form_box_child_1.addWidget(self.fill_color_entry) - self.form_box_child_1.addWidget(self.fill_color_button) - self.form_box_child_1.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter) - - grid0.addWidget(self.fill_color_label, 20, 0) - grid0.addLayout(self.form_box_child_1, 20, 1) - - self.layout.addStretch() - - # Setting plot colors signals - self.tline_color_entry.editingFinished.connect(self.on_tline_color_entry) - self.tline_color_button.clicked.connect(self.on_tline_color_button) - self.tfill_color_entry.editingFinished.connect(self.on_tfill_color_entry) - self.tfill_color_button.clicked.connect(self.on_tfill_color_button) - self.tcolor_alpha_spinner.valueChanged.connect(self.on_tcolor_spinner) - self.tcolor_alpha_slider.valueChanged.connect(self.on_tcolor_slider) - - self.line_color_entry.editingFinished.connect(self.on_line_color_entry) - self.line_color_button.clicked.connect(self.on_line_color_button) - self.fill_color_entry.editingFinished.connect(self.on_fill_color_entry) - self.fill_color_button.clicked.connect(self.on_fill_color_button) - - # ------------------------------------------------------ - # Setting travel colors handlers - # ------------------------------------------------------ - def on_tfill_color_entry(self): - self.app.defaults['cncjob_travel_fill'] = self.tfill_color_entry.get_value()[:7] + \ - self.app.defaults['cncjob_travel_fill'][7:9] - self.tfill_color_button.setStyleSheet( - "background-color:%s" % str(self.app.defaults['cncjob_travel_fill'])[:7]) - - def on_tfill_color_button(self): - current_color = QtGui.QColor(self.app.defaults['cncjob_travel_fill'][:7]) - - c_dialog = QtWidgets.QColorDialog() - plot_fill_color = c_dialog.getColor(initial=current_color) - - if plot_fill_color.isValid() is False: - return - - self.tfill_color_button.setStyleSheet("background-color:%s" % str(plot_fill_color.name())) - - new_val = str(plot_fill_color.name()) + str(self.app.defaults['cncjob_travel_fill'][7:9]) - self.tfill_color_entry.set_value(new_val) - self.app.defaults['cncjob_travel_fill'] = new_val - - def on_tcolor_spinner(self): - spinner_value = self.tcolor_alpha_spinner.value() - self.tcolor_alpha_slider.setValue(spinner_value) - self.app.defaults['cncjob_travel_fill'] = \ - self.app.defaults['cncjob_travel_fill'][:7] + \ - (hex(spinner_value)[2:] if int(hex(spinner_value)[2:], 16) > 0 else '00') - self.app.defaults['cncjob_travel_line'] = \ - self.app.defaults['cncjob_travel_line'][:7] + \ - (hex(spinner_value)[2:] if int(hex(spinner_value)[2:], 16) > 0 else '00') - - def on_tcolor_slider(self): - slider_value = self.tcolor_alpha_slider.value() - self.tcolor_alpha_spinner.setValue(slider_value) - - def on_tline_color_entry(self): - self.app.defaults['cncjob_travel_line'] = self.tline_color_entry.get_value()[:7] + \ - self.app.defaults['cncjob_travel_line'][7:9] - self.tline_color_button.setStyleSheet( - "background-color:%s" % str(self.app.defaults['cncjob_travel_line'])[:7]) - - def on_tline_color_button(self): - current_color = QtGui.QColor(self.app.defaults['cncjob_travel_line'][:7]) - # print(current_color) - - c_dialog = QtWidgets.QColorDialog() - plot_line_color = c_dialog.getColor(initial=current_color) - - if plot_line_color.isValid() is False: - return - - self.tline_color_button.setStyleSheet("background-color:%s" % str(plot_line_color.name())) - - new_val_line = str(plot_line_color.name()) + str(self.app.defaults['cncjob_travel_line'][7:9]) - self.tline_color_entry.set_value(new_val_line) - self.app.defaults['cncjob_travel_line'] = new_val_line - - # ------------------------------------------------------ - # Setting plot colors handlers - # ------------------------------------------------------ - def on_fill_color_entry(self): - self.app.defaults['cncjob_plot_fill'] = self.fill_color_entry.get_value()[:7] + \ - self.app.defaults['cncjob_plot_fill'][7:9] - self.fill_color_button.setStyleSheet( - "background-color:%s" % str(self.app.defaults['cncjob_plot_fill'])[:7]) - - def on_fill_color_button(self): - current_color = QtGui.QColor(self.app.defaults['cncjob_plot_fill'][:7]) - - c_dialog = QtWidgets.QColorDialog() - plot_fill_color = c_dialog.getColor(initial=current_color) - - if plot_fill_color.isValid() is False: - return - - self.fill_color_button.setStyleSheet("background-color:%s" % str(plot_fill_color.name())) - - new_val = str(plot_fill_color.name()) + str(self.app.defaults['cncjob_plot_fill'][7:9]) - self.fill_color_entry.set_value(new_val) - self.app.defaults['cncjob_plot_fill'] = new_val - - def on_line_color_entry(self): - self.app.defaults['cncjob_plot_line'] = self.line_color_entry.get_value()[:7] + \ - self.app.defaults['cncjob_plot_line'][7:9] - self.line_color_button.setStyleSheet( - "background-color:%s" % str(self.app.defaults['cncjob_plot_line'])[:7]) - - def on_line_color_button(self): - current_color = QtGui.QColor(self.app.defaults['cncjob_plot_line'][:7]) - # print(current_color) - - c_dialog = QtWidgets.QColorDialog() - plot_line_color = c_dialog.getColor(initial=current_color) - - if plot_line_color.isValid() is False: - return - - self.line_color_button.setStyleSheet("background-color:%s" % str(plot_line_color.name())) - - new_val_line = str(plot_line_color.name()) + str(self.app.defaults['cncjob_plot_line'][7:9]) - self.line_color_entry.set_value(new_val_line) - self.app.defaults['cncjob_plot_line'] = new_val_line + HeadingOptionUI(label_text="CNCJob Object Color"), + ColorOptionUI( + option="cncjob_plot_line", + label_text="Outline", + label_tooltip="Set the line color for plotted objects.", + ), + ColorOptionUI( + option="cncjob_plot_fill", + label_text="Fill", + label_tooltip="Set the fill color for plotted objects.\n" + "First 6 digits are the color and the last 2\n" + "digits are for alpha (transparency) level." + ), + ColorAlphaSliderOptionUI( + applies_to=["cncjob_plot_line", "cncjob_plot_fill"], + group=self, + label_text="Alpha", + label_tooltip="Set the transparency for plotted objects." + ) + ] \ No newline at end of file diff --git a/flatcamGUI/preferences/cncjob/CNCJobPreferencesUI.py b/flatcamGUI/preferences/cncjob/CNCJobPreferencesUI.py index f9e617ad..e5f73af8 100644 --- a/flatcamGUI/preferences/cncjob/CNCJobPreferencesUI.py +++ b/flatcamGUI/preferences/cncjob/CNCJobPreferencesUI.py @@ -6,19 +6,25 @@ from flatcamGUI.preferences.cncjob.CNCJobAdvOptPrefGroupUI import CNCJobAdvOptPr from flatcamGUI.preferences.cncjob.CNCJobOptPrefGroupUI import CNCJobOptPrefGroupUI from flatcamGUI.preferences.cncjob.CNCJobGenPrefGroupUI import CNCJobGenPrefGroupUI +import gettext +import FlatCAMTranslation as fcTranslate +import builtins +fcTranslate.apply_language('strings') +if '_' not in builtins.__dict__: + _ = gettext.gettext + class CNCJobPreferencesUI(PreferencesSectionUI): def __init__(self, decimals, **kwargs): self.decimals = decimals - self.cncjob_gen_group = CNCJobGenPrefGroupUI(decimals=self.decimals) self.cncjob_opt_group = CNCJobOptPrefGroupUI(decimals=self.decimals) self.cncjob_adv_opt_group = CNCJobAdvOptPrefGroupUI(decimals=self.decimals) super().__init__(**kwargs) def build_groups(self) -> [OptionsGroupUI]: return [ - self.cncjob_gen_group, + CNCJobGenPrefGroupUI(decimals=self.decimals), self.cncjob_opt_group, self.cncjob_adv_opt_group ] From 5304cd1ac928407b96e21cc714f160040d0c873c Mon Sep 17 00:00:00 2001 From: David Robertson Date: Sat, 9 May 2020 19:08:15 +0100 Subject: [PATCH 31/41] CNC job options --- flatcamGUI/preferences/OptionUI.py | 46 ++++++++- .../preferences/PreferencesUIManager.py | 5 - .../cncjob/CNCJobOptPrefGroupUI.py | 95 ++++++------------- .../preferences/cncjob/CNCJobPreferencesUI.py | 3 +- 4 files changed, 71 insertions(+), 78 deletions(-) diff --git a/flatcamGUI/preferences/OptionUI.py b/flatcamGUI/preferences/OptionUI.py index 90512c04..a594f5cd 100644 --- a/flatcamGUI/preferences/OptionUI.py +++ b/flatcamGUI/preferences/OptionUI.py @@ -1,8 +1,10 @@ from typing import Union, Sequence, List -from PyQt5 import QtWidgets +from PyQt5 import QtWidgets, QtGui +from PyQt5.QtCore import QSettings + from flatcamGUI.GUIElements import RadioSet, FCCheckBox, FCButton, FCComboBox, FCEntry, FCSpinner, FCColorEntry, \ - FCSliderWithSpinner, FCDoubleSpinner, FloatEntry + FCSliderWithSpinner, FCDoubleSpinner, FloatEntry, FCTextArea import gettext import FlatCAMTranslation as fcTranslate @@ -67,13 +69,13 @@ class LineEntryOptionUI(BasicOptionUI): def build_entry_widget(self) -> QtWidgets.QWidget: return FCEntry() + # Not sure why this is needed over DoubleSpinnerOptionUI class FloatEntryOptionUI(BasicOptionUI): def build_entry_widget(self) -> QtWidgets.QWidget: return FloatEntry() - class RadioSetOptionUI(BasicOptionUI): def __init__(self, option: str, label_text: str, choices: list, orientation='horizontal', **kwargs): @@ -85,6 +87,44 @@ class RadioSetOptionUI(BasicOptionUI): return RadioSet(choices=self.choices, orientation=self.orientation) +class TextAreaOptionUI(OptionUI): + + def __init__(self, option: str, label_text: str, label_tooltip: str): + super().__init__(option=option) + self.label_text = label_text + self.label_tooltip = label_tooltip + self.label_widget = self.build_label_widget() + self.textarea_widget = self.build_textarea_widget() + + def build_label_widget(self): + label = QtWidgets.QLabel(_(self.label_text)) + label.setToolTip(_(self.label_tooltip)) + return label + + def build_textarea_widget(self): + textarea = FCTextArea() + textarea.setPlaceholderText(_(self.label_tooltip)) + + qsettings = QSettings("Open Source", "FlatCAM") + if qsettings.contains("textbox_font_size"): + tb_fsize = qsettings.value('textbox_font_size', type=int) + else: + tb_fsize = 10 + font = QtGui.QFont() + font.setPointSize(tb_fsize) + textarea.setFont(font) + + return textarea + + def get_field(self): + return self.textarea_widget + + def add_to_grid(self, grid: QtWidgets.QGridLayout, row: int) -> int: + grid.addWidget(self.label_widget, row, 0, 1, 3) + grid.addWidget(self.textarea_widget, row+1, 0, 1, 3) + return 2 + + class CheckboxOptionUI(OptionUI): def __init__(self, option: str, label_text: str, label_tooltip: str): diff --git a/flatcamGUI/preferences/PreferencesUIManager.py b/flatcamGUI/preferences/PreferencesUIManager.py index be279f62..a1b04eb0 100644 --- a/flatcamGUI/preferences/PreferencesUIManager.py +++ b/flatcamGUI/preferences/PreferencesUIManager.py @@ -142,11 +142,6 @@ class PreferencesUIManager: self.ui.excellon_defaults_form.excellon_editor_group.slot_array_circular_angle_entry, - - # CNC Job Options - "cncjob_prepend": self.ui.cncjob_defaults_form.cncjob_opt_group.prepend_text, - "cncjob_append": self.ui.cncjob_defaults_form.cncjob_opt_group.append_text, - # CNC Job Advanced Options "cncjob_toolchange_macro": self.ui.cncjob_defaults_form.cncjob_adv_opt_group.toolchange_text, "cncjob_toolchange_macro_enable": self.ui.cncjob_defaults_form.cncjob_adv_opt_group.toolchange_cb, diff --git a/flatcamGUI/preferences/cncjob/CNCJobOptPrefGroupUI.py b/flatcamGUI/preferences/cncjob/CNCJobOptPrefGroupUI.py index c8eb7e66..eefaee28 100644 --- a/flatcamGUI/preferences/cncjob/CNCJobOptPrefGroupUI.py +++ b/flatcamGUI/preferences/cncjob/CNCJobOptPrefGroupUI.py @@ -1,80 +1,39 @@ -from PyQt5 import QtWidgets, QtGui -from PyQt5.QtCore import QSettings - -from flatcamGUI.GUIElements import FCTextArea -from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI +from flatcamGUI.preferences.OptionUI import * +from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI2 import gettext import FlatCAMTranslation as fcTranslate import builtins - fcTranslate.apply_language('strings') if '_' not in builtins.__dict__: _ = gettext.gettext -settings = QSettings("Open Source", "FlatCAM") -if settings.contains("machinist"): - machinist_setting = settings.value('machinist', type=int) -else: - machinist_setting = 0 +class CNCJobOptPrefGroupUI(OptionsGroupUI2): -class CNCJobOptPrefGroupUI(OptionsGroupUI): - def __init__(self, decimals=4, parent=None): - # OptionsGroupUI.__init__(self, "CNC Job Options Preferences", parent=None) - super(CNCJobOptPrefGroupUI, self).__init__(self, parent=parent) - - self.setTitle(str(_("CNC Job Options"))) + def __init__(self, decimals=4, **kwargs): self.decimals = decimals + super().__init__(**kwargs) + self.setTitle(str(_("CNC Job Options"))) - # ## Export G-Code - self.export_gcode_label = QtWidgets.QLabel("%s:" % _("Export G-Code")) - self.export_gcode_label.setToolTip( - _("Export and save G-Code to\n" - "make this object to a file.") - ) - self.layout.addWidget(self.export_gcode_label) - - qsettings = QSettings("Open Source", "FlatCAM") - if qsettings.contains("textbox_font_size"): - tb_fsize = qsettings.value('textbox_font_size', type=int) - else: - tb_fsize = 10 - font = QtGui.QFont() - font.setPointSize(tb_fsize) - - # Prepend to G-Code - prependlabel = QtWidgets.QLabel('%s:' % _('Prepend to G-Code')) - prependlabel.setToolTip( - _("Type here any G-Code commands you would\n" - "like to add at the beginning of the G-Code file.") - ) - self.layout.addWidget(prependlabel) - - self.prepend_text = FCTextArea() - self.prepend_text.setPlaceholderText( - _("Type here any G-Code commands you would " - "like to add at the beginning of the G-Code file.") - ) - self.layout.addWidget(self.prepend_text) - self.prepend_text.setFont(font) - - # Append text to G-Code - appendlabel = QtWidgets.QLabel('%s:' % _('Append to G-Code')) - appendlabel.setToolTip( - _("Type here any G-Code commands you would\n" - "like to append to the generated file.\n" - "I.e.: M2 (End of program)") - ) - self.layout.addWidget(appendlabel) - - self.append_text = FCTextArea() - self.append_text.setPlaceholderText( - _("Type here any G-Code commands you would " - "like to append to the generated file.\n" - "I.e.: M2 (End of program)") - ) - self.layout.addWidget(self.append_text) - self.append_text.setFont(font) - - self.layout.addStretch() + def build_options(self) -> [OptionUI]: + return [ + HeadingOptionUI( + label_text="Export G-Code", + label_tooltip="Export and save G-Code to\n" + "make this object to a file." + ), + TextAreaOptionUI( + option="cncjob_prepend", + label_text="Prepend to G-Code", + label_tooltip="Type here any G-Code commands you would\n" + "like to add at the beginning of the G-Code file." + ), + TextAreaOptionUI( + option="cncjob_append", + label_text="Append to G-Code", + label_tooltip="Type here any G-Code commands you would\n" + "like to append to the generated file.\n" + "I.e.: M2 (End of program)" + ) + ] diff --git a/flatcamGUI/preferences/cncjob/CNCJobPreferencesUI.py b/flatcamGUI/preferences/cncjob/CNCJobPreferencesUI.py index e5f73af8..82cb2c86 100644 --- a/flatcamGUI/preferences/cncjob/CNCJobPreferencesUI.py +++ b/flatcamGUI/preferences/cncjob/CNCJobPreferencesUI.py @@ -18,14 +18,13 @@ class CNCJobPreferencesUI(PreferencesSectionUI): def __init__(self, decimals, **kwargs): self.decimals = decimals - self.cncjob_opt_group = CNCJobOptPrefGroupUI(decimals=self.decimals) self.cncjob_adv_opt_group = CNCJobAdvOptPrefGroupUI(decimals=self.decimals) super().__init__(**kwargs) def build_groups(self) -> [OptionsGroupUI]: return [ CNCJobGenPrefGroupUI(decimals=self.decimals), - self.cncjob_opt_group, + CNCJobOptPrefGroupUI(decimals=self.decimals), self.cncjob_adv_opt_group ] From 73757a66cda47c1d3251e7d8a782cfe9d0881b20 Mon Sep 17 00:00:00 2001 From: David Robertson Date: Sat, 9 May 2020 19:30:18 +0100 Subject: [PATCH 32/41] CNC job advanced --- flatcamGUI/preferences/OptionUI.py | 2 +- .../preferences/PreferencesUIManager.py | 18 -- .../cncjob/CNCJobAdvOptPrefGroupUI.py | 211 +++++------------- 3 files changed, 56 insertions(+), 175 deletions(-) diff --git a/flatcamGUI/preferences/OptionUI.py b/flatcamGUI/preferences/OptionUI.py index a594f5cd..ce851d4f 100644 --- a/flatcamGUI/preferences/OptionUI.py +++ b/flatcamGUI/preferences/OptionUI.py @@ -97,7 +97,7 @@ class TextAreaOptionUI(OptionUI): self.textarea_widget = self.build_textarea_widget() def build_label_widget(self): - label = QtWidgets.QLabel(_(self.label_text)) + label = QtWidgets.QLabel("%s:" % _(self.label_text)) label.setToolTip(_(self.label_tooltip)) return label diff --git a/flatcamGUI/preferences/PreferencesUIManager.py b/flatcamGUI/preferences/PreferencesUIManager.py index a1b04eb0..e9eae026 100644 --- a/flatcamGUI/preferences/PreferencesUIManager.py +++ b/flatcamGUI/preferences/PreferencesUIManager.py @@ -141,13 +141,6 @@ class PreferencesUIManager: "excellon_editor_slot_circ_angle": self.ui.excellon_defaults_form.excellon_editor_group.slot_array_circular_angle_entry, - - # CNC Job Advanced Options - "cncjob_toolchange_macro": self.ui.cncjob_defaults_form.cncjob_adv_opt_group.toolchange_text, - "cncjob_toolchange_macro_enable": self.ui.cncjob_defaults_form.cncjob_adv_opt_group.toolchange_cb, - "cncjob_annotation_fontsize": self.ui.cncjob_defaults_form.cncjob_adv_opt_group.annotation_fontsize_sp, - "cncjob_annotation_fontcolor": self.ui.cncjob_defaults_form.cncjob_adv_opt_group.annotation_fontcolor_entry, - # NCC Tool "tools_ncctools": self.ui.tools_defaults_form.tools_ncc_group.ncc_tool_dia_entry, "tools_nccorder": self.ui.tools_defaults_form.tools_ncc_group.ncc_order_radio, @@ -532,17 +525,6 @@ class PreferencesUIManager: "background-color:%s;" "border-color: dimgray" % str(self.defaults['excellon_plot_line'])[:7]) - - - - - # Init the Annotation CNC Job color - self.ui.cncjob_defaults_form.cncjob_adv_opt_group.annotation_fontcolor_entry.set_value( - self.defaults['cncjob_annotation_fontcolor']) - self.ui.cncjob_defaults_form.cncjob_adv_opt_group.annotation_fontcolor_button.setStyleSheet( - "background-color:%s;" - "border-color: dimgray" % str(self.defaults['cncjob_annotation_fontcolor'])[:7]) - # Init the Tool Film color self.ui.tools_defaults_form.tools_film_group.film_color_entry.set_value( self.defaults['tools_film_color']) diff --git a/flatcamGUI/preferences/cncjob/CNCJobAdvOptPrefGroupUI.py b/flatcamGUI/preferences/cncjob/CNCJobAdvOptPrefGroupUI.py index 8d7a1cf0..5422e297 100644 --- a/flatcamGUI/preferences/cncjob/CNCJobAdvOptPrefGroupUI.py +++ b/flatcamGUI/preferences/cncjob/CNCJobAdvOptPrefGroupUI.py @@ -1,8 +1,7 @@ -from PyQt5 import QtWidgets, QtGui, QtCore -from PyQt5.QtCore import QSettings, Qt +from PyQt5.QtCore import Qt -from flatcamGUI.GUIElements import FCTextArea, FCCheckBox, FCComboBox, FCSpinner, FCEntry -from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI +from flatcamGUI.preferences.OptionUI import * +from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI2 import gettext import FlatCAMTranslation as fcTranslate import builtins @@ -11,93 +10,18 @@ fcTranslate.apply_language('strings') if '_' not in builtins.__dict__: _ = gettext.gettext -settings = QSettings("Open Source", "FlatCAM") -if settings.contains("machinist"): - machinist_setting = settings.value('machinist', type=int) -else: - machinist_setting = 0 +class CNCJobAdvOptPrefGroupUI(OptionsGroupUI2): -class CNCJobAdvOptPrefGroupUI(OptionsGroupUI): - def __init__(self, decimals=4, parent=None): - # OptionsGroupUI.__init__(self, "CNC Job Advanced Options Preferences", parent=None) - super(CNCJobAdvOptPrefGroupUI, self).__init__(self, parent=parent) + def __init__(self, decimals=4, **kwargs): self.decimals = decimals - + super().__init__(**kwargs) self.setTitle(str(_("CNC Job Adv. Options"))) - # ## Export G-Code - self.export_gcode_label = QtWidgets.QLabel("%s:" % _("Export CNC Code")) - self.export_gcode_label.setToolTip( - _("Export and save G-Code to\n" - "make this object to a file.") - ) - self.layout.addWidget(self.export_gcode_label) - - # Prepend to G-Code - toolchangelabel = QtWidgets.QLabel('%s' % _('Toolchange G-Code')) - toolchangelabel.setToolTip( - _( - "Type here any G-Code commands you would\n" - "like to be executed when Toolchange event is encountered.\n" - "This will constitute a Custom Toolchange GCode,\n" - "or a Toolchange Macro.\n" - "The FlatCAM variables are surrounded by '%' symbol.\n\n" - "WARNING: it can be used only with a preprocessor file\n" - "that has 'toolchange_custom' in it's name and this is built\n" - "having as template the 'Toolchange Custom' posprocessor file." - ) - ) - self.layout.addWidget(toolchangelabel) - - qsettings = QSettings("Open Source", "FlatCAM") - if qsettings.contains("textbox_font_size"): - tb_fsize = qsettings.value('textbox_font_size', type=int) - else: - tb_fsize = 10 - font = QtGui.QFont() - font.setPointSize(tb_fsize) - - self.toolchange_text = FCTextArea() - self.toolchange_text.setPlaceholderText( - _( - "Type here any G-Code commands you would " - "like to be executed when Toolchange event is encountered.\n" - "This will constitute a Custom Toolchange GCode, " - "or a Toolchange Macro.\n" - "The FlatCAM variables are surrounded by '%' symbol.\n" - "WARNING: it can be used only with a preprocessor file " - "that has 'toolchange_custom' in it's name." - ) - ) - self.layout.addWidget(self.toolchange_text) - self.toolchange_text.setFont(font) - - hlay = QtWidgets.QHBoxLayout() - self.layout.addLayout(hlay) - - # Toolchange Replacement GCode - self.toolchange_cb = FCCheckBox(label='%s' % _('Use Toolchange Macro')) - self.toolchange_cb.setToolTip( - _("Check this box if you want to use\n" - "a Custom Toolchange GCode (macro).") - ) - hlay.addWidget(self.toolchange_cb) - hlay.addStretch() - - hlay1 = QtWidgets.QHBoxLayout() - self.layout.addLayout(hlay1) - - # Variable list - self.tc_variable_combo = FCComboBox() - self.tc_variable_combo.setToolTip( - _("A list of the FlatCAM variables that can be used\n" - "in the Toolchange event.\n" - "They have to be surrounded by the '%' symbol") - ) - hlay1.addWidget(self.tc_variable_combo) + self.toolchange_text = self.option_dict()["cncjob_toolchange_macro"].get_field() # Populate the Combo Box + self.tc_variable_combo = self.option_dict()["__toolchange_variable"].get_field() variables = [_('Parameters'), 'tool', 'tooldia', 't_drills', 'x_toolchange', 'y_toolchange', 'z_toolchange', 'z_cut', 'z_move', 'z_depthpercut', 'spindlespeed', 'dwelltime'] self.tc_variable_combo.addItems(variables) @@ -126,83 +50,58 @@ class CNCJobAdvOptPrefGroupUI(OptionsGroupUI): _("dwelltime = time to dwell to allow the spindle to reach it's set RPM"), Qt.ToolTipRole) - # hlay1.addStretch() - - # Insert Variable into the Toolchange G-Code Text Box - # self.tc_insert_buton = FCButton("Insert") - # self.tc_insert_buton.setToolTip( - # "Insert the variable in the GCode Box\n" - # "surrounded by the '%' symbol." - # ) - # hlay1.addWidget(self.tc_insert_buton) - - grid0 = QtWidgets.QGridLayout() - self.layout.addLayout(grid0) - - grid0.addWidget(QtWidgets.QLabel(''), 1, 0, 1, 2) - - # Annotation Font Size - self.annotation_fontsize_label = QtWidgets.QLabel('%s:' % _("Annotation Size")) - self.annotation_fontsize_label.setToolTip( - _("The font size of the annotation text. In pixels.") - ) - grid0.addWidget(self.annotation_fontsize_label, 2, 0) - self.annotation_fontsize_sp = FCSpinner() - self.annotation_fontsize_sp.set_range(0, 9999) - - grid0.addWidget(self.annotation_fontsize_sp, 2, 1) - grid0.addWidget(QtWidgets.QLabel(''), 2, 2) - - # Annotation Font Color - self.annotation_color_label = QtWidgets.QLabel('%s:' % _('Annotation Color')) - self.annotation_color_label.setToolTip( - _("Set the font color for the annotation texts.") - ) - self.annotation_fontcolor_entry = FCEntry() - self.annotation_fontcolor_button = QtWidgets.QPushButton() - self.annotation_fontcolor_button.setFixedSize(15, 15) - - self.form_box_child = QtWidgets.QHBoxLayout() - self.form_box_child.setContentsMargins(0, 0, 0, 0) - self.form_box_child.addWidget(self.annotation_fontcolor_entry) - self.form_box_child.addWidget(self.annotation_fontcolor_button, alignment=Qt.AlignRight) - self.form_box_child.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter) - - color_widget = QtWidgets.QWidget() - color_widget.setLayout(self.form_box_child) - grid0.addWidget(self.annotation_color_label, 3, 0) - grid0.addWidget(color_widget, 3, 1) - grid0.addWidget(QtWidgets.QLabel(''), 3, 2) - - self.layout.addStretch() - self.tc_variable_combo.currentIndexChanged[str].connect(self.on_cnc_custom_parameters) - self.annotation_fontcolor_entry.editingFinished.connect(self.on_annotation_fontcolor_entry) - self.annotation_fontcolor_button.clicked.connect(self.on_annotation_fontcolor_button) + def build_options(self) -> [OptionUI]: + return [ + HeadingOptionUI( + label_text="Export CNC Code", + label_tooltip="Export and save G-Code to\n" + "make this object to a file." + ), + CheckboxOptionUI( + option="cncjob_toolchange_macro_enable", + label_text="Use Toolchange Macro", + label_tooltip="Check this box if you want to use\n" + "a Custom Toolchange GCode (macro)." + ), + TextAreaOptionUI( + option="cncjob_toolchange_macro", + label_text="Toolchange G-Code", + label_tooltip="Type here any G-Code commands you would " + "like to be executed when Toolchange event is encountered.\n" + "This will constitute a Custom Toolchange GCode, " + "or a Toolchange Macro.\n" + "The FlatCAM variables are surrounded by '%' symbol.\n" + "WARNING: it can be used only with a preprocessor file " + "that has 'toolchange_custom' in it's name." + ), + ComboboxOptionUI( + option="__toolchange_variable", + label_text="Insert variable", + label_tooltip="A list of the FlatCAM variables that can be used\n" + "in the Toolchange event.\n" + "They have to be surrounded by the '%' symbol", + choices=[] # see init. + ), + + SpinnerOptionUI( + option="cncjob_annotation_fontsize", + label_text="Annotation Size", + label_tooltip="The font size of the annotation text. In pixels.", + min_value=1, max_value=9999, step=1 + ), + ColorOptionUI( + option="cncjob_annotation_fontcolor", + label_text="Annotation Color", + label_tooltip="Set the font color for the annotation texts." + ) + ] def on_cnc_custom_parameters(self, signal_text): - if signal_text == 'Parameters': + if signal_text == _("Parameters"): return else: self.toolchange_text.insertPlainText('%%%s%%' % signal_text) + self.tc_variable_combo.set_value(_("Parameters")) - def on_annotation_fontcolor_entry(self): - self.app.defaults['cncjob_annotation_fontcolor'] = self.annotation_fontcolor_entry.get_value() - self.annotation_fontcolor_button.setStyleSheet( - "background-color:%s" % str(self.app.defaults['cncjob_annotation_fontcolor'])) - - def on_annotation_fontcolor_button(self): - current_color = QtGui.QColor(self.app.defaults['cncjob_annotation_fontcolor']) - - c_dialog = QtWidgets.QColorDialog() - annotation_color = c_dialog.getColor(initial=current_color) - - if annotation_color.isValid() is False: - return - - self.annotation_fontcolor_button.setStyleSheet("background-color:%s" % str(annotation_color.name())) - - new_val_sel = str(annotation_color.name()) - self.annotation_fontcolor_entry.set_value(new_val_sel) - self.app.defaults['cncjob_annotation_fontcolor'] = new_val_sel From 13296aea1df409d9b4dc58e91d0b37ba86b85c46 Mon Sep 17 00:00:00 2001 From: David Robertson Date: Sat, 9 May 2020 19:31:09 +0100 Subject: [PATCH 33/41] cleanup --- flatcamGUI/preferences/cncjob/CNCJobPreferencesUI.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/flatcamGUI/preferences/cncjob/CNCJobPreferencesUI.py b/flatcamGUI/preferences/cncjob/CNCJobPreferencesUI.py index 82cb2c86..d81134d8 100644 --- a/flatcamGUI/preferences/cncjob/CNCJobPreferencesUI.py +++ b/flatcamGUI/preferences/cncjob/CNCJobPreferencesUI.py @@ -1,5 +1,3 @@ -from PyQt5 import QtWidgets - from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI from flatcamGUI.preferences.PreferencesSectionUI import PreferencesSectionUI from flatcamGUI.preferences.cncjob.CNCJobAdvOptPrefGroupUI import CNCJobAdvOptPrefGroupUI @@ -18,14 +16,13 @@ class CNCJobPreferencesUI(PreferencesSectionUI): def __init__(self, decimals, **kwargs): self.decimals = decimals - self.cncjob_adv_opt_group = CNCJobAdvOptPrefGroupUI(decimals=self.decimals) super().__init__(**kwargs) def build_groups(self) -> [OptionsGroupUI]: return [ CNCJobGenPrefGroupUI(decimals=self.decimals), CNCJobOptPrefGroupUI(decimals=self.decimals), - self.cncjob_adv_opt_group + CNCJobAdvOptPrefGroupUI(decimals=self.decimals) ] def get_tab_id(self): From 500cc346399cfadb30d22ba62838bf90a33d07eb Mon Sep 17 00:00:00 2001 From: David Robertson Date: Sat, 9 May 2020 23:29:59 +0100 Subject: [PATCH 34/41] Added a custom layout for the prefs so that it adjusts to different screen sizes automatically. I may have gotten slightly carried away on this one........ --- flatcamGUI/ColumnarFlowLayout.py | 174 ++++++++++++++++++ .../preferences/PreferencesSectionUI.py | 9 +- 2 files changed, 178 insertions(+), 5 deletions(-) create mode 100644 flatcamGUI/ColumnarFlowLayout.py diff --git a/flatcamGUI/ColumnarFlowLayout.py b/flatcamGUI/ColumnarFlowLayout.py new file mode 100644 index 00000000..753c070b --- /dev/null +++ b/flatcamGUI/ColumnarFlowLayout.py @@ -0,0 +1,174 @@ +import sys + +from PyQt5.QtCore import QPoint, QRect, QSize, Qt +from PyQt5.QtWidgets import QLayout, QSizePolicy +import math + +class ColumnarFlowLayout(QLayout): + def __init__(self, parent=None, margin=0, spacing=-1): + super().__init__(parent) + + if parent is not None: + self.setContentsMargins(margin, margin, margin, margin) + + self.setSpacing(spacing) + self.itemList = [] + + def __del__(self): + item = self.takeAt(0) + while item: + item = self.takeAt(0) + + def addItem(self, item): + self.itemList.append(item) + + def count(self): + return len(self.itemList) + + def itemAt(self, index): + if 0 <= index < len(self.itemList): + return self.itemList[index] + return None + + def takeAt(self, index): + if 0 <= index < len(self.itemList): + return self.itemList.pop(index) + return None + + def expandingDirections(self): + return Qt.Orientations(Qt.Orientation(0)) + + def hasHeightForWidth(self): + return True + + def heightForWidth(self, width): + height = self.doLayout(QRect(0, 0, width, 0), True) + return height + + def setGeometry(self, rect): + super().setGeometry(rect) + self.doLayout(rect, False) + + def sizeHint(self): + return self.minimumSize() + + def minimumSize(self): + size = QSize() + + for item in self.itemList: + size = size.expandedTo(item.minimumSize()) + + margin, _, _, _ = self.getContentsMargins() + + size += QSize(2 * margin, 2 * margin) + return size + + def doLayout(self, rect: QRect, testOnly: bool) -> int: + spacing = self.spacing() + x = rect.x() + y = rect.y() + + # Determine width of widest item + widest = 0 + for item in self.itemList: + widest = max(widest, item.sizeHint().width()) + + # Determine how many equal-width columns we can get, and how wide each one should be + column_count = math.floor(rect.width() / (widest + spacing)) + column_count = min(column_count, len(self.itemList)) + column_count = max(1, column_count) + column_width = math.floor((rect.width() - (column_count-1)*spacing - 1) / column_count) + + # Get the heights for all of our items + item_heights = {} + for item in self.itemList: + height = item.heightForWidth(column_width) if item.hasHeightForWidth() else item.sizeHint().height() + item_heights[item] = height + + # Prepare our column representation + column_contents = [] + column_heights = [] + for column_index in range(column_count): + column_contents.append([]) + column_heights.append(0) + + def add_to_column(column: int, item): + column_contents[column].append(item) + column_heights[column] += (item_heights[item] + spacing) + + def shove_one(from_column: int) -> bool: + if len(column_contents[from_column]) >= 1: + item = column_contents[from_column].pop(0) + column_heights[from_column] -= (item_heights[item] + spacing) + add_to_column(from_column-1, item) + return True + return False + + def shove_cascade_consider(from_column: int) -> bool: + changed = False + + if len(column_contents[from_column]) > 1: + item = column_contents[from_column][0] + item_height = item_heights[item] + if column_heights[from_column-1] + item_height < max(column_heights): + changed = shove_one(from_column) or changed + + if from_column+1 < column_count: + changed = shove_cascade_consider(from_column+1) or changed + + return changed + + def shove_cascade() -> bool: + if column_count < 2: + return False + changed = True + while changed: + changed = shove_cascade_consider(1) + return changed + + def pick_best_shoving_position() -> int: + best_pos = 1 + best_height = sys.maxsize + for column_index in range(1, column_count): + if len(column_contents[column_index]) == 0: + continue + item = column_contents[column_index][0] + height_after_shove = column_heights[column_index-1] + item_heights[item] + if height_after_shove < best_height: + best_height = height_after_shove + best_pos = column_index + return best_pos + + # Calculate the best layout + column_index = 0 + for item in self.itemList: + item_height = item_heights[item] + if column_heights[column_index] != 0 and (column_heights[column_index] + item_height) > max(column_heights): + column_index += 1 + if column_index >= column_count: + # Run out of room, need to shove more stuff in each column + if column_count >= 2: + changed = shove_cascade() + if not changed: + shoving_pos = pick_best_shoving_position() + shove_one(shoving_pos) + shove_cascade() + column_index = column_count-1 + + add_to_column(column_index, item) + + shove_cascade() + + # Set geometry according to the layout we have calculated + if not testOnly: + for column_index, items in enumerate(column_contents): + x = column_index * (column_width + spacing) + y = 0 + for item in items: + height = item_heights[item] + item.setGeometry(QRect(x, y, column_width, height)) + y += (height + spacing) + + # Return the overall height + return max(column_heights) + diff --git a/flatcamGUI/preferences/PreferencesSectionUI.py b/flatcamGUI/preferences/PreferencesSectionUI.py index fa55ec31..92168377 100644 --- a/flatcamGUI/preferences/PreferencesSectionUI.py +++ b/flatcamGUI/preferences/PreferencesSectionUI.py @@ -1,7 +1,7 @@ from typing import Dict +from PyQt5 import QtWidgets, QtCore -from PyQt5 import QtWidgets - +from flatcamGUI.ColumnarFlowLayout import ColumnarFlowLayout from flatcamGUI.preferences.OptionUI import OptionUI from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI @@ -10,8 +10,7 @@ class PreferencesSectionUI(QtWidgets.QWidget): def __init__(self, **kwargs): super().__init__(**kwargs) - - self.layout = QtWidgets.QHBoxLayout() + self.layout = ColumnarFlowLayout() #QtWidgets.QHBoxLayout() self.setLayout(self.layout) self.groups = self.build_groups() @@ -19,7 +18,6 @@ class PreferencesSectionUI(QtWidgets.QWidget): group.setMinimumWidth(250) self.layout.addWidget(group) - self.layout.addStretch() def build_groups(self) -> [OptionsGroupUI]: return [] @@ -34,6 +32,7 @@ class PreferencesSectionUI(QtWidgets.QWidget): def build_tab(self): scroll_area = QtWidgets.QScrollArea() scroll_area.setWidget(self) + scroll_area.setWidgetResizable(True) return scroll_area def get_tab_id(self) -> str: From 5d3f4ee038efd3df0b224544b57730c7a889b851 Mon Sep 17 00:00:00 2001 From: David Robertson Date: Sun, 10 May 2020 22:05:47 +0100 Subject: [PATCH 35/41] excellon opt --- .../preferences/PreferencesUIManager.py | 23 - .../excellon/ExcellonOptPrefGroupUI.py | 461 +++++++----------- .../excellon/ExcellonPreferencesUI.py | 7 + 3 files changed, 178 insertions(+), 313 deletions(-) diff --git a/flatcamGUI/preferences/PreferencesUIManager.py b/flatcamGUI/preferences/PreferencesUIManager.py index e9eae026..de0a23fd 100644 --- a/flatcamGUI/preferences/PreferencesUIManager.py +++ b/flatcamGUI/preferences/PreferencesUIManager.py @@ -68,29 +68,6 @@ class PreferencesUIManager: "excellon_plot_fill": self.ui.excellon_defaults_form.excellon_gen_group.fill_color_entry, "excellon_plot_line": self.ui.excellon_defaults_form.excellon_gen_group.line_color_entry, - # Excellon Options - "excellon_operation": self.ui.excellon_defaults_form.excellon_opt_group.operation_radio, - "excellon_milling_type": self.ui.excellon_defaults_form.excellon_opt_group.milling_type_radio, - - "excellon_milling_dia": self.ui.excellon_defaults_form.excellon_opt_group.mill_dia_entry, - - "excellon_cutz": self.ui.excellon_defaults_form.excellon_opt_group.cutz_entry, - "excellon_multidepth": self.ui.excellon_defaults_form.excellon_opt_group.mpass_cb, - "excellon_depthperpass": self.ui.excellon_defaults_form.excellon_opt_group.maxdepth_entry, - "excellon_travelz": self.ui.excellon_defaults_form.excellon_opt_group.travelz_entry, - "excellon_endz": self.ui.excellon_defaults_form.excellon_opt_group.endz_entry, - "excellon_endxy": self.ui.excellon_defaults_form.excellon_opt_group.endxy_entry, - - "excellon_feedrate_z": self.ui.excellon_defaults_form.excellon_opt_group.feedrate_z_entry, - "excellon_spindlespeed": self.ui.excellon_defaults_form.excellon_opt_group.spindlespeed_entry, - "excellon_dwell": self.ui.excellon_defaults_form.excellon_opt_group.dwell_cb, - "excellon_dwelltime": self.ui.excellon_defaults_form.excellon_opt_group.dwelltime_entry, - "excellon_toolchange": self.ui.excellon_defaults_form.excellon_opt_group.toolchange_cb, - "excellon_toolchangez": self.ui.excellon_defaults_form.excellon_opt_group.toolchangez_entry, - "excellon_ppname_e": self.ui.excellon_defaults_form.excellon_opt_group.pp_excellon_name_cb, - "excellon_tooldia": self.ui.excellon_defaults_form.excellon_opt_group.tooldia_entry, - "excellon_slot_tooldia": self.ui.excellon_defaults_form.excellon_opt_group.slot_tooldia_entry, - "excellon_gcode_type": self.ui.excellon_defaults_form.excellon_opt_group.excellon_gcode_type_radio, # Excellon Advanced Options "excellon_offset": self.ui.excellon_defaults_form.excellon_adv_opt_group.offset_entry, diff --git a/flatcamGUI/preferences/excellon/ExcellonOptPrefGroupUI.py b/flatcamGUI/preferences/excellon/ExcellonOptPrefGroupUI.py index cdc6ce5e..4f68eaca 100644 --- a/flatcamGUI/preferences/excellon/ExcellonOptPrefGroupUI.py +++ b/flatcamGUI/preferences/excellon/ExcellonOptPrefGroupUI.py @@ -1,10 +1,7 @@ -from PyQt5 import QtWidgets -from PyQt5.QtCore import Qt, QSettings - -from flatcamGUI.GUIElements import RadioSet, FCDoubleSpinner, FCCheckBox, FCEntry, FCSpinner, OptionalInputSection, \ - FCComboBox +from flatcamGUI.GUIElements import OptionalInputSection from flatcamGUI.preferences import machinist_setting -from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI +from flatcamGUI.preferences.OptionUI import * +from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI2 import gettext import FlatCAMTranslation as fcTranslate import builtins @@ -20,298 +17,182 @@ else: machinist_setting = 0 -class ExcellonOptPrefGroupUI(OptionsGroupUI): +class ExcellonOptPrefGroupUI(OptionsGroupUI2): - def __init__(self, decimals=4, parent=None): - # OptionsGroupUI.__init__(self, "Excellon Options", parent=parent) - super(ExcellonOptPrefGroupUI, self).__init__(self, parent=parent) - - self.setTitle(str(_("Excellon Options"))) + def __init__(self, decimals=4, **kwargs): self.decimals = decimals + super().__init__(**kwargs) + self.setTitle(str(_("Excellon Options"))) - # ## Create CNC Job - self.cncjob_label = QtWidgets.QLabel('%s' % _('Create CNC Job')) - self.cncjob_label.setToolTip( - _("Parameters used to create a CNC Job object\n" - "for this drill object.") - ) - self.layout.addWidget(self.cncjob_label) + self.pp_excellon_name_cb = self.option_dict()["excellon_ppname_e"].get_field() - grid2 = QtWidgets.QGridLayout() - self.layout.addLayout(grid2) - grid2.setColumnStretch(0, 0) - grid2.setColumnStretch(1, 1) + self.multidepth_cb = self.option_dict()["excellon_multidepth"].get_field() + self.depthperpass_entry = self.option_dict()["excellon_depthperpass"].get_field() + self.ois_multidepth = OptionalInputSection(self.multidepth_cb, [self.depthperpass_entry]) - # Operation Type - self.operation_label = QtWidgets.QLabel('%s:' % _('Operation')) - self.operation_label.setToolTip( - _("Operation type:\n" - "- Drilling -> will drill the drills/slots associated with this tool\n" - "- Milling -> will mill the drills/slots") - ) - self.operation_radio = RadioSet( - [ - {'label': _('Drilling'), 'value': 'drill'}, - {'label': _("Milling"), 'value': 'mill'} - ] - ) + self.dwell_cb = self.option_dict()["excellon_dwell"].get_field() + self.dwelltime_entry = self.option_dict()["excellon_dwelltime"].get_field() + self.ois_dwell = OptionalInputSection(self.dwell_cb, [self.dwelltime_entry]) - grid2.addWidget(self.operation_label, 0, 0) - grid2.addWidget(self.operation_radio, 0, 1) + # FIXME until this feature is implemented these are disabled + self.option_dict()["excellon_gcode_type"].label_widget.hide() + self.option_dict()["excellon_gcode_type"].get_field().hide() - self.mill_type_label = QtWidgets.QLabel('%s:' % _('Milling Type')) - self.mill_type_label.setToolTip( - _("Milling type:\n" - "- Drills -> will mill the drills associated with this tool\n" - "- Slots -> will mill the slots associated with this tool\n" - "- Both -> will mill both drills and mills or whatever is available") - ) - self.milling_type_radio = RadioSet( - [ - {'label': _('Drills'), 'value': 'drills'}, - {'label': _("Slots"), 'value': 'slots'}, - {'label': _("Both"), 'value': 'both'}, - ] - ) + def build_options(self) -> [OptionUI]: + return [ + HeadingOptionUI( + label_text="Create CNC Job", + label_tooltip="Parameters used to create a CNC Job object\n" + "for this drill object." + ), + RadioSetOptionUI( + option="excellon_operation", + label_text="Operation", + label_bold=True, + label_tooltip="Operation type:\n" + "- Drilling -> will drill the drills/slots associated with this tool\n" + "- Milling -> will mill the drills/slots", + choices=[ + {'label': _('Drilling'), 'value': 'drill'}, + {'label': _("Milling"), 'value': 'mill'} + ] + ), + RadioSetOptionUI( + option="excellon_milling_type", + label_text="Milling Type", + label_tooltip="Milling type:\n" + "- Drills -> will mill the drills associated with this tool\n" + "- Slots -> will mill the slots associated with this tool\n" + "- Both -> will mill both drills and mills or whatever is available", + choices=[ + {'label': _('Drills'), 'value': 'drills'}, + {'label': _("Slots"), 'value': 'slots'}, + {'label': _("Both"), 'value': 'both'}, + ] + ), + DoubleSpinnerOptionUI( + option="excellon_milling_dia", + label_text="Milling Diameter", + label_tooltip="The diameter of the tool who will do the milling", + min_value=0.0, max_value=9999.9999, step=0.1, decimals=self.decimals + ), + DoubleSpinnerOptionUI( + option="excellon_cutz", + label_text="Cut Z", + label_tooltip="Drill depth (negative) \nbelow the copper surface.", + min_value=-9999.9999, max_value=(9999.9999 if machinist_setting else 0.0), + step=0.1, decimals=self.decimals + ), - grid2.addWidget(self.mill_type_label, 1, 0) - grid2.addWidget(self.milling_type_radio, 1, 1) - self.mill_dia_label = QtWidgets.QLabel('%s:' % _('Milling Diameter')) - self.mill_dia_label.setToolTip( - _("The diameter of the tool who will do the milling") - ) + CheckboxOptionUI( + option="excellon_multidepth", + label_text="Multi-Depth", + label_tooltip="Use multiple passes to limit\n" + "the cut depth in each pass. Will\n" + "cut multiple times until Cut Z is\n" + "reached." + ), + DoubleSpinnerOptionUI( + option="excellon_depthperpass", + label_text="Depth/Pass", + label_tooltip="Depth of each pass (positive).", + min_value=0, max_value=99999, step=0.1, decimals=self.decimals + ), + DoubleSpinnerOptionUI( + option="excellon_travelz", + label_text="Travel Z", + label_tooltip="Tool height when travelling\nacross the XY plane.", + min_value=(-9999.9999 if machinist_setting else 0.0001), max_value=9999.9999, + step=0.1, decimals=self.decimals + ), + CheckboxOptionUI( + option="excellon_toolchange", + label_text="Tool change", + label_tooltip="Include tool-change sequence\nin G-Code (Pause for tool change)." + ), + DoubleSpinnerOptionUI( + option="excellon_toolchangez", + label_text="Toolchange Z", + label_tooltip="Z-axis position (height) for\ntool change.", + min_value=(-9999.9999 if machinist_setting else 0.0), max_value=9999.9999, + step=0.1, decimals=self.decimals + ), + DoubleSpinnerOptionUI( + option="excellon_endz", + label_text="End move Z", + label_tooltip="Height of the tool after\nthe last move at the end of the job.", + min_value=(-9999.9999 if machinist_setting else 0.0), max_value=9999.9999, + step=0.1, decimals=self.decimals + ), + LineEntryOptionUI( + option="excellon_endxy", + label_text="End move X,Y", + label_tooltip="End move X,Y position. In format (x,y).\n" + "If no value is entered then there is no move\n" + "on X,Y plane at the end of the job." + ), + DoubleSpinnerOptionUI( + option="excellon_feedrate_z", + label_text="Feedrate Z", + label_tooltip="Tool speed while drilling\n" + "(in units per minute).\n" + "So called 'Plunge' feedrate.\n" + "This is for linear move G01.", + min_value=0, max_value=99999.9999, step=0.1, decimals=self.decimals + ), + SpinnerOptionUI( + option="excellon_spindlespeed", + label_text="Spindle speed", + label_tooltip="Speed of the spindle in RPM (optional).", + min_value=0, max_value=1000000, step=100 + ), + CheckboxOptionUI( + option="excellon_dwell", + label_text="Enable Dwell", + label_tooltip="Pause to allow the spindle to reach its\nspeed before cutting." + ), + DoubleSpinnerOptionUI( + option="excellon_dwelltime", + label_text="Duration", + label_tooltip="Number of time units for spindle to dwell.", + min_value=0, max_value=999999, step=0.5, decimals=self.decimals + ), + ComboboxOptionUI( + option="excellon_ppname_e", + label_text="Preprocessor", + label_tooltip="The preprocessor JSON file that dictates\nGcode output.", # FIXME tooltip incorrect? + choices=[] # Populated in App (FIXME) + ), + RadioSetOptionUI( + option="excellon_gcode_type", + label_text="Gcode", + label_bold=True, + label_tooltip="Choose what to use for GCode generation:\n" + "'Drills', 'Slots' or 'Both'.\n" + "When choosing 'Slots' or 'Both', slots will be\n" + "converted to drills.", + choices=[ + {'label': 'Drills', 'value': 'drills'}, + {'label': 'Slots', 'value': 'slots'}, + {'label': 'Both', 'value': 'both'} + ] + ), - self.mill_dia_entry = FCDoubleSpinner() - self.mill_dia_entry.set_precision(self.decimals) - self.mill_dia_entry.set_range(0.0000, 9999.9999) - - grid2.addWidget(self.mill_dia_label, 2, 0) - grid2.addWidget(self.mill_dia_entry, 2, 1) - - # Cut Z - cutzlabel = QtWidgets.QLabel('%s:' % _('Cut Z')) - cutzlabel.setToolTip( - _("Drill depth (negative)\n" - "below the copper surface.") - ) - - self.cutz_entry = FCDoubleSpinner() - - if machinist_setting == 0: - self.cutz_entry.set_range(-9999.9999, 0.0000) - else: - self.cutz_entry.set_range(-9999.9999, 9999.9999) - - self.cutz_entry.setSingleStep(0.1) - self.cutz_entry.set_precision(self.decimals) - - grid2.addWidget(cutzlabel, 3, 0) - grid2.addWidget(self.cutz_entry, 3, 1) - - # Multi-Depth - self.mpass_cb = FCCheckBox('%s:' % _("Multi-Depth")) - self.mpass_cb.setToolTip( - _( - "Use multiple passes to limit\n" - "the cut depth in each pass. Will\n" - "cut multiple times until Cut Z is\n" - "reached." + HeadingOptionUI( + label_text="Mill Holes", + label_tooltip="Create Geometry for milling holes." + ), + DoubleSpinnerOptionUI( + option="excellon_tooldia", + label_text="Drill Tool dia", + label_tooltip="Diameter of the cutting tool", + min_value=0.0, max_value=999.9999, step=0.1, decimals=self.decimals + ), + DoubleSpinnerOptionUI( + option="excellon_slot_tooldia", + label_text="Slot Tool dia", + label_tooltip="Diameter of the cutting tool\nwhen milling slots.", + min_value=0.0, max_value=999.9999, step=0.1, decimals=self.decimals ) - ) - - self.maxdepth_entry = FCDoubleSpinner() - self.maxdepth_entry.set_precision(self.decimals) - self.maxdepth_entry.set_range(0, 9999.9999) - self.maxdepth_entry.setSingleStep(0.1) - - self.maxdepth_entry.setToolTip(_("Depth of each pass (positive).")) - - grid2.addWidget(self.mpass_cb, 4, 0) - grid2.addWidget(self.maxdepth_entry, 4, 1) - - # Travel Z - travelzlabel = QtWidgets.QLabel('%s:' % _('Travel Z')) - travelzlabel.setToolTip( - _("Tool height when travelling\n" - "across the XY plane.") - ) - - self.travelz_entry = FCDoubleSpinner() - self.travelz_entry.set_precision(self.decimals) - - if machinist_setting == 0: - self.travelz_entry.set_range(0.0001, 9999.9999) - else: - self.travelz_entry.set_range(-9999.9999, 9999.9999) - - grid2.addWidget(travelzlabel, 5, 0) - grid2.addWidget(self.travelz_entry, 5, 1) - - # Tool change: - self.toolchange_cb = FCCheckBox('%s' % _("Tool change")) - self.toolchange_cb.setToolTip( - _("Include tool-change sequence\n" - "in G-Code (Pause for tool change).") - ) - grid2.addWidget(self.toolchange_cb, 6, 0, 1, 2) - - # Tool Change Z - toolchangezlabel = QtWidgets.QLabel('%s:' % _('Toolchange Z')) - toolchangezlabel.setToolTip( - _("Z-axis position (height) for\n" - "tool change.") - ) - - self.toolchangez_entry = FCDoubleSpinner() - self.toolchangez_entry.set_precision(self.decimals) - - if machinist_setting == 0: - self.toolchangez_entry.set_range(0.0001, 9999.9999) - else: - self.toolchangez_entry.set_range(-9999.9999, 9999.9999) - - grid2.addWidget(toolchangezlabel, 7, 0) - grid2.addWidget(self.toolchangez_entry, 7, 1) - - # End Move Z - endz_label = QtWidgets.QLabel('%s:' % _('End move Z')) - endz_label.setToolTip( - _("Height of the tool after\n" - "the last move at the end of the job.") - ) - self.endz_entry = FCDoubleSpinner() - self.endz_entry.set_precision(self.decimals) - - if machinist_setting == 0: - self.endz_entry.set_range(0.0000, 9999.9999) - else: - self.endz_entry.set_range(-9999.9999, 9999.9999) - - grid2.addWidget(endz_label, 8, 0) - grid2.addWidget(self.endz_entry, 8, 1) - - # End Move X,Y - endmove_xy_label = QtWidgets.QLabel('%s:' % _('End move X,Y')) - endmove_xy_label.setToolTip( - _("End move X,Y position. In format (x,y).\n" - "If no value is entered then there is no move\n" - "on X,Y plane at the end of the job.") - ) - self.endxy_entry = FCEntry() - - grid2.addWidget(endmove_xy_label, 9, 0) - grid2.addWidget(self.endxy_entry, 9, 1) - - # Feedrate Z - frlabel = QtWidgets.QLabel('%s:' % _('Feedrate Z')) - frlabel.setToolTip( - _("Tool speed while drilling\n" - "(in units per minute).\n" - "So called 'Plunge' feedrate.\n" - "This is for linear move G01.") - ) - self.feedrate_z_entry = FCDoubleSpinner() - self.feedrate_z_entry.set_precision(self.decimals) - self.feedrate_z_entry.set_range(0, 99999.9999) - - grid2.addWidget(frlabel, 10, 0) - grid2.addWidget(self.feedrate_z_entry, 10, 1) - - # Spindle speed - spdlabel = QtWidgets.QLabel('%s:' % _('Spindle Speed')) - spdlabel.setToolTip( - _("Speed of the spindle\n" - "in RPM (optional)") - ) - - self.spindlespeed_entry = FCSpinner() - self.spindlespeed_entry.set_range(0, 1000000) - self.spindlespeed_entry.set_step(100) - - grid2.addWidget(spdlabel, 11, 0) - grid2.addWidget(self.spindlespeed_entry, 11, 1) - - # Dwell - self.dwell_cb = FCCheckBox('%s' % _('Enable Dwell')) - self.dwell_cb .setToolTip( - _("Pause to allow the spindle to reach its\n" - "speed before cutting.") - ) - - grid2.addWidget(self.dwell_cb, 12, 0, 1, 2) - - # Dwell Time - dwelltime = QtWidgets.QLabel('%s:' % _('Duration')) - dwelltime.setToolTip(_("Number of time units for spindle to dwell.")) - self.dwelltime_entry = FCDoubleSpinner() - self.dwelltime_entry.set_precision(self.decimals) - self.dwelltime_entry.set_range(0, 99999.9999) - - grid2.addWidget(dwelltime, 13, 0) - grid2.addWidget(self.dwelltime_entry, 13, 1) - - self.ois_dwell_exc = OptionalInputSection(self.dwell_cb, [self.dwelltime_entry]) - - # preprocessor selection - pp_excellon_label = QtWidgets.QLabel('%s:' % _("Preprocessor")) - pp_excellon_label.setToolTip( - _("The preprocessor JSON file that dictates\n" - "Gcode output.") - ) - - self.pp_excellon_name_cb = FCComboBox() - self.pp_excellon_name_cb.setFocusPolicy(Qt.StrongFocus) - - grid2.addWidget(pp_excellon_label, 14, 0) - grid2.addWidget(self.pp_excellon_name_cb, 14, 1) - - # ### Choose what to use for Gcode creation: Drills, Slots or Both - excellon_gcode_type_label = QtWidgets.QLabel('%s' % _('Gcode')) - excellon_gcode_type_label.setToolTip( - _("Choose what to use for GCode generation:\n" - "'Drills', 'Slots' or 'Both'.\n" - "When choosing 'Slots' or 'Both', slots will be\n" - "converted to drills.") - ) - self.excellon_gcode_type_radio = RadioSet([{'label': 'Drills', 'value': 'drills'}, - {'label': 'Slots', 'value': 'slots'}, - {'label': 'Both', 'value': 'both'}]) - grid2.addWidget(excellon_gcode_type_label, 15, 0) - grid2.addWidget(self.excellon_gcode_type_radio, 15, 1) - - # until I decide to implement this feature those remain disabled - excellon_gcode_type_label.hide() - self.excellon_gcode_type_radio.setVisible(False) - - # ### Milling Holes ## ## - self.mill_hole_label = QtWidgets.QLabel('%s' % _('Mill Holes')) - self.mill_hole_label.setToolTip( - _("Create Geometry for milling holes.") - ) - grid2.addWidget(self.mill_hole_label, 16, 0, 1, 2) - - tdlabel = QtWidgets.QLabel('%s:' % _('Drill Tool dia')) - tdlabel.setToolTip( - _("Diameter of the cutting tool.") - ) - self.tooldia_entry = FCDoubleSpinner() - self.tooldia_entry.set_precision(self.decimals) - self.tooldia_entry.set_range(0, 999.9999) - - grid2.addWidget(tdlabel, 18, 0) - grid2.addWidget(self.tooldia_entry, 18, 1) - - stdlabel = QtWidgets.QLabel('%s:' % _('Slot Tool dia')) - stdlabel.setToolTip( - _("Diameter of the cutting tool\n" - "when milling slots.") - ) - self.slot_tooldia_entry = FCDoubleSpinner() - self.slot_tooldia_entry.set_precision(self.decimals) - self.slot_tooldia_entry.set_range(0, 999.9999) - - grid2.addWidget(stdlabel, 21, 0) - grid2.addWidget(self.slot_tooldia_entry, 21, 1) - - self.layout.addStretch() + ] diff --git a/flatcamGUI/preferences/excellon/ExcellonPreferencesUI.py b/flatcamGUI/preferences/excellon/ExcellonPreferencesUI.py index 01616d37..e3584129 100644 --- a/flatcamGUI/preferences/excellon/ExcellonPreferencesUI.py +++ b/flatcamGUI/preferences/excellon/ExcellonPreferencesUI.py @@ -6,6 +6,13 @@ from flatcamGUI.preferences.excellon.ExcellonAdvOptPrefGroupUI import ExcellonAd from flatcamGUI.preferences.excellon.ExcellonOptPrefGroupUI import ExcellonOptPrefGroupUI from flatcamGUI.preferences.excellon.ExcellonGenPrefGroupUI import ExcellonGenPrefGroupUI +import gettext +import FlatCAMTranslation as fcTranslate +import builtins +fcTranslate.apply_language('strings') +if '_' not in builtins.__dict__: + _ = gettext.gettext + class ExcellonPreferencesUI(PreferencesSectionUI): From 3a1089c277b6a1ec373c65c4c2b64e43281f12ca Mon Sep 17 00:00:00 2001 From: David Robertson Date: Sun, 10 May 2020 22:43:50 +0100 Subject: [PATCH 36/41] move the excellon export settings sync code out of FlatCAMApp --- FlatCAMApp.py | 135 ------------------ .../excellon/ExcellonPreferencesUI.py | 26 ++++ 2 files changed, 26 insertions(+), 135 deletions(-) diff --git a/FlatCAMApp.py b/FlatCAMApp.py index cb9c9979..90b39e03 100644 --- a/FlatCAMApp.py +++ b/FlatCAMApp.py @@ -1011,15 +1011,6 @@ class App(QtCore.QObject): self.object_status_changed.connect(self.on_collection_updated) - # Make sure that when the Excellon loading parameters are changed, the change is reflected in the - # Export Excellon parameters. - self.ui.excellon_defaults_form.excellon_gen_group.update_excellon_cb.stateChanged.connect( - self.on_update_exc_export - ) - - # call it once to make sure it is updated at startup - self.on_update_exc_export(state=self.defaults["excellon_update"]) - # when there are arguments at application startup this get launched self.args_at_startup[list].connect(self.on_startup_args) @@ -4623,133 +4614,7 @@ class App(QtCore.QObject): self.app_cursor.enabled = True self.app_cursor.enabled = False - def on_update_exc_export(self, state): - """ - This is handling the update of Excellon Export parameters based on the ones in the Excellon General but only - if the update_excellon_cb checkbox is checked - :param state: state of the checkbox whose signals is tied to his slot - :return: - """ - if state: - # first try to disconnect - try: - self.ui.excellon_defaults_form.excellon_gen_group.excellon_format_upper_in_entry.returnPressed. \ - disconnect(self.on_excellon_format_changed) - except TypeError: - pass - try: - self.ui.excellon_defaults_form.excellon_gen_group.excellon_format_lower_in_entry.returnPressed. \ - disconnect(self.on_excellon_format_changed) - except TypeError: - pass - try: - self.ui.excellon_defaults_form.excellon_gen_group.excellon_format_upper_mm_entry.returnPressed. \ - disconnect(self.on_excellon_format_changed) - except TypeError: - pass - try: - self.ui.excellon_defaults_form.excellon_gen_group.excellon_format_lower_mm_entry.returnPressed. \ - disconnect(self.on_excellon_format_changed) - except TypeError: - pass - - try: - self.ui.excellon_defaults_form.excellon_gen_group.excellon_zeros_radio.activated_custom. \ - disconnect(self.on_excellon_zeros_changed) - except TypeError: - pass - try: - self.ui.excellon_defaults_form.excellon_gen_group.excellon_units_radio.activated_custom. \ - disconnect(self.on_excellon_zeros_changed) - except TypeError: - pass - - # the connect them - self.ui.excellon_defaults_form.excellon_gen_group.excellon_format_upper_in_entry.returnPressed.connect( - self.on_excellon_format_changed) - self.ui.excellon_defaults_form.excellon_gen_group.excellon_format_lower_in_entry.returnPressed.connect( - self.on_excellon_format_changed) - self.ui.excellon_defaults_form.excellon_gen_group.excellon_format_upper_mm_entry.returnPressed.connect( - self.on_excellon_format_changed) - self.ui.excellon_defaults_form.excellon_gen_group.excellon_format_lower_mm_entry.returnPressed.connect( - self.on_excellon_format_changed) - self.ui.excellon_defaults_form.excellon_gen_group.excellon_zeros_radio.activated_custom.connect( - self.on_excellon_zeros_changed) - self.ui.excellon_defaults_form.excellon_gen_group.excellon_units_radio.activated_custom.connect( - self.on_excellon_units_changed) - else: - # disconnect the signals - try: - self.ui.excellon_defaults_form.excellon_gen_group.excellon_format_upper_in_entry.returnPressed. \ - disconnect(self.on_excellon_format_changed) - except TypeError: - pass - try: - self.ui.excellon_defaults_form.excellon_gen_group.excellon_format_lower_in_entry.returnPressed. \ - disconnect(self.on_excellon_format_changed) - except TypeError: - pass - try: - self.ui.excellon_defaults_form.excellon_gen_group.excellon_format_upper_mm_entry.returnPressed. \ - disconnect(self.on_excellon_format_changed) - except TypeError: - pass - try: - self.ui.excellon_defaults_form.excellon_gen_group.excellon_format_lower_mm_entry.returnPressed. \ - disconnect(self.on_excellon_format_changed) - except TypeError: - pass - - try: - self.ui.excellon_defaults_form.excellon_gen_group.excellon_zeros_radio.activated_custom. \ - disconnect(self.on_excellon_zeros_changed) - except TypeError: - pass - try: - self.ui.excellon_defaults_form.excellon_gen_group.excellon_units_radio.activated_custom. \ - disconnect(self.on_excellon_zeros_changed) - except TypeError: - pass - - def on_excellon_format_changed(self): - """ - Slot activated when the user changes the Excellon format values in Preferences -> Excellon -> Excellon General - :return: None - """ - if self.ui.excellon_defaults_form.excellon_gen_group.excellon_units_radio.get_value().upper() == 'METRIC': - self.ui.excellon_defaults_form.excellon_exp_group.format_whole_entry.set_value( - self.ui.excellon_defaults_form.excellon_gen_group.excellon_format_upper_mm_entry.get_value() - ) - self.ui.excellon_defaults_form.excellon_exp_group.format_dec_entry.set_value( - self.ui.excellon_defaults_form.excellon_gen_group.excellon_format_lower_mm_entry.get_value() - ) - else: - self.ui.excellon_defaults_form.excellon_exp_group.format_whole_entry.set_value( - self.ui.excellon_defaults_form.excellon_gen_group.excellon_format_upper_in_entry.get_value() - ) - self.ui.excellon_defaults_form.excellon_exp_group.format_dec_entry.set_value( - self.ui.excellon_defaults_form.excellon_gen_group.excellon_format_lower_in_entry.get_value() - ) - - def on_excellon_zeros_changed(self): - """ - Slot activated when the user changes the Excellon zeros values in Preferences -> Excellon -> Excellon General - :return: None - """ - self.ui.excellon_defaults_form.excellon_exp_group.zeros_radio.set_value( - self.ui.excellon_defaults_form.excellon_gen_group.excellon_zeros_radio.get_value() + 'Z' - ) - - def on_excellon_units_changed(self): - """ - Slot activated when the user changes the Excellon unit values in Preferences -> Excellon -> Excellon General - :return: None - """ - self.ui.excellon_defaults_form.excellon_exp_group.excellon_units_radio.set_value( - self.ui.excellon_defaults_form.excellon_gen_group.excellon_units_radio.get_value() - ) - self.on_excellon_format_changed() def on_film_color_entry(self): self.defaults['tools_film_color'] = \ diff --git a/flatcamGUI/preferences/excellon/ExcellonPreferencesUI.py b/flatcamGUI/preferences/excellon/ExcellonPreferencesUI.py index e3584129..f406ca90 100644 --- a/flatcamGUI/preferences/excellon/ExcellonPreferencesUI.py +++ b/flatcamGUI/preferences/excellon/ExcellonPreferencesUI.py @@ -19,12 +19,23 @@ class ExcellonPreferencesUI(PreferencesSectionUI): def __init__(self, decimals, **kwargs): self.decimals = decimals self.excellon_gen_group = ExcellonGenPrefGroupUI(decimals=self.decimals) + + # FIXME: remove the need for external access to excellon_opt_group self.excellon_opt_group = ExcellonOptPrefGroupUI(decimals=self.decimals) + self.excellon_exp_group = ExcellonExpPrefGroupUI(decimals=self.decimals) self.excellon_adv_opt_group = ExcellonAdvOptPrefGroupUI(decimals=self.decimals) self.excellon_editor_group = ExcellonEditorPrefGroupUI(decimals=self.decimals) super().__init__(**kwargs) + self.excellon_gen_group.excellon_format_upper_in_entry.returnPressed.connect(self.sync_export) + self.excellon_gen_group.excellon_format_lower_in_entry.returnPressed.connect(self.sync_export) + self.excellon_gen_group.excellon_format_upper_mm_entry.returnPressed.connect(self.sync_export) + self.excellon_gen_group.excellon_format_lower_mm_entry.returnPressed.connect(self.sync_export) + self.excellon_gen_group.excellon_zeros_radio.activated_custom.connect(self.sync_export) + self.excellon_gen_group.excellon_units_radio.activated_custom.connect(self.sync_export) + + def build_groups(self) -> [OptionsGroupUI]: return [ self.excellon_gen_group, @@ -40,3 +51,18 @@ class ExcellonPreferencesUI(PreferencesSectionUI): def get_tab_label(self): return _("EXCELLON") + def sync_export(self): + if not self.excellon_gen_group.update_excellon_cb.get_value(): + # User has disabled sync. + return + + self.excellon_exp_group.zeros_radio.set_value(self.excellon_gen_group.excellon_zeros_radio.get_value() + 'Z') + self.excellon_exp_group.excellon_units_radio.set_value(self.excellon_gen_group.excellon_units_radio.get_value()) + if self.excellon_gen_group.excellon_units_radio.get_value().upper() == 'METRIC': + self.excellon_exp_group.format_whole_entry.set_value(self.excellon_gen_group.excellon_format_upper_mm_entry.get_value()) + self.excellon_exp_group.format_dec_entry.set_value(self.excellon_gen_group.excellon_format_lower_mm_entry.get_value()) + else: + self.excellon_exp_group.format_whole_entry.set_value(self.excellon_gen_group.excellon_format_upper_in_entry.get_value()) + self.excellon_exp_group.format_dec_entry.set_value(self.excellon_gen_group.excellon_format_lower_in_entry.get_value()) + + From 73479e75b68654bdb27df23319ccaa630b676cd1 Mon Sep 17 00:00:00 2001 From: David Robertson Date: Sun, 10 May 2020 23:33:21 +0100 Subject: [PATCH 37/41] excellon general --- FlatCAMApp.py | 11 +- flatcamGUI/preferences/OptionUI.py | 5 +- .../preferences/PreferencesUIManager.py | 37 -- .../excellon/ExcellonGenPrefGroupUI.py | 576 ++++++------------ .../excellon/ExcellonPreferencesUI.py | 34 +- 5 files changed, 206 insertions(+), 457 deletions(-) diff --git a/FlatCAMApp.py b/FlatCAMApp.py index 90b39e03..7fc15f8d 100644 --- a/FlatCAMApp.py +++ b/FlatCAMApp.py @@ -452,6 +452,8 @@ class App(QtCore.QObject): self.current_units = self.defaults['units'] + + # ########################################################################################################### # #################################### SETUP OBJECT CLASSES ################################################# # ########################################################################################################### @@ -1590,11 +1592,7 @@ class App(QtCore.QObject): self.set_ui_title(name=_("New Project - Not saved")) - # disable the Excellon path optimizations made with Google OR-Tools if the app is run on a 32bit platform - current_platform = platform.architecture()[0] - if current_platform != '64bit': - self.ui.excellon_defaults_form.excellon_gen_group.excellon_optimization_radio.set_value('T') - self.ui.excellon_defaults_form.excellon_gen_group.excellon_optimization_radio.setDisabled(True) + # ########################################################################################################### # ########################################### EXCLUSION AREAS ############################################### @@ -10340,8 +10338,7 @@ class App(QtCore.QObject): alpha_level = 'BF' for sel_obj in sel_obj_list: if sel_obj.kind == 'excellon': - alpha_level = str(hex( - self.ui.excellon_defaults_form.excellon_gen_group.color_alpha_slider.value())[2:]) + alpha_level = self.defaults["excellon_plot_fill"][7:] elif sel_obj.kind == 'gerber': alpha_level = self.defaults["gerber_plot_fill"][7:] elif sel_obj.kind == 'geometry': diff --git a/flatcamGUI/preferences/OptionUI.py b/flatcamGUI/preferences/OptionUI.py index ce851d4f..824c417a 100644 --- a/flatcamGUI/preferences/OptionUI.py +++ b/flatcamGUI/preferences/OptionUI.py @@ -302,7 +302,7 @@ class SeparatorOptionUI(OptionUI): class FullWidthButtonOptionUI(OptionUI): - def __init__(self, option: str, label_text: str, label_tooltip: str): + def __init__(self, option: str, label_text: str, label_tooltip: Union[str, None]): super().__init__(option=option) self.label_text = label_text self.label_tooltip = label_tooltip @@ -310,7 +310,8 @@ class FullWidthButtonOptionUI(OptionUI): def build_button_widget(self): button = FCButton(_(self.label_text)) - button.setToolTip(_(self.label_tooltip)) + if self.label_tooltip is not None: + button.setToolTip(_(self.label_tooltip)) return button def add_to_grid(self, grid: QtWidgets.QGridLayout, row: int) -> int: diff --git a/flatcamGUI/preferences/PreferencesUIManager.py b/flatcamGUI/preferences/PreferencesUIManager.py index de0a23fd..71d8d642 100644 --- a/flatcamGUI/preferences/PreferencesUIManager.py +++ b/flatcamGUI/preferences/PreferencesUIManager.py @@ -49,26 +49,6 @@ class PreferencesUIManager: # def new_object(self, kind, name, initialize, active=True, fit=True, plot=True) self.defaults_form_fields = { - # Excellon General - "excellon_plot": self.ui.excellon_defaults_form.excellon_gen_group.plot_cb, - "excellon_solid": self.ui.excellon_defaults_form.excellon_gen_group.solid_cb, - "excellon_format_upper_in": - self.ui.excellon_defaults_form.excellon_gen_group.excellon_format_upper_in_entry, - "excellon_format_lower_in": - self.ui.excellon_defaults_form.excellon_gen_group.excellon_format_lower_in_entry, - "excellon_format_upper_mm": - self.ui.excellon_defaults_form.excellon_gen_group.excellon_format_upper_mm_entry, - "excellon_format_lower_mm": - self.ui.excellon_defaults_form.excellon_gen_group.excellon_format_lower_mm_entry, - "excellon_zeros": self.ui.excellon_defaults_form.excellon_gen_group.excellon_zeros_radio, - "excellon_units": self.ui.excellon_defaults_form.excellon_gen_group.excellon_units_radio, - "excellon_update": self.ui.excellon_defaults_form.excellon_gen_group.update_excellon_cb, - "excellon_optimization_type": self.ui.excellon_defaults_form.excellon_gen_group.excellon_optimization_radio, - "excellon_search_time": self.ui.excellon_defaults_form.excellon_gen_group.optimization_time_entry, - "excellon_plot_fill": self.ui.excellon_defaults_form.excellon_gen_group.fill_color_entry, - "excellon_plot_line": self.ui.excellon_defaults_form.excellon_gen_group.line_color_entry, - - # Excellon Advanced Options "excellon_offset": self.ui.excellon_defaults_form.excellon_adv_opt_group.offset_entry, "excellon_toolchangexy": self.ui.excellon_defaults_form.excellon_adv_opt_group.toolchangexy_entry, @@ -485,23 +465,6 @@ class PreferencesUIManager: log.debug("Finished Preferences GUI form initialization.") def __init_color_pickers(self): - # Init Excellon Plot Colors - self.ui.excellon_defaults_form.excellon_gen_group.fill_color_entry.set_value( - self.defaults['excellon_plot_fill']) - self.ui.excellon_defaults_form.excellon_gen_group.fill_color_button.setStyleSheet( - "background-color:%s;" - "border-color: dimgray" % str(self.defaults['excellon_plot_fill'])[:7]) - self.ui.excellon_defaults_form.excellon_gen_group.color_alpha_spinner.set_value( - int(self.defaults['excellon_plot_fill'][7:9], 16)) - self.ui.excellon_defaults_form.excellon_gen_group.color_alpha_slider.setValue( - int(self.defaults['excellon_plot_fill'][7:9], 16)) - - self.ui.excellon_defaults_form.excellon_gen_group.line_color_entry.set_value( - self.defaults['excellon_plot_line']) - self.ui.excellon_defaults_form.excellon_gen_group.line_color_button.setStyleSheet( - "background-color:%s;" - "border-color: dimgray" % str(self.defaults['excellon_plot_line'])[:7]) - # Init the Tool Film color self.ui.tools_defaults_form.tools_film_group.film_color_entry.set_value( self.defaults['tools_film_color']) diff --git a/flatcamGUI/preferences/excellon/ExcellonGenPrefGroupUI.py b/flatcamGUI/preferences/excellon/ExcellonGenPrefGroupUI.py index 06d4dfc7..91b3dcde 100644 --- a/flatcamGUI/preferences/excellon/ExcellonGenPrefGroupUI.py +++ b/flatcamGUI/preferences/excellon/ExcellonGenPrefGroupUI.py @@ -1,415 +1,199 @@ import platform +from flatcamGUI.preferences.OptionUI import * +from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI2 -from PyQt5 import QtWidgets, QtCore, QtGui -from PyQt5.QtCore import QSettings - -from flatcamGUI.GUIElements import FCCheckBox, FCSpinner, RadioSet, FCEntry -from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI import gettext import FlatCAMTranslation as fcTranslate import builtins - fcTranslate.apply_language('strings') if '_' not in builtins.__dict__: _ = gettext.gettext -settings = QSettings("Open Source", "FlatCAM") -if settings.contains("machinist"): - machinist_setting = settings.value('machinist', type=int) -else: - machinist_setting = 0 +class ExcellonGenPrefGroupUI(OptionsGroupUI2): -class ExcellonGenPrefGroupUI(OptionsGroupUI): - - def __init__(self, decimals=4, parent=None): - # OptionsGroupUI.__init__(self, "Excellon Options", parent=parent) - super(ExcellonGenPrefGroupUI, self).__init__(self, parent=parent) - - self.setTitle(str(_("Excellon General"))) + def __init__(self, decimals=4, **kwargs): self.decimals = decimals + super().__init__(**kwargs) + self.setTitle(str(_("Excellon General"))) - # Plot options - self.plot_options_label = QtWidgets.QLabel("%s:" % _("Plot Options")) - self.layout.addWidget(self.plot_options_label) + # disable the Excellon path optimizations made with Google OR-Tools if the app is run on a 32bit platform + if platform.architecture()[0] != '64bit': + self.option_dict()["excellon_optimization_type"].get_field().set_value('T') + self.option_dict()["excellon_optimization_type"].get_field().setDisabled(True) + self.option_dict()["excellon_optimization_type"].label_widget.setDisabled(True) - grid1 = QtWidgets.QGridLayout() - self.layout.addLayout(grid1) - - self.plot_cb = FCCheckBox(label=_('Plot')) - self.plot_cb.setToolTip( - "Plot (show) this object." - ) - grid1.addWidget(self.plot_cb, 0, 0) - - self.solid_cb = FCCheckBox(label=_('Solid')) - self.solid_cb.setToolTip( - "Plot as solid circles." - ) - grid1.addWidget(self.solid_cb, 0, 1) - - separator_line = QtWidgets.QFrame() - separator_line.setFrameShape(QtWidgets.QFrame.HLine) - separator_line.setFrameShadow(QtWidgets.QFrame.Sunken) - grid1.addWidget(separator_line, 1, 0, 1, 2) - - grid2 = QtWidgets.QGridLayout() - self.layout.addLayout(grid2) - grid2.setColumnStretch(0, 0) - grid2.setColumnStretch(1, 1) - - # Excellon format - self.excellon_format_label = QtWidgets.QLabel("%s:" % _("Excellon Format")) - self.excellon_format_label.setToolTip( - _("The NC drill files, usually named Excellon files\n" - "are files that can be found in different formats.\n" - "Here we set the format used when the provided\n" - "coordinates are not using period.\n" - "\n" - "Possible presets:\n" - "\n" - "PROTEUS 3:3 MM LZ\n" - "DipTrace 5:2 MM TZ\n" - "DipTrace 4:3 MM LZ\n" - "\n" - "EAGLE 3:3 MM TZ\n" - "EAGLE 4:3 MM TZ\n" - "EAGLE 2:5 INCH TZ\n" - "EAGLE 3:5 INCH TZ\n" - "\n" - "ALTIUM 2:4 INCH LZ\n" - "Sprint Layout 2:4 INCH LZ" - "\n" - "KiCAD 3:5 INCH TZ") - ) - grid2.addWidget(self.excellon_format_label, 0, 0, 1, 2) - - self.excellon_format_in_label = QtWidgets.QLabel('%s:' % _("INCH")) - self.excellon_format_in_label.setToolTip(_("Default values for INCH are 2:4")) - - hlay1 = QtWidgets.QHBoxLayout() - self.excellon_format_upper_in_entry = FCSpinner() - self.excellon_format_upper_in_entry.set_range(0, 9) - self.excellon_format_upper_in_entry.setMinimumWidth(30) - self.excellon_format_upper_in_entry.setToolTip( - _("This numbers signify the number of digits in\n" - "the whole part of Excellon coordinates.") - ) - hlay1.addWidget(self.excellon_format_upper_in_entry) - - excellon_separator_in_label = QtWidgets.QLabel(':') - excellon_separator_in_label.setFixedWidth(5) - hlay1.addWidget(excellon_separator_in_label) - - self.excellon_format_lower_in_entry = FCSpinner() - self.excellon_format_lower_in_entry.set_range(0, 9) - self.excellon_format_lower_in_entry.setMinimumWidth(30) - self.excellon_format_lower_in_entry.setToolTip( - _("This numbers signify the number of digits in\n" - "the decimal part of Excellon coordinates.") - ) - hlay1.addWidget(self.excellon_format_lower_in_entry) - - grid2.addWidget(self.excellon_format_in_label, 1, 0) - grid2.addLayout(hlay1, 1, 1) - - self.excellon_format_mm_label = QtWidgets.QLabel('%s:' % _("METRIC")) - self.excellon_format_mm_label.setToolTip(_("Default values for METRIC are 3:3")) - - hlay2 = QtWidgets.QHBoxLayout() - self.excellon_format_upper_mm_entry = FCSpinner() - self.excellon_format_upper_mm_entry.set_range(0, 9) - self.excellon_format_upper_mm_entry.setMinimumWidth(30) - self.excellon_format_upper_mm_entry.setToolTip( - _("This numbers signify the number of digits in\n" - "the whole part of Excellon coordinates.") - ) - hlay2.addWidget(self.excellon_format_upper_mm_entry) - - excellon_separator_mm_label = QtWidgets.QLabel(':') - excellon_separator_mm_label.setFixedWidth(5) - hlay2.addWidget(excellon_separator_mm_label, QtCore.Qt.AlignLeft) - - self.excellon_format_lower_mm_entry = FCSpinner() - self.excellon_format_lower_mm_entry.set_range(0, 9) - self.excellon_format_lower_mm_entry.setMinimumWidth(30) - self.excellon_format_lower_mm_entry.setToolTip( - _("This numbers signify the number of digits in\n" - "the decimal part of Excellon coordinates.") - ) - hlay2.addWidget(self.excellon_format_lower_mm_entry) - - grid2.addWidget(self.excellon_format_mm_label, 2, 0) - grid2.addLayout(hlay2, 2, 1) - - self.excellon_zeros_label = QtWidgets.QLabel('%s:' % _('Zeros')) - self.excellon_zeros_label.setAlignment(QtCore.Qt.AlignLeft) - self.excellon_zeros_label.setToolTip( - _("This sets the type of Excellon zeros.\n" - "If LZ then Leading Zeros are kept and\n" - "Trailing Zeros are removed.\n" - "If TZ is checked then Trailing Zeros are kept\n" - "and Leading Zeros are removed.\n\n" - "This is used when there is no information\n" - "stored in the Excellon file.") - ) - grid2.addWidget(self.excellon_zeros_label, 3, 0) - - self.excellon_zeros_radio = RadioSet([{'label': _('LZ'), 'value': 'L'}, - {'label': _('TZ'), 'value': 'T'}]) - - grid2.addWidget(self.excellon_zeros_radio, 3, 1) - - self.excellon_units_label = QtWidgets.QLabel('%s:' % _('Units')) - self.excellon_units_label.setAlignment(QtCore.Qt.AlignLeft) - self.excellon_units_label.setToolTip( - _("This sets the default units of Excellon files.\n" - "If it is not detected in the parsed file the value here\n" - "will be used." - "Some Excellon files don't have an header\n" - "therefore this parameter will be used.") - ) - - self.excellon_units_radio = RadioSet([{'label': _('INCH'), 'value': 'INCH'}, - {'label': _('MM'), 'value': 'METRIC'}]) - self.excellon_units_radio.setToolTip( - _("This sets the units of Excellon files.\n" - "Some Excellon files don't have an header\n" - "therefore this parameter will be used.") - ) - - grid2.addWidget(self.excellon_units_label, 4, 0) - grid2.addWidget(self.excellon_units_radio, 4, 1) - - self.update_excellon_cb = FCCheckBox(label=_('Update Export settings')) - self.update_excellon_cb.setToolTip( - "If checked, the Excellon Export settings will be updated with the ones above." - ) - grid2.addWidget(self.update_excellon_cb, 5, 0, 1, 2) - - # Adding the Excellon Format Defaults Button - self.excellon_defaults_button = QtWidgets.QPushButton() - self.excellon_defaults_button.setText(str(_("Restore Defaults"))) - self.excellon_defaults_button.setMinimumWidth(80) - grid2.addWidget(self.excellon_defaults_button, 6, 0, 1, 2) - - separator_line = QtWidgets.QFrame() - separator_line.setFrameShape(QtWidgets.QFrame.HLine) - separator_line.setFrameShadow(QtWidgets.QFrame.Sunken) - grid2.addWidget(separator_line, 7, 0, 1, 2) - - self.excellon_general_label = QtWidgets.QLabel("%s:" % _("Excellon Optimization")) - grid2.addWidget(self.excellon_general_label, 8, 0, 1, 2) - - self.excellon_optimization_label = QtWidgets.QLabel(_('Algorithm:')) - self.excellon_optimization_label.setToolTip( - _("This sets the optimization type for the Excellon drill path.\n" - "If <> is checked then Google OR-Tools algorithm with\n" - "MetaHeuristic Guided Local Path is used. Default search time is 3sec.\n" - "If <> is checked then Google OR-Tools Basic algorithm is used.\n" - "If <> is checked then Travelling Salesman algorithm is used for\n" - "drill path optimization.\n" - "\n" - "If this control is disabled, then FlatCAM works in 32bit mode and it uses\n" - "Travelling Salesman algorithm for path optimization.") - ) - - self.excellon_optimization_radio = RadioSet([{'label': _('MetaHeuristic'), 'value': 'M'}, - {'label': _('Basic'), 'value': 'B'}, - {'label': _('TSA'), 'value': 'T'}], - orientation='vertical', stretch=False) - self.excellon_optimization_radio.setToolTip( - _("This sets the optimization type for the Excellon drill path.\n" - "If <> is checked then Google OR-Tools algorithm with\n" - "MetaHeuristic Guided Local Path is used. Default search time is 3sec.\n" - "If <> is checked then Google OR-Tools Basic algorithm is used.\n" - "If <> is checked then Travelling Salesman algorithm is used for\n" - "drill path optimization.\n" - "\n" - "If this control is disabled, then FlatCAM works in 32bit mode and it uses\n" - "Travelling Salesman algorithm for path optimization.") - ) - - grid2.addWidget(self.excellon_optimization_label, 9, 0) - grid2.addWidget(self.excellon_optimization_radio, 9, 1) - - self.optimization_time_label = QtWidgets.QLabel('%s:' % _('Duration')) - self.optimization_time_label.setAlignment(QtCore.Qt.AlignLeft) - self.optimization_time_label.setToolTip( - _("When OR-Tools Metaheuristic (MH) is enabled there is a\n" - "maximum threshold for how much time is spent doing the\n" - "path optimization. This max duration is set here.\n" - "In seconds.") - - ) - - self.optimization_time_entry = FCSpinner() - self.optimization_time_entry.set_range(0, 999) - - grid2.addWidget(self.optimization_time_label, 10, 0) - grid2.addWidget(self.optimization_time_entry, 10, 1) - - separator_line = QtWidgets.QFrame() - separator_line.setFrameShape(QtWidgets.QFrame.HLine) - separator_line.setFrameShadow(QtWidgets.QFrame.Sunken) - grid2.addWidget(separator_line, 11, 0, 1, 2) - - # Excellon Object Color - self.gerber_color_label = QtWidgets.QLabel('%s' % _('Excellon Object Color')) - grid2.addWidget(self.gerber_color_label, 12, 0, 1, 2) - - # Plot Line Color - self.line_color_label = QtWidgets.QLabel('%s:' % _('Outline')) - self.line_color_label.setToolTip( - _("Set the line color for plotted objects.") - ) - self.line_color_entry = FCEntry() - self.line_color_button = QtWidgets.QPushButton() - self.line_color_button.setFixedSize(15, 15) - - self.form_box_child_2 = QtWidgets.QHBoxLayout() - self.form_box_child_2.addWidget(self.line_color_entry) - self.form_box_child_2.addWidget(self.line_color_button) - self.form_box_child_2.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter) - - grid2.addWidget(self.line_color_label, 13, 0) - grid2.addLayout(self.form_box_child_2, 13, 1) - - # Plot Fill Color - self.fill_color_label = QtWidgets.QLabel('%s:' % _('Fill')) - self.fill_color_label.setToolTip( - _("Set the fill color for plotted objects.\n" - "First 6 digits are the color and the last 2\n" - "digits are for alpha (transparency) level.") - ) - self.fill_color_entry = FCEntry() - self.fill_color_button = QtWidgets.QPushButton() - self.fill_color_button.setFixedSize(15, 15) - - self.form_box_child_1 = QtWidgets.QHBoxLayout() - self.form_box_child_1.addWidget(self.fill_color_entry) - self.form_box_child_1.addWidget(self.fill_color_button) - self.form_box_child_1.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter) - - grid2.addWidget(self.fill_color_label, 14, 0) - grid2.addLayout(self.form_box_child_1, 14, 1) - - # Plot Fill Transparency Level - self.alpha_label = QtWidgets.QLabel('%s:' % _('Alpha')) - self.alpha_label.setToolTip( - _("Set the fill transparency for plotted objects.") - ) - self.color_alpha_slider = QtWidgets.QSlider(QtCore.Qt.Horizontal) - self.color_alpha_slider.setMinimum(0) - self.color_alpha_slider.setMaximum(255) - self.color_alpha_slider.setSingleStep(1) - - self.color_alpha_spinner = FCSpinner() - self.color_alpha_spinner.setMinimumWidth(70) - self.color_alpha_spinner.set_range(0, 255) - - self.form_box_child_3 = QtWidgets.QHBoxLayout() - self.form_box_child_3.addWidget(self.color_alpha_slider) - self.form_box_child_3.addWidget(self.color_alpha_spinner) - - grid2.addWidget(self.alpha_label, 15, 0) - grid2.addLayout(self.form_box_child_3, 15, 1) - - self.layout.addStretch() - - current_platform = platform.architecture()[0] - if current_platform == '64bit': - self.excellon_optimization_label.setDisabled(False) - self.excellon_optimization_radio.setDisabled(False) - self.optimization_time_label.setDisabled(False) - self.optimization_time_entry.setDisabled(False) - self.excellon_optimization_radio.activated_custom.connect(self.optimization_selection) - - else: - self.excellon_optimization_label.setDisabled(True) - self.excellon_optimization_radio.setDisabled(True) - self.optimization_time_label.setDisabled(True) - self.optimization_time_entry.setDisabled(True) - - # Setting plot colors signals - self.line_color_entry.editingFinished.connect(self.on_line_color_entry) - self.line_color_button.clicked.connect(self.on_line_color_button) - self.fill_color_entry.editingFinished.connect(self.on_fill_color_entry) - self.fill_color_button.clicked.connect(self.on_fill_color_button) - self.color_alpha_spinner.valueChanged.connect(self.on_color_spinner) - self.color_alpha_slider.valueChanged.connect(self.on_color_slider) + # Enable/disable the duration box according to type selected + self.option_dict()["excellon_optimization_type"].get_field().activated_custom.connect(self.optimization_selection) + self.optimization_selection() # Load the defaults values into the Excellon Format and Excellon Zeros fields - self.excellon_defaults_button.clicked.connect(self.on_excellon_defaults_button) + self.option_dict()["__excellon_restore_defaults"].get_field().clicked.connect(self.on_defaults_button) + + + def build_options(self) -> [OptionUI]: + return [ + HeadingOptionUI(label_text="Plot Options"), + CheckboxOptionUI( + option="excellon_plot", + label_text="Plot", + label_tooltip="Plot (show) this object." + ), + CheckboxOptionUI( + option="excellon_solid", + label_text="Solid", + label_tooltip="Plot as solid circles." + ), + SeparatorOptionUI(), + + HeadingOptionUI( + label_text="Excellon Format", + label_tooltip="The NC drill files, usually named Excellon files\n" + "are files that can be found in different formats.\n" + "Here we set the format used when the provided\n" + "coordinates are not using period.\n" + "\n" + "Possible presets:\n" + "\n" + "PROTEUS 3:3 MM LZ\n" + "DipTrace 5:2 MM TZ\n" + "DipTrace 4:3 MM LZ\n" + "\n" + "EAGLE 3:3 MM TZ\n" + "EAGLE 4:3 MM TZ\n" + "EAGLE 2:5 INCH TZ\n" + "EAGLE 3:5 INCH TZ\n" + "\n" + "ALTIUM 2:4 INCH LZ\n" + "Sprint Layout 2:4 INCH LZ" + "\n" + "KiCAD 3:5 INCH TZ" + ), + SpinnerOptionUI( + option="excellon_format_upper_in", + label_text="INCH int", + label_tooltip="This number signifies the number of digits in\nthe whole part of Excellon coordinates.", + min_value=0, max_value=9, step=1 + ), + SpinnerOptionUI( + option="excellon_format_lower_in", + label_text="INCH decimals", + label_tooltip="This number signifies the number of digits in\nthe decimal part of Excellon coordinates.", + min_value=0, max_value=9, step=1 + ), + SpinnerOptionUI( + option="excellon_format_upper_mm", + label_text="METRIC int", + label_tooltip="This number signifies the number of digits in\nthe whole part of Excellon coordinates.", + min_value=0, max_value=9, step=1 + ), + SpinnerOptionUI( + option="excellon_format_lower_mm", + label_text="METRIC decimals", + label_tooltip="This number signifies the number of digits in\nthe decimal part of Excellon coordinates.", + min_value=0, max_value=9, step=1 + ), + RadioSetOptionUI( + option="excellon_zeros", + label_text="Zeros", + label_tooltip="This sets the type of Excellon zeros.\n" + "If LZ then Leading Zeros are kept and\n" + "Trailing Zeros are removed.\n" + "If TZ is checked then Trailing Zeros are kept\n" + "and Leading Zeros are removed.\n\n" + "This is used when there is no information\n" + "stored in the Excellon file.", + choices=[ + {'label': _('LZ'), 'value': 'L'}, + {'label': _('TZ'), 'value': 'T'} + ] + ), + RadioSetOptionUI( + option="excellon_units", + label_text="Units", + label_tooltip="This sets the default units of Excellon files.\n" + "If it is not detected in the parsed file the value here\n" + "will be used." + "Some Excellon files don't have an header\n" + "therefore this parameter will be used.", + choices=[ + {'label': _('INCH'), 'value': 'INCH'}, + {'label': _('MM'), 'value': 'METRIC'} + ] + ), + CheckboxOptionUI( + option="excellon_update", + label_text="Update Export settings", + label_tooltip="If checked, the Excellon Export settings will be updated with the ones above." + ), + FullWidthButtonOptionUI( + option="__excellon_restore_defaults", + label_text="Restore Defaults", + label_tooltip=None + ), + SeparatorOptionUI(), + + HeadingOptionUI(label_text="Excellon Optimization"), + RadioSetOptionUI( + option="excellon_optimization_type", + label_text="Algorithm", + label_tooltip="This sets the optimization type for the Excellon drill path.\n" + "If <> is checked then Google OR-Tools algorithm with\n" + "MetaHeuristic Guided Local Path is used. Default search time is 3sec.\n" + "If <> is checked then Google OR-Tools Basic algorithm is used.\n" + "If <> is checked then Travelling Salesman algorithm is used for\n" + "drill path optimization.\n" + "\n" + "If this control is disabled, then FlatCAM works in 32bit mode and it uses\n" + "Travelling Salesman algorithm for path optimization.", + choices=[ + {'label': _('MetaHeuristic'), 'value': 'M'}, + {'label': _('Basic'), 'value': 'B'}, + {'label': _('TSA'), 'value': 'T'} + ], + orientation="vertical" + ), + SpinnerOptionUI( + option="excellon_search_time", + label_text="Duration", + label_tooltip="When OR-Tools Metaheuristic (MH) is enabled there is a\n" + "maximum threshold for how much time is spent doing the\n" + "path optimization. This max duration is set here.\n" + "In seconds.", + min_value=1, max_value=999, step=1 + ), + SeparatorOptionUI(), + + HeadingOptionUI(label_text="Excellon Object Color"), + ColorOptionUI( + option="excellon_plot_line", + label_text="Outline", + label_tooltip="Set the line color for plotted objects.", + ), + ColorOptionUI( + option="excellon_plot_fill", + label_text="Fill", + label_tooltip="Set the fill color for plotted objects.\n" + "First 6 digits are the color and the last 2\n" + "digits are for alpha (transparency) level." + ), + ColorAlphaSliderOptionUI( + applies_to=["excellon_plot_line", "excellon_plot_fill"], + group=self, + label_text="Alpha", + label_tooltip="Set the transparency for plotted objects." + ) + ] def optimization_selection(self): - if self.excellon_optimization_radio.get_value() == 'M': - self.optimization_time_label.setDisabled(False) - self.optimization_time_entry.setDisabled(False) - else: - self.optimization_time_label.setDisabled(True) - self.optimization_time_entry.setDisabled(True) + disable_time = (self.option_dict()["excellon_optimization_type"].get_field().get_value() != 'M') + self.option_dict()["excellon_search_time"].label_widget.setDisabled(disable_time) + self.option_dict()["excellon_search_time"].get_field().setDisabled(disable_time) - # Setting plot colors handlers - def on_fill_color_entry(self): - self.app.defaults['excellon_plot_fill'] = self.fill_color_entry.get_value()[:7] + \ - self.app.defaults['excellon_plot_fill'][7:9] - self.fill_color_button.setStyleSheet("background-color:%s" % str(self.app.defaults['excellon_plot_fill'])[:7]) - - def on_fill_color_button(self): - current_color = QtGui.QColor(self.app.defaults['excellon_plot_fill'][:7]) - - c_dialog = QtWidgets.QColorDialog() - plot_fill_color = c_dialog.getColor(initial=current_color) - - if plot_fill_color.isValid() is False: - return - - self.fill_color_button.setStyleSheet("background-color:%s" % str(plot_fill_color.name())) - - new_val = str(plot_fill_color.name()) + str(self.app.defaults['excellon_plot_fill'][7:9]) - self.fill_color_entry.set_value(new_val) - self.app.defaults['excellon_plot_fill'] = new_val - - def on_color_spinner(self): - spinner_value = self.color_alpha_spinner.value() - self.color_alpha_slider.setValue(spinner_value) - self.app.defaults['excellon_plot_fill'] = \ - self.app.defaults['excellon_plot_fill'][:7] + \ - (hex(spinner_value)[2:] if int(hex(spinner_value)[2:], 16) > 0 else '00') - self.app.defaults['excellon_plot_line'] = \ - self.app.defaults['excellon_plot_line'][:7] + \ - (hex(spinner_value)[2:] if int(hex(spinner_value)[2:], 16) > 0 else '00') - - def on_color_slider(self): - slider_value = self.color_alpha_slider.value() - self.color_alpha_spinner.setValue(slider_value) - - def on_line_color_entry(self): - self.app.defaults['excellon_plot_line'] = self.line_color_entry.get_value()[:7] + \ - self.app.defaults['excellon_plot_line'][7:9] - self.line_color_button.setStyleSheet("background-color:%s" % str(self.app.defaults['excellon_plot_line'])[:7]) - - def on_line_color_button(self): - current_color = QtGui.QColor(self.app.defaults['excellon_plot_line'][:7]) - # print(current_color) - - c_dialog = QtWidgets.QColorDialog() - plot_line_color = c_dialog.getColor(initial=current_color) - - if plot_line_color.isValid() is False: - return - - self.line_color_button.setStyleSheet("background-color:%s" % str(plot_line_color.name())) - - new_val_line = str(plot_line_color.name()) + str(self.app.defaults['excellon_plot_line'][7:9]) - self.line_color_entry.set_value(new_val_line) - self.app.defaults['excellon_plot_line'] = new_val_line - - def on_excellon_defaults_button(self): - self.app.preferencesUiManager.defaults_form_fields["excellon_format_lower_in"].set_value('4') - self.app.preferencesUiManager.defaults_form_fields["excellon_format_upper_in"].set_value('2') - self.app.preferencesUiManager.defaults_form_fields["excellon_format_lower_mm"].set_value('3') - self.app.preferencesUiManager.defaults_form_fields["excellon_format_upper_mm"].set_value('3') - self.app.preferencesUiManager.defaults_form_fields["excellon_zeros"].set_value('L') - self.app.preferencesUiManager.defaults_form_fields["excellon_units"].set_value('INCH') + def on_defaults_button(self): + self.option_dict()["excellon_format_lower_in"].get_field().set_value('4') + self.option_dict()["excellon_format_upper_in"].get_field().set_value('2') + self.option_dict()["excellon_format_lower_mm"].get_field().set_value('3') + self.option_dict()["excellon_format_upper_mm"].get_field().set_value('3') + self.option_dict()["excellon_zeros"].get_field().set_value('L') + self.option_dict()["excellon_units"].get_field().set_value('INCH') diff --git a/flatcamGUI/preferences/excellon/ExcellonPreferencesUI.py b/flatcamGUI/preferences/excellon/ExcellonPreferencesUI.py index f406ca90..364c623c 100644 --- a/flatcamGUI/preferences/excellon/ExcellonPreferencesUI.py +++ b/flatcamGUI/preferences/excellon/ExcellonPreferencesUI.py @@ -26,14 +26,9 @@ class ExcellonPreferencesUI(PreferencesSectionUI): self.excellon_exp_group = ExcellonExpPrefGroupUI(decimals=self.decimals) self.excellon_adv_opt_group = ExcellonAdvOptPrefGroupUI(decimals=self.decimals) self.excellon_editor_group = ExcellonEditorPrefGroupUI(decimals=self.decimals) - super().__init__(**kwargs) - self.excellon_gen_group.excellon_format_upper_in_entry.returnPressed.connect(self.sync_export) - self.excellon_gen_group.excellon_format_lower_in_entry.returnPressed.connect(self.sync_export) - self.excellon_gen_group.excellon_format_upper_mm_entry.returnPressed.connect(self.sync_export) - self.excellon_gen_group.excellon_format_lower_mm_entry.returnPressed.connect(self.sync_export) - self.excellon_gen_group.excellon_zeros_radio.activated_custom.connect(self.sync_export) - self.excellon_gen_group.excellon_units_radio.activated_custom.connect(self.sync_export) + super().__init__(**kwargs) + self.init_sync_export() def build_groups(self) -> [OptionsGroupUI]: @@ -51,18 +46,27 @@ class ExcellonPreferencesUI(PreferencesSectionUI): def get_tab_label(self): return _("EXCELLON") + def init_sync_export(self): + self.option_dict()["excellon_update"].get_field().stateChanged.connect(self.sync_export) + self.option_dict()["excellon_format_upper_in"].get_field().returnPressed.connect(self.sync_export) + self.option_dict()["excellon_format_lower_in"].get_field().returnPressed.connect(self.sync_export) + self.option_dict()["excellon_format_upper_mm"].get_field().returnPressed.connect(self.sync_export) + self.option_dict()["excellon_format_lower_mm"].get_field().returnPressed.connect(self.sync_export) + self.option_dict()["excellon_zeros"].get_field().activated_custom.connect(self.sync_export) + self.option_dict()["excellon_units"].get_field().activated_custom.connect(self.sync_export) + def sync_export(self): - if not self.excellon_gen_group.update_excellon_cb.get_value(): + if not self.option_dict()["excellon_update"].get_field().get_value(): # User has disabled sync. return - self.excellon_exp_group.zeros_radio.set_value(self.excellon_gen_group.excellon_zeros_radio.get_value() + 'Z') - self.excellon_exp_group.excellon_units_radio.set_value(self.excellon_gen_group.excellon_units_radio.get_value()) - if self.excellon_gen_group.excellon_units_radio.get_value().upper() == 'METRIC': - self.excellon_exp_group.format_whole_entry.set_value(self.excellon_gen_group.excellon_format_upper_mm_entry.get_value()) - self.excellon_exp_group.format_dec_entry.set_value(self.excellon_gen_group.excellon_format_lower_mm_entry.get_value()) + self.excellon_exp_group.zeros_radio.set_value(self.option_dict()["excellon_zeros"].get_field().get_value() + 'Z') + self.excellon_exp_group.excellon_units_radio.set_value(self.option_dict()["excellon_units"].get_field().get_value()) + if self.option_dict()["excellon_units"].get_field().get_value().upper() == 'METRIC': + self.excellon_exp_group.format_whole_entry.set_value(self.option_dict()["excellon_format_upper_mm"].get_field().get_value()) + self.excellon_exp_group.format_dec_entry.set_value(self.option_dict()["excellon_format_lower_mm"].get_field().get_value()) else: - self.excellon_exp_group.format_whole_entry.set_value(self.excellon_gen_group.excellon_format_upper_in_entry.get_value()) - self.excellon_exp_group.format_dec_entry.set_value(self.excellon_gen_group.excellon_format_lower_in_entry.get_value()) + self.excellon_exp_group.format_whole_entry.set_value(self.option_dict()["excellon_format_upper_in"].get_field().get_value()) + self.excellon_exp_group.format_dec_entry.set_value(self.option_dict()["excellon_format_lower_in"].get_field().get_value()) From d464fa587823397632cf609fbbf87a18319023b5 Mon Sep 17 00:00:00 2001 From: David Robertson Date: Sun, 10 May 2020 23:52:20 +0100 Subject: [PATCH 38/41] excellon export --- .../preferences/PreferencesUIManager.py | 8 - .../excellon/ExcellonExpPrefGroupUI.py | 224 ++++++------------ .../excellon/ExcellonPreferencesUI.py | 27 ++- 3 files changed, 86 insertions(+), 173 deletions(-) diff --git a/flatcamGUI/preferences/PreferencesUIManager.py b/flatcamGUI/preferences/PreferencesUIManager.py index 71d8d642..ce857851 100644 --- a/flatcamGUI/preferences/PreferencesUIManager.py +++ b/flatcamGUI/preferences/PreferencesUIManager.py @@ -60,14 +60,6 @@ class PreferencesUIManager: "excellon_f_plunge": self.ui.excellon_defaults_form.excellon_adv_opt_group.fplunge_cb, "excellon_f_retract": self.ui.excellon_defaults_form.excellon_adv_opt_group.fretract_cb, - # Excellon Export - "excellon_exp_units": self.ui.excellon_defaults_form.excellon_exp_group.excellon_units_radio, - "excellon_exp_format": self.ui.excellon_defaults_form.excellon_exp_group.format_radio, - "excellon_exp_integer": self.ui.excellon_defaults_form.excellon_exp_group.format_whole_entry, - "excellon_exp_decimals": self.ui.excellon_defaults_form.excellon_exp_group.format_dec_entry, - "excellon_exp_zeros": self.ui.excellon_defaults_form.excellon_exp_group.zeros_radio, - "excellon_exp_slot_type": self.ui.excellon_defaults_form.excellon_exp_group.slot_type_radio, - # Excellon Editor "excellon_editor_sel_limit": self.ui.excellon_defaults_form.excellon_editor_group.sel_limit_entry, "excellon_editor_newdia": self.ui.excellon_defaults_form.excellon_editor_group.addtool_entry, diff --git a/flatcamGUI/preferences/excellon/ExcellonExpPrefGroupUI.py b/flatcamGUI/preferences/excellon/ExcellonExpPrefGroupUI.py index db2e922a..52905e30 100644 --- a/flatcamGUI/preferences/excellon/ExcellonExpPrefGroupUI.py +++ b/flatcamGUI/preferences/excellon/ExcellonExpPrefGroupUI.py @@ -1,168 +1,86 @@ -from PyQt5 import QtWidgets, QtCore -from PyQt5.QtCore import QSettings +from flatcamGUI.preferences.OptionUI import * +from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI2 -from flatcamGUI.GUIElements import RadioSet, FCSpinner -from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI import gettext import FlatCAMTranslation as fcTranslate import builtins - fcTranslate.apply_language('strings') if '_' not in builtins.__dict__: _ = gettext.gettext -settings = QSettings("Open Source", "FlatCAM") -if settings.contains("machinist"): - machinist_setting = settings.value('machinist', type=int) -else: - machinist_setting = 0 +class ExcellonExpPrefGroupUI(OptionsGroupUI2): -class ExcellonExpPrefGroupUI(OptionsGroupUI): - - def __init__(self, decimals=4, parent=None): - super(ExcellonExpPrefGroupUI, self).__init__(self, parent=parent) - - self.setTitle(str(_("Excellon Export"))) + def __init__(self, decimals=4, **kwargs): self.decimals = decimals + super().__init__(**kwargs) + self.setTitle(str(_("Excellon Export"))) - # Plot options - self.export_options_label = QtWidgets.QLabel("%s:" % _("Export Options")) - self.export_options_label.setToolTip( - _("The parameters set here are used in the file exported\n" - "when using the File -> Export -> Export Excellon menu entry.") - ) - self.layout.addWidget(self.export_options_label) + self.option_dict()["excellon_exp_format"].get_field().activated_custom.connect(self.optimization_selection) - form = QtWidgets.QFormLayout() - self.layout.addLayout(form) - - # Excellon Units - self.excellon_units_label = QtWidgets.QLabel('%s:' % _('Units')) - self.excellon_units_label.setToolTip( - _("The units used in the Excellon file.") - ) - - self.excellon_units_radio = RadioSet([{'label': _('INCH'), 'value': 'INCH'}, - {'label': _('MM'), 'value': 'METRIC'}]) - self.excellon_units_radio.setToolTip( - _("The units used in the Excellon file.") - ) - - form.addRow(self.excellon_units_label, self.excellon_units_radio) - - # Excellon non-decimal format - self.digits_label = QtWidgets.QLabel("%s:" % _("Int/Decimals")) - self.digits_label.setToolTip( - _("The NC drill files, usually named Excellon files\n" - "are files that can be found in different formats.\n" - "Here we set the format used when the provided\n" - "coordinates are not using period.") - ) - - hlay1 = QtWidgets.QHBoxLayout() - - self.format_whole_entry = FCSpinner() - self.format_whole_entry.set_range(0, 9) - self.format_whole_entry.setMinimumWidth(30) - self.format_whole_entry.setToolTip( - _("This numbers signify the number of digits in\n" - "the whole part of Excellon coordinates.") - ) - hlay1.addWidget(self.format_whole_entry, QtCore.Qt.AlignLeft) - - excellon_separator_label = QtWidgets.QLabel(':') - excellon_separator_label.setFixedWidth(5) - hlay1.addWidget(excellon_separator_label, QtCore.Qt.AlignLeft) - - self.format_dec_entry = FCSpinner() - self.format_dec_entry.set_range(0, 9) - self.format_dec_entry.setMinimumWidth(30) - self.format_dec_entry.setToolTip( - _("This numbers signify the number of digits in\n" - "the decimal part of Excellon coordinates.") - ) - hlay1.addWidget(self.format_dec_entry, QtCore.Qt.AlignLeft) - hlay1.addStretch() - - form.addRow(self.digits_label, hlay1) - - # Select the Excellon Format - self.format_label = QtWidgets.QLabel("%s:" % _("Format")) - self.format_label.setToolTip( - _("Select the kind of coordinates format used.\n" - "Coordinates can be saved with decimal point or without.\n" - "When there is no decimal point, it is required to specify\n" - "the number of digits for integer part and the number of decimals.\n" - "Also it will have to be specified if LZ = leading zeros are kept\n" - "or TZ = trailing zeros are kept.") - ) - self.format_radio = RadioSet([{'label': _('Decimal'), 'value': 'dec'}, - {'label': _('No-Decimal'), 'value': 'ndec'}]) - self.format_radio.setToolTip( - _("Select the kind of coordinates format used.\n" - "Coordinates can be saved with decimal point or without.\n" - "When there is no decimal point, it is required to specify\n" - "the number of digits for integer part and the number of decimals.\n" - "Also it will have to be specified if LZ = leading zeros are kept\n" - "or TZ = trailing zeros are kept.") - ) - - form.addRow(self.format_label, self.format_radio) - - # Excellon Zeros - self.zeros_label = QtWidgets.QLabel('%s:' % _('Zeros')) - self.zeros_label.setAlignment(QtCore.Qt.AlignLeft) - self.zeros_label.setToolTip( - _("This sets the type of Excellon zeros.\n" - "If LZ then Leading Zeros are kept and\n" - "Trailing Zeros are removed.\n" - "If TZ is checked then Trailing Zeros are kept\n" - "and Leading Zeros are removed.") - ) - - self.zeros_radio = RadioSet([{'label': _('LZ'), 'value': 'LZ'}, - {'label': _('TZ'), 'value': 'TZ'}]) - self.zeros_radio.setToolTip( - _("This sets the default type of Excellon zeros.\n" - "If LZ then Leading Zeros are kept and\n" - "Trailing Zeros are removed.\n" - "If TZ is checked then Trailing Zeros are kept\n" - "and Leading Zeros are removed.") - ) - - form.addRow(self.zeros_label, self.zeros_radio) - - # Slot type - self.slot_type_label = QtWidgets.QLabel('%s:' % _('Slot type')) - self.slot_type_label.setAlignment(QtCore.Qt.AlignLeft) - self.slot_type_label.setToolTip( - _("This sets how the slots will be exported.\n" - "If ROUTED then the slots will be routed\n" - "using M15/M16 commands.\n" - "If DRILLED(G85) the slots will be exported\n" - "using the Drilled slot command (G85).") - ) - - self.slot_type_radio = RadioSet([{'label': _('Routed'), 'value': 'routing'}, - {'label': _('Drilled(G85)'), 'value': 'drilling'}]) - self.slot_type_radio.setToolTip( - _("This sets how the slots will be exported.\n" - "If ROUTED then the slots will be routed\n" - "using M15/M16 commands.\n" - "If DRILLED(G85) the slots will be exported\n" - "using the Drilled slot command (G85).") - ) - - form.addRow(self.slot_type_label, self.slot_type_radio) - - self.layout.addStretch() - self.format_radio.activated_custom.connect(self.optimization_selection) + def build_options(self) -> [OptionUI]: + return [ + HeadingOptionUI( + label_text="Export Options", + label_tooltip="The parameters set here are used in the file exported\n" + "when using the File -> Export -> Export Excellon menu entry." + ), + RadioSetOptionUI( + option="excellon_exp_units", + label_text="Units", + label_tooltip="The units used in the Excellon file.", + choices=[{'label': _('INCH'), 'value': 'INCH'}, + {'label': _('MM'), 'value': 'METRIC'}] + ), + SpinnerOptionUI( + option="excellon_exp_integer", + label_text="Int", + label_tooltip="This number signifies the number of digits in\nthe whole part of Excellon coordinates.", + min_value=0, max_value=9, step=1 + ), + SpinnerOptionUI( + option="excellon_exp_decimals", + label_text="Decimals", + label_tooltip="This number signifies the number of digits in\nthe decimal part of Excellon coordinates.", + min_value=0, max_value=9, step=1 + ), + RadioSetOptionUI( + option="excellon_exp_format", + label_text="Format", + label_tooltip="Select the kind of coordinates format used.\n" + "Coordinates can be saved with decimal point or without.\n" + "When there is no decimal point, it is required to specify\n" + "the number of digits for integer part and the number of decimals.\n" + "Also it will have to be specified if LZ = leading zeros are kept\n" + "or TZ = trailing zeros are kept.", + choices=[{'label': _('Decimal'), 'value': 'dec'}, + {'label': _('No-Decimal'), 'value': 'ndec'}] + ), + RadioSetOptionUI( + option="excellon_exp_zeros", + label_text="Zeros", + label_tooltip="This sets the type of Excellon zeros.\n" + "If LZ then Leading Zeros are kept and\n" + "Trailing Zeros are removed.\n" + "If TZ is checked then Trailing Zeros are kept\n" + "and Leading Zeros are removed.", + choices=[{'label': _('LZ'), 'value': 'LZ'}, + {'label': _('TZ'), 'value': 'TZ'}] + ), + RadioSetOptionUI( + option="excellon_exp_slot_type", + label_text="Slot type", + label_tooltip="This sets how the slots will be exported.\n" + "If ROUTED then the slots will be routed\n" + "using M15/M16 commands.\n" + "If DRILLED(G85) the slots will be exported\n" + "using the Drilled slot command (G85).", + choices=[{'label': _('Routed'), 'value': 'routing'}, + {'label': _('Drilled(G85)'), 'value': 'drilling'}] + ) + ] def optimization_selection(self): - if self.format_radio.get_value() == 'dec': - self.zeros_label.setDisabled(True) - self.zeros_radio.setDisabled(True) - else: - self.zeros_label.setDisabled(False) - self.zeros_radio.setDisabled(False) + disable_zeros = self.option_dict()["excellon_exp_format"].get_field().get_value() == "dec" + self.option_dict()["excellon_exp_zeros"].label_widget.setDisabled(disable_zeros) + self.option_dict()["excellon_exp_zeros"].get_field().setDisabled(disable_zeros) diff --git a/flatcamGUI/preferences/excellon/ExcellonPreferencesUI.py b/flatcamGUI/preferences/excellon/ExcellonPreferencesUI.py index 364c623c..ee773d2a 100644 --- a/flatcamGUI/preferences/excellon/ExcellonPreferencesUI.py +++ b/flatcamGUI/preferences/excellon/ExcellonPreferencesUI.py @@ -18,24 +18,21 @@ class ExcellonPreferencesUI(PreferencesSectionUI): def __init__(self, decimals, **kwargs): self.decimals = decimals - self.excellon_gen_group = ExcellonGenPrefGroupUI(decimals=self.decimals) # FIXME: remove the need for external access to excellon_opt_group self.excellon_opt_group = ExcellonOptPrefGroupUI(decimals=self.decimals) - self.excellon_exp_group = ExcellonExpPrefGroupUI(decimals=self.decimals) self.excellon_adv_opt_group = ExcellonAdvOptPrefGroupUI(decimals=self.decimals) self.excellon_editor_group = ExcellonEditorPrefGroupUI(decimals=self.decimals) super().__init__(**kwargs) self.init_sync_export() - def build_groups(self) -> [OptionsGroupUI]: return [ - self.excellon_gen_group, + ExcellonGenPrefGroupUI(decimals=self.decimals), self.excellon_opt_group, - self.excellon_exp_group, + ExcellonExpPrefGroupUI(decimals=self.decimals), self.excellon_adv_opt_group, self.excellon_editor_group ] @@ -60,13 +57,19 @@ class ExcellonPreferencesUI(PreferencesSectionUI): # User has disabled sync. return - self.excellon_exp_group.zeros_radio.set_value(self.option_dict()["excellon_zeros"].get_field().get_value() + 'Z') - self.excellon_exp_group.excellon_units_radio.set_value(self.option_dict()["excellon_units"].get_field().get_value()) - if self.option_dict()["excellon_units"].get_field().get_value().upper() == 'METRIC': - self.excellon_exp_group.format_whole_entry.set_value(self.option_dict()["excellon_format_upper_mm"].get_field().get_value()) - self.excellon_exp_group.format_dec_entry.set_value(self.option_dict()["excellon_format_lower_mm"].get_field().get_value()) + zeros = self.option_dict()["excellon_zeros"].get_field().get_value() + 'Z' + self.option_dict()["excellon_exp_zeros"].get_field().set_value(zeros) + + units = self.option_dict()["excellon_units"].get_field().get_value() + self.option_dict()["excellon_exp_units"].get_field().set_value(units) + + if units.upper() == 'METRIC': + whole = self.option_dict()["excellon_format_upper_mm"].get_field().get_value() + dec = self.option_dict()["excellon_format_lower_mm"].get_field().get_value() else: - self.excellon_exp_group.format_whole_entry.set_value(self.option_dict()["excellon_format_upper_in"].get_field().get_value()) - self.excellon_exp_group.format_dec_entry.set_value(self.option_dict()["excellon_format_lower_in"].get_field().get_value()) + whole = self.option_dict()["excellon_format_upper_in"].get_field().get_value() + dec = self.option_dict()["excellon_format_lower_in"].get_field().get_value() + self.option_dict()["excellon_exp_integer"].get_field().set_value(whole) + self.option_dict()["excellon_exp_decimals"].get_field().set_value(dec) From 3340590f60ae086942c09a4f23fddf23fdaee36e Mon Sep 17 00:00:00 2001 From: David Robertson Date: Mon, 11 May 2020 00:06:08 +0100 Subject: [PATCH 39/41] excellon advanced --- .../preferences/PreferencesUIManager.py | 10 - .../excellon/ExcellonAdvOptPrefGroupUI.py | 228 +++++++----------- .../excellon/ExcellonPreferencesUI.py | 6 +- 3 files changed, 86 insertions(+), 158 deletions(-) diff --git a/flatcamGUI/preferences/PreferencesUIManager.py b/flatcamGUI/preferences/PreferencesUIManager.py index ce857851..295f8fda 100644 --- a/flatcamGUI/preferences/PreferencesUIManager.py +++ b/flatcamGUI/preferences/PreferencesUIManager.py @@ -49,16 +49,6 @@ class PreferencesUIManager: # def new_object(self, kind, name, initialize, active=True, fit=True, plot=True) self.defaults_form_fields = { - # Excellon Advanced Options - "excellon_offset": self.ui.excellon_defaults_form.excellon_adv_opt_group.offset_entry, - "excellon_toolchangexy": self.ui.excellon_defaults_form.excellon_adv_opt_group.toolchangexy_entry, - "excellon_startz": self.ui.excellon_defaults_form.excellon_adv_opt_group.estartz_entry, - "excellon_feedrate_rapid": self.ui.excellon_defaults_form.excellon_adv_opt_group.feedrate_rapid_entry, - "excellon_z_pdepth": self.ui.excellon_defaults_form.excellon_adv_opt_group.pdepth_entry, - "excellon_feedrate_probe": self.ui.excellon_defaults_form.excellon_adv_opt_group.feedrate_probe_entry, - "excellon_spindledir": self.ui.excellon_defaults_form.excellon_adv_opt_group.spindledir_radio, - "excellon_f_plunge": self.ui.excellon_defaults_form.excellon_adv_opt_group.fplunge_cb, - "excellon_f_retract": self.ui.excellon_defaults_form.excellon_adv_opt_group.fretract_cb, # Excellon Editor "excellon_editor_sel_limit": self.ui.excellon_defaults_form.excellon_editor_group.sel_limit_entry, diff --git a/flatcamGUI/preferences/excellon/ExcellonAdvOptPrefGroupUI.py b/flatcamGUI/preferences/excellon/ExcellonAdvOptPrefGroupUI.py index a63998f9..321fc21b 100644 --- a/flatcamGUI/preferences/excellon/ExcellonAdvOptPrefGroupUI.py +++ b/flatcamGUI/preferences/excellon/ExcellonAdvOptPrefGroupUI.py @@ -1,155 +1,97 @@ -from PyQt5 import QtWidgets -from PyQt5.QtCore import QSettings +from flatcamGUI.preferences.OptionUI import * +from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI2 -from flatcamGUI.GUIElements import FCDoubleSpinner, FCEntry, FloatEntry, RadioSet, FCCheckBox -from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI import gettext import FlatCAMTranslation as fcTranslate import builtins - fcTranslate.apply_language('strings') if '_' not in builtins.__dict__: _ = gettext.gettext -settings = QSettings("Open Source", "FlatCAM") -if settings.contains("machinist"): - machinist_setting = settings.value('machinist', type=int) -else: - machinist_setting = 0 +class ExcellonAdvOptPrefGroupUI(OptionsGroupUI2): -class ExcellonAdvOptPrefGroupUI(OptionsGroupUI): - - def __init__(self, decimals=4, parent=None): - # OptionsGroupUI.__init__(self, "Excellon Advanced Options", parent=parent) - super(ExcellonAdvOptPrefGroupUI, self).__init__(self, parent=parent) - - self.setTitle(str(_("Excellon Adv. Options"))) + def __init__(self, decimals=4, **kwargs): self.decimals = decimals + super().__init__(**kwargs) + self.setTitle(str(_("Excellon Adv. Options"))) - # ####################### - # ## ADVANCED OPTIONS ### - # ####################### - - self.exc_label = QtWidgets.QLabel('%s:' % _('Advanced Options')) - self.exc_label.setToolTip( - _("A list of Excellon advanced parameters.\n" - "Those parameters are available only for\n" - "Advanced App. Level.") - ) - self.layout.addWidget(self.exc_label) - - grid1 = QtWidgets.QGridLayout() - self.layout.addLayout(grid1) - - # Offset Z - offsetlabel = QtWidgets.QLabel('%s:' % _('Offset Z')) - offsetlabel.setToolTip( - _("Some drill bits (the larger ones) need to drill deeper\n" - "to create the desired exit hole diameter due of the tip shape.\n" - "The value here can compensate the Cut Z parameter.")) - self.offset_entry = FCDoubleSpinner() - self.offset_entry.set_precision(self.decimals) - self.offset_entry.set_range(-999.9999, 999.9999) - - grid1.addWidget(offsetlabel, 0, 0) - grid1.addWidget(self.offset_entry, 0, 1) - - # ToolChange X,Y - toolchange_xy_label = QtWidgets.QLabel('%s:' % _('Toolchange X,Y')) - toolchange_xy_label.setToolTip( - _("Toolchange X,Y position.") - ) - self.toolchangexy_entry = FCEntry() - - grid1.addWidget(toolchange_xy_label, 1, 0) - grid1.addWidget(self.toolchangexy_entry, 1, 1) - - # Start Z - startzlabel = QtWidgets.QLabel('%s:' % _('Start Z')) - startzlabel.setToolTip( - _("Height of the tool just after start.\n" - "Delete the value if you don't need this feature.") - ) - self.estartz_entry = FloatEntry() - - grid1.addWidget(startzlabel, 2, 0) - grid1.addWidget(self.estartz_entry, 2, 1) - - # Feedrate Rapids - fr_rapid_label = QtWidgets.QLabel('%s:' % _('Feedrate Rapids')) - fr_rapid_label.setToolTip( - _("Tool speed while drilling\n" - "(in units per minute).\n" - "This is for the rapid move G00.\n" - "It is useful only for Marlin,\n" - "ignore for any other cases.") - ) - self.feedrate_rapid_entry = FCDoubleSpinner() - self.feedrate_rapid_entry.set_precision(self.decimals) - self.feedrate_rapid_entry.set_range(0, 99999.9999) - - grid1.addWidget(fr_rapid_label, 3, 0) - grid1.addWidget(self.feedrate_rapid_entry, 3, 1) - - # Probe depth - self.pdepth_label = QtWidgets.QLabel('%s:' % _("Probe Z depth")) - self.pdepth_label.setToolTip( - _("The maximum depth that the probe is allowed\n" - "to probe. Negative value, in current units.") - ) - self.pdepth_entry = FCDoubleSpinner() - self.pdepth_entry.set_precision(self.decimals) - self.pdepth_entry.set_range(-99999.9999, 0.0000) - - grid1.addWidget(self.pdepth_label, 4, 0) - grid1.addWidget(self.pdepth_entry, 4, 1) - - # Probe feedrate - self.feedrate_probe_label = QtWidgets.QLabel('%s:' % _("Feedrate Probe")) - self.feedrate_probe_label.setToolTip( - _("The feedrate used while the probe is probing.") - ) - self.feedrate_probe_entry = FCDoubleSpinner() - self.feedrate_probe_entry.set_precision(self.decimals) - self.feedrate_probe_entry.set_range(0, 99999.9999) - - grid1.addWidget(self.feedrate_probe_label, 5, 0) - grid1.addWidget(self.feedrate_probe_entry, 5, 1) - - # Spindle direction - spindle_dir_label = QtWidgets.QLabel('%s:' % _('Spindle direction')) - spindle_dir_label.setToolTip( - _("This sets the direction that the spindle is rotating.\n" - "It can be either:\n" - "- CW = clockwise or\n" - "- CCW = counter clockwise") - ) - - self.spindledir_radio = RadioSet([{'label': _('CW'), 'value': 'CW'}, - {'label': _('CCW'), 'value': 'CCW'}]) - grid1.addWidget(spindle_dir_label, 6, 0) - grid1.addWidget(self.spindledir_radio, 6, 1) - - self.fplunge_cb = FCCheckBox('%s' % _('Fast Plunge')) - self.fplunge_cb.setToolTip( - _("By checking this, the vertical move from\n" - "Z_Toolchange to Z_move is done with G0,\n" - "meaning the fastest speed available.\n" - "WARNING: the move is done at Toolchange X,Y coords.") - ) - grid1.addWidget(self.fplunge_cb, 7, 0, 1, 2) - - self.fretract_cb = FCCheckBox('%s' % _('Fast Retract')) - self.fretract_cb.setToolTip( - _("Exit hole strategy.\n" - " - When uncheked, while exiting the drilled hole the drill bit\n" - "will travel slow, with set feedrate (G1), up to zero depth and then\n" - "travel as fast as possible (G0) to the Z Move (travel height).\n" - " - When checked the travel from Z cut (cut depth) to Z_move\n" - "(travel height) is done as fast as possible (G0) in one move.") - ) - - grid1.addWidget(self.fretract_cb, 8, 0, 1, 2) - - self.layout.addStretch() + def build_options(self) -> [OptionUI]: + return [ + HeadingOptionUI( + label_text="Advanced Options", + label_tooltip="A list of Excellon advanced parameters.\n" + "Those parameters are available only for\n" + "Advanced App. Level." + ), + DoubleSpinnerOptionUI( + option="excellon_offset", + label_text="Offset Z", + label_tooltip="Some drill bits (the larger ones) need to drill deeper\n" + "to create the desired exit hole diameter due of the tip shape.\n" + "The value here can compensate the Cut Z parameter.", + min_value=-999.9999, max_value=999.9999, step=0.1, decimals=self.decimals + ), + LineEntryOptionUI( + option="excellon_toolchangexy", + label_text="Toolchange X,Y", + label_tooltip="Toolchange X,Y position." + ), + FloatEntryOptionUI( + option="excellon_startz", + label_text="Start Z", + label_tooltip="Height of the tool just after start.\n" + "Delete the value if you don't need this feature." + ), + DoubleSpinnerOptionUI( + option="excellon_feedrate_rapid", + label_text="Feedrate Rapids", + label_tooltip="Tool speed while drilling\n" + "(in units per minute).\n" + "This is for the rapid move G00.\n" + "It is useful only for Marlin,\n" + "ignore for any other cases.", + min_value=0.0001, max_value=99999.9999, step=50, decimals=self.decimals + ), + DoubleSpinnerOptionUI( + option="excellon_z_pdepth", + label_text="Probe Z depth", + label_tooltip="The maximum depth that the probe is allowed\n" + "to probe. Negative value, in current units.", + min_value=-99999.9999, max_value=0.0, step=0.1, decimals=self.decimals + ), + DoubleSpinnerOptionUI( + option="excellon_feedrate_probe", + label_text="Feedrate Probe", + label_tooltip="The feedrate used while the probe is probing.", + min_value=0.0001, max_value=99999.9999, step=0.1, decimals=self.decimals + ), + RadioSetOptionUI( + option="excellon_spindledir", + label_text="Spindle direction", + label_tooltip="This sets the direction that the spindle is rotating.\n" + "It can be either:\n" + "- CW = clockwise or\n" + "- CCW = counter clockwise", + choices=[{'label': _('CW'), 'value': 'CW'}, + {'label': _('CCW'), 'value': 'CCW'}] + ), + CheckboxOptionUI( + option="excellon_f_plunge", + label_text="Fast Plunge", + label_tooltip="By checking this, the vertical move from\n" + "Z_Toolchange to Z_move is done with G0,\n" + "meaning the fastest speed available.\n" + "WARNING: the move is done at Toolchange X,Y coords." + ), + CheckboxOptionUI( + option="excellon_f_retract", + label_text="Fast Retract", + label_tooltip="Exit hole strategy.\n" + " - When uncheked, while exiting the drilled hole the drill bit\n" + "will travel slow, with set feedrate (G1), up to zero depth and then\n" + "travel as fast as possible (G0) to the Z Move (travel height).\n" + " - When checked the travel from Z cut (cut depth) to Z_move\n" + "(travel height) is done as fast as possible (G0) in one move." + ) + ] \ No newline at end of file diff --git a/flatcamGUI/preferences/excellon/ExcellonPreferencesUI.py b/flatcamGUI/preferences/excellon/ExcellonPreferencesUI.py index ee773d2a..e366fce3 100644 --- a/flatcamGUI/preferences/excellon/ExcellonPreferencesUI.py +++ b/flatcamGUI/preferences/excellon/ExcellonPreferencesUI.py @@ -18,13 +18,9 @@ class ExcellonPreferencesUI(PreferencesSectionUI): def __init__(self, decimals, **kwargs): self.decimals = decimals - # FIXME: remove the need for external access to excellon_opt_group self.excellon_opt_group = ExcellonOptPrefGroupUI(decimals=self.decimals) - - self.excellon_adv_opt_group = ExcellonAdvOptPrefGroupUI(decimals=self.decimals) self.excellon_editor_group = ExcellonEditorPrefGroupUI(decimals=self.decimals) - super().__init__(**kwargs) self.init_sync_export() @@ -33,7 +29,7 @@ class ExcellonPreferencesUI(PreferencesSectionUI): ExcellonGenPrefGroupUI(decimals=self.decimals), self.excellon_opt_group, ExcellonExpPrefGroupUI(decimals=self.decimals), - self.excellon_adv_opt_group, + ExcellonAdvOptPrefGroupUI(decimals=self.decimals), self.excellon_editor_group ] From d8fdbcdb111ed39f5a9ed8b4226d0567a6500e84 Mon Sep 17 00:00:00 2001 From: David Robertson Date: Mon, 11 May 2020 00:30:21 +0100 Subject: [PATCH 40/41] excellon editor --- .../preferences/PreferencesUIManager.py | 31 -- .../excellon/ExcellonEditorPrefGroupUI.py | 441 ++++++------------ .../excellon/ExcellonPreferencesUI.py | 3 +- 3 files changed, 155 insertions(+), 320 deletions(-) diff --git a/flatcamGUI/preferences/PreferencesUIManager.py b/flatcamGUI/preferences/PreferencesUIManager.py index 295f8fda..de4468b1 100644 --- a/flatcamGUI/preferences/PreferencesUIManager.py +++ b/flatcamGUI/preferences/PreferencesUIManager.py @@ -49,37 +49,6 @@ class PreferencesUIManager: # def new_object(self, kind, name, initialize, active=True, fit=True, plot=True) self.defaults_form_fields = { - - # Excellon Editor - "excellon_editor_sel_limit": self.ui.excellon_defaults_form.excellon_editor_group.sel_limit_entry, - "excellon_editor_newdia": self.ui.excellon_defaults_form.excellon_editor_group.addtool_entry, - "excellon_editor_array_size": self.ui.excellon_defaults_form.excellon_editor_group.drill_array_size_entry, - "excellon_editor_lin_dir": self.ui.excellon_defaults_form.excellon_editor_group.drill_axis_radio, - "excellon_editor_lin_pitch": self.ui.excellon_defaults_form.excellon_editor_group.drill_pitch_entry, - "excellon_editor_lin_angle": self.ui.excellon_defaults_form.excellon_editor_group.drill_angle_entry, - "excellon_editor_circ_dir": self.ui.excellon_defaults_form.excellon_editor_group.drill_circular_dir_radio, - "excellon_editor_circ_angle": - self.ui.excellon_defaults_form.excellon_editor_group.drill_circular_angle_entry, - # Excellon Slots - "excellon_editor_slot_direction": - self.ui.excellon_defaults_form.excellon_editor_group.slot_axis_radio, - "excellon_editor_slot_angle": - self.ui.excellon_defaults_form.excellon_editor_group.slot_angle_spinner, - "excellon_editor_slot_length": - self.ui.excellon_defaults_form.excellon_editor_group.slot_length_entry, - # Excellon Slots - "excellon_editor_slot_array_size": - self.ui.excellon_defaults_form.excellon_editor_group.slot_array_size_entry, - "excellon_editor_slot_lin_dir": self.ui.excellon_defaults_form.excellon_editor_group.slot_array_axis_radio, - "excellon_editor_slot_lin_pitch": - self.ui.excellon_defaults_form.excellon_editor_group.slot_array_pitch_entry, - "excellon_editor_slot_lin_angle": - self.ui.excellon_defaults_form.excellon_editor_group.slot_array_angle_entry, - "excellon_editor_slot_circ_dir": - self.ui.excellon_defaults_form.excellon_editor_group.slot_array_circular_dir_radio, - "excellon_editor_slot_circ_angle": - self.ui.excellon_defaults_form.excellon_editor_group.slot_array_circular_angle_entry, - # NCC Tool "tools_ncctools": self.ui.tools_defaults_form.tools_ncc_group.ncc_tool_dia_entry, "tools_nccorder": self.ui.tools_defaults_form.tools_ncc_group.ncc_order_radio, diff --git a/flatcamGUI/preferences/excellon/ExcellonEditorPrefGroupUI.py b/flatcamGUI/preferences/excellon/ExcellonEditorPrefGroupUI.py index 5b04cf2f..162cdf8a 100644 --- a/flatcamGUI/preferences/excellon/ExcellonEditorPrefGroupUI.py +++ b/flatcamGUI/preferences/excellon/ExcellonEditorPrefGroupUI.py @@ -1,306 +1,173 @@ -from PyQt5 import QtWidgets -from PyQt5.QtCore import QSettings - -from flatcamGUI.GUIElements import FCSpinner, FCDoubleSpinner, RadioSet -from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI +from flatcamGUI.preferences.OptionUI import * +from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI2 import gettext import FlatCAMTranslation as fcTranslate import builtins - fcTranslate.apply_language('strings') if '_' not in builtins.__dict__: _ = gettext.gettext -settings = QSettings("Open Source", "FlatCAM") -if settings.contains("machinist"): - machinist_setting = settings.value('machinist', type=int) -else: - machinist_setting = 0 +class ExcellonEditorPrefGroupUI(OptionsGroupUI2): -class ExcellonEditorPrefGroupUI(OptionsGroupUI): - def __init__(self, decimals=4, parent=None): - super(ExcellonEditorPrefGroupUI, self).__init__(self, parent=parent) - - self.setTitle(str(_("Excellon Editor"))) + def __init__(self, decimals=4, **kwargs): self.decimals = decimals + super().__init__(**kwargs) + self.setTitle(str(_("Excellon Editor"))) - # Excellon Editor Parameters - self.param_label = QtWidgets.QLabel("%s:" % _("Parameters")) - self.param_label.setToolTip( - _("A list of Excellon Editor parameters.") - ) - self.layout.addWidget(self.param_label) + def build_options(self) -> [OptionUI]: + return [ + HeadingOptionUI( + label_text="Parameters", + label_tooltip="A list of Excellon Editor parameters." + ), + SpinnerOptionUI( + option="excellon_editor_sel_limit", + label_text="Selection limit", + label_tooltip="Set the number of selected Excellon geometry\n" + "items above which the utility geometry\n" + "becomes just a selection rectangle.\n" + "Increases the performance when moving a\n" + "large number of geometric elements.", + min_value=0, max_value=99999, step=1 + ), + DoubleSpinnerOptionUI( + option="excellon_editor_newdia", + label_text="New Dia", + label_tooltip="Diameter for the new tool", + min_value=0.000001, max_value=99.9999, step=0.1, decimals=self.decimals + ), + SpinnerOptionUI( + option="excellon_editor_array_size", + label_text="Nr of drills", + label_tooltip="Specify how many drills to be in the array.", + min_value=0, max_value=9999, step=1 + ), - grid0 = QtWidgets.QGridLayout() - self.layout.addLayout(grid0) + HeadingOptionUI(label_text="Linear Drill Array"), + RadioSetOptionUI( + option="excellon_editor_lin_dir", + label_text="Linear Direction", + label_tooltip="Direction on which the linear array is oriented:\n" + "- 'X' - horizontal axis \n" + "- 'Y' - vertical axis or \n" + "- 'Angle' - a custom angle for the array inclination", + choices=[ + {'label': _('X'), 'value': 'X'}, + {'label': _('Y'), 'value': 'Y'}, + {'label': _('Angle'), 'value': 'A'} + ] + ), + DoubleSpinnerOptionUI( + option="excellon_editor_lin_pitch", + label_text="Pitch", + label_tooltip="Pitch = Distance between elements of the array.", + min_value=0, max_value=99999.9999, step=0.1, decimals=self.decimals + ), + DoubleSpinnerOptionUI( + option="excellon_editor_lin_angle", + label_text="Angle", + label_tooltip="Angle at which each element in circular array is placed.", # FIXME tooltip seems wrong ? + min_value=-360, max_value=360, step=5, decimals=self.decimals + ), - # Selection Limit - self.sel_limit_label = QtWidgets.QLabel('%s:' % _("Selection limit")) - self.sel_limit_label.setToolTip( - _("Set the number of selected Excellon geometry\n" - "items above which the utility geometry\n" - "becomes just a selection rectangle.\n" - "Increases the performance when moving a\n" - "large number of geometric elements.") - ) - self.sel_limit_entry = FCSpinner() - self.sel_limit_entry.set_range(0, 99999) + HeadingOptionUI(label_text="Circular Drill Array"), + RadioSetOptionUI( + option="excellon_editor_circ_dir", + label_text="Circular Direction", + label_tooltip="Direction for circular array.\n" + "Can be CW = clockwise or CCW = counter clockwise.", + choices=[ + {'label': _('CW'), 'value': 'CW'}, + {'label': _('CCW'), 'value': 'CCW'} + ] + ), + DoubleSpinnerOptionUI( + option="excellon_editor_circ_angle", + label_text="Angle", + label_tooltip="Angle at which each element in circular array is placed.", + min_value=-360, max_value=360, step=5, decimals=self.decimals + ), - grid0.addWidget(self.sel_limit_label, 0, 0) - grid0.addWidget(self.sel_limit_entry, 0, 1) + HeadingOptionUI(label_text="Slots"), + DoubleSpinnerOptionUI( + option="excellon_editor_slot_length", + label_text="Length", + label_tooltip="Length = The length of the slot.", + min_value=0, max_value=99999, step=1, decimals=self.decimals + ), + RadioSetOptionUI( + option="excellon_editor_slot_direction", + label_text="Direction", + label_tooltip="Direction on which the slot is oriented:\n" + "- 'X' - horizontal axis \n" + "- 'Y' - vertical axis or \n" + "- 'Angle' - a custom angle for the slot inclination", + choices=[ + {'label': _('X'), 'value': 'X'}, + {'label': _('Y'), 'value': 'Y'}, + {'label': _('Angle'), 'value': 'A'} + ] + ), + DoubleSpinnerOptionUI( + option="excellon_editor_slot_angle", + label_text="Angle", + label_tooltip="Angle at which the slot is placed.\n" + "The precision is of max 2 decimals.\n" + "Min value is: -359.99 degrees.\n" + "Max value is: 360.00 degrees.", + min_value=-359.99, max_value=360.00, step=5, decimals=self.decimals + ), - # New Diameter - self.addtool_entry_lbl = QtWidgets.QLabel('%s:' % _('New Dia')) - self.addtool_entry_lbl.setToolTip( - _("Diameter for the new tool") - ) + HeadingOptionUI(label_text="Linear Slot Array"), + SpinnerOptionUI( + option="excellon_editor_slot_array_size", + label_text="Nr of slots", + label_tooltip="Specify how many slots to be in the array.", + min_value=0, max_value=999999, step=1 + ), + RadioSetOptionUI( + option="excellon_editor_slot_lin_dir", + label_text="Linear Direction", + label_tooltip="Direction on which the linear array is oriented:\n" + "- 'X' - horizontal axis \n" + "- 'Y' - vertical axis or \n" + "- 'Angle' - a custom angle for the array inclination", + choices=[ + {'label': _('X'), 'value': 'X'}, + {'label': _('Y'), 'value': 'Y'}, + {'label': _('Angle'), 'value': 'A'} + ] + ), + DoubleSpinnerOptionUI( + option="excellon_editor_slot_lin_pitch", + label_text="Pitch", + label_tooltip="Pitch = Distance between elements of the array.", + min_value=0, max_value=999999, step=1, decimals=self.decimals + ), + DoubleSpinnerOptionUI( + option="excellon_editor_slot_lin_angle", + label_text="Angle", + label_tooltip="Angle at which each element in circular array is placed.", # FIXME + min_value=-360, max_value=360, step=5, decimals=self.decimals + ), - self.addtool_entry = FCDoubleSpinner() - self.addtool_entry.set_range(0.000001, 99.9999) - self.addtool_entry.set_precision(self.decimals) + HeadingOptionUI(label_text="Circular Slot Array"), + RadioSetOptionUI( + option="excellon_editor_slot_circ_dir", + label_text="Circular Direction", + label_tooltip="Direction for circular array.\n" + "Can be CW = clockwise or CCW = counter clockwise.", + choices=[{'label': _('CW'), 'value': 'CW'}, + {'label': _('CCW'), 'value': 'CCW'}] + ), + DoubleSpinnerOptionUI( + option="excellon_editor_slot_circ_angle", + label_text="Circular Angle", + label_tooltip="Angle at which each element in circular array is placed.", + min_value=-360, max_value=360, step=5, decimals=self.decimals + ) - grid0.addWidget(self.addtool_entry_lbl, 1, 0) - grid0.addWidget(self.addtool_entry, 1, 1) + ] - # Number of drill holes in a drill array - self.drill_array_size_label = QtWidgets.QLabel('%s:' % _('Nr of drills')) - self.drill_array_size_label.setToolTip( - _("Specify how many drills to be in the array.") - ) - # self.drill_array_size_label.setMinimumWidth(100) - - self.drill_array_size_entry = FCSpinner() - self.drill_array_size_entry.set_range(0, 9999) - - grid0.addWidget(self.drill_array_size_label, 2, 0) - grid0.addWidget(self.drill_array_size_entry, 2, 1) - - self.drill_array_linear_label = QtWidgets.QLabel('%s:' % _('Linear Drill Array')) - grid0.addWidget(self.drill_array_linear_label, 3, 0, 1, 2) - - # Linear Drill Array direction - self.drill_axis_label = QtWidgets.QLabel('%s:' % _('Linear Direction')) - self.drill_axis_label.setToolTip( - _("Direction on which the linear array is oriented:\n" - "- 'X' - horizontal axis \n" - "- 'Y' - vertical axis or \n" - "- 'Angle' - a custom angle for the array inclination") - ) - # self.drill_axis_label.setMinimumWidth(100) - self.drill_axis_radio = RadioSet([{'label': _('X'), 'value': 'X'}, - {'label': _('Y'), 'value': 'Y'}, - {'label': _('Angle'), 'value': 'A'}]) - - grid0.addWidget(self.drill_axis_label, 4, 0) - grid0.addWidget(self.drill_axis_radio, 4, 1) - - # Linear Drill Array pitch distance - self.drill_pitch_label = QtWidgets.QLabel('%s:' % _('Pitch')) - self.drill_pitch_label.setToolTip( - _("Pitch = Distance between elements of the array.") - ) - # self.drill_pitch_label.setMinimumWidth(100) - self.drill_pitch_entry = FCDoubleSpinner() - self.drill_pitch_entry.set_range(0, 99999.9999) - self.drill_pitch_entry.set_precision(self.decimals) - - grid0.addWidget(self.drill_pitch_label, 5, 0) - grid0.addWidget(self.drill_pitch_entry, 5, 1) - - # Linear Drill Array custom angle - self.drill_angle_label = QtWidgets.QLabel('%s:' % _('Angle')) - self.drill_angle_label.setToolTip( - _("Angle at which each element in circular array is placed.") - ) - self.drill_angle_entry = FCDoubleSpinner() - self.drill_pitch_entry.set_range(-360, 360) - self.drill_pitch_entry.set_precision(self.decimals) - self.drill_angle_entry.setWrapping(True) - self.drill_angle_entry.setSingleStep(5) - - grid0.addWidget(self.drill_angle_label, 6, 0) - grid0.addWidget(self.drill_angle_entry, 6, 1) - - self.drill_array_circ_label = QtWidgets.QLabel('%s:' % _('Circular Drill Array')) - grid0.addWidget(self.drill_array_circ_label, 7, 0, 1, 2) - - # Circular Drill Array direction - self.drill_circular_direction_label = QtWidgets.QLabel('%s:' % _('Circular Direction')) - self.drill_circular_direction_label.setToolTip( - _("Direction for circular array.\n" - "Can be CW = clockwise or CCW = counter clockwise.") - ) - - self.drill_circular_dir_radio = RadioSet([{'label': _('CW'), 'value': 'CW'}, - {'label': _('CCW'), 'value': 'CCW'}]) - - grid0.addWidget(self.drill_circular_direction_label, 8, 0) - grid0.addWidget(self.drill_circular_dir_radio, 8, 1) - - # Circular Drill Array Angle - self.drill_circular_angle_label = QtWidgets.QLabel('%s:' % _('Circular Angle')) - self.drill_circular_angle_label.setToolTip( - _("Angle at which each element in circular array is placed.") - ) - self.drill_circular_angle_entry = FCDoubleSpinner() - self.drill_circular_angle_entry.set_range(-360, 360) - self.drill_circular_angle_entry.set_precision(self.decimals) - self.drill_circular_angle_entry.setWrapping(True) - self.drill_circular_angle_entry.setSingleStep(5) - - grid0.addWidget(self.drill_circular_angle_label, 9, 0) - grid0.addWidget(self.drill_circular_angle_entry, 9, 1) - - # ##### SLOTS ##### - # ################# - self.drill_array_circ_label = QtWidgets.QLabel('%s:' % _('Slots')) - grid0.addWidget(self.drill_array_circ_label, 10, 0, 1, 2) - - # Slot length - self.slot_length_label = QtWidgets.QLabel('%s:' % _('Length')) - self.slot_length_label.setToolTip( - _("Length = The length of the slot.") - ) - self.slot_length_label.setMinimumWidth(100) - - self.slot_length_entry = FCDoubleSpinner() - self.slot_length_entry.set_range(0, 99999) - self.slot_length_entry.set_precision(self.decimals) - self.slot_length_entry.setWrapping(True) - self.slot_length_entry.setSingleStep(1) - - grid0.addWidget(self.slot_length_label, 11, 0) - grid0.addWidget(self.slot_length_entry, 11, 1) - - # Slot direction - self.slot_axis_label = QtWidgets.QLabel('%s:' % _('Direction')) - self.slot_axis_label.setToolTip( - _("Direction on which the slot is oriented:\n" - "- 'X' - horizontal axis \n" - "- 'Y' - vertical axis or \n" - "- 'Angle' - a custom angle for the slot inclination") - ) - self.slot_axis_label.setMinimumWidth(100) - - self.slot_axis_radio = RadioSet([{'label': _('X'), 'value': 'X'}, - {'label': _('Y'), 'value': 'Y'}, - {'label': _('Angle'), 'value': 'A'}]) - grid0.addWidget(self.slot_axis_label, 12, 0) - grid0.addWidget(self.slot_axis_radio, 12, 1) - - # Slot custom angle - self.slot_angle_label = QtWidgets.QLabel('%s:' % _('Angle')) - self.slot_angle_label.setToolTip( - _("Angle at which the slot is placed.\n" - "The precision is of max 2 decimals.\n" - "Min value is: -359.99 degrees.\n" - "Max value is: 360.00 degrees.") - ) - self.slot_angle_label.setMinimumWidth(100) - - self.slot_angle_spinner = FCDoubleSpinner() - self.slot_angle_spinner.set_precision(self.decimals) - self.slot_angle_spinner.setWrapping(True) - self.slot_angle_spinner.setRange(-359.99, 360.00) - self.slot_angle_spinner.setSingleStep(5) - - grid0.addWidget(self.slot_angle_label, 13, 0) - grid0.addWidget(self.slot_angle_spinner, 13, 1) - - # #### SLOTS ARRAY ####### - # ######################## - - self.slot_array_linear_label = QtWidgets.QLabel('%s:' % _('Linear Slot Array')) - grid0.addWidget(self.slot_array_linear_label, 14, 0, 1, 2) - - # Number of slot holes in a drill array - self.slot_array_size_label = QtWidgets.QLabel('%s:' % _('Nr of slots')) - self.drill_array_size_label.setToolTip( - _("Specify how many slots to be in the array.") - ) - # self.slot_array_size_label.setMinimumWidth(100) - - self.slot_array_size_entry = FCSpinner() - self.slot_array_size_entry.set_range(0, 999999) - - grid0.addWidget(self.slot_array_size_label, 15, 0) - grid0.addWidget(self.slot_array_size_entry, 15, 1) - - # Linear Slot Array direction - self.slot_array_axis_label = QtWidgets.QLabel('%s:' % _('Linear Direction')) - self.slot_array_axis_label.setToolTip( - _("Direction on which the linear array is oriented:\n" - "- 'X' - horizontal axis \n" - "- 'Y' - vertical axis or \n" - "- 'Angle' - a custom angle for the array inclination") - ) - # self.slot_axis_label.setMinimumWidth(100) - self.slot_array_axis_radio = RadioSet([{'label': _('X'), 'value': 'X'}, - {'label': _('Y'), 'value': 'Y'}, - {'label': _('Angle'), 'value': 'A'}]) - - grid0.addWidget(self.slot_array_axis_label, 16, 0) - grid0.addWidget(self.slot_array_axis_radio, 16, 1) - - # Linear Slot Array pitch distance - self.slot_array_pitch_label = QtWidgets.QLabel('%s:' % _('Pitch')) - self.slot_array_pitch_label.setToolTip( - _("Pitch = Distance between elements of the array.") - ) - # self.drill_pitch_label.setMinimumWidth(100) - self.slot_array_pitch_entry = FCDoubleSpinner() - self.slot_array_pitch_entry.set_precision(self.decimals) - self.slot_array_pitch_entry.setWrapping(True) - self.slot_array_pitch_entry.setRange(0, 999999) - self.slot_array_pitch_entry.setSingleStep(1) - - grid0.addWidget(self.slot_array_pitch_label, 17, 0) - grid0.addWidget(self.slot_array_pitch_entry, 17, 1) - - # Linear Slot Array custom angle - self.slot_array_angle_label = QtWidgets.QLabel('%s:' % _('Angle')) - self.slot_array_angle_label.setToolTip( - _("Angle at which each element in circular array is placed.") - ) - self.slot_array_angle_entry = FCDoubleSpinner() - self.slot_array_angle_entry.set_precision(self.decimals) - self.slot_array_angle_entry.setWrapping(True) - self.slot_array_angle_entry.setRange(-360, 360) - self.slot_array_angle_entry.setSingleStep(5) - - grid0.addWidget(self.slot_array_angle_label, 18, 0) - grid0.addWidget(self.slot_array_angle_entry, 18, 1) - - self.slot_array_circ_label = QtWidgets.QLabel('%s:' % _('Circular Slot Array')) - grid0.addWidget(self.slot_array_circ_label, 19, 0, 1, 2) - - # Circular Slot Array direction - self.slot_array_circular_direction_label = QtWidgets.QLabel('%s:' % _('Circular Direction')) - self.slot_array_circular_direction_label.setToolTip( - _("Direction for circular array.\n" - "Can be CW = clockwise or CCW = counter clockwise.") - ) - - self.slot_array_circular_dir_radio = RadioSet([{'label': _('CW'), 'value': 'CW'}, - {'label': _('CCW'), 'value': 'CCW'}]) - - grid0.addWidget(self.slot_array_circular_direction_label, 20, 0) - grid0.addWidget(self.slot_array_circular_dir_radio, 20, 1) - - # Circular Slot Array Angle - self.slot_array_circular_angle_label = QtWidgets.QLabel('%s:' % _('Circular Angle')) - self.slot_array_circular_angle_label.setToolTip( - _("Angle at which each element in circular array is placed.") - ) - self.slot_array_circular_angle_entry = FCDoubleSpinner() - self.slot_array_circular_angle_entry.set_precision(self.decimals) - self.slot_array_circular_angle_entry.setWrapping(True) - self.slot_array_circular_angle_entry.setRange(-360, 360) - self.slot_array_circular_angle_entry.setSingleStep(5) - - grid0.addWidget(self.slot_array_circular_angle_label, 21, 0) - grid0.addWidget(self.slot_array_circular_angle_entry, 21, 1) - - self.layout.addStretch() diff --git a/flatcamGUI/preferences/excellon/ExcellonPreferencesUI.py b/flatcamGUI/preferences/excellon/ExcellonPreferencesUI.py index e366fce3..91176f9d 100644 --- a/flatcamGUI/preferences/excellon/ExcellonPreferencesUI.py +++ b/flatcamGUI/preferences/excellon/ExcellonPreferencesUI.py @@ -20,7 +20,6 @@ class ExcellonPreferencesUI(PreferencesSectionUI): self.decimals = decimals # FIXME: remove the need for external access to excellon_opt_group self.excellon_opt_group = ExcellonOptPrefGroupUI(decimals=self.decimals) - self.excellon_editor_group = ExcellonEditorPrefGroupUI(decimals=self.decimals) super().__init__(**kwargs) self.init_sync_export() @@ -30,7 +29,7 @@ class ExcellonPreferencesUI(PreferencesSectionUI): self.excellon_opt_group, ExcellonExpPrefGroupUI(decimals=self.decimals), ExcellonAdvOptPrefGroupUI(decimals=self.decimals), - self.excellon_editor_group + ExcellonEditorPrefGroupUI(decimals=self.decimals) ] def get_tab_id(self): From 612aa6a48fc1b1766e23c2fa32ec8a2ad07d07b8 Mon Sep 17 00:00:00 2001 From: Marius Stanciu Date: Mon, 1 Jun 2020 12:57:10 +0000 Subject: [PATCH 41/41] Revert "Preferences refactoring (pull request #309)" --- CHANGELOG.md | 10 - FlatCAMApp.py | 295 ++++-- FlatCAMCommon.py | 13 +- FlatCAMTranslation.py | 2 +- Utils/vispy_example.py | 195 ---- defaults.py | 1 - flatcamEditors/FlatCAMExcEditor.py | 20 +- flatcamEditors/FlatCAMGeoEditor.py | 41 +- flatcamEditors/FlatCAMGrbEditor.py | 19 +- flatcamGUI/ColumnarFlowLayout.py | 174 ---- flatcamGUI/FlatCAMGUI.py | 259 ++--- flatcamGUI/GUIElements.py | 98 -- flatcamGUI/PlotCanvas.py | 33 +- flatcamGUI/PlotCanvasLegacy.py | 73 -- flatcamGUI/VisPyCanvas.py | 1 - flatcamGUI/preferences/OptionUI.py | 322 ------- flatcamGUI/preferences/OptionsGroupUI.py | 62 +- .../preferences/PreferencesSectionUI.py | 42 - .../preferences/PreferencesUIManager.py | 568 +++++++++-- .../cncjob/CNCJobAdvOptPrefGroupUI.py | 211 +++-- .../cncjob/CNCJobGenPrefGroupUI.py | 497 +++++++--- .../cncjob/CNCJobOptPrefGroupUI.py | 95 +- .../preferences/cncjob/CNCJobPreferencesUI.py | 40 +- .../excellon/ExcellonAdvOptPrefGroupUI.py | 228 +++-- .../excellon/ExcellonEditorPrefGroupUI.py | 441 ++++++--- .../excellon/ExcellonExpPrefGroupUI.py | 224 +++-- .../excellon/ExcellonGenPrefGroupUI.py | 576 ++++++++---- .../excellon/ExcellonOptPrefGroupUI.py | 461 +++++---- .../excellon/ExcellonPreferencesUI.py | 83 +- .../general/GeneralAPPSetGroupUI.py | 483 ++++++++++ .../general/GeneralAppPrefGroupUI.py | 575 ++++++----- .../general/GeneralAppSettingsGroupUI.py | 301 ------ .../general/GeneralGUIPrefGroupUI.py | 889 ++++++++++++++---- .../general/GeneralPreferencesUI.py | 50 +- .../geometry/GeometryAdvOptPrefGroupUI.py | 368 +++++--- .../geometry/GeometryEditorPrefGroupUI.py | 84 +- .../geometry/GeometryGenPrefGroupUI.py | 147 ++- .../geometry/GeometryOptPrefGroupUI.py | 366 ++++--- .../geometry/GeometryPreferencesUI.py | 47 +- .../gerber/GerberAdvOptPrefGroupUI.py | 274 +++--- .../gerber/GerberEditorPrefGroupUI.py | 351 ++++--- .../gerber/GerberExpPrefGroupUI.py | 149 ++- .../gerber/GerberGenPrefGroupUI.py | 349 +++++-- .../gerber/GerberOptPrefGroupUI.py | 266 ++++-- .../preferences/gerber/GerberPreferencesUI.py | 51 +- .../preferences/tools/Tools2PreferencesUI.py | 86 +- .../preferences/tools/ToolsPreferencesUI.py | 90 +- .../utilities/UtilPreferencesUI.py | 40 +- flatcamTools/ToolCopperThieving.py | 16 +- flatcamTools/ToolDistance.py | 15 +- flatcamTools/ToolNCC.py | 16 +- flatcamTools/ToolPaint.py | 16 +- 52 files changed, 6162 insertions(+), 3951 deletions(-) delete mode 100644 Utils/vispy_example.py delete mode 100644 flatcamGUI/ColumnarFlowLayout.py delete mode 100644 flatcamGUI/preferences/OptionUI.py delete mode 100644 flatcamGUI/preferences/PreferencesSectionUI.py create mode 100644 flatcamGUI/preferences/general/GeneralAPPSetGroupUI.py delete mode 100644 flatcamGUI/preferences/general/GeneralAppSettingsGroupUI.py diff --git a/CHANGELOG.md b/CHANGELOG.md index 1f6c6b3d..7770a326 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,16 +7,6 @@ CHANGELOG for FlatCAM beta ================================================= -11.05.2020 - -- removed the labels in status bar that display X,Y positions and replaced it with a HUD display on canvas (combo key SHIFT+H) will toggle the display of the HUD -- made the HUD work in Legacy2D mode -- fixed situation when the mouse cursor is outside of the canvas and no therefore returning None values - -10.05.2020 - -- fixed the problem with using comma as decimal separator in Grid Snap fields - 9.05.2020 - modified the GUI for Exclusion areas; now the shapes are displayed in a Table where they can be selected and deleted. Modification applied for Geometry Objects only (for now). diff --git a/FlatCAMApp.py b/FlatCAMApp.py index a07f28c4..4641420d 100644 --- a/FlatCAMApp.py +++ b/FlatCAMApp.py @@ -285,8 +285,6 @@ class App(QtCore.QObject): :rtype: App """ - super().__init__() - App.log.info("FlatCAM Starting...") self.main_thread = QtWidgets.QApplication.instance().thread() @@ -454,8 +452,6 @@ class App(QtCore.QObject): self.current_units = self.defaults['units'] - - # ########################################################################################################### # #################################### SETUP OBJECT CLASSES ################################################# # ########################################################################################################### @@ -508,6 +504,8 @@ class App(QtCore.QObject): self.FC_light_blue = '#a5a5ffbf' self.FC_dark_blue = '#0000ffbf' + QtCore.QObject.__init__(self) + self.ui = FlatCAMGUI(self) theme_settings = QtCore.QSettings("Open Source", "FlatCAM") @@ -605,11 +603,13 @@ class App(QtCore.QObject): # ################################ It's done only once after install ##################################### # ########################################################################################################### if self.defaults["first_run"] is True: - # ONLY AT FIRST STARTUP INIT THE GUI LAYOUT TO 'minimal' + # ONLY AT FIRST STARTUP INIT THE GUI LAYOUT TO 'COMPACT' initial_lay = 'minimal' - layout_field = self.preferencesUiManager.get_form_field("layout") - layout_field.setCurrentIndex(layout_field.findText(initial_lay)) - self.ui.set_layout(initial_lay) + self.ui.general_defaults_form.general_gui_group.on_layout(lay=initial_lay) + + # Set the combobox in Preferences to the current layout + idx = self.ui.general_defaults_form.general_gui_group.layout_combo.findText(initial_lay) + self.ui.general_defaults_form.general_gui_group.layout_combo.setCurrentIndex(idx) # after the first run, this object should be False self.defaults["first_run"] = False @@ -632,9 +632,8 @@ class App(QtCore.QObject): # ########################################################################################################### self.languages = fcTranslate.load_languages() - language_field = self.preferencesUiManager.get_form_field("global_language") for name in sorted(self.languages.values()): - language_field.addItem(name) + self.ui.general_defaults_form.general_app_group.language_cb.addItem(name) # ########################################################################################################### # ####################################### APPLY APP LANGUAGE ################################################ @@ -647,7 +646,7 @@ class App(QtCore.QObject): 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.preferencesUiManager.get_form_field("global_language").setCurrentText(ret_val) + self.ui.general_defaults_form.general_app_group.language_cb.setCurrentText(ret_val) log.debug("App.__init__() --> Applied %s language." % str(ret_val).capitalize()) # ########################################################################################################### @@ -967,25 +966,23 @@ class App(QtCore.QObject): # #################################### GUI PREFERENCES SIGNALS ############################################## # ########################################################################################################### - self.preferencesUiManager.get_form_field("units").activated_custom.connect( + self.ui.general_defaults_form.general_app_group.units_radio.activated_custom.connect( lambda: self.on_toggle_units(no_pref=False)) # ##################################### Workspace Setting Signals ########################################### - - - self.preferencesUiManager.get_form_field("global_workspaceT").currentIndexChanged.connect( + self.ui.general_defaults_form.general_app_set_group.wk_cb.currentIndexChanged.connect( self.on_workspace_modified) - self.preferencesUiManager.get_form_field("global_workspace_orientation").activated_custom.connect( + self.ui.general_defaults_form.general_app_set_group.wk_orientation_radio.activated_custom.connect( self.on_workspace_modified ) - self.preferencesUiManager.get_form_field("global_workspace").stateChanged.connect(self.on_workspace) + self.ui.general_defaults_form.general_app_set_group.workspace_cb.stateChanged.connect(self.on_workspace) # ########################################################################################################### # ######################################## GUI SETTINGS SIGNALS ############################################# # ########################################################################################################### - self.preferencesUiManager.get_form_field("global_graphic_engine").activated_custom.connect(self.on_app_restart) - self.preferencesUiManager.get_form_field("global_cursor_type").activated_custom.connect(self.on_cursor_type) + self.ui.general_defaults_form.general_app_group.ge_radio.activated_custom.connect(self.on_app_restart) + self.ui.general_defaults_form.general_app_set_group.cursor_radio.activated_custom.connect(self.on_cursor_type) # ######################################## Tools related signals ############################################ # Film Tool @@ -1005,7 +1002,7 @@ class App(QtCore.QObject): self.on_qrcode_back_color_button) # portability changed signal - self.preferencesUiManager.get_form_field("global_portable").stateChanged.connect(self.on_portable_checked) + self.ui.general_defaults_form.general_app_group.portability_cb.stateChanged.connect(self.on_portable_checked) # Object list self.collection.view.activated.connect(self.on_row_activated) @@ -1013,6 +1010,15 @@ class App(QtCore.QObject): self.object_status_changed.connect(self.on_collection_updated) + # Make sure that when the Excellon loading parameters are changed, the change is reflected in the + # Export Excellon parameters. + self.ui.excellon_defaults_form.excellon_gen_group.update_excellon_cb.stateChanged.connect( + self.on_update_exc_export + ) + + # call it once to make sure it is updated at startup + self.on_update_exc_export(state=self.defaults["excellon_update"]) + # when there are arguments at application startup this get launched self.args_at_startup[list].connect(self.on_startup_args) @@ -1419,8 +1425,8 @@ class App(QtCore.QObject): # Separate thread (Not worker) # Check for updates on startup but only if the user consent and the app is not in Beta version if (self.beta is False or self.beta is None) and \ - self.preferencesUiManager.get_form_field("global_version_check").get_value() is True: - App.log.info("Checking for updates in background (this is version %s)." % str(self.version)) + self.ui.general_defaults_form.general_app_group.version_check_cb.get_value() is True: + App.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, @@ -1547,7 +1553,7 @@ class App(QtCore.QObject): self.abort_flag = False # set the value used in the Windows Title - self.engine = self.preferencesUiManager.get_form_field("global_graphic_engine").get_value() + 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 @@ -1592,7 +1598,11 @@ class App(QtCore.QObject): self.set_ui_title(name=_("New Project - Not saved")) - + # disable the Excellon path optimizations made with Google OR-Tools if the app is run on a 32bit platform + current_platform = platform.architecture()[0] + if current_platform != '64bit': + self.ui.excellon_defaults_form.excellon_gen_group.excellon_optimization_radio.set_value('T') + self.ui.excellon_defaults_form.excellon_gen_group.excellon_optimization_radio.setDisabled(True) # ########################################################################################################### # ########################################### EXCLUSION AREAS ############################################### @@ -3561,24 +3571,24 @@ class App(QtCore.QObject): stgs.setValue('maximized_gui', self.ui.isMaximized()) stgs.setValue( 'language', - self.preferencesUiManager.get_form_field("global_language").get_value() + self.ui.general_defaults_form.general_app_group.language_cb.get_value() ) stgs.setValue( 'notebook_font_size', - self.preferencesUiManager.get_form_field("notebook_font_size").get_value() + self.ui.general_defaults_form.general_app_set_group.notebook_font_size_spinner.get_value() ) stgs.setValue( 'axis_font_size', - self.preferencesUiManager.get_form_field("axis_font_size").get_value() + self.ui.general_defaults_form.general_app_set_group.axis_font_size_spinner.get_value() ) stgs.setValue( 'textbox_font_size', - self.preferencesUiManager.get_form_field("textbox_font_size").get_value() + self.ui.general_defaults_form.general_app_set_group.textbox_font_size_spinner.get_value() ) stgs.setValue('toolbar_lock', self.ui.lock_action.isChecked()) stgs.setValue( 'machinist', - 1 if self.preferencesUiManager.get_form_field("global_machinist_setting").get_value() else 0 + 1 if self.ui.general_defaults_form.general_app_set_group.machinist_cb.get_value() else 0 ) # This will write the setting to the platform specific storage. @@ -4201,18 +4211,18 @@ class App(QtCore.QObject): def on_toggle_units_click(self): try: - self.preferencesUiManager.get_form_field("units").activated_custom.disconnect() + self.ui.general_defaults_form.general_app_group.units_radio.activated_custom.disconnect() except (TypeError, AttributeError): pass if self.defaults["units"] == 'MM': - self.preferencesUiManager.get_form_field("units").set_value("IN") + self.ui.general_defaults_form.general_app_group.units_radio.set_value("IN") else: - self.preferencesUiManager.get_form_field("units").set_value("MM") + self.ui.general_defaults_form.general_app_group.units_radio.set_value("MM") self.on_toggle_units(no_pref=True) - self.preferencesUiManager.get_form_field("units").activated_custom.connect( + self.ui.general_defaults_form.general_app_group.units_radio.activated_custom.connect( lambda: self.on_toggle_units(no_pref=False)) def on_toggle_units(self, no_pref=False): @@ -4230,7 +4240,7 @@ class App(QtCore.QObject): if self.toggle_units_ignore: return - new_units = self.preferencesUiManager.get_form_field("units").get_value().upper() + new_units = self.ui.general_defaults_form.general_app_group.units_radio.get_value().upper() # If option is the same, then ignore if new_units == self.defaults["units"].upper(): @@ -4441,9 +4451,9 @@ class App(QtCore.QObject): # Undo toggling self.toggle_units_ignore = True if self.defaults['units'].upper() == 'MM': - self.preferencesUiManager.get_form_field("units").set_value('IN') + self.ui.general_defaults_form.general_app_group.units_radio.set_value('IN') else: - self.preferencesUiManager.get_form_field("units").set_value('MM') + self.ui.general_defaults_form.general_app_group.units_radio.set_value('MM') self.toggle_units_ignore = False # store the grid values so they are not changed in the next step @@ -4612,7 +4622,133 @@ class App(QtCore.QObject): self.app_cursor.enabled = True self.app_cursor.enabled = False + def on_update_exc_export(self, state): + """ + This is handling the update of Excellon Export parameters based on the ones in the Excellon General but only + if the update_excellon_cb checkbox is checked + :param state: state of the checkbox whose signals is tied to his slot + :return: + """ + if state: + # first try to disconnect + try: + self.ui.excellon_defaults_form.excellon_gen_group.excellon_format_upper_in_entry.returnPressed. \ + disconnect(self.on_excellon_format_changed) + except TypeError: + pass + try: + self.ui.excellon_defaults_form.excellon_gen_group.excellon_format_lower_in_entry.returnPressed. \ + disconnect(self.on_excellon_format_changed) + except TypeError: + pass + try: + self.ui.excellon_defaults_form.excellon_gen_group.excellon_format_upper_mm_entry.returnPressed. \ + disconnect(self.on_excellon_format_changed) + except TypeError: + pass + try: + self.ui.excellon_defaults_form.excellon_gen_group.excellon_format_lower_mm_entry.returnPressed. \ + disconnect(self.on_excellon_format_changed) + except TypeError: + pass + + try: + self.ui.excellon_defaults_form.excellon_gen_group.excellon_zeros_radio.activated_custom. \ + disconnect(self.on_excellon_zeros_changed) + except TypeError: + pass + try: + self.ui.excellon_defaults_form.excellon_gen_group.excellon_units_radio.activated_custom. \ + disconnect(self.on_excellon_zeros_changed) + except TypeError: + pass + + # the connect them + self.ui.excellon_defaults_form.excellon_gen_group.excellon_format_upper_in_entry.returnPressed.connect( + self.on_excellon_format_changed) + self.ui.excellon_defaults_form.excellon_gen_group.excellon_format_lower_in_entry.returnPressed.connect( + self.on_excellon_format_changed) + self.ui.excellon_defaults_form.excellon_gen_group.excellon_format_upper_mm_entry.returnPressed.connect( + self.on_excellon_format_changed) + self.ui.excellon_defaults_form.excellon_gen_group.excellon_format_lower_mm_entry.returnPressed.connect( + self.on_excellon_format_changed) + self.ui.excellon_defaults_form.excellon_gen_group.excellon_zeros_radio.activated_custom.connect( + self.on_excellon_zeros_changed) + self.ui.excellon_defaults_form.excellon_gen_group.excellon_units_radio.activated_custom.connect( + self.on_excellon_units_changed) + else: + # disconnect the signals + try: + self.ui.excellon_defaults_form.excellon_gen_group.excellon_format_upper_in_entry.returnPressed. \ + disconnect(self.on_excellon_format_changed) + except TypeError: + pass + try: + self.ui.excellon_defaults_form.excellon_gen_group.excellon_format_lower_in_entry.returnPressed. \ + disconnect(self.on_excellon_format_changed) + except TypeError: + pass + try: + self.ui.excellon_defaults_form.excellon_gen_group.excellon_format_upper_mm_entry.returnPressed. \ + disconnect(self.on_excellon_format_changed) + except TypeError: + pass + try: + self.ui.excellon_defaults_form.excellon_gen_group.excellon_format_lower_mm_entry.returnPressed. \ + disconnect(self.on_excellon_format_changed) + except TypeError: + pass + + try: + self.ui.excellon_defaults_form.excellon_gen_group.excellon_zeros_radio.activated_custom. \ + disconnect(self.on_excellon_zeros_changed) + except TypeError: + pass + try: + self.ui.excellon_defaults_form.excellon_gen_group.excellon_units_radio.activated_custom. \ + disconnect(self.on_excellon_zeros_changed) + except TypeError: + pass + + def on_excellon_format_changed(self): + """ + Slot activated when the user changes the Excellon format values in Preferences -> Excellon -> Excellon General + :return: None + """ + if self.ui.excellon_defaults_form.excellon_gen_group.excellon_units_radio.get_value().upper() == 'METRIC': + self.ui.excellon_defaults_form.excellon_exp_group.format_whole_entry.set_value( + self.ui.excellon_defaults_form.excellon_gen_group.excellon_format_upper_mm_entry.get_value() + ) + self.ui.excellon_defaults_form.excellon_exp_group.format_dec_entry.set_value( + self.ui.excellon_defaults_form.excellon_gen_group.excellon_format_lower_mm_entry.get_value() + ) + else: + self.ui.excellon_defaults_form.excellon_exp_group.format_whole_entry.set_value( + self.ui.excellon_defaults_form.excellon_gen_group.excellon_format_upper_in_entry.get_value() + ) + self.ui.excellon_defaults_form.excellon_exp_group.format_dec_entry.set_value( + self.ui.excellon_defaults_form.excellon_gen_group.excellon_format_lower_in_entry.get_value() + ) + + def on_excellon_zeros_changed(self): + """ + Slot activated when the user changes the Excellon zeros values in Preferences -> Excellon -> Excellon General + :return: None + """ + self.ui.excellon_defaults_form.excellon_exp_group.zeros_radio.set_value( + self.ui.excellon_defaults_form.excellon_gen_group.excellon_zeros_radio.get_value() + 'Z' + ) + + def on_excellon_units_changed(self): + """ + Slot activated when the user changes the Excellon unit values in Preferences -> Excellon -> Excellon General + :return: None + """ + self.ui.excellon_defaults_form.excellon_exp_group.excellon_units_radio.set_value( + self.ui.excellon_defaults_form.excellon_gen_group.excellon_units_radio.get_value() + ) + self.on_excellon_format_changed() def on_film_color_entry(self): self.defaults['tools_film_color'] = \ @@ -4739,7 +4875,7 @@ class App(QtCore.QObject): self.plotcanvas.draw_workspace(workspace_size=self.defaults['global_workspaceT']) def on_workspace(self): - if self.preferencesUiManager.get_form_field("global_workspace").get_value(): + if self.ui.general_defaults_form.general_app_set_group.workspace_cb.get_value(): self.plotcanvas.draw_workspace(workspace_size=self.defaults['global_workspaceT']) else: self.plotcanvas.delete_workspace() @@ -4747,13 +4883,13 @@ class App(QtCore.QObject): # self.save_defaults(silent=True) def on_workspace_toggle(self): - state = False if self.preferencesUiManager.get_form_field("global_workspace").get_value() else True + state = False if self.ui.general_defaults_form.general_app_set_group.workspace_cb.get_value() else True try: - self.preferencesUiManager.get_form_field("global_workspace").stateChanged.disconnect(self.on_workspace) + self.ui.general_defaults_form.general_app_set_group.workspace_cb.stateChanged.disconnect(self.on_workspace) except TypeError: pass - self.preferencesUiManager.get_form_field("global_workspace").set_value(state) - self.preferencesUiManager.get_form_field("global_workspace").stateChanged.connect(self.on_workspace) + self.ui.general_defaults_form.general_app_set_group.workspace_cb.set_value(state) + self.ui.general_defaults_form.general_app_set_group.workspace_cb.stateChanged.connect(self.on_workspace) self.on_workspace() def on_cursor_type(self, val): @@ -4765,12 +4901,12 @@ class App(QtCore.QObject): self.app_cursor.enabled = False if val == 'small': - self.preferencesUiManager.get_form_field("global_cursor_size").setDisabled(False) - #self.ui.general_defaults_form.general_app_set_group.cursor_size_lbl.setDisabled(False) + self.ui.general_defaults_form.general_app_set_group.cursor_size_entry.setDisabled(False) + self.ui.general_defaults_form.general_app_set_group.cursor_size_lbl.setDisabled(False) self.app_cursor = self.plotcanvas.new_cursor() else: - self.preferencesUiManager.get_form_field("global_cursor_size").setDisabled(False) - #self.ui.general_defaults_form.general_app_set_group.cursor_size_lbl.setDisabled(True) + self.ui.general_defaults_form.general_app_set_group.cursor_size_entry.setDisabled(True) + self.ui.general_defaults_form.general_app_set_group.cursor_size_lbl.setDisabled(True) self.app_cursor = self.plotcanvas.new_cursor(big=True) if self.ui.grid_snap_btn.isChecked(): @@ -5242,20 +5378,14 @@ class App(QtCore.QObject): edge_width=self.defaults["global_cursor_width"], size=self.defaults["global_cursor_size"]) + # Set the position label + self.ui.position_label.setText("    X: %.4f   " + "Y: %.4f" % (location[0], location[1])) # Set the relative position label dx = location[0] - float(self.rel_point1[0]) dy = location[1] - float(self.rel_point1[1]) - # self.ui.position_label.setText("    X: %.4f   " - # "Y: %.4f" % (location[0], location[1])) - # # Set the position label - # - # self.ui.rel_position_label.setText("Dx: %.4f   Dy: " - # "%.4f    " % (dx, dy)) - - units = self.defaults["units"].lower() - self.plotcanvas.text_hud.text = \ - 'Dx:\t{:<.4f} [{:s}]\nDy:\t{:<.4f} [{:s}]\nX: \t{:<.4f} [{:s}]\nY: \t{:<.4f} [{:s}]'.format( - dx, units, dy, units, location[0], units, location[1], units) + self.ui.rel_position_label.setText("Dx: %.4f   Dy: " + "%.4f    " % (dx, dy)) self.inform.emit('[success] %s' % _("Done.")) return location @@ -5397,19 +5527,14 @@ class App(QtCore.QObject): edge_width=self.defaults["global_cursor_width"], size=self.defaults["global_cursor_size"]) + # Set the position label + self.ui.position_label.setText("    X: %.4f   " + "Y: %.4f" % (location[0], location[1])) # Set the relative position label self.dx = location[0] - float(self.rel_point1[0]) self.dy = location[1] - float(self.rel_point1[1]) - # Set the position label - # self.ui.position_label.setText("    X: %.4f   " - # "Y: %.4f" % (location[0], location[1])) - # self.ui.rel_position_label.setText("Dx: %.4f   Dy: " - # "%.4f    " % (self.dx, self.dy)) - - units = self.defaults["units"].lower() - self.plotcanvas.text_hud.text = \ - 'Dx:\t{:<.4f} [{:s}]\nDy:\t{:<.4f} [{:s}]\nX: \t{:<.4f} [{:s}]\nY: \t{:<.4f} [{:s}]'.format( - self.dx, units, self.dy, units, location[0], units, location[1], units) + self.ui.rel_position_label.setText("Dx: %.4f   Dy: " + "%.4f    " % (self.dx, self.dy)) self.inform.emit('[success] %s' % _("Done.")) return location @@ -5718,8 +5843,8 @@ class App(QtCore.QObject): self.ui.plot_tab_area.addTab(self.ui.preferences_tab, _("Preferences")) # delete the absolute and relative position and messages in the infobar - # self.ui.position_label.setText("") - # self.ui.rel_position_label.setText("") + self.ui.position_label.setText("") + self.ui.rel_position_label.setText("") # Switch plot_area to preferences page self.ui.plot_tab_area.setCurrentWidget(self.ui.preferences_tab) @@ -6613,9 +6738,6 @@ class App(QtCore.QObject): try: # May fail in case mouse not within axes pos_canvas = self.plotcanvas.translate_coords(event_pos) - if pos_canvas[0] is None or pos_canvas[1] is None: - return - if self.grid_status(): pos = self.geo_editor.snap(pos_canvas[0], pos_canvas[1]) @@ -6627,19 +6749,13 @@ class App(QtCore.QObject): else: pos = (pos_canvas[0], pos_canvas[1]) + self.ui.position_label.setText("    X: %.4f   " + "Y: %.4f" % (pos[0], pos[1])) + self.dx = pos[0] - float(self.rel_point1[0]) self.dy = pos[1] - float(self.rel_point1[1]) - - # self.ui.position_label.setText("    X: %.4f   " - # "Y: %.4f" % (pos[0], pos[1])) - # self.ui.rel_position_label.setText("Dx: %.4f   Dy: " - # "%.4f    " % (self.dx, self.dy)) - - units = self.defaults["units"].lower() - self.plotcanvas.text_hud.text = \ - 'Dx:\t{:<.4f} [{:s}]\nDy:\t{:<.4f} [{:s}]\nX: \t{:<.4f} [{:s}]\nY: \t{:<.4f} [{:s}]'.format( - self.dx, units, self.dy, units, pos[0], units, pos[1], units) - + self.ui.rel_position_label.setText("Dx: %.4f   Dy: " + "%.4f    " % (self.dx, self.dy)) self.mouse = [pos[0], pos[1]] # if the mouse is moved and the LMB is clicked then the action is a selection @@ -6688,10 +6804,9 @@ class App(QtCore.QObject): # In this case poly_obj creation (see above) will fail pass - except Exception as e: - log.debug("App.on_mouse_move_over_plot() - rel_point1 is not None -> %s" % str(e)) - # self.ui.position_label.setText("") - # self.ui.rel_position_label.setText("") + except Exception: + self.ui.position_label.setText("") + self.ui.rel_position_label.setText("") self.mouse = None def on_mouse_click_release_over_plot(self, event): @@ -10019,8 +10134,7 @@ class App(QtCore.QObject): self.log.debug("version_check()") - - if self.defaults["global_send_stats"] is True: + if self.ui.general_defaults_form.general_app_group.send_stats_cb.get_value() is True: full_url = "%s?s=%s&v=%s&os=%s&%s" % ( App.version_url, str(self.defaults['global_serial']), @@ -10359,9 +10473,10 @@ class App(QtCore.QObject): alpha_level = 'BF' for sel_obj in sel_obj_list: if sel_obj.kind == 'excellon': - alpha_level = self.defaults["excellon_plot_fill"][7:] + alpha_level = str(hex( + self.ui.excellon_defaults_form.excellon_gen_group.color_alpha_slider.value())[2:]) elif sel_obj.kind == 'gerber': - alpha_level = self.defaults["gerber_plot_fill"][7:] + alpha_level = str(hex(self.ui.gerber_defaults_form.gerber_gen_group.pf_color_alpha_slider.value())[2:]) elif sel_obj.kind == 'geometry': alpha_level = 'FF' else: diff --git a/FlatCAMCommon.py b/FlatCAMCommon.py index bcd61a98..b95091aa 100644 --- a/FlatCAMCommon.py +++ b/FlatCAMCommon.py @@ -466,20 +466,15 @@ class ExclusionAreas(QtCore.QObject): size=self.app.defaults["global_cursor_size"]) # update the positions on status bar + self.app.ui.position_label.setText("    X: %.4f   " + "Y: %.4f" % (curr_pos[0], curr_pos[1])) if self.cursor_pos is None: self.cursor_pos = (0, 0) self.app.dx = curr_pos[0] - float(self.cursor_pos[0]) self.app.dy = curr_pos[1] - float(self.cursor_pos[1]) - # self.app.ui.position_label.setText("    X: %.4f   " - # "Y: %.4f" % (curr_pos[0], curr_pos[1])) - # self.app.ui.rel_position_label.setText("Dx: %.4f   Dy: " - # "%.4f    " % (self.app.dx, self.app.dy)) - - units = self.app.defaults["units"].lower() - self.app.plotcanvas.text_hud.text = \ - 'Dx:\t{:<.4f} [{:s}]\nDy:\t{:<.4f} [{:s}]\nX: \t{:<.4f} [{:s}]\nY: \t{:<.4f} [{:s}]'.format( - self.app.dx, units, self.app.dy, units, curr_pos[0], units, curr_pos[1], units) + self.app.ui.rel_position_label.setText("Dx: %.4f   Dy: " + "%.4f    " % (self.app.dx, self.app.dy)) if self.obj_type == 'excellon': color = "#FF7400" diff --git a/FlatCAMTranslation.py b/FlatCAMTranslation.py index ddd376c7..82a8ac33 100644 --- a/FlatCAMTranslation.py +++ b/FlatCAMTranslation.py @@ -79,7 +79,7 @@ def on_language_apply_click(app, restart=False): :return: """ - name = app.preferencesUiManager.get_form_field("global_language").currentText() + name = app.ui.general_defaults_form.general_app_group.language_cb.currentText() theme_settings = QSettings("Open Source", "FlatCAM") if theme_settings.contains("theme"): diff --git a/Utils/vispy_example.py b/Utils/vispy_example.py deleted file mode 100644 index a9eaee12..00000000 --- a/Utils/vispy_example.py +++ /dev/null @@ -1,195 +0,0 @@ -from PyQt5.QtGui import QPalette -from PyQt5 import QtCore, QtWidgets - -import vispy.scene as scene -from vispy.scene.visuals import Rectangle, Text -from vispy.color import Color - -import sys - - -class VisPyCanvas(scene.SceneCanvas): - - def __init__(self, config=None): - super().__init__(config=config, keys=None) - - self.unfreeze() - - # Colors used by the Scene - theme_color = Color('#FFFFFF') - tick_color = Color('#000000') - back_color = str(QPalette().color(QPalette.Window).name()) - - # Central Widget Colors - self.central_widget.bgcolor = back_color - self.central_widget.border_color = back_color - - self.grid_widget = self.central_widget.add_grid(margin=10) - self.grid_widget.spacing = 0 - - # TOP Padding - top_padding = self.grid_widget.add_widget(row=0, col=0, col_span=2) - top_padding.height_max = 0 - - # RIGHT Padding - right_padding = self.grid_widget.add_widget(row=0, col=2, row_span=2) - right_padding.width_max = 0 - - # X Axis - self.xaxis = scene.AxisWidget( - orientation='bottom', axis_color=tick_color, text_color=tick_color, - font_size=8, axis_width=1, - anchors=['center', 'bottom'] - ) - self.xaxis.height_max = 30 - self.grid_widget.add_widget(self.xaxis, row=2, col=1) - - # Y Axis - self.yaxis = scene.AxisWidget( - orientation='left', axis_color=tick_color, text_color=tick_color, - font_size=8, axis_width=1 - ) - self.yaxis.width_max = 55 - self.grid_widget.add_widget(self.yaxis, row=1, col=0) - - # View & Camera - self.view = self.grid_widget.add_view(row=1, col=1, border_color=tick_color, - bgcolor=theme_color) - self.view.camera = scene.PanZoomCamera(aspect=1, rect=(-25, -25, 150, 150)) - - self.xaxis.link_view(self.view) - self.yaxis.link_view(self.view) - - self.grid = scene.GridLines(parent=self.view.scene, color='dimgray') - self.grid.set_gl_state(depth_test=False) - - self.rect = Rectangle(center=(65,30), color=Color('#0000FF10'), border_color=Color('#0000FF10'), - width=120, height=50, radius=[5, 5, 5, 5], parent=self.view) - self.rect.set_gl_state(depth_test=False) - - self.text = Text('', parent=self.view, color='black', pos=(5, 30), method='gpu', anchor_x='left') - self.text.font_size = 8 - self.text.text = 'Coordinates:\nX: %s\nY: %s' % ('0.0000', '0.0000') - - self.freeze() - - # self.measure_fps() - - -class PlotCanvas(QtCore.QObject): - - def __init__(self, container, my_app): - """ - The constructor configures the VisPy figure that - will contain all plots, creates the base axes and connects - events to the plotting area. - - :param container: The parent container in which to draw plots. - :rtype: PlotCanvas - """ - - super().__init__() - - # VisPyCanvas instance - self.vispy_canvas = VisPyCanvas() - - self.vispy_canvas.unfreeze() - - self.my_app = my_app - - # Parent container - self.container = container - - # - self.vispy_canvas.create_native() - self.vispy_canvas.native.setParent(self.my_app.ui) - - # - self.container.addWidget(self.vispy_canvas.native) - - # add two Infinite Lines to act as markers for the X,Y axis - self.v_line = scene.visuals.InfiniteLine( - pos=0, color=(0.0, 0.0, 1.0, 0.3), vertical=True, - parent=self.vispy_canvas.view.scene) - - self.h_line = scene.visuals.InfiniteLine( - pos=0, color=(0.00, 0.0, 1.0, 0.3), vertical=False, - parent=self.vispy_canvas.view.scene) - - self.vispy_canvas.freeze() - - def event_connect(self, event, callback): - getattr(self.vispy_canvas.events, event).connect(callback) - - def event_disconnect(self, event, callback): - getattr(self.vispy_canvas.events, event).disconnect(callback) - - def translate_coords(self, pos): - """ - Translate pixels to canvas units. - """ - tr = self.vispy_canvas.grid.get_transform('canvas', 'visual') - return tr.map(pos) - - -class MyGui(QtWidgets.QMainWindow): - - def __init__(self): - super().__init__() - - self.setWindowTitle("VisPy Test") - - # add Menubar - self.menu = self.menuBar() - self.menufile = self.menu.addMenu("File") - self.menuedit = self.menu.addMenu("Edit") - self.menufhelp = self.menu.addMenu("Help") - - # add a Toolbar - self.file_toolbar = QtWidgets.QToolBar("File Toolbar") - self.addToolBar(self.file_toolbar) - self.button = self.file_toolbar.addAction("Open") - - # add Central Widget - self.c_widget = QtWidgets.QWidget() - self.central_layout = QtWidgets.QVBoxLayout() - self.c_widget.setLayout(self.central_layout) - self.setCentralWidget(self.c_widget) - - # add InfoBar - # self.infobar = self.statusBar() - # self.position_label = QtWidgets.QLabel("Position: X: 0.0000\tY: 0.0000") - # self.infobar.addWidget(self.position_label) - - -class MyApp(QtCore.QObject): - - def __init__(self): - super().__init__() - - self.ui = MyGui() - self.plot = PlotCanvas(container=self.ui.central_layout, my_app=self) - - self.ui.show() - - self.plot.event_connect(event="mouse_move", callback=self.on_mouse_move) - - def on_mouse_move(self, event): - cursor_pos = event.pos - - pos_canvas = self.plot.translate_coords(cursor_pos) - - # we don't need all the info in the tuple returned by the translate_coords() - # only first 2 elements - pos_canvas = [pos_canvas[0], pos_canvas[1]] - # self.ui.position_label.setText("Position: X: %.4f\tY: %.4f" % (pos_canvas[0], pos_canvas[1])) - # pos_text = 'Coordinates: \nX: {:<7.4f}\nY: {:<7.4f}'.format(pos_canvas[0], pos_canvas[1]) - pos_text = 'Coordinates: \nX: {:<.4f}\nY: {:<.4f}'.format(pos_canvas[0], pos_canvas[1]) - self.plot.vispy_canvas.text.text = pos_text - - -if __name__ == '__main__': - app = QtWidgets.QApplication(sys.argv) - - m_app = MyApp() - sys.exit(app.exec_()) diff --git a/defaults.py b/defaults.py index 64f0fa70..b446a39a 100644 --- a/defaults.py +++ b/defaults.py @@ -43,7 +43,6 @@ class FlatCAMDefaults: # General "global_graphic_engine": '3D', - "global_hud": True, "global_app_level": 'b', "global_portable": False, "global_language": 'English', diff --git a/flatcamEditors/FlatCAMExcEditor.py b/flatcamEditors/FlatCAMExcEditor.py index 26666e0a..49dc5eb5 100644 --- a/flatcamEditors/FlatCAMExcEditor.py +++ b/flatcamEditors/FlatCAMExcEditor.py @@ -2119,7 +2119,7 @@ class FlatCAMExcEditor(QtCore.QObject): if self.app.is_legacy is False: self.shapes = self.app.plotcanvas.new_shape_collection(layers=1) if self.app.plotcanvas.big_cursor is True: - self.tool_shape = self.app.plotcanvas.new_shape_collection(layers=1) + self.tool_shape = self.app.plotcanvas.new_shape_collection(layers=1, line_width=2) else: self.tool_shape = self.app.plotcanvas.new_shape_collection(layers=1) else: @@ -3801,22 +3801,18 @@ class FlatCAMExcEditor(QtCore.QObject): self.snap_x = x self.snap_y = y + # update the position label in the infobar since the APP mouse event handlers are disconnected + self.app.ui.position_label.setText("    X: %.4f   " + "Y: %.4f" % (x, y)) + if self.pos is None: self.pos = (0, 0) self.app.dx = x - self.pos[0] self.app.dy = y - self.pos[1] - # # update the position label in the infobar since the APP mouse event handlers are disconnected - # self.app.ui.position_label.setText("    X: %.4f   " - # "Y: %.4f" % (x, y)) - # # update the reference position label in the infobar since the APP mouse event handlers are disconnected - # self.app.ui.rel_position_label.setText("Dx: %.4f   Dy: " - # "%.4f    " % (self.app.dx, self.app.dy)) - - units = self.app.defaults["units"].lower() - self.plotcanvas.text_hud.text = \ - 'Dx:\t{:<.4f} [{:s}]\nDy:\t{:<.4f} [{:s}]\nX: \t{:<.4f} [{:s}]\nY: \t{:<.4f} [{:s}]'.format( - self.app.dx, units, self.app.dy, units, x, units, y, units) + # update the reference position label in the infobar since the APP mouse event handlers are disconnected + self.app.ui.rel_position_label.setText("Dx: %.4f   Dy: " + "%.4f    " % (self.app.dx, self.app.dy)) # ## Utility geometry (animated) self.update_utility_geometry(data=(x, y)) diff --git a/flatcamEditors/FlatCAMGeoEditor.py b/flatcamEditors/FlatCAMGeoEditor.py index e8d969cb..ccf67ce4 100644 --- a/flatcamEditors/FlatCAMGeoEditor.py +++ b/flatcamEditors/FlatCAMGeoEditor.py @@ -3467,32 +3467,22 @@ class FlatCAMGeoEditor(QtCore.QObject): :return: """ try: - text_value = entry.text() - if ',' in text_value: - text_value = text_value.replace(',', '.') - self.options[opt] = float(text_value) + self.options[opt] = float(entry.text()) except Exception as e: - entry.set_value(self.app.defaults[opt]) log.debug("FlatCAMGeoEditor.__init__().entry2option() --> %s" % str(e)) return - def grid_changed(goption, gentry): + def gridx_changed(goption, gentry): """ - :param goption: String. Can be either 'global_gridx' or 'global_gridy' - :param gentry: A GUI element which text value is read and used + :param goption: String. Can be either 'global_gridx' or 'global_gridy' + :param gentry: A GUI element which text value is read and used :return: """ - if goption not in ['global_gridx', 'global_gridy']: - return - entry2option(opt=goption, entry=gentry) # if the grid link is checked copy the value in the GridX field to GridY try: - text_value = gentry.text() - if ',' in text_value: - text_value = text_value.replace(',', '.') - val = float(text_value) + val = float(gentry.get_value()) except ValueError: return @@ -3501,7 +3491,7 @@ class FlatCAMGeoEditor(QtCore.QObject): self.app.ui.grid_gap_x_entry.setValidator(QtGui.QDoubleValidator()) self.app.ui.grid_gap_x_entry.textChanged.connect( - lambda: grid_changed("global_gridx", self.app.ui.grid_gap_x_entry)) + lambda: gridx_changed("global_gridx", self.app.ui.grid_gap_x_entry)) self.app.ui.grid_gap_y_entry.setValidator(QtGui.QDoubleValidator()) self.app.ui.grid_gap_y_entry.textChanged.connect( @@ -4271,23 +4261,18 @@ class FlatCAMGeoEditor(QtCore.QObject): self.snap_y = y self.app.mouse = [x, y] + # update the position label in the infobar since the APP mouse event handlers are disconnected + self.app.ui.position_label.setText("    X: %.4f   " + "Y: %.4f" % (x, y)) + if self.pos is None: self.pos = (0, 0) self.app.dx = x - self.pos[0] self.app.dy = y - self.pos[1] - # # update the position label in the infobar since the APP mouse event handlers are disconnected - # self.app.ui.position_label.setText("    X: %.4f   " - # "Y: %.4f" % (x, y)) - # - # # update the reference position label in the infobar since the APP mouse event handlers are disconnected - # self.app.ui.rel_position_label.setText("Dx: %.4f   Dy: " - # "%.4f    " % (self.app.dx, self.app.dy)) - - units = self.app.defaults["units"].lower() - self.plotcanvas.text_hud.text = \ - 'Dx:\t{:<.4f} [{:s}]\nDy:\t{:<.4f} [{:s}]\nX: \t{:<.4f} [{:s}]\nY: \t{:<.4f} [{:s}]'.format( - self.app.dx, units, self.app.dy, units, x, units, y, units) + # update the reference position label in the infobar since the APP mouse event handlers are disconnected + self.app.ui.rel_position_label.setText("Dx: %.4f   Dy: " + "%.4f    " % (self.app.dx, self.app.dy)) if event.button == 1 and event_is_dragging and isinstance(self.active_tool, FCEraser): pass diff --git a/flatcamEditors/FlatCAMGrbEditor.py b/flatcamEditors/FlatCAMGrbEditor.py index d5659fbf..3362c5ba 100644 --- a/flatcamEditors/FlatCAMGrbEditor.py +++ b/flatcamEditors/FlatCAMGrbEditor.py @@ -4774,23 +4774,18 @@ class FlatCAMGrbEditor(QtCore.QObject): self.app.mouse = [x, y] + # update the position label in the infobar since the APP mouse event handlers are disconnected + self.app.ui.position_label.setText("    X: %.4f   " + "Y: %.4f" % (x, y)) + if self.pos is None: self.pos = (0, 0) self.app.dx = x - self.pos[0] self.app.dy = y - self.pos[1] - # # update the position label in the infobar since the APP mouse event handlers are disconnected - # self.app.ui.position_label.setText("    X: %.4f   " - # "Y: %.4f" % (x, y)) - # - # # update the reference position label in the infobar since the APP mouse event handlers are disconnected - # self.app.ui.rel_position_label.setText("Dx: %.4f   Dy: " - # "%.4f    " % (self.app.dx, self.app.dy)) - - units = self.app.defaults["units"].lower() - self.plotcanvas.text_hud.text = \ - 'Dx:\t{:<.4f} [{:s}]\nDy:\t{:<.4f} [{:s}]\nX: \t{:<.4f} [{:s}]\nY: \t{:<.4f} [{:s}]'.format( - self.app.dx, units, self.app.dy, units, x, units, y, units) + # update the reference position label in the infobar since the APP mouse event handlers are disconnected + self.app.ui.rel_position_label.setText("Dx: %.4f   Dy: " + "%.4f    " % (self.app.dx, self.app.dy)) self.update_utility_geometry(data=(x, y)) diff --git a/flatcamGUI/ColumnarFlowLayout.py b/flatcamGUI/ColumnarFlowLayout.py deleted file mode 100644 index 753c070b..00000000 --- a/flatcamGUI/ColumnarFlowLayout.py +++ /dev/null @@ -1,174 +0,0 @@ -import sys - -from PyQt5.QtCore import QPoint, QRect, QSize, Qt -from PyQt5.QtWidgets import QLayout, QSizePolicy -import math - -class ColumnarFlowLayout(QLayout): - def __init__(self, parent=None, margin=0, spacing=-1): - super().__init__(parent) - - if parent is not None: - self.setContentsMargins(margin, margin, margin, margin) - - self.setSpacing(spacing) - self.itemList = [] - - def __del__(self): - item = self.takeAt(0) - while item: - item = self.takeAt(0) - - def addItem(self, item): - self.itemList.append(item) - - def count(self): - return len(self.itemList) - - def itemAt(self, index): - if 0 <= index < len(self.itemList): - return self.itemList[index] - return None - - def takeAt(self, index): - if 0 <= index < len(self.itemList): - return self.itemList.pop(index) - return None - - def expandingDirections(self): - return Qt.Orientations(Qt.Orientation(0)) - - def hasHeightForWidth(self): - return True - - def heightForWidth(self, width): - height = self.doLayout(QRect(0, 0, width, 0), True) - return height - - def setGeometry(self, rect): - super().setGeometry(rect) - self.doLayout(rect, False) - - def sizeHint(self): - return self.minimumSize() - - def minimumSize(self): - size = QSize() - - for item in self.itemList: - size = size.expandedTo(item.minimumSize()) - - margin, _, _, _ = self.getContentsMargins() - - size += QSize(2 * margin, 2 * margin) - return size - - def doLayout(self, rect: QRect, testOnly: bool) -> int: - spacing = self.spacing() - x = rect.x() - y = rect.y() - - # Determine width of widest item - widest = 0 - for item in self.itemList: - widest = max(widest, item.sizeHint().width()) - - # Determine how many equal-width columns we can get, and how wide each one should be - column_count = math.floor(rect.width() / (widest + spacing)) - column_count = min(column_count, len(self.itemList)) - column_count = max(1, column_count) - column_width = math.floor((rect.width() - (column_count-1)*spacing - 1) / column_count) - - # Get the heights for all of our items - item_heights = {} - for item in self.itemList: - height = item.heightForWidth(column_width) if item.hasHeightForWidth() else item.sizeHint().height() - item_heights[item] = height - - # Prepare our column representation - column_contents = [] - column_heights = [] - for column_index in range(column_count): - column_contents.append([]) - column_heights.append(0) - - def add_to_column(column: int, item): - column_contents[column].append(item) - column_heights[column] += (item_heights[item] + spacing) - - def shove_one(from_column: int) -> bool: - if len(column_contents[from_column]) >= 1: - item = column_contents[from_column].pop(0) - column_heights[from_column] -= (item_heights[item] + spacing) - add_to_column(from_column-1, item) - return True - return False - - def shove_cascade_consider(from_column: int) -> bool: - changed = False - - if len(column_contents[from_column]) > 1: - item = column_contents[from_column][0] - item_height = item_heights[item] - if column_heights[from_column-1] + item_height < max(column_heights): - changed = shove_one(from_column) or changed - - if from_column+1 < column_count: - changed = shove_cascade_consider(from_column+1) or changed - - return changed - - def shove_cascade() -> bool: - if column_count < 2: - return False - changed = True - while changed: - changed = shove_cascade_consider(1) - return changed - - def pick_best_shoving_position() -> int: - best_pos = 1 - best_height = sys.maxsize - for column_index in range(1, column_count): - if len(column_contents[column_index]) == 0: - continue - item = column_contents[column_index][0] - height_after_shove = column_heights[column_index-1] + item_heights[item] - if height_after_shove < best_height: - best_height = height_after_shove - best_pos = column_index - return best_pos - - # Calculate the best layout - column_index = 0 - for item in self.itemList: - item_height = item_heights[item] - if column_heights[column_index] != 0 and (column_heights[column_index] + item_height) > max(column_heights): - column_index += 1 - if column_index >= column_count: - # Run out of room, need to shove more stuff in each column - if column_count >= 2: - changed = shove_cascade() - if not changed: - shoving_pos = pick_best_shoving_position() - shove_one(shoving_pos) - shove_cascade() - column_index = column_count-1 - - add_to_column(column_index, item) - - shove_cascade() - - # Set geometry according to the layout we have calculated - if not testOnly: - for column_index, items in enumerate(column_contents): - x = column_index * (column_width + spacing) - y = 0 - for item in items: - height = item_heights[item] - item.setGeometry(QRect(x, y, column_width, height)) - y += (height + spacing) - - # Return the overall height - return max(column_heights) - diff --git a/flatcamGUI/FlatCAMGUI.py b/flatcamGUI/FlatCAMGUI.py index deda0428..09d7383b 100644 --- a/flatcamGUI/FlatCAMGUI.py +++ b/flatcamGUI/FlatCAMGUI.py @@ -1207,6 +1207,89 @@ class FlatCAMGUI(QtWidgets.QMainWindow): self.pref_tab_area_tabBar.setExpanding(True) self.pref_tab_layout.addWidget(self.pref_tab_area) + self.general_tab = QtWidgets.QWidget() + self.general_tab.setObjectName("general_tab") + self.pref_tab_area.addTab(self.general_tab, _("General")) + self.general_tab_lay = QtWidgets.QVBoxLayout() + self.general_tab_lay.setContentsMargins(2, 2, 2, 2) + self.general_tab.setLayout(self.general_tab_lay) + + self.hlay1 = QtWidgets.QHBoxLayout() + self.general_tab_lay.addLayout(self.hlay1) + + self.hlay1.addStretch() + + self.general_scroll_area = QtWidgets.QScrollArea() + self.general_tab_lay.addWidget(self.general_scroll_area) + + self.gerber_tab = QtWidgets.QWidget() + self.gerber_tab.setObjectName("gerber_tab") + self.pref_tab_area.addTab(self.gerber_tab, _("GERBER")) + self.gerber_tab_lay = QtWidgets.QVBoxLayout() + self.gerber_tab_lay.setContentsMargins(2, 2, 2, 2) + self.gerber_tab.setLayout(self.gerber_tab_lay) + + self.gerber_scroll_area = QtWidgets.QScrollArea() + self.gerber_tab_lay.addWidget(self.gerber_scroll_area) + + self.excellon_tab = QtWidgets.QWidget() + self.excellon_tab.setObjectName("excellon_tab") + self.pref_tab_area.addTab(self.excellon_tab, _("EXCELLON")) + self.excellon_tab_lay = QtWidgets.QVBoxLayout() + self.excellon_tab_lay.setContentsMargins(2, 2, 2, 2) + self.excellon_tab.setLayout(self.excellon_tab_lay) + + self.excellon_scroll_area = QtWidgets.QScrollArea() + self.excellon_tab_lay.addWidget(self.excellon_scroll_area) + + self.geometry_tab = QtWidgets.QWidget() + self.geometry_tab.setObjectName("geometry_tab") + self.pref_tab_area.addTab(self.geometry_tab, _("GEOMETRY")) + self.geometry_tab_lay = QtWidgets.QVBoxLayout() + self.geometry_tab_lay.setContentsMargins(2, 2, 2, 2) + self.geometry_tab.setLayout(self.geometry_tab_lay) + + self.geometry_scroll_area = QtWidgets.QScrollArea() + self.geometry_tab_lay.addWidget(self.geometry_scroll_area) + + self.text_editor_tab = QtWidgets.QWidget() + self.text_editor_tab.setObjectName("text_editor_tab") + self.pref_tab_area.addTab(self.text_editor_tab, _("CNC-JOB")) + self.cncjob_tab_lay = QtWidgets.QVBoxLayout() + self.cncjob_tab_lay.setContentsMargins(2, 2, 2, 2) + self.text_editor_tab.setLayout(self.cncjob_tab_lay) + + self.cncjob_scroll_area = QtWidgets.QScrollArea() + self.cncjob_tab_lay.addWidget(self.cncjob_scroll_area) + + self.tools_tab = QtWidgets.QWidget() + self.pref_tab_area.addTab(self.tools_tab, _("TOOLS")) + self.tools_tab_lay = QtWidgets.QVBoxLayout() + self.tools_tab_lay.setContentsMargins(2, 2, 2, 2) + self.tools_tab.setLayout(self.tools_tab_lay) + + self.tools_scroll_area = QtWidgets.QScrollArea() + self.tools_tab_lay.addWidget(self.tools_scroll_area) + + self.tools2_tab = QtWidgets.QWidget() + self.pref_tab_area.addTab(self.tools2_tab, _("TOOLS 2")) + self.tools2_tab_lay = QtWidgets.QVBoxLayout() + self.tools2_tab_lay.setContentsMargins(2, 2, 2, 2) + self.tools2_tab.setLayout(self.tools2_tab_lay) + + self.tools2_scroll_area = QtWidgets.QScrollArea() + self.tools2_tab_lay.addWidget(self.tools2_scroll_area) + + self.fa_tab = QtWidgets.QWidget() + self.fa_tab.setObjectName("fa_tab") + self.pref_tab_area.addTab(self.fa_tab, _("UTILITIES")) + self.fa_tab_lay = QtWidgets.QVBoxLayout() + self.fa_tab_lay.setContentsMargins(2, 2, 2, 2) + self.fa_tab.setLayout(self.fa_tab_lay) + + self.fa_scroll_area = QtWidgets.QScrollArea() + self.fa_tab_lay.addWidget(self.fa_scroll_area) + self.pref_tab_bottom_layout = QtWidgets.QHBoxLayout() self.pref_tab_bottom_layout.setAlignment(QtCore.Qt.AlignVCenter) self.pref_tab_layout.addLayout(self.pref_tab_bottom_layout) @@ -2223,17 +2306,17 @@ class FlatCAMGUI(QtWidgets.QMainWindow): self.snap_infobar_label.setPixmap(QtGui.QPixmap(self.app.resource_location + '/snap_16.png')) self.infobar.addWidget(self.snap_infobar_label) - # self.rel_position_label = QtWidgets.QLabel( - # "Dx: 0.0000   Dy: 0.0000    ") - # self.rel_position_label.setMinimumWidth(110) - # self.rel_position_label.setToolTip(_("Relative measurement.\nReference is last click position")) - # self.infobar.addWidget(self.rel_position_label) - # - # self.position_label = QtWidgets.QLabel( - # "    X: 0.0000   Y: 0.0000") - # self.position_label.setMinimumWidth(110) - # self.position_label.setToolTip(_("Absolute measurement.\nReference is (X=0, Y= 0) position")) - # self.infobar.addWidget(self.position_label) + self.rel_position_label = QtWidgets.QLabel( + "Dx: 0.0000   Dy: 0.0000    ") + self.rel_position_label.setMinimumWidth(110) + self.rel_position_label.setToolTip(_("Relative measurement.\nReference is last click position")) + self.infobar.addWidget(self.rel_position_label) + + self.position_label = QtWidgets.QLabel( + "    X: 0.0000   Y: 0.0000") + self.position_label.setMinimumWidth(110) + self.position_label.setToolTip(_("Absolute measurement.\nReference is (X=0, Y= 0) position")) + self.infobar.addWidget(self.position_label) self.units_label = QtWidgets.QLabel("[in]") self.units_label.setMargin(2) @@ -2910,11 +2993,6 @@ class FlatCAMGUI(QtWidgets.QMainWindow): if key == QtCore.Qt.Key_G: self.app.on_toggle_axis() - # Toggle HUD (Heads-Up Display) - if key == QtCore.Qt.Key_H: - state = False if self.app.plotcanvas.hud_enabled else True - self.app.plotcanvas.on_toggle_hud(state=state) - # Locate in Object if key == QtCore.Qt.Key_J: self.app.on_locate(obj=self.app.collection.get_active()) @@ -3984,7 +4062,7 @@ class FlatCAMGUI(QtWidgets.QMainWindow): if key == QtCore.Qt.Key_T or key == 'T': self.app.exc_editor.launched_from_shortcuts = True # ## Current application units in Upper Case - self.units = self.general_defaults_form.option_dict()["units"].get_field().get_value().upper() + self.units = self.general_defaults_form.general_app_group.units_radio.get_value().upper() tool_add_popup = FCInputDialog(title=_("New Tool ..."), text='%s:' % _('Enter a Tool Diameter'), min=0.0000, max=99.9999, decimals=4) @@ -4202,153 +4280,6 @@ class FlatCAMGUI(QtWidgets.QMainWindow): self.final_save.emit() event.ignore() - def set_layout(self, layout: str): - """ - Set the toolbars layout (location) - - :param index: - :param lay: Type of layout to be set on the toolbard - :return: None - """ - - self.app.defaults.report_usage("on_layout()") - - lay_settings = QSettings("Open Source", "FlatCAM") - lay_settings.setValue('layout', layout) - # This will write the setting to the platform specific storage. - del lay_settings - - # first remove the toolbars: - try: - self.removeToolBar(self.app.ui.toolbarfile) - self.removeToolBar(self.app.ui.toolbargeo) - self.removeToolBar(self.app.ui.toolbarview) - self.removeToolBar(self.app.ui.toolbarshell) - self.removeToolBar(self.app.ui.toolbartools) - self.removeToolBar(self.app.ui.exc_edit_toolbar) - self.removeToolBar(self.app.ui.geo_edit_toolbar) - self.removeToolBar(self.app.ui.grb_edit_toolbar) - self.removeToolBar(self.app.ui.snap_toolbar) - self.removeToolBar(self.app.ui.toolbarshell) - except Exception: - pass - - if layout == 'compact': - # ## TOOLBAR INSTALLATION # ## - self.toolbarfile = QtWidgets.QToolBar('File Toolbar') - self.toolbarfile.setObjectName('File_TB') - self.addToolBar(Qt.LeftToolBarArea, self.app.ui.toolbarfile) - - self.toolbargeo = QtWidgets.QToolBar('Edit Toolbar') - self.toolbargeo.setObjectName('Edit_TB') - self.addToolBar(Qt.LeftToolBarArea, self.app.ui.toolbargeo) - - self.toolbarshell = QtWidgets.QToolBar('Shell Toolbar') - self.toolbarshell.setObjectName('Shell_TB') - self.addToolBar(Qt.LeftToolBarArea, self.app.ui.toolbarshell) - - self.toolbartools = QtWidgets.QToolBar('Tools Toolbar') - self.toolbartools.setObjectName('Tools_TB') - self.addToolBar(Qt.LeftToolBarArea, self.app.ui.toolbartools) - - self.geo_edit_toolbar = QtWidgets.QToolBar('Geometry Editor Toolbar') - # self.geo_edit_toolbar.setVisible(False) - self.geo_edit_toolbar.setObjectName('GeoEditor_TB') - self.addToolBar(Qt.RightToolBarArea, self.app.ui.geo_edit_toolbar) - - self.toolbarview = QtWidgets.QToolBar('View Toolbar') - self.toolbarview.setObjectName('View_TB') - self.addToolBar(Qt.RightToolBarArea, self.app.ui.toolbarview) - - self.addToolBarBreak(area=Qt.RightToolBarArea) - - self.grb_edit_toolbar = QtWidgets.QToolBar('Gerber Editor Toolbar') - # self.grb_edit_toolbar.setVisible(False) - self.grb_edit_toolbar.setObjectName('GrbEditor_TB') - self.addToolBar(Qt.RightToolBarArea, self.app.ui.grb_edit_toolbar) - - self.exc_edit_toolbar = QtWidgets.QToolBar('Excellon Editor Toolbar') - self.exc_edit_toolbar.setObjectName('ExcEditor_TB') - self.addToolBar(Qt.RightToolBarArea, self.app.ui.exc_edit_toolbar) - - self.snap_toolbar = QtWidgets.QToolBar('Grid Toolbar') - self.snap_toolbar.setObjectName('Snap_TB') - self.snap_toolbar.setMaximumHeight(30) - self.splitter_left.addWidget(self.app.ui.snap_toolbar) - - self.corner_snap_btn.setVisible(True) - self.snap_magnet.setVisible(True) - else: - # ## TOOLBAR INSTALLATION # ## - self.toolbarfile = QtWidgets.QToolBar('File Toolbar') - self.toolbarfile.setObjectName('File_TB') - self.addToolBar(self.app.ui.toolbarfile) - - self.toolbargeo = QtWidgets.QToolBar('Edit Toolbar') - self.toolbargeo.setObjectName('Edit_TB') - self.addToolBar(self.app.ui.toolbargeo) - - self.toolbarview = QtWidgets.QToolBar('View Toolbar') - self.toolbarview.setObjectName('View_TB') - self.addToolBar(self.app.ui.toolbarview) - - self.toolbarshell = QtWidgets.QToolBar('Shell Toolbar') - self.toolbarshell.setObjectName('Shell_TB') - self.addToolBar(self.app.ui.toolbarshell) - - self.toolbartools = QtWidgets.QToolBar('Tools Toolbar') - self.toolbartools.setObjectName('Tools_TB') - self.addToolBar(self.app.ui.toolbartools) - - self.exc_edit_toolbar = QtWidgets.QToolBar('Excellon Editor Toolbar') - # self.exc_edit_toolbar.setVisible(False) - self.exc_edit_toolbar.setObjectName('ExcEditor_TB') - self.addToolBar(self.app.ui.exc_edit_toolbar) - - self.addToolBarBreak() - - self.geo_edit_toolbar = QtWidgets.QToolBar('Geometry Editor Toolbar') - # self.geo_edit_toolbar.setVisible(False) - self.geo_edit_toolbar.setObjectName('GeoEditor_TB') - self.addToolBar(self.app.ui.geo_edit_toolbar) - - self.grb_edit_toolbar = QtWidgets.QToolBar('Gerber Editor Toolbar') - # self.grb_edit_toolbar.setVisible(False) - self.grb_edit_toolbar.setObjectName('GrbEditor_TB') - self.addToolBar(self.app.ui.grb_edit_toolbar) - - self.snap_toolbar = QtWidgets.QToolBar('Grid Toolbar') - self.snap_toolbar.setObjectName('Snap_TB') - # self.snap_toolbar.setMaximumHeight(30) - self.addToolBar(self.app.ui.snap_toolbar) - - self.corner_snap_btn.setVisible(False) - self.snap_magnet.setVisible(False) - - if layout == 'minimal': - self.toolbarview.setVisible(False) - self.toolbarshell.setVisible(False) - self.snap_toolbar.setVisible(False) - self.geo_edit_toolbar.setVisible(False) - self.grb_edit_toolbar.setVisible(False) - self.exc_edit_toolbar.setVisible(False) - self.lock_toolbar(lock=True) - - # add all the actions to the toolbars - self.populate_toolbars() - - # reconnect all the signals to the toolbar actions - self.app.connect_toolbar_signals() - - self.grid_snap_btn.setChecked(True) - self.on_grid_snap_triggered(state=True) - - self.grid_gap_x_entry.setText(str(self.app.defaults["global_gridx"])) - self.grid_gap_y_entry.setText(str(self.app.defaults["global_gridy"])) - self.snap_max_dist_entry.setText(str(self.app.defaults["global_snap_max"])) - self.grid_gap_link_cb.setChecked(True) - - class FlatCAMActivityView(QtWidgets.QWidget): """ diff --git a/flatcamGUI/GUIElements.py b/flatcamGUI/GUIElements.py index d048a022..7b9b38f4 100644 --- a/flatcamGUI/GUIElements.py +++ b/flatcamGUI/GUIElements.py @@ -656,104 +656,6 @@ class EvalEntry2(QtWidgets.QLineEdit): return QtCore.QSize(EDIT_SIZE_HINT, default_hint_size.height()) -class FCColorEntry(QtWidgets.QFrame): - - def __init__(self, **kwargs): - super().__init__(**kwargs) - - self.entry = FCEntry() - - self.button = QtWidgets.QPushButton() - self.button.setFixedSize(15, 15) - self.button.setStyleSheet("border-color: dimgray;") - - self.layout = QtWidgets.QHBoxLayout() - self.layout.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter) - self.layout.setContentsMargins(0, 0, 0, 0) - self.layout.addWidget(self.entry) - self.layout.addWidget(self.button) - self.setLayout(self.layout) - - self.entry.editingFinished.connect(self._sync_button_color) - self.button.clicked.connect(self._on_button_clicked) - - - def get_value(self) -> str: - return self.entry.get_value() - - def set_value(self, value: str): - self.entry.set_value(value) - self._sync_button_color() - - def _sync_button_color(self): - value = self.get_value() - self.button.setStyleSheet("background-color:%s;" % self._extract_color(value)) - - def _on_button_clicked(self): - value = self.entry.get_value() - current_color = QtGui.QColor(self._extract_color(value)) - - color_dialog = QtWidgets.QColorDialog() - selected_color = color_dialog.getColor(initial=current_color, options=QtWidgets.QColorDialog.ShowAlphaChannel) - - if selected_color.isValid() is False: - return - - new_value = str(selected_color.name()) + self._extract_alpha(value) - self.set_value(new_value) - - def _extract_color(self, value: str) -> str: - return value[:7] - - def _extract_alpha(self, value: str) -> str: - return value[7:9] - - -class FCSliderWithSpinner(QtWidgets.QFrame): - - def __init__(self, min=0, max=100, step=1, **kwargs): - super().__init__(**kwargs) - - self.slider = QtWidgets.QSlider(QtCore.Qt.Horizontal) - self.slider.setMinimum(min) - self.slider.setMaximum(max) - self.slider.setSingleStep(step) - - self.spinner = FCSpinner() - self.spinner.set_range(min, max) - self.spinner.set_step(step) - self.spinner.setMinimumWidth(70) - - self.layout = QtWidgets.QHBoxLayout() - self.layout.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter) - self.layout.setContentsMargins(0, 0, 0, 0) - self.layout.addWidget(self.slider) - self.layout.addWidget(self.spinner) - self.setLayout(self.layout) - - self.slider.valueChanged.connect(self._on_slider) - self.spinner.valueChanged.connect(self._on_spinner) - - self.valueChanged = self.spinner.valueChanged - - def get_value(self) -> int: - return self.spinner.get_value() - - def set_value(self, value: int): - self.spinner.set_value(value) - - def _on_spinner(self): - spinner_value = self.spinner.value() - self.slider.setValue(spinner_value) - - def _on_slider(self): - slider_value = self.slider.value() - self.spinner.set_value(slider_value) - - - - - class FCSpinner(QtWidgets.QSpinBox): returnPressed = QtCore.pyqtSignal() diff --git a/flatcamGUI/PlotCanvas.py b/flatcamGUI/PlotCanvas.py index a1be6099..44af74d0 100644 --- a/flatcamGUI/PlotCanvas.py +++ b/flatcamGUI/PlotCanvas.py @@ -10,7 +10,7 @@ from PyQt5 import QtCore import logging from flatcamGUI.VisPyCanvas import VisPyCanvas, Color from flatcamGUI.VisPyVisuals import ShapeGroup, ShapeCollection, TextCollection, TextGroup, Cursor -from vispy.scene.visuals import InfiniteLine, Line, Rectangle, Text +from vispy.scene.visuals import InfiniteLine, Line import numpy as np from vispy.geometry import Rect @@ -54,12 +54,8 @@ class PlotCanvas(QtCore.QObject, VisPyCanvas): if theme == 'white': self.line_color = (0.3, 0.0, 0.0, 1.0) - self.rect_hud_color = Color('#0000FF10') - self.text_hud_color = 'black' else: self.line_color = (0.4, 0.4, 0.4, 1.0) - self.rect_hud_color = Color('#0000FF10') - self.text_hud_color = 'white' # workspace lines; I didn't use the rectangle because I didn't want to add another VisPy Node, # which might decrease performance @@ -150,28 +146,13 @@ class PlotCanvas(QtCore.QObject, VisPyCanvas): self.cursor_h_line = InfiniteLine(pos=None, color=c_color, vertical=False, parent=self.line_parent) - self.rect_hud = Rectangle(center=(90,45), color=self.rect_hud_color, border_color=self.rect_hud_color, - width=170, height=80, radius=[5, 5, 5, 5], parent=None) - self.rect_hud.set_gl_state(depth_test=False) - - # HUD Display - self.hud_enabled = False - - self.text_hud = Text('', color=self.text_hud_color, pos=(8, 45), method='gpu', anchor_x='left', parent=None) - self.text_hud.font_size = 8 - units = self.fcapp.defaults["units"].lower() - self.text_hud.text = 'Dx:\t%s [%s]\nDy:\t%s [%s]\nX: \t%s [%s]\nY: \t%s [%s]' % \ - ('0.0000', units, '0.0000', units, '0.0000', units, '0.0000', units) - - if self.fcapp.defaults['global_hud'] is True: - self.on_toggle_hud(state=True) - self.shape_collections = [] self.shape_collection = self.new_shape_collection() self.fcapp.pool_recreated.connect(self.on_pool_recreated) self.text_collection = self.new_text_collection() + # TODO: Should be setting to show/hide CNC job annotations (global or per object) self.text_collection.enabled = True self.c = None @@ -182,16 +163,6 @@ class PlotCanvas(QtCore.QObject, VisPyCanvas): self.graph_event_connect('mouse_wheel', self.on_mouse_scroll) - def on_toggle_hud(self, state): - if state: - self.hud_enabled = True - self.rect_hud.parent = self.view - self.text_hud.parent = self.view - else: - self.hud_enabled = False - self.rect_hud.parent = None - self.text_hud.parent = None - def draw_workspace(self, workspace_size): """ Draw a rectangular shape on canvas to specify our valid workspace. diff --git a/flatcamGUI/PlotCanvasLegacy.py b/flatcamGUI/PlotCanvasLegacy.py index 7856bb8f..a9a6216f 100644 --- a/flatcamGUI/PlotCanvasLegacy.py +++ b/flatcamGUI/PlotCanvasLegacy.py @@ -29,7 +29,6 @@ mpl_use("Qt5Agg") from matplotlib.figure import Figure from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas from matplotlib.lines import Line2D -from matplotlib.offsetbox import AnchoredText # from matplotlib.widgets import Cursor fcTranslate.apply_language('strings') @@ -148,13 +147,9 @@ class PlotCanvasLegacy(QtCore.QObject): if self.app.defaults['global_theme'] == 'white': theme_color = '#FFFFFF' tick_color = '#000000' - self.rect_hud_color = '#0000FF10' - self.text_hud_color = '#000000' else: theme_color = '#000000' tick_color = '#FFFFFF' - self.rect_hud_color = '#0000FF10' - self.text_hud_color = '#000000' # workspace lines; I didn't use the rectangle because I didn't want to add another VisPy Node, # which might decrease performance @@ -303,79 +298,11 @@ class PlotCanvasLegacy(QtCore.QObject): # signal if there is a doubleclick self.is_dblclk = False - self.hud_enabled = False - self.text_hud = self.Thud(plotcanvas=self) - - # bbox_props = dict(boxstyle="round,pad=0.3", fc="blue", ec="b", lw=0) - # self.text_hud = self.figure.text(0, 0, "Direction", ha="left", va="center", rotation=0, - # size=15, - # bbox=bbox_props) - # draw a rectangle made out of 4 lines on the canvas to serve as a hint for the work area # all CNC have a limited workspace if self.app.defaults['global_workspace'] is True: self.draw_workspace(workspace_size=self.app.defaults["global_workspaceT"]) - if self.app.defaults['global_hud'] is True: - self.on_toggle_hud(state=True) - - def on_toggle_hud(self, state): - if state: - self.hud_enabled = True - self.text_hud.add_artist() - else: - self.hud_enabled = False - self.text_hud.remove_artist() - self.canvas.draw() - - class Thud(QtCore.QObject): - text_changed = QtCore.pyqtSignal(str) - - def __init__(self, plotcanvas): - super().__init__() - - self.p = plotcanvas - units = self.p.app.defaults['units'] - self._text = 'Dx: %s [%s]\nDy: %s [%s]\nX: %s [%s]\nY: %s [%s]' % \ - ('0.0000', units, '0.0000', units, '0.0000', units, '0.0000', units) - - self.hud_holder = AnchoredText(self._text, - prop=dict(size=20), frameon=True, - loc='upper left', - ) - self.hud_holder.patch.set_boxstyle("round,pad=0.,rounding_size=0.2") - - self.hud_holder.patch.set_facecolor('blue') - self.hud_holder.patch.set_alpha(0.3) - self.hud_holder.patch.set_edgecolor((0, 0, 0, 0)) - - self.text_changed.connect(self.on_text_changed) - - @property - def text(self): - return self._text - - @text.setter - def text(self, val): - self.text_changed.emit(val) - self._text = val - - def on_text_changed(self, txt): - try: - txt = txt.replace('\t', ' ') - self.hud_holder.txt.set_text(txt) - self.p.canvas.draw() - except Exception: - pass - - def add_artist(self): - if self.hud_holder not in self.p.axes.artists: - self.p.axes.add_artist(self.hud_holder) - - def remove_artist(self): - if self.hud_holder in self.p.axes.artists: - self.p.axes.artists.remove(self.hud_holder) - def draw_workspace(self, workspace_size): """ Draw a rectangular shape on canvas to specify our valid workspace. diff --git a/flatcamGUI/VisPyCanvas.py b/flatcamGUI/VisPyCanvas.py index aa55675f..7d7efe13 100644 --- a/flatcamGUI/VisPyCanvas.py +++ b/flatcamGUI/VisPyCanvas.py @@ -13,7 +13,6 @@ import numpy as np import vispy.scene as scene from vispy.scene.cameras.base_camera import BaseCamera -# from vispy.scene.widgets import Widget as VisPyWidget from vispy.color import Color import time diff --git a/flatcamGUI/preferences/OptionUI.py b/flatcamGUI/preferences/OptionUI.py deleted file mode 100644 index 824c417a..00000000 --- a/flatcamGUI/preferences/OptionUI.py +++ /dev/null @@ -1,322 +0,0 @@ -from typing import Union, Sequence, List - -from PyQt5 import QtWidgets, QtGui -from PyQt5.QtCore import QSettings - -from flatcamGUI.GUIElements import RadioSet, FCCheckBox, FCButton, FCComboBox, FCEntry, FCSpinner, FCColorEntry, \ - FCSliderWithSpinner, FCDoubleSpinner, FloatEntry, FCTextArea - -import gettext -import FlatCAMTranslation as fcTranslate -import builtins - -fcTranslate.apply_language('strings') -if '_' not in builtins.__dict__: - _ = gettext.gettext - - -class OptionUI: - - def __init__(self, option: str): - self.option = option - - def add_to_grid(self, grid: QtWidgets.QGridLayout, row: int) -> int: - """ - Adds the necessary widget to the grid, starting at the supplied row. - Returns the number of rows used (normally 1) - """ - raise NotImplementedError() - - def get_field(self): - raise NotImplementedError() - - -class BasicOptionUI(OptionUI): - """Abstract OptionUI that has a label on the left then some other widget on the right""" - def __init__(self, option: str, label_text: str, label_tooltip: Union[str, None] = None, label_bold: bool = False, label_color: Union[str, None] = None): - super().__init__(option=option) - self.label_text = label_text - self.label_tooltip = label_tooltip - self.label_bold = label_bold - self.label_color = label_color - self.label_widget = self.build_label_widget() - self.entry_widget = self.build_entry_widget() - - def build_label_widget(self) -> QtWidgets.QLabel: - fmt = "%s:" - if self.label_bold: - fmt = "%s" % fmt - if self.label_color: - fmt = "%s" % (self.label_color, fmt) - label_widget = QtWidgets.QLabel(fmt % _(self.label_text)) - if self.label_tooltip is not None: - label_widget.setToolTip(_(self.label_tooltip)) - return label_widget - - def build_entry_widget(self) -> QtWidgets.QWidget: - raise NotImplementedError() - - def add_to_grid(self, grid: QtWidgets.QGridLayout, row: int) -> int: - grid.addWidget(self.label_widget, row, 0) - grid.addWidget(self.entry_widget, row, 1) - return 1 - - def get_field(self): - return self.entry_widget - - -class LineEntryOptionUI(BasicOptionUI): - def build_entry_widget(self) -> QtWidgets.QWidget: - return FCEntry() - - -# Not sure why this is needed over DoubleSpinnerOptionUI -class FloatEntryOptionUI(BasicOptionUI): - def build_entry_widget(self) -> QtWidgets.QWidget: - return FloatEntry() - - -class RadioSetOptionUI(BasicOptionUI): - - def __init__(self, option: str, label_text: str, choices: list, orientation='horizontal', **kwargs): - self.choices = choices - self.orientation = orientation - super().__init__(option=option, label_text=label_text, **kwargs) - - def build_entry_widget(self) -> QtWidgets.QWidget: - return RadioSet(choices=self.choices, orientation=self.orientation) - - -class TextAreaOptionUI(OptionUI): - - def __init__(self, option: str, label_text: str, label_tooltip: str): - super().__init__(option=option) - self.label_text = label_text - self.label_tooltip = label_tooltip - self.label_widget = self.build_label_widget() - self.textarea_widget = self.build_textarea_widget() - - def build_label_widget(self): - label = QtWidgets.QLabel("%s:" % _(self.label_text)) - label.setToolTip(_(self.label_tooltip)) - return label - - def build_textarea_widget(self): - textarea = FCTextArea() - textarea.setPlaceholderText(_(self.label_tooltip)) - - qsettings = QSettings("Open Source", "FlatCAM") - if qsettings.contains("textbox_font_size"): - tb_fsize = qsettings.value('textbox_font_size', type=int) - else: - tb_fsize = 10 - font = QtGui.QFont() - font.setPointSize(tb_fsize) - textarea.setFont(font) - - return textarea - - def get_field(self): - return self.textarea_widget - - def add_to_grid(self, grid: QtWidgets.QGridLayout, row: int) -> int: - grid.addWidget(self.label_widget, row, 0, 1, 3) - grid.addWidget(self.textarea_widget, row+1, 0, 1, 3) - return 2 - - -class CheckboxOptionUI(OptionUI): - - def __init__(self, option: str, label_text: str, label_tooltip: str): - super().__init__(option=option) - self.label_text = label_text - self.label_tooltip = label_tooltip - self.checkbox_widget = self.build_checkbox_widget() - - def build_checkbox_widget(self): - checkbox = FCCheckBox('%s' % _(self.label_text)) - checkbox.setToolTip(_(self.label_tooltip)) - return checkbox - - def add_to_grid(self, grid: QtWidgets.QGridLayout, row: int) -> int: - grid.addWidget(self.checkbox_widget, row, 0, 1, 3) - return 1 - - def get_field(self): - return self.checkbox_widget - - -class ComboboxOptionUI(BasicOptionUI): - - def __init__(self, option: str, label_text: str, choices: Sequence, **kwargs): - self.choices = choices - super().__init__(option=option, label_text=label_text, **kwargs) - - def build_entry_widget(self): - combo = FCComboBox() - for choice in self.choices: - # don't translate the QCombo items as they are used in QSettings and identified by name - combo.addItem(choice) - return combo - - -class ColorOptionUI(BasicOptionUI): - def build_entry_widget(self) -> QtWidgets.QWidget: - entry = FCColorEntry() - return entry - - -class SliderWithSpinnerOptionUI(BasicOptionUI): - def __init__(self, option: str, label_text: str, min_value=0, max_value=100, step=1, **kwargs): - self.min_value = min_value - self.max_value = max_value - self.step = step - super().__init__(option=option, label_text=label_text, **kwargs) - - def build_entry_widget(self) -> QtWidgets.QWidget: - entry = FCSliderWithSpinner(min=self.min_value, max=self.max_value, step=self.step) - return entry - - -class ColorAlphaSliderOptionUI(SliderWithSpinnerOptionUI): - def __init__(self, applies_to: List[str], group, label_text: str, **kwargs): - self.applies_to = applies_to - self.group = group - super().__init__(option="__color_alpha_slider", label_text=label_text, min_value=0, max_value=255, step=1, **kwargs) - self.get_field().valueChanged.connect(self._on_alpha_change) - - def add_to_grid(self, grid: QtWidgets.QGridLayout, row: int) -> int: - for index, field in enumerate(self._get_target_fields()): - field.entry.textChanged.connect(lambda value, i=index: self._on_target_change(target_index=i)) - return super().add_to_grid(grid, row) - - def _get_target_fields(self): - return list(map(lambda n: self.group.option_dict()[n].get_field(), self.applies_to)) - - def _on_target_change(self, target_index: int): - field = self._get_target_fields()[target_index] - color = field.get_value() - alpha_part = color[7:] - if len(alpha_part) != 2: - return - alpha = int(alpha_part, 16) - if alpha < 0 or alpha > 255 or self.get_field().get_value() == alpha: - return - self.get_field().set_value(alpha) - - def _on_alpha_change(self): - alpha = self.get_field().get_value() - for field in self._get_target_fields(): - old_value = field.get_value() - new_value = self._modify_color_alpha(old_value, alpha=alpha) - field.set_value(new_value) - - def _modify_color_alpha(self, color: str, alpha: int): - color_without_alpha = color[:7] - if alpha > 255: - return color_without_alpha + "FF" - elif alpha < 0: - return color_without_alpha + "00" - else: - hexalpha = hex(alpha)[2:] - if len(hexalpha) == 1: - hexalpha = "0" + hexalpha - return color_without_alpha + hexalpha - - -class SpinnerOptionUI(BasicOptionUI): - def __init__(self, option: str, label_text: str, min_value: int, max_value: int, step: int = 1, **kwargs): - self.min_value = min_value - self.max_value = max_value - self.step = step - super().__init__(option=option, label_text=label_text, **kwargs) - - def build_entry_widget(self) -> QtWidgets.QWidget: - entry = FCSpinner() - entry.set_range(self.min_value, self.max_value) - entry.set_step(self.step) - entry.setWrapping(True) - return entry - - -class DoubleSpinnerOptionUI(BasicOptionUI): - def __init__(self, option: str, label_text: str, step: float, decimals: int, min_value=None, max_value=None, suffix=None, **kwargs): - self.min_value = min_value - self.max_value = max_value - self.step = step - self.suffix = suffix - self.decimals = decimals - super().__init__(option=option, label_text=label_text, **kwargs) - - def build_entry_widget(self) -> QtWidgets.QWidget: - entry = FCDoubleSpinner(suffix=self.suffix) - entry.set_precision(self.decimals) - entry.setSingleStep(self.step) - if self.min_value is None: - self.min_value = entry.minimum() - else: - entry.setMinimum(self.min_value) - if self.max_value is None: - self.max_value = entry.maximum() - else: - entry.setMaximum(self.max_value) - return entry - - -class HeadingOptionUI(OptionUI): - def __init__(self, label_text: str, label_tooltip: Union[str, None] = None): - super().__init__(option="__heading") - self.label_text = label_text - self.label_tooltip = label_tooltip - - def build_heading_widget(self): - heading = QtWidgets.QLabel('%s' % _(self.label_text)) - heading.setToolTip(_(self.label_tooltip)) - return heading - - def add_to_grid(self, grid: QtWidgets.QGridLayout, row: int) -> int: - grid.addWidget(self.build_heading_widget(), row, 0, 1, 2) - return 1 - - def get_field(self): - return None - - -class SeparatorOptionUI(OptionUI): - - def __init__(self): - super().__init__(option="__separator") - - def build_separator_widget(self): - separator = QtWidgets.QFrame() - separator.setFrameShape(QtWidgets.QFrame.HLine) - separator.setFrameShadow(QtWidgets.QFrame.Sunken) - return separator - - def add_to_grid(self, grid: QtWidgets.QGridLayout, row: int) -> int: - grid.addWidget(self.build_separator_widget(), row, 0, 1, 2) - return 1 - - def get_field(self): - return None - - -class FullWidthButtonOptionUI(OptionUI): - def __init__(self, option: str, label_text: str, label_tooltip: Union[str, None]): - super().__init__(option=option) - self.label_text = label_text - self.label_tooltip = label_tooltip - self.button_widget = self.build_button_widget() - - def build_button_widget(self): - button = FCButton(_(self.label_text)) - if self.label_tooltip is not None: - button.setToolTip(_(self.label_tooltip)) - return button - - def add_to_grid(self, grid: QtWidgets.QGridLayout, row: int) -> int: - grid.addWidget(self.button_widget, row, 0, 1, 3) - return 1 - - def get_field(self): - return self.button_widget \ No newline at end of file diff --git a/flatcamGUI/preferences/OptionsGroupUI.py b/flatcamGUI/preferences/OptionsGroupUI.py index 2f519ea9..98780004 100644 --- a/flatcamGUI/preferences/OptionsGroupUI.py +++ b/flatcamGUI/preferences/OptionsGroupUI.py @@ -1,32 +1,12 @@ -from typing import Dict - from PyQt5 import QtWidgets -from PyQt5.QtCore import QSettings - -import gettext -import FlatCAMTranslation as fcTranslate -import builtins - -from flatcamGUI.preferences.OptionUI import OptionUI - -fcTranslate.apply_language('strings') -if '_' not in builtins.__dict__: - _ = gettext.gettext - -settings = QSettings("Open Source", "FlatCAM") -if settings.contains("machinist"): - machinist_setting = settings.value('machinist', type=int) -else: - machinist_setting = 0 - class OptionsGroupUI(QtWidgets.QGroupBox): app = None - def __init__(self, fixme_get_rid_of_this=None, **kwargs): - super().__init__(**kwargs) - + def __init__(self, title, parent=None): + # QtGui.QGroupBox.__init__(self, title, parent=parent) + super(OptionsGroupUI, self).__init__() self.setStyleSheet(""" QGroupBox { @@ -36,38 +16,4 @@ class OptionsGroupUI(QtWidgets.QGroupBox): """) self.layout = QtWidgets.QVBoxLayout() - self.setLayout(self.layout) - - def option_dict(self) -> Dict[str, OptionUI]: - # FIXME! - return {} - - -class OptionsGroupUI2(OptionsGroupUI): - - def __init__(self, **kwargs): - super().__init__(**kwargs) - - self.grid = QtWidgets.QGridLayout() - self.layout.addLayout(self.grid) - self.grid.setColumnStretch(0, 0) - self.grid.setColumnStretch(1, 1) - - self.options = self.build_options() - - row = 0 - for option in self.options: - row += option.add_to_grid(grid=self.grid, row=row) - - self.layout.addStretch() - - def build_options(self) -> [OptionUI]: - return [] - - def option_dict(self) -> Dict[str, OptionUI]: - result = {} - for optionui in self.options: - result[optionui.option] = optionui - return result - - + self.setLayout(self.layout) \ No newline at end of file diff --git a/flatcamGUI/preferences/PreferencesSectionUI.py b/flatcamGUI/preferences/PreferencesSectionUI.py deleted file mode 100644 index 92168377..00000000 --- a/flatcamGUI/preferences/PreferencesSectionUI.py +++ /dev/null @@ -1,42 +0,0 @@ -from typing import Dict -from PyQt5 import QtWidgets, QtCore - -from flatcamGUI.ColumnarFlowLayout import ColumnarFlowLayout -from flatcamGUI.preferences.OptionUI import OptionUI -from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI - - -class PreferencesSectionUI(QtWidgets.QWidget): - - def __init__(self, **kwargs): - super().__init__(**kwargs) - self.layout = ColumnarFlowLayout() #QtWidgets.QHBoxLayout() - self.setLayout(self.layout) - - self.groups = self.build_groups() - for group in self.groups: - group.setMinimumWidth(250) - self.layout.addWidget(group) - - - def build_groups(self) -> [OptionsGroupUI]: - return [] - - def option_dict(self) -> Dict[str, OptionUI]: - result = {} - for group in self.groups: - groupoptions = group.option_dict() - result.update(groupoptions) - return result - - def build_tab(self): - scroll_area = QtWidgets.QScrollArea() - scroll_area.setWidget(self) - scroll_area.setWidgetResizable(True) - return scroll_area - - def get_tab_id(self) -> str: - raise NotImplementedError - - def get_tab_label(self) -> str: - raise NotImplementedError diff --git a/flatcamGUI/preferences/PreferencesUIManager.py b/flatcamGUI/preferences/PreferencesUIManager.py index de4468b1..c49841ba 100644 --- a/flatcamGUI/preferences/PreferencesUIManager.py +++ b/flatcamGUI/preferences/PreferencesUIManager.py @@ -1,6 +1,4 @@ import os -from typing import Any, Dict - from PyQt5 import QtGui, QtCore, QtWidgets from PyQt5.QtCore import QSettings from defaults import FlatCAMDefaults @@ -10,8 +8,6 @@ import gettext import FlatCAMTranslation as fcTranslate import builtins -from flatcamGUI.preferences.OptionUI import OptionUI - fcTranslate.apply_language('strings') if '_' not in builtins.__dict__: _ = gettext.gettext @@ -24,6 +20,7 @@ else: log = logging.getLogger('PreferencesUIManager') + class PreferencesUIManager: def __init__(self, defaults: FlatCAMDefaults, data_path: str, ui, inform): @@ -33,7 +30,7 @@ class PreferencesUIManager: :param defaults: a dictionary storage where all the application settings are stored :param data_path: a path to the file where all the preferences are stored for persistence :param ui: reference to the FlatCAMGUI class which constructs the UI - :param inform: a pyqtSignal used to display information in the StatusBar of the GUI + :param inform: a pyqtSignal used to display information's in the StatusBar of the GUI """ self.defaults = defaults @@ -48,6 +45,298 @@ class PreferencesUIManager: # when adding entries here read the comments in the method found below named: # def new_object(self, kind, name, initialize, active=True, fit=True, plot=True) self.defaults_form_fields = { + # General App + "decimals_inch": self.ui.general_defaults_form.general_app_group.precision_inch_entry, + "decimals_metric": self.ui.general_defaults_form.general_app_group.precision_metric_entry, + "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_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, + "global_shell_at_startup": self.ui.general_defaults_form.general_app_group.shell_startup_cb, + "global_project_at_startup": self.ui.general_defaults_form.general_app_group.project_startup_cb, + "global_version_check": self.ui.general_defaults_form.general_app_group.version_check_cb, + "global_send_stats": self.ui.general_defaults_form.general_app_group.send_stats_cb, + + "global_worker_number": self.ui.general_defaults_form.general_app_group.worker_number_sb, + "global_tolerance": self.ui.general_defaults_form.general_app_group.tol_entry, + + "global_compression_level": self.ui.general_defaults_form.general_app_group.compress_spinner, + "global_save_compressed": self.ui.general_defaults_form.general_app_group.save_type_cb, + "global_autosave": self.ui.general_defaults_form.general_app_group.autosave_cb, + "global_autosave_timeout": self.ui.general_defaults_form.general_app_group.autosave_entry, + + "global_tpdf_tmargin": self.ui.general_defaults_form.general_app_group.tmargin_entry, + "global_tpdf_bmargin": self.ui.general_defaults_form.general_app_group.bmargin_entry, + "global_tpdf_lmargin": self.ui.general_defaults_form.general_app_group.lmargin_entry, + "global_tpdf_rmargin": self.ui.general_defaults_form.general_app_group.rmargin_entry, + + # General GUI Preferences + "global_theme": self.ui.general_defaults_form.general_gui_group.theme_radio, + "global_gray_icons": self.ui.general_defaults_form.general_gui_group.gray_icons_cb, + "global_layout": self.ui.general_defaults_form.general_gui_group.layout_combo, + "global_hover": self.ui.general_defaults_form.general_gui_group.hover_cb, + "global_selection_shape": self.ui.general_defaults_form.general_gui_group.selection_cb, + + "global_sel_fill": self.ui.general_defaults_form.general_gui_group.sf_color_entry, + "global_sel_line": self.ui.general_defaults_form.general_gui_group.sl_color_entry, + "global_alt_sel_fill": self.ui.general_defaults_form.general_gui_group.alt_sf_color_entry, + "global_alt_sel_line": self.ui.general_defaults_form.general_gui_group.alt_sl_color_entry, + "global_draw_color": self.ui.general_defaults_form.general_gui_group.draw_color_entry, + "global_sel_draw_color": self.ui.general_defaults_form.general_gui_group.sel_draw_color_entry, + + "global_proj_item_color": self.ui.general_defaults_form.general_gui_group.proj_color_entry, + "global_proj_item_dis_color": self.ui.general_defaults_form.general_gui_group.proj_color_dis_entry, + "global_project_autohide": self.ui.general_defaults_form.general_gui_group.project_autohide_cb, + + # General GUI Settings + "global_gridx": self.ui.general_defaults_form.general_app_set_group.gridx_entry, + "global_gridy": self.ui.general_defaults_form.general_app_set_group.gridy_entry, + "global_snap_max": self.ui.general_defaults_form.general_app_set_group.snap_max_dist_entry, + "global_workspace": self.ui.general_defaults_form.general_app_set_group.workspace_cb, + "global_workspaceT": self.ui.general_defaults_form.general_app_set_group.wk_cb, + "global_workspace_orientation": self.ui.general_defaults_form.general_app_set_group.wk_orientation_radio, + + "global_cursor_type": self.ui.general_defaults_form.general_app_set_group.cursor_radio, + "global_cursor_size": self.ui.general_defaults_form.general_app_set_group.cursor_size_entry, + "global_cursor_width": self.ui.general_defaults_form.general_app_set_group.cursor_width_entry, + "global_cursor_color_enabled": self.ui.general_defaults_form.general_app_set_group.mouse_cursor_color_cb, + "global_cursor_color": self.ui.general_defaults_form.general_app_set_group.mouse_cursor_entry, + "global_pan_button": self.ui.general_defaults_form.general_app_set_group.pan_button_radio, + "global_mselect_key": self.ui.general_defaults_form.general_app_set_group.mselect_radio, + "global_delete_confirmation": self.ui.general_defaults_form.general_app_set_group.delete_conf_cb, + "global_open_style": self.ui.general_defaults_form.general_app_set_group.open_style_cb, + "global_toggle_tooltips": self.ui.general_defaults_form.general_app_set_group.toggle_tooltips_cb, + "global_machinist_setting": self.ui.general_defaults_form.general_app_set_group.machinist_cb, + + "global_bookmarks_limit": self.ui.general_defaults_form.general_app_set_group.bm_limit_spinner, + "global_activity_icon": self.ui.general_defaults_form.general_app_set_group.activity_combo, + + # Gerber General + "gerber_plot": self.ui.gerber_defaults_form.gerber_gen_group.plot_cb, + "gerber_solid": self.ui.gerber_defaults_form.gerber_gen_group.solid_cb, + "gerber_multicolored": self.ui.gerber_defaults_form.gerber_gen_group.multicolored_cb, + "gerber_circle_steps": self.ui.gerber_defaults_form.gerber_gen_group.circle_steps_entry, + "gerber_def_units": self.ui.gerber_defaults_form.gerber_gen_group.gerber_units_radio, + "gerber_def_zeros": self.ui.gerber_defaults_form.gerber_gen_group.gerber_zeros_radio, + "gerber_clean_apertures": self.ui.gerber_defaults_form.gerber_gen_group.gerber_clean_cb, + "gerber_extra_buffering": self.ui.gerber_defaults_form.gerber_gen_group.gerber_extra_buffering, + "gerber_plot_fill": self.ui.gerber_defaults_form.gerber_gen_group.pf_color_entry, + "gerber_plot_line": self.ui.gerber_defaults_form.gerber_gen_group.pl_color_entry, + + # Gerber Options + "gerber_isotooldia": self.ui.gerber_defaults_form.gerber_opt_group.iso_tool_dia_entry, + "gerber_isopasses": self.ui.gerber_defaults_form.gerber_opt_group.iso_width_entry, + "gerber_isooverlap": self.ui.gerber_defaults_form.gerber_opt_group.iso_overlap_entry, + "gerber_combine_passes": self.ui.gerber_defaults_form.gerber_opt_group.combine_passes_cb, + "gerber_iso_scope": self.ui.gerber_defaults_form.gerber_opt_group.iso_scope_radio, + "gerber_milling_type": self.ui.gerber_defaults_form.gerber_opt_group.milling_type_radio, + "gerber_noncoppermargin": self.ui.gerber_defaults_form.gerber_opt_group.noncopper_margin_entry, + "gerber_noncopperrounded": self.ui.gerber_defaults_form.gerber_opt_group.noncopper_rounded_cb, + "gerber_bboxmargin": self.ui.gerber_defaults_form.gerber_opt_group.bbmargin_entry, + "gerber_bboxrounded": self.ui.gerber_defaults_form.gerber_opt_group.bbrounded_cb, + + # Gerber Advanced Options + "gerber_aperture_display": self.ui.gerber_defaults_form.gerber_adv_opt_group.aperture_table_visibility_cb, + # "gerber_aperture_scale_factor": self.ui.gerber_defaults_form.gerber_adv_opt_group.scale_aperture_entry, + # "gerber_aperture_buffer_factor": self.ui.gerber_defaults_form.gerber_adv_opt_group.buffer_aperture_entry, + "gerber_follow": self.ui.gerber_defaults_form.gerber_adv_opt_group.follow_cb, + "gerber_tool_type": self.ui.gerber_defaults_form.gerber_adv_opt_group.tool_type_radio, + "gerber_vtipdia": self.ui.gerber_defaults_form.gerber_adv_opt_group.tipdia_spinner, + "gerber_vtipangle": self.ui.gerber_defaults_form.gerber_adv_opt_group.tipangle_spinner, + "gerber_vcutz": self.ui.gerber_defaults_form.gerber_adv_opt_group.cutz_spinner, + "gerber_iso_type": self.ui.gerber_defaults_form.gerber_adv_opt_group.iso_type_radio, + + "gerber_buffering": self.ui.gerber_defaults_form.gerber_adv_opt_group.buffering_radio, + "gerber_simplification": self.ui.gerber_defaults_form.gerber_adv_opt_group.simplify_cb, + "gerber_simp_tolerance": self.ui.gerber_defaults_form.gerber_adv_opt_group.simplification_tol_spinner, + + # Gerber Export + "gerber_exp_units": self.ui.gerber_defaults_form.gerber_exp_group.gerber_units_radio, + "gerber_exp_integer": self.ui.gerber_defaults_form.gerber_exp_group.format_whole_entry, + "gerber_exp_decimals": self.ui.gerber_defaults_form.gerber_exp_group.format_dec_entry, + "gerber_exp_zeros": self.ui.gerber_defaults_form.gerber_exp_group.zeros_radio, + + # Gerber Editor + "gerber_editor_sel_limit": self.ui.gerber_defaults_form.gerber_editor_group.sel_limit_entry, + "gerber_editor_newcode": self.ui.gerber_defaults_form.gerber_editor_group.addcode_entry, + "gerber_editor_newsize": self.ui.gerber_defaults_form.gerber_editor_group.addsize_entry, + "gerber_editor_newtype": self.ui.gerber_defaults_form.gerber_editor_group.addtype_combo, + "gerber_editor_newdim": self.ui.gerber_defaults_form.gerber_editor_group.adddim_entry, + "gerber_editor_array_size": self.ui.gerber_defaults_form.gerber_editor_group.grb_array_size_entry, + "gerber_editor_lin_axis": self.ui.gerber_defaults_form.gerber_editor_group.grb_axis_radio, + "gerber_editor_lin_pitch": self.ui.gerber_defaults_form.gerber_editor_group.grb_pitch_entry, + "gerber_editor_lin_angle": self.ui.gerber_defaults_form.gerber_editor_group.grb_angle_entry, + "gerber_editor_circ_dir": self.ui.gerber_defaults_form.gerber_editor_group.grb_circular_dir_radio, + "gerber_editor_circ_angle": + self.ui.gerber_defaults_form.gerber_editor_group.grb_circular_angle_entry, + "gerber_editor_scale_f": self.ui.gerber_defaults_form.gerber_editor_group.grb_scale_entry, + "gerber_editor_buff_f": self.ui.gerber_defaults_form.gerber_editor_group.grb_buff_entry, + "gerber_editor_ma_low": self.ui.gerber_defaults_form.gerber_editor_group.grb_ma_low_entry, + "gerber_editor_ma_high": self.ui.gerber_defaults_form.gerber_editor_group.grb_ma_high_entry, + + # Excellon General + "excellon_plot": self.ui.excellon_defaults_form.excellon_gen_group.plot_cb, + "excellon_solid": self.ui.excellon_defaults_form.excellon_gen_group.solid_cb, + "excellon_format_upper_in": + self.ui.excellon_defaults_form.excellon_gen_group.excellon_format_upper_in_entry, + "excellon_format_lower_in": + self.ui.excellon_defaults_form.excellon_gen_group.excellon_format_lower_in_entry, + "excellon_format_upper_mm": + self.ui.excellon_defaults_form.excellon_gen_group.excellon_format_upper_mm_entry, + "excellon_format_lower_mm": + self.ui.excellon_defaults_form.excellon_gen_group.excellon_format_lower_mm_entry, + "excellon_zeros": self.ui.excellon_defaults_form.excellon_gen_group.excellon_zeros_radio, + "excellon_units": self.ui.excellon_defaults_form.excellon_gen_group.excellon_units_radio, + "excellon_update": self.ui.excellon_defaults_form.excellon_gen_group.update_excellon_cb, + "excellon_optimization_type": self.ui.excellon_defaults_form.excellon_gen_group.excellon_optimization_radio, + "excellon_search_time": self.ui.excellon_defaults_form.excellon_gen_group.optimization_time_entry, + "excellon_plot_fill": self.ui.excellon_defaults_form.excellon_gen_group.fill_color_entry, + "excellon_plot_line": self.ui.excellon_defaults_form.excellon_gen_group.line_color_entry, + + # Excellon Options + "excellon_operation": self.ui.excellon_defaults_form.excellon_opt_group.operation_radio, + "excellon_milling_type": self.ui.excellon_defaults_form.excellon_opt_group.milling_type_radio, + + "excellon_milling_dia": self.ui.excellon_defaults_form.excellon_opt_group.mill_dia_entry, + + "excellon_cutz": self.ui.excellon_defaults_form.excellon_opt_group.cutz_entry, + "excellon_multidepth": self.ui.excellon_defaults_form.excellon_opt_group.mpass_cb, + "excellon_depthperpass": self.ui.excellon_defaults_form.excellon_opt_group.maxdepth_entry, + "excellon_travelz": self.ui.excellon_defaults_form.excellon_opt_group.travelz_entry, + "excellon_endz": self.ui.excellon_defaults_form.excellon_opt_group.endz_entry, + "excellon_endxy": self.ui.excellon_defaults_form.excellon_opt_group.endxy_entry, + + "excellon_feedrate_z": self.ui.excellon_defaults_form.excellon_opt_group.feedrate_z_entry, + "excellon_spindlespeed": self.ui.excellon_defaults_form.excellon_opt_group.spindlespeed_entry, + "excellon_dwell": self.ui.excellon_defaults_form.excellon_opt_group.dwell_cb, + "excellon_dwelltime": self.ui.excellon_defaults_form.excellon_opt_group.dwelltime_entry, + "excellon_toolchange": self.ui.excellon_defaults_form.excellon_opt_group.toolchange_cb, + "excellon_toolchangez": self.ui.excellon_defaults_form.excellon_opt_group.toolchangez_entry, + "excellon_ppname_e": self.ui.excellon_defaults_form.excellon_opt_group.pp_excellon_name_cb, + "excellon_tooldia": self.ui.excellon_defaults_form.excellon_opt_group.tooldia_entry, + "excellon_slot_tooldia": self.ui.excellon_defaults_form.excellon_opt_group.slot_tooldia_entry, + "excellon_gcode_type": self.ui.excellon_defaults_form.excellon_opt_group.excellon_gcode_type_radio, + + # Excellon Advanced Options + "excellon_offset": self.ui.excellon_defaults_form.excellon_adv_opt_group.offset_entry, + "excellon_toolchangexy": self.ui.excellon_defaults_form.excellon_adv_opt_group.toolchangexy_entry, + "excellon_startz": self.ui.excellon_defaults_form.excellon_adv_opt_group.estartz_entry, + "excellon_feedrate_rapid": self.ui.excellon_defaults_form.excellon_adv_opt_group.feedrate_rapid_entry, + "excellon_z_pdepth": self.ui.excellon_defaults_form.excellon_adv_opt_group.pdepth_entry, + "excellon_feedrate_probe": self.ui.excellon_defaults_form.excellon_adv_opt_group.feedrate_probe_entry, + "excellon_spindledir": self.ui.excellon_defaults_form.excellon_adv_opt_group.spindledir_radio, + "excellon_f_plunge": self.ui.excellon_defaults_form.excellon_adv_opt_group.fplunge_cb, + "excellon_f_retract": self.ui.excellon_defaults_form.excellon_adv_opt_group.fretract_cb, + + # Excellon Export + "excellon_exp_units": self.ui.excellon_defaults_form.excellon_exp_group.excellon_units_radio, + "excellon_exp_format": self.ui.excellon_defaults_form.excellon_exp_group.format_radio, + "excellon_exp_integer": self.ui.excellon_defaults_form.excellon_exp_group.format_whole_entry, + "excellon_exp_decimals": self.ui.excellon_defaults_form.excellon_exp_group.format_dec_entry, + "excellon_exp_zeros": self.ui.excellon_defaults_form.excellon_exp_group.zeros_radio, + "excellon_exp_slot_type": self.ui.excellon_defaults_form.excellon_exp_group.slot_type_radio, + + # Excellon Editor + "excellon_editor_sel_limit": self.ui.excellon_defaults_form.excellon_editor_group.sel_limit_entry, + "excellon_editor_newdia": self.ui.excellon_defaults_form.excellon_editor_group.addtool_entry, + "excellon_editor_array_size": self.ui.excellon_defaults_form.excellon_editor_group.drill_array_size_entry, + "excellon_editor_lin_dir": self.ui.excellon_defaults_form.excellon_editor_group.drill_axis_radio, + "excellon_editor_lin_pitch": self.ui.excellon_defaults_form.excellon_editor_group.drill_pitch_entry, + "excellon_editor_lin_angle": self.ui.excellon_defaults_form.excellon_editor_group.drill_angle_entry, + "excellon_editor_circ_dir": self.ui.excellon_defaults_form.excellon_editor_group.drill_circular_dir_radio, + "excellon_editor_circ_angle": + self.ui.excellon_defaults_form.excellon_editor_group.drill_circular_angle_entry, + # Excellon Slots + "excellon_editor_slot_direction": + self.ui.excellon_defaults_form.excellon_editor_group.slot_axis_radio, + "excellon_editor_slot_angle": + self.ui.excellon_defaults_form.excellon_editor_group.slot_angle_spinner, + "excellon_editor_slot_length": + self.ui.excellon_defaults_form.excellon_editor_group.slot_length_entry, + # Excellon Slots + "excellon_editor_slot_array_size": + self.ui.excellon_defaults_form.excellon_editor_group.slot_array_size_entry, + "excellon_editor_slot_lin_dir": self.ui.excellon_defaults_form.excellon_editor_group.slot_array_axis_radio, + "excellon_editor_slot_lin_pitch": + self.ui.excellon_defaults_form.excellon_editor_group.slot_array_pitch_entry, + "excellon_editor_slot_lin_angle": + self.ui.excellon_defaults_form.excellon_editor_group.slot_array_angle_entry, + "excellon_editor_slot_circ_dir": + self.ui.excellon_defaults_form.excellon_editor_group.slot_array_circular_dir_radio, + "excellon_editor_slot_circ_angle": + self.ui.excellon_defaults_form.excellon_editor_group.slot_array_circular_angle_entry, + + # Geometry General + "geometry_plot": self.ui.geometry_defaults_form.geometry_gen_group.plot_cb, + "geometry_circle_steps": self.ui.geometry_defaults_form.geometry_gen_group.circle_steps_entry, + "geometry_cnctooldia": self.ui.geometry_defaults_form.geometry_gen_group.cnctooldia_entry, + "geometry_plot_line": self.ui.geometry_defaults_form.geometry_gen_group.line_color_entry, + + # Geometry Options + "geometry_cutz": self.ui.geometry_defaults_form.geometry_opt_group.cutz_entry, + "geometry_travelz": self.ui.geometry_defaults_form.geometry_opt_group.travelz_entry, + "geometry_feedrate": self.ui.geometry_defaults_form.geometry_opt_group.cncfeedrate_entry, + "geometry_feedrate_z": self.ui.geometry_defaults_form.geometry_opt_group.feedrate_z_entry, + "geometry_spindlespeed": self.ui.geometry_defaults_form.geometry_opt_group.cncspindlespeed_entry, + "geometry_dwell": self.ui.geometry_defaults_form.geometry_opt_group.dwell_cb, + "geometry_dwelltime": self.ui.geometry_defaults_form.geometry_opt_group.dwelltime_entry, + "geometry_ppname_g": self.ui.geometry_defaults_form.geometry_opt_group.pp_geometry_name_cb, + "geometry_toolchange": self.ui.geometry_defaults_form.geometry_opt_group.toolchange_cb, + "geometry_toolchangez": self.ui.geometry_defaults_form.geometry_opt_group.toolchangez_entry, + "geometry_endz": self.ui.geometry_defaults_form.geometry_opt_group.endz_entry, + "geometry_endxy": self.ui.geometry_defaults_form.geometry_opt_group.endxy_entry, + "geometry_depthperpass": self.ui.geometry_defaults_form.geometry_opt_group.depthperpass_entry, + "geometry_multidepth": self.ui.geometry_defaults_form.geometry_opt_group.multidepth_cb, + + # Geometry Advanced Options + "geometry_toolchangexy": self.ui.geometry_defaults_form.geometry_adv_opt_group.toolchangexy_entry, + "geometry_startz": self.ui.geometry_defaults_form.geometry_adv_opt_group.gstartz_entry, + "geometry_feedrate_rapid": self.ui.geometry_defaults_form.geometry_adv_opt_group.feedrate_rapid_entry, + "geometry_extracut": self.ui.geometry_defaults_form.geometry_adv_opt_group.extracut_cb, + "geometry_extracut_length": self.ui.geometry_defaults_form.geometry_adv_opt_group.e_cut_entry, + "geometry_z_pdepth": self.ui.geometry_defaults_form.geometry_adv_opt_group.pdepth_entry, + "geometry_feedrate_probe": self.ui.geometry_defaults_form.geometry_adv_opt_group.feedrate_probe_entry, + "geometry_spindledir": self.ui.geometry_defaults_form.geometry_adv_opt_group.spindledir_radio, + "geometry_f_plunge": self.ui.geometry_defaults_form.geometry_adv_opt_group.fplunge_cb, + "geometry_segx": self.ui.geometry_defaults_form.geometry_adv_opt_group.segx_entry, + "geometry_segy": self.ui.geometry_defaults_form.geometry_adv_opt_group.segy_entry, + "geometry_area_exclusion": self.ui.geometry_defaults_form.geometry_adv_opt_group.exclusion_cb, + "geometry_area_shape": self.ui.geometry_defaults_form.geometry_adv_opt_group.area_shape_radio, + "geometry_area_strategy": self.ui.geometry_defaults_form.geometry_adv_opt_group.strategy_radio, + "geometry_area_overz": self.ui.geometry_defaults_form.geometry_adv_opt_group.over_z_entry, + + # Geometry Editor + "geometry_editor_sel_limit": self.ui.geometry_defaults_form.geometry_editor_group.sel_limit_entry, + "geometry_editor_milling_type": self.ui.geometry_defaults_form.geometry_editor_group.milling_type_radio, + + # CNCJob General + "cncjob_plot": self.ui.cncjob_defaults_form.cncjob_gen_group.plot_cb, + "cncjob_plot_kind": self.ui.cncjob_defaults_form.cncjob_gen_group.cncplot_method_radio, + "cncjob_annotation": self.ui.cncjob_defaults_form.cncjob_gen_group.annotation_cb, + + "cncjob_tooldia": self.ui.cncjob_defaults_form.cncjob_gen_group.tooldia_entry, + "cncjob_coords_type": self.ui.cncjob_defaults_form.cncjob_gen_group.coords_type_radio, + "cncjob_coords_decimals": self.ui.cncjob_defaults_form.cncjob_gen_group.coords_dec_entry, + "cncjob_fr_decimals": self.ui.cncjob_defaults_form.cncjob_gen_group.fr_dec_entry, + "cncjob_steps_per_circle": self.ui.cncjob_defaults_form.cncjob_gen_group.steps_per_circle_entry, + "cncjob_line_ending": self.ui.cncjob_defaults_form.cncjob_gen_group.line_ending_cb, + "cncjob_plot_line": self.ui.cncjob_defaults_form.cncjob_gen_group.line_color_entry, + "cncjob_plot_fill": self.ui.cncjob_defaults_form.cncjob_gen_group.fill_color_entry, + "cncjob_travel_line": self.ui.cncjob_defaults_form.cncjob_gen_group.tline_color_entry, + "cncjob_travel_fill": self.ui.cncjob_defaults_form.cncjob_gen_group.tfill_color_entry, + + # CNC Job Options + "cncjob_prepend": self.ui.cncjob_defaults_form.cncjob_opt_group.prepend_text, + "cncjob_append": self.ui.cncjob_defaults_form.cncjob_opt_group.append_text, + + # CNC Job Advanced Options + "cncjob_toolchange_macro": self.ui.cncjob_defaults_form.cncjob_adv_opt_group.toolchange_text, + "cncjob_toolchange_macro_enable": self.ui.cncjob_defaults_form.cncjob_adv_opt_group.toolchange_cb, + "cncjob_annotation_fontsize": self.ui.cncjob_defaults_form.cncjob_adv_opt_group.annotation_fontsize_sp, + "cncjob_annotation_fontcolor": self.ui.cncjob_defaults_form.cncjob_adv_opt_group.annotation_fontcolor_entry, # NCC Tool "tools_ncctools": self.ui.tools_defaults_form.tools_ncc_group.ncc_tool_dia_entry, @@ -298,49 +587,17 @@ class PreferencesUIManager: } - self.sections = [ - ui.general_defaults_form, - ui.gerber_defaults_form, - ui.excellon_defaults_form, - ui.geometry_defaults_form, - ui.cncjob_defaults_form, - ui.tools_defaults_form, - ui.tools2_defaults_form, - ui.util_defaults_form - ] - - def get_form_fields(self) -> Dict[str, Any]: - result = {} - result.update(self.defaults_form_fields) - result.update(self._option_field_dict()) - return result - - def get_form_field(self, option: str) -> Any: - return self.get_form_fields()[option] - - def option_dict(self) -> Dict[str, OptionUI]: - result = {} - for section in self.sections: - sectionoptions = section.option_dict() - result.update(sectionoptions) - return result - - def _option_field_dict(self): - result = {k: v.get_field() for k, v in self.option_dict().items()} - return result - def defaults_read_form(self): """ Will read all the values in the Preferences GUI and update the defaults dictionary. :return: None """ - for option in self.get_form_fields(): - if option in self.defaults: - try: - self.defaults[option] = self.get_form_field(option=option).get_value() - except Exception as e: - log.debug("App.defaults_read_form() --> %s" % str(e)) + for option in self.defaults_form_fields: + try: + self.defaults[option] = self.defaults_form_fields[option].get_value() + except Exception as e: + log.debug("App.defaults_read_form() --> %s" % str(e)) def defaults_write_form(self, factor=None, fl_units=None, source_dict=None): """ @@ -380,7 +637,7 @@ class PreferencesUIManager: if factor is not None: value *= factor - form_field = self.get_form_field(option=field) + form_field = self.defaults_form_fields[field] if units is None: form_field.set_value(value) elif (units == 'IN' or units == 'MM') and (field == 'global_gridx' or field == 'global_gridy'): @@ -397,12 +654,70 @@ class PreferencesUIManager: :return: None """ - # FIXME this should be done in __init__ - for section in self.sections: - tab = section.build_tab() - tab.setObjectName(section.get_tab_id()) - self.ui.pref_tab_area.addTab(tab, section.get_tab_label()) + gen_form = self.ui.general_defaults_form + try: + self.ui.general_scroll_area.takeWidget() + except Exception: + log.debug("Nothing to remove") + self.ui.general_scroll_area.setWidget(gen_form) + gen_form.show() + + ger_form = self.ui.gerber_defaults_form + try: + self.ui.gerber_scroll_area.takeWidget() + except Exception: + log.debug("Nothing to remove") + self.ui.gerber_scroll_area.setWidget(ger_form) + ger_form.show() + + exc_form = self.ui.excellon_defaults_form + try: + self.ui.excellon_scroll_area.takeWidget() + except Exception: + log.debug("Nothing to remove") + self.ui.excellon_scroll_area.setWidget(exc_form) + exc_form.show() + + geo_form = self.ui.geometry_defaults_form + try: + self.ui.geometry_scroll_area.takeWidget() + except Exception: + log.debug("Nothing to remove") + self.ui.geometry_scroll_area.setWidget(geo_form) + geo_form.show() + + cnc_form = self.ui.cncjob_defaults_form + try: + self.ui.cncjob_scroll_area.takeWidget() + except Exception: + log.debug("Nothing to remove") + self.ui.cncjob_scroll_area.setWidget(cnc_form) + cnc_form.show() + + tools_form = self.ui.tools_defaults_form + try: + self.ui.tools_scroll_area.takeWidget() + except Exception: + log.debug("Nothing to remove") + self.ui.tools_scroll_area.setWidget(tools_form) + tools_form.show() + + tools2_form = self.ui.tools2_defaults_form + try: + self.ui.tools2_scroll_area.takeWidget() + except Exception: + log.debug("Nothing to remove") + self.ui.tools2_scroll_area.setWidget(tools2_form) + tools2_form.show() + + fa_form = self.ui.util_defaults_form + try: + self.ui.fa_scroll_area.takeWidget() + except Exception: + log.debug("Nothing to remove") + self.ui.fa_scroll_area.setWidget(fa_form) + fa_form.show() # Initialize the color box's color in Preferences -> Global -> Colo self.__init_color_pickers() @@ -416,6 +731,148 @@ class PreferencesUIManager: log.debug("Finished Preferences GUI form initialization.") def __init_color_pickers(self): + # Init Gerber Plot Colors + self.ui.gerber_defaults_form.gerber_gen_group.pf_color_entry.set_value(self.defaults['gerber_plot_fill']) + self.ui.gerber_defaults_form.gerber_gen_group.pf_color_button.setStyleSheet( + "background-color:%s;" + "border-color: dimgray" % str(self.defaults['gerber_plot_fill'])[:7]) + self.ui.gerber_defaults_form.gerber_gen_group.pf_color_alpha_spinner.set_value( + int(self.defaults['gerber_plot_fill'][7:9], 16)) + self.ui.gerber_defaults_form.gerber_gen_group.pf_color_alpha_slider.setValue( + int(self.defaults['gerber_plot_fill'][7:9], 16)) + + self.ui.gerber_defaults_form.gerber_gen_group.pl_color_entry.set_value(self.defaults['gerber_plot_line']) + self.ui.gerber_defaults_form.gerber_gen_group.pl_color_button.setStyleSheet( + "background-color:%s;" + "border-color: dimgray" % str(self.defaults['gerber_plot_line'])[:7]) + + # Init Excellon Plot Colors + self.ui.excellon_defaults_form.excellon_gen_group.fill_color_entry.set_value( + self.defaults['excellon_plot_fill']) + self.ui.excellon_defaults_form.excellon_gen_group.fill_color_button.setStyleSheet( + "background-color:%s;" + "border-color: dimgray" % str(self.defaults['excellon_plot_fill'])[:7]) + self.ui.excellon_defaults_form.excellon_gen_group.color_alpha_spinner.set_value( + int(self.defaults['excellon_plot_fill'][7:9], 16)) + self.ui.excellon_defaults_form.excellon_gen_group.color_alpha_slider.setValue( + int(self.defaults['excellon_plot_fill'][7:9], 16)) + + self.ui.excellon_defaults_form.excellon_gen_group.line_color_entry.set_value( + self.defaults['excellon_plot_line']) + self.ui.excellon_defaults_form.excellon_gen_group.line_color_button.setStyleSheet( + "background-color:%s;" + "border-color: dimgray" % str(self.defaults['excellon_plot_line'])[:7]) + + # Init Geometry Plot Colors + self.ui.geometry_defaults_form.geometry_gen_group.line_color_entry.set_value( + self.defaults['geometry_plot_line']) + self.ui.geometry_defaults_form.geometry_gen_group.line_color_button.setStyleSheet( + "background-color:%s;" + "border-color: dimgray" % str(self.defaults['geometry_plot_line'])[:7]) + + # Init CNCJob Travel Line Colors + self.ui.cncjob_defaults_form.cncjob_gen_group.tfill_color_entry.set_value( + self.defaults['cncjob_travel_fill']) + self.ui.cncjob_defaults_form.cncjob_gen_group.tfill_color_button.setStyleSheet( + "background-color:%s;" + "border-color: dimgray" % str(self.defaults['cncjob_travel_fill'])[:7]) + self.ui.cncjob_defaults_form.cncjob_gen_group.tcolor_alpha_spinner.set_value( + int(self.defaults['cncjob_travel_fill'][7:9], 16)) + self.ui.cncjob_defaults_form.cncjob_gen_group.tcolor_alpha_slider.setValue( + int(self.defaults['cncjob_travel_fill'][7:9], 16)) + + self.ui.cncjob_defaults_form.cncjob_gen_group.tline_color_entry.set_value( + self.defaults['cncjob_travel_line']) + self.ui.cncjob_defaults_form.cncjob_gen_group.tline_color_button.setStyleSheet( + "background-color:%s;" + "border-color: dimgray" % str(self.defaults['cncjob_travel_line'])[:7]) + + # Init CNCJob Plot Colors + self.ui.cncjob_defaults_form.cncjob_gen_group.fill_color_entry.set_value( + self.defaults['cncjob_plot_fill']) + self.ui.cncjob_defaults_form.cncjob_gen_group.fill_color_button.setStyleSheet( + "background-color:%s;" + "border-color: dimgray" % str(self.defaults['cncjob_plot_fill'])[:7]) + + self.ui.cncjob_defaults_form.cncjob_gen_group.line_color_entry.set_value( + self.defaults['cncjob_plot_line']) + self.ui.cncjob_defaults_form.cncjob_gen_group.line_color_button.setStyleSheet( + "background-color:%s;" + "border-color: dimgray" % str(self.defaults['cncjob_plot_line'])[:7]) + + # Init Left-Right Selection colors + self.ui.general_defaults_form.general_gui_group.sf_color_entry.set_value(self.defaults['global_sel_fill']) + self.ui.general_defaults_form.general_gui_group.sf_color_button.setStyleSheet( + "background-color:%s;" + "border-color: dimgray" % str(self.defaults['global_sel_fill'])[:7]) + self.ui.general_defaults_form.general_gui_group.sf_color_alpha_spinner.set_value( + int(self.defaults['global_sel_fill'][7:9], 16)) + self.ui.general_defaults_form.general_gui_group.sf_color_alpha_slider.setValue( + int(self.defaults['global_sel_fill'][7:9], 16)) + + self.ui.general_defaults_form.general_gui_group.sl_color_entry.set_value(self.defaults['global_sel_line']) + self.ui.general_defaults_form.general_gui_group.sl_color_button.setStyleSheet( + "background-color:%s;" + "border-color: dimgray" % str(self.defaults['global_sel_line'])[:7]) + + # Init Right-Left Selection colors + self.ui.general_defaults_form.general_gui_group.alt_sf_color_entry.set_value( + self.defaults['global_alt_sel_fill']) + self.ui.general_defaults_form.general_gui_group.alt_sf_color_button.setStyleSheet( + "background-color:%s;" + "border-color: dimgray" % str(self.defaults['global_alt_sel_fill'])[:7]) + self.ui.general_defaults_form.general_gui_group.alt_sf_color_alpha_spinner.set_value( + int(self.defaults['global_sel_fill'][7:9], 16)) + self.ui.general_defaults_form.general_gui_group.alt_sf_color_alpha_slider.setValue( + int(self.defaults['global_sel_fill'][7:9], 16)) + + self.ui.general_defaults_form.general_gui_group.alt_sl_color_entry.set_value( + self.defaults['global_alt_sel_line']) + self.ui.general_defaults_form.general_gui_group.alt_sl_color_button.setStyleSheet( + "background-color:%s;" + "border-color: dimgray" % str(self.defaults['global_alt_sel_line'])[:7]) + + # Init Draw color and Selection Draw Color + self.ui.general_defaults_form.general_gui_group.draw_color_entry.set_value( + self.defaults['global_draw_color']) + self.ui.general_defaults_form.general_gui_group.draw_color_button.setStyleSheet( + "background-color:%s;" + "border-color: dimgray" % str(self.defaults['global_draw_color'])[:7]) + + self.ui.general_defaults_form.general_gui_group.sel_draw_color_entry.set_value( + self.defaults['global_sel_draw_color']) + self.ui.general_defaults_form.general_gui_group.sel_draw_color_button.setStyleSheet( + "background-color:%s;" + "border-color: dimgray" % str(self.defaults['global_sel_draw_color'])[:7]) + + # Init Project Items color + self.ui.general_defaults_form.general_gui_group.proj_color_entry.set_value( + self.defaults['global_proj_item_color']) + self.ui.general_defaults_form.general_gui_group.proj_color_button.setStyleSheet( + "background-color:%s;" + "border-color: dimgray" % str(self.defaults['global_proj_item_color'])[:7]) + + # Init Project Disabled Items color + self.ui.general_defaults_form.general_gui_group.proj_color_dis_entry.set_value( + self.defaults['global_proj_item_dis_color']) + self.ui.general_defaults_form.general_gui_group.proj_color_dis_button.setStyleSheet( + "background-color:%s;" + "border-color: dimgray" % str(self.defaults['global_proj_item_dis_color'])[:7]) + + # Init Project Disabled Items color + self.ui.general_defaults_form.general_app_set_group.mouse_cursor_entry.set_value( + self.defaults['global_cursor_color']) + self.ui.general_defaults_form.general_app_set_group.mouse_cursor_button.setStyleSheet( + "background-color:%s;" + "border-color: dimgray" % str(self.defaults['global_cursor_color'])[:7]) + + # Init the Annotation CNC Job color + self.ui.cncjob_defaults_form.cncjob_adv_opt_group.annotation_fontcolor_entry.set_value( + self.defaults['cncjob_annotation_fontcolor']) + self.ui.cncjob_defaults_form.cncjob_adv_opt_group.annotation_fontcolor_button.setStyleSheet( + "background-color:%s;" + "border-color: dimgray" % str(self.defaults['cncjob_annotation_fontcolor'])[:7]) + # Init the Tool Film color self.ui.tools_defaults_form.tools_film_group.film_color_entry.set_value( self.defaults['tools_film_color']) @@ -464,8 +921,7 @@ class PreferencesUIManager: theme = 'white' should_restart = False - - val = self.get_form_field("global_theme").get_value() + val = self.ui.general_defaults_form.general_gui_group.theme_radio.get_value() if val != theme: msgbox = QtWidgets.QMessageBox() msgbox.setText(_("Are you sure you want to continue?")) @@ -500,20 +956,20 @@ class PreferencesUIManager: settgs = QSettings("Open Source", "FlatCAM") # save the notebook font size - fsize = self.get_form_field("notebook_font_size").get_value() + fsize = self.ui.general_defaults_form.general_app_set_group.notebook_font_size_spinner.get_value() settgs.setValue('notebook_font_size', fsize) # save the axis font size - g_fsize = self.get_form_field("axis_font_size").get_value() + g_fsize = self.ui.general_defaults_form.general_app_set_group.axis_font_size_spinner.get_value() settgs.setValue('axis_font_size', g_fsize) # save the textbox font size - tb_fsize = self.get_form_field("textbox_font_size").get_value() + tb_fsize = self.ui.general_defaults_form.general_app_set_group.textbox_font_size_spinner.get_value() settgs.setValue('textbox_font_size', tb_fsize) settgs.setValue( 'machinist', - 1 if self.get_form_field("global_machinist_setting").get_value() else 0 + 1 if self.ui.general_defaults_form.general_app_set_group.machinist_cb.get_value() else 0 ) # This will write the setting to the platform specific storage. @@ -536,11 +992,11 @@ class PreferencesUIManager: self.ignore_tab_close_event = True try: - self.get_form_field("units").activated_custom.disconnect() + self.ui.general_defaults_form.general_app_group.units_radio.activated_custom.disconnect() except (TypeError, AttributeError): pass self.defaults_write_form(source_dict=self.defaults.current_defaults) - self.get_form_field("units").activated_custom.connect( + self.ui.general_defaults_form.general_app_group.units_radio.activated_custom.connect( lambda: self.ui.app.on_toggle_units(no_pref=False)) self.defaults.update(self.defaults.current_defaults) diff --git a/flatcamGUI/preferences/cncjob/CNCJobAdvOptPrefGroupUI.py b/flatcamGUI/preferences/cncjob/CNCJobAdvOptPrefGroupUI.py index 5422e297..8d7a1cf0 100644 --- a/flatcamGUI/preferences/cncjob/CNCJobAdvOptPrefGroupUI.py +++ b/flatcamGUI/preferences/cncjob/CNCJobAdvOptPrefGroupUI.py @@ -1,7 +1,8 @@ -from PyQt5.QtCore import Qt +from PyQt5 import QtWidgets, QtGui, QtCore +from PyQt5.QtCore import QSettings, Qt -from flatcamGUI.preferences.OptionUI import * -from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI2 +from flatcamGUI.GUIElements import FCTextArea, FCCheckBox, FCComboBox, FCSpinner, FCEntry +from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI import gettext import FlatCAMTranslation as fcTranslate import builtins @@ -10,18 +11,93 @@ fcTranslate.apply_language('strings') if '_' not in builtins.__dict__: _ = gettext.gettext +settings = QSettings("Open Source", "FlatCAM") +if settings.contains("machinist"): + machinist_setting = settings.value('machinist', type=int) +else: + machinist_setting = 0 -class CNCJobAdvOptPrefGroupUI(OptionsGroupUI2): - def __init__(self, decimals=4, **kwargs): +class CNCJobAdvOptPrefGroupUI(OptionsGroupUI): + def __init__(self, decimals=4, parent=None): + # OptionsGroupUI.__init__(self, "CNC Job Advanced Options Preferences", parent=None) + super(CNCJobAdvOptPrefGroupUI, self).__init__(self, parent=parent) self.decimals = decimals - super().__init__(**kwargs) + self.setTitle(str(_("CNC Job Adv. Options"))) - self.toolchange_text = self.option_dict()["cncjob_toolchange_macro"].get_field() + # ## Export G-Code + self.export_gcode_label = QtWidgets.QLabel("%s:" % _("Export CNC Code")) + self.export_gcode_label.setToolTip( + _("Export and save G-Code to\n" + "make this object to a file.") + ) + self.layout.addWidget(self.export_gcode_label) + + # Prepend to G-Code + toolchangelabel = QtWidgets.QLabel('%s' % _('Toolchange G-Code')) + toolchangelabel.setToolTip( + _( + "Type here any G-Code commands you would\n" + "like to be executed when Toolchange event is encountered.\n" + "This will constitute a Custom Toolchange GCode,\n" + "or a Toolchange Macro.\n" + "The FlatCAM variables are surrounded by '%' symbol.\n\n" + "WARNING: it can be used only with a preprocessor file\n" + "that has 'toolchange_custom' in it's name and this is built\n" + "having as template the 'Toolchange Custom' posprocessor file." + ) + ) + self.layout.addWidget(toolchangelabel) + + qsettings = QSettings("Open Source", "FlatCAM") + if qsettings.contains("textbox_font_size"): + tb_fsize = qsettings.value('textbox_font_size', type=int) + else: + tb_fsize = 10 + font = QtGui.QFont() + font.setPointSize(tb_fsize) + + self.toolchange_text = FCTextArea() + self.toolchange_text.setPlaceholderText( + _( + "Type here any G-Code commands you would " + "like to be executed when Toolchange event is encountered.\n" + "This will constitute a Custom Toolchange GCode, " + "or a Toolchange Macro.\n" + "The FlatCAM variables are surrounded by '%' symbol.\n" + "WARNING: it can be used only with a preprocessor file " + "that has 'toolchange_custom' in it's name." + ) + ) + self.layout.addWidget(self.toolchange_text) + self.toolchange_text.setFont(font) + + hlay = QtWidgets.QHBoxLayout() + self.layout.addLayout(hlay) + + # Toolchange Replacement GCode + self.toolchange_cb = FCCheckBox(label='%s' % _('Use Toolchange Macro')) + self.toolchange_cb.setToolTip( + _("Check this box if you want to use\n" + "a Custom Toolchange GCode (macro).") + ) + hlay.addWidget(self.toolchange_cb) + hlay.addStretch() + + hlay1 = QtWidgets.QHBoxLayout() + self.layout.addLayout(hlay1) + + # Variable list + self.tc_variable_combo = FCComboBox() + self.tc_variable_combo.setToolTip( + _("A list of the FlatCAM variables that can be used\n" + "in the Toolchange event.\n" + "They have to be surrounded by the '%' symbol") + ) + hlay1.addWidget(self.tc_variable_combo) # Populate the Combo Box - self.tc_variable_combo = self.option_dict()["__toolchange_variable"].get_field() variables = [_('Parameters'), 'tool', 'tooldia', 't_drills', 'x_toolchange', 'y_toolchange', 'z_toolchange', 'z_cut', 'z_move', 'z_depthpercut', 'spindlespeed', 'dwelltime'] self.tc_variable_combo.addItems(variables) @@ -50,58 +126,83 @@ class CNCJobAdvOptPrefGroupUI(OptionsGroupUI2): _("dwelltime = time to dwell to allow the spindle to reach it's set RPM"), Qt.ToolTipRole) + # hlay1.addStretch() + + # Insert Variable into the Toolchange G-Code Text Box + # self.tc_insert_buton = FCButton("Insert") + # self.tc_insert_buton.setToolTip( + # "Insert the variable in the GCode Box\n" + # "surrounded by the '%' symbol." + # ) + # hlay1.addWidget(self.tc_insert_buton) + + grid0 = QtWidgets.QGridLayout() + self.layout.addLayout(grid0) + + grid0.addWidget(QtWidgets.QLabel(''), 1, 0, 1, 2) + + # Annotation Font Size + self.annotation_fontsize_label = QtWidgets.QLabel('%s:' % _("Annotation Size")) + self.annotation_fontsize_label.setToolTip( + _("The font size of the annotation text. In pixels.") + ) + grid0.addWidget(self.annotation_fontsize_label, 2, 0) + self.annotation_fontsize_sp = FCSpinner() + self.annotation_fontsize_sp.set_range(0, 9999) + + grid0.addWidget(self.annotation_fontsize_sp, 2, 1) + grid0.addWidget(QtWidgets.QLabel(''), 2, 2) + + # Annotation Font Color + self.annotation_color_label = QtWidgets.QLabel('%s:' % _('Annotation Color')) + self.annotation_color_label.setToolTip( + _("Set the font color for the annotation texts.") + ) + self.annotation_fontcolor_entry = FCEntry() + self.annotation_fontcolor_button = QtWidgets.QPushButton() + self.annotation_fontcolor_button.setFixedSize(15, 15) + + self.form_box_child = QtWidgets.QHBoxLayout() + self.form_box_child.setContentsMargins(0, 0, 0, 0) + self.form_box_child.addWidget(self.annotation_fontcolor_entry) + self.form_box_child.addWidget(self.annotation_fontcolor_button, alignment=Qt.AlignRight) + self.form_box_child.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter) + + color_widget = QtWidgets.QWidget() + color_widget.setLayout(self.form_box_child) + grid0.addWidget(self.annotation_color_label, 3, 0) + grid0.addWidget(color_widget, 3, 1) + grid0.addWidget(QtWidgets.QLabel(''), 3, 2) + + self.layout.addStretch() + self.tc_variable_combo.currentIndexChanged[str].connect(self.on_cnc_custom_parameters) - def build_options(self) -> [OptionUI]: - return [ - HeadingOptionUI( - label_text="Export CNC Code", - label_tooltip="Export and save G-Code to\n" - "make this object to a file." - ), - CheckboxOptionUI( - option="cncjob_toolchange_macro_enable", - label_text="Use Toolchange Macro", - label_tooltip="Check this box if you want to use\n" - "a Custom Toolchange GCode (macro)." - ), - TextAreaOptionUI( - option="cncjob_toolchange_macro", - label_text="Toolchange G-Code", - label_tooltip="Type here any G-Code commands you would " - "like to be executed when Toolchange event is encountered.\n" - "This will constitute a Custom Toolchange GCode, " - "or a Toolchange Macro.\n" - "The FlatCAM variables are surrounded by '%' symbol.\n" - "WARNING: it can be used only with a preprocessor file " - "that has 'toolchange_custom' in it's name." - ), - ComboboxOptionUI( - option="__toolchange_variable", - label_text="Insert variable", - label_tooltip="A list of the FlatCAM variables that can be used\n" - "in the Toolchange event.\n" - "They have to be surrounded by the '%' symbol", - choices=[] # see init. - ), - - SpinnerOptionUI( - option="cncjob_annotation_fontsize", - label_text="Annotation Size", - label_tooltip="The font size of the annotation text. In pixels.", - min_value=1, max_value=9999, step=1 - ), - ColorOptionUI( - option="cncjob_annotation_fontcolor", - label_text="Annotation Color", - label_tooltip="Set the font color for the annotation texts." - ) - ] + self.annotation_fontcolor_entry.editingFinished.connect(self.on_annotation_fontcolor_entry) + self.annotation_fontcolor_button.clicked.connect(self.on_annotation_fontcolor_button) def on_cnc_custom_parameters(self, signal_text): - if signal_text == _("Parameters"): + if signal_text == 'Parameters': return else: self.toolchange_text.insertPlainText('%%%s%%' % signal_text) - self.tc_variable_combo.set_value(_("Parameters")) + def on_annotation_fontcolor_entry(self): + self.app.defaults['cncjob_annotation_fontcolor'] = self.annotation_fontcolor_entry.get_value() + self.annotation_fontcolor_button.setStyleSheet( + "background-color:%s" % str(self.app.defaults['cncjob_annotation_fontcolor'])) + + def on_annotation_fontcolor_button(self): + current_color = QtGui.QColor(self.app.defaults['cncjob_annotation_fontcolor']) + + c_dialog = QtWidgets.QColorDialog() + annotation_color = c_dialog.getColor(initial=current_color) + + if annotation_color.isValid() is False: + return + + self.annotation_fontcolor_button.setStyleSheet("background-color:%s" % str(annotation_color.name())) + + new_val_sel = str(annotation_color.name()) + self.annotation_fontcolor_entry.set_value(new_val_sel) + self.app.defaults['cncjob_annotation_fontcolor'] = new_val_sel diff --git a/flatcamGUI/preferences/cncjob/CNCJobGenPrefGroupUI.py b/flatcamGUI/preferences/cncjob/CNCJobGenPrefGroupUI.py index e999fb6e..66276e23 100644 --- a/flatcamGUI/preferences/cncjob/CNCJobGenPrefGroupUI.py +++ b/flatcamGUI/preferences/cncjob/CNCJobGenPrefGroupUI.py @@ -1,142 +1,389 @@ -from flatcamGUI.preferences.OptionUI import * -from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI2 +from PyQt5 import QtWidgets, QtCore, QtGui +from PyQt5.QtCore import QSettings +from flatcamGUI.GUIElements import FCCheckBox, RadioSet, FCSpinner, FCDoubleSpinner, FCEntry +from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI import gettext import FlatCAMTranslation as fcTranslate import builtins + fcTranslate.apply_language('strings') if '_' not in builtins.__dict__: _ = gettext.gettext +settings = QSettings("Open Source", "FlatCAM") +if settings.contains("machinist"): + machinist_setting = settings.value('machinist', type=int) +else: + machinist_setting = 0 -class CNCJobGenPrefGroupUI(OptionsGroupUI2): - def __init__(self, decimals=4, **kwargs): - self.decimals = decimals - super().__init__(**kwargs) +class CNCJobGenPrefGroupUI(OptionsGroupUI): + def __init__(self, decimals=4, parent=None): + # OptionsGroupUI.__init__(self, "CNC Job General Preferences", parent=None) + super(CNCJobGenPrefGroupUI, self).__init__(self, parent=parent) + self.setTitle(str(_("CNC Job General"))) + self.decimals = decimals + + # ## Plot options + self.plot_options_label = QtWidgets.QLabel("%s:" % _("Plot Options")) + self.layout.addWidget(self.plot_options_label) + + grid0 = QtWidgets.QGridLayout() + self.layout.addLayout(grid0) + grid0.setColumnStretch(0, 0) + grid0.setColumnStretch(1, 1) + + # Plot CB + # self.plot_cb = QtWidgets.QCheckBox('Plot') + self.plot_cb = FCCheckBox(_('Plot Object')) + self.plot_cb.setToolTip(_("Plot (show) this object.")) + grid0.addWidget(self.plot_cb, 0, 0, 1, 2) + + # Plot Kind + self.cncplot_method_label = QtWidgets.QLabel('%s:' % _("Plot kind")) + self.cncplot_method_label.setToolTip( + _("This selects the kind of geometries on the canvas to plot.\n" + "Those can be either of type 'Travel' which means the moves\n" + "above the work piece or it can be of type 'Cut',\n" + "which means the moves that cut into the material.") + ) + + self.cncplot_method_radio = RadioSet([ + {"label": _("All"), "value": "all"}, + {"label": _("Travel"), "value": "travel"}, + {"label": _("Cut"), "value": "cut"} + ], orientation='vertical') + + grid0.addWidget(self.cncplot_method_label, 1, 0) + grid0.addWidget(self.cncplot_method_radio, 1, 1) + grid0.addWidget(QtWidgets.QLabel(''), 1, 2) + + # Display Annotation + self.annotation_cb = FCCheckBox(_("Display Annotation")) + self.annotation_cb.setToolTip( + _("This selects if to display text annotation on the plot.\n" + "When checked it will display numbers in order for each end\n" + "of a travel line." + ) + ) + + grid0.addWidget(self.annotation_cb, 2, 0, 1, 3) + + # ################################################################### + # Number of circle steps for circular aperture linear approximation # + # ################################################################### + self.steps_per_circle_label = QtWidgets.QLabel('%s:' % _("Circle Steps")) + self.steps_per_circle_label.setToolTip( + _("The number of circle steps for GCode \n" + "circle and arc shapes linear approximation.") + ) + grid0.addWidget(self.steps_per_circle_label, 3, 0) + self.steps_per_circle_entry = FCSpinner() + self.steps_per_circle_entry.set_range(0, 99999) + grid0.addWidget(self.steps_per_circle_entry, 3, 1) + + # Tool dia for plot + tdlabel = QtWidgets.QLabel('%s:' % _('Travel dia')) + tdlabel.setToolTip( + _("The width of the travel lines to be\n" + "rendered in the plot.") + ) + self.tooldia_entry = FCDoubleSpinner() + self.tooldia_entry.set_range(0, 99999) + self.tooldia_entry.set_precision(self.decimals) + self.tooldia_entry.setSingleStep(0.1) + self.tooldia_entry.setWrapping(True) + + grid0.addWidget(tdlabel, 4, 0) + grid0.addWidget(self.tooldia_entry, 4, 1) + + # add a space + grid0.addWidget(QtWidgets.QLabel('%s:' % _("G-code Decimals")), 5, 0, 1, 2) + + # Number of decimals to use in GCODE coordinates + cdeclabel = QtWidgets.QLabel('%s:' % _('Coordinates')) + cdeclabel.setToolTip( + _("The number of decimals to be used for \n" + "the X, Y, Z coordinates in CNC code (GCODE, etc.)") + ) + self.coords_dec_entry = FCSpinner() + self.coords_dec_entry.set_range(0, 9) + self.coords_dec_entry.setWrapping(True) + + grid0.addWidget(cdeclabel, 6, 0) + grid0.addWidget(self.coords_dec_entry, 6, 1) + + # Number of decimals to use in GCODE feedrate + frdeclabel = QtWidgets.QLabel('%s:' % _('Feedrate')) + frdeclabel.setToolTip( + _("The number of decimals to be used for \n" + "the Feedrate parameter in CNC code (GCODE, etc.)") + ) + self.fr_dec_entry = FCSpinner() + self.fr_dec_entry.set_range(0, 9) + self.fr_dec_entry.setWrapping(True) + + grid0.addWidget(frdeclabel, 7, 0) + grid0.addWidget(self.fr_dec_entry, 7, 1) + + # The type of coordinates used in the Gcode: Absolute or Incremental + coords_type_label = QtWidgets.QLabel('%s:' % _('Coordinates type')) + coords_type_label.setToolTip( + _("The type of coordinates to be used in Gcode.\n" + "Can be:\n" + "- Absolute G90 -> the reference is the origin x=0, y=0\n" + "- Incremental G91 -> the reference is the previous position") + ) + self.coords_type_radio = RadioSet([ + {"label": _("Absolute G90"), "value": "G90"}, + {"label": _("Incremental G91"), "value": "G91"} + ], orientation='vertical', stretch=False) + grid0.addWidget(coords_type_label, 8, 0) + grid0.addWidget(self.coords_type_radio, 8, 1) # hidden for the time being, until implemented - self.option_dict()["cncjob_coords_type"].label_widget.hide() - self.option_dict()["cncjob_coords_type"].get_field().hide() + coords_type_label.hide() + self.coords_type_radio.hide() - def build_options(self) -> [OptionUI]: - return [ - HeadingOptionUI(label_text="Plot Options"), - CheckboxOptionUI( - option="cncjob_plot", - label_text="Plot Object", - label_tooltip="Plot (show) this object." - ), - RadioSetOptionUI( - option="cncjob_plot_kind", - label_text="Plot kind", - label_tooltip="This selects the kind of geometries on the canvas to plot.\n" - "Those can be either of type 'Travel' which means the moves\n" - "above the work piece or it can be of type 'Cut',\n" - "which means the moves that cut into the material.", - choices=[ - {"label": _("All"), "value": "all"}, - {"label": _("Travel"), "value": "travel"}, - {"label": _("Cut"), "value": "cut"} - ], - orientation="vertical" - ), - CheckboxOptionUI( - option="cncjob_annotation", - label_text="Display Annotation", - label_tooltip="This selects if to display text annotation on the plot.\n" - "When checked it will display numbers in order for each end\n" - "of a travel line." - ), - SpinnerOptionUI( - option="cncjob_steps_per_circle", - label_text="Circle Steps", - label_tooltip="The number of circle steps for GCode \n" - "circle and arc shapes linear approximation.", - min_value=3, max_value=99999, step=1 - ), - DoubleSpinnerOptionUI( - option="cncjob_tooldia", - label_text="Travel dia", - label_tooltip="The width of the travel lines to be\n" - "rendered in the plot.", - min_value=0, max_value=99999, step=0.1, decimals=self.decimals - ), + # Line Endings + self.line_ending_cb = FCCheckBox(_("Force Windows style line-ending")) + self.line_ending_cb.setToolTip( + _("When checked will force a Windows style line-ending\n" + "(\\r\\n) on non-Windows OS's.") + ) - HeadingOptionUI(label_text="G-code Decimals"), - SpinnerOptionUI( - option="cncjob_coords_decimals", - label_text="Coordinates", - label_tooltip="The number of decimals to be used for \n" - "the X, Y, Z coordinates in CNC code (GCODE, etc.)", - min_value=0, max_value=9, step=1 - ), - SpinnerOptionUI( - option="cncjob_fr_decimals", - label_text="Feedrate", - label_tooltip="The number of decimals to be used for \n" - "the Feedrate parameter in CNC code (GCODE, etc.)", - min_value=0, max_value=9, step=1 - ), - RadioSetOptionUI( - option="cncjob_coords_type", - label_text="Coordinates type", - label_tooltip="The type of coordinates to be used in Gcode.\n" - "Can be:\n" - "- Absolute G90 -> the reference is the origin x=0, y=0\n" - "- Incremental G91 -> the reference is the previous position", - choices=[ - {"label": _("Absolute G90"), "value": "G90"}, - {"label": _("Incremental G91"), "value": "G91"} - ], - orientation="vertical" - ), - CheckboxOptionUI( - option="cncjob_line_ending", - label_text="Force Windows style line-ending", - label_tooltip="When checked will force a Windows style line-ending\n" - "(\\r\\n) on non-Windows OS's." - ), - SeparatorOptionUI(), + grid0.addWidget(self.line_ending_cb, 9, 0, 1, 3) - HeadingOptionUI(label_text="Travel Line Color"), - ColorOptionUI( - option="cncjob_travel_line", - label_text="Outline", - label_tooltip="Set the line color for plotted objects.", - ), - ColorOptionUI( - option="cncjob_travel_fill", - label_text="Fill", - label_tooltip="Set the fill color for plotted objects.\n" - "First 6 digits are the color and the last 2\n" - "digits are for alpha (transparency) level." - ), - ColorAlphaSliderOptionUI( - applies_to=["cncjob_travel_line", "cncjob_travel_fill"], - group=self, - label_text="Alpha", - label_tooltip="Set the transparency for plotted objects." - ), + separator_line = QtWidgets.QFrame() + separator_line.setFrameShape(QtWidgets.QFrame.HLine) + separator_line.setFrameShadow(QtWidgets.QFrame.Sunken) + grid0.addWidget(separator_line, 12, 0, 1, 2) - HeadingOptionUI(label_text="CNCJob Object Color"), - ColorOptionUI( - option="cncjob_plot_line", - label_text="Outline", - label_tooltip="Set the line color for plotted objects.", - ), - ColorOptionUI( - option="cncjob_plot_fill", - label_text="Fill", - label_tooltip="Set the fill color for plotted objects.\n" - "First 6 digits are the color and the last 2\n" - "digits are for alpha (transparency) level." - ), - ColorAlphaSliderOptionUI( - applies_to=["cncjob_plot_line", "cncjob_plot_fill"], - group=self, - label_text="Alpha", - label_tooltip="Set the transparency for plotted objects." - ) - ] \ No newline at end of file + # Travel Line Color + self.travel_color_label = QtWidgets.QLabel('%s' % _('Travel Line Color')) + grid0.addWidget(self.travel_color_label, 13, 0, 1, 2) + + # Plot Line Color + self.tline_color_label = QtWidgets.QLabel('%s:' % _('Outline')) + self.tline_color_label.setToolTip( + _("Set the travel line color for plotted objects.") + ) + self.tline_color_entry = FCEntry() + self.tline_color_button = QtWidgets.QPushButton() + self.tline_color_button.setFixedSize(15, 15) + + self.form_box_child_2 = QtWidgets.QHBoxLayout() + self.form_box_child_2.addWidget(self.tline_color_entry) + self.form_box_child_2.addWidget(self.tline_color_button) + self.form_box_child_2.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter) + + grid0.addWidget(self.tline_color_label, 14, 0) + grid0.addLayout(self.form_box_child_2, 14, 1) + + # Plot Fill Color + self.tfill_color_label = QtWidgets.QLabel('%s:' % _('Fill')) + self.tfill_color_label.setToolTip( + _("Set the fill color for plotted objects.\n" + "First 6 digits are the color and the last 2\n" + "digits are for alpha (transparency) level.") + ) + self.tfill_color_entry = FCEntry() + self.tfill_color_button = QtWidgets.QPushButton() + self.tfill_color_button.setFixedSize(15, 15) + + self.form_box_child_1 = QtWidgets.QHBoxLayout() + self.form_box_child_1.addWidget(self.tfill_color_entry) + self.form_box_child_1.addWidget(self.tfill_color_button) + self.form_box_child_1.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter) + + grid0.addWidget(self.tfill_color_label, 15, 0) + grid0.addLayout(self.form_box_child_1, 15, 1) + + # Plot Fill Transparency Level + self.alpha_label = QtWidgets.QLabel('%s:' % _('Alpha')) + self.alpha_label.setToolTip( + _("Set the fill transparency for plotted objects.") + ) + self.tcolor_alpha_slider = QtWidgets.QSlider(QtCore.Qt.Horizontal) + self.tcolor_alpha_slider.setMinimum(0) + self.tcolor_alpha_slider.setMaximum(255) + self.tcolor_alpha_slider.setSingleStep(1) + + self.tcolor_alpha_spinner = FCSpinner() + self.tcolor_alpha_spinner.setMinimumWidth(70) + self.tcolor_alpha_spinner.set_range(0, 255) + + self.form_box_child_3 = QtWidgets.QHBoxLayout() + self.form_box_child_3.addWidget(self.tcolor_alpha_slider) + self.form_box_child_3.addWidget(self.tcolor_alpha_spinner) + + grid0.addWidget(self.alpha_label, 16, 0) + grid0.addLayout(self.form_box_child_3, 16, 1) + + separator_line = QtWidgets.QFrame() + separator_line.setFrameShape(QtWidgets.QFrame.HLine) + separator_line.setFrameShadow(QtWidgets.QFrame.Sunken) + grid0.addWidget(separator_line, 17, 0, 1, 2) + + # CNCJob Object Color + self.cnc_color_label = QtWidgets.QLabel('%s' % _('CNCJob Object Color')) + grid0.addWidget(self.cnc_color_label, 18, 0, 1, 2) + + # Plot Line Color + self.line_color_label = QtWidgets.QLabel('%s:' % _('Outline')) + self.line_color_label.setToolTip( + _("Set the color for plotted objects.") + ) + self.line_color_entry = FCEntry() + self.line_color_button = QtWidgets.QPushButton() + self.line_color_button.setFixedSize(15, 15) + + self.form_box_child_2 = QtWidgets.QHBoxLayout() + self.form_box_child_2.addWidget(self.line_color_entry) + self.form_box_child_2.addWidget(self.line_color_button) + self.form_box_child_2.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter) + + grid0.addWidget(self.line_color_label, 19, 0) + grid0.addLayout(self.form_box_child_2, 19, 1) + + # Plot Fill Color + self.fill_color_label = QtWidgets.QLabel('%s:' % _('Fill')) + self.fill_color_label.setToolTip( + _("Set the fill color for plotted objects.\n" + "First 6 digits are the color and the last 2\n" + "digits are for alpha (transparency) level.") + ) + self.fill_color_entry = FCEntry() + self.fill_color_button = QtWidgets.QPushButton() + self.fill_color_button.setFixedSize(15, 15) + + self.form_box_child_1 = QtWidgets.QHBoxLayout() + self.form_box_child_1.addWidget(self.fill_color_entry) + self.form_box_child_1.addWidget(self.fill_color_button) + self.form_box_child_1.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter) + + grid0.addWidget(self.fill_color_label, 20, 0) + grid0.addLayout(self.form_box_child_1, 20, 1) + + self.layout.addStretch() + + # Setting plot colors signals + self.tline_color_entry.editingFinished.connect(self.on_tline_color_entry) + self.tline_color_button.clicked.connect(self.on_tline_color_button) + self.tfill_color_entry.editingFinished.connect(self.on_tfill_color_entry) + self.tfill_color_button.clicked.connect(self.on_tfill_color_button) + self.tcolor_alpha_spinner.valueChanged.connect(self.on_tcolor_spinner) + self.tcolor_alpha_slider.valueChanged.connect(self.on_tcolor_slider) + + self.line_color_entry.editingFinished.connect(self.on_line_color_entry) + self.line_color_button.clicked.connect(self.on_line_color_button) + self.fill_color_entry.editingFinished.connect(self.on_fill_color_entry) + self.fill_color_button.clicked.connect(self.on_fill_color_button) + + # ------------------------------------------------------ + # Setting travel colors handlers + # ------------------------------------------------------ + def on_tfill_color_entry(self): + self.app.defaults['cncjob_travel_fill'] = self.tfill_color_entry.get_value()[:7] + \ + self.app.defaults['cncjob_travel_fill'][7:9] + self.tfill_color_button.setStyleSheet( + "background-color:%s" % str(self.app.defaults['cncjob_travel_fill'])[:7]) + + def on_tfill_color_button(self): + current_color = QtGui.QColor(self.app.defaults['cncjob_travel_fill'][:7]) + + c_dialog = QtWidgets.QColorDialog() + plot_fill_color = c_dialog.getColor(initial=current_color) + + if plot_fill_color.isValid() is False: + return + + self.tfill_color_button.setStyleSheet("background-color:%s" % str(plot_fill_color.name())) + + new_val = str(plot_fill_color.name()) + str(self.app.defaults['cncjob_travel_fill'][7:9]) + self.tfill_color_entry.set_value(new_val) + self.app.defaults['cncjob_travel_fill'] = new_val + + def on_tcolor_spinner(self): + spinner_value = self.tcolor_alpha_spinner.value() + self.tcolor_alpha_slider.setValue(spinner_value) + self.app.defaults['cncjob_travel_fill'] = \ + self.app.defaults['cncjob_travel_fill'][:7] + \ + (hex(spinner_value)[2:] if int(hex(spinner_value)[2:], 16) > 0 else '00') + self.app.defaults['cncjob_travel_line'] = \ + self.app.defaults['cncjob_travel_line'][:7] + \ + (hex(spinner_value)[2:] if int(hex(spinner_value)[2:], 16) > 0 else '00') + + def on_tcolor_slider(self): + slider_value = self.tcolor_alpha_slider.value() + self.tcolor_alpha_spinner.setValue(slider_value) + + def on_tline_color_entry(self): + self.app.defaults['cncjob_travel_line'] = self.tline_color_entry.get_value()[:7] + \ + self.app.defaults['cncjob_travel_line'][7:9] + self.tline_color_button.setStyleSheet( + "background-color:%s" % str(self.app.defaults['cncjob_travel_line'])[:7]) + + def on_tline_color_button(self): + current_color = QtGui.QColor(self.app.defaults['cncjob_travel_line'][:7]) + # print(current_color) + + c_dialog = QtWidgets.QColorDialog() + plot_line_color = c_dialog.getColor(initial=current_color) + + if plot_line_color.isValid() is False: + return + + self.tline_color_button.setStyleSheet("background-color:%s" % str(plot_line_color.name())) + + new_val_line = str(plot_line_color.name()) + str(self.app.defaults['cncjob_travel_line'][7:9]) + self.tline_color_entry.set_value(new_val_line) + self.app.defaults['cncjob_travel_line'] = new_val_line + + # ------------------------------------------------------ + # Setting plot colors handlers + # ------------------------------------------------------ + def on_fill_color_entry(self): + self.app.defaults['cncjob_plot_fill'] = self.fill_color_entry.get_value()[:7] + \ + self.app.defaults['cncjob_plot_fill'][7:9] + self.fill_color_button.setStyleSheet( + "background-color:%s" % str(self.app.defaults['cncjob_plot_fill'])[:7]) + + def on_fill_color_button(self): + current_color = QtGui.QColor(self.app.defaults['cncjob_plot_fill'][:7]) + + c_dialog = QtWidgets.QColorDialog() + plot_fill_color = c_dialog.getColor(initial=current_color) + + if plot_fill_color.isValid() is False: + return + + self.fill_color_button.setStyleSheet("background-color:%s" % str(plot_fill_color.name())) + + new_val = str(plot_fill_color.name()) + str(self.app.defaults['cncjob_plot_fill'][7:9]) + self.fill_color_entry.set_value(new_val) + self.app.defaults['cncjob_plot_fill'] = new_val + + def on_line_color_entry(self): + self.app.defaults['cncjob_plot_line'] = self.line_color_entry.get_value()[:7] + \ + self.app.defaults['cncjob_plot_line'][7:9] + self.line_color_button.setStyleSheet( + "background-color:%s" % str(self.app.defaults['cncjob_plot_line'])[:7]) + + def on_line_color_button(self): + current_color = QtGui.QColor(self.app.defaults['cncjob_plot_line'][:7]) + # print(current_color) + + c_dialog = QtWidgets.QColorDialog() + plot_line_color = c_dialog.getColor(initial=current_color) + + if plot_line_color.isValid() is False: + return + + self.line_color_button.setStyleSheet("background-color:%s" % str(plot_line_color.name())) + + new_val_line = str(plot_line_color.name()) + str(self.app.defaults['cncjob_plot_line'][7:9]) + self.line_color_entry.set_value(new_val_line) + self.app.defaults['cncjob_plot_line'] = new_val_line diff --git a/flatcamGUI/preferences/cncjob/CNCJobOptPrefGroupUI.py b/flatcamGUI/preferences/cncjob/CNCJobOptPrefGroupUI.py index eefaee28..c8eb7e66 100644 --- a/flatcamGUI/preferences/cncjob/CNCJobOptPrefGroupUI.py +++ b/flatcamGUI/preferences/cncjob/CNCJobOptPrefGroupUI.py @@ -1,39 +1,80 @@ -from flatcamGUI.preferences.OptionUI import * -from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI2 +from PyQt5 import QtWidgets, QtGui +from PyQt5.QtCore import QSettings + +from flatcamGUI.GUIElements import FCTextArea +from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI import gettext import FlatCAMTranslation as fcTranslate import builtins + fcTranslate.apply_language('strings') if '_' not in builtins.__dict__: _ = gettext.gettext +settings = QSettings("Open Source", "FlatCAM") +if settings.contains("machinist"): + machinist_setting = settings.value('machinist', type=int) +else: + machinist_setting = 0 -class CNCJobOptPrefGroupUI(OptionsGroupUI2): - def __init__(self, decimals=4, **kwargs): - self.decimals = decimals - super().__init__(**kwargs) +class CNCJobOptPrefGroupUI(OptionsGroupUI): + def __init__(self, decimals=4, parent=None): + # OptionsGroupUI.__init__(self, "CNC Job Options Preferences", parent=None) + super(CNCJobOptPrefGroupUI, self).__init__(self, parent=parent) + self.setTitle(str(_("CNC Job Options"))) + self.decimals = decimals - def build_options(self) -> [OptionUI]: - return [ - HeadingOptionUI( - label_text="Export G-Code", - label_tooltip="Export and save G-Code to\n" - "make this object to a file." - ), - TextAreaOptionUI( - option="cncjob_prepend", - label_text="Prepend to G-Code", - label_tooltip="Type here any G-Code commands you would\n" - "like to add at the beginning of the G-Code file." - ), - TextAreaOptionUI( - option="cncjob_append", - label_text="Append to G-Code", - label_tooltip="Type here any G-Code commands you would\n" - "like to append to the generated file.\n" - "I.e.: M2 (End of program)" - ) - ] + # ## Export G-Code + self.export_gcode_label = QtWidgets.QLabel("%s:" % _("Export G-Code")) + self.export_gcode_label.setToolTip( + _("Export and save G-Code to\n" + "make this object to a file.") + ) + self.layout.addWidget(self.export_gcode_label) + + qsettings = QSettings("Open Source", "FlatCAM") + if qsettings.contains("textbox_font_size"): + tb_fsize = qsettings.value('textbox_font_size', type=int) + else: + tb_fsize = 10 + font = QtGui.QFont() + font.setPointSize(tb_fsize) + + # Prepend to G-Code + prependlabel = QtWidgets.QLabel('%s:' % _('Prepend to G-Code')) + prependlabel.setToolTip( + _("Type here any G-Code commands you would\n" + "like to add at the beginning of the G-Code file.") + ) + self.layout.addWidget(prependlabel) + + self.prepend_text = FCTextArea() + self.prepend_text.setPlaceholderText( + _("Type here any G-Code commands you would " + "like to add at the beginning of the G-Code file.") + ) + self.layout.addWidget(self.prepend_text) + self.prepend_text.setFont(font) + + # Append text to G-Code + appendlabel = QtWidgets.QLabel('%s:' % _('Append to G-Code')) + appendlabel.setToolTip( + _("Type here any G-Code commands you would\n" + "like to append to the generated file.\n" + "I.e.: M2 (End of program)") + ) + self.layout.addWidget(appendlabel) + + self.append_text = FCTextArea() + self.append_text.setPlaceholderText( + _("Type here any G-Code commands you would " + "like to append to the generated file.\n" + "I.e.: M2 (End of program)") + ) + self.layout.addWidget(self.append_text) + self.append_text.setFont(font) + + self.layout.addStretch() diff --git a/flatcamGUI/preferences/cncjob/CNCJobPreferencesUI.py b/flatcamGUI/preferences/cncjob/CNCJobPreferencesUI.py index d81134d8..cc9a7e32 100644 --- a/flatcamGUI/preferences/cncjob/CNCJobPreferencesUI.py +++ b/flatcamGUI/preferences/cncjob/CNCJobPreferencesUI.py @@ -1,33 +1,27 @@ -from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI -from flatcamGUI.preferences.PreferencesSectionUI import PreferencesSectionUI +from PyQt5 import QtWidgets + from flatcamGUI.preferences.cncjob.CNCJobAdvOptPrefGroupUI import CNCJobAdvOptPrefGroupUI from flatcamGUI.preferences.cncjob.CNCJobOptPrefGroupUI import CNCJobOptPrefGroupUI from flatcamGUI.preferences.cncjob.CNCJobGenPrefGroupUI import CNCJobGenPrefGroupUI -import gettext -import FlatCAMTranslation as fcTranslate -import builtins -fcTranslate.apply_language('strings') -if '_' not in builtins.__dict__: - _ = gettext.gettext +class CNCJobPreferencesUI(QtWidgets.QWidget): -class CNCJobPreferencesUI(PreferencesSectionUI): - - def __init__(self, decimals, **kwargs): + def __init__(self, decimals, parent=None): + QtWidgets.QWidget.__init__(self, parent=parent) + self.layout = QtWidgets.QHBoxLayout() + self.setLayout(self.layout) self.decimals = decimals - super().__init__(**kwargs) - def build_groups(self) -> [OptionsGroupUI]: - return [ - CNCJobGenPrefGroupUI(decimals=self.decimals), - CNCJobOptPrefGroupUI(decimals=self.decimals), - CNCJobAdvOptPrefGroupUI(decimals=self.decimals) - ] + self.cncjob_gen_group = CNCJobGenPrefGroupUI(decimals=self.decimals) + self.cncjob_gen_group.setMinimumWidth(260) + self.cncjob_opt_group = CNCJobOptPrefGroupUI(decimals=self.decimals) + self.cncjob_opt_group.setMinimumWidth(260) + self.cncjob_adv_opt_group = CNCJobAdvOptPrefGroupUI(decimals=self.decimals) + self.cncjob_adv_opt_group.setMinimumWidth(260) - def get_tab_id(self): - # FIXME this doesn't seem right - return "text_editor_tab" + self.layout.addWidget(self.cncjob_gen_group) + self.layout.addWidget(self.cncjob_opt_group) + self.layout.addWidget(self.cncjob_adv_opt_group) - def get_tab_label(self): - return _("CNC-JOB") \ No newline at end of file + self.layout.addStretch() diff --git a/flatcamGUI/preferences/excellon/ExcellonAdvOptPrefGroupUI.py b/flatcamGUI/preferences/excellon/ExcellonAdvOptPrefGroupUI.py index 321fc21b..a63998f9 100644 --- a/flatcamGUI/preferences/excellon/ExcellonAdvOptPrefGroupUI.py +++ b/flatcamGUI/preferences/excellon/ExcellonAdvOptPrefGroupUI.py @@ -1,97 +1,155 @@ -from flatcamGUI.preferences.OptionUI import * -from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI2 +from PyQt5 import QtWidgets +from PyQt5.QtCore import QSettings +from flatcamGUI.GUIElements import FCDoubleSpinner, FCEntry, FloatEntry, RadioSet, FCCheckBox +from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI import gettext import FlatCAMTranslation as fcTranslate import builtins + fcTranslate.apply_language('strings') if '_' not in builtins.__dict__: _ = gettext.gettext +settings = QSettings("Open Source", "FlatCAM") +if settings.contains("machinist"): + machinist_setting = settings.value('machinist', type=int) +else: + machinist_setting = 0 -class ExcellonAdvOptPrefGroupUI(OptionsGroupUI2): - def __init__(self, decimals=4, **kwargs): - self.decimals = decimals - super().__init__(**kwargs) +class ExcellonAdvOptPrefGroupUI(OptionsGroupUI): + + def __init__(self, decimals=4, parent=None): + # OptionsGroupUI.__init__(self, "Excellon Advanced Options", parent=parent) + super(ExcellonAdvOptPrefGroupUI, self).__init__(self, parent=parent) + self.setTitle(str(_("Excellon Adv. Options"))) + self.decimals = decimals - def build_options(self) -> [OptionUI]: - return [ - HeadingOptionUI( - label_text="Advanced Options", - label_tooltip="A list of Excellon advanced parameters.\n" - "Those parameters are available only for\n" - "Advanced App. Level." - ), - DoubleSpinnerOptionUI( - option="excellon_offset", - label_text="Offset Z", - label_tooltip="Some drill bits (the larger ones) need to drill deeper\n" - "to create the desired exit hole diameter due of the tip shape.\n" - "The value here can compensate the Cut Z parameter.", - min_value=-999.9999, max_value=999.9999, step=0.1, decimals=self.decimals - ), - LineEntryOptionUI( - option="excellon_toolchangexy", - label_text="Toolchange X,Y", - label_tooltip="Toolchange X,Y position." - ), - FloatEntryOptionUI( - option="excellon_startz", - label_text="Start Z", - label_tooltip="Height of the tool just after start.\n" - "Delete the value if you don't need this feature." - ), - DoubleSpinnerOptionUI( - option="excellon_feedrate_rapid", - label_text="Feedrate Rapids", - label_tooltip="Tool speed while drilling\n" - "(in units per minute).\n" - "This is for the rapid move G00.\n" - "It is useful only for Marlin,\n" - "ignore for any other cases.", - min_value=0.0001, max_value=99999.9999, step=50, decimals=self.decimals - ), - DoubleSpinnerOptionUI( - option="excellon_z_pdepth", - label_text="Probe Z depth", - label_tooltip="The maximum depth that the probe is allowed\n" - "to probe. Negative value, in current units.", - min_value=-99999.9999, max_value=0.0, step=0.1, decimals=self.decimals - ), - DoubleSpinnerOptionUI( - option="excellon_feedrate_probe", - label_text="Feedrate Probe", - label_tooltip="The feedrate used while the probe is probing.", - min_value=0.0001, max_value=99999.9999, step=0.1, decimals=self.decimals - ), - RadioSetOptionUI( - option="excellon_spindledir", - label_text="Spindle direction", - label_tooltip="This sets the direction that the spindle is rotating.\n" - "It can be either:\n" - "- CW = clockwise or\n" - "- CCW = counter clockwise", - choices=[{'label': _('CW'), 'value': 'CW'}, - {'label': _('CCW'), 'value': 'CCW'}] - ), - CheckboxOptionUI( - option="excellon_f_plunge", - label_text="Fast Plunge", - label_tooltip="By checking this, the vertical move from\n" - "Z_Toolchange to Z_move is done with G0,\n" - "meaning the fastest speed available.\n" - "WARNING: the move is done at Toolchange X,Y coords." - ), - CheckboxOptionUI( - option="excellon_f_retract", - label_text="Fast Retract", - label_tooltip="Exit hole strategy.\n" - " - When uncheked, while exiting the drilled hole the drill bit\n" - "will travel slow, with set feedrate (G1), up to zero depth and then\n" - "travel as fast as possible (G0) to the Z Move (travel height).\n" - " - When checked the travel from Z cut (cut depth) to Z_move\n" - "(travel height) is done as fast as possible (G0) in one move." - ) - ] \ No newline at end of file + # ####################### + # ## ADVANCED OPTIONS ### + # ####################### + + self.exc_label = QtWidgets.QLabel('%s:' % _('Advanced Options')) + self.exc_label.setToolTip( + _("A list of Excellon advanced parameters.\n" + "Those parameters are available only for\n" + "Advanced App. Level.") + ) + self.layout.addWidget(self.exc_label) + + grid1 = QtWidgets.QGridLayout() + self.layout.addLayout(grid1) + + # Offset Z + offsetlabel = QtWidgets.QLabel('%s:' % _('Offset Z')) + offsetlabel.setToolTip( + _("Some drill bits (the larger ones) need to drill deeper\n" + "to create the desired exit hole diameter due of the tip shape.\n" + "The value here can compensate the Cut Z parameter.")) + self.offset_entry = FCDoubleSpinner() + self.offset_entry.set_precision(self.decimals) + self.offset_entry.set_range(-999.9999, 999.9999) + + grid1.addWidget(offsetlabel, 0, 0) + grid1.addWidget(self.offset_entry, 0, 1) + + # ToolChange X,Y + toolchange_xy_label = QtWidgets.QLabel('%s:' % _('Toolchange X,Y')) + toolchange_xy_label.setToolTip( + _("Toolchange X,Y position.") + ) + self.toolchangexy_entry = FCEntry() + + grid1.addWidget(toolchange_xy_label, 1, 0) + grid1.addWidget(self.toolchangexy_entry, 1, 1) + + # Start Z + startzlabel = QtWidgets.QLabel('%s:' % _('Start Z')) + startzlabel.setToolTip( + _("Height of the tool just after start.\n" + "Delete the value if you don't need this feature.") + ) + self.estartz_entry = FloatEntry() + + grid1.addWidget(startzlabel, 2, 0) + grid1.addWidget(self.estartz_entry, 2, 1) + + # Feedrate Rapids + fr_rapid_label = QtWidgets.QLabel('%s:' % _('Feedrate Rapids')) + fr_rapid_label.setToolTip( + _("Tool speed while drilling\n" + "(in units per minute).\n" + "This is for the rapid move G00.\n" + "It is useful only for Marlin,\n" + "ignore for any other cases.") + ) + self.feedrate_rapid_entry = FCDoubleSpinner() + self.feedrate_rapid_entry.set_precision(self.decimals) + self.feedrate_rapid_entry.set_range(0, 99999.9999) + + grid1.addWidget(fr_rapid_label, 3, 0) + grid1.addWidget(self.feedrate_rapid_entry, 3, 1) + + # Probe depth + self.pdepth_label = QtWidgets.QLabel('%s:' % _("Probe Z depth")) + self.pdepth_label.setToolTip( + _("The maximum depth that the probe is allowed\n" + "to probe. Negative value, in current units.") + ) + self.pdepth_entry = FCDoubleSpinner() + self.pdepth_entry.set_precision(self.decimals) + self.pdepth_entry.set_range(-99999.9999, 0.0000) + + grid1.addWidget(self.pdepth_label, 4, 0) + grid1.addWidget(self.pdepth_entry, 4, 1) + + # Probe feedrate + self.feedrate_probe_label = QtWidgets.QLabel('%s:' % _("Feedrate Probe")) + self.feedrate_probe_label.setToolTip( + _("The feedrate used while the probe is probing.") + ) + self.feedrate_probe_entry = FCDoubleSpinner() + self.feedrate_probe_entry.set_precision(self.decimals) + self.feedrate_probe_entry.set_range(0, 99999.9999) + + grid1.addWidget(self.feedrate_probe_label, 5, 0) + grid1.addWidget(self.feedrate_probe_entry, 5, 1) + + # Spindle direction + spindle_dir_label = QtWidgets.QLabel('%s:' % _('Spindle direction')) + spindle_dir_label.setToolTip( + _("This sets the direction that the spindle is rotating.\n" + "It can be either:\n" + "- CW = clockwise or\n" + "- CCW = counter clockwise") + ) + + self.spindledir_radio = RadioSet([{'label': _('CW'), 'value': 'CW'}, + {'label': _('CCW'), 'value': 'CCW'}]) + grid1.addWidget(spindle_dir_label, 6, 0) + grid1.addWidget(self.spindledir_radio, 6, 1) + + self.fplunge_cb = FCCheckBox('%s' % _('Fast Plunge')) + self.fplunge_cb.setToolTip( + _("By checking this, the vertical move from\n" + "Z_Toolchange to Z_move is done with G0,\n" + "meaning the fastest speed available.\n" + "WARNING: the move is done at Toolchange X,Y coords.") + ) + grid1.addWidget(self.fplunge_cb, 7, 0, 1, 2) + + self.fretract_cb = FCCheckBox('%s' % _('Fast Retract')) + self.fretract_cb.setToolTip( + _("Exit hole strategy.\n" + " - When uncheked, while exiting the drilled hole the drill bit\n" + "will travel slow, with set feedrate (G1), up to zero depth and then\n" + "travel as fast as possible (G0) to the Z Move (travel height).\n" + " - When checked the travel from Z cut (cut depth) to Z_move\n" + "(travel height) is done as fast as possible (G0) in one move.") + ) + + grid1.addWidget(self.fretract_cb, 8, 0, 1, 2) + + self.layout.addStretch() diff --git a/flatcamGUI/preferences/excellon/ExcellonEditorPrefGroupUI.py b/flatcamGUI/preferences/excellon/ExcellonEditorPrefGroupUI.py index 162cdf8a..5b04cf2f 100644 --- a/flatcamGUI/preferences/excellon/ExcellonEditorPrefGroupUI.py +++ b/flatcamGUI/preferences/excellon/ExcellonEditorPrefGroupUI.py @@ -1,173 +1,306 @@ -from flatcamGUI.preferences.OptionUI import * -from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI2 +from PyQt5 import QtWidgets +from PyQt5.QtCore import QSettings + +from flatcamGUI.GUIElements import FCSpinner, FCDoubleSpinner, RadioSet +from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI import gettext import FlatCAMTranslation as fcTranslate import builtins + fcTranslate.apply_language('strings') if '_' not in builtins.__dict__: _ = gettext.gettext +settings = QSettings("Open Source", "FlatCAM") +if settings.contains("machinist"): + machinist_setting = settings.value('machinist', type=int) +else: + machinist_setting = 0 -class ExcellonEditorPrefGroupUI(OptionsGroupUI2): - def __init__(self, decimals=4, **kwargs): - self.decimals = decimals - super().__init__(**kwargs) +class ExcellonEditorPrefGroupUI(OptionsGroupUI): + def __init__(self, decimals=4, parent=None): + super(ExcellonEditorPrefGroupUI, self).__init__(self, parent=parent) + self.setTitle(str(_("Excellon Editor"))) + self.decimals = decimals - def build_options(self) -> [OptionUI]: - return [ - HeadingOptionUI( - label_text="Parameters", - label_tooltip="A list of Excellon Editor parameters." - ), - SpinnerOptionUI( - option="excellon_editor_sel_limit", - label_text="Selection limit", - label_tooltip="Set the number of selected Excellon geometry\n" - "items above which the utility geometry\n" - "becomes just a selection rectangle.\n" - "Increases the performance when moving a\n" - "large number of geometric elements.", - min_value=0, max_value=99999, step=1 - ), - DoubleSpinnerOptionUI( - option="excellon_editor_newdia", - label_text="New Dia", - label_tooltip="Diameter for the new tool", - min_value=0.000001, max_value=99.9999, step=0.1, decimals=self.decimals - ), - SpinnerOptionUI( - option="excellon_editor_array_size", - label_text="Nr of drills", - label_tooltip="Specify how many drills to be in the array.", - min_value=0, max_value=9999, step=1 - ), + # Excellon Editor Parameters + self.param_label = QtWidgets.QLabel("%s:" % _("Parameters")) + self.param_label.setToolTip( + _("A list of Excellon Editor parameters.") + ) + self.layout.addWidget(self.param_label) - HeadingOptionUI(label_text="Linear Drill Array"), - RadioSetOptionUI( - option="excellon_editor_lin_dir", - label_text="Linear Direction", - label_tooltip="Direction on which the linear array is oriented:\n" - "- 'X' - horizontal axis \n" - "- 'Y' - vertical axis or \n" - "- 'Angle' - a custom angle for the array inclination", - choices=[ - {'label': _('X'), 'value': 'X'}, - {'label': _('Y'), 'value': 'Y'}, - {'label': _('Angle'), 'value': 'A'} - ] - ), - DoubleSpinnerOptionUI( - option="excellon_editor_lin_pitch", - label_text="Pitch", - label_tooltip="Pitch = Distance between elements of the array.", - min_value=0, max_value=99999.9999, step=0.1, decimals=self.decimals - ), - DoubleSpinnerOptionUI( - option="excellon_editor_lin_angle", - label_text="Angle", - label_tooltip="Angle at which each element in circular array is placed.", # FIXME tooltip seems wrong ? - min_value=-360, max_value=360, step=5, decimals=self.decimals - ), + grid0 = QtWidgets.QGridLayout() + self.layout.addLayout(grid0) - HeadingOptionUI(label_text="Circular Drill Array"), - RadioSetOptionUI( - option="excellon_editor_circ_dir", - label_text="Circular Direction", - label_tooltip="Direction for circular array.\n" - "Can be CW = clockwise or CCW = counter clockwise.", - choices=[ - {'label': _('CW'), 'value': 'CW'}, - {'label': _('CCW'), 'value': 'CCW'} - ] - ), - DoubleSpinnerOptionUI( - option="excellon_editor_circ_angle", - label_text="Angle", - label_tooltip="Angle at which each element in circular array is placed.", - min_value=-360, max_value=360, step=5, decimals=self.decimals - ), + # Selection Limit + self.sel_limit_label = QtWidgets.QLabel('%s:' % _("Selection limit")) + self.sel_limit_label.setToolTip( + _("Set the number of selected Excellon geometry\n" + "items above which the utility geometry\n" + "becomes just a selection rectangle.\n" + "Increases the performance when moving a\n" + "large number of geometric elements.") + ) + self.sel_limit_entry = FCSpinner() + self.sel_limit_entry.set_range(0, 99999) - HeadingOptionUI(label_text="Slots"), - DoubleSpinnerOptionUI( - option="excellon_editor_slot_length", - label_text="Length", - label_tooltip="Length = The length of the slot.", - min_value=0, max_value=99999, step=1, decimals=self.decimals - ), - RadioSetOptionUI( - option="excellon_editor_slot_direction", - label_text="Direction", - label_tooltip="Direction on which the slot is oriented:\n" - "- 'X' - horizontal axis \n" - "- 'Y' - vertical axis or \n" - "- 'Angle' - a custom angle for the slot inclination", - choices=[ - {'label': _('X'), 'value': 'X'}, - {'label': _('Y'), 'value': 'Y'}, - {'label': _('Angle'), 'value': 'A'} - ] - ), - DoubleSpinnerOptionUI( - option="excellon_editor_slot_angle", - label_text="Angle", - label_tooltip="Angle at which the slot is placed.\n" - "The precision is of max 2 decimals.\n" - "Min value is: -359.99 degrees.\n" - "Max value is: 360.00 degrees.", - min_value=-359.99, max_value=360.00, step=5, decimals=self.decimals - ), + grid0.addWidget(self.sel_limit_label, 0, 0) + grid0.addWidget(self.sel_limit_entry, 0, 1) - HeadingOptionUI(label_text="Linear Slot Array"), - SpinnerOptionUI( - option="excellon_editor_slot_array_size", - label_text="Nr of slots", - label_tooltip="Specify how many slots to be in the array.", - min_value=0, max_value=999999, step=1 - ), - RadioSetOptionUI( - option="excellon_editor_slot_lin_dir", - label_text="Linear Direction", - label_tooltip="Direction on which the linear array is oriented:\n" - "- 'X' - horizontal axis \n" - "- 'Y' - vertical axis or \n" - "- 'Angle' - a custom angle for the array inclination", - choices=[ - {'label': _('X'), 'value': 'X'}, - {'label': _('Y'), 'value': 'Y'}, - {'label': _('Angle'), 'value': 'A'} - ] - ), - DoubleSpinnerOptionUI( - option="excellon_editor_slot_lin_pitch", - label_text="Pitch", - label_tooltip="Pitch = Distance between elements of the array.", - min_value=0, max_value=999999, step=1, decimals=self.decimals - ), - DoubleSpinnerOptionUI( - option="excellon_editor_slot_lin_angle", - label_text="Angle", - label_tooltip="Angle at which each element in circular array is placed.", # FIXME - min_value=-360, max_value=360, step=5, decimals=self.decimals - ), + # New Diameter + self.addtool_entry_lbl = QtWidgets.QLabel('%s:' % _('New Dia')) + self.addtool_entry_lbl.setToolTip( + _("Diameter for the new tool") + ) - HeadingOptionUI(label_text="Circular Slot Array"), - RadioSetOptionUI( - option="excellon_editor_slot_circ_dir", - label_text="Circular Direction", - label_tooltip="Direction for circular array.\n" - "Can be CW = clockwise or CCW = counter clockwise.", - choices=[{'label': _('CW'), 'value': 'CW'}, - {'label': _('CCW'), 'value': 'CCW'}] - ), - DoubleSpinnerOptionUI( - option="excellon_editor_slot_circ_angle", - label_text="Circular Angle", - label_tooltip="Angle at which each element in circular array is placed.", - min_value=-360, max_value=360, step=5, decimals=self.decimals - ) + self.addtool_entry = FCDoubleSpinner() + self.addtool_entry.set_range(0.000001, 99.9999) + self.addtool_entry.set_precision(self.decimals) - ] + grid0.addWidget(self.addtool_entry_lbl, 1, 0) + grid0.addWidget(self.addtool_entry, 1, 1) + # Number of drill holes in a drill array + self.drill_array_size_label = QtWidgets.QLabel('%s:' % _('Nr of drills')) + self.drill_array_size_label.setToolTip( + _("Specify how many drills to be in the array.") + ) + # self.drill_array_size_label.setMinimumWidth(100) + + self.drill_array_size_entry = FCSpinner() + self.drill_array_size_entry.set_range(0, 9999) + + grid0.addWidget(self.drill_array_size_label, 2, 0) + grid0.addWidget(self.drill_array_size_entry, 2, 1) + + self.drill_array_linear_label = QtWidgets.QLabel('%s:' % _('Linear Drill Array')) + grid0.addWidget(self.drill_array_linear_label, 3, 0, 1, 2) + + # Linear Drill Array direction + self.drill_axis_label = QtWidgets.QLabel('%s:' % _('Linear Direction')) + self.drill_axis_label.setToolTip( + _("Direction on which the linear array is oriented:\n" + "- 'X' - horizontal axis \n" + "- 'Y' - vertical axis or \n" + "- 'Angle' - a custom angle for the array inclination") + ) + # self.drill_axis_label.setMinimumWidth(100) + self.drill_axis_radio = RadioSet([{'label': _('X'), 'value': 'X'}, + {'label': _('Y'), 'value': 'Y'}, + {'label': _('Angle'), 'value': 'A'}]) + + grid0.addWidget(self.drill_axis_label, 4, 0) + grid0.addWidget(self.drill_axis_radio, 4, 1) + + # Linear Drill Array pitch distance + self.drill_pitch_label = QtWidgets.QLabel('%s:' % _('Pitch')) + self.drill_pitch_label.setToolTip( + _("Pitch = Distance between elements of the array.") + ) + # self.drill_pitch_label.setMinimumWidth(100) + self.drill_pitch_entry = FCDoubleSpinner() + self.drill_pitch_entry.set_range(0, 99999.9999) + self.drill_pitch_entry.set_precision(self.decimals) + + grid0.addWidget(self.drill_pitch_label, 5, 0) + grid0.addWidget(self.drill_pitch_entry, 5, 1) + + # Linear Drill Array custom angle + self.drill_angle_label = QtWidgets.QLabel('%s:' % _('Angle')) + self.drill_angle_label.setToolTip( + _("Angle at which each element in circular array is placed.") + ) + self.drill_angle_entry = FCDoubleSpinner() + self.drill_pitch_entry.set_range(-360, 360) + self.drill_pitch_entry.set_precision(self.decimals) + self.drill_angle_entry.setWrapping(True) + self.drill_angle_entry.setSingleStep(5) + + grid0.addWidget(self.drill_angle_label, 6, 0) + grid0.addWidget(self.drill_angle_entry, 6, 1) + + self.drill_array_circ_label = QtWidgets.QLabel('%s:' % _('Circular Drill Array')) + grid0.addWidget(self.drill_array_circ_label, 7, 0, 1, 2) + + # Circular Drill Array direction + self.drill_circular_direction_label = QtWidgets.QLabel('%s:' % _('Circular Direction')) + self.drill_circular_direction_label.setToolTip( + _("Direction for circular array.\n" + "Can be CW = clockwise or CCW = counter clockwise.") + ) + + self.drill_circular_dir_radio = RadioSet([{'label': _('CW'), 'value': 'CW'}, + {'label': _('CCW'), 'value': 'CCW'}]) + + grid0.addWidget(self.drill_circular_direction_label, 8, 0) + grid0.addWidget(self.drill_circular_dir_radio, 8, 1) + + # Circular Drill Array Angle + self.drill_circular_angle_label = QtWidgets.QLabel('%s:' % _('Circular Angle')) + self.drill_circular_angle_label.setToolTip( + _("Angle at which each element in circular array is placed.") + ) + self.drill_circular_angle_entry = FCDoubleSpinner() + self.drill_circular_angle_entry.set_range(-360, 360) + self.drill_circular_angle_entry.set_precision(self.decimals) + self.drill_circular_angle_entry.setWrapping(True) + self.drill_circular_angle_entry.setSingleStep(5) + + grid0.addWidget(self.drill_circular_angle_label, 9, 0) + grid0.addWidget(self.drill_circular_angle_entry, 9, 1) + + # ##### SLOTS ##### + # ################# + self.drill_array_circ_label = QtWidgets.QLabel('%s:' % _('Slots')) + grid0.addWidget(self.drill_array_circ_label, 10, 0, 1, 2) + + # Slot length + self.slot_length_label = QtWidgets.QLabel('%s:' % _('Length')) + self.slot_length_label.setToolTip( + _("Length = The length of the slot.") + ) + self.slot_length_label.setMinimumWidth(100) + + self.slot_length_entry = FCDoubleSpinner() + self.slot_length_entry.set_range(0, 99999) + self.slot_length_entry.set_precision(self.decimals) + self.slot_length_entry.setWrapping(True) + self.slot_length_entry.setSingleStep(1) + + grid0.addWidget(self.slot_length_label, 11, 0) + grid0.addWidget(self.slot_length_entry, 11, 1) + + # Slot direction + self.slot_axis_label = QtWidgets.QLabel('%s:' % _('Direction')) + self.slot_axis_label.setToolTip( + _("Direction on which the slot is oriented:\n" + "- 'X' - horizontal axis \n" + "- 'Y' - vertical axis or \n" + "- 'Angle' - a custom angle for the slot inclination") + ) + self.slot_axis_label.setMinimumWidth(100) + + self.slot_axis_radio = RadioSet([{'label': _('X'), 'value': 'X'}, + {'label': _('Y'), 'value': 'Y'}, + {'label': _('Angle'), 'value': 'A'}]) + grid0.addWidget(self.slot_axis_label, 12, 0) + grid0.addWidget(self.slot_axis_radio, 12, 1) + + # Slot custom angle + self.slot_angle_label = QtWidgets.QLabel('%s:' % _('Angle')) + self.slot_angle_label.setToolTip( + _("Angle at which the slot is placed.\n" + "The precision is of max 2 decimals.\n" + "Min value is: -359.99 degrees.\n" + "Max value is: 360.00 degrees.") + ) + self.slot_angle_label.setMinimumWidth(100) + + self.slot_angle_spinner = FCDoubleSpinner() + self.slot_angle_spinner.set_precision(self.decimals) + self.slot_angle_spinner.setWrapping(True) + self.slot_angle_spinner.setRange(-359.99, 360.00) + self.slot_angle_spinner.setSingleStep(5) + + grid0.addWidget(self.slot_angle_label, 13, 0) + grid0.addWidget(self.slot_angle_spinner, 13, 1) + + # #### SLOTS ARRAY ####### + # ######################## + + self.slot_array_linear_label = QtWidgets.QLabel('%s:' % _('Linear Slot Array')) + grid0.addWidget(self.slot_array_linear_label, 14, 0, 1, 2) + + # Number of slot holes in a drill array + self.slot_array_size_label = QtWidgets.QLabel('%s:' % _('Nr of slots')) + self.drill_array_size_label.setToolTip( + _("Specify how many slots to be in the array.") + ) + # self.slot_array_size_label.setMinimumWidth(100) + + self.slot_array_size_entry = FCSpinner() + self.slot_array_size_entry.set_range(0, 999999) + + grid0.addWidget(self.slot_array_size_label, 15, 0) + grid0.addWidget(self.slot_array_size_entry, 15, 1) + + # Linear Slot Array direction + self.slot_array_axis_label = QtWidgets.QLabel('%s:' % _('Linear Direction')) + self.slot_array_axis_label.setToolTip( + _("Direction on which the linear array is oriented:\n" + "- 'X' - horizontal axis \n" + "- 'Y' - vertical axis or \n" + "- 'Angle' - a custom angle for the array inclination") + ) + # self.slot_axis_label.setMinimumWidth(100) + self.slot_array_axis_radio = RadioSet([{'label': _('X'), 'value': 'X'}, + {'label': _('Y'), 'value': 'Y'}, + {'label': _('Angle'), 'value': 'A'}]) + + grid0.addWidget(self.slot_array_axis_label, 16, 0) + grid0.addWidget(self.slot_array_axis_radio, 16, 1) + + # Linear Slot Array pitch distance + self.slot_array_pitch_label = QtWidgets.QLabel('%s:' % _('Pitch')) + self.slot_array_pitch_label.setToolTip( + _("Pitch = Distance between elements of the array.") + ) + # self.drill_pitch_label.setMinimumWidth(100) + self.slot_array_pitch_entry = FCDoubleSpinner() + self.slot_array_pitch_entry.set_precision(self.decimals) + self.slot_array_pitch_entry.setWrapping(True) + self.slot_array_pitch_entry.setRange(0, 999999) + self.slot_array_pitch_entry.setSingleStep(1) + + grid0.addWidget(self.slot_array_pitch_label, 17, 0) + grid0.addWidget(self.slot_array_pitch_entry, 17, 1) + + # Linear Slot Array custom angle + self.slot_array_angle_label = QtWidgets.QLabel('%s:' % _('Angle')) + self.slot_array_angle_label.setToolTip( + _("Angle at which each element in circular array is placed.") + ) + self.slot_array_angle_entry = FCDoubleSpinner() + self.slot_array_angle_entry.set_precision(self.decimals) + self.slot_array_angle_entry.setWrapping(True) + self.slot_array_angle_entry.setRange(-360, 360) + self.slot_array_angle_entry.setSingleStep(5) + + grid0.addWidget(self.slot_array_angle_label, 18, 0) + grid0.addWidget(self.slot_array_angle_entry, 18, 1) + + self.slot_array_circ_label = QtWidgets.QLabel('%s:' % _('Circular Slot Array')) + grid0.addWidget(self.slot_array_circ_label, 19, 0, 1, 2) + + # Circular Slot Array direction + self.slot_array_circular_direction_label = QtWidgets.QLabel('%s:' % _('Circular Direction')) + self.slot_array_circular_direction_label.setToolTip( + _("Direction for circular array.\n" + "Can be CW = clockwise or CCW = counter clockwise.") + ) + + self.slot_array_circular_dir_radio = RadioSet([{'label': _('CW'), 'value': 'CW'}, + {'label': _('CCW'), 'value': 'CCW'}]) + + grid0.addWidget(self.slot_array_circular_direction_label, 20, 0) + grid0.addWidget(self.slot_array_circular_dir_radio, 20, 1) + + # Circular Slot Array Angle + self.slot_array_circular_angle_label = QtWidgets.QLabel('%s:' % _('Circular Angle')) + self.slot_array_circular_angle_label.setToolTip( + _("Angle at which each element in circular array is placed.") + ) + self.slot_array_circular_angle_entry = FCDoubleSpinner() + self.slot_array_circular_angle_entry.set_precision(self.decimals) + self.slot_array_circular_angle_entry.setWrapping(True) + self.slot_array_circular_angle_entry.setRange(-360, 360) + self.slot_array_circular_angle_entry.setSingleStep(5) + + grid0.addWidget(self.slot_array_circular_angle_label, 21, 0) + grid0.addWidget(self.slot_array_circular_angle_entry, 21, 1) + + self.layout.addStretch() diff --git a/flatcamGUI/preferences/excellon/ExcellonExpPrefGroupUI.py b/flatcamGUI/preferences/excellon/ExcellonExpPrefGroupUI.py index 52905e30..db2e922a 100644 --- a/flatcamGUI/preferences/excellon/ExcellonExpPrefGroupUI.py +++ b/flatcamGUI/preferences/excellon/ExcellonExpPrefGroupUI.py @@ -1,86 +1,168 @@ -from flatcamGUI.preferences.OptionUI import * -from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI2 +from PyQt5 import QtWidgets, QtCore +from PyQt5.QtCore import QSettings +from flatcamGUI.GUIElements import RadioSet, FCSpinner +from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI import gettext import FlatCAMTranslation as fcTranslate import builtins + fcTranslate.apply_language('strings') if '_' not in builtins.__dict__: _ = gettext.gettext +settings = QSettings("Open Source", "FlatCAM") +if settings.contains("machinist"): + machinist_setting = settings.value('machinist', type=int) +else: + machinist_setting = 0 -class ExcellonExpPrefGroupUI(OptionsGroupUI2): - def __init__(self, decimals=4, **kwargs): - self.decimals = decimals - super().__init__(**kwargs) +class ExcellonExpPrefGroupUI(OptionsGroupUI): + + def __init__(self, decimals=4, parent=None): + super(ExcellonExpPrefGroupUI, self).__init__(self, parent=parent) + self.setTitle(str(_("Excellon Export"))) + self.decimals = decimals - self.option_dict()["excellon_exp_format"].get_field().activated_custom.connect(self.optimization_selection) + # Plot options + self.export_options_label = QtWidgets.QLabel("%s:" % _("Export Options")) + self.export_options_label.setToolTip( + _("The parameters set here are used in the file exported\n" + "when using the File -> Export -> Export Excellon menu entry.") + ) + self.layout.addWidget(self.export_options_label) - def build_options(self) -> [OptionUI]: - return [ - HeadingOptionUI( - label_text="Export Options", - label_tooltip="The parameters set here are used in the file exported\n" - "when using the File -> Export -> Export Excellon menu entry." - ), - RadioSetOptionUI( - option="excellon_exp_units", - label_text="Units", - label_tooltip="The units used in the Excellon file.", - choices=[{'label': _('INCH'), 'value': 'INCH'}, - {'label': _('MM'), 'value': 'METRIC'}] - ), - SpinnerOptionUI( - option="excellon_exp_integer", - label_text="Int", - label_tooltip="This number signifies the number of digits in\nthe whole part of Excellon coordinates.", - min_value=0, max_value=9, step=1 - ), - SpinnerOptionUI( - option="excellon_exp_decimals", - label_text="Decimals", - label_tooltip="This number signifies the number of digits in\nthe decimal part of Excellon coordinates.", - min_value=0, max_value=9, step=1 - ), - RadioSetOptionUI( - option="excellon_exp_format", - label_text="Format", - label_tooltip="Select the kind of coordinates format used.\n" - "Coordinates can be saved with decimal point or without.\n" - "When there is no decimal point, it is required to specify\n" - "the number of digits for integer part and the number of decimals.\n" - "Also it will have to be specified if LZ = leading zeros are kept\n" - "or TZ = trailing zeros are kept.", - choices=[{'label': _('Decimal'), 'value': 'dec'}, - {'label': _('No-Decimal'), 'value': 'ndec'}] - ), - RadioSetOptionUI( - option="excellon_exp_zeros", - label_text="Zeros", - label_tooltip="This sets the type of Excellon zeros.\n" - "If LZ then Leading Zeros are kept and\n" - "Trailing Zeros are removed.\n" - "If TZ is checked then Trailing Zeros are kept\n" - "and Leading Zeros are removed.", - choices=[{'label': _('LZ'), 'value': 'LZ'}, - {'label': _('TZ'), 'value': 'TZ'}] - ), - RadioSetOptionUI( - option="excellon_exp_slot_type", - label_text="Slot type", - label_tooltip="This sets how the slots will be exported.\n" - "If ROUTED then the slots will be routed\n" - "using M15/M16 commands.\n" - "If DRILLED(G85) the slots will be exported\n" - "using the Drilled slot command (G85).", - choices=[{'label': _('Routed'), 'value': 'routing'}, - {'label': _('Drilled(G85)'), 'value': 'drilling'}] - ) - ] + form = QtWidgets.QFormLayout() + self.layout.addLayout(form) + + # Excellon Units + self.excellon_units_label = QtWidgets.QLabel('%s:' % _('Units')) + self.excellon_units_label.setToolTip( + _("The units used in the Excellon file.") + ) + + self.excellon_units_radio = RadioSet([{'label': _('INCH'), 'value': 'INCH'}, + {'label': _('MM'), 'value': 'METRIC'}]) + self.excellon_units_radio.setToolTip( + _("The units used in the Excellon file.") + ) + + form.addRow(self.excellon_units_label, self.excellon_units_radio) + + # Excellon non-decimal format + self.digits_label = QtWidgets.QLabel("%s:" % _("Int/Decimals")) + self.digits_label.setToolTip( + _("The NC drill files, usually named Excellon files\n" + "are files that can be found in different formats.\n" + "Here we set the format used when the provided\n" + "coordinates are not using period.") + ) + + hlay1 = QtWidgets.QHBoxLayout() + + self.format_whole_entry = FCSpinner() + self.format_whole_entry.set_range(0, 9) + self.format_whole_entry.setMinimumWidth(30) + self.format_whole_entry.setToolTip( + _("This numbers signify the number of digits in\n" + "the whole part of Excellon coordinates.") + ) + hlay1.addWidget(self.format_whole_entry, QtCore.Qt.AlignLeft) + + excellon_separator_label = QtWidgets.QLabel(':') + excellon_separator_label.setFixedWidth(5) + hlay1.addWidget(excellon_separator_label, QtCore.Qt.AlignLeft) + + self.format_dec_entry = FCSpinner() + self.format_dec_entry.set_range(0, 9) + self.format_dec_entry.setMinimumWidth(30) + self.format_dec_entry.setToolTip( + _("This numbers signify the number of digits in\n" + "the decimal part of Excellon coordinates.") + ) + hlay1.addWidget(self.format_dec_entry, QtCore.Qt.AlignLeft) + hlay1.addStretch() + + form.addRow(self.digits_label, hlay1) + + # Select the Excellon Format + self.format_label = QtWidgets.QLabel("%s:" % _("Format")) + self.format_label.setToolTip( + _("Select the kind of coordinates format used.\n" + "Coordinates can be saved with decimal point or without.\n" + "When there is no decimal point, it is required to specify\n" + "the number of digits for integer part and the number of decimals.\n" + "Also it will have to be specified if LZ = leading zeros are kept\n" + "or TZ = trailing zeros are kept.") + ) + self.format_radio = RadioSet([{'label': _('Decimal'), 'value': 'dec'}, + {'label': _('No-Decimal'), 'value': 'ndec'}]) + self.format_radio.setToolTip( + _("Select the kind of coordinates format used.\n" + "Coordinates can be saved with decimal point or without.\n" + "When there is no decimal point, it is required to specify\n" + "the number of digits for integer part and the number of decimals.\n" + "Also it will have to be specified if LZ = leading zeros are kept\n" + "or TZ = trailing zeros are kept.") + ) + + form.addRow(self.format_label, self.format_radio) + + # Excellon Zeros + self.zeros_label = QtWidgets.QLabel('%s:' % _('Zeros')) + self.zeros_label.setAlignment(QtCore.Qt.AlignLeft) + self.zeros_label.setToolTip( + _("This sets the type of Excellon zeros.\n" + "If LZ then Leading Zeros are kept and\n" + "Trailing Zeros are removed.\n" + "If TZ is checked then Trailing Zeros are kept\n" + "and Leading Zeros are removed.") + ) + + self.zeros_radio = RadioSet([{'label': _('LZ'), 'value': 'LZ'}, + {'label': _('TZ'), 'value': 'TZ'}]) + self.zeros_radio.setToolTip( + _("This sets the default type of Excellon zeros.\n" + "If LZ then Leading Zeros are kept and\n" + "Trailing Zeros are removed.\n" + "If TZ is checked then Trailing Zeros are kept\n" + "and Leading Zeros are removed.") + ) + + form.addRow(self.zeros_label, self.zeros_radio) + + # Slot type + self.slot_type_label = QtWidgets.QLabel('%s:' % _('Slot type')) + self.slot_type_label.setAlignment(QtCore.Qt.AlignLeft) + self.slot_type_label.setToolTip( + _("This sets how the slots will be exported.\n" + "If ROUTED then the slots will be routed\n" + "using M15/M16 commands.\n" + "If DRILLED(G85) the slots will be exported\n" + "using the Drilled slot command (G85).") + ) + + self.slot_type_radio = RadioSet([{'label': _('Routed'), 'value': 'routing'}, + {'label': _('Drilled(G85)'), 'value': 'drilling'}]) + self.slot_type_radio.setToolTip( + _("This sets how the slots will be exported.\n" + "If ROUTED then the slots will be routed\n" + "using M15/M16 commands.\n" + "If DRILLED(G85) the slots will be exported\n" + "using the Drilled slot command (G85).") + ) + + form.addRow(self.slot_type_label, self.slot_type_radio) + + self.layout.addStretch() + self.format_radio.activated_custom.connect(self.optimization_selection) def optimization_selection(self): - disable_zeros = self.option_dict()["excellon_exp_format"].get_field().get_value() == "dec" - self.option_dict()["excellon_exp_zeros"].label_widget.setDisabled(disable_zeros) - self.option_dict()["excellon_exp_zeros"].get_field().setDisabled(disable_zeros) + if self.format_radio.get_value() == 'dec': + self.zeros_label.setDisabled(True) + self.zeros_radio.setDisabled(True) + else: + self.zeros_label.setDisabled(False) + self.zeros_radio.setDisabled(False) diff --git a/flatcamGUI/preferences/excellon/ExcellonGenPrefGroupUI.py b/flatcamGUI/preferences/excellon/ExcellonGenPrefGroupUI.py index 91b3dcde..06d4dfc7 100644 --- a/flatcamGUI/preferences/excellon/ExcellonGenPrefGroupUI.py +++ b/flatcamGUI/preferences/excellon/ExcellonGenPrefGroupUI.py @@ -1,199 +1,415 @@ import platform -from flatcamGUI.preferences.OptionUI import * -from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI2 +from PyQt5 import QtWidgets, QtCore, QtGui +from PyQt5.QtCore import QSettings + +from flatcamGUI.GUIElements import FCCheckBox, FCSpinner, RadioSet, FCEntry +from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI import gettext import FlatCAMTranslation as fcTranslate import builtins + fcTranslate.apply_language('strings') if '_' not in builtins.__dict__: _ = gettext.gettext +settings = QSettings("Open Source", "FlatCAM") +if settings.contains("machinist"): + machinist_setting = settings.value('machinist', type=int) +else: + machinist_setting = 0 -class ExcellonGenPrefGroupUI(OptionsGroupUI2): - def __init__(self, decimals=4, **kwargs): - self.decimals = decimals - super().__init__(**kwargs) +class ExcellonGenPrefGroupUI(OptionsGroupUI): + + def __init__(self, decimals=4, parent=None): + # OptionsGroupUI.__init__(self, "Excellon Options", parent=parent) + super(ExcellonGenPrefGroupUI, self).__init__(self, parent=parent) + self.setTitle(str(_("Excellon General"))) + self.decimals = decimals - # disable the Excellon path optimizations made with Google OR-Tools if the app is run on a 32bit platform - if platform.architecture()[0] != '64bit': - self.option_dict()["excellon_optimization_type"].get_field().set_value('T') - self.option_dict()["excellon_optimization_type"].get_field().setDisabled(True) - self.option_dict()["excellon_optimization_type"].label_widget.setDisabled(True) + # Plot options + self.plot_options_label = QtWidgets.QLabel("%s:" % _("Plot Options")) + self.layout.addWidget(self.plot_options_label) - # Enable/disable the duration box according to type selected - self.option_dict()["excellon_optimization_type"].get_field().activated_custom.connect(self.optimization_selection) - self.optimization_selection() + grid1 = QtWidgets.QGridLayout() + self.layout.addLayout(grid1) + + self.plot_cb = FCCheckBox(label=_('Plot')) + self.plot_cb.setToolTip( + "Plot (show) this object." + ) + grid1.addWidget(self.plot_cb, 0, 0) + + self.solid_cb = FCCheckBox(label=_('Solid')) + self.solid_cb.setToolTip( + "Plot as solid circles." + ) + grid1.addWidget(self.solid_cb, 0, 1) + + separator_line = QtWidgets.QFrame() + separator_line.setFrameShape(QtWidgets.QFrame.HLine) + separator_line.setFrameShadow(QtWidgets.QFrame.Sunken) + grid1.addWidget(separator_line, 1, 0, 1, 2) + + grid2 = QtWidgets.QGridLayout() + self.layout.addLayout(grid2) + grid2.setColumnStretch(0, 0) + grid2.setColumnStretch(1, 1) + + # Excellon format + self.excellon_format_label = QtWidgets.QLabel("%s:" % _("Excellon Format")) + self.excellon_format_label.setToolTip( + _("The NC drill files, usually named Excellon files\n" + "are files that can be found in different formats.\n" + "Here we set the format used when the provided\n" + "coordinates are not using period.\n" + "\n" + "Possible presets:\n" + "\n" + "PROTEUS 3:3 MM LZ\n" + "DipTrace 5:2 MM TZ\n" + "DipTrace 4:3 MM LZ\n" + "\n" + "EAGLE 3:3 MM TZ\n" + "EAGLE 4:3 MM TZ\n" + "EAGLE 2:5 INCH TZ\n" + "EAGLE 3:5 INCH TZ\n" + "\n" + "ALTIUM 2:4 INCH LZ\n" + "Sprint Layout 2:4 INCH LZ" + "\n" + "KiCAD 3:5 INCH TZ") + ) + grid2.addWidget(self.excellon_format_label, 0, 0, 1, 2) + + self.excellon_format_in_label = QtWidgets.QLabel('%s:' % _("INCH")) + self.excellon_format_in_label.setToolTip(_("Default values for INCH are 2:4")) + + hlay1 = QtWidgets.QHBoxLayout() + self.excellon_format_upper_in_entry = FCSpinner() + self.excellon_format_upper_in_entry.set_range(0, 9) + self.excellon_format_upper_in_entry.setMinimumWidth(30) + self.excellon_format_upper_in_entry.setToolTip( + _("This numbers signify the number of digits in\n" + "the whole part of Excellon coordinates.") + ) + hlay1.addWidget(self.excellon_format_upper_in_entry) + + excellon_separator_in_label = QtWidgets.QLabel(':') + excellon_separator_in_label.setFixedWidth(5) + hlay1.addWidget(excellon_separator_in_label) + + self.excellon_format_lower_in_entry = FCSpinner() + self.excellon_format_lower_in_entry.set_range(0, 9) + self.excellon_format_lower_in_entry.setMinimumWidth(30) + self.excellon_format_lower_in_entry.setToolTip( + _("This numbers signify the number of digits in\n" + "the decimal part of Excellon coordinates.") + ) + hlay1.addWidget(self.excellon_format_lower_in_entry) + + grid2.addWidget(self.excellon_format_in_label, 1, 0) + grid2.addLayout(hlay1, 1, 1) + + self.excellon_format_mm_label = QtWidgets.QLabel('%s:' % _("METRIC")) + self.excellon_format_mm_label.setToolTip(_("Default values for METRIC are 3:3")) + + hlay2 = QtWidgets.QHBoxLayout() + self.excellon_format_upper_mm_entry = FCSpinner() + self.excellon_format_upper_mm_entry.set_range(0, 9) + self.excellon_format_upper_mm_entry.setMinimumWidth(30) + self.excellon_format_upper_mm_entry.setToolTip( + _("This numbers signify the number of digits in\n" + "the whole part of Excellon coordinates.") + ) + hlay2.addWidget(self.excellon_format_upper_mm_entry) + + excellon_separator_mm_label = QtWidgets.QLabel(':') + excellon_separator_mm_label.setFixedWidth(5) + hlay2.addWidget(excellon_separator_mm_label, QtCore.Qt.AlignLeft) + + self.excellon_format_lower_mm_entry = FCSpinner() + self.excellon_format_lower_mm_entry.set_range(0, 9) + self.excellon_format_lower_mm_entry.setMinimumWidth(30) + self.excellon_format_lower_mm_entry.setToolTip( + _("This numbers signify the number of digits in\n" + "the decimal part of Excellon coordinates.") + ) + hlay2.addWidget(self.excellon_format_lower_mm_entry) + + grid2.addWidget(self.excellon_format_mm_label, 2, 0) + grid2.addLayout(hlay2, 2, 1) + + self.excellon_zeros_label = QtWidgets.QLabel('%s:' % _('Zeros')) + self.excellon_zeros_label.setAlignment(QtCore.Qt.AlignLeft) + self.excellon_zeros_label.setToolTip( + _("This sets the type of Excellon zeros.\n" + "If LZ then Leading Zeros are kept and\n" + "Trailing Zeros are removed.\n" + "If TZ is checked then Trailing Zeros are kept\n" + "and Leading Zeros are removed.\n\n" + "This is used when there is no information\n" + "stored in the Excellon file.") + ) + grid2.addWidget(self.excellon_zeros_label, 3, 0) + + self.excellon_zeros_radio = RadioSet([{'label': _('LZ'), 'value': 'L'}, + {'label': _('TZ'), 'value': 'T'}]) + + grid2.addWidget(self.excellon_zeros_radio, 3, 1) + + self.excellon_units_label = QtWidgets.QLabel('%s:' % _('Units')) + self.excellon_units_label.setAlignment(QtCore.Qt.AlignLeft) + self.excellon_units_label.setToolTip( + _("This sets the default units of Excellon files.\n" + "If it is not detected in the parsed file the value here\n" + "will be used." + "Some Excellon files don't have an header\n" + "therefore this parameter will be used.") + ) + + self.excellon_units_radio = RadioSet([{'label': _('INCH'), 'value': 'INCH'}, + {'label': _('MM'), 'value': 'METRIC'}]) + self.excellon_units_radio.setToolTip( + _("This sets the units of Excellon files.\n" + "Some Excellon files don't have an header\n" + "therefore this parameter will be used.") + ) + + grid2.addWidget(self.excellon_units_label, 4, 0) + grid2.addWidget(self.excellon_units_radio, 4, 1) + + self.update_excellon_cb = FCCheckBox(label=_('Update Export settings')) + self.update_excellon_cb.setToolTip( + "If checked, the Excellon Export settings will be updated with the ones above." + ) + grid2.addWidget(self.update_excellon_cb, 5, 0, 1, 2) + + # Adding the Excellon Format Defaults Button + self.excellon_defaults_button = QtWidgets.QPushButton() + self.excellon_defaults_button.setText(str(_("Restore Defaults"))) + self.excellon_defaults_button.setMinimumWidth(80) + grid2.addWidget(self.excellon_defaults_button, 6, 0, 1, 2) + + separator_line = QtWidgets.QFrame() + separator_line.setFrameShape(QtWidgets.QFrame.HLine) + separator_line.setFrameShadow(QtWidgets.QFrame.Sunken) + grid2.addWidget(separator_line, 7, 0, 1, 2) + + self.excellon_general_label = QtWidgets.QLabel("%s:" % _("Excellon Optimization")) + grid2.addWidget(self.excellon_general_label, 8, 0, 1, 2) + + self.excellon_optimization_label = QtWidgets.QLabel(_('Algorithm:')) + self.excellon_optimization_label.setToolTip( + _("This sets the optimization type for the Excellon drill path.\n" + "If <> is checked then Google OR-Tools algorithm with\n" + "MetaHeuristic Guided Local Path is used. Default search time is 3sec.\n" + "If <> is checked then Google OR-Tools Basic algorithm is used.\n" + "If <> is checked then Travelling Salesman algorithm is used for\n" + "drill path optimization.\n" + "\n" + "If this control is disabled, then FlatCAM works in 32bit mode and it uses\n" + "Travelling Salesman algorithm for path optimization.") + ) + + self.excellon_optimization_radio = RadioSet([{'label': _('MetaHeuristic'), 'value': 'M'}, + {'label': _('Basic'), 'value': 'B'}, + {'label': _('TSA'), 'value': 'T'}], + orientation='vertical', stretch=False) + self.excellon_optimization_radio.setToolTip( + _("This sets the optimization type for the Excellon drill path.\n" + "If <> is checked then Google OR-Tools algorithm with\n" + "MetaHeuristic Guided Local Path is used. Default search time is 3sec.\n" + "If <> is checked then Google OR-Tools Basic algorithm is used.\n" + "If <> is checked then Travelling Salesman algorithm is used for\n" + "drill path optimization.\n" + "\n" + "If this control is disabled, then FlatCAM works in 32bit mode and it uses\n" + "Travelling Salesman algorithm for path optimization.") + ) + + grid2.addWidget(self.excellon_optimization_label, 9, 0) + grid2.addWidget(self.excellon_optimization_radio, 9, 1) + + self.optimization_time_label = QtWidgets.QLabel('%s:' % _('Duration')) + self.optimization_time_label.setAlignment(QtCore.Qt.AlignLeft) + self.optimization_time_label.setToolTip( + _("When OR-Tools Metaheuristic (MH) is enabled there is a\n" + "maximum threshold for how much time is spent doing the\n" + "path optimization. This max duration is set here.\n" + "In seconds.") + + ) + + self.optimization_time_entry = FCSpinner() + self.optimization_time_entry.set_range(0, 999) + + grid2.addWidget(self.optimization_time_label, 10, 0) + grid2.addWidget(self.optimization_time_entry, 10, 1) + + separator_line = QtWidgets.QFrame() + separator_line.setFrameShape(QtWidgets.QFrame.HLine) + separator_line.setFrameShadow(QtWidgets.QFrame.Sunken) + grid2.addWidget(separator_line, 11, 0, 1, 2) + + # Excellon Object Color + self.gerber_color_label = QtWidgets.QLabel('%s' % _('Excellon Object Color')) + grid2.addWidget(self.gerber_color_label, 12, 0, 1, 2) + + # Plot Line Color + self.line_color_label = QtWidgets.QLabel('%s:' % _('Outline')) + self.line_color_label.setToolTip( + _("Set the line color for plotted objects.") + ) + self.line_color_entry = FCEntry() + self.line_color_button = QtWidgets.QPushButton() + self.line_color_button.setFixedSize(15, 15) + + self.form_box_child_2 = QtWidgets.QHBoxLayout() + self.form_box_child_2.addWidget(self.line_color_entry) + self.form_box_child_2.addWidget(self.line_color_button) + self.form_box_child_2.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter) + + grid2.addWidget(self.line_color_label, 13, 0) + grid2.addLayout(self.form_box_child_2, 13, 1) + + # Plot Fill Color + self.fill_color_label = QtWidgets.QLabel('%s:' % _('Fill')) + self.fill_color_label.setToolTip( + _("Set the fill color for plotted objects.\n" + "First 6 digits are the color and the last 2\n" + "digits are for alpha (transparency) level.") + ) + self.fill_color_entry = FCEntry() + self.fill_color_button = QtWidgets.QPushButton() + self.fill_color_button.setFixedSize(15, 15) + + self.form_box_child_1 = QtWidgets.QHBoxLayout() + self.form_box_child_1.addWidget(self.fill_color_entry) + self.form_box_child_1.addWidget(self.fill_color_button) + self.form_box_child_1.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter) + + grid2.addWidget(self.fill_color_label, 14, 0) + grid2.addLayout(self.form_box_child_1, 14, 1) + + # Plot Fill Transparency Level + self.alpha_label = QtWidgets.QLabel('%s:' % _('Alpha')) + self.alpha_label.setToolTip( + _("Set the fill transparency for plotted objects.") + ) + self.color_alpha_slider = QtWidgets.QSlider(QtCore.Qt.Horizontal) + self.color_alpha_slider.setMinimum(0) + self.color_alpha_slider.setMaximum(255) + self.color_alpha_slider.setSingleStep(1) + + self.color_alpha_spinner = FCSpinner() + self.color_alpha_spinner.setMinimumWidth(70) + self.color_alpha_spinner.set_range(0, 255) + + self.form_box_child_3 = QtWidgets.QHBoxLayout() + self.form_box_child_3.addWidget(self.color_alpha_slider) + self.form_box_child_3.addWidget(self.color_alpha_spinner) + + grid2.addWidget(self.alpha_label, 15, 0) + grid2.addLayout(self.form_box_child_3, 15, 1) + + self.layout.addStretch() + + current_platform = platform.architecture()[0] + if current_platform == '64bit': + self.excellon_optimization_label.setDisabled(False) + self.excellon_optimization_radio.setDisabled(False) + self.optimization_time_label.setDisabled(False) + self.optimization_time_entry.setDisabled(False) + self.excellon_optimization_radio.activated_custom.connect(self.optimization_selection) + + else: + self.excellon_optimization_label.setDisabled(True) + self.excellon_optimization_radio.setDisabled(True) + self.optimization_time_label.setDisabled(True) + self.optimization_time_entry.setDisabled(True) + + # Setting plot colors signals + self.line_color_entry.editingFinished.connect(self.on_line_color_entry) + self.line_color_button.clicked.connect(self.on_line_color_button) + self.fill_color_entry.editingFinished.connect(self.on_fill_color_entry) + self.fill_color_button.clicked.connect(self.on_fill_color_button) + self.color_alpha_spinner.valueChanged.connect(self.on_color_spinner) + self.color_alpha_slider.valueChanged.connect(self.on_color_slider) # Load the defaults values into the Excellon Format and Excellon Zeros fields - self.option_dict()["__excellon_restore_defaults"].get_field().clicked.connect(self.on_defaults_button) - - - def build_options(self) -> [OptionUI]: - return [ - HeadingOptionUI(label_text="Plot Options"), - CheckboxOptionUI( - option="excellon_plot", - label_text="Plot", - label_tooltip="Plot (show) this object." - ), - CheckboxOptionUI( - option="excellon_solid", - label_text="Solid", - label_tooltip="Plot as solid circles." - ), - SeparatorOptionUI(), - - HeadingOptionUI( - label_text="Excellon Format", - label_tooltip="The NC drill files, usually named Excellon files\n" - "are files that can be found in different formats.\n" - "Here we set the format used when the provided\n" - "coordinates are not using period.\n" - "\n" - "Possible presets:\n" - "\n" - "PROTEUS 3:3 MM LZ\n" - "DipTrace 5:2 MM TZ\n" - "DipTrace 4:3 MM LZ\n" - "\n" - "EAGLE 3:3 MM TZ\n" - "EAGLE 4:3 MM TZ\n" - "EAGLE 2:5 INCH TZ\n" - "EAGLE 3:5 INCH TZ\n" - "\n" - "ALTIUM 2:4 INCH LZ\n" - "Sprint Layout 2:4 INCH LZ" - "\n" - "KiCAD 3:5 INCH TZ" - ), - SpinnerOptionUI( - option="excellon_format_upper_in", - label_text="INCH int", - label_tooltip="This number signifies the number of digits in\nthe whole part of Excellon coordinates.", - min_value=0, max_value=9, step=1 - ), - SpinnerOptionUI( - option="excellon_format_lower_in", - label_text="INCH decimals", - label_tooltip="This number signifies the number of digits in\nthe decimal part of Excellon coordinates.", - min_value=0, max_value=9, step=1 - ), - SpinnerOptionUI( - option="excellon_format_upper_mm", - label_text="METRIC int", - label_tooltip="This number signifies the number of digits in\nthe whole part of Excellon coordinates.", - min_value=0, max_value=9, step=1 - ), - SpinnerOptionUI( - option="excellon_format_lower_mm", - label_text="METRIC decimals", - label_tooltip="This number signifies the number of digits in\nthe decimal part of Excellon coordinates.", - min_value=0, max_value=9, step=1 - ), - RadioSetOptionUI( - option="excellon_zeros", - label_text="Zeros", - label_tooltip="This sets the type of Excellon zeros.\n" - "If LZ then Leading Zeros are kept and\n" - "Trailing Zeros are removed.\n" - "If TZ is checked then Trailing Zeros are kept\n" - "and Leading Zeros are removed.\n\n" - "This is used when there is no information\n" - "stored in the Excellon file.", - choices=[ - {'label': _('LZ'), 'value': 'L'}, - {'label': _('TZ'), 'value': 'T'} - ] - ), - RadioSetOptionUI( - option="excellon_units", - label_text="Units", - label_tooltip="This sets the default units of Excellon files.\n" - "If it is not detected in the parsed file the value here\n" - "will be used." - "Some Excellon files don't have an header\n" - "therefore this parameter will be used.", - choices=[ - {'label': _('INCH'), 'value': 'INCH'}, - {'label': _('MM'), 'value': 'METRIC'} - ] - ), - CheckboxOptionUI( - option="excellon_update", - label_text="Update Export settings", - label_tooltip="If checked, the Excellon Export settings will be updated with the ones above." - ), - FullWidthButtonOptionUI( - option="__excellon_restore_defaults", - label_text="Restore Defaults", - label_tooltip=None - ), - SeparatorOptionUI(), - - HeadingOptionUI(label_text="Excellon Optimization"), - RadioSetOptionUI( - option="excellon_optimization_type", - label_text="Algorithm", - label_tooltip="This sets the optimization type for the Excellon drill path.\n" - "If <> is checked then Google OR-Tools algorithm with\n" - "MetaHeuristic Guided Local Path is used. Default search time is 3sec.\n" - "If <> is checked then Google OR-Tools Basic algorithm is used.\n" - "If <> is checked then Travelling Salesman algorithm is used for\n" - "drill path optimization.\n" - "\n" - "If this control is disabled, then FlatCAM works in 32bit mode and it uses\n" - "Travelling Salesman algorithm for path optimization.", - choices=[ - {'label': _('MetaHeuristic'), 'value': 'M'}, - {'label': _('Basic'), 'value': 'B'}, - {'label': _('TSA'), 'value': 'T'} - ], - orientation="vertical" - ), - SpinnerOptionUI( - option="excellon_search_time", - label_text="Duration", - label_tooltip="When OR-Tools Metaheuristic (MH) is enabled there is a\n" - "maximum threshold for how much time is spent doing the\n" - "path optimization. This max duration is set here.\n" - "In seconds.", - min_value=1, max_value=999, step=1 - ), - SeparatorOptionUI(), - - HeadingOptionUI(label_text="Excellon Object Color"), - ColorOptionUI( - option="excellon_plot_line", - label_text="Outline", - label_tooltip="Set the line color for plotted objects.", - ), - ColorOptionUI( - option="excellon_plot_fill", - label_text="Fill", - label_tooltip="Set the fill color for plotted objects.\n" - "First 6 digits are the color and the last 2\n" - "digits are for alpha (transparency) level." - ), - ColorAlphaSliderOptionUI( - applies_to=["excellon_plot_line", "excellon_plot_fill"], - group=self, - label_text="Alpha", - label_tooltip="Set the transparency for plotted objects." - ) - ] + self.excellon_defaults_button.clicked.connect(self.on_excellon_defaults_button) def optimization_selection(self): - disable_time = (self.option_dict()["excellon_optimization_type"].get_field().get_value() != 'M') - self.option_dict()["excellon_search_time"].label_widget.setDisabled(disable_time) - self.option_dict()["excellon_search_time"].get_field().setDisabled(disable_time) + if self.excellon_optimization_radio.get_value() == 'M': + self.optimization_time_label.setDisabled(False) + self.optimization_time_entry.setDisabled(False) + else: + self.optimization_time_label.setDisabled(True) + self.optimization_time_entry.setDisabled(True) - def on_defaults_button(self): - self.option_dict()["excellon_format_lower_in"].get_field().set_value('4') - self.option_dict()["excellon_format_upper_in"].get_field().set_value('2') - self.option_dict()["excellon_format_lower_mm"].get_field().set_value('3') - self.option_dict()["excellon_format_upper_mm"].get_field().set_value('3') - self.option_dict()["excellon_zeros"].get_field().set_value('L') - self.option_dict()["excellon_units"].get_field().set_value('INCH') + # Setting plot colors handlers + def on_fill_color_entry(self): + self.app.defaults['excellon_plot_fill'] = self.fill_color_entry.get_value()[:7] + \ + self.app.defaults['excellon_plot_fill'][7:9] + self.fill_color_button.setStyleSheet("background-color:%s" % str(self.app.defaults['excellon_plot_fill'])[:7]) + + def on_fill_color_button(self): + current_color = QtGui.QColor(self.app.defaults['excellon_plot_fill'][:7]) + + c_dialog = QtWidgets.QColorDialog() + plot_fill_color = c_dialog.getColor(initial=current_color) + + if plot_fill_color.isValid() is False: + return + + self.fill_color_button.setStyleSheet("background-color:%s" % str(plot_fill_color.name())) + + new_val = str(plot_fill_color.name()) + str(self.app.defaults['excellon_plot_fill'][7:9]) + self.fill_color_entry.set_value(new_val) + self.app.defaults['excellon_plot_fill'] = new_val + + def on_color_spinner(self): + spinner_value = self.color_alpha_spinner.value() + self.color_alpha_slider.setValue(spinner_value) + self.app.defaults['excellon_plot_fill'] = \ + self.app.defaults['excellon_plot_fill'][:7] + \ + (hex(spinner_value)[2:] if int(hex(spinner_value)[2:], 16) > 0 else '00') + self.app.defaults['excellon_plot_line'] = \ + self.app.defaults['excellon_plot_line'][:7] + \ + (hex(spinner_value)[2:] if int(hex(spinner_value)[2:], 16) > 0 else '00') + + def on_color_slider(self): + slider_value = self.color_alpha_slider.value() + self.color_alpha_spinner.setValue(slider_value) + + def on_line_color_entry(self): + self.app.defaults['excellon_plot_line'] = self.line_color_entry.get_value()[:7] + \ + self.app.defaults['excellon_plot_line'][7:9] + self.line_color_button.setStyleSheet("background-color:%s" % str(self.app.defaults['excellon_plot_line'])[:7]) + + def on_line_color_button(self): + current_color = QtGui.QColor(self.app.defaults['excellon_plot_line'][:7]) + # print(current_color) + + c_dialog = QtWidgets.QColorDialog() + plot_line_color = c_dialog.getColor(initial=current_color) + + if plot_line_color.isValid() is False: + return + + self.line_color_button.setStyleSheet("background-color:%s" % str(plot_line_color.name())) + + new_val_line = str(plot_line_color.name()) + str(self.app.defaults['excellon_plot_line'][7:9]) + self.line_color_entry.set_value(new_val_line) + self.app.defaults['excellon_plot_line'] = new_val_line + + def on_excellon_defaults_button(self): + self.app.preferencesUiManager.defaults_form_fields["excellon_format_lower_in"].set_value('4') + self.app.preferencesUiManager.defaults_form_fields["excellon_format_upper_in"].set_value('2') + self.app.preferencesUiManager.defaults_form_fields["excellon_format_lower_mm"].set_value('3') + self.app.preferencesUiManager.defaults_form_fields["excellon_format_upper_mm"].set_value('3') + self.app.preferencesUiManager.defaults_form_fields["excellon_zeros"].set_value('L') + self.app.preferencesUiManager.defaults_form_fields["excellon_units"].set_value('INCH') diff --git a/flatcamGUI/preferences/excellon/ExcellonOptPrefGroupUI.py b/flatcamGUI/preferences/excellon/ExcellonOptPrefGroupUI.py index 4f68eaca..cdc6ce5e 100644 --- a/flatcamGUI/preferences/excellon/ExcellonOptPrefGroupUI.py +++ b/flatcamGUI/preferences/excellon/ExcellonOptPrefGroupUI.py @@ -1,7 +1,10 @@ -from flatcamGUI.GUIElements import OptionalInputSection +from PyQt5 import QtWidgets +from PyQt5.QtCore import Qt, QSettings + +from flatcamGUI.GUIElements import RadioSet, FCDoubleSpinner, FCCheckBox, FCEntry, FCSpinner, OptionalInputSection, \ + FCComboBox from flatcamGUI.preferences import machinist_setting -from flatcamGUI.preferences.OptionUI import * -from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI2 +from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI import gettext import FlatCAMTranslation as fcTranslate import builtins @@ -17,182 +20,298 @@ else: machinist_setting = 0 -class ExcellonOptPrefGroupUI(OptionsGroupUI2): +class ExcellonOptPrefGroupUI(OptionsGroupUI): + + def __init__(self, decimals=4, parent=None): + # OptionsGroupUI.__init__(self, "Excellon Options", parent=parent) + super(ExcellonOptPrefGroupUI, self).__init__(self, parent=parent) - def __init__(self, decimals=4, **kwargs): - self.decimals = decimals - super().__init__(**kwargs) self.setTitle(str(_("Excellon Options"))) + self.decimals = decimals - self.pp_excellon_name_cb = self.option_dict()["excellon_ppname_e"].get_field() + # ## Create CNC Job + self.cncjob_label = QtWidgets.QLabel('%s' % _('Create CNC Job')) + self.cncjob_label.setToolTip( + _("Parameters used to create a CNC Job object\n" + "for this drill object.") + ) + self.layout.addWidget(self.cncjob_label) - self.multidepth_cb = self.option_dict()["excellon_multidepth"].get_field() - self.depthperpass_entry = self.option_dict()["excellon_depthperpass"].get_field() - self.ois_multidepth = OptionalInputSection(self.multidepth_cb, [self.depthperpass_entry]) + grid2 = QtWidgets.QGridLayout() + self.layout.addLayout(grid2) + grid2.setColumnStretch(0, 0) + grid2.setColumnStretch(1, 1) - self.dwell_cb = self.option_dict()["excellon_dwell"].get_field() - self.dwelltime_entry = self.option_dict()["excellon_dwelltime"].get_field() - self.ois_dwell = OptionalInputSection(self.dwell_cb, [self.dwelltime_entry]) + # Operation Type + self.operation_label = QtWidgets.QLabel('%s:' % _('Operation')) + self.operation_label.setToolTip( + _("Operation type:\n" + "- Drilling -> will drill the drills/slots associated with this tool\n" + "- Milling -> will mill the drills/slots") + ) + self.operation_radio = RadioSet( + [ + {'label': _('Drilling'), 'value': 'drill'}, + {'label': _("Milling"), 'value': 'mill'} + ] + ) - # FIXME until this feature is implemented these are disabled - self.option_dict()["excellon_gcode_type"].label_widget.hide() - self.option_dict()["excellon_gcode_type"].get_field().hide() + grid2.addWidget(self.operation_label, 0, 0) + grid2.addWidget(self.operation_radio, 0, 1) - def build_options(self) -> [OptionUI]: - return [ - HeadingOptionUI( - label_text="Create CNC Job", - label_tooltip="Parameters used to create a CNC Job object\n" - "for this drill object." - ), - RadioSetOptionUI( - option="excellon_operation", - label_text="Operation", - label_bold=True, - label_tooltip="Operation type:\n" - "- Drilling -> will drill the drills/slots associated with this tool\n" - "- Milling -> will mill the drills/slots", - choices=[ - {'label': _('Drilling'), 'value': 'drill'}, - {'label': _("Milling"), 'value': 'mill'} - ] - ), - RadioSetOptionUI( - option="excellon_milling_type", - label_text="Milling Type", - label_tooltip="Milling type:\n" - "- Drills -> will mill the drills associated with this tool\n" - "- Slots -> will mill the slots associated with this tool\n" - "- Both -> will mill both drills and mills or whatever is available", - choices=[ - {'label': _('Drills'), 'value': 'drills'}, - {'label': _("Slots"), 'value': 'slots'}, - {'label': _("Both"), 'value': 'both'}, - ] - ), - DoubleSpinnerOptionUI( - option="excellon_milling_dia", - label_text="Milling Diameter", - label_tooltip="The diameter of the tool who will do the milling", - min_value=0.0, max_value=9999.9999, step=0.1, decimals=self.decimals - ), - DoubleSpinnerOptionUI( - option="excellon_cutz", - label_text="Cut Z", - label_tooltip="Drill depth (negative) \nbelow the copper surface.", - min_value=-9999.9999, max_value=(9999.9999 if machinist_setting else 0.0), - step=0.1, decimals=self.decimals - ), + self.mill_type_label = QtWidgets.QLabel('%s:' % _('Milling Type')) + self.mill_type_label.setToolTip( + _("Milling type:\n" + "- Drills -> will mill the drills associated with this tool\n" + "- Slots -> will mill the slots associated with this tool\n" + "- Both -> will mill both drills and mills or whatever is available") + ) + self.milling_type_radio = RadioSet( + [ + {'label': _('Drills'), 'value': 'drills'}, + {'label': _("Slots"), 'value': 'slots'}, + {'label': _("Both"), 'value': 'both'}, + ] + ) + grid2.addWidget(self.mill_type_label, 1, 0) + grid2.addWidget(self.milling_type_radio, 1, 1) - CheckboxOptionUI( - option="excellon_multidepth", - label_text="Multi-Depth", - label_tooltip="Use multiple passes to limit\n" - "the cut depth in each pass. Will\n" - "cut multiple times until Cut Z is\n" - "reached." - ), - DoubleSpinnerOptionUI( - option="excellon_depthperpass", - label_text="Depth/Pass", - label_tooltip="Depth of each pass (positive).", - min_value=0, max_value=99999, step=0.1, decimals=self.decimals - ), - DoubleSpinnerOptionUI( - option="excellon_travelz", - label_text="Travel Z", - label_tooltip="Tool height when travelling\nacross the XY plane.", - min_value=(-9999.9999 if machinist_setting else 0.0001), max_value=9999.9999, - step=0.1, decimals=self.decimals - ), - CheckboxOptionUI( - option="excellon_toolchange", - label_text="Tool change", - label_tooltip="Include tool-change sequence\nin G-Code (Pause for tool change)." - ), - DoubleSpinnerOptionUI( - option="excellon_toolchangez", - label_text="Toolchange Z", - label_tooltip="Z-axis position (height) for\ntool change.", - min_value=(-9999.9999 if machinist_setting else 0.0), max_value=9999.9999, - step=0.1, decimals=self.decimals - ), - DoubleSpinnerOptionUI( - option="excellon_endz", - label_text="End move Z", - label_tooltip="Height of the tool after\nthe last move at the end of the job.", - min_value=(-9999.9999 if machinist_setting else 0.0), max_value=9999.9999, - step=0.1, decimals=self.decimals - ), - LineEntryOptionUI( - option="excellon_endxy", - label_text="End move X,Y", - label_tooltip="End move X,Y position. In format (x,y).\n" - "If no value is entered then there is no move\n" - "on X,Y plane at the end of the job." - ), - DoubleSpinnerOptionUI( - option="excellon_feedrate_z", - label_text="Feedrate Z", - label_tooltip="Tool speed while drilling\n" - "(in units per minute).\n" - "So called 'Plunge' feedrate.\n" - "This is for linear move G01.", - min_value=0, max_value=99999.9999, step=0.1, decimals=self.decimals - ), - SpinnerOptionUI( - option="excellon_spindlespeed", - label_text="Spindle speed", - label_tooltip="Speed of the spindle in RPM (optional).", - min_value=0, max_value=1000000, step=100 - ), - CheckboxOptionUI( - option="excellon_dwell", - label_text="Enable Dwell", - label_tooltip="Pause to allow the spindle to reach its\nspeed before cutting." - ), - DoubleSpinnerOptionUI( - option="excellon_dwelltime", - label_text="Duration", - label_tooltip="Number of time units for spindle to dwell.", - min_value=0, max_value=999999, step=0.5, decimals=self.decimals - ), - ComboboxOptionUI( - option="excellon_ppname_e", - label_text="Preprocessor", - label_tooltip="The preprocessor JSON file that dictates\nGcode output.", # FIXME tooltip incorrect? - choices=[] # Populated in App (FIXME) - ), - RadioSetOptionUI( - option="excellon_gcode_type", - label_text="Gcode", - label_bold=True, - label_tooltip="Choose what to use for GCode generation:\n" - "'Drills', 'Slots' or 'Both'.\n" - "When choosing 'Slots' or 'Both', slots will be\n" - "converted to drills.", - choices=[ - {'label': 'Drills', 'value': 'drills'}, - {'label': 'Slots', 'value': 'slots'}, - {'label': 'Both', 'value': 'both'} - ] - ), + self.mill_dia_label = QtWidgets.QLabel('%s:' % _('Milling Diameter')) + self.mill_dia_label.setToolTip( + _("The diameter of the tool who will do the milling") + ) - HeadingOptionUI( - label_text="Mill Holes", - label_tooltip="Create Geometry for milling holes." - ), - DoubleSpinnerOptionUI( - option="excellon_tooldia", - label_text="Drill Tool dia", - label_tooltip="Diameter of the cutting tool", - min_value=0.0, max_value=999.9999, step=0.1, decimals=self.decimals - ), - DoubleSpinnerOptionUI( - option="excellon_slot_tooldia", - label_text="Slot Tool dia", - label_tooltip="Diameter of the cutting tool\nwhen milling slots.", - min_value=0.0, max_value=999.9999, step=0.1, decimals=self.decimals + self.mill_dia_entry = FCDoubleSpinner() + self.mill_dia_entry.set_precision(self.decimals) + self.mill_dia_entry.set_range(0.0000, 9999.9999) + + grid2.addWidget(self.mill_dia_label, 2, 0) + grid2.addWidget(self.mill_dia_entry, 2, 1) + + # Cut Z + cutzlabel = QtWidgets.QLabel('%s:' % _('Cut Z')) + cutzlabel.setToolTip( + _("Drill depth (negative)\n" + "below the copper surface.") + ) + + self.cutz_entry = FCDoubleSpinner() + + if machinist_setting == 0: + self.cutz_entry.set_range(-9999.9999, 0.0000) + else: + self.cutz_entry.set_range(-9999.9999, 9999.9999) + + self.cutz_entry.setSingleStep(0.1) + self.cutz_entry.set_precision(self.decimals) + + grid2.addWidget(cutzlabel, 3, 0) + grid2.addWidget(self.cutz_entry, 3, 1) + + # Multi-Depth + self.mpass_cb = FCCheckBox('%s:' % _("Multi-Depth")) + self.mpass_cb.setToolTip( + _( + "Use multiple passes to limit\n" + "the cut depth in each pass. Will\n" + "cut multiple times until Cut Z is\n" + "reached." ) - ] + ) + + self.maxdepth_entry = FCDoubleSpinner() + self.maxdepth_entry.set_precision(self.decimals) + self.maxdepth_entry.set_range(0, 9999.9999) + self.maxdepth_entry.setSingleStep(0.1) + + self.maxdepth_entry.setToolTip(_("Depth of each pass (positive).")) + + grid2.addWidget(self.mpass_cb, 4, 0) + grid2.addWidget(self.maxdepth_entry, 4, 1) + + # Travel Z + travelzlabel = QtWidgets.QLabel('%s:' % _('Travel Z')) + travelzlabel.setToolTip( + _("Tool height when travelling\n" + "across the XY plane.") + ) + + self.travelz_entry = FCDoubleSpinner() + self.travelz_entry.set_precision(self.decimals) + + if machinist_setting == 0: + self.travelz_entry.set_range(0.0001, 9999.9999) + else: + self.travelz_entry.set_range(-9999.9999, 9999.9999) + + grid2.addWidget(travelzlabel, 5, 0) + grid2.addWidget(self.travelz_entry, 5, 1) + + # Tool change: + self.toolchange_cb = FCCheckBox('%s' % _("Tool change")) + self.toolchange_cb.setToolTip( + _("Include tool-change sequence\n" + "in G-Code (Pause for tool change).") + ) + grid2.addWidget(self.toolchange_cb, 6, 0, 1, 2) + + # Tool Change Z + toolchangezlabel = QtWidgets.QLabel('%s:' % _('Toolchange Z')) + toolchangezlabel.setToolTip( + _("Z-axis position (height) for\n" + "tool change.") + ) + + self.toolchangez_entry = FCDoubleSpinner() + self.toolchangez_entry.set_precision(self.decimals) + + if machinist_setting == 0: + self.toolchangez_entry.set_range(0.0001, 9999.9999) + else: + self.toolchangez_entry.set_range(-9999.9999, 9999.9999) + + grid2.addWidget(toolchangezlabel, 7, 0) + grid2.addWidget(self.toolchangez_entry, 7, 1) + + # End Move Z + endz_label = QtWidgets.QLabel('%s:' % _('End move Z')) + endz_label.setToolTip( + _("Height of the tool after\n" + "the last move at the end of the job.") + ) + self.endz_entry = FCDoubleSpinner() + self.endz_entry.set_precision(self.decimals) + + if machinist_setting == 0: + self.endz_entry.set_range(0.0000, 9999.9999) + else: + self.endz_entry.set_range(-9999.9999, 9999.9999) + + grid2.addWidget(endz_label, 8, 0) + grid2.addWidget(self.endz_entry, 8, 1) + + # End Move X,Y + endmove_xy_label = QtWidgets.QLabel('%s:' % _('End move X,Y')) + endmove_xy_label.setToolTip( + _("End move X,Y position. In format (x,y).\n" + "If no value is entered then there is no move\n" + "on X,Y plane at the end of the job.") + ) + self.endxy_entry = FCEntry() + + grid2.addWidget(endmove_xy_label, 9, 0) + grid2.addWidget(self.endxy_entry, 9, 1) + + # Feedrate Z + frlabel = QtWidgets.QLabel('%s:' % _('Feedrate Z')) + frlabel.setToolTip( + _("Tool speed while drilling\n" + "(in units per minute).\n" + "So called 'Plunge' feedrate.\n" + "This is for linear move G01.") + ) + self.feedrate_z_entry = FCDoubleSpinner() + self.feedrate_z_entry.set_precision(self.decimals) + self.feedrate_z_entry.set_range(0, 99999.9999) + + grid2.addWidget(frlabel, 10, 0) + grid2.addWidget(self.feedrate_z_entry, 10, 1) + + # Spindle speed + spdlabel = QtWidgets.QLabel('%s:' % _('Spindle Speed')) + spdlabel.setToolTip( + _("Speed of the spindle\n" + "in RPM (optional)") + ) + + self.spindlespeed_entry = FCSpinner() + self.spindlespeed_entry.set_range(0, 1000000) + self.spindlespeed_entry.set_step(100) + + grid2.addWidget(spdlabel, 11, 0) + grid2.addWidget(self.spindlespeed_entry, 11, 1) + + # Dwell + self.dwell_cb = FCCheckBox('%s' % _('Enable Dwell')) + self.dwell_cb .setToolTip( + _("Pause to allow the spindle to reach its\n" + "speed before cutting.") + ) + + grid2.addWidget(self.dwell_cb, 12, 0, 1, 2) + + # Dwell Time + dwelltime = QtWidgets.QLabel('%s:' % _('Duration')) + dwelltime.setToolTip(_("Number of time units for spindle to dwell.")) + self.dwelltime_entry = FCDoubleSpinner() + self.dwelltime_entry.set_precision(self.decimals) + self.dwelltime_entry.set_range(0, 99999.9999) + + grid2.addWidget(dwelltime, 13, 0) + grid2.addWidget(self.dwelltime_entry, 13, 1) + + self.ois_dwell_exc = OptionalInputSection(self.dwell_cb, [self.dwelltime_entry]) + + # preprocessor selection + pp_excellon_label = QtWidgets.QLabel('%s:' % _("Preprocessor")) + pp_excellon_label.setToolTip( + _("The preprocessor JSON file that dictates\n" + "Gcode output.") + ) + + self.pp_excellon_name_cb = FCComboBox() + self.pp_excellon_name_cb.setFocusPolicy(Qt.StrongFocus) + + grid2.addWidget(pp_excellon_label, 14, 0) + grid2.addWidget(self.pp_excellon_name_cb, 14, 1) + + # ### Choose what to use for Gcode creation: Drills, Slots or Both + excellon_gcode_type_label = QtWidgets.QLabel('%s' % _('Gcode')) + excellon_gcode_type_label.setToolTip( + _("Choose what to use for GCode generation:\n" + "'Drills', 'Slots' or 'Both'.\n" + "When choosing 'Slots' or 'Both', slots will be\n" + "converted to drills.") + ) + self.excellon_gcode_type_radio = RadioSet([{'label': 'Drills', 'value': 'drills'}, + {'label': 'Slots', 'value': 'slots'}, + {'label': 'Both', 'value': 'both'}]) + grid2.addWidget(excellon_gcode_type_label, 15, 0) + grid2.addWidget(self.excellon_gcode_type_radio, 15, 1) + + # until I decide to implement this feature those remain disabled + excellon_gcode_type_label.hide() + self.excellon_gcode_type_radio.setVisible(False) + + # ### Milling Holes ## ## + self.mill_hole_label = QtWidgets.QLabel('%s' % _('Mill Holes')) + self.mill_hole_label.setToolTip( + _("Create Geometry for milling holes.") + ) + grid2.addWidget(self.mill_hole_label, 16, 0, 1, 2) + + tdlabel = QtWidgets.QLabel('%s:' % _('Drill Tool dia')) + tdlabel.setToolTip( + _("Diameter of the cutting tool.") + ) + self.tooldia_entry = FCDoubleSpinner() + self.tooldia_entry.set_precision(self.decimals) + self.tooldia_entry.set_range(0, 999.9999) + + grid2.addWidget(tdlabel, 18, 0) + grid2.addWidget(self.tooldia_entry, 18, 1) + + stdlabel = QtWidgets.QLabel('%s:' % _('Slot Tool dia')) + stdlabel.setToolTip( + _("Diameter of the cutting tool\n" + "when milling slots.") + ) + self.slot_tooldia_entry = FCDoubleSpinner() + self.slot_tooldia_entry.set_precision(self.decimals) + self.slot_tooldia_entry.set_range(0, 999.9999) + + grid2.addWidget(stdlabel, 21, 0) + grid2.addWidget(self.slot_tooldia_entry, 21, 1) + + self.layout.addStretch() diff --git a/flatcamGUI/preferences/excellon/ExcellonPreferencesUI.py b/flatcamGUI/preferences/excellon/ExcellonPreferencesUI.py index 91176f9d..b3d6d165 100644 --- a/flatcamGUI/preferences/excellon/ExcellonPreferencesUI.py +++ b/flatcamGUI/preferences/excellon/ExcellonPreferencesUI.py @@ -1,5 +1,6 @@ -from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI -from flatcamGUI.preferences.PreferencesSectionUI import PreferencesSectionUI +from PyQt5 import QtWidgets +from PyQt5.QtCore import QSettings + from flatcamGUI.preferences.excellon.ExcellonEditorPrefGroupUI import ExcellonEditorPrefGroupUI from flatcamGUI.preferences.excellon.ExcellonExpPrefGroupUI import ExcellonExpPrefGroupUI from flatcamGUI.preferences.excellon.ExcellonAdvOptPrefGroupUI import ExcellonAdvOptPrefGroupUI @@ -9,62 +10,44 @@ from flatcamGUI.preferences.excellon.ExcellonGenPrefGroupUI import ExcellonGenPr import gettext import FlatCAMTranslation as fcTranslate import builtins + fcTranslate.apply_language('strings') if '_' not in builtins.__dict__: _ = gettext.gettext +settings = QSettings("Open Source", "FlatCAM") +if settings.contains("machinist"): + machinist_setting = settings.value('machinist', type=int) +else: + machinist_setting = 0 -class ExcellonPreferencesUI(PreferencesSectionUI): - def __init__(self, decimals, **kwargs): +class ExcellonPreferencesUI(QtWidgets.QWidget): + + def __init__(self, decimals, parent=None): + QtWidgets.QWidget.__init__(self, parent=parent) + self.layout = QtWidgets.QHBoxLayout() + self.setLayout(self.layout) self.decimals = decimals - # FIXME: remove the need for external access to excellon_opt_group + + self.excellon_gen_group = ExcellonGenPrefGroupUI(decimals=self.decimals) + self.excellon_gen_group.setMinimumWidth(220) self.excellon_opt_group = ExcellonOptPrefGroupUI(decimals=self.decimals) - super().__init__(**kwargs) - self.init_sync_export() + self.excellon_opt_group.setMinimumWidth(290) + self.excellon_exp_group = ExcellonExpPrefGroupUI(decimals=self.decimals) + self.excellon_exp_group.setMinimumWidth(250) + self.excellon_adv_opt_group = ExcellonAdvOptPrefGroupUI(decimals=self.decimals) + self.excellon_adv_opt_group.setMinimumWidth(250) + self.excellon_editor_group = ExcellonEditorPrefGroupUI(decimals=self.decimals) + self.excellon_editor_group.setMinimumWidth(260) - def build_groups(self) -> [OptionsGroupUI]: - return [ - ExcellonGenPrefGroupUI(decimals=self.decimals), - self.excellon_opt_group, - ExcellonExpPrefGroupUI(decimals=self.decimals), - ExcellonAdvOptPrefGroupUI(decimals=self.decimals), - ExcellonEditorPrefGroupUI(decimals=self.decimals) - ] - - def get_tab_id(self): - return "excellon_tab" - - def get_tab_label(self): - return _("EXCELLON") - - def init_sync_export(self): - self.option_dict()["excellon_update"].get_field().stateChanged.connect(self.sync_export) - self.option_dict()["excellon_format_upper_in"].get_field().returnPressed.connect(self.sync_export) - self.option_dict()["excellon_format_lower_in"].get_field().returnPressed.connect(self.sync_export) - self.option_dict()["excellon_format_upper_mm"].get_field().returnPressed.connect(self.sync_export) - self.option_dict()["excellon_format_lower_mm"].get_field().returnPressed.connect(self.sync_export) - self.option_dict()["excellon_zeros"].get_field().activated_custom.connect(self.sync_export) - self.option_dict()["excellon_units"].get_field().activated_custom.connect(self.sync_export) - - def sync_export(self): - if not self.option_dict()["excellon_update"].get_field().get_value(): - # User has disabled sync. - return - - zeros = self.option_dict()["excellon_zeros"].get_field().get_value() + 'Z' - self.option_dict()["excellon_exp_zeros"].get_field().set_value(zeros) - - units = self.option_dict()["excellon_units"].get_field().get_value() - self.option_dict()["excellon_exp_units"].get_field().set_value(units) - - if units.upper() == 'METRIC': - whole = self.option_dict()["excellon_format_upper_mm"].get_field().get_value() - dec = self.option_dict()["excellon_format_lower_mm"].get_field().get_value() - else: - whole = self.option_dict()["excellon_format_upper_in"].get_field().get_value() - dec = self.option_dict()["excellon_format_lower_in"].get_field().get_value() - self.option_dict()["excellon_exp_integer"].get_field().set_value(whole) - self.option_dict()["excellon_exp_decimals"].get_field().set_value(dec) + self.vlay = QtWidgets.QVBoxLayout() + self.vlay.addWidget(self.excellon_opt_group) + self.vlay.addWidget(self.excellon_exp_group) + self.layout.addWidget(self.excellon_gen_group) + self.layout.addLayout(self.vlay) + self.layout.addWidget(self.excellon_adv_opt_group) + self.layout.addWidget(self.excellon_editor_group) + self.layout.addStretch() diff --git a/flatcamGUI/preferences/general/GeneralAPPSetGroupUI.py b/flatcamGUI/preferences/general/GeneralAPPSetGroupUI.py new file mode 100644 index 00000000..3daff809 --- /dev/null +++ b/flatcamGUI/preferences/general/GeneralAPPSetGroupUI.py @@ -0,0 +1,483 @@ +from PyQt5 import QtCore, QtWidgets, QtGui +from PyQt5.QtCore import QSettings + +from flatcamGUI.GUIElements import FCDoubleSpinner, FCCheckBox, FCComboBox, RadioSet, OptionalInputSection, FCSpinner, \ + FCEntry +from flatcamGUI.preferences import settings +from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI + +import gettext +import FlatCAMTranslation as fcTranslate +import builtins + +fcTranslate.apply_language('strings') +if '_' not in builtins.__dict__: + _ = gettext.gettext + +settings = QSettings("Open Source", "FlatCAM") +if settings.contains("machinist"): + machinist_setting = settings.value('machinist', type=int) +else: + machinist_setting = 0 + + +class GeneralAPPSetGroupUI(OptionsGroupUI): + def __init__(self, decimals=4, parent=None): + super(GeneralAPPSetGroupUI, self).__init__(self, parent=parent) + + self.setTitle(str(_("App Settings"))) + self.decimals = decimals + + theme_settings = QtCore.QSettings("Open Source", "FlatCAM") + if theme_settings.contains("theme"): + theme = theme_settings.value('theme', type=str) + else: + theme = 'white' + + if theme == 'white': + self.resource_loc = 'assets/resources' + else: + self.resource_loc = 'assets/resources' + + # Create a grid layout for the Application general settings + grid0 = QtWidgets.QGridLayout() + self.layout.addLayout(grid0) + grid0.setColumnStretch(0, 0) + grid0.setColumnStretch(1, 1) + + # GRID Settings + self.grid_label = QtWidgets.QLabel('%s' % _('Grid Settings')) + grid0.addWidget(self.grid_label, 0, 0, 1, 2) + + # Grid X Entry + self.gridx_label = QtWidgets.QLabel('%s:' % _('X value')) + self.gridx_label.setToolTip( + _("This is the Grid snap value on X axis.") + ) + self.gridx_entry = FCDoubleSpinner() + self.gridx_entry.set_precision(self.decimals) + self.gridx_entry.setSingleStep(0.1) + + grid0.addWidget(self.gridx_label, 1, 0) + grid0.addWidget(self.gridx_entry, 1, 1) + + # Grid Y Entry + self.gridy_label = QtWidgets.QLabel('%s:' % _('Y value')) + self.gridy_label.setToolTip( + _("This is the Grid snap value on Y axis.") + ) + self.gridy_entry = FCDoubleSpinner() + self.gridy_entry.set_precision(self.decimals) + self.gridy_entry.setSingleStep(0.1) + + grid0.addWidget(self.gridy_label, 2, 0) + grid0.addWidget(self.gridy_entry, 2, 1) + + # Snap Max Entry + self.snap_max_label = QtWidgets.QLabel('%s:' % _('Snap Max')) + self.snap_max_label.setToolTip(_("Max. magnet distance")) + self.snap_max_dist_entry = FCDoubleSpinner() + self.snap_max_dist_entry.set_precision(self.decimals) + self.snap_max_dist_entry.setSingleStep(0.1) + + grid0.addWidget(self.snap_max_label, 3, 0) + grid0.addWidget(self.snap_max_dist_entry, 3, 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) + + # Workspace + self.workspace_label = QtWidgets.QLabel('%s' % _('Workspace Settings')) + grid0.addWidget(self.workspace_label, 5, 0, 1, 2) + + self.workspace_cb = FCCheckBox('%s' % _('Active')) + self.workspace_cb.setToolTip( + _("Draw a delimiting rectangle on canvas.\n" + "The purpose is to illustrate the limits for our work.") + ) + + grid0.addWidget(self.workspace_cb, 6, 0, 1, 2) + + self.workspace_type_lbl = QtWidgets.QLabel('%s:' % _('Size')) + self.workspace_type_lbl.setToolTip( + _("Select the type of rectangle to be used on canvas,\n" + "as valid workspace.") + ) + self.wk_cb = FCComboBox() + + grid0.addWidget(self.workspace_type_lbl, 7, 0) + grid0.addWidget(self.wk_cb, 7, 1) + + self.pagesize = {} + self.pagesize.update( + { + 'A0': (841, 1189), + 'A1': (594, 841), + 'A2': (420, 594), + 'A3': (297, 420), + 'A4': (210, 297), + 'A5': (148, 210), + 'A6': (105, 148), + 'A7': (74, 105), + 'A8': (52, 74), + 'A9': (37, 52), + 'A10': (26, 37), + + 'B0': (1000, 1414), + 'B1': (707, 1000), + 'B2': (500, 707), + 'B3': (353, 500), + 'B4': (250, 353), + 'B5': (176, 250), + 'B6': (125, 176), + 'B7': (88, 125), + 'B8': (62, 88), + 'B9': (44, 62), + 'B10': (31, 44), + + 'C0': (917, 1297), + 'C1': (648, 917), + 'C2': (458, 648), + 'C3': (324, 458), + 'C4': (229, 324), + 'C5': (162, 229), + 'C6': (114, 162), + 'C7': (81, 114), + 'C8': (57, 81), + 'C9': (40, 57), + 'C10': (28, 40), + + # American paper sizes + 'LETTER': (8.5, 11), + 'LEGAL': (8.5, 14), + 'ELEVENSEVENTEEN': (11, 17), + + # From https://en.wikipedia.org/wiki/Paper_size + 'JUNIOR_LEGAL': (5, 8), + 'HALF_LETTER': (5.5, 8), + 'GOV_LETTER': (8, 10.5), + 'GOV_LEGAL': (8.5, 13), + 'LEDGER': (17, 11), + } + ) + + page_size_list = list(self.pagesize.keys()) + + self.wk_cb.addItems(page_size_list) + + # Page orientation + self.wk_orientation_label = QtWidgets.QLabel('%s:' % _("Orientation")) + self.wk_orientation_label.setToolTip(_("Can be:\n" + "- Portrait\n" + "- Landscape")) + + self.wk_orientation_radio = RadioSet([{'label': _('Portrait'), 'value': 'p'}, + {'label': _('Landscape'), 'value': 'l'}, + ], stretch=False) + + self.wks = OptionalInputSection(self.workspace_cb, + [ + self.workspace_type_lbl, + self.wk_cb, + self.wk_orientation_label, + self.wk_orientation_radio + ]) + + grid0.addWidget(self.wk_orientation_label, 8, 0) + grid0.addWidget(self.wk_orientation_radio, 8, 1) + + separator_line = QtWidgets.QFrame() + separator_line.setFrameShape(QtWidgets.QFrame.HLine) + separator_line.setFrameShadow(QtWidgets.QFrame.Sunken) + grid0.addWidget(separator_line, 9, 0, 1, 2) + + # Font Size + self.font_size_label = QtWidgets.QLabel('%s' % _('Font Size')) + grid0.addWidget(self.font_size_label, 10, 0, 1, 2) + + # Notebook Font Size + self.notebook_font_size_label = QtWidgets.QLabel('%s:' % _('Notebook')) + self.notebook_font_size_label.setToolTip( + _("This sets the font size for the elements found in the Notebook.\n" + "The notebook is the collapsible area in the left side of the GUI,\n" + "and include the Project, Selected and Tool tabs.") + ) + + self.notebook_font_size_spinner = FCSpinner() + self.notebook_font_size_spinner.set_range(8, 40) + self.notebook_font_size_spinner.setWrapping(True) + + qsettings = QSettings("Open Source", "FlatCAM") + if qsettings.contains("notebook_font_size"): + self.notebook_font_size_spinner.set_value(qsettings.value('notebook_font_size', type=int)) + else: + self.notebook_font_size_spinner.set_value(12) + + grid0.addWidget(self.notebook_font_size_label, 11, 0) + grid0.addWidget(self.notebook_font_size_spinner, 11, 1) + + # Axis Font Size + self.axis_font_size_label = QtWidgets.QLabel('%s:' % _('Axis')) + self.axis_font_size_label.setToolTip( + _("This sets the font size for canvas axis.") + ) + + self.axis_font_size_spinner = FCSpinner() + self.axis_font_size_spinner.set_range(0, 40) + self.axis_font_size_spinner.setWrapping(True) + + qsettings = QSettings("Open Source", "FlatCAM") + if qsettings.contains("axis_font_size"): + self.axis_font_size_spinner.set_value(qsettings.value('axis_font_size', type=int)) + else: + self.axis_font_size_spinner.set_value(8) + + grid0.addWidget(self.axis_font_size_label, 12, 0) + grid0.addWidget(self.axis_font_size_spinner, 12, 1) + + # TextBox Font Size + self.textbox_font_size_label = QtWidgets.QLabel('%s:' % _('Textbox')) + self.textbox_font_size_label.setToolTip( + _("This sets the font size for the Textbox GUI\n" + "elements that are used in FlatCAM.") + ) + + self.textbox_font_size_spinner = FCSpinner() + self.textbox_font_size_spinner.set_range(8, 40) + self.textbox_font_size_spinner.setWrapping(True) + + qsettings = QSettings("Open Source", "FlatCAM") + if qsettings.contains("textbox_font_size"): + self.textbox_font_size_spinner.set_value(settings.value('textbox_font_size', type=int)) + else: + self.textbox_font_size_spinner.set_value(10) + + grid0.addWidget(self.textbox_font_size_label, 13, 0) + grid0.addWidget(self.textbox_font_size_spinner, 13, 1) + + separator_line = QtWidgets.QFrame() + separator_line.setFrameShape(QtWidgets.QFrame.HLine) + separator_line.setFrameShadow(QtWidgets.QFrame.Sunken) + grid0.addWidget(separator_line, 14, 0, 1, 2) + + # ----------------------------------------------------------- + # -------------- MOUSE SETTINGS ----------------------------- + # ----------------------------------------------------------- + + self.mouse_lbl = QtWidgets.QLabel('%s' % _('Mouse Settings')) + grid0.addWidget(self.mouse_lbl, 21, 0, 1, 2) + + # Mouse Cursor Shape + self.cursor_lbl = QtWidgets.QLabel('%s:' % _('Cursor Shape')) + self.cursor_lbl.setToolTip( + _("Choose a mouse cursor shape.\n" + "- Small -> with a customizable size.\n" + "- Big -> Infinite lines") + ) + + self.cursor_radio = RadioSet([ + {"label": _("Small"), "value": "small"}, + {"label": _("Big"), "value": "big"} + ], orientation='horizontal', stretch=False) + + grid0.addWidget(self.cursor_lbl, 22, 0) + grid0.addWidget(self.cursor_radio, 22, 1) + + # Mouse Cursor Size + self.cursor_size_lbl = QtWidgets.QLabel('%s:' % _('Cursor Size')) + self.cursor_size_lbl.setToolTip( + _("Set the size of the mouse cursor, in pixels.") + ) + + self.cursor_size_entry = FCSpinner() + self.cursor_size_entry.set_range(10, 70) + self.cursor_size_entry.setWrapping(True) + + grid0.addWidget(self.cursor_size_lbl, 23, 0) + grid0.addWidget(self.cursor_size_entry, 23, 1) + + # Cursor Width + self.cursor_width_lbl = QtWidgets.QLabel('%s:' % _('Cursor Width')) + self.cursor_width_lbl.setToolTip( + _("Set the line width of the mouse cursor, in pixels.") + ) + + self.cursor_width_entry = FCSpinner() + self.cursor_width_entry.set_range(1, 10) + self.cursor_width_entry.setWrapping(True) + + grid0.addWidget(self.cursor_width_lbl, 24, 0) + grid0.addWidget(self.cursor_width_entry, 24, 1) + + # Cursor Color Enable + self.mouse_cursor_color_cb = FCCheckBox(label='%s' % _('Cursor Color')) + self.mouse_cursor_color_cb.setToolTip( + _("Check this box to color mouse cursor.") + ) + grid0.addWidget(self.mouse_cursor_color_cb, 25, 0, 1, 2) + + # Cursor Color + self.mouse_color_label = QtWidgets.QLabel('%s:' % _('Cursor Color')) + self.mouse_color_label.setToolTip( + _("Set the color of the mouse cursor.") + ) + self.mouse_cursor_entry = FCEntry() + self.mouse_cursor_button = QtWidgets.QPushButton() + self.mouse_cursor_button.setFixedSize(15, 15) + + self.form_box_child_1 = QtWidgets.QHBoxLayout() + self.form_box_child_1.addWidget(self.mouse_cursor_entry) + self.form_box_child_1.addWidget(self.mouse_cursor_button) + self.form_box_child_1.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter) + + grid0.addWidget(self.mouse_color_label, 26, 0) + grid0.addLayout(self.form_box_child_1, 26, 1) + + self.mois = OptionalInputSection( + self.mouse_cursor_color_cb, + [ + self.mouse_color_label, + self.mouse_cursor_entry, + self.mouse_cursor_button + ] + ) + # Select mouse pan button + self.panbuttonlabel = QtWidgets.QLabel('%s:' % _('Pan Button')) + self.panbuttonlabel.setToolTip( + _("Select the mouse button to use for panning:\n" + "- MMB --> Middle Mouse Button\n" + "- RMB --> Right Mouse Button") + ) + self.pan_button_radio = RadioSet([{'label': _('MMB'), 'value': '3'}, + {'label': _('RMB'), 'value': '2'}]) + + grid0.addWidget(self.panbuttonlabel, 27, 0) + grid0.addWidget(self.pan_button_radio, 27, 1) + + # Multiple Selection Modifier Key + self.mselectlabel = QtWidgets.QLabel('%s:' % _('Multiple Selection')) + self.mselectlabel.setToolTip( + _("Select the key used for multiple selection.") + ) + self.mselect_radio = RadioSet([{'label': _('CTRL'), 'value': 'Control'}, + {'label': _('SHIFT'), 'value': 'Shift'}]) + + grid0.addWidget(self.mselectlabel, 28, 0) + grid0.addWidget(self.mselect_radio, 28, 1) + + separator_line = QtWidgets.QFrame() + separator_line.setFrameShape(QtWidgets.QFrame.HLine) + separator_line.setFrameShadow(QtWidgets.QFrame.Sunken) + grid0.addWidget(separator_line, 29, 0, 1, 2) + + # Delete confirmation + self.delete_conf_cb = FCCheckBox(_('Delete object confirmation')) + self.delete_conf_cb.setToolTip( + _("When checked the application will ask for user confirmation\n" + "whenever the Delete object(s) event is triggered, either by\n" + "menu shortcut or key shortcut.") + ) + grid0.addWidget(self.delete_conf_cb, 30, 0, 1, 2) + + # Open behavior + self.open_style_cb = FCCheckBox('%s' % _('"Open" behavior')) + self.open_style_cb.setToolTip( + _("When checked the path for the last saved file is used when saving files,\n" + "and the path for the last opened file is used when opening files.\n\n" + "When unchecked the path for opening files is the one used last: either the\n" + "path for saving files or the path for opening files.") + ) + + grid0.addWidget(self.open_style_cb, 31, 0, 1, 2) + + # Enable/Disable ToolTips globally + self.toggle_tooltips_cb = FCCheckBox(label=_('Enable ToolTips')) + self.toggle_tooltips_cb.setToolTip( + _("Check this box if you want to have toolTips displayed\n" + "when hovering with mouse over items throughout the App.") + ) + + grid0.addWidget(self.toggle_tooltips_cb, 32, 0, 1, 2) + + # Machinist settings that allow unsafe settings + self.machinist_cb = FCCheckBox(_("Allow Machinist Unsafe Settings")) + self.machinist_cb.setToolTip( + _("If checked, some of the application settings will be allowed\n" + "to have values that are usually unsafe to use.\n" + "Like Z travel negative values or Z Cut positive values.\n" + "It will applied at the next application start.\n" + "<>: Don't change this unless you know what you are doing !!!") + ) + + grid0.addWidget(self.machinist_cb, 33, 0, 1, 2) + + # Bookmarks Limit in the Help Menu + self.bm_limit_spinner = FCSpinner() + self.bm_limit_spinner.set_range(0, 9999) + self.bm_limit_label = QtWidgets.QLabel('%s:' % _('Bookmarks limit')) + self.bm_limit_label.setToolTip( + _("The maximum number of bookmarks that may be installed in the menu.\n" + "The number of bookmarks in the bookmark manager may be greater\n" + "but the menu will hold only so much.") + ) + + grid0.addWidget(self.bm_limit_label, 34, 0) + grid0.addWidget(self.bm_limit_spinner, 34, 1) + + # Activity monitor icon + self.activity_label = QtWidgets.QLabel('%s:' % _("Activity Icon")) + self.activity_label.setToolTip( + _("Select the GIF that show activity when FlatCAM is active.") + ) + self.activity_combo = FCComboBox() + self.activity_combo.addItems(['Ball black', 'Ball green', 'Arrow green', 'Eclipse green']) + + grid0.addWidget(self.activity_label, 35, 0) + grid0.addWidget(self.activity_combo, 35, 1) + + self.layout.addStretch() + + self.mouse_cursor_color_cb.stateChanged.connect(self.on_mouse_cursor_color_enable) + + self.mouse_cursor_entry.editingFinished.connect(self.on_mouse_cursor_entry) + self.mouse_cursor_button.clicked.connect(self.on_mouse_cursor_button) + + def on_mouse_cursor_color_enable(self, val): + if val: + self.app.cursor_color_3D = self.app.defaults["global_cursor_color"] + else: + theme_settings = QtCore.QSettings("Open Source", "FlatCAM") + if theme_settings.contains("theme"): + theme = theme_settings.value('theme', type=str) + else: + theme = 'white' + + if theme == 'white': + self.app.cursor_color_3D = 'black' + else: + self.app.cursor_color_3D = 'gray' + + def on_mouse_cursor_entry(self): + self.app.defaults['global_cursor_color'] = self.mouse_cursor_entry.get_value() + self.mouse_cursor_button.setStyleSheet("background-color:%s" % str(self.app.defaults['global_cursor_color'])) + + self.app.cursor_color_3D = self.app.defaults["global_cursor_color"] + + def on_mouse_cursor_button(self): + current_color = QtGui.QColor(self.app.defaults['global_cursor_color']) + + c_dialog = QtWidgets.QColorDialog() + proj_color = c_dialog.getColor(initial=current_color) + + if proj_color.isValid() is False: + return + + self.mouse_cursor_button.setStyleSheet("background-color:%s" % str(proj_color.name())) + + new_val_sel = str(proj_color.name()) + self.mouse_cursor_entry.set_value(new_val_sel) + self.app.defaults['global_cursor_color'] = new_val_sel + + self.app.cursor_color_3D = self.app.defaults["global_cursor_color"] diff --git a/flatcamGUI/preferences/general/GeneralAppPrefGroupUI.py b/flatcamGUI/preferences/general/GeneralAppPrefGroupUI.py index 4ab4f105..7f238b5f 100644 --- a/flatcamGUI/preferences/general/GeneralAppPrefGroupUI.py +++ b/flatcamGUI/preferences/general/GeneralAppPrefGroupUI.py @@ -1,251 +1,382 @@ import sys + +from PyQt5 import QtWidgets from PyQt5.QtCore import QSettings -from flatcamGUI.GUIElements import OptionalInputSection -from flatcamGUI.preferences.OptionUI import * -from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI2 + +from flatcamGUI.GUIElements import RadioSet, FCSpinner, FCCheckBox, FCComboBox, FCButton, OptionalInputSection, \ + FCDoubleSpinner +from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI import gettext import FlatCAMTranslation as fcTranslate import builtins + fcTranslate.apply_language('strings') if '_' not in builtins.__dict__: _ = gettext.gettext +settings = QSettings("Open Source", "FlatCAM") +if settings.contains("machinist"): + machinist_setting = settings.value('machinist', type=int) +else: + machinist_setting = 0 -class GeneralAppPrefGroupUI(OptionsGroupUI2): - def __init__(self, decimals=4, **kwargs): + +class GeneralAppPrefGroupUI(OptionsGroupUI): + def __init__(self, decimals=4, parent=None): + super(GeneralAppPrefGroupUI, self).__init__(self, parent=parent) + + self.setTitle(_("App Preferences")) self.decimals = decimals - super().__init__(**kwargs) - self.setTitle(str(_("App Preferences"))) - if sys.platform != 'win32': - self.option_dict()["global_portable"].get_field().hide() - self.option_dict()["splash_screen"].get_field().stateChanged.connect(self.on_splash_changed) - self.option_dict()["global_shell_at_startup"].get_field().clicked.connect(self.on_toggle_shell_from_settings) - self.option_dict()["__apply_language_button"].get_field().clicked.connect(lambda: fcTranslate.on_language_apply_click(app=self.app, restart=True)) + # Create a form layout for the Application general settings + grid0 = QtWidgets.QGridLayout() + self.layout.addLayout(grid0) + grid0.setColumnStretch(0, 0) + grid0.setColumnStretch(1, 1) + + # Units for FlatCAM + self.unitslabel = QtWidgets.QLabel('%s:' % _('Units')) + self.unitslabel.setToolTip(_("The default value for FlatCAM units.\n" + "Whatever is selected here is set every time\n" + "FlatCAM is started.")) + self.units_radio = RadioSet([{'label': _('MM'), 'value': 'MM'}, + {'label': _('IN'), 'value': 'IN'}]) + + grid0.addWidget(self.unitslabel, 0, 0) + grid0.addWidget(self.units_radio, 0, 1) + + # Precision Metric + self.precision_metric_label = QtWidgets.QLabel('%s:' % _('Precision MM')) + self.precision_metric_label.setToolTip( + _("The number of decimals used throughout the application\n" + "when the set units are in METRIC system.\n" + "Any change here require an application restart.") + ) + self.precision_metric_entry = FCSpinner() + 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) + + # Precision Inch + self.precision_inch_label = QtWidgets.QLabel('%s:' % _('Precision INCH')) + self.precision_inch_label.setToolTip( + _("The number of decimals used throughout the application\n" + "when the set units are in INCH system.\n" + "Any change here require an application restart.") + ) + self.precision_inch_entry = FCSpinner() + 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) + + # Graphic Engine for FlatCAM + self.ge_label = QtWidgets.QLabel('%s:' % _('Graphic Engine')) + self.ge_label.setToolTip(_("Choose what graphic engine to use in FlatCAM.\n" + "Legacy(2D) -> reduced functionality, slow performance but enhanced compatibility.\n" + "OpenGL(3D) -> full functionality, high performance\n" + "Some graphic cards are too old and do not work in OpenGL(3D) mode, like:\n" + "Intel HD3000 or older. In this case the plot area will be black therefore\n" + "use the Legacy(2D) mode.")) + self.ge_radio = RadioSet([{'label': _('Legacy(2D)'), 'value': '2D'}, + {'label': _('OpenGL(3D)'), 'value': '3D'}], + orientation='vertical') + + grid0.addWidget(self.ge_label, 3, 0) + grid0.addWidget(self.ge_radio, 3, 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) + + # Application Level for FlatCAM + self.app_level_label = QtWidgets.QLabel('%s:' % _('APP. LEVEL')) + self.app_level_label.setToolTip(_("Choose the default level of usage for FlatCAM.\n" + "BASIC level -> reduced functionality, best for beginner's.\n" + "ADVANCED level -> full functionality.\n\n" + "The choice here will influence the parameters in\n" + "the Selected Tab for all kinds of FlatCAM objects.")) + self.app_level_radio = RadioSet([{'label': _('Basic'), 'value': 'b'}, + {'label': _('Advanced'), 'value': 'a'}]) + + grid0.addWidget(self.app_level_label, 5, 0) + grid0.addWidget(self.app_level_radio, 5, 1) + + # Portability for FlatCAM + 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, 6, 0, 1, 2) + + separator_line = QtWidgets.QFrame() + separator_line.setFrameShape(QtWidgets.QFrame.HLine) + separator_line.setFrameShadow(QtWidgets.QFrame.Sunken) + grid0.addWidget(separator_line, 7, 0, 1, 2) + + # Languages for FlatCAM + self.languagelabel = QtWidgets.QLabel('%s' % _('Languages')) + self.languagelabel.setToolTip(_("Set the language used throughout FlatCAM.")) + self.language_cb = FCComboBox() + + grid0.addWidget(self.languagelabel, 8, 0, 1, 2) + grid0.addWidget(self.language_cb, 9, 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) + + separator_line = QtWidgets.QFrame() + separator_line.setFrameShape(QtWidgets.QFrame.HLine) + separator_line.setFrameShadow(QtWidgets.QFrame.Sunken) + grid0.addWidget(separator_line, 16, 0, 1, 2) + + # ----------------------------------------------------------- + # ----------- APPLICATION STARTUP SETTINGS ------------------ + # ----------------------------------------------------------- + + self.startup_label = QtWidgets.QLabel('%s' % _('Startup Settings')) + grid0.addWidget(self.startup_label, 17, 0, 1, 2) + + # Splash Screen + self.splash_cb = FCCheckBox('%s' % _('Splash Screen')) + self.splash_cb.setToolTip( + _("Enable display of the splash screen at application startup.") + ) qsettings = QSettings("Open Source", "FlatCAM") if qsettings.value("splash_screen"): - self.option_dict()["splash_screen"].get_field().set_value(True) + self.splash_cb.set_value(True) else: - self.option_dict()["splash_screen"].get_field().set_value(False) + self.splash_cb.set_value(False) - self.version_check_field = self.option_dict()["global_version_check"].get_field() - self.send_stats_field = self.option_dict()["global_send_stats"].get_field() - self.ois_version_check = OptionalInputSection(self.version_check_field, [self.send_stats_field]) + grid0.addWidget(self.splash_cb, 18, 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) + + # Shell StartUp CB + self.shell_startup_cb = FCCheckBox(label='%s' % _('Show Shell')) + self.shell_startup_cb.setToolTip( + _("Check this box if you want the shell to\n" + "start automatically at startup.") + ) + + grid0.addWidget(self.shell_startup_cb, 20, 0, 1, 2) + + # Project at StartUp CB + self.project_startup_cb = FCCheckBox(label='%s' % _('Show Project')) + self.project_startup_cb.setToolTip( + _("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) + + # Version Check CB + self.version_check_cb = FCCheckBox(label='%s' % _('Version Check')) + self.version_check_cb.setToolTip( + _("Check this box if you want to check\n" + "for a new version automatically at startup.") + ) + + grid0.addWidget(self.version_check_cb, 22, 0, 1, 2) + + # Send Stats CB + self.send_stats_cb = FCCheckBox(label='%s' % _('Send Statistics')) + self.send_stats_cb.setToolTip( + _("Check this box if you agree to send anonymous\n" + "stats automatically at startup, to help improve FlatCAM.") + ) + + grid0.addWidget(self.send_stats_cb, 23, 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) + + # Worker Numbers + self.worker_number_label = QtWidgets.QLabel('%s:' % _('Workers number')) + self.worker_number_label.setToolTip( + _("The number of Qthreads made available to the App.\n" + "A bigger number may finish the jobs more quickly but\n" + "depending on your computer speed, may make the App\n" + "unresponsive. Can have a value between 2 and 16.\n" + "Default value is 2.\n" + "After change, it will be applied at next App start.") + ) + 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) + + # Geometric tolerance + tol_label = QtWidgets.QLabel('%s:' % _("Geo Tolerance")) + tol_label.setToolTip(_( + "This value can counter the effect of the Circle Steps\n" + "parameter. Default value is 0.005.\n" + "A lower value will increase the detail both in image\n" + "and in Gcode for the circles, with a higher cost in\n" + "performance. Higher value will provide more\n" + "performance at the expense of level of detail." + )) + self.tol_entry = FCDoubleSpinner() + 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) + + separator_line = QtWidgets.QFrame() + separator_line.setFrameShape(QtWidgets.QFrame.HLine) + separator_line.setFrameShadow(QtWidgets.QFrame.Sunken) + grid0.addWidget(separator_line, 27, 0, 1, 2) + + # Save Settings + self.save_label = QtWidgets.QLabel('%s' % _("Save Settings")) + grid0.addWidget(self.save_label, 28, 0, 1, 2) + + # Save compressed project CB + self.save_type_cb = FCCheckBox(_('Save Compressed Project')) + self.save_type_cb.setToolTip( + _("Whether to save a compressed or uncompressed project.\n" + "When checked it will save a compressed FlatCAM project.") + ) + + grid0.addWidget(self.save_type_cb, 29, 0, 1, 2) + + # Project LZMA Comppression Level + self.compress_spinner = FCSpinner() + self.compress_spinner.set_range(0, 9) + self.compress_label = QtWidgets.QLabel('%s:' % _('Compression')) + self.compress_label.setToolTip( + _("The level of compression used when saving\n" + "a FlatCAM project. Higher value means better compression\n" + "but require more RAM usage and more processing time.") + ) + + grid0.addWidget(self.compress_label, 30, 0) + grid0.addWidget(self.compress_spinner, 30, 1) + + self.proj_ois = OptionalInputSection(self.save_type_cb, [self.compress_label, self.compress_spinner], True) + + # Auto save CB + self.autosave_cb = FCCheckBox(_('Enable Auto Save')) + self.autosave_cb.setToolTip( + _("Check to enable the autosave feature.\n" + "When enabled, the application will try to save a project\n" + "at the set interval.") + ) + + grid0.addWidget(self.autosave_cb, 31, 0, 1, 2) + + # Auto Save Timeout Interval + self.autosave_entry = FCSpinner() + self.autosave_entry.set_range(0, 9999999) + self.autosave_label = QtWidgets.QLabel('%s:' % _('Interval')) + self.autosave_label.setToolTip( + _("Time interval for autosaving. In milliseconds.\n" + "The application will try to save periodically but only\n" + "if the project was saved manually at least once.\n" + "While active, some operations may block this feature.") + ) + + grid0.addWidget(self.autosave_label, 32, 0) + grid0.addWidget(self.autosave_entry, 32, 1) - self.save_compressed_field = self.option_dict()["global_save_compressed"].get_field() - self.compression_label = self.option_dict()["global_compression_level"].label_widget - self.compression_field = self.option_dict()["global_compression_level"].get_field() - self.proj_ois = OptionalInputSection(self.save_compressed_field, [self.compression_label, self.compression_field], True) # self.as_ois = OptionalInputSection(self.autosave_cb, [self.autosave_label, self.autosave_entry], True) - def build_options(self) -> [OptionUI]: - return [ - RadioSetOptionUI( - option="units", - label_text="Units", - label_tooltip="The default value for FlatCAM units.\n" - "Whatever is selected here is set every time\n" - "FlatCAM is started.", - label_bold=True, - label_color="red", - choices=[{'label': _('MM'), 'value': 'MM'}, - {'label': _('IN'), 'value': 'IN'}] - ), - SpinnerOptionUI( - option="decimals_metric", - label_text="Precision MM", - label_tooltip="The number of decimals used throughout the application\n" - "when the set units are in METRIC system.\n" - "Any change here require an application restart.", - min_value=2, max_value=16, step=1 - ), - SpinnerOptionUI( - option="decimals_metric", - label_text="Precision INCH", - label_tooltip="The number of decimals used throughout the application\n" - "when the set units are in INCH system.\n" - "Any change here require an application restart.", - min_value=2, max_value=16, step=1 - ), - RadioSetOptionUI( - option="global_graphic_engine", - label_text='Graphic Engine', - label_tooltip="Choose what graphic engine to use in FlatCAM.\n" - "Legacy(2D) -> reduced functionality, slow performance but enhanced compatibility.\n" - "OpenGL(3D) -> full functionality, high performance\n" - "Some graphic cards are too old and do not work in OpenGL(3D) mode, like:\n" - "Intel HD3000 or older. In this case the plot area will be black therefore\n" - "use the Legacy(2D) mode.", - label_bold=True, - choices=[{'label': _('Legacy(2D)'), 'value': '2D'}, - {'label': _('OpenGL(3D)'), 'value': '3D'}], - orientation="vertical" - ), - SeparatorOptionUI(), + separator_line = QtWidgets.QFrame() + separator_line.setFrameShape(QtWidgets.QFrame.HLine) + separator_line.setFrameShadow(QtWidgets.QFrame.Sunken) + grid0.addWidget(separator_line, 33, 0, 1, 2) - RadioSetOptionUI( - option="global_app_level", - label_text="APP. LEVEL", - label_tooltip="Choose the default level of usage for FlatCAM.\n" - "BASIC level -> reduced functionality, best for beginner's.\n" - "ADVANCED level -> full functionality.\n\n" - "The choice here will influence the parameters in\n" - "the Selected Tab for all kinds of FlatCAM objects.", - label_bold=True, - label_color="red", - choices=[{'label': _('Basic'), 'value': 'b'}, - {'label': _('Advanced'), 'value': 'a'}] - ), - CheckboxOptionUI( - option="global_portable", - label_text="Portable app", - label_tooltip="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." - ), - SeparatorOptionUI(), + self.pdf_param_label = QtWidgets.QLabel('%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) - HeadingOptionUI(label_text="Languages", label_tooltip="Set the language used throughout FlatCAM."), - ComboboxOptionUI( - option="global_language", - label_text="Language", - label_tooltip="Set the language used throughout FlatCAM.", - choices=[] # FIXME: choices should be added here instead of in App - ), - FullWidthButtonOptionUI( - option="__apply_language_button", - label_text="Apply Language", - label_tooltip="Set the language used throughout FlatCAM.\n" - "The app will restart after click." - ), - SeparatorOptionUI(), + # Top Margin value + self.tmargin_entry = FCDoubleSpinner() + self.tmargin_entry.set_precision(self.decimals) + self.tmargin_entry.set_range(0.0000, 9999.9999) - HeadingOptionUI("Startup Settings", label_tooltip=None), - CheckboxOptionUI( - option="splash_screen", - label_text="Splash Screen", - label_tooltip="Enable display of the splash screen at application startup." - ), - CheckboxOptionUI( - option="global_systray_icon", - label_text="Sys Tray Icon", - label_tooltip="Enable display of FlatCAM icon in Sys Tray." - ), - CheckboxOptionUI( - option="global_shell_at_startup", - label_text="Show Shell", - label_tooltip="Check this box if you want the shell to\n" - "start automatically at startup." - ), - CheckboxOptionUI( - option="global_project_at_startup", - label_text="Show Project", - label_tooltip="Check this box if you want the project/selected/tool tab area to\n" - "to be shown automatically at startup." - ), - CheckboxOptionUI( - option="global_version_check", - label_text="Version Check", - label_tooltip="Check this box if you want to check\n" - "for a new version automatically at startup." - ), - CheckboxOptionUI( - option="global_send_stats", - label_text="Send Statistics", - label_tooltip="Check this box if you agree to send anonymous\n" - "stats automatically at startup, to help improve FlatCAM." - ), - SeparatorOptionUI(), + self.tmargin_label = QtWidgets.QLabel('%s:' % _("Top Margin")) + self.tmargin_label.setToolTip( + _("Distance between text body and the top of the PDF file.") + ) - SpinnerOptionUI( - option="global_worker_number", - label_text="Workers number", - label_tooltip="The number of Qthreads made available to the App.\n" - "A bigger number may finish the jobs more quickly but\n" - "depending on your computer speed, may make the App\n" - "unresponsive. Can have a value between 2 and 16.\n" - "Default value is 2.\n" - "After change, it will be applied at next App start.", - min_value=2, max_value=16, step=1 - ), - DoubleSpinnerOptionUI( - option="global_tolerance", - label_text="Geo Tolerance", - label_tooltip="This value can counter the effect of the Circle Steps\n" - "parameter. Default value is 0.005.\n" - "A lower value will increase the detail both in image\n" - "and in Gcode for the circles, with a higher cost in\n" - "performance. Higher value will provide more\n" - "performance at the expense of level of detail.", - min_value=0.0, max_value=100.0, step=0.001, decimals=6 - ), - SeparatorOptionUI(), + grid0.addWidget(self.tmargin_label, 35, 0) + grid0.addWidget(self.tmargin_entry, 35, 1) - HeadingOptionUI(label_text="Save Settings"), - CheckboxOptionUI( - option="global_save_compressed", - label_text="Save Compressed Project", - label_tooltip="Whether to save a compressed or uncompressed project.\n" - "When checked it will save a compressed FlatCAM project." - ), - SpinnerOptionUI( - option="global_compression_level", - label_text="Compression", - label_tooltip="The level of compression used when saving\n" - "a FlatCAM project. Higher value means better compression\n" - "but require more RAM usage and more processing time.", - min_value=0, max_value=9, step=1 - ), - CheckboxOptionUI( - option="global_autosave", - label_text="Enable Auto Save", - label_tooltip="Check to enable the autosave feature.\n" - "When enabled, the application will try to save a project\n" - "at the set interval." - ), - SpinnerOptionUI( - option="global_autosave_timeout", - label_text="Interval", - label_tooltip="Time interval for autosaving. In milliseconds.\n" - "The application will try to save periodically but only\n" - "if the project was saved manually at least once.\n" - "While active, some operations may block this feature.", - min_value=500, max_value=9999999, step=60000 - ), - SeparatorOptionUI(), + # Bottom Margin value + self.bmargin_entry = FCDoubleSpinner() + self.bmargin_entry.set_precision(self.decimals) + self.bmargin_entry.set_range(0.0000, 9999.9999) - HeadingOptionUI( - label_text="Text to PDF parameters", - label_tooltip="Used when saving text in Code Editor or in FlatCAM Document objects." - ), - DoubleSpinnerOptionUI( - option="global_tpdf_tmargin", - label_text="Top Margin", - label_tooltip="Distance between text body and the top of the PDF file.", - min_value=0.0, max_value=9999.9999, step=1, decimals=2 - ), - DoubleSpinnerOptionUI( - option="global_tpdf_bmargin", - label_text="Bottom Margin", - label_tooltip="Distance between text body and the bottom of the PDF file.", - min_value=0.0, max_value=9999.9999, step=1, decimals=2 - ), - DoubleSpinnerOptionUI( - option="global_tpdf_lmargin", - label_text="Left Margin", - label_tooltip="Distance between text body and the left of the PDF file.", - min_value=0.0, max_value=9999.9999, step=1, decimals=2 - ), - DoubleSpinnerOptionUI( - option="global_tpdf_rmargin", - label_text="Right Margin", - label_tooltip="Distance between text body and the right of the PDF file.", - min_value=0.0, max_value=9999.9999, step=1, decimals=2 - ) - ] + self.bmargin_label = QtWidgets.QLabel('%s:' % _("Bottom Margin")) + self.bmargin_label.setToolTip( + _("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) + + # Left Margin value + self.lmargin_entry = FCDoubleSpinner() + self.lmargin_entry.set_precision(self.decimals) + self.lmargin_entry.set_range(0.0000, 9999.9999) + + self.lmargin_label = QtWidgets.QLabel('%s:' % _("Left Margin")) + self.lmargin_label.setToolTip( + _("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) + + # Right Margin value + self.rmargin_entry = FCDoubleSpinner() + self.rmargin_entry.set_precision(self.decimals) + self.rmargin_entry.set_range(0.0000, 9999.9999) + + self.rmargin_label = QtWidgets.QLabel('%s:' % _("Right Margin")) + self.rmargin_label.setToolTip( + _("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) + + self.layout.addStretch() + + if sys.platform != 'win32': + self.portability_cb.hide() + + # splash screen button signal + self.splash_cb.stateChanged.connect(self.on_splash_changed) + + # Monitor the checkbox from the Application Defaults Tab and show the TCL shell or not depending on it's value + self.shell_startup_cb.clicked.connect(self.on_toggle_shell_from_settings) + + self.language_apply_btn.clicked.connect(lambda: fcTranslate.on_language_apply_click(app=self.app, restart=True)) def on_toggle_shell_from_settings(self, state): """ @@ -268,4 +399,4 @@ class GeneralAppPrefGroupUI(OptionsGroupUI2): qsettings.setValue('splash_screen', 1) if state else qsettings.setValue('splash_screen', 0) # This will write the setting to the platform specific storage. - del qsettings \ No newline at end of file + del qsettings diff --git a/flatcamGUI/preferences/general/GeneralAppSettingsGroupUI.py b/flatcamGUI/preferences/general/GeneralAppSettingsGroupUI.py deleted file mode 100644 index 1978bd6d..00000000 --- a/flatcamGUI/preferences/general/GeneralAppSettingsGroupUI.py +++ /dev/null @@ -1,301 +0,0 @@ -from PyQt5 import QtCore -from PyQt5.QtCore import QSettings -from flatcamGUI.GUIElements import OptionalInputSection -from flatcamGUI.preferences import settings -from flatcamGUI.preferences.OptionUI import * -from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI2 - -import gettext -import FlatCAMTranslation as fcTranslate -import builtins -fcTranslate.apply_language('strings') -if '_' not in builtins.__dict__: - _ = gettext.gettext - - -class GeneralAppSettingsGroupUI(OptionsGroupUI2): - def __init__(self, decimals=4, **kwargs): - self.decimals = decimals - self.pagesize = {} - self.pagesize.update( - { - 'A0': (841, 1189), - 'A1': (594, 841), - 'A2': (420, 594), - 'A3': (297, 420), - 'A4': (210, 297), - 'A5': (148, 210), - 'A6': (105, 148), - 'A7': (74, 105), - 'A8': (52, 74), - 'A9': (37, 52), - 'A10': (26, 37), - - 'B0': (1000, 1414), - 'B1': (707, 1000), - 'B2': (500, 707), - 'B3': (353, 500), - 'B4': (250, 353), - 'B5': (176, 250), - 'B6': (125, 176), - 'B7': (88, 125), - 'B8': (62, 88), - 'B9': (44, 62), - 'B10': (31, 44), - - 'C0': (917, 1297), - 'C1': (648, 917), - 'C2': (458, 648), - 'C3': (324, 458), - 'C4': (229, 324), - 'C5': (162, 229), - 'C6': (114, 162), - 'C7': (81, 114), - 'C8': (57, 81), - 'C9': (40, 57), - 'C10': (28, 40), - - # American paper sizes - 'LETTER': (8.5, 11), - 'LEGAL': (8.5, 14), - 'ELEVENSEVENTEEN': (11, 17), - - # From https://en.wikipedia.org/wiki/Paper_size - 'JUNIOR_LEGAL': (5, 8), - 'HALF_LETTER': (5.5, 8), - 'GOV_LETTER': (8, 10.5), - 'GOV_LEGAL': (8.5, 13), - 'LEDGER': (17, 11), - } - ) - super().__init__(**kwargs) - - self.setTitle(str(_("App Settings"))) - - qsettings = QSettings("Open Source", "FlatCAM") - - self.notebook_font_size_field = self.option_dict()["notebook_font_size"].get_field() - if qsettings.contains("notebook_font_size"): - self.notebook_font_size_field.set_value(qsettings.value('notebook_font_size', type=int)) - else: - self.notebook_font_size_field.set_value(12) - - self.axis_font_size_field = self.option_dict()["axis_font_size"].get_field() - if qsettings.contains("axis_font_size"): - self.axis_font_size_field.set_value(qsettings.value('axis_font_size', type=int)) - else: - self.axis_font_size_field.set_value(8) - - self.textbox_font_size_field = self.option_dict()["textbox_font_size"].get_field() - if qsettings.contains("textbox_font_size"): - self.textbox_font_size_field.set_value(settings.value('textbox_font_size', type=int)) - else: - self.textbox_font_size_field.set_value(10) - - self.workspace_enabled_field = self.option_dict()["global_workspace"].get_field() - self.workspace_type_field = self.option_dict()["global_workspaceT"].get_field() - self.workspace_type_label = self.option_dict()["global_workspaceT"].label_widget - self.workspace_orientation_field = self.option_dict()["global_workspace_orientation"].get_field() - self.workspace_orientation_label = self.option_dict()["global_workspace_orientation"].label_widget - self.wks = OptionalInputSection(self.workspace_enabled_field, [self.workspace_type_label, self.workspace_type_field, self.workspace_orientation_label, self.workspace_orientation_field]) - - self.mouse_cursor_color_enabled_field = self.option_dict()["global_cursor_color_enabled"].get_field() - self.mouse_cursor_color_field = self.option_dict()["global_cursor_color"].get_field() - self.mouse_cursor_color_label = self.option_dict()["global_cursor_color"].label_widget - self.mois = OptionalInputSection(self.mouse_cursor_color_enabled_field, [self.mouse_cursor_color_label, self.mouse_cursor_color_field]) - self.mouse_cursor_color_enabled_field.stateChanged.connect(self.on_mouse_cursor_color_enable) - self.mouse_cursor_color_field.entry.editingFinished.connect(self.on_mouse_cursor_entry) - - def build_options(self) -> [OptionUI]: - return [ - HeadingOptionUI(label_text="Grid Settings", label_tooltip=None), - DoubleSpinnerOptionUI( - option="global_gridx", - label_text="X value", - label_tooltip="This is the Grid snap value on X axis.", - step=0.1, - decimals=self.decimals - ), - DoubleSpinnerOptionUI( - option="global_gridy", - label_text='Y value', - label_tooltip="This is the Grid snap value on Y axis.", - step=0.1, - decimals=self.decimals - ), - DoubleSpinnerOptionUI( - option="global_snap_max", - label_text="Snap Max", - label_tooltip="Max. magnet distance", - step=0.1, - decimals=self.decimals - ), - SeparatorOptionUI(), - - HeadingOptionUI(label_text="Workspace Settings", label_tooltip=None), - CheckboxOptionUI( - option="global_workspace", - label_text="Active", - label_tooltip="Draw a delimiting rectangle on canvas.\n" - "The purpose is to illustrate the limits for our work." - ), - ComboboxOptionUI( - option="global_workspaceT", - label_text="Size", - label_tooltip="Select the type of rectangle to be used on canvas,\nas valid workspace.", - choices=list(self.pagesize.keys()) - ), - RadioSetOptionUI( - option="global_workspace_orientation", - label_text="Orientation", - label_tooltip="Can be:\n- Portrait\n- Landscape", - choices=[ - {'label': _('Portrait'), 'value': 'p'}, - {'label': _('Landscape'), 'value': 'l'}, - ] - ), - # FIXME enabling OptionalInputSection ?? - SeparatorOptionUI(), - - HeadingOptionUI(label_text="Font Size", label_tooltip=None), - SpinnerOptionUI( - option="notebook_font_size", - label_text="Notebook", - label_tooltip="This sets the font size for the elements found in the Notebook.\n" - "The notebook is the collapsible area in the left side of the GUI,\n" - "and include the Project, Selected and Tool tabs.", - min_value=8, max_value=40, step=1 - ), - SpinnerOptionUI( - option="axis_font_size", - label_text="Axis", - label_tooltip="This sets the font size for canvas axis.", - min_value=8, max_value=40, step=1 - ), - SpinnerOptionUI( - option="textbox_font_size", - label_text="Textbox", - label_tooltip="This sets the font size for the Textbox GUI\n" - "elements that are used in FlatCAM.", - min_value=8, max_value=40, step=1 - ), - SeparatorOptionUI(), - - HeadingOptionUI(label_text="Mouse Settings", label_tooltip=None), - RadioSetOptionUI( - option="global_cursor_type", - label_text="Cursor Shape", - label_tooltip="Choose a mouse cursor shape.\n" - "- Small -> with a customizable size.\n" - "- Big -> Infinite lines", - choices=[ - {"label": _("Small"), "value": "small"}, - {"label": _("Big"), "value": "big"} - ] - ), - SpinnerOptionUI( - option="global_cursor_size", - label_text="Cursor Size", - label_tooltip="Set the size of the mouse cursor, in pixels.", - min_value=10, max_value=70, step=1 - ), - SpinnerOptionUI( - option="global_cursor_width", - label_text="Cursor Width", - label_tooltip="Set the line width of the mouse cursor, in pixels.", - min_value=1, max_value=10, step=1 - ), - CheckboxOptionUI( - option="global_cursor_color_enabled", - label_text="Cursor Color", - label_tooltip="Check this box to color mouse cursor." - ), - ColorOptionUI( - option="global_cursor_color", - label_text="Cursor Color", - label_tooltip="Set the color of the mouse cursor." - ), - # FIXME enabling of cursor color - RadioSetOptionUI( - option="global_pan_button", - label_text="Pan Button", - label_tooltip="Select the mouse button to use for panning:\n" - "- MMB --> Middle Mouse Button\n" - "- RMB --> Right Mouse Button", - choices=[{'label': _('MMB'), 'value': '3'}, - {'label': _('RMB'), 'value': '2'}] - ), - RadioSetOptionUI( - option="global_mselect_key", - label_text="Multiple Selection", - label_tooltip="Select the key used for multiple selection.", - choices=[{'label': _('CTRL'), 'value': 'Control'}, - {'label': _('SHIFT'), 'value': 'Shift'}] - ), - SeparatorOptionUI(), - - CheckboxOptionUI( - option="global_delete_confirmation", - label_text="Delete object confirmation", - label_tooltip="When checked the application will ask for user confirmation\n" - "whenever the Delete object(s) event is triggered, either by\n" - "menu shortcut or key shortcut." - ), - CheckboxOptionUI( - option="global_open_style", - label_text='"Open" behavior', - label_tooltip="When checked the path for the last saved file is used when saving files,\n" - "and the path for the last opened file is used when opening files.\n\n" - "When unchecked the path for opening files is the one used last: either the\n" - "path for saving files or the path for opening files." - ), - CheckboxOptionUI( - option="global_toggle_tooltips", - label_text="Enable ToolTips", - label_tooltip="Check this box if you want to have toolTips displayed\n" - "when hovering with mouse over items throughout the App." - ), - CheckboxOptionUI( - option="global_machinist_setting", - label_text="Allow Machinist Unsafe Settings", - label_tooltip="If checked, some of the application settings will be allowed\n" - "to have values that are usually unsafe to use.\n" - "Like Z travel negative values or Z Cut positive values.\n" - "It will applied at the next application start.\n" - "<>: Don't change this unless you know what you are doing !!!" - ), - SpinnerOptionUI( - option="global_bookmarks_limit", - label_text="Bookmarks limit", - label_tooltip="The maximum number of bookmarks that may be installed in the menu.\n" - "The number of bookmarks in the bookmark manager may be greater\n" - "but the menu will hold only so much.", - min_value=0, max_value=9999, step=1 - ), - ComboboxOptionUI( - option="global_activity_icon", - label_text="Activity Icon", - label_tooltip="Select the GIF that show activity when FlatCAM is active.", - choices=['Ball black', 'Ball green', 'Arrow green', 'Eclipse green'] - ) - - ] - - def on_mouse_cursor_color_enable(self, val): - if val: - self.app.cursor_color_3D = self.app.defaults["global_cursor_color"] - else: - theme_settings = QtCore.QSettings("Open Source", "FlatCAM") - if theme_settings.contains("theme"): - theme = theme_settings.value('theme', type=str) - else: - theme = 'white' - - if theme == 'white': - self.app.cursor_color_3D = 'black' - else: - self.app.cursor_color_3D = 'gray' - - def on_mouse_cursor_entry(self): - self.app.defaults['global_cursor_color'] = self.mouse_cursor_color_field.get_value() - self.app.cursor_color_3D = self.app.defaults["global_cursor_color"] diff --git a/flatcamGUI/preferences/general/GeneralGUIPrefGroupUI.py b/flatcamGUI/preferences/general/GeneralGUIPrefGroupUI.py index 44172641..baedacc7 100644 --- a/flatcamGUI/preferences/general/GeneralGUIPrefGroupUI.py +++ b/flatcamGUI/preferences/general/GeneralGUIPrefGroupUI.py @@ -1,187 +1,423 @@ -from PyQt5 import QtWidgets, QtCore -from PyQt5.QtCore import QSettings -from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI2 +from PyQt5 import QtWidgets, QtCore, QtGui +from PyQt5.QtCore import QSettings, Qt + +from flatcamGUI.GUIElements import RadioSet, FCCheckBox, FCButton, FCComboBox, FCEntry, FCSpinner +from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI import gettext import FlatCAMTranslation as fcTranslate import builtins + fcTranslate.apply_language('strings') if '_' not in builtins.__dict__: _ = gettext.gettext -from flatcamGUI.preferences.OptionUI import OptionUI, CheckboxOptionUI, RadioSetOptionUI, \ - SeparatorOptionUI, HeadingOptionUI, ComboboxOptionUI, ColorOptionUI, FullWidthButtonOptionUI, \ - SliderWithSpinnerOptionUI, ColorAlphaSliderOptionUI +settings = QSettings("Open Source", "FlatCAM") +if settings.contains("machinist"): + machinist_setting = settings.value('machinist', type=int) +else: + machinist_setting = 0 -class GeneralGUIPrefGroupUI(OptionsGroupUI2): +class GeneralGUIPrefGroupUI(OptionsGroupUI): + def __init__(self, decimals=4, parent=None): + super(GeneralGUIPrefGroupUI, self).__init__(self, parent=parent) - def __init__(self, decimals=4, **kwargs): - self.decimals = decimals - super().__init__(**kwargs) self.setTitle(str(_("GUI Preferences"))) + self.decimals = decimals - self.layout_field = self.option_dict()["layout"].get_field() - self.layout_field.activated.connect(self.on_layout) + # Create a grid layout for the Application general settings + grid0 = QtWidgets.QGridLayout() + self.layout.addLayout(grid0) + grid0.setColumnStretch(0, 0) + grid0.setColumnStretch(1, 1) - self.theme_field = self.option_dict()["global_theme"].get_field() + # Theme selection + self.theme_label = QtWidgets.QLabel('%s:' % _('Theme')) + self.theme_label.setToolTip( + _("Select a theme for FlatCAM.\n" + "It will theme the plot area.") + ) - self.style_field = self.option_dict()["style"].get_field() - current_style_index = self.style_field.findText(QtWidgets.qApp.style().objectName(), QtCore.Qt.MatchFixedString) - self.style_field.setCurrentIndex(current_style_index) - self.style_field.activated[str].connect(self.handle_style) + self.theme_radio = RadioSet([ + {"label": _("Light"), "value": "white"}, + {"label": _("Dark"), "value": "black"} + ], orientation='vertical') + + grid0.addWidget(self.theme_label, 0, 0) + grid0.addWidget(self.theme_radio, 0, 1) + + # Enable Gray Icons + self.gray_icons_cb = FCCheckBox('%s' % _('Use Gray Icons')) + self.gray_icons_cb.setToolTip( + _("Check this box to use a set of icons with\n" + "a lighter (gray) color. To be used when a\n" + "full dark theme is applied.") + ) + grid0.addWidget(self.gray_icons_cb, 1, 0, 1, 3) + + # self.theme_button = FCButton(_("Apply Theme")) + # self.theme_button.setToolTip( + # _("Select a theme for FlatCAM.\n" + # "It will theme the plot area.\n" + # "The application will restart after change.") + # ) + # grid0.addWidget(self.theme_button, 2, 0, 1, 3) + + separator_line = QtWidgets.QFrame() + separator_line.setFrameShape(QtWidgets.QFrame.HLine) + separator_line.setFrameShadow(QtWidgets.QFrame.Sunken) + grid0.addWidget(separator_line, 3, 0, 1, 2) + + # Layout selection + self.layout_label = QtWidgets.QLabel('%s:' % _('Layout')) + self.layout_label.setToolTip( + _("Select an layout for FlatCAM.\n" + "It is applied immediately.") + ) + self.layout_combo = FCComboBox() + # don't translate the QCombo items as they are used in QSettings and identified by name + self.layout_combo.addItem("standard") + self.layout_combo.addItem("compact") + self.layout_combo.addItem("minimal") + + grid0.addWidget(self.layout_label, 4, 0) + grid0.addWidget(self.layout_combo, 4, 1) + + # Set the current index for layout_combo + qsettings = QSettings("Open Source", "FlatCAM") + if qsettings.contains("layout"): + layout = qsettings.value('layout', type=str) + idx = self.layout_combo.findText(layout.capitalize()) + self.layout_combo.setCurrentIndex(idx) + + # Style selection + self.style_label = QtWidgets.QLabel('%s:' % _('Style')) + self.style_label.setToolTip( + _("Select an style for FlatCAM.\n" + "It will be applied at the next app start.") + ) + self.style_combo = FCComboBox() + self.style_combo.addItems(QtWidgets.QStyleFactory.keys()) + # find current style + index = self.style_combo.findText(QtWidgets.qApp.style().objectName(), QtCore.Qt.MatchFixedString) + self.style_combo.setCurrentIndex(index) + self.style_combo.activated[str].connect(self.handle_style) + + grid0.addWidget(self.style_label, 5, 0) + grid0.addWidget(self.style_combo, 5, 1) + + # Enable High DPI Support + self.hdpi_cb = FCCheckBox('%s' % _('Activate HDPI Support')) + self.hdpi_cb.setToolTip( + _("Enable High DPI support for FlatCAM.\n" + "It will be applied at the next app start.") + ) - self.hdpi_field = self.option_dict()["hdpi"].get_field() qsettings = QSettings("Open Source", "FlatCAM") if qsettings.contains("hdpi"): - self.hdpi_field.set_value(qsettings.value('hdpi', type=int)) + self.hdpi_cb.set_value(qsettings.value('hdpi', type=int)) else: - self.hdpi_field.set_value(False) - self.hdpi_field.stateChanged.connect(self.handle_hdpi) + self.hdpi_cb.set_value(False) + self.hdpi_cb.stateChanged.connect(self.handle_hdpi) - def build_options(self) -> [OptionUI]: - return [ - RadioSetOptionUI( - option="global_theme", - label_text="Theme", - label_tooltip="Select a theme for FlatCAM.\nIt will theme the plot area.", - choices=[ - {"label": _("Light"), "value": "white"}, - {"label": _("Dark"), "value": "black"} - ], - orientation='vertical' - ), - CheckboxOptionUI( - option="global_gray_icons", - label_text="Use Gray Icons", - label_tooltip="Check this box to use a set of icons with\na lighter (gray) color. To be used when a\nfull dark theme is applied." - ), - SeparatorOptionUI(), + grid0.addWidget(self.hdpi_cb, 6, 0, 1, 3) - ComboboxOptionUI( - option="layout", - label_text="Layout", - label_tooltip="Select an layout for FlatCAM.\nIt is applied immediately.", - choices=[ - "standard", - "compact", - "minimal" - ] - ), - ComboboxOptionUI( - option="style", - label_text="Style", - label_tooltip="Select an style for FlatCAM.\nIt will be applied at the next app start.", - choices=QtWidgets.QStyleFactory.keys() - ), - CheckboxOptionUI( - option="hdpi", - label_text='Activate HDPI Support', - label_tooltip="Enable High DPI support for FlatCAM.\nIt will be applied at the next app start.", - ), - CheckboxOptionUI( - option="global_hover", - label_text='Display Hover Shape', - label_tooltip="Enable display of a hover shape for FlatCAM objects.\nIt is displayed whenever the mouse cursor is hovering\nover any kind of not-selected object.", - ), - CheckboxOptionUI( - option="global_selection_shape", - label_text='Display Selection Shape', - label_tooltip="Enable the display of a selection shape for FlatCAM objects.\n" - "It is displayed whenever the mouse selects an object\n" - "either by clicking or dragging mouse from left to right or\n" - "right to left." - ), - SeparatorOptionUI(), + # Enable Hover box + self.hover_cb = FCCheckBox('%s' % _('Display Hover Shape')) + self.hover_cb.setToolTip( + _("Enable display of a hover shape for FlatCAM objects.\n" + "It is displayed whenever the mouse cursor is hovering\n" + "over any kind of not-selected object.") + ) + grid0.addWidget(self.hover_cb, 8, 0, 1, 3) - HeadingOptionUI(label_text="Left-Right Selection Color", label_tooltip=None), - ColorOptionUI( - option="global_sel_line", - label_text="Outline", - label_tooltip="Set the line color for the 'left to right' selection box." - ), - ColorOptionUI( - option="global_sel_fill", - label_text="Fill", - label_tooltip="Set the fill color for the selection box\n" - "in case that the selection is done from left to right.\n" - "First 6 digits are the color and the last 2\n" - "digits are for alpha (transparency) level." - ), - ColorAlphaSliderOptionUI( - applies_to=["global_sel_line", "global_sel_fill"], - group=self, - label_text="Alpha", - label_tooltip="Set the fill transparency for the 'left to right' selection box." - ), - SeparatorOptionUI(), + # Enable Selection box + self.selection_cb = FCCheckBox('%s' % _('Display Selection Shape')) + self.selection_cb.setToolTip( + _("Enable the display of a selection shape for FlatCAM objects.\n" + "It is displayed whenever the mouse selects an object\n" + "either by clicking or dragging mouse from left to right or\n" + "right to left.") + ) + grid0.addWidget(self.selection_cb, 9, 0, 1, 3) - HeadingOptionUI(label_text="Right-Left Selection Color", label_tooltip=None), - ColorOptionUI( - option="global_alt_sel_line", - label_text="Outline", - label_tooltip="Set the line color for the 'right to left' selection box." - ), - ColorOptionUI( - option="global_alt_sel_fill", - label_text="Fill", - label_tooltip="Set the fill color for the selection box\n" - "in case that the selection is done from right to left.\n" - "First 6 digits are the color and the last 2\n" - "digits are for alpha (transparency) level." - ), - ColorAlphaSliderOptionUI( - applies_to=["global_alt_sel_line", "global_alt_sel_fill"], - group=self, - label_text="Alpha", - label_tooltip="Set the fill transparency for the 'right to left' selection box." - ), - SeparatorOptionUI(), + separator_line = QtWidgets.QFrame() + separator_line.setFrameShape(QtWidgets.QFrame.HLine) + separator_line.setFrameShadow(QtWidgets.QFrame.Sunken) + grid0.addWidget(separator_line, 14, 0, 1, 2) - HeadingOptionUI(label_text='Editor Color', label_tooltip=None), - ColorOptionUI( - option="global_draw_color", - label_text="Drawing", - label_tooltip="Set the color for the shape." - ), - ColorOptionUI( - option="global_sel_draw_color", - label_text="Selection", - label_tooltip="Set the color of the shape when selected." - ), - SeparatorOptionUI(), + # Plot Selection (left - right) Color + self.sel_lr_label = QtWidgets.QLabel('%s' % _('Left-Right Selection Color')) + grid0.addWidget(self.sel_lr_label, 15, 0, 1, 2) - HeadingOptionUI(label_text='Project Items Color', label_tooltip=None), - ColorOptionUI( - option="global_proj_item_color", - label_text="Enabled", - label_tooltip="Set the color of the items in Project Tab Tree." - ), - ColorOptionUI( - option="global_proj_item_dis_color", - label_text="Disabled", - label_tooltip="Set the color of the items in Project Tab Tree,\n" - "for the case when the items are disabled." - ), - CheckboxOptionUI( - option="global_project_autohide", - label_text="Project AutoHide", - label_tooltip="Check this box if you want the project/selected/tool tab area to\n" - "hide automatically when there are no objects loaded and\n" - "to show whenever a new object is created." - ), - ] + self.sl_color_label = QtWidgets.QLabel('%s:' % _('Outline')) + self.sl_color_label.setToolTip( + _("Set the line color for the 'left to right' selection box.") + ) + self.sl_color_entry = FCEntry() + self.sl_color_button = QtWidgets.QPushButton() + self.sl_color_button.setFixedSize(15, 15) - def on_layout(self, index=None, lay=None): - if lay: - current_layout = lay - else: - current_layout = self.layout_field.get_value() - self.app.ui.set_layout(current_layout) + self.form_box_child_4 = QtWidgets.QHBoxLayout() + self.form_box_child_4.addWidget(self.sl_color_entry) + self.form_box_child_4.addWidget(self.sl_color_button) + self.form_box_child_4.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter) + + grid0.addWidget(self.sl_color_label, 16, 0) + grid0.addLayout(self.form_box_child_4, 16, 1) + + self.sf_color_label = QtWidgets.QLabel('%s:' % _('Fill')) + self.sf_color_label.setToolTip( + _("Set the fill color for the selection box\n" + "in case that the selection is done from left to right.\n" + "First 6 digits are the color and the last 2\n" + "digits are for alpha (transparency) level.") + ) + self.sf_color_entry = FCEntry() + self.sf_color_button = QtWidgets.QPushButton() + self.sf_color_button.setFixedSize(15, 15) + + self.form_box_child_5 = QtWidgets.QHBoxLayout() + self.form_box_child_5.addWidget(self.sf_color_entry) + self.form_box_child_5.addWidget(self.sf_color_button) + self.form_box_child_5.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter) + + grid0.addWidget(self.sf_color_label, 17, 0) + grid0.addLayout(self.form_box_child_5, 17, 1) + + # Plot Selection (left - right) Fill Transparency Level + self.sf_alpha_label = QtWidgets.QLabel('%s:' % _('Alpha')) + self.sf_alpha_label.setToolTip( + _("Set the fill transparency for the 'left to right' selection box.") + ) + self.sf_color_alpha_slider = QtWidgets.QSlider(QtCore.Qt.Horizontal) + self.sf_color_alpha_slider.setMinimum(0) + self.sf_color_alpha_slider.setMaximum(255) + self.sf_color_alpha_slider.setSingleStep(1) + + self.sf_color_alpha_spinner = FCSpinner() + self.sf_color_alpha_spinner.setMinimumWidth(70) + self.sf_color_alpha_spinner.set_range(0, 255) + + self.form_box_child_6 = QtWidgets.QHBoxLayout() + self.form_box_child_6.addWidget(self.sf_color_alpha_slider) + self.form_box_child_6.addWidget(self.sf_color_alpha_spinner) + + grid0.addWidget(self.sf_alpha_label, 18, 0) + grid0.addLayout(self.form_box_child_6, 18, 1) + + separator_line = QtWidgets.QFrame() + separator_line.setFrameShape(QtWidgets.QFrame.HLine) + separator_line.setFrameShadow(QtWidgets.QFrame.Sunken) + grid0.addWidget(separator_line, 19, 0, 1, 2) + + # Plot Selection (left - right) Color + self.sel_rl_label = QtWidgets.QLabel('%s' % _('Right-Left Selection Color')) + grid0.addWidget(self.sel_rl_label, 20, 0, 1, 2) + + # Plot Selection (right - left) Line Color + self.alt_sl_color_label = QtWidgets.QLabel('%s:' % _('Outline')) + self.alt_sl_color_label.setToolTip( + _("Set the line color for the 'right to left' selection box.") + ) + self.alt_sl_color_entry = FCEntry() + self.alt_sl_color_button = QtWidgets.QPushButton() + self.alt_sl_color_button.setFixedSize(15, 15) + + self.form_box_child_7 = QtWidgets.QHBoxLayout() + self.form_box_child_7.addWidget(self.alt_sl_color_entry) + self.form_box_child_7.addWidget(self.alt_sl_color_button) + self.form_box_child_7.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter) + + grid0.addWidget(self.alt_sl_color_label, 21, 0) + grid0.addLayout(self.form_box_child_7, 21, 1) + + # Plot Selection (right - left) Fill Color + self.alt_sf_color_label = QtWidgets.QLabel('%s:' % _('Fill')) + self.alt_sf_color_label.setToolTip( + _("Set the fill color for the selection box\n" + "in case that the selection is done from right to left.\n" + "First 6 digits are the color and the last 2\n" + "digits are for alpha (transparency) level.") + ) + self.alt_sf_color_entry = FCEntry() + self.alt_sf_color_button = QtWidgets.QPushButton() + self.alt_sf_color_button.setFixedSize(15, 15) + + self.form_box_child_8 = QtWidgets.QHBoxLayout() + self.form_box_child_8.addWidget(self.alt_sf_color_entry) + self.form_box_child_8.addWidget(self.alt_sf_color_button) + self.form_box_child_8.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter) + + grid0.addWidget(self.alt_sf_color_label, 22, 0) + grid0.addLayout(self.form_box_child_8, 22, 1) + + # Plot Selection (right - left) Fill Transparency Level + self.alt_sf_alpha_label = QtWidgets.QLabel('%s:' % _('Alpha')) + self.alt_sf_alpha_label.setToolTip( + _("Set the fill transparency for selection 'right to left' box.") + ) + self.alt_sf_color_alpha_slider = QtWidgets.QSlider(QtCore.Qt.Horizontal) + self.alt_sf_color_alpha_slider.setMinimum(0) + self.alt_sf_color_alpha_slider.setMaximum(255) + self.alt_sf_color_alpha_slider.setSingleStep(1) + + self.alt_sf_color_alpha_spinner = FCSpinner() + self.alt_sf_color_alpha_spinner.setMinimumWidth(70) + self.alt_sf_color_alpha_spinner.set_range(0, 255) + + self.form_box_child_9 = QtWidgets.QHBoxLayout() + self.form_box_child_9.addWidget(self.alt_sf_color_alpha_slider) + self.form_box_child_9.addWidget(self.alt_sf_color_alpha_spinner) + + grid0.addWidget(self.alt_sf_alpha_label, 23, 0) + grid0.addLayout(self.form_box_child_9, 23, 1) + + separator_line = QtWidgets.QFrame() + separator_line.setFrameShape(QtWidgets.QFrame.HLine) + separator_line.setFrameShadow(QtWidgets.QFrame.Sunken) + grid0.addWidget(separator_line, 24, 0, 1, 2) + + # ------------------------------------------------------------------ + # ----------------------- Editor Color ----------------------------- + # ------------------------------------------------------------------ + + self.editor_color_label = QtWidgets.QLabel('%s' % _('Editor Color')) + grid0.addWidget(self.editor_color_label, 25, 0, 1, 2) + + # Editor Draw Color + self.draw_color_label = QtWidgets.QLabel('%s:' % _('Drawing')) + self.alt_sf_color_label.setToolTip( + _("Set the color for the shape.") + ) + self.draw_color_entry = FCEntry() + self.draw_color_button = QtWidgets.QPushButton() + self.draw_color_button.setFixedSize(15, 15) + + self.form_box_child_10 = QtWidgets.QHBoxLayout() + self.form_box_child_10.addWidget(self.draw_color_entry) + self.form_box_child_10.addWidget(self.draw_color_button) + self.form_box_child_10.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter) + + grid0.addWidget(self.draw_color_label, 26, 0) + grid0.addLayout(self.form_box_child_10, 26, 1) + + # Editor Draw Selection Color + self.sel_draw_color_label = QtWidgets.QLabel('%s:' % _('Selection')) + self.sel_draw_color_label.setToolTip( + _("Set the color of the shape when selected.") + ) + self.sel_draw_color_entry = FCEntry() + self.sel_draw_color_button = QtWidgets.QPushButton() + self.sel_draw_color_button.setFixedSize(15, 15) + + self.form_box_child_11 = QtWidgets.QHBoxLayout() + self.form_box_child_11.addWidget(self.sel_draw_color_entry) + self.form_box_child_11.addWidget(self.sel_draw_color_button) + self.form_box_child_11.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter) + + grid0.addWidget(self.sel_draw_color_label, 27, 0) + grid0.addLayout(self.form_box_child_11, 27, 1) + + separator_line = QtWidgets.QFrame() + separator_line.setFrameShape(QtWidgets.QFrame.HLine) + separator_line.setFrameShadow(QtWidgets.QFrame.Sunken) + grid0.addWidget(separator_line, 28, 0, 1, 2) + + # ------------------------------------------------------------------ + # ----------------------- Project Settings ----------------------------- + # ------------------------------------------------------------------ + + self.proj_settings_label = QtWidgets.QLabel('%s' % _('Project Items Color')) + grid0.addWidget(self.proj_settings_label, 29, 0, 1, 2) + + # Project Tab items color + self.proj_color_label = QtWidgets.QLabel('%s:' % _('Enabled')) + self.proj_color_label.setToolTip( + _("Set the color of the items in Project Tab Tree.") + ) + self.proj_color_entry = FCEntry() + self.proj_color_button = QtWidgets.QPushButton() + self.proj_color_button.setFixedSize(15, 15) + + self.form_box_child_12 = QtWidgets.QHBoxLayout() + self.form_box_child_12.addWidget(self.proj_color_entry) + self.form_box_child_12.addWidget(self.proj_color_button) + self.form_box_child_12.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter) + + grid0.addWidget(self.proj_color_label, 30, 0) + grid0.addLayout(self.form_box_child_12, 30, 1) + + self.proj_color_dis_label = QtWidgets.QLabel('%s:' % _('Disabled')) + self.proj_color_dis_label.setToolTip( + _("Set the color of the items in Project Tab Tree,\n" + "for the case when the items are disabled.") + ) + self.proj_color_dis_entry = FCEntry() + self.proj_color_dis_button = QtWidgets.QPushButton() + self.proj_color_dis_button.setFixedSize(15, 15) + + self.form_box_child_13 = QtWidgets.QHBoxLayout() + self.form_box_child_13.addWidget(self.proj_color_dis_entry) + self.form_box_child_13.addWidget(self.proj_color_dis_button) + self.form_box_child_13.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter) + + grid0.addWidget(self.proj_color_dis_label, 31, 0) + grid0.addLayout(self.form_box_child_13, 31, 1) + + # Project autohide CB + self.project_autohide_cb = FCCheckBox(label=_('Project AutoHide')) + self.project_autohide_cb.setToolTip( + _("Check this box if you want the project/selected/tool tab area to\n" + "hide automatically when there are no objects loaded and\n" + "to show whenever a new object is created.") + ) + + grid0.addWidget(self.project_autohide_cb, 32, 0, 1, 2) + + # Just to add empty rows + grid0.addWidget(QtWidgets.QLabel(''), 33, 0, 1, 2) + + self.layout.addStretch() + + # ############################################################################# + # ############################# GUI COLORS SIGNALS ############################ + # ############################################################################# + + # Setting selection (left - right) colors signals + self.sf_color_entry.editingFinished.connect(self.on_sf_color_entry) + self.sf_color_button.clicked.connect(self.on_sf_color_button) + self.sf_color_alpha_spinner.valueChanged.connect(self.on_sf_color_spinner) + self.sf_color_alpha_slider.valueChanged.connect(self.on_sf_color_slider) + self.sl_color_entry.editingFinished.connect(self.on_sl_color_entry) + self.sl_color_button.clicked.connect(self.on_sl_color_button) + + # Setting selection (right - left) colors signals + self.alt_sf_color_entry.editingFinished.connect(self.on_alt_sf_color_entry) + self.alt_sf_color_button.clicked.connect(self.on_alt_sf_color_button) + self.alt_sf_color_alpha_spinner.valueChanged.connect(self.on_alt_sf_color_spinner) + self.alt_sf_color_alpha_slider.valueChanged.connect(self.on_alt_sf_color_slider) + self.alt_sl_color_entry.editingFinished.connect(self.on_alt_sl_color_entry) + self.alt_sl_color_button.clicked.connect(self.on_alt_sl_color_button) + + # Setting Editor Draw colors signals + self.draw_color_entry.editingFinished.connect(self.on_draw_color_entry) + self.draw_color_button.clicked.connect(self.on_draw_color_button) + + self.sel_draw_color_entry.editingFinished.connect(self.on_sel_draw_color_entry) + self.sel_draw_color_button.clicked.connect(self.on_sel_draw_color_button) + + self.proj_color_entry.editingFinished.connect(self.on_proj_color_entry) + self.proj_color_button.clicked.connect(self.on_proj_color_button) + + self.proj_color_dis_entry.editingFinished.connect(self.on_proj_color_dis_entry) + self.proj_color_dis_button.clicked.connect(self.on_proj_color_dis_button) + + self.layout_combo.activated.connect(self.on_layout) @staticmethod def handle_style(style): - # FIXME: this should be moved out to a view model # set current style qsettings = QSettings("Open Source", "FlatCAM") qsettings.setValue('style', style) @@ -191,10 +427,349 @@ class GeneralGUIPrefGroupUI(OptionsGroupUI2): @staticmethod def handle_hdpi(state): - # FIXME: this should be moved out to a view model # set current HDPI qsettings = QSettings("Open Source", "FlatCAM") qsettings.setValue('hdpi', state) # This will write the setting to the platform specific storage. - del qsettings \ No newline at end of file + del qsettings + + # Setting selection colors (left - right) handlers + def on_sf_color_entry(self): + self.app.defaults['global_sel_fill'] = self.app.defaults['global_sel_fill'][7:9] + self.sf_color_button.setStyleSheet("background-color:%s" % str(self.app.defaults['global_sel_fill'])[:7]) + + def on_sf_color_button(self): + current_color = QtGui.QColor(self.app.defaults['global_sel_fill'][:7]) + + c_dialog = QtWidgets.QColorDialog() + plot_fill_color = c_dialog.getColor(initial=current_color) + + if plot_fill_color.isValid() is False: + return + + self.sf_color_button.setStyleSheet("background-color:%s" % str(plot_fill_color.name())) + + new_val = str(plot_fill_color.name()) + str(self.app.defaults['global_sel_fill'][7:9]) + self.sf_color_entry.set_value(new_val) + self.app.defaults['global_sel_fill'] = new_val + + def on_sf_color_spinner(self): + spinner_value = self.sf_color_alpha_spinner.value() + self.sf_color_alpha_slider.setValue(spinner_value) + self.app.defaults['global_sel_fill'] = self.app.defaults['global_sel_fill'][:7] + \ + (hex(spinner_value)[2:] if int(hex(spinner_value)[2:], 16) > 0 else '00') + self.app.defaults['global_sel_line'] = self.app.defaults['global_sel_line'][:7] + \ + (hex(spinner_value)[2:] if int(hex(spinner_value)[2:], 16) > 0 else '00') + + def on_sf_color_slider(self): + slider_value = self.sf_color_alpha_slider.value() + self.sf_color_alpha_spinner.setValue(slider_value) + + def on_sl_color_entry(self): + self.app.defaults['global_sel_line'] = self.sl_color_entry.get_value()[:7] + \ + self.app.defaults['global_sel_line'][7:9] + self.sl_color_button.setStyleSheet("background-color:%s" % str(self.app.defaults['global_sel_line'])[:7]) + + def on_sl_color_button(self): + current_color = QtGui.QColor(self.app.defaults['global_sel_line'][:7]) + + c_dialog = QtWidgets.QColorDialog() + plot_line_color = c_dialog.getColor(initial=current_color) + + if plot_line_color.isValid() is False: + return + + self.sl_color_button.setStyleSheet("background-color:%s" % str(plot_line_color.name())) + + new_val_line = str(plot_line_color.name()) + str(self.app.defaults['global_sel_line'][7:9]) + self.sl_color_entry.set_value(new_val_line) + self.app.defaults['global_sel_line'] = new_val_line + + # Setting selection colors (right - left) handlers + def on_alt_sf_color_entry(self): + self.app.defaults['global_alt_sel_fill'] = self.alt_sf_color_entry.get_value()[:7] + \ + self.app.defaults['global_alt_sel_fill'][7:9] + self.alt_sf_color_button.setStyleSheet( + "background-color:%s" % str(self.app.defaults['global_alt_sel_fill'])[:7] + ) + + def on_alt_sf_color_button(self): + current_color = QtGui.QColor(self.app.defaults['global_alt_sel_fill'][:7]) + + c_dialog = QtWidgets.QColorDialog() + plot_fill_color = c_dialog.getColor(initial=current_color) + + if plot_fill_color.isValid() is False: + return + + self.alt_sf_color_button.setStyleSheet("background-color:%s" % str(plot_fill_color.name())) + + new_val = str(plot_fill_color.name()) + str(self.app.defaults['global_alt_sel_fill'][7:9]) + self.alt_sf_color_entry.set_value(new_val) + self.app.defaults['global_alt_sel_fill'] = new_val + + def on_alt_sf_color_spinner(self): + spinner_value = self.alt_sf_color_alpha_spinner.value() + self.alt_sf_color_alpha_slider.setValue(spinner_value) + self.app.defaults['global_alt_sel_fill'] = self.app.defaults['global_alt_sel_fill'][:7] + \ + (hex(spinner_value)[2:] if int(hex(spinner_value)[2:], 16) > 0 else '00') + self.app.defaults['global_alt_sel_line'] = self.app.defaults['global_alt_sel_line'][:7] + \ + (hex(spinner_value)[2:] if int(hex(spinner_value)[2:], 16) > 0 else '00') + + def on_alt_sf_color_slider(self): + slider_value = self.alt_sf_color_alpha_slider.value() + self.alt_sf_color_alpha_spinner.setValue(slider_value) + + def on_alt_sl_color_entry(self): + self.app.defaults['global_alt_sel_line'] = self.alt_sl_color_entry.get_value()[:7] + \ + self.app.defaults['global_alt_sel_line'][7:9] + self.alt_sl_color_button.setStyleSheet( + "background-color:%s" % str(self.app.defaults['global_alt_sel_line'])[:7] + ) + + def on_alt_sl_color_button(self): + current_color = QtGui.QColor(self.app.defaults['global_alt_sel_line'][:7]) + + c_dialog = QtWidgets.QColorDialog() + plot_line_color = c_dialog.getColor(initial=current_color) + + if plot_line_color.isValid() is False: + return + + self.alt_sl_color_button.setStyleSheet("background-color:%s" % str(plot_line_color.name())) + + new_val_line = str(plot_line_color.name()) + str(self.app.defaults['global_alt_sel_line'][7:9]) + self.alt_sl_color_entry.set_value(new_val_line) + self.app.defaults['global_alt_sel_line'] = new_val_line + + # Setting Editor colors + def on_draw_color_entry(self): + self.app.defaults['global_draw_color'] = self.draw_color_entry.get_value() + self.draw_color_button.setStyleSheet("background-color:%s" % str(self.app.defaults['global_draw_color'])) + + def on_draw_color_button(self): + current_color = QtGui.QColor(self.app.defaults['global_draw_color']) + + c_dialog = QtWidgets.QColorDialog() + draw_color = c_dialog.getColor(initial=current_color) + + if draw_color.isValid() is False: + return + + self.draw_color_button.setStyleSheet("background-color:%s" % str(draw_color.name())) + + new_val = str(draw_color.name()) + self.draw_color_entry.set_value(new_val) + self.app.defaults['global_draw_color'] = new_val + + def on_sel_draw_color_entry(self): + self.app.defaults['global_sel_draw_color'] = self.sel_draw_color_entry.get_value() + self.sel_draw_color_button.setStyleSheet( + "background-color:%s" % str(self.app.defaults['global_sel_draw_color'])) + + def on_sel_draw_color_button(self): + current_color = QtGui.QColor(self.app.defaults['global_sel_draw_color']) + + c_dialog = QtWidgets.QColorDialog() + sel_draw_color = c_dialog.getColor(initial=current_color) + + if sel_draw_color.isValid() is False: + return + + self.sel_draw_color_button.setStyleSheet("background-color:%s" % str(sel_draw_color.name())) + + new_val_sel = str(sel_draw_color.name()) + self.sel_draw_color_entry.set_value(new_val_sel) + self.app.defaults['global_sel_draw_color'] = new_val_sel + + def on_proj_color_entry(self): + self.app.defaults['global_proj_item_color'] = self.proj_color_entry.get_value() + self.proj_color_button.setStyleSheet( + "background-color:%s" % str(self.app.defaults['global_proj_item_color'])) + + def on_proj_color_button(self): + current_color = QtGui.QColor(self.app.defaults['global_proj_item_color']) + + c_dialog = QtWidgets.QColorDialog() + proj_color = c_dialog.getColor(initial=current_color) + + if proj_color.isValid() is False: + return + + self.proj_color_button.setStyleSheet("background-color:%s" % str(proj_color.name())) + + new_val_sel = str(proj_color.name()) + self.proj_color_entry.set_value(new_val_sel) + self.app.defaults['global_proj_item_color'] = new_val_sel + + def on_proj_color_dis_entry(self): + self.app.defaults['global_proj_item_dis_color'] = self.proj_color_dis_entry.get_value() + self.proj_color_dis_button.setStyleSheet( + "background-color:%s" % str(self.app.defaults['global_proj_item_dis_color'])) + + def on_proj_color_dis_button(self): + current_color = QtGui.QColor(self.app.defaults['global_proj_item_dis_color']) + + c_dialog = QtWidgets.QColorDialog() + proj_color = c_dialog.getColor(initial=current_color) + + if proj_color.isValid() is False: + return + + self.proj_color_dis_button.setStyleSheet("background-color:%s" % str(proj_color.name())) + + new_val_sel = str(proj_color.name()) + self.proj_color_dis_entry.set_value(new_val_sel) + self.app.defaults['global_proj_item_dis_color'] = new_val_sel + + def on_layout(self, index=None, lay=None): + """ + Set the toolbars layout (location) + + :param index: + :param lay: Type of layout to be set on the toolbard + :return: None + """ + + self.app.defaults.report_usage("on_layout()") + if lay: + current_layout = lay + else: + current_layout = self.layout_combo.get_value() + + lay_settings = QSettings("Open Source", "FlatCAM") + lay_settings.setValue('layout', current_layout) + + # This will write the setting to the platform specific storage. + del lay_settings + + # first remove the toolbars: + try: + self.app.ui.removeToolBar(self.app.ui.toolbarfile) + self.app.ui.removeToolBar(self.app.ui.toolbargeo) + self.app.ui.removeToolBar(self.app.ui.toolbarview) + self.app.ui.removeToolBar(self.app.ui.toolbarshell) + self.app.ui.removeToolBar(self.app.ui.toolbartools) + self.app.ui.removeToolBar(self.app.ui.exc_edit_toolbar) + self.app.ui.removeToolBar(self.app.ui.geo_edit_toolbar) + self.app.ui.removeToolBar(self.app.ui.grb_edit_toolbar) + self.app.ui.removeToolBar(self.app.ui.snap_toolbar) + self.app.ui.removeToolBar(self.app.ui.toolbarshell) + except Exception: + pass + + if current_layout == 'compact': + # ## TOOLBAR INSTALLATION # ## + self.app.ui.toolbarfile = QtWidgets.QToolBar('File Toolbar') + self.app.ui.toolbarfile.setObjectName('File_TB') + self.app.ui.addToolBar(Qt.LeftToolBarArea, self.app.ui.toolbarfile) + + self.app.ui.toolbargeo = QtWidgets.QToolBar('Edit Toolbar') + self.app.ui.toolbargeo.setObjectName('Edit_TB') + self.app.ui.addToolBar(Qt.LeftToolBarArea, self.app.ui.toolbargeo) + + self.app.ui.toolbarshell = QtWidgets.QToolBar('Shell Toolbar') + self.app.ui.toolbarshell.setObjectName('Shell_TB') + self.app.ui.addToolBar(Qt.LeftToolBarArea, self.app.ui.toolbarshell) + + self.app.ui.toolbartools = QtWidgets.QToolBar('Tools Toolbar') + self.app.ui.toolbartools.setObjectName('Tools_TB') + self.app.ui.addToolBar(Qt.LeftToolBarArea, self.app.ui.toolbartools) + + self.app.ui.geo_edit_toolbar = QtWidgets.QToolBar('Geometry Editor Toolbar') + # self.app.ui.geo_edit_toolbar.setVisible(False) + self.app.ui.geo_edit_toolbar.setObjectName('GeoEditor_TB') + self.app.ui.addToolBar(Qt.RightToolBarArea, self.app.ui.geo_edit_toolbar) + + self.app.ui.toolbarview = QtWidgets.QToolBar('View Toolbar') + self.app.ui.toolbarview.setObjectName('View_TB') + self.app.ui.addToolBar(Qt.RightToolBarArea, self.app.ui.toolbarview) + + self.app.ui.addToolBarBreak(area=Qt.RightToolBarArea) + + self.app.ui.grb_edit_toolbar = QtWidgets.QToolBar('Gerber Editor Toolbar') + # self.app.ui.grb_edit_toolbar.setVisible(False) + self.app.ui.grb_edit_toolbar.setObjectName('GrbEditor_TB') + self.app.ui.addToolBar(Qt.RightToolBarArea, self.app.ui.grb_edit_toolbar) + + self.app.ui.exc_edit_toolbar = QtWidgets.QToolBar('Excellon Editor Toolbar') + self.app.ui.exc_edit_toolbar.setObjectName('ExcEditor_TB') + self.app.ui.addToolBar(Qt.RightToolBarArea, self.app.ui.exc_edit_toolbar) + + self.app.ui.snap_toolbar = QtWidgets.QToolBar('Grid Toolbar') + self.app.ui.snap_toolbar.setObjectName('Snap_TB') + self.app.ui.snap_toolbar.setMaximumHeight(30) + self.app.ui.splitter_left.addWidget(self.app.ui.snap_toolbar) + + self.app.ui.corner_snap_btn.setVisible(True) + self.app.ui.snap_magnet.setVisible(True) + else: + # ## TOOLBAR INSTALLATION # ## + self.app.ui.toolbarfile = QtWidgets.QToolBar('File Toolbar') + self.app.ui.toolbarfile.setObjectName('File_TB') + self.app.ui.addToolBar(self.app.ui.toolbarfile) + + self.app.ui.toolbargeo = QtWidgets.QToolBar('Edit Toolbar') + self.app.ui.toolbargeo.setObjectName('Edit_TB') + self.app.ui.addToolBar(self.app.ui.toolbargeo) + + self.app.ui.toolbarview = QtWidgets.QToolBar('View Toolbar') + self.app.ui.toolbarview.setObjectName('View_TB') + self.app.ui.addToolBar(self.app.ui.toolbarview) + + self.app.ui.toolbarshell = QtWidgets.QToolBar('Shell Toolbar') + self.app.ui.toolbarshell.setObjectName('Shell_TB') + self.app.ui.addToolBar(self.app.ui.toolbarshell) + + self.app.ui.toolbartools = QtWidgets.QToolBar('Tools Toolbar') + self.app.ui.toolbartools.setObjectName('Tools_TB') + self.app.ui.addToolBar(self.app.ui.toolbartools) + + self.app.ui.exc_edit_toolbar = QtWidgets.QToolBar('Excellon Editor Toolbar') + # self.app.ui.exc_edit_toolbar.setVisible(False) + self.app.ui.exc_edit_toolbar.setObjectName('ExcEditor_TB') + self.app.ui.addToolBar(self.app.ui.exc_edit_toolbar) + + self.app.ui.addToolBarBreak() + + self.app.ui.geo_edit_toolbar = QtWidgets.QToolBar('Geometry Editor Toolbar') + # self.app.ui.geo_edit_toolbar.setVisible(False) + self.app.ui.geo_edit_toolbar.setObjectName('GeoEditor_TB') + self.app.ui.addToolBar(self.app.ui.geo_edit_toolbar) + + self.app.ui.grb_edit_toolbar = QtWidgets.QToolBar('Gerber Editor Toolbar') + # self.app.ui.grb_edit_toolbar.setVisible(False) + self.app.ui.grb_edit_toolbar.setObjectName('GrbEditor_TB') + self.app.ui.addToolBar(self.app.ui.grb_edit_toolbar) + + self.app.ui.snap_toolbar = QtWidgets.QToolBar('Grid Toolbar') + self.app.ui.snap_toolbar.setObjectName('Snap_TB') + # self.app.ui.snap_toolbar.setMaximumHeight(30) + self.app.ui.addToolBar(self.app.ui.snap_toolbar) + + self.app.ui.corner_snap_btn.setVisible(False) + self.app.ui.snap_magnet.setVisible(False) + + if current_layout == 'minimal': + self.app.ui.toolbarview.setVisible(False) + self.app.ui.toolbarshell.setVisible(False) + self.app.ui.snap_toolbar.setVisible(False) + self.app.ui.geo_edit_toolbar.setVisible(False) + self.app.ui.grb_edit_toolbar.setVisible(False) + self.app.ui.exc_edit_toolbar.setVisible(False) + self.app.ui.lock_toolbar(lock=True) + + # add all the actions to the toolbars + self.app.ui.populate_toolbars() + + # reconnect all the signals to the toolbar actions + self.app.connect_toolbar_signals() + + self.app.ui.grid_snap_btn.setChecked(True) + self.app.ui.on_grid_snap_triggered(state=True) + + self.app.ui.grid_gap_x_entry.setText(str(self.app.defaults["global_gridx"])) + self.app.ui.grid_gap_y_entry.setText(str(self.app.defaults["global_gridy"])) + self.app.ui.snap_max_dist_entry.setText(str(self.app.defaults["global_snap_max"])) + self.app.ui.grid_gap_link_cb.setChecked(True) diff --git a/flatcamGUI/preferences/general/GeneralPreferencesUI.py b/flatcamGUI/preferences/general/GeneralPreferencesUI.py index c88d7362..46636438 100644 --- a/flatcamGUI/preferences/general/GeneralPreferencesUI.py +++ b/flatcamGUI/preferences/general/GeneralPreferencesUI.py @@ -1,25 +1,43 @@ -from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI -from flatcamGUI.preferences.PreferencesSectionUI import PreferencesSectionUI +from PyQt5 import QtWidgets +from PyQt5.QtCore import QSettings + from flatcamGUI.preferences.general.GeneralAppPrefGroupUI import GeneralAppPrefGroupUI -from flatcamGUI.preferences.general.GeneralAppSettingsGroupUI import GeneralAppSettingsGroupUI +from flatcamGUI.preferences.general.GeneralAPPSetGroupUI import GeneralAPPSetGroupUI from flatcamGUI.preferences.general.GeneralGUIPrefGroupUI import GeneralGUIPrefGroupUI +import gettext +import FlatCAMTranslation as fcTranslate +import builtins -class GeneralPreferencesUI(PreferencesSectionUI): +fcTranslate.apply_language('strings') +if '_' not in builtins.__dict__: + _ = gettext.gettext - def __init__(self, decimals, **kwargs): +settings = QSettings("Open Source", "FlatCAM") +if settings.contains("machinist"): + machinist_setting = settings.value('machinist', type=int) +else: + machinist_setting = 0 + + +class GeneralPreferencesUI(QtWidgets.QWidget): + def __init__(self, decimals, parent=None): + QtWidgets.QWidget.__init__(self, parent=parent) + self.layout = QtWidgets.QHBoxLayout() + self.setLayout(self.layout) self.decimals = decimals - super().__init__(**kwargs) - def build_groups(self) -> [OptionsGroupUI]: - return [ - GeneralAppPrefGroupUI(decimals=self.decimals), - GeneralGUIPrefGroupUI(decimals=self.decimals), - GeneralAppSettingsGroupUI(decimals=self.decimals) - ] + self.general_app_group = GeneralAppPrefGroupUI(decimals=self.decimals) + self.general_app_group.setMinimumWidth(250) - def get_tab_id(self): - return "general_tab" + self.general_gui_group = GeneralGUIPrefGroupUI(decimals=self.decimals) + self.general_gui_group.setMinimumWidth(250) - def get_tab_label(self): - return _("General") + self.general_app_set_group = GeneralAPPSetGroupUI(decimals=self.decimals) + self.general_app_set_group.setMinimumWidth(250) + + self.layout.addWidget(self.general_app_group) + self.layout.addWidget(self.general_gui_group) + self.layout.addWidget(self.general_app_set_group) + + self.layout.addStretch() diff --git a/flatcamGUI/preferences/geometry/GeometryAdvOptPrefGroupUI.py b/flatcamGUI/preferences/geometry/GeometryAdvOptPrefGroupUI.py index 57993400..7ade9b90 100644 --- a/flatcamGUI/preferences/geometry/GeometryAdvOptPrefGroupUI.py +++ b/flatcamGUI/preferences/geometry/GeometryAdvOptPrefGroupUI.py @@ -1,150 +1,246 @@ -from flatcamGUI.preferences.OptionUI import * -from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI2 +from PyQt5 import QtWidgets +from PyQt5.QtCore import QSettings + +from flatcamGUI.GUIElements import FCEntry, FloatEntry, FCDoubleSpinner, FCCheckBox, RadioSet, FCLabel +from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI import gettext import FlatCAMTranslation as fcTranslate import builtins + fcTranslate.apply_language('strings') if '_' not in builtins.__dict__: _ = gettext.gettext +settings = QSettings("Open Source", "FlatCAM") +if settings.contains("machinist"): + machinist_setting = settings.value('machinist', type=int) +else: + machinist_setting = 0 -class GeometryAdvOptPrefGroupUI(OptionsGroupUI2): - def __init__(self, decimals=4, **kwargs): - self.decimals = decimals - super().__init__(**kwargs) +class GeometryAdvOptPrefGroupUI(OptionsGroupUI): + def __init__(self, decimals=4, parent=None): + # OptionsGroupUI.__init__(self, "Geometry Advanced Options Preferences", parent=parent) + super(GeometryAdvOptPrefGroupUI, self).__init__(self, parent=parent) + self.setTitle(str(_("Geometry Adv. Options"))) + self.decimals = decimals - def build_options(self) -> [OptionUI]: - return [ - HeadingOptionUI( - label_text="Advanced Options", - label_tooltip="A list of Geometry advanced parameters.\n" - "Those parameters are available only for\n" - "Advanced App. Level." - ), - LineEntryOptionUI( - option="geometry_toolchangexy", - label_text="Toolchange X-Y", - label_tooltip="Toolchange X,Y position." - ), - FloatEntryOptionUI( - option="geometry_startz", - label_text="Start Z", - label_tooltip="Height of the tool just after starting the work.\n" - "Delete the value if you don't need this feature." - ), - DoubleSpinnerOptionUI( - option="geometry_feedrate_rapid", - label_text="Feedrate Rapids", - label_tooltip="Cutting speed in the XY plane\n" - "(in units per minute).\n" - "This is for the rapid move G00.\n" - "It is useful only for Marlin,\n" - "ignore for any other cases.", - min_value=0, max_value=99999.9999, step=10, decimals=self.decimals - ), - CheckboxOptionUI( - option="geometry_extracut", - label_text="Re-cut", - label_tooltip="In order to remove possible\n" - "copper leftovers where first cut\n" - "meet with last cut, we generate an\n" - "extended cut over the first cut section." - ), - DoubleSpinnerOptionUI( - option="geometry_extracut_length", - label_text="Re-cut length", - label_tooltip="In order to remove possible\n" - "copper leftovers where first cut\n" - "meet with last cut, we generate an\n" - "extended cut over the first cut section.", - min_value=0, max_value=99999, step=0.1, decimals=self.decimals - ), - DoubleSpinnerOptionUI( - option="geometry_z_pdepth", - label_text="Probe Z depth", - label_tooltip="The maximum depth that the probe is allowed\n" - "to probe. Negative value, in current units.", - min_value=-99999, max_value=0.0, step=0.1, decimals=self.decimals - ), - DoubleSpinnerOptionUI( - option="geometry_feedrate_probe", - label_text="Feedrate Probe", - label_tooltip="The feedrate used while the probe is probing.", - min_value=0, max_value=99999.9999, step=0.1, decimals=self.decimals - ), - RadioSetOptionUI( - option="geometry_spindledir", - label_text="Spindle direction", - label_tooltip="This sets the direction that the spindle is rotating.\n" - "It can be either:\n" - "- CW = clockwise or\n" - "- CCW = counter clockwise", - choices=[{'label': _('CW'), 'value': 'CW'}, - {'label': _('CCW'), 'value': 'CCW'}] - ), - CheckboxOptionUI( - option="geometry_f_plunge", - label_text="Fast Plunge", - label_tooltip="By checking this, the vertical move from\n" - "Z_Toolchange to Z_move is done with G0,\n" - "meaning the fastest speed available.\n" - "WARNING: the move is done at Toolchange X,Y coords." - ), - DoubleSpinnerOptionUI( - option="geometry_segx", - label_text="Segment X size", - label_tooltip="The size of the trace segment on the X axis.\n" - "Useful for auto-leveling.\n" - "A value of 0 means no segmentation on the X axis.", - min_value=0, max_value=99999, step=0.1, decimals=self.decimals - ), - DoubleSpinnerOptionUI( - option="geometry_segy", - label_text="Segment Y size", - label_tooltip="The size of the trace segment on the Y axis.\n" - "Useful for auto-leveling.\n" - "A value of 0 means no segmentation on the Y axis.", - min_value=0, max_value=99999, step=0.1, decimals=self.decimals - ), + # ------------------------------ + # ## Advanced Options + # ------------------------------ + self.geo_label = QtWidgets.QLabel('%s:' % _('Advanced Options')) + self.geo_label.setToolTip( + _("A list of Geometry advanced parameters.\n" + "Those parameters are available only for\n" + "Advanced App. Level.") + ) + self.layout.addWidget(self.geo_label) - HeadingOptionUI( - label_text="Area Exclusion", - label_tooltip="Area exclusion parameters.\n" - "Those parameters are available only for\n" - "Advanced App. Level." - ), - CheckboxOptionUI( - option="geometry_area_exclusion", - label_text="Exclusion areas", - label_tooltip="Include exclusion areas.\n" - "In those areas the travel of the tools\n" - "is forbidden." - ), - RadioSetOptionUI( - option="geometry_area_shape", - label_text="Shape", - label_tooltip="The kind of selection shape used for area selection.", - choices=[{'label': _("Square"), 'value': 'square'}, - {'label': _("Polygon"), 'value': 'polygon'}] - ), - RadioSetOptionUI( - option="geometry_area_strategy", - label_text="Strategy", - label_tooltip="The strategy followed when encountering an exclusion area.\n" - "Can be:\n" - "- Over -> when encountering the area, the tool will go to a set height\n" - "- Around -> will avoid the exclusion area by going around the area", - choices=[{'label': _('Over'), 'value': 'over'}, - {'label': _('Around'), 'value': 'around'}] - ), - DoubleSpinnerOptionUI( - option="geometry_area_overz", - label_text="Over Z", - label_tooltip="The height Z to which the tool will rise in order to avoid\n" - "an interdiction area.", - min_value=0.0, max_value=9999.9999, step=0.5, decimals=self.decimals + grid1 = QtWidgets.QGridLayout() + self.layout.addLayout(grid1) + + # Toolchange X,Y + toolchange_xy_label = QtWidgets.QLabel('%s:' % _('Toolchange X-Y')) + toolchange_xy_label.setToolTip( + _("Toolchange X,Y position.") + ) + grid1.addWidget(toolchange_xy_label, 1, 0) + self.toolchangexy_entry = FCEntry() + grid1.addWidget(self.toolchangexy_entry, 1, 1) + + # Start move Z + startzlabel = QtWidgets.QLabel('%s:' % _('Start Z')) + startzlabel.setToolTip( + _("Height of the tool just after starting the work.\n" + "Delete the value if you don't need this feature.") + ) + grid1.addWidget(startzlabel, 2, 0) + self.gstartz_entry = FloatEntry() + grid1.addWidget(self.gstartz_entry, 2, 1) + + # Feedrate rapids + fr_rapid_label = QtWidgets.QLabel('%s:' % _('Feedrate Rapids')) + fr_rapid_label.setToolTip( + _("Cutting speed in the XY plane\n" + "(in units per minute).\n" + "This is for the rapid move G00.\n" + "It is useful only for Marlin,\n" + "ignore for any other cases.") + ) + self.feedrate_rapid_entry = FCDoubleSpinner() + self.feedrate_rapid_entry.set_range(0, 99999.9999) + self.feedrate_rapid_entry.set_precision(self.decimals) + self.feedrate_rapid_entry.setSingleStep(0.1) + self.feedrate_rapid_entry.setWrapping(True) + + grid1.addWidget(fr_rapid_label, 4, 0) + grid1.addWidget(self.feedrate_rapid_entry, 4, 1) + + # End move extra cut + self.extracut_cb = FCCheckBox('%s' % _('Re-cut')) + self.extracut_cb.setToolTip( + _("In order to remove possible\n" + "copper leftovers where first cut\n" + "meet with last cut, we generate an\n" + "extended cut over the first cut section.") + ) + + self.e_cut_entry = FCDoubleSpinner() + self.e_cut_entry.set_range(0, 99999) + self.e_cut_entry.set_precision(self.decimals) + self.e_cut_entry.setSingleStep(0.1) + self.e_cut_entry.setWrapping(True) + self.e_cut_entry.setToolTip( + _("In order to remove possible\n" + "copper leftovers where first cut\n" + "meet with last cut, we generate an\n" + "extended cut over the first cut section.") + ) + grid1.addWidget(self.extracut_cb, 5, 0) + grid1.addWidget(self.e_cut_entry, 5, 1) + + # Probe depth + self.pdepth_label = QtWidgets.QLabel('%s:' % _("Probe Z depth")) + self.pdepth_label.setToolTip( + _("The maximum depth that the probe is allowed\n" + "to probe. Negative value, in current units.") + ) + self.pdepth_entry = FCDoubleSpinner() + self.pdepth_entry.set_range(-99999, 0.0000) + self.pdepth_entry.set_precision(self.decimals) + self.pdepth_entry.setSingleStep(0.1) + self.pdepth_entry.setWrapping(True) + + grid1.addWidget(self.pdepth_label, 6, 0) + grid1.addWidget(self.pdepth_entry, 6, 1) + + # Probe feedrate + self.feedrate_probe_label = QtWidgets.QLabel('%s:' % _("Feedrate Probe")) + self.feedrate_probe_label.setToolTip( + _("The feedrate used while the probe is probing.") + ) + self.feedrate_probe_entry = FCDoubleSpinner() + self.feedrate_probe_entry.set_range(0, 99999.9999) + self.feedrate_probe_entry.set_precision(self.decimals) + self.feedrate_probe_entry.setSingleStep(0.1) + self.feedrate_probe_entry.setWrapping(True) + + grid1.addWidget(self.feedrate_probe_label, 7, 0) + grid1.addWidget(self.feedrate_probe_entry, 7, 1) + + # Spindle direction + spindle_dir_label = QtWidgets.QLabel('%s:' % _('Spindle direction')) + spindle_dir_label.setToolTip( + _("This sets the direction that the spindle is rotating.\n" + "It can be either:\n" + "- CW = clockwise or\n" + "- CCW = counter clockwise") + ) + + self.spindledir_radio = RadioSet([{'label': _('CW'), 'value': 'CW'}, + {'label': _('CCW'), 'value': 'CCW'}]) + grid1.addWidget(spindle_dir_label, 8, 0) + grid1.addWidget(self.spindledir_radio, 8, 1) + + # Fast Move from Z Toolchange + self.fplunge_cb = FCCheckBox('%s' % _('Fast Plunge')) + self.fplunge_cb.setToolTip( + _("By checking this, the vertical move from\n" + "Z_Toolchange to Z_move is done with G0,\n" + "meaning the fastest speed available.\n" + "WARNING: the move is done at Toolchange X,Y coords.") + ) + grid1.addWidget(self.fplunge_cb, 9, 0, 1, 2) + + # Size of trace segment on X axis + segx_label = QtWidgets.QLabel('%s:' % _("Segment X size")) + segx_label.setToolTip( + _("The size of the trace segment on the X axis.\n" + "Useful for auto-leveling.\n" + "A value of 0 means no segmentation on the X axis.") + ) + self.segx_entry = FCDoubleSpinner() + self.segx_entry.set_range(0, 99999) + self.segx_entry.set_precision(self.decimals) + self.segx_entry.setSingleStep(0.1) + self.segx_entry.setWrapping(True) + + grid1.addWidget(segx_label, 10, 0) + grid1.addWidget(self.segx_entry, 10, 1) + + # Size of trace segment on Y axis + segy_label = QtWidgets.QLabel('%s:' % _("Segment Y size")) + segy_label.setToolTip( + _("The size of the trace segment on the Y axis.\n" + "Useful for auto-leveling.\n" + "A value of 0 means no segmentation on the Y axis.") + ) + self.segy_entry = FCDoubleSpinner() + self.segy_entry.set_range(0, 99999) + self.segy_entry.set_precision(self.decimals) + self.segy_entry.setSingleStep(0.1) + self.segy_entry.setWrapping(True) + + grid1.addWidget(segy_label, 11, 0) + grid1.addWidget(self.segy_entry, 11, 1) + + # ----------------------------- + # --- Area Exclusion ---------- + # ----------------------------- + self.adv_label = QtWidgets.QLabel('%s:' % _('Area Exclusion')) + self.adv_label.setToolTip( + _("Area exclusion parameters.\n" + "Those parameters are available only for\n" + "Advanced App. Level.") + ) + grid1.addWidget(self.adv_label, 12, 0, 1, 2) + + # Exclusion Area CB + self.exclusion_cb = FCCheckBox('%s:' % _("Exclusion areas")) + self.exclusion_cb.setToolTip( + _( + "Include exclusion areas.\n" + "In those areas the travel of the tools\n" + "is forbidden." ) - ] + ) + grid1.addWidget(self.exclusion_cb, 13, 0, 1, 2) + + # Area Selection shape + self.area_shape_label = QtWidgets.QLabel('%s:' % _("Shape")) + self.area_shape_label.setToolTip( + _("The kind of selection shape used for area selection.") + ) + + self.area_shape_radio = RadioSet([{'label': _("Square"), 'value': 'square'}, + {'label': _("Polygon"), 'value': 'polygon'}]) + + grid1.addWidget(self.area_shape_label, 14, 0) + grid1.addWidget(self.area_shape_radio, 14, 1) + + # Chose Strategy + self.strategy_label = FCLabel('%s:' % _("Strategy")) + self.strategy_label.setToolTip(_("The strategy followed when encountering an exclusion area.\n" + "Can be:\n" + "- Over -> when encountering the area, the tool will go to a set height\n" + "- Around -> will avoid the exclusion area by going around the area")) + self.strategy_radio = RadioSet([{'label': _('Over'), 'value': 'over'}, + {'label': _('Around'), 'value': 'around'}]) + + grid1.addWidget(self.strategy_label, 15, 0) + grid1.addWidget(self.strategy_radio, 15, 1) + + # Over Z + self.over_z_label = FCLabel('%s:' % _("Over Z")) + self.over_z_label.setToolTip(_("The height Z to which the tool will rise in order to avoid\n" + "an interdiction area.")) + self.over_z_entry = FCDoubleSpinner() + self.over_z_entry.set_range(0.000, 9999.9999) + self.over_z_entry.set_precision(self.decimals) + + grid1.addWidget(self.over_z_label, 18, 0) + grid1.addWidget(self.over_z_entry, 18, 1) + + self.layout.addStretch() diff --git a/flatcamGUI/preferences/geometry/GeometryEditorPrefGroupUI.py b/flatcamGUI/preferences/geometry/GeometryEditorPrefGroupUI.py index fe861c34..9c5204ab 100644 --- a/flatcamGUI/preferences/geometry/GeometryEditorPrefGroupUI.py +++ b/flatcamGUI/preferences/geometry/GeometryEditorPrefGroupUI.py @@ -1,41 +1,67 @@ -from flatcamGUI.preferences.OptionUI import * -from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI2 +from PyQt5 import QtWidgets +from PyQt5.QtCore import QSettings + +from flatcamGUI.GUIElements import FCSpinner, RadioSet +from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI import gettext import FlatCAMTranslation as fcTranslate import builtins + fcTranslate.apply_language('strings') if '_' not in builtins.__dict__: _ = gettext.gettext +settings = QSettings("Open Source", "FlatCAM") +if settings.contains("machinist"): + machinist_setting = settings.value('machinist', type=int) +else: + machinist_setting = 0 -class GeometryEditorPrefGroupUI(OptionsGroupUI2): - def __init__(self, decimals=4, **kwargs): - self.decimals = decimals - super().__init__(**kwargs) +class GeometryEditorPrefGroupUI(OptionsGroupUI): + def __init__(self, decimals=4, parent=None): + # OptionsGroupUI.__init__(self, "Gerber Adv. Options Preferences", parent=parent) + super(GeometryEditorPrefGroupUI, self).__init__(self, parent=parent) + self.setTitle(str(_("Geometry Editor"))) + self.decimals = decimals - def build_options(self) -> [OptionUI]: - return [ - HeadingOptionUI(label_text="Parameters"), - SpinnerOptionUI( - option="geometry_editor_sel_limit", - label_text="Selection limit", - label_tooltip="Set the number of selected geometry\n" - "items above which the utility geometry\n" - "becomes just a selection rectangle.\n" - "Increases the performance when moving a\n" - "large number of geometric elements.", - min_value=0, max_value=9999, step=1 - ), - RadioSetOptionUI( - option="geometry_editor_milling_type", - label_text="Milling Type", - label_tooltip="Milling type:\n" - "- climb / best for precision milling and to reduce tool usage\n" - "- conventional / useful when there is no backlash compensation", - choices=[{'label': _('Climb'), 'value': 'cl'}, - {'label': _('Conventional'), 'value': 'cv'}] - ) - ] \ No newline at end of file + # Advanced Geometry Parameters + self.param_label = QtWidgets.QLabel("%s:" % _("Parameters")) + self.param_label.setToolTip( + _("A list of Geometry Editor parameters.") + ) + self.layout.addWidget(self.param_label) + + grid0 = QtWidgets.QGridLayout() + self.layout.addLayout(grid0) + + # Selection Limit + self.sel_limit_label = QtWidgets.QLabel('%s:' % _("Selection limit")) + self.sel_limit_label.setToolTip( + _("Set the number of selected geometry\n" + "items above which the utility geometry\n" + "becomes just a selection rectangle.\n" + "Increases the performance when moving a\n" + "large number of geometric elements.") + ) + self.sel_limit_entry = FCSpinner() + self.sel_limit_entry.set_range(0, 9999) + + grid0.addWidget(self.sel_limit_label, 0, 0) + grid0.addWidget(self.sel_limit_entry, 0, 1) + + # Milling Type + milling_type_label = QtWidgets.QLabel('%s:' % _('Milling Type')) + milling_type_label.setToolTip( + _("Milling type:\n" + "- climb / best for precision milling and to reduce tool usage\n" + "- conventional / useful when there is no backlash compensation") + ) + self.milling_type_radio = RadioSet([{'label': _('Climb'), 'value': 'cl'}, + {'label': _('Conventional'), 'value': 'cv'}]) + grid0.addWidget(milling_type_label, 1, 0) + grid0.addWidget(self.milling_type_radio, 1, 1) + + self.layout.addStretch() diff --git a/flatcamGUI/preferences/geometry/GeometryGenPrefGroupUI.py b/flatcamGUI/preferences/geometry/GeometryGenPrefGroupUI.py index 1e800702..60479236 100644 --- a/flatcamGUI/preferences/geometry/GeometryGenPrefGroupUI.py +++ b/flatcamGUI/preferences/geometry/GeometryGenPrefGroupUI.py @@ -1,5 +1,8 @@ -from flatcamGUI.preferences.OptionUI import * -from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI2 +from PyQt5 import QtWidgets, QtCore, QtGui +from PyQt5.QtCore import QSettings + +from flatcamGUI.GUIElements import FCCheckBox, FCSpinner, FCEntry +from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI import gettext import FlatCAMTranslation as fcTranslate @@ -9,46 +12,112 @@ fcTranslate.apply_language('strings') if '_' not in builtins.__dict__: _ = gettext.gettext +settings = QSettings("Open Source", "FlatCAM") +if settings.contains("machinist"): + machinist_setting = settings.value('machinist', type=int) +else: + machinist_setting = 0 -class GeometryGenPrefGroupUI(OptionsGroupUI2): - def __init__(self, decimals=4, **kwargs): - self.decimals = decimals - super().__init__(**kwargs) +class GeometryGenPrefGroupUI(OptionsGroupUI): + def __init__(self, decimals=4, parent=None): + # OptionsGroupUI.__init__(self, "Geometry General Preferences", parent=parent) + super(GeometryGenPrefGroupUI, self).__init__(self, parent=parent) + self.setTitle(str(_("Geometry General"))) + self.decimals = decimals - def build_options(self) -> [OptionUI]: - return [ - HeadingOptionUI(label_text="Plot Options"), - CheckboxOptionUI( - option="geometry_plot", - label_text="Plot", - label_tooltip="Plot (show) this object." - ), - SpinnerOptionUI( - option="geometry_circle_steps", - label_text="Circle Steps", - label_tooltip="The number of circle steps for Geometry \n" - "circle and arc shapes linear approximation.", - min_value=0, max_value=9999, step=1 - ), - HeadingOptionUI(label_text="Tools"), - LineEntryOptionUI( - option="geometry_cnctooldia", - label_text="Tools Dia", - label_color="green", - label_bold=True, - label_tooltip="Diameters of the tools, separated by comma.\n" - "The value of the diameter has to use the dot decimals separator.\n" - "Valid values: 0.3, 1.0" - ), - SeparatorOptionUI(), + # ## Plot options + self.plot_options_label = QtWidgets.QLabel("%s:" % _("Plot Options")) + self.layout.addWidget(self.plot_options_label) - HeadingOptionUI(label_text="Geometry Object Color"), - ColorOptionUI( - option="geometry_plot_line", - label_text="Outline", + # Plot CB + self.plot_cb = FCCheckBox(label=_('Plot')) + self.plot_cb.setToolTip( + _("Plot (show) this object.") + ) + self.layout.addWidget(self.plot_cb) - label_tooltip="Set the line color for plotted objects.", - ), - ] + grid0 = QtWidgets.QGridLayout() + self.layout.addLayout(grid0) + grid0.setColumnStretch(0, 0) + grid0.setColumnStretch(1, 1) + + # Number of circle steps for circular aperture linear approximation + self.circle_steps_label = QtWidgets.QLabel('%s:' % _("Circle Steps")) + self.circle_steps_label.setToolTip( + _("The number of circle steps for Geometry \n" + "circle and arc shapes linear approximation.") + ) + self.circle_steps_entry = FCSpinner() + self.circle_steps_entry.set_range(0, 999) + + grid0.addWidget(self.circle_steps_label, 1, 0) + grid0.addWidget(self.circle_steps_entry, 1, 1) + + # Tools + self.tools_label = QtWidgets.QLabel("%s:" % _("Tools")) + grid0.addWidget(self.tools_label, 2, 0, 1, 2) + + # Tooldia + tdlabel = QtWidgets.QLabel('%s:' % _('Tools Dia')) + tdlabel.setToolTip( + _("Diameters of the tools, separated by comma.\n" + "The value of the diameter has to use the dot decimals separator.\n" + "Valid values: 0.3, 1.0") + ) + self.cnctooldia_entry = FCEntry() + + grid0.addWidget(tdlabel, 3, 0) + grid0.addWidget(self.cnctooldia_entry, 3, 1) + + separator_line = QtWidgets.QFrame() + separator_line.setFrameShape(QtWidgets.QFrame.HLine) + separator_line.setFrameShadow(QtWidgets.QFrame.Sunken) + grid0.addWidget(separator_line, 9, 0, 1, 2) + + # Geometry Object Color + self.gerber_color_label = QtWidgets.QLabel('%s' % _('Geometry Object Color')) + grid0.addWidget(self.gerber_color_label, 10, 0, 1, 2) + + # Plot Line Color + self.line_color_label = QtWidgets.QLabel('%s:' % _('Outline')) + self.line_color_label.setToolTip( + _("Set the line color for plotted objects.") + ) + self.line_color_entry = FCEntry() + self.line_color_button = QtWidgets.QPushButton() + self.line_color_button.setFixedSize(15, 15) + + self.form_box_child_2 = QtWidgets.QHBoxLayout() + self.form_box_child_2.addWidget(self.line_color_entry) + self.form_box_child_2.addWidget(self.line_color_button) + self.form_box_child_2.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter) + + grid0.addWidget(self.line_color_label, 11, 0) + grid0.addLayout(self.form_box_child_2, 11, 1) + + self.layout.addStretch() + + # Setting plot colors signals + self.line_color_entry.editingFinished.connect(self.on_line_color_entry) + self.line_color_button.clicked.connect(self.on_line_color_button) + + def on_line_color_entry(self): + self.app.defaults['geometry_plot_line'] = self.line_color_entry.get_value()[:7] + 'FF' + self.line_color_button.setStyleSheet("background-color:%s" % str(self.app.defaults['geometry_plot_line'])[:7]) + + def on_line_color_button(self): + current_color = QtGui.QColor(self.app.defaults['geometry_plot_line'][:7]) + # print(current_color) + + c_dialog = QtWidgets.QColorDialog() + plot_line_color = c_dialog.getColor(initial=current_color) + + if plot_line_color.isValid() is False: + return + + self.line_color_button.setStyleSheet("background-color:%s" % str(plot_line_color.name())) + + new_val_line = str(plot_line_color.name()) + str(self.app.defaults['geometry_plot_line'][7:9]) + self.line_color_entry.set_value(new_val_line) diff --git a/flatcamGUI/preferences/geometry/GeometryOptPrefGroupUI.py b/flatcamGUI/preferences/geometry/GeometryOptPrefGroupUI.py index 102a9273..c2e0f6e2 100644 --- a/flatcamGUI/preferences/geometry/GeometryOptPrefGroupUI.py +++ b/flatcamGUI/preferences/geometry/GeometryOptPrefGroupUI.py @@ -1,13 +1,14 @@ -from PyQt5.QtCore import QSettings +from PyQt5 import QtWidgets +from PyQt5.QtCore import Qt, QSettings -from flatcamGUI.GUIElements import OptionalInputSection +from flatcamGUI.GUIElements import FCDoubleSpinner, FCCheckBox, OptionalInputSection, FCEntry, FCSpinner, FCComboBox from flatcamGUI.preferences import machinist_setting -from flatcamGUI.preferences.OptionUI import * -from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI2 +from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI import gettext import FlatCAMTranslation as fcTranslate import builtins + fcTranslate.apply_language('strings') if '_' not in builtins.__dict__: _ = gettext.gettext @@ -19,135 +20,246 @@ else: machinist_setting = 0 -class GeometryOptPrefGroupUI(OptionsGroupUI2): +class GeometryOptPrefGroupUI(OptionsGroupUI): + def __init__(self, decimals=4, parent=None): + # OptionsGroupUI.__init__(self, "Geometry Options Preferences", parent=parent) + super(GeometryOptPrefGroupUI, self).__init__(self, parent=parent) - def __init__(self, decimals=4, **kwargs): - self.decimals = decimals - super().__init__(**kwargs) self.setTitle(str(_("Geometry Options"))) - self.pp_geometry_name_cb = self.option_dict()["geometry_ppname_g"].get_field() + self.decimals = decimals + + # ------------------------------ + # ## Create CNC Job + # ------------------------------ + self.cncjob_label = QtWidgets.QLabel('%s:' % _('Create CNC Job')) + self.cncjob_label.setToolTip( + _("Create a CNC Job object\n" + "tracing the contours of this\n" + "Geometry object.") + ) + self.layout.addWidget(self.cncjob_label) + + grid1 = QtWidgets.QGridLayout() + self.layout.addLayout(grid1) + grid1.setColumnStretch(0, 0) + grid1.setColumnStretch(1, 1) + + # Cut Z + cutzlabel = QtWidgets.QLabel('%s:' % _('Cut Z')) + cutzlabel.setToolTip( + _("Cutting depth (negative)\n" + "below the copper surface.") + ) + self.cutz_entry = FCDoubleSpinner() + + if machinist_setting == 0: + self.cutz_entry.set_range(-9999.9999, 0.0000) + else: + self.cutz_entry.set_range(-9999.9999, 9999.9999) + + self.cutz_entry.set_precision(self.decimals) + self.cutz_entry.setSingleStep(0.1) + self.cutz_entry.setWrapping(True) + + grid1.addWidget(cutzlabel, 0, 0) + grid1.addWidget(self.cutz_entry, 0, 1) + + # Multidepth CheckBox + self.multidepth_cb = FCCheckBox(label=_('Multi-Depth')) + self.multidepth_cb.setToolTip( + _( + "Use multiple passes to limit\n" + "the cut depth in each pass. Will\n" + "cut multiple times until Cut Z is\n" + "reached." + ) + ) + grid1.addWidget(self.multidepth_cb, 1, 0) + + # Depth/pass + dplabel = QtWidgets.QLabel('%s:' % _('Depth/Pass')) + dplabel.setToolTip( + _("The depth to cut on each pass,\n" + "when multidepth is enabled.\n" + "It has positive value although\n" + "it is a fraction from the depth\n" + "which has negative value.") + ) + + self.depthperpass_entry = FCDoubleSpinner() + self.depthperpass_entry.set_range(0, 99999) + self.depthperpass_entry.set_precision(self.decimals) + self.depthperpass_entry.setSingleStep(0.1) + self.depthperpass_entry.setWrapping(True) + + grid1.addWidget(dplabel, 2, 0) + grid1.addWidget(self.depthperpass_entry, 2, 1) - self.multidepth_cb = self.option_dict()["geometry_multidepth"].get_field() - self.depthperpass_entry = self.option_dict()["geometry_depthperpass"].get_field() self.ois_multidepth = OptionalInputSection(self.multidepth_cb, [self.depthperpass_entry]) - self.dwell_cb = self.option_dict()["geometry_dwell"].get_field() - self.dwelltime_entry = self.option_dict()["geometry_dwelltime"].get_field() + # Travel Z + travelzlabel = QtWidgets.QLabel('%s:' % _('Travel Z')) + travelzlabel.setToolTip( + _("Height of the tool when\n" + "moving without cutting.") + ) + self.travelz_entry = FCDoubleSpinner() + + if machinist_setting == 0: + self.travelz_entry.set_range(0.0001, 9999.9999) + else: + self.travelz_entry.set_range(-9999.9999, 9999.9999) + + self.travelz_entry.set_precision(self.decimals) + self.travelz_entry.setSingleStep(0.1) + self.travelz_entry.setWrapping(True) + + grid1.addWidget(travelzlabel, 3, 0) + grid1.addWidget(self.travelz_entry, 3, 1) + + # Tool change: + self.toolchange_cb = FCCheckBox('%s' % _("Tool change")) + self.toolchange_cb.setToolTip( + _( + "Include tool-change sequence\n" + "in the Machine Code (Pause for tool change)." + ) + ) + grid1.addWidget(self.toolchange_cb, 4, 0, 1, 2) + + # Toolchange Z + toolchangezlabel = QtWidgets.QLabel('%s:' % _('Toolchange Z')) + toolchangezlabel.setToolTip( + _( + "Z-axis position (height) for\n" + "tool change." + ) + ) + self.toolchangez_entry = FCDoubleSpinner() + + if machinist_setting == 0: + self.toolchangez_entry.set_range(0.000, 9999.9999) + else: + self.toolchangez_entry.set_range(-9999.9999, 9999.9999) + + self.toolchangez_entry.set_precision(self.decimals) + self.toolchangez_entry.setSingleStep(0.1) + self.toolchangez_entry.setWrapping(True) + + grid1.addWidget(toolchangezlabel, 5, 0) + grid1.addWidget(self.toolchangez_entry, 5, 1) + + # End move Z + endz_label = QtWidgets.QLabel('%s:' % _('End move Z')) + endz_label.setToolTip( + _("Height of the tool after\n" + "the last move at the end of the job.") + ) + self.endz_entry = FCDoubleSpinner() + + if machinist_setting == 0: + self.endz_entry.set_range(0.000, 9999.9999) + else: + self.endz_entry.set_range(-9999.9999, 9999.9999) + + self.endz_entry.set_precision(self.decimals) + self.endz_entry.setSingleStep(0.1) + self.endz_entry.setWrapping(True) + + grid1.addWidget(endz_label, 6, 0) + grid1.addWidget(self.endz_entry, 6, 1) + + # End Move X,Y + endmove_xy_label = QtWidgets.QLabel('%s:' % _('End move X,Y')) + endmove_xy_label.setToolTip( + _("End move X,Y position. In format (x,y).\n" + "If no value is entered then there is no move\n" + "on X,Y plane at the end of the job.") + ) + self.endxy_entry = FCEntry() + + grid1.addWidget(endmove_xy_label, 7, 0) + grid1.addWidget(self.endxy_entry, 7, 1) + + # Feedrate X-Y + frlabel = QtWidgets.QLabel('%s:' % _('Feedrate X-Y')) + frlabel.setToolTip( + _("Cutting speed in the XY\n" + "plane in units per minute") + ) + self.cncfeedrate_entry = FCDoubleSpinner() + self.cncfeedrate_entry.set_range(0, 99999.9999) + self.cncfeedrate_entry.set_precision(self.decimals) + self.cncfeedrate_entry.setSingleStep(0.1) + self.cncfeedrate_entry.setWrapping(True) + + grid1.addWidget(frlabel, 8, 0) + grid1.addWidget(self.cncfeedrate_entry, 8, 1) + + # Feedrate Z (Plunge) + frz_label = QtWidgets.QLabel('%s:' % _('Feedrate Z')) + frz_label.setToolTip( + _("Cutting speed in the XY\n" + "plane in units per minute.\n" + "It is called also Plunge.") + ) + self.feedrate_z_entry = FCDoubleSpinner() + self.feedrate_z_entry.set_range(0, 99999.9999) + self.feedrate_z_entry.set_precision(self.decimals) + self.feedrate_z_entry.setSingleStep(0.1) + self.feedrate_z_entry.setWrapping(True) + + grid1.addWidget(frz_label, 9, 0) + grid1.addWidget(self.feedrate_z_entry, 9, 1) + + # Spindle Speed + spdlabel = QtWidgets.QLabel('%s:' % _('Spindle speed')) + spdlabel.setToolTip( + _( + "Speed of the spindle in RPM (optional).\n" + "If LASER preprocessor is used,\n" + "this value is the power of laser." + ) + ) + self.cncspindlespeed_entry = FCSpinner() + self.cncspindlespeed_entry.set_range(0, 1000000) + self.cncspindlespeed_entry.set_step(100) + + grid1.addWidget(spdlabel, 10, 0) + grid1.addWidget(self.cncspindlespeed_entry, 10, 1) + + # Dwell + self.dwell_cb = FCCheckBox(label='%s' % _('Enable Dwell')) + self.dwell_cb.setToolTip( + _("Pause to allow the spindle to reach its\n" + "speed before cutting.") + ) + dwelltime = QtWidgets.QLabel('%s:' % _('Duration')) + dwelltime.setToolTip( + _("Number of time units for spindle to dwell.") + ) + self.dwelltime_entry = FCDoubleSpinner() + self.dwelltime_entry.set_range(0, 99999) + self.dwelltime_entry.set_precision(self.decimals) + self.dwelltime_entry.setSingleStep(0.1) + self.dwelltime_entry.setWrapping(True) + + grid1.addWidget(self.dwell_cb, 11, 0) + grid1.addWidget(dwelltime, 12, 0) + grid1.addWidget(self.dwelltime_entry, 12, 1) + self.ois_dwell = OptionalInputSection(self.dwell_cb, [self.dwelltime_entry]) - def build_options(self) -> [OptionUI]: - return [ - HeadingOptionUI( - label_text="Create CNC Job", - label_tooltip="Create a CNC Job object\n" - "tracing the contours of this\n" - "Geometry object." - ), - DoubleSpinnerOptionUI( - option="geometry_cutz", - label_text="Cut Z", - label_tooltip="Cutting depth (negative)\n" - "below the copper surface.", - min_value=-9999.9999, max_value=(9999.999 if machinist_setting else 0.0), - decimals=self.decimals, step=0.1 - ), - CheckboxOptionUI( - option="geometry_multidepth", - label_text="Multi-Depth", - label_tooltip="Use multiple passes to limit\n" - "the cut depth in each pass. Will\n" - "cut multiple times until Cut Z is\n" - "reached." - ), - DoubleSpinnerOptionUI( - option="geometry_depthperpass", - label_text="Depth/Pass", - label_tooltip="The depth to cut on each pass,\n" - "when multidepth is enabled.\n" - "It has positive value although\n" - "it is a fraction from the depth\n" - "which has negative value.", - min_value=0, max_value=99999, step=0.1, decimals=self.decimals + # preprocessor selection + pp_label = QtWidgets.QLabel('%s:' % _("Preprocessor")) + pp_label.setToolTip( + _("The Preprocessor file that dictates\n" + "the Machine Code (like GCode, RML, HPGL) output.") + ) + self.pp_geometry_name_cb = FCComboBox() + self.pp_geometry_name_cb.setFocusPolicy(Qt.StrongFocus) - ), - DoubleSpinnerOptionUI( - option="geometry_travelz", - label_text="Travel Z", - label_tooltip="Height of the tool when\n" - "moving without cutting.", - min_value=(-9999.9999 if machinist_setting else 0.0001), max_value=9999.9999, - step=0.1, decimals=self.decimals - ), - CheckboxOptionUI( - option="geometry_toolchange", - label_text="Tool change", - label_tooltip="Include tool-change sequence\n" - "in the Machine Code (Pause for tool change)." - ), - DoubleSpinnerOptionUI( - option="geometry_toolchangez", - label_text="Toolchange Z", - label_tooltip="Z-axis position (height) for\n" - "tool change.", - min_value=(-9999.9999 if machinist_setting else 0.0), max_value=9999.9999, - step=0.1, decimals=self.decimals - ), - DoubleSpinnerOptionUI( - option="geometry_endz", - label_text="End move Z", - label_tooltip="Height of the tool after\n" - "the last move at the end of the job.", - min_value=(-9999.9999 if machinist_setting else 0.0), max_value=9999.9999, - step=0.1, decimals=self.decimals - ), - LineEntryOptionUI( - option="geometry_endxy", - label_text="End move X,Y", - label_tooltip="End move X,Y position. In format (x,y).\n" - "If no value is entered then there is no move\n" - "on X,Y plane at the end of the job." - ), - DoubleSpinnerOptionUI( - option="geometry_feedrate", - label_text="Feedrate X-Y", - label_tooltip="Cutting speed in the XY\n" - "plane in units per minute", - min_value=0, max_value=99999.9999, step=0.1, decimals=self.decimals - ), - DoubleSpinnerOptionUI( - option="geometry_feedrate_z", - label_text="Feedrate Z", - label_tooltip="Cutting speed in the XY\n" - "plane in units per minute.\n" - "It is called also Plunge.", - min_value=0, max_value=99999.9999, step=0.1, decimals=self.decimals - ), - SpinnerOptionUI( - option="geometry_spindlespeed", - label_text="Spindle speed", - label_tooltip="Speed of the spindle in RPM (optional).\n" - "If LASER preprocessor is used,\n" - "this value is the power of laser.", - min_value=0, max_value=1000000, step=100 - ), - CheckboxOptionUI( - option="geometry_dwell", - label_text="Enable Dwell", - label_tooltip="Pause to allow the spindle to reach its\n" - "speed before cutting." - ), - DoubleSpinnerOptionUI( - option="geometry_dwelltime", - label_text="Duration", - label_tooltip="Number of time units for spindle to dwell.", - min_value=0, max_value=999999, step=0.5, decimals=self.decimals - ), - ComboboxOptionUI( - option="geometry_ppname_g", - label_text="Preprocessor", - label_tooltip="The Preprocessor file that dictates\n" - "the Machine Code (like GCode, RML, HPGL) output.", - choices=[] # Populated in App (FIXME) - ) - ] + grid1.addWidget(pp_label, 13, 0) + grid1.addWidget(self.pp_geometry_name_cb, 13, 1) + self.layout.addStretch() diff --git a/flatcamGUI/preferences/geometry/GeometryPreferencesUI.py b/flatcamGUI/preferences/geometry/GeometryPreferencesUI.py index 643b606d..cf906d61 100644 --- a/flatcamGUI/preferences/geometry/GeometryPreferencesUI.py +++ b/flatcamGUI/preferences/geometry/GeometryPreferencesUI.py @@ -1,5 +1,6 @@ -from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI -from flatcamGUI.preferences.PreferencesSectionUI import PreferencesSectionUI +from PyQt5 import QtWidgets +from PyQt5.QtCore import QSettings + from flatcamGUI.preferences.geometry.GeometryEditorPrefGroupUI import GeometryEditorPrefGroupUI from flatcamGUI.preferences.geometry.GeometryAdvOptPrefGroupUI import GeometryAdvOptPrefGroupUI from flatcamGUI.preferences.geometry.GeometryOptPrefGroupUI import GeometryOptPrefGroupUI @@ -8,30 +9,38 @@ from flatcamGUI.preferences.geometry.GeometryGenPrefGroupUI import GeometryGenPr import gettext import FlatCAMTranslation as fcTranslate import builtins + fcTranslate.apply_language('strings') if '_' not in builtins.__dict__: _ = gettext.gettext +settings = QSettings("Open Source", "FlatCAM") +if settings.contains("machinist"): + machinist_setting = settings.value('machinist', type=int) +else: + machinist_setting = 0 -class GeometryPreferencesUI(PreferencesSectionUI): - def __init__(self, decimals, **kwargs): +class GeometryPreferencesUI(QtWidgets.QWidget): + + def __init__(self, decimals, parent=None): + QtWidgets.QWidget.__init__(self, parent=parent) + self.layout = QtWidgets.QHBoxLayout() + self.setLayout(self.layout) self.decimals = decimals - # FIXME: remove the need for external access to geometry_opt_group + + self.geometry_gen_group = GeometryGenPrefGroupUI(decimals=self.decimals) + self.geometry_gen_group.setMinimumWidth(220) self.geometry_opt_group = GeometryOptPrefGroupUI(decimals=self.decimals) - super().__init__(**kwargs) + self.geometry_opt_group.setMinimumWidth(300) + self.geometry_adv_opt_group = GeometryAdvOptPrefGroupUI(decimals=self.decimals) + self.geometry_adv_opt_group.setMinimumWidth(270) + self.geometry_editor_group = GeometryEditorPrefGroupUI(decimals=self.decimals) + self.geometry_editor_group.setMinimumWidth(250) - def build_groups(self) -> [OptionsGroupUI]: - return [ - GeometryGenPrefGroupUI(decimals=self.decimals), - self.geometry_opt_group, - GeometryAdvOptPrefGroupUI(decimals=self.decimals), - GeometryEditorPrefGroupUI(decimals=self.decimals) - ] - - def get_tab_id(self): - return "geometry_tab" - - def get_tab_label(self): - return _("GEOMETRY") + self.layout.addWidget(self.geometry_gen_group) + self.layout.addWidget(self.geometry_opt_group) + self.layout.addWidget(self.geometry_adv_opt_group) + self.layout.addWidget(self.geometry_editor_group) + self.layout.addStretch() diff --git a/flatcamGUI/preferences/gerber/GerberAdvOptPrefGroupUI.py b/flatcamGUI/preferences/gerber/GerberAdvOptPrefGroupUI.py index af9f28c8..20376bfd 100644 --- a/flatcamGUI/preferences/gerber/GerberAdvOptPrefGroupUI.py +++ b/flatcamGUI/preferences/gerber/GerberAdvOptPrefGroupUI.py @@ -1,6 +1,8 @@ -from flatcamGUI.GUIElements import OptionalInputSection -from flatcamGUI.preferences.OptionUI import * -from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI2 +from PyQt5 import QtWidgets +from PyQt5.QtCore import QSettings + +from flatcamGUI.GUIElements import FCCheckBox, RadioSet, FCDoubleSpinner, FCSpinner, OptionalInputSection +from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI import gettext import FlatCAMTranslation as fcTranslate @@ -10,113 +12,175 @@ fcTranslate.apply_language('strings') if '_' not in builtins.__dict__: _ = gettext.gettext +settings = QSettings("Open Source", "FlatCAM") +if settings.contains("machinist"): + machinist_setting = settings.value('machinist', type=int) +else: + machinist_setting = 0 -class GerberAdvOptPrefGroupUI(OptionsGroupUI2): - def __init__(self, decimals=4, **kwargs): - self.decimals = decimals - super().__init__(**kwargs) +class GerberAdvOptPrefGroupUI(OptionsGroupUI): + def __init__(self, decimals=4, parent=None): + # OptionsGroupUI.__init__(self, "Gerber Adv. Options Preferences", parent=parent) + super(GerberAdvOptPrefGroupUI, self).__init__(self, parent=parent) + self.setTitle(str(_("Gerber Adv. Options"))) + self.decimals = decimals - self.simplify_cb = self.option_dict()["gerber_simplification"].get_field() - self.simplification_tol_label = self.option_dict()["gerber_simp_tolerance"].label_widget - self.simplification_tol_spinner = self.option_dict()["gerber_simp_tolerance"].get_field() - self.ois_simplif = OptionalInputSection(self.simplify_cb, [self.simplification_tol_label, self.simplification_tol_spinner], logic=True) + # ## Advanced Gerber Parameters + self.adv_param_label = QtWidgets.QLabel('%s:' % _('Advanced Options')) + self.adv_param_label.setToolTip( + _("A list of Gerber advanced parameters.\n" + "Those parameters are available only for\n" + "Advanced App. Level.") + ) + self.layout.addWidget(self.adv_param_label) - def build_options(self) -> [OptionUI]: - return [ - HeadingOptionUI( - label_text="Advanced Options", - label_tooltip="A list of Gerber advanced parameters.\n" - "Those parameters are available only for\n" - "Advanced App. Level." - ), - CheckboxOptionUI( - option="gerber_follow", - label_text='"Follow"', - label_tooltip="Generate a 'Follow' geometry.\n" - "This means that it will cut through\n" - "the middle of the trace." - ), - CheckboxOptionUI( - option="gerber_aperture_display", - label_text="Table Show/Hide", - label_tooltip="Toggle the display of the Gerber Apertures Table.\n" - "Also, on hide, it will delete all mark shapes\n" - "that are drawn on canvas." - ), - SeparatorOptionUI(), + grid0 = QtWidgets.QGridLayout() + self.layout.addLayout(grid0) - RadioSetOptionUI( - option="gerber_tool_type", - label_text="Tool Type", - label_bold=True, - label_tooltip="Choose which tool to use for Gerber isolation:\n" - "'Circular' or 'V-shape'.\n" - "When the 'V-shape' is selected then the tool\n" - "diameter will depend on the chosen cut depth.", - choices=[{'label': 'Circular', 'value': 'circular'}, - {'label': 'V-Shape', 'value': 'v'}] - ), - DoubleSpinnerOptionUI( - option="gerber_vtipdia", - label_text="V-Tip Dia", - label_tooltip="The tip diameter for V-Shape Tool", - min_value=-99.9999, max_value=99.9999, step=0.1, decimals=self.decimals - ), - SpinnerOptionUI( - option="gerber_vtipangle", - label_text="V-Tip Angle", - label_tooltip="The tip angle for V-Shape Tool.\n" - "In degrees.", - min_value=1, max_value=180, step=5 - ), - DoubleSpinnerOptionUI( - option="gerber_vcutz", - label_text="Cut Z", - label_tooltip="Cutting depth (negative)\n" - "below the copper surface.", - min_value=-99.9999, max_value=0.0000, step=0.1, decimals=self.decimals - ), + # Follow Attribute + self.follow_cb = FCCheckBox(label=_('"Follow"')) + self.follow_cb.setToolTip( + _("Generate a 'Follow' geometry.\n" + "This means that it will cut through\n" + "the middle of the trace.") + ) + grid0.addWidget(self.follow_cb, 0, 0, 1, 2) - RadioSetOptionUI( - option="gerber_iso_type", - label_text="Isolation Type", - label_tooltip="Choose how the isolation will be executed:\n" - "- 'Full' -> complete isolation of polygons\n" - "- 'Ext' -> will isolate only on the outside\n" - "- 'Int' -> will isolate only on the inside\n" - "'Exterior' isolation is almost always possible\n" - "(with the right tool) but 'Interior'\n" - "isolation can be done only when there is an opening\n" - "inside of the polygon (e.g polygon is a 'doughnut' shape).", - choices=[{'label': _('Full'), 'value': 'full'}, - {'label': _('Exterior'), 'value': 'ext'}, - {'label': _('Interior'), 'value': 'int'}] - ), - SeparatorOptionUI(), + # Aperture Table Visibility CB + self.aperture_table_visibility_cb = FCCheckBox(label=_('Table Show/Hide')) + self.aperture_table_visibility_cb.setToolTip( + _("Toggle the display of the Gerber Apertures Table.\n" + "Also, on hide, it will delete all mark shapes\n" + "that are drawn on canvas.") - RadioSetOptionUI( - option="gerber_buffering", - label_text="Buffering", - label_tooltip="Buffering type:\n" - "- None --> best performance, fast file loading but no so good display\n" - "- Full --> slow file loading but good visuals. This is the default.\n" - "<>: Don't change this unless you know what you are doing !!!", - choices=[{'label': _('None'), 'value': 'no'}, - {'label': _('Full'), 'value': 'full'}] - ), - CheckboxOptionUI( - option="gerber_simplification", - label_text="Simplify", - label_tooltip="When checked all the Gerber polygons will be\n" - "loaded with simplification having a set tolerance.\n" - "<>: Don't change this unless you know what you are doing !!!" - ), - DoubleSpinnerOptionUI( - option="gerber_simp_tolerance", - label_text="Tolerance", - label_tooltip="Tolerance for polygon simplification.", - min_value=0.0, max_value=0.01, step=0.0001, decimals=self.decimals+1 - ) - ] \ No newline at end of file + ) + grid0.addWidget(self.aperture_table_visibility_cb, 1, 0, 1, 2) + + separator_line = QtWidgets.QFrame() + separator_line.setFrameShape(QtWidgets.QFrame.HLine) + separator_line.setFrameShadow(QtWidgets.QFrame.Sunken) + grid0.addWidget(separator_line, 2, 0, 1, 2) + + # Tool Type + self.tool_type_label = QtWidgets.QLabel('%s' % _('Tool Type')) + self.tool_type_label.setToolTip( + _("Choose which tool to use for Gerber isolation:\n" + "'Circular' or 'V-shape'.\n" + "When the 'V-shape' is selected then the tool\n" + "diameter will depend on the chosen cut depth.") + ) + self.tool_type_radio = RadioSet([{'label': 'Circular', 'value': 'circular'}, + {'label': 'V-Shape', 'value': 'v'}]) + + grid0.addWidget(self.tool_type_label, 3, 0) + grid0.addWidget(self.tool_type_radio, 3, 1, 1, 2) + + # Tip Dia + self.tipdialabel = QtWidgets.QLabel('%s:' % _('V-Tip Dia')) + self.tipdialabel.setToolTip( + _("The tip diameter for V-Shape Tool") + ) + self.tipdia_spinner = FCDoubleSpinner() + self.tipdia_spinner.set_precision(self.decimals) + self.tipdia_spinner.set_range(-99.9999, 99.9999) + self.tipdia_spinner.setSingleStep(0.1) + self.tipdia_spinner.setWrapping(True) + grid0.addWidget(self.tipdialabel, 4, 0) + grid0.addWidget(self.tipdia_spinner, 4, 1, 1, 2) + + # Tip Angle + self.tipanglelabel = QtWidgets.QLabel('%s:' % _('V-Tip Angle')) + self.tipanglelabel.setToolTip( + _("The tip angle for V-Shape Tool.\n" + "In degree.") + ) + self.tipangle_spinner = FCSpinner() + self.tipangle_spinner.set_range(1, 180) + self.tipangle_spinner.set_step(5) + self.tipangle_spinner.setWrapping(True) + grid0.addWidget(self.tipanglelabel, 5, 0) + grid0.addWidget(self.tipangle_spinner, 5, 1, 1, 2) + + # Cut Z + self.cutzlabel = QtWidgets.QLabel('%s:' % _('Cut Z')) + self.cutzlabel.setToolTip( + _("Cutting depth (negative)\n" + "below the copper surface.") + ) + self.cutz_spinner = FCDoubleSpinner() + self.cutz_spinner.set_precision(self.decimals) + self.cutz_spinner.set_range(-99.9999, 0.0000) + self.cutz_spinner.setSingleStep(0.1) + self.cutz_spinner.setWrapping(True) + + grid0.addWidget(self.cutzlabel, 6, 0) + grid0.addWidget(self.cutz_spinner, 6, 1, 1, 2) + + # Isolation Type + self.iso_type_label = QtWidgets.QLabel('%s:' % _('Isolation Type')) + self.iso_type_label.setToolTip( + _("Choose how the isolation will be executed:\n" + "- 'Full' -> complete isolation of polygons\n" + "- 'Ext' -> will isolate only on the outside\n" + "- 'Int' -> will isolate only on the inside\n" + "'Exterior' isolation is almost always possible\n" + "(with the right tool) but 'Interior'\n" + "isolation can be done only when there is an opening\n" + "inside of the polygon (e.g polygon is a 'doughnut' shape).") + ) + self.iso_type_radio = RadioSet([{'label': _('Full'), 'value': 'full'}, + {'label': _('Exterior'), 'value': 'ext'}, + {'label': _('Interior'), 'value': 'int'}]) + + grid0.addWidget(self.iso_type_label, 7, 0,) + grid0.addWidget(self.iso_type_radio, 7, 1, 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) + + # Buffering Type + buffering_label = QtWidgets.QLabel('%s:' % _('Buffering')) + buffering_label.setToolTip( + _("Buffering type:\n" + "- None --> best performance, fast file loading but no so good display\n" + "- Full --> slow file loading but good visuals. This is the default.\n" + "<>: Don't change this unless you know what you are doing !!!") + ) + self.buffering_radio = RadioSet([{'label': _('None'), 'value': 'no'}, + {'label': _('Full'), 'value': 'full'}]) + grid0.addWidget(buffering_label, 9, 0) + grid0.addWidget(self.buffering_radio, 9, 1) + + # Simplification + self.simplify_cb = FCCheckBox(label=_('Simplify')) + self.simplify_cb.setToolTip( + _("When checked all the Gerber polygons will be\n" + "loaded with simplification having a set tolerance.\n" + "<>: Don't change this unless you know what you are doing !!!") + ) + grid0.addWidget(self.simplify_cb, 10, 0, 1, 2) + + # Simplification tolerance + self.simplification_tol_label = QtWidgets.QLabel(_('Tolerance')) + self.simplification_tol_label.setToolTip(_("Tolerance for polygon simplification.")) + + self.simplification_tol_spinner = FCDoubleSpinner() + self.simplification_tol_spinner.set_precision(self.decimals + 1) + self.simplification_tol_spinner.setWrapping(True) + self.simplification_tol_spinner.setRange(0.00000, 0.01000) + self.simplification_tol_spinner.setSingleStep(0.0001) + + grid0.addWidget(self.simplification_tol_label, 11, 0) + grid0.addWidget(self.simplification_tol_spinner, 11, 1) + self.ois_simplif = OptionalInputSection( + self.simplify_cb, + [ + self.simplification_tol_label, self.simplification_tol_spinner + ], + logic=True) + + self.layout.addStretch() diff --git a/flatcamGUI/preferences/gerber/GerberEditorPrefGroupUI.py b/flatcamGUI/preferences/gerber/GerberEditorPrefGroupUI.py index 2b9bd49e..3ba0da99 100644 --- a/flatcamGUI/preferences/gerber/GerberEditorPrefGroupUI.py +++ b/flatcamGUI/preferences/gerber/GerberEditorPrefGroupUI.py @@ -1,138 +1,247 @@ -from flatcamGUI.preferences.OptionUI import * -from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI2 +from PyQt5 import QtWidgets +from PyQt5.QtCore import QSettings + +from flatcamGUI.GUIElements import FCSpinner, FCDoubleSpinner, FCComboBox, FCEntry, RadioSet +from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI import gettext import FlatCAMTranslation as fcTranslate import builtins + fcTranslate.apply_language('strings') if '_' not in builtins.__dict__: _ = gettext.gettext +settings = QSettings("Open Source", "FlatCAM") +if settings.contains("machinist"): + machinist_setting = settings.value('machinist', type=int) +else: + machinist_setting = 0 -class GerberEditorPrefGroupUI(OptionsGroupUI2): - def __init__(self, decimals=4, **kwargs): - self.decimals = decimals - super().__init__(**kwargs) +class GerberEditorPrefGroupUI(OptionsGroupUI): + def __init__(self, decimals=4, parent=None): + # OptionsGroupUI.__init__(self, "Gerber Adv. Options Preferences", parent=parent) + super(GerberEditorPrefGroupUI, self).__init__(self, parent=parent) + self.setTitle(str(_("Gerber Editor"))) + self.decimals = decimals - def build_options(self) -> [OptionUI]: - return [ - HeadingOptionUI( - label_text="Parameters", - label_tooltip="A list of Gerber Editor parameters." - ), - SpinnerOptionUI( - option="gerber_editor_sel_limit", - label_text="Selection limit", - label_tooltip="Set the number of selected Gerber geometry\n" - "items above which the utility geometry\n" - "becomes just a selection rectangle.\n" - "Increases the performance when moving a\n" - "large number of geometric elements.", - min_value=0, max_value=9999, step=1 - ), - SpinnerOptionUI( - option="gerber_editor_newcode", - label_text="New Aperture code", - label_tooltip="Code for the new aperture", - min_value=10, max_value=99, step=1 - ), - DoubleSpinnerOptionUI( - option="gerber_editor_newsize", - label_text="New Aperture size", - label_tooltip="Size for the new aperture", - min_value=0.0, max_value=100.0, step=0.1, decimals=self.decimals - ), - ComboboxOptionUI( - option="gerber_editor_newtype", - label_text="New Aperture type", - label_tooltip="Type for the new aperture.\n" - "Can be 'C', 'R' or 'O'.", - choices=['C', 'R', 'O'] - ), - SpinnerOptionUI( - option="gerber_editor_array_size", - label_text="Nr of pads", - label_tooltip="Specify how many pads to be in the array.", - min_value=0, max_value=9999, step=1 - ), - LineEntryOptionUI( - option="gerber_editor_newdim", - label_text="Aperture Dimensions", - label_tooltip="Diameters of the tools, separated by comma.\n" - "The value of the diameter has to use the dot decimals separator.\n" - "Valid values: 0.3, 1.0" - ), + # Advanced Gerber Parameters + self.param_label = QtWidgets.QLabel("%s:" % _("Parameters")) + self.param_label.setToolTip( + _("A list of Gerber Editor parameters.") + ) + self.layout.addWidget(self.param_label) - HeadingOptionUI(label_text="Linear Pad Array"), - RadioSetOptionUI( - option="gerber_editor_lin_axis", - label_text="Linear Direction", - label_tooltip="Direction on which the linear array is oriented:\n" - "- 'X' - horizontal axis \n" - "- 'Y' - vertical axis or \n" - "- 'Angle' - a custom angle for the array inclination", - choices=[{'label': _('X'), 'value': 'X'}, - {'label': _('Y'), 'value': 'Y'}, - {'label': _('Angle'), 'value': 'A'}] - ), - DoubleSpinnerOptionUI( - option="gerber_editor_lin_pitch", - label_text="Pitch", - label_tooltip="Pitch = Distance between elements of the array.", - min_value=-9999.99, max_value=9999.99, step=0.1, decimals=self.decimals - ), - DoubleSpinnerOptionUI( - option="gerber_editor_lin_angle", - label_text="Angle", - label_tooltip="Angle at which each element in circular array is placed.", # FIXME: this seems wrong - min_value=-360, max_value=360, step=5, decimals=self.decimals - ), + grid0 = QtWidgets.QGridLayout() + self.layout.addLayout(grid0) - HeadingOptionUI(label_text="Circular Pad Array"), - RadioSetOptionUI( - option="gerber_editor_circ_dir", - label_text="Circular Direction", - label_tooltip="Direction for circular array.\n" - "Can be CW = clockwise or CCW = counter clockwise.", - choices=[{'label': _('CW'), 'value': 'CW'}, - {'label': _('CCW'), 'value': 'CCW'}] - ), - DoubleSpinnerOptionUI( - option="gerber_editor_circ_angle", - label_text="Circular Angle", - label_tooltip="Angle at which each element in circular array is placed.", - min_value=-360, max_value=360, step=5, decimals=self.decimals - ), + # Selection Limit + self.sel_limit_label = QtWidgets.QLabel('%s:' % _("Selection limit")) + self.sel_limit_label.setToolTip( + _("Set the number of selected Gerber geometry\n" + "items above which the utility geometry\n" + "becomes just a selection rectangle.\n" + "Increases the performance when moving a\n" + "large number of geometric elements.") + ) + self.sel_limit_entry = FCSpinner() + self.sel_limit_entry.set_range(0, 9999) - HeadingOptionUI(label_text="Buffer Tool"), - DoubleSpinnerOptionUI( - option="gerber_editor_buff_f", - label_text="Buffer distance", - label_tooltip="Distance at which to buffer the Gerber element.", - min_value=-9999, max_value=9999, step=0.1, decimals=self.decimals - ), + grid0.addWidget(self.sel_limit_label, 0, 0) + grid0.addWidget(self.sel_limit_entry, 0, 1) - HeadingOptionUI(label_text="Scale Tool"), - DoubleSpinnerOptionUI( - option="gerber_editor_scale_f", - label_text="Scale factor", - label_tooltip="Factor to scale the Gerber element.", - min_value=0, max_value=9999, step=0.1, decimals=self.decimals - ), + # New aperture code + self.addcode_entry_lbl = QtWidgets.QLabel('%s:' % _('New Aperture code')) + self.addcode_entry_lbl.setToolTip( + _("Code for the new aperture") + ) - HeadingOptionUI(label_text="Mark Area Tool"), - DoubleSpinnerOptionUI( - option="gerber_editor_ma_low", - label_text="Threshold low", - label_tooltip="Threshold value under which the apertures are not marked.", - min_value=0, max_value=9999, step=0.1, decimals=self.decimals - ), - DoubleSpinnerOptionUI( - option="gerber_editor_ma_high", - label_text="Threshold high", - label_tooltip="Threshold value over which the apertures are not marked.", - min_value=0, max_value=9999, step=0.1, decimals=self.decimals - ) - ] + self.addcode_entry = FCSpinner() + self.addcode_entry.set_range(10, 99) + self.addcode_entry.setWrapping(True) + + grid0.addWidget(self.addcode_entry_lbl, 1, 0) + grid0.addWidget(self.addcode_entry, 1, 1) + + # New aperture size + self.addsize_entry_lbl = QtWidgets.QLabel('%s:' % _('New Aperture size')) + self.addsize_entry_lbl.setToolTip( + _("Size for the new aperture") + ) + + self.addsize_entry = FCDoubleSpinner() + self.addsize_entry.set_range(0, 100) + self.addsize_entry.set_precision(self.decimals) + + grid0.addWidget(self.addsize_entry_lbl, 2, 0) + grid0.addWidget(self.addsize_entry, 2, 1) + + # New aperture type + self.addtype_combo_lbl = QtWidgets.QLabel('%s:' % _('New Aperture type')) + self.addtype_combo_lbl.setToolTip( + _("Type for the new aperture.\n" + "Can be 'C', 'R' or 'O'.") + ) + + self.addtype_combo = FCComboBox() + self.addtype_combo.addItems(['C', 'R', 'O']) + + grid0.addWidget(self.addtype_combo_lbl, 3, 0) + grid0.addWidget(self.addtype_combo, 3, 1) + + # Number of pads in a pad array + self.grb_array_size_label = QtWidgets.QLabel('%s:' % _('Nr of pads')) + self.grb_array_size_label.setToolTip( + _("Specify how many pads to be in the array.") + ) + + self.grb_array_size_entry = FCSpinner() + self.grb_array_size_entry.set_range(0, 9999) + + grid0.addWidget(self.grb_array_size_label, 4, 0) + grid0.addWidget(self.grb_array_size_entry, 4, 1) + + self.adddim_label = QtWidgets.QLabel('%s:' % _('Aperture Dimensions')) + self.adddim_label.setToolTip( + _("Diameters of the tools, separated by comma.\n" + "The value of the diameter has to use the dot decimals separator.\n" + "Valid values: 0.3, 1.0") + ) + grid0.addWidget(self.adddim_label, 5, 0) + self.adddim_entry = FCEntry() + grid0.addWidget(self.adddim_entry, 5, 1) + + self.grb_array_linear_label = QtWidgets.QLabel('%s:' % _('Linear Pad Array')) + grid0.addWidget(self.grb_array_linear_label, 6, 0, 1, 2) + + # Linear Pad Array direction + self.grb_axis_label = QtWidgets.QLabel('%s:' % _('Linear Direction')) + self.grb_axis_label.setToolTip( + _("Direction on which the linear array is oriented:\n" + "- 'X' - horizontal axis \n" + "- 'Y' - vertical axis or \n" + "- 'Angle' - a custom angle for the array inclination") + ) + + self.grb_axis_radio = RadioSet([{'label': _('X'), 'value': 'X'}, + {'label': _('Y'), 'value': 'Y'}, + {'label': _('Angle'), 'value': 'A'}]) + + grid0.addWidget(self.grb_axis_label, 7, 0) + grid0.addWidget(self.grb_axis_radio, 7, 1) + + # Linear Pad Array pitch distance + self.grb_pitch_label = QtWidgets.QLabel('%s:' % _('Pitch')) + self.grb_pitch_label.setToolTip( + _("Pitch = Distance between elements of the array.") + ) + # self.drill_pitch_label.setMinimumWidth(100) + self.grb_pitch_entry = FCDoubleSpinner() + self.grb_pitch_entry.set_precision(self.decimals) + + grid0.addWidget(self.grb_pitch_label, 8, 0) + grid0.addWidget(self.grb_pitch_entry, 8, 1) + + # Linear Pad Array custom angle + self.grb_angle_label = QtWidgets.QLabel('%s:' % _('Angle')) + self.grb_angle_label.setToolTip( + _("Angle at which each element in circular array is placed.") + ) + self.grb_angle_entry = FCDoubleSpinner() + self.grb_angle_entry.set_precision(self.decimals) + self.grb_angle_entry.set_range(-360, 360) + self.grb_angle_entry.setSingleStep(5) + + grid0.addWidget(self.grb_angle_label, 9, 0) + grid0.addWidget(self.grb_angle_entry, 9, 1) + + self.grb_array_circ_label = QtWidgets.QLabel('%s:' % _('Circular Pad Array')) + grid0.addWidget(self.grb_array_circ_label, 10, 0, 1, 2) + + # Circular Pad Array direction + self.grb_circular_direction_label = QtWidgets.QLabel('%s:' % _('Circular Direction')) + self.grb_circular_direction_label.setToolTip( + _("Direction for circular array.\n" + "Can be CW = clockwise or CCW = counter clockwise.") + ) + + self.grb_circular_dir_radio = RadioSet([{'label': _('CW'), 'value': 'CW'}, + {'label': _('CCW'), 'value': 'CCW'}]) + + grid0.addWidget(self.grb_circular_direction_label, 11, 0) + grid0.addWidget(self.grb_circular_dir_radio, 11, 1) + + # Circular Pad Array Angle + self.grb_circular_angle_label = QtWidgets.QLabel('%s:' % _('Circular Angle')) + self.grb_circular_angle_label.setToolTip( + _("Angle at which each element in circular array is placed.") + ) + self.grb_circular_angle_entry = FCDoubleSpinner() + self.grb_circular_angle_entry.set_precision(self.decimals) + self.grb_circular_angle_entry.set_range(-360, 360) + + self.grb_circular_angle_entry.setSingleStep(5) + + grid0.addWidget(self.grb_circular_angle_label, 12, 0) + grid0.addWidget(self.grb_circular_angle_entry, 12, 1) + + self.grb_array_tools_b_label = QtWidgets.QLabel('%s:' % _('Buffer Tool')) + grid0.addWidget(self.grb_array_tools_b_label, 13, 0, 1, 2) + + # Buffer Distance + self.grb_buff_label = QtWidgets.QLabel('%s:' % _('Buffer distance')) + self.grb_buff_label.setToolTip( + _("Distance at which to buffer the Gerber element.") + ) + self.grb_buff_entry = FCDoubleSpinner() + self.grb_buff_entry.set_precision(self.decimals) + self.grb_buff_entry.set_range(-9999, 9999) + + grid0.addWidget(self.grb_buff_label, 14, 0) + grid0.addWidget(self.grb_buff_entry, 14, 1) + + self.grb_array_tools_s_label = QtWidgets.QLabel('%s:' % _('Scale Tool')) + grid0.addWidget(self.grb_array_tools_s_label, 15, 0, 1, 2) + + # Scale Factor + self.grb_scale_label = QtWidgets.QLabel('%s:' % _('Scale factor')) + self.grb_scale_label.setToolTip( + _("Factor to scale the Gerber element.") + ) + self.grb_scale_entry = FCDoubleSpinner() + self.grb_scale_entry.set_precision(self.decimals) + self.grb_scale_entry.set_range(0, 9999) + + grid0.addWidget(self.grb_scale_label, 16, 0) + grid0.addWidget(self.grb_scale_entry, 16, 1) + + self.grb_array_tools_ma_label = QtWidgets.QLabel('%s:' % _('Mark Area Tool')) + grid0.addWidget(self.grb_array_tools_ma_label, 17, 0, 1, 2) + + # Mark area Tool low threshold + self.grb_ma_low_label = QtWidgets.QLabel('%s:' % _('Threshold low')) + self.grb_ma_low_label.setToolTip( + _("Threshold value under which the apertures are not marked.") + ) + self.grb_ma_low_entry = FCDoubleSpinner() + self.grb_ma_low_entry.set_precision(self.decimals) + self.grb_ma_low_entry.set_range(0, 9999) + + grid0.addWidget(self.grb_ma_low_label, 18, 0) + grid0.addWidget(self.grb_ma_low_entry, 18, 1) + + # Mark area Tool high threshold + self.grb_ma_high_label = QtWidgets.QLabel('%s:' % _('Threshold high')) + self.grb_ma_high_label.setToolTip( + _("Threshold value over which the apertures are not marked.") + ) + self.grb_ma_high_entry = FCDoubleSpinner() + self.grb_ma_high_entry.set_precision(self.decimals) + self.grb_ma_high_entry.set_range(0, 9999) + + grid0.addWidget(self.grb_ma_high_label, 19, 0) + grid0.addWidget(self.grb_ma_high_entry, 19, 1) + + self.layout.addStretch() diff --git a/flatcamGUI/preferences/gerber/GerberExpPrefGroupUI.py b/flatcamGUI/preferences/gerber/GerberExpPrefGroupUI.py index e6e85fb6..01729dc5 100644 --- a/flatcamGUI/preferences/gerber/GerberExpPrefGroupUI.py +++ b/flatcamGUI/preferences/gerber/GerberExpPrefGroupUI.py @@ -1,5 +1,8 @@ -from flatcamGUI.preferences.OptionUI import * -from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI2 +from PyQt5 import QtWidgets, QtCore +from PyQt5.QtCore import QSettings + +from flatcamGUI.GUIElements import RadioSet, FCSpinner +from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI import gettext import FlatCAMTranslation as fcTranslate @@ -9,49 +12,107 @@ fcTranslate.apply_language('strings') if '_' not in builtins.__dict__: _ = gettext.gettext +settings = QSettings("Open Source", "FlatCAM") +if settings.contains("machinist"): + machinist_setting = settings.value('machinist', type=int) +else: + machinist_setting = 0 -class GerberExpPrefGroupUI(OptionsGroupUI2): - def __init__(self, decimals=4, **kwargs): - self.decimals = decimals - super().__init__(**kwargs) +class GerberExpPrefGroupUI(OptionsGroupUI): + + def __init__(self, decimals=4, parent=None): + super(GerberExpPrefGroupUI, self).__init__(self, parent=parent) + self.setTitle(str(_("Gerber Export"))) + self.decimals = decimals - def build_options(self) -> [OptionUI]: - return [ - HeadingOptionUI( - label_text="Export Options", - label_tooltip="The parameters set here are used in the file exported\n" - "when using the File -> Export -> Export Gerber menu entry." - ), - RadioSetOptionUI( - option="gerber_exp_units", - label_text="Units", - label_tooltip="The units used in the Gerber file.", - choices=[{'label': _('INCH'), 'value': 'IN'}, - {'label': _('MM'), 'value': 'MM'}] - ), - SpinnerOptionUI( - option="gerber_exp_integer", - label_text="Int", - label_tooltip="The number of digits in the whole part of Gerber coordinates", - min_value=0, max_value=9, step=1 - ), - SpinnerOptionUI( - option="gerber_exp_decimals", - label_text="Decimals", - label_tooltip="The number of digits in the decimal part of Gerber coordinates", - min_value=0, max_value=9, step=1 - ), - RadioSetOptionUI( - option="gerber_exp_zeros", - label_text="Zeros", - label_tooltip="This sets the type of Gerber zeros.\n" - "If LZ then Leading Zeros are removed and\n" - "Trailing Zeros are kept.\n" - "If TZ is checked then Trailing Zeros are removed\n" - "and Leading Zeros are kept.", - choices=[{'label': _('LZ'), 'value': 'L'}, - {'label': _('TZ'), 'value': 'T'}] - ) - ] \ No newline at end of file + # Plot options + self.export_options_label = QtWidgets.QLabel("%s:" % _("Export Options")) + self.export_options_label.setToolTip( + _("The parameters set here are used in the file exported\n" + "when using the File -> Export -> Export Gerber menu entry.") + ) + self.layout.addWidget(self.export_options_label) + + form = QtWidgets.QFormLayout() + self.layout.addLayout(form) + + # Gerber Units + self.gerber_units_label = QtWidgets.QLabel('%s:' % _('Units')) + self.gerber_units_label.setToolTip( + _("The units used in the Gerber file.") + ) + + self.gerber_units_radio = RadioSet([{'label': _('INCH'), 'value': 'IN'}, + {'label': _('MM'), 'value': 'MM'}]) + self.gerber_units_radio.setToolTip( + _("The units used in the Gerber file.") + ) + + form.addRow(self.gerber_units_label, self.gerber_units_radio) + + # Gerber format + self.digits_label = QtWidgets.QLabel("%s:" % _("Int/Decimals")) + self.digits_label.setToolTip( + _("The number of digits in the whole part of the number\n" + "and in the fractional part of the number.") + ) + + hlay1 = QtWidgets.QHBoxLayout() + + self.format_whole_entry = FCSpinner() + self.format_whole_entry.set_range(0, 9) + self.format_whole_entry.set_step(1) + self.format_whole_entry.setWrapping(True) + + self.format_whole_entry.setMinimumWidth(30) + self.format_whole_entry.setToolTip( + _("This numbers signify the number of digits in\n" + "the whole part of Gerber coordinates.") + ) + hlay1.addWidget(self.format_whole_entry, QtCore.Qt.AlignLeft) + + gerber_separator_label = QtWidgets.QLabel(':') + gerber_separator_label.setFixedWidth(5) + hlay1.addWidget(gerber_separator_label, QtCore.Qt.AlignLeft) + + self.format_dec_entry = FCSpinner() + self.format_dec_entry.set_range(0, 9) + self.format_dec_entry.set_step(1) + self.format_dec_entry.setWrapping(True) + + self.format_dec_entry.setMinimumWidth(30) + self.format_dec_entry.setToolTip( + _("This numbers signify the number of digits in\n" + "the decimal part of Gerber coordinates.") + ) + hlay1.addWidget(self.format_dec_entry, QtCore.Qt.AlignLeft) + hlay1.addStretch() + + form.addRow(self.digits_label, hlay1) + + # Gerber Zeros + self.zeros_label = QtWidgets.QLabel('%s:' % _('Zeros')) + self.zeros_label.setAlignment(QtCore.Qt.AlignLeft) + self.zeros_label.setToolTip( + _("This sets the type of Gerber zeros.\n" + "If LZ then Leading Zeros are removed and\n" + "Trailing Zeros are kept.\n" + "If TZ is checked then Trailing Zeros are removed\n" + "and Leading Zeros are kept.") + ) + + self.zeros_radio = RadioSet([{'label': _('LZ'), 'value': 'L'}, + {'label': _('TZ'), 'value': 'T'}]) + self.zeros_radio.setToolTip( + _("This sets the type of Gerber zeros.\n" + "If LZ then Leading Zeros are removed and\n" + "Trailing Zeros are kept.\n" + "If TZ is checked then Trailing Zeros are removed\n" + "and Leading Zeros are kept.") + ) + + form.addRow(self.zeros_label, self.zeros_radio) + + self.layout.addStretch() diff --git a/flatcamGUI/preferences/gerber/GerberGenPrefGroupUI.py b/flatcamGUI/preferences/gerber/GerberGenPrefGroupUI.py index 33acdfcc..6f52fe45 100644 --- a/flatcamGUI/preferences/gerber/GerberGenPrefGroupUI.py +++ b/flatcamGUI/preferences/gerber/GerberGenPrefGroupUI.py @@ -1,106 +1,273 @@ -from flatcamGUI.preferences.OptionUI import * -from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI2 +from PyQt5 import QtWidgets, QtCore, QtGui +from PyQt5.QtCore import QSettings + +from flatcamGUI.GUIElements import FCCheckBox, FCSpinner, RadioSet, FCEntry +from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI import gettext import FlatCAMTranslation as fcTranslate import builtins + fcTranslate.apply_language('strings') if '_' not in builtins.__dict__: _ = gettext.gettext +settings = QSettings("Open Source", "FlatCAM") +if settings.contains("machinist"): + machinist_setting = settings.value('machinist', type=int) +else: + machinist_setting = 0 + + +class GerberGenPrefGroupUI(OptionsGroupUI): + def __init__(self, decimals=4, parent=None): + # OptionsGroupUI.__init__(self, "Gerber General Preferences", parent=parent) + super(GerberGenPrefGroupUI, self).__init__(self, parent=parent) -class GerberGenPrefGroupUI(OptionsGroupUI2): - def __init__(self, decimals=4, **kwargs): - self.decimals = decimals - super().__init__(**kwargs) self.setTitle(str(_("Gerber General"))) + self.decimals = decimals - def build_options(self) -> [OptionUI]: - return [ - HeadingOptionUI(label_text="Plot Options"), - CheckboxOptionUI( - option="gerber_solid", - label_text="Solid", - label_tooltip="Solid color polygons." - ), - CheckboxOptionUI( - option="gerber_multicolored", - label_text="M-Color", - label_tooltip="Draw polygons in different colors." - ), - CheckboxOptionUI( - option="gerber_plot", - label_text="Plot", - label_tooltip="Plot (show) this object." - ), - SpinnerOptionUI( - option="gerber_circle_steps", - label_text="Circle Steps", - label_tooltip="The number of circle steps for Gerber \n" - "circular aperture linear approximation.", - min_value=0, max_value=9999, step=1 - ), - SeparatorOptionUI(), + # ## Plot options + self.plot_options_label = QtWidgets.QLabel("%s:" % _("Plot Options")) + self.layout.addWidget(self.plot_options_label) - HeadingOptionUI( - label_text="Default Values", - label_tooltip="Those values will be used as fallback values\n" - "in case that they are not found in the Gerber file." - ), - RadioSetOptionUI( - option="gerber_def_units", - label_text="Units", - label_tooltip="The units used in the Gerber file.", - choices=[{'label': _('INCH'), 'value': 'IN'}, - {'label': _('MM'), 'value': 'MM'}] - ), - RadioSetOptionUI( - option="gerber_def_zeros", - label_text="Zeros", - label_tooltip="This sets the type of Gerber zeros.\n" - "If LZ then Leading Zeros are removed and\n" - "Trailing Zeros are kept.\n" - "If TZ is checked then Trailing Zeros are removed\n" - "and Leading Zeros are kept.", - choices=[{'label': _('LZ'), 'value': 'L'}, - {'label': _('TZ'), 'value': 'T'}] - ), - SeparatorOptionUI(), + grid0 = QtWidgets.QGridLayout() + self.layout.addLayout(grid0) - CheckboxOptionUI( - option="gerber_clean_apertures", - label_text="Clean Apertures", - label_tooltip="Will remove apertures that do not have geometry\n" - "thus lowering the number of apertures in the Gerber object." - ), - CheckboxOptionUI( - option="gerber_extra_buffering", - label_text="Polarity change buffer", - label_tooltip="Will apply extra buffering for the\n" - "solid geometry when we have polarity changes.\n" - "May help loading Gerber files that otherwise\n" - "do not load correctly." - ), - SeparatorOptionUI(), + # Solid CB + self.solid_cb = FCCheckBox(label='%s' % _('Solid')) + self.solid_cb.setToolTip( + _("Solid color polygons.") + ) + grid0.addWidget(self.solid_cb, 0, 0) - HeadingOptionUI(label_text="Gerber Object Color"), - ColorOptionUI( - option="gerber_plot_line", - label_text="Outline", - label_tooltip="Set the line color for plotted objects.", - ), - ColorOptionUI( - option="gerber_plot_fill", - label_text="Fill", - label_tooltip="Set the fill color for plotted objects.\n" - "First 6 digits are the color and the last 2\n" - "digits are for alpha (transparency) level." - ), - ColorAlphaSliderOptionUI( - applies_to=["gerber_plot_line", "gerber_plot_fill"], - group=self, - label_text="Alpha", - label_tooltip="Set the transparency for plotted objects." - ) - ] + # Multicolored CB + self.multicolored_cb = FCCheckBox(label='%s' % _('M-Color')) + self.multicolored_cb.setToolTip( + _("Draw polygons in different colors.") + ) + grid0.addWidget(self.multicolored_cb, 0, 1) + # Plot CB + self.plot_cb = FCCheckBox(label='%s' % _('Plot')) + self.plot_options_label.setToolTip( + _("Plot (show) this object.") + ) + grid0.addWidget(self.plot_cb, 0, 2) + + # Number of circle steps for circular aperture linear approximation + self.circle_steps_label = QtWidgets.QLabel('%s:' % _("Circle Steps")) + self.circle_steps_label.setToolTip( + _("The number of circle steps for Gerber \n" + "circular aperture linear approximation.") + ) + self.circle_steps_entry = FCSpinner() + self.circle_steps_entry.set_range(0, 9999) + + grid0.addWidget(self.circle_steps_label, 1, 0) + grid0.addWidget(self.circle_steps_entry, 1, 1, 1, 2) + + grid0.addWidget(QtWidgets.QLabel(''), 2, 0, 1, 3) + + # Default format for Gerber + self.gerber_default_label = QtWidgets.QLabel('%s:' % _('Default Values')) + self.gerber_default_label.setToolTip( + _("Those values will be used as fallback values\n" + "in case that they are not found in the Gerber file.") + ) + + grid0.addWidget(self.gerber_default_label, 3, 0, 1, 3) + + # Gerber Units + self.gerber_units_label = QtWidgets.QLabel('%s:' % _('Units')) + self.gerber_units_label.setToolTip( + _("The units used in the Gerber file.") + ) + + self.gerber_units_radio = RadioSet([{'label': _('INCH'), 'value': 'IN'}, + {'label': _('MM'), 'value': 'MM'}]) + self.gerber_units_radio.setToolTip( + _("The units used in the Gerber file.") + ) + + grid0.addWidget(self.gerber_units_label, 4, 0) + grid0.addWidget(self.gerber_units_radio, 4, 1, 1, 2) + + # Gerber Zeros + self.gerber_zeros_label = QtWidgets.QLabel('%s:' % _('Zeros')) + self.gerber_zeros_label.setAlignment(QtCore.Qt.AlignLeft) + self.gerber_zeros_label.setToolTip( + _("This sets the type of Gerber zeros.\n" + "If LZ then Leading Zeros are removed and\n" + "Trailing Zeros are kept.\n" + "If TZ is checked then Trailing Zeros are removed\n" + "and Leading Zeros are kept.") + ) + + self.gerber_zeros_radio = RadioSet([{'label': _('LZ'), 'value': 'L'}, + {'label': _('TZ'), 'value': 'T'}]) + self.gerber_zeros_radio.setToolTip( + _("This sets the type of Gerber zeros.\n" + "If LZ then Leading Zeros are removed and\n" + "Trailing Zeros are kept.\n" + "If TZ is checked then Trailing Zeros are removed\n" + "and Leading Zeros are kept.") + ) + + grid0.addWidget(self.gerber_zeros_label, 5, 0) + grid0.addWidget(self.gerber_zeros_radio, 5, 1, 1, 2) + + separator_line = QtWidgets.QFrame() + separator_line.setFrameShape(QtWidgets.QFrame.HLine) + separator_line.setFrameShadow(QtWidgets.QFrame.Sunken) + grid0.addWidget(separator_line, 6, 0, 1, 3) + + # Apertures Cleaning + self.gerber_clean_cb = FCCheckBox(label='%s' % _('Clean Apertures')) + self.gerber_clean_cb.setToolTip( + _("Will remove apertures that do not have geometry\n" + "thus lowering the number of apertures in the Gerber object.") + ) + grid0.addWidget(self.gerber_clean_cb, 7, 0, 1, 3) + + # Apply Extra Buffering + self.gerber_extra_buffering = FCCheckBox(label='%s' % _('Polarity change buffer')) + self.gerber_extra_buffering.setToolTip( + _("Will apply extra buffering for the\n" + "solid geometry when we have polarity changes.\n" + "May help loading Gerber files that otherwise\n" + "do not load correctly.") + ) + grid0.addWidget(self.gerber_extra_buffering, 8, 0, 1, 3) + + separator_line = QtWidgets.QFrame() + separator_line.setFrameShape(QtWidgets.QFrame.HLine) + separator_line.setFrameShadow(QtWidgets.QFrame.Sunken) + grid0.addWidget(separator_line, 9, 0, 1, 3) + + # Gerber Object Color + self.gerber_color_label = QtWidgets.QLabel('%s' % _('Gerber Object Color')) + grid0.addWidget(self.gerber_color_label, 10, 0, 1, 3) + + # Plot Line Color + self.pl_color_label = QtWidgets.QLabel('%s:' % _('Outline')) + self.pl_color_label.setToolTip( + _("Set the line color for plotted objects.") + ) + self.pl_color_entry = FCEntry() + self.pl_color_button = QtWidgets.QPushButton() + self.pl_color_button.setFixedSize(15, 15) + + self.form_box_child_2 = QtWidgets.QHBoxLayout() + self.form_box_child_2.addWidget(self.pl_color_entry) + self.form_box_child_2.addWidget(self.pl_color_button) + self.form_box_child_2.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter) + + grid0.addWidget(self.pl_color_label, 11, 0) + grid0.addLayout(self.form_box_child_2, 11, 1, 1, 2) + + # Plot Fill Color + self.pf_color_label = QtWidgets.QLabel('%s:' % _('Fill')) + self.pf_color_label.setToolTip( + _("Set the fill color for plotted objects.\n" + "First 6 digits are the color and the last 2\n" + "digits are for alpha (transparency) level.") + ) + self.pf_color_entry = FCEntry() + self.pf_color_button = QtWidgets.QPushButton() + self.pf_color_button.setFixedSize(15, 15) + + self.form_box_child_1 = QtWidgets.QHBoxLayout() + self.form_box_child_1.addWidget(self.pf_color_entry) + self.form_box_child_1.addWidget(self.pf_color_button) + self.form_box_child_1.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter) + + grid0.addWidget(self.pf_color_label, 12, 0) + grid0.addLayout(self.form_box_child_1, 12, 1, 1, 2) + + # Plot Fill Transparency Level + self.pf_alpha_label = QtWidgets.QLabel('%s:' % _('Alpha')) + self.pf_alpha_label.setToolTip( + _("Set the fill transparency for plotted objects.") + ) + self.pf_color_alpha_slider = QtWidgets.QSlider(QtCore.Qt.Horizontal) + self.pf_color_alpha_slider.setMinimum(0) + self.pf_color_alpha_slider.setMaximum(255) + self.pf_color_alpha_slider.setSingleStep(1) + + self.pf_color_alpha_spinner = FCSpinner() + self.pf_color_alpha_spinner.setMinimumWidth(70) + self.pf_color_alpha_spinner.set_range(0, 255) + + self.form_box_child_3 = QtWidgets.QHBoxLayout() + self.form_box_child_3.addWidget(self.pf_color_alpha_slider) + self.form_box_child_3.addWidget(self.pf_color_alpha_spinner) + + grid0.addWidget(self.pf_alpha_label, 13, 0) + grid0.addLayout(self.form_box_child_3, 13, 1, 1, 2) + + self.layout.addStretch() + + # Setting plot colors signals + self.pl_color_entry.editingFinished.connect(self.on_pl_color_entry) + self.pl_color_button.clicked.connect(self.on_pl_color_button) + self.pf_color_entry.editingFinished.connect(self.on_pf_color_entry) + self.pf_color_button.clicked.connect(self.on_pf_color_button) + self.pf_color_alpha_spinner.valueChanged.connect(self.on_pf_color_spinner) + self.pf_color_alpha_slider.valueChanged.connect(self.on_pf_color_slider) + + # Setting plot colors handlers + def on_pf_color_entry(self): + self.app.defaults['gerber_plot_fill'] = self.pf_color_entry.get_value()[:7] + \ + self.app.defaults['gerber_plot_fill'][7:9] + self.pf_color_button.setStyleSheet("background-color:%s" % str(self.app.defaults['gerber_plot_fill'])[:7]) + + def on_pf_color_button(self): + current_color = QtGui.QColor(self.app.defaults['gerber_plot_fill'][:7]) + + c_dialog = QtWidgets.QColorDialog() + plot_fill_color = c_dialog.getColor(initial=current_color) + + if plot_fill_color.isValid() is False: + return + + self.pf_color_button.setStyleSheet("background-color:%s" % str(plot_fill_color.name())) + + new_val = str(plot_fill_color.name()) + str(self.app.defaults['gerber_plot_fill'][7:9]) + self.pf_color_entry.set_value(new_val) + self.app.defaults['gerber_plot_fill'] = new_val + + def on_pf_color_spinner(self): + spinner_value = self.pf_color_alpha_spinner.value() + self.pf_color_alpha_slider.setValue(spinner_value) + self.app.defaults['gerber_plot_fill'] = \ + self.app.defaults['gerber_plot_fill'][:7] + \ + (hex(spinner_value)[2:] if int(hex(spinner_value)[2:], 16) > 0 else '00') + self.app.defaults['gerber_plot_line'] = \ + self.app.defaults['gerber_plot_line'][:7] + \ + (hex(spinner_value)[2:] if int(hex(spinner_value)[2:], 16) > 0 else '00') + + def on_pf_color_slider(self): + slider_value = self.pf_color_alpha_slider.value() + self.pf_color_alpha_spinner.setValue(slider_value) + + def on_pl_color_entry(self): + self.app.defaults['gerber_plot_line'] = self.pl_color_entry.get_value()[:7] + \ + self.app.defaults['gerber_plot_line'][7:9] + self.pl_color_button.setStyleSheet("background-color:%s" % str(self.app.defaults['gerber_plot_line'])[:7]) + + def on_pl_color_button(self): + current_color = QtGui.QColor(self.app.defaults['gerber_plot_line'][:7]) + # print(current_color) + + c_dialog = QtWidgets.QColorDialog() + plot_line_color = c_dialog.getColor(initial=current_color) + + if plot_line_color.isValid() is False: + return + + self.pl_color_button.setStyleSheet("background-color:%s" % str(plot_line_color.name())) + + new_val_line = str(plot_line_color.name()) + str(self.app.defaults['gerber_plot_line'][7:9]) + self.pl_color_entry.set_value(new_val_line) + self.app.defaults['gerber_plot_line'] = new_val_line diff --git a/flatcamGUI/preferences/gerber/GerberOptPrefGroupUI.py b/flatcamGUI/preferences/gerber/GerberOptPrefGroupUI.py index 231c6528..404f17ba 100644 --- a/flatcamGUI/preferences/gerber/GerberOptPrefGroupUI.py +++ b/flatcamGUI/preferences/gerber/GerberOptPrefGroupUI.py @@ -1,5 +1,8 @@ -from flatcamGUI.preferences.OptionUI import * -from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI2 +from PyQt5 import QtWidgets +from PyQt5.QtCore import QSettings + +from flatcamGUI.GUIElements import FCDoubleSpinner, FCSpinner, RadioSet, FCCheckBox +from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI import gettext import FlatCAMTranslation as fcTranslate @@ -9,103 +12,176 @@ fcTranslate.apply_language('strings') if '_' not in builtins.__dict__: _ = gettext.gettext +settings = QSettings("Open Source", "FlatCAM") +if settings.contains("machinist"): + machinist_setting = settings.value('machinist', type=int) +else: + machinist_setting = 0 -class GerberOptPrefGroupUI(OptionsGroupUI2): - def __init__(self, decimals=4, **kwargs): +class GerberOptPrefGroupUI(OptionsGroupUI): + def __init__(self, decimals=4, parent=None): + # OptionsGroupUI.__init__(self, "Gerber Options Preferences", parent=parent) + super(GerberOptPrefGroupUI, self).__init__(self, parent=parent) + self.decimals = decimals - super().__init__(**kwargs) + self.setTitle(str(_("Gerber Options"))) - def build_options(self) -> [OptionUI]: - return [ - HeadingOptionUI( - label_text="Isolation Routing", - label_tooltip="Create a Geometry object with\n" - "toolpaths to cut outside polygons." - ), - DoubleSpinnerOptionUI( - option="gerber_isotooldia", - label_text="Tool dia", - label_tooltip="Diameter of the cutting tool.", - min_value=0.0, max_value=9999.9, step=0.1, decimals=self.decimals - ), - SpinnerOptionUI( - option="gerber_isopasses", - label_text="# Passes", - label_tooltip="Width of the isolation gap in\n" - "number (integer) of tool widths.", - min_value=1, max_value=999, step=1 - ), - DoubleSpinnerOptionUI( - option="gerber_isooverlap", - label_text="Pass overlap", - label_tooltip="How much (percentage) of the tool width to overlap each tool pass.", - min_value=0.0, max_value=99.9999, step=0.1, decimals=self.decimals, suffix="%" - ), - RadioSetOptionUI( - option="gerber_iso_scope", - label_text="Scope", - label_tooltip="Isolation scope. Choose what to isolate:\n" - "- 'All' -> Isolate all the polygons in the object\n" - "- 'Selection' -> Isolate a selection of polygons.", - choices=[{'label': _('All'), 'value': 'all'}, - {'label': _('Selection'), 'value': 'single'}] - ), - RadioSetOptionUI( - option="gerber_milling_type", - label_text="Milling Type", - label_tooltip="Milling type:\n" - "- climb / best for precision milling and to reduce tool usage\n" - "- conventional / useful when there is no backlash compensation", - choices=[{'label': _('Climb'), 'value': 'cl'}, - {'label': _('Conventional'), 'value': 'cv'}] - ), - CheckboxOptionUI( - option="gerber_combine_passes", - label_text="Combine Passes", - label_tooltip="Combine all passes into one object" - ), - SeparatorOptionUI(), + # ## Isolation Routing + self.isolation_routing_label = QtWidgets.QLabel("%s:" % _("Isolation Routing")) + self.isolation_routing_label.setToolTip( + _("Create a Geometry object with\n" + "toolpaths to cut outside polygons.") + ) + self.layout.addWidget(self.isolation_routing_label) - HeadingOptionUI( - label_text="Non-copper regions", - label_tooltip="Create polygons covering the\n" - "areas without copper on the PCB.\n" - "Equivalent to the inverse of this\n" - "object. Can be used to remove all\n" - "copper from a specified region." - ), - DoubleSpinnerOptionUI( - option="gerber_noncoppermargin", - label_text="Boundary Margin", - label_tooltip="Specify the edge of the PCB\n" - "by drawing a box around all\n" - "objects with this minimum\n" - "distance.", - min_value=-9999, max_value=9999, step=0.1, decimals=self.decimals - ), - CheckboxOptionUI( - option="gerber_noncopperrounded", - label_text="Rounded Geo", - label_tooltip="Resulting geometry will have rounded corners." - ), - SeparatorOptionUI(), + # Cutting Tool Diameter + grid0 = QtWidgets.QGridLayout() + self.layout.addLayout(grid0) - HeadingOptionUI(label_text="Bounding Box"), - DoubleSpinnerOptionUI( - option="gerber_bboxmargin", - label_text="Boundary Margin", - label_tooltip="Distance of the edges of the box\n" - "to the nearest polygon.", - min_value=-9999, max_value=9999, step=0.1, decimals=self.decimals - ), - CheckboxOptionUI( - option="gerber_bboxrounded", - label_text="Rounded Geo", - label_tooltip="If the bounding box is \n" - "to have rounded corners\n" - "their radius is equal to\n" - "the margin." - ), - ] \ No newline at end of file + tdlabel = QtWidgets.QLabel('%s:' % _('Tool dia')) + tdlabel.setToolTip( + _("Diameter of the cutting tool.") + ) + grid0.addWidget(tdlabel, 0, 0) + self.iso_tool_dia_entry = FCDoubleSpinner() + self.iso_tool_dia_entry.set_precision(self.decimals) + self.iso_tool_dia_entry.setSingleStep(0.1) + self.iso_tool_dia_entry.set_range(-9999, 9999) + + grid0.addWidget(self.iso_tool_dia_entry, 0, 1) + + # Nr of passes + passlabel = QtWidgets.QLabel('%s:' % _('# Passes')) + passlabel.setToolTip( + _("Width of the isolation gap in\n" + "number (integer) of tool widths.") + ) + self.iso_width_entry = FCSpinner() + self.iso_width_entry.set_range(1, 999) + + grid0.addWidget(passlabel, 1, 0) + grid0.addWidget(self.iso_width_entry, 1, 1) + + # Pass overlap + overlabel = QtWidgets.QLabel('%s:' % _('Pass overlap')) + overlabel.setToolTip( + _("How much (percentage) of the tool width to overlap each tool pass.") + ) + self.iso_overlap_entry = FCDoubleSpinner(suffix='%') + self.iso_overlap_entry.set_precision(self.decimals) + self.iso_overlap_entry.setWrapping(True) + self.iso_overlap_entry.setRange(0.0000, 99.9999) + self.iso_overlap_entry.setSingleStep(0.1) + + grid0.addWidget(overlabel, 2, 0) + grid0.addWidget(self.iso_overlap_entry, 2, 1) + + # Isolation Scope + self.iso_scope_label = QtWidgets.QLabel('%s:' % _('Scope')) + self.iso_scope_label.setToolTip( + _("Isolation scope. Choose what to isolate:\n" + "- 'All' -> Isolate all the polygons in the object\n" + "- 'Selection' -> Isolate a selection of polygons.") + ) + self.iso_scope_radio = RadioSet([{'label': _('All'), 'value': 'all'}, + {'label': _('Selection'), 'value': 'single'}]) + + grid0.addWidget(self.iso_scope_label, 3, 0) + grid0.addWidget(self.iso_scope_radio, 3, 1, 1, 2) + + # Milling Type + milling_type_label = QtWidgets.QLabel('%s:' % _('Milling Type')) + milling_type_label.setToolTip( + _("Milling type:\n" + "- climb / best for precision milling and to reduce tool usage\n" + "- conventional / useful when there is no backlash compensation") + ) + grid0.addWidget(milling_type_label, 4, 0) + self.milling_type_radio = RadioSet([{'label': _('Climb'), 'value': 'cl'}, + {'label': _('Conventional'), 'value': 'cv'}]) + grid0.addWidget(self.milling_type_radio, 4, 1) + + # Combine passes + self.combine_passes_cb = FCCheckBox(label=_('Combine Passes')) + self.combine_passes_cb.setToolTip( + _("Combine all passes into one object") + ) + grid0.addWidget(self.combine_passes_cb, 5, 0, 1, 2) + + separator_line = QtWidgets.QFrame() + separator_line.setFrameShape(QtWidgets.QFrame.HLine) + separator_line.setFrameShadow(QtWidgets.QFrame.Sunken) + grid0.addWidget(separator_line, 6, 0, 1, 2) + + # ## Clear non-copper regions + self.clearcopper_label = QtWidgets.QLabel("%s:" % _("Non-copper regions")) + self.clearcopper_label.setToolTip( + _("Create polygons covering the\n" + "areas without copper on the PCB.\n" + "Equivalent to the inverse of this\n" + "object. Can be used to remove all\n" + "copper from a specified region.") + ) + self.layout.addWidget(self.clearcopper_label) + + grid1 = QtWidgets.QGridLayout() + self.layout.addLayout(grid1) + + # Margin + bmlabel = QtWidgets.QLabel('%s:' % _('Boundary Margin')) + bmlabel.setToolTip( + _("Specify the edge of the PCB\n" + "by drawing a box around all\n" + "objects with this minimum\n" + "distance.") + ) + grid1.addWidget(bmlabel, 0, 0) + self.noncopper_margin_entry = FCDoubleSpinner() + self.noncopper_margin_entry.set_precision(self.decimals) + self.noncopper_margin_entry.setSingleStep(0.1) + self.noncopper_margin_entry.set_range(-9999, 9999) + grid1.addWidget(self.noncopper_margin_entry, 0, 1) + + # Rounded corners + self.noncopper_rounded_cb = FCCheckBox(label=_("Rounded Geo")) + self.noncopper_rounded_cb.setToolTip( + _("Resulting geometry will have rounded corners.") + ) + grid1.addWidget(self.noncopper_rounded_cb, 1, 0, 1, 2) + + separator_line = QtWidgets.QFrame() + separator_line.setFrameShape(QtWidgets.QFrame.HLine) + separator_line.setFrameShadow(QtWidgets.QFrame.Sunken) + grid1.addWidget(separator_line, 2, 0, 1, 2) + + # ## Bounding box + self.boundingbox_label = QtWidgets.QLabel('%s:' % _('Bounding Box')) + self.layout.addWidget(self.boundingbox_label) + + grid2 = QtWidgets.QGridLayout() + self.layout.addLayout(grid2) + + bbmargin = QtWidgets.QLabel('%s:' % _('Boundary Margin')) + bbmargin.setToolTip( + _("Distance of the edges of the box\n" + "to the nearest polygon.") + ) + self.bbmargin_entry = FCDoubleSpinner() + self.bbmargin_entry.set_precision(self.decimals) + self.bbmargin_entry.setSingleStep(0.1) + self.bbmargin_entry.set_range(-9999, 9999) + + grid2.addWidget(bbmargin, 0, 0) + grid2.addWidget(self.bbmargin_entry, 0, 1) + + self.bbrounded_cb = FCCheckBox(label='%s' % _("Rounded Geo")) + self.bbrounded_cb.setToolTip( + _("If the bounding box is \n" + "to have rounded corners\n" + "their radius is equal to\n" + "the margin.") + ) + grid2.addWidget(self.bbrounded_cb, 1, 0, 1, 2) + self.layout.addStretch() diff --git a/flatcamGUI/preferences/gerber/GerberPreferencesUI.py b/flatcamGUI/preferences/gerber/GerberPreferencesUI.py index 8d3b3e90..f9d9f8aa 100644 --- a/flatcamGUI/preferences/gerber/GerberPreferencesUI.py +++ b/flatcamGUI/preferences/gerber/GerberPreferencesUI.py @@ -1,5 +1,6 @@ -from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI -from flatcamGUI.preferences.PreferencesSectionUI import PreferencesSectionUI +from PyQt5 import QtWidgets +from PyQt5.QtCore import QSettings + from flatcamGUI.preferences.gerber.GerberEditorPrefGroupUI import GerberEditorPrefGroupUI from flatcamGUI.preferences.gerber.GerberExpPrefGroupUI import GerberExpPrefGroupUI from flatcamGUI.preferences.gerber.GerberAdvOptPrefGroupUI import GerberAdvOptPrefGroupUI @@ -9,30 +10,44 @@ from flatcamGUI.preferences.gerber.GerberGenPrefGroupUI import GerberGenPrefGrou import gettext import FlatCAMTranslation as fcTranslate import builtins + fcTranslate.apply_language('strings') if '_' not in builtins.__dict__: _ = gettext.gettext +settings = QSettings("Open Source", "FlatCAM") +if settings.contains("machinist"): + machinist_setting = settings.value('machinist', type=int) +else: + machinist_setting = 0 -class GerberPreferencesUI(PreferencesSectionUI): - def __init__(self, decimals, **kwargs): +class GerberPreferencesUI(QtWidgets.QWidget): + + def __init__(self, decimals, parent=None): + QtWidgets.QWidget.__init__(self, parent=parent) + self.layout = QtWidgets.QHBoxLayout() + self.setLayout(self.layout) self.decimals = decimals - super().__init__(**kwargs) - def build_groups(self) -> [OptionsGroupUI]: - return [ - GerberGenPrefGroupUI(decimals=self.decimals), + self.gerber_gen_group = GerberGenPrefGroupUI(decimals=self.decimals) + self.gerber_gen_group.setMinimumWidth(250) + self.gerber_opt_group = GerberOptPrefGroupUI(decimals=self.decimals) + self.gerber_opt_group.setMinimumWidth(250) + self.gerber_exp_group = GerberExpPrefGroupUI(decimals=self.decimals) + self.gerber_exp_group.setMinimumWidth(230) + self.gerber_adv_opt_group = GerberAdvOptPrefGroupUI(decimals=self.decimals) + self.gerber_adv_opt_group.setMinimumWidth(200) + self.gerber_editor_group = GerberEditorPrefGroupUI(decimals=self.decimals) + self.gerber_editor_group.setMinimumWidth(200) - GerberOptPrefGroupUI(decimals=self.decimals), # FIXME vertical layout with opt and exp - GerberExpPrefGroupUI(decimals=self.decimals), + self.vlay = QtWidgets.QVBoxLayout() + self.vlay.addWidget(self.gerber_opt_group) + self.vlay.addWidget(self.gerber_exp_group) - GerberAdvOptPrefGroupUI(decimals=self.decimals), - GerberEditorPrefGroupUI(decimals=self.decimals) - ] + self.layout.addWidget(self.gerber_gen_group) + self.layout.addLayout(self.vlay) + self.layout.addWidget(self.gerber_adv_opt_group) + self.layout.addWidget(self.gerber_editor_group) - def get_tab_id(self): - return "gerber_tab" - - def get_tab_label(self): - return _("GERBER") + self.layout.addStretch() diff --git a/flatcamGUI/preferences/tools/Tools2PreferencesUI.py b/flatcamGUI/preferences/tools/Tools2PreferencesUI.py index 168940a0..01ed4def 100644 --- a/flatcamGUI/preferences/tools/Tools2PreferencesUI.py +++ b/flatcamGUI/preferences/tools/Tools2PreferencesUI.py @@ -1,5 +1,6 @@ -from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI -from flatcamGUI.preferences.PreferencesSectionUI import PreferencesSectionUI +from PyQt5 import QtWidgets +from PyQt5.QtCore import QSettings + from flatcamGUI.preferences.tools.Tools2InvertPrefGroupUI import Tools2InvertPrefGroupUI from flatcamGUI.preferences.tools.Tools2PunchGerberPrefGroupUI import Tools2PunchGerberPrefGroupUI from flatcamGUI.preferences.tools.Tools2EDrillsPrefGroupUI import Tools2EDrillsPrefGroupUI @@ -10,46 +11,79 @@ from flatcamGUI.preferences.tools.Tools2QRCodePrefGroupUI import Tools2QRCodePre from flatcamGUI.preferences.tools.Tools2OptimalPrefGroupUI import Tools2OptimalPrefGroupUI from flatcamGUI.preferences.tools.Tools2RulesCheckPrefGroupUI import Tools2RulesCheckPrefGroupUI +import gettext +import FlatCAMTranslation as fcTranslate +import builtins -class Tools2PreferencesUI(PreferencesSectionUI): +fcTranslate.apply_language('strings') +if '_' not in builtins.__dict__: + _ = gettext.gettext - def __init__(self, decimals, **kwargs): +settings = QSettings("Open Source", "FlatCAM") +if settings.contains("machinist"): + machinist_setting = settings.value('machinist', type=int) +else: + machinist_setting = 0 + + +class Tools2PreferencesUI(QtWidgets.QWidget): + + def __init__(self, decimals, parent=None): + QtWidgets.QWidget.__init__(self, parent=parent) + self.layout = QtWidgets.QHBoxLayout() + self.setLayout(self.layout) self.decimals = decimals + self.tools2_checkrules_group = Tools2RulesCheckPrefGroupUI(decimals=self.decimals) + self.tools2_checkrules_group.setMinimumWidth(220) + self.tools2_optimal_group = Tools2OptimalPrefGroupUI(decimals=self.decimals) + self.tools2_optimal_group.setMinimumWidth(220) + self.tools2_qrcode_group = Tools2QRCodePrefGroupUI(decimals=self.decimals) + self.tools2_qrcode_group.setMinimumWidth(220) + self.tools2_cfill_group = Tools2CThievingPrefGroupUI(decimals=self.decimals) + self.tools2_cfill_group.setMinimumWidth(220) + self.tools2_fiducials_group = Tools2FiducialsPrefGroupUI(decimals=self.decimals) + self.tools2_fiducials_group.setMinimumWidth(220) + self.tools2_cal_group = Tools2CalPrefGroupUI(decimals=self.decimals) + self.tools2_cal_group.setMinimumWidth(220) + self.tools2_edrills_group = Tools2EDrillsPrefGroupUI(decimals=self.decimals) + self.tools2_edrills_group.setMinimumWidth(220) + self.tools2_punch_group = Tools2PunchGerberPrefGroupUI(decimals=self.decimals) + self.tools2_punch_group.setMinimumWidth(220) + self.tools2_invert_group = Tools2InvertPrefGroupUI(decimals=self.decimals) - super().__init__(**kwargs) + self.tools2_invert_group.setMinimumWidth(220) - def build_groups(self) -> [OptionsGroupUI]: - return [ - # fixme column 1 - self.tools2_checkrules_group, - self.tools2_optimal_group, + self.vlay = QtWidgets.QVBoxLayout() + self.vlay.addWidget(self.tools2_checkrules_group) + self.vlay.addWidget(self.tools2_optimal_group) - # fixme column 2 - self.tools2_qrcode_group, - self.tools2_fiducials_group, + self.vlay1 = QtWidgets.QVBoxLayout() + self.vlay1.addWidget(self.tools2_qrcode_group) + self.vlay1.addWidget(self.tools2_fiducials_group) - # fixme column 3 - self.tools2_cfill_group, + self.vlay2 = QtWidgets.QVBoxLayout() + self.vlay2.addWidget(self.tools2_cfill_group) - # fixme column 4 - self.tools2_cal_group, - self.tools2_edrills_group, + self.vlay3 = QtWidgets.QVBoxLayout() + self.vlay3.addWidget(self.tools2_cal_group) + self.vlay3.addWidget(self.tools2_edrills_group) - # fixme column 5 - self.tools2_punch_group, - self.tools2_invert_group, - ] + self.vlay4 = QtWidgets.QVBoxLayout() + self.vlay4.addWidget(self.tools2_punch_group) + self.vlay4.addWidget(self.tools2_invert_group) - def get_tab_id(self): - return "tools2_tab" + self.layout.addLayout(self.vlay) + self.layout.addLayout(self.vlay1) + self.layout.addLayout(self.vlay2) + self.layout.addLayout(self.vlay3) + self.layout.addLayout(self.vlay4) - def get_tab_label(self): - return _("TOOLS 2") \ No newline at end of file + self.layout.addStretch() diff --git a/flatcamGUI/preferences/tools/ToolsPreferencesUI.py b/flatcamGUI/preferences/tools/ToolsPreferencesUI.py index 0c4ffd70..dc3061a8 100644 --- a/flatcamGUI/preferences/tools/ToolsPreferencesUI.py +++ b/flatcamGUI/preferences/tools/ToolsPreferencesUI.py @@ -1,5 +1,6 @@ -from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI -from flatcamGUI.preferences.PreferencesSectionUI import PreferencesSectionUI +from PyQt5 import QtWidgets +from PyQt5.QtCore import QSettings + from flatcamGUI.preferences.tools.ToolsSubPrefGroupUI import ToolsSubPrefGroupUI from flatcamGUI.preferences.tools.ToolsSolderpastePrefGroupUI import ToolsSolderpastePrefGroupUI from flatcamGUI.preferences.tools.ToolsTransformPrefGroupUI import ToolsTransformPrefGroupUI @@ -11,48 +12,83 @@ from flatcamGUI.preferences.tools.Tools2sidedPrefGroupUI import Tools2sidedPrefG from flatcamGUI.preferences.tools.ToolsCutoutPrefGroupUI import ToolsCutoutPrefGroupUI from flatcamGUI.preferences.tools.ToolsNCCPrefGroupUI import ToolsNCCPrefGroupUI +import gettext +import FlatCAMTranslation as fcTranslate +import builtins -class ToolsPreferencesUI(PreferencesSectionUI): +fcTranslate.apply_language('strings') +if '_' not in builtins.__dict__: + _ = gettext.gettext - def __init__(self, decimals, **kwargs): +settings = QSettings("Open Source", "FlatCAM") +if settings.contains("machinist"): + machinist_setting = settings.value('machinist', type=int) +else: + machinist_setting = 0 + + +class ToolsPreferencesUI(QtWidgets.QWidget): + + def __init__(self, decimals, parent=None): + QtWidgets.QWidget.__init__(self, parent=parent) + self.layout = QtWidgets.QHBoxLayout() + self.setLayout(self.layout) self.decimals = decimals + self.tools_ncc_group = ToolsNCCPrefGroupUI(decimals=self.decimals) + self.tools_ncc_group.setMinimumWidth(220) + self.tools_paint_group = ToolsPaintPrefGroupUI(decimals=self.decimals) + self.tools_paint_group.setMinimumWidth(220) + self.tools_cutout_group = ToolsCutoutPrefGroupUI(decimals=self.decimals) + self.tools_cutout_group.setMinimumWidth(220) + self.tools_2sided_group = Tools2sidedPrefGroupUI(decimals=self.decimals) + self.tools_2sided_group.setMinimumWidth(220) + self.tools_film_group = ToolsFilmPrefGroupUI(decimals=self.decimals) + self.tools_film_group.setMinimumWidth(220) + self.tools_panelize_group = ToolsPanelizePrefGroupUI(decimals=self.decimals) + self.tools_panelize_group.setMinimumWidth(220) + self.tools_calculators_group = ToolsCalculatorsPrefGroupUI(decimals=self.decimals) + self.tools_calculators_group.setMinimumWidth(220) + self.tools_transform_group = ToolsTransformPrefGroupUI(decimals=self.decimals) + self.tools_transform_group.setMinimumWidth(200) + self.tools_solderpaste_group = ToolsSolderpastePrefGroupUI(decimals=self.decimals) + self.tools_solderpaste_group.setMinimumWidth(200) + self.tools_sub_group = ToolsSubPrefGroupUI(decimals=self.decimals) - super().__init__(**kwargs) + self.tools_sub_group.setMinimumWidth(200) - def build_groups(self) -> [OptionsGroupUI]: - return [ - # fixme column 1 - self.tools_ncc_group, - self.tools_cutout_group, + self.vlay = QtWidgets.QVBoxLayout() + self.vlay.addWidget(self.tools_ncc_group) + self.vlay.addWidget(self.tools_cutout_group) - # fixme column 2 - self.tools_paint_group, - self.tools_panelize_group, + self.vlay1 = QtWidgets.QVBoxLayout() + self.vlay1.addWidget(self.tools_paint_group) + self.vlay1.addWidget(self.tools_panelize_group) - # fixme column 3 - self.tools_transform_group, - self.tools_2sided_group, - self.tools_sub_group, + self.vlay2 = QtWidgets.QVBoxLayout() + self.vlay2.addWidget(self.tools_transform_group) + self.vlay2.addWidget(self.tools_2sided_group) + self.vlay2.addWidget(self.tools_sub_group) - # fixme column 4 - self.tools_film_group, - self.tools_calculators_group, + self.vlay3 = QtWidgets.QVBoxLayout() + self.vlay3.addWidget(self.tools_film_group) + self.vlay3.addWidget(self.tools_calculators_group) - # fixme column 5 - self.tools_solderpaste_group, - ] + self.vlay4 = QtWidgets.QVBoxLayout() + self.vlay4.addWidget(self.tools_solderpaste_group) - def get_tab_id(self): - return "tools_tab" + self.layout.addLayout(self.vlay) + self.layout.addLayout(self.vlay1) + self.layout.addLayout(self.vlay2) + self.layout.addLayout(self.vlay3) + self.layout.addLayout(self.vlay4) - def get_tab_label(self): - return _("TOOLS") + self.layout.addStretch() diff --git a/flatcamGUI/preferences/utilities/UtilPreferencesUI.py b/flatcamGUI/preferences/utilities/UtilPreferencesUI.py index 9e2f40b1..ae9e2110 100644 --- a/flatcamGUI/preferences/utilities/UtilPreferencesUI.py +++ b/flatcamGUI/preferences/utilities/UtilPreferencesUI.py @@ -1,31 +1,37 @@ -from flatcamGUI.preferences.OptionsGroupUI import OptionsGroupUI -from flatcamGUI.preferences.PreferencesSectionUI import PreferencesSectionUI +from PyQt5 import QtWidgets + from flatcamGUI.preferences.utilities.AutoCompletePrefGroupUI import AutoCompletePrefGroupUI from flatcamGUI.preferences.utilities.FAGrbPrefGroupUI import FAGrbPrefGroupUI from flatcamGUI.preferences.utilities.FAGcoPrefGroupUI import FAGcoPrefGroupUI from flatcamGUI.preferences.utilities.FAExcPrefGroupUI import FAExcPrefGroupUI -class UtilPreferencesUI(PreferencesSectionUI): +class UtilPreferencesUI(QtWidgets.QWidget): - def __init__(self, decimals, **kwargs): + def __init__(self, decimals, parent=None): + QtWidgets.QWidget.__init__(self, parent=parent) + self.layout = QtWidgets.QHBoxLayout() + self.setLayout(self.layout) self.decimals = decimals + + self.vlay = QtWidgets.QVBoxLayout() self.fa_excellon_group = FAExcPrefGroupUI(decimals=self.decimals) + self.fa_excellon_group.setMinimumWidth(260) + self.fa_gcode_group = FAGcoPrefGroupUI(decimals=self.decimals) + self.fa_gcode_group.setMinimumWidth(260) + + self.vlay.addWidget(self.fa_excellon_group) + self.vlay.addWidget(self.fa_gcode_group) + self.fa_gerber_group = FAGrbPrefGroupUI(decimals=self.decimals) + self.fa_gerber_group.setMinimumWidth(260) + self.kw_group = AutoCompletePrefGroupUI(decimals=self.decimals) - super().__init__(**kwargs) + self.kw_group.setMinimumWidth(260) - def build_groups(self) -> [OptionsGroupUI]: - return [ - self.fa_excellon_group, # fixme column with fa_excellon and fa_gcode - self.fa_gcode_group, - self.fa_gerber_group, - self.kw_group, - ] + self.layout.addLayout(self.vlay) + self.layout.addWidget(self.fa_gerber_group) + self.layout.addWidget(self.kw_group) - def get_tab_id(self): - return "fa_tab" - - def get_tab_label(self): - return _("UTILITIES") \ No newline at end of file + self.layout.addStretch() diff --git a/flatcamTools/ToolCopperThieving.py b/flatcamTools/ToolCopperThieving.py index f6c85731..d6fd310a 100644 --- a/flatcamTools/ToolCopperThieving.py +++ b/flatcamTools/ToolCopperThieving.py @@ -910,22 +910,16 @@ class ToolCopperThieving(FlatCAMTool): edge_width=self.app.defaults["global_cursor_width"], size=self.app.defaults["global_cursor_size"]) + # update the positions on status bar + self.app.ui.position_label.setText("    X: %.4f   " + "Y: %.4f" % (curr_pos[0], curr_pos[1])) if self.cursor_pos is None: self.cursor_pos = (0, 0) self.app.dx = curr_pos[0] - float(self.cursor_pos[0]) self.app.dy = curr_pos[1] - float(self.cursor_pos[1]) - - # # update the positions on status bar - # self.app.ui.position_label.setText("    X: %.4f   " - # "Y: %.4f" % (curr_pos[0], curr_pos[1])) - # self.app.ui.rel_position_label.setText("Dx: %.4f   Dy: " - # "%.4f    " % (self.app.dx, self.app.dy)) - - units = self.app.defaults["units"].lower() - self.plotcanvas.text_hud.text = \ - 'Dx:\t{:<.4f} [{:s}]\nDy:\t{:<.4f} [{:s}]\nX: \t{:<.4f} [{:s}]\nY: \t{:<.4f} [{:s}]'.format( - self.app.dx, units, self.app.dy, units, curr_pos[0], units, curr_pos[1], units) + self.app.ui.rel_position_label.setText("Dx: %.4f   Dy: " + "%.4f    " % (self.app.dx, self.app.dy)) # draw the utility geometry if self.first_click: diff --git a/flatcamTools/ToolDistance.py b/flatcamTools/ToolDistance.py index bcc506fb..ea62c64e 100644 --- a/flatcamTools/ToolDistance.py +++ b/flatcamTools/ToolDistance.py @@ -544,16 +544,11 @@ class Distance(FlatCAMTool): else: pos = (pos_canvas[0], pos_canvas[1]) - # self.app.ui.position_label.setText( - # "    X: {}   Y: {}".format( - # '%.*f' % (self.decimals, pos[0]), '%.*f' % (self.decimals, pos[1]) - # ) - # ) - - units = self.app.defaults["units"].lower() - self.plotcanvas.text_hud.text = \ - 'Dx:\t{:<.4f} [{:s}]\nDy:\t{:<.4f} [{:s}]\nX: \t{:<.4f} [{:s}]\nY: \t{:<.4f} [{:s}]'.format( - 0.0000, units, 0.0000, units, pos[0], units, pos[1], units) + self.app.ui.position_label.setText( + "    X: {}   Y: {}".format( + '%.*f' % (self.decimals, pos[0]), '%.*f' % (self.decimals, pos[1]) + ) + ) if self.rel_point1 is not None: dx = pos[0] - float(self.rel_point1[0]) diff --git a/flatcamTools/ToolNCC.py b/flatcamTools/ToolNCC.py index d01f02de..0b80c735 100644 --- a/flatcamTools/ToolNCC.py +++ b/flatcamTools/ToolNCC.py @@ -1825,22 +1825,16 @@ class NonCopperClear(FlatCAMTool, Gerber): edge_width=self.app.defaults["global_cursor_width"], size=self.app.defaults["global_cursor_size"]) + # update the positions on status bar + self.app.ui.position_label.setText("    X: %.4f   " + "Y: %.4f" % (curr_pos[0], curr_pos[1])) if self.cursor_pos is None: self.cursor_pos = (0, 0) self.app.dx = curr_pos[0] - float(self.cursor_pos[0]) self.app.dy = curr_pos[1] - float(self.cursor_pos[1]) - - # # update the positions on status bar - # self.app.ui.position_label.setText("    X: %.4f   " - # "Y: %.4f" % (curr_pos[0], curr_pos[1])) - # self.app.ui.rel_position_label.setText("Dx: %.4f   Dy: " - # "%.4f    " % (self.app.dx, self.app.dy)) - - units = self.app.defaults["units"].lower() - self.plotcanvas.text_hud.text = \ - 'Dx:\t{:<.4f} [{:s}]\nDy:\t{:<.4f} [{:s}]\nX: \t{:<.4f} [{:s}]\nY: \t{:<.4f} [{:s}]'.format( - self.app.dx, units, self.app.dy, units, curr_pos[0], units, curr_pos[1], units) + self.app.ui.rel_position_label.setText("Dx: %.4f   Dy: " + "%.4f    " % (self.app.dx, self.app.dy)) # draw the utility geometry if shape_type == "square": diff --git a/flatcamTools/ToolPaint.py b/flatcamTools/ToolPaint.py index ae1b23cc..4dda2d36 100644 --- a/flatcamTools/ToolPaint.py +++ b/flatcamTools/ToolPaint.py @@ -1724,22 +1724,16 @@ class ToolPaint(FlatCAMTool, Gerber): edge_width=self.app.defaults["global_cursor_width"], size=self.app.defaults["global_cursor_size"]) + # update the positions on status bar + self.app.ui.position_label.setText("    X: %.4f   " + "Y: %.4f" % (curr_pos[0], curr_pos[1])) if self.cursor_pos is None: self.cursor_pos = (0, 0) self.app.dx = curr_pos[0] - float(self.cursor_pos[0]) self.app.dy = curr_pos[1] - float(self.cursor_pos[1]) - - # # update the positions on status bar - # self.app.ui.position_label.setText("    X: %.4f   " - # "Y: %.4f" % (curr_pos[0], curr_pos[1])) - # self.app.ui.rel_position_label.setText("Dx: %.4f   Dy: " - # "%.4f    " % (self.app.dx, self.app.dy)) - - units = self.app.defaults["units"].lower() - self.plotcanvas.text_hud.text = \ - 'Dx:\t{:<.4f} [{:s}]\nDy:\t{:<.4f} [{:s}]\nX: \t{:<.4f} [{:s}]\nY: \t{:<.4f} [{:s}]'.format( - self.app.dx, units, self.app.dy, units, curr_pos[0], units, curr_pos[1], units) + self.app.ui.rel_position_label.setText("Dx: %.4f   Dy: " + "%.4f    " % (self.app.dx, self.app.dy)) # draw the utility geometry if shape_type == "square":