31 from classes.logger
import log
32 from classes
import info
39 import simplejson
as json
49 raise NotImplementedError(
"updateStatus() not implemented in UpdateWatcher implementer.")
60 raise NotImplementedError(
"changed() not implemented in UpdateInterface implementer.")
67 def __init__(self, type=None, key=[], values=None, partial_update=False):
79 def json(self, is_array=False, only_value=False):
83 data_dict = copy.deepcopy(self.
values)
85 data_dict = {
"type": self.
type,
87 "value": copy.deepcopy(self.
values),
94 if data_dict.get(
"value")
and "history" in data_dict.get(
"value"):
95 data_dict.get(
"value").pop(
"history",
None)
96 if data_dict.get(
"old_values")
and "history" in data_dict.get(
"old_values"):
97 data_dict.get(
"old_values").pop(
"history",
None)
99 log.info(
'Warning: failed to clear history attribute from undo/redo data.')
103 update_action_dict = data_dict
106 update_action_dict = [data_dict]
109 return json.dumps(update_action_dict)
116 update_action_dict = json.loads(value, strict=
False)
119 self.
type = update_action_dict.get(
"type")
120 self.
key = update_action_dict.get(
"key")
121 self.
values = update_action_dict.get(
"value")
122 self.
old_values = update_action_dict.get(
"old_values")
129 self.values.pop(
"history",
None)
131 self.old_values.pop(
"history",
None)
133 log.info(
'Warning: failed to clear history attribute from undo/redo data.')
153 self.redoHistory.clear()
154 self.actionHistory.clear()
157 history = project.get([
"history"])
161 for actionDict
in history.get(
"redo", []):
163 action.load_json(json.dumps(actionDict))
164 if action.type !=
"load" and action.key[0] !=
"history":
165 self.redoHistory.append(action)
167 log.info(
"Loading redo history, skipped key: %s" % str(action.key))
168 for actionDict
in history.get(
"undo", []):
170 action.load_json(json.dumps(actionDict))
171 if action.type !=
"load" and action.key[0] !=
"history":
172 self.actionHistory.append(action)
174 log.info(
"Loading undo history, skipped key: %s" % str(action.key))
187 history_length_int = int(history_length)
188 for action
in self.
redoHistory[-history_length_int:]:
189 if action.type !=
"load" and action.key[0] !=
"history":
190 actionDict = json.loads(action.json(), strict=
False)
191 redo_list.append(actionDict)
193 log.info(
"Saving redo history, skipped key: %s" % str(action.key))
195 if action.type !=
"load" and action.key[0] !=
"history":
196 actionDict = json.loads(action.json(), strict=
False)
197 undo_list.append(actionDict)
199 log.info(
"Saving undo, skipped key: %s" % str(action.key))
203 self.
update([
"history"], {
"redo": redo_list,
"undo": undo_list})
209 self.actionHistory.clear()
210 self.redoHistory.clear()
219 self.updateListeners.append(listener)
222 self.updateListeners.insert(index, listener)
224 log.warning(
"Listener already added.")
231 self.statusWatchers.append(watcher)
233 log.warning(
"Watcher already added.")
242 watcher.updateStatusChanged(*new_status)
252 reverse =
UpdateAction(action.type, action.key, action.values, action.partial_update)
254 if action.type ==
"insert":
255 reverse.type =
"delete"
258 id = action.values[
"id"]
259 action.key.append({
"id": id})
262 elif action.type ==
"delete":
263 reverse.type =
"insert"
265 if reverse.type ==
"insert" and isinstance(reverse.key[-1], dict)
and "id" in reverse.key[-1]:
266 reverse.key = reverse.key[:-1]
270 reverse.old_values = action.values
271 reverse.values = action.old_values
281 last_action = copy.deepcopy(self.actionHistory.pop())
283 self.redoHistory.append(last_action)
294 next_action = copy.deepcopy(self.redoHistory.pop())
297 if next_action.type ==
"insert" and isinstance(next_action.key[-1], dict)
and "id" in next_action.key[-1]:
298 next_action.key = next_action.key[:-1]
300 self.actionHistory.append(next_action)
313 listener.changed(action)
315 except Exception
as ex:
316 log.error(
"Couldn't apply '{}' to update listener: {}\n{}".format(action.type, listener, ex))
325 self.redoHistory.clear()
326 self.actionHistory.clear()
335 self.redoHistory.clear()
342 def update(self, key, values, partial_update=False):
345 if self.last_action.key
and self.last_action.key[0] !=
"history":
347 self.redoHistory.clear()
357 self.redoHistory.clear()
366 self.last_action.set_old_values(previous_value)
def insert
Insert a new UpdateAction into the UpdateManager (this action will then be distributed to all listene...
def apply_last_action_to_history
Apply the last action to the history.
This class is used to track and distribute changes to listeners.
def add_watcher
Add a new watcher (which will invoke the updateStatusChanged() method each time a 'redo' or 'undo' ac...
def save_history
Save history to project.
def json
Get the JSON string representing this UpdateAction.
def update
Update the UpdateManager with an UpdateAction (this action will then be distributed to all listeners)...
def load_json
Load this UpdateAction from a JSON string.
def add_listener
Add a new listener (which will invoke the changed(action) method each time an UpdateAction is availab...
def dispatch_action
Distribute changes to all listeners (by calling their changed() method)
A data structure representing a single update manager action, including any necessary data to reverse...
def load_history
Load history from project.
def delete
Delete an item from the UpdateManager with an UpdateAction (this action will then be distributed to a...
def reset
Reset the UpdateManager, and clear all UpdateActions and History.
def redo
Redo the last UpdateAction (and notify all listeners and watchers)
def load
Load all project data via an UpdateAction into the UpdateManager (this action will then be distribute...
Interface for classes that listen for 'undo' and 'redo' events.
def get_reverse_action
Convert an UpdateAction into the opposite type (i.e.
def updateStatusChanged
Easily be notified each time there are 'undo' or 'redo' actions available in the UpdateManager.
def update_watchers
Notify all watchers if any 'undo' or 'redo' actions are available.
def undo
Undo the last UpdateAction (and notify all listeners and watchers)
def changed
This method is invoked each time the UpdateManager is changed.
Interface for classes that listen for changes (insert, update, and delete).