예제 #1
0
    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)
예제 #2
0
    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)
예제 #3
0
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)
예제 #4
0
    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()
예제 #5
0
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)
예제 #6
0
    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 = []
예제 #7
0
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))