def parse_expression(self, expr: str): """Parse expression.""" try: args_list = parse_params(expr) except LarkError: QMessageBox.warning( self, "Loading failed", f"Your expression is in an incorrect format." ) else: for args in args_list: links = args[0].split(',') link_names = { vlink.name for vlink in self.entities_link.data() } for link_name in links: # If link name not exist. if link_name not in link_names: self.add_link(link_name, 'Blue') row_count = self.entities_point.rowCount() self.command_stack.beginMacro(f"Add {{Point{row_count}}}") self.command_stack.push(AddTable(self.entities_point)) self.command_stack.push(EditPointTable( row_count, self.entities_point, self.entities_link, args )) self.command_stack.endMacro()
def __edit_point(self, row: Union[int, bool] = False): """Edit point function.""" dlg = EditPointDialog(self.entities_point.data_tuple(), self.entities_link.data_tuple(), row, self) dlg.show() if not dlg.exec(): dlg.deleteLater() return row_count = self.entities_point.rowCount() type_str = dlg.type_box.currentText().split()[0] if type_str != 'R': type_str += f":{dlg.angle_box.value() % 360}" args = (','.join( dlg.selected.item(link).text() for link in range(dlg.selected.count())), type_str, dlg.color_box.currentText(), dlg.x_box.value(), dlg.y_box.value()) if row is False: self.command_stack.beginMacro(f"Add {{Point{row_count}}}") self.command_stack.push(AddTable(self.entities_point)) row = row_count else: row = dlg.name_box.currentIndex() self.command_stack.beginMacro(f"Edit {{Point{row}}}") dlg.deleteLater() self.command_stack.push( EditPointTable(row, self.entities_point, self.entities_link, args)) self.command_stack.endMacro()
def clone_point(self): """Clone a point (with orange color).""" row = self.entities_point.currentRow() args = self.entities_point.row_text(row) args[2] = 'Orange' row_count = self.entities_point.rowCount() self.command_stack.beginMacro( f"Clone {{Point{row}}} as {{Point{row_count}}}") self.command_stack.push(AddTable(self.entities_point)) self.command_stack.push( EditPointTable(row_count, self.entities_point, self.entities_link, args)) self.command_stack.endMacro()
def deletePoint(self, row: int): """Push delete point command to stack.""" args = self.EntitiesPoint.rowTexts(row) args[0] = '' self.CommandStack.beginMacro(f"Delete {{Point{row}}}") self.CommandStack.push( EditPointTable(row, self.EntitiesPoint, self.EntitiesLink, args)) for i in range(self.EntitiesLink.rowCount()): self.CommandStack.push(FixSequenceNumber(self.EntitiesLink, i, row)) self.CommandStack.push( DeleteTable(row, self.EntitiesPoint, is_rename=True)) self.InputsWidget.variableExcluding(row) self.CommandStack.endMacro()
def set_free_move(self, args: Sequence[Tuple[int, Tuple[float, float, float]]]): """Free move function.""" points_text = ", ".join(f"Point{c[0]}" for c in args) self.command_stack.beginMacro(f"Moved {{{points_text}}}") for row, (x, y, angle) in args: args = self.entities_point.row_text(row) args[3] = x args[4] = y if args[1] != 'R': args[1] = f"{args[1].split(':')[0]}:{angle:.02f}" self.command_stack.push( EditPointTable(row, self.entities_point, self.entities_link, args)) self.command_stack.endMacro()
def __set_scale(self): """Scale the mechanism.""" dlg = _ScaleDialog(self) if not dlg.exec_(): return factor = dlg.factor() self.CommandStack.beginMacro(f"Scale mechanism: {factor}") for row in range(self.EntitiesPoint.rowCount()): args = self.EntitiesPoint.rowTexts(row) args[3] = float(args[3]) * factor args[4] = float(args[4]) * factor self.CommandStack.push( EditPointTable(row, self.EntitiesPoint, self.EntitiesLink, args)) self.CommandStack.endMacro()
def lock_points(self): """Turn a group of points to fixed on ground or not.""" to_fixed = self.action_point_context_lock.isChecked() for row in self.entities_point.selected_rows(): new_links = self.entities_point.item(row, 1).text().split(',') if to_fixed: if 'ground' not in new_links: new_links.append('ground') else: if 'ground' in new_links: new_links.remove('ground') args = self.entities_point.row_text(row) args[0] = ','.join(s for s in new_links if s) self.command_stack.beginMacro(f"Edit {{Point{row}}}") self.command_stack.push( EditPointTable(row, self.entities_point, self.entities_link, args)) self.command_stack.endMacro()
def add_point(self, x: float, y: float, links: str = "", color: str = 'Green', type_num: int = VJoint.R, angle: float = 0.) -> int: """Add an ordinary point. Return the row count of new point.""" row_count = self.entities_point.rowCount() self.command_stack.beginMacro(f"Add {{Point{row_count}}}") self.command_stack.push(AddTable(self.entities_point)) self.command_stack.push( EditPointTable( row_count, self.entities_point, self.entities_link, (links, ('R', f'P:{angle}', f'RP:{angle}')[type_num], color, x, y))) self.command_stack.endMacro() return row_count
def __set_scale(self): """Scale the mechanism.""" dlg = _ScaleDialog(self) if not dlg.exec(): dlg.deleteLater() return factor = dlg.factor() dlg.deleteLater() self.command_stack.beginMacro(f"Scale mechanism: {factor}") for row in range(self.entities_point.rowCount()): args = self.entities_point.row_text(row) args[3] = float(args[3]) * factor args[4] = float(args[4]) * factor self.command_stack.push( EditPointTable(row, self.entities_point, self.entities_link, args)) self.command_stack.endMacro()
def __to_multiple_joint(self, index: int, points: Tuple[int]): """Merge points into a multiple joint. @index: The index of main joint in the sequence. """ row = points[index] points_text = ", ".join(f'Point{p}' for p in points) self.CommandStack.beginMacro( f"Merge {{{points_text}}} as multiple joint {{Point{row}}}") vpoints = self.EntitiesPoint.dataTuple() links = list(vpoints[row].links) args = self.EntitiesPoint.rowTexts(row) for point in sorted(points, reverse=True): for link in vpoints[point].links: if link not in links: links.append(link) self.deletePoint(point) args[0] = ','.join(links) self.CommandStack.push(AddTable(self.EntitiesPoint)) self.CommandStack.push( EditPointTable(self.EntitiesPoint.rowCount() - 1, self.EntitiesPoint, self.EntitiesLink, args)) self.CommandStack.endMacro()
def delete_point(self, row: Optional[int] = None): """Push delete point command to stack.""" if row is None: row = self.entities_point.currentRow() if row < 0: return args = self.entities_point.row_text(row) args[0] = '' self.command_stack.beginMacro(f"Delete {{Point{row}}}") for i in reversed([ i for i, (b, d, a) in enumerate(self.inputs_widget.input_pairs()) if row in {b, d} ]): self.inputs_widget.remove_var(i) self.command_stack.push( EditPointTable(row, self.entities_point, self.entities_link, args)) for i in range(self.entities_link.rowCount()): self.command_stack.push( FixSequenceNumber(self.entities_link, i, row)) self.command_stack.push( DeleteTable(row, self.entities_point, is_rename=True)) self.inputs_widget.variable_excluding(row) self.command_stack.endMacro()