Commit 221dd11c authored by Colomban Wendling's avatar Colomban Wendling

Implement undo/redo support

parent f4f0bacc
......@@ -110,6 +110,102 @@ class CellRendererColor(Gtk.CellRenderer):
cr.stroke()
class UndoStack(object):
def __init__(self):
self._items = []
self._current = -1
def push(self, data):
while len(self._items) - 1 > self._current:
self._items.pop()
self._current += 1
self._items.append(data)
assert(len(self._items) - 1 == self._current)
def can_undo(self):
return self._current > 0
def undo(self):
if self.can_undo():
self._current -= 1
return self._items[self._current]
else:
return None
def can_redo(self):
return self._current + 1 < len(self._items)
def redo(self):
if self.can_redo():
self._current += 1
return self._items[self._current]
else:
return None
def get(self):
if self._current >= 0 and self._current < len(self._items):
return self._items[self._current]
else:
return None
# FIXME: only save the changed rows, not the whole store
class UndoableStore(Gtk.ListStore):
_stack = UndoStack()
_freeze = False
def __init__(self, *args, **kwargs):
self._stack = UndoStack()
self._freeze = False
super().__init__(*args, **kwargs)
self._save()
def do_row_changed(self, path, iter):
self._save()
def do_row_deleted(self, path):
self._save()
def do_row_inserted(self, path, iter):
self._save()
def _save(self):
# don't save state when restoring it
if self._freeze:
return
data = [[col for col in row] for row in self]
self._stack.push(data)
def _update(self):
data = self._stack.get()
self._freeze = True
self.clear()
for row in data:
self.append(row)
self._freeze = False
def can_undo(self):
return self._stack.can_undo()
def can_redo(self):
return self._stack.can_redo()
def undo(self):
if self.can_undo():
self._stack.undo()
self._update()
def redo(self):
if self.can_redo():
self._stack.redo()
self._update()
def clear_undo_stack(self):
self._stack = UndoStack()
self._save()
class AppWindow(Gtk.ApplicationWindow):
ROW_KEY = 0
ROW_COLOR = 1
......@@ -135,12 +231,17 @@ class AppWindow(Gtk.ApplicationWindow):
add.connect('activate', self.on_add_activate)
remove = builder.get_object('remove')
remove.connect('activate', self.on_remove_activate)
self.store = builder.get_object('liststore1')
undo = builder.get_object('undo')
undo.connect('activate', self.on_undo_activate)
redo = builder.get_object('redo')
redo.connect('activate', self.on_redo_activate)
self.view = builder.get_object('treeview1')
self.view.connect('row-activated', self.on_row_activated)
self.store = UndoableStore(str, str)
self.view.set_model(self.store)
column = builder.get_object('treeviewcolumn2')
renderer = CellRendererColor()
column.pack_start(renderer, True)
......@@ -155,11 +256,17 @@ class AppWindow(Gtk.ApplicationWindow):
self.load()
self.store.clear_undo_stack()
undo.set_sensitive(self.store.can_undo())
redo.set_sensitive(self.store.can_redo())
def on_model_changed(model, path, iter=None, data=None):
undo.set_sensitive(self.store.can_undo())
redo.set_sensitive(self.store.can_redo())
self.update_theme()
self.store.connect('row-changed', on_model_changed)
self.store.connect('row-deleted', on_model_changed)
self.store.connect('row-inserted', on_model_changed)
self.store.connect_after('row-changed', on_model_changed)
self.store.connect_after('row-deleted', on_model_changed)
self.store.connect_after('row-inserted', on_model_changed)
def on_row_activated(self, view, path, column, data=None):
iter = self.store.get_iter(path)
......@@ -192,6 +299,12 @@ class AppWindow(Gtk.ApplicationWindow):
if iter is not None:
model.remove(iter)
def on_undo_activate(self, action, data=None):
self.store.undo()
def on_redo_activate(self, action, data=None):
self.store.redo()
def load(self):
scheme = self.settings.get_string('gtk-color-scheme').strip()
n = 0
......
......@@ -58,14 +58,6 @@
</toolbar>
</ui>
</object>
<object class="GtkListStore" id="liststore1">
<columns>
<!-- column-name key -->
<column type="gchararray"/>
<!-- column-name color -->
<column type="gchararray"/>
</columns>
</object>
<object class="GtkVBox" id="box">
<property name="can_focus">False</property>
<property name="border_width">12</property>
......@@ -91,7 +83,6 @@
<object class="GtkTreeView" id="treeview1">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="model">liststore1</property>
<child internal-child="selection">
<object class="GtkTreeSelection" id="treeview-selection1"/>
</child>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment