File: actions_handler.py

package info (click to toggle)
linux-show-player 0.5.3-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 4,896 kB
  • sloc: python: 12,408; sh: 154; makefile: 17; xml: 8
file content (131 lines) | stat: -rw-r--r-- 3,953 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
# -*- coding: utf-8 -*-
#
# This file is part of Linux Show Player
#
# Copyright 2012-2016 Francesco Ceruti <ceppofrancy@gmail.com>
#
# Linux Show Player is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Linux Show Player is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Linux Show Player.  If not, see <http://www.gnu.org/licenses/>.

import logging
from collections import deque

from lisp.core import configuration as cfg
from lisp.core.action import Action
from lisp.core.signal import Signal


class ActionsHandler:
    """Provide a classic undo/redo mechanism based on stacks."""

    MaxStackSize = int(cfg.config['Actions']['MaxStackSize'])

    def __init__(self):
        super().__init__()

        self.action_done = Signal()
        self.action_undone = Signal()
        self.action_redone = Signal()

        self._undo = deque()
        self._redo = deque()
        if self.MaxStackSize > 0:
            self._undo.maxlen = self.MaxStackSize
            self._redo.maxlen = self.MaxStackSize

        self._saved_action = None

    def clear(self):
        """Clear the `undo` and `redo` stacks."""
        self._undo.clear()
        self._redo.clear()
        self._saved_action = None

    def do_action(self, action: Action):
        """Execute the action, and add it the `undo` stack.

        When an action is executed:
         * is logged
         * is appended to the `undo` stack
         * the `redo` stack is cleared to maintain consistency
         * the `action_done` signal is emitted
        """
        action.do()

        self._logging(action, 'Last action: ')
        self._undo.append(action)
        # Clean the redo stack for maintain consistency
        self._redo.clear()

        self.action_done.emit(action)

    def undo_action(self):
        """Undo the last executed action, and add it to the `redo` stack.

        When an action is undone:
         * is removed from the `undo` stack
         * is logged
         * is appended to the `redo` stack
         * the signal `action_undone` is emitted
        """
        if self._undo:
            action = self._undo.pop()
            action.undo()

            self._logging(action, 'Undo: ')
            self._redo.append(action)

            self.action_undone.emit(action)

    def redo_action(self):
        """Redo the last undone action, and add it back to the `undo` stack.

        When an action is redone:
         * is remove from the `redo` stack
         * is logged
         * is added to the `undo` stack
         * the `action_redone` signal is emitted
        """
        if self._redo:
            action = self._redo.pop()
            action.redo()

            self._logging(action, 'Redo: ')
            self._undo.append(action)

            self.action_redone.emit(action)

    def set_saved(self):
        """Set the action at the _top_ of the `undo` stack as `save-point`."""
        if self._undo:
            self._saved_action = self._undo[-1]

    def is_saved(self) -> bool:
        """Return True if the action at the _top_ of the `undo` stack is the
        `save-point`.
        """
        if self._undo:
            return self._undo[-1] is self._saved_action
        else:
            return True

    @staticmethod
    def _logging(action: Action, pre: str):
        message = action.log()
        if message.strip() == '':
            message = type(action).__name__

        logging.info(pre + message)


MainActionsHandler = ActionsHandler()  # "global" action-handler