def _load(self): if self.loaded: return self.service = locator.get_scoped("DialogueService") module_service = locator.get_scoped("ModuleService") characters_model = module_service.get_module( "Characters").entries_model layout = QHBoxLayout(self) characters_list = QListView() characters_list.setModel(characters_model) characters_list.setSizePolicy( QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Expanding)) characters_list.selectionModel().currentRowChanged.connect( self._update_selection) self.list = characters_list scroll_area = QScrollArea() form_container = QWidget() form = QFormLayout() self.editors = [] for dialogue in self.service.dialogues: label = QLabel(dialogue.name) editor = QLineEdit() editor.editingFinished.connect( lambda e=editor, d=dialogue: self._on_editor_change(e, d)) self.editors.append(editor) form.addRow(label, editor) form_container.setLayout(form) scroll_area.setWidgetResizable(True) scroll_area.setWidget(form_container) layout.addWidget(characters_list) layout.addWidget(scroll_area) self.setLayout(layout) self.service.load() self.loaded = True
class PlotControlWidget(QWidget): # noinspection PyTypeChecker def __init__(self, parent=None): super().__init__(parent) # setup settings for the class self.settings = QSettings() self.settings.beginGroup("plot_control") self.base_vector_data = vpype.VectorData() self.vector_data: vpype.VectorData = None # settings self.page_format: str = self.settings.value("page_format", "A4") self.landscape: bool = self.settings.value("landscape", False) self.rotated: bool = self.settings.value("rotate", False) self.rotated: bool = self.settings.value("rotated", False) self.center: bool = self.settings.value("center", True) self.fit_page: bool = self.settings.value("fit_page", False) self.margin_value: float = self.settings.value("margin_value", 2.0) self.margin_unit: str = self.settings.value("margin_unit", "cm") # setup plot area self.plot = VectorDataPlotWidget() self.plot.setSizePolicy( QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)) # page layout controls page_box = QGroupBox("Page layout") page_layout = QFormLayout() page_format_combo = QComboBox() for k in PAGE_FORMATS: page_format_combo.addItem(k) page_format_combo.setCurrentText(self.page_format) page_format_combo.currentTextChanged.connect( lambda text: self.set_page_format(text)) landscape_check = QCheckBox("Landscape") landscape_check.setChecked(self.landscape) landscape_check.stateChanged.connect( lambda: self.set_landscape(landscape_check.isChecked())) rotated_check = QCheckBox("Rotated") rotated_check.setChecked(self.landscape) rotated_check.stateChanged.connect( lambda: self.set_rotated(rotated_check.isChecked())) center_check = QCheckBox("Center on page") center_check.setChecked(self.center) center_check.stateChanged.connect( lambda: self.set_center(center_check.isChecked())) fit_page_check = QCheckBox("Fit to page") fit_page_check.setChecked(self.fit_page) fit_page_check.stateChanged.connect( lambda: self.set_fit_page(fit_page_check.isChecked())) margin_layout = QHBoxLayout() margin_spin = QDoubleSpinBox() margin_spin.setValue(self.margin_value) margin_spin.valueChanged.connect(lambda: self.set_margin( margin_spin.value(), margin_unit.currentText())) margin_unit = UnitComboBox() margin_unit.setCurrentText(self.margin_unit) margin_unit.currentTextChanged.connect(lambda: self.set_margin( margin_spin.value(), margin_unit.currentText())) margin_layout.addWidget(margin_spin) margin_layout.addWidget(margin_unit) page_layout.addRow("Page format:", page_format_combo) page_layout.addRow("", landscape_check) page_layout.addRow("", rotated_check) page_layout.addRow("", center_check) page_layout.addRow("", fit_page_check) page_layout.addRow("Margin:", margin_layout) page_box.setLayout(page_layout) # Action buttons pen_up_btn = QPushButton("UP") pen_down_btn = QPushButton("DOWN") pen_up_btn.clicked.connect(lambda: axy.pen_up()) pen_down_btn.clicked.connect(lambda: axy.pen_down()) pen_up_spin = AxySettingsSpinBox(self.settings, "pen_pos_up", 60.0) pen_down_spin = AxySettingsSpinBox(self.settings, "pen_pos_down", 40.0) pen_up_layout = QHBoxLayout() pen_up_layout.addWidget(pen_up_spin) pen_up_layout.addWidget(pen_up_btn) pen_down_layout = QHBoxLayout() pen_down_layout.addWidget(pen_down_spin) pen_down_layout.addWidget(pen_down_btn) shutdown_btn = QPushButton("OFF") shutdown_btn.clicked.connect(lambda: axy.shutdown()) plot_btn = QPushButton("PLOT") plot_btn.clicked.connect(lambda: self.plot_svg()) action_box = QGroupBox("Actions") action_layout = QFormLayout() action_layout.addRow("Pen up: ", pen_up_layout) action_layout.addRow("Pen down: ", pen_down_layout) action_layout.addRow("Motor off:", shutdown_btn) action_layout.addRow("Plot:", plot_btn) action_box.setLayout(action_layout) self.list = QListView() self.list.setFixedHeight(120) self.list.setSizePolicy( QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred)) # controls layout controls_layout = QVBoxLayout() controls_layout.addWidget(self.list) controls_layout.addWidget(page_box) controls_layout.addWidget(action_box) controls_layout.addItem( QSpacerItem(20, 40, QSizePolicy.Minimum, QSizePolicy.Expanding)) # setup layout root_layout = QHBoxLayout() root_layout.addWidget(self.plot) root_layout.addLayout(controls_layout) self.setLayout(root_layout) self.update_view() # FIXME: stub vector data # vd = vpype.VectorData() # vd.add(vpype.LineCollection([(0, 100), (200, 1001 + 201j)]), 1) # vd.add(vpype.LineCollection([(0, 100 + 100j), (300j, 400j + 100)]), 2) self.load_svg( "/Users/hhip/Drive/axidraw/wheel_cards/wheel_card_triple_5_40.svg") # self.load_svg("/Users/hhip/Downloads/spirograph-grids/spirograph-grid.svg") def add_actions(self, toolbar: QToolBar): colorful_act = toolbar.addAction(QIcon("images/icons_colorful.png"), "Colorful") colorful_act.setCheckable(True) colorful_act.setChecked(self.plot.colorful) colorful_act.triggered.connect( lambda checked: setattr(self.plot, "colorful", checked)) show_points_act = toolbar.addAction( QIcon("images/icons_show_points.png"), "Points") show_points_act.setCheckable(True) show_points_act.setChecked(self.plot.show_points) show_points_act.triggered.connect( lambda checked: setattr(self.plot, "show_points", checked)) show_pen_up_act = toolbar.addAction( QIcon("images/icons_show_pen_up.png"), "Pen-Up") show_pen_up_act.setCheckable(True) show_pen_up_act.setChecked(self.plot.show_pen_up) show_pen_up_act.triggered.connect( lambda checked: setattr(self.plot, "show_pen_up", checked)) show_axes_act = toolbar.addAction(QIcon("images/icons_show_axes.png"), "Axes") show_axes_act.setCheckable(True) show_axes_act.setChecked(self.plot.show_axes) show_axes_act.triggered.connect( lambda checked: setattr(self.plot, "show_axes", checked)) scale = UnitComboBox() scale.setCurrentText(self.plot.unit) scale.currentTextChanged.connect( lambda text: setattr(self.plot, "unit", text)) toolbar.addWidget(scale) def load_svg(self, path: str): # TODO: make quantization a parameters vd = vpype.read_multilayer_svg(path, 0.05) self.set_vector_data(vd) def plot_svg(self): vd = vpype.VectorData() for lid in self.vector_data.layers: if self.plot.layer_visible(lid): vd.add(self.vector_data.layers[lid], 1) svg = io.StringIO() vpype.write_svg(svg, vd, page_format=self.plot.page_format) axy.plot_svg(svg.getvalue()) def set_vector_data(self, vector_data: vpype.VectorData): self.base_vector_data = vector_data self.update_view() model = QStandardItemModel() for lid in vector_data.layers: item = QStandardItem() item.setCheckable(True) item.setCheckState( Qt.Checked if self.plot.layer_visible(lid) else Qt.Unchecked) pixmap = QPixmap(16, 12) pixmap.fill(QColor(*[c * 255 for c in self.plot.layer_color(lid)])) item.setIcon(QIcon(pixmap)) item.setText(f"Layer {lid}") item.setSelectable(False) item.setEditable(False) item.setData(lid, Qt.UserRole + 1) model.appendRow(item) model.itemChanged.connect(lambda it: self.plot.set_layer_visible( it.data(Qt.UserRole + 1), it.checkState() == Qt.Checked)) self.list.setModel(model) def set_page_format(self, page_format: str): self.page_format = page_format self.settings.setValue("page_format", page_format) self.update_view() def set_landscape(self, landscape: bool): self.landscape = landscape self.settings.setValue("landscape", landscape) self.update_view() def set_rotated(self, rotated: bool): self.rotated = rotated self.settings.setValue("rotated", rotated) self.update_view() def set_center(self, center: bool): self.center = center self.settings.setValue("center", center) self.update_view() def set_fit_page(self, fit_page: bool): self.fit_page = fit_page self.settings.setValue("fit_page", fit_page) self.update_view() def set_margin(self, value: float, unit: str): self.margin_value = value self.margin_unit = unit self.settings.setValue("margin_value", value) self.settings.setValue("margin_unit", unit) if self.fit_page: self.update_view() def update_view(self): self.vector_data = copy.deepcopy(self.base_vector_data) # scale/center according to settings width, height = PAGE_FORMATS[str(self.page_format)] if self.landscape: width, height = height, width if self.rotated: self.vector_data.rotate(-math.pi / 2) self.vector_data.translate(0, height) bounds = self.vector_data.bounds() if bounds is not None: min_x, min_y, max_x, max_y = bounds margin = self.margin_value * vpype.convert(self.margin_unit) if self.fit_page: factor_x = (width - 2 * margin) / (max_x - min_x) factor_y = (height - 2 * margin) / (max_y - min_y) scale = min(factor_x, factor_y) self.vector_data.translate(-min_x, -min_y) self.vector_data.scale(scale) if factor_x < factor_y: self.vector_data.translate( margin, margin + (height - 2 * margin - (max_y - min_y) * scale) / 2) else: self.vector_data.translate( margin + (width - 2 * margin - (max_x - min_x) * scale) / 2, margin) elif self.center: self.vector_data.translate( (width - (max_x - min_x)) / 2 - min_x, (height - (max_y - min_y)) / 2 - min_y, ) # configure plot widget self.plot.vector_data = self.vector_data self.plot.page_format = (width, height)