class DoubleSpin(QWidget): #a custom widget containing 2 QSpinBoxes in a row #is used for pair user input (like x,y or width, height) def __init__(self, parent=None): QWidget.__init__(self, parent) layout = QHBoxLayout() self.sbx = QSpinBox() self.sby = QSpinBox() self.sbx.setRange(0, 1000) self.sby.setRange(0, 1000) lb = QLabel('x') lb.setSizePolicy(Qt.QSizePolicy.Minimum, Qt.QSizePolicy.Minimum) layout.addWidget(lb) self.sbx.setSizePolicy(Qt.QSizePolicy.Maximum, Qt.QSizePolicy.Maximum) layout.addWidget(self.sbx) lby = QLabel('y') lby.setSizePolicy(Qt.QSizePolicy.Minimum, Qt.QSizePolicy.Minimum) layout.addWidget(lby) layout.setAlignment(Qt.Qt.AlignLeft) layout.addWidget(self.sby) self.setLayout(layout) def setX(self, x): self.sbx.setValue(x) def setY(self, y): self.sby.setValue(y) def getValues(self): return (self.sbx.value(), self.sby.value())
def __mkSpinBox(self, value, min, max, options={}): spBox = QSpinBox() spBox.setValue(value) spBox.setMinimum(min) spBox.setMaximum(max) valueChangedSlot = options.get("valueChangedSlot", None) if valueChangedSlot is not None: spBox.valueChanged.connect(valueChangedSlot) return spBox
def bindSpinboxAndSlider(editor: QSpinBox, slider: QSlider, slot): # 联动 editor.valueChanged.connect(lambda value: slider.setValue(value)) slider.valueChanged.connect(lambda value: editor.setValue(value)) # 绑定槽函数 slider.valueChanged.connect(slot)
class GenerateLabelsDialog(QDialog): #Generate labels dialog class def __init__(self, p=None): QDialog.__init__(self, p) self.setWindowTitle("Generate page layout...") self.layout = QFormLayout() self.numberOfLabelsSpinBox = QSpinBox() self.numberOfLabelsSpinBox.setRange(1, 200) self.numberOfLabelsSpinBox.setValue( generate_settings['defaultNumberOfLabels']) self.layout.addRow("Number of labels", self.numberOfLabelsSpinBox) self.firstLabelArticleNumberSB = QSpinBox() self.firstLabelArticleNumberSB.setRange(0, 9999) self.firstLabelArticleNumberSB.setValue( generate_settings['firstLabelArticleNumber']) self.layout.addRow("First label article number", self.firstLabelArticleNumberSB) self.weekNrYearLE = QLineEdit() self.weekNrYearLE.setText(generate_settings['weekNrYear']) self.layout.addRow("Week nr/ year", self.weekNrYearLE) self.lotNameLE = QLineEdit() self.lotNameLE.setText(generate_settings['lotName']) self.layout.addRow("Lot", self.lotNameLE) self.generatePB = QPushButton("Generate") self.generatePB.clicked.connect(self.onGenerate) self.layout.addRow("", self.generatePB) self.cancelPB = QPushButton("Cancel") self.cancelPB.clicked.connect(self.close) self.layout.addRow("", self.cancelPB) self.setLayout(self.layout) def onGenerate(self): generate_settings[ 'defaultNumberOfLabels'] = self.numberOfLabelsSpinBox.value() generate_settings[ 'firstLabelArticleNumber'] = self.firstLabelArticleNumberSB.value( ) generate_settings['weekNrYear'] = self.weekNrYearLE.text() generate_settings['lotName'] = self.lotNameLE.text() self.accept()
class ConfigWidget(QWidget): def __init__(self): QWidget.__init__(self) self.l = QHBoxLayout() self.setLayout(self.l) self.label = QLabel("Max number of last issues to download:") self.l.addWidget(self.label) self.max_number = QSpinBox(self) self.max_number.setValue(prefs["max_numbers"]) self.max_number.setMinimum(0) self.l.addWidget(self.max_number) self.label.setBuddy(self.max_number) def save_settings(self): prefs["max_numbers"] = self.max_number.value() prefs.commit()
def _setup_ui(self): layout = QHBoxLayout() layout.addWidget(QLabel(self._parm.get_name())) # IntParameter if isinstance(self._parm, IntParameter): spin_box = QSpinBox() spin_box.setMaximum(99999) spin_box.setValue(self._parm.get_value()) spin_box.valueChanged.connect(self._update) layout.addWidget(spin_box) # RangeParameter elif isinstance(self._parm, RangeParameter): range_slider = RangeSlider() range_slider.setRangeLimit(0, 255) range_slider.setRange(*self._parm.get_value()) range_slider.valueChanged.connect(self._update) range_label = RangeLabel(range_slider) layout.addWidget(range_slider) layout.addWidget(range_label) # ColorParameter elif isinstance(self._parm, ColorParameter): color_picker = ColorPicker(self._parm.get_value()) color_picker.valueChanged.connect(self._update) layout.addWidget(color_picker) # FileParameter elif isinstance(self._parm, FileParameter): file_picker = FilePicker() file_picker.valueChanged.connect(self._update) layout.addWidget(file_picker) self.setLayout(layout)
class GcodeUI(object): def __init__(self, ui, layout): self.main_ui = ui self.layout = layout super(GcodeUI, self).__init__() self.isOutlineMode = True self.isLaserMode = True self.handler = GcodeHandler(self) self.set_ui() self.connect_slot() self.gcode = '' def set_ui(self): self._set_up_frame_ui() self._set_middle_frame_ui() self._set_down_frame_ui() def _set_up_frame_ui(self): self.up_frame = QFrame() self.up_frame.setMinimumHeight(300) self.up_frame.setMaximumHeight(500) self.up_layout = QHBoxLayout(self.up_frame) up_left_frame = QFrame() # up_left_frame.setMinimumWidth(self.main_ui.window.geometry().width() / 2) # up_left_frame.setMaximumWidth(self.geometry().width() / 2) up_right_frame = QFrame() # up_right_frame.setMinimumWidth(self.main_ui.window.geometry().width() / 2) # up_right_frame.setMaximumWidth(self.geometry().width() / 2) self.up_left_layout = QHBoxLayout(up_left_frame) self.up_right_layout = QHBoxLayout(up_right_frame) self.up_layout.addWidget(up_left_frame) # self.up_layout.addWidget(up_right_frame) self.layout.addWidget(self.up_frame) self.label_img = QLabel() # self.label_img.setMaximumHeight(320) # self.label_img.setMaximumWidth(480) # self.label_img.setSizePolicy(QSizePolicy.Ignored, QSizePolicy.Ignored) # self.label_img.setScaledContents(True) img = QImage() if img.load(os.path.join(icon_path, 'tmp.svg')): self.label_img.setPixmap(QPixmap.fromImage(img)) with open(os.path.join(icon_path, 'tmp.svg'), 'rb') as f: self.handler.source = f.read() self.up_left_layout.addWidget(self.label_img) self.label_img_preview = QLabel() # self.label_img_preview.setMaximumHeight(320) # self.label_img_preview.setMaximumWidth(480) self.label_img_preview.setDisabled(True) # # self.label_img_preview.setSizePolicy(QSizePolicy.Ignored, QSizePolicy.Ignored) # # self.label_img_preview.setScaledContents(True) # data = np.zeros(320 * 240) # img = QImage(data, 320, 240, QImage.Format_RGB888) # pixmap = QPixmap.fromImage(img) # self.label_img_preview.setPixmap(pixmap) self.up_right_layout.addWidget(self.label_img_preview) # self.up_frame.hide() def _set_middle_frame_ui(self): middle_frame = QFrame() self.middle_layout = QHBoxLayout(middle_frame) middle_left_frame = QFrame() # middle_left_frame.setMinimumWidth(self.main_ui.window.geometry().width() / 2 - 20) middle_right_frame = QFrame() # middle_right_frame.setMinimumWidth(self.main_ui.window.geometry().width() / 2 - 20) self.middle_left_layout = QGridLayout(middle_left_frame) self.middle_right_layout = QGridLayout(middle_right_frame) self.middle_layout.addWidget(middle_left_frame) self.middle_layout.addWidget(middle_right_frame) self.layout.addWidget(middle_frame) row = 0 self.checkbox_outline = QRadioButton('OutLine') self.checkbox_gray = QRadioButton('Gray') self.checkbox_gray.hide() self.btn_load_img = QPushButton('LoadImage') self.checkbox_outline.toggle() self.isOutlineMode = True self.checkbox_outline.setDisabled(True) self.middle_left_layout.addWidget(self.checkbox_outline, row, 0) self.middle_left_layout.addWidget(self.checkbox_gray, row, 1) self.middle_left_layout.addWidget(self.btn_load_img, row, 2) row += 1 label_x_home = QLabel('x_home:') self.slider_x_home = QSlider(QtCore.Qt.Horizontal) self.slider_x_home.setMinimum(0) self.slider_x_home.setMaximum(2000) self.slider_x_home.setValue(1500) self.spinbox_x_home = QDoubleSpinBox() self.spinbox_x_home.setDecimals(1) self.spinbox_x_home.setSingleStep(0.1) self.spinbox_x_home.setMinimum(0.0) self.spinbox_x_home.setMaximum(200.0) self.spinbox_x_home.setValue(150.0) self.slider_x_home.mouseReleaseEvent = functools.partial( self.mouseReleaseEvent, source=self.slider_x_home.mouseReleaseEvent) self.spinbox_x_home.focusOutEvent = functools.partial( self.focusOutEvent, source=self.spinbox_x_home.focusOutEvent) self.middle_left_layout.addWidget(label_x_home, row, 0) self.middle_left_layout.addWidget(self.slider_x_home, row, 1) self.middle_left_layout.addWidget(self.spinbox_x_home, row, 2) row += 1 label_y_home = QLabel('y_home:') self.slider_y_home = QSlider(QtCore.Qt.Horizontal) self.slider_y_home.setMinimum(-1500) self.slider_y_home.setMaximum(1500) self.slider_y_home.setValue(0) self.spinbox_y_home = QDoubleSpinBox() self.spinbox_y_home.setDecimals(1) self.spinbox_y_home.setSingleStep(0.1) self.spinbox_y_home.setMinimum(-150.0) self.spinbox_y_home.setMaximum(150.0) self.spinbox_y_home.setValue(0.0) self.slider_y_home.mouseReleaseEvent = functools.partial( self.mouseReleaseEvent, source=self.slider_y_home.mouseReleaseEvent) self.spinbox_y_home.focusOutEvent = functools.partial( self.focusOutEvent, source=self.spinbox_y_home.focusOutEvent) self.middle_left_layout.addWidget(label_y_home, row, 0) self.middle_left_layout.addWidget(self.slider_y_home, row, 1) self.middle_left_layout.addWidget(self.spinbox_y_home, row, 2) row += 1 label_z_home = QLabel('z_home:') self.slider_z_home = QSlider(QtCore.Qt.Horizontal) self.slider_z_home.setMinimum(0) self.slider_z_home.setMaximum(1500) self.slider_z_home.setValue(900) self.spinbox_z_home = QDoubleSpinBox() self.spinbox_z_home.setDecimals(1) self.spinbox_z_home.setSingleStep(0.1) self.spinbox_z_home.setMinimum(0.0) self.spinbox_z_home.setMaximum(150.0) self.spinbox_z_home.setValue(90.0) self.slider_z_home.mouseReleaseEvent = functools.partial( self.mouseReleaseEvent, source=self.slider_z_home.mouseReleaseEvent) self.spinbox_z_home.focusOutEvent = functools.partial( self.focusOutEvent, source=self.spinbox_z_home.focusOutEvent) self.middle_left_layout.addWidget(label_z_home, row, 0) self.middle_left_layout.addWidget(self.slider_z_home, row, 1) self.middle_left_layout.addWidget(self.spinbox_z_home, row, 2) row += 1 label_x_offset = QLabel('x_offset:') self.slider_x_offset = QSlider(QtCore.Qt.Horizontal) self.slider_x_offset.setMinimum(-5000) self.slider_x_offset.setMaximum(5000) self.slider_x_offset.setValue(0) self.spinbox_x_offset = QDoubleSpinBox() self.spinbox_x_offset.setSingleStep(0.1) self.spinbox_x_offset.setDecimals(1) self.spinbox_x_offset.setMinimum(-500.0) self.spinbox_x_offset.setMaximum(500.0) self.spinbox_x_offset.setValue(0.0) self.slider_x_offset.mouseReleaseEvent = functools.partial( self.mouseReleaseEvent, source=self.slider_x_offset.mouseReleaseEvent) self.spinbox_x_offset.focusOutEvent = functools.partial( self.focusOutEvent, source=self.spinbox_x_offset.focusOutEvent) self.middle_left_layout.addWidget(label_x_offset, row, 0) self.middle_left_layout.addWidget(self.slider_x_offset, row, 1) self.middle_left_layout.addWidget(self.spinbox_x_offset, row, 2) row += 1 label_y_offset = QLabel('y_offset:') self.slider_y_offset = QSlider(QtCore.Qt.Horizontal) self.slider_y_offset.setMinimum(-5000) self.slider_y_offset.setMaximum(5000) self.slider_y_offset.setValue(0) self.spinbox_y_offset = QDoubleSpinBox() self.spinbox_y_offset.setDecimals(1) self.spinbox_y_offset.setSingleStep(0.1) self.spinbox_y_offset.setMinimum(-500.0) self.spinbox_y_offset.setMaximum(500.0) self.spinbox_y_offset.setValue(0.0) self.slider_y_offset.mouseReleaseEvent = functools.partial( self.mouseReleaseEvent, source=self.slider_y_offset.mouseReleaseEvent) self.spinbox_y_offset.focusOutEvent = functools.partial( self.focusOutEvent, source=self.spinbox_y_offset.focusOutEvent) self.middle_left_layout.addWidget(label_y_offset, row, 0) self.middle_left_layout.addWidget(self.slider_y_offset, row, 1) self.middle_left_layout.addWidget(self.spinbox_y_offset, row, 2) row += 1 label_z_offset = QLabel('z_offset:') self.slider_z_offset = QSlider(QtCore.Qt.Horizontal) self.slider_z_offset.setMinimum(-1000) self.slider_z_offset.setMaximum(1500) self.slider_z_offset.setValue(900) self.spinbox_z_offset = QDoubleSpinBox() self.spinbox_z_offset.setDecimals(1) self.spinbox_z_offset.setSingleStep(0.1) self.spinbox_z_offset.setMinimum(-100.0) self.spinbox_z_offset.setMaximum(150.0) self.spinbox_z_offset.setValue(90.0) self.slider_z_offset.mouseReleaseEvent = functools.partial( self.mouseReleaseEvent, source=self.slider_z_offset.mouseReleaseEvent) self.spinbox_z_offset.focusOutEvent = functools.partial( self.focusOutEvent, source=self.spinbox_z_offset.focusOutEvent) self.middle_left_layout.addWidget(label_z_offset, row, 0) self.middle_left_layout.addWidget(self.slider_z_offset, row, 1) self.middle_left_layout.addWidget(self.spinbox_z_offset, row, 2) row += 1 label_pen_up = QLabel('pen_up:') self.slider_pen_up = QSlider(QtCore.Qt.Horizontal) self.slider_pen_up.setMinimum(0) self.slider_pen_up.setMaximum(500) self.slider_pen_up.setValue(200) self.spinbox_pen_up = QDoubleSpinBox() self.spinbox_pen_up.setDecimals(1) self.spinbox_pen_up.setSingleStep(0.1) self.spinbox_pen_up.setMinimum(0.0) self.spinbox_pen_up.setMaximum(50.0) self.spinbox_pen_up.setValue(20.0) self.slider_pen_up.mouseReleaseEvent = functools.partial( self.mouseReleaseEvent, source=self.slider_pen_up.mouseReleaseEvent) self.spinbox_pen_up.focusOutEvent = functools.partial( self.focusOutEvent, source=self.spinbox_pen_up.focusOutEvent) self.slider_pen_up.setDisabled(True) self.spinbox_pen_up.setDisabled(True) self.middle_left_layout.addWidget(label_pen_up, row, 0) self.middle_left_layout.addWidget(self.slider_pen_up, row, 1) self.middle_left_layout.addWidget(self.spinbox_pen_up, row, 2) row = 0 self.checkbox_laser = QRadioButton('Laser') self.checkbox_pen = QRadioButton('Pen') self.checkbox_laser.toggle() self.isLaserMode = True self.middle_right_layout.addWidget(self.checkbox_laser, row, 0) self.middle_right_layout.addWidget(self.checkbox_pen, row, 1) row += 1 label_drawing_feedrate = QLabel('drawing_feedrate:') self.slider_drawing_feedrate = QSlider(QtCore.Qt.Horizontal) self.slider_drawing_feedrate.setMinimum(5) self.slider_drawing_feedrate.setMaximum(1000) self.slider_drawing_feedrate.setValue(100) self.spinbox_drawing_feedrate = QSpinBox() self.spinbox_drawing_feedrate.setMinimum(5) self.spinbox_drawing_feedrate.setMaximum(1000) self.spinbox_drawing_feedrate.setValue(100) self.slider_drawing_feedrate.mouseReleaseEvent = functools.partial( self.mouseReleaseEvent, source=self.slider_drawing_feedrate.mouseReleaseEvent) self.spinbox_drawing_feedrate.focusOutEvent = functools.partial( self.focusOutEvent, source=self.spinbox_drawing_feedrate.focusOutEvent) self.middle_right_layout.addWidget(label_drawing_feedrate, row, 0) self.middle_right_layout.addWidget(self.slider_drawing_feedrate, row, 1) self.middle_right_layout.addWidget(self.spinbox_drawing_feedrate, row, 2) row += 1 label_moving_feedrate = QLabel('moving_feedrate:') self.slider_moving_feedrate = QSlider(QtCore.Qt.Horizontal) self.slider_moving_feedrate.setMinimum(5) self.slider_moving_feedrate.setMaximum(20000) self.slider_moving_feedrate.setValue(100) self.spinbox_moving_feedrate = QSpinBox() self.spinbox_moving_feedrate.setMinimum(5) self.spinbox_moving_feedrate.setMaximum(20000) self.spinbox_moving_feedrate.setValue(100) self.slider_moving_feedrate.mouseReleaseEvent = functools.partial( self.mouseReleaseEvent, source=self.slider_moving_feedrate.mouseReleaseEvent) self.spinbox_moving_feedrate.focusOutEvent = functools.partial( self.focusOutEvent, source=self.spinbox_moving_feedrate.focusOutEvent) self.middle_right_layout.addWidget(label_moving_feedrate, row, 0) self.middle_right_layout.addWidget(self.slider_moving_feedrate, row, 1) self.middle_right_layout.addWidget(self.spinbox_moving_feedrate, row, 2) row += 1 label_scale = QLabel('scale:') self.slider_scale = QSlider(QtCore.Qt.Horizontal) self.slider_scale.setMinimum(1) self.slider_scale.setMaximum(100) self.slider_scale.setValue(10) self.spinbox_scale = QDoubleSpinBox() self.spinbox_scale.setDecimals(1) self.spinbox_scale.setSingleStep(0.1) self.spinbox_scale.setMinimum(0.1) self.spinbox_scale.setMaximum(10.0) self.spinbox_scale.setValue(1.0) # self.slider_scale.setDisabled(True) # self.spinbox_scale.setDisabled(True) self.slider_scale.mouseReleaseEvent = functools.partial( self.mouseReleaseEvent, source=self.slider_scale.mouseReleaseEvent) self.spinbox_scale.focusOutEvent = functools.partial( self.focusOutEvent, source=self.spinbox_scale.focusOutEvent) self.middle_right_layout.addWidget(label_scale, row, 0) self.middle_right_layout.addWidget(self.slider_scale, row, 1) self.middle_right_layout.addWidget(self.spinbox_scale, row, 2) row += 1 label_resolution = QLabel('resolution:') self.slider_resolution = QSlider(QtCore.Qt.Horizontal) self.slider_resolution.setMinimum(1) self.slider_resolution.setMaximum(100) self.slider_resolution.setValue(10) self.spinbox_resolution = QDoubleSpinBox() self.spinbox_resolution.setMinimum(0.1) self.spinbox_resolution.setMaximum(10.0) self.spinbox_resolution.setSingleStep(0.1) self.spinbox_resolution.setDecimals(1) self.spinbox_resolution.setValue(1.0) self.slider_resolution.setDisabled(True) self.spinbox_resolution.setDisabled(True) self.middle_right_layout.addWidget(label_resolution, row, 0) self.middle_right_layout.addWidget(self.slider_resolution, row, 1) self.middle_right_layout.addWidget(self.spinbox_resolution, row, 2) row += 1 self.btn_generate_gcode = QPushButton('Generate_Gcode') self.middle_right_layout.addWidget(self.btn_generate_gcode, row, 0) row += 1 self.label_x_min = QLabel('') self.label_x_max = QLabel('') self.middle_right_layout.addWidget(self.label_x_min, row, 0) self.middle_right_layout.addWidget(self.label_x_max, row, 1) row += 1 self.label_y_min = QLabel('') self.label_y_max = QLabel('') self.middle_right_layout.addWidget(self.label_y_min, row, 0) self.middle_right_layout.addWidget(self.label_y_max, row, 1) def _set_down_frame_ui(self): self.down_frame = QFrame() self.down_layout = QHBoxLayout(self.down_frame) self.layout.addWidget(self.down_frame) self.textEdit = QTextEdit() self.down_layout.addWidget(self.textEdit) # self.down_frame.hide() def select_engrave_mode(self, event): self.isOutlineMode = event # print('outline: {}, laser: {}'.format(self.isOutlineMode, self.isLaserMode)) def select_end_type(self, event): self.isLaserMode = event self.slider_pen_up.setDisabled(self.isLaserMode) self.spinbox_pen_up.setDisabled(self.isLaserMode) self.generate_gcode() # print('outline: {}, laser: {}'.format(self.isOutlineMode, self.isLaserMode)) def connect_slot(self): self.checkbox_outline.toggled.connect(self.select_engrave_mode) self.checkbox_laser.toggled.connect(self.select_end_type) self.btn_load_img.clicked.connect(self.load_image) self.slider_x_home.valueChanged.connect( functools.partial(self.slider_spinbox_related, slave=self.spinbox_x_home, scale=.1)) self.spinbox_x_home.valueChanged.connect( functools.partial(self.slider_spinbox_related, slave=self.slider_x_home, scale=10)) self.slider_y_home.valueChanged.connect( functools.partial(self.slider_spinbox_related, slave=self.spinbox_y_home, scale=.1)) self.spinbox_y_home.valueChanged.connect( functools.partial(self.slider_spinbox_related, slave=self.slider_y_home, scale=10)) self.slider_z_home.valueChanged.connect( functools.partial(self.slider_spinbox_related, slave=self.spinbox_z_home, scale=.1)) self.spinbox_z_home.valueChanged.connect( functools.partial(self.slider_spinbox_related, slave=self.slider_z_home, scale=10)) self.slider_x_offset.valueChanged.connect( functools.partial(self.slider_spinbox_related, slave=self.spinbox_x_offset, scale=.1)) self.spinbox_x_offset.valueChanged.connect( functools.partial(self.slider_spinbox_related, slave=self.slider_x_offset, scale=10)) self.slider_y_offset.valueChanged.connect( functools.partial(self.slider_spinbox_related, slave=self.spinbox_y_offset, scale=.1)) self.spinbox_y_offset.valueChanged.connect( functools.partial(self.slider_spinbox_related, slave=self.slider_y_offset, scale=10)) self.slider_z_offset.valueChanged.connect( functools.partial(self.slider_spinbox_related, slave=self.spinbox_z_offset, scale=.1)) self.spinbox_z_offset.valueChanged.connect( functools.partial(self.slider_spinbox_related, slave=self.slider_z_offset, scale=10)) self.slider_pen_up.valueChanged.connect( functools.partial(self.slider_spinbox_related, slave=self.spinbox_pen_up, scale=.1)) self.spinbox_pen_up.valueChanged.connect( functools.partial(self.slider_spinbox_related, slave=self.slider_pen_up, scale=10)) self.slider_scale.valueChanged.connect( functools.partial(self.slider_spinbox_related, slave=self.spinbox_scale, scale=.1)) self.spinbox_scale.valueChanged.connect( functools.partial(self.slider_spinbox_related, slave=self.slider_scale, scale=10)) self.slider_resolution.valueChanged.connect( functools.partial(self.slider_spinbox_related, slave=self.spinbox_resolution, scale=.1)) self.spinbox_resolution.valueChanged.connect( functools.partial(self.slider_spinbox_related, slave=self.slider_resolution, scale=10)) self.slider_drawing_feedrate.valueChanged.connect( functools.partial(self.slider_spinbox_related, slave=self.spinbox_drawing_feedrate, scale=1)) self.spinbox_drawing_feedrate.valueChanged.connect( functools.partial(self.slider_spinbox_related, slave=self.slider_drawing_feedrate, scale=1)) self.slider_moving_feedrate.valueChanged.connect( functools.partial(self.slider_spinbox_related, slave=self.spinbox_moving_feedrate, scale=1)) self.spinbox_moving_feedrate.valueChanged.connect( functools.partial(self.slider_spinbox_related, slave=self.slider_moving_feedrate, scale=1)) self.btn_generate_gcode.clicked.connect( functools.partial(self.generate_gcode, flag=True)) def slider_spinbox_related(self, value, master=None, slave=None, scale=1): try: slave.setValue(value * scale) except Exception as e: print(e) def mouseReleaseEvent(self, event, source=None): try: self.generate_gcode() except Exception as e: print(e) source(event) def focusOutEvent(self, event, source=None): try: self.generate_gcode() except Exception as e: print(e) source(event) def generate_gcode(self, flag=False): if self.handler.template is None and flag: self.handler.svg_to_gcode() if self.handler.template: pen_up = self.spinbox_pen_up.value() if not self.isLaserMode else 0 config = { 'x_home': self.spinbox_x_home.value(), 'y_home': self.spinbox_y_home.value(), 'z_home': self.spinbox_z_home.value(), 'z_offset': self.spinbox_z_offset.value(), 'pen_up': pen_up, 'z_offset_pen_up': self.spinbox_z_offset.value() + pen_up, 'moving_feedrate': self.spinbox_moving_feedrate.value(), 'drawing_feedrate': self.spinbox_drawing_feedrate.value(), } self.gcode = self.handler.template.format(**config) self.change_gcode() # self.textEdit.setText(self.gcode) def change_gcode(self): if self.gcode: x_offset = self.spinbox_x_offset.value() y_offset = self.spinbox_y_offset.value() z_offset = self.spinbox_z_offset.value() moving_feedrate = self.spinbox_moving_feedrate.value() drawing_feedrate = self.spinbox_drawing_feedrate.value() scale = self.spinbox_scale.value() lines = self.gcode.split('\n') for i, line in enumerate(lines): List = line.strip().split(' ') line = '' for l in List: if l.startswith('F'): if line.startswith(('G01', 'G1')): l = 'F{}'.format(drawing_feedrate) elif line.startswith(('G00', 'G0')): l = 'F{}'.format(moving_feedrate) elif l.startswith('X'): x = float(l[1:]) * scale + x_offset l = 'X{0:.2f}'.format(x) elif l.startswith('Y'): y = float(l[1:]) * scale + y_offset l = 'Y{0:.2f}'.format(y) # elif l.startswith('Z'): # z = float(l[1:]) + z_offset # l = 'Z{0:.2f}'.format(z) line += l + ' ' line = line.strip() lines[i] = line self.calc_gcode(lines) gcode = '\n'.join(lines) self.textEdit.setText(gcode) def calc_gcode(self, lines): x_list = [] y_list = [] for i, line in enumerate(lines): if line.startswith(tuple(['G0', 'G1', 'G00', 'G01'])): List = line.strip().split(' ') for l in List: if l.startswith('X'): x = float(l[1:]) x_list.append(x) elif l.startswith('Y'): y = float(l[1:]) y_list.append(y) if len(x_list) > 0: x_min = np.min(x_list) x_max = np.max(x_list) self.label_x_min.setText('X(min): ' + str(x_min)) self.label_x_max.setText('X(max): ' + str(x_max)) # print('x_min: {}, x_max: {}, x_distance: {}'.format(x_min, x_max, x_max - x_min)) if len(y_list) > 0: y_min = np.min(y_list) y_max = np.max(y_list) self.label_y_min.setText('Y(min): ' + str(y_min)) self.label_y_max.setText('Y(max): ' + str(y_max)) # print('y_min: {}, y_max: {}, y_distance: {}'.format(y_min, y_max, y_max - y_min)) def load_image(self): fname = QFileDialog.getOpenFileName(self.main_ui.window, 'Open file', '', '*.svg') if fname and fname[0]: img = QImage() if img.load(fname[0]): self.label_img.setPixmap(QPixmap.fromImage(img)) with open(fname[0], 'rb') as f: self.handler.source = f.read() self.handler.template = None self.gcode = None self.up_frame.show()
class AddEmptyBookDialog(QDialog): def __init__(self, parent, db, author, series=None, title=None): QDialog.__init__(self, parent) self.db = db self.setWindowTitle(_('How many empty books?')) self._layout = QGridLayout(self) self.setLayout(self._layout) self.qty_label = QLabel(_('How many empty books should be added?')) self._layout.addWidget(self.qty_label, 0, 0, 1, 2) self.qty_spinbox = QSpinBox(self) self.qty_spinbox.setRange(1, 10000) self.qty_spinbox.setValue(1) self._layout.addWidget(self.qty_spinbox, 1, 0, 1, 2) self.author_label = QLabel(_('Set the author of the new books to:')) self._layout.addWidget(self.author_label, 2, 0, 1, 2) self.authors_combo = EditWithComplete(self) self.authors_combo.setSizeAdjustPolicy( self.authors_combo.AdjustToMinimumContentsLengthWithIcon) self.authors_combo.setEditable(True) self._layout.addWidget(self.authors_combo, 3, 0, 1, 1) self.initialize_authors(db, author) self.clear_button = QToolButton(self) self.clear_button.setIcon(QIcon(I('trash.png'))) self.clear_button.setToolTip(_('Reset author to Unknown')) self.clear_button.clicked.connect(self.reset_author) self._layout.addWidget(self.clear_button, 3, 1, 1, 1) self.series_label = QLabel(_('Set the series of the new books to:')) self._layout.addWidget(self.series_label, 4, 0, 1, 2) self.series_combo = EditWithComplete(self) self.series_combo.setSizeAdjustPolicy( self.authors_combo.AdjustToMinimumContentsLengthWithIcon) self.series_combo.setEditable(True) self._layout.addWidget(self.series_combo, 5, 0, 1, 1) self.initialize_series(db, series) self.sclear_button = QToolButton(self) self.sclear_button.setIcon(QIcon(I('trash.png'))) self.sclear_button.setToolTip(_('Reset series')) self.sclear_button.clicked.connect(self.reset_series) self._layout.addWidget(self.sclear_button, 5, 1, 1, 1) self.title_label = QLabel(_('Set the title of the new books to:')) self._layout.addWidget(self.title_label, 6, 0, 1, 2) self.title_edit = QLineEdit(self) self.title_edit.setText(title or '') self._layout.addWidget(self.title_edit, 7, 0, 1, 1) self.tclear_button = QToolButton(self) self.tclear_button.setIcon(QIcon(I('trash.png'))) self.tclear_button.setToolTip(_('Reset title')) self.tclear_button.clicked.connect(self.title_edit.clear) self._layout.addWidget(self.tclear_button, 7, 1, 1, 1) self.format_label = QLabel(_('Also create an empty ebook in format:')) self._layout.addWidget(self.format_label, 8, 0, 1, 2) c = self.format_value = QComboBox(self) from calibre.ebooks.oeb.polish.create import valid_empty_formats possible_formats = [''] + sorted(x.upper() for x in valid_empty_formats) c.addItems(possible_formats) c.setToolTip(_('Also create an empty book format file that you can subsequently edit')) if gprefs.get('create_empty_epub_file', False): # Migration of the check box gprefs.set('create_empty_format_file', 'epub') del gprefs['create_empty_epub_file'] use_format = gprefs.get('create_empty_format_file', '').upper() try: c.setCurrentIndex(possible_formats.index(use_format)) except Exception: pass self._layout.addWidget(c, 9, 0, 1, 1) button_box = self.bb = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) button_box.accepted.connect(self.accept) button_box.rejected.connect(self.reject) self._layout.addWidget(button_box, 10, 0, 1, -1) self.resize(self.sizeHint()) def accept(self): gprefs['create_empty_format_file'] = self.format_value.currentText().lower() return QDialog.accept(self) def reset_author(self, *args): self.authors_combo.setEditText(_('Unknown')) def reset_series(self): self.series_combo.setEditText('') def initialize_authors(self, db, author): au = author if not au: au = _('Unknown') self.authors_combo.show_initial_value(au.replace('|', ',')) self.authors_combo.set_separator('&') self.authors_combo.set_space_before_sep(True) self.authors_combo.set_add_separator(tweaks['authors_completer_append_separator']) self.authors_combo.update_items_cache(db.all_author_names()) def initialize_series(self, db, series): self.series_combo.show_initial_value(series or '') self.series_combo.update_items_cache(db.all_series_names()) self.series_combo.set_separator(None) @property def qty_to_add(self): return self.qty_spinbox.value() @property def selected_authors(self): return string_to_authors(unicode(self.authors_combo.text())) @property def selected_series(self): return unicode(self.series_combo.text()) @property def selected_title(self): return self.title_edit.text().strip()
class XArmUI(object): def __init__(self, ui, layout): self.main_ui = ui self.layout = layout super(XArmUI, self).__init__() self.handler = XArmHandler(self) self.lang = self.main_ui.lang self.set_ui() self.set_disable(True) def set_ui(self): self._set_common_top_ui() self._set_tab() self._set_common_down_ui() self.connect_slot() def _set_common_top_ui(self): top_frame = QFrame() top_frame.setMaximumHeight(60) top_layout = QVBoxLayout(top_frame) self.layout.addWidget(top_frame) common_top_frame = QFrame() common_top_frame.setMinimumHeight(50) common_top_layout = QHBoxLayout(common_top_frame) top_layout.addWidget(common_top_frame) label_1 = QLabel(i18n[self.lang]['Connected'] + ':') self.label_connected = QLabel() img = QImage() self.label_connected.setMaximumHeight(20) self.label_connected.setMaximumWidth(20) self.label_connected.setScaledContents(True) if img.load(disconnect_icon_path): self.label_connected.setPixmap(QPixmap.fromImage(img)) label_2 = QLabel(i18n[self.lang]['Reported'] + ':') self.label_reported = QLabel() img = QImage() self.label_reported.setMaximumHeight(20) self.label_reported.setMaximumWidth(20) self.label_reported.setScaledContents(True) if img.load(disconnect_icon_path): self.label_reported.setPixmap(QPixmap.fromImage(img)) self.lnt_addr = QLineEdit('192.168.1.182') self.lnt_addr.setMaximumWidth(100) self.lnt_addr.setMinimumWidth(60) self.btn_connect = QPushButton(i18n[self.lang]['Connect']) # self.btn_connect.setMaximumWidth(50) # common_top_layout.addStretch(0) common_top_layout.setSpacing(10) common_top_layout.addWidget(label_1) common_top_layout.addWidget(self.label_connected) common_top_layout.addWidget(label_2) common_top_layout.addWidget(self.label_reported) common_top_layout.addWidget(self.lnt_addr) common_top_layout.addWidget(self.btn_connect) # common_down_frame = QFrame() # common_down_layout = QHBoxLayout(common_down_frame) # common_down_layout.setSpacing(0) # top_layout.addWidget(common_down_frame) common_down_layout = common_top_layout label = QLabel(i18n[self.lang]['WarnCode'] + ':') self.label_warn_code = QLabel('0') self.label_warn_code.setStyleSheet('''color: gray;font:bold;''') common_down_layout.addWidget(label) common_down_layout.addWidget(self.label_warn_code) label = QLabel(i18n[self.lang]['ErrorCode'] + ':') self.label_error_code = QLabel('0') self.label_error_code.setStyleSheet('''color: gray;font:bold;''') common_down_layout.addWidget(label) common_down_layout.addWidget(self.label_error_code) label = QLabel(i18n[self.lang]['CmdCount'] + ':') self.label_cmd_count = QLabel('0') self.label_cmd_count.setStyleSheet('''color: gray;font:bold;''') common_down_layout.addWidget(label) common_down_layout.addWidget(self.label_cmd_count) label = QLabel(i18n[self.lang]['State'] + ':') self.label_state = QLabel('4') self.label_state.setStyleSheet('''color: gray;font:bold;''') common_down_layout.addWidget(label) common_down_layout.addWidget(self.label_state) label = QLabel(i18n[self.lang]['Maable'] + ':') self.label_maable = QLabel('128') self.label_maable.setStyleSheet('''color: gray;font:bold;''') common_down_layout.addWidget(label) common_down_layout.addWidget(self.label_maable) label = QLabel(i18n[self.lang]['Mtbrake'] + ':') self.label_mtbrake = QLabel('128') self.label_mtbrake.setStyleSheet('''color: gray;font:bold;''') common_down_layout.addWidget(label) common_down_layout.addWidget(self.label_mtbrake) def _set_tab(self): tab_widget = QTabWidget() tab_widget.setMaximumHeight(self.main_ui.window.geometry().height() // 2) self.layout.addWidget(tab_widget) toolBox1 = QToolBox() toolBox2 = QToolBox() groupBox1 = QGroupBox() groupBox2 = QGroupBox() toolBox1.addItem(groupBox1, "") toolBox2.addItem(groupBox2, "") tab_widget.addTab(toolBox1, i18n[self.lang]['Joint']) tab_widget.addTab(toolBox2, i18n[self.lang]['Cartesian']) joint_layout = QVBoxLayout(groupBox1) cartesian_layout = QVBoxLayout(groupBox2) self.cartesian_ui = CartesianUI(self, cartesian_layout) self.axis_ui = JointUI(self, joint_layout) def _set_common_down_ui(self): slider_frame = QFrame() slider_layout = QGridLayout(slider_frame) self.layout.addWidget(slider_frame) label = QLabel(i18n[self.lang]['Speed'] + ':') self.slider_speed = QSlider(Qt.Horizontal) self.spinbox_speed = QSpinBox() self.slider_speed.setMinimum(1) self.slider_speed.setMaximum(1000) self.slider_speed.setValue(50) self.spinbox_speed.setSingleStep(1) self.spinbox_speed.setMinimum(1) self.spinbox_speed.setMaximum(1000) self.spinbox_speed.setValue(50) slider_layout.addWidget(label, 0, 0) slider_layout.addWidget(self.slider_speed, 0, 1) slider_layout.addWidget(self.spinbox_speed, 0, 2) label = QLabel(i18n[self.lang]['Acc'] + ':') self.slider_acc = QSlider(Qt.Horizontal) self.spinbox_acc = QSpinBox() self.slider_acc.setMinimum(1) self.slider_acc.setMaximum(100000) self.slider_acc.setValue(5000) self.spinbox_acc.setSingleStep(1) self.spinbox_acc.setMinimum(1) self.spinbox_acc.setMaximum(100000) self.spinbox_acc.setValue(5000) slider_layout.addWidget(label, 0, 3) slider_layout.addWidget(self.slider_acc, 0, 4) slider_layout.addWidget(self.spinbox_acc, 0, 5) common_frame = QFrame() common_layout = QGridLayout(common_frame) self.layout.addWidget(common_frame) self.btn_stop = QPushButton(i18n[self.lang]['Stop']) self.btn_clean = QPushButton(i18n[self.lang]['CleanErrorWarn']) self.btn_reset = QPushButton(i18n[self.lang]['Reset']) self.btn_get_servo_dbmsg = QPushButton( i18n[self.lang]['GetServoDebugMsg']) common_layout.addWidget(self.btn_stop, 0, 0) common_layout.addWidget(self.btn_clean, 0, 2) common_layout.addWidget(self.btn_reset, 0, 3) common_layout.addWidget(self.btn_get_servo_dbmsg, 0, 4) btn_frame = QFrame() btn_layout = QGridLayout(btn_frame) self.layout.addWidget(btn_frame) self.combobox_servo = QComboBox() self.combobox_servo.setStyleSheet('''color: blue;''') for item in [ 'axis-all', 'axis-1', 'axis-2', 'axis-3', 'axis-4', 'axis-5', 'axis-6', 'axis-7' ]: self.combobox_servo.addItem(item) self.combobox_servo.setCurrentIndex(1) btn_layout.addWidget(self.combobox_servo, 0, 0) self.btn_motion_enable = QPushButton(i18n[self.lang]['MotionEnable']) self.btn_motion_disable = QPushButton(i18n[self.lang]['MotionDisable']) self.btn_servo_attach = QPushButton(i18n[self.lang]['ServoAttach']) self.btn_servo_detach = QPushButton(i18n[self.lang]['ServoDetach']) self.combobox_state = QComboBox() self.combobox_state.setStyleSheet('''color: blue;''') for item in ['sport', 'pause', 'stop']: self.combobox_state.addItem(item) self.combobox_state.setCurrentIndex(0) self.btn_set_state = QPushButton(i18n[self.lang]['SetState']) btn_layout.addWidget(self.btn_motion_enable, 0, 1) btn_layout.addWidget(self.btn_motion_disable, 0, 2) btn_layout.addWidget(self.btn_servo_attach, 0, 3) btn_layout.addWidget(self.btn_servo_detach, 0, 4) btn_layout.addWidget(self.combobox_state, 0, 5) btn_layout.addWidget(self.btn_set_state, 0, 6) self.lnt_servo_addr = QLineEdit('servo_addr') self.lnt_servo_addr_value = QLineEdit('value') self.btn_get_servo_addr16 = QPushButton( i18n[self.lang]['GetServoAddr16']) self.btn_set_servo_addr16 = QPushButton( i18n[self.lang]['SetServoAddr16']) self.btn_get_servo_addr32 = QPushButton( i18n[self.lang]['GetServoAddr32']) self.btn_set_servo_addr32 = QPushButton( i18n[self.lang]['SetServoAddr32']) self.btn_set_servo_zero = QPushButton(i18n[self.lang]['SetServoZero']) btn_layout.addWidget(self.lnt_servo_addr, 1, 0) btn_layout.addWidget(self.lnt_servo_addr_value, 1, 1) btn_layout.addWidget(self.btn_get_servo_addr16, 1, 2) btn_layout.addWidget(self.btn_set_servo_addr16, 1, 3) btn_layout.addWidget(self.btn_get_servo_addr32, 1, 4) btn_layout.addWidget(self.btn_set_servo_addr32, 1, 5) btn_layout.addWidget(self.btn_set_servo_zero, 1, 6) def connect_slot(self): self.btn_connect.clicked.connect(self.connect) self.slider_speed.valueChanged.connect( functools.partial(self.slider_spinbox_related, slave=self.spinbox_speed, scale=1)) self.spinbox_speed.valueChanged.connect( functools.partial(self.slider_spinbox_related, slave=self.slider_speed, scale=1)) self.slider_acc.valueChanged.connect( functools.partial(self.slider_spinbox_related, slave=self.spinbox_acc, scale=1)) self.spinbox_acc.valueChanged.connect( functools.partial(self.slider_spinbox_related, slave=self.slider_acc, scale=1)) self.btn_stop.clicked.connect(self.stop) self.btn_clean.clicked.connect(self.clean) self.btn_reset.clicked.connect(self.reset) self.btn_get_servo_dbmsg.clicked.connect( functools.partial(self.handler.get_servo_debug_msg, only_log_error_servo=False)) self.btn_motion_enable.clicked.connect(self.motion_enable) self.btn_motion_disable.clicked.connect(self.motion_disable) self.btn_servo_attach.clicked.connect(self.set_servo_attach) self.btn_servo_detach.clicked.connect(self.set_servo_detach) self.btn_set_state.clicked.connect(self.set_state) self.btn_get_servo_addr16.clicked.connect(self.get_servo_addr_16) self.btn_set_servo_addr16.clicked.connect(self.set_servo_addr_16) self.btn_get_servo_addr32.clicked.connect(self.get_servo_addr_32) self.btn_set_servo_addr32.clicked.connect(self.set_servo_addr_32) self.btn_set_servo_zero.clicked.connect(self.set_servo_zero) @staticmethod def slider_spinbox_related(value, master=None, slave=None, scale=1): try: slave.setValue(value * scale) except Exception as e: print(e) def reset_flag(self): self.cartesian_ui.reset_flag() self.axis_ui.reset_flag() def update_maable_mtbrake(self, maable, mtbrake): try: self.label_maable.setText(str(maable)) self.label_mtbrake.setText(str(mtbrake)) self.label_maable.setStyleSheet('''color: green;font:bold;''') self.label_mtbrake.setStyleSheet('''color: green;font:bold;''') except Exception as e: print(e) def update_cmd_count(self, cmdnum): try: self.label_cmd_count.setText(str(cmdnum)) self.label_cmd_count.setStyleSheet('''color: green;font:bold;''') except Exception as e: print(e) def update_state(self, state): try: if state == 1: state_str = 'sport' self.label_state.setText(state_str) self.label_state.setStyleSheet('''color: green;font:bold;''') elif state == 2: state_str = 'sleep' self.label_state.setText(state_str) self.label_state.setStyleSheet('''color: gray;font:bold;''') elif state == 3: state_str = 'pause' self.label_state.setText(state_str) self.label_state.setStyleSheet('''color: orange;font:bold;''') elif state == 4: state_str = 'stop' self.label_state.setText(state_str) self.label_state.setStyleSheet('''color: red;font:bold;''') except Exception as e: print(e) # getattr(self, 'label_state').setText(state_str) # getattr(self, 'label_state').setText(str(state)) if state != 1: self.reset_flag() def update_warn_error(self, item): try: warn, error = item self.label_warn_code.setText(str(warn)) self.label_error_code.setText(str(error)) if warn != 0: self.label_warn_code.setStyleSheet('''color: red;font:bold;''') else: self.label_warn_code.setStyleSheet( '''color: green;font:bold;''') if error != 0: self.label_error_code.setStyleSheet( '''color: red;font:bold;''') else: self.label_error_code.setStyleSheet( '''color: green;font:bold;''') except Exception as e: print(e) def update_connect_status(self, item): try: img = QImage() if item[0]: logger.info('connect to {} success, report: {}'.format( self.handler.addr, self.handler.report_type)) if img.load(connect_icon_path): self.label_connected.setPixmap(QPixmap.fromImage(img)) self.btn_connect.setText(i18n[self.lang]['Disconnect']) self.btn_connect.setStyleSheet('''color: red;font:bold;''') self.set_disable(False) else: logger.info('disconnect from or failed connect {}'.format( self.handler.addr)) self.handler.cmd_que.queue.clear() if img.load(disconnect_icon_path): self.label_connected.setPixmap(QPixmap.fromImage(img)) self.btn_connect.setText(i18n[self.lang]['Connect']) self.btn_connect.setStyleSheet( '''color: green;font:bold;''') self.set_disable(True) if item[1]: if img.load(connect_icon_path): self.label_reported.setPixmap(QPixmap.fromImage(img)) else: if img.load(disconnect_icon_path): self.label_reported.setPixmap(QPixmap.fromImage(img)) except Exception as e: print(e) def connect(self, event): try: if str(self.btn_connect.text()) == i18n[self.lang]['Connect']: addr = self.lnt_addr.text().strip() if addr == '192.168.1.': addr = 'localhost' report_type = 'normal' else: tmp = addr.split(':') addr = tmp[0] report_type = tmp[1] if len(tmp) > 1 else 'normal' self.btn_connect.setText('Connecting') self.btn_connect.setStyleSheet('''color: orange;font:bold;''') self.handler.connect(addr, report_type=report_type) # if self.window.connect(addr, report_type=report_type): # self.btn_connect.setText(self.disconnect_label) # self.btn_connect.setStyleSheet('''color: red;font:bold;''') elif str(self.btn_connect.text()) == i18n[self.lang]['Disconnect']: self.handler.disconnect() self.btn_connect.setText(i18n[self.lang]['Connect']) self.btn_connect.setStyleSheet('''color: green;font:bold;''') except Exception as e: print(e) def stop(self, event): try: self.handler.cmd_que.queue.clear() if self.handler.xarm and self.handler.xarm.warn_code != 0: item = { 'cmd': 'clean_warn', } self.handler.put_cmd_que(item) if self.handler.xarm and self.handler.xarm.error_code != 0: item = { 'cmd': 'clean_error', } self.handler.put_cmd_que(item) item = { 'cmd': 'motion_enable', 'kwargs': { 'servo_id': 0, 'enable': True } } self.handler.put_cmd_que(item) item = { 'cmd': 'urgent_stop', } self.handler.put_cmd_que(item) self.reset_flag() except Exception as e: print(e) def clean(self, event): try: self.handler.cmd_que.queue.clear() if self.handler.xarm and self.handler.xarm.warn_code != 0: item = { 'cmd': 'clean_warn', } self.handler.put_cmd_que(item) if self.handler.xarm and self.handler.xarm.error_code != 0: item = { 'cmd': 'clean_error', } self.handler.put_cmd_que(item) except Exception as e: print(e) def reset(self, event): try: self.handler.cmd_que.queue.clear() if self.handler.xarm and self.handler.xarm.warn_code != 0: item = { 'cmd': 'clean_warn', } self.handler.put_cmd_que(item) if self.handler.xarm and self.handler.xarm.error_code != 0: item = { 'cmd': 'clean_error', } self.handler.put_cmd_que(item) item = { 'cmd': 'motion_enable', 'kwargs': { 'servo_id': 0, 'enable': True } } self.handler.put_cmd_que(item) item = {'cmd': 'set_state', 'kwargs': {'state': 0}} self.handler.put_cmd_que(item) item = { 'cmd': 'move_gohome', 'kwargs': { 'speed': 30, 'mvacc': 5000, } } self.handler.put_cmd_que(item) self.reset_flag() except Exception as e: print(e) def get_servo_addr_16(self, event): try: addr = self.lnt_servo_addr.text().strip() try: if addr.lower().startswith('0x'): addr = int(addr, base=16) else: addr = int(addr) except: QMessageBox.warning(self.main_ui.window, '错误', '请输入正确的地址, 地址必须是u16类型') return text = self.combobox_servo.currentText() if text == 'axis-all': QMessageBox.warning(self.main_ui.window, '警告', '请选择其中一个电机,不能选择所有电机') return else: servo_id = int(text.split('-')[-1]) tmp = '你确定要获取电机{}的地址{}的值吗?'.format(servo_id, addr) if QMessageBox.question(self.main_ui.window, '警告', tmp) == QMessageBox.Yes: item = { 'cmd': 'get_servo_addr_16', 'kwargs': { 'servo_id': servo_id, 'addr': addr } } self.handler.put_cmd_que(item) except Exception as e: print(e) def get_servo_addr_32(self, event): try: addr = self.lnt_servo_addr.text().strip() try: if addr.lower().startswith('0x'): addr = int(addr, base=16) else: addr = int(addr) except: QMessageBox.warning(self.main_ui.window, '错误', '请输入正确的地址, 地址必须是u16类型') return text = self.combobox_servo.currentText() if text == 'axis-all': QMessageBox.warning(self.main_ui.window, '警告', '请选择其中一个电机,不能选择所有电机') return else: servo_id = int(text.split('-')[-1]) tmp = '你确定要获取电机{}的地址{}的值吗?'.format(servo_id, addr) if QMessageBox.question(self.main_ui.window, '警告', tmp) == QMessageBox.Yes: item = { 'cmd': 'get_servo_addr_32', 'kwargs': { 'servo_id': servo_id, 'addr': addr } } self.handler.put_cmd_que(item) except Exception as e: print(e) def set_servo_addr_16(self, event): try: addr = self.lnt_servo_addr.text().strip() try: if addr.lower().startswith('0x'): addr = int(addr, base=16) else: addr = int(addr) except: QMessageBox.warning(self.main_ui.window, '错误', '请输入正确的地址, 地址必须是u16类型') return value = self.lnt_servo_addr_value.text().strip() try: value = float(value) except: QMessageBox.warning(self.main_ui.window, '错误', '请输入正确的值, 值必须是float32类型') return text = self.combobox_servo.currentText() if text == 'axis-all': QMessageBox.warning(self.main_ui.window, '警告', '请选择其中一个电机,不能选择所有电机') return else: servo_id = int(text.split('-')[-1]) tmp = '你确定要设置电机{}的地址{}的值为{}吗?'.format(servo_id, addr, value) if QMessageBox.question(self.main_ui.window, '警告', tmp) == QMessageBox.Yes: item = { 'cmd': 'set_servo_addr_16', 'kwargs': { 'servo_id': servo_id, 'addr': addr, 'value': value } } self.handler.put_cmd_que(item) except Exception as e: print(e) def set_servo_addr_32(self, event): try: addr = self.lnt_servo_addr.text().strip() try: if addr.lower().startswith('0x'): addr = int(addr, base=16) else: addr = int(addr) except: QMessageBox.warning(self.main_ui.window, '错误', '请输入正确的地址, 地址必须是u16类型') return value = self.lnt_servo_addr_value.text().strip() try: value = float(value) except: QMessageBox.warning(self.main_ui.window, '错误', '请输入正确的值, 值必须是float32类型') return text = self.combobox_servo.currentText() if text == 'axis-all': QMessageBox.warning(self.main_ui.window, '警告', '请选择其中一个电机,不能选择所有电机') return else: servo_id = int(text.split('-')[-1]) tmp = '你确定要设置电机{}的地址{}的值为{}吗?'.format(servo_id, addr, value) if QMessageBox.question(self.main_ui.window, '警告', tmp) == QMessageBox.Yes: item = { 'cmd': 'set_servo_addr_32', 'kwargs': { 'servo_id': servo_id, 'addr': addr, 'value': value } } self.handler.put_cmd_que(item) except Exception as e: print(e) def set_servo_zero(self, event): try: text = self.combobox_servo.currentText() if text == 'axis-all': servo_id = 8 else: servo_id = int(text.split('-')[-1]) if servo_id == 8: tmp = '你确定要设置所有电机的零点吗?' else: tmp = '你确定要设置电机{}的零点吗?'.format(servo_id) if QMessageBox.question(self.main_ui.window, '警告', tmp) == QMessageBox.Yes: item = { 'cmd': 'set_servo_zero', 'kwargs': { 'servo_id': servo_id } } self.handler.put_cmd_que(item) except Exception as e: print(e) def set_servo_attach(self, event): try: text = self.combobox_servo.currentText() if text == 'axis-all': servo_id = 8 else: servo_id = int(text.split('-')[-1]) item = { 'cmd': 'set_servo_attach', 'kwargs': { 'servo_id': servo_id } } self.handler.put_cmd_que(item) item = { 'cmd': 'motion_enable', 'kwargs': { 'servo_id': servo_id, 'enable': True } } self.handler.put_cmd_que(item) item = {'cmd': 'set_state', 'kwargs': {'state': 0}} self.handler.put_cmd_que(item) except Exception as e: print(e) def set_servo_detach(self, event): try: text = self.combobox_servo.currentText() if text == 'axis-all': servo_id = 8 else: servo_id = int(text.split('-')[-1]) if servo_id == 8: tmp = '你确定要解锁所有电机吗?' else: tmp = '你确定要解锁电机{}吗?'.format(servo_id) if QMessageBox.question(self.main_ui.window, '警告', tmp) == QMessageBox.Yes: item = { 'cmd': 'set_servo_detach', 'kwargs': { 'servo_id': servo_id } } self.handler.put_cmd_que(item) except Exception as e: print(e) def motion_enable(self, event): self._motion_enable(True) def motion_disable(self, event): self._motion_enable(False) def _motion_enable(self, enable=True): try: text = self.combobox_servo.currentText() if text == 'axis-all': servo_id = 8 else: servo_id = int(text.split('-')[-1]) item = { 'cmd': 'motion_enable', 'kwargs': { 'servo_id': servo_id, 'enable': enable } } self.handler.put_cmd_que(item) except Exception as e: print(e) def set_state(self, event): try: text = self.combobox_state.currentText() if text == 'sport': state = 0 elif text == 'pause': state = 3 elif text == 'stop': state = 4 else: return if state in [0, 3, 4]: item = {'cmd': 'set_state', 'kwargs': {'state': state}} self.handler.put_cmd_que(item) except Exception as e: print(e) def set_disable(self, disable): try: self.btn_stop.setDisabled(disable) self.btn_clean.setDisabled(disable) self.btn_reset.setDisabled(disable) self.btn_get_servo_dbmsg.setDisabled(disable) self.combobox_servo.setDisabled(disable) self.combobox_state.setDisabled(disable) self.btn_motion_enable.setDisabled(disable) self.btn_motion_disable.setDisabled(disable) self.btn_servo_attach.setDisabled(disable) self.btn_servo_detach.setDisabled(disable) self.btn_set_state.setDisabled(disable) self.lnt_servo_addr.setDisabled(disable) self.lnt_servo_addr_value.setDisabled(disable) self.btn_get_servo_addr16.setDisabled(disable) self.btn_set_servo_addr16.setDisabled(disable) self.btn_get_servo_addr32.setDisabled(disable) self.btn_set_servo_addr32.setDisabled(disable) self.btn_set_servo_zero.setDisabled(disable) self.slider_speed.setDisabled(disable) self.spinbox_speed.setDisabled(disable) self.slider_acc.setDisabled(disable) self.spinbox_acc.setDisabled(disable) self.axis_ui.set_disable(disable) self.cartesian_ui.set_disable(disable) except Exception as e: print(e)
class UArmUI(object): def __init__(self, ui, layout): self.main_ui = ui self.layout = layout super(UArmUI, self).__init__() self.handler = UArmHandler(self) self.lang = self.main_ui.lang self.status = 0 self.set_ui() self.set_disable(True) def set_ui(self): self._set_common_top_ui() self._set_tab() self._set_common_down_ui() self.connect_slot() def _set_common_top_ui(self): top_frame = QFrame() top_frame.setMaximumHeight(60) top_layout = QVBoxLayout(top_frame) self.layout.addWidget(top_frame) common_top_frame = QFrame() common_top_frame.setMinimumHeight(50) common_top_frame.setMaximumHeight(50) common_top_layout = QHBoxLayout(common_top_frame) top_layout.addWidget(common_top_frame) common_top_layout.addStretch(0) label = QLabel(i18n[self.lang]['Type'] + ':') self.label_type = QLabel('') self.label_type.setStyleSheet('''color: gray;font:bold;''') common_top_layout.addWidget(label) common_top_layout.addWidget(self.label_type) label = QLabel(i18n[self.lang]['Mode'] + ':') self.label_mode = QLabel('') self.label_mode.setStyleSheet('''color: gray;font:bold;''') common_top_layout.addWidget(label) common_top_layout.addWidget(self.label_mode) label = QLabel(i18n[self.lang]['HardwareVersion'] + ':') self.label_hard_version = QLabel('') self.label_hard_version.setStyleSheet('''color: gray;font:bold;''') common_top_layout.addWidget(label) common_top_layout.addWidget(self.label_hard_version) label = QLabel(i18n[self.lang]['FirmwareVersion'] + ':') self.label_firm_version = QLabel('') self.label_firm_version.setStyleSheet('''color: gray;font:bold;''') common_top_layout.addWidget(label) common_top_layout.addWidget(self.label_firm_version) label_1 = QLabel(i18n[self.lang]['Connected'] + ':') self.label_connected = QLabel() img = QImage() self.label_connected.setMaximumHeight(20) self.label_connected.setMaximumWidth(20) self.label_connected.setScaledContents(True) if img.load(disconnect_icon_path): self.label_connected.setPixmap(QPixmap.fromImage(img)) self.lnt_addr = QLineEdit('COM12') self.lnt_addr.setMaximumWidth(50) self.lnt_addr.setMinimumWidth(30) self.btn_connect = QPushButton(i18n[self.lang]['Connect']) # self.btn_connect.setMaximumWidth(50) # common_top_layout.addStretch(0) common_top_layout.setSpacing(10) common_top_layout.addWidget(label_1) common_top_layout.addWidget(self.label_connected) common_top_layout.addWidget(self.lnt_addr) common_top_layout.addWidget(self.btn_connect) def _set_common_down_ui(self): slider_frame = QFrame() slider_layout = QGridLayout(slider_frame) self.layout.addWidget(slider_frame) label = QLabel(i18n[self.lang]['Speed'] + ':') self.slider_speed = QSlider(Qt.Horizontal) self.spinbox_speed = QSpinBox() self.slider_speed.setMinimum(1) self.slider_speed.setMaximum(100000) self.slider_speed.setValue(10000) self.spinbox_speed.setSingleStep(1) self.spinbox_speed.setMinimum(1) self.spinbox_speed.setMaximum(100000) self.spinbox_speed.setValue(10000) slider_layout.addWidget(label, 0, 0) slider_layout.addWidget(self.slider_speed, 0, 1) slider_layout.addWidget(self.spinbox_speed, 0, 2) # label = QLabel(i18n[self.lang]['Acc'] + ':') # self.slider_acc = QSlider(Qt.Horizontal) # self.spinbox_acc = QSpinBox() # self.slider_acc.setMinimum(1) # self.slider_acc.setMaximum(100000) # self.slider_acc.setValue(5000) # self.spinbox_acc.setSingleStep(1) # self.spinbox_acc.setMinimum(1) # self.spinbox_acc.setMaximum(100000) # self.spinbox_acc.setValue(5000) # slider_layout.addWidget(label, 0, 3) # slider_layout.addWidget(self.slider_acc, 0, 4) # slider_layout.addWidget(self.spinbox_acc, 0, 5) btn_frame = QFrame() btn_layout = QGridLayout(btn_frame) self.layout.addWidget(btn_frame) self.btn_get_device_info = QPushButton(i18n[self.lang]['GetDeviceInfo']) self.btn_get_position = QPushButton(i18n[self.lang]['GetPosition']) self.btn_get_polar = QPushButton(i18n[self.lang]['GetPolar']) self.btn_get_servo_angle = QPushButton(i18n[self.lang]['GetServoAngle']) self.btn_get_mode = QPushButton(i18n[self.lang]['GetMode']) btn_layout.addWidget(self.btn_get_device_info, 0, 0) btn_layout.addWidget(self.btn_get_position, 0, 1) btn_layout.addWidget(self.btn_get_polar, 0, 2) btn_layout.addWidget(self.btn_get_servo_angle, 0, 3) btn_layout.addWidget(self.btn_get_mode, 0, 4) self.combobox_servo = QComboBox() self.combobox_servo.setStyleSheet('''color: blue;''') for item in ['axis-1', 'axis-2', 'axis-3', 'axis-all']: self.combobox_servo.addItem(item) self.combobox_servo.setCurrentIndex(0) btn_layout.addWidget(self.combobox_servo, 0, 0) self.btn_servo_attach = QPushButton(i18n[self.lang]['ServoAttach']) self.btn_servo_detach = QPushButton(i18n[self.lang]['ServoDetach']) self.combobox_mode = QComboBox() self.combobox_mode.setStyleSheet('''color: blue;''') for item in ['normal', 'laser', '3D', 'pen']: self.combobox_mode.addItem(item) self.combobox_mode.setCurrentIndex(0) self.btn_set_mode = QPushButton(i18n[self.lang]['SetMode']) btn_layout.addWidget(self.combobox_servo, 1, 0) btn_layout.addWidget(self.btn_servo_attach, 1, 1) btn_layout.addWidget(self.btn_servo_detach, 1, 2) btn_layout.addWidget(self.combobox_mode, 1, 3) btn_layout.addWidget(self.btn_set_mode, 1, 4) self.btn_reset = QPushButton(i18n[self.lang]['Reset']) self.btn_pump_on = QPushButton(i18n[self.lang]['PumpOn']) self.btn_pump_off = QPushButton(i18n[self.lang]['PumpOff']) self.btn_gripper_catch = QPushButton(i18n[self.lang]['GripperCatch']) self.btn_gripper_release = QPushButton(i18n[self.lang]['GripperRelease']) btn_layout.addWidget(self.btn_reset, 2, 0) btn_layout.addWidget(self.btn_pump_on, 2, 1) btn_layout.addWidget(self.btn_pump_off, 2, 2) btn_layout.addWidget(self.btn_gripper_catch, 2, 3) btn_layout.addWidget(self.btn_gripper_release, 2, 4) @staticmethod def slider_spinbox_related(value, master=None, slave=None, scale=1): try: slave.setValue(value * scale) except Exception as e: print(e) def connect_slot(self): self.btn_connect.clicked.connect(self.connect) self.slider_speed.valueChanged.connect( functools.partial(self.slider_spinbox_related, slave=self.spinbox_speed, scale=1)) self.spinbox_speed.valueChanged.connect( functools.partial(self.slider_spinbox_related, slave=self.slider_speed, scale=1)) # self.slider_acc.valueChanged.connect( # functools.partial(self.slider_spinbox_related, slave=self.spinbox_acc, scale=1)) # self.spinbox_acc.valueChanged.connect( # functools.partial(self.slider_spinbox_related, slave=self.slider_acc, scale=1)) self.btn_get_device_info.clicked.connect(self.get_device_info) self.btn_get_position.clicked.connect(self.get_position) self.btn_get_polar.clicked.connect(self.get_polar) self.btn_get_servo_angle.clicked.connect(self.get_servo_angle) self.btn_get_mode.clicked.connect(self.get_mode) self.btn_servo_attach.clicked.connect(self.set_servo_attach) self.btn_servo_detach.clicked.connect(self.set_servo_detach) self.btn_set_mode.clicked.connect(self.set_mode) self.btn_reset.clicked.connect(self.reset) self.btn_pump_on.clicked.connect(self.pump_on) self.btn_pump_off.clicked.connect(self.pump_off) self.btn_gripper_catch.clicked.connect(self.gripper_catch) self.btn_gripper_release.clicked.connect(self.gripper_release) def reset_flag(self): self.cartesian_ui.reset_flag() self.axis_ui.reset_flag() def update_connect_status(self, item): try: img = QImage() if item and self.status != 1: self.status = 1 logger.info('connect to {} success'.format(self.handler.port)) if img.load(connect_icon_path): self.label_connected.setPixmap(QPixmap.fromImage(img)) self.btn_connect.setText(i18n[self.lang]['Disconnect']) self.btn_connect.setStyleSheet('''color: red;font:bold;''') self.set_disable(False) elif not item and self.status != 0: self.status = 0 logger.info('disconnect from {0} or failed connect {0}'.format(self.handler.port)) self.handler.cmd_que.queue.clear() if img.load(disconnect_icon_path): self.label_connected.setPixmap(QPixmap.fromImage(img)) self.btn_connect.setText(i18n[self.lang]['Connect']) self.btn_connect.setStyleSheet('''color: green;font:bold;''') self.set_disable(True) except Exception as e: print(e) def connect(self): try: if str(self.btn_connect.text()) == i18n[self.lang]['Connect']: addr = self.lnt_addr.text().strip() if addr == 'auto': addr = None self.btn_connect.setText('Connecting') self.status = 2 self.btn_connect.setStyleSheet('''color: orange;font:bold;''') self.handler.connect(addr) # if self.window.connect(addr, report_type=report_type): # self.btn_connect.setText(self.disconnect_label) # self.btn_connect.setStyleSheet('''color: red;font:bold;''') elif str(self.btn_connect.text()) == i18n[self.lang]['Disconnect']: self.handler.disconnect() self.btn_connect.setText(i18n[self.lang]['Connect']) self.btn_connect.setStyleSheet('''color: green;font:bold;''') except Exception as e: print(e) def get_device_info(self, event): try: item = { 'cmd': 'get_device_info', } self.handler.put_cmd_que(item) except Exception as e: print(e) def get_mode(self, event): try: item = { 'cmd': 'get_mode', } self.handler.put_cmd_que(item) except Exception as e: print(e) def get_position(self, event): try: item = { 'cmd': 'get_position', } self.handler.put_cmd_que(item) except Exception as e: print(e) def get_polar(self, event): try: item = { 'cmd': 'get_polar', } self.handler.put_cmd_que(item) except Exception as e: print(e) def get_servo_angle(self, event): try: item = { 'cmd': 'get_servo_angle', } self.handler.put_cmd_que(item) except Exception as e: print(e) def set_servo_attach(self, event): try: text = self.combobox_servo.currentText() if text == 'axis-all': servo_id = None else: servo_id = int(self.combobox_servo.currentIndex()) item = { 'cmd': 'set_servo_attach', 'kwargs': { 'servo_id': servo_id } } self.handler.put_cmd_que(item) except Exception as e: print(e) def set_servo_detach(self, event): try: text = self.combobox_servo.currentText() if text == 'axis-all': servo_id = None else: servo_id = int(self.combobox_servo.currentIndex()) item = { 'cmd': 'set_servo_detach', 'kwargs': { 'servo_id': servo_id } } self.handler.put_cmd_que(item) except Exception as e: print(e) def pump_on(self, event): try: item = { 'cmd': 'set_pump', 'kwargs': { 'on': True } } self.handler.put_cmd_que(item) except Exception as e: print(e) def pump_off(self, event): try: item = { 'cmd': 'set_pump', 'kwargs': { 'on': False } } self.handler.put_cmd_que(item) except Exception as e: print(e) def gripper_catch(self, event): try: item = { 'cmd': 'set_gripper', 'kwargs': { 'catch': True } } self.handler.put_cmd_que(item) except Exception as e: print(e) def gripper_release(self, event): try: item = { 'cmd': 'set_gripper', 'kwargs': { 'catch': False } } self.handler.put_cmd_que(item) except Exception as e: print(e) def set_mode(self, event): try: mode = self.combobox_mode.currentIndex() item = { 'cmd': 'set_mode', 'kwargs': { 'mode': int(mode) } } self.handler.put_cmd_que(item) except Exception as e: print(e) def reset(self, event): try: self.handler.cmd_que.queue.clear() item = { 'cmd': 'reset', 'kwargs': { 'speed': self.spinbox_speed.value(), 'wait': False, } } self.handler.put_cmd_que(item) self.reset_flag() except Exception as e: print(e) @staticmethod def slider_spinbox_related(value, master=None, slave=None, scale=1): try: slave.setValue(value * scale) except Exception as e: print(e) def _set_tab(self): tab_widget = QTabWidget() tab_widget.setMaximumHeight(self.main_ui.window.geometry().height() // 2) self.layout.addWidget(tab_widget) toolBox1 = QToolBox() toolBox2 = QToolBox() groupBox1 = QGroupBox() groupBox2 = QGroupBox() toolBox1.addItem(groupBox1, "") toolBox2.addItem(groupBox2, "") tab_widget.addTab(toolBox1, i18n[self.lang]['Angle']) tab_widget.addTab(toolBox2, i18n[self.lang]['Coordinate']) joint_layout = QVBoxLayout(groupBox1) cartesian_layout = QVBoxLayout(groupBox2) self.cartesian_ui = CoordinateUI(self, cartesian_layout) self.axis_ui = AngleUI(self, joint_layout) def update_device_info(self, device_info): if device_info is not None: self.label_type.setText(str(device_info.get('device_type', None))) self.label_hard_version.setText(str(device_info.get('hardware_version', None))) self.label_firm_version.setText(str(device_info.get('firmware_version', None))) def update_mode(self, mode): if mode is not None: if mode == 0: mode_str = 'Normal' elif mode == 1: mode_str = 'Laser' elif mode == 2: mode_str = '3D' elif mode == 3: mode_str = 'Pen' else: mode_str = self.label_mode.text() self.label_mode.setText(mode_str) def set_disable(self, disable): try: self.btn_get_device_info.setDisabled(disable) self.btn_get_position.setDisabled(disable) self.btn_get_polar.setDisabled(disable) self.btn_get_servo_angle.setDisabled(disable) self.btn_get_mode.setDisabled(disable) self.combobox_servo.setDisabled(disable) self.combobox_mode.setDisabled(disable) self.btn_servo_attach.setDisabled(disable) self.btn_servo_detach.setDisabled(disable) self.btn_reset.setDisabled(disable) self.btn_pump_on.setDisabled(disable) self.btn_pump_off.setDisabled(disable) self.btn_gripper_catch.setDisabled(disable) self.btn_gripper_release.setDisabled(disable) self.slider_speed.setDisabled(disable) self.spinbox_speed.setDisabled(disable) # self.slider_acc.setDisabled(disable) # self.spinbox_acc.setDisabled(disable) self.axis_ui.set_disable(disable) self.cartesian_ui.set_disable(disable) except Exception as e: print(e)
class AddEmptyBookDialog(QDialog): def __init__(self, parent, db, author, series=None): QDialog.__init__(self, parent) self.db = db self.setWindowTitle(_('How many empty books?')) self._layout = QGridLayout(self) self.setLayout(self._layout) self.qty_label = QLabel(_('How many empty books should be added?')) self._layout.addWidget(self.qty_label, 0, 0, 1, 2) self.qty_spinbox = QSpinBox(self) self.qty_spinbox.setRange(1, 10000) self.qty_spinbox.setValue(1) self._layout.addWidget(self.qty_spinbox, 1, 0, 1, 2) self.author_label = QLabel(_('Set the author of the new books to:')) self._layout.addWidget(self.author_label, 2, 0, 1, 2) self.authors_combo = EditWithComplete(self) self.authors_combo.setSizeAdjustPolicy( self.authors_combo.AdjustToMinimumContentsLengthWithIcon) self.authors_combo.setEditable(True) self._layout.addWidget(self.authors_combo, 3, 0, 1, 1) self.initialize_authors(db, author) self.clear_button = QToolButton(self) self.clear_button.setIcon(QIcon(I('trash.png'))) self.clear_button.setToolTip(_('Reset author to Unknown')) self.clear_button.clicked.connect(self.reset_author) self._layout.addWidget(self.clear_button, 3, 1, 1, 1) self.series_label = QLabel(_('Set the series of the new books to:')) self._layout.addWidget(self.series_label, 4, 0, 1, 2) self.series_combo = EditWithComplete(self) self.authors_combo.setSizeAdjustPolicy( self.authors_combo.AdjustToMinimumContentsLengthWithIcon) self.series_combo.setEditable(True) self._layout.addWidget(self.series_combo, 5, 0, 1, 1) self.initialize_series(db, series) self.sclear_button = QToolButton(self) self.sclear_button.setIcon(QIcon(I('trash.png'))) self.sclear_button.setToolTip(_('Reset series')) self.sclear_button.clicked.connect(self.reset_series) self._layout.addWidget(self.sclear_button, 5, 1, 1, 1) self.create_epub = c = QCheckBox(_('Create an empty EPUB file as well')) c.setChecked(gprefs.get('create_empty_epub_file', False)) c.setToolTip(_('Also create an empty EPUB file that you can subsequently edit')) self._layout.addWidget(c, 6, 0, 1, -1) button_box = self.bb = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) button_box.accepted.connect(self.accept) button_box.rejected.connect(self.reject) self._layout.addWidget(button_box, 7, 0, 1, -1) self.resize(self.sizeHint()) def accept(self): oval = gprefs.get('create_empty_epub_file', False) if self.create_epub.isChecked() != oval: gprefs['create_empty_epub_file'] = self.create_epub.isChecked() return QDialog.accept(self) def reset_author(self, *args): self.authors_combo.setEditText(_('Unknown')) def reset_series(self): self.series_combo.setEditText('') def initialize_authors(self, db, author): au = author if not au: au = _('Unknown') self.authors_combo.show_initial_value(au.replace('|', ',')) self.authors_combo.set_separator('&') self.authors_combo.set_space_before_sep(True) self.authors_combo.set_add_separator(tweaks['authors_completer_append_separator']) self.authors_combo.update_items_cache(db.all_author_names()) def initialize_series(self, db, series): self.series_combo.show_initial_value(series or '') self.series_combo.update_items_cache(db.all_series_names()) self.series_combo.set_separator(None) @property def qty_to_add(self): return self.qty_spinbox.value() @property def selected_authors(self): return string_to_authors(unicode(self.authors_combo.text())) @property def selected_series(self): return unicode(self.series_combo.text())
class TabRewards_gui(QWidget): def __init__(self, imgDir, *args, **kwargs): QWidget.__init__(self) self.imgDir = imgDir self.initRewardsForm() mainVertical = QVBoxLayout() mainVertical.addWidget(self.rewardsForm) buttonbox = QHBoxLayout() buttonbox.addStretch(1) buttonbox.addWidget(self.btn_Cancel) mainVertical.addLayout(buttonbox) self.setLayout(mainVertical) def initRewardsForm(self): self.rewardsForm = QGroupBox() self.rewardsForm.setTitle("Transfer UTXOs") layout = QFormLayout() layout.setContentsMargins(10, 10, 10, 10) layout.setSpacing(13) layout.setFieldGrowthPolicy(QFormLayout.AllNonFixedFieldsGrow) ##--- ROW 1 line1 = QHBoxLayout() line1.addWidget(QLabel("Account HW")) self.edt_hwAccount = QSpinBox() self.edt_hwAccount.setMaximum(9999) self.edt_hwAccount.setFixedWidth(50) self.edt_hwAccount.setToolTip( "account number of the hardware wallet.\nIf unsure put 0") self.edt_hwAccount.setValue(0) line1.addWidget(self.edt_hwAccount) line1.addWidget(QLabel("spath from")) self.edt_spathFrom = QSpinBox() self.edt_spathFrom.setMaximum(9999) self.edt_spathFrom.setFixedWidth(50) self.edt_spathFrom.setToolTip("starting address n.") self.edt_spathFrom.setValue(0) line1.addWidget(self.edt_spathFrom) line1.addWidget(QLabel("spath to")) self.edt_spathTo = QSpinBox() self.edt_spathTo.setMaximum(9999) self.edt_spathTo.setFixedWidth(50) self.edt_spathTo.setToolTip("ending address n.") self.edt_spathTo.setValue(10) line1.addWidget(self.edt_spathTo) line1.addWidget(QLabel("internal/external")) self.edt_internalExternal = QSpinBox() self.edt_internalExternal.setFixedWidth(50) self.edt_internalExternal.setToolTip("ending address n.") self.edt_internalExternal.setValue(0) self.edt_internalExternal.setMaximum(1) line1.addWidget(self.edt_internalExternal) line1.addStretch(1) self.btn_reload = QPushButton("Scan Ledger device") self.btn_reload.setToolTip("Reload data from ledger device") line1.addWidget(self.btn_reload) layout.addRow(line1) hBox = QHBoxLayout() self.addySelect = QComboBox() self.addySelect.setToolTip("Select Address") hBox.addWidget(self.addySelect) layout.addRow(hBox) ## --- ROW 2: UTXOs self.rewardsList = QVBoxLayout() self.rewardsList.statusLabel = QLabel( '<b style="color:red">Reload Rewards</b>') self.rewardsList.statusLabel.setVisible(True) self.rewardsList.addWidget(self.rewardsList.statusLabel) self.rewardsList.box = QTableWidget() self.rewardsList.box.setMinimumHeight(200) #self.rewardsList.box.setMaximumHeight(140) self.rewardsList.box.setHorizontalScrollBarPolicy( Qt.ScrollBarAlwaysOff) self.rewardsList.box.setSelectionMode(QAbstractItemView.MultiSelection) self.rewardsList.box.setSelectionBehavior(QAbstractItemView.SelectRows) self.rewardsList.box.setShowGrid(True) self.rewardsList.box.setColumnCount(4) self.rewardsList.box.setRowCount(0) self.rewardsList.box.horizontalHeader().setSectionResizeMode( 2, QHeaderView.Stretch) self.rewardsList.box.verticalHeader().hide() item = QTableWidgetItem() item.setText("PIVs") item.setTextAlignment(Qt.AlignCenter) self.rewardsList.box.setHorizontalHeaderItem(0, item) item = QTableWidgetItem() item.setText("Confirmations") item.setTextAlignment(Qt.AlignCenter) self.rewardsList.box.setHorizontalHeaderItem(1, item) item = QTableWidgetItem() item.setText("TX Hash") item.setTextAlignment(Qt.AlignCenter) self.rewardsList.box.setHorizontalHeaderItem(2, item) item = QTableWidgetItem() item.setText("TX Output N") item.setTextAlignment(Qt.AlignCenter) self.rewardsList.box.setHorizontalHeaderItem(3, item) item = QTableWidgetItem() self.rewardsList.addWidget(self.rewardsList.box) layout.addRow(self.rewardsList) ##--- ROW 3 hBox2 = QHBoxLayout() self.btn_selectAllRewards = QPushButton("Select All") self.btn_selectAllRewards.setToolTip("Select all available UTXOs") hBox2.addWidget(self.btn_selectAllRewards) self.btn_deselectAllRewards = QPushButton("Deselect All") self.btn_deselectAllRewards.setToolTip("Deselect current selection") hBox2.addWidget(self.btn_deselectAllRewards) hBox2.addWidget(QLabel("Selected UTXOs")) self.selectedRewardsLine = QLabel() self.selectedRewardsLine.setMinimumWidth(200) self.selectedRewardsLine.setStyleSheet("color: purple") self.selectedRewardsLine.setToolTip("PIVX to move away") hBox2.addWidget(self.selectedRewardsLine) hBox2.addStretch(1) self.swiftxCheck = QCheckBox() self.swiftxCheck.setToolTip( "check for SwiftX instant transaction (flat fee rate of 0.01 PIV)") hBox2.addWidget(QLabel("Use SwiftX")) hBox2.addWidget(self.swiftxCheck) layout.addRow(hBox2) ##--- ROW 4 hBox3 = QHBoxLayout() self.destinationLine = QLineEdit() self.destinationLine.setToolTip("PIVX address to send PIV to") hBox3.addWidget(self.destinationLine) hBox3.addWidget(QLabel("Fee")) self.feeLine = QDoubleSpinBox() self.feeLine.setDecimals(8) self.feeLine.setPrefix("PIV ") self.feeLine.setToolTip("Insert a small fee amount") self.feeLine.setFixedWidth(150) self.feeLine.setSingleStep(0.001) hBox3.addWidget(self.feeLine) self.btn_sendRewards = QPushButton("Send") hBox3.addWidget(self.btn_sendRewards) layout.addRow(QLabel("Destination Address"), hBox3) hBox4 = QHBoxLayout() hBox4.addStretch(1) self.loadingLine = QLabel( "<b style='color:red'>Preparing TX.</b> Completed: ") self.loadingLinePercent = QProgressBar() self.loadingLinePercent.setMaximumWidth(200) self.loadingLinePercent.setMaximumHeight(10) self.loadingLinePercent.setRange(0, 100) hBox4.addWidget(self.loadingLine) hBox4.addWidget(self.loadingLinePercent) self.loadingLine.hide() self.loadingLinePercent.hide() layout.addRow(hBox4) #--- Set Layout self.rewardsForm.setLayout(layout) #--- ROW 5 self.btn_Cancel = QPushButton("Clear") def resetStatusLabel(self, message=None): if message is None: self.rewardsList.statusLabel.setText( '<em><b style="color:purple">Checking explorer...</b></em>') else: self.rewardsList.statusLabel.setText(message) self.rewardsList.statusLabel.setVisible(True)
class AddEmptyBookDialog(QDialog): def __init__(self, parent, db, author, series=None, title=None, dup_title=None): QDialog.__init__(self, parent) self.db = db self.setWindowTitle(_('How many empty books?')) self._layout = QGridLayout(self) self.setLayout(self._layout) self.qty_label = QLabel(_('How many empty books should be added?')) self._layout.addWidget(self.qty_label, 0, 0, 1, 2) self.qty_spinbox = QSpinBox(self) self.qty_spinbox.setRange(1, 10000) self.qty_spinbox.setValue(1) self._layout.addWidget(self.qty_spinbox, 1, 0, 1, 2) self.author_label = QLabel(_('Set the author of the new books to:')) self._layout.addWidget(self.author_label, 2, 0, 1, 2) self.authors_combo = EditWithComplete(self) self.authors_combo.setSizeAdjustPolicy( self.authors_combo.AdjustToMinimumContentsLengthWithIcon) self.authors_combo.setEditable(True) self._layout.addWidget(self.authors_combo, 3, 0, 1, 1) self.initialize_authors(db, author) self.clear_button = QToolButton(self) self.clear_button.setIcon(QIcon(I('trash.png'))) self.clear_button.setToolTip(_('Reset author to Unknown')) self.clear_button.clicked.connect(self.reset_author) self._layout.addWidget(self.clear_button, 3, 1, 1, 1) self.series_label = QLabel(_('Set the series of the new books to:')) self._layout.addWidget(self.series_label, 4, 0, 1, 2) self.series_combo = EditWithComplete(self) self.series_combo.setSizeAdjustPolicy( self.authors_combo.AdjustToMinimumContentsLengthWithIcon) self.series_combo.setEditable(True) self._layout.addWidget(self.series_combo, 5, 0, 1, 1) self.initialize_series(db, series) self.sclear_button = QToolButton(self) self.sclear_button.setIcon(QIcon(I('trash.png'))) self.sclear_button.setToolTip(_('Reset series')) self.sclear_button.clicked.connect(self.reset_series) self._layout.addWidget(self.sclear_button, 5, 1, 1, 1) self.title_label = QLabel(_('Set the title of the new books to:')) self._layout.addWidget(self.title_label, 6, 0, 1, 2) self.title_edit = QLineEdit(self) self.title_edit.setText(title or '') self._layout.addWidget(self.title_edit, 7, 0, 1, 1) self.tclear_button = QToolButton(self) self.tclear_button.setIcon(QIcon(I('trash.png'))) self.tclear_button.setToolTip(_('Reset title')) self.tclear_button.clicked.connect(self.title_edit.clear) self._layout.addWidget(self.tclear_button, 7, 1, 1, 1) self.format_label = QLabel(_('Also create an empty e-book in format:')) self._layout.addWidget(self.format_label, 8, 0, 1, 2) c = self.format_value = QComboBox(self) from calibre.ebooks.oeb.polish.create import valid_empty_formats possible_formats = [''] + sorted(x.upper() for x in valid_empty_formats) c.addItems(possible_formats) c.setToolTip(_('Also create an empty book format file that you can subsequently edit')) if gprefs.get('create_empty_epub_file', False): # Migration of the check box gprefs.set('create_empty_format_file', 'epub') del gprefs['create_empty_epub_file'] use_format = gprefs.get('create_empty_format_file', '').upper() try: c.setCurrentIndex(possible_formats.index(use_format)) except Exception: pass self._layout.addWidget(c, 9, 0, 1, 1) self.copy_formats = cf = QCheckBox(_('Also copy book &formats when duplicating a book'), self) cf.setToolTip(_( 'Also copy all e-book files into the newly created duplicate' ' books.')) cf.setChecked(gprefs.get('create_empty_copy_dup_formats', False)) self._layout.addWidget(cf, 10, 0, 1, -1) button_box = self.bb = QDialogButtonBox(QDialogButtonBox.StandardButton.Ok | QDialogButtonBox.StandardButton.Cancel) button_box.accepted.connect(self.accept) button_box.rejected.connect(self.reject) self._layout.addWidget(button_box, 11, 0, 1, -1) if dup_title: self.dup_button = b = button_box.addButton(_('&Duplicate current book'), button_box.ActionRole) b.clicked.connect(self.do_duplicate_book) b.setIcon(QIcon(I('edit-copy.png'))) b.setToolTip(_( 'Make the new empty book records exact duplicates\n' 'of the current book "%s", with all metadata identical' ) % dup_title) self.resize(self.sizeHint()) self.duplicate_current_book = False def do_duplicate_book(self): self.duplicate_current_book = True self.accept() def accept(self): self.save_settings() return QDialog.accept(self) def save_settings(self): gprefs['create_empty_format_file'] = self.format_value.currentText().lower() gprefs['create_empty_copy_dup_formats'] = self.copy_formats.isChecked() def reject(self): self.save_settings() return QDialog.reject(self) def reset_author(self, *args): self.authors_combo.setEditText(_('Unknown')) def reset_series(self): self.series_combo.setEditText('') def initialize_authors(self, db, author): au = author if not au: au = _('Unknown') self.authors_combo.show_initial_value(au.replace('|', ',')) self.authors_combo.set_separator('&') self.authors_combo.set_space_before_sep(True) self.authors_combo.set_add_separator(tweaks['authors_completer_append_separator']) self.authors_combo.update_items_cache(db.all_author_names()) def initialize_series(self, db, series): self.series_combo.show_initial_value(series or '') self.series_combo.update_items_cache(db.all_series_names()) self.series_combo.set_separator(None) @property def qty_to_add(self): return self.qty_spinbox.value() @property def selected_authors(self): return string_to_authors(unicode_type(self.authors_combo.text())) @property def selected_series(self): return unicode_type(self.series_combo.text()) @property def selected_title(self): return self.title_edit.text().strip()
class ConfigWidget(QWidget): """Configuration widget for managing calibre-comicvine config.""" def __init__(self): QWidget.__init__(self) self.layout = QGridLayout() self.layout.setSpacing(10) self.setLayout(self.layout) self.index = 0 self.api_key = QLineEdit(self) self.api_key.setText(PREFS['api_key']) self.add_labeled_widget('&API key:', self.api_key) # Worker threads is the maximum number of worker threads to spawn. # Restricted to 1+ self.worker_threads = QSpinBox(self) self.worker_threads.setMinimum(1) self.worker_threads.setValue(PREFS['worker_threads']) self.add_labeled_widget('&Worker threads:', self.worker_threads) # Request interval represents wait time between batches of requests. self.request_interval = QSpinBox(self) self.request_interval.setMinimum(0) self.request_interval.setValue(PREFS['request_interval']) self.add_labeled_widget('&Request interval (seconds):', self.request_interval) # Request batch is the maximum number of requests to run at a time. # Restricted to 1+ self.request_batch_size = QSpinBox(self) self.request_batch_size.setMinimum(1) self.request_batch_size.setValue(PREFS['request_batch_size']) self.add_labeled_widget('&Request batch size:', self.request_batch_size) # Retries is the number of times to retry if we get any error # from comicvine besides a rate limit error. self.retries = QSpinBox(self) self.retries.setMinimum(0) self.retries.setValue(PREFS['retries']) self.add_labeled_widget('&Retries:', self.retries) # Search volume limit is the max number of volumes to return from # a volume search. self.search_volume_limit = QSpinBox(self) self.search_volume_limit.setMinimum(10) self.search_volume_limit.setMaximum(10000) self.search_volume_limit.setSingleStep(10) self.search_volume_limit.setValue(PREFS['search_volume_limit']) self.add_labeled_widget('&search_volume_limit:', self.search_volume_limit) def add_labeled_widget(self, label_text, widget): """ Add a configuration widget, incrementing the index for the next widget. """ self.index += 1 label = QLabel(label_text) label.setBuddy(widget) self.layout.addWidget(label, self.index, 0) self.layout.addWidget(widget, self.index, 1) def save_settings(self): """Apply new settings value.""" PREFS['api_key'] = unicode(self.api_key.text()) PREFS['worker_threads'] = self.worker_threads.value() PREFS['request_interval'] = self.request_interval.value() PREFS['request_batch_size'] = self.request_batch_size.value() PREFS['retries'] = self.retries.value() PREFS['search_volume_limit'] = self.search_volume_limit.value()
def createGuiCalibration(): gb = QGroupBox("Gui Calibration") layout = QGridLayout() label1 = QLabel("Time speed (delay):") label2 = QLabel("Sine amplitude:") label3 = QLabel("Pen width:") label4 = QLabel("Vertical position:") label5 = QLabel("X axis offset from right:") timeDelay_sb = QSpinBox() timeDelay_sb.setRange(2, 20) # actual ms is times 10 timeDelay_sb.setValue(tracker.timer_interval / 10) # value is in multiples of 10 ms timeDelay_sb.setMaximumWidth(60) timeDelay_sb.setMinimumHeight(25) timeDelay_sb.valueChanged.connect(tracker.set_timer_interval) amplitude_sb = QSpinBox() amplitude_sb.setRange(20, 300) amplitude_sb.setValue(tracker.amplitude) amplitude_sb.setMaximumWidth(60) amplitude_sb.setMinimumHeight(25) amplitude_sb.valueChanged.connect(tracker.set_amplitude) penWidth_sb = QSpinBox() penWidth_sb.setRange(1, 20) penWidth_sb.setValue(tracker.pen_width) penWidth_sb.setMaximumWidth(60) penWidth_sb.setMinimumHeight(25) penWidth_sb.valueChanged.connect(tracker.set_pen_width) vertPos_sb = QSpinBox() vertPos_sb.setRange(200, 800) vertPos_sb.setValue(tracker.x_axis_y_coordinate) vertPos_sb.setMaximumWidth(60) vertPos_sb.setMinimumHeight(25) vertPos_sb.valueChanged.connect(tracker.set_x_axis_y_coordinate) xAxisLength_sb = QSpinBox() xAxisLength_sb.setRange(50, 1000) xAxisLength_sb.setValue(tracker.x_axis_offset_from_right) xAxisLength_sb.setMaximumWidth(60) xAxisLength_sb.setMinimumHeight(25) xAxisLength_sb.valueChanged.connect(tracker.set_x_axis_offset_from_right) layout.setContentsMargins(0, 0, 0, 0) layout.setSpacing(0) layout.addWidget(label1, 0, 0, 1, 1) layout.addWidget(timeDelay_sb, 0, 1, 1, 1) layout.addWidget(label2, 1, 0, 1, 1) layout.addWidget(amplitude_sb, 1, 1, 1, 1) layout.addWidget(label3, 2, 0, 1, 1) layout.addWidget(penWidth_sb, 2, 1, 1, 1) layout.addWidget(label4, 3, 0, 1, 1) layout.addWidget(vertPos_sb, 3, 1, 1, 1) layout.addWidget(label5, 4, 0, 1, 1) layout.addWidget(xAxisLength_sb, 4, 1, 1, 1) upper = QWidget() upper.setLayout(layout) #------------------------------------------------- vbox = QVBoxLayout() vbox.setContentsMargins(0, 0, 0, 0) vbox.setSpacing(0) vbox.addWidget(upper) vbox.addStretch(1) gb.setLayout(vbox) return gb
def createPcCalibrationControls(): gb = QGroupBox("PC Calibration") #------------------------------------------- layout = QHBoxLayout() label = QLabel("Calibration offset for 180:") global offAt180_sb offAt180_sb = QDoubleSpinBox() offAt180_sb.setRange(-4.0, 0.0) offAt180_sb.setSingleStep(0.5) offAt180_sb.setValue(-3.5) offAt180_sb.setMaximumWidth(60) layout.addWidget(label) layout.addWidget(offAt180_sb) layout.setContentsMargins(0, 0, 0, 0) layout.setSpacing(0) upper = QWidget() upper.setLayout(layout) #------------------------------------------- layout = QHBoxLayout() btn2p5 = QPushButton("2.5") btn2p5.clicked.connect(lambda: offAt180_sb.setValue(-2.5)) btn3 = QPushButton("3.0") btn3.clicked.connect(lambda: offAt180_sb.setValue(-3.0)) btn3p5 = QPushButton("3.5") btn3p5.clicked.connect(lambda: offAt180_sb.setValue(-3.5)) layout.setContentsMargins(0, 0, 0, 0) layout.setSpacing(0) layout.addWidget(btn2p5) layout.addWidget(btn3) layout.addWidget(btn3p5) middle = QWidget() middle.setLayout(layout) #------------------------------------------- layout = QHBoxLayout() label = QLabel("Running Angle offset:") global runningAngleOffset_sb runningAngleOffset_sb = QSpinBox() runningAngleOffset_sb.setToolTip( "offset in degrees to add to the angle reported by arduino") runningAngleOffset_sb.setRange(0, 5) runningAngleOffset_sb.setValue(2) runningAngleOffset_sb.setMaximumWidth(60) layout.setContentsMargins(0, 0, 0, 0) layout.setSpacing(0) layout.addWidget(label) layout.addWidget(runningAngleOffset_sb) lower = QWidget() lower.setLayout(layout) #------------------------------------------- vbox = QVBoxLayout() vbox.addWidget(upper) vbox.addWidget(middle) vbox.addWidget(lower) vbox.addStretch(1) vbox.setContentsMargins(0, 0, 0, 0) vbox.setSpacing(0) gb.setLayout(vbox) return gb
class TwoPlots(QWidget): ''' Widget to plot 2 curves x(t) & y(t), or Vx(t) & Vy(t)''' Ylabels = { "position": ("X [pixel]", "Y [pixel]"), "velocity": ("VX [pixel/s]", "VY [pixel/s]"), "position_mm": ("X [mm]", "Y [mm]"), "velocity_mm": ("VX [mm/s]", "VY [mm/s]") } CurveLabels = { "position": ("X(t) [{}]", "Y(t) [{}]"), "velocity": ("VX(t) {}", "VY(t) {}") } def __init__(self, mainWindow, quantity): # appel du constructeur de la classe de base : QWidget.__init__(self, mainWindow) self.mw = mainWindow # la fenêtre de l'application principale # Attributs (objets persistants) self.__quantity = quantity # "position" or "velocity" self.__data1 = None # data for the first plot self.__data2 = None # data for tthe second self.__figure = None # figure tracé self.__axes1 = None # système d'axes tracé 1 self.__axes2 = None # système d'axes tracé 2 self.__canvas = None # pour le tracé matplot.lib self.__toolbar = None # barre d'outils tracé self.__time = None # abcissa values for plot self.__xlim = None # xmin, xmay tracé self.__xlabel = None # étiquette axe X (n° image ou temps [s]) self.__ylim1 = None # ymin, ymax tracé x(t) self.__ylim2 = None # ymin, ymax tracé y(t) self.btn_imageSize = QRadioButton("ImageSize", self) self.btn_autoSize = QRadioButton("AutoSize", self) self.btn_smooth_Vx = QCheckBox("Lissage Vx", self) self.btn_smooth_Vy = QCheckBox("Lissage Vy", self) self.x_mav_nb_pts = QSpinBox(parent=self) # X velocity moving average self.y_mav_nb_pts = QSpinBox(parent=self) # Y velocity moving average self.__initUI() # Initialisation de l'interface utilisateur def __initUI(self): if self.__quantity == "position": for w in (self.btn_smooth_Vx, self.btn_smooth_Vy, self.x_mav_nb_pts, self.y_mav_nb_pts): w.setVisible(False) w.setEnabled(False) group = QButtonGroup(self) group.addButton(self.btn_imageSize) group.addButton(self.btn_autoSize) self.btn_imageSize.toggled.connect(self.__ImageSizePlotXYLim) self.btn_imageSize.setEnabled(False) texte = "Tracé avec les bornes min et max de l'image" self.btn_imageSize.setStatusTip(texte) self.btn_imageSize.setChecked(True) self.btn_autoSize.toggled.connect(self.__AutoSizePlotXYLim) self.btn_autoSize.setEnabled(False) texte = "Tracé avec les bornes min et max de la " texte += "trajectoire calculée" self.btn_autoSize.setStatusTip(texte) elif self.__quantity == "velocity": for w in (self.btn_imageSize, self.btn_autoSize): w.setVisible(False) w.setEnabled(False) self.btn_smooth_Vx.stateChanged.connect(self.__smooth_Vx_wanted) self.btn_smooth_Vy.stateChanged.connect(self.__smooth_Vy_wanted) self.x_mav_nb_pts.setEnabled(False) self.y_mav_nb_pts.setEnabled(False) self.x_mav_nb_pts.setRange(3, 100) self.y_mav_nb_pts.setRange(3, 100) self.x_mav_nb_pts.setSingleStep(2) self.y_mav_nb_pts.setSingleStep(2) self.x_mav_nb_pts.valueChanged.connect(self.__smooth_vX) self.y_mav_nb_pts.valueChanged.connect(self.__smooth_vY) vbox = QVBoxLayout() self.setLayout(vbox) # Ligne 1 : tracé de l'image self.setLayout(vbox) self.__figure = Figure() self.__axes1 = self.__figure.add_subplot(211) self.__axes2 = self.__figure.add_subplot(212) self.__figure.subplots_adjust(left=0.120, right=0.99, bottom=0.11, top=0.98) self.__canvas = FigureCanvas(self.__figure) self.__toolbar = NavigationToolbar(self.__canvas, self) #self.__toolbar.setMinimumWidth(450) vbox.addWidget(self.__canvas) hbox = QHBoxLayout() hbox.addWidget(self.__toolbar) hbox.addStretch() if self.__quantity == "position": hbox.addWidget(self.btn_imageSize) hbox.addWidget(self.btn_autoSize) elif self.__quantity == "velocity": vb = QVBoxLayout() hb = QHBoxLayout() hb.addWidget(self.btn_smooth_Vx) hb.addWidget(self.x_mav_nb_pts) vb.addLayout(hb) hb = QHBoxLayout() hb.addWidget(self.btn_smooth_Vy) hb.addWidget(self.y_mav_nb_pts) vb.addLayout(hb) hbox.addLayout(vb) vbox.addLayout(hbox) def reset(self): if self.__quantity == "velocity": for w in (self.btn_smooth_Vx, self.btn_smooth_Vy, self.x_mav_nb_pts, self.y_mav_nb_pts): w.setVisible(True) w.setEnabled(True) self.x_mav_nb_pts.setValue(self.x_mav_nb_pts.minimum()) self.y_mav_nb_pts.setValue(self.y_mav_nb_pts.minimum()) self.btn_smooth_Vx.setCheckState(Qt.Unchecked) self.btn_smooth_Vy.setCheckState(Qt.Unchecked) def __smooth_Vx_wanted(self, checked): if checked: self.x_mav_nb_pts.setEnabled(True) else: self.x_mav_nb_pts.setEnabled(False) self.Plot() def __smooth_Vy_wanted(self, checked): if checked: self.y_mav_nb_pts.setEnabled(True) else: self.y_mav_nb_pts.setEnabled(False) self.Plot() def __smooth_vX(self, nb_pts): if self.btn_smooth_Vx.isChecked(): self.Plot() else: pass def __smooth_vY(self, nb_pts): if self.btn_smooth_Vy.isChecked(): self.Plot() else: pass def __compute_velocity(self, U, plot_id): """Computes the velocity with the centered finite difference of order 1 : V[i] = (U[i+1] - U[i-1])/(T[i+1] - T[i-1]) for i in [1,N-1] V[0] = (U[1] - U[0])/(T[1] - T[0]) V[-1] = (U[-1] - U[-2])/(T[-1] - T[-2]) """ V = U.copy() T = self.__time V[0] = (U[1] - U[0]) / (T[1] - T[0]) V[-1] = (U[-1] - U[-2]) / (T[-1] - T[-2]) V[1:-1] = (U[2:] - U[:-2]) / (T[2:] - T[:-2]) if plot_id == "x": if self.btn_smooth_Vx.isChecked(): N = self.x_mav_nb_pts.value() V = self.__smooth_data(V, N) elif plot_id == "y": if self.btn_smooth_Vy.isChecked(): N = self.y_mav_nb_pts.value() V = self.__smooth_data(V, N) return V def __smooth_data(self, U, nb_pts): """Computes the nb_pts moving average on U.""" N = nb_pts V = U.copy() V.fill(np.nan) mav = deque(maxlen=N) # initialize the mav (moving average) for e in U[:N]: mav.append(e) # move! index, count = N // 2, 0 while count < V.shape[0] - N: V[index] = np.mean(mav) mav.append(U[N + count]) count += 1 index += 1 return V def Plot(self): target_pos = self.mw.target_pos if target_pos is None: return else: self.__data1, self.__data2, I = target_pos scale = self.mw.imageTab.pix_to_mm_coeff if self.__quantity == "position": self.btn_imageSize.setEnabled(True) self.btn_autoSize.setEnabled(True) elif self.__quantity == "velocity": pass # Effacement automatiqe si demandé à chaque nouveau tracé : if self.mw.flags["autoClearTraj"]: if self.__axes1 is not None: self.__axes1.clear() if self.__axes2 is not None: self.__axes2.clear() # Récupération du nom de l'alagorithme de traitement : algo = self.mw.imageTab.btn_algo.currentText() # Récupération de la valeur de FP (Frame per seconde) pour calcul # du pas de temps et des abscisses : deltaT = None if self.mw.imageTab.video_FPS is not None: deltaT = 1. / self.mw.imageTab.video_FPS self.__time = np.array(I) * deltaT self.__xlabel = "temps [s]" else: self.__time = np.array(I) self.__xlabel = "image #" if self.__quantity == "velocity": if deltaT is not None: self.__data1 = self.__compute_velocity(self.__data1, "x") self.__data2 = self.__compute_velocity(self.__data2, "y") if self.btn_smooth_Vx.isChecked(): N = self.x_mav_nb_pts.value() if self.btn_smooth_Vy.isChecked(): N = self.y_mav_nb_pts.value() self.__AutoSizePlotXYLim() else: self.__data1, self.__data2 = None, None self.mw.target_veloc = np.array([self.__data1, self.__data2]) else: self.__ImageSizePlotXYLim() if self.__data1 is None or self.__data2 is None: return curveLabelX, curveLabelY = TwoPlots.CurveLabels[self.__quantity] if self.__quantity == "position": Xlabel, Ylabel = curveLabelX.format(algo), curveLabelY.format(algo) else: Xlabel, Ylabel = curveLabelX.format(""), curveLabelY.format("") color = 'b' if self.mw.target_RGB is None else self.mw.target_RGB / 255 # tracé de courbe x(t) self.__axes1.plot(self.__time, self.__data1 * scale, color=color, marker='o', markersize=2, linewidth=.4, label=Xlabel) self.__axes1.grid(True) #self.__axes1.legend(fontsize=9, framealpha=0.7, # bbox_to_anchor=(-0.1, 1.1), loc='upper left') self.__axes1.legend(loc='best', fontsize=10) # tracé de courbe y(t) self.__axes2.plot(self.__time, self.__data2 * scale, color=color, marker='o', markersize=2, linewidth=.4, label=Ylabel) self.__axes2.grid(True) #self.__axes2.legend(fontsize=9, framealpha=0.7, # bbox_to_anchor=(1.1, 1.1), loc='upper right') self.__axes2.legend(loc='best', fontsize=10) self.__canvas.draw() def __AutoSizePlotXYLim(self): if self.mw.target_pos is None: return y1label, y2label = TwoPlots.Ylabels[self.__quantity] self.__xlim = np.array( [np.nanmin(self.__time), np.nanmax(self.__time)]) scale = self.mw.imageTab.pix_to_mm_coeff if not self.btn_smooth_Vx.isChecked(): self.__ylim1 = np.array( [np.nanmin(self.__data1), np.nanmax(self.__data1)]) * scale offset = (self.__ylim1[1] - self.__ylim1[0]) / 10 self.__ylim1 += np.array([-offset, offset]) else: #self.__ylim1 = self.__axes1.get_ylim() pass if not self.btn_smooth_Vy.isChecked(): self.__ylim2 = np.array( [np.nanmin(self.__data2), np.nanmax(self.__data2)]) * scale offset = (self.__ylim2[1] - self.__ylim2[0]) / 10 self.__ylim2 += np.array([-offset, offset]) else: #self.__ylim2 = self.__axes2.get_ylim() pass if self.mw.imageTab.valid_scale: y1label, y2label = TwoPlots.Ylabels[self.__quantity + "_mm"] self.__axes1.set_xlim(*self.__xlim) self.__axes2.set_xlim(*self.__xlim) self.__axes1.set_ylim(*self.__ylim1) self.__axes2.set_ylim(*self.__ylim2) self.__axes1.set_ylabel(y1label) self.__axes2.set_ylabel(y2label) self.__axes2.set_xlabel(self.__xlabel) self.__canvas.draw() def __ImageSizePlotXYLim(self): if self.mw.target_pos is None: return scale = self.mw.imageTab.pix_to_mm_coeff y1label, y2label = TwoPlots.Ylabels[self.__quantity] w, h = self.mw.imageTab.video_size self.__xlim = np.array( [np.nanmin(self.__time), np.nanmax(self.__time)]) self.__ylim1 = np.array([0, w - 1], dtype=float) * scale self.__ylim2 = np.array([0, h - 1], dtype=float) * scale if self.mw.imageTab.valid_scale: y1label, y2label = TwoPlots.Ylabels[self.__quantity + "_mm"] self.__axes1.set_xlim(*self.__xlim) self.__axes2.set_xlim(*self.__xlim) self.__axes1.set_ylim(*self.__ylim1) self.__axes2.set_ylim(*self.__ylim2) self.__axes1.set_ylabel(y1label) self.__axes2.set_ylabel(y2label) self.__axes2.set_xlabel(self.__xlabel) self.__canvas.draw() def ClearAxes(self): if self.__axes1 is not None: self.__axes1.clear() if self.__axes2 is not None: self.__axes2.clear() self.__canvas.draw()
class ExtendedGroupBox(DeviceOptionsGroupBox): """The options group for KoboTouchExtended.""" def __init__(self, parent, device): """Set up driver config options group.""" super(ExtendedGroupBox, self).__init__( parent, device, _("Extended driver") # noqa: F821 ) self.options_layout = QGridLayout() self.options_layout.setObjectName("options_layout") self.setLayout(self.options_layout) self.extra_features_checkbox = create_checkbox( _("Enable Extended Kobo Features"), # noqa: F821 _("Choose whether to enable extra customizations"), # noqa: F821 device.get_pref("extra_features"), ) self.upload_encumbered_checkbox = create_checkbox( _("Upload DRM-encumbered ePub files"), # noqa: F821 _( # noqa: F821 "Select this to upload ePub files encumbered by DRM. If this " "is not selected, it is a fatal error to upload an encumbered " "file"), device.get_pref("upload_encumbered"), ) self.skip_failed_checkbox = create_checkbox( _("Silently Ignore Failed Conversions"), # noqa: F821 _( # noqa: F821 "Select this to not upload any book that fails conversion to " "kepub. If this is not selected, the upload process will be " "stopped at the first book that fails. If this is selected, " "failed books will be silently removed from the upload queue." ), device.get_pref("skip_failed"), ) self.hyphenate_checkbox = create_checkbox( _("Hyphenate Files"), # noqa: F821 _( # noqa: F821 "Select this to add a CSS file which enables hyphenation. The " "language used will be the language defined for the book in " "calibre. Please see the README file for directions on " "updating hyphenation dictionaries."), device.get_pref("hyphenate"), ) self.smarten_punctuation_checkbox = create_checkbox( _("Smarten Punctuation"), # noqa: F821 _("Select this to smarten punctuation in the ePub"), # noqa: F821 device.get_pref("smarten_punctuation"), ) self.clean_markup_checkbox = create_checkbox( _("Clean up ePub Markup"), # noqa: F821 _("Select this to clean up the internal ePub markup." ), # noqa: F821 device.get_pref("clean_markup"), ) self.file_copy_dir_checkbox = create_checkbox( _("Copy generated KePub files to a directory"), # noqa: F821 _( # noqa: F821 "Enter an absolute directory path to copy all generated KePub " "files into for debugging purposes."), device.get_pref("file_copy_dir"), ) self.file_copy_dir_label = QLabel( _("Copy generated KePub files to a directory") # noqa: F821 ) self.file_copy_dir_edit = QLineEdit(self) self.file_copy_dir_edit.setToolTip( _( # noqa: F821 "Enter an absolute directory path to copy all generated KePub " "files into for debugging purposes.")) self.file_copy_dir_edit.setText(device.get_pref("file_copy_dir")) self.file_copy_dir_label.setBuddy(self.file_copy_dir_edit) self.full_page_numbers_checkbox = create_checkbox( _("Use full book page numbers"), # noqa: F821 _( # noqa: F821 "Select this to show page numbers for the whole book, instead " "of each chapter. This will also affect regular ePub page " "number display!"), device.get_pref("full_page_numbers"), ) self.disable_hyphenation_checkbox = create_checkbox( _("Disable hyphenation"), # noqa: F821 _("Select this to disable hyphenation for books."), # noqa: F821 device.get_pref("disable_hyphenation"), ) self.opt_kepub_hyphenate_chars_label = QLabel( _("Minimum word length to hyphenate") + ":" # noqa: F821 ) self.opt_kepub_hyphenate_chars = QSpinBox(self) self.opt_kepub_hyphenate_chars_label.setBuddy( self.opt_kepub_hyphenate_chars) self.opt_kepub_hyphenate_chars.setObjectName( "opt_kepub_hyphenate_chars") self.opt_kepub_hyphenate_chars.setSpecialValueText( _("Disabled")) # noqa: F821 self.opt_kepub_hyphenate_chars.valueChanged.connect( functools.partial( common.intValueChanged, self.opt_kepub_hyphenate_chars, _("character"), # noqa: F821 _("characters"), # noqa: F821 )) self.opt_kepub_hyphenate_chars.setValue( device.get_pref("hyphenate_chars")) self.opt_kepub_hyphenate_chars_before_label = QLabel( _("Minimum characters before hyphens") + ":" # noqa: F821 ) self.opt_kepub_hyphenate_chars_before = QSpinBox(self) self.opt_kepub_hyphenate_chars_before_label.setBuddy( self.opt_kepub_hyphenate_chars_before) self.opt_kepub_hyphenate_chars_before.setObjectName( "opt_kepub_hyphenate_chars_before") self.opt_kepub_hyphenate_chars_before.valueChanged.connect( functools.partial( common.intValueChanged, self.opt_kepub_hyphenate_chars_before, _("character"), # noqa: F821 _("characters"), # noqa: F821 )) self.opt_kepub_hyphenate_chars_before.setMinimum(2) self.opt_kepub_hyphenate_chars_before.setValue( device.get_pref("hyphenate_chars_before")) self.opt_kepub_hyphenate_chars_after_label = QLabel( _("Minimum characters after hyphens") + ":" # noqa: F821 ) self.opt_kepub_hyphenate_chars_after = QSpinBox(self) self.opt_kepub_hyphenate_chars_after_label.setBuddy( self.opt_kepub_hyphenate_chars_after) self.opt_kepub_hyphenate_chars_after.setObjectName( "opt_kepub_hyphenate_chars_after") self.opt_kepub_hyphenate_chars_after.valueChanged.connect( functools.partial( common.intValueChanged, self.opt_kepub_hyphenate_chars_after, _("character"), # noqa: F821 _("characters"), # noqa: F821 )) self.opt_kepub_hyphenate_chars_after.setMinimum(2) self.opt_kepub_hyphenate_chars_after.setValue( device.get_pref("hyphenate_chars_after")) self.opt_kepub_hyphenate_limit_lines_label = QLabel( _("Maximum consecutive hyphenated lines") + ":" # noqa: F821 ) self.opt_kepub_hyphenate_limit_lines = QSpinBox(self) self.opt_kepub_hyphenate_limit_lines_label.setBuddy( self.opt_kepub_hyphenate_limit_lines) self.opt_kepub_hyphenate_limit_lines.setObjectName( "opt_kepub_hyphenate_limit_lines") self.opt_kepub_hyphenate_limit_lines.setSpecialValueText( _("Disabled") # noqa: F821 ) self.opt_kepub_hyphenate_limit_lines.valueChanged.connect( functools.partial( common.intValueChanged, self.opt_kepub_hyphenate_limit_lines, _("line"), # noqa: F821 _("lines"), # noqa: F821 )) self.opt_kepub_hyphenate_limit_lines.setValue( device.get_pref("hyphenate_limit_lines")) self.options_layout.addWidget(self.extra_features_checkbox, 0, 0, 1, 1) self.options_layout.addWidget(self.upload_encumbered_checkbox, 0, 1, 1, 1) self.options_layout.addWidget(self.skip_failed_checkbox, 1, 0, 1, 1) self.options_layout.addWidget(self.hyphenate_checkbox, 1, 1, 1, 1) self.options_layout.addWidget(self.smarten_punctuation_checkbox, 2, 1, 1, 1) self.options_layout.addWidget(self.clean_markup_checkbox, 3, 0, 1, 1) self.options_layout.addWidget(self.file_copy_dir_label, 4, 0, 1, 1) self.options_layout.addWidget(self.file_copy_dir_edit, 4, 1, 1, 1) self.options_layout.addWidget(self.full_page_numbers_checkbox, 5, 0, 1, 1) self.options_layout.addWidget(self.disable_hyphenation_checkbox, 5, 1, 1, 1) self.options_layout.addWidget(self.opt_kepub_hyphenate_chars_label, 6, 0, 1, 1) self.options_layout.addWidget(self.opt_kepub_hyphenate_chars, 6, 1, 1, 1) self.options_layout.addWidget( self.opt_kepub_hyphenate_chars_before_label, 7, 0, 1, 1) self.options_layout.addWidget(self.opt_kepub_hyphenate_chars_before, 7, 1, 1, 1) self.options_layout.addWidget( self.opt_kepub_hyphenate_chars_after_label, 8, 0, 1, 1) self.options_layout.addWidget(self.opt_kepub_hyphenate_chars_after, 8, 1, 1, 1) self.options_layout.addWidget( self.opt_kepub_hyphenate_limit_lines_label, 9, 0, 1, 1) self.options_layout.addWidget(self.opt_kepub_hyphenate_limit_lines, 9, 1, 1, 1) self.options_layout.setRowStretch(10, 2) @property def extra_features(self): """Determine if Kobo extra features are enabled.""" return self.extra_features_checkbox.isChecked() @property def upload_encumbered(self): """Determine if DRM-encumbered files will be uploaded.""" return self.upload_encumbered_checkbox.isChecked() @property def skip_failed(self): """Determine if failed conversions will be skipped.""" return self.skip_failed_checkbox.isChecked() @property def hyphenate(self): """Determine if hyphenation should be enabled.""" return self.hyphenate_checkbox.isChecked() @property def smarten_punctuation(self): """Determine if punctuation should be converted to smart punctuation.""" return self.smarten_punctuation_checkbox.isChecked() @property def clean_markup(self): """Determine if additional markup cleanup will be done.""" return self.clean_markup_checkbox.isChecked() @property def full_page_numbers(self): """Determine if full-book page numbers will be displayed.""" return self.full_page_numbers_checkbox.isChecked() @property def disable_hyphenation(self): """Determine if hyphenation should be disabled.""" return self.disable_hyphenation_checkbox.isChecked() @property def file_copy_dir(self): """Determine where to copy converted KePub books to.""" return self.file_copy_dir_edit.text().strip() @property def hyphenate_chars(self): return self.opt_kepub_hyphenate_chars.value() @property def hyphenate_chars_before(self): return self.opt_kepub_hyphenate_chars_before.value() @property def hyphenate_chars_after(self): return self.opt_kepub_hyphenate_chars_after.value() @property def hyphenate_limit_lines(self): return self.opt_kepub_hyphenate_limit_lines.value()
def __init__(self, mi=None, prefs=None, parent=None, for_global_prefs=False): QWidget.__init__(self, parent) self.ignore_changed = False self.for_global_prefs = for_global_prefs self.l = l = QHBoxLayout(self) l.setContentsMargins(0, 0, 0, 0) self.setLayout(l) self.settings_tabs = st = QTabWidget(self) l.addWidget(st) self.preview_label = la = Preview(self) l.addWidget(la) if prefs is None: prefs = cprefs self.original_prefs = prefs self.mi = mi or self.default_mi() self.colors_page = cp = QWidget(st) st.addTab(cp, _('&Colors')) cp.l = l = QGridLayout() cp.setLayout(l) if for_global_prefs: msg = _( 'When generating covers, a color scheme for the cover is chosen at random from the' ' color schemes below. You can prevent an individual scheme from being selected by' ' unchecking it. The preview on the right shows the currently selected color scheme.' ) else: msg = _( 'Choose a color scheme to be used for this generated cover.' ) + '<p>' + _( 'In normal cover generation, the color scheme is chosen at random from the list of color schemes below. You' ' can prevent an individual color scheme from being chosen by unchecking it here.' ) cp.la = la = QLabel('<p>' + msg) la.setWordWrap(True) l.addWidget(la, 0, 0, 1, -1) self.colors_list = cl = QListWidget(cp) l.addWidget(cl, 1, 0, 1, -1) self.colors_map = OrderedDict() self.ncs = ncs = QPushButton(QIcon(I('plus.png')), _('&New color scheme'), cp) ncs.clicked.connect(self.create_color_scheme) l.addWidget(ncs) self.ecs = ecs = QPushButton(QIcon(I('format-fill-color.png')), _('&Edit color scheme'), cp) ecs.clicked.connect(self.edit_color_scheme) l.addWidget(ecs, l.rowCount() - 1, 1) self.rcs = rcs = QPushButton(QIcon(I('minus.png')), _('&Remove color scheme'), cp) rcs.clicked.connect(self.remove_color_scheme) l.addWidget(rcs, l.rowCount() - 1, 2) self.styles_page = sp = QWidget(st) st.addTab(sp, _('&Styles')) sp.l = l = QVBoxLayout() sp.setLayout(l) if for_global_prefs: msg = _( 'When generating covers, a style for the cover is chosen at random from the' ' styles below. You can prevent an individual style from being selected by' ' unchecking it. The preview on the right shows the currently selected style.' ) else: msg = _( 'Choose a style to be used for this generated cover.' ) + '<p>' + _( 'In normal cover generation, the style is chosen at random from the list of styles below. You' ' can prevent an individual style from being chosen by unchecking it here.' ) sp.la = la = QLabel('<p>' + msg) la.setWordWrap(True) l.addWidget(la) self.styles_list = sl = QListWidget(sp) l.addWidget(sl) self.style_map = OrderedDict() self.font_page = fp = QWidget(st) st.addTab(fp, _('&Fonts and sizes')) fp.l = l = QFormLayout() fp.setLayout(l) fp.f = [] def add_hline(): f = QFrame() fp.f.append(f) f.setFrameShape(QFrame.Shape.HLine) l.addRow(f) for x, label, size_label in ( ('title', _('&Title font family:'), _('&Title font size:')), ('subtitle', _('&Subtitle font family'), _('&Subtitle font size:')), ('footer', _('&Footer font family'), _('&Footer font size')), ): attr = '%s_font_family' % x ff = FontFamilyChooser(fp) setattr(self, attr, ff) l.addRow(label, ff) ff.family_changed.connect(self.emit_changed) attr = '%s_font_size' % x fs = QSpinBox(fp) setattr(self, attr, fs) fs.setMinimum(8), fs.setMaximum(200), fs.setSuffix(' px') fs.setValue(prefs[attr]) fs.valueChanged.connect(self.emit_changed) l.addRow(size_label, fs) add_hline() self.changed_timer = t = QTimer(self) t.setSingleShot(True), t.setInterval(500), t.timeout.connect( self.emit_changed) def create_sz(label): ans = QSpinBox(self) ans.setSuffix(' px'), ans.setMinimum(100), ans.setMaximum(10000) l.addRow(label, ans) ans.valueChanged.connect(self.changed_timer.start) return ans self.cover_width = create_sz(_('Cover &width:')) self.cover_height = create_sz(_('Cover &height:')) fp.cla = la = QLabel( _('Note that the preview to the side is of fixed aspect ratio, so changing the cover' ' width above will not have any effect. If you change the height, you should also change the width nevertheless' ' as it will be used in actual cover generation.')) la.setWordWrap(True) l.addRow(la) self.templates_page = tp = QWidget(st) st.addTab(tp, _('&Text')) tp.l = l = QVBoxLayout() tp.setLayout(l) tp.la = la = QLabel( _('The text on the generated cover is taken from the metadata of the book.' ' This is controlled via templates. You can use the <b>, <i> and <br> tags' ' in the templates for bold, italic and line breaks, respectively. The' ' default templates use the title, series and authors. You can change them to use' ' whatever metadata you like.')) la.setWordWrap(True), la.setTextFormat(Qt.TextFormat.PlainText) l.addWidget(la) def create_template_widget(title, which, button): attr = which + '_template' heading = QLabel('<h2>' + title) setattr(tp, attr + '_heading', heading) l.addWidget(heading) la = QLabel() setattr(self, attr, la) l.addWidget(la), la.setTextFormat( Qt.TextFormat.PlainText), la.setStyleSheet( 'QLabel {font-family: monospace}') la.setWordWrap(True) b = QPushButton(button) b.setSizePolicy(QSizePolicy.Policy.Fixed, QSizePolicy.Policy.Fixed) connect_lambda(b.clicked, self, lambda self: self.change_template(which)) setattr(self, attr + '_button', b) l.addWidget(b) if which != 'footer': f = QFrame(tp) setattr(tp, attr + '_sep', f), f.setFrameShape(QFrame.Shape.HLine) l.addWidget(f) l.addSpacing(10) create_template_widget(_('The title template'), 'title', _('Change the &title template')) create_template_widget(_('The sub-title template'), 'subtitle', _('Change the &sub-title template')) create_template_widget(_('The footer template'), 'footer', _('Change the &footer template')) l.addStretch(2) self.apply_prefs(prefs) self.changed.connect(self.update_preview) self.styles_list.itemSelectionChanged.connect(self.update_preview) self.colors_list.itemSelectionChanged.connect(self.update_preview) self.update_preview()
checks.move(20, 20) # Флажок Прописные буквы checkp = QCheckBox('Прописные буквы', window) checkp.move(220, 20) # Флажок цифры checkc = QCheckBox('Цифры', window) checkc.move(20, 60) # Поле для ввода целых чисел label = QtWidgets.QLabel('Количество символов', window) label.move(80, 102) spin = QSpinBox(window) spin.move(30, 100) spin.setValue(6) # Однострочное текстовое поле tekst = QLineEdit(window) tekst.resize(150, 25) tekst.move(20, 160) # Кнопка буфер обмена buttonb = QtWidgets.QPushButton("В буфер", window) buttonb.resize(80, 30) buttonb.move(20, 210) buttonb.clicked.connect(on_buff) # Кнопка выход buttone = QtWidgets.QPushButton("Выход", window) buttone.resize(80, 30)
class ConfigWidget(QWidget): """Configuration widget for managing calibre-comicvine config.""" def __init__(self): QWidget.__init__(self) self.layout = QGridLayout() self.layout.setSpacing(10) self.setLayout(self.layout) self.index = 0 self.api_key = QLineEdit(self) self.api_key.setText(PREFS['api_key']) self.add_labeled_widget('&API key:', self.api_key) # Worker threads is the maximum number of worker threads to spawn. # Restricted to 1+ self.worker_threads = QSpinBox(self) self.worker_threads.setMinimum(1) self.worker_threads.setValue(PREFS['worker_threads']) self.add_labeled_widget('&Worker threads:', self.worker_threads) # Request interval represents wait time between batches of requests. self.request_interval = QSpinBox(self) self.request_interval.setMinimum(0) self.request_interval.setValue(PREFS['request_interval']) self.add_labeled_widget('&Request interval (seconds):', self.request_interval) # Request batch is the maximum number of requests to run at a time. # Restricted to 1+ self.request_batch_size = QSpinBox(self) self.request_batch_size.setMinimum(1) self.request_batch_size.setValue(PREFS['request_batch_size']) self.add_labeled_widget('&Request batch size:', self.request_batch_size) # Retries is the number of times to retry if we get any error # from comicvine besides a rate limit error. self.retries = QSpinBox(self) self.retries.setMinimum(0) self.retries.setValue(PREFS['retries']) self.add_labeled_widget('&Retries:', self.retries) # Search volume limit is the max number of volumes to return from # a volume search. self.search_volume_limit = QSpinBox(self) self.search_volume_limit.setMinimum(10) self.search_volume_limit.setMaximum(10000) self.search_volume_limit.setSingleStep(10) self.search_volume_limit.setValue(PREFS['search_volume_limit']) self.add_labeled_widget('&search_volume_limit:', self.search_volume_limit) def add_labeled_widget(self, label_text, widget): """ Add a configuration widget, incrementing the index for the next widget. """ self.index += 1 label = QLabel(label_text) label.setBuddy(widget) self.layout.addWidget(label, self.index, 0) self.layout.addWidget(widget, self.index, 1) def save_settings(self): """Apply new settings value.""" PREFS['api_key'] = unicode(self.api_key.text()) PREFS['worker_threads'] = self.worker_threads.value() PREFS['request_interval'] = self.request_interval.value() PREFS['request_batch_size'] = self.request_batch_size.value() PREFS['retries'] = self.retries.value() PREFS['search_volume_limit'] = self.search_volume_limit.value()
def __init__(self, mi=None, prefs=None, parent=None, for_global_prefs=False): QWidget.__init__(self, parent) self.ignore_changed = False self.for_global_prefs = for_global_prefs self.l = l = QHBoxLayout(self) l.setContentsMargins(0, 0, 0, 0) self.setLayout(l) self.settings_tabs = st = QTabWidget(self) l.addWidget(st) self.preview_label = la = Preview(self) l.addWidget(la) if prefs is None: prefs = cprefs self.original_prefs = prefs self.mi = mi or self.default_mi() self.colors_page = cp = QWidget(st) st.addTab(cp, _('&Colors')) cp.l = l = QGridLayout() cp.setLayout(l) if for_global_prefs: msg = _( 'When generating covers, a color scheme for the cover is chosen at random from the' ' color schemes below. You can prevent an individual scheme from being selected by' ' unchecking it. The preview on the right shows the currently selected color scheme.' ) else: msg = _( 'Choose a color scheme to be used for this generated cover.' ) + '<p>' + _( 'In normal cover generation, the color scheme is chosen at random from the list of color schemes below. You' ' can prevent an individual color scheme from being chosen by unchecking it here.' ) cp.la = la = QLabel('<p>' + msg) la.setWordWrap(True) l.addWidget(la, 0, 0, 1, -1) self.colors_list = cl = QListWidget(cp) l.addWidget(cl, 1, 0, 1, -1) self.colors_map = OrderedDict() self.ncs = ncs = QPushButton( QIcon(I('plus.png')), _('&New color scheme'), cp) ncs.clicked.connect(self.create_color_scheme) l.addWidget(ncs) self.ecs = ecs = QPushButton( QIcon(I('format-fill-color.png')), _('&Edit color scheme'), cp) ecs.clicked.connect(self.edit_color_scheme) l.addWidget(ecs, l.rowCount() - 1, 1) self.rcs = rcs = QPushButton( QIcon(I('minus.png')), _('&Remove color scheme'), cp) rcs.clicked.connect(self.remove_color_scheme) l.addWidget(rcs, l.rowCount() - 1, 2) self.styles_page = sp = QWidget(st) st.addTab(sp, _('&Styles')) sp.l = l = QVBoxLayout() sp.setLayout(l) if for_global_prefs: msg = _( 'When generating covers, a style for the cover is chosen at random from the' ' styles below. You can prevent an individual style from being selected by' ' unchecking it. The preview on the right shows the currently selected style.' ) else: msg = _( 'Choose a style to be used for this generated cover.' ) + '<p>' + _( 'In normal cover generation, the style is chosen at random from the list of styles below. You' ' can prevent an individual style from being chosen by unchecking it here.' ) sp.la = la = QLabel('<p>' + msg) la.setWordWrap(True) l.addWidget(la) self.styles_list = sl = QListWidget(sp) l.addWidget(sl) self.style_map = OrderedDict() self.font_page = fp = QWidget(st) st.addTab(fp, _('&Fonts and Sizes')) fp.l = l = QFormLayout() fp.setLayout(l) fp.f = [] def add_hline(): f = QFrame() fp.f.append(f) f.setFrameShape(f.HLine) l.addRow(f) for x, label, size_label in ( ('title', _('&Title font family:'), _('&Title font size:')), ('subtitle', _('&Subtitle font family'), _('&Subtitle font size:')), ('footer', _('&Footer font family'), _('&Footer font size')), ): attr = '%s_font_family' % x ff = FontFamilyChooser(fp) setattr(self, attr, ff) l.addRow(label, ff) ff.family_changed.connect(self.emit_changed) attr = '%s_font_size' % x fs = QSpinBox(fp) setattr(self, attr, fs) fs.setMinimum(8), fs.setMaximum(200), fs.setSuffix(' px') fs.setValue(prefs[attr]) fs.valueChanged.connect(self.emit_changed) l.addRow(size_label, fs) add_hline() self.changed_timer = t = QTimer(self) t.setSingleShot(True), t.setInterval(500), t.timeout.connect( self.emit_changed) def create_sz(label): ans = QSpinBox(self) ans.setSuffix(' px'), ans.setMinimum(100), ans.setMaximum(10000) l.addRow(label, ans) ans.valueChanged.connect(self.changed_timer.start) return ans self.cover_width = create_sz(_('Cover &width:')) self.cover_height = create_sz(_('Cover &height:')) fp.cla = la = QLabel( _('Note that the preview to the side is of fixed aspect ratio, so changing the cover' ' width above will not have any effect. If you change the height, you should also change the width nevertheless' ' as it will be used in actual cover generation.')) la.setWordWrap(True) l.addRow(la) self.templates_page = tp = QWidget(st) st.addTab(tp, _('&Text')) tp.l = l = QVBoxLayout() tp.setLayout(l) tp.la = la = QLabel( _('The text on the generated cover is taken from the metadata of the book.' ' This is controlled via templates. You can use the <b>, <i> and <br> tags' ' in the templates for bold, italic and line breaks, respectively. The' ' default templates use the title, series and authors. You can change them to use' ' whatever metadata you like.')) la.setWordWrap(True), la.setTextFormat(Qt.PlainText) l.addWidget(la) def create_template_widget(title, which, button): attr = which + '_template' heading = QLabel('<h2>' + title) setattr(tp, attr + '_heading', heading) l.addWidget(heading) la = QLabel() setattr(self, attr, la) l.addWidget(la), la.setTextFormat(Qt.PlainText), la.setStyleSheet( 'QLabel {font-family: monospace}') la.setWordWrap(True) b = QPushButton(button) b.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) b.clicked.connect(partial(self.change_template, which)) setattr(self, attr + '_button', b) l.addWidget(b) if which != 'footer': f = QFrame(tp) setattr(tp, attr + '_sep', f), f.setFrameShape(QFrame.HLine) l.addWidget(f) l.addSpacing(10) create_template_widget( _('The title template'), 'title', _('Change the &title template')) create_template_widget( _('The sub-title template'), 'subtitle', _('Change the &sub-title template')) create_template_widget( _('The footer template'), 'footer', _('Change the &footer template')) l.addStretch(2) self.apply_prefs(prefs) self.changed.connect(self.update_preview) self.styles_list.itemSelectionChanged.connect(self.update_preview) self.colors_list.itemSelectionChanged.connect(self.update_preview) self.update_preview()
class ImageDisplay(QWidget): video_infos = ['vidéo : {}','nb frames : {}','taille : {}','FPS : {}','durée : {:.2f} sec'] video_keys = ['videoname','nframes','size','fps','duration'] algo_traj = ['barycentre','minmax'] def __init__(self, mainWindow): # acall the base class constructor: super().__init__(mainWindow) self.mw = mainWindow # Attributs (objets persistants) self.img_lbl = QLabel(self) # to display the current image self.img_lbl.installEventFilter(self) # filter to catch evenements self.selectTargetRect = None # display a rectangle to show teh target color selection self.rubberBand = QRubberBand(QRubberBand.Line, self) # Boutons pour avancer/reculer self.btn_prev = QPushButton(QIcon("icones/go-prev.png"), "", self) self.btn_next = QPushButton(QIcon("icones/go-next.png"), "", self) self.btn_first = QPushButton(QIcon("icones/go-first.png"), "", self) self.btn_last = QPushButton(QIcon("icones/go-last.png"), "", self) self.btn_traj = QPushButton(QIcon("icones/extract.png"), "Extraire...", self) self.btn_clear = QPushButton(QIcon("icones/clear.png"), "Effacer courbes...", self) self.btn_exportCSV = QPushButton(QIcon("icones/exportCSV.png"), "Export CSV", self) self.btn_algo = QComboBox(self) self.image_index = QLabel(self) # widget QSpinBox self.images_step = QSpinBox(parent=self) self.images_firstRank = QSpinBox(parent=self) self.images_lastRank = QSpinBox(parent=self) # QLabel to display the target color self.target_color_label = QLabel("target color",parent=self) self.picked_color = QLabel(self) self.video_path = None # Chemin de la dernière vidéo self.images_dir = None # Dossier contenant les images self.__img_idx = None # Rang de l'image affichée self.img_path = None # nom du chemin de l'image courante self.nb_img = None # nombre d'images self.video_name = None # nom de la video ("aaaaaa.mp4") self.video_nframes = None # nombre d'images dans la video self.video_size = None # taille (width, height) des images self.video_FPS = None # nombre d'images par seconde self.video_duration = None # durée de la video en secondes self.videoLabels = [] # liste de QLabel contenant les infos vidéo self.dico_video = {} # dictionnaire des méta-données self.dico_unit = {} # dictionary "pixels", "mm" self.scale_pixel = None # nombre de pixels pour conversion en mm self.scale_mm = None # nbre de mm pour scale_pixel self.valid_scale = False # données de l'échelle valides ou pas self.pix_to_mm_coeff= 1. # le coefficient de converion pixels -> mm self.dicoScale = {} # dictionnaire des QWidget d'info scale self.lbl_epsilon = None # label epsilon self.epsi_spin = None # boite de choix de epsilon # créer l'onglet de visualisation image """ self.__initUI() self.scaleInfoVisible(False) self.__epsilonVisible(False) def __initUI(self): # Onglet "Visualisation images" vbox = QVBoxLayout() # Ligne 1 : extraction trajec self.picked_color.setFrameStyle(QFrame.StyledPanel | QFrame.Plain); line1 = QHBoxLayout() line1.addStretch(1) line1.addWidget(self.btn_algo) line1.addWidget(self.btn_traj) line1.addWidget(self.target_color_label) line1.addWidget(self.picked_color) line1.addWidget(self.btn_clear) line1.addWidget(self.btn_exportCSV) line1.addStretch(1) # Ligne 2 : infos video + visu image line2 = QHBoxLayout() # boîte d'infos sur la vidéo infoVBox = QVBoxLayout() for _ in ImageDisplay.video_infos: label = QLabel(self) label.setFrameStyle(QFrame.StyledPanel | QFrame.Plain); infoVBox.addWidget(label) self.videoLabels.append(label) infoVBox.addStretch() widget = QLabel("Conversion pixels -> mm", self) self.dicoScale['Pixels-mm'] = widget infoVBox.addWidget(widget) grid = QGridLayout() infoVBox.addLayout(grid) widget = QLabel("pixels ",self) self.dicoScale['pixels'] = widget grid.addWidget(widget,1,1) self.scale_pixel = QLineEdit(self) self.dicoScale['pixelsForMM'] = self.scale_pixel grid.addWidget(self.scale_pixel,1,2) widget = QLabel("millimètres ",self) self.dicoScale['millimeters'] = widget grid.addWidget(widget,2,1) self.scale_mm = QLineEdit(self) self.dicoScale['mmForPixels'] = self.scale_mm grid.addWidget(self.scale_mm,2,2) self.lbl_epsilon = QLabel("Epsilon ",self) grid.addWidget(self.lbl_epsilon,5,1) self.epsi_spin = QSpinBox(self) self.epsi_spin.setRange(1,50) self.epsi_spin.setSingleStep(1) self.epsi_spin.setValue(10) grid.addWidget(self.epsi_spin,5,2) infoVBox.addStretch() line2.addLayout(infoVBox) line2.addStretch(1) line2.addWidget(self.img_lbl) # le QLabel por afficher l'image line2.addStretch(1) # line 3 : navigation boutons self.image_index.setFrameStyle(QFrame.Panel | QFrame.Sunken) self.image_index.setText(" ") line3 = QHBoxLayout() line3.addStretch(1) line3.addWidget(self.btn_first) line3.addWidget(self.btn_prev) line3.addWidget(self.image_index) line3.addWidget(self.btn_next) line3.addWidget(self.btn_last) line3.addStretch(1) # line 4 : first , step, last image selection line4 = QHBoxLayout() line4.addStretch(1) line4.addWidget(self.images_firstRank) line4.addWidget(self.images_step) line4.addWidget(self.images_lastRank) line4.addStretch(1) vbox.addLayout(line1) vbox.addStretch(1) vbox.addLayout(line2) vbox.addStretch(1) vbox.addLayout(line3) vbox.addLayout(line4) self.setLayout(vbox) self.buttonsState() self.__buttonsConnect() self.__setVideoLabelVisible(False) def __setVideoLabelVisible(self, state): for label in self.videoLabels: label.setVisible(state) def __buttonsConnect(self): self.btn_traj.clicked.connect(self.extract_trajectoire) self.btn_clear.clicked.connect(self.mw.clearPlots) self.btn_exportCSV.clicked.connect(self.mw.ExportCSV) self.btn_prev.clicked.connect(self.prev_image) self.btn_next.clicked.connect(self.next_image) self.btn_first.clicked.connect(self.first_image) self.btn_last.clicked.connect(self.last_image) self.images_step.valueChanged.connect(self.__step_changed) self.images_firstRank.valueChanged.connect(self.__first_rank_changed) self.images_lastRank.valueChanged.connect(self.__last_rank_changed) def buttonsState(self, importCSV=False): self.btn_traj.setEnabled(False) self.picked_color.setText("X") self.picked_color.setEnabled(False) self.btn_traj.setStatusTip('Extrait la trajectoire de la cible'+ 'dont la couleur a été choisie') self.target_color_label.setEnabled(False) self.picked_color.setStyleSheet('background-color : rgb(255, 255, 255)') self.btn_clear.setEnabled(False) self.btn_clear.setStatusTip('Nettoye tous les tracés des onglets'+ '<trajectoire> et <X(t), Y(t)>') self.btn_exportCSV.setEnabled(False) texte = "Export des données dans un fichier CSV" self.btn_exportCSV.setStatusTip(texte) if not importCSV: self.btn_algo.addItems(ImageDisplay.algo_traj) self.btn_algo.setEnabled(False) self.btn_prev.setEnabled(False) self.btn_prev.setStatusTip("affiche l'image précédente") self.btn_next.setEnabled(False) self.btn_next.setStatusTip("affiche l'image suivante") self.btn_first.setEnabled(False) self.btn_first.setStatusTip("affiche la première image à traiter") self.btn_last.setEnabled(False) self.btn_last.setStatusTip("affiche la dernière image à traiter") # SpinBoxes parameters: self.images_step.setRange(1,1000) self.images_step.setSingleStep(1) self.images_step.setValue(1) self.images_step.setPrefix("step: ") self.images_step.setEnabled(False) self.images_step.setStatusTip("Fixe le pas pour passer d'une image à l'autre") self.images_firstRank.setRange(1,1000) self.images_firstRank.setSingleStep(1) self.images_firstRank.setValue(1) self.images_firstRank.setPrefix("first: ") self.images_firstRank.setEnabled(False) self.images_firstRank.setStatusTip("Fixe le rang de la première image à traiter") self.images_lastRank.setRange(1,10000) self.images_lastRank.setSingleStep(1) self.images_lastRank.setValue(1) self.images_lastRank.setPrefix("last: ") self.images_lastRank.setEnabled(False) self.images_lastRank.setStatusTip("Fixe le rang de la dernière image à traiter") def __first_rank_changed(self, val): if self.img_idx is None: return if self.img_idx < val: self.img_idx = val self.show_image() def __last_rank_changed(self, val): if self.img_idx is None: return if self.img_idx > val: self.img_idx = val self.show_image() def __step_changed(self, val): if self.img_idx is None: return def setTextInfoVideoGrid(self): for field, name, key in zip(self.videoLabels, ImageDisplay.video_infos, ImageDisplay.video_keys): mess = name.format(self.dico_video.get(key,'?')) field.setText(mess) self.__setVideoLabelVisible(True) def scaleInfoVisible(self, state): for widget in self.dicoScale.values(): widget.setVisible(state) def __epsilonVisible(self, state): self.lbl_epsilon.setVisible(state) self.epsi_spin.setVisible(state) def open_video(self): '''Lance un sélecteur de fichier pour choisir la vidéo à traiter.''' fname = QFileDialog.getOpenFileName(None, 'Choisir une vidéo', self.mw.cur_dir, 'Fichier vidéo (*.mp4)') if fname[0] != '' : # un fichier vidéo a été chosi : vp = fname[0] if self.video_path == vp : name = os.path.basename(vp) rep = QMessageBox.question(self, # widget parent de QMessageBox 'Question', # texte du bandeau de la fenêtre 'Voulez-vous recharger le fichier video {} ?'.format(name), QMessageBox.Yes | QMessageBox.No, # afficher les boutons Yes et No QMessageBox.No) # bouton No sélectionné par défaut if rep == QMessageBox.No: return # fichier vidéo à traiter => faire le split des images : self.video_path = vp self.extract_images_from_video() def load_images_from_directory(self): '''Charge les images '*.png' contenue dans le répertoire des images choisi avec un sélecteur graphique.''' # Choix du répertoire avec un sélecteur de fichier : dname = QFileDialog.getExistingDirectory(None, 'Choisir un dossier images', self.mw.image_dir) if dname != '' : # un répertoire valide a été choisi : self.video_path = None self.images_dir = dname + "/" try: # Lecture du fichier ascii des méta-données with open(self.images_dir + "metaData.txt", "r") as F: data = F.read() exec('self.dico_video = '+data) except: rep = QMessageBox.critical( None, # widget parent de QMessageBox 'Erreur', # bandeau de la fenêtre 'Pas de fichier de méta-données dans le répertoire'+\ ' <{}>'.format(os.path.basename(dname)), QMessageBox.Ok) return print("méta données :", self.dico_video) self.parse_meta_data() self.setTextInfoVideoGrid() # Mettre à jour l'application avec les nouvelles images chargées : self.update_images() def extract_trajectoire(self): '''Méthode utilisée pour extraire la trajectoire du centre de la cible pour toutes les images de la vidéo.''' # Récupérer l'algorithme de calcul du centre de la cible : algo = self.btn_algo.currentText() # Définition de la liste dans laquelle on va récupérer les coordonnées # du centre cible pour toutes les images : target_pos = [] # Création d'un objet ProgressBar qui va lancer le travail # d'extraction de la cible dans les images tout en affichant une # barre d'avancement : first = self.images_firstRank.value() last = self.images_lastRank.value() step = self.images_step.value() last = last - (last - first) % step first_last_step = (first, last, step) pg = ProgressBar(self.images_dir, self) pg.configure_for_target_extraction(self.mw.target_RGB, algo, self.epsi_spin.value(), target_pos, first_last_step) ret = pg.exec_() # lance la barre et le travail d'extraction... print("retour de pg.exec_() :",ret) if ret != 0: self.mw.target_pos = None return target_pos = np.array(target_pos) width, height = self.video_size # l'axe verticale est retourné et decalé: target_pos[1] = height - target_pos[1] self.scale_XY() self.mw.target_pos = target_pos self.display_plots() # remettre le bouton extraire_trajectoire disabled: self.btn_exportCSV.setEnabled(True) def display_plots(self): self.mw.clearPlots() # Plot trajectory (X(t), Y(t)) : self.mw.onePlot.setEnabled(True) self.mw.onePlot.Plot() # Plot curves X(t) and Y(t) self.mw.twoPlots_xy.setEnabled(True) self.mw.tabs.setCurrentWidget(self.mw.twoPlots_xy) self.mw.twoPlots_xy.Plot() # Plot curves VX(t) and VY(t) self.mw.twoPlots_VxVy.setEnabled(True) self.mw.tabs.setCurrentWidget(self.mw.twoPlots_xy) self.mw.twoPlots_VxVy.Plot() def extract_images_from_video(self) : # name of the video file without path and suffix: videoname = os.path.basename(self.video_path)[:-4] # directory where to put extracted iamges: self.images_dir = self.mw.image_dir + videoname + "/" if os.path.isdir(self.images_dir) : print("Effacement de tous les fichiers de '{}'"\ .format(self.images_dir)) for fn in os.listdir(self.images_dir) : os.remove(self.images_dir+fn) else : os.mkdir(self.images_dir) video = cv2.VideoCapture(self.video_path) self.dico_video['nframes'] = int(video.get(cv2.CAP_PROP_FRAME_COUNT)) self.dico_video['size'] = (int(video.get(cv2.CAP_PROP_FRAME_WIDTH)), int(video.get(cv2.CAP_PROP_FRAME_HEIGHT))) self.dico_video['fps'] = int(video.get(cv2.CAP_PROP_FPS)) self.dico_video['duration'] = video.get(cv2.CAP_PROP_FRAME_COUNT)/video.get(cv2.CAP_PROP_FPS) self.dico_video['videoname'] = os.path.basename(self.video_path) self.parse_meta_data() self.dico_video["videoname"] = videoname+".mp4" self.setTextInfoVideoGrid() # Création d'un objet ProgressBar qui va lancer le travail # d'extraction des images tout en affichant une barre d'avancement : pg = ProgressBar(self.images_dir, self) pg.configure_for_video_extraction(video, self.mw.image_fmt) ret = pg.exec_() print("retour de pg.exec_() :", ret) if ret != 0: return # MAJ de la liste des fichiers images : self.update_images() # écriture des méta-data dans le fichier 'nom_video'.info with open(self.mw.image_dir+videoname+"/metaData.txt", "w") as F: F.write(str(self.dico_video)) def computeTargetColor(self, draw_selection=False): col_min,row_min,col_max,row_max = self.selection.getCoords() print("Pixels selectionnés : lignes [{},{}] colonnes [{},{}]".\ format(row_min, row_max, col_min, col_max)) tab = imread(self.img_path) self.target_pix = tab[row_min:row_max+1, col_min:col_max+1, :] R = round(self.target_pix[:,:,0].mean()) G = round(self.target_pix[:,:,1].mean()) B = round(self.target_pix[:,:,2].mean()) self.mw.target_RGB = np.array([R, G, B], dtype=int) print("RGB sélection dans <{}> :".format(os.path.basename(self.img_path)), self.mw.target_RGB) draw_selection = self.mw.flags["drawTargetSelection"] if draw_selection: self.show_image() print("drawTargetSelection") #if self.selectTargetRect is not None : del self.selectTargetRect # create painter instance with pixmap self.selectTargetRect = QPainter(self.img_lbl.pixmap()) # set rectangle color and thickness self.penRectangle = QPen(QColor(0,0,0)) self.penRectangle.setWidth(2) # draw rectangle on painter self.selectTargetRect.begin(self) self.selectTargetRect.setPen(self.penRectangle) self.selectTargetRect.drawRect(col_min,row_min, col_max-col_min,row_max-row_min) self.selectTargetRect.setOpacity(0.1) self.selectTargetRect.end() #self.show_image() self.btn_traj.setEnabled(True) self.btn_algo.setEnabled(True) self.btn_clear.setEnabled(True) self.target_color_label.setEnabled(True) self.picked_color.setStyleSheet('background-color : rgb({},{},{})'.format(R, G, B)) @property def img_idx(self): return self.__img_idx @img_idx.setter def img_idx(self, index): self.__img_idx = index self.image_index.setText(str(index)) def update_images(self) : '''Méthode à exécuter quand de nouvelles images sont apparues après une extraction d'images depuis une vidéo par exemple. Cette méthode : - met à jour des attributs qui dépendant de la liste des images, - met à jour l'état de certains boutons - fait afficher la première image et un message d'information.''' if self.images_dir is None : self.__img_idx = None #self.btn_prev.setEnabled(False) self.btn_prev.setStatusTip("") #self.btn_next.setEnabled(False) self.btn_next.setStatusTip("") self.images_step.setEnabled(False) self.images_firstRank.setEnabled(False) self.images_lastRank.setEnabled(False) else : self.buttonsState() self.mw.clearPlots() self.mw.twoPlots_VxVy.reset() # liste des noms des fichiers image pour avoir leur nombre : file_names = [ f for f in os.listdir(self.images_dir) \ if f.endswith('.png')] file_names.sort() self.nb_img = len(file_names) # Update spinBox: self.images_step.setEnabled(True) self.images_firstRank.setEnabled(True) self.images_lastRank.setEnabled(True) self.images_firstRank.setValue(1) self.images_step.setValue(1) self.images_lastRank.setValue(self.nb_img) self.images_firstRank.setMaximum(self.nb_img) self.images_lastRank.setMaximum(self.nb_img) self.images_step.setMaximum(self.nb_img) # MAJ des boutons prev et next self.img_idx = self.images_firstRank.value() self.btn_prev.setEnabled(True) self.btn_first.setEnabled(True) self.btn_prev.setStatusTip("charge l'image précédente") self.btn_next.setEnabled(True) self.btn_last.setEnabled(True) self.btn_next.setStatusTip("afficher "+self.mw.image_fmt.format(\ self.img_idx+self.images_step.value())) self.show_image() self.scaleInfoVisible(True) self.__epsilonVisible(True) self.mw.tabs.setCurrentWidget(self) self.scale_mm.clear() self.scale_mm.setText("???") self.scale_pixel.clear() try: text = str(self.video_size[1]) except: text = "" self.scale_pixel.setText(text) self.mw.twoPlots_VxVy.reset() if self.mw.flags["displayInfo"]: rep = QMessageBox.information( None, # widget parent de QMessageBox 'Information', # bandeau de la fenêtre 'Vous pouvez maintenant sélectionner une couleur de cible'+\ 'avec la souris...', QMessageBox.Ok) def show_image(self): '''Affiche l'image dont le numéro est donné par l'attribut 'img_idx'.''' if self.img_idx is None : self.img_path = '' else : self.img_path = self.images_dir+self.mw.image_fmt.format(self.img_idx) pixmap = QPixmap(self.img_path) self.img_lbl.setPixmap(pixmap) self.img_lbl.setStatusTip(os.path.basename(self.img_path)) def first_image(self) : if self.img_idx == None : return self.img_idx = self.images_firstRank.value() self.mw.statusBar().showMessage("") self.show_image() def prev_image(self) : if self.img_idx == None : return if self.img_idx >= self.images_firstRank.value() + self.images_step.value(): self.img_idx -= self.images_step.value() self.mw.statusBar().showMessage("") self.show_image() def last_image(self) : if self.img_idx == None : return self.img_idx = self.images_lastRank.value() # rank of last image to process self.mw.statusBar().showMessage("") self.show_image() def next_image(self) : if self.img_idx == None : return if self.img_idx <= self.images_lastRank.value()-self.images_step.value(): self.img_idx += self.images_step.value() self.mw.statusBar().showMessage("") self.show_image() def parse_meta_data(self): self.video_nframes = self.dico_video.get('nframes', None) self.video_size = self.dico_video.get('size', None) self.video_FPS = self.dico_video.get('fps', None) self.video_duration = self.dico_video.get('duration', None) self.video_name = self.dico_video.get('videoname',"none.mp4") if self.mw.flags["debug"]: info= " nb images : {},\n taille image : {},\n FPS : {} image/sec,\n durée : {.2f} sec." info = info.format(self.video_nframes, self.video_size, self.video_FPS, self.video_duration) QMessageBox.about(None, # widget parent de QMessageBox 'Informations video {}'.format(self.video_name), info) def eventFilter(self, object, event): if object == self.img_lbl : if event.type() == QEvent.MouseButtonPress: self.mousePressInLabel(event) return True elif event.type() == QEvent.MouseButtonRelease: self.mouseReleaseInLabel(event) return True elif event.type() == QEvent.MouseMove: self.mouseMoveInLabel(event) return True return False def mousePressInLabel(self, event): if event.button() == Qt.LeftButton: self.pt1 = event.pos() self.pt1_rect = self.img_lbl.mapTo(self, self.pt1) print("\nCoord. pt1 image :",self.pt1) self.rubberBand.setGeometry(QRect(self.pt1_rect, QSize())) self.rubberBand.show() self.mw.statusBar().showMessage('sélection en cours....') def mouseMoveInLabel(self, event): if not self.pt1.isNull(): pt = self.img_lbl.mapTo(self,event.pos()) self.rubberBand.setGeometry(QRect(self.pt1_rect, pt).normalized()) def mouseReleaseInLabel(self, event): if event.button() == Qt.LeftButton: self.pt2 = event.pos() print("Coord. pt2 image :", self.pt2) self.rubberBand.hide() self.selection = QRect(self.pt1, self.pt2).normalized() print(self.selection) self.computeTargetColor() def scale_XY(self): self.valid_scale = False self.pix_to_mm_coeff = 1. try : pixels = float(self.scale_pixel.text()) mm = float(self.scale_mm.text()) except : if self.mw.flags["displayInfo"]: info = 'Les données de conversion Pixels -> mm n\'ont pas été ' info += 'complétées.. les ordonnées des tracés seront en pixels.' rep = QMessageBox.information(None, # parent de QMessageBox 'Info', # bandeau de la fenêtre info, QMessageBox.Ok) return self.valid_scale = True self.pix_to_mm_coeff = mm/pixels print("valid scale : ", self.pix_to_mm_coeff)
class TabMNConf_gui(QWidget): def __init__(self, masternode_alias=None, *args, **kwargs): QWidget.__init__(self) self.initConfigForm(masternode_alias) ###-- Compose tab2 layout mainVertical2 = QVBoxLayout() mainVertical2.setSpacing(10) mainVertical2.addWidget(self.configForm) vBox = QVBoxLayout() vBox.addStretch(1) mainVertical2.addLayout(vBox) mainVertical2.addLayout(self.footer) self.setLayout(mainVertical2) def clearConfigForm(self): self.testnetCheck.setChecked(False) self.edt_name.setText('') self.edt_masternodeIp.setText('') self.edt_masternodePort.setValue(51472) self.edt_mnPrivKey.setText('') self.edt_hwAccount.setValue(0) self.edt_address.setText('') self.edt_spath.setValue(0) self.edt_pubKey.setText('') self.edt_txid.setText('') self.edt_txidn.setValue(0) self.configForm.setTitle('New Masternode') def fillConfigForm(self, masternode): self.edt_name.setText(masternode['name']) self.edt_masternodeIp.setText(masternode['ip']) self.edt_masternodePort.setValue(masternode['port']) self.edt_mnPrivKey.setText(masternode['mnPrivKey']) self.edt_hwAccount.setValue(masternode['hwAcc']) if masternode['isTestnet'] == 1: self.testnetCheck.setChecked(True) else: self.testnetCheck.setChecked(False) self.edt_address.setText(masternode['collateral'].get('address')) self.edt_spath.setValue(masternode['collateral'].get('spath')) self.edt_pubKey.setText(masternode['collateral'].get('pubKey')) self.edt_txid.setText(masternode['collateral'].get('txid')) self.edt_txidn.setValue(masternode['collateral'].get('txidn')) self.configForm.setTitle("Edit Masternode") def initConfigForm(self, masternode_alias=None): self.configForm = QGroupBox() if not masternode_alias: self.configForm.setTitle("New Masternode") else: self.configForm.setTitle("Edit Masternode [%s]" % masternode_alias) layout = QFormLayout() layout.setFieldGrowthPolicy(QFormLayout.AllNonFixedFieldsGrow) layout.setContentsMargins(10, 20, 10, 10) layout.setSpacing(13) ##--- ROW 1 self.edt_name = QLineEdit() self.edt_name.setToolTip( "masternode Alias.\n-- example: My Masternode 1") layout.addRow(QLabel("Name"), self.edt_name) ##--- ROW 2 line1 = QHBoxLayout() self.edt_masternodeIp = QLineEdit() self.edt_masternodeIp.setToolTip( "masternode IP address\n-- example [IPv4] 88.172.23.1\n-- example [IPv6] 2001:db8:85a3::8a2e:370:7334" ) line1.addWidget(self.edt_masternodeIp) line1.addWidget(QLabel("IP Port")) self.edt_masternodePort = QSpinBox() self.edt_masternodePort.setRange(1, 65535) self.edt_masternodePort.setValue(51472) self.edt_masternodePort.setToolTip( "remote masternode tcp port \n-- example: 51472") self.edt_masternodePort.setFixedWidth(180) line1.addWidget(self.edt_masternodePort) layout.addRow(QLabel("IP Address"), line1) ##--- ROW 3 self.edt_mnPrivKey = QLineEdit() self.edt_mnPrivKey.setToolTip( "masternode private key \n-- output of 'masternode genkey' command" ) self.btn_genKey = QPushButton("Generate") self.btn_genKey.setToolTip( "generate masternode privKey from hardware wallet") hBox2 = QHBoxLayout() hBox2.addWidget(self.edt_mnPrivKey) hBox2.addWidget(self.btn_genKey) ## Testnet check self.testnetCheck = QCheckBox() self.testnetCheck.setToolTip("check for TESTNET masternode setup") hBox2.addWidget(QLabel("testnet")) hBox2.addWidget(self.testnetCheck) layout.addRow(QLabel("MN Priv Key"), hBox2) ##--- ROW 4/5 layout.addRow(QFrame()) layout.addRow(QLabel("<em>Masternode Collateral</em>")) hBox3 = QHBoxLayout() self.edt_hwAccount = QSpinBox() self.edt_hwAccount.setFixedWidth(50) self.edt_hwAccount.setToolTip( "account number of the hardware wallet.\nIf unsure put 0") self.edt_hwAccount.setValue(0) hBox3.addWidget(self.edt_hwAccount) hBox3.addWidget(QLabel("PIVX Address")) self.edt_address = QLineEdit() self.edt_address.setToolTip("the address containing 10000 PIV") self.edt_spath = QSpinBox() self.edt_spath.setToolTip("BIP44 spath for the address") self.edt_spath.setFixedWidth(75) self.edt_spath.setValue(0) self.btn_spathToAddress = QPushButton("<<") self.btn_spathToAddress.setToolTip( "find address and public key of given account/spath_id") self.btn_addressToSpath = QPushButton(">>") self.btn_addressToSpath.setToolTip( "find spath_id and public key of given account/address") hBox3.addWidget(self.edt_address) hBox3.addWidget(self.btn_spathToAddress) hBox3.addWidget(self.btn_addressToSpath) hBox3.addWidget(QLabel("spath_id")) hBox3.addWidget(self.edt_spath) layout.addRow(QLabel("Account HW"), hBox3) ##--- ROW 6 self.edt_pubKey = QLineEdit() self.edt_pubKey.setToolTip("public key corresponding to address") self.edt_pubKey.setEnabled(False) layout.addRow(QLabel("Public Key"), self.edt_pubKey) ##--- ROW 7 hBox5 = QHBoxLayout() self.btn_findTxid = QPushButton("Lookup") self.btn_findTxid.setToolTip("look for txid and txidn on explorer") hBox5.addWidget(self.btn_findTxid) hBox5.addWidget(QLabel("/")) self.btn_editTxid = QPushButton("Edit") self.btn_editTxid.setToolTip("edit txid and txidn manually") hBox5.addWidget(self.btn_editTxid) hBox5.addWidget(QLabel("txid")) self.edt_txid = QLineEdit() self.edt_txid.setToolTip("txid for the collateral") self.edt_txid.setEnabled(False) hBox5.addWidget(self.edt_txid) hBox5.addWidget(QLabel("txidn")) self.edt_txidn = QSpinBox() self.edt_txidn.setFixedWidth(50) self.edt_txidn.setToolTip("txidn for the collateral") self.edt_txidn.setEnabled(False) hBox5.addWidget(self.edt_txidn) layout.addRow(QLabel("Transaction"), hBox5) ##--- Set Layout self.configForm.setLayout(layout) ##--- Footer self.footer = QHBoxLayout() self.footer.addStretch(1) self.btn_cancelMNConf = QPushButton('Cancel') self.btn_cancelMNConf.setToolTip( "cancel changes and go back to main list") self.footer.addWidget(self.btn_cancelMNConf) self.btn_saveMNConf = QPushButton('Save') self.btn_saveMNConf.setToolTip( "save configuration and go back to main list") self.footer.addWidget(self.btn_saveMNConf)
class PreferencesDialog(QDialog): #the user preferences itself def __init__(self, parent=None): QDialog.__init__(self, parent) self.setWindowTitle('Preferences') self.resize(600, 240) layout = QHBoxLayout() preview = Preview(self) #Antonio has a problem with the width of Preview form = QFormLayout() self.widthSB = QSpinBox() self.heightSB = QSpinBox() self.widthSB.setRange(1, 1000) self.heightSB.setRange(1, 1000) self.widthSB.setValue(label_size[0]) self.heightSB.setValue(label_size[1]) form.addRow('Width', self.widthSB) form.addRow('Height', self.heightSB) self.spacingDS = DoubleSpin() self.spacingDS.setX(spacing[0]) self.spacingDS.setY(spacing[1]) form.addRow('Spacing', self.spacingDS) self.offsetDS = DoubleSpin() self.offsetDS.setX(first_label_offset[0]) self.offsetDS.setY(first_label_offset[1]) form.addRow('Offset', self.offsetDS) self.p1 = DoubleSpin() self.p1.setX(item_positions['article'][0]) self.p1.setY(item_positions['article'][1]) form.addRow('p1', self.p1) self.p2 = DoubleSpin() self.p2.setX(item_positions['week'][0]) self.p2.setY(item_positions['week'][1]) form.addRow('p2', self.p2) self.p3 = DoubleSpin() self.p3.setX(item_positions['lot'][0]) self.p3.setY(item_positions['lot'][1]) form.addRow('p3', self.p3) self.p4 = DoubleSpin() self.p4.setX(item_positions['code'][0]) self.p4.setY(item_positions['code'][1]) form.addRow('p4', self.p4) self.qr_sizeDS = DoubleSpin() self.qr_sizeDS.setX(qr_size[0]) self.qr_sizeDS.setY(qr_size[1]) form.addRow('QR size', self.qr_sizeDS) self.alignament_mark = DoubleSpin() self.alignament_mark.setX( item_positions['logo'] [0]) #instead of logo, position of alignment_mark is used self.alignament_mark.setY(item_positions['logo'][1]) form.addRow('Alignment mark', self.alignament_mark) self.numberofColumnsSB = QSpinBox() self.numberofColumnsSB.setRange(1, 10) self.numberofColumnsSB.setValue(n_columns) form.addRow('Number of columns', self.numberofColumnsSB) self.numberofRowsSB = QSpinBox() self.numberofRowsSB.setRange(1, 50) self.numberofRowsSB.setValue(n_rows_per_page) form.addRow('Number of rows', self.numberofRowsSB) self.fontSizeSB = QSpinBox() self.fontSizeSB.setRange(4, 25) self.fontSizeSB.setValue(font['size']) form.addRow('Font size', self.fontSizeSB) self.frame_visible = QComboBox() self.frame_visible.addItem('True') self.frame_visible.addItem('False') form.addRow('Frame visible?', self.frame_visible) pbOk = QPushButton('OK') pbOk.clicked.connect(self.accept) form.addRow('', pbOk) pbCancel = QPushButton('Cancel') pbCancel.clicked.connect(self.reject) form.addRow('', pbCancel) layout.addWidget(preview) layout.addLayout(form) self.setLayout(layout)
class AddEmptyBookDialog(QDialog): def __init__(self, parent, db, author, series=None): QDialog.__init__(self, parent) self.db = db self.setWindowTitle(_('How many empty books?')) self._layout = QGridLayout(self) self.setLayout(self._layout) self.qty_label = QLabel(_('How many empty books should be added?')) self._layout.addWidget(self.qty_label, 0, 0, 1, 2) self.qty_spinbox = QSpinBox(self) self.qty_spinbox.setRange(1, 10000) self.qty_spinbox.setValue(1) self._layout.addWidget(self.qty_spinbox, 1, 0, 1, 2) self.author_label = QLabel(_('Set the author of the new books to:')) self._layout.addWidget(self.author_label, 2, 0, 1, 2) self.authors_combo = EditWithComplete(self) self.authors_combo.setSizeAdjustPolicy( self.authors_combo.AdjustToMinimumContentsLengthWithIcon) self.authors_combo.setEditable(True) self._layout.addWidget(self.authors_combo, 3, 0, 1, 1) self.initialize_authors(db, author) self.clear_button = QToolButton(self) self.clear_button.setIcon(QIcon(I('trash.png'))) self.clear_button.setToolTip(_('Reset author to Unknown')) self.clear_button.clicked.connect(self.reset_author) self._layout.addWidget(self.clear_button, 3, 1, 1, 1) self.series_label = QLabel(_('Set the series of the new books to:')) self._layout.addWidget(self.series_label, 4, 0, 1, 2) self.series_combo = EditWithComplete(self) self.authors_combo.setSizeAdjustPolicy( self.authors_combo.AdjustToMinimumContentsLengthWithIcon) self.series_combo.setEditable(True) self._layout.addWidget(self.series_combo, 5, 0, 1, 1) self.initialize_series(db, series) self.sclear_button = QToolButton(self) self.sclear_button.setIcon(QIcon(I('trash.png'))) self.sclear_button.setToolTip(_('Reset series')) self.sclear_button.clicked.connect(self.reset_series) self._layout.addWidget(self.sclear_button, 5, 1, 1, 1) self.create_epub = c = QCheckBox( _('Create an empty EPUB file as well')) c.setChecked(gprefs.get('create_empty_epub_file', False)) c.setToolTip( _('Also create an empty EPUB file that you can subsequently edit')) self._layout.addWidget(c, 6, 0, 1, -1) button_box = self.bb = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) button_box.accepted.connect(self.accept) button_box.rejected.connect(self.reject) self._layout.addWidget(button_box, 7, 0, 1, -1) self.resize(self.sizeHint()) def accept(self): oval = gprefs.get('create_empty_epub_file', False) if self.create_epub.isChecked() != oval: gprefs['create_empty_epub_file'] = self.create_epub.isChecked() return QDialog.accept(self) def reset_author(self, *args): self.authors_combo.setEditText(_('Unknown')) def reset_series(self): self.series_combo.setEditText('') def initialize_authors(self, db, author): au = author if not au: au = _('Unknown') self.authors_combo.show_initial_value(au.replace('|', ',')) self.authors_combo.set_separator('&') self.authors_combo.set_space_before_sep(True) self.authors_combo.set_add_separator( tweaks['authors_completer_append_separator']) self.authors_combo.update_items_cache(db.all_author_names()) def initialize_series(self, db, series): self.series_combo.show_initial_value(series or '') self.series_combo.update_items_cache(db.all_series_names()) self.series_combo.set_separator(None) @property def qty_to_add(self): return self.qty_spinbox.value() @property def selected_authors(self): return string_to_authors(unicode(self.authors_combo.text())) @property def selected_series(self): return unicode(self.series_combo.text())
class GUI(QtWidgets.QMainWindow): def __init__(self): '''Asetetaan muuttujille alkuarvoja ohjelman suorittamiseksi''' super().__init__() self.title = "Lujuusanalysaattori" self.left = 200 self.top = 200 self.width = 1300 self.height = 700 self.palkin_default_pituus = 5 self.square_size = 10 self.ikkuna() self.button_height = 75 self.button_width = 150 self.button_separation = 25 self.x = 0 self.y = 0 self.palkin_leveys = 700 self.palkin_korkeus = 75 self.palkin_keskipiste = 650 self.palkin_paatypiste = 1000 self.yksikko_arvo = 0 self.voima = 20 self.maks_jannitys = "-" self.asteikko_teksti = QGraphicsSimpleTextItem() '''Lisää QGraphicsScenen ruudukon piirtämistä varten''' self.scene = QtWidgets.QGraphicsScene() self.scene.setSceneRect(0, -20, self.width - 200, self.height - 100) '''Suoritetaan lukuisia metodeja, jolla ohjelma "alustetaan"''' self.aloita_simulaatio() self.simulaatioikkuna() self.simulaatio_nappi() self.materiaali_valikko() self.uusi_palkki_nappi() self.lisaa_tuki_nappi() self.lisaa_ulkoinen_voima_nappi() self.poista_ulkoinen_voima_nappi() self.vaihda_tuki_nappi() Ominaisuudet.alkuarvot(self) self.lisaa_palkki() self.palkin_pituus_valikko() self.yksikko_pituus() self.asteikko() self.lisaa_asteikko_arvo() self.asteikko_teksti.hide() self.tulos_teksti() self.lisaa_seina_tuki() self.lisaa_tuki_alhaalta() self.ulkoinen_voima_valikko() self.ulkoinen_voima_nuoli_alatuki() self.ulkoinen_voima_nuoli_seinatuki() Ominaisuudet.alkuarvot(self) '''Asetetaan tietyille napeille tietty näkyvyys''' self.lisaa_tuki.setEnabled(False) self.simuloi.setEnabled(False) self.show() def ikkuna(self): '''Tekee ohjelman pääikkunan''' self.setGeometry(self.left, self.top, self.width, self.height) self.setWindowTitle('Lujuusanalysaattori') self.horizontal = QtWidgets.QHBoxLayout() '''Luo menubarin''' self.uusiAction = QAction("Uusi simulaatio", self) self.uusiAction.setStatusTip("Luo uusi rakenne") self.uusiAction.triggered.connect(self.uusi_rakenne) self.uusiAction.setEnabled(True) self.uusiAction.setShortcut("Ctrl+N") self.tallennaAction = QAction("Tallenna simulaatio", self) self.tallennaAction.setStatusTip("Tallenna simulaatio") self.tallennaAction.triggered.connect(self.tallenna_rakenne) self.tallennaAction.setEnabled(False) self.tallennaAction.setShortcut("Ctrl+S") self.avaaAction = QAction("Lataa simulaatio", self) self.avaaAction.setStatusTip("Lataa simulaatio tiedostosta") self.avaaAction.triggered.connect(self.lataa_tallennettu_rakenne) self.avaaAction.setShortcut("Ctrl+O") self.exitAction = QAction("Exit", self) self.exitAction.setToolTip("Lopeta ohjelma") self.exitAction.triggered.connect(self.close_application) self.exitAction.setShortcut("Ctrl+E") self.statusBar() mainMenu = self.menuBar() fileMenu = mainMenu.addMenu('&File') aboutMenu = mainMenu.addMenu('&About') fileMenu.addAction(self.uusiAction) fileMenu.addAction(self.avaaAction) fileMenu.addAction(self.tallennaAction) fileMenu.addAction(self.exitAction) def tallenna_rakenne(self): '''Hoitaa rakenteen tallentamisen''' tallennus = Tallennin.tallenin(self) if tallennus == True: '''Kerrotaan käyttäjälle, että tallennus onnistui''' msgBox = QMessageBox() msgBox.setText("Tallennus onnistui!") msgBox.setWindowTitle("Onnistunut Tallennus") msgBox.setMinimumWidth(50) msgBox.addButton(QPushButton('OK'), QMessageBox.NoRole) msgBox.exec_() def lataa_tallennettu_rakenne(self): '''Metodi avaa QFileDialog ikkunan, josta käyttäjä valitsee tiedoston, jossa aiemmin tallennettu rakenne sijaitsee. Vain .txt -tiedostot ovat ladattavissa ''' options = QFileDialog.Options() options |= QFileDialog.DontUseNativeDialog tiedosto, _ = QFileDialog.getOpenFileName(self, "Valitse tiedosto", "", "txt Files (*.txt)", options=options) lataus = Lataaja.lataaja(self, tiedosto) if lataus == False: return if lataus == True: self.uusi_rakenne() Lataaja.lataaja(self, tiedosto) tuen_tyyppi = Ominaisuudet.palauta_tuen_tyyppi(self) '''Jos tuki on seinästä, piirretään sitä vastaava grafiikka''' if tuen_tyyppi == 0: self.nayta_seina_tuki() self.gradient_seina_tuki() '''Jos tuki on alhaalta, piirretään sitä vastaava grafiikka''' if tuen_tyyppi == 1: self.nayta_tuki_alhaalta() self.gradient_alatuki() if tuen_tyyppi != 2: self.vaihda_tuki.show() self.lisaa_tuki.hide() '''Jos ulkoinen voima on asetettu, piirretään se''' ulkoinen_voima = int( Ominaisuudet.onko_ulkoinen_voima_asetettu(self)) if ulkoinen_voima == 1: self.nayta_ulkoinen_voima() self.nayta_palkki() Laskin.laskin(self) self.paivita_tulos_teksti() self.tulos.show() self.sp.setValue(float(Ominaisuudet.palauta_palkin_pituus(self))) self.uusiAction.setEnabled(True) self.simuloi.setEnabled(True) '''Kerrotaan käyttäjälle, että kaikki onnistui''' msgBox = QMessageBox() msgBox.setText("Lataus onnistui!") msgBox.setWindowTitle("Onnistunut lataus") msgBox.addButton(QPushButton('OK'), QMessageBox.NoRole) msgBox.exec_() def aloita_simulaatio(self): '''Aloittaa simulaation''' self.setCentralWidget(QtWidgets.QWidget()) self.horizontal = QtWidgets.QHBoxLayout() self.centralWidget().setLayout(self.horizontal) def simulaatioikkuna(self): '''lisää view näyttämistä varten''' self.view = QtWidgets.QGraphicsView(self.scene, self) self.view.adjustSize() self.view.show() self.horizontal.addWidget(self.view) def uusi_palkki_nappi(self): '''Luo Uusi palkki -napin''' self.uusi_palkki = QPushButton('Uusi palkki') self.uusi_palkki.setToolTip("Lisää uusi palkki") self.uusi_palkki.move(0, 0) self.uusi_palkki.resize(self.button_width, self.button_height) self.uusi_palkki.font = QtGui.QFont() self.uusi_palkki.font.setPointSize(12) self.uusi_palkki.setFont(self.uusi_palkki.font) self.uusi_palkki.setEnabled(True) self.scene.addWidget(self.uusi_palkki) self.uusi_palkki.clicked.connect(self.nayta_palkki) def nayta_palkki(self): '''Näyttää kaikki palkkiin liittyvät komponentit sekä asettaa uusi palkki -napin toimimattomaksi''' self.rect.show() self.palkin_pituus.show() self.sp.show() self.yksikko.show() self.asteikko_teksti.show() self.line.show() self.nuoli_1.show() self.nuoli_2.show() self.uusi_palkki.setEnabled(False) self.lisaa_tuki.setEnabled(True) self.materiaali_valinta.setEnabled(True) def lisaa_palkki(self): '''lisää palkin''' self.rect = QGraphicsRectItem(300, 200, self.palkin_leveys, self.palkin_korkeus) self.rect.setBrush(QBrush(4)) self.scene.addItem(self.rect) self.rect.hide() self.lisaa_tuki.setEnabled(True) '''Aina kun on uusi palkki luotu, voidaan aloittaa simulaatio alusta''' self.uusiAction.setEnabled(True) def lisaa_tuki_nappi(self): '''Luo Lisää tuki -napin''' self.lisaa_tuki = QPushButton("Lisää tuki") self.lisaa_tuki.setToolTip("Lisää tuki") self.lisaa_tuki.move(0, self.button_height + self.button_separation) self.lisaa_tuki.resize(self.button_width, self.button_height) self.lisaa_tuki.font = QtGui.QFont() self.lisaa_tuki.font.setPointSize(12) self.lisaa_tuki.setFont(self.lisaa_tuki.font) self.lisaa_tuki.setEnabled(False) self.lisaa_tuki.clicked.connect(self.valitse_tuki) self.scene.addWidget(self.lisaa_tuki) def vaihda_tuki_nappi(self): '''Luo vaihda tuki -napin''' self.vaihda_tuki = QPushButton("Vaihda tuki") self.vaihda_tuki.setToolTip("Vaihda tuki") self.vaihda_tuki.move(0, self.button_height + self.button_separation) self.vaihda_tuki.resize(self.button_width, self.button_height) self.vaihda_tuki.setFont(self.lisaa_tuki.font) self.vaihda_tuki.clicked.connect(self.valitse_tuki) self.scene.addWidget(self.vaihda_tuki) self.vaihda_tuki.hide() def valitse_tuki(self): '''Tuen valinta. Jos tuki on seinästä (tyyppi = 0), kysytään halutaanko vaihtaa. Jos haluaa muutetaan tuen grafiikka ja arvo''' if Ominaisuudet.palauta_tuen_tyyppi(self) == 0: msgBox = QMessageBox() msgBox.setText("Haluatko vaihtaa tuen tyyppiä?") msgBox.addButton(QPushButton('En'), QMessageBox.NoRole) msgBox.addButton(QPushButton('Kyllä'), QMessageBox.YesRole) vastaus = msgBox.exec_() self.rect.setBrush(QBrush(4)) if vastaus == 1: self.viiva_1.hide() self.viiva_2.hide() self.viiva_3.hide() self.viiva_4.hide() self.nayta_tuki_alhaalta() if int(Ominaisuudet.onko_ulkoinen_voima_asetettu(self)) == 1: self.viiva.hide() self.nuoli_3.hide() self.viiva_5.show() self.nuoli_6.show() Ominaisuudet.tuki(self, 1) return '''Jos tuki on alhaalta (tyyppi = 1), kysytään halutaanko vaihtaa. Jos haluaa muutetaan tuen grafiikka ja arvo''' if Ominaisuudet.palauta_tuen_tyyppi(self) == 1: msgBox = QMessageBox() msgBox.setText("Haluatko vaihtaa tuen tyyppiä?") msgBox.addButton(QPushButton('Kyllä'), QMessageBox.YesRole) msgBox.addButton(QPushButton('En'), QMessageBox.NoRole) vastaus = msgBox.exec_() self.rect.setBrush(QBrush(4)) if vastaus == 0: Ominaisuudet.tuki(self, 0) self.nuoli_4.hide() self.nuoli_5.hide() self.nayta_seina_tuki() if int(Ominaisuudet.onko_ulkoinen_voima_asetettu(self)) == 1: self.viiva.show() self.nuoli_3.show() self.viiva_5.hide() self.nuoli_6.hide() if vastaus == 1: pass '''Jos tukea ei ole (tyyppi = 2). Tuen tyypin valinta''' if Ominaisuudet.palauta_tuen_tyyppi(self) == 2: msgBox = QMessageBox() msgBox.setText("Valitse tuen tyyppi") msgBox.addButton(QPushButton('Seinätuki'), QMessageBox.YesRole) msgBox.addButton(QPushButton('Tuki alhaalta'), QMessageBox.NoRole) vastaus = msgBox.exec_() self.vaihda_tuki.show() self.lisaa_tuki.hide() if vastaus == 0: self.nayta_seina_tuki() Ominaisuudet.tuki(self, 0) if vastaus == 1: self.nayta_tuki_alhaalta() Ominaisuudet.tuki(self, 1) '''Joka tapauksessa asetetaan ulkoisen voiman lisääminen mahdolliseksi sekä maalataan palkki normaaliksi''' self.lisaa_ulkoinen_voima.setEnabled(True) self.simuloi.setEnabled(True) def nayta_seina_tuki(self): '''Näytetään seinätukea kuvaavat grafiikat''' self.viiva_1.show() self.viiva_2.show() self.viiva_3.show() self.viiva_4.show() def nayta_tuki_alhaalta(self): '''Näytetään alatukea kuvaavat grafiikat''' self.nuoli_4.show() self.nuoli_5.show() def paivita_tuen_tyyppi(self, tyyppi): '''Päivittää tuen tyypin arvon Ominaisuudet luokassa''' Ominaisuudet.tuki(self, tyyppi) def lisaa_seina_tuki(self): '''Piirtää seinätukea kuvaavat viivat sekä asettaa self.tuen_tyyppi arvoksi Asettaa SIMULOI-napin painettavaksi''' viiva = QtGui.QPen(QtCore.Qt.black, 2) viiva.setStyle(QtCore.Qt.SolidLine) self.viiva_1 = QGraphicsLineItem(QtCore.QLineF(300, 202, 275, 225)) self.viiva_2 = QGraphicsLineItem(QtCore.QLineF(300, 222, 275, 245)) self.viiva_3 = QGraphicsLineItem(QtCore.QLineF(300, 242, 275, 265)) self.viiva_4 = QGraphicsLineItem(QtCore.QLineF(300, 262, 275, 285)) self.scene.addItem(self.viiva_1) self.scene.addItem(self.viiva_2) self.scene.addItem(self.viiva_3) self.scene.addItem(self.viiva_4) self.viiva_1.hide() self.viiva_2.hide() self.viiva_3.hide() self.viiva_4.hide() tyyppi = 0 Ominaisuudet.tuki(self, tyyppi) self.simuloi.setEnabled(True) def lisaa_tuki_alhaalta(self): '''Piirtää alhaalta tukemista kuvaavat grafiikat sekä asettaa self.tuen_tyyppi arvoksi 1''' leveys = 15 #nuolen leveus pikseleissä korkeus = 30 #nuuolen korkeus pikseleissä '''Nuolen kärkien koordinaatit''' nuoli_piste_1 = QtCore.QPointF(305, 275) nuoli_piste_2 = QtCore.QPointF(305 - leveys, 275 + korkeus) nuoli_piste_3 = QtCore.QPointF(305 + leveys, 275 + korkeus) nuoli_piste_4 = QtCore.QPointF(995, 275) nuoli_piste_5 = QtCore.QPointF(995 - leveys, 275 + korkeus) nuoli_piste_6 = QtCore.QPointF(995 + leveys, 275 + korkeus) '''Luodaan nuolia kuvaavat QPolygonF oliot''' self.nuoli_4 = QGraphicsPolygonItem( QtGui.QPolygonF([nuoli_piste_1, nuoli_piste_2, nuoli_piste_3])) self.nuoli_5 = QGraphicsPolygonItem( QtGui.QPolygonF([nuoli_piste_4, nuoli_piste_5, nuoli_piste_6])) self.nuoli_brush = QtGui.QBrush(1) self.nuoli_pencil = QtGui.QPen(QtCore.Qt.black, 2) self.nuoli_pencil.setStyle(QtCore.Qt.SolidLine) '''Lisätään nuolet sceneen''' self.scene.addItem(self.nuoli_4) self.scene.addItem(self.nuoli_5) self.nuoli_4.hide() self.nuoli_5.hide() tyyppi = 1 Ominaisuudet.tuki(self, tyyppi) self.simuloi.setEnabled(True) def lisaa_ulkoinen_voima_nappi(self): '''Luo Lisää ulkoinen voima -napin''' self.lisaa_ulkoinen_voima = QPushButton("Lisää ulkoinen voima") self.lisaa_ulkoinen_voima.setToolTip("Lisää ulkoinen voima") self.lisaa_ulkoinen_voima.move( 0, 2 * self.button_height + 2 * self.button_separation) self.lisaa_ulkoinen_voima.resize(self.button_width, self.button_height) self.lisaa_ulkoinen_voima.font = QtGui.QFont() self.lisaa_ulkoinen_voima.font.setPointSize(8) self.lisaa_ulkoinen_voima.setFont(self.lisaa_ulkoinen_voima.font) self.lisaa_ulkoinen_voima.clicked.connect(self.nayta_ulkoinen_voima) self.lisaa_ulkoinen_voima.clicked.connect(self.nollaa_gradientti) self.lisaa_ulkoinen_voima.setEnabled(False) self.scene.addWidget(self.lisaa_ulkoinen_voima) def poista_ulkoinen_voima_nappi(self): '''Luo poista ulkoinen voima -napin''' self.poista_ulkoinen_voima = QPushButton("Poista ulkoinen voima") self.poista_ulkoinen_voima.setToolTip("Poista ulkoinen voima") self.poista_ulkoinen_voima.move( 0, 2 * self.button_height + 2 * self.button_separation) self.poista_ulkoinen_voima.resize(self.button_width, self.button_height) self.poista_ulkoinen_voima.setFont(self.lisaa_ulkoinen_voima.font) self.poista_ulkoinen_voima.clicked.connect(self.piilota_ulkoinen_voima) self.poista_ulkoinen_voima.clicked.connect(self.nollaa_gradientti) self.scene.addWidget(self.poista_ulkoinen_voima) self.poista_ulkoinen_voima.hide() def piilota_ulkoinen_voima(self): '''Piilotaa kaiken ulkoiseen voimaan liittyvän''' self.sp_voima.hide() self.yksikko_voima.hide() self.ulkoinen_voima.hide() self.lisaa_ulkoinen_voima.show() self.lisaa_ulkoinen_voima.setEnabled(True) self.viiva.hide() self.nuoli_3.hide() self.viiva_5.hide() self.nuoli_6.hide() self.poista_ulkoinen_voima.hide() self.lisaa_ulkoinen_voima.show() self.tulos.hide() Ominaisuudet.ulkoinen_voima(self, 0) def nayta_ulkoinen_voima(self): '''Näytetään ulkoinen voima riippuen tuen tyypistä''' self.sp_voima.show() self.yksikko_voima.show() self.ulkoinen_voima.show() self.lisaa_ulkoinen_voima.hide() self.poista_ulkoinen_voima.show() if int(Ominaisuudet.palauta_tuen_tyyppi(self)) == 0: self.viiva.show() self.nuoli_3.show() if int(Ominaisuudet.palauta_tuen_tyyppi(self)) == 1: self.viiva_5.show() self.nuoli_6.show() Ominaisuudet.ulkoinen_voima(self, 1) def ulkoinen_voima_valikko(self): '''Luo voiman suuruus -tekstin''' self.ulkoinen_voima = QGraphicsSimpleTextItem("Voiman suuruus") self.ulkoinen_voima.setPos(600, 5) self.ulkoinen_voima.font = QtGui.QFont() self.ulkoinen_voima.font.setPointSize(12) self.ulkoinen_voima.setFont(self.ulkoinen_voima.font) self.lisaa_ulkoinen_voima.setEnabled(False) self.scene.addItem(self.ulkoinen_voima) self.ulkoinen_voima.hide() '''Luo voiman arvon QSpinBoxin''' self.sp_voima = QSpinBox() self.sp_voima.move(750, 5) self.sp_voima.setRange(0, 10000) self.sp_voima.setSingleStep(1) self.sp_voima.setMinimumHeight(30) self.sp_voima.setValue(int(Ominaisuudet.palauta_voima(self))) self.sp_voima.valueChanged.connect(self.paivita_voima) self.scene.addWidget(self.sp_voima) self.sp_voima.hide() '''Luo yksikönvalinta QComboBOxin''' self.yksikko_voima = QComboBox() self.yksikko_voima.addItem("kN", 0) self.yksikko_voima.addItem("N", 1) self.yksikko_voima.move(820, 5) self.yksikko_voima.setMinimumHeight(30) self.yksikko_voima.setCurrentIndex( int(Ominaisuudet.palauta_voiman_yksikko(self))) self.yksikko_voima.setEditable(True) self.yksikko_voima.lineEdit().setAlignment(QtCore.Qt.AlignCenter) self.scene.addWidget(self.yksikko_voima) self.yksikko_voima.currentIndexChanged.connect( self.paivita_yksikko_voima) self.yksikko_voima.hide() def ulkoinen_voima_nuoli_seinatuki(self): '''Luo nuolen osoittamaan ulkoisen voiman paikkaa''' voima_viiva = QtGui.QPen(QtCore.Qt.black, 2) voima_viiva.setStyle(QtCore.Qt.SolidLine) '''Nuolen kärkien koordinaatit seinätuelle''' nuoli_piste_1 = QtCore.QPointF(self.palkin_paatypiste - 7, 185) nuoli_piste_2 = QtCore.QPointF(self.palkin_paatypiste, 200) nuoli_piste_3 = QtCore.QPointF(self.palkin_paatypiste + 7, 185) viiva_x = self.palkin_paatypiste self.viiva = QGraphicsLineItem( QtCore.QLineF(viiva_x, 100, viiva_x, 200)) '''Luodaan nuoli QPolygonItem olio''' self.nuoli_3 = QGraphicsPolygonItem( QtGui.QPolygonF([nuoli_piste_1, nuoli_piste_2, nuoli_piste_3])) self.nuoli_brush = QtGui.QBrush(1) self.nuoli_pencil = QtGui.QPen(QtCore.Qt.black, 2) self.nuoli_pencil.setStyle(QtCore.Qt.SolidLine) '''Lisätään viiva sekä päiden nuolet sceneen''' self.scene.addItem(self.viiva) self.scene.addItem(self.nuoli_3) self.viiva.hide() self.nuoli_3.hide() '''Lisätään tieto, että voima on asetettu''' Ominaisuudet.ulkoinen_voima(self, 1) def ulkoinen_voima_nuoli_alatuki(self): '''Nuolen kärkien koordinaatit alhaalta tuetulle palkille''' nuoli_piste_1 = QtCore.QPointF(self.palkin_keskipiste - 7, 185) nuoli_piste_2 = QtCore.QPointF(self.palkin_keskipiste, 200) nuoli_piste_3 = QtCore.QPointF(self.palkin_keskipiste + 7, 185) viiva_x = self.palkin_keskipiste '''Luodaan nuoli QPolygonItem olio''' self.nuoli_6 = QGraphicsPolygonItem( QtGui.QPolygonF([nuoli_piste_1, nuoli_piste_2, nuoli_piste_3])) self.nuoli_brush = QtGui.QBrush(1) self.nuoli_pencil = QtGui.QPen(QtCore.Qt.black, 2) self.nuoli_pencil.setStyle(QtCore.Qt.SolidLine) self.viiva_5 = QGraphicsLineItem( QtCore.QLineF(viiva_x, 100, viiva_x, 200)) '''Lisätään viiva sekä päiden nuolet sceneen''' self.scene.addItem(self.viiva_5) self.scene.addItem(self.nuoli_6) self.viiva_5.hide() self.nuoli_6.hide() '''Lisätään tieto, että voima on asetettu''' Ominaisuudet.ulkoinen_voima(self, 1) def paivita_voima(self): '''Lukee voiman arvon ja kutsuu Ominaisuudet luoka metodia voima''' voima = self.sp_voima.value() Ominaisuudet.voima(self, voima) def paivita_yksikko_voima(self): '''Lukee ykiskön arvon ja kutsuu Ominaisuudet-luokan metodia yksikko_voima''' self.yksikko_voima_arvo = self.yksikko_voima.currentData() Ominaisuudet.yksikko_voima(self, self.yksikko_voima_arvo) def materiaali_valikko(self): ''' Luo Materiaali-otsikon''' self.materiaali = QGraphicsSimpleTextItem("Materiaali") self.materiaali.setPos( 0, 3 * self.button_height + 3 * self.button_separation) self.materiaali.font = QtGui.QFont() self.materiaali.font.setPointSize(12) self.materiaali.setFont(self.materiaali.font) self.scene.addItem(self.materiaali) '''Luo drop down valikon materiaalivalinnalle''' self.materiaali_valinta = QComboBox() self.materiaali_valinta.addItem("Teräs", 0) self.materiaali_valinta.addItem("Alumiini", 1) self.materiaali_valinta.addItem("Muovi", 2) self.materiaali_valinta.move( 0, 3 * self.button_height + 3 * self.button_separation + 25) self.materiaali_valinta.resize(self.button_width, self.button_height - 25) self.materiaali_valinta.setEditable(True) self.materiaali_valinta.lineEdit().setAlignment(QtCore.Qt.AlignCenter) self.materiaali_valinta.setCurrentIndex(0) self.scene.addWidget(self.materiaali_valinta) self.materiaali_valinta.setEnabled(False) self.materiaali_valinta.currentIndexChanged.connect( self.paivita_materiaali) def paivita_materiaali(self): '''Lukee materiaalin arvon ja kutsuu Ominaisuudet-luokan metodia materiaali''' materiaali = self.materiaali_valinta.currentData() Ominaisuudet.materiaali(self, materiaali) def simulaatio_nappi(self): '''Luo SIMULOI-napin''' self.simuloi = QPushButton('SIMULOI') self.simuloi.setToolTip('Simuloi valittu rakenne') self.simuloi.move(0, 4 * self.button_height + 4 * self.button_separation) self.simuloi.setStyleSheet("background-color:rgb(122, 201, 255)") self.simuloi.resize(self.button_width, self.button_height) self.simuloi.font = QtGui.QFont() self.simuloi.font.setPointSize(12) self.simuloi.setFont(self.simuloi.font) self.simuloi.setEnabled(False) self.simuloi.clicked.connect(self.simulaatio) self.scene.addWidget(self.simuloi) def simulaatio(self): '''Kutsuu laskentaa suorittavaa metodia ja tallentaa tuloksen. Tämän jälkeen kutsuu lopputuloksen esittävän tekstin päivittävää metodia sekä palkin visualisoivaa gradient-metodia''' Laskin.laskin(self) Ominaisuudet.palauta_tulos(self) self.paivita_tulos_teksti() self.tallennaAction.setEnabled(True) if Ominaisuudet.palauta_tuen_tyyppi(self) == 0: if Ominaisuudet.onko_ulkoinen_voima_asetettu(self) == 1: self.gradient_seina_tuki() if Ominaisuudet.onko_ulkoinen_voima_asetettu(self) == 0: self.gradient_seina_tuki_ei_voimaa() if Ominaisuudet.palauta_tuen_tyyppi(self) == 1: self.gradient_alatuki() def tulos_teksti(self): '''Lisää tekstin, joka kertoo maksimijänintyksen arvon''' teksti = "Maksimijännitys " + str(self.maks_jannitys) + " MPa" self.tulos = QGraphicsSimpleTextItem(teksti) self.tulos.setPos(550, 500) self.tulos.font = QtGui.QFont() self.tulos.font.setPointSize(12) self.tulos.setFont(self.tulos.font) self.scene.addItem(self.tulos) self.tulos.hide() def paivita_tulos_teksti(self): '''Päivittää maksimijännityksen arvoa kuvaavan tekstin''' maks_jannitys = Ominaisuudet.palauta_tulos(self) self.tulos.setText("Maksimijännitys " + str(maks_jannitys) + " MPa") self.tulos.show() def palkin_pituus_valikko(self): '''Luo palkin pituus tekstin sekä spinbox-valitsimen pituuden asettamista varten Päivittää palkin pituuden Ominaisuudet luokan avulla''' self.palkin_pituus = QGraphicsSimpleTextItem("Palkin pituus") self.palkin_pituus.setPos(300, 5) self.palkin_pituus.font = QtGui.QFont() self.palkin_pituus.font.setPointSize(12) self.palkin_pituus.setFont(self.palkin_pituus.font) self.scene.addItem(self.palkin_pituus) self.palkin_pituus.hide() self.sp = QSpinBox() self.scene.addWidget(self.sp) self.sp.hide() self.sp.move(450, 5) self.sp.setRange(0, 100) self.sp.setSingleStep(1) self.sp.setMinimumHeight(30) self.sp.setValue(int(Ominaisuudet.palauta_palkin_pituus(self))) self.paivita_pituus() self.sp.valueChanged.connect(self.paivita_pituus) def paivita_pituus(self): '''Lukee palkin pituuden ja aktivoi Ominaisuudet luokan meodin palkin pituus''' self.palkin_pituus_arvo = self.sp.value() Ominaisuudet.palkin_pituus(self, self.palkin_pituus_arvo) self.paivita_asteikon_arvot() def yksikko_pituus(self): '''Luo yksikönvalinta dropdown-menun ja arvon muuttuessa päivittää yksikön Ominaisuudet-luokassa''' self.yksikko = QComboBox() self.yksikko.addItem("m", 0) self.yksikko.addItem("cm", 1) self.yksikko.addItem("mm", 2) self.yksikko.move(500, 5) self.yksikko.setMinimumHeight(30) self.yksikko.setEditable(True) self.yksikko.lineEdit().setAlignment(QtCore.Qt.AlignCenter) self.yksikko.setCurrentIndex( Ominaisuudet.palauta_pituuden_yksikko(self)) self.scene.addWidget(self.yksikko) self.yksikko.hide() self.yksikko_arvo = self.yksikko.currentData() self.yksikko.currentIndexChanged.connect(self.paivita_yksikko) def paivita_yksikko(self): '''Lukee yksikön arvon ja kutsuu Ominaisuudet-luokan metodia yksikko''' self.yksikko_arvo = self.yksikko.currentData() Ominaisuudet.yksikko(self, self.yksikko_arvo) self.paivita_asteikon_arvot() def asteikko(self): ''''Luodaan viivaa kuvaava olio''' viiva = QtGui.QPen(QtCore.Qt.black, 2) viiva.setStyle(QtCore.Qt.SolidLine) '''Oikean puoleisen nuolen kärkien koordinaatit''' nuoli_1_piste_1 = QtCore.QPointF(990, 390) nuoli_1_piste_2 = QtCore.QPointF(1000, 400) nuoli_1_piste_3 = QtCore.QPointF(990, 410) '''Vasemman puoleisen nuolen kärkien koordinaatit''' nuoli_2_piste_1 = QtCore.QPointF(310, 390) nuoli_2_piste_2 = QtCore.QPointF(300, 400) nuoli_2_piste_3 = QtCore.QPointF(310, 410) '''Luodaan nuoli QPolygonF oliot''' self.nuoli_1 = QGraphicsPolygonItem( QtGui.QPolygonF( [nuoli_1_piste_1, nuoli_1_piste_2, nuoli_1_piste_3])) self.nuoli_2 = QGraphicsPolygonItem( QtGui.QPolygonF( [nuoli_2_piste_1, nuoli_2_piste_2, nuoli_2_piste_3])) self.nuoli_brush = QtGui.QBrush(1) self.nuoli_pencil = QtGui.QPen(QtCore.Qt.black, 2) self.nuoli_pencil.setStyle(QtCore.Qt.SolidLine) self.line = QGraphicsLineItem(QtCore.QLineF(300, 400, 1000, 400)) '''Lisätään viiva sekä päiden nuolet sceneen''' self.scene.addItem(self.line) self.scene.addItem(self.nuoli_1) self.scene.addItem(self.nuoli_2) self.line.hide() self.nuoli_1.hide() self.nuoli_2.hide() def lisaa_asteikko_arvo(self): '''Lisää tekstikentän pituuden arvolle sekä yksikölle''' teksti = (str(Ominaisuudet.palauta_palkin_pituus(self)) + " " + "m") self.asteikko_teksti = QGraphicsSimpleTextItem() self.asteikko_teksti.setText(teksti) self.asteikko_teksti.setPos(650, 425) self.asteikko_teksti.font = QtGui.QFont() self.asteikko_teksti.font.setPointSize(12) self.asteikko_teksti.setFont(self.asteikko_teksti.font) self.scene.addItem(self.asteikko_teksti) self.asteikko_teksti.hide() def paivita_asteikon_arvot(self): '''Päivittää palkin pituutta kuvaavan asteikon''' yksikko = Ominaisuudet.palauta_pituuden_yksikko(self) if yksikko == 0: self.yksikko_merkki = "m" if yksikko == 1: self.yksikko_merkki = "cm" if yksikko == 2: self.yksikko_merkki = "mm" pituus = float(Ominaisuudet.palauta_palkin_pituus(self)) teksti = str(str(pituus) + " " + self.yksikko_merkki) self.asteikko_teksti.setText(teksti) self.asteikko_teksti.show() def gradient_seina_tuki(self): '''Luo seinästä tuetun palkin rasitusta kuvaavan gradientin''' gradient = QLinearGradient(300, 200, 300 + self.palkin_leveys, 200) gradient.setColorAt(0, QColor(244, 72, 66)) gradient.setColorAt(1, QColor(65, 244, 83)) self.rect.setBrush(gradient) def gradient_seina_tuki_ei_voimaa(self): '''Luo ilman ulkoista voimaa olevan gradientin''' gradient = QLinearGradient(300, 200, 300 + (self.palkin_leveys / 2), 200) gradient.setColorAt(0, QColor(244, 72, 66)) gradient.setColorAt(1, QColor(65, 244, 83)) self.rect.setBrush(gradient) def gradient_alatuki(self): '''Luo kahdella alatuella olevan palkin rasitusta kuvaavan gradientin''' gradient = QLinearGradient(300, 200, 300 + self.palkin_leveys, 200) gradient.setColorAt(0, QColor(65, 244, 83)) gradient.setColorAt(0.5, QColor(244, 72, 66)) gradient.setColorAt(1, QColor(65, 244, 83)) self.rect.setBrush(gradient) def nollaa_gradientti(self): '''Asettaa palkin "normaaliksi"''' self.rect.setBrush(QBrush(4)) def uusi_rakenne(self): '''Muokkaa ikkunaa uuden simulaation luomista varten''' self.rect.hide() self.ulkoinen_voima.hide() self.sp_voima.hide() self.yksikko_voima.hide() self.nuoli_1.hide() self.nuoli_2.hide() self.nuoli_3.hide() self.nuoli_4.hide() self.nuoli_5.hide() self.nuoli_6.hide() self.viiva_1.hide() self.viiva_2.hide() self.viiva_3.hide() self.viiva_4.hide() self.viiva_5.hide() self.viiva.hide() self.palkin_pituus.hide() self.sp.hide() self.yksikko.hide() self.line.hide() self.asteikko_teksti.hide() self.tulos.hide() self.nollaa_gradientti() self.lisaa_tuki.show() self.vaihda_tuki.hide() self.poista_ulkoinen_voima.hide() self.lisaa_ulkoinen_voima.show() Ominaisuudet.alkuarvot(self) '''Asettaa napit''' self.uusi_palkki.setEnabled(True) self.lisaa_ulkoinen_voima.setEnabled(False) self.lisaa_tuki.setEnabled(False) self.simuloi.setEnabled(False) self.tallennaAction.setEnabled(False) '''Päivittää tuen tyypiksi arvon, joka vastaa, ettei tukea ole''' self.tuen_tyyppi = 2 def close_application(self): '''sulkee ohjelman''' sys.exit()