示例#1
0
    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())
示例#2
0
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
示例#3
0
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
示例#4
0
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']
示例#5
0
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'
示例#6
0
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
示例#7
0
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
示例#8
0
 def replace_shapes_store(self, shapes: List[Shape]):
     self._shapes = ShapesStore(self, shapes)
     self.update()
示例#9
0
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()
示例#10
0
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
示例#11
0
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()]
示例#12
0
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
示例#13
0
def shapes_store() -> ShapesStore:
    controller = ControllerMockup()
    shapes_store = ShapesStore(controller)
    return shapes_store