diff --git a/CHANGELOG.md b/CHANGELOG.md index cc6bf9ef..e66676eb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,6 +23,7 @@ CHANGELOG for FlatCAM beta - trimmed the application strings - updated the Italian translation (by Massimiliano Golfetto) - fixed a series of issues in Gerber Editor tools when the user is trying to use the tools by preselecting a aperture without size (aperture macro) +- moved all the UI stuff out of the Gerber Editor class in its own class 2.11.2020 diff --git a/appEditors/AppGerberEditor.py b/appEditors/AppGerberEditor.py index 0127ad12..ee6bd3f0 100644 --- a/appEditors/AppGerberEditor.py +++ b/appEditors/AppGerberEditor.py @@ -392,7 +392,7 @@ class FCPad(FCShapeTool): def clean_up(self): self.draw_app.selected = [] - self.draw_app.apertures_table.clearSelection() + self.draw_app.ui.apertures_table.clearSelection() self.draw_app.plot_all() try: self.draw_app.app.jump_signal.disconnect() @@ -419,7 +419,7 @@ class FCPadArray(FCShapeTool): self.complete = True self.dont_execute = True self.draw_app.in_action = False - self.draw_app.array_frame.hide() + self.draw_app.ui.array_frame.hide() self.draw_app.select_tool('select') return @@ -451,7 +451,7 @@ class FCPadArray(FCShapeTool): except KeyError: pass - self.draw_app.array_frame.show() + self.draw_app.ui.array_frame.show() self.selected_size = None self.pad_axis = 'X' @@ -512,15 +512,15 @@ class FCPadArray(FCShapeTool): self.draw_app.select_tool('select') return - self.pad_axis = self.draw_app.pad_axis_radio.get_value() - self.pad_direction = self.draw_app.pad_direction_radio.get_value() - self.pad_array = self.draw_app.array_type_combo.get_value() + self.pad_axis = self.draw_app.ui.pad_axis_radio.get_value() + self.pad_direction = self.draw_app.ui.pad_direction_radio.get_value() + self.pad_array = self.draw_app.ui.array_type_combo.get_value() try: - self.pad_array_size = int(self.draw_app.pad_array_size_entry.get_value()) + self.pad_array_size = int(self.draw_app.ui.pad_array_size_entry.get_value()) try: - self.pad_pitch = float(self.draw_app.pad_pitch_entry.get_value()) - self.pad_linear_angle = float(self.draw_app.linear_angle_spinner.get_value()) - self.pad_angle = float(self.draw_app.pad_angle_entry.get_value()) + self.pad_pitch = float(self.draw_app.ui.pad_pitch_entry.get_value()) + self.pad_linear_angle = float(self.draw_app.ui.linear_angle_spinner.get_value()) + self.pad_angle = float(self.draw_app.ui.pad_angle_entry.get_value()) except TypeError: self.draw_app.app.inform.emit('[ERROR_NOTCL] %s' % _("The value is not Float. Check for comma instead of dot separator.")) @@ -741,12 +741,12 @@ class FCPadArray(FCShapeTool): self.complete = True self.draw_app.app.inform.emit('[success] %s' % _("Done.")) self.draw_app.in_action = False - self.draw_app.array_frame.hide() + self.draw_app.ui.array_frame.hide() self.draw_app.app.jump_signal.disconnect() def clean_up(self): self.draw_app.selected = [] - self.draw_app.apertures_table.clearSelection() + self.draw_app.ui.apertures_table.clearSelection() self.draw_app.plot_all() try: self.draw_app.app.jump_signal.disconnect() @@ -860,7 +860,7 @@ class FCPoligonize(FCShapeTool): def clean_up(self): self.draw_app.selected = [] - self.draw_app.apertures_table.clearSelection() + self.draw_app.ui.apertures_table.clearSelection() self.draw_app.plot_all() @@ -1172,7 +1172,7 @@ class FCRegion(FCShapeTool): def clean_up(self): self.draw_app.selected = [] - self.draw_app.apertures_table.clearSelection() + self.draw_app.ui.apertures_table.clearSelection() self.draw_app.plot_all() try: self.draw_app.app.jump_signal.disconnect() @@ -1445,7 +1445,7 @@ class FCTrack(FCShapeTool): def clean_up(self): self.draw_app.selected = [] - self.draw_app.apertures_table.clearSelection() + self.draw_app.ui.apertures_table.clearSelection() self.draw_app.plot_all() try: self.draw_app.app.jump_signal.disconnect() @@ -1558,7 +1558,7 @@ class FCDisc(FCShapeTool): def clean_up(self): self.draw_app.selected = [] - self.draw_app.apertures_table.clearSelection() + self.draw_app.ui.apertures_table.clearSelection() self.draw_app.plot_all() try: self.draw_app.app.jump_signal.disconnect() @@ -1613,10 +1613,11 @@ class FCSemiDisc(FCShapeTool): if '0' in self.draw_app.storage_dict: self.storage_obj = self.draw_app.storage_dict['0']['geometry'] else: - self.draw_app.storage_dict['0'] = {} - self.draw_app.storage_dict['0']['type'] = 'C' - self.draw_app.storage_dict['0']['size'] = 0.0 - self.draw_app.storage_dict['0']['geometry'] = [] + self.draw_app.storage_dict['0'] = { + 'type': 'C', + 'size': 0.0, + 'geometry': [] + } self.storage_obj = self.draw_app.storage_dict['0']['geometry'] self.steps_per_circ = self.draw_app.app.defaults["gerber_circle_steps"] @@ -1846,7 +1847,7 @@ class FCSemiDisc(FCShapeTool): def clean_up(self): self.draw_app.selected = [] - self.draw_app.apertures_table.clearSelection() + self.draw_app.ui.apertures_table.clearSelection() self.draw_app.plot_all() try: self.draw_app.app.jump_signal.disconnect() @@ -1872,16 +1873,16 @@ class FCScale(FCShapeTool): def activate_scale(self): self.draw_app.hide_tool('all') - self.draw_app.scale_tool_frame.show() + self.draw_app.ui.scale_tool_frame.show() try: - self.draw_app.scale_button.clicked.disconnect() + self.draw_app.ui.scale_button.clicked.disconnect() except (TypeError, AttributeError): pass - self.draw_app.scale_button.clicked.connect(self.on_scale_click) + self.draw_app.ui.scale_button.clicked.connect(self.on_scale_click) def deactivate_scale(self): - self.draw_app.scale_button.clicked.disconnect() + self.draw_app.ui.scale_button.clicked.disconnect() self.complete = True self.draw_app.select_tool("select") self.draw_app.hide_tool(self.name) @@ -1892,7 +1893,7 @@ class FCScale(FCShapeTool): def clean_up(self): self.draw_app.selected = [] - self.draw_app.apertures_table.clearSelection() + self.draw_app.ui.apertures_table.clearSelection() self.draw_app.plot_all() @@ -1914,16 +1915,16 @@ class FCBuffer(FCShapeTool): def activate_buffer(self): self.draw_app.hide_tool('all') - self.draw_app.buffer_tool_frame.show() + self.draw_app.ui.buffer_tool_frame.show() try: - self.draw_app.buffer_button.clicked.disconnect() + self.draw_app.ui.buffer_button.clicked.disconnect() except (TypeError, AttributeError): pass - self.draw_app.buffer_button.clicked.connect(self.on_buffer_click) + self.draw_app.ui.buffer_button.clicked.connect(self.on_buffer_click) def deactivate_buffer(self): - self.draw_app.buffer_button.clicked.disconnect() + self.draw_app.ui.buffer_button.clicked.disconnect() self.complete = True self.draw_app.select_tool("select") self.draw_app.hide_tool(self.name) @@ -1934,7 +1935,7 @@ class FCBuffer(FCShapeTool): def clean_up(self): self.draw_app.selected = [] - self.draw_app.apertures_table.clearSelection() + self.draw_app.ui.apertures_table.clearSelection() self.draw_app.plot_all() @@ -1955,31 +1956,31 @@ class FCMarkArea(FCShapeTool): self.activate_markarea() def activate_markarea(self): - self.draw_app.ma_tool_frame.show() + self.draw_app.ui.ma_tool_frame.show() # clear previous marking - self.draw_app.ma_annotation.clear(update=True) + self.draw_app.ui.ma_annotation.clear(update=True) try: - self.draw_app.ma_threshold_button.clicked.disconnect() + self.draw_app.ui.ma_threshold_button.clicked.disconnect() except (TypeError, AttributeError): pass - self.draw_app.ma_threshold_button.clicked.connect(self.on_markarea_click) + self.draw_app.ui.ma_threshold_button.clicked.connect(self.on_markarea_click) try: - self.draw_app.ma_delete_button.clicked.disconnect() + self.draw_app.ui.ma_delete_button.clicked.disconnect() except TypeError: pass - self.draw_app.ma_delete_button.clicked.connect(self.on_markarea_delete) + self.draw_app.ui.ma_delete_button.clicked.connect(self.on_markarea_delete) try: - self.draw_app.ma_clear_button.clicked.disconnect() + self.draw_app.ui.ma_clear_button.clicked.disconnect() except TypeError: pass - self.draw_app.ma_clear_button.clicked.connect(self.on_markarea_clear) + self.draw_app.ui.ma_clear_button.clicked.connect(self.on_markarea_clear) def deactivate_markarea(self): - self.draw_app.ma_threshold_button.clicked.disconnect() + self.draw_app.ui.ma_threshold_button.clicked.disconnect() self.complete = True self.draw_app.select_tool("select") self.draw_app.hide_tool(self.name) @@ -1997,7 +1998,7 @@ class FCMarkArea(FCShapeTool): def clean_up(self): self.draw_app.selected = [] - self.draw_app.apertures_table.clearSelection() + self.draw_app.ui.apertures_table.clearSelection() self.draw_app.plot_all() @@ -2027,10 +2028,10 @@ class FCApertureMove(FCShapeTool): self.current_storage = None self.geometry = [] - for index in self.draw_app.apertures_table.selectedIndexes(): + for index in self.draw_app.ui.apertures_table.selectedIndexes(): row = index.row() # on column 1 in tool tables we hold the aperture codes, and we retrieve them as strings - aperture_on_row = self.draw_app.apertures_table.item(row, 1).text() + aperture_on_row = self.draw_app.ui.apertures_table.item(row, 1).text() self.selected_apertures.append(aperture_on_row) # Switch notebook to Properties page @@ -2143,7 +2144,7 @@ class FCApertureMove(FCShapeTool): def clean_up(self): self.draw_app.selected = [] - self.draw_app.apertures_table.clearSelection() + self.draw_app.ui.apertures_table.clearSelection() self.draw_app.plot_all() try: @@ -2242,10 +2243,10 @@ class FCEraser(FCShapeTool): self.current_storage = None self.geometry = [] - for index in self.draw_app.apertures_table.selectedIndexes(): + for index in self.draw_app.ui.apertures_table.selectedIndexes(): row = index.row() # on column 1 in tool tables we hold the aperture codes, and we retrieve them as strings - aperture_on_row = self.draw_app.apertures_table.item(row, 1).text() + aperture_on_row = self.draw_app.ui.apertures_table.item(row, 1).text() self.selected_apertures.append(aperture_on_row) # Switch notebook to Properties page @@ -2260,7 +2261,7 @@ class FCEraser(FCShapeTool): def click(self, point): if len(self.draw_app.get_selected()) == 0: - self.draw_app.apertures_table.clearSelection() + self.draw_app.ui.apertures_table.clearSelection() sel_aperture = set() for storage in self.draw_app.storage_dict: @@ -2277,19 +2278,19 @@ class FCEraser(FCShapeTool): # select the aperture in the Apertures Table that is associated with the selected shape try: - self.draw_app.apertures_table.cellPressed.disconnect() + self.draw_app.ui.apertures_table.cellPressed.disconnect() except Exception as e: log.debug("AppGerberEditor.FCEraser.click_release() --> %s" % str(e)) - self.draw_app.apertures_table.setSelectionMode(QtWidgets.QAbstractItemView.MultiSelection) + self.draw_app.ui.apertures_table.setSelectionMode(QtWidgets.QAbstractItemView.MultiSelection) for aper in sel_aperture: - for row in range(self.draw_app.apertures_table.rowCount()): - if str(aper) == self.draw_app.apertures_table.item(row, 1).text(): - self.draw_app.apertures_table.selectRow(row) + for row in range(self.draw_app.ui.apertures_table.rowCount()): + if str(aper) == self.draw_app.ui.apertures_table.item(row, 1).text(): + self.draw_app.ui.apertures_table.selectRow(row) self.draw_app.last_aperture_selected = aper - self.draw_app.apertures_table.setSelectionMode(QtWidgets.QAbstractItemView.ExtendedSelection) + self.draw_app.ui.apertures_table.setSelectionMode(QtWidgets.QAbstractItemView.ExtendedSelection) - self.draw_app.apertures_table.cellPressed.connect(self.draw_app.on_row_selected) + self.draw_app.ui.apertures_table.cellPressed.connect(self.draw_app.on_row_selected) if len(self.draw_app.get_selected()) == 0: return "Nothing to ersase." @@ -2334,7 +2335,7 @@ class FCEraser(FCShapeTool): def clean_up(self): self.draw_app.selected = [] - self.draw_app.apertures_table.clearSelection() + self.draw_app.ui.apertures_table.clearSelection() self.draw_app.plot_all() try: self.draw_app.app.jump_signal.disconnect() @@ -2372,33 +2373,33 @@ class FCEraser(FCShapeTool): class FCApertureSelect(DrawTool): - def __init__(self, grb_editor_app): - DrawTool.__init__(self, grb_editor_app) + def __init__(self, draw_app): + DrawTool.__init__(self, draw_app) self.name = 'select' self.origin = None - self.grb_editor_app = grb_editor_app - self.storage = self.grb_editor_app.storage_dict - # self.selected = self.grb_editor_app.selected + self.draw_app = draw_app + self.storage = self.draw_app.storage_dict + # self.selected = self.draw_app.selected # here we store all shapes that were selected self.sel_storage = [] # since FCApertureSelect tool is activated whenever a tool is exited I place here the reinitialization of the # bending modes using in FCRegion and FCTrack - self.grb_editor_app.bend_mode = 1 + self.draw_app.bend_mode = 1 # here store the selected apertures self.sel_aperture = [] try: - self.grb_editor_app.apertures_table.clearSelection() + self.draw_app.ui.apertures_table.clearSelection() except Exception as e: log.error("FlatCAMGerbEditor.FCApertureSelect.__init__() --> %s" % str(e)) - self.grb_editor_app.hide_tool('all') - self.grb_editor_app.hide_tool('select') - self.grb_editor_app.array_frame.hide() + self.draw_app.hide_tool('all') + self.draw_app.hide_tool('select') + self.draw_app.ui.array_frame.hide() try: QtGui.QGuiApplication.restoreOverrideCursor() @@ -2406,16 +2407,16 @@ class FCApertureSelect(DrawTool): log.debug("AppGerberEditor.FCApertureSelect --> %s" % str(e)) try: - self.grb_editor_app.selection_triggered.disconnect() + self.draw_app.selection_triggered.disconnect() except (TypeError, AttributeError): pass - self.grb_editor_app.selection_triggered.connect(self.selection_worker) + self.draw_app.selection_triggered.connect(self.selection_worker) try: - self.grb_editor_app.plot_object.disconnect() + self.draw_app.plot_object.disconnect() except (TypeError, AttributeError): pass - self.grb_editor_app.plot_object.connect(self.clean_up) + self.draw_app.plot_object.connect(self.clean_up) def set_origin(self, origin): self.origin = origin @@ -2430,13 +2431,13 @@ class FCApertureSelect(DrawTool): else: mod_key = None - if mod_key == self.grb_editor_app.app.defaults["global_mselect_key"]: + if mod_key == self.draw_app.app.defaults["global_mselect_key"]: pass else: - self.grb_editor_app.selected = [] + self.draw_app.selected = [] def click_release(self, point): - self.grb_editor_app.apertures_table.clearSelection() + self.draw_app.ui.apertures_table.clearSelection() key_modifier = QtWidgets.QApplication.keyboardModifiers() if key_modifier == QtCore.Qt.ShiftModifier: @@ -2446,11 +2447,11 @@ class FCApertureSelect(DrawTool): else: mod_key = None - if mod_key != self.grb_editor_app.app.defaults["global_mselect_key"]: - self.grb_editor_app.selected.clear() + if mod_key != self.draw_app.app.defaults["global_mselect_key"]: + self.draw_app.selected.clear() self.sel_aperture.clear() - self.grb_editor_app.selection_triggered.emit(point) + self.draw_app.selection_triggered.emit(point) def selection_worker(self, point): def job_thread(editor_obj): @@ -2471,15 +2472,15 @@ class FCApertureSelect(DrawTool): if brake_flag is True: break - # ############################################################################################################# + # ###################################################################################################### # select the aperture in the Apertures Table that is associated with the selected shape - # ############################################################################################################# + # ###################################################################################################### self.sel_aperture.clear() - editor_obj.apertures_table.clearSelection() + editor_obj.ui.apertures_table.clearSelection() # disconnect signal when clicking in the table try: - editor_obj.apertures_table.cellPressed.disconnect() + editor_obj.ui.apertures_table.cellPressed.disconnect() except Exception as e: log.debug("AppGerberEditor.FCApertureSelect.click_release() --> %s" % str(e)) @@ -2495,21 +2496,21 @@ class FCApertureSelect(DrawTool): # actual row selection is done here for aper in self.sel_aperture: - for row in range(editor_obj.apertures_table.rowCount()): - if str(aper) == editor_obj.apertures_table.item(row, 1).text(): - if not editor_obj.apertures_table.item(row, 0).isSelected(): - editor_obj.apertures_table.selectRow(row) + for row in range(editor_obj.ui.apertures_table.rowCount()): + if str(aper) == editor_obj.ui.apertures_table.item(row, 1).text(): + if not editor_obj.ui.apertures_table.item(row, 0).isSelected(): + editor_obj.ui.apertures_table.selectRow(row) editor_obj.last_aperture_selected = aper # reconnect signal when clicking in the table - editor_obj.apertures_table.cellPressed.connect(editor_obj.on_row_selected) + editor_obj.ui.apertures_table.cellPressed.connect(editor_obj.on_row_selected) editor_obj.plot_object.emit(None) - self.grb_editor_app.app.worker_task.emit({'fcn': job_thread, 'params': [self.grb_editor_app]}) + self.draw_app.app.worker_task.emit({'fcn': job_thread, 'params': [self.draw_app]}) def clean_up(self): - self.grb_editor_app.plot_all() + self.draw_app.plot_all() class FCTransform(FCShapeTool): @@ -2553,473 +2554,7 @@ class AppGerberEditor(QtCore.QObject): # Current application units in Upper Case self.units = self.app.defaults['units'].upper() - self.grb_edit_widget = QtWidgets.QWidget() - - layout = QtWidgets.QVBoxLayout() - self.grb_edit_widget.setLayout(layout) - - # Page Title box (spacing between children) - self.title_box = QtWidgets.QHBoxLayout() - layout.addLayout(self.title_box) - - # Page Title icon - pixmap = QtGui.QPixmap(self.app.resource_location + '/flatcam_icon32.png') - self.icon = QtWidgets.QLabel() - self.icon.setPixmap(pixmap) - self.title_box.addWidget(self.icon, stretch=0) - - # Title label - self.title_label = QtWidgets.QLabel("%s" % _('Gerber Editor')) - self.title_label.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter) - self.title_box.addWidget(self.title_label, stretch=1) - - # Object name - self.name_box = QtWidgets.QHBoxLayout() - layout.addLayout(self.name_box) - name_label = QtWidgets.QLabel(_("Name:")) - self.name_box.addWidget(name_label) - self.name_entry = FCEntry() - self.name_box.addWidget(self.name_entry) - - # Box for custom widgets - # This gets populated in offspring implementations. - self.custom_box = QtWidgets.QVBoxLayout() - layout.addLayout(self.custom_box) - - # ######################### - # ### Gerber Apertures #### - # ######################### - self.apertures_table_label = QtWidgets.QLabel('%s:' % _('Apertures')) - self.apertures_table_label.setToolTip( - _("Apertures Table for the Gerber Object.") - ) - self.custom_box.addWidget(self.apertures_table_label) - - self.apertures_table = FCTable() - # delegate = SpinBoxDelegate(units=self.units) - # self.apertures_table.setItemDelegateForColumn(1, delegate) - - self.custom_box.addWidget(self.apertures_table) - - self.apertures_table.setColumnCount(5) - self.apertures_table.setHorizontalHeaderLabels(['#', _('Code'), _('Type'), _('Size'), _('Dim')]) - self.apertures_table.setSortingEnabled(False) - self.apertures_table.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectRows) - - self.apertures_table.horizontalHeaderItem(0).setToolTip( - _("Index")) - self.apertures_table.horizontalHeaderItem(1).setToolTip( - _("Aperture Code")) - self.apertures_table.horizontalHeaderItem(2).setToolTip( - _("Type of aperture: circular, rectangle, macros etc")) - self.apertures_table.horizontalHeaderItem(4).setToolTip( - _("Aperture Size:")) - self.apertures_table.horizontalHeaderItem(4).setToolTip( - _("Aperture Dimensions:\n" - " - (width, height) for R, O type.\n" - " - (dia, nVertices) for P type")) - - self.empty_label = QtWidgets.QLabel('') - self.custom_box.addWidget(self.empty_label) - - # add a frame and inside add a vertical box layout. Inside this vbox layout I add all the Apertures widgets - # this way I can hide/show the frame - self.apertures_frame = QtWidgets.QFrame() - self.apertures_frame.setContentsMargins(0, 0, 0, 0) - self.custom_box.addWidget(self.apertures_frame) - self.apertures_box = QtWidgets.QVBoxLayout() - self.apertures_box.setContentsMargins(0, 0, 0, 0) - self.apertures_frame.setLayout(self.apertures_box) - - # # ## Add/Delete an new Aperture ## ## - - grid1 = QtWidgets.QGridLayout() - self.apertures_box.addLayout(grid1) - grid1.setColumnStretch(0, 0) - grid1.setColumnStretch(1, 1) - - apcode_lbl = QtWidgets.QLabel('%s:' % _('Aperture Code')) - apcode_lbl.setToolTip(_("Code for the new aperture")) - grid1.addWidget(apcode_lbl, 1, 0) - - self.apcode_entry = FCSpinner() - self.apcode_entry.set_range(0, 999) - self.apcode_entry.setWrapping(True) - - grid1.addWidget(self.apcode_entry, 1, 1) - - apsize_lbl = QtWidgets.QLabel('%s' % _('Aperture Size:')) - apsize_lbl.setToolTip( - _("Size for the new aperture.\n" - "If aperture type is 'R' or 'O' then\n" - "this value is automatically\n" - "calculated as:\n" - "sqrt(width**2 + height**2)") - ) - grid1.addWidget(apsize_lbl, 2, 0) - - self.apsize_entry = FCDoubleSpinner() - self.apsize_entry.set_precision(self.decimals) - self.apsize_entry.set_range(0.0, 9999) - - grid1.addWidget(self.apsize_entry, 2, 1) - - aptype_lbl = QtWidgets.QLabel('%s:' % _('Aperture Type')) - aptype_lbl.setToolTip( - _("Select the type of new aperture. Can be:\n" - "C = circular\n" - "R = rectangular\n" - "O = oblong") - ) - grid1.addWidget(aptype_lbl, 3, 0) - - self.aptype_cb = FCComboBox() - self.aptype_cb.addItems(['C', 'R', 'O']) - grid1.addWidget(self.aptype_cb, 3, 1) - - self.apdim_lbl = QtWidgets.QLabel('%s:' % _('Aperture Dim')) - self.apdim_lbl.setToolTip( - _("Dimensions for the new aperture.\n" - "Active only for rectangular apertures (type R).\n" - "The format is (width, height)") - ) - grid1.addWidget(self.apdim_lbl, 4, 0) - - self.apdim_entry = EvalEntry2() - grid1.addWidget(self.apdim_entry, 4, 1) - - apadd_del_lbl = QtWidgets.QLabel('%s:' % _('Add/Delete Aperture')) - apadd_del_lbl.setToolTip( - _("Add/Delete an aperture in the aperture table") - ) - self.apertures_box.addWidget(apadd_del_lbl) - - hlay_ad = QtWidgets.QHBoxLayout() - self.apertures_box.addLayout(hlay_ad) - - self.addaperture_btn = QtWidgets.QPushButton(_('Add')) - self.addaperture_btn.setToolTip( - _("Add a new aperture to the aperture list.") - ) - - self.delaperture_btn = QtWidgets.QPushButton(_('Delete')) - self.delaperture_btn.setToolTip( - _("Delete a aperture in the aperture list") - ) - hlay_ad.addWidget(self.addaperture_btn) - hlay_ad.addWidget(self.delaperture_btn) - - # ################### - # ### BUFFER TOOL ### - # ################### - self.buffer_tool_frame = QtWidgets.QFrame() - self.buffer_tool_frame.setContentsMargins(0, 0, 0, 0) - self.custom_box.addWidget(self.buffer_tool_frame) - self.buffer_tools_box = QtWidgets.QVBoxLayout() - self.buffer_tools_box.setContentsMargins(0, 0, 0, 0) - self.buffer_tool_frame.setLayout(self.buffer_tools_box) - self.buffer_tool_frame.hide() - - # Title - buf_title_lbl = QtWidgets.QLabel('%s:' % _('Buffer Aperture')) - buf_title_lbl.setToolTip( - _("Buffer a aperture in the aperture list") - ) - self.buffer_tools_box.addWidget(buf_title_lbl) - - # Form Layout - buf_form_layout = QtWidgets.QFormLayout() - self.buffer_tools_box.addLayout(buf_form_layout) - - # Buffer distance - self.buffer_distance_entry = FCDoubleSpinner() - self.buffer_distance_entry.set_precision(self.decimals) - self.buffer_distance_entry.set_range(-10000.0000, 10000.0000) - - buf_form_layout.addRow('%s:' % _("Buffer distance"), self.buffer_distance_entry) - self.buffer_corner_lbl = QtWidgets.QLabel('%s:' % _("Buffer corner")) - self.buffer_corner_lbl.setToolTip( - _("There are 3 types of corners:\n" - " - 'Round': the corner is rounded.\n" - " - 'Square': the corner is met in a sharp angle.\n" - " - 'Beveled': the corner is a line that directly connects the features meeting in the corner") - ) - self.buffer_corner_cb = FCComboBox() - self.buffer_corner_cb.addItem(_("Round")) - self.buffer_corner_cb.addItem(_("Square")) - self.buffer_corner_cb.addItem(_("Beveled")) - buf_form_layout.addRow(self.buffer_corner_lbl, self.buffer_corner_cb) - - # Buttons - hlay_buf = QtWidgets.QHBoxLayout() - self.buffer_tools_box.addLayout(hlay_buf) - - self.buffer_button = QtWidgets.QPushButton(_("Buffer")) - hlay_buf.addWidget(self.buffer_button) - - # ################## - # ### SCALE TOOL ### - # ################## - self.scale_tool_frame = QtWidgets.QFrame() - self.scale_tool_frame.setContentsMargins(0, 0, 0, 0) - self.custom_box.addWidget(self.scale_tool_frame) - self.scale_tools_box = QtWidgets.QVBoxLayout() - self.scale_tools_box.setContentsMargins(0, 0, 0, 0) - self.scale_tool_frame.setLayout(self.scale_tools_box) - self.scale_tool_frame.hide() - - # Title - scale_title_lbl = QtWidgets.QLabel('%s:' % _('Scale Aperture')) - scale_title_lbl.setToolTip( - _("Scale a aperture in the aperture list") - ) - self.scale_tools_box.addWidget(scale_title_lbl) - - # Form Layout - scale_form_layout = QtWidgets.QFormLayout() - self.scale_tools_box.addLayout(scale_form_layout) - - self.scale_factor_lbl = QtWidgets.QLabel('%s:' % _("Scale factor")) - self.scale_factor_lbl.setToolTip( - _("The factor by which to scale the selected aperture.\n" - "Values can be between 0.0000 and 999.9999") - ) - self.scale_factor_entry = FCDoubleSpinner() - self.scale_factor_entry.set_precision(self.decimals) - self.scale_factor_entry.set_range(0.0000, 10000.0000) - - scale_form_layout.addRow(self.scale_factor_lbl, self.scale_factor_entry) - - # Buttons - hlay_scale = QtWidgets.QHBoxLayout() - self.scale_tools_box.addLayout(hlay_scale) - - self.scale_button = QtWidgets.QPushButton(_("Scale")) - hlay_scale.addWidget(self.scale_button) - - # ###################### - # ### Mark Area TOOL ### - # ###################### - self.ma_tool_frame = QtWidgets.QFrame() - self.ma_tool_frame.setContentsMargins(0, 0, 0, 0) - self.custom_box.addWidget(self.ma_tool_frame) - self.ma_tools_box = QtWidgets.QVBoxLayout() - self.ma_tools_box.setContentsMargins(0, 0, 0, 0) - self.ma_tool_frame.setLayout(self.ma_tools_box) - self.ma_tool_frame.hide() - - # Title - ma_title_lbl = QtWidgets.QLabel('%s:' % _('Mark polygons')) - ma_title_lbl.setToolTip( - _("Mark the polygon areas.") - ) - self.ma_tools_box.addWidget(ma_title_lbl) - - # Form Layout - ma_form_layout = QtWidgets.QFormLayout() - self.ma_tools_box.addLayout(ma_form_layout) - - self.ma_upper_threshold_lbl = QtWidgets.QLabel('%s:' % _("Area UPPER threshold")) - self.ma_upper_threshold_lbl.setToolTip( - _("The threshold value, all areas less than this are marked.\n" - "Can have a value between 0.0000 and 10000.0000") - ) - self.ma_upper_threshold_entry = FCDoubleSpinner() - self.ma_upper_threshold_entry.set_precision(self.decimals) - self.ma_upper_threshold_entry.set_range(0, 10000) - - self.ma_lower_threshold_lbl = QtWidgets.QLabel('%s:' % _("Area LOWER threshold")) - self.ma_lower_threshold_lbl.setToolTip( - _("The threshold value, all areas more than this are marked.\n" - "Can have a value between 0.0000 and 10000.0000") - ) - self.ma_lower_threshold_entry = FCDoubleSpinner() - self.ma_lower_threshold_entry.set_precision(self.decimals) - self.ma_lower_threshold_entry.set_range(0, 10000) - - ma_form_layout.addRow(self.ma_lower_threshold_lbl, self.ma_lower_threshold_entry) - ma_form_layout.addRow(self.ma_upper_threshold_lbl, self.ma_upper_threshold_entry) - - # Buttons - hlay_ma = QtWidgets.QHBoxLayout() - self.ma_tools_box.addLayout(hlay_ma) - - self.ma_threshold_button = QtWidgets.QPushButton(_("Mark")) - self.ma_threshold_button.setToolTip( - _("Mark the polygons that fit within limits.") - ) - hlay_ma.addWidget(self.ma_threshold_button) - - self.ma_delete_button = QtWidgets.QPushButton(_("Delete")) - self.ma_delete_button.setToolTip( - _("Delete all the marked polygons.") - ) - hlay_ma.addWidget(self.ma_delete_button) - - self.ma_clear_button = QtWidgets.QPushButton(_("Clear")) - self.ma_clear_button.setToolTip( - _("Clear all the markings.") - ) - hlay_ma.addWidget(self.ma_clear_button) - - # ###################### - # ### Add Pad Array #### - # ###################### - # add a frame and inside add a vertical box layout. Inside this vbox layout I add - # all the add Pad array widgets - # this way I can hide/show the frame - self.array_frame = QtWidgets.QFrame() - self.array_frame.setContentsMargins(0, 0, 0, 0) - self.custom_box.addWidget(self.array_frame) - self.array_box = QtWidgets.QVBoxLayout() - self.array_box.setContentsMargins(0, 0, 0, 0) - self.array_frame.setLayout(self.array_box) - - self.emptyarray_label = QtWidgets.QLabel('') - self.array_box.addWidget(self.emptyarray_label) - - self.padarray_label = QtWidgets.QLabel('%s' % _("Add Pad Array")) - self.padarray_label.setToolTip( - _("Add an array of pads (linear or circular array)") - ) - self.array_box.addWidget(self.padarray_label) - - self.array_type_combo = FCComboBox() - self.array_type_combo.setToolTip( - _("Select the type of pads array to create.\n" - "It can be Linear X(Y) or Circular") - ) - self.array_type_combo.addItem(_("Linear")) - self.array_type_combo.addItem(_("Circular")) - - self.array_box.addWidget(self.array_type_combo) - - self.array_form = QtWidgets.QFormLayout() - self.array_box.addLayout(self.array_form) - - self.pad_array_size_label = QtWidgets.QLabel('%s:' % _('Nr of pads')) - self.pad_array_size_label.setToolTip( - _("Specify how many pads to be in the array.") - ) - self.pad_array_size_label.setMinimumWidth(100) - - self.pad_array_size_entry = FCSpinner() - self.pad_array_size_entry.set_range(1, 9999) - - self.array_form.addRow(self.pad_array_size_label, self.pad_array_size_entry) - - self.array_linear_frame = QtWidgets.QFrame() - self.array_linear_frame.setContentsMargins(0, 0, 0, 0) - self.array_box.addWidget(self.array_linear_frame) - self.linear_box = QtWidgets.QVBoxLayout() - self.linear_box.setContentsMargins(0, 0, 0, 0) - self.array_linear_frame.setLayout(self.linear_box) - - self.linear_form = QtWidgets.QFormLayout() - self.linear_box.addLayout(self.linear_form) - - self.pad_axis_label = QtWidgets.QLabel('%s:' % _('Direction')) - self.pad_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.pad_axis_label.setMinimumWidth(100) - - self.pad_axis_radio = RadioSet([{'label': _('X'), 'value': 'X'}, - {'label': _('Y'), 'value': 'Y'}, - {'label': _('Angle'), 'value': 'A'}]) - self.pad_axis_radio.set_value('X') - self.linear_form.addRow(self.pad_axis_label, self.pad_axis_radio) - - self.pad_pitch_label = QtWidgets.QLabel('%s:' % _('Pitch')) - self.pad_pitch_label.setToolTip( - _("Pitch = Distance between elements of the array.") - ) - self.pad_pitch_label.setMinimumWidth(100) - - self.pad_pitch_entry = FCDoubleSpinner() - self.pad_pitch_entry.set_precision(self.decimals) - self.pad_pitch_entry.set_range(0.0000, 10000.0000) - self.pad_pitch_entry.setSingleStep(0.1) - - self.linear_form.addRow(self.pad_pitch_label, self.pad_pitch_entry) - - self.linear_angle_label = QtWidgets.QLabel('%s:' % _('Angle')) - self.linear_angle_label.setToolTip( - _("Angle at which the linear array is placed.\n" - "The precision is of max 2 decimals.\n" - "Min value is: -360.00 degrees.\n" - "Max value is: 360.00 degrees.") - ) - self.linear_angle_label.setMinimumWidth(100) - - self.linear_angle_spinner = FCDoubleSpinner() - self.linear_angle_spinner.set_precision(self.decimals) - self.linear_angle_spinner.setRange(-360.00, 360.00) - self.linear_form.addRow(self.linear_angle_label, self.linear_angle_spinner) - - self.array_circular_frame = QtWidgets.QFrame() - self.array_circular_frame.setContentsMargins(0, 0, 0, 0) - self.array_box.addWidget(self.array_circular_frame) - self.circular_box = QtWidgets.QVBoxLayout() - self.circular_box.setContentsMargins(0, 0, 0, 0) - self.array_circular_frame.setLayout(self.circular_box) - - self.pad_direction_label = QtWidgets.QLabel('%s:' % _('Direction')) - self.pad_direction_label.setToolTip( - _("Direction for circular array.\n" - "Can be CW = clockwise or CCW = counter clockwise.") - ) - self.pad_direction_label.setMinimumWidth(100) - - self.circular_form = QtWidgets.QFormLayout() - self.circular_box.addLayout(self.circular_form) - - self.pad_direction_radio = RadioSet([{'label': _('CW'), 'value': 'CW'}, - {'label': _('CCW'), 'value': 'CCW'}]) - self.pad_direction_radio.set_value('CW') - self.circular_form.addRow(self.pad_direction_label, self.pad_direction_radio) - - self.pad_angle_label = QtWidgets.QLabel('%s:' % _('Angle')) - self.pad_angle_label.setToolTip( - _("Angle at which each element in circular array is placed.") - ) - self.pad_angle_label.setMinimumWidth(100) - - self.pad_angle_entry = FCDoubleSpinner() - self.pad_angle_entry.set_precision(self.decimals) - self.pad_angle_entry.set_range(-360.00, 360.00) - self.pad_angle_entry.setSingleStep(0.1) - - self.circular_form.addRow(self.pad_angle_label, self.pad_angle_entry) - - self.array_circular_frame.hide() - - self.linear_angle_spinner.hide() - self.linear_angle_label.hide() - - self.array_frame.hide() - self.custom_box.addStretch() - - layout.addStretch() - - # Editor - self.exit_editor_button = QtWidgets.QPushButton(_('Exit Editor')) - self.exit_editor_button.setIcon(QtGui.QIcon(self.app.resource_location + '/power16.png')) - self.exit_editor_button.setToolTip( - _("Exit from Editor.") - ) - self.exit_editor_button.setStyleSheet(""" - QPushButton - { - font-weight: bold; - } - """) - layout.addWidget(self.exit_editor_button) - - self.exit_editor_button.clicked.connect(lambda: self.app.editor2object()) + self.ui = AppGerberEditorUI(self.app) # Toolbar events and properties self.tools_gerber = {} @@ -3058,9 +2593,12 @@ class AppGerberEditor(QtCore.QObject): # this var will store the state of the toolbar before starting the editor self.toolbar_old_state = False - # Init appGUI - self.apdim_lbl.hide() - self.apdim_entry.hide() + # ############################################################################################################# + # ######################### Init appGUI ####################################################################### + # ############################################################################################################# + self.ui.apdim_lbl.hide() + self.ui.apdim_entry.hide() + self.gerber_obj = None self.gerber_obj_options = {} @@ -3079,8 +2617,6 @@ class AppGerberEditor(QtCore.QObject): name='ma_anno_grb_editor', annotation_job=True) - self.app.pool_recreated.connect(self.pool_recreated) - # Event signals disconnect id holders self.mp = None self.mm = None @@ -3113,14 +2649,16 @@ class AppGerberEditor(QtCore.QObject): def_tol_val = float(self.app.defaults["global_tolerance"]) self.tolerance = def_tol_val if self.units == 'MM'else def_tol_val / 20 + # options of this widget (AppGerberEditor class is a widget) self.options = { - "global_gridx": 0.1, - "global_gridy": 0.1, - "snap_max": 0.05, - "grid_snap": True, - "corner_snap": False, - "grid_gap_link": True + "global_gridx": 0.1, + "global_gridy": 0.1, + "snap_max": 0.05, + "grid_snap": True, + "corner_snap": False, + "grid_gap_link": True } + # fill it with the application options (application preferences) self.options.update(self.app.options) for option in self.options: @@ -3152,25 +2690,12 @@ class AppGerberEditor(QtCore.QObject): # ############################################################################################################# # ######################### Gerber Editor Signals ############################################################# # ############################################################################################################# + self.app.pool_recreated.connect(self.pool_recreated) + self.mp_finished.connect(self.on_multiprocessing_finished) # connect the toolbar signals self.connect_grb_toolbar_signals() - self.buffer_button.clicked.connect(self.on_buffer) - self.scale_button.clicked.connect(self.on_scale) - - self.app.ui.aperture_delete_btn.triggered.connect(self.on_delete_btn) - self.name_entry.returnPressed.connect(self.on_name_activate) - - self.aptype_cb.currentIndexChanged[str].connect(self.on_aptype_changed) - - self.addaperture_btn.clicked.connect(self.on_aperture_add) - self.apsize_entry.returnPressed.connect(self.on_aperture_add) - self.apdim_entry.returnPressed.connect(self.on_aperture_add) - - self.delaperture_btn.clicked.connect(self.on_aperture_delete) - self.apertures_table.cellPressed.connect(self.on_row_selected) - self.app.ui.grb_add_pad_menuitem.triggered.connect(self.on_pad_add) self.app.ui.grb_add_pad_array_menuitem.triggered.connect(self.on_pad_add_array) @@ -3192,10 +2717,25 @@ class AppGerberEditor(QtCore.QObject): self.app.ui.grb_move_menuitem.triggered.connect(self.on_move_button) - self.array_type_combo.currentIndexChanged.connect(self.on_array_type_combo) - self.pad_axis_radio.activated_custom.connect(self.on_linear_angle_radio) + self.ui.buffer_button.clicked.connect(self.on_buffer) + self.ui.scale_button.clicked.connect(self.on_scale) - self.mp_finished.connect(self.on_multiprocessing_finished) + self.app.ui.aperture_delete_btn.triggered.connect(self.on_delete_btn) + self.ui.name_entry.returnPressed.connect(self.on_name_activate) + + self.ui.aptype_cb.currentIndexChanged[str].connect(self.on_aptype_changed) + + self.ui.addaperture_btn.clicked.connect(self.on_aperture_add) + self.ui.apsize_entry.returnPressed.connect(self.on_aperture_add) + self.ui.apdim_entry.returnPressed.connect(self.on_aperture_add) + + self.ui.delaperture_btn.clicked.connect(self.on_aperture_delete) + self.ui.apertures_table.cellPressed.connect(self.on_row_selected) + + self.ui.array_type_combo.currentIndexChanged.connect(self.on_array_type_combo) + self.ui.pad_axis_radio.activated_custom.connect(self.on_linear_angle_radio) + + self.ui.exit_editor_button.clicked.connect(lambda: self.app.editor2object()) self.conversion_factor = 1 @@ -3262,36 +2802,37 @@ class AppGerberEditor(QtCore.QObject): tt_aperture = self.sorted_apcode[i] self.tid2apcode[i + 1] = tt_aperture + # ############################################################################################################# # Init appGUI + # ############################################################################################################# + self.ui.buffer_distance_entry.set_value(self.app.defaults["gerber_editor_buff_f"]) + self.ui.scale_factor_entry.set_value(self.app.defaults["gerber_editor_scale_f"]) + self.ui.ma_upper_threshold_entry.set_value(self.app.defaults["gerber_editor_ma_high"]) + self.ui.ma_lower_threshold_entry.set_value(self.app.defaults["gerber_editor_ma_low"]) - self.buffer_distance_entry.set_value(self.app.defaults["gerber_editor_buff_f"]) - self.scale_factor_entry.set_value(self.app.defaults["gerber_editor_scale_f"]) - self.ma_upper_threshold_entry.set_value(self.app.defaults["gerber_editor_ma_high"]) - self.ma_lower_threshold_entry.set_value(self.app.defaults["gerber_editor_ma_low"]) + self.ui.apsize_entry.set_value(self.app.defaults["gerber_editor_newsize"]) + self.ui.aptype_cb.set_value(self.app.defaults["gerber_editor_newtype"]) + self.ui.apdim_entry.set_value(self.app.defaults["gerber_editor_newdim"]) - self.apsize_entry.set_value(self.app.defaults["gerber_editor_newsize"]) - self.aptype_cb.set_value(self.app.defaults["gerber_editor_newtype"]) - self.apdim_entry.set_value(self.app.defaults["gerber_editor_newdim"]) - - self.pad_array_size_entry.set_value(int(self.app.defaults["gerber_editor_array_size"])) + self.ui.pad_array_size_entry.set_value(int(self.app.defaults["gerber_editor_array_size"])) # linear array - self.pad_axis_radio.set_value(self.app.defaults["gerber_editor_lin_axis"]) - self.pad_pitch_entry.set_value(float(self.app.defaults["gerber_editor_lin_pitch"])) - self.linear_angle_spinner.set_value(self.app.defaults["gerber_editor_lin_angle"]) + self.ui.pad_axis_radio.set_value(self.app.defaults["gerber_editor_lin_axis"]) + self.ui.pad_pitch_entry.set_value(float(self.app.defaults["gerber_editor_lin_pitch"])) + self.ui.linear_angle_spinner.set_value(self.app.defaults["gerber_editor_lin_angle"]) # circular array - self.pad_direction_radio.set_value(self.app.defaults["gerber_editor_circ_dir"]) - self.pad_angle_entry.set_value(float(self.app.defaults["gerber_editor_circ_angle"])) + self.ui.pad_direction_radio.set_value(self.app.defaults["gerber_editor_circ_dir"]) + self.ui.pad_angle_entry.set_value(float(self.app.defaults["gerber_editor_circ_angle"])) def build_ui(self, first_run=None): try: # if connected, disconnect the signal from the slot on item_changed as it creates issues - self.apertures_table.itemChanged.disconnect() + self.ui.apertures_table.itemChanged.disconnect() except (TypeError, AttributeError): pass try: - self.apertures_table.cellPressed.disconnect() + self.ui.apertures_table.cellPressed.disconnect() except (TypeError, AttributeError): pass @@ -3300,7 +2841,7 @@ class AppGerberEditor(QtCore.QObject): # make a new name for the new Excellon object (the one with edited content) self.edited_obj_name = self.gerber_obj.options['name'] - self.name_entry.set_value(self.edited_obj_name) + self.ui.name_entry.set_value(self.edited_obj_name) self.apertures_row = 0 # aper_no = self.apertures_row + 1 @@ -3318,14 +2859,14 @@ class AppGerberEditor(QtCore.QObject): # n = len(sorted_apertures) + len(sorted_macros) n = len(sorted_apertures) - self.apertures_table.setRowCount(n) + self.ui.apertures_table.setRowCount(n) for ap_code in sorted_apertures: ap_code = str(ap_code) ap_code_item = QtWidgets.QTableWidgetItem('%d' % int(self.apertures_row + 1)) ap_code_item.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled) - self.apertures_table.setItem(self.apertures_row, 0, ap_code_item) # Tool name/id + self.ui.apertures_table.setItem(self.apertures_row, 0, ap_code_item) # Tool name/id ap_code_item = QtWidgets.QTableWidgetItem(ap_code) ap_code_item.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled) @@ -3364,10 +2905,10 @@ class AppGerberEditor(QtCore.QObject): else: ap_size_item.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled) - self.apertures_table.setItem(self.apertures_row, 1, ap_code_item) # Aperture Code - self.apertures_table.setItem(self.apertures_row, 2, ap_type_item) # Aperture Type - self.apertures_table.setItem(self.apertures_row, 3, ap_size_item) # Aperture Size - self.apertures_table.setItem(self.apertures_row, 4, ap_dim_item) # Aperture Dimensions + self.ui.apertures_table.setItem(self.apertures_row, 1, ap_code_item) # Aperture Code + self.ui.apertures_table.setItem(self.apertures_row, 2, ap_type_item) # Aperture Type + self.ui.apertures_table.setItem(self.apertures_row, 3, ap_size_item) # Aperture Size + self.ui.apertures_table.setItem(self.apertures_row, 4, ap_dim_item) # Aperture Dimensions self.apertures_row += 1 if first_run is True: @@ -3379,31 +2920,31 @@ class AppGerberEditor(QtCore.QObject): # # ap_code_item = QtWidgets.QTableWidgetItem('%d' % int(self.apertures_row + 1)) # ap_code_item.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled) - # self.apertures_table.setItem(self.apertures_row, 0, ap_code_item) # Tool name/id + # self.ui.apertures_table.setItem(self.apertures_row, 0, ap_code_item) # Tool name/id # # ap_code_item = QtWidgets.QTableWidgetItem(ap_code) # # ap_type_item = QtWidgets.QTableWidgetItem('AM') # ap_type_item.setFlags(QtCore.Qt.ItemIsEnabled) # - # self.apertures_table.setItem(self.apertures_row, 1, ap_code_item) # Aperture Code - # self.apertures_table.setItem(self.apertures_row, 2, ap_type_item) # Aperture Type + # self.ui.apertures_table.setItem(self.apertures_row, 1, ap_code_item) # Aperture Code + # self.ui.apertures_table.setItem(self.apertures_row, 2, ap_type_item) # Aperture Type # # self.apertures_row += 1 # if first_run is True: # # set now the last aperture selected # self.last_aperture_selected = ap_code - self.apertures_table.selectColumn(0) - self.apertures_table.resizeColumnsToContents() - self.apertures_table.resizeRowsToContents() + self.ui.apertures_table.selectColumn(0) + self.ui.apertures_table.resizeColumnsToContents() + self.ui.apertures_table.resizeRowsToContents() - vertical_header = self.apertures_table.verticalHeader() + vertical_header = self.ui.apertures_table.verticalHeader() # vertical_header.setSectionResizeMode(QtWidgets.QHeaderView.ResizeToContents) vertical_header.hide() - self.apertures_table.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff) + self.ui.apertures_table.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff) - horizontal_header = self.apertures_table.horizontalHeader() + horizontal_header = self.ui.apertures_table.horizontalHeader() horizontal_header.setMinimumSectionSize(10) horizontal_header.setDefaultSectionSize(70) horizontal_header.setSectionResizeMode(0, QtWidgets.QHeaderView.Fixed) @@ -3413,31 +2954,31 @@ class AppGerberEditor(QtCore.QObject): horizontal_header.setSectionResizeMode(3, QtWidgets.QHeaderView.ResizeToContents) horizontal_header.setSectionResizeMode(4, QtWidgets.QHeaderView.Stretch) - self.apertures_table.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff) - self.apertures_table.setSortingEnabled(False) - self.apertures_table.setMinimumHeight(self.apertures_table.getHeight()) - self.apertures_table.setMaximumHeight(self.apertures_table.getHeight()) + self.ui.apertures_table.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff) + self.ui.apertures_table.setSortingEnabled(False) + self.ui.apertures_table.setMinimumHeight(self.ui.apertures_table.getHeight()) + self.ui.apertures_table.setMaximumHeight(self.ui.apertures_table.getHeight()) # make sure no rows are selected so the user have to click the correct row, meaning selecting the correct tool - self.apertures_table.clearSelection() + self.ui.apertures_table.clearSelection() # Remove anything else in the GUI Properties Tab self.app.ui.properties_scroll_area.takeWidget() # Put ourselves in the GUI Properties Tab - self.app.ui.properties_scroll_area.setWidget(self.grb_edit_widget) + self.app.ui.properties_scroll_area.setWidget(self.ui.grb_edit_widget) # Switch notebook to Properties page self.app.ui.notebook.setCurrentWidget(self.app.ui.properties_tab) # we reactivate the signals after the after the tool adding as we don't need to see the tool been populated - self.apertures_table.itemChanged.connect(self.on_tool_edit) - self.apertures_table.cellPressed.connect(self.on_row_selected) + self.ui.apertures_table.itemChanged.connect(self.on_tool_edit) + self.ui.apertures_table.cellPressed.connect(self.on_row_selected) # for convenience set the next aperture code in the apcode field try: - self.apcode_entry.set_value(max(self.tid2apcode.values()) + 1) + self.ui.apcode_entry.set_value(max(self.tid2apcode.values()) + 1) except ValueError: # this means that the edited object has no apertures so we start with 10 (Gerber specifications) - self.apcode_entry.set_value(self.app.defaults["gerber_editor_newcode"]) + self.ui.apcode_entry.set_value(self.app.defaults["gerber_editor_newcode"]) def on_aperture_add(self, apcode=None): self.is_modified = True @@ -3445,7 +2986,7 @@ class AppGerberEditor(QtCore.QObject): ap_code = apcode else: try: - ap_code = str(self.apcode_entry.get_value()) + ap_code = str(self.ui.apcode_entry.get_value()) except ValueError: self.app.inform.emit('[WARNING_NOTCL] %s' % _("Aperture code value is missing or wrong format. Add it and retry.")) @@ -3460,7 +3001,7 @@ class AppGerberEditor(QtCore.QObject): self.storage_dict[ap_code] = {} self.storage_dict[ap_code]['type'] = 'REG' size_val = 0 - self.apsize_entry.set_value(size_val) + self.ui.apsize_entry.set_value(size_val) self.storage_dict[ap_code]['size'] = size_val self.storage_dict[ap_code]['geometry'] = [] @@ -3477,12 +3018,12 @@ class AppGerberEditor(QtCore.QObject): if type_val == 'R' or type_val == 'O': try: - dims = self.apdim_entry.get_value() + dims = self.ui.apdim_entry.get_value() self.storage_dict[ap_code]['width'] = dims[0] self.storage_dict[ap_code]['height'] = dims[1] size_val = np.sqrt((dims[0] ** 2) + (dims[1] ** 2)) - self.apsize_entry.set_value(size_val) + self.ui.apsize_entry.set_value(size_val) except Exception as e: log.error("AppGerberEditor.on_aperture_add() --> the R or O aperture dims has to be in a " @@ -3493,12 +3034,12 @@ class AppGerberEditor(QtCore.QObject): return else: try: - size_val = float(self.apsize_entry.get_value()) + size_val = float(self.ui.apsize_entry.get_value()) except ValueError: # try to convert comma to decimal point. if it's still not working error message and return try: - size_val = float(self.apsize_entry.get_value().replace(',', '.')) - self.apsize_entry.set_value(size_val) + size_val = float(self.ui.apsize_entry.get_value().replace(',', '.')) + self.ui.apsize_entry.set_value(size_val) except ValueError: self.app.inform.emit('[WARNING_NOTCL] %s' % _("Aperture size value is missing or wrong format. Add it and retry.")) @@ -3531,7 +3072,7 @@ class AppGerberEditor(QtCore.QObject): if self.tid2apcode[key] == int(ap_code): row_to_be_selected = int(key) - 1 break - self.apertures_table.selectRow(row_to_be_selected) + self.ui.apertures_table.selectRow(row_to_be_selected) def on_aperture_delete(self, ap_code=None): """ @@ -3549,15 +3090,15 @@ class AppGerberEditor(QtCore.QObject): except TypeError: deleted_apcode_list = [ap_code] else: - # deleted_tool_dia = float(self.apertures_table.item(self.apertures_table.currentRow(), 1).text()) - if len(self.apertures_table.selectionModel().selectedRows()) == 0: + # deleted_tool_dia = float(self.ui.apertures_table.item(self.ui.apertures_table.currentRow(), 1).text()) + if len(self.ui.apertures_table.selectionModel().selectedRows()) == 0: self.app.inform.emit('[WARNING_NOTCL] %s' % _(" Select an aperture in Aperture Table")) return deleted_apcode_list = [] - for index in self.apertures_table.selectionModel().selectedRows(): + for index in self.ui.apertures_table.selectionModel().selectedRows(): row = index.row() - deleted_apcode_list.append(self.apertures_table.item(row, 1).text()) + deleted_apcode_list.append(self.ui.apertures_table.item(row, 1).text()) except Exception as exc: self.app.inform.emit('[WARNING_NOTCL] %s %s' % (_("Select an aperture in Aperture Table -->", str(exc)))) return @@ -3582,62 +3123,62 @@ class AppGerberEditor(QtCore.QObject): # 'new' last aperture selected because there are tools who depend on it. # if there is no aperture left, then add a default one :) if self.last_aperture_selected in deleted_apcode_list: - if self.apertures_table.rowCount() == 0: + if self.ui.apertures_table.rowCount() == 0: self.on_aperture_add('10') self.last_aperture_selected = '10' else: - self.last_aperture_selected = self.apertures_table.item(0, 1).text() + self.last_aperture_selected = self.ui.apertures_table.item(0, 1).text() def on_tool_edit(self): - if self.apertures_table.currentItem() is None: + if self.ui.apertures_table.currentItem() is None: return # if connected, disconnect the signal from the slot on item_changed as it creates issues - self.apertures_table.itemChanged.disconnect() - # self.apertures_table.cellPressed.disconnect() + self.ui.apertures_table.itemChanged.disconnect() + # self.ui.apertures_table.cellPressed.disconnect() self.is_modified = True val_edited = None - row_of_item_changed = self.apertures_table.currentRow() - col_of_item_changed = self.apertures_table.currentColumn() + row_of_item_changed = self.ui.apertures_table.currentRow() + col_of_item_changed = self.ui.apertures_table.currentColumn() # rows start with 0, tools start with 1 so we adjust the value by 1 key_in_tid2apcode = row_of_item_changed + 1 ap_code_old = str(self.tid2apcode[key_in_tid2apcode]) - ap_code_new = self.apertures_table.item(row_of_item_changed, 1).text() + ap_code_new = self.ui.apertures_table.item(row_of_item_changed, 1).text() if col_of_item_changed == 1: # we edited the Aperture Code column (int) try: - val_edited = int(self.apertures_table.currentItem().text()) + val_edited = int(self.ui.apertures_table.currentItem().text()) except ValueError as e: log.debug("AppGerberEditor.on_tool_edit() --> %s" % str(e)) - # self.apertures_table.setCurrentItem(None) + # self.ui.apertures_table.setCurrentItem(None) # we reactivate the signals after the after the tool editing - self.apertures_table.itemChanged.connect(self.on_tool_edit) + self.ui.apertures_table.itemChanged.connect(self.on_tool_edit) return elif col_of_item_changed == 3: # we edited the Size column (float) try: - val_edited = float(self.apertures_table.currentItem().text()) + val_edited = float(self.ui.apertures_table.currentItem().text()) except ValueError as e: log.debug("AppGerberEditor.on_tool_edit() --> %s" % str(e)) - # self.apertures_table.setCurrentItem(None) + # self.ui.apertures_table.setCurrentItem(None) # we reactivate the signals after the after the tool editing - self.apertures_table.itemChanged.connect(self.on_tool_edit) + self.ui.apertures_table.itemChanged.connect(self.on_tool_edit) return elif col_of_item_changed == 4: # we edit the Dimensions column (tuple) try: val_edited = [ - float(x.strip()) for x in self.apertures_table.currentItem().text().split(",") if x != '' + float(x.strip()) for x in self.ui.apertures_table.currentItem().text().split(",") if x != '' ] except ValueError as e: log.debug("AppGerberEditor.on_tool_edit() --> %s" % str(e)) # we reactivate the signals after the after the tool editing - self.apertures_table.itemChanged.connect(self.on_tool_edit) + self.ui.apertures_table.itemChanged.connect(self.on_tool_edit) return if len(val_edited) != 2: @@ -3645,9 +3186,9 @@ class AppGerberEditor(QtCore.QObject): old_dims_txt = '%s, %s' % (str(self.storage_dict[ap_code_new]['width']), str(self.storage_dict[ap_code_new]['height'])) - self.apertures_table.currentItem().setText(old_dims_txt) + self.ui.apertures_table.currentItem().setText(old_dims_txt) # we reactivate the signals after the after the tool editing - self.apertures_table.itemChanged.connect(self.on_tool_edit) + self.ui.apertures_table.itemChanged.connect(self.on_tool_edit) return else: self.app.inform.emit("[success] %s" % _("Dimensions edited.")) @@ -3768,22 +3309,22 @@ class AppGerberEditor(QtCore.QObject): self.plot_all() # we reactivate the signals after the after the tool editing - self.apertures_table.itemChanged.connect(self.on_tool_edit) - # self.apertures_table.cellPressed.connect(self.on_row_selected) + self.ui.apertures_table.itemChanged.connect(self.on_tool_edit) + # self.ui.apertures_table.cellPressed.connect(self.on_row_selected) def on_name_activate(self): - self.edited_obj_name = self.name_entry.get_value() + self.edited_obj_name = self.ui.name_entry.get_value() def on_aptype_changed(self, current_text): # 'O' is letter O not zero. if current_text == 'R' or current_text == 'O': - self.apdim_lbl.show() - self.apdim_entry.show() - self.apsize_entry.setDisabled(True) + self.ui.apdim_lbl.show() + self.ui.apdim_entry.show() + self.ui.apsize_entry.setDisabled(True) else: - self.apdim_lbl.hide() - self.apdim_entry.hide() - self.apsize_entry.setDisabled(False) + self.ui.apdim_lbl.hide() + self.ui.apdim_entry.hide() + self.ui.apsize_entry.setDisabled(False) def activate_grb_editor(self): # adjust the status of the menu entries related to the editor @@ -4056,9 +3597,9 @@ class AppGerberEditor(QtCore.QObject): self.activate_grb_editor() # reset the tool table - self.apertures_table.clear() + self.ui.apertures_table.clear() - self.apertures_table.setHorizontalHeaderLabels(['#', _('Code'), _('Type'), _('Size'), _('Dim')]) + self.ui.apertures_table.setHorizontalHeaderLabels(['#', _('Code'), _('Type'), _('Size'), _('Dim')]) self.last_aperture_selected = None # create a reference to the source object @@ -4087,7 +3628,7 @@ class AppGerberEditor(QtCore.QObject): try: # we activate this after the initial build as we don't need to see the tool been populated - self.apertures_table.itemChanged.connect(self.on_tool_edit) + self.ui.apertures_table.itemChanged.connect(self.on_tool_edit) except Exception as e: log.debug("AppGerberEditor.edit_fcgerber() --> %s" % str(e)) @@ -4522,7 +4063,7 @@ class AppGerberEditor(QtCore.QObject): self.selected = [] try: - selected_ap_code = self.apertures_table.item(row, 1).text() + selected_ap_code = self.ui.apertures_table.item(row, 1).text() self.last_aperture_selected = copy(selected_ap_code) for obj in self.storage_dict[selected_ap_code]['geometry']: @@ -4778,7 +4319,7 @@ class AppGerberEditor(QtCore.QObject): poly_selection = Polygon([start_pos, (end_pos[0], start_pos[1]), end_pos, (start_pos[0], end_pos[1])]) sel_aperture = set() - self.apertures_table.clearSelection() + self.ui.apertures_table.clearSelection() self.app.delete_selection_shape() for storage in self.storage_dict: @@ -4799,20 +4340,20 @@ class AppGerberEditor(QtCore.QObject): sel_aperture.add(storage) try: - self.apertures_table.cellPressed.disconnect() + self.ui.apertures_table.cellPressed.disconnect() except Exception as e: log.debug("AppGerberEditor.draw_selection_Area_handler() --> %s" % str(e)) # select the aperture code of the selected geometry, in the tool table - self.apertures_table.setSelectionMode(QtWidgets.QAbstractItemView.MultiSelection) + self.ui.apertures_table.setSelectionMode(QtWidgets.QAbstractItemView.MultiSelection) for aper in sel_aperture: - for row_to_sel in range(self.apertures_table.rowCount()): - if str(aper) == self.apertures_table.item(row_to_sel, 1).text(): - if row_to_sel not in set(index.row() for index in self.apertures_table.selectedIndexes()): - self.apertures_table.selectRow(row_to_sel) + for row_to_sel in range(self.ui.apertures_table.rowCount()): + if str(aper) == self.ui.apertures_table.item(row_to_sel, 1).text(): + if row_to_sel not in set(index.row() for index in self.ui.apertures_table.selectedIndexes()): + self.ui.apertures_table.selectRow(row_to_sel) self.last_aperture_selected = aper - self.apertures_table.setSelectionMode(QtWidgets.QAbstractItemView.ExtendedSelection) + self.ui.apertures_table.setSelectionMode(QtWidgets.QAbstractItemView.ExtendedSelection) - self.apertures_table.cellPressed.connect(self.on_row_selected) + self.ui.apertures_table.cellPressed.connect(self.on_row_selected) self.plot_all() def on_canvas_move(self, event): @@ -5152,23 +4693,23 @@ class AppGerberEditor(QtCore.QObject): self.selected.remove(geo_el) def on_array_type_combo(self): - if self.array_type_combo.currentIndex() == 0: - self.array_circular_frame.hide() - self.array_linear_frame.show() + if self.ui.array_type_combo.currentIndex() == 0: + self.ui.array_circular_frame.hide() + self.ui.array_linear_frame.show() else: self.delete_utility_geometry() - self.array_circular_frame.show() - self.array_linear_frame.hide() + self.ui.array_circular_frame.show() + self.ui.array_linear_frame.hide() self.app.inform.emit(_("Click on the circular array Center position")) def on_linear_angle_radio(self): - val = self.pad_axis_radio.get_value() + val = self.ui.pad_axis_radio.get_value() if val == 'A': - self.linear_angle_spinner.show() - self.linear_angle_label.show() + self.ui.linear_angle_spinner.show() + self.ui.linear_angle_label.show() else: - self.linear_angle_spinner.hide() - self.linear_angle_label.hide() + self.ui.linear_angle_spinner.hide() + self.ui.linear_angle_label.hide() def on_copy_button(self): self.select_tool('copy') @@ -5204,19 +4745,20 @@ class AppGerberEditor(QtCore.QObject): log.debug("AppGerberEditor.on_buffer()") try: - buff_value = float(self.buffer_distance_entry.get_value()) + buff_value = float(self.ui.buffer_distance_entry.get_value()) except ValueError: # try to convert comma to decimal point. if it's still not working error message and return try: - buff_value = float(self.buffer_distance_entry.get_value().replace(',', '.')) - self.buffer_distance_entry.set_value(buff_value) + buff_value = float(self.ui.buffer_distance_entry.get_value().replace(',', '.')) + self.ui.buffer_distance_entry.set_value(buff_value) except ValueError: self.app.inform.emit('[WARNING_NOTCL] %s' % _("Buffer distance value is missing or wrong format. Add it and retry.")) return + # the cb index start from 0 but the join styles for the buffer start from 1 therefore the adjustment # I populated the combobox such that the index coincide with the join styles value (which is really an INT) - join_style = self.buffer_corner_cb.currentIndex() + 1 + join_style = self.ui.buffer_corner_cb.currentIndex() + 1 def buffer_recursion(geom_el, selection): if type(geom_el) == list: @@ -5238,14 +4780,14 @@ class AppGerberEditor(QtCore.QObject): else: return geom_el - if not self.apertures_table.selectedItems(): + if not self.ui.apertures_table.selectedItems(): self.app.inform.emit('[WARNING_NOTCL] %s' % _("No aperture to buffer. Select at least one aperture and try again.")) return - for x in self.apertures_table.selectedItems(): + for x in self.ui.apertures_table.selectedItems(): try: - apcode = self.apertures_table.item(x.row(), 1).text() + apcode = self.ui.apertures_table.item(x.row(), 1).text() temp_storage = deepcopy(buffer_recursion(self.storage_dict[apcode]['geometry'], self.selected)) self.storage_dict[apcode]['geometry'] = [] @@ -5263,12 +4805,12 @@ class AppGerberEditor(QtCore.QObject): log.debug("AppGerberEditor.on_scale()") try: - scale_factor = float(self.scale_factor_entry.get_value()) + scale_factor = float(self.ui.scale_factor_entry.get_value()) except ValueError: # try to convert comma to decimal point. if it's still not working error message and return try: - scale_factor = float(self.scale_factor_entry.get_value().replace(',', '.')) - self.scale_factor_entry.set_value(scale_factor) + scale_factor = float(self.ui.scale_factor_entry.get_value().replace(',', '.')) + self.ui.scale_factor_entry.set_value(scale_factor) except ValueError: self.app.inform.emit('[WARNING_NOTCL] %s' % _("Scale factor value is missing or wrong format. Add it and retry.")) @@ -5301,14 +4843,14 @@ class AppGerberEditor(QtCore.QObject): else: return geom_el - if not self.apertures_table.selectedItems(): + if not self.ui.apertures_table.selectedItems(): self.app.inform.emit('[WARNING_NOTCL] %s' % _("No aperture to scale. Select at least one aperture and try again.")) return - for x in self.apertures_table.selectedItems(): + for x in self.ui.apertures_table.selectedItems(): try: - apcode = self.apertures_table.item(x.row(), 1).text() + apcode = self.ui.apertures_table.item(x.row(), 1).text() temp_storage = deepcopy(scale_recursion(self.storage_dict[apcode]['geometry'], self.selected)) self.storage_dict[apcode]['geometry'] = [] @@ -5335,12 +4877,12 @@ class AppGerberEditor(QtCore.QObject): if 'solid' in geo_el.geo: area = geo_el.geo['solid'].area try: - upper_threshold_val = self.ma_upper_threshold_entry.get_value() + upper_threshold_val = self.ui.ma_upper_threshold_entry.get_value() except Exception: return try: - lower_threshold_val = self.ma_lower_threshold_entry.get_value() + lower_threshold_val = self.ui.ma_lower_threshold_entry.get_value() except Exception: lower_threshold_val = 0.0 @@ -5382,20 +4924,497 @@ class AppGerberEditor(QtCore.QObject): # self.app.ui.notebook.setTabText(2, _("Tools")) try: if tool_name == 'all': - self.apertures_frame.hide() + self.ui.apertures_frame.hide() if tool_name == 'select': - self.apertures_frame.show() + self.ui.apertures_frame.show() if tool_name == 'buffer' or tool_name == 'all': - self.buffer_tool_frame.hide() + self.ui.buffer_tool_frame.hide() if tool_name == 'scale' or tool_name == 'all': - self.scale_tool_frame.hide() + self.ui.scale_tool_frame.hide() if tool_name == 'markarea' or tool_name == 'all': - self.ma_tool_frame.hide() + self.ui.ma_tool_frame.hide() except Exception as e: log.debug("AppGerberEditor.hide_tool() --> %s" % str(e)) self.app.ui.notebook.setCurrentWidget(self.app.ui.properties_tab) +class AppGerberEditorUI: + def __init__(self, app): + self.app = app + + # Number of decimals used by tools in this class + self.decimals = self.app.decimals + + # ## Current application units in Upper Case + self.units = self.app.defaults['units'].upper() + + self.grb_edit_widget = QtWidgets.QWidget() + + layout = QtWidgets.QVBoxLayout() + self.grb_edit_widget.setLayout(layout) + + # Page Title box (spacing between children) + self.title_box = QtWidgets.QHBoxLayout() + layout.addLayout(self.title_box) + + # Page Title icon + pixmap = QtGui.QPixmap(self.app.resource_location + '/flatcam_icon32.png') + self.icon = QtWidgets.QLabel() + self.icon.setPixmap(pixmap) + self.title_box.addWidget(self.icon, stretch=0) + + # Title label + self.title_label = QtWidgets.QLabel("%s" % _('Gerber Editor')) + self.title_label.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter) + self.title_box.addWidget(self.title_label, stretch=1) + + # Object name + self.name_box = QtWidgets.QHBoxLayout() + layout.addLayout(self.name_box) + name_label = QtWidgets.QLabel(_("Name:")) + self.name_box.addWidget(name_label) + self.name_entry = FCEntry() + self.name_box.addWidget(self.name_entry) + + # Box for custom widgets + # This gets populated in offspring implementations. + self.custom_box = QtWidgets.QVBoxLayout() + layout.addLayout(self.custom_box) + + # ######################### + # ### Gerber Apertures #### + # ######################### + self.apertures_table_label = QtWidgets.QLabel('%s:' % _('Apertures')) + self.apertures_table_label.setToolTip( + _("Apertures Table for the Gerber Object.") + ) + self.custom_box.addWidget(self.apertures_table_label) + + self.apertures_table = FCTable() + # delegate = SpinBoxDelegate(units=self.units) + # self.apertures_table.setItemDelegateForColumn(1, delegate) + + self.custom_box.addWidget(self.apertures_table) + + self.apertures_table.setColumnCount(5) + self.apertures_table.setHorizontalHeaderLabels(['#', _('Code'), _('Type'), _('Size'), _('Dim')]) + self.apertures_table.setSortingEnabled(False) + self.apertures_table.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectRows) + + self.apertures_table.horizontalHeaderItem(0).setToolTip( + _("Index")) + self.apertures_table.horizontalHeaderItem(1).setToolTip( + _("Aperture Code")) + self.apertures_table.horizontalHeaderItem(2).setToolTip( + _("Type of aperture: circular, rectangle, macros etc")) + self.apertures_table.horizontalHeaderItem(4).setToolTip( + _("Aperture Size:")) + self.apertures_table.horizontalHeaderItem(4).setToolTip( + _("Aperture Dimensions:\n" + " - (width, height) for R, O type.\n" + " - (dia, nVertices) for P type")) + + self.empty_label = QtWidgets.QLabel('') + self.custom_box.addWidget(self.empty_label) + + # add a frame and inside add a vertical box layout. Inside this vbox layout I add all the Apertures widgets + # this way I can hide/show the frame + self.apertures_frame = QtWidgets.QFrame() + self.apertures_frame.setContentsMargins(0, 0, 0, 0) + self.custom_box.addWidget(self.apertures_frame) + self.apertures_box = QtWidgets.QVBoxLayout() + self.apertures_box.setContentsMargins(0, 0, 0, 0) + self.apertures_frame.setLayout(self.apertures_box) + + # # ## Add/Delete an new Aperture ## ## + + grid1 = QtWidgets.QGridLayout() + self.apertures_box.addLayout(grid1) + grid1.setColumnStretch(0, 0) + grid1.setColumnStretch(1, 1) + + apcode_lbl = QtWidgets.QLabel('%s:' % _('Aperture Code')) + apcode_lbl.setToolTip(_("Code for the new aperture")) + grid1.addWidget(apcode_lbl, 1, 0) + + self.apcode_entry = FCSpinner() + self.apcode_entry.set_range(0, 999) + self.apcode_entry.setWrapping(True) + + grid1.addWidget(self.apcode_entry, 1, 1) + + apsize_lbl = QtWidgets.QLabel('%s' % _('Aperture Size:')) + apsize_lbl.setToolTip( + _("Size for the new aperture.\n" + "If aperture type is 'R' or 'O' then\n" + "this value is automatically\n" + "calculated as:\n" + "sqrt(width**2 + height**2)") + ) + grid1.addWidget(apsize_lbl, 2, 0) + + self.apsize_entry = FCDoubleSpinner() + self.apsize_entry.set_precision(self.decimals) + self.apsize_entry.set_range(0.0, 9999) + + grid1.addWidget(self.apsize_entry, 2, 1) + + aptype_lbl = QtWidgets.QLabel('%s:' % _('Aperture Type')) + aptype_lbl.setToolTip( + _("Select the type of new aperture. Can be:\n" + "C = circular\n" + "R = rectangular\n" + "O = oblong") + ) + grid1.addWidget(aptype_lbl, 3, 0) + + self.aptype_cb = FCComboBox() + self.aptype_cb.addItems(['C', 'R', 'O']) + grid1.addWidget(self.aptype_cb, 3, 1) + + self.apdim_lbl = QtWidgets.QLabel('%s:' % _('Aperture Dim')) + self.apdim_lbl.setToolTip( + _("Dimensions for the new aperture.\n" + "Active only for rectangular apertures (type R).\n" + "The format is (width, height)") + ) + grid1.addWidget(self.apdim_lbl, 4, 0) + + self.apdim_entry = EvalEntry2() + grid1.addWidget(self.apdim_entry, 4, 1) + + apadd_del_lbl = QtWidgets.QLabel('%s:' % _('Add/Delete Aperture')) + apadd_del_lbl.setToolTip( + _("Add/Delete an aperture in the aperture table") + ) + self.apertures_box.addWidget(apadd_del_lbl) + + hlay_ad = QtWidgets.QHBoxLayout() + self.apertures_box.addLayout(hlay_ad) + + self.addaperture_btn = QtWidgets.QPushButton(_('Add')) + self.addaperture_btn.setToolTip( + _("Add a new aperture to the aperture list.") + ) + + self.delaperture_btn = QtWidgets.QPushButton(_('Delete')) + self.delaperture_btn.setToolTip( + _("Delete a aperture in the aperture list") + ) + hlay_ad.addWidget(self.addaperture_btn) + hlay_ad.addWidget(self.delaperture_btn) + + # ################### + # ### BUFFER TOOL ### + # ################### + self.buffer_tool_frame = QtWidgets.QFrame() + self.buffer_tool_frame.setContentsMargins(0, 0, 0, 0) + self.custom_box.addWidget(self.buffer_tool_frame) + self.buffer_tools_box = QtWidgets.QVBoxLayout() + self.buffer_tools_box.setContentsMargins(0, 0, 0, 0) + self.buffer_tool_frame.setLayout(self.buffer_tools_box) + self.buffer_tool_frame.hide() + + # Title + buf_title_lbl = QtWidgets.QLabel('%s:' % _('Buffer Aperture')) + buf_title_lbl.setToolTip( + _("Buffer a aperture in the aperture list") + ) + self.buffer_tools_box.addWidget(buf_title_lbl) + + # Form Layout + buf_form_layout = QtWidgets.QFormLayout() + self.buffer_tools_box.addLayout(buf_form_layout) + + # Buffer distance + self.buffer_distance_entry = FCDoubleSpinner() + self.buffer_distance_entry.set_precision(self.decimals) + self.buffer_distance_entry.set_range(-10000.0000, 10000.0000) + + buf_form_layout.addRow('%s:' % _("Buffer distance"), self.buffer_distance_entry) + self.buffer_corner_lbl = QtWidgets.QLabel('%s:' % _("Buffer corner")) + self.buffer_corner_lbl.setToolTip( + _("There are 3 types of corners:\n" + " - 'Round': the corner is rounded.\n" + " - 'Square': the corner is met in a sharp angle.\n" + " - 'Beveled': the corner is a line that directly connects the features meeting in the corner") + ) + self.buffer_corner_cb = FCComboBox() + self.buffer_corner_cb.addItem(_("Round")) + self.buffer_corner_cb.addItem(_("Square")) + self.buffer_corner_cb.addItem(_("Beveled")) + buf_form_layout.addRow(self.buffer_corner_lbl, self.buffer_corner_cb) + + # Buttons + hlay_buf = QtWidgets.QHBoxLayout() + self.buffer_tools_box.addLayout(hlay_buf) + + self.buffer_button = QtWidgets.QPushButton(_("Buffer")) + hlay_buf.addWidget(self.buffer_button) + + # ################## + # ### SCALE TOOL ### + # ################## + self.scale_tool_frame = QtWidgets.QFrame() + self.scale_tool_frame.setContentsMargins(0, 0, 0, 0) + self.custom_box.addWidget(self.scale_tool_frame) + self.scale_tools_box = QtWidgets.QVBoxLayout() + self.scale_tools_box.setContentsMargins(0, 0, 0, 0) + self.scale_tool_frame.setLayout(self.scale_tools_box) + self.scale_tool_frame.hide() + + # Title + scale_title_lbl = QtWidgets.QLabel('%s:' % _('Scale Aperture')) + scale_title_lbl.setToolTip( + _("Scale a aperture in the aperture list") + ) + self.scale_tools_box.addWidget(scale_title_lbl) + + # Form Layout + scale_form_layout = QtWidgets.QFormLayout() + self.scale_tools_box.addLayout(scale_form_layout) + + self.scale_factor_lbl = QtWidgets.QLabel('%s:' % _("Scale factor")) + self.scale_factor_lbl.setToolTip( + _("The factor by which to scale the selected aperture.\n" + "Values can be between 0.0000 and 999.9999") + ) + self.scale_factor_entry = FCDoubleSpinner() + self.scale_factor_entry.set_precision(self.decimals) + self.scale_factor_entry.set_range(0.0000, 10000.0000) + + scale_form_layout.addRow(self.scale_factor_lbl, self.scale_factor_entry) + + # Buttons + hlay_scale = QtWidgets.QHBoxLayout() + self.scale_tools_box.addLayout(hlay_scale) + + self.scale_button = QtWidgets.QPushButton(_("Scale")) + hlay_scale.addWidget(self.scale_button) + + # ###################### + # ### Mark Area TOOL ### + # ###################### + self.ma_tool_frame = QtWidgets.QFrame() + self.ma_tool_frame.setContentsMargins(0, 0, 0, 0) + self.custom_box.addWidget(self.ma_tool_frame) + self.ma_tools_box = QtWidgets.QVBoxLayout() + self.ma_tools_box.setContentsMargins(0, 0, 0, 0) + self.ma_tool_frame.setLayout(self.ma_tools_box) + self.ma_tool_frame.hide() + + # Title + ma_title_lbl = QtWidgets.QLabel('%s:' % _('Mark polygons')) + ma_title_lbl.setToolTip( + _("Mark the polygon areas.") + ) + self.ma_tools_box.addWidget(ma_title_lbl) + + # Form Layout + ma_form_layout = QtWidgets.QFormLayout() + self.ma_tools_box.addLayout(ma_form_layout) + + self.ma_upper_threshold_lbl = QtWidgets.QLabel('%s:' % _("Area UPPER threshold")) + self.ma_upper_threshold_lbl.setToolTip( + _("The threshold value, all areas less than this are marked.\n" + "Can have a value between 0.0000 and 10000.0000") + ) + self.ma_upper_threshold_entry = FCDoubleSpinner() + self.ma_upper_threshold_entry.set_precision(self.decimals) + self.ma_upper_threshold_entry.set_range(0, 10000) + + self.ma_lower_threshold_lbl = QtWidgets.QLabel('%s:' % _("Area LOWER threshold")) + self.ma_lower_threshold_lbl.setToolTip( + _("The threshold value, all areas more than this are marked.\n" + "Can have a value between 0.0000 and 10000.0000") + ) + self.ma_lower_threshold_entry = FCDoubleSpinner() + self.ma_lower_threshold_entry.set_precision(self.decimals) + self.ma_lower_threshold_entry.set_range(0, 10000) + + ma_form_layout.addRow(self.ma_lower_threshold_lbl, self.ma_lower_threshold_entry) + ma_form_layout.addRow(self.ma_upper_threshold_lbl, self.ma_upper_threshold_entry) + + # Buttons + hlay_ma = QtWidgets.QHBoxLayout() + self.ma_tools_box.addLayout(hlay_ma) + + self.ma_threshold_button = QtWidgets.QPushButton(_("Mark")) + self.ma_threshold_button.setToolTip( + _("Mark the polygons that fit within limits.") + ) + hlay_ma.addWidget(self.ma_threshold_button) + + self.ma_delete_button = QtWidgets.QPushButton(_("Delete")) + self.ma_delete_button.setToolTip( + _("Delete all the marked polygons.") + ) + hlay_ma.addWidget(self.ma_delete_button) + + self.ma_clear_button = QtWidgets.QPushButton(_("Clear")) + self.ma_clear_button.setToolTip( + _("Clear all the markings.") + ) + hlay_ma.addWidget(self.ma_clear_button) + + # ###################### + # ### Add Pad Array #### + # ###################### + # add a frame and inside add a vertical box layout. Inside this vbox layout I add + # all the add Pad array widgets + # this way I can hide/show the frame + self.array_frame = QtWidgets.QFrame() + self.array_frame.setContentsMargins(0, 0, 0, 0) + self.custom_box.addWidget(self.array_frame) + self.array_box = QtWidgets.QVBoxLayout() + self.array_box.setContentsMargins(0, 0, 0, 0) + self.array_frame.setLayout(self.array_box) + + self.emptyarray_label = QtWidgets.QLabel('') + self.array_box.addWidget(self.emptyarray_label) + + self.padarray_label = QtWidgets.QLabel('%s' % _("Add Pad Array")) + self.padarray_label.setToolTip( + _("Add an array of pads (linear or circular array)") + ) + self.array_box.addWidget(self.padarray_label) + + self.array_type_combo = FCComboBox() + self.array_type_combo.setToolTip( + _("Select the type of pads array to create.\n" + "It can be Linear X(Y) or Circular") + ) + self.array_type_combo.addItem(_("Linear")) + self.array_type_combo.addItem(_("Circular")) + + self.array_box.addWidget(self.array_type_combo) + + self.array_form = QtWidgets.QFormLayout() + self.array_box.addLayout(self.array_form) + + self.pad_array_size_label = QtWidgets.QLabel('%s:' % _('Nr of pads')) + self.pad_array_size_label.setToolTip( + _("Specify how many pads to be in the array.") + ) + self.pad_array_size_label.setMinimumWidth(100) + + self.pad_array_size_entry = FCSpinner() + self.pad_array_size_entry.set_range(1, 9999) + + self.array_form.addRow(self.pad_array_size_label, self.pad_array_size_entry) + + self.array_linear_frame = QtWidgets.QFrame() + self.array_linear_frame.setContentsMargins(0, 0, 0, 0) + self.array_box.addWidget(self.array_linear_frame) + self.linear_box = QtWidgets.QVBoxLayout() + self.linear_box.setContentsMargins(0, 0, 0, 0) + self.array_linear_frame.setLayout(self.linear_box) + + self.linear_form = QtWidgets.QFormLayout() + self.linear_box.addLayout(self.linear_form) + + self.pad_axis_label = QtWidgets.QLabel('%s:' % _('Direction')) + self.pad_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.pad_axis_label.setMinimumWidth(100) + + self.pad_axis_radio = RadioSet([{'label': _('X'), 'value': 'X'}, + {'label': _('Y'), 'value': 'Y'}, + {'label': _('Angle'), 'value': 'A'}]) + self.pad_axis_radio.set_value('X') + self.linear_form.addRow(self.pad_axis_label, self.pad_axis_radio) + + self.pad_pitch_label = QtWidgets.QLabel('%s:' % _('Pitch')) + self.pad_pitch_label.setToolTip( + _("Pitch = Distance between elements of the array.") + ) + self.pad_pitch_label.setMinimumWidth(100) + + self.pad_pitch_entry = FCDoubleSpinner() + self.pad_pitch_entry.set_precision(self.decimals) + self.pad_pitch_entry.set_range(0.0000, 10000.0000) + self.pad_pitch_entry.setSingleStep(0.1) + + self.linear_form.addRow(self.pad_pitch_label, self.pad_pitch_entry) + + self.linear_angle_label = QtWidgets.QLabel('%s:' % _('Angle')) + self.linear_angle_label.setToolTip( + _("Angle at which the linear array is placed.\n" + "The precision is of max 2 decimals.\n" + "Min value is: -360.00 degrees.\n" + "Max value is: 360.00 degrees.") + ) + self.linear_angle_label.setMinimumWidth(100) + + self.linear_angle_spinner = FCDoubleSpinner() + self.linear_angle_spinner.set_precision(self.decimals) + self.linear_angle_spinner.setRange(-360.00, 360.00) + self.linear_form.addRow(self.linear_angle_label, self.linear_angle_spinner) + + self.array_circular_frame = QtWidgets.QFrame() + self.array_circular_frame.setContentsMargins(0, 0, 0, 0) + self.array_box.addWidget(self.array_circular_frame) + self.circular_box = QtWidgets.QVBoxLayout() + self.circular_box.setContentsMargins(0, 0, 0, 0) + self.array_circular_frame.setLayout(self.circular_box) + + self.pad_direction_label = QtWidgets.QLabel('%s:' % _('Direction')) + self.pad_direction_label.setToolTip( + _("Direction for circular array.\n" + "Can be CW = clockwise or CCW = counter clockwise.") + ) + self.pad_direction_label.setMinimumWidth(100) + + self.circular_form = QtWidgets.QFormLayout() + self.circular_box.addLayout(self.circular_form) + + self.pad_direction_radio = RadioSet([{'label': _('CW'), 'value': 'CW'}, + {'label': _('CCW'), 'value': 'CCW'}]) + self.pad_direction_radio.set_value('CW') + self.circular_form.addRow(self.pad_direction_label, self.pad_direction_radio) + + self.pad_angle_label = QtWidgets.QLabel('%s:' % _('Angle')) + self.pad_angle_label.setToolTip( + _("Angle at which each element in circular array is placed.") + ) + self.pad_angle_label.setMinimumWidth(100) + + self.pad_angle_entry = FCDoubleSpinner() + self.pad_angle_entry.set_precision(self.decimals) + self.pad_angle_entry.set_range(-360.00, 360.00) + self.pad_angle_entry.setSingleStep(0.1) + + self.circular_form.addRow(self.pad_angle_label, self.pad_angle_entry) + + self.array_circular_frame.hide() + + self.linear_angle_spinner.hide() + self.linear_angle_label.hide() + + self.array_frame.hide() + self.custom_box.addStretch() + + layout.addStretch() + + # Editor + self.exit_editor_button = QtWidgets.QPushButton(_('Exit Editor')) + self.exit_editor_button.setIcon(QtGui.QIcon(self.app.resource_location + '/power16.png')) + self.exit_editor_button.setToolTip( + _("Exit from Editor.") + ) + self.exit_editor_button.setStyleSheet(""" + QPushButton + { + font-weight: bold; + } + """) + layout.addWidget(self.exit_editor_button) + + class TransformEditorTool(AppTool): """ Inputs to specify how to paint the selected polygons.