def init(self, parent): """ Finishes initializing the editor by creating the underlying toolkit widget. """ factory = self.factory if not factory.low_name: self.low = factory.low if not factory.high_name: self.high = factory.high self.sync_value(factory.low_name, 'low', 'from') self.sync_value(factory.high_name, 'high', 'from') low = self.low high = self.high self.control = QDoubleSpinBox() if factory.step: self.control.setSingleStep(factory.step) self.control.setMinimum(low) self.control.setMaximum(high) self.control.setValue(self.value) QtCore.QObject.connect(self.control, QtCore.SIGNAL('valueChanged(int)'), self.update_object) self.set_tooltip()
class _DoubleSpinnerEditor(SimpleSpinEditor): def init (self, parent): """ Finishes initializing the editor by creating the underlying toolkit widget. """ factory = self.factory if not factory.low_name: self.low = factory.low if not factory.high_name: self.high = factory.high self.sync_value(factory.low_name, 'low', 'from') self.sync_value(factory.high_name, 'high', 'from') low = self.low high = self.high self.control = QDoubleSpinBox() if factory.step: self.control.setSingleStep(factory.step) self.control.setMinimum(low) self.control.setMaximum(high) self.control.setValue(self.value) QtCore.QObject.connect(self.control, QtCore.SIGNAL('valueChanged(int)'), self.update_object) self.set_tooltip()
def __init__(self, parent=None): super(ExplicitBezierCurveWidget, self).__init__(parent) graphics_view = QGraphicsView() def graphics_view_resize_event(event): assert isinstance(event, QResizeEvent) graphics_view.fitInView(QRectF(0, -SCENE_SIZE_2, SCENE_SIZE, SCENE_SIZE), Qt.KeepAspectRatio) super(QGraphicsView, graphics_view).resizeEvent(event) graphics_view.resizeEvent = graphics_view_resize_event self.explicit_bezier_curve_scene = ExplicitBezierCurveScene(self) graphics_view.setScene(self.explicit_bezier_curve_scene) graphics_view.setRenderHints(QPainter.Antialiasing | QPainter.SmoothPixmapTransform) properties_group_box = QGroupBox() properties_group_box.setTitle("Properties") properties_group_box_layout = QVBoxLayout() properties_group_box.setLayout(properties_group_box_layout) # Degree degree_layout = QHBoxLayout() properties_group_box_layout.addLayout(degree_layout) degree_label = QLabel("Polynomial degree") self.degree_spinbox = QSpinBox() self.degree_spinbox.setRange(MIN_POLYNOMIAL_DEGREE, MAX_POLYNOMIAL_DEGREE) self.degree_spinbox.setValue(POLYNOMIAL_DEGREE_DEFAULT) self.degree_spinbox.valueChanged.connect(self.process_degree_changed) degree_label.setBuddy(self.degree_spinbox) degree_layout.addWidget(degree_label) degree_layout.addWidget(self.degree_spinbox) # X - range x_layout = QHBoxLayout() x_label = QLabel("X:") x_layout.addWidget(x_label) properties_group_box_layout.addLayout(x_layout) min_x_value_label = QLabel("Min") x_layout.addWidget(min_x_value_label) self.min_x_value_spinbox = QDoubleSpinBox() x_layout.addWidget(self.min_x_value_spinbox) self.min_x_value_spinbox.setRange(MIN_X_VALUE, DEFAULT_MAX_X_VALUE-MIN_X_RANGE) self.min_x_value_spinbox.setValue(DEFAULT_MIN_X_VALUE) self.min_x_value_spinbox.valueChanged.connect(self.process_min_x_value_changed) max_x_value_label = QLabel("Max") x_layout.addWidget(max_x_value_label) self.max_x_value_spinbox = QDoubleSpinBox() x_layout.addWidget(self.max_x_value_spinbox) self.max_x_value_spinbox.setRange(DEFAULT_MIN_X_VALUE - MIN_X_RANGE, MAX_X_VALUE) self.max_x_value_spinbox.setValue(DEFAULT_MAX_X_VALUE) self.max_x_value_spinbox.valueChanged.connect(self.process_max_x_value_changed) # Y - range y_layout = QHBoxLayout() properties_group_box_layout.addLayout(y_layout) y_label = QLabel("Y:") y_layout.addWidget(y_label) min_y_value_label = QLabel("Min") y_layout.addWidget(min_y_value_label) self.min_y_value_spinbox = QDoubleSpinBox() self.min_y_value_spinbox.setRange(MIN_Y_VALUE, DEFAULT_MAX_Y_VALUE-MIN_Y_RANGE) self.min_y_value_spinbox.setValue(DEFAULT_MIN_Y_VALUE) self.min_y_value_spinbox.valueChanged.connect(self.process_min_value_changed) min_y_value_label.setBuddy(self.min_y_value_spinbox) y_layout.addWidget(self.min_y_value_spinbox) max_y_value_label = QLabel("Max") y_layout.addWidget(max_y_value_label) self.max_y_value_spinbox = QDoubleSpinBox() self.max_y_value_spinbox.setRange(DEFAULT_MIN_Y_VALUE - MIN_Y_RANGE, MAX_Y_VALUE) self.max_y_value_spinbox.setValue(DEFAULT_MAX_Y_VALUE) self.max_y_value_spinbox.valueChanged.connect(self.process_max_value_changed) max_y_value_label.setBuddy(self.max_y_value_spinbox) y_layout.addWidget(self.max_y_value_spinbox) properties_group_box_layout.addStretch() self.polynom_widget = LatexLabelWidget() main_layout = QVBoxLayout() upper_layout = QVBoxLayout() upper_layout.addWidget(graphics_view) upper_layout.addWidget(properties_group_box) main_layout.addLayout(upper_layout) main_layout.addWidget(self.polynom_widget) self.setLayout(main_layout) self.process_control_points_changed()
class ExplicitBezierCurveWidget(QWidget): bezier_curve_changed = Signal(dict, name="bezier_curve_changed") def __init__(self, parent=None): super(ExplicitBezierCurveWidget, self).__init__(parent) graphics_view = QGraphicsView() def graphics_view_resize_event(event): assert isinstance(event, QResizeEvent) graphics_view.fitInView(QRectF(0, -SCENE_SIZE_2, SCENE_SIZE, SCENE_SIZE), Qt.KeepAspectRatio) super(QGraphicsView, graphics_view).resizeEvent(event) graphics_view.resizeEvent = graphics_view_resize_event self.explicit_bezier_curve_scene = ExplicitBezierCurveScene(self) graphics_view.setScene(self.explicit_bezier_curve_scene) graphics_view.setRenderHints(QPainter.Antialiasing | QPainter.SmoothPixmapTransform) properties_group_box = QGroupBox() properties_group_box.setTitle("Properties") properties_group_box_layout = QVBoxLayout() properties_group_box.setLayout(properties_group_box_layout) # Degree degree_layout = QHBoxLayout() properties_group_box_layout.addLayout(degree_layout) degree_label = QLabel("Polynomial degree") self.degree_spinbox = QSpinBox() self.degree_spinbox.setRange(MIN_POLYNOMIAL_DEGREE, MAX_POLYNOMIAL_DEGREE) self.degree_spinbox.setValue(POLYNOMIAL_DEGREE_DEFAULT) self.degree_spinbox.valueChanged.connect(self.process_degree_changed) degree_label.setBuddy(self.degree_spinbox) degree_layout.addWidget(degree_label) degree_layout.addWidget(self.degree_spinbox) # X - range x_layout = QHBoxLayout() x_label = QLabel("X:") x_layout.addWidget(x_label) properties_group_box_layout.addLayout(x_layout) min_x_value_label = QLabel("Min") x_layout.addWidget(min_x_value_label) self.min_x_value_spinbox = QDoubleSpinBox() x_layout.addWidget(self.min_x_value_spinbox) self.min_x_value_spinbox.setRange(MIN_X_VALUE, DEFAULT_MAX_X_VALUE-MIN_X_RANGE) self.min_x_value_spinbox.setValue(DEFAULT_MIN_X_VALUE) self.min_x_value_spinbox.valueChanged.connect(self.process_min_x_value_changed) max_x_value_label = QLabel("Max") x_layout.addWidget(max_x_value_label) self.max_x_value_spinbox = QDoubleSpinBox() x_layout.addWidget(self.max_x_value_spinbox) self.max_x_value_spinbox.setRange(DEFAULT_MIN_X_VALUE - MIN_X_RANGE, MAX_X_VALUE) self.max_x_value_spinbox.setValue(DEFAULT_MAX_X_VALUE) self.max_x_value_spinbox.valueChanged.connect(self.process_max_x_value_changed) # Y - range y_layout = QHBoxLayout() properties_group_box_layout.addLayout(y_layout) y_label = QLabel("Y:") y_layout.addWidget(y_label) min_y_value_label = QLabel("Min") y_layout.addWidget(min_y_value_label) self.min_y_value_spinbox = QDoubleSpinBox() self.min_y_value_spinbox.setRange(MIN_Y_VALUE, DEFAULT_MAX_Y_VALUE-MIN_Y_RANGE) self.min_y_value_spinbox.setValue(DEFAULT_MIN_Y_VALUE) self.min_y_value_spinbox.valueChanged.connect(self.process_min_value_changed) min_y_value_label.setBuddy(self.min_y_value_spinbox) y_layout.addWidget(self.min_y_value_spinbox) max_y_value_label = QLabel("Max") y_layout.addWidget(max_y_value_label) self.max_y_value_spinbox = QDoubleSpinBox() self.max_y_value_spinbox.setRange(DEFAULT_MIN_Y_VALUE - MIN_Y_RANGE, MAX_Y_VALUE) self.max_y_value_spinbox.setValue(DEFAULT_MAX_Y_VALUE) self.max_y_value_spinbox.valueChanged.connect(self.process_max_value_changed) max_y_value_label.setBuddy(self.max_y_value_spinbox) y_layout.addWidget(self.max_y_value_spinbox) properties_group_box_layout.addStretch() self.polynom_widget = LatexLabelWidget() main_layout = QVBoxLayout() upper_layout = QVBoxLayout() upper_layout.addWidget(graphics_view) upper_layout.addWidget(properties_group_box) main_layout.addLayout(upper_layout) main_layout.addWidget(self.polynom_widget) self.setLayout(main_layout) self.process_control_points_changed() def process_degree_changed(self, value): self.explicit_bezier_curve_scene.set_polynomial_degree(value) self.process_control_points_changed() def process_max_x_value_changed(self, max_x_value): self.min_x_value_spinbox.setRange(MIN_X_VALUE, max_x_value-MIN_X_RANGE) self.process_control_points_changed() def process_min_x_value_changed(self, min_x_value): self.max_y_value_spinbox.setRange(min_x_value - MIN_X_RANGE, MAX_X_VALUE) self.process_control_points_changed() def process_max_value_changed(self, max_value): self.min_y_value_spinbox.setRange(MIN_Y_VALUE, max_value-MIN_Y_RANGE) self.process_control_points_changed() def process_min_value_changed(self, min_value): self.max_y_value_spinbox.setRange(min_value - MIN_Y_RANGE, MAX_Y_VALUE) self.process_control_points_changed() def process_control_points_changed(self): control_points = self.explicit_bezier_curve_scene.control_points n = len(control_points) - 1 x_0 = self.map_x_from_scene(control_points[0].pos().x()) x_1 = self.map_x_from_scene(control_points[-1].pos().x()) x, result = symbols('x result') result = 0 for i in range(0, n + 1): y_i = self.map_y_from_scene(control_points[i].pos().y()) result += binom(n, i) * ((x_1 - x) / (x_1 - x_0)) ** (n - i) * ((x - x_0) / (x_1 - x_0)) ** i * y_i self.polynom_widget.set_latex_expression( latex(N(simplify(expand(result)), 3))) self.bezier_curve_changed.emit(self.serialize()) def map_y_from_scene(self, y): max_y = self.max_y_value_spinbox.value() min_y = self.min_y_value_spinbox.value() a = (max_y-min_y)/(MAX_LINE_Y-MIN_LINE_Y) b = -(max_y*MIN_LINE_Y-min_y*MAX_LINE_Y)/(MAX_LINE_Y-MIN_LINE_Y) return a*y+b def map_x_from_scene(self, x): max_x = self.max_x_value_spinbox.value() min_x = self.min_x_value_spinbox.value() a = (max_x-min_x)/(MAX_LINE_X-MIN_LINE_X) b = -(max_x*MIN_LINE_X-min_x*MAX_LINE_X)/(MAX_LINE_X-MIN_LINE_X) return a*x+b def map_y_to_scene(self, y): max_y = self.max_y_value_spinbox.value() min_y = self.min_y_value_spinbox.value() a = (MAX_LINE_Y-MIN_LINE_Y)/(max_y-min_y) b = (max_y*MIN_LINE_Y-min_y*MAX_LINE_Y)/(max_y-min_y) return a*y+b def serialize(self): """ :return: widget state in the following format { "min_x" : -10, "max_x" : 10, "min_y" : -10, "max_y" : 10, "degree": 3, "ys" : [3, 3, 3, 2] } """ control_points = self.explicit_bezier_curve_scene.control_points state = dict() state["min_x"] = self.min_x_value_spinbox.value() state["max_x"] = self.max_x_value_spinbox.value() state["min_y"] = self.min_y_value_spinbox.value() state["max_y"] = self.max_y_value_spinbox.value() state["degree"] = self.degree_spinbox.value() state["ys"] = [self.map_y_from_scene(control_point.pos().y()) for control_point in control_points] return state def deserialize(self, state): """ This method setups widget controls to the state specified. :param state: widget state in the following format { "min_x" : -10, "max_x" : 10, "min_y" : -10, "max_y" : 10, "degree": 3, "ys" : [3, 3, 3, 2] } :return: """ self.min_x_value_spinbox.setValue(state["min_x"]) self.max_x_value_spinbox.setValue(state["max_x"]) self.min_y_value_spinbox.setValue(state["min_y"]) self.max_y_value_spinbox.setValue(state["max_y"]) self.degree_spinbox.setValue(state["degree"]) ys = [self.map_y_to_scene(y) for y in state["ys"]] n = self.degree_spinbox.value() for i, (x, y) in enumerate(zip(linspace(0.02*SCENE_SIZE, 0.98*SCENE_SIZE, num=n + 1), ys)): self.explicit_bezier_curve_scene.control_points[i].setPos(QPointF(x, y))
def __init__(self, universe, parent=None): super(NaturalLawPropertiesWidget, self).__init__(parent) self.natural_law = None self.universe = universe self.name_editor = QLineEdit() self.name_editor_groupbox = QGroupBox("Name") self.name_editor_groupbox_layout = QHBoxLayout() self.name_editor_groupbox.setLayout(self.name_editor_groupbox_layout) self.name_editor_groupbox_layout.addWidget(self.name_editor) self.name_editor_groupbox_layout.addStretch() self.force_combo_box = QComboBox() self.force_combo_box.setModel(ForcesInUniverseListModel(universe)) self.atom_in_combo_box = QComboBox() self.atom_in_combo_box.setModel(AtomsInUniverseListModel(universe)) self.atom_out_combo_box = QComboBox() self.atom_out_combo_box.setModel(AtomsInUniverseListModel(universe)) self.transformation_label = QLabel() self.conversion_scheme_groupbox = QGroupBox("Conversion scheme") self.conversion_scheme_groupbox.setVisible(False) self.conversion_scheme_groupbox_layout = QGridLayout() self.conversion_scheme_groupbox.setLayout(self.conversion_scheme_groupbox_layout) self.conversion_scheme_groupbox_layout.addWidget(self.atom_in_combo_box, 1, 0) self.conversion_scheme_groupbox_layout.addWidget(self.force_combo_box, 0, 1) self.conversion_scheme_groupbox_layout.addWidget(self.atom_out_combo_box, 1, 2) self.conversion_scheme_groupbox_layout.addWidget(self.transformation_label, 1, 1) self.conversion_rate_formula_label = LatexLabelWidget() self.multiplicative_component_label = QLabel(u"υ = ") self.multiplicative_component_label.setFont(QFont("Times New Roman", 15, italic=True)) self.multiplicative_component_double_spinbox = QDoubleSpinBox() self.additive_component_label = QLabel(u"s = ") self.additive_component_label.setFont(QFont("Times New Roman", 15, italic=True)) self.additive_component_double_spinbox = QDoubleSpinBox() self.conversion_rate_groupbox = QGroupBox("Conversion rate") self.conversion_rate_groupbox_layout = QGridLayout() self.conversion_rate_groupbox.setLayout(self.conversion_rate_groupbox_layout) self.conversion_rate_groupbox_layout.addWidget(self.conversion_rate_formula_label, 0, 0, 1, 2) self.conversion_rate_groupbox_layout.addWidget(self.multiplicative_component_label, 1, 0) self.conversion_rate_groupbox_layout.addWidget(self.multiplicative_component_double_spinbox, 1, 1) self.conversion_rate_groupbox_layout.addWidget(self.additive_component_label, 2, 0) self.conversion_rate_groupbox_layout.addWidget(self.additive_component_double_spinbox, 2, 1) main_layout = QVBoxLayout() main_layout.addWidget(self.name_editor_groupbox) main_layout.addWidget(self.conversion_scheme_groupbox) main_layout.addWidget(self.conversion_rate_groupbox) main_layout.addStretch() self.setLayout(main_layout) self.name_editor.textChanged.connect(self.name_editor_text_changed) self.multiplicative_component_double_spinbox.valueChanged.connect(self.multiplicative_component_value_changed) self.additive_component_double_spinbox.valueChanged.connect(self.additive_component_value_changed) self.atom_in_combo_box.currentIndexChanged.connect(self.atom_in_combo_box_current_index_changed) self.setDisabled(True)
class NaturalLawPropertiesWidget(QWidget): """ This widget modifies properties of a natural law """ def __init__(self, universe, parent=None): super(NaturalLawPropertiesWidget, self).__init__(parent) self.natural_law = None self.universe = universe self.name_editor = QLineEdit() self.name_editor_groupbox = QGroupBox("Name") self.name_editor_groupbox_layout = QHBoxLayout() self.name_editor_groupbox.setLayout(self.name_editor_groupbox_layout) self.name_editor_groupbox_layout.addWidget(self.name_editor) self.name_editor_groupbox_layout.addStretch() self.force_combo_box = QComboBox() self.force_combo_box.setModel(ForcesInUniverseListModel(universe)) self.atom_in_combo_box = QComboBox() self.atom_in_combo_box.setModel(AtomsInUniverseListModel(universe)) self.atom_out_combo_box = QComboBox() self.atom_out_combo_box.setModel(AtomsInUniverseListModel(universe)) self.transformation_label = QLabel() self.conversion_scheme_groupbox = QGroupBox("Conversion scheme") self.conversion_scheme_groupbox.setVisible(False) self.conversion_scheme_groupbox_layout = QGridLayout() self.conversion_scheme_groupbox.setLayout(self.conversion_scheme_groupbox_layout) self.conversion_scheme_groupbox_layout.addWidget(self.atom_in_combo_box, 1, 0) self.conversion_scheme_groupbox_layout.addWidget(self.force_combo_box, 0, 1) self.conversion_scheme_groupbox_layout.addWidget(self.atom_out_combo_box, 1, 2) self.conversion_scheme_groupbox_layout.addWidget(self.transformation_label, 1, 1) self.conversion_rate_formula_label = LatexLabelWidget() self.multiplicative_component_label = QLabel(u"υ = ") self.multiplicative_component_label.setFont(QFont("Times New Roman", 15, italic=True)) self.multiplicative_component_double_spinbox = QDoubleSpinBox() self.additive_component_label = QLabel(u"s = ") self.additive_component_label.setFont(QFont("Times New Roman", 15, italic=True)) self.additive_component_double_spinbox = QDoubleSpinBox() self.conversion_rate_groupbox = QGroupBox("Conversion rate") self.conversion_rate_groupbox_layout = QGridLayout() self.conversion_rate_groupbox.setLayout(self.conversion_rate_groupbox_layout) self.conversion_rate_groupbox_layout.addWidget(self.conversion_rate_formula_label, 0, 0, 1, 2) self.conversion_rate_groupbox_layout.addWidget(self.multiplicative_component_label, 1, 0) self.conversion_rate_groupbox_layout.addWidget(self.multiplicative_component_double_spinbox, 1, 1) self.conversion_rate_groupbox_layout.addWidget(self.additive_component_label, 2, 0) self.conversion_rate_groupbox_layout.addWidget(self.additive_component_double_spinbox, 2, 1) main_layout = QVBoxLayout() main_layout.addWidget(self.name_editor_groupbox) main_layout.addWidget(self.conversion_scheme_groupbox) main_layout.addWidget(self.conversion_rate_groupbox) main_layout.addStretch() self.setLayout(main_layout) self.name_editor.textChanged.connect(self.name_editor_text_changed) self.multiplicative_component_double_spinbox.valueChanged.connect(self.multiplicative_component_value_changed) self.additive_component_double_spinbox.valueChanged.connect(self.additive_component_value_changed) self.atom_in_combo_box.currentIndexChanged.connect(self.atom_in_combo_box_current_index_changed) self.setDisabled(True) def switch_to_natural_law(self, natural_law): """ This method initializes widget with current state of natural law provided and keeps and eye on specific natural law by writing changes to NaturalLaw object as far as properties are modified in graphical interface :param natural_law: a natural law in concern :type natural_law: engine.NaturalLaw :return: Nothing """ self.natural_law = natural_law self.name_editor.setText(self.natural_law.name) if self.natural_law.atom_in is not None: self.atom_in_combo_box.setCurrentIndex(self.universe.atoms.index(self.natural_law.atom_in)) if self.natural_law.atom_out is not None: self.atom_out_combo_box.setCurrentIndex(self.universe.atoms.index(self.natural_law.atom_out)) if self.natural_law.accelerator is not None: self.force_combo_box.setCurrentIndex(self.universe.forces.index(self.natural_law.accelerator)) self.multiplicative_component_double_spinbox.setValue(self.natural_law.multiplicative_component) self.additive_component_double_spinbox.setValue(self.natural_law.additive_component) self.update_conversion_rate_formula_label() self.setEnabled(True) def invalidate(self): self.switch_to_natural_law(self.natural_law) def name_editor_text_changed(self, value): self.natural_law.name = value def multiplicative_component_value_changed(self, value): self.natural_law.multiplicative_component = value self.update_conversion_rate_formula_label() def additive_component_value_changed(self, value): self.natural_law.additive_component = value self.update_conversion_rate_formula_label() def update_conversion_rate_formula_label(self): self.conversion_rate_formula_label.text.set_text( "$ f * \upsilon + s = f * {upsilon} + {s} $".format( upsilon=self.natural_law.multiplicative_component, s=self.natural_law.additive_component ) ) self.conversion_rate_formula_label.draw() def atom_in_combo_box_current_index_changed(self, index): # here we should remove the previous connection. pass