def __init__(self): self._gui = MainWindow(self) self._command_engine = CommandEngine(self) self._printer = CanvasPrinter(self._gui.canvas) self._shapes = ShapesStore(self) # import CliParser this late to avoid import loop from app.parsers.cli_parser import CliParser self._cli_parser = CliParser(self, RgbColorParser())
def test_move_shapes(shapes_store: ShapesStore, shapes: Dict[str, Shape]): shapes_store.add_shapes(*shapes.values()) res = shapes_store.move_shapes(Point(10, 10), Point(-100, 100)) assert res['moved'] == [ Polyline(Point(-100, 100), Point(-90, 110), Point(-80, 100), color=Color(48, 210, 111)) ] assert res['before_move'] == [*shapes.values()] assert len(shapes_store._controller.result) == 3 shapes_store.add_shapes( Rectangle(Point(-10, 3490), 20, 20, Color(255, 255, 255))) # Getting the previously moved polyline back shapes_store.move_shapes(Point(-100, 100), Point(10, 10)) res = shapes_store.move_shapes(Point(0, 3500), Point(-1000, -1000)) assert res['moved'] == [ Rectangle(Point(-1000, -4500), 1, 50000, Color(255, 255, 255)), Rectangle(Point(-1010, -1010), 20, 20, Color(255, 255, 255)) ] assert res['before_move'] == [ shapes['dot'], shapes['line'], shapes['rectangle'], shapes['circle'], Rectangle(Point(-10, 3490), 20, 20, Color(255, 255, 255)), shapes['polyline'] ] assert len(shapes_store._controller.result) == 8
def test_remove_shapes_at(shapes_store: ShapesStore): r1 = Rectangle(Point(0, 0), 100, 100, QColor(0, 0, 0)) r2 = Rectangle(Point(1, 1), 100, 100, QColor(0, 0, 0)) c = Circle(Point(0, 0), 50, QColor(0, 0, 0)) l1 = Line(Point(-10, 0), Point(10, 0), QColor(0, 0, 0)) l2 = Line(Point(-10, 1), Point(10, 1), QColor(0, 0, 0)) d = Dot(Point(0, 0), QColor(0, 0, 0)) shapes_store.add_shapes(r1, r2, c, l1, l2, d) res = shapes_store.remove_shapes_at(Point(0, 0)) assert res['before_remove'] == [r1, r2, c, l1, l2, d] assert res['removed'] == [r1, c, l1, d] assert shapes_store._shapes == [r2, l2] assert len(shapes_store._controller.result) == 2
def test_add_shapes(shapes_store: ShapesStore, shapes: Dict[str, Shape]): shapes_store.add_shapes(shapes['dot']) assert shapes_store._shapes.index(shapes['dot']) == 0 assert len(shapes_store._controller.result) == 1 assert len(shapes_store._shapes) == 1 assert shapes_store._shapes[0] is not shapes['dot'] shapes_store.add_shapes(shapes['line'], shapes['rectangle'], shapes['circle']) assert shapes_store._shapes.index(shapes['line']) == 1 assert shapes_store._shapes.index(shapes['rectangle']) == 2 assert shapes_store._shapes.index(shapes['circle']) == 3 assert len(shapes_store._controller.result) == 2 assert len(shapes_store._shapes) == 4 assert shapes_store._shapes[1] is not shapes['line'] assert shapes_store._shapes[2] is not shapes['rectangle'] assert shapes_store._shapes[3] is not shapes['circle']
def test_print_all(shapes_store: ShapesStore, shapes: Dict[str, Shape]): shapes_store.add_shapes(*shapes.values()) shapes_store.set_preview(shapes['rectangle']) printer = PrinterMockup() shapes_store.print_all(printer) assert printer.dot == 'printed' assert printer.line == 'printed' assert printer.polyline == 'printed' assert printer.rect == 'printedprinted' assert printer.circle == 'printed' shapes_store.print_all(printer, Point(10, 10)) assert printer.polyline == 'printedprinted'
def test_restart(shapes_store: ShapesStore, shapes: Dict[str, Shape]): shapes_store.add_shapes(*shapes.values()) shapes_store._preview = shapes['line'] shapes_store.restart() assert shapes_store.is_empty() is True assert shapes_store._preview is None assert len(shapes_store._controller.result) == 2
def test_remove_last_shape(shapes_store: ShapesStore, shapes: Dict[str, Shape]): # Removing last shape if there are no shapes at all shouldn't do anything shapes_store.remove_last_shape() shapes_store.add_shapes(*shapes.values()) shapes_store.remove_last_shape() last_item = shapes['circle'] assert len(shapes_store._controller.result) == 2 assert len(shapes_store._shapes) == len(shapes) - 1 assert last_item not in shapes_store._shapes
def replace_shapes_store(self, shapes: List[Shape]): self._shapes = ShapesStore(self, shapes) self.update()
class Controller: """ Main class of this application. Holds all crucial pieces together. It represents an observer in the observer design pattern. """ def __init__(self): self._gui = MainWindow(self) self._command_engine = CommandEngine(self) self._printer = CanvasPrinter(self._gui.canvas) self._shapes = ShapesStore(self) # import CliParser this late to avoid import loop from app.parsers.cli_parser import CliParser self._cli_parser = CliParser(self, RgbColorParser()) def add_shapes(self, *shapes: Shape): for shape in shapes: self.print_to_history(str(shape)) self._shapes.add_shapes(*shapes) def move_shapes(self, move_from: Point, move_to: Point, divergence: bool = False) -> Dict[str, List[Shape]]: return self._shapes.move_shapes(move_from, move_to, divergence) def replace_shapes_store(self, shapes: List[Shape]): self._shapes = ShapesStore(self, shapes) self.update() def remove_last_shape(self): self._shapes.remove_last_shape() def remove_shapes_at(self, point: Point, divergence: bool = False) -> Dict[str, List[Shape]]: return self._shapes.remove_shapes_at(point, divergence) def preview_shape(self, shape: Shape): self._shapes.set_preview(shape) def end_preview(self): self._shapes.set_preview(None) def parse_command(self, command_text: str): command = self._cli_parser.parse_input(command_text) self.execute_command(command, command_text=command_text) def execute_command(self, command: Command, from_redo: bool = False, command_text: str = None): history_line = ' > ' + (command_text or str(command)) self._gui.print_lines_to_history(history_line) self._command_engine.execute_command(command, from_redo=from_redo) def remove_last_command(self): self._command_engine.remove_last_command() def print_to_history(self, lines: str): self._gui.print_lines_to_history(lines) def delete_from_history(self, number_of_lines: int = 1): self._gui.delete_from_history(number_of_lines) def shapes_at(self, point: Point = None, divergence: bool = False) -> List[Shape]: return self._shapes.shapes_at(point, divergence) def print_shapes_to_history(self, point: Point): for shape in self.shapes_at(point): self.print_to_history(str(shape)) def print_all_shapes(self, printer: Printer = None) -> List[Shape]: return self._shapes.print_all(printer or self._printer) def update(self): self._printer.update(self) def undo(self): self._command_engine.undo() def redo(self): self._command_engine.redo() def enable_undo(self): self._gui.enable_undo() def enable_redo(self): self._gui.enable_redo() def disable_undo(self): self._gui.disable_undo() def disable_redo(self): self._gui.disable_redo() def save_dialog(self, path_to_file: str): self._gui.save_dialog(path_to_file) def load_dialog(self, path_to_file: str): self._gui.load_dialog(path_to_file) def save(self, file: str): commands = self._command_engine.get_all_commands() with open(file, 'w+', encoding='utf-8') as f: [f.write(str(c) + '\n') for c in commands['undos']] self._gui.set_status('File saved!') def load(self, file: str): with open(file, 'r', encoding='utf-8') as f: # Getting rid of the newline `\n` at the end of every line commands = [line[:-1] for line in f.readlines()] for command_text in commands: command = self._cli_parser.parse_input(command_text) self.execute_command(command, command_text=command_text) self._gui.set_status('File loaded!') def run_app(self): # Run the whole app self._gui.show() def clear_dialog(self) -> bool: return self._gui.clear_dialog() def restart(self): self._shapes.restart() def quit(self): self._gui.close()
def test_set_preview(shapes_store: ShapesStore, shapes: Dict[str, Shape]): assert shapes_store._preview is None shapes_store.set_preview(shapes['line']) assert shapes_store._preview == shapes['line'] assert len(shapes_store._controller.result) == 1
def test_shapes_at(shapes_store: ShapesStore, shapes: Dict[str, Shape]): assert shapes_store.shapes_at() == [] shapes_store.add_shapes(*shapes.values()) assert shapes_store.shapes_at(Point(0, 0)) == [shapes['rectangle']] assert shapes_store.shapes_at() == [*shapes.values()]
def test_is_empty(shapes_store: ShapesStore, shapes: Dict[str, Shape]): assert shapes_store.is_empty() is True shapes_store.add_shapes(shapes['circle']) assert shapes_store.is_empty() is False
def shapes_store() -> ShapesStore: controller = ControllerMockup() shapes_store = ShapesStore(controller) return shapes_store