def __init__(self, parent=None): QtWidgets.QDialog.__init__(self) self.setupUi(self) self.canvas = Canvas() self.point_widget = PointWidget(self.canvas, self) self.findChild(QtWidgets.QGroupBox, 'groupBoxPointWidget').layout().addWidget(self.point_widget) self.graphicsView.setScene(self.canvas) self.graphicsView.load_image.connect(self.canvas.load_image) self.graphicsView.region_selected.connect(self.canvas.select_points) self.graphicsView.delete_selection.connect(self.canvas.delete_selected_points) self.graphicsView.relabel_selection.connect(self.canvas.relabel_selected_points) self.graphicsView.toggle_points.connect(self.point_widget.checkBoxDisplayPoints.toggle) self.graphicsView.add_point.connect(self.canvas.add_point) self.canvas.image_loaded.connect(self.graphicsView.image_loaded) # Image data fields self.canvas.image_loaded.connect(self.display_coordinates) self.canvas.image_loaded.connect(self.get_custom_field_data) self.canvas.fields_updated.connect(self.display_custom_fields) self.lineEditX.textEdited.connect(self.update_coordinates) self.lineEditY.textEdited.connect(self.update_coordinates) self.pushButtonAddField.clicked.connect(self.add_field_dialog) self.pushButtonDeleteField.clicked.connect(self.delete_field_dialog)
def __init__(self, parent=None): QtWidgets.QDialog.__init__(self) self.setupUi(self) self.canvas = Canvas() self.point_widget = PointWidget(self.canvas, self) self.findChild(QtWidgets.QFrame, 'framePointWidget').layout().addWidget( self.point_widget) self.point_widget.hide_custom_fields.connect(self.hide_custom_fields) self.up_arrow = QtWidgets.QShortcut( QtGui.QKeySequence(QtCore.Qt.Key_Up), self) self.up_arrow.setContext(QtCore.Qt.WidgetWithChildrenShortcut) self.up_arrow.activated.connect(self.point_widget.previous) self.down_arrow = QtWidgets.QShortcut( QtGui.QKeySequence(QtCore.Qt.Key_Down), self) self.down_arrow.setContext(QtCore.Qt.WidgetWithChildrenShortcut) self.down_arrow.activated.connect(self.point_widget.next) self.graphicsView.setScene(self.canvas) self.graphicsView.drop_complete.connect(self.canvas.load) self.graphicsView.region_selected.connect(self.canvas.select_points) self.graphicsView.delete_selection.connect( self.canvas.delete_selected_points) self.graphicsView.relabel_selection.connect( self.canvas.relabel_selected_points) self.graphicsView.toggle_points.connect( self.point_widget.checkBoxDisplayPoints.toggle) self.graphicsView.toggle_grid.connect( self.point_widget.checkBoxDisplayGrid.toggle) self.graphicsView.switch_class.connect( self.point_widget.set_active_class) self.graphicsView.add_point.connect(self.canvas.add_point) self.canvas.image_loaded.connect(self.graphicsView.image_loaded) self.canvas.directory_set.connect(self.display_working_directory) # Image data fields self.canvas.image_loaded.connect(self.display_coordinates) self.canvas.image_loaded.connect(self.get_custom_field_data) self.canvas.fields_updated.connect(self.display_custom_fields) self.lineEditX.textEdited.connect(self.update_coordinates) self.lineEditY.textEdited.connect(self.update_coordinates) self.pushButtonAddField.clicked.connect(self.add_field_dialog) self.pushButtonDeleteField.clicked.connect(self.delete_field_dialog) self.pushButtonFolder.clicked.connect(self.select_folder) self.pushButtonZoomOut.clicked.connect(self.graphicsView.zoom_out) self.pushButtonZoomIn.clicked.connect(self.graphicsView.zoom_in)
class CentralWidget(QtWidgets.QDialog, CLASS_DIALOG): load_custom_data = QtCore.pyqtSignal(dict) def __init__(self, parent=None): QtWidgets.QDialog.__init__(self) self.setupUi(self) self.canvas = Canvas() self.point_widget = PointWidget(self.canvas, self) self.findChild(QtWidgets.QFrame, 'framePointWidget').layout().addWidget( self.point_widget) self.up_arrow = QtWidgets.QShortcut( QtGui.QKeySequence(QtCore.Qt.Key_Up), self) self.up_arrow.setContext(QtCore.Qt.WidgetWithChildrenShortcut) self.up_arrow.activated.connect(self.point_widget.previous) self.down_arrow = QtWidgets.QShortcut( QtGui.QKeySequence(QtCore.Qt.Key_Down), self) self.down_arrow.setContext(QtCore.Qt.WidgetWithChildrenShortcut) self.down_arrow.activated.connect(self.point_widget.next) self.graphicsView.setScene(self.canvas) self.graphicsView.drop_complete.connect(self.canvas.load) self.graphicsView.region_selected.connect(self.canvas.select_points) self.graphicsView.delete_selection.connect( self.canvas.delete_selected_points) self.graphicsView.relabel_selection.connect( self.canvas.relabel_selected_points) self.graphicsView.toggle_points.connect( self.point_widget.checkBoxDisplayPoints.toggle) self.graphicsView.toggle_grid.connect( self.point_widget.checkBoxDisplayGrid.toggle) self.graphicsView.add_point.connect(self.canvas.add_point) self.canvas.image_loaded.connect(self.graphicsView.image_loaded) self.canvas.directory_set.connect(self.display_working_directory) # Image data fields self.canvas.image_loaded.connect(self.display_coordinates) self.canvas.image_loaded.connect(self.get_custom_field_data) self.canvas.fields_updated.connect(self.display_custom_fields) self.lineEditX.textEdited.connect(self.update_coordinates) self.lineEditY.textEdited.connect(self.update_coordinates) self.pushButtonAddField.clicked.connect(self.add_field_dialog) self.pushButtonDeleteField.clicked.connect(self.delete_field_dialog) def resizeEvent(self, theEvent): self.graphicsView.fitInView(self.canvas.itemsBoundingRect(), QtCore.Qt.KeepAspectRatio) self.graphicsView.setSceneRect(self.canvas.itemsBoundingRect()) # Image data field functions def add_field(self): field_def = (self.field_name.text(), self.field_type.currentText()) field_names = [x[0] for x in self.canvas.custom_fields['fields']] if field_def[0] in field_names: QtWidgets.QMessageBox.warning(self, 'Warning', 'Field name already exists') else: self.canvas.add_custom_field(field_def) self.add_dialog.close() def add_field_dialog(self): self.field_name = QtWidgets.QLineEdit() self.field_type = QtWidgets.QComboBox() self.field_type.addItems(['line', 'box']) self.add_button = QtWidgets.QPushButton('Save') self.add_button.clicked.connect(self.add_field) self.add_dialog = QtWidgets.QDialog(self) self.add_dialog.setWindowTitle('Add Custom Field') self.add_dialog.setLayout(QtWidgets.QVBoxLayout()) self.add_dialog.layout().addWidget(self.field_name) self.add_dialog.layout().addWidget(self.field_type) self.add_dialog.layout().addWidget(self.add_button) self.add_dialog.resize(250, self.add_dialog.height()) self.add_dialog.show() def delete_field(self): self.canvas.delete_custom_field(self.field_list.currentText()) self.delete_dialog.close() def delete_field_dialog(self): self.field_list = QtWidgets.QComboBox() self.field_list.addItems( [x[0] for x in self.canvas.custom_fields['fields']]) self.delete_button = QtWidgets.QPushButton('Delete') self.delete_button.clicked.connect(self.delete_field) self.delete_dialog = QtWidgets.QDialog(self) self.delete_dialog.setWindowTitle('Delete Custom Field') self.delete_dialog.setLayout(QtWidgets.QVBoxLayout()) self.delete_dialog.layout().addWidget(self.field_list) self.delete_dialog.layout().addWidget(self.delete_button) self.delete_dialog.resize(250, self.delete_dialog.height()) self.delete_dialog.show() def display_coordinates(self, directory, image): if image in self.canvas.coordinates: self.lineEditX.setText(self.canvas.coordinates[image]['x']) self.lineEditY.setText(self.canvas.coordinates[image]['y']) else: self.lineEditX.setText('') self.lineEditY.setText('') def display_custom_fields(self, fields): def build(item): container = QtWidgets.QGroupBox(item[0], self) container.setObjectName(item[0]) container.setLayout(QtWidgets.QVBoxLayout()) if item[1].lower() == 'line': edit = LineText(container) else: edit = BoxText(container) edit.update.connect(self.canvas.save_custom_field_data) self.load_custom_data.connect(edit.load_data) container.layout().addWidget(edit) return container custom_fields = self.findChild(QtWidgets.QFrame, 'frameCustomFields') if custom_fields.layout() is None: custom_fields.setLayout(QtWidgets.QVBoxLayout()) else: layout = custom_fields.layout() while layout.count(): child = layout.takeAt(0) if child.widget(): child.widget().deleteLater() for item in fields: widget = build(item) custom_fields.layout().addWidget(widget) v = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) custom_fields.layout().addItem(v) self.get_custom_field_data() def display_working_directory(self, directory): self.labelWorkingDirectory.setText(directory) def get_custom_field_data(self): self.load_custom_data.emit(self.canvas.get_custom_field_data()) def update_coordinates(self, text): x = self.lineEditX.text() y = self.lineEditY.text() self.canvas.save_coordinates(x, y)
def __init__(self, parent=None): QtWidgets.QDialog.__init__(self) self.setupUi(self) self.canvas = Canvas() self.point_widget = PointWidget(self.canvas, self) self.findChild(QtWidgets.QFrame, 'framePointWidget').layout().addWidget( self.point_widget) self.point_widget.hide_custom_fields.connect(self.hide_custom_fields) self.point_widget.saving.connect(self.display_quick_save) # Set up keyboard shortcuts self.save_shortcut = QtGui.QShortcut( QtGui.QKeySequence(self.tr("Ctrl+S")), self) # quick save using Ctrl+S self.save_shortcut.setContext( QtCore.Qt.ShortcutContext.WidgetWithChildrenShortcut) self.save_shortcut.activated.connect(self.point_widget.quick_save) self.up_arrow = QtGui.QShortcut( QtGui.QKeySequence(QtCore.Qt.Key.Key_Up), self) self.up_arrow.setContext( QtCore.Qt.ShortcutContext.WidgetWithChildrenShortcut) self.up_arrow.activated.connect(self.point_widget.previous) self.down_arrow = QtGui.QShortcut( QtGui.QKeySequence(QtCore.Qt.Key.Key_Down), self) self.down_arrow.setContext( QtCore.Qt.ShortcutContext.WidgetWithChildrenShortcut) self.down_arrow.activated.connect(self.point_widget.next) # same as arrows but conventient for right handed people self.up_arrow = QtGui.QShortcut(QtGui.QKeySequence(self.tr("W")), self) self.up_arrow.setContext( QtCore.Qt.ShortcutContext.WidgetWithChildrenShortcut) self.up_arrow.activated.connect(self.point_widget.previous) self.down_arrow = QtGui.QShortcut(QtGui.QKeySequence(self.tr("S")), self) self.down_arrow.setContext( QtCore.Qt.ShortcutContext.WidgetWithChildrenShortcut) self.down_arrow.activated.connect(self.point_widget.next) # Make signal slot connections self.graphicsView.setScene(self.canvas) self.graphicsView.drop_complete.connect(self.canvas.load) self.graphicsView.region_selected.connect(self.canvas.select_points) self.graphicsView.delete_selection.connect( self.canvas.delete_selected_points) self.graphicsView.relabel_selection.connect( self.canvas.relabel_selected_points) self.graphicsView.toggle_points.connect( self.point_widget.checkBoxDisplayPoints.toggle) self.graphicsView.toggle_grid.connect( self.point_widget.checkBoxDisplayGrid.toggle) self.graphicsView.switch_class.connect( self.point_widget.set_active_class) self.graphicsView.add_point.connect(self.canvas.add_point) self.canvas.image_loaded.connect(self.graphicsView.image_loaded) self.canvas.directory_set.connect(self.display_working_directory) # Image data fields self.canvas.image_loaded.connect(self.display_coordinates) self.canvas.image_loaded.connect(self.get_custom_field_data) self.canvas.fields_updated.connect(self.display_custom_fields) self.lineEditX.textEdited.connect(self.update_coordinates) self.lineEditY.textEdited.connect(self.update_coordinates) # Buttons self.pushButtonAddField.clicked.connect(self.add_field_dialog) self.pushButtonDeleteField.clicked.connect(self.delete_field_dialog) self.pushButtonFolder.clicked.connect(self.select_folder) self.pushButtonZoomOut.clicked.connect(self.graphicsView.zoom_out) self.pushButtonZoomIn.clicked.connect(self.graphicsView.zoom_in) # Fix icons since no QRC file integration self.pushButtonFolder.setIcon(QtGui.QIcon('icons:folder.svg')) self.pushButtonZoomIn.setIcon(QtGui.QIcon('icons:zoom_in.svg')) self.pushButtonZoomOut.setIcon(QtGui.QIcon('icons:zoom_out.svg')) self.pushButtonDeleteField.setIcon(QtGui.QIcon('icons:delete.svg')) self.pushButtonAddField.setIcon(QtGui.QIcon('icons:add.svg')) self.quick_save_frame = QtWidgets.QFrame(self.graphicsView) self.quick_save_frame.setStyleSheet( "QFrame { background: #4caf50;color: #FFF;font-weight: bold}") self.quick_save_frame.setLayout(QtWidgets.QHBoxLayout()) self.quick_save_frame.layout().addWidget(QtWidgets.QLabel('Saving...')) self.quick_save_frame.setGeometry(3, 3, 100, 35) self.quick_save_frame.hide()
class CentralWidget(QtWidgets.QDialog, CLASS_DIALOG): load_custom_data = QtCore.pyqtSignal(dict) def __init__(self, parent=None): QtWidgets.QDialog.__init__(self) self.setupUi(self) self.canvas = Canvas() self.point_widget = PointWidget(self.canvas, self) self.findChild(QtWidgets.QFrame, 'framePointWidget').layout().addWidget( self.point_widget) self.point_widget.hide_custom_fields.connect(self.hide_custom_fields) self.point_widget.saving.connect(self.display_quick_save) # Set up keyboard shortcuts self.save_shortcut = QtGui.QShortcut( QtGui.QKeySequence(self.tr("Ctrl+S")), self) # quick save using Ctrl+S self.save_shortcut.setContext( QtCore.Qt.ShortcutContext.WidgetWithChildrenShortcut) self.save_shortcut.activated.connect(self.point_widget.quick_save) self.up_arrow = QtGui.QShortcut( QtGui.QKeySequence(QtCore.Qt.Key.Key_Up), self) self.up_arrow.setContext( QtCore.Qt.ShortcutContext.WidgetWithChildrenShortcut) self.up_arrow.activated.connect(self.point_widget.previous) self.down_arrow = QtGui.QShortcut( QtGui.QKeySequence(QtCore.Qt.Key.Key_Down), self) self.down_arrow.setContext( QtCore.Qt.ShortcutContext.WidgetWithChildrenShortcut) self.down_arrow.activated.connect(self.point_widget.next) # same as arrows but conventient for right handed people self.up_arrow = QtGui.QShortcut(QtGui.QKeySequence(self.tr("W")), self) self.up_arrow.setContext( QtCore.Qt.ShortcutContext.WidgetWithChildrenShortcut) self.up_arrow.activated.connect(self.point_widget.previous) self.down_arrow = QtGui.QShortcut(QtGui.QKeySequence(self.tr("S")), self) self.down_arrow.setContext( QtCore.Qt.ShortcutContext.WidgetWithChildrenShortcut) self.down_arrow.activated.connect(self.point_widget.next) # Make signal slot connections self.graphicsView.setScene(self.canvas) self.graphicsView.drop_complete.connect(self.canvas.load) self.graphicsView.region_selected.connect(self.canvas.select_points) self.graphicsView.delete_selection.connect( self.canvas.delete_selected_points) self.graphicsView.relabel_selection.connect( self.canvas.relabel_selected_points) self.graphicsView.toggle_points.connect( self.point_widget.checkBoxDisplayPoints.toggle) self.graphicsView.toggle_grid.connect( self.point_widget.checkBoxDisplayGrid.toggle) self.graphicsView.switch_class.connect( self.point_widget.set_active_class) self.graphicsView.add_point.connect(self.canvas.add_point) self.canvas.image_loaded.connect(self.graphicsView.image_loaded) self.canvas.directory_set.connect(self.display_working_directory) # Image data fields self.canvas.image_loaded.connect(self.display_coordinates) self.canvas.image_loaded.connect(self.get_custom_field_data) self.canvas.fields_updated.connect(self.display_custom_fields) self.lineEditX.textEdited.connect(self.update_coordinates) self.lineEditY.textEdited.connect(self.update_coordinates) # Buttons self.pushButtonAddField.clicked.connect(self.add_field_dialog) self.pushButtonDeleteField.clicked.connect(self.delete_field_dialog) self.pushButtonFolder.clicked.connect(self.select_folder) self.pushButtonZoomOut.clicked.connect(self.graphicsView.zoom_out) self.pushButtonZoomIn.clicked.connect(self.graphicsView.zoom_in) # Fix icons since no QRC file integration self.pushButtonFolder.setIcon(QtGui.QIcon('icons:folder.svg')) self.pushButtonZoomIn.setIcon(QtGui.QIcon('icons:zoom_in.svg')) self.pushButtonZoomOut.setIcon(QtGui.QIcon('icons:zoom_out.svg')) self.pushButtonDeleteField.setIcon(QtGui.QIcon('icons:delete.svg')) self.pushButtonAddField.setIcon(QtGui.QIcon('icons:add.svg')) self.quick_save_frame = QtWidgets.QFrame(self.graphicsView) self.quick_save_frame.setStyleSheet( "QFrame { background: #4caf50;color: #FFF;font-weight: bold}") self.quick_save_frame.setLayout(QtWidgets.QHBoxLayout()) self.quick_save_frame.layout().addWidget(QtWidgets.QLabel('Saving...')) self.quick_save_frame.setGeometry(3, 3, 100, 35) self.quick_save_frame.hide() def resizeEvent(self, theEvent): self.graphicsView.resize_image() # Image data field functions def add_field(self): field_def = (self.field_name.text(), self.field_type.currentText()) field_names = [x[0] for x in self.canvas.custom_fields['fields']] if field_def[0] in field_names: QtWidgets.QMessageBox.warning(self, 'Warning', 'Field name already exists') else: self.canvas.add_custom_field(field_def) self.add_dialog.close() def add_field_dialog(self): self.field_name = QtWidgets.QLineEdit() self.field_type = QtWidgets.QComboBox() self.field_type.addItems(['line', 'box']) self.add_button = QtWidgets.QPushButton('Save') self.add_button.clicked.connect(self.add_field) self.add_dialog = QtWidgets.QDialog(self) self.add_dialog.setWindowTitle('Add Custom Field') self.add_dialog.setLayout(QtWidgets.QVBoxLayout()) self.add_dialog.layout().addWidget(self.field_name) self.add_dialog.layout().addWidget(self.field_type) self.add_dialog.layout().addWidget(self.add_button) self.add_dialog.resize(250, self.add_dialog.height()) self.add_dialog.show() def delete_field(self): self.canvas.delete_custom_field(self.field_list.currentText()) self.delete_dialog.close() def delete_field_dialog(self): self.field_list = QtWidgets.QComboBox() self.field_list.addItems( [x[0] for x in self.canvas.custom_fields['fields']]) self.delete_button = QtWidgets.QPushButton('Delete') self.delete_button.clicked.connect(self.delete_field) self.delete_dialog = QtWidgets.QDialog(self) self.delete_dialog.setWindowTitle('Delete Custom Field') self.delete_dialog.setLayout(QtWidgets.QVBoxLayout()) self.delete_dialog.layout().addWidget(self.field_list) self.delete_dialog.layout().addWidget(self.delete_button) self.delete_dialog.resize(250, self.delete_dialog.height()) self.delete_dialog.show() def display_coordinates(self, directory, image): if image in self.canvas.coordinates: self.lineEditX.setText(self.canvas.coordinates[image]['x']) self.lineEditY.setText(self.canvas.coordinates[image]['y']) else: self.lineEditX.setText('') self.lineEditY.setText('') def display_custom_fields(self, fields): def build(item): container = QtWidgets.QGroupBox(item[0], self) container.setObjectName(item[0]) container.setLayout(QtWidgets.QVBoxLayout()) if item[1].lower() == 'line': edit = LineText(container) else: edit = BoxText(container) edit.update.connect(self.canvas.save_custom_field_data) self.load_custom_data.connect(edit.load_data) container.layout().addWidget(edit) return container custom_fields = self.findChild(QtWidgets.QFrame, 'frameCustomFields') if custom_fields.layout() is None: custom_fields.setLayout(QtWidgets.QVBoxLayout()) else: layout = custom_fields.layout() while layout.count(): child = layout.takeAt(0) if child.widget(): child.widget().deleteLater() for item in fields: widget = build(item) custom_fields.layout().addWidget(widget) v = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Policy.Minimum, QtWidgets.QSizePolicy.Policy.Expanding) custom_fields.layout().addItem(v) self.get_custom_field_data() def display_working_directory(self, directory): self.labelWorkingDirectory.setText(directory) def display_quick_save(self): self.quick_save_frame.show() QtCore.QTimer.singleShot(500, self.quick_save_frame.hide) def get_custom_field_data(self): self.load_custom_data.emit(self.canvas.get_custom_field_data()) def hide_custom_fields(self, hide): if hide is True: self.frameCustomField.hide() else: self.frameCustomField.show() def select_folder(self): name = QtWidgets.QFileDialog.getExistingDirectory( self, 'Select image folder', self.canvas.directory) if name != '': self.canvas.load([QtCore.QUrl('file:{}'.format(name))]) def update_coordinates(self, text): x = self.lineEditX.text() y = self.lineEditY.text() self.canvas.save_coordinates(x, y)
def __init__(self, parent=None): from functools import partial _translate = QtCore.QCoreApplication.translate QtWidgets.QDialog.__init__(self) self.setupUi(self) self.canvas = Canvas() self.point_widget = PointWidget(self.canvas, self) self.findChild(QtWidgets.QFrame, 'framePointWidget').layout().addWidget( self.point_widget) self.point_widget.hide_custom_fields.connect(self.hide_custom_fields) self.point_widget.saving.connect(self.display_quick_save) self.point_widget.class_selection_changed.connect( self.display_attributes) self.point_widget.lineEditSurveyId.textEdited.connect( self.set_survey_id) self.save_shortcut = QtWidgets.QShortcut( QtGui.QKeySequence(self.tr("Ctrl+S")), self) # quick save using Ctrl+S self.save_shortcut.setContext(QtCore.Qt.WidgetWithChildrenShortcut) self.save_shortcut.activated.connect(self.point_widget.quick_save) self.graphicsView.setScene(self.canvas) self.graphicsView.drop_complete.connect(self.canvas.load) self.graphicsView.region_selected.connect(self.canvas.select) self.graphicsView.delete_selection.connect( self.canvas.delete_selection) self.graphicsView.clear_selection.connect(self.canvas.clear_selection) self.graphicsView.relabel_selection.connect( self.canvas.relabel_selection) self.graphicsView.measure_area.connect(self.canvas.measure_area) self.graphicsView.toggle_points.connect( self.point_widget.checkBoxDisplayPoints.toggle) self.graphicsView.toggle_grid.connect( self.point_widget.checkBoxDisplayGrid.toggle) self.graphicsView.scale_selected.connect(self.set_scale) self.graphicsView.select_class.connect( self.point_widget.select_tree_item_from_name) self.graphicsView.add_class.connect( lambda: self.point_widget.add_class(askname=False)) self.graphicsView.search.connect(self.search) self.canvas.edit_style_selected.connect( self.graphicsView._set_edit_style) self.graphicsView.add_point.connect(self.canvas.add_point) self.graphicsView.display_pointer_coordinates.connect( self.display_pointer_coordinates) self.graphicsView.find_point.connect(self.find_point) self.canvas.image_loaded.connect(self.graphicsView.image_loaded) self.canvas.directory_set.connect(self.display_working_directory) self.canvas.rect_size_changed.connect( self.update_component_size_from_canvas) # Image data fields self.canvas.image_loaded.connect(self.display_coordinates) self.canvas.image_loaded.connect(self.display_attributes) self.canvas.fields_updated.connect(self.display_attributes) self.dataLineEditsNames = [ "lineEdit_ecu", "lineEdit_pcb", "comboBox_pos", "lineEditX", "lineEditY" ] pcbAttr = ["ECU Name", "PCB Name", "Side", "Length", "Width"] self.attribute_widget_names = [ "comboBox_manufacturer", "lineEdit_partnumber", "comboBox_family", "lineEdit_description", "lineEdit_specifications", "comboBox_package", "lineEdit_pincount", "lineEdit_marking", "lineEdit_diameter", "lineEdit_length", "lineEdit_width", "lineEdit_height", "break", "comboBox_placement", "comboBox_metrik", "lineEdit_Researchprice", "lineEdit_Researchvol", "lineEdit_ResearchSource", "lineEdit_stdRef" ] self.attribute_names = [ "Manufacturer", "Mfr. Partnumber", "Component Family", "Description", "Specifications", "Package", "Pin Count", "Marking", "Diameter", "Length", "Width", "Height", "Costing", "Placement", "Metrik", "Research Price [$]", "Research Volume [k]", "Research Source", "Std. Comp. Reference" ] value_types = { "Diameter": "float", "Length": "float", "Width": "float", "Height": "float", "Research Price [$]": "float", "Research Volume [k]": "float" } for i, k in enumerate(self.dataLineEditsNames): box = self.groupBoxImageData layout = self.gridLayout_2 if "line" in k: widget = LineEdit(box, available_actions=["Copy", "Paste"]) widget.setContextMenuPolicy(QtCore.Qt.CustomContextMenu) widget.setAcceptDrops(False) widget.setObjectName(k) widget.setDisabled(True) widget.returnPressed.connect(self.cycle_edits) if "X" in k or "Y" in k: widget.textEdited.connect(self.update_pcb_info) else: widget.returnPressed.connect(self.update_ecu_name) else: widget = QtWidgets.QComboBox() widget.addItems(["Top", "Bottom"]) widget.setDisabled(True) widget.setCurrentIndex(0) widget.activated.connect(self.update_ecu_name) layout.addWidget(widget, i, 1, 1, 1) label = QtWidgets.QLabel(box) sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Preferred) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth( label.sizePolicy().hasHeightForWidth()) label.setSizePolicy(sizePolicy) label.setText(_translate("CentralWidget", pcbAttr[i])) layout.addWidget(label, i, 0, 1, 1) setattr(self, k, widget) self.attribute_widgets = {} for i, k in enumerate(self.attribute_widget_names): box = self.groupBoxCustomFields layout = self.gridLayout if "line" in k: value_type = value_types.get(self.attribute_names[i], "string") widget = LineEdit(box, value_type=value_type) widget.setContextMenuPolicy(QtCore.Qt.CustomContextMenu) widget.setAcceptDrops(False) widget.setObjectName(k) widget.setDisabled(True) widget.textEdited.connect( partial(self.update_attributes, name=k)) widget.returnPressed.connect(self.cycle_edits) widget.copy_all_signal.connect(self.copy_all_attributes) widget.paste_all_signal.connect(self.paste_all_attributes) widget.setFrame(False) elif "combo" in k: widget = QtWidgets.QComboBox(box) widget.setDisabled(True) widget.setObjectName(k) widget.setLineEdit(LineEdit()) widget.currentTextChanged.connect( partial(self.update_attributes, name=k)) widget.currentIndexChanged.connect( partial(self.update_attributes, name=k)) widget.lineEdit().textEdited.connect( partial(self.update_attributes, name=k)) widget.lineEdit().returnPressed.connect(self.cycle_edits) widget.lineEdit().copy_all_signal.connect( self.copy_all_attributes) widget.lineEdit().paste_all_signal.connect( self.paste_all_attributes) widget.setFrame(False) elif k == "break": widget = QtWidgets.QFrame(box) widget.setFrameShape(QtWidgets.QFrame.HLine) # layout.addWidget(line, i, 1, 1, 1) # continue layout.addWidget(widget, i, 1, 1, 1) label = QtWidgets.QLabel(box) sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Preferred) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth( label.sizePolicy().hasHeightForWidth()) label.setSizePolicy(sizePolicy) if k != "break": label.setText( _translate("CentralWidget", self.attribute_names[i])) else: label.setText("<b>" + self.attribute_names[i] + "</b>") layout.addWidget(label, i, 0, 1, 1) self.attribute_widgets[self.attribute_names[i]] = widget setattr(self, k, widget) setattr( self, k.replace("lineEdit", "label").replace("comboBox", "label"), label) self.info_widgets = self.dataLineEditsNames.copy() self.info_widgets.extend(self.attribute_widget_names) self.set_tool_tips() package_completer = QtWidgets.QCompleter(completion.packages) package_completer.setCaseSensitivity(QtCore.Qt.CaseInsensitive) self.comboBox_package.lineEdit().setCompleter(package_completer) self.comboBox_package.addItems(completion.packages) self.comboBox_package.setCurrentText("") package_completer.setCompletionMode( QtWidgets.QCompleter.PopupCompletion) manufacturer_completer = QtWidgets.QCompleter(completion.manufacturers) manufacturer_completer.setCaseSensitivity(QtCore.Qt.CaseInsensitive) self.comboBox_manufacturer.lineEdit().setCompleter( manufacturer_completer) self.comboBox_manufacturer.addItems(completion.manufacturers) self.comboBox_manufacturer.setCurrentText("") manufacturer_completer.setCompletionMode( QtWidgets.QCompleter.PopupCompletion) metrik_completer = QtWidgets.QCompleter(completion.metriks) metrik_completer.setCaseSensitivity(QtCore.Qt.CaseInsensitive) self.comboBox_metrik.lineEdit().setCompleter(metrik_completer) self.comboBox_metrik.addItems(completion.metriks) self.comboBox_metrik.setCurrentText("") metrik_completer.setCompletionMode( QtWidgets.QCompleter.PopupCompletion) placement_list = list(sorted(completion.placement)) placement_completer = QtWidgets.QCompleter(sorted(placement_list)) placement_completer.setCaseSensitivity(QtCore.Qt.CaseInsensitive) self.comboBox_placement.lineEdit().setCompleter(placement_completer) self.comboBox_placement.addItems(placement_list) self.comboBox_placement.setCurrentText("") placement_completer.setCompletionMode( QtWidgets.QCompleter.PopupCompletion) # self.pushButtonFolder.clicked.connect(self.select_folder) self.pushButtonZoomOut.clicked.connect(self.graphicsView.zoom_out) self.pushButtonZoomIn.clicked.connect(self.graphicsView.zoom_in) self.quick_save_frame = QtWidgets.QFrame(self.graphicsView) self.quick_save_frame.setStyleSheet( "QFrame { background: #4caf50;color: #FFF;font-weight: bold}") self.quick_save_frame.setLayout(QtWidgets.QHBoxLayout()) self.quick_save_frame.layout().addWidget(QtWidgets.QLabel('Saving...')) self.quick_save_frame.setGeometry(3, 3, 100, 35) self.quick_save_frame.hide() # add toolbar self.toolBar = QtWidgets.QToolBar() self.toolLayout.addWidget(self.toolBar) self.toolButtons = []
class CentralWidget(QtWidgets.QDialog, CLASS_DIALOG): def __init__(self, parent=None): from functools import partial _translate = QtCore.QCoreApplication.translate QtWidgets.QDialog.__init__(self) self.setupUi(self) self.canvas = Canvas() self.point_widget = PointWidget(self.canvas, self) self.findChild(QtWidgets.QFrame, 'framePointWidget').layout().addWidget( self.point_widget) self.point_widget.hide_custom_fields.connect(self.hide_custom_fields) self.point_widget.saving.connect(self.display_quick_save) self.point_widget.class_selection_changed.connect( self.display_attributes) self.point_widget.lineEditSurveyId.textEdited.connect( self.set_survey_id) self.save_shortcut = QtWidgets.QShortcut( QtGui.QKeySequence(self.tr("Ctrl+S")), self) # quick save using Ctrl+S self.save_shortcut.setContext(QtCore.Qt.WidgetWithChildrenShortcut) self.save_shortcut.activated.connect(self.point_widget.quick_save) self.graphicsView.setScene(self.canvas) self.graphicsView.drop_complete.connect(self.canvas.load) self.graphicsView.region_selected.connect(self.canvas.select) self.graphicsView.delete_selection.connect( self.canvas.delete_selection) self.graphicsView.clear_selection.connect(self.canvas.clear_selection) self.graphicsView.relabel_selection.connect( self.canvas.relabel_selection) self.graphicsView.measure_area.connect(self.canvas.measure_area) self.graphicsView.toggle_points.connect( self.point_widget.checkBoxDisplayPoints.toggle) self.graphicsView.toggle_grid.connect( self.point_widget.checkBoxDisplayGrid.toggle) self.graphicsView.scale_selected.connect(self.set_scale) self.graphicsView.select_class.connect( self.point_widget.select_tree_item_from_name) self.graphicsView.add_class.connect( lambda: self.point_widget.add_class(askname=False)) self.graphicsView.search.connect(self.search) self.canvas.edit_style_selected.connect( self.graphicsView._set_edit_style) self.graphicsView.add_point.connect(self.canvas.add_point) self.graphicsView.display_pointer_coordinates.connect( self.display_pointer_coordinates) self.graphicsView.find_point.connect(self.find_point) self.canvas.image_loaded.connect(self.graphicsView.image_loaded) self.canvas.directory_set.connect(self.display_working_directory) self.canvas.rect_size_changed.connect( self.update_component_size_from_canvas) # Image data fields self.canvas.image_loaded.connect(self.display_coordinates) self.canvas.image_loaded.connect(self.display_attributes) self.canvas.fields_updated.connect(self.display_attributes) self.dataLineEditsNames = [ "lineEdit_ecu", "lineEdit_pcb", "comboBox_pos", "lineEditX", "lineEditY" ] pcbAttr = ["ECU Name", "PCB Name", "Side", "Length", "Width"] self.attribute_widget_names = [ "comboBox_manufacturer", "lineEdit_partnumber", "comboBox_family", "lineEdit_description", "lineEdit_specifications", "comboBox_package", "lineEdit_pincount", "lineEdit_marking", "lineEdit_diameter", "lineEdit_length", "lineEdit_width", "lineEdit_height", "break", "comboBox_placement", "comboBox_metrik", "lineEdit_Researchprice", "lineEdit_Researchvol", "lineEdit_ResearchSource", "lineEdit_stdRef" ] self.attribute_names = [ "Manufacturer", "Mfr. Partnumber", "Component Family", "Description", "Specifications", "Package", "Pin Count", "Marking", "Diameter", "Length", "Width", "Height", "Costing", "Placement", "Metrik", "Research Price [$]", "Research Volume [k]", "Research Source", "Std. Comp. Reference" ] value_types = { "Diameter": "float", "Length": "float", "Width": "float", "Height": "float", "Research Price [$]": "float", "Research Volume [k]": "float" } for i, k in enumerate(self.dataLineEditsNames): box = self.groupBoxImageData layout = self.gridLayout_2 if "line" in k: widget = LineEdit(box, available_actions=["Copy", "Paste"]) widget.setContextMenuPolicy(QtCore.Qt.CustomContextMenu) widget.setAcceptDrops(False) widget.setObjectName(k) widget.setDisabled(True) widget.returnPressed.connect(self.cycle_edits) if "X" in k or "Y" in k: widget.textEdited.connect(self.update_pcb_info) else: widget.returnPressed.connect(self.update_ecu_name) else: widget = QtWidgets.QComboBox() widget.addItems(["Top", "Bottom"]) widget.setDisabled(True) widget.setCurrentIndex(0) widget.activated.connect(self.update_ecu_name) layout.addWidget(widget, i, 1, 1, 1) label = QtWidgets.QLabel(box) sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Preferred) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth( label.sizePolicy().hasHeightForWidth()) label.setSizePolicy(sizePolicy) label.setText(_translate("CentralWidget", pcbAttr[i])) layout.addWidget(label, i, 0, 1, 1) setattr(self, k, widget) self.attribute_widgets = {} for i, k in enumerate(self.attribute_widget_names): box = self.groupBoxCustomFields layout = self.gridLayout if "line" in k: value_type = value_types.get(self.attribute_names[i], "string") widget = LineEdit(box, value_type=value_type) widget.setContextMenuPolicy(QtCore.Qt.CustomContextMenu) widget.setAcceptDrops(False) widget.setObjectName(k) widget.setDisabled(True) widget.textEdited.connect( partial(self.update_attributes, name=k)) widget.returnPressed.connect(self.cycle_edits) widget.copy_all_signal.connect(self.copy_all_attributes) widget.paste_all_signal.connect(self.paste_all_attributes) widget.setFrame(False) elif "combo" in k: widget = QtWidgets.QComboBox(box) widget.setDisabled(True) widget.setObjectName(k) widget.setLineEdit(LineEdit()) widget.currentTextChanged.connect( partial(self.update_attributes, name=k)) widget.currentIndexChanged.connect( partial(self.update_attributes, name=k)) widget.lineEdit().textEdited.connect( partial(self.update_attributes, name=k)) widget.lineEdit().returnPressed.connect(self.cycle_edits) widget.lineEdit().copy_all_signal.connect( self.copy_all_attributes) widget.lineEdit().paste_all_signal.connect( self.paste_all_attributes) widget.setFrame(False) elif k == "break": widget = QtWidgets.QFrame(box) widget.setFrameShape(QtWidgets.QFrame.HLine) # layout.addWidget(line, i, 1, 1, 1) # continue layout.addWidget(widget, i, 1, 1, 1) label = QtWidgets.QLabel(box) sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Preferred) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth( label.sizePolicy().hasHeightForWidth()) label.setSizePolicy(sizePolicy) if k != "break": label.setText( _translate("CentralWidget", self.attribute_names[i])) else: label.setText("<b>" + self.attribute_names[i] + "</b>") layout.addWidget(label, i, 0, 1, 1) self.attribute_widgets[self.attribute_names[i]] = widget setattr(self, k, widget) setattr( self, k.replace("lineEdit", "label").replace("comboBox", "label"), label) self.info_widgets = self.dataLineEditsNames.copy() self.info_widgets.extend(self.attribute_widget_names) self.set_tool_tips() package_completer = QtWidgets.QCompleter(completion.packages) package_completer.setCaseSensitivity(QtCore.Qt.CaseInsensitive) self.comboBox_package.lineEdit().setCompleter(package_completer) self.comboBox_package.addItems(completion.packages) self.comboBox_package.setCurrentText("") package_completer.setCompletionMode( QtWidgets.QCompleter.PopupCompletion) manufacturer_completer = QtWidgets.QCompleter(completion.manufacturers) manufacturer_completer.setCaseSensitivity(QtCore.Qt.CaseInsensitive) self.comboBox_manufacturer.lineEdit().setCompleter( manufacturer_completer) self.comboBox_manufacturer.addItems(completion.manufacturers) self.comboBox_manufacturer.setCurrentText("") manufacturer_completer.setCompletionMode( QtWidgets.QCompleter.PopupCompletion) metrik_completer = QtWidgets.QCompleter(completion.metriks) metrik_completer.setCaseSensitivity(QtCore.Qt.CaseInsensitive) self.comboBox_metrik.lineEdit().setCompleter(metrik_completer) self.comboBox_metrik.addItems(completion.metriks) self.comboBox_metrik.setCurrentText("") metrik_completer.setCompletionMode( QtWidgets.QCompleter.PopupCompletion) placement_list = list(sorted(completion.placement)) placement_completer = QtWidgets.QCompleter(sorted(placement_list)) placement_completer.setCaseSensitivity(QtCore.Qt.CaseInsensitive) self.comboBox_placement.lineEdit().setCompleter(placement_completer) self.comboBox_placement.addItems(placement_list) self.comboBox_placement.setCurrentText("") placement_completer.setCompletionMode( QtWidgets.QCompleter.PopupCompletion) # self.pushButtonFolder.clicked.connect(self.select_folder) self.pushButtonZoomOut.clicked.connect(self.graphicsView.zoom_out) self.pushButtonZoomIn.clicked.connect(self.graphicsView.zoom_in) self.quick_save_frame = QtWidgets.QFrame(self.graphicsView) self.quick_save_frame.setStyleSheet( "QFrame { background: #4caf50;color: #FFF;font-weight: bold}") self.quick_save_frame.setLayout(QtWidgets.QHBoxLayout()) self.quick_save_frame.layout().addWidget(QtWidgets.QLabel('Saving...')) self.quick_save_frame.setGeometry(3, 3, 100, 35) self.quick_save_frame.hide() # add toolbar self.toolBar = QtWidgets.QToolBar() self.toolLayout.addWidget(self.toolBar) self.toolButtons = [] def reset_toolbar(self): self.pointsToolButton.setChecked(True) self.rectsToolButton.setChecked(False) self.canvas.set_edit_style(EditStyle.POINTS) def create_toolbar(self, actions): """ Set buttons on the toolsbar wth the actions "Actions" params: ------ actions: list list of QActions """ import warnings if self.toolButtons: warnings.warn("Toolbar already set. Ignore resetting") return for action in actions: button = QtWidgets.QToolButton() button.setCheckable(True) button.setAutoExclusive(True) button.setDefaultAction(action) self.toolButtons.append(button) self.toolBar.addWidget(button) self.toolButtons[0].setChecked(True) def copy_all_attributes(self): from os import linesep clipboard = QtWidgets.QApplication.clipboard() text = "" for attr, widget in self.attribute_widgets.items(): text = text + attr + "\t" + getText(widget) + linesep clipboard.setText(text.strip(linesep)) def paste_all_attributes(self): from os import linesep clipboard = QtWidgets.QApplication.clipboard() text = clipboard.text() if linesep in text: text = text.split(linesep) elif "\n" in text: text = text.split("\n") if text[-1] == "\n" or text[-1] == linesep: text = text[:-1] attributes = list(self.attribute_widgets.keys()) for i, t in enumerate(text): if i == len(attributes): break val = t.split("\t") if len(val) > 1: val = val[-1] setText(self.attribute_widgets[attributes[i]], val) def cycle_edits(self): cycled = cycle(self.info_widgets) for k in cycled: w = getattr(self, k) if w.hasFocus(): w.clearFocus() nextW = getattr(self, next(cycled)) nextW.setFocus() break def display_pointer_coordinates(self, point): img = self.canvas.current_image_name image_scale = self.canvas.image_scale.get(img, Scale()) scale = image_scale.scale left = image_scale.left top = image_scale.top unit = image_scale.unit text = "{:5.1f}, {:5.1f} {} || {:5.1f}, {:5.1f} px".format( int(point.x()) * scale - left, int(point.y()) * scale - top, unit, int(point.x()) - left, int(point.y()) - top) self.posLabel.setText(text) def display_coordinates(self, directory, image): if self.canvas.current_image_name is None: for i, k in enumerate(self.dataLineEditsNames): getattr(self, k).setDisabled(True) else: for i, k in enumerate(self.dataLineEditsNames): getattr(self, k).setDisabled(False) ecu_name, pcb_name, position = self.canvas.get_ecu_info(image) self.lineEditX.setText(self.canvas.pcb_info[image]['x']) self.lineEditY.setText(self.canvas.pcb_info[image]['y']) self.lineEdit_ecu.setText(ecu_name) self.comboBox_pos.setCurrentText(position) self.lineEdit_pcb.setText(pcb_name) def display_attributes(self): if self.canvas.current_class_name is None or self.canvas.current_image_name is None: for _, w in self.attribute_widgets.items(): setText(w, "") w.setDisabled(True) else: for k, widget in self.attribute_widgets.items(): widget.setDisabled(False) value = self.canvas.class_attributes[ self.canvas.current_class_name].get(k, "") setText(widget, value) def display_ecu_name(self): if self.canvas.current_image_name is not None: ecu_name, pcb_name, position = self.canvas.get_ecu_info( self.canvas.current_image_name) self.lineEdit_ecu.setText(ecu_name) self.lineEdit_pcb.setText(pcb_name) self.comboBox_pos.setCurrentText(position) def display_working_directory(self, directory): self.labelWorkingDirectory.setText(directory) def display_quick_save(self): self.quick_save_frame.show() QtCore.QTimer.singleShot(500, self.quick_save_frame.hide) def find_point(self, point): self.graphicsView.hovered_name = None if self.canvas.current_image_name is None: return item = self.canvas.itemAt(point, QtGui.QTransform()) if item is None or not isinstance(item, QtWidgets.QGraphicsEllipseItem): return classes = self.canvas.points[self.canvas.current_image_name] if len(classes) == 0: return for c, points in classes.items(): for p in points: if item.contains(p): self.graphicsView.hovered_name = c break def hide_custom_fields(self, hide): if hide is True: self.frameCustomField.hide() else: self.frameCustomField.show() def resizeEvent(self, theEvent): self.graphicsView.resize_image() def set_scale(self, rect): from ddg.dialogs.scale_dialog import getScale direction, mm = getScale() if mm: mm = max(mm, 1) self.canvas.set_scale(mm, direction, rect) def select_folder(self): name = QtWidgets.QFileDialog.getExistingDirectory( self, 'Select image folder', self.canvas.directory) if name != '': self.canvas.load([QtCore.QUrl('file:{}'.format(name))]) def set_tool_tips(self): self.lineEdit_ecu.setToolTip( "ECU name of active PCB. To change name hit 'Enter'") self.lineEdit_pcb.setToolTip( "Name of active PCB. To change name hit 'Enter'") self.lineEditX.setToolTip("Width of active PCB. Saved when edited") self.lineEditY.setToolTip("Width of active PCB. Saved when edited") for attr, edit in zip(self.attribute_names, self.attribute_widget_names): widget = self.__dict__.get(edit, None) if widget: widget.setToolTip( "{:} of active component. Saved when text changed.".format( attr)) def update_pcb_info(self, info): x = self.lineEditX.text() y = self.lineEditY.text() self.canvas.save_pcb_info(x, y) def update_ecu_name(self): new_name = None ecu_name, pcb_name, position = self.canvas.get_ecu_info( self.canvas.current_image_name) new_ecu = self.lineEdit_ecu.text() if len(ecu_name) == 1: self.lineEdit_ecu.setText(ecu_name) new_ecu = ecu_name new_pcb = self.lineEdit_pcb.text() if len(pcb_name) == 1: self.lineEdit_pcb.setText(pcb_name) new_ecu = pcb_name new_pos = self.comboBox_pos.currentText() if new_ecu != ecu_name: new_name = new_ecu pcb_name = None position = None elif new_pcb != pcb_name: new_name = new_pcb position = None elif new_pos != position: new_name = new_pos if new_name: done = self.canvas.rename_ecu(new_name, ecu_name, pcb_name, position) if not done: self.lineEdit_ecu.setText(ecu_name) self.lineEdit_pcb.setText(pcb_name) self.comboBox_pos.setCurrentText(position) else: self.point_widget.display_count_tree() def update_attributes(self, text, name): if "combo" in name.lower(): text = getattr(self, name).currentText() i = self.attribute_widget_names.index(name) attr = self.attribute_names[i] if name in [ "Length", "Width", "Height", "Diameter", "Research Volume [k]", "Research Price [$]" ]: text = text.replace(",", ".") self.canvas.set_component_attribute(attr, text) def set_survey_id(self): self.canvas.survey_id = self.point_widget.lineEditSurveyId.text() def search(self): dialog = SearchDialog(self) dialog.component_clicked.connect( self.point_widget.select_tree_item_from_name) dialog.exec_() def update_component_size_from_canvas(self, l, w): fmt = "{:.2f}" self.lineEdit_length.setText(fmt.format(l)) self.lineEdit_width.setText(fmt.format(w))